Gauges: the CLOSEOUT wave -- radar pips, Myomers dedup, attribute parity, ledger sweep (tasks #14-#17)
TASK #17 -- AUTHENTIC RADAR SYMBOLOGY (the cross-blip stand-in retired). The recon proved the 'missing pip raster set' never existed as BT game code: pips are the ENGINE's L4GaugeImage vector-stroke system (T0 source in tree, L4GAUIMA.cpp == FUN_0046f0c0 line-for-line), the 'pip table' is L4Warehouse:: gaugeImageBin keyed by Entity::resourceID, and BTL4.RES ships 110 type-0x12 shapes (every mech/vehicle/building/tree). The six btl4rdr stubs are wired to the real facilities: contacts draw their authentic model silhouettes with LOD selection, the target gets the binary's 4px-inflated box highlight, and player-name labels resolve via Mission::GetSmallNameBitmap (the prebuilt 64x16 egg rasters keyed by the player's bitmapindex). DECODED: the invented 'VideoObject' was Entity::owningPlayer all along (+0x190; nameID = playerBitmapIndex@0x1E0, target = BTPlayer::objectiveMech@0x284 -- new bridge BTPlayerObjectiveMechOf); the 'LabelledEntity' class is Landmark (cultural.h; label path dormant -- no landmark content ships, no runtime landmarkID writer). The L4GREND BT_DEV_GAUGES warehouse guard is removed (its AV had a different culprit, below); resource type 18 corrected to GaugeImageStream in decomp-reference (was mislabeled 'ModelList'). TASK #14 -- the Myomers ODR duplicate ELIMINATED: the powersub.cpp/hpp 'Myomers' (classID 0xBC3 -- actually Sensor) is retired whole; it duplicated ?DefaultData@Myomers@@ against the real class (dumpbin-verified) and /FORCE picked the winner by link order. The real Myomers (0xBC6) now chains PoweredSubsystem's handler set (ids 4-8) and publishes its SEVEN binary attributes (@00511588: SpeedEffect/Current/Recommended/Min/MaxSeekVoltage- Index/SeekVoltage/OutputVoltage) -- the old empty unchained index starved the Myomer engineering panel of every resolve. TASK #16 -- attribute parity: MechWeapon publishes the FULL binary table @0x511890 (11 entries; ids renumbered to binary truth -- the port aliases had squatted the binary's DistanceToTarget/TargetWithinRange ids; the streamed TriggerState 0x13 binding unchanged). Binary names resolved two TODO members: pipState -> estimatedReadyTime (attr 0x1A), and the EXT-model flag is the binary's RearFiring (0x1B). ThermalSight LightState published. HUD (offset conflicts) + missile-side tables (id encoding suspect) documented for a re-dump instead of publishing blind. THE CRASH THIS EXPOSED [T2, cdb-verified]: gotcha #11's dense-table gap is a LATENT AV, not a guaranteed one -- the old table's 0x0D..0x12 gap (task #5) survived on heap luck; the renumber reshuffled allocations and Find() AV'd on a garbage entryName in WeaponCluster's PercentDone resolve. Fixed with five named PAD entries (the mech.cpp attrPad idiom) + a static_assert locking the pad base to PoweredSubsystem::NextAttributeID. Gotcha #11 amended with the proof. TASK #15 -- stale-ledger sweep: GAUGE_COMPOSITE ('composite not yet built', Reservoir shadow, PlayerStatus/vehicleSubSystems 'remaining', valve-dormant- until-0xBD3, sensor guard, the superseded 'Heat MFD near-static' reframe -- all banner-corrected), gauges-hud frontmatter, L4VB16 + powersub comments. Verified live: 50/50 config attribute bindings resolve, 0 NULLs, 0 parse skips, mech spawns and simulates 31/31 subsystems, no cross-blip fallbacks, the pip cache fills through entity registration without the old guard. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
80cadc98c7
commit
dd27238ceb
+31
-27
@@ -1,9 +1,8 @@
|
||||
# Gauge / MFD render pipeline — map + dev-composite plan
|
||||
|
||||
**Status:** pipeline MAPPED (workflow `gauge-pipeline-map`, 2026-07); the dev composite is **planned, not
|
||||
yet built**. This is the execute-ready plan for making the pod's gauges/MFDs render + be VISUALLY testable
|
||||
on a dev box — the "MFD compositing on dev" follow-up the platform profile gates (see §8 / the PLATFORM
|
||||
PROFILE entry in CLAUDE.md). Companion: the platform-profile scaffold (`-platform pod|dev`).
|
||||
**Status (updated 2026-07-12):** the dev composite is **BUILT AND LIVE** (Milestones A/B/C done —
|
||||
BT_DEV_GAUGES / BT_DEV_GAUGES_DOCK; all 6 MFD surfaces composite; 50/50 attr bindings, 0 parse-skips).
|
||||
The header below preserved the original PLAN framing; see the increments + Phase logs for what landed.
|
||||
|
||||
## The draw model — CONFIRMED (the good news)
|
||||
|
||||
@@ -443,18 +442,17 @@ fill the gaps (bind not-yet-needed ids to a shared read-only pad member).
|
||||
Resource fetch = `renderer->warehousePointer->bitMapBin.Get/Release(name)` (FUN_00442aec/00442c12).
|
||||
|
||||
### Deferred / follow-ups
|
||||
- `HeatSink/AmbientTemperature` maps to `ambientTemperature`@0x1D4 on the AGGREGATE HeatSink-bank class
|
||||
(0xBBE, ctor @4ae8d0) which is `#if 0`'d — reviving it + its own table is a separate task (Heat `A`
|
||||
readout stays 0 until then).
|
||||
- Reservoir shadow: `Reservoir::coolantCapacity`@0x128 shadows the inherited `thermalCapacity` the gauge
|
||||
reads → `Reservoir/CoolantCapacity` reads the base default; fix = delete the shadow + write thermalCapacity
|
||||
in the Reservoir ctor (bundle with the Reservoir coolant-bar verification).
|
||||
- ✅ `HeatSink/AmbientTemperature` — LANDED (AggregateHeatSink 0xBBE reconstructed, commit 16f5f54;
|
||||
cleared the last NULL binding; the bank is also the ambient radiator since task #9).
|
||||
- ✅ Reservoir shadow — LANDED (heatfamily_reslice.cpp now writes thermalCapacity from the resource
|
||||
coolantCapacity; the shadow member is gone).
|
||||
- ✅ **oneOfSeveralPixInt** DONE (increment 5). The Mech table now reaches 0x37 so `DuckState` resolves;
|
||||
`Searchlight/LightOn` still needs a Searchlight `LightOn` table to make that button dynamic.
|
||||
- ✅ **map** DONE (increment 6) — renders the view wedge. FOLLOW-UPS: the spatial-query contact
|
||||
classification (0 contacts today) + the stubbed pip/name/video-object infrastructure (contacts + labels)
|
||||
+ `SetTargetRange` (radar zoom, currently a 500m default).
|
||||
- Remaining widgets (task #13): `PlayerStatus` (comm/score, 8 uses), `vehicleSubSystems` (26 uses).
|
||||
- ✅ **map** DONE (increment 6) — view wedge + live contact blips; ✅ `SetTargetRange` LANDED (radar
|
||||
zoom). REMAINING: the stubbed pip/name/video-object symbology (contacts draw the cross-blip stand-in,
|
||||
no labels) — under reconstruction (task #17, 2026-07-12).
|
||||
- ✅ Remaining widgets — BOTH LANDED: `PlayerStatus` (increment 7, commit b691863) and
|
||||
`vehicleSubSystems` (see docs/VEHICLE_SUBSYSTEMS.md Phase 2).
|
||||
|
||||
### Remaining widgets — scope (assessed 2026-07; NOT quick registration wins)
|
||||
- ✅ **PlayerStatus** DONE (increment 7; commit b691863) — reconstructed the whole family (mapped by the
|
||||
@@ -469,11 +467,9 @@ fill the gaps (bind not-yet-needed ids to a shared read-only pad member).
|
||||
Pixelmap8 returns NULL (the mech-outline recolor needs the DynamicMemoryStream read API + Pixmap pixel-copy
|
||||
mapped) → the score/name-box/status-box render but not the recoloured mech schematic. Player resolve uses
|
||||
`application->GetMissionPlayer()` (WinTesla-clean) instead of the binary's raw App+0x24 "Players"-node walk.
|
||||
- **vehicleSubSystems** (26 uses -- the most-used unregistered widget) — no class declared; fully
|
||||
from-scratch. Config: `vehicleSubSystems(qjak0.pcc..qjak7.pcc)` (8 subsystem-group bitmaps, no attribute
|
||||
bindings -- reads the mech's subsystem roster internally). Find its Make/ctor/Execute via the .data
|
||||
methodDescription table (the "vehicleSubSystems" string is a .data const, not inlined in the decomp).
|
||||
A focused effort (~250-300 lines across 3-5 functions).
|
||||
- ✅ **vehicleSubSystems** — LANDED (docs/VEHICLE_SUBSYSTEMS.md: 7 authentic engineering panels with
|
||||
real aux-screen positions via the BTGetSubsystemAuxScreen bridge). The from-scratch scoping note above
|
||||
is historical.
|
||||
|
||||
---
|
||||
|
||||
@@ -482,8 +478,10 @@ fill the gaps (bind not-yet-needed ids to a shared read-only pad member).
|
||||
Goal (user directive: "all of this needs to work as the game originally played. no shortcuts"): make every
|
||||
cockpit gauge read + reflect LIVE game state exactly as the 1995 pod. The `gauge-databinding-map` workflow
|
||||
(5 surface maps + 2 adversarial verifies) mapped every binding → subsystem/member → published-vs-missing →
|
||||
authentic value → fix. **KEY REFRAME (verified against the shipped .SUB data + the binary sim): the Heat MFD
|
||||
is authentically NEAR-STATIC, not a live heat-accumulation display.** `currentTemperature =
|
||||
authentic value → fix. **[SUPERSEDED 2026-07-11, tasks #9/#10: the reframe below was computed at the
|
||||
DEGENERATE bring-up heat scale. At the authentic 1e7-unit economy the Heat MFD is FULLY DYNAMIC —
|
||||
weapons 77→2000, condensers/generators 100-1400, bank ~600; see context/gauges-hud.md.]** The original
|
||||
(superseded) reframe read: the Heat MFD is authentically NEAR-STATIC — `currentTemperature =
|
||||
heatEnergy/thermalMass`; ThermalMass=1.39e6, so heatEnergy_init = 1.07e8 whose float32 ULP is 8.0 — a
|
||||
3.5-heat laser shot ROUNDS TO ZERO (reaching Degradation 5000 needs ~2 billion shots). Coolant is
|
||||
DAMAGE-gated (not fire), the valve moves only on player toggle, AmbientTemperature is a hardcoded 300. So the
|
||||
@@ -567,7 +565,8 @@ AggregateHeatSink cleared the last, `HeatSink/AmbientTemperature`), and every co
|
||||
built (`[gskip]`=0). Diagnostic `BT_GAUGE_SKIP_LOG` (GAUGREND.cpp, gated) logs each unregistered primitive the
|
||||
dev-parse skips — the tool that pinned the last 3 (⚠ the gauge renderer builds LAZILY, so verification runs must wait
|
||||
long enough for BuildConfigurationFile; a too-early kill shows [gparse]=0 and looks like "not built"). Remaining gauge
|
||||
work is DATA FEEDS, not widgets: the valve/message CONTROL routes (0xBD3 SubsystemMessageManager, WAVE 8) and the
|
||||
work is DATA FEEDS, not widgets — [UPDATE 2026-07-12: the 0xBD3 untangle landed (task #7) and the valve
|
||||
CONTROL landed (task #13, live MoveValve via the rookie-role gate); only the message half remains]: the
|
||||
status-message queue (StatusMessagePool) — deferred systems, cleanly marked. `SeekVoltageGraph::Execute` (@004c6934)
|
||||
is a cluster-child (not config-called) — its 4 Seek* attributes are the only remaining publish, non-blocking.
|
||||
|
||||
@@ -590,8 +589,9 @@ is a cluster-child (not config-called) — its 4 Seek* attributes are the only r
|
||||
6 condensers each read flow=0.166667 (=1/6).** ValveSetting→coolantFlowScale now authentic.
|
||||
(3) **MoveValve** — the reconstructed @4afbe0 body was a MISLABEL (MechControlsMapper mode cycler);
|
||||
disassembled the real handler @4ae464 (valveState cycle 1→5→50→0 + RecomputeCondenserValves) and replaced
|
||||
it. DORMANT: its guard + message route go through the 0xBD3 SubsystemMessageManager (WAVE 8) → the valve
|
||||
gauge shows the static authentic 1/N until 0xBD3 lands (no V-key bring-up stand-in added).
|
||||
it. [UPDATE 2026-07-12: LIVE (task #13) — the guard was never the 0xBD3 messmgr; FUN_004ac9c8 is the
|
||||
owning player's ROOKIE-ROLE lockout (roleClassIndex@0x274==0, task #12 bridge). MoveValve is registered
|
||||
(id 4, table @0x50E52C), verified valveState 1→5 / flow 1/6→5/10; 'C' key + BT_VALVE_SLOT.]
|
||||
- ✅ **Combat SCORING feed** (KILLS/SCORE) — DONE (commit 34aaa7d; scoring-feed-decode workflow). The
|
||||
scoreboard read 0 for 4 reasons (none was handler logic — the ScoreMessage/VehicleDead/ScoreInflicted
|
||||
handlers were already reconstructed): (1) no producer — added the posts (per-hit ScoreInflicted at the
|
||||
@@ -618,10 +618,14 @@ is a cluster-child (not config-called) — its 4 Seek* attributes are the only r
|
||||
|
||||
### Phase 4 — DEEP/DEFERRED
|
||||
Byte-exact re-base of the PoweredSubsystem:HeatSink LEAF (Sensor/Emitter/Myomers) → radarPercent heat penalty
|
||||
(delete the sensor.cpp:287-288 guard) + the raw-offset cluster reads; radar pip/name symbology + staticEntities;
|
||||
CycleDisplayMode→ModeManager mask (activates cmArmor/cmCrit/cmHeat schematic layers); numericSpeed units.
|
||||
(delete the sensor.cpp:287-288 guard — ✅ LANDED: the guard is deleted and the leaf is byte-exact,
|
||||
sensor.cpp:407-413) + the raw-offset cluster reads (partially locked since — MechWeapon byte-exact);
|
||||
radar pip/name symbology + staticEntities (task #17, under reconstruction 2026-07-12);
|
||||
CycleDisplayMode→ModeManager mask (machinery reconstructed, gauge-layer toggle unverified [T3]);
|
||||
numericSpeed units (open).
|
||||
|
||||
### Authentically-static (do NOT "fix")
|
||||
currentTemperature ~77 (huge thermalMass); Degradation/Failure temps (fixed threshold markers); AmbientTemperature
|
||||
[currentTemperature "~77 static" REMOVED 2026-07-11 — dynamic at the authentic heat economy, tasks #9/#10.]
|
||||
Degradation/Failure temps (fixed threshold markers); AmbientTemperature
|
||||
300; MaxRunSpeed (per-mech constant); cmArmor/cmCrit all-green (undamaged solo player — BT is PvP-only);
|
||||
CoolantMassLeakRate 0 on a pristine mech (damage-gated); Player RANK 1 in solo.
|
||||
|
||||
Reference in New Issue
Block a user