Dehardcode menu gametype selection, part 2

- Add "Gametype" toggle option to pause menu for admins
    - A/Confirm button on any gametype other than current to do random map in new gametype
    - C/Extra button to return to current gametype
    - A/Confirm button on current gametype does a funny noise and nothing else right now, idk what to do
- `randomlevel` supports the same `-gametype` parameter as `map`
- Both `randomlevel` and `map`'s `-gametype` parameter prohibits `GTR_FORBIDMP` mask gametype changes in netgames
- `randomlevel` properly sets encore based on `cv_kartencore`'s value (and permitting `GTR_ENCORE`)
- Split out `menugametype` change functions
- `yellowmap` now remaps all intermediary shades of grey to match funny pause menu remaps
This commit is contained in:
toaster 2022-12-30 20:34:35 +00:00
parent 3ee8713e46
commit ebb2a79666
6 changed files with 196 additions and 62 deletions

View file

@ -358,7 +358,22 @@ static void CON_SetupColormaps(void)
*memorysrc = (UINT8)(i & 0xFF); // remap each color to itself... *memorysrc = (UINT8)(i & 0xFF); // remap each color to itself...
purplemap[0] = (UINT8)163; purplemap[0] = (UINT8)163;
yellowmap[0] = (UINT8)73; yellowmap[0] = (UINT8)73;
yellowmap[1] = (UINT8)73;
yellowmap[3] = (UINT8)74;
yellowmap[6] = (UINT8)74;
yellowmap[7] = (UINT8)190;
yellowmap[8] = (UINT8)190;
yellowmap[10] = (UINT8)190;
yellowmap[12] = (UINT8)190;
yellowmap[14] = (UINT8)149;
yellowmap[15] = (UINT8)149;
yellowmap[16] = (UINT8)149;
yellowmap[21] = (UINT8)152;
yellowmap[23] = (UINT8)173;
yellowmap[24] = (UINT8)167;
greenmap[0] = (UINT8)98; greenmap[0] = (UINT8)98;
bluemap[0] = (UINT8)148; bluemap[0] = (UINT8)148;
redmap[0] = (UINT8)34; // battle redmap[0] = (UINT8)34; // battle

View file

@ -2739,15 +2739,6 @@ static void Command_Map_f(void)
if (option_gametype) if (option_gametype)
{ {
#if 0
if (!multiplayer)
{
CONS_Printf(M_GetText(
"You can't switch gametypes in single player!\n"));
return;
}
else
#endif //#if 0
if (COM_Argc() < option_gametype + 2)/* no argument after? */ if (COM_Argc() < option_gametype + 2)/* no argument after? */
{ {
CONS_Alert(CONS_ERROR, CONS_Alert(CONS_ERROR,
@ -2823,13 +2814,23 @@ static void Command_Map_f(void)
else else
{ {
CONS_Alert(CONS_ERROR, CONS_Alert(CONS_ERROR,
"'%s' is not a gametype.\n", "'%s' is not a valid gametype.\n",
gametypename); gametypename);
Z_Free(realmapname); Z_Free(realmapname);
Z_Free(mapname); Z_Free(mapname);
return; return;
} }
} }
if (Playing() && netgame && (gametypes[newgametype]->rules & GTR_FORBIDMP))
{
CONS_Alert(CONS_ERROR,
"'%s' is not a net-compatible gametype.\n",
gametypename);
Z_Free(realmapname);
Z_Free(mapname);
return;
}
} }
else if (!Playing()) else if (!Playing())
{ {
@ -3061,9 +3062,10 @@ static void Command_RandomMap(void)
{ {
INT32 oldmapnum; INT32 oldmapnum;
INT32 newmapnum; INT32 newmapnum;
INT32 newgametype; INT32 newgametype = (Playing() ? gametype : menugametype);
boolean newencoremode; boolean newencore = false;
boolean newresetplayers; boolean newresetplayers;
size_t option_gametype;
if (client && !IsPlayerAdmin(consoleplayer)) if (client && !IsPlayerAdmin(consoleplayer))
{ {
@ -3071,13 +3073,69 @@ static void Command_RandomMap(void)
return; return;
} }
if ((option_gametype = COM_CheckPartialParm("-g")))
{
const char *gametypename;
if (COM_Argc() < option_gametype + 2)/* no argument after? */
{
CONS_Alert(CONS_ERROR,
"No gametype name follows parameter '%s'.\n",
COM_Argv(option_gametype));
return;
}
// new gametype value
// use current one by default
gametypename = COM_Argv(option_gametype + 1);
newgametype = G_GetGametypeByName(gametypename);
if (newgametype == -1) // reached end of the list with no match
{
/* Did they give us a gametype number? That's okay too! */
if (isdigit(gametypename[0]))
{
INT16 d = atoi(gametypename);
if (d >= 0 && d < numgametypes)
newgametype = d;
else
{
CONS_Alert(CONS_ERROR,
"Gametype number %d is out of range. Use a number between"
" 0 and %d inclusive. ...Or just use the name. :v\n",
d,
numgametypes-1);
return;
}
}
else
{
CONS_Alert(CONS_ERROR,
"'%s' is not a valid gametype.\n",
gametypename);
return;
}
}
if (Playing() && netgame && (gametypes[newgametype]->rules & GTR_FORBIDMP))
{
CONS_Alert(CONS_ERROR,
"'%s' is not a net-compatible gametype.\n",
gametypename);
return;
}
}
// TODO: Handle singleplayer conditions. // TODO: Handle singleplayer conditions.
// The existing ones are way too annoyingly complicated and "anti-cheat" for my tastes. // The existing ones are way too annoyingly complicated and "anti-cheat" for my tastes.
if (Playing()) if (Playing())
{ {
newgametype = gametype; if (cv_kartencore.value == 1 && (gametypes[newgametype]->rules & GTR_ENCORE))
newencoremode = encoremode; {
newencore = true;
}
newresetplayers = false; newresetplayers = false;
if (gamestate == GS_LEVEL) if (gamestate == GS_LEVEL)
@ -3091,14 +3149,12 @@ static void Command_RandomMap(void)
} }
else else
{ {
newgametype = menugametype;
newencoremode = false;
newresetplayers = true; newresetplayers = true;
oldmapnum = -1; oldmapnum = -1;
} }
newmapnum = G_RandMap(G_TOLFlag(newgametype), oldmapnum, 0, 0, false, NULL) + 1; newmapnum = G_RandMap(G_TOLFlag(newgametype), oldmapnum, 0, 0, false, NULL) + 1;
D_MapChange(newmapnum, newgametype, newencoremode, newresetplayers, 0, false, false); D_MapChange(newmapnum, newgametype, newencore, newresetplayers, 0, false, false);
} }
static void Command_RestartLevel(void) static void Command_RestartLevel(void)

View file

@ -116,7 +116,8 @@ struct menucolor_t {
extern menucolor_t *menucolorhead, *menucolortail; extern menucolor_t *menucolorhead, *menucolortail;
extern INT16 menugametype; extern INT16 menugametype;
void M_HandleMenuGametype(INT32 choice); void M_HandleHostMenuGametype(INT32 choice);
void M_HandlePauseMenuGametype(INT32 choice);
// //
// MENU TYPEDEFS // MENU TYPEDEFS
@ -414,6 +415,7 @@ extern menu_t MISC_StatisticsDef;
typedef enum typedef enum
{ {
mpause_addons = 0, mpause_addons = 0,
mpause_changegametype,
mpause_switchmap, mpause_switchmap,
mpause_restartmap, mpause_restartmap,
mpause_tryagain, mpause_tryagain,

View file

@ -363,7 +363,7 @@ menuitem_t PLAY_MP_Host[] =
NULL, {.cvar = &cv_maxplayers}, 0, 0}, NULL, {.cvar = &cv_maxplayers}, 0, 0},
{IT_STRING | IT_KEYHANDLER, "Gamemode", "Choose the type of play on your server.", {IT_STRING | IT_KEYHANDLER, "Gamemode", "Choose the type of play on your server.",
NULL, {.routine = M_HandleMenuGametype}, 0, 0}, NULL, {.routine = M_HandleHostMenuGametype}, 0, 0},
{IT_STRING | IT_CALL, "GO", "Select a map with the currently selected gamemode", {IT_STRING | IT_CALL, "GO", "Select a map with the currently selected gamemode",
NULL, {.routine = M_MPSetupNetgameMapSelect}, 0, 0}, NULL, {.routine = M_MPSetupNetgameMapSelect}, 0, 0},
@ -1593,6 +1593,9 @@ menuitem_t PAUSE_Main[] =
{IT_STRING | IT_CALL, "ADDONS", "M_ICOADD", {IT_STRING | IT_CALL, "ADDONS", "M_ICOADD",
NULL, {.routine = M_Addons}, 0, 0}, NULL, {.routine = M_Addons}, 0, 0},
{IT_STRING | IT_KEYHANDLER, "GAMETYPE", "M_ICOGAM",
NULL, {.routine = M_HandlePauseMenuGametype}, 0, 0},
{IT_STRING | IT_SUBMENU, "CHANGE MAP", "M_ICOMAP", {IT_STRING | IT_SUBMENU, "CHANGE MAP", "M_ICOMAP",
NULL, {.submenu = &PAUSE_GamemodesDef}, 0, 0}, NULL, {.submenu = &PAUSE_GamemodesDef}, 0, 0},

View file

@ -2468,7 +2468,7 @@ void M_DrawMPHost(void)
} }
case IT_KEYHANDLER: case IT_KEYHANDLER:
{ {
if (currentMenu->menuitems[i].itemaction.routine != M_HandleMenuGametype) if (currentMenu->menuitems[i].itemaction.routine != M_HandleHostMenuGametype)
break; break;
w = V_ThinStringWidth(gametypes[menugametype]->name, V_6WIDTHSPACE); w = V_ThinStringWidth(gametypes[menugametype]->name, V_6WIDTHSPACE);
@ -3778,12 +3778,26 @@ void M_DrawPause(void)
word1[word1len] = '\0'; word1[word1len] = '\0';
word2[word2len] = '\0'; word2[word2len] = '\0';
// If there's no 2nd word, take this opportunity to center this line of text. if (itemOn == mpause_changegametype)
if (word1len) {
V_DrawCenteredLSTitleHighString(220 + offset*2, 75 + (!word2len ? 10 : 0), 0, word1); INT32 w = V_LSTitleLowStringWidth(gametypes[menugametype]->name, 0)/2;
if (word2len) if (word1len)
V_DrawCenteredLSTitleLowString(220 + offset*2, 103, 0, word2); V_DrawCenteredLSTitleHighString(220 + offset*2, 75, 0, word1);
V_DrawLSTitleLowString(220-w + offset*2, 103, V_YELLOWMAP, gametypes[menugametype]->name);
V_DrawCharacter(220-w + offset*2 - 8 - (skullAnimCounter/5), 103+6, '\x1C' | V_YELLOWMAP, false); // left arrow
V_DrawCharacter(220+w + offset*2 + 4 + (skullAnimCounter/5), 103+6, '\x1D' | V_YELLOWMAP, false); // right arrow
}
else
{
// If there's no 2nd word, take this opportunity to center this line of text.
if (word1len)
V_DrawCenteredLSTitleHighString(220 + offset*2, 75 + (!word2len ? 10 : 0), 0, word1);
if (word2len)
V_DrawCenteredLSTitleLowString(220 + offset*2, 103, 0, word2);
}
} }
tic_t playback_last_menu_interaction_leveltime = 0; tic_t playback_last_menu_interaction_leveltime = 0;

View file

@ -4162,10 +4162,37 @@ void M_MPHostInit(INT32 choice)
itemOn = mhost_go; itemOn = mhost_go;
} }
void M_HandleMenuGametype(INT32 choice) static void M_NextMenuGametype(UINT32 forbidden)
{
const INT16 currentmenugametype = menugametype;
do
{
menugametype++;
if (menugametype >= numgametypes)
menugametype = 0;
if (!(gametypes[menugametype]->rules & forbidden))
break;
} while (menugametype != currentmenugametype);
}
static void M_PrevMenuGametype(UINT32 forbidden)
{
const INT16 currentmenugametype = menugametype;
do
{
if (menugametype == 0)
menugametype = numgametypes;
menugametype--;
if (!(gametypes[menugametype]->rules & forbidden))
break;
} while (menugametype != currentmenugametype);
}
void M_HandleHostMenuGametype(INT32 choice)
{ {
const UINT8 pid = 0; const UINT8 pid = 0;
const INT16 currentmenugametype = menugametype;
UINT32 forbidden = GTR_FORBIDMP; UINT32 forbidden = GTR_FORBIDMP;
(void)choice; (void)choice;
@ -4173,42 +4200,24 @@ void M_HandleMenuGametype(INT32 choice)
if (currentMenu->menuitems[itemOn].mvar1 != 0) if (currentMenu->menuitems[itemOn].mvar1 != 0)
forbidden = currentMenu->menuitems[itemOn].mvar1; forbidden = currentMenu->menuitems[itemOn].mvar1;
if (menucmd[pid].dpad_lr > 0 || M_MenuConfirmPressed(pid)) if (M_MenuBackPressed(pid))
{ {
do M_GoBack(0);
{ M_SetMenuDelay(pid);
menugametype++; return;
if (menugametype >= numgametypes) }
menugametype = 0; else if (menucmd[pid].dpad_lr > 0 || M_MenuConfirmPressed(pid))
{
if (!(gametypes[menugametype]->rules & forbidden)) M_NextMenuGametype(forbidden);
break;
} while (menugametype != currentmenugametype);
S_StartSound(NULL, sfx_s3k5b); S_StartSound(NULL, sfx_s3k5b);
M_SetMenuDelay(pid); M_SetMenuDelay(pid);
} }
else if (menucmd[pid].dpad_lr < 0) else if (menucmd[pid].dpad_lr < 0)
{ {
do M_PrevMenuGametype(forbidden);
{
if (menugametype == 0)
menugametype = numgametypes;
menugametype--;
if (!(gametypes[menugametype]->rules & forbidden))
break;
} while (menugametype != currentmenugametype);
S_StartSound(NULL, sfx_s3k5b); S_StartSound(NULL, sfx_s3k5b);
M_SetMenuDelay(pid); M_SetMenuDelay(pid);
} }
else if (M_MenuBackPressed(pid))
{
M_GoBack(0);
M_SetMenuDelay(pid);
return;
}
if (menucmd[pid].dpad_ud > 0) if (menucmd[pid].dpad_ud > 0)
{ {
@ -6150,6 +6159,7 @@ void M_OpenPauseMenu(void)
// By default, disable anything sensitive: // By default, disable anything sensitive:
PAUSE_Main[mpause_addons].status = IT_DISABLED; PAUSE_Main[mpause_addons].status = IT_DISABLED;
PAUSE_Main[mpause_changegametype].status = IT_DISABLED;
PAUSE_Main[mpause_switchmap].status = IT_DISABLED; PAUSE_Main[mpause_switchmap].status = IT_DISABLED;
PAUSE_Main[mpause_restartmap].status = IT_DISABLED; PAUSE_Main[mpause_restartmap].status = IT_DISABLED;
PAUSE_Main[mpause_tryagain].status = IT_DISABLED; PAUSE_Main[mpause_tryagain].status = IT_DISABLED;
@ -6171,14 +6181,8 @@ void M_OpenPauseMenu(void)
if (server || IsPlayerAdmin(consoleplayer)) if (server || IsPlayerAdmin(consoleplayer))
{ {
PAUSE_Main[mpause_switchmap].status = IT_STRING | IT_SUBMENU; PAUSE_Main[mpause_changegametype].status = IT_STRING | IT_KEYHANDLER;
for (i = 0; i < PAUSE_GamemodesDef.numitems; i++) PAUSE_Main[mpause_switchmap].status = IT_STRING | IT_CALL;
{
if (PAUSE_GamemodesMenu[i].mvar2 != gametype)
continue;
PAUSE_GamemodesDef.lastOn = i;
break;
}
PAUSE_Main[mpause_restartmap].status = IT_STRING | IT_CALL; PAUSE_Main[mpause_restartmap].status = IT_STRING | IT_CALL;
PAUSE_Main[mpause_addons].status = IT_STRING | IT_CALL; PAUSE_Main[mpause_addons].status = IT_STRING | IT_CALL;
} }
@ -6279,6 +6283,46 @@ boolean M_PauseInputs(INT32 ch)
return false; return false;
} }
// Change gametype
void M_HandlePauseMenuGametype(INT32 choice)
{
const UINT8 pid = 0;
UINT32 forbidden = GTR_FORBIDMP;
(void)choice;
if (M_MenuConfirmPressed(pid))
{
if (menugametype != gametype)
{
M_ClearMenus(true);
COM_ImmedExecute(va("randommap -gt %s", gametypes[menugametype]->name));
return;
}
M_SetMenuDelay(pid);
S_StartSound(NULL, sfx_s3k7b);
}
else if (M_MenuExtraPressed(pid))
{
menugametype = gametype;
M_SetMenuDelay(pid);
S_StartSound(NULL, sfx_s3k7b);
}
else if (menucmd[pid].dpad_lr > 0)
{
M_NextMenuGametype(forbidden);
S_StartSound(NULL, sfx_s3k5b);
M_SetMenuDelay(pid);
}
else if (menucmd[pid].dpad_lr < 0)
{
M_PrevMenuGametype(forbidden);
S_StartSound(NULL, sfx_s3k5b);
M_SetMenuDelay(pid);
}
}
// Restart map // Restart map
void M_RestartMap(INT32 choice) void M_RestartMap(INT32 choice)
{ {