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