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