From 04d50c924279b8c20addadf6230e311056e90455 Mon Sep 17 00:00:00 2001 From: arcattack Date: Tue, 21 Jul 2026 10:54:09 -0500 Subject: [PATCH] FE menu: BT_FE_SOLO=1 trims to a solo-only menu (play_solo.bat) The user hit the full session menu from play_solo -- HOST/JOIN LAN modes, NET PORT and the Steam buttons don't belong in the solo flow (LAN goes through the join bats + operator; Steam through play_steam.bat). BT_FE_SOLO=1 (set by play_solo.bat + the btoperator generated bat): - the MODE cycle keeps only the two solo entries (kModes lists them first: SOLO MISSION, RAW SOLO) via the GroupSize clamp - NET PORT row and the HOST/JOIN STEAM buttons are not laid out - a stale fe_last.ini mode of hostlan/joinlan is rejected by the existing LoadPersisted GroupSize clamp, so the selection can never land on a hidden mode play_steam.bat keeps the full menu. Co-Authored-By: Claude Opus 4.8 (1M context) --- game/glass/btl4fe.cpp | 34 ++++++++++++++++++++++++++++++---- players/play_solo.bat | 1 + tools/btoperator.py | 2 +- 3 files changed, 32 insertions(+), 5 deletions(-) diff --git a/game/glass/btl4fe.cpp b/game/glass/btl4fe.cpp index d91f53f..489718f 100644 --- a/game/glass/btl4fe.cpp +++ b/game/glass/btl4fe.cpp @@ -568,6 +568,26 @@ static MenuState menu; static const COLORREF kGreenBright = RGB(64, 255, 64); static const COLORREF kGreenDim = RGB(24, 140, 24); +// +// BT_FE_SOLO=1 (play_solo.bat): a SOLO-ONLY menu. The mode cycle keeps just +// the two solo entries (kModes lists them FIRST: solo, raw), and the network +// rows/buttons (NET PORT, HOST/JOIN STEAM) are not laid out -- LAN play goes +// through the join bats + operator, Steam through play_steam.bat. A stale +// fe_last.ini mode of hostlan/joinlan is rejected by the GroupSize clamp in +// LoadPersisted, so the selection can never land on a hidden mode. +// +static int + FeSoloOnly() +{ + static int s = -1; + if (s < 0) + { + const char *e = getenv("BT_FE_SOLO"); + s = (e != NULL && *e != '0') ? 1 : 0; + } + return s; +} + static int GroupSize(int group) { @@ -585,7 +605,7 @@ static int case GroupPatch: return COUNT(kPatches); case GroupDropZone: return COUNT(kDropZones); case GroupAdvDamage: return COUNT(kAdvDamage); - case GroupMode: return COUNT(kModes); + case GroupMode: return FeSoloOnly() ? 2 : COUNT(kModes); // solo, raw case GroupPort: return COUNT(kPorts); default: return 1; } @@ -713,13 +733,19 @@ static void // col4: emblem + patch y = MenuTopY; AddGroup(GroupBadge, MenuCol4X, &y); AddGroup(GroupPatch, MenuCol4X, &y); - // col5: the session + controls + // col5: the session + controls (solo-only: no net port, no steam buttons) y = MenuTopY; AddGroup(GroupMode, MenuCol5X, &y); + if (!FeSoloOnly()) + { AddGroup(GroupPort, MenuCol5X, &y); + } AddButton(GroupLaunch, MenuCol5X, MenuClientH - 190, 220, 52); #ifdef BT_STEAM - AddButton(GroupSteamHost, MenuCol5X, MenuClientH - 120, 220, 34); - AddButton(GroupSteamJoin, MenuCol5X, MenuClientH - 76, 220, 34); + if (!FeSoloOnly()) + { + AddButton(GroupSteamHost, MenuCol5X, MenuClientH - 120, 220, 34); + AddButton(GroupSteamJoin, MenuCol5X, MenuClientH - 76, 220, 34); + } #endif } diff --git a/players/play_solo.bat b/players/play_solo.bat index fa95826..8a9e58c 100644 --- a/players/play_solo.bat +++ b/players/play_solo.bat @@ -13,6 +13,7 @@ if not exist "content\OPERATOR.EGG" goto badpath set BT_START_INSIDE=1 set BT_DEV_GAUGES=1 set BT_LOG=join.log +set BT_FE_SOLO=1 cd content ..\build\Release\btl4.exe echo. diff --git a/tools/btoperator.py b/tools/btoperator.py index 98c40e5..512b040 100644 --- a/tools/btoperator.py +++ b/tools/btoperator.py @@ -857,7 +857,7 @@ class Operator(QMainWindow): "rem experience, weather, length; the menu returns after each " "mission).\n", "set BT_START_INSIDE=1\nset BT_DEV_GAUGES=1\n" - "set BT_LOG=join.log\n", + "set BT_LOG=join.log\nset BT_FE_SOLO=1\n", "..\\build\\Release\\btl4.exe\n", "echo.\necho The game has exited. If it closed unexpectedly,\n" "echo send the operator content\\join.log.\npause\n"))