# HEAT.CPP / POWERSUB.CPP — the power/heat wave (Phase 5.3.10, 2026-07-21) The mech's thermal + electrical economy is LIVE: weapons dump firing heat into their own sinks, the sinks conduct through the Condenser bank into the central HeatSink, temperatures drive the degradation/failure alarms, and every powered subsystem tracks its generator through the electrical state machine. ## The heat topology (wire-verified on TEST.EGG) `linkedSinkIndex` (the previously-missing HeatSink resource int — see below) wires the authored conduction graph at construction: weapons / equipment -> Condenser1..6 (slots 4-9) -> central HeatSink (slot 2) GeneratorA..D (10-13) -> Condensers Reservoir (3) -> central HeatSink Authored values match the BT411 calibration audit EXACTLY: central bank mass 1.39e6, PPC's own sink 174000, thresholds 77 start / 1000 degradation / 2000 failure, PPC conductance 86800. (The central sink's own `linkedSinkIdx=5` is a FORWARD reference — Condenser2 isn't constructed yet at slot 2's ctor — so its drain is unwired; a post-walk fixup is a small future item. Everything drains INTO it fine.) ## Reconstructed - **HeatSink::HeatSinkSimulation** (@004ad924): absorb pendingHeat → T = E/mass → UpdateHeatLoad (15-sample filter) → ConductHeat → alarm thresholds. Installed by the HeatSink ctor (derived classes override and chain it). - **ConductHeat / ComputeHeatFlow** (@004ad8ac/@004ad9ec): the two-body equilibrium relaxation — `(T·massScale − (E_other+pending+E_own)/denom)·tau· (1−exp(−dt·conductance·(coolant/capacity)·flowScale/denom))`. Verified: flow == 0 exactly at uniform temperature; a fired PPC bleeds ~170K units/step into Condenser4. - **PoweredSubsystem ctor + PoweredSubsystemSimulation** (@004b0f74/@004b0bd0): resolves `voltageSourceIndex` from the roster (GeneratorA-D — wire-verified), attaches the tap (`Generator::TapVoltageSource`, −1 when full), and runs the electrical FSM (Starting=0 / NoVoltage=1 / Shorted=2 / GeneratorOff=3 / Ready=4) watching the generator state. Deferred: the AutoConnect replacement-generator hunt (needs the status flags / damage wave). - **Generator::GeneratorSimulation** (PARTIAL): heat step + start/short-recovery timers; the load model (voltage sag, I²R self-heat feeding the charge integration) joins the electrical-charge wave (TrackSeekVoltage). - **Sensor::SensorSimulation** upgraded to the authentic gating (@004b1c4c): power step first, radar = 1 − damage, electrical-Ready gate (badVoltage), heat-state switch (Degradation ×0.5, Failure → 0). Verified: voltState=4, radar 100% on the healthy mech. - Weapons: Emitter/Projectile sims run the power step at their head; the Loading recharge is gated on electrical Ready (authentic @4bbdf5); FireWeapon dumps the firing heat. ## Heat units (1e7-native) — TWO authoring conventions The heat chain is 1e7-unit-native (BT411 audit). The stream stores `heatCostToFire` in TWO conventions: - **Energy weapons: small units** (PPC = 11) — the ×1e7 comes from the energy closed form ((1−dF)·E ≈ heatCost·1e7 at full charge). Our partial multiplies by 1e7 pending the charge model. - **Ballistics: native units** (SRM6 = 5.06e7) — dumped RAW. (Double-scaling this to 5e14 was the runaway-temperature bug during bring-up.) Both land ~+640K on the weapon's own sink — the consistent design magnitude. ## The resource-alignment resolution (wire-verified, closes the +3 mystery) The raw-stream dumps pinned the FULL ancestry alignment: - `HeatSink__SubsystemResource.linkedSinkIndex` — THE missing int that shifted every descendant block +1 (PoweredSubsystem's voltageSourceIndex previously read the linked-sink index — hence "power sources" appearing to be Condensers). - The MechWeapon pip tail is `pipPosition(int) + pipColor(3 floats) + pipExtendedRange(int)` (+2) — matches BT411's verified overlay exactly. - +1 +2 = the +3 the interim ProjectileWeapon pad compensated; the pad is gone. - True bhk1 reads: PPC recharge **5.0 s** (not the misaligned 1.0), discharge 0.99 s, range 900, damage 12, heatCost 11, pipColor (0,0,1); SRM6 recharge 5 s, range 800, salvo damage 35, missileCount 6. ## VERIFIED (BT_FORCE_FIRE + BT_POWER_LOG) PPC: 77° → fires → ~709° → relaxes to 441° across its 5 s reload → sustained fire climbs the residual 441 → 674 → 838 → 960 — brushing the 1000° degradation threshold: the authentic fire-discipline game. SRM salvos spike +641K and cross degradation after three. Condensers absorb and pass to the central bank. Neutral run: sensor Ready/100%, mech holds, zero Fail. ## Heat consequences (Phase 5.3.11, 2026-07-22) The weapon-side consequences are wired and VERIFIED under sustained fire: - **Ballistic gate 1** (@4bbd36): weapon destroyed-state or its own sink at FailureHeat pins full recoil + the unavailable alarm (the NoAmmo roach-motel re-asserts). (Mech-disabled half joins the damage wave.) - **CheckForJam** (@4bbfcc): `p = 0.41·T/failT` clamped [minJamChance, 1.0], rolled per granted shot against the MUNGA uniform `Random`. Interim gate: heat-degraded only (stands in for the deferred `LiveFireEnabled` novice switch AND the trivially-true `heatLoad>0` early-out — the exact spurious- cold-jam trap the BT411 port documented). Verified: SRM6s jam at T≈1200-1320 (24%+ rolls past the 1000° threshold), stay jammed. - **Emitter hard gate** (@4baab9): FailureHeat drops the beam state + charge each frame; SELF-RECOVERING — conduction cools the sink below 2000° and the weapon resumes from Loading. Verified: the PPC settles into an emergent thermal duty cycle (fire at ~1930° → spike 2562° → shutdown → cool → refire); the lasers oscillate around ~2200°. ## Still deferred UpdateCoolant / BalanceCoolant (coolant depletion + venting), the HeatModelOff / LiveFireEnabled experience gates (novice mode), the electrical charge model (TrackSeekVoltage / voltage sag / I²R), the mech-disabled halves of the weapon gates (damage wave), the central sink's forward-linked drain, Condenser MoveValve handling, jam recovery via ResetToInitialState (mission reset path).