BT410 5.3.33: MissileLauncher was wired to the wrong shared-data tables

MissileLauncher::DefaultData passed Subsystem::MessageHandlers and
Subsystem::AttributeIndex where every sibling weapon passes MechWeapon's --
and a launcher publishes no tables of its own, so it must chain MechWeapon's
exactly as ProjectileWeapon (its own base) does.  Wired to Subsystem's, EVERY
weapon attribute on a missile launcher resolved to nothing and the gauge read
the unbound zero cell: PercentDone, TriggerState, WeaponState,
DistanceToTarget, RearFiring.

The cockpit is what found it.  The shipped binary lights a fire-ready disc on
the STREAK 6 panel (WeaponCluster gates it on PercentDone >= 0.99) and ours
never did -- while the launcher itself reported state=Loaded recoil=0 level=1
bin=24.  A healthy weapon behind a dead binding.

  head   missing before -> after      extra
  Mfd1        8807 -> 4991            4063 -> 4003
  Mfd3        6935 -> 3174            2659 -> 2608
  Mfd2        6882 -> 6870   (unchanged -- it hosts no missile panel)

~7.6K missing pixels recovered.  The disc, its rays and the stencilled ammo
cells now draw; the digits themselves stay blank pending the ammo feed, which
is the documented inert gap in the BallisticWeaponCluster ledger.

Traces added, all env-gated on BT_VIS_LOG and kept as tooling: [warn]
(cluster percentDone/warn state) and [proj-state] (launcher state, recoil,
recharge rate, bin count) -- the pair that separated "broken weapon" from
"broken binding" in one run.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Cyd
2026-07-27 12:25:53 -05:00
co-authored by Claude Fable 5
parent 883315a647
commit 341a503641
3 changed files with 55 additions and 3 deletions
+14 -2
View File
@@ -43,11 +43,23 @@ Derivation
"MissileLauncher"
);
//
// The shared data must carry the WEAPON tables, not Subsystem's -- a
// MissileLauncher publishes no attributes or handlers of its own, so it
// chains MechWeapon's exactly as ProjectileWeapon (its own base) does.
// Wired to Subsystem's, EVERY weapon attribute on a launcher resolved to
// nothing: PercentDone, TriggerState, WeaponState, DistanceToTarget,
// RearFiring. The cockpit found it -- the shipped binary lights the
// fire-ready disc on the STREAK 6 panel (WeaponCluster gates it on
// PercentDone >= 0.99) and ours never did, while the launcher itself
// reported state=Loaded recoil=0 level=1 bin=24. The gauge was reading
// the unbound zero cell, not a broken weapon.
//
MissileLauncher::SharedData
MissileLauncher::DefaultData(
MissileLauncher::ClassDerivations,
Subsystem::MessageHandlers,
Subsystem::AttributeIndex,
MechWeapon::MessageHandlers,
MechWeapon::AttributeIndex,
Subsystem::StateCount
);
+18
View File
@@ -446,5 +446,23 @@ void
break;
}
if (getenv("BT_VIS_LOG"))
{
static int projStateSamples = 0;
if (projStateSamples < 8)
{
++projStateSamples;
DEBUG_STREAM << "[proj-state] '" << GetName()
<< "' state=" << GetWeaponState()
<< " recoil=" << recoil
<< " rechargeRate=" << rechargeRate
<< " level=" << rechargeLevel
<< " bin=" << ((bin != NULL) ? bin->GetAmmoCount() : -1)
<< " simState=" << GetSimulationState()
<< " heatState=" << GetHeatState()
<< "\n" << flush;
}
}
Check_Fpu();
}
+23 -1
View File
@@ -1915,6 +1915,8 @@ SubsystemCluster::SubsystemCluster(
// buffer). A model that authored nothing keeps the bare frame.
//
background = NULL;
int clusterPlacement = -1;
const char *clusterBackgroundName = NULL;
{
int placement = -1;
if (subsystem_in != NULL
@@ -1922,6 +1924,7 @@ SubsystemCluster::SubsystemCluster(
{
placement =
((PoweredSubsystem *)subsystem_in)->GetAuxScreenPlacement();
clusterPlacement = placement;
}
if (placement >= 0 && placement < 8 && image_names != NULL
&& image_names[placement] != NULL)
@@ -1933,6 +1936,7 @@ SubsystemCluster::SubsystemCluster(
0xff, 0 // fg / bg
);
Register_Object(background);
clusterBackgroundName = image_names[placement];
}
}
@@ -1963,7 +1967,12 @@ SubsystemCluster::SubsystemCluster(
Register_Object(titleBanner);
}
if (getenv("BT_VIS_LOG"))
DEBUG_STREAM << "[cluster] port=" << mfd_port
DEBUG_STREAM << "[cluster] sub='"
<< ((subsystem_in != NULL) ? subsystem_in->GetName() : "(null)")
<< "' powered=" << (powered ? 1 : 0)
<< " placement=" << clusterPlacement
<< " bg='" << (clusterBackgroundName ? clusterBackgroundName : "(none)")
<< "' port=" << mfd_port
<< " x=" << x << " y=" << y
<< " title='" << (title ? title : "(null)")
<< "' banner=" << (titleBanner ? 1 : 0) << "\n" << flush;
@@ -2523,6 +2532,19 @@ void
warningState = -2; // lamp: force redraw too
}
if (getenv("BT_VIS_LOG"))
{
static int weaponWarnSamples = 0;
if (weaponWarnSamples < 16)
{
++weaponWarnSamples;
DEBUG_STREAM << "[warn] " << identificationString
<< " drawState=" << previousDrawState
<< " percentDone=" << percentDone
<< " warnState=" << warningState << "\n" << flush;
}
}
if (previousDrawState == 0)
{
int