mirror of
https://github.com/mangosfour/server.git
synced 2025-12-13 13:37:05 +00:00
[8658] Threat calculation fixes and improvements.
* Add single arg version Unit::AddThreat for just adding to threat list. * Req. provide schollmask and crit flag for any real threat value for proper threats mod apply. * Send crit flag in DealDamage as MELEE_HIT_CRIT for spell damage for later send to threat call. * For not affected by modifiers threat values use SPELL_SCHOOL_MASK_NONE. * Implement aura SPELL_AURA_MOD_CRITICAL_THREAT (used only in itemset 529 effect).
This commit is contained in:
parent
ba62cdbe8f
commit
b258a17ba4
15 changed files with 50 additions and 32 deletions
|
|
@ -60,7 +60,7 @@ AggressorAI::MoveInLineOfSight(Unit *u)
|
|||
}
|
||||
else if(sMapStore.LookupEntry(m_creature->GetMapId())->IsDungeon())
|
||||
{
|
||||
m_creature->AddThreat(u, 0.0f);
|
||||
m_creature->AddThreat(u);
|
||||
u->SetInCombatWith(m_creature);
|
||||
}
|
||||
}
|
||||
|
|
@ -155,7 +155,7 @@ AggressorAI::AttackStart(Unit *u)
|
|||
// DEBUG_LOG("Creature %s tagged a victim to kill [guid=%u]", m_creature->GetName(), u->GetGUIDLow());
|
||||
i_victimGuid = u->GetGUID();
|
||||
|
||||
m_creature->AddThreat(u, 0.0f);
|
||||
m_creature->AddThreat(u);
|
||||
m_creature->SetInCombatWith(u);
|
||||
u->SetInCombatWith(m_creature);
|
||||
|
||||
|
|
|
|||
|
|
@ -2057,7 +2057,7 @@ void Creature::SetInCombatWithZone()
|
|||
if (pPlayer->isAlive())
|
||||
{
|
||||
pPlayer->SetInCombatWith(this);
|
||||
AddThreat(pPlayer, 0.0f);
|
||||
AddThreat(pPlayer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -948,7 +948,7 @@ void CreatureEventAI::AttackStart(Unit *who)
|
|||
|
||||
if (m_creature->Attack(who, MeleeEnabled))
|
||||
{
|
||||
m_creature->AddThreat(who, 0.0f);
|
||||
m_creature->AddThreat(who);
|
||||
m_creature->SetInCombatWith(who);
|
||||
who->SetInCombatWith(m_creature);
|
||||
|
||||
|
|
@ -1010,7 +1010,7 @@ void CreatureEventAI::MoveInLineOfSight(Unit *who)
|
|||
}
|
||||
else if (m_creature->GetMap()->IsDungeon())
|
||||
{
|
||||
m_creature->AddThreat(who, 0.0f);
|
||||
m_creature->AddThreat(who);
|
||||
who->SetInCombatWith(m_creature);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -138,7 +138,7 @@ void GuardAI::AttackStart(Unit *u)
|
|||
if(m_creature->Attack(u,true))
|
||||
{
|
||||
i_victimGuid = u->GetGUID();
|
||||
m_creature->AddThreat(u, 0.0f);
|
||||
m_creature->AddThreat(u);
|
||||
m_creature->SetInCombatWith(u);
|
||||
u->SetInCombatWith(m_creature);
|
||||
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ void HostileRefManager::threatAssist(Unit *pVictim, float pThreat, SpellEntry co
|
|||
ref = getFirst();
|
||||
while(ref != NULL)
|
||||
{
|
||||
float threat = ThreatCalcHelper::calcThreat(pVictim, iOwner, pThreat, (pThreatSpell ? GetSpellSchoolMask(pThreatSpell) : SPELL_SCHOOL_MASK_NORMAL), pThreatSpell);
|
||||
float threat = ThreatCalcHelper::calcThreat(pVictim, iOwner, pThreat, false, (pThreatSpell ? GetSpellSchoolMask(pThreatSpell) : SPELL_SCHOOL_MASK_NORMAL), pThreatSpell);
|
||||
if(pVictim == getOwner())
|
||||
ref->addThreat(float (threat) / size); // It is faster to modify the threat durectly if possible
|
||||
else
|
||||
|
|
|
|||
|
|
@ -172,7 +172,7 @@ void PetAI::UpdateAI(const uint32 diff)
|
|||
return;
|
||||
|
||||
//if pet misses its target, it will also be the first in threat list
|
||||
m_creature->getVictim()->AddThreat(m_creature,0.0f);
|
||||
m_creature->getVictim()->AddThreat(m_creature);
|
||||
|
||||
if( _needToStop() )
|
||||
_stopAttack();
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ ReactorAI::AttackStart(Unit *p)
|
|||
{
|
||||
DEBUG_LOG("Tag unit GUID: %u (TypeId: %u) as a victim", p->GetGUIDLow(), p->GetTypeId());
|
||||
i_victimGuid = p->GetGUID();
|
||||
m_creature->AddThreat(p, 0.0f);
|
||||
m_creature->AddThreat(p);
|
||||
|
||||
m_creature->SetInCombatWith(p);
|
||||
p->SetInCombatWith(m_creature);
|
||||
|
|
|
|||
|
|
@ -1092,7 +1092,7 @@ void Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask)
|
|||
if (!unit->isInCombat() && unit->GetTypeId() != TYPEID_PLAYER && ((Creature*)unit)->AI())
|
||||
((Creature*)unit)->AI()->AttackedBy(realCaster);
|
||||
|
||||
unit->AddThreat(realCaster, 0.0f);
|
||||
unit->AddThreat(realCaster);
|
||||
unit->SetInCombatWith(realCaster);
|
||||
realCaster->SetInCombatWith(unit);
|
||||
|
||||
|
|
@ -1116,7 +1116,7 @@ void Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask)
|
|||
if (unit->isInCombat() && !(m_spellInfo->AttributesEx & SPELL_ATTR_EX_NO_INITIAL_AGGRO))
|
||||
{
|
||||
realCaster->SetInCombatState(unit->GetCombatTimer() > 0);
|
||||
unit->getHostileRefManager().threatAssist(realCaster, 0.0f);
|
||||
unit->getHostileRefManager().threatAssist(realCaster, 0.0f, m_spellInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3770,7 +3770,7 @@ void Spell::HandleThreatSpells(uint32 spellId)
|
|||
if(!threat)
|
||||
return;
|
||||
|
||||
m_targets.getUnitTarget()->AddThreat(m_caster, float(threat));
|
||||
m_targets.getUnitTarget()->AddThreat(m_caster, float(threat), false, GetSpellSchoolMask(m_spellInfo), m_spellInfo);
|
||||
|
||||
DEBUG_LOG("Spell %u, rank %u, added an additional %i threat", spellId, spellmgr.GetSpellRank(spellId), threat);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -233,7 +233,7 @@ pAuraHandler AuraHandler[TOTAL_AURAS]=
|
|||
&Aura::HandleNoImmediateEffect, //180 SPELL_AURA_MOD_FLAT_SPELL_DAMAGE_VERSUS implemented in Unit::SpellDamageBonus
|
||||
&Aura::HandleUnused, //181 unused (3.0.8a) old SPELL_AURA_MOD_FLAT_SPELL_CRIT_DAMAGE_VERSUS
|
||||
&Aura::HandleAuraModResistenceOfStatPercent, //182 SPELL_AURA_MOD_RESISTANCE_OF_STAT_PERCENT
|
||||
&Aura::HandleNULL, //183 SPELL_AURA_MOD_CRITICAL_THREAT only used in 28746
|
||||
&Aura::HandleNoImmediateEffect, //183 SPELL_AURA_MOD_CRITICAL_THREAT only used in 28746, implemented in ThreatCalcHelper::calcThreat
|
||||
&Aura::HandleNoImmediateEffect, //184 SPELL_AURA_MOD_ATTACKER_MELEE_HIT_CHANCE implemented in Unit::RollMeleeOutcomeAgainst
|
||||
&Aura::HandleNoImmediateEffect, //185 SPELL_AURA_MOD_ATTACKER_RANGED_HIT_CHANCE implemented in Unit::RollMeleeOutcomeAgainst
|
||||
&Aura::HandleNoImmediateEffect, //186 SPELL_AURA_MOD_ATTACKER_SPELL_HIT_CHANCE implemented in Unit::MagicSpellHitResult
|
||||
|
|
@ -2195,7 +2195,7 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
|
|||
case 1515: // Tame beast
|
||||
// FIX_ME: this is 2.0.12 threat effect replaced in 2.1.x by dummy aura, must be checked for correctness
|
||||
if( caster && m_target->CanHaveThreatList())
|
||||
m_target->AddThreat(caster, 10.0f);
|
||||
m_target->AddThreat(caster, 10.0f, false, GetSpellSchoolMask(GetSpellProto()), GetSpellProto());
|
||||
return;
|
||||
case 13139: // net-o-matic
|
||||
// root to self part of (root_target->charge->root_self sequence
|
||||
|
|
@ -4039,7 +4039,7 @@ void Aura::HandleAuraModTotalThreat(bool apply, bool Real)
|
|||
|
||||
float threatMod = apply ? float(m_modifier.m_amount) : float(-m_modifier.m_amount);
|
||||
|
||||
m_target->getHostileRefManager().threatAssist(caster, threatMod);
|
||||
m_target->getHostileRefManager().threatAssist(caster, threatMod, GetSpellProto());
|
||||
}
|
||||
|
||||
void Aura::HandleModTaunt(bool apply, bool Real)
|
||||
|
|
@ -6311,6 +6311,10 @@ void Aura::PeriodicTick()
|
|||
// This method can modify pdamage
|
||||
bool isCrit = IsCritFromAbilityAura(pCaster, pdamage);
|
||||
|
||||
// send critical in hit info for threat calculation
|
||||
if (isCrit)
|
||||
cleanDamage.hitOutCome = MELEE_HIT_CRIT;
|
||||
|
||||
pCaster->CalcAbsorbResist(m_target, GetSpellSchoolMask(GetSpellProto()), DOT, pdamage, &absorb, &resist);
|
||||
|
||||
sLog.outDetail("PeriodicTick: %u (TypeId: %u) attacked %u (TypeId: %u) for %u dmg inflicted by %u abs is %u",
|
||||
|
|
@ -6556,7 +6560,7 @@ void Aura::PeriodicTick()
|
|||
if(gain_amount)
|
||||
{
|
||||
int32 gain = pCaster->ModifyPower(power, gain_amount);
|
||||
m_target->AddThreat(pCaster, float(gain) * 0.5f, GetSpellSchoolMask(GetSpellProto()), GetSpellProto());
|
||||
m_target->AddThreat(pCaster, float(gain) * 0.5f, pInfo.critical, GetSpellSchoolMask(GetSpellProto()), GetSpellProto());
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4681,7 +4681,7 @@ void Spell::EffectThreat(uint32 /*i*/)
|
|||
if(!unitTarget->CanHaveThreatList())
|
||||
return;
|
||||
|
||||
unitTarget->AddThreat(m_caster, float(damage));
|
||||
unitTarget->AddThreat(m_caster, float(damage), false, GetSpellSchoolMask(m_spellInfo), m_spellInfo);
|
||||
}
|
||||
|
||||
void Spell::EffectHealMaxHealth(uint32 /*i*/)
|
||||
|
|
|
|||
|
|
@ -30,12 +30,21 @@
|
|||
//==============================================================
|
||||
|
||||
// The pHatingUnit is not used yet
|
||||
float ThreatCalcHelper::calcThreat(Unit* pHatedUnit, Unit* pHatingUnit, float pThreat, SpellSchoolMask schoolMask, SpellEntry const *pThreatSpell)
|
||||
float ThreatCalcHelper::calcThreat(Unit* pHatedUnit, Unit* pHatingUnit, float pThreat, bool crit, SpellSchoolMask schoolMask, SpellEntry const *pThreatSpell)
|
||||
{
|
||||
// all flat mods applied early
|
||||
if(!pThreat)
|
||||
return 0.0f;
|
||||
|
||||
if (pThreatSpell)
|
||||
{
|
||||
if (Player* modOwner = pHatedUnit->GetSpellModOwner())
|
||||
modOwner->ApplySpellMod(pThreatSpell->Id, SPELLMOD_THREAT, pThreat);
|
||||
|
||||
if(crit)
|
||||
pThreat *= pHatedUnit->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_CRITICAL_THREAT,schoolMask);
|
||||
}
|
||||
|
||||
float threat = pHatedUnit->ApplyTotalThreatModifier(pThreat, schoolMask);
|
||||
return threat;
|
||||
}
|
||||
|
|
@ -357,7 +366,7 @@ void ThreatManager::clearReferences()
|
|||
|
||||
//============================================================
|
||||
|
||||
void ThreatManager::addThreat(Unit* pVictim, float pThreat, SpellSchoolMask schoolMask, SpellEntry const *pThreatSpell)
|
||||
void ThreatManager::addThreat(Unit* pVictim, float pThreat, bool crit, SpellSchoolMask schoolMask, SpellEntry const *pThreatSpell)
|
||||
{
|
||||
//function deals with adding threat and adding players and pets into ThreatList
|
||||
//mobs, NPCs, guards have ThreatList and HateOfflineList
|
||||
|
|
@ -378,7 +387,7 @@ void ThreatManager::addThreat(Unit* pVictim, float pThreat, SpellSchoolMask scho
|
|||
|
||||
assert(getOwner()->GetTypeId()== TYPEID_UNIT);
|
||||
|
||||
float threat = ThreatCalcHelper::calcThreat(pVictim, iOwner, pThreat, schoolMask, pThreatSpell);
|
||||
float threat = ThreatCalcHelper::calcThreat(pVictim, iOwner, pThreat, crit, schoolMask, pThreatSpell);
|
||||
|
||||
HostileReference* ref = iThreatContainer.addThreat(pVictim, threat);
|
||||
// Ref is not in the online refs, search the offline refs next
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ struct SpellEntry;
|
|||
class ThreatCalcHelper
|
||||
{
|
||||
public:
|
||||
static float calcThreat(Unit* pHatedUnit, Unit* pHatingUnit, float threat, SpellSchoolMask schoolMask = SPELL_SCHOOL_MASK_NORMAL, SpellEntry const *threatSpell = NULL);
|
||||
static float calcThreat(Unit* pHatedUnit, Unit* pHatingUnit, float threat, bool crit, SpellSchoolMask schoolMask, SpellEntry const *threatSpell);
|
||||
};
|
||||
|
||||
//==============================================================
|
||||
|
|
@ -176,7 +176,8 @@ class MANGOS_DLL_SPEC ThreatManager
|
|||
|
||||
void clearReferences();
|
||||
|
||||
void addThreat(Unit* pVictim, float threat, SpellSchoolMask schoolMask = SPELL_SCHOOL_MASK_NORMAL, SpellEntry const *threatSpell = NULL);
|
||||
void addThreat(Unit* pVictim, float threat, bool crit, SpellSchoolMask schoolMask, SpellEntry const *threatSpell);
|
||||
void addThreat(Unit* pVictim, float threat) { addThreat(pVictim,threat,false,SPELL_SCHOOL_MASK_NONE,NULL); }
|
||||
void modifyThreatPercent(Unit *pVictim, int32 pPercent);
|
||||
|
||||
float getThreat(Unit *pVictim, bool pAlsoSearchOfflineList = false);
|
||||
|
|
|
|||
|
|
@ -761,9 +761,9 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa
|
|||
if (pVictim->GetTypeId() != TYPEID_PLAYER)
|
||||
{
|
||||
if(spellProto && IsDamageToThreatSpell(spellProto))
|
||||
pVictim->AddThreat(this, damage*2, damageSchoolMask, spellProto);
|
||||
pVictim->AddThreat(this, damage*2, (cleanDamage && cleanDamage->hitOutCome == MELEE_HIT_CRIT), damageSchoolMask, spellProto);
|
||||
else
|
||||
pVictim->AddThreat(this, damage, damageSchoolMask, spellProto);
|
||||
pVictim->AddThreat(this, damage, (cleanDamage && cleanDamage->hitOutCome == MELEE_HIT_CRIT), damageSchoolMask, spellProto);
|
||||
}
|
||||
else // victim is a player
|
||||
{
|
||||
|
|
@ -1125,7 +1125,7 @@ void Unit::CalculateSpellDamage(SpellNonMeleeDamage *damageInfo, int32 damage, S
|
|||
|
||||
void Unit::DealSpellDamage(SpellNonMeleeDamage *damageInfo, bool durabilityLoss)
|
||||
{
|
||||
if (damageInfo==0)
|
||||
if (!damageInfo)
|
||||
return;
|
||||
|
||||
Unit *pVictim = damageInfo->target;
|
||||
|
|
@ -1152,8 +1152,8 @@ void Unit::DealSpellDamage(SpellNonMeleeDamage *damageInfo, bool durabilityLoss)
|
|||
return;
|
||||
}
|
||||
|
||||
// Call default DealDamage
|
||||
CleanDamage cleanDamage(damageInfo->cleanDamage, BASE_ATTACK, MELEE_HIT_NORMAL);
|
||||
// Call default DealDamage (send critical in hit info for threat calculation)
|
||||
CleanDamage cleanDamage(damageInfo->cleanDamage, BASE_ATTACK, damageInfo->HitInfo & SPELL_HIT_TYPE_CRIT ? MELEE_HIT_CRIT : MELEE_HIT_NORMAL);
|
||||
DealDamage(pVictim, damageInfo->damage, &cleanDamage, SPELL_DIRECT_DAMAGE, SpellSchoolMask(damageInfo->schoolMask), spellProto, durabilityLoss);
|
||||
}
|
||||
|
||||
|
|
@ -10196,7 +10196,10 @@ bool Unit::CanHaveThreatList() const
|
|||
|
||||
float Unit::ApplyTotalThreatModifier(float threat, SpellSchoolMask schoolMask)
|
||||
{
|
||||
if(!HasAuraType(SPELL_AURA_MOD_THREAT))
|
||||
if (!HasAuraType(SPELL_AURA_MOD_THREAT))
|
||||
return threat;
|
||||
|
||||
if (schoolMask == SPELL_SCHOOL_MASK_NONE)
|
||||
return threat;
|
||||
|
||||
SpellSchools school = GetFirstSchoolInMask(schoolMask);
|
||||
|
|
@ -10206,11 +10209,11 @@ float Unit::ApplyTotalThreatModifier(float threat, SpellSchoolMask schoolMask)
|
|||
|
||||
//======================================================================
|
||||
|
||||
void Unit::AddThreat(Unit* pVictim, float threat, SpellSchoolMask schoolMask, SpellEntry const *threatSpell)
|
||||
void Unit::AddThreat(Unit* pVictim, float threat, bool crit, SpellSchoolMask schoolMask, SpellEntry const *threatSpell /*= NULL*/)
|
||||
{
|
||||
// Only mobs can manage threat lists
|
||||
if(CanHaveThreatList())
|
||||
m_ThreatManager.addThreat(pVictim, threat, schoolMask, threatSpell);
|
||||
m_ThreatManager.addThreat(pVictim, threat, crit, schoolMask, threatSpell);
|
||||
}
|
||||
|
||||
//======================================================================
|
||||
|
|
|
|||
|
|
@ -1336,7 +1336,8 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
|
|||
|
||||
// Threat related methods
|
||||
bool CanHaveThreatList() const;
|
||||
void AddThreat(Unit* pVictim, float threat, SpellSchoolMask schoolMask = SPELL_SCHOOL_MASK_NORMAL, SpellEntry const *threatSpell = NULL);
|
||||
void AddThreat(Unit* pVictim, float threat, bool crit, SpellSchoolMask schoolMask, SpellEntry const *threatSpell = NULL);
|
||||
void AddThreat(Unit* pVictim) { AddThreat(pVictim, 0.0f, false, SPELL_SCHOOL_MASK_NORMAL, NULL); }
|
||||
float ApplyTotalThreatModifier(float threat, SpellSchoolMask schoolMask = SPELL_SCHOOL_MASK_NORMAL);
|
||||
void DeleteThreatList();
|
||||
bool SelectHostileTarget();
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#ifndef __REVISION_NR_H__
|
||||
#define __REVISION_NR_H__
|
||||
#define REVISION_NR "8657"
|
||||
#define REVISION_NR "8658"
|
||||
#endif // __REVISION_NR_H__
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue