diff --git a/src/g_game.c b/src/g_game.c index 08ae1d90c..fb49b598c 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3404,23 +3404,27 @@ INT16 G_GetFirstMapOfGametype(UINT8 pgametype) { UINT8 i = 0; INT16 mapnum = NEXTMAP_INVALID; - UINT32 tol = G_TOLFlag(pgametype); + levelsearch_t templevelsearch; - levellist.cupmode = (!(gametypedefaultrules[pgametype] & GTR_NOCUPSELECT)); - levellist.timeattack = false; + templevelsearch.cup = NULL; + templevelsearch.typeoflevel = G_TOLFlag(pgametype); + templevelsearch.cupmode = (!(gametypedefaultrules[pgametype] & GTR_NOCUPSELECT)); + templevelsearch.timeattack = false; + templevelsearch.checklocked = true; - if (levellist.cupmode) + if (templevelsearch.cupmode) { - cupheader_t *cup = kartcupheaders; - while (cup && mapnum >= nummapheaders) + templevelsearch.cup = kartcupheaders; + while (templevelsearch.cup && mapnum >= nummapheaders) { - mapnum = M_GetFirstLevelInList(&i, tol, cup); + mapnum = M_GetFirstLevelInList(&i, &templevelsearch); i = 0; + templevelsearch.cup = templevelsearch.cup->next; } } else { - mapnum = M_GetFirstLevelInList(&i, tol, NULL); + mapnum = M_GetFirstLevelInList(&i, &templevelsearch); } return mapnum; diff --git a/src/k_menu.h b/src/k_menu.h index 6578595e8..eb57069b7 100644 --- a/src/k_menu.h +++ b/src/k_menu.h @@ -695,23 +695,28 @@ extern struct cupgrid_s { boolean netgame; // Start the game in an actual server } cupgrid; +typedef struct levelsearch_s { + UINT32 typeoflevel; + cupheader_t *cup; + boolean timeattack; + boolean cupmode; + boolean checklocked; +} levelsearch_t; + extern struct levellist_s { SINT8 cursor; UINT16 y; UINT16 dest; - cupheader_t *selectedcup; INT16 choosemap; UINT8 newgametype; - UINT32 typeoflevel; - boolean cupmode; - boolean timeattack; // Setup time attack menu after picking + levelsearch_t levelsearch; boolean netgame; // Start the game in an actual server } levellist; -boolean M_CanShowLevelInList(INT16 mapnum, UINT32 tol, cupheader_t *cup); -UINT16 M_CountLevelsToShowInList(UINT32 tol, cupheader_t *cup); -UINT16 M_GetFirstLevelInList(UINT8 *i, UINT32 tol, cupheader_t *cup); -UINT16 M_GetNextLevelInList(UINT16 map, UINT8 *i, UINT32 tol, cupheader_t *cup); +boolean M_CanShowLevelInList(INT16 mapnum, levelsearch_t *levelsearch); +UINT16 M_CountLevelsToShowInList(levelsearch_t *levelsearch); +UINT16 M_GetFirstLevelInList(UINT8 *i, levelsearch_t *levelsearch); +UINT16 M_GetNextLevelInList(UINT16 mapnum, UINT8 *i, levelsearch_t *levelsearch); void M_LevelSelectInit(INT32 choice); void M_CupSelectHandler(INT32 choice); diff --git a/src/k_menudraw.c b/src/k_menudraw.c index 8bc19a3a4..9071907bc 100644 --- a/src/k_menudraw.c +++ b/src/k_menudraw.c @@ -1922,24 +1922,24 @@ void M_DrawRaceDifficulty(void) // LEVEL SELECT -static void M_DrawCupPreview(INT16 y, cupheader_t *cup) +static void M_DrawCupPreview(INT16 y, levelsearch_t *levelsearch) { UINT8 i = 0; - INT16 maxlevels = M_CountLevelsToShowInList(levellist.typeoflevel, cup); + INT16 maxlevels = M_CountLevelsToShowInList(levelsearch); INT16 x = -(cupgrid.previewanim % 82); INT16 add; - INT16 map, start = M_GetFirstLevelInList(&i, levellist.typeoflevel, cup); + INT16 map, start = M_GetFirstLevelInList(&i, levelsearch); UINT8 starti = i; V_DrawFill(0, y, BASEVIDWIDTH, 54, 31); - if (cup && !M_CupLocked(cup)) + if (levelsearch->cup && !M_CupLocked(levelsearch->cup)) { add = (cupgrid.previewanim / 82) % maxlevels; map = start; while (add > 0) { - map = M_GetNextLevelInList(map, &i, levellist.typeoflevel, cup); + map = M_GetNextLevelInList(map, &i, levelsearch); if (map >= nummapheaders) { @@ -1965,7 +1965,7 @@ static void M_DrawCupPreview(INT16 y, cupheader_t *cup) x += 82; - map = M_GetNextLevelInList(map, &i, levellist.typeoflevel, cup); + map = M_GetNextLevelInList(map, &i, levelsearch); } } else @@ -2009,7 +2009,8 @@ static void M_DrawCupTitle(INT16 y, cupheader_t *cup) void M_DrawCupSelect(void) { UINT8 i, j; - cupheader_t *cup = cupgrid.builtgrid[CUPMENU_CURSORID]; + levelsearch_t templevelsearch = levellist.levelsearch; // full copy + templevelsearch.cup = cupgrid.builtgrid[CUPMENU_CURSORID]; for (i = 0; i < CUPMENU_COLUMNS; i++) { @@ -2057,8 +2058,8 @@ void M_DrawCupSelect(void) 0, W_CachePatchName("CUPCURS", PU_CACHE) ); - M_DrawCupPreview(146 + (24*menutransition.tics), cup); - M_DrawCupTitle(120 - (24*menutransition.tics), cup); + M_DrawCupPreview(146 + (24*menutransition.tics), &templevelsearch); + M_DrawCupTitle(120 - (24*menutransition.tics), templevelsearch.cup); } static void M_DrawHighLowLevelTitle(INT16 x, INT16 y, INT16 map) @@ -2190,7 +2191,7 @@ void M_DrawLevelSelect(void) { INT16 i = 0; UINT8 j = 0; - INT16 map = M_GetFirstLevelInList(&j, levellist.typeoflevel, levellist.selectedcup); + INT16 map = M_GetFirstLevelInList(&j, &levellist.levelsearch); INT16 t = (64*menutransition.tics), tay = 0; INT16 y = 80 - (12 * levellist.y); boolean tatransition = ((menutransition.startmenu == &PLAY_TimeAttackDef || menutransition.endmenu == &PLAY_TimeAttackDef) && menutransition.tics); @@ -2221,10 +2222,10 @@ void M_DrawLevelSelect(void) y += 72; i++; - map = M_GetNextLevelInList(map, &j, levellist.typeoflevel, levellist.selectedcup); + map = M_GetNextLevelInList(map, &j, &levellist.levelsearch); } - M_DrawCupTitle(tay, levellist.selectedcup); + M_DrawCupTitle(tay, levellist.levelsearch.cup); } void M_DrawTimeAttack(void) @@ -4638,27 +4639,16 @@ static void M_DrawChallengePreview(INT32 x, INT32 y) } case SECRET_CUP: { - cupheader_t *cup = M_UnlockableCup(ref); -#if 0 // First attempt - UINT8 i = cup->numlevels; + levelsearch_t templevelsearch; - x = 4; - y = (BASEVIDHEIGHT-4) - 38; + templevelsearch.cup = M_UnlockableCup(ref); + templevelsearch.typeoflevel = G_TOLFlag(GT_RACE)|G_TOLFlag(GT_BATTLE); + templevelsearch.cupmode = true; + templevelsearch.timeattack = false; + templevelsearch.checklocked = false; + + M_DrawCupPreview(146, &templevelsearch); - while (i > 0) - { - i--; - K_DrawMapThumbnail( - (x+(i*2))<cachedlevels[i], - NULL); - } -#else - M_DrawCupPreview(146, cup); -#endif break; } case SECRET_MAP: diff --git a/src/k_menufunc.c b/src/k_menufunc.c index a0a5ebd76..71a447a9e 100644 --- a/src/k_menufunc.c +++ b/src/k_menufunc.c @@ -3386,8 +3386,11 @@ void M_SetupDifficultySelect(INT32 choice) // // Determines whether to show a given map in the various level-select lists. // -boolean M_CanShowLevelInList(INT16 mapnum, UINT32 tol, cupheader_t *cup) +boolean M_CanShowLevelInList(INT16 mapnum, levelsearch_t *levelsearch) { + if (!levelsearch) + return false; + if (mapnum >= nummapheaders) return false; @@ -3403,11 +3406,11 @@ boolean M_CanShowLevelInList(INT16 mapnum, UINT32 tol, cupheader_t *cup) if (mapheaderinfo[mapnum]->lumpnum == LUMPERROR) return false; - if (M_MapLocked(mapnum+1)) + if (levelsearch->checklocked && M_MapLocked(mapnum+1)) return false; // not unlocked // Check for TOL - if (!(mapheaderinfo[mapnum]->typeoflevel & tol)) + if (!(mapheaderinfo[mapnum]->typeoflevel & levelsearch->typeoflevel)) return false; // Should the map be hidden? @@ -3415,26 +3418,31 @@ boolean M_CanShowLevelInList(INT16 mapnum, UINT32 tol, cupheader_t *cup) return false; // I don't know why, but some may have exceptions. - if (levellist.timeattack && (mapheaderinfo[mapnum]->menuflags & LF2_NOTIMEATTACK)) + if (levelsearch->timeattack && (mapheaderinfo[mapnum]->menuflags & LF2_NOTIMEATTACK)) return false; // Don't permit cup when no cup requested (also no dupes in time attack) - if (levellist.cupmode && (levellist.timeattack || !cup) && mapheaderinfo[mapnum]->cup != cup) + if (levelsearch->cupmode + && (levelsearch->timeattack || !levelsearch->cup) + && mapheaderinfo[mapnum]->cup != levelsearch->cup) return false; // Survived our checks. return true; } -UINT16 M_CountLevelsToShowInList(UINT32 tol, cupheader_t *cup) +UINT16 M_CountLevelsToShowInList(levelsearch_t *levelsearch) { INT16 i, count = 0; - if (cup) + if (!levelsearch) + return false; + + if (levelsearch->cup) { for (i = 0; i < CUPCACHE_MAX; i++) { - if (!M_CanShowLevelInList(cup->cachedlevels[i], tol, cup)) + if (!M_CanShowLevelInList(levelsearch->cup->cachedlevels[i], levelsearch)) continue; count++; } @@ -3443,60 +3451,66 @@ UINT16 M_CountLevelsToShowInList(UINT32 tol, cupheader_t *cup) } for (i = 0; i < nummapheaders; i++) - if (M_CanShowLevelInList(i, tol, NULL)) + if (M_CanShowLevelInList(i, levelsearch)) count++; return count; } -UINT16 M_GetFirstLevelInList(UINT8 *i, UINT32 tol, cupheader_t *cup) +UINT16 M_GetFirstLevelInList(UINT8 *i, levelsearch_t *levelsearch) { INT16 mapnum = NEXTMAP_INVALID; - if (cup) + if (!levelsearch) + return false; + + if (levelsearch->cup) { *i = 0; mapnum = NEXTMAP_INVALID; for (; *i < CUPCACHE_MAX; (*i)++) { - if (!M_CanShowLevelInList(cup->cachedlevels[*i], tol, cup)) + if (!M_CanShowLevelInList(levelsearch->cup->cachedlevels[*i], levelsearch)) continue; - mapnum = cup->cachedlevels[*i]; + mapnum = levelsearch->cup->cachedlevels[*i]; break; } } else { for (mapnum = 0; mapnum < nummapheaders; mapnum++) - if (M_CanShowLevelInList(mapnum, tol, NULL)) + if (M_CanShowLevelInList(mapnum, levelsearch)) break; } return mapnum; } -UINT16 M_GetNextLevelInList(UINT16 map, UINT8 *i, UINT32 tol, cupheader_t *cup) +UINT16 M_GetNextLevelInList(UINT16 mapnum, UINT8 *i, levelsearch_t *levelsearch) { - if (cup) + if (!levelsearch) + return false; + + if (levelsearch->cup) { - map = NEXTMAP_INVALID; + mapnum = NEXTMAP_INVALID; (*i)++; for (; *i < CUPCACHE_MAX; (*i)++) { - if (!M_CanShowLevelInList(cup->cachedlevels[*i], tol, cup)) + if (!M_CanShowLevelInList(levelsearch->cup->cachedlevels[*i], levelsearch)) continue; - map = cup->cachedlevels[*i]; + mapnum = levelsearch->cup->cachedlevels[*i]; break; } } else { - map++; - while (!M_CanShowLevelInList(map, tol, NULL) && map < nummapheaders) - map++; + mapnum++; + while (!M_CanShowLevelInList(mapnum, levelsearch) && mapnum < nummapheaders) + mapnum++; } - return map; + return mapnum; } struct cupgrid_s cupgrid; @@ -3504,7 +3518,7 @@ struct levellist_s levellist; static void M_LevelSelectScrollDest(void) { - UINT16 m = M_CountLevelsToShowInList(levellist.typeoflevel, levellist.selectedcup)-1; + UINT16 m = M_CountLevelsToShowInList(&levellist.levelsearch)-1; levellist.dest = (6*levellist.cursor); @@ -3522,9 +3536,9 @@ static void M_LevelListFromGametype(INT16 gt) if (first || gt != levellist.newgametype) { levellist.newgametype = gt; - levellist.typeoflevel = G_TOLFlag(gt); - levellist.cupmode = (!(gametypedefaultrules[gt] & GTR_NOCUPSELECT)); - levellist.selectedcup = NULL; + levellist.levelsearch.typeoflevel = G_TOLFlag(gt); + levellist.levelsearch.cupmode = (!(gametypedefaultrules[gt] & GTR_NOCUPSELECT)); + levellist.levelsearch.cup = NULL; first = false; } @@ -3533,14 +3547,17 @@ static void M_LevelListFromGametype(INT16 gt) // Obviously go to Cup Select in gametypes that have cups. // Use a really long level select in gametypes that don't use cups. - if (levellist.cupmode) + if (levellist.levelsearch.cupmode) { - cupheader_t *cup = kartcupheaders; + levelsearch_t templevelsearch = levellist.levelsearch; // full copy size_t currentid = 0, highestunlockedid = 0; const size_t unitlen = sizeof(cupheader_t*) * (CUPMENU_COLUMNS * CUPMENU_ROWS); + templevelsearch.cup = kartcupheaders; + templevelsearch.checklocked = false; + // Make sure there's valid cups before going to this menu. - if (cup == NULL) + if (templevelsearch.cup == NULL) I_Error("Can you really call this a racing game, I didn't recieve any Cups on my pillow or anything"); if (!cupgrid.builtgrid) @@ -3558,12 +3575,12 @@ static void M_LevelListFromGametype(INT16 gt) } memset(cupgrid.builtgrid, 0, cupgrid.cappages * unitlen); - while (cup) + while (templevelsearch.cup) { - if (!M_CountLevelsToShowInList(levellist.typeoflevel, cup)) + if (!M_CountLevelsToShowInList(&templevelsearch)) { // No valid maps, skip. - cup = cup->next; + templevelsearch.cup = templevelsearch.cup->next; continue; } @@ -3584,21 +3601,21 @@ static void M_LevelListFromGametype(INT16 gt) cupgrid.cappages *= 2; } - cupgrid.builtgrid[currentid] = cup; + cupgrid.builtgrid[currentid] = templevelsearch.cup; - if (!M_CupLocked(cup)) + if (!M_CupLocked(templevelsearch.cup)) { highestunlockedid = currentid; - if (Playing() && mapheaderinfo[gamemap-1] && mapheaderinfo[gamemap-1]->cup == cup) + if (Playing() && mapheaderinfo[gamemap-1] && mapheaderinfo[gamemap-1]->cup == templevelsearch.cup) { - cupgrid.x = cup->id % CUPMENU_COLUMNS; - cupgrid.y = (cup->id / CUPMENU_COLUMNS) % CUPMENU_ROWS; - cupgrid.pageno = cup->id / (CUPMENU_COLUMNS * CUPMENU_ROWS); + cupgrid.x = currentid % CUPMENU_COLUMNS; + cupgrid.y = (currentid / CUPMENU_COLUMNS) % CUPMENU_ROWS; + cupgrid.pageno = currentid / (CUPMENU_COLUMNS * CUPMENU_ROWS); } } currentid++; - cup = cup->next; + templevelsearch.cup = templevelsearch.cup->next; } cupgrid.numpages = (highestunlockedid / (CUPMENU_COLUMNS * CUPMENU_ROWS)) + 1; @@ -3614,10 +3631,10 @@ static void M_LevelListFromGametype(INT16 gt) } // Reset position properly if you go back & forth between gametypes - if (levellist.selectedcup) + if (levellist.levelsearch.cup) { levellist.cursor = 0; - levellist.selectedcup = NULL; + levellist.levelsearch.cup = NULL; } M_LevelSelectScrollDest(); @@ -3636,22 +3653,24 @@ void M_LevelSelectInit(INT32 choice) { (void)choice; - levellist.netgame = false; // Make sure this is reset as we'll only be using this function for offline games! - cupgrid.netgame = false; // Ditto + // Make sure this is reset as we'll only be using this function for offline games! + cupgrid.netgame = false; + levellist.netgame = false; + levellist.levelsearch.checklocked = true; switch (currentMenu->menuitems[itemOn].mvar1) { case 0: cupgrid.grandprix = false; - levellist.timeattack = false; + levellist.levelsearch.timeattack = false; break; case 1: cupgrid.grandprix = false; - levellist.timeattack = true; + levellist.levelsearch.timeattack = true; break; case 2: cupgrid.grandprix = true; - levellist.timeattack = false; + levellist.levelsearch.timeattack = false; break; default: CONS_Alert(CONS_WARNING, "Bad level select init\n"); @@ -3787,10 +3806,10 @@ void M_CupSelectHandler(INT32 choice) else { // Keep cursor position if you select the same cup again, reset if it's a different cup - if (levellist.selectedcup != newcup) + if (levellist.levelsearch.cup != newcup) { levellist.cursor = 0; - levellist.selectedcup = newcup; + levellist.levelsearch.cup = newcup; } M_LevelSelectScrollDest(); @@ -3818,7 +3837,7 @@ void M_CupSelectTick(void) void M_LevelSelectHandler(INT32 choice) { - INT16 maxlevels = M_CountLevelsToShowInList(levellist.typeoflevel, levellist.selectedcup); + INT16 maxlevels = M_CountLevelsToShowInList(&levellist.levelsearch); const UINT8 pid = 0; (void)choice; @@ -3850,14 +3869,14 @@ void M_LevelSelectHandler(INT32 choice) if (M_MenuConfirmPressed(pid) /*|| M_MenuButtonPressed(pid, MBT_START)*/) { UINT8 i = 0; - INT16 map = M_GetFirstLevelInList(&i, levellist.typeoflevel, levellist.selectedcup); + INT16 map = M_GetFirstLevelInList(&i, &levellist.levelsearch); INT16 add = levellist.cursor; M_SetMenuDelay(pid); while (add > 0) { - map = M_GetNextLevelInList(map, &i, levellist.typeoflevel, levellist.selectedcup); + map = M_GetNextLevelInList(map, &i, &levellist.levelsearch); if (map >= nummapheaders) { @@ -3875,7 +3894,7 @@ void M_LevelSelectHandler(INT32 choice) levellist.choosemap = map; - if (levellist.timeattack) + if (levellist.levelsearch.timeattack) { M_SetupNextMenu(&PLAY_TimeAttackDef, false); S_StartSound(NULL, sfx_s3k63); @@ -4106,10 +4125,13 @@ void M_MPSetupNetgameMapSelect(INT32 choice) INT16 gt = GT_RACE; (void)choice; - levellist.netgame = true; // Yep, we'll be starting a netgame. - cupgrid.netgame = true; // Ditto - levellist.timeattack = false; // Make sure we reset those - cupgrid.grandprix = false; // Ditto + // Yep, we'll be starting a netgame. + levellist.netgame = true; + cupgrid.netgame = true; + // Make sure we reset those + levellist.levelsearch.timeattack = false; + levellist.levelsearch.checklocked = true; + cupgrid.grandprix = false; // In case we ever want to add new gamemodes there somehow, have at it! switch (cv_dummygametype.value)