home *** CD-ROM | disk | FTP | other *** search
/ Quake 'em / QUAKEEM.BIN / quake / programs / byomv10 / items.qc < prev    next >
Encoding:
Text File  |  1996-08-13  |  30.7 KB  |  1,413 lines

  1. void() W_SetCurrentAmmo;
  2. /* ALL LIGHTS SHOULD BE 0 1 0 IN COLOR ALL OTHER ITEMS SHOULD
  3. BE .8 .3 .4 IN COLOR */
  4.  
  5.  
  6. void() SUB_regen =
  7. {
  8.     self.model = self.mdl;        // restore original model
  9.     self.solid = SOLID_TRIGGER;    // allow it to be touched again
  10.     sound (self, CHAN_VOICE, "items/itembk2.wav", 1, ATTN_NORM);    // play respawn sound
  11.     setorigin (self, self.origin);
  12. };
  13.  
  14.  
  15.  
  16. /*QUAKED noclass (0 0 0) (-8 -8 -8) (8 8 8)
  17. prints a warning message when spawned
  18. */
  19. void() noclass =
  20. {
  21.     dprint ("noclass spawned at");
  22.     dprint (vtos(self.origin));
  23.     dprint ("\n");
  24.     remove (self);
  25. };
  26.  
  27.  
  28.  
  29. /*
  30. ============
  31. PlaceItem
  32.  
  33. plants the object on the floor
  34. ============
  35. */
  36. void() PlaceItem =
  37. {
  38.     local float    oldz;
  39.  
  40.     self.mdl = self.model;        // so it can be restored on respawn
  41.     self.flags = FL_ITEM;        // make extra wide
  42.     self.solid = SOLID_TRIGGER;
  43.     self.movetype = MOVETYPE_TOSS;    
  44.     self.velocity = '0 0 0';
  45.     self.origin_z = self.origin_z + 6;
  46.     oldz = self.origin_z;
  47.     if (!droptofloor())
  48.     {
  49.         dprint ("Bonus item fell out of level at ");
  50.         dprint (vtos(self.origin));
  51.         dprint ("\n");
  52.         remove(self);
  53.         return;
  54.     }
  55. };
  56.  
  57. /*
  58. ============
  59. StartItem
  60.  
  61. Sets the clipping size and plants the object on the floor
  62. ============
  63. */
  64. void() StartItem =
  65. {
  66.     self.nextthink = time + 0.2;    // items start after other solids
  67.     self.think = PlaceItem;
  68. };
  69.  
  70. /*
  71. =========================================================================
  72.  
  73. HEALTH BOX
  74.  
  75. =========================================================================
  76. */
  77. //
  78. // T_Heal: add health to an entity, limiting health to max_health
  79. // "ignore" will ignore max_health limit
  80. //
  81. float (entity e, float healamount, float ignore) T_Heal =
  82. {
  83.     if (e.health <= 0)
  84.         return 0;
  85.     if ((!ignore) && (e.health >= other.max_health))
  86.         return 0;
  87.     healamount = ceil(healamount);
  88.  
  89.     e.health = e.health + healamount;
  90.     if ((!ignore) && (e.health >= other.max_health))
  91.         e.health = other.max_health;
  92.  
  93.     // BYOM change to accomadate health limits
  94.     if (e.health > (2.5 * other.max_health))
  95.         e.health = (2.5 * other.max_health);
  96.     return 1;
  97. };
  98.  
  99. /*QUAKED item_health (.3 .3 1) (0 0 0) (32 32 32) rotten megahealth
  100. Health box. Normally gives 25 points.
  101. Rotten box heals 5-10 points,
  102. megahealth will add 100 health, then 
  103. rot you down to your maximum health limit, 
  104. one point per second.
  105. */
  106.  
  107. float    H_ROTTEN = 1;
  108. float    H_MEGA = 2;
  109. .float    healamount, healtype;
  110. void() health_touch;
  111. void() item_megahealth_rot;
  112.  
  113. void() item_health =
  114. {    
  115.     self.touch = health_touch;
  116.  
  117.     if (self.spawnflags & H_ROTTEN)
  118.     {
  119.         precache_model("maps/b_bh10.bsp");
  120.  
  121.         precache_sound("items/r_item1.wav");
  122.         setmodel(self, "maps/b_bh10.bsp");
  123.         self.noise = "items/r_item1.wav";
  124.         self.healamount = 15;
  125.         self.healtype = 0;
  126.     }
  127.     else
  128.     if (self.spawnflags & H_MEGA)
  129.     {
  130.         precache_model("maps/b_bh100.bsp");
  131.         precache_sound("items/r_item2.wav");
  132.         setmodel(self, "maps/b_bh100.bsp");
  133.         self.noise = "items/r_item2.wav";
  134.         self.healamount = 100;
  135.         self.healtype = 2;
  136.     }
  137.     else
  138.     {
  139.         precache_model("maps/b_bh25.bsp");
  140.         precache_sound("items/health1.wav");
  141.         setmodel(self, "maps/b_bh25.bsp");
  142.         self.noise = "items/health1.wav";
  143.         self.healamount = 25;
  144.         self.healtype = 1;
  145.     }
  146.     setsize (self, '0 0 0', '32 32 56');
  147.     StartItem ();
  148. };
  149.  
  150.  
  151. void() health_touch =
  152. {
  153.     local    float amount;
  154.     local    string    s;
  155.     
  156.     if (other.classname != "player")
  157.         return;
  158.  
  159.     // BYOM -- health increase dependant on max_health
  160.     //             health boxes are less effective the more health you have
  161.     if (self.healtype == 2) // Megahealth?  Ignore max_health...
  162.     {
  163.         if (other.health >= (2.5 * other.max_health))
  164.             return;
  165.         if (!T_Heal(other, other.max_health, 1))
  166.             return;
  167.     }
  168.     else
  169.     {
  170.         if (!T_Heal(other, (self.healamount * (100 / other.max_health)), 0))
  171.             return;
  172.     }
  173.     
  174.     sprint(other, "You receive ");
  175.     s = ftos(self.healamount);
  176.     sprint(other, s);
  177.     sprint(other, " health\n");
  178.     
  179. // health touch sound
  180.     sound(other, CHAN_ITEM, self.noise, 1, ATTN_NORM);
  181.  
  182.     stuffcmd (other, "bf\n");
  183.     
  184.     self.model = string_null;
  185.     self.solid = SOLID_NOT;
  186.  
  187.     // Megahealth = rot down the player's super health
  188.     if (self.healtype == 2)
  189.     {
  190.         other.items = other.items | IT_SUPERHEALTH;
  191.         self.nextthink = time + 5;
  192.         self.think = item_megahealth_rot;
  193.         self.owner = other;
  194.     }
  195.     else
  196.     {
  197.         if (deathmatch != 2)        // deathmatch 2 is the silly old rules
  198.         {
  199.             if (deathmatch)
  200.                 self.nextthink = time + 20;
  201.             self.think = SUB_regen;
  202.         }
  203.     }
  204.     
  205.     activator = other;
  206.     SUB_UseTargets();                // fire all targets / killtargets
  207. };    
  208.  
  209. void() item_megahealth_rot =
  210. {
  211.     other = self.owner;
  212.  
  213.     // BYOM -- megahealth rot different for each class
  214.     if (other.health > other.max_health)
  215.     {
  216.         other.health = other.health - 1;
  217.         self.nextthink = time + (100.0 / other.max_health);
  218.         return;
  219.     }
  220.  
  221. // it is possible for a player to die and respawn between rots, so don't
  222. // just blindly subtract the flag off
  223.     other.items = other.items - (other.items & IT_SUPERHEALTH);
  224.     
  225.     if (deathmatch == 1)    // deathmatch 2 is silly old rules
  226.     {
  227.         self.nextthink = time + 20;
  228.         self.think = SUB_regen;
  229.     }
  230. };
  231.  
  232. /*
  233. ===============================================================================
  234.  
  235. ARMOR
  236.  
  237. ===============================================================================
  238. */
  239.  
  240. void() armor_touch;
  241.  
  242. void() armor_touch =
  243. {
  244.     local    float    type, value, bit;
  245.     
  246.     if (other.health <= 0)
  247.         return;
  248.     if (other.classname != "player")
  249.         return;
  250.  
  251.     if (self.classname == "item_armor1")
  252.     {
  253.         type = 0.3;
  254.         value = 100;
  255.         bit = IT_ARMOR1;
  256.     }
  257.     if (self.classname == "item_armor2")
  258.     {
  259.         type = 0.6;
  260.         value = 150;
  261.         bit = IT_ARMOR2;
  262.     }
  263.     if (self.classname == "item_armorInv")
  264.     {
  265.         type = 0.8;
  266.         value = 200;
  267.         bit = IT_ARMOR3;
  268.     }
  269.     if (other.armortype*other.armorvalue >= type*value)
  270.         return;
  271.     // BYOM -- monsters can't use armor
  272.     if (other.class) {
  273.         sprint(other, "You destroy that which you cannot possess\n");
  274.         self.solid = SOLID_NOT;
  275.         self.model = string_null;
  276.         if (deathmatch == 1)
  277.             self.nextthink = time + 20;
  278.         self.think = SUB_regen;
  279.  
  280.         activator = other;
  281.         SUB_UseTargets();               // fire all targets / killtargets
  282.         return;
  283.     }
  284.     other.armortype = type;
  285.     other.armorvalue = value;
  286.     other.items = other.items - (other.items & (IT_ARMOR1 | IT_ARMOR2 | IT_ARMOR3)) + bit;
  287.  
  288.     sprint(other, "You got armor\n");
  289. // armor touch sound
  290.     sound(other, CHAN_ITEM, "items/armor1.wav", 1, ATTN_NORM);
  291.     stuffcmd (other, "bf\n");
  292.  
  293.     self.solid = SOLID_NOT;
  294.     self.model = string_null;
  295.     if (deathmatch == 1)
  296.         self.nextthink = time + 20;
  297.     self.think = SUB_regen;
  298.  
  299.     activator = other;
  300.     SUB_UseTargets();                // fire all targets / killtargets
  301. };
  302.  
  303.  
  304. /*QUAKED item_armor1 (0 .5 .8) (-16 -16 0) (16 16 32)
  305. */
  306.  
  307. void() item_armor1 =
  308. {
  309.     self.touch = armor_touch;
  310.     precache_model ("progs/armor.mdl");
  311.     setmodel (self, "progs/armor.mdl");
  312.     self.skin = 0;
  313.     setsize (self, '-16 -16 0', '16 16 56');
  314.     StartItem ();
  315. };
  316.  
  317. /*QUAKED item_armor2 (0 .5 .8) (-16 -16 0) (16 16 32)
  318. */
  319.  
  320. void() item_armor2 =
  321. {
  322.     self.touch = armor_touch;
  323.     precache_model ("progs/armor.mdl");
  324.     setmodel (self, "progs/armor.mdl");
  325.     self.skin = 1;
  326.     setsize (self, '-16 -16 0', '16 16 56');
  327.     StartItem ();
  328. };
  329.  
  330. /*QUAKED item_armorInv (0 .5 .8) (-16 -16 0) (16 16 32)
  331. */
  332.  
  333. void() item_armorInv =
  334. {
  335.     self.touch = armor_touch;
  336.     precache_model ("progs/armor.mdl");
  337.     setmodel (self, "progs/armor.mdl");
  338.     self.skin = 2;
  339.     setsize (self, '-16 -16 0', '16 16 56');
  340.     StartItem ();
  341. };
  342.  
  343. /*
  344. ===============================================================================
  345.  
  346. WEAPONS
  347.  
  348. ===============================================================================
  349. */
  350.  
  351. void() bound_other_ammo =
  352. {
  353.     if (other.ammo_shells > 100)
  354.         other.ammo_shells = 100;
  355.     if (other.ammo_nails > 200)
  356.         other.ammo_nails = 200;
  357.     if (other.ammo_rockets > 100)
  358.         other.ammo_rockets = 100;        
  359.     if (other.ammo_cells > 100)
  360.         other.ammo_cells = 100;        
  361. };
  362.  
  363.  
  364. float(float w) RankForWeapon =
  365. {
  366.     if (w == IT_LIGHTNING)
  367.         return 1;
  368.     if (w == IT_ROCKET_LAUNCHER)
  369.         return 2;
  370.     if (w == IT_SUPER_NAILGUN)
  371.         return 3;
  372.     if (w == IT_GRENADE_LAUNCHER)
  373.         return 4;
  374.     if (w == IT_SUPER_SHOTGUN)
  375.         return 5;
  376.     if (w == IT_NAILGUN)
  377.         return 6;
  378.     return 7;
  379. };
  380.  
  381. /*
  382. =============
  383. Deathmatch_Weapon
  384.  
  385. Deathmatch weapon change rules for picking up a weapon
  386.  
  387. .float        ammo_shells, ammo_nails, ammo_rockets, ammo_cells;
  388. =============
  389. */
  390. void(float old, float new) Deathmatch_Weapon =
  391. {
  392.     local float or, nr;
  393.  
  394. // change self.weapon if desired
  395.     or = RankForWeapon (self.weapon);
  396.     nr = RankForWeapon (new);
  397.     if ( nr < or )
  398.         self.weapon = new;
  399. };
  400.  
  401. /*
  402. =============
  403. weapon_touch
  404. =============
  405. */
  406. float() W_BestWeapon;
  407.  
  408. void() weapon_touch =
  409. {
  410.     local    float    hadammo, best, new, old;
  411.     local    entity    stemp;
  412.     local    float    leave;
  413.  
  414.     if (!(other.flags & FL_CLIENT))
  415.         return;
  416.  
  417. // if the player was using his best weapon, change up to the new one if better        
  418.     stemp = self;
  419.     self = other;
  420.     best = W_BestWeapon();
  421.     self = stemp;
  422.  
  423.     if (deathmatch == 2 || coop)
  424.         leave = 1;
  425.     else
  426.         leave = 0;
  427.  
  428.     // BYOM -- monsters have no use for weapons
  429.     if (other.class) {
  430.         sprint(other, "You destroy that which you cannot possess\n");
  431.         // remove it in single player, or setup for respawning in deathmatch
  432.         self.model = string_null;
  433.         self.solid = SOLID_NOT;
  434.         if (deathmatch == 1)
  435.             self.nextthink = time + 30;
  436.         self.think = SUB_regen; 
  437.         activator = other;
  438.         SUB_UseTargets();               // fire all targets / killtargets
  439.         return;
  440.     }
  441.  
  442.     if (self.classname == "weapon_nailgun")
  443.     {
  444.         if (leave && (other.items & IT_NAILGUN) )
  445.             return;
  446.         hadammo = other.ammo_nails;            
  447.         new = IT_NAILGUN;
  448.         other.ammo_nails = other.ammo_nails + 30;
  449.     }
  450.     else if (self.classname == "weapon_supernailgun")
  451.     {
  452.         if (leave && (other.items & IT_SUPER_NAILGUN) )
  453.             return;
  454.         hadammo = other.ammo_rockets;            
  455.         new = IT_SUPER_NAILGUN;
  456.         other.ammo_nails = other.ammo_nails + 30;
  457.     }
  458.     else if (self.classname == "weapon_supershotgun")
  459.     {
  460.         if (leave && (other.items & IT_SUPER_SHOTGUN) )
  461.             return;
  462.         hadammo = other.ammo_rockets;            
  463.         new = IT_SUPER_SHOTGUN;
  464.         other.ammo_shells = other.ammo_shells + 5;
  465.     }
  466.     else if (self.classname == "weapon_rocketlauncher")
  467.     {
  468.         if (leave && (other.items & IT_ROCKET_LAUNCHER) )
  469.             return;
  470.         hadammo = other.ammo_rockets;            
  471.         new = IT_ROCKET_LAUNCHER;
  472.         other.ammo_rockets = other.ammo_rockets + 5;
  473.     }
  474.     else if (self.classname == "weapon_grenadelauncher")
  475.     {
  476.         if (leave && (other.items & IT_GRENADE_LAUNCHER) )
  477.             return;
  478.         hadammo = other.ammo_rockets;            
  479.         new = IT_GRENADE_LAUNCHER;
  480.         other.ammo_rockets = other.ammo_rockets + 5;
  481.     }
  482.     else if (self.classname == "weapon_lightning")
  483.     {
  484.         if (leave && (other.items & IT_LIGHTNING) )
  485.             return;
  486.         hadammo = other.ammo_rockets;            
  487.         new = IT_LIGHTNING;
  488.         other.ammo_cells = other.ammo_cells + 15;
  489.     }
  490.     else
  491.         objerror ("weapon_touch: unknown classname");
  492.  
  493.     sprint (other, "You got the ");
  494.     sprint (other, self.netname);
  495.     sprint (other, "\n");
  496. // weapon touch sound
  497.     sound (other, CHAN_ITEM, "weapons/pkup.wav", 1, ATTN_NORM);
  498.     stuffcmd (other, "bf\n");
  499.  
  500.     bound_other_ammo ();
  501.  
  502. // change to the weapon
  503.     old = other.items;
  504.     other.items = other.items | new;
  505.     
  506.     stemp = self;
  507.     self = other;
  508.  
  509.     if (!deathmatch)
  510.         self.weapon = new;
  511.     else
  512.         Deathmatch_Weapon (old, new);
  513.  
  514.     W_SetCurrentAmmo();
  515.  
  516.     self = stemp;
  517.  
  518.     if (leave)
  519.         return;
  520.  
  521. // remove it in single player, or setup for respawning in deathmatch
  522.     self.model = string_null;
  523.     self.solid = SOLID_NOT;
  524.     if (deathmatch == 1)
  525.         self.nextthink = time + 30;
  526.     
  527.     self.think = SUB_regen;
  528.  
  529.     activator = other;
  530.     SUB_UseTargets();                // fire all targets / killtargets
  531.  
  532.  
  533. };
  534.  
  535.  
  536. /*QUAKED weapon_supershotgun (0 .5 .8) (-16 -16 0) (16 16 32)
  537. */
  538.  
  539. void() weapon_supershotgun =
  540. {
  541.     precache_model ("progs/g_shot.mdl");
  542.     setmodel (self, "progs/g_shot.mdl");
  543.     self.weapon = IT_SUPER_SHOTGUN;
  544.     self.netname = "Double-barrelled Shotgun";
  545.     self.touch = weapon_touch;
  546.     setsize (self, '-16 -16 0', '16 16 56');
  547.     StartItem ();
  548. };
  549.  
  550. /*QUAKED weapon_nailgun (0 .5 .8) (-16 -16 0) (16 16 32)
  551. */
  552.  
  553. void() weapon_nailgun =
  554. {
  555.     precache_model ("progs/g_nail.mdl");
  556.     setmodel (self, "progs/g_nail.mdl");
  557.     self.weapon = IT_NAILGUN;
  558.     self.netname = "nailgun";
  559.     self.touch = weapon_touch;
  560.     setsize (self, '-16 -16 0', '16 16 56');
  561.     StartItem ();
  562. };
  563.  
  564. /*QUAKED weapon_supernailgun (0 .5 .8) (-16 -16 0) (16 16 32)
  565. */
  566.  
  567. void() weapon_supernailgun =
  568. {
  569.     precache_model ("progs/g_nail2.mdl");
  570.     setmodel (self, "progs/g_nail2.mdl");
  571.     self.weapon = IT_SUPER_NAILGUN;
  572.     self.netname = "Super Nailgun";
  573.     self.touch = weapon_touch;
  574.     setsize (self, '-16 -16 0', '16 16 56');
  575.     StartItem ();
  576. };
  577.  
  578. /*QUAKED weapon_grenadelauncher (0 .5 .8) (-16 -16 0) (16 16 32)
  579. */
  580.  
  581. void() weapon_grenadelauncher =
  582. {
  583.     precache_model ("progs/g_rock.mdl");
  584.     setmodel (self, "progs/g_rock.mdl");
  585.     self.weapon = 3;
  586.     self.netname = "Grenade Launcher";
  587.     self.touch = weapon_touch;
  588.     setsize (self, '-16 -16 0', '16 16 56');
  589.     StartItem ();
  590. };
  591.  
  592. /*QUAKED weapon_rocketlauncher (0 .5 .8) (-16 -16 0) (16 16 32)
  593. */
  594.  
  595. void() weapon_rocketlauncher =
  596. {
  597.     precache_model ("progs/g_rock2.mdl");
  598.     setmodel (self, "progs/g_rock2.mdl");
  599.     self.weapon = 3;
  600.     self.netname = "Rocket Launcher";
  601.     self.touch = weapon_touch;
  602.     setsize (self, '-16 -16 0', '16 16 56');
  603.     StartItem ();
  604. };
  605.  
  606.  
  607. /*QUAKED weapon_lightning (0 .5 .8) (-16 -16 0) (16 16 32)
  608. */
  609.  
  610. void() weapon_lightning =
  611. {
  612.     precache_model ("progs/g_light.mdl");
  613.     setmodel (self, "progs/g_light.mdl");
  614.     self.weapon = 3;
  615.     self.netname = "Thunderbolt";
  616.     self.touch = weapon_touch;
  617.     setsize (self, '-16 -16 0', '16 16 56');
  618.     StartItem ();
  619. };
  620.  
  621.  
  622. /*
  623. ===============================================================================
  624.  
  625. AMMO
  626.  
  627. ===============================================================================
  628. */
  629.  
  630. void() ammo_touch =
  631. {
  632. local entity    stemp;
  633. local float        best;
  634.  
  635.     if (other.classname != "player")
  636.         return;
  637.     if (other.health <= 0)
  638.         return;
  639.  
  640.     // BYOM -- monsters have no use for weapons
  641.     if (other.class) {
  642.         // remove it in single player, or setup for respawning in deathmatch
  643.         sprint(other, "You destroy that which you cannot possess\n");
  644.         self.model = string_null;
  645.         self.solid = SOLID_NOT;
  646.         if (deathmatch == 1)
  647.             self.nextthink = time + 30;    
  648.         self.think = SUB_regen;
  649.  
  650.         activator = other;
  651.         SUB_UseTargets();               // fire all targets / killtargets
  652.         return;
  653.     }
  654.  
  655.  
  656. // if the player was using his best weapon, change up to the new one if better
  657.     stemp = self;
  658.     self = other;
  659.     best = W_BestWeapon();
  660.     self = stemp;
  661.  
  662.  
  663. // shotgun
  664.     if (self.weapon == 1)
  665.     {
  666.         if (other.ammo_shells >= 100)
  667.             return;
  668.         other.ammo_shells = other.ammo_shells + self.aflag;
  669.     }
  670.  
  671. // spikes
  672.     if (self.weapon == 2)
  673.     {
  674.         if (other.ammo_nails >= 200)
  675.             return;
  676.         other.ammo_nails = other.ammo_nails + self.aflag;
  677.     }
  678.  
  679. //    rockets
  680.     if (self.weapon == 3)
  681.     {
  682.         if (other.ammo_rockets >= 100)
  683.             return;
  684.         other.ammo_rockets = other.ammo_rockets + self.aflag;
  685.     }
  686.  
  687. //    cells
  688.     if (self.weapon == 4)
  689.     {
  690.         if (other.ammo_cells >= 200)
  691.             return;
  692.         other.ammo_cells = other.ammo_cells + self.aflag;
  693.     }
  694.  
  695.     bound_other_ammo ();
  696.     
  697.     sprint (other, "You got the ");
  698.     sprint (other, self.netname);
  699.     sprint (other, "\n");
  700. // ammo touch sound
  701.     sound (other, CHAN_ITEM, "weapons/lock4.wav", 1, ATTN_NORM);
  702.     stuffcmd (other, "bf\n");
  703.  
  704. // change to a better weapon if appropriate
  705.  
  706.     if ( other.weapon == best )
  707.     {
  708.         stemp = self;
  709.         self = other;
  710.         self.weapon = W_BestWeapon();
  711.         W_SetCurrentAmmo ();
  712.         self = stemp;
  713.     }
  714.  
  715. // if changed current ammo, update it
  716.     stemp = self;
  717.     self = other;
  718.     W_SetCurrentAmmo();
  719.     self = stemp;
  720.  
  721. // remove it in single player, or setup for respawning in deathmatch
  722.     self.model = string_null;
  723.     self.solid = SOLID_NOT;
  724.     if (deathmatch == 1)
  725.         self.nextthink = time + 30;
  726.     
  727.     self.think = SUB_regen;
  728.  
  729.     activator = other;
  730.     SUB_UseTargets();                // fire all targets / killtargets
  731. };
  732.  
  733.  
  734.  
  735.  
  736. float WEAPON_BIG2 = 1;
  737.  
  738. /*QUAKED item_shells (0 .5 .8) (0 0 0) (32 32 32) big
  739. */
  740.  
  741. void() item_shells =
  742. {
  743.     self.touch = ammo_touch;
  744.  
  745.     if (self.spawnflags & WEAPON_BIG2)
  746.     {
  747.         precache_model ("maps/b_shell1.bsp");
  748.         setmodel (self, "maps/b_shell1.bsp");
  749.         self.aflag = 40;
  750.     }
  751.     else
  752.     {
  753.         precache_model ("maps/b_shell0.bsp");
  754.         setmodel (self, "maps/b_shell0.bsp");
  755.         self.aflag = 20;
  756.     }
  757.     self.weapon = 1;
  758.     self.netname = "shells";
  759.     setsize (self, '0 0 0', '32 32 56');
  760.     StartItem ();
  761. };
  762.  
  763. /*QUAKED item_spikes (0 .5 .8) (0 0 0) (32 32 32) big
  764. */
  765.  
  766. void() item_spikes =
  767. {
  768.     self.touch = ammo_touch;
  769.  
  770.     if (self.spawnflags & WEAPON_BIG2)
  771.     {
  772.         precache_model ("maps/b_nail1.bsp");
  773.         setmodel (self, "maps/b_nail1.bsp");
  774.         self.aflag = 50;
  775.     }
  776.     else
  777.     {
  778.         precache_model ("maps/b_nail0.bsp");
  779.         setmodel (self, "maps/b_nail0.bsp");
  780.         self.aflag = 25;
  781.     }
  782.     self.weapon = 2;
  783.     self.netname = "nails";
  784.     setsize (self, '0 0 0', '32 32 56');
  785.     StartItem ();
  786. };
  787.  
  788. /*QUAKED item_rockets (0 .5 .8) (0 0 0) (32 32 32) big
  789. */
  790.  
  791. void() item_rockets =
  792. {
  793.     self.touch = ammo_touch;
  794.  
  795.     if (self.spawnflags & WEAPON_BIG2)
  796.     {
  797.         precache_model ("maps/b_rock1.bsp");
  798.         setmodel (self, "maps/b_rock1.bsp");
  799.         self.aflag = 10;
  800.     }
  801.     else
  802.     {
  803.         precache_model ("maps/b_rock0.bsp");
  804.         setmodel (self, "maps/b_rock0.bsp");
  805.         self.aflag = 5;
  806.     }
  807.     self.weapon = 3;
  808.     self.netname = "rockets";
  809.     setsize (self, '0 0 0', '32 32 56');
  810.     StartItem ();
  811. };
  812.  
  813.  
  814. /*QUAKED item_cells (0 .5 .8) (0 0 0) (32 32 32) big
  815. */
  816.  
  817. void() item_cells =
  818. {
  819.     self.touch = ammo_touch;
  820.  
  821.     if (self.spawnflags & WEAPON_BIG2)
  822.     {
  823.         precache_model ("maps/b_batt1.bsp");
  824.         setmodel (self, "maps/b_batt1.bsp");
  825.         self.aflag = 12;
  826.     }
  827.     else
  828.     {
  829.         precache_model ("maps/b_batt0.bsp");
  830.         setmodel (self, "maps/b_batt0.bsp");
  831.         self.aflag = 6;
  832.     }
  833.     self.weapon = 4;
  834.     self.netname = "cells";
  835.     setsize (self, '0 0 0', '32 32 56');
  836.     StartItem ();
  837. };
  838.  
  839.  
  840. /*QUAKED item_weapon (0 .5 .8) (0 0 0) (32 32 32) shotgun rocket spikes big
  841. DO NOT USE THIS!!!! IT WILL BE REMOVED!
  842. */
  843.  
  844. float WEAPON_SHOTGUN = 1;
  845. float WEAPON_ROCKET = 2;
  846. float WEAPON_SPIKES = 4;
  847. float WEAPON_BIG = 8;
  848. void() item_weapon =
  849. {
  850.     self.touch = ammo_touch;
  851.  
  852.     if (self.spawnflags & WEAPON_SHOTGUN)
  853.     {
  854.         if (self.spawnflags & WEAPON_BIG)
  855.         {
  856.             precache_model ("maps/b_shell1.bsp");
  857.             setmodel (self, "maps/b_shell1.bsp");
  858.             self.aflag = 40;
  859.         }
  860.         else
  861.         {
  862.             precache_model ("maps/b_shell0.bsp");
  863.             setmodel (self, "maps/b_shell0.bsp");
  864.             self.aflag = 20;
  865.         }
  866.         self.weapon = 1;
  867.         self.netname = "shells";
  868.     }
  869.  
  870.     if (self.spawnflags & WEAPON_SPIKES)
  871.     {
  872.         if (self.spawnflags & WEAPON_BIG)
  873.         {
  874.             precache_model ("maps/b_nail1.bsp");
  875.             setmodel (self, "maps/b_nail1.bsp");
  876.             self.aflag = 40;
  877.         }
  878.         else
  879.         {
  880.             precache_model ("maps/b_nail0.bsp");
  881.             setmodel (self, "maps/b_nail0.bsp");
  882.             self.aflag = 20;
  883.         }
  884.         self.weapon = 2;
  885.         self.netname = "spikes";
  886.     }
  887.  
  888.     if (self.spawnflags & WEAPON_ROCKET)
  889.     {
  890.         if (self.spawnflags & WEAPON_BIG)
  891.         {
  892.             precache_model ("maps/b_rock1.bsp");
  893.             setmodel (self, "maps/b_rock1.bsp");
  894.             self.aflag = 10;
  895.         }
  896.         else
  897.         {
  898.             precache_model ("maps/b_rock0.bsp");
  899.             setmodel (self, "maps/b_rock0.bsp");
  900.             self.aflag = 5;
  901.         }
  902.         self.weapon = 3;
  903.         self.netname = "rockets";
  904.     }
  905.     
  906.     setsize (self, '0 0 0', '32 32 56');
  907.     StartItem ();
  908. };
  909.  
  910.  
  911. /*
  912. ===============================================================================
  913.  
  914. KEYS
  915.  
  916. ===============================================================================
  917. */
  918.  
  919. void() key_touch =
  920. {
  921. local entity    stemp;
  922. local float        best;
  923.  
  924.     if (other.classname != "player")
  925.         return;
  926.     if (other.health <= 0)
  927.         return;
  928.     if (other.items & self.items)
  929.         return;
  930.  
  931.     sprint (other, "You got the ");
  932.     sprint (other, self.netname);
  933.     sprint (other,"\n");
  934.  
  935.     sound (other, CHAN_ITEM, self.noise, 1, ATTN_NORM);
  936.     stuffcmd (other, "bf\n");
  937.     other.items = other.items | self.items;
  938.  
  939.     if (!coop)
  940.     {    
  941.         self.solid = SOLID_NOT;
  942.         self.model = string_null;
  943.     }
  944.  
  945.     activator = other;
  946.     SUB_UseTargets();                // fire all targets / killtargets
  947. };
  948.  
  949.  
  950. void() key_setsounds =
  951. {
  952.     if (world.worldtype == 0)
  953.     {
  954.         precache_sound ("misc/medkey.wav");
  955.         self.noise = "misc/medkey.wav";
  956.     }
  957.     if (world.worldtype == 1)
  958.     {
  959.         precache_sound ("misc/runekey.wav");
  960.         self.noise = "misc/runekey.wav";
  961.     }
  962.     if (world.worldtype == 2)
  963.     {
  964.         precache_sound2 ("misc/basekey.wav");
  965.         self.noise = "misc/basekey.wav";
  966.     }
  967. };
  968.  
  969. /*QUAKED item_key1 (0 .5 .8) (-16 -16 -24) (16 16 32)
  970. SILVER key
  971. In order for keys to work
  972. you MUST set your maps
  973. worldtype to one of the
  974. following:
  975. 0: medieval
  976. 1: metal
  977. 2: base
  978. */
  979.  
  980. void() item_key1 =
  981. {
  982.     if (world.worldtype == 0)
  983.     {
  984.         precache_model ("progs/w_s_key.mdl");
  985.         setmodel (self, "progs/w_s_key.mdl");
  986.         self.netname = "silver key";
  987.     }
  988.     else if (world.worldtype == 1)
  989.     {
  990.         precache_model ("progs/m_s_key.mdl");
  991.         setmodel (self, "progs/m_s_key.mdl");
  992.         self.netname = "silver runekey";
  993.     }
  994.     else if (world.worldtype == 2)
  995.     {
  996.         precache_model2 ("progs/b_s_key.mdl");
  997.         setmodel (self, "progs/b_s_key.mdl");
  998.         self.netname = "silver keycard";
  999.     }
  1000.     key_setsounds();
  1001.     self.touch = key_touch;
  1002.     self.items = IT_KEY1;
  1003.     setsize (self, '-16 -16 -24', '16 16 32');
  1004.     StartItem ();
  1005. };
  1006.  
  1007. /*QUAKED item_key2 (0 .5 .8) (-16 -16 -24) (16 16 32)
  1008. GOLD key
  1009. In order for keys to work
  1010. you MUST set your maps
  1011. worldtype to one of the
  1012. following:
  1013. 0: medieval
  1014. 1: metal
  1015. 2: base
  1016. */
  1017.  
  1018. void() item_key2 =
  1019. {
  1020.     if (world.worldtype == 0)
  1021.     {
  1022.         precache_model ("progs/w_g_key.mdl");
  1023.         setmodel (self, "progs/w_g_key.mdl");
  1024.         self.netname = "gold key";
  1025.     }
  1026.     if (world.worldtype == 1)
  1027.     {
  1028.         precache_model ("progs/m_g_key.mdl");
  1029.         setmodel (self, "progs/m_g_key.mdl");
  1030.         self.netname = "gold runekey";
  1031.     }
  1032.     if (world.worldtype == 2)
  1033.     {
  1034.         precache_model2 ("progs/b_g_key.mdl");
  1035.         setmodel (self, "progs/b_g_key.mdl");
  1036.         self.netname = "gold keycard";
  1037.     }
  1038.     key_setsounds();
  1039.     self.touch = key_touch;
  1040.     self.items = IT_KEY2;
  1041.     setsize (self, '-16 -16 -24', '16 16 32');
  1042.     StartItem ();
  1043. };
  1044.  
  1045.  
  1046.  
  1047. /*
  1048. ===============================================================================
  1049.  
  1050. END OF LEVEL RUNES
  1051.  
  1052. ===============================================================================
  1053. */
  1054.  
  1055. void() sigil_touch =
  1056. {
  1057. local entity    stemp;
  1058. local float        best;
  1059.  
  1060.     if (other.classname != "player")
  1061.         return;
  1062.     if (other.health <= 0)
  1063.         return;
  1064.  
  1065.     centerprint (other, "You got the rune!");
  1066.  
  1067.     sound (other, CHAN_ITEM, self.noise, 1, ATTN_NORM);
  1068.     stuffcmd (other, "bf\n");
  1069.     self.solid = SOLID_NOT;
  1070.     self.model = string_null;
  1071.     serverflags = serverflags | (self.spawnflags & 15);
  1072.     self.classname = "";        // so rune doors won't find it
  1073.     
  1074.     activator = other;
  1075.     SUB_UseTargets();                // fire all targets / killtargets
  1076. };
  1077.  
  1078.  
  1079. /*QUAKED item_sigil (0 .5 .8) (-16 -16 -24) (16 16 32) E1 E2 E3 E4
  1080. End of level sigil, pick up to end episode and return to jrstart.
  1081. */
  1082.  
  1083. void() item_sigil =
  1084. {
  1085.     if (!self.spawnflags)
  1086.         objerror ("no spawnflags");
  1087.  
  1088.     precache_sound ("misc/runekey.wav");
  1089.     self.noise = "misc/runekey.wav";
  1090.  
  1091.     if (self.spawnflags & 1)
  1092.     {
  1093.         precache_model ("progs/end1.mdl");
  1094.         setmodel (self, "progs/end1.mdl");
  1095.     }
  1096.     if (self.spawnflags & 2)
  1097.     {
  1098.         precache_model2 ("progs/end2.mdl");
  1099.         setmodel (self, "progs/end2.mdl");
  1100.     }
  1101.     if (self.spawnflags & 4)
  1102.     {
  1103.         precache_model2 ("progs/end3.mdl");
  1104.         setmodel (self, "progs/end3.mdl");
  1105.     }
  1106.     if (self.spawnflags & 8)
  1107.     {
  1108.         precache_model2 ("progs/end4.mdl");
  1109.         setmodel (self, "progs/end4.mdl");
  1110.     }
  1111.     
  1112.     self.touch = sigil_touch;
  1113.     setsize (self, '-16 -16 -24', '16 16 32');
  1114.     StartItem ();
  1115. };
  1116.  
  1117. /*
  1118. ===============================================================================
  1119.  
  1120. POWERUPS
  1121.  
  1122. ===============================================================================
  1123. */
  1124.  
  1125. void() powerup_touch;
  1126.  
  1127.  
  1128. void() powerup_touch =
  1129. {
  1130. local entity    stemp;
  1131. local float        best;
  1132.  
  1133.     if (other.classname != "player")
  1134.         return;
  1135.     if (other.health <= 0)
  1136.         return;
  1137.  
  1138.     sprint (other, "You got the ");
  1139.     sprint (other, self.netname);
  1140.     sprint (other,"\n");
  1141.     // BYOM -- changes made to keep monsters from using invisiblity
  1142.     //              and biosuit
  1143.     if (deathmatch)
  1144.     {
  1145.         self.mdl = self.model;
  1146.         
  1147.         if ((self.classname == "item_artifact_invulnerability") ||
  1148.             (self.classname == "item_artifact_invisibility"))
  1149.             self.nextthink = time + 60*5;
  1150.         else
  1151.             self.nextthink = time + 60;
  1152.         
  1153.         self.think = SUB_regen;
  1154.     }    
  1155.  
  1156.     sound (other, CHAN_VOICE, self.noise, 1, ATTN_NORM);
  1157.     stuffcmd (other, "bf\n");
  1158.     self.solid = SOLID_NOT;
  1159.     self.model = string_null;
  1160.  
  1161. // do the apropriate action
  1162.     if (self.classname == "item_artifact_envirosuit")
  1163.     {
  1164.         if (other.class) {
  1165.             sprint(other, "The suit does not fit your monstrous body!\n");
  1166.         }
  1167.         else {
  1168.             other.rad_time = 1;
  1169.             other.radsuit_finished = time + 30;
  1170.             other.items = other.items | self.items;
  1171.         }
  1172.     }
  1173.     
  1174.     if (self.classname == "item_artifact_invulnerability")
  1175.     {
  1176.         other.invincible_time = 1;
  1177.         other.invincible_finished = time + 30;
  1178.         other.items = other.items | self.items;
  1179.     }
  1180.     
  1181.     if (self.classname == "item_artifact_invisibility")
  1182.     {
  1183.         if (other.class) {
  1184.             sprint(other, "The ring does not fit on your monstrous fingers!\n");
  1185.         }
  1186.         else {
  1187.             other.invisible_time = 1;
  1188.             other.invisible_finished = time + 30;
  1189.             other.items = other.items | self.items;
  1190.         }
  1191.     }
  1192.  
  1193.     if (self.classname == "item_artifact_super_damage")
  1194.     {
  1195.         other.super_time = 1;
  1196.         other.super_damage_finished = time + 30;
  1197.         other.items = other.items | self.items;
  1198.     }
  1199.  
  1200.  
  1201.     activator = other;
  1202.     SUB_UseTargets();                // fire all targets / killtargets
  1203. };
  1204.  
  1205.  
  1206.  
  1207. /*QUAKED item_artifact_invulnerability (0 .5 .8) (-16 -16 -24) (16 16 32)
  1208. Player is invulnerable for 30 seconds
  1209. */
  1210. void() item_artifact_invulnerability =
  1211. {
  1212.     self.touch = powerup_touch;
  1213.  
  1214.     precache_model ("progs/invulner.mdl");
  1215.     precache_sound ("items/protect.wav");
  1216.     precache_sound ("items/protect2.wav");
  1217.     precache_sound ("items/protect3.wav");
  1218.     self.noise = "items/protect.wav";
  1219.     setmodel (self, "progs/invulner.mdl");
  1220.     self.netname = "Pentagram of Protection";
  1221.     self.items = IT_INVULNERABILITY;
  1222.     setsize (self, '-16 -16 -24', '16 16 32');
  1223.     StartItem ();
  1224. };
  1225.  
  1226. /*QUAKED item_artifact_envirosuit (0 .5 .8) (-16 -16 -24) (16 16 32)
  1227. Player takes no damage from water or slime for 30 seconds
  1228. */
  1229. void() item_artifact_envirosuit =
  1230. {
  1231.     self.touch = powerup_touch;
  1232.  
  1233.     precache_model ("progs/suit.mdl");
  1234.     precache_sound ("items/suit.wav");
  1235.     precache_sound ("items/suit2.wav");
  1236.     self.noise = "items/suit.wav";
  1237.     setmodel (self, "progs/suit.mdl");
  1238.     self.netname = "Biosuit";
  1239.     self.items = IT_SUIT;
  1240.     setsize (self, '-16 -16 -24', '16 16 32');
  1241.     StartItem ();
  1242. };
  1243.  
  1244.  
  1245. /*QUAKED item_artifact_invisibility (0 .5 .8) (-16 -16 -24) (16 16 32)
  1246. Player is invisible for 30 seconds
  1247. */
  1248. void() item_artifact_invisibility =
  1249. {
  1250.     self.touch = powerup_touch;
  1251.  
  1252.     precache_model ("progs/invisibl.mdl");
  1253.     precache_sound ("items/inv1.wav");
  1254.     precache_sound ("items/inv2.wav");
  1255.     precache_sound ("items/inv3.wav");
  1256.     self.noise = "items/inv1.wav";
  1257.     setmodel (self, "progs/invisibl.mdl");
  1258.     self.netname = "Ring of Shadows";
  1259.     self.items = IT_INVISIBILITY;
  1260.     setsize (self, '-16 -16 -24', '16 16 32');
  1261.     StartItem ();
  1262. };
  1263.  
  1264.  
  1265. /*QUAKED item_artifact_super_damage (0 .5 .8) (-16 -16 -24) (16 16 32)
  1266. The next attack from the player will do 4x damage
  1267. */
  1268. void() item_artifact_super_damage =
  1269. {
  1270.     self.touch = powerup_touch;
  1271.  
  1272.     precache_model ("progs/quaddama.mdl");
  1273.     precache_sound ("items/damage.wav");
  1274.     precache_sound ("items/damage2.wav");
  1275.     precache_sound ("items/damage3.wav");
  1276.     self.noise = "items/damage.wav";
  1277.     setmodel (self, "progs/quaddama.mdl");
  1278.     self.netname = "Quad Damage";
  1279.     self.items = IT_QUAD;
  1280.     setsize (self, '-16 -16 -24', '16 16 32');
  1281.     StartItem ();
  1282. };
  1283.  
  1284.  
  1285.  
  1286. /*
  1287. ===============================================================================
  1288.  
  1289. PLAYER BACKPACKS
  1290.  
  1291. ===============================================================================
  1292. */
  1293.  
  1294. void() BackpackTouch =
  1295. {
  1296.     local string    s;
  1297.     local    float    best;
  1298.     local        entity    stemp;
  1299.     
  1300.     if (other.classname != "player")
  1301.         return;
  1302.     if (other.health <= 0)
  1303.         return;
  1304.  
  1305.     // BYOM
  1306.     if (other.class) {
  1307.         sprint(other, "You destroy that which you cannot possess\n");
  1308.         remove(self);
  1309.         self = other;
  1310.         return;
  1311.     }
  1312.         
  1313. // if the player was using his best weapon, change up to the new one if better        
  1314.     stemp = self;
  1315.     self = other;
  1316.     best = W_BestWeapon();
  1317.     self = stemp;
  1318.  
  1319. // change weapons
  1320.     other.ammo_shells = other.ammo_shells + self.ammo_shells;
  1321.     other.ammo_nails = other.ammo_nails + self.ammo_nails;
  1322.     other.ammo_rockets = other.ammo_rockets + self.ammo_rockets;
  1323.     other.ammo_cells = other.ammo_cells + self.ammo_cells;
  1324.  
  1325.     other.items = other.items | self.items;
  1326.     
  1327.     bound_other_ammo ();
  1328.  
  1329.     sprint (other, "You get ");
  1330.  
  1331.     if (self.ammo_shells)
  1332.     {
  1333.         s = ftos(self.ammo_shells);
  1334.         sprint (other, s);
  1335.         sprint (other, " shells  ");
  1336.     }
  1337.     if (self.ammo_nails)
  1338.     {
  1339.         s = ftos(self.ammo_nails);
  1340.         sprint (other, s);
  1341.         sprint (other, " nails ");
  1342.     }
  1343.     if (self.ammo_rockets)
  1344.     {
  1345.         s = ftos(self.ammo_rockets);
  1346.         sprint (other, s);
  1347.         sprint (other, " rockets  ");
  1348.     }
  1349.     if (self.ammo_cells)
  1350.     {
  1351.         s = ftos(self.ammo_cells);
  1352.         sprint (other, s);
  1353.         sprint (other, " cells  ");
  1354.     }
  1355.     
  1356.     sprint (other, "\n");
  1357. // backpack touch sound
  1358.     sound (other, CHAN_ITEM, "weapons/lock4.wav", 1, ATTN_NORM);
  1359.     stuffcmd (other, "bf\n");
  1360.  
  1361. // change to a better weapon if appropriate
  1362.     if ( other.weapon == best )
  1363.     {
  1364.         stemp = self;
  1365.         self = other;
  1366.         self.weapon = W_BestWeapon();
  1367.         self = stemp;
  1368.     }
  1369.  
  1370.     
  1371.     remove(self);
  1372.     
  1373.     self = other;
  1374.     W_SetCurrentAmmo ();
  1375. };
  1376.  
  1377. /*
  1378. ===============
  1379. DropBackpack
  1380. ===============
  1381. */
  1382. void() DropBackpack =
  1383. {
  1384.     local entity    item;
  1385.  
  1386.     if (!(self.ammo_shells + self.ammo_nails + self.ammo_rockets + self.ammo_cells))
  1387.         return;    // nothing in it
  1388.  
  1389.     item = spawn();
  1390.     item.origin = self.origin - '0 0 24';
  1391.     
  1392.     item.items = self.weapon;
  1393.  
  1394.     item.ammo_shells = self.ammo_shells;
  1395.     item.ammo_nails = self.ammo_nails;
  1396.     item.ammo_rockets = self.ammo_rockets;
  1397.     item.ammo_cells = self.ammo_cells;
  1398.  
  1399.     item.velocity_z = 300;
  1400.     item.velocity_x = -100 + (random() * 200);
  1401.     item.velocity_y = -100 + (random() * 200);
  1402.     
  1403.     item.flags = FL_ITEM;
  1404.     item.solid = SOLID_TRIGGER;
  1405.     item.movetype = MOVETYPE_TOSS;
  1406.     setmodel (item, "progs/backpack.mdl");
  1407.     setsize (item, '-16 -16 0', '16 16 56');
  1408.     item.touch = BackpackTouch;
  1409.     
  1410.     item.nextthink = time + 120;    // remove after 2 minutes
  1411.     item.think = SUB_Remove;
  1412. };
  1413.