From 02ce55194edaee13c2cb333e4fd2761befe33e66 Mon Sep 17 00:00:00 2001 From: arcattack Date: Tue, 14 Jul 2026 09:19:12 -0500 Subject: [PATCH] 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 --- game/reconstructed/mech2.cpp | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/game/reconstructed/mech2.cpp b/game/reconstructed/mech2.cpp index 152643b..4cf0bc1 100644 --- a/game/reconstructed/mech2.cpp +++ b/game/reconstructed/mech2.cpp @@ -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)