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