• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2*/
3void (entity targ, entity inflictor, entity attacker, float damage) T_Damage;
4void () player_run;
5void(entity bomb, entity attacker, float rad, entity ignore, string dtype) T_RadiusDamage;
6void(vector org, float damage) SpawnBlood;
7void() SuperDamageSound;
8
9
10// called by worldspawn
11void() W_Precache =
12{
13	precache_sound ("weapons/r_exp3.wav");  // new rocket explosion
14	precache_sound ("weapons/rocket1i.wav");        // spike gun
15	precache_sound ("weapons/sgun1.wav");
16	precache_sound ("weapons/guncock.wav"); // player shotgun
17	precache_sound ("weapons/ric1.wav");    // ricochet (used in c code)
18	precache_sound ("weapons/ric2.wav");    // ricochet (used in c code)
19	precache_sound ("weapons/ric3.wav");    // ricochet (used in c code)
20	precache_sound ("weapons/spike2.wav");  // super spikes
21	precache_sound ("weapons/tink1.wav");   // spikes tink (used in c code)
22	precache_sound ("weapons/grenade.wav"); // grenade launcher
23	precache_sound ("weapons/bounce.wav");          // grenade bounce
24	precache_sound ("weapons/shotgn2.wav"); // super shotgun
25};
26
27float() crandom =
28{
29	return 2*(random() - 0.5);
30};
31
32/*
33================
34W_FireAxe
35================
36*/
37void() W_FireAxe =
38{
39	local   vector  source;
40	local   vector  org;
41
42	makevectors (self.v_angle);
43	source = self.origin + '0 0 16';
44	traceline (source, source + v_forward*64, FALSE, self);
45	if (trace_fraction == 1.0)
46		return;
47
48	org = trace_endpos - v_forward*4;
49
50	if (trace_ent.takedamage)
51	{
52		trace_ent.axhitme = 1;
53		SpawnBlood (org, 20);
54		if (deathmatch > 3)
55			T_Damage (trace_ent, self, self, 75);
56		else
57			T_Damage (trace_ent, self, self, 20);
58	}
59	else
60	{       // hit wall
61		sound (self, CHAN_WEAPON, "player/axhit2.wav", 1, ATTN_NORM);
62
63		WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
64		WriteByte (MSG_MULTICAST, TE_GUNSHOT);
65		WriteByte (MSG_MULTICAST, 3);
66		WriteCoord (MSG_MULTICAST, org_x);
67		WriteCoord (MSG_MULTICAST, org_y);
68		WriteCoord (MSG_MULTICAST, org_z);
69		multicast (org, MULTICAST_PVS);
70	}
71};
72
73
74//============================================================================
75
76
77vector() wall_velocity =
78{
79	local vector    vel;
80
81	vel = normalize (self.velocity);
82	vel = normalize(vel + v_up*(random()- 0.5) + v_right*(random()- 0.5));
83	vel = vel + 2*trace_plane_normal;
84	vel = vel * 200;
85
86	return vel;
87};
88
89
90/*
91================
92SpawnMeatSpray
93================
94*/
95void(vector org, vector vel) SpawnMeatSpray =
96{
97	local   entity missile;
98	local   vector  org;
99
100	missile = spawn ();
101	missile.owner = self;
102	missile.movetype = MOVETYPE_BOUNCE;
103	missile.solid = SOLID_NOT;
104
105	makevectors (self.angles);
106
107	missile.velocity = vel;
108	missile.velocity_z = missile.velocity_z + 250 + 50*random();
109
110	missile.avelocity = '3000 1000 2000';
111
112// set missile duration
113	missile.nextthink = time + 1;
114	missile.think = SUB_Remove;
115
116	setmodel (missile, "progs/zom_gib.mdl");
117	setsize (missile, '0 0 0', '0 0 0');
118	setorigin (missile, org);
119};
120
121/*
122================
123SpawnBlood
124================
125*/
126void(vector org, float damage) SpawnBlood =
127{
128	WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
129	WriteByte (MSG_MULTICAST, TE_BLOOD);
130	WriteByte (MSG_MULTICAST, 1);
131	WriteCoord (MSG_MULTICAST, org_x);
132	WriteCoord (MSG_MULTICAST, org_y);
133	WriteCoord (MSG_MULTICAST, org_z);
134	multicast (org, MULTICAST_PVS);
135};
136
137/*
138================
139spawn_touchblood
140================
141*/
142void(float damage) spawn_touchblood =
143{
144	local vector    vel;
145
146	vel = wall_velocity () * 0.2;
147	SpawnBlood (self.origin + vel*0.01, damage);
148};
149
150/*
151==============================================================================
152
153MULTI-DAMAGE
154
155Collects multiple small damages into a single damage
156
157==============================================================================
158*/
159
160entity  multi_ent;
161float   multi_damage;
162
163vector  blood_org;
164float   blood_count;
165
166vector  puff_org;
167float   puff_count;
168
169void() ClearMultiDamage =
170{
171	multi_ent = world;
172	multi_damage = 0;
173	blood_count = 0;
174	puff_count = 0;
175};
176
177void() ApplyMultiDamage =
178{
179	if (!multi_ent)
180		return;
181	T_Damage (multi_ent, self, self, multi_damage);
182};
183
184void(entity hit, float damage) AddMultiDamage =
185{
186	if (!hit)
187		return;
188
189	if (hit != multi_ent)
190	{
191		ApplyMultiDamage ();
192		multi_damage = damage;
193		multi_ent = hit;
194	}
195	else
196		multi_damage = multi_damage + damage;
197};
198
199void() Multi_Finish =
200{
201	if (puff_count)
202	{
203		WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
204		WriteByte (MSG_MULTICAST, TE_GUNSHOT);
205		WriteByte (MSG_MULTICAST, puff_count);
206		WriteCoord (MSG_MULTICAST, puff_org_x);
207		WriteCoord (MSG_MULTICAST, puff_org_y);
208		WriteCoord (MSG_MULTICAST, puff_org_z);
209		multicast (puff_org, MULTICAST_PVS);
210	}
211
212	if (blood_count)
213	{
214		WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
215		WriteByte (MSG_MULTICAST, TE_BLOOD);
216		WriteByte (MSG_MULTICAST, blood_count);
217		WriteCoord (MSG_MULTICAST, blood_org_x);
218		WriteCoord (MSG_MULTICAST, blood_org_y);
219		WriteCoord (MSG_MULTICAST, blood_org_z);
220		multicast (puff_org, MULTICAST_PVS);
221	}
222};
223
224/*
225==============================================================================
226BULLETS
227==============================================================================
228*/
229
230/*
231================
232TraceAttack
233================
234*/
235void(float damage, vector dir) TraceAttack =
236{
237	local   vector  vel, org;
238
239	vel = normalize(dir + v_up*crandom() + v_right*crandom());
240	vel = vel + 2*trace_plane_normal;
241	vel = vel * 200;
242
243	org = trace_endpos - dir*4;
244
245	if (trace_ent.takedamage)
246	{
247		blood_count = blood_count + 1;
248		blood_org = org;
249		AddMultiDamage (trace_ent, damage);
250	}
251	else
252	{
253		puff_count = puff_count + 1;
254	}
255};
256
257/*
258================
259FireBullets
260
261Used by shotgun, super shotgun, and enemy soldier firing
262Go to the trouble of combining multiple pellets into a single damage call.
263================
264*/
265void(float shotcount, vector dir, vector spread) FireBullets =
266{
267	local   vector direction;
268	local   vector  src;
269
270	makevectors(self.v_angle);
271
272	src = self.origin + v_forward*10;
273	src_z = self.absmin_z + self.size_z * 0.7;
274
275	ClearMultiDamage ();
276
277	traceline (src, src + dir*2048, FALSE, self);
278	puff_org = trace_endpos - dir*4;
279
280	while (shotcount > 0)
281	{
282		direction = dir + crandom()*spread_x*v_right + crandom()*spread_y*v_up;
283		traceline (src, src + direction*2048, FALSE, self);
284		if (trace_fraction != 1.0)
285			TraceAttack (4, direction);
286
287		shotcount = shotcount - 1;
288	}
289	ApplyMultiDamage ();
290	Multi_Finish ();
291};
292
293/*
294================
295W_FireShotgun
296================
297*/
298void() W_FireShotgun =
299{
300	local vector dir;
301
302	sound (self, CHAN_WEAPON, "weapons/guncock.wav", 1, ATTN_NORM);
303
304	msg_entity = self;
305	WriteByte (MSG_ONE, SVC_SMALLKICK);
306
307	if (deathmatch != 4 )
308		self.currentammo = self.ammo_shells = self.ammo_shells - 1;
309
310	dir = aim (self, 100000);
311	FireBullets (6, dir, '0.04 0.04 0');
312};
313
314
315/*
316================
317W_FireSuperShotgun
318================
319*/
320void() W_FireSuperShotgun =
321{
322	local vector dir;
323
324	if (self.currentammo == 1)
325	{
326		W_FireShotgun ();
327		return;
328	}
329
330	sound (self ,CHAN_WEAPON, "weapons/shotgn2.wav", 1, ATTN_NORM);
331
332	msg_entity = self;
333	WriteByte (MSG_ONE, SVC_BIGKICK);
334
335	if (deathmatch != 4)
336		self.currentammo = self.ammo_shells = self.ammo_shells - 2;
337	dir = aim (self, 100000);
338	FireBullets (14, dir, '0.14 0.08 0');
339};
340
341
342/*
343==============================================================================
344
345ROCKETS
346
347==============================================================================
348*/
349
350void() T_MissileTouch =
351{
352	local float     damg;
353
354//	if (deathmatch == 4)
355//	{
356//	if ( ((other.weapon == 32) || (other.weapon == 16)))
357//		{
358//			if (random() < 0.1)
359//			{
360//				if (other != world)
361//				{
362//	//				bprint (PRINT_HIGH, "Got here\n");
363//					other.deathtype = "blaze";
364//					T_Damage (other, self, self.owner, 1000 );
365//					T_RadiusDamage (self, self.owner, 1000, other);
366//				}
367//			}
368//		}
369//	}
370
371	if (other == self.owner)
372		return;         // don't explode on owner
373
374	if (self.voided) {
375		return;
376	}
377	self.voided = 1;
378
379	if (pointcontents(self.origin) == CONTENT_SKY)
380	{
381		remove(self);
382		return;
383	}
384
385	damg = 100 + random()*20;
386
387	if (other.health)
388	{
389		other.deathtype = "rocket";
390		T_Damage (other, self, self.owner, damg );
391	}
392
393	// don't do radius damage to the other, because all the damage
394	// was done in the impact
395
396
397	T_RadiusDamage (self, self.owner, 120, other, "rocket");
398
399//  sound (self, CHAN_WEAPON, "weapons/r_exp3.wav", 1, ATTN_NORM);
400	self.origin = self.origin - 8 * normalize(self.velocity);
401
402	WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
403	WriteByte (MSG_MULTICAST, TE_EXPLOSION);
404	WriteCoord (MSG_MULTICAST, self.origin_x);
405	WriteCoord (MSG_MULTICAST, self.origin_y);
406	WriteCoord (MSG_MULTICAST, self.origin_z);
407	multicast (self.origin, MULTICAST_PHS);
408
409	remove(self);
410};
411
412
413
414/*
415================
416W_FireRocket
417================
418*/
419void() W_FireRocket =
420{
421	if (deathmatch != 4)
422		self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
423
424	sound (self, CHAN_WEAPON, "weapons/sgun1.wav", 1, ATTN_NORM);
425
426	msg_entity = self;
427	WriteByte (MSG_ONE, SVC_SMALLKICK);
428
429	newmis = spawn ();
430	newmis.owner = self;
431	newmis.movetype = MOVETYPE_FLYMISSILE;
432	newmis.solid = SOLID_BBOX;
433
434// set newmis speed
435
436	makevectors (self.v_angle);
437	newmis.velocity = aim(self, 1000);
438	newmis.velocity = newmis.velocity * 1000;
439	newmis.angles = vectoangles(newmis.velocity);
440
441	newmis.touch = T_MissileTouch;
442	newmis.voided = 0;
443
444// set newmis duration
445	newmis.nextthink = time + 5;
446	newmis.think = SUB_Remove;
447	newmis.classname = "rocket";
448
449	setmodel (newmis, "progs/missile.mdl");
450	setsize (newmis, '0 0 0', '0 0 0');
451	setorigin (newmis, self.origin + v_forward*8 + '0 0 16');
452};
453
454/*
455===============================================================================
456LIGHTNING
457===============================================================================
458*/
459
460void(entity from, float damage) LightningHit =
461{
462	WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
463	WriteByte (MSG_MULTICAST, TE_LIGHTNINGBLOOD);
464	WriteCoord (MSG_MULTICAST, trace_endpos_x);
465	WriteCoord (MSG_MULTICAST, trace_endpos_y);
466	WriteCoord (MSG_MULTICAST, trace_endpos_z);
467	multicast (trace_endpos, MULTICAST_PVS);
468
469	T_Damage (trace_ent, from, from, damage);
470};
471
472/*
473=================
474LightningDamage
475=================
476*/
477void(vector p1, vector p2, entity from, float damage) LightningDamage =
478{
479	local entity            e1, e2;
480	local vector            f;
481
482	f = p2 - p1;
483	normalize (f);
484	f_x = 0 - f_y;
485	f_y = f_x;
486	f_z = 0;
487	f = f*16;
488
489	e1 = e2 = world;
490
491	traceline (p1, p2, FALSE, self);
492
493	if (trace_ent.takedamage)
494	{
495		LightningHit (from, damage);
496		if (self.classname == "player")
497		{
498			if (other.classname == "player")
499				trace_ent.velocity_z = trace_ent.velocity_z + 400;
500		}
501	}
502	e1 = trace_ent;
503
504	traceline (p1 + f, p2 + f, FALSE, self);
505	if (trace_ent != e1 && trace_ent.takedamage)
506	{
507		LightningHit (from, damage);
508	}
509	e2 = trace_ent;
510
511	traceline (p1 - f, p2 - f, FALSE, self);
512	if (trace_ent != e1 && trace_ent != e2 && trace_ent.takedamage)
513	{
514		LightningHit (from, damage);
515	}
516};
517
518
519void() W_FireLightning =
520{
521	local   vector          org;
522	local   float           cells;
523
524	if (self.ammo_cells < 1)
525	{
526		self.weapon = W_BestWeapon ();
527		W_SetCurrentAmmo ();
528		return;
529	}
530
531// explode if under water
532	if (self.waterlevel > 1)
533	{
534		if (deathmatch > 3)
535		{
536			if (random() <= 0.5)
537			{
538				self.deathtype = "selfwater";
539				T_Damage (self, self, self.owner, 4000 );
540			}
541			else
542			{
543				cells = self.ammo_cells;
544				self.ammo_cells = 0;
545				W_SetCurrentAmmo ();
546				T_RadiusDamage (self, self, 35*cells, world, "");
547				return;
548			}
549		}
550		else
551		{
552			cells = self.ammo_cells;
553			self.ammo_cells = 0;
554			W_SetCurrentAmmo ();
555			T_RadiusDamage (self, self, 35*cells, world,"");
556			return;
557		}
558	}
559
560	if (self.t_width < time)
561	{
562		sound (self, CHAN_WEAPON, "weapons/lhit.wav", 1, ATTN_NORM);
563		self.t_width = time + 0.6;
564	}
565	msg_entity = self;
566	WriteByte (MSG_ONE, SVC_SMALLKICK);
567
568	if (deathmatch != 4)
569		self.currentammo = self.ammo_cells = self.ammo_cells - 1;
570
571	org = self.origin + '0 0 16';
572
573	traceline (org, org + v_forward*600, TRUE, self);
574
575	WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
576	WriteByte (MSG_MULTICAST, TE_LIGHTNING2);
577	WriteEntity (MSG_MULTICAST, self);
578	WriteCoord (MSG_MULTICAST, org_x);
579	WriteCoord (MSG_MULTICAST, org_y);
580	WriteCoord (MSG_MULTICAST, org_z);
581	WriteCoord (MSG_MULTICAST, trace_endpos_x);
582	WriteCoord (MSG_MULTICAST, trace_endpos_y);
583	WriteCoord (MSG_MULTICAST, trace_endpos_z);
584	multicast (org, MULTICAST_PHS);
585
586	LightningDamage (self.origin, trace_endpos + v_forward*4, self, 30);
587};
588
589
590//=============================================================================
591
592
593void() GrenadeExplode =
594{
595	if (self.voided) {
596		return;
597	}
598	self.voided = 1;
599
600	T_RadiusDamage (self, self.owner, 120, world, "grenade");
601
602	WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
603	WriteByte (MSG_MULTICAST, TE_EXPLOSION);
604	WriteCoord (MSG_MULTICAST, self.origin_x);
605	WriteCoord (MSG_MULTICAST, self.origin_y);
606	WriteCoord (MSG_MULTICAST, self.origin_z);
607	multicast (self.origin, MULTICAST_PHS);
608
609	remove (self);
610};
611
612void() GrenadeTouch =
613{
614	if (other == self.owner)
615		return;         // don't explode on owner
616	if (other.takedamage == DAMAGE_AIM)
617	{
618		GrenadeExplode();
619		return;
620	}
621	sound (self, CHAN_WEAPON, "weapons/bounce.wav", 1, ATTN_NORM);  // bounce sound
622	if (self.velocity == '0 0 0')
623		self.avelocity = '0 0 0';
624};
625
626/*
627================
628W_FireGrenade
629================
630*/
631void() W_FireGrenade =
632{
633	if (deathmatch != 4)
634		self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
635
636	sound (self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
637
638	msg_entity = self;
639	WriteByte (MSG_ONE, SVC_SMALLKICK);
640
641	newmis = spawn ();
642	newmis.voided=0;
643	newmis.owner = self;
644	newmis.movetype = MOVETYPE_BOUNCE;
645	newmis.solid = SOLID_BBOX;
646	newmis.classname = "grenade";
647
648// set newmis speed
649
650	makevectors (self.v_angle);
651
652	if (self.v_angle_x)
653		newmis.velocity = v_forward*600 + v_up * 200 + crandom()*v_right*10 + crandom()*v_up*10;
654	else
655	{
656		newmis.velocity = aim(self, 10000);
657		newmis.velocity = newmis.velocity * 600;
658		newmis.velocity_z = 200;
659	}
660
661	newmis.avelocity = '300 300 300';
662
663	newmis.angles = vectoangles(newmis.velocity);
664
665	newmis.touch = GrenadeTouch;
666
667// set newmis duration
668	if (deathmatch == 4)
669	{
670		newmis.nextthink = time + 2.5;
671		self.attack_finished = time + 1.1;
672//		self.health = self.health - 1;
673		T_Damage (self, self, self.owner, 10 );
674	}
675	else
676		newmis.nextthink = time + 2.5;
677
678	newmis.think = GrenadeExplode;
679
680	setmodel (newmis, "progs/grenade.mdl");
681	setsize (newmis, '0 0 0', '0 0 0');
682	setorigin (newmis, self.origin);
683};
684
685
686//=============================================================================
687
688void() spike_touch;
689void() superspike_touch;
690
691
692/*
693===============
694launch_spike
695
696Used for both the player and the ogre
697===============
698*/
699void(vector org, vector dir) launch_spike =
700{
701	newmis = spawn ();
702	newmis.voided=0;
703	newmis.owner = self;
704	newmis.movetype = MOVETYPE_FLYMISSILE;
705	newmis.solid = SOLID_BBOX;
706
707	newmis.angles = vectoangles(dir);
708
709	newmis.touch = spike_touch;
710	newmis.classname = "spike";
711	newmis.think = SUB_Remove;
712	newmis.nextthink = time + 6;
713	setmodel (newmis, "progs/spike.mdl");
714	setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);
715	setorigin (newmis, org);
716
717	newmis.velocity = dir * 1000;
718};
719
720void() W_FireSuperSpikes =
721{
722	local vector    dir;
723	local entity    old;
724
725	sound (self, CHAN_WEAPON, "weapons/spike2.wav", 1, ATTN_NORM);
726	self.attack_finished = time + 0.2;
727	if (deathmatch != 4)
728		self.currentammo = self.ammo_nails = self.ammo_nails - 2;
729	dir = aim (self, 1000);
730	launch_spike (self.origin + '0 0 16', dir);
731	newmis.touch = superspike_touch;
732	setmodel (newmis, "progs/s_spike.mdl");
733	setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);
734	msg_entity = self;
735	WriteByte (MSG_ONE, SVC_SMALLKICK);
736};
737
738void(float ox) W_FireSpikes =
739{
740	local vector    dir;
741	local entity    old;
742
743	makevectors (self.v_angle);
744
745	if (self.ammo_nails >= 2 && self.weapon == IT_SUPER_NAILGUN)
746	{
747		W_FireSuperSpikes ();
748		return;
749	}
750
751	if (self.ammo_nails < 1)
752	{
753		self.weapon = W_BestWeapon ();
754		W_SetCurrentAmmo ();
755		return;
756	}
757
758	sound (self, CHAN_WEAPON, "weapons/rocket1i.wav", 1, ATTN_NORM);
759	self.attack_finished = time + 0.2;
760	if (deathmatch != 4)
761		self.currentammo = self.ammo_nails = self.ammo_nails - 1;
762	dir = aim (self, 1000);
763	launch_spike (self.origin + '0 0 16' + v_right*ox, dir);
764
765	msg_entity = self;
766	WriteByte (MSG_ONE, SVC_SMALLKICK);
767};
768
769
770
771.float hit_z;
772void() spike_touch =
773{
774local float rand;
775	if (other == self.owner)
776		return;
777
778	if (self.voided) {
779		return;
780	}
781	self.voided = 1;
782
783	if (other.solid == SOLID_TRIGGER)
784		return; // trigger field, do nothing
785
786	if (pointcontents(self.origin) == CONTENT_SKY)
787	{
788		remove(self);
789		return;
790	}
791
792// hit something that bleeds
793	if (other.takedamage)
794	{
795		spawn_touchblood (9);
796		other.deathtype = "nail";
797		T_Damage (other, self, self.owner, 9);
798	}
799	else
800	{
801		WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
802		if (self.classname == "wizspike")
803			WriteByte (MSG_MULTICAST, TE_WIZSPIKE);
804		else if (self.classname == "knightspike")
805			WriteByte (MSG_MULTICAST, TE_KNIGHTSPIKE);
806		else
807			WriteByte (MSG_MULTICAST, TE_SPIKE);
808		WriteCoord (MSG_MULTICAST, self.origin_x);
809		WriteCoord (MSG_MULTICAST, self.origin_y);
810		WriteCoord (MSG_MULTICAST, self.origin_z);
811		multicast (self.origin, MULTICAST_PHS);
812	}
813
814	remove(self);
815
816};
817
818void() superspike_touch =
819{
820local float rand;
821	if (other == self.owner)
822		return;
823
824	if (self.voided) {
825		return;
826	}
827	self.voided = 1;
828
829
830	if (other.solid == SOLID_TRIGGER)
831		return; // trigger field, do nothing
832
833	if (pointcontents(self.origin) == CONTENT_SKY)
834	{
835		remove(self);
836		return;
837	}
838
839// hit something that bleeds
840	if (other.takedamage)
841	{
842		spawn_touchblood (18);
843		other.deathtype = "supernail";
844		T_Damage (other, self, self.owner, 18);
845	}
846	else
847	{
848		WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
849		WriteByte (MSG_MULTICAST, TE_SUPERSPIKE);
850		WriteCoord (MSG_MULTICAST, self.origin_x);
851		WriteCoord (MSG_MULTICAST, self.origin_y);
852		WriteCoord (MSG_MULTICAST, self.origin_z);
853		multicast (self.origin, MULTICAST_PHS);
854	}
855
856	remove(self);
857
858};
859
860
861/*
862===============================================================================
863
864PLAYER WEAPON USE
865
866===============================================================================
867*/
868
869void() W_SetCurrentAmmo =
870{
871	player_run ();          // get out of any weapon firing states
872
873	self.items = self.items - ( self.items & (IT_SHELLS | IT_NAILS | IT_ROCKETS | IT_CELLS) );
874
875	if (self.weapon == IT_AXE)
876	{
877		self.currentammo = 0;
878		self.weaponmodel = "progs/v_axe.mdl";
879		self.weaponframe = 0;
880	}
881	else if (self.weapon == IT_SHOTGUN)
882	{
883		self.currentammo = self.ammo_shells;
884		self.weaponmodel = "progs/v_shot.mdl";
885		self.weaponframe = 0;
886		self.items = self.items | IT_SHELLS;
887	}
888	else if (self.weapon == IT_SUPER_SHOTGUN)
889	{
890		self.currentammo = self.ammo_shells;
891		self.weaponmodel = "progs/v_shot2.mdl";
892		self.weaponframe = 0;
893		self.items = self.items | IT_SHELLS;
894	}
895	else if (self.weapon == IT_NAILGUN)
896	{
897		self.currentammo = self.ammo_nails;
898		self.weaponmodel = "progs/v_nail.mdl";
899		self.weaponframe = 0;
900		self.items = self.items | IT_NAILS;
901	}
902	else if (self.weapon == IT_SUPER_NAILGUN)
903	{
904		self.currentammo = self.ammo_nails;
905		self.weaponmodel = "progs/v_nail2.mdl";
906		self.weaponframe = 0;
907		self.items = self.items | IT_NAILS;
908	}
909	else if (self.weapon == IT_GRENADE_LAUNCHER)
910	{
911		self.currentammo = self.ammo_rockets;
912		self.weaponmodel = "progs/v_rock.mdl";
913		self.weaponframe = 0;
914		self.items = self.items | IT_ROCKETS;
915	}
916	else if (self.weapon == IT_ROCKET_LAUNCHER)
917	{
918		self.currentammo = self.ammo_rockets;
919		self.weaponmodel = "progs/v_rock2.mdl";
920		self.weaponframe = 0;
921		self.items = self.items | IT_ROCKETS;
922	}
923	else if (self.weapon == IT_LIGHTNING)
924	{
925		self.currentammo = self.ammo_cells;
926		self.weaponmodel = "progs/v_light.mdl";
927		self.weaponframe = 0;
928		self.items = self.items | IT_CELLS;
929	}
930	else
931	{
932		self.currentammo = 0;
933		self.weaponmodel = "";
934		self.weaponframe = 0;
935	}
936};
937
938float() W_BestWeapon =
939{
940	local   float   it;
941
942	it = self.items;
943
944	if (self.waterlevel <= 1 && self.ammo_cells >= 1 && (it & IT_LIGHTNING) )
945		return IT_LIGHTNING;
946	else if(self.ammo_nails >= 2 && (it & IT_SUPER_NAILGUN) )
947		return IT_SUPER_NAILGUN;
948	else if(self.ammo_shells >= 2 && (it & IT_SUPER_SHOTGUN) )
949		return IT_SUPER_SHOTGUN;
950	else if(self.ammo_nails >= 1 && (it & IT_NAILGUN) )
951		return IT_NAILGUN;
952	else if(self.ammo_shells >= 1 && (it & IT_SHOTGUN)  )
953		return IT_SHOTGUN;
954
955/*
956	if(self.ammo_rockets >= 1 && (it & IT_ROCKET_LAUNCHER) )
957		return IT_ROCKET_LAUNCHER;
958	else if(self.ammo_rockets >= 1 && (it & IT_GRENADE_LAUNCHER) )
959		return IT_GRENADE_LAUNCHER;
960
961*/
962
963	return IT_AXE;
964};
965
966float() W_CheckNoAmmo =
967{
968	if (self.currentammo > 0)
969		return TRUE;
970
971	if (self.weapon == IT_AXE)
972		return TRUE;
973
974	self.weapon = W_BestWeapon ();
975
976	W_SetCurrentAmmo ();
977
978// drop the weapon down
979	return FALSE;
980};
981
982/*
983============
984W_Attack
985
986An attack impulse can be triggered now
987============
988*/
989void()  player_axe1;
990void()  player_axeb1;
991void()  player_axec1;
992void()  player_axed1;
993void()  player_shot1;
994void()  player_nail1;
995void()  player_light1;
996void()  player_rocket1;
997
998void() W_Attack =
999{
1000	local   float   r;
1001
1002	if (!W_CheckNoAmmo ())
1003		return;
1004
1005	makevectors     (self.v_angle);                 // calculate forward angle for velocity
1006	self.show_hostile = time + 1;   // wake monsters up
1007
1008	if (self.weapon == IT_AXE)
1009	{
1010		self.attack_finished = time + 0.5;
1011		sound (self, CHAN_WEAPON, "weapons/ax1.wav", 1, ATTN_NORM);
1012		r = random();
1013		if (r < 0.25)
1014			player_axe1 ();
1015		else if (r<0.5)
1016			player_axeb1 ();
1017		else if (r<0.75)
1018			player_axec1 ();
1019		else
1020			player_axed1 ();
1021	}
1022	else if (self.weapon == IT_SHOTGUN)
1023	{
1024		player_shot1 ();
1025		self.attack_finished = time + 0.5;
1026		W_FireShotgun ();
1027	}
1028	else if (self.weapon == IT_SUPER_SHOTGUN)
1029	{
1030		player_shot1 ();
1031		self.attack_finished = time + 0.7;
1032		W_FireSuperShotgun ();
1033	}
1034	else if (self.weapon == IT_NAILGUN)
1035	{
1036		player_nail1 ();
1037	}
1038	else if (self.weapon == IT_SUPER_NAILGUN)
1039	{
1040		player_nail1 ();
1041	}
1042	else if (self.weapon == IT_GRENADE_LAUNCHER)
1043	{
1044		player_rocket1();
1045		self.attack_finished = time + 0.6;
1046		W_FireGrenade();
1047	}
1048	else if (self.weapon == IT_ROCKET_LAUNCHER)
1049	{
1050		player_rocket1();
1051		self.attack_finished = time + 0.8;
1052		W_FireRocket();
1053	}
1054	else if (self.weapon == IT_LIGHTNING)
1055	{
1056		self.attack_finished = time + 0.1;
1057		sound (self, CHAN_AUTO, "weapons/lstart.wav", 1, ATTN_NORM);
1058		player_light1();
1059	}
1060};
1061
1062/*
1063============
1064W_ChangeWeapon
1065
1066============
1067*/
1068void() W_ChangeWeapon =
1069{
1070	local   float   it, am, fl;
1071
1072	it = self.items;
1073	am = 0;
1074
1075	if (self.impulse == 1)
1076	{
1077		fl = IT_AXE;
1078	}
1079	else if (self.impulse == 2)
1080	{
1081		fl = IT_SHOTGUN;
1082		if (self.ammo_shells < 1)
1083			am = 1;
1084	}
1085	else if (self.impulse == 3)
1086	{
1087		fl = IT_SUPER_SHOTGUN;
1088		if (self.ammo_shells < 2)
1089			am = 1;
1090	}
1091	else if (self.impulse == 4)
1092	{
1093		fl = IT_NAILGUN;
1094		if (self.ammo_nails < 1)
1095			am = 1;
1096	}
1097	else if (self.impulse == 5)
1098	{
1099		fl = IT_SUPER_NAILGUN;
1100		if (self.ammo_nails < 2)
1101			am = 1;
1102	}
1103	else if (self.impulse == 6)
1104	{
1105		fl = IT_GRENADE_LAUNCHER;
1106		if (self.ammo_rockets < 1)
1107			am = 1;
1108	}
1109	else if (self.impulse == 7)
1110	{
1111		fl = IT_ROCKET_LAUNCHER;
1112		if (self.ammo_rockets < 1)
1113			am = 1;
1114	}
1115	else if (self.impulse == 8)
1116	{
1117		fl = IT_LIGHTNING;
1118		if (self.ammo_cells < 1)
1119			am = 1;
1120	}
1121
1122	self.impulse = 0;
1123
1124	if (!(self.items & fl))
1125	{       // don't have the weapon or the ammo
1126		sprint (self, PRINT_HIGH, "no weapon.\n");
1127		return;
1128	}
1129
1130	if (am)
1131	{       // don't have the ammo
1132		sprint (self, PRINT_HIGH, "not enough ammo.\n");
1133		return;
1134	}
1135
1136//
1137// set weapon, set ammo
1138//
1139	self.weapon = fl;
1140	W_SetCurrentAmmo ();
1141};
1142
1143/*
1144============
1145CheatCommand
1146============
1147*/
1148void() CheatCommand =
1149{
1150//      if (deathmatch || coop)
1151		return;
1152
1153	self.ammo_rockets = 100;
1154	self.ammo_nails = 200;
1155	self.ammo_shells = 100;
1156	self.items = self.items |
1157		IT_AXE |
1158		IT_SHOTGUN |
1159		IT_SUPER_SHOTGUN |
1160		IT_NAILGUN |
1161		IT_SUPER_NAILGUN |
1162		IT_GRENADE_LAUNCHER |
1163		IT_ROCKET_LAUNCHER |
1164		IT_KEY1 | IT_KEY2;
1165
1166	self.ammo_cells = 200;
1167	self.items = self.items | IT_LIGHTNING;
1168
1169	self.weapon = IT_ROCKET_LAUNCHER;
1170	self.impulse = 0;
1171	W_SetCurrentAmmo ();
1172};
1173
1174/*
1175============
1176CycleWeaponCommand
1177
1178Go to the next weapon with ammo
1179============
1180*/
1181void() CycleWeaponCommand =
1182{
1183	local   float   it, am;
1184
1185	it = self.items;
1186	self.impulse = 0;
1187
1188	while (1)
1189	{
1190		am = 0;
1191
1192		if (self.weapon == IT_LIGHTNING)
1193		{
1194			self.weapon = IT_AXE;
1195		}
1196		else if (self.weapon == IT_AXE)
1197		{
1198			self.weapon = IT_SHOTGUN;
1199			if (self.ammo_shells < 1)
1200				am = 1;
1201		}
1202		else if (self.weapon == IT_SHOTGUN)
1203		{
1204			self.weapon = IT_SUPER_SHOTGUN;
1205			if (self.ammo_shells < 2)
1206				am = 1;
1207		}
1208		else if (self.weapon == IT_SUPER_SHOTGUN)
1209		{
1210			self.weapon = IT_NAILGUN;
1211			if (self.ammo_nails < 1)
1212				am = 1;
1213		}
1214		else if (self.weapon == IT_NAILGUN)
1215		{
1216			self.weapon = IT_SUPER_NAILGUN;
1217			if (self.ammo_nails < 2)
1218				am = 1;
1219		}
1220		else if (self.weapon == IT_SUPER_NAILGUN)
1221		{
1222			self.weapon = IT_GRENADE_LAUNCHER;
1223			if (self.ammo_rockets < 1)
1224				am = 1;
1225		}
1226		else if (self.weapon == IT_GRENADE_LAUNCHER)
1227		{
1228			self.weapon = IT_ROCKET_LAUNCHER;
1229			if (self.ammo_rockets < 1)
1230				am = 1;
1231		}
1232		else if (self.weapon == IT_ROCKET_LAUNCHER)
1233		{
1234			self.weapon = IT_LIGHTNING;
1235			if (self.ammo_cells < 1)
1236				am = 1;
1237		}
1238
1239		if ( (self.items & self.weapon) && am == 0)
1240		{
1241			W_SetCurrentAmmo ();
1242			return;
1243		}
1244	}
1245
1246};
1247
1248
1249/*
1250============
1251CycleWeaponReverseCommand
1252
1253Go to the prev weapon with ammo
1254============
1255*/
1256void() CycleWeaponReverseCommand =
1257{
1258	local   float   it, am;
1259
1260	it = self.items;
1261	self.impulse = 0;
1262
1263	while (1)
1264	{
1265		am = 0;
1266
1267		if (self.weapon == IT_LIGHTNING)
1268		{
1269			self.weapon = IT_ROCKET_LAUNCHER;
1270			if (self.ammo_rockets < 1)
1271				am = 1;
1272		}
1273		else if (self.weapon == IT_ROCKET_LAUNCHER)
1274		{
1275			self.weapon = IT_GRENADE_LAUNCHER;
1276			if (self.ammo_rockets < 1)
1277				am = 1;
1278		}
1279		else if (self.weapon == IT_GRENADE_LAUNCHER)
1280		{
1281			self.weapon = IT_SUPER_NAILGUN;
1282			if (self.ammo_nails < 2)
1283				am = 1;
1284		}
1285		else if (self.weapon == IT_SUPER_NAILGUN)
1286		{
1287			self.weapon = IT_NAILGUN;
1288			if (self.ammo_nails < 1)
1289				am = 1;
1290		}
1291		else if (self.weapon == IT_NAILGUN)
1292		{
1293			self.weapon = IT_SUPER_SHOTGUN;
1294			if (self.ammo_shells < 2)
1295				am = 1;
1296		}
1297		else if (self.weapon == IT_SUPER_SHOTGUN)
1298		{
1299			self.weapon = IT_SHOTGUN;
1300			if (self.ammo_shells < 1)
1301				am = 1;
1302		}
1303		else if (self.weapon == IT_SHOTGUN)
1304		{
1305			self.weapon = IT_AXE;
1306		}
1307		else if (self.weapon == IT_AXE)
1308		{
1309			self.weapon = IT_LIGHTNING;
1310			if (self.ammo_cells < 1)
1311				am = 1;
1312		}
1313
1314		if ( (it & self.weapon) && am == 0)
1315		{
1316			W_SetCurrentAmmo ();
1317			return;
1318		}
1319	}
1320
1321};
1322
1323
1324/*
1325============
1326ServerflagsCommand
1327
1328Just for development
1329============
1330*/
1331void() ServerflagsCommand =
1332{
1333	serverflags = serverflags * 2 + 1;
1334};
1335
1336
1337/*
1338============
1339ImpulseCommands
1340
1341============
1342*/
1343void() ImpulseCommands =
1344{
1345	if (self.impulse >= 1 && self.impulse <= 8)
1346		W_ChangeWeapon ();
1347
1348	if (self.impulse == 9)
1349		CheatCommand ();
1350	if (self.impulse == 10)
1351		CycleWeaponCommand ();
1352	if (self.impulse == 11)
1353		ServerflagsCommand ();
1354	if (self.impulse == 12)
1355		CycleWeaponReverseCommand ();
1356
1357	self.impulse = 0;
1358};
1359
1360/*
1361============
1362W_WeaponFrame
1363
1364Called every frame so impulse events can be handled as well as possible
1365============
1366*/
1367void() W_WeaponFrame =
1368{
1369	if (time < self.attack_finished)
1370		return;
1371
1372	ImpulseCommands ();
1373
1374// check for attack
1375	if (self.button0)
1376	{
1377		SuperDamageSound ();
1378		W_Attack ();
1379	}
1380};
1381
1382/*
1383========
1384SuperDamageSound
1385
1386Plays sound if needed
1387========
1388*/
1389void() SuperDamageSound =
1390{
1391	if (self.super_damage_finished > time)
1392	{
1393		if (self.super_sound < time)
1394		{
1395			self.super_sound = time + 1;
1396			sound (self, CHAN_BODY, "items/damage3.wav", 1, ATTN_NORM);
1397		}
1398	}
1399	return;
1400};
1401
1402
1403