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"
|
||||
);
|
||||
}
|
||||
// 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();
|
||||
return attribute_pointer;
|
||||
}
|
||||
@@ -2198,6 +2204,9 @@ void *
|
||||
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();
|
||||
return attribute_pointer;
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ GaussRifle::SharedData
|
||||
GaussRifle::DefaultData(
|
||||
&GaussRifle::ClassDerivations,
|
||||
GaussRifle::MessageHandlers,
|
||||
GaussRifle::AttributeIndex,
|
||||
MechWeapon::GetAttributeIndex(), // gauge wave: inherit temps/InputVoltage/OutputVoltage/PercentDone (was empty)
|
||||
GaussRifle::StateCount
|
||||
);
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ PPC::SharedData
|
||||
PPC::DefaultData(
|
||||
&PPC::ClassDerivations,
|
||||
PPC::MessageHandlers,
|
||||
PPC::AttributeIndex,
|
||||
MechWeapon::GetAttributeIndex(), // gauge wave: inherit temps/InputVoltage/OutputVoltage/PercentDone (was empty)
|
||||
PPC::StateCount
|
||||
);
|
||||
|
||||
|
||||
@@ -123,9 +123,15 @@ Logical Mech::IsDisabled()
|
||||
return (movementMode == 2 || movementMode == 9) ? True : False;
|
||||
}
|
||||
|
||||
// TODO(bring-up): writes mech+0x404 (HUD/weapon target range).
|
||||
void Mech::SetTargetRange(Scalar /*range*/)
|
||||
// mech+0x404 = the radar display scale. Both the radar map's currentScale and
|
||||
// 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
|
||||
|
||||
@@ -125,7 +125,7 @@ Emitter::SharedData
|
||||
Emitter::DefaultData(
|
||||
&Emitter::ClassDerivations,
|
||||
Emitter::MessageHandlers,
|
||||
Emitter::AttributeIndex,
|
||||
MechWeapon::GetAttributeIndex(), // gauge wave: inherit temps/InputVoltage/OutputVoltage/PercentDone (was empty)
|
||||
Emitter::StateCount
|
||||
);
|
||||
|
||||
|
||||
@@ -332,7 +332,18 @@ const HeatSink::IndexEntry
|
||||
{
|
||||
ATTRIBUTE_ENTRY(HeatSink, CoolantMass, coolantLevel), // @0x12C (live: UpdateCoolant depletes it)
|
||||
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&
|
||||
|
||||
@@ -334,6 +334,15 @@ inline int
|
||||
CoolantMassAttributeID = HeatableSubsystem::NextAttributeID,
|
||||
CoolantCapacityAttributeID,
|
||||
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
|
||||
};
|
||||
private:
|
||||
|
||||
@@ -81,13 +81,34 @@ Derivation
|
||||
);
|
||||
|
||||
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::DefaultData(
|
||||
&MechWeapon::ClassDerivations,
|
||||
MechWeapon::MessageHandlers,
|
||||
MechWeapon::AttributeIndex,
|
||||
MechWeapon::GetAttributeIndex(),
|
||||
MechWeapon::StateCount
|
||||
);
|
||||
|
||||
|
||||
@@ -109,6 +109,28 @@ class CockpitHud;
|
||||
static AttributeIndexSet AttributeIndex;
|
||||
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
|
||||
// the weapon-specific alarm/idle state appended by WriteUpdateRecord.
|
||||
|
||||
@@ -93,7 +93,7 @@ MissileLauncher::SharedData
|
||||
MissileLauncher::DefaultData(
|
||||
&MissileLauncher::ClassDerivations,
|
||||
MissileLauncher::MessageHandlers,
|
||||
MissileLauncher::AttributeIndex,
|
||||
MechWeapon::GetAttributeIndex(), // gauge wave: inherit temps/InputVoltage/OutputVoltage/PercentDone (was empty)
|
||||
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
|
||||
//
|
||||
|
||||
@@ -90,6 +90,27 @@ class Generator;
|
||||
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.
|
||||
//
|
||||
|
||||
@@ -130,7 +130,7 @@ ProjectileWeapon::SharedData
|
||||
ProjectileWeapon::DefaultData(
|
||||
&ProjectileWeapon::ClassDerivations,
|
||||
ProjectileWeapon::MessageHandlers,
|
||||
ProjectileWeapon::AttributeIndex,
|
||||
MechWeapon::GetAttributeIndex(), // gauge wave: inherit temps/InputVoltage/OutputVoltage/PercentDone (was empty)
|
||||
ProjectileWeapon::StateCount
|
||||
);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user