From cae56afc82fd8ac680ca51df33a03faad26e2a45 Mon Sep 17 00:00:00 2001 From: Erik Date: Thu, 2 Jul 2026 19:21:28 +0200 Subject: [PATCH] =?UTF-8?q?docs(R):=20Phase=20R=20plan=20of=20record=20?= =?UTF-8?q?=E2=80=94=20retail=20motion+animation=20ground-up=20reconstruct?= =?UTF-8?q?ion?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit User mandate 2026-07-02: complete new movement + animation system, verbatim retail equivalent, all entity classes, inbound + outbound, no frozen code, no bandaids. Executed as a staged verbatim reconstruction (R1 CSequence -> R8 cutover audit), each stage harness-gated with the proven cdb-golden technique; legacy paths DELETED at each cutover. Supersedes L.2g S3-S6; absorbs shipped S1/S2/S5 as components. Co-Authored-By: Claude Fable 5 --- docs/plans/2026-04-11-roadmap.md | 8 ++ ...6-07-02-retail-motion-animation-rewrite.md | 124 ++++++++++++++++++ 2 files changed, 132 insertions(+) create mode 100644 docs/plans/2026-07-02-retail-motion-animation-rewrite.md diff --git a/docs/plans/2026-04-11-roadmap.md b/docs/plans/2026-04-11-roadmap.md index f03bdcd0..86ca3760 100644 --- a/docs/plans/2026-04-11-roadmap.md +++ b/docs/plans/2026-04-11-roadmap.md @@ -697,6 +697,14 @@ diagnostic scaffolding, not yet the final collision system. tests to real-world fixtures and verify local acdream view plus retail observer view. ACE accepting a position is a compatibility check, not proof of fine-grained retail collision parity. +- **Phase R — retail motion & animation ground-up reconstruction (2026-07-02, + user mandate: total overhaul, verbatim, all entity classes, no frozen + code).** Plan of record: `docs/plans/2026-07-02-retail-motion-animation-rewrite.md` + — stages R1 (CSequence) → R8 (cutover audit). SUPERSEDES the L.2g S3–S6 + slices below; L.2g S1/S2/S5 (shipped 2026-07-02: staleness gate, inbound + funnel + 183-case live-retail conformance harness, pace-guesser deletion) + are absorbed as components. NOTE: this Phase R is unrelated to the retired + "R1→R8 refactor sketch" from early 2026 — same letter, new plan. - **L.2g — Inbound motion interpretation (remote-entity CMotionInterp funnel).** ACTIVE 2026-07-02. Port retail's inbound motion pipeline verbatim for ALL remote entities (players, NPCs, monsters — one funnel, user-approved): diff --git a/docs/plans/2026-07-02-retail-motion-animation-rewrite.md b/docs/plans/2026-07-02-retail-motion-animation-rewrite.md new file mode 100644 index 00000000..1a1d3efe --- /dev/null +++ b/docs/plans/2026-07-02-retail-motion-animation-rewrite.md @@ -0,0 +1,124 @@ +# Phase R — retail motion & animation stack, ground-up reconstruction + +Date: 2026-07-02. **Mandate (user, verbatim intent):** a complete new +movement + animation system, verbatim retail equivalent — all movement, +inbound and outbound, all animation, for players, NPCs, and monsters. No +frozen code, no bandaids, no guessing, no approximation. Total overhaul. + +**Execution shape:** a staged verbatim RECONSTRUCTION, not a big-bang +cutover — each stage builds a retail class 1:1 with a conformance harness, +cuts consumers over, and DELETES the legacy path in the same stage. "New +system" is the destination; the client keeps running between stages. The +cdb-golden technique is proven (183/183 live-retail dispatch conformance in +S2a) and is the acceptance mechanism for every stage: the user's eyes are a +final sanity pass only. + +Supersedes the L.2g S3–S6 slice plan (S1/S2/S5 landed and are absorbed as +components). This doc is the plan of record; the deviation map +(`docs/research/2026-07-02-inbound-motion-deviation-map.md`), the funnel +pseudocode (`…-s2-inbound-funnel-pseudocode.md`), and the 2026-06-04 +sequencer deep-dive are its research base. + +## The retail module map to reconstruct (per physics object, ALL classes) + +``` +CPhysicsObj (local player, remote player, NPC, monster — ONE pipeline) + ├─ MovementManager unpack_movement 0x00524440 (10-way dispatch), + │ │ PerformMovement, MotionDone relay + │ ├─ CMotionInterp raw_state + interpreted_state + pending_motions, + │ │ DoMotion / DoInterpretedMotion / StopInterpretedMotion, + │ │ apply_raw/interpreted/current_movement, my_run_rate, + │ │ HitGround / LeaveGround / ReportExhaustion, jump family + │ └─ MoveToManager movement types 6/7/8/9 (MoveToObject/Position, + │ TurnToObject/Heading), node stepping, arrival radii, + │ fail distance, CanCharge walk/run selection + ├─ CPartArray → MotionTableManager pending_animations, add_to_queue 0x0051bfe0, + │ │ remove_redundant_links 0x0051bf20, + │ │ CheckForCompletedMotions 0x0051be00 → AnimationDone + │ └─ CMotionTable::GetObjectSequence 0x00522860 + │ │ same-substate fast path (change_cycle_speed + + │ │ subtract/combine_motion), link path (get_link + + │ │ style-default double-hop), re_modify, is_allowed + │ └─ CSequence anim-node DLList, append_animation 0x00525510, + │ remove_cyclic_anims, clear_physics, velocity/omega + │ accumulators, update/update_internal + apply_physics + │ (root motion), placement frames, hook dispatch + ├─ PositionManager InterpolationManager [PORTED ✓ L.3] + StickyManager + │ + ConstraintManager + └─ per-tick UpdateObjectInternal 0x005156b0 order: + CPartArray.Update (CSequence root motion) → PositionManager.adjust_offset + (chase REPLACES) → Frame.combine → UpdatePhysicsInternal → FULL transition + sweep (ALL entities — retires the remote no-sweep fork) → MovementManager.UseTime + / CPartArray.HandleMovement / PositionManager.UseTime → process_hooks +``` + +## Already-verbatim components (absorbed, not rewritten) + +- `MotionSequenceGate` (S1) — is_newer 3-stamp gate, live-validated. +- Inbound funnel: `MoveToInterpretedState` / `ApplyInterpretedMovement` / + `DispatchInterpretedMotion` / verbatim `contact_allows_move` (S2a) + + 183-case live-trace conformance suite. +- `InterpolationManager` (L.3) — chase constants re-verified 2026-07-02. +- Outbound: `RawMotionState::Pack` default-difference, MoveToStatePack + trailer, JumpPack (L.2b/D6.2b, golden-byte tests); dual command catalogs + (L.1b); `adjust_motion`/`apply_run_to_command`/`apply_raw_movement`/ + `get_state_velocity` (D6). + +Everything else is reconstruction scope — especially: `AnimationSequencer` +internals (becomes the CSequence port's host or is replaced by it), the +three per-tick drive paths in `GameWindow.TickAnimations`, `RemoteMotionSink` +(temporary S2b seam — dissolves into GetObjectSequence), `RemoteMoveToDriver`, +`ServerControlledLocomotion`, the motion half of `PlayerMovementController`, +the 300 ms stop-detection window, NPC UP hard-snaps. + +## Stage plan (each: pseudocode → harness → port → cutover → DELETE legacy → register sweep) + +- **R1 — CSequence verbatim.** Node list, framerate/rate math, velocity+ + omega accumulators (set/combine/subtract), update/update_internal root + motion, apply_physics, placement frames, hook dispatch. Goldens: dat + MotionData fixtures + a cdb trace of append_animation/remove_cyclic_anims + args (script pattern: tools/cdb/l2g-observer.cdb). Cutover: becomes the + sequencer core behind the existing AnimationSequencer API, then the API + narrows to retail's. +- **R2 — GetObjectSequence + MotionTableManager.** Fast path, link path + (restores the walk↔run link pose — old S4), re_modify (modifier blend — + retires AP-73), pending_animations + remove_redundant_links + + CheckForCompletedMotions → AnimationDone→MotionDone chain (old S3). + RemoteMotionSink's single-cycle pick DELETED — GetObjectSequence decides. +- **R3 — CMotionInterp completion.** pending_motions/MotionDone, DoMotion, + jump family (jump_charge_is_allowed/motion_allows_jump verbatim — the + misattribution found in S2a), HitGround/LeaveGround/ReportExhaustion, + enter_default_state. LOCAL PLAYER unifies onto it (PlayerMovementController + keeps input + camera; motion state machine moves here). +- **R4 — MoveToManager verbatim.** Types 6/7/8/9 (TurnToObject/TurnToHeading + — the dropped D9/DEV-5 commands), node stepping, arrival, fail distance, + CanCharge. Replaces RemoteMoveToDriver + ServerControlledLocomotion. + Retires AD-8/AD-9/AP-8/AP-9. +- **R5 — MovementManager + MovementSystem facade.** One per-object pipeline + for every entity class; StickyManager (stick_to_object — the motionFlags + 0x100 bit) + ConstraintManager ports; GameWindow's OnLiveMotionUpdated + shrinks to parse→MovementSystem.HandleMovementEvent. +- **R6 — per-tick UpdateObjectInternal order.** Retail tick order for ALL + entities incl. the transition sweep for remotes (retires the L.3-M2 + no-sweep fork + the path A/B split + the 300 ms stop window + NPC UP + hard-snap special cases). GameWindow.TickAnimations sheds its motion + logic entirely (Code Structure Rule 1). +- **R7 — outbound autonomy cadence.** ShouldSendPositionEvent (0x006b45e0) + + the MTS/AP stamp split — retires TS-33. Outbound becomes 100% verbatim. +- **R8 — cutover audit.** grep-sweep for legacy motion code, register + reconciliation (every AD/AP/TS motion row retired or re-justified), full + live protocol (walk/run/toggle/turn/circle/stop/jump/MoveTo/TurnTo, + player+NPC+monster), ONE final user visual pass. + +## Standing rules for every stage + +1. Decomp is the oracle; ACE the interpretation aid; cdb/TTD the runtime + arbiter when they disagree (the S0/S2 pattern). +2. No stage ships without its conformance fixtures. Golden sources: dat + tables, cdb traces (both observer + actor side), captured wire logs. +3. Every commit: build + full suite green; register rows added/retired in + the same commit; roadmap stage table updated on stage completion. +4. New code lives in `src/AcDream.Core/Physics/Motion/` (pure logic; GL-free) + with App seams only for rendering handoff (Structure Rule 2). +5. Delete, don't gate: when a stage cuts over, the legacy path is REMOVED in + that stage (mandate: no frozen code, no bandaids).