Level select no longer assumes that games will always be linear

- If a level is in-between two with the same header, it would previously create two headers with the same name. Now it groups all levels with the same header together.
- Previously, a header would only be visible if its first map was visible. Now it will show the header if you've visited any level under the header.

For SUGOI.
This commit is contained in:
Sally Coolatta 2021-04-30 21:46:09 -04:00
parent 1355a82aa5
commit 381ead4d7e

View file

@ -5166,34 +5166,75 @@ static boolean M_GametypeHasLevels(INT32 gt)
static INT32 M_CountRowsToShowOnPlatter(INT32 gt)
{
INT32 mapnum = 0, prevmapnum = 0, col = 0, rows = 0;
INT32 col = 0, rows = 0;
INT32 mapIterate = 0;
INT32 headingIterate = 0;
boolean mapAddedAlready[NUMMAPS];
while (mapnum < NUMMAPS)
memset(mapAddedAlready, 0, sizeof mapAddedAlready);
for (mapIterate = 0; mapIterate < NUMMAPS; mapIterate++)
{
if (M_CanShowLevelOnPlatter(mapnum, gt))
boolean forceNewRow = true;
if (mapAddedAlready[mapIterate] == true)
{
if (rows == 0)
// Already added under another heading
continue;
}
if (M_CanShowLevelOnPlatter(mapIterate, gt) == false)
{
// Don't show this one
continue;
}
for (headingIterate = mapIterate; headingIterate < NUMMAPS; headingIterate++)
{
boolean wide = false;
if (mapAddedAlready[headingIterate] == true)
{
// Already added under another heading
continue;
}
if (M_CanShowLevelOnPlatter(headingIterate, gt) == false)
{
// Don't show this one
continue;
}
if (!fastcmp(mapheaderinfo[mapIterate]->selectheading, mapheaderinfo[headingIterate]->selectheading))
{
// Headers don't match
continue;
}
wide = (mapheaderinfo[headingIterate]->menuflags & LF2_WIDEICON);
// preparing next position to drop mapnum into
if (col == 2 // no more space on the row?
|| wide || forceNewRow)
{
col = 0;
rows++;
}
else
{
if (col == 2
|| (mapheaderinfo[prevmapnum]->menuflags & LF2_WIDEICON)
|| (mapheaderinfo[mapnum]->menuflags & LF2_WIDEICON)
|| !(fastcmp(mapheaderinfo[mapnum]->selectheading, mapheaderinfo[prevmapnum]->selectheading)))
{
col = 0;
rows++;
}
else
col++;
col++;
}
prevmapnum = mapnum;
// Done adding this one
mapAddedAlready[headingIterate] = true;
forceNewRow = wide;
}
mapnum++;
}
if (levellistmode == LLM_CREATESERVER)
{
rows++;
}
return rows;
}
@ -5223,7 +5264,10 @@ static void M_CacheLevelPlatter(void)
static boolean M_PrepareLevelPlatter(INT32 gt, boolean nextmappick)
{
INT32 numrows = M_CountRowsToShowOnPlatter(gt);
INT32 mapnum = 0, prevmapnum = 0, col = 0, row = 0, startrow = 0;
INT32 col = 0, row = 0, startrow = 0;
INT32 mapIterate = 0; // First level of map loop -- find starting points for select headings
INT32 headingIterate = 0; // Second level of map loop -- finding maps that match mapIterate's heading.
boolean mapAddedAlready[NUMMAPS];
if (!numrows)
return false;
@ -5240,6 +5284,8 @@ static boolean M_PrepareLevelPlatter(INT32 gt, boolean nextmappick)
// done here so lsrow and lscol can be set if cv_nextmap is on the platter
lsrow = lscol = lshli = lsoffs[0] = lsoffs[1] = 0;
memset(mapAddedAlready, 0, sizeof mapAddedAlready);
if (levellistmode == LLM_CREATESERVER)
{
sprintf(levelselect.rows[0].header, "Gametype");
@ -5251,31 +5297,75 @@ static boolean M_PrepareLevelPlatter(INT32 gt, boolean nextmappick)
char_notes = NULL;
}
while (mapnum < NUMMAPS)
for (mapIterate = 0; mapIterate < NUMMAPS; mapIterate++)
{
if (M_CanShowLevelOnPlatter(mapnum, gt))
INT32 headerRow = -1;
boolean anyAvailable = false;
boolean forceNewRow = true;
if (mapAddedAlready[mapIterate] == true)
{
const UINT8 actnum = mapheaderinfo[mapnum]->actnum;
const boolean headingisname = (fastcmp(mapheaderinfo[mapnum]->selectheading, mapheaderinfo[mapnum]->lvlttl));
const boolean wide = (mapheaderinfo[mapnum]->menuflags & LF2_WIDEICON);
// Already added under another heading
continue;
}
if (M_CanShowLevelOnPlatter(mapIterate, gt) == false)
{
// Don't show this one
continue;
}
for (headingIterate = mapIterate; headingIterate < NUMMAPS; headingIterate++)
{
UINT8 actnum = 0;
boolean headingisname = false;
boolean wide = false;
if (mapAddedAlready[headingIterate] == true)
{
// Already added under another heading
continue;
}
if (M_CanShowLevelOnPlatter(headingIterate, gt) == false)
{
// Don't show this one
continue;
}
if (!fastcmp(mapheaderinfo[mapIterate]->selectheading, mapheaderinfo[headingIterate]->selectheading))
{
// Headers don't match
continue;
}
actnum = mapheaderinfo[headingIterate]->actnum;
headingisname = (fastcmp(mapheaderinfo[headingIterate]->selectheading, mapheaderinfo[headingIterate]->lvlttl));
wide = (mapheaderinfo[headingIterate]->menuflags & LF2_WIDEICON);
// preparing next position to drop mapnum into
if (levelselect.rows[startrow].maplist[0])
{
if (col == 2 // no more space on the row?
|| wide
|| (mapheaderinfo[prevmapnum]->menuflags & LF2_WIDEICON)
|| !(fastcmp(mapheaderinfo[mapnum]->selectheading, mapheaderinfo[prevmapnum]->selectheading))) // a new heading is starting?
|| wide || forceNewRow)
{
col = 0;
row++;
}
else
{
col++;
}
}
levelselect.rows[row].maplist[col] = mapnum+1; // putting the map on the platter
levelselect.rows[row].mapavailable[col] = M_LevelAvailableOnPlatter(mapnum);
if (headerRow == -1)
{
// Set where the header row is meant to be
headerRow = row;
}
levelselect.rows[row].maplist[col] = headingIterate+1; // putting the map on the platter
levelselect.rows[row].mapavailable[col] = M_LevelAvailableOnPlatter(headingIterate);
if ((lswide(row) = wide)) // intentionally assignment
{
@ -5283,7 +5373,7 @@ static boolean M_PrepareLevelPlatter(INT32 gt, boolean nextmappick)
levelselect.rows[row].mapavailable[2] = levelselect.rows[row].mapavailable[1] = levelselect.rows[row].mapavailable[0];
}
if (nextmappick && cv_nextmap.value == mapnum+1) // A little quality of life improvement.
if (nextmappick && cv_nextmap.value == headingIterate+1) // A little quality of life improvement.
{
lsrow = row;
lscol = col;
@ -5292,6 +5382,8 @@ static boolean M_PrepareLevelPlatter(INT32 gt, boolean nextmappick)
// individual map name
if (levelselect.rows[row].mapavailable[col])
{
anyAvailable = true;
if (headingisname)
{
if (actnum)
@ -5302,7 +5394,7 @@ static boolean M_PrepareLevelPlatter(INT32 gt, boolean nextmappick)
else if (wide)
{
// Yes, with LF2_WIDEICON it'll continue on over into the next 17+1 char block. That's alright; col is always zero, the string is contiguous, and the maximum length is lvlttl[22] + ' ' + ZONE + ' ' + INT32, which is about 39 or so - barely crossing into the third column.
char* mapname = G_BuildMapTitle(mapnum+1);
char* mapname = G_BuildMapTitle(headingIterate+1);
strcpy(levelselect.rows[row].mapnames[col], (const char *)mapname);
Z_Free(mapname);
}
@ -5311,9 +5403,9 @@ static boolean M_PrepareLevelPlatter(INT32 gt, boolean nextmappick)
char mapname[22+1+11]; // lvlttl[22] + ' ' + INT32
if (actnum)
sprintf(mapname, "%s %d", mapheaderinfo[mapnum]->lvlttl, actnum);
sprintf(mapname, "%s %d", mapheaderinfo[headingIterate]->lvlttl, actnum);
else
strcpy(mapname, mapheaderinfo[mapnum]->lvlttl);
strcpy(mapname, mapheaderinfo[headingIterate]->lvlttl);
if (strlen(mapname) >= 17)
strcpy(mapname+17-3, "...");
@ -5322,27 +5414,36 @@ static boolean M_PrepareLevelPlatter(INT32 gt, boolean nextmappick)
}
}
else
sprintf(levelselect.rows[row].mapnames[col], "???");
// creating header text
if (!col && ((row == startrow) || !(fastcmp(mapheaderinfo[mapnum]->selectheading, mapheaderinfo[levelselect.rows[row-1].maplist[0]-1]->selectheading))))
{
if (!levelselect.rows[row].mapavailable[col])
sprintf(levelselect.rows[row].header, "???");
else
{
sprintf(levelselect.rows[row].header, "%s", mapheaderinfo[mapnum]->selectheading);
if (!(mapheaderinfo[mapnum]->levelflags & LF_NOZONE) && headingisname)
{
sprintf(levelselect.rows[row].header + strlen(levelselect.rows[row].header), " ZONE");
}
}
sprintf(levelselect.rows[row].mapnames[col], "???");
}
prevmapnum = mapnum;
// Done adding this one
mapAddedAlready[headingIterate] = true;
forceNewRow = wide;
}
mapnum++;
if (headerRow == -1)
{
// Shouldn't happen
continue;
}
// creating header text
if (anyAvailable == false)
{
sprintf(levelselect.rows[headerRow].header, "???");
}
else
{
sprintf(levelselect.rows[headerRow].header, "%s", mapheaderinfo[mapIterate]->selectheading);
if (!(mapheaderinfo[mapIterate]->levelflags & LF_NOZONE)
&& fastcmp(mapheaderinfo[mapIterate]->selectheading, mapheaderinfo[mapIterate]->lvlttl))
{
sprintf(levelselect.rows[headerRow].header + strlen(levelselect.rows[headerRow].header), " ZONE");
}
}
}
#ifdef SYMMETRICAL_PLATTER