diff options
author | Matan Shukry <matanshukry@gmail.com> | 2021-03-27 04:16:52 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-03-27 02:16:52 +0100 |
commit | cfb32584b0bd91a091e9861a51533ee157792d8e (patch) | |
tree | f082b030aac57c5a62bac04bb021e50a03bad1ab /src | |
parent | 3f479399695ce4aed7f508be46cfdccfd4353eee (diff) |
Core/Auras: Prevent recursive infinite loops with spell mod auras affecting each other (#26165)
Diffstat (limited to 'src')
-rw-r--r-- | src/server/game/Spells/Auras/SpellAuraEffects.cpp | 22 | ||||
-rw-r--r-- | src/server/game/Spells/Auras/SpellAuraEffects.h | 12 |
2 files changed, 19 insertions, 15 deletions
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 54b216cebcc..cbd6bf70309 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -791,7 +791,7 @@ void AuraEffect::CalculateSpellMod() GetBase()->CallScriptEffectCalcSpellModHandlers(this, m_spellmod); } -void AuraEffect::ChangeAmount(int32 newAmount, bool mark, bool onStackOrReapply) +void AuraEffect::ChangeAmount(int32 newAmount, bool mark, bool onStackOrReapply, AuraEffect const* triggeredBy /* = nullptr */) { // Reapply if amount change uint8 handleMask = 0; @@ -809,7 +809,7 @@ void AuraEffect::ChangeAmount(int32 newAmount, bool mark, bool onStackOrReapply) for (AuraApplication* aurApp : effectApplications) { aurApp->GetTarget()->_RegisterAuraEffect(this, false); - HandleEffect(aurApp, handleMask, false); + HandleEffect(aurApp, handleMask, false, triggeredBy); } if (handleMask & AURA_EFFECT_HANDLE_CHANGE_AMOUNT) @@ -827,14 +827,14 @@ void AuraEffect::ChangeAmount(int32 newAmount, bool mark, bool onStackOrReapply) continue; aurApp->GetTarget()->_RegisterAuraEffect(this, true); - HandleEffect(aurApp, handleMask, true); + HandleEffect(aurApp, handleMask, true, triggeredBy); } if (GetSpellInfo()->HasAttribute(SPELL_ATTR8_AURA_SEND_AMOUNT) || Aura::EffectTypeNeedsSendingAmount(GetAuraType())) GetBase()->SetNeedClientUpdateForTargets(); } -void AuraEffect::HandleEffect(AuraApplication * aurApp, uint8 mode, bool apply) +void AuraEffect::HandleEffect(AuraApplication * aurApp, uint8 mode, bool apply, AuraEffect const* triggeredBy /*= nullptr*/) { // check if call is correct, we really don't want using bitmasks here (with 1 exception) ASSERT(mode == AURA_EFFECT_HANDLE_REAL @@ -852,7 +852,7 @@ void AuraEffect::HandleEffect(AuraApplication * aurApp, uint8 mode, bool apply) // real aura apply/remove, handle modifier if (mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK) - ApplySpellMod(aurApp->GetTarget(), apply); + ApplySpellMod(aurApp->GetTarget(), apply, triggeredBy); // call scripts helping/replacing effect handlers bool prevented = false; @@ -880,14 +880,14 @@ void AuraEffect::HandleEffect(AuraApplication * aurApp, uint8 mode, bool apply) GetBase()->CallScriptAfterEffectRemoveHandlers(this, aurApp, (AuraEffectHandleModes)mode); } -void AuraEffect::HandleEffect(Unit* target, uint8 mode, bool apply) +void AuraEffect::HandleEffect(Unit* target, uint8 mode, bool apply, AuraEffect const* triggeredBy /*= nullptr*/) { AuraApplication* aurApp = GetBase()->GetApplicationOfTarget(target->GetGUID()); ASSERT(aurApp); - HandleEffect(aurApp, mode, apply); + HandleEffect(aurApp, mode, apply, triggeredBy); } -void AuraEffect::ApplySpellMod(Unit* target, bool apply) +void AuraEffect::ApplySpellMod(Unit* target, bool apply, AuraEffect const* triggeredBy /*= nullptr*/) { if (!m_spellmod || target->GetTypeId() != TYPEID_PLAYER) return; @@ -927,6 +927,9 @@ void AuraEffect::ApplySpellMod(Unit* target, bool apply) if (recalculateEffectMask.any()) { + if (!triggeredBy) + triggeredBy = this; + ObjectGuid guid = target->GetGUID(); Unit::AuraApplicationMap& auras = target->GetAppliedAuras(); for (auto iter = auras.begin(); iter != auras.end(); ++iter) @@ -938,7 +941,8 @@ void AuraEffect::ApplySpellMod(Unit* target, bool apply) for (size_t i = 0; i < recalculateEffectMask.size(); ++i) if (recalculateEffectMask[i]) if (AuraEffect* aurEff = aura->GetEffect(i)) - aurEff->RecalculateAmount(); + if (aurEff != triggeredBy) + aurEff->RecalculateAmount(triggeredBy); } } } diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.h b/src/server/game/Spells/Auras/SpellAuraEffects.h index 4ec5d04e5a0..71fbfe49364 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.h +++ b/src/server/game/Spells/Auras/SpellAuraEffects.h @@ -63,14 +63,14 @@ class TC_GAME_API AuraEffect int32 CalculateAmount(Unit* caster); void CalculatePeriodic(Unit* caster, bool resetPeriodicTimer = true, bool load = false); void CalculateSpellMod(); - void ChangeAmount(int32 newAmount, bool mark = true, bool onStackOrReapply = false); - void RecalculateAmount() { if (!CanBeRecalculated()) return; ChangeAmount(CalculateAmount(GetCaster()), false); } - void RecalculateAmount(Unit* caster) { if (!CanBeRecalculated()) return; ChangeAmount(CalculateAmount(caster), false); } + void ChangeAmount(int32 newAmount, bool mark = true, bool onStackOrReapply = false, AuraEffect const* triggeredBy = nullptr); + void RecalculateAmount(AuraEffect const* triggeredBy = nullptr) { if (!CanBeRecalculated()) return; ChangeAmount(CalculateAmount(GetCaster()), false, false, triggeredBy); } + void RecalculateAmount(Unit* caster, AuraEffect const* triggeredBy = nullptr) { if (!CanBeRecalculated()) return; ChangeAmount(CalculateAmount(caster), false, false, triggeredBy); } bool CanBeRecalculated() const { return m_canBeRecalculated; } void SetCanBeRecalculated(bool val) { m_canBeRecalculated = val; } - void HandleEffect(AuraApplication * aurApp, uint8 mode, bool apply); - void HandleEffect(Unit* target, uint8 mode, bool apply); - void ApplySpellMod(Unit* target, bool apply); + void HandleEffect(AuraApplication * aurApp, uint8 mode, bool apply, AuraEffect const* triggeredBy = nullptr); + void HandleEffect(Unit* target, uint8 mode, bool apply, AuraEffect const* triggeredBy = nullptr); + void ApplySpellMod(Unit* target, bool apply, AuraEffect const* triggeredBy = nullptr); void SetDamage(int32 val) { m_damage = val; } int32 GetDamage() const { return m_damage; } |