home *** CD-ROM | disk | FTP | other *** search
/ Gambler 19 / GAMBLERCD19.BIN / UTILS / 3D / BRONIE / DUAL_LAU.ZIP / src / g_items.c < prev    next >
C/C++ Source or Header  |  1997-11-25  |  42KB  |  2,026 lines

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