home *** CD-ROM | disk | FTP | other *** search
/ PC Gamer 3.2 / 1997-05_Disc_3.2.iso / QUAKECTF / SRC / CTF / ITEMS.QC < prev    next >
Text File  |  1997-01-16  |  38KB  |  1,750 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.     self.bot_wants_item = TRUE;        // CTFBOT bot optimization
  57. };
  58.  
  59. /*
  60. ============
  61. StartItem
  62.  
  63. Sets the clipping size and plants the object on the floor
  64. ============
  65. */
  66. void() StartItem =
  67. {
  68.     self.nextthink = time + 0.2;    // items start after other solids
  69.     self.think = PlaceItem;
  70. };
  71.  
  72. /*
  73. =========================================================================
  74.  
  75. HEALTH BOX
  76.  
  77. =========================================================================
  78. */
  79. //
  80. // T_Heal: add health to an entity, limiting health to max_health
  81. // "ignore" will ignore max_health limit
  82. //
  83. float (entity e, float healamount, float ignore) T_Heal =
  84. {
  85.     if (e.health <= 0)
  86.         return 0;
  87.     if ((!ignore) && (e.health >= other.max_health))
  88.         return 0;
  89.     healamount = ceil(healamount);
  90.  
  91.     e.health = e.health + healamount;
  92.     if ((!ignore) && (e.health >= other.max_health))
  93.         e.health = other.max_health;
  94.         
  95.     if (e.health > 250)
  96.         e.health = 250;
  97.     return 1;
  98. };
  99.  
  100. /*QUAKED item_health (.3 .3 1) (0 0 0) (32 32 32) rotten megahealth
  101. Health box. Normally gives 25 points.
  102. Rotten box heals 5-10 points,
  103. megahealth will add 100 health, then 
  104. rot you down to your maximum health limit, 
  105. one point per second.
  106. */
  107.  
  108. float    H_ROTTEN = 1;
  109. float    H_MEGA = 2;
  110. .float    healamount, healtype;
  111. void() health_touch;
  112. void() item_megahealth_rot;
  113.  
  114. void() item_health =
  115. {    
  116.     self.touch = health_touch;
  117.  
  118.     if (self.spawnflags & H_ROTTEN)
  119.     {
  120.         precache_model("maps/b_bh10.bsp");
  121.  
  122.         precache_sound("items/r_item1.wav");
  123.         setmodel(self, "maps/b_bh10.bsp");
  124.         self.noise = "items/r_item1.wav";
  125.         self.healamount = 15;
  126.         self.healtype = 0;
  127.     }
  128.     else
  129.     if (self.spawnflags & H_MEGA)
  130.     {
  131.         precache_model("maps/b_bh100.bsp");
  132.         precache_sound("items/r_item2.wav");
  133.         setmodel(self, "maps/b_bh100.bsp");
  134.         self.noise = "items/r_item2.wav";
  135.         self.healamount = 100;
  136.         self.healtype = 2;
  137.     }
  138.     else
  139.     {
  140.         precache_model("maps/b_bh25.bsp");
  141.         precache_sound("items/health1.wav");
  142.         setmodel(self, "maps/b_bh25.bsp");
  143.         self.noise = "items/health1.wav";
  144.         self.healamount = 25;
  145.         self.healtype = 1;
  146.     }
  147.     setsize (self, '0 0 0', '32 32 56');
  148.     StartItem ();
  149. };
  150.  
  151.  
  152. void() health_touch =
  153. {
  154.     local    float amount;
  155.     local    string    s;
  156.     
  157.     if (other.classname != "player" && other.classname != "bot")    // CTFBOT
  158.         return;
  159.     
  160.     if (self.healtype == 2) // Megahealth?  Ignore max_health...
  161.     {
  162.         if (other.health >= 250)
  163.             return;
  164.         if (!T_Heal(other, self.healamount, 1))
  165.             return;
  166.     }
  167.     else
  168.     {
  169.         if (!T_Heal(other, self.healamount, 0))
  170.             return;
  171.     }
  172.     
  173.     if (other.classname == "player")    // CTFBOT
  174.     {                        // CTFBOT
  175.  
  176. // ZOID--remove uncessary msgs
  177.     if (!deathmatch) {
  178.         sprint(other, "You receive ");
  179.         s = ftos(self.healamount);
  180.         sprint(other, s);
  181.         sprint(other, " health\n");
  182.     }
  183.  
  184.         stuffcmd (other, "bf\n");        // CTFBOT moved from below
  185.  
  186.     }    // CTFBOT
  187.     
  188. // health touch sound
  189.     sound(other, CHAN_ITEM, self.noise, 1, ATTN_NORM);
  190.     
  191.     self.model = string_null;
  192.     self.solid = SOLID_NOT;
  193.  
  194.     // Megahealth = rot down the player's super health
  195.     if (self.healtype == 2)
  196.     {
  197.         other.items = other.items | IT_SUPERHEALTH;
  198.         self.nextthink = time + 5;
  199.         self.think = item_megahealth_rot;
  200.         self.owner = other;
  201.     }
  202.     else
  203.     {
  204.         if (deathmatch != 2)        // deathmatch 2 is the silly old rules
  205.         {
  206.             if (deathmatch)
  207.                 self.nextthink = time + 20;
  208.             self.think = SUB_regen;
  209.         }
  210.     }
  211.     
  212.     activator = other;
  213.     SUB_UseTargets();                // fire all targets / killtargets
  214. };    
  215.  
  216. void() item_megahealth_rot =
  217. {
  218.     other = self.owner;
  219.     
  220. //ZOID: player doesn't rot if they have Elder Magic rune
  221.     if (other.health > other.max_health && 
  222.         !(other.player_flag & ITEM_RUNE4_FLAG)) {
  223.         other.health = other.health - 1;
  224.         self.nextthink = time + 1;
  225.         return;
  226.     }
  227.  
  228. // it is possible for a player to die and respawn between rots, so don't
  229. // just blindly subtract the flag off
  230.     other.items = other.items - (other.items & IT_SUPERHEALTH);
  231.     
  232.     if (deathmatch == 1 || deathmatch == 3)    // deathmatch 2 is silly old rules
  233.     {
  234.         self.nextthink = time + 20;
  235.         self.think = SUB_regen;
  236.     }
  237. };
  238.  
  239. /*
  240. ===============================================================================
  241.  
  242. ARMOR
  243.  
  244. ===============================================================================
  245. */
  246.  
  247. void() armor_touch;
  248.  
  249. void() armor_touch =
  250. {
  251.     local    float    type, value, bit;
  252.     
  253.     if (other.health <= 0)
  254.         return;
  255.     if (other.classname != "player" && other.classname != "bot")    // CTFBOT
  256.         return;
  257.  
  258.     if (self.classname == "item_armor1")
  259.     {
  260.         type = 0.3;
  261.         value = 100;
  262.         bit = IT_ARMOR1;
  263.     }
  264.     if (self.classname == "item_armor2")
  265.     {
  266.         type = 0.6;
  267.         value = 150;
  268.         bit = IT_ARMOR2;
  269.     }
  270.     if (self.classname == "item_armorInv")
  271.     {
  272.         type = 0.8;
  273.         value = 200;
  274.         bit = IT_ARMOR3;
  275.     }
  276.     if (other.armortype*other.armorvalue >= type*value)
  277.         return;
  278.         
  279.     other.armortype = type;
  280.     other.armorvalue = value;
  281.     other.items = other.items - (other.items & (IT_ARMOR1 | IT_ARMOR2 | IT_ARMOR3)) + bit;
  282.  
  283.     self.solid = SOLID_NOT;
  284.     self.model = string_null;
  285.     if (deathmatch == 1 || deathmatch == 3)
  286.         self.nextthink = time + 20;
  287.     self.think = SUB_regen;
  288.  
  289.     // armor touch sound                            // CTFBOT moved
  290.     sound(other, CHAN_ITEM, "items/armor1.wav", 1, ATTN_NORM);    // CTFBOT moved
  291.  
  292.     if (other.classname == "player")    // CTFBOT
  293.     {                         // CTFBOT
  294.  
  295. //ZOID--remove unneccessary msgs
  296.     if (!deathmatch)
  297.         sprint(other, "You got armor\n");
  298.     stuffcmd (other, "bf\n");
  299.  
  300.     } // CTFBOT
  301.     
  302.     activator = other;
  303.     SUB_UseTargets();                // fire all targets / killtargets
  304. };
  305.  
  306.  
  307. /*QUAKED item_armor1 (0 .5 .8) (-16 -16 0) (16 16 32)
  308. */
  309.  
  310. void() item_armor1 =
  311. {
  312.     self.touch = armor_touch;
  313.     precache_model ("progs/armor.mdl");
  314.     setmodel (self, "progs/armor.mdl");
  315.     self.skin = 0;
  316.     setsize (self, '-16 -16 0', '16 16 56');
  317.     StartItem ();
  318. };
  319.  
  320. /*QUAKED item_armor2 (0 .5 .8) (-16 -16 0) (16 16 32)
  321. */
  322.  
  323. void() item_armor2 =
  324. {
  325.     self.touch = armor_touch;
  326.     precache_model ("progs/armor.mdl");
  327.     setmodel (self, "progs/armor.mdl");
  328.     self.skin = 1;
  329.     setsize (self, '-16 -16 0', '16 16 56');
  330.     StartItem ();
  331. };
  332.  
  333. /*QUAKED item_armorInv (0 .5 .8) (-16 -16 0) (16 16 32)
  334. */
  335.  
  336. void() item_armorInv =
  337. {
  338.     self.touch = armor_touch;
  339.     precache_model ("progs/armor.mdl");
  340.     setmodel (self, "progs/armor.mdl");
  341.     self.skin = 2;
  342.     setsize (self, '-16 -16 0', '16 16 56');
  343.     StartItem ();
  344. };
  345.  
  346. /*
  347. ===============================================================================
  348.  
  349. WEAPONS
  350.  
  351. ===============================================================================
  352. */
  353.  
  354. void() bound_other_ammo =
  355. {
  356.     if (other.ammo_shells > 100)
  357.         other.ammo_shells = 100;
  358.     if (other.ammo_nails > 200)
  359.         other.ammo_nails = 200;
  360.     if (other.ammo_rockets > 100)
  361.         other.ammo_rockets = 100;        
  362.     if (other.ammo_cells > 100)
  363.         other.ammo_cells = 100;        
  364. };
  365.  
  366.  
  367. float(float w) RankForWeapon =
  368. {
  369.     if (w == IT_LIGHTNING)
  370.         return 1;
  371.     if (w == IT_ROCKET_LAUNCHER)
  372.         return 2;
  373.     if (w == IT_SUPER_NAILGUN)
  374.         return 3;
  375.     if (w == IT_GRENADE_LAUNCHER)
  376.         return 4;
  377.     if (w == IT_SUPER_SHOTGUN)
  378.         return 5;
  379.     if (w == IT_NAILGUN)
  380.         return 6;
  381.     return 7;
  382. };
  383.  
  384. /*
  385. =============
  386. Deathmatch_Weapon
  387.  
  388. Deathmatch weapon change rules for picking up a weapon
  389.  
  390. .float        ammo_shells, ammo_nails, ammo_rockets, ammo_cells;
  391. =============
  392. */
  393. void(float old, float new) Deathmatch_Weapon =
  394. {
  395.     local float or, nr;
  396.  
  397. // change self.weapon if desired
  398.     if (self.weapon == IT_HOOK && self.button0)
  399.         return; // never change if we pulled ourselves to it.
  400.     or = RankForWeapon (self.weapon);
  401.     nr = RankForWeapon (new);
  402.     if ( nr < or )
  403.         self.weapon = new;
  404. };
  405.  
  406. /*
  407. =============
  408. weapon_touch
  409. =============
  410. */
  411. float() W_BestWeapon;
  412.  
  413. void() weapon_touch =
  414. {
  415.     local    float    hadammo, best, new, old;
  416.     local float bbest;    // CTFBOT
  417.     local    entity    stemp;
  418.     local    float    leave;
  419. //McBain: added prevweapon local variable
  420.     local    float    prevweapon;
  421.  
  422.     if ((!(other.flags & FL_CLIENT)) && other.classname != "bot")    // CTFBOT
  423.         return;
  424.  
  425. // if the player was using his best weapon, change up to the new one if better        
  426.     stemp = self;
  427.     self = other;
  428.     best = W_BestWeapon();
  429.     self = stemp;
  430.  
  431.     if (deathmatch == 2 || deathmatch == 3 || coop)
  432.         leave = 1;
  433.     else
  434.         leave = 0;
  435.     
  436.     if (self.classname == "weapon_nailgun")
  437.     {
  438.         if (leave && (other.items & IT_NAILGUN) )
  439.             return;
  440.         hadammo = other.ammo_nails;            
  441.         new = IT_NAILGUN;
  442. // *TEAMPLAY*
  443.         if ( !( coop && (teamplay & TEAM_DROP_ITEMS) ) )
  444.             other.ammo_nails = other.ammo_nails + 30;
  445.     }
  446.     else if (self.classname == "weapon_supernailgun")
  447.     {
  448.         if (leave && (other.items & IT_SUPER_NAILGUN) )
  449.             return;
  450.         hadammo = other.ammo_rockets;            
  451.         new = IT_SUPER_NAILGUN;
  452. // *TEAMPLAY*
  453.         if ( !( coop && (teamplay & TEAM_DROP_ITEMS) ) ) {
  454.             other.ammo_nails = other.ammo_nails + 30;
  455.         }
  456.     }
  457.     else if (self.classname == "weapon_supershotgun")
  458.     {
  459.         if (leave && (other.items & IT_SUPER_SHOTGUN) )
  460.             return;
  461.         hadammo = other.ammo_rockets;            
  462.         new = IT_SUPER_SHOTGUN;
  463. // *TEAMPLAY*
  464.         if ( !( coop && (teamplay & TEAM_DROP_ITEMS) ) )
  465.             other.ammo_shells = other.ammo_shells + 5;
  466.     }
  467.     else if (self.classname == "weapon_rocketlauncher")
  468.     {
  469.         if (leave && (other.items & IT_ROCKET_LAUNCHER) )
  470.             return;
  471.         hadammo = other.ammo_rockets;            
  472.         new = IT_ROCKET_LAUNCHER;
  473. // *TEAMPLAY*
  474.         if ( !( coop && (teamplay & TEAM_DROP_ITEMS) ) )
  475.             other.ammo_rockets = other.ammo_rockets + 5;
  476.     }
  477.     else if (self.classname == "weapon_grenadelauncher")
  478.     {
  479.         if (leave && (other.items & IT_GRENADE_LAUNCHER) )
  480.             return;
  481.         hadammo = other.ammo_rockets;            
  482.         new = IT_GRENADE_LAUNCHER;
  483. // *TEAMPLAY*
  484.         if ( !( coop && (teamplay & TEAM_DROP_ITEMS) ) )
  485.             other.ammo_rockets = other.ammo_rockets + 5;
  486.     }
  487.     else if (self.classname == "weapon_lightning")
  488.     {
  489.         if (leave && (other.items & IT_LIGHTNING) )
  490.             return;
  491.         hadammo = other.ammo_rockets;            
  492.         new = IT_LIGHTNING;
  493. // *TEAMPLAY*
  494.         if ( !( coop && (teamplay & TEAM_DROP_ITEMS) ) )
  495.             other.ammo_cells = other.ammo_cells + 15;
  496.     }
  497.     else
  498.         objerror ("weapon_touch: unknown classname");
  499.  
  500.     if (other.classname == "player")    // CTFBOT
  501.     {                        // CTFBOT
  502.  
  503. //ZOID--remove unnessary msgs
  504.     if (!deathmatch) {
  505.         sprint (other, "You got the ");
  506.         sprint (other, self.netname);
  507.         sprint (other, "\n");
  508.     }
  509.     stuffcmd (other, "bf\n");    // CTFBOT moved from below
  510.     
  511.     }    // CTFBOT
  512.  
  513. // weapon touch sound
  514.     sound (other, CHAN_ITEM, "weapons/pkup.wav", 1, ATTN_NORM);
  515.  
  516.     bound_other_ammo ();
  517.  
  518. // change to the weapon
  519.     old = other.items;
  520.     other.items = other.items | new;
  521.     
  522.     stemp = self;
  523.     self = other;
  524.  
  525. //McBain: temp store old weapon
  526.     prevweapon = self.weapon; 
  527.  
  528.     if (!deathmatch)
  529.         self.weapon = new;
  530.     else
  531.         Deathmatch_Weapon (old, new);
  532.  
  533. //McBain: save previous weapon if different
  534.     if (self.weapon != prevweapon)
  535.         self.previous_weapon = prevweapon;
  536.  
  537.     W_SetCurrentAmmo();
  538.  
  539.     self = stemp;
  540.  
  541.     if (leave)
  542.         return;
  543.  
  544. // remove it in single player, or setup for respawning in deathmatch
  545.     self.model = string_null;
  546.     self.solid = SOLID_NOT;
  547.     if (deathmatch == 1 || deathmatch == 3)
  548.         self.nextthink = time + 30;
  549.     self.think = SUB_regen;
  550.     
  551.     activator = other;
  552.     SUB_UseTargets();                // fire all targets / killtargets
  553. };
  554.  
  555.  
  556. /*QUAKED weapon_supershotgun (0 .5 .8) (-16 -16 0) (16 16 32)
  557. */
  558.  
  559. void() weapon_supershotgun =
  560. {
  561.     precache_model ("progs/g_shot.mdl");
  562.     setmodel (self, "progs/g_shot.mdl");
  563.     self.weapon = IT_SUPER_SHOTGUN;
  564.     self.netname = "Double-barrelled Shotgun";
  565.     self.touch = weapon_touch;
  566.     setsize (self, '-16 -16 0', '16 16 56');
  567.     StartItem ();
  568. };
  569.  
  570. /*QUAKED weapon_nailgun (0 .5 .8) (-16 -16 0) (16 16 32)
  571. */
  572.  
  573. void() weapon_nailgun =
  574. {
  575.     precache_model ("progs/g_nail.mdl");
  576.     setmodel (self, "progs/g_nail.mdl");
  577.     self.weapon = IT_NAILGUN;
  578.     self.netname = "nailgun";
  579.     self.touch = weapon_touch;
  580.     setsize (self, '-16 -16 0', '16 16 56');
  581.     StartItem ();
  582. };
  583.  
  584. /*QUAKED weapon_supernailgun (0 .5 .8) (-16 -16 0) (16 16 32)
  585. */
  586.  
  587. void() weapon_supernailgun =
  588. {
  589.     precache_model ("progs/g_nail2.mdl");
  590.     setmodel (self, "progs/g_nail2.mdl");
  591.     self.weapon = IT_SUPER_NAILGUN;
  592.     self.netname = "Super Nailgun";
  593.     self.touch = weapon_touch;
  594.     setsize (self, '-16 -16 0', '16 16 56');
  595.     StartItem ();
  596. };
  597.  
  598. /*QUAKED weapon_grenadelauncher (0 .5 .8) (-16 -16 0) (16 16 32)
  599. */
  600.  
  601. void() weapon_grenadelauncher =
  602. {
  603.     precache_model ("progs/g_rock.mdl");
  604.     setmodel (self, "progs/g_rock.mdl");
  605.     self.weapon = 3;
  606.     self.netname = "Grenade Launcher";
  607.     self.touch = weapon_touch;
  608.     setsize (self, '-16 -16 0', '16 16 56');
  609.     StartItem ();
  610. };
  611.  
  612. /*QUAKED weapon_rocketlauncher (0 .5 .8) (-16 -16 0) (16 16 32)
  613. */
  614.  
  615. void() weapon_rocketlauncher =
  616. {
  617.     precache_model ("progs/g_rock2.mdl");
  618.     setmodel (self, "progs/g_rock2.mdl");
  619.     self.weapon = 3;
  620.     self.netname = "Rocket Launcher";
  621.     self.touch = weapon_touch;
  622.     setsize (self, '-16 -16 0', '16 16 56');
  623.     StartItem ();
  624. };
  625.  
  626.  
  627. /*QUAKED weapon_lightning (0 .5 .8) (-16 -16 0) (16 16 32)
  628. */
  629.  
  630. void() weapon_lightning =
  631. {
  632.     precache_model ("progs/g_light.mdl");
  633.     setmodel (self, "progs/g_light.mdl");
  634.     self.weapon = 3;
  635.     self.netname = "Thunderbolt";
  636.     self.touch = weapon_touch;
  637.     setsize (self, '-16 -16 0', '16 16 56');
  638.     StartItem ();
  639. };
  640.  
  641.  
  642. /*
  643. ===============================================================================
  644.  
  645. AMMO
  646.  
  647. ===============================================================================
  648. */
  649.  
  650. void() ammo_touch =
  651. {
  652. local entity    stemp;
  653. local float        best;
  654.  
  655.     if (other.classname != "player" && other.classname != "bot")    // CTFBOT
  656.         return;
  657.     if (other.health <= 0)
  658.         return;
  659.  
  660. // if the player was using his best weapon, change up to the new one if better        
  661.     stemp = self;
  662.     self = other;
  663.     best = W_BestWeapon();
  664.     self = stemp;
  665.  
  666.  
  667. // shotgun
  668.     if (self.weapon == 1)
  669.     {
  670.         if (other.ammo_shells >= 100)
  671.             return;
  672.         other.ammo_shells = other.ammo_shells + self.aflag;
  673.     }
  674.  
  675. // spikes
  676.     if (self.weapon == 2)
  677.     {
  678.         if (other.ammo_nails >= 200)
  679.             return;
  680.         other.ammo_nails = other.ammo_nails + self.aflag;
  681.     }
  682.  
  683. //    rockets
  684.     if (self.weapon == 3)
  685.     {
  686.         if (other.ammo_rockets >= 100)
  687.             return;
  688.         other.ammo_rockets = other.ammo_rockets + self.aflag;
  689.     }
  690.  
  691. //    cells
  692.     if (self.weapon == 4)
  693.     {
  694.         if (other.ammo_cells >= 100)
  695.             return;
  696.         other.ammo_cells = other.ammo_cells + self.aflag;
  697.     }
  698.  
  699.     bound_other_ammo ();
  700.     
  701.     // ammo touch sound CTFBOT moved from below
  702.     sound (other, CHAN_ITEM, "weapons/lock4.wav", 1, ATTN_NORM);
  703.  
  704.     if (other.classname == "player")        // CTFBOT
  705.     {                            // CTFBOT
  706.  
  707. //ZOID--remove unnessary msgs
  708.     if (!deathmatch) {
  709.         sprint (other, "You got the ");
  710.         sprint (other, self.netname);
  711.         sprint (other, "\n");
  712.     }
  713.     stuffcmd (other, "bf\n");
  714.     }        // CTFBOT
  715.  
  716. // change to a better weapon if appropriate
  717.  
  718.     if ( other.weapon == best )
  719.     {
  720.         stemp = self;
  721.         self = other;
  722.         self.weapon = W_BestWeapon();
  723.         W_SetCurrentAmmo ();
  724.         self = stemp;
  725.     }
  726.  
  727. // if changed current ammo, update it
  728.     stemp = self;
  729.     self = other;
  730.     W_SetCurrentAmmo();
  731.     self = stemp;
  732.  
  733. // remove it in single player, or setup for respawning in deathmatch
  734.     self.model = string_null;
  735.     self.solid = SOLID_NOT;
  736.     if (deathmatch == 1 || deathmatch == 3)
  737.         self.nextthink = time + 30;
  738.     self.think = SUB_regen;
  739.  
  740.     activator = other;
  741.     SUB_UseTargets();                // fire all targets / killtargets
  742. };
  743.  
  744.  
  745.  
  746.  
  747. float WEAPON_BIG2 = 1;
  748.  
  749. /*QUAKED item_shells (0 .5 .8) (0 0 0) (32 32 32) big
  750. */
  751.  
  752. void() item_shells =
  753. {
  754.     self.touch = ammo_touch;
  755.  
  756.     if (self.spawnflags & WEAPON_BIG2)
  757.     {
  758.         precache_model ("maps/b_shell1.bsp");
  759.         setmodel (self, "maps/b_shell1.bsp");
  760.         self.aflag = 40;
  761.     }
  762.     else
  763.     {
  764.         precache_model ("maps/b_shell0.bsp");
  765.         setmodel (self, "maps/b_shell0.bsp");
  766.         self.aflag = 20;
  767.     }
  768.     self.weapon = 1;
  769.     self.netname = "shells";
  770.     setsize (self, '0 0 0', '32 32 56');
  771.     StartItem ();
  772. };
  773.  
  774. /*QUAKED item_spikes (0 .5 .8) (0 0 0) (32 32 32) big
  775. */
  776.  
  777. void() item_spikes =
  778. {
  779.     self.touch = ammo_touch;
  780.  
  781.     if (self.spawnflags & WEAPON_BIG2)
  782.     {
  783.         precache_model ("maps/b_nail1.bsp");
  784.         setmodel (self, "maps/b_nail1.bsp");
  785.         self.aflag = 50;
  786.     }
  787.     else
  788.     {
  789.         precache_model ("maps/b_nail0.bsp");
  790.         setmodel (self, "maps/b_nail0.bsp");
  791.         self.aflag = 25;
  792.     }
  793.     self.weapon = 2;
  794.     self.netname = "nails";
  795.     setsize (self, '0 0 0', '32 32 56');
  796.     StartItem ();
  797. };
  798.  
  799. /*QUAKED item_rockets (0 .5 .8) (0 0 0) (32 32 32) big
  800. */
  801.  
  802. void() item_rockets =
  803. {
  804.     self.touch = ammo_touch;
  805.  
  806.     if (self.spawnflags & WEAPON_BIG2)
  807.     {
  808.         precache_model ("maps/b_rock1.bsp");
  809.         setmodel (self, "maps/b_rock1.bsp");
  810.         self.aflag = 10;
  811.     }
  812.     else
  813.     {
  814.         precache_model ("maps/b_rock0.bsp");
  815.         setmodel (self, "maps/b_rock0.bsp");
  816.         self.aflag = 5;
  817.     }
  818.     self.weapon = 3;
  819.     self.netname = "rockets";
  820.     setsize (self, '0 0 0', '32 32 56');
  821.     StartItem ();
  822. };
  823.  
  824.  
  825. /*QUAKED item_cells (0 .5 .8) (0 0 0) (32 32 32) big
  826. */
  827.  
  828. void() item_cells =
  829. {
  830.     self.touch = ammo_touch;
  831.  
  832.     if (self.spawnflags & WEAPON_BIG2)
  833.     {
  834.         precache_model ("maps/b_batt1.bsp");
  835.         setmodel (self, "maps/b_batt1.bsp");
  836.         self.aflag = 12;
  837.     }
  838.     else
  839.     {
  840.         precache_model ("maps/b_batt0.bsp");
  841.         setmodel (self, "maps/b_batt0.bsp");
  842.         self.aflag = 6;
  843.     }
  844.     self.weapon = 4;
  845.     self.netname = "cells";
  846.     setsize (self, '0 0 0', '32 32 56');
  847.     StartItem ();
  848. };
  849.  
  850.  
  851. /*QUAKED item_weapon (0 .5 .8) (0 0 0) (32 32 32) shotgun rocket spikes big
  852. DO NOT USE THIS!!!! IT WILL BE REMOVED!
  853. */
  854.  
  855. float WEAPON_SHOTGUN = 1;
  856. float WEAPON_ROCKET = 2;
  857. float WEAPON_SPIKES = 4;
  858. float WEAPON_BIG = 8;
  859. void() item_weapon =
  860. {
  861.     self.touch = ammo_touch;
  862.  
  863.     if (self.spawnflags & WEAPON_SHOTGUN)
  864.     {
  865.         if (self.spawnflags & WEAPON_BIG)
  866.         {
  867.             precache_model ("maps/b_shell1.bsp");
  868.             setmodel (self, "maps/b_shell1.bsp");
  869.             self.aflag = 40;
  870.         }
  871.         else
  872.         {
  873.             precache_model ("maps/b_shell0.bsp");
  874.             setmodel (self, "maps/b_shell0.bsp");
  875.             self.aflag = 20;
  876.         }
  877.         self.weapon = 1;
  878.         self.netname = "shells";
  879.     }
  880.  
  881.     if (self.spawnflags & WEAPON_SPIKES)
  882.     {
  883.         if (self.spawnflags & WEAPON_BIG)
  884.         {
  885.             precache_model ("maps/b_nail1.bsp");
  886.             setmodel (self, "maps/b_nail1.bsp");
  887.             self.aflag = 40;
  888.         }
  889.         else
  890.         {
  891.             precache_model ("maps/b_nail0.bsp");
  892.             setmodel (self, "maps/b_nail0.bsp");
  893.             self.aflag = 20;
  894.         }
  895.         self.weapon = 2;
  896.         self.netname = "spikes";
  897.     }
  898.  
  899.     if (self.spawnflags & WEAPON_ROCKET)
  900.     {
  901.         if (self.spawnflags & WEAPON_BIG)
  902.         {
  903.             precache_model ("maps/b_rock1.bsp");
  904.             setmodel (self, "maps/b_rock1.bsp");
  905.             self.aflag = 10;
  906.         }
  907.         else
  908.         {
  909.             precache_model ("maps/b_rock0.bsp");
  910.             setmodel (self, "maps/b_rock0.bsp");
  911.             self.aflag = 5;
  912.         }
  913.         self.weapon = 3;
  914.         self.netname = "rockets";
  915.     }
  916.     
  917.     setsize (self, '0 0 0', '32 32 56');
  918.     StartItem ();
  919. };
  920.  
  921.  
  922. /*
  923. ===============================================================================
  924.  
  925. KEYS
  926.  
  927. ===============================================================================
  928. */
  929.  
  930. void() key_touch =
  931. {
  932. local entity    stemp;
  933. local float        best;
  934.  
  935.     if (other.classname != "player")
  936.         return;
  937.     if (other.health <= 0)
  938.         return;
  939.     if (other.items & self.items)
  940.         return;
  941.  
  942.     sprint (other, "You got the ");
  943.     sprint (other, self.netname);
  944.     sprint (other,"\n");
  945.  
  946.     sound (other, CHAN_ITEM, self.noise, 1, ATTN_NORM);
  947.     stuffcmd (other, "bf\n");
  948.     other.items = other.items | self.items;
  949.  
  950.     if (!coop)
  951.     {    
  952.         self.solid = SOLID_NOT;
  953.         self.model = string_null;
  954.     }
  955.  
  956.     activator = other;
  957.     SUB_UseTargets();                // fire all targets / killtargets
  958. };
  959.  
  960.  
  961. void() key_setsounds =
  962. {
  963.     if (world.worldtype == 0)
  964.     {
  965.         precache_sound ("misc/medkey.wav");
  966.         self.noise = "misc/medkey.wav";
  967.     }
  968.     if (world.worldtype == 1)
  969.     {
  970.         precache_sound ("misc/runekey.wav");
  971.         self.noise = "misc/runekey.wav";
  972.     }
  973.     if (world.worldtype == 2)
  974.     {
  975.         precache_sound2 ("misc/basekey.wav");
  976.         self.noise = "misc/basekey.wav";
  977.     }
  978. };
  979.  
  980. /*QUAKED item_key1 (0 .5 .8) (-16 -16 -24) (16 16 32)
  981. SILVER key
  982. In order for keys to work
  983. you MUST set your maps
  984. worldtype to one of the
  985. following:
  986. 0: medieval
  987. 1: metal
  988. 2: base
  989. */
  990.  
  991. void() item_key1 =
  992. {
  993.     if (world.worldtype == 0)
  994.     {
  995.         precache_model ("progs/w_s_key.mdl");
  996.         setmodel (self, "progs/w_s_key.mdl");
  997.         self.netname = "silver key";
  998.     }
  999.     else if (world.worldtype == 1)
  1000.     {
  1001.         precache_model ("progs/m_s_key.mdl");
  1002.         setmodel (self, "progs/m_s_key.mdl");
  1003.         self.netname = "silver runekey";
  1004.     }
  1005.     else if (world.worldtype == 2)
  1006.     {
  1007.         precache_model2 ("progs/b_s_key.mdl");
  1008.         setmodel (self, "progs/b_s_key.mdl");
  1009.         self.netname = "silver keycard";
  1010.     }
  1011.     key_setsounds();
  1012.     self.touch = key_touch;
  1013.     self.items = IT_KEY1;
  1014.     setsize (self, '-16 -16 -24', '16 16 32');
  1015.     StartItem ();
  1016. };
  1017.  
  1018. /*QUAKED item_key2 (0 .5 .8) (-16 -16 -24) (16 16 32)
  1019. GOLD key
  1020. In order for keys to work
  1021. you MUST set your maps
  1022. worldtype to one of the
  1023. following:
  1024. 0: medieval
  1025. 1: metal
  1026. 2: base
  1027. */
  1028.  
  1029. void() item_key2 =
  1030. {
  1031.     if (world.worldtype == 0)
  1032.     {
  1033.         precache_model ("progs/w_g_key.mdl");
  1034.         setmodel (self, "progs/w_g_key.mdl");
  1035.         self.netname = "gold key";
  1036.     }
  1037.     if (world.worldtype == 1)
  1038.     {
  1039.         precache_model ("progs/m_g_key.mdl");
  1040.         setmodel (self, "progs/m_g_key.mdl");
  1041.         self.netname = "gold runekey";
  1042.     }
  1043.     if (world.worldtype == 2)
  1044.     {
  1045.         precache_model2 ("progs/b_g_key.mdl");
  1046.         setmodel (self, "progs/b_g_key.mdl");
  1047.         self.netname = "gold keycard";
  1048.     }
  1049.     key_setsounds();
  1050.     self.touch = key_touch;
  1051.     self.items = IT_KEY2;
  1052.     setsize (self, '-16 -16 -24', '16 16 32');
  1053.     StartItem ();
  1054. };
  1055.  
  1056.  
  1057.  
  1058. /*
  1059. ===============================================================================
  1060.  
  1061. END OF LEVEL RUNES
  1062.  
  1063. ===============================================================================
  1064. */
  1065.  
  1066. void() sigil_touch =
  1067. {
  1068. local entity    stemp;
  1069. local float        best;
  1070.  
  1071.     if (other.classname != "player")
  1072.         return;
  1073.     if (other.health <= 0)
  1074.         return;
  1075.  
  1076.     centerprint (other, "You got the rune!");
  1077.  
  1078.     sound (other, CHAN_ITEM, self.noise, 1, ATTN_NORM);
  1079.     stuffcmd (other, "bf\n");
  1080.     self.solid = SOLID_NOT;
  1081.     self.model = string_null;
  1082.     serverflags = serverflags | (self.spawnflags & 15);
  1083.     self.classname = "";        // so rune doors won't find it
  1084.     
  1085.     activator = other;
  1086.     SUB_UseTargets();                // fire all targets / killtargets
  1087. };
  1088.  
  1089.  
  1090. /*QUAKED item_sigil (0 .5 .8) (-16 -16 -24) (16 16 32) E1 E2 E3 E4
  1091. End of level sigil, pick up to end episode and return to jrstart.
  1092. */
  1093.  
  1094. void() item_sigil =
  1095. {
  1096.     if (!self.spawnflags)
  1097.         objerror ("no spawnflags");
  1098.  
  1099.     precache_sound ("misc/runekey.wav");
  1100.     self.noise = "misc/runekey.wav";
  1101.  
  1102.     if (self.spawnflags & 1)
  1103.     {
  1104.         precache_model ("progs/end1.mdl");
  1105.         setmodel (self, "progs/end1.mdl");
  1106.     }
  1107.     if (self.spawnflags & 2)
  1108.     {
  1109.         precache_model2 ("progs/end2.mdl");
  1110.         setmodel (self, "progs/end2.mdl");
  1111.     }
  1112.     if (self.spawnflags & 4)
  1113.     {
  1114.         precache_model2 ("progs/end3.mdl");
  1115.         setmodel (self, "progs/end3.mdl");
  1116.     }
  1117.     if (self.spawnflags & 8)
  1118.     {
  1119.         precache_model2 ("progs/end4.mdl");
  1120.         setmodel (self, "progs/end4.mdl");
  1121.     }
  1122.     
  1123.     self.touch = sigil_touch;
  1124.     setsize (self, '-16 -16 -24', '16 16 32');
  1125.     StartItem ();
  1126. };
  1127.  
  1128. /*
  1129. ===============================================================================
  1130.  
  1131. POWERUPS
  1132.  
  1133. ===============================================================================
  1134. */
  1135.  
  1136. void() powerup_touch;
  1137.  
  1138.  
  1139. void() powerup_touch =
  1140. {
  1141. local entity    stemp;
  1142. local float        best;
  1143.  
  1144.     if (other.classname != "player" && other.classname != "bot")        // CTFBOT
  1145.         return;
  1146.     if (other.health <= 0)
  1147.         return;
  1148.  
  1149.     if (other.classname == "player")    // CTFBOT
  1150.     {
  1151.         sprint (other, "You got the ");
  1152.         sprint (other, self.netname);
  1153.         sprint (other,"\n");
  1154.         stuffcmd (other, "bf\n");        // CTFBOT moved from below
  1155.     }
  1156.  
  1157.     if (deathmatch)
  1158.     {
  1159.         self.mdl = self.model;
  1160.         
  1161.         if ((self.classname == "item_artifact_invulnerability") ||
  1162.             (self.classname == "item_artifact_invisibility"))
  1163.             self.nextthink = time + 60*5;
  1164.         else
  1165.             self.nextthink = time + 60;
  1166.         
  1167.         self.think = SUB_regen;
  1168.     }    
  1169.  
  1170.     sound (other, CHAN_VOICE, self.noise, 1, ATTN_NORM);
  1171.     self.solid = SOLID_NOT;
  1172.     other.items = other.items | self.items;
  1173.     self.model = string_null;
  1174.  
  1175. // do the apropriate action
  1176.     if (self.classname == "item_artifact_envirosuit")
  1177.     {
  1178.         other.rad_time = 1;
  1179.         other.radsuit_finished = time + 30;
  1180.     }
  1181.     
  1182.     if (self.classname == "item_artifact_invulnerability")
  1183.     {
  1184.         other.invincible_time = 1;
  1185.         other.invincible_finished = time + 30;
  1186.     }
  1187.     
  1188.     if (self.classname == "item_artifact_invisibility")
  1189.     {
  1190.         other.invisible_time = 1;
  1191.         other.invisible_finished = time + 30;
  1192.     }
  1193.  
  1194.     if (self.classname == "item_artifact_super_damage")
  1195.     {
  1196.         other.super_time = 1;
  1197.         other.super_damage_finished = time + 30;
  1198.     }    
  1199.  
  1200.     activator = other;
  1201.     SUB_UseTargets();                // fire all targets / killtargets
  1202. };
  1203.  
  1204.  
  1205.  
  1206. /*QUAKED item_artifact_invulnerability (0 .5 .8) (-16 -16 -24) (16 16 32)
  1207. Player is invulnerable for 30 seconds
  1208. */
  1209. void() item_artifact_invulnerability =
  1210. {
  1211.     self.touch = powerup_touch;
  1212.  
  1213.     precache_model ("progs/invulner.mdl");
  1214.     precache_sound ("items/protect.wav");
  1215.     precache_sound ("items/protect2.wav");
  1216.     precache_sound ("items/protect3.wav");
  1217.     self.noise = "items/protect.wav";
  1218.     setmodel (self, "progs/invulner.mdl");
  1219.     self.netname = "Pentagram of Protection";
  1220.     self.items = IT_INVULNERABILITY;
  1221.     setsize (self, '-16 -16 -24', '16 16 32');
  1222.     StartItem ();
  1223. };
  1224.  
  1225. /*QUAKED item_artifact_envirosuit (0 .5 .8) (-16 -16 -24) (16 16 32)
  1226. Player takes no damage from water or slime for 30 seconds
  1227. */
  1228. void() item_artifact_envirosuit =
  1229. {
  1230.     self.touch = powerup_touch;
  1231.  
  1232.     precache_model ("progs/suit.mdl");
  1233.     precache_sound ("items/suit.wav");
  1234.     precache_sound ("items/suit2.wav");
  1235.     self.noise = "items/suit.wav";
  1236.     setmodel (self, "progs/suit.mdl");
  1237.     self.netname = "Biosuit";
  1238.     self.items = IT_SUIT;
  1239.     setsize (self, '-16 -16 -24', '16 16 32');
  1240.     StartItem ();
  1241. };
  1242.  
  1243.  
  1244. /*QUAKED item_artifact_invisibility (0 .5 .8) (-16 -16 -24) (16 16 32)
  1245. Player is invisible for 30 seconds
  1246. */
  1247. void() item_artifact_invisibility =
  1248. {
  1249.     self.touch = powerup_touch;
  1250.  
  1251.     precache_model ("progs/invisibl.mdl");
  1252.     precache_sound ("items/inv1.wav");
  1253.     precache_sound ("items/inv2.wav");
  1254.     precache_sound ("items/inv3.wav");
  1255.     self.noise = "items/inv1.wav";
  1256.     setmodel (self, "progs/invisibl.mdl");
  1257.     self.netname = "Ring of Shadows";
  1258.     self.items = IT_INVISIBILITY;
  1259.     setsize (self, '-16 -16 -24', '16 16 32');
  1260.     StartItem ();
  1261. };
  1262.  
  1263.  
  1264. /*QUAKED item_artifact_super_damage (0 .5 .8) (-16 -16 -24) (16 16 32)
  1265. The next attack from the player will do 4x damage
  1266. */
  1267. void() item_artifact_super_damage =
  1268. {
  1269.     self.touch = powerup_touch;
  1270.  
  1271.     precache_model ("progs/quaddama.mdl");
  1272.     precache_sound ("items/damage.wav");
  1273.     precache_sound ("items/damage2.wav");
  1274.     precache_sound ("items/damage3.wav");
  1275.     self.noise = "items/damage.wav";
  1276.     setmodel (self, "progs/quaddama.mdl");
  1277.     self.netname = "Quad Damage";
  1278.     self.items = IT_QUAD;
  1279.     setsize (self, '-16 -16 -24', '16 16 32');
  1280.     StartItem ();
  1281. };
  1282.  
  1283.  
  1284.  
  1285. /*
  1286. ===============================================================================
  1287.  
  1288. PLAYER BACKPACKS
  1289.  
  1290. ===============================================================================
  1291. */
  1292.  
  1293. void() BackpackTouch =
  1294. {
  1295.     local string    s;
  1296.     local    float    best, old, new;
  1297.     local float bbest;        // CTFBOT
  1298.     local        entity    stemp;
  1299.     local    float    acount;
  1300.     
  1301.     if (other.classname != "player" && other.classname != "bot")    // CTFBOT
  1302.         return;
  1303.     if (other.health <= 0)
  1304.         return;
  1305.     //don't let self pick it up for a sec
  1306.     if ((other == self.owner) && ( (self.nextthink - time) > 118 ) )
  1307.         return;
  1308.  
  1309.     acount = 0;
  1310.     if (other.classname == "player")        // CTFBOT
  1311.         sprint (other, "You get ");
  1312.  
  1313.     /* CTFBOT changed "You get the backpack, 23 shells..." to "You get 23 shells..."
  1314.     if (self.items)
  1315.         if ((other.items & self.items) == 0)
  1316.         {
  1317.             acount = 1;
  1318.             if (other.classname == "player")        // CTFBOT
  1319.                 sprint (other, "the ");
  1320.             if (other.classname == "player")        // CTFBOT
  1321.                 sprint (other, self.netname);
  1322.         }
  1323.     */ // CTFBOT
  1324.     
  1325. // if the player was using his best weapon, change up to the new one if better        
  1326.     stemp = self;
  1327.     self = other;
  1328.     best = W_BestWeapon();
  1329.     self = stemp;
  1330.  
  1331. // change weapons
  1332.     other.ammo_shells = other.ammo_shells + self.ammo_shells;
  1333.     other.ammo_nails = other.ammo_nails + self.ammo_nails;
  1334.     other.ammo_rockets = other.ammo_rockets + self.ammo_rockets;
  1335.     other.ammo_cells = other.ammo_cells + self.ammo_cells;
  1336.  
  1337.     new = self.items;
  1338.     if (!new)
  1339.         new = other.weapon;
  1340.     old = other.items;
  1341.     other.items = other.items | new;
  1342.     
  1343.     bound_other_ammo ();
  1344.  
  1345.     if (other.classname == "player")    // CTFBOT
  1346.     {                        // CTFBOT
  1347.  
  1348.     if (self.ammo_shells)
  1349.     {
  1350.         if (acount)
  1351.             sprint(other, ", ");
  1352.         acount = 1;
  1353.         s = ftos(self.ammo_shells);
  1354.         sprint (other, s);
  1355.         sprint (other, " shells");
  1356.     }
  1357.     if (self.ammo_nails)
  1358.     {
  1359.         if (acount)
  1360.             sprint(other, ", ");
  1361.         acount = 1;
  1362.         s = ftos(self.ammo_nails);
  1363.         sprint (other, s);
  1364.         sprint (other, " nails");
  1365.     }
  1366.     if (self.ammo_rockets)
  1367.     {
  1368.         if (acount)
  1369.             sprint(other, ", ");
  1370.         acount = 1;
  1371.         s = ftos(self.ammo_rockets);
  1372.         sprint (other, s);
  1373.         sprint (other, " rockets");
  1374.     }
  1375.     if (self.ammo_cells)
  1376.     {
  1377.         if (acount)
  1378.             sprint(other, ", ");
  1379.         acount = 1;
  1380.         s = ftos(self.ammo_cells);
  1381.         sprint (other, s);
  1382.         sprint (other, " cells");
  1383.     }
  1384.     
  1385.     sprint (other, "\n");
  1386.     stuffcmd (other, "bf\n");
  1387.     }        // CTFBOT
  1388.  
  1389.     // backpack touch sound CTFBOT moved
  1390.     sound (other, CHAN_ITEM, "weapons/lock4.wav", 1, ATTN_NORM);
  1391.  
  1392. // remove the backpack, change self to the player
  1393.     remove(self);
  1394.     self = other;
  1395.  
  1396. // change to the weapon
  1397.     if (!deathmatch)
  1398.         self.weapon = new;
  1399.     else
  1400.         Deathmatch_Weapon (old, new);
  1401.  
  1402.     W_SetCurrentAmmo ();
  1403. };
  1404.  
  1405. /*
  1406. ===============
  1407. DropBackpack
  1408. ===============
  1409. */
  1410. void() DropBackpack =
  1411. {
  1412.     local entity    item;
  1413.  
  1414.     if (!(self.ammo_shells + self.ammo_nails + self.ammo_rockets + self.ammo_cells))
  1415.         return;    // nothing in it
  1416.  
  1417.     item = spawn();
  1418.     item.origin = self.origin - '0 0 24';
  1419.  
  1420.     item.items = 0; // none by default
  1421.  
  1422. //ZOID--axe and hook don't go into backpack
  1423.     if (self.weapon != IT_HOOK || self.weapon != IT_AXE)
  1424.         item.items = self.weapon;
  1425.  
  1426.     if (item.items == IT_SHOTGUN)
  1427.         item.netname = "Shotgun";
  1428.     else if (item.items == IT_SUPER_SHOTGUN)
  1429.         item.netname = "Double-barrelled Shotgun";
  1430.     else if (item.items == IT_NAILGUN)
  1431.         item.netname = "Nailgun";
  1432.     else if (item.items == IT_SUPER_NAILGUN)
  1433.         item.netname = "Super Nailgun";
  1434.     else if (item.items == IT_GRENADE_LAUNCHER)
  1435.         item.netname = "Grenade Launcher";
  1436.     else if (item.items == IT_ROCKET_LAUNCHER)
  1437.         item.netname = "Rocket Launcher";
  1438.     else if (item.items == IT_LIGHTNING)
  1439.         item.netname = "Thunderbolt";
  1440.     else
  1441.         item.netname = "";
  1442.  
  1443.     item.ammo_shells = self.ammo_shells;
  1444.     item.ammo_nails = self.ammo_nails;
  1445.     item.ammo_rockets = self.ammo_rockets;
  1446.     item.ammo_cells = self.ammo_cells;
  1447.  
  1448.     item.velocity_z = 300;
  1449.     item.velocity_x = -100 + (random() * 200);
  1450.     item.velocity_y = -100 + (random() * 200);
  1451.     
  1452.     item.flags = FL_ITEM;
  1453.     item.solid = SOLID_TRIGGER;
  1454.     item.movetype = MOVETYPE_TOSS;
  1455.     setmodel (item, "progs/backpack.mdl");
  1456.     setsize (item, '-16 -16 0', '16 16 56');
  1457.     item.touch = BackpackTouch;
  1458.     
  1459.     item.nextthink = time + 120;    // remove after 2 minutes
  1460.     item.think = SUB_Remove;
  1461.     
  1462.     item.bot_wants_item = TRUE;        // CTFBOT optimization
  1463.  
  1464.     item.classname = "backpack";    // CTFBOT give backpacks a class name
  1465.                                     // CTFBOT so bots can see them
  1466.  
  1467.     item.netname = "backpack";    // CTFBOT give backpacks a net name
  1468.                                 // CTFBOT for better debug messages
  1469. };
  1470.  
  1471. /*----------------------------------------------------------------------
  1472.   The Rune Game modes
  1473.  
  1474.   Rune 1 - Earth Magic
  1475.       resistance
  1476.   Rune 2 - Black Magic
  1477.       strength
  1478.   Rune 3 - Hell Magic
  1479.       haste
  1480.   Rune 4 - Elder Magic
  1481.       regeneration
  1482.  
  1483.  ----------------------------------------------------------------------*/
  1484.  
  1485. entity() SelectRuneSpawnPoint =
  1486. {
  1487.     runespawn = find(runespawn, classname, "info_player_deathmatch");
  1488.     if (runespawn == world)
  1489.         runespawn = find (runespawn, classname, "info_player_deathmatch");
  1490.     if (runespawn == world)
  1491.         error("no info_player_deathmatch to spawn rune");
  1492.     return runespawn;
  1493. };
  1494.  
  1495. void() RuneTouch =
  1496. {
  1497.     local string    s;
  1498.     local    float    best;
  1499.     local        entity    stemp;
  1500.     
  1501.     if (other.classname != "player" && other.classname != "bot")   // CTFBOT
  1502.         return;
  1503.     if (other.health <= 0)
  1504.         return;
  1505.         
  1506.     // CTFBOT EXTRAS [[[
  1507.     if ((time < (other.rune_drop_time + 2)) && (other.last_rune == self.player_flag))
  1508.         return;
  1509.     // CTFBOT EXTRAS ]]]
  1510.         
  1511.     if (other.player_flag & ITEM_RUNE_MASK) {
  1512.         if (other.classname == "player")    // CTFBOT
  1513.         {
  1514.             if (other.rune_notice_time < time) 
  1515.             {
  1516.                 // CTFBOT EXTRAS [[[
  1517.                 if (other.player_flag & ITEM_RUNE1_FLAG) {
  1518.                     sprint(other, "You already have ┼ß≥⌠Φ ═ßτΘπ!\n");
  1519.                 }
  1520.                 else if (other.player_flag & ITEM_RUNE2_FLAG) {
  1521.                     sprint(other, "You already have ┬∞ßπδ ═ßτΘπ!\n");
  1522.                 }
  1523.                 else if (other.player_flag & ITEM_RUNE3_FLAG) {
  1524.                     sprint(other, "You already have ╚σ∞∞ ═ßτΘπ!\n");
  1525.                 }
  1526.                 else if (other.player_flag & ITEM_RUNE4_FLAG) {
  1527.                     sprint(other, "You already have ┼∞Σσ≥ ═ßτΘπ!\n");
  1528.                 }
  1529.  
  1530.                 sprint(other, "Use impulse 40 to drop your rune\n");
  1531.  
  1532.                 // CTFBOT EXTRAS ]]]
  1533.  
  1534.                 other.rune_notice_time = time + 5;
  1535.             }
  1536.         }
  1537.         return; // one per customer
  1538.     }
  1539.         
  1540.     other.player_flag = other.player_flag | self.player_flag;
  1541.  
  1542.     // backpack touch sound    CTFBOT moved from below
  1543.     sound (other, CHAN_ITEM, "weapons/lock4.wav", 1, ATTN_NORM);
  1544.  
  1545.     
  1546.  
  1547.     // CTFBOT [[[
  1548.  
  1549.     if (other.classname == "bot")
  1550.     {
  1551.         if (bot_debug >= 1)
  1552.         {
  1553.             dprint(other.netname);
  1554.             dprint(" got a rune\n");
  1555.         }
  1556.         remove(self);
  1557.         return;
  1558.     }    
  1559.     // CTFBOT ]]]
  1560.  
  1561.  
  1562.     // notification of rune, no nofity in team mode
  1563.     if (self.player_flag & ITEM_RUNE1_FLAG) {
  1564.         if (teamplay == 0) {
  1565.             bprint(other.netname);
  1566.             bprint(" got the rune of ┼ß≥⌠Φ ═ßτΘπ!\n");
  1567.         }
  1568.         // CTFBOT EXTRAS [[[
  1569.         else {
  1570.             sprint(other, "You got the rune of ┼ß≥⌠Φ ═ßτΘπ!\n");//, ╥σ≤Θ≤⌠ßεπσ!\n");
  1571.         }
  1572.         // CTFBOT EXTRAS ]]]
  1573.         centerprint(other, "┼ß≥⌠Φ ═ßτΘπ!\n\n╥σ≤Θ≤⌠ßεπσ");
  1574.     }
  1575.     if (self.player_flag & ITEM_RUNE2_FLAG) {
  1576.         if (teamplay == 0) {
  1577.             bprint(other.netname);
  1578.             bprint(" got the rune of ┬∞ßπδ ═ßτΘπ!\n");
  1579.         }
  1580.         // CTFBOT EXTRAS [[[
  1581.         else {
  1582.             sprint(other, "You got the rune of ┬∞ßπδ ═ßτΘπ!\n");//, ╙⌠≥σετ⌠Φ!\n");
  1583.         }
  1584.         // CTFBOT EXTRAS ]]]
  1585.         centerprint(other, "┬∞ßπδ ═ßτΘπ!\n\n╙⌠≥σετ⌠Φ");
  1586.     }
  1587.     if (self.player_flag & ITEM_RUNE3_FLAG) {
  1588.         if (teamplay == 0) {
  1589.             bprint(other.netname);
  1590.             bprint(" got the rune of ╚σ∞∞ ═ßτΘπ!\n");
  1591.         }
  1592.         // CTFBOT EXTRAS [[[
  1593.         else {
  1594.             sprint(other, "You got the rune of ╚σ∞∞ ═ßτΘπ!\n");//, ╚ß≤⌠σ!\n");
  1595.         }
  1596.         // CTFBOT EXTRAS ]]]
  1597.         centerprint(other, "╚σ∞∞ ═ßτΘπ!\n\n╚ß≤⌠σ");
  1598.     }
  1599.     if (self.player_flag & ITEM_RUNE4_FLAG) {
  1600.         if (teamplay == 0) {
  1601.             bprint(other.netname);
  1602.             bprint(" got the rune of ┼∞Σσ≥ ═ßτΘπ!\n");
  1603.         }
  1604.         // CTFBOT EXTRAS [[[
  1605.         else {
  1606.             sprint(other, "You got the rune of ┼∞Σσ≥ ═ßτΘπ!\n");//, ╥στσεσ≥ß⌠Θ∩ε!\n");
  1607.         }
  1608.         // CTFBOT EXTRAS ]]]
  1609.         centerprint(other, "┼∞Σσ≥ ═ßτΘπ!\n\n╥στσεσ≥ß⌠Θ∩ε");
  1610.     }
  1611.     
  1612.     stuffcmd (other, "bf\n");
  1613.  
  1614.     remove(self);
  1615. };
  1616.  
  1617. entity (float flag) Do_DropRune;        // CTFBOT
  1618.  
  1619. void() RuneRespawn =
  1620. {
  1621.     local entity oself;
  1622.  
  1623.     oself = self;
  1624.  
  1625.     // choose random starting points
  1626.     self = SelectRuneSpawnPoint();
  1627.     Do_DropRune(oself.player_flag);
  1628.  
  1629.     remove(oself);
  1630. };
  1631.  
  1632. entity (float flag) Do_DropRune =     // CTFBOT
  1633. {
  1634.     local entity    item;
  1635.  
  1636.     item = spawn();
  1637.     item.origin = self.origin - '0 0 24';
  1638.     
  1639.     item.player_flag = flag;
  1640.  
  1641.     item.velocity_z = 400;
  1642.     item.velocity_x = -500 + (random() * 1000);
  1643.     item.velocity_y = -500 + (random() * 1000);
  1644.     
  1645.     item.bot_wants_item = TRUE;        // CTFBOT optimization
  1646.     
  1647.     item.flags = FL_ITEM;
  1648.     item.solid = SOLID_TRIGGER;
  1649.     item.movetype = MOVETYPE_TOSS;
  1650.     if (flag & ITEM_RUNE1_FLAG)
  1651.         setmodel (item, "progs/end1.mdl");
  1652.     else if (flag & ITEM_RUNE2_FLAG)
  1653.         setmodel (item, "progs/end2.mdl");
  1654.     else if (flag & ITEM_RUNE3_FLAG)
  1655.         setmodel (item, "progs/end3.mdl");
  1656.     else if (flag & ITEM_RUNE4_FLAG)
  1657.         setmodel (item, "progs/end4.mdl");
  1658.     setsize (item, '-16 -16 0', '16 16 56');
  1659.  
  1660.     item.touch = RuneTouch;
  1661.  
  1662.     item.nextthink = time + 120; /* if no one touches it in two minutes,
  1663.         respawn it somewhere else, so inaccessible ones will come 'back' */
  1664.     item.think = RuneRespawn;
  1665.     
  1666.     // CTFBOT [[[ let bots know what runes are
  1667.     if (flag & ITEM_RUNE1_FLAG)
  1668.     {
  1669.         item.classname = "item_rune1";
  1670.         item.netname = "Resistance";
  1671.     }
  1672.     else if (flag & ITEM_RUNE2_FLAG)
  1673.     {
  1674.         item.classname = "item_rune2";
  1675.         item.netname = "Strength";
  1676.     }
  1677.     else if (flag & ITEM_RUNE3_FLAG)
  1678.     {
  1679.         item.classname = "item_rune3";
  1680.         item.netname = "Haste";
  1681.     }
  1682.     else if (flag & ITEM_RUNE4_FLAG)
  1683.     {
  1684.         item.classname = "item_rune4";
  1685.         item.netname = "Regeneration";
  1686.     }
  1687.     
  1688.     return item;
  1689.     // CTFBOT ]]]
  1690. };
  1691.  
  1692. /*
  1693. ===============
  1694. Droprune
  1695. self is player
  1696. ===============
  1697. */
  1698. void() DropRune =
  1699. {
  1700.     if (self.player_flag & ITEM_RUNE1_FLAG)
  1701.         Do_DropRune(ITEM_RUNE1_FLAG);
  1702.     if (self.player_flag & ITEM_RUNE2_FLAG)
  1703.         Do_DropRune(ITEM_RUNE2_FLAG);
  1704.     if (self.player_flag & ITEM_RUNE3_FLAG)
  1705.         Do_DropRune(ITEM_RUNE3_FLAG);
  1706.     if (self.player_flag & ITEM_RUNE4_FLAG)
  1707.         Do_DropRune(ITEM_RUNE4_FLAG);
  1708.     self.player_flag = self.player_flag - (self.player_flag & ITEM_RUNE_MASK);
  1709. };
  1710.  
  1711. /*
  1712. ================
  1713. SpawnRunes
  1714. spawn all the runes
  1715. self is the entity that was created for us, we remove it
  1716. ================
  1717. */
  1718. void() SpawnRunes =
  1719. {
  1720.     local entity oself;
  1721.     local float i;
  1722.  
  1723.     if (runespawned) {
  1724.         remove(self);
  1725.         return;
  1726.     }
  1727.  
  1728.     oself = self;
  1729.  
  1730.     // choose random starting points
  1731.     i = random() * 10;
  1732.     while (i > 0) {
  1733.         self = SelectRuneSpawnPoint();
  1734.         i = i - 1;
  1735.     }
  1736.  
  1737.     self = SelectRuneSpawnPoint();
  1738.     Do_DropRune(ITEM_RUNE1_FLAG);
  1739.     self = SelectRuneSpawnPoint();
  1740.     Do_DropRune(ITEM_RUNE2_FLAG);
  1741.     self = SelectRuneSpawnPoint();
  1742.     Do_DropRune(ITEM_RUNE3_FLAG);
  1743.     self = SelectRuneSpawnPoint();
  1744.     Do_DropRune(ITEM_RUNE4_FLAG);
  1745.  
  1746.     runespawned = 1;
  1747.  
  1748.     remove(oself);        // temp entity that was created to spawn the runes
  1749. };
  1750.