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:
@@ -0,0 +1,34 @@
|
||||
using Unity.Entities;
|
||||
using Unity.NetCode;
|
||||
|
||||
namespace ProjectM.Simulation
|
||||
{
|
||||
/// <summary>
|
||||
/// END-1 — the losable Engine Core. An aggregate base-integrity meter that rides the GLOBAL CycleDirector
|
||||
/// ghost (the untagged ghost already carrying <see cref="CycleState"/>/<see cref="GoalProgress"/>/the resource
|
||||
/// ledger), so it is visible to every player regardless of region with NO new ghost and NO relevancy work — it
|
||||
/// must NEVER be region-tagged (the shared-global-state rule; <c>SetIsIrrelevant</c> would hide it cross-region).
|
||||
/// <para>
|
||||
/// A Husk that breaches to the Core radius drains <see cref="Current"/> and despawns (server-only
|
||||
/// <c>CoreDamageSystem</c>); in Calm the Core regenerates toward <see cref="Max"/> (<c>CoreRestoreSystem</c>) so a
|
||||
/// chipped-but-survived base reads as "we got hurt but we're okay." When <see cref="Current"/> reaches 0 during a
|
||||
/// Siege the SOFT-loss edge fires once in <c>CyclePhaseSystem</c> (the sole Phase writer): the siege ends, the
|
||||
/// shared ledger is drained, the base persists wounded (no rollback — the locked DR-029 fork). <see cref="Max"/> is
|
||||
/// baked from <c>CycleDirectorAuthoring</c>; <see cref="Current"/> is born-correct at spawn (full, or the persisted
|
||||
/// wounded value from a Continue save).
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public struct CoreIntegrity : IComponentData
|
||||
{
|
||||
/// <summary>Current integrity (0 = breached/overrun). Server-authoritative; replicated for the HUD bar.</summary>
|
||||
[GhostField] public int Current;
|
||||
|
||||
/// <summary>Integrity ceiling (baked from authoring; not persisted — a restored Core caps at the baked Max).</summary>
|
||||
[GhostField] public int Max;
|
||||
|
||||
/// <summary>Server tick of the most recent overrun breach (0 = never). A TRANSIENT pulse the client HUD
|
||||
/// edge-detects to flash a "BASE OVERRUN" banner — a SOFT loss is non-terminal ("keep playing"), so this is
|
||||
/// the right shape, not a latching run-outcome (the terminal Victory latch is END-2's job).</summary>
|
||||
[GhostField] public uint OverrunTick;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a933c59d7c550d844b615e3672b333f6
|
||||
Reference in New Issue
Block a user