From 9b0c1a9459007ec31b30183fc74b1a2d91c59cd1 Mon Sep 17 00:00:00 2001 From: JohnM <234386938+treuenten@users.noreply.github.com> Date: Sat, 10 Oct 2026 00:13:24 +0800 Subject: [PATCH] End a private match from End Game and return to the lobby The Yes button of the pause menu's End Game popup is rewritten to `disconnect` (03016c48). The host of a private match therefore quits instead of ending the match: nobody sees the "Host ended game" end-of-match flow, and the host lands on the main menu with the lobby gone. The button now sends the "endround" menu response to the game scripts, which end the match as host-ended, run the end-of-game display and then end the level, so the host returns to the private lobby. The hud still turns that response into `disconnect` unless the local player hosts a private lobby (ui_lobby_host set, ui_lobby_public not set), so public lobbies and clients leave as they do today. This reverses the end-game leave from 03016c48 for private hosts only. Co-Authored-By: Claude Opus 5.5 --- crates/hud/src/menus/mod.rs | 14 ++++++++++++++ crates/ui/src/menu.rs | 2 +- docs/GSC-RUNTIME.md | 6 +++--- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/crates/hud/src/menus/mod.rs b/crates/hud/src/menus/mod.rs index 26e2689..af28515 100644 --- a/crates/hud/src/menus/mod.rs +++ b/crates/hud/src/menus/mod.rs @@ -789,6 +789,20 @@ fn flush_outputs(menus: &mut ScriptMenus, out: &mut MenuOutputs, local: sim::Cli diag::info!(Ui, "menu exec: {text}"); out.exec.write(UiExecCommand { text }); } + let private_host = out.dvars.get("ui_lobby_host") == Some("1") + && out.dvars.get("ui_lobby_public") != Some("1"); + menus.responses.retain(|(menu, response)| { + let end_game = menu.eq_ignore_ascii_case("popup_endgame") + || menu.eq_ignore_ascii_case("popup_endgame_ranked"); + if !end_game || !response.eq_ignore_ascii_case("endround") || private_host { + return true; + } + diag::info!(Ui, "menu exec: disconnect"); + out.exec.write(UiExecCommand { + text: "disconnect".into(), + }); + false + }); let (Some(inbox), Some(ids)) = (out.inbox.as_mut(), out.ids.as_mut()) else { menus.responses.clear(); return; diff --git a/crates/ui/src/menu.rs b/crates/ui/src/menu.rs index 6359205..f37912a 100644 --- a/crates/ui/src/menu.rs +++ b/crates/ui/src/menu.rs @@ -116,7 +116,7 @@ pub fn install_frontend_menus(catalog: &mut asset_game::MenuCatalog) -> Result<( for item in &mut menu.items { if item.name == "button_yes" { item.handlers.action = vec![asset_game::MenuEvent::Script( - "play mouse_click; close self; exec \"disconnect\";".into(), + "play mouse_click; close self; scriptmenuresponse \"endround\";".into(), )]; } } diff --git a/docs/GSC-RUNTIME.md b/docs/GSC-RUNTIME.md index dcb37a1..4ed8a27 100644 --- a/docs/GSC-RUNTIME.md +++ b/docs/GSC-RUNTIME.md @@ -373,9 +373,9 @@ record is imported or initialized. ## Remaining A live bomb plant/defuse check. Native IW4L menus can create a private lobby, -select a map/mode and start a match. When the match scripts end it, the host -returns to the same private lobby with map, mode and rules kept, as it does when -the map fails to load. A disconnect, including End Game from the pause menu, +select a map/mode and start a match. When the match scripts end it, or the host +picks End Game from the pause menu, the host returns to the same private lobby with +map, mode and rules kept, as it does when the map fails to load. A disconnect returns to the main menu. Browser/public-lobby actions are connected but still need multiplayer validation. Display mode/resolution, brightness, volume, VSync, shadows, depth of field and bloom are bound to runtime settings and persisted locally. Surround output, voice/chat