From 1282063cc7efd38dd7355a3313a6bef87dd4a7f0 Mon Sep 17 00:00:00 2001 From: Joe DiPrima Date: Wed, 12 Aug 2026 02:14:34 -0500 Subject: [PATCH] #164 hardened to impossibility + the config theory tested NULL: the beam draw now requires the weapon to actually BE in Firing(0) -- the 1995 visual rode ContinueDischarge's per-frame re-messaging which stopped the instant the state left 0, so state-gated drawing is the faithful semantics and makes ANY beamFlag bookkeeping stick invisible by construction (Conn Man's screenshot: red laser, leg-level origin, dials green = a live weapon with a stuck flag). Receipts stand armed for the field: [beam] STUCK-ON (armed flag outside Firing) and DESTROYED-BUT-ON, each naming the weapon. The config-mid-discharge theory was tested deterministically (BT_CFGTEST waits for state 0 and dispatches ConfigureMappables to that weapon): the dispatch landed with beamFlag=1 and NO stick followed -- the handler does not disturb the discharge; theory retired with receipts. Upstream cause remains open; one field recurrence now names it. Co-Authored-By: Claude Fable 5 --- game/reconstructed/emitter.hpp | 3 ++ game/reconstructed/mech4.cpp | 62 ++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/game/reconstructed/emitter.hpp b/game/reconstructed/emitter.hpp index e07f2ee..f3167eb 100644 --- a/game/reconstructed/emitter.hpp +++ b/game/reconstructed/emitter.hpp @@ -226,6 +226,9 @@ class NotationFile; // beam from this live sim state -- the authentic per-weapon fire look). // int BeamOn() const { return beamFlag; } // 0x46c + // #164: the DRAW-side state read (cross-family, gotcha-22 style) -- the + // beam renders only while the weapon is actually in Firing(0). + int WeaponStateCell() { return GetWeaponState(); } Scalar DischargeTimer() const { return dischargeTimer; } // forensics // REPLICANT-side beam aging (port, 2026-07-13): replicated discharge // state arrives via update records, but replicant subsystems never diff --git a/game/reconstructed/mech4.cpp b/game/reconstructed/mech4.cpp index 2721a32..cfcc7a0 100644 --- a/game/reconstructed/mech4.cpp +++ b/game/reconstructed/mech4.cpp @@ -7854,6 +7854,43 @@ void } } + // #164 repro (BT_CFGTEST): the field composition of Conn Man's hanging + // beam -- a config-mode PROGRAM press landing MID-DISCHARGE. Waits for + // any Emitter/PPC to enter Firing(0), then dispatches ConfigureMappables + // (msg 9, press) to that exact weapon. The alarm re-level knocks the + // state out of 0 with beamFlag still armed; the [beam] STUCK-ON receipt + // + refused draw are the PASS evidence. + if (getenv("BT_CFGTEST") && (Entity *)this == application->GetViewpointEntity()) + { + static int s_cfgDone = 0; + static int s_cfgFrame = 0; + if (!s_cfgDone && ++s_cfgFrame > 900) + { + for (int s = 1; s < GetSubsystemCount(); ++s) + { + Subsystem *sub = GetSubsystem(s); + if (sub == 0) + continue; + const int cid = (int)sub->GetClassID(); + if (cid != 3016 && cid != 3028) // Emitter / PPC + continue; + if (((Emitter *)sub)->WeaponStateCell() != 0) + continue; // not mid-discharge + ReceiverDataMessageOf msg( + 9 /*MechWeapon::ConfigureMappablesMessageID*/, + sizeof(ReceiverDataMessageOf), + (ControlsButton)0x0f /*a config element press*/); + sub->Dispatch(&msg); + s_cfgDone = 1; + DEBUG_STREAM << "[cfgtest] ConfigureMappables dispatched to '" + << (sub->GetName() ? sub->GetName() : "?") + << "' MID-DISCHARGE (state was 0, beamFlag=" + << ((Emitter *)sub)->BeamOn() << ")\n" << std::flush; + break; + } + } + } + // issue #20 verify (BT_BALTEST): alternate a MoveValve (id 4) press to // the first condenser with a Mech BalanceCoolant (id 0x16) press every // ~2s -- BT_VALVE_LOG shows the valve going 1->5 then BALANCE pulling @@ -9091,6 +9128,31 @@ void } continue; } + // #164 THE FAITHFUL DRAW CONDITION (Conn Man's screenshot: RED laser + // beam, leg-level origin, weapon dials all GREEN -- a live weapon with + // a stuck beamFlag). The 1995 beam visual rode ContinueDischarge's + // PER-FRAME re-messaging, which stops the instant the weapon leaves + // Firing(0) -- e.g. a config-mode PROGRAM press mid-discharge re-levels + // weaponAlarm out of state 0, the case-0 countdown never resumes, and + // beamFlag (cleared only by ResetFiringState) stays armed forever while + // the weapon itself recovers. Drawing from beamFlag alone is the port + // divergence; require the weapon to actually BE discharging, exactly as + // the message stream did. (Replicants mirror firingActive into + // weaponAlarm 0/2 in ReadUpdateRecord, so the same test serves both.) + if (em->WeaponStateCell() != 0) + { + static int s_stateStuck = 0; + if (em->BeamOn() && s_stateStuck < 20) + { + ++s_stateStuck; + DEBUG_STREAM << "[beam] STUCK-ON: '" + << (em->GetName() ? em->GetName() : "?") + << "' beamFlag armed outside Firing (state=" + << em->WeaponStateCell() + << ") -- draw refused (#164)\n" << std::flush; + } + continue; + } Point3D mz; em->MuzzlePoint(mz); // LIVE muzzle (tracks the gun) // MOUNT FALLBACK: when the weapon's mount segment doesn't