diff --git a/context/subsystems.md b/context/subsystems.md index 14150b8..79e2b93 100644 --- a/context/subsystems.md +++ b/context/subsystems.md @@ -180,10 +180,18 @@ disarmed, and the #64 full de-shadow sweep remains the long-term cleanup. Verif rattle and weapon crits (`[critroll]`) both drive `[cool]` leak lines (draw ≈ dmg×heatLoad, level draining, hysteresis arming). **Authored damage routing** (BTL4.RES): collision rattle targets HeatSinkBank 0.3 / Gyro 0.35 / Torso 0.25 / Myomers 0.35 — Condenser + Reservoir are authored 0 -for collisions; weapon crits select via the ZONE's crit-entry list. Remaining fidelity item: -`HeatSink::DrawCoolant` (vtable slot 14, the central-system top-up) is still a `return 0` TODO, so -a leaking subsystem drains its own loop; the pull-through to the central Reservoir gauge rides the -loop-flow machinery. +for collisions; weapon crits select via the ZONE's crit-entry list. +**The central pull-through is ALSO live (same day):** `HeatSink::DrawCoolant` was a `return 0` +stub; the real base @0x4add00 (disassembled) RECURSES UP the sink linkage — `return +resolve(linkedSinks)->DrawCoolant(requested × coolantFlowScale@0x15C)` — terminating at the +Reservoir's supply (@0x4af3b0, already faithfully ported as `Reservoir::DrawCoolant`: clamp to +[0, coolantLevel], drain, return granted). Binary terminal hop = the bank's slot-14 override +@0x4ae8b0 resolving its reservoir connection @0x1D8 (the port's `helper` member — NOT vestigial); +the port terminates equivalently via the Reservoir-ctor Attach into the bank's `linkedSinks` + +the Reservoir override (the extra bank hop scales by its ctor-default flowScale 1.0 — a no-op). +Verified live (`[resdraw]`): a destroyed myomer's leak pulled the central Reservoir tank +6.0 → 5.58 over ~30 s — **`Reservoir/CoolantMass`, the cockpit coolant BAR, now visibly drops +as a damaged mech bleeds coolant**, and DeathReset refills it on respawn. ## The coolant FLUSH (Gitea #7, 2026-07-19) — Reservoir InjectCoolant end-to-end [T2 live-verified] The manual-p24 coolant button (coolant MFD top-right; punch or HOLD): message id **4 "InjectCoolant"** diff --git a/game/reconstructed/heat.cpp b/game/reconstructed/heat.cpp index e257d39..9446f27 100644 --- a/game/reconstructed/heat.cpp +++ b/game/reconstructed/heat.cpp @@ -1001,14 +1001,30 @@ void } // -// vtable slot 14 (@vtable+0x38). Base sinks supply nothing on their own; -// a central-cooling-system subclass overrides this. -// TODO: verify against the real slot-14 target (not captured in decomp). +// vtable slot 14 (@vtable+0x38) -- the base @0x4add00, disassembled + decoded +// 2026-07-31 (the old `return 0` stub was why a leaking subsystem could never +// pull from the central tank -- the Reservoir bar never moved on damage): +// linked = resolve(linkedSinks@0x164) ; FUN_00417ab4 +// return linked->DrawCoolant(requested * coolantFlowScale@0x15C) +// i.e. the draw RECURSES UP the sink linkage, scaling per hop, and terminates +// at the Reservoir's own override (@0x4af3b0: clamp to [0, coolantLevel], +// drain the tank, return the granted amount). In the binary the terminal hop +// is the bank's slot-14 override @0x4ae8b0 resolving its reservoir connection +// @0x1D8; in the port the reservoir sits in the bank's linkedSinks (the +// Reservoir-ctor Attach) and Reservoir::DrawCoolant IS the @0x4af3b0 body, so +// the same chain terminates identically (the extra bank hop multiplies by its +// coolantFlowScale, ctor-default 1.0 -- a no-op). PORT GUARD: the binary +// calls through the resolved link UNGUARDED (authored topology always links); +// an unlinked port sink supplies 0 instead of faulting. // Scalar - HeatSink::DrawCoolant(Scalar /*requested*/) + HeatSink::DrawCoolant(Scalar requested) { - return 0.0f; + HeatSink *linked = (HeatSink *)linkedSinks.Resolve(); // FUN_00417ab4(this+0x59) + requested *= coolantFlowScale; // @0x15C + if (linked == 0) + return 0.0f; + return linked->DrawCoolant(requested); // vtbl+0x38 (virtual) } diff --git a/game/reconstructed/heatfamily_reslice.cpp b/game/reconstructed/heatfamily_reslice.cpp index 6866709..a406697 100644 --- a/game/reconstructed/heatfamily_reslice.cpp +++ b/game/reconstructed/heatfamily_reslice.cpp @@ -870,6 +870,14 @@ Scalar } } coolantLevel -= supplied; + if (getenv("BT_COOL_LOG") && supplied > 0.0f) + { + static int s_n = 0; + if ((s_n++ % 60) == 0) + DEBUG_STREAM << "[resdraw] granted=" << supplied + << " tank=" << coolantLevel << "/" << thermalCapacity + << "\n" << std::flush; + } return supplied; }