From e94b2948c7b20e4b12764dab6ae56fc804ea27e3 Mon Sep 17 00:00:00 2001 From: Luis Gonzalez Date: Mon, 15 Jun 2026 13:20:22 -0700 Subject: [PATCH] SL-5: retry/quit actions on the END-2 win/loss banner The terminal banner gains PLAY AGAIN + QUIT TO MENU buttons so a finished run has a clear action (no Esc-hunting). PLAY AGAIN restarts a fresh Single run via WorldLauncher.StartSession (the proven menu lifecycle, no save load); QUIT TO MENU reuses TeardownToMenu (autosave + menu); both self-guard on WorldLauncher.Busy. The button row picks (Position) under the Ignore banner root, matching the build-palette idiom. AimReticleSystem (the sole Cursor.visible writer) keeps the cursor visible while RunOutcome != InProgress so the buttons are clickable regardless of aim state. 342/342 EditMode green. Co-op retry-together stays a cut slice-limit (a client's Play Again starts a solo run). See DR-036. Co-Authored-By: Claude Opus 4.8 --- .../Client/Presentation/AimReticleSystem.cs | 5 ++++- .../Scripts/Client/Presentation/HudSystem.cs | 16 +++++++++++++--- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/Assets/_Project/Scripts/Client/Presentation/AimReticleSystem.cs b/Assets/_Project/Scripts/Client/Presentation/AimReticleSystem.cs index 2afa82da7..5895f9785 100644 --- a/Assets/_Project/Scripts/Client/Presentation/AimReticleSystem.cs +++ b/Assets/_Project/Scripts/Client/Presentation/AimReticleSystem.cs @@ -144,7 +144,10 @@ namespace ProjectM.Client // Hide the OS cursor only while aiming AND focused; restore otherwise (focus loss / pre-spawn) so an // unfocused editor or a windowed session is never stranded with an invisible pointer. - bool wantHidden = haveTarget && Application.isFocused && !AimPresentation.ForceCursorVisible; + // END-2: while the run is over (terminal banner up) keep the cursor visible so the player can click the + // Play Again / Quit buttons, regardless of aim state. AimReticleSystem is the sole Cursor.visible writer. + bool runOver = SystemAPI.TryGetSingleton(out var ro) && ro.Value != RunOutcomeId.InProgress; + bool wantHidden = haveTarget && Application.isFocused && !AimPresentation.ForceCursorVisible && !runOver; if (wantHidden != _cursorHidden) { if (wantHidden) Cursor.lockState = CursorLockMode.None; diff --git a/Assets/_Project/Scripts/Client/Presentation/HudSystem.cs b/Assets/_Project/Scripts/Client/Presentation/HudSystem.cs index 5c001e733..050a525c4 100644 --- a/Assets/_Project/Scripts/Client/Presentation/HudSystem.cs +++ b/Assets/_Project/Scripts/Client/Presentation/HudSystem.cs @@ -883,9 +883,19 @@ namespace ProjectM.Client _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); + // END-2 (SL-5): the terminal banner offers a clear action so the player isn't hunting for Esc. + // PLAY AGAIN restarts a fresh Single run via the proven menu lifecycle; QUIT TO MENU reuses the teardown. + // Both self-guard on WorldLauncher.Busy. The row picks (Position) even though the banner root Ignores. + var btnRow = new VisualElement(); + btnRow.style.flexDirection = FlexDirection.Row; + btnRow.style.justifyContent = Justify.Center; + btnRow.style.marginTop = 28; + btnRow.pickingMode = PickingMode.Position; + var again = MenuUi.Button("PLAY AGAIN", () => WorldLauncher.StartSession(SessionMode.Single, null, false)); + again.style.marginRight = 12; + btnRow.Add(again); + btnRow.Add(MenuUi.Button("QUIT TO MENU", WorldLauncher.TeardownToMenu)); + col.Add(btnRow); _runBanner.Add(col); _runBanner.style.display = DisplayStyle.None; root.Add(_runBanner);