set g_spawn_furthest 1 "this amount of the spawns shall be far away from any players"
set g_spawn_useallspawns 0 "use all spawns, e.g. also team spawns in non-teamplay, and all spawns, even enemy spawns, in teamplay"
// respawn delay
-set g_respawn_delay 2 "number of seconds you have to wait before you can respawn again"
+set g_respawn_delay_small 2 "small game number of seconds you have to wait before you can respawn again"
+set g_respawn_delay_small_count 0 "Player count per team for g_respawn_delay_small. <=0 values mean the minimum amount of players to have gameplay (typically 2 in FFA, 1 in teamplay)."
+set g_respawn_delay_large 2 "large game number of seconds you have to wait before you can respawn again"
+set g_respawn_delay_large_count 8 "Player count per team for g_respawn_delay_large. <=0 values mean the minimum amount of players to have gameplay (typically 2 in FFA, 1 in teamplay)."
set g_respawn_delay_max 0 "number of seconds you can wait before you're forced to respawn (only effective with g_forced_respawn 1)"
set g_respawn_waves 0 "respawn in waves (every n seconds), intended to decrease overwhelming base attacks"
// =================================
// respawn delay/waves/weapon_stay
// =================================
-// when variables are set to anything other than 0, they take over the global setting...
+// when variables are set to anything other than 0, they take over the global setting. Negative values force an output value of zero.
// to force disable delay or waves, set them to 0.125
-set g_ctf_respawn_delay 5
+set g_ctf_respawn_delay_small 5
+set g_ctf_respawn_delay_small_count 0
+set g_ctf_respawn_delay_large 5
+set g_ctf_respawn_delay_large_count 0
+set g_ctf_respawn_delay_max 0
set g_ctf_respawn_waves 0
set g_ctf_weapon_stay 0
-set g_dm_respawn_delay 0
+set g_dm_respawn_delay_small 0
+set g_dm_respawn_delay_small_count 0
+set g_dm_respawn_delay_large 0
+set g_dm_respawn_delay_large_count 0
+set g_dm_respawn_delay_max 0
set g_dm_respawn_waves 0
set g_dm_weapon_stay 0
-set g_dom_respawn_delay 0
+set g_dom_respawn_delay_small 0
+set g_dom_respawn_delay_small_count 0
+set g_dom_respawn_delay_large 0
+set g_dom_respawn_delay_large_count 0
+set g_dom_respawn_delay_max 0
set g_dom_respawn_waves 0
set g_dom_weapon_stay 0
-set g_lms_respawn_delay 0
+set g_lms_respawn_delay_small 0
+set g_lms_respawn_delay_small_count 0
+set g_lms_respawn_delay_large 0
+set g_lms_respawn_delay_large_count 0
+set g_lms_respawn_delay_max 0
set g_lms_respawn_waves 0
set g_lms_weapon_stay 0
-set g_tdm_respawn_delay 0
+set g_tdm_respawn_delay_small 0
+set g_tdm_respawn_delay_small_count 0
+set g_tdm_respawn_delay_large 0
+set g_tdm_respawn_delay_large_count 0
+set g_tdm_respawn_delay_max 0
set g_tdm_respawn_waves 0
set g_tdm_weapon_stay 0
-set g_ka_respawn_delay 0
+set g_ka_respawn_delay_small 0
+set g_ka_respawn_delay_small_count 0
+set g_ka_respawn_delay_large 0
+set g_ka_respawn_delay_large_count 0
+set g_ka_respawn_delay_max 0
set g_ka_respawn_waves 0
set g_ka_weapon_stay 0
-set g_kh_respawn_delay 0
+set g_kh_respawn_delay_small 0
+set g_kh_respawn_delay_small_count 0
+set g_kh_respawn_delay_large 0
+set g_kh_respawn_delay_large_count 0
+set g_kh_respawn_delay_max 0
set g_kh_respawn_waves 0
set g_kh_weapon_stay 0
-set g_ca_respawn_delay 0
+set g_ca_respawn_delay_small 0
+set g_ca_respawn_delay_small_count 0
+set g_ca_respawn_delay_large 0
+set g_ca_respawn_delay_large_count 0
+set g_ca_respawn_delay_max 0
set g_ca_respawn_waves 0
set g_ca_weapon_stay 0
-set g_nb_respawn_delay 0
+set g_nb_respawn_delay_small 0
+set g_nb_respawn_delay_small_count 0
+set g_nb_respawn_delay_large 0
+set g_nb_respawn_delay_large_count 0
+set g_nb_respawn_delay_max 0
set g_nb_respawn_waves 0
set g_nb_weapon_stay 0
-set g_as_respawn_delay 0
+set g_as_respawn_delay_small 0
+set g_as_respawn_delay_small_count 0
+set g_as_respawn_delay_large 0
+set g_as_respawn_delay_large_count 0
+set g_as_respawn_delay_max 0
set g_as_respawn_waves 0
set g_as_weapon_stay 0
-set g_ons_respawn_delay 0
+set g_ons_respawn_delay_small 0
+set g_ons_respawn_delay_small_count 0
+set g_ons_respawn_delay_large 0
+set g_ons_respawn_delay_large_count 0
+set g_ons_respawn_delay_max 0
set g_ons_respawn_waves 0
set g_ons_weapon_stay 0
+set g_rc_respawn_delay_small 0
+set g_rc_respawn_delay_small_count 0
+set g_rc_respawn_delay_large 0
+set g_rc_respawn_delay_large_count 0
+set g_rc_respawn_delay_max 0
set g_rc_respawn_waves 0
-set g_rc_respawn_delay 0
set g_rc_weapon_stay 0
+set g_cts_respawn_delay_small -1 // CTS shall have instant respawn.
+set g_cts_respawn_delay_small_count 0
+set g_cts_respawn_delay_large -1 // CTS shall have instant respawn.
+set g_cts_respawn_delay_large_count 0
+set g_cts_respawn_delay_max 0
set g_cts_respawn_waves 0
-set g_cts_respawn_delay 0
set g_cts_weapon_stay 2
+set g_ft_respawn_delay_small 0
+set g_ft_respawn_delay_small_count 0
+set g_ft_respawn_delay_large 0
+set g_ft_respawn_delay_large_count 0
+set g_ft_respawn_delay_max 0
set g_ft_respawn_waves 0
-set g_ft_respawn_delay 0
set g_ft_weapon_stay 0
+set g_inv_respawn_delay_small 0
+set g_inv_respawn_delay_small_count 0
+set g_inv_respawn_delay_large 0
+set g_inv_respawn_delay_large_count 0
+set g_inv_respawn_delay_max 0
set g_inv_respawn_waves 0
-set g_inv_respawn_delay 0
set g_inv_weapon_stay 0
float autocvar_g_domination_point_rate;
float autocvar_g_domination_teams_override;
float autocvar_g_forced_respawn;
-float autocvar_g_respawn_delay_max;
string autocvar_g_forced_team_blue;
string autocvar_g_forced_team_otherwise;
string autocvar_g_forced_team_pink;
float autocvar_g_race_qualifying_timelimit;
float autocvar_g_race_qualifying_timelimit_override;
float autocvar_g_race_teams;
-float autocvar_g_respawn_delay;
+float autocvar_g_respawn_delay_small;
+float autocvar_g_respawn_delay_small_count;
+float autocvar_g_respawn_delay_large;
+float autocvar_g_respawn_delay_large_count;
+float autocvar_g_respawn_delay_max;
float autocvar_g_respawn_ghosts;
float autocvar_g_respawn_ghosts_maxtime;
float autocvar_g_respawn_ghosts_speed;
}
}
+// g_<gametype>_str:
+// If 0, default is used.
+// If <0, 0 is used.
+// Otherwise, g_str (default value) is used.
+// For consistency, negative values there are mapped to zero too.
+#define GAMETYPE_DEFAULTED_SETTING(str) \
+ ((gametype_setting_tmp = cvar(strcat("g_", GetGametype(), "_" #str))), \
+ (gametype_setting_tmp < 0) ? 0 : \
+ (gametype_setting_tmp == 0) ? max(0, autocvar_g_##str) : \
+ gametype_setting_tmp)
+
+
+void calculate_player_respawn_time()
+{
+ float gametype_setting_tmp;
+ float sdelay_max = GAMETYPE_DEFAULTED_SETTING(respawn_delay_max);
+ float sdelay_small = GAMETYPE_DEFAULTED_SETTING(respawn_delay_small);
+ float sdelay_large = GAMETYPE_DEFAULTED_SETTING(respawn_delay_large);
+ float sdelay_small_count = GAMETYPE_DEFAULTED_SETTING(respawn_delay_small_count);
+ float sdelay_large_count = GAMETYPE_DEFAULTED_SETTING(respawn_delay_large_count);
+ float waves = GAMETYPE_DEFAULTED_SETTING(respawn_waves);
+
+ float pcount = 1; // Include myself whether or not team is already set right and I'm a "player".
+ entity pl;
+ if (teamplay)
+ {
+ FOR_EACH_PLAYER(pl)
+ if (pl != self)
+ if (pl.team == self.team)
+ ++pcount;
+ if (sdelay_small_count == 0)
+ sdelay_small_count = 1;
+ if (sdelay_large_count == 0)
+ sdelay_large_count = 1;
+ }
+ else
+ {
+ FOR_EACH_PLAYER(pl)
+ if (pl != self)
+ ++pcount;
+ if (sdelay_small_count == 0)
+ {
+ if (g_cts)
+ {
+ // Players play independently. No point in requiring enemies.
+ sdelay_small_count = 1;
+ }
+ else
+ {
+ // Players play AGAINST each other. Enemies required.
+ sdelay_small_count = 2;
+ }
+ }
+ if (sdelay_large_count == 0)
+ {
+ if (g_cts)
+ {
+ // Players play independently. No point in requiring enemies.
+ sdelay_large_count = 1;
+ }
+ else
+ {
+ // Players play AGAINST each other. Enemies required.
+ sdelay_large_count = 2;
+ }
+ }
+ }
+
+ float sdelay;
+
+ if (pcount <= sdelay_small_count)
+ sdelay = sdelay_small;
+ else if (pcount >= sdelay_large_count)
+ sdelay = sdelay_large;
+ else // NOTE: this case implies sdelay_large_count > sdelay_small_count.
+ sdelay = sdelay_small + (sdelay_large - sdelay_small) * (pcount - sdelay_small_count) / (sdelay_large_count - sdelay_small_count);
+
+ if(waves)
+ self.respawn_time = ceil((time + sdelay) / waves) * waves;
+ else
+ self.respawn_time = time + sdelay;
+
+ if(sdelay < sdelay_max)
+ self.respawn_time_max = time + sdelay_max;
+ else
+ self.respawn_time_max = self.respawn_time;
+
+ if((sdelay + waves >= 5.0) && (self.respawn_time - time > 1.75))
+ self.respawn_countdown = 10; // first number to count down from is 10
+ else
+ self.respawn_countdown = -1; // do not count down
+
+ if(g_cts || autocvar_g_forced_respawn)
+ self.respawn_flags = self.respawn_flags | RESPAWN_FORCE;
+}
+
void ClientKill_Now_TeamChange();
void PlayerDamage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
{
- float take, save, waves, sdelay, dh, da, j;
+ float take, save, dh, da, j;
vector v;
float valid_damage_for_weaponstats;
float excess;
// dying animation
self.deadflag = DEAD_DYING;
// when to allow respawn
- sdelay = 0;
- waves = 0;
- sdelay = cvar(strcat("g_", GetGametype(), "_respawn_delay"));
- if(!sdelay)
- {
- if(g_cts)
- sdelay = 0; // no respawn delay in CTS
- else
- sdelay = autocvar_g_respawn_delay;
- }
- waves = cvar(strcat("g_", GetGametype(), "_respawn_waves"));
- if(!waves)
- waves = autocvar_g_respawn_waves;
- if(waves)
- self.respawn_time = ceil((time + sdelay) / waves) * waves;
- else
- self.respawn_time = time + sdelay;
- if(autocvar_g_respawn_delay_max > sdelay)
- self.respawn_time_max = time + autocvar_g_respawn_delay_max;
- else
- self.respawn_time_max = self.respawn_time;
- if((sdelay + waves >= 5.0) && (self.respawn_time - time > 1.75))
- self.respawn_countdown = 10; // first number to count down from is 10
- else
- self.respawn_countdown = -1; // do not count down
-
- if(g_cts || autocvar_g_forced_respawn)
- self.respawn_flags = self.respawn_flags | RESPAWN_FORCE;
+ calculate_player_respawn_time();
self.death_time = time;
if (random() < 0.5)