home *** CD-ROM | disk | FTP | other *** search
/ Superpower (Alt) / SUPERPOWER.iso / q / patch / mbq714 / weapons.qc < prev   
Encoding:
Text File  |  1996-08-05  |  37.0 KB  |  1,675 lines

  1. /*
  2.  
  3. Bouncing Fragmentation Grenade!    7/28/96 by Steve Bond
  4. Email: wedge@nuc.net    WWW: http://www.nuc.net/quake
  5.  
  6. >>>READ THE README!
  7.  
  8. Hey ID! 
  9. If you are reading this, PUH-LEEZE fly me and John to Texas!
  10. We'll scrub the shitters at id for the chance to shake hands!
  11. (I mean - we'll wash our hands first and everything)
  12.  
  13. */
  14.  
  15. void (entity targ, entity inflictor, entity attacker, float damage) T_Damage;
  16. void () player_run;
  17. void(entity bomb, entity attacker, float rad, entity ignore) T_RadiusDamage;
  18. void(vector org, vector vel, float damage) SpawnBlood;
  19. void() SuperDamageSound;
  20.  
  21. float bombtimer;
  22.  
  23.  
  24. void() W_FireBomb;
  25. void() BombTouch;
  26. void() BombExplode;
  27. void() BombExplosion;
  28. void() ShrapnelExplode;
  29. void() BombTime;
  30.  
  31. // called by worldspawn
  32. void() W_Precache =
  33. {
  34.     precache_sound ("weapons/r_exp3.wav");  // new rocket explosion
  35.     precache_sound ("weapons/rocket1i.wav");        // spike gun
  36.     precache_sound ("weapons/sgun1.wav");
  37.     precache_sound ("weapons/guncock.wav"); // player shotgun
  38.     precache_sound ("weapons/ric1.wav");    // ricochet (used in c code)
  39.     precache_sound ("weapons/ric2.wav");    // ricochet (used in c code)
  40.     precache_sound ("weapons/ric3.wav");    // ricochet (used in c code)
  41.     precache_sound ("weapons/spike2.wav");  // super spikes
  42.     precache_sound ("weapons/tink1.wav");   // spikes tink (used in c code)
  43.     precache_sound ("weapons/grenade.wav"); // grenade launcher
  44.     precache_sound ("weapons/bounce.wav");          // grenade bounce
  45.     precache_sound ("weapons/shotgn2.wav"); // super shotgun
  46.     precache_sound ("items/damage2.wav");
  47. };
  48.  
  49. float() crandom =
  50. {
  51.     return 2*(random() - 0.5);
  52. };
  53.  
  54. /*
  55. ================
  56. W_FireAxe
  57. ================
  58. */
  59. void() W_FireAxe =
  60. {
  61.     local   vector  source;
  62.     local   vector  org;
  63.  
  64.     source = self.origin + '0 0 16';
  65.     traceline (source, source + v_forward*64, FALSE, self);
  66.     if (trace_fraction == 1.0)
  67.         return;
  68.     
  69.     org = trace_endpos - v_forward*4;
  70.  
  71.     if (trace_ent.takedamage)
  72.     {
  73.         trace_ent.axhitme = 1;
  74.         SpawnBlood (org, '0 0 0', 20);
  75.         T_Damage (trace_ent, self, self, 20);
  76.     }
  77.     else
  78.     {       // hit wall
  79.         sound (self, CHAN_WEAPON, "player/axhit2.wav", 1, ATTN_NORM);
  80.         WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  81.         WriteByte (MSG_BROADCAST, TE_GUNSHOT);
  82.         WriteCoord (MSG_BROADCAST, org_x);
  83.         WriteCoord (MSG_BROADCAST, org_y);
  84.         WriteCoord (MSG_BROADCAST, org_z);
  85.     }
  86. };
  87.  
  88.  
  89. //============================================================================
  90.  
  91.  
  92. vector() wall_velocity =
  93. {
  94.     local vector    vel;
  95.     
  96.     vel = normalize (self.velocity);
  97.     vel = normalize(vel + v_up*(random()- 0.5) + v_right*(random()- 0.5));
  98.     vel = vel + 2*trace_plane_normal;
  99.     vel = vel * 200;
  100.     
  101.     return vel;
  102. };
  103.  
  104.  
  105. /*
  106. ================
  107. SpawnMeatSpray
  108. ================
  109. */
  110. void(vector org, vector vel) SpawnMeatSpray =
  111. {
  112.     local   entity missile, mpuff;
  113.     local   vector  org;
  114.  
  115.     missile = spawn ();
  116.     missile.owner = self;
  117.     missile.movetype = MOVETYPE_BOUNCE;
  118.     missile.solid = SOLID_NOT;
  119.  
  120.     makevectors (self.angles);
  121.  
  122.     missile.velocity = vel;
  123.     missile.velocity_z = missile.velocity_z + 250 + 50*random();
  124.  
  125.     missile.avelocity = '3000 1000 2000';
  126.     
  127. // set missile duration
  128.     missile.nextthink = time + 1;
  129.     missile.think = SUB_Remove;
  130.  
  131.     setmodel (missile, "progs/zom_gib.mdl");
  132.     setsize (missile, '0 0 0', '0 0 0');            
  133.     setorigin (missile, org);
  134. };
  135.  
  136. /*
  137. ================
  138. SpawnBlood
  139. ================
  140. */
  141. void(vector org, vector vel, float damage) SpawnBlood =
  142. {
  143.     particle (org, vel*0.1, 73, damage*2);
  144. };
  145.  
  146. /*
  147. ================
  148. spawn_touchblood
  149. ================
  150. */
  151. void(float damage) spawn_touchblood =
  152. {
  153.     local vector    vel;
  154.  
  155.     vel = wall_velocity () * 0.2;
  156.     SpawnBlood (self.origin + vel*0.01, vel, damage);
  157. };
  158.  
  159.  
  160. /*
  161. ================
  162. SpawnChunk
  163. ================
  164. */
  165. void(vector org, vector vel) SpawnChunk =
  166. {
  167.     particle (org, vel*0.02, 0, 10);
  168. };
  169.  
  170. /*
  171. ==============================================================================
  172.  
  173. MULTI-DAMAGE
  174.  
  175. Collects multiple small damages into a single damage
  176.  
  177. ==============================================================================
  178. */
  179.  
  180. entity  multi_ent;
  181. float   multi_damage;
  182.  
  183. void() ClearMultiDamage =
  184. {
  185.     multi_ent = world;
  186.     multi_damage = 0;
  187. };
  188.  
  189. void() ApplyMultiDamage =
  190. {
  191.     if (!multi_ent)
  192.         return;
  193.     T_Damage (multi_ent, self, self, multi_damage);
  194. };
  195.  
  196. void(entity hit, float damage) AddMultiDamage =
  197. {
  198.     if (!hit)
  199.         return;
  200.     
  201.     if (hit != multi_ent)
  202.     {
  203.         ApplyMultiDamage ();
  204.         multi_damage = damage;
  205.         multi_ent = hit;
  206.     }
  207.     else
  208.         multi_damage = multi_damage + damage;
  209. };
  210.  
  211. /*
  212. ==============================================================================
  213.  
  214. BULLETS
  215.  
  216. ==============================================================================
  217. */
  218.  
  219. /*
  220. ================
  221. TraceAttack
  222. ================
  223. */
  224. void(float damage, vector dir) TraceAttack =
  225. {
  226.     local   vector  vel, org;
  227.     
  228.     vel = normalize(dir + v_up*crandom() + v_right*crandom());
  229.     vel = vel + 2*trace_plane_normal;
  230.     vel = vel * 200;
  231.  
  232.     org = trace_endpos - dir*4;
  233.  
  234.     if (trace_ent.takedamage)
  235.     {
  236.         SpawnBlood (org, vel*0.2, damage);
  237.         AddMultiDamage (trace_ent, damage);
  238.     }
  239.     else
  240.     {
  241.         WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  242.         WriteByte (MSG_BROADCAST, TE_GUNSHOT);
  243.         WriteCoord (MSG_BROADCAST, org_x);
  244.         WriteCoord (MSG_BROADCAST, org_y);
  245.         WriteCoord (MSG_BROADCAST, org_z);
  246.     }
  247. };
  248.  
  249. /*
  250. ================
  251. FireBullets
  252.  
  253. Used by shotgun, super shotgun, and enemy soldier firing
  254. Go to the trouble of combining multiple pellets into a single damage call.
  255. ================
  256. */
  257. void(float shotcount, vector dir, vector spread) FireBullets =
  258. {
  259.     local   vector direction;
  260.     local   vector  src;
  261.     
  262.     makevectors(self.v_angle);
  263.  
  264.     src = self.origin + v_forward*10;
  265.     src_z = self.absmin_z + self.size_z * 0.7;
  266.  
  267.     ClearMultiDamage ();
  268.     while (shotcount > 0)
  269.     {
  270.         direction = dir + crandom()*spread_x*v_right + crandom()*spread_y*v_up;
  271.  
  272.         traceline (src, src + direction*2048, FALSE, self);
  273.         if (trace_fraction != 1.0)
  274.             TraceAttack (4, direction);
  275.  
  276.         shotcount = shotcount - 1;
  277.     }
  278.     ApplyMultiDamage ();
  279. };
  280.  
  281. /*
  282. ================
  283. W_FireShotgun
  284. ================
  285. */
  286. void() W_FireShotgun =
  287. {
  288.     local vector dir;
  289.  
  290.     sound (self, CHAN_WEAPON, "weapons/guncock.wav", 1, ATTN_NORM); 
  291.  
  292.     self.punchangle_x = -2;
  293.     
  294.     self.currentammo = self.ammo_shells = self.ammo_shells - 1;
  295.     dir = aim (self, 100000);
  296.     FireBullets (6, dir, '0.04 0.04 0');
  297. };
  298.  
  299.  
  300. /*
  301. ================
  302. W_FireSuperShotgun
  303. ================
  304. */
  305. void() W_FireSuperShotgun =
  306. {
  307.     local vector dir;
  308.  
  309.     if (self.currentammo == 1)
  310.     {
  311.         W_FireShotgun ();
  312.         return;
  313.     }
  314.         
  315.     sound (self ,CHAN_WEAPON, "weapons/shotgn2.wav", 1, ATTN_NORM); 
  316.  
  317.     self.punchangle_x = -4;
  318.     
  319.     self.currentammo = self.ammo_shells = self.ammo_shells - 2;
  320.     dir = aim (self, 100000);
  321.     FireBullets (14, dir, '0.14 0.08 0');
  322. };
  323.  
  324.  
  325. /*
  326. ==============================================================================
  327.  
  328. ROCKETS
  329.  
  330. ==============================================================================
  331. */
  332.  
  333. void()  s_explode1      =       [0,             s_explode2] {};
  334. void()  s_explode2      =       [1,             s_explode3] {};
  335. void()  s_explode3      =       [2,             s_explode4] {};
  336. void()  s_explode4      =       [3,             s_explode5] {};
  337. void()  s_explode5      =       [4,             s_explode6] {};
  338. void()  s_explode6      =       [5,             SUB_Remove] {};
  339.  
  340. void() BecomeExplosion =
  341. {
  342.     self.movetype = MOVETYPE_NONE;
  343.     self.velocity = '0 0 0';
  344.     self.touch = SUB_Null;
  345.     setmodel (self, "progs/s_explod.spr");
  346.     self.solid = SOLID_NOT;
  347.     s_explode1 ();
  348. };
  349.  
  350. void() T_MissileTouch =
  351. {
  352.     local float     damg;
  353.  
  354.     if (other == self.owner)
  355.         return;         // don't explode on owner
  356.  
  357.     if (pointcontents(self.origin) == CONTENT_SKY)
  358.     {
  359.         remove(self);
  360.         return;
  361.     }
  362.  
  363.     damg = 100 + random()*20;
  364.     
  365.     if (other.health)
  366.     {
  367.         if (other.classname == "monster_shambler")
  368.             damg = damg * 0.5;      // mostly immune
  369.         T_Damage (other, self, self.owner, damg );
  370.     }
  371.  
  372.     // don't do radius damage to the other, because all the damage
  373.     // was done in the impact
  374.     T_RadiusDamage (self, self.owner, 120, other);
  375.  
  376. //      sound (self, CHAN_WEAPON, "weapons/r_exp3.wav", 1, ATTN_NORM);
  377.     self.origin = self.origin - 8*normalize(self.velocity);
  378.  
  379.     WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  380.     WriteByte (MSG_BROADCAST, TE_EXPLOSION);
  381.     WriteCoord (MSG_BROADCAST, self.origin_x);
  382.     WriteCoord (MSG_BROADCAST, self.origin_y);
  383.     WriteCoord (MSG_BROADCAST, self.origin_z);
  384.  
  385.     BecomeExplosion ();
  386. };
  387.  
  388.  
  389.  
  390. /*
  391. ================
  392. W_FireRocket
  393. ================
  394. */
  395. void() W_FireRocket =
  396. {
  397.     local   entity missile, mpuff;
  398.     
  399.     self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
  400.     
  401.     sound (self, CHAN_WEAPON, "weapons/sgun1.wav", 1, ATTN_NORM);
  402.  
  403.     self.punchangle_x = -2;
  404.  
  405.     missile = spawn ();
  406.     missile.owner = self;
  407.     missile.movetype = MOVETYPE_FLYMISSILE;
  408.     missile.solid = SOLID_BBOX;
  409.         
  410. // set missile speed    
  411.  
  412.     makevectors (self.v_angle);
  413.     missile.velocity = aim(self, 1000);
  414.     missile.velocity = missile.velocity * 1000;
  415.     missile.angles = vectoangles(missile.velocity);
  416.     
  417.     missile.touch = T_MissileTouch;
  418.     
  419. // set missile duration
  420.     missile.nextthink = time + 5;
  421.     missile.think = SUB_Remove;
  422.  
  423.     setmodel (missile, "progs/missile.mdl");
  424.     setsize (missile, '0 0 0', '0 0 0');            
  425.     setorigin (missile, self.origin + v_forward*8 + '0 0 16');
  426. };
  427.  
  428. /*
  429. ===============================================================================
  430.  
  431. LIGHTNING
  432.  
  433. ===============================================================================
  434. */
  435.  
  436. /*
  437. =================
  438. LightningDamage
  439. =================
  440. */
  441. void(vector p1, vector p2, entity from, float damage) LightningDamage =
  442. {
  443.     local entity            e1, e2;
  444.     local vector            f;
  445.     
  446.     f = p2 - p1;
  447.     normalize (f);
  448.     f_x = 0 - f_y;
  449.     f_y = f_x;
  450.     f_z = 0;
  451.     f = f*16;
  452.  
  453.     e1 = e2 = world;
  454.  
  455.     traceline (p1, p2, FALSE, self);
  456.     if (trace_ent.takedamage)
  457.     {
  458.         particle (trace_endpos, '0 0 100', 225, damage*4);
  459.         T_Damage (trace_ent, from, from, damage);
  460.         if (self.classname == "player")
  461.         {
  462.             if (other.classname == "player")
  463.                 trace_ent.velocity_z = trace_ent.velocity_z + 400;
  464.         }
  465.     }
  466.     e1 = trace_ent;
  467.  
  468.     traceline (p1 + f, p2 + f, FALSE, self);
  469.     if (trace_ent != e1 && trace_ent.takedamage)
  470.     {
  471.         particle (trace_endpos, '0 0 100', 225, damage*4);
  472.         T_Damage (trace_ent, from, from, damage);
  473.     }
  474.     e2 = trace_ent;
  475.  
  476.     traceline (p1 - f, p2 - f, FALSE, self);
  477.     if (trace_ent != e1 && trace_ent != e2 && trace_ent.takedamage)
  478.     {
  479.         particle (trace_endpos, '0 0 100', 225, damage*4);
  480.         T_Damage (trace_ent, from, from, damage);
  481.     }
  482. };
  483.  
  484.  
  485. void() W_FireLightning =
  486. {
  487.     local   vector          org;
  488.  
  489.     if (self.ammo_cells < 1)
  490.     {
  491.         self.weapon = W_BestWeapon ();
  492.         W_SetCurrentAmmo ();
  493.         return;
  494.     }
  495.  
  496. // explode if under water
  497.     if (self.waterlevel > 1)
  498.     {
  499.         T_RadiusDamage (self, self, 35*self.ammo_cells, world);
  500.         self.ammo_cells = 0;
  501.         W_SetCurrentAmmo ();
  502.         return;
  503.     }
  504.  
  505.     if (self.t_width < time)
  506.     {
  507.         sound (self, CHAN_WEAPON, "weapons/lhit.wav", 1, ATTN_NORM);
  508.         self.t_width = time + 0.6;
  509.     }
  510.     self.punchangle_x = -2;
  511.  
  512.     self.currentammo = self.ammo_cells = self.ammo_cells - 1;
  513.  
  514.     org = self.origin + '0 0 16';
  515.     
  516.     traceline (org, org + v_forward*600, TRUE, self);
  517.  
  518.     WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  519.     WriteByte (MSG_BROADCAST, TE_LIGHTNING2);
  520.     WriteEntity (MSG_BROADCAST, self);
  521.     WriteCoord (MSG_BROADCAST, org_x);
  522.     WriteCoord (MSG_BROADCAST, org_y);
  523.     WriteCoord (MSG_BROADCAST, org_z);
  524.     WriteCoord (MSG_BROADCAST, trace_endpos_x);
  525.     WriteCoord (MSG_BROADCAST, trace_endpos_y);
  526.     WriteCoord (MSG_BROADCAST, trace_endpos_z);
  527.  
  528.     LightningDamage (self.origin, trace_endpos + v_forward*4, self, 30);
  529. };
  530.  
  531.  
  532. //=============================================================================
  533.  
  534.  
  535. void() GrenadeExplode =
  536. {
  537.     T_RadiusDamage (self, self.owner, 120, world);
  538.  
  539.     WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  540.     WriteByte (MSG_BROADCAST, TE_EXPLOSION);
  541.     WriteCoord (MSG_BROADCAST, self.origin_x);
  542.     WriteCoord (MSG_BROADCAST, self.origin_y);
  543.     WriteCoord (MSG_BROADCAST, self.origin_z);
  544.  
  545.     BecomeExplosion ();
  546. };
  547.  
  548. void() GrenadeTouch =
  549. {
  550.     if (other == self.owner)
  551.         return;         // don't explode on owner
  552.     if (other.takedamage == DAMAGE_AIM)
  553.     {
  554.         GrenadeExplode();
  555.         return;
  556.     }
  557.     sound (self, CHAN_WEAPON, "weapons/bounce.wav", 1, ATTN_NORM);  // bounce sound
  558.     if (self.velocity == '0 0 0')
  559.         self.avelocity = '0 0 0';
  560. };
  561.  
  562. /*
  563. ================
  564. W_FireGrenade
  565. ================
  566. */
  567. void() W_FireGrenade =
  568. {
  569.     local   entity missile, mpuff;
  570.     
  571.     self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
  572.     
  573.     sound (self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
  574.  
  575.     self.punchangle_x = -2;
  576.  
  577.     missile = spawn ();
  578.     missile.owner = self;
  579.     missile.movetype = MOVETYPE_BOUNCE;
  580.     missile.solid = SOLID_BBOX;
  581.     missile.classname = "grenade";
  582.         
  583. // set missile speed    
  584.  
  585.     makevectors (self.v_angle);
  586.  
  587.     if (self.v_angle_x)
  588.         missile.velocity = v_forward*600 + v_up * 200 + crandom()*v_right*10 + crandom()*v_up*10;
  589.     else
  590.     {
  591.         missile.velocity = aim(self, 10000);
  592.         missile.velocity = missile.velocity * 600;
  593.         missile.velocity_z = 200;
  594.     }
  595.  
  596.     missile.avelocity = '300 300 300';
  597.  
  598.     missile.angles = vectoangles(missile.velocity);
  599.     
  600.     missile.touch = GrenadeTouch;
  601.     
  602. // set missile duration
  603.     missile.nextthink = time + 2.5;
  604.     missile.think = GrenadeExplode;
  605.  
  606.     setmodel (missile, "progs/grenade.mdl");
  607.     setsize (missile, '0 0 0', '0 0 0');            
  608.     setorigin (missile, self.origin);
  609. };
  610.  
  611.  
  612. //=============================================================================
  613.  
  614. void() spike_touch;
  615. void() superspike_touch;
  616.  
  617.  
  618. /*
  619. ===============
  620. launch_spike
  621.  
  622. Used for both the player and the ogre
  623. ===============
  624. */
  625. void(vector org, vector dir) launch_spike =
  626. {
  627.     newmis = spawn ();
  628.     newmis.owner = self;
  629.     newmis.movetype = MOVETYPE_FLYMISSILE;
  630.     newmis.solid = SOLID_BBOX;
  631.  
  632.     newmis.angles = vectoangles(dir);
  633.     
  634.     newmis.touch = spike_touch;
  635.     newmis.classname = "spike";
  636.     newmis.think = SUB_Remove;
  637. // Bump the nail's lifespan up to 11 seconds(?),so it will stick for a bit        
  638.     newmis.nextthink = time + 11;
  639.     setmodel (newmis, "progs/spike.mdl");
  640.     setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);               
  641.     setorigin (newmis, org);
  642.  
  643.     newmis.velocity = dir * 1000;
  644. };
  645.  
  646. void() W_FireSuperSpikes =
  647. {
  648.     local vector    dir;
  649.     local entity    old;
  650.     
  651.     sound (self, CHAN_WEAPON, "weapons/spike2.wav", 1, ATTN_NORM);
  652.     self.attack_finished = time + 0.2;
  653.     self.currentammo = self.ammo_nails = self.ammo_nails - 2;
  654.     dir = aim (self, 1000);
  655.     launch_spike (self.origin + '0 0 16', dir);
  656.     newmis.touch = superspike_touch;
  657.     setmodel (newmis, "progs/s_spike.mdl");
  658.     setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);               
  659.     self.punchangle_x = -2;
  660. };
  661.  
  662. void(float ox) W_FireSpikes =
  663. {
  664.     local vector    dir;
  665.     local entity    old;
  666.     
  667.     makevectors (self.v_angle);
  668.     
  669.     if (self.ammo_nails >= 2 && self.weapon == IT_SUPER_NAILGUN)
  670.     {
  671.         W_FireSuperSpikes ();
  672.         return;
  673.     }
  674.  
  675.     if (self.ammo_nails < 1)
  676.     {
  677.         self.weapon = W_BestWeapon ();
  678.         W_SetCurrentAmmo ();
  679.         return;
  680.     }
  681.  
  682.     sound (self, CHAN_WEAPON, "weapons/rocket1i.wav", 1, ATTN_NORM);
  683.     self.attack_finished = time + 0.2;
  684.     self.currentammo = self.ammo_nails = self.ammo_nails - 1;
  685.     dir = aim (self, 1000);
  686.     launch_spike (self.origin + '0 0 16' + v_right*ox, dir);
  687.  
  688.     self.punchangle_x = -2;
  689. };
  690.  
  691.  
  692.  
  693. .float hit_z;
  694. void() spike_touch =
  695. {
  696. local float rand;
  697.     if (other == self.owner)
  698.         return;
  699.  
  700.     if (other.solid == SOLID_TRIGGER)
  701.         return; // trigger field, do nothing
  702.  
  703.     if (pointcontents(self.origin) == CONTENT_SKY)
  704.     {
  705.         remove(self);
  706.         return;
  707.     }
  708.     
  709. // hit something that bleeds
  710.     if (other.takedamage)
  711.     {
  712.         spawn_touchblood (9);
  713.         T_Damage (other, self, self.owner, 9);
  714.         remove(self);
  715.     }
  716.     else
  717.     {
  718.         WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  719.         
  720.         if (self.classname == "wizspike")
  721.             WriteByte (MSG_BROADCAST, TE_WIZSPIKE);
  722.         else if (self.classname == "knightspike")
  723.             WriteByte (MSG_BROADCAST, TE_KNIGHTSPIKE);
  724.         else
  725.             WriteByte (MSG_BROADCAST, TE_SPIKE);
  726.         WriteCoord (MSG_BROADCAST, self.origin_x);
  727.         WriteCoord (MSG_BROADCAST, self.origin_y);
  728.         WriteCoord (MSG_BROADCAST, self.origin_z);
  729.     }
  730.  
  731. /*
  732. DO NOT let the nail remove itself. This section of code is only executed
  733. when the nail has hit a wall, floor, or plat. These are places we want the 
  734. nail to stick, so we comment out the REMOVE(SELF); function call
  735. */
  736.     self.velocity='0 0 0'; // make the nail stop!
  737.     remove(self);
  738.  
  739. };
  740.  
  741. void() superspike_touch =
  742. {
  743. local float rand;
  744.     if (other == self.owner)
  745.         return;
  746.  
  747.     if (other.solid == SOLID_TRIGGER)
  748.         return; // trigger field, do nothing
  749.  
  750.     if (pointcontents(self.origin) == CONTENT_SKY)
  751.     {
  752.         remove(self);
  753.         return;
  754.     }
  755.     
  756. // hit something that bleeds
  757.     if (other.takedamage)
  758.     {
  759.         spawn_touchblood (18);
  760.         T_Damage (other, self, self.owner, 18);
  761.     }
  762.     else
  763.     {
  764.         WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  765.         WriteByte (MSG_BROADCAST, TE_SUPERSPIKE);
  766.         WriteCoord (MSG_BROADCAST, self.origin_x);
  767.         WriteCoord (MSG_BROADCAST, self.origin_y);
  768.         WriteCoord (MSG_BROADCAST, self.origin_z);
  769.     }
  770.  
  771.     remove(self);
  772.  
  773. };
  774.  
  775.  
  776.  
  777.  
  778.  
  779.  
  780. /*========================================================================
  781. BOUNCING FRAGMENTATION GRENADE - Version .9
  782. 7/28/96 - Steve Bond  email:wedge@nuc.net
  783. http://www.nuc.net/quake
  784. =======================================================================*/
  785.  
  786. //This code segment handles the impact of shrapnel
  787. //this is merely id's superspike_touch code, reworked
  788. void() shrapnel_touch =
  789. {
  790. local float rand;
  791. // has the shrapnel hit a switch? 
  792.     if (other.solid == SOLID_TRIGGER)
  793.         return; // trigger field, do nothing
  794.  
  795. // has the shrapnel hit the sky?
  796.     if (pointcontents(self.origin) == CONTENT_SKY)
  797.     {
  798.         remove(self);
  799.         return;
  800.     }
  801.     
  802. // has the shrapnel hit a living thing?
  803.     if (other.takedamage)
  804.     {
  805.         spawn_touchblood (18);
  806.         T_Damage (other, self, self.owner, 18);
  807.     }
  808.     else
  809.     {
  810.         WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  811.         WriteByte (MSG_BROADCAST, TE_SUPERSPIKE);
  812.         WriteCoord (MSG_BROADCAST, self.origin_x);
  813.         WriteCoord (MSG_BROADCAST, self.origin_y);
  814.         WriteCoord (MSG_BROADCAST, self.origin_z);
  815.     }
  816.  
  817. };
  818.  
  819. /*
  820. Code to spawn ONE randomly directed piece of shrapnel
  821. this is id's launch_spike code, reworked
  822. Pass a vector to this function to determine the shrap's origin
  823. */
  824. void (vector org, float spin, entity shooter) launch_shrapnel=
  825. {
  826.     local float xdir,ydir,zdir;
  827.     
  828. //Assign a random direction for the shrapnel to fly in
  829.     xdir = 110 * random() - 55;
  830.     ydir = 110 * random() - 55;
  831.     zdir = 50 * random() - 25;
  832.  
  833.     newmis = spawn ();
  834.     newmis.owner = shooter;
  835.     newmis.movetype = MOVETYPE_BOUNCE;
  836.     self.touch = SUB_Null;
  837.     newmis.solid = SOLID_BBOX;
  838.  
  839.     newmis.touch = shrapnel_touch;
  840.     newmis.classname = "spike";
  841.     newmis.think =     ShrapnelExplode;
  842.     
  843. // this is how many seconds(?) the nails can exist.        
  844.     newmis.nextthink = time + 1;
  845.     
  846. // speed at which to move the shrapnel        
  847.     newmis.velocity_x = xdir * 2;
  848.     newmis.velocity_y = ydir * 2;
  849.     newmis.velocity_z = zdir * 15;
  850.  
  851. /*
  852. as best I can figure, AVELOCITY means "attitude velocity"        
  853. or something thereabouts. Anyway, it makes shit spin on 
  854. the x,y,z axes by the given velocity for each axis. In this 
  855. case, it makes the shrapnel spin in flight. Good stuff.
  856. this segment assigns one of five preset attitudes for 
  857. each piece of shrapnel, based on the number passed to the
  858. function.
  859. */        
  860.     if (spin == 0)
  861.     newmis.avelocity='250 300 400';
  862.     if (spin == 1)
  863.     newmis.avelocity='400 250 300';
  864.     if (spin == 2)
  865.     newmis.avelocity='300 400 250';
  866.     if (spin == 3)
  867.     newmis.avelocity='300 300 300';
  868.     if (spin == 4) 
  869.     newmis.avelocity='400 250 400';
  870.  
  871.     setmodel (newmis, "progs/grenade.mdl");
  872.     setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);
  873.     setorigin (newmis, org);
  874. };
  875.  
  876. // This code segment detonates the 'second stage' of the grenade
  877. // (After it has popped up)
  878. void()  BouncerExplode =
  879. {
  880.     
  881. // Do the damage
  882.     T_RadiusDamage (self, self.owner, 120, world);
  883. // Tell the network
  884.     WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  885.     WriteByte (MSG_BROADCAST, TE_EXPLOSION);
  886.     WriteCoord (MSG_BROADCAST, self.origin_x);
  887.     WriteCoord (MSG_BROADCAST, self.origin_y);
  888.     WriteCoord (MSG_BROADCAST, self.origin_z);
  889.  
  890. // Let Quake handle the explosion and deallocation of the grenade        
  891.     self.solid=SOLID_NOT;
  892.     BecomeExplosion ();
  893.  
  894. // Launch a hail (20 pieces) of shrapnel
  895.     launch_shrapnel (self.origin + '0 0 -1',0,self.owner);
  896.     launch_shrapnel (self.origin + '0 0 -1',1,self.owner);
  897.     launch_shrapnel (self.origin + '0 0 -1',2,self.owner);
  898.     launch_shrapnel (self.origin + '0 0 -1',3,self.owner);
  899.     launch_shrapnel (self.origin + '0 0 -1',4,self.owner);
  900.     launch_shrapnel (self.origin + '0 0 -1',0,self.owner);
  901.     launch_shrapnel (self.origin + '0 0 -1',1,self.owner);
  902.     launch_shrapnel (self.origin + '0 0 -1',2,self.owner);
  903.     launch_shrapnel (self.origin + '0 0 -1',3,self.owner);
  904.     launch_shrapnel (self.origin + '0 0 -1',4,self.owner);
  905.     
  906. };
  907.  
  908. /*
  909. This code segment makes the 'first stage' of the bouncer pop upward
  910. after it's time has expired.
  911. */
  912. void() BouncerTouch;
  913. void() BouncerPopUp=
  914. {
  915.     local entity missile, mpuff;
  916.  
  917. // Make the grenade stop
  918.     self.movetype=MOVETYPE_NONE;
  919.     self.velocity='0 0 0';
  920. // Draw a tiny explosion (no particles)        
  921.     setmodel (self, "progs/s_explod.spr");
  922.     s_explode1 ();
  923. // Make the :FOOMP: grenade launcher sound        
  924.     sound (self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
  925. // Spawn and animate the 'second stage'
  926.     missile = spawn ();
  927.     missile.owner = self.owner;
  928.     missile.movetype = MOVETYPE_BOUNCE;
  929.     missile.solid = SOLID_BBOX;
  930.     missile.classname = "grenade";
  931. // Set speed
  932.     missile.velocity = '0 0 650';
  933.     missile.angles = vectoangles(missile.velocity);
  934.     missile.touch = BouncerTouch;
  935. // Set Duration
  936.     missile.nextthink = time + 1;
  937.     missile.think = BouncerExplode;
  938.  
  939.     setmodel (missile, "progs/missile.mdl");
  940.     setsize (missile, '0 0 0', '0 0 0');
  941.     setorigin (missile, self.origin);
  942. };
  943.  
  944. // This code segment handles collisions for the 'first stage'
  945. // Of the grenade (after launch and before popup)
  946.  
  947. void() BouncerTouch =
  948. {
  949. //Did the grenade hit a 'living' thing?
  950.     if (other.takedamage)
  951.     {
  952. // yes, so play the bounce sound
  953.     sound (self, CHAN_WEAPON, "weapons/bounce.wav", 1, ATTN_NORM);
  954. // now, exit the function without cause damage to the thing        
  955.     return;
  956.     }
  957.  
  958. // This controls what happens when the grenade hits walls, etz        
  959. // It just plays the sound and bounces on
  960.     sound (self, CHAN_WEAPON, "weapons/bounce.wav", 1, ATTN_NORM);
  961.     if (self.velocity == '0 0 0')
  962.         self.avelocity = '0 0 0';
  963. };
  964.  
  965. /*
  966. This code segment handles the launching of the Bouncing Fragmentation Grenade
  967. this is a reworked copy of id's W_launchgrenade code
  968. */
  969. void() W_LaunchBouncer =
  970. {
  971. // If player doesn't have 3 or more rockets, don't launch
  972.     if ((self.ammo_rockets < 10) || (self.weapon != IT_FIREWALL))
  973.     {
  974.     return;
  975.     }
  976.  
  977.     local   entity missile, mpuff;
  978.     
  979. // Take 3 rockets from the player        
  980.     self.currentammo = self.ammo_rockets = self.ammo_rockets - 10;
  981.     
  982.     //sound (self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
  983. /*
  984. self.punchangle_x (x, y, or z) defines how hard the weapon         
  985. recoils (or 'punches' the player, making the screen shake)
  986. */        
  987.     self.punchangle_x = -2;
  988.  
  989. // This spawns the grenade - it is all id's standard grenade code        
  990.     missile = spawn ();
  991.     missile.owner = self;
  992.     missile.movetype = MOVETYPE_BOUNCE;
  993.     missile.solid = SOLID_BBOX;
  994.     missile.classname = "grenade";
  995.         
  996. // set missile speed    
  997.  
  998.     makevectors (self.v_angle);
  999.  
  1000.     if (self.v_angle_x)
  1001.         missile.velocity = v_forward*600 + v_up * 200 + crandom()*v_right*10 + crandom()*v_up*10;
  1002.     else
  1003.     {
  1004.         missile.velocity = aim(self, 10000);
  1005.         missile.velocity = missile.velocity * 600;
  1006.         missile.velocity_z = 200;
  1007.     }
  1008.  
  1009.     missile.avelocity = '300 300 300';
  1010.  
  1011.     missile.angles = vectoangles(missile.velocity);
  1012.     
  1013. // if the grenade touches anything, BouncerTouch() is called        
  1014.     missile.touch = BouncerTouch;
  1015.     
  1016. // Grenade has a maximum lifespan of 1.5 (seconds?)
  1017. // set missile duration
  1018.     missile.nextthink = time + 1;
  1019.     
  1020. // when the grenade's lifespan has expired, BouncerPopUp() is called        
  1021.     missile.think = BouncerPopUp;
  1022.  
  1023.     setmodel (missile, "progs/grenade.mdl");
  1024.     setsize (missile, '0 0 0', '0 0 0');            
  1025.     setorigin (missile, self.origin);
  1026. //    sprint(self,"Gib 'em!\n");
  1027. };
  1028. /*
  1029. ===============================================================================
  1030. End of Bouncing Fragmentation Grenade code.
  1031. ===============================================================================
  1032. */
  1033.  
  1034.  
  1035.  
  1036.  
  1037.  
  1038.  
  1039. /*
  1040.  
  1041. PLAYER WEAPON USE
  1042.  
  1043. ===============================================================================
  1044. */
  1045.  
  1046. void() W_SetCurrentAmmo =
  1047. {
  1048.     player_run ();          // get out of any weapon firing states
  1049.  
  1050.     self.items = self.items - ( self.items & (IT_SHELLS | IT_NAILS | IT_ROCKETS | IT_CELLS) );
  1051.     
  1052.     if (self.weapon == IT_AXE)
  1053.     {
  1054.         self.currentammo = 0;
  1055.         self.weaponmodel = "progs/v_axe.mdl";
  1056.         self.weaponframe = 0;
  1057.     }
  1058.     else if (self.weapon == IT_SHOTGUN)
  1059.     {
  1060.         self.currentammo = self.ammo_shells;
  1061.         self.weaponmodel = "progs/v_shot.mdl";
  1062.         self.weaponframe = 0;
  1063.         self.items = self.items | IT_SHELLS;
  1064.     }
  1065.     else if (self.weapon == IT_SUPER_SHOTGUN)
  1066.     {
  1067.         self.currentammo = self.ammo_shells;
  1068.         self.weaponmodel = "progs/v_shot2.mdl";
  1069.         self.weaponframe = 0;
  1070.         self.items = self.items | IT_SHELLS;
  1071.     }
  1072.     else if (self.weapon == IT_NAILGUN)
  1073.     {
  1074.         self.currentammo = self.ammo_nails;
  1075.         self.weaponmodel = "progs/v_nail.mdl";
  1076.         self.weaponframe = 0;
  1077.         self.items = self.items | IT_NAILS;
  1078.     }
  1079.     else if (self.weapon == IT_SUPER_NAILGUN)
  1080.     {
  1081.         self.currentammo = self.ammo_nails;
  1082.         self.weaponmodel = "progs/v_nail2.mdl";
  1083.         self.weaponframe = 0;
  1084.         self.items = self.items | IT_NAILS;
  1085.     }
  1086.     else if ((self.weapon == IT_GRENADE_LAUNCHER) || (self.weapon == IT_FIREWALL) || (self.weapon == IT_BOMB))
  1087.     {
  1088.         self.currentammo = self.ammo_rockets;
  1089.         self.weaponmodel = "progs/v_rock.mdl";
  1090.         self.weaponframe = 0;
  1091.         self.items = self.items | IT_ROCKETS;
  1092.     }
  1093.     else if (self.weapon == IT_ROCKET_LAUNCHER)
  1094.     {
  1095.         self.currentammo = self.ammo_rockets;
  1096.         self.weaponmodel = "progs/v_rock2.mdl";
  1097.         self.weaponframe = 0;
  1098.         self.items = self.items | IT_ROCKETS;
  1099.     }
  1100.     else if (self.weapon == IT_LIGHTNING)
  1101.     {
  1102.         self.currentammo = self.ammo_cells;
  1103.         self.weaponmodel = "progs/v_light.mdl";
  1104.         self.weaponframe = 0;
  1105.         self.items = self.items | IT_CELLS;
  1106.     }
  1107.     else
  1108.     {
  1109.         self.currentammo = 0;
  1110.         self.weaponmodel = "";
  1111.         self.weaponframe = 0;
  1112.     }
  1113. };
  1114.  
  1115. float() W_BestWeapon =
  1116. {
  1117.     local   float   it;
  1118.     
  1119.     it = self.items;
  1120.  
  1121.     if(self.ammo_cells >= 1 && (it & IT_LIGHTNING) )
  1122.         return IT_LIGHTNING;
  1123.     else if(self.ammo_nails >= 2 && (it & IT_SUPER_NAILGUN) )
  1124.         return IT_SUPER_NAILGUN;
  1125.     else if(self.ammo_shells >= 2 && (it & IT_SUPER_SHOTGUN) )
  1126.         return IT_SUPER_SHOTGUN;
  1127.     else if(self.ammo_nails >= 1 && (it & IT_NAILGUN) )
  1128.         return IT_NAILGUN;
  1129.     else if(self.ammo_shells >= 1 && (it & IT_SHOTGUN) )
  1130.         return IT_SHOTGUN;
  1131.         
  1132. /*
  1133.     if(self.ammo_rockets >= 1 && (it & IT_ROCKET_LAUNCHER) )
  1134.         return IT_ROCKET_LAUNCHER;
  1135.     else if(self.ammo_rockets >= 1 && (it & IT_GRENADE_LAUNCHER) )
  1136.         return IT_GRENADE_LAUNCHER;
  1137.  
  1138. */
  1139.  
  1140.     return IT_AXE;
  1141. };
  1142.  
  1143. float() W_CheckNoAmmo =
  1144. {
  1145.     if (self.currentammo > 0)
  1146.         return TRUE;
  1147.  
  1148.     if (self.weapon == IT_AXE)
  1149.         return TRUE;
  1150.     
  1151.     self.weapon = W_BestWeapon ();
  1152.  
  1153.     W_SetCurrentAmmo ();
  1154.     
  1155. // drop the weapon down
  1156.     return FALSE;
  1157. };
  1158.  
  1159. /*
  1160. ============
  1161. W_Attack
  1162.  
  1163. An attack impulse can be triggered now
  1164. ============
  1165. */
  1166. void()  player_axe1;
  1167. void()  player_axeb1;
  1168. void()  player_axec1;
  1169. void()  player_axed1;
  1170. void()  player_shot1;
  1171. void()  player_nail1;
  1172. void()  player_light1;
  1173. void()  player_rocket1;
  1174.  
  1175. void() W_Attack =
  1176. {
  1177.     local   float   r;
  1178.  
  1179.     if (!W_CheckNoAmmo ())
  1180.         return;
  1181.  
  1182.     makevectors     (self.v_angle);                 // calculate forward angle for velocity
  1183.     self.show_hostile = time + 1;   // wake monsters up
  1184.  
  1185.     if (self.weapon == IT_AXE)
  1186.     {
  1187.         sound (self, CHAN_WEAPON, "weapons/ax1.wav", 1, ATTN_NORM);
  1188.         r = random();
  1189.         if (r < 0.25)
  1190.             player_axe1 ();
  1191.         else if (r<0.5)
  1192.             player_axeb1 ();
  1193.         else if (r<0.75)
  1194.             player_axec1 ();
  1195.         else
  1196.             player_axed1 ();
  1197.         self.attack_finished = time + 0.5;
  1198.     }
  1199.     else if (self.weapon == IT_SHOTGUN)
  1200.     {
  1201.         player_shot1 ();
  1202.         W_FireShotgun ();
  1203.         self.attack_finished = time + 0.5;
  1204.     }
  1205.     else if (self.weapon == IT_SUPER_SHOTGUN)
  1206.     {
  1207.         player_shot1 ();
  1208.         W_FireSuperShotgun ();
  1209.         self.attack_finished = time + 0.7;
  1210.     }
  1211.     else if (self.weapon == IT_NAILGUN)
  1212.     {
  1213.         player_nail1 ();
  1214.     }
  1215.     else if (self.weapon == IT_SUPER_NAILGUN)
  1216.     {
  1217.         player_nail1 ();
  1218.     }
  1219.     else if (self.weapon == IT_GRENADE_LAUNCHER)
  1220.     {
  1221.         player_rocket1();
  1222.         W_FireGrenade();
  1223.         self.attack_finished = time + 0.6;
  1224.     }
  1225.     else if (self.weapon == IT_ROCKET_LAUNCHER)
  1226.     {
  1227.         player_rocket1();
  1228.         W_FireRocket();
  1229.         self.attack_finished = time + 0.8;
  1230.     }
  1231.     else if (self.weapon == IT_LIGHTNING)
  1232.     {
  1233.         player_light1();
  1234.         self.attack_finished = time + 0.1;
  1235.         sound (self, CHAN_AUTO, "weapons/lstart.wav", 1, ATTN_NORM);
  1236.     }
  1237.     else if (self.weapon == IT_FIREWALL)
  1238.     {
  1239.         W_LaunchBouncer();
  1240.         self.attack_finished = time + 0.8;
  1241.     }
  1242.     else if (self.weapon == IT_BOMB)
  1243.     {
  1244.         W_FireBomb();
  1245.         self.attack_finished = time + 0.8;
  1246.     }    
  1247. };
  1248.  
  1249. /*
  1250. ============
  1251. W_ChangeWeapon
  1252.  
  1253. ============
  1254. */
  1255. void() W_ChangeWeapon =
  1256. {
  1257.     local   float   it, am, fl;
  1258.     
  1259.     it = self.items;
  1260.     am = 0;
  1261.     
  1262.     if (self.impulse == 1)
  1263.     {
  1264.         fl = IT_AXE;
  1265.     }
  1266.     else if (self.impulse == 2)
  1267.     {
  1268.         fl = IT_SHOTGUN;
  1269.         if (self.ammo_shells < 1)
  1270.             am = 1;
  1271.     }
  1272.     else if (self.impulse == 3)
  1273.     {
  1274.         fl = IT_SUPER_SHOTGUN;
  1275.         if (self.ammo_shells < 2)
  1276.             am = 1;
  1277.     }               
  1278.     else if (self.impulse == 4)
  1279.     {
  1280.         fl = IT_NAILGUN;
  1281.         if (self.ammo_nails < 1)
  1282.             am = 1;
  1283.     }
  1284.     else if (self.impulse == 5)
  1285.     {
  1286.         fl = IT_SUPER_NAILGUN;
  1287.         if (self.ammo_nails < 2)
  1288.             am = 1;
  1289.     }
  1290.     else if (self.impulse == 6)
  1291.     {
  1292.         if (self.weapon == IT_GRENADE_LAUNCHER)
  1293.         { 
  1294.             self.weapon = IT_FIREWALL;
  1295.             sprint(self,"Firewall mode\n");
  1296.             return;
  1297.         } 
  1298.         if (self.weapon == IT_FIREWALL)
  1299.         {
  1300.             self.weapon = IT_BOMB;
  1301.             sprint(self,"Proximity mine mode\n");
  1302.             return;
  1303.         }  
  1304.         sprint(self,"Grenade Launcher Mode\n");
  1305.         
  1306.         fl = IT_GRENADE_LAUNCHER;
  1307.         if (self.ammo_rockets < 1)
  1308.             am = 1;
  1309.     }
  1310.     else if (self.impulse == 7)
  1311.     {
  1312.         fl = IT_ROCKET_LAUNCHER;
  1313.         if (self.ammo_rockets < 1)
  1314.             am = 1;
  1315.     }
  1316.     else if (self.impulse == 8)
  1317.     {
  1318.         fl = IT_LIGHTNING;
  1319.         if (self.ammo_cells < 1)
  1320.             am = 1;
  1321.     }
  1322.  
  1323.     self.impulse = 0;
  1324.     
  1325.     if (!(self.items & fl))
  1326.     {       // don't have the weapon or the ammo
  1327.         sprint (self, "no weapon.\n");
  1328.         return;
  1329.     }
  1330.     
  1331.     if (am)
  1332.     {       // don't have the ammo
  1333.         sprint (self, "not enough ammo.\n");
  1334.         return;
  1335.     }
  1336.  
  1337. //
  1338. // set weapon, set ammo
  1339. //
  1340.     self.weapon = fl;               
  1341.     W_SetCurrentAmmo ();
  1342. };
  1343.  
  1344. /*
  1345. ============
  1346. CheatCommand
  1347. ============
  1348. */
  1349. void() CheatCommand =
  1350. {
  1351.     if (deathmatch || coop)
  1352.         return;
  1353.  
  1354.     self.ammo_rockets = 100;
  1355.     self.ammo_nails = 200;
  1356.     self.ammo_shells = 100;
  1357.     self.items = self.items | 
  1358.         IT_AXE |
  1359.         IT_SHOTGUN |
  1360.         IT_SUPER_SHOTGUN |
  1361.         IT_NAILGUN |
  1362.         IT_SUPER_NAILGUN |
  1363.         IT_GRENADE_LAUNCHER |
  1364.         IT_ROCKET_LAUNCHER |
  1365.         IT_KEY1 | IT_KEY2;
  1366.  
  1367.     self.ammo_cells = 200;
  1368.     self.items = self.items | IT_LIGHTNING;
  1369.  
  1370.     self.weapon = IT_ROCKET_LAUNCHER;
  1371.     self.impulse = 0;
  1372.     W_SetCurrentAmmo ();
  1373. };
  1374.  
  1375. /*
  1376. ============
  1377. CycleWeaponCommand
  1378.  
  1379. Go to the next weapon with ammo
  1380. ============
  1381. */
  1382. void() CycleWeaponCommand =
  1383. {
  1384.     local   float   it, am;
  1385.     
  1386.     it = self.items;
  1387.     self.impulse = 0;
  1388.     
  1389.     while (1)
  1390.     {
  1391.         am = 0;
  1392.  
  1393.         if (self.weapon == IT_LIGHTNING)
  1394.         {
  1395.             self.weapon = IT_AXE;
  1396.         }
  1397.         else if (self.weapon == IT_AXE)
  1398.         {
  1399.             self.weapon = IT_SHOTGUN;
  1400.             if (self.ammo_shells < 1)
  1401.                 am = 1;
  1402.         }
  1403.         else if (self.weapon == IT_SHOTGUN)
  1404.         {
  1405.             self.weapon = IT_SUPER_SHOTGUN;
  1406.             if (self.ammo_shells < 2)
  1407.                 am = 1;
  1408.         }               
  1409.         else if (self.weapon == IT_SUPER_SHOTGUN)
  1410.         {
  1411.             self.weapon = IT_NAILGUN;
  1412.             if (self.ammo_nails < 1)
  1413.                 am = 1;
  1414.         }
  1415.         else if (self.weapon == IT_NAILGUN)
  1416.         {
  1417.             self.weapon = IT_SUPER_NAILGUN;
  1418.             if (self.ammo_nails < 2)
  1419.                 am = 1;
  1420.         }
  1421.         else if (self.weapon == IT_SUPER_NAILGUN)
  1422.         {
  1423.             self.weapon = IT_GRENADE_LAUNCHER;
  1424.             if (self.ammo_rockets < 1)
  1425.                 am = 1;
  1426.         }
  1427.         else if (self.weapon == IT_GRENADE_LAUNCHER)
  1428.         {
  1429.             self.weapon = IT_ROCKET_LAUNCHER;
  1430.             if (self.ammo_rockets < 1)
  1431.                 am = 1;
  1432.         }
  1433.         else if (self.weapon == IT_ROCKET_LAUNCHER)
  1434.         {
  1435.             self.weapon = IT_LIGHTNING;
  1436.             if (self.ammo_cells < 1)
  1437.                 am = 1;
  1438.         }
  1439.     
  1440.         if ( (self.items & self.weapon) && am == 0)
  1441.         {
  1442.             W_SetCurrentAmmo ();
  1443.             return;
  1444.         }
  1445.     }
  1446.  
  1447. };
  1448.  
  1449. /*
  1450. ============
  1451. ServerflagsCommand
  1452.  
  1453. Just for development
  1454. ============
  1455. */
  1456. void() ServerflagsCommand =
  1457. {
  1458.     serverflags = serverflags * 2 + 1;
  1459. };
  1460.  
  1461. void() QuadCheat =
  1462. {
  1463.     if (deathmatch || coop)
  1464.         return;
  1465.     self.super_time = 1;
  1466.     self.super_damage_finished = time + 30;
  1467.     self.items = self.items | IT_QUAD;
  1468.     dprint ("quad cheat\n");
  1469. };
  1470.  
  1471. /*
  1472. ============
  1473. ImpulseCommands
  1474.  
  1475. ============
  1476. */
  1477. void() ImpulseCommands =
  1478. {
  1479.     if (self.impulse >= 1 && self.impulse <= 8)
  1480.         W_ChangeWeapon ();
  1481.  
  1482.     if (self.impulse == 9)
  1483.         CheatCommand ();
  1484.     if (self.impulse == 10)
  1485.         CycleWeaponCommand ();
  1486.     if (self.impulse == 11)
  1487.         ServerflagsCommand ();
  1488.     
  1489.     // PATCH FOR BOUNCERS
  1490.     if (self.impulse == 20)
  1491.         W_LaunchBouncer ();
  1492.     if (self.impulse == 21)
  1493.         W_FireBomb ();
  1494.     
  1495.     if (self.impulse == 255)
  1496.         QuadCheat ();
  1497.         
  1498.     self.impulse = 0;
  1499. };
  1500.  
  1501. /*
  1502. ============
  1503. W_WeaponFrame
  1504.  
  1505. Called every frame so impulse events can be handled as well as possible
  1506. ============
  1507. */
  1508. void() W_WeaponFrame =
  1509. {
  1510.     if (time < self.attack_finished)
  1511.         return;
  1512.  
  1513.     ImpulseCommands ();
  1514.     
  1515. // check for attack
  1516.     if (self.button0)
  1517.     {
  1518.         SuperDamageSound ();
  1519.         W_Attack ();
  1520.     }
  1521. };
  1522.  
  1523. /*
  1524. ========
  1525. SuperDamageSound
  1526.  
  1527. Plays sound if needed
  1528. ========
  1529. */
  1530. void() SuperDamageSound =
  1531. {
  1532.     if (self.super_damage_finished > time)
  1533.     {
  1534.         if (self.super_sound < time)
  1535.         {
  1536.             self.super_sound = time + 1;
  1537.             sound (self, CHAN_BODY, "items/damage3.wav", 1, ATTN_NORM);
  1538.         }
  1539.     }
  1540.     return;
  1541. };
  1542.  
  1543.  
  1544. /***********************************************************************************
  1545. ================
  1546. W_FireBomb
  1547. ================
  1548. ************************************************************************************/
  1549. void() W_FireBomb =
  1550. {
  1551.     local   entity missile, mpuff;
  1552.  
  1553.     if ((self.ammo_rockets < 5) || (self.weapon != IT_BOMB))
  1554.     {
  1555.         return;
  1556.     }
  1557.  
  1558.  
  1559.     if (bombtimer >0 )
  1560.     {
  1561.         return;
  1562.     }
  1563.     else     bombtimer=1.5;
  1564.  
  1565.  
  1566.     self.currentammo = self.ammo_rockets = self.ammo_rockets - 5;
  1567.     
  1568.  
  1569.  
  1570.     self.punchangle_x = -10;
  1571.  
  1572.     missile = spawn ();
  1573.     missile.owner = self;
  1574.     missile.movetype = MOVETYPE_FLY;
  1575.     missile.solid = SOLID_TRIGGER;
  1576.     missile.classname = "Bomb";
  1577.         
  1578. // set missile speed    
  1579.  
  1580.     makevectors (self.v_angle);
  1581.  
  1582.  
  1583.     missile.velocity= '0 0 0';
  1584.     missile.avelocity= '0 0 0';
  1585.     
  1586.     missile.touch = BombTouch;
  1587.     
  1588. // set missile duration
  1589.     missile.nextthink = time + 0.25;
  1590.     missile.think = BombTime;
  1591.  
  1592.     setmodel (missile, "progs/grenade.mdl");
  1593.     setsize (missile, '-48 -48 -4', '48 48 4');            
  1594.     setorigin (missile, self.origin - '0 0 20');
  1595. //    sprint(self,"Better stay the hell clear now\n");
  1596. };
  1597.  
  1598. void() BombTime =
  1599. {
  1600.     bombtimer = bombtimer - 0.25;
  1601.     if (bombtimer)
  1602.         {
  1603.         if (bombtimer == 0.5) self.velocity='0 0 24';
  1604.         sound (self, CHAN_WEAPON, "weapons/bounce.wav", 1, ATTN_NORM);  // bounce sound
  1605.         self.nextthink = time + 0.25;
  1606.         self.think = BombTime;
  1607.         } 
  1608.     else
  1609.     {
  1610.         self.nextthink = time + 180;
  1611.         self.think = BecomeExplosion;
  1612.         self.classname = "ArmedBomb";
  1613.         self.velocity='0 0 0';
  1614.         self.avelocity='0 800 800';
  1615.         
  1616.         self.health = 20;
  1617.         self.th_die = BombExplode;
  1618.         self.takedamage = DAMAGE_AIM;
  1619.  
  1620.     }
  1621. };
  1622.  
  1623. void() BombTouch =
  1624. {
  1625.     if (other.takedamage && (self.classname == "ArmedBomb") && (other.classname != "ArmedBomb"))
  1626.     {
  1627.         BombExplode();
  1628.         return;
  1629.     }
  1630.  
  1631. };
  1632.  
  1633. void() BombExplode =
  1634. {
  1635.     T_RadiusDamage (self, self.owner, 120, world);
  1636.     T_RadiusDamage (self, self.owner, 120, world);
  1637.  
  1638.     WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  1639.     WriteByte (MSG_BROADCAST, TE_EXPLOSION);
  1640.     WriteCoord (MSG_BROADCAST, self.origin_x);
  1641.     WriteCoord (MSG_BROADCAST, self.origin_y);
  1642.     WriteCoord (MSG_BROADCAST, self.origin_z);
  1643.     WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  1644.     WriteByte (MSG_BROADCAST, TE_EXPLOSION);
  1645.     WriteCoord (MSG_BROADCAST, self.origin_x);
  1646.     WriteCoord (MSG_BROADCAST, self.origin_y);
  1647.     WriteCoord (MSG_BROADCAST, self.origin_z);
  1648.  
  1649.     BombExplosion ();
  1650. };
  1651.  
  1652. void() BombExplosion =
  1653. {
  1654.     sound (self, CHAN_AUTO, "items/damage2.wav", 1, ATTN_NORM);
  1655.     self.movetype = MOVETYPE_NONE;
  1656.     self.velocity = '0 0 0';
  1657.     self.touch = SUB_Null;
  1658.     setmodel (self, "progs/s_explod.spr");
  1659.     self.solid = SOLID_NOT;
  1660.     s_explode1 ();
  1661. };
  1662.  
  1663. void() ShrapnelExplode =
  1664. {
  1665.     T_RadiusDamage (self, self.owner, 120, world);
  1666.  
  1667.     WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  1668.     WriteByte (MSG_BROADCAST, TE_EXPLOSION);
  1669.     WriteCoord (MSG_BROADCAST, self.origin_x);
  1670.     WriteCoord (MSG_BROADCAST, self.origin_y);
  1671.     WriteCoord (MSG_BROADCAST, self.origin_z);
  1672.  
  1673.     BecomeExplosion ();
  1674. };
  1675.