feat(R4-V2): MoveToManager verbatim - all 33 members + conformance harness (closes M1/M3/M4/M5/M6/M10/M14-core)
The retail server-directed-movement brain (0x00529010-0x0052a987), Core-only with every App dependency as a ctor/property seam for the V4/V5 cutovers: node-plan builders for all four movement types (TurnToObject's desired-heading clobber quirk VERBATIM; TurnToHeading's immediate BeginNextNode - ACE's one-tick-late gap not copied), PerformMovement (cancel 0x36 + unstick first), BeginNextNode with the sticky handoff order (radius/height/tlid read BEFORE CleanUp), BeginMoveForward (GetCommand walk/run cascade + stored-params write-back + progress-clock seed), HandleMoveToPosition (chase arrival dist <= distance_to_object per the adjudicated BN inversion; fail distance -> 0x3D; progress >= 0.25 units/s over >= 1 s, incremental AND overall; fail_progress_count write-only - retail has NO give-up threshold and none was invented), HandleTurnToHeading (20/340 aux deadband; the Ghidra-confirmed heading_diff mirror), HandleUpdateTarget 0x0052a7d0 (deferred-start: object moves wait for the first Ok callback; retargets reset the progress clock without requeueing), UseTime's initialized gate, InitializeLocalVariables per retail (flags word + context_id zeroed, floats stale, FLT_MAX resets - not ACE's transpositions). TDD catch: default(Quaternion) is the ZERO quaternion, not identity - a fresh manager's heading computations would silently read 90 degrees; explicit IdentityPosition resets match the decomp's identity-Frame semantics. Also pinned: retail's explicit double adjust_motion in _DoMotion/_StopMotion; entry points never drain pending_actions (only PerformMovement's cancel does) - re-issues must route through PerformMovement, documented + tested. 101 new conformance tests incl. three end-to-end scripted drives (chase turn->run->walk-demote->arrive; flee; frozen-heading TurnToObject through retarget). Full suite: 3,961 passed. Implemented by a dedicated agent against the V0-pinned spec; scope + suite independently verified. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
e0d2492cbb
commit
addc8e97a8
13 changed files with 3779 additions and 0 deletions
1592
src/AcDream.Core/Physics/Motion/MoveToManager.cs
Normal file
1592
src/AcDream.Core/Physics/Motion/MoveToManager.cs
Normal file
File diff suppressed because it is too large
Load diff
47
src/AcDream.Core/Physics/Motion/MoveToNode.cs
Normal file
47
src/AcDream.Core/Physics/Motion/MoveToNode.cs
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
namespace AcDream.Core.Physics.Motion;
|
||||
|
||||
/// <summary>
|
||||
/// R4-V2 — verbatim port of retail's <c>MoveToManager::MovementNode</c>
|
||||
/// (<c>acclient.h:57702</c>, struct #6350):
|
||||
/// <code>
|
||||
/// struct __cppobj MoveToManager::MovementNode : DLListData
|
||||
/// { // +0 dllist_next, +4 dllist_prev (DLListData)
|
||||
/// MovementTypes::Type type; // +8 — only 7 (MoveToPosition) and 9 (TurnToHeading) ever queued
|
||||
/// float heading; // +0xc — only meaningful for type 9
|
||||
/// };
|
||||
/// </code>
|
||||
///
|
||||
/// <para>
|
||||
/// <b>NAME WATCH (r4-port-plan.md §3 "New code target"):</b> named
|
||||
/// <c>MoveToNode</c>, NOT <c>MovementNode</c>, to avoid colliding with R2's
|
||||
/// <see cref="MotionNode"/> (the UNRELATED <c>CMotionInterp::pending_motions</c>
|
||||
/// node — a different queue on a different class; see the AD-34 register
|
||||
/// wording on both node types' shared "managed collection standing in for
|
||||
/// retail's intrusive DLList/LList" pattern).
|
||||
/// </para>
|
||||
///
|
||||
/// <para>
|
||||
/// Retail allocates these with <c>operator new(0x10)</c> and links them onto
|
||||
/// <c>MoveToManager::pending_actions</c> (a <c>DLList</c> — doubly-linked,
|
||||
/// unlike <c>CMotionInterp</c>'s singly-linked <c>LList</c>) via
|
||||
/// <c>DLListBase::InsertAfter</c> (tail-append; r4-moveto-decomp.md §4a).
|
||||
/// Ported as a managed <see cref="System.Collections.Generic.LinkedList{T}"/>
|
||||
/// of this value type — same pattern as <see cref="MotionNode"/>'s port
|
||||
/// (AD-34 wording): node identity semantics preserved via
|
||||
/// <c>LinkedListNode<MoveToNode></c> references rather than raw
|
||||
/// prev/next pointers, FIFO order preserved via tail-append +
|
||||
/// <c>RemoveFirst</c>.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
/// <param name="Type">Retail <c>type</c> (+8) — only
|
||||
/// <see cref="MovementType.MoveToPosition"/> (7) and
|
||||
/// <see cref="MovementType.TurnToHeading"/> (9) are ever queued
|
||||
/// (r4-moveto-decomp.md §4a: <c>AddMoveToPositionNode</c> /
|
||||
/// <c>AddTurnToHeadingNode</c> are the only two producers;
|
||||
/// <see cref="MoveToManager.BeginNextNode"/>'s dispatch is a defensive
|
||||
/// <c>if/if</c>, not a full switch — an unknown type stalls rather than
|
||||
/// throwing, matching the raw's shape).</param>
|
||||
/// <param name="Heading">Retail <c>heading</c> (+0xc) — only meaningful for
|
||||
/// <see cref="MovementType.TurnToHeading"/> nodes; zero/unused for
|
||||
/// <see cref="MovementType.MoveToPosition"/> nodes.</param>
|
||||
public readonly record struct MoveToNode(MovementType Type, float Heading);
|
||||
Loading…
Add table
Add a link
Reference in a new issue