diff options
| -rw-r--r-- | src/server/game/Entities/Unit/Unit.cpp | 23 | ||||
| -rw-r--r-- | src/server/game/Entities/Unit/Unit.h | 1 | ||||
| -rw-r--r-- | src/server/game/Spells/Auras/SpellAuraDefines.h | 4 | ||||
| -rw-r--r-- | src/server/game/Spells/Auras/SpellAuraEffects.cpp | 6 | ||||
| -rw-r--r-- | src/server/game/Spells/Spell.cpp | 16 |
5 files changed, 36 insertions, 14 deletions
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index f8baf13cdd1..bf2a9a1fc1f 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -2745,7 +2745,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)) && - !HasAuraTypeWithAffectMask(SPELL_AURA_CAST_WHILE_WALKING, autoRepeatSpellInfo)) + !CanCastSpellWhileMoving(autoRepeatSpellInfo)) { // cancel wand shoot if (autoRepeatSpellInfo->Id != 75) @@ -2967,6 +2967,10 @@ bool Unit::IsMovementPreventedByCasting() const if (!HasUnitState(UNIT_STATE_CASTING)) return false; + if (Spell* spell = m_currentSpells[CURRENT_GENERIC_SPELL]) + if (CanCastSpellWhileMoving(spell->GetSpellInfo())) + return false; + // 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()) @@ -2977,6 +2981,21 @@ bool Unit::IsMovementPreventedByCasting() const return true; } +bool Unit::CanCastSpellWhileMoving(SpellInfo const* spellInfo) const +{ + if (HasAuraTypeWithAffectMask(SPELL_AURA_CAST_WHILE_WALKING, spellInfo)) + return true; + + if (HasAuraType(SPELL_AURA_CAST_WHILE_WALKING_ALL)) + return true; + + for (uint32 label : spellInfo->Labels) + if (HasAuraTypeWithMiscvalue(SPELL_AURA_CAST_WHILE_WALKING_BY_SPELL_LABEL, label)) + return true; + + return false; +} + bool Unit::isInFrontInMap(Unit const* target, float distance, float arc) const { return IsWithinDistInMap(target, distance) && HasInArc(arc, target); @@ -3874,7 +3893,7 @@ bool IsInterruptFlagIgnoredForSpell(InterruptFlag /*flag*/, Unit const* /*unit*/ template<> bool IsInterruptFlagIgnoredForSpell(SpellAuraInterruptFlags flag, Unit const* unit, SpellInfo const* spellInfo) { - return flag == SpellAuraInterruptFlags::Moving && unit->HasAuraTypeWithAffectMask(SPELL_AURA_CAST_WHILE_WALKING, spellInfo); + return flag == SpellAuraInterruptFlags::Moving && unit->CanCastSpellWhileMoving(spellInfo); } template <typename InterruptFlags> diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 95efb8fc925..82b94f3b096 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1498,6 +1498,7 @@ class TC_GAME_API Unit : public WorldObject virtual bool IsFocusing(Spell const* /*focusSpell*/ = nullptr, bool /*withDelay*/ = false) { return false; } virtual bool IsMovementPreventedByCasting() const; + bool CanCastSpellWhileMoving(SpellInfo const* spellInfo) const; SpellHistory* GetSpellHistory() { return _spellHistory; } SpellHistory const* GetSpellHistory() const { return _spellHistory; } diff --git a/src/server/game/Spells/Auras/SpellAuraDefines.h b/src/server/game/Spells/Auras/SpellAuraDefines.h index 040c7a1df7b..2287a1f772f 100644 --- a/src/server/game/Spells/Auras/SpellAuraDefines.h +++ b/src/server/game/Spells/Auras/SpellAuraDefines.h @@ -392,7 +392,7 @@ enum AuraType : uint32 SPELL_AURA_MOD_FAKE_INEBRIATE = 304, SPELL_AURA_MOD_MINIMUM_SPEED = 305, SPELL_AURA_MOD_CRIT_CHANCE_FOR_CASTER = 306, - SPELL_AURA_CAST_WHILE_WALKING_BY_SPELL_LABEL = 307, // NYI + SPELL_AURA_CAST_WHILE_WALKING_BY_SPELL_LABEL = 307, SPELL_AURA_MOD_CRIT_CHANCE_FOR_CASTER_WITH_ABILITIES = 308, SPELL_AURA_MOD_RESILIENCE = 309, // NYI SPELL_AURA_MOD_CREATURE_AOE_DAMAGE_AVOIDANCE = 310, @@ -462,7 +462,7 @@ enum AuraType : uint32 SPELL_AURA_MODIFY_FALL_DAMAGE_PCT = 374, // NYI SPELL_AURA_HIDE_MODEL_AND_EQUIPEMENT_SLOTS = 375, SPELL_AURA_MOD_CURRENCY_GAIN_FROM_SOURCE = 376, // NYI - SPELL_AURA_CAST_WHILE_WALKING_2 = 377, // NYI + SPELL_AURA_CAST_WHILE_WALKING_ALL = 377, // Enables casting all spells while moving SPELL_AURA_MOD_POSSESS_PET = 378, SPELL_AURA_MOD_MANA_REGEN_PCT = 379, SPELL_AURA_380 = 380, diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index d1cd0b044fe..ff7ffd5f443 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -375,7 +375,7 @@ NonDefaultConstructible<pAuraEffectHandler> AuraEffectHandler[TOTAL_AURAS]= &AuraEffect::HandleAuraModFakeInebriation, //304 SPELL_AURA_MOD_DRUNK &AuraEffect::HandleAuraModIncreaseSpeed, //305 SPELL_AURA_MOD_MINIMUM_SPEED &AuraEffect::HandleNoImmediateEffect, //306 SPELL_AURA_MOD_CRIT_CHANCE_FOR_CASTER implemented in Unit::GetUnitCriticalChance and Unit::GetUnitSpellCriticalChance - &AuraEffect::HandleNULL, //307 SPELL_AURA_CAST_WHILE_WALKING_BY_SPELL_LABEL + &AuraEffect::HandleNoImmediateEffect, //307 SPELL_AURA_CAST_WHILE_WALKING_BY_SPELL_LABEL implemented in Unit::CanCastSpellWhileMoving &AuraEffect::HandleNoImmediateEffect, //308 SPELL_AURA_MOD_CRIT_CHANCE_FOR_CASTER_WITH_ABILITIES implemented in Unit::GetUnitSpellCriticalChance &AuraEffect::HandleNULL, //309 SPELL_AURA_MOD_RESILIENCE &AuraEffect::HandleNoImmediateEffect, //310 SPELL_AURA_MOD_CREATURE_AOE_DAMAGE_AVOIDANCE implemented in Spell::CalculateDamageDone @@ -398,7 +398,7 @@ NonDefaultConstructible<pAuraEffectHandler> AuraEffectHandler[TOTAL_AURAS]= &AuraEffect::HandlePhaseAlwaysVisible, //327 SPELL_AURA_PHASE_ALWAYS_VISIBLE &AuraEffect::HandleTriggerSpellOnPowerPercent, //328 SPELL_AURA_TRIGGER_SPELL_ON_POWER_PCT &AuraEffect::HandleNULL, //329 SPELL_AURA_MOD_POWER_GAIN_PCT - &AuraEffect::HandleNoImmediateEffect, //330 SPELL_AURA_CAST_WHILE_WALKING + &AuraEffect::HandleNoImmediateEffect, //330 SPELL_AURA_CAST_WHILE_WALKING implemented in Unit::CanCastSpellWhileMoving &AuraEffect::HandleAuraForceWeather, //331 SPELL_AURA_FORCE_WEATHER &AuraEffect::HandleNoImmediateEffect, //332 SPELL_AURA_OVERRIDE_ACTIONBAR_SPELLS implemented in Unit::GetCastSpellInfo &AuraEffect::HandleNoImmediateEffect, //333 SPELL_AURA_OVERRIDE_ACTIONBAR_SPELLS_TRIGGERED implemented in Unit::GetCastSpellInfo @@ -445,7 +445,7 @@ NonDefaultConstructible<pAuraEffectHandler> AuraEffectHandler[TOTAL_AURAS]= &AuraEffect::HandleNULL, //374 SPELL_AURA_MODIFY_FALL_DAMAGE_PCT &AuraEffect::HandleNULL, //375 SPELL_AURA_HIDE_MODEL_AND_EQUIPEMENT_SLOTS implemented clientside &AuraEffect::HandleNULL, //376 SPELL_AURA_MOD_CURRENCY_GAIN_FROM_SOURCE - &AuraEffect::HandleNULL, //377 SPELL_AURA_CAST_WHILE_WALKING_2 + &AuraEffect::HandleNoImmediateEffect, //377 SPELL_AURA_CAST_WHILE_WALKING_ALL implemented in Unit::CanCastSpellWhileMoving &AuraEffect::HandleModPossessPet, //378 SPELL_AURA_MOD_POSSESS_PET &AuraEffect::HandleModManaRegenPct, //379 SPELL_AURA_MOD_MANA_REGEN_PCT implemented in Player::UpdateManaRegen &AuraEffect::HandleNULL, //380 diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 90efc980ffb..90d342e1b3d 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -3153,8 +3153,8 @@ void Spell::prepare(SpellCastTargets const& targets, AuraEffect const* triggered // exception are only channeled spells that have no casttime and SPELL_ATTR5_CAN_CHANNEL_WHEN_MOVING // (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->ToPlayer()->IsCharmed() && m_caster->ToPlayer()->GetCharmerGUID().IsCreature()) && m_caster->ToPlayer()->isMoving() && - m_spellInfo->InterruptFlags.HasFlag(SpellInterruptFlags::Movement)) && !m_caster->ToPlayer()->HasAuraTypeWithAffectMask(SPELL_AURA_CAST_WHILE_WALKING, m_spellInfo)) + 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)) { // 1. Has casttime, 2. Or doesn't have flag to allow movement during channel if (m_casttime || !m_spellInfo->IsMoveAllowedChannel()) @@ -3843,9 +3843,9 @@ 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->ToPlayer()->isMoving() && (m_spellInfo->InterruptFlags.HasFlag(SpellInterruptFlags::Movement)) && - (!m_spellInfo->HasEffect(SPELL_EFFECT_STUCK) || !m_caster->ToPlayer()->HasUnitMovementFlag(MOVEMENTFLAG_FALLING_FAR)) && - !m_caster->ToPlayer()->HasAuraTypeWithAffectMask(SPELL_AURA_CAST_WHILE_WALKING, m_spellInfo)) + 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)) { // don't cancel for melee, autorepeat, triggered and instant spells if (!m_spellInfo->IsNextMeleeSwingSpell() && !IsAutoRepeat() && !IsTriggered() && !(IsChannelActive() && m_spellInfo->IsMoveAllowedChannel())) @@ -3853,7 +3853,7 @@ void Spell::update(uint32 difftime) // 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->ToPlayer()->GetCharmerGUID().IsCreature()) + if (!m_caster->ToUnit()->GetCharmerGUID().IsCreature()) cancel(); } } @@ -5268,7 +5268,9 @@ SpellCastResult Spell::CheckCast(bool strict, int32* param1 /*= nullptr*/, int32 // 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->HasAuraTypeWithAffectMask(SPELL_AURA_CAST_WHILE_WALKING, m_spellInfo)) + 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)) && |
