Boss gate: the exit gate fails closed; it opens only for a boss that spawned and then died
ZonePack.BossSpawned records the spawn, since a dead boss leaves no entity. RunGoal.ExitOpen requires it, so an exit zone without a boss stays sealed, and ZoneGenerator logs that configuration by field and code. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
cb56557b4d
commit
c8d40eaf74
5 changed files with 59 additions and 2 deletions
|
|
@ -11,9 +11,10 @@ public static class RunGoal
|
|||
|
||||
public static bool BossAlive(Zone zone) => Boss(zone) != null;
|
||||
|
||||
// The exit gate is open in the galaxy's exit zone once that zone holds no living boss.
|
||||
// The exit gate fails closed: it is open only in the galaxy's exit zone, once a boss was spawned there and no living
|
||||
// boss remains. An exit zone that never got a boss stays sealed, so a missing boss can never read as a dead one.
|
||||
public static bool ExitOpen(Zone zone) =>
|
||||
zone.Galaxy?.Exit != null && zone.GalaxyZone == zone.Galaxy.Exit && !BossAlive(zone);
|
||||
zone.Galaxy?.Exit != null && zone.GalaxyZone == zone.Galaxy.Exit && zone.Pack.BossSpawned && !BossAlive(zone);
|
||||
|
||||
// Where the exit gate sits: at the adjacency wormholes' radius (the zone's radius times the ratio), in the middle of
|
||||
// the widest angular gap between them, so it shares a point with none. A zone with no neighbours gets the +x axis.
|
||||
|
|
|
|||
|
|
@ -182,6 +182,7 @@ public class Zone
|
|||
Orbits = Orbits.Keys.Select(key => new CultRecordRef<OrbitData>(key)).ToList(),
|
||||
Planets = Planets.Keys.Select(key => new CultRecordRef<BodyData>(key)).ToList(),
|
||||
Time = _time,
|
||||
BossSpawned = Pack.BossSpawned,
|
||||
// Cut 2 (docs/mining-cut.md): drop entries that carry no live information -- healed (no damage) and
|
||||
// not currently broken -- so a save never accumulates wear rows for chunks nobody has touched since
|
||||
// they last respawned.
|
||||
|
|
|
|||
|
|
@ -43,6 +43,11 @@ public class ZonePack
|
|||
// default instance.
|
||||
[JsonProperty("chunkWear"), Key(6)]
|
||||
public List<ChunkWearPack> ChunkWear;
|
||||
|
||||
// True once this zone's boss has been spawned. The dead boss leaves no entity, so this is the one fact that tells a
|
||||
// slain boss from one that never existed; RunGoal.ExitOpen reads it. Written only by ZoneGenerator, carried by PackZone.
|
||||
[JsonProperty("bossSpawned"), Key(7)]
|
||||
public bool BossSpawned;
|
||||
}
|
||||
|
||||
// Cut 2 (docs/mining-cut.md): one packed wear entry for one chunk. "Field" names the body that owns the chunk
|
||||
|
|
|
|||
|
|
@ -349,8 +349,12 @@ public static class ZoneGenerator
|
|||
}
|
||||
boss.Boss = true;
|
||||
pack.Entities.Add(boss);
|
||||
pack.BossSpawned = true;
|
||||
}
|
||||
|
||||
if (galaxyZone == galaxy.Exit && !pack.BossSpawned)
|
||||
itemManager.Log("Galaxy.Exit has no boss: Galaxy.BossZones does not map a boss faction to the exit zone, or its boss could not be generated (ZoneGenerator exit-without-boss). The exit gate stays sealed.");
|
||||
|
||||
if (!ambient) return pack;
|
||||
|
||||
var enemyCount = (int)(random.NextFloat() * factionPresence * 2) + baseStationCount;
|
||||
|
|
|
|||
Loading…
Reference in a new issue