#include <server/damage.qh>
#include <server/gamelog.qh>
#include <server/hook.qh>
-#include <server/intermission.qh>
#include <server/ipban.qh>
#include <server/items/items.qh>
#include <server/main.qh>
#include <server/scores_rules.qh>
#include <server/spawnpoints.qh>
#include <server/teamplay.qh>
-#include <server/weapons/common.qh>
#include <server/weapons/weaponstats.qh>
const float LATENCY_THINKRATE = 10;
BADCVAR("g_duel_not_dm_maps");
BADCVAR("g_freezetag");
BADCVAR("g_freezetag_teams");
- BADCVAR("g_invasion_teams");
BADCVAR("g_invasion_type");
BADCVAR("g_jailbreak");
BADCVAR("g_jailbreak_teams");
BADCVAR("g_maplist");
BADCVAR("g_maplist_mostrecent");
BADCVAR("sv_motd");
+ BADCVAR("sv_termsofservice_url");
v = cvar_string(k);
d = cvar_defstring(k);
// does nothing gameplay relevant
BADCVAR("captureleadlimit_override");
BADCVAR("condump_stripcolors");
- BADCVAR("gameversion");
BADCVAR("fs_gamedir");
BADCVAR("g_allow_oldvortexbeam");
BADCVAR("g_balance_kill_delay");
BADCVAR("w_prop_interval");
BADPREFIX("chat_");
BADPREFIX("crypto_");
- BADPREFIX("gameversion_");
+ BADPREFIX("gameversion");
BADPREFIX("g_chat_");
BADPREFIX("g_ctf_captimerecord_");
BADPREFIX("g_hats_");
BADPREFIX("sv_timeout_");
BADPREFIX("sv_vote_");
BADPREFIX("timelimit_");
+ BADPRESUFFIX("g_", "_round_timelimit");
// allowed changes to server admins (please sync this to server.cfg)
// vi commands:
BADCVAR("g_start_delay");
BADCVAR("g_superspectate");
BADCVAR("g_tdm_teams_override");
- BADCVAR("g_warmup");
BADCVAR("g_weapon_stay"); BADPRESUFFIX("g_", "_weapon_stay");
BADCVAR("hostname");
BADCVAR("log_file");
BADVALUE("sys_ticrate", "0.0333333");
BADCVAR("teamplay_mode");
BADCVAR("timelimit_override");
- BADPREFIX("g_warmup_");
+ BADPREFIX("g_warmup");
BADPREFIX("sv_info_");
BADPREFIX("sv_ready_restart_");
BADCVAR("g_grappling_hook");
BADCVAR("g_jetpack");
- // temporary for testing
- // TODO remove before 0.8.3 release
- BADCVAR("g_ca_weaponarena");
- BADCVAR("g_freezetag_weaponarena");
- BADCVAR("g_lms_weaponarena");
- BADCVAR("g_ctf_stalemate_time");
-
#undef BADPRESUFFIX
#undef BADPREFIX
#undef BADCVAR
void GameplayMode_DelayedInit(entity this)
{
+ // at this stage team entities are spawned, teamplay contains the number of them
+
if(!scores_initialized)
ScoreRules_generic();
+
+ if (warmup_stage >= 0 && autocvar_g_maxplayers >= 0)
+ return;
+ if (!g_duel)
+ MapReadSizes(mapname);
+
+ if (autocvar_g_maxplayers < 0 && teamplay)
+ {
+ // automatic maxplayers should be a multiple of team count
+ if (map_maxplayers == 0 || map_maxplayers > maxclients)
+ map_maxplayers = maxclients; // unlimited, but may need rounding
+ int d = map_maxplayers % AVAILABLE_TEAMS;
+ int u = AVAILABLE_TEAMS - d;
+ map_maxplayers += (u <= d && u + map_maxplayers <= maxclients) ? u : -d;
+ }
+
+ if (warmup_stage < 0)
+ {
+ int m = GetPlayerLimit();
+ if (m <= 0) m = maxclients;
+ map_minplayers = bound(max(2, AVAILABLE_TEAMS * 2), map_minplayers, m);
+ if (teamplay)
+ {
+ // automatic minplayers should be a multiple of team count
+ int d = map_minplayers % AVAILABLE_TEAMS;
+ int u = AVAILABLE_TEAMS - d;
+ map_minplayers += (u < d && u + map_minplayers <= m) ? u : -d;
+ }
+ warmup_limit = -1;
+ }
+ else
+ map_minplayers = 0; // don't display a minimum if it's not used
}
void InitGameplayMode()
bool world_already_spawned;
spawnfunc(worldspawn)
{
+ cvar_set("_endmatch", "0");
server_is_dedicated = boolean(stof(cvar_defstring("is_dedicated")));
if (autocvar_sv_termsofservice_url && autocvar_sv_termsofservice_url != "")
GameRules_limit_fallbacks();
if(warmup_limit == 0)
- warmup_limit = (autocvar_timelimit > 0) ? autocvar_timelimit * 60 : autocvar_timelimit;
+ warmup_limit = autocvar_timelimit * 60;
player_count = 0;
bot_waypoints_for_items = autocvar_g_waypoints_for_items;
WaypointSprite_Init();
- GameLogInit(); // prepare everything
// NOTE for matchid:
// changing the logic generating it is okay. But:
// it HAS to stay <= 64 chars
// character set: ASCII 33-126 without the following characters: : ; ' " \ $
- if(autocvar_sv_eventlog)
- {
- string num = strftime_s(); // strftime(false, "%s") isn't reliable, see strftime_s description
- string s = sprintf("%s.%s.%06d", itos(autocvar_sv_eventlog_files_counter), num, floor(random() * 1000000));
- matchid = strzone(s);
-
- GameLogEcho(strcat(":gamestart:", GetGametype(), "_", GetMapname(), ":", s));
- s = ":gameinfo:mutators:LIST";
-
- MUTATOR_CALLHOOK(BuildMutatorsString, s);
- s = M_ARGV(0, string);
-
- // initialiation stuff, not good in the mutator system
- if(!autocvar_g_use_ammunition)
- s = strcat(s, ":no_use_ammunition");
+ // strftime(false, "%s") isn't reliable, see strftime_s description
+ matchid = strzone(sprintf("%d.%s.%06d", autocvar_sv_eventlog_files_counter, strftime_s(), random() * 1000000));
- // initialiation stuff, not good in the mutator system
- if(autocvar_g_pickup_items == 0)
- s = strcat(s, ":no_pickup_items");
- if(autocvar_g_pickup_items > 0)
- s = strcat(s, ":pickup_items");
-
- // initialiation stuff, not good in the mutator system
- if(autocvar_g_weaponarena != "0")
- s = strcat(s, ":", autocvar_g_weaponarena, " arena");
-
- // TODO to mutator system
- if(autocvar_g_norecoil)
- s = strcat(s, ":norecoil");
-
- GameLogEcho(s);
- GameLogEcho(":gameinfo:end");
- }
- else
- matchid = strzone(ftos(random()));
+ if(autocvar_sv_eventlog)
+ GameLogInit(); // requires matchid to be set
cvar_set("nextmap", "");
delete(this);
}
-bool MoveToRandomLocationWithinBounds(entity e, vector boundmin, vector boundmax, float goodcontents, float badcontents, float badsurfaceflags, int attempts, float maxaboveground, float minviewdistance)
+bool MoveToRandomLocationWithinBounds(entity e, vector boundmin, vector boundmax, float goodcontents, float badcontents, float badsurfaceflags, int attempts, float maxaboveground, float minviewdistance, bool frompos)
{
float m = e.dphitcontentsmask;
e.dphitcontentsmask = goodcontents | badcontents;
continue;
// rule 4: we must "see" some spawnpoint or item
- entity sp = NULL;
- IL_EACH(g_spawnpoints, checkpvs(mstart, it),
- {
- if((traceline(mstart, it.origin, MOVE_NORMAL, e), trace_fraction) >= 1)
- {
- sp = it;
- break;
- }
- });
+ entity sp = NULL;
+ if(frompos)
+ {
+ if((traceline(mstart, e.origin, MOVE_NORMAL, e), trace_fraction) >= 1)
+ sp = e;
+ }
+ if(!sp)
+ {
+ IL_EACH(g_spawnpoints, checkpvs(mstart, it),
+ {
+ if((traceline(mstart, it.origin, MOVE_NORMAL, e), trace_fraction) >= 1)
+ {
+ sp = it;
+ break;
+ }
+ });
+ }
if(!sp)
{
int items_checked = 0;
float MoveToRandomMapLocation(entity e, float goodcontents, float badcontents, float badsurfaceflags, float attempts, float maxaboveground, float minviewdistance)
{
- return MoveToRandomLocationWithinBounds(e, world.mins, world.maxs, goodcontents, badcontents, badsurfaceflags, attempts, maxaboveground, minviewdistance);
+ return MoveToRandomLocationWithinBounds(e, world.mins, world.maxs, goodcontents, badcontents, badsurfaceflags, attempts, maxaboveground, minviewdistance, false);
}
/*