feat(R4-V1): command-selection family + state widening (closes M2-mechanics, M11, M12, M15)
MovementParameters gains the verbatim selection family: GetCommand 0x0052aa00 (the walk-vs-run cascade INCLUDING the CanCharge 0x10 fast-path ACE dropped - retail's default can_charge=false + the fast-path present, the A13+A15 canceling-pair trap avoided; inclusive threshold edge per the raw), TowardsAndAway, GetDesiredHeading per the live Ghidra decompile (fwd-towards 0 / fwd-away 180 / back-towards 180 / back-away 0), FromWire/FromWireTurnTo (UnPackNet semantics, all 18 A4 masks round-tripped). New MoveToMath: HeadingDiff per the live Ghidra decompile of 0x00528fb0 (the 360-diff NOT-TurnRight mirror + F_EPSILON 0.000199999995f - the BN "arg unused" artifact corrected), HeadingGreater (the visible TurnRight idiom), PositionHeading/Get/SetHeading reusing the codebase's single yaw-heading convention (P5), CylinderDistance (PDB arg order; planar-minus-radii shape documented as the interpretation - the raw's x87 body is garbled; seam noted). MovementType gains Invalid + retail 6/7/8/9; MovementStruct widened (ObjectId/TopLevelId/Pos/Radius/Height/Params, additive); WeenieError += 0x0B/0x36/0x37/0x38/0x3D with retail-meaning doc comments. 148 new conformance tests. Full suite: 3,860 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
386b1ce550
commit
e0d2492cbb
14 changed files with 1973 additions and 4 deletions
|
|
@ -95,11 +95,31 @@ public static class MotionCommand
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Movement type passed in PerformMovement's switch statement.
|
||||
/// Matches the 5-case switch at FUN_00529a90.
|
||||
/// Movement type passed in PerformMovement's switch statement. Matches
|
||||
/// retail's <c>MovementTypes::Type</c> (acclient.h:2856, enum #229) in full.
|
||||
///
|
||||
/// <para>
|
||||
/// <b>R4-V1 widening (closes M11).</b> Values 1-5 dispatch through
|
||||
/// <c>CMotionInterp</c> (the 5-case switch at FUN_00529a90, unchanged since
|
||||
/// R1-R3); values 6-9 dispatch through <c>MoveToManager</c>
|
||||
/// (<c>MovementManager::PerformMovement</c>, r4-moveto-decomp.md §2b:
|
||||
/// <c>(type - 1) > 8 → 0x47</c>, case 0-4 → CMotionInterp, case 5-8 →
|
||||
/// MoveToManager). <c>Invalid=0</c> and values > 9 both fail with
|
||||
/// <see cref="WeenieError.GeneralMovementFailure"/> (0x47) at the
|
||||
/// MovementManager level — no consumer wiring changes in this slice
|
||||
/// (mechanical, additive-only; MoveToManager itself is R4-V2+).
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public enum MovementType
|
||||
{
|
||||
/// <summary>
|
||||
/// 0 — no movement in progress / uninitialized. R4-V1 addition (M11).
|
||||
/// <c>MoveToManager::InitializeLocalVariables</c> resets
|
||||
/// <c>movement_type</c> to this value; <c>MovementManager::PerformMovement</c>
|
||||
/// rejects it with 0x47 (§2b: <c>(type - 1) > 8</c> underflows to a
|
||||
/// huge unsigned value for type 0, which is always > 8).
|
||||
/// </summary>
|
||||
Invalid = 0,
|
||||
/// <summary>case 1 — raw motion command (DoMotion).</summary>
|
||||
RawCommand = 1,
|
||||
/// <summary>case 2 — interpreted motion command (DoInterpretedMotion).</summary>
|
||||
|
|
@ -110,6 +130,31 @@ public enum MovementType
|
|||
StopInterpretedCommand = 4,
|
||||
/// <summary>case 5 — stop completely (StopCompletely).</summary>
|
||||
StopCompletely = 5,
|
||||
/// <summary>
|
||||
/// 6 — MoveToObject. R4-V1 addition (M11). Dispatches to
|
||||
/// <c>MoveToManager::MoveToObject</c> (r4-moveto-decomp.md §3b); uses
|
||||
/// <see cref="MovementStruct.ObjectId"/>/<see cref="MovementStruct.TopLevelId"/>/
|
||||
/// <see cref="MovementStruct.Radius"/>/<see cref="MovementStruct.Height"/>.
|
||||
/// </summary>
|
||||
MoveToObject = 6,
|
||||
/// <summary>
|
||||
/// 7 — MoveToPosition. R4-V1 addition (M11). Dispatches to
|
||||
/// <c>MoveToManager::MoveToPosition</c> (§3c); uses
|
||||
/// <see cref="MovementStruct.Pos"/>.
|
||||
/// </summary>
|
||||
MoveToPosition = 7,
|
||||
/// <summary>
|
||||
/// 8 — TurnToObject. R4-V1 addition (M11). Dispatches to
|
||||
/// <c>MoveToManager::TurnToObject</c> (§3d); uses
|
||||
/// <see cref="MovementStruct.ObjectId"/>/<see cref="MovementStruct.TopLevelId"/>.
|
||||
/// </summary>
|
||||
TurnToObject = 8,
|
||||
/// <summary>
|
||||
/// 9 — TurnToHeading. R4-V1 addition (M11). Dispatches to
|
||||
/// <c>MoveToManager::TurnToHeading</c> (§3e); uses
|
||||
/// <see cref="MovementStruct.Params"/>'s <c>DesiredHeading</c>.
|
||||
/// </summary>
|
||||
TurnToHeading = 9,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -144,6 +189,15 @@ public enum WeenieError : uint
|
|||
/// </summary>
|
||||
NoPhysicsObject = 0x08,
|
||||
/// <summary>
|
||||
/// 0x0B — NoMotionInterpreter. R4-V1 addition (M12), per
|
||||
/// docs/research/2026-07-03-r4-moveto/r4-moveto-decomp.md §12 constants
|
||||
/// inventory (<c>8, 0xb, 0x36, 0x37, 0x38, 0x3d, 0x47</c>). ACE name;
|
||||
/// the retail sites that store this code were not individually
|
||||
/// extracted in the R4 pass (no MoveToManager consumer in this slice —
|
||||
/// V1 pins the numeric value only).
|
||||
/// </summary>
|
||||
NoMotionInterpreter = 0x0B,
|
||||
/// <summary>
|
||||
/// 0x24 — not grounded / no contact. Sites (A10):
|
||||
/// <c>jump_is_allowed</c> @305570 (gravity-active creature without
|
||||
/// Contact+OnWalkable; also the <c>physics_obj == null</c> case, which
|
||||
|
|
@ -173,6 +227,30 @@ public enum WeenieError : uint
|
|||
/// </summary>
|
||||
ChatEmoteOutsideNonCombat = 0x42,
|
||||
/// <summary>
|
||||
/// 0x36 — ActionCancelled. R4-V1 addition (M12). Site:
|
||||
/// <c>MoveToManager::PerformMovement</c> (r4-moveto-decomp.md §3a
|
||||
/// @0052a901) — every new moveto cancels the previous one with this
|
||||
/// code before dispatching; also <c>CPhysicsObj::interrupt_current_movement</c>
|
||||
/// → <c>MovementManager::CancelMoveTo(0x36)</c> (§9e — the TS-36 cancel
|
||||
/// entry). Per §7c, <c>MoveToManager::CancelMoveTo</c>'s WeenieError arg
|
||||
/// is NEVER READ in this build's body — kept for parity/logging only.
|
||||
/// </summary>
|
||||
ActionCancelled = 0x36,
|
||||
/// <summary>
|
||||
/// 0x37 — ObjectGone. R4-V1 addition (M12). Site:
|
||||
/// <c>MoveToManager::HandleUpdateTarget</c> (§6d @307866-307867) — a
|
||||
/// RETARGET delivery arrives with a non-OK target status (the target
|
||||
/// object was already being tracked, then went away).
|
||||
/// </summary>
|
||||
ObjectGone = 0x37,
|
||||
/// <summary>
|
||||
/// 0x38 — NoObject. R4-V1 addition (M12). Site:
|
||||
/// <c>MoveToManager::HandleUpdateTarget</c> (§6d @307857-307858) — the
|
||||
/// FIRST target callback arrives with a non-OK status (the target never
|
||||
/// resolved in the first place).
|
||||
/// </summary>
|
||||
NoObject = 0x38,
|
||||
/// <summary>
|
||||
/// 0x45 — action-queue depth cap: an action-class motion (bit
|
||||
/// 0x10000000) with <c>GetNumActions() >= 6</c> pending. Site:
|
||||
/// DoMotion @306209.
|
||||
|
|
@ -203,6 +281,17 @@ public enum WeenieError : uint
|
|||
/// @304941; <c>charge_jump</c> @305454.
|
||||
/// </summary>
|
||||
CantJumpLoadedDown = 0x49,
|
||||
/// <summary>
|
||||
/// 0x3D — YouChargedTooFar. R4-V1 addition (M12). Site:
|
||||
/// <c>MoveToManager::HandleMoveToPosition</c> Phase 2 arrival check
|
||||
/// (r4-moveto-decomp.md §6b) — the <c>fail_distance</c> progress gate
|
||||
/// exceeded (<c>CheckProgressMade</c> §5b failing for >1s AND the
|
||||
/// mover overshot <c>fail_distance</c>). NOTE: numerically out of A10's
|
||||
/// increasing order (0x3D < 0x3F/0x40/0x41/0x42/0x45) because it was
|
||||
/// not part of the CMotionInterp jump-family sweep this code sits
|
||||
/// beside — it belongs to the MoveToManager family instead (§7c, §12).
|
||||
/// </summary>
|
||||
YouChargedTooFar = 0x3D,
|
||||
}
|
||||
|
||||
// ── Motion state structs ───────────────────────────────────────────────────────
|
||||
|
|
@ -404,12 +493,40 @@ public struct InterpretedMotionState
|
|||
/// <summary>
|
||||
/// Lightweight struct passed into PerformMovement.
|
||||
/// Fields correspond to what the retail dispatcher read from param_1 (the movement packet struct).
|
||||
///
|
||||
/// <para>
|
||||
/// <b>R4-V1 widening (closes M11).</b> Retail's full <c>MovementStruct</c>
|
||||
/// (acclient.h:38069, struct #4067):
|
||||
/// <code>
|
||||
/// struct __cppobj MovementStruct
|
||||
/// {
|
||||
/// MovementTypes::Type type;
|
||||
/// unsigned int motion; // types 1-4 only
|
||||
/// unsigned int object_id; // types 6, 8
|
||||
/// unsigned int top_level_id; // types 6, 8
|
||||
/// Position pos; // type 7
|
||||
/// float radius; // type 6
|
||||
/// float height; // type 6
|
||||
/// MovementParameters *params; // types 1-4, 6-9
|
||||
/// };
|
||||
/// </code>
|
||||
/// <see cref="ObjectId"/>/<see cref="TopLevelId"/>/<see cref="Pos"/>/
|
||||
/// <see cref="Radius"/>/<see cref="Height"/>/<see cref="Params"/> are the
|
||||
/// R4-V1 additions — additive only, no consumer wiring in this slice
|
||||
/// (MoveToManager itself is R4-V2). The pre-R4 fields (<see cref="Type"/>/
|
||||
/// <see cref="Motion"/>/<see cref="Speed"/>/<see cref="Autonomous"/>/
|
||||
/// <see cref="ModifyInterpretedState"/>/<see cref="ModifyRawState"/>) are
|
||||
/// untouched. <see cref="Pos"/> uses acdream's <see cref="Position"/>
|
||||
/// (ObjCellId + CellFrame) rather than retail's block-local Position —
|
||||
/// V0-pins.md §P5: distances are equivalent after rebase in acdream's
|
||||
/// streaming-world space.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public struct MovementStruct
|
||||
{
|
||||
/// <summary>Which of the 5 motion types to dispatch.</summary>
|
||||
/// <summary>Which movement type to dispatch (retail <c>MovementTypes::Type</c>, full 0-9 range).</summary>
|
||||
public MovementType Type;
|
||||
/// <summary>Motion command ID (e.g. WalkForward).</summary>
|
||||
/// <summary>Motion command ID (e.g. WalkForward). Types 1-4 only.</summary>
|
||||
public uint Motion;
|
||||
/// <summary>Speed scalar for this motion.</summary>
|
||||
public float Speed;
|
||||
|
|
@ -419,6 +536,35 @@ public struct MovementStruct
|
|||
public bool ModifyInterpretedState;
|
||||
/// <summary>Whether to modify the raw state.</summary>
|
||||
public bool ModifyRawState;
|
||||
|
||||
/// <summary>
|
||||
/// R4-V1 — retail <c>object_id</c>. Types 6 (MoveToObject), 8
|
||||
/// (TurnToObject) only.
|
||||
/// </summary>
|
||||
public uint ObjectId;
|
||||
/// <summary>
|
||||
/// R4-V1 — retail <c>top_level_id</c>. Types 6 (MoveToObject), 8
|
||||
/// (TurnToObject) only.
|
||||
/// </summary>
|
||||
public uint TopLevelId;
|
||||
/// <summary>
|
||||
/// R4-V1 — retail <c>pos</c> (world position + cell). Type 7
|
||||
/// (MoveToPosition) only.
|
||||
/// </summary>
|
||||
public Position Pos;
|
||||
/// <summary>
|
||||
/// R4-V1 — retail <c>radius</c>. Type 6 (MoveToObject) only.
|
||||
/// </summary>
|
||||
public float Radius;
|
||||
/// <summary>
|
||||
/// R4-V1 — retail <c>height</c>. Type 6 (MoveToObject) only.
|
||||
/// </summary>
|
||||
public float Height;
|
||||
/// <summary>
|
||||
/// R4-V1 — retail <c>params</c> (a pointer in retail; a reference
|
||||
/// here). Types 1-4 and 6-9.
|
||||
/// </summary>
|
||||
public Motion.MovementParameters? Params;
|
||||
}
|
||||
|
||||
// ── Optional WeenieObject interface ──────────────────────────────────────────
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue