From 05303666879ceef7168bcb8065aa901478754c04 Mon Sep 17 00:00:00 2001 From: Joe DiPrima Date: Fri, 7 Aug 2026 16:16:12 -0500 Subject: [PATCH] #142 crouch: the mech is fine -- it is a missing PANEL ANIMATION Benched solo AND in MP on the same chassis: both presses reach DuckRequestMessageHandler, zero drops, SQUAT -> squat clip parked -> RISE. Locomotion is not the bug, and MP is not refusing it. Added an ungated [duck] REQUEST DROPPED receipt at the consumer's silent miss. The squatCapable==0 path skips the consumer entirely AND leaves duckState latched at 1 with NO log today; the posture-gate miss logged only under BT_DUCK_LOG, which no player sets. Neither fired on madcat. What the pilot sees, traced with BT_LAMP_LOG: the button lamp is momentary press feedback, not state -- PRESS -> [lamp] 0x13 <- 0x3c SQUAT -> mech crouches, clip parked RELEASE -> [lamp] 0x13 <- 0x14 <-- while still CROUCHED so crouched and standing look identical. Era testimony corrects the scope: the button should ANIMATE A MECH SYMBOL beside it, standing <-> crouching (operator). Lynx: 'When a mech stops, crouch button lowers its stance and plays crouch animation. Mech is immobilized until crouch is pushed again, and mech rises.' Draco concurs. Two real gaps, neither fixed here: 1. no immobilization while crouched -- nothing gates movement on duckState or the parked leg alarm. NB a driven mech with a parked leg channel is the [skate] signature (#52), so this may not be cosmetic. 2. no stance symbol -- no gauge element draws one, and the decomp carries no crouch/squat/stance/duck graphic string, so it is an authored IMAGE on the secondary MFD; find it in that gauge's element list, not by string. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01NCJQkvq6G2JNrpVbA75tVZ --- game/reconstructed/mech4.cpp | 26 +++++++++++ scratchpad/night13/crouch142.sh | 61 +++++++++++++++++++++++++ scratchpad/night13/crouch142_update.py | 59 ++++++++++++++++++++++++ scratchpad/night13/crouchmp.sh | 63 ++++++++++++++++++++++++++ 4 files changed, 209 insertions(+) create mode 100644 scratchpad/night13/crouch142.sh create mode 100644 scratchpad/night13/crouch142_update.py create mode 100644 scratchpad/night13/crouchmp.sh diff --git a/game/reconstructed/mech4.cpp b/game/reconstructed/mech4.cpp index 9f8e240..51be77e 100644 --- a/game/reconstructed/mech4.cpp +++ b/game/reconstructed/mech4.cpp @@ -4420,6 +4420,32 @@ void // stability, so peers pose the squat for free) and flip the // stability alarm (ducked = 0, risen = 1). The request is // consumed whenever both gates passed, hit or miss. + // #142 RECEIPT (ungated, 1 Hz). A pending duck request that produces + // no posture change is INVISIBLE today: if squatCapable is 0 the + // consumer below is skipped entirely -- no log, and duckState is not + // even consumed, so the latch sticks at 1 forever. The other miss + // (posture not 1/2) logs only under BT_DUCK_LOG, which no player + // sets. Field report (Oracle, night 13): "the light next to it + // always flashes when pressed, but state does not change" -- the + // press reaches the handler and a GATE declines it, exactly the + // shape the eject bug had (#108: EvaluateEjectPermission refusing a + // healthy mech while the lamp still responded). Name the gate. + if (duckState != 0 + && (squatCapable == 0 || (mapPosture != 1 && mapPosture != 2))) + { + static int s_duckDrop = 0; + if ((s_duckDrop++ % 60) == 0) + DEBUG_STREAM << "[duck] REQUEST DROPPED: squatCapable=" + << squatCapable << " posture=" << mapPosture + << " mode=" << MovementMode() + << " legLvl=" << (int)legStateAlarm.GetLevel() + << " myo=" << myomerEffectiveness + << (squatCapable == 0 + ? " <-- no squ/sqd clips: consumer skipped, latch stuck" + : " <-- posture gate") + << "\n" << std::flush; + } + if (duckState != 0 && squatCapable != 0) { if (mapPosture == 1) diff --git a/scratchpad/night13/crouch142.sh b/scratchpad/night13/crouch142.sh new file mode 100644 index 0000000..1c78f19 --- /dev/null +++ b/scratchpad/night13/crouch142.sh @@ -0,0 +1,61 @@ +#!/usr/bin/env bash +# ========================================================================= +# #142 CROUCH does not toggle -- name the gate. +# +# FIELD (Oracle, night 13): "the crouch button did not toggle to display +# crouched ... no state change ... the light next to it always flashes when +# pressed, but state does not change. Remains in stand mode." +# +# That is the EJECT bug's signature: the press reaches the handler (lamp +# responds) and a GATE silently declines it. DuckRequestMessageHandler +# always succeeds -- it just sets duckState=1. The CONSUMER (mech4.cpp) is +# where it dies: +# +# if (duckState != 0 && squatCapable != 0) { +# if (mapPosture == 1) squat; +# else if (mapPosture == 2) rise; +# else if (BT_DUCK_LOG) log; <- only diagnostic, env-gated +# duckState = 0; +# } +# +# squatCapable == 0 skips the whole block: no log, and the latch is not even +# consumed. A new ungated [duck] REQUEST DROPPED receipt covers both misses. +# +# Runs the SAME chassis twice is pointless -- squatCapable is per-model +# ('squ'/'sqd' clips shipped), so sweep several. CROUCH is button 0x13 +# (shipped bindings: left column 0x10-0x15 = map+/map-/IR/CROUCH/searchlight/ +# display). BT_BTNTEST2 exists precisely for "crouch then rise". +# ========================================================================= +set -x +V="${1:-madcat}" +. /c/git/bt411/scratchpad/night6/bench_common.sh +cd /c/git/bt411/content || exit 1 +taskkill //F //IM btl4.exe > /dev/null 2>&1 +sleep 2 +rm -f cr_${V}.log +bt_expert_egg MP.EGG CR.EGG +sed -i "s/^map=.*/map=grass/; s/^time=.*/time=day/; s/^vehicle=.*/vehicle=${V}/" CR.EGG + +( export BT_BTNTEST=0x13,900,960 # CROUCH press + export BT_BTNTEST2=0x13,1500,1560 # and again (toggle back / retry) + export BT_DUCK_LOG=1 BT_GAIT_LOG=1 BT_KEY_NOFOCUS=1 + bt_launch cr_${V}.log CR.EGG 0x03 ) +for i in $(seq 1 60); do grep -aq "btntest" cr_${V}.log 2>/dev/null && break; sleep 2; done +sleep 45 +bt_kill_ours; sleep 2; taskkill //F //IM btl4.exe > /dev/null 2>&1; sleep 2 + +echo "=================== #142 CROUCH vehicle=$V ===================" +echo "--- 1. did the press reach the handler? ---" +grep -a "btntest" cr_${V}.log | head -4 +grep -a "DuckRequest" cr_${V}.log | head -3 +echo +echo "--- 2. THE GATE: why was it dropped? ---" +grep -a "REQUEST DROPPED" cr_${V}.log | head -4 +echo -n "dropped-receipt count: "; grep -ac "REQUEST DROPPED" cr_${V}.log +echo +echo "--- 3. did a posture change actually happen? ---" +grep -aE "\[duck\] (SQUAT|RISE)" cr_${V}.log | head -4 +echo -n "SQUAT/RISE events: "; grep -acE "\[duck\] (SQUAT|RISE)" cr_${V}.log +echo +echo "--- 4. does this chassis even ship the squat clips? ---" +grep -aiE "squatCapable|squ.*clip|sqd" cr_${V}.log | head -4 diff --git a/scratchpad/night13/crouch142_update.py b/scratchpad/night13/crouch142_update.py new file mode 100644 index 0000000..8fa6dae --- /dev/null +++ b/scratchpad/night13/crouch142_update.py @@ -0,0 +1,59 @@ +"""#142 -- correct the report and record what benching established. ASCII only.""" +import sys +sys.path.insert(0, r"C:\git\bt411\scratchpad\night7") +import gitea + +gitea.comment(142, """**RE-SCOPED 2026-08-07 -- the mech crouches fine; this is a missing PANEL ANIMATION.** + +The original report ("the crouch button did not toggle to display crouched ... the light next to +it always flashes when pressed, but state does not change") reads like a locomotion or lamp bug. +Benching says it is neither. + +## What works (benched, `scratchpad/night13/crouch142.sh` + `crouchmp.sh`) + +* SOLO, madcat: both presses reach `DuckRequestMessageHandler`, zero drops, `[duck] SQUAT (posture + 1 -> leg clip 2)` then `squat clip parked`, then `[duck] RISE`. A full toggle cycle. +* MULTIPLAYER, same chassis: identical -- 2 requests, 0 drops, SQUAT + RISE. So the MP path is not + refusing it either. + +A receipt was added at the consumer's silent miss (`[duck] REQUEST DROPPED`, ungated) covering both +gates -- `squatCapable == 0` (which skips the consumer entirely AND leaves `duckState` latched at 1, +with no log at all today) and `mapPosture` not 1/2 (previously logged only under `BT_DUCK_LOG`, +which no player sets). Neither fired on madcat. Chassis without `squ`/`sqd` clips are still +untested; the bench takes a vehicle argument for that sweep. + +## What the pilot actually sees + +The crouch button's LAMP is momentary press feedback, not state. Traced with `BT_LAMP_LOG`: + + PRESS -> [lamp] 0x13 <- 0x3c (lit) + SQUAT -> mech crouches, clip parked + RELEASE -> [lamp] 0x13 <- 0x14 (unlit) <-- while still CROUCHED + PRESS2 -> [lamp] 0x13 <- 0x3c + RISE -> mech stands + RELEASE -> [lamp] 0x13 <- 0x14 + +Crouched and standing are visually identical, so the lamp can never carry posture. + +## What it is SUPPOSED to be (era testimony, this day) + +The operator, correcting the framing: the crouch button is supposed to **animate a MECH SYMBOL next +to the button**, standing <-> crouching. Not a two-state lamp -- a missing animation. + +VGL Lynx: *"When a mech stops, crouch button lowers its stance and plays crouch animation. Mech is +immobilized until crouch is pushed again, and mech rises."* Draco: *"Checks out with my memories."* + +## Two gaps, and the second is the reported one + +1. **No immobilization while crouched.** Nothing in the port gates movement on `duckState` or the + parked leg alarm -- grep of every consumer of both across `game/reconstructed/` finds no + speed/throttle/demand gate. Per Lynx the mech should be immobile until the button is pushed + again. ⚠ Worth checking what a crouched mech that IS driven does today, since the leg clip is + parked -- a moving mech with a parked leg channel is the [skate] signature (#52). +2. **No stance symbol.** No gauge element anywhere in `btl4gau*.cpp` draws a posture/stance icon, + and the decomp has no crouch/squat/stance/duck graphic STRING (only substring false positives: + "existance", "distance"). So it is likely an authored IMAGE element on the secondary/radar MFD + rather than something findable by name -- next step is the secondary MFD's element list in the + binary, not another string search. + +Not fixed. Re-scoped, with the locomotion half cleared and the real target named.""") diff --git a/scratchpad/night13/crouchmp.sh b/scratchpad/night13/crouchmp.sh new file mode 100644 index 0000000..4bfb384 --- /dev/null +++ b/scratchpad/night13/crouchmp.sh @@ -0,0 +1,63 @@ +#!/usr/bin/env bash +# ========================================================================= +# #142 CROUCH in MULTIPLAYER -- solo works, so MP is the variable. +# +# crouch142.sh proved a madcat crouches and rises cleanly SOLO: both presses +# reached DuckRequest, zero REQUEST DROPPED, SQUAT then RISE fired. The +# reporters were in MP, and the wording matters: +# Oracle: "the crouch button did not toggle to DISPLAY crouched ... no state +# change ... the light next to it always flashes when pressed, but +# state does not change. Remains in stand mode." +# +# Three things that could produce that with the mech itself working: +# (a) MP-only refusal -- some gate differs on a networked master +# (b) replication -- master squats, PEER never poses it +# (c) indicator -- mech squats, but the button LAMP / state readout +# never latches, so the pilot sees "stand" +# +# Same chassis as the passing solo run, so MP is the only changed variable. +# A presses crouch twice; B observes. Read all three layers. +# ========================================================================= +set -x +. /c/git/bt411/scratchpad/night6/bench_common.sh +cd /c/git/bt411/content || exit 1 +bt_assert_player_env +taskkill //F //IM btl4.exe > /dev/null 2>&1 +sleep 2 +rm -f cm_a.log cm_b.log cm_relay.log +bt_expert_egg MP.EGG CM.EGG +sed -i "s/^map=.*/map=grass/; s/^time=.*/time=day/; s/^vehicle=.*/vehicle=madcat/" CM.EGG + +( export BT_DUCK_LOG=1 BT_GAIT_LOG=1 BT_MP_LOG=1 + bt_launch cm_b.log CM.EGG 0x0C -net 1601 ) +sleep 2 +( export BT_BTNTEST=0x13,900,960 BT_BTNTEST2=0x13,1800,1860 + export BT_DUCK_LOG=1 BT_GAIT_LOG=1 BT_MP_LOG=1 BT_KEY_NOFOCUS=1 + bt_launch cm_a.log CM.EGG 0x03 -net 1501 ) +sleep 5 +python ../tools/btconsole.py CM.EGG 127.0.0.1:1501 127.0.0.1:1601 > cm_relay.log 2>&1 & +RELAY=$! +sleep 240 +kill $RELAY 2>/dev/null +sleep 3 +bt_kill_ours; sleep 2; taskkill //F //IM btl4.exe > /dev/null 2>&1; sleep 3 + +AID=$(grep -aoE "MY mech entityID=[0-9]+:[0-9]+" cm_a.log | head -1 | cut -d= -f2) +echo "=================== #142 CROUCH in MP (A=${AID:-?}) ===================" +echo "--- (a) did A's press reach the handler, and was it dropped? ---" +grep -a "btntest" cm_a.log | head -4 +echo -n "DuckRequests : "; grep -ac "DuckRequest" cm_a.log +echo -n "REQUEST DROPPED: "; grep -ac "REQUEST DROPPED" cm_a.log +grep -a "REQUEST DROPPED" cm_a.log | head -3 +echo +echo "--- (b) did A's own mech actually change posture? ---" +grep -aE "\[duck\] (SQUAT|RISE|squat clip)" cm_a.log | head -6 +echo -n "SQUAT/RISE on A: "; grep -acE "\[duck\] (SQUAT|RISE)" cm_a.log +echo +echo "--- (c) did the PEER pose the squat? (legState ships in the type-3 record) ---" +echo -n "B duck lines for A: "; grep -ac "\[duck\]" cm_b.log +grep -a "\[duck\]" cm_b.log | head -4 +echo -n "B legState-2/3 sightings: "; grep -aoE "legState=[23]" cm_b.log | wc -l +echo +echo "--- (d) the INDICATOR: does anything latch a crouched state? ---" +grep -aiE "lamp.*0x13|stability|duckState" cm_a.log | head -6