refactor(Core/Combat): Port TrinityCore heap-based threat system (#24715)

Co-authored-by: blinkysc <blinkysc@users.noreply.github.com>
Co-authored-by: Treeston <treeston.mmoc@gmail.com>
Co-authored-by: killerwife <killerwife@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
blinkysc
2026-03-18 13:36:59 -05:00
committed by GitHub
parent c80a0f1fad
commit 984baa92dd
101 changed files with 7045 additions and 2659 deletions
@@ -281,7 +281,7 @@ enum AuraType
SPELL_AURA_HASTE_RANGED = 218,
SPELL_AURA_MOD_MANA_REGEN_FROM_STAT = 219,
SPELL_AURA_MOD_RATING_FROM_STAT = 220,
SPELL_AURA_IGNORED = 221,
SPELL_AURA_MOD_DETAUNT = 221,
SPELL_AURA_222 = 222,
SPELL_AURA_RAID_PROC_FROM_CHARGE = 223,
SPELL_AURA_224 = 224,
@@ -283,7 +283,7 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS] =
&AuraEffect::HandleAuraModRangedHaste, //218 SPELL_AURA_HASTE_RANGED
&AuraEffect::HandleModManaRegen, //219 SPELL_AURA_MOD_MANA_REGEN_FROM_STAT
&AuraEffect::HandleModRatingFromStat, //220 SPELL_AURA_MOD_RATING_FROM_STAT
&AuraEffect::HandleNoImmediateEffect, //221 SPELL_AURA_IGNORED
&AuraEffect::HandleModDetaunt, //221 SPELL_AURA_MOD_DETAUNT
&AuraEffect::HandleUnused, //222 unused (3.2.0) only for spell 44586 that not used in real spell cast
&AuraEffect::HandleNoImmediateEffect, //223 SPELL_AURA_RAID_PROC_FROM_CHARGE
&AuraEffect::HandleUnused, //224 unused (3.0.8a)
@@ -2984,19 +2984,17 @@ void AuraEffect::HandleFeignDeath(AuraApplication const* aurApp, uint8 mode, boo
}
}
if (target->GetInstanceScript() && target->GetInstanceScript()->IsEncounterInProgress())
for (auto& pair : target->GetThreatMgr().GetThreatenedByMeList())
pair.second->ScaleThreat(0.0f);
if (target->GetMap()->IsDungeon()) // feign death does not remove combat in dungeons
{
// Xinef: replaced with CombatStop(false)
target->AttackStop();
target->RemoveAllAttackers();
target->getHostileRefMgr().addThreatPercent(-100);
target->ToPlayer()->SendAttackSwingCancelAttack(); // melee and ranged forced attack cancel
if (Player* targetPlayer = target->ToPlayer())
targetPlayer->SendAttackSwingCancelAttack();
}
else
{
target->CombatStop();
target->getHostileRefMgr().deleteReferences();
}
target->CombatStop(false, false);
target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_IMMUNE_OR_LOST_SELECTION);
@@ -3551,26 +3549,16 @@ void AuraEffect::HandleForceMoveForward(AuraApplication const* aurApp, uint8 mod
/*** THREAT ***/
/****************************/
void AuraEffect::HandleModThreat(AuraApplication const* aurApp, uint8 mode, bool apply) const
void AuraEffect::HandleModThreat(AuraApplication const* aurApp, uint8 mode, bool /*apply*/) const
{
if (!(mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK))
return;
Unit* target = aurApp->GetTarget();
for (uint8 i = 0; i < MAX_SPELL_SCHOOL; ++i)
if (GetMiscValue() & (1 << i))
{
if (apply)
AddPct(target->m_threatModifier[i], GetAmount());
else
{
float amount = target->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_THREAT, 1 << i);
target->m_threatModifier[i] = amount;
}
}
target->GetThreatMgr().UpdateMySpellSchoolModifiers();
}
void AuraEffect::HandleAuraModTotalThreat(AuraApplication const* aurApp, uint8 mode, bool apply) const
void AuraEffect::HandleAuraModTotalThreat(AuraApplication const* aurApp, uint8 mode, bool /*apply*/) const
{
if (!(mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK))
return;
@@ -3582,10 +3570,10 @@ void AuraEffect::HandleAuraModTotalThreat(AuraApplication const* aurApp, uint8 m
Unit* caster = GetCaster();
if (caster && caster->IsAlive())
target->getHostileRefMgr().addTempThreat((float)GetAmount(), apply);
caster->GetThreatMgr().UpdateMyTempModifiers();
}
void AuraEffect::HandleModTaunt(AuraApplication const* aurApp, uint8 mode, bool apply) const
void AuraEffect::HandleModTaunt(AuraApplication const* aurApp, uint8 mode, bool /*apply*/) const
{
if (!(mode & AURA_EFFECT_HANDLE_REAL))
return;
@@ -3595,17 +3583,21 @@ void AuraEffect::HandleModTaunt(AuraApplication const* aurApp, uint8 mode, bool
if (!target->IsAlive() || !target->CanHaveThreatList())
return;
Unit* caster = GetCaster();
if (!caster || !caster->IsAlive())
target->GetThreatMgr().TauntUpdate();
}
void AuraEffect::HandleModDetaunt(AuraApplication const* aurApp, uint8 mode, bool /*apply*/) const
{
if (!(mode & AURA_EFFECT_HANDLE_REAL))
return;
if (apply)
target->TauntApply(caster);
else
{
// When taunt aura fades out, mob will switch to previous target if current has less than 1.1 * secondthreat
target->TauntFadeOut(caster);
}
Unit* caster = GetCaster();
Unit* target = aurApp->GetTarget();
if (!caster || !caster->IsAlive() || !target->IsAlive() || !caster->CanHaveThreatList())
return;
caster->GetThreatMgr().TauntUpdate();
}
/*****************************/
@@ -3620,6 +3612,8 @@ void AuraEffect::HandleModConfuse(AuraApplication const* aurApp, uint8 mode, boo
Unit* target = aurApp->GetTarget();
target->SetControlled(apply, UNIT_STATE_CONFUSED);
if (apply)
target->GetThreatMgr().EvaluateSuppressed();
}
void AuraEffect::HandleModFear(AuraApplication const* aurApp, uint8 mode, bool apply) const
@@ -3640,6 +3634,8 @@ void AuraEffect::HandleAuraModStun(AuraApplication const* aurApp, uint8 mode, bo
Unit* target = aurApp->GetTarget();
target->SetControlled(apply, UNIT_STATE_STUNNED);
if (apply)
target->GetThreatMgr().EvaluateSuppressed();
}
void AuraEffect::HandleAuraModRoot(AuraApplication const* aurApp, uint8 mode, bool apply) const
@@ -4359,6 +4355,9 @@ void AuraEffect::HandleAuraModSchoolImmunity(AuraApplication const* aurApp, uint
target->ApplySpellImmune(GetId(), IMMUNITY_SCHOOL, GetMiscValue(), (apply));
if (apply)
target->GetThreatMgr().EvaluateSuppressed();
if (GetSpellInfo()->Mechanic == MECHANIC_BANISH)
{
if (apply)
@@ -4417,6 +4416,9 @@ void AuraEffect::HandleAuraModDmgImmunity(AuraApplication const* aurApp, uint8 m
Unit* target = aurApp->GetTarget();
target->ApplySpellImmune(GetId(), IMMUNITY_DAMAGE, GetMiscValue(), apply);
if (apply)
target->GetThreatMgr().EvaluateSuppressed();
}
void AuraEffect::HandleAuraModDispelImmunity(AuraApplication const* aurApp, uint8 mode, bool apply) const
@@ -6895,7 +6897,7 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) c
float threat = float(caster->HealBySpell(healInfo)) * 0.5f;
if (caster->IsClass(CLASS_PALADIN))
threat *= 0.5f;
caster->getHostileRefMgr().threatAssist(caster, threat, GetSpellInfo());
caster->GetThreatMgr().ForwardThreatForAssistingMe(caster, threat, GetSpellInfo());
}
void AuraEffect::HandlePeriodicHealthFunnelAuraTick(Unit* target, Unit* caster) const
@@ -7030,8 +7032,7 @@ void AuraEffect::HandlePeriodicHealAurasTick(Unit* target, Unit* caster) const
float threat = float(gain) * 0.5f;
if (caster->IsClass(CLASS_PALADIN))
threat *= 0.5f;
target->getHostileRefMgr().threatAssist(caster, threat, GetSpellInfo());
target->GetThreatMgr().ForwardThreatForAssistingMe(caster, threat, GetSpellInfo());
}
bool haveCastItem = GetBase()->GetCastItemGUID();
@@ -7117,8 +7118,6 @@ void AuraEffect::HandlePeriodicManaLeechAuraTick(Unit* target, Unit* caster) con
target->AddThreat(caster, float(gainedAmount) * 0.5f, GetSpellInfo()->GetSchoolMask(), GetSpellInfo());
}
target->AddThreat(caster, float(gainedAmount) * 0.5f, GetSpellInfo()->GetSchoolMask(), GetSpellInfo());
// remove CC auras
target->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TAKE_DAMAGE);
@@ -7169,7 +7168,7 @@ void AuraEffect::HandleObsModPowerAuraTick(Unit* target, Unit* caster) const
int32 gain = target->ModifyPower(PowerType, amount);
if (caster)
target->getHostileRefMgr().threatAssist(caster, float(gain) * 0.5f, GetSpellInfo());
target->GetThreatMgr().ForwardThreatForAssistingMe(caster, float(gain) * 0.5f, GetSpellInfo(), true);
}
void AuraEffect::HandlePeriodicEnergizeAuraTick(Unit* target, Unit* caster) const
@@ -7203,7 +7202,7 @@ void AuraEffect::HandlePeriodicEnergizeAuraTick(Unit* target, Unit* caster) cons
int32 gain = target->ModifyPower(PowerType, amount);
if (caster)
target->getHostileRefMgr().threatAssist(caster, float(gain) * 0.5f, GetSpellInfo());
target->GetThreatMgr().ForwardThreatForAssistingMe(caster, float(gain) * 0.5f, GetSpellInfo(), true);
}
void AuraEffect::HandlePeriodicPowerBurnAuraTick(Unit* target, Unit* caster) const
@@ -206,6 +206,7 @@ public:
void HandleModThreat(AuraApplication const* aurApp, uint8 mode, bool apply) const;
void HandleAuraModTotalThreat(AuraApplication const* aurApp, uint8 mode, bool apply) const;
void HandleModTaunt(AuraApplication const* aurApp, uint8 mode, bool apply) const;
void HandleModDetaunt(AuraApplication const* aurApp, uint8 mode, bool apply) const;
// control
void HandleModConfuse(AuraApplication const* aurApp, uint8 mode, bool apply) const;
void HandleModFear(AuraApplication const* aurApp, uint8 mode, bool apply) const;
@@ -237,6 +237,12 @@ public:
AuraScript* GetScriptByName(std::string const& scriptName) const;
template <class Script>
Script* GetScript(std::string const& scriptName) const
{
return dynamic_cast<Script*>(GetScriptByName(scriptName));
}
std::list<AuraScript*> m_loadedScripts;
virtual std::string GetDebugInfo() const;
+23 -37
View File
@@ -2751,8 +2751,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target)
float threat = float(gain) * 0.5f;
if (caster->IsClass(CLASS_PALADIN))
threat *= 0.5f;
unitTarget->getHostileRefMgr().threatAssist(caster, threat, m_spellInfo);
unitTarget->GetThreatMgr().ForwardThreatForAssistingMe(caster, threat, m_spellInfo);
m_healing = gain;
// Xinef: if heal actually healed something, add no overheal flag
@@ -2877,8 +2876,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target)
if (missInfo == SPELL_MISS_RESIST && m_spellInfo->HasAttribute(SPELL_ATTR0_CU_PICKPOCKET) && unitTarget->IsCreature() && m_caster)
{
m_caster->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TALK);
if (unitTarget->ToCreature()->IsAIEnabled)
unitTarget->ToCreature()->AI()->AttackStart(m_caster);
unitTarget->ToCreature()->EngageWithTarget(m_caster);
}
}
@@ -2887,19 +2885,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target)
if (missInfo != SPELL_MISS_EVADE && !m_caster->IsFriendlyTo(effectUnit) && (!m_spellInfo->IsPositive() || m_spellInfo->HasEffect(SPELL_EFFECT_DISPEL)))
{
if (!m_triggeredByAuraSpell.spellInfo || m_damage || (!(m_triggeredByAuraSpell.spellInfo->Effects[m_triggeredByAuraSpell.effectIndex].TriggerSpell == m_spellInfo->Id) && !(m_triggeredByAuraSpell.spellInfo->IsAuraEffectEqual(m_spellInfo))))
m_caster->CombatStart(effectUnit, !(m_spellInfo->AttributesEx3 & SPELL_ATTR3_SUPPRESS_TARGET_PROCS));
// Patch 3.0.8: All player spells which cause a creature to become aggressive to you will now also immediately cause the creature to be tapped.
if (effectUnit->IsInCombatWith(m_caster))
{
if (Creature* creature = effectUnit->ToCreature())
{
if (!creature->hasLootRecipient() && m_caster->IsPlayer())
{
creature->SetLootRecipient(m_caster);
}
}
}
m_caster->AtTargetAttacked(effectUnit, !(m_spellInfo->HasAttribute(SPELL_ATTR1_NO_THREAT) || m_spellInfo->HasAttribute(SPELL_ATTR3_SUPPRESS_TARGET_PROCS)));
// Unsure if there are more spells that are not supposed to stop enemy from
// regenerating HP from food, so for now it stays as an ID.
@@ -3036,10 +3022,11 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleA
}
// xinef: triggered spells should not prolong combat
if (unit->IsInCombat() && !m_spellInfo->HasAttribute(SPELL_ATTR3_SUPPRESS_TARGET_PROCS) && !m_triggeredByAuraSpell)
if (m_originalCaster && unit->IsInCombat() && !m_spellInfo->HasAttribute(SPELL_ATTR3_SUPPRESS_TARGET_PROCS) && !m_triggeredByAuraSpell)
{
m_caster->SetInCombatState(unit->GetCombatTimer() > 0, unit);
unit->getHostileRefMgr().threatAssist(m_caster, 0.0f);
if (m_originalCaster->HasUnitFlag(UNIT_FLAG_PLAYER_CONTROLLED))
m_originalCaster->GetCombatManager().InheritCombatStatesFrom(unit);
unit->GetThreatMgr().ForwardThreatForAssistingMe(m_originalCaster, 0.0f, nullptr, true);
}
}
}
@@ -4048,12 +4035,6 @@ void Spell::_cast(bool skipCheck)
if (target->IsCreature())
m_caster->CastSpell(target, 32747, true);
// xinef: start combat at cast for delayed spells, only for explicit target
if (Unit* target = m_targets.GetUnitTarget())
if (m_caster->IsPlayer() || (m_caster->IsPet() && m_caster->IsControlledByPlayer()))
if (GetDelayMoment() > 0 && !m_caster->IsFriendlyTo(target) && !m_spellInfo->HasAura(SPELL_AURA_BIND_SIGHT) && (!m_spellInfo->IsPositive() || m_spellInfo->HasEffect(SPELL_EFFECT_DISPEL)))
m_caster->CombatStartOnCast(target, !m_spellInfo->HasAttribute(SPELL_ATTR3_SUPPRESS_TARGET_PROCS), GetDelayMoment() + 500); // xinef: increase this time so we dont leave and enter combat in a moment
if (m_caster->IsPlayer())
if (m_caster->ToPlayer()->GetCommandStatus(CHEAT_COOLDOWN))
m_caster->ToPlayer()->RemoveSpellCooldown(m_spellInfo->Id, true);
@@ -5558,11 +5539,13 @@ void Spell::HandleThreatSpells()
if (m_spellInfo->HasAttribute(SPELL_ATTR1_NO_THREAT) || m_spellInfo->HasAttribute(SPELL_ATTR3_SUPPRESS_TARGET_PROCS))
return;
Unit* unitCaster = m_originalCaster ? m_originalCaster : m_caster;
float threat = 0.0f;
if (SpellThreatEntry const* threatEntry = sSpellMgr->GetSpellThreatEntry(m_spellInfo->Id))
{
if (threatEntry->apPctMod != 0.0f)
threat += threatEntry->apPctMod * m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
threat += threatEntry->apPctMod * unitCaster->GetTotalAttackPowerValue(BASE_ATTACK);
threat += threatEntry->flatMod;
}
@@ -5576,23 +5559,27 @@ void Spell::HandleThreatSpells()
// since 2.0.1 threat from positive effects also is distributed among all targets, so the overall caused threat is at most the defined bonus
threat /= m_UniqueTargetInfo.size();
for (std::list<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
for (auto& ihit : m_UniqueTargetInfo)
{
float threatToAdd = threat;
if (ihit->missCondition != SPELL_MISS_NONE)
if (ihit.missCondition != SPELL_MISS_NONE)
threatToAdd = 0.0f;
Unit* target = ObjectAccessor::GetUnit(*m_caster, ihit->targetGUID);
Unit* target = ObjectAccessor::GetUnit(*unitCaster, ihit.targetGUID);
if (!target)
continue;
bool IsFriendly = m_caster->IsFriendlyTo(target);
// positive spells distribute threat among all units that are in combat with target, like healing
if (m_spellInfo->_IsPositiveSpell() && IsFriendly)
target->getHostileRefMgr().threatAssist(m_caster, threatToAdd, m_spellInfo);
if (m_spellInfo->_IsPositiveSpell())
target->GetThreatMgr().ForwardThreatForAssistingMe(unitCaster, threatToAdd, m_spellInfo);
// for negative spells threat gets distributed among affected targets
else if (!m_spellInfo->_IsPositiveSpell() && !IsFriendly && target->CanHaveThreatList())
target->AddThreat(m_caster, threatToAdd, m_spellInfo->GetSchoolMask(), m_spellInfo);
// ignoreModifiers=true because flat SpellThreatEntry threat should not have modifiers applied twice
else
{
if (!target->CanHaveThreatList())
continue;
target->GetThreatMgr().AddThreat(unitCaster, threatToAdd, m_spellInfo, true);
}
}
LOG_DEBUG("spells.aura", "Spell {}, added an additional {} threat for {} {} target(s)", m_spellInfo->Id, threat, m_spellInfo->_IsPositiveSpell() ? "assisting" : "harming", uint32(m_UniqueTargetInfo.size()));
}
@@ -5772,8 +5759,7 @@ SpellCastResult Spell::CheckCast(bool strict)
if (Unit* victim = member->GetVictim())
if (victim->IsInCombat() && m_caster->GetDistance(victim) < m_caster->GetVisibilityRange())
{
m_caster->CombatStart(victim);
victim->AddThreat(m_caster, 1.0f);
m_caster->EngageWithTarget(victim);
break;
}
return SPELL_FAILED_TARGET_CANNOT_BE_RESURRECTED;
+22 -35
View File
@@ -2652,7 +2652,7 @@ void Spell::EffectDispel(SpellEffIndex effIndex)
// put in combat
if (unitTarget->IsFriendlyTo(m_caster))
unitTarget->getHostileRefMgr().threatAssist(m_caster, 0.0f, m_spellInfo);
unitTarget->GetThreatMgr().ForwardThreatForAssistingMe(m_caster, 0.0f, m_spellInfo);
if (success_list.empty())
return;
@@ -3299,33 +3299,25 @@ void Spell::EffectTaunt(SpellEffIndex /*effIndex*/)
if (!unitTarget)
return;
// xinef: Hand of Reckoning, cast before checing canhavethreatlist. fixes damage against pets
// xinef: Hand of Reckoning, cast before checking canhavethreatlist. fixes damage against pets
if (m_spellInfo->Id == 62124 && unitTarget->GetVictim() != m_caster)
{
m_caster->CastSpell(unitTarget, 67485, true);
unitTarget->CombatStart(m_caster);
}
// this effect use before aura Taunt apply for prevent taunt already attacking target
// for spell as marked "non effective at already attacking target"
if (!unitTarget->CanHaveThreatList() || (unitTarget->GetVictim() == m_caster && !m_spellInfo->HasAura(SPELL_AURA_MOD_TAUNT)))
if (!unitTarget->CanHaveThreatList())
{
SendCastResult(SPELL_FAILED_DONT_REPORT);
return;
}
if (!unitTarget->GetThreatMgr().GetOnlineContainer().empty())
ThreatManager& mgr = unitTarget->GetThreatMgr();
if (mgr.GetCurrentVictim() == m_caster)
{
// Also use this effect to set the taunter's threat to the taunted creature's highest value
float myThreat = unitTarget->GetThreatMgr().GetThreat(m_caster);
float topThreat = unitTarget->GetThreatMgr().GetOnlineContainer().getMostHated()->GetThreat();
if (topThreat > myThreat)
unitTarget->GetThreatMgr().DoAddThreat(m_caster, topThreat - myThreat);
//Set aggro victim to caster
if (HostileReference* forcedVictim = unitTarget->GetThreatMgr().GetOnlineContainer().getReferenceByTarget(m_caster))
unitTarget->GetThreatMgr().setCurrentVictim(forcedVictim);
SendCastResult(SPELL_FAILED_DONT_REPORT);
return;
}
if (!mgr.IsThreatListEmpty())
mgr.MatchUnitThreatToHighestThreat(m_caster);
}
void Spell::EffectWeaponDmg(SpellEffIndex effIndex)
@@ -3677,7 +3669,8 @@ void Spell::EffectThreat(SpellEffIndex /*effIndex*/)
if (!unitTarget->CanHaveThreatList() || m_caster->IsFriendlyTo(unitTarget))
return;
unitTarget->AddThreat(m_caster, float(damage));
// SPELL_EFFECT_THREAT adds flat threat that should not be modified by threat reduction
unitTarget->GetThreatMgr().AddThreat(m_caster, float(damage), m_spellInfo, true);
}
void Spell::EffectHealMaxHealth(SpellEffIndex /*effIndex*/)
@@ -4002,24 +3995,18 @@ void Spell::EffectSanctuary(SpellEffIndex /*effIndex*/)
if (!unitTarget)
return;
if (unitTarget->GetInstanceScript() && unitTarget->GetInstanceScript()->IsEncounterInProgress())
unitTarget->GetThreatMgr().EvaluateSuppressed();
if (unitTarget->IsPlayer() && !unitTarget->GetMap()->IsDungeon())
{
unitTarget->getHostileRefMgr().UpdateVisibility(true);
// Xinef: replaced with CombatStop(false)
unitTarget->AttackStop();
unitTarget->RemoveAllAttackers();
// Night Elf: Shadowmeld only resets threat temporarily
if (m_spellInfo->Id != 59646)
unitTarget->getHostileRefMgr().addThreatPercent(-100);
if (unitTarget->IsPlayer())
unitTarget->ToPlayer()->SendAttackSwingCancelAttack(); // melee and ranged forced attack cancel
// stop all pve combat for players outside dungeons, suppress pvp combat
unitTarget->CombatStop(false, false);
}
else
{
unitTarget->getHostileRefMgr().UpdateVisibility(m_spellInfo->Id == 59646); // Night Elf: Shadowmeld
unitTarget->CombatStop(true);
// in dungeons (or for nonplayers), reset this unit on all enemies' threat lists
for (auto const& pair : unitTarget->GetThreatMgr().GetThreatenedByMeList())
pair.second->ScaleThreat(0.0f);
}
UnitList targets;
@@ -5185,7 +5172,7 @@ void Spell::EffectDispelMechanic(SpellEffIndex effIndex)
// put in combat
if (unitTarget->IsFriendlyTo(m_caster))
unitTarget->getHostileRefMgr().threatAssist(m_caster, 0.0f, m_spellInfo);
unitTarget->GetThreatMgr().ForwardThreatForAssistingMe(m_caster, 0.0f, m_spellInfo);
}
void Spell::EffectResurrectPet(SpellEffIndex /*effIndex*/)
@@ -5903,7 +5890,7 @@ void Spell::EffectRedirectThreat(SpellEffIndex /*effIndex*/)
return;
if (unitTarget)
m_caster->SetRedirectThreat(unitTarget->GetGUID(), uint32(damage));
m_caster->GetThreatMgr().RegisterRedirectThreat(m_spellInfo->Id, unitTarget->GetGUID(), uint32(damage));
}
void Spell::EffectGameObjectDamage(SpellEffIndex /*effIndex*/)
+5
View File
@@ -1286,6 +1286,11 @@ bool SpellInfo::IsAutoRepeatRangedSpell() const
return AttributesEx2 & SPELL_ATTR2_AUTO_REPEAT;
}
bool SpellInfo::HasInitialAggro() const
{
return !(HasAttribute(SPELL_ATTR1_NO_THREAT) || HasAttribute(SPELL_ATTR3_SUPPRESS_TARGET_PROCS));
}
bool SpellInfo::IsAffected(uint32 familyName, flag96 const& familyFlags) const
{
if (!familyName)
+1
View File
@@ -466,6 +466,7 @@ public:
bool IsBreakingStealth() const;
bool IsRangedWeaponSpell() const;
bool IsAutoRepeatRangedSpell() const;
bool HasInitialAggro() const;
[[nodiscard]] bool IsAffected(uint32 familyName, flag96 const& familyFlags) const;