END-2: final siege + latching win/lose (SL-3)
At GoalProgress.Charge>=Target a new server-only GoalReachedSystem arms a larger final siege (x live FinalSiegeMultiplier) and flips RunPhase=FinalDefense; CyclePhaseSystem latches a REPLICATED RunOutcome (Victory on clear / Loss on Core breach) and halts the director. RunOutcome is a [GhostField] byte on the global CycleDirector ghost (the client banner observes it); RunPhase stays server-only. ThreatDirector/CoreRestore/CoreDamage halt once decided; SiegeTimeout is off during the final siege. SaveData v5 persists the outcome so a won/lost run loads finished. GoalProgress.Target 10->4. Completes Path A's spine. See DR-036. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -64,6 +64,10 @@ namespace ProjectM.Client
|
||||
Label _coreText;
|
||||
uint _lastOverrunTick;
|
||||
float _overrunFlashLeft;
|
||||
// END-2: terminal win/loss banner (observes the replicated RunOutcome; latched server-side).
|
||||
VisualElement _runBanner;
|
||||
Label _runBannerText, _runBannerSub;
|
||||
|
||||
|
||||
readonly List<VisualElement> _pips = new();
|
||||
|
||||
@@ -250,6 +254,21 @@ namespace ProjectM.Client
|
||||
_locationText.text = "BASE OVERRUN - resources lost; the Core will recover";
|
||||
_locationText.style.color = new Color(1f, 0.3f, 0.25f);
|
||||
}
|
||||
// ---- END-2: terminal run banner (Victory / Loss), observed from the replicated RunOutcome ----
|
||||
if (SystemAPI.TryGetSingleton<RunOutcome>(out var runOutcome) && runOutcome.Value != RunOutcomeId.InProgress)
|
||||
{
|
||||
bool win = runOutcome.Value == RunOutcomeId.Victory;
|
||||
_runBanner.style.display = DisplayStyle.Flex;
|
||||
_runBannerText.text = win ? "THE ENGINE HOLDS" : "OVERRUN";
|
||||
_runBannerText.style.color = win ? new Color(0.45f, 0.95f, 1f) : new Color(1f, 0.35f, 0.3f);
|
||||
_runBannerSub.text = win ? "VICTORY - the final siege is broken" : "THE FINAL STAND FELL";
|
||||
_runBannerSub.style.color = win ? new Color(0.7f, 0.95f, 1f) : new Color(1f, 0.6f, 0.5f);
|
||||
}
|
||||
else
|
||||
{
|
||||
_runBanner.style.display = DisplayStyle.None;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ---- Threat readout (top-right) — hidden entirely at base with zero husks; its reappearance is the cue ----
|
||||
@@ -565,6 +584,7 @@ namespace ProjectM.Client
|
||||
BuildHintBar(root);
|
||||
BuildDowned(root);
|
||||
BuildInventory(root);
|
||||
BuildRunBanner(root);
|
||||
}
|
||||
|
||||
void BuildVignette(VisualElement root)
|
||||
@@ -839,6 +859,29 @@ namespace ProjectM.Client
|
||||
_downed.style.display = DisplayStyle.None;
|
||||
root.Add(_downed);
|
||||
}
|
||||
void BuildRunBanner(VisualElement root)
|
||||
{
|
||||
_runBanner = new VisualElement();
|
||||
_runBanner.style.position = Position.Absolute;
|
||||
_runBanner.style.left = 0; _runBanner.style.right = 0; _runBanner.style.top = 0; _runBanner.style.bottom = 0;
|
||||
_runBanner.style.alignItems = Align.Center;
|
||||
_runBanner.style.justifyContent = Justify.Center;
|
||||
_runBanner.pickingMode = PickingMode.Ignore;
|
||||
_runBanner.style.backgroundColor = new Color(0.02f, 0.03f, 0.05f, 0.55f);
|
||||
var col = HudUi.Group(Align.Center);
|
||||
_runBannerText = HudUi.Display("", 72, Color.white, TextAnchor.MiddleCenter);
|
||||
col.Add(_runBannerText);
|
||||
_runBannerSub = HudUi.Text("", 22, MenuUi.SubCol, TextAnchor.MiddleCenter);
|
||||
_runBannerSub.style.marginTop = 8;
|
||||
col.Add(_runBannerSub);
|
||||
var hint = HudUi.Text("Esc - menu", 15, MenuUi.SubCol, TextAnchor.MiddleCenter);
|
||||
hint.style.marginTop = 24;
|
||||
col.Add(hint);
|
||||
_runBanner.Add(col);
|
||||
_runBanner.style.display = DisplayStyle.None;
|
||||
root.Add(_runBanner);
|
||||
}
|
||||
|
||||
|
||||
void BuildInventory(VisualElement root)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user