fix(B.6+B.7): bump AutonomousPosition heartbeat 1Hz -> 10Hz while moving

User correctly called out: 'why workarounds? Nothing wrong with ACE,
our client is wrong.' Three of the four workarounds in B.6/B.7
(arrival margin, re-send-on-arrival, AP flush on arrival) exist
because our client sends 1Hz position heartbeat. Retail sent every
tick. ACE's CreateMoveToChain polls WithinUseRadius every ~0.1 s
using the latest Player.Location — at 1Hz we leave up to 1 s of
stale position data on the server, so ACE rejects re-sent actions
as still-out-of-range.

Fix: bump heartbeat to ~10 Hz when the body is actively moving
(auto-walk OR user pressing W/A/S/D). Idle still 1 Hz.
ACE sees us approach in near-real-time; server-side MoveToChain
converges normally; CreateMoveToChain's own callback fires the
action when in radius — no client-side re-send needed.

This SHOULD make the existing workarounds redundant:
  * Arrival margin (0.2m) — can shrink toward 0 since position
    drift is bounded by 100ms instead of 1s
  * Re-send on arrival — ACE's chain completes on its own
  * AP flush on arrival — included in normal heartbeat

Plan to retire them in a follow-up commit once we verify the
heartbeat bump alone is enough.
This commit is contained in:
Erik 2026-05-15 11:39:14 +02:00
parent 64c9793248
commit 301281d8d0

View file

@ -1140,7 +1140,20 @@ public sealed class PlayerMovementController
// early return) skips Update entirely, so reaching this line implies
// we're in a valid in-world pose.
_heartbeatAccum += dt;
HeartbeatDue = _heartbeatAccum >= HeartbeatInterval;
// B.6+B.7 (2026-05-15): bump heartbeat from 1 Hz to ~10 Hz while
// the body is actively moving (auto-walk OR user pressing W/A/S/D).
// ACE's server-side CreateMoveToChain polls WithinUseRadius every
// ~0.1 s using the latest Player.Location; 1 Hz heartbeats leave
// up to 1 s of stale position data on the server, which meant
// ACE's MoveToChain rejected our re-sent Use action as still
// out-of-range. With 10 Hz updates ACE sees us approaching in
// ~real-time and the server-side chain converges normally —
// retires the arrival-margin / re-send / flush-AP workarounds.
bool activelyMoving = _autoWalkActive
|| input.Forward || input.Backward
|| input.StrafeLeft || input.StrafeRight;
float effectiveInterval = activelyMoving ? 0.1f : HeartbeatInterval;
HeartbeatDue = _heartbeatAccum >= effectiveInterval;
if (HeartbeatDue) _heartbeatAccum = 0f;
// K-fix5 (2026-04-26): local-animation-cycle pacing. Visual rate