fix(anim): Phase L.1c match MoveTo run speed

Retail MovementManager::PerformMovement (0x00524440) reads MoveTo speed and runRate from the packet, MovementParameters::UnPackNet (0x0052AC50) defines the layout, and CMotionInterp::apply_run_to_command (0x00527BE0) multiplies RunForward by runRate. Parse those fields for UpdateMotion/CreateObject, seed server-controlled MoveTo locomotion with the retail speed multiplier, and avoid overriding active monster MoveTo with sparse UpdatePosition-derived velocity.
This commit is contained in:
Erik 2026-04-28 20:58:22 +02:00
parent 4dd8d4b46e
commit 9812965183
6 changed files with 246 additions and 26 deletions

View file

@ -34,9 +34,21 @@ public static class ServerControlledLocomotion
// Retail MoveToManager::BeginMoveForward -> MovementParameters::get_command
// (0x0052AA00) seeds forward motion before the next position update.
public static LocomotionCycle PlanMoveToStart()
public static LocomotionCycle PlanMoveToStart(
float moveToSpeed = 1f,
float runRate = 1f,
bool canRun = true)
{
return new LocomotionCycle(MotionCommand.RunForward, 1f, true);
moveToSpeed = SanitizePositive(moveToSpeed);
runRate = SanitizePositive(runRate);
if (!canRun)
return new LocomotionCycle(MotionCommand.WalkForward, moveToSpeed, true);
return new LocomotionCycle(
MotionCommand.RunForward,
moveToSpeed * runRate,
true);
}
public static LocomotionCycle PlanFromVelocity(Vector3 worldVelocity)
@ -67,4 +79,9 @@ public static class ServerControlledLocomotion
uint Motion,
float SpeedMod,
bool IsMoving);
private static float SanitizePositive(float value)
{
return float.IsFinite(value) && value > 0f ? value : 1f;
}
}