fix(Core/Movement): followers match their target's motion speed (#25085)

Co-authored-by: killerwife <killerwife@gmail.com>
This commit is contained in:
sogladev 2026-03-16 13:11:24 +01:00 committed by GitHub
parent e8d98dfc34
commit 17ecef7a07
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 52 additions and 36 deletions

View file

@ -995,6 +995,30 @@ std::string Object::GetDebugInfo() const
return sstr.str();
}
UnitMoveType MovementInfo::GetSpeedType(uint32 moveFlags)
{
if (moveFlags & MOVEMENTFLAG_FLYING)
{
if (moveFlags & MOVEMENTFLAG_BACKWARD)
return MOVE_FLIGHT_BACK;
return MOVE_FLIGHT;
}
else if (moveFlags & MOVEMENTFLAG_SWIMMING)
{
if (moveFlags & MOVEMENTFLAG_BACKWARD)
return MOVE_SWIM_BACK;
return MOVE_SWIM;
}
else if (moveFlags & MOVEMENTFLAG_WALKING)
return MOVE_WALK;
else if (moveFlags & MOVEMENTFLAG_BACKWARD)
return MOVE_RUN_BACK;
return MOVE_RUN;
}
void MovementInfo::OutDebug()
{
LOG_INFO("movement", "MOVEMENT INFO");

View file

@ -31,6 +31,7 @@
#include "ObjectGuid.h"
#include "Optional.h"
#include "Position.h"
#include "UnitDefines.h"
#include "UpdateData.h"
#include "UpdateMask.h"
#include "ObjectVisibilityContainer.h"
@ -344,6 +345,9 @@ struct MovementInfo
void RemoveMovementFlag(uint32 flag) { flags &= ~flag; }
[[nodiscard]] bool HasMovementFlag(uint32 flag) const { return flags & flag; }
[[nodiscard]] UnitMoveType GetSpeedType() const { return GetSpeedType(flags); }
[[nodiscard]] static UnitMoveType GetSpeedType(uint32 moveFlags);
[[nodiscard]] uint16 GetExtraMovementFlags() const { return flags2; }
void AddExtraMovementFlag(uint16 flag) { flags2 |= flag; }
[[nodiscard]] bool HasExtraMovementFlag(uint16 flag) const { return flags2 & flag; }

View file

@ -15,6 +15,9 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ACORE_UNITDEFINES_H
#define ACORE_UNITDEFINES_H
#include "Define.h"
#include "EnumFlag.h"
@ -487,3 +490,5 @@ enum SplineType
SPLINETYPE_FACING_TARGET = 3,
SPLINETYPE_FACING_ANGLE = 4
};
#endif // ACORE_UNITDEFINES_H

View file

@ -430,20 +430,27 @@ void ChaseMovementGenerator<T>::MovementInform(T* owner)
//-----------------------------------------------//
static float GetTargetSpeedInMotion(Unit* target)
{
if (!target->movespline->Finalized())
return target->movespline->Velocity();
return target->GetSpeed(target->m_movementInfo.GetSpeedType());
}
static Optional<float> GetVelocity(Unit* owner, Unit* target, G3D::Vector3 const& dest, bool playerPet)
{
Optional<float> speed = {};
if (!owner->IsInCombat() && !owner->IsVehicle() && !owner->HasUnitFlag(UNIT_FLAG_POSSESSED) &&
(owner->IsPet() || owner->IsGuardian() || owner->GetGUID() == target->GetCritterGUID() || owner->GetCharmerOrOwnerGUID() == target->GetGUID()))
{
uint32 moveFlags = target->GetUnitMovementFlags();
if (target->IsWalking())
{
moveFlags |= MOVEMENTFLAG_WALKING;
}
if (owner->IsInCombat() || owner->IsVehicle() || owner->HasUnitFlag(UNIT_FLAG_POSSESSED))
return speed;
bool isPetLike = owner->IsPet() || owner->IsGuardian() || owner->GetGUID() == target->GetCritterGUID() || owner->GetCharmerOrOwnerGUID() == target->GetGUID();
// For pets/guardians/critters or creature-to-creature follow: sync with target's speed
if (isPetLike || (owner->IsCreature() && target->IsCreature()))
{
speed = GetTargetSpeedInMotion(target);
UnitMoveType moveType = Movement::SelectSpeedType(moveFlags);
speed = target->GetSpeed(moveType);
if (playerPet)
{
float distance = owner->GetDistance2d(dest.x, dest.y) - target->GetObjectSize() - (*speed / 2.f);
@ -462,7 +469,7 @@ static Position const PredictPosition(Unit* target)
{
Position pos = target->GetPosition();
// 0.5 - it's time (0.5 sec) between starting movement opcode (e.g. MSG_MOVE_START_FORWARD) and MSG_MOVE_HEARTBEAT sent by client
float speed = target->GetSpeed(Movement::SelectSpeedType(target->GetUnitMovementFlags())) * 0.5f;
float speed = target->GetSpeed(target->m_movementInfo.GetSpeedType()) * 0.5f;
float orientation = target->GetOrientation();
if (target->m_movementInfo.HasMovementFlag(MOVEMENTFLAG_FORWARD))

View file

@ -29,31 +29,7 @@ namespace Movement
{
UnitMoveType SelectSpeedType(uint32 moveFlags)
{
if (moveFlags & MOVEMENTFLAG_FLYING)
{
if (moveFlags & MOVEMENTFLAG_BACKWARD /*&& speed_obj.flight >= speed_obj.flight_back*/)
return MOVE_FLIGHT_BACK;
else
return MOVE_FLIGHT;
}
else if (moveFlags & MOVEMENTFLAG_SWIMMING)
{
if (moveFlags & MOVEMENTFLAG_BACKWARD /*&& speed_obj.swim >= speed_obj.swim_back*/)
return MOVE_SWIM_BACK;
else
return MOVE_SWIM;
}
else if (moveFlags & MOVEMENTFLAG_WALKING)
{
//if (speed_obj.run > speed_obj.walk)
return MOVE_WALK;
}
else if (moveFlags & MOVEMENTFLAG_BACKWARD /*&& speed_obj.run >= speed_obj.run_back*/)
return MOVE_RUN_BACK;
// Flying creatures use MOVEMENTFLAG_CAN_FLY or MOVEMENTFLAG_DISABLE_GRAVITY
// Run speed is their default flight speed.
return MOVE_RUN;
return MovementInfo::GetSpeedType(moveFlags);
}
int32 MoveSplineInit::Launch()