docs(B.6): record Slice 1 trace findings — ACE sends mtRun=0.00, no UP echo

Captured a live ACDREAM_PROBE_AUTOWALK trace double-clicking +Je from
~3.5m. Findings folded into the spec's State at design freeze section:

1. Wire parser is correct (matches ACE MoveToObject.Write +
   MoveToParameters.Write byte-for-byte).
2. ACE sends mtRun=0.00. Not a parser bug — that's the wire value.
   Retail's apply_run_to_command (0x00527BE0) fell back to the
   player's own rate; our Slice 2 needs the same fallback chain.
3. Player position never changed during the entire trace — current
   behavior is pure no-op on the inbound MoveToObject (literally
   ignored, as our code at OnLiveMotionUpdated:3289 suggests).
4. ACE does NOT broadcast UpdatePosition for the local player during
   auto-walk. Definitively kills Option C — nothing to blend with.
   Local body must drive itself.

The trace validates the spec's Option A path. Slice 2 implementation
can proceed without further wire-format guessing.
This commit is contained in:
Erik 2026-05-14 18:45:17 +02:00
parent 1b4f3bac6b
commit d82b0648b5

View file

@ -379,8 +379,44 @@ infrastructure.
`CPhysicsObj::MoveToObject` on the local player's body. Option C
(server-position-blend) is not retail-faithful and is no longer
considered.
- **Next session entry point:** Slice 1 — add the
`ACDREAM_PROBE_AUTOWALK` diagnostic as the baseline, run a failed
auto-walk reproduction for a clean trace, then proceed to Slice 2
(`PlayerMovementController.BeginServerAutoWalk` + `RemoteMoveToDriver`
reuse for the local player).
- **Slice 1 shipped 2026-05-14** (`eda8278` + `1b4f3ba`):
`ACDREAM_PROBE_AUTOWALK` diagnostic + DebugPanel checkbox.
### Trace-captured findings (post-Slice-1)
A live trace captured at Holtburg with the probe enabled —
double-clicking `+Je` (a remote player at `(111.34, 5.96, 94.01)` in
cell `0xA9B40021`) from ~3.5 m away, 4 successive Use sends. Findings:
1. **Parser confirmed correct.** Each `[autowalk-mt]` line reads
`mt=0x06 isMoveTo=True moveTowards=True
path=cell=0xA9B40021,xyz=(111.34,5.96,94.01),minDist=0.00,objDist=0.50
mtSpd=1.00 mtRun=0.00`. Matches ACE's
`MoveToObject.Write` + `MoveToParameters.Write` byte-for-byte.
2. **ACE sends `mtRun=0.00`** — not a parser bug. ACE's
`Player_Move.MoveTo` default for unspecified `runRate` is `0.0f`,
and the call into MoveToObject uses that wire value directly. Retail
decomp at `0x005245e9` copies the wire value into
`motion_interpreter->my_run_rate`; if 0, the local MoveToManager
falls back to the player's own run-rate via
`CMotionInterp::apply_run_to_command` (`0x00527BE0`).
3. **Player position never changed** during the entire trace. All
`[autowalk-up]` lines after the 4 Use sends report
`pos=(112.32, 9.36, 94.00)` verbatim — current behavior is pure
no-op on the inbound MoveToObject.
4. **ACE does NOT broadcast `UpdatePosition` for the local player
during the auto-walk.** This kills Option C even more firmly than
the retail decomp did. The local body has to drive itself.
5. **Slice 2 must handle `mtRun == 0.0`** — fall back to the player's
own current run rate. The trace also captured `fwdSpd=2.86` for
the user's normal running before the auto-walk attempt — that's
the server-echoed `ForwardSpeed`, available as a recent-history
source for the fallback. Default `1.0` if no echo yet.
### Next session entry point
Slice 2: add `PlayerMovementController.BeginServerAutoWalk` /
`EndServerAutoWalk` + per-tick steering via `RemoteMoveToDriver`-style
heading + arrival. Wire in `GameWindow.OnLiveMotionUpdated` with the
`mtRun=0` fallback chain. Suppress user-input motion while
auto-walking; cancel on movement-key press.