fix(physics): movement-parity fixes - adjusted catch-up cap, autorun retail semantics, AP-30 retired

Ports CMotionInterp::get_adjusted_max_speed (0x00527D00, byte-decoded:
bare rate unless RunForward; forward_speed x 4.0 when running;
current_speed_factor proven a ctor-constant 1.0 at 0x00528C34) and swaps
all five interpolation catch-up call sites to it - retail's
fUseAdjustedSpeed_ static (.data 0x0081F418 = 1) makes this the live
branch, so standing/walking remotes now catch up at ~2x runRate instead
of 4x too fast (the #41/#165 presentation family). Autorun now hard-
forces Run for its duration and cancels on every fresh forward press
(CommandInterpreter::HandleNewForwardMovement 0x006b3d60 is literally
SetAutoRun(0,1)); the old test pin codified the divergence. AP-30
retired: retail Frame::is_equal genuinely uses the 0.0002 epsilon - the
row recorded a non-divergence. Three catch-up test pins re-baselined to
retail semantics with citations. Full Release suite 9,983/0.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-07-30 15:04:17 +02:00
parent 2123b44e8c
commit c0afcacbb2
10 changed files with 174 additions and 32 deletions

View file

@ -300,9 +300,14 @@ public sealed class RemotePhysicsUpdaterTests
ownerClockEpoch: binding.Record.ObjectClockEpoch);
// InterpolationManager::adjust_offset clamps the 1 m correction to
// maxSpeed (8 m/s) * 0.1 s = 0.8 m and replaces the authored 10 m
// root origin rather than adding to it.
Assert.InRange(motion.Body.Position.X, 10.79f, 10.81f);
// 2 x GetAdjustedMaxSpeed x 0.1 s. Movement parity audit 2026-07-30:
// retail's cap uses get_adjusted_max_speed (fUseAdjustedSpeed_ = 1,
// .data 0x0081F418) — for this fixture's Ready interpreted state that
// is the BARE rate (1.0), so 2 m/s x 0.1 s = 0.2 m, and the clamped
// correction replaces the authored 10 m root origin rather than
// adding to it. (The former 10.8 pin encoded the old unconditional
// GetMaxSpeed cap — 4x retail for a non-running remote.)
Assert.InRange(motion.Body.Position.X, 10.19f, 10.21f);
Assert.InRange(
MathF.Abs(Quaternion.Dot(
Quaternion.Normalize(target),