END-1: the base can be lost - a losable Engine Core with integrity

Adds CoreIntegrity{[GhostField] Current,Max,OverrunTick} on the GLOBAL
CycleDirector ghost (no new ghost/relevancy). CoreDamageSystem (server,
after EnemyAISystem): a Husk within ~3u of PlotCenter drains + is consumed;
CoreRestoreSystem regenerates only in Calm. The SOFT-loss edge lives inside
CyclePhaseSystem (sole Phase writer): Current<=0 in Siege flips to Calm with
NO goal reward, StorageMath.DrainFraction drains the shared ledger, all Husks
despawn, and OverrunTick is stamped (a transient HUD-flash pulse, not a
latching outcome - the Victory latch is END-2's). EnemyAISystem treats the
Core as a FALLBACK target so an undefended base is overrun instead of idling.
SaveData -> v4 persists CoreCurrent (0 -> born full, the EB-1 HP sentinel);
3 live TuningConfig knobs + a red HUD Core bar. Soft-loss + targeting +
breach-resolution forks operator-locked.

See DR-034.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-12 21:51:43 -07:00
parent 3fdac3517b
commit 60e1e21dd3
18 changed files with 396 additions and 16 deletions
@@ -36,6 +36,12 @@ namespace ProjectM.Server
? SystemAPI.GetComponent<GoalProgress>(dir)
: default;
// END-1: persist the Engine Core integrity (a wounded base stays wounded across save/quit).
var core = SystemAPI.HasComponent<CoreIntegrity>(dir)
? SystemAPI.GetComponent<CoreIntegrity>(dir)
: default;
// The shared ledger lives on this same CycleDirector ghost (ResourceLedger-tagged StorageEntry buffer).
var buffer = SystemAPI.GetBuffer<StorageEntry>(dir);
var rows = new LedgerRow[buffer.Length];
@@ -50,6 +56,8 @@ namespace ProjectM.Server
{
GoalCharge = goal.Charge,
GoalTarget = goal.Target,
CoreCurrent = core.Current,
Ledger = rows,
Structures = structures,
StructureIo = structureIo,