Tutorials are now strongly ordered, as opposed to passively ordered

- You will only see one uncompleted course on the Tutorial level select at a time.
    - All subsequent stages will not be visible.
    - This actually doesn't apply if you've beaten all the basegame Tutorial courses, and then load custom ones, to avoid discouraging the creation of those.
- If you select the menu and any loaded Tutorial stage is not completed, that stage will be highlighted automatically.
    - Uses the same icon as the Grand Prix backup tracker
        - Partly because it's the same general concept, saving your progress between sessions and alerting you to incompletion
        - Partly so I didn't have to bother any asset creators for something more specialised
This commit is contained in:
toaster 2023-11-04 22:13:24 +00:00
parent 993dea580c
commit 95ea6ae883
3 changed files with 69 additions and 7 deletions

View file

@ -2894,7 +2894,7 @@ static void M_DrawHighLowLevelTitle(INT16 x, INT16 y, INT16 map)
V_DrawLSTitleLowString(x2, y+28, 0, word2);
}
static void M_DrawLevelSelectBlock(INT16 x, INT16 y, INT16 map, boolean redblink, boolean greyscale)
static void M_DrawLevelSelectBlock(INT16 x, INT16 y, UINT16 map, boolean redblink, boolean greyscale)
{
UINT8 *colormap = NULL;
@ -2913,6 +2913,20 @@ static void M_DrawLevelSelectBlock(INT16 x, INT16 y, INT16 map, boolean redblink
map,
colormap);
M_DrawHighLowLevelTitle(98+x, y+8, map);
if (levellist.levelsearch.tutorial && !(mapheaderinfo[map]->records.mapvisited & MV_BEATEN))
{
V_DrawScaledPatch(
x + 80 + 3, y + 50, 0,
W_CachePatchName(
va(
"CUPBKUP%c",
(greyscale ? '1' : '2')
),
PU_CACHE
)
);
}
}
void M_DrawLevelSelect(void)

View file

@ -80,7 +80,11 @@ static void M_StatisticsMaps(void)
headerexists = false;
for (i = 0; i < nummapheaders; i++)
{
M_StatisticsAddMap(i, NULL, &headerexists, true);
if (M_StatisticsAddMap(i, NULL, &headerexists, true))
{
if (!(mapheaderinfo[i]->records.mapvisited & MV_BEATEN))
break;
}
}
if ((i = statisticsmenu.numextramedals) != 0)

View file

@ -125,9 +125,25 @@ 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;
}
}
return count;
}
@ -188,6 +204,13 @@ 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++;
@ -412,19 +435,41 @@ boolean M_LevelListFromGametype(INT16 gt)
// Okay, just a list of maps then.
if (M_GetFirstLevelInList(&temp, &levellist.levelsearch) == NEXTMAP_INVALID)
boolean invalidatedcursor = (
levellist.levelsearch.cup != NULL
|| levellist.levelsearch.tutorial != (gt == GT_TUTORIAL)
);
levellist.levelsearch.cup = NULL;
levellist.levelsearch.tutorial = (gt == GT_TUTORIAL);
UINT16 test = M_GetFirstLevelInList(&temp, &levellist.levelsearch);
if (test == NEXTMAP_INVALID)
{
return false;
}
// Reset position properly if you go back & forth between gametypes
if (levellist.levelsearch.cup)
levellist.mapcount = M_CountLevelsToShowInList(&levellist.levelsearch);
if (levellist.levelsearch.tutorial && levellist.levelsearch.checklocked)
{
// Find the first level we haven't played.
UINT16 possiblecursor = 0;
while (test < nummapheaders && (mapheaderinfo[test]->records.mapvisited & MV_BEATEN))
{
test = M_GetNextLevelInList(test, &temp, &levellist.levelsearch);
possiblecursor++;
}
if (test != NEXTMAP_INVALID)
levellist.cursor = possiblecursor;
}
else if (invalidatedcursor)
{
levellist.cursor = 0;
levellist.levelsearch.cup = NULL;
}
levellist.mapcount = M_CountLevelsToShowInList(&levellist.levelsearch);
M_LevelSelectScrollDest();
levellist.y = levellist.dest;
@ -450,7 +495,6 @@ void M_LevelSelectInit(INT32 choice)
// Make sure this is reset as we'll only be using this function for offline games!
levellist.netgame = false;
levellist.levelsearch.checklocked = true;
levellist.levelsearch.tutorial = (gt == GT_TUTORIAL);
switch (currentMenu->menuitems[itemOn].mvar1)
{