Every remote's server-directed movement now runs the verbatim retail MoveToManager. EnsureRemoteMotionBindings constructs it per remote with the full V2 seam set (position/heading/velocity providers, the P4 TargetTracker adapter via setTarget/clearTarget storing the tracked guid on RemoteMotion) and binds InterruptCurrentMovement -> CancelMoveTo(0x36) - the retail interrupt chain (TS-36 remote side). UM routing is retail's unpack_movement dispatch (0x00524440): the head-interrupt + unstick fire for EVERY movement type, then mt 6/7 build MovementParameters.FromWire(raw bitfield - now surfaced by the parser) + a MovementStruct (mt 6 resolves the target guid against the entity table, degrading to MoveToPosition at the wire origin per the plan's 2f; my_run_rate written from MoveToRunRate per @300603) -> MoveTo.PerformMovement; mt 8/9 likewise via FromWireTurnTo; ONLY mt 0 flows through the interpreted funnel (the PlanMoveToStart seed is DELETED - retail never routes MoveTo types through the interpreted state copy). Per tick: the P4 tracker feeds HandleUpdateTarget(Ok/ExitWorld) from the live entity table, then UseTime runs the manager's steering/ arrival/fail handlers, then apply_current_movement recomputes velocity - the same shape ordinary locomotion uses. The legacy driver branches, the stale-destination timer, and the ClampApproachVelocity band-aid are gone; arrival now uses retail cylinder distance (watch melee-range stop distance in the visual pass). DELETED: RemoteMoveToDriver.cs + its tests (OriginToWorld relocated verbatim to MoveToMath; the B.6 auto-walk's two surviving constants inlined into PlayerMovementController, dying with it in V5); ServerControlledLocomotion.PlanMoveToStart + tests (PlanFromVelocity survives - new AP-80 row); the RemoteMotion MoveTo capture fields. Registers: AD-8/AD-9/AP-8/AP-9 retired; AP-79 (TargetTracker adapter, retire R5) + AP-80 added. Full suite green: 3,948 passed. Live smoke launched - NPC chase/wander behavior pending user verification (recorded in the session handoff). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
55 lines
1.6 KiB
C#
55 lines
1.6 KiB
C#
using System.Numerics;
|
|
using AcDream.Core.Physics;
|
|
using Xunit;
|
|
|
|
namespace AcDream.Core.Tests.Physics;
|
|
|
|
public sealed class ServerControlledLocomotionTests
|
|
{
|
|
|
|
|
|
|
|
[Fact]
|
|
public void PlanFromVelocity_StopsBelowRetailNoiseThreshold()
|
|
{
|
|
var plan = ServerControlledLocomotion.PlanFromVelocity(
|
|
new Vector3(0.10f, 0.12f, 3.0f));
|
|
|
|
Assert.False(plan.IsMoving);
|
|
Assert.Equal(MotionCommand.Ready, plan.Motion);
|
|
Assert.Equal(1.0f, plan.SpeedMod);
|
|
}
|
|
|
|
[Fact]
|
|
public void PlanFromVelocity_WalksForSlowServerControlledMotion()
|
|
{
|
|
var plan = ServerControlledLocomotion.PlanFromVelocity(
|
|
new Vector3(0.0f, 0.80f, 0.0f));
|
|
|
|
Assert.True(plan.IsMoving);
|
|
Assert.Equal(MotionCommand.WalkForward, plan.Motion);
|
|
Assert.InRange(plan.SpeedMod, 0.25f, 0.27f);
|
|
}
|
|
|
|
[Fact]
|
|
public void PlanFromVelocity_RunsAtRetailRunScale()
|
|
{
|
|
var plan = ServerControlledLocomotion.PlanFromVelocity(
|
|
new Vector3(0.0f, MotionInterpreter.RunAnimSpeed, 0.0f));
|
|
|
|
Assert.True(plan.IsMoving);
|
|
Assert.Equal(MotionCommand.RunForward, plan.Motion);
|
|
Assert.Equal(1.0f, plan.SpeedMod, precision: 4);
|
|
}
|
|
|
|
[Fact]
|
|
public void PlanFromVelocity_ClampsVeryFastSnapshots()
|
|
{
|
|
var plan = ServerControlledLocomotion.PlanFromVelocity(
|
|
new Vector3(0.0f, 30.0f, 0.0f));
|
|
|
|
Assert.True(plan.IsMoving);
|
|
Assert.Equal(MotionCommand.RunForward, plan.Motion);
|
|
Assert.Equal(ServerControlledLocomotion.MaxSpeedMod, plan.SpeedMod);
|
|
}
|
|
}
|