Xonotic QuakeC
The free, fast arena FPS with crisp movement and a wide array of weapons
hagar.qc
Go to the documentation of this file.
1#include "hagar.qh"
2
3#ifdef SVQC
4
5// NO bounce protection, as bounces are limited!
6
7void W_Hagar_Explode(entity this, entity directhitentity)
8{
9 this.event_damage = func_null;
10 RadiusDamage(this, this.realowner, WEP_CVAR_PRI(WEP_HAGAR, damage), WEP_CVAR_PRI(WEP_HAGAR, edgedamage), WEP_CVAR_PRI(WEP_HAGAR, radius), NULL, NULL, WEP_CVAR_PRI(WEP_HAGAR, force), this.projectiledeathtype, this.weaponentity_fld, directhitentity);
11
12 delete(this);
13}
14
15void W_Hagar_Explode_use(entity this, entity actor, entity trigger)
16{
17 W_Hagar_Explode(this, trigger);
18}
19
20void W_Hagar_Explode2(entity this, entity directhitentity)
21{
22 this.event_damage = func_null;
23 RadiusDamage(this, this.realowner, WEP_CVAR_SEC(WEP_HAGAR, damage), WEP_CVAR_SEC(WEP_HAGAR, edgedamage), WEP_CVAR_SEC(WEP_HAGAR, radius), NULL, NULL, WEP_CVAR_SEC(WEP_HAGAR, force), this.projectiledeathtype, this.weaponentity_fld, directhitentity);
24
25 delete(this);
26}
27
28void W_Hagar_Explode2_use(entity this, entity actor, entity trigger)
29{
30 W_Hagar_Explode2(this, trigger);
31}
32
33void W_Hagar_Damage(entity this, entity inflictor, entity attacker, float damage, int deathtype, .entity weaponentity, vector hitloc, vector force)
34{
35 if(GetResource(this, RES_HEALTH) <= 0)
36 return;
37
38 float is_linkexplode = ( ((inflictor.owner != NULL) ? (inflictor.owner == this.owner) : true)
39 && (inflictor.projectiledeathtype & HITTYPE_SECONDARY)
41
42 if(is_linkexplode)
43 is_linkexplode = (is_linkexplode && WEP_CVAR_SEC(WEP_HAGAR, load_linkexplode));
44 else
45 is_linkexplode = -1; // not secondary load, so continue as normal without exception.
46
47 if(!W_CheckProjectileDamage(inflictor.realowner, this.realowner, deathtype, is_linkexplode))
48 return; // g_projectiles_damage says to halt
49
50 TakeResource(this, RES_HEALTH, damage);
51 this.angles = vectoangles(this.velocity);
52
53 if(GetResource(this, RES_HEALTH) <= 0)
54 W_PrepareExplosionByDamage(this, attacker, getthink(this));
55}
56
58{
60 this.use(this, NULL, toucher);
61}
62
64{
66
67 if(this.cnt > 0 || toucher.takedamage == DAMAGE_AIM) {
68 this.use(this, NULL, toucher);
69 } else {
70 this.cnt++;
71 Send_Effect(EFFECT_HAGAR_BOUNCE, this.origin, this.velocity, 1);
72 this.angles = vectoangles(this.velocity);
73 this.owner = NULL;
75 }
76}
77
78void W_Hagar_Attack(Weapon thiswep, entity actor, .entity weaponentity)
79{
80 entity missile;
81
82 W_DecreaseAmmo(thiswep, actor, WEP_CVAR_PRI(WEP_HAGAR, ammo), weaponentity);
83
84 W_SetupShot(actor, weaponentity, false, 2, SND_HAGAR_FIRE, CH_WEAPON_A, WEP_CVAR_PRI(WEP_HAGAR, damage), thiswep.m_id);
85
86 W_MuzzleFlash(thiswep, actor, weaponentity, w_shotorg, w_shotdir);
87
88 missile = new(missile);
89 missile.owner = missile.realowner = actor;
90 missile.bot_dodge = true;
91 missile.bot_dodgerating = WEP_CVAR_PRI(WEP_HAGAR, damage);
92
93 missile.takedamage = DAMAGE_YES;
94 SetResourceExplicit(missile, RES_HEALTH, WEP_CVAR_PRI(WEP_HAGAR, health));
95 missile.damageforcescale = WEP_CVAR_PRI(WEP_HAGAR, damageforcescale);
96 missile.event_damage = W_Hagar_Damage;
97 missile.damagedbycontents = true;
99
100 settouch(missile, W_Hagar_Touch);
101 missile.use = W_Hagar_Explode_use;
103 missile.nextthink = time + WEP_CVAR_PRI(WEP_HAGAR, lifetime);
104 PROJECTILE_MAKETRIGGER(missile);
105 missile.projectiledeathtype = thiswep.m_id;
106 missile.weaponentity_fld = weaponentity;
107 setorigin(missile, w_shotorg);
108 setsize(missile, '0 0 0', '0 0 0');
109
110 set_movetype(missile, MOVETYPE_FLY);
111 W_SetupProjVelocity_PRI(missile, WEP_HAGAR);
112
113 missile.angles = vectoangles(missile.velocity);
114 missile.flags = FL_PROJECTILE;
115 IL_PUSH(g_projectiles, missile);
116 IL_PUSH(g_bot_dodge, missile);
117 missile.missile_flags = MIF_SPLASH;
118
119 CSQCProjectile(missile, true, PROJECTILE_HAGAR, true);
120
121 MUTATOR_CALLHOOK(EditProjectile, actor, missile);
122}
123
124void W_Hagar_Attack2(Weapon thiswep, entity actor, .entity weaponentity)
125{
126 entity missile;
127
128 W_DecreaseAmmo(thiswep, actor, WEP_CVAR_SEC(WEP_HAGAR, ammo), weaponentity);
129
130 W_SetupShot(actor, weaponentity, false, 2, SND_HAGAR_FIRE, CH_WEAPON_A, WEP_CVAR_SEC(WEP_HAGAR, damage), thiswep.m_id | HITTYPE_SECONDARY);
131
132 W_MuzzleFlash(thiswep, actor, weaponentity, w_shotorg, w_shotdir);
133
134 missile = new(missile);
135 missile.owner = missile.realowner = actor;
136 missile.bot_dodge = true;
137 missile.bot_dodgerating = WEP_CVAR_SEC(WEP_HAGAR, damage);
138
139 missile.takedamage = DAMAGE_YES;
140 SetResourceExplicit(missile, RES_HEALTH, WEP_CVAR_SEC(WEP_HAGAR, health));
141 missile.damageforcescale = WEP_CVAR_SEC(WEP_HAGAR, damageforcescale);
142 missile.event_damage = W_Hagar_Damage;
143 missile.damagedbycontents = true;
145
146 settouch(missile, W_Hagar_Touch2);
147 missile.cnt = 0;
148 missile.use = W_Hagar_Explode2_use;
150 missile.nextthink = time + WEP_CVAR_SEC(WEP_HAGAR, lifetime_min) + random() * WEP_CVAR_SEC(WEP_HAGAR, lifetime_rand);
151 PROJECTILE_MAKETRIGGER(missile);
152 missile.projectiledeathtype = thiswep.m_id | HITTYPE_SECONDARY;
153 missile.weaponentity_fld = weaponentity;
154 setorigin(missile, w_shotorg);
155 setsize(missile, '0 0 0', '0 0 0');
156
158 W_SetupProjVelocity_SEC(missile, WEP_HAGAR);
159
160 missile.angles = vectoangles(missile.velocity);
161 missile.flags = FL_PROJECTILE;
162 IL_PUSH(g_projectiles, missile);
163 IL_PUSH(g_bot_dodge, missile);
164 missile.missile_flags = MIF_SPLASH;
165
166 CSQCProjectile(missile, true, PROJECTILE_HAGAR_BOUNCING, true);
167
168 MUTATOR_CALLHOOK(EditProjectile, actor, missile);
169}
170
172void W_Hagar_Attack2_Load_Release(Weapon thiswep, entity actor, .entity weaponentity)
173{
174 // time to release the rockets we've loaded
175
176 entity missile;
177 float counter, shots, spread_pershot;
178 vector s;
179 vector forward, right, up;
180
181 if(!actor.(weaponentity).hagar_load)
182 return;
183
184 weapon_prepareattack_do(actor, weaponentity, true, WEP_CVAR_SEC(WEP_HAGAR, refire));
185
186 shots = actor.(weaponentity).hagar_load;
187 W_SetupShot(actor, weaponentity, false, 2, SND_HAGAR_FIRE, CH_WEAPON_A, WEP_CVAR_SEC(WEP_HAGAR, damage) * shots, thiswep.m_id | HITTYPE_SECONDARY);
188 W_MuzzleFlash(thiswep, actor, weaponentity, w_shotorg, w_shotdir);
189
190 forward = v_forward;
191 right = v_right;
192 up = v_up;
193
194 missile = NULL;
195 for(counter = 0; counter < shots; ++counter)
196 {
197 missile = new(missile);
198 missile.owner = missile.realowner = actor;
199 missile.bot_dodge = true;
200 missile.bot_dodgerating = WEP_CVAR_SEC(WEP_HAGAR, damage);
201
202 missile.takedamage = DAMAGE_YES;
203 SetResourceExplicit(missile, RES_HEALTH, WEP_CVAR_SEC(WEP_HAGAR, health));
204 missile.damageforcescale = WEP_CVAR_SEC(WEP_HAGAR, damageforcescale);
205 missile.event_damage = W_Hagar_Damage;
206 missile.damagedbycontents = true;
208
209 settouch(missile, W_Hagar_Touch); // not bouncy
210 missile.use = W_Hagar_Explode2_use;
212 missile.nextthink = time + WEP_CVAR_SEC(WEP_HAGAR, lifetime_min) + random() * WEP_CVAR_SEC(WEP_HAGAR, lifetime_rand);
213 PROJECTILE_MAKETRIGGER(missile);
214 missile.projectiledeathtype = thiswep.m_id | HITTYPE_SECONDARY;
215 missile.weaponentity_fld = weaponentity;
216 setorigin(missile, w_shotorg);
217 setsize(missile, '0 0 0', '0 0 0');
218 set_movetype(missile, MOVETYPE_FLY);
219 missile.missile_flags = MIF_SPLASH;
220
221 // per-shot spread calculation: the more shots there are, the less spread is applied (based on the bias cvar)
222 spread_pershot = ((shots - 1) / (WEP_CVAR_SEC(WEP_HAGAR, load_max) - 1));
223 spread_pershot = (1 - (spread_pershot * WEP_CVAR_SEC(WEP_HAGAR, load_spread_bias)));
224 spread_pershot = (WEP_CVAR_SEC(WEP_HAGAR, spread) * spread_pershot * autocvar_g_weaponspreadfactor);
225
226 s = W_CalculateSpreadPattern(1, 0, counter, shots);
227 s = s * WEP_CVAR_SEC(WEP_HAGAR, load_spread) * autocvar_g_weaponspreadfactor;
228
229 W_SetupProjVelocity_Explicit(missile, w_shotdir + right * s.y + up * s.z, v_up, WEP_CVAR_SEC(WEP_HAGAR, speed), 0, 0, spread_pershot, false);
230
231 missile.angles = vectoangles(missile.velocity);
232 missile.flags = FL_PROJECTILE;
233 IL_PUSH(g_projectiles, missile);
234 IL_PUSH(g_bot_dodge, missile);
235
236 CSQCProjectile(missile, true, PROJECTILE_HAGAR, true);
237
238 MUTATOR_CALLHOOK(EditProjectile, actor, missile);
239 }
240
241 weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, WEP_CVAR_SEC(WEP_HAGAR, load_animtime), w_ready);
242 actor.(weaponentity).hagar_loadstep = time + WEP_CVAR_SEC(WEP_HAGAR, refire) * W_WeaponRateFactor(actor);
243 actor.(weaponentity).hagar_load = 0;
244}
245
246void W_Hagar_Attack2_Load(Weapon thiswep, entity actor, .entity weaponentity)
247{
248 // loadable hagar secondary attack, must always run each frame
249 if(time < game_starttime || time < actor.race_penalty || timeout_status == TIMEOUT_ACTIVE)
250 return;
251 if (weaponUseForbidden(actor))
252 return;
253
254 bool loaded = actor.(weaponentity).hagar_load >= WEP_CVAR_SEC(WEP_HAGAR, load_max);
255
256 // this is different than WR_CHECKAMMO when it comes to reloading
257 bool enough_ammo;
258 if(actor.items & IT_UNLIMITED_AMMO)
259 enough_ammo = true;
260 else if(autocvar_g_balance_hagar_reload_ammo)
261 enough_ammo = actor.(weaponentity).(weapon_load[thiswep.m_id]) >= WEP_CVAR_SEC(WEP_HAGAR, ammo);
262 else
263 enough_ammo = GetResource(actor, thiswep.ammo_type) >= WEP_CVAR_SEC(WEP_HAGAR, ammo);
264
265 bool stopped = loaded || !enough_ammo;
266
267 if(PHYS_INPUT_BUTTON_ATCK2(actor))
268 {
269 if(PHYS_INPUT_BUTTON_ATCK(actor) && WEP_CVAR_SEC(WEP_HAGAR, load_abort))
270 {
271 if(actor.(weaponentity).hagar_load)
272 {
273 // if we pressed primary fire while loading, unload all rockets and abort
274 actor.(weaponentity).state = WS_READY;
275 W_DecreaseAmmo(thiswep, actor, WEP_CVAR_SEC(WEP_HAGAR, ammo) * actor.(weaponentity).hagar_load * -1, weaponentity); // give back ammo
276 actor.(weaponentity).hagar_load = 0;
277 sound(actor, CH_WEAPON_A, SND_HAGAR_BEEP, VOL_BASE, ATTN_NORM);
278
279 // pause until we can load rockets again, once we re-press the alt fire button
280 actor.(weaponentity).hagar_loadstep = time + WEP_CVAR_SEC(WEP_HAGAR, load_speed) * W_WeaponRateFactor(actor);
281
282 // require letting go of the alt fire button before we can load again
283 actor.(weaponentity).hagar_loadblock = true;
284 }
285 }
286 else
287 {
288 // check if we can attempt to load another rocket
289 if(!stopped)
290 {
291 if(!actor.(weaponentity).hagar_loadblock && actor.(weaponentity).hagar_loadstep < time)
292 {
293 W_DecreaseAmmo(thiswep, actor, WEP_CVAR_SEC(WEP_HAGAR, ammo), weaponentity);
294 actor.(weaponentity).state = WS_INUSE;
295 actor.(weaponentity).hagar_load += 1;
296 sound(actor, CH_WEAPON_B, SND_HAGAR_LOAD, VOL_BASE * 0.8, ATTN_NORM); // sound is too loud according to most
297
298 if(actor.(weaponentity).hagar_load >= WEP_CVAR_SEC(WEP_HAGAR, load_max))
299 stopped = true;
300 else
301 actor.(weaponentity).hagar_loadstep = time + WEP_CVAR_SEC(WEP_HAGAR, load_speed) * W_WeaponRateFactor(actor);
302 }
303 }
304 if(stopped && !actor.(weaponentity).hagar_loadbeep && actor.(weaponentity).hagar_load) // prevents the beep from playing each frame
305 {
306 // if this is the last rocket we can load, play a beep sound to notify the player
307 sound(actor, CH_WEAPON_A, SND_HAGAR_BEEP, VOL_BASE, ATTN_NORM);
308 actor.(weaponentity).hagar_loadbeep = true;
309 actor.(weaponentity).hagar_loadstep = time + WEP_CVAR_SEC(WEP_HAGAR, load_hold) * W_WeaponRateFactor(actor);
310 }
311 }
312 }
313 else if(actor.(weaponentity).hagar_loadblock)
314 {
315 // the alt fire button has been released, so re-enable loading if blocked
316 actor.(weaponentity).hagar_loadblock = false;
317 }
318
319 if(actor.(weaponentity).hagar_load)
320 {
321 // play warning sound if we're about to release
322 if(stopped && actor.(weaponentity).hagar_loadstep - 0.5 < time && WEP_CVAR_SEC(WEP_HAGAR, load_hold) >= 0)
323 {
324 if(!actor.(weaponentity).hagar_warning) // prevents the beep from playing each frame
325 {
326 // we're about to automatically release after holding time, play a beep sound to notify the player
327 sound(actor, CH_WEAPON_A, SND_HAGAR_BEEP, VOL_BASE, ATTN_NORM);
328 actor.(weaponentity).hagar_warning = true;
329 }
330 }
331
332 // release if player let go of button or if they've held it in too long
333 if(!PHYS_INPUT_BUTTON_ATCK2(actor) || (stopped && actor.(weaponentity).hagar_loadstep < time && WEP_CVAR_SEC(WEP_HAGAR, load_hold) >= 0))
334 {
335 actor.(weaponentity).state = WS_READY;
336 W_Hagar_Attack2_Load_Release(thiswep, actor, weaponentity);
337 }
338 }
339 else
340 {
341 actor.(weaponentity).hagar_loadbeep = false;
342 actor.(weaponentity).hagar_warning = false;
343
344 // we aren't checking ammo during an attack, so we must do it here
345 if(!(thiswep.wr_checkammo1(thiswep, actor, weaponentity) + thiswep.wr_checkammo2(thiswep, actor, weaponentity)))
346 if(!(actor.items & IT_UNLIMITED_AMMO))
347 {
348 // note: this doesn't force the switch
349 W_SwitchToOtherWeapon(actor, weaponentity);
350 return;
351 }
352 }
353}
354
355void W_Hagar_Attack_Auto(Weapon thiswep, entity actor, .entity weaponentity, int fire)
356{
357 if(!(fire & 1) || actor.(weaponentity).hagar_load || actor.(weaponentity).hagar_loadblock || actor.(weaponentity).m_switchweapon != thiswep || !weapon_prepareattack_check(thiswep, actor, weaponentity, false, -1))
358 {
359 w_ready(thiswep, actor, weaponentity, fire);
360 return;
361 }
362
363 if(!thiswep.wr_checkammo1(thiswep, actor, weaponentity))
364 if(!(actor.items & IT_UNLIMITED_AMMO))
365 {
366 W_SwitchWeapon_Force(actor, w_getbestweapon(actor, weaponentity), weaponentity);
367 w_ready(thiswep, actor, weaponentity, fire);
368 return;
369 }
370
371 W_Hagar_Attack(thiswep, actor, weaponentity);
372
373 ATTACK_FINISHED(actor, weaponentity) = time + WEP_CVAR_PRI(WEP_HAGAR, refire) * W_WeaponRateFactor(actor);
374 actor.(weaponentity).wframe = WFRAME_FIRE1;
375 weapon_thinkf(actor, weaponentity, WFRAME_DONTCHANGE, WEP_CVAR_PRI(WEP_HAGAR, refire), W_Hagar_Attack_Auto);
376}
377
378METHOD(Hagar, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
379{
380 if(random()>0.15)
381 PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, weaponentity, WEP_CVAR_PRI(WEP_HAGAR, speed), 0, WEP_CVAR_PRI(WEP_HAGAR, lifetime), false, true);
382 else // not using secondary_speed since these are only 15% and should cause some ricochets without re-aiming
383 PHYS_INPUT_BUTTON_ATCK2(actor) = bot_aim(actor, weaponentity, WEP_CVAR_PRI(WEP_HAGAR, speed), 0, WEP_CVAR_PRI(WEP_HAGAR, lifetime), false, true);
384}
385
386METHOD(Hagar, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
387{
388 float loadable_secondary;
389 loadable_secondary = (WEP_CVAR_SEC(WEP_HAGAR, load) && WEP_CVAR(WEP_HAGAR, secondary));
390
391 if(loadable_secondary)
392 W_Hagar_Attack2_Load(thiswep, actor, weaponentity); // must always run each frame
393 if(autocvar_g_balance_hagar_reload_ammo && actor.(weaponentity).clip_load < min(WEP_CVAR_PRI(WEP_HAGAR, ammo), WEP_CVAR_SEC(WEP_HAGAR, ammo))) { // forced reload
394 thiswep.wr_reload(thiswep, actor, weaponentity);
395 }
396 else if((fire & 1) && !actor.(weaponentity).hagar_load && !actor.(weaponentity).hagar_loadblock) // not while secondary is loaded or awaiting reset
397 {
398 if(weapon_prepareattack(thiswep, actor, weaponentity, false, 0))
399 W_Hagar_Attack_Auto(thiswep, actor, weaponentity, fire);
400 }
401 else if((fire & 2) && !loadable_secondary && WEP_CVAR(WEP_HAGAR, secondary))
402 {
403 if(weapon_prepareattack(thiswep, actor, weaponentity, true, WEP_CVAR_SEC(WEP_HAGAR, refire)))
404 {
405 W_Hagar_Attack2(thiswep, actor, weaponentity);
406 weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, WEP_CVAR_SEC(WEP_HAGAR, refire), w_ready);
407 }
408 }
409}
410
411METHOD(Hagar, wr_gonethink, void(entity thiswep, entity actor, .entity weaponentity))
412{
413 // we lost the weapon and want to prepare switching away
414 if(actor.(weaponentity).hagar_load)
415 {
416 actor.(weaponentity).state = WS_READY;
417 W_Hagar_Attack2_Load_Release(thiswep, actor, weaponentity);
418 }
419}
420
421METHOD(Hagar, wr_setup, void(entity thiswep, entity actor, .entity weaponentity))
422{
423 actor.(weaponentity).hagar_loadblock = false;
424 if(actor.(weaponentity).hagar_load)
425 {
426 W_DecreaseAmmo(thiswep, actor, WEP_CVAR_SEC(WEP_HAGAR, ammo) * actor.(weaponentity).hagar_load * -1, weaponentity); // give back ammo if necessary
427 actor.(weaponentity).hagar_load = 0;
428 }
429}
430
431METHOD(Hagar, wr_checkammo1, bool(entity thiswep, entity actor, .entity weaponentity))
432{
433 float ammo_amount = GetResource(actor, thiswep.ammo_type) >= WEP_CVAR_PRI(WEP_HAGAR, ammo);
434 ammo_amount += actor.(weaponentity).(weapon_load[thiswep.m_id]) >= WEP_CVAR_PRI(WEP_HAGAR, ammo);
435 return ammo_amount;
436}
437
438METHOD(Hagar, wr_checkammo2, bool(entity thiswep, entity actor, .entity weaponentity))
439{
440 float ammo_amount = GetResource(actor, thiswep.ammo_type) >= WEP_CVAR_SEC(WEP_HAGAR, ammo);
441 ammo_amount += actor.(weaponentity).(weapon_load[thiswep.m_id]) >= WEP_CVAR_SEC(WEP_HAGAR, ammo);
442 return ammo_amount;
443}
444
445METHOD(Hagar, wr_resetplayer, void(entity thiswep, entity actor))
446{
447 for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
448 {
449 .entity weaponentity = weaponentities[slot];
450 actor.(weaponentity).hagar_load = 0;
451 }
452}
453
454METHOD(Hagar, wr_playerdeath, void(entity thiswep, entity actor, .entity weaponentity))
455{
456 // if we have any rockets loaded when we die, release them
457 if(actor.(weaponentity).hagar_load && WEP_CVAR_SEC(WEP_HAGAR, load_releasedeath))
458 W_Hagar_Attack2_Load_Release(thiswep, actor, weaponentity);
459}
460
461METHOD(Hagar, wr_reload, void(entity thiswep, entity actor, .entity weaponentity))
462{
463 if(!actor.(weaponentity).hagar_load) // require releasing loaded rockets first
464 W_Reload(actor, weaponentity, min(WEP_CVAR_PRI(WEP_HAGAR, ammo), WEP_CVAR_SEC(WEP_HAGAR, ammo)), SND_RELOAD);
465}
466
467METHOD(Hagar, wr_suicidemessage, Notification(entity thiswep))
468{
469 return WEAPON_HAGAR_SUICIDE;
470}
471
472METHOD(Hagar, wr_killmessage, Notification(entity thiswep))
473{
475 return WEAPON_HAGAR_MURDER_BURST;
476 else
477 return WEAPON_HAGAR_MURDER_SPRAY;
478}
479
480#endif
481#ifdef CSQC
482
483METHOD(Hagar, wr_impacteffect, void(entity thiswep, entity actor))
484{
485 vector org2 = w_org + w_backoff * 2;
486 pointparticles(EFFECT_HAGAR_EXPLODE, org2, '0 0 0', 1);
487 if(!w_issilent)
489}
490
491#endif
492#ifdef MENUQC
494
495METHOD(Hagar, describe, string(Hagar this))
496{
497 TC(Hagar, this);
499 PAR(_("The %s rapidly fires small propelled rockets forwards, dealing some splash damage on impact."), COLORED_NAME(this));
500 PAR(_("When the secondary fire is held, multiple rockets are loaded up, and they're shot at the same time when released. "
501 "These rockets can't be held forever, so it will fire itself after some time (after a warning beep) if the secondary fire isn't released."));
502 PAR(_("It consumes %s ammo for each rocket."), COLORED_NAME(ITEM_Rockets));
503 PAR(_("The %s works best over close to medium ranges, since it's hard to land hits at a long distance. "
504 "A common usage is fully loading the secondary fire before turning a corner, so you can surprise any enemies around the corner with a bunch of rockets to the face."), COLORED_NAME(this));
505 PAR(W_Guide_Keybinds(this));
506 PAR(W_Guide_DPS_secondaryMultishot(this.netname, "primary", "secondary", "secondary_load_max", "secondary_load_speed", true));
507 return PAGE_TEXT;
508}
509
510#endif
bool bot_aim(entity this,.entity weaponentity, float shotspeed, float shotspeedupward, float maxshottime, float applygravity, bool shot_accurate)
IntrusiveList g_bot_dodge
Definition api.qh:150
#define MUTATOR_CALLHOOK(id,...)
Definition base.qh:143
vector W_CalculateSpreadPattern(int pattern, float bias, int counter, int total)
float autocvar_g_weaponspreadfactor
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.
void TakeResource(entity receiver, Resource res_type, float amount)
Takes an entity some resource.
bool SetResourceExplicit(entity e, Resource res_type, float amount)
Sets the resource amount of an entity without calling any hooks.
Definition hagar.qh:19
fields which are explicitly/manually set are marked with "M", fields set automatically are marked wit...
Definition weapon.qh:44
Resource ammo_type
M: ammotype : main ammo type.
Definition weapon.qh:51
int m_id
Definition weapon.qh:45
virtual void wr_checkammo2()
(SERVER) checks ammo for weapon second
Definition weapon.qh:94
virtual void wr_checkammo1()
(SERVER) checks ammo for weapon primary
Definition weapon.qh:92
string netname
Definition powerups.qc:20
float lifetime
Definition powerups.qc:23
float cnt
Definition powerups.qc:24
entity owner
Definition main.qh:87
#define COLORED_NAME(this)
Definition color.qh:195
const int IT_UNLIMITED_AMMO
Definition item.qh:23
float radius
Definition impulse.qh:11
#define PHYS_INPUT_BUTTON_ATCK(s)
Definition player.qh:150
#define PHYS_INPUT_BUTTON_ATCK2(s)
Definition player.qh:152
int timeout_status
Definition stats.qh:87
float game_starttime
Definition stats.qh:82
float W_WeaponRateFactor(entity this)
const int FL_PROJECTILE
Definition constants.qh:85
vector v_up
vector velocity
float time
vector v_right
vector v_forward
vector origin
const float ATTN_NORM
#define use
void CSQCProjectile(entity e, float clientanimate, int type, float docull)
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:981
IntrusiveList g_damagedbycontents
Definition damage.qh:135
void W_SwitchWeapon_Force(Player this, Weapon w,.entity weaponentity)
Definition selection.qc:246
int state
vector w_org
int w_deathtype
float damageforcescale
float w_random
vector w_backoff
float w_issilent
const int HITTYPE_BOUNCE
Definition all.qh:31
const int HITTYPE_SECONDARY
Definition all.qh:29
float speed
Definition dynlight.qc:9
#define pointparticles(effect, org, vel, howmany)
Definition effect.qh:7
void Send_Effect(entity eff, vector eff_loc, vector eff_vel, int eff_cnt)
Definition all.qc:124
ent angles
Definition ent_cs.qc:121
float hagar_loadbeep
Definition hagar.qc:171
void W_Hagar_Explode_use(entity this, entity actor, entity trigger)
Definition hagar.qc:15
void W_Hagar_Attack2(Weapon thiswep, entity actor,.entity weaponentity)
Definition hagar.qc:124
void W_Hagar_Attack_Auto(Weapon thiswep, entity actor,.entity weaponentity, int fire)
Definition hagar.qc:355
void W_Hagar_Attack(Weapon thiswep, entity actor,.entity weaponentity)
Definition hagar.qc:78
void W_Hagar_Attack2_Load_Release(Weapon thiswep, entity actor,.entity weaponentity)
Definition hagar.qc:172
void W_Hagar_Explode2_use(entity this, entity actor, entity trigger)
Definition hagar.qc:28
void W_Hagar_Explode(entity this, entity directhitentity)
Definition hagar.qc:7
float hagar_loadstep
Definition hagar.qc:171
float hagar_warning
Definition hagar.qc:171
void W_Hagar_Damage(entity this, entity inflictor, entity attacker, float damage, int deathtype,.entity weaponentity, vector hitloc, vector force)
Definition hagar.qc:33
float hagar_loadblock
Definition hagar.qc:171
void W_Hagar_Touch2(entity this, entity toucher)
Definition hagar.qc:63
void W_Hagar_Attack2_Load(Weapon thiswep, entity actor,.entity weaponentity)
Definition hagar.qc:246
void W_Hagar_Explode2(entity this, entity directhitentity)
Definition hagar.qc:20
void W_Hagar_Touch(entity this, entity toucher)
Definition hagar.qc:57
Sound SND_HAGEXP_RANDOM(float rnd)
Definition hagar.qh:14
ERASEABLE entity IL_PUSH(IntrusiveList this, entity it)
Push to tail.
#define TC(T, sym)
Definition _all.inc:82
float random(void)
vector vectoangles(vector v)
float min(float f,...)
void set_movetype(entity this, int mt)
Definition movetypes.qc:4
const int MOVETYPE_BOUNCEMISSILE
Definition movetypes.qh:140
const int MOVETYPE_FLY
Definition movetypes.qh:134
var void func_null()
entity Notification
always last
Definition all.qh:81
#define METHOD(cname, name, prototype)
Definition oo.qh:269
#define NULL
Definition post.qh:14
const int PROJECTILE_HAGAR
const int PROJECTILE_HAGAR_BOUNCING
float health
Legacy fields for the resources. To be removed.
Definition resources.qh:9
void W_SwitchToOtherWeapon(entity this,.entity weaponentity)
Definition selection.qc:256
#define w_getbestweapon(ent, wepent)
Definition selection.qh:23
#define setthink(e, f)
#define getthink(e)
vector
Definition self.qh:92
entity entity toucher
Definition self.qh:72
#define settouch(e, f)
Definition self.qh:73
const float TIMEOUT_ACTIVE
Definition common.qh:49
float W_CheckProjectileDamage(entity inflictor, entity projowner, int deathtype, float exception)
Definition common.qc:45
void W_PrepareExplosionByDamage(entity this, entity attacker, void(entity this) explode)
Definition common.qc:87
void adaptor_think2use_hittype_splash(entity this)
Definition common.qc:106
const int MIF_SPLASH
Definition common.qh:46
int projectiledeathtype
Definition common.qh:21
#define PROJECTILE_TOUCH(e, t)
Definition common.qh:28
IntrusiveList g_projectiles
Definition common.qh:58
#define PROJECTILE_MAKETRIGGER(e)
Definition common.qh:34
const float VOL_BASE
Definition sound.qh:36
const int CH_SHOTS
Definition sound.qh:14
const int CH_WEAPON_A
Definition sound.qh:7
#define sound(e, c, s, v, a)
Definition sound.qh:52
const int CH_WEAPON_B
Definition sound.qh:8
#define PAGE_TEXT
Definition string.qh:643
#define PAR(...)
Adds an individually translatable paragraph to PAGE_TEXT without having to deal with strcat and sprin...
Definition string.qh:649
#define PAGE_TEXT_INIT()
Definition string.qh:642
const int DAMAGE_YES
Definition subs.qh:80
const int DAMAGE_AIM
Definition subs.qh:81
float ammo
Definition sv_turrets.qh:43
entity realowner
void W_SetupProjVelocity_Explicit(entity proj, vector dir, vector upDir, float pSpeed, float pUpSpeed, float pZSpeed, float spread, float forceAbsolute)
Definition tracing.qc:192
#define W_SetupProjVelocity_SEC(ent, wep)
Definition tracing.qh:67
vector w_shotdir
Definition tracing.qh:20
#define W_SetupProjVelocity_PRI(ent, wep)
Definition tracing.qh:65
vector w_shotorg
Definition tracing.qh:19
#define W_SetupShot(ent, wepent, antilag, recoil, snd, chan, maxdamage, deathtype)
Definition tracing.qh:34
string W_Guide_Keybinds(Weapon wep)
Definition all.qc:836
string W_Guide_DPS_secondaryMultishot(string name, string pri, string sec, string shots, string refire2, bool sec_variable)
Definition all.qc:967
void W_MuzzleFlash(Weapon thiswep, entity actor,.entity weaponentity, vector shotorg, vector shotdir)
Definition all.qc:728
#define WEP_CVAR_PRI(wep, name)
Definition all.qh:322
WFRAME wframe
Definition all.qh:414
#define WEP_CVAR(wep, name)
Definition all.qh:321
#define WEP_CVAR_SEC(wep, name)
Definition all.qh:323
const int MAX_WEAPONSLOTS
Definition weapon.qh:16
const int WS_READY
idle frame
Definition weapon.qh:41
entity weaponentities[MAX_WEAPONSLOTS]
Definition weapon.qh:17
const int WS_INUSE
fire state
Definition weapon.qh:39
void W_DecreaseAmmo(Weapon wep, entity actor, float ammo_use,.entity weaponentity)
void W_Reload(entity actor,.entity weaponentity, float sent_ammo_min, Sound sent_sound)
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)
bool weaponUseForbidden(entity player)
void w_ready(Weapon thiswep, entity actor,.entity weaponentity, int fire)
void weapon_prepareattack_do(entity actor,.entity weaponentity, bool secondary, float attacktime)
bool weapon_prepareattack_check(Weapon thiswep, entity actor,.entity weaponentity, bool secondary, float attacktime)
#define ATTACK_FINISHED(ent, w)
entity weaponentity_fld
float weapon_load[REGISTRY_MAX(Weapons)]
int hagar_load
Definition wepent.qh:13