docs(issues): file #45 (local sidestep walk too slow); update #39 progress

#45 — local +Acdream slow-strafe walking renders too slow. User
observed during fix #5 visual verify of #39: the observer-side fix
landed, then the user noticed the matching animation on the local
player was also playing at sub-walk cadence. Likely the same
SidestepAnimSpeed (1.25) vs WalkAnimSpeed (3.12) mismatch as fix #5
but on the local UpdatePlayerAnimation path. Filed for separate
investigation.

#39 — added "Progress 2026-05-06" section listing the five-commit
fix sequence (8fa04af863d96bbb026b72653b30cc62e1c349ba65), the wire-level finding that retail genuinely does NOT
broadcast on Shift toggle (refuting the earlier confused trace
analysis), the user-verified working cases (1/2/4/5) and the
residual items (latency from 500ms UM grace, direction-flip cases
3/6/7 not yet explicitly verified).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Erik 2026-05-06 08:45:50 +02:00
parent 349ba65f3e
commit 69cdd7f492

View file

@ -130,41 +130,33 @@ the same direction. Add a `LastUMUpdateTime` grace window (e.g.
- No spurious cycle thrashing during turning while running (ObservedOmega
doesn't trigger velocity-bucket changes).
**Progress 2026-05-06 — candidate fix INEFFECTIVE per visual verify:**
**Progress 2026-05-06 — Shift-toggle cases (#1, #2, #4, #5) fixed; user-verified:**
Candidate fix `8fa04af` shipped a velocity-fallback path
(`LastUMTime` + `ApplyPlayerLocomotionRefinement`), built on the
hypothesis that retail does not send a fresh MoveToState on
HoldKey-only changes. **That hypothesis is refuted.** Visual-verify
log (`launch-39-candidate.log`) shows:
Five-commit sequence on this branch (`claude/determined-solomon-d0356d`):
- `[FWD_WIRE]` for retail-driven actor `0x50000001` contains many
direct Walk↔Run UM transitions (`0x44000007 ↔ 0x45000005`). ACE
IS broadcasting UMs on Shift toggle.
- `[SETCYCLE]` fires correctly for each transition; `Sequencer.CurrentMotion`
cycles through Walk/Run/Turn/Sidestep at varied sample moments.
- `[UPCYCLE_PLAYER]` never fires (UM grace correctly suppresses it
while UMs arrive at >2 Hz).
- User report: "blips forward in walking animation" — the visible
cycle stays in Walk despite the wire / sequencer saying Run.
| Commit | Effect |
|---|---|
| `8fa04af` | First candidate — added `RemoteMotion.LastUMTime` + `ApplyPlayerLocomotionRefinement` with 500 ms UM grace + forward-direction hysteresis. **Ineffective** because the call site lived in dead code for player remotes. |
| `863d96b` | Skip transition link in SetCycle for direct cyclic-locomotion → cyclic-locomotion. **Reduces queue accumulation** (qCount climbs slower); not the actual case-#1 fix but architecturally correct. |
| `bb026b7` | Per-tick `[CURRNODE]` diagnostic — exposed that `_currNode` was correctly tracking SetCycle's intent and so the bug was elsewhere. Read-only. |
| `2653b30` | **Wire `ApplyServerControlledVelocityCycle` into the L.3 M2 player-remote path.** Found via the diag — the existing call site at `OnLivePositionUpdated` line ~3879 was unreachable for players because the L.3 M2 routing returns at line 3755. New synth-velocity computation + call inserted in the player branch. **User-verified working** for forward Run↔Walk via Shift toggle. |
| `cc62e1c` | Handle backward (`CurrentSpeedMod < 0` → preserve negative sign) and sidestep (low byte 0x0F / 0x10 → keep motion ID, refine magnitude). Backward regression resolved. |
| `349ba65` | Use `SidestepAnimSpeed` (1.25) instead of `WalkAnimSpeed` (3.12) when computing sidestep magnitude — fix #4's mapping was 2.5× too small for slow strafe. |
So the bug is **downstream of `Sequencer.CurrentMotion`** — same as
2026-05-03 hypothesis F. Most likely `_currNode` lands on the
walk-to-run transition link after `SetCycle`, the link plays as a
walking-like pose, and `Advance` never advances past it to the
run cycle. `[SCFULL]` confirms `currNodeIsCyclic=False` after every
Walk↔Run transition.
**Wire-level finding refuting the original ISSUES.md root-cause hypothesis: Earlier diagnostic claims that ACE broadcasts UMs on Shift toggle were misread.** A clean test (`launch-39-diag2.log`) holding W and toggling Shift while held shows `[FWD_WIRE]` for retail-driven actor only emitting `Ready ↔ Run` transitions — no Walk wire transitions at all, despite a clear walk-pace ↔ run-pace shift visible in `[VEL_DIAG]`. So retail's outbound DOES go silent on HoldKey-only changes. The earlier launch's many Walk↔Run `[FWD_WIRE]` lines came from W press/release cycles with Shift held continuously — different scenarios.
The candidate fix code is left in place — the infrastructure is
harmless (UM grace blocks all calls in normal flow) and may be
useful for cases #2#7 follow-up if those turn out to need
velocity fallback. But it does NOT close case #1.
**Verified working (user, 2026-05-06):**
**Next investigation step:** target `AnimationSequencer.Advance`
queue-handling for cyclic→cyclic direct transitions. See
[findings-static.md](research/2026-05-06-locomotion-cycle-transitions/findings-static.md)
§"Where the bug actually lives" + §"What to do next" for the
specific code paths and recommended diagnostic additions.
- Forward Run↔Walk via Shift toggle (case #1)
- Backward Walk slow↔fast via Shift toggle (case #2) — animation matches direction, no rubber-band
- Strafe-left / strafe-right slow↔fast via Shift toggle (cases #4 / #5) — cadence visibly changes
**Residual / not yet verified:**
- "Not as fast as retail" — ~500 ms `UmGraceSeconds` window adds latency on top of the UP cadence (510 Hz). Could be tuned shorter once cases #3 / #6 / #7 are validated.
- Direction-flip cases (#3 W↔S, #6 A↔D, #7 W↔A/D) — believed to work via direct UM, not explicitly verified yet.
**New related issue filed: #45** — local-player slow-strafe-walk renders too slow. Same `SidestepAnimSpeed` vs `WalkAnimSpeed` mismatch pattern as fix #5, but on the local-player render path (`UpdatePlayerAnimation`), not the observer side.
## #42 — [DONE 2026-05-05 · ec59a08] Airborne XY drift on observed player remote jumps (~1 m horizontal offset over arc)
@ -1266,6 +1258,40 @@ If hypothesis (a) is correct, this issue effectively rolls into **#28** — the
---
## #45 — Local +Acdream sidestep walking renders too slow
**Status:** OPEN
**Severity:** LOW (visible animation cadence; not a correctness/wire bug)
**Filed:** 2026-05-06
**Component:** physics / animation (local player path: `PlayerMovementController``UpdatePlayerAnimation``AnimationSequencer.SetCycle`)
**Description:** When the local +Acdream character strafes (A or D held) at slow pace (no Shift), the visible leg cycle for the local player plays slower than retail's equivalent. Fast strafe (with Shift held) appears correct. Observed by user 2026-05-06 immediately after fix #5 (commit `349ba65`) landed the matching fix on the *observer-side* `ApplyPlayerLocomotionRefinement` for retail-driven remotes.
**Root cause / status:**
Likely the same constant mismatch as fix #5: the local player's sidestep speedMod was being computed off `WalkAnimSpeed` (3.12 m/s) where it should use `SidestepAnimSpeed` (1.25 m/s). Because the wire-emitted `SideStepSpeed` already encodes a 0.5× multiplier (per ACE `MovementData.cs:124-131`), dividing the wrong base on either send or render side compresses the slow strafe to a sub-walk cadence.
To confirm: look at `UpdatePlayerAnimation` in `src/AcDream.App/Rendering/GameWindow.cs` (~line 7000) and trace where the strafe speedMod is sourced from. Either the speedMod passed to `SetCycle` is too small, or the framerate computation downstream applies an extra 0.5×.
Cross-reference:
- `MotionInterpreter.SidestepAnimSpeed = 1.25f`
- `MotionInterpreter.WalkAnimSpeed = 3.12f`
- ACE `MovementData(MoveToState)`: `interpState.SidestepSpeed = speed * 3.12f / 1.25f * 0.5f`
**Files:**
- `src/AcDream.App/Rendering/GameWindow.cs``UpdatePlayerAnimation` (~line 7000)
- `src/AcDream.App/Input/PlayerMovementController.cs` — wire-builder for outbound MoveToState (sidestep path)
- `src/AcDream.Core/Physics/MotionInterpreter.cs:243-247` — anim-speed constants
**Acceptance:**
- Local +Acdream slow strafe (A or D, no Shift) plays at the same visible cadence as retail's slow strafe in a side-by-side comparison.
- Local fast strafe (A or D + Shift) does not regress.
- Forward / backward / run cycles do not regress.
---
---
# Recently closed