1 // g_weapon.c
2
3 #include "g_local.h"
4 #include "m_player.h"
5
6
7 static qboolean is_quad;
8 static byte is_silenced;
9
10
11 void weapon_grenade_firex (edict_t *ent, qboolean held);
12
13
P_ProjectSource(gclient_t * client,vec3_t point,vec3_t distance,vec3_t forward,vec3_t right,vec3_t result)14 static void P_ProjectSource (gclient_t *client, vec3_t point, vec3_t distance, vec3_t forward, vec3_t right, vec3_t result)
15 {
16 vec3_t _distance;
17
18 VectorCopy (distance, _distance);
19 if (client->pers.hand == LEFT_HANDED)
20 _distance[1] *= -1;
21 else if (client->pers.hand == CENTER_HANDED)
22 _distance[1] = 0;
23 G_ProjectSource (point, _distance, forward, right, result);
24 }
25
26
27 /*
28 ===============
29 PlayerNoise
30
31 Each player can have two noise objects associated with it:
32 a personal noise (jumping, pain, weapon firing), and a weapon
33 target noise (bullet wall impacts)
34
35 Monsters that don't directly see the player can move
36 to a noise in hopes of seeing the player from there.
37 ===============
38 */
PlayerNoise(edict_t * who,vec3_t where,int type)39 void PlayerNoise(edict_t *who, vec3_t where, int type)
40 {
41 edict_t *noise;
42
43 if (type == PNOISE_WEAPON)
44 {
45 if (who->client->silencer_shots)
46 {
47 who->client->silencer_shots--;
48 return;
49 }
50 }
51
52 if (deathmatch->value)
53 return;
54
55 if (who->flags & FL_NOTARGET)
56 return;
57
58
59 if (!who->mynoise)
60 {
61 noise = G_Spawn();
62 noise->classname = "player_noise";
63 VectorSet (noise->mins, -8, -8, -8);
64 VectorSet (noise->maxs, 8, 8, 8);
65 noise->owner = who;
66 noise->svflags = SVF_NOCLIENT;
67 who->mynoise = noise;
68
69 noise = G_Spawn();
70 noise->classname = "player_noise";
71 VectorSet (noise->mins, -8, -8, -8);
72 VectorSet (noise->maxs, 8, 8, 8);
73 noise->owner = who;
74 noise->svflags = SVF_NOCLIENT;
75 who->mynoise2 = noise;
76 }
77
78 if (type == PNOISE_SELF || type == PNOISE_WEAPON)
79 {
80 noise = who->mynoise;
81 level.sound_entity = noise;
82 level.sound_entity_framenum = level.framenum;
83 }
84 else // type == PNOISE_IMPACT
85 {
86 noise = who->mynoise2;
87 level.sound2_entity = noise;
88 level.sound2_entity_framenum = level.framenum;
89 }
90
91 VectorCopy (where, noise->s.origin);
92 VectorSubtract (where, noise->maxs, noise->absmin);
93 VectorAdd (where, noise->maxs, noise->absmax);
94 noise->teleport_time = level.time;
95 gi.linkentity (noise);
96 }
97
98
Pickup_Weapon(edict_t * ent,edict_t * other)99 qboolean Pickup_Weapon (edict_t *ent, edict_t *other)
100 {
101 int index;
102 gitem_t *ammo;
103
104 index = ITEM_INDEX(ent->item);
105
106 if ( ( ((int)(dmflags->value) & DF_WEAPONS_STAY) || coop->value)
107 && other->client->pers.inventory[index])
108 {
109 if (!(ent->spawnflags & (DROPPED_ITEM | DROPPED_PLAYER_ITEM) ) )
110 return false; // leave the weapon for others to pickup
111 }
112
113 other->client->pers.inventory[index]+=2;
114
115 if (!(ent->spawnflags & DROPPED_ITEM) )
116 {
117 // give them some ammo with it
118 ammo = FindItem (ent->item->ammo);
119 if ( (int)dmflags->value & DF_INFINITE_AMMO )
120 Add_Ammo (other, ammo, 1000);
121 else
122 Add_Ammo (other, ammo, ammo->quantity);
123
124 if (! (ent->spawnflags & DROPPED_PLAYER_ITEM) )
125 {
126 if (deathmatch->value)
127 {
128 if ((int)(dmflags->value) & DF_WEAPONS_STAY)
129 ent->flags |= FL_RESPAWN;
130 else
131 SetRespawn (ent, (int)weaponrespawntime->value);
132 //SetRespawn (ent, 30);
133 }
134 if (coop->value)
135 ent->flags |= FL_RESPAWN;
136 }
137 }
138
139 if (other->client->pers.weapon != ent->item &&
140 (other->client->pers.inventory[index] == 1) &&
141 ( !deathmatch->value || other->client->pers.weapon == FindItem("blaster") ) )
142 other->client->newweapon = ent->item;
143
144 return true;
145 }
146
147
148 /*
149 ===============
150 ChangeWeapon
151
152 The old weapon has been dropped all the way, so make the new one
153 current
154 ===============
155 */
ChangeWeapon(edict_t * ent)156 void ChangeWeapon (edict_t *ent)
157 {
158 int i;
159
160 if (ent->client->grenade_time)
161 {
162 ent->client->grenade_time = level.time;
163 ent->client->weapon_sound = 0;
164 // weapon_grenade_firex (ent, false);
165 ent->client->grenade_time = 0;
166 }
167 ent->client->ps.fov = 90;
168 ent->client->pers.lastweapon = ent->client->pers.weapon;
169 ent->client->pers.weapon = ent->client->newweapon;
170 ent->client->newweapon = NULL;
171 ent->client->machinegun_shots = 0;
172
173 // set visible model
174 if (ent->s.modelindex == 255) {
175 if (ent->client->pers.weapon)
176 i = ((ent->client->pers.weapon->weapmodel & 0xff) << 8);
177 else
178 i = 0;
179 ent->s.skinnum = (ent - g_edicts - 1) | i;
180 }
181
182 if (ent->client->pers.weapon && ent->client->pers.weapon->ammo)
183 ent->client->ammo_index = ITEM_INDEX(FindItem(ent->client->pers.weapon->ammo));
184 else
185 ent->client->ammo_index = 0;
186
187 if (!ent->client->pers.weapon)
188 { // dead
189 ent->client->ps.gunindex = 0;
190 return;
191 }
192
193 ent->client->weaponstate = WEAPON_ACTIVATING;
194 ent->client->ps.gunframe = 0;
195
196 if(ent->client->akimbo)
197 ent->client->ps.gunindex = gi.modelindex(ent->client->pers.weapon->akimbo_model);
198 else
199 ent->client->ps.gunindex = gi.modelindex(ent->client->pers.weapon->view_model);
200 //SKULL
201 /* Don't display weapon if chasetoggle is on */
202 if (ent->client->chasetoggle)
203 ent->client->ps.gunindex = 0;
204 //END
205
206 ent->client->anim_priority = ANIM_PAIN;
207 if(ent->client->ps.pmove.pm_flags & PMF_DUCKED)
208 {
209 ent->s.frame = FRAME_crpain1;
210 ent->client->anim_end = FRAME_crpain4;
211 }
212 else
213 {
214 ent->s.frame = FRAME_pain301;
215 ent->client->anim_end = FRAME_pain304;
216
217 }
218 }
219
220 /*
221 =================
222 NoAmmoWeaponChange
223 =================
224 */
NoAmmoWeaponChange(edict_t * ent)225 void NoAmmoWeaponChange (edict_t *ent)
226 {
227 if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("bullets"))]
228 && ent->client->pers.inventory[ITEM_INDEX(FindItem("surface to surface missile rack"))] >0
229 && ent->client->pers.inventory[ent->client->ammo_index] >= ammo_rack->value)
230 {
231 ent->client->newweapon = FindItem ("surface to surface missile rack");
232 ent->client->akimbo = false;
233 return;
234 }
235 if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("bullets"))]
236 && ent->client->pers.inventory[ITEM_INDEX(FindItem("m4 assault rifle"))] >0
237 && ent->client->pers.inventory[ent->client->ammo_index] >= ammo_m4->value)
238 {
239 ent->client->newweapon = FindItem ("m4 assault rifle");
240 ent->client->akimbo = true;
241 return;
242 }
243 if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("bullets"))]
244 && ent->client->pers.inventory[ITEM_INDEX(FindItem("grenades"))] >0
245 && ent->client->pers.inventory[ent->client->ammo_index] >= ammo_grenade->value)
246 {
247 ent->client->newweapon = FindItem ("grenades");
248 ent->client->akimbo = false;
249 return;
250 }
251 if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("bullets"))]
252 && ent->client->pers.inventory[ITEM_INDEX(FindItem("pump action shotgun"))] >0
253 && ent->client->pers.inventory[ent->client->ammo_index] >= ammo_pumps->value)
254 {
255 ent->client->newweapon = FindItem ("pump action shotgun");
256 ent->client->akimbo = true;
257 return;
258 }
259 if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("bullets"))]
260 && ent->client->pers.inventory[ITEM_INDEX(FindItem("desert eagle pistol"))] >0
261 && ent->client->pers.inventory[ent->client->ammo_index] >= ammo_deserts->value)
262 {
263 ent->client->newweapon = FindItem ("desert eagle pistol");
264 ent->client->akimbo = true;
265 return;
266 }
267 if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("bullets"))]
268 && ent->client->pers.inventory[ITEM_INDEX(FindItem("mk 23 pistol"))] >0
269 && ent->client->pers.inventory[ent->client->ammo_index] >= ammo_mk23->value)
270 {
271 ent->client->newweapon = FindItem ("mk 23 pistol");
272 ent->client->akimbo = true;
273 return;
274 }
275 if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("bullets"))]
276 && ent->client->pers.inventory[ITEM_INDEX(FindItem("mp5 machine gun"))] >0
277 && ent->client->pers.inventory[ent->client->ammo_index] >= ammo_mp5->value)
278 {
279 ent->client->newweapon = FindItem ("mp5 machine gun");
280 ent->client->akimbo = true;
281 return;
282 }
283 ent->client->newweapon = FindItem ("Fists of Fury");
284 //ent->client->pers.weapon->view_model = ent->client->newweapon->view_model;
285 ent->client->akimbo =false;
286
287
288 }
289
290 /*
291 =================
292 Think_Weapon
293
294 Called by ClientBeginServerFrame and ClientThink
295 =================
296 */
Think_Weapon(edict_t * ent)297 void Think_Weapon (edict_t *ent)
298 {
299 // if just died, put the weapon away
300 if (ent->health < 1)
301 {
302 ent->client->newweapon = NULL;
303 ChangeWeapon (ent);
304 }
305
306 // call active weapon think routine
307 if (ent->client->pers.weapon && ent->client->pers.weapon->weaponthink)
308 {
309 is_quad = (ent->client->quad_framenum > level.framenum);
310 if (ent->client->silencer_shots)
311 is_silenced = MZ_SILENCED;
312 else
313 is_silenced = 0;
314 ent->client->pers.weapon->weaponthink (ent);
315 }
316 }
317
318
319 /*
320 ================
321 Use_Weapon
322
323 Make the weapon ready if there is ammo
324 ================
325 */
Use_Weapon(edict_t * ent,gitem_t * item)326 void Use_Weapon (edict_t *ent, gitem_t *item)
327 {
328 int ammo_index;
329 gitem_t *ammo_item;
330
331 // see if we're already using it
332 if (item == ent->client->pers.weapon)
333 return;
334
335 if (item->ammo && !g_select_empty->value && !(item->flags & IT_AMMO))
336 {
337 ammo_item = FindItem(item->ammo);
338 ammo_index = ITEM_INDEX(ammo_item);
339
340 if (!ent->client->pers.inventory[ammo_index])
341 {
342 gi.cprintf (ent, PRINT_HIGH, "No %s for %s.\n", ammo_item->pickup_name, item->pickup_name);
343 return;
344 }
345
346 if (ent->client->pers.inventory[ammo_index] < item->quantity)
347 {
348 gi.cprintf (ent, PRINT_HIGH, "Not enough %s for %s.\n", ammo_item->pickup_name, item->pickup_name);
349 return;
350 }
351 }
352
353 // change to this weapon when down
354 ent->client->newweapon = item;
355 }
356
357
358
359 /*
360 ================
361 Drop_Weapon
362 ================
363 */
Drop_Weapon(edict_t * ent,gitem_t * item)364 void Drop_Weapon (edict_t *ent, gitem_t *item)
365 {
366 int index;
367
368 if ((int)(dmflags->value) & DF_WEAPONS_STAY)
369 return;
370
371 index = ITEM_INDEX(item);
372 // see if we're already using it
373 if ( ((item == ent->client->pers.weapon) || (item == ent->client->newweapon))&& (ent->client->pers.inventory[index] == 1) )
374 {
375 gi.cprintf (ent, PRINT_HIGH, "Can't drop current weapon\n");
376 return;
377 }
378
379 Drop_Item (ent, item);
380 ent->client->pers.inventory[index]--;
381 }
382
383
384 /*
385 ================
386 Weapon_Generic
387
388 A generic function to handle the basics of weapon thinking
389 ================
390 */
391 #define FRAME_FIRE_FIRST (FRAME_ACTIVATE_LAST + 1)
392 #define FRAME_IDLE_FIRST (FRAME_FIRE_LAST + 1)
393 #define FRAME_DEACTIVATE_FIRST (FRAME_IDLE_LAST + 1)
394
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),int ammouse)395 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), int ammouse)
396 {
397 int n;
398 int FRAME_FIRE_SECONDARY_FIRST;
399 int FRAME_FIRE_SECONDARY_LAST;
400 qboolean secondary_fire_weapon = false;
401
402 if(strcmp(ent->client->pers.weapon->classname, "weapon_knives") == 0)
403 {
404 FRAME_FIRE_SECONDARY_FIRST = 103;
405 FRAME_FIRE_SECONDARY_LAST = 106;
406 secondary_fire_weapon = true;
407 }
408
409 if ((ent->client->ps.gunindex == gi.modelindex(ent->client->pers.weapon->akimbo_model)))
410 ent->client->ps.gunindex = gi.modelindex(ent->client->pers.weapon->view_model);
411
412 if(ent->deadflag || ent->s.modelindex != 255) // VWep animations screw up corpses
413 {
414 return;
415 }
416
417 if (ent->client->weaponstate == WEAPON_DROPPING)
418 {
419 if (ent->client->ps.gunframe == FRAME_DEACTIVATE_LAST)
420 {
421 ChangeWeapon (ent);
422 return;
423 }
424 else if ((FRAME_DEACTIVATE_LAST - ent->client->ps.gunframe) == 4)
425 {
426 ent->client->anim_priority = ANIM_REVERSE;
427 if(ent->client->ps.pmove.pm_flags & PMF_DUCKED)
428 {
429 ent->s.frame = FRAME_crpain4+1;
430 ent->client->anim_end = FRAME_crpain1;
431 }
432 else
433 {
434 ent->s.frame = FRAME_pain304+1;
435 ent->client->anim_end = FRAME_pain301;
436
437 }
438 }
439
440 ent->client->ps.gunframe++;
441 return;
442 }
443
444 if (ent->client->weaponstate == WEAPON_ACTIVATING)
445 {
446 if (ent->client->ps.gunframe == FRAME_ACTIVATE_LAST)
447 {
448 ent->client->weaponstate = WEAPON_READY;
449 ent->client->ps.gunframe = FRAME_IDLE_FIRST;
450 return;
451 }
452
453 ent->client->ps.gunframe++;
454 return;
455 }
456
457 if ((ent->client->newweapon) && (ent->client->weaponstate != WEAPON_FIRING))
458 {
459 ent->client->weaponstate = WEAPON_DROPPING;
460 ent->client->ps.gunframe = FRAME_DEACTIVATE_FIRST;
461
462 if ((FRAME_DEACTIVATE_LAST - FRAME_DEACTIVATE_FIRST) < 4)
463 {
464 ent->client->anim_priority = ANIM_REVERSE;
465 if(ent->client->ps.pmove.pm_flags & PMF_DUCKED)
466 {
467 ent->s.frame = FRAME_crpain4+1;
468 ent->client->anim_end = FRAME_crpain1;
469 }
470 else
471 {
472 ent->s.frame = FRAME_pain304+1;
473 ent->client->anim_end = FRAME_pain301;
474
475 }
476 }
477 return;
478 }
479
480 if (ent->client->weaponstate == WEAPON_READY)
481 {
482 if ( ((ent->client->latched_buttons|ent->client->buttons) & BUTTON_ATTACK) || ent->secondaryfire )
483 {
484 ent->client->latched_buttons &= ~BUTTON_ATTACK;
485 if ((!ent->client->ammo_index) ||
486 ( ent->client->pers.inventory[ent->client->ammo_index] >= ammouse))
487 {
488 if (ent->secondaryfire && secondary_fire_weapon)
489 ent->client->ps.gunframe = FRAME_FIRE_SECONDARY_FIRST;
490 else
491 ent->client->ps.gunframe = FRAME_FIRE_FIRST;
492
493 ent->client->weaponstate = WEAPON_FIRING;
494
495 // start the animation
496 ent->client->anim_priority = ANIM_ATTACK;
497 if (ent->client->ps.pmove.pm_flags & PMF_DUCKED)
498 {
499 ent->s.frame = FRAME_crattak1-1;
500 ent->client->anim_end = FRAME_crattak9;
501 }
502 else
503 {
504 ent->s.frame = FRAME_attack1-1;
505 ent->client->anim_end = FRAME_attack8;
506 }
507 }
508 else
509 {
510 if (level.time >= ent->pain_debounce_time)
511 {
512 gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0);
513 ent->pain_debounce_time = level.time + 1;
514 }
515 NoAmmoWeaponChange (ent);
516 }
517 }
518 else
519 {
520 if (ent->client->ps.gunframe == FRAME_IDLE_LAST)
521 {
522 ent->client->ps.gunframe = FRAME_IDLE_FIRST;
523 return;
524 }
525
526 if (pause_frames)
527 {
528 for (n = 0; pause_frames[n]; n++)
529 {
530 if (ent->client->ps.gunframe == pause_frames[n])
531 {
532 if (rand()&15)
533 return;
534 }
535 }
536 }
537
538 ent->client->ps.gunframe++;
539 return;
540 }
541 }
542
543 if (ent->client->weaponstate == WEAPON_FIRING)
544 {
545 for (n = 0; fire_frames[n]; n++)
546 {
547 if (ent->client->ps.gunframe == fire_frames[n])
548 {
549 if (ent->client->quad_framenum > level.framenum)
550 gi.sound(ent, CHAN_ITEM, gi.soundindex("items/damage3.wav"), 1, ATTN_NORM, 0);
551
552 fire (ent);
553 break;
554 }
555 }
556
557 if (!fire_frames[n])
558 ent->client->ps.gunframe++;
559
560 if (ent->client->ps.gunframe == FRAME_IDLE_FIRST+1)
561 {
562 ent->client->weaponstate = WEAPON_READY;
563 }
564
565 if(strcmp(ent->client->pers.weapon->classname, "weapon_fists") == 0)
566 if(ent->secondaryfire && ent->client->ps.gunframe == FRAME_ACTIVATE_LAST+4)
567 {
568 ent->client->ps.gunframe = FRAME_IDLE_FIRST+1;
569 ent->client->weaponstate = WEAPON_READY;
570 }
571
572 if (ent->client->ps.gunframe > FRAME_FIRE_SECONDARY_LAST && secondary_fire_weapon)
573 {
574 ent->client->ps.gunframe = FRAME_IDLE_FIRST+1;
575 ent->client->weaponstate = WEAPON_READY;
576 }
577 }
578 }
579
580
581 /*
582 ======================================================================
583
584 GRENADE
585
586 ======================================================================
587 */
588
589 #define GRENADE_TIMER 3.0
590 #define GRENADE_MINSPEED 400
591 #define GRENADE_MAXSPEED 800
592
593 //MATRIX i haxored teh granades!!
weapon_grenade_firex(edict_t * ent,qboolean held)594 void weapon_grenade_firex (edict_t *ent, qboolean held)
595 {
596 vec3_t offset;
597 vec3_t forward, right;
598 vec3_t start;
599 int damage = radiusdamage_grenade->value;
600 float timer;
601 int speed;
602 float radius;
603
604 radius = damageradius_grenade->value;
605 if (is_quad)
606 damage *= 4;
607
608 VectorSet(offset, 8, 8, ent->viewheight-8);
609 //SKULL
610 if (ent->client->use)
611 AngleVectors (ent->client->oldplayer->s.angles, forward, right, NULL);
612 else
613 //END
614 AngleVectors (ent->client->v_angle, forward, right, NULL);
615 P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
616
617 timer = ent->client->grenade_time - level.time;
618 speed = GRENADE_MINSPEED + (GRENADE_TIMER - timer) * ((GRENADE_MAXSPEED - GRENADE_MINSPEED) / GRENADE_TIMER);
619 fire_grenade2 (ent, start, forward, damage, speed, timer, radius, held);
620
621 if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
622 ent->client->pers.inventory[ent->client->ammo_index]-= ammo_grenade->value;
623
624 ent->client->grenade_time = level.time + 1.0;
625
626 if(ent->deadflag || ent->s.modelindex != 255) // VWep animations screw up corpses
627 {
628 return;
629 }
630
631 if (ent->health <= 0)
632 return;
633
634 if (ent->client->ps.pmove.pm_flags & PMF_DUCKED)
635 {
636 ent->client->anim_priority = ANIM_ATTACK;
637 ent->s.frame = FRAME_crattak1-1;
638 ent->client->anim_end = FRAME_crattak3;
639 }
640 else
641 {
642 ent->client->anim_priority = ANIM_REVERSE;
643 ent->s.frame = FRAME_wave08;
644 ent->client->anim_end = FRAME_wave01;
645 }
646 }
647
Weapon_Grenadex(edict_t * ent)648 void Weapon_Grenadex (edict_t *ent) //haxored!!!!
649 {
650 if ((ent->client->newweapon) && (ent->client->weaponstate == WEAPON_READY))
651 {
652 ChangeWeapon (ent);
653 return;
654 }
655
656 if (ent->client->weaponstate == WEAPON_ACTIVATING)
657 {
658 ent->client->weaponstate = WEAPON_READY;
659 ent->client->ps.gunframe = 16;
660 return;
661 }
662
663 if (ent->client->weaponstate == WEAPON_READY)
664 {
665 if ( ((ent->client->latched_buttons|ent->client->buttons) & BUTTON_ATTACK) || ent->secondaryfire )
666 {
667 ent->client->latched_buttons &= ~BUTTON_ATTACK;
668 if (ent->client->pers.inventory[ent->client->ammo_index])
669 {
670 ent->client->ps.gunframe = 1;
671 ent->client->weaponstate = WEAPON_FIRING;
672 ent->client->grenade_time = 0;
673 }
674 else
675 {
676 if (level.time >= ent->pain_debounce_time)
677 {
678 gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0);
679 ent->pain_debounce_time = level.time + 1;
680 }
681 NoAmmoWeaponChange (ent);
682 }
683 return;
684 }
685
686 if ((ent->client->ps.gunframe == 29) || (ent->client->ps.gunframe == 34) || (ent->client->ps.gunframe == 39) || (ent->client->ps.gunframe == 48))
687 {
688 if (rand()&15)
689 return;
690 }
691
692 if (++ent->client->ps.gunframe > 48)
693 ent->client->ps.gunframe = 16;
694 return;
695 }
696
697 if (ent->client->weaponstate == WEAPON_FIRING)
698 {
699 if (ent->client->ps.gunframe == 5)
700 gi.sound(ent, CHAN_WEAPON, gi.soundindex("weapons/hgrena1b.wav"), 1, ATTN_NORM, 0);
701
702 if (ent->client->ps.gunframe == 11)
703 {
704 if (!ent->client->grenade_time)
705 {
706 ent->client->grenade_time = level.time + GRENADE_TIMER + 0.2;
707 ent->client->weapon_sound = gi.soundindex("weapons/hgrenc1b.wav");
708 }
709
710 // they waited too long, detonate it in their hand
711 if (!ent->client->grenade_blew_up && level.time >= ent->client->grenade_time)
712 {
713 ent->client->weapon_sound = 0;
714 weapon_grenade_fire (ent, true);
715 ent->client->grenade_blew_up = true;
716 }
717
718 if (ent->client->buttons & BUTTON_ATTACK)
719 return;
720
721 if (ent->client->grenade_blew_up)
722 {
723 if (level.time >= ent->client->grenade_time)
724 {
725 ent->client->ps.gunframe = 15;
726 ent->client->grenade_blew_up = false;
727 }
728 else
729 {
730 return;
731 }
732 }
733 }
734
735 if (ent->client->ps.gunframe == 12)
736 {
737 ent->client->weapon_sound = 0;
738 weapon_grenade_fire (ent, false);
739 }
740
741 if ((ent->client->ps.gunframe == 15) && (level.time < ent->client->grenade_time))
742 return;
743
744 ent->client->ps.gunframe++;
745
746 if (ent->client->ps.gunframe == 16)
747 {
748 ent->client->grenade_time = 0;
749 ent->client->weaponstate = WEAPON_READY;
750 }
751 }
752 }
753
754 /*
755 ======================================================================
756
757 GRENADE LAUNCHER
758
759 ======================================================================
760 */
761
weapon_grenadelauncher_fire(edict_t * ent)762 void weapon_grenadelauncher_fire (edict_t *ent)
763 {
764 vec3_t offset;
765 vec3_t forward, right;
766 vec3_t start;
767 int damage = 120;
768 float radius;
769
770 radius = damage+40;
771 if (is_quad)
772 damage *= 4;
773
774 VectorSet(offset, 8, 8, ent->viewheight-8);
775 //SKULL
776 if (ent->client->use)
777 AngleVectors (ent->client->oldplayer->s.angles, forward, right, NULL);
778 else
779 //END
780 AngleVectors (ent->client->v_angle, forward, right, NULL);
781 P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
782
783 VectorScale (forward, -2, ent->client->kick_origin);
784 ent->client->kick_angles[0] = -1;
785
786 fire_grenade (ent, start, forward, damage, 600, 2.5, radius);
787
788 gi.WriteByte (svc_muzzleflash);
789 //SKULL
790 if (ent->client->oldplayer)
791 gi.WriteShort (ent->client->oldplayer-g_edicts);
792 else
793 gi.WriteShort (ent-g_edicts);
794 //END
795 gi.WriteByte (MZ_GRENADE | is_silenced);
796 //SKULL
797 if (ent->client->oldplayer)
798 gi.multicast (ent->client->oldplayer->s.origin, MULTICAST_PVS);
799 else
800 gi.multicast (ent->s.origin, MULTICAST_PVS);
801 //END
802
803 ent->client->ps.gunframe++;
804
805 PlayerNoise(ent, start, PNOISE_WEAPON);
806
807 if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
808 ent->client->pers.inventory[ent->client->ammo_index]--;
809 }
810
Weapon_GrenadeLauncher(edict_t * ent)811 void Weapon_GrenadeLauncher (edict_t *ent)
812 {
813 static int pause_frames[] = {34, 51, 59, 0};
814 static int fire_frames[] = {6, 0};
815
816 Weapon_Generic (ent, 5, 16, 59, 64, pause_frames, fire_frames, weapon_grenadelauncher_fire, ent->client->pers.weapon->quantity);
817 }
818
819 /*
820 ======================================================================
821
822 ROCKET
823
824 ======================================================================
825 */
826
Weapon_RocketLauncher_Fire(edict_t * ent)827 void Weapon_RocketLauncher_Fire (edict_t *ent)
828 {
829 vec3_t offset, start;
830 vec3_t forward, right;
831 int damage;
832 float damage_radius;
833 int radius_damage;
834
835 damage = 100 + (int)(random() * 20.0);
836 radius_damage = 120;
837 damage_radius = 120;
838 if (is_quad)
839 {
840 damage *= 4;
841 radius_damage *= 4;
842 }
843
844 //SKULL
845 if (ent->client->use)
846 AngleVectors (ent->client->oldplayer->s.angles, forward, right, NULL);
847 else
848 //END
849 AngleVectors (ent->client->v_angle, forward, right, NULL);
850
851 VectorScale (forward, -2, ent->client->kick_origin);
852 ent->client->kick_angles[0] = -1;
853
854 VectorSet(offset, 8, 8, ent->viewheight-8);
855 P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
856 fire_rocket (ent, start, forward, damage, 650, damage_radius, radius_damage);
857
858 // send muzzle flash
859 gi.WriteByte (svc_muzzleflash);
860 //SKULL
861 if (ent->client->oldplayer)
862 gi.WriteShort (ent->client->oldplayer-g_edicts);
863 else
864 gi.WriteShort (ent-g_edicts);
865 //END
866 gi.WriteByte (MZ_ROCKET | is_silenced);
867 //SKULL
868 if (ent->client->oldplayer)
869 gi.multicast (ent->client->oldplayer->s.origin, MULTICAST_PVS);
870 else
871 gi.multicast (ent->s.origin, MULTICAST_PVS);
872 //END
873
874 ent->client->ps.gunframe++;
875
876 PlayerNoise(ent, start, PNOISE_WEAPON);
877
878 if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
879 ent->client->pers.inventory[ent->client->ammo_index]--;
880 }
881
Weapon_RocketLauncher(edict_t * ent)882 void Weapon_RocketLauncher (edict_t *ent)
883 {
884 static int pause_frames[] = {25, 33, 42, 50, 0};
885 static int fire_frames[] = {5, 0};
886
887 Weapon_Generic (ent, 4, 12, 50, 54, pause_frames, fire_frames, Weapon_RocketLauncher_Fire, ent->client->pers.weapon->quantity);
888 }
889
890
891 /*
892 ======================================================================
893
894 BLASTER / HYPERBLASTER
895
896 ======================================================================
897 */
898
Blaster_Fire(edict_t * ent,vec3_t g_offset,int damage,qboolean hyper,int effect)899 void Blaster_Fire (edict_t *ent, vec3_t g_offset, int damage, qboolean hyper, int effect)
900 {
901 vec3_t forward, right;
902 vec3_t start;
903 vec3_t offset;
904
905 if (is_quad)
906 damage *= 4;
907 //SKULL
908 if (ent->client->use)
909 AngleVectors (ent->client->oldplayer->s.angles, forward, right, NULL);
910 else
911 //END
912 AngleVectors (ent->client->v_angle, forward, right, NULL);
913 VectorSet(offset, 24, 8, ent->viewheight-8);
914 VectorAdd (offset, g_offset, offset);
915 P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
916
917 VectorScale (forward, -2, ent->client->kick_origin);
918 ent->client->kick_angles[0] = -1;
919
920 fire_blaster (ent, start, forward, damage, 1000, effect, hyper);
921
922 // send muzzle flash
923 gi.WriteByte (svc_muzzleflash);
924 //SKULL
925 if (ent->client->oldplayer)
926 gi.WriteShort (ent->client->oldplayer-g_edicts);
927 else
928 gi.WriteShort (ent-g_edicts);
929 //END
930 if (hyper)
931 gi.WriteByte (MZ_HYPERBLASTER | is_silenced);
932 else
933 gi.WriteByte (MZ_BLASTER | is_silenced);
934 //SKULL
935 if (ent->client->oldplayer)
936 gi.multicast (ent->client->oldplayer->s.origin, MULTICAST_PVS);
937 else
938 gi.multicast (ent->s.origin, MULTICAST_PVS);
939 //END
940
941 PlayerNoise(ent, start, PNOISE_WEAPON);
942 }
943
944
Weapon_Blaster_Fire(edict_t * ent)945 void Weapon_Blaster_Fire (edict_t *ent)
946 {
947 int damage;
948
949 if (deathmatch->value)
950 damage = 15;
951 else
952 damage = 10;
953 Blaster_Fire (ent, vec3_origin, damage, false, EF_BLASTER);
954 ent->client->ps.gunframe++;
955 }
956
Weapon_Blaster(edict_t * ent)957 void Weapon_Blaster (edict_t *ent)
958 {
959 static int pause_frames[] = {19, 32, 0};
960 static int fire_frames[] = {5, 0};
961
962 Weapon_Generic (ent, 4, 8, 52, 55, pause_frames, fire_frames, Weapon_Blaster_Fire, ent->client->pers.weapon->quantity);
963 }
964
965
Weapon_HyperBlaster_Fire(edict_t * ent)966 void Weapon_HyperBlaster_Fire (edict_t *ent)
967 {
968 float rotation;
969 vec3_t offset;
970 int effect;
971 int damage;
972
973 ent->client->weapon_sound = gi.soundindex("weapons/hyprbl1a.wav");
974
975 if (!(ent->client->buttons & BUTTON_ATTACK))
976 {
977 ent->client->ps.gunframe++;
978 }
979 else
980 {
981 if (! ent->client->pers.inventory[ent->client->ammo_index] )
982 {
983 if (level.time >= ent->pain_debounce_time)
984 {
985 gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0);
986 ent->pain_debounce_time = level.time + 1;
987 }
988 NoAmmoWeaponChange (ent);
989 }
990 else
991 {
992 rotation = (ent->client->ps.gunframe - 5) * 2*M_PI/6;
993 offset[0] = -4 * sin(rotation);
994 offset[1] = 0;
995 offset[2] = 4 * cos(rotation);
996
997 if ((ent->client->ps.gunframe == 6) || (ent->client->ps.gunframe == 9))
998 effect = EF_HYPERBLASTER;
999 else
1000 effect = 0;
1001 if (deathmatch->value)
1002 damage = 15;
1003 else
1004 damage = 20;
1005 Blaster_Fire (ent, offset, damage, true, effect);
1006 if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
1007 ent->client->pers.inventory[ent->client->ammo_index]--;
1008
1009 ent->client->anim_priority = ANIM_ATTACK;
1010 if (ent->client->ps.pmove.pm_flags & PMF_DUCKED)
1011 {
1012 ent->s.frame = FRAME_crattak1 - 1;
1013 ent->client->anim_end = FRAME_crattak9;
1014 }
1015 else
1016 {
1017 ent->s.frame = FRAME_attack1 - 1;
1018 ent->client->anim_end = FRAME_attack8;
1019 }
1020 }
1021
1022 ent->client->ps.gunframe++;
1023 if (ent->client->ps.gunframe == 12 && ent->client->pers.inventory[ent->client->ammo_index])
1024 ent->client->ps.gunframe = 6;
1025 }
1026
1027 if (ent->client->ps.gunframe == 12)
1028 {
1029 gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/hyprbd1a.wav"), 1, ATTN_NORM, 0);
1030 ent->client->weapon_sound = 0;
1031 }
1032
1033 }
1034
Weapon_HyperBlaster(edict_t * ent)1035 void Weapon_HyperBlaster (edict_t *ent)
1036 {
1037 static int pause_frames[] = {0};
1038 static int fire_frames[] = {6, 7, 8, 9, 10, 11, 0};
1039
1040 Weapon_Generic (ent, 5, 20, 49, 53, pause_frames, fire_frames, Weapon_HyperBlaster_Fire, ent->client->pers.weapon->quantity);
1041 }
1042
1043 /*
1044 ======================================================================
1045
1046 MACHINEGUN / CHAINGUN
1047
1048 ======================================================================
1049 */
1050
Machinegun_Fire(edict_t * ent)1051 void Machinegun_Fire (edict_t *ent)
1052 {
1053 int i;
1054 vec3_t start;
1055 vec3_t forward, right;
1056 vec3_t angles;
1057 int damage = 8;
1058 int kick = 2;
1059 vec3_t offset;
1060
1061 if (!(ent->client->buttons & BUTTON_ATTACK))
1062 {
1063 ent->client->machinegun_shots = 0;
1064 ent->client->ps.gunframe++;
1065 return;
1066 }
1067
1068 if (ent->client->ps.gunframe == 5)
1069 ent->client->ps.gunframe = 4;
1070 else
1071 ent->client->ps.gunframe = 5;
1072
1073 if (ent->client->pers.inventory[ent->client->ammo_index] < 1)
1074 {
1075 ent->client->ps.gunframe = 6;
1076 if (level.time >= ent->pain_debounce_time)
1077 {
1078 gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0);
1079 ent->pain_debounce_time = level.time + 1;
1080 }
1081 NoAmmoWeaponChange (ent);
1082 return;
1083 }
1084
1085 if (is_quad)
1086 {
1087 damage *= 4;
1088 kick *= 4;
1089 }
1090
1091 for (i=1 ; i<3 ; i++)
1092 {
1093 ent->client->kick_origin[i] = crandom() * 0.35;
1094 ent->client->kick_angles[i] = crandom() * 0.7;
1095 }
1096 ent->client->kick_origin[0] = crandom() * 0.35;
1097 ent->client->kick_angles[0] = ent->client->machinegun_shots * -1.5;
1098
1099 // raise the gun as it is firing
1100 if (!deathmatch->value)
1101 {
1102 ent->client->machinegun_shots++;
1103 if (ent->client->machinegun_shots > 9)
1104 ent->client->machinegun_shots = 9;
1105 }
1106
1107 // get start / end positions
1108 //SKULL
1109 if (ent->client->use)
1110 VectorAdd (ent->client->oldplayer->s.angles, ent->client->kick_angles, angles);
1111 else
1112 //END
1113 VectorAdd (ent->client->v_angle, ent->client->kick_angles, angles);
1114 AngleVectors (angles, forward, right, NULL);
1115 VectorSet(offset, 0, 8, ent->viewheight-8);
1116 P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
1117 fire_bullet (ent, start, forward, damage, kick, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, MOD_MACHINEGUN);
1118
1119 gi.WriteByte (svc_muzzleflash);
1120 //SKULL
1121 if (ent->client->oldplayer)
1122 gi.WriteShort (ent->client->oldplayer-g_edicts);
1123 else
1124 gi.WriteShort (ent-g_edicts);
1125 //END
1126 gi.WriteByte (MZ_MACHINEGUN | is_silenced);
1127 //SKULL
1128 if (ent->client->oldplayer)
1129 gi.multicast (ent->client->oldplayer->s.origin, MULTICAST_PVS);
1130 else
1131 gi.multicast (ent->s.origin, MULTICAST_PVS);
1132 //END
1133
1134 PlayerNoise(ent, start, PNOISE_WEAPON);
1135
1136 if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
1137 ent->client->pers.inventory[ent->client->ammo_index]--;
1138
1139 ent->client->anim_priority = ANIM_ATTACK;
1140 if (ent->client->ps.pmove.pm_flags & PMF_DUCKED)
1141 {
1142 ent->s.frame = FRAME_crattak1 - (int) (random()+0.25);
1143 ent->client->anim_end = FRAME_crattak9;
1144 }
1145 else
1146 {
1147 ent->s.frame = FRAME_attack1 - (int) (random()+0.25);
1148 ent->client->anim_end = FRAME_attack8;
1149 }
1150 }
1151
Weapon_Machinegun(edict_t * ent)1152 void Weapon_Machinegun (edict_t *ent)
1153 {
1154 static int pause_frames[] = {23, 45, 0};
1155 static int fire_frames[] = {4, 5, 0};
1156
1157 Weapon_Generic (ent, 3, 5, 45, 49, pause_frames, fire_frames, Machinegun_Fire, ent->client->pers.weapon->quantity);
1158 }
1159
Chaingun_Fire(edict_t * ent)1160 void Chaingun_Fire (edict_t *ent)
1161 {
1162 int i;
1163 int shots;
1164 vec3_t start;
1165 vec3_t forward, right, up;
1166 float r, u;
1167 vec3_t offset;
1168 int damage;
1169 int kick = 2;
1170
1171 if (deathmatch->value)
1172 damage = 6;
1173 else
1174 damage = 8;
1175
1176 if (ent->client->ps.gunframe == 5)
1177 gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/chngnu1a.wav"), 1, ATTN_IDLE, 0);
1178
1179 if ((ent->client->ps.gunframe == 14) && !(ent->client->buttons & BUTTON_ATTACK))
1180 {
1181 ent->client->ps.gunframe = 32;
1182 ent->client->weapon_sound = 0;
1183 return;
1184 }
1185 else if ((ent->client->ps.gunframe == 21) && (ent->client->buttons & BUTTON_ATTACK)
1186 && ent->client->pers.inventory[ent->client->ammo_index])
1187 {
1188 ent->client->ps.gunframe = 15;
1189 }
1190 else
1191 {
1192 ent->client->ps.gunframe++;
1193 }
1194
1195 if (ent->client->ps.gunframe == 22)
1196 {
1197 ent->client->weapon_sound = 0;
1198 gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/chngnd1a.wav"), 1, ATTN_IDLE, 0);
1199 }
1200 else
1201 {
1202 ent->client->weapon_sound = gi.soundindex("weapons/chngnl1a.wav");
1203 }
1204
1205 ent->client->anim_priority = ANIM_ATTACK;
1206 if (ent->client->ps.pmove.pm_flags & PMF_DUCKED)
1207 {
1208 ent->s.frame = FRAME_crattak1 - (ent->client->ps.gunframe & 1);
1209 ent->client->anim_end = FRAME_crattak9;
1210 }
1211 else
1212 {
1213 ent->s.frame = FRAME_attack1 - (ent->client->ps.gunframe & 1);
1214 ent->client->anim_end = FRAME_attack8;
1215 }
1216
1217 if (ent->client->ps.gunframe <= 9)
1218 shots = 1;
1219 else if (ent->client->ps.gunframe <= 14)
1220 {
1221 if (ent->client->buttons & BUTTON_ATTACK)
1222 shots = 2;
1223 else
1224 shots = 1;
1225 }
1226 else
1227 shots = 3;
1228
1229 if (ent->client->pers.inventory[ent->client->ammo_index] < shots)
1230 shots = ent->client->pers.inventory[ent->client->ammo_index];
1231
1232 if (!shots)
1233 {
1234 if (level.time >= ent->pain_debounce_time)
1235 {
1236 gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0);
1237 ent->pain_debounce_time = level.time + 1;
1238 }
1239 NoAmmoWeaponChange (ent);
1240 return;
1241 }
1242
1243 if (is_quad)
1244 {
1245 damage *= 4;
1246 kick *= 4;
1247 }
1248
1249 for (i=0 ; i<3 ; i++)
1250 {
1251 ent->client->kick_origin[i] = crandom() * 0.35;
1252 ent->client->kick_angles[i] = crandom() * 0.7;
1253 }
1254
1255 for (i=0 ; i<shots ; i++)
1256 {
1257 // get start / end positions
1258 //SKULL
1259 if (ent->client->use)
1260 AngleVectors (ent->client->oldplayer->s.angles, forward, right, NULL);
1261 else
1262 //END
1263 AngleVectors (ent->client->v_angle, forward, right, up);
1264 r = 7 + crandom()*4;
1265 u = crandom()*4;
1266 VectorSet(offset, 0, r, u + ent->viewheight-8);
1267 P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
1268
1269 fire_bullet (ent, start, forward, damage, kick, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, MOD_CHAINGUN);
1270 }
1271
1272 // send muzzle flash
1273 gi.WriteByte (svc_muzzleflash);
1274 //SKULL
1275 if (ent->client->oldplayer)
1276 gi.WriteShort (ent->client->oldplayer-g_edicts);
1277 else
1278 gi.WriteShort (ent-g_edicts);
1279 //END
1280 gi.WriteByte ((MZ_CHAINGUN1 + shots - 1) | is_silenced);
1281 //SKULL
1282 if (ent->client->oldplayer)
1283 gi.multicast (ent->client->oldplayer->s.origin, MULTICAST_PVS);
1284 else
1285 gi.multicast (ent->s.origin, MULTICAST_PVS);
1286 //END
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] -= shots;
1292 }
1293
1294
Weapon_Chaingun(edict_t * ent)1295 void Weapon_Chaingun (edict_t *ent)
1296 {
1297 static int pause_frames[] = {38, 43, 51, 61, 0};
1298 static int fire_frames[] = {5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 0};
1299
1300 Weapon_Generic (ent, 4, 31, 61, 64, pause_frames, fire_frames, Chaingun_Fire, ent->client->pers.weapon->quantity);
1301 }
1302
1303
1304 /*
1305 ======================================================================
1306
1307 SHOTGUN / SUPERSHOTGUN
1308
1309 ======================================================================
1310 */
1311
weapon_shotgun_fire(edict_t * ent)1312 void weapon_shotgun_fire (edict_t *ent)
1313 {
1314 vec3_t start;
1315 vec3_t forward, right;
1316 vec3_t offset;
1317 int damage = 4;
1318 int kick = 8;
1319
1320 if (ent->client->ps.gunframe == 9)
1321 {
1322 ent->client->ps.gunframe++;
1323 return;
1324 }
1325
1326 //SKULL
1327 if (ent->client->use)
1328 AngleVectors (ent->client->oldplayer->s.angles, forward, right, NULL);
1329 else
1330 //END
1331 AngleVectors (ent->client->v_angle, forward, right, NULL);
1332
1333 VectorScale (forward, -2, ent->client->kick_origin);
1334 ent->client->kick_angles[0] = -2;
1335
1336 VectorSet(offset, 0, 8, ent->viewheight-8);
1337 P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
1338
1339 if (is_quad)
1340 {
1341 damage *= 4;
1342 kick *= 4;
1343 }
1344
1345 if (deathmatch->value)
1346 fire_shotgun (ent, start, forward, damage, kick, 500, 500, DEFAULT_DEATHMATCH_SHOTGUN_COUNT, MOD_SHOTGUN);
1347 else
1348 fire_shotgun (ent, start, forward, damage, kick, 500, 500, DEFAULT_SHOTGUN_COUNT, MOD_SHOTGUN);
1349
1350 // send muzzle flash
1351 gi.WriteByte (svc_muzzleflash);
1352 //SKULL
1353 if (ent->client->oldplayer)
1354 gi.WriteShort (ent->client->oldplayer-g_edicts);
1355 else
1356 gi.WriteShort (ent-g_edicts);
1357 //END
1358 gi.WriteByte (MZ_SHOTGUN | is_silenced);
1359 //SKULL
1360 if (ent->client->oldplayer)
1361 gi.multicast (ent->client->oldplayer->s.origin, MULTICAST_PVS);
1362 else
1363 gi.multicast (ent->s.origin, MULTICAST_PVS);
1364 //END
1365
1366 ent->client->ps.gunframe++;
1367 PlayerNoise(ent, start, PNOISE_WEAPON);
1368
1369 if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
1370 ent->client->pers.inventory[ent->client->ammo_index]--;
1371 }
1372
Weapon_Shotgun(edict_t * ent)1373 void Weapon_Shotgun (edict_t *ent)
1374 {
1375 static int pause_frames[] = {22, 28, 34, 0};
1376 static int fire_frames[] = {8, 9, 0};
1377
1378 Weapon_Generic (ent, 7, 18, 36, 39, pause_frames, fire_frames, weapon_shotgun_fire, ent->client->pers.weapon->quantity);
1379 }
1380
1381
weapon_supershotgun_fire(edict_t * ent)1382 void weapon_supershotgun_fire (edict_t *ent)
1383 {
1384 vec3_t start;
1385 vec3_t forward, right;
1386 vec3_t offset;
1387 vec3_t v;
1388 int damage = 6;
1389 int kick = 12;
1390
1391 //SKULL
1392 if (ent->client->use)
1393 AngleVectors (ent->client->oldplayer->s.angles, forward, right, NULL);
1394 else
1395 //END
1396 AngleVectors (ent->client->v_angle, forward, right, NULL);
1397
1398 VectorScale (forward, -2, ent->client->kick_origin);
1399 ent->client->kick_angles[0] = -2;
1400
1401 VectorSet(offset, 0, 8, ent->viewheight-8);
1402 P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
1403
1404 if (is_quad)
1405 {
1406 damage *= 4;
1407 kick *= 4;
1408 }
1409
1410 //SKULL
1411 if (ent->client->use)
1412 {
1413 v[PITCH] = ent->client->oldplayer->s.angles[PITCH];
1414 v[YAW] = ent->client->oldplayer->s.angles[YAW] - 5;
1415 v[ROLL] = ent->client->oldplayer->s.angles[ROLL];
1416 }
1417 else
1418 {
1419 v[PITCH] = ent->client->v_angle[PITCH];
1420 v[YAW] = ent->client->v_angle[YAW] - 5;
1421 v[ROLL] = ent->client->v_angle[ROLL];
1422 }
1423 AngleVectors (v, forward, NULL, NULL);
1424 fire_shotgun (ent, start, forward, damage, kick, DEFAULT_SHOTGUN_HSPREAD, DEFAULT_SHOTGUN_VSPREAD, DEFAULT_SSHOTGUN_COUNT/2, MOD_SSHOTGUN);
1425 if (ent->client->use)
1426 v[YAW] = ent->client->oldplayer->s.angles[YAW] + 5;
1427 else
1428 //END
1429 v[YAW] = ent->client->v_angle[YAW] + 5;
1430 AngleVectors (v, forward, NULL, NULL);
1431 fire_shotgun (ent, start, forward, damage, kick, DEFAULT_SHOTGUN_HSPREAD, DEFAULT_SHOTGUN_VSPREAD, DEFAULT_SSHOTGUN_COUNT/2, MOD_SSHOTGUN);
1432
1433 // send muzzle flash
1434 gi.WriteByte (svc_muzzleflash);
1435 //SKULL
1436 if (ent->client->oldplayer)
1437 gi.WriteShort (ent->client->oldplayer-g_edicts);
1438 else
1439 gi.WriteShort (ent-g_edicts);
1440 //END
1441 gi.WriteByte (MZ_SSHOTGUN | is_silenced);
1442 //SKULL
1443 if (ent->client->oldplayer)
1444 gi.multicast (ent->client->oldplayer->s.origin, MULTICAST_PVS);
1445 else
1446 gi.multicast (ent->s.origin, MULTICAST_PVS);
1447 //END
1448
1449 ent->client->ps.gunframe++;
1450 PlayerNoise(ent, start, PNOISE_WEAPON);
1451
1452 if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
1453 ent->client->pers.inventory[ent->client->ammo_index] -= 2;
1454 }
1455
Weapon_SuperShotgun(edict_t * ent)1456 void Weapon_SuperShotgun (edict_t *ent)
1457 {
1458 static int pause_frames[] = {29, 42, 57, 0};
1459 static int fire_frames[] = {7, 0};
1460
1461 Weapon_Generic (ent, 6, 17, 57, 61, pause_frames, fire_frames, weapon_supershotgun_fire, ent->client->pers.weapon->quantity);
1462 }
1463
1464
1465
1466 /*
1467 ======================================================================
1468
1469 RAILGUN
1470
1471 ======================================================================
1472 */
1473
weapon_railgun_fire(edict_t * ent)1474 void weapon_railgun_fire (edict_t *ent)
1475 {
1476 vec3_t start;
1477 vec3_t forward, right;
1478 vec3_t offset;
1479 int damage;
1480 int kick;
1481
1482 if (deathmatch->value)
1483 { // normal damage is too extreme in dm
1484 damage = 100;
1485 kick = 200;
1486 }
1487 else
1488 {
1489 damage = 150;
1490 kick = 250;
1491 }
1492
1493 if (is_quad)
1494 {
1495 damage *= 4;
1496 kick *= 4;
1497 }
1498
1499 //SKULL
1500 if (ent->client->use)
1501 AngleVectors (ent->client->oldplayer->s.angles, forward, right, NULL);
1502 else
1503 //END
1504 AngleVectors (ent->client->v_angle, forward, right, NULL);
1505
1506 VectorScale (forward, -3, ent->client->kick_origin);
1507 ent->client->kick_angles[0] = -3;
1508
1509 VectorSet(offset, 0, 7, ent->viewheight-8);
1510 P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
1511 fire_rail (ent, start, forward, damage, kick);
1512
1513 // send muzzle flash
1514 gi.WriteByte (svc_muzzleflash);
1515 //SKULL
1516 //if (ent->client->oldplayer)
1517 if (ent->client->use)
1518 gi.WriteShort (ent->client->oldplayer-g_edicts);
1519 else
1520 gi.WriteShort (ent-g_edicts);
1521 //END
1522 gi.WriteByte (MZ_RAILGUN | is_silenced);
1523 //SKULL
1524 //if (ent->client->oldplayer)
1525 if (ent->client->use)
1526 gi.multicast (ent->client->oldplayer->s.origin, MULTICAST_PVS);
1527 else
1528 gi.multicast (ent->s.origin, MULTICAST_PVS);
1529 //END
1530
1531 ent->client->ps.gunframe++;
1532 PlayerNoise(ent, start, PNOISE_WEAPON);
1533
1534 if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
1535 ent->client->pers.inventory[ent->client->ammo_index]--;
1536 }
1537
1538
Weapon_Railgun(edict_t * ent)1539 void Weapon_Railgun (edict_t *ent)
1540 {
1541 static int pause_frames[] = {56, 0};
1542 static int fire_frames[] = {4, 0};
1543
1544 Weapon_Generic (ent, 3, 18, 56, 61, pause_frames, fire_frames, weapon_railgun_fire, ent->client->pers.weapon->quantity);
1545 }
1546
1547
1548 /*
1549 ======================================================================
1550
1551 BFG10K
1552
1553 ======================================================================
1554 */
1555
weapon_bfg_fire(edict_t * ent)1556 void weapon_bfg_fire (edict_t *ent)
1557 {
1558 vec3_t offset, start;
1559 vec3_t forward, right;
1560 int damage;
1561 float damage_radius = 1000;
1562
1563 if (deathmatch->value)
1564 damage = 200;
1565 else
1566 damage = 500;
1567
1568 if (ent->client->ps.gunframe == 9)
1569 {
1570 // send muzzle flash
1571 gi.WriteByte (svc_muzzleflash);
1572 //SKULL
1573 if (ent->client->oldplayer)
1574 gi.WriteShort (ent->client->oldplayer-g_edicts);
1575 else
1576 gi.WriteShort (ent-g_edicts);
1577 //END
1578 gi.WriteByte (MZ_BFG | is_silenced);
1579 //SKULL
1580 if (ent->client->oldplayer)
1581 gi.multicast (ent->client->oldplayer->s.origin, MULTICAST_PVS);
1582 else
1583 gi.multicast (ent->s.origin, MULTICAST_PVS);
1584 //END
1585
1586 ent->client->ps.gunframe++;
1587
1588 PlayerNoise(ent, start, PNOISE_WEAPON);
1589 return;
1590 }
1591
1592 // cells can go down during windup (from power armor hits), so
1593 // check again and abort firing if we don't have enough now
1594 if (ent->client->pers.inventory[ent->client->ammo_index] < 50)
1595 {
1596 ent->client->ps.gunframe++;
1597 return;
1598 }
1599
1600 if (is_quad)
1601 damage *= 4;
1602
1603 //SKULL
1604 if (ent->client->use)
1605 AngleVectors (ent->client->oldplayer->s.angles, forward, right, NULL);
1606 else
1607 //END
1608 AngleVectors (ent->client->v_angle, forward, right, NULL);
1609
1610 VectorScale (forward, -2, ent->client->kick_origin);
1611
1612 // make a big pitch kick with an inverse fall
1613 ent->client->v_dmg_pitch = -40;
1614 ent->client->v_dmg_roll = crandom()*8;
1615 ent->client->v_dmg_time = level.time + DAMAGE_TIME;
1616
1617 VectorSet(offset, 8, 8, ent->viewheight-8);
1618 P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
1619 fire_bfg (ent, start, forward, damage, 400, damage_radius);
1620
1621 ent->client->ps.gunframe++;
1622
1623 PlayerNoise(ent, start, PNOISE_WEAPON);
1624
1625 if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
1626 ent->client->pers.inventory[ent->client->ammo_index] -= 50;
1627 }
1628
Weapon_BFG(edict_t * ent)1629 void Weapon_BFG (edict_t *ent)
1630 {
1631 static int pause_frames[] = {39, 45, 50, 55, 0};
1632 static int fire_frames[] = {9, 17, 0};
1633
1634 Weapon_Generic (ent, 8, 32, 55, 58, pause_frames, fire_frames, weapon_bfg_fire, ent->client->pers.weapon->quantity);
1635 }
1636
1637
1638 //======================================================================
1639