From 2db7562c24f0452979902f13fa789fb94d64cf87 Mon Sep 17 00:00:00 2001 From: toaster Date: Sat, 31 Dec 2022 16:22:46 +0000 Subject: [PATCH] LF2_FINISHNEEDED - Replacement for LF2_VISITNEEDED, which was itself a Kart-specific inversion of LF2_NOVISITNEEDED - Prevents selection in time attack before you've beaten the level in another context (GP, or MP if applicable) - Should be used for Sealed Stars (and Adventure Example) exclusively IMO, but usable for others too Related adjustments: - Allow a map to have a `TypeOfLevel` of 0 without error - Change the Condition String for UC_MAPVISITED to "Finish a round on X" (previously "Beat X") --- src/deh_soc.c | 8 ++++---- src/deh_tables.c | 2 +- src/doomstat.h | 8 ++++---- src/k_menufunc.c | 21 +++++++++++++++++++-- src/m_cond.c | 7 +++++-- 5 files changed, 33 insertions(+), 13 deletions(-) diff --git a/src/deh_soc.c b/src/deh_soc.c index 930ace846..4fb40b087 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -1140,7 +1140,7 @@ void readlevelheader(MYFILE *f, char * name) } else if (fastcmp(word, "TYPEOFLEVEL")) { - if (i) // it's just a number + if (i || isdigit(word2[0])) // it's just a number mapheaderinfo[num]->typeoflevel = (UINT32)i; else { @@ -1279,12 +1279,12 @@ void readlevelheader(MYFILE *f, char * name) else mapheaderinfo[num]->menuflags &= ~LF2_NOTIMEATTACK; } - else if (fastcmp(word, "VISITNEEDED")) + else if (fastcmp(word, "FINISHNEEDED")) { if (i || word2[0] == 'T' || word2[0] == 'Y') - mapheaderinfo[num]->menuflags |= LF2_VISITNEEDED; + mapheaderinfo[num]->menuflags |= LF2_FINISHNEEDED; else - mapheaderinfo[num]->menuflags &= ~LF2_VISITNEEDED; + mapheaderinfo[num]->menuflags &= ~LF2_FINISHNEEDED; } else if (fastcmp(word, "GRAVITY")) mapheaderinfo[num]->gravity = FLOAT_TO_FIXED(atof(word2)); diff --git a/src/deh_tables.c b/src/deh_tables.c index 8b9be00ff..5217e3c6c 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -6300,7 +6300,7 @@ struct int_const_s const INT_CONST[] = { {"LF2_HIDEINMENU",LF2_HIDEINMENU}, {"LF2_HIDEINSTATS",LF2_HIDEINSTATS}, {"LF2_NOTIMEATTACK",LF2_NOTIMEATTACK}, - {"LF2_VISITNEEDED",LF2_VISITNEEDED}, + {"LF2_FINISHNEEDED",LF2_FINISHNEEDED}, // Emeralds {"EMERALD_CHAOS1",EMERALD_CHAOS1}, diff --git a/src/doomstat.h b/src/doomstat.h index 7520342a9..76ec0cb25 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -440,10 +440,10 @@ struct mapheader_t #define LF_SECTIONRACE (1<<2) ///< Section race level #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_VISITNEEDED (1<<3) ///< Not available in Time Attack modes until you visit the level +#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_FINISHNEEDED (1<<3) ///< Not available in Time Attack modes until you beat the level extern mapheader_t** mapheaderinfo; extern INT32 nummapheaders, mapallocsize; diff --git a/src/k_menufunc.c b/src/k_menufunc.c index a421ba8a5..6e7c9e4dd 100644 --- a/src/k_menufunc.c +++ b/src/k_menufunc.c @@ -3418,8 +3418,18 @@ boolean M_CanShowLevelInList(INT16 mapnum, levelsearch_t *levelsearch) if (mapheaderinfo[mapnum]->lumpnum == LUMPERROR) return false; - if (levelsearch->checklocked && M_MapLocked(mapnum+1)) - return false; // not unlocked + // Does the map have lock conditions? + if (levelsearch->checklocked) + { + // Check for completion + if ((mapheaderinfo[mapnum]->menuflags & LF2_FINISHNEEDED) + && !(mapheaderinfo[mapnum]->mapvisited & MV_BEATEN)) + return false; + + // Check for unlock + if (M_MapLocked(mapnum+1)) + return false; + } // Check for TOL if (!(mapheaderinfo[mapnum]->typeoflevel & levelsearch->typeoflevel)) @@ -7688,9 +7698,16 @@ void M_Statistics(INT32 choice) if (!mapheaderinfo[i]) continue; + // Check for no visibility + legacy box if (mapheaderinfo[i]->menuflags & (LF2_NOTIMEATTACK|LF2_HIDEINSTATS|LF2_HIDEINMENU)) continue; + // Check for completion + if ((mapheaderinfo[i]->menuflags & LF2_FINISHNEEDED) + && !(mapheaderinfo[i]->mapvisited & MV_BEATEN)) + continue; + + // Check for unlock if (M_MapLocked(i+1)) continue; diff --git a/src/m_cond.c b/src/m_cond.c index 052f23dc0..14ad2b6b4 100644 --- a/src/m_cond.c +++ b/src/m_cond.c @@ -570,7 +570,10 @@ static char *M_BuildConditionTitle(UINT16 map) { char *title, *ref; - if (M_MapLocked(map+1)) + if (((mapheaderinfo[map]->menuflags & LF2_FINISHNEEDED) + // the following is intentionally not MV_BEATEN, just in case the title is for "Finish a round on X" + && !(mapheaderinfo[map]->mapvisited & MV_VISITED)) + || M_MapLocked(map+1)) return Z_StrDup("???"); title = ref = G_BuildMapTitle(map+1); @@ -629,7 +632,7 @@ static const char *M_GetConditionString(condition_t *cn) title = BUILDCONDITIONTITLE(cn->requirement); work = va("%s %s%s", - (cn->type == UC_MAPVISITED) ? "Visit" : "Beat", + (cn->type == UC_MAPVISITED) ? "Visit" : "Finish a round on", title, (cn->type == UC_MAPENCORE) ? " in Encore Mode" : ""); Z_Free(title);