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