home *** CD-ROM | disk | FTP | other *** search
/ Quake 'em / QUAKEEM.BIN / quake / programs / racnab20 / racnab20.qc < prev    next >
Encoding:
Text File  |  1996-08-06  |  41.4 KB  |  1,835 lines

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