diff --git a/Source/Framework/Constants/Spells/SpellConst.cs b/Source/Framework/Constants/Spells/SpellConst.cs index ff1c6bbeb..57c1f8b9f 100644 --- a/Source/Framework/Constants/Spells/SpellConst.cs +++ b/Source/Framework/Constants/Spells/SpellConst.cs @@ -98,6 +98,13 @@ namespace Framework.Constants Ranged = 2 //hunter range and ranged weapon } + public enum SpellFinishReason + { + SuccessfulCast = 0, // spell has sucessfully launched + Canceled = 1, // spell has been canceled (interrupts) + ChannelingComplete = 2 // spell channeling has been finished + } + [Flags] public enum SpellInterruptFlags { diff --git a/Source/Game/AI/CoreAI/CreatureAI.cs b/Source/Game/AI/CoreAI/CreatureAI.cs index 24939e55a..661c408c9 100644 --- a/Source/Game/AI/CoreAI/CreatureAI.cs +++ b/Source/Game/AI/CoreAI/CreatureAI.cs @@ -492,11 +492,8 @@ namespace Game.AI // Called when spell hits a target public virtual void SpellHitTarget(WorldObject target, SpellInfo spellInfo) { } - // Called when a spell cast gets interrupted - public virtual void OnSpellCastInterrupt(SpellInfo spell) { } - - // Called when a spell cast has been successfully finished - public virtual void OnSuccessfulSpellCast(SpellInfo spell) { } + // Called when a spell either finishes, interrupts or cancels a spell cast + public virtual void OnSpellCastFinished(SpellInfo spell, SpellFinishReason reason) { } // Should return true if the NPC is currently being escorted public virtual bool IsEscorted() { return false; } diff --git a/Source/Game/Entities/Unit/Unit.Spells.cs b/Source/Game/Entities/Unit/Unit.Spells.cs index ab39a766e..907941c2b 100644 --- a/Source/Game/Entities/Unit/Unit.Spells.cs +++ b/Source/Game/Entities/Unit/Unit.Spells.cs @@ -2422,7 +2422,7 @@ namespace Game.Entities } if (IsCreature() && IsAIEnabled()) - ToCreature().GetAI().OnSpellCastInterrupt(spell.GetSpellInfo()); + ToCreature().GetAI().OnSpellCastFinished(spell.GetSpellInfo(), SpellFinishReason.Canceled); } } public void UpdateInterruptMask() diff --git a/Source/Game/Spells/Spell.cs b/Source/Game/Spells/Spell.cs index d40041593..ba223e5e3 100644 --- a/Source/Game/Spells/Spell.cs +++ b/Source/Game/Spells/Spell.cs @@ -2904,7 +2904,7 @@ namespace Game.Spells Creature caster = m_originalCaster.ToCreature(); if (caster) if (caster.IsAIEnabled()) - caster.GetAI().OnSuccessfulSpellCast(GetSpellInfo()); + caster.GetAI().OnSpellCastFinished(GetSpellInfo(), SpellFinishReason.SuccessfulCast); } void DoProcessTargetContainer(List targetContainer) where T : TargetInfoBase @@ -3267,6 +3267,12 @@ namespace Game.Spells { SendChannelUpdate(0); Finish(); + + // We call the hook here instead of in Spell::finish because we only want to call it for completed channeling. Everything else is handled by interrupts + Creature creatureCaster = m_caster.ToCreature(); + if (creatureCaster != null) + if (creatureCaster.IsAIEnabled()) + creatureCaster.GetAI().OnSpellCastFinished(m_spellInfo, SpellFinishReason.ChannelingComplete); } break; }