diff options
author | Shauren <shauren.trinity@gmail.com> | 2022-05-07 23:31:55 +0200 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2022-05-07 23:31:55 +0200 |
commit | 538fa8e97ff4b4e36a59e37fd74ea8958e6e30d2 (patch) | |
tree | a41886fe93437c3381eae6e52552a22d5c005e23 /src | |
parent | 0620b829b2597777f2b5d931dfb0336f79dfd0df (diff) |
Core/Spells: Cleanup movement checks in spells - use correct interrupt flags
Diffstat (limited to 'src')
-rw-r--r-- | src/server/game/Entities/Creature/Creature.cpp | 2 | ||||
-rw-r--r-- | src/server/game/Entities/Unit/Unit.cpp | 5 | ||||
-rw-r--r-- | src/server/game/Spells/Spell.cpp | 73 | ||||
-rw-r--r-- | src/server/game/Spells/Spell.h | 1 |
4 files changed, 41 insertions, 40 deletions
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 35fc80c0e22..03f2b9f783e 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -3363,7 +3363,7 @@ bool Creature::IsMovementPreventedByCasting() const if (Spell* spell = m_currentSpells[CURRENT_CHANNELED_SPELL]) { if (spell->getState() != SPELL_STATE_FINISHED && spell->IsChannelActive()) - if (spell->GetSpellInfo()->IsMoveAllowedChannel()) + if (spell->CheckMovement() != SPELL_CAST_OK) return false; } diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 5ae10b11ca9..b4a689e6f4a 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -2784,8 +2784,7 @@ void Unit::_UpdateAutoRepeatSpell() // check "realtime" interrupts // don't cancel spells which are affected by a SPELL_AURA_CAST_WHILE_WALKING effect - if (((GetTypeId() == TYPEID_PLAYER && ToPlayer()->isMoving()) || IsNonMeleeSpellCast(false, false, true, autoRepeatSpellInfo->Id == 75)) && - !CanCastSpellWhileMoving(autoRepeatSpellInfo)) + if ((isMoving() && m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->CheckMovement() != SPELL_CAST_OK) || IsNonMeleeSpellCast(false, false, true, autoRepeatSpellInfo->Id == 75)) { // cancel wand shoot if (autoRepeatSpellInfo->Id != 75) @@ -3015,7 +3014,7 @@ bool Unit::IsMovementPreventedByCasting() const // channeled spells during channel stage (after the initial cast timer) allow movement with a specific spell attribute if (Spell* spell = m_currentSpells[CURRENT_CHANNELED_SPELL]) if (spell->getState() != SPELL_STATE_FINISHED && spell->IsChannelActive()) - if (spell->GetSpellInfo()->IsMoveAllowedChannel()) + if (spell->GetSpellInfo()->IsMoveAllowedChannel() || CanCastSpellWhileMoving(spell->GetSpellInfo())) return false; // prohibit movement for all other spell casts diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 119585fb60b..e207befbf55 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -3375,19 +3375,14 @@ SpellCastResult Spell::prepare(SpellCastTargets const& targets, AuraEffect const else m_casttime = m_spellInfo->CalcCastTime(this); - // don't allow channeled spells / spells with cast time to be cast while moving - // exception are only channeled spells that have no casttime and dont have movement interrupt flag - // (even if they are interrupted on moving, spells with almost immediate effect get to have their effect processed before movement interrupter kicks in) - // don't cancel spells which are affected by a SPELL_AURA_CAST_WHILE_WALKING effect - if (((m_spellInfo->IsChanneled() || m_casttime) && m_caster->GetTypeId() == TYPEID_PLAYER && !(m_caster->ToUnit()->IsCharmed() && m_caster->ToUnit()->GetCharmerGUID().IsCreature()) && m_caster->ToUnit()->isMoving() && - m_spellInfo->InterruptFlags.HasFlag(SpellInterruptFlags::Movement)) && !m_caster->ToUnit()->CanCastSpellWhileMoving(m_spellInfo)) + if (m_caster->IsUnit() && m_caster->ToUnit()->isMoving()) { - // 1. Has casttime, 2. Or doesn't have flag to allow movement during channel - if (m_casttime || !m_spellInfo->IsMoveAllowedChannel()) + result = CheckMovement(); + if (result != SPELL_CAST_OK) { - SendCastResult(SPELL_FAILED_MOVING); + SendCastResult(result); finish(false); - return SPELL_FAILED_MOVING; + return result; } } @@ -4110,20 +4105,13 @@ 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_caster->GetTypeId() == TYPEID_PLAYER && m_timer != 0) && - m_caster->ToUnit()->isMoving() && (m_spellInfo->InterruptFlags.HasFlag(SpellInterruptFlags::Movement)) && - (!m_spellInfo->HasEffect(SPELL_EFFECT_STUCK) || !m_caster->ToUnit()->HasUnitMovementFlag(MOVEMENTFLAG_FALLING_FAR)) && - !m_caster->ToUnit()->CanCastSpellWhileMoving(m_spellInfo)) + if (m_timer != 0 && m_caster->IsUnit() && m_caster->ToUnit()->isMoving() && CheckMovement() != SPELL_CAST_OK) { - // don't cancel for melee, autorepeat, triggered and instant spells - if (!m_spellInfo->IsNextMeleeSwingSpell() && !IsAutoRepeat() && !IsTriggered() && !(IsChannelActive() && m_spellInfo->IsMoveAllowedChannel())) - { - // 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 - // however, checking what type of movement the spline is for every single spline would be really expensive - if (!m_caster->ToUnit()->GetCharmerGUID().IsCreature()) - cancel(); - } + // 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 + // however, checking what type of movement the spline is for every single spline would be really expensive + if (!m_caster->ToUnit()->GetCharmerGUID().IsCreature()) + cancel(); } switch (m_spellState) @@ -5579,19 +5567,6 @@ SpellCastResult Spell::CheckCast(bool strict, int32* param1 /*= nullptr*/, int32 return SPELL_FAILED_AFFECTING_COMBAT; } - // cancel autorepeat spells if cast start when moving - // (not wand currently autorepeat cast delayed to moving stop anyway in spell update code) - // Do not cancel spells which are affected by a SPELL_AURA_CAST_WHILE_WALKING effect - if (unitCaster->GetTypeId() == TYPEID_PLAYER && unitCaster->ToPlayer()->isMoving() - && (!unitCaster->IsCharmed() || !unitCaster->GetCharmerGUID().IsCreature()) - && !unitCaster->CanCastSpellWhileMoving(m_spellInfo)) - { - // skip stuck spell to allow use it in falling case and apply spell limitations at movement - if ((!unitCaster->HasUnitMovementFlag(MOVEMENTFLAG_FALLING_FAR) || !m_spellInfo->HasEffect(SPELL_EFFECT_STUCK)) && - (IsAutoRepeat() || m_spellInfo->HasAuraInterruptFlag(SpellAuraInterruptFlags::Standing))) - return SPELL_FAILED_MOVING; - } - // Check vehicle flags if (!(_triggeredCastFlags & TRIGGERED_IGNORE_CASTER_MOUNTED_OR_ON_VEHICLE)) { @@ -6861,6 +6836,32 @@ SpellCastResult Spell::CheckArenaAndRatedBattlegroundCastRules() return SPELL_CAST_OK; } +SpellCastResult Spell::CheckMovement() const +{ + if (IsTriggered()) + return SPELL_CAST_OK; + + if (Unit* unitCaster = m_caster->ToUnit()) + { + if (!unitCaster->CanCastSpellWhileMoving(m_spellInfo)) + { + if (m_casttime) + { + if (m_spellInfo->InterruptFlags.HasFlag(SpellInterruptFlags::Movement)) + return SPELL_FAILED_MOVING; + } + else + { + // only fail channeled casts if they are instant but cannot be channeled while moving + if (m_spellInfo->IsChanneled() && !m_spellInfo->IsMoveAllowedChannel()) + return SPELL_FAILED_MOVING; + } + } + } + + return SPELL_CAST_OK; +} + int32 Spell::CalculateDamage(SpellEffectInfo const& spellEffectInfo, Unit const* target, float* var /*= nullptr*/) const { bool needRecalculateBasePoints = !(m_spellValue->CustomBasePointsMask & (1 << spellEffectInfo.EffectIndex)); diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h index 23e044c30e2..86a6404fd6d 100644 --- a/src/server/game/Spells/Spell.h +++ b/src/server/game/Spells/Spell.h @@ -464,6 +464,7 @@ class TC_GAME_API Spell SpellCastResult CheckRuneCost() const; SpellCastResult CheckCasterAuras(int32* param1) const; SpellCastResult CheckArenaAndRatedBattlegroundCastRules(); + SpellCastResult CheckMovement() const; bool CheckSpellCancelsAuraEffect(AuraType auraType, int32* param1) const; bool CheckSpellCancelsCharm(int32* param1) const; |