diff --git a/src/console.c b/src/console.c index ede2f633a..10baa4254 100644 --- a/src/console.c +++ b/src/console.c @@ -358,7 +358,22 @@ static void CON_SetupColormaps(void) *memorysrc = (UINT8)(i & 0xFF); // remap each color to itself... purplemap[0] = (UINT8)163; + 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; bluemap[0] = (UINT8)148; redmap[0] = (UINT8)34; // battle diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 2cdb92bd2..e7a343a03 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -2739,15 +2739,6 @@ static void Command_Map_f(void) 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? */ { CONS_Alert(CONS_ERROR, @@ -2823,13 +2814,23 @@ static void Command_Map_f(void) else { CONS_Alert(CONS_ERROR, - "'%s' is not a gametype.\n", + "'%s' is not a valid gametype.\n", gametypename); Z_Free(realmapname); Z_Free(mapname); 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()) { @@ -3061,9 +3062,10 @@ static void Command_RandomMap(void) { INT32 oldmapnum; INT32 newmapnum; - INT32 newgametype; - boolean newencoremode; + INT32 newgametype = (Playing() ? gametype : menugametype); + boolean newencore = false; boolean newresetplayers; + size_t option_gametype; if (client && !IsPlayerAdmin(consoleplayer)) { @@ -3071,13 +3073,69 @@ static void Command_RandomMap(void) 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. // The existing ones are way too annoyingly complicated and "anti-cheat" for my tastes. if (Playing()) { - newgametype = gametype; - newencoremode = encoremode; + if (cv_kartencore.value == 1 && (gametypes[newgametype]->rules & GTR_ENCORE)) + { + newencore = true; + } newresetplayers = false; if (gamestate == GS_LEVEL) @@ -3091,14 +3149,12 @@ static void Command_RandomMap(void) } else { - newgametype = menugametype; - newencoremode = false; newresetplayers = true; oldmapnum = -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) diff --git a/src/k_menu.h b/src/k_menu.h index 4dd5db602..9382c8647 100644 --- a/src/k_menu.h +++ b/src/k_menu.h @@ -116,7 +116,8 @@ struct menucolor_t { extern menucolor_t *menucolorhead, *menucolortail; extern INT16 menugametype; -void M_HandleMenuGametype(INT32 choice); +void M_HandleHostMenuGametype(INT32 choice); +void M_HandlePauseMenuGametype(INT32 choice); // // MENU TYPEDEFS @@ -414,6 +415,7 @@ extern menu_t MISC_StatisticsDef; typedef enum { mpause_addons = 0, + mpause_changegametype, mpause_switchmap, mpause_restartmap, mpause_tryagain, diff --git a/src/k_menudef.c b/src/k_menudef.c index 374c44968..74260d6e4 100644 --- a/src/k_menudef.c +++ b/src/k_menudef.c @@ -363,7 +363,7 @@ menuitem_t PLAY_MP_Host[] = NULL, {.cvar = &cv_maxplayers}, 0, 0}, {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", NULL, {.routine = M_MPSetupNetgameMapSelect}, 0, 0}, @@ -1593,6 +1593,9 @@ menuitem_t PAUSE_Main[] = {IT_STRING | IT_CALL, "ADDONS", "M_ICOADD", 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", NULL, {.submenu = &PAUSE_GamemodesDef}, 0, 0}, diff --git a/src/k_menudraw.c b/src/k_menudraw.c index 4087fdd7a..b872c768d 100644 --- a/src/k_menudraw.c +++ b/src/k_menudraw.c @@ -2468,7 +2468,7 @@ void M_DrawMPHost(void) } case IT_KEYHANDLER: { - if (currentMenu->menuitems[i].itemaction.routine != M_HandleMenuGametype) + if (currentMenu->menuitems[i].itemaction.routine != M_HandleHostMenuGametype) break; w = V_ThinStringWidth(gametypes[menugametype]->name, V_6WIDTHSPACE); @@ -3778,12 +3778,26 @@ void M_DrawPause(void) word1[word1len] = '\0'; word2[word2len] = '\0'; - // 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 (itemOn == mpause_changegametype) + { + INT32 w = V_LSTitleLowStringWidth(gametypes[menugametype]->name, 0)/2; - if (word2len) - V_DrawCenteredLSTitleLowString(220 + offset*2, 103, 0, word2); + if (word1len) + 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; diff --git a/src/k_menufunc.c b/src/k_menufunc.c index 0cd21d572..759e35de9 100644 --- a/src/k_menufunc.c +++ b/src/k_menufunc.c @@ -4162,10 +4162,37 @@ void M_MPHostInit(INT32 choice) 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 INT16 currentmenugametype = menugametype; UINT32 forbidden = GTR_FORBIDMP; (void)choice; @@ -4173,42 +4200,24 @@ void M_HandleMenuGametype(INT32 choice) if (currentMenu->menuitems[itemOn].mvar1 != 0) forbidden = currentMenu->menuitems[itemOn].mvar1; - if (menucmd[pid].dpad_lr > 0 || M_MenuConfirmPressed(pid)) + if (M_MenuBackPressed(pid)) { - do - { - menugametype++; - if (menugametype >= numgametypes) - menugametype = 0; - - if (!(gametypes[menugametype]->rules & forbidden)) - break; - } while (menugametype != currentmenugametype); - + M_GoBack(0); + M_SetMenuDelay(pid); + return; + } + else if (menucmd[pid].dpad_lr > 0 || M_MenuConfirmPressed(pid)) + { + M_NextMenuGametype(forbidden); S_StartSound(NULL, sfx_s3k5b); M_SetMenuDelay(pid); } else if (menucmd[pid].dpad_lr < 0) { - do - { - if (menugametype == 0) - menugametype = numgametypes; - menugametype--; - - if (!(gametypes[menugametype]->rules & forbidden)) - break; - } while (menugametype != currentmenugametype); - + M_PrevMenuGametype(forbidden); S_StartSound(NULL, sfx_s3k5b); M_SetMenuDelay(pid); } - else if (M_MenuBackPressed(pid)) - { - M_GoBack(0); - M_SetMenuDelay(pid); - return; - } if (menucmd[pid].dpad_ud > 0) { @@ -6150,6 +6159,7 @@ void M_OpenPauseMenu(void) // By default, disable anything sensitive: PAUSE_Main[mpause_addons].status = IT_DISABLED; + PAUSE_Main[mpause_changegametype].status = IT_DISABLED; PAUSE_Main[mpause_switchmap].status = IT_DISABLED; PAUSE_Main[mpause_restartmap].status = IT_DISABLED; PAUSE_Main[mpause_tryagain].status = IT_DISABLED; @@ -6171,14 +6181,8 @@ void M_OpenPauseMenu(void) if (server || IsPlayerAdmin(consoleplayer)) { - PAUSE_Main[mpause_switchmap].status = IT_STRING | IT_SUBMENU; - for (i = 0; i < PAUSE_GamemodesDef.numitems; i++) - { - if (PAUSE_GamemodesMenu[i].mvar2 != gametype) - continue; - PAUSE_GamemodesDef.lastOn = i; - break; - } + PAUSE_Main[mpause_changegametype].status = IT_STRING | IT_KEYHANDLER; + PAUSE_Main[mpause_switchmap].status = IT_STRING | IT_CALL; PAUSE_Main[mpause_restartmap].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; } +// 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 void M_RestartMap(INT32 choice) {