diff --git a/src/deh_soc.c b/src/deh_soc.c index 2e11d2ba2..6787b7b2f 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -1372,13 +1372,6 @@ void readlevelheader(MYFILE *f, char * name) else mapheaderinfo[num]->menuflags &= ~LF2_HIDEINMENU; } - else if (fastcmp(word, "HIDEINSTATS")) - { - if (i || word2[0] == 'T' || word2[0] == 'Y') - mapheaderinfo[num]->menuflags |= LF2_HIDEINSTATS; - else - mapheaderinfo[num]->menuflags &= ~LF2_HIDEINSTATS; - } else if (fastcmp(word, "NOTIMEATTACK") || fastcmp(word, "NORECORDATTACK")) { // RECORDATTACK is an accepted alias if (i || word2[0] == 'T' || word2[0] == 'Y') @@ -1393,6 +1386,13 @@ void readlevelheader(MYFILE *f, char * name) else mapheaderinfo[num]->menuflags &= ~LF2_FINISHNEEDED; } + else if (fastcmp(word, "NOVISITNEEDED")) + { + if (i || word2[0] == 'T' || word2[0] == 'Y') + mapheaderinfo[num]->menuflags |= LF2_NOVISITNEEDED; + else + mapheaderinfo[num]->menuflags &= ~LF2_NOVISITNEEDED; + } else if (fastcmp(word, "GRAVITY")) mapheaderinfo[num]->gravity = FLOAT_TO_FIXED(atof(word2)); else if (fastcmp(word, "DESTROYOBJECTSFORCHALLENGES")) diff --git a/src/deh_tables.c b/src/deh_tables.c index 135b79456..2682f7d2b 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -6853,8 +6853,8 @@ struct int_const_s const INT_CONST[] = { {"LF_SUBTRACTNUM",LF_SUBTRACTNUM}, // And map flags {"LF2_HIDEINMENU",LF2_HIDEINMENU}, - {"LF2_HIDEINSTATS",LF2_HIDEINSTATS}, {"LF2_NOTIMEATTACK",LF2_NOTIMEATTACK}, + {"LF2_NOVISITNEEDED",LF2_NOVISITNEEDED}, {"LF2_FINISHNEEDED",LF2_FINISHNEEDED}, // Emeralds diff --git a/src/doomstat.h b/src/doomstat.h index 738a3a22e..2839aa313 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -572,8 +572,8 @@ struct mapheader_t #define LF_SUBTRACTNUM (1<<3) ///< Use subtractive position number (for bright levels) #define LF2_HIDEINMENU (1<<0) ///< Hide in the multiplayer menu -#define LF2_HIDEINSTATS (1<<1) ///< Hide in the statistics screen -#define LF2_NOTIMEATTACK (1<<2) ///< Hide this map in Time Attack modes +#define LF2_NOTIMEATTACK (1<<1) ///< Hide this map in Time Attack modes +#define LF2_NOVISITNEEDED (1<<2) ///< Map does not require visitation to be selectable #define LF2_FINISHNEEDED (1<<3) ///< Not available in Time Attack modes until you beat the level extern mapheader_t** mapheaderinfo; diff --git a/src/k_menudraw.c b/src/k_menudraw.c index 96b0b4f98..f0cd65abf 100644 --- a/src/k_menudraw.c +++ b/src/k_menudraw.c @@ -205,6 +205,17 @@ void M_PickMenuBGMap(void) continue; } + if (!(mapheaderinfo[i]->menuflags & LF2_NOVISITNEEDED) + && !(mapheaderinfo[i]->records.mapvisited & MV_VISITED) + && !( + mapheaderinfo[i]->cup + && mapheaderinfo[i]->cup->cachedlevels[0] == i + )) + { + // Not visited OR head of cup + continue; + } + if (M_MapLocked(i + 1) == true) { // We haven't earned this one. @@ -7177,7 +7188,7 @@ static void M_DrawStatsMaps(void) for (i = 0; i < nummapheaders; i++) { // Check for no visibility - if (!mapheaderinfo[i] || (mapheaderinfo[i]->menuflags & (LF2_NOTIMEATTACK|LF2_HIDEINSTATS|LF2_HIDEINMENU))) + if (!mapheaderinfo[i] || (mapheaderinfo[i]->menuflags & (LF2_NOTIMEATTACK|LF2_HIDEINMENU))) continue; // Has to be accessible via time attack diff --git a/src/m_cond.c b/src/m_cond.c index e170f8fe6..d38db3930 100644 --- a/src/m_cond.c +++ b/src/m_cond.c @@ -1094,7 +1094,7 @@ static void M_PrecacheLevelLocks(void) { if (!mapheaderinfo[mapcheck] || mapheaderinfo[mapcheck]->cup != NULL) continue; - if (mapheaderinfo[mapcheck]->menuflags & (LF2_HIDEINSTATS|LF2_HIDEINMENU)) + if (mapheaderinfo[mapcheck]->menuflags & LF2_HIDEINMENU) continue; if (((mapheaderinfo[mapcheck]->typeoflevel & TOL_TUTORIAL) == TOL_TUTORIAL) != ((mapheaderinfo[map]->typeoflevel & TOL_TUTORIAL) == TOL_TUTORIAL)) @@ -1475,7 +1475,7 @@ boolean M_CheckCondition(condition_t *cn, player_t *player) { for (i = 0; i < basenummapheaders; i++) { - if (!mapheaderinfo[i] || mapheaderinfo[i]->menuflags & (LF2_HIDEINSTATS|LF2_HIDEINMENU)) + if (!mapheaderinfo[i] || mapheaderinfo[i]->menuflags & (LF2_HIDEINMENU)) continue; total++; @@ -1957,7 +1957,7 @@ static char *M_BuildConditionTitle(UINT16 map) { char *title, *ref; - if (((mapheaderinfo[map]->menuflags & LF2_FINISHNEEDED) + if ((!(mapheaderinfo[map]->menuflags & LF2_NOVISITNEEDED) // the following is intentionally not MV_BEATEN, just in case the title is for "Finish a round on X" && !(mapheaderinfo[map]->records.mapvisited & MV_VISITED)) || M_MapLocked(map+1)) diff --git a/src/menus/extras-statistics.c b/src/menus/extras-statistics.c index 1c2866c5a..293c90227 100644 --- a/src/menus/extras-statistics.c +++ b/src/menus/extras-statistics.c @@ -21,13 +21,22 @@ static boolean M_StatisticsAddMap(UINT16 map, cupheader_t *cup, boolean *headere return false; // Check for no visibility - if (mapheaderinfo[map]->menuflags & (LF2_HIDEINSTATS|LF2_HIDEINMENU)) + if (mapheaderinfo[map]->menuflags & LF2_HIDEINMENU) return false; + // Check for visitation + // (M_CanShowLevelInList also checks being the first map in a cup, + // but we don't need to do this here because it'd just muddy stats!) + if (!(mapheaderinfo[map]->menuflags & LF2_NOVISITNEEDED) + && !(mapheaderinfo[map]->records.mapvisited & MV_VISITED)) + return false; + +#if 0 // Check for completion if ((mapheaderinfo[map]->menuflags & LF2_FINISHNEEDED) && !(mapheaderinfo[map]->records.mapvisited & MV_BEATEN)) return false; +#endif // Check for unlock if (M_MapLocked(map+1)) @@ -80,11 +89,7 @@ static void M_StatisticsMaps(void) headerexists = false; for (i = 0; i < nummapheaders; i++) { - if (M_StatisticsAddMap(i, NULL, &headerexists, true)) - { - if (!(mapheaderinfo[i]->records.mapvisited & MV_BEATEN)) - break; - } + M_StatisticsAddMap(i, NULL, &headerexists, true); } if ((i = statisticsmenu.numextramedals) != 0) diff --git a/src/menus/transient/level-select.c b/src/menus/transient/level-select.c index 73189a3bb..28eed536a 100644 --- a/src/menus/transient/level-select.c +++ b/src/menus/transient/level-select.c @@ -77,11 +77,11 @@ boolean M_CanShowLevelInList(INT16 mapnum, levelsearch_t *levelsearch) if (levelsearch->timeattack && (mapheaderinfo[mapnum]->menuflags & LF2_NOTIMEATTACK)) return false; + cupheader_t *cup = (levelsearch->cup == &dummy_lostandfound) ? NULL : levelsearch->cup; + // Don't permit cup when no cup requested (also no dupes in time attack) if (levelsearch->cupmode) { - cupheader_t *cup = (levelsearch->cup == &dummy_lostandfound) ? NULL : levelsearch->cup; - if ((!cup || levelsearch->timeattack) && mapheaderinfo[mapnum]->cup != cup) return false; @@ -90,6 +90,12 @@ boolean M_CanShowLevelInList(INT16 mapnum, levelsearch_t *levelsearch) // Finally, the most complex check: does the map have lock conditions? if (levelsearch->checklocked) { + // Check for visitation + if (!(mapheaderinfo[mapnum]->menuflags & LF2_NOVISITNEEDED) + && !(mapheaderinfo[mapnum]->records.mapvisited & MV_VISITED) + && !(cup && cup->cachedlevels[0] == mapnum)) + return false; + // Check for completion if ((mapheaderinfo[mapnum]->menuflags & LF2_FINISHNEEDED) && !(mapheaderinfo[mapnum]->records.mapvisited & MV_BEATEN)) @@ -128,22 +134,9 @@ UINT16 M_CountLevelsToShowInList(levelsearch_t *levelsearch) for (i = 0; i < nummapheaders; i++) { - if (M_CanShowLevelInList(i, levelsearch)) - { - count++; - - // Tutorial will only show what you've made your way to - if (!levelsearch->checklocked) - continue; - if (!levelsearch->tutorial) - continue; - if (i >= basenummapheaders) - continue; - if (mapheaderinfo[i]->records.mapvisited & MV_BEATEN) - continue; - - break; - } + if (!M_CanShowLevelInList(i, levelsearch)) + continue; + count++; } return count; @@ -206,13 +199,6 @@ UINT16 M_GetNextLevelInList(UINT16 mapnum, UINT8 *i, levelsearch_t *levelsearch) } else { - // Tutorial will only show what you've made your way to - if (levelsearch->checklocked - && levelsearch->tutorial - && mapnum < basenummapheaders - && !(mapheaderinfo[mapnum]->records.mapvisited & MV_BEATEN)) - return NEXTMAP_INVALID; - mapnum++; while (!M_CanShowLevelInList(mapnum, levelsearch) && mapnum < nummapheaders) mapnum++; diff --git a/src/s_sound.c b/src/s_sound.c index 142eaa4ba..562e05bcc 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -1393,11 +1393,13 @@ static boolean S_SoundTestDefLocked(musicdef_t *def) mapheader_t *header = mapheaderinfo[def->sequence.map]; - // Is the level tied to SP progression? - if (( - (header->menuflags & (LF2_FINISHNEEDED|LF2_HIDEINMENU)) - || (def->sequence.altref == ALTREF_REQUIRESBEATEN) // Associated music only when completed - ) + // Visitation required? + if (!(header->menuflags & LF2_NOVISITNEEDED) + && !(header->records.mapvisited & MV_VISITED)) + return true; + + // Associated music only when completed + if ((def->sequence.altref == ALTREF_REQUIRESBEATEN) && !(header->records.mapvisited & MV_BEATEN)) return true;