1 /*
2  * Copyright (C) 1997-2001 Id Software, Inc.
3  *
4  * This program is free software; you can redistribute it and/or modify it under
5  * the terms of the GNU General Public License as published by the Free
6  * Software Foundation; either version 2 of the License, or (at your option)
7  * any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.
12  *
13  * See the GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along with
16  * this program; if not, write to the Free Software Foundation, Inc., 59
17  * Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18  *
19  */
20 #include "g_local.h"
21 
22 
23 qboolean	Pickup_Weapon(edict_t * ent, edict_t * other);
24 void		Use_Weapon(edict_t * ent, gitem_t * inv);
25 void		Drop_Weapon(edict_t * ent, gitem_t * inv);
26 
27 void		Weapon_Blaster(edict_t * ent);
28 void		Weapon_Shotgun(edict_t * ent);
29 void		Weapon_SuperShotgun(edict_t * ent);
30 void		Weapon_Machinegun(edict_t * ent);
31 void		Weapon_Chaingun(edict_t * ent);
32 void		Weapon_HyperBlaster(edict_t * ent);
33 void		Weapon_RocketLauncher(edict_t * ent);
34 void		Weapon_Grenade(edict_t * ent);
35 void		Weapon_GrenadeLauncher(edict_t * ent);
36 void		Weapon_Railgun(edict_t * ent);
37 void		Weapon_BFG(edict_t * ent);
38 
39 gitem_armor_t	jacketarmor_info = {25, 50, .30, .00, ARMOR_JACKET};
40 gitem_armor_t	combatarmor_info = {50, 100, .60, .30, ARMOR_COMBAT};
41 gitem_armor_t	bodyarmor_info = {100, 200, .80, .60, ARMOR_BODY};
42 
43 int	jacket_armor_index;
44 int	combat_armor_index;
45 int	body_armor_index;
46 static int	power_screen_index;
47 static int	power_shield_index;
48 
49 #define HEALTH_IGNORE_MAX	1
50 #define HEALTH_TIMED		2
51 
52 void		Use_Quad  (edict_t * ent, gitem_t * item);
53 static int	quad_drop_timeout_hack;
54 
55 /* ====================================================================== */
56 
57 /*
58  * =============== GetItemByIndex ===============
59  */
60 gitem_t        *
GetItemByIndex(int index)61 GetItemByIndex(int index)
62 {
63 	if (index == 0 || index >= game.num_items)
64 		return NULL;
65 
66 	return &itemlist[index];
67 }
68 
69 
70 /*
71  * =============== FindItemByClassname
72  *
73  * ===============
74  */
75 gitem_t        *
FindItemByClassname(char * classname)76 FindItemByClassname(char *classname)
77 {
78 	int		i;
79 	gitem_t        *it;
80 
81 	it = itemlist;
82 	for (i = 0; i < game.num_items; i++, it++) {
83 		if (!it->classname)
84 			continue;
85 		if (!Q_stricmp(it->classname, classname))
86 			return it;
87 	}
88 
89 	return NULL;
90 }
91 
92 /*
93  * =============== FindItem
94  *
95  * ===============
96  */
97 gitem_t        *
FindItem(char * pickup_name)98 FindItem(char *pickup_name)
99 {
100 	int		i;
101 	gitem_t        *it;
102 
103 	it = itemlist;
104 	for (i = 0; i < game.num_items; i++, it++) {
105 		if (!it->pickup_name)
106 			continue;
107 		if (!Q_stricmp(it->pickup_name, pickup_name))
108 			return it;
109 	}
110 
111 	return NULL;
112 }
113 
114 /* ====================================================================== */
115 
116 void
DoRespawn(edict_t * ent)117 DoRespawn(edict_t * ent)
118 {
119 	if (ent->team) {
120 		edict_t        *master;
121 		int		count;
122 		int		choice;
123 
124 		master = ent->teammaster;
125 
126 		for (count = 0, ent = master; ent; ent = ent->chain, count++);
127 
128 		choice = rand() % count;
129 
130 		for (count = 0, ent = master; count < choice; ent = ent->chain, count++);
131 	}
132 	ent->svflags &= ~SVF_NOCLIENT;
133 	ent->solid = SOLID_TRIGGER;
134 	gi.linkentity(ent);
135 
136 	/* send an effect */
137 	ent->s.event = EV_ITEM_RESPAWN;
138 }
139 
140 void
SetRespawn(edict_t * ent,float delay)141 SetRespawn(edict_t * ent, float delay)
142 {
143 	ent->flags |= FL_RESPAWN;
144 	ent->svflags |= SVF_NOCLIENT;
145 	ent->solid = SOLID_NOT;
146 	ent->nextthink = level.time + delay;
147 	ent->think = DoRespawn;
148 	gi.linkentity(ent);
149 }
150 
151 
152 /* ====================================================================== */
153 
154 qboolean
Pickup_Powerup(edict_t * ent,edict_t * other)155 Pickup_Powerup(edict_t * ent, edict_t * other)
156 {
157 	int		quantity;
158 
159 	quantity = other->client->pers.inventory[ITEM_INDEX(ent->item)];
160 	if ((skill->value == 1 && quantity >= 2) || (skill->value >= 2 && quantity >= 1))
161 		return false;
162 
163 	if ((coop->value) && (ent->item->flags & IT_STAY_COOP) && (quantity > 0))
164 		return false;
165 
166 	other->client->pers.inventory[ITEM_INDEX(ent->item)]++;
167 
168 	if (deathmatch->value) {
169 		if (!(ent->spawnflags & DROPPED_ITEM))
170 			SetRespawn(ent, ent->item->quantity);
171 		if (((int)dmflags->value & DF_INSTANT_ITEMS) || ((ent->item->use == Use_Quad) && (ent->spawnflags & DROPPED_PLAYER_ITEM))) {
172 			if ((ent->item->use == Use_Quad) && (ent->spawnflags & DROPPED_PLAYER_ITEM))
173 				quad_drop_timeout_hack = (ent->nextthink - level.time) / FRAMETIME;
174 			ent->item->use(other, ent->item);
175 		}
176 	}
177 	return true;
178 }
179 
180 void
Drop_General(edict_t * ent,gitem_t * item)181 Drop_General(edict_t * ent, gitem_t * item)
182 {
183 	Drop_Item(ent, item);
184 	ent->client->pers.inventory[ITEM_INDEX(item)]--;
185 	ValidateSelectedItem(ent);
186 }
187 
188 
189 /* ====================================================================== */
190 
191 qboolean
Pickup_Adrenaline(edict_t * ent,edict_t * other)192 Pickup_Adrenaline(edict_t * ent, edict_t * other)
193 {
194 	if (!deathmatch->value)
195 		other->max_health += 1;
196 
197 	if (other->health < other->max_health)
198 		other->health = other->max_health;
199 
200 	if (!(ent->spawnflags & DROPPED_ITEM) && (deathmatch->value))
201 		SetRespawn(ent, ent->item->quantity);
202 
203 	return true;
204 }
205 
206 qboolean
Pickup_AncientHead(edict_t * ent,edict_t * other)207 Pickup_AncientHead(edict_t * ent, edict_t * other)
208 {
209 	other->max_health += 2;
210 
211 	if (!(ent->spawnflags & DROPPED_ITEM) && (deathmatch->value))
212 		SetRespawn(ent, ent->item->quantity);
213 
214 	return true;
215 }
216 
217 qboolean
Pickup_Bandolier(edict_t * ent,edict_t * other)218 Pickup_Bandolier(edict_t * ent, edict_t * other)
219 {
220 	gitem_t        *item;
221 	int		index;
222 
223 	if (other->client->pers.max_bullets < 250)
224 		other->client->pers.max_bullets = 250;
225 	if (other->client->pers.max_shells < 150)
226 		other->client->pers.max_shells = 150;
227 	if (other->client->pers.max_cells < 250)
228 		other->client->pers.max_cells = 250;
229 	if (other->client->pers.max_slugs < 75)
230 		other->client->pers.max_slugs = 75;
231 
232 	item = FindItem("Bullets");
233 	if (item) {
234 		index = ITEM_INDEX(item);
235 		other->client->pers.inventory[index] += item->quantity;
236 		if (other->client->pers.inventory[index] > other->client->pers.max_bullets)
237 			other->client->pers.inventory[index] = other->client->pers.max_bullets;
238 	}
239 	item = FindItem("Shells");
240 	if (item) {
241 		index = ITEM_INDEX(item);
242 		other->client->pers.inventory[index] += item->quantity;
243 		if (other->client->pers.inventory[index] > other->client->pers.max_shells)
244 			other->client->pers.inventory[index] = other->client->pers.max_shells;
245 	}
246 	if (!(ent->spawnflags & DROPPED_ITEM) && (deathmatch->value))
247 		SetRespawn(ent, ent->item->quantity);
248 
249 	return true;
250 }
251 
252 qboolean
Pickup_Pack(edict_t * ent,edict_t * other)253 Pickup_Pack(edict_t * ent, edict_t * other)
254 {
255 	gitem_t        *item;
256 	int		index;
257 
258 	if (other->client->pers.max_bullets < 300)
259 		other->client->pers.max_bullets = 300;
260 	if (other->client->pers.max_shells < 200)
261 		other->client->pers.max_shells = 200;
262 	if (other->client->pers.max_rockets < 100)
263 		other->client->pers.max_rockets = 100;
264 	if (other->client->pers.max_grenades < 100)
265 		other->client->pers.max_grenades = 100;
266 	if (other->client->pers.max_cells < 300)
267 		other->client->pers.max_cells = 300;
268 	if (other->client->pers.max_slugs < 100)
269 		other->client->pers.max_slugs = 100;
270 
271 	item = FindItem("Bullets");
272 	if (item) {
273 		index = ITEM_INDEX(item);
274 		other->client->pers.inventory[index] += item->quantity;
275 		if (other->client->pers.inventory[index] > other->client->pers.max_bullets)
276 			other->client->pers.inventory[index] = other->client->pers.max_bullets;
277 	}
278 	item = FindItem("Shells");
279 	if (item) {
280 		index = ITEM_INDEX(item);
281 		other->client->pers.inventory[index] += item->quantity;
282 		if (other->client->pers.inventory[index] > other->client->pers.max_shells)
283 			other->client->pers.inventory[index] = other->client->pers.max_shells;
284 	}
285 	item = FindItem("Cells");
286 	if (item) {
287 		index = ITEM_INDEX(item);
288 		other->client->pers.inventory[index] += item->quantity;
289 		if (other->client->pers.inventory[index] > other->client->pers.max_cells)
290 			other->client->pers.inventory[index] = other->client->pers.max_cells;
291 	}
292 	item = FindItem("Grenades");
293 	if (item) {
294 		index = ITEM_INDEX(item);
295 		other->client->pers.inventory[index] += item->quantity;
296 		if (other->client->pers.inventory[index] > other->client->pers.max_grenades)
297 			other->client->pers.inventory[index] = other->client->pers.max_grenades;
298 	}
299 	item = FindItem("Rockets");
300 	if (item) {
301 		index = ITEM_INDEX(item);
302 		other->client->pers.inventory[index] += item->quantity;
303 		if (other->client->pers.inventory[index] > other->client->pers.max_rockets)
304 			other->client->pers.inventory[index] = other->client->pers.max_rockets;
305 	}
306 	item = FindItem("Slugs");
307 	if (item) {
308 		index = ITEM_INDEX(item);
309 		other->client->pers.inventory[index] += item->quantity;
310 		if (other->client->pers.inventory[index] > other->client->pers.max_slugs)
311 			other->client->pers.inventory[index] = other->client->pers.max_slugs;
312 	}
313 	if (!(ent->spawnflags & DROPPED_ITEM) && (deathmatch->value))
314 		SetRespawn(ent, ent->item->quantity);
315 
316 	return true;
317 }
318 
319 /* ====================================================================== */
320 
321 void
Use_Quad(edict_t * ent,gitem_t * item)322 Use_Quad(edict_t * ent, gitem_t * item)
323 {
324 	int		timeout;
325 
326 	ent->client->pers.inventory[ITEM_INDEX(item)]--;
327 	ValidateSelectedItem(ent);
328 
329 	if (quad_drop_timeout_hack) {
330 		timeout = quad_drop_timeout_hack;
331 		quad_drop_timeout_hack = 0;
332 	} else {
333 		timeout = 300;
334 	}
335 
336 	if (ent->client->quad_framenum > level.framenum)
337 		ent->client->quad_framenum += timeout;
338 	else
339 		ent->client->quad_framenum = level.framenum + timeout;
340 
341 	gi.sound(ent, CHAN_ITEM, gi.soundindex("items/damage.wav"), 1, ATTN_NORM, 0);
342 }
343 
344 /* ====================================================================== */
345 
346 void
Use_Breather(edict_t * ent,gitem_t * item)347 Use_Breather(edict_t * ent, gitem_t * item)
348 {
349 	ent->client->pers.inventory[ITEM_INDEX(item)]--;
350 	ValidateSelectedItem(ent);
351 
352 	if (ent->client->breather_framenum > level.framenum)
353 		ent->client->breather_framenum += 300;
354 	else
355 		ent->client->breather_framenum = level.framenum + 300;
356 
357 	/*
358 	 * gi.sound(ent, CHAN_ITEM, gi.soundindex("items/damage.wav"), 1,
359 	 * ATTN_NORM, 0);
360 	 */
361 }
362 
363 /* ====================================================================== */
364 
365 void
Use_Envirosuit(edict_t * ent,gitem_t * item)366 Use_Envirosuit(edict_t * ent, gitem_t * item)
367 {
368 	ent->client->pers.inventory[ITEM_INDEX(item)]--;
369 	ValidateSelectedItem(ent);
370 
371 	if (ent->client->enviro_framenum > level.framenum)
372 		ent->client->enviro_framenum += 300;
373 	else
374 		ent->client->enviro_framenum = level.framenum + 300;
375 
376 	/*
377 	 * gi.sound(ent, CHAN_ITEM, gi.soundindex("items/damage.wav"), 1,
378 	 * ATTN_NORM, 0);
379 	 */
380 }
381 
382 /* ====================================================================== */
383 
384 void
Use_Invulnerability(edict_t * ent,gitem_t * item)385 Use_Invulnerability(edict_t * ent, gitem_t * item)
386 {
387 	ent->client->pers.inventory[ITEM_INDEX(item)]--;
388 	ValidateSelectedItem(ent);
389 
390 	if (ent->client->invincible_framenum > level.framenum)
391 		ent->client->invincible_framenum += 300;
392 	else
393 		ent->client->invincible_framenum = level.framenum + 300;
394 
395 	gi.sound(ent, CHAN_ITEM, gi.soundindex("items/protect.wav"), 1, ATTN_NORM, 0);
396 }
397 
398 /* ====================================================================== */
399 
400 void
Use_Silencer(edict_t * ent,gitem_t * item)401 Use_Silencer(edict_t * ent, gitem_t * item)
402 {
403 	ent->client->pers.inventory[ITEM_INDEX(item)]--;
404 	ValidateSelectedItem(ent);
405 	ent->client->silencer_shots += 30;
406 
407 	/*
408 	 * gi.sound(ent, CHAN_ITEM, gi.soundindex("items/damage.wav"), 1,
409 	 * ATTN_NORM, 0);
410 	 */
411 }
412 
413 /* ====================================================================== */
414 
415 qboolean
Pickup_Key(edict_t * ent,edict_t * other)416 Pickup_Key(edict_t * ent, edict_t * other)
417 {
418 	if (coop->value) {
419 		if (strcmp(ent->classname, "key_power_cube") == 0) {
420 			if (other->client->pers.power_cubes & ((ent->spawnflags & 0x0000ff00) >> 8))
421 				return false;
422 			other->client->pers.inventory[ITEM_INDEX(ent->item)]++;
423 			other->client->pers.power_cubes |= ((ent->spawnflags & 0x0000ff00) >> 8);
424 		} else {
425 			if (other->client->pers.inventory[ITEM_INDEX(ent->item)])
426 				return false;
427 			other->client->pers.inventory[ITEM_INDEX(ent->item)] = 1;
428 		}
429 		return true;
430 	}
431 	other->client->pers.inventory[ITEM_INDEX(ent->item)]++;
432 	return true;
433 }
434 
435 /* ====================================================================== */
436 
437 qboolean
Add_Ammo(edict_t * ent,gitem_t * item,int count)438 Add_Ammo(edict_t * ent, gitem_t * item, int count)
439 {
440 	int		index;
441 	int		max;
442 
443 	if (!ent->client)
444 		return false;
445 
446 	if (item->tag == AMMO_BULLETS)
447 		max = ent->client->pers.max_bullets;
448 	else if (item->tag == AMMO_SHELLS)
449 		max = ent->client->pers.max_shells;
450 	else if (item->tag == AMMO_ROCKETS)
451 		max = ent->client->pers.max_rockets;
452 	else if (item->tag == AMMO_GRENADES)
453 		max = ent->client->pers.max_grenades;
454 	else if (item->tag == AMMO_CELLS)
455 		max = ent->client->pers.max_cells;
456 	else if (item->tag == AMMO_SLUGS)
457 		max = ent->client->pers.max_slugs;
458 	else
459 		return false;
460 
461 	index = ITEM_INDEX(item);
462 
463 	if (ent->client->pers.inventory[index] == max)
464 		return false;
465 
466 	ent->client->pers.inventory[index] += count;
467 
468 	if (ent->client->pers.inventory[index] > max)
469 		ent->client->pers.inventory[index] = max;
470 
471 	return true;
472 }
473 
474 qboolean
Pickup_Ammo(edict_t * ent,edict_t * other)475 Pickup_Ammo(edict_t * ent, edict_t * other)
476 {
477 	int		oldcount;
478 	int		count;
479 	qboolean	weapon;
480 
481 	weapon = (ent->item->flags & IT_WEAPON);
482 	if ((weapon) && ((int)dmflags->value & DF_INFINITE_AMMO))
483 		count = 1000;
484 	else if (ent->count)
485 		count = ent->count;
486 	else
487 		count = ent->item->quantity;
488 
489 	oldcount = other->client->pers.inventory[ITEM_INDEX(ent->item)];
490 
491 	if (!Add_Ammo(other, ent->item, count))
492 		return false;
493 
494 	if (weapon && !oldcount) {
495 		if (other->client->pers.weapon != ent->item && (!deathmatch->value || other->client->pers.weapon == FindItem("blaster")))
496 			other->client->newweapon = ent->item;
497 	}
498 	if (!(ent->spawnflags & (DROPPED_ITEM | DROPPED_PLAYER_ITEM)) && (deathmatch->value))
499 		SetRespawn(ent, 30);
500 	return true;
501 }
502 
503 void
Drop_Ammo(edict_t * ent,gitem_t * item)504 Drop_Ammo(edict_t * ent, gitem_t * item)
505 {
506 	edict_t        *dropped;
507 	int		index;
508 
509 	index = ITEM_INDEX(item);
510 	dropped = Drop_Item(ent, item);
511 	if (ent->client->pers.inventory[index] >= item->quantity)
512 		dropped->count = item->quantity;
513 	else
514 		dropped->count = ent->client->pers.inventory[index];
515 
516 	if (ent->client->pers.weapon &&
517 	    ent->client->pers.weapon->tag == AMMO_GRENADES &&
518 	    item->tag == AMMO_GRENADES &&
519 	    ent->client->pers.inventory[index] - dropped->count <= 0) {
520 #ifdef WITH_ACEBOT
521 		safe_cprintf
522 #else
523 		gi.cprintf
524 #endif
525 		    (ent, PRINT_HIGH, "Can't drop current weapon\n");
526 		G_FreeEdict(dropped);
527 		return;
528 	}
529 	ent->client->pers.inventory[index] -= dropped->count;
530 	ValidateSelectedItem(ent);
531 }
532 
533 
534 /* ====================================================================== */
535 
536 void
MegaHealth_think(edict_t * self)537 MegaHealth_think(edict_t * self)
538 {
539 	if (self->owner->health > self->owner->max_health) {
540 		self->nextthink = level.time + 1;
541 		self->owner->health -= 1;
542 		return;
543 	}
544 	if (!(self->spawnflags & DROPPED_ITEM) && (deathmatch->value))
545 		SetRespawn(self, 20);
546 	else
547 		G_FreeEdict(self);
548 }
549 
550 qboolean
Pickup_Health(edict_t * ent,edict_t * other)551 Pickup_Health(edict_t * ent, edict_t * other)
552 {
553 	if (!(ent->style & HEALTH_IGNORE_MAX))
554 		if (other->health >= other->max_health)
555 			return false;
556 
557 	other->health += ent->count;
558 
559 	if (!(ent->style & HEALTH_IGNORE_MAX)) {
560 		if (other->health > other->max_health)
561 			other->health = other->max_health;
562 	}
563 	if (ent->style & HEALTH_TIMED) {
564 		ent->think = MegaHealth_think;
565 		ent->nextthink = level.time + 5;
566 		ent->owner = other;
567 		ent->flags |= FL_RESPAWN;
568 		ent->svflags |= SVF_NOCLIENT;
569 		ent->solid = SOLID_NOT;
570 	} else {
571 		if (!(ent->spawnflags & DROPPED_ITEM) && (deathmatch->value))
572 			SetRespawn(ent, 30);
573 	}
574 
575 	return true;
576 }
577 
578 /* ====================================================================== */
579 
580 int
ArmorIndex(edict_t * ent)581 ArmorIndex(edict_t * ent)
582 {
583 	if (!ent->client)
584 		return 0;
585 
586 	if (ent->client->pers.inventory[jacket_armor_index] > 0)
587 		return jacket_armor_index;
588 
589 	if (ent->client->pers.inventory[combat_armor_index] > 0)
590 		return combat_armor_index;
591 
592 	if (ent->client->pers.inventory[body_armor_index] > 0)
593 		return body_armor_index;
594 
595 	return 0;
596 }
597 
598 qboolean
Pickup_Armor(edict_t * ent,edict_t * other)599 Pickup_Armor(edict_t * ent, edict_t * other)
600 {
601 	int		old_armor_index;
602 	gitem_armor_t  *oldinfo;
603 	gitem_armor_t  *newinfo;
604 	int		newcount;
605 	float		salvage;
606 	int		salvagecount;
607 
608 	/* get info on new armor */
609 	newinfo = (gitem_armor_t *) ent->item->info;
610 
611 	old_armor_index = ArmorIndex(other);
612 
613 	/* handle armor shards specially */
614 	if (ent->item->tag == ARMOR_SHARD) {
615 		if (!old_armor_index)
616 			other->client->pers.inventory[jacket_armor_index] = 2;
617 		else
618 			other->client->pers.inventory[old_armor_index] += 2;
619 	}
620 	/* if player has no armor, just use it */
621 	else if (!old_armor_index) {
622 		other->client->pers.inventory[ITEM_INDEX(ent->item)] = newinfo->base_count;
623 	}
624 	/* use the better armor */
625 	else {
626 		/* get info on old armor */
627 		if (old_armor_index == jacket_armor_index)
628 			oldinfo = &jacketarmor_info;
629 		else if (old_armor_index == combat_armor_index)
630 			oldinfo = &combatarmor_info;
631 		else		/* (old_armor_index == body_armor_index) */
632 			oldinfo = &bodyarmor_info;
633 
634 		if (newinfo->normal_protection > oldinfo->normal_protection) {
635 			/* calc new armor values */
636 			salvage = oldinfo->normal_protection / newinfo->normal_protection;
637 			salvagecount = salvage * other->client->pers.inventory[old_armor_index];
638 			newcount = newinfo->base_count + salvagecount;
639 			if (newcount > newinfo->max_count)
640 				newcount = newinfo->max_count;
641 
642 			/* zero count of old armor so it goes away */
643 			other->client->pers.inventory[old_armor_index] = 0;
644 
645 			/* change armor to new item with computed value */
646 			other->client->pers.inventory[ITEM_INDEX(ent->item)] = newcount;
647 		} else {
648 			/* calc new armor values */
649 			salvage = newinfo->normal_protection / oldinfo->normal_protection;
650 			salvagecount = salvage * newinfo->base_count;
651 			newcount = other->client->pers.inventory[old_armor_index] + salvagecount;
652 			if (newcount > oldinfo->max_count)
653 				newcount = oldinfo->max_count;
654 
655 			/*
656 			 * if we're already maxed out then we don't need the
657 			 * new armor
658 			 */
659 			if (other->client->pers.inventory[old_armor_index] >= newcount)
660 				return false;
661 
662 			/* update current armor value */
663 			other->client->pers.inventory[old_armor_index] = newcount;
664 		}
665 	}
666 
667 	if (!(ent->spawnflags & DROPPED_ITEM) && (deathmatch->value))
668 		SetRespawn(ent, 20);
669 
670 	return true;
671 }
672 
673 /* ====================================================================== */
674 
675 int
PowerArmorType(edict_t * ent)676 PowerArmorType(edict_t * ent)
677 {
678 	if (!ent->client)
679 		return POWER_ARMOR_NONE;
680 
681 	if (!(ent->flags & FL_POWER_ARMOR))
682 		return POWER_ARMOR_NONE;
683 
684 	if (ent->client->pers.inventory[power_shield_index] > 0)
685 		return POWER_ARMOR_SHIELD;
686 
687 	if (ent->client->pers.inventory[power_screen_index] > 0)
688 		return POWER_ARMOR_SCREEN;
689 
690 	return POWER_ARMOR_NONE;
691 }
692 
693 void
Use_PowerArmor(edict_t * ent,gitem_t * item)694 Use_PowerArmor(edict_t * ent, gitem_t * item)
695 {
696 	int		index;
697 
698 	if (ent->flags & FL_POWER_ARMOR) {
699 		ent->flags &= ~FL_POWER_ARMOR;
700 		gi.sound(ent, CHAN_AUTO, gi.soundindex("misc/power2.wav"), 1, ATTN_NORM, 0);
701 	} else {
702 		index = ITEM_INDEX(FindItem("cells"));
703 		if (!ent->client->pers.inventory[index]) {
704 #ifdef WITH_ACEBOT
705 			safe_cprintf
706 #else
707 			gi.cprintf
708 #endif
709 			    (ent, PRINT_HIGH, "No cells for power armor.\n");
710 			return;
711 		}
712 		ent->flags |= FL_POWER_ARMOR;
713 		gi.sound(ent, CHAN_AUTO, gi.soundindex("misc/power1.wav"), 1, ATTN_NORM, 0);
714 	}
715 }
716 
717 qboolean
Pickup_PowerArmor(edict_t * ent,edict_t * other)718 Pickup_PowerArmor(edict_t * ent, edict_t * other)
719 {
720 	int		quantity;
721 
722 	quantity = other->client->pers.inventory[ITEM_INDEX(ent->item)];
723 
724 	other->client->pers.inventory[ITEM_INDEX(ent->item)]++;
725 
726 	if (deathmatch->value) {
727 		if (!(ent->spawnflags & DROPPED_ITEM))
728 			SetRespawn(ent, ent->item->quantity);
729 		/* auto-use for DM only if we didn't already have one */
730 		if (!quantity)
731 			ent->item->use(other, ent->item);
732 	}
733 	return true;
734 }
735 
736 void
Drop_PowerArmor(edict_t * ent,gitem_t * item)737 Drop_PowerArmor(edict_t * ent, gitem_t * item)
738 {
739 	if ((ent->flags & FL_POWER_ARMOR) && (ent->client->pers.inventory[ITEM_INDEX(item)] == 1))
740 		Use_PowerArmor(ent, item);
741 	Drop_General(ent, item);
742 }
743 
744 /* ====================================================================== */
745 
746 /*
747  * =============== Touch_Item ===============
748  */
749 void
Touch_Item(edict_t * ent,edict_t * other,cplane_t * plane,csurface_t * surf)750 Touch_Item(edict_t * ent, edict_t * other, cplane_t * plane, csurface_t * surf)
751 {
752 	qboolean	taken;
753 
754 	if (!other->client)
755 		return;
756 	if (other->health < 1)
757 		return;		/* dead people can't pickup */
758 	if (!ent->item->pickup)
759 		return;		/* not a grabbable item? */
760 
761 	taken = ent->item->pickup(ent, other);
762 
763 	if (taken) {
764 		/* flash the screen */
765 		other->client->bonus_alpha = 0.25;
766 
767 		/* show icon and name on status bar */
768 		other->client->ps.stats[STAT_PICKUP_ICON] = gi.imageindex(ent->item->icon);
769 		other->client->ps.stats[STAT_PICKUP_STRING] = CS_ITEMS + ITEM_INDEX(ent->item);
770 		other->client->pickup_msg_time = level.time + 3.0;
771 
772 		/* change selected item */
773 		if (ent->item->use)
774 			other->client->pers.selected_item = other->client->ps.stats[STAT_SELECTED_ITEM] = ITEM_INDEX(ent->item);
775 
776 		if (ent->item->pickup == Pickup_Health) {
777 			if (ent->count == 2)
778 				gi.sound(other, CHAN_ITEM, gi.soundindex("items/s_health.wav"), 1, ATTN_NORM, 0);
779 			else if (ent->count == 10)
780 				gi.sound(other, CHAN_ITEM, gi.soundindex("items/n_health.wav"), 1, ATTN_NORM, 0);
781 			else if (ent->count == 25)
782 				gi.sound(other, CHAN_ITEM, gi.soundindex("items/l_health.wav"), 1, ATTN_NORM, 0);
783 			else	/* (ent->count == 100) */
784 				gi.sound(other, CHAN_ITEM, gi.soundindex("items/m_health.wav"), 1, ATTN_NORM, 0);
785 		} else if (ent->item->pickup_sound) {
786 			gi.sound(other, CHAN_ITEM, gi.soundindex(ent->item->pickup_sound), 1, ATTN_NORM, 0);
787 		}
788 	}
789 	if (!(ent->spawnflags & ITEM_TARGETS_USED)) {
790 		G_UseTargets(ent, other);
791 		ent->spawnflags |= ITEM_TARGETS_USED;
792 	}
793 	if (!taken)
794 		return;
795 
796 	if (!((coop->value) && (ent->item->flags & IT_STAY_COOP)) || (ent->spawnflags & (DROPPED_ITEM | DROPPED_PLAYER_ITEM))) {
797 		if (ent->flags & FL_RESPAWN)
798 			ent->flags &= ~FL_RESPAWN;
799 		else
800 			G_FreeEdict(ent);
801 	}
802 }
803 
804 /* ====================================================================== */
805 
806 static void
drop_temp_touch(edict_t * ent,edict_t * other,cplane_t * plane,csurface_t * surf)807 drop_temp_touch(edict_t * ent, edict_t * other, cplane_t * plane, csurface_t * surf)
808 {
809 	if (other == ent->owner)
810 		return;
811 
812 	Touch_Item(ent, other, plane, surf);
813 }
814 
815 static void
drop_make_touchable(edict_t * ent)816 drop_make_touchable(edict_t * ent)
817 {
818 	ent->touch = Touch_Item;
819 	if (deathmatch->value) {
820 		ent->nextthink = level.time + 29;
821 		ent->think = G_FreeEdict;
822 	}
823 }
824 
825 edict_t        *
Drop_Item(edict_t * ent,gitem_t * item)826 Drop_Item(edict_t * ent, gitem_t * item)
827 {
828 	edict_t        *dropped;
829 	vec3_t		forward, right;
830 	vec3_t		offset;
831 
832 	dropped = G_Spawn();
833 
834 	dropped->classname = item->classname;
835 	dropped->item = item;
836 	dropped->spawnflags = DROPPED_ITEM;
837 	dropped->s.effects = item->world_model_flags;
838 	dropped->s.renderfx = RF_GLOW;
839 	VectorSet(dropped->mins, -15, -15, -15);
840 	VectorSet(dropped->maxs, 15, 15, 15);
841 	gi.setmodel(dropped, dropped->item->world_model);
842 	dropped->solid = SOLID_TRIGGER;
843 	dropped->movetype = MOVETYPE_TOSS;
844 	dropped->touch = drop_temp_touch;
845 	dropped->owner = ent;
846 
847 	if (ent->client) {
848 		trace_t		trace;
849 
850 		AngleVectors(ent->client->v_angle, forward, right, NULL);
851 		VectorSet(offset, 24, 0, -16);
852 		G_ProjectSource(ent->s.origin, offset, forward, right, dropped->s.origin);
853 		trace = gi.trace(ent->s.origin, dropped->mins, dropped->maxs,
854 		    dropped->s.origin, ent, CONTENTS_SOLID);
855 		VectorCopy(trace.endpos, dropped->s.origin);
856 	} else {
857 		AngleVectors(ent->s.angles, forward, right, NULL);
858 		VectorCopy(ent->s.origin, dropped->s.origin);
859 	}
860 
861 	VectorScale(forward, 100, dropped->velocity);
862 	dropped->velocity[2] = 300;
863 
864 	dropped->think = drop_make_touchable;
865 	dropped->nextthink = level.time + 1;
866 
867 	gi.linkentity(dropped);
868 
869 	return dropped;
870 }
871 
872 void
Use_Item(edict_t * ent,edict_t * other,edict_t * activator)873 Use_Item(edict_t * ent, edict_t * other, edict_t * activator)
874 {
875 	ent->svflags &= ~SVF_NOCLIENT;
876 	ent->use = NULL;
877 
878 	if (ent->spawnflags & ITEM_NO_TOUCH) {
879 		ent->solid = SOLID_BBOX;
880 		ent->touch = NULL;
881 	} else {
882 		ent->solid = SOLID_TRIGGER;
883 		ent->touch = Touch_Item;
884 	}
885 
886 	gi.linkentity(ent);
887 }
888 
889 /* ====================================================================== */
890 
891 /*
892  * ================ droptofloor ================
893  */
894 void
droptofloor(edict_t * ent)895 droptofloor(edict_t * ent)
896 {
897 	trace_t		tr;
898 	vec3_t		dest;
899 	float          *v;
900 
901 	v = tv(-15, -15, -15);
902 	VectorCopy(v, ent->mins);
903 	v = tv(15, 15, 15);
904 	VectorCopy(v, ent->maxs);
905 
906 	if (ent->model)
907 		gi.setmodel(ent, ent->model);
908 	else
909 		gi.setmodel(ent, ent->item->world_model);
910 	ent->solid = SOLID_TRIGGER;
911 	ent->movetype = MOVETYPE_TOSS;
912 	ent->touch = Touch_Item;
913 
914 	v = tv(0, 0, -128);
915 	VectorAdd(ent->s.origin, v, dest);
916 
917 	tr = gi.trace(ent->s.origin, ent->mins, ent->maxs, dest, ent, MASK_SOLID);
918 	if (tr.startsolid) {
919 		gi.dprintf("droptofloor: %s startsolid at %s\n", ent->classname, vtos(ent->s.origin));
920 		G_FreeEdict(ent);
921 		return;
922 	}
923 	VectorCopy(tr.endpos, ent->s.origin);
924 
925 	if (ent->team) {
926 		ent->flags &= ~FL_TEAMSLAVE;
927 		ent->chain = ent->teamchain;
928 		ent->teamchain = NULL;
929 
930 		ent->svflags |= SVF_NOCLIENT;
931 		ent->solid = SOLID_NOT;
932 		if (ent == ent->teammaster) {
933 			ent->nextthink = level.time + FRAMETIME;
934 			ent->think = DoRespawn;
935 		}
936 	}
937 	if (ent->spawnflags & ITEM_NO_TOUCH) {
938 		ent->solid = SOLID_BBOX;
939 		ent->touch = NULL;
940 		ent->s.effects &= ~EF_ROTATE;
941 		ent->s.renderfx &= ~RF_GLOW;
942 	}
943 	if (ent->spawnflags & ITEM_TRIGGER_SPAWN) {
944 		ent->svflags |= SVF_NOCLIENT;
945 		ent->solid = SOLID_NOT;
946 		ent->use = Use_Item;
947 	}
948 	gi.linkentity(ent);
949 }
950 
951 
952 /*
953  * =============== PrecacheItem
954  *
955  * Precaches all data needed for a given item. This will be called for each item
956  * spawned in a level, and for each item in each client's inventory.
957  * ===============
958  */
959 void
PrecacheItem(gitem_t * it)960 PrecacheItem(gitem_t * it)
961 {
962 	char           *s, *start;
963 	char		data      [MAX_QPATH];
964 	int		len;
965 	gitem_t        *ammo;
966 
967 	if (!it)
968 		return;
969 
970 	if (it->pickup_sound)
971 		gi.soundindex(it->pickup_sound);
972 	if (it->world_model)
973 		gi.modelindex(it->world_model);
974 	if (it->view_model)
975 		gi.modelindex(it->view_model);
976 	if (it->icon)
977 		gi.imageindex(it->icon);
978 
979 	/* parse everything for its ammo */
980 	if (it->ammo && it->ammo[0]) {
981 		ammo = FindItem(it->ammo);
982 		if (ammo != it)
983 			PrecacheItem(ammo);
984 	}
985 	/* parse the space seperated precache string for other items */
986 	s = it->precaches;
987 	if (!s || !s[0])
988 		return;
989 
990 	while (*s) {
991 		start = s;
992 		while (*s && *s != ' ')
993 			s++;
994 
995 		len = s - start;
996 		if (len >= MAX_QPATH || len < 5)
997 			gi.error("PrecacheItem: %s has bad precache string", it->classname);
998 		memcpy(data, start, len);
999 		data[len] = 0;
1000 		if (*s)
1001 			s++;
1002 
1003 		/* determine type based on extension */
1004 		if (!strcmp(data + len - 3, "md2"))
1005 			gi.modelindex(data);
1006 		else if (!strcmp(data + len - 3, "sp2"))
1007 			gi.modelindex(data);
1008 		else if (!strcmp(data + len - 3, "wav"))
1009 			gi.soundindex(data);
1010 		if (!strcmp(data + len - 3, "pcx"))
1011 			gi.imageindex(data);
1012 	}
1013 }
1014 
1015 /*
1016  * ============ SpawnItem
1017  *
1018  * Sets the clipping size and plants the object on the floor.
1019  *
1020  * Items can't be immediately dropped to floor, because they might be on an
1021  * entity that hasn't spawned yet. ============
1022  */
1023 void
SpawnItem(edict_t * ent,gitem_t * item)1024 SpawnItem(edict_t * ent, gitem_t * item)
1025 {
1026 	PrecacheItem(item);
1027 
1028 	if (ent->spawnflags) {
1029 		if (strcmp(ent->classname, "key_power_cube") != 0) {
1030 			ent->spawnflags = 0;
1031 			gi.dprintf("%s at %s has invalid spawnflags set\n", ent->classname, vtos(ent->s.origin));
1032 		}
1033 	}
1034 	/* some items will be prevented in deathmatch */
1035 	if (deathmatch->value) {
1036 		if ((int)dmflags->value & DF_NO_ARMOR) {
1037 			if (item->pickup == Pickup_Armor || item->pickup == Pickup_PowerArmor) {
1038 				G_FreeEdict(ent);
1039 				return;
1040 			}
1041 		}
1042 		if ((int)dmflags->value & DF_NO_ITEMS) {
1043 			if (item->pickup == Pickup_Powerup) {
1044 				G_FreeEdict(ent);
1045 				return;
1046 			}
1047 		}
1048 		if ((int)dmflags->value & DF_NO_HEALTH) {
1049 			if (item->pickup == Pickup_Health || item->pickup == Pickup_Adrenaline || item->pickup == Pickup_AncientHead) {
1050 				G_FreeEdict(ent);
1051 				return;
1052 			}
1053 		}
1054 		if ((int)dmflags->value & DF_INFINITE_AMMO) {
1055 			if ((item->flags == IT_AMMO) || (strcmp(ent->classname, "weapon_bfg") == 0)) {
1056 				G_FreeEdict(ent);
1057 				return;
1058 			}
1059 		}
1060 	}
1061 	if (coop->value && (strcmp(ent->classname, "key_power_cube") == 0)) {
1062 		ent->spawnflags |= (1 << (8 + level.power_cubes));
1063 		level.power_cubes++;
1064 	}
1065 	/* don't let them drop items that stay in a coop game */
1066 	if ((coop->value) && (item->flags & IT_STAY_COOP)) {
1067 		item->drop = NULL;
1068 	}
1069 	ent->item = item;
1070 	ent->nextthink = level.time + 2 * FRAMETIME;	/* items start after
1071 							 * other solids */
1072 	ent->think = droptofloor;
1073 	ent->s.effects = item->world_model_flags;
1074 	ent->s.renderfx = RF_GLOW;
1075 #ifdef GAME_MOD
1076 	/* Weapons Shell in game	 */
1077 	if (weap_shell->value) {
1078 		if (strcmp(ent->classname, "weapon_shotgun") == 0) {
1079 			ent->s.effects |= EF_COLOR_SHELL;
1080 			ent->s.renderfx |= RF_SHELL_GREEN;
1081 		}
1082 		if (strcmp(ent->classname, "weapon_supershotgun") == 0) {
1083 			ent->s.effects |= EF_COLOR_SHELL;
1084 			ent->s.renderfx |= RF_SHELL_RED;
1085 		}
1086 		if (strcmp(ent->classname, "weapon_machinegun") == 0) {
1087 			ent->s.effects |= EF_COLOR_SHELL;
1088 			ent->s.renderfx |= RF_SHELL_BLUE;
1089 		}
1090 		if (strcmp(ent->classname, "weapon_chaingun") == 0) {
1091 			ent->s.effects |= EF_COLOR_SHELL;
1092 			ent->s.renderfx |= RF_SHELL_GREEN;
1093 		}
1094 		if (strcmp(ent->classname, "weapon_hyperblaster") == 0) {
1095 			ent->s.effects |= EF_COLOR_SHELL;
1096 			ent->s.renderfx |= RF_SHELL_RED;
1097 		}
1098 		if (strcmp(ent->classname, "weapon_rocketlauncher") == 0) {
1099 			ent->s.effects |= EF_COLOR_SHELL;
1100 			ent->s.renderfx |= RF_SHELL_RED;
1101 		}
1102 		if (strcmp(ent->classname, "weapon_grenade") == 0) {
1103 			ent->s.effects |= EF_COLOR_SHELL;
1104 			ent->s.renderfx |= RF_SHELL_GREEN;
1105 		}
1106 		if (strcmp(ent->classname, "weapon_grenadelauncher") == 0) {
1107 			ent->s.effects |= EF_COLOR_SHELL;
1108 			ent->s.renderfx |= RF_SHELL_RED;
1109 		}
1110 		if (strcmp(ent->classname, "weapon_railgun") == 0) {
1111 			ent->s.effects |= EF_COLOR_SHELL;
1112 			ent->s.renderfx |= RF_SHELL_BLUE;
1113 		}
1114 		if (strcmp(ent->classname, "weapon_bfg") == 0) {
1115 			ent->s.effects |= EF_COLOR_SHELL;
1116 			ent->s.renderfx |= RF_SHELL_GREEN;
1117 		}
1118 	}
1119 #endif
1120 	if (ent->model)
1121 		gi.modelindex(ent->model);
1122 }
1123 
1124 /* ====================================================================== */
1125 
1126 gitem_t		itemlist[] =
1127 {
1128 	{
1129 		NULL
1130 	},			/* leave index 0 alone */
1131 
1132 	//
1133 	/* ARMOR */
1134 	//
1135 
1136 	/*
1137 	 * QUAKED item_armor_body (.3 .3 1) (-16 -16 -16) (16 16 16)
1138 	 */
1139 	{
1140 		"item_armor_body",
1141 		Pickup_Armor,
1142 		NULL,
1143 		NULL,
1144 		NULL,
1145 		"misc/ar1_pkup.wav",
1146 		"models/items/armor/body/tris.md2", EF_ROTATE,
1147 		NULL,
1148 		 /* icon */ "i_bodyarmor",
1149 		 /* pickup */ "Body Armor",
1150 		 /* width */ 3,
1151 		0,
1152 		NULL,
1153 		IT_ARMOR,
1154 		0,
1155 		&bodyarmor_info,
1156 		ARMOR_BODY,
1157 		 /* precache */ ""
1158 	},
1159 
1160 	/*
1161 	 * QUAKED item_armor_combat (.3 .3 1) (-16 -16 -16) (16 16 16)
1162 	 */
1163 	{
1164 		"item_armor_combat",
1165 		Pickup_Armor,
1166 		NULL,
1167 		NULL,
1168 		NULL,
1169 		"misc/ar1_pkup.wav",
1170 		"models/items/armor/combat/tris.md2", EF_ROTATE,
1171 		NULL,
1172 		 /* icon */ "i_combatarmor",
1173 		 /* pickup */ "Combat Armor",
1174 		 /* width */ 3,
1175 		0,
1176 		NULL,
1177 		IT_ARMOR,
1178 		0,
1179 		&combatarmor_info,
1180 		ARMOR_COMBAT,
1181 		 /* precache */ ""
1182 	},
1183 
1184 	/*
1185 	 * QUAKED item_armor_jacket (.3 .3 1) (-16 -16 -16) (16 16 16)
1186 	 */
1187 	{
1188 		"item_armor_jacket",
1189 		Pickup_Armor,
1190 		NULL,
1191 		NULL,
1192 		NULL,
1193 		"misc/ar1_pkup.wav",
1194 		"models/items/armor/jacket/tris.md2", EF_ROTATE,
1195 		NULL,
1196 		 /* icon */ "i_jacketarmor",
1197 		 /* pickup */ "Jacket Armor",
1198 		 /* width */ 3,
1199 		0,
1200 		NULL,
1201 		IT_ARMOR,
1202 		0,
1203 		&jacketarmor_info,
1204 		ARMOR_JACKET,
1205 		 /* precache */ ""
1206 	},
1207 
1208 	/*
1209 	 * QUAKED item_armor_shard (.3 .3 1) (-16 -16 -16) (16 16 16)
1210 	 */
1211 	{
1212 		"item_armor_shard",
1213 		Pickup_Armor,
1214 		NULL,
1215 		NULL,
1216 		NULL,
1217 		"misc/ar2_pkup.wav",
1218 		"models/items/armor/shard/tris.md2", EF_ROTATE,
1219 		NULL,
1220 		 /* icon */ "i_jacketarmor",
1221 		 /* pickup */ "Armor Shard",
1222 		 /* width */ 3,
1223 		0,
1224 		NULL,
1225 		IT_ARMOR,
1226 		0,
1227 		NULL,
1228 		ARMOR_SHARD,
1229 		 /* precache */ ""
1230 	},
1231 
1232 
1233 	/*
1234 	 * QUAKED item_power_screen (.3 .3 1) (-16 -16 -16) (16 16 16)
1235 	 */
1236 	{
1237 		"item_power_screen",
1238 		Pickup_PowerArmor,
1239 		Use_PowerArmor,
1240 		Drop_PowerArmor,
1241 		NULL,
1242 		"misc/ar3_pkup.wav",
1243 		"models/items/armor/screen/tris.md2", EF_ROTATE,
1244 		NULL,
1245 		 /* icon */ "i_powerscreen",
1246 		 /* pickup */ "Power Screen",
1247 		 /* width */ 0,
1248 		60,
1249 		NULL,
1250 		IT_ARMOR,
1251 		0,
1252 		NULL,
1253 		0,
1254 		 /* precache */ ""
1255 	},
1256 
1257 	/*
1258 	 * QUAKED item_power_shield (.3 .3 1) (-16 -16 -16) (16 16 16)
1259 	 */
1260 	{
1261 		"item_power_shield",
1262 		Pickup_PowerArmor,
1263 		Use_PowerArmor,
1264 		Drop_PowerArmor,
1265 		NULL,
1266 		"misc/ar3_pkup.wav",
1267 		"models/items/armor/shield/tris.md2", EF_ROTATE,
1268 		NULL,
1269 		 /* icon */ "i_powershield",
1270 		 /* pickup */ "Power Shield",
1271 		 /* width */ 0,
1272 		60,
1273 		NULL,
1274 		IT_ARMOR,
1275 		0,
1276 		NULL,
1277 		0,
1278 		 /* precache */ "misc/power2.wav misc/power1.wav"
1279 	},
1280 
1281 
1282 	//
1283 	/* WEAPONS  */
1284 	//
1285 
1286 	/*
1287 	 * weapon_blaster (.3 .3 1) (-16 -16 -16) (16 16 16) always owned,
1288 	 * never in the world
1289 	 */
1290 	{
1291 		"weapon_blaster",
1292 		NULL,
1293 		Use_Weapon,
1294 		NULL,
1295 		Weapon_Blaster,
1296 		"misc/w_pkup.wav",
1297 		NULL, 0,
1298 		"models/weapons/v_blast/tris.md2",
1299 		 /* icon */ "w_blaster",
1300 		 /* pickup */ "Blaster",
1301 		0,
1302 		0,
1303 		NULL,
1304 		IT_WEAPON | IT_STAY_COOP,
1305 		WEAP_BLASTER,
1306 		NULL,
1307 		0,
1308 		 /* precache */ "weapons/blastf1a.wav misc/lasfly.wav"
1309 	},
1310 
1311 	/*
1312 	 * QUAKED weapon_shotgun (.3 .3 1) (-16 -16 -16) (16 16 16)
1313 	 */
1314 	{
1315 		"weapon_shotgun",
1316 		Pickup_Weapon,
1317 		Use_Weapon,
1318 		Drop_Weapon,
1319 		Weapon_Shotgun,
1320 		"misc/w_pkup.wav",
1321 		"models/weapons/g_shotg/tris.md2", EF_ROTATE,
1322 		"models/weapons/v_shotg/tris.md2",
1323 		 /* icon */ "w_shotgun",
1324 		 /* pickup */ "Shotgun",
1325 		0,
1326 		1,
1327 		"Shells",
1328 		IT_WEAPON | IT_STAY_COOP,
1329 		WEAP_SHOTGUN,
1330 		NULL,
1331 		0,
1332 		 /* precache */ "weapons/shotgf1b.wav weapons/shotgr1b.wav"
1333 	},
1334 
1335 	/*
1336 	 * QUAKED weapon_supershotgun (.3 .3 1) (-16 -16 -16) (16 16 16)
1337 	 */
1338 	{
1339 		"weapon_supershotgun",
1340 		Pickup_Weapon,
1341 		Use_Weapon,
1342 		Drop_Weapon,
1343 		Weapon_SuperShotgun,
1344 		"misc/w_pkup.wav",
1345 		"models/weapons/g_shotg2/tris.md2", EF_ROTATE,
1346 		"models/weapons/v_shotg2/tris.md2",
1347 		 /* icon */ "w_sshotgun",
1348 		 /* pickup */ "Super Shotgun",
1349 		0,
1350 		2,
1351 		"Shells",
1352 		IT_WEAPON | IT_STAY_COOP,
1353 		WEAP_SUPERSHOTGUN,
1354 		NULL,
1355 		0,
1356 		 /* precache */ "weapons/sshotf1b.wav"
1357 	},
1358 
1359 	/*
1360 	 * QUAKED weapon_machinegun (.3 .3 1) (-16 -16 -16) (16 16 16)
1361 	 */
1362 	{
1363 		"weapon_machinegun",
1364 		Pickup_Weapon,
1365 		Use_Weapon,
1366 		Drop_Weapon,
1367 		Weapon_Machinegun,
1368 		"misc/w_pkup.wav",
1369 		"models/weapons/g_machn/tris.md2", EF_ROTATE,
1370 		"models/weapons/v_machn/tris.md2",
1371 		 /* icon */ "w_machinegun",
1372 		 /* pickup */ "Machinegun",
1373 		0,
1374 		1,
1375 		"Bullets",
1376 		IT_WEAPON | IT_STAY_COOP,
1377 		WEAP_MACHINEGUN,
1378 		NULL,
1379 		0,
1380 		 /* precache */ "weapons/machgf1b.wav weapons/machgf2b.wav weapons/machgf3b.wav weapons/machgf4b.wav weapons/machgf5b.wav"
1381 	},
1382 
1383 	/*
1384 	 * QUAKED weapon_chaingun (.3 .3 1) (-16 -16 -16) (16 16 16)
1385 	 */
1386 	{
1387 		"weapon_chaingun",
1388 		Pickup_Weapon,
1389 		Use_Weapon,
1390 		Drop_Weapon,
1391 		Weapon_Chaingun,
1392 		"misc/w_pkup.wav",
1393 		"models/weapons/g_chain/tris.md2", EF_ROTATE,
1394 		"models/weapons/v_chain/tris.md2",
1395 		 /* icon */ "w_chaingun",
1396 		 /* pickup */ "Chaingun",
1397 		0,
1398 		1,
1399 		"Bullets",
1400 		IT_WEAPON | IT_STAY_COOP,
1401 		WEAP_CHAINGUN,
1402 		NULL,
1403 		0,
1404 		 /* precache */ "weapons/chngnu1a.wav weapons/chngnl1a.wav weapons/machgf3b.wav` weapons/chngnd1a.wav"
1405 	},
1406 
1407 	/*
1408 	 * QUAKED ammo_grenades (.3 .3 1) (-16 -16 -16) (16 16 16)
1409 	 */
1410 	{
1411 		"ammo_grenades",
1412 		Pickup_Ammo,
1413 		Use_Weapon,
1414 		Drop_Ammo,
1415 		Weapon_Grenade,
1416 		"misc/am_pkup.wav",
1417 		"models/items/ammo/grenades/medium/tris.md2", 0,
1418 		"models/weapons/v_handgr/tris.md2",
1419 		 /* icon */ "a_grenades",
1420 		 /* pickup */ "Grenades",
1421 		 /* width */ 3,
1422 		5,
1423 		"grenades",
1424 		IT_AMMO | IT_WEAPON,
1425 		WEAP_GRENADES,
1426 		NULL,
1427 		AMMO_GRENADES,
1428 		 /* precache */ "weapons/hgrent1a.wav weapons/hgrena1b.wav weapons/hgrenc1b.wav weapons/hgrenb1a.wav weapons/hgrenb2a.wav "
1429 	},
1430 
1431 	/*
1432 	 * QUAKED weapon_grenadelauncher (.3 .3 1) (-16 -16 -16) (16 16 16)
1433 	 */
1434 	{
1435 		"weapon_grenadelauncher",
1436 		Pickup_Weapon,
1437 		Use_Weapon,
1438 		Drop_Weapon,
1439 		Weapon_GrenadeLauncher,
1440 		"misc/w_pkup.wav",
1441 		"models/weapons/g_launch/tris.md2", EF_ROTATE,
1442 		"models/weapons/v_launch/tris.md2",
1443 		 /* icon */ "w_glauncher",
1444 		 /* pickup */ "Grenade Launcher",
1445 		0,
1446 		1,
1447 		"Grenades",
1448 		IT_WEAPON | IT_STAY_COOP,
1449 		WEAP_GRENADELAUNCHER,
1450 		NULL,
1451 		0,
1452 		 /* precache */ "models/objects/grenade/tris.md2 weapons/grenlf1a.wav weapons/grenlr1b.wav weapons/grenlb1b.wav"
1453 	},
1454 
1455 	/*
1456 	 * QUAKED weapon_rocketlauncher (.3 .3 1) (-16 -16 -16) (16 16 16)
1457 	 */
1458 	{
1459 		"weapon_rocketlauncher",
1460 		Pickup_Weapon,
1461 		Use_Weapon,
1462 		Drop_Weapon,
1463 		Weapon_RocketLauncher,
1464 		"misc/w_pkup.wav",
1465 		"models/weapons/g_rocket/tris.md2", EF_ROTATE,
1466 		"models/weapons/v_rocket/tris.md2",
1467 		 /* icon */ "w_rlauncher",
1468 		 /* pickup */ "Rocket Launcher",
1469 		0,
1470 		1,
1471 		"Rockets",
1472 		IT_WEAPON | IT_STAY_COOP,
1473 		WEAP_ROCKETLAUNCHER,
1474 		NULL,
1475 		0,
1476 		 /* precache */ "models/objects/rocket/tris.md2 weapons/rockfly.wav weapons/rocklf1a.wav weapons/rocklr1b.wav models/objects/debris2/tris.md2"
1477 	},
1478 
1479 	/*
1480 	 * QUAKED weapon_hyperblaster (.3 .3 1) (-16 -16 -16) (16 16 16)
1481 	 */
1482 	{
1483 		"weapon_hyperblaster",
1484 		Pickup_Weapon,
1485 		Use_Weapon,
1486 		Drop_Weapon,
1487 		Weapon_HyperBlaster,
1488 		"misc/w_pkup.wav",
1489 		"models/weapons/g_hyperb/tris.md2", EF_ROTATE,
1490 		"models/weapons/v_hyperb/tris.md2",
1491 		 /* icon */ "w_hyperblaster",
1492 		 /* pickup */ "HyperBlaster",
1493 		0,
1494 		1,
1495 		"Cells",
1496 		IT_WEAPON | IT_STAY_COOP,
1497 		WEAP_HYPERBLASTER,
1498 		NULL,
1499 		0,
1500 		 /* precache */ "weapons/hyprbu1a.wav weapons/hyprbl1a.wav weapons/hyprbf1a.wav weapons/hyprbd1a.wav misc/lasfly.wav"
1501 	},
1502 
1503 	/*
1504 	 * QUAKED weapon_railgun (.3 .3 1) (-16 -16 -16) (16 16 16)
1505 	 */
1506 	{
1507 		"weapon_railgun",
1508 		Pickup_Weapon,
1509 		Use_Weapon,
1510 		Drop_Weapon,
1511 		Weapon_Railgun,
1512 		"misc/w_pkup.wav",
1513 		"models/weapons/g_rail/tris.md2", EF_ROTATE,
1514 		"models/weapons/v_rail/tris.md2",
1515 		 /* icon */ "w_railgun",
1516 		 /* pickup */ "Railgun",
1517 		0,
1518 		1,
1519 		"Slugs",
1520 		IT_WEAPON | IT_STAY_COOP,
1521 		WEAP_RAILGUN,
1522 		NULL,
1523 		0,
1524 		 /* precache */ "weapons/rg_hum.wav"
1525 	},
1526 
1527 	/*
1528 	 * QUAKED weapon_bfg (.3 .3 1) (-16 -16 -16) (16 16 16)
1529 	 */
1530 	{
1531 		"weapon_bfg",
1532 		Pickup_Weapon,
1533 		Use_Weapon,
1534 		Drop_Weapon,
1535 		Weapon_BFG,
1536 		"misc/w_pkup.wav",
1537 		"models/weapons/g_bfg/tris.md2", EF_ROTATE,
1538 		"models/weapons/v_bfg/tris.md2",
1539 		 /* icon */ "w_bfg",
1540 		 /* pickup */ "BFG10K",
1541 		0,
1542 		50,
1543 		"Cells",
1544 		IT_WEAPON | IT_STAY_COOP,
1545 		WEAP_BFG,
1546 		NULL,
1547 		0,
1548 		 /* precache */ "sprites/s_bfg1.sp2 sprites/s_bfg2.sp2 sprites/s_bfg3.sp2 weapons/bfg__f1y.wav weapons/bfg__l1a.wav weapons/bfg__x1b.wav weapons/bfg_hum.wav"
1549 	},
1550 
1551 	//
1552 	/* AMMO ITEMS */
1553 	//
1554 
1555 	/*
1556 	 * QUAKED ammo_shells (.3 .3 1) (-16 -16 -16) (16 16 16)
1557 	 */
1558 	{
1559 		"ammo_shells",
1560 		Pickup_Ammo,
1561 		NULL,
1562 		Drop_Ammo,
1563 		NULL,
1564 		"misc/am_pkup.wav",
1565 		"models/items/ammo/shells/medium/tris.md2", 0,
1566 		NULL,
1567 		 /* icon */ "a_shells",
1568 		 /* pickup */ "Shells",
1569 		 /* width */ 3,
1570 		10,
1571 		NULL,
1572 		IT_AMMO,
1573 		0,
1574 		NULL,
1575 		AMMO_SHELLS,
1576 		 /* precache */ ""
1577 	},
1578 
1579 	/*
1580 	 * QUAKED ammo_bullets (.3 .3 1) (-16 -16 -16) (16 16 16)
1581 	 */
1582 	{
1583 		"ammo_bullets",
1584 		Pickup_Ammo,
1585 		NULL,
1586 		Drop_Ammo,
1587 		NULL,
1588 		"misc/am_pkup.wav",
1589 		"models/items/ammo/bullets/medium/tris.md2", 0,
1590 		NULL,
1591 		 /* icon */ "a_bullets",
1592 		 /* pickup */ "Bullets",
1593 		 /* width */ 3,
1594 		50,
1595 		NULL,
1596 		IT_AMMO,
1597 		0,
1598 		NULL,
1599 		AMMO_BULLETS,
1600 		 /* precache */ ""
1601 	},
1602 
1603 	/*
1604 	 * QUAKED ammo_cells (.3 .3 1) (-16 -16 -16) (16 16 16)
1605 	 */
1606 	{
1607 		"ammo_cells",
1608 		Pickup_Ammo,
1609 		NULL,
1610 		Drop_Ammo,
1611 		NULL,
1612 		"misc/am_pkup.wav",
1613 		"models/items/ammo/cells/medium/tris.md2", 0,
1614 		NULL,
1615 		 /* icon */ "a_cells",
1616 		 /* pickup */ "Cells",
1617 		 /* width */ 3,
1618 		50,
1619 		NULL,
1620 		IT_AMMO,
1621 		0,
1622 		NULL,
1623 		AMMO_CELLS,
1624 		 /* precache */ ""
1625 	},
1626 
1627 	/*
1628 	 * QUAKED ammo_rockets (.3 .3 1) (-16 -16 -16) (16 16 16)
1629 	 */
1630 	{
1631 		"ammo_rockets",
1632 		Pickup_Ammo,
1633 		NULL,
1634 		Drop_Ammo,
1635 		NULL,
1636 		"misc/am_pkup.wav",
1637 		"models/items/ammo/rockets/medium/tris.md2", 0,
1638 		NULL,
1639 		 /* icon */ "a_rockets",
1640 		 /* pickup */ "Rockets",
1641 		 /* width */ 3,
1642 		5,
1643 		NULL,
1644 		IT_AMMO,
1645 		0,
1646 		NULL,
1647 		AMMO_ROCKETS,
1648 		 /* precache */ ""
1649 	},
1650 
1651 	/*
1652 	 * QUAKED ammo_slugs (.3 .3 1) (-16 -16 -16) (16 16 16)
1653 	 */
1654 	{
1655 		"ammo_slugs",
1656 		Pickup_Ammo,
1657 		NULL,
1658 		Drop_Ammo,
1659 		NULL,
1660 		"misc/am_pkup.wav",
1661 		"models/items/ammo/slugs/medium/tris.md2", 0,
1662 		NULL,
1663 		 /* icon */ "a_slugs",
1664 		 /* pickup */ "Slugs",
1665 		 /* width */ 3,
1666 		10,
1667 		NULL,
1668 		IT_AMMO,
1669 		0,
1670 		NULL,
1671 		AMMO_SLUGS,
1672 		 /* precache */ ""
1673 	},
1674 
1675 
1676 	//
1677 	/* POWERUP ITEMS */
1678 	//
1679 
1680 	/*
1681 	 * QUAKED item_quad (.3 .3 1) (-16 -16 -16) (16 16 16)
1682 	 */
1683 	{
1684 		"item_quad",
1685 		Pickup_Powerup,
1686 		Use_Quad,
1687 		Drop_General,
1688 		NULL,
1689 		"items/pkup.wav",
1690 		"models/items/quaddama/tris.md2", EF_ROTATE,
1691 		NULL,
1692 		 /* icon */ "p_quad",
1693 		 /* pickup */ "Quad Damage",
1694 		 /* width */ 2,
1695 		60,
1696 		NULL,
1697 		IT_POWERUP,
1698 		0,
1699 		NULL,
1700 		0,
1701 		 /* precache */ "items/damage.wav items/damage2.wav items/damage3.wav"
1702 	},
1703 
1704 	/*
1705 	 * QUAKED item_invulnerability (.3 .3 1) (-16 -16 -16) (16 16 16)
1706 	 */
1707 	{
1708 		"item_invulnerability",
1709 		Pickup_Powerup,
1710 		Use_Invulnerability,
1711 		Drop_General,
1712 		NULL,
1713 		"items/pkup.wav",
1714 		"models/items/invulner/tris.md2", EF_ROTATE,
1715 		NULL,
1716 		 /* icon */ "p_invulnerability",
1717 		 /* pickup */ "Invulnerability",
1718 		 /* width */ 2,
1719 		300,
1720 		NULL,
1721 		IT_POWERUP,
1722 		0,
1723 		NULL,
1724 		0,
1725 		 /* precache */ "items/protect.wav items/protect2.wav items/protect4.wav"
1726 	},
1727 
1728 	/*
1729 	 * QUAKED item_silencer (.3 .3 1) (-16 -16 -16) (16 16 16)
1730 	 */
1731 	{
1732 		"item_silencer",
1733 		Pickup_Powerup,
1734 		Use_Silencer,
1735 		Drop_General,
1736 		NULL,
1737 		"items/pkup.wav",
1738 		"models/items/silencer/tris.md2", EF_ROTATE,
1739 		NULL,
1740 		 /* icon */ "p_silencer",
1741 		 /* pickup */ "Silencer",
1742 		 /* width */ 2,
1743 		60,
1744 		NULL,
1745 		IT_POWERUP,
1746 		0,
1747 		NULL,
1748 		0,
1749 		 /* precache */ ""
1750 	},
1751 
1752 	/*
1753 	 * QUAKED item_breather (.3 .3 1) (-16 -16 -16) (16 16 16)
1754 	 */
1755 	{
1756 		"item_breather",
1757 		Pickup_Powerup,
1758 		Use_Breather,
1759 		Drop_General,
1760 		NULL,
1761 		"items/pkup.wav",
1762 		"models/items/breather/tris.md2", EF_ROTATE,
1763 		NULL,
1764 		 /* icon */ "p_rebreather",
1765 		 /* pickup */ "Rebreather",
1766 		 /* width */ 2,
1767 		60,
1768 		NULL,
1769 		IT_STAY_COOP | IT_POWERUP,
1770 		0,
1771 		NULL,
1772 		0,
1773 		 /* precache */ "items/airout.wav"
1774 	},
1775 
1776 	/*
1777 	 * QUAKED item_enviro (.3 .3 1) (-16 -16 -16) (16 16 16)
1778 	 */
1779 	{
1780 		"item_enviro",
1781 		Pickup_Powerup,
1782 		Use_Envirosuit,
1783 		Drop_General,
1784 		NULL,
1785 		"items/pkup.wav",
1786 		"models/items/enviro/tris.md2", EF_ROTATE,
1787 		NULL,
1788 		 /* icon */ "p_envirosuit",
1789 		 /* pickup */ "Environment Suit",
1790 		 /* width */ 2,
1791 		60,
1792 		NULL,
1793 		IT_STAY_COOP | IT_POWERUP,
1794 		0,
1795 		NULL,
1796 		0,
1797 		 /* precache */ "items/airout.wav"
1798 	},
1799 
1800 	/*
1801 	 * QUAKED item_ancient_head (.3 .3 1) (-16 -16 -16) (16 16 16)
1802 	 * Special item that gives +2 to maximum health
1803 	 */
1804 	{
1805 		"item_ancient_head",
1806 		Pickup_AncientHead,
1807 		NULL,
1808 		NULL,
1809 		NULL,
1810 		"items/pkup.wav",
1811 		"models/items/c_head/tris.md2", EF_ROTATE,
1812 		NULL,
1813 		 /* icon */ "i_fixme",
1814 		 /* pickup */ "Ancient Head",
1815 		 /* width */ 2,
1816 		60,
1817 		NULL,
1818 		0,
1819 		0,
1820 		NULL,
1821 		0,
1822 		 /* precache */ ""
1823 	},
1824 
1825 	/*
1826 	 * QUAKED item_adrenaline (.3 .3 1) (-16 -16 -16) (16 16 16) gives +1
1827 	 * to maximum health
1828 	 */
1829 	{
1830 		"item_adrenaline",
1831 		Pickup_Adrenaline,
1832 		NULL,
1833 		NULL,
1834 		NULL,
1835 		"items/pkup.wav",
1836 		"models/items/adrenal/tris.md2", EF_ROTATE,
1837 		NULL,
1838 		 /* icon */ "p_adrenaline",
1839 		 /* pickup */ "Adrenaline",
1840 		 /* width */ 2,
1841 		60,
1842 		NULL,
1843 		0,
1844 		0,
1845 		NULL,
1846 		0,
1847 		 /* precache */ ""
1848 	},
1849 
1850 	/*
1851 	 * QUAKED item_bandolier (.3 .3 1) (-16 -16 -16) (16 16 16)
1852 	 */
1853 	{
1854 		"item_bandolier",
1855 		Pickup_Bandolier,
1856 		NULL,
1857 		NULL,
1858 		NULL,
1859 		"items/pkup.wav",
1860 		"models/items/band/tris.md2", EF_ROTATE,
1861 		NULL,
1862 		 /* icon */ "p_bandolier",
1863 		 /* pickup */ "Bandolier",
1864 		 /* width */ 2,
1865 		60,
1866 		NULL,
1867 		0,
1868 		0,
1869 		NULL,
1870 		0,
1871 		 /* precache */ ""
1872 	},
1873 
1874 	/*
1875 	 * QUAKED item_pack (.3 .3 1) (-16 -16 -16) (16 16 16)
1876 	 */
1877 	{
1878 		"item_pack",
1879 		Pickup_Pack,
1880 		NULL,
1881 		NULL,
1882 		NULL,
1883 		"items/pkup.wav",
1884 		"models/items/pack/tris.md2", EF_ROTATE,
1885 		NULL,
1886 		 /* icon */ "i_pack",
1887 		 /* pickup */ "Ammo Pack",
1888 		 /* width */ 2,
1889 		180,
1890 		NULL,
1891 		0,
1892 		0,
1893 		NULL,
1894 		0,
1895 		 /* precache */ ""
1896 	},
1897 
1898 	//
1899 	/* KEYS */
1900 	//
1901 
1902 	/*
1903 	 * QUAKED key_data_cd (0 .5 .8) (-16 -16 -16) (16 16 16) key for
1904 	 * computer centers
1905 	 */
1906 	{
1907 		"key_data_cd",
1908 		Pickup_Key,
1909 		NULL,
1910 		Drop_General,
1911 		NULL,
1912 		"items/pkup.wav",
1913 		"models/items/keys/data_cd/tris.md2", EF_ROTATE,
1914 		NULL,
1915 		"k_datacd",
1916 		"Data CD",
1917 		2,
1918 		0,
1919 		NULL,
1920 		IT_STAY_COOP | IT_KEY,
1921 		0,
1922 		NULL,
1923 		0,
1924 		 /* precache */ ""
1925 	},
1926 
1927 	/*
1928 	 * QUAKED key_power_cube (0 .5 .8) (-16 -16 -16) (16 16 16)
1929 	 * TRIGGER_SPAWN NO_TOUCH warehouse circuits
1930 	 */
1931 	{
1932 		"key_power_cube",
1933 		Pickup_Key,
1934 		NULL,
1935 		Drop_General,
1936 		NULL,
1937 		"items/pkup.wav",
1938 		"models/items/keys/power/tris.md2", EF_ROTATE,
1939 		NULL,
1940 		"k_powercube",
1941 		"Power Cube",
1942 		2,
1943 		0,
1944 		NULL,
1945 		IT_STAY_COOP | IT_KEY,
1946 		0,
1947 		NULL,
1948 		0,
1949 		 /* precache */ ""
1950 	},
1951 
1952 	/*
1953 	 * QUAKED key_pyramid (0 .5 .8) (-16 -16 -16) (16 16 16) key for the
1954 	 * entrance of jail3
1955 	 */
1956 	{
1957 		"key_pyramid",
1958 		Pickup_Key,
1959 		NULL,
1960 		Drop_General,
1961 		NULL,
1962 		"items/pkup.wav",
1963 		"models/items/keys/pyramid/tris.md2", EF_ROTATE,
1964 		NULL,
1965 		"k_pyramid",
1966 		"Pyramid Key",
1967 		2,
1968 		0,
1969 		NULL,
1970 		IT_STAY_COOP | IT_KEY,
1971 		0,
1972 		NULL,
1973 		0,
1974 		 /* precache */ ""
1975 	},
1976 
1977 	/*
1978 	 * QUAKED key_data_spinner (0 .5 .8) (-16 -16 -16) (16 16 16) key for
1979 	 * the city computer
1980 	 */
1981 	{
1982 		"key_data_spinner",
1983 		Pickup_Key,
1984 		NULL,
1985 		Drop_General,
1986 		NULL,
1987 		"items/pkup.wav",
1988 		"models/items/keys/spinner/tris.md2", EF_ROTATE,
1989 		NULL,
1990 		"k_dataspin",
1991 		"Data Spinner",
1992 		2,
1993 		0,
1994 		NULL,
1995 		IT_STAY_COOP | IT_KEY,
1996 		0,
1997 		NULL,
1998 		0,
1999 		 /* precache */ ""
2000 	},
2001 
2002 	/*
2003 	 * QUAKED key_pass (0 .5 .8) (-16 -16 -16) (16 16 16) security pass
2004 	 * for the security level
2005 	 */
2006 	{
2007 		"key_pass",
2008 		Pickup_Key,
2009 		NULL,
2010 		Drop_General,
2011 		NULL,
2012 		"items/pkup.wav",
2013 		"models/items/keys/pass/tris.md2", EF_ROTATE,
2014 		NULL,
2015 		"k_security",
2016 		"Security Pass",
2017 		2,
2018 		0,
2019 		NULL,
2020 		IT_STAY_COOP | IT_KEY,
2021 		0,
2022 		NULL,
2023 		0,
2024 		 /* precache */ ""
2025 	},
2026 
2027 	/*
2028 	 * QUAKED key_blue_key (0 .5 .8) (-16 -16 -16) (16 16 16) normal door
2029 	 * key - blue
2030 	 */
2031 	{
2032 		"key_blue_key",
2033 		Pickup_Key,
2034 		NULL,
2035 		Drop_General,
2036 		NULL,
2037 		"items/pkup.wav",
2038 		"models/items/keys/key/tris.md2", EF_ROTATE,
2039 		NULL,
2040 		"k_bluekey",
2041 		"Blue Key",
2042 		2,
2043 		0,
2044 		NULL,
2045 		IT_STAY_COOP | IT_KEY,
2046 		0,
2047 		NULL,
2048 		0,
2049 		 /* precache */ ""
2050 	},
2051 
2052 	/*
2053 	 * QUAKED key_red_key (0 .5 .8) (-16 -16 -16) (16 16 16) normal door
2054 	 * key - red
2055 	 */
2056 	{
2057 		"key_red_key",
2058 		Pickup_Key,
2059 		NULL,
2060 		Drop_General,
2061 		NULL,
2062 		"items/pkup.wav",
2063 		"models/items/keys/red_key/tris.md2", EF_ROTATE,
2064 		NULL,
2065 		"k_redkey",
2066 		"Red Key",
2067 		2,
2068 		0,
2069 		NULL,
2070 		IT_STAY_COOP | IT_KEY,
2071 		0,
2072 		NULL,
2073 		0,
2074 		 /* precache */ ""
2075 	},
2076 
2077 	/*
2078 	 * QUAKED key_commander_head (0 .5 .8) (-16 -16 -16) (16 16 16) tank
2079 	 * commander's head
2080 	 */
2081 	{
2082 		"key_commander_head",
2083 		Pickup_Key,
2084 		NULL,
2085 		Drop_General,
2086 		NULL,
2087 		"items/pkup.wav",
2088 		"models/monsters/commandr/head/tris.md2", EF_GIB,
2089 		NULL,
2090 		 /* icon */ "k_comhead",
2091 		 /* pickup */ "Commander's Head",
2092 		 /* width */ 2,
2093 		0,
2094 		NULL,
2095 		IT_STAY_COOP | IT_KEY,
2096 		0,
2097 		NULL,
2098 		0,
2099 		 /* precache */ ""
2100 	},
2101 
2102 	/*
2103 	 * QUAKED key_airstrike_target (0 .5 .8) (-16 -16 -16) (16 16 16)
2104 	 * tank commander's head
2105 	 */
2106 	{
2107 		"key_airstrike_target",
2108 		Pickup_Key,
2109 		NULL,
2110 		Drop_General,
2111 		NULL,
2112 		"items/pkup.wav",
2113 		"models/items/keys/target/tris.md2", EF_ROTATE,
2114 		NULL,
2115 		 /* icon */ "i_airstrike",
2116 		 /* pickup */ "Airstrike Marker",
2117 		 /* width */ 2,
2118 		0,
2119 		NULL,
2120 		IT_STAY_COOP | IT_KEY,
2121 		0,
2122 		NULL,
2123 		0,
2124 		 /* precache */ ""
2125 	},
2126 
2127 	{
2128 		NULL,
2129 		Pickup_Health,
2130 		NULL,
2131 		NULL,
2132 		NULL,
2133 		"items/pkup.wav",
2134 		NULL, 0,
2135 		NULL,
2136 		 /* icon */ "i_health",
2137 		 /* pickup */ "Health",
2138 		 /* width */ 3,
2139 		0,
2140 		NULL,
2141 		0,
2142 		0,
2143 		NULL,
2144 		0,
2145 		 /* precache */ "items/s_health.wav items/n_health.wav items/l_health.wav items/m_health.wav"
2146 	},
2147 
2148 	/* end of list marker */
2149 	{NULL}
2150 };
2151 
2152 
2153 /*
2154  * QUAKED item_health (.3 .3 1) (-16 -16 -16) (16 16 16)
2155  */
2156 void
SP_item_health(edict_t * self)2157 SP_item_health(edict_t * self)
2158 {
2159 	if (deathmatch->value && ((int)dmflags->value & DF_NO_HEALTH)) {
2160 		G_FreeEdict(self);
2161 		return;
2162 	}
2163 	self->model = "models/items/healing/medium/tris.md2";
2164 	self->count = 10;
2165 	SpawnItem(self, FindItem("Health"));
2166 	gi.soundindex("items/n_health.wav");
2167 }
2168 
2169 /*
2170  * QUAKED item_health_small (.3 .3 1) (-16 -16 -16) (16 16 16)
2171  */
2172 void
SP_item_health_small(edict_t * self)2173 SP_item_health_small(edict_t * self)
2174 {
2175 	if (deathmatch->value && ((int)dmflags->value & DF_NO_HEALTH)) {
2176 		G_FreeEdict(self);
2177 		return;
2178 	}
2179 	self->model = "models/items/healing/stimpack/tris.md2";
2180 	self->count = 2;
2181 	SpawnItem(self, FindItem("Health"));
2182 	self->style = HEALTH_IGNORE_MAX;
2183 	gi.soundindex("items/s_health.wav");
2184 }
2185 
2186 /*
2187  * QUAKED item_health_large (.3 .3 1) (-16 -16 -16) (16 16 16)
2188  */
2189 void
SP_item_health_large(edict_t * self)2190 SP_item_health_large(edict_t * self)
2191 {
2192 	if (deathmatch->value && ((int)dmflags->value & DF_NO_HEALTH)) {
2193 		G_FreeEdict(self);
2194 		return;
2195 	}
2196 	self->model = "models/items/healing/large/tris.md2";
2197 	self->count = 25;
2198 	SpawnItem(self, FindItem("Health"));
2199 	gi.soundindex("items/l_health.wav");
2200 }
2201 
2202 /*
2203  * QUAKED item_health_mega (.3 .3 1) (-16 -16 -16) (16 16 16)
2204  */
2205 void
SP_item_health_mega(edict_t * self)2206 SP_item_health_mega(edict_t * self)
2207 {
2208 	if (deathmatch->value && ((int)dmflags->value & DF_NO_HEALTH)) {
2209 		G_FreeEdict(self);
2210 		return;
2211 	}
2212 	self->model = "models/items/mega_h/tris.md2";
2213 	self->count = 100;
2214 	SpawnItem(self, FindItem("Health"));
2215 	gi.soundindex("items/m_health.wav");
2216 	self->style = HEALTH_IGNORE_MAX | HEALTH_TIMED;
2217 }
2218 
2219 
2220 void
InitItems(void)2221 InitItems(void)
2222 {
2223 	game.num_items = sizeof(itemlist) / sizeof(itemlist[0]) - 1;
2224 }
2225 
2226 
2227 
2228 /*
2229  * =============== SetItemNames
2230  *
2231  * Called by worldspawn ===============
2232  */
2233 void
SetItemNames(void)2234 SetItemNames(void)
2235 {
2236 	int		i;
2237 	gitem_t        *it;
2238 
2239 	for (i = 0; i < game.num_items; i++) {
2240 		it = &itemlist[i];
2241 		gi.configstring(CS_ITEMS + i, it->pickup_name);
2242 	}
2243 
2244 	jacket_armor_index = ITEM_INDEX(FindItem("Jacket Armor"));
2245 	combat_armor_index = ITEM_INDEX(FindItem("Combat Armor"));
2246 	body_armor_index = ITEM_INDEX(FindItem("Body Armor"));
2247 	power_screen_index = ITEM_INDEX(FindItem("Power Screen"));
2248 	power_shield_index = ITEM_INDEX(FindItem("Power Shield"));
2249 }
2250