From 56077b35c30a97fd90e73a14df6e6597f8f21414 Mon Sep 17 00:00:00 2001 From: Meji Date: Sat, 21 Oct 2023 20:41:40 +0200 Subject: [PATCH] Core/Creatures: Improved movement interruption while casting spells --- src/server/game/Entities/Creature/Creature.cpp | 15 ++------------- src/server/game/Entities/Unit/Unit.cpp | 3 ++- src/server/game/Spells/Spell.cpp | 10 ++++++++-- 3 files changed, 12 insertions(+), 16 deletions(-) diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index da81949dc6..256ffcf243 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -3236,21 +3236,10 @@ void Creature::ReacquireSpellFocusTarget() bool Creature::IsMovementPreventedByCasting() const { - // Creature is not casting. This state check is needed for scripted casting states which are usually considered hacks but for now we keep it. - if (!HasUnitState(UNIT_STATE_CASTING)) + if (!Unit::IsMovementPreventedByCasting() && !HasSpellFocus()) return false; - Spell* spellToCheck = nullptr; - - if (Spell* spell = m_currentSpells[CURRENT_CHANNELED_SPELL]) // Check for active channeled spells - spellToCheck = spell; - else if (Spell* spell = m_currentSpells[CURRENT_GENERIC_SPELL]) // Check for ongoing spell casts - spellToCheck = spell; - - if (!spellToCheck) - return false; - - return (spellToCheck->CheckMovement() != SPELL_CAST_OK); + return true; } void Creature::StartPickPocketRefillTimer() diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 77085beb15..bea9788d7b 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -2892,7 +2892,8 @@ bool Unit::IsMovementPreventedByCasting() const return false; if (Spell* spell = m_currentSpells[CURRENT_GENERIC_SPELL]) - if (HasAuraTypeWithAffectMask(SPELL_AURA_CAST_WHILE_WALKING, spell->GetSpellInfo())) + if (HasAuraTypeWithAffectMask(SPELL_AURA_CAST_WHILE_WALKING, spell->GetSpellInfo()) || spell->getState() == SPELL_STATE_FINISHED || + !spell->m_spellInfo->InterruptFlags.HasFlag(SpellInterruptFlags::Movement)) return false; // channeled spells during channel stage (after the initial cast timer) allow movement with a specific spell attribute diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 0bc42444a8..4ea468ee81 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -3377,7 +3377,7 @@ SpellCastResult Spell::prepare(SpellCastTargets const& targets, AuraEffect const else m_casttime = m_spellInfo->CalcCastTime(m_caster->IsUnit() ? m_caster->ToUnit()->getLevel() : 0, this); - if (m_caster->IsPlayer() && m_caster->ToUnit()->isMoving()) + if (m_caster->IsUnit() && m_caster->ToUnit()->isMoving()) { result = CheckMovement(); if (result != SPELL_CAST_OK) @@ -4076,7 +4076,7 @@ void Spell::update(uint32 difftime) // check if the player caster has moved before the spell finished // with the exception of spells affected with SPELL_AURA_CAST_WHILE_WALKING effect - if (m_timer != 0 && m_caster->IsPlayer() && m_caster->ToUnit()->isMoving() && CheckMovement() != SPELL_CAST_OK) + if (m_timer != 0 && m_caster->IsUnit() && m_caster->ToUnit()->isMoving() && CheckMovement() != SPELL_CAST_OK) { // if charmed by creature, trust the AI not to cheat and allow the cast to proceed // @todo this is a hack, "creature" movesplines don't differentiate turning/moving right now @@ -6805,6 +6805,12 @@ SpellCastResult Spell::CheckMovement() const if (IsTriggered()) return SPELL_CAST_OK; + // Creatures (not controlled) give priority to spell casting over movement. + // We assume that the casting is always valid and the current movement + // is stopped by Unit:IsmovementPreventedByCasting to prevent casting interruption. + if (m_caster->IsCreature() && !m_caster->ToCreature()->IsControlledByPlayer()) + return SPELL_CAST_OK; + if (Unit* unitCaster = m_caster->ToUnit()) { if (!unitCaster->HasAuraTypeWithAffectMask(SPELL_AURA_CAST_WHILE_WALKING, m_spellInfo))