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")
This commit is contained in:
toaster 2022-12-31 16:22:46 +00:00
parent dc7222821c
commit 2db7562c24
5 changed files with 33 additions and 13 deletions

View file

@ -1140,7 +1140,7 @@ void readlevelheader(MYFILE *f, char * name)
} }
else if (fastcmp(word, "TYPEOFLEVEL")) 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; mapheaderinfo[num]->typeoflevel = (UINT32)i;
else else
{ {
@ -1279,12 +1279,12 @@ void readlevelheader(MYFILE *f, char * name)
else else
mapheaderinfo[num]->menuflags &= ~LF2_NOTIMEATTACK; mapheaderinfo[num]->menuflags &= ~LF2_NOTIMEATTACK;
} }
else if (fastcmp(word, "VISITNEEDED")) else if (fastcmp(word, "FINISHNEEDED"))
{ {
if (i || word2[0] == 'T' || word2[0] == 'Y') if (i || word2[0] == 'T' || word2[0] == 'Y')
mapheaderinfo[num]->menuflags |= LF2_VISITNEEDED; mapheaderinfo[num]->menuflags |= LF2_FINISHNEEDED;
else else
mapheaderinfo[num]->menuflags &= ~LF2_VISITNEEDED; mapheaderinfo[num]->menuflags &= ~LF2_FINISHNEEDED;
} }
else if (fastcmp(word, "GRAVITY")) else if (fastcmp(word, "GRAVITY"))
mapheaderinfo[num]->gravity = FLOAT_TO_FIXED(atof(word2)); mapheaderinfo[num]->gravity = FLOAT_TO_FIXED(atof(word2));

View file

@ -6300,7 +6300,7 @@ struct int_const_s const INT_CONST[] = {
{"LF2_HIDEINMENU",LF2_HIDEINMENU}, {"LF2_HIDEINMENU",LF2_HIDEINMENU},
{"LF2_HIDEINSTATS",LF2_HIDEINSTATS}, {"LF2_HIDEINSTATS",LF2_HIDEINSTATS},
{"LF2_NOTIMEATTACK",LF2_NOTIMEATTACK}, {"LF2_NOTIMEATTACK",LF2_NOTIMEATTACK},
{"LF2_VISITNEEDED",LF2_VISITNEEDED}, {"LF2_FINISHNEEDED",LF2_FINISHNEEDED},
// Emeralds // Emeralds
{"EMERALD_CHAOS1",EMERALD_CHAOS1}, {"EMERALD_CHAOS1",EMERALD_CHAOS1},

View file

@ -443,7 +443,7 @@ struct mapheader_t
#define LF2_HIDEINMENU (1<<0) ///< Hide in the multiplayer menu #define LF2_HIDEINMENU (1<<0) ///< Hide in the multiplayer menu
#define LF2_HIDEINSTATS (1<<1) ///< Hide in the statistics screen #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<<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_FINISHNEEDED (1<<3) ///< Not available in Time Attack modes until you beat the level
extern mapheader_t** mapheaderinfo; extern mapheader_t** mapheaderinfo;
extern INT32 nummapheaders, mapallocsize; extern INT32 nummapheaders, mapallocsize;

View file

@ -3418,8 +3418,18 @@ boolean M_CanShowLevelInList(INT16 mapnum, levelsearch_t *levelsearch)
if (mapheaderinfo[mapnum]->lumpnum == LUMPERROR) if (mapheaderinfo[mapnum]->lumpnum == LUMPERROR)
return false; return false;
if (levelsearch->checklocked && M_MapLocked(mapnum+1)) // Does the map have lock conditions?
return false; // not unlocked 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 // Check for TOL
if (!(mapheaderinfo[mapnum]->typeoflevel & levelsearch->typeoflevel)) if (!(mapheaderinfo[mapnum]->typeoflevel & levelsearch->typeoflevel))
@ -7688,9 +7698,16 @@ void M_Statistics(INT32 choice)
if (!mapheaderinfo[i]) if (!mapheaderinfo[i])
continue; continue;
// Check for no visibility + legacy box
if (mapheaderinfo[i]->menuflags & (LF2_NOTIMEATTACK|LF2_HIDEINSTATS|LF2_HIDEINMENU)) if (mapheaderinfo[i]->menuflags & (LF2_NOTIMEATTACK|LF2_HIDEINSTATS|LF2_HIDEINMENU))
continue; continue;
// Check for completion
if ((mapheaderinfo[i]->menuflags & LF2_FINISHNEEDED)
&& !(mapheaderinfo[i]->mapvisited & MV_BEATEN))
continue;
// Check for unlock
if (M_MapLocked(i+1)) if (M_MapLocked(i+1))
continue; continue;

View file

@ -570,7 +570,10 @@ static char *M_BuildConditionTitle(UINT16 map)
{ {
char *title, *ref; 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("???"); return Z_StrDup("???");
title = ref = G_BuildMapTitle(map+1); title = ref = G_BuildMapTitle(map+1);
@ -629,7 +632,7 @@ static const char *M_GetConditionString(condition_t *cn)
title = BUILDCONDITIONTITLE(cn->requirement); title = BUILDCONDITIONTITLE(cn->requirement);
work = va("%s %s%s", work = va("%s %s%s",
(cn->type == UC_MAPVISITED) ? "Visit" : "Beat", (cn->type == UC_MAPVISITED) ? "Visit" : "Finish a round on",
title, title,
(cn->type == UC_MAPENCORE) ? " in Encore Mode" : ""); (cn->type == UC_MAPENCORE) ? " in Encore Mode" : "");
Z_Free(title); Z_Free(title);