BT410 5.3.47: the whole authored watcher set is published -- cockpit renders in the pod

Ladder rungs, each run-verified on the pod rig: ReportLeak (HeatSink),
GeneratorOn (Generator -- member existed, publication missing),
ConfigureActivePress (MechSubsystem -- likewise), AmmoState +
FireCountdownStarted + the rest of the AmmoBin table.

THE PINNED RANGE IS NOW THE AUTHENTIC SHAPE.  Publishing ReportLeak on
HeatSink and ConfigureActivePress on MechSubsystem shifts the chain down two,
and MechWeapon's bridge to its binary-pinned PercentDone (0x12) collapses
from THREE guessed pads to ONE -- which is exactly the arithmetic the shipped
string pool predicts (MechSubsystem 1, HeatableSubsystem 3, HeatSink 6,
PoweredSubsystem 5).  Three pads of guesswork replaced by a real attribute
and a real base-class row.  HeatableSubsystem and Torso rebase onto
MechSubsystem::AttributeIndex; MechControlsMapper does not (it derives from
Subsystem directly).

Types were chosen deliberately this time, per the AudioWatcher families the
engine instantiates (Motion / Hinge / Scalar / StateIndicator): every *State
name resolves to a StateIndicator, ReportLeak is a Scalar.

RESULT: the pod run now gets past every authored watcher and DRAWS THE FULL
COCKPIT -- sensor cluster, myomers, cooling, the weapon panels, kills/deaths
-- with the board booted and audio running.  It then exits without flushing
its redirected stdout, so the exit reason is not yet known; next step is a
run with the redirect removed so the console is readable.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Cyd
2026-07-28 08:09:56 -05:00
co-authored by Claude Fable 5
parent afb9e3f5d9
commit 4168f1ad4d
11 changed files with 120 additions and 13 deletions
+19 -2
View File
@@ -25,11 +25,28 @@ Derivation
"AmmoBin"
);
const AmmoBin::IndexEntry
AmmoBin::AttributePointers[]=
{
ATTRIBUTE_ENTRY(AmmoBin, AmmoCount, ammoCount),
ATTRIBUTE_ENTRY(AmmoBin, TimeToReady, feedTimer),
ATTRIBUTE_ENTRY(AmmoBin, AmmoClassID, ammoClassID),
ATTRIBUTE_ENTRY(AmmoBin, AmmoState, ammoAlarm),
ATTRIBUTE_ENTRY(AmmoBin, FireCountdownStarted, fireCountdownStarted)
};
AmmoBin::AttributeIndexSet
AmmoBin::AttributeIndex(
ELEMENTS(AmmoBin::AttributePointers),
AmmoBin::AttributePointers,
MechSubsystem::AttributeIndex
);
AmmoBin::SharedData
AmmoBin::DefaultData(
AmmoBin::ClassDerivations,
Subsystem::MessageHandlers,
Subsystem::AttributeIndex,
AmmoBin::AttributeIndex,
Subsystem::StateCount
);
@@ -55,7 +72,7 @@ AmmoBin::AmmoBin(
heatPerRound = resource->heatPerRound;
cookOffArmed = 0;
cookOffTime = 0;
reserved = 0;
fireCountdownStarted = 0; // was: reserved
for (int i = 0; i < 12; ++i)
{
+28 -1
View File
@@ -95,6 +95,29 @@
);
~AmmoBin();
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Attribute Support. The shipped pool lists this class's attributes
// contiguously after the class name:
// AmmoCount TimeToReady AmmoClassID AmmoState FireCountdownStarted
// and BTL4.RES binds watchers to AmmoState and FireCountdownStarted on
// every bin. AmmoState is a *State name, so it MUST resolve to a
// StateIndicator (see RENDER-ROADMAP.NOTES.md) -- ammoAlarm below is
// one. AmmoBin chains HeatWatcher -> MechSubsystem, so the ids start
// at MechSubsystem::NextAttributeID.
//
public:
enum {
AmmoCountAttributeID = MechSubsystem::NextAttributeID,
TimeToReadyAttributeID,
AmmoClassIDAttributeID,
AmmoStateAttributeID,
FireCountdownStartedAttributeID,
NextAttributeID
};
static const IndexEntry AttributePointers[];
static AttributeIndexSet AttributeIndex;
protected:
int ammoCount;
int initialAmmoCount;
@@ -106,7 +129,11 @@
Scalar heatPerRound;
int cookOffArmed;
int cookOffTime;
int reserved;
//
// Spends the spare reserved slot rather than growing the class --
// AmmoBin has offset-sensitive neighbours.
//
int fireCountdownStarted; // was: reserved
AlarmIndicator ammoAlarm;
//
// Cook-off heat-source registration state (advanced by the heat sim).
+4 -2
View File
@@ -71,7 +71,7 @@ HeatableSubsystem::AttributeIndexSet
HeatableSubsystem::AttributeIndex(
ELEMENTS(HeatableSubsystem::AttributePointers),
HeatableSubsystem::AttributePointers,
Subsystem::AttributeIndex
MechSubsystem::AttributeIndex
);
HeatableSubsystem::SharedData
@@ -199,7 +199,8 @@ const HeatSink::IndexEntry
ATTRIBUTE_ENTRY(HeatSink, CoolantMass, coolantLevel),
ATTRIBUTE_ENTRY(HeatSink, CoolantCapacity, thermalCapacity),
ATTRIBUTE_ENTRY(HeatSink, CoolantMassLeakRate, coolantDraw),
ATTRIBUTE_ENTRY(HeatSink, CoolantAvailable, coolantAvailable)
ATTRIBUTE_ENTRY(HeatSink, CoolantAvailable, coolantAvailable),
ATTRIBUTE_ENTRY(HeatSink, ReportLeak, reportLeak)
};
HeatSink::AttributeIndexSet
@@ -246,6 +247,7 @@ HeatSink::HeatSink(
coolantLevel = thermalCapacity;
coolantDraw = 0.0f;
coolantAvailable = 1;
reportLeak = 0.0f; // staged: no leak-report model yet
coolantActive = 0;
startingTemperature = currentTemperature;
+16 -1
View File
@@ -64,7 +64,7 @@
//
public:
enum {
CurrentTemperatureAttributeID = Subsystem::NextAttributeID, // 2
CurrentTemperatureAttributeID = MechSubsystem::NextAttributeID, // 3
HeatLoadAttributeID, // 3
DegradationTemperatureAttributeID, // 4
FailureTemperatureAttributeID, // 5
@@ -245,6 +245,15 @@
CoolantCapacityAttributeID, // 7
CoolantMassLeakRateAttributeID, // 8
CoolantAvailableAttributeID, // 9
//
// Authored watcher, bound on Avionics / every Condenser /
// every Generator / Myomers / every weapon -- i.e. the whole
// heat-bearing family, which is why it belongs on HeatSink.
// Adding it here pushes PoweredSubsystem::NextAttributeID from
// 0x0F to 0x10, so MechWeapon drops one bridging pad to keep
// PercentDone on its binary-pinned 0x12 (see MECHWEAP.CPP).
//
ReportLeakAttributeID, // 0x0A
NextAttributeID // 0x0A
};
@@ -394,6 +403,12 @@
SubsystemConnection linkedSinks;
AlarmIndicator heatAlarm;
AverageOf<Scalar> heatFilter;
//
// STAGED, appended last: no leak-reporting model yet. A Scalar
// because the audio watcher families instantiate Motion / Hinge /
// Scalar / StateIndicator, and this is not a *State name.
//
Scalar reportLeak;
};
//###########################################################################
+14 -1
View File
@@ -44,11 +44,24 @@ Derivation
"MechSubsystem"
);
const MechSubsystem::IndexEntry
MechSubsystem::AttributePointers[]=
{
ATTRIBUTE_ENTRY(MechSubsystem, ConfigureActivePress, configureActivePress)
};
MechSubsystem::AttributeIndexSet
MechSubsystem::AttributeIndex(
ELEMENTS(MechSubsystem::AttributePointers),
MechSubsystem::AttributePointers,
Subsystem::AttributeIndex
);
MechSubsystem::SharedData
MechSubsystem::DefaultData(
MechSubsystem::ClassDerivations,
Subsystem::MessageHandlers,
Subsystem::AttributeIndex,
MechSubsystem::AttributeIndex,
Subsystem::StateCount
);
+22
View File
@@ -60,6 +60,28 @@
static Derivation ClassDerivations;
static SharedData DefaultData;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Attribute Support. The shipped pool puts ConfigureActivePress
// immediately after the class name MechSubsystem, i.e. it is this
// class's one attribute and the FIRST id past Subsystem's. BTL4.RES
// binds it on Avionics, Myomers and every weapon -- all of which chain
// through here. The member has been in this class all along; only the
// publication was missing.
//
// Everything downstream shifts by one, which is the AUTHENTIC shape:
// with this row in place MechWeapon needs exactly ONE bridging pad to
// land PercentDone on its binary-pinned 0x12 (it needed three before
// ReportLeak and this were published).
//
public:
enum {
ConfigureActivePressAttributeID = Subsystem::NextAttributeID, // 2
NextAttributeID // 3
};
static const IndexEntry AttributePointers[];
static AttributeIndexSet AttributeIndex;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Status model
//
+6 -3
View File
@@ -83,9 +83,12 @@ MechWeapon::MessageHandlerSet
const MechWeapon::IndexEntry
MechWeapon::AttributePointers[]=
{
MECHWEAP_PAD( 0, "MechWeaponPad0F"),
MECHWEAP_PAD( 1, "MechWeaponPad10"),
MECHWEAP_PAD( 2, "MechWeaponPad11"),
//
// TWO pads now, not three: HeatSink grew ReportLeak, so
// PoweredSubsystem::NextAttributeID moved 0x0F -> 0x10 and the bridge
// to the binary-pinned PercentDone (0x12) is one slot shorter.
//
MECHWEAP_PAD( 0, "MechWeaponPad11"),
ATTRIBUTE_ENTRY(MechWeapon, PercentDone, rechargeLevel), // 0x12
ATTRIBUTE_ENTRY(MechWeapon, TriggerState, fireImpulse), // 0x13
ATTRIBUTE_ENTRY(MechWeapon, DistanceToTarget, rangeToTarget), // 0x14
+3 -1
View File
@@ -596,7 +596,9 @@ const Generator::IndexEntry
ATTRIBUTE_ENTRY(Generator, OutputVoltage, outputVoltage),
ATTRIBUTE_ENTRY(Generator, RatedVoltage, ratedVoltage),
ATTRIBUTE_ENTRY(Generator, GeneratorNumber, generatorNumber),
ATTRIBUTE_ENTRY(Generator, GeneratorState, stateAlarm)
ATTRIBUTE_ENTRY(Generator, GeneratorState, stateAlarm),
{ (int)Generator::GeneratorOnAttributeID2, "GeneratorOn",
(Simulation::AttributePointer)&Generator::generatorOn }
};
Generator::AttributeIndexSet
+6
View File
@@ -355,6 +355,12 @@
RatedVoltageAttributeID, // 0x0B
GeneratorNumberAttributeID, // 0x0C
GeneratorStateAttributeID, // authored watcher: GeneratorX/GeneratorState
//
// Authored watcher too (GeneratorX/GeneratorOn, 36 bindings).
// The member has been here since the generator wave -- only the
// publication was missing, the same as EyepointRotation.
//
GeneratorOnAttributeID2,
NextAttributeID
};
+1 -1
View File
@@ -45,7 +45,7 @@ Torso::AttributeIndexSet
Torso::AttributeIndex(
ELEMENTS(Torso::AttributePointers),
Torso::AttributePointers,
Subsystem::AttributeIndex
MechSubsystem::AttributeIndex
);
Torso::SharedData
+1 -1
View File
@@ -117,7 +117,7 @@
//
public:
enum {
RotationOfTorsoVerticalAttributeID = Subsystem::NextAttributeID,
RotationOfTorsoVerticalAttributeID = MechSubsystem::NextAttributeID,
RotationOfTorsoHorizontalAttributeID,
HorizontalLimitRightAttributeID,
HorizontalLimitLeftAttributeID,