mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-10-30 08:01:28 +00:00
More universal Course restriction based on progression
All courses are restricted in Match Race/Time Attack/Online if not visited in GP UNLESS:
- It is the first Race Course of a Cup
- Course has "NoVisitNeeded = True`
- The Controls Tutorial and Test Run are the only two stages that will need this
The above replaces:
- A lot of restricted courses having to be marked with `FinishNeeded = True`
- Hidden Palace
- Sealed Stars 1-14
- Once Special Mode is unlocked, it will now be possible to practice Sealed Stars before rematching them in GP
- Almost all Tutorial-specific behaviour, since it was heinously hacky
HOWEVER, `FinishNeeded = True` was left in specifically for future releases, and I reserve the right to use it on Adventure Example again before launch.
This commit is contained in:
parent
601b39378d
commit
83366b6507
8 changed files with 54 additions and 50 deletions
|
|
@ -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"))
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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++;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue