gauges: register + wire the map (radar) -- the tactical display renders
MapDisplay (the radar/threat-map gauge, btl4rdr.cpp) was fully reconstructed (ctor + Execute + DrawViewWedge/DrawStatic/DrawMoving/DrawNames) but never registered and its data attributes never published. Wire it up end-to-end: DATA (the attributes the map binds): * Mech table extended to the full 0x15..0x38 (was the 0x21 prefix): add RadarRange@0x2f -> radarRange, RadarLinearPosition@0x30 -> radarLinearPosition (Point3D* -> &localOrigin.linearPosition), RadarAngularPosition@0x31 -> radarAngularPosition (Quaternion* -> &localOrigin.angularPosition), DuckState @0x37 -> duckState; the rest bind the shared attrPad (kept dense so Find can't strcmp a gap). New members set in the Mech ctor; radarRange defaults to 500 (SetTargetRange is still stubbed) so nearby contacts are on-scale. The map's position/angle attributes resolve to Point3D**/Quaternion** (AttributePointer is int Simulation::*, so the ATTRIBUTE_ENTRY reinterpret binds pointer members fine -- verified live: posPtr/anglePtr resolve). * Sensor (named "Avionics") publishes RadarPercent/SelfTest/BadVoltage: define Sensor::AttributePointers[] + build the previously-empty Sensor::AttributeIndex chained to PoweredSubsystem::GetAttributeIndex() (= HeatSink's dense index). WIDGET (the registration glue -- NOT in the assert-anchored decomp, so reconstructed from the config + ctor): * MapDisplay::methodDescription (config "map") + MapDisplay::Make. The offset_position keyword "center"/"bottom" is typed as a STRING and converted in Make, avoiding a ModeManager named-constant registration. Registered in BTL4MethodDescription[] (btl4grnd.cpp now includes btl4rdr.hpp). Three crash fixes exposed once the map ran (each a pre-existing stub the map is the first consumer of): * Sensor radarPercent went hugely negative (RadarBaseline - HeatMasterEnergy(), where the inherited heatEnergy is un-normalized in the not-byte-exact heat-leaf branch) -> the radar reported non-operational. Guard: treat an out-of-[0,1] heat term as no penalty (marked bring-up; real overheat penalty needs the heat normalization). * ResolveOperatorEntity was a stub returning NULL -> EntityPosition(NULL) crashed CalculateBounds. Fixed to the renderer linked-entity + application viewpoint fallback (same as HeadingPointer). * MapName::ExtractFromEntity didn't guard a NULL entity (the binary's Verify(False) iterator-mismatch path compiles out at DEBUG_LEVEL 0) -> EntityPosition(NULL). Guarded. Verified live (BT_DEV_GAUGES): the radar now draws the view wedge (the mech's 180-deg FOV cone) and completes the full wedge/static/moving/names cycle with operating=1, cap=1, scale=500, position/angle resolved, 0 crashes. Combat un- regressed (TARGET DESTROYED after 8 hits), heap-clean under BT_HEAPCHECK. Permanent gated diagnostic: BT_MAP_LOG traces the phase/draw pipeline. Contacts show 0 (the spatial-query entity classification is a follow-up); DuckState now resolves for the duck button too. 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
eae631ba04
commit
48ed3a8b73
@@ -103,8 +103,29 @@ Derivation
|
||||
Receiver::MessageHandlerSet
|
||||
Sensor::MessageHandlers;
|
||||
|
||||
//
|
||||
// Attribute Support -- the gauge bindings for the Sensor (named "Avionics" in the
|
||||
// cockpit config): Avionics/RadarPercent (the map's capabilities ratio), SelfTest,
|
||||
// BadVoltage. SENSOR.HPP declares the enum + AttributePointers[]; the empty
|
||||
// default-ctor AttributeIndex published NOTHING (not even SimulationState). Build
|
||||
// it from the table chained to PoweredSubsystem::GetAttributeIndex() (which
|
||||
// resolves to HeatSink's dense index) so the merged index stays dense (ids run
|
||||
// contiguously from PoweredSubsystem::NextAttributeID).
|
||||
//
|
||||
const Sensor::IndexEntry
|
||||
Sensor::AttributePointers[]=
|
||||
{
|
||||
ATTRIBUTE_ENTRY(Sensor, RadarPercent, radarPercent), // @0x31C (map capabilities ratio)
|
||||
ATTRIBUTE_ENTRY(Sensor, SelfTest, selfTest),
|
||||
ATTRIBUTE_ENTRY(Sensor, BadVoltage, badVoltage)
|
||||
};
|
||||
|
||||
Sensor::AttributeIndexSet
|
||||
Sensor::AttributeIndex;
|
||||
Sensor::AttributeIndex(
|
||||
ELEMENTS(Sensor::AttributePointers),
|
||||
Sensor::AttributePointers,
|
||||
PoweredSubsystem::GetAttributeIndex()
|
||||
);
|
||||
|
||||
Sensor::SharedData
|
||||
Sensor::DefaultData(
|
||||
@@ -256,6 +277,16 @@ void
|
||||
// this[0x38] is the resolved thermal master sink; +0x158 == heatEnergy.
|
||||
radarPercent = RadarBaseline - HeatMasterEnergy();
|
||||
|
||||
// ⚠ BRING-UP GUARD (heat-leaf branch not byte-exact): the inherited heatEnergy
|
||||
// reads un-normalized/garbage here (~3850) so radarPercent goes hugely negative
|
||||
// and the radar reports non-operational. radarPercent is authentically a [0,1]
|
||||
// capability ratio, so when the heat term is out of range treat it as no penalty
|
||||
// (full radar). A real overheat penalty needs the heat-energy normalization
|
||||
// (deferred with the heat-leaf re-base). Exposed once the map gauge began
|
||||
// reading Avionics/RadarPercent; inert before.
|
||||
if (HeatMasterEnergy() < 0.0f || HeatMasterEnergy() > RadarBaseline)
|
||||
radarPercent = RadarBaseline;
|
||||
|
||||
if (HeatModelOff()) // this[0x10] == 1
|
||||
{
|
||||
radarPercent = 0.0f;
|
||||
|
||||
Reference in New Issue
Block a user