Read live armor from the persistent combat ledger

- The ship console's CURRENT HULL / SHIELDS now reflect the combat system's hull and shields values at all times, not just while a fight is active.
- Previously, with no combat running the plate fell back to the maxima, masking damage that persists between fights until a landing or jump-arrival repair.
- Updated the shipScreen.json comment and ShipScreenModel docs to describe the ledger as persistent across fights and clarify `nominalLabel` is an at-full copy, not an out-of-combat flag.
This commit is contained in:
Brian Fertig 2026-09-30 18:53:41 -06:00
parent 97607ec984
commit 57024084f4
3 changed files with 20 additions and 10 deletions

View File

@ -105,7 +105,7 @@
"hotBelow": 0.34
},
{
"_comment": "CURRENT HULL \u2014 the armor actually on the ship right now (the live fight's hull; full strength with no fight running).",
"_comment": "CURRENT HULL \u2014 the armor actually on the ship right now (the combat ledger's hull; it persists between fights and reads full once a landing or jump-arrival repairs it).",
"id": "hullNow",
"group": "armor",
"label": "CURRENT HULL",

View File

@ -8923,21 +8923,26 @@ export class GameScene extends Phaser.Scene {
const s = this.ship;
if (!s) return null;
const c = this.combat;
const fighting = !!(c && c.active);
// The maxima come from the combat system when it exists — that's where
// the per-level armor bump lands (progression.reward.hullPerLevel /
// shieldPerLevel), so the plate never shows a stale base number.
const hullMax = Math.max(1, Math.round(Number(c?.maxHull ?? s.stats?.hullIntegrity) || 0));
const shieldsMax = Math.max(0, Math.round(Number(c?.maxShields ?? s.stats?.shields) || 0));
// The CURRENT armor is the combat system's ledger too — it PERSISTS
// between fights (damage only heals on a landing's repairFull or a
// jump's arrival repair), so the plate reads it even when no pack is
// live: a fight over at half hull is still flying at half hull.
const hullNow = c ? Math.max(0, Math.round(Number(c.hull) || 0)) : hullMax;
const shieldsNow = c ? Math.max(0, Math.round(Number(c.shields) || 0)) : shieldsMax;
// THE SKILL TREE DOOR — the ship console's standby tab lights the moment the
// run's class owns a tree (data/skills.json → classes.<id>.skills).
const skillDoor = !!(this.classState?.hasClass && skillHasTree(this.classState.id));
return {
skillDoor,
live: {
hull: fighting ? Math.max(0, Math.round(Number(c.hull) || 0)) : hullMax,
hull: hullNow,
hullMax,
shields: fighting ? Math.max(0, Math.round(Number(c.shields) || 0)) : shieldsMax,
shields: shieldsNow,
shieldsMax,
},
ship: {

View File

@ -12,12 +12,17 @@
* 'ship:<dotted path>' a field of the ship snapshot (stats.cargoHold,
* minerals, credits, cargo.used …) — state the run
* mutates (upgrades, ore, buys/sells).
* 'live:<key>' the LIVE combat session's armor (hull / hullMax /
* shields / shieldsMax), folded by GameScene: while
* a fight runs these are the session's values, and
* with no fight they read the maxima (the ship is
* never damaged out of combat — the plate says so
* through the row's `nominalLabel`).
* 'live:<key>' the combat session's armor (hull / hullMax /
* shields / shieldsMax), folded by GameScene:
* the combat system's ledger PERSISTS between
* fights (damage only heals on a landing's
* repairFull or a jump's arrival repair), so
* these read the run's current armor whether a
* fight is live or not — and only with no combat
* system do they read the maxima (a fresh, never-
* flown ship). The `nominalLabel` is the row's
* at-full copy (hull at its limit is 'NOMINAL'),
* not an out-of-combat flag.
*
* Optional per-row math: op 'reciprocal' (a cooldown → a rate) and, for an
* array of sources, op 'product' (damage × shots/sec = DPS). A row's meter is