home *** CD-ROM | disk | FTP | other *** search
/ Quake 'em / QUAKEEM.BIN / quake / programs / jteam092 / teamplay.qc < prev    next >
Encoding:
Text File  |  1996-08-17  |  19.7 KB  |  783 lines

  1. /* teamplay.qc
  2.  
  3.    From
  4.         The Comlete Enhanced Teamplay
  5.  
  6.    John Spickes -- jspickes@eng.umd.edu
  7.  
  8.     $Id: teamplay.qc 1.17 1996/08/17 16:52:45 jspickes Exp $
  9.  
  10.     $Log: teamplay.qc $
  11.     Revision 1.17  1996/08/17 16:52:45  jspickes
  12.     Fixed a problem with displaying the current team settings that could cause
  13.     the wrong output when teamplay was negative.  Also added code to indicate
  14.     when ID's silly teamplay code is being used.
  15.  
  16.     Revision 1.16  1996/08/17 00:41:52  jspickes
  17.     Turned off strict coop by default.
  18.     Fixed a bug that could have caused strange behavior if TEAM_COLOR* was
  19.     set to -2.
  20.  
  21.     Revision 1.15  1996/08/17 00:34:17  jspickes
  22.     Added instructions on drop-item use in current settings output.
  23.     Fixed a problem that would allow you to drop lots of backpacks with
  24.     nothing in them.
  25.  
  26. */
  27.  
  28. /** Defs **/
  29.  
  30. /** MODIFIABLE CONSTANTS **/
  31.  
  32. float TEAM_DEFAULT_PENALTY =    1;      // Default frag penalty
  33. float TEAM_STRICT_COOP =    0;    // Strict Coop
  34.  
  35. // Allowed team colors
  36. // -1 indicates no color
  37.  
  38. float TEAM_COLOR1       =       4;
  39. float TEAM_COLOR2       =       13;
  40. float TEAM_COLOR3       =       -1;
  41. float TEAM_COLOR4       =       -1;
  42.  
  43. /** End of MODIFIABLE CONSTANTS **/
  44.  
  45. // Globals
  46.  
  47. // Teamplay bitfield entries
  48.  
  49. float TEAM_HEALTH_PROTECT =     1;      // No health damage from friendly fire
  50. float TEAM_ARMOR_PROTECT =      2;      // No armor damage from friendly fire
  51. float TEAM_ATTACKER_DAMAGE =    4;      // Attacker takes damage from hitting teammates
  52. float TEAM_FRAG_PENALTY =       8;      // One frag penalty for killing teammate
  53. float TEAM_DEATH_PENALTY =      16;     // Die when you kill a teammate.
  54. float TEAM_LOCK_COLORS =        32;     // Allow only team colors
  55. float TEAM_STATIC_TEAMS =       64;     // Don't allow players to switch teams
  56. float TEAM_DROP_ITEMS =     128;    // Allow players to drop packs and 
  57.                     // weapons.
  58.  
  59. // Prototypes
  60. float() W_BestWeapon;
  61. void() W_SetCurrentAmmo;
  62. void() bound_other_ammo;
  63. void(float o, float n) Deathmatch_Weapon;
  64. void() BackpackTouch;
  65.  
  66. /*
  67. ================
  68. TeamPrintSettings
  69.  
  70. Print out current teamplay options
  71. ================
  72. */
  73.  
  74. void() TeamPrintSettings =
  75. {
  76.     local string s;
  77.     
  78.     sprint(self,"The following Teamplay options are set:\n");
  79.     
  80.     if(teamplay < 0)
  81.     {
  82.         sprint(self, "Frag penalty manually set to ");
  83.         s = ftos(teamplay);
  84.         sprint(self, s);
  85.         sprint(self, "\n");
  86.         return;
  87.     }
  88.     
  89.     if(!teamplay) 
  90.     {
  91.         sprint(self, "None\n");
  92.         return;
  93.     }
  94.     
  95.     if(1 == teamplay)
  96.     {
  97.         sprint(self, "ID's original teamplay 1\n");
  98.         return;
  99.     }
  100.     
  101.     if(teamplay & TEAM_HEALTH_PROTECT)
  102.         sprint(self, "Health-Protect ");
  103.     
  104.     if(teamplay & TEAM_ARMOR_PROTECT)
  105.         sprint(self, "Armor-Protect ");
  106.         
  107.     if(teamplay & TEAM_ATTACKER_DAMAGE)
  108.         sprint(self, "Mirror-Damage ");
  109.         
  110.     if(teamplay & TEAM_FRAG_PENALTY)
  111.         sprint(self, "Frag-Penalty ");
  112.         
  113.     if(teamplay & TEAM_DEATH_PENALTY)
  114.         sprint(self, "Death-Penalty ");
  115.         
  116.     if(teamplay & TEAM_LOCK_COLORS)
  117.         sprint(self, "Lock-Colors ");
  118.         
  119.     if(teamplay & TEAM_STATIC_TEAMS)
  120.         sprint(self, "Static-Teams ");
  121.         
  122.     if(teamplay & TEAM_DROP_ITEMS)
  123.         sprint(self, "Drop-Items (Backpack Impulse 20, Weapon Impulse 21)");
  124.         
  125.     sprint(self, "\n");
  126. };
  127.  
  128. /*
  129. ================
  130. TeamArmorDam
  131.  
  132. Return TRUE if the target's armor can take damage from this attacker.
  133. ================
  134. */
  135.  
  136. float(entity targ, entity inflictor, entity attacker, float damage) TeamArmorDam =
  137. {
  138.         if( teamplay < 0 )
  139.                 return TRUE;
  140.         if( (teamplay & TEAM_ARMOR_PROTECT) && (attacker.team == targ.team) && (attacker != targ) && (targ.team > 0) )
  141.         {
  142.                 // Armor is protected
  143.                 return FALSE;
  144.         }
  145.         return TRUE;
  146. };
  147.  
  148. /*
  149. ================
  150. TeamHealthDam
  151.  
  152. Return TRUE if the target can take health damage from this attacker.
  153. ================
  154. */
  155.  
  156. float(entity targ, entity inflictor, entity attacker, float damage) TeamHealthDam =
  157. {
  158.         if( teamplay < 0 )
  159.         {
  160.                 return TRUE;
  161.         }
  162.         if( (attacker.team == targ.team) && (attacker != targ) && (targ.team > 0) )
  163.         {
  164.                 // Attacker and target are on the same team.
  165.                 if( teamplay & TEAM_ATTACKER_DAMAGE )
  166.                 {
  167.                         // Damage applied to teammate.
  168.                         T_Damage(attacker, inflictor, attacker, damage);
  169.                 }
  170.                 if( teamplay & TEAM_HEALTH_PROTECT )
  171.                 {
  172.                         // Health is protected
  173.                         return FALSE;
  174.                 }
  175.         }
  176.         return TRUE;
  177. };
  178.  
  179. /*
  180. ================
  181. TeamPFrags
  182.  
  183. Return the number of frags we should penalize attacker for killing targ.
  184. ================
  185. */
  186.  
  187. float(entity targ, entity attacker) TeamPFrags =
  188. {
  189.         if( teamplay < 0 )
  190.                 return (-1 * teamplay);
  191.         if( (targ.team > 0) && (targ != attacker) && (targ.team == attacker.team) )
  192.         {
  193.                 // targ and attacker are on the same team
  194.                 if( teamplay < 0 )
  195.                 {
  196.                         // teamplay indicates frag penalty
  197.                         return ( -1 * teamplay );
  198.                 }
  199.                 if( teamplay & TEAM_FRAG_PENALTY )
  200.                 {
  201.                         // default penalty
  202.                         return TEAM_DEFAULT_PENALTY;
  203.                 }
  204.         }
  205.         // No frag penalty
  206.         return 0;
  207. };
  208.  
  209. /*
  210. ================
  211. TeamFragPenalty
  212.  
  213. If attacker should be penalized for killing targ, penalize attacker
  214. and return TRUE.
  215. ================
  216. */
  217.  
  218. float(entity targ, entity attacker) TeamFragPenalty =
  219. {
  220.         local float f;
  221.  
  222.         f = TeamPFrags(targ, attacker);
  223.  
  224.         if( f )
  225.         {
  226.                 // We should penalize some frags.
  227.                 attacker.frags = attacker.frags - f;
  228.                 return TRUE;
  229.         }
  230.         // No penalty
  231.         return FALSE;
  232. };
  233.  
  234. /*
  235. =================
  236. TeamDeathPenalty
  237.  
  238. If attacker should be killed for killing targ, kill attacker and
  239. add a frag to offset the one attacker will lose for killing himself.
  240. */
  241.  
  242. void(entity targ, entity attacker) TeamDeathPenalty =
  243. {
  244.         //Don't kill anyone if teamplay is negative.
  245.         if ( teamplay < 0 )
  246.                 return;
  247.  
  248.         if ( (teamplay & TEAM_DEATH_PENALTY) && (targ.team > 0) && (attacker != targ) && (attacker.team == targ.team) )
  249.         {
  250.                 //We should kill the attacker.
  251.                 T_Damage(attacker,attacker,attacker,1000);
  252.                 //Add a frag to offset the self-kill penalty.
  253.                 attacker.frags = attacker.frags + 1;
  254.         }
  255. };
  256.  
  257. /*
  258. ==================
  259. TeamColorIsLegal
  260.  
  261. Return TRUE if the indicated color is legal
  262. ==================
  263. */
  264. float(float color) TeamColorIsLegal =
  265. {
  266.         // All colors are legal if teamplay is negative.
  267.         if( teamplay < 0 )
  268.                 return TRUE;
  269.         // All colors are legal if TEAM_LOCK_COLORS is off.
  270.         if( !(teamplay & TEAM_LOCK_COLORS) )
  271.                 return TRUE;
  272.         if( (color == TEAM_COLOR1) && (TEAM_COLOR1 >= 0) )
  273.                 return TRUE;
  274.         if( (color == TEAM_COLOR2) && (TEAM_COLOR2 >= 0) )
  275.                 return TRUE;
  276.         if( (color == TEAM_COLOR3) && (TEAM_COLOR3 >= 0) )
  277.                 return TRUE;
  278.         if( (color == TEAM_COLOR4) && (TEAM_COLOR4 >= 0) )
  279.                 return TRUE;
  280. };
  281.  
  282. /*
  283. ==================
  284. TeamCheckTeam
  285.  
  286. Check if the team self is on is legal, and put self in a legal team if not.
  287. Return TRUE if the current color is ok, FALSE if we have to set it.
  288. ==================
  289. */
  290. float() TeamCheckTeam =
  291. {
  292.         local float TEAM1;
  293.         local float TEAM2;
  294.         local float TEAM3;
  295.         local float TEAM4;
  296.  
  297.         local float newcolor;
  298.         local float t;
  299.  
  300.         local entity p;
  301.  
  302.         local string n; 
  303.  
  304.  
  305.         // If self.lastteam is negative, force a team assignment.
  306.         if( self.lastteam >= 0 )
  307.         {
  308.                 if(TeamColorIsLegal(self.team - 1))
  309.                         return TRUE;
  310.         }
  311.  
  312.         // Assign the player to a team.
  313.  
  314.         // Sum the players on all the teams.
  315.  
  316.         TEAM1 = 0;
  317.         TEAM2 = 0;
  318.         TEAM3 = 0;
  319.         TEAM4 = 0;
  320.  
  321.         p = find (world, classname, "player");
  322.  
  323.         while(p)
  324.         {
  325.                 if( (TEAM_COLOR1 >= 0) && (p.team == (TEAM_COLOR1 +1)) )
  326.                         TEAM1 = TEAM1 + 1;
  327.                 if( (TEAM_COLOR2 >= 0) && (p.team == (TEAM_COLOR2 +1)) )
  328.                         TEAM2 = TEAM2 + 1;
  329.                 if( (TEAM_COLOR3 >= 0) && (p.team == (TEAM_COLOR3 +1)) )
  330.                         TEAM3 = TEAM3 + 1;
  331.                 if( (TEAM_COLOR4 >= 0) && (p.team == (TEAM_COLOR4 +1)) )
  332.                         TEAM4 = TEAM4 + 1;
  333.  
  334.                 p = find(p, classname, "player");
  335.         }
  336.  
  337.         // Find the team with the least players.
  338.  
  339.         newcolor = TEAM_COLOR1;
  340.         t = TEAM1;
  341.  
  342.         if ( (TEAM_COLOR2 >= 0) && (TEAM2 < t) )
  343.         {
  344.                 newcolor = TEAM_COLOR2;
  345.                 t = TEAM2;
  346.         }
  347.  
  348.         if ( (TEAM_COLOR3 >= 0) && (TEAM3 < t) )
  349.         {
  350.                 newcolor = TEAM_COLOR3;
  351.                 t = TEAM3;
  352.         }
  353.  
  354.         if ( (TEAM_COLOR4 >= 0) && (TEAM4 < t) )
  355.         {
  356.                 newcolor = TEAM_COLOR4;
  357.                 t = TEAM4;
  358.         }
  359.  
  360.         // Put the player on a the new team.
  361.  
  362.         n = ftos(newcolor);
  363.         stuffcmd(self, "color ");
  364.         stuffcmd(self, n);
  365.         stuffcmd(self, "\n");
  366.  
  367.         sprint(self, "You have been assigned color ");
  368.         sprint(self, n);
  369.         sprint(self, "\nLegal colors are:");
  370.         if(TEAM_COLOR1 >= 0)
  371.         {
  372.                 n = ftos(TEAM_COLOR1);
  373.                 sprint(self, " ");
  374.                 sprint(self, n);
  375.         }
  376.         if(TEAM_COLOR2 >= 0)
  377.         {
  378.                 n = ftos(TEAM_COLOR2);
  379.                 sprint(self, " ");
  380.                 sprint(self, n);
  381.         }
  382.         if(TEAM_COLOR3 >= 0)
  383.         {
  384.                 n = ftos(TEAM_COLOR3);
  385.                 sprint(self, " ");
  386.                 sprint(self, n);
  387.         }
  388.         if(TEAM_COLOR4 >= 0)
  389.         {
  390.                 n = ftos(TEAM_COLOR4);
  391.                 sprint(self, " ");
  392.                 sprint(self, n);
  393.         }
  394.  
  395.         sprint(self, "\n");
  396.  
  397.         self.lastteam = newcolor + 1;      // Remember what team we're on
  398.         return FALSE;
  399. };
  400.  
  401.  
  402.  
  403. /*
  404. ===============
  405. TeamCheckLock
  406.  
  407. Check for team changing and perform whatever actions are neccessary.
  408. ===============
  409. */
  410. void() TeamCheckLock =
  411. {
  412.         local   float   n;
  413.         local   string  s;
  414.  
  415.         // Don't do anything if teamplay is negative
  416.         if ( teamplay < 0 )
  417.                 return;
  418.  
  419.         if ( !TeamColorIsLegal(self.team - 1) && (self.team == self.lastteam) )
  420.                 self.lastteam = -1;
  421.  
  422.         // Check to see if the player has changed colors
  423.         if (self.team != self.lastteam)
  424.         {
  425.                 // Player has changed colors
  426.  
  427.                 // If teams are static and we've been on some team already,
  428.                 // put us back on the team we were on.
  429.  
  430.                 if ( (teamplay & TEAM_STATIC_TEAMS) && (self.lastteam >= 0) )
  431.                 {
  432.                         if ( TeamColorIsLegal(self.lastteam - 1) )
  433.                         {
  434.                                 sprint(self, "You cannot change teams.\n");
  435.                                 stuffcmd(self, "color ");
  436.                                 n = self.lastteam - 1;
  437.                                 s = ftos(n);
  438.                                 stuffcmd(self, s);
  439.                                 stuffcmd(self, "\n");
  440.                                 return;
  441.                         }
  442.                         else
  443.                                 self.lastteam = -50;
  444.                                 // If we're on an illegal team, force a change.
  445.                 }
  446.  
  447.                 // If teamlock is turned off, don't do anything more.
  448.                 if ( !(teamplay & TEAM_LOCK_COLORS) )
  449.                 {
  450.                         if ( teamplay & TEAM_STATIC_TEAMS )
  451.                                 self.lastteam = self.team;
  452.                         return;
  453.                 }
  454.  
  455.                 if(self.lastteam > 0) 
  456.         {
  457.             s = ftos(self.lastteam);
  458.                         T_Damage(self,self,self,1000);  // Kill the player
  459.         }
  460.                 self.frags = 0;                 // Zero out frags
  461.                 if(TeamCheckTeam())
  462.                         self.lastteam = self.team;
  463.         }
  464. };
  465.  
  466. /*
  467. =======================
  468. TossBackPack
  469.  
  470. Original idea by Vhold
  471. Rewritten by John Spickes
  472.  
  473. Toss out a backpack containing some ammo from your current weapon,
  474. and any weapons you don't have.
  475. =======================
  476. */
  477. void() TossBackpack =
  478. {
  479.     local entity     item;
  480.  
  481.     // If we don't have any ammo, return
  482.     if(self.currentammo <= 0)
  483.         return;
  484.  
  485.     item = spawn();
  486.  
  487.     // See if you have the Shotgun or Super Shotgun on
  488.         if ( (self.weapon == IT_SHOTGUN) || (self.weapon == IT_SUPER_SHOTGUN) )
  489.     {
  490.         if( self.ammo_shells >= 20 ) {
  491.             item.ammo_shells = 20;
  492.             self.ammo_shells = self.ammo_shells - 20;
  493.         }
  494.         else
  495.         {
  496.             item.ammo_shells = self.ammo_shells;
  497.             self.ammo_shells = 0;
  498.         }
  499.     }        
  500.     
  501.     // See if you have neither the Shotgun or Super Shotgun
  502.         if ( !(self.items & IT_SHOTGUN) && !(self.items & IT_SUPER_SHOTGUN) )
  503.     {
  504.         if( self.ammo_shells >= 20 ) {
  505.             item.ammo_shells = 20;
  506.             self.ammo_shells = self.ammo_shells - 20;
  507.         }
  508.         else
  509.         {
  510.             item.ammo_shells = self.ammo_shells;
  511.             self.ammo_shells = 0;
  512.         }
  513.     }        
  514.     
  515.     // See if we are using a nailgun
  516.         if ( (self.weapon == IT_NAILGUN) || (self.weapon == IT_SUPER_NAILGUN) )
  517.     {
  518.         if( self.ammo_nails >= 20 )
  519.         {
  520.             item.ammo_nails = 20;
  521.             self.ammo_nails = self.ammo_nails - 20;
  522.         }
  523.         else
  524.         {
  525.             item.ammo_nails = self.ammo_nails;
  526.             self.ammo_nails = 0;
  527.         }
  528.     }    
  529.     // Check to see if we have neither nailgun
  530.         if ( !(self.items & IT_NAILGUN) && !(self.items & IT_SUPER_NAILGUN) )
  531.     {
  532.         if( self.ammo_nails >= 20 )
  533.         {
  534.             item.ammo_nails = 20;
  535.             self.ammo_nails = self.ammo_nails - 20;
  536.         }
  537.         else
  538.         {
  539.             item.ammo_nails = self.ammo_nails;
  540.             self.ammo_nails = 0;
  541.         }
  542.     }    
  543.     
  544.     // See if we are using a grenade or rocket launcher
  545.         if ( (self.weapon == IT_GRENADE_LAUNCHER) || (self.weapon == IT_ROCKET_LAUNCHER) )
  546.     {
  547.         if( self.ammo_rockets >= 10 )
  548.         {
  549.             item.ammo_rockets = 10;
  550.             self.ammo_rockets = self.ammo_rockets - 10;
  551.         }
  552.         else
  553.         {
  554.             item.ammo_rockets = self.ammo_rockets;
  555.             self.ammo_rockets = 0;
  556.         }
  557.     }
  558.     // See if we have neither the Grenade or rocket launcher
  559.         if ( !(self.items & IT_GRENADE_LAUNCHER) && !(self.items & IT_ROCKET_LAUNCHER) )
  560.     {
  561.         if( self.ammo_rockets >= 10 )
  562.         {
  563.             item.ammo_rockets = 10;
  564.             self.ammo_rockets = self.ammo_rockets - 10;
  565.         }
  566.         else
  567.         {
  568.             item.ammo_rockets = self.ammo_rockets;
  569.             self.ammo_rockets = 0;
  570.         }
  571.     }
  572.  
  573.     // See if we're using the lightning gun
  574.     if ( self.weapon == IT_LIGHTNING )
  575.     {    
  576.         if( self.ammo_cells >= 20 )
  577.         {
  578.             item.ammo_cells = 20;
  579.             self.ammo_cells = self.ammo_cells - 20;
  580.         }
  581.         else
  582.         {
  583.             item.ammo_cells = self.ammo_cells;
  584.             self.ammo_cells = 0;
  585.         }
  586.     }
  587.     // see if we don't have the lightning gun
  588.         if ( !(self.items & IT_LIGHTNING) )
  589.     {    
  590.         if( self.ammo_cells >= 20 )
  591.         {
  592.             item.ammo_cells = 20;
  593.             self.ammo_cells = self.ammo_cells - 20;
  594.         }
  595.         else
  596.         {
  597.             item.ammo_cells = self.ammo_cells;
  598.             self.ammo_cells = 0;
  599.         }
  600.     }
  601.      
  602.     item.owner = self;
  603.     makevectors(self.v_angle);
  604.  
  605.     setorigin(item, self.origin + '0 0 16');
  606.     item.velocity = aim(self, 1000);
  607.     item.velocity = item.velocity * 500;
  608.     item.flags = FL_ITEM;
  609.     item.solid = SOLID_TRIGGER;
  610.     item.movetype = MOVETYPE_BOUNCE;
  611.  
  612.     setmodel (item, "progs/backpack.mdl");
  613.     setsize(item, '-16 -16 0', '16 16 56');
  614.     item.touch = BackpackTouch;
  615.     item.nextthink = time + 120;    // remove after 2 minutes
  616.     item.think = SUB_Remove;
  617.  
  618.     W_SetCurrentAmmo();
  619.  
  620. };
  621.  
  622. void() Team_weapon_touch =
  623. {
  624.     local    float    hadammo, best, new, old;
  625.     local    entity    stemp;
  626.  
  627.     if (!(other.flags & FL_CLIENT))
  628.         return;
  629.     // Don't let the owner pick up his own weapon for a second.
  630.     if ( (other == self.owner) && ( (self.nextthink - time) > 119 ) )
  631.         return;
  632.  
  633. // if the player was using his best weapon, change up to the new one if better        
  634.     stemp = self;
  635.     self = other;
  636.     best = W_BestWeapon();
  637.     self = stemp;
  638.  
  639.     if (self.classname == "weapon_nailgun")
  640.     {
  641.         hadammo = other.ammo_nails;            
  642.         new = IT_NAILGUN;
  643.     }
  644.     else if (self.classname == "weapon_supernailgun")
  645.     {
  646.         hadammo = other.ammo_rockets;            
  647.         new = IT_SUPER_NAILGUN;
  648.     }
  649.     else if (self.classname == "weapon_supershotgun")
  650.     {
  651.         hadammo = other.ammo_rockets;            
  652.         new = IT_SUPER_SHOTGUN;
  653.     }
  654.     else if (self.classname == "weapon_rocketlauncher")
  655.     {
  656.         hadammo = other.ammo_rockets;            
  657.         new = IT_ROCKET_LAUNCHER;
  658.     }
  659.     else if (self.classname == "weapon_grenadelauncher")
  660.     {
  661.         hadammo = other.ammo_rockets;            
  662.         new = IT_GRENADE_LAUNCHER;
  663.     }
  664.     else if (self.classname == "weapon_lightning")
  665.     {
  666.         hadammo = other.ammo_rockets;            
  667.         new = IT_LIGHTNING;
  668.     }
  669.     else
  670.         objerror ("Team_weapon_touch: unknown classname");
  671.  
  672.     sprint (other, "You got the ");
  673.     sprint (other, self.netname);
  674.     sprint (other, "\n");
  675. // weapon touch sound
  676.     sound (other, CHAN_ITEM, "weapons/pkup.wav", 1, ATTN_NORM);
  677.     stuffcmd (other, "bf\n");
  678.  
  679.     bound_other_ammo ();
  680.  
  681. // change to the weapon
  682.     old = other.items;
  683.     other.items = other.items | new;
  684.     
  685.     stemp = self;
  686.     self = other;
  687.  
  688.     if (!deathmatch)
  689.         self.weapon = new;
  690.     else
  691.         Deathmatch_Weapon (old, new);
  692.  
  693.     W_SetCurrentAmmo();
  694.  
  695.     self = stemp;
  696.  
  697.     self.model = string_null;
  698.     self.solid = SOLID_NOT;
  699.     
  700.     activator = other;
  701.     SUB_UseTargets();                // fire all targets / killtargets
  702. };
  703.         
  704. void() TossWeapon =
  705. {
  706.     local entity item;
  707.     
  708.     if((self.weapon == IT_AXE) || (self.weapon == IT_SHOTGUN))
  709.         return;
  710.         
  711.     item = spawn();
  712.     item.owner = self;
  713.     makevectors(self.v_angle);
  714.  
  715.     setorigin(item, self.origin + '0 0 16');
  716.     item.velocity = aim(self, 1000);
  717.     item.velocity = item.velocity * 500;
  718.     item.flags = FL_ITEM;
  719.     item.solid = SOLID_TRIGGER;
  720.     item.movetype = MOVETYPE_BOUNCE;
  721.     
  722.     if(self.weapon == IT_SUPER_SHOTGUN)
  723.     {
  724.         setmodel (item, "progs/g_shot.mdl");
  725.         item.weapon = IT_SUPER_SHOTGUN;
  726.         item.netname = "Double-barrelled Shotgun";
  727.         item.classname = "weapon_supershotgun";
  728.         self.items = self.items - IT_SUPER_SHOTGUN;
  729.     }
  730.  
  731.     if( self.weapon == IT_NAILGUN )
  732.     {
  733.         setmodel (item, "progs/g_nail.mdl");
  734.         item.weapon = IT_NAILGUN;
  735.         item.netname = "nailgun";
  736.         item.classname = "weapon_nailgun";
  737.         self.items = self.items - IT_NAILGUN;
  738.     }
  739.         
  740.     if( self.weapon == IT_SUPER_NAILGUN )
  741.     {
  742.         setmodel (item, "progs/g_nail2.mdl");
  743.         item.weapon = IT_SUPER_NAILGUN;
  744.         item.netname = "Super Nailgun";
  745.         item.classname = "weapon_supernailgun";
  746.         self.items = self.items - IT_SUPER_NAILGUN;
  747.     }
  748.     
  749.     if( self.weapon == IT_GRENADE_LAUNCHER )
  750.     {
  751.         setmodel (item, "progs/g_rock.mdl");
  752.         item.weapon = 3;
  753.         item.netname = "Grenade Launcher";
  754.         item.classname = "weapon_grenadelauncher";
  755.         self.items = self.items - IT_GRENADE_LAUNCHER;
  756.     }
  757.     
  758.     if( self.weapon == IT_ROCKET_LAUNCHER )
  759.     {
  760.         setmodel (item, "progs/g_rock2.mdl");
  761.         item.weapon = 3;
  762.         item.netname = "Rocket Launcher";
  763.         item.classname = "weapon_rocketlauncher";
  764.         self.items = self.items - IT_ROCKET_LAUNCHER;
  765.     }
  766.     
  767.     if( self.weapon == IT_LIGHTNING )
  768.     {
  769.         setmodel (item, "progs/g_light.mdl");
  770.         item.weapon = 3;
  771.         item.netname = "Thunderbolt";
  772.         item.classname = "weapon_lightning";
  773.         self.items = self.items - IT_LIGHTNING;
  774.     }
  775.     setsize(item, '-16 -16 0', '16 16 56');
  776.     item.touch = Team_weapon_touch;
  777.     item.think = SUB_Null;
  778.     item.nextthink = time + 120;
  779.     
  780.     self.weapon = W_BestWeapon();
  781.     W_SetCurrentAmmo();
  782. };
  783.