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