aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2024-05-18 11:50:00 +0200
committerShauren <shauren.trinity@gmail.com>2024-05-18 11:50:00 +0200
commitf80f931e2bee9dbf08c3edee94d0c79dbbb64072 (patch)
treee83b6b14abb48a34a9baa85139e549e77af25897
parent2ad7c7829b17bb9e6e951632e8e0e68f68b9aa44 (diff)
Core/Spells: Prevent creatures from being able to cast all their spells while moving
Closes #26137
-rw-r--r--src/server/game/Movement/MovementDefines.h15
-rw-r--r--src/server/game/Spells/Spell.cpp47
-rw-r--r--src/server/game/Spells/SpellEffects.cpp4
3 files changed, 38 insertions, 28 deletions
diff --git a/src/server/game/Movement/MovementDefines.h b/src/server/game/Movement/MovementDefines.h
index c00cb7a7b88..e2b2dc16e5d 100644
--- a/src/server/game/Movement/MovementDefines.h
+++ b/src/server/game/Movement/MovementDefines.h
@@ -49,6 +49,21 @@ enum MovementGeneratorType : uint8
MAX_MOTION_TYPE // SKIP
};
+constexpr bool CanStopMovementForSpellCasting(MovementGeneratorType type)
+{
+ // MovementGenerators that don't check Unit::IsMovementPreventedByCasting
+ switch (type)
+ {
+ case HOME_MOTION_TYPE:
+ case FLIGHT_MOTION_TYPE:
+ case EFFECT_MOTION_TYPE: // knockbacks, jumps, falling, land/takeoff transitions
+ return false;
+ default:
+ break;
+ }
+ return true;
+}
+
enum MovementGeneratorMode : uint8
{
MOTION_MODE_DEFAULT = 0,
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index 53d14d7ea69..cacc14b1f49 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -43,6 +43,7 @@
#include "Log.h"
#include "Loot.h"
#include "LootMgr.h"
+#include "MotionMaster.h"
#include "ObjectAccessor.h"
#include "ObjectMgr.h"
#include "PathGenerator.h"
@@ -3528,16 +3529,9 @@ SpellCastResult Spell::prepare(SpellCastTargets const& targets, AuraEffect const
m_casttime = CallScriptCalcCastTimeHandlers(m_spellInfo->CalcCastTime(this));
+ SpellCastResult movementResult = SPELL_CAST_OK;
if (m_caster->IsUnit() && m_caster->ToUnit()->isMoving())
- {
- result = CheckMovement();
- if (result != SPELL_CAST_OK)
- {
- SendCastResult(result);
- finish(result);
- return result;
- }
- }
+ movementResult = CheckMovement();
// Creatures focus their target when possible
if (m_casttime && m_caster->IsCreature() && !m_spellInfo->IsNextMeleeSwingSpell() && !IsAutoRepeat() && !m_caster->ToUnit()->HasUnitFlag(UNIT_FLAG_POSSESSED))
@@ -3550,6 +3544,24 @@ SpellCastResult Spell::prepare(SpellCastTargets const& targets, AuraEffect const
m_caster->ToCreature()->SetSpellFocus(this, nullptr);
}
+ if (movementResult != SPELL_CAST_OK)
+ {
+ if (m_caster->ToUnit()->IsControlledByPlayer() || !CanStopMovementForSpellCasting(m_caster->ToUnit()->GetMotionMaster()->GetCurrentMovementGeneratorType()))
+ {
+ SendCastResult(movementResult);
+ finish(movementResult);
+ return movementResult;
+ }
+ else
+ {
+ // Creatures (not controlled) give priority to spell casting over movement.
+ // We assume that the casting is always valid and the current movement
+ // is stopped immediately (because spells are updated before movement, so next Unit::Update would cancel the spell before stopping movement)
+ // and future attempts are stopped by by Unit::IsMovementPreventedByCasting in movement generators to prevent casting interruption.
+ m_caster->ToUnit()->StopMoving();
+ }
+ }
+
CallScriptOnPrecastHandler();
// set timer base at cast time
@@ -4278,16 +4290,9 @@ void Spell::update(uint32 difftime)
return;
}
- // check if the player caster has moved before the spell finished
- // with the exception of spells affected with SPELL_AURA_CAST_WHILE_WALKING effect
+ // check if the unit caster has moved before the spell finished
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
- // however, checking what type of movement the spline is for every single spline would be really expensive
- if (!m_caster->ToUnit()->GetCharmerGUID().IsCreature())
- cancel();
- }
+ cancel();
switch (m_spellState)
{
@@ -7238,12 +7243,6 @@ 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->CanCastSpellWhileMoving(m_spellInfo))
diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp
index 28a0ead95f3..1ca54fc6b76 100644
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -3917,10 +3917,6 @@ void Spell::EffectKnockBack()
if (unitTarget->HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED))
return;
- // Instantly interrupt non melee spells being cast
- if (unitTarget->IsNonMeleeSpellCast(true))
- unitTarget->InterruptNonMeleeSpells(true);
-
float ratio = 0.1f;
float speedxy = float(effectInfo->MiscValue) * ratio;
float speedz = float(damage) * ratio;