LANTERN purge: delete the superseded base/expedition shell (audit H1/H3/M5)

The 2026-08-06 audit found the shipping scene was still the abandoned
co-op-Hades game with LANTERN combat bolted on, and that a third of the
codebase was live code for a direction abandoned on 2026-07-13. Operator
chose deletion over freezing: "everything is saved in source control if
needed. I want the project to be clean."

DELETED (~140 source files, Scripts 335->231, Tests 77->43):
- Enemy variants + boss (H3). ChargerAuthoring / SpitterAuthoring /
  SwarmerAuthoring were attached to ZERO prefabs, so LungeState /
  SpitterState / SwarmerTag were never baked: ~272 lines of Bursted AI
  passes, BossAISystem (261 lines) and the whole MixBands escalation
  curve could not match a single chunk at runtime, while 734 lines of
  green tests certified them. Both shipping enemy prefabs were already
  byte-identical in stats.
- Run/room lifecycle: RunDirector FSM, RunInfo/RunMap/RoomPlan/RoomTag,
  route select, portal interact, ready-check, room field/teardown.
- Meta shop, prep loadout, boons (incl. KillRewardSystem and
  DashTrailDamageSystem, which existed only to serve boon flags).
- Build palette + structures, shared storage, inventory/equipment
  (already recorded PAUSED in CLAUDE.md).
- The HUD panels driving all of the above (HudSystem 1168 -> 610).

KEPT deliberately: BaseGridMath + BaseAnchor (8 systems use PlotCenter
for spawn rings, respawn and dynamic light), the resource ledger +
StorageMath, the save system, region/relevancy. Three of these were in
the delete set until I checked their consumers — worth remembering that
the file-level manifest was wrong about them.

Also folds in audit finding M5: PlayerClass was a second, server-only
copy of the byte FrameId already replicates. It existed for the meta
shop; with that gone, FrameId is the single frame identity.

Harvest is now single-sink (ledger). HarvestMath keeps its shape so
LANTERN's carried-vs-banked cargo split lands in one place, not two.

295/295 EditMode green, zero compile errors. Subscene re-bake and Play
validation follow in the next commit.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-07 12:59:39 -07:00
parent 6a412fe3e7
commit 62e48a3b0b
304 changed files with 260 additions and 14591 deletions
@@ -48,20 +48,9 @@ namespace ProjectM.Server
var wave = SystemAPI.GetComponent<WaveState>(directorEntity);
// MC-2 fork-4a: the base siege adopts the 4-type weighted mix (BaseCount = the Grunt base). The size
// curve becomes WaveSlots(wave, bands) — a deliberate, operator-approved redefinition; MaxAlive is the
// mandatory cap so spitter spits + swarmer packs can't spike the relevancy loop during the END-game climax.
var bands = new MixBands
{
GruntBase = director.BaseCount,
ChargerBase = director.ChargerBase,
SpitterBase = director.SpitterBase,
SwarmerSlotBase = director.SwarmerSlotBase,
ChargerPerEpoch = director.ChargerPerEpoch,
SpitterPerEpoch = director.SpitterPerEpoch,
SwarmerSlotPerEpoch = director.SwarmerSlotPerEpoch,
SwarmerPackPerEpoch = director.SwarmerPackPerEpoch,
};
// 2026-08-07 audit purge: the 4-type weighted mix (MixBands) is gone. Its Charger/Spitter/Swarmer
// authoring was on ZERO prefabs, so every weighted slot resolved to Grunt at runtime anyway. MaxAlive
// stays the mandatory cap on the relevancy loop.
// Ring centre on the base plot when present.
float3 center = new float3(0f, 1f, 0f);
@@ -77,7 +66,7 @@ namespace ProjectM.Server
{
// Start the next (bigger) wave.
wave.WaveNumber += 1;
wave.RemainingToSpawn = ZoneEnemyMath.WaveSlots(wave.WaveNumber, bands);
wave.RemainingToSpawn = ZoneEnemyMath.WaveSize(wave.WaveNumber, director.BaseCount);
wave.Phase = WavePhase.Spawning;
wave.NextActionTick = TickUtil.NonZero(now); // spawn the first Husk this tick
}
@@ -89,9 +78,8 @@ namespace ProjectM.Server
if (dueNow)
{
int slots = math.max(1, director.RingSlots);
byte kind = ZoneEnemyMath.KindForSlot(wave.WaveNumber, wave.SpawnCounter, bands);
int packSize = kind == ZoneEnemyMath.KindSwarmer
? ZoneEnemyMath.PackSizeForSlot(wave.WaveNumber, wave.SpawnCounter, bands, director.SwarmerPackSize) : 1;
const byte kind = ZoneEnemyMath.KindGrunt;
const int packSize = 1;
// Live BASE husks for the entity cap (expedition zone enemies are EnemyTag too -> excluded).
int aliveBase = 0;