|
|
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];
1.1.1.2 ! root 505:
! 506: if (ent->client->pers.weapon &&
! 507: ent->client->pers.weapon->tag == AMMO_GRENADES &&
! 508: item->tag == AMMO_GRENADES &&
! 509: ent->client->pers.inventory[index] - dropped->count <= 0) {
! 510: gi.cprintf (ent, PRINT_HIGH, "Can't drop current weapon\n");
! 511: G_FreeEdict(dropped);
! 512: return;
! 513: }
! 514:
1.1 root 515: ent->client->pers.inventory[index] -= dropped->count;
516: ValidateSelectedItem (ent);
517: }
518:
519:
520: //======================================================================
521:
522: void MegaHealth_think (edict_t *self)
523: {
524: if (self->owner->health > self->owner->max_health)
525: {
526: self->nextthink = level.time + 1;
527: self->owner->health -= 1;
528: return;
529: }
530:
531: if (!(self->spawnflags & DROPPED_ITEM) && (deathmatch->value))
532: SetRespawn (self, 20);
533: else
534: G_FreeEdict (self);
535: }
536:
537: qboolean Pickup_Health (edict_t *ent, edict_t *other)
538: {
539: if (!(ent->style & HEALTH_IGNORE_MAX))
540: if (other->health >= other->max_health)
541: return false;
542:
543: other->health += ent->count;
544:
545: if (ent->count == 2)
546: ent->item->pickup_sound = "items/s_health.wav";
547: else if (ent->count == 10)
548: ent->item->pickup_sound = "items/n_health.wav";
549: else if (ent->count == 25)
550: ent->item->pickup_sound = "items/l_health.wav";
551: else // (ent->count == 100)
552: ent->item->pickup_sound = "items/m_health.wav";
553:
554: if (!(ent->style & HEALTH_IGNORE_MAX))
555: {
556: if (other->health > other->max_health)
557: other->health = other->max_health;
558: }
559:
560: if (ent->style & HEALTH_TIMED)
561: {
562: ent->think = MegaHealth_think;
563: ent->nextthink = level.time + 5;
564: ent->owner = other;
565: ent->flags |= FL_RESPAWN;
566: ent->svflags |= SVF_NOCLIENT;
567: ent->solid = SOLID_NOT;
568: }
569: else
570: {
571: if (!(ent->spawnflags & DROPPED_ITEM) && (deathmatch->value))
572: SetRespawn (ent, 30);
573: }
574:
575: return true;
576: }
577:
578: //======================================================================
579:
580: int ArmorIndex (edict_t *ent)
581: {
582: if (!ent->client)
583: return 0;
584:
585: if (ent->client->pers.inventory[jacket_armor_index] > 0)
586: return jacket_armor_index;
587:
588: if (ent->client->pers.inventory[combat_armor_index] > 0)
589: return combat_armor_index;
590:
591: if (ent->client->pers.inventory[body_armor_index] > 0)
592: return body_armor_index;
593:
594: return 0;
595: }
596:
597: qboolean Pickup_Armor (edict_t *ent, edict_t *other)
598: {
599: int old_armor_index;
600: gitem_armor_t *oldinfo;
601: gitem_armor_t *newinfo;
602: int newcount;
603: float salvage;
604: int salvagecount;
605:
606: // get info on new armor
607: newinfo = (gitem_armor_t *)ent->item->info;
608:
609: old_armor_index = ArmorIndex (other);
610:
611: // handle armor shards specially
612: if (ent->item->tag == ARMOR_SHARD)
613: {
614: if (!old_armor_index)
615: other->client->pers.inventory[jacket_armor_index] = 2;
616: else
617: other->client->pers.inventory[old_armor_index] += 2;
618: }
619:
620: // if player has no armor, just use it
621: else if (!old_armor_index)
622: {
623: other->client->pers.inventory[ITEM_INDEX(ent->item)] = newinfo->base_count;
624: }
625:
626: // use the better armor
627: else
628: {
629: // get info on old armor
630: if (old_armor_index == jacket_armor_index)
631: oldinfo = &jacketarmor_info;
632: else if (old_armor_index == combat_armor_index)
633: oldinfo = &combatarmor_info;
634: else // (old_armor_index == body_armor_index)
635: oldinfo = &bodyarmor_info;
636:
637: if (newinfo->normal_protection > oldinfo->normal_protection)
638: {
639: // calc new armor values
640: salvage = oldinfo->normal_protection / newinfo->normal_protection;
641: salvagecount = salvage * other->client->pers.inventory[old_armor_index];
642: newcount = newinfo->base_count + salvagecount;
643: if (newcount > newinfo->max_count)
644: newcount = newinfo->max_count;
645:
646: // zero count of old armor so it goes away
647: other->client->pers.inventory[old_armor_index] = 0;
648:
649: // change armor to new item with computed value
650: other->client->pers.inventory[ITEM_INDEX(ent->item)] = newcount;
651: }
652: else
653: {
654: // calc new armor values
655: salvage = newinfo->normal_protection / oldinfo->normal_protection;
656: salvagecount = salvage * newinfo->base_count;
657: newcount = other->client->pers.inventory[old_armor_index] + salvagecount;
658: if (newcount > oldinfo->max_count)
659: newcount = oldinfo->max_count;
660:
661: // if we're already maxed out then we don't need the new armor
662: if (other->client->pers.inventory[old_armor_index] >= newcount)
663: return false;
664:
665: // update current armor value
666: other->client->pers.inventory[old_armor_index] = newcount;
667: }
668: }
669:
670: if (!(ent->spawnflags & DROPPED_ITEM) && (deathmatch->value))
671: SetRespawn (ent, 20);
672:
673: return true;
674: }
675:
676: //======================================================================
677:
678: int PowerArmorType (edict_t *ent)
679: {
680: if (!ent->client)
681: return POWER_ARMOR_NONE;
682:
683: if (!(ent->flags & FL_POWER_ARMOR))
684: return POWER_ARMOR_NONE;
685:
686: if (ent->client->pers.inventory[power_shield_index] > 0)
687: return POWER_ARMOR_SHIELD;
688:
689: if (ent->client->pers.inventory[power_screen_index] > 0)
690: return POWER_ARMOR_SCREEN;
691:
692: return POWER_ARMOR_NONE;
693: }
694:
695: void Use_PowerArmor (edict_t *ent, gitem_t *item)
696: {
697: int index;
698:
699: if (ent->flags & FL_POWER_ARMOR)
700: {
701: ent->flags &= ~FL_POWER_ARMOR;
702: gi.sound(ent, CHAN_AUTO, gi.soundindex("misc/power2.wav"), 1, ATTN_NORM, 0);
703: }
704: else
705: {
706: index = ITEM_INDEX(FindItem("cells"));
707: if (!ent->client->pers.inventory[index])
708: {
709: gi.cprintf (ent, PRINT_HIGH, "No cells for power armor.\n");
710: return;
711: }
712: ent->flags |= FL_POWER_ARMOR;
713: gi.sound(ent, CHAN_AUTO, gi.soundindex("misc/power1.wav"), 1, ATTN_NORM, 0);
714: }
715: }
716:
717: qboolean Pickup_PowerArmor (edict_t *ent, edict_t *other)
718: {
719: int quantity;
720:
721: quantity = other->client->pers.inventory[ITEM_INDEX(ent->item)];
722:
723: other->client->pers.inventory[ITEM_INDEX(ent->item)]++;
724:
725: if (deathmatch->value)
726: {
727: if (!(ent->spawnflags & DROPPED_ITEM) )
728: SetRespawn (ent, ent->item->quantity);
729: // auto-use for DM only if we didn't already have one
730: if (!quantity)
731: ent->item->use (other, ent->item);
732: }
733:
734: return true;
735: }
736:
737: void Drop_PowerArmor (edict_t *ent, gitem_t *item)
738: {
739: if ((ent->flags & FL_POWER_ARMOR) && (ent->client->pers.inventory[ITEM_INDEX(item)] == 1))
740: Use_PowerArmor (ent, item);
741: Drop_General (ent, item);
742: }
743:
744: //======================================================================
745:
746: /*
747: ===============
748: Touch_Item
749: ===============
750: */
751: void Touch_Item (edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf)
752: {
753: qboolean taken;
754:
755: if (!other->client)
756: return;
757: if (other->health < 1)
758: return; // dead people can't pickup
759: if (!ent->item->pickup)
760: return; // not a grabbable item?
761:
762: taken = ent->item->pickup(ent, other);
763:
764: if (taken)
765: {
766: // flash the screen
767: other->client->bonus_alpha = 0.25;
768:
769: // show icon and name on status bar
770: other->client->ps.stats[STAT_PICKUP_ICON] = gi.imageindex(ent->item->icon);
771: other->client->ps.stats[STAT_PICKUP_STRING] = CS_ITEMS+ITEM_INDEX(ent->item);
772: other->client->pickup_msg_time = level.time + 3.0;
773:
774: // change selected item
775: if (ent->item->use)
776: other->client->pers.selected_item = other->client->ps.stats[STAT_SELECTED_ITEM] = ITEM_INDEX(ent->item);
777:
778: gi.sound(other, CHAN_ITEM, gi.soundindex(ent->item->pickup_sound), 1, ATTN_NORM, 0);
779: }
780:
781: if (!(ent->spawnflags & ITEM_TARGETS_USED))
782: {
783: G_UseTargets (ent, other);
784: ent->spawnflags |= ITEM_TARGETS_USED;
785: }
786:
787: if (!taken)
788: return;
789:
790: if (!((coop->value) && (ent->item->flags & IT_STAY_COOP)) || (ent->spawnflags & (DROPPED_ITEM | DROPPED_PLAYER_ITEM)))
791: {
792: if (ent->flags & FL_RESPAWN)
793: ent->flags &= ~FL_RESPAWN;
794: else
795: G_FreeEdict (ent);
796: }
797: }
798:
799: //======================================================================
800:
801: static void drop_temp_touch (edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf)
802: {
803: if (other == ent->owner)
804: return;
805:
806: Touch_Item (ent, other, plane, surf);
807: }
808:
809: static void drop_make_touchable (edict_t *ent)
810: {
811: ent->touch = Touch_Item;
812: if (deathmatch->value)
813: {
814: ent->nextthink = level.time + 29;
815: ent->think = G_FreeEdict;
816: }
817: }
818:
819: edict_t *Drop_Item (edict_t *ent, gitem_t *item)
820: {
821: edict_t *dropped;
822: vec3_t forward, right;
823: vec3_t offset;
824:
825: dropped = G_Spawn();
826:
827: dropped->classname = item->classname;
828: dropped->item = item;
829: dropped->spawnflags = DROPPED_ITEM;
830: dropped->s.effects = item->world_model_flags;
831: dropped->s.renderfx = RF_GLOW;
832: VectorSet (dropped->mins, -15, -15, -15);
833: VectorSet (dropped->maxs, 15, 15, 15);
834: gi.setmodel (dropped, dropped->item->world_model);
835: dropped->solid = SOLID_TRIGGER;
836: dropped->movetype = MOVETYPE_TOSS;
837: dropped->touch = drop_temp_touch;
838: dropped->owner = ent;
839:
840: if (ent->client)
841: {
842: trace_t trace;
843:
844: AngleVectors (ent->client->v_angle, forward, right, NULL);
845: VectorSet(offset, 24, 0, -16);
846: G_ProjectSource (ent->s.origin, offset, forward, right, dropped->s.origin);
847: trace = gi.trace (ent->s.origin, dropped->mins, dropped->maxs,
848: dropped->s.origin, ent, CONTENTS_SOLID);
849: VectorCopy (trace.endpos, dropped->s.origin);
850: }
851: else
852: {
853: AngleVectors (ent->s.angles, forward, right, NULL);
854: VectorCopy (ent->s.origin, dropped->s.origin);
855: }
856:
857: VectorScale (forward, 100, dropped->velocity);
858: dropped->velocity[2] = 300;
859:
860: dropped->think = drop_make_touchable;
861: dropped->nextthink = level.time + 1;
862:
863: gi.linkentity (dropped);
864:
865: return dropped;
866: }
867:
868: void Use_Item (edict_t *ent, edict_t *other, edict_t *activator)
869: {
870: ent->svflags &= ~SVF_NOCLIENT;
871: ent->use = NULL;
872:
873: if (ent->spawnflags & ITEM_NO_TOUCH)
874: {
875: ent->solid = SOLID_BBOX;
876: ent->touch = NULL;
877: }
878: else
879: {
880: ent->solid = SOLID_TRIGGER;
881: ent->touch = Touch_Item;
882: }
883:
884: gi.linkentity (ent);
885: }
886:
887: //======================================================================
888:
889: /*
890: ================
891: droptofloor
892: ================
893: */
894: void droptofloor (edict_t *ent)
895: {
896: trace_t tr;
897: vec3_t dest;
898: float *v;
899:
900: v = tv(-15,-15,-15);
901: VectorCopy (v, ent->mins);
902: v = tv(15,15,15);
903: VectorCopy (v, ent->maxs);
904:
905: if (ent->model)
906: gi.setmodel (ent, ent->model);
907: else
908: gi.setmodel (ent, ent->item->world_model);
909: ent->solid = SOLID_TRIGGER;
910: ent->movetype = MOVETYPE_TOSS;
911: ent->touch = Touch_Item;
912:
913: v = tv(0,0,-128);
914: VectorAdd (ent->s.origin, v, dest);
915:
916: tr = gi.trace (ent->s.origin, ent->mins, ent->maxs, dest, ent, MASK_SOLID);
917: if (tr.startsolid)
918: {
919: gi.dprintf ("droptofloor: %s startsolid at %s\n", ent->classname, vtos(ent->s.origin));
920: G_FreeEdict (ent);
921: return;
922: }
923:
924: VectorCopy (tr.endpos, ent->s.origin);
925:
926: if (ent->team)
927: {
928: ent->flags &= ~FL_TEAMSLAVE;
929: ent->chain = ent->teamchain;
930: ent->teamchain = NULL;
931:
932: ent->svflags |= SVF_NOCLIENT;
933: ent->solid = SOLID_NOT;
934: if (ent == ent->teammaster)
935: {
936: ent->nextthink = level.time + FRAMETIME;
937: ent->think = DoRespawn;
938: }
939: }
940:
941: if (ent->spawnflags & ITEM_NO_TOUCH)
942: {
943: ent->solid = SOLID_BBOX;
944: ent->touch = NULL;
945: ent->s.effects &= ~EF_ROTATE;
946: ent->s.renderfx &= ~RF_GLOW;
947: }
948:
949: if (ent->spawnflags & ITEM_TRIGGER_SPAWN)
950: {
951: ent->svflags |= SVF_NOCLIENT;
952: ent->solid = SOLID_NOT;
953: ent->use = Use_Item;
954: }
955:
956: gi.linkentity (ent);
957: }
958:
959:
960: /*
961: ===============
962: PrecacheItem
963:
964: Precaches all data needed for a given item.
965: This will be called for each item spawned in a level,
966: and for each item in each client's inventory.
967: ===============
968: */
969: void PrecacheItem (gitem_t *it)
970: {
971: char *s, *start;
972: char data[MAX_QPATH];
973: int len;
974: gitem_t *ammo;
975:
976: if (!it)
977: return;
978:
979: if (it->pickup_sound)
980: gi.soundindex (it->pickup_sound);
981: if (it->world_model)
982: gi.modelindex (it->world_model);
983: if (it->view_model)
984: gi.modelindex (it->view_model);
985: if (it->icon)
986: gi.imageindex (it->icon);
987:
988: // parse everything for its ammo
989: if (it->ammo && it->ammo[0])
990: {
991: ammo = FindItem (it->ammo);
992: if (ammo != it)
993: PrecacheItem (ammo);
994: }
995:
996: // parse the space seperated precache string for other items
997: s = it->precaches;
998: if (!s || !s[0])
999: return;
1000:
1001: while (*s)
1002: {
1003: start = s;
1004: while (*s && *s != ' ')
1005: s++;
1006:
1007: len = s-start;
1008: if (len >= MAX_QPATH || len < 5)
1009: gi.error ("PrecacheItem: %s has bad precache string", it->classname);
1010: memcpy (data, start, len);
1011: data[len] = 0;
1012: if (*s)
1013: s++;
1014:
1015: // determine type based on extension
1016: if (!strcmp(data+len-3, "md2"))
1017: gi.modelindex (data);
1018: else if (!strcmp(data+len-3, "sp2"))
1019: gi.modelindex (data);
1020: else if (!strcmp(data+len-3, "wav"))
1021: gi.soundindex (data);
1022: if (!strcmp(data+len-3, "pcx"))
1023: gi.imageindex (data);
1024: }
1025: }
1026:
1027: /*
1028: ============
1029: SpawnItem
1030:
1031: Sets the clipping size and plants the object on the floor.
1032:
1033: Items can't be immediately dropped to floor, because they might
1034: be on an entity that hasn't spawned yet.
1035: ============
1036: */
1037: void SpawnItem (edict_t *ent, gitem_t *item)
1038: {
1039: PrecacheItem (item);
1040:
1041: if (ent->spawnflags)
1042: {
1043: if (strcmp(ent->classname, "key_power_cube") != 0)
1044: {
1045: ent->spawnflags = 0;
1046: gi.dprintf("%s at %s has invalid spawnflags set\n", ent->classname, vtos(ent->s.origin));
1047: }
1048: }
1049:
1050: // some items will be prevented in deathmatch
1051: if (deathmatch->value)
1052: {
1053: if ( (int)dmflags->value & DF_NO_ARMOR )
1054: {
1055: if (item->pickup == Pickup_Armor || item->pickup == Pickup_PowerArmor)
1056: {
1057: G_FreeEdict (ent);
1058: return;
1059: }
1060: }
1061: if ( (int)dmflags->value & DF_NO_ITEMS )
1062: {
1063: if (item->pickup == Pickup_Powerup)
1064: {
1065: G_FreeEdict (ent);
1066: return;
1067: }
1068: }
1069: if ( (int)dmflags->value & DF_NO_HEALTH )
1070: {
1071: if (item->pickup == Pickup_Health || item->pickup == Pickup_Adrenaline || item->pickup == Pickup_AncientHead)
1072: {
1073: G_FreeEdict (ent);
1074: return;
1075: }
1076: }
1077: if ( (int)dmflags->value & DF_INFINITE_AMMO )
1078: {
1079: if ( (item->flags == IT_AMMO) || (strcmp(ent->classname, "weapon_bfg") == 0) )
1080: {
1081: G_FreeEdict (ent);
1082: return;
1083: }
1084: }
1085: }
1086:
1087: if (coop->value && (strcmp(ent->classname, "key_power_cube") == 0))
1088: {
1089: ent->spawnflags |= (1 << (8 + level.power_cubes));
1090: level.power_cubes++;
1091: }
1092:
1093: // don't let them drop items that stay in a coop game
1094: if ((coop->value) && (item->flags & IT_STAY_COOP))
1095: {
1096: item->drop = NULL;
1097: }
1098:
1099: ent->item = item;
1100: ent->nextthink = level.time + 2 * FRAMETIME; // items start after other solids
1101: ent->think = droptofloor;
1102: ent->s.effects = item->world_model_flags;
1103: ent->s.renderfx = RF_GLOW;
1104: if (ent->model)
1105: gi.modelindex (ent->model);
1106: }
1107:
1108: //======================================================================
1109:
1110: gitem_t itemlist[] =
1111: {
1112: {
1113: NULL
1114: }, // leave index 0 alone
1115:
1116: //
1117: // ARMOR
1118: //
1119:
1120: /*QUAKED item_armor_body (.3 .3 1) (-16 -16 -16) (16 16 16)
1121: */
1122: {
1123: "item_armor_body",
1124: Pickup_Armor,
1125: NULL,
1126: NULL,
1127: NULL,
1128: "misc/ar1_pkup.wav",
1129: "models/items/armor/body/tris.md2", EF_ROTATE,
1130: NULL,
1131: /* icon */ "i_bodyarmor",
1132: /* pickup */ "Body Armor",
1133: /* width */ 3,
1134: 0,
1135: NULL,
1136: IT_ARMOR,
1.1.1.2 ! root 1137: 0,
1.1 root 1138: &bodyarmor_info,
1139: ARMOR_BODY,
1140: /* precache */ ""
1141: },
1142:
1143: /*QUAKED item_armor_combat (.3 .3 1) (-16 -16 -16) (16 16 16)
1144: */
1145: {
1146: "item_armor_combat",
1147: Pickup_Armor,
1148: NULL,
1149: NULL,
1150: NULL,
1151: "misc/ar1_pkup.wav",
1152: "models/items/armor/combat/tris.md2", EF_ROTATE,
1153: NULL,
1154: /* icon */ "i_combatarmor",
1155: /* pickup */ "Combat Armor",
1156: /* width */ 3,
1157: 0,
1158: NULL,
1159: IT_ARMOR,
1.1.1.2 ! root 1160: 0,
1.1 root 1161: &combatarmor_info,
1162: ARMOR_COMBAT,
1163: /* precache */ ""
1164: },
1165:
1166: /*QUAKED item_armor_jacket (.3 .3 1) (-16 -16 -16) (16 16 16)
1167: */
1168: {
1169: "item_armor_jacket",
1170: Pickup_Armor,
1171: NULL,
1172: NULL,
1173: NULL,
1174: "misc/ar1_pkup.wav",
1175: "models/items/armor/jacket/tris.md2", EF_ROTATE,
1176: NULL,
1177: /* icon */ "i_jacketarmor",
1178: /* pickup */ "Jacket Armor",
1179: /* width */ 3,
1180: 0,
1181: NULL,
1182: IT_ARMOR,
1.1.1.2 ! root 1183: 0,
1.1 root 1184: &jacketarmor_info,
1185: ARMOR_JACKET,
1186: /* precache */ ""
1187: },
1188:
1189: /*QUAKED item_armor_shard (.3 .3 1) (-16 -16 -16) (16 16 16)
1190: */
1191: {
1192: "item_armor_shard",
1193: Pickup_Armor,
1194: NULL,
1195: NULL,
1196: NULL,
1197: "misc/ar2_pkup.wav",
1198: "models/items/armor/shard/tris.md2", EF_ROTATE,
1199: NULL,
1200: /* icon */ "i_jacketarmor",
1201: /* pickup */ "Armor Shard",
1202: /* width */ 3,
1203: 0,
1204: NULL,
1205: IT_ARMOR,
1.1.1.2 ! root 1206: 0,
1.1 root 1207: NULL,
1208: ARMOR_SHARD,
1209: /* precache */ ""
1210: },
1211:
1212:
1213: /*QUAKED item_power_screen (.3 .3 1) (-16 -16 -16) (16 16 16)
1214: */
1215: {
1216: "item_power_screen",
1217: Pickup_PowerArmor,
1218: Use_PowerArmor,
1219: Drop_PowerArmor,
1220: NULL,
1221: "misc/ar3_pkup.wav",
1222: "models/items/armor/screen/tris.md2", EF_ROTATE,
1223: NULL,
1224: /* icon */ "i_powerscreen",
1225: /* pickup */ "Power Screen",
1226: /* width */ 0,
1227: 60,
1228: NULL,
1229: IT_ARMOR,
1.1.1.2 ! root 1230: 0,
1.1 root 1231: NULL,
1232: 0,
1233: /* precache */ ""
1234: },
1235:
1236: /*QUAKED item_power_shield (.3 .3 1) (-16 -16 -16) (16 16 16)
1237: */
1238: {
1239: "item_power_shield",
1240: Pickup_PowerArmor,
1241: Use_PowerArmor,
1242: Drop_PowerArmor,
1243: NULL,
1244: "misc/ar3_pkup.wav",
1245: "models/items/armor/shield/tris.md2", EF_ROTATE,
1246: NULL,
1247: /* icon */ "i_powershield",
1248: /* pickup */ "Power Shield",
1249: /* width */ 0,
1250: 60,
1251: NULL,
1252: IT_ARMOR,
1.1.1.2 ! root 1253: 0,
1.1 root 1254: NULL,
1255: 0,
1256: /* precache */ "misc/power2.wav misc/power1.wav"
1257: },
1258:
1259:
1260: //
1261: // WEAPONS
1262: //
1263:
1264: /* weapon_blaster (.3 .3 1) (-16 -16 -16) (16 16 16)
1265: always owned, never in the world
1266: */
1267: {
1268: "weapon_blaster",
1269: NULL,
1270: Use_Weapon,
1271: NULL,
1272: Weapon_Blaster,
1273: "misc/w_pkup.wav",
1274: NULL, 0,
1275: "models/weapons/v_blast/tris.md2",
1276: /* icon */ "w_blaster",
1277: /* pickup */ "Blaster",
1278: 0,
1279: 0,
1280: NULL,
1281: IT_WEAPON|IT_STAY_COOP,
1.1.1.2 ! root 1282: WEAP_BLASTER,
1.1 root 1283: NULL,
1284: 0,
1285: /* precache */ "weapons/blastf1a.wav misc/lasfly.wav"
1286: },
1287:
1288: /*QUAKED weapon_shotgun (.3 .3 1) (-16 -16 -16) (16 16 16)
1289: */
1290: {
1291: "weapon_shotgun",
1292: Pickup_Weapon,
1293: Use_Weapon,
1294: Drop_Weapon,
1295: Weapon_Shotgun,
1296: "misc/w_pkup.wav",
1297: "models/weapons/g_shotg/tris.md2", EF_ROTATE,
1298: "models/weapons/v_shotg/tris.md2",
1299: /* icon */ "w_shotgun",
1300: /* pickup */ "Shotgun",
1301: 0,
1302: 1,
1303: "Shells",
1304: IT_WEAPON|IT_STAY_COOP,
1.1.1.2 ! root 1305: WEAP_SHOTGUN,
1.1 root 1306: NULL,
1307: 0,
1308: /* precache */ "weapons/shotgf1b.wav weapons/shotgr1b.wav"
1309: },
1310:
1311: /*QUAKED weapon_supershotgun (.3 .3 1) (-16 -16 -16) (16 16 16)
1312: */
1313: {
1314: "weapon_supershotgun",
1315: Pickup_Weapon,
1316: Use_Weapon,
1317: Drop_Weapon,
1318: Weapon_SuperShotgun,
1319: "misc/w_pkup.wav",
1320: "models/weapons/g_shotg2/tris.md2", EF_ROTATE,
1321: "models/weapons/v_shotg2/tris.md2",
1322: /* icon */ "w_sshotgun",
1323: /* pickup */ "Super Shotgun",
1324: 0,
1325: 2,
1326: "Shells",
1327: IT_WEAPON|IT_STAY_COOP,
1.1.1.2 ! root 1328: WEAP_SUPERSHOTGUN,
1.1 root 1329: NULL,
1330: 0,
1331: /* precache */ "weapons/sshotf1b.wav"
1332: },
1333:
1334: /*QUAKED weapon_machinegun (.3 .3 1) (-16 -16 -16) (16 16 16)
1335: */
1336: {
1337: "weapon_machinegun",
1338: Pickup_Weapon,
1339: Use_Weapon,
1340: Drop_Weapon,
1341: Weapon_Machinegun,
1342: "misc/w_pkup.wav",
1343: "models/weapons/g_machn/tris.md2", EF_ROTATE,
1344: "models/weapons/v_machn/tris.md2",
1345: /* icon */ "w_machinegun",
1346: /* pickup */ "Machinegun",
1347: 0,
1348: 1,
1349: "Bullets",
1350: IT_WEAPON|IT_STAY_COOP,
1.1.1.2 ! root 1351: WEAP_MACHINEGUN,
1.1 root 1352: NULL,
1353: 0,
1354: /* precache */ "weapons/machgf1b.wav weapons/machgf2b.wav weapons/machgf3b.wav weapons/machgf4b.wav weapons/machgf5b.wav"
1355: },
1356:
1357: /*QUAKED weapon_chaingun (.3 .3 1) (-16 -16 -16) (16 16 16)
1358: */
1359: {
1360: "weapon_chaingun",
1361: Pickup_Weapon,
1362: Use_Weapon,
1363: Drop_Weapon,
1364: Weapon_Chaingun,
1365: "misc/w_pkup.wav",
1366: "models/weapons/g_chain/tris.md2", EF_ROTATE,
1367: "models/weapons/v_chain/tris.md2",
1368: /* icon */ "w_chaingun",
1369: /* pickup */ "Chaingun",
1370: 0,
1371: 1,
1372: "Bullets",
1373: IT_WEAPON|IT_STAY_COOP,
1.1.1.2 ! root 1374: WEAP_CHAINGUN,
1.1 root 1375: NULL,
1376: 0,
1377: /* precache */ "weapons/chngnu1a.wav weapons/chngnl1a.wav weapons/machgf3b.wav` weapons/chngnd1a.wav"
1378: },
1379:
1380: /*QUAKED ammo_grenades (.3 .3 1) (-16 -16 -16) (16 16 16)
1381: */
1382: {
1383: "ammo_grenades",
1384: Pickup_Ammo,
1385: Use_Weapon,
1386: Drop_Ammo,
1387: Weapon_Grenade,
1388: "misc/am_pkup.wav",
1389: "models/items/ammo/grenades/medium/tris.md2", 0,
1390: "models/weapons/v_handgr/tris.md2",
1391: /* icon */ "a_grenades",
1392: /* pickup */ "Grenades",
1393: /* width */ 3,
1394: 5,
1395: "grenades",
1396: IT_AMMO|IT_WEAPON,
1.1.1.2 ! root 1397: WEAP_GRENADES,
1.1 root 1398: NULL,
1399: AMMO_GRENADES,
1400: /* precache */ "weapons/hgrent1a.wav weapons/hgrena1b.wav weapons/hgrenc1b.wav weapons/hgrenb1a.wav weapons/hgrenb2a.wav "
1401: },
1402:
1403: /*QUAKED weapon_grenadelauncher (.3 .3 1) (-16 -16 -16) (16 16 16)
1404: */
1405: {
1406: "weapon_grenadelauncher",
1407: Pickup_Weapon,
1408: Use_Weapon,
1409: Drop_Weapon,
1410: Weapon_GrenadeLauncher,
1411: "misc/w_pkup.wav",
1412: "models/weapons/g_launch/tris.md2", EF_ROTATE,
1413: "models/weapons/v_launch/tris.md2",
1414: /* icon */ "w_glauncher",
1415: /* pickup */ "Grenade Launcher",
1416: 0,
1417: 1,
1418: "Grenades",
1419: IT_WEAPON|IT_STAY_COOP,
1.1.1.2 ! root 1420: WEAP_GRENADELAUNCHER,
1.1 root 1421: NULL,
1422: 0,
1423: /* precache */ "models/objects/grenade/tris.md2 weapons/grenlf1a.wav weapons/grenlr1b.wav weapons/grenlb1b.wav"
1424: },
1425:
1426: /*QUAKED weapon_rocketlauncher (.3 .3 1) (-16 -16 -16) (16 16 16)
1427: */
1428: {
1429: "weapon_rocketlauncher",
1430: Pickup_Weapon,
1431: Use_Weapon,
1432: Drop_Weapon,
1433: Weapon_RocketLauncher,
1434: "misc/w_pkup.wav",
1435: "models/weapons/g_rocket/tris.md2", EF_ROTATE,
1436: "models/weapons/v_rocket/tris.md2",
1437: /* icon */ "w_rlauncher",
1438: /* pickup */ "Rocket Launcher",
1439: 0,
1440: 1,
1441: "Rockets",
1442: IT_WEAPON|IT_STAY_COOP,
1.1.1.2 ! root 1443: WEAP_ROCKETLAUNCHER,
1.1 root 1444: NULL,
1445: 0,
1446: /* precache */ "models/objects/rocket/tris.md2 weapons/rockfly.wav weapons/rocklf1a.wav weapons/rocklr1b.wav models/objects/debris2/tris.md2"
1447: },
1448:
1449: /*QUAKED weapon_hyperblaster (.3 .3 1) (-16 -16 -16) (16 16 16)
1450: */
1451: {
1452: "weapon_hyperblaster",
1453: Pickup_Weapon,
1454: Use_Weapon,
1455: Drop_Weapon,
1456: Weapon_HyperBlaster,
1457: "misc/w_pkup.wav",
1458: "models/weapons/g_hyperb/tris.md2", EF_ROTATE,
1459: "models/weapons/v_hyperb/tris.md2",
1460: /* icon */ "w_hyperblaster",
1461: /* pickup */ "HyperBlaster",
1462: 0,
1463: 1,
1464: "Cells",
1465: IT_WEAPON|IT_STAY_COOP,
1.1.1.2 ! root 1466: WEAP_HYPERBLASTER,
1.1 root 1467: NULL,
1468: 0,
1469: /* precache */ "weapons/hyprbu1a.wav weapons/hyprbl1a.wav weapons/hyprbf1a.wav weapons/hyprbd1a.wav misc/lasfly.wav"
1470: },
1471:
1472: /*QUAKED weapon_railgun (.3 .3 1) (-16 -16 -16) (16 16 16)
1473: */
1474: {
1475: "weapon_railgun",
1476: Pickup_Weapon,
1477: Use_Weapon,
1478: Drop_Weapon,
1479: Weapon_Railgun,
1480: "misc/w_pkup.wav",
1481: "models/weapons/g_rail/tris.md2", EF_ROTATE,
1482: "models/weapons/v_rail/tris.md2",
1483: /* icon */ "w_railgun",
1484: /* pickup */ "Railgun",
1485: 0,
1486: 1,
1487: "Slugs",
1488: IT_WEAPON|IT_STAY_COOP,
1.1.1.2 ! root 1489: WEAP_RAILGUN,
1.1 root 1490: NULL,
1491: 0,
1492: /* precache */ "weapons/rg_hum.wav"
1493: },
1494:
1495: /*QUAKED weapon_bfg (.3 .3 1) (-16 -16 -16) (16 16 16)
1496: */
1497: {
1498: "weapon_bfg",
1499: Pickup_Weapon,
1500: Use_Weapon,
1501: Drop_Weapon,
1502: Weapon_BFG,
1503: "misc/w_pkup.wav",
1504: "models/weapons/g_bfg/tris.md2", EF_ROTATE,
1505: "models/weapons/v_bfg/tris.md2",
1506: /* icon */ "w_bfg",
1507: /* pickup */ "BFG10K",
1508: 0,
1509: 50,
1510: "Cells",
1511: IT_WEAPON|IT_STAY_COOP,
1.1.1.2 ! root 1512: WEAP_BFG,
1.1 root 1513: NULL,
1514: 0,
1515: /* 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"
1516: },
1517:
1518: //
1519: // AMMO ITEMS
1520: //
1521:
1522: /*QUAKED ammo_shells (.3 .3 1) (-16 -16 -16) (16 16 16)
1523: */
1524: {
1525: "ammo_shells",
1526: Pickup_Ammo,
1527: NULL,
1528: Drop_Ammo,
1529: NULL,
1530: "misc/am_pkup.wav",
1531: "models/items/ammo/shells/medium/tris.md2", 0,
1532: NULL,
1533: /* icon */ "a_shells",
1534: /* pickup */ "Shells",
1535: /* width */ 3,
1536: 10,
1537: NULL,
1538: IT_AMMO,
1.1.1.2 ! root 1539: 0,
1.1 root 1540: NULL,
1541: AMMO_SHELLS,
1542: /* precache */ ""
1543: },
1544:
1545: /*QUAKED ammo_bullets (.3 .3 1) (-16 -16 -16) (16 16 16)
1546: */
1547: {
1548: "ammo_bullets",
1549: Pickup_Ammo,
1550: NULL,
1551: Drop_Ammo,
1552: NULL,
1553: "misc/am_pkup.wav",
1554: "models/items/ammo/bullets/medium/tris.md2", 0,
1555: NULL,
1556: /* icon */ "a_bullets",
1557: /* pickup */ "Bullets",
1558: /* width */ 3,
1559: 50,
1560: NULL,
1561: IT_AMMO,
1.1.1.2 ! root 1562: 0,
1.1 root 1563: NULL,
1564: AMMO_BULLETS,
1565: /* precache */ ""
1566: },
1567:
1568: /*QUAKED ammo_cells (.3 .3 1) (-16 -16 -16) (16 16 16)
1569: */
1570: {
1571: "ammo_cells",
1572: Pickup_Ammo,
1573: NULL,
1574: Drop_Ammo,
1575: NULL,
1576: "misc/am_pkup.wav",
1577: "models/items/ammo/cells/medium/tris.md2", 0,
1578: NULL,
1579: /* icon */ "a_cells",
1580: /* pickup */ "Cells",
1581: /* width */ 3,
1582: 50,
1583: NULL,
1584: IT_AMMO,
1.1.1.2 ! root 1585: 0,
1.1 root 1586: NULL,
1587: AMMO_CELLS,
1588: /* precache */ ""
1589: },
1590:
1591: /*QUAKED ammo_rockets (.3 .3 1) (-16 -16 -16) (16 16 16)
1592: */
1593: {
1594: "ammo_rockets",
1595: Pickup_Ammo,
1596: NULL,
1597: Drop_Ammo,
1598: NULL,
1599: "misc/am_pkup.wav",
1600: "models/items/ammo/rockets/medium/tris.md2", 0,
1601: NULL,
1602: /* icon */ "a_rockets",
1603: /* pickup */ "Rockets",
1604: /* width */ 3,
1605: 5,
1606: NULL,
1607: IT_AMMO,
1.1.1.2 ! root 1608: 0,
1.1 root 1609: NULL,
1610: AMMO_ROCKETS,
1611: /* precache */ ""
1612: },
1613:
1614: /*QUAKED ammo_slugs (.3 .3 1) (-16 -16 -16) (16 16 16)
1615: */
1616: {
1617: "ammo_slugs",
1618: Pickup_Ammo,
1619: NULL,
1620: Drop_Ammo,
1621: NULL,
1622: "misc/am_pkup.wav",
1623: "models/items/ammo/slugs/medium/tris.md2", 0,
1624: NULL,
1625: /* icon */ "a_slugs",
1626: /* pickup */ "Slugs",
1627: /* width */ 3,
1628: 10,
1629: NULL,
1630: IT_AMMO,
1.1.1.2 ! root 1631: 0,
1.1 root 1632: NULL,
1633: AMMO_SLUGS,
1634: /* precache */ ""
1635: },
1636:
1637:
1638: //
1639: // POWERUP ITEMS
1640: //
1641: /*QUAKED item_quad (.3 .3 1) (-16 -16 -16) (16 16 16)
1642: */
1643: {
1644: "item_quad",
1645: Pickup_Powerup,
1646: Use_Quad,
1647: Drop_General,
1648: NULL,
1649: "items/pkup.wav",
1650: "models/items/quaddama/tris.md2", EF_ROTATE,
1651: NULL,
1652: /* icon */ "p_quad",
1653: /* pickup */ "Quad Damage",
1654: /* width */ 2,
1655: 60,
1656: NULL,
1657: IT_POWERUP,
1.1.1.2 ! root 1658: 0,
1.1 root 1659: NULL,
1660: 0,
1661: /* precache */ "items/damage.wav items/damage2.wav items/damage3.wav"
1662: },
1663:
1664: /*QUAKED item_invulnerability (.3 .3 1) (-16 -16 -16) (16 16 16)
1665: */
1666: {
1667: "item_invulnerability",
1668: Pickup_Powerup,
1669: Use_Invulnerability,
1670: Drop_General,
1671: NULL,
1672: "items/pkup.wav",
1673: "models/items/invulner/tris.md2", EF_ROTATE,
1674: NULL,
1675: /* icon */ "p_invulnerability",
1676: /* pickup */ "Invulnerability",
1677: /* width */ 2,
1678: 300,
1679: NULL,
1680: IT_POWERUP,
1.1.1.2 ! root 1681: 0,
1.1 root 1682: NULL,
1683: 0,
1684: /* precache */ "items/protect.wav items/protect2.wav items/protect4.wav"
1685: },
1686:
1687: /*QUAKED item_silencer (.3 .3 1) (-16 -16 -16) (16 16 16)
1688: */
1689: {
1690: "item_silencer",
1691: Pickup_Powerup,
1692: Use_Silencer,
1693: Drop_General,
1694: NULL,
1695: "items/pkup.wav",
1696: "models/items/silencer/tris.md2", EF_ROTATE,
1697: NULL,
1698: /* icon */ "p_silencer",
1699: /* pickup */ "Silencer",
1700: /* width */ 2,
1701: 60,
1702: NULL,
1703: IT_POWERUP,
1.1.1.2 ! root 1704: 0,
1.1 root 1705: NULL,
1706: 0,
1707: /* precache */ ""
1708: },
1709:
1710: /*QUAKED item_breather (.3 .3 1) (-16 -16 -16) (16 16 16)
1711: */
1712: {
1713: "item_breather",
1714: Pickup_Powerup,
1715: Use_Breather,
1716: Drop_General,
1717: NULL,
1718: "items/pkup.wav",
1719: "models/items/breather/tris.md2", EF_ROTATE,
1720: NULL,
1721: /* icon */ "p_rebreather",
1722: /* pickup */ "Rebreather",
1723: /* width */ 2,
1724: 60,
1725: NULL,
1726: IT_STAY_COOP|IT_POWERUP,
1.1.1.2 ! root 1727: 0,
1.1 root 1728: NULL,
1729: 0,
1730: /* precache */ "items/airout.wav"
1731: },
1732:
1733: /*QUAKED item_enviro (.3 .3 1) (-16 -16 -16) (16 16 16)
1734: */
1735: {
1736: "item_enviro",
1737: Pickup_Powerup,
1738: Use_Envirosuit,
1739: Drop_General,
1740: NULL,
1741: "items/pkup.wav",
1742: "models/items/enviro/tris.md2", EF_ROTATE,
1743: NULL,
1744: /* icon */ "p_envirosuit",
1745: /* pickup */ "Environment Suit",
1746: /* width */ 2,
1747: 60,
1748: NULL,
1749: IT_STAY_COOP|IT_POWERUP,
1.1.1.2 ! root 1750: 0,
1.1 root 1751: NULL,
1752: 0,
1753: /* precache */ "items/airout.wav"
1754: },
1755:
1756: /*QUAKED item_ancient_head (.3 .3 1) (-16 -16 -16) (16 16 16)
1757: Special item that gives +2 to maximum health
1758: */
1759: {
1760: "item_ancient_head",
1761: Pickup_AncientHead,
1762: NULL,
1763: NULL,
1764: NULL,
1765: "items/pkup.wav",
1766: "models/items/c_head/tris.md2", EF_ROTATE,
1767: NULL,
1768: /* icon */ "i_fixme",
1769: /* pickup */ "Ancient Head",
1770: /* width */ 2,
1771: 60,
1772: NULL,
1773: 0,
1.1.1.2 ! root 1774: 0,
1.1 root 1775: NULL,
1776: 0,
1777: /* precache */ ""
1778: },
1779:
1780: /*QUAKED item_adrenaline (.3 .3 1) (-16 -16 -16) (16 16 16)
1781: gives +1 to maximum health
1782: */
1783: {
1784: "item_adrenaline",
1785: Pickup_Adrenaline,
1786: NULL,
1787: NULL,
1788: NULL,
1789: "items/pkup.wav",
1790: "models/items/adrenal/tris.md2", EF_ROTATE,
1791: NULL,
1792: /* icon */ "p_adrenaline",
1793: /* pickup */ "Adrenaline",
1794: /* width */ 2,
1795: 60,
1796: NULL,
1797: 0,
1.1.1.2 ! root 1798: 0,
1.1 root 1799: NULL,
1800: 0,
1801: /* precache */ ""
1802: },
1803:
1804: /*QUAKED item_bandolier (.3 .3 1) (-16 -16 -16) (16 16 16)
1805: */
1806: {
1807: "item_bandolier",
1808: Pickup_Bandolier,
1809: NULL,
1810: NULL,
1811: NULL,
1812: "items/pkup.wav",
1813: "models/items/band/tris.md2", EF_ROTATE,
1814: NULL,
1815: /* icon */ "p_bandolier",
1816: /* pickup */ "Bandolier",
1817: /* width */ 2,
1818: 60,
1819: NULL,
1820: 0,
1.1.1.2 ! root 1821: 0,
1.1 root 1822: NULL,
1823: 0,
1824: /* precache */ ""
1825: },
1826:
1827: /*QUAKED item_pack (.3 .3 1) (-16 -16 -16) (16 16 16)
1828: */
1829: {
1830: "item_pack",
1831: Pickup_Pack,
1832: NULL,
1833: NULL,
1834: NULL,
1835: "items/pkup.wav",
1836: "models/items/pack/tris.md2", EF_ROTATE,
1837: NULL,
1838: /* icon */ "i_pack",
1839: /* pickup */ "Ammo Pack",
1840: /* width */ 2,
1841: 180,
1842: NULL,
1843: 0,
1.1.1.2 ! root 1844: 0,
1.1 root 1845: NULL,
1846: 0,
1847: /* precache */ ""
1848: },
1849:
1850: //
1851: // KEYS
1852: //
1853: /*QUAKED key_data_cd (0 .5 .8) (-16 -16 -16) (16 16 16)
1854: key for computer centers
1855: */
1856: {
1857: "key_data_cd",
1858: Pickup_Key,
1859: NULL,
1860: Drop_General,
1861: NULL,
1862: "items/pkup.wav",
1863: "models/items/keys/data_cd/tris.md2", EF_ROTATE,
1864: NULL,
1865: "k_datacd",
1866: "Data CD",
1867: 2,
1868: 0,
1869: NULL,
1870: IT_STAY_COOP|IT_KEY,
1.1.1.2 ! root 1871: 0,
1.1 root 1872: NULL,
1873: 0,
1874: /* precache */ ""
1875: },
1876:
1877: /*QUAKED key_power_cube (0 .5 .8) (-16 -16 -16) (16 16 16) TRIGGER_SPAWN NO_TOUCH
1878: warehouse circuits
1879: */
1880: {
1881: "key_power_cube",
1882: Pickup_Key,
1883: NULL,
1884: Drop_General,
1885: NULL,
1886: "items/pkup.wav",
1887: "models/items/keys/power/tris.md2", EF_ROTATE,
1888: NULL,
1889: "k_powercube",
1890: "Power Cube",
1891: 2,
1892: 0,
1893: NULL,
1894: IT_STAY_COOP|IT_KEY,
1.1.1.2 ! root 1895: 0,
1.1 root 1896: NULL,
1897: 0,
1898: /* precache */ ""
1899: },
1900:
1901: /*QUAKED key_pyramid (0 .5 .8) (-16 -16 -16) (16 16 16)
1902: key for the entrance of jail3
1903: */
1904: {
1905: "key_pyramid",
1906: Pickup_Key,
1907: NULL,
1908: Drop_General,
1909: NULL,
1910: "items/pkup.wav",
1911: "models/items/keys/pyramid/tris.md2", EF_ROTATE,
1912: NULL,
1913: "k_pyramid",
1914: "Pyramid Key",
1915: 2,
1916: 0,
1917: NULL,
1918: IT_STAY_COOP|IT_KEY,
1.1.1.2 ! root 1919: 0,
1.1 root 1920: NULL,
1921: 0,
1922: /* precache */ ""
1923: },
1924:
1925: /*QUAKED key_data_spinner (0 .5 .8) (-16 -16 -16) (16 16 16)
1926: key for the city computer
1927: */
1928: {
1929: "key_data_spinner",
1930: Pickup_Key,
1931: NULL,
1932: Drop_General,
1933: NULL,
1934: "items/pkup.wav",
1935: "models/items/keys/spinner/tris.md2", EF_ROTATE,
1936: NULL,
1937: "k_dataspin",
1938: "Data Spinner",
1939: 2,
1940: 0,
1941: NULL,
1942: IT_STAY_COOP|IT_KEY,
1.1.1.2 ! root 1943: 0,
1.1 root 1944: NULL,
1945: 0,
1946: /* precache */ ""
1947: },
1948:
1949: /*QUAKED key_pass (0 .5 .8) (-16 -16 -16) (16 16 16)
1950: security pass for the security level
1951: */
1952: {
1953: "key_pass",
1954: Pickup_Key,
1955: NULL,
1956: Drop_General,
1957: NULL,
1958: "items/pkup.wav",
1959: "models/items/keys/pass/tris.md2", EF_ROTATE,
1960: NULL,
1961: "k_security",
1962: "Security Pass",
1963: 2,
1964: 0,
1965: NULL,
1966: IT_STAY_COOP|IT_KEY,
1.1.1.2 ! root 1967: 0,
1.1 root 1968: NULL,
1969: 0,
1970: /* precache */ ""
1971: },
1972:
1973: /*QUAKED key_blue_key (0 .5 .8) (-16 -16 -16) (16 16 16)
1974: normal door key - blue
1975: */
1976: {
1977: "key_blue_key",
1978: Pickup_Key,
1979: NULL,
1980: Drop_General,
1981: NULL,
1982: "items/pkup.wav",
1983: "models/items/keys/key/tris.md2", EF_ROTATE,
1984: NULL,
1985: "k_bluekey",
1986: "Blue Key",
1987: 2,
1988: 0,
1989: NULL,
1990: IT_STAY_COOP|IT_KEY,
1.1.1.2 ! root 1991: 0,
1.1 root 1992: NULL,
1993: 0,
1994: /* precache */ ""
1995: },
1996:
1997: /*QUAKED key_red_key (0 .5 .8) (-16 -16 -16) (16 16 16)
1998: normal door key - red
1999: */
2000: {
2001: "key_red_key",
2002: Pickup_Key,
2003: NULL,
2004: Drop_General,
2005: NULL,
2006: "items/pkup.wav",
2007: "models/items/keys/red_key/tris.md2", EF_ROTATE,
2008: NULL,
2009: "k_redkey",
2010: "Red Key",
2011: 2,
2012: 0,
2013: NULL,
2014: IT_STAY_COOP|IT_KEY,
1.1.1.2 ! root 2015: 0,
1.1 root 2016: NULL,
2017: 0,
2018: /* precache */ ""
2019: },
2020:
2021: /*QUAKED key_commander_head (0 .5 .8) (-16 -16 -16) (16 16 16)
2022: tank commander's head
2023: */
2024: {
2025: "key_commander_head",
2026: Pickup_Key,
2027: NULL,
2028: Drop_General,
2029: NULL,
2030: "items/pkup.wav",
2031: "models/monsters/commandr/head/tris.md2", EF_GIB,
2032: NULL,
2033: /* icon */ "k_comhead",
2034: /* pickup */ "Commander's Head",
2035: /* width */ 2,
2036: 0,
2037: NULL,
2038: IT_STAY_COOP|IT_KEY,
1.1.1.2 ! root 2039: 0,
1.1 root 2040: NULL,
2041: 0,
2042: /* precache */ ""
2043: },
2044:
2045: /*QUAKED key_airstrike_target (0 .5 .8) (-16 -16 -16) (16 16 16)
2046: tank commander's head
2047: */
2048: {
2049: "key_airstrike_target",
2050: Pickup_Key,
2051: NULL,
2052: Drop_General,
2053: NULL,
2054: "items/pkup.wav",
2055: "models/items/keys/target/tris.md2", EF_ROTATE,
2056: NULL,
2057: /* icon */ "i_airstrike",
2058: /* pickup */ "Airstrike Marker",
2059: /* width */ 2,
2060: 0,
2061: NULL,
2062: IT_STAY_COOP|IT_KEY,
1.1.1.2 ! root 2063: 0,
1.1 root 2064: NULL,
2065: 0,
2066: /* precache */ ""
2067: },
2068:
2069: {
2070: NULL,
2071: Pickup_Health,
2072: NULL,
2073: NULL,
2074: NULL,
2075: "items/pkup.wav",
2076: NULL, 0,
2077: NULL,
2078: /* icon */ "i_health",
2079: /* pickup */ "Health",
2080: /* width */ 3,
2081: 0,
2082: NULL,
2083: 0,
1.1.1.2 ! root 2084: 0,
1.1 root 2085: NULL,
2086: 0,
2087: /* precache */ ""
2088: },
2089:
2090: // end of list marker
2091: {NULL}
2092: };
2093:
2094:
2095: /*QUAKED item_health (.3 .3 1) (-16 -16 -16) (16 16 16)
2096: */
2097: void SP_item_health (edict_t *self)
2098: {
2099: if ( deathmatch->value && ((int)dmflags->value & DF_NO_HEALTH) )
2100: {
2101: G_FreeEdict (self);
2102: return;
2103: }
2104:
2105: self->model = "models/items/healing/medium/tris.md2";
2106: self->count = 10;
2107: SpawnItem (self, FindItem ("Health"));
2108: gi.soundindex ("items/n_health.wav");
2109: }
2110:
2111: /*QUAKED item_health_small (.3 .3 1) (-16 -16 -16) (16 16 16)
2112: */
2113: void SP_item_health_small (edict_t *self)
2114: {
2115: if ( deathmatch->value && ((int)dmflags->value & DF_NO_HEALTH) )
2116: {
2117: G_FreeEdict (self);
2118: return;
2119: }
2120:
2121: self->model = "models/items/healing/stimpack/tris.md2";
2122: self->count = 2;
2123: SpawnItem (self, FindItem ("Health"));
2124: self->style = HEALTH_IGNORE_MAX;
2125: gi.soundindex ("items/s_health.wav");
2126: }
2127:
2128: /*QUAKED item_health_large (.3 .3 1) (-16 -16 -16) (16 16 16)
2129: */
2130: void SP_item_health_large (edict_t *self)
2131: {
2132: if ( deathmatch->value && ((int)dmflags->value & DF_NO_HEALTH) )
2133: {
2134: G_FreeEdict (self);
2135: return;
2136: }
2137:
2138: self->model = "models/items/healing/large/tris.md2";
2139: self->count = 25;
2140: SpawnItem (self, FindItem ("Health"));
2141: gi.soundindex ("items/l_health.wav");
2142: }
2143:
2144: /*QUAKED item_health_mega (.3 .3 1) (-16 -16 -16) (16 16 16)
2145: */
2146: void SP_item_health_mega (edict_t *self)
2147: {
2148: if ( deathmatch->value && ((int)dmflags->value & DF_NO_HEALTH) )
2149: {
2150: G_FreeEdict (self);
2151: return;
2152: }
2153:
2154: self->model = "models/items/mega_h/tris.md2";
2155: self->count = 100;
2156: SpawnItem (self, FindItem ("Health"));
2157: gi.soundindex ("items/m_health.wav");
2158: self->style = HEALTH_IGNORE_MAX|HEALTH_TIMED;
2159: }
2160:
2161:
2162: void InitItems (void)
2163: {
2164: game.num_items = sizeof(itemlist)/sizeof(itemlist[0]) - 1;
2165: }
2166:
2167:
2168:
2169: /*
2170: ===============
2171: SetItemNames
2172:
2173: Called by worldspawn
2174: ===============
2175: */
2176: void SetItemNames (void)
2177: {
2178: int i;
2179: gitem_t *it;
2180:
2181: for (i=0 ; i<game.num_items ; i++)
2182: {
2183: it = &itemlist[i];
2184: gi.configstring (CS_ITEMS+i, it->pickup_name);
2185: }
2186:
2187: jacket_armor_index = ITEM_INDEX(FindItem("Jacket Armor"));
2188: combat_armor_index = ITEM_INDEX(FindItem("Combat Armor"));
2189: body_armor_index = ITEM_INDEX(FindItem("Body Armor"));
2190: power_screen_index = ITEM_INDEX(FindItem("Power Screen"));
2191: power_shield_index = ITEM_INDEX(FindItem("Power Shield"));
2192: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.