using Unity.Entities; using Unity.NetCode; namespace ProjectM.Simulation { /// /// END-2 — server-only marker of which run-phase the macro loop is in. Lives on the GLOBAL CycleDirector /// entity beside //; NOT replicated /// (the client never needs to distinguish "the final siege is armed" — the larger wave + telegraph already read /// as escalation; the client shows the terminal banner from the replicated instead). /// SINGLE writer: GoalReachedSystem flips -> /// exactly once when reaches Target. /// Added at spawn by CycleDirectorSpawnSystem (like CycleRuntime/ThreatState), so it is server-world-only /// and never on the ghost serializer (no re-hash). A byte (never an enum) so a Bursted reader can't trip /// the cross-assembly-enum Burst ICE. /// public struct RunPhase : IComponentData { public byte Value; } /// Phase constants for (bytes — never an enum on a Bursted path). public static class RunPhaseId { /// Normal play: scheduled / post-expedition sieges arm; the goal meter climbs +1 per survived siege. public const byte Normal = 0; /// The goal cap was reached: the larger FINAL siege is armed/running. No further sieges arm. public const byte FinalDefense = 1; } /// /// END-2 — the terminal run outcome: the LATCHING win/lose state, REPLICATED so the client HUD shows the /// victory/loss banner by simply observing it (no fragile client-side reconstruction). Rides the GLOBAL /// untagged CycleDirector ghost (relevant to every connection in every region — it must NEVER be region-tagged; /// the shared-global-state rule), one [GhostField] byte alongside / /// . SINGLE writer: CyclePhaseSystem latches /// (final siege cleared) or (Core breached during the final siege). Once it is /// non- the run HALTS (GoalReachedSystem + ThreatDirectorSystem stop arming; /// CoreRestoreSystem stops regen). Baked onto the prefab so it is part of the ghost (adding this [GhostField] /// re-hashes the CycleDirector ghost -> one re-bake); born-correct at spawn (InProgress for a New Game, or the /// persisted value on Continue — SaveData v5). /// public struct RunOutcome : IComponentData { [GhostField] public byte Value; } /// Outcome constants for (bytes — never an enum on a Bursted/serialized path). public static class RunOutcomeId { /// The run is live (no terminal result yet). public const byte InProgress = 0; /// The final siege was survived — the Engine holds. Terminal; the run halts. public const byte Victory = 1; /// The Core was breached during the final siege — overrun. Terminal; the run halts. public const byte Loss = 2; } }