aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp23
-rw-r--r--src/server/game/Entities/Unit/Unit.h1
-rw-r--r--src/server/game/Spells/Auras/SpellAuraDefines.h4
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.cpp6
-rw-r--r--src/server/game/Spells/Spell.cpp16
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)) &&