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