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)
v x
Definition ent_cs.qc:146

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.
virtual void tr_setup()
(BOTH) setup turret data
Definition turret.qh:36
SetResourceExplicit(ent, RES_ARMOR, ReadByte() *DEC_FACTOR)) ENTCS_PROP(NAME
#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:96
float sys_frametime
Definition common.qh:57
entity enemy
Definition sv_ctf.qh:152
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:72

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
float solid
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
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:74
var entity(vector mins, vector maxs,.entity tofield) findbox_tofield_OrFallback
string classname
#define LOG_TRACE(...)
Definition log.qh:74
entity find(entity start,.string field, string match)
#define new_pure(class)
purely logical entities (not linked to the area grid)
Definition oo.qh:66
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:2427
void InitializeEntity(entity e, void(entity this) func, int order)
Definition world.qc:2229

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:77
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:76
#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:146
WriteByte(chan, ent.angles.y/DEC_FACTOR)
const int MSG_ENTITY
Definition net.qh:156
#define WriteHeader(to, id)
Definition net.qh:265
#define WriteRegistered(r, to, it)
Definition net.qh:292
float ceil(float f)
void WriteShort(float data, float dest, float desto)
void WriteCoord(float data, float dest, float desto)
float rint(float f)
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)
Return a angle within +/- 360.
Definition angle.qc:10
ERASEABLE vector shortangle_vxy(vector ang1, vector ang2)
Definition angle.qc:49
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)
Return the angle offset between angle ang and angle of the vector from->to.
Definition angle.qc:60
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().