alias sv_hook_gamestart_ft
alias sv_hook_gamestart_inv
alias sv_hook_gamestart_duel
+alias sv_hook_gamestart_tka
// there is currently no hook for when the match is restarted
// see sv_hook_readyrestart for previous uses of this hook
//alias sv_hook_gamerestart
alias sv_vote_gametype_hook_rc
alias sv_vote_gametype_hook_tdm
alias sv_vote_gametype_hook_duel
+alias sv_vote_gametype_hook_tka
// Example preset to allow 1v1ctf to be used for the gametype voting screen.
// Aliases can have max 31 chars so the gametype can have max 9 chars.
set g_duel_respawn_delay_max 0
set g_duel_respawn_waves 0
set g_duel_weapon_stay 0
+set g_tka_respawn_delay_small 0
+set g_tka_respawn_delay_small_count 0
+set g_tka_respawn_delay_large 0
+set g_tka_respawn_delay_large_count 0
+set g_tka_respawn_delay_max 0
+set g_tka_respawn_waves 0
+set g_tka_weapon_stay 0
// =========
set g_ca_point_leadlimit -1 "Clan Arena point lead limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
set g_ca_spectate_enemies 0 "allow eliminated players to spectate enemy players during Clan Arena games"
set g_ca_warmup 10 "time players get to run around before the round starts"
- set g_ca_damage2score_multiplier 0.01
+ set g_ca_damage2score 100 "every this amount of damage done give players 1 point"
set g_ca_round_timelimit 180 "round time limit in seconds"
set g_ca_teams_override 0
set g_ca_team_spawns 0 "when 1, players spawn from the team spawnpoints of the map, if any"
set g_lms 0 "Last Man Standing: everyone starts with a certain amount of lives, and the survivor wins"
set g_lms_lives_override -1
set g_lms_extra_lives 0
- set g_lms_regenerate 0
+ set g_lms_regenerate 0 "health and/or armor regeneration, according to g_balance_health_regen and g_balance_armor_regen"
+ set g_lms_rot 0 "health and/or armor rotting, according to g_balance_health_rot and g_balance_armor_rot"
set g_lms_last_join 3 "if g_lms_join_anytime is 0, new players can only join if the worst active player has (fraglimit - g_lms_last_join) or more lives; in other words, new players can no longer join once the worst player loses more than g_lms_last_join lives"
set g_lms_join_anytime 1 "1: new players can join, but get same amount of lives as the worst player; 0: new players can only join if the worst active player has (fraglimit - g_lms_last_join) or more lives"
+ set g_lms_items 0 "enables items to spawn, weaponarena still disables weapons and ammo (to force all items to spawn, use g_pickup_items 1 instead)"
set g_lms_weaponarena "most_available" "starting weapons - takes the same options as g_weaponarena"
+ set g_lms_forfeit_min_match_time 30 "end the match early if at least this many seconds have elapsed and less than 2 players are playing due to forfeits"
// =========
//set g_duel_warmup 180 "Have a short warmup period before beginning the actual duel"
set g_duel_with_powerups 0 "Enable powerups to spawn in the duel gamemode"
set g_duel_not_dm_maps 0 "when this is set, DM maps will NOT be listed in duel"
+
+// ===============
+// team keepaway
+// ===============
+set g_tka 0 "another game mode which focuses around a ball"
+set g_tka_on_dm_maps 0 "when this is set, all DM and KA maps automatically support TKA"
+set g_tka_teams 2 "how many teams are in team keepaway (set by mapinfo)"
+set g_tka_team_spawns 0 "when 1, players spawn from the team spawnpoints of the map, if any"
+set g_tka_teams_override 0 "how many teams are in team keepaway"
+set g_tka_point_limit -1 "TKA point limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
+set g_tka_point_leadlimit -1 "TKA point lead limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
+set g_tka_score_team 1 "allow points to be awarded to teammates for any kill when the ball is in your team's possession"
+set g_tka_score_bckill 1 "points for killing the ball barrier (Ball Carrier Kill)"
+set g_tka_score_killac 1 "points for kills while holding the ball (Kill As Carrier)"
+set g_tka_score_timeinterval 1 "amount of time it takes between intervals for timepoints to be added to the score"
+set g_tka_score_timepoints 0 "points to add to score per timeinterval, 0 for no points"
+set g_tka_ballcarrier_effects 8 "Add together the numbers you want: EF_ADDITIVE (32) / EF_NODEPTHTEST (8192) / EF_DIMLIGHT (8)"
+set g_tka_ballcarrier_highspeed 1 "speed multiplier done to the person holding the ball (recommended when used with some mutators)"
+set g_tka_ballcarrier_damage 1 "damage multiplier while holding the ball"
+set g_tka_ballcarrier_force 1 "force multiplier while holding the ball"
+set g_tka_ballcarrier_selfdamage 1 "self damage multiplier while holding the ball"
+set g_tka_ballcarrier_selfforce 1 "self force multiplier while holding the ball"
+set g_tka_noncarrier_warn 1 "warn players when they kill without holding the ball"
+set g_tka_noncarrier_damage 1 "damage done to other players if both you and they don't have the ball"
+set g_tka_noncarrier_force 1 "force done to other players if both you and they don't have the ball"
+set g_tka_noncarrier_selfdamage 1 "self damage if you don't have the ball"
+set g_tka_noncarrier_selfforce 1 "self force if you don't have the ball"
+set g_tkaball_effects 0 "Add together the numbers you want: EF_ADDITIVE (32) / EF_NODEPTHTEST (8192) / EF_DIMLIGHT (8)"
+set g_tkaball_trail_color 254 "particle trail color from player/ball"
+set g_tkaball_damageforcescale 3 "Scale of force which is applied to the ball by weapons/explosions/etc"
+set g_tkaball_respawntime 10 "if no one picks up the ball, how long to wait until the ball respawns"
float game_starttime; //point in time when the countdown to game start is over
float round_starttime; //point in time when the countdown to round start is over
int autocvar_leadlimit;
+ int overtimes; // overtimes added (-1 = sudden death)
+ int timeout_status; // (values: 0, 1, 2) contains whether a timeout is not active (0), was called but still at leadtime (1) or is active (2)
+
// TODO: world.qh can't be included here due to circular includes!
#define autocvar_fraglimit cvar("fraglimit")
#define autocvar_fraglimit_override cvar("fraglimit_override")
/** arc heat in [0,1] */
REGISTER_STAT(PRESSED_KEYS, int)
REGISTER_STAT(FUEL, int)
- REGISTER_STAT(NB_METERSTART, float)
/** compressShotOrigin */
REGISTER_STAT(SHOTORG, int)
REGISTER_STAT(LEADLIMIT, float, autocvar_leadlimit)
REGISTER_STAT(LAST_PICKUP, float)
REGISTER_STAT(HUD, int)
REGISTER_STAT(HIT_TIME, float)
- REGISTER_STAT(DAMAGE_DEALT_TOTAL, int)
+ REGISTER_STAT(HITSOUND_DAMAGE_DEALT_TOTAL, int)
REGISTER_STAT(TYPEHIT_TIME, float)
REGISTER_STAT(AIR_FINISHED, float)
REGISTER_STAT(VEHICLESTAT_HEALTH, int)
REGISTER_STAT(SECRETS_FOUND, int, secrets_found)
REGISTER_STAT(RESPAWN_TIME, float)
REGISTER_STAT(ROUNDSTARTTIME, float, round_starttime)
+ REGISTER_STAT(OVERTIMES, int, overtimes)
+ REGISTER_STAT(TIMEOUT_STATUS, int, timeout_status)
REGISTER_STAT(MONSTERS_TOTAL, int)
REGISTER_STAT(MONSTERS_KILLED, int)
REGISTER_STAT(NADE_BONUS, float)
REGISTER_STAT(KILL_TIME, float)
REGISTER_STAT(VEIL_ORB, float)
REGISTER_STAT(VEIL_ORB_ALPHA, float)
+REGISTER_STAT(TKA_BALLSTATUS, int)
#ifdef SVQC
float autocvar_sv_showfps = 0;
REGISTER_STAT(DOM_PPS_YELLOW, float)
REGISTER_STAT(DOM_PPS_PINK, float)
+ // nexball
+ REGISTER_STAT(NB_METERSTART, float)
+
#ifdef SVQC
float autocvar_g_teleport_maxspeed;
#endif
#ifdef SVQC
#include "physics/movetypes/movetypes.qh"
float warmup_limit;
+ float round_limit;
+ int rounds_played;
#endif
#ifdef SVQC
REGISTER_STAT(FRAGLIMIT, float, autocvar_fraglimit)
REGISTER_STAT(TIMELIMIT, float, autocvar_timelimit)
REGISTER_STAT(WARMUP_TIMELIMIT, float, warmup_limit)
+ REGISTER_STAT(ROUNDS_PLAYED, int, rounds_played)
+ REGISTER_STAT(ROUND_TIMELIMIT, float, round_limit)
#ifdef SVQC
float autocvar_sv_wallfriction;
#define autocvar_sv_gravity cvar("sv_gravity")
BADCVAR("g_tdm");
BADCVAR("g_tdm_on_dm_maps");
BADCVAR("g_tdm_teams");
+ BADCVAR("g_tka");
+ BADCVAR("g_tka_on_dm_maps");
+ BADCVAR("g_tka_teams");
BADCVAR("g_vip");
BADCVAR("leadlimit");
BADCVAR("nextmap");
BADCVAR("g_physics_clientselect");
BADCVAR("g_pinata");
BADCVAR("g_powerups");
+ BADCVAR("g_powerups_drop_ondeath");
BADCVAR("g_player_brightness");
BADCVAR("g_rocket_flying");
BADCVAR("g_rocket_flying_disabledelays");
BADCVAR("sv_maxrate");
BADCVAR("sv_motd");
BADCVAR("sv_public");
- BADCVAR("sv_ready_restart");
BADCVAR("sv_showfps");
+ BADCVAR("sv_showspectators");
BADCVAR("sv_status_privacy");
BADCVAR("sv_taunt");
BADCVAR("sv_vote_call");
{
server_is_dedicated = boolean(stof(cvar_defstring("is_dedicated")));
+ if (autocvar_sv_termsofservice_url && autocvar_sv_termsofservice_url != "")
+ {
+ strcpy(sv_termsofservice_url_escaped, strreplace(":", "|", autocvar_sv_termsofservice_url));
+ }
+ else
+ {
+ strcpy(sv_termsofservice_url_escaped, "INVALID");
+ }
+
bool wantrestart = false;
{
if (!server_is_dedicated)
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();
FOREACH_CLIENT(IS_REAL_CLIENT(it) || (IS_BOT_CLIENT(it) && autocvar_sv_logscores_bots), {
s = strcat(":player:see-labels:", GetPlayerScoreString(it, 0), ":");
s = strcat(s, ftos(rint(time - CS(it).jointime)), ":");
- if(IS_PLAYER(it) || MUTATOR_CALLHOOK(GetPlayerStatus, it))
+ if(IS_PLAYER(it) || INGAME_JOINED(it))
s = strcat(s, ftos(it.team), ":");
else
s = strcat(s, "spectator:");
*/
void NextLevel()
{
+ cvar_set("_endmatch", "0");
game_stopped = true;
intermission_running = true; // game over
GameLogClose();
- FOREACH_CLIENT(IS_PLAYER(it), {
+ int winner_team = 0;
+ FOREACH_CLIENT(IS_PLAYER(it) || INGAME(it), {
FixIntermissionClient(it);
if(it.winning)
- bprint(playername(it.netname, it.team, false), " ^7wins.\n");
+ {
+ if (teamplay && !winner_team)
+ {
+ winner_team = it.team;
+ bprint(Team_ColorCode(winner_team), Team_ColorName_Upper(winner_team), "^7 team wins the match\n");
+ }
+ bprint(playername(it.netname, it.team, false), " ^7wins\n");
+ }
});
target_music_kill();
}
- 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);
// set the .winning flag for exactly those players with a given field value
void SetWinners(.float field, float value)
{
- FOREACH_CLIENT(IS_PLAYER(it), { it.winning = (it.(field) == value); });
+ FOREACH_CLIENT(IS_PLAYER(it) || INGAME(it), { it.winning = (it.(field) == value); });
}
// set the .winning flag for those players with a given field value
void AddWinners(.float field, float value)
{
- FOREACH_CLIENT(IS_PLAYER(it), {
+ FOREACH_CLIENT(IS_PLAYER(it) || INGAME(it), {
if(it.(field) == value)
it.winning = 1;
});
// clear the .winning flags
void ClearWinners()
{
- FOREACH_CLIENT(IS_PLAYER(it), { it.winning = 0; });
+ FOREACH_CLIENT(IS_PLAYER(it) || INGAME(it), { it.winning = 0; });
}
int fragsleft_last;
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)
{
if(readyplayers || playerswithlaps >= 2)
{
checkrules_suddendeathend = 0;
- ReadyRestart(); // go to race
+ ReadyRestart(true); // go to race
return;
}
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); });
STAT(TYPEHIT_TIME, it) = time;
} else if (e.killsound) {
STAT(KILL_TIME, it) = time;
- } else if (e.damage_dealt) {
+ } else if (e.hitsound_damage_dealt) {
STAT(HIT_TIME, it) = time;
- STAT(DAMAGE_DEALT_TOTAL, it) += ceil(e.damage_dealt);
+ // NOTE: this is not accurate as client code doesn't need so much accuracy for its purposes
+ STAT(HITSOUND_DAMAGE_DEALT_TOTAL, it) += ceil(e.hitsound_damage_dealt);
}
});
// add 1 frametime because after this, engine SV_Physics
float altime = time + frametime * (1 + autocvar_g_antilag_nudge);
FOREACH_CLIENT(true, {
it.typehitsound = false;
- it.damage_dealt = 0;
+ it.hitsound_damage_dealt = 0;
it.killsound = false;
antilag_record(it, CS(it), altime);
});
WeaponStats_Shutdown();
MapInfo_Shutdown();
+
+ strfree(sv_termsofservice_url_escaped);
}
else if(world_initialized == 0)
{