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 //PGM
11 static byte damage_multiplier;
12 //PGM
13
14 void weapon_grenade_fire (edict_t *ent, qboolean held);
15
16 //========
17 //ROGUE
P_DamageModifier(edict_t * ent)18 byte P_DamageModifier(edict_t *ent)
19 {
20 is_quad = 0;
21 damage_multiplier = 1;
22
23 if(ent->client->quad_framenum > level.framenum)
24 {
25 damage_multiplier *= 4;
26 is_quad = 1;
27
28 // if we're quad and DF_NO_STACK_DOUBLE is on, return now.
29 if(((int)(dmflags->value) & DF_NO_STACK_DOUBLE))
30 return damage_multiplier;
31 }
32 if(ent->client->double_framenum > level.framenum)
33 {
34 if ((deathmatch->value) || (damage_multiplier == 1))
35 {
36 damage_multiplier *= 2;
37 is_quad = 1;
38 }
39 }
40
41 return damage_multiplier;
42 }
43 //ROGUE
44 //========
45
P_ProjectSource(gclient_t * client,vec3_t point,vec3_t distance,vec3_t forward,vec3_t right,vec3_t result)46 void P_ProjectSource (gclient_t *client, vec3_t point, vec3_t distance, vec3_t forward, vec3_t right, vec3_t result)
47 {
48 vec3_t _distance;
49
50 VectorCopy (distance, _distance);
51 if (client->pers.hand == LEFT_HANDED)
52 _distance[1] *= -1;
53 else if (client->pers.hand == CENTER_HANDED)
54 _distance[1] = 0;
55 G_ProjectSource (point, _distance, forward, right, result);
56 }
57
P_ProjectSource2(gclient_t * client,vec3_t point,vec3_t distance,vec3_t forward,vec3_t right,vec3_t up,vec3_t result)58 static void P_ProjectSource2 (gclient_t *client, vec3_t point, vec3_t distance, vec3_t forward,
59 vec3_t right, vec3_t up, vec3_t result)
60 {
61 vec3_t _distance;
62
63 VectorCopy (distance, _distance);
64 if (client->pers.hand == LEFT_HANDED)
65 _distance[1] *= -1;
66 else if (client->pers.hand == CENTER_HANDED)
67 _distance[1] = 0;
68 G_ProjectSource2 (point, _distance, forward, right, up, result);
69 }
70
71 /*
72 ===============
73 PlayerNoise
74
75 Each player can have two noise objects associated with it:
76 a personal noise (jumping, pain, weapon firing), and a weapon
77 target noise (bullet wall impacts)
78
79 Monsters that don't directly see the player can move
80 to a noise in hopes of seeing the player from there.
81 ===============
82 */
PlayerNoise(edict_t * who,vec3_t where,int type)83 void PlayerNoise(edict_t *who, vec3_t where, int type)
84 {
85 edict_t *noise;
86
87 if (type == PNOISE_WEAPON)
88 {
89 if (who->client->silencer_shots)
90 {
91 who->client->silencer_shots--;
92 return;
93 }
94 }
95
96 if (deathmatch->value)
97 return;
98
99 if (who->flags & FL_NOTARGET)
100 return;
101
102 if (who->flags & FL_DISGUISED)
103 {
104 if (type == PNOISE_WEAPON)
105 {
106 level.disguise_violator = who;
107 level.disguise_violation_framenum = level.framenum + 5;
108 }
109 else
110 return;
111 }
112
113 if (!who->mynoise)
114 {
115 noise = G_Spawn();
116 noise->classname = "player_noise";
117 VectorSet (noise->mins, -8, -8, -8);
118 VectorSet (noise->maxs, 8, 8, 8);
119 noise->owner = who;
120 noise->svflags = SVF_NOCLIENT;
121 who->mynoise = noise;
122
123 noise = G_Spawn();
124 noise->classname = "player_noise";
125 VectorSet (noise->mins, -8, -8, -8);
126 VectorSet (noise->maxs, 8, 8, 8);
127 noise->owner = who;
128 noise->svflags = SVF_NOCLIENT;
129 who->mynoise2 = noise;
130 }
131
132 if (type == PNOISE_SELF || type == PNOISE_WEAPON)
133 {
134 noise = who->mynoise;
135 level.sound_entity = noise;
136 level.sound_entity_framenum = level.framenum;
137 }
138 else // type == PNOISE_IMPACT
139 {
140 noise = who->mynoise2;
141 level.sound2_entity = noise;
142 level.sound2_entity_framenum = level.framenum;
143 }
144
145 VectorCopy (where, noise->s.origin);
146 VectorSubtract (where, noise->maxs, noise->absmin);
147 VectorAdd (where, noise->maxs, noise->absmax);
148 noise->teleport_time = level.time;
149 gi.linkentity (noise);
150 }
151
152
Pickup_Weapon(edict_t * ent,edict_t * other)153 qboolean Pickup_Weapon (edict_t *ent, edict_t *other)
154 {
155 int index;
156 gitem_t *ammo;
157
158 index = ITEM_INDEX(ent->item);
159
160 if ( ( ((int)(dmflags->value) & DF_WEAPONS_STAY) || coop->value)
161 && other->client->pers.inventory[index])
162 {
163 if (!(ent->spawnflags & (DROPPED_ITEM | DROPPED_PLAYER_ITEM) ) )
164 return false; // leave the weapon for others to pickup
165 }
166
167 other->client->pers.inventory[index]++;
168
169 if (!(ent->spawnflags & DROPPED_ITEM) )
170 {
171 // give them some ammo with it
172 // PGM -- IF APPROPRIATE!
173 if(ent->item->ammo) //PGM
174 {
175 ammo = FindItem (ent->item->ammo);
176 if ( (int)dmflags->value & DF_INFINITE_AMMO )
177 Add_Ammo (other, ammo, 1000);
178 else
179 Add_Ammo (other, ammo, ammo->quantity);
180 }
181
182 if (! (ent->spawnflags & DROPPED_PLAYER_ITEM) )
183 {
184 if (deathmatch->value)
185 {
186 if ((int)(dmflags->value) & DF_WEAPONS_STAY)
187 ent->flags |= FL_RESPAWN;
188 else
189 SetRespawn (ent, 30);
190 }
191 if (coop->value)
192 ent->flags |= FL_RESPAWN;
193 }
194 }
195
196 if (other->client->pers.weapon != ent->item &&
197 (other->client->pers.inventory[index] == 1) &&
198 ( !deathmatch->value || other->client->pers.weapon == FindItem("blaster") ) )
199 other->client->newweapon = ent->item;
200
201 return true;
202 }
203
204
205 /*
206 ===============
207 ChangeWeapon
208
209 The old weapon has been dropped all the way, so make the new one
210 current
211 ===============
212 */
ChangeWeapon(edict_t * ent)213 void ChangeWeapon (edict_t *ent)
214 {
215 int i;
216
217 if (ent->client->grenade_time)
218 {
219 ent->client->grenade_time = level.time;
220 ent->client->weapon_sound = 0;
221 weapon_grenade_fire (ent, false);
222 ent->client->grenade_time = 0;
223 }
224
225 ent->client->pers.lastweapon = ent->client->pers.weapon;
226 ent->client->pers.weapon = ent->client->newweapon;
227 ent->client->newweapon = NULL;
228 ent->client->machinegun_shots = 0;
229
230 // set visible model
231 if (ent->s.modelindex == 255)
232 {
233 if (ent->client->pers.weapon)
234 i = ((ent->client->pers.weapon->weapmodel & 0xff) << 8);
235 else
236 i = 0;
237 ent->s.skinnum = (ent - g_edicts - 1) | i;
238 }
239
240 if (ent->client->pers.weapon && ent->client->pers.weapon->ammo)
241 ent->client->ammo_index = ITEM_INDEX(FindItem(ent->client->pers.weapon->ammo));
242 else
243 ent->client->ammo_index = 0;
244
245 if (!ent->client->pers.weapon)
246 { // dead
247 ent->client->ps.gunindex = 0;
248 return;
249 }
250
251 ent->client->weaponstate = WEAPON_ACTIVATING;
252 ent->client->ps.gunframe = 0;
253 ent->client->ps.gunindex = gi.modelindex(ent->client->pers.weapon->view_model);
254
255 ent->client->anim_priority = ANIM_PAIN;
256 if(ent->client->ps.pmove.pm_flags & PMF_DUCKED)
257 {
258 ent->s.frame = FRAME_crpain1;
259 ent->client->anim_end = FRAME_crpain4;
260 }
261 else
262 {
263 ent->s.frame = FRAME_pain301;
264 ent->client->anim_end = FRAME_pain304;
265
266 }
267 }
268
269 /*
270 =================
271 NoAmmoWeaponChange
272 =================
273 */
274
275 // PMM - added rogue weapons to the list
276
NoAmmoWeaponChange(edict_t * ent)277 void NoAmmoWeaponChange (edict_t *ent)
278 {
279 if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("slugs"))]
280 && ent->client->pers.inventory[ITEM_INDEX(FindItem("railgun"))] )
281 {
282 ent->client->newweapon = FindItem ("railgun");
283 return;
284 }
285 // ROGUE
286 if ( (ent->client->pers.inventory[ITEM_INDEX(FindItem("cells"))] >= 2)
287 && ent->client->pers.inventory[ITEM_INDEX(FindItem("Plasma Beam"))] )
288 {
289 ent->client->newweapon = FindItem ("Plasma Beam");
290 return;
291 }
292 // -ROGUE
293 /*
294 if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("cells"))]
295 && ent->client->pers.inventory[ITEM_INDEX(FindItem("hyperblaster"))] )
296 {
297 ent->client->newweapon = FindItem ("hyperblaster");
298 return;
299 }
300 */
301 // ROGUE
302 if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("flechettes"))]
303 && ent->client->pers.inventory[ITEM_INDEX(FindItem("etf rifle"))] )
304 {
305 ent->client->newweapon = FindItem ("etf rifle");
306 return;
307 }
308 // -ROGUE
309 if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("bullets"))]
310 && ent->client->pers.inventory[ITEM_INDEX(FindItem("chaingun"))] )
311 {
312 ent->client->newweapon = FindItem ("chaingun");
313 return;
314 }
315 if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("bullets"))]
316 && ent->client->pers.inventory[ITEM_INDEX(FindItem("machinegun"))] )
317 {
318 ent->client->newweapon = FindItem ("machinegun");
319 return;
320 }
321 if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("shells"))] > 1
322 && ent->client->pers.inventory[ITEM_INDEX(FindItem("super shotgun"))] )
323 {
324 ent->client->newweapon = FindItem ("super shotgun");
325 return;
326 }
327 if ( ent->client->pers.inventory[ITEM_INDEX(FindItem("shells"))]
328 && ent->client->pers.inventory[ITEM_INDEX(FindItem("shotgun"))] )
329 {
330 ent->client->newweapon = FindItem ("shotgun");
331 return;
332 }
333 ent->client->newweapon = FindItem ("blaster");
334 }
335
336 /*
337 =================
338 Think_Weapon
339
340 Called by ClientBeginServerFrame and ClientThink
341 =================
342 */
Think_Weapon(edict_t * ent)343 void Think_Weapon (edict_t *ent)
344 {
345 // if just died, put the weapon away
346 if (ent->health < 1)
347 {
348 ent->client->newweapon = NULL;
349 ChangeWeapon (ent);
350 }
351
352 // call active weapon think routine
353 if (ent->client->pers.weapon && ent->client->pers.weapon->weaponthink)
354 {
355 //PGM
356 P_DamageModifier(ent);
357 // is_quad = (ent->client->quad_framenum > level.framenum);
358 //PGM
359 if (ent->client->silencer_shots)
360 is_silenced = MZ_SILENCED;
361 else
362 is_silenced = 0;
363 ent->client->pers.weapon->weaponthink (ent);
364 }
365 }
366
367
368 /*
369 ================
370 Use_Weapon
371
372 Make the weapon ready if there is ammo
373 ================
374 */
Use_Weapon(edict_t * ent,gitem_t * item)375 void Use_Weapon (edict_t *ent, gitem_t *item)
376 {
377 int ammo_index;
378 gitem_t *ammo_item;
379
380 // see if we're already using it
381 if (item == ent->client->pers.weapon)
382 return;
383
384 if (item->ammo && !g_select_empty->value && !(item->flags & IT_AMMO))
385 {
386 ammo_item = FindItem(item->ammo);
387 ammo_index = ITEM_INDEX(ammo_item);
388
389 if (!ent->client->pers.inventory[ammo_index])
390 {
391 #ifdef WITH_ACEBOT
392 safe_cprintf
393 #else
394 gi.cprintf
395 #endif
396 (ent, PRINT_HIGH, "No %s for %s.\n", ammo_item->pickup_name, item->pickup_name);
397 return;
398 }
399
400 if (ent->client->pers.inventory[ammo_index] < item->quantity)
401 {
402 #ifdef WITH_ACEBOT
403 safe_cprintf
404 #else
405 gi.cprintf
406 #endif
407 (ent, PRINT_HIGH, "Not enough %s for %s.\n", ammo_item->pickup_name, item->pickup_name);
408 return;
409 }
410 }
411
412 // change to this weapon when down
413 ent->client->newweapon = item;
414 }
415
416
417
418 /*
419 ================
420 Drop_Weapon
421 ================
422 */
Drop_Weapon(edict_t * ent,gitem_t * item)423 void Drop_Weapon (edict_t *ent, gitem_t *item)
424 {
425 int index;
426
427 if ((int)(dmflags->value) & DF_WEAPONS_STAY)
428 return;
429
430 index = ITEM_INDEX(item);
431 // see if we're already using it
432 if ( ((item == ent->client->pers.weapon) || (item == ent->client->newweapon))&& (ent->client->pers.inventory[index] == 1) )
433 {
434 #ifdef WITH_ACEBOT
435 safe_cprintf
436 #else
437 gi.cprintf
438 #endif
439 (ent, PRINT_HIGH, "Can't drop current weapon\n");
440 return;
441 }
442
443 Drop_Item (ent, item);
444 ent->client->pers.inventory[index]--;
445 }
446
447
448 /*
449 ================
450 Weapon_Generic
451
452 A generic function to handle the basics of weapon thinking
453 ================
454 */
455 #define FRAME_FIRE_FIRST (FRAME_ACTIVATE_LAST + 1)
456 #define FRAME_IDLE_FIRST (FRAME_FIRE_LAST + 1)
457 #define FRAME_DEACTIVATE_FIRST (FRAME_IDLE_LAST + 1)
458
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))459 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))
460 {
461 int n;
462
463 if(ent->deadflag || ent->s.modelindex != 255) // VWep animations screw up corpses
464 {
465 return;
466 }
467
468 if (ent->client->weaponstate == WEAPON_DROPPING)
469 {
470 if (ent->client->ps.gunframe == FRAME_DEACTIVATE_LAST)
471 {
472 ChangeWeapon (ent);
473 return;
474 }
475 else if ((FRAME_DEACTIVATE_LAST - ent->client->ps.gunframe) == 4)
476 {
477 ent->client->anim_priority = ANIM_REVERSE;
478 if(ent->client->ps.pmove.pm_flags & PMF_DUCKED)
479 {
480 ent->s.frame = FRAME_crpain4+1;
481 ent->client->anim_end = FRAME_crpain1;
482 }
483 else
484 {
485 ent->s.frame = FRAME_pain304+1;
486 ent->client->anim_end = FRAME_pain301;
487
488 }
489 }
490
491 ent->client->ps.gunframe++;
492 return;
493 }
494
495 if (ent->client->weaponstate == WEAPON_ACTIVATING)
496 {
497 if (ent->client->ps.gunframe == FRAME_ACTIVATE_LAST)
498 {
499 ent->client->weaponstate = WEAPON_READY;
500 ent->client->ps.gunframe = FRAME_IDLE_FIRST;
501 return;
502 }
503
504 ent->client->ps.gunframe++;
505 return;
506 }
507
508 if ((ent->client->newweapon) && (ent->client->weaponstate != WEAPON_FIRING))
509 {
510 ent->client->weaponstate = WEAPON_DROPPING;
511 ent->client->ps.gunframe = FRAME_DEACTIVATE_FIRST;
512
513 if ((FRAME_DEACTIVATE_LAST - FRAME_DEACTIVATE_FIRST) < 4)
514 {
515 ent->client->anim_priority = ANIM_REVERSE;
516 if(ent->client->ps.pmove.pm_flags & PMF_DUCKED)
517 {
518 ent->s.frame = FRAME_crpain4+1;
519 ent->client->anim_end = FRAME_crpain1;
520 }
521 else
522 {
523 ent->s.frame = FRAME_pain304+1;
524 ent->client->anim_end = FRAME_pain301;
525
526 }
527 }
528 return;
529 }
530
531 if (ent->client->weaponstate == WEAPON_READY)
532 {
533 if ( ((ent->client->latched_buttons|ent->client->buttons) & BUTTON_ATTACK) )
534 {
535 ent->client->latched_buttons &= ~BUTTON_ATTACK;
536 if ((!ent->client->ammo_index) ||
537 ( ent->client->pers.inventory[ent->client->ammo_index] >= ent->client->pers.weapon->quantity))
538 {
539 ent->client->ps.gunframe = FRAME_FIRE_FIRST;
540 ent->client->weaponstate = WEAPON_FIRING;
541
542 // start the animation
543 ent->client->anim_priority = ANIM_ATTACK;
544 if (ent->client->ps.pmove.pm_flags & PMF_DUCKED)
545 {
546 ent->s.frame = FRAME_crattak1-1;
547 ent->client->anim_end = FRAME_crattak9;
548 }
549 else
550 {
551 ent->s.frame = FRAME_attack1-1;
552 ent->client->anim_end = FRAME_attack8;
553 }
554 }
555 else
556 {
557 if (level.time >= ent->pain_debounce_time)
558 {
559 gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0);
560 ent->pain_debounce_time = level.time + 1;
561 }
562 NoAmmoWeaponChange (ent);
563 }
564 }
565 else
566 {
567 if (ent->client->ps.gunframe == FRAME_IDLE_LAST)
568 {
569 ent->client->ps.gunframe = FRAME_IDLE_FIRST;
570 return;
571 }
572
573 if (pause_frames)
574 {
575 for (n = 0; pause_frames[n]; n++)
576 {
577 if (ent->client->ps.gunframe == pause_frames[n])
578 {
579 if (rand()&15)
580 return;
581 }
582 }
583 }
584
585 ent->client->ps.gunframe++;
586 return;
587 }
588 }
589
590 if (ent->client->weaponstate == WEAPON_FIRING)
591 {
592 for (n = 0; fire_frames[n]; n++)
593 {
594 if (ent->client->ps.gunframe == fire_frames[n])
595 {
596 // FIXME - double should use different sound
597 if (ent->client->quad_framenum > level.framenum)
598 gi.sound(ent, CHAN_ITEM, gi.soundindex("items/damage3.wav"), 1, ATTN_NORM, 0);
599 else if (ent->client->double_framenum > level.framenum)
600 gi.sound(ent, CHAN_ITEM, gi.soundindex("misc/ddamage3.wav"), 1, ATTN_NORM, 0);
601
602 fire (ent);
603 break;
604 }
605 }
606
607 if (!fire_frames[n])
608 ent->client->ps.gunframe++;
609
610 if (ent->client->ps.gunframe == FRAME_IDLE_FIRST+1)
611 ent->client->weaponstate = WEAPON_READY;
612 }
613 }
614
615
616 /*
617 ======================================================================
618
619 GRENADE
620
621 ======================================================================
622 */
623
624 #define GRENADE_TIMER 3.0
625 #define GRENADE_MINSPEED 400
626 #define GRENADE_MAXSPEED 800
627
weapon_grenade_fire(edict_t * ent,qboolean held)628 void weapon_grenade_fire (edict_t *ent, qboolean held)
629 {
630 vec3_t offset;
631 vec3_t forward, right, up;
632 vec3_t start;
633 int damage = 125;
634 float timer;
635 int speed;
636 float radius;
637
638 radius = damage+40;
639 if (is_quad)
640 // damage *= 4;
641 damage *= damage_multiplier; // PGM
642
643 AngleVectors (ent->client->v_angle, forward, right, up);
644 if (ent->client->pers.weapon->tag == AMMO_TESLA)
645 {
646 // VectorSet(offset, 0, -12, ent->viewheight-26);
647 VectorSet(offset, 0, -4, ent->viewheight-22);
648 }
649 else
650 {
651 // VectorSet(offset, 8, 8, ent->viewheight-8);
652 VectorSet(offset, 2, 6, ent->viewheight-14);
653 }
654 P_ProjectSource2 (ent->client, ent->s.origin, offset, forward, right, up, start);
655
656 timer = ent->client->grenade_time - level.time;
657 speed = GRENADE_MINSPEED + (GRENADE_TIMER - timer) * ((GRENADE_MAXSPEED - GRENADE_MINSPEED) / GRENADE_TIMER);
658 if (speed > GRENADE_MAXSPEED)
659 speed = GRENADE_MAXSPEED;
660
661 // fire_grenade2 (ent, start, forward, damage, speed, timer, radius, held);
662
663 // ============
664 // PGM
665 switch(ent->client->pers.weapon->tag)
666 {
667 case AMMO_GRENADES:
668 fire_grenade2 (ent, start, forward, damage, speed, timer, radius, held);
669 break;
670 case AMMO_TESLA:
671 fire_tesla (ent, start, forward, damage_multiplier, speed);
672 break;
673 default:
674 fire_prox (ent, start, forward, damage_multiplier, speed);
675 break;
676 }
677 // PGM
678 // ============
679
680 if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
681 ent->client->pers.inventory[ent->client->ammo_index]--;
682
683 ent->client->grenade_time = level.time + 1.0;
684
685 if(ent->deadflag || ent->s.modelindex != 255) // VWep animations screw up corpses
686 {
687 return;
688 }
689
690 if (ent->health <= 0)
691 return;
692
693 if (ent->client->ps.pmove.pm_flags & PMF_DUCKED)
694 {
695 ent->client->anim_priority = ANIM_ATTACK;
696 ent->s.frame = FRAME_crattak1-1;
697 ent->client->anim_end = FRAME_crattak3;
698 }
699 else
700 {
701 ent->client->anim_priority = ANIM_REVERSE;
702 ent->s.frame = FRAME_wave08;
703 ent->client->anim_end = FRAME_wave01;
704 }
705 }
706 /*
707 void Weapon_Grenade (edict_t *ent)
708 {
709 if ((ent->client->newweapon) && (ent->client->weaponstate == WEAPON_READY))
710 {
711 ChangeWeapon (ent);
712 return;
713 }
714
715 if (ent->client->weaponstate == WEAPON_ACTIVATING)
716 {
717 ent->client->weaponstate = WEAPON_READY;
718 ent->client->ps.gunframe = 16;
719 return;
720 }
721
722 if (ent->client->weaponstate == WEAPON_READY)
723 {
724 if ( ((ent->client->latched_buttons|ent->client->buttons) & BUTTON_ATTACK) )
725 {
726 ent->client->latched_buttons &= ~BUTTON_ATTACK;
727 if (ent->client->pers.inventory[ent->client->ammo_index])
728 {
729 ent->client->ps.gunframe = 1;
730 ent->client->weaponstate = WEAPON_FIRING;
731 ent->client->grenade_time = 0;
732 }
733 else
734 {
735 if (level.time >= ent->pain_debounce_time)
736 {
737 gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0);
738 ent->pain_debounce_time = level.time + 1;
739 }
740 NoAmmoWeaponChange (ent);
741 }
742 return;
743 }
744
745 if ((ent->client->ps.gunframe == 29) || (ent->client->ps.gunframe == 34) || (ent->client->ps.gunframe == 39) || (ent->client->ps.gunframe == 48))
746 {
747 if (rand()&15)
748 return;
749 }
750
751 if (++ent->client->ps.gunframe > 48)
752 ent->client->ps.gunframe = 16;
753 return;
754 }
755
756 if (ent->client->weaponstate == WEAPON_FIRING)
757 {
758 if (ent->client->ps.gunframe == 5)
759 gi.sound(ent, CHAN_WEAPON, gi.soundindex("weapons/hgrena1b.wav"), 1, ATTN_NORM, 0);
760
761 if (ent->client->ps.gunframe == 11)
762 {
763 if (!ent->client->grenade_time)
764 {
765 ent->client->grenade_time = level.time + GRENADE_TIMER + 0.2;
766 ent->client->weapon_sound = gi.soundindex("weapons/hgrenc1b.wav");
767 }
768
769 // they waited too long, detonate it in their hand
770 if (!ent->client->grenade_blew_up && level.time >= ent->client->grenade_time)
771 {
772 ent->client->weapon_sound = 0;
773 weapon_grenade_fire (ent, true);
774 ent->client->grenade_blew_up = true;
775 }
776
777 if (ent->client->buttons & BUTTON_ATTACK)
778 return;
779
780 if (ent->client->grenade_blew_up)
781 {
782 if (level.time >= ent->client->grenade_time)
783 {
784 ent->client->ps.gunframe = 15;
785 ent->client->grenade_blew_up = false;
786 }
787 else
788 {
789 return;
790 }
791 }
792 }
793
794 if (ent->client->ps.gunframe == 12)
795 {
796 ent->client->weapon_sound = 0;
797 weapon_grenade_fire (ent, false);
798 }
799
800 if ((ent->client->ps.gunframe == 15) && (level.time < ent->client->grenade_time))
801 return;
802
803 ent->client->ps.gunframe++;
804
805 if (ent->client->ps.gunframe == 16)
806 {
807 ent->client->grenade_time = 0;
808 ent->client->weaponstate = WEAPON_READY;
809 }
810 }
811 }
812 */
813
814 #define FRAME_IDLE_FIRST (FRAME_FIRE_LAST + 1)
815
816 //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))
817 // 15 48 5 11 12 29,34,39,48
Throw_Generic(edict_t * ent,int FRAME_FIRE_LAST,int FRAME_IDLE_LAST,int FRAME_THROW_SOUND,int FRAME_THROW_HOLD,int FRAME_THROW_FIRE,int * pause_frames,int EXPLODE,void (* fire)(edict_t * ent,qboolean held))818 void Throw_Generic (edict_t *ent, int FRAME_FIRE_LAST, int FRAME_IDLE_LAST, int FRAME_THROW_SOUND,
819 int FRAME_THROW_HOLD, int FRAME_THROW_FIRE, int *pause_frames, int EXPLODE,
820 void (*fire)(edict_t *ent, qboolean held))
821 {
822 int n;
823
824 if ((ent->client->newweapon) && (ent->client->weaponstate == WEAPON_READY))
825 {
826 ChangeWeapon (ent);
827 return;
828 }
829
830 if (ent->client->weaponstate == WEAPON_ACTIVATING)
831 {
832 ent->client->weaponstate = WEAPON_READY;
833 ent->client->ps.gunframe = FRAME_IDLE_FIRST;
834 return;
835 }
836
837 if (ent->client->weaponstate == WEAPON_READY)
838 {
839 if ( ((ent->client->latched_buttons|ent->client->buttons) & BUTTON_ATTACK) )
840 {
841 ent->client->latched_buttons &= ~BUTTON_ATTACK;
842 if (ent->client->pers.inventory[ent->client->ammo_index])
843 {
844 ent->client->ps.gunframe = 1;
845 ent->client->weaponstate = WEAPON_FIRING;
846 ent->client->grenade_time = 0;
847 }
848 else
849 {
850 if (level.time >= ent->pain_debounce_time)
851 {
852 gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0);
853 ent->pain_debounce_time = level.time + 1;
854 }
855 NoAmmoWeaponChange (ent);
856 }
857 return;
858 }
859
860 if (ent->client->ps.gunframe == FRAME_IDLE_LAST)
861 {
862 ent->client->ps.gunframe = FRAME_IDLE_FIRST;
863 return;
864 }
865
866 if (pause_frames)
867 {
868 for (n = 0; pause_frames[n]; n++)
869 {
870 if (ent->client->ps.gunframe == pause_frames[n])
871 {
872 if (rand()&15)
873 return;
874 }
875 }
876 }
877
878 ent->client->ps.gunframe++;
879 return;
880 }
881
882 if (ent->client->weaponstate == WEAPON_FIRING)
883 {
884 if (ent->client->ps.gunframe == FRAME_THROW_SOUND)
885 gi.sound(ent, CHAN_WEAPON, gi.soundindex("weapons/hgrena1b.wav"), 1, ATTN_NORM, 0);
886
887 if (ent->client->ps.gunframe == FRAME_THROW_HOLD)
888 {
889 if (!ent->client->grenade_time)
890 {
891 ent->client->grenade_time = level.time + GRENADE_TIMER + 0.2;
892 switch(ent->client->pers.weapon->tag)
893 {
894 case AMMO_GRENADES:
895 ent->client->weapon_sound = gi.soundindex("weapons/hgrenc1b.wav");
896 break;
897 }
898 }
899
900 // they waited too long, detonate it in their hand
901 if (EXPLODE && !ent->client->grenade_blew_up && level.time >= ent->client->grenade_time)
902 {
903 ent->client->weapon_sound = 0;
904 fire (ent, true);
905 ent->client->grenade_blew_up = true;
906 }
907
908 if (ent->client->buttons & BUTTON_ATTACK)
909 return;
910
911 if (ent->client->grenade_blew_up)
912 {
913 if (level.time >= ent->client->grenade_time)
914 {
915 ent->client->ps.gunframe = FRAME_FIRE_LAST;
916 ent->client->grenade_blew_up = false;
917 }
918 else
919 {
920 return;
921 }
922 }
923 }
924
925 if (ent->client->ps.gunframe == FRAME_THROW_FIRE)
926 {
927 ent->client->weapon_sound = 0;
928 fire (ent, true);
929 }
930
931 if ((ent->client->ps.gunframe == FRAME_FIRE_LAST) && (level.time < ent->client->grenade_time))
932 return;
933
934 ent->client->ps.gunframe++;
935
936 if (ent->client->ps.gunframe == FRAME_IDLE_FIRST)
937 {
938 ent->client->grenade_time = 0;
939 ent->client->weaponstate = WEAPON_READY;
940 }
941 }
942 }
943
944 //void Throw_Generic (edict_t *ent, int FRAME_FIRE_LAST, int FRAME_IDLE_LAST, int FRAME_THROW_SOUND,
945 // int FRAME_THROW_HOLD, int FRAME_THROW_FIRE, int *pause_frames,
946 // int EXPLOSION_TIME, void (*fire)(edict_t *ent))
947
Weapon_Grenade(edict_t * ent)948 void Weapon_Grenade (edict_t *ent)
949 {
950 static int pause_frames[] = {29,34,39,48,0};
951
952 Throw_Generic (ent, 15, 48, 5, 11, 12, pause_frames, GRENADE_TIMER, weapon_grenade_fire);
953 }
954
Weapon_Prox(edict_t * ent)955 void Weapon_Prox (edict_t *ent)
956 {
957 static int pause_frames[] = {22, 29, 0};
958
959 Throw_Generic (ent, 7, 27, 99, 2, 4, pause_frames, 0, weapon_grenade_fire);
960 }
961
Weapon_Tesla(edict_t * ent)962 void Weapon_Tesla (edict_t *ent)
963 {
964 static int pause_frames[] = {21, 0};
965
966 if ((ent->client->ps.gunframe > 1) && (ent->client->ps.gunframe < 9))
967 {
968 ent->client->ps.gunindex = gi.modelindex ("models/weapons/v_tesla2/tris.md2");
969 }
970 else
971 {
972 ent->client->ps.gunindex = gi.modelindex ("models/weapons/v_tesla/tris.md2");
973 }
974
975 Throw_Generic (ent, 8, 32, 99, 1, 2, pause_frames, 0, weapon_grenade_fire);
976 }
977
978
979
980 /*
981 ======================================================================
982
983 GRENADE LAUNCHER
984
985 ======================================================================
986 */
987
weapon_grenadelauncher_fire(edict_t * ent)988 void weapon_grenadelauncher_fire (edict_t *ent)
989 {
990 vec3_t offset;
991 vec3_t forward, right;
992 vec3_t start;
993 // int damage = 120;
994 int damage; // PGM
995 float radius;
996
997 // =====
998 // PGM
999 switch(ent->client->pers.weapon->tag)
1000 {
1001 case AMMO_PROX:
1002 damage = 90;
1003 break;
1004 default:
1005 damage = 120;
1006 break;
1007 }
1008 // PGM
1009 // =====
1010
1011 radius = damage+40;
1012 if (is_quad)
1013 // damage *= 4;
1014 damage *= damage_multiplier; //pgm
1015
1016 VectorSet(offset, 8, 8, ent->viewheight-8);
1017 AngleVectors (ent->client->v_angle, forward, right, NULL);
1018 P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
1019
1020 VectorScale (forward, -2, ent->client->kick_origin);
1021 ent->client->kick_angles[0] = -1;
1022
1023 // fire_grenade (ent, start, forward, damage, 600, 2.5, radius);
1024 // =====
1025 // PGM
1026 switch(ent->client->pers.weapon->tag)
1027 {
1028 case AMMO_PROX:
1029 fire_prox (ent, start, forward, damage_multiplier, 600);
1030 break;
1031 default:
1032 fire_grenade (ent, start, forward, damage, 600, 2.5, radius);
1033 break;
1034 }
1035 // PGM
1036 // =====
1037
1038 gi.WriteByte (svc_muzzleflash);
1039 gi.WriteShort (ent-g_edicts);
1040 gi.WriteByte (MZ_GRENADE | is_silenced);
1041 gi.multicast (ent->s.origin, MULTICAST_PVS);
1042
1043 ent->client->ps.gunframe++;
1044
1045 PlayerNoise(ent, start, PNOISE_WEAPON);
1046
1047 if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
1048 ent->client->pers.inventory[ent->client->ammo_index]--;
1049 }
1050
Weapon_GrenadeLauncher(edict_t * ent)1051 void Weapon_GrenadeLauncher (edict_t *ent)
1052 {
1053 static int pause_frames[] = {34, 51, 59, 0};
1054 static int fire_frames[] = {6, 0};
1055
1056 Weapon_Generic (ent, 5, 16, 59, 64, pause_frames, fire_frames, weapon_grenadelauncher_fire);
1057 }
1058
1059 //==========
1060 //PGM
Weapon_ProxLauncher(edict_t * ent)1061 void Weapon_ProxLauncher (edict_t *ent)
1062 {
1063 static int pause_frames[] = {34, 51, 59, 0};
1064 static int fire_frames[] = {6, 0};
1065
1066 Weapon_Generic (ent, 5, 16, 59, 64, pause_frames, fire_frames, weapon_grenadelauncher_fire);
1067 }
1068 //PGM
1069 //==========
1070
1071 /*
1072 ======================================================================
1073
1074 ROCKET
1075
1076 ======================================================================
1077 */
1078
Weapon_RocketLauncher_Fire(edict_t * ent)1079 void Weapon_RocketLauncher_Fire (edict_t *ent)
1080 {
1081 vec3_t offset, start;
1082 vec3_t forward, right;
1083 int damage;
1084 float damage_radius;
1085 int radius_damage;
1086
1087 damage = 100 + (int)(random() * 20.0);
1088 radius_damage = 120;
1089 damage_radius = 120;
1090 if (is_quad)
1091 {
1092 //PGM
1093 // damage *= 4;
1094 damage *= damage_multiplier;
1095 // radius_damage *= 4;
1096 radius_damage *= damage_multiplier;
1097 //PGM
1098 }
1099
1100 AngleVectors (ent->client->v_angle, forward, right, NULL);
1101
1102 VectorScale (forward, -2, ent->client->kick_origin);
1103 ent->client->kick_angles[0] = -1;
1104
1105 VectorSet(offset, 8, 8, ent->viewheight-8);
1106 P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
1107 fire_rocket (ent, start, forward, damage, 650, damage_radius, radius_damage);
1108
1109 // send muzzle flash
1110 gi.WriteByte (svc_muzzleflash);
1111 gi.WriteShort (ent-g_edicts);
1112 gi.WriteByte (MZ_ROCKET | is_silenced);
1113 gi.multicast (ent->s.origin, MULTICAST_PVS);
1114
1115 ent->client->ps.gunframe++;
1116
1117 PlayerNoise(ent, start, PNOISE_WEAPON);
1118
1119 if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
1120 ent->client->pers.inventory[ent->client->ammo_index]--;
1121 }
1122
Weapon_RocketLauncher(edict_t * ent)1123 void Weapon_RocketLauncher (edict_t *ent)
1124 {
1125 static int pause_frames[] = {25, 33, 42, 50, 0};
1126 static int fire_frames[] = {5, 0};
1127
1128 Weapon_Generic (ent, 4, 12, 50, 54, pause_frames, fire_frames, Weapon_RocketLauncher_Fire);
1129 }
1130
1131
1132 /*
1133 ======================================================================
1134
1135 BLASTER / HYPERBLASTER
1136
1137 ======================================================================
1138 */
1139
Blaster_Fire(edict_t * ent,vec3_t g_offset,int damage,qboolean hyper,int effect)1140 void Blaster_Fire (edict_t *ent, vec3_t g_offset, int damage, qboolean hyper, int effect)
1141 {
1142 vec3_t forward, right;
1143 vec3_t start;
1144 vec3_t offset;
1145
1146 if (is_quad)
1147 // damage *= 4;
1148 damage *= damage_multiplier; //pgm
1149
1150 AngleVectors (ent->client->v_angle, forward, right, NULL);
1151 VectorSet(offset, 24, 8, ent->viewheight-8);
1152 VectorAdd (offset, g_offset, offset);
1153 P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
1154
1155 VectorScale (forward, -2, ent->client->kick_origin);
1156 ent->client->kick_angles[0] = -1;
1157
1158 fire_blaster (ent, start, forward, damage, 1000, effect, hyper);
1159
1160 // send muzzle flash
1161 gi.WriteByte (svc_muzzleflash);
1162 gi.WriteShort (ent-g_edicts);
1163 if (hyper)
1164 gi.WriteByte (MZ_HYPERBLASTER | is_silenced);
1165 else
1166 gi.WriteByte (MZ_BLASTER | is_silenced);
1167 gi.multicast (ent->s.origin, MULTICAST_PVS);
1168
1169 PlayerNoise(ent, start, PNOISE_WEAPON);
1170 }
1171
1172
Weapon_Blaster_Fire(edict_t * ent)1173 void Weapon_Blaster_Fire (edict_t *ent)
1174 {
1175 int damage;
1176
1177 if (deathmatch->value)
1178 damage = 15;
1179 else
1180 damage = 10;
1181 Blaster_Fire (ent, vec3_origin, damage, false, EF_BLASTER);
1182 ent->client->ps.gunframe++;
1183 }
1184
Weapon_Blaster(edict_t * ent)1185 void Weapon_Blaster (edict_t *ent)
1186 {
1187 static int pause_frames[] = {19, 32, 0};
1188 static int fire_frames[] = {5, 0};
1189
1190 Weapon_Generic (ent, 4, 8, 52, 55, pause_frames, fire_frames, Weapon_Blaster_Fire);
1191 }
1192
1193
Weapon_HyperBlaster_Fire(edict_t * ent)1194 void Weapon_HyperBlaster_Fire (edict_t *ent)
1195 {
1196 float rotation;
1197 vec3_t offset;
1198 int effect;
1199 int damage;
1200
1201 ent->client->weapon_sound = gi.soundindex("weapons/hyprbl1a.wav");
1202
1203 if (!(ent->client->buttons & BUTTON_ATTACK))
1204 {
1205 ent->client->ps.gunframe++;
1206 }
1207 else
1208 {
1209 if (! ent->client->pers.inventory[ent->client->ammo_index] )
1210 {
1211 if (level.time >= ent->pain_debounce_time)
1212 {
1213 gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0);
1214 ent->pain_debounce_time = level.time + 1;
1215 }
1216 NoAmmoWeaponChange (ent);
1217 }
1218 else
1219 {
1220 rotation = (ent->client->ps.gunframe - 5) * 2*M_PI/6;
1221 offset[0] = -4 * sin(rotation);
1222 offset[1] = 0;
1223 offset[2] = 4 * cos(rotation);
1224
1225 if ((ent->client->ps.gunframe == 6) || (ent->client->ps.gunframe == 9))
1226 effect = EF_HYPERBLASTER;
1227 else
1228 effect = 0;
1229 if (deathmatch->value)
1230 damage = 15;
1231 else
1232 damage = 20;
1233 Blaster_Fire (ent, offset, damage, true, effect);
1234 if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
1235 ent->client->pers.inventory[ent->client->ammo_index]--;
1236
1237 ent->client->anim_priority = ANIM_ATTACK;
1238 if (ent->client->ps.pmove.pm_flags & PMF_DUCKED)
1239 {
1240 ent->s.frame = FRAME_crattak1 - 1;
1241 ent->client->anim_end = FRAME_crattak9;
1242 }
1243 else
1244 {
1245 ent->s.frame = FRAME_attack1 - 1;
1246 ent->client->anim_end = FRAME_attack8;
1247 }
1248 }
1249
1250 ent->client->ps.gunframe++;
1251 if (ent->client->ps.gunframe == 12 && ent->client->pers.inventory[ent->client->ammo_index])
1252 ent->client->ps.gunframe = 6;
1253 }
1254
1255 if (ent->client->ps.gunframe == 12)
1256 {
1257 gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/hyprbd1a.wav"), 1, ATTN_NORM, 0);
1258 ent->client->weapon_sound = 0;
1259 }
1260
1261 }
1262
Weapon_HyperBlaster(edict_t * ent)1263 void Weapon_HyperBlaster (edict_t *ent)
1264 {
1265 static int pause_frames[] = {0};
1266 static int fire_frames[] = {6, 7, 8, 9, 10, 11, 0};
1267
1268 Weapon_Generic (ent, 5, 20, 49, 53, pause_frames, fire_frames, Weapon_HyperBlaster_Fire);
1269 }
1270
1271
1272 #ifdef GAME_MOD
Extr_Shell_Touch(edict_t * self,edict_t * other,cplane_t * plane,csurface_t * surf)1273 void Extr_Shell_Touch(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
1274 {
1275 gi.sound(self, CHAN_VOICE, gi.soundindex("misc/brass_shell.wav"), 1, ATTN_NORM, 0);
1276 self->solid = SOLID_NOT;
1277 }
1278
1279
1280
Extr_Shell(edict_t * self,char * modelname,vec3_t start,vec3_t aimdir,int speed,vec3_t velocity,char * kierunek)1281 void Extr_Shell (edict_t *self, char *modelname, vec3_t start, vec3_t aimdir, int speed, vec3_t velocity, char *kierunek)
1282 {
1283 edict_t *Extr_Shell;
1284 vec3_t dir;
1285 vec3_t forward, right, up;
1286
1287 if (deathmatch->value || coop->value) {
1288 if (!eject_bullets_dm_coop->value)
1289 return;
1290 }
1291
1292 vectoangles (aimdir, dir);
1293 AngleVectors (dir, forward, right, up);
1294
1295 Extr_Shell = G_Spawn();
1296
1297 VectorCopy (start, Extr_Shell->s.origin);
1298 VectorCopy (aimdir, Extr_Shell->movedir);
1299 VectorCopy (velocity, Extr_Shell->velocity);
1300 vectoangles (aimdir, Extr_Shell->s.angles);
1301 VectorMA (Extr_Shell->velocity, 120 + random()*20, up, Extr_Shell->velocity);
1302
1303 if (!stricmp(kierunek, "right"))
1304 VectorMA (Extr_Shell->velocity, -80 - random()*20, right, Extr_Shell->velocity);
1305 else
1306 VectorMA (Extr_Shell->velocity, 80 + random()*20, right, Extr_Shell->velocity);
1307
1308 Extr_Shell->avelocity[0] = random()*600;
1309 Extr_Shell->avelocity[1] = random()*600;
1310 Extr_Shell->avelocity[2] = random()*600;
1311 gi.setmodel (Extr_Shell, modelname);
1312
1313 Extr_Shell->movetype = MOVETYPE_BOUNCE;
1314 Extr_Shell->clipmask = MASK_SHOT;
1315 Extr_Shell->solid = SOLID_BBOX;
1316 Extr_Shell->owner = self;
1317
1318 VectorSet(Extr_Shell->mins, -1.5, -0.6, -0.55);
1319 VectorSet(Extr_Shell->maxs, 1.5, 0.6, 0.55);
1320
1321 Extr_Shell->nextthink = level.time + 25 + random()*1;
1322 Extr_Shell->think = G_FreeEdict;
1323 Extr_Shell->touch = Extr_Shell_Touch;
1324 Extr_Shell->classname = "Extr_Shell";
1325 gi.linkentity (Extr_Shell);
1326 }
1327 #endif
1328
1329 /*
1330 ======================================================================
1331
1332 MACHINEGUN / CHAINGUN
1333
1334 ======================================================================
1335 */
1336
Machinegun_Fire(edict_t * ent)1337 void Machinegun_Fire (edict_t *ent)
1338 {
1339 int i;
1340 vec3_t start;
1341 vec3_t forward, right;
1342 vec3_t angles;
1343 int damage = 8;
1344 int kick = 2;
1345 vec3_t offset;
1346 #ifdef GAME_MOD
1347 vec3_t start_shell, forward_shell, left_shell, offset_shell;
1348 #endif
1349 if (!(ent->client->buttons & BUTTON_ATTACK))
1350 {
1351 ent->client->machinegun_shots = 0;
1352 ent->client->ps.gunframe++;
1353 return;
1354 }
1355
1356 if (ent->client->ps.gunframe == 5)
1357 ent->client->ps.gunframe = 4;
1358 else
1359 ent->client->ps.gunframe = 5;
1360
1361 if (ent->client->pers.inventory[ent->client->ammo_index] < 1)
1362 {
1363 ent->client->ps.gunframe = 6;
1364 if (level.time >= ent->pain_debounce_time)
1365 {
1366 gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0);
1367 ent->pain_debounce_time = level.time + 1;
1368 }
1369 NoAmmoWeaponChange (ent);
1370 return;
1371 }
1372
1373 if (is_quad)
1374 {
1375 //PGM
1376 // damage *= 4;
1377 damage *= damage_multiplier;
1378 // kick *= 4;
1379 kick *= damage_multiplier;
1380 //PGM
1381 }
1382
1383 for (i=1 ; i<3 ; i++)
1384 {
1385 ent->client->kick_origin[i] = crandom() * 0.35;
1386 ent->client->kick_angles[i] = crandom() * 0.7;
1387 }
1388 ent->client->kick_origin[0] = crandom() * 0.35;
1389 ent->client->kick_angles[0] = ent->client->machinegun_shots * -1.5;
1390
1391 // raise the gun as it is firing
1392 if (!deathmatch->value)
1393 {
1394 ent->client->machinegun_shots++;
1395 if (ent->client->machinegun_shots > 9)
1396 ent->client->machinegun_shots = 9;
1397 }
1398
1399 #ifdef GAME_MOD
1400 if (eject_bullets->value) {
1401 VectorSet(offset_shell, 12, 8.7, ent->viewheight-3.2);
1402 AngleVectors (ent->client->v_angle, forward_shell, left_shell, NULL);
1403 P_ProjectSource (ent->client, ent->s.origin, offset_shell, forward_shell, left_shell, start_shell);
1404 VectorScale (forward_shell, -2, ent->client->kick_origin);
1405 Extr_Shell (ent, "models/shells/m_shell.md2", start_shell, forward_shell, 2, ent->velocity, "leftt");
1406 }
1407 #endif
1408 // get start / end positions
1409 VectorAdd (ent->client->v_angle, ent->client->kick_angles, angles);
1410 AngleVectors (angles, forward, right, NULL);
1411 VectorSet(offset, 0, 8, ent->viewheight-8);
1412 P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
1413 fire_bullet (ent, start, forward, damage, kick, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, MOD_MACHINEGUN);
1414
1415 gi.WriteByte (svc_muzzleflash);
1416 gi.WriteShort (ent-g_edicts);
1417 gi.WriteByte (MZ_MACHINEGUN | is_silenced);
1418 gi.multicast (ent->s.origin, MULTICAST_PVS);
1419
1420 PlayerNoise(ent, start, PNOISE_WEAPON);
1421
1422 if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
1423 ent->client->pers.inventory[ent->client->ammo_index]--;
1424
1425 ent->client->anim_priority = ANIM_ATTACK;
1426 if (ent->client->ps.pmove.pm_flags & PMF_DUCKED)
1427 {
1428 ent->s.frame = FRAME_crattak1 - (int) (random()+0.25);
1429 ent->client->anim_end = FRAME_crattak9;
1430 }
1431 else
1432 {
1433 ent->s.frame = FRAME_attack1 - (int) (random()+0.25);
1434 ent->client->anim_end = FRAME_attack8;
1435 }
1436 }
1437
Weapon_Machinegun(edict_t * ent)1438 void Weapon_Machinegun (edict_t *ent)
1439 {
1440 static int pause_frames[] = {23, 45, 0};
1441 static int fire_frames[] = {4, 5, 0};
1442
1443 Weapon_Generic (ent, 3, 5, 45, 49, pause_frames, fire_frames, Machinegun_Fire);
1444 }
1445
Chaingun_Fire(edict_t * ent)1446 void Chaingun_Fire (edict_t *ent)
1447 {
1448 int i;
1449 int shots;
1450 vec3_t start;
1451 vec3_t forward, right, up;
1452 float r, u;
1453 vec3_t offset;
1454 int damage;
1455 int kick = 2;
1456 #ifdef GAME_MOD
1457 vec3_t start_shell, forward_shell, left_shell, offset_shell;
1458 #endif
1459 if (deathmatch->value)
1460 damage = 6;
1461 else
1462 damage = 8;
1463
1464 if (ent->client->ps.gunframe == 5)
1465 gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/chngnu1a.wav"), 1, ATTN_IDLE, 0);
1466
1467 if ((ent->client->ps.gunframe == 14) && !(ent->client->buttons & BUTTON_ATTACK))
1468 {
1469 ent->client->ps.gunframe = 32;
1470 ent->client->weapon_sound = 0;
1471 return;
1472 }
1473 else if ((ent->client->ps.gunframe == 21) && (ent->client->buttons & BUTTON_ATTACK)
1474 && ent->client->pers.inventory[ent->client->ammo_index])
1475 {
1476 ent->client->ps.gunframe = 15;
1477 }
1478 else
1479 {
1480 ent->client->ps.gunframe++;
1481 }
1482
1483 if (ent->client->ps.gunframe == 22)
1484 {
1485 ent->client->weapon_sound = 0;
1486 gi.sound(ent, CHAN_AUTO, gi.soundindex("weapons/chngnd1a.wav"), 1, ATTN_IDLE, 0);
1487 }
1488 else
1489 {
1490 ent->client->weapon_sound = gi.soundindex("weapons/chngnl1a.wav");
1491 }
1492
1493 ent->client->anim_priority = ANIM_ATTACK;
1494 if (ent->client->ps.pmove.pm_flags & PMF_DUCKED)
1495 {
1496 ent->s.frame = FRAME_crattak1 - (ent->client->ps.gunframe & 1);
1497 ent->client->anim_end = FRAME_crattak9;
1498 }
1499 else
1500 {
1501 ent->s.frame = FRAME_attack1 - (ent->client->ps.gunframe & 1);
1502 ent->client->anim_end = FRAME_attack8;
1503 }
1504
1505 if (ent->client->ps.gunframe <= 9)
1506 shots = 1;
1507 else if (ent->client->ps.gunframe <= 14)
1508 {
1509 if (ent->client->buttons & BUTTON_ATTACK)
1510 shots = 2;
1511 else
1512 shots = 1;
1513 }
1514 else
1515 shots = 3;
1516
1517 if (ent->client->pers.inventory[ent->client->ammo_index] < shots)
1518 shots = ent->client->pers.inventory[ent->client->ammo_index];
1519
1520 if (!shots)
1521 {
1522 if (level.time >= ent->pain_debounce_time)
1523 {
1524 gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0);
1525 ent->pain_debounce_time = level.time + 1;
1526 }
1527 NoAmmoWeaponChange (ent);
1528 return;
1529 }
1530
1531 if (is_quad)
1532 {
1533 //PGM
1534 // damage *= 4;
1535 damage *= damage_multiplier;
1536 // kick *= 4;
1537 kick *= damage_multiplier;
1538 //PGM
1539 }
1540
1541 for (i=0 ; i<3 ; i++)
1542 {
1543 ent->client->kick_origin[i] = crandom() * 0.35;
1544 ent->client->kick_angles[i] = crandom() * 0.7;
1545 }
1546
1547 #ifdef GAME_MOD
1548 if (eject_bullets->value) {
1549 VectorSet(offset_shell, 12, 8.7, ent->viewheight-3.2);
1550 AngleVectors (ent->client->v_angle, forward_shell, left_shell, NULL);
1551 P_ProjectSource (ent->client, ent->s.origin, offset_shell, forward_shell, left_shell, start_shell);
1552 VectorScale (forward_shell, 2, ent->client->kick_origin);
1553 Extr_Shell (ent, "models/shells/m_shell.md2", start_shell, forward_shell, 2, ent->velocity, "left");
1554 }
1555 #endif
1556 for (i=0 ; i<shots ; i++)
1557 {
1558 // get start / end positions
1559 AngleVectors (ent->client->v_angle, forward, right, up);
1560 r = 7 + crandom()*4;
1561 u = crandom()*4;
1562 VectorSet(offset, 0, r, u + ent->viewheight-8);
1563 P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
1564
1565 fire_bullet (ent, start, forward, damage, kick, DEFAULT_BULLET_HSPREAD, DEFAULT_BULLET_VSPREAD, MOD_CHAINGUN);
1566 }
1567
1568 // send muzzle flash
1569 gi.WriteByte (svc_muzzleflash);
1570 gi.WriteShort (ent-g_edicts);
1571 gi.WriteByte ((MZ_CHAINGUN1 + shots - 1) | is_silenced);
1572 gi.multicast (ent->s.origin, MULTICAST_PVS);
1573
1574 PlayerNoise(ent, start, PNOISE_WEAPON);
1575
1576 if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
1577 ent->client->pers.inventory[ent->client->ammo_index] -= shots;
1578 }
1579
1580
Weapon_Chaingun(edict_t * ent)1581 void Weapon_Chaingun (edict_t *ent)
1582 {
1583 static int pause_frames[] = {38, 43, 51, 61, 0};
1584 static int fire_frames[] = {5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 0};
1585
1586 Weapon_Generic (ent, 4, 31, 61, 64, pause_frames, fire_frames, Chaingun_Fire);
1587 }
1588
1589
1590 /*
1591 ======================================================================
1592
1593 SHOTGUN / SUPERSHOTGUN
1594
1595 ======================================================================
1596 */
1597
weapon_shotgun_fire(edict_t * ent)1598 void weapon_shotgun_fire (edict_t *ent)
1599 {
1600 vec3_t start;
1601 vec3_t forward, right;
1602 vec3_t offset;
1603 int damage = 4;
1604 int kick = 8;
1605 #ifdef GAME_MOD
1606 vec3_t start_shell, forward_shell, left_shell, offset_shell;
1607 #endif
1608 if (ent->client->ps.gunframe == 9)
1609 {
1610 ent->client->ps.gunframe++;
1611 return;
1612 }
1613
1614 AngleVectors (ent->client->v_angle, forward, right, NULL);
1615
1616 VectorScale (forward, -2, ent->client->kick_origin);
1617 ent->client->kick_angles[0] = -2;
1618
1619 VectorSet(offset, 0, 8, ent->viewheight-8);
1620 P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
1621
1622 #ifdef GAME_MOD
1623 if (eject_bullets->value) {
1624 VectorSet(offset_shell, 12, 8.7, ent->viewheight-3.2);
1625 AngleVectors (ent->client->v_angle, forward_shell, left_shell, NULL);
1626 P_ProjectSource (ent->client, ent->s.origin, offset_shell, forward_shell, left_shell, start_shell);
1627 VectorScale (forward_shell, -2, ent->client->kick_origin);
1628 Extr_Shell (ent, "models/shells/s_shell.md2", start_shell, forward_shell, 2, ent->velocity, "right");
1629 }
1630 #endif
1631 if (is_quad)
1632 {
1633 //PGM
1634 // damage *= 4;
1635 damage *= damage_multiplier;
1636 // kick *= 4;
1637 kick *= damage_multiplier;
1638 //PGM
1639 }
1640
1641 if (deathmatch->value)
1642 fire_shotgun (ent, start, forward, damage, kick, 500, 500, DEFAULT_DEATHMATCH_SHOTGUN_COUNT, MOD_SHOTGUN);
1643 else
1644 fire_shotgun (ent, start, forward, damage, kick, 500, 500, DEFAULT_SHOTGUN_COUNT, MOD_SHOTGUN);
1645
1646 // send muzzle flash
1647 gi.WriteByte (svc_muzzleflash);
1648 gi.WriteShort (ent-g_edicts);
1649 gi.WriteByte (MZ_SHOTGUN | is_silenced);
1650 gi.multicast (ent->s.origin, MULTICAST_PVS);
1651
1652 ent->client->ps.gunframe++;
1653 PlayerNoise(ent, start, PNOISE_WEAPON);
1654
1655 if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
1656 ent->client->pers.inventory[ent->client->ammo_index]--;
1657 }
1658
Weapon_Shotgun(edict_t * ent)1659 void Weapon_Shotgun (edict_t *ent)
1660 {
1661 static int pause_frames[] = {22, 28, 34, 0};
1662 static int fire_frames[] = {8, 9, 0};
1663
1664 Weapon_Generic (ent, 7, 18, 36, 39, pause_frames, fire_frames, weapon_shotgun_fire);
1665 }
1666
1667
weapon_supershotgun_fire(edict_t * ent)1668 void weapon_supershotgun_fire (edict_t *ent)
1669 {
1670 vec3_t start;
1671 vec3_t forward, right;
1672 vec3_t offset;
1673 vec3_t v;
1674 int damage = 6;
1675 int kick = 12;
1676 #ifdef GAME_MOD
1677 vec3_t start_shell, forward_shell, left_shell, offset_shell;
1678 #endif
1679 AngleVectors (ent->client->v_angle, forward, right, NULL);
1680
1681 VectorScale (forward, -2, ent->client->kick_origin);
1682 ent->client->kick_angles[0] = -2;
1683
1684 VectorSet(offset, 0, 8, ent->viewheight-8);
1685 P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
1686
1687 if (is_quad)
1688 {
1689 //PGM
1690 // damage *= 4;
1691 damage *= damage_multiplier;
1692 // kick *= 4;
1693 kick *= damage_multiplier;
1694 //PGM
1695 }
1696
1697 #ifdef GAME_MOD
1698 if (eject_bullets->value) {
1699 VectorSet(offset_shell, 12, 8.7, ent->viewheight-3.2);
1700 AngleVectors (ent->client->v_angle, forward_shell, left_shell, NULL);
1701 P_ProjectSource (ent->client, ent->s.origin, offset_shell, forward_shell, left_shell, start_shell);
1702 VectorScale (forward_shell, -2, ent->client->kick_origin);
1703 Extr_Shell (ent, "models/shells/s_shell.md2", start_shell, forward_shell, 2, ent->velocity, "right");
1704
1705
1706 VectorSet(offset_shell, 15, 10.9, ent->viewheight-5.4);
1707 AngleVectors (ent->client->v_angle, forward_shell, left_shell, NULL);
1708 P_ProjectSource (ent->client, ent->s.origin, offset_shell, forward_shell, left_shell, start_shell);
1709 VectorScale (forward_shell, 0, ent->client->kick_origin);
1710 Extr_Shell (ent, "models/shells/s_shell.md2", start_shell, forward_shell, 4, ent->velocity, "right");
1711 }
1712 #endif
1713 v[PITCH] = ent->client->v_angle[PITCH];
1714 v[YAW] = ent->client->v_angle[YAW] - 5;
1715 v[ROLL] = ent->client->v_angle[ROLL];
1716 AngleVectors (v, forward, NULL, NULL);
1717 fire_shotgun (ent, start, forward, damage, kick, DEFAULT_SHOTGUN_HSPREAD, DEFAULT_SHOTGUN_VSPREAD, DEFAULT_SSHOTGUN_COUNT/2, MOD_SSHOTGUN);
1718 v[YAW] = ent->client->v_angle[YAW] + 5;
1719 AngleVectors (v, forward, NULL, NULL);
1720 fire_shotgun (ent, start, forward, damage, kick, DEFAULT_SHOTGUN_HSPREAD, DEFAULT_SHOTGUN_VSPREAD, DEFAULT_SSHOTGUN_COUNT/2, MOD_SSHOTGUN);
1721
1722 // send muzzle flash
1723 gi.WriteByte (svc_muzzleflash);
1724 gi.WriteShort (ent-g_edicts);
1725 gi.WriteByte (MZ_SSHOTGUN | is_silenced);
1726 gi.multicast (ent->s.origin, MULTICAST_PVS);
1727
1728 ent->client->ps.gunframe++;
1729 PlayerNoise(ent, start, PNOISE_WEAPON);
1730
1731 if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
1732 ent->client->pers.inventory[ent->client->ammo_index] -= 2;
1733 }
1734
Weapon_SuperShotgun(edict_t * ent)1735 void Weapon_SuperShotgun (edict_t *ent)
1736 {
1737 static int pause_frames[] = {29, 42, 57, 0};
1738 static int fire_frames[] = {7, 0};
1739
1740 Weapon_Generic (ent, 6, 17, 57, 61, pause_frames, fire_frames, weapon_supershotgun_fire);
1741 }
1742
1743
1744
1745 /*
1746 ======================================================================
1747
1748 RAILGUN
1749
1750 ======================================================================
1751 */
1752
weapon_railgun_fire(edict_t * ent)1753 void weapon_railgun_fire (edict_t *ent)
1754 {
1755 vec3_t start;
1756 vec3_t forward, right;
1757 vec3_t offset;
1758 int damage;
1759 int kick;
1760
1761 if (deathmatch->value)
1762 { // normal damage is too extreme in dm
1763 damage = 100;
1764 kick = 200;
1765 }
1766 else
1767 {
1768 damage = 150;
1769 kick = 250;
1770 }
1771
1772 if (is_quad)
1773 {
1774 //PGM
1775 // damage *= 4;
1776 damage *= damage_multiplier;
1777 // kick *= 4;
1778 kick *= damage_multiplier;
1779 //PGM
1780 }
1781
1782 AngleVectors (ent->client->v_angle, forward, right, NULL);
1783
1784 VectorScale (forward, -3, ent->client->kick_origin);
1785 ent->client->kick_angles[0] = -3;
1786
1787 VectorSet(offset, 0, 7, ent->viewheight-8);
1788 P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
1789 fire_rail (ent, start, forward, damage, kick);
1790
1791 // send muzzle flash
1792 gi.WriteByte (svc_muzzleflash);
1793 gi.WriteShort (ent-g_edicts);
1794 gi.WriteByte (MZ_RAILGUN | is_silenced);
1795 gi.multicast (ent->s.origin, MULTICAST_PVS);
1796
1797 ent->client->ps.gunframe++;
1798 PlayerNoise(ent, start, PNOISE_WEAPON);
1799
1800 if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
1801 ent->client->pers.inventory[ent->client->ammo_index]--;
1802 }
1803
1804
Weapon_Railgun(edict_t * ent)1805 void Weapon_Railgun (edict_t *ent)
1806 {
1807 static int pause_frames[] = {56, 0};
1808 static int fire_frames[] = {4, 0};
1809
1810 Weapon_Generic (ent, 3, 18, 56, 61, pause_frames, fire_frames, weapon_railgun_fire);
1811 }
1812
1813
1814 /*
1815 ======================================================================
1816
1817 BFG10K
1818
1819 ======================================================================
1820 */
1821
weapon_bfg_fire(edict_t * ent)1822 void weapon_bfg_fire (edict_t *ent)
1823 {
1824 vec3_t offset, start;
1825 vec3_t forward, right;
1826 int damage;
1827 float damage_radius = 1000;
1828
1829 if (deathmatch->value)
1830 damage = 200;
1831 else
1832 damage = 500;
1833
1834 if (ent->client->ps.gunframe == 9)
1835 {
1836 // send muzzle flash
1837 gi.WriteByte (svc_muzzleflash);
1838 gi.WriteShort (ent-g_edicts);
1839 gi.WriteByte (MZ_BFG | is_silenced);
1840 gi.multicast (ent->s.origin, MULTICAST_PVS);
1841
1842 ent->client->ps.gunframe++;
1843
1844 PlayerNoise(ent, start, PNOISE_WEAPON);
1845 return;
1846 }
1847
1848 // cells can go down during windup (from power armor hits), so
1849 // check again and abort firing if we don't have enough now
1850 if (ent->client->pers.inventory[ent->client->ammo_index] < 50)
1851 {
1852 ent->client->ps.gunframe++;
1853 return;
1854 }
1855
1856 if (is_quad)
1857 //PGM
1858 // damage *= 4;
1859 damage *= damage_multiplier;
1860 //PGM
1861
1862 AngleVectors (ent->client->v_angle, forward, right, NULL);
1863
1864 VectorScale (forward, -2, ent->client->kick_origin);
1865
1866 // make a big pitch kick with an inverse fall
1867 ent->client->v_dmg_pitch = -40;
1868 ent->client->v_dmg_roll = crandom()*8;
1869 ent->client->v_dmg_time = level.time + DAMAGE_TIME;
1870
1871 VectorSet(offset, 8, 8, ent->viewheight-8);
1872 P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
1873 fire_bfg (ent, start, forward, damage, 400, damage_radius);
1874
1875 ent->client->ps.gunframe++;
1876
1877 PlayerNoise(ent, start, PNOISE_WEAPON);
1878
1879 if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
1880 ent->client->pers.inventory[ent->client->ammo_index] -= 50;
1881 }
1882
Weapon_BFG(edict_t * ent)1883 void Weapon_BFG (edict_t *ent)
1884 {
1885 static int pause_frames[] = {39, 45, 50, 55, 0};
1886 static int fire_frames[] = {9, 17, 0};
1887
1888 Weapon_Generic (ent, 8, 32, 55, 58, pause_frames, fire_frames, weapon_bfg_fire);
1889 }
1890
1891
1892 //======================================================================
1893 // ROGUE MODS BELOW
1894 //======================================================================
1895
1896
1897 //
1898 // CHAINFIST
1899 //
1900 #define CHAINFIST_REACH 64
1901
weapon_chainfist_fire(edict_t * ent)1902 void weapon_chainfist_fire (edict_t *ent)
1903 {
1904 vec3_t offset;
1905 vec3_t forward, right, up;
1906 vec3_t start;
1907 int damage;
1908
1909 damage = 15;
1910 if(deathmatch->value)
1911 damage = 30;
1912
1913 if (is_quad)
1914 damage *= damage_multiplier;
1915
1916 AngleVectors (ent->client->v_angle, forward, right, up);
1917
1918 // kick back
1919 VectorScale (forward, -2, ent->client->kick_origin);
1920 ent->client->kick_angles[0] = -1;
1921
1922 // set start point
1923 VectorSet(offset, 0, 8, ent->viewheight-4);
1924 P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
1925
1926 fire_player_melee (ent, start, forward, CHAINFIST_REACH, damage, 100, 1, MOD_CHAINFIST);
1927
1928 PlayerNoise(ent, start, PNOISE_WEAPON);
1929
1930 ent->client->ps.gunframe++;
1931 ent->client->pers.inventory[ent->client->ammo_index] -= ent->client->pers.weapon->quantity;
1932 }
1933
1934 // this spits out some smoke from the motor. it's a two-stroke, you know.
chainfist_smoke(edict_t * ent)1935 void chainfist_smoke (edict_t *ent)
1936 {
1937 vec3_t tempVec, forward, right, up;
1938 vec3_t offset;
1939
1940 AngleVectors(ent->client->v_angle, forward, right, up);
1941 VectorSet(offset, 8, 8, ent->viewheight -4);
1942 P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, tempVec);
1943
1944 gi.WriteByte (svc_temp_entity);
1945 gi.WriteByte (TE_CHAINFIST_SMOKE);
1946 gi.WritePosition (tempVec);
1947 gi.unicast (ent, 0);
1948 // gi.multicast (tempVec, MULTICAST_PVS);
1949 }
1950
1951 #define HOLD_FRAMES 0
1952
Weapon_ChainFist(edict_t * ent)1953 void Weapon_ChainFist (edict_t *ent)
1954 {
1955 static int pause_frames[] = {0};
1956 static int fire_frames[] = {8, 9, 16, 17, 18, 30, 31, 0};
1957
1958 // these are caches for the sound index. there's probably a better way to do this.
1959 // static int idle_index;
1960 // static int attack_index;
1961 float chance;
1962 int last_sequence;
1963
1964 last_sequence = 0;
1965
1966 // load chainsaw sounds and store the indexes for later use.
1967 // if(!idle_index && !attack_index)
1968 // {
1969 // idle_index = gi.soundindex("weapons/sawidle.wav");
1970 // attack_index = gi.soundindex("weapons/sawhit.wav");
1971 // }
1972
1973 if(ent->client->ps.gunframe == 13 ||
1974 ent->client->ps.gunframe == 23) // end of attack, go idle
1975 ent->client->ps.gunframe = 32;
1976
1977 #if HOLD_FRAMES
1978 else if(ent->client->ps.gunframe == 9 && ((ent->client->buttons) & BUTTON_ATTACK))
1979 ent->client->ps.gunframe = 7;
1980 else if(ent->client->ps.gunframe == 18 && ((ent->client->buttons) & BUTTON_ATTACK))
1981 ent->client->ps.gunframe = 16;
1982 #endif
1983
1984 // holds for idle sequence
1985 else if(ent->client->ps.gunframe == 42 && (rand()&7))
1986 {
1987 if((ent->client->pers.hand != CENTER_HANDED) && random() < 0.4)
1988 chainfist_smoke(ent);
1989 // ent->client->ps.gunframe = 40;
1990 }
1991 else if(ent->client->ps.gunframe == 51 && (rand()&7))
1992 {
1993 if((ent->client->pers.hand != CENTER_HANDED) && random() < 0.4)
1994 chainfist_smoke(ent);
1995 // ent->client->ps.gunframe = 49;
1996 }
1997
1998 // set the appropriate weapon sound.
1999 if(ent->client->weaponstate == WEAPON_FIRING)
2000 // ent->client->weapon_sound = attack_index;
2001 ent->client->weapon_sound = gi.soundindex("weapons/sawhit.wav");
2002 else if(ent->client->weaponstate == WEAPON_DROPPING)
2003 ent->client->weapon_sound = 0;
2004 else
2005 // ent->client->weapon_sound = idle_index;
2006 ent->client->weapon_sound = gi.soundindex("weapons/sawidle.wav");
2007
2008 Weapon_Generic (ent, 4, 32, 57, 60, pause_frames, fire_frames, weapon_chainfist_fire);
2009
2010 // gi.dprintf("chainfist %d\n", ent->client->ps.gunframe);
2011 if((ent->client->buttons) & BUTTON_ATTACK)
2012 {
2013 if(ent->client->ps.gunframe == 13 ||
2014 ent->client->ps.gunframe == 23 ||
2015 ent->client->ps.gunframe == 32)
2016 {
2017 last_sequence = ent->client->ps.gunframe;
2018 ent->client->ps.gunframe = 6;
2019 }
2020 }
2021
2022 if (ent->client->ps.gunframe == 6)
2023 {
2024 chance = random();
2025 if(last_sequence == 13) // if we just did sequence 1, do 2 or 3.
2026 chance -= 0.34;
2027 else if(last_sequence == 23) // if we just did sequence 2, do 1 or 3
2028 chance += 0.33;
2029 else if(last_sequence == 32) // if we just did sequence 3, do 1 or 2
2030 {
2031 if(chance >= 0.33)
2032 chance += 0.34;
2033 }
2034
2035 if(chance < 0.33)
2036 ent->client->ps.gunframe = 14;
2037 else if(chance < 0.66)
2038 ent->client->ps.gunframe = 24;
2039 }
2040
2041 }
2042
2043 //
2044 // Disintegrator
2045 //
2046
weapon_tracker_fire(edict_t * self)2047 void weapon_tracker_fire (edict_t *self)
2048 {
2049 vec3_t forward, right;
2050 vec3_t start;
2051 vec3_t end;
2052 vec3_t offset;
2053 edict_t *enemy;
2054 trace_t tr;
2055 int damage;
2056 vec3_t mins, maxs;
2057
2058 // PMM - felt a little high at 25
2059 if(deathmatch->value)
2060 damage = 30;
2061 else
2062 damage = 45;
2063
2064 if (is_quad)
2065 damage *= damage_multiplier; //pgm
2066
2067 VectorSet(mins, -16, -16, -16);
2068 VectorSet(maxs, 16, 16, 16);
2069 AngleVectors (self->client->v_angle, forward, right, NULL);
2070 VectorSet(offset, 24, 8, self->viewheight-8);
2071 P_ProjectSource (self->client, self->s.origin, offset, forward, right, start);
2072
2073 // FIXME - can we shorten this? do we need to?
2074 VectorMA (start, 8192, forward, end);
2075 enemy = NULL;
2076 //PMM - doing two traces .. one point and one box.
2077 tr = gi.trace (start, vec3_origin, vec3_origin, end, self, MASK_SHOT);
2078 if(tr.ent != world)
2079 {
2080 if(tr.ent->svflags & SVF_MONSTER || tr.ent->client || tr.ent->svflags & SVF_DAMAGEABLE)
2081 {
2082 if(tr.ent->health > 0)
2083 enemy = tr.ent;
2084 }
2085 }
2086 else
2087 {
2088 tr = gi.trace (start, mins, maxs, end, self, MASK_SHOT);
2089 if(tr.ent != world)
2090 {
2091 if(tr.ent->svflags & SVF_MONSTER || tr.ent->client || tr.ent->svflags & SVF_DAMAGEABLE)
2092 {
2093 if(tr.ent->health > 0)
2094 enemy = tr.ent;
2095 }
2096 }
2097 }
2098
2099 VectorScale (forward, -2, self->client->kick_origin);
2100 self->client->kick_angles[0] = -1;
2101
2102 fire_tracker (self, start, forward, damage, 1000, enemy);
2103
2104 // send muzzle flash
2105 gi.WriteByte (svc_muzzleflash);
2106 gi.WriteShort (self-g_edicts);
2107 gi.WriteByte (MZ_TRACKER);
2108 gi.multicast (self->s.origin, MULTICAST_PVS);
2109
2110 PlayerNoise(self, start, PNOISE_WEAPON);
2111
2112 self->client->ps.gunframe++;
2113 self->client->pers.inventory[self->client->ammo_index] -= self->client->pers.weapon->quantity;
2114 }
2115
Weapon_Disintegrator(edict_t * ent)2116 void Weapon_Disintegrator (edict_t *ent)
2117 {
2118 static int pause_frames[] = {14, 19, 23, 0};
2119 // static int fire_frames[] = {7, 0};
2120 static int fire_frames[] = {5, 0};
2121
2122 Weapon_Generic (ent, 4, 9, 29, 34, pause_frames, fire_frames, weapon_tracker_fire);
2123 }
2124
2125 /*
2126 ======================================================================
2127
2128 ETF RIFLE
2129
2130 ======================================================================
2131 */
weapon_etf_rifle_fire(edict_t * ent)2132 void weapon_etf_rifle_fire (edict_t *ent)
2133 {
2134 vec3_t forward, right, up;
2135 vec3_t start, tempPt;
2136 int damage;
2137 int kick = 3;
2138 int i;
2139 vec3_t angles;
2140 vec3_t offset;
2141
2142 if(deathmatch->value)
2143 damage = 10;
2144 else
2145 damage = 10;
2146
2147 // PGM - adjusted to use the quantity entry in the weapon structure.
2148 if(ent->client->pers.inventory[ent->client->ammo_index] < ent->client->pers.weapon->quantity)
2149 {
2150 VectorClear (ent->client->kick_origin);
2151 VectorClear (ent->client->kick_angles);
2152 ent->client->ps.gunframe = 8;
2153
2154 if (level.time >= ent->pain_debounce_time)
2155 {
2156 gi.sound(ent, CHAN_VOICE, gi.soundindex("weapons/noammo.wav"), 1, ATTN_NORM, 0);
2157 ent->pain_debounce_time = level.time + 1;
2158 }
2159 NoAmmoWeaponChange (ent);
2160 return;
2161 }
2162
2163 if (is_quad)
2164 {
2165 damage *= damage_multiplier;
2166 kick *= damage_multiplier;
2167 }
2168
2169 for(i=0;i<3;i++)
2170 {
2171 ent->client->kick_origin[i] = crandom() * 0.85;
2172 ent->client->kick_angles[i] = crandom() * 0.85;
2173 }
2174
2175 // get start / end positions
2176 VectorAdd (ent->client->v_angle, ent->client->kick_angles, angles);
2177 // AngleVectors (angles, forward, right, NULL);
2178 // gi.dprintf("v_angle: %s\n", vtos(ent->client->v_angle));
2179 AngleVectors (ent->client->v_angle, forward, right, up);
2180
2181 // FIXME - set correct frames for different offsets.
2182
2183 if(ent->client->ps.gunframe == 6) // right barrel
2184 {
2185 // gi.dprintf("right\n");
2186 VectorSet(offset, 15, 8, -8);
2187 }
2188 else // left barrel
2189 {
2190 // gi.dprintf("left\n");
2191 VectorSet(offset, 15, 6, -8);
2192 }
2193
2194 VectorCopy (ent->s.origin, tempPt);
2195 tempPt[2] += ent->viewheight;
2196 P_ProjectSource2 (ent->client, tempPt, offset, forward, right, up, start);
2197 // gi.dprintf("start: %s\n", vtos(start));
2198 fire_flechette (ent, start, forward, damage, 750, kick);
2199
2200 // send muzzle flash
2201 gi.WriteByte (svc_muzzleflash);
2202 gi.WriteShort (ent-g_edicts);
2203 gi.WriteByte (MZ_ETF_RIFLE);
2204 gi.multicast (ent->s.origin, MULTICAST_PVS);
2205
2206 PlayerNoise(ent, start, PNOISE_WEAPON);
2207
2208 ent->client->ps.gunframe++;
2209 ent->client->pers.inventory[ent->client->ammo_index] -= ent->client->pers.weapon->quantity;
2210
2211 ent->client->anim_priority = ANIM_ATTACK;
2212 if (ent->client->ps.pmove.pm_flags & PMF_DUCKED)
2213 {
2214 ent->s.frame = FRAME_crattak1 - 1;
2215 ent->client->anim_end = FRAME_crattak9;
2216 }
2217 else
2218 {
2219 ent->s.frame = FRAME_attack1 - 1;
2220 ent->client->anim_end = FRAME_attack8;
2221 }
2222
2223 }
2224
Weapon_ETF_Rifle(edict_t * ent)2225 void Weapon_ETF_Rifle (edict_t *ent)
2226 {
2227 static int pause_frames[] = {18, 28, 0};
2228 static int fire_frames[] = {6, 7, 0};
2229 // static int idle_seq;
2230
2231 // note - if you change the fire frame number, fix the offset in weapon_etf_rifle_fire.
2232
2233 // if (!(ent->client->buttons & BUTTON_ATTACK))
2234 // ent->client->machinegun_shots = 0;
2235
2236 if (ent->client->weaponstate == WEAPON_FIRING)
2237 {
2238 if (ent->client->pers.inventory[ent->client->ammo_index] <= 0)
2239 ent->client->ps.gunframe = 8;
2240 }
2241
2242 Weapon_Generic (ent, 4, 7, 37, 41, pause_frames, fire_frames, weapon_etf_rifle_fire);
2243
2244 if(ent->client->ps.gunframe == 8 && (ent->client->buttons & BUTTON_ATTACK))
2245 ent->client->ps.gunframe = 6;
2246
2247 // gi.dprintf("etf rifle %d\n", ent->client->ps.gunframe);
2248 }
2249
2250 // pgm - this now uses ent->client->pers.weapon->quantity like all the other weapons
2251 //#define HEATBEAM_AMMO_USE 2
2252 #define HEATBEAM_DM_DMG 15
2253 #define HEATBEAM_SP_DMG 15
2254
Heatbeam_Fire(edict_t * ent)2255 void Heatbeam_Fire (edict_t *ent)
2256 {
2257 vec3_t start;
2258 vec3_t forward, right, up;
2259 vec3_t offset;
2260 int damage;
2261 int kick;
2262
2263 // for comparison, the hyperblaster is 15/20
2264 // jim requested more damage, so try 15/15 --- PGM 07/23/98
2265 if (deathmatch->value)
2266 damage = HEATBEAM_DM_DMG;
2267 else
2268 damage = HEATBEAM_SP_DMG;
2269
2270 if (deathmatch->value) // really knock 'em around in deathmatch
2271 kick = 75;
2272 else
2273 kick = 30;
2274
2275 // if(ent->client->pers.inventory[ent->client->ammo_index] < HEATBEAM_AMMO_USE)
2276 // {
2277 // NoAmmoWeaponChange (ent);
2278 // return;
2279 // }
2280
2281 ent->client->ps.gunframe++;
2282 ent->client->ps.gunindex = gi.modelindex ("models/weapons/v_beamer2/tris.md2");
2283
2284 if (is_quad)
2285 {
2286 damage *= damage_multiplier;
2287 kick *= damage_multiplier;
2288 }
2289
2290 VectorClear (ent->client->kick_origin);
2291 VectorClear (ent->client->kick_angles);
2292
2293 // get start / end positions
2294 AngleVectors (ent->client->v_angle, forward, right, up);
2295
2296 // This offset is the "view" offset for the beam start (used by trace)
2297
2298 VectorSet(offset, 7, 2, ent->viewheight-3);
2299 P_ProjectSource (ent->client, ent->s.origin, offset, forward, right, start);
2300
2301 // This offset is the entity offset
2302 VectorSet(offset, 2, 7, -3);
2303
2304 fire_heat (ent, start, forward, offset, damage, kick, false);
2305
2306 // send muzzle flash
2307 gi.WriteByte (svc_muzzleflash);
2308 gi.WriteShort (ent-g_edicts);
2309 gi.WriteByte (MZ_HEATBEAM | is_silenced);
2310 gi.multicast (ent->s.origin, MULTICAST_PVS);
2311
2312 PlayerNoise(ent, start, PNOISE_WEAPON);
2313
2314 if (! ( (int)dmflags->value & DF_INFINITE_AMMO ) )
2315 ent->client->pers.inventory[ent->client->ammo_index] -= ent->client->pers.weapon->quantity;
2316
2317 ent->client->anim_priority = ANIM_ATTACK;
2318 if (ent->client->ps.pmove.pm_flags & PMF_DUCKED)
2319 {
2320 ent->s.frame = FRAME_crattak1 - 1;
2321 ent->client->anim_end = FRAME_crattak9;
2322 }
2323 else
2324 {
2325 ent->s.frame = FRAME_attack1 - 1;
2326 ent->client->anim_end = FRAME_attack8;
2327 }
2328
2329 }
2330
Weapon_Heatbeam(edict_t * ent)2331 void Weapon_Heatbeam (edict_t *ent)
2332 {
2333 // static int pause_frames[] = {38, 43, 51, 61, 0};
2334 // static int fire_frames[] = {5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 0};
2335 static int pause_frames[] = {35, 0};
2336 // static int fire_frames[] = {9, 0};
2337 static int fire_frames[] = {9, 10, 11, 12, 0};
2338 // static int attack_index;
2339 // static int off_model, on_model;
2340
2341 // if ((g_showlogic) && (g_showlogic->value)) {
2342 // gi.dprintf ("Frame %d, skin %d\n", ent->client->ps.gunframe, ent->client->ps.gunskin);
2343 // }
2344
2345 // if (!attack_index)
2346 // {
2347 // attack_index = gi.soundindex ("weapons/bfg__l1a.wav");
2348 // off_model = gi.modelindex ("models/weapons/v_beamer/tris.md2");
2349 // on_model = gi.modelindex ("models/weapons/v_beamer2/tris.md2");
2350 //ent->client->ps.gunindex = gi.modelindex(ent->client->pers.weapon->view_model);
2351 // }
2352
2353 if (ent->client->weaponstate == WEAPON_FIRING)
2354 {
2355 // ent->client->weapon_sound = attack_index;
2356 ent->client->weapon_sound = gi.soundindex ("weapons/bfg__l1a.wav");
2357 if ((ent->client->pers.inventory[ent->client->ammo_index] >= 2) && ((ent->client->buttons) & BUTTON_ATTACK))
2358 {
2359 // if(ent->client->ps.gunframe >= 9 && ((ent->client->buttons) & BUTTON_ATTACK))
2360 // if(ent->client->ps.gunframe >= 12 && ((ent->client->buttons) & BUTTON_ATTACK))
2361 if(ent->client->ps.gunframe >= 13)
2362 {
2363 ent->client->ps.gunframe = 9;
2364 // ent->client->ps.gunframe = 8;
2365 // ent->client->ps.gunskin = 0;
2366 // ent->client->ps.gunindex = on_model;
2367 ent->client->ps.gunindex = gi.modelindex ("models/weapons/v_beamer2/tris.md2");
2368 }
2369 else
2370 {
2371 // ent->client->ps.gunskin = 1;
2372 // ent->client->ps.gunindex = on_model;
2373 ent->client->ps.gunindex = gi.modelindex ("models/weapons/v_beamer2/tris.md2");
2374 }
2375 }
2376 else
2377 {
2378 // ent->client->ps.gunframe = 10;
2379 ent->client->ps.gunframe = 13;
2380 // ent->client->ps.gunskin = 1;
2381 // ent->client->ps.gunindex = off_model;
2382 ent->client->ps.gunindex = gi.modelindex ("models/weapons/v_beamer/tris.md2");
2383 }
2384 }
2385 else
2386 {
2387 // ent->client->ps.gunskin = 1;
2388 // ent->client->ps.gunindex = off_model;
2389 ent->client->ps.gunindex = gi.modelindex ("models/weapons/v_beamer/tris.md2");
2390 ent->client->weapon_sound = 0;
2391 }
2392
2393 // Weapon_Generic (ent, 8, 9, 39, 44, pause_frames, fire_frames, Heatbeam_Fire);
2394 Weapon_Generic (ent, 8, 12, 39, 44, pause_frames, fire_frames, Heatbeam_Fire);
2395 }
2396