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