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