1void() W_SetCurrentAmmo;
2/* ALL LIGHTS SHOULD BE 0 1 0 IN COLOR ALL OTHER ITEMS SHOULD
3BE .8 .3 .4 IN COLOR */
4
5
6void() SUB_regen =
7{
8	self.model = self.mdl;		// restore original model
9	self.solid = SOLID_TRIGGER;	// allow it to be touched again
10	sound (self, CHAN_VOICE, "items/itembk2.wav", 1, ATTN_NORM);	// play respawn sound
11	setorigin (self, self.origin);
12};
13
14
15
16/*QUAKED noclass (0 0 0) (-8 -8 -8) (8 8 8)
17prints a warning message when spawned
18*/
19void() noclass =
20{
21	dprint ("noclass spawned at");
22	dprint (vtos(self.origin));
23	dprint ("\n");
24	remove (self);
25};
26
27
28
29/*
30============
31PlaceItem
32
33plants the object on the floor
34============
35*/
36void() PlaceItem =
37{
38	local float	oldz;
39
40	self.mdl = self.model;		// so it can be restored on respawn
41	self.flags = FL_ITEM;		// make extra wide
42	self.solid = SOLID_TRIGGER;
43	self.movetype = MOVETYPE_TOSS;
44	self.velocity = '0 0 0';
45	self.origin_z = self.origin_z + 6;
46	oldz = self.origin_z;
47	if (!droptofloor())
48	{
49		dprint ("Bonus item fell out of level at ");
50		dprint (vtos(self.origin));
51		dprint ("\n");
52		remove(self);
53		return;
54	}
55};
56
57/*
58============
59StartItem
60
61Sets the clipping size and plants the object on the floor
62============
63*/
64void() StartItem =
65{
66	self.nextthink = time + 0.2;	// items start after other solids
67	self.think = PlaceItem;
68};
69
70/*
71=========================================================================
72
73HEALTH BOX
74
75=========================================================================
76*/
77//
78// T_Heal: add health to an entity, limiting health to max_health
79// "ignore" will ignore max_health limit
80//
81float (entity e, float healamount, float ignore) T_Heal =
82{
83	if (e.health <= 0)
84		return 0;
85	if ((!ignore) && (e.health >= other.max_health))
86		return 0;
87	healamount = ceil(healamount);
88
89	e.health = e.health + healamount;
90	if ((!ignore) && (e.health >= other.max_health))
91		e.health = other.max_health;
92
93	if (e.health > 250)
94		e.health = 250;
95	return 1;
96};
97
98/*QUAKED item_health (.3 .3 1) (0 0 0) (32 32 32) rotten megahealth
99Health box. Normally gives 25 points.
100Rotten box heals 5-10 points,
101megahealth will add 100 health, then
102rot you down to your maximum health limit,
103one point per second.
104*/
105
106float	H_ROTTEN = 1;
107float	H_MEGA = 2;
108.float	healamount, healtype;
109void() health_touch;
110void() item_megahealth_rot;
111
112void() item_health =
113{
114	self.touch = health_touch;
115
116	if (self.spawnflags & H_ROTTEN)
117	{
118		precache_model("maps/b_bh10.bsp");
119
120		precache_sound("items/r_item1.wav");
121		setmodel(self, "maps/b_bh10.bsp");
122		self.noise = "items/r_item1.wav";
123		self.healamount = 15;
124		self.healtype = 0;
125	}
126	else
127	if (self.spawnflags & H_MEGA)
128	{
129		precache_model("maps/b_bh100.bsp");
130		precache_sound("items/r_item2.wav");
131		setmodel(self, "maps/b_bh100.bsp");
132		self.noise = "items/r_item2.wav";
133		self.healamount = 100;
134		self.healtype = 2;
135	}
136	else
137	{
138		precache_model("maps/b_bh25.bsp");
139		precache_sound("items/health1.wav");
140		setmodel(self, "maps/b_bh25.bsp");
141		self.noise = "items/health1.wav";
142		self.healamount = 25;
143		self.healtype = 1;
144	}
145	setsize (self, '0 0 0', '32 32 56');
146	StartItem ();
147};
148
149
150void() health_touch =
151{
152	local	float amount;
153	local	string	s;
154
155	if (other.classname != "player")
156		return;
157
158	if (self.healtype == 2) // Megahealth?  Ignore max_health...
159	{
160		if (other.health >= 250)
161			return;
162		if (!T_Heal(other, self.healamount, 1))
163			return;
164	}
165	else
166	{
167		if (!T_Heal(other, self.healamount, 0))
168			return;
169	}
170
171	sprint(other, "You receive ");
172	s = ftos(self.healamount);
173	sprint(other, s);
174	sprint(other, " health\n");
175
176// health touch sound
177	sound(other, CHAN_ITEM, self.noise, 1, ATTN_NORM);
178
179	stuffcmd (other, "bf\n");
180
181	self.model = string_null;
182	self.solid = SOLID_NOT;
183
184	// Megahealth = rot down the player's super health
185	if (self.healtype == 2)
186	{
187		other.items = other.items | IT_SUPERHEALTH;
188		self.nextthink = time + 5;
189		self.think = item_megahealth_rot;
190		self.owner = other;
191	}
192	else
193	{
194		if (deathmatch != 2)		// deathmatch 2 is the silly old rules
195		{
196			if (deathmatch)
197				self.nextthink = time + 20;
198			self.think = SUB_regen;
199		}
200	}
201
202	activator = other;
203	SUB_UseTargets();				// fire all targets / killtargets
204};
205
206void() item_megahealth_rot =
207{
208	other = self.owner;
209
210	if (other.health > other.max_health)
211	{
212		other.health = other.health - 1;
213		self.nextthink = time + 1;
214		return;
215	}
216
217// it is possible for a player to die and respawn between rots, so don't
218// just blindly subtract the flag off
219	other.items = other.items - (other.items & IT_SUPERHEALTH);
220
221	if (deathmatch == 1)	// deathmatch 2 is silly old rules
222	{
223		self.nextthink = time + 20;
224		self.think = SUB_regen;
225	}
226};
227
228/*
229===============================================================================
230
231ARMOR
232
233===============================================================================
234*/
235
236void() armor_touch;
237
238void() armor_touch =
239{
240	local	float	type, value, bit;
241
242	if (other.health <= 0)
243		return;
244	if (other.classname != "player")
245		return;
246
247	if (self.classname == "item_armor1")
248	{
249		type = 0.3;
250		value = 100;
251		bit = IT_ARMOR1;
252	}
253	if (self.classname == "item_armor2")
254	{
255		type = 0.6;
256		value = 150;
257		bit = IT_ARMOR2;
258	}
259	if (self.classname == "item_armorInv")
260	{
261		type = 0.8;
262		value = 200;
263		bit = IT_ARMOR3;
264	}
265	if (other.armortype*other.armorvalue >= type*value)
266		return;
267
268	other.armortype = type;
269	other.armorvalue = value;
270	other.items = other.items - (other.items & (IT_ARMOR1 | IT_ARMOR2 | IT_ARMOR3)) + bit;
271
272	self.solid = SOLID_NOT;
273	self.model = string_null;
274	if (deathmatch == 1)
275		self.nextthink = time + 20;
276	self.think = SUB_regen;
277
278	sprint(other, "You got armor\n");
279// armor touch sound
280	sound(other, CHAN_ITEM, "items/armor1.wav", 1, ATTN_NORM);
281	stuffcmd (other, "bf\n");
282
283	activator = other;
284	SUB_UseTargets();				// fire all targets / killtargets
285};
286
287
288/*QUAKED item_armor1 (0 .5 .8) (-16 -16 0) (16 16 32)
289*/
290
291void() item_armor1 =
292{
293	self.touch = armor_touch;
294	precache_model ("progs/armor.mdl");
295	setmodel (self, "progs/armor.mdl");
296	self.skin = 0;
297	setsize (self, '-16 -16 0', '16 16 56');
298	StartItem ();
299};
300
301/*QUAKED item_armor2 (0 .5 .8) (-16 -16 0) (16 16 32)
302*/
303
304void() item_armor2 =
305{
306	self.touch = armor_touch;
307	precache_model ("progs/armor.mdl");
308	setmodel (self, "progs/armor.mdl");
309	self.skin = 1;
310	setsize (self, '-16 -16 0', '16 16 56');
311	StartItem ();
312};
313
314/*QUAKED item_armorInv (0 .5 .8) (-16 -16 0) (16 16 32)
315*/
316
317void() item_armorInv =
318{
319	self.touch = armor_touch;
320	precache_model ("progs/armor.mdl");
321	setmodel (self, "progs/armor.mdl");
322	self.skin = 2;
323	setsize (self, '-16 -16 0', '16 16 56');
324	StartItem ();
325};
326
327/*
328===============================================================================
329
330WEAPONS
331
332===============================================================================
333*/
334
335void() bound_other_ammo =
336{
337	if (other.ammo_shells > 100)
338		other.ammo_shells = 100;
339	if (other.ammo_nails > 200)
340		other.ammo_nails = 200;
341	if (other.ammo_rockets > 100)
342		other.ammo_rockets = 100;
343	if (other.ammo_cells > 100)
344		other.ammo_cells = 100;
345};
346
347
348float(float w) RankForWeapon =
349{
350	if (w == IT_LIGHTNING)
351		return 1;
352	if (w == IT_ROCKET_LAUNCHER)
353		return 2;
354	if (w == IT_SUPER_NAILGUN)
355		return 3;
356	if (w == IT_GRENADE_LAUNCHER)
357		return 4;
358	if (w == IT_SUPER_SHOTGUN)
359		return 5;
360	if (w == IT_NAILGUN)
361		return 6;
362	return 7;
363};
364
365/*
366=============
367Deathmatch_Weapon
368
369Deathmatch weapon change rules for picking up a weapon
370
371.float		ammo_shells, ammo_nails, ammo_rockets, ammo_cells;
372=============
373*/
374void(float old, float new) Deathmatch_Weapon =
375{
376	local float or, nr;
377
378// change self.weapon if desired
379	or = RankForWeapon (self.weapon);
380	nr = RankForWeapon (new);
381	if ( nr < or )
382		self.weapon = new;
383};
384
385/*
386=============
387weapon_touch
388=============
389*/
390float() W_BestWeapon;
391
392void() weapon_touch =
393{
394	local	float	hadammo, best, new, old;
395	local	entity	stemp;
396	local	float	leave;
397
398	if (!(other.flags & FL_CLIENT))
399		return;
400
401// if the player was using his best weapon, change up to the new one if better
402	stemp = self;
403	self = other;
404	best = W_BestWeapon();
405	self = stemp;
406
407	if (deathmatch == 2 || coop)
408		leave = 1;
409	else
410		leave = 0;
411
412	if (self.classname == "weapon_nailgun")
413	{
414		if (leave && (other.items & IT_NAILGUN) )
415			return;
416		hadammo = other.ammo_nails;
417		new = IT_NAILGUN;
418		other.ammo_nails = other.ammo_nails + 30;
419	}
420	else if (self.classname == "weapon_supernailgun")
421	{
422		if (leave && (other.items & IT_SUPER_NAILGUN) )
423			return;
424		hadammo = other.ammo_rockets;
425		new = IT_SUPER_NAILGUN;
426		other.ammo_nails = other.ammo_nails + 30;
427	}
428	else if (self.classname == "weapon_supershotgun")
429	{
430		if (leave && (other.items & IT_SUPER_SHOTGUN) )
431			return;
432		hadammo = other.ammo_rockets;
433		new = IT_SUPER_SHOTGUN;
434		other.ammo_shells = other.ammo_shells + 5;
435	}
436	else if (self.classname == "weapon_rocketlauncher")
437	{
438		if (leave && (other.items & IT_ROCKET_LAUNCHER) )
439			return;
440		hadammo = other.ammo_rockets;
441		new = IT_ROCKET_LAUNCHER;
442		other.ammo_rockets = other.ammo_rockets + 5;
443	}
444	else if (self.classname == "weapon_grenadelauncher")
445	{
446		if (leave && (other.items & IT_GRENADE_LAUNCHER) )
447			return;
448		hadammo = other.ammo_rockets;
449		new = IT_GRENADE_LAUNCHER;
450		other.ammo_rockets = other.ammo_rockets + 5;
451	}
452	else if (self.classname == "weapon_lightning")
453	{
454		if (leave && (other.items & IT_LIGHTNING) )
455			return;
456		hadammo = other.ammo_rockets;
457		new = IT_LIGHTNING;
458		other.ammo_cells = other.ammo_cells + 15;
459	}
460	else
461		objerror ("weapon_touch: unknown classname");
462
463	sprint (other, "You got the ");
464	sprint (other, self.netname);
465	sprint (other, "\n");
466// weapon touch sound
467	sound (other, CHAN_ITEM, "weapons/pkup.wav", 1, ATTN_NORM);
468	stuffcmd (other, "bf\n");
469
470	bound_other_ammo ();
471
472// change to the weapon
473	old = other.items;
474	other.items = other.items | new;
475
476	stemp = self;
477	self = other;
478
479	if (!deathmatch)
480		self.weapon = new;
481	else
482		Deathmatch_Weapon (old, new);
483
484	W_SetCurrentAmmo();
485
486	self = stemp;
487
488	if (leave)
489		return;
490
491// remove it in single player, or setup for respawning in deathmatch
492	self.model = string_null;
493	self.solid = SOLID_NOT;
494	if (deathmatch == 1)
495		self.nextthink = time + 30;
496	self.think = SUB_regen;
497
498	activator = other;
499	SUB_UseTargets();				// fire all targets / killtargets
500};
501
502
503/*QUAKED weapon_supershotgun (0 .5 .8) (-16 -16 0) (16 16 32)
504*/
505
506void() weapon_supershotgun =
507{
508	precache_model ("progs/g_shot.mdl");
509	setmodel (self, "progs/g_shot.mdl");
510	self.weapon = IT_SUPER_SHOTGUN;
511	self.netname = "Double-barrelled Shotgun";
512	self.touch = weapon_touch;
513	setsize (self, '-16 -16 0', '16 16 56');
514	StartItem ();
515};
516
517/*QUAKED weapon_nailgun (0 .5 .8) (-16 -16 0) (16 16 32)
518*/
519
520void() weapon_nailgun =
521{
522	precache_model ("progs/g_nail.mdl");
523	setmodel (self, "progs/g_nail.mdl");
524	self.weapon = IT_NAILGUN;
525	self.netname = "nailgun";
526	self.touch = weapon_touch;
527	setsize (self, '-16 -16 0', '16 16 56');
528	StartItem ();
529};
530
531/*QUAKED weapon_supernailgun (0 .5 .8) (-16 -16 0) (16 16 32)
532*/
533
534void() weapon_supernailgun =
535{
536	precache_model ("progs/g_nail2.mdl");
537	setmodel (self, "progs/g_nail2.mdl");
538	self.weapon = IT_SUPER_NAILGUN;
539	self.netname = "Super Nailgun";
540	self.touch = weapon_touch;
541	setsize (self, '-16 -16 0', '16 16 56');
542	StartItem ();
543};
544
545/*QUAKED weapon_grenadelauncher (0 .5 .8) (-16 -16 0) (16 16 32)
546*/
547
548void() weapon_grenadelauncher =
549{
550	precache_model ("progs/g_rock.mdl");
551	setmodel (self, "progs/g_rock.mdl");
552	self.weapon = 3;
553	self.netname = "Grenade Launcher";
554	self.touch = weapon_touch;
555	setsize (self, '-16 -16 0', '16 16 56');
556	StartItem ();
557};
558
559/*QUAKED weapon_rocketlauncher (0 .5 .8) (-16 -16 0) (16 16 32)
560*/
561
562void() weapon_rocketlauncher =
563{
564	precache_model ("progs/g_rock2.mdl");
565	setmodel (self, "progs/g_rock2.mdl");
566	self.weapon = 3;
567	self.netname = "Rocket Launcher";
568	self.touch = weapon_touch;
569	setsize (self, '-16 -16 0', '16 16 56');
570	StartItem ();
571};
572
573
574/*QUAKED weapon_lightning (0 .5 .8) (-16 -16 0) (16 16 32)
575*/
576
577void() weapon_lightning =
578{
579	precache_model ("progs/g_light.mdl");
580	setmodel (self, "progs/g_light.mdl");
581	self.weapon = 3;
582	self.netname = "Thunderbolt";
583	self.touch = weapon_touch;
584	setsize (self, '-16 -16 0', '16 16 56');
585	StartItem ();
586};
587
588
589/*
590===============================================================================
591
592AMMO
593
594===============================================================================
595*/
596
597void() ammo_touch =
598{
599local entity	stemp;
600local float		best;
601
602	if (other.classname != "player")
603		return;
604	if (other.health <= 0)
605		return;
606
607// if the player was using his best weapon, change up to the new one if better
608	stemp = self;
609	self = other;
610	best = W_BestWeapon();
611	self = stemp;
612
613
614// shotgun
615	if (self.weapon == 1)
616	{
617		if (other.ammo_shells >= 100)
618			return;
619		other.ammo_shells = other.ammo_shells + self.aflag;
620	}
621
622// spikes
623	if (self.weapon == 2)
624	{
625		if (other.ammo_nails >= 200)
626			return;
627		other.ammo_nails = other.ammo_nails + self.aflag;
628	}
629
630//	rockets
631	if (self.weapon == 3)
632	{
633		if (other.ammo_rockets >= 100)
634			return;
635		other.ammo_rockets = other.ammo_rockets + self.aflag;
636	}
637
638//	cells
639	if (self.weapon == 4)
640	{
641		if (other.ammo_cells >= 200)
642			return;
643		other.ammo_cells = other.ammo_cells + self.aflag;
644	}
645
646	bound_other_ammo ();
647
648	sprint (other, "You got the ");
649	sprint (other, self.netname);
650	sprint (other, "\n");
651// ammo touch sound
652	sound (other, CHAN_ITEM, "weapons/lock4.wav", 1, ATTN_NORM);
653	stuffcmd (other, "bf\n");
654
655// change to a better weapon if appropriate
656
657	if ( other.weapon == best )
658	{
659		stemp = self;
660		self = other;
661		self.weapon = W_BestWeapon();
662		W_SetCurrentAmmo ();
663		self = stemp;
664	}
665
666// if changed current ammo, update it
667	stemp = self;
668	self = other;
669	W_SetCurrentAmmo();
670	self = stemp;
671
672// remove it in single player, or setup for respawning in deathmatch
673	self.model = string_null;
674	self.solid = SOLID_NOT;
675	if (deathmatch == 1)
676		self.nextthink = time + 30;
677
678	self.think = SUB_regen;
679
680	activator = other;
681	SUB_UseTargets();				// fire all targets / killtargets
682};
683
684
685
686
687float WEAPON_BIG2 = 1;
688
689/*QUAKED item_shells (0 .5 .8) (0 0 0) (32 32 32) big
690*/
691
692void() item_shells =
693{
694	self.touch = ammo_touch;
695
696	if (self.spawnflags & WEAPON_BIG2)
697	{
698		precache_model ("maps/b_shell1.bsp");
699		setmodel (self, "maps/b_shell1.bsp");
700		self.aflag = 40;
701	}
702	else
703	{
704		precache_model ("maps/b_shell0.bsp");
705		setmodel (self, "maps/b_shell0.bsp");
706		self.aflag = 20;
707	}
708	self.weapon = 1;
709	self.netname = "shells";
710	setsize (self, '0 0 0', '32 32 56');
711	StartItem ();
712};
713
714/*QUAKED item_spikes (0 .5 .8) (0 0 0) (32 32 32) big
715*/
716
717void() item_spikes =
718{
719	self.touch = ammo_touch;
720
721	if (self.spawnflags & WEAPON_BIG2)
722	{
723		precache_model ("maps/b_nail1.bsp");
724		setmodel (self, "maps/b_nail1.bsp");
725		self.aflag = 50;
726	}
727	else
728	{
729		precache_model ("maps/b_nail0.bsp");
730		setmodel (self, "maps/b_nail0.bsp");
731		self.aflag = 25;
732	}
733	self.weapon = 2;
734	self.netname = "nails";
735	setsize (self, '0 0 0', '32 32 56');
736	StartItem ();
737};
738
739/*QUAKED item_rockets (0 .5 .8) (0 0 0) (32 32 32) big
740*/
741
742void() item_rockets =
743{
744	self.touch = ammo_touch;
745
746	if (self.spawnflags & WEAPON_BIG2)
747	{
748		precache_model ("maps/b_rock1.bsp");
749		setmodel (self, "maps/b_rock1.bsp");
750		self.aflag = 10;
751	}
752	else
753	{
754		precache_model ("maps/b_rock0.bsp");
755		setmodel (self, "maps/b_rock0.bsp");
756		self.aflag = 5;
757	}
758	self.weapon = 3;
759	self.netname = "rockets";
760	setsize (self, '0 0 0', '32 32 56');
761	StartItem ();
762};
763
764
765/*QUAKED item_cells (0 .5 .8) (0 0 0) (32 32 32) big
766*/
767
768void() item_cells =
769{
770	self.touch = ammo_touch;
771
772	if (self.spawnflags & WEAPON_BIG2)
773	{
774		precache_model ("maps/b_batt1.bsp");
775		setmodel (self, "maps/b_batt1.bsp");
776		self.aflag = 12;
777	}
778	else
779	{
780		precache_model ("maps/b_batt0.bsp");
781		setmodel (self, "maps/b_batt0.bsp");
782		self.aflag = 6;
783	}
784	self.weapon = 4;
785	self.netname = "cells";
786	setsize (self, '0 0 0', '32 32 56');
787	StartItem ();
788};
789
790
791/*QUAKED item_weapon (0 .5 .8) (0 0 0) (32 32 32) shotgun rocket spikes big
792DO NOT USE THIS!!!! IT WILL BE REMOVED!
793*/
794
795float WEAPON_SHOTGUN = 1;
796float WEAPON_ROCKET = 2;
797float WEAPON_SPIKES = 4;
798float WEAPON_BIG = 8;
799void() item_weapon =
800{
801	self.touch = ammo_touch;
802
803	if (self.spawnflags & WEAPON_SHOTGUN)
804	{
805		if (self.spawnflags & WEAPON_BIG)
806		{
807			precache_model ("maps/b_shell1.bsp");
808			setmodel (self, "maps/b_shell1.bsp");
809			self.aflag = 40;
810		}
811		else
812		{
813			precache_model ("maps/b_shell0.bsp");
814			setmodel (self, "maps/b_shell0.bsp");
815			self.aflag = 20;
816		}
817		self.weapon = 1;
818		self.netname = "shells";
819	}
820
821	if (self.spawnflags & WEAPON_SPIKES)
822	{
823		if (self.spawnflags & WEAPON_BIG)
824		{
825			precache_model ("maps/b_nail1.bsp");
826			setmodel (self, "maps/b_nail1.bsp");
827			self.aflag = 40;
828		}
829		else
830		{
831			precache_model ("maps/b_nail0.bsp");
832			setmodel (self, "maps/b_nail0.bsp");
833			self.aflag = 20;
834		}
835		self.weapon = 2;
836		self.netname = "spikes";
837	}
838
839	if (self.spawnflags & WEAPON_ROCKET)
840	{
841		if (self.spawnflags & WEAPON_BIG)
842		{
843			precache_model ("maps/b_rock1.bsp");
844			setmodel (self, "maps/b_rock1.bsp");
845			self.aflag = 10;
846		}
847		else
848		{
849			precache_model ("maps/b_rock0.bsp");
850			setmodel (self, "maps/b_rock0.bsp");
851			self.aflag = 5;
852		}
853		self.weapon = 3;
854		self.netname = "rockets";
855	}
856
857	setsize (self, '0 0 0', '32 32 56');
858	StartItem ();
859};
860
861
862/*
863===============================================================================
864
865KEYS
866
867===============================================================================
868*/
869
870void() key_touch =
871{
872local entity	stemp;
873local float		best;
874
875	if (other.classname != "player")
876		return;
877	if (other.health <= 0)
878		return;
879	if (other.items & self.items)
880		return;
881
882	sprint (other, "You got the ");
883	sprint (other, self.netname);
884	sprint (other,"\n");
885
886	sound (other, CHAN_ITEM, self.noise, 1, ATTN_NORM);
887	stuffcmd (other, "bf\n");
888	other.items = other.items | self.items;
889
890	if (!coop)
891	{
892		self.solid = SOLID_NOT;
893		self.model = string_null;
894	}
895
896	activator = other;
897	SUB_UseTargets();				// fire all targets / killtargets
898};
899
900
901void() key_setsounds =
902{
903	if (world.worldtype == 0)
904	{
905		precache_sound ("misc/medkey.wav");
906		self.noise = "misc/medkey.wav";
907	}
908	if (world.worldtype == 1)
909	{
910		precache_sound ("misc/runekey.wav");
911		self.noise = "misc/runekey.wav";
912	}
913	if (world.worldtype == 2)
914	{
915		precache_sound2 ("misc/basekey.wav");
916		self.noise = "misc/basekey.wav";
917	}
918};
919
920/*QUAKED item_key1 (0 .5 .8) (-16 -16 -24) (16 16 32)
921SILVER key
922In order for keys to work
923you MUST set your maps
924worldtype to one of the
925following:
9260: medieval
9271: metal
9282: base
929*/
930
931void() item_key1 =
932{
933	if (world.worldtype == 0)
934	{
935		precache_model ("progs/w_s_key.mdl");
936		setmodel (self, "progs/w_s_key.mdl");
937		self.netname = "silver key";
938	}
939	else if (world.worldtype == 1)
940	{
941		precache_model ("progs/m_s_key.mdl");
942		setmodel (self, "progs/m_s_key.mdl");
943		self.netname = "silver runekey";
944	}
945	else if (world.worldtype == 2)
946	{
947		precache_model2 ("progs/b_s_key.mdl");
948		setmodel (self, "progs/b_s_key.mdl");
949		self.netname = "silver keycard";
950	}
951	key_setsounds();
952	self.touch = key_touch;
953	self.items = IT_KEY1;
954	setsize (self, '-16 -16 -24', '16 16 32');
955	StartItem ();
956};
957
958/*QUAKED item_key2 (0 .5 .8) (-16 -16 -24) (16 16 32)
959GOLD key
960In order for keys to work
961you MUST set your maps
962worldtype to one of the
963following:
9640: medieval
9651: metal
9662: base
967*/
968
969void() item_key2 =
970{
971	if (world.worldtype == 0)
972	{
973		precache_model ("progs/w_g_key.mdl");
974		setmodel (self, "progs/w_g_key.mdl");
975		self.netname = "gold key";
976	}
977	if (world.worldtype == 1)
978	{
979		precache_model ("progs/m_g_key.mdl");
980		setmodel (self, "progs/m_g_key.mdl");
981		self.netname = "gold runekey";
982	}
983	if (world.worldtype == 2)
984	{
985		precache_model2 ("progs/b_g_key.mdl");
986		setmodel (self, "progs/b_g_key.mdl");
987		self.netname = "gold keycard";
988	}
989	key_setsounds();
990	self.touch = key_touch;
991	self.items = IT_KEY2;
992	setsize (self, '-16 -16 -24', '16 16 32');
993	StartItem ();
994};
995
996
997
998/*
999===============================================================================
1000
1001END OF LEVEL RUNES
1002
1003===============================================================================
1004*/
1005
1006void() sigil_touch =
1007{
1008local entity	stemp;
1009local float		best;
1010
1011	if (other.classname != "player")
1012		return;
1013	if (other.health <= 0)
1014		return;
1015
1016	centerprint (other, "You got the rune!");
1017
1018	sound (other, CHAN_ITEM, self.noise, 1, ATTN_NORM);
1019	stuffcmd (other, "bf\n");
1020	self.solid = SOLID_NOT;
1021	self.model = string_null;
1022	serverflags = serverflags | (self.spawnflags & 15);
1023	self.classname = "";		// so rune doors won't find it
1024
1025	activator = other;
1026	SUB_UseTargets();				// fire all targets / killtargets
1027};
1028
1029
1030/*QUAKED item_sigil (0 .5 .8) (-16 -16 -24) (16 16 32) E1 E2 E3 E4
1031End of level sigil, pick up to end episode and return to jrstart.
1032*/
1033
1034void() item_sigil =
1035{
1036	if (!self.spawnflags)
1037		objerror ("no spawnflags");
1038
1039	precache_sound ("misc/runekey.wav");
1040	self.noise = "misc/runekey.wav";
1041
1042	if (self.spawnflags & 1)
1043	{
1044		precache_model ("progs/end1.mdl");
1045		setmodel (self, "progs/end1.mdl");
1046	}
1047	if (self.spawnflags & 2)
1048	{
1049		precache_model2 ("progs/end2.mdl");
1050		setmodel (self, "progs/end2.mdl");
1051	}
1052	if (self.spawnflags & 4)
1053	{
1054		precache_model2 ("progs/end3.mdl");
1055		setmodel (self, "progs/end3.mdl");
1056	}
1057	if (self.spawnflags & 8)
1058	{
1059		precache_model2 ("progs/end4.mdl");
1060		setmodel (self, "progs/end4.mdl");
1061	}
1062
1063	self.touch = sigil_touch;
1064	setsize (self, '-16 -16 -24', '16 16 32');
1065	StartItem ();
1066};
1067
1068/*
1069===============================================================================
1070
1071POWERUPS
1072
1073===============================================================================
1074*/
1075
1076void() powerup_touch;
1077
1078
1079void() powerup_touch =
1080{
1081local entity	stemp;
1082local float		best;
1083
1084	if (other.classname != "player")
1085		return;
1086	if (other.health <= 0)
1087		return;
1088
1089	sprint (other, "You got the ");
1090	sprint (other, self.netname);
1091	sprint (other,"\n");
1092
1093	if (deathmatch)
1094	{
1095		self.mdl = self.model;
1096
1097		if ((self.classname == "item_artifact_invulnerability") ||
1098			(self.classname == "item_artifact_invisibility"))
1099			self.nextthink = time + 60*5;
1100		else
1101			self.nextthink = time + 60;
1102
1103		self.think = SUB_regen;
1104	}
1105
1106	sound (other, CHAN_VOICE, self.noise, 1, ATTN_NORM);
1107	stuffcmd (other, "bf\n");
1108	self.solid = SOLID_NOT;
1109	other.items = other.items | self.items;
1110	self.model = string_null;
1111
1112// do the apropriate action
1113	if (self.classname == "item_artifact_envirosuit")
1114	{
1115		other.rad_time = 1;
1116		other.radsuit_finished = time + 30;
1117	}
1118
1119	if (self.classname == "item_artifact_invulnerability")
1120	{
1121		other.invincible_time = 1;
1122		other.invincible_finished = time + 30;
1123	}
1124
1125	if (self.classname == "item_artifact_invisibility")
1126	{
1127		other.invisible_time = 1;
1128		other.invisible_finished = time + 30;
1129	}
1130
1131	if (self.classname == "item_artifact_super_damage")
1132	{
1133		other.super_time = 1;
1134		other.super_damage_finished = time + 30;
1135	}
1136
1137	activator = other;
1138	SUB_UseTargets();				// fire all targets / killtargets
1139};
1140
1141
1142
1143/*QUAKED item_artifact_invulnerability (0 .5 .8) (-16 -16 -24) (16 16 32)
1144Player is invulnerable for 30 seconds
1145*/
1146void() item_artifact_invulnerability =
1147{
1148	self.touch = powerup_touch;
1149
1150	precache_model ("progs/invulner.mdl");
1151	precache_sound ("items/protect.wav");
1152	precache_sound ("items/protect2.wav");
1153	precache_sound ("items/protect3.wav");
1154	self.noise = "items/protect.wav";
1155	setmodel (self, "progs/invulner.mdl");
1156	self.netname = "Pentagram of Protection";
1157	self.items = IT_INVULNERABILITY;
1158	setsize (self, '-16 -16 -24', '16 16 32');
1159	StartItem ();
1160};
1161
1162/*QUAKED item_artifact_envirosuit (0 .5 .8) (-16 -16 -24) (16 16 32)
1163Player takes no damage from water or slime for 30 seconds
1164*/
1165void() item_artifact_envirosuit =
1166{
1167	self.touch = powerup_touch;
1168
1169	precache_model ("progs/suit.mdl");
1170	precache_sound ("items/suit.wav");
1171	precache_sound ("items/suit2.wav");
1172	self.noise = "items/suit.wav";
1173	setmodel (self, "progs/suit.mdl");
1174	self.netname = "Biosuit";
1175	self.items = IT_SUIT;
1176	setsize (self, '-16 -16 -24', '16 16 32');
1177	StartItem ();
1178};
1179
1180
1181/*QUAKED item_artifact_invisibility (0 .5 .8) (-16 -16 -24) (16 16 32)
1182Player is invisible for 30 seconds
1183*/
1184void() item_artifact_invisibility =
1185{
1186	self.touch = powerup_touch;
1187
1188	precache_model ("progs/invisibl.mdl");
1189	precache_sound ("items/inv1.wav");
1190	precache_sound ("items/inv2.wav");
1191	precache_sound ("items/inv3.wav");
1192	self.noise = "items/inv1.wav";
1193	setmodel (self, "progs/invisibl.mdl");
1194	self.netname = "Ring of Shadows";
1195	self.items = IT_INVISIBILITY;
1196	setsize (self, '-16 -16 -24', '16 16 32');
1197	StartItem ();
1198};
1199
1200
1201/*QUAKED item_artifact_super_damage (0 .5 .8) (-16 -16 -24) (16 16 32)
1202The next attack from the player will do 4x damage
1203*/
1204void() item_artifact_super_damage =
1205{
1206	self.touch = powerup_touch;
1207
1208	precache_model ("progs/quaddama.mdl");
1209	precache_sound ("items/damage.wav");
1210	precache_sound ("items/damage2.wav");
1211	precache_sound ("items/damage3.wav");
1212	self.noise = "items/damage.wav";
1213	setmodel (self, "progs/quaddama.mdl");
1214	self.netname = "Quad Damage";
1215	self.items = IT_QUAD;
1216	setsize (self, '-16 -16 -24', '16 16 32');
1217	StartItem ();
1218};
1219
1220
1221
1222/*
1223===============================================================================
1224
1225PLAYER BACKPACKS
1226
1227===============================================================================
1228*/
1229
1230void() BackpackTouch =
1231{
1232	local string	s;
1233	local	float	best;
1234	local		entity	stemp;
1235
1236	if (other.classname != "player")
1237		return;
1238	if (other.health <= 0)
1239		return;
1240
1241// if the player was using his best weapon, change up to the new one if better
1242	stemp = self;
1243	self = other;
1244	best = W_BestWeapon();
1245	self = stemp;
1246
1247// change weapons
1248	other.ammo_shells = other.ammo_shells + self.ammo_shells;
1249	other.ammo_nails = other.ammo_nails + self.ammo_nails;
1250	other.ammo_rockets = other.ammo_rockets + self.ammo_rockets;
1251	other.ammo_cells = other.ammo_cells + self.ammo_cells;
1252
1253	other.items = other.items | self.items;
1254
1255	bound_other_ammo ();
1256
1257	sprint (other, "You get ");
1258
1259	if (self.ammo_shells)
1260	{
1261		s = ftos(self.ammo_shells);
1262		sprint (other, s);
1263		sprint (other, " shells  ");
1264	}
1265	if (self.ammo_nails)
1266	{
1267		s = ftos(self.ammo_nails);
1268		sprint (other, s);
1269		sprint (other, " nails ");
1270	}
1271	if (self.ammo_rockets)
1272	{
1273		s = ftos(self.ammo_rockets);
1274		sprint (other, s);
1275		sprint (other, " rockets  ");
1276	}
1277	if (self.ammo_cells)
1278	{
1279		s = ftos(self.ammo_cells);
1280		sprint (other, s);
1281		sprint (other, " cells  ");
1282	}
1283
1284	sprint (other, "\n");
1285// backpack touch sound
1286	sound (other, CHAN_ITEM, "weapons/lock4.wav", 1, ATTN_NORM);
1287	stuffcmd (other, "bf\n");
1288
1289// change to a better weapon if appropriate
1290	if ( other.weapon == best )
1291	{
1292		stemp = self;
1293		self = other;
1294		self.weapon = W_BestWeapon();
1295		self = stemp;
1296	}
1297
1298
1299	remove(self);
1300
1301	self = other;
1302	W_SetCurrentAmmo ();
1303};
1304
1305/*
1306===============
1307DropBackpack
1308===============
1309*/
1310void() DropBackpack =
1311{
1312	local entity	item;
1313
1314	if (!(self.ammo_shells + self.ammo_nails + self.ammo_rockets + self.ammo_cells))
1315		return;	// nothing in it
1316
1317	item = spawn();
1318	item.origin = self.origin - '0 0 24';
1319
1320	item.items = self.weapon;
1321
1322	item.ammo_shells = self.ammo_shells;
1323	item.ammo_nails = self.ammo_nails;
1324	item.ammo_rockets = self.ammo_rockets;
1325	item.ammo_cells = self.ammo_cells;
1326
1327	item.velocity_z = 300;
1328	item.velocity_x = -100 + (random() * 200);
1329	item.velocity_y = -100 + (random() * 200);
1330
1331	item.flags = FL_ITEM;
1332	item.solid = SOLID_TRIGGER;
1333	item.movetype = MOVETYPE_TOSS;
1334	setmodel (item, "progs/backpack.mdl");
1335	setsize (item, '-16 -16 0', '16 16 56');
1336	item.touch = BackpackTouch;
1337
1338	item.nextthink = time + 120;	// remove after 2 minutes
1339	item.think = SUB_Remove;
1340};
1341