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

Go to the source code of this file.

Macros

#define TRY(x)
#define X(class, prefix, fld, type)

Functions

void load_unit_settings (entity ent, bool is_reload)
vector turret_aim_generic (entity this)
bool turret_checkfire (entity this)
bool turret_closetotarget (entity this, vector targ, float range)
void turret_damage (entity this, entity inflictor, entity attacker, float damage, int deathtype,.entity weaponentity, vector hitloc, vector vforce)
void turret_die (entity this)
void turret_do_updates (entity t_turret)
 updates enemy distances, predicted impact point/time and updated aim<->predict impact distance.
void turret_findtarget (entity this)
void turret_fire (entity this)
bool turret_firecheck (entity this)
 Preforms pre-fire checks based on the uints firecheck_flags.
bool turret_heal (entity targ, entity inflictor, float amount, float limit)
void turret_hide (entity this)
bool turret_initialize (entity this, Turret tur)
void turret_initparams (entity tur)
void turret_link (entity this)
entity turret_projectile (entity actor, Sound _snd, float _size, float _health, float _death, float _proj_type, float _cull, float _cli_anim)
void turret_projectile_damage (entity this, entity inflictor, entity attacker, float damage, int deathtype,.entity weaponentity, vector hitloc, vector vforce)
void turret_projectile_explode (entity this)
void turret_projectile_touch (entity this, entity toucher)
void turret_reset (entity this)
void turret_respawn (entity this)
entity turret_select_target (entity this)
bool turret_send (entity this, entity to, int sf)
float turret_targetscore_generic (entity _turret, entity _target)
float turret_targetscore_support (entity _turret, entity _target)
void turret_think (entity this)
void turret_track (entity this)
void turret_use (entity this, entity actor, entity trigger)
float turret_validate_target (entity e_turret, entity e_target, float validate_flags)
 Evaluate a entity for target valitity based on validate_flags NOTE: the caller must check takedamage before calling this, to inline this check.
void turrets_manager_think (entity this)
void turrets_setframe (entity this, float _frame, float client_only)

Variables

float clientframe
float turret_framecounter
 Handles head rotation according to the units .track_type and .track_flags.

Macro Definition Documentation

◆ TRY

#define TRY ( x)
Value:
(x) ? (x)

Referenced by turret_initparams().

◆ X

#define X ( class,
prefix,
fld,
type )
Value:
ent.fld = cvar(strcat("g_turrets_unit_", prefix, "_", #fld));
float cvar(string name)
strcat(_("^F4Countdown stopped!"), "\n^BG", _("Teams are too unbalanced."))

Function Documentation

◆ load_unit_settings()

void load_unit_settings ( entity ent,
bool is_reload )

Definition at line 365 of file sv_turrets.qc.

366{
367 if (ent == NULL)
368 return;
369
370 if (!ent.turret_scale_damage) ent.turret_scale_damage = 1;
371 if (!ent.turret_scale_range) ent.turret_scale_range = 1;
372 if (!ent.turret_scale_refire) ent.turret_scale_refire = 1;
373 if (!ent.turret_scale_ammo) ent.turret_scale_ammo = 1;
374 if (!ent.turret_scale_aim) ent.turret_scale_aim = 1;
375 if (!ent.turret_scale_health) ent.turret_scale_health = 1;
376 if (!ent.turret_scale_respawn) ent.turret_scale_respawn = 1;
377
378 if (is_reload)
379 {
380 ent.enemy = NULL;
381 ent.tur_head.avelocity = '0 0 0';
382
383 ent.tur_head.angles = '0 0 0';
384 }
385
386 string unitname = ent.netname;
387 #define X(class, prefix, fld, type) ent.fld = cvar(strcat("g_turrets_unit_", prefix, "_", #fld));
388 TR_PROPS_COMMON(X, , unitname)
389 #undef X
390
391 ent.ammo_max *= ent.turret_scale_ammo;
392 ent.ammo_recharge *= ent.turret_scale_ammo;
393 ent.aim_speed *= ent.turret_scale_aim;
394 SetResourceExplicit(ent, RES_HEALTH, GetResource(ent, RES_HEALTH) * ent.turret_scale_health);
395 ent.respawntime *= ent.turret_scale_respawn;
396 ent.shot_dmg *= ent.turret_scale_damage;
397 ent.shot_refire *= ent.turret_scale_refire;
398 ent.shot_radius *= ent.turret_scale_damage;
399 ent.shot_force *= ent.turret_scale_damage;
400 ent.shot_volly_refire *= ent.turret_scale_refire;
401 ent.target_range *= ent.turret_scale_range;
402 ent.target_range_min *= ent.turret_scale_range;
403 ent.target_range_optimal *= ent.turret_scale_range;
404
405 if (is_reload)
406 {
407 Turret tur = get_turretinfo(ent.m_id);
408 tur.tr_setup(tur, ent);
409 }
410}
float GetResource(entity e, Resource res_type)
Returns the current amount of resource the given entity has.
bool SetResourceExplicit(entity e, Resource res_type, float amount)
Sets the resource amount of an entity without calling any hooks.
virtual void tr_setup()
(BOTH) setup turret data
Definition turret.qh:36
#define X()
#define NULL
Definition post.qh:14
#define get_turretinfo(i)
Definition all.qh:9
#define TR_PROPS_COMMON(P, class, prefix)
Definition all.qh:13

References entity(), get_turretinfo, GetResource(), NULL, SetResourceExplicit(), TR_PROPS_COMMON, Turret::tr_setup(), and X.

Referenced by turret_initialize(), and turrets_manager_think().

◆ turret_aim_generic()

vector turret_aim_generic ( entity this)

Definition at line 12 of file sv_turrets.qc.

13{
15
16 if (this.aim_flags & TFL_AIM_SIMPLE)
17 return real_origin(this.enemy);
18
19 // Baseline
20 vector pre_pos = real_origin(this.enemy);
21
22 // Lead?
23 if (this.aim_flags & TFL_AIM_LEAD)
24 {
25 float mintime = max(this.attack_finished_single[0] - time, 0) + sys_frametime;
26
27 if (this.aim_flags & TFL_AIM_SHOTTIMECOMPENSATE) // Need to conpensate for shot traveltime
28 {
29 vector prep = pre_pos;
30
31 float impact_time = vlen(prep - this.tur_shotorg) / this.shot_speed;
32
33 prep += this.enemy.velocity * (impact_time + mintime);
34
35 if ((this.aim_flags & TFL_AIM_ZPREDICT)
36 && !IS_ONGROUND(this.enemy)
37 && (this.enemy.move_movetype == MOVETYPE_WALK || this.enemy.move_movetype == MOVETYPE_TOSS || this.enemy.move_movetype == MOVETYPE_BOUNCE))
38 {
39 prep.z = pre_pos.z;
40 float vz = this.enemy.velocity.z;
41 for (float i = 0; i < impact_time; i += sys_frametime)
42 {
44 prep.z += vz * sys_frametime;
45 }
46 }
47 pre_pos = prep;
48 }
49 else
50 pre_pos += this.enemy.velocity * mintime;
51 }
52
53 if (this.aim_flags & TFL_AIM_SPLASH)
54 {
55 //tracebox(pre_pos + '0 0 32', this.enemy.mins, this.enemy.maxs, pre_pos -'0 0 64', MOVE_WORLDONLY, this.enemy);
56 traceline(pre_pos + '0 0 32', pre_pos - '0 0 64', MOVE_WORLDONLY, this.enemy);
57 if (trace_fraction != 1.0)
58 pre_pos = trace_endpos;
59 }
60
61 return pre_pos;
62}
#define autocvar_sv_gravity
Definition stats.qh:423
float turret_tag_fire_update(entity this)
Update this.tur_shotorg by getting up2date bone info NOTICE this func overwrites the global v_forward...
Definition util.qc:9
vector real_origin(entity ent)
Definition util.qc:147
float time
vector trace_endpos
float MOVE_WORLDONLY
float trace_fraction
float vlen(vector v)
float max(float f,...)
const int MOVETYPE_WALK
Definition movetypes.qh:132
const int MOVETYPE_TOSS
Definition movetypes.qh:135
const int MOVETYPE_BOUNCE
Definition movetypes.qh:139
#define IS_ONGROUND(s)
Definition movetypes.qh:16
vector
Definition self.qh:92
float sys_frametime
Definition common.qh:57
entity enemy
Definition sv_ctf.qh:153
vector tur_shotorg
Definition sv_turrets.qh:30
const int TFL_AIM_LEAD
try to predict target movement
Definition turret.qh:100
const int TFL_AIM_SPLASH
aim for ground around the target's feet
Definition turret.qh:99
const int TFL_AIM_ZPREDICT
predict target's z position at impact
Definition turret.qh:102
const int TFL_AIM_SHOTTIMECOMPENSATE
compensate for shot traveltime when leading
Definition turret.qh:101
int aim_flags
Definition turret.qh:97
const int TFL_AIM_SIMPLE
aim at player's current location
Definition turret.qh:103
float attack_finished_single[MAX_WEAPONSLOTS]

References aim_flags, attack_finished_single, autocvar_sv_gravity, enemy, entity(), IS_ONGROUND, max(), MOVE_WORLDONLY, MOVETYPE_BOUNCE, MOVETYPE_TOSS, MOVETYPE_WALK, real_origin(), sys_frametime, TFL_AIM_LEAD, TFL_AIM_SHOTTIMECOMPENSATE, TFL_AIM_SIMPLE, TFL_AIM_SPLASH, TFL_AIM_ZPREDICT, time, trace_endpos, trace_fraction, tur_shotorg, turret_tag_fire_update(), vector, and vlen().

Referenced by turret_think().

◆ turret_checkfire()

bool turret_checkfire ( entity this)

Definition at line 952 of file sv_turrets.qc.

953{
954 if (MUTATOR_CALLHOOK(Turret_CheckFire, this))
955 return M_ARGV(1, bool);
956
957 return this.turret_firecheckfunc(this);
958}
#define MUTATOR_CALLHOOK(id,...)
Definition base.qh:143
#define M_ARGV(x, type)
Definition events.qh:17

References entity(), M_ARGV, and MUTATOR_CALLHOOK.

Referenced by turret_think().

◆ turret_closetotarget()

bool turret_closetotarget ( entity this,
vector targ,
float range )

Definition at line 1212 of file sv_turrets.qc.

1213{
1214 vector path_extra_size = '1 1 1' * range;
1215 return boxesoverlap(targ - path_extra_size, targ + path_extra_size, this.absmin - path_extra_size, this.absmax + path_extra_size);
1216}
vector absmax
vector absmin
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

References absmax, absmin, boxesoverlap(), entity(), and vector.

Referenced by ewheel_move_path(), Monster_Move(), and walker_move_path().

◆ turret_damage()

void turret_damage ( entity this,
entity inflictor,
entity attacker,
float damage,
int deathtype,
.entity weaponentity,
vector hitloc,
vector vforce )

Definition at line 207 of file sv_turrets.qc.

208{
209 // Enough already!
210 if (this.deadflag == DEAD_DEAD)
211 return;
212
213 // Inactive turrets take no damage. (hm..)
214 if (!this.active)
215 return;
216
217 if (SAME_TEAM(this, attacker))
218 {
220 damage *= autocvar_g_friendlyfire;
221 else
222 return;
223 }
224
225 TakeResource(this, RES_HEALTH, damage);
226
227 // thorw head slightly off aim when hit?
229 {
230 this.tur_head.angles.x += (random() - 0.5) * damage;
231 this.tur_head.angles.y += (random() - 0.5) * damage;
232
233 this.SendFlags |= TNSF_ANG;
234 }
235
236 if (this.turret_flags & TUR_FLAG_MOVE)
237 this.velocity += vforce;
238
239 if (GetResource(this, RES_HEALTH) <= 0)
240 {
241 this.event_damage = func_null;
242 this.tur_head.event_damage = func_null;
243 this.event_heal = func_null;
244 this.tur_head.event_heal = func_null;
245 this.takedamage = DAMAGE_NO;
246 this.nextthink = time;
247 setthink(this, turret_die);
248 }
249
250 this.SendFlags |= TNSF_STATUS;
251}
void TakeResource(entity receiver, Resource res_type, float amount)
Takes an entity some resource.
void turret_die(entity this)
vector velocity
float nextthink
float autocvar_g_friendlyfire
Definition damage.qh:26
int active
Definition defs.qh:34
int SendFlags
Definition net.qh:159
float random(void)
var void func_null()
float deadflag
Definition progsdefs.qc:149
float DEAD_DEAD
Definition progsdefs.qc:276
#define setthink(e, f)
const int DAMAGE_NO
Definition subs.qh:79
float takedamage
Definition subs.qh:78
entity tur_head
Definition sv_turrets.qh:28
#define SAME_TEAM(a, b)
Definition teams.qh:241
const int TFL_DMG_HEADSHAKE
damage shakes head
Definition turret.qh:173
const int TNSF_ANG
Definition turret.qh:188
int turret_flags
Definition turret.qh:136
int damage_flags
Definition turret.qh:165
const int TNSF_STATUS
Definition turret.qh:186
const int TUR_FLAG_MOVE
can move
Definition turret.qh:151

References active, autocvar_g_friendlyfire, damage_flags, DAMAGE_NO, DEAD_DEAD, deadflag, entity(), func_null(), GetResource(), nextthink, random(), SAME_TEAM, SendFlags, setthink, takedamage, TakeResource(), TFL_DMG_HEADSHAKE, time, TNSF_ANG, TNSF_STATUS, TUR_FLAG_MOVE, tur_head, turret_die(), turret_flags, vector, and velocity.

Referenced by turret_initialize(), and turret_respawn().

◆ turret_die()

void turret_die ( entity this)

Definition at line 166 of file sv_turrets.qc.

167{
168 this.deadflag = DEAD_DEAD;
169 this.tur_head.deadflag = this.deadflag;
170
171 // Unsolidify and hide real parts
172 this.solid = SOLID_NOT;
173 this.tur_head.solid = this.solid;
174
175 this.event_damage = func_null;
176 this.event_heal = func_null;
177 this.takedamage = DAMAGE_NO;
178
179 SetResourceExplicit(this, RES_HEALTH, 0);
180
181 // Go boom
182 //RadiusDamage(this, this, min(this.ammo, 50), min(this.ammo, 50) * 0.25, 250, NULL, min(this.ammo, 50) * 5, DEATH_TURRET, NULL);
183
184 Turret tur = get_turretinfo(this.m_id);
186 {
187 // do a simple explosion effect here, since CSQC can't do it on a to-be-removed entity
188 sound(this, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
189 Send_Effect(EFFECT_ROCKET_EXPLODE, this.origin, '0 0 0', 1);
190
191 tur.tr_death(tur, this);
192
193 delete(this.tur_head);
194 delete(this);
195 }
196 else
197 {
198 // Setup respawn
199 this.SendFlags |= TNSF_STATUS;
200 this.nextthink = time + 0.2;
201 setthink(this, turret_hide);
202
203 tur.tr_death(tur, this);
204 }
205}
virtual void tr_death()
(SERVER) called when turret dies
Definition turret.qh:42
const float SOLID_NOT
vector origin
int m_id
Definition effect.qh:19
void Send_Effect(entity eff, vector eff_loc, vector eff_vel, int eff_cnt)
Definition all.qc:120
solid
Definition ent_cs.qc:165
const float VOL_BASE
Definition sound.qh:36
const int CH_SHOTS
Definition sound.qh:14
const float ATTEN_NORM
Definition sound.qh:30
#define sound(e, c, s, v, a)
Definition sound.qh:52
void turret_hide(entity this)
const int TFL_DMG_DEATH_NORESPAWN
no re-spawning
Definition turret.qh:174

References ATTEN_NORM, CH_SHOTS, damage_flags, DAMAGE_NO, DEAD_DEAD, deadflag, entity(), func_null(), get_turretinfo, m_id, nextthink, origin, Send_Effect(), SendFlags, SetResourceExplicit(), setthink, solid, SOLID_NOT, sound, takedamage, TFL_DMG_DEATH_NORESPAWN, time, TNSF_STATUS, Turret::tr_death(), tur_head, turret_hide(), and VOL_BASE.

◆ turret_do_updates()

void turret_do_updates ( entity t_turret)

updates enemy distances, predicted impact point/time and updated aim<->predict impact distance.

updates aim org, shot org, shot dir and enemy org for selected turret

Definition at line 496 of file sv_turrets.qc.

497{
498 vector enemy_pos = real_origin(t_turret.enemy);
499
500 turret_tag_fire_update(t_turret);
501
502 t_turret.tur_shotdir_updated = v_forward;
503 t_turret.tur_dist_enemy = vlen(t_turret.tur_shotorg - enemy_pos);
504 t_turret.tur_dist_aimpos = vlen(t_turret.tur_shotorg - t_turret.tur_aimpos);
505
506 /*if ((t_turret.firecheck_flags & TFL_FIRECHECK_VERIFIED) && t_turret.enemy)
507 {
508 oldpos = t_turret.enemy.origin;
509 setorigin(t_turret.enemy, t_turret.tur_aimpos);
510 tracebox(t_turret.tur_shotorg, '-1 -1 -1', '1 1 1', t_turret.tur_shotorg + t_turret.tur_shotdir_updated * t_turret.tur_dist_aimpos, MOVE_NORMAL, t_turret);
511 setorigin(t_turret.enemy, oldpos);
512
513 if (trace_ent == t_turret.enemy)
514 t_turret.tur_dist_impact_to_aimpos = 0;
515 else
516 t_turret.tur_dist_impact_to_aimpos = vlen(trace_endpos - t_turret.tur_aimpos);
517 }
518 else*/
519 tracebox(t_turret.tur_shotorg, '-1 -1 -1', '1 1 1', t_turret.tur_shotorg + t_turret.tur_shotdir_updated * t_turret.tur_dist_aimpos, MOVE_NORMAL, t_turret);
520
521 t_turret.tur_dist_impact_to_aimpos = vlen(trace_endpos - t_turret.tur_aimpos) - 0.5 * vlen(t_turret.enemy.maxs - t_turret.enemy.mins);
522 t_turret.tur_impactent = trace_ent;
523 t_turret.tur_impacttime = vlen(t_turret.tur_shotorg - trace_endpos) / t_turret.shot_speed;
524}
entity trace_ent
const float MOVE_NORMAL
vector v_forward

References entity(), MOVE_NORMAL, real_origin(), trace_endpos, trace_ent, turret_tag_fire_update(), v_forward, vector, and vlen().

Referenced by beam_think(), and turret_think().

◆ turret_findtarget()

void turret_findtarget ( entity this)

Definition at line 1218 of file sv_turrets.qc.

1219{
1220 entity e = find(NULL, classname, "turret_manager");
1221 if (!e)
1222 {
1223 e = new_pure(turret_manager);
1225 e.nextthink = time + 2;
1226 }
1227
1228 entity targ = find(NULL, targetname, this.target);
1229 if (targ.classname == "turret_checkpoint")
1230 return; // turrets don't defend checkpoints?
1231
1232 if (!targ)
1233 {
1234 this.target = "";
1235 LOG_TRACE("Turret has invalid defendpoint!");
1236 }
1237
1238 this.tur_defend = targ;
1239 this.idle_aim = this.tur_head.angles + angleofs(this.tur_head, targ);
1240}
#define angleofs(from, to)
Definition angle.qc:88
var entity(vector mins, vector maxs,.entity tofield) findbox_tofield_OrFallback
string classname
#define LOG_TRACE(...)
Definition log.qh:76
entity find(entity start,.string field, string match)
#define new_pure(class)
purely logical entities (not linked to the area grid)
Definition oo.qh:67
void turrets_manager_think(entity this)
vector idle_aim
Definition sv_turrets.qh:44
entity tur_defend
Definition sv_turrets.qh:29
string targetname
Definition triggers.qh:56
string target
Definition triggers.qh:55

References angleofs, classname, entity(), find(), idle_aim, LOG_TRACE, new_pure, NULL, setthink, target, targetname, time, tur_defend, tur_head, and turrets_manager_think().

Referenced by turret_initialize().

◆ turret_fire()

void turret_fire ( entity this)

Definition at line 960 of file sv_turrets.qc.

961{
963 return;
964 if (MUTATOR_CALLHOOK(TurretFire, this))
965 return;
966
967 Turret info = get_turretinfo(this.m_id);
968 info.tr_attack(info, this);
969
970 this.attack_finished_single[0] = time + this.shot_refire;
971 this.ammo -= this.shot_dmg;
972 --this.volly_counter;
973
974 if (this.volly_counter <= 0)
975 {
976 this.volly_counter = this.shot_volly;
977
979 this.enemy = NULL;
980
981 if (this.shot_volly > 1)
982 this.attack_finished_single[0] = time + this.shot_volly_refire;
983 }
984
985#ifdef TURRET_DEBUG
986 if (this.enemy)
987 paint_target3(this.tur_aimpos, 64, this.tur_debug_rvec, this.tur_impacttime + 0.25);
988#endif
989}
virtual void tr_attack()
(SERVER) called when turret attacks
Definition turret.qh:51
float volly_counter
Definition sv_turrets.qh:37
bool autocvar_g_turrets_nofire
Definition sv_turrets.qh:7
float ammo
Definition sv_turrets.qh:43
vector tur_aimpos
Definition sv_turrets.qh:31
float tur_impacttime
Definition sv_turrets.qh:32
const int TFL_SHOOT_CLEARTARGET
lose target after attack (after volly is done if in volly mode)
Definition turret.qh:132
int shoot_flags
Definition turret.qh:127

References ammo, attack_finished_single, autocvar_g_turrets_nofire, enemy, entity(), get_turretinfo, m_id, MUTATOR_CALLHOOK, NULL, shoot_flags, TFL_SHOOT_CLEARTARGET, time, Turret::tr_attack(), tur_aimpos, tur_impacttime, and volly_counter.

Referenced by turret_think().

◆ turret_firecheck()

bool turret_firecheck ( entity this)

Preforms pre-fire checks based on the uints firecheck_flags.

Definition at line 874 of file sv_turrets.qc.

875{
876 // This one just dont care =)
878 return true;
879
880 if (this.enemy == NULL)
881 return false;
882
883 // Ready?
885 && this.attack_finished_single[0] > time)
886 return false;
887
888 // Special case: volly fire turret that has to fire a full volly if a shot was fired.
890 && this.volly_counter != this.shot_volly
891 && this.ammo >= this.shot_dmg)
892 return true;
893
894 // Lack of zombies makes shooting dead things unnecessary :P
896 && IS_DEAD(this.enemy))
897 return false;
898
899 // Own ammo?
901 && this.ammo < this.shot_dmg)
902 return false;
903
904 // Other's ammo? (support-supply units)
906 && this.enemy.ammo >= this.enemy.ammo_max)
907 return false;
908
909 // Target of opertunity?
911 {
912 this.enemy = this.tur_impactent;
913 return true;
914 }
915
917 {
918 // To close?
919 if (this.tur_dist_aimpos < this.target_range_min)
920 {
922 return true; // Target of opertunity?
923 return false;
924 }
925 }
926
927 // Try to avoid FF?
929 && SAME_TEAM(this.tur_impactent, this))
930 return false;
931
932 // aim<->predicted impact
934 && this.tur_dist_impact_to_aimpos > this.aim_firetolerance_dist)
935 return false;
936
937 // Volly status
938 if (this.shot_volly > 1
939 && this.volly_counter == this.shot_volly
940 && this.ammo < this.shot_dmg * this.shot_volly)
941 return false;
942
943 /*
944 if ((this.firecheck_flags & TFL_FIRECHECK_VERIFIED)
945 && this.tur_impactent != this.enemy)
946 return false;
947 */
948
949 return true;
950}
#define IS_DEAD(s)
Definition player.qh:244
float turret_validate_target(entity e_turret, entity e_target, float validate_flags)
Evaluate a entity for target valitity based on validate_flags NOTE: the caller must check takedamage ...
entity tur_impactent
Definition sv_turrets.qh:33
float tur_dist_aimpos
Definition sv_turrets.qh:35
float tur_dist_impact_to_aimpos
Definition sv_turrets.qh:36
const int TFL_FIRECHECK_DISTANCES
another range check
Definition turret.qh:114
const int TFL_FIRECHECK_AMMO_OWN
own ammo needs to be larger than damage dealt
Definition turret.qh:121
int target_validate_flags
Definition turret.qh:80
const int TFL_SHOOT_VOLLYALWAYS
always do a full volly, even if target is lost
Definition turret.qh:130
const int TFL_FIRECHECK_DEAD
don't attack dead targets (zombies?)
Definition turret.qh:113
const int TFL_FIRECHECK_AIMDIST
consider distance impactpoint<->aimspot
Definition turret.qh:116
const int TFL_FIRECHECK_AMMO_OTHER
target's ammo needs to be less than max
Definition turret.qh:122
const int TFL_FIRECHECK_REFIRE
check single attack finished delays
Definition turret.qh:123
const int TFL_FIRECHECK_NO
no prefire checks
Definition turret.qh:124
int firecheck_flags
Definition turret.qh:112
const int TFL_FIRECHECK_AFF
try to avoid any friendly fire
Definition turret.qh:120

References ammo, attack_finished_single, enemy, entity(), firecheck_flags, IS_DEAD, NULL, SAME_TEAM, shoot_flags, target_validate_flags, TFL_FIRECHECK_AFF, TFL_FIRECHECK_AIMDIST, TFL_FIRECHECK_AMMO_OTHER, TFL_FIRECHECK_AMMO_OWN, TFL_FIRECHECK_DEAD, TFL_FIRECHECK_DISTANCES, TFL_FIRECHECK_NO, TFL_FIRECHECK_REFIRE, TFL_SHOOT_VOLLYALWAYS, time, tur_dist_aimpos, tur_dist_impact_to_aimpos, tur_impactent, turret_validate_target(), and volly_counter.

Referenced by turret_initialize(), turret_phaser_firecheck(), turret_tesla_firecheck(), and walker_firecheck().

◆ turret_heal()

bool turret_heal ( entity targ,
entity inflictor,
float amount,
float limit )

Definition at line 253 of file sv_turrets.qc.

254{
255 float true_limit = (limit != RES_LIMIT_NONE) ? limit : targ.max_health;
256 if (GetResource(targ, RES_HEALTH) <= 0 || GetResource(targ, RES_HEALTH) >= true_limit)
257 return false;
258
259 GiveResourceWithLimit(targ, RES_HEALTH, amount, true_limit);
260 targ.SendFlags |= TNSF_STATUS;
261 return true;
262}
float max_health
const int RES_LIMIT_NONE
Definition resources.qh:60
void GiveResourceWithLimit(entity receiver, Resource res_type, float amount, float limit)
Gives an entity some resource but not more than a limit.

References entity(), GetResource(), GiveResourceWithLimit(), RES_LIMIT_NONE, and TNSF_STATUS.

Referenced by turret_initialize(), and turret_respawn().

◆ turret_hide()

void turret_hide ( entity this)

Definition at line 159 of file sv_turrets.qc.

160{
161 this.effects |= EF_NODRAW;
162 this.nextthink = time + this.respawntime - 0.2;
164}
float effects
const float EF_NODRAW
float respawntime
Definition items.qh:31
void turret_respawn(entity this)

References EF_NODRAW, effects, entity(), nextthink, respawntime, setthink, time, and turret_respawn().

Referenced by turret_die().

◆ turret_initialize()

bool turret_initialize ( entity this,
Turret tur )

Definition at line 1247 of file sv_turrets.qc.

1248{
1249 if (!autocvar_g_turrets)
1250 return false;
1251
1252 if (tur.m_id == 0)
1253 return false; // invalid turret
1254
1255 // if tur_head exists, we can assume this turret re-spawned
1256 if (!this.tur_head)
1257 {
1258 tur.tr_precache(tur);
1259 IL_PUSH(g_turrets, this);
1260 IL_PUSH(g_bot_targets, this);
1261 }
1262
1263 if (!(this.spawnflags & TSF_SUSPENDED))
1265
1266 this.netname = tur.netname;
1267 load_unit_settings(this, 0);
1268
1269 if (!this.team || !teamplay) this.team = FLOAT_MAX;
1270 if (!GetResource(this, RES_HEALTH)) SetResourceExplicit(this, RES_HEALTH, 1000);
1271 if (!this.shot_refire) this.shot_refire = 1;
1272 if (!this.tur_shotorg) this.tur_shotorg = '50 0 50';
1276 if (!this.track_type) this.track_type = TFL_TRACKTYPE_STEPMOTOR;
1282
1283 if (this.track_type != TFL_TRACKTYPE_STEPMOTOR)
1284 {
1285 // Fluid / Ineria mode. Looks mutch nicer.
1286 // Can reduce aim preformance alot, needs a bit diffrent aimspeed
1287
1288 this.aim_speed = bound(0.1, (!this.aim_speed ? 180 : this.aim_speed), 1000);
1289
1290 if (!this.track_accel_pitch)
1291 this.track_accel_pitch = 0.5;
1292 if (!this.track_accel_rot)
1293 this.track_accel_rot = 0.5;
1294 if (!this.track_blendrate)
1295 this.track_blendrate = 0.35;
1296 }
1297
1298 turret_initparams(this);
1299
1301
1302 if (this.turret_flags & TUR_FLAG_SPLASH)
1303 this.aim_flags |= TFL_AIM_SPLASH;
1304
1305 if (this.turret_flags & TUR_FLAG_MISSILE)
1307
1308 if (this.turret_flags & TUR_FLAG_PLAYER)
1310
1311 if (this.spawnflags & TSL_NO_RESPAWN)
1313
1314 if (this.turret_flags & TUR_FLAG_SUPPORT)
1315 this.turret_score_target = turret_targetscore_support;
1316 else
1317 this.turret_score_target = turret_targetscore_generic;
1318
1319 ++turret_count;
1320
1321 _setmodel(this, tur.model);
1322 setsize(this, tur.m_mins, tur.m_maxs);
1323
1324 this.m_id = tur.m_id;
1325 this.active = ACTIVE_ACTIVE;
1326 this.effects = EF_NODRAW;
1327 this.netname = tur.m_name;
1328 this.max_health = GetResource(this, RES_HEALTH);
1330 this.ammo = this.ammo_max;
1331 this.solid = SOLID_BBOX;
1332 this.takedamage = DAMAGE_AIM;
1334 this.view_ofs = '0 0 0';
1335 this.idle_aim = '0 0 0';
1336 this.turret_firecheckfunc = turret_firecheck;
1337 this.event_damage = turret_damage;
1338 this.event_heal = turret_heal;
1339 this.use = turret_use;
1340 this.bot_attack = true;
1341 this.nextthink = time + 1;
1342 this.reset = turret_reset;
1343
1344 this.tur_head = new(turret_head);
1345 _setmodel(this.tur_head, tur.head_model);
1346 setsize(this.tur_head, '0 0 0', '0 0 0');
1347 setorigin(this.tur_head, '0 0 0');
1348 setattachment(this.tur_head, this, "tag_head");
1349
1350 this.tur_head.netname = this.tur_head.classname;
1351 this.tur_head.team = this.team;
1352 this.tur_head.owner = this;
1353 this.tur_head.takedamage = DAMAGE_NO;
1354 this.tur_head.solid = SOLID_NOT;
1356
1357 this.weaponentities[0] = this; // lol
1358
1359 if (!this.tur_defend && this.target != "")
1361
1362#ifdef TURRET_DEBUG
1363 this.tur_debug_start = this.nextthink;
1364 while (vdist(this.tur_debug_rvec, <, 2))
1365 this.tur_debug_rvec = randomvec() * 4;
1366
1367 this.tur_debug_rvec.x = fabs(this.tur_debug_rvec.x);
1368 this.tur_debug_rvec.y = fabs(this.tur_debug_rvec.y);
1369 this.tur_debug_rvec.z = fabs(this.tur_debug_rvec.z);
1370#endif
1371
1372 turret_link(this);
1373 turret_respawn(this);
1375
1376 tur.tr_setup(tur, this);
1377
1378 if (MUTATOR_CALLHOOK(TurretSpawn, this))
1379 return false;
1380
1381 return true;
1382}
float bot_attack
Definition api.qh:38
IntrusiveList g_bot_targets
Definition api.qh:149
string m_name
human readable name
Definition turret.qh:16
int m_id
Definition turret.qh:9
vector m_maxs
turret hitbox size
Definition turret.qh:31
virtual void tr_precache()
(BOTH) precaches models/sounds used by this turret
Definition turret.qh:46
vector m_mins
turret hitbox size
Definition turret.qh:29
int spawnflags
Definition turret.qh:27
string netname
Definition powerups.qc:20
int team
Definition main.qh:188
int spawnflags
Definition ammo.qh:15
const int INITPRIO_FINDTARGET
Definition constants.qh:96
const float SOLID_BBOX
#define use
const int ACTIVE_ACTIVE
Definition defs.qh:37
const float FLOAT_MAX
Definition float.qh:3
ERASEABLE entity IL_PUSH(IntrusiveList this, entity it)
Push to tail.
float bound(float min, float value, float max)
vector randomvec(void)
float fabs(float f)
void set_movetype(entity this, int mt)
Definition movetypes.qc:4
float move_movetype
Definition movetypes.qh:76
const int MOVETYPE_NOCLIP
Definition movetypes.qh:137
vector view_ofs
Definition progsdefs.qc:151
const int DAMAGE_AIM
Definition subs.qh:81
bool turret_heal(entity targ, entity inflictor, float amount, float limit)
void turret_findtarget(entity this)
float turret_targetscore_support(entity _turret, entity _target)
Definition sv_turrets.qc:64
void turret_damage(entity this, entity inflictor, entity attacker, float damage, int deathtype,.entity weaponentity, vector hitloc, vector vforce)
bool turret_firecheck(entity this)
Preforms pre-fire checks based on the uints firecheck_flags.
void turret_link(entity this)
void turret_use(entity this, entity actor, entity trigger)
void turret_reset(entity this)
float turret_targetscore_generic(entity _turret, entity _target)
Definition sv_turrets.qc:78
void turret_initparams(entity tur)
void load_unit_settings(entity ent, bool is_reload)
bool autocvar_g_turrets
Definition sv_turrets.qh:5
float turret_count
Definition sv_turrets.qh:90
IntrusiveList g_turrets
const float TFL_TRACKTYPE_STEPMOTOR
Definition sv_turrets.qh:62
bool teamplay
Definition teams.qh:59
const int TFL_TARGETSELECT_ANGLELIMITS
apply extra angular limits to target selection
Definition turret.qh:86
const int TUR_FLAG_SUPPORT
supports other units
Definition turret.qh:148
const int TSF_SUSPENDED
Definition turret.qh:177
const int TFL_TARGETSELECT_TEAMCHECK
don't attack teammates
Definition turret.qh:88
const int TUR_FLAG_MISSILE
can damage missiles
Definition turret.qh:147
const int TFL_DMG_YES
can be damaged
Definition turret.qh:167
const int TUR_FLAG_ISTURRET
identifies this unit as a turret
Definition turret.qh:153
const int TFL_TARGETSELECT_PLAYERS
target players
Definition turret.qh:83
int track_flags
Definition turret.qh:106
const int TUR_FLAG_PLAYER
can damage players
Definition turret.qh:146
const int TFL_TARGETSELECT_RANGELIMITS
limit target selection range
Definition turret.qh:87
const int TFL_TRACK_ROTATE
rotate head
Definition turret.qh:109
int target_select_flags
Definition turret.qh:79
const int TFL_DMG_AIMSHAKE
damage throws off aim
Definition turret.qh:172
const int TSL_NO_RESPAWN
don't re-spawn
Definition turret.qh:181
const int TFL_AMMO_ENERGY
uses power
Definition turret.qh:158
const int TFL_FIRECHECK_LOS
line of sight
Definition turret.qh:115
const int TFL_DMG_RETALIATE
target attackers
Definition turret.qh:169
const int TFL_TARGETSELECT_LOS
require line of sight to find targets
Definition turret.qh:82
const int TFL_AMMO_RECHARGE
regenerates ammo
Definition turret.qh:161
const int TFL_FIRECHECK_TEAMCHECK
don't attack teammates
Definition turret.qh:119
const int TFL_TRACK_PITCH
pitch head
Definition turret.qh:108
const int TUR_FLAG_SPLASH
can deal splash damage
Definition turret.qh:139
const int TFL_TARGETSELECT_MISSILES
target projectiles
Definition turret.qh:84
const int TUR_FLAG_MEDPROJ
turret fires medium projectiles
Definition turret.qh:144
#define ammo_flags
Definition turret.qh:156
#define vdist(v, cmp, f)
Vector distance comparison, avoids sqrt()
Definition vector.qh:8
entity weaponentities[MAX_WEAPONSLOTS]
Definition weapon.qh:17
void DropToFloor_QC_DelayedInit(entity this)
Definition world.qc:2428
void InitializeEntity(entity e, void(entity this) func, int order)
Definition world.qc:2230

References active, ACTIVE_ACTIVE, aim_flags, ammo, ammo_flags, autocvar_g_turrets, bot_attack, bound(), DAMAGE_AIM, damage_flags, DAMAGE_NO, DropToFloor_QC_DelayedInit(), EF_NODRAW, effects, entity(), fabs(), firecheck_flags, FLOAT_MAX, g_bot_targets, g_turrets, GetResource(), idle_aim, IL_PUSH(), InitializeEntity(), INITPRIO_FINDTARGET, load_unit_settings(), m_id, Turret::m_id, Turret::m_maxs, Turret::m_mins, Turret::m_name, max_health, move_movetype, MOVETYPE_NOCLIP, MUTATOR_CALLHOOK, netname, nextthink, randomvec(), set_movetype(), SetResourceExplicit(), solid, SOLID_BBOX, SOLID_NOT, spawnflags, Turret::spawnflags, takedamage, target, target_select_flags, target_validate_flags, team, teamplay, TFL_AIM_LEAD, TFL_AIM_SHOTTIMECOMPENSATE, TFL_AIM_SPLASH, TFL_AMMO_ENERGY, TFL_AMMO_RECHARGE, TFL_DMG_AIMSHAKE, TFL_DMG_DEATH_NORESPAWN, TFL_DMG_RETALIATE, TFL_DMG_YES, TFL_FIRECHECK_AIMDIST, TFL_FIRECHECK_AMMO_OWN, TFL_FIRECHECK_DEAD, TFL_FIRECHECK_DISTANCES, TFL_FIRECHECK_LOS, TFL_FIRECHECK_REFIRE, TFL_FIRECHECK_TEAMCHECK, TFL_TARGETSELECT_ANGLELIMITS, TFL_TARGETSELECT_LOS, TFL_TARGETSELECT_MISSILES, TFL_TARGETSELECT_PLAYERS, TFL_TARGETSELECT_RANGELIMITS, TFL_TARGETSELECT_TEAMCHECK, TFL_TRACK_PITCH, TFL_TRACK_ROTATE, TFL_TRACKTYPE_STEPMOTOR, time, Turret::tr_precache(), Turret::tr_setup(), track_flags, TSF_SUSPENDED, TSL_NO_RESPAWN, tur_defend, TUR_FLAG_ISTURRET, TUR_FLAG_MEDPROJ, TUR_FLAG_MISSILE, TUR_FLAG_PLAYER, TUR_FLAG_SPLASH, TUR_FLAG_SUPPORT, tur_head, tur_shotorg, turret_count, turret_damage(), turret_findtarget(), turret_firecheck(), turret_flags, turret_heal(), turret_initparams(), turret_link(), turret_reset(), turret_respawn(), turret_tag_fire_update(), turret_targetscore_generic(), turret_targetscore_support(), turret_use(), use, vdist, view_ofs, and weaponentities.

Referenced by spawnfunc(), spawnfunc(), spawnfunc(), spawnfunc(), spawnfunc(), spawnfunc(), spawnfunc(), spawnfunc(), spawnfunc(), spawnfunc(), spawnfunc(), and spawnfunc().

◆ turret_initparams()

void turret_initparams ( entity tur)

Definition at line 1183 of file sv_turrets.qc.

1184{
1185 #define TRY(x) (x) ? (x)
1186 tur.respawntime = max (-1, (TRY(tur.respawntime) : 60 ));
1187 tur.shot_refire = bound(0.01, (TRY(tur.shot_refire) : 1 ), 9999);
1188 tur.shot_dmg = max (1, (TRY(tur.shot_dmg) : tur.shot_refire * 50 ));
1189 tur.shot_radius = max (1, (TRY(tur.shot_radius) : tur.shot_dmg * 0.5 ));
1190 tur.shot_speed = max (1, (TRY(tur.shot_speed) : 2500 ));
1191 tur.shot_spread = bound(0.0001, (TRY(tur.shot_spread) : 0.0125 ), 500);
1192 tur.shot_force = bound(0.001, (TRY(tur.shot_force) : tur.shot_dmg * 0.5 + tur.shot_radius * 0.5 ), 5000);
1193 tur.shot_volly = bound(1, (TRY(tur.shot_volly) : 1 ), floor(tur.ammo_max / tur.shot_dmg));
1194 tur.shot_volly_refire = bound(tur.shot_refire, (TRY(tur.shot_volly_refire) : tur.shot_refire * tur.shot_volly ), 60);
1195 tur.target_range = bound(0, (TRY(tur.target_range) : tur.shot_speed * 0.5 ), max_shot_distance);
1196 tur.target_range_min = bound(0, (TRY(tur.target_range_min) : tur.shot_radius * 2 ), max_shot_distance);
1197 tur.target_range_optimal = bound(0, (TRY(tur.target_range_optimal) : tur.target_range * 0.5 ), max_shot_distance);
1198 tur.aim_maxrot = bound(0, (TRY(tur.aim_maxrot) : 90 ), 360);
1199 tur.aim_maxpitch = bound(0, (TRY(tur.aim_maxpitch) : 20 ), 90);
1200 tur.aim_speed = bound(0.1, (TRY(tur.aim_speed) : 36 ), 1000);
1201 tur.aim_firetolerance_dist = bound(0.1, (TRY(tur.aim_firetolerance_dist) : 5 + (tur.shot_radius * 2) ), max_shot_distance);
1202 tur.target_select_rangebias = bound(-10, (TRY(tur.target_select_rangebias) : 1 ), 10);
1203 tur.target_select_samebias = bound(-10, (TRY(tur.target_select_samebias) : 1 ), 10);
1204 tur.target_select_anglebias = bound(-10, (TRY(tur.target_select_anglebias) : 1 ), 10);
1205 tur.target_select_missilebias = bound(-10, (TRY(tur.target_select_missilebias) : 1 ), 10);
1206 tur.target_select_playerbias = bound(-10, (TRY(tur.target_select_playerbias) : 1 ), 10);
1207 tur.ammo_max = max (tur.shot_dmg, (TRY(tur.ammo_max) : tur.shot_dmg * 10 ));
1208 tur.ammo_recharge = max (0, (TRY(tur.ammo_recharge) : tur.shot_dmg * 0.5 ));
1209 #undef TRY
1210}
float floor(float f)
#define TRY(x)
int max_shot_distance
Definition weapon.qh:245

References bound(), entity(), floor(), max(), max_shot_distance, and TRY.

Referenced by turret_initialize().

◆ turret_link()

void turret_link ( entity this)

Definition at line 1158 of file sv_turrets.qc.

1159{
1160 Net_LinkEntity(this, true, 0, turret_send);
1161 setthink(this, turret_think);
1162 this.nextthink = time;
1163 this.tur_head.effects = EF_NODRAW;
1164}
void Net_LinkEntity(entity e, bool docull, float dt, bool(entity this, entity to, int sendflags) sendfunc)
Definition net.qh:167
bool turret_send(entity this, entity to, int sf)
void turret_think(entity this)

References EF_NODRAW, entity(), Net_LinkEntity(), nextthink, setthink, time, tur_head, turret_send(), and turret_think().

Referenced by turret_initialize().

◆ turret_projectile()

entity turret_projectile ( entity actor,
Sound _snd,
float _size,
float _health,
float _death,
float _proj_type,
float _cull,
float _cli_anim )

Definition at line 455 of file sv_turrets.qc.

456{
457 TC(Sound, _snd);
458
459 sound(actor, CH_WEAPON_A, _snd, VOL_BASE, ATTEN_NORM);
460 entity proj = spawn();
461 setorigin(proj, actor.tur_shotorg);
462 setsize(proj, '-0.5 -0.5 -0.5' * _size, '0.5 0.5 0.5' * _size);
463 proj.owner = actor;
464 proj.realowner = actor;
465 proj.bot_dodge = true;
466 proj.bot_dodgerating = actor.shot_dmg;
469 proj.nextthink = time + 9;
471 proj.velocity = normalize(actor.tur_shotdir_updated + randomvec() * actor.shot_spread) * actor.shot_speed;
472 proj.flags = FL_PROJECTILE;
473 IL_PUSH(g_projectiles, proj);
474 IL_PUSH(g_bot_dodge, proj);
475 proj.enemy = actor.enemy;
476 proj.projectiledeathtype = _death;
478 if (_health)
479 {
480 SetResourceExplicit(proj, RES_HEALTH, _health);
481 proj.takedamage = DAMAGE_YES;
482 proj.event_damage = turret_projectile_damage;
483 }
484 else
485 proj.flags |= FL_NOTARGET;
486
487 CSQCProjectile(proj, _cli_anim, _proj_type, _cull);
488
489 return proj;
490}
IntrusiveList g_bot_dodge
Definition api.qh:150
const int FL_PROJECTILE
Definition constants.qh:85
const int FL_NOTARGET
Definition constants.qh:76
#define spawn
void CSQCProjectile(entity e, float clientanimate, int type, float docull)
#define TC(T, sym)
Definition _all.inc:82
vector normalize(vector v)
const int MOVETYPE_FLYMISSILE
Definition movetypes.qh:138
#define settouch(e, f)
Definition self.qh:73
IntrusiveList g_projectiles
Definition common.qh:58
#define PROJECTILE_MAKETRIGGER(e)
Definition common.qh:34
const int CH_WEAPON_A
Definition sound.qh:7
const int DAMAGE_YES
Definition subs.qh:80
void turret_projectile_touch(entity this, entity toucher)
void turret_projectile_damage(entity this, entity inflictor, entity attacker, float damage, int deathtype,.entity weaponentity, vector hitloc, vector vforce)
void turret_projectile_explode(entity this)

References ATTEN_NORM, CH_WEAPON_A, CSQCProjectile(), DAMAGE_YES, entity(), FL_NOTARGET, FL_PROJECTILE, g_bot_dodge, g_projectiles, IL_PUSH(), MOVETYPE_FLYMISSILE, normalize(), PROJECTILE_MAKETRIGGER, randomvec(), set_movetype(), SetResourceExplicit(), setthink, settouch, sound, spawn, TC, time, turret_projectile_damage(), turret_projectile_explode(), turret_projectile_touch(), and VOL_BASE.

◆ turret_projectile_damage()

void turret_projectile_damage ( entity this,
entity inflictor,
entity attacker,
float damage,
int deathtype,
.entity weaponentity,
vector hitloc,
vector vforce )

Definition at line 446 of file sv_turrets.qc.

447{
448 this.velocity += vforce;
449 TakeResource(this, RES_HEALTH, damage);
450 //this.realowner = attacker; // Dont change realowner, it does not make much sense for turrets
451 if (GetResource(this, RES_HEALTH) <= 0)
453}
entity owner
Definition main.qh:87
void W_PrepareExplosionByDamage(entity this, entity attacker, void(entity this) explode)
Definition common.qc:87

References entity(), GetResource(), owner, TakeResource(), turret_projectile_explode(), vector, velocity, and W_PrepareExplosionByDamage().

Referenced by turret_projectile().

◆ turret_projectile_explode()

void turret_projectile_explode ( entity this)

Definition at line 412 of file sv_turrets.qc.

413{
414 this.takedamage = DAMAGE_NO;
415 this.event_damage = func_null;
416
417#ifdef TURRET_DEBUG
418 float d = RadiusDamage(this, this.owner,
419#else
420 RadiusDamage(this, this.realowner,
421#endif
422 this.owner.shot_dmg,
423 0,
424 this.owner.shot_radius,
425 this,
426 NULL,
427 this.owner.shot_force,
428 this.projectiledeathtype,
429 DMG_NOWEP,
430 NULL
431 );
432#ifdef TURRET_DEBUG
433 this.owner.tur_debug_dmg_t_h += d;
434 this.owner.tur_debug_dmg_t_f += this.owner.shot_dmg;
435#endif
436
437 delete(this);
438}
float RadiusDamage(entity inflictor, entity attacker, float coredamage, float edgedamage, float rad, entity cantbe, entity mustbe, float forceintensity, int deathtype,.entity weaponentity, entity directhitentity)
Definition damage.qc:943
#define DMG_NOWEP
Definition damage.qh:104
entity realowner

References DAMAGE_NO, DMG_NOWEP, entity(), func_null(), NULL, owner, RadiusDamage(), realowner, and takedamage.

Referenced by turret_hellion_missile_think(), turret_hk_missile_think(), turret_projectile(), turret_projectile_damage(), and turret_projectile_touch().

◆ turret_projectile_touch()

void turret_projectile_touch ( entity this,
entity toucher )

Definition at line 440 of file sv_turrets.qc.

441{
444}
entity entity toucher
Definition self.qh:72
#define PROJECTILE_TOUCH(e, t)
Definition common.qh:28

References entity(), PROJECTILE_TOUCH, toucher, and turret_projectile_explode().

Referenced by turret_projectile().

◆ turret_reset()

void turret_reset ( entity this)

Definition at line 1242 of file sv_turrets.qc.

1243{
1244 turret_respawn(this);
1245}

References entity(), and turret_respawn().

Referenced by turret_initialize().

◆ turret_respawn()

void turret_respawn ( entity this)

Definition at line 265 of file sv_turrets.qc.

266{
267 // Make sure all parts belong to the same team since
268 // this function doubles as "teamchange" function.
269 this.tur_head.team = this.team;
270 this.effects &= ~EF_NODRAW;
271 this.deadflag = DEAD_NO;
273 this.solid = SOLID_BBOX;
274 this.takedamage = DAMAGE_AIM;
275 this.event_damage = turret_damage;
276 this.event_heal = turret_heal;
277 this.avelocity = '0 0 0';
278 this.tur_head.avelocity = this.avelocity;
279 this.tur_head.angles = this.idle_aim;
280 SetResourceExplicit(this, RES_HEALTH, this.max_health);
281 this.enemy = NULL;
282 this.volly_counter = this.shot_volly;
283 this.ammo = this.ammo_max;
284
285 this.nextthink = time;
286 setthink(this, turret_think);
287
289
290 Turret tur = get_turretinfo(this.m_id);
291 tur.tr_setup(tur, this);
292
293 setorigin(this, this.origin); // make sure it's linked to the area grid
294}
vector avelocity
float EF_LOWPRECISION
float DEAD_NO
Definition progsdefs.qc:274
const int TNSF_FULL_UPDATE
Definition turret.qh:194

References ammo, avelocity, DAMAGE_AIM, DEAD_NO, deadflag, EF_LOWPRECISION, EF_NODRAW, effects, enemy, entity(), get_turretinfo, idle_aim, m_id, max_health, nextthink, NULL, origin, SendFlags, SetResourceExplicit(), setthink, solid, SOLID_BBOX, takedamage, team, time, TNSF_FULL_UPDATE, Turret::tr_setup(), tur_head, turret_damage(), turret_heal(), turret_think(), and volly_counter.

Referenced by assault_roundstart_use(), MUTATOR_HOOKFUNCTION(), turret_hide(), turret_initialize(), and turret_reset().

◆ turret_select_target()

entity turret_select_target ( entity this)

Definition at line 809 of file sv_turrets.qc.

810{
811 entity e; // target looper entity
812 float score; // target looper entity score
813 entity e_enemy; // currently best scoreing target
814 float m_score; // currently best scoreing target's score
815
816 m_score = 0;
817 if (this.enemy && this.enemy.takedamage && turret_validate_target(this, this.enemy, this.target_validate_flags) > 0)
818 {
819 e_enemy = this.enemy;
820 m_score = this.turret_score_target(this, e_enemy) * this.target_select_samebias;
821 }
822 else
823 e_enemy = this.enemy = NULL;
824
825 e = findradius(this.origin, this.target_range);
826
827 // Nothing to aim at?
828 if (!e)
829 return NULL;
830
831 float f;
832 for (; e; e = e.chain)
833 if (e.takedamage)
834 {
836 //dprint("F is: ", ftos(f), "\n");
837 if (f > 0)
838 {
839 score = this.turret_score_target(this, e);
840 if (score > m_score && score > 0)
841 {
842 e_enemy = e;
843 m_score = score;
844 }
845 }
846 }
847
848 return e_enemy;
849}

References enemy, entity(), NULL, origin, target_select_flags, target_validate_flags, and turret_validate_target().

Referenced by turret_tesla_firecheck(), and turret_think().

◆ turret_send()

bool turret_send ( entity this,
entity to,
int sf )

Definition at line 314 of file sv_turrets.qc.

315{
316 WriteHeader(MSG_ENTITY, ENT_CLIENT_TURRET);
318 if (sf & TNSF_SETUP)
319 {
320 WriteRegistered(Turrets, MSG_ENTITY, this);
321
322 WriteVector(MSG_ENTITY, this.origin);
323
324 WriteAngleVector2D(MSG_ENTITY, this.angles);
325 }
326
327 if (sf & TNSF_ANG)
328 {
329 WriteShort(MSG_ENTITY, rint(this.tur_head.angles.x));
330 WriteShort(MSG_ENTITY, rint(this.tur_head.angles.y));
331 }
332
333 if (sf & TNSF_AVEL)
334 {
335 WriteShort(MSG_ENTITY, rint(this.tur_head.avelocity.x));
336 WriteShort(MSG_ENTITY, rint(this.tur_head.avelocity.y));
337 }
338
339 if (sf & TNSF_MOVE)
340 {
341 WriteVector(MSG_ENTITY, this.origin);
342 WriteVector(MSG_ENTITY, this.velocity);
344 }
345
346 if (sf & TNSF_ANIM)
347 {
350 }
351
352 if (sf & TNSF_STATUS)
353 {
355
356 if (GetResource(this, RES_HEALTH) <= 0)
358 else
359 WriteByte(MSG_ENTITY, ceil((GetResource(this, RES_HEALTH) / this.max_health) * 255));
360 }
361
362 return true;
363}
float frame
primary framegroup animation (strength = 1 - lerpfrac - lerpfrac3 - lerpfrac4)
Definition anim.qh:6
float anim_start_time
Definition items.qc:15
ent angles
Definition ent_cs.qc:121
const int MSG_ENTITY
Definition net.qh:156
#define WriteHeader(to, id)
Definition net.qh:265
#define WriteRegistered(r, to, it)
Definition net.qh:293
float ceil(float f)
void WriteShort(float data, float dest, float desto)
void WriteCoord(float data, float dest, float desto)
float rint(float f)
void WriteByte(float data, float dest, float desto)
const int TNSF_AVEL
Definition turret.qh:189
const int TNSF_SETUP
Definition turret.qh:187
const int TNSF_MOVE
Definition turret.qh:190
const int TNSF_ANIM
Definition turret.qh:192

References angles, anim_start_time, ceil(), entity(), frame, GetResource(), max_health, MSG_ENTITY, origin, rint(), team, TNSF_ANG, TNSF_ANIM, TNSF_AVEL, TNSF_MOVE, TNSF_SETUP, TNSF_STATUS, tur_head, velocity, WriteByte(), WriteCoord(), WriteHeader, WriteRegistered, and WriteShort().

Referenced by turret_link().

◆ turret_targetscore_generic()

float turret_targetscore_generic ( entity _turret,
entity _target )

Definition at line 78 of file sv_turrets.qc.

79{
80 float d_dist; // Defendmode Distance
81 float score; // Total score
82 float d_score; // Distance score
83 float a_score; // Angular score
84 float m_score = 0; // missile score
85 float p_score = 0; // player score
86 float ikr; // ideal kill range
87
88 if (_turret.tur_defend)
89 {
90 d_dist = vlen(real_origin(_target) - _turret.tur_defend.origin);
91 ikr = vlen(_turret.origin - _turret.tur_defend.origin);
92 d_score = 1 - d_dist / _turret.target_range;
93 }
94 else
95 {
96 // Make a normlized value base on the targets distance from our optimal killzone
97 ikr = _turret.target_range_optimal;
98 d_score = min(ikr, tvt_dist) / max(ikr, tvt_dist);
99 }
100
101 a_score = 1 - tvt_thadf / _turret.aim_maxrot;
102
103 if (_turret.target_select_missilebias > 0 && (_target.flags & FL_PROJECTILE))
104 m_score = 1;
105
106 if (_turret.target_select_playerbias > 0 && IS_CLIENT(_target))
107 p_score = 1;
108
109 d_score = max(d_score, 0);
110 a_score = max(a_score, 0);
111 m_score = max(m_score, 0);
112 p_score = max(p_score, 0);
113
114 score = (d_score * _turret.target_select_rangebias)
115 + (a_score * _turret.target_select_anglebias)
116 + (m_score * _turret.target_select_missilebias)
117 + (p_score * _turret.target_select_playerbias);
118
119 if (vdist(_turret.tur_shotorg - real_origin(_target), >, _turret.target_range))
120 {
121 //dprint("Wtf?\n");
122 score *= 0.001;
123 }
124
125#ifdef TURRET_DEBUG
126 string sd = ftos(d_score);
127 d_score *= _turret.target_select_rangebias;
128 string sdt = ftos(d_score);
129
130 //string sv = ftos(v_score);
131 //v_score *= _turret.target_select_samebias;
132 //string svt = ftos(v_score);
133
134 string sa = ftos(a_score);
135 a_score *= _turret.target_select_anglebias;
136 string sat = ftos(a_score);
137
138 string sm = ftos(m_score);
139 m_score *= _turret.target_select_missilebias;
140 string smt = ftos(m_score);
141
142 string sp = ftos(p_score);
143 p_score *= _turret.target_select_playerbias;
144 string spt = ftos(p_score);
145
146 ss = ftos(score);
147 bprint("^3Target scores^7 \[ ", _turret.netname, " \] ^3for^7 \[ ", _target.netname, " \]\n");
148 bprint("^5Range:\[ ", sd, " \]^2+bias:\[ ", sdt, " \]\n");
149 bprint("^5Angle:\[ ", sa, " \]^2+bias:\[ ", sat, " \]\n");
150 bprint("^5Missile:\[ ", sm, " \]^2+bias:\[ ", smt, " \]\n");
151 bprint("^5Player:\[ ", sp, " \]^2+bias:\[ ", spt, " \]\n");
152 bprint("^3Total (w/bias):\[^1", ss, "\]\n");
153#endif
154
155 return score;
156}
#define IS_CLIENT(s)
Definition player.qh:241
void bprint(string text,...)
float min(float f,...)
string ftos(float f)
float tvt_thadf
float tvt_dist

References bprint(), entity(), FL_PROJECTILE, ftos(), IS_CLIENT, max(), min(), real_origin(), tvt_dist, tvt_thadf, vdist, and vlen().

Referenced by turret_initialize().

◆ turret_targetscore_support()

float turret_targetscore_support ( entity _turret,
entity _target )

Definition at line 64 of file sv_turrets.qc.

65{
66 float s_score = (_turret.enemy == _target);
67 float d_score = min(_turret.target_range_optimal, tvt_dist) / max(_turret.target_range_optimal, tvt_dist);
68
69 // Total score
70 float score = (d_score * _turret.target_select_rangebias)
71 + (s_score * _turret.target_select_samebias);
72 return score;
73}

References entity(), max(), min(), and tvt_dist.

Referenced by turret_initialize().

◆ turret_think()

void turret_think ( entity this)

Definition at line 991 of file sv_turrets.qc.

992{
993 this.nextthink = time;
994
995 MUTATOR_CALLHOOK(TurretThink, this);
996
997#ifdef TURRET_DEBUG
998 if (this.tur_debug_tmr1 < time)
999 {
1000 if (this.enemy)
1001 paint_target(this.enemy, 128, this.tur_debug_rvec, 0.9);
1002 paint_target(this, 256, this.tur_debug_rvec, 0.9);
1003 this.tur_debug_tmr1 = time + 1;
1004 }
1005#endif
1006
1007 // Handle ammo
1008 if (!(this.spawnflags & TSF_NO_AMMO_REGEN)
1009 && this.ammo < this.ammo_max)
1010 this.ammo = min(this.ammo + this.ammo_recharge * frametime, this.ammo_max);
1011
1012 // Inactive turrets needs to run the think loop,
1013 // So they can handle animation and wake up if need be.
1014 if (!this.active)
1015 {
1016 turret_track(this);
1017 return;
1018 }
1019
1020 // This is typicaly used for zaping every target in range
1021 // turret_fusionreactor uses this to recharge friendlys.
1023 {
1024 // Do a this.turret_fire for every valid target.
1025 for (entity e = findradius(this.origin, this.target_range); e; e = e.chain)
1026 if (e.takedamage)
1027 {
1029 {
1030 this.enemy = e;
1031
1032 turret_do_updates(this);
1033
1034 if (turret_checkfire(this))
1035 turret_fire(this);
1036 }
1037 }
1038
1039 this.enemy = NULL;
1040 }
1041 else if (this.shoot_flags & TFL_SHOOT_CUSTOM)
1042 {
1043 // This one is doing something.. oddball. assume its handles what needs to be handled.
1044
1045 if (!(this.aim_flags & TFL_AIM_NO)) // Predict?
1046 this.tur_aimpos = turret_aim_generic(this);
1047
1048 if (!(this.track_flags & TFL_TRACK_NO)) // Turn & pitch?
1049 turret_track(this);
1050
1051 turret_do_updates(this);
1052
1053 if (turret_checkfire(this)) // Fire?
1054 turret_fire(this);
1055 }
1056 else
1057 {
1058 // Special case for volly always. if it fired once it must compleate the volly.
1060 && this.volly_counter != this.shot_volly)
1061 {
1062 // Predict or whatnot
1063 if (!(this.aim_flags & TFL_AIM_NO))
1064 this.tur_aimpos = turret_aim_generic(this);
1065
1066 // Turn & pitch
1067 if (!(this.track_flags & TFL_TRACK_NO))
1068 turret_track(this);
1069
1070 turret_do_updates(this);
1071
1072 // Fire!
1073 if (turret_checkfire(this))
1074 turret_fire(this);
1075
1076 Turret tur = get_turretinfo(this.m_id);
1077 tur.tr_think(tur, this);
1078
1079 return;
1080 }
1081
1082 // Check if we have a vailid enemy, and try to find one if we dont.
1083
1084 // g_turrets_targetscan_maxdelay forces a target re-scan at least this often
1085 float do_target_scan = 0;
1087 do_target_scan = 1;
1088
1089 // Old target (if any) invalid?
1090 if (this.target_validate_time < time
1091 && turret_validate_target(this, this.enemy, this.target_validate_flags) <= 0)
1092 {
1093 this.enemy = NULL;
1094 this.target_validate_time = time + 0.5;
1095 do_target_scan = 1;
1096 }
1097
1098 // But never more often then g_turrets_targetscan_mindelay!
1100 do_target_scan = 0;
1101
1102 if (do_target_scan)
1103 {
1104 this.enemy = turret_select_target(this);
1105 this.target_select_time = time;
1106 }
1107
1108 // No target, just go to idle, do any custom stuff and bail.
1109 if (this.enemy == NULL)
1110 {
1111 // Turn & pitch
1112 if (!(this.track_flags & TFL_TRACK_NO))
1113 turret_track(this);
1114
1115 Turret tur = get_turretinfo(this.m_id);
1116 tur.tr_think(tur, this);
1117
1118 // And bail.
1119 return;
1120 }
1121 else
1122 this.lip = time + autocvar_g_turrets_aimidle_delay; // Keep track of the last time we had a target.
1123
1124 // Predict?
1125 if (!(this.aim_flags & TFL_AIM_NO))
1126 this.tur_aimpos = turret_aim_generic(this);
1127
1128 // Turn & pitch?
1129 if (!(this.track_flags & TFL_TRACK_NO))
1130 turret_track(this);
1131
1132 turret_do_updates(this);
1133
1134 // Fire?
1135 if (turret_checkfire(this))
1136 turret_fire(this);
1137 }
1138
1139 Turret tur = get_turretinfo(this.m_id);
1140 tur.tr_think(tur, this);
1141}
virtual void tr_think()
(SERVER) logic to run every frame
Definition turret.qh:40
float frametime
float lip
Definition subs.qh:40
bool turret_checkfire(entity this)
entity turret_select_target(entity this)
void turret_fire(entity this)
vector turret_aim_generic(entity this)
Definition sv_turrets.qc:12
void turret_do_updates(entity t_turret)
updates enemy distances, predicted impact point/time and updated aim<->predict impact distance.
void turret_track(entity this)
float target_validate_time
Definition sv_turrets.qh:40
float autocvar_g_turrets_targetscan_maxdelay
Definition sv_turrets.qh:9
float autocvar_g_turrets_targetscan_mindelay
Definition sv_turrets.qh:10
float target_select_time
Definition sv_turrets.qh:39
float autocvar_g_turrets_aimidle_delay
Definition sv_turrets.qh:6
const int TFL_TRACK_NO
don't move head
Definition turret.qh:107
const int TSF_NO_AMMO_REGEN
disable builtin ammo regeneration
Definition turret.qh:179
const int TFL_AIM_NO
no aiming
Definition turret.qh:98
const int TFL_SHOOT_CUSTOM
custom attacking
Definition turret.qh:133
const int TFL_SHOOT_HITALLVALID
loop through all valid targets
Definition turret.qh:131

References active, aim_flags, ammo, autocvar_g_turrets_aimidle_delay, autocvar_g_turrets_targetscan_maxdelay, autocvar_g_turrets_targetscan_mindelay, enemy, entity(), frametime, get_turretinfo, lip, m_id, min(), MUTATOR_CALLHOOK, nextthink, NULL, origin, shoot_flags, spawnflags, target_select_time, target_validate_flags, target_validate_time, TFL_AIM_NO, TFL_SHOOT_CUSTOM, TFL_SHOOT_HITALLVALID, TFL_SHOOT_VOLLYALWAYS, TFL_TRACK_NO, time, Turret::tr_think(), track_flags, TSF_NO_AMMO_REGEN, tur_aimpos, turret_aim_generic(), turret_checkfire(), turret_do_updates(), turret_fire(), turret_select_target(), turret_track(), turret_validate_target(), and volly_counter.

Referenced by turret_link(), and turret_respawn().

◆ turret_track()

void turret_track ( entity this)

Definition at line 528 of file sv_turrets.qc.

529{
530 vector target_angle; // This is where we want to aim
531 vector move_angle; // This is where we can aim
532 float f_tmp;
533 vector v1, v2;
534 v1 = this.tur_head.angles;
535 v2 = this.tur_head.avelocity;
536
537 if (this.track_flags == TFL_TRACK_NO)
538 return;
539
540 if (!this.active)
541 target_angle = this.idle_aim - ('1 0 0' * this.aim_maxpitch);
542 else if (this.enemy == NULL)
543 {
544 if (time > this.lip)
545 target_angle = this.idle_aim + this.angles;
546 else
547 target_angle = vectoangles(normalize(this.tur_aimpos - this.tur_shotorg));
548 }
549 else
550 {
551 target_angle = vectoangles(normalize(this.tur_aimpos - this.tur_shotorg));
552 }
553
554 this.tur_head.angles.x = anglemods(this.tur_head.angles.x);
555 this.tur_head.angles.y = anglemods(this.tur_head.angles.y);
556
557 // Find the diffrence between where we currently aim and where we want to aim
558 //move_angle = target_angle - (this.angles + this.tur_head.angles);
559 //move_angle = shortangle_vxy(move_angle, this.angles + this.tur_head.angles);
560
562 move_angle = shortangle_vxy(move_angle, this.tur_head.angles);
563
564 switch (this.track_type)
565 {
567 f_tmp = this.aim_speed * frametime;
568 if (this.track_flags & TFL_TRACK_PITCH)
569 {
570 this.tur_head.angles.x += bound(-f_tmp, move_angle.x, f_tmp);
571 if (this.tur_head.angles.x > this.aim_maxpitch)
572 this.tur_head.angles.x = this.aim_maxpitch;
573
574 if (this.tur_head.angles.x < -this.aim_maxpitch)
575 this.tur_head.angles.x = this.aim_maxpitch;
576 }
577
578 if (this.track_flags & TFL_TRACK_ROTATE)
579 {
580 this.tur_head.angles.y += bound(-f_tmp, move_angle.y, f_tmp);
581 if (this.tur_head.angles.y > this.aim_maxrot)
582 this.tur_head.angles.y = this.aim_maxrot;
583
584 if (this.tur_head.angles.y < -this.aim_maxrot)
585 this.tur_head.angles.y = this.aim_maxrot;
586 }
587
588 // CSQC
589 this.SendFlags |= TNSF_ANG;
590 return;
591
593 f_tmp = this.aim_speed * frametime;
594 move_angle.x = bound(-this.aim_speed, move_angle.x * this.track_accel_pitch * f_tmp, this.aim_speed);
595 move_angle.y = bound(-this.aim_speed, move_angle.y * this.track_accel_rot * f_tmp, this.aim_speed);
596 move_angle = this.tur_head.avelocity * this.track_blendrate + move_angle * (1 - this.track_blendrate);
597 break;
598
600 move_angle.y = bound(-this.aim_speed, move_angle.y, this.aim_speed);
601 move_angle.x = bound(-this.aim_speed, move_angle.x, this.aim_speed);
602 break;
603 }
604
605 // pitch
606 if (this.track_flags & TFL_TRACK_PITCH)
607 {
608 this.tur_head.avelocity.x = move_angle.x;
609 if (this.tur_head.angles.x + this.tur_head.avelocity.x * frametime > this.aim_maxpitch)
610 {
611 this.tur_head.avelocity.x = 0;
612 this.tur_head.angles.x = this.aim_maxpitch;
613
614 this.SendFlags |= TNSF_ANG;
615 }
616
617 if (this.tur_head.angles.x + this.tur_head.avelocity.x * frametime < -this.aim_maxpitch)
618 {
619 this.tur_head.avelocity.x = 0;
620 this.tur_head.angles.x = -this.aim_maxpitch;
621
622 this.SendFlags |= TNSF_ANG;
623 }
624 }
625
626 // rot
627 if (this.track_flags & TFL_TRACK_ROTATE)
628 {
629 this.tur_head.avelocity.y = move_angle.y;
630
631 if (this.tur_head.angles.y + this.tur_head.avelocity.y * frametime > this.aim_maxrot)
632 {
633 this.tur_head.avelocity.y = 0;
634 this.tur_head.angles.y = this.aim_maxrot;
635
636 this.SendFlags |= TNSF_ANG;
637 }
638
639 if (this.tur_head.angles.y + this.tur_head.avelocity.y * frametime < -this.aim_maxrot)
640 {
641 this.tur_head.avelocity.y = 0;
642 this.tur_head.angles.y = -this.aim_maxrot;
643
644 this.SendFlags |= TNSF_ANG;
645 }
646 }
647
648 this.SendFlags |= TNSF_AVEL;
649
650 // Force a angle update every 10'th frame
651 ++this.turret_framecounter;
652 if (this.turret_framecounter >= 10)
653 {
654 this.SendFlags |= TNSF_ANG;
655 this.turret_framecounter = 0;
656 }
657}
ERASEABLE float anglemods(float v)
Definition angle.qc:13
ERASEABLE vector shortangle_vxy(vector ang1, vector ang2)
Definition angle.qc:58
vector AnglesTransform_ToAngles(vector v)
vector AnglesTransform_LeftDivide(vector from_transform, vector to_transform)
vector AnglesTransform_FromAngles(vector v)
vector vectoangles(vector v)
float turret_framecounter
Handles head rotation according to the units .track_type and .track_flags.
const float TFL_TRACKTYPE_FLUIDINERTIA
Definition sv_turrets.qh:64
const float TFL_TRACKTYPE_FLUIDPRECISE
Definition sv_turrets.qh:63

References active, anglemods(), angles, AnglesTransform_FromAngles(), AnglesTransform_LeftDivide(), AnglesTransform_ToAngles(), bound(), enemy, entity(), frametime, idle_aim, lip, normalize(), NULL, SendFlags, shortangle_vxy(), TFL_TRACK_NO, TFL_TRACK_PITCH, TFL_TRACK_ROTATE, TFL_TRACKTYPE_FLUIDINERTIA, TFL_TRACKTYPE_FLUIDPRECISE, TFL_TRACKTYPE_STEPMOTOR, time, TNSF_ANG, TNSF_AVEL, track_flags, tur_aimpos, tur_head, tur_shotorg, turret_framecounter, vectoangles(), and vector.

Referenced by turret_think().

◆ turret_use()

void turret_use ( entity this,
entity actor,
entity trigger )

Definition at line 1147 of file sv_turrets.qc.

1148{
1149 LOG_TRACE("Turret ", this.netname, " used by ", actor.classname);
1150
1151 this.team = actor.team;
1152
1153 this.active = (this.team == 0)
1154 ? ACTIVE_NOT
1155 : ACTIVE_ACTIVE;
1156}
const int ACTIVE_NOT
Definition defs.qh:36

References active, ACTIVE_ACTIVE, ACTIVE_NOT, entity(), LOG_TRACE, netname, and team.

Referenced by turret_initialize().

◆ turret_validate_target()

float turret_validate_target ( entity e_turret,
entity e_target,
float validate_flags )

Evaluate a entity for target valitity based on validate_flags NOTE: the caller must check takedamage before calling this, to inline this check.

Definition at line 677 of file sv_turrets.qc.

678{
679 //if (!validate_flags & TFL_TARGETSELECT_NOBUILTIN)
680 // return -0.5;
681
682 if (!e_target)
683 return -2;
684
685 if (e_target.owner == e_turret || e_target == e_turret.realowner) // Don't attack against owner
686 return -0.5;
687
688 if (!checkpvs(e_target.origin, e_turret))
689 return -1;
690 if (e_target.alpha != 0 && e_target.alpha <= 0.3)
691 return -1;
692
693 if (MUTATOR_CALLHOOK(TurretValidateTarget, e_turret, e_target, validate_flags))
694 return M_ARGV(3, float);
695
696 if (validate_flags & TFL_TARGETSELECT_NO)
697 return -4;
698
699 if (e_target.flags & FL_NOTARGET) // If only this was used more..
700 return -5;
701
702 if (GetResource(e_target, RES_HEALTH) <= 0) // Cant touch this
703 return -6;
704
705 // vehicle
706 if (IS_VEHICLE(e_target)
707 && (validate_flags & TFL_TARGETSELECT_VEHICLES) && !e_target.owner)
708 return -7;
709
710 if (IS_CLIENT(e_target)) // player
711 {
712 if (!(validate_flags & TFL_TARGETSELECT_PLAYERS))
713 return -7;
714 if (IS_DEAD(e_target))
715 return -8;
716 }
717
718 // enemy turrets
719 if ((validate_flags & TFL_TARGETSELECT_NOTURRETS)
720 && e_target.owner.tur_head == e_target
721 && DIFF_TEAM(e_target, e_turret)) // Dont break support units.
722 return -9;
723
724 // Missile
725 if ((e_target.flags & FL_PROJECTILE)
726 && !(validate_flags & TFL_TARGETSELECT_MISSILES))
727 return -10;
728
729 if ((validate_flags & TFL_TARGETSELECT_MISSILESONLY)
730 && !(e_target.flags & FL_PROJECTILE))
731 return -10.5;
732
733 // Team check
734 if (validate_flags & TFL_TARGETSELECT_TEAMCHECK)
735 {
736 if (validate_flags & TFL_TARGETSELECT_OWNTEAM)
737 {
738 if (DIFF_TEAM(e_target, e_turret))
739 return -11;
740 if (DIFF_TEAM(e_turret, e_target.owner))
741 return -12;
742 if (DIFF_TEAM(e_turret, e_target.aiment))
743 return -12; // portals
744 }
745 else
746 {
747 if (SAME_TEAM(e_target, e_turret))
748 return -13;
749 if (SAME_TEAM(e_turret, e_target.owner))
750 return -14;
751 if (SAME_TEAM(e_turret, e_target.aiment))
752 return -14; // portals
753 }
754 }
755
756 // Range limits?
757 tvt_dist = vlen(e_turret.origin - real_origin(e_target));
758 if (validate_flags & TFL_TARGETSELECT_RANGELIMITS)
759 {
760 if (tvt_dist < e_turret.target_range_min)
761 return -15;
762 if (tvt_dist > e_turret.target_range)
763 return -16;
764 }
765
766 // Can we even aim this thing?
767 tvt_thadv = angleofs3(e_turret.tur_head.origin, e_turret.angles + e_turret.tur_head.angles, e_target.origin);
768 tvt_tadv = shortangle_vxy(angleofs(e_turret, e_target), e_turret.angles);
770
771 /*
772 if ((validate_flags & TFL_TARGETSELECT_FOV)
773 && e_turret.target_select_fov < tvt_thadf)
774 return -21;
775 */
776
777 if (validate_flags & TFL_TARGETSELECT_ANGLELIMITS)
778 {
779 if (fabs(tvt_tadv.x) > e_turret.aim_maxpitch)
780 return -17;
781 if (fabs(tvt_tadv.y) > e_turret.aim_maxrot)
782 return -18;
783 }
784
785 // Line of sight?
786 if (validate_flags & TFL_TARGETSELECT_LOS)
787 {
788 vector v_tmp = real_origin(e_target) + 0.5 * (e_target.mins + e_target.maxs);
789
790 traceline(e_turret.origin + '0 0 16', v_tmp, 0, e_turret);
791 if (vdist(v_tmp - trace_endpos, >, e_turret.aim_firetolerance_dist))
792 return -19;
793 }
794
795 if (e_target.classname == "grapplinghook")
796 return -20;
797 /*
798 if (e_target.classname == "func_button")
799 return -21;
800 */
801
802#ifdef TURRET_DEBUG_TARGETSELECT
803 LOG_TRACE("Target:", e_target.netname, " is a valid target for ", e_turret.netname);
804#endif
805
806 return 1;
807}
ERASEABLE vector angleofs3(vector from, vector ang, vector to)
Definition angle.qc:73
float checkpvs(vector viewpos, entity viewee)
vector tvt_thadv
vector tvt_tadv
#define DIFF_TEAM(a, b)
Definition teams.qh:242
const int TFL_TARGETSELECT_NO
don't automatically find targets
Definition turret.qh:81
const int TFL_TARGETSELECT_VEHICLES
target manned vehicles
Definition turret.qh:94
const int TFL_TARGETSELECT_NOTURRETS
don't attack other turrets
Definition turret.qh:91
const int TFL_TARGETSELECT_OWNTEAM
only attack teammates
Definition turret.qh:90
const int TFL_TARGETSELECT_MISSILESONLY
only attack missiles
Definition turret.qh:93
#define IS_VEHICLE(v)
Definition utils.qh:24

References angleofs, angleofs3(), checkpvs(), DIFF_TEAM, entity(), fabs(), FL_NOTARGET, FL_PROJECTILE, GetResource(), IS_CLIENT, IS_DEAD, IS_VEHICLE, LOG_TRACE, M_ARGV, MUTATOR_CALLHOOK, real_origin(), SAME_TEAM, shortangle_vxy(), TFL_TARGETSELECT_ANGLELIMITS, TFL_TARGETSELECT_LOS, TFL_TARGETSELECT_MISSILES, TFL_TARGETSELECT_MISSILESONLY, TFL_TARGETSELECT_NO, TFL_TARGETSELECT_NOTURRETS, TFL_TARGETSELECT_OWNTEAM, TFL_TARGETSELECT_PLAYERS, TFL_TARGETSELECT_RANGELIMITS, TFL_TARGETSELECT_TEAMCHECK, TFL_TARGETSELECT_VEHICLES, trace_endpos, tvt_dist, tvt_tadv, tvt_thadf, tvt_thadv, vdist, vector, and vlen().

Referenced by turret_firecheck(), turret_hk_addtarget(), turret_select_target(), turret_tesla_firecheck(), turret_think(), and walker_melee_do_dmg().

◆ turrets_manager_think()

void turrets_manager_think ( entity this)

Definition at line 1166 of file sv_turrets.qc.

1167{
1168 this.nextthink = time + 1;
1169
1171 {
1172 Turret tur;
1173 IL_EACH(g_turrets, true,
1174 {
1175 load_unit_settings(it, true);
1176 tur = get_turretinfo(it.m_id);
1177 tur.tr_think(tur, it);
1178 });
1179 cvar_set("g_turrets_reloadcvars", "0");
1180 }
1181}
#define IL_EACH(this, cond, body)
void cvar_set(string name, string value)
bool autocvar_g_turrets_reloadcvars
Definition sv_turrets.qh:8

References autocvar_g_turrets_reloadcvars, cvar_set(), entity(), g_turrets, get_turretinfo, IL_EACH, load_unit_settings(), nextthink, time, and Turret::tr_think().

Referenced by turret_findtarget().

◆ turrets_setframe()

void turrets_setframe ( entity this,
float _frame,
float client_only )

Definition at line 299 of file sv_turrets.qc.

300{
301 if ((client_only ? this.clientframe : this.frame) != _frame)
302 {
303 this.SendFlags |= TNSF_ANIM;
304 this.anim_start_time = time;
305 }
306
307 if (client_only)
308 this.clientframe = _frame;
309 else
310 this.frame = _frame;
311
312}
float clientframe

References anim_start_time, clientframe, entity(), frame, SendFlags, time, and TNSF_ANIM.

Referenced by ewheel_move_enemy(), and walker_setnoanim().

Variable Documentation

◆ clientframe

float clientframe

Definition at line 298 of file sv_turrets.qc.

Referenced by turrets_setframe().

◆ turret_framecounter

float turret_framecounter

Handles head rotation according to the units .track_type and .track_flags.

Definition at line 527 of file sv_turrets.qc.

Referenced by turret_track().