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 if (isPlayer) {
20 turret_initparams(actor);
21 W_SetupShot_Dir(actor, weaponentity, v_forward, false, 0, SND_HunterKillerAttack_FIRE, CH_WEAPON_B, 0, DEATH_TURRET_HK.m_id);
22 actor.tur_shotdir_updated = w_shotdir;
23 actor.tur_shotorg = w_shotorg;
24 actor.tur_head = actor;
25 weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, 0.5, w_ready);
26 }
27 entity missile = turret_projectile(actor, SND_HunterKillerAttack_FIRE, 6, 10, DEATH_TURRET_HK.m_id, PROJECTILE_ROCKET, false, false);
28 te_explosion (missile.origin);
29
31 missile.nextthink = time + 0.25;
33 missile.velocity = actor.tur_shotdir_updated * (actor.shot_speed * 0.75);
34 missile.angles = vectoangles(missile.velocity);
35 missile.cnt = time + 30;
36 missile.missile_flags = MIF_SPLASH | MIF_PROXY | MIF_GUIDED_AI;
37
38 if (!isPlayer)
39 if (actor.tur_head.frame == 0)
40 actor.tur_head.frame = actor.tur_head.frame + 1;
41 }
42}
43
44bool hk_is_valid_target(entity this, entity proj, entity targ);
46{
47 vector vu, vd, vf, vl, vr, ve; // Vector (direction)
48 float fu, fd, ff, fl, fr, fe; // Fraction to solid
49 vector olddir,wishdir,newdir; // Final direction
50 float lt_for; // Length of Trace FORwrad
51 float lt_seek; // Length of Trace SEEK (left, right, up down)
52 float pt_seek; // Pitch of Trace SEEK (How mutch to angele left, right up, down trace towards v_forward)
53 float myspeed;
54
55 this.nextthink = time;
56
57 //if (this.cnt < time)
58 // turret_hk_missile_explode();
59
60 if (IS_DEAD(this.enemy) || IS_SPEC(this.enemy) || IS_OBSERVER(this.enemy))
61 this.enemy = NULL;
62
63 // Pick the closest valid target.
64 if (!this.enemy)
65 {
66 // in this case, the lighter check is to validate it first, and check distance if it is valid
68 {
69 if(vdist(it.origin, >, 5000))
70 continue;
71
72 if(!this.enemy)
73 this.enemy = it;
74 else if(vlen2(this.origin - it.origin) < vlen2(this.origin - this.enemy.origin))
75 this.enemy = it;
76 });
77 }
78
79 this.angles = vectoangles(this.velocity);
80 this.angles_x = this.angles_x * -1;
81 makevectors(this.angles);
82 this.angles_x = this.angles_x * -1;
83
84 if (this.enemy)
85 {
86 // Close enougth to do decent damage?
87 if(vdist(this.origin - this.enemy.origin, <=, (this.owner.shot_radius * 0.25)))
88 {
90 return;
91 }
92
93 // Get data on enemy position
94 vector pre_pos = this.enemy.origin +
95 this.enemy.velocity *
96 min((vlen(this.enemy.origin - this.origin) / vlen(this.velocity)),0.5);
97
98 traceline(this.origin, pre_pos,true,this.enemy);
99 ve = normalize(pre_pos - this.origin);
100 fe = trace_fraction;
101
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)) && (myspeed > (autocvar_g_turrets_unit_hk_shot_speed)) )
127
128 // Failry clear, accelerate.
129 if ( (ff > 0.7) && (myspeed < (autocvar_g_turrets_unit_hk_shot_speed_max)) )
131
132 // Setup trace pitch
133 pt_seek = 1 - ff;
134 pt_seek = bound(0.15,pt_seek,0.8);
135 if (ff < 0.5) pt_seek = 1;
136
137 // Trace left
138 traceline(this.origin, this.origin + (-1 * (v_right * pt_seek) + (v_forward * ff)) * lt_seek,false,this);
139 vl = trace_endpos;
140 fl = trace_fraction;
141
142 // Trace right
143 traceline(this.origin, this.origin + ((v_right * pt_seek) + (v_forward * ff)) * lt_seek ,false,this);
144 vr = trace_endpos;
145 fr = trace_fraction;
146
147 // Trace up
148 traceline(this.origin, this.origin + ((v_up * pt_seek) + (v_forward * ff)) * lt_seek ,false,this);
149 vu = trace_endpos;
150 fu = trace_fraction;
151
152 // Trace down
153 traceline(this.origin, this.origin + (-1 * (v_up * pt_seek) + (v_forward * ff)) * lt_seek ,false,this);
154 vd = trace_endpos;
155 fd = trace_fraction;
156
157 vl = normalize(vl - this.origin);
158 vr = normalize(vr - this.origin);
159 vu = normalize(vu - this.origin);
160 vd = normalize(vd - this.origin);
161
162 // Panic tresh passed, find a single direction and turn as hard as we can
163 if (pt_seek == 1)
164 {
165 wishdir = v_right;
166 if (fl > fr) wishdir = -1 * v_right;
167 if (fu > fl) wishdir = v_up;
168 if (fd > fu) wishdir = -1 * v_up;
169 }
170 else
171 {
172 // Normalize our trace vectors to make a smooth path
173 wishdir = normalize( (vl * fl) + (vr * fr) + (vu * fu) + (vd * fd) );
174 }
175
176 if (this.enemy)
177 {
178 if (fe < 0.1) fe = 0.1; // Make sure we always try to move sligtly towards our target
179 wishdir = (wishdir * (1 - fe)) + (ve * fe);
180 }
181 }
182 else
183 {
184 // Got a clear path to target, speed up fast (if not at full speed) and go straight for it.
185 myspeed = vlen(this.velocity);
188
189 wishdir = ve;
190 }
191
192 if ((myspeed > (autocvar_g_turrets_unit_hk_shot_speed)) && (this.cnt > time))
194
195 // Ranoutagazfish?
196 if (this.cnt < time)
197 {
198 this.cnt = time + 0.25;
199 this.nextthink = 0;
201 return;
202 }
203
204 // Calculate new heading
205 olddir = normalize(this.velocity);
206 newdir = normalize(olddir + wishdir * (autocvar_g_turrets_unit_hk_shot_speed_turnrate));
207
208 // Set heading & speed
209 this.velocity = newdir * myspeed;
210
211 // Align model with new heading
212 this.angles = vectoangles(this.velocity);
213
214
215#ifdef TURRET_DEBUG_HK
216 //if(this.atime < time) {
217 if ((fe <= 0.99)||vdist(this.origin - this.enemy.origin, >, 1000))
218 {
219 te_lightning2(NULL,this.origin, this.origin + vr * lt_seek);
220 te_lightning2(NULL,this.origin, this.origin + vl * lt_seek);
221 te_lightning2(NULL,this.origin, this.origin + vu * lt_seek);
222 te_lightning2(NULL,this.origin, this.origin + vd * lt_seek);
223 te_lightning2(NULL,this.origin, vf);
224 }
225 else
226 {
227 te_lightning2(NULL,this.origin, this.enemy.origin);
228 }
229 bprint("Speed: ", ftos(rint(myspeed)), "\n");
230 bprint("Trace to solid: ", ftos(rint(ff * 100)), "%\n");
231 bprint("Trace to target:", ftos(rint(fe * 100)), "%\n");
232 this.atime = time + 0.2;
233 //}
234#endif
235
237}
238
240{
241 if (!targ)
242 return false;
243
244 // we know for sure pure entities are bad targets
245 if(is_pure(targ))
246 return false;
247
248 // If only this was used more..
249 if (targ.flags & FL_NOTARGET)
250 return false;
251
252 // Cant touch this
253 if ((targ.takedamage == DAMAGE_NO) || (GetResource(targ, RES_HEALTH) < 0))
254 return false;
255
256 // player
257 if (IS_PLAYER(targ))
258 {
259 if (this.target_select_playerbias < 0)
260 return false;
261
262 if (IS_DEAD(targ))
263 return false;
264 }
265
266 // Missile
267 if ((targ.flags & FL_PROJECTILE) && (this.target_select_missilebias < 0))
268 return false;
269
270 // Team check
271 if ((targ.team == this.team) || (this.team == targ.owner.team))
272 return false;
273
274 return true;
275}
276
277#endif
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:245
#define IS_PLAYER(s)
Definition player.qh:243
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:135
ent angles
Definition ent_cs.qc:121
void turret_hk_missile_think(entity this)
Definition hk_weapon.qc:45
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:239
#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:225
#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)
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)