fix(Core/Movement): followers match their target's motion speed (#25085)
Co-authored-by: killerwife <killerwife@gmail.com>
This commit is contained in:
@@ -995,6 +995,30 @@ std::string Object::GetDebugInfo() const
|
|||||||
return sstr.str();
|
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()
|
void MovementInfo::OutDebug()
|
||||||
{
|
{
|
||||||
LOG_INFO("movement", "MOVEMENT INFO");
|
LOG_INFO("movement", "MOVEMENT INFO");
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
#include "ObjectGuid.h"
|
#include "ObjectGuid.h"
|
||||||
#include "Optional.h"
|
#include "Optional.h"
|
||||||
#include "Position.h"
|
#include "Position.h"
|
||||||
|
#include "UnitDefines.h"
|
||||||
#include "UpdateData.h"
|
#include "UpdateData.h"
|
||||||
#include "UpdateMask.h"
|
#include "UpdateMask.h"
|
||||||
#include "ObjectVisibilityContainer.h"
|
#include "ObjectVisibilityContainer.h"
|
||||||
@@ -344,6 +345,9 @@ struct MovementInfo
|
|||||||
void RemoveMovementFlag(uint32 flag) { flags &= ~flag; }
|
void RemoveMovementFlag(uint32 flag) { flags &= ~flag; }
|
||||||
[[nodiscard]] bool HasMovementFlag(uint32 flag) const { return 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; }
|
[[nodiscard]] uint16 GetExtraMovementFlags() const { return flags2; }
|
||||||
void AddExtraMovementFlag(uint16 flag) { flags2 |= flag; }
|
void AddExtraMovementFlag(uint16 flag) { flags2 |= flag; }
|
||||||
[[nodiscard]] bool HasExtraMovementFlag(uint16 flag) const { return flags2 & flag; }
|
[[nodiscard]] bool HasExtraMovementFlag(uint16 flag) const { return flags2 & flag; }
|
||||||
|
|||||||
@@ -15,6 +15,9 @@
|
|||||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef ACORE_UNITDEFINES_H
|
||||||
|
#define ACORE_UNITDEFINES_H
|
||||||
|
|
||||||
#include "Define.h"
|
#include "Define.h"
|
||||||
#include "EnumFlag.h"
|
#include "EnumFlag.h"
|
||||||
|
|
||||||
@@ -487,3 +490,5 @@ enum SplineType
|
|||||||
SPLINETYPE_FACING_TARGET = 3,
|
SPLINETYPE_FACING_TARGET = 3,
|
||||||
SPLINETYPE_FACING_ANGLE = 4
|
SPLINETYPE_FACING_ANGLE = 4
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif // ACORE_UNITDEFINES_H
|
||||||
|
|||||||
@@ -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)
|
static Optional<float> GetVelocity(Unit* owner, Unit* target, G3D::Vector3 const& dest, bool playerPet)
|
||||||
{
|
{
|
||||||
Optional<float> speed = {};
|
Optional<float> speed = {};
|
||||||
if (!owner->IsInCombat() && !owner->IsVehicle() && !owner->HasUnitFlag(UNIT_FLAG_POSSESSED) &&
|
if (owner->IsInCombat() || owner->IsVehicle() || owner->HasUnitFlag(UNIT_FLAG_POSSESSED))
|
||||||
(owner->IsPet() || owner->IsGuardian() || owner->GetGUID() == target->GetCritterGUID() || owner->GetCharmerOrOwnerGUID() == target->GetGUID()))
|
return speed;
|
||||||
{
|
|
||||||
uint32 moveFlags = target->GetUnitMovementFlags();
|
bool isPetLike = owner->IsPet() || owner->IsGuardian() || owner->GetGUID() == target->GetCritterGUID() || owner->GetCharmerOrOwnerGUID() == target->GetGUID();
|
||||||
if (target->IsWalking())
|
|
||||||
{
|
// For pets/guardians/critters or creature-to-creature follow: sync with target's speed
|
||||||
moveFlags |= MOVEMENTFLAG_WALKING;
|
if (isPetLike || (owner->IsCreature() && target->IsCreature()))
|
||||||
}
|
{
|
||||||
|
speed = GetTargetSpeedInMotion(target);
|
||||||
|
|
||||||
UnitMoveType moveType = Movement::SelectSpeedType(moveFlags);
|
|
||||||
speed = target->GetSpeed(moveType);
|
|
||||||
if (playerPet)
|
if (playerPet)
|
||||||
{
|
{
|
||||||
float distance = owner->GetDistance2d(dest.x, dest.y) - target->GetObjectSize() - (*speed / 2.f);
|
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();
|
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
|
// 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();
|
float orientation = target->GetOrientation();
|
||||||
|
|
||||||
if (target->m_movementInfo.HasMovementFlag(MOVEMENTFLAG_FORWARD))
|
if (target->m_movementInfo.HasMovementFlag(MOVEMENTFLAG_FORWARD))
|
||||||
|
|||||||
@@ -29,31 +29,7 @@ namespace Movement
|
|||||||
{
|
{
|
||||||
UnitMoveType SelectSpeedType(uint32 moveFlags)
|
UnitMoveType SelectSpeedType(uint32 moveFlags)
|
||||||
{
|
{
|
||||||
if (moveFlags & MOVEMENTFLAG_FLYING)
|
return MovementInfo::GetSpeedType(moveFlags);
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int32 MoveSplineInit::Launch()
|
int32 MoveSplineInit::Launch()
|
||||||
|
|||||||
Reference in New Issue
Block a user