Docs: END-1 session log + DR-034; CLAUDE.md losable-core bullet
DR-034 records the losable-Core decisions: CoreIntegrity on the global ghost, the soft-loss edge inside CyclePhaseSystem, the Core-as-fallback-target and despawn-on-breach forks, the transient OverrunTick (vs END-2's latching outcome), and SaveData v4. Session log captures the build + validation (330/330 EditMode; Play-verified server==client drain->regen->replicate). CLAUDE.md adds the END-1 bullet; EB-1/EB-2/inventory bullets condensed net-neutral to stay under the size budget. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
---
|
||||
id: DR-034
|
||||
title: END-1 — a losable Engine Core (soft-loss base-integrity meter)
|
||||
status: accepted
|
||||
date: 2026-06-12
|
||||
tags:
|
||||
- decision
|
||||
- design
|
||||
- endgame
|
||||
- netcode
|
||||
- end-1
|
||||
permalink: gamevault/07-sessions/decisions/dr-034-end1-losable-core
|
||||
---
|
||||
|
||||
# DR-034 — END-1: The Base Can Be Lost (a Core with Integrity)
|
||||
|
||||
> Path A milestone (the first **Endgame** beat); forks locked in [[DR-029_Path_A_Fork_Locks]]. Continues the economy braid [[DR-032_EB1_Machines_Can_Die]] · [[DR-033_EB2_Felt_Spend_Charge_Economy]]. Spec: [[Path_to_Fun#END-1 — The base can be lost: a Core with integrity]]. Session: [[2026-06-12_END1_Losable_Core]].
|
||||
|
||||
## Context
|
||||
|
||||
EB-1 made structures losable; EB-2 made defense *cost* the harvest. But the base still had no **aggregate** loss condition — a siege could chew machines yet never actually *take the base*. END-1 adds the **Engine Core**: a base-integrity meter a breaking-through siege drains, giving the siege teeth without a hard game-over (the locked **soft-loss** fork).
|
||||
|
||||
## Decision
|
||||
|
||||
**1. `CoreIntegrity` rides the GLOBAL CycleDirector ghost** — `{[GhostField] int Current, Max; [GhostField] uint OverrunTick}`. No new ghost, no relevancy work (the shared-global-state rule — it must never be region-tagged). `Max` is baked from `CycleDirectorAuthoring` (default 100); `Current` is born-correct at spawn (full, or the persisted wounded value). Adding the `[GhostField]` re-hashes the runtime-spawned director ghost — server and client bake the same prefab so the hash matches (Play-verified server==client).
|
||||
|
||||
**2. Two new server-only plain-group systems:**
|
||||
- `CoreDamageSystem` `[UpdateAfter(EnemyAISystem)]` — a Husk within ~3u (`CoreReachRadius`, structural const) of `BaseGridMath.PlotCenter` BREACHES: drains `CoreDamagePerHusk` and is **consumed** (despawned, at-most-once ECB). Reads each Husk's post-move position. Idles once `Current<=0` (the lose-edge owns resolution).
|
||||
- `CoreRestoreSystem` — regenerates +1 every `CoreRegenIntervalTicks` **ONLY in Calm** (deterministic server-only `now % interval` gate). A chipped-but-survived Core heals between sieges, so a breach is a setback, not a death spiral.
|
||||
|
||||
**3. The SOFT-loss edge lives INSIDE `CyclePhaseSystem`** (which stays the sole Phase/WaveState writer — no second Phase writer, dodging the documented invisible-cycle hazard). In the Siege branch, checked BEFORE survival: `Current<=0` →
|
||||
- flip to **Calm** with **NO** `GoalProgress` reward (you were overrun, not survived);
|
||||
- drain a fraction (`CoreOverrunDrainPct`, default 0.5) of the shared `StorageEntry` ledger via the new pure `StorageMath.DrainFraction`;
|
||||
- **despawn every remaining Husk** (the locked "siege ends on breach" fork) + reset `WaveState`;
|
||||
- stamp `OverrunTick` (a TRANSIENT pulse, see decision 5);
|
||||
- autosave the wounded state.
|
||||
|
||||
**4. The Core is a FALLBACK target in `EnemyAISystem`** (the locked targeting fork — present-the-forks ritual, 2026-06-12). When no living player/structure remains, undefended Husks march on `PlotCenter` (target `Entity.Null`, the `DamageEvent` strike append is guarded — the Core takes damage only via the proximity `CoreDamageSystem`, not the strike path). This guarantees "a Husk the team fails to intercept walks to the Engine" instead of the swarm idling, **without** the Core competing with structures (preserving EB-1's structure-destruction stakes).
|
||||
|
||||
**5. `OverrunTick` is a transient pulse, NOT a latching `RunOutcome`** — a *deliberate deviation* from the spec's literal "sets `RunOutcome{Overrun}`". A SOFT loss is **non-terminal** ("keep playing"), so a latching terminal outcome is the wrong shape; the HUD edge-detects the `OverrunTick` change and flashes a ~3.5s "BASE OVERRUN" banner. The latching `RunOutcome` (Victory) is deferred to **END-2**, where a win genuinely latches.
|
||||
|
||||
**6. Persistence: `SaveData` → v4** adds `CoreCurrent` (additive; `MinLoadableVersion` stays 2). A pre-v4 save lacks the field → JsonUtility defaults it to 0 → born-correct maps 0 → baked Max (full), reusing EB-1's exact HP `0→Max` sentinel convention. A wounded base persists across save/quit (the locked fork).
|
||||
|
||||
**7. Three live `TuningConfig` knobs** (with baked fallbacks): `CoreDamagePerHusk` (10), `CoreRegenIntervalTicks` (18), `CoreOverrunDrainPct` (0.5). `CoreReachRadius` stays a structural const. HUD: a red Core-integrity bar mirroring the GoalProgress bar.
|
||||
|
||||
## Locked forks (END-1)
|
||||
|
||||
Per [[DR-029_Path_A_Fork_Locks]] + the 2026-06-12 present-the-forks pass:
|
||||
- **Lose-severity = SOFT** (drain ledger + end siege + persist wounded; no rollback).
|
||||
- **Breach drains the Core bar only** — structure destruction stays EB-1's job.
|
||||
- **Wounded base persists** in SaveData v4.
|
||||
- **Core targeting = FALLBACK** (sought only when no live player/structure) — *recommended option, operator-chosen 2026-06-12* (vs. always-weighted vs. proximity-only).
|
||||
- **Breach resolution = despawn remaining Husks** (clean reset-to-recover) — *operator-chosen 2026-06-12*.
|
||||
|
||||
## Consequences
|
||||
|
||||
- A real lose condition exists: an undefended base gets overrun, loses resources, and ends the siege wounded — the stakes the whole economy is for.
|
||||
- **END-2 hooks:** `RunOutcome` (latching Victory byte) is END-2's to add on the same director ghost; the soft-loss `OverrunTick`/banner path is reused for the win banner.
|
||||
- Reversible: lose-severity/damage/regen/drain are live singletons; the soft-vs-hard byte was NOT added (DR-029 locked soft) — a future hard-rollback mode would add it + host reload infra.
|
||||
- 330/330 EditMode green (+12 END-1); Play-validated server==client + live drain→regen→replicate.
|
||||
Reference in New Issue
Block a user