]> git.rm.cloudns.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Separate and improve MapReadSizes()
authorbones_was_here <bones_was_here@xonotic.au>
Mon, 26 Sep 2022 05:21:19 +0000 (15:21 +1000)
committerbones_was_here <bones_was_here@xonotic.au>
Mon, 26 Sep 2022 05:21:19 +0000 (15:21 +1000)
Ensure maps with small minimum player count can be selected for voting
when player count is low or zero, even if their minimum would otherwise be
too high, to reduce chance of maplist fallback (which ignores sizes).
Setting (for example) every CTF map to min 4 and every DM map to min 2
is a viable config with this code.

Add g_maplist_sizes_specparty, reduces player count used when selecting
maps to allow for a consistent spectator population.

Better debugging messages.

qcsrc/common/mapinfo.qc
qcsrc/common/mapinfo.qh
qcsrc/server/intermission.qc
xonotic-server.cfg

index c0b67ff4d535e97e9752132fafd7134c28c9ae6d..23c8d8704e6438817176307e53076e779703c237 100644 (file)
@@ -1083,6 +1083,23 @@ int MapInfo_Get_ByName(string pFilename, float pAllowGenerate, Gametype pGametyp
        return r;
 }
 
+bool MapReadSizes(string map)
+{
+       // TODO: implement xonotic#28 / xonvote 172 (sizes in mapinfo)
+       string readsize_msg = strcat("MapReadSizes ", map);
+       float fh = fopen(strcat("maps/", map, ".sizes"), FILE_READ);
+       if(fh >= 0)
+       {
+               map_minplayers = stoi(fgets(fh));
+               map_maxplayers = stoi(fgets(fh));
+               fclose(fh);
+               LOG_TRACEF(readsize_msg, ": ok, min %d max %d", map_minplayers, map_maxplayers);
+               return true;
+       }
+       LOG_TRACE(readsize_msg, ": not found");
+       return false;
+}
+
 float MapInfo_FindName(string s)
 {
        // if there is exactly one map of prefix s, return it
index a7bf6ce0aab77fdcb4718c0f084998c30da9f517..c2bb5cf449cf2e930941aec58747ad31b9c3e27e 100644 (file)
@@ -168,6 +168,11 @@ string MapInfo_BSPName_ByID(float i);
 // load info about a map by name into the MapInfo_Map_* globals
 int MapInfo_Get_ByName(string s, float allowGenerate, Gametype gametypeToSet); // 1 on success, 0 on failure, 2 if it autogenerated a mapinfo file
 
+// load map-specific player limits
+int map_minplayers;
+int map_maxplayers;
+bool MapReadSizes(string map);
+
 // look for a map by a prefix, returns the actual map name on success, string_null on failure or ambigous match
 string MapInfo_FindName_match; // the name of the map that was found
 float MapInfo_FindName_firstResult; // -1 if none were found, index of first one if not unique but found (FindName then returns -1)
index c1a5d33d8feec8551c493fa78272fd832b946b62..e9c622be48abde7bcfc5049a10660ea6f9e01319 100644 (file)
@@ -71,32 +71,32 @@ bool MapHasRightSize(string map)
                return true;
 
        // open map size restriction file
-       string opensize_msg = strcat("opensize ", map);
-       float fh = fopen(strcat("maps/", map, ".sizes"), FILE_READ);
+       if(!MapReadSizes(map))
+               return true; // map has no size restrictions
+
+       string checksize_msg = strcat("MapHasRightSize ", map);
        int player_limit = ((autocvar_g_maplist_sizes_count_maxplayers) ? GetPlayerLimit() : 0);
        int pcount = ((player_limit > 0) ? min(player_count, player_limit) : player_count); // bind it to the player limit so that forced spectators don't influence the limits
+
        if(!autocvar_g_maplist_sizes_count_bots)
                pcount -= currentbots;
-       if(fh >= 0)
+       pcount -= rint(cvar("g_maplist_sizes_specparty") * pcount);
+
+       // ensure small maps can be selected when pcount is low
+       if(map_minplayers <= (_MapInfo_GetTeamPlayBool(MapInfo_CurrentGametype()) ? 4 : 2))
+               map_minplayers = 0;
+
+       if(pcount < map_minplayers)
        {
-               opensize_msg = strcat(opensize_msg, ": ok, ");
-               int mapmin = stoi(fgets(fh));
-               int mapmax = stoi(fgets(fh));
-               fclose(fh);
-               if(pcount < mapmin)
-               {
-                       LOG_TRACE(opensize_msg, "not enough");
-                       return false;
-               }
-               if(mapmax && pcount > mapmax)
-               {
-                       LOG_TRACE(opensize_msg, "too many");
-                       return false;
-               }
-               LOG_TRACE(opensize_msg, "right size");
-               return true;
+               LOG_TRACE(checksize_msg, ": not enough");
+               return false;
+       }
+       if(map_maxplayers && pcount > map_maxplayers)
+       {
+               LOG_TRACE(checksize_msg, ": too many");
+               return false;
        }
-       LOG_TRACE(opensize_msg, ": not found");
+       LOG_TRACE(checksize_msg, ": right size");
        return true;
 }
 
index 334f749a2552baf0ab69165c106bbbb2aad469c8..f0937a16d1a23b4750ee0df279cde36d56364abe 100644 (file)
@@ -231,6 +231,7 @@ set g_maplist_check_waypoints 0 "when 1, maps are skipped if there currently are
 set g_maplist_ignore_sizes 0 "when 1, all maps are shown in the map list regardless of player count"
 set g_maplist_sizes_count_maxplayers 1 "check the player limit when getting the player count so forced spectators don't affect the size restrictions"
 set g_maplist_sizes_count_bots 1 "include the number of bots currently in the server when counting the number of players for size restrictions"
+set g_maplist_sizes_specparty 0 "this fraction of people are expected to only spectate, reduces player count used to select voting GUI maps"
 
 set g_items_mindist 4000 "starting distance for the fading of items"
 set g_items_maxdist 4500 "maximum distance at which an item can be viewed, after which it will be invisible"