diff options
| author | Shauren <shauren.trinity@gmail.com> | 2023-06-29 11:39:02 +0200 |
|---|---|---|
| committer | Shauren <shauren.trinity@gmail.com> | 2023-06-29 11:39:02 +0200 |
| commit | 29eac37a16df2ec14cba89f4d6e28f54ca1a4e25 (patch) | |
| tree | 0e340300bd3e1e0aaf8ff27324434b59f6a3e2d2 /src/server/game/Spells | |
| parent | bacfbec25180cd0a02fec20e788d74e2fcaf1a0c (diff) | |
Core/Spells: Fully prevent infinite proc loops and add logging to detect most spells that could possibly trigger this behavior at startup
Closes #28865
Diffstat (limited to 'src/server/game/Spells')
| -rw-r--r-- | src/server/game/Spells/Spell.cpp | 1 | ||||
| -rw-r--r-- | src/server/game/Spells/Spell.h | 3 | ||||
| -rw-r--r-- | src/server/game/Spells/SpellMgr.cpp | 21 |
3 files changed, 25 insertions, 0 deletions
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index ba4ac81046f..4029dfdcfa0 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -584,6 +584,7 @@ m_spellValue(new SpellValue(m_spellInfo, caster)), _spellEvent(nullptr) memset(m_misc.Raw.Data, 0, sizeof(m_misc.Raw.Data)); m_SpellVisual.SpellXSpellVisualID = caster->GetCastSpellXSpellVisualId(m_spellInfo); m_triggeredByAuraSpell = nullptr; + m_procChainLength = caster->IsUnit() ? caster->ToUnit()->GetProcChainLength() : 0; _spellAura = nullptr; _dynObjAura = nullptr; diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h index 3ebadc1c125..52b57d48d7c 100644 --- a/src/server/game/Spells/Spell.h +++ b/src/server/game/Spells/Spell.h @@ -607,6 +607,8 @@ class TC_GAME_API Spell bool IsTriggeredByAura(SpellInfo const* auraSpellInfo) const { return (auraSpellInfo == m_triggeredByAuraSpell); } + int32 GetProcChainLength() const { return m_procChainLength; } + bool IsDeletable() const { return !m_referencedFromCurrentSpell && !m_executedCurrently; } void SetReferencedFromCurrent(bool yes) { m_referencedFromCurrentSpell = yes; } bool IsInterruptable() const { return !m_executedCurrently; } @@ -895,6 +897,7 @@ class TC_GAME_API Spell // we can't store original aura link to prevent access to deleted auras // and in same time need aura data and after aura deleting. SpellInfo const* m_triggeredByAuraSpell; + int32 m_procChainLength; std::unique_ptr<PathGenerator> m_preGeneratedPath; diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index 5e39db72916..c4279567f70 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -1813,6 +1813,7 @@ void SpellMgr::LoadSpellProcs() procEntry.SpellPhaseMask = PROC_SPELL_PHASE_HIT; procEntry.HitMask = PROC_HIT_NONE; // uses default proc @see SpellMgr::CanSpellTriggerProcOnEvent + bool triggersSpell = false; for (SpellEffectInfo const& spellEffectInfo : spellInfo.GetEffects()) { if (!spellEffectInfo.IsAura()) @@ -1838,6 +1839,10 @@ void SpellMgr::LoadSpellProcs() if (spellEffectInfo.CalcValue() <= -100) procEntry.HitMask = PROC_HIT_MISS; break; + case SPELL_AURA_PROC_TRIGGER_SPELL: + case SPELL_AURA_PROC_TRIGGER_SPELL_WITH_VALUE: + triggersSpell = spellEffectInfo.TriggerSpell != 0; + break; default: continue; } @@ -1856,6 +1861,22 @@ void SpellMgr::LoadSpellProcs() procEntry.Cooldown = Milliseconds(spellInfo.ProcCooldown); procEntry.Charges = spellInfo.ProcCharges; + if (spellInfo.HasAttribute(SPELL_ATTR3_CAN_PROC_FROM_PROCS) && !procEntry.SpellFamilyMask + && procEntry.Chance >= 100 + && spellInfo.ProcBasePPM <= 0.0f + && procEntry.Cooldown <= 0ms + && procEntry.Charges <= 0 + && procEntry.ProcFlags & (PROC_FLAG_DEAL_MELEE_ABILITY | PROC_FLAG_DEAL_RANGED_ATTACK | PROC_FLAG_DEAL_RANGED_ABILITY | PROC_FLAG_DEAL_HELPFUL_ABILITY + | PROC_FLAG_DEAL_HARMFUL_ABILITY | PROC_FLAG_DEAL_HELPFUL_SPELL | PROC_FLAG_DEAL_HARMFUL_SPELL | PROC_FLAG_DEAL_HARMFUL_PERIODIC + | PROC_FLAG_DEAL_HELPFUL_PERIODIC) + && triggersSpell) + { + TC_LOG_ERROR("sql.sql", "Spell Id {} has SPELL_ATTR3_CAN_PROC_FROM_PROCS attribute and no restriction on what spells can cause it to proc and no cooldown. " + "This spell can cause infinite proc loops. Proc data for this spell was not generated, data in `spell_proc` table is required for it to function!", + spellInfo.Id); + continue; + } + mSpellProcMap[{ spellInfo.Id, spellInfo.Difficulty }] = procEntry; ++count; } |
