diff --git a/src/deh_soc.c b/src/deh_soc.c index d63301901..87cc55328 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -1183,8 +1183,10 @@ void readlevelheader(MYFILE *f, char * name) mapheaderinfo[num]->numlaps = (UINT8)i; else if (fastcmp(word, "UNLOCKABLE")) { - if (i >= 0 && i <= MAXUNLOCKABLES) // 0 for no unlock required, anything else requires something - mapheaderinfo[num]->unlockrequired = (SINT8)i - 1; + if (i == 0 || word2[0] == 'F' || word2[0] == 'N') + mapheaderinfo[num]->unlockrequired = MAXUNLOCKABLES; + else if (i > 0 && i <= MAXUNLOCKABLES) // 0 for no unlock required, anything else requires something + mapheaderinfo[num]->unlockrequired = (UINT8)(i-1); else deh_warning("Level header %d: invalid unlockable number %d", num, i); } @@ -3087,8 +3089,10 @@ void readcupheader(MYFILE *f, cupheader_t *cup) } else if (fastcmp(word, "UNLOCKABLE")) { - if (i >= 0 && i <= MAXUNLOCKABLES) // 0 for no unlock required, anything else requires something - cup->unlockrequired = (SINT8)i - 1; + if (i == 0 || word2[0] == 'F' || word2[0] == 'N') + cup->unlockrequired = MAXUNLOCKABLES; + else if (i > 0 && i <= MAXUNLOCKABLES) // 0 for no unlock required, anything else requires something + cup->unlockrequired = (UINT8)(i-1); else deh_warning("%s Cup: invalid unlockable number %d", cup->name, i); } diff --git a/src/dehacked.c b/src/dehacked.c index 005924ef4..b2fd16e03 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -486,7 +486,7 @@ static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile) { cup = Z_Calloc(sizeof (cupheader_t), PU_STATIC, NULL); cup->id = numkartcupheaders; - cup->unlockrequired = -1; + cup->unlockrequired = MAXUNLOCKABLES; deh_strlcpy(cup->name, word2, sizeof(cup->name), va("Cup header %s: name", word2)); if (prev != NULL) diff --git a/src/doomstat.h b/src/doomstat.h index 55644bfb2..d7b09f060 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -355,7 +355,7 @@ typedef struct cupheader_s UINT8 numlevels; ///< Number of levels defined in levellist UINT8 numbonus; ///< Number of bonus stages defined UINT8 emeraldnum; ///< ID of Emerald to use for special stage (1-7 for Chaos Emeralds, 8-14 for Super Emeralds, 0 for no emerald) - SINT8 unlockrequired; ///< An unlockable is required to select this cup. -1 for no unlocking required. + UINT8 unlockrequired; ///< An unlockable is required to select this cup. -1 for no unlocking required. struct cupheader_s *next; ///< Next cup in linked list } cupheader_t; @@ -391,7 +391,7 @@ typedef struct // Selection metadata char keywords[33]; ///< Keywords separated by space to search for. 32 characters. - SINT8 unlockrequired; ///< Is an unlockable required to play this level? -1 if no. + UINT8 unlockrequired; ///< Is an unlockable required to play this level? -1 if no. UINT8 levelselect; ///< Is this map available in the level select? If so, which map list is it available in? UINT16 menuflags; ///< LF2_flags: options that affect record attack menus diff --git a/src/g_game.c b/src/g_game.c index bafbf2ec3..f00ffcbe5 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3870,7 +3870,7 @@ static void G_GetNextMap(void) while (cup) { // Not unlocked? Grab the next result afterwards - if (!marathonmode && cup->unlockrequired != -1 && !gamedata->unlocked[cup->unlockrequired]) + if (!marathonmode && cup->unlockrequired < MAXUNLOCKABLES && !gamedata->unlocked[cup->unlockrequired]) { cup = cup->next; gettingresult = 1; diff --git a/src/k_menudraw.c b/src/k_menudraw.c index c72871577..a3cae5651 100644 --- a/src/k_menudraw.c +++ b/src/k_menudraw.c @@ -1911,7 +1911,7 @@ static void M_DrawCupPreview(INT16 y, cupheader_t *cup) V_DrawFill(0, y, BASEVIDWIDTH, 54, 31); - if (cup && (cup->unlockrequired == -1 || gamedata->unlocked[cup->unlockrequired])) + if (cup && (cup->unlockrequired >= MAXUNLOCKABLES || gamedata->unlocked[cup->unlockrequired])) { i = (cupgrid.previewanim / 82) % cup->numlevels; while (x < BASEVIDWIDTH + pad) @@ -1949,7 +1949,7 @@ static void M_DrawCupTitle(INT16 y, cupheader_t *cup) if (cup) { - boolean unlocked = (cup->unlockrequired == -1 || gamedata->unlocked[cup->unlockrequired]); + boolean unlocked = (cup->unlockrequired >= MAXUNLOCKABLES || gamedata->unlocked[cup->unlockrequired]); UINT8 *colormap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_GREY, GTC_MENUCACHE); patch_t *icon = W_CachePatchName(cup->icon, PU_CACHE); const char *str = (unlocked ? va("%s Cup", cup->name) : "???"); @@ -2017,7 +2017,7 @@ void M_DrawCupSelect(void) V_DrawScaledPatch(x, y, 0, patch); - if (iconcup->unlockrequired != -1 && !gamedata->unlocked[iconcup->unlockrequired]) + if (iconcup->unlockrequired < MAXUNLOCKABLES && !gamedata->unlocked[iconcup->unlockrequired]) { patch_t *st = W_CachePatchName(va("ICONST0%d", (cupgrid.previewanim % 4) + 1), PU_CACHE); V_DrawScaledPatch(x + 8, y + icony, 0, st); diff --git a/src/k_menufunc.c b/src/k_menufunc.c index 07af02502..b1c34c19f 100644 --- a/src/k_menufunc.c +++ b/src/k_menufunc.c @@ -3459,7 +3459,7 @@ static void M_LevelListFromGametype(INT16 gt) while (cup) { - if (cup->unlockrequired == -1 || gamedata->unlocked[cup->unlockrequired]) + if (cup->unlockrequired >= MAXUNLOCKABLES || gamedata->unlocked[cup->unlockrequired]) { highestid = cup->id; if (Playing() && mapheaderinfo[gamemap-1] && mapheaderinfo[gamemap-1]->cup == cup) @@ -3593,7 +3593,7 @@ void M_CupSelectHandler(INT32 choice) M_SetMenuDelay(pid); if ((!newcup) - || (newcup && newcup->unlockrequired != -1 && !gamedata->unlocked[newcup->unlockrequired]) + || (newcup && newcup->unlockrequired < MAXUNLOCKABLES && !gamedata->unlocked[newcup->unlockrequired]) || (newcup->cachedlevels[0] == NEXTMAP_INVALID)) { S_StartSound(NULL, sfx_s3kb2); diff --git a/src/m_cond.c b/src/m_cond.c index 4bf644e23..46f81cfc8 100644 --- a/src/m_cond.c +++ b/src/m_cond.c @@ -761,11 +761,23 @@ UINT8 M_MapLocked(INT32 mapnum) // That just makes hosts' lives hell. if (dedicated) return false; + + // No skipping over any part of your marathon. + if (marathonmode) + return false; - if (!mapheaderinfo[mapnum-1] || mapheaderinfo[mapnum-1]->unlockrequired < 0) + if (!mapheaderinfo[mapnum-1]) return false; - if (!gamedata->unlocked[mapheaderinfo[mapnum-1]->unlockrequired]) + if (mapheaderinfo[mapnum-1]->cup) + { + if ((mapheaderinfo[mapnum-1]->cup->unlockrequired < MAXUNLOCKABLES) + && (!gamedata->unlocked[mapheaderinfo[mapnum-1]->cup->unlockrequired])) + return true; + } + + if ((mapheaderinfo[mapnum-1]->unlockrequired < MAXUNLOCKABLES) + && (!gamedata->unlocked[mapheaderinfo[mapnum-1]->unlockrequired])) return true; return false; diff --git a/src/p_setup.c b/src/p_setup.c index 9c06e7038..3e9747505 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -400,7 +400,7 @@ static void P_ClearSingleMapHeaderInfo(INT16 num) mapheaderinfo[num]->palette = UINT16_MAX; mapheaderinfo[num]->encorepal = UINT16_MAX; mapheaderinfo[num]->numlaps = NUMLAPS_DEFAULT; - mapheaderinfo[num]->unlockrequired = -1; + mapheaderinfo[num]->unlockrequired = MAXUNLOCKABLES; mapheaderinfo[num]->levelselect = 0; mapheaderinfo[num]->levelflags = 0; mapheaderinfo[num]->menuflags = 0;