mirror of
https://github.com/liyunfan1223/azerothcore-wotlk.git
synced 2026-08-08 07:48:02 +00:00
fix(Core/Movement): creatures should not cast while moving (#9141)
- Closes #8843
This commit is contained in:
@@ -359,7 +359,7 @@ public:
|
|||||||
void SetTarget(ObjectGuid guid = ObjectGuid::Empty) override;
|
void SetTarget(ObjectGuid guid = ObjectGuid::Empty) override;
|
||||||
void FocusTarget(Spell const* focusSpell, WorldObject const* target);
|
void FocusTarget(Spell const* focusSpell, WorldObject const* target);
|
||||||
void ReleaseFocus(Spell const* focusSpell);
|
void ReleaseFocus(Spell const* focusSpell);
|
||||||
bool IsMovementPreventedByCasting() const;
|
bool IsMovementPreventedByCasting() const override;
|
||||||
|
|
||||||
// Part of Evade mechanics
|
// Part of Evade mechanics
|
||||||
[[nodiscard]] time_t GetLastDamagedTime() const;
|
[[nodiscard]] time_t GetLastDamagedTime() const;
|
||||||
|
|||||||
@@ -3683,6 +3683,30 @@ int32 Unit::GetCurrentSpellCastTime(uint32 spell_id) const
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Unit::IsMovementPreventedByCasting() const
|
||||||
|
{
|
||||||
|
// can always move when not casting
|
||||||
|
if (!HasUnitState(UNIT_STATE_CASTING))
|
||||||
|
{
|
||||||
|
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())
|
||||||
|
{
|
||||||
|
if (spell->GetSpellInfo()->IsMoveAllowedChannel())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// prohibit movement for all other spell casts
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool Unit::CanMoveDuringChannel() const
|
bool Unit::CanMoveDuringChannel() const
|
||||||
{
|
{
|
||||||
if (Spell* spell = m_currentSpells[CURRENT_CHANNELED_SPELL])
|
if (Spell* spell = m_currentSpells[CURRENT_CHANNELED_SPELL])
|
||||||
|
|||||||
@@ -2145,6 +2145,8 @@ public:
|
|||||||
[[nodiscard]] Spell* FindCurrentSpellBySpellId(uint32 spell_id) const;
|
[[nodiscard]] Spell* FindCurrentSpellBySpellId(uint32 spell_id) const;
|
||||||
[[nodiscard]] int32 GetCurrentSpellCastTime(uint32 spell_id) const;
|
[[nodiscard]] int32 GetCurrentSpellCastTime(uint32 spell_id) const;
|
||||||
|
|
||||||
|
virtual bool IsMovementPreventedByCasting() const;
|
||||||
|
|
||||||
ObjectGuid m_SummonSlot[MAX_SUMMON_SLOT];
|
ObjectGuid m_SummonSlot[MAX_SUMMON_SLOT];
|
||||||
ObjectGuid m_ObjectSlot[MAX_GAMEOBJECT_SLOT];
|
ObjectGuid m_ObjectSlot[MAX_GAMEOBJECT_SLOT];
|
||||||
|
|
||||||
|
|||||||
@@ -121,8 +121,11 @@ void ConfusedMovementGenerator<T>::DoReset(T* unit)
|
|||||||
template<class T>
|
template<class T>
|
||||||
bool ConfusedMovementGenerator<T>::DoUpdate(T* unit, uint32 diff)
|
bool ConfusedMovementGenerator<T>::DoUpdate(T* unit, uint32 diff)
|
||||||
{
|
{
|
||||||
if (unit->HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED | UNIT_STATE_DISTRACTED))
|
if (unit->HasUnitState(UNIT_STATE_NOT_MOVE) || unit->IsMovementPreventedByCasting())
|
||||||
|
{
|
||||||
|
unit->StopMoving();
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (i_nextMoveTime.Passed())
|
if (i_nextMoveTime.Passed())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -50,9 +50,9 @@ bool EscortMovementGenerator<T>::DoUpdate(T* unit, uint32 /*diff*/)
|
|||||||
if (!unit)
|
if (!unit)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (unit->HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED))
|
if (unit->HasUnitState(UNIT_STATE_NOT_MOVE) || unit->IsMovementPreventedByCasting())
|
||||||
{
|
{
|
||||||
unit->ClearUnitState(UNIT_STATE_ROAMING_MOVE);
|
unit->StopMoving();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,8 +33,10 @@ void FleeingMovementGenerator<T>::_setTargetLocation(T* owner)
|
|||||||
if (!owner)
|
if (!owner)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (owner->HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED))
|
if (owner->HasUnitState(UNIT_STATE_NOT_MOVE) || owner->IsMovementPreventedByCasting())
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!_setMoveData(owner))
|
if (!_setMoveData(owner))
|
||||||
return;
|
return;
|
||||||
@@ -346,9 +348,9 @@ bool FleeingMovementGenerator<T>::DoUpdate(T* owner, uint32 time_diff)
|
|||||||
if (!owner || !owner->IsAlive())
|
if (!owner || !owner->IsAlive())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (owner->HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED))
|
if (owner->HasUnitState(UNIT_STATE_NOT_MOVE) || owner->IsMovementPreventedByCasting())
|
||||||
{
|
{
|
||||||
owner->ClearUnitState(UNIT_STATE_FLEEING_MOVE);
|
owner->StopMoving();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -385,9 +387,9 @@ bool TimedFleeingMovementGenerator::Update(Unit* owner, uint32 time_diff)
|
|||||||
if (!owner->IsAlive())
|
if (!owner->IsAlive())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (owner->HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED))
|
if (owner->HasUnitState(UNIT_STATE_NOT_MOVE) || owner->IsMovementPreventedByCasting())
|
||||||
{
|
{
|
||||||
owner->ClearUnitState(UNIT_STATE_FLEEING_MOVE);
|
owner->StopMoving();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
template<class T>
|
template<class T>
|
||||||
void PointMovementGenerator<T>::DoInitialize(T* unit)
|
void PointMovementGenerator<T>::DoInitialize(T* unit)
|
||||||
{
|
{
|
||||||
if (unit->HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED))
|
if (unit->HasUnitState(UNIT_STATE_NOT_MOVE) || unit->IsMovementPreventedByCasting())
|
||||||
{
|
{
|
||||||
// the next line is to ensure that a new spline is created in DoUpdate() once the unit is no longer rooted/stunned
|
// the next line is to ensure that a new spline is created in DoUpdate() once the unit is no longer rooted/stunned
|
||||||
// todo: rename this flag to something more appropriate since it is set to true even without speed change now.
|
// todo: rename this flag to something more appropriate since it is set to true even without speed change now.
|
||||||
@@ -98,9 +98,9 @@ bool PointMovementGenerator<T>::DoUpdate(T* unit, uint32 /*diff*/)
|
|||||||
if (!unit)
|
if (!unit)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (unit->HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED))
|
if (unit->HasUnitState(UNIT_STATE_NOT_MOVE) || unit->IsMovementPreventedByCasting())
|
||||||
{
|
{
|
||||||
unit->ClearUnitState(UNIT_STATE_ROAMING_MOVE);
|
unit->StopMoving();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -260,10 +260,10 @@ void RandomMovementGenerator<Creature>::DoFinalize(Creature* creature)
|
|||||||
template<>
|
template<>
|
||||||
bool RandomMovementGenerator<Creature>::DoUpdate(Creature* creature, const uint32 diff)
|
bool RandomMovementGenerator<Creature>::DoUpdate(Creature* creature, const uint32 diff)
|
||||||
{
|
{
|
||||||
if (creature->HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED | UNIT_STATE_DISTRACTED))
|
if (creature->HasUnitState(UNIT_STATE_NOT_MOVE) || creature->IsMovementPreventedByCasting())
|
||||||
{
|
{
|
||||||
_nextMoveTime.Reset(0); // Expire the timer
|
_nextMoveTime.Reset(0); // Expire the timer
|
||||||
creature->ClearUnitState(UNIT_STATE_ROAMING_MOVE);
|
creature->StopMoving();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -275,23 +275,6 @@ bool RandomMovementGenerator<Creature>::DoUpdate(Creature* creature, const uint3
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// prevent movement while casting spells with cast time or channel time
|
|
||||||
if (creature->HasUnitState(UNIT_STATE_CASTING))
|
|
||||||
{
|
|
||||||
bool stop = true;
|
|
||||||
if (Spell* spell = creature->GetCurrentSpell(CURRENT_CHANNELED_SPELL))
|
|
||||||
if (!(spell->GetSpellInfo()->ChannelInterruptFlags & (AURA_INTERRUPT_FLAG_MOVE | AURA_INTERRUPT_FLAG_TURNING)) && !(spell->GetSpellInfo()->InterruptFlags & SPELL_INTERRUPT_FLAG_MOVEMENT))
|
|
||||||
stop = false;
|
|
||||||
|
|
||||||
if (stop)
|
|
||||||
{
|
|
||||||
if (!creature->IsStopped())
|
|
||||||
creature->StopMoving();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (creature->movespline->Finalized())
|
if (creature->movespline->Finalized())
|
||||||
{
|
{
|
||||||
_nextMoveTime.Update(diff);
|
_nextMoveTime.Update(diff);
|
||||||
|
|||||||
@@ -145,8 +145,10 @@ bool WaypointMovementGenerator<Creature>::StartMove(Creature* creature)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// xinef: do not initialize motion if we got stunned in movementinform
|
// xinef: do not initialize motion if we got stunned in movementinform
|
||||||
if (creature->HasUnitState(UNIT_STATE_NOT_MOVE))
|
if (creature->HasUnitState(UNIT_STATE_NOT_MOVE) || creature->IsMovementPreventedByCasting())
|
||||||
|
{
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
WaypointData const* node = i_path->at(i_currentNode);
|
WaypointData const* node = i_path->at(i_currentNode);
|
||||||
|
|
||||||
@@ -204,11 +206,13 @@ bool WaypointMovementGenerator<Creature>::DoUpdate(Creature* creature, uint32 di
|
|||||||
{
|
{
|
||||||
// Waypoint movement can be switched on/off
|
// Waypoint movement can be switched on/off
|
||||||
// This is quite handy for escort quests and other stuff
|
// This is quite handy for escort quests and other stuff
|
||||||
if (creature->HasUnitState(UNIT_STATE_NOT_MOVE))
|
if (creature->HasUnitState(UNIT_STATE_NOT_MOVE) || creature->IsMovementPreventedByCasting())
|
||||||
{
|
{
|
||||||
creature->ClearUnitState(UNIT_STATE_ROAMING_MOVE);
|
creature->StopMoving();
|
||||||
|
Stop(1000);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// prevent a crash at empty waypoint path.
|
// prevent a crash at empty waypoint path.
|
||||||
if (!i_path || i_path->empty())
|
if (!i_path || i_path->empty())
|
||||||
return false;
|
return false;
|
||||||
@@ -217,23 +221,6 @@ bool WaypointMovementGenerator<Creature>::DoUpdate(Creature* creature, uint32 di
|
|||||||
if (!creature->IsAlive())
|
if (!creature->IsAlive())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// prevent movement while casting spells with cast time or channel time
|
|
||||||
if (creature->HasUnitState(UNIT_STATE_CASTING))
|
|
||||||
{
|
|
||||||
bool stop = true;
|
|
||||||
if (Spell* spell = creature->GetCurrentSpell(CURRENT_CHANNELED_SPELL))
|
|
||||||
if (!(spell->GetSpellInfo()->ChannelInterruptFlags & (AURA_INTERRUPT_FLAG_MOVE | AURA_INTERRUPT_FLAG_TURNING)) && !(spell->GetSpellInfo()->InterruptFlags & SPELL_INTERRUPT_FLAG_MOVEMENT))
|
|
||||||
stop = false;
|
|
||||||
|
|
||||||
if (stop)
|
|
||||||
{
|
|
||||||
Stop(1000);
|
|
||||||
if (!creature->IsStopped())
|
|
||||||
creature->StopMoving();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Stopped())
|
if (Stopped())
|
||||||
{
|
{
|
||||||
if (CanMove(diff))
|
if (CanMove(diff))
|
||||||
|
|||||||
@@ -1243,7 +1243,7 @@ bool SpellInfo::IsChanneled() const
|
|||||||
|
|
||||||
bool SpellInfo::IsMoveAllowedChannel() const
|
bool SpellInfo::IsMoveAllowedChannel() const
|
||||||
{
|
{
|
||||||
return IsChanneled() && (HasAttribute(SPELL_ATTR5_ALLOW_ACTION_DURING_CHANNEL) || (!(ChannelInterruptFlags & (AURA_INTERRUPT_FLAG_MOVE | AURA_INTERRUPT_FLAG_TURNING))));
|
return IsChanneled() && HasAttribute(SPELL_ATTR5_ALLOW_ACTION_DURING_CHANNEL);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SpellInfo::NeedsComboPoints() const
|
bool SpellInfo::NeedsComboPoints() const
|
||||||
|
|||||||
Reference in New Issue
Block a user