Quake II RTX doxygen  1.0 dev
p_weapon.c
Go to the documentation of this file.
1 /*
2 Copyright (C) 1997-2001 Id Software, Inc.
3 
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13 
14 You should have received a copy of the GNU General Public License along
15 with this program; if not, write to the Free Software Foundation, Inc.,
16 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18 // g_weapon.c
19 
20 #include "g_local.h"
21 #include "m_player.h"
22 
23 
24 static qboolean is_quad;
25 static byte is_silenced;
26 
27 
28 void weapon_grenade_fire(edict_t *ent, qboolean held);
29 
30 
31 static void P_ProjectSource(gclient_t *client, vec3_t point, vec3_t distance, vec3_t forward, vec3_t right, vec3_t result)
32 {
33  vec3_t _distance;
34 
35  VectorCopy(distance, _distance);
36  if (client->pers.hand == LEFT_HANDED)
37  _distance[1] *= -1;
38  else if (client->pers.hand == CENTER_HANDED)
39  _distance[1] = 0;
40  G_ProjectSource(point, _distance, forward, right, result);
41 }
42 
43 
44 /*
45 ===============
46 PlayerNoise
47 
48 Each player can have two noise objects associated with it:
49 a personal noise (jumping, pain, weapon firing), and a weapon
50 target noise (bullet wall impacts)
51 
52 Monsters that don't directly see the player can move
53 to a noise in hopes of seeing the player from there.
54 ===============
55 */
56 void PlayerNoise(edict_t *who, vec3_t where, int type)
57 {
58  edict_t *noise;
59 
60  if (type == PNOISE_WEAPON) {
61  if (who->client->silencer_shots) {
62  who->client->silencer_shots--;
63  return;
64  }
65  }
66 
67  if (deathmatch->value)
68  return;
69 
70  if (who->flags & FL_NOTARGET)
71  return;
72 
73 
74  if (!who->mynoise) {
75  noise = G_Spawn();
76  noise->classname = "player_noise";
77  VectorSet(noise->mins, -8, -8, -8);
78  VectorSet(noise->maxs, 8, 8, 8);
79  noise->owner = who;
80  noise->svflags = SVF_NOCLIENT;
81  who->mynoise = noise;
82 
83  noise = G_Spawn();
84  noise->classname = "player_noise";
85  VectorSet(noise->mins, -8, -8, -8);
86  VectorSet(noise->maxs, 8, 8, 8);
87  noise->owner = who;
88  noise->svflags = SVF_NOCLIENT;
89  who->mynoise2 = noise;
90  }
91 
92  if (type == PNOISE_SELF || type == PNOISE_WEAPON) {
93  noise = who->mynoise;
94  level.sound_entity = noise;
96  } else { // type == PNOISE_IMPACT
97  noise = who->mynoise2;
98  level.sound2_entity = noise;
100  }
101 
102  VectorCopy(where, noise->s.origin);
103  VectorSubtract(where, noise->maxs, noise->absmin);
104  VectorAdd(where, noise->maxs, noise->absmax);
105  noise->teleport_time = level.time;
106  gi.linkentity(noise);
107 }
108 
109 
110 qboolean Pickup_Weapon(edict_t *ent, edict_t *other)
111 {
112  int index;
113  gitem_t *ammo;
114 
115  index = ITEM_INDEX(ent->item);
116 
117  if ((((int)(dmflags->value) & DF_WEAPONS_STAY) || coop->value)
118  && other->client->pers.inventory[index]) {
119  if (!(ent->spawnflags & (DROPPED_ITEM | DROPPED_PLAYER_ITEM)))
120  return qfalse; // leave the weapon for others to pickup
121  }
122 
123  other->client->pers.inventory[index]++;
124 
125  if (!(ent->spawnflags & DROPPED_ITEM)) {
126  // give them some ammo with it
127  ammo = FindItem(ent->item->ammo);
128  if ((int)dmflags->value & DF_INFINITE_AMMO)
129  Add_Ammo(other, ammo, 1000);
130  else
131  Add_Ammo(other, ammo, ammo->quantity);
132 
133  if (!(ent->spawnflags & DROPPED_PLAYER_ITEM)) {
134  if (deathmatch->value) {
135  if ((int)(dmflags->value) & DF_WEAPONS_STAY)
136  ent->flags |= FL_RESPAWN;
137  else
138  SetRespawn(ent, 30);
139  }
140  if (coop->value)
141  ent->flags |= FL_RESPAWN;
142  }
143  }
144 
145  if (other->client->pers.weapon != ent->item &&
146  (other->client->pers.inventory[index] == 1) &&
147  (!deathmatch->value || other->client->pers.weapon == FindItem("blaster")))
148  other->client->newweapon = ent->item;
149 
150  return qtrue;
151 }
152 
153 
154 /*
155 ===============
156 ChangeWeapon
157 
158 The old weapon has been dropped all the way, so make the new one
159 current
160 ===============
161 */
162 void ChangeWeapon(edict_t *ent)
163 {
164  int i;
165 
166  if (ent->client->grenade_time) {
167  ent->client->grenade_time = level.time;
168  ent->client->weapon_sound = 0;
169  weapon_grenade_fire(ent, qfalse);
170  ent->client->grenade_time = 0;
171  }
172 
173  ent->client->pers.lastweapon = ent->client->pers.weapon;
174  ent->client->pers.weapon = ent->client->newweapon;
175  ent->client->newweapon = NULL;
176  ent->client->machinegun_shots = 0;
177 
178  // set visible model
179  if (ent->s.modelindex == 255) {
180  if (ent->client->pers.weapon)
181  i = ((ent->client->pers.weapon->weapmodel & 0xff) << 8);
182  else
183  i = 0;
184  ent->s.skinnum = (ent - g_edicts - 1) | i;
185  }
186 
187  if (ent->client->pers.weapon && ent->client->pers.weapon->ammo)
188  ent->client->ammo_index = ITEM_INDEX(FindItem(ent->client->pers.weapon->ammo));
189  else
190  ent->client->ammo_index = 0;
191 
192  if (!ent->client->pers.weapon) {
193  // dead
194  ent->client->ps.gunindex = 0;
195  return;
196  }
197 
198  ent->client->weaponstate = WEAPON_ACTIVATING;
199  ent->client->ps.gunframe = 0;
200  ent->client->ps.gunindex = gi.modelindex(ent->client->pers.weapon->view_model);
201 
202  ent->client->anim_priority = ANIM_PAIN;
203  if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) {
204  ent->s.frame = FRAME_crpain1;
205  ent->client->anim_end = FRAME_crpain4;
206  } else {
207  ent->s.frame = FRAME_pain301;
208  ent->client->anim_end = FRAME_pain304;
209 
210  }
211 }
212 
213 /*
214 =================
215 NoAmmoWeaponChange
216 =================
217 */
218 void NoAmmoWeaponChange(edict_t *ent)
219 {
220  if (ent->client->pers.inventory[ITEM_INDEX(FindItem("slugs"))]
221  && ent->client->pers.inventory[ITEM_INDEX(FindItem("railgun"))]) {
222  ent->client->newweapon = FindItem("railgun");
223  return;
224  }
225  if (ent->client->pers.inventory[ITEM_INDEX(FindItem("cells"))]
226  && ent->client->pers.inventory[ITEM_INDEX(FindItem("hyperblaster"))]) {
227  ent->client->newweapon = FindItem("hyperblaster");
228  return;
229  }
230  if (ent->client->pers.inventory[ITEM_INDEX(FindItem("bullets"))]
231  && ent->client->pers.inventory[ITEM_INDEX(FindItem("chaingun"))]) {
232  ent->client->newweapon = FindItem("chaingun");
233  return;
234  }
235  if (ent->client->pers.inventory[ITEM_INDEX(FindItem("bullets"))]
236  && ent->client->pers.inventory[ITEM_INDEX(FindItem("machinegun"))]) {
237  ent->client->newweapon = FindItem("machinegun");
238  return;
239  }
240  if (ent->client->pers.inventory[ITEM_INDEX(FindItem("shells"))] > 1
241  && ent->client->pers.inventory[ITEM_INDEX(FindItem("super shotgun"))]) {
242  ent->client->newweapon = FindItem("super shotgun");
243  return;
244  }
245  if (ent->client->pers.inventory[ITEM_INDEX(FindItem("shells"))]
246  && ent->client->pers.inventory[ITEM_INDEX(FindItem("shotgun"))]) {
247  ent->client->newweapon = FindItem("shotgun");
248  return;
249  }
250  ent->client->newweapon = FindItem("blaster");
251 }
252 
253 /*
254 =================
255 Think_Weapon
256 
257 Called by ClientBeginServerFrame and ClientThink
258 =================
259 */
260 void Think_Weapon(edict_t *ent)
261 {
262  // if just died, put the weapon away
263  if (ent->health < 1) {
264  ent->client->newweapon = NULL;
265  ChangeWeapon(ent);
266  }
267 
268  // call active weapon think routine
269  if (ent->client->pers.weapon && ent->client->pers.weapon->weaponthink) {
270  is_quad = (ent->client->quad_framenum > level.framenum);
271  if (ent->client->silencer_shots)
272  is_silenced = MZ_SILENCED;
273  else
274  is_silenced = 0;
275  ent->client->pers.weapon->weaponthink(ent);
276  }
277 }
278 
279 
280 /*
281 ================
282 Use_Weapon
283 
284 Make the weapon ready if there is ammo
285 ================
286 */
287 void Use_Weapon(edict_t *ent, gitem_t *item)
288 {
289  int ammo_index;
290  gitem_t *ammo_item;
291 
292  // see if we're already using it
293  if (item == ent->client->pers.weapon)
294  return;
295 
296  if (item->ammo && !g_select_empty->value && !(item->flags & IT_AMMO)) {
297  ammo_item = FindItem(item->ammo);
298  ammo_index = ITEM_INDEX(ammo_item);
299 
300  if (!ent->client->pers.inventory[ammo_index]) {
301  gi.cprintf(ent, PRINT_HIGH, "No %s for %s.\n", ammo_item->pickup_name, item->pickup_name);
302  return;
303  }
304 
305  if (ent->client->pers.inventory[ammo_index] < item->quantity) {
306  gi.cprintf(ent, PRINT_HIGH, "Not enough %s for %s.\n", ammo_item->pickup_name, item->pickup_name);
307  return;
308  }
309  }
310 
311  // change to this weapon when down
312  ent->client->newweapon = item;
313 }
314 
315 
316 
317 /*
318 ================
319 Drop_Weapon
320 ================
321 */
322 void Drop_Weapon(edict_t *ent, gitem_t *item)
323 {
324  int index;
325 
326  if ((int)(dmflags->value) & DF_WEAPONS_STAY)
327  return;
328 
329  index = ITEM_INDEX(item);
330  // see if we're already using it
331  if (((item == ent->client->pers.weapon) || (item == ent->client->newweapon)) && (ent->client->pers.inventory[index] == 1)) {
332  gi.cprintf(ent, PRINT_HIGH, "Can't drop current weapon\n");
333  return;
334  }
335 
336  Drop_Item(ent, item);
337  ent->client->pers.inventory[index]--;
338 }
339 
340 
341 /*
342 ================
343 Weapon_Generic
344 
345 A generic function to handle the basics of weapon thinking
346 ================
347 */
348 #define FRAME_FIRE_FIRST (FRAME_ACTIVATE_LAST + 1)
349 #define FRAME_IDLE_FIRST (FRAME_FIRE_LAST + 1)
350 #define FRAME_DEACTIVATE_FIRST (FRAME_IDLE_LAST + 1)
351 
352 void Weapon_Generic(edict_t *ent, int FRAME_ACTIVATE_LAST, int FRAME_FIRE_LAST, int FRAME_IDLE_LAST, int FRAME_DEACTIVATE_LAST, int *pause_frames, int *fire_frames, void (*fire)(edict_t *ent))
353 {
354  int n;
355 
356  if (ent->deadflag || ent->s.modelindex != 255) { // VWep animations screw up corpses
357  return;
358  }
359 
360  if (ent->client->weaponstate == WEAPON_DROPPING) {
361  if (ent->client->ps.gunframe == FRAME_DEACTIVATE_LAST) {
362  ChangeWeapon(ent);
363  return;
364  } else if ((FRAME_DEACTIVATE_LAST - ent->client->ps.gunframe) == 4) {
365  ent->client->anim_priority = ANIM_REVERSE;
366  if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) {
367  ent->s.frame = FRAME_crpain4 + 1;
368  ent->client->anim_end = FRAME_crpain1;
369  } else {
370  ent->s.frame = FRAME_pain304 + 1;
371  ent->client->anim_end = FRAME_pain301;
372 
373  }
374  }
375 
376  ent->client->ps.gunframe++;
377  return;
378  }
379 
380  if (ent->client->weaponstate == WEAPON_ACTIVATING) {
381  if (ent->client->ps.gunframe == FRAME_ACTIVATE_LAST) {
382  ent->client->weaponstate = WEAPON_READY;
383  ent->client->ps.gunframe = FRAME_IDLE_FIRST;
384  return;
385  }
386 
387  ent->client->ps.gunframe++;
388  return;
389  }
390 
391  if ((ent->client->newweapon) && (ent->client->weaponstate != WEAPON_FIRING)) {
392  ent->client->weaponstate = WEAPON_DROPPING;
393  ent->client->ps.gunframe = FRAME_DEACTIVATE_FIRST;
394 
395  if ((FRAME_DEACTIVATE_LAST - FRAME_DEACTIVATE_FIRST) < 4) {
396  ent->client->anim_priority = ANIM_REVERSE;
397  if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) {
398  ent->s.frame = FRAME_crpain4 + 1;
399  ent->client->anim_end = FRAME_crpain1;
400  } else {
401  ent->s.frame = FRAME_pain304 + 1;
402  ent->client->anim_end = FRAME_pain301;
403 
404  }
405  }
406  return;
407  }
408 
409  if (ent->client->weaponstate == WEAPON_READY) {
410  if (((ent->client->latched_buttons | ent->client->buttons) & BUTTON_ATTACK)) {
411  ent->client->latched_buttons &= ~BUTTON_ATTACK;
412  if ((!ent->client->ammo_index) ||
413  (ent->client->pers.inventory[ent->client->ammo_index] >= ent->client->pers.weapon->quantity)) {
414  ent->client->ps.gunframe = FRAME_FIRE_FIRST;
415  ent->client->weaponstate = WEAPON_FIRING;
416 
417  // start the animation
418  ent->client->anim_priority = ANIM_ATTACK;
419  if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) {
420  ent->s.frame = FRAME_crattak1 - 1;
421  ent->client->anim_end = FRAME_crattak9;
422  } else {
423  ent->s.frame = FRAME_attack1 - 1;
424  ent->client->anim_end = FRAME_attack8;
425  }
426  } else {
427  if (level.time >= ent->pain_debounce_time) {
428  gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0);
429  ent->pain_debounce_time = level.time + 1;
430  }
431  NoAmmoWeaponChange(ent);
432  }
433  } else {
434  if (ent->client->ps.gunframe == FRAME_IDLE_LAST) {
435  ent->client->ps.gunframe = FRAME_IDLE_FIRST;
436  return;
437  }
438 
439  if (pause_frames) {
440  for (n = 0; pause_frames[n]; n++) {
441  if (ent->client->ps.gunframe == pause_frames[n]) {
442  if (rand() & 15)
443  return;
444  }
445  }
446  }
447 
448  ent->client->ps.gunframe++;
449  return;
450  }
451  }
452 
453  if (ent->client->weaponstate == WEAPON_FIRING) {
454  for (n = 0; fire_frames[n]; n++) {
455  if (ent->client->ps.gunframe == fire_frames[n]) {
456  if (ent->client->quad_framenum > level.framenum)
457  gi.sound(ent, CHAN_ITEM, gi.soundindex("items/damage3.wav"), 1, ATTN_NORM, 0);
458 
459  fire(ent);
460  break;
461  }
462  }
463 
464  if (!fire_frames[n])
465  ent->client->ps.gunframe++;
466 
467  if (ent->client->ps.gunframe == FRAME_IDLE_FIRST + 1)
468  ent->client->weaponstate = WEAPON_READY;
469  }
470 }
471 
472 
473 /*
474 ======================================================================
475 
476 GRENADE
477 
478 ======================================================================
479 */
480 
481 #define GRENADE_TIMER 3.0
482 #define GRENADE_MINSPEED 400
483 #define GRENADE_MAXSPEED 800
484 
485 void weapon_grenade_fire(edict_t *ent, qboolean held)
486 {
487  vec3_t offset;
488  vec3_t forward, right;
489  vec3_t start;
490  int damage = 125;
491  float timer;
492  int speed;
493  float radius;
494 
495  radius = damage + 40;
496  if (is_quad)
497  damage *= 4;
498 
499  VectorSet(offset, 8, 8, ent->viewheight - 8);
500  AngleVectors(ent->client->v_angle, forward, right, NULL);
501  P_ProjectSource(ent->client, ent->s.origin, offset, forward, right, start);
502 
503  timer = ent->client->grenade_time - level.time;
505  fire_grenade2(ent, start, forward, damage, speed, timer, radius, held);
506 
507  if (!((int)dmflags->value & DF_INFINITE_AMMO))
508  ent->client->pers.inventory[ent->client->ammo_index]--;
509 
510  ent->client->grenade_time = level.time + 1.0;
511 
512  if (ent->deadflag || ent->s.modelindex != 255) { // VWep animations screw up corpses
513  return;
514  }
515 
516  if (ent->health <= 0)
517  return;
518 
519  if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) {
520  ent->client->anim_priority = ANIM_ATTACK;
521  ent->s.frame = FRAME_crattak1 - 1;
522  ent->client->anim_end = FRAME_crattak3;
523  } else {
524  ent->client->anim_priority = ANIM_REVERSE;
525  ent->s.frame = FRAME_wave08;
526  ent->client->anim_end = FRAME_wave01;
527  }
528 }
529 
530 void Weapon_Grenade(edict_t *ent)
531 {
532  if ((ent->client->newweapon) && (ent->client->weaponstate == WEAPON_READY)) {
533  ChangeWeapon(ent);
534  return;
535  }
536 
537  if (ent->client->weaponstate == WEAPON_ACTIVATING) {
538  ent->client->weaponstate = WEAPON_READY;
539  ent->client->ps.gunframe = 16;
540  return;
541  }
542 
543  if (ent->client->weaponstate == WEAPON_READY) {
544  if (((ent->client->latched_buttons | ent->client->buttons) & BUTTON_ATTACK)) {
545  ent->client->latched_buttons &= ~BUTTON_ATTACK;
546  if (ent->client->pers.inventory[ent->client->ammo_index]) {
547  ent->client->ps.gunframe = 1;
548  ent->client->weaponstate = WEAPON_FIRING;
549  ent->client->grenade_time = 0;
550  } else {
551  if (level.time >= ent->pain_debounce_time) {
552  gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0);
553  ent->pain_debounce_time = level.time + 1;
554  }
555  NoAmmoWeaponChange(ent);
556  }
557  return;
558  }
559 
560  if ((ent->client->ps.gunframe == 29) || (ent->client->ps.gunframe == 34) || (ent->client->ps.gunframe == 39) || (ent->client->ps.gunframe == 48)) {
561  if (rand() & 15)
562  return;
563  }
564 
565  if (++ent->client->ps.gunframe > 48)
566  ent->client->ps.gunframe = 16;
567  return;
568  }
569 
570  if (ent->client->weaponstate == WEAPON_FIRING) {
571  if (ent->client->ps.gunframe == 5)
572  gi.sound(ent, CHAN_WEAPON, gi.soundindex("weapons/hgrena1b.wav"), 1, ATTN_NORM, 0);
573 
574  if (ent->client->ps.gunframe == 11) {
575  if (!ent->client->grenade_time) {
576  ent->client->grenade_time = level.time + GRENADE_TIMER + 0.2;
577  ent->client->weapon_sound = gi.soundindex("weapons/hgrenc1b.wav");
578  }
579 
580  // they waited too long, detonate it in their hand
581  if (!ent->client->grenade_blew_up && level.time >= ent->client->grenade_time) {
582  ent->client->weapon_sound = 0;
583  weapon_grenade_fire(ent, qtrue);
584  ent->client->grenade_blew_up = qtrue;
585  }
586 
587  if (ent->client->buttons & BUTTON_ATTACK)
588  return;
589 
590  if (ent->client->grenade_blew_up) {
591  if (level.time >= ent->client->grenade_time) {
592  ent->client->ps.gunframe = 15;
593  ent->client->grenade_blew_up = qfalse;
594  } else {
595  return;
596  }
597  }
598  }
599 
600  if (ent->client->ps.gunframe == 12) {
601  ent->client->weapon_sound = 0;
602  weapon_grenade_fire(ent, qfalse);
603  }
604 
605  if ((ent->client->ps.gunframe == 15) && (level.time < ent->client->grenade_time))
606  return;
607 
608  ent->client->ps.gunframe++;
609 
610  if (ent->client->ps.gunframe == 16) {
611  ent->client->grenade_time = 0;
612  ent->client->weaponstate = WEAPON_READY;
613  }
614  }
615 }
616 
617 /*
618 ======================================================================
619 
620 GRENADE LAUNCHER
621 
622 ======================================================================
623 */
624 
625 void weapon_grenadelauncher_fire(edict_t *ent)
626 {
627  vec3_t offset;
628  vec3_t forward, right;
629  vec3_t start;
630  int damage = 120;
631  float radius;
632 
633  radius = damage + 40;
634  if (is_quad)
635  damage *= 4;
636 
637  VectorSet(offset, 8, 8, ent->viewheight - 8);
638  AngleVectors(ent->client->v_angle, forward, right, NULL);
639  P_ProjectSource(ent->client, ent->s.origin, offset, forward, right, start);
640 
641  VectorScale(forward, -2, ent->client->kick_origin);
642  ent->client->kick_angles[0] = -1;
643 
644  fire_grenade(ent, start, forward, damage, 600, 2.5, radius);
645 
646  gi.WriteByte(svc_muzzleflash);
647  gi.WriteShort(ent - g_edicts);
648  gi.WriteByte(MZ_GRENADE | is_silenced);
649  gi.multicast(ent->s.origin, MULTICAST_PVS);
650 
651  ent->client->ps.gunframe++;
652 
653  PlayerNoise(ent, start, PNOISE_WEAPON);
654 
655  if (!((int)dmflags->value & DF_INFINITE_AMMO))
656  ent->client->pers.inventory[ent->client->ammo_index]--;
657 }
658 
659 void Weapon_GrenadeLauncher(edict_t *ent)
660 {
661  static int pause_frames[] = {34, 51, 59, 0};
662  static int fire_frames[] = {6, 0};
663 
664  Weapon_Generic(ent, 5, 16, 59, 64, pause_frames, fire_frames, weapon_grenadelauncher_fire);
665 }
666 
667 /*
668 ======================================================================
669 
670 ROCKET
671 
672 ======================================================================
673 */
674 
675 void Weapon_RocketLauncher_Fire(edict_t *ent)
676 {
677  vec3_t offset, start;
678  vec3_t forward, right;
679  int damage;
680  float damage_radius;
681  int radius_damage;
682 
683  damage = 100 + (int)(random() * 20.0);
684  radius_damage = 120;
685  damage_radius = 120;
686  if (is_quad) {
687  damage *= 4;
688  radius_damage *= 4;
689  }
690 
691  AngleVectors(ent->client->v_angle, forward, right, NULL);
692 
693  VectorScale(forward, -2, ent->client->kick_origin);
694  ent->client->kick_angles[0] = -1;
695 
696  VectorSet(offset, 8, 8, ent->viewheight - 8);
697  P_ProjectSource(ent->client, ent->s.origin, offset, forward, right, start);
698  fire_rocket(ent, start, forward, damage, 650, damage_radius, radius_damage);
699 
700  // send muzzle flash
701  gi.WriteByte(svc_muzzleflash);
702  gi.WriteShort(ent - g_edicts);
703  gi.WriteByte(MZ_ROCKET | is_silenced);
704  gi.multicast(ent->s.origin, MULTICAST_PVS);
705 
706  ent->client->ps.gunframe++;
707 
708  PlayerNoise(ent, start, PNOISE_WEAPON);
709 
710  if (!((int)dmflags->value & DF_INFINITE_AMMO))
711  ent->client->pers.inventory[ent->client->ammo_index]--;
712 }
713 
714 void Weapon_RocketLauncher(edict_t *ent)
715 {
716  static int pause_frames[] = {25, 33, 42, 50, 0};
717  static int fire_frames[] = {5, 0};
718 
719  Weapon_Generic(ent, 4, 12, 50, 54, pause_frames, fire_frames, Weapon_RocketLauncher_Fire);
720 }
721 
722 
723 /*
724 ======================================================================
725 
726 BLASTER / HYPERBLASTER
727 
728 ======================================================================
729 */
730 
731 void Blaster_Fire(edict_t *ent, vec3_t g_offset, int damage, qboolean hyper, int effect)
732 {
733  vec3_t forward, right;
734  vec3_t start;
735  vec3_t offset;
736 
737  if (is_quad)
738  damage *= 4;
739  AngleVectors(ent->client->v_angle, forward, right, NULL);
740  VectorSet(offset, 24, 8, ent->viewheight - 8);
741  VectorAdd(offset, g_offset, offset);
742  P_ProjectSource(ent->client, ent->s.origin, offset, forward, right, start);
743 
744  VectorScale(forward, -2, ent->client->kick_origin);
745  ent->client->kick_angles[0] = -1;
746 
747  fire_blaster(ent, start, forward, damage, 1000, effect, hyper);
748 
749  // send muzzle flash
750  gi.WriteByte(svc_muzzleflash);
751  gi.WriteShort(ent - g_edicts);
752  if (hyper)
753  gi.WriteByte(MZ_HYPERBLASTER | is_silenced);
754  else
755  gi.WriteByte(MZ_BLASTER | is_silenced);
756  gi.multicast(ent->s.origin, MULTICAST_PVS);
757 
758  PlayerNoise(ent, start, PNOISE_WEAPON);
759 }
760 
761 
762 void Weapon_Blaster_Fire(edict_t *ent)
763 {
764  int damage;
765 
766  if (deathmatch->value)
767  damage = 15;
768  else
769  damage = 10;
770  Blaster_Fire(ent, vec3_origin, damage, qfalse, EF_BLASTER);
771  ent->client->ps.gunframe++;
772 }
773 
774 void Weapon_Blaster(edict_t *ent)
775 {
776  static int pause_frames[] = {19, 32, 0};
777  static int fire_frames[] = {5, 0};
778 
779  Weapon_Generic(ent, 4, 8, 52, 55, pause_frames, fire_frames, Weapon_Blaster_Fire);
780 }
781 
782 
783 void Weapon_HyperBlaster_Fire(edict_t *ent)
784 {
785  float rotation;
786  vec3_t offset;
787  int effect;
788  int damage;
789 
790  ent->client->weapon_sound = gi.soundindex("weapons/hyprbl1a.wav");
791 
792  if (!(ent->client->buttons & BUTTON_ATTACK)) {
793  ent->client->ps.gunframe++;
794  } else {
795  if (! ent->client->pers.inventory[ent->client->ammo_index]) {
796  if (level.time >= ent->pain_debounce_time) {
797  gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0);
798  ent->pain_debounce_time = level.time + 1;
799  }
800  NoAmmoWeaponChange(ent);
801  } else {
802  rotation = (ent->client->ps.gunframe - 5) * 2 * M_PI / 6;
803  offset[0] = -4 * sin(rotation);
804  offset[1] = 0;
805  offset[2] = 4 * cos(rotation);
806 
807  if ((ent->client->ps.gunframe == 6) || (ent->client->ps.gunframe == 9))
808  effect = EF_HYPERBLASTER;
809  else
810  effect = 0;
811  if (deathmatch->value)
812  damage = 15;
813  else
814  damage = 20;
815  Blaster_Fire(ent, offset, damage, qtrue, effect);
816  if (!((int)dmflags->value & DF_INFINITE_AMMO))
817  ent->client->pers.inventory[ent->client->ammo_index]--;
818 
819  ent->client->anim_priority = ANIM_ATTACK;
820  if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) {
821  ent->s.frame = FRAME_crattak1 - 1;
822  ent->client->anim_end = FRAME_crattak9;
823  } else {
824  ent->s.frame = FRAME_attack1 - 1;
825  ent->client->anim_end = FRAME_attack8;
826  }
827  }
828 
829  ent->client->ps.gunframe++;
830  if (ent->client->ps.gunframe == 12 && ent->client->pers.inventory[ent->client->ammo_index])
831  ent->client->ps.gunframe = 6;
832  }
833 
834  if (ent->client->ps.gunframe == 12) {
835  gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/hyprbd1a.wav"), 1, ATTN_NORM, 0);
836  ent->client->weapon_sound = 0;
837  }
838 
839 }
840 
841 void Weapon_HyperBlaster(edict_t *ent)
842 {
843  static int pause_frames[] = {0};
844  static int fire_frames[] = {6, 7, 8, 9, 10, 11, 0};
845 
846  Weapon_Generic(ent, 5, 20, 49, 53, pause_frames, fire_frames, Weapon_HyperBlaster_Fire);
847 }
848 
849 /*
850 ======================================================================
851 
852 MACHINEGUN / CHAINGUN
853 
854 ======================================================================
855 */
856 
857 void Machinegun_Fire(edict_t *ent)
858 {
859  int i;
860  vec3_t start;
861  vec3_t forward, right;
862  vec3_t angles;
863  int damage = 8;
864  int kick = 2;
865  vec3_t offset;
866 
867  if (!(ent->client->buttons & BUTTON_ATTACK)) {
868  ent->client->machinegun_shots = 0;
869  ent->client->ps.gunframe++;
870  return;
871  }
872 
873  if (ent->client->ps.gunframe == 5)
874  ent->client->ps.gunframe = 4;
875  else
876  ent->client->ps.gunframe = 5;
877 
878  if (ent->client->pers.inventory[ent->client->ammo_index] < 1) {
879  ent->client->ps.gunframe = 6;
880  if (level.time >= ent->pain_debounce_time) {
881  gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0);
882  ent->pain_debounce_time = level.time + 1;
883  }
884  NoAmmoWeaponChange(ent);
885  return;
886  }
887 
888  if (is_quad) {
889  damage *= 4;
890  kick *= 4;
891  }
892 
893  for (i = 1 ; i < 3 ; i++) {
894  ent->client->kick_origin[i] = crandom() * 0.35;
895  ent->client->kick_angles[i] = crandom() * 0.7;
896  }
897  ent->client->kick_origin[0] = crandom() * 0.35;
898  ent->client->kick_angles[0] = ent->client->machinegun_shots * -1.5;
899 
900  // raise the gun as it is firing
901  if (!deathmatch->value) {
902  ent->client->machinegun_shots++;
903  if (ent->client->machinegun_shots > 9)
904  ent->client->machinegun_shots = 9;
905  }
906 
907  // get start / end positions
908  VectorAdd(ent->client->v_angle, ent->client->kick_angles, angles);
909  AngleVectors(angles, forward, right, NULL);
910  VectorSet(offset, 0, 8, ent->viewheight - 8);
911  P_ProjectSource(ent->client, ent->s.origin, offset, forward, right, start);
913 
914  gi.WriteByte(svc_muzzleflash);
915  gi.WriteShort(ent - g_edicts);
916  gi.WriteByte(MZ_MACHINEGUN | is_silenced);
917  gi.multicast(ent->s.origin, MULTICAST_PVS);
918 
919  PlayerNoise(ent, start, PNOISE_WEAPON);
920 
921  if (!((int)dmflags->value & DF_INFINITE_AMMO))
922  ent->client->pers.inventory[ent->client->ammo_index]--;
923 
924  ent->client->anim_priority = ANIM_ATTACK;
925  if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) {
926  ent->s.frame = FRAME_crattak1 - (int)(random() + 0.25);
927  ent->client->anim_end = FRAME_crattak9;
928  } else {
929  ent->s.frame = FRAME_attack1 - (int)(random() + 0.25);
930  ent->client->anim_end = FRAME_attack8;
931  }
932 }
933 
934 void Weapon_Machinegun(edict_t *ent)
935 {
936  static int pause_frames[] = {23, 45, 0};
937  static int fire_frames[] = {4, 5, 0};
938 
939  Weapon_Generic(ent, 3, 5, 45, 49, pause_frames, fire_frames, Machinegun_Fire);
940 }
941 
942 void Chaingun_Fire(edict_t *ent)
943 {
944  int i;
945  int shots;
946  vec3_t start;
947  vec3_t forward, right, up;
948  float r, u;
949  vec3_t offset;
950  int damage;
951  int kick = 2;
952 
953  if (deathmatch->value)
954  damage = 6;
955  else
956  damage = 8;
957 
958  if (ent->client->ps.gunframe == 5)
959  gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/chngnu1a.wav"), 1, ATTN_IDLE, 0);
960 
961  if ((ent->client->ps.gunframe == 14) && !(ent->client->buttons & BUTTON_ATTACK)) {
962  ent->client->ps.gunframe = 32;
963  ent->client->weapon_sound = 0;
964  return;
965  } else if ((ent->client->ps.gunframe == 21) && (ent->client->buttons & BUTTON_ATTACK)
966  && ent->client->pers.inventory[ent->client->ammo_index]) {
967  ent->client->ps.gunframe = 15;
968  } else {
969  ent->client->ps.gunframe++;
970  }
971 
972  if (ent->client->ps.gunframe == 22) {
973  ent->client->weapon_sound = 0;
974  gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/chngnd1a.wav"), 1, ATTN_IDLE, 0);
975  } else {
976  ent->client->weapon_sound = gi.soundindex("weapons/chngnl1a.wav");
977  }
978 
979  ent->client->anim_priority = ANIM_ATTACK;
980  if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) {
981  ent->s.frame = FRAME_crattak1 - (ent->client->ps.gunframe & 1);
982  ent->client->anim_end = FRAME_crattak9;
983  } else {
984  ent->s.frame = FRAME_attack1 - (ent->client->ps.gunframe & 1);
985  ent->client->anim_end = FRAME_attack8;
986  }
987 
988  if (ent->client->ps.gunframe <= 9)
989  shots = 1;
990  else if (ent->client->ps.gunframe <= 14) {
991  if (ent->client->buttons & BUTTON_ATTACK)
992  shots = 2;
993  else
994  shots = 1;
995  } else
996  shots = 3;
997 
998  if (ent->client->pers.inventory[ent->client->ammo_index] < shots)
999  shots = ent->client->pers.inventory[ent->client->ammo_index];
1000 
1001  if (!shots) {
1002  if (level.time >= ent->pain_debounce_time) {
1003  gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0);
1004  ent->pain_debounce_time = level.time + 1;
1005  }
1006  NoAmmoWeaponChange(ent);
1007  return;
1008  }
1009 
1010  if (is_quad) {
1011  damage *= 4;
1012  kick *= 4;
1013  }
1014 
1015  for (i = 0 ; i < 3 ; i++) {
1016  ent->client->kick_origin[i] = crandom() * 0.35;
1017  ent->client->kick_angles[i] = crandom() * 0.7;
1018  }
1019 
1020  for (i = 0 ; i < shots ; i++) {
1021  // get start / end positions
1022  AngleVectors(ent->client->v_angle, forward, right, up);
1023  r = 7 + crandom() * 4;
1024  u = crandom() * 4;
1025  VectorSet(offset, 0, r, u + ent->viewheight - 8);
1026  P_ProjectSource(ent->client, ent->s.origin, offset, forward, right, start);
1027 
1029  }
1030 
1031  // send muzzle flash
1032  gi.WriteByte(svc_muzzleflash);
1033  gi.WriteShort(ent - g_edicts);
1034  gi.WriteByte((MZ_CHAINGUN1 + shots - 1) | is_silenced);
1035  gi.multicast(ent->s.origin, MULTICAST_PVS);
1036 
1037  PlayerNoise(ent, start, PNOISE_WEAPON);
1038 
1039  if (!((int)dmflags->value & DF_INFINITE_AMMO))
1040  ent->client->pers.inventory[ent->client->ammo_index] -= shots;
1041 }
1042 
1043 
1044 void Weapon_Chaingun(edict_t *ent)
1045 {
1046  static int pause_frames[] = {38, 43, 51, 61, 0};
1047  static int fire_frames[] = {5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 0};
1048 
1049  Weapon_Generic(ent, 4, 31, 61, 64, pause_frames, fire_frames, Chaingun_Fire);
1050 }
1051 
1052 
1053 /*
1054 ======================================================================
1055 
1056 SHOTGUN / SUPERSHOTGUN
1057 
1058 ======================================================================
1059 */
1060 
1061 void weapon_shotgun_fire(edict_t *ent)
1062 {
1063  vec3_t start;
1064  vec3_t forward, right;
1065  vec3_t offset;
1066  int damage = 4;
1067  int kick = 8;
1068 
1069  if (ent->client->ps.gunframe == 9) {
1070  ent->client->ps.gunframe++;
1071  return;
1072  }
1073 
1074  AngleVectors(ent->client->v_angle, forward, right, NULL);
1075 
1076  VectorScale(forward, -2, ent->client->kick_origin);
1077  ent->client->kick_angles[0] = -2;
1078 
1079  VectorSet(offset, 0, 8, ent->viewheight - 8);
1080  P_ProjectSource(ent->client, ent->s.origin, offset, forward, right, start);
1081 
1082  if (is_quad) {
1083  damage *= 4;
1084  kick *= 4;
1085  }
1086 
1087  if (deathmatch->value)
1088  fire_shotgun(ent, start, forward, damage, kick, 500, 500, DEFAULT_DEATHMATCH_SHOTGUN_COUNT, MOD_SHOTGUN);
1089  else
1090  fire_shotgun(ent, start, forward, damage, kick, 500, 500, DEFAULT_SHOTGUN_COUNT, MOD_SHOTGUN);
1091 
1092  // send muzzle flash
1093  gi.WriteByte(svc_muzzleflash);
1094  gi.WriteShort(ent - g_edicts);
1095  gi.WriteByte(MZ_SHOTGUN | is_silenced);
1096  gi.multicast(ent->s.origin, MULTICAST_PVS);
1097 
1098  ent->client->ps.gunframe++;
1099  PlayerNoise(ent, start, PNOISE_WEAPON);
1100 
1101  if (!((int)dmflags->value & DF_INFINITE_AMMO))
1102  ent->client->pers.inventory[ent->client->ammo_index]--;
1103 }
1104 
1105 void Weapon_Shotgun(edict_t *ent)
1106 {
1107  static int pause_frames[] = {22, 28, 34, 0};
1108  static int fire_frames[] = {8, 9, 0};
1109 
1110  Weapon_Generic(ent, 7, 18, 36, 39, pause_frames, fire_frames, weapon_shotgun_fire);
1111 }
1112 
1113 
1114 void weapon_supershotgun_fire(edict_t *ent)
1115 {
1116  vec3_t start;
1117  vec3_t forward, right;
1118  vec3_t offset;
1119  vec3_t v;
1120  int damage = 6;
1121  int kick = 12;
1122 
1123  AngleVectors(ent->client->v_angle, forward, right, NULL);
1124 
1125  VectorScale(forward, -2, ent->client->kick_origin);
1126  ent->client->kick_angles[0] = -2;
1127 
1128  VectorSet(offset, 0, 8, ent->viewheight - 8);
1129  P_ProjectSource(ent->client, ent->s.origin, offset, forward, right, start);
1130 
1131  if (is_quad) {
1132  damage *= 4;
1133  kick *= 4;
1134  }
1135 
1136  v[PITCH] = ent->client->v_angle[PITCH];
1137  v[YAW] = ent->client->v_angle[YAW] - 5;
1138  v[ROLL] = ent->client->v_angle[ROLL];
1139  AngleVectors(v, forward, NULL, NULL);
1141  v[YAW] = ent->client->v_angle[YAW] + 5;
1142  AngleVectors(v, forward, NULL, NULL);
1144 
1145  // send muzzle flash
1146  gi.WriteByte(svc_muzzleflash);
1147  gi.WriteShort(ent - g_edicts);
1148  gi.WriteByte(MZ_SSHOTGUN | is_silenced);
1149  gi.multicast(ent->s.origin, MULTICAST_PVS);
1150 
1151  ent->client->ps.gunframe++;
1152  PlayerNoise(ent, start, PNOISE_WEAPON);
1153 
1154  if (!((int)dmflags->value & DF_INFINITE_AMMO))
1155  ent->client->pers.inventory[ent->client->ammo_index] -= 2;
1156 }
1157 
1158 void Weapon_SuperShotgun(edict_t *ent)
1159 {
1160  static int pause_frames[] = {29, 42, 57, 0};
1161  static int fire_frames[] = {7, 0};
1162 
1163  Weapon_Generic(ent, 6, 17, 57, 61, pause_frames, fire_frames, weapon_supershotgun_fire);
1164 }
1165 
1166 
1167 
1168 /*
1169 ======================================================================
1170 
1171 RAILGUN
1172 
1173 ======================================================================
1174 */
1175 
1176 void weapon_railgun_fire(edict_t *ent)
1177 {
1178  vec3_t start;
1179  vec3_t forward, right;
1180  vec3_t offset;
1181  int damage;
1182  int kick;
1183 
1184  if (deathmatch->value) {
1185  // normal damage is too extreme in dm
1186  damage = 100;
1187  kick = 200;
1188  } else {
1189  damage = 150;
1190  kick = 250;
1191  }
1192 
1193  if (is_quad) {
1194  damage *= 4;
1195  kick *= 4;
1196  }
1197 
1198  AngleVectors(ent->client->v_angle, forward, right, NULL);
1199 
1200  VectorScale(forward, -3, ent->client->kick_origin);
1201  ent->client->kick_angles[0] = -3;
1202 
1203  VectorSet(offset, 0, 7, ent->viewheight - 8);
1204  P_ProjectSource(ent->client, ent->s.origin, offset, forward, right, start);
1205  fire_rail(ent, start, forward, damage, kick);
1206 
1207  // send muzzle flash
1208  gi.WriteByte(svc_muzzleflash);
1209  gi.WriteShort(ent - g_edicts);
1210  gi.WriteByte(MZ_RAILGUN | is_silenced);
1211  gi.multicast(ent->s.origin, MULTICAST_PVS);
1212 
1213  ent->client->ps.gunframe++;
1214  PlayerNoise(ent, start, PNOISE_WEAPON);
1215 
1216  if (!((int)dmflags->value & DF_INFINITE_AMMO))
1217  ent->client->pers.inventory[ent->client->ammo_index]--;
1218 }
1219 
1220 
1221 void Weapon_Railgun(edict_t *ent)
1222 {
1223  static int pause_frames[] = {56, 0};
1224  static int fire_frames[] = {4, 0};
1225 
1226  Weapon_Generic(ent, 3, 18, 56, 61, pause_frames, fire_frames, weapon_railgun_fire);
1227 }
1228 
1229 
1230 /*
1231 ======================================================================
1232 
1233 BFG10K
1234 
1235 ======================================================================
1236 */
1237 
1238 void weapon_bfg_fire(edict_t *ent)
1239 {
1240  vec3_t offset, start;
1241  vec3_t forward, right;
1242  int damage;
1243  float damage_radius = 1000;
1244 
1245  if (deathmatch->value)
1246  damage = 200;
1247  else
1248  damage = 500;
1249 
1250  if (ent->client->ps.gunframe == 9) {
1251  // send muzzle flash
1252  gi.WriteByte(svc_muzzleflash);
1253  gi.WriteShort(ent - g_edicts);
1254  gi.WriteByte(MZ_BFG | is_silenced);
1255  gi.multicast(ent->s.origin, MULTICAST_PVS);
1256 
1257  ent->client->ps.gunframe++;
1258 
1259  PlayerNoise(ent, start, PNOISE_WEAPON);
1260  return;
1261  }
1262 
1263  // cells can go down during windup (from power armor hits), so
1264  // check again and abort firing if we don't have enough now
1265  if (ent->client->pers.inventory[ent->client->ammo_index] < 50) {
1266  ent->client->ps.gunframe++;
1267  return;
1268  }
1269 
1270  if (is_quad)
1271  damage *= 4;
1272 
1273  AngleVectors(ent->client->v_angle, forward, right, NULL);
1274 
1275  VectorScale(forward, -2, ent->client->kick_origin);
1276 
1277  // make a big pitch kick with an inverse fall
1278  ent->client->v_dmg_pitch = -40;
1279  ent->client->v_dmg_roll = crandom() * 8;
1280  ent->client->v_dmg_time = level.time + DAMAGE_TIME;
1281 
1282  VectorSet(offset, 8, 8, ent->viewheight - 8);
1283  P_ProjectSource(ent->client, ent->s.origin, offset, forward, right, start);
1284  fire_bfg(ent, start, forward, damage, 400, damage_radius);
1285 
1286  ent->client->ps.gunframe++;
1287 
1288  PlayerNoise(ent, start, PNOISE_WEAPON);
1289 
1290  if (!((int)dmflags->value & DF_INFINITE_AMMO))
1291  ent->client->pers.inventory[ent->client->ammo_index] -= 50;
1292 }
1293 
1294 void Weapon_BFG(edict_t *ent)
1295 {
1296  static int pause_frames[] = {39, 45, 50, 55, 0};
1297  static int fire_frames[] = {9, 17, 0};
1298 
1299  Weapon_Generic(ent, 8, 32, 55, 58, pause_frames, fire_frames, weapon_bfg_fire);
1300 }
1301 
1302 
1303 //======================================================================
1304 
1305 /*
1306  * Forward declaration for fire_flaregun(), which is defined in
1307  * g_weapon.c.
1308  */
1309 void fire_flaregun(edict_t *self, vec3_t start, vec3_t aimdir, int damage,
1310  int speed, float timer, float damage_radius);
1311 /*
1312  * weapon_flaregun_fire (edict_t *ent)
1313  *
1314  * Basically used to wrap the call to fire_flaregun(), this function
1315  * calculates all the parameters needed by fire_flaregun. Calls
1316  * fire_flaregun and then subtracts 1 from the firing entity's
1317  * cell stash.
1318  */
1319 void weapon_flaregun_fire(edict_t *ent)
1320 {
1321  vec3_t offset;
1322  vec3_t forward, right;
1323  vec3_t start;
1324 
1325  // Setup the parameters used in the call to fire_flaregun()
1326  //
1327  VectorSet(offset, 8, 8, ent->viewheight - 8);
1328  AngleVectors(ent->client->v_angle, forward, right, NULL);
1329  P_ProjectSource(ent->client, ent->s.origin, offset, forward, right, start);
1330 
1331  VectorScale(forward, -2, ent->client->kick_origin);
1332  ent->client->kick_angles[0] = -1;
1333 
1334  // Make the flaregun actually shoot the flare
1335  //
1336  fire_flaregun(ent, start, forward, 0, 800, 25, 0);
1337 
1338  gi.WriteByte(svc_muzzleflash);
1339  gi.WriteShort(ent - g_edicts);
1340  gi.WriteByte(MZ_FLARE | is_silenced);
1341  gi.multicast(ent->s.origin, MULTICAST_PVS);
1342 
1343  // Bump the gunframe
1344  //
1345  ent->client->ps.gunframe++;
1346 
1347  PlayerNoise(ent, start, PNOISE_WEAPON);
1348 
1349  // Subtract one cell from our inventory
1350  //
1351  ent->client->pers.inventory[ent->client->ammo_index]--;
1352 }
1353 
1354 /*
1355  * Weapon_FlareGun (edict_t *ent)
1356  *
1357  * This is the function that is referenced in the itemlist structure
1358  * defined in g_items.c. It is called every frame when our weapon is
1359  * active. It calls Weapon_Generic() to handle per-frame weapon
1360  * handling (like animation and stuff). Haven't delved too deeply
1361  * into Weapon_Generic()'s responsiblities... if someone has insight
1362  * drop me a line :)
1363  */
1364 void Weapon_FlareGun(edict_t *ent)
1365 {
1366  static int pause_frames[] = { 39, 45, 50, 53, 0 };
1367  static int fire_frames[] = { 9, 17, 0 };
1368  // Check the top of p_weapon.c for definition of Weapon_Generic
1369  //
1370  Weapon_Generic(ent, 8, 13, 49, 53,
1371  pause_frames,
1372  fire_frames,
1374 }
FindItem
gitem_t * FindItem(char *pickup_name)
Definition: g_items.c:98
gi
game_import_t gi
Definition: g_main.c:23
IT_AMMO
#define IT_AMMO
Definition: g_local.h:212
deathmatch
cvar_t * deathmatch
Definition: g_main.c:33
G_ProjectSource
void G_ProjectSource(const vec3_t point, const vec3_t distance, const vec3_t forward, const vec3_t right, vec3_t result)
Definition: g_utils.c:23
FRAME_pain301
#define FRAME_pain301
Definition: m_actor.h:102
G_Spawn
edict_t * G_Spawn(void)
Definition: g_utils.c:391
DEFAULT_BULLET_HSPREAD
#define DEFAULT_BULLET_HSPREAD
Definition: g_local.h:654
P_ProjectSource
static void P_ProjectSource(gclient_t *client, vec3_t point, vec3_t distance, vec3_t forward, vec3_t right, vec3_t result)
Definition: p_weapon.c:31
FRAME_crpain1
#define FRAME_crpain1
Definition: m_player.h:191
FRAME_attack1
#define FRAME_attack1
Definition: m_boss2.h:92
WEAPON_DROPPING
@ WEAPON_DROPPING
Definition: g_local.h:95
m_player.h
Think_Weapon
void Think_Weapon(edict_t *ent)
Definition: p_weapon.c:260
fire_flaregun
void fire_flaregun(edict_t *self, vec3_t start, vec3_t aimdir, int damage, int speed, float timer, float damage_radius)
Definition: g_weapon.c:956
FRAME_crattak3
#define FRAME_crattak3
Definition: m_player.h:184
weapon_supershotgun_fire
void weapon_supershotgun_fire(edict_t *ent)
Definition: p_weapon.c:1114
PNOISE_WEAPON
#define PNOISE_WEAPON
Definition: g_local.h:180
FRAME_crattak1
#define FRAME_crattak1
Definition: m_player.h:182
MOD_CHAINGUN
#define MOD_CHAINGUN
Definition: g_local.h:462
WEAPON_READY
@ WEAPON_READY
Definition: g_local.h:93
Add_Ammo
qboolean Add_Ammo(edict_t *ent, gitem_t *item, int count)
Definition: g_items.c:426
weapon_flaregun_fire
void weapon_flaregun_fire(edict_t *ent)
Definition: p_weapon.c:1319
fire_rail
void fire_rail(edict_t *self, vec3_t start, vec3_t aimdir, int damage, int kick)
Definition: g_weapon.c:615
Weapon_HyperBlaster
void Weapon_HyperBlaster(edict_t *ent)
Definition: p_weapon.c:841
Drop_Weapon
void Drop_Weapon(edict_t *ent, gitem_t *item)
Definition: p_weapon.c:322
FRAME_wave01
#define FRAME_wave01
Definition: m_actor.h:284
fire_rocket
void fire_rocket(edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, float damage_radius, int radius_damage)
Definition: g_weapon.c:577
FRAME_pain304
#define FRAME_pain304
Definition: m_boss31.h:112
Blaster_Fire
void Blaster_Fire(edict_t *ent, vec3_t g_offset, int damage, qboolean hyper, int effect)
Definition: p_weapon.c:731
ITEM_INDEX
#define ITEM_INDEX(x)
Definition: g_local.h:600
weapon_grenade_fire
void weapon_grenade_fire(edict_t *ent, qboolean held)
Definition: p_weapon.c:485
NoAmmoWeaponChange
void NoAmmoWeaponChange(edict_t *ent)
Definition: p_weapon.c:218
fire_bfg
void fire_bfg(edict_t *self, vec3_t start, vec3_t dir, int damage, int speed, float damage_radius)
Definition: g_weapon.c:830
GRENADE_MINSPEED
#define GRENADE_MINSPEED
Definition: p_weapon.c:482
Pickup_Weapon
qboolean Pickup_Weapon(edict_t *ent, edict_t *other)
Definition: p_weapon.c:110
Weapon_Chaingun
void Weapon_Chaingun(edict_t *ent)
Definition: p_weapon.c:1044
DEFAULT_SHOTGUN_COUNT
#define DEFAULT_SHOTGUN_COUNT
Definition: g_local.h:659
FRAME_FIRE_FIRST
#define FRAME_FIRE_FIRST
Definition: p_weapon.c:348
fire_grenade
void fire_grenade(edict_t *self, vec3_t start, vec3_t aimdir, int damage, int speed, float timer, float damage_radius)
Definition: g_weapon.c:450
GRENADE_TIMER
#define GRENADE_TIMER
Definition: p_weapon.c:481
WEAPON_ACTIVATING
@ WEAPON_ACTIVATING
Definition: g_local.h:94
Weapon_HyperBlaster_Fire
void Weapon_HyperBlaster_Fire(edict_t *ent)
Definition: p_weapon.c:783
fire_grenade2
void fire_grenade2(edict_t *self, vec3_t start, vec3_t aimdir, int damage, int speed, float timer, float damage_radius, qboolean held)
Definition: g_weapon.c:483
g_edicts
edict_t * g_edicts
Definition: g_main.c:31
other
@ other
Definition: ogg.c:63
FRAME_IDLE_FIRST
#define FRAME_IDLE_FIRST
Definition: p_weapon.c:349
weapon_railgun_fire
void weapon_railgun_fire(edict_t *ent)
Definition: p_weapon.c:1176
svc_muzzleflash
#define svc_muzzleflash
Definition: g_local.h:36
ANIM_PAIN
#define ANIM_PAIN
Definition: g_local.h:814
ANIM_REVERSE
#define ANIM_REVERSE
Definition: g_local.h:817
Weapon_FlareGun
void Weapon_FlareGun(edict_t *ent)
Definition: p_weapon.c:1364
vec3_origin
vec3_t vec3_origin
Definition: shared.c:21
DEFAULT_BULLET_VSPREAD
#define DEFAULT_BULLET_VSPREAD
Definition: g_local.h:655
DAMAGE_TIME
#define DAMAGE_TIME
Definition: g_local.h:46
Chaingun_Fire
void Chaingun_Fire(edict_t *ent)
Definition: p_weapon.c:942
FL_RESPAWN
#define FL_RESPAWN
Definition: g_local.h:72
gitem_s::ammo
char * ammo
Definition: g_local.h:249
DROPPED_PLAYER_ITEM
#define DROPPED_PLAYER_ITEM
Definition: g_local.h:558
forward
static vec3_t forward
Definition: p_view.c:27
PlayerNoise
void PlayerNoise(edict_t *who, vec3_t where, int type)
Definition: p_weapon.c:56
crandom
#define crandom()
Definition: g_local.h:505
MOD_MACHINEGUN
#define MOD_MACHINEGUN
Definition: g_local.h:461
random
#define random()
Definition: g_local.h:504
WEAPON_FIRING
@ WEAPON_FIRING
Definition: g_local.h:96
Weapon_Grenade
void Weapon_Grenade(edict_t *ent)
Definition: p_weapon.c:530
AngleVectors
void AngleVectors(vec3_t angles, vec3_t forward, vec3_t right, vec3_t up)
Definition: shared.c:23
FL_NOTARGET
#define FL_NOTARGET
Definition: g_local.h:64
gitem_s::pickup_name
char * pickup_name
Definition: g_local.h:245
weapon_shotgun_fire
void weapon_shotgun_fire(edict_t *ent)
Definition: p_weapon.c:1061
level_locals_t::sound2_entity
edict_t * sound2_entity
Definition: g_local.h:318
SetRespawn
void SetRespawn(edict_t *ent, float delay)
Definition: g_items.c:142
is_silenced
static byte is_silenced
Definition: p_weapon.c:25
MOD_SHOTGUN
#define MOD_SHOTGUN
Definition: g_local.h:459
FRAME_wave08
#define FRAME_wave08
Definition: m_actor.h:291
FRAME_DEACTIVATE_FIRST
#define FRAME_DEACTIVATE_FIRST
Definition: p_weapon.c:350
FRAME_attack8
#define FRAME_attack8
Definition: m_boss2.h:99
Weapon_Machinegun
void Weapon_Machinegun(edict_t *ent)
Definition: p_weapon.c:934
GRENADE_MAXSPEED
#define GRENADE_MAXSPEED
Definition: p_weapon.c:483
gitem_s::quantity
int quantity
Definition: g_local.h:248
level_locals_t::framenum
int framenum
Definition: g_local.h:298
Weapon_RocketLauncher_Fire
void Weapon_RocketLauncher_Fire(edict_t *ent)
Definition: p_weapon.c:675
level_locals_t::time
float time
Definition: g_local.h:299
fire_bullet
void fire_bullet(edict_t *self, vec3_t start, vec3_t aimdir, int damage, int kick, int hspread, int vspread, int mod)
Definition: g_weapon.c:255
DROPPED_ITEM
#define DROPPED_ITEM
Definition: g_local.h:557
coop
cvar_t * coop
Definition: g_main.c:34
LEFT_HANDED
#define LEFT_HANDED
Definition: g_local.h:162
ANIM_ATTACK
#define ANIM_ATTACK
Definition: g_local.h:815
FRAME_crattak9
#define FRAME_crattak9
Definition: m_player.h:190
DEFAULT_DEATHMATCH_SHOTGUN_COUNT
#define DEFAULT_DEATHMATCH_SHOTGUN_COUNT
Definition: g_local.h:658
g_select_empty
cvar_t * g_select_empty
Definition: g_main.c:45
level_locals_t::sound_entity
edict_t * sound_entity
Definition: g_local.h:316
level_locals_t::sound_entity_framenum
int sound_entity_framenum
Definition: g_local.h:317
up
static vec3_t up
Definition: p_view.c:27
PNOISE_SELF
#define PNOISE_SELF
Definition: g_local.h:179
Use_Weapon
void Use_Weapon(edict_t *ent, gitem_t *item)
Definition: p_weapon.c:287
DEFAULT_SHOTGUN_HSPREAD
#define DEFAULT_SHOTGUN_HSPREAD
Definition: g_local.h:656
right
static vec3_t right
Definition: p_view.c:27
ChangeWeapon
void ChangeWeapon(edict_t *ent)
Definition: p_weapon.c:162
CENTER_HANDED
#define CENTER_HANDED
Definition: g_local.h:163
Drop_Item
edict_t * Drop_Item(edict_t *ent, gitem_t *item)
Definition: g_items.c:798
Weapon_RocketLauncher
void Weapon_RocketLauncher(edict_t *ent)
Definition: p_weapon.c:714
weapon_grenadelauncher_fire
void weapon_grenadelauncher_fire(edict_t *ent)
Definition: p_weapon.c:625
Weapon_Blaster_Fire
void Weapon_Blaster_Fire(edict_t *ent)
Definition: p_weapon.c:762
level
level_locals_t level
Definition: g_main.c:22
FRAME_crpain4
#define FRAME_crpain4
Definition: m_player.h:194
DEFAULT_SHOTGUN_VSPREAD
#define DEFAULT_SHOTGUN_VSPREAD
Definition: g_local.h:657
is_quad
static qboolean is_quad
Definition: p_weapon.c:24
Weapon_SuperShotgun
void Weapon_SuperShotgun(edict_t *ent)
Definition: p_weapon.c:1158
fire_blaster
void fire_blaster(edict_t *self, vec3_t start, vec3_t aimdir, int damage, int speed, int effect, qboolean hyper)
Definition: g_weapon.c:319
Weapon_Generic
void Weapon_Generic(edict_t *ent, int FRAME_ACTIVATE_LAST, int FRAME_FIRE_LAST, int FRAME_IDLE_LAST, int FRAME_DEACTIVATE_LAST, int *pause_frames, int *fire_frames, void(*fire)(edict_t *ent))
Definition: p_weapon.c:352
dmflags
cvar_t * dmflags
Definition: g_main.c:35
int
CONST PIXELFORMATDESCRIPTOR int
Definition: wgl.c:26
weapon_bfg_fire
void weapon_bfg_fire(edict_t *ent)
Definition: p_weapon.c:1238
fire_shotgun
void fire_shotgun(edict_t *self, vec3_t start, vec3_t aimdir, int damage, int kick, int hspread, int vspread, int count, int mod)
Definition: g_weapon.c:268
Weapon_Shotgun
void Weapon_Shotgun(edict_t *ent)
Definition: p_weapon.c:1105
Weapon_BFG
void Weapon_BFG(edict_t *ent)
Definition: p_weapon.c:1294
Weapon_Blaster
void Weapon_Blaster(edict_t *ent)
Definition: p_weapon.c:774
level_locals_t::sound2_entity_framenum
int sound2_entity_framenum
Definition: g_local.h:319
DEFAULT_SSHOTGUN_COUNT
#define DEFAULT_SSHOTGUN_COUNT
Definition: g_local.h:660
Weapon_Railgun
void Weapon_Railgun(edict_t *ent)
Definition: p_weapon.c:1221
gitem_s::flags
int flags
Definition: g_local.h:250
Machinegun_Fire
void Machinegun_Fire(edict_t *ent)
Definition: p_weapon.c:857
Weapon_GrenadeLauncher
void Weapon_GrenadeLauncher(edict_t *ent)
Definition: p_weapon.c:659
MOD_SSHOTGUN
#define MOD_SSHOTGUN
Definition: g_local.h:460
g_local.h
gitem_s
Definition: g_local.h:232