feat(R2-Q5): RemoteMotionSink DELETED — funnel dispatches straight into PerformMovement; AP-73 retired

The funnel's retail-ordered dispatches now go directly into the entity's
motion-table stack via Motion/MotionTableDispatchSink (Core):
ApplyMotion → PerformMovement(InterpretedCommand), StopMotion →
PerformMovement(StopInterpretedCommand). No axis collection, no
single-cycle priority pick, no Commit pass, no HasCycle probe, no
Run→Walk→Ready fallback chain — GetObjectSequence 0x00522860 +
is_allowed decide (closes H4, H5-callers, H11-callers, H15, H17-carry).
Run-while-turning now blends for real: the turn is a Branch-4 modifier
combined over the untouched run substate (AP-73 DELETED from the
register).

AnimationSequencer gains the public PerformMovement passthrough (lazy
initialize_state + locomotion velocity synthesis on success — AP-75;
remote body translation via PositionManager.ComputeOffset depends on
CurrentVelocity) and InitializeState(); HasCycle DELETED (the miss
hazard is structurally gone — GetObjectSequence checks the cycle before
any surgery; new conformance test pins sequence+state untouched on a
miss).

GameWindow: sink swap with the TurnApplied/TurnStopped ObservedOmega
callbacks (H17 carried verbatim — register AP-76, retire R6); spawn +
door sites run retail's enter-world order (initialize_state installs
the table default, the wire's initial motion dispatches unguarded — the
L.1c fallback chains deleted); despawn drains the pending queue via
HandleExitWorld (MotionDone success:false per entry, 0x0051bda0).

5 new MotionTableDispatchSink conformance tests (lazy init, Branch-4
turn blend + callback, Case-B stop unwind, Case-A stop re-drive,
miss no-op). Full suite green: 3,462 passed.

Live smoke vs ACE: in-world, NPC emote/Ready UMs dispatching through
the new path, [MOTIONDONE] completions firing across entities — first
live proof of the Q3→Q4→Q5 chain. Zero exceptions.

Registers: AP-73 deleted; AP-76 added.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-07-02 21:55:13 +02:00
parent c072b73686
commit d82f07d4e5
8 changed files with 399 additions and 395 deletions

View file

@ -179,9 +179,9 @@ accepted-divergence entries (#96, #49, #50).
---
| AP-73 | **Remote motion sink maps retail's substate+modifier animation model onto ONE cycle** — the L.2g S2 funnel dispatches retail-verbatim (style/forward/sidestep/turn per `apply_interpreted_movement` order + action-stamp gate), but `RemoteMotionSink.Commit` resolves the axes into a single `SetCycle` (forward locomotion > sidestep > turn priority + Run→Walk→Ready missing-cycle fallback); retail BLENDS modifiers over the substate cycle via `CMotionTable::re_modify` (DEV-9) | `src/AcDream.App/Rendering/RemoteMotionSink.cs` (`Commit`) | The pick + fallback are the pre-S2 behavior moved verbatim (user-verified across L.1/L.3); the STATE side is now fully retail through the funnel, so only the visible-animation composition approximates. Retire with the S3/S6 modifier port (`re_modify` + `subtract_motion` omega/velocity combine) | Run-while-turning shows pure run legs (no lean/turn blend); sidestep-while-walking shows one cycle only — animation-composition mismatch vs retail observers, position unaffected | `CMotionTable::re_modify` (GetObjectSequence tail, pc:298636); `StopSequenceMotion` modifier branch pc:298954 |
| AP-74 | **K-fix18 `skipTransitionLink`** post-Q4 expression: `SetCycle(..., skipTransitionLink:true)` strips the just-dispatched transition links via `CSequence.RemoveAllLinkAnimations` so Falling engages instantly on jump start; retail gets the same strip from `LeaveGround``CPhysicsObj::RemoveLinkAnimations` (0x0050fe20) fired by the physics layer detecting ground departure (R2-Q4 rehost of the 2026-04-26 K-fix18) | `src/AcDream.Core/Physics/AnimationSequencer.cs` (`SetCycle` skip branch); GameWindow :4830/:10201 callers | Same primitive retail uses, fired from the caller instead of the ground-transition event; pending-queue tick counts intentionally not zeroed (retail's RemoveLinkAnimations doesn't touch the manager queue — the countdown chain absorbs the stall) | If a code path sets the flag outside a genuine ground-departure, links retail would play get eaten; queue completion for the stripped entry reports late (next sentinel) | `LeaveGround` 0x00528b00 → `RemoveLinkAnimations` 0x0050fe20; retire in R3-W4 (flag + call sites deleted, LeaveGround fires it) |
| AP-75 | **Adapter-boundary `adjust_motion` + locomotion velocity/omega synthesis**: `SetCycle` still (a) remaps TurnLeft/SideStepLeft/WalkBackward to their mirrors with negated speed BEFORE dispatch (retail adjusts in `CMotionInterp` — R3 scope; GameWindow's local-player path passes raw ids), and (b) post-dispatch overwrites sequence velocity (low-bytes 05/06/07/0F/10) and omega (0D/0E, only when dat-silent) with the retail locomotion constants — retail drives BODY velocity from `get_state_velocity`, not the sequence accumulators (R2-Q4 carry-over of the pre-Q4 adapter tail) | `src/AcDream.Core/Physics/AnimationSequencer.cs` (`SetCycle` head remap + tail synthesis) | (a) preserves unadjusted GameWindow callers until R3-W6 unifies the local player onto MotionInterpreter; (b) preserves the remote-DR and local Option-B velocity consumers until R6 root motion drives the body (sibling of IA-3) | (a) none while callers stay in the known set; (b) a dat whose locomotion MotionData carries a REAL velocity different from the constants gets overwritten — exotic-creature speed skew (same class as IA-3's risk) | `CMotionInterp::adjust_motion` @305343; `get_state_velocity` 0x00528960; retire (a) R3-W6, (b) R6 |
| AP-76 | **Remote rotation from the ObservedOmega side-channel**: the R2-Q5 sink callbacks (`MotionTableDispatchSink.TurnApplied/TurnStopped`) seed `RemoteMotion.ObservedOmega = (0,0,-(pi/2)*signedTurnSpeed)` on wire turns and zero it on turn-stops; GameWindow's per-tick step applies ObservedOmega (preferring it over sequence omega) to the remote body's orientation. Retail rotates the body from the SEQUENCE omega inside the per-tick apply_physics chain (CSequence::apply_physics -> CPhysicsObj omega integration) (carried verbatim from the deleted RemoteMotionSink; H17) | `src/AcDream.App/Rendering/GameWindow.cs` (sink callbacks in OnLiveMotionUpdated + the omegaToApply step in TickAnimations) | Same angular rate retail derives (pi/2 rad/s x turn speed); starts rotation the same tick as the wire turn without waiting for R6's per-tick order; UpdatePosition orientation snaps bound any drift | If the dat's turn modifier omega differs from the pi/2 constant, remote rotation rate diverges until an orientation snap; double-application risk if R6 lands apply_physics-driven rotation without deleting this seam | retire in R6 (retail per-tick order: apply_physics drives remote rotation) |
## 4. Temporary stopgap (TS) — 33 rows