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:
@@ -1,4 +1,5 @@
|
||||
using Unity.Entities;
|
||||
using Unity.Entities;using Unity.Mathematics;
|
||||
|
||||
|
||||
namespace ProjectM.Simulation
|
||||
{
|
||||
@@ -71,5 +72,28 @@ namespace ProjectM.Simulation
|
||||
total += buffer[i].Count;
|
||||
return total;
|
||||
}
|
||||
|
||||
/// <summary>END-1 soft-loss penalty: remove a FRACTION (0..1) of EVERY row, floored per row, dropping any
|
||||
/// row that hits zero. Pure/deterministic (no RNG, no wall-clock), Burst-safe; iterates back-to-front so a
|
||||
/// dropped row never skips its successor. No-op for fraction <= 0.</summary>
|
||||
public static void DrainFraction(DynamicBuffer<StorageEntry> buffer, float fraction)
|
||||
{
|
||||
fraction = math.clamp(fraction, 0f, 1f);
|
||||
if (fraction <= 0f)
|
||||
return;
|
||||
for (int i = buffer.Length - 1; i >= 0; i--)
|
||||
{
|
||||
var entry = buffer[i];
|
||||
int drop = (int)math.floor(entry.Count * fraction);
|
||||
if (drop <= 0)
|
||||
continue;
|
||||
entry.Count -= drop;
|
||||
if (entry.Count <= 0)
|
||||
buffer.RemoveAt(i);
|
||||
else
|
||||
buffer[i] = entry;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user