diff --git a/Source/Framework/Constants/Spells/SpellConst.cs b/Source/Framework/Constants/Spells/SpellConst.cs index fda3f2f8e..084c124a6 100644 --- a/Source/Framework/Constants/Spells/SpellConst.cs +++ b/Source/Framework/Constants/Spells/SpellConst.cs @@ -39,10 +39,10 @@ namespace Framework.Constants public enum SpellLinkedType { - Cast = 0, // +: cast; -: remove - Hit = 1 * 200000, - Aura = 2 * 200000, // +: aura; -: immune - Remove = 0 + Cast = 0, // +: cast; -: remove + Hit = 1, + Aura = 2, // +: aura; -: immune + Remove = 3 } //Spell targets used by SelectSpell diff --git a/Source/Game/Spells/Auras/Aura.cs b/Source/Game/Spells/Auras/Aura.cs index 8e661a349..96bc80028 100644 --- a/Source/Game/Spells/Auras/Aura.cs +++ b/Source/Game/Spells/Auras/Aura.cs @@ -1238,7 +1238,7 @@ namespace Game.Spells // apply linked auras if (apply) { - var spellTriggered = Global.SpellMgr.GetSpellLinked((int)GetId() + (int)SpellLinkedType.Aura); + var spellTriggered = Global.SpellMgr.GetSpellLinked(SpellLinkedType.Aura, GetId()); if (spellTriggered != null) { foreach (var spell in spellTriggered) @@ -1253,7 +1253,7 @@ namespace Game.Spells else { // remove linked auras - var spellTriggered = Global.SpellMgr.GetSpellLinked(-(int)GetId()); + var spellTriggered = Global.SpellMgr.GetSpellLinked(SpellLinkedType.Remove, GetId()); if (spellTriggered != null) { foreach (var spell in spellTriggered) @@ -1266,7 +1266,7 @@ namespace Game.Spells .SetOriginalCastId(GetCastId())); } } - spellTriggered = Global.SpellMgr.GetSpellLinked((int)GetId() + (int)SpellLinkedType.Aura); + spellTriggered = Global.SpellMgr.GetSpellLinked(SpellLinkedType.Aura, GetId()); if (spellTriggered != null) { foreach (var id in spellTriggered) @@ -1282,7 +1282,7 @@ namespace Game.Spells else if (apply) { // modify stack amount of linked auras - var spellTriggered = Global.SpellMgr.GetSpellLinked((int)GetId() + (int)SpellLinkedType.Aura); + var spellTriggered = Global.SpellMgr.GetSpellLinked(SpellLinkedType.Aura, GetId()); if (spellTriggered != null) { foreach (var id in spellTriggered) diff --git a/Source/Game/Spells/Spell.cs b/Source/Game/Spells/Spell.cs index 269ddcb67..660b48eb0 100644 --- a/Source/Game/Spells/Spell.cs +++ b/Source/Game/Spells/Spell.cs @@ -2312,7 +2312,7 @@ namespace Game.Spells // trigger linked auras remove/apply // @todo remove/cleanup this, as this table is not documented and people are doing stupid things with it - var spellTriggered = Global.SpellMgr.GetSpellLinked((int)m_spellInfo.Id + (int)SpellLinkedType.Hit); + var spellTriggered = Global.SpellMgr.GetSpellLinked(SpellLinkedType.Hit, m_spellInfo.Id); if (spellTriggered != null) { foreach (var id in spellTriggered) @@ -2894,7 +2894,7 @@ namespace Game.Spells CallScriptAfterCastHandlers(); - var spell_triggered = Global.SpellMgr.GetSpellLinked((int)m_spellInfo.Id); + var spell_triggered = Global.SpellMgr.GetSpellLinked(SpellLinkedType.Cast, m_spellInfo.Id); if (spell_triggered != null) { foreach (var spellId in spell_triggered) diff --git a/Source/Game/Spells/SpellManager.cs b/Source/Game/Spells/SpellManager.cs index 4c0a0207b..da41439ae 100644 --- a/Source/Game/Spells/SpellManager.cs +++ b/Source/Game/Spells/SpellManager.cs @@ -562,9 +562,9 @@ namespace Game.Entities return false; } - public List GetSpellLinked(int spell_id) + public List GetSpellLinked(SpellLinkedType type, uint spellId) { - return mSpellLinkedMap.LookupByKey(spell_id); + return mSpellLinkedMap.LookupByKey((type, spellId)); } public MultiMap GetPetLevelupSpellList(CreatureFamily petFamily) @@ -1730,7 +1730,7 @@ namespace Game.Entities { int trigger = result.Read(0); int effect = result.Read(1); - int type = result.Read(2); + SpellLinkedType type = (SpellLinkedType)result.Read(2); SpellInfo spellInfo = GetSpellInfo((uint)Math.Abs(trigger), Difficulty.None); if (spellInfo == null) @@ -1754,14 +1754,32 @@ namespace Game.Entities continue; } - if (type != 0) //we will find a better way when more types are needed + if (type < SpellLinkedType.Cast || type > SpellLinkedType.Remove) { - if (trigger > 0) - trigger += 200000 * type; - else - trigger -= 200000 * type; + Log.outError(LogFilter.Sql, $"The spell trigger {trigger}, effect {effect} listed in `spell_linked_spell` has invalid link type {type}, skipped."); + continue; } - mSpellLinkedMap.Add(trigger, effect); + + if (trigger < 0) + { + if (type != SpellLinkedType.Cast) + Log.outError(LogFilter.Sql, $"The spell trigger {trigger} listed in `spell_linked_spell` has invalid link type {type}, changed to 0."); + + trigger = -trigger; + type = SpellLinkedType.Remove; + } + + + if (type != SpellLinkedType.Aura) + { + if (trigger == effect) + { + Log.outError(LogFilter.Sql, $"The spell trigger {trigger}, effect {effect} listed in `spell_linked_spell` triggers itself (infinite loop), skipped."); + continue; + } + } + + mSpellLinkedMap.Add((type, (uint)trigger), effect); ++count; } while (result.NextRow()); @@ -4729,7 +4747,7 @@ namespace Game.Entities Dictionary<(uint id, Difficulty difficulty), SpellProcEntry> mSpellProcMap = new(); Dictionary mSpellThreatMap = new(); Dictionary mSpellPetAuraMap = new(); - MultiMap mSpellLinkedMap = new(); + MultiMap<(SpellLinkedType, uint), int> mSpellLinkedMap = new(); Dictionary mSpellEnchantProcEventMap = new(); MultiMap mSpellAreaMap = new(); MultiMap mSpellAreaForQuestMap = new();