From db4e2e692b18ff06e060a3b21bc60c2193cd0415 Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 13 Jan 2024 14:32:07 -0800 Subject: [PATCH] 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 --- src/d_netcmd.c | 25 +++++++++++++++++++++++-- src/deh_soc.c | 23 +++++++++++++++++++++++ src/doomstat.h | 1 + src/g_game.c | 13 ++++++++++++- src/g_game.h | 1 + src/p_setup.cpp | 1 + 6 files changed, 61 insertions(+), 3 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 165d8ca84..a4f52e383 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -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); diff --git a/src/deh_soc.c b/src/deh_soc.c index 9ceb61f95..9d9ff8bf3 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -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); } diff --git a/src/doomstat.h b/src/doomstat.h index 5247ea082..333bfd6f0 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -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 diff --git a/src/g_game.c b/src/g_game.c index 35161cb79..457062058 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -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. diff --git a/src/g_game.h b/src/g_game.h index d1378ce30..4f08804c6 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -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); diff --git a/src/p_setup.cpp b/src/p_setup.cpp index a1af94db5..604f29b06 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -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);