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:
parent
2123b44e8c
commit
c0afcacbb2
10 changed files with 174 additions and 32 deletions
|
|
@ -666,6 +666,69 @@ public sealed class MotionInterpreterTests
|
|||
Assert.Equal(MotionInterpreter.RunAnimSpeed * 1.75f, speed, precision: 4);
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// GetAdjustedMaxSpeed (CMotionInterp::get_adjusted_max_speed @ 0x00527D00)
|
||||
// Movement parity audit 2026-07-30 — the accessor InterpolationManager's
|
||||
// catch-up cap actually uses (fUseAdjustedSpeed_ = 0x1, .data 0x0081F418).
|
||||
// Byte-decoded: NOT RunForward → bare rate; RunForward → forward_speed ×
|
||||
// RunAnimSpeed (current_speed_factor is a ctor-constant 1.0, 0x00528C34).
|
||||
// =========================================================================
|
||||
|
||||
[Theory]
|
||||
[InlineData(MotionCommand.WalkForward)]
|
||||
[InlineData(MotionCommand.WalkBackward)]
|
||||
[InlineData(MotionCommand.Ready)]
|
||||
public void GetAdjustedMaxSpeed_NotRunForward_ReturnsBareRunRate(uint command)
|
||||
{
|
||||
// The 4x-too-fast walking-remote catch-up fix: a non-RunForward mover's
|
||||
// adjusted max speed is the BARE rate — no RunAnimSpeed multiply
|
||||
// (0x00527d2a jnz falls straight to ret with rate in st0).
|
||||
var weenie = new FakeWeenie { RunRate = 2.94f };
|
||||
var interp = MakeInterp(weenie: weenie);
|
||||
interp.InterpretedState.ForwardCommand = command;
|
||||
|
||||
Assert.Equal(2.94f, interp.GetAdjustedMaxSpeed(), precision: 4);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetAdjustedMaxSpeed_RunForward_ReturnsForwardSpeedTimesRunAnimSpeed()
|
||||
{
|
||||
// RunForward DISCARDS the queried rate (fstp st0) and returns
|
||||
// forward_speed / current_speed_factor(=1.0) * 4.0.
|
||||
var weenie = new FakeWeenie { RunRate = 99f }; // must be ignored
|
||||
var interp = MakeInterp(weenie: weenie);
|
||||
interp.InterpretedState.ForwardCommand = MotionCommand.RunForward;
|
||||
interp.InterpretedState.ForwardSpeed = 2.5f;
|
||||
|
||||
Assert.Equal(
|
||||
2.5f * MotionInterpreter.RunAnimSpeed,
|
||||
interp.GetAdjustedMaxSpeed(),
|
||||
precision: 4); // 10.0 — NOT 99×4
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetAdjustedMaxSpeed_NoWeenie_FallsBackToLiteralOne()
|
||||
{
|
||||
// 0x00527d0b: no weenie → fld [0x007928b0] = 1.0 (NOT my_run_rate).
|
||||
var interp = MakeInterp(weenie: null);
|
||||
interp.MyRunRate = 3.5f;
|
||||
interp.InterpretedState.ForwardCommand = MotionCommand.WalkForward;
|
||||
|
||||
Assert.Equal(1.0f, interp.GetAdjustedMaxSpeed(), precision: 4);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetAdjustedMaxSpeed_InqRunRateFails_FallsBackToMyRunRate()
|
||||
{
|
||||
// 0x00527d1d-0x00527d23: InqRunRate false → fld [this+0x7c] my_run_rate.
|
||||
var weenie = new FakeWeenie { RunRate = 5f, InqRunRateResult = false };
|
||||
var interp = MakeInterp(weenie: weenie);
|
||||
interp.MyRunRate = 2.4f;
|
||||
interp.InterpretedState.ForwardCommand = MotionCommand.Ready;
|
||||
|
||||
Assert.Equal(2.4f, interp.GetAdjustedMaxSpeed(), precision: 4);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetMaxSpeed_NoWeenie_ReturnsLiteralOneTimesRunAnimSpeed()
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue