Gait: FIX replicant statue + jerky walk -- replicant-tuned trn entry (regression)

Two more master rules in the trn entry broke replicants:
(1) the LOCKSTEP body weld: a replicant never runs the body SM ('joints only',
    mech4.cpp:1989), so the first trn entry armed the body to state 4 where it stuck
    forever -- bodyAnimationState==Standing then blocked EVERY later trn entry (the
    peer 'rotates as a statue').  Replicants now skip the weld gate and do not arm
    the inert body channel.
(2) today's authentic full [0,standSpeed] entry range: a replicant's DERIVED speed
    sweeps that band on every dead-reckoned start/stop with derived turnDemand
    pinned +-1, so trn kept arming mid-locomotion and speed-exiting (jerky walking).
    Replicants keep the narrow near-zero entry gate (the pre-#64b accommodation).
Masters keep the authentic dispatcher (full range + lockstep weld) unchanged. [T3
replicant accommodation / T1 master logic]

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
arcattack
2026-07-14 09:19:12 -05:00
co-authored by Claude Fable 5
parent 992aedece8
commit 02ce55194e
+18 -3
View File
@@ -613,11 +613,25 @@ Scalar
// cases and the port never per-frame-clears the latch), so gating entry on
// it here would wrongly block trn after every walk. Omitted by design;
// see locomotion.md "turn-in-place dispatcher".
// REPLICANT accommodation (regression fix, 2026-07-14): the dispatcher
// above is MASTER-perf logic; a replicant feeds this SM DERIVED signals
// (speed/turn from the dead-reckon stream, mech4.cpp:1948) and runs ONLY
// the leg channel. Two master rules break it:
// (1) the body weld -- a replicant never runs the body SM, so arming the
// body to 4 sticks bodyAnimationState there forever and BLOCKS every
// later trn entry (the peer "rotates as a statue");
// (2) the full [0,standSpeed] entry -- the derived speed sweeps that band
// on every dead-reckoned start/stop with turnDemand pinned +-1, so
// trn keeps arming mid-locomotion and speed-exiting (jerky walking).
// Replicants: no body weld / no body arm (channel is inert, mj=0) and the
// narrow near-zero entry gate (the pre-#64b accommodation). [T3]
const int trnIsRepl = (GetInstance() == ReplicantInstance);
const Scalar trnEntryMax = trnIsRepl ? standSpeed * 0.25f : standSpeed;
if (hasCrashSet != 0 && mppr != 0
&& commandedSpeed >= ZeroSpeed && commandedSpeed <= standSpeed
&& commandedSpeed >= ZeroSpeed && commandedSpeed <= trnEntryMax
&& (mppr->turnDemand > 0.05f
|| mppr->turnDemand < -0.05f)
&& bodyAnimationState == StandingAnimation) // weld: enter only when BOTH can
&& (trnIsRepl || bodyAnimationState == StandingAnimation)) // weld: masters only
{
// LOCKSTEP (task #64): arm BOTH channels on the same frame. Arming
// only the leg let the body enter walk on its own schedule ~7-20
@@ -631,7 +645,8 @@ Scalar
// (the authentic dispatcher in the un-decompiled 0x4a9b5c gap arms
// both -- the body's case-4/finish machinery is dead code otherwise).
SetLegAnimation(4); // turn-in-place (trn), channel A
SetBodyAnimation(4); // channel B, same frame [lockstep]
if (!trnIsRepl)
SetBodyAnimation(4); // channel B, same frame [lockstep, masters]
goto advance_normally;
}
if (ZeroSpeed <= commandedSpeed)