Xonotic QuakeC
The free, fast arena FPS with crisp movement and a wide array of weapons
sv_keepaway.qc
Go to the documentation of this file.
1#include "sv_keepaway.qh"
2
5#include <server/client.qh>
6#include <server/gamelog.qh>
7#include <server/damage.qh>
9#include <server/world.qh>
10
12.entity previous_owner; // also used on kh keys
13
21
31
32bool ka_ballcarrier_waypointsprite_visible_for_player(entity this, entity player, entity view) // runs on waypoints which are attached to ballcarriers, updates once per frame
33{
34 if(view.ballcarried && IS_SPEC(player))
35 return false; // we don't want spectators of the ballcarrier to see the attached waypoint on the top of their screen
36 if(IS_SPEC(player) || warmup_stage)
37 return true;
38 if(IS_INVISIBLE(this.owner))
39 return false; // hide the waypointsprite if the owner is invisible
40
42}
43
44void ka_EventLog(string mode, entity actor) // use an alias for easy changing and quick editing later
45{
47 GameLogEcho(strcat(":ka:", mode, ((actor != NULL) ? (strcat(":", ftos(actor.playerid))) : "")));
48}
49
50void ka_RespawnBall(entity this) // runs whenever the ball needs to be relocated
51{
52 if(game_stopped) return;
53 vector oldballorigin = this.origin;
54
56 setorigin(this, SelectSpawnPoint(this, true).origin);
57
59 this.velocity = '0 0 200';
60 this.angles = '0 0 0';
65
66 Send_Effect(EFFECT_KA_BALL_RESPAWN, oldballorigin, '0 0 0', 1);
67 Send_Effect(EFFECT_KA_BALL_RESPAWN, this.origin, '0 0 0', 1);
68
70 {
71 WaypointSprite_Spawn(WP_KaBall, 0, 0, this, '0 0 64', NULL, this.team, this, waypointsprite_attachedforcarrier, false, RADARICON_FLAGCARRIER);
73 }
74
75 sound(this, CH_TRIGGER, SND_KA_RESPAWN, VOL_BASE, ATTEN_NONE); // ATTEN_NONE (it's a sound intended to be heard anywhere)
76}
77
78// field where the decimal part of SCORE is accumulated (shared with other gametypes)
80MUTATOR_HOOKFUNCTION(ka, reset_map_global)
81{
82 FOREACH_CLIENT(true,
83 {
84 it.float2int_decimal_fld = 0;
85 });
86 return true;
87}
88
91{
94 GameRules_scoring_add(this.owner, KEEPAWAY_BCTIME, frametime);
95
96 this.nextthink = time;
97
98 // animate, this is ~copied from KH
99#define BALL_XYSPEED 100 // KH 45
100#define BALL_XYDIST 24 // KH 24
101 makevectors(vec3(0, (360 * this.cnt / this.owner.ballcarried.cnt) + (time % 360) * BALL_XYSPEED, 0));
102 setorigin(this, vec3(v_forward.x * BALL_XYDIST, v_forward.y * BALL_XYDIST, this.origin.z));
103
104 // sync any invisibility effect
105 this.alpha = this.owner.alpha;
106}
107
108void ka_DamageEvent(entity this, entity inflictor, entity attacker, float damage, int deathtype, .entity weaponentity, vector hitloc, vector force)
109{
110 if(ITEM_DAMAGE_NEEDKILL(deathtype))
111 ka_RespawnBall(this);
112}
113
114void ka_TouchEvent(entity this, entity toucher) // runs any time that the ball comes in contact with something
115{
116 if (!this || game_stopped)
117 return;
118
120 { // The ball fell off the map, respawn it since players can't get to it
121 ka_RespawnBall(this);
122 return;
123 }
124 // TODO: mutator hook to prevent picking up objectives
125 if(IS_INDEPENDENT_PLAYER(toucher)) { return; }
126 if(IS_DEAD(toucher)) { return; }
127 if (!IS_PLAYER(toucher))
128 { // The ball just touched an object, most likely the world
129 Send_Effect(EFFECT_BALL_SPARKS, this.origin, '0 0 0', 1);
130 sound(this, CH_TRIGGER, SND_KA_TOUCH, VOL_BASE, ATTEN_NORM);
131 return;
132 }
133 else if(this.wait > time && this.previous_owner == toucher)
134 return;
135
136 if (toucher.ballcarried) // multiple balls exist
137 {
139 return;
140 this.ballcarried = toucher.ballcarried; // new ball will be inserted at start of chain
141 this.cnt = toucher.ballcarried.cnt + 1; // for orbit animation offset
142 }
143 else
144 this.cnt = 1;
145
146 // attach the ball to the player
147 this.owner = toucher;
148 toucher.ballcarried = this;
150 setattachment(this, toucher, "");
151 this.solid = SOLID_NOT; // before setorigin to ensure area grid unlinking
152 setorigin(this, '0 0 0');
153
154 // make the ball unable to do anything, set up time scoring
155 this.velocity = '0 0 0';
157 this.scale = 12/16; // somewhat smaller while carried
159 this.nextthink = time;
160 this.takedamage = DAMAGE_NO;
161 this.event_damage = func_null;
162 this.damagedbycontents = false;
165
166 // messages and sounds
167 ka_EventLog("pickup", toucher);
168 Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_KEEPAWAY_PICKUP, toucher.netname);
169 Send_Notification(NOTIF_ALL_EXCEPT, toucher, MSG_CENTER, CENTER_KEEPAWAY_PICKUP, toucher.netname);
170 Send_Notification(NOTIF_ONE, toucher, MSG_CENTER, CENTER_KEEPAWAY_PICKUP_SELF);
171 sound(this.owner, CH_TRIGGER, SND_KA_PICKEDUP, VOL_BASE, ATTEN_NONE); // ATTEN_NONE (it's a sound intended to be heard anywhere)
172
173 // scoring
174 GameRules_scoring_add(toucher, KEEPAWAY_PICKUPS, 1);
175
176 // waypoints
177 WaypointSprite_AttachCarrier(WP_KaBallCarrier, toucher, RADARICON_FLAGCARRIER);
178 toucher.waypointsprite_attachedforcarrier.waypointsprite_visible_for_player = ka_ballcarrier_waypointsprite_visible_for_player;
179 WaypointSprite_UpdateRule(toucher.waypointsprite_attachedforcarrier, 0, SPRITERULE_DEFAULT);
180 WaypointSprite_Ping(toucher.waypointsprite_attachedforcarrier);
182}
183
185{
186 player.ballcarried = NULL;
187 GameRules_scoring_vip(player, false);
188 WaypointSprite_Kill(player.waypointsprite_attachedforcarrier);
189}
190
191void ka_DropEvent(entity player) // runs any time that a player is supposed to lose the ball
192{
193 entity ball = player.ballcarried;
194
195 if(!ball) { return; }
196
197 // reset the ball
198 setattachment(ball, NULL, "");
200 ball.previous_owner = player;
201 ball.wait = time + 0.5; // same as for thrown weapons
203 ball.nextthink = time + autocvar_g_keepawayball_respawntime;
204 ball.takedamage = DAMAGE_YES;
205 ball.event_damage = ka_DamageEvent;
206 ball.damagedbycontents = true;
208 ball.scale = 1; // it's smaller while carried
209 ball.alpha = 1; // in case the carrier had an invisibility effect
210 ball.solid = SOLID_TRIGGER; // before setorigin to ensure area grid linking
211 setorigin(ball, player.origin + ball.origin + '0 0 10'); // include attachment offset to reduce jump
212 nudgeoutofsolid_OrFallback(ball); // a ball has a horizontally bigger bbox than a player
213 ball.velocity = '0 0 200' + '0 100 0'*crandom() + '100 0 0'*crandom();
214 ball.owner = NULL;
215 navigation_dynamicgoal_set(ball, player);
216
217 // messages and sounds
218 ka_EventLog("dropped", player);
219 Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_KEEPAWAY_DROPPED, player.netname);
220 Send_Notification(NOTIF_ALL, NULL, MSG_CENTER, CENTER_KEEPAWAY_DROPPED, player.netname);
221 sound(NULL, CH_TRIGGER, SND_KA_DROPPED, VOL_BASE, ATTEN_NONE); // ATTEN_NONE (it's a sound intended to be heard anywhere)
222
223 // waypoints
225 {
226 WaypointSprite_Spawn(WP_KaBall, 0, 0, ball, '0 0 64', NULL, ball.team, ball, waypointsprite_attachedforcarrier, false, RADARICON_FLAGCARRIER);
227 WaypointSprite_UpdateRule(ball.waypointsprite_attachedforcarrier, 0, SPRITERULE_DEFAULT);
228 WaypointSprite_Ping(ball.waypointsprite_attachedforcarrier);
229 }
230
231 if (ball.ballcarried) // >1 ball was chained, first one was just dropped
232 {
233 player.ballcarried = ball.ballcarried; // move the next one up
234 ball.ballcarried = NULL; // prevent infinite loop
235 }
236 else // no balls remaining so remove bc status
237 ka_PlayerReset(player);
238}
239
241
242MODEL(KA_BALL, "models/orbs/orbblue.md3");
243
245{
246 IL_EACH(g_kaballs, true,
247 {
248 if (it.owner) // it was attached
249 ka_PlayerReset(it.owner);
250 else
252 delete(it);
253 });
254}
255
257{
258 int i = 0;
259 do // never allow less than 1 ball to spawn
260 {
261 entity e = new(keepawayball);
262 setmodel(e, MDL_KA_BALL);
263 e.solid = SOLID_TRIGGER; // before setsize to ensure area grid linking
264 // 20 20 20 was too big, player is only 16 16 24... gotta cheat with the Z (20) axis so that the particle isn't cut off
265 // bones_was_here: that was WITH sv_legacy_bbox_expand 1 and FL_ITEM (mins -= '15 15 1'; maxs += '15 15 1')
266 // it's round so should have a symmetrical bbox, same height as pickup items so it can't be jumped over in any physics
267 setsize(e, '-24 -24 -24', '24 24 24');
268 e.damageforcescale = autocvar_g_keepawayball_damageforcescale;
269 e.takedamage = DAMAGE_YES;
270 e.event_damage = ka_DamageEvent;
271 e.damagedbycontents = true;
275 e.glow_trail = true;
276 e.flags = FL_ITEM;
277 IL_PUSH(g_items, e);
278 e.pushable = true;
280 e.owner = NULL;
281 IL_PUSH(g_kaballs, e);
283
285
286 ++i;
287 }
289}
290
292{
293 if(time < game_starttime)
294 {
295 if (!IL_EMPTY(g_kaballs))
297 }
298 else
299 {
300 if (IL_EMPTY(g_kaballs))
301 ka_SpawnBalls(); // ;)
302 }
303
304 this.nextthink = time;
305}
306
307
308// ================
309// Bot player logic
310// ================
311
313{
314 entity ball_wp = e.waypointsprite_attachedforcarrier;
315 if (!ball_wp)
316 if (dropped || !ball_wp.waypointsprite_visible_for_player(ball_wp, this, WaypointSprite_getviewentity(this)))
317 { // has no waypoint, or waypoint not visible
318 if (!checkpvs(this.origin + this.view_ofs, e)) // ball cannot be seen
319 return false;
320 }
321 return true;
322}
323
324void havocbot_goalrating_ball(entity this, float ratingscale, vector org)
325{
326 entity ball = NULL, ball_carried = NULL;
327
328 // stops at last ball, prefers ball without carrier
329 IL_EACH(g_kaballs, it.owner != this,
330 {
331 if (it.owner)
332 {
333 if (!ka_waypointsprite_visible_for_bot(this, it.owner, false))
334 continue;
335 ball_carried = it.owner;
336 }
337 else
338 {
339 if (!ka_waypointsprite_visible_for_bot(this, it, true))
340 continue;
341 ball = it;
342 }
343 });
344
345 if (ball)
346 navigation_routerating(this, ball, ratingscale, 2000);
347 else if (ball_carried)
348 navigation_routerating(this, ball_carried, ratingscale, 2000);
349}
350
352{
353 if (IS_DEAD(this))
354 return;
355
357 {
359 havocbot_goalrating_items(this, 10000, this.origin, 10000);
360 havocbot_goalrating_enemyplayers(this, 10000, this.origin, 10000);
361 havocbot_goalrating_waypoints(this, 1, this.origin, 3000);
363
365 }
366
367 if (!this.ballcarried)
368 {
369 this.havocbot_role = havocbot_role_ka_collector;
371 }
372}
373
375{
376 if (IS_DEAD(this))
377 return;
378
380 {
382 havocbot_goalrating_items(this, 10000, this.origin, 10000);
383 havocbot_goalrating_enemyplayers(this, 500, this.origin, 10000);
384 havocbot_goalrating_ball(this, 8000, this.origin);
386
388 }
389
390 if (this.ballcarried)
391 {
392 this.havocbot_role = havocbot_role_ka_carrier;
394 }
395}
396
397
398// ==============
399// Hook Functions
400// ==============
401
402MUTATOR_HOOKFUNCTION(ka, PlayerDies)
403{
404 entity frag_attacker = M_ARGV(1, entity);
406
407 if((frag_attacker != frag_target) && (IS_PLAYER(frag_attacker)))
408 {
409 if(frag_target.ballcarried) // add to amount of times killing carrier
410 {
411 GameRules_scoring_add(frag_attacker, KEEPAWAY_CARRIERKILLS, 1);
412 if(autocvar_g_keepaway_score_bckill) // add bckills to the score
414 }
415 else if(!frag_attacker.ballcarried)
416 {
418 Send_Notification(NOTIF_ONE_ONLY, frag_attacker, MSG_CENTER, CENTER_KEEPAWAY_WARN);
419 }
420
421 if(frag_attacker.ballcarried) // add to amount of kills while ballcarrier
423 }
424
425 while (frag_target.ballcarried)
426 ka_DropEvent(frag_target); // a player with ball(s) has died, drop them
427}
428
429MUTATOR_HOOKFUNCTION(ka, GiveFragsForKill)
430{
431 M_ARGV(2, float) = 0; // no frags counted in keepaway
432 return true; // you deceptive little bugger ;3 This needs to be true in order for this function to even count.
433}
434
435MUTATOR_HOOKFUNCTION(ka, Scores_CountFragsRemaining)
436{
437 // announce remaining frags, but only when timed scoring is off
439}
440
442{
443 entity player = M_ARGV(0, entity);
444
445 // if the player has the ball, make sure they have the item for it (Used for HUD primarily)
446 STAT(OBJECTIVE_STATUS, player) = BITSET(STAT(OBJECTIVE_STATUS, player), KA_CARRYING, player.ballcarried != NULL);
447}
448
450{
451 entity player = M_ARGV(0, entity);
452
453 if(MUTATOR_RETURNVALUE == 0)
454 if(player.ballcarried)
455 {
456 ka_DropEvent(player);
457 return true;
458 }
459}
460
461MUTATOR_HOOKFUNCTION(ka, Damage_Calculate) // for changing damage and force values that are applied to players
462{
463 entity frag_attacker = M_ARGV(1, entity);
465
466 // as a gametype rule, only apply scaling to player versus player combat
467 if (!IS_PLAYER(frag_attacker) || !IS_PLAYER(frag_target))
468 return;
469
470 if (frag_attacker.ballcarried) // if the attacker is a ballcarrier
471 {
472 if (frag_target == frag_attacker) // damage done to themselves
473 {
476 }
477 else if (frag_target.ballcarried) // damage done to other ballcarriers
478 {
481 }
482 else // damage done to noncarriers
483 {
486 }
487 }
488 else
489 {
490 if (frag_target == frag_attacker) // damage done to themselves
491 {
494 }
495 else if (frag_target.ballcarried) // damage done to ballcarriers
496 {
499 }
500 else // damage done to other noncarriers
501 {
504 }
505 }
506}
507
509{
510 entity player = M_ARGV(0, entity);
511
512 while (player.ballcarried)
513 ka_DropEvent(player); // a player with ball(s) has left the match, drop them
514}
515
516MUTATOR_HOOKFUNCTION(ka, MakePlayerObserver)
517{
518 entity player = M_ARGV(0, entity);
519
520 while (player.ballcarried)
521 ka_DropEvent(player); // a player with ball(s) has left the match, drop them
522}
523
524MUTATOR_HOOKFUNCTION(ka, PlayerPowerups)
525{
526// entity player = M_ARGV(0, entity);
527
528 // In the future this hook is supposed to allow me to do some extra stuff with waypointsprites and invisibility powerup
529 // So bare with me until I can fix a certain bug with ka_ballcarrier_waypointsprite_visible_for_player()
530}
531
532
533MUTATOR_HOOKFUNCTION(ka, PlayerPhysics_UpdateStats)
534{
535 entity player = M_ARGV(0, entity);
536 // these automatically reset, no need to worry
537
538 if(player.ballcarried)
539 STAT(MOVEVARS_HIGHSPEED, player) *= autocvar_g_keepaway_ballcarrier_highspeed;
540}
541
542MUTATOR_HOOKFUNCTION(ka, BotShouldAttack)
543{
544 entity bot = M_ARGV(0, entity);
545 entity targ = M_ARGV(1, entity);
546
547 // if neither player has ball then don't attack unless the ball is on the ground
548 bool have_held_ball = false;
549 IL_EACH(g_kaballs, it.owner,
550 {
551 have_held_ball = true;
552 break;
553 });
554 if(!targ.ballcarried && !bot.ballcarried && have_held_ball)
555 return true;
556}
557
558MUTATOR_HOOKFUNCTION(ka, HavocBot_ChooseRole)
559{
560 entity bot = M_ARGV(0, entity);
561
562 if (bot.ballcarried)
563 bot.havocbot_role = havocbot_role_ka_carrier;
564 else
565 bot.havocbot_role = havocbot_role_ka_collector;
566 return true;
567}
568
569MUTATOR_HOOKFUNCTION(ka, DropSpecialItems)
570{
572
573 while (frag_target.ballcarried)
575}
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_dynamicgoal_init(entity this, bool initially_static)
Definition navigation.qc:77
void navigation_routerating(entity this, entity e, float f, float rangebias)
void navigation_dynamicgoal_set(entity this, entity dropper)
Definition navigation.qc:87
void navigation_goalrating_timeout_expire(entity this, float seconds)
Definition navigation.qc:36
void navigation_goalrating_end(entity this)
void navigation_dynamicgoal_unset(entity this)
Definition navigation.qc:96
#define MUTATOR_HOOKFUNCTION(...)
Definition base.qh:335
#define MUTATOR_RETURNVALUE
Definition base.qh:328
#define BITSET(var, mask, flag)
Definition bits.qh:11
var entity(vector mins, vector maxs,.entity tofield) findbox_tofield_OrFallback
float cnt
Definition powerups.qc:24
bool pushable
Definition items.qc:14
float alpha
Definition items.qc:13
float wait
Definition items.qc:17
entity owner
Definition main.qh:87
bool warmup_stage
Definition main.qh:120
int team
Definition main.qh:188
#define setmodel(this, m)
Definition model.qh:26
#define M_ARGV(x, type)
Definition events.qh:17
#define IS_DEAD(s)
Definition player.qh:245
#define IS_PLAYER(s)
Definition player.qh:243
float game_starttime
Definition stats.qh:82
float game_stopped
Definition stats.qh:81
const int FL_ITEM
Definition constants.qh:77
float Q3SURFACEFLAG_SKY
float DPCONTENTS_SKY
const float SOLID_TRIGGER
float DPCONTENTS_DONOTENTER
float DPCONTENTS_SOLID
float frametime
float DPCONTENTS_CORPSE
vector velocity
float DPCONTENTS_BODY
const float SOLID_NOT
float effects
float DPCONTENTS_PLAYERCLIP
float DPCONTENTS_SLIME
float time
float checkpvs(vector viewpos, entity viewee)
float nextthink
float trace_dphitq3surfaceflags
vector v_forward
vector origin
float DPCONTENTS_LAVA
float Q3SURFACEFLAG_NOIMPACT
float damagedbycontents
Definition damage.qh:45
IntrusiveList g_damagedbycontents
Definition damage.qh:135
void Send_Effect(entity eff, vector eff_loc, vector eff_vel, int eff_cnt)
Definition all.qc:124
ent angles
Definition ent_cs.qc:121
solid
Definition ent_cs.qc:165
void GameLogEcho(string s)
Definition gamelog.qc:15
bool autocvar_sv_eventlog
Definition gamelog.qh:3
ERASEABLE void IL_REMOVE(IntrusiveList this, entity it)
Remove any element, anywhere in the list.
ERASEABLE entity IL_PUSH(IntrusiveList this, entity it)
Push to tail.
#define IL_EACH(this, cond, body)
#define IL_EMPTY(this)
const int KA_CARRYING
Definition keepaway.qh:24
#define PlayerPreThink
Definition _all.inc:254
#define ClientDisconnect
Definition _all.inc:242
#define STAT(...)
Definition stats.qh:82
string ftos(float f)
#define MODEL(name, path)
Definition all.qh:8
void set_movetype(entity this, int mt)
Definition movetypes.qc:4
const int MOVETYPE_NONE
Definition movetypes.qh:129
const int MOVETYPE_BOUNCE
Definition movetypes.qh:139
var void func_null()
strcat(_("^F4Countdown stopped!"), "\n^BG", _("Teams are too unbalanced."))
void Send_Notification(NOTIF broadcast, entity client, MSG net_type, Notification net_name,...count)
Definition all.qc:1573
#define NULL
Definition post.qh:14
#define makevectors
Definition post.qh:21
vector view_ofs
Definition progsdefs.qc:151
float scale
Definition projectile.qc:14
#define crandom()
Returns a random number between -1.0 and 1.0.
Definition random.qh:32
#define setthink(e, f)
vector
Definition self.qh:92
vector org
Definition self.qh:92
entity entity toucher
Definition self.qh:72
#define settouch(e, f)
Definition self.qh:73
void PlayerUseKey(entity this)
Definition client.qc:2584
#define IS_INDEPENDENT_PLAYER(e)
Definition client.qh:312
IntrusiveList g_items
Definition items.qh:125
#define ITEM_DAMAGE_NEEDKILL(dt)
Definition items.qh:129
entity SelectSpawnPoint(entity this, bool anypoint)
const int CH_TRIGGER
Definition sound.qh:12
const float VOL_BASE
Definition sound.qh:36
const float ATTEN_NONE
Definition sound.qh:27
const float ATTEN_NORM
Definition sound.qh:30
#define sound(e, c, s, v, a)
Definition sound.qh:52
const int DAMAGE_YES
Definition subs.qh:80
const int DAMAGE_NO
Definition subs.qh:79
float takedamage
Definition subs.qh:78
float float2int_decimal_fld
entity frag_target
Definition sv_ctf.qc:2321
int autocvar_g_keepawayball_trail_color
entity ballcarried
#define BALL_XYSPEED
bool autocvar_g_keepaway_noncarrier_warn
vector autocvar_g_keepaway_ballcarrier_damage
int autocvar_g_keepawayball_tracking
void ka_DamageEvent(entity this, entity inflictor, entity attacker, float damage, int deathtype,.entity weaponentity, vector hitloc, vector force)
vector autocvar_g_keepaway_noncarrier_damage
void havocbot_role_ka_collector(entity this)
int autocvar_g_keepaway_ballcarrier_maxballs
float autocvar_g_keepawayball_respawntime
void ka_SpawnBalls()
int autocvar_g_keepaway_score_timepoints
bool ka_waypointsprite_visible_for_bot(entity this, entity e, bool dropped)
float autocvar_g_keepaway_ballcarrier_highspeed
void ka_BallThink_Carried(entity this)
runs (only) while a player is carrying the ball
int autocvar_g_keepawayball_effects
int autocvar_g_keepawayball_count
void ka_RespawnBall(entity this)
entity previous_owner
float autocvar_g_keepawayball_damageforcescale
void ka_DropEvent(entity player)
int autocvar_g_keepaway_score_bckill
vector autocvar_g_keepaway_ballcarrier_force
void havocbot_goalrating_ball(entity this, float ratingscale, vector org)
int autocvar_g_keepaway_score_killac
bool ka_ballcarrier_waypointsprite_visible_for_player(entity this, entity player, entity view)
void ka_PlayerReset(entity player)
void ka_TouchEvent(entity this, entity toucher)
vector autocvar_g_keepaway_noncarrier_force
void havocbot_role_ka_carrier(entity this)
#define BALL_XYDIST
void ka_RemoveBalls()
void ka_EventLog(string mode, entity actor)
void ka_Handler_CheckBall(entity this)
IntrusiveList g_kaballs
Definition sv_keepaway.qh:8
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
#define GameRules_scoring_add_float2int(client, fld, value, float_field, score_factor)
Definition sv_rules.qh:83
#define GameRules_scoring_vip(player, value)
Definition sv_rules.qh:78
#define GameRules_scoring_add(client, fld, value)
Definition sv_rules.qh:85
#define IS_INVISIBLE(v)
Definition utils.qh:27
#define IS_SPEC(v)
Definition utils.qh:10
#define FOREACH_CLIENT(cond, body)
Definition utils.qh:50
#define vec3(_x, _y, _z)
Definition vector.qh:95
void WaypointSprite_Kill(entity wp)
void WaypointSprite_Ping(entity e)
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_getviewentity(entity e)
entity WaypointSprite_AttachCarrier(entity spr, entity carrier, entity icon)
void WaypointSprite_DetachCarrier(entity carrier)
void WaypointSprite_UpdateRule(entity e, float t, float r)
const int SPRITERULE_DEFAULT
entity waypointsprite_attachedforcarrier
float MoveToRandomMapLocation(entity e, float goodcontents, float badcontents, float badsurfaceflags, float attempts, float maxaboveground, float minviewdistance)
Definition world.qc:1231