diag(motion): #39 — per-tick [CURRNODE] for sequencer node identity

Visual-verify of fix #2 (commit 863d96b) showed [SCFULL] correctly reports
currNodeIsCyclic=True after each direct Walk↔Run SetCycle (the link is
removed and _currNode is set to _firstCyclic). User report still:

- Animation continues running visually after Shift toggle to Walk
- Body slows ("speed decreases"), causing rubber-banding
- Adding a turn motion in that state makes the cycle finally transition
  to walking

So either:
- _currNode is reset to a stale node BETWEEN SetCycle and Advance
- _currNode is correctly on the new cycle but its AnimRef is wrong
  (e.g., the same Animation as the previous cycle, dat-side issue)
- BuildBlendedFrame reads from somewhere other than _currNode

Adds CurrentNodeDiag + FirstCyclicAnimRefHash properties on
AnimationSequencer that expose the active node's Animation
identity-hash, IsLooping, Framerate, frame range, and FramePosition.
TickAnimations logs them on every SEQSTATE tick (1 Hz throttle, gated
on ACDREAM_REMOTE_VEL_DIAG=1).

The [CURRNODE] line with animRef vs firstCyclicAnimRef proves whether
_currNode is actually on the new cycle's anim or has drifted to
something else. Compared across SetCycle SCFULL log lines + the
following CURRNODE ticks, we can see the exact moment the cycle
diverges from what SetCycle set.

No code-behavior changes. Pure read-only instrumentation. Per
Phase 4.5 of systematic-debugging — STOP attempting fixes; gather
evidence first.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Erik 2026-05-06 08:17:56 +02:00
parent 863d96bb23
commit bb026b7991
2 changed files with 50 additions and 0 deletions

View file

@ -6805,6 +6805,23 @@ public sealed class GameWindow : IDisposable
System.Console.WriteLine(
$"[SEQSTATE] guid={serverGuid:X8} CurrentMotion=0x{ae.Sequencer.CurrentMotion:X8} "
+ $"CurrentSpeedMod={ae.Sequencer.CurrentSpeedMod:F3}");
// #39 fix-3 evidence (2026-05-06): CURRNODE proves
// whether _currNode is actually on the cycle (anim
// ref hash matches FirstCyclic) or stuck somewhere
// else. SCFULL captures _currNode==_firstCyclic only
// at SetCycle return; this captures it per render
// tick so we can see if something resets it later.
var d = ae.Sequencer.CurrentNodeDiag;
int firstHash = ae.Sequencer.FirstCyclicAnimRefHash;
System.Console.WriteLine(
$"[CURRNODE] guid={serverGuid:X8} "
+ $"animRef=0x{d.AnimRefHash:X8} firstCyclicAnimRef=0x{firstHash:X8} "
+ $"isOnCyclic={d.AnimRefHash == firstHash && firstHash != 0} "
+ $"isLooping={d.IsLooping} fr={d.Framerate:F2} "
+ $"frame=[{d.StartFrame}..{d.EndFrame}] "
+ $"pos={d.FramePosition:F2} qCount={d.QueueCount}");
rmDiag.LastSeqStateLogTime = nowSec;
}
}