return mapname;
}
-float Map_Count, Map_Current;
-string Map_Current_Name;
+int Map_Count, Map_Current;
// NOTE: this now expects the map list to be already tokenized and the count in Map_Count
int GetMaplistPosition()
{
int minplayers = max(0, floor(autocvar_minplayers));
if (teamplay)
- minplayers = max(0, floor(autocvar_minplayers_per_team) * AvailableTeams());
+ minplayers = max(0, floor(autocvar_minplayers_per_team) * AVAILABLE_TEAMS);
if (autocvar_g_maplist_check_waypoints
&& (currentbots || autocvar_bot_number || player_count < minplayers))
{
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;
}
- LOG_TRACE(opensize_msg, ": not found");
+ if(map_maxplayers && pcount > map_maxplayers)
+ {
+ LOG_TRACE(checksize_msg, ": too many");
+ return false;
+ }
+ LOG_TRACE(checksize_msg, ": right size");
return true;
}
{
if(pass == 2)
return true;
+ // MapInfo_Map_flags was set by MapInfo_CheckMap()
+ if (MapInfo_Map_flags & MAPINFO_FLAG_DONOTWANT)
+ return false;
if(MapHasRightSize(map_next))
return true;
return false;
getmapname_stored = strzone(nextmapname);
}
-void Map_Goto_SetFloat(float position)
+void Map_Goto_SetIndex(int position)
{
+ Map_Current = position;
cvar_set("g_maplist_index", ftos(position));
Map_Goto_SetStr(argv(position));
}
// return codes of map selectors:
// -1 = temporary failure (that is, try some method that is guaranteed to succeed)
// -2 = permanent failure
-float MaplistMethod_Iterate() // usual method
+int MaplistMethod_Iterate(void) // usual method
{
- float pass, i;
+ int pass, i;
LOG_TRACE("Trying MaplistMethod_Iterate");
{
for(i = 1; i < Map_Count; ++i)
{
- float mapindex;
+ int mapindex;
mapindex = (i + Map_Current) % Map_Count;
if(Map_Check(mapindex, pass))
return mapindex;
return -1;
}
-float MaplistMethod_Repeat() // fallback method
+int MaplistMethod_Repeat(void) // fallback method
{
LOG_TRACE("Trying MaplistMethod_Repeat");
return -2;
}
-float MaplistMethod_Random() // random map selection
+int MaplistMethod_Random(void) // random map selection
{
- float i, imax;
+ int i, imax;
LOG_TRACE("Trying MaplistMethod_Random");
for(i = 0; i <= imax; ++i)
{
- float mapindex;
+ int mapindex;
mapindex = (Map_Current + floor(random() * (Map_Count - 1) + 1)) % Map_Count; // any OTHER map
if(Map_Check(mapindex, 1))
return mapindex;
return -1;
}
-float MaplistMethod_Shuffle(float exponent) // more clever shuffling
// the exponent sets a bias on the map selection:
// the higher the exponent, the less likely "shortly repeated" same maps are
+int MaplistMethod_Shuffle(float exponent) // more clever shuffling
{
float i, j, imax, insertpos;
// insert the current map there
newlist = "";
- for(j = 1; j < insertpos; ++j) // i == 1: no loop, will be inserted as first; however, i == 1 has been excluded above
- newlist = strcat(newlist, " ", argv(j));
+ for(j = 1; j < insertpos; ) // i == 1: no loop, will be inserted as first; however, i == 1 has been excluded above
+ {
+ if (j + 2 < insertpos)
+ newlist = strcat(newlist, " ", argv(j++), " ", argv(j++), " ", argv(j++));
+ else
+ newlist = strcat(newlist, " ", argv(j++));
+ }
newlist = strcat(newlist, " ", argv(0)); // now insert the just selected map
- for(j = insertpos; j < Map_Count; ++j) // i == Map_Count: no loop, has just been inserted as last
- newlist = strcat(newlist, " ", argv(j));
+ for(j = insertpos; j < Map_Count; ) // i == Map_Count: no loop, has just been inserted as last
+ {
+ if (j + 2 < Map_Count)
+ newlist = strcat(newlist, " ", argv(j++), " ", argv(j++), " ", argv(j++));
+ else
+ newlist = strcat(newlist, " ", argv(j++));
+ }
newlist = substring(newlist, 1, strlen(newlist) - 1);
cvar_set("g_maplist", newlist);
Map_Count = tokenizebyseparator(autocvar_g_maplist, " ");
// NOTE: the selected map has just been inserted at (insertpos-1)th position
- Map_Current = insertpos - 1; // this is not really valid, but this way the fallback has a chance of working
- if(Map_Check(Map_Current, 1))
- return Map_Current;
+ if (Map_Check(insertpos - 1, 1))
+ return insertpos - 1;
}
return -1;
}
-void Maplist_Init()
+int Maplist_Init(void)
{
- float i = Map_Count = 0;
+ int i, available_maps = 0;
+ Map_Count = 0;
if(autocvar_g_maplist != "")
{
Map_Count = tokenizebyseparator(autocvar_g_maplist, " ");
for (i = 0; i < Map_Count; ++i)
- {
if (Map_Check(i, 2))
- break;
- }
+ ++available_maps;
}
- if (i == Map_Count)
+ if (!available_maps)
{
bprint( "Maplist contains no usable maps! Resetting it to default map list.\n" );
- cvar_set("g_maplist", MapInfo_ListAllAllowedMaps(MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags() | MAPINFO_FLAG_NOAUTOMAPLIST));
- if(autocvar_g_maplist_shuffle)
- ShuffleMaplist();
+ cvar_set("g_maplist", MapInfo_ListAllowedMaps(MapInfo_CurrentGametype(), MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags()));
if(!server_is_dedicated)
localcmd("\nmenu_cmd sync\n");
Map_Count = tokenizebyseparator(autocvar_g_maplist, " ");
+ for (i = 0; i < Map_Count; ++i)
+ if (Map_Check(i, 2))
+ ++available_maps;
}
+
if(Map_Count == 0)
error("empty maplist, cannot select a new map");
+
Map_Current = bound(0, GetMaplistPosition(), Map_Count - 1);
- strcpy(Map_Current_Name, argv(Map_Current)); // will be automatically freed on exit thanks to DP
- // this may or may not be correct, but who cares, in the worst case a map
- // isn't chosen in the first pass that should have been
+ if(autocvar_g_maplist_shuffle)
+ cvar_set("g_maplist", shufflewords(autocvar_g_maplist));
+
+ return available_maps;
}
-string GetNextMap()
+// NOTE: call Maplist_Init() before making GetNextMap() call(s)
+string GetNextMap(void)
{
- Maplist_Init();
- float nextMap = -1;
+ int nextMap = -1;
- if(nextMap == -1)
- if(autocvar_g_maplist_shuffle > 0)
- nextMap = MaplistMethod_Shuffle(autocvar_g_maplist_shuffle + 1);
+ if(nextMap == -1 && autocvar_g_maplist_shuffle > 0)
+ nextMap = MaplistMethod_Shuffle(autocvar_g_maplist_shuffle + 1);
- if(nextMap == -1)
- if(autocvar_g_maplist_selectrandom)
- nextMap = MaplistMethod_Random();
+ if(nextMap == -1 && autocvar_g_maplist_selectrandom)
+ nextMap = MaplistMethod_Random();
if(nextMap == -1)
nextMap = MaplistMethod_Iterate();
if(nextMap >= 0)
{
- Map_Goto_SetFloat(nextMap);
+ Map_Goto_SetIndex(nextMap);
return getmapname_stored;
}
return;
alreadychangedlevel = true;
+ Maplist_Init();
string nextMap = GetNextMap();
if(nextMap == "")
error("Everything is broken - cannot find a next map. Please report this to the developers.");
Map_Goto(reinit);
}
-void ShuffleMaplist()
-{
- cvar_set("g_maplist", shufflewords(autocvar_g_maplist));
-}
-
string GotoMap(string m)
{
m = GameTypeVote_MapInfo_FixName(m);
if(!MapInfo_CheckMap(m))
return "The map you suggested does not support the current game mode.";
cvar_set("nextmap", m);
- cvar_set("timelimit", "-1");
+ if (!intermission_running)
+ cvar_set("_endmatch", "1");
if(mapvote_initialized || alreadychangedlevel)
{
if(DoNextMapOverride(0))
&& ((this.autoscreenshot > 0) && (time > this.autoscreenshot)) )
{
this.autoscreenshot = -1;
- if(IS_REAL_CLIENT(this)) { stuffcmd(this, sprintf("\nscreenshot screenshots/autoscreenshot/%s-%s.jpg; echo \"^5A screenshot has been taken at request of the server.\"\n", GetMapname(), strftime(false, "%s"))); }
+ if(IS_REAL_CLIENT(this))
+ {
+ string num = strftime_s(); // strftime(false, "%s") isn't reliable, see strftime_s description
+ stuffcmd(this, sprintf("\nscreenshot screenshots/autoscreenshot/%s-%s.jpg; "
+ "echo \"^5A screenshot has been taken at request of the server.\"\n", GetMapname(), num));
+ }
return;
}