alias lockteams "qc_cmd_sv lockteams ${* ?}" // Disable the ability for players to switch or enter teams
alias make_mapinfo "qc_cmd_sv make_mapinfo ${* ?}" // Automatically rebuild mapinfo files
alias moveplayer "qc_cmd_sv moveplayer ${* ?}" // Change the team/status of a player
+alias nextmap "qc_cmd_sv nextmap ${* ?}" // Set/Query the next map
alias nospectators "qc_cmd_sv nospectators ${* ?}" // Automatically remove spectators from a match
alias printstats "qc_cmd_sv printstats ${* ?}" // Dump eventlog player stats and other score information
alias radarmap "qc_cmd_sv radarmap ${* ?}" // Generate a radar image of the map
sb_gameinfo_type_fontsize = hud_fontsize * 2.5;
sb_gameinfo_detail_fontsize = hud_fontsize * 1.3;
+ if (GET_NEXTMAP() != "")
+ {
+ // NOTE: nextmap is drawn before title to avoid covering title in case of long map name
+ str = strcat("^7", _("Next map:"), " ^9", GET_NEXTMAP());
+ drawcolorcodedstring(pos + vec2(hud_fontsize.x * 0.5, sb_gameinfo_type_fontsize.y - hud_fontsize.y * 1.25),
+ str, hud_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
+ }
+
// Game Info: Game Type
if (scoreboard_ui_enabled == 2)
str = _("Team Selection");
string autocvar_scoreboard_columns;
float autocvar_hud_panel_scoreboard_namesize = 15;
+string autocvar__nextmap;
+// no reason for get_nextmap to be a function for now
+// macro to not have an unnecessary function call stackframe
+#define GET_NEXTMAP() autocvar__nextmap
+
bool sb_showscores; // set by +showscores engine command
bool scoreboard_active;
setpause(0);
localcmd("\nsv_hook_firstjoin\n");
}
+
+ if (get_nextmap() != "")
+ Send_NextMap_To_Player(this);
}
.string shootfromfixedorigin;
}
}
+void GameCommand_nextmap(int request, int argc)
+{
+ switch (request)
+ {
+ case CMD_REQUEST_COMMAND:
+ {
+ if (argc >= 2) // nextmap with mapname arg
+ {
+ if (argc > 2)
+ LOG_HELP("Warning: nextmap only takes 1 argument");
+
+ string map = ValidateMap(argv(1), NULL);
+ if (map != "" && map != get_nextmap())
+ Set_NextMap(map);
+ }
+ else // nextmap without args
+ {
+ if (get_nextmap() != "")
+ LOG_HELP(get_nextmap());
+ else
+ LOG_HELP("none");
+ }
+ return; // never fall through to usage
+ }
+
+ default:
+ case CMD_REQUEST_USAGE:
+ {
+ LOG_HELP("Usage:^3 sv_cmd nextmap [<mapname>]");
+ LOG_HELP(" Without arguments it prints current nextmap if one is set");
+ LOG_HELP(" With arguments it attempts to set nextmap");
+ return;
+ }
+ }
+}
+
void GameCommand_nospectators(int request)
{
switch (request)
SERVER_COMMAND(lockteams, "Disable the ability for players to switch or enter teams") { GameCommand_lockteams(request); }
SERVER_COMMAND(make_mapinfo, "Automatically rebuild mapinfo files") { GameCommand_make_mapinfo(request); }
SERVER_COMMAND(moveplayer, "Change the team/status of a player") { GameCommand_moveplayer(request, arguments); }
+SERVER_COMMAND(nextmap, "Set/Query the next map") { GameCommand_nextmap(request, arguments); }
SERVER_COMMAND(nospectators, "Automatically remove spectators from a match") { GameCommand_nospectators(request); }
SERVER_COMMAND(printstats, "Dump eventlog player stats and other score information") { GameCommand_printstats(request); }
SERVER_COMMAND(radarmap, "Generate a radar image of the map") { GameCommand_radarmap(request, arguments); }
void VoteThink();
void VoteReset(bool verbose);
void VoteCommand(int request, entity caller, int argc, string vote_command);
+string ValidateMap(string validated_map, entity caller);
// warmup and nagger stuff
const float RESTART_COUNTDOWN = 10;
#include <server/scores_rules.qh>
#include <server/world.qh>
+void Send_NextMap_To_Player(entity pl)
+{
+ stuffcmd(pl, sprintf("\nsettemp _nextmap %s\n", get_nextmap()));
+}
+
+void Set_NextMap(string mapname)
+{
+ if (mapname != "")
+ strcpy(_nextmap, mapname);
+ else
+ strfree(_nextmap);
+
+ FOREACH_CLIENT(IS_REAL_CLIENT(it), { Send_NextMap_To_Player(it); });
+}
+
string GetGametype()
{
return MapInfo_Type_ToString(MapInfo_LoadedGametype);
alreadychangedlevel = true;
return true;
}
- if(autocvar_nextmap != "")
+ if(get_nextmap() != "")
{
string m;
- m = GameTypeVote_MapInfo_FixName(autocvar_nextmap);
- cvar_set("nextmap",m);
+ m = GameTypeVote_MapInfo_FixName(get_nextmap());
+ if (m != get_nextmap())
+ Set_NextMap(m);
if(!m || gametypevote)
return false;
if (!m)
return "The map you suggested is not available on this server.";
if (!autocvar_sv_vote_gametype)
- if(!MapInfo_CheckMap(m))
+ if (!MapInfo_CheckMap(m))
return "The map you suggested does not support the current game mode.";
- cvar_set("nextmap", m);
+ if (m != get_nextmap())
+ Set_NextMap(m);
if (!intermission_running)
cvar_set("_endmatch", "1");
- if(mapvote_initialized || alreadychangedlevel)
+ if (mapvote_initialized || alreadychangedlevel)
{
if(DoNextMapOverride(0))
return "Map switch initiated.";
#pragma once
bool autocvar_lastlevel;
-string autocvar_nextmap;
+
+string _nextmap;
+void Send_NextMap_To_Player(entity pl);
+void Set_NextMap(string mapname);
+
+// no reason for get_nextmap to be a function for now
+// macro to not have an unnecessary function call stackframe
+#define get_nextmap() _nextmap
+
bool autocvar_samelevel;
bool autocvar_sv_autoscreenshot;
string autocvar_sv_intermission_cdtrack;
if( type == NULL )
return flag;
- if ( autocvar_nextmap != "" )
+ if ( get_nextmap() != "" )
{
- if ( !MapInfo_Get_ByName(autocvar_nextmap, false, NULL) )
+ if ( !MapInfo_Get_ByName(get_nextmap(), false, NULL) )
return flag;
if (!(MapInfo_Map_supportedGametypes & type.gametype_flags))
return flag;
{
// gametype vote
WriteByte(MSG_ENTITY, BIT(0)); // gametypevote_flags
- WriteString(MSG_ENTITY, autocvar_nextmap);
+ WriteString(MSG_ENTITY, get_nextmap());
}
else if ( autocvar_sv_vote_gametype )
{
if ( GameTypeVote_Finished(mappos) )
{
gametypevote = false;
- if(autocvar_nextmap != "")
+ if(get_nextmap() != "")
{
- Map_Goto_SetStr(autocvar_nextmap);
+ Map_Goto_SetStr(get_nextmap());
Map_Goto(0);
alreadychangedlevel = true;
strfree(voted_gametype_string);
}
if(autocvar_sv_vote_gametype) { GameTypeVote_Start(); }
- else if(autocvar_nextmap == "") { MapVote_Init(); }
+ else if(get_nextmap() == "") { MapVote_Init(); }
}
MapVote_Tick();
BADCVAR("g_tmayhem_teams");
BADCVAR("g_vip");
BADCVAR("leadlimit");
- BADCVAR("nextmap");
BADCVAR("teamplay");
BADCVAR("timelimit");
BADCVAR("g_mapinfo_q3compat");
if(autocvar_sv_eventlog)
GameLogInit(); // requires matchid to be set
- cvar_set("nextmap", "");
-
SetDefaultAlpha();
if(autocvar_g_campaign)
seta sbar_info_pos 0 "Y-axis distance from lower right corner for engine info prints"
+set _nextmap "" "internal cvar, automatically synced with server's nextmap"
+
// scoreboard
seta scoreboard_columns default
set sv_eventlog_files_namesuffix .log "suffix of individual log file names"
set sv_eventlog_ipv6_delimiter 0 "use a _ delimiter for IPV6 IPs, so that they can be easily detected in scripts"
-set nextmap "" "override the maplist when switching to the next map"
set lastlevel "" "for singleplayer use, shows the menu once the match has ended"
set quit_when_empty 0 "set to 1, then the server exits when the next level would start but is empty"
set quit_and_redirect "" "set to an IP to redirect all players at the end of the match to another server. Set to \"self\" to let all players reconnect at the end of the match (use it to make seamless engine updates)"