#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 <noreply@anthropic.com>
This commit is contained in:
Joe DiPrima
2026-08-12 02:14:34 -05:00
co-authored by Claude Fable 5
parent f4feaea4c1
commit 1282063cc7
2 changed files with 65 additions and 0 deletions
+3
View File
@@ -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
+62
View File
@@ -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<ControlsButton> msg(
9 /*MechWeapon::ConfigureMappablesMessageID*/,
sizeof(ReceiverDataMessageOf<ControlsButton>),
(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