From 341a50364174b90f9ab65ba782c1055325dd8d69 Mon Sep 17 00:00:00 2001 From: Cyd Date: Mon, 27 Jul 2026 12:25:53 -0500 Subject: [PATCH] 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 --- restoration/source410/BT/MISLANCH.CPP | 16 ++++++++++++++-- restoration/source410/BT/PROJWEAP.CPP | 18 ++++++++++++++++++ restoration/source410/BT_L4/BTL4GAU2.CPP | 24 +++++++++++++++++++++++- 3 files changed, 55 insertions(+), 3 deletions(-) diff --git a/restoration/source410/BT/MISLANCH.CPP b/restoration/source410/BT/MISLANCH.CPP index 6d2ab606..565bdf58 100644 --- a/restoration/source410/BT/MISLANCH.CPP +++ b/restoration/source410/BT/MISLANCH.CPP @@ -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 ); diff --git a/restoration/source410/BT/PROJWEAP.CPP b/restoration/source410/BT/PROJWEAP.CPP index a25bf52f..b7343ea1 100644 --- a/restoration/source410/BT/PROJWEAP.CPP +++ b/restoration/source410/BT/PROJWEAP.CPP @@ -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(); } diff --git a/restoration/source410/BT_L4/BTL4GAU2.CPP b/restoration/source410/BT_L4/BTL4GAU2.CPP index 8ea37b0c..4b526686 100644 --- a/restoration/source410/BT_L4/BTL4GAU2.CPP +++ b/restoration/source410/BT_L4/BTL4GAU2.CPP @@ -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