Add LobbySize option to level headers, controls whether the map appears in vote, based on player count

- Prevents a map from appearing on the vote screen if
  there are too many players
- LobbySize
  - Duel - 2 players max
  - Small - 5 players max
  - Medium - 10 players max
  - Large - 16 players max (default if not set)
- Future proofing
  - Doesn't count bot players in gametypes that don't
    support bots
This commit is contained in:
James R 2024-01-13 14:32:07 -08:00
parent fd7eb42e9d
commit db4e2e692b
6 changed files with 61 additions and 3 deletions

View file

@ -2208,13 +2208,34 @@ void D_SetupVote(INT16 newgametype)
WRITEUINT8(p, ((cv_kartencore.value == 1) && (rules & GTR_ENCORE)));
WRITEUINT8(p, G_SometimesGetDifferentEncore());
UINT8 numPlayers = 0;
for (i = 0; i < MAXPLAYERS; ++i)
{
if (!playeringame[i] || players[i].spectator)
{
continue;
}
extern consvar_t cv_forcebots; // debug
if (!(rules & GTR_BOTS) && players[i].bot && !cv_forcebots.value)
{
// Gametype doesn't support bots
continue;
}
numPlayers++;
}
for (i = 0; i < VOTE_NUM_LEVELS; i++)
{
UINT16 m = G_RandMap(
UINT16 m = G_RandMapPerPlayerCount(
G_TOLFlag(newgametype),
prevmap, false,
(i < VOTE_NUM_LEVELS-1),
votebuffer
votebuffer,
numPlayers
);
votebuffer[i] = m;
WRITEUINT16(p, m);

View file

@ -1417,6 +1417,29 @@ void readlevelheader(MYFILE *f, char * name)
mapheaderinfo[num]->destroyforchallenge_size = j;
}
}
else if (fastcmp(word, "LOBBYSIZE"))
{
if (fastcmp(word2, "DUEL"))
{
mapheaderinfo[num]->playerLimit = 2;
}
else if (fastcmp(word2, "SMALL"))
{
mapheaderinfo[num]->playerLimit = 5;
}
else if (fastcmp(word2, "MEDIUM"))
{
mapheaderinfo[num]->playerLimit = 10;
}
else if (fastcmp(word2, "LARGE"))
{
mapheaderinfo[num]->playerLimit = 16;
}
else
{
deh_warning("Level header %d: invalid lobby size '%s'", num, word2);
}
}
else
deh_warning("Level header %d: unknown word '%s'", num, word);
}

View file

@ -501,6 +501,7 @@ struct mapheader_t
UINT8 levelselect; ///< Is this map available in the level select? If so, which map list is it available in?
UINT16 menuflags; ///< LF2_flags: options that affect record attack menus
UINT8 playerLimit; ///< This map does not appear in multiplayer vote if there are too many players
// Operational metadata
UINT16 levelflags; ///< LF_flags: merged booleans into one UINT16 for space, see below

View file

@ -3499,7 +3499,7 @@ static UINT16 *g_allowedMaps = NULL;
static size_t g_randMapStack = 0;
#endif
UINT16 G_RandMap(UINT32 tolflags, UINT16 pprevmap, boolean ignoreBuffers, boolean callAgainSoon, UINT16 *extBuffer)
UINT16 G_RandMapPerPlayerCount(UINT32 tolflags, UINT16 pprevmap, boolean ignoreBuffers, boolean callAgainSoon, UINT16 *extBuffer, UINT8 numPlayers)
{
INT32 allowedMapsCount = 0;
INT32 extBufferCount = 0;
@ -3558,6 +3558,12 @@ tryAgain:
continue;
}
if (numPlayers > mapheaderinfo[i]->playerLimit)
{
// Too many players for this map.
continue;
}
// Only care about restrictions if the host is a listen server.
if (!dedicated)
{
@ -3665,6 +3671,11 @@ tryAgain:
return ret;
}
UINT16 G_RandMap(UINT32 tolflags, UINT16 pprevmap, boolean ignoreBuffers, boolean callAgainSoon, UINT16 *extBuffer)
{
return G_RandMapPerPlayerCount(tolflags, pprevmap, ignoreBuffers, callAgainSoon, extBuffer, 0);
}
void G_AddMapToBuffer(UINT16 map)
{
if (mapheaderinfo[map]->justPlayed == 0) // Started playing a new map.

View file

@ -277,6 +277,7 @@ FUNCMATH INT32 G_TicsToMilliseconds(tic_t tics);
UINT32 G_TOLFlag(INT32 pgametype);
UINT16 G_GetFirstMapOfGametype(UINT16 pgametype);
UINT16 G_RandMapPerPlayerCount(UINT32 tolflags, UINT16 pprevmap, boolean ignoreBuffers, boolean callAgainSoon, UINT16 *extBuffer, UINT8 numPlayers);
UINT16 G_RandMap(UINT32 tolflags, UINT16 pprevmap, boolean ignoreBuffers, boolean callAgainSoon, UINT16 *extBuffer);
void G_AddMapToBuffer(UINT16 map);

View file

@ -457,6 +457,7 @@ static void P_ClearSingleMapHeaderInfo(INT16 num)
mapheaderinfo[num]->levelselect = 0;
mapheaderinfo[num]->levelflags = 0;
mapheaderinfo[num]->menuflags = 0;
mapheaderinfo[num]->playerLimit = MAXPLAYERS;
mapheaderinfo[num]->mobj_scale = FRACUNIT;
mapheaderinfo[num]->default_waypoint_radius = 0;
P_ClearMapHeaderLighting(&mapheaderinfo[num]->lighting);