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