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

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