Three unpack_movement parity items (facade deferred per the handoff's
own optional clause — see r5-wiring-handoff §V4 status):
1. HEAD style-on-change (0x00524440 @00524502-0052452c): both GameWindow
routing heads (remote + player) now dispatch DoMotion(style, ctor
defaults) when the UM's stance differs from the interp's current
style, BEFORE the movement-type routing — for EVERY type. Previously
style applied only through the mt-0 funnel copy, so a chase/turn UM
(mt 6-9) carrying a stance change started the move in the OLD stance
(a monster charged in NonCombat posture until the next mt-0). The
RetailObserverTraceConformanceTests exclusion note updated — the
trace filter stays (head calls can't appear in a
MoveToInterpretedState replay) but the production gap it pointed at
is closed.
2. #164 (closes): the action-replay loop threads each action's autonomy
into the dispatch params (Autonomous = the 0x1000 splice, raw
305982) — replayed actions enter the interpreted actions list with
their real autonomy instead of ctor-default false.
3. mt-0 wire flags consumed (UpdateMotion parsed them since R4-V3):
0x1 StickToObject → CPhysicsObj::stick_to_object port (0x005127e0:
resolve target, PartArray radii — 0 when shapeless, guid-as-is for
acdream's flat entity table — → PositionManager.StickTo; unresolvable
target → no stick), at BOTH case-0 tails in retail order
(@00524583-0052458e: funnel apply → stick → longjump flag);
0x2 StandingLongJump → Motion.StandingLongJump, UNCONDITIONAL write
(absent flag clears — retail @0052458e). ServerMotionState gains the
StandingLongJump field.
Conformance: ChaseArm_WithStanceChange_AppliesStanceBeforeTheChase
(harness mirrors the routing-head dispatch) +
Actions_ReplayCarriesAutonomyIntoTheInterpretedList. Suite 4041 green.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The two parallel DoInterpretedMotion implementations MERGE into one
verbatim pair (0x00528360/@305639): contact gate, StandingLongJump
state-only branch, Dead → RemoveLinkAnimations, the jump_error_code
double-check WITH the DisableJumpDuringLink 0x20000 leg (W2's TODO(W5)
resolved — MovementParameters now flows), ModifyInterpretedState
gating, CurCell-null tail, AddToQueue with the real ContextId;
StopInterpretedMotion's post-stop Ready node + raw-mirror RemoveMotion.
Legacy overloads + ApplyMotionToInterpretedState DELETED. The funnel's
public surface unchanged (183-case suite compiles + passes as-is).
DoMotion 0x00528d20 verbatim: cancel_moveto interrupt; SetHoldKey(key,
cancelMoveToBit) BEFORE adjust_motion; params re-default for the
interpreted call; combat-stance gates on the ORIGINAL id (Crouch/Sit/
Sleep → 0x3f/0x40/0x41; & 0x2000000 → 0x42 outside NonCombat); action
depth cap ≥6 → 0x45; raw mirror ORIGINAL id. StopMotion 0x00528530
mirror shape. StopCompletely 0x00527e40 with the A9 snapshot quirk
(motion_allows_jump on the OLD forward command, stashed in the queued
node) + the J9 fix (sidestep/turn SPEEDS untouched — the 1.0 resets
were a divergence). PerformMovement flushes zero-tick completions after
every dispatched op via the new CheckForCompletedMotions seam
(0x0050fe30) — bound App-side per entity (remotes via
EnsureRemoteMotionBindings, player at the sequencer bind site).
PORT DISCOVERY (not in the W0 pins): retail's DoInterpretedMotion
RESULT gates both add_to_queue AND the state write — a void sink let
the style dispatch's apply-only failure clobber ForwardCommand before
the forward axis read it, regressing 74/183 live-trace cases.
IInterpretedMotionSink.ApplyMotion/StopMotion now return bool
(documented on the interface with the raw anchors); one funnel
assertion corrected with raw-line citations (airborne ForwardCommand
ends at Falling under the fully-wired verbatim algorithm).
62 new gate-table tests. Full suite: 3,729 passed.
Implemented by a dedicated agent against the W0-pinned spec; seam
bound + suite independently re-verified by the orchestrator.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Port the inbound funnel verbatim into MotionInterpreter:
- MoveToInterpretedState (0x005289c0): raw-state style adopt, FLAT
copy_movement_from overwrite, apply, then action replay under the
15-bit server_action_stamp wraparound gate (local player skips its
own autonomous echoes).
- ApplyInterpretedMovement (0x00528600): my_run_rate cache from
RunForward speed, then retail dispatch order style -> forward-or-
Falling -> sidestep(-stop) -> turn(-stop), turn early-return.
- DispatchInterpretedMotion (0x00528360): contact-gated sink dispatch
(IInterpretedMotionSink = the GetObjectSequence backend the App
implements); blocked non-action motions take the apply-only path —
retail's real mechanism behind K-fix17's 'airborne remotes keep
their cycle' empirical guard.
- contact_allows_move REWRITTEN VERBATIM from the real 0x00528240
(pseudo-C 305471): Falling/0x40000011 + turns always allowed,
non-creature weenies + no-gravity bypass, else Contact+OnWalkable.
The previous body conflated jump_charge_is_allowed (0x00527a50)
posture checks — the 2026-06-04 deep-dive divergence, now retired.
Six tests that pinned the misattributed behavior corrected
(grounded posture does NOT block motion; airborne accepts
Falling/turns only).
- IWeenieObject.IsCreature (default true) for the gate's non-creature
bypass.
Conformance harness (the user-requested 'prove it equals retail'
apparatus, layer 1): RetailObserverTraceConformanceTests parses the
LIVE cdb trace of a retail observer (Fixtures/l2g-observer-trace.log,
captured via tools/cdb/l2g-observer.cdb) into 183 golden cases —
each [MTIS] input state replayed through our funnel must produce
retail's exact [DIM] dispatch sequence. 183/183 conformant, including
the airborne jump case (replayed contact-free; pre-gate vs post-gate
accounting + HitGround second-pass truncation documented in-test).
13 synthetic funnel tests cover the branches the trace missed
(actions, stamps, longjump, sidestep).
GameWindow integration (S2b) follows; funnel not yet wired.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>