Xonotic QuakeC
The free, fast arena FPS with crisp movement and a wide array of weapons
hk_weapon.qc
Go to the documentation of this file.
1#include "hk_weapon.qh"
2
3#ifdef SVQC
4
11
13SOUND(HunterKillerAttack_FIRE, W_Sound("rocket_fire"));
14METHOD(HunterKillerAttack, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
15{
16 bool isPlayer = IS_PLAYER(actor);
17 if (fire & 1)
18 if (!isPlayer || weapon_prepareattack(thiswep, actor, weaponentity, false, 1))
19 {
20 if (isPlayer)
21 {
22 turret_initparams(actor);
23 W_SetupShot_Dir(actor, weaponentity, v_forward, false, 0, SND_HunterKillerAttack_FIRE, CH_WEAPON_B, 0, DEATH_TURRET_HK.m_id);
24 actor.tur_shotdir_updated = w_shotdir;
25 actor.tur_shotorg = w_shotorg;
26 actor.tur_head = actor;
27 weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, 0.5, w_ready);
28 }
29 entity missile = turret_projectile(actor, SND_HunterKillerAttack_FIRE, 6, 10, DEATH_TURRET_HK.m_id, PROJECTILE_ROCKET, false, false);
30 te_explosion(missile.origin);
31
33 missile.nextthink = time + 0.25;
35 missile.velocity = actor.tur_shotdir_updated * (actor.shot_speed * 0.75);
36 missile.angles = vectoangles(missile.velocity);
37 missile.cnt = time + 30;
38 missile.missile_flags = MIF_SPLASH | MIF_PROXY | MIF_GUIDED_AI;
39
40 if (!isPlayer
41 && actor.tur_head.frame == 0)
42 ++actor.tur_head.frame;
43 }
44}
45
46bool hk_is_valid_target(entity this, entity proj, entity targ);
48{
49 vector vu, vd, vf, vl, vr, ve; // Vector (direction)
50 float fu, fd, ff, fl, fr, fe; // Fraction to solid
51 vector olddir, wishdir, newdir; // Final direction
52 float lt_for; // Length of Trace FORwrad
53 float lt_seek; // Length of Trace SEEK (left, right, up down)
54 float pt_seek; // Pitch of Trace SEEK (How mutch to angele left, right up, down trace towards v_forward)
55 float myspeed;
56
57 this.nextthink = time;
58
59 //if (this.cnt < time)
60 // turret_hk_missile_explode();
61
62 if (IS_DEAD(this.enemy) || IS_SPEC(this.enemy) || IS_OBSERVER(this.enemy))
63 this.enemy = NULL;
64
65 // Pick the closest valid target.
66 if (!this.enemy)
67 {
68 // in this case, the lighter check is to validate it first, and check distance if it is valid
70 {
71 if (vdist(it.origin, >, 5000))
72 continue;
73
74 if (!this.enemy)
75 this.enemy = it;
76 else if (vlen2(this.origin - it.origin) < vlen2(this.origin - this.enemy.origin))
77 this.enemy = it;
78 });
79 }
80
81 this.angles = vectoangles(this.velocity);
82 this.angles.x = -this.angles.x;
83 makevectors(this.angles);
84 this.angles.x = -this.angles.x;
85
86 if (this.enemy)
87 {
88 // Close enougth to do decent damage?
89 if (vdist(this.origin - this.enemy.origin, <=, (this.owner.shot_radius * 0.25)))
90 {
92 return;
93 }
94
95 // Get data on enemy position
96 vector pre_pos = this.enemy.origin
97 + this.enemy.velocity * min(vlen(this.enemy.origin - this.origin) / vlen(this.velocity), 0.5);
98
99 traceline(this.origin, pre_pos, true, this.enemy);
100 ve = normalize(pre_pos - this.origin);
101 fe = trace_fraction;
102 }
103 else
104 {
105 ve = '0 0 0';
106 fe = 0;
107 }
108
109 if (fe != 1 || this.enemy == NULL || vdist(this.origin - this.enemy.origin, >, 1000))
110 {
111 myspeed = vlen(this.velocity);
112
113 lt_for = myspeed * 3;
114 lt_seek = myspeed * 2.95;
115
116 // Trace forward
117 traceline(this.origin, this.origin + v_forward * lt_for, false, this);
118 vf = trace_endpos;
119 ff = trace_fraction;
120
121 // Find angular offset
122 float ad = vlen(vectoangles(normalize(this.enemy.origin - this.origin)) - this.angles);
123
124 // To close to something, Slow down!
125 if ((ff < 0.7 || ad > 4)
128
129 // Failry clear, accelerate.
130 if (ff > 0.7
133
134 // Setup trace pitch
135 pt_seek = bound(0.15, 1 - ff, 0.8);
136 if (ff < 0.5)
137 pt_seek = 1;
138
139 // Trace left
140 traceline(this.origin, this.origin + (-(v_right * pt_seek) + (v_forward * ff)) * lt_seek, false, this);
141 vl = trace_endpos;
142 fl = trace_fraction;
143
144 // Trace right
145 traceline(this.origin, this.origin + ((v_right * pt_seek) + (v_forward * ff)) * lt_seek, false, this);
146 vr = trace_endpos;
147 fr = trace_fraction;
148
149 // Trace up
150 traceline(this.origin, this.origin + ((v_up * pt_seek) + (v_forward * ff)) * lt_seek, false, this);
151 vu = trace_endpos;
152 fu = trace_fraction;
153
154 // Trace down
155 traceline(this.origin, this.origin + (-(v_up * pt_seek) + (v_forward * ff)) * lt_seek, false, this);
156 vd = trace_endpos;
157 fd = trace_fraction;
158
159 vl = normalize(vl - this.origin);
160 vr = normalize(vr - this.origin);
161 vu = normalize(vu - this.origin);
162 vd = normalize(vd - this.origin);
163
164 // Panic tresh passed, find a single direction and turn as hard as we can
165 if (pt_seek == 1)
166 {
167 wishdir = v_right;
168 if (fl > fr) wishdir = -v_right;
169 if (fu > fl) wishdir = v_up;
170 if (fd > fu) wishdir = -v_up;
171 }
172 else
173 {
174 // Normalize our trace vectors to make a smooth path
175 wishdir = normalize((vl * fl) + (vr * fr) + (vu * fu) + (vd * fd));
176 }
177
178 if (this.enemy)
179 {
180 if (fe < 0.1)
181 fe = 0.1; // Make sure we always try to move sligtly towards our target
182 wishdir = wishdir * (1 - fe) + (ve * fe);
183 }
184 }
185 else
186 {
187 // Got a clear path to target, speed up fast (if not at full speed) and go straight for it.
188 myspeed = vlen(this.velocity);
191
192 wishdir = ve;
193 }
194
195 if (myspeed > autocvar_g_turrets_unit_hk_shot_speed && this.cnt > time)
197
198 // Ranoutagazfish?
199 if (this.cnt < time)
200 {
201 this.cnt = time + 0.25;
202 this.nextthink = 0;
204 return;
205 }
206
207 // Calculate new heading
208 olddir = normalize(this.velocity);
210
211 // Set heading & speed
212 this.velocity = newdir * myspeed;
213
214 // Align model with new heading
215 this.angles = vectoangles(this.velocity);
216
217
218#ifdef TURRET_DEBUG_HK
219 //if (this.atime < time) {
220 if (fe <= 0.99 || vdist(this.origin - this.enemy.origin, >, 1000))
221 {
222 te_lightning2(NULL, this.origin, this.origin + vr * lt_seek);
223 te_lightning2(NULL, this.origin, this.origin + vl * lt_seek);
224 te_lightning2(NULL, this.origin, this.origin + vu * lt_seek);
225 te_lightning2(NULL, this.origin, this.origin + vd * lt_seek);
226 te_lightning2(NULL, this.origin, vf);
227 }
228 else
229 te_lightning2(NULL, this.origin, this.enemy.origin);
230
231 bprint("Speed: ", ftos(rint(myspeed)), "\n");
232 bprint("Trace to solid: ", ftos(rint(ff * 100)), "%\n");
233 bprint("Trace to target:", ftos(rint(fe * 100)), "%\n");
234 this.atime = time + 0.2;
235 //}
236#endif
237
239}
240
242{
243 if (!targ)
244 return false;
245 if (is_pure(targ)) // we know for sure pure entities are bad targets
246 return false;
247 if (targ.flags & FL_NOTARGET) // If only this was used more..
248 return false;
249
250 if (targ.takedamage == DAMAGE_NO || GetResource(targ, RES_HEALTH) < 0) // Cant touch this
251 return false;
252
253 if (IS_PLAYER(targ)) // player
254 {
255 if (this.target_select_playerbias < 0)
256 return false;
257
258 if (IS_DEAD(targ))
259 return false;
260 }
261
262 if ((targ.flags & FL_PROJECTILE) && this.target_select_missilebias < 0) // Missile
263 return false;
264
265 if (SAME_TEAM(targ, this) || SAME_TEAM(this, targ.owner)) // Team check
266 return false;
267
268 return true;
269}
270
271#endif // SVQC
var entity(vector mins, vector maxs,.entity tofield) findbox_tofield_OrFallback
float GetResource(entity e, Resource res_type)
Returns the current amount of resource the given entity has.
float cnt
Definition powerups.qc:24
entity owner
Definition main.qh:87
#define IS_DEAD(s)
Definition player.qh:244
#define IS_PLAYER(s)
Definition player.qh:242
const int FL_PROJECTILE
Definition constants.qh:85
const int FL_NOTARGET
Definition constants.qh:76
vector v_up
vector velocity
float time
vector v_right
vector trace_endpos
float nextthink
vector v_forward
vector origin
float trace_fraction
void UpdateCSQCProjectile(entity e)
IntrusiveList g_damagedbycontents
Definition damage.qh:143
ent angles
Definition ent_cs.qc:121
void turret_hk_missile_think(entity this)
Definition hk_weapon.qc:47
float autocvar_g_turrets_unit_hk_shot_speed_decel
Definition hk_weapon.qc:8
float autocvar_g_turrets_unit_hk_shot_speed_accel2
Definition hk_weapon.qc:7
float autocvar_g_turrets_unit_hk_shot_speed_turnrate
Definition hk_weapon.qc:10
float autocvar_g_turrets_unit_hk_shot_speed_accel
Definition hk_weapon.qc:6
float autocvar_g_turrets_unit_hk_shot_speed_max
Definition hk_weapon.qc:9
float autocvar_g_turrets_unit_hk_shot_speed
Definition hk_weapon.qc:5
bool hk_is_valid_target(entity this, entity proj, entity targ)
Definition hk_weapon.qc:241
#define IL_EACH(this, cond, body)
float bound(float min, float value, float max)
void bprint(string text,...)
float vlen(vector v)
vector vectoangles(vector v)
float min(float f,...)
float rint(float f)
vector normalize(vector v)
string ftos(float f)
float max(float f,...)
void set_movetype(entity this, int mt)
Definition movetypes.qc:4
const int MOVETYPE_BOUNCEMISSILE
Definition movetypes.qh:140
const int MOVETYPE_BOUNCE
Definition movetypes.qh:139
#define is_pure(e)
Definition oo.qh:16
#define METHOD(cname, name, prototype)
Definition oo.qh:269
#define NULL
Definition post.qh:14
#define makevectors
Definition post.qh:21
const int PROJECTILE_ROCKET
Definition projectiles.qh:4
#define setthink(e, f)
vector
Definition self.qh:92
const int MIF_SPLASH
Definition common.qh:46
const int MIF_PROXY
Definition common.qh:48
const int MIF_GUIDED_AI
Definition common.qh:52
const int CH_WEAPON_B
Definition sound.qh:8
string W_Sound(string w_snd)
Definition all.qc:226
#define SOUND(name, path)
Definition all.qh:30
const int DAMAGE_NO
Definition subs.qh:79
entity enemy
Definition sv_ctf.qh:153
entity turret_projectile(entity actor, Sound _snd, float _size, float _health, float _death, float _proj_type, float _cull, float _cli_anim)
void turret_initparams(entity tur)
void turret_projectile_explode(entity this)
#define SAME_TEAM(a, b)
Definition teams.qh:241
vector w_shotdir
Definition tracing.qh:20
vector w_shotorg
Definition tracing.qh:19
#define W_SetupShot_Dir(ent, wepent, s_forward, antilag, recoil, snd, chan, maxdamage, deathtype)
Definition tracing.qh:32
#define IS_OBSERVER(v)
Definition utils.qh:11
#define IS_SPEC(v)
Definition utils.qh:10
#define vlen2(v)
Definition vector.qh:4
#define vdist(v, cmp, f)
Vector distance comparison, avoids sqrt()
Definition vector.qh:8
void weapon_thinkf(entity actor,.entity weaponentity, WFRAME fr, float t, void(Weapon thiswep, entity actor,.entity weaponentity, int fire) func)
bool weapon_prepareattack(Weapon thiswep, entity actor,.entity weaponentity, bool secondary, float attacktime)
void w_ready(Weapon thiswep, entity actor,.entity weaponentity, int fire)