diff --git a/src/d_main.cpp b/src/d_main.cpp index d1814813b..18b2e3709 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -1609,6 +1609,7 @@ void D_SRB2Main(void) // P_InitMapData(); basenummapheaders = nummapheaders; + basenumkartcupheaders = numkartcupheaders; CON_SetLoadingProgress(LOADED_IWAD); diff --git a/src/deh_soc.c b/src/deh_soc.c index 86b36931b..974532c24 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -2464,6 +2464,20 @@ void readunlockable(MYFILE *f, INT32 num) Z_Free(s); } +// Todo: Own func +static cupheader_t *SOChelper_cupbyname(char *name) +{ + cupheader_t *cup = kartcupheaders; + UINT32 hash = quickncasehash(name, MAXCUPNAME); + while (cup) + { + if (hash == cup->namehash && !strcmp(cup->name, name)) + return cup; + cup = cup->next; + } + return NULL; +} + // This is a home-grown strtok(" ") equivalent so we can isolate the first chunk without destroying the rest of the line. static void conditiongetparam(char **params, UINT8 paramid, char **spos) { @@ -2690,6 +2704,63 @@ static void readcondition(UINT16 set, UINT32 id, char *word2) re = -1; x1 = atoi(params[2]); } + else if (fastcmp(params[0], "ALLCUPRECORDS")) + { + ty = UC_ALLCUPRECORDS; + + re = -1; + x1 = 0; + x2 = KARTSPEED_EASY; + + if (params[1]) + { + if (!fastcmp(params[1], "ALL")) + { + cupheader_t *cup = SOChelper_cupbyname(params[1]); + + if (!cup) + { + deh_warning("Invalid cup %s for condition ID %d", params[1], id+1); + return; + } + + re = cup->id; + } + + if (params[2]) + { + if (!fastcmp(params[1], "ANY")) + { + if ((offset=0) || fastcmp(params[2], "GOLD") + || (++offset && fastcmp(params[2], "SILVER")) + || (++offset && fastcmp(params[2], "BRONZE"))) + { + x1 = offset + 1; + } + else + { + deh_warning("placement requirement \"%s\" invalid for condition ID %d", params[2], id+1); + return; + } + } + + if (params[3]) + { + if (fastcmp(params[3], "NORMAL")) + x2 = KARTSPEED_NORMAL; + else if (fastcmp(params[3], "HARD")) + x2 = KARTSPEED_HARD; + else if (fastcmp(params[3], "MASTER")) + x2 = KARTGP_MASTER; + else + { + deh_warning("gamespeed requirement \"%s\" invalid for condition ID %d", params[3], id+1); + return; + } + } + } + } + } else if ((offset=0) || fastcmp(params[0], "ALLCHAOS") || (++offset && fastcmp(params[0], "ALLSUPER")) || (++offset && fastcmp(params[0], "ALLEMERALDS"))) @@ -2907,14 +2978,7 @@ static void readcondition(UINT16 set, UINT32 id, char *word2) re = -1; if (!fastcmp(params[1], "ANY")) { - cupheader_t *cup = kartcupheaders; - UINT32 hash = quickncasehash(params[1], MAXCUPNAME); - while (cup) - { - if (hash == cup->namehash && !strcmp(cup->name, params[1])) - break; - cup = cup->next; - } + cupheader_t *cup = SOChelper_cupbyname(params[1]); if (!cup) { diff --git a/src/dehacked.c b/src/dehacked.c index bc3e3ae0a..0bb710a18 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -489,13 +489,18 @@ static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile) if (!cup) { cup = Z_Calloc(sizeof (cupheader_t), PU_STATIC, NULL); - cup->id = numkartcupheaders; - cup->monitor = 1; - cup->cache_cuplock = MAXUNLOCKABLES; + deh_strlcpy(cup->name, word2, sizeof(cup->name), va("Cup header %s: name", word2)); cup->namehash = hash; + // Handle some variable init. + cup->monitor = 1; + cup->id = numkartcupheaders; + cup->cache_cuplock = MAXUNLOCKABLES; + for (i = 0; i < CUPCACHE_MAX; i++) + cup->cachedlevels[i] = NEXTMAP_INVALID; + char *start = strchr(word2, '_'); if (start) start++; @@ -608,6 +613,7 @@ static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile) if (gamedataadded) { basenummapheaders = nummapheaders; + basenumkartcupheaders = numkartcupheaders; G_LoadGameData(); } diff --git a/src/doomstat.h b/src/doomstat.h index 4f3a5ac58..300558131 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -57,6 +57,9 @@ extern UINT32 maptol; extern INT32 cursaveslot; extern UINT8 gamecomplete; +#define CUPMENU_COLUMNS 7 +#define CUPMENU_ROWS 2 + // Extra abilities/settings for skins (combinable stuff) typedef enum { @@ -424,7 +427,7 @@ struct cupheader_t }; extern cupheader_t *kartcupheaders; // Start of cup linked list -extern UINT16 numkartcupheaders; +extern UINT16 numkartcupheaders, basenumkartcupheaders; struct unloaded_cupheader_t { diff --git a/src/g_game.c b/src/g_game.c index 2e1222f17..b5b7df905 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -204,6 +204,7 @@ unloaded_mapheader_t *unloadedmapheaders = NULL; // Kart cup definitions cupheader_t *kartcupheaders = NULL; UINT16 numkartcupheaders = 0; +UINT16 basenumkartcupheaders = 0; unloaded_cupheader_t *unloadedcupheaders = NULL; diff --git a/src/k_menu.h b/src/k_menu.h index e4700187a..cbc3c899a 100644 --- a/src/k_menu.h +++ b/src/k_menu.h @@ -752,8 +752,6 @@ void M_SetupPlayMenu(INT32 choice); void M_SetupGametypeMenu(INT32 choice); void M_SetupRaceMenu(INT32 choice); -#define CUPMENU_COLUMNS 7 -#define CUPMENU_ROWS 2 #define CUPMENU_CURSORID (cupgrid.x + (cupgrid.y * CUPMENU_COLUMNS) + (cupgrid.pageno * (CUPMENU_COLUMNS * CUPMENU_ROWS))) extern struct cupgrid_s { @@ -764,6 +762,7 @@ extern struct cupgrid_s { size_t cappages; tic_t previewanim; boolean grandprix; // Setup grand prix server after picking + boolean cache_secondrowlocked; } cupgrid; typedef struct levelsearch_s { @@ -1274,6 +1273,8 @@ extern struct challengesmenu_s { UINT16 unlockcount[CMC_MAX]; UINT8 fade; + + boolean cache_secondrowlocked; } challengesmenu; menu_t *M_InterruptMenuWithChallenges(menu_t *desiredmenu); diff --git a/src/k_menudraw.c b/src/k_menudraw.c index e73087c6f..9a5a6b035 100644 --- a/src/k_menudraw.c +++ b/src/k_menudraw.c @@ -2712,7 +2712,9 @@ void M_DrawCupSelect(void) for (i = 0; i < CUPMENU_COLUMNS; i++) { - for (j = 0; j < CUPMENU_ROWS; j++) + x = 14 + (i*42); + + for (j = 0; j < (cupgrid.cache_secondrowlocked ? 1 : CUPMENU_ROWS); j++) { size_t id = (i + (j * CUPMENU_COLUMNS)) + (cupgrid.pageno * (CUPMENU_COLUMNS * CUPMENU_ROWS)); @@ -2721,8 +2723,9 @@ void M_DrawCupSelect(void) templevelsearch.cup = cupgrid.builtgrid[id]; - x = 14 + (i*42); y = 20 + (j*44) - (30*menutransition.tics); + if (cupgrid.cache_secondrowlocked == true) + y += 28; const boolean isGP = (cupgrid.grandprix && (cv_dummygpdifficulty.value >= 0 && cv_dummygpdifficulty.value < KARTGP_MAX)); if (isGP) @@ -2745,11 +2748,23 @@ void M_DrawCupSelect(void) V_DrawScaledPatch(x + 32, y + 32, 0, W_CachePatchName("CUPBKUP1", PU_CACHE)); } + // used to be 8 + (j*100) - (30*menutransition.tics) + // but one-row mode means y has to be changed + // this is the difference between y and that + if (j == 0) + { + y -= 12; // (8) - (20) + } + else + { + y += 44; //(8 + 100) - (20 + 44) + } + if (windata && windata->best_placement != 0) { M_DrawCupWinData( x, - 8 + (j*100) - (30*menutransition.tics), + y, templevelsearch.cup, cv_dummygpdifficulty.value, (cupgrid.previewanim & 1), @@ -2761,6 +2776,8 @@ void M_DrawCupSelect(void) x = 14 + (cupgrid.x*42); y = 20 + (cupgrid.y*44) - (30*menutransition.tics); + if (cupgrid.cache_secondrowlocked == true) + y += 28; V_DrawScaledPatch(x - 4, y - 1, 0, W_CachePatchName("CUPCURS", PU_CACHE)); @@ -5670,40 +5687,56 @@ static void M_DrawChallengePreview(INT32 x, INT32 y) M_DrawCupPreview(146, &templevelsearch); - maxid = id = (temp->id % 14); + maxid = id = (temp->id % (CUPMENU_COLUMNS * CUPMENU_ROWS)); offset = (temp->id - id) * 2; - while (temp && maxid < 14) + while (temp && maxid < (CUPMENU_COLUMNS * CUPMENU_ROWS)) { maxid++; temp = temp->next; } - V_DrawFadeFill(4, (BASEVIDHEIGHT-(4+16)), 28 + offset, 16, 0, 31, challengetransparentstrength); + y = (BASEVIDHEIGHT-(4+16)); + if (challengesmenu.cache_secondrowlocked == true) + y += 8; + + V_DrawFadeFill( + 4, + y, + 28 + offset, + (challengesmenu.cache_secondrowlocked ? 8 : 16), + 0, + 31, + challengetransparentstrength + ); for (i = 0; i < offset; i += 4) { - V_DrawFill(4+1 + i, (BASEVIDHEIGHT-(4+16))+3, 2, 2, 15); - V_DrawFill(4+1 + i, (BASEVIDHEIGHT-(4+16))+8+3, 2, 2, 15); + V_DrawFill(4+1 + i, y+3, 2, 2, 15); + + if (challengesmenu.cache_secondrowlocked == false) + V_DrawFill(4+1 + i, y+8+3, 2, 2, 15); } - for (i = 0; i < 7; i++) + for (i = 0; i < CUPMENU_COLUMNS; i++) { if (templevelsearch.cup && id == i) { - V_DrawFill(offset + 4 + (i*4), (BASEVIDHEIGHT-(4+16)), 4, 8, 0); + V_DrawFill(offset + 4 + (i*4), y, 4, 8, 0); } else if (i < maxid) { - V_DrawFill(offset + 4+1 + (i*4), (BASEVIDHEIGHT-(4+16))+3, 2, 2, 0); + V_DrawFill(offset + 4+1 + (i*4), y+3, 2, 2, 0); } - if (templevelsearch.cup && (templevelsearch.cup->id % 14) == i+7) + if (templevelsearch.cup && id == i+CUPMENU_COLUMNS) { - V_DrawFill(offset + 4 + (i*4), (BASEVIDHEIGHT-(4+16))+8, 4, 8, 0); + V_DrawFill(offset + 4 + (i*4), y+8, 4, 8, 0); } - else if (i+7 < maxid) + else if (challengesmenu.cache_secondrowlocked == true) + ; + else if (i+CUPMENU_COLUMNS < maxid) { - V_DrawFill(offset + 4+1 + (i*4), (BASEVIDHEIGHT-(4+16))+8+3, 2, 2, 0); + V_DrawFill(offset + 4+1 + (i*4), y+8+3, 2, 2, 0); } } diff --git a/src/m_cond.c b/src/m_cond.c index f1ae5068e..4928f0407 100644 --- a/src/m_cond.c +++ b/src/m_cond.c @@ -1388,6 +1388,39 @@ boolean M_CheckCondition(condition_t *cn, player_t *player) return (skins[cn->requirement].records.wins >= (UINT32)cn->extrainfo1); + case UC_ALLCUPRECORDS: + { + cupheader_t *cup; + UINT8 difficulty = cn->extrainfo2; + + if (gamestate == GS_LEVEL) + return false; // this one could be laggy with many cups available + + if (difficulty > KARTGP_MASTER) + difficulty = KARTGP_MASTER; + + for (cup = kartcupheaders; cup; cup = cup->next) + { + // Ok, achieved up to the desired cup. + if (cn->requirement == cup->id) + return true; + + cupwindata_t *windata = &cup->windata[cn->extrainfo2]; + + // Did you actually get it? + if (windata->best_placement == 0) + return false; + + // Sufficient placement? + if (cn->extrainfo1 && windata->best_placement > cn->extrainfo1) + return false; + } + + // If we ended up here, check we were looking for all cups achieved. + return (cn->requirement == -1); + } + + case UC_ALLCHAOS: case UC_ALLSUPER: case UC_ALLEMERALDS: @@ -2120,6 +2153,50 @@ static const char *M_GetConditionString(condition_t *cn) work); } + case UC_ALLCUPRECORDS: + { + const char *completetype = "Complete", *orbetter = "", *specialtext = NULL, *speedtext = ""; + + if (cn->extrainfo1 == 0) + ; + else if (cn->extrainfo1 == 1) + completetype = "get Gold over"; + else + { + if (cn->extrainfo1 == 2) + completetype = "get Silver"; + else if (cn->extrainfo1 == 3) + completetype = "get Bronze"; + orbetter = " or better over"; + } + + if (cn->extrainfo2 == KARTSPEED_NORMAL) + { + speedtext = " on Normal"; + } + else if (cn->extrainfo2 == KARTSPEED_HARD) + { + speedtext = " on Hard"; + } + else if (cn->extrainfo2 == KARTGP_MASTER) + { + if (M_SecretUnlocked(SECRET_MASTERMODE, true)) + speedtext = " on Master"; + else + speedtext = " on ???"; + } + + if (cn->requirement == -1) + specialtext = "every Cup"; + else if (M_CupSecondRowLocked() == true && cn->requirement+1 >= CUPMENU_COLUMNS) + specialtext = "the first ??? Cups"; + + if (specialtext != NULL) + return va("GRAND PRIX: %s%s %s%s", completetype, orbetter, specialtext, speedtext); + + return va("GRAND PRIX: %s%s the first %d Cups%s", completetype, orbetter, cn->requirement, speedtext); + } + case UC_ALLCHAOS: case UC_ALLSUPER: case UC_ALLEMERALDS: @@ -2138,17 +2215,17 @@ static const char *M_GetConditionString(condition_t *cn) /*if (cn->requirement == KARTSPEED_NORMAL) -- Emeralds can not be collected on Easy { - speedtext = " on Normal difficulty"; + speedtext = " on Normal"; } else*/ if (cn->requirement == KARTSPEED_HARD) { - speedtext = " on Hard difficulty"; + speedtext = " on Hard"; } else if (cn->requirement == KARTGP_MASTER) { if (M_SecretUnlocked(SECRET_MASTERMODE, true)) - speedtext = " on Master difficulty"; + speedtext = " on Master"; else speedtext = " on ???"; } @@ -2401,16 +2478,16 @@ static const char *M_GetConditionString(condition_t *cn) if (cn->requirement == KARTSPEED_NORMAL) { - speedtext = "on Normal difficulty"; + speedtext = "on Normal"; } else if (cn->requirement == KARTSPEED_HARD) { - speedtext = "on Hard difficulty"; + speedtext = "on Hard"; } else if (cn->requirement == KARTGP_MASTER) { if (M_SecretUnlocked(SECRET_MASTERMODE, true)) - speedtext = "on Master difficulty"; + speedtext = "on Master"; else speedtext = "on ???"; } @@ -3190,6 +3267,33 @@ boolean M_CupLocked(cupheader_t *cup) return false; } +boolean M_CupSecondRowLocked(void) +{ + // The following was pre-optimised for cached behaviour. + // It would need a refactor if the cache system were to + // change, maybe to iterate over unlockable_t instead. + cupheader_t *cup; + for (cup = kartcupheaders; cup; cup = cup->next) + { + // Only important for the second row. + if ((cup->id % (CUPMENU_COLUMNS * CUPMENU_ROWS)) < CUPMENU_COLUMNS) + continue; + + // Only important for ones that can be locked. + if (cup->cache_cuplock == MAXUNLOCKABLES) + continue; + + // If it's NOT unlocked, can't be used as proof of unlock. + if (!M_CheckNetUnlockByID(cup->cache_cuplock)) + continue; + + // Okay, at least one cup on the second row is unlocked! + return false; + } + + return true; +} + boolean M_MapLocked(UINT16 mapnum) { // Don't lock maps in dedicated servers. diff --git a/src/m_cond.h b/src/m_cond.h index 2b20bb769..e79a28676 100644 --- a/src/m_cond.h +++ b/src/m_cond.h @@ -47,6 +47,8 @@ typedef enum UC_CHARACTERWINS, // CHARACTERWINS [character] [x rounds] + UC_ALLCUPRECORDS, // ALLCUPRECORDS [cup to complete up to] [minimum position] [minimum difficulty] + UC_ALLCHAOS, // ALLCHAOS [minimum difficulty] UC_ALLSUPER, // ALLSUPER [minimum difficulty] UC_ALLEMERALDS, // ALLEMERALDS [minimum difficulty] @@ -437,6 +439,7 @@ UINT16 M_CompletionEmblems(void); boolean M_CheckNetUnlockByID(UINT16 unlockid); boolean M_SecretUnlocked(INT32 type, boolean local); boolean M_CupLocked(cupheader_t *cup); +boolean M_CupSecondRowLocked(void); boolean M_MapLocked(UINT16 mapnum); INT32 M_CountMedals(boolean all, boolean extraonly); diff --git a/src/menus/extras-challenges.c b/src/menus/extras-challenges.c index 92b4d48ee..da5dc2bd1 100644 --- a/src/menus/extras-challenges.c +++ b/src/menus/extras-challenges.c @@ -58,6 +58,8 @@ static void M_UpdateChallengeGridVisuals(void) { UINT16 i; + challengesmenu.cache_secondrowlocked = M_CupSecondRowLocked(); + challengesmenu.unlockcount[CMC_UNLOCKED] = 0; challengesmenu.unlockcount[CMC_TOTAL] = 0; diff --git a/src/menus/extras-statistics.c b/src/menus/extras-statistics.c index 7d9971443..1c2866c5a 100644 --- a/src/menus/extras-statistics.c +++ b/src/menus/extras-statistics.c @@ -60,7 +60,7 @@ static void M_StatisticsMaps(void) if (M_CupLocked(cup)) continue; - for (i = 0; i < CUPCACHE_MAX; i++) + for (i = 0; i < CUPCACHE_PODIUM; i++) { if (cup->cachedlevels[i] >= nummapheaders) continue; diff --git a/src/menus/transient/cup-select.c b/src/menus/transient/cup-select.c index 69e155592..0f2f75239 100644 --- a/src/menus/transient/cup-select.c +++ b/src/menus/transient/cup-select.c @@ -214,7 +214,9 @@ void M_CupSelectHandler(INT32 choice) M_SetMenuDelay(pid); } - if (menucmd[pid].dpad_ud > 0) + if (cupgrid.cache_secondrowlocked == true) + ; // No up/down for you! + else if (menucmd[pid].dpad_ud > 0) { cupgrid.y++; if (cupgrid.y >= CUPMENU_ROWS) diff --git a/src/menus/transient/level-select.c b/src/menus/transient/level-select.c index 8929e25b8..c01f4c65f 100644 --- a/src/menus/transient/level-select.c +++ b/src/menus/transient/level-select.c @@ -114,7 +114,7 @@ UINT16 M_CountLevelsToShowInList(levelsearch_t *levelsearch) if (levelsearch->checklocked && M_CupLocked(levelsearch->cup)) return 0; - for (i = 0; i < CUPCACHE_MAX; i++) + for (i = 0; i < CUPCACHE_PODIUM; i++) { if (!M_CanShowLevelInList(levelsearch->cup->cachedlevels[i], levelsearch)) continue; @@ -158,13 +158,13 @@ UINT16 M_GetFirstLevelInList(UINT8 *i, levelsearch_t *levelsearch) { if (levelsearch->checklocked && M_CupLocked(levelsearch->cup)) { - *i = CUPCACHE_MAX; + *i = CUPCACHE_PODIUM; return NEXTMAP_INVALID; } *i = 0; mapnum = NEXTMAP_INVALID; - for (; *i < CUPCACHE_MAX; (*i)++) + for (; *i < CUPCACHE_PODIUM; (*i)++) { if (!M_CanShowLevelInList(levelsearch->cup->cachedlevels[*i], levelsearch)) continue; @@ -194,7 +194,7 @@ UINT16 M_GetNextLevelInList(UINT16 mapnum, UINT8 *i, levelsearch_t *levelsearch) { mapnum = NEXTMAP_INVALID; (*i)++; - for (; *i < CUPCACHE_MAX; (*i)++) + for (; *i < CUPCACHE_PODIUM; (*i)++) { if (!M_CanShowLevelInList(levelsearch->cup->cachedlevels[*i], levelsearch)) continue; @@ -299,18 +299,28 @@ boolean M_LevelListFromGametype(INT16 gt) if (levellist.levelsearch.cupmode) { + const boolean secondrowlocked = M_CupSecondRowLocked(); + if (cupgrid.cache_secondrowlocked != secondrowlocked) + { + cupgrid.cache_secondrowlocked = secondrowlocked; + if (cupgrid.y || cupgrid.pageno) + { + // Prevent softlock, reset to start + cupgrid.x = cupgrid.y = cupgrid.pageno = 0; + } + } + levelsearch_t templevelsearch = levellist.levelsearch; // full copy size_t currentid = 0, highestunlockedid = 0; const size_t pagelen = sizeof(cupheader_t*) * (CUPMENU_COLUMNS * CUPMENU_ROWS); boolean foundany = false, currentvalid = false; + size_t deltaid = 0; G_GetBackupCupData( cupgrid.grandprix == true && cv_splitplayers.value <= 1 ); - templevelsearch.cup = kartcupheaders; - #if 0 // Make sure there's valid cups before going to this menu. -- rip sweet prince if (templevelsearch.cup == NULL) @@ -357,8 +367,89 @@ boolean M_LevelListFromGametype(INT16 gt) cupgrid.pageno = currentid / (CUPMENU_COLUMNS * CUPMENU_ROWS); \ currentvalid = true; - while (templevelsearch.cup) +#define GRID_TIDYLOCKED(rewind) \ + currentid -= rewind; \ + memset(&cupgrid.builtgrid[currentid], 0, pagelen); \ + deltaid = 0; + + boolean lostandfoundready = true; + // foundanythispage SHOULD start out as false... but if + // nothing is unlocked, the first page should never be wiped! + boolean foundanythispage = true; + + templevelsearch.cup = kartcupheaders; + while (true) { + // Handle reaching the end of the base-game cups. + if (lostandfoundready == true + && ( + templevelsearch.cup == NULL + || templevelsearch.cup->id == basenumkartcupheaders + ) + ) + { + lostandfoundready = false; + + if (deltaid != 0 && foundanythispage == false) + { + GRID_TIDYLOCKED(deltaid); + } + + size_t olddelta = deltaid; + if (cupgrid.grandprix == false) + { + cupheader_t *restore = templevelsearch.cup; + + templevelsearch.cup = &dummy_lostandfound; + templevelsearch.checklocked = true; + + if (M_GetFirstLevelInList(&temp, &templevelsearch) != NEXTMAP_INVALID) + { + foundany = foundanythispage = true; + GRID_INSERTCUP; + highestunlockedid = currentid; + + if (Playing() + ? (mapheaderinfo[gamemap-1] && mapheaderinfo[gamemap-1]->cup == NULL) + : (gt == -1 && levellist.levelsearch.cup == templevelsearch.cup)) + { + GRID_FOCUSCUP; + } + + currentid++; + deltaid = currentid % (CUPMENU_COLUMNS * CUPMENU_ROWS); + } + + templevelsearch.cup = restore; + } + + // Lost and Found marks the transition point between base + // and custom cups. Always force a page break between these + // (unless LnF is the only "cup" on the page, for sanity). + + if ( + (deltaid == 0) // a new page already + || (olddelta == 0 && deltaid == 1) // LnF is first and only entry + ) + ; // this page layout is fine + else + { + if (foundanythispage == false) + { + GRID_TIDYLOCKED(deltaid); + } + else + { + currentid += (CUPMENU_COLUMNS * CUPMENU_ROWS) - deltaid; + deltaid = 0; + foundanythispage = false; + } + } + } + + if (templevelsearch.cup == NULL) + break; + templevelsearch.checklocked = false; if (!M_CountLevelsToShowInList(&templevelsearch)) { @@ -374,6 +465,7 @@ boolean M_LevelListFromGametype(INT16 gt) templevelsearch.checklocked = true; if (M_GetFirstLevelInList(&temp, &templevelsearch) != NEXTMAP_INVALID) { + foundanythispage = true; highestunlockedid = currentid; if (Playing() @@ -385,37 +477,34 @@ boolean M_LevelListFromGametype(INT16 gt) } } - currentid++; templevelsearch.cup = templevelsearch.cup->next; - } - // Lost and found, a simplified version of the above loop. - if (cupgrid.grandprix == false) - { - templevelsearch.cup = &dummy_lostandfound; - templevelsearch.checklocked = true; + currentid++; + deltaid = currentid % (CUPMENU_COLUMNS * CUPMENU_ROWS); - if (M_GetFirstLevelInList(&temp, &templevelsearch) != NEXTMAP_INVALID) + if (secondrowlocked == true) { - foundany = true; - GRID_INSERTCUP; - highestunlockedid = currentid; - - if (Playing() - ? (mapheaderinfo[gamemap-1] && mapheaderinfo[gamemap-1]->cup == NULL) - : (gt == -1 && levellist.levelsearch.cup == templevelsearch.cup)) + // If the second row is locked and you've reached it, skip onward. + if (deltaid >= CUPMENU_COLUMNS) { - GRID_FOCUSCUP; + currentid += (CUPMENU_COLUMNS * CUPMENU_ROWS) - deltaid; + deltaid = 0; } - - currentid++; } - templevelsearch.cup = NULL; + if (deltaid == 0) + { + if (foundanythispage == false) + { + GRID_TIDYLOCKED((CUPMENU_COLUMNS * CUPMENU_ROWS)); + } + foundanythispage = false; + } } #undef GRID_INSERTCUP #undef GRID_FOCUSCUP +#undef GRID_TIDYLOCKED if (foundany == false) {