#118: coolant-clause hysteresis kills the panic-arm flap (10 Hz mode churn)

Post-respawn under sustained fire the bank fraction hovers at the 0.05 arm
threshold and the plain compare flipped ejectPermitted EVERY FRAME --
hundreds of mode ON/off pairs churning the mask, the lamp, and the arm cue.
The evaluator was dead code in shipped 4.10, so the boundary flap is a
first-ever-exercised condition; completed with the engine's own idiom
(HeatSink coolantActive dual thresholds): ARM below 0.05 (the binary
constant), release above 0.06, no new members.  Stress bench: 1 arm
transition in 3 minutes (was: hundreds).

NOTE: the operator's ticking SOUND persists past this fix -- it is the
separate, pre-existing night-10 "audio stutter on coolant leak" family;
hunt continues at the audio-cue chokepoint.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Joe DiPrima
2026-08-04 02:18:58 -05:00
co-authored by Claude Fable 5
parent 5a4ee55e4e
commit 38872ac726
+13 -1
View File
@@ -572,10 +572,22 @@ int
extern int BTPlayerExperienceSimLive(void *owner_mech); // btplayer.cpp (+0x25c;
int noviceSim = (BTPlayerExperienceSimLive(this) == 0); // NULL-player reads LIVE)
// COOLANT-CLAUSE HYSTERESIS [T3 intent-completion, 2026-08-03]: the
// binary's clause is a plain `< 0.05` compare -- but this evaluator was
// DEAD CODE in shipped 4.10 (never called), so the boundary flap was
// never exercised. Live, a bank fraction hovering at 0.05 under fire
// flips the panic-arm mode EVERY FRAME (observed: hundreds of ON/off
// pairs), churning the mode mask, the lamp, and the arm audio cue into a
// ~10 Hz stutter tick. The engine's own idiom for exactly this is the
// dual-threshold pair (HeatSink coolantActive: 0.003 on / 0.0025 off);
// mirrored here: ARM below 0.05 (the binary constant @0049fb50), stay
// armed until the fraction RECOVERS above 0.06. No new members -- the
// current ejectPermitted is the state.
Scalar coolantGate = ejectPermitted ? 0.06f : 0.05f;
ejectPermitted =
(liveWeapons < ejectMinWeapons) // @0x448 floor (inert at 0)
|| (liveGenerators == 0)
|| (coolantFrac < 0.05f) // _DAT_0049fb50
|| (coolantFrac < coolantGate) // _DAT_0049fb50 + hysteresis
|| (gimped && noviceSim);
return ejectPermitted;
}