From 99d8e33cfded7068bf9581b7e75abbc233a348b9 Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 14 Sep 2025 22:32:57 +0100 Subject: [PATCH 1/3] Net-safe item toggle menu Use cvar callbacks for items-thunderdome relationship & sounds --- src/cvars.cpp | 70 ++++++++++++----------- src/d_netcmd.c | 22 +++++++ src/menus/options-gameplay-item-toggles.c | 40 ++++++++----- 3 files changed, 85 insertions(+), 47 deletions(-) diff --git a/src/cvars.cpp b/src/cvars.cpp index 63b1f7f90..7c32f9b6d 100644 --- a/src/cvars.cpp +++ b/src/cvars.cpp @@ -666,40 +666,42 @@ consvar_t cv_cheats = UnsavedNetVar(cvlist_command)("cheats", consvar_t cv_countdowntime = UnsavedNetVar("countdowntime", "30").min_max(15, 9999); consvar_t cv_duelspectatorreentry = UnsavedNetVar("duelspectatorreentry", "180").min_max(0, 10*60); +void KartItem_OnChange(void); + // SRB2kart consvar_t cv_items[] = { - UnsavedNetVar("sneaker", "On").on_off(), - UnsavedNetVar("rocketsneaker", "On").on_off(), - UnsavedNetVar("invincibility", "On").on_off(), - UnsavedNetVar("banana", "On").on_off(), - UnsavedNetVar("eggmark", "On").on_off(), - UnsavedNetVar("orbinaut", "On").on_off(), - UnsavedNetVar("jawz", "On").on_off(), - UnsavedNetVar("mine", "On").on_off(), - UnsavedNetVar("landmine", "On").on_off(), - UnsavedNetVar("ballhog", "On").on_off(), - UnsavedNetVar("selfpropelledbomb", "On").on_off(), - UnsavedNetVar("grow", "On").on_off(), - UnsavedNetVar("shrink", "On").on_off(), - UnsavedNetVar("lightningshield", "On").on_off(), - UnsavedNetVar("bubbleshield", "On").on_off(), - UnsavedNetVar("flameshield", "On").on_off(), - UnsavedNetVar("hyudoro", "On").on_off(), - UnsavedNetVar("pogospring", "On").on_off(), - UnsavedNetVar("superring", "On").on_off(), - UnsavedNetVar("kitchensink", "On").on_off(), - UnsavedNetVar("droptarget", "On").on_off(), - UnsavedNetVar("gardentop", "On").on_off(), - UnsavedNetVar("gachabom", "On").on_off(), - UnsavedNetVar("stoneshoe", "On").on_off(), - UnsavedNetVar("toxomister", "On").on_off(), - UnsavedNetVar("dualsneaker", "On").on_off(), - UnsavedNetVar("triplesneaker", "On").on_off(), - UnsavedNetVar("triplebanana", "On").on_off(), - UnsavedNetVar("tripleorbinaut", "On").on_off(), - UnsavedNetVar("quadorbinaut", "On").on_off(), - UnsavedNetVar("dualjawz", "On").on_off(), - UnsavedNetVar("triplegachabom", "On").on_off(), + UnsavedNetVar("sneaker", "On").on_off().onchange_noinit(KartItem_OnChange), + UnsavedNetVar("rocketsneaker", "On").on_off().onchange_noinit(KartItem_OnChange), + UnsavedNetVar("invincibility", "On").on_off().onchange_noinit(KartItem_OnChange), + UnsavedNetVar("banana", "On").on_off().onchange_noinit(KartItem_OnChange), + UnsavedNetVar("eggmark", "On").on_off().onchange_noinit(KartItem_OnChange), + UnsavedNetVar("orbinaut", "On").on_off().onchange_noinit(KartItem_OnChange), + UnsavedNetVar("jawz", "On").on_off().onchange_noinit(KartItem_OnChange), + UnsavedNetVar("mine", "On").on_off().onchange_noinit(KartItem_OnChange), + UnsavedNetVar("landmine", "On").on_off().onchange_noinit(KartItem_OnChange), + UnsavedNetVar("ballhog", "On").on_off().onchange_noinit(KartItem_OnChange), + UnsavedNetVar("selfpropelledbomb", "On").on_off().onchange_noinit(KartItem_OnChange), + UnsavedNetVar("grow", "On").on_off().onchange_noinit(KartItem_OnChange), + UnsavedNetVar("shrink", "On").on_off().onchange_noinit(KartItem_OnChange), + UnsavedNetVar("lightningshield", "On").on_off().onchange_noinit(KartItem_OnChange), + UnsavedNetVar("bubbleshield", "On").on_off().onchange_noinit(KartItem_OnChange), + UnsavedNetVar("flameshield", "On").on_off().onchange_noinit(KartItem_OnChange), + UnsavedNetVar("hyudoro", "On").on_off().onchange_noinit(KartItem_OnChange), + UnsavedNetVar("pogospring", "On").on_off().onchange_noinit(KartItem_OnChange), + UnsavedNetVar("superring", "On").on_off().onchange_noinit(KartItem_OnChange), + UnsavedNetVar("kitchensink", "On").on_off().onchange_noinit(KartItem_OnChange), + UnsavedNetVar("droptarget", "On").on_off().onchange_noinit(KartItem_OnChange), + UnsavedNetVar("gardentop", "On").on_off().onchange_noinit(KartItem_OnChange), + UnsavedNetVar("gachabom", "On").on_off().onchange_noinit(KartItem_OnChange), + UnsavedNetVar("stoneshoe", "On").on_off().onchange_noinit(KartItem_OnChange), + UnsavedNetVar("toxomister", "On").on_off().onchange_noinit(KartItem_OnChange), + UnsavedNetVar("dualsneaker", "On").on_off().onchange_noinit(KartItem_OnChange), + UnsavedNetVar("triplesneaker", "On").on_off().onchange_noinit(KartItem_OnChange), + UnsavedNetVar("triplebanana", "On").on_off().onchange_noinit(KartItem_OnChange), + UnsavedNetVar("tripleorbinaut", "On").on_off().onchange_noinit(KartItem_OnChange), + UnsavedNetVar("quadorbinaut", "On").on_off().onchange_noinit(KartItem_OnChange), + UnsavedNetVar("dualjawz", "On").on_off().onchange_noinit(KartItem_OnChange), + UnsavedNetVar("triplegachabom", "On").on_off().onchange_noinit(KartItem_OnChange), }; consvar_t cv_kartbot = UnsavedNetVar("bots", "Off").values({ @@ -784,7 +786,9 @@ consvar_t cv_shoutcolor = UnsavedNetVar("shout_color", "Red").values({ consvar_t cv_shoutname = UnsavedNetVar("shout_name", "SERVER"); consvar_t cv_spectatorreentry = UnsavedNetVar("spectatorreentry", "30").min_max(0, 10*60); -consvar_t cv_thunderdome = UnsavedNetVar("thunderdome", "Off").on_off(); + +void ThunderDome_OnChange(void); +consvar_t cv_thunderdome = UnsavedNetVar("thunderdome", "Off").on_off().onchange_noinit(ThunderDome_OnChange); void TimeLimit_OnChange(void); consvar_t cv_timelimit = UnsavedNetVar("timelimit", "Default").min_max(1, 30*60, {{0, "None"}, {-1, "Default"}}).onchange_noinit(TimeLimit_OnChange); diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 75bd50915..9c9505ae5 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -7434,6 +7434,26 @@ void NumLaps_OnChange(void) } } +boolean M_AnyItemsEnabled(void); +void KartItem_OnChange(void); +void KartItem_OnChange(void) +{ + if (netgame && !server) + return; + + const boolean check = !M_AnyItemsEnabled(); + if (cv_thunderdome.value != check) + CV_SetValue(&cv_thunderdome, check); +} + +void ThunderDome_MenuSound(void); +void ThunderDome_OnChange(void); +void ThunderDome_OnChange(void) +{ + ThunderDome_MenuSound(); +} + +void KartFrantic_MenuSound(void); void KartFrantic_OnChange(void); void KartFrantic_OnChange(void) { @@ -7451,6 +7471,8 @@ void KartFrantic_OnChange(void) { CONS_Printf(M_GetText("Frantic items will be turned %s next round.\n"), cv_kartfrantic.value ? M_GetText("on") : M_GetText("off")); } + + KartFrantic_MenuSound(); } void KartSpeed_OnChange(void); diff --git a/src/menus/options-gameplay-item-toggles.c b/src/menus/options-gameplay-item-toggles.c index 0ef0272c9..039c4dfd4 100644 --- a/src/menus/options-gameplay-item-toggles.c +++ b/src/menus/options-gameplay-item-toggles.c @@ -85,7 +85,8 @@ menu_t OPTIONS_GameplayItemsDef = { NULL, }; -static boolean M_AnyItemsEnabled(void) +boolean M_AnyItemsEnabled(void); +boolean M_AnyItemsEnabled(void) { INT32 i; for (i = 0; i < NUMKARTRESULTS-1; i++) @@ -96,9 +97,29 @@ static boolean M_AnyItemsEnabled(void) return false; } -static void M_ToggleThunderdome(void) +void ThunderDome_MenuSound(void); +void ThunderDome_MenuSound(void) { - CV_SetValue(&cv_thunderdome, !M_AnyItemsEnabled()); + if (!menuactive || currentMenu != &OPTIONS_GameplayItemsDef) + return; + + if (cv_thunderdome.value) + { + S_StartSoundAtVolume(NULL, sfx_slot02, 80); + } + else + { + S_StartSound(NULL, sfx_itrolf); + } +} + +void KartFrantic_MenuSound(void); +void KartFrantic_MenuSound(void) +{ + if (!menuactive || currentMenu != &OPTIONS_GameplayItemsDef) + return; + + S_StartSound(NULL, (cv_kartfrantic.value ? sfx_noooo2 : sfx_kc48)); } void M_HandleItemToggles(INT32 choice) @@ -119,15 +140,7 @@ void M_HandleItemToggles(INT32 choice) { CV_SetValue(&cv_items[i], v); } - M_ToggleThunderdome(); - if (cv_thunderdome.value) - { - S_StartSoundAtVolume(NULL, sfx_slot02, 80); - } - else - { - S_StartSound(NULL, sfx_itrolf); - } + // KartItem_OnChange will toggle thunderdome and play sound M_SetMenuDelay(pid); } @@ -135,7 +148,6 @@ void M_HandleItemToggles(INT32 choice) else if (M_MenuButtonPressed(pid, MBT_R)) { CV_AddValue(&cv_kartfrantic, 1); - S_StartSound(NULL, (cv_kartfrantic.value ? sfx_noooo2 : sfx_kc48)); M_SetMenuDelay(pid); } @@ -219,7 +231,7 @@ void M_HandleItemToggles(INT32 choice) S_StartSound(NULL, sfx_s1ba); } CV_AddValue(&cv_items[currentMenu->menuitems[itemOn].mvar1-1], 1); - M_ToggleThunderdome(); + // KartItem_OnChange will toggle thunderdome and play sound } } From ca4b58a023ed2d5fc47b43d32a6956d8536fd057 Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 14 Sep 2025 22:33:24 +0100 Subject: [PATCH 2/3] Item toggle menu: Show "(next)" for frantic items, since it changes on map reload --- src/k_menudraw.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/k_menudraw.c b/src/k_menudraw.c index 2a0e926b4..5e617d0af 100644 --- a/src/k_menudraw.c +++ b/src/k_menudraw.c @@ -5997,8 +5997,10 @@ void M_DrawItemToggles(void) } // Button prompts - K_DrawGameControl( - (BASEVIDWIDTH/2) - cv_kartfrantic.value, BASEVIDHEIGHT-20, 0, + x = (BASEVIDWIDTH/2) - cv_kartfrantic.value; + y = BASEVIDHEIGHT-20; + INT32 w = K_DrawGameControl( + x, y, 0, va( " Toggle All %s Frantic Mode: %s", cv_thunderdome.value ? "(Ring Box Mode) " : "(Item Box Mode)", @@ -6007,6 +6009,14 @@ void M_DrawItemToggles(void) 1, TINY_FONT, (((row == height-1) && (drawnum > 1)) ? V_TRANSLUCENT : 0) ); + + if (cv_kartfrantic.value != franticitems) + { + V_DrawThinString( + x + w/2, y, 0, + (cv_kartfrantic.value ? "\x85 (next)" : "\x86 (next)") + ); + } } From 9336538c5c0c62c8fb6660a5af70f38dc6c7a5b1 Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 14 Sep 2025 23:17:36 +0100 Subject: [PATCH 3/3] Fix LOUD case lol --- src/menus/options-gameplay-item-toggles.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/menus/options-gameplay-item-toggles.c b/src/menus/options-gameplay-item-toggles.c index 039c4dfd4..1e47aecad 100644 --- a/src/menus/options-gameplay-item-toggles.c +++ b/src/menus/options-gameplay-item-toggles.c @@ -135,10 +135,11 @@ void M_HandleItemToggles(INT32 choice) if (M_MenuExtraPressed(pid)) { - INT32 v = !M_AnyItemsEnabled(); + const boolean check = !M_AnyItemsEnabled(); for (i = 0; i < NUMKARTRESULTS-1; i++) { - CV_SetValue(&cv_items[i], v); + if (cv_items[i].value != check) + CV_SetValue(&cv_items[i], check); } // KartItem_OnChange will toggle thunderdome and play sound