Register: - Verified retired: AD-8/AD-9/AP-8/AP-9 (V4), TS-36/AD-26 (V5) - all gone. - AD-34 widened: MoveToManager.pending_actions joins the managed-LinkedList row, with the MoveToNode rename note (retail MoveToManager::MovementNode, renamed to avoid colliding with R2's MotionNode) - V2 owed this note. - NEW TS-39: MoveToManager.StickTo/Unstick are unbound no-op seams - a sticky MoveTo (wire bit 0x80) completes-and-stops instead of sticking; PositionManager/StickyManager bodies are R5 scope (call shapes only in the R4 extraction). Retires with R5. - Re-anchored after the V5 controller deletion shifted lines: AD-25 (:1212->:874), AP-24 (:170->:176), AP-30 (:1503->:1110), TS-21 (:362->:311, stale-comment clause updated - V5 fixed the comment). - AP-79 (widened in V5's commit) and the PlanFromVelocity row (V4) verified present. Roadmap: Phase R entry - R4 SHIPPED 2026-07-03 (V0-V6 trail), R2+R3+R4 share the ONE pending user visual pass; next code stage R5 (MovementManager facade + Sticky/Constraint/TargetManager). Plan of record: R4 stage entry filled in with the full V0-V6 commit trail + expected-diffs for the visual pass (retail cylinder-distance stop, real turn cycles during corrections, CanCharge walk/run legs). Handoff doc: postscript - R4 complete, V4 smoke log analyzed clean and deleted; memory index updated (animation deep-dive map: MoveToManager gap CLOSED, the "three approximations" pattern retired). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
174 lines
12 KiB
Markdown
174 lines
12 KiB
Markdown
# 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. SHIPPED 2026-07-02** (commits 1371c2a1 P0/P1, 778744bf P2, 5138b8fb P3, 658b91d8 P4, 9147344a P5, +P6): the verbatim core (AnimSequenceNode/CSequence/FrameOps, 56 conformance tests) + the AnimationSequencer adapter rehost deleting the legacy epsilon/stale-head/safety-cap/per-node-flag mechanisms; root motion flows through Advance(dt, Frame) = retail update(Frame*). Registers AD-33/AD-34. 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. SHIPPED 2026-07-02 (pending
|
||
the stage visual pass).** 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.
|
||
Progress: Q0 pins (dc54a3e4) + Q1 MotionState (2345da30), Q2 CMotionTable all-4-branch
|
||
GetObjectSequence + statics (98f58db9, 44 tests), Q3 MotionTableManager+
|
||
pending_animations (aa65990a, 47 tests), Q4 adapter cutover (3b9d9bb6 —
|
||
SetCycle/PlayAction → PerformMovement; Fix B / fast-path / stop-anim
|
||
fallback / G17 gate DELETED; 11-scenario trace conformance a6235a36).
|
||
Q5 RemoteMotionSink DELETED (d82f07d4 — funnel → MotionTableDispatchSink →
|
||
PerformMovement; AP-73 retired; spawn/despawn run initialize_state/
|
||
HandleExitWorld; live smoke green: MOTIONDONE chain firing in-world).
|
||
Q6 sweep done with Q5. OUTSTANDING: the ONE user visual pass (walk↔run
|
||
stride continuity, turn-while-running legs, emote overlay, stop settle).
|
||
R3 prep done in parallel: research base 8eff3978 + W0 pins cd0289be (all
|
||
10 ambiguities resolved, adversarially verified).
|
||
- **R3 — CMotionInterp completion. SHIPPED 2026-07-03 (pending the stage
|
||
visual pass).** 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 unified (edge-driven CommandInterpreter altitude; the
|
||
synthesis layer + UpdatePlayerAnimation deleted).
|
||
Trail: W-1 research 8eff3978, W0 pins cd0289be (A1-A10 adversarially
|
||
verified), W1 state completion 86649591, W2 pending_motions 37167991,
|
||
W3 jump family af476444, W4 ground transitions + K-fix18 DELETED
|
||
e214acdf, W5 one-DoInterpretedMotion + zero-tick flush df7b096d
|
||
(discovery: the dispatch RESULT gates queue+state writes — sink returns
|
||
bool), W6 local-player unification fb7beb70 (map fc5a2cda; discoveries:
|
||
ChargeJump never wired, CurrentHoldKey shadow-field staleness, the
|
||
autonomous-flag clobber). Registers through the arc: retired AP-73/
|
||
AP-74/AP-78/TS-34/IA-4 + the Fix-B-class inventions; added AD-36
|
||
(narrowed), AP-75/76/77, TS-35/36/37/38. EXPECTED-DIFFS for the visual
|
||
pass: #45 sidestep factor + ANIM_SPEED_SCALE retired (local now matches
|
||
remotes), auto-walk-at-run walk-pace legs (R4), ApplyServerRunRate echo
|
||
live through fast re-speed. R3+R2 share ONE visual pass.
|
||
- **R4 — MoveToManager verbatim. SHIPPED 2026-07-03 (pending the stage
|
||
visual pass).** Types 6/7/8/9 (TurnToObject/TurnToHeading — the dropped
|
||
D9/DEV-5 commands), node stepping, arrival, fail distance, CanCharge.
|
||
RemoteMoveToDriver + ServerControlledLocomotion.PlanMoveToStart + B.6
|
||
auto-walk all DELETED.
|
||
Trail: research base 988304e1, V0 pins 386b1ce5 (P1-P7 resolved; P1
|
||
autonomous-echo gate + P3 heading_diff mirror adversarially sealed, P3
|
||
down to instruction bytes), V1 command-selection family e0d2492c
|
||
(GetCommand + CanCharge fast-path + MoveToMath), V2 the verbatim manager
|
||
addc8e97 (all 33 members, 101 tests, seam-injected harness), V3 wire
|
||
completion a144e873 (mt 8/9 parse + full params exposure + sticky
|
||
trailer), V4 remote cutover 7016b26c (per-remote manager, P4
|
||
TargetTracker adapter, retail unpack dispatch; retired AD-8/AD-9/AP-8/
|
||
AP-9; smoke log verified clean), V5 local-player cutover b3decdfa (P1
|
||
gate ported verbatim — ACE's autonomous echo dropped before unpack;
|
||
B.6 deleted; TS-36 bound — input/jump/teleport cancel through the retail
|
||
interrupt chain; run-rate re-anchored to PD skills + mt-6/7 my_run_rate,
|
||
echo tap deleted with NO AD row; MoveToComplete client seam widened to
|
||
natural completion for AD-27; adversarial-review fixes: remote HitGround
|
||
relay, mt-8 wire_heading degrade, remote curTime clock), V6 register/
|
||
docs sweep (AD-34 widened with the MoveToNode rename, NEW TS-39 StickTo/
|
||
Unstick no-op seams → R5, TS-33 extended with the orientation-diff gap,
|
||
TS-21/AD-25/AP-24/AP-30 re-anchored). EXPECTED-DIFFS for the visual
|
||
pass: melee-range stop distance (retail cylinder distance — the AD-8
|
||
max() class is gone), auto-walk legs now walk/run per CanCharge with
|
||
real turn cycles during corrections, walk-pace close-in demote.
|
||
OUTSTANDING: the stage visual pass (folds into the pending R2+R3 pass).
|
||
- **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).
|