#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:
co-authored by
Claude Fable 5
parent
f4feaea4c1
commit
1282063cc7
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user