Commit graph

2 commits

Author SHA1 Message Date
Erik
c06b6c51e1 fix(motion): full queue reset on locomotion-cycle direct transitions
When AnimationSequencer.SetCycle transitions between forward-locomotion
cycles (Walk↔Run, Walk↔WalkBackward, etc.) — i.e. when both old and new
motion's low byte is in {0x05 WalkForward, 0x06 WalkBackward, 0x07
RunForward} — do a full queue drain + _currNode/_firstCyclic reset
(matching the existing skipTransitionLink branch) instead of just
ClearCyclicTail. Without this, _currNode is left pointing into the
previous cycle's non-cyclic head (link frames from the prior Ready→walk
transition), and the visible legs continue playing those head frames
before reaching the new run cycle.

Investigation findings (cdb live trace of retail at
tools/cdb-scripts/walk_run_motion_trace.log):

  Retail's actual approach is "additive add_to_queue with no truncate" —
  MotionTableManager handles the natural progression via per-tick
  CheckForCompletedMotions / remove_redundant_links cleanup. Acdream
  doesn't have that machinery, so this fix is the closest viable
  emulation: force the queue back to a clean state and rebuild from
  scratch on the locomotion-cycle transition.

User-reported symptom this addresses (walk→run direct transition,
release shift while W held): visible animation cycle did not switch
until next motion event. Verified via FWD_WIRE + SETCYCLE diags that
both ACE and our SetCycle are firing correctly on the transition.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-03 17:00:55 +02:00
Erik
b1d8e122ed research(motion): cdb live trace of retail walk-to-run transition
Live cdb trace of retail acclient.exe (v11.4186, PDB-matched) capturing
the exact function call sequence for a direct walk-to-run motion
transition where the user holds shift+W (walk) then releases SHIFT
while still holding W (transition to run).

Trace bps on:
- CPhysicsObj::DoInterpretedMotion (0x0050EA70)
- CPartArray::DoInterpretedMotion  (0x00518750)
- MotionTableManager::PerformMovement (0x0051C0B0)
- MotionTableManager::add_to_queue (0x0051BFE0)
- MotionTableManager::truncate_animation_list (0x0051BCA0)
- CMotionTable::DoObjectMotion (0x00523E90)
- CMotionTable::StopObjectMotion (0x00523EC0)

Captured trace at tools/cdb-scripts/walk_run_motion_trace.log shows
the precise walk-to-run sequence:

  [79] CPhysicsObj::DoInterpretedMotion: motion=45000005   walk start
  [82] CMotionTable::DoObjectMotion: motion=45000005
  [83] MotionTableManager::add_to_queue: arg1=45000005 arg2=00000001

  [89] CPhysicsObj::DoInterpretedMotion: motion=44000007   run start
  [92] CMotionTable::DoObjectMotion: motion=44000007
  [93] MotionTableManager::add_to_queue: arg1=44000007 arg2=00000001

  [104] CMotionTable::StopObjectMotion: motion=44000007    run end

Critical structural finding for #L.4-walk-run:

  Retail does NOT call truncate_animation_list during the walk→run
  transition. truncate_animation_list never fires in the entire 200-hit
  trace. Retail also does NOT call StopObjectMotion(WalkForward) before
  add_to_queue(RunForward). Retail just appends the new motion to the
  queue and lets MotionTableManager (and its CheckForCompletedMotions /
  remove_redundant_links per-tick cleanup, not yet traced) handle the
  natural progression.

  acdream's AnimationSequencer.SetCycle aggressively calls
  ClearCyclicTail() at line 430 BEFORE enqueuing the new cycle, which
  destroys the in-flight walk cycle's frames. The new run cycle is
  enqueued but _currNode is left in a state that doesn't smoothly
  continue — visible to the user as "it just blips forward walking,
  AS SOON as press another key like turning, its starts running"
  (the next motion event re-fires SetCycle which finally aligns state).

  Fix is a structural refactor of SetCycle to mirror retail's
  "additive queue with auto-cleanup" semantics. Out of scope for this
  research commit; filed as #L.4 in the next ISSUES.md entry.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-03 16:54:34 +02:00