fix(#170): armed moveto always ticks UseTime — the SERVERVEL branch starved the chase
The "sustain the run" residual. The handoff's "Ready stop-node backlog drains a beat slower than retail" framing was DISPROVEN: a new full-stack offline harness (RemoteChaseEndToEndHarnessTests — real MoveToManager + MotionInterpreter + AnimationSequencer + MotionTableDispatchSink + the manual omega integration, wired field-for-field like EnsureRemoteMotionBindings and ticked in TickAnimations' exact phase order) proves the Core turn/run/drain pipeline healthy: the chase turn completes in <1 s both directions, BeginMoveForward installs per arm, the run sustains across re-arms and attack swings, and pending_motions fully empties (retail cdb invariant add_to_queue == MotionDone). The real mechanism (launch-drainq.log, corrected per-guid attribution — the previous session's timeline mis-attributed [mvto] lines that fire in the network phase): funnel per chasing scamp was 16 mt-6 arms -> 11 dispatched turns -> ONE BeginMoveForward. Any NPC receiving UpdatePositions gets HasServerVelocity=true (synthesized from position deltas even when the wire carries no velocity), and the grounded per-tick branch routed those to the SERVERVEL leg, which SKIPS MoveToManager.UseTime — [npc-tick] literally logged "branch=SERVERVEL (skips UseTime) mtState=MoveToObject". The armed moveto was starved for exactly the duration of the server-side chase: legs stayed in Ready while the body glided on synthesized velocity (the #170 slide); the manager only woke in UP-silent gaps (creature stopped server-side) and its stale-heading turn was interrupted by the next UM before reaching BeginMoveForward. Retail runs MovementManager::UseTime UNCONDITIONALLY every tick (CPhysicsObj::UpdateObjectInternal 0x005156b0, call @0x00515998) and has no wire-velocity leg-driver anywhere; between UPs a moveto-driven body translates from the motion state (get_state_velocity) with UP hard-snaps correcting drift. Fix: an armed moveto (MovementTypeState != Invalid) always takes the MOVETO leg; SERVERVEL remains only as the legacy fallback for entities without a moveto (scripted paths / missiles). Register: TS-41 (the narrowed SERVERVEL stopgap), TS-42 (drain-order divergence also pinned this session: acdream drains AnimDone->MotionDone AFTER HandleTargetting/MoveTo.UseTime; retail's process_hooks @0x00512d3d runs BEFORE TargetManager/MovementManager in UpdateObjectInternal — one frame of extra latency, R6 scope). New conformance: RemoteChaseEndToEndHarnessTests (3 scenarios + theory) + RemoteChaseDrainBisectTests (the drain-chain pin; its first run also demonstrated the TS-40 InWorld=false link-strip wedge shape — harness bodies must replicate the live RemoteMotion construction). ISSUES #170 updated (awaiting user visual gate; probes stay until then); handoff doc superseded-note added. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
e744192361
commit
1051fc83c6
6 changed files with 811 additions and 20 deletions
|
|
@ -48,25 +48,33 @@ Copy this block when adding a new issue:
|
|||
|
||||
## #170 — Remote creature chase+attack renders wrong vs retail (glide, over-frequency, uniform attack anims)
|
||||
|
||||
**Status:** OPEN — **PARTIAL FIX landed `427332ac` (2026-07-04); residual = "sustain the run".**
|
||||
Root-caused end-to-end with live retail cdb tracing + acdream probes. The chase run
|
||||
cycle is manufactured client-side from mt-6 (`HandleUpdateTarget → MoveToObject_Internal
|
||||
→ TurnToHeading node completes via UseTime → BeginMoveForward → RunForward substate`);
|
||||
`BeginTurnToHeading` bails while `CMotionInterp.motions_pending` is non-empty
|
||||
(retail-faithful). acdream's `pending_motions` EXPLODED to ~1.3M entries because the
|
||||
NPC per-tick called `apply_current_movement` EVERY FRAME (re-dispatching stance+attack+
|
||||
stops), so `MotionsPending()` stayed permanently true → the chase turn never started →
|
||||
no RunForward → slide. FIX = delete the per-frame `apply_current_movement` (GameWindow
|
||||
~9992; retail dispatches per UM, `add_to_queue==MotionDone`). VERIFIED: flood 1.3M→~1,
|
||||
"stuck attack" GONE (user-confirmed), run installs (BeginMoveForward 1→10). **RESIDUAL
|
||||
(next session):** still blocked motionsPending=True 94% by a `Ready` (0x41000003)
|
||||
stop-node backlog that drains a beat slower than retail (~10 run-starts vs retail 21 →
|
||||
twitches+glides). Fix the R2/R3 `Ready`-stop DRAIN so acdream fully empties like retail
|
||||
(retail is the oracle — cdb the drain). **SSOT + pickup:**
|
||||
**Status:** OPEN — **residual fix landed 2026-07-04 ("sustain the run" — SERVERVEL
|
||||
starvation); AWAITING VISUAL GATE.** Fix #1 (`427332ac`): the per-frame
|
||||
`apply_current_movement` re-dispatch flooded `pending_motions` to ~1.3M → deleted;
|
||||
flood 1.3M→~1, "stuck attack" gone (user-confirmed), run installs 1→10. Fix #2 (this
|
||||
session): **the "slow Ready drain" framing was WRONG** — a full-stack offline harness
|
||||
(`RemoteChaseEndToEndHarnessTests`, real MoveToManager + MotionInterpreter +
|
||||
AnimationSequencer + omega integration in GameWindow's exact tick order) proved the
|
||||
Core drain/turn/run pipeline healthy (turn completes <1 s, run sustains, add==done).
|
||||
Corrected per-guid log attribution (launch-drainq.log) showed the REAL funnel: 16 arms
|
||||
→ 11 turns dispatched → **1 run install**, because the per-tick branch arbitration
|
||||
routed any UP-receiving NPC to the SERVERVEL leg (`HasServerVelocity` synthesized from
|
||||
position deltas) which **skips `MoveToManager.UseTime`** — the armed moveto was starved
|
||||
for exactly the duration of the server-side chase (`[npc-tick] branch=SERVERVEL (skips
|
||||
UseTime) mtState=MoveToObject`), legs stayed Ready while the body glided on synthesized
|
||||
velocity; the manager only woke in UP-silent gaps and was interrupted by the next UM.
|
||||
Retail runs `MovementManager::UseTime` UNCONDITIONALLY per tick
|
||||
(`CPhysicsObj::UpdateObjectInternal` 0x005156b0 @0x00515998) and has no wire-velocity
|
||||
leg-driver. FIX: an armed moveto (`MovementTypeState != Invalid`) always takes the
|
||||
MOVETO leg; SERVERVEL remains only for non-moveto entities (register TS-41; drain-order
|
||||
one-frame divergence also pinned + filed as TS-42). **SSOT + pickup:**
|
||||
`docs/research/2026-07-04-170-creature-run-handoff.md` +
|
||||
`docs/research/2026-07-04-170-pickup-prompt.md`. SUPERSEDES the earlier
|
||||
MovementManager-coexistence hypothesis (`eb423fb7`, wrong) and the velocity fix
|
||||
(`d2ccc80e`, correct but position-only). #159 was a red herring here.
|
||||
`docs/research/2026-07-04-170-pickup-prompt.md` (residual sections superseded by this
|
||||
entry). SUPERSEDES the earlier MovementManager-coexistence hypothesis (`eb423fb7`,
|
||||
wrong shape — but the starvation IS a coexistence bug at the tick-arbitration altitude)
|
||||
and keeps the `d2ccc80e` velocity fix. #159 was a red herring here. NEXT: user visual
|
||||
gate (retail side-by-side, chase a fleeing player) → then strip the #170 probes
|
||||
(`s_mvtoDiag`, `s_drainDiag`, `[npc-tick]`, `UM ↳ actions`) and close.
|
||||
**Severity:** MEDIUM (visual — remote combat / aggro)
|
||||
**Filed:** 2026-07-03 (user retail side-by-side during the R5-V2 visual gate)
|
||||
**Component:** animation, remote entity, combat
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue