mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-16 07:30:42 +01:00
Core/Spells: Prevent creatures from being able to cast all their spells while moving
Closes #26137
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user