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