Restore menu state after playsim

- restoreMenu, M_SpecificMenuRestore
    - From any Cup Select, Level Select, or Time Attack context (including non-net replay playback), return to the relevant "core menu"
    - From any server OR server connection failure, return to the Online EGGA CHANNEL top-level menu
    - From netreplay, head to replay hut without incorrect gamestate/fade cope
    - Interruption for Challenges unlock sequence now happens on all menu returns, not just post-titlescreen
- M_StartControlPanel
    - Integrate with above
    - Handle menu re-initialisation properly under more contexts
- D_ClearState
    - Split out from D_StartTitle
    - Can be used alongside M_StartControlPanel to restore menu state from any play session in a way just as reliable as D_StartTitle was
This commit is contained in:
toaster 2023-01-29 23:53:21 +00:00
parent 154d9c5f18
commit 20e9b2f5e8
16 changed files with 220 additions and 104 deletions

View file

@ -1533,7 +1533,8 @@ static boolean CL_FinishedFileList(void)
{ {
D_QuitNetGame(); D_QuitNetGame();
CL_Reset(); CL_Reset();
D_StartTitle(); D_ClearState();
M_StartControlPanel();
M_StartMessage(M_GetText( M_StartMessage(M_GetText(
"You have too many WAD files loaded\n" "You have too many WAD files loaded\n"
"to add ones the server is using.\n" "to add ones the server is using.\n"
@ -1546,7 +1547,8 @@ static boolean CL_FinishedFileList(void)
{ {
D_QuitNetGame(); D_QuitNetGame();
CL_Reset(); CL_Reset();
D_StartTitle(); D_ClearState();
M_StartControlPanel();
M_StartMessage(M_GetText( M_StartMessage(M_GetText(
"You have the wrong addons loaded.\n\n" "You have the wrong addons loaded.\n\n"
"To play on this server, restart\n" "To play on this server, restart\n"
@ -1713,7 +1715,8 @@ static boolean CL_ServerConnectionSearchTicker(tic_t *asksent)
D_QuitNetGame(); D_QuitNetGame();
CL_Reset(); CL_Reset();
D_StartTitle(); D_ClearState();
M_StartControlPanel();
M_StartMessage(va( M_StartMessage(va(
"Your EXE differs from the server.\n" "Your EXE differs from the server.\n"
@ -1864,7 +1867,8 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic
CONS_Printf(M_GetText("Network game synchronization aborted.\n")); CONS_Printf(M_GetText("Network game synchronization aborted.\n"));
D_QuitNetGame(); D_QuitNetGame();
CL_Reset(); CL_Reset();
D_StartTitle(); D_ClearState();
M_StartControlPanel();
M_StartMessage(M_GetText( M_StartMessage(M_GetText(
"The direct download encountered an error.\n" "The direct download encountered an error.\n"
"See the logfile for more info.\n" "See the logfile for more info.\n"
@ -1893,7 +1897,8 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic
CONS_Printf(M_GetText("Network game synchronization aborted.\n")); CONS_Printf(M_GetText("Network game synchronization aborted.\n"));
D_QuitNetGame(); D_QuitNetGame();
CL_Reset(); CL_Reset();
D_StartTitle(); D_ClearState();
M_StartControlPanel();
M_StartMessage(M_GetText( M_StartMessage(M_GetText(
"5 minute wait time exceeded.\n" "5 minute wait time exceeded.\n"
"You may retry connection.\n" "You may retry connection.\n"
@ -1982,7 +1987,8 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic
D_QuitNetGame(); D_QuitNetGame();
CL_Reset(); CL_Reset();
D_StartTitle(); D_ClearState();
M_StartControlPanel();
return false; return false;
} }
@ -2507,6 +2513,7 @@ static void Command_connect(void)
SplitScreen_OnChange(); SplitScreen_OnChange();
} }
restoreMenu = &PLAY_MP_OptSelectDef;
CL_ConnectToServer(); CL_ConnectToServer();
} }
@ -3142,7 +3149,8 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
D_QuitNetGame(); D_QuitNetGame();
CL_Reset(); CL_Reset();
D_StartTitle(); D_ClearState();
M_StartControlPanel();
if (msg == KICK_MSG_CON_FAIL) if (msg == KICK_MSG_CON_FAIL)
M_StartMessage(M_GetText("Server closed connection\n(Synch failure)\nPress (B)\n"), NULL, MM_NOTHING); M_StartMessage(M_GetText("Server closed connection\n(Synch failure)\nPress (B)\n"), NULL, MM_NOTHING);
@ -4169,7 +4177,8 @@ static void HandleShutdown(SINT8 node)
LUA_HookBool(false, HOOK(GameQuit)); LUA_HookBool(false, HOOK(GameQuit));
D_QuitNetGame(); D_QuitNetGame();
CL_Reset(); CL_Reset();
D_StartTitle(); D_ClearState();
M_StartControlPanel();
M_StartMessage(M_GetText("Server has shutdown\n\nPress (B)\n"), NULL, MM_NOTHING); M_StartMessage(M_GetText("Server has shutdown\n\nPress (B)\n"), NULL, MM_NOTHING);
} }
@ -4184,7 +4193,8 @@ static void HandleTimeout(SINT8 node)
LUA_HookBool(false, HOOK(GameQuit)); LUA_HookBool(false, HOOK(GameQuit));
D_QuitNetGame(); D_QuitNetGame();
CL_Reset(); CL_Reset();
D_StartTitle(); D_ClearState();
M_StartControlPanel();
M_StartMessage(M_GetText("Server Timeout\n\nPress (B)\n"), NULL, MM_NOTHING); M_StartMessage(M_GetText("Server Timeout\n\nPress (B)\n"), NULL, MM_NOTHING);
} }
@ -4370,7 +4380,8 @@ static void HandlePacketFromAwayNode(SINT8 node)
D_QuitNetGame(); D_QuitNetGame();
CL_Reset(); CL_Reset();
D_StartTitle(); D_ClearState();
M_StartControlPanel();
if (reason[1] == '|') if (reason[1] == '|')
{ {

View file

@ -915,9 +915,9 @@ void D_SRB2Loop(void)
// ========================================================================= // =========================================================================
// //
// D_StartTitle // D_ClearState
// //
void D_StartTitle(void) void D_ClearState(void)
{ {
INT32 i; INT32 i;
@ -932,7 +932,7 @@ void D_StartTitle(void)
i = G_GetFirstMapOfGametype(gametype)+1; i = G_GetFirstMapOfGametype(gametype)+1;
if (i > nummapheaders) if (i > nummapheaders)
I_Error("D_StartTitle: No valid map ID found!?"); I_Error("D_ClearState: No valid map ID found!?");
COM_BufAddText(va("map %s\n", G_BuildMapName(i))); COM_BufAddText(va("map %s\n", G_BuildMapName(i)));
} }
@ -979,15 +979,27 @@ void D_StartTitle(void)
memset(gamekeydown, 0, sizeof (gamekeydown)); memset(gamekeydown, 0, sizeof (gamekeydown));
memset(deviceResponding, false, sizeof (deviceResponding)); memset(deviceResponding, false, sizeof (deviceResponding));
F_StartTitleScreen();
M_ClearMenus(false);
// Reset the palette // Reset the palette
if (rendermode != render_none) if (rendermode != render_none)
V_SetPaletteLump("PLAYPAL"); V_SetPaletteLump("PLAYPAL");
// The title screen is obviously not a tutorial! (Unless I'm mistaken) // The title screen is obviously not a tutorial! (Unless I'm mistaken)
tutorialmode = false; tutorialmode = false;
G_SetGamestate(GS_NULL);
}
//
// D_StartTitle
//
void D_StartTitle(void)
{
D_ClearState();
if (netgame)
return;
F_StartTitleScreen();
M_ClearMenus(false);
} }
// //

View file

@ -57,6 +57,7 @@ const char *D_Home(void);
// //
// BASE LEVEL // BASE LEVEL
// //
void D_ClearState(void);
void D_StartTitle(void); void D_StartTitle(void);
#ifdef __cplusplus #ifdef __cplusplus

View file

@ -2971,6 +2971,7 @@ static void Command_Map_f(void)
if (!Playing()) if (!Playing())
{ {
multiplayer = true; multiplayer = true;
restoreMenu = NULL;
} }
} }
@ -5782,7 +5783,10 @@ void Command_ExitGame_f(void)
closefilemenu(true); closefilemenu(true);
if (!modeattacking) if (!modeattacking)
D_StartTitle(); {
D_ClearState();
M_StartControlPanel();
}
} }
void Command_Retry_f(void) void Command_Retry_f(void)

View file

@ -2990,7 +2990,8 @@ void G_ExitLevel(void)
{ {
D_QuitNetGame(); D_QuitNetGame();
CL_Reset(); CL_Reset();
D_StartTitle(); D_ClearState();
M_StartControlPanel();
} }
} }
else else
@ -4003,15 +4004,7 @@ void G_AfterIntermission(void)
if (demo.playback) if (demo.playback)
{ {
G_StopDemo(); M_PlaybackQuit(0);
#if 0
if (demo.inreplayhut)
M_ReplayHut(0);
else
#endif
D_StartTitle();
return; return;
} }
else if (demo.recording && (modeattacking || demo.savemode != DSM_NOTSAVING)) else if (demo.recording && (modeattacking || demo.savemode != DSM_NOTSAVING))
@ -4170,8 +4163,8 @@ void G_EndGame(void)
{ {
if (nextmap == NEXTMAP_CEREMONY) // end game with ceremony if (nextmap == NEXTMAP_CEREMONY) // end game with ceremony
{ {
D_StartTitle(); //F_StartEnding(); -- temporary /*F_StartEnding(); -- temporary
return; return;*/
} }
if (nextmap == NEXTMAP_CREDITS) // end game with credits if (nextmap == NEXTMAP_CREDITS) // end game with credits
{ {
@ -4186,7 +4179,8 @@ void G_EndGame(void)
} }
// direct or competitive multiplayer, so go back to title screen. // direct or competitive multiplayer, so go back to title screen.
D_StartTitle(); D_ClearState();
M_StartControlPanel();
} }
// //

View file

@ -466,6 +466,8 @@ typedef enum
void Moviemode_option_Onchange(void); void Moviemode_option_Onchange(void);
extern menu_t *currentMenu; extern menu_t *currentMenu;
extern menu_t *restoreMenu;
extern char dummystaffname[22]; extern char dummystaffname[22];
extern consvar_t cv_dummystaff; extern consvar_t cv_dummystaff;
@ -583,6 +585,7 @@ boolean M_MenuExtraPressed(UINT8 pid);
boolean M_MenuExtraHeld(UINT8 pid); boolean M_MenuExtraHeld(UINT8 pid);
void M_StartControlPanel(void); void M_StartControlPanel(void);
menu_t *M_SpecificMenuRestore(menu_t *torestore);
void M_ClearMenus(boolean callexitmenufunc); void M_ClearMenus(boolean callexitmenufunc);
void M_SelectableClearMenus(INT32 choice); void M_SelectableClearMenus(INT32 choice);
void M_SetupNextMenu(menu_t *menudef, boolean nofade); void M_SetupNextMenu(menu_t *menudef, boolean nofade);

View file

@ -237,7 +237,7 @@ static void M_DrawMenuParty(void)
UINT16 color; UINT16 color;
UINT8 *colormap; UINT8 *colormap;
if (setup_numplayers == 0 || currentMenu == &PLAY_CharSelectDef) if (setup_numplayers == 0 || currentMenu == &PLAY_CharSelectDef || currentMenu == &MISC_ChallengesDef)
{ {
return; return;
} }

View file

@ -35,6 +35,7 @@ boolean fromlevelselect = false;
// current menudef // current menudef
menu_t *currentMenu = &MAIN_ProfilesDef; menu_t *currentMenu = &MAIN_ProfilesDef;
menu_t *restoreMenu = NULL;
char dummystaffname[22]; char dummystaffname[22];
@ -355,6 +356,51 @@ boolean M_Responder(event_t *ev)
return true; return true;
} }
//
// M_SpecificMenuRestore
//
menu_t *M_SpecificMenuRestore(menu_t *torestore)
{
// I'd advise the following not be a switch case because they're pointers...
if (torestore == &PLAY_CupSelectDef
|| torestore == &PLAY_LevelSelectDef
|| torestore == &PLAY_TimeAttackDef)
{
// Handle unlock restrictions
M_SetupGametypeMenu(-1);
M_SetupRaceMenu(-1);
if (!M_LevelListFromGametype(-1))
{
if (PLAY_LevelSelectDef.prevMenu == &PLAY_CupSelectDef)
{
torestore = PLAY_CupSelectDef.prevMenu;
}
else
{
torestore = PLAY_LevelSelectDef.prevMenu;
}
}
else if (torestore == &PLAY_TimeAttackDef)
{
M_PrepareTimeAttack(0);
}
}
else if (torestore == &EXTRAS_ReplayHutDef)
{
// Handle modifications to the folder while playing
M_ReplayHut(0);
}
if (setup_numplayers == 0)
{
setup_numplayers = 1;
}
return torestore;
}
// //
// M_StartControlPanel // M_StartControlPanel
// //
@ -370,32 +416,18 @@ void M_StartControlPanel(void)
} }
// intro might call this repeatedly // intro might call this repeatedly
if (menuactive) if (menuactive && gamestate != GS_NULL)
{ {
CON_ToggleOff(); // move away console CON_ToggleOff(); // move away console
return; return;
} }
if (gamestate == GS_TITLESCREEN) // Set up menu state if (gamestate == GS_TITLESCREEN && restoreMenu == NULL) // Set up menu state
{ {
// No instantly skipping the titlescreen. // No instantly skipping the titlescreen.
// (We can change this timer later when extra animation is added.) // (We can change this timer later when extra animation is added.)
if (finalecount < 1) if (finalecount < 1)
return; return;
G_SetGamestate(GS_MENU);
gameaction = ga_nothing;
paused = false;
CON_ToggleOff();
if (cv_menujam_update.value)
{
CV_AddValue(&cv_menujam, 1);
CV_SetValue(&cv_menujam_update, 0);
}
S_ChangeMusicInternal(cv_menujam.string, true);
} }
menuactive = true; menuactive = true;
@ -408,6 +440,28 @@ void M_StartControlPanel(void)
{ {
M_StopMessage(0); // Doesn't work with MM_YESNO or MM_EVENTHANDLER... but good enough to get the game as it is currently functional again M_StopMessage(0); // Doesn't work with MM_YESNO or MM_EVENTHANDLER... but good enough to get the game as it is currently functional again
if (gamestate != GS_MENU)
{
G_SetGamestate(GS_MENU);
gameaction = ga_nothing;
paused = false;
CON_ToggleOff();
modeattacking = ATTACKING_NONE;
if (cv_menujam_update.value)
{
CV_AddValue(&cv_menujam, 1);
CV_SetValue(&cv_menujam_update, 0);
}
S_ChangeMusicInternal(cv_menujam.string, true);
if (!restoreMenu)
restoreMenu = &MainDef;
}
if (cv_currprofile.value == -1) // Only ask once per session. if (cv_currprofile.value == -1) // Only ask once per session.
{ {
// Make sure the profile data is ready now since we need to select a profile. // Make sure the profile data is ready now since we need to select a profile.
@ -431,8 +485,10 @@ void M_StartControlPanel(void)
} }
else else
{ {
currentMenu = M_InterruptMenuWithChallenges(&MainDef); currentMenu = M_SpecificMenuRestore(M_InterruptMenuWithChallenges(restoreMenu));
} }
restoreMenu = NULL;
} }
else else
{ {

View file

@ -416,6 +416,8 @@ boolean M_ChallengesInputs(INT32 ch)
{ {
if (M_MenuBackPressed(pid) || start) if (M_MenuBackPressed(pid) || start)
{ {
currentMenu->prevMenu = M_SpecificMenuRestore(currentMenu->prevMenu);
M_GoBack(0); M_GoBack(0);
M_SetMenuDelay(pid); M_SetMenuDelay(pid);

View file

@ -26,11 +26,11 @@ menu_t EXTRAS_ReplayHutDef =
EXTRAS_ReplayHut, EXTRAS_ReplayHut,
30, 80, 30, 80,
0, 0, 0, 0,
0, 0, 41, 1,
M_DrawReplayHut, M_DrawReplayHut,
NULL, NULL,
NULL, NULL,
M_QuitReplayHut, NULL,
NULL NULL
}; };
@ -58,7 +58,7 @@ menu_t EXTRAS_ReplayStartDef =
EXTRAS_ReplayStart, EXTRAS_ReplayStart,
27, 80, 27, 80,
0, 0, 0, 0,
0, 0, 41, 1,
M_DrawReplayStartMenu, M_DrawReplayStartMenu,
NULL, NULL,
NULL, NULL,
@ -102,37 +102,43 @@ void M_ReplayHut(INT32 choice)
{ {
(void)choice; (void)choice;
extrasmenu.replayScrollTitle = 0; if (demo.inreplayhut)
extrasmenu.replayScrollDelay = TICRATE; {
extrasmenu.replayScrollDir = 1; demo.rewinding = false;
CL_ClearRewinds();
if (!demo.inreplayhut) }
else
{ {
snprintf(menupath, 1024, "%s"PATHSEP"media"PATHSEP"replay"PATHSEP"online"PATHSEP, srb2home); snprintf(menupath, 1024, "%s"PATHSEP"media"PATHSEP"replay"PATHSEP"online"PATHSEP, srb2home);
menupathindex[(menudepthleft = menudepth-1)] = strlen(menupath); menupathindex[(menudepthleft = menudepth-1)] = strlen(menupath);
} }
if (!preparefilemenu(false, true)) if (!preparefilemenu(false, true))
{ {
M_StartMessage("No replays found.\n\nPress (B)\n", NULL, MM_NOTHING); M_StartMessage("No replays found.\n\nPress (B)\n", NULL, MM_NOTHING);
if (restoreMenu == &EXTRAS_ReplayHutDef)
{
restoreMenu = &EXTRAS_MainDef;
}
return; return;
} }
else if (!demo.inreplayhut) else if (!demo.inreplayhut)
{
dir_on[menudepthleft] = 0; dir_on[menudepthleft] = 0;
demo.inreplayhut = true; }
extrasmenu.replayScrollTitle = 0; extrasmenu.replayScrollDelay = TICRATE; extrasmenu.replayScrollDir = 1; extrasmenu.replayScrollTitle = 0;
extrasmenu.replayScrollDelay = TICRATE;
extrasmenu.replayScrollDir = 1;
M_PrepReplayList(); M_PrepReplayList();
menuactive = true; if (!demo.inreplayhut)
M_SetupNextMenu(&EXTRAS_ReplayHutDef, false); M_SetupNextMenu(&EXTRAS_ReplayHutDef, false);
//G_SetGamestate(GS_TIMEATTACK);
//titlemapinaction = TITLEMAP_OFF; // Nope don't give us HOMs please
demo.rewinding = false; demo.inreplayhut = true;
CL_ClearRewinds();
//S_ChangeMusicInternal("replst", true);
} }
// key handler // key handler
@ -223,11 +229,11 @@ void M_HandleReplayHutList(INT32 choice)
M_PrepReplayList(); M_PrepReplayList();
break; break;
default: default:
// We can't just use M_SetupNextMenu because that'll run ReplayDef's quitroutine and boot us back to the title screen! M_SetupNextMenu(&EXTRAS_ReplayStartDef, false);
currentMenu->lastOn = itemOn;
currentMenu = &EXTRAS_ReplayStartDef;
extrasmenu.replayScrollTitle = 0; extrasmenu.replayScrollDelay = TICRATE; extrasmenu.replayScrollDir = 1; extrasmenu.replayScrollTitle = 0;
extrasmenu.replayScrollDelay = TICRATE;
extrasmenu.replayScrollDir = 1;
switch (extrasmenu.demolist[dir_on[menudepthleft]].addonstatus) switch (extrasmenu.demolist[dir_on[menudepthleft]].addonstatus)
{ {
@ -267,16 +273,13 @@ void M_HandleReplayHutList(INT32 choice)
boolean M_QuitReplayHut(void) boolean M_QuitReplayHut(void)
{ {
// D_StartTitle does its own wipe, since GS_TIMEATTACK is now a complete gamestate.
menuactive = false;
D_StartTitle();
if (extrasmenu.demolist) if (extrasmenu.demolist)
Z_Free(extrasmenu.demolist); Z_Free(extrasmenu.demolist);
extrasmenu.demolist = NULL; extrasmenu.demolist = NULL;
demo.inreplayhut = false; demo.inreplayhut = false;
M_GoBack(0);
return true; return true;
} }
@ -284,6 +287,8 @@ void M_HutStartReplay(INT32 choice)
{ {
(void)choice; (void)choice;
restoreMenu = &EXTRAS_ReplayHutDef;
M_ClearMenus(false); M_ClearMenus(false);
demo.loadfiles = (itemOn == 0); demo.loadfiles = (itemOn == 0);
demo.ignorefiles = (itemOn != 0); demo.ignorefiles = (itemOn != 0);

View file

@ -25,9 +25,8 @@ menu_t PLAY_GamemodesDef = KARTGAMEMODEMENU(PLAY_GamemodesMenu, &PLAY_MainDef);
void M_SetupGametypeMenu(INT32 choice) void M_SetupGametypeMenu(INT32 choice)
{ {
(void)choice; if (choice != -1)
PLAY_GamemodesDef.prevMenu = currentMenu;
PLAY_GamemodesDef.prevMenu = currentMenu;
// Battle and Capsules (and Special) disabled // Battle and Capsules (and Special) disabled
PLAY_GamemodesMenu[1].status = IT_DISABLED; PLAY_GamemodesMenu[1].status = IT_DISABLED;
@ -65,5 +64,6 @@ void M_SetupGametypeMenu(INT32 choice)
} }
} }
M_SetupNextMenu(&PLAY_GamemodesDef, false); if (choice != -1)
M_SetupNextMenu(&PLAY_GamemodesDef, false);
} }

View file

@ -22,9 +22,8 @@ menu_t PLAY_RaceGamemodesDef = KARTGAMEMODEMENU(PLAY_RaceGamemodesMenu, &PLAY_Ga
void M_SetupRaceMenu(INT32 choice) void M_SetupRaceMenu(INT32 choice)
{ {
(void)choice; if (choice != -1)
PLAY_RaceGamemodesDef.prevMenu = currentMenu;
PLAY_RaceGamemodesDef.prevMenu = currentMenu;
// Time Attack disabled // Time Attack disabled
PLAY_RaceGamemodesMenu[2].status = IT_DISABLED; PLAY_RaceGamemodesMenu[2].status = IT_DISABLED;
@ -36,5 +35,6 @@ void M_SetupRaceMenu(INT32 choice)
PLAY_RaceGamemodesMenu[2].status = IT_STRING | IT_CALL; PLAY_RaceGamemodesMenu[2].status = IT_STRING | IT_CALL;
} }
M_SetupNextMenu(&PLAY_RaceGamemodesDef, false); if (choice != -1)
M_SetupNextMenu(&PLAY_RaceGamemodesDef, false);
} }

View file

@ -290,8 +290,12 @@ void M_HandleStaffReplay(INT32 choice)
void M_ReplayTimeAttack(INT32 choice) void M_ReplayTimeAttack(INT32 choice)
{ {
const char *which; const char *which;
restoreMenu = &PLAY_TimeAttackDef;
M_ClearMenus(true); M_ClearMenus(true);
demo.loadfiles = false; demo.ignorefiles = true; // Just assume that record attack replays have the files needed demo.loadfiles = false;
demo.ignorefiles = true; // Just assume that record attack replays have the files needed
switch (choice) switch (choice)
{ {
@ -445,6 +449,8 @@ void M_StartTimeAttack(INT32 choice)
else else
G_RecordDemo(nameofdemo); G_RecordDemo(nameofdemo);
restoreMenu = &PLAY_TimeAttackDef;
M_ClearMenus(true); M_ClearMenus(true);
D_MapChange(levellist.choosemap+1, levellist.newgametype, (cv_dummygpencore.value == 1), 1, 1, false, false); D_MapChange(levellist.choosemap+1, levellist.newgametype, (cv_dummygpencore.value == 1), 1, 1, false, false);
} }

View file

@ -157,6 +157,8 @@ void M_CupSelectHandler(INT32 choice)
); );
M_ClearMenus(true); M_ClearMenus(true);
restoreMenu = &PLAY_CupSelectDef;
} }
else if (count == 1) else if (count == 1)
{ {

View file

@ -195,13 +195,14 @@ void M_LevelSelectScrollDest(void)
levellist.dest = (6*m)-3; levellist.dest = (6*m)-3;
} }
// Builds the level list we'll be using from the gametype we're choosing and send us to the apropriate menu. // Builds the level list we'll be using from the gametype we're choosing and send us to the apropriate menu.
// A gt of -1 means the menu is being restored.
boolean M_LevelListFromGametype(INT16 gt) boolean M_LevelListFromGametype(INT16 gt)
{ {
static boolean first = true; static boolean first = true;
UINT8 temp = 0; UINT8 temp = 0;
if (first || gt != levellist.newgametype || levellist.guessgt != MAXGAMETYPES) if (gt != -1 && (first || gt != levellist.newgametype || levellist.guessgt != MAXGAMETYPES))
{ {
if (first) if (first)
{ {
@ -224,7 +225,6 @@ boolean M_LevelListFromGametype(INT16 gt)
} }
levellist.levelsearch.cupmode = (!(gametypes[gt]->rules & GTR_NOCUPSELECT)); levellist.levelsearch.cupmode = (!(gametypes[gt]->rules & GTR_NOCUPSELECT));
levellist.levelsearch.cup = NULL;
first = false; first = false;
} }
@ -237,7 +237,7 @@ boolean M_LevelListFromGametype(INT16 gt)
levelsearch_t templevelsearch = levellist.levelsearch; // full copy levelsearch_t templevelsearch = levellist.levelsearch; // full copy
size_t currentid = 0, highestunlockedid = 0; size_t currentid = 0, highestunlockedid = 0;
const size_t pagelen = sizeof(cupheader_t*) * (CUPMENU_COLUMNS * CUPMENU_ROWS); const size_t pagelen = sizeof(cupheader_t*) * (CUPMENU_COLUMNS * CUPMENU_ROWS);
boolean foundany = false; boolean foundany = false, currentvalid = false;
templevelsearch.cup = kartcupheaders; templevelsearch.cup = kartcupheaders;
@ -297,11 +297,15 @@ boolean M_LevelListFromGametype(INT16 gt)
if (M_GetFirstLevelInList(&temp, &templevelsearch) != NEXTMAP_INVALID) if (M_GetFirstLevelInList(&temp, &templevelsearch) != NEXTMAP_INVALID)
{ {
highestunlockedid = currentid; highestunlockedid = currentid;
if (Playing() && mapheaderinfo[gamemap-1] && mapheaderinfo[gamemap-1]->cup == templevelsearch.cup)
if (Playing()
? (mapheaderinfo[gamemap-1] && mapheaderinfo[gamemap-1]->cup == templevelsearch.cup)
: (gt == -1 && levellist.levelsearch.cup == templevelsearch.cup))
{ {
cupgrid.x = currentid % CUPMENU_COLUMNS; cupgrid.x = currentid % CUPMENU_COLUMNS;
cupgrid.y = (currentid / CUPMENU_COLUMNS) % CUPMENU_ROWS; cupgrid.y = (currentid / CUPMENU_COLUMNS) % CUPMENU_ROWS;
cupgrid.pageno = currentid / (CUPMENU_COLUMNS * CUPMENU_ROWS); cupgrid.pageno = currentid / (CUPMENU_COLUMNS * CUPMENU_ROWS);
currentvalid = true;
} }
} }
@ -314,15 +318,27 @@ boolean M_LevelListFromGametype(INT16 gt)
return false; return false;
} }
if (currentvalid == false)
{
levellist.levelsearch.cup = NULL;
if (gt == -1 && restoreMenu != &PLAY_CupSelectDef)
{
restoreMenu = &PLAY_CupSelectDef;
}
}
cupgrid.numpages = (highestunlockedid / (CUPMENU_COLUMNS * CUPMENU_ROWS)) + 1; cupgrid.numpages = (highestunlockedid / (CUPMENU_COLUMNS * CUPMENU_ROWS)) + 1;
if (cupgrid.pageno >= cupgrid.numpages) if (cupgrid.pageno >= cupgrid.numpages)
{ {
cupgrid.pageno = 0; cupgrid.pageno = 0;
} }
PLAY_CupSelectDef.prevMenu = currentMenu; if (gt != -1)
PLAY_LevelSelectDef.prevMenu = &PLAY_CupSelectDef; {
M_SetupNextMenu(&PLAY_CupSelectDef, false); PLAY_CupSelectDef.prevMenu = currentMenu;
PLAY_LevelSelectDef.prevMenu = &PLAY_CupSelectDef;
M_SetupNextMenu(&PLAY_CupSelectDef, false);
}
return true; return true;
} }
@ -344,8 +360,11 @@ boolean M_LevelListFromGametype(INT16 gt)
M_LevelSelectScrollDest(); M_LevelSelectScrollDest();
levellist.y = levellist.dest; levellist.y = levellist.dest;
PLAY_LevelSelectDef.prevMenu = currentMenu; if (gt != -1)
M_SetupNextMenu(&PLAY_LevelSelectDef, false); {
PLAY_LevelSelectDef.prevMenu = currentMenu;
M_SetupNextMenu(&PLAY_LevelSelectDef, false);
}
return true; return true;
} }
@ -478,6 +497,15 @@ void M_LevelSelected(INT16 add)
CV_StealthSet(&cv_kartspeed, (cv_dummykartspeed.value == KARTSPEED_NORMAL) ? "Auto" : cv_dummykartspeed.string); CV_StealthSet(&cv_kartspeed, (cv_dummykartspeed.value == KARTSPEED_NORMAL) ? "Auto" : cv_dummykartspeed.string);
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 (levellist.netgame == true)
{
restoreMenu = &PLAY_MP_OptSelectDef;
}
else
{
restoreMenu = &PLAY_LevelSelectDef;
}
} }
else else
{ {

View file

@ -54,17 +54,9 @@ void M_EndModeAttackRun(void)
if (gamestate == GS_LEVEL || gamestate == GS_INTERMISSION) if (gamestate == GS_LEVEL || gamestate == GS_INTERMISSION)
Command_ExitGame_f(); Command_ExitGame_f();
M_StartControlPanel();
M_PrepareTimeAttack(0);
currentMenu = &PLAY_TimeAttackDef;
itemOn = currentMenu->lastOn;
G_SetGamestate(GS_MENU);
S_ChangeMusicInternal("menu", true);
modeattacking = ATTACKING_NONE; modeattacking = ATTACKING_NONE;
M_StartControlPanel();
} }
// Replay Playback Menu // Replay Playback Menu
@ -250,7 +242,7 @@ void M_PlaybackQuit(INT32 choice)
G_StopDemo(); G_StopDemo();
if (demo.inreplayhut) if (demo.inreplayhut)
M_ReplayHut(choice); M_StartControlPanel();
else if (modeattacking) else if (modeattacking)
M_EndModeAttackRun(); M_EndModeAttackRun();
else else