Merge branch 'in-flight-menus' into 'master'

Course List QOL

See merge request KartKrew/Kart!1867
This commit is contained in:
Oni 2024-01-28 23:31:59 +00:00
commit ff20f38ffa
8 changed files with 224 additions and 71 deletions

View file

@ -2490,6 +2490,7 @@ static void Command_connect(void)
// Menu restore state. // Menu restore state.
restoreMenu = &PLAY_MP_OptSelectDef; restoreMenu = &PLAY_MP_OptSelectDef;
currentMenu->lastOn = itemOn;
Music_Remap("menu", "NETMD2"); Music_Remap("menu", "NETMD2");

View file

@ -1999,14 +1999,14 @@ void K_drawKartTimestamp(tic_t drawtime, INT32 TX, INT32 TY, INT32 splitflags, U
if (gamedata->collected[(stickermedalinfo.emblems[i]-emblemlocations)]) if (gamedata->collected[(stickermedalinfo.emblems[i]-emblemlocations)])
{ {
V_DrawSmallMappedPatch(workx, worky, splitflags, V_DrawMappedPatch(workx, worky, splitflags,
static_cast<patch_t*>(W_CachePatchName(M_GetEmblemPatch(stickermedalinfo.emblems[i], false), PU_CACHE)), static_cast<patch_t*>(W_CachePatchName(M_GetEmblemPatch(stickermedalinfo.emblems[i], false), PU_CACHE)),
R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(stickermedalinfo.emblems[i]), GTC_CACHE) R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(stickermedalinfo.emblems[i]), GTC_CACHE)
); );
} }
else else
{ {
V_DrawSmallMappedPatch(workx, worky, splitflags, V_DrawMappedPatch(workx, worky, splitflags,
static_cast<patch_t*>(W_CachePatchName("NEEDIT", PU_CACHE)), static_cast<patch_t*>(W_CachePatchName("NEEDIT", PU_CACHE)),
NULL NULL
); );

View file

@ -275,7 +275,6 @@ typedef enum
ta_replay = 0, ta_replay = 0,
ta_guest, ta_guest,
ta_ghosts, ta_ghosts,
ta_spb,
ta_spacer, ta_spacer,
ta_start, ta_start,
} ta_e; } ta_e;
@ -824,7 +823,7 @@ typedef struct levelsearch_s {
#define M_LEVELLIST_SLIDETIME 4 #define M_LEVELLIST_SLIDETIME 4
extern struct levellist_s { typedef struct levellist_s {
SINT8 cursor; SINT8 cursor;
menu_anim_t slide; menu_anim_t slide;
UINT16 y; UINT16 y;
@ -834,7 +833,11 @@ extern struct levellist_s {
UINT8 guessgt; UINT8 guessgt;
levelsearch_t levelsearch; levelsearch_t levelsearch;
boolean netgame; // Start the game in an actual server boolean netgame; // Start the game in an actual server
} levellist; menu_t *backMenu;
} levellist_t;
extern levellist_t levellist;
extern levellist_t restorelevellist;
extern cupheader_t dummy_lostandfound; extern cupheader_t dummy_lostandfound;
@ -851,7 +854,8 @@ void M_CupSelectTick(void);
void M_LevelSelectHandler(INT32 choice); void M_LevelSelectHandler(INT32 choice);
void M_LevelSelectTick(void); void M_LevelSelectTick(void);
void M_LevelSelected(INT16 add); void M_LevelSelected(INT16 add, boolean menuupdate);
boolean M_LevelSelectCupSwitch(boolean next, boolean skipones);
// dummy consvars for GP & match race setup // dummy consvars for GP & match race setup
extern consvar_t cv_dummygpdifficulty; extern consvar_t cv_dummygpdifficulty;
@ -894,7 +898,7 @@ void M_PleaseWait(void);
void M_PopupMasterServerRules(void); void M_PopupMasterServerRules(void);
// Time Attack // Time Attack
void M_PrepareTimeAttack(INT32 choice); void M_PrepareTimeAttack(boolean menuupdate);
void M_StartTimeAttack(INT32 choice); void M_StartTimeAttack(INT32 choice);
void M_ReplayTimeAttack(INT32 choice); void M_ReplayTimeAttack(INT32 choice);
void M_HandleStaffReplay(INT32 choice); void M_HandleStaffReplay(INT32 choice);

View file

@ -533,26 +533,29 @@ menu_t *M_SpecificMenuRestore(menu_t *torestore)
|| torestore == &PLAY_TimeAttackDef) || torestore == &PLAY_TimeAttackDef)
{ {
// Handle unlock restrictions // Handle unlock restrictions
levellist = restorelevellist;
cupheader_t *currentcup = levellist.levelsearch.cup; cupheader_t *currentcup = levellist.levelsearch.cup;
M_SetupGametypeMenu(-1); if (levellist.levelsearch.tutorial)
if (levellist.newgametype == GT_RACE)
{ {
M_SetupRaceMenu(-1); M_InitExtras(-1);
M_SetupDifficultyOptions((cupgrid.grandprix == false)); }
else
{
M_SetupGametypeMenu(-1);
if (levellist.newgametype == GT_RACE)
{
M_SetupRaceMenu(-1);
M_SetupDifficultyOptions((cupgrid.grandprix == false));
}
} }
if (!M_LevelListFromGametype(-1)) if (!M_LevelListFromGametype(-1))
{ {
if (PLAY_LevelSelectDef.prevMenu == &PLAY_CupSelectDef) torestore = levellist.backMenu;
{
torestore = PLAY_CupSelectDef.prevMenu;
}
else
{
torestore = PLAY_LevelSelectDef.prevMenu;
}
} }
else else
{ {
@ -560,19 +563,12 @@ menu_t *M_SpecificMenuRestore(menu_t *torestore)
{ {
torestore = &PLAY_CupSelectDef; torestore = &PLAY_CupSelectDef;
} }
else if (torestore == &PLAY_TimeAttackDef) else if (levellist.levelsearch.timeattack)
{ {
M_PrepareTimeAttack(0); M_PrepareTimeAttack(true);
} }
} }
} }
else if (torestore == &PLAY_RaceDifficultyDef)
{
// Handle a much smaller subset of unlock restrictions
M_SetupGametypeMenu(-1);
M_SetupRaceMenu(-1);
M_SetupDifficultyOptions((cupgrid.grandprix == false));
}
else if (torestore == &PLAY_MP_OptSelectDef) else if (torestore == &PLAY_MP_OptSelectDef)
{ {
// Ticker init // Ticker init
@ -671,8 +667,6 @@ void M_StartControlPanel(void)
} }
} }
M_PickMenuBGMap();
if (M_GameTrulyStarted() == false) if (M_GameTrulyStarted() == false)
{ {
// Are you ready for the First Boot Experience? // Are you ready for the First Boot Experience?
@ -717,14 +711,15 @@ void M_StartControlPanel(void)
M_PlayMenuJam(); M_PlayMenuJam();
} }
itemOn = currentMenu->lastOn;
M_UpdateMenuBGImage(true);
} }
else else
{ {
M_OpenPauseMenu(); M_OpenPauseMenu();
} }
itemOn = currentMenu->lastOn;
CON_ToggleOff(); // move away console CON_ToggleOff(); // move away console
} }
@ -745,6 +740,8 @@ void M_ClearMenus(boolean callexitmenufunc)
COM_BufAddText(va("saveconfig \"%s\" -silent\n", configfile)); COM_BufAddText(va("saveconfig \"%s\" -silent\n", configfile));
#endif //Alam: But not on the Dreamcast's VMUs #endif //Alam: But not on the Dreamcast's VMUs
currentMenu->lastOn = itemOn;
if (gamestate == GS_MENU) // Back to title screen if (gamestate == GS_MENU) // Back to title screen
{ {
int i; int i;

View file

@ -52,6 +52,42 @@ boolean M_TimeAttackInputs(INT32 ch)
return true; return true;
} }
if (menucmd[pid].dpad_lr != 0
&& !((currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_ARROWS
|| (currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_CVAR)
)
{
if (menucmd[pid].dpad_lr > 0)
{
levellist.cursor++;
if (levellist.cursor >= levellist.mapcount)
{
M_LevelSelectCupSwitch(true, false);
levellist.cursor = 0;
}
}
else
{
levellist.cursor--;
if (levellist.cursor < 0)
{
M_LevelSelectCupSwitch(false, false);
levellist.cursor = levellist.mapcount-1;
}
}
M_LevelSelectScrollDest();
levellist.slide.start = 0;
M_LevelSelected(levellist.cursor, false);
itemOn = ta_start;
S_StartSound(NULL, sfx_s3k5b);
M_SetMenuDelay(pid);
return true;
}
return false; return false;
} }
@ -215,11 +251,12 @@ menu_t PLAY_TAGhostsDef = {
}; };
// time attack stuff... // time attack stuff...
void M_PrepareTimeAttack(INT32 choice) void M_PrepareTimeAttack(boolean menuupdate)
{ {
(void) choice; if (menuupdate)
{
timeattackmenu.ticker = 0; timeattackmenu.ticker = 0;
}
// Gametype guess // Gametype guess
if (levellist.guessgt != MAXGAMETYPES) if (levellist.guessgt != MAXGAMETYPES)
@ -426,7 +463,7 @@ static void M_WriteGuestReplay(INT32 ch)
Z_Free(rguest); Z_Free(rguest);
Z_Free(gpath); Z_Free(gpath);
M_PrepareTimeAttack(0); M_PrepareTimeAttack(false);
M_SetupNextMenu(&PLAY_TimeAttackDef, false); M_SetupNextMenu(&PLAY_TimeAttackDef, false);
// TODO the following isn't showing up and I'm not sure why // TODO the following isn't showing up and I'm not sure why

View file

@ -129,7 +129,9 @@ static void M_StartCup(UINT8 entry)
SV_StartSinglePlayerServer(levellist.newgametype, levellist.netgame); SV_StartSinglePlayerServer(levellist.newgametype, levellist.netgame);
M_ClearMenus(true); M_ClearMenus(true);
restoreMenu = &PLAY_CupSelectDef; restoreMenu = &PLAY_CupSelectDef;
restorelevellist = levellist;
if (entry < roundqueue.size) if (entry < roundqueue.size)
{ {
@ -265,12 +267,21 @@ void M_CupSelectHandler(INT32 choice)
M_SetMenuDelay(pid); M_SetMenuDelay(pid);
if (!newcup)
{
S_StartSound(NULL, sfx_s3kb2);
return;
}
levellist.levelsearch.cup = newcup; levellist.levelsearch.cup = newcup;
count = M_CountLevelsToShowInList(&levellist.levelsearch); count = M_CountLevelsToShowInList(&levellist.levelsearch);
if ((!newcup) if (count == 0
|| (count == 0) || (
|| (cupgrid.grandprix == true && newcup->cachedlevels[0] == NEXTMAP_INVALID)) cupgrid.grandprix == true
&& newcup->cachedlevels[0] == NEXTMAP_INVALID
)
)
{ {
S_StartSound(NULL, sfx_s3kb2); S_StartSound(NULL, sfx_s3kb2);
return; return;
@ -300,7 +311,7 @@ void M_CupSelectHandler(INT32 choice)
else if (count == 1 && levellist.levelsearch.timeattack == true) else if (count == 1 && levellist.levelsearch.timeattack == true)
{ {
currentMenu->transitionID = PLAY_TimeAttackDef.transitionID+1; currentMenu->transitionID = PLAY_TimeAttackDef.transitionID+1;
M_LevelSelected(0); M_LevelSelected(0, true);
} }
else else
{ {

View file

@ -37,7 +37,8 @@ menu_t PLAY_LevelSelectDef = {
NULL NULL
}; };
struct levellist_s levellist; levellist_t levellist;
levellist_t restorelevellist;
// //
// M_CanShowLevelInList // M_CanShowLevelInList
@ -278,6 +279,8 @@ boolean M_LevelListFromGametype(INT16 gt)
CV_SetValue(&cv_dummyspbattack, 0); CV_SetValue(&cv_dummyspbattack, 0);
} }
levellist.backMenu = currentMenu;
if (gamestate == GS_MENU) if (gamestate == GS_MENU)
{ {
const char *music; const char *music;
@ -290,8 +293,8 @@ boolean M_LevelListFromGametype(INT16 gt)
} }
else else
{ {
music = currentMenu->music; music = levellist.backMenu->music;
bgroutine = currentMenu->bgroutine; bgroutine = levellist.backMenu->bgroutine;
} }
menu_t *remap_menus[] = { menu_t *remap_menus[] = {
@ -304,17 +307,18 @@ boolean M_LevelListFromGametype(INT16 gt)
NULL NULL
}; };
size_t i; INT16 i, j;
for (i = 0; remap_menus[i]; i++) for (i = 0; remap_menus[i]; i++)
{ {
remap_menus[i]->music = music; remap_menus[i]->music = music;
remap_menus[i]->bgroutine = bgroutine; remap_menus[i]->bgroutine = bgroutine;
}
// Not for the time attack ones for (j = 0; j < remap_menus[i]->numitems; j++)
PLAY_CupSelectDef.menuitems[0].patch = \ {
PLAY_LevelSelectDef.menuitems[0].patch = \ remap_menus[i]->menuitems[j].patch = \
currentMenu->menuitems[itemOn].patch; currentMenu->menuitems[itemOn].patch;
}
}
} }
} }
@ -548,10 +552,11 @@ boolean M_LevelListFromGametype(INT16 gt)
cupgrid.pageno = 0; cupgrid.pageno = 0;
} }
PLAY_CupSelectDef.prevMenu = levellist.backMenu;
PLAY_LevelSelectDef.prevMenu = &PLAY_CupSelectDef;
if (gt != -1) if (gt != -1)
{ {
PLAY_CupSelectDef.prevMenu = currentMenu;
PLAY_LevelSelectDef.prevMenu = &PLAY_CupSelectDef;
M_SetupNextMenu(&PLAY_CupSelectDef, false); M_SetupNextMenu(&PLAY_CupSelectDef, false);
} }
@ -597,15 +602,16 @@ boolean M_LevelListFromGametype(INT16 gt)
M_LevelSelectScrollDest(); M_LevelSelectScrollDest();
levellist.slide.start = 0; levellist.slide.start = 0;
PLAY_LevelSelectDef.prevMenu = levellist.backMenu;
if (gt != -1) if (gt != -1)
{ {
if (levellist.levelsearch.tutorial && levellist.mapcount == 1) if (levellist.levelsearch.tutorial && levellist.mapcount == 1)
{ {
M_LevelSelected(0); // Skip the list! M_LevelSelected(0, true); // Skip the list!
} }
else else
{ {
PLAY_LevelSelectDef.prevMenu = currentMenu;
M_SetupNextMenu(&PLAY_LevelSelectDef, false); M_SetupNextMenu(&PLAY_LevelSelectDef, false);
} }
} }
@ -658,7 +664,7 @@ void M_LevelSelectInit(INT32 choice)
} }
} }
void M_LevelSelected(INT16 add) void M_LevelSelected(INT16 add, boolean menuupdate)
{ {
UINT8 i = 0; UINT8 i = 0;
INT16 map = M_GetFirstLevelInList(&i, &levellist.levelsearch); INT16 map = M_GetFirstLevelInList(&i, &levellist.levelsearch);
@ -685,13 +691,18 @@ void M_LevelSelected(INT16 add)
if (levellist.levelsearch.timeattack) if (levellist.levelsearch.timeattack)
{ {
S_StartSound(NULL, sfx_s3k63); restorelevellist = levellist;
M_PrepareTimeAttack(0); M_PrepareTimeAttack(menuupdate);
PLAY_TimeAttackDef.lastOn = ta_start; if (menuupdate)
PLAY_TimeAttackDef.prevMenu = currentMenu; {
M_SetupNextMenu(&PLAY_TimeAttackDef, false); S_StartSound(NULL, sfx_s3k63);
PLAY_TimeAttackDef.lastOn = ta_start;
PLAY_TimeAttackDef.prevMenu = currentMenu;
M_SetupNextMenu(&PLAY_TimeAttackDef, false);
}
} }
else else
{ {
@ -744,19 +755,17 @@ void M_LevelSelected(INT16 add)
D_MapChange(levellist.choosemap+1, levellist.newgametype, (cv_kartencore.value == 1), 1, 1, false, false); D_MapChange(levellist.choosemap+1, levellist.newgametype, (cv_kartencore.value == 1), 1, 1, false, false);
if (!M_GameTrulyStarted() || if (levellist.netgame == true)
levellist.levelsearch.tutorial)
{
restoreMenu = currentMenu;
}
else if (levellist.netgame == true)
{ {
restoreMenu = &PLAY_MP_OptSelectDef; restoreMenu = &PLAY_MP_OptSelectDef;
} }
else else /*if (!M_GameTrulyStarted() ||
levellist.levelsearch.tutorial)*/
{ {
restoreMenu = &PLAY_RaceDifficultyDef; restoreMenu = currentMenu;
} }
restorelevellist = levellist;
} }
else else
{ {
@ -768,6 +777,87 @@ void M_LevelSelected(INT16 add)
} }
} }
boolean M_LevelSelectCupSwitch(boolean next, boolean skipones)
{
levelsearch_t templevelsearch = levellist.levelsearch;
while (1)
{
if (next)
{
// Next
if (++cupgrid.x >= CUPMENU_COLUMNS)
{
cupgrid.x = 0;
if (++cupgrid.y >= CUPMENU_ROWS)
{
cupgrid.y = 0;
if (++cupgrid.pageno >= cupgrid.numpages)
{
cupgrid.pageno = 0;
}
}
}
}
else
{
// Prev
if (cupgrid.x == 0)
{
cupgrid.x = CUPMENU_COLUMNS;
if (cupgrid.y == 0)
{
cupgrid.y = CUPMENU_ROWS;
if (cupgrid.pageno == 0)
{
cupgrid.pageno = cupgrid.numpages;
}
cupgrid.pageno--;
}
cupgrid.y--;
}
cupgrid.x--;
}
templevelsearch.cup = cupgrid.builtgrid[CUPMENU_CURSORID];
if (templevelsearch.cup == levellist.levelsearch.cup)
{
return false;
}
if (!templevelsearch.cup)
{
continue;
}
UINT16 count = M_CountLevelsToShowInList(&templevelsearch);
if (count == 0
// The following isn't ideal, but in addition to the
// necessary programming work being extremely annoying,
// I also just think being forced to switch between
// Time Attack single-course views and multi-course
// selections would just plain kind of look bad.
// ~toast 250124 (ON A PLANE BACK FROM MAGFEST WOOOOOOOO)
|| (skipones && count == 1))
{
continue;
}
levellist.levelsearch = templevelsearch;
levellist.mapcount = count;
if (levellist.cursor >= count)
levellist.cursor = count-1;
M_LevelSelectScrollDest();
levellist.slide.start = 0;
return true;
}
}
void M_LevelSelectHandler(INT32 choice) void M_LevelSelectHandler(INT32 choice)
{ {
const UINT8 pid = 0; const UINT8 pid = 0;
@ -795,13 +885,26 @@ void M_LevelSelectHandler(INT32 choice)
S_StartSound(NULL, sfx_s3k5b); S_StartSound(NULL, sfx_s3k5b);
M_SetMenuDelay(pid); M_SetMenuDelay(pid);
} }
else if (levellist.levelsearch.cup == NULL)
; // Mode with no cup? No left/right input for you!
else if (menucmd[pid].dpad_lr != 0)
{
if (M_LevelSelectCupSwitch(
(menucmd[pid].dpad_lr > 0),
levellist.levelsearch.timeattack)
)
{
S_StartSound(NULL, sfx_s3k5b);
M_SetMenuDelay(pid);
}
}
M_LevelSelectScrollDest(); M_LevelSelectScrollDest();
if (M_MenuConfirmPressed(pid) /*|| M_MenuButtonPressed(pid, MBT_START)*/) if (M_MenuConfirmPressed(pid) /*|| M_MenuButtonPressed(pid, MBT_START)*/)
{ {
M_SetMenuDelay(pid); M_SetMenuDelay(pid);
M_LevelSelected(levellist.cursor); M_LevelSelected(levellist.cursor, true);
} }
else if (M_MenuBackPressed(pid)) else if (M_MenuBackPressed(pid))
{ {

View file

@ -123,7 +123,7 @@ void M_OpenPauseMenu(void)
pausemenu.openoffset.dist = 0; pausemenu.openoffset.dist = 0;
pausemenu.closing = false; pausemenu.closing = false;
currentMenu->lastOn = mpause_continue; // Make sure we select "RESUME GAME" by default itemOn = currentMenu->lastOn = mpause_continue; // Make sure we select "RESUME GAME" by default
// Now the hilarious balancing act of deciding what options should be enabled and which ones shouldn't be! // Now the hilarious balancing act of deciding what options should be enabled and which ones shouldn't be!
// By default, disable anything sensitive: // By default, disable anything sensitive: