InterpretedMotionState + the unified RawMotionState (LegacyRawMotionState
folded away) gain retail's action FIFO + ApplyMotion/RemoveMotion, ported
verbatim from the raw named decomp (0x0051e790/0x0051eb60 region, pc
293252-293703) including two genuine retail quirks pinned by tests and
independently re-verified against the raw text before commit:
- RawMotionState::ApplyMotion's RunForward (0x44000007) dead branch — a
cycle-class apply of literal RunForward writes NOTHING (retail encodes
run as WalkForward + HoldKey_Run on the raw state; same family as the
D6 apply_run_to_command early-return).
- InterpretedMotionState::RemoveMotion's exact-match-only TurnRight/
SideStepRight handling (left variants fall through to the style/
forward branches).
MovementParameters verbatim (A4 pin): 18 named flags per the absolute
mask table, ctor = 0x1EE0F expansion + distance_to_object 0.6 /
fail_distance FLT_MAX / speed 1 / walk_run_threshhold 15 / hold_key
Invalid — with the two ACE-divergence traps ported RETAIL-side
(can_charge FALSE where ACE defaults true; threshold 15.0 not 1.0).
MotionNode {ContextId, Motion, JumpErrorCode} (acclient.h:53293) — the
pending_motions node W2 consumes.
WeenieError renumbered to retail's numeric semantics (A10 table):
NotGrounded=0x24, GeneralMovementFailure 0x24→0x47, new 0x3f/0x40/0x41
combat-stance rejects + 0x42 chat-emote + 0x45 action-depth; the
airborne jump/action returns corrected 0x48→0x24 per the A10 sweep
(incl. jump_is_allowed's null-physics-obj 0x24-not-8 divergence from
ACE). Codes are local-only — wire untouched.
Outbound packer proof: RawMotionStatePacker unmodified; all 6
golden-byte RawMotionStatePackTests pass unmodified. TS-24 register row
updated (capability landed; outbound wiring still open).
Implemented by a dedicated agent against the W0-pinned spec; quirks,
scope, and suite independently verified. Full suite green: 3,531
(374+425+713+2015+4 pre-existing skips).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
33 lines
913 B
C#
33 lines
913 B
C#
using AcDream.Core.Physics.Motion;
|
|
using Xunit;
|
|
|
|
namespace AcDream.Core.Tests.Physics.Motion;
|
|
|
|
/// <summary>
|
|
/// R3-W1 — <c>CMotionInterp::MotionNode</c> shape pin. Oracle:
|
|
/// acclient.h:53293 (struct #5857). W2 consumes this as the
|
|
/// <c>pending_motions</c> element type; W1 only ports the shape.
|
|
/// </summary>
|
|
public sealed class MotionNodeTests
|
|
{
|
|
[Fact]
|
|
public void Ctor_StoresAllThreeFields()
|
|
{
|
|
var node = new MotionNode(ContextId: 7u, Motion: 0x41000003u, JumpErrorCode: 0x48u);
|
|
|
|
Assert.Equal(7u, node.ContextId);
|
|
Assert.Equal(0x41000003u, node.Motion);
|
|
Assert.Equal(0x48u, node.JumpErrorCode);
|
|
}
|
|
|
|
[Fact]
|
|
public void Equality_IsValueBased()
|
|
{
|
|
var a = new MotionNode(1u, 2u, 3u);
|
|
var b = new MotionNode(1u, 2u, 3u);
|
|
var c = new MotionNode(1u, 2u, 4u);
|
|
|
|
Assert.Equal(a, b);
|
|
Assert.NotEqual(a, c);
|
|
}
|
|
}
|