#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");
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("sv_motd");
BADCVAR("sv_public");
BADCVAR("sv_showfps");
+ BADCVAR("sv_showspectators");
BADCVAR("sv_status_privacy");
BADCVAR("sv_taunt");
BADCVAR("sv_vote_call");
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
if(autocvar_g_campaign)
CampaignPreInit();
+ else
+ PlayerStats_GameReport_Init(); // we need this to be initiated before InitGameplayMode
Map_MarkAsRecent(mapname);
- PlayerStats_GameReport_Init(); // we need this to be initiated before InitGameplayMode
-
InitGameplayMode();
static_init_late();
static_init_precache();
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");
-
- // 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");
+ // 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));
- // 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);
}
/*
*/
void NextLevel()
{
+ cvar_set("_endmatch", "0");
game_stopped = true;
intermission_running = true; // game over
}
-float InitiateSuddenDeath()
+int InitiateSuddenDeath()
{
// Check first whether normal overtimes could be added before initiating suddendeath mode
// - for this timelimit_overtime needs to be >0 of course
if(!checkrules_suddendeathend)
{
if(autocvar_g_campaign)
+ {
checkrules_suddendeathend = time; // no suddendeath in campaign
+ }
else
+ {
checkrules_suddendeathend = time + 60 * autocvar_timelimit_suddendeath;
+ overtimes = -1;
+ }
if(g_race && !g_race_qualifying)
race_StartCompleting();
}
void InitiateOvertime() // ONLY call this if InitiateSuddenDeath returned true
{
++checkrules_overtimesadded;
+ overtimes = checkrules_overtimesadded;
//add one more overtime by simply extending the timelimit
cvar_set("timelimit", ftos(autocvar_timelimit + autocvar_timelimit_overtime));
Send_Notification(NOTIF_ALL, NULL, MSG_CENTER, CENTER_OVERTIME_TIME, autocvar_timelimit_overtime * 60);
leadlimit = 0; // no leadlimit for now
}
- if(timelimit > 0)
- {
- timelimit += game_starttime;
- }
- else if (timelimit < 0)
+ if (autocvar__endmatch || timelimit < 0)
{
// endmatch
NextLevel();
return;
}
- float wantovertime;
- wantovertime = 0;
+ if(timelimit > 0)
+ timelimit += game_starttime;
+
+ int overtimes_prev = overtimes;
+ int wantovertime = 0;
if(checkrules_suddendeathend)
{
Send_Notification(NOTIF_ALL, NULL, MSG_CENTER, CENTER_RACE_FINISHLAP);
else
Send_Notification(NOTIF_ALL, NULL, MSG_CENTER, CENTER_OVERTIME_FRAG);
- checkrules_overtimesadded = 1;
}
}
else
if(checkrules_status == WINNING_YES)
{
+ if (overtimes == -1 && overtimes != overtimes_prev)
+ {
+ // if suddendeathend overtime has just begun, revert it
+ checkrules_suddendeathend = 0;
+ overtimes = overtimes_prev;
+ }
//print("WINNING\n");
NextLevel();
}
else if (s == "all" || s == "1")
{
g_weaponarena = 1;
- g_weaponarena_list = "All Weapons";
+ g_weaponarena_list = "All Weapons Arena";
g_weaponarena_weapons = weapons_all();
}
else if (s == "devall")
{
g_weaponarena = 1;
- g_weaponarena_list = "Dev All Weapons";
+ g_weaponarena_list = "Dev All Weapons Arena";
g_weaponarena_weapons = weapons_devall();
}
else if (s == "most")
{
g_weaponarena = 1;
- g_weaponarena_list = "Most Weapons";
+ g_weaponarena_list = "Most Weapons Arena";
g_weaponarena_weapons = weapons_most();
}
else if (s == "all_available")
{
g_weaponarena = 1;
- g_weaponarena_list = "All Available Weapons";
+ g_weaponarena_list = "All Available Weapons Arena";
// this needs to run after weaponsInMapAll is initialized
InitializeEntity(NULL, weaponarena_available_all_update, INITPRIO_FINDTARGET);
else if (s == "devall_available")
{
g_weaponarena = 1;
- g_weaponarena_list = "Dev All Available Weapons";
+ g_weaponarena_list = "Dev All Available Weapons Arena";
// this needs to run after weaponsInMapAll is initialized
InitializeEntity(NULL, weaponarena_available_devall_update, INITPRIO_FINDTARGET);
else if (s == "most_available")
{
g_weaponarena = 1;
- g_weaponarena_list = "Most Available Weapons";
+ g_weaponarena_list = "Most Available Weapons Arena";
// this needs to run after weaponsInMapAll is initialized
InitializeEntity(NULL, weaponarena_available_most_update, INITPRIO_FINDTARGET);
else if (s == "none")
{
g_weaponarena = 1;
- g_weaponarena_list = "No Weapons";
+ g_weaponarena_list = "No Weapons Arena";
}
else
{
if(wep != WEP_Null)
{
g_weaponarena_weapons |= (wep.m_wepset);
- g_weaponarena_list = strcat(g_weaponarena_list, wep.m_name, " & ");
+ g_weaponarena_list = strcat(g_weaponarena_list, wep.netname, " & ");
}
}
- g_weaponarena_list = strzone(substring(g_weaponarena_list, 0, strlen(g_weaponarena_list) - 3));
+ if (g_weaponarena_list != "") // remove trailing " & "
+ g_weaponarena_list = substring(g_weaponarena_list, 0, strlen(g_weaponarena_list) - 3);
+ else // no valid weapon found
+ g_weaponarena_list = "No Weapons Arena";
}
if (g_weaponarena)
g_weapon_stay = 0; // incompatible
start_weapons = g_weaponarena_weapons;
start_items |= IT_UNLIMITED_AMMO | IT_UNLIMITED_SUPERWEAPONS;
+ g_weaponarena_list = strzone(g_weaponarena_list);
}
else
{
MUTATOR_CALLHOOK(ReadLevelCvars);
- if (!warmup_stage)
+ if (!warmup_stage && !autocvar_g_campaign)
game_starttime = time + cvar("g_start_delay");
FOREACH(Weapons, it != WEP_Null, { it.wr_init(it); });