gauge wave P1a: publish heat/power/weapon attributes + radar zoom
The gauge-databinding-map workflow found most cockpit gauges resolve NULL because the reconstructed subsystems publish only a fraction of the attributes the config binds. First publishing batch (attribute tables are read-only static data; ids kept a dense prefix from each parent's NextAttributeID): - HeatSink table dense-append: DegradationTemperature/FailureTemperature (the condenser temp-bar warn/max endpoints -- were NULL, so the two-part bars could not scale), NormalizedPressure/DegradationPressure/CoolantMassLeakRate, and the HeatSink link. Condenser/Reservoir inherit this -> all 6 condenser temp bars now resolve current/warn/max (verified: BT_GAUGE_ATTR_LOG all OK). - PoweredSubsystem::GetAttributeIndex() (new) publishes InputVoltage->voltageSource -- the cluster power-branch gate (the power-lamp/generator-voltage/state-lamp sub-branch is skipped when it resolves NULL). Flows to Sensor/Myomers/weapons. - MechWeapon::GetAttributeIndex() (new) publishes OutputVoltage/PercentDone-> rechargeLevel; Emitter/PPC/ProjectileWeapon/MissileLauncher/GaussRifle DefaultData re-pointed at it (they carried an EMPTY default-constructed index -> resolved NOTHING). Verified: the ER MED LASER / PPC / STREAK weapon clusters now render live recharge dials (were blank TEMP/STATUS). - Mech::SetTargetRange un-stubbed (radarRange = range) -> the radar map scale + overlay range readout track the mapper's zoom (was frozen at 1000). - GAUGREND ParseAttribute: env-gated per-binding resolution trace (BT_GAUGE_ATTR_LOG) -- durable diagnostic infra for the wave. Verified DBASE+dev gauges: no startup/gauge-construction crash (dense chain intact), combat un-regressed (TARGET DESTROYED), clusters build with InputVoltage resolving. Remaining config-binding NULLs: HeatSink/AmbientTemperature (aggregate bank, P3) + Searchlight/LightOn (P1b). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
c850ffa26c
commit
070af409f7
@@ -2180,6 +2180,12 @@ void *
|
|||||||
string_pointer << "' not found\n"
|
string_pointer << "' not found\n"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
// gauge data-binding wave: a per-binding resolution trace to the
|
||||||
|
// log file (env BT_GAUGE_ATTR_LOG) -- proves which cockpit bindings
|
||||||
|
// resolve to a live member vs read NULL (unpublished attribute).
|
||||||
|
if (getenv("BT_GAUGE_ATTR_LOG"))
|
||||||
|
DEBUG_STREAM << "[attr] " << string_pointer
|
||||||
|
<< (attribute_pointer ? " OK\n" : " NULL\n") << std::flush;
|
||||||
Check_Fpu();
|
Check_Fpu();
|
||||||
return attribute_pointer;
|
return attribute_pointer;
|
||||||
}
|
}
|
||||||
@@ -2198,6 +2204,9 @@ void *
|
|||||||
source << "' not found\n"
|
source << "' not found\n"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
if (getenv("BT_GAUGE_ATTR_LOG"))
|
||||||
|
DEBUG_STREAM << "[attr] " << source
|
||||||
|
<< (attribute_pointer ? " OK (entity)\n" : " NULL (entity)\n") << std::flush;
|
||||||
Check_Fpu();
|
Check_Fpu();
|
||||||
return attribute_pointer;
|
return attribute_pointer;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ GaussRifle::SharedData
|
|||||||
GaussRifle::DefaultData(
|
GaussRifle::DefaultData(
|
||||||
&GaussRifle::ClassDerivations,
|
&GaussRifle::ClassDerivations,
|
||||||
GaussRifle::MessageHandlers,
|
GaussRifle::MessageHandlers,
|
||||||
GaussRifle::AttributeIndex,
|
MechWeapon::GetAttributeIndex(), // gauge wave: inherit temps/InputVoltage/OutputVoltage/PercentDone (was empty)
|
||||||
GaussRifle::StateCount
|
GaussRifle::StateCount
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ PPC::SharedData
|
|||||||
PPC::DefaultData(
|
PPC::DefaultData(
|
||||||
&PPC::ClassDerivations,
|
&PPC::ClassDerivations,
|
||||||
PPC::MessageHandlers,
|
PPC::MessageHandlers,
|
||||||
PPC::AttributeIndex,
|
MechWeapon::GetAttributeIndex(), // gauge wave: inherit temps/InputVoltage/OutputVoltage/PercentDone (was empty)
|
||||||
PPC::StateCount
|
PPC::StateCount
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -123,9 +123,15 @@ Logical Mech::IsDisabled()
|
|||||||
return (movementMode == 2 || movementMode == 9) ? True : False;
|
return (movementMode == 2 || movementMode == 9) ? True : False;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(bring-up): writes mech+0x404 (HUD/weapon target range).
|
// mech+0x404 = the radar display scale. Both the radar map's currentScale and
|
||||||
void Mech::SetTargetRange(Scalar /*range*/)
|
// the overlay range readout bind Mech/RadarRange -> radarRange. The controls
|
||||||
|
// mapper slews targetRangeExponent and calls SetTargetRange(250*2^exp) every
|
||||||
|
// frame (btl4mppr.cpp:407) off the zoom buttons, so writing the member makes the
|
||||||
|
// radar map zoom + the range numeric track the zoom (default exp 2.0 -> 1000,
|
||||||
|
// matching the historic frozen value). Faithful body (the binary writes [this+0x404]).
|
||||||
|
void Mech::SetTargetRange(Scalar range)
|
||||||
{
|
{
|
||||||
|
radarRange = range;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Install the cockpit-mapping subsystem into the Mech's reserved ControlsMapper
|
// Install the cockpit-mapping subsystem into the Mech's reserved ControlsMapper
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ Emitter::SharedData
|
|||||||
Emitter::DefaultData(
|
Emitter::DefaultData(
|
||||||
&Emitter::ClassDerivations,
|
&Emitter::ClassDerivations,
|
||||||
Emitter::MessageHandlers,
|
Emitter::MessageHandlers,
|
||||||
Emitter::AttributeIndex,
|
MechWeapon::GetAttributeIndex(), // gauge wave: inherit temps/InputVoltage/OutputVoltage/PercentDone (was empty)
|
||||||
Emitter::StateCount
|
Emitter::StateCount
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -332,7 +332,18 @@ const HeatSink::IndexEntry
|
|||||||
{
|
{
|
||||||
ATTRIBUTE_ENTRY(HeatSink, CoolantMass, coolantLevel), // @0x12C (live: UpdateCoolant depletes it)
|
ATTRIBUTE_ENTRY(HeatSink, CoolantMass, coolantLevel), // @0x12C (live: UpdateCoolant depletes it)
|
||||||
ATTRIBUTE_ENTRY(HeatSink, CoolantCapacity, thermalCapacity), // @0x128
|
ATTRIBUTE_ENTRY(HeatSink, CoolantCapacity, thermalCapacity), // @0x128
|
||||||
ATTRIBUTE_ENTRY(HeatSink, CurrentTemperature, currentTemperature) // @0x114 (inherited from HeatableSubsystem)
|
ATTRIBUTE_ENTRY(HeatSink, CurrentTemperature, currentTemperature), // @0x114 (inherited from HeatableSubsystem)
|
||||||
|
// --- gauge data-binding wave: the config's GenericHeatGauges vertBar binds
|
||||||
|
// Condenser<N>/DegradationTemperature (@4=warn) + FailureTemperature (@5=max);
|
||||||
|
// without these the two-part temp bar's warn/max endpoints were NULL -> the
|
||||||
|
// bar could not scale (division by a zero max). Condenser/Reservoir inherit
|
||||||
|
// this table, so publishing here covers all 6 condensers + both coolant banks.
|
||||||
|
ATTRIBUTE_ENTRY(HeatSink, DegradationTemperature, degradationTemperature), // @0x118 (constant warn threshold)
|
||||||
|
ATTRIBUTE_ENTRY(HeatSink, FailureTemperature, failureTemperature), // @0x11C (constant max threshold)
|
||||||
|
ATTRIBUTE_ENTRY(HeatSink, NormalizedPressure, heatLoad), // @0x120 (smoothed radiated heat)
|
||||||
|
ATTRIBUTE_ENTRY(HeatSink, DegradationPressure, coolantEfficiency), // @0x124
|
||||||
|
ATTRIBUTE_ENTRY(HeatSink, CoolantMassLeakRate, coolantDraw), // @0x130 (LeakGauge; damage-driven)
|
||||||
|
ATTRIBUTE_ENTRY(HeatSink, HeatSink, linkedSinks) // @0x164 (Eng linked-sink temp readout)
|
||||||
};
|
};
|
||||||
|
|
||||||
HeatSink::AttributeIndexSet&
|
HeatSink::AttributeIndexSet&
|
||||||
|
|||||||
@@ -334,6 +334,15 @@ inline int
|
|||||||
CoolantMassAttributeID = HeatableSubsystem::NextAttributeID,
|
CoolantMassAttributeID = HeatableSubsystem::NextAttributeID,
|
||||||
CoolantCapacityAttributeID,
|
CoolantCapacityAttributeID,
|
||||||
CurrentTemperatureAttributeID,
|
CurrentTemperatureAttributeID,
|
||||||
|
// --- dense-append (gauge data-binding wave): the config binds these
|
||||||
|
// per condenser/heat-sink (L4GAUGE.CFG GenericHeatGauges1/2 + the Eng
|
||||||
|
// clusters). Ids stay contiguous so AttributeIndexSet::Build has no gap.
|
||||||
|
DegradationTemperatureAttributeID, // @0x118 constant amber warn line
|
||||||
|
FailureTemperatureAttributeID, // @0x11C constant max reference
|
||||||
|
NormalizedPressureAttributeID, // @0x120 heatLoad (smoothed radiated heat)
|
||||||
|
DegradationPressureAttributeID, // @0x124 coolantEfficiency
|
||||||
|
CoolantMassLeakRateAttributeID, // @0x130 coolantDraw (damage-driven leak)
|
||||||
|
HeatSinkAttributeID, // @0x164 linkedSinks (link to master sink)
|
||||||
NextAttributeID
|
NextAttributeID
|
||||||
};
|
};
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -81,13 +81,34 @@ Derivation
|
|||||||
);
|
);
|
||||||
|
|
||||||
Receiver::MessageHandlerSet MechWeapon::MessageHandlers;
|
Receiver::MessageHandlerSet MechWeapon::MessageHandlers;
|
||||||
Simulation::AttributeIndexSet MechWeapon::AttributeIndex;
|
Simulation::AttributeIndexSet MechWeapon::AttributeIndex; // legacy empty member (superseded by GetAttributeIndex)
|
||||||
|
|
||||||
|
// gauge data-binding wave: OutputVoltage/PercentDone -> rechargeLevel (1.0 ==
|
||||||
|
// ready; ComputeOutputVoltage/the charge state machine drive it, so both animate
|
||||||
|
// as the weapon recharges). Chained to PoweredSubsystem's dense index.
|
||||||
|
const MechWeapon::IndexEntry
|
||||||
|
MechWeapon::AttributePointers[]=
|
||||||
|
{
|
||||||
|
ATTRIBUTE_ENTRY(MechWeapon, OutputVoltage, rechargeLevel), // @0x320 (charge/ready level)
|
||||||
|
ATTRIBUTE_ENTRY(MechWeapon, PercentDone, rechargeLevel) // @0x320 (recharge dial fraction)
|
||||||
|
};
|
||||||
|
|
||||||
|
MechWeapon::AttributeIndexSet&
|
||||||
|
MechWeapon::GetAttributeIndex()
|
||||||
|
{
|
||||||
|
static MechWeapon::AttributeIndexSet attributeIndex(
|
||||||
|
ELEMENTS(MechWeapon::AttributePointers),
|
||||||
|
MechWeapon::AttributePointers,
|
||||||
|
PoweredSubsystem::GetAttributeIndex()
|
||||||
|
);
|
||||||
|
return attributeIndex;
|
||||||
|
}
|
||||||
|
|
||||||
MechWeapon::SharedData
|
MechWeapon::SharedData
|
||||||
MechWeapon::DefaultData(
|
MechWeapon::DefaultData(
|
||||||
&MechWeapon::ClassDerivations,
|
&MechWeapon::ClassDerivations,
|
||||||
MechWeapon::MessageHandlers,
|
MechWeapon::MessageHandlers,
|
||||||
MechWeapon::AttributeIndex,
|
MechWeapon::GetAttributeIndex(),
|
||||||
MechWeapon::StateCount
|
MechWeapon::StateCount
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -109,6 +109,28 @@ class CockpitHud;
|
|||||||
static AttributeIndexSet AttributeIndex;
|
static AttributeIndexSet AttributeIndex;
|
||||||
static SharedData DefaultData;
|
static SharedData DefaultData;
|
||||||
|
|
||||||
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
// Attribute Support (gauge data-binding wave)
|
||||||
|
//
|
||||||
|
// The energy/ballistic weapon engineering clusters read OutputVoltage (the
|
||||||
|
// charge/ready level -- animates as the weapon recharges after firing) and
|
||||||
|
// PercentDone (the recharge dial), both onto rechargeLevel (1.0 == ready).
|
||||||
|
// GetAttributeIndex() chains to PoweredSubsystem's so InputVoltage + the
|
||||||
|
// HeatSink temps also resolve; Emitter/PPC/ProjectileWeapon/MissileLauncher
|
||||||
|
// point their DefaultData at MechWeapon::GetAttributeIndex() to inherit it
|
||||||
|
// (they carried an EMPTY default-constructed index -> resolved NOTHING).
|
||||||
|
//
|
||||||
|
public:
|
||||||
|
enum {
|
||||||
|
OutputVoltageAttributeID = PoweredSubsystem::NextAttributeID,
|
||||||
|
PercentDoneAttributeID,
|
||||||
|
NextAttributeID
|
||||||
|
};
|
||||||
|
private:
|
||||||
|
static const IndexEntry AttributePointers[];
|
||||||
|
public:
|
||||||
|
static AttributeIndexSet& GetAttributeIndex();
|
||||||
|
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
// Update record (replication) -- extends the base Simulation record with
|
// Update record (replication) -- extends the base Simulation record with
|
||||||
// the weapon-specific alarm/idle state appended by WriteUpdateRecord.
|
// the weapon-specific alarm/idle state appended by WriteUpdateRecord.
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ MissileLauncher::SharedData
|
|||||||
MissileLauncher::DefaultData(
|
MissileLauncher::DefaultData(
|
||||||
&MissileLauncher::ClassDerivations,
|
&MissileLauncher::ClassDerivations,
|
||||||
MissileLauncher::MessageHandlers,
|
MissileLauncher::MessageHandlers,
|
||||||
MissileLauncher::AttributeIndex,
|
MechWeapon::GetAttributeIndex(), // gauge wave: inherit temps/InputVoltage/OutputVoltage/PercentDone (was empty)
|
||||||
MissileLauncher::StateCount
|
MissileLauncher::StateCount
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -82,6 +82,31 @@ static const Scalar MinVoltageScale = 1.0f; // _DAT_004b1924 (PowerWatcher thr
|
|||||||
//###########################################################################
|
//###########################################################################
|
||||||
//###########################################################################
|
//###########################################################################
|
||||||
|
|
||||||
|
//#############################################################################
|
||||||
|
// Attribute Support (gauge data-binding wave)
|
||||||
|
//
|
||||||
|
// InputVoltage -> voltageSource (the 0xC connection to the powering Generator;
|
||||||
|
// the cluster's power-branch gate + the source of GeneratorVoltageConnection).
|
||||||
|
// Chained to HeatSink's dense index; a function-local static so the parent
|
||||||
|
// index is safely constructed on first use regardless of static-init order.
|
||||||
|
//
|
||||||
|
const PoweredSubsystem::IndexEntry
|
||||||
|
PoweredSubsystem::AttributePointers[]=
|
||||||
|
{
|
||||||
|
ATTRIBUTE_ENTRY(PoweredSubsystem, InputVoltage, voltageSource) // @0x1D0
|
||||||
|
};
|
||||||
|
|
||||||
|
PoweredSubsystem::AttributeIndexSet&
|
||||||
|
PoweredSubsystem::GetAttributeIndex()
|
||||||
|
{
|
||||||
|
static PoweredSubsystem::AttributeIndexSet attributeIndex(
|
||||||
|
ELEMENTS(PoweredSubsystem::AttributePointers),
|
||||||
|
PoweredSubsystem::AttributePointers,
|
||||||
|
HeatSink::GetAttributeIndex()
|
||||||
|
);
|
||||||
|
return attributeIndex;
|
||||||
|
}
|
||||||
|
|
||||||
//#############################################################################
|
//#############################################################################
|
||||||
// Shared Data Support
|
// Shared Data Support
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -90,6 +90,27 @@ class Generator;
|
|||||||
AutoConnect = 2 // scan all GeneratorClassID segments and attach
|
AutoConnect = 2 // scan all GeneratorClassID segments and attach
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
// Attribute Support (gauge data-binding wave)
|
||||||
|
//
|
||||||
|
// The engineering subsystem clusters bind PoweredSubsystem/InputVoltage --
|
||||||
|
// the power-source gate that decides whether the power-lamp / generator-
|
||||||
|
// voltage-bar / state-lamp sub-branch is even constructed (SubsystemCluster
|
||||||
|
// ctor skips it when InputVoltage resolves NULL). Published on top of
|
||||||
|
// HeatSink's dense index; Sensor/Myomers/MechWeapon chain to GetAttributeIndex()
|
||||||
|
// below and inherit it (so InputVoltage + the HeatSink temps reach every
|
||||||
|
// powered/weapon subsystem's cluster).
|
||||||
|
//
|
||||||
|
public:
|
||||||
|
enum {
|
||||||
|
InputVoltageAttributeID = HeatSink::NextAttributeID,
|
||||||
|
NextAttributeID
|
||||||
|
};
|
||||||
|
private:
|
||||||
|
static const IndexEntry AttributePointers[];
|
||||||
|
public:
|
||||||
|
static AttributeIndexSet& GetAttributeIndex();
|
||||||
|
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
// Streamed model resource.
|
// Streamed model resource.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ ProjectileWeapon::SharedData
|
|||||||
ProjectileWeapon::DefaultData(
|
ProjectileWeapon::DefaultData(
|
||||||
&ProjectileWeapon::ClassDerivations,
|
&ProjectileWeapon::ClassDerivations,
|
||||||
ProjectileWeapon::MessageHandlers,
|
ProjectileWeapon::MessageHandlers,
|
||||||
ProjectileWeapon::AttributeIndex,
|
MechWeapon::GetAttributeIndex(), // gauge wave: inherit temps/InputVoltage/OutputVoltage/PercentDone (was empty)
|
||||||
ProjectileWeapon::StateCount
|
ProjectileWeapon::StateCount
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user