diff --git a/src/deh_soc.c b/src/deh_soc.c index 52d2e7501..ce7ac6515 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -1181,15 +1181,6 @@ void readlevelheader(MYFILE *f, char * name) mapheaderinfo[num]->encorepal = (UINT16)i; else if (fastcmp(word, "NUMLAPS")) mapheaderinfo[num]->numlaps = (UINT8)i; - else if (fastcmp(word, "UNLOCKABLE")) - { - 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); - } else if (fastcmp(word, "SKYBOXSCALE")) mapheaderinfo[num]->skybox_scalex = mapheaderinfo[num]->skybox_scaley = mapheaderinfo[num]->skybox_scalez = (INT16)i; else if (fastcmp(word, "SKYBOXSCALEX")) @@ -3091,15 +3082,6 @@ void readcupheader(MYFILE *f, cupheader_t *cup) else deh_warning("%s Cup: invalid emerald number %d", cup->name, i); } - else if (fastcmp(word, "UNLOCKABLE")) - { - 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); - } else deh_warning("%s Cup: unknown word '%s'", cup->name, word); } diff --git a/src/dehacked.c b/src/dehacked.c index b2fd16e03..35f603bdd 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -486,7 +486,6 @@ static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile) { cup = Z_Calloc(sizeof (cupheader_t), PU_STATIC, NULL); cup->id = numkartcupheaders; - 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 7c311ace1..a4cfb246f 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -355,7 +355,6 @@ struct cupheader_t 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) - UINT8 unlockrequired; ///< An unlockable is required to select this cup. MAXUNLOCKABLES for no unlocking required. cupheader_t *next; ///< Next cup in linked list }; @@ -391,7 +390,6 @@ struct mapheader_t // Selection metadata char keywords[33]; ///< Keywords separated by space to search for. 32 characters. - 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 5f5a9f8a7..1b090dd7a 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3866,7 +3866,7 @@ static void G_GetNextMap(void) while (cup) { // Not unlocked? Grab the next result afterwards - if (!marathonmode && M_CheckNetUnlockByID(cup->unlockrequired)) + if (!marathonmode && M_CupLocked(cup)) { cup = cup->next; gettingresult = 1; diff --git a/src/k_menudraw.c b/src/k_menudraw.c index e31d5df28..d9a23ac97 100644 --- a/src/k_menudraw.c +++ b/src/k_menudraw.c @@ -1929,7 +1929,7 @@ static void M_DrawCupPreview(INT16 y, cupheader_t *cup) V_DrawFill(0, y, BASEVIDWIDTH, 54, 31); - if (cup && (cup->unlockrequired >= MAXUNLOCKABLES || M_CheckNetUnlockByID(cup->unlockrequired))) + if (cup && !M_CupLocked(cup)) { i = (cupgrid.previewanim / 82) % cup->numlevels; while (x < BASEVIDWIDTH) @@ -1964,7 +1964,7 @@ static void M_DrawCupTitle(INT16 y, cupheader_t *cup) if (cup) { - boolean unlocked = (cup->unlockrequired >= MAXUNLOCKABLES || M_CheckNetUnlockByID(cup->unlockrequired)); + boolean unlocked = !M_CupLocked(cup); 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) : "???"); @@ -2032,7 +2032,7 @@ void M_DrawCupSelect(void) V_DrawScaledPatch(x, y, 0, patch); - if (iconcup->unlockrequired < MAXUNLOCKABLES && !M_CheckNetUnlockByID(iconcup->unlockrequired)) + if (M_CupLocked(iconcup)) { 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 7c23c3d78..e21a5902d 100644 --- a/src/k_menufunc.c +++ b/src/k_menufunc.c @@ -3478,7 +3478,7 @@ static void M_LevelListFromGametype(INT16 gt) while (cup) { - if (cup->unlockrequired >= MAXUNLOCKABLES || M_CheckNetUnlockByID(cup->unlockrequired)) + if (!M_CupLocked(cup)) { highestid = cup->id; if (Playing() && mapheaderinfo[gamemap-1] && mapheaderinfo[gamemap-1]->cup == cup) @@ -3612,7 +3612,7 @@ void M_CupSelectHandler(INT32 choice) M_SetMenuDelay(pid); if ((!newcup) - || (newcup->unlockrequired < MAXUNLOCKABLES && !M_CheckNetUnlockByID(newcup->unlockrequired)) + || (M_CupLocked(newcup)) || (newcup->cachedlevels[0] == NEXTMAP_INVALID)) { S_StartSound(NULL, sfx_s3kb2); diff --git a/src/lua_maplib.c b/src/lua_maplib.c index 0557456b2..37ccc955b 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -2449,8 +2449,6 @@ static int mapheaderinfo_get(lua_State *L) lua_pushinteger(L, header->palette); else if (fastcmp(field,"numlaps")) lua_pushinteger(L, header->numlaps); - else if (fastcmp(field,"unlockrequired")) - lua_pushinteger(L, header->unlockrequired); else if (fastcmp(field,"levelselect")) lua_pushinteger(L, header->levelselect); else if (fastcmp(field,"levelflags")) diff --git a/src/m_cond.c b/src/m_cond.c index 1bd2c13ac..fb1f6ee1a 100644 --- a/src/m_cond.c +++ b/src/m_cond.c @@ -1001,8 +1001,38 @@ boolean M_SecretUnlocked(INT32 type, boolean local) #endif //if 0 } +boolean M_CupLocked(cupheader_t *cup) +{ + UINT8 i; + + // Don't lock maps in dedicated servers. + // That just makes hosts' lives hell. + if (dedicated) + return false; + + // No skipping over any part of your marathon. + if (marathonmode) + return false; + + if (!cup) + return false; + + for (i = 0; i < MAXUNLOCKABLES; ++i) + { + if (unlockables[i].type != SECRET_CUP) + continue; + if (M_UnlockableCup(&unlockables[i]) != cup) + continue; + return !M_CheckNetUnlockByID(i); + } + + return false; +} + boolean M_MapLocked(INT32 mapnum) { + UINT8 i; + // Don't lock maps in dedicated servers. // That just makes hosts' lives hell. if (dedicated) @@ -1017,11 +1047,21 @@ boolean M_MapLocked(INT32 mapnum) if (mapheaderinfo[mapnum-1]->cup) { - if (!M_CheckNetUnlockByID(mapheaderinfo[mapnum-1]->cup->unlockrequired)) - return true; + return M_CupLocked(mapheaderinfo[mapnum-1]->cup); } - return !M_CheckNetUnlockByID(mapheaderinfo[mapnum-1]->unlockrequired); + for (i = 0; i < MAXUNLOCKABLES; ++i) + { + if (unlockables[i].type != SECRET_CUP) + continue; + if (!unlockables[i].stringVar || !unlockables[i].stringVar[0]) + continue; + if (G_MapNumber(unlockables[i].stringVar) != mapnum-1) + continue; + return !M_CheckNetUnlockByID(i); + } + + return false; } INT32 M_CountMedals(boolean all) @@ -1150,6 +1190,40 @@ INT32 M_UnlockableFollowerNum(unlockable_t *unlock) return -1; } +cupheader_t *M_UnlockableCup(unlockable_t *unlock) +{ + cupheader_t *cup = kartcupheaders; + + if (unlock->type != SECRET_CUP) + { + // This isn't a cup unlockable... + return NULL; + } + + if (unlock->stringVar && unlock->stringVar[0]) + { + // Get the cup from the string. + while (cup) + { + if (!strcmp(cup->name, unlock->stringVar)) + break; + cup = cup->next; + } + } + else + { + // Use the number directly. + while (cup) + { + if (cup->id == unlock->variable) + break; + cup = cup->next; + } + } + + return cup; +} + // ---------------- // Misc Emblem shit // ---------------- diff --git a/src/m_cond.h b/src/m_cond.h index 8932805d4..fd8037e2f 100644 --- a/src/m_cond.h +++ b/src/m_cond.h @@ -99,7 +99,7 @@ typedef enum // One step above bragging rights SECRET_EXTRAMEDAL, // Extra medal for your counter - // Level restrictions (TODO) + // Level restrictions SECRET_CUP, // Permit access to entire cup (overrides SECRET_MAP) SECRET_MAP, // Permit access to single map @@ -207,6 +207,7 @@ UINT8 M_CompletionEmblems(void); // Checking unlockable status boolean M_CheckNetUnlockByID(UINT8 unlockid); boolean M_SecretUnlocked(INT32 type, boolean local); +boolean M_CupLocked(cupheader_t *cup); boolean M_MapLocked(INT32 mapnum); INT32 M_CountMedals(boolean all); @@ -223,6 +224,8 @@ UINT8 M_GotLowEnoughTime(INT32 tictime); INT32 M_UnlockableSkinNum(unlockable_t *unlock); INT32 M_UnlockableFollowerNum(unlockable_t *unlock); +cupheader_t *M_UnlockableCup(unlockable_t *unlock); + INT32 M_EmblemSkinNum(emblem_t *emblem); #define M_Achieved(a) ((a) >= MAXCONDITIONSETS || gamedata->achieved[a]) diff --git a/src/p_setup.c b/src/p_setup.c index e5cbba81e..4b2e9323b 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -400,7 +400,6 @@ static void P_ClearSingleMapHeaderInfo(INT16 num) mapheaderinfo[num]->palette = UINT16_MAX; mapheaderinfo[num]->encorepal = UINT16_MAX; mapheaderinfo[num]->numlaps = NUMLAPS_DEFAULT; - mapheaderinfo[num]->unlockrequired = MAXUNLOCKABLES; mapheaderinfo[num]->levelselect = 0; mapheaderinfo[num]->levelflags = 0; mapheaderinfo[num]->menuflags = 0;