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