Xonotic QuakeC
The free, fast arena FPS with crisp movement and a wide array of weapons
sv_freezetag.qc File Reference
Include dependency graph for sv_freezetag.qc:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define IN_REVIVING_RANGE(player, it, revive_extra_size)

Functions

void freezetag_Add_Score (entity targ, entity attacker)
bool freezetag_CheckTeams ()
bool freezetag_CheckWinner ()
void freezetag_count_alive_players ()
void freezetag_Freeze (entity targ, entity attacker)
void freezetag_Ice_Think (entity this)
void freezetag_Initialize ()
bool freezetag_isEliminated (entity e)
entity freezetag_LastPlayerForTeam (entity this)
void freezetag_LastPlayerForTeam_Notify (entity this)
void freezetag_Unfreeze (entity targ, bool reset_health)
void ft_RemovePlayer (entity this)
void havocbot_goalrating_ft_freeplayers (entity this, float ratingscale, vector org, float sradius)
void havocbot_role_ft_freeing (entity this)
void havocbot_role_ft_offense (entity this)
 MUTATOR_HOOKFUNCTION (ft, AccuracyTargetValid)
 MUTATOR_HOOKFUNCTION (ft, AllowMobSpawning)
 MUTATOR_HOOKFUNCTION (ft, BotShouldAttack)
 MUTATOR_HOOKFUNCTION (ft, BuffTouch)
 MUTATOR_HOOKFUNCTION (ft, ClientDisconnect)
 MUTATOR_HOOKFUNCTION (ft, ClientKill)
 MUTATOR_HOOKFUNCTION (ft, Damage_Calculate)
 MUTATOR_HOOKFUNCTION (ft, FragCenterMessage)
 MUTATOR_HOOKFUNCTION (ft, GiveFragsForKill, CBC_ORDER_FIRST)
 MUTATOR_HOOKFUNCTION (ft, HavocBot_ChooseRole)
 MUTATOR_HOOKFUNCTION (ft, ItemTouch)
 MUTATOR_HOOKFUNCTION (ft, LockWeapon)
 MUTATOR_HOOKFUNCTION (ft, MakePlayerObserver)
 MUTATOR_HOOKFUNCTION (ft, MonsterValidTarget)
 MUTATOR_HOOKFUNCTION (ft, PlayerAnim)
 MUTATOR_HOOKFUNCTION (ft, PlayerDamaged)
 MUTATOR_HOOKFUNCTION (ft, PlayerDied)
 MUTATOR_HOOKFUNCTION (ft, PlayerDies)
 MUTATOR_HOOKFUNCTION (ft, PlayerPreThink, CBC_ORDER_FIRST)
 MUTATOR_HOOKFUNCTION (ft, PlayerRegen)
 MUTATOR_HOOKFUNCTION (ft, PlayerSpawn)
 MUTATOR_HOOKFUNCTION (ft, PutClientInServer)
 MUTATOR_HOOKFUNCTION (ft, reset_map_global)
 MUTATOR_HOOKFUNCTION (ft, reset_map_players)
 MUTATOR_HOOKFUNCTION (ft, Scores_CountFragsRemaining)
 MUTATOR_HOOKFUNCTION (ft, SetStartItems)
 MUTATOR_HOOKFUNCTION (ft, SetWeaponArena)
 MUTATOR_HOOKFUNCTION (ft, SpectateCopy)
 MUTATOR_HOOKFUNCTION (ft, SV_ParseServerCommand)
 MUTATOR_HOOKFUNCTION (ft, TeamBalance_CheckAllowedTeams, CBC_ORDER_EXCLUSIVE)
 MUTATOR_HOOKFUNCTION (ft, TurretValidateTarget)
 void (entity this) havocbot_role_ft_freeing

Variables

float autocvar_g_freezetag_frozen_maxtime
float autocvar_g_freezetag_revive_clearspeed
float autocvar_g_freezetag_round_enddelay
float autocvar_g_freezetag_round_timelimit
int autocvar_g_freezetag_teams_override
float autocvar_g_freezetag_warmup
float autocvar_g_ft_start_ammo_cells = 180
float autocvar_g_ft_start_ammo_fuel = 0
float autocvar_g_ft_start_ammo_nails = 320
float autocvar_g_ft_start_ammo_rockets = 160
float autocvar_g_ft_start_ammo_shells = 60
float autocvar_g_ft_start_armor = 100
float autocvar_g_ft_start_health = 100

Macro Definition Documentation

◆ IN_REVIVING_RANGE

#define IN_REVIVING_RANGE ( player,
it,
revive_extra_size )
Value:
(it != player && !IS_DEAD(it) && SAME_TEAM(it, player) \
&& boxesoverlap(player.absmin - revive_extra_size, player.absmax + revive_extra_size, it.absmin, it.absmax))
#define IS_DEAD(s)
Definition player.qh:245
#define SAME_TEAM(a, b)
Definition teams.qh:241
ERASEABLE float boxesoverlap(vector m1, vector m2, vector m3, vector m4)
requires that m2>m1 in all coordinates, and that m4>m3
Definition vector.qh:73

Definition at line 713 of file sv_freezetag.qc.

713#define IN_REVIVING_RANGE(player, it, revive_extra_size) \
714 (it != player && !IS_DEAD(it) && SAME_TEAM(it, player) \
715 && boxesoverlap(player.absmin - revive_extra_size, player.absmax + revive_extra_size, it.absmin, it.absmax))

Referenced by MUTATOR_HOOKFUNCTION().

Function Documentation

◆ freezetag_Add_Score()

void freezetag_Add_Score ( entity targ,
entity attacker )

Definition at line 162 of file sv_freezetag.qc.

163{
164 if(attacker == targ)
165 {
166 // you froze your own dumb self
167 // counted as "suicide" already
168 GameRules_scoring_add(targ, SCORE, -1);
169 }
170 else if(IS_PLAYER(attacker))
171 {
172 // got frozen by an enemy
173 // counted as "kill" and "death" already
174 if(SAME_TEAM(attacker, targ))
175 GameRules_scoring_add(attacker, SCORE, -1);
176 else
177 GameRules_scoring_add(attacker, SCORE, +1);
178 GameRules_scoring_add(targ, SCORE, -1);
179 }
180 // else nothing - got frozen by the gametype rules themselves
181}
#define IS_PLAYER(s)
Definition player.qh:243
#define GameRules_scoring_add(client, fld, value)
Definition sv_rules.qh:85

References entity(), GameRules_scoring_add, IS_PLAYER, and SAME_TEAM.

Referenced by freezetag_Freeze(), and MUTATOR_HOOKFUNCTION().

◆ freezetag_CheckTeams()

bool freezetag_CheckTeams ( )

Definition at line 52 of file sv_freezetag.qc.

53{
54 static float prev_missing_teams_mask;
57 return true;
58 if(total_players == 0)
59 return false;
60 for (int i = 1; i <= NUM_TEAMS; ++i)
61 {
64 {
66 }
67 }
68 if(prev_missing_teams_mask != missing_teams_mask)
69 prev_missing_teams_mask = missing_teams_mask;
70 return false;
71}
int missing_teams_mask
Definition stats.qh:85
int NumTeams(int teams)
float freezetag_teams
int total_players
Definition sv_rules.qh:12
int Team_GetNumberOfAlivePlayers(entity team_ent)
Returns the number of alive players in a team.
Definition teamplay.qc:85
int Team_GetNumberOfAliveTeams()
Returns the number of alive teams.
Definition teamplay.qc:110
entity Team_GetTeamFromIndex(int index)
Returns the global team entity at the given index.
Definition teamplay.qc:57
const int NUM_TEAMS
Number of teams in the game.
Definition teams.qh:3
int Team_IndexToBit(int index)
Converts team index into bit value that is used in team bitmasks.
Definition teams.qh:211

References freezetag_teams, missing_teams_mask, NUM_TEAMS, NumTeams(), Team_GetNumberOfAlivePlayers(), Team_GetNumberOfAliveTeams(), Team_GetTeamFromIndex(), Team_IndexToBit(), and total_players.

Referenced by freezetag_Initialize().

◆ freezetag_CheckWinner()

bool freezetag_CheckWinner ( )

Definition at line 73 of file sv_freezetag.qc.

74{
77 {
78 Send_Notification(NOTIF_ALL, NULL, MSG_CENTER, CENTER_ROUND_OVER);
79 Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_ROUND_OVER);
81 it.freezetag_frozen_timeout = 0;
82 it.freezetag_revive_time = 0;
84 });
85 game_stopped = true;
87 return true;
88 }
89
90 int winner_team = Team_GetWinnerAliveTeam();
91 if (!winner_team)
92 {
94 return false;
95 }
96
97 // delay round ending a bit
100 && round_handler_GetEndTime() - time > 0) // don't delay past timelimit
101 {
103 {
105 return 0;
106 }
108 {
109 return 0;
110 }
111 }
112
113 if(winner_team > 0)
114 {
115 Send_Notification(NOTIF_ALL, NULL, MSG_CENTER, APP_TEAM_NUM(winner_team, CENTER_ROUND_TEAM_WIN));
116 Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(winner_team, INFO_ROUND_TEAM_WIN));
117 TeamScore_AddToTeam(winner_team, ST_FT_ROUNDS, +1);
118 }
119 else if(winner_team == -1)
120 {
121 Send_Notification(NOTIF_ALL, NULL, MSG_CENTER, CENTER_ROUND_TIED);
122 Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_ROUND_TIED);
123 }
124
126 it.freezetag_frozen_timeout = 0;
127 it.freezetag_revive_time = 0;
129 });
130
131 game_stopped = true;
133 return true;
134}
float game_stopped
Definition stats.qh:81
float time
float min(float f,...)
void Send_Notification(NOTIF broadcast, entity client, MSG net_type, Notification net_name,...count)
Definition all.qc:1573
#define APP_TEAM_NUM(num, prefix)
Definition all.qh:84
#define NULL
Definition post.qh:14
void round_handler_Init(float the_delay, float the_count, float the_round_timelimit)
#define round_handler_GetEndTime()
#define round_handler_SetEndDelayTime(t)
#define round_handler_GetEndDelayTime()
#define round_handler_ResetEndDelayTime()
float TeamScore_AddToTeam(int t, float scorefield, float score)
Adds a score to the given team.
Definition scores.qc:107
float autocvar_g_freezetag_round_enddelay
float autocvar_g_freezetag_warmup
float autocvar_g_freezetag_round_timelimit
const int ST_FT_ROUNDS
void nades_RemovePlayer(entity this)
Definition sv_nades.qc:885
int Team_GetWinnerAliveTeam()
Returns the winner team.
Definition teamplay.qc:95
#define FOREACH_CLIENT(cond, body)
Definition utils.qh:50

References APP_TEAM_NUM, autocvar_g_freezetag_round_enddelay, autocvar_g_freezetag_round_timelimit, autocvar_g_freezetag_warmup, FOREACH_CLIENT, game_stopped, IS_PLAYER, min(), nades_RemovePlayer(), NULL, round_handler_GetEndDelayTime, round_handler_GetEndTime, round_handler_Init(), round_handler_ResetEndDelayTime, round_handler_SetEndDelayTime, Send_Notification(), ST_FT_ROUNDS, Team_GetWinnerAliveTeam(), TeamScore_AddToTeam(), and time.

Referenced by freezetag_Initialize().

◆ freezetag_count_alive_players()

void freezetag_count_alive_players ( )

Definition at line 22 of file sv_freezetag.qc.

23{
24 total_players = 0;
25 for (int i = 1; i <= NUM_TEAMS; ++i)
26 {
28 }
30 {
32 if (GetResource(it, RES_HEALTH) < 1 || STAT(FROZEN, it))
33 {
34 continue;
35 }
36 entity team_ = Entity_GetTeam(it);
37 int num_alive = Team_GetNumberOfAlivePlayers(team_);
38 ++num_alive;
39 Team_SetNumberOfAlivePlayers(team_, num_alive);
40 });
42 {
47 });
48
49 eliminatedPlayers.SendFlags |= 1;
50}
var entity(vector mins, vector maxs,.entity tofield) findbox_tofield_OrFallback
float GetResource(entity e, Resource res_type)
Returns the current amount of resource the given entity has.
entity eliminatedPlayers
Definition elimination.qh:3
#define STAT(...)
Definition stats.qh:82
entity Entity_GetTeam(entity this)
Returns the team entity of the given entity.
Definition teamplay.qc:186
bool Entity_HasValidTeam(entity this)
Returns whether the given entity belongs to a valid team.
Definition teamplay.qc:176
void Team_SetNumberOfAlivePlayers(entity team_ent, int number)
Sets the number of alive players in a team.
Definition teamplay.qc:90
#define IS_REAL_CLIENT(v)
Definition utils.qh:17

References eliminatedPlayers, entity(), Entity_GetTeam(), Entity_HasValidTeam(), FOREACH_CLIENT, GetResource(), IS_PLAYER, IS_REAL_CLIENT, NUM_TEAMS, STAT, Team_GetNumberOfAlivePlayers(), Team_GetTeamFromIndex(), Team_SetNumberOfAlivePlayers(), and total_players.

Referenced by freezetag_Freeze(), ft_RemovePlayer(), MUTATOR_HOOKFUNCTION(), MUTATOR_HOOKFUNCTION(), MUTATOR_HOOKFUNCTION(), and MUTATOR_HOOKFUNCTION().

◆ freezetag_Freeze()

void freezetag_Freeze ( entity targ,
entity attacker )

Definition at line 197 of file sv_freezetag.qc.

198{
199 if(!IS_PLAYER(targ) || STAT(FROZEN, targ))
200 return;
201
202 targ.freezetag_frozen_time = time;
204 targ.freezetag_frozen_timeout = time + autocvar_g_freezetag_frozen_maxtime;
205
206 STAT(FROZEN, targ) = true;
207 STAT(REVIVE_PROGRESS, targ) = 0;
208 SetResource(targ, RES_HEALTH, 1);
209 targ.revive_speed = 0;
210 if(targ.bot_attack)
212 targ.bot_attack = false;
213 targ.freeze_time = time;
214
215 entity ice = new(ice);
216 ice.owner = targ;
217 ice.scale = targ.scale;
218 // set_movetype(ice, MOVETYPE_FOLLOW) would rotate the ice model with the player
220 ice.nextthink = time;
221 ice.frame = floor(random() * 21); // ice model has 20 different looking frames
222 setmodel(ice, MDL_ICE);
223 ice.alpha = 1;
224 ice.colormod = Team_ColorRGB(targ.team);
225 ice.glowmod = ice.colormod;
226 targ.iceblock = ice;
227 targ.revival_time = 0;
228
230
232
234 {
235 for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
236 {
237 .entity weaponentity = weaponentities[slot];
238 if(it.(weaponentity).hook.aiment == targ)
239 RemoveHook(it.(weaponentity).hook);
240 }
241 });
242
243 WaypointSprite_Spawn(WP_Frozen, 0, 0, targ, '0 0 64', NULL, targ.team, targ, waypointsprite_attached, true, RADARICON_WAYPOINT);
244
246
247 freezetag_Add_Score(targ, attacker);
248}
IntrusiveList g_bot_targets
Definition api.qh:149
void SetResource(entity e, Resource res_type, float amount)
Sets the current amount of resource the given entity will have.
#define setmodel(this, m)
Definition model.qh:26
ERASEABLE void IL_REMOVE(IntrusiveList this, entity it)
Remove any element, anywhere in the list.
float random(void)
float floor(float f)
#define setthink(e, f)
void RemoveHook(entity this)
Definition hook.qc:48
void RemoveGrapplingHooks(entity pl)
Definition hook.qc:30
void freezetag_count_alive_players()
float autocvar_g_freezetag_frozen_maxtime
void freezetag_Ice_Think(entity this)
void freezetag_Add_Score(entity targ, entity attacker)
bool autocvar_g_freezetag_revive_auto
vector Team_ColorRGB(int teamid)
Definition teams.qh:76
entity WaypointSprite_Spawn(entity spr, float _lifetime, float maxdistance, entity ref, vector ofs, entity showto, float t, entity own,.entity ownfield, float hideable, entity icon)
entity waypointsprite_attached
const int MAX_WEAPONSLOTS
Definition weapon.qh:16
entity weaponentities[MAX_WEAPONSLOTS]
Definition weapon.qh:17

References autocvar_g_freezetag_frozen_maxtime, autocvar_g_freezetag_revive_auto, entity(), floor(), FOREACH_CLIENT, freezetag_Add_Score(), freezetag_count_alive_players(), freezetag_Ice_Think(), g_bot_targets, IL_REMOVE(), IS_PLAYER, MAX_WEAPONSLOTS, NULL, random(), RemoveGrapplingHooks(), RemoveHook(), setmodel, SetResource(), setthink, STAT, Team_ColorRGB(), time, waypointsprite_attached, WaypointSprite_Spawn(), and weaponentities.

Referenced by MUTATOR_HOOKFUNCTION(), and MUTATOR_HOOKFUNCTION().

◆ freezetag_Ice_Think()

void freezetag_Ice_Think ( entity this)

Definition at line 183 of file sv_freezetag.qc.

184{
185 if(!STAT(FROZEN, this.owner) || this.owner.iceblock != this)
186 {
187 delete(this);
188 return;
189 }
190 vector ice_org = this.owner.origin - '0 0 16';
191 if (this.origin != ice_org)
192 setorigin(this, ice_org);
193 this.nextthink = time;
194}
entity owner
Definition main.qh:87
float nextthink
vector origin
vector
Definition self.qh:92

References entity(), nextthink, origin, owner, STAT, time, and vector.

Referenced by freezetag_Freeze().

◆ freezetag_Initialize()

void freezetag_Initialize ( )

Definition at line 1022 of file sv_freezetag.qc.

1023{
1025 if(freezetag_teams < 2)
1026 freezetag_teams = cvar("g_freezetag_teams"); // read the cvar directly as it gets written earlier in the same frame
1027
1030 field_team(ST_FT_ROUNDS, "rounds", SFL_SORT_PRIO_PRIMARY);
1031 field(SP_FREEZETAG_REVIVALS, "revivals", 0);
1032 });
1033
1036
1038}
#define BITS(n)
Definition bits.qh:9
const int SFL_SORT_PRIO_PRIMARY
Definition scores.qh:134
void EliminatedPlayers_Init(float(entity) isEliminated_func)
float bound(float min, float value, float max)
float cvar(string name)
var void func_null()
void round_handler_Spawn(bool() canRoundStart_func, bool() canRoundEnd_func, void() roundStart_func)
int autocvar_g_freezetag_teams_override
bool freezetag_isEliminated(entity e)
bool freezetag_CheckTeams()
bool freezetag_CheckWinner()
#define GameRules_scoring(teams, spprio, stprio, fields)
Definition sv_rules.qh:58

References autocvar_g_freezetag_round_timelimit, autocvar_g_freezetag_teams_override, autocvar_g_freezetag_warmup, BITS, bound(), cvar(), EliminatedPlayers_Init(), freezetag_CheckTeams(), freezetag_CheckWinner(), freezetag_isEliminated(), freezetag_teams, func_null(), GameRules_scoring, round_handler_Init(), round_handler_Spawn(), SFL_SORT_PRIO_PRIMARY, and ST_FT_ROUNDS.

Referenced by REGISTER_MUTATOR().

◆ freezetag_isEliminated()

bool freezetag_isEliminated ( entity e)

Definition at line 288 of file sv_freezetag.qc.

289{
290 if(IS_PLAYER(e) && (STAT(FROZEN, e) || IS_DEAD(e)))
291 return true;
292 return false;
293}

References entity(), IS_DEAD, IS_PLAYER, and STAT.

Referenced by freezetag_Initialize().

◆ freezetag_LastPlayerForTeam()

entity freezetag_LastPlayerForTeam ( entity this)

Definition at line 136 of file sv_freezetag.qc.

137{
138 entity last_pl = NULL;
139 FOREACH_CLIENT(IS_PLAYER(it) && it != this && SAME_TEAM(it, this), {
140 if (!STAT(FROZEN, it) && GetResource(it, RES_HEALTH) >= 1)
141 {
142 if (!last_pl)
143 last_pl = it;
144 else
145 return NULL;
146 }
147 });
148 return last_pl;
149}

References entity(), FOREACH_CLIENT, GetResource(), IS_PLAYER, NULL, SAME_TEAM, and STAT.

Referenced by freezetag_LastPlayerForTeam_Notify().

◆ freezetag_LastPlayerForTeam_Notify()

void freezetag_LastPlayerForTeam_Notify ( entity this)

Definition at line 151 of file sv_freezetag.qc.

152{
155 {
157 if(pl)
158 Send_Notification(NOTIF_ONE, pl, MSG_CENTER, CENTER_ALONE);
159 }
160}
#define round_handler_IsActive()
#define round_handler_IsRoundStarted()
entity freezetag_LastPlayerForTeam(entity this)

References entity(), freezetag_LastPlayerForTeam(), round_handler_IsActive, round_handler_IsRoundStarted, and Send_Notification().

Referenced by ft_RemovePlayer(), and MUTATOR_HOOKFUNCTION().

◆ freezetag_Unfreeze()

void freezetag_Unfreeze ( entity targ,
bool reset_health )

Definition at line 250 of file sv_freezetag.qc.

251{
252 if(!STAT(FROZEN, targ))
253 return;
254
255 if (reset_health)
256 SetResource(targ, RES_HEALTH, ((IS_PLAYER(targ)) ? start_health : targ.max_health));
257
258 targ.pauseregen_finished = time + autocvar_g_balance_pause_health_regen;
259
260 STAT(FROZEN, targ) = false;
261 STAT(REVIVE_PROGRESS, targ) = 0;
262 targ.revival_time = time;
263 if(!targ.bot_attack)
264 IL_PUSH(g_bot_targets, targ);
265 targ.bot_attack = true;
266
267 WaypointSprite_Kill(targ.waypointsprite_attached);
268
270 {
271 for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
272 {
273 .entity weaponentity = weaponentities[slot];
274 if(it.(weaponentity).hook.aiment == targ)
275 RemoveHook(it.(weaponentity).hook);
276 }
277 });
278
279 // remove the ice block
280 if(targ.iceblock)
281 delete(targ.iceblock);
282 targ.iceblock = NULL;
283
284 targ.freezetag_frozen_time = 0;
285 targ.freezetag_frozen_timeout = 0;
286}
ERASEABLE entity IL_PUSH(IntrusiveList this, entity it)
Push to tail.
float autocvar_g_balance_pause_health_regen
void WaypointSprite_Kill(entity wp)
float start_health
Definition world.qh:96

References autocvar_g_balance_pause_health_regen, entity(), FOREACH_CLIENT, g_bot_targets, IL_PUSH(), IS_PLAYER, MAX_WEAPONSLOTS, NULL, RemoveHook(), SetResource(), start_health, STAT, time, WaypointSprite_Kill(), and weaponentities.

Referenced by ft_RemovePlayer(), MUTATOR_HOOKFUNCTION(), MUTATOR_HOOKFUNCTION(), MUTATOR_HOOKFUNCTION(), MUTATOR_HOOKFUNCTION(), MUTATOR_HOOKFUNCTION(), MUTATOR_HOOKFUNCTION(), and MUTATOR_HOOKFUNCTION().

◆ ft_RemovePlayer()

void ft_RemovePlayer ( entity this)

Definition at line 404 of file sv_freezetag.qc.

405{
406 if (!STAT(FROZEN, this))
408 freezetag_Unfreeze(this, false);
409
410 SetResourceExplicit(this, RES_HEALTH, 0); // neccessary to correctly count alive players
412}
bool SetResourceExplicit(entity e, Resource res_type, float amount)
Sets the resource amount of an entity without calling any hooks.
void freezetag_Unfreeze(entity targ, bool reset_health)
void freezetag_LastPlayerForTeam_Notify(entity this)

References entity(), freezetag_count_alive_players(), freezetag_LastPlayerForTeam_Notify(), freezetag_Unfreeze(), SetResourceExplicit(), and STAT.

Referenced by MUTATOR_HOOKFUNCTION(), and MUTATOR_HOOKFUNCTION().

◆ havocbot_goalrating_ft_freeplayers()

void havocbot_goalrating_ft_freeplayers ( entity this,
float ratingscale,
vector org,
float sradius )

Definition at line 303 of file sv_freezetag.qc.

304{
305 entity best_pl = NULL;
306 float best_dist2 = FLOAT_MAX;
307 FOREACH_CLIENT(IS_PLAYER(it) && it != this && SAME_TEAM(it, this), {
308 if (STAT(FROZEN, it))
309 {
310 if(vdist(it.origin - org, >, sradius))
311 continue;
312 navigation_routerating(this, it, ratingscale, 2000);
313 }
314 else if (best_dist2
315 && GetResource(it, RES_HEALTH) < GetResource(this, RES_HEALTH) + 30
316 && vlen2(it.origin - org) < best_dist2)
317 {
318 // If teamate is not frozen still seek them out as fight better
319 // in a group.
320 best_dist2 = vlen2(it.origin - org);
321 if (best_dist2 < 700 ** 2)
322 {
323 best_pl = NULL;
324 best_dist2 = 0; // already close to a teammate
325 }
326 else
327 best_pl = it;
328 }
329 });
330 if (best_pl)
331 navigation_routerating(this, best_pl, ratingscale / 2, 2000);
332}
void navigation_routerating(entity this, entity e, float f, float rangebias)
const float FLOAT_MAX
Definition float.qh:3
vector org
Definition self.qh:92
#define vlen2(v)
Definition vector.qh:4
#define vdist(v, cmp, f)
Vector distance comparison, avoids sqrt()
Definition vector.qh:8

References entity(), FLOAT_MAX, FOREACH_CLIENT, GetResource(), IS_PLAYER, navigation_routerating(), NULL, org, SAME_TEAM, STAT, vdist, vector, and vlen2.

Referenced by havocbot_role_ft_freeing(), and havocbot_role_ft_offense().

◆ havocbot_role_ft_freeing()

void havocbot_role_ft_freeing ( entity this)

Definition at line 370 of file sv_freezetag.qc.

371{
372 if(IS_DEAD(this))
373 return;
374
375 if (!this.havocbot_role_timeout)
376 this.havocbot_role_timeout = time + random() * 10 + 20;
377
378 if (time > this.havocbot_role_timeout)
379 {
380 LOG_TRACE("changing role to offense");
381 this.havocbot_role = havocbot_role_ft_offense;
382 this.havocbot_role_timeout = 0;
383 return;
384 }
385
387 {
389 havocbot_goalrating_items(this, 10000, this.origin, 10000);
390 havocbot_goalrating_enemyplayers(this, 5000, this.origin, 10000);
391 havocbot_goalrating_ft_freeplayers(this, 20000, this.origin, 10000);
392 havocbot_goalrating_waypoints(this, 1, this.origin, 3000);
394
396 }
397}
void havocbot_goalrating_waypoints(entity this, float ratingscale, vector org, float sradius)
Definition roles.qc:16
void navigation_goalrating_start(entity this)
void navigation_goalrating_timeout_set(entity this)
Definition navigation.qc:20
bool navigation_goalrating_timeout(entity this)
Definition navigation.qc:44
void navigation_goalrating_end(entity this)
float havocbot_role_timeout
Definition api.qh:46
#define LOG_TRACE(...)
Definition log.qh:76
void havocbot_role_ft_offense(entity this)
void havocbot_goalrating_ft_freeplayers(entity this, float ratingscale, vector org, float sradius)
void havocbot_goalrating_items(entity this, float ratingscale, vector org, float sradius)
Definition roles.qc:106
void havocbot_goalrating_enemyplayers(entity this, float ratingscale, vector org, float sradius)
Definition roles.qc:176

References entity(), havocbot_goalrating_enemyplayers(), havocbot_goalrating_ft_freeplayers(), havocbot_goalrating_items(), havocbot_goalrating_waypoints(), havocbot_role_ft_offense(), havocbot_role_timeout, IS_DEAD, LOG_TRACE, navigation_goalrating_end(), navigation_goalrating_start(), navigation_goalrating_timeout(), navigation_goalrating_timeout_set(), origin, random(), and time.

Referenced by havocbot_role_ft_offense(), MUTATOR_HOOKFUNCTION(), and void().

◆ havocbot_role_ft_offense()

void havocbot_role_ft_offense ( entity this)

Definition at line 334 of file sv_freezetag.qc.

335{
336 if(IS_DEAD(this))
337 return;
338
339 if (!this.havocbot_role_timeout)
340 this.havocbot_role_timeout = time + random() * 10 + 20;
341
342 // Count how many players on team are unfrozen.
343 int unfrozen = 0;
344 FOREACH_CLIENT(IS_PLAYER(it) && SAME_TEAM(it, this) && !STAT(FROZEN, it), {
345 unfrozen++;
346 });
347
348 // If only one left on team or if role has timed out then start trying to free players.
349 if ((!unfrozen && !STAT(FROZEN, this)) || time > this.havocbot_role_timeout)
350 {
351 LOG_TRACE("changing role to freeing");
352 this.havocbot_role = havocbot_role_ft_freeing;
353 this.havocbot_role_timeout = 0;
354 return;
355 }
356
358 {
360 havocbot_goalrating_items(this, 12000, this.origin, 10000);
361 havocbot_goalrating_enemyplayers(this, 10000, this.origin, 10000);
362 havocbot_goalrating_ft_freeplayers(this, 9000, this.origin, 10000);
363 havocbot_goalrating_waypoints(this, 1, this.origin, 3000);
365
367 }
368}
void havocbot_role_ft_freeing(entity this)

References entity(), FOREACH_CLIENT, havocbot_goalrating_enemyplayers(), havocbot_goalrating_ft_freeplayers(), havocbot_goalrating_items(), havocbot_goalrating_waypoints(), havocbot_role_ft_freeing(), havocbot_role_timeout, IS_DEAD, IS_PLAYER, LOG_TRACE, navigation_goalrating_end(), navigation_goalrating_start(), navigation_goalrating_timeout(), navigation_goalrating_timeout_set(), origin, random(), SAME_TEAM, STAT, and time.

Referenced by havocbot_role_ft_freeing(), MUTATOR_HOOKFUNCTION(), and void().

◆ MUTATOR_HOOKFUNCTION() [1/31]

MUTATOR_HOOKFUNCTION ( ft ,
AccuracyTargetValid  )

Definition at line 608 of file sv_freezetag.qc.

609{
611
612 // damage to frozen players is good only if it happens in the frame they get frozen
613 if (STAT(FROZEN, frag_target) && time > frag_target.freeze_time)
615 return MUT_ACCADD_VALID;
616}
#define M_ARGV(x, type)
Definition events.qh:17
@ MUT_ACCADD_INDIFFERENT
Definition events.qh:862
@ MUT_ACCADD_VALID
Definition events.qh:860
entity frag_target
Definition sv_ctf.qc:2321

References entity(), frag_target, M_ARGV, MUT_ACCADD_INDIFFERENT, MUT_ACCADD_VALID, STAT, and time.

◆ MUTATOR_HOOKFUNCTION() [2/31]

MUTATOR_HOOKFUNCTION ( ft ,
AllowMobSpawning  )

Definition at line 927 of file sv_freezetag.qc.

928{
929 M_ARGV(1, string) = "You can't spawn monsters while frozen";
930 return true;
931}

References M_ARGV.

◆ MUTATOR_HOOKFUNCTION() [3/31]

MUTATOR_HOOKFUNCTION ( ft ,
BotShouldAttack  )

Definition at line 952 of file sv_freezetag.qc.

953{
954 entity targ = M_ARGV(1, entity);
955
956 return STAT(FROZEN, targ);
957}

References entity(), M_ARGV, and STAT.

◆ MUTATOR_HOOKFUNCTION() [4/31]

MUTATOR_HOOKFUNCTION ( ft ,
BuffTouch  )

Definition at line 905 of file sv_freezetag.qc.

906{
908
909 return STAT(FROZEN, toucher);
910}
entity entity toucher
Definition self.qh:72

References entity(), M_ARGV, STAT, and toucher.

◆ MUTATOR_HOOKFUNCTION() [5/31]

MUTATOR_HOOKFUNCTION ( ft ,
ClientDisconnect  )

Definition at line 414 of file sv_freezetag.qc.

415{
416 entity player = M_ARGV(0, entity);
417
418 ft_RemovePlayer(player);
419 return true;
420}
void ft_RemovePlayer(entity this)

References ClientDisconnect, entity(), ft_RemovePlayer(), and M_ARGV.

◆ MUTATOR_HOOKFUNCTION() [6/31]

MUTATOR_HOOKFUNCTION ( ft ,
ClientKill  )

Definition at line 438 of file sv_freezetag.qc.

439{
440 entity player = M_ARGV(0, entity);
441
442 return STAT(FROZEN, player);
443}

References ClientKill, entity(), M_ARGV, and STAT.

◆ MUTATOR_HOOKFUNCTION() [7/31]

MUTATOR_HOOKFUNCTION ( ft ,
Damage_Calculate  )

Definition at line 618 of file sv_freezetag.qc.

619{
620 entity frag_attacker = M_ARGV(1, entity);
622 float frag_deathtype = M_ARGV(3, float);
623 float frag_damage = M_ARGV(4, float);
625
626 frag_target.freezetag_frozen_armor = GetResource(frag_target, RES_ARMOR);
627
630 {
631 float t = 0;
633 && frag_target.freezetag_frozen_timeout > time)
634 {
636 {
638 t = vlen(frag_force);
639 // limit hit force considered at once, e.g when you have the Strength
640 // powerup but also with weapons that fire multiple projectiles at once (crylink)
641 if (frag_target.freezetag_frozen_force + t > maxforce)
642 {
643 t = max(0, maxforce - frag_target.freezetag_frozen_force);
644 frag_target.freezetag_frozen_force = maxforce;
645 }
646 else
647 frag_target.freezetag_frozen_force += t;
649 }
650 frag_target.freezetag_frozen_timeout -= t;
651 if (frag_target.freezetag_frozen_timeout < time)
652 frag_target.freezetag_frozen_timeout = time;
653 }
654 }
655
656 if(STAT(FROZEN, frag_target) && !ITEM_DAMAGE_NEEDKILL(frag_deathtype)
657 && frag_deathtype != DEATH_TEAMCHANGE.m_id && frag_deathtype != DEATH_AUTOTEAMCHANGE.m_id)
658 {
659 if(autocvar_g_frozen_revive_falldamage > 0 && frag_deathtype == DEATH_FALL.m_id && frag_damage >= autocvar_g_frozen_revive_falldamage)
660 {
663 Send_Effect(EFFECT_ICEORGLASS, frag_target.origin, '0 0 0', 3);
664 Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_FREEZETAG_REVIVED_FALL, frag_target.netname);
665 Send_Notification(NOTIF_ONE, frag_target, MSG_CENTER, CENTER_FREEZETAG_REVIVE_SELF);
666 }
667
668 frag_damage = 0;
670 }
671
672 if(IS_PLAYER(frag_target) && STAT(FROZEN, frag_target)
674 {
675 Send_Effect(EFFECT_TELEPORT, frag_target.origin, '0 0 0', 1);
676
677 entity spot = SelectSpawnPoint(frag_target, false);
678 if(spot)
679 {
680 frag_damage = 0;
681 frag_target.deadflag = DEAD_NO;
682
683 frag_target.angles = spot.angles;
684
685 frag_target.effects = 0;
686 frag_target.effects |= EF_TELEPORT_BIT;
687
688 frag_target.angles_z = 0; // never spawn tilted even if the spot says to
689 frag_target.fixangle = true; // turn this way immediately
690 frag_target.velocity = '0 0 0';
691 frag_target.avelocity = '0 0 0';
692 frag_target.punchangle = '0 0 0';
693 frag_target.punchvector = '0 0 0';
694 frag_target.oldvelocity = frag_target.velocity;
695
696 frag_target.spawnorigin = spot.origin;
697 setorigin(frag_target, spot.origin + '0 0 1' * (1 - frag_target.mins.z - 24));
698 // don't reset back to last position, even if new position is stuck in solid
699 frag_target.oldorigin = frag_target.origin;
700
701 Send_Effect(EFFECT_TELEPORT, frag_target.origin, '0 0 0', 1);
702 }
703 }
704
705 M_ARGV(4, float) = frag_damage;
707}
const int EF_TELEPORT_BIT
void Send_Effect(entity eff, vector eff_loc, vector eff_vel, int eff_cnt)
Definition all.qc:124
RES_ARMOR
Definition ent_cs.qc:130
float vlen(vector v)
float fabs(float f)
float max(float f,...)
float DEAD_NO
Definition progsdefs.qc:274
#define ITEM_DAMAGE_NEEDKILL(dt)
Definition items.qh:129
entity SelectSpawnPoint(entity this, bool anypoint)
float frag_damage
Definition sv_ctf.qc:2322
vector frag_force
Definition sv_ctf.qc:2323
bool autocvar_g_frozen_damage_trigger
int autocvar_g_freezetag_revive_auto_reducible
float autocvar_g_freezetag_revive_auto_reducible_forcefactor
float autocvar_g_frozen_force
float autocvar_g_frozen_revive_falldamage
float autocvar_g_freezetag_revive_auto_reducible_maxforce
int autocvar_g_frozen_revive_falldamage_health
#define DIFF_TEAM(a, b)
Definition teams.qh:242

References autocvar_g_freezetag_frozen_maxtime, autocvar_g_freezetag_revive_auto, autocvar_g_freezetag_revive_auto_reducible, autocvar_g_freezetag_revive_auto_reducible_forcefactor, autocvar_g_freezetag_revive_auto_reducible_maxforce, autocvar_g_frozen_damage_trigger, autocvar_g_frozen_force, autocvar_g_frozen_revive_falldamage, autocvar_g_frozen_revive_falldamage_health, DEAD_NO, DIFF_TEAM, EF_TELEPORT_BIT, entity(), fabs(), frag_damage, frag_force, frag_target, freezetag_Unfreeze(), GetResource(), IS_PLAYER, ITEM_DAMAGE_NEEDKILL, M_ARGV, max(), NULL, RES_ARMOR, SelectSpawnPoint(), Send_Effect(), Send_Notification(), SetResource(), STAT, time, vector, and vlen().

◆ MUTATOR_HOOKFUNCTION() [8/31]

MUTATOR_HOOKFUNCTION ( ft ,
FragCenterMessage  )

Definition at line 990 of file sv_freezetag.qc.

991{
992 entity frag_attacker = M_ARGV(0, entity);
994 //float frag_deathtype = M_ARGV(2, float);
995 int kill_count_to_attacker = M_ARGV(3, int);
996 int kill_count_to_target = M_ARGV(4, int);
997
998 if(STAT(FROZEN, frag_target))
999 return; // target was already frozen, so this is just pushing them off the cliff
1000
1001 Send_Notification(NOTIF_ONE, frag_attacker, MSG_CHOICE, CHOICE_FRAG_FREEZE, frag_target.netname, kill_count_to_attacker, (IS_BOT_CLIENT(frag_target) ? -1 : CS(frag_target).ping));
1002 Send_Notification(NOTIF_ONE, frag_target, MSG_CHOICE, CHOICE_FRAGGED_FREEZE, frag_attacker.netname, kill_count_to_target,
1003 GetResource(frag_attacker, RES_HEALTH), GetResource(frag_attacker, RES_ARMOR), (IS_BOT_CLIENT(frag_attacker) ? -1 : CS(frag_attacker).ping));
1004
1005 return true;
1006}
float ping
Definition main.qh:169
ClientState CS(Client this)
Definition state.qh:47
#define IS_BOT_CLIENT(v)
want: (IS_CLIENT(v) && !IS_REAL_CLIENT(v))
Definition utils.qh:15

References CS(), entity(), frag_target, GetResource(), IS_BOT_CLIENT, M_ARGV, ping, RES_ARMOR, Send_Notification(), and STAT.

◆ MUTATOR_HOOKFUNCTION() [9/31]

MUTATOR_HOOKFUNCTION ( ft ,
GiveFragsForKill ,
CBC_ORDER_FIRST  )

Definition at line 590 of file sv_freezetag.qc.

591{
592 M_ARGV(2, float) = 0; // no frags counted in Freeze Tag
593 return true;
594}

References CBC_ORDER_FIRST, and M_ARGV.

◆ MUTATOR_HOOKFUNCTION() [10/31]

MUTATOR_HOOKFUNCTION ( ft ,
HavocBot_ChooseRole  )

Definition at line 959 of file sv_freezetag.qc.

960{
961 entity bot = M_ARGV(0, entity);
962
963 if (!IS_DEAD(bot))
964 {
965 if (random() < 0.5)
966 bot.havocbot_role = havocbot_role_ft_freeing;
967 else
968 bot.havocbot_role = havocbot_role_ft_offense;
969 }
970
971 // if bots spawn all at once assign them a more appropriated role after a while
972 if (time < CS(bot).jointime + 1)
973 bot.havocbot_role_timeout = time + 10 + random() * 10;
974
975 return true;
976}
float jointime
Definition client.qh:66

References CS(), entity(), havocbot_role_ft_freeing(), havocbot_role_ft_offense(), IS_DEAD, jointime, M_ARGV, random(), and time.

◆ MUTATOR_HOOKFUNCTION() [11/31]

MUTATOR_HOOKFUNCTION ( ft ,
ItemTouch  )

Definition at line 894 of file sv_freezetag.qc.

895{
896 if(MUTATOR_RETURNVALUE) return false;
897
899
900 if(STAT(FROZEN, toucher))
903}
#define MUTATOR_RETURNVALUE
Definition base.qh:328
@ MUT_ITEMTOUCH_RETURN
Definition events.qh:735
@ MUT_ITEMTOUCH_CONTINUE
Definition events.qh:734

References entity(), M_ARGV, MUT_ITEMTOUCH_CONTINUE, MUT_ITEMTOUCH_RETURN, MUTATOR_RETURNVALUE, STAT, and toucher.

◆ MUTATOR_HOOKFUNCTION() [12/31]

MUTATOR_HOOKFUNCTION ( ft ,
LockWeapon  )

Definition at line 596 of file sv_freezetag.qc.

597{
598 entity player = M_ARGV(0, entity);
599 return STAT(FROZEN, player);
600}

References entity(), M_ARGV, and STAT.

◆ MUTATOR_HOOKFUNCTION() [13/31]

MUTATOR_HOOKFUNCTION ( ft ,
MakePlayerObserver  )

Definition at line 422 of file sv_freezetag.qc.

423{
424 entity player = M_ARGV(0, entity);
425
426 ft_RemovePlayer(player);
427}

References entity(), ft_RemovePlayer(), and M_ARGV.

◆ MUTATOR_HOOKFUNCTION() [14/31]

MUTATOR_HOOKFUNCTION ( ft ,
MonsterValidTarget  )

Definition at line 933 of file sv_freezetag.qc.

934{
935 entity targ = M_ARGV(1, entity);
936
937 return !STAT(FROZEN, targ);
938}

References entity(), M_ARGV, and STAT.

◆ MUTATOR_HOOKFUNCTION() [15/31]

MUTATOR_HOOKFUNCTION ( ft ,
PlayerAnim  )

Definition at line 562 of file sv_freezetag.qc.

563{
564 entity player = M_ARGV(0, entity);
565
566 if(STAT(FROZEN, player))
567 M_ARGV(1, int) |= ANIMSTATE_FROZEN;
568}
const int ANIMSTATE_FROZEN

References ANIMSTATE_FROZEN, entity(), M_ARGV, and STAT.

◆ MUTATOR_HOOKFUNCTION() [16/31]

MUTATOR_HOOKFUNCTION ( ft ,
PlayerDamaged  )

Definition at line 602 of file sv_freezetag.qc.

603{
605 return STAT(FROZEN, frag_target);
606}

References entity(), frag_target, M_ARGV, and STAT.

◆ MUTATOR_HOOKFUNCTION() [17/31]

MUTATOR_HOOKFUNCTION ( ft ,
PlayerDied  )

Definition at line 445 of file sv_freezetag.qc.

446{
447 entity player = M_ARGV(0, entity);
448
449 freezetag_Unfreeze(player, false);
450}

References entity(), freezetag_Unfreeze(), and M_ARGV.

◆ MUTATOR_HOOKFUNCTION() [18/31]

MUTATOR_HOOKFUNCTION ( ft ,
PlayerDies  )

Definition at line 452 of file sv_freezetag.qc.

453{
454 entity frag_attacker = M_ARGV(1, entity);
456 float frag_deathtype = M_ARGV(3, float);
457
460 {
461 if (STAT(FROZEN, frag_target))
464 frag_target.respawn_time = time;
465 frag_target.respawn_flags |= RESPAWN_FORCE;
466 return true;
467 }
468
469 frag_target.respawn_time = time + 1;
470 frag_target.respawn_flags |= RESPAWN_FORCE;
471
472 // let the player die, they will be automatically frozen when they respawn
473 // it fixes a bug where you both really die (gibbing) and get frozen
474 // if you succeed changing team through the menu
475 if (frag_deathtype == DEATH_TEAMCHANGE.m_id || frag_deathtype == DEATH_AUTOTEAMCHANGE.m_id)
476 {
477 freezetag_Add_Score(frag_target, frag_attacker);
480 frag_target.freezetag_frozen_timeout = -2; // freeze on respawn
481 return true;
482 }
483
484 if(ITEM_DAMAGE_NEEDKILL(frag_deathtype))
485 {
486 // can't use freezetag_Add_Score here since it doesn't assign any points
487 // if the attacker is not a player (e.g. triggerhurt) by design
488 if (!STAT(FROZEN, frag_target) && !IS_PLAYER(frag_attacker))
490
491 // by restoring some health right after player death (soft-kill)
492 // weapons and ammo won't be reset
493 SetResourceExplicit(frag_target, RES_HEALTH, 1);
494 // restore armor as it was removed in PlayerDamage
495 SetResourceExplicit(frag_target, RES_ARMOR, frag_target.freezetag_frozen_armor);
496
497 // relocate
498 entity spot = SelectSpawnPoint(frag_target, true);
499 setorigin(frag_target, spot.origin);
500 frag_target.oldorigin = frag_target.origin;
501 frag_target.fixangle = true; // turn this way immediately
502 frag_target.angles = vec2(spot.angles);
503 frag_target.velocity = '0 0 0';
504 frag_target.oldvelocity = frag_target.velocity; // prevents fall damage, see CreatureFrame_FallDamage
505 frag_target.avelocity = '0 0 0';
506 frag_target.punchangle = '0 0 0';
507 frag_target.punchvector = '0 0 0';
508 }
509
510 if (STAT(FROZEN, frag_target))
511 return true;
512
513 freezetag_Freeze(frag_target, frag_attacker);
515
516 if(frag_attacker == frag_target || frag_attacker == NULL)
517 {
519 Send_Notification(NOTIF_ONE, frag_target, MSG_CENTER, CENTER_FREEZETAG_SELF);
520 Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_FREEZETAG_SELF, frag_target.netname);
521 }
522 else
523 {
524 Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_FREEZETAG_FREEZE, frag_target.netname, frag_attacker.netname);
525 }
526
527 return true;
528}
#define round_handler_CountdownRunning()
const int RESPAWN_FORCE
Definition client.qh:326
void freezetag_Freeze(entity targ, entity attacker)
#define vec2(...)
Definition vector.qh:90

References entity(), frag_target, freezetag_Add_Score(), freezetag_count_alive_players(), freezetag_Freeze(), freezetag_LastPlayerForTeam_Notify(), freezetag_Unfreeze(), GameRules_scoring_add, IS_PLAYER, ITEM_DAMAGE_NEEDKILL, M_ARGV, NULL, RES_ARMOR, RESPAWN_FORCE, round_handler_CountdownRunning, round_handler_IsActive, SelectSpawnPoint(), Send_Notification(), SetResourceExplicit(), STAT, time, and vec2.

◆ MUTATOR_HOOKFUNCTION() [19/31]

MUTATOR_HOOKFUNCTION ( ft ,
PlayerPreThink ,
CBC_ORDER_FIRST  )

Definition at line 717 of file sv_freezetag.qc.

718{
719 if(game_stopped)
720 return true;
721
724 return true;
725
726 entity player = M_ARGV(0, entity);
727 //if (STAT(FROZEN, player))
728 //if(player.freezetag_frozen_timeout > 0 && time < player.freezetag_frozen_timeout)
729 //player.iceblock.alpha = ICE_MIN_ALPHA + (ICE_MAX_ALPHA - ICE_MIN_ALPHA) * (player.freezetag_frozen_timeout - time) / (player.freezetag_frozen_timeout - player.freezetag_frozen_time);
730
731 player.freezetag_frozen_force = 0;
732
733 if (!(frametime && IS_PLAYER(player)))
734 return true;
735
736 entity revivers_last = NULL;
737 entity revivers_first = NULL;
738
739 bool player_is_reviving = false;
740 int n = 0;
741 vector revive_extra_size = '1 1 1' * autocvar_g_freezetag_revive_extra_size;
743 // check if player is reviving anyone
744 if (STAT(FROZEN, it))
745 {
746 if ((STAT(FROZEN, player)))
747 continue;
748 if (!IN_REVIVING_RANGE(player, it, revive_extra_size))
749 continue;
750 player_is_reviving = true;
751 break;
752 }
753
754 if (!(STAT(FROZEN, player)))
755 continue; // both player and it are NOT frozen
756 if (!IN_REVIVING_RANGE(player, it, revive_extra_size))
757 continue;
758
759 // found a teammate that is reviving player
760 if (autocvar_g_freezetag_revive_time_to_score > 0 && STAT(FROZEN, player))
761 {
762 it.freezetag_revive_time += frametime / autocvar_g_freezetag_revive_time_to_score;
763 while (it.freezetag_revive_time > 1)
764 {
765 GameRules_scoring_add(it, SCORE, +1);
766 it.freezetag_revive_time -= 1;
767 }
768 }
769 if (revivers_last)
770 revivers_last.chain = it;
771 revivers_last = it;
772 if (!revivers_first)
773 revivers_first = it;
774 ++n;
775 });
776 if (revivers_last)
777 revivers_last.chain = NULL;
778
779 // allow normal revival during automatic revival
780 // (if we wouldn't allow it then freezetag_frozen_timeout should be checked too in the previous loop)
781 //if (STAT(FROZEN, player)) // redundant check
782 if (!n && player.freezetag_frozen_timeout > 0 && time >= player.freezetag_frozen_timeout)
783 n = -1;
784
785 float base_progress = 0;
786 if (STAT(FROZEN, player) && autocvar_g_freezetag_revive_auto
788 {
789 // NOTE if auto-revival is in progress, manual revive speed is reduced so that it always takes the same amount of time
790 base_progress = bound(0, (1 - (player.freezetag_frozen_timeout - time) / autocvar_g_freezetag_frozen_maxtime), 1);
791 }
792
793 if (!n) // no teammate nearby
794 {
796 if (STAT(FROZEN, player))
797 {
799 {
800 if (STAT(REVIVE_PROGRESS, player) > base_progress)
801 {
802 // reduce auto-revival time based on manual revival progress
803 base_progress = STAT(REVIVE_PROGRESS, player);
804 player.freezetag_frozen_timeout = time + autocvar_g_freezetag_frozen_maxtime * (1 - STAT(REVIVE_PROGRESS, player));
805 }
806 // don't clear revive progress, it would allow stacking points
807 // by entering and exiting the revival zone many times
808 STAT(REVIVE_PROGRESS, player) = base_progress;
809 }
810 else
811 STAT(REVIVE_PROGRESS, player) = bound(base_progress, STAT(REVIVE_PROGRESS, player) - frametime * clearspeed * (1 - base_progress), 1);
812 }
813 else if (!STAT(FROZEN, player) && !player_is_reviving)
814 STAT(REVIVE_PROGRESS, player) = base_progress; // thawing nobody
815 }
816 else if (STAT(FROZEN, player)) // OK, there is at least one teammate reviving us
817 {
820 spd = autocvar_g_freezetag_revive_speed * (1 - base_progress);
821 STAT(REVIVE_PROGRESS, player) = bound(base_progress, STAT(REVIVE_PROGRESS, player) + frametime * max(1/60, spd), 1);
822
823 if(STAT(REVIVE_PROGRESS, player) >= 1)
824 {
825 float frozen_time = time - player.freezetag_frozen_time;
826 freezetag_Unfreeze(player, false);
828 player.spawnshieldtime = time + autocvar_g_freezetag_revive_spawnshield;
830
831 if(n == -1)
832 {
834 GameLogEcho(strcat(":ft:autorevival:", ftos(player.playerid)));
835 Send_Notification(NOTIF_ONE, player, MSG_CENTER, CENTER_FREEZETAG_AUTO_REVIVED, frozen_time);
836 Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_FREEZETAG_AUTO_REVIVED, player.netname, frozen_time);
837 return true;
838 }
839
840 // EVERY teammate nearby gets a point (even if multiple!)
841 for(entity it = revivers_first; it; it = it.chain)
842 {
843 GameRules_scoring_add(it, FREEZETAG_REVIVALS, +1);
845 GameRules_scoring_add(it, SCORE, +1);
847 }
848
849 Send_Notification(NOTIF_ONE, player, MSG_CENTER, CENTER_FREEZETAG_REVIVED, revivers_first.netname);
850 Send_Notification(NOTIF_ONE, revivers_first, MSG_CENTER, CENTER_FREEZETAG_REVIVE, player.netname);
851 Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_FREEZETAG_REVIVED, player.netname, revivers_first.netname);
853 {
854 string revivers = "";
855 for(entity it = revivers_first; it; it = it.chain)
856 revivers = strcat(revivers, ftos(it.playerid), ",");
857 revivers = substring(revivers, 0, strlen(revivers) - 1);
858 GameLogEcho(strcat(":ft:revival:", ftos(player.playerid), ":", revivers));
859 }
860 }
861
862 for(entity it = revivers_first; it; it = it.chain)
863 STAT(REVIVE_PROGRESS, it) = STAT(REVIVE_PROGRESS, player);
864 }
865
866 if (STAT(FROZEN, player))
867 {
868 entity player_wp = player.waypointsprite_attached;
869 if (n > 0 || (n == 0 && STAT(REVIVE_PROGRESS, player) > 0.95))
870 {
871 WaypointSprite_UpdateSprites(player_wp, WP_Reviving, WP_Null, WP_Null);
872 WaypointSprite_UpdateTeamRadar(player_wp, RADARICON_WAYPOINT, WP_REVIVING_COLOR);
873 }
874 else
875 {
876 WaypointSprite_UpdateSprites(player_wp, WP_Frozen, WP_Null, WP_Null);
877 WaypointSprite_UpdateTeamRadar(player_wp, RADARICON_WAYPOINT, WP_FROZEN_COLOR);
878 }
879
880 WaypointSprite_UpdateMaxHealth(player_wp, 1);
881 WaypointSprite_UpdateHealth(player_wp, STAT(REVIVE_PROGRESS, player));
882 }
883
884 return true;
885}
bool warmup_stage
Definition main.qh:120
float frametime
#define strlen
void GameLogEcho(string s)
Definition gamelog.qc:15
bool autocvar_sv_eventlog
Definition gamelog.qh:3
string substring(string s, float start, float length)
string ftos(float f)
const vector WP_FROZEN_COLOR
Definition all.inc:8
const vector WP_REVIVING_COLOR
Definition all.inc:9
strcat(_("^F4Countdown stopped!"), "\n^BG", _("Teams are too unbalanced."))
void nades_GiveBonus(entity player, float score)
Definition sv_nades.qc:434
#define IN_REVIVING_RANGE(player, it, revive_extra_size)
float autocvar_g_freezetag_revive_clearspeed
float autocvar_g_freezetag_revive_speed
float autocvar_g_freezetag_revive_spawnshield
float autocvar_g_freezetag_revive_extra_size
float autocvar_g_freezetag_revive_speed_t2s
int autocvar_g_freezetag_revive_auto_progress
float autocvar_g_freezetag_revive_time_to_score
int autocvar_g_nades_bonus_score_low
Definition sv_nades.qh:37
void WaypointSprite_UpdateTeamRadar(entity e, entity icon, vector col)
void WaypointSprite_UpdateSprites(entity e, entity _m1, entity _m2, entity _m3)
void WaypointSprite_UpdateMaxHealth(entity e, float f)
void WaypointSprite_UpdateHealth(entity e, float f)
float warmup_start_health
Definition world.qh:107

References autocvar_g_freezetag_frozen_maxtime, autocvar_g_freezetag_revive_auto, autocvar_g_freezetag_revive_auto_progress, autocvar_g_freezetag_revive_clearspeed, autocvar_g_freezetag_revive_extra_size, autocvar_g_freezetag_revive_spawnshield, autocvar_g_freezetag_revive_speed, autocvar_g_freezetag_revive_speed_t2s, autocvar_g_freezetag_revive_time_to_score, autocvar_g_nades_bonus_score_low, autocvar_sv_eventlog, bound(), CBC_ORDER_FIRST, entity(), FOREACH_CLIENT, frametime, freezetag_count_alive_players(), freezetag_Unfreeze(), ftos(), game_stopped, GameLogEcho(), GameRules_scoring_add, IN_REVIVING_RANGE, IS_PLAYER, M_ARGV, max(), nades_GiveBonus(), NULL, PlayerPreThink, round_handler_IsActive, round_handler_IsRoundStarted, Send_Notification(), SetResourceExplicit(), start_health, STAT, strcat(), strlen, substring(), time, vector, warmup_stage, warmup_start_health, WaypointSprite_UpdateHealth(), WaypointSprite_UpdateMaxHealth(), WaypointSprite_UpdateSprites(), WaypointSprite_UpdateTeamRadar(), WP_FROZEN_COLOR, and WP_REVIVING_COLOR.

◆ MUTATOR_HOOKFUNCTION() [20/31]

MUTATOR_HOOKFUNCTION ( ft ,
PlayerRegen  )

Definition at line 887 of file sv_freezetag.qc.

888{
889 entity player = M_ARGV(0, entity);
890
891 return STAT(FROZEN, player);
892}

References entity(), M_ARGV, and STAT.

◆ MUTATOR_HOOKFUNCTION() [21/31]

MUTATOR_HOOKFUNCTION ( ft ,
PlayerSpawn  )

Definition at line 530 of file sv_freezetag.qc.

531{
532 entity player = M_ARGV(0, entity);
533
534 freezetag_Unfreeze(player, false);
535
536 if(player.freezetag_frozen_timeout == -1) // if PlayerSpawn is called by reset_map_players
537 return true; // do nothing, round is starting right now
538
539 if(player.freezetag_frozen_timeout <= -2) // player was dead
540 {
541 freezetag_Freeze(player, NULL);
542 return true;
543 }
544
546
549 {
550 Send_Notification(NOTIF_ONE, player, MSG_CENTER, CENTER_FREEZETAG_SPAWN_LATE);
551 freezetag_Freeze(player, NULL);
552 }
553
554 return true;
555}

References entity(), freezetag_count_alive_players(), freezetag_Freeze(), freezetag_Unfreeze(), M_ARGV, NULL, round_handler_IsActive, round_handler_IsRoundStarted, and Send_Notification().

◆ MUTATOR_HOOKFUNCTION() [22/31]

MUTATOR_HOOKFUNCTION ( ft ,
PutClientInServer  )

Definition at line 557 of file sv_freezetag.qc.

558{
559 eliminatedPlayers.SendFlags |= 1;
560}

References eliminatedPlayers, and PutClientInServer.

◆ MUTATOR_HOOKFUNCTION() [23/31]

MUTATOR_HOOKFUNCTION ( ft ,
reset_map_global  )

Definition at line 570 of file sv_freezetag.qc.

571{
572 FOREACH_CLIENT(IS_PLAYER(it) && STAT(FROZEN, it), {
573 freezetag_Unfreeze(it, false);
574 });
575}

References FOREACH_CLIENT, freezetag_Unfreeze(), IS_PLAYER, and STAT.

◆ MUTATOR_HOOKFUNCTION() [24/31]

MUTATOR_HOOKFUNCTION ( ft ,
reset_map_players  )

Definition at line 577 of file sv_freezetag.qc.

578{
580 CS(it).killcount = 0;
581 it.freezetag_revive_time = 0;
582 it.freezetag_frozen_timeout = -1;
584 it.freezetag_frozen_timeout = 0;
585 });
587 return true;
588}
#define PutClientInServer
Definition _all.inc:246

References CS(), FOREACH_CLIENT, freezetag_count_alive_players(), IS_PLAYER, and PutClientInServer.

◆ MUTATOR_HOOKFUNCTION() [25/31]

MUTATOR_HOOKFUNCTION ( ft ,
Scores_CountFragsRemaining  )

Definition at line 1016 of file sv_freezetag.qc.

1017{
1018 // announce remaining frags
1019 return true;
1020}

◆ MUTATOR_HOOKFUNCTION() [26/31]

MUTATOR_HOOKFUNCTION ( ft ,
SetStartItems  )

Definition at line 912 of file sv_freezetag.qc.

913{
915 if(!cvar("g_use_ammunition"))
917
925}
const int IT_UNLIMITED_AMMO
Definition item.qh:23
const int IT_UNLIMITED_SUPERWEAPONS
Definition item.qh:24
float autocvar_g_ft_start_ammo_nails
float autocvar_g_ft_start_health
float autocvar_g_ft_start_ammo_fuel
float autocvar_g_ft_start_ammo_rockets
float autocvar_g_ft_start_ammo_shells
float autocvar_g_ft_start_armor
float autocvar_g_ft_start_ammo_cells
float warmup_start_ammo_cells
Definition world.qh:105
float start_ammo_shells
Definition world.qh:84
float warmup_start_ammo_rockets
Definition world.qh:104
float warmup_start_ammo_shells
Definition world.qh:102
float start_ammo_fuel
Definition world.qh:88
int start_items
Definition world.qh:83
float warmup_start_ammo_nails
Definition world.qh:103
float start_ammo_cells
Definition world.qh:87
float start_ammo_rockets
Definition world.qh:86
float start_armorvalue
Definition world.qh:97
float warmup_start_ammo_fuel
Definition world.qh:106
float warmup_start_armorvalue
Definition world.qh:108
float start_ammo_nails
Definition world.qh:85

References autocvar_g_ft_start_ammo_cells, autocvar_g_ft_start_ammo_fuel, autocvar_g_ft_start_ammo_nails, autocvar_g_ft_start_ammo_rockets, autocvar_g_ft_start_ammo_shells, autocvar_g_ft_start_armor, autocvar_g_ft_start_health, cvar(), IT_UNLIMITED_AMMO, IT_UNLIMITED_SUPERWEAPONS, start_ammo_cells, start_ammo_fuel, start_ammo_nails, start_ammo_rockets, start_ammo_shells, start_armorvalue, start_health, start_items, warmup_start_ammo_cells, warmup_start_ammo_fuel, warmup_start_ammo_nails, warmup_start_ammo_rockets, warmup_start_ammo_shells, warmup_start_armorvalue, and warmup_start_health.

◆ MUTATOR_HOOKFUNCTION() [27/31]

MUTATOR_HOOKFUNCTION ( ft ,
SetWeaponArena  )

Definition at line 984 of file sv_freezetag.qc.

985{
986 if(M_ARGV(0, string) == "0" || M_ARGV(0, string) == "")
988}
string autocvar_g_freezetag_weaponarena

References autocvar_g_freezetag_weaponarena, and M_ARGV.

◆ MUTATOR_HOOKFUNCTION() [28/31]

MUTATOR_HOOKFUNCTION ( ft ,
SpectateCopy  )

Definition at line 429 of file sv_freezetag.qc.

430{
431 entity spectatee = M_ARGV(0, entity);
432 entity client = M_ARGV(1, entity);
433
434 STAT(FROZEN, client) = STAT(FROZEN, spectatee);
435 STAT(REVIVE_PROGRESS, client) = STAT(REVIVE_PROGRESS, spectatee);
436}

References entity(), M_ARGV, SpectateCopy(), and STAT.

◆ MUTATOR_HOOKFUNCTION() [29/31]

MUTATOR_HOOKFUNCTION ( ft ,
SV_ParseServerCommand  )

Definition at line 1008 of file sv_freezetag.qc.

1009{
1010 string cmd_name = M_ARGV(0, string);
1011 if (cmd_name == "shuffleteams")
1013 return false;
1014}
string cmd_name
Definition events.qh:12
bool shuffleteams_on_reset_map
Definition sv_cmd.qh:7

References cmd_name, M_ARGV, round_handler_IsActive, round_handler_IsRoundStarted, and shuffleteams_on_reset_map.

◆ MUTATOR_HOOKFUNCTION() [30/31]

MUTATOR_HOOKFUNCTION ( ft ,
TeamBalance_CheckAllowedTeams ,
CBC_ORDER_EXCLUSIVE  )

Definition at line 978 of file sv_freezetag.qc.

979{
980 M_ARGV(0, float) = freezetag_teams;
981 return true;
982}

References CBC_ORDER_EXCLUSIVE, freezetag_teams, M_ARGV, and TeamBalance_CheckAllowedTeams().

◆ MUTATOR_HOOKFUNCTION() [31/31]

MUTATOR_HOOKFUNCTION ( ft ,
TurretValidateTarget  )

Definition at line 940 of file sv_freezetag.qc.

941{
942 entity targ = M_ARGV(1, entity);
943
944 if(STAT(FROZEN, targ))
945 {
946 M_ARGV(3, float) = -6;
947 return true;
948 }
949 return false;
950}

References entity(), M_ARGV, and STAT.

◆ void()

Variable Documentation

◆ autocvar_g_freezetag_frozen_maxtime

float autocvar_g_freezetag_frozen_maxtime

Definition at line 6 of file sv_freezetag.qc.

Referenced by freezetag_Freeze(), MUTATOR_HOOKFUNCTION(), and MUTATOR_HOOKFUNCTION().

◆ autocvar_g_freezetag_revive_clearspeed

float autocvar_g_freezetag_revive_clearspeed

Definition at line 7 of file sv_freezetag.qc.

Referenced by MUTATOR_HOOKFUNCTION().

◆ autocvar_g_freezetag_round_enddelay

float autocvar_g_freezetag_round_enddelay

Definition at line 12 of file sv_freezetag.qc.

Referenced by freezetag_CheckWinner().

◆ autocvar_g_freezetag_round_timelimit

float autocvar_g_freezetag_round_timelimit

Definition at line 8 of file sv_freezetag.qc.

Referenced by freezetag_CheckWinner(), and freezetag_Initialize().

◆ autocvar_g_freezetag_teams_override

int autocvar_g_freezetag_teams_override

Definition at line 10 of file sv_freezetag.qc.

Referenced by freezetag_Initialize().

◆ autocvar_g_freezetag_warmup

float autocvar_g_freezetag_warmup

Definition at line 11 of file sv_freezetag.qc.

Referenced by freezetag_CheckWinner(), and freezetag_Initialize().

◆ autocvar_g_ft_start_ammo_cells

float autocvar_g_ft_start_ammo_cells = 180

Definition at line 19 of file sv_freezetag.qc.

Referenced by MUTATOR_HOOKFUNCTION().

◆ autocvar_g_ft_start_ammo_fuel

float autocvar_g_ft_start_ammo_fuel = 0

Definition at line 20 of file sv_freezetag.qc.

Referenced by MUTATOR_HOOKFUNCTION().

◆ autocvar_g_ft_start_ammo_nails

float autocvar_g_ft_start_ammo_nails = 320

Definition at line 17 of file sv_freezetag.qc.

Referenced by MUTATOR_HOOKFUNCTION().

◆ autocvar_g_ft_start_ammo_rockets

float autocvar_g_ft_start_ammo_rockets = 160

Definition at line 18 of file sv_freezetag.qc.

Referenced by MUTATOR_HOOKFUNCTION().

◆ autocvar_g_ft_start_ammo_shells

float autocvar_g_ft_start_ammo_shells = 60

Definition at line 16 of file sv_freezetag.qc.

Referenced by MUTATOR_HOOKFUNCTION().

◆ autocvar_g_ft_start_armor

float autocvar_g_ft_start_armor = 100

Definition at line 15 of file sv_freezetag.qc.

Referenced by MUTATOR_HOOKFUNCTION().

◆ autocvar_g_ft_start_health

float autocvar_g_ft_start_health = 100

Definition at line 14 of file sv_freezetag.qc.

Referenced by MUTATOR_HOOKFUNCTION().