From cdb3b1ca982a41f10db10b100742ace229307a17 Mon Sep 17 00:00:00 2001 From: SinnamonLat Date: Sat, 11 Dec 2021 18:22:56 +0100 Subject: [PATCH] Difficulty select before GP, match race & netgames --- src/k_menu.h | 15 ++++++ src/k_menudef.c | 52 +++++++++++++++++-- src/k_menudraw.c | 129 +++++++++++++++++++++++++++++++++++++++++++++++ src/k_menufunc.c | 104 +++++++++++++++++++++++++++++++++++--- 4 files changed, 291 insertions(+), 9 deletions(-) diff --git a/src/k_menu.h b/src/k_menu.h index 7eca2ca0d..1f70256d0 100644 --- a/src/k_menu.h +++ b/src/k_menu.h @@ -174,6 +174,9 @@ extern menu_t PLAY_GamemodesDef; extern menuitem_t PLAY_RaceGamemodesMenu[]; extern menu_t PLAY_RaceGamemodesDef; +extern menuitem_t PLAY_RaceDifficulty[]; +extern menu_t PLAY_RaceDifficultyDef; + extern menuitem_t PLAY_CupSelect[]; extern menu_t PLAY_CupSelectDef; @@ -478,6 +481,16 @@ void M_CupSelectTick(void); void M_LevelSelectHandler(INT32 choice); void M_LevelSelectTick(void); +// dummy consvars for GP & match race setup +extern consvar_t cv_dummygpdifficulty; +extern consvar_t cv_dummykartspeed; +extern consvar_t cv_dummygpencore; +extern consvar_t cv_dummymatchbots; + +void M_SetupDifficultySelect(INT32 choice); +void M_SetupDifficultySelectMP(INT32 choice); +void M_DifficultySelectInputs(INT32 choice); + // Multiplayer menu stuff // Keep track of multiplayer menu related data @@ -692,6 +705,8 @@ void M_DrawCupSelect(void); void M_DrawLevelSelect(void); void M_DrawTimeAttack(void); +void M_DrawRaceDifficulty(void); + // Multiplayer menu stuff void M_DrawMPOptSelect(void); void M_DrawMPHost(void); diff --git a/src/k_menudef.c b/src/k_menudef.c index 6a9487828..38ddcbe29 100644 --- a/src/k_menudef.c +++ b/src/k_menudef.c @@ -100,10 +100,10 @@ menu_t PLAY_GamemodesDef = KARTGAMEMODEMENU(PLAY_GamemodesMenu, &PLAY_MainDef); menuitem_t PLAY_RaceGamemodesMenu[] = { {IT_STRING | IT_CALL, "Grand Prix", "Compete for the best rank over five races!", - NULL, M_LevelSelectInit, 2, GT_RACE}, + NULL, M_SetupDifficultySelect, 0, 0}, {IT_STRING | IT_CALL, "Match Race", "Play by your own rules in a specialized, single race!", - "MENIMG01", M_LevelSelectInit, 0, GT_RACE}, + "MENIMG01", M_SetupDifficultySelect, 1, 0}, {IT_STRING | IT_CALL, "Time Attack", "Record your best time on any track!", NULL, M_LevelSelectInit, 1, GT_RACE}, @@ -113,6 +113,52 @@ menuitem_t PLAY_RaceGamemodesMenu[] = menu_t PLAY_RaceGamemodesDef = KARTGAMEMODEMENU(PLAY_RaceGamemodesMenu, &PLAY_GamemodesDef); + +// difficulty selection: +menuitem_t PLAY_RaceDifficulty[] = +{ + // local play + {IT_STRING | IT_CVAR, "Difficulty", "Select the game difficulty", + NULL, &cv_dummygpdifficulty, 0, 0}, + + // netgames + {IT_STRING | IT_CVAR, "Difficulty", "Select the game speed", + NULL, &cv_dummykartspeed, 0, 0}, + + // DISABLE THAT OPTION OUTSIDE OF MATCH RACE + {IT_STRING2 | IT_CVAR, "CPU Players", "Enable or disable CPU players.", // 2 whitestring is used by the drawer to know to draw shitstring + NULL, &cv_dummymatchbots, 0, 0}, + + {IT_STRING2 | IT_CVAR, "Encore", "Enable or disable Encore mode", // 3 + NULL, &cv_dummygpencore, 0, 0}, + + // For GP: + {IT_STRING | IT_CALL, "Cup Select", "Go on and select a cup!", NULL, M_LevelSelectInit, 2, GT_RACE}, // 4 + + // For Match Race: + {IT_STRING | IT_CALL, "Map Select", "Go on and select a race track!", NULL, M_LevelSelectInit, 0, GT_RACE}, // 5 + + // For Match Race in NETGAMES: + {IT_STRING | IT_CALL, "Map Select", "Go on and select a race track!", NULL, M_MPSetupNetgameMapSelect, 0, GT_RACE}, // 6 + + {IT_STRING | IT_CALL, "Back", NULL, NULL, M_GoBack, 0, 0}, +}; + +menu_t PLAY_RaceDifficultyDef = { + sizeof(PLAY_RaceDifficulty) / sizeof(menuitem_t), + &PLAY_RaceGamemodesDef, + 0, + PLAY_RaceDifficulty, + 0, 0, + 0, 0, + 1, 10, + M_DrawRaceDifficulty, + NULL, + NULL, + NULL +}; + + menuitem_t PLAY_CupSelect[] = { {IT_NOTHING | IT_KEYHANDLER, NULL, NULL, NULL, M_CupSelectHandler, 0, 0}, @@ -234,7 +280,7 @@ menuitem_t PLAY_MP_Host[] = NULL, &cv_dummygametype, 0, 0}, {IT_STRING | IT_CALL, "GO", "Select a map with the currently selected gamemode", - NULL, M_MPSetupNetgameMapSelect, 0, 0}, + NULL, M_SetupDifficultySelectMP, 0, 0}, }; diff --git a/src/k_menudraw.c b/src/k_menudraw.c index de9a354d0..abc29e912 100644 --- a/src/k_menudraw.c +++ b/src/k_menudraw.c @@ -1020,6 +1020,135 @@ void M_DrawCharacterSelect(void) M_DrawCharSelectCursor(priority); } +// DIFFICULTY SELECT +// This is a mix of K_DrawKartGamemodeMenu and the generic menu drawer depending on what we need. +// This is only ever used here (I hope because this is starting to pile up on hacks to look like the old m_menu.c lol...) + +void M_DrawRaceDifficulty(void) +{ + UINT8 n = currentMenu->numitems-4; + patch_t *box = W_CachePatchName("M_DBOX", PU_CACHE); + + INT32 i; + INT32 x = 120; + INT32 y = 48; + + M_DrawMenuTooltips(); + + // Draw the box for difficulty... + V_DrawFixedPatch((111 + 24*menutransition.tics)*FRACUNIT, 33*FRACUNIT, FRACUNIT, 0, box, NULL); + + if (menutransition.tics) + { + x += 24 * menutransition.tics; + } + + for (i = 0; i < currentMenu->numitems; i++) + { + if (i >= n) + { + + x = GM_STARTX + (GM_XOFFSET * 5 / 2); + y = GM_STARTY + (GM_YOFFSET * 5 / 2); + + if (i < currentMenu->numitems-1) + { + x -= GM_XOFFSET; + y -= GM_YOFFSET; + } + + + if (menutransition.tics) + { + x += 24 * menutransition.tics; + } + } + + switch (currentMenu->menuitems[i].status & IT_DISPLAY) + { + // This is HACKY...... + + case IT_STRING2: + { + + INT32 f = (i == itemOn) ? highlightflags : 0; + + V_DrawString(140 + 24*menutransition.tics, y, f, currentMenu->menuitems[i].text); + + if (currentMenu->menuitems[i].status & IT_CVAR) + { + // implicitely we'll only take care of normal cvars + INT32 cx = 260 + 24*menutransition.tics; + consvar_t *cv = (consvar_t *)currentMenu->menuitems[i].itemaction; + + V_DrawCenteredString(cx, y, f, cv->string); + + if (i == itemOn) + { + + INT32 w = V_StringWidth(cv->string, 0)/2; + + V_DrawCharacter(cx - 10 - w - (skullAnimCounter/5), y, '\x1C' | highlightflags, false); // left arrow + V_DrawCharacter(cx + w + 2 + (skullAnimCounter/5), y, '\x1D' | highlightflags, false); // right arrow + } + } + + y += 12; + + break; + } + + case IT_STRING: + { + + UINT8 *colormap = NULL; + + if (i == itemOn) + { + colormap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_PLAGUE, GTC_CACHE); + } + else + { + colormap = R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_MOSS, GTC_CACHE); + } + + + if (currentMenu->menuitems[i].status & IT_CVAR) + { + + INT32 fx = (x - 24*menutransition.tics); + INT32 centx = fx + (320-fx)/2 + (menutransition.tics*24); // undo the menutransition movement to redo it here otherwise the text won't move at the same speed lole. + + // implicitely we'll only take care of normal consvars + consvar_t *cv = (consvar_t *)currentMenu->menuitems[i].itemaction; + + V_DrawFixedPatch(x*FRACUNIT, y*FRACUNIT, FRACUNIT, 0, W_CachePatchName("MENUSHRT", PU_CACHE), colormap); + V_DrawCenteredGamemodeString(centx, y - 3, V_ALLOWLOWERCASE, colormap, cv->string); + + if (i == itemOn) + { + patch_t *arr_r = W_CachePatchName("GM_ARRL", PU_CACHE); + patch_t *arr_l = W_CachePatchName("GM_ARRR", PU_CACHE); + + V_DrawFixedPatch((centx-54 - arr_r->width - (skullAnimCounter/5))*FRACUNIT, (y-3)*FRACUNIT, FRACUNIT, 0, arr_r, colormap); + V_DrawFixedPatch((centx+54 + (skullAnimCounter/5))*FRACUNIT, (y-3)*FRACUNIT, FRACUNIT, 0, arr_l, colormap); + } + + } + else // not a cvar + { + V_DrawFixedPatch(x*FRACUNIT, y*FRACUNIT, FRACUNIT, 0, W_CachePatchName("MENUPLTR", PU_CACHE), colormap); + V_DrawGamemodeString(x + 16, y - 3, V_ALLOWLOWERCASE, colormap, currentMenu->menuitems[i].text); + } + x += GM_XOFFSET; + y += GM_YOFFSET; + + break; + } + } + } +} + // LEVEL SELECT static void M_DrawCupPreview(INT16 y, cupheader_t *cup) diff --git a/src/k_menufunc.c b/src/k_menufunc.c index 349f9e560..a507f1632 100644 --- a/src/k_menufunc.c +++ b/src/k_menufunc.c @@ -166,6 +166,9 @@ static CV_PossibleValue_t dummyscramble_cons_t[] = {{0, "Random"}, {1, "Points"} static CV_PossibleValue_t dummystaff_cons_t[] = {{0, "MIN"}, {100, "MAX"}, {0, NULL}}; static CV_PossibleValue_t dummygametype_cons_t[] = {{0, "Race"}, {1, "Battle"}, {0, NULL}}; +static CV_PossibleValue_t dummygpdifficulty_cons_t[] = {{0, "Easy"}, {1, "Normal"}, {2, "Hard"}, {3, "Master"}, {0, NULL}}; +static CV_PossibleValue_t dummykartspeed_cons_t[] = {{-1, "Auto"}, {0, "Easy"}, {1, "Normal"}, {2, "Hard"}, {0, NULL}}; + //static consvar_t cv_dummymenuplayer = CVAR_INIT ("dummymenuplayer", "P1", CV_HIDDEN|CV_CALL, dummymenuplayer_cons_t, Dummymenuplayer_OnChange); static consvar_t cv_dummyteam = CVAR_INIT ("dummyteam", "Spectator", CV_HIDDEN, dummyteam_cons_t, NULL); //static cv_dummyspectate = CVAR_INITconsvar_t ("dummyspectate", "Spectator", CV_HIDDEN, dummyspectate_cons_t, NULL); @@ -176,6 +179,26 @@ consvar_t cv_dummyip = CVAR_INIT ("dummyip", "", CV_HIDDEN, NULL, NULL); consvar_t cv_dummymenuplayer = CVAR_INIT ("dummymenuplayer", "P1", CV_HIDDEN|CV_CALL, dummymenuplayer_cons_t, Dummymenuplayer_OnChange); consvar_t cv_dummyspectate = CVAR_INIT ("dummyspectate", "Spectator", CV_HIDDEN, dummyspectate_cons_t, NULL); +consvar_t cv_dummygpdifficulty = CVAR_INIT ("dummygpdifficulty", "Normal", CV_HIDDEN, dummygpdifficulty_cons_t, NULL); +consvar_t cv_dummykartspeed = CVAR_INIT ("dummykartspeed", "Auto", CV_HIDDEN, dummykartspeed_cons_t, NULL); +consvar_t cv_dummygpencore = CVAR_INIT ("dummygpdifficulty", "No", CV_HIDDEN, CV_YesNo, NULL); + +static CV_PossibleValue_t dummymatchbots_cons_t[] = { + {0, "Off"}, + {1, "Lv.1"}, + {2, "Lv.2"}, + {3, "Lv.3"}, + {4, "Lv.4"}, + {5, "Lv.5"}, + {6, "Lv.6"}, + {7, "Lv.7"}, + {8, "Lv.8"}, + {9, "Lv.9"}, + {0, NULL} +}; + +consvar_t cv_dummymatchbots = CVAR_INIT ("dummymatchbots", "Off", CV_HIDDEN|CV_SAVE, dummymatchbots_cons_t, NULL); // Save this one if you wanna test your stuff without bots for instance + // ========================================================================== // CVAR ONCHANGE EVENTS GO HERE // ========================================================================== @@ -1629,6 +1652,11 @@ void M_Init(void) CV_RegisterVar(&cv_dummygametype); CV_RegisterVar(&cv_dummyip); + CV_RegisterVar(&cv_dummygpdifficulty); + CV_RegisterVar(&cv_dummykartspeed); + CV_RegisterVar(&cv_dummygpencore); + CV_RegisterVar(&cv_dummymatchbots); + M_UpdateMenuBGImage(true); #if 0 @@ -2347,6 +2375,60 @@ boolean M_CharacterSelectQuit(void) return true; } +// DIFFICULTY SELECT + +void M_SetupDifficultySelect(INT32 choice) +{ + // check what we picked. + choice = currentMenu->menuitems[itemOn].mvar1; + + // setup the difficulty menu and then remove choices depending on choice + PLAY_RaceDifficultyDef.prevMenu = currentMenu; + M_SetupNextMenu(&PLAY_RaceDifficultyDef, false); + + PLAY_RaceDifficulty[0].status = IT_STRING|IT_CVAR; + PLAY_RaceDifficulty[1].status = IT_DISABLED; + PLAY_RaceDifficulty[2].status = IT_DISABLED; + PLAY_RaceDifficulty[3].status = IT_DISABLED; + PLAY_RaceDifficulty[4].status = IT_DISABLED; + PLAY_RaceDifficulty[5].status = IT_DISABLED; + PLAY_RaceDifficulty[6].status = IT_DISABLED; + + if (choice) // Match Race + { + PLAY_RaceDifficulty[2].status = IT_STRING2|IT_CVAR; // CPUs on/off use string2 to signify not to use the normal gm font drawer + PLAY_RaceDifficulty[3].status = IT_STRING2|IT_CVAR; // Encore on/off use string2 to signify not to use the normal gm font drawer + PLAY_RaceDifficulty[5].status = IT_STRING|IT_CALL; // Level Select (Match Race) + itemOn = 5; // Select cup select by default. + + } + else // GP + { + PLAY_RaceDifficulty[3].status = IT_STRING2|IT_CVAR; // Encore on/off use string2 to signify not to use the normal gm font drawer + PLAY_RaceDifficulty[4].status = IT_STRING|IT_CALL; // Level Select (GP) + itemOn = 4; // Select cup select by default. + } +} + +// calls the above but changes the cvar we set +void M_SetupDifficultySelectMP(INT32 choice) +{ + (void) choice; + + PLAY_RaceDifficultyDef.prevMenu = currentMenu; + M_SetupNextMenu(&PLAY_RaceDifficultyDef, false); + + PLAY_RaceDifficulty[0].status = IT_DISABLED; + PLAY_RaceDifficulty[1].status = IT_STRING|IT_CVAR; + PLAY_RaceDifficulty[2].status = IT_STRING2|IT_CVAR; // CPUs on/off use string2 to signify not to use the normal gm font drawer + PLAY_RaceDifficulty[3].status = IT_STRING2|IT_CVAR; // Encore on/off use string2 to signify not to use the normal gm font drawer + PLAY_RaceDifficulty[4].status = IT_DISABLED; + PLAY_RaceDifficulty[5].status = IT_DISABLED; + PLAY_RaceDifficulty[6].status = IT_STRING|IT_CALL; + + itemOn = 6; // Select cup select by default. +} + // LEVEL SELECT // @@ -2585,10 +2667,11 @@ void M_CupSelectHandler(INT32 choice) memset(&grandprixinfo, 0, sizeof(struct grandprixinfo)); - // TODO: game settings screen - grandprixinfo.gamespeed = KARTSPEED_NORMAL; - grandprixinfo.masterbots = false; - grandprixinfo.encore = false; + // read our dummy cvars + + grandprixinfo.gamespeed = min(KARTSPEED_HARD, cv_dummygpdifficulty.value); + grandprixinfo.masterbots = (cv_dummygpdifficulty.value == 3); + grandprixinfo.encore = (boolean)cv_dummygpencore.value; grandprixinfo.cup = newcup; @@ -2744,9 +2827,18 @@ void M_LevelSelectHandler(INT32 choice) SV_StartSinglePlayerServer(); multiplayer = true; // yeah, SV_StartSinglePlayerServer clobbers this... netgame = levellist.netgame; // ^ ditto. - } - D_MapChange(levellist.choosemap+1, levellist.newgametype, (cv_kartencore.value == 1), 1, 1, false, false); + // this is considered to be CV_CHEAT however... + CV_StealthSet(&cv_kartbot, cv_dummymatchbots.string); // Match the kartbot value to the dummy match bots value. + + if (netgame) // check for the dummy kartspeed value + CV_StealthSet(&cv_kartspeed, cv_dummykartspeed.string); + + + D_MapChange(levellist.choosemap+1, levellist.newgametype, (cv_dummygpencore.value == 1), 1, 1, false, false); + } + else // directly do the map change + D_MapChange(levellist.choosemap+1, levellist.newgametype, (cv_kartencore.value == 1), 1, 1, false, false); M_ClearMenus(true); }