home *** CD-ROM | disk | FTP | other *** search
/ Quake 'em / QUAKEEM.BIN / quake / programs / skarmod3 / weapons.qc < prev    next >
Encoding:
Text File  |  1996-08-18  |  54.9 KB  |  2,529 lines

  1. /*
  2.   - Weapons.qc modified by Skarsnik. v. 1.2
  3.  
  4.  - Impulse 1 = Axe.
  5.  - Impulse 2 = Shotgun/Double barrel shotgun.
  6.  - Impulse 3 = Pipe bomb launcher/trigger pipebombs.
  7.  - Impulse 4 = Nailgun.
  8.  - Impulse 5 = Super-Nailgun.
  9.  - Impulse 6 = Grenade/Nail bomb launcher.
  10.  - Impulse 7 = Rocket/Homer launcher.
  11.  - Impulse 8 = Lightning gun.
  12.  - Impulse 9 = Laser.
  13.  - Impulse 12 = Cheat. 
  14.  - Impulse 13 = Fire a flare.
  15.  - Impulse 20 = Throw backpack with some ammo.
  16.  - Impulse 50 = Hologram (costs 10 power cells).
  17.  - Impulse 200 = Change skin (forward).
  18.  - Impulse 201 = Change skin (backwards).
  19.  - Impulse 254 = Fiend cheat.
  20.  - Impulse 255 = Quad cheat.
  21.  
  22.  More things added like:
  23.  
  24.   - Splat sound for axe.
  25.   - Zombies on walls are now gibbable.
  26.   - Lots more.. see skarmod*.txt for more info.
  27.  
  28. */
  29. void (entity targ, entity inflictor, entity attacker, float damage) T_Damage;
  30. void () player_run;
  31. void(entity bomb, entity attacker, float rad, entity ignore) T_RadiusDamage;
  32. void(vector org, vector vel, float damage) SpawnBlood;
  33. void() SuperDamageSound;
  34.  
  35. // called by worldspawn
  36. void() W_Precache =
  37. {
  38.  
  39.         precache_model ("shelcase.mdl"); // Shell casing.
  40.         precache_sound ("shellhit.wav");  // Shell Casing.
  41.         precache_model ("progs/pipebomb.mdl"); //Pipebomb
  42.     precache_model ("progs/v_pipe.mdl"); //Pipebomb launcher!
  43.         precache_model ("progs/g_laser.mdl"); //Laser Gun!
  44.     precache_model ("progs/laser.mdl"); // Enforcer laser for flare
  45.     precache_sound ("misc/power.wav");  // new rocket explosion
  46.         precache_model ("progs/quaddama.mdl");    //laser bolt
  47.         precache_sound ("enforcer/enfire.wav");  // laser
  48.         precache_sound ("enforcer/enfstop.wav"); // enforcer something
  49.         precache_sound ("zombie/z_miss.wav");  // axe splat
  50.         precache_sound ("weapons/r_exp3.wav");    // new rocket explosion
  51.     precache_sound ("weapons/rocket1i.wav");    // spike gun
  52.     precache_sound ("weapons/sgun1.wav");
  53.     precache_sound ("weapons/guncock.wav");    // player shotgun
  54.     precache_sound ("weapons/ric1.wav");    // ricochet (used in c code)
  55.     precache_sound ("weapons/ric2.wav");    // ricochet (used in c code)
  56.     precache_sound ("weapons/ric3.wav");    // ricochet (used in c code)
  57.     precache_sound ("weapons/spike2.wav");    // super spikes
  58.     precache_sound ("weapons/tink1.wav");    // spikes tink (used in c code)
  59.     precache_sound ("weapons/grenade.wav");    // grenade launcher
  60.     precache_sound ("weapons/bounce.wav");        // grenade bounce
  61.     precache_sound ("weapons/shotgn2.wav");    // super shotgun
  62. };
  63.  
  64. float() crandom =
  65. {
  66.     return 2*(random() - 0.5);
  67. };
  68. /*
  69. ================
  70. W_FireAxe
  71. ================
  72. */
  73. void() W_FireAxe =
  74. {
  75.     local    vector    source;
  76.     local    vector    org;
  77.  
  78.     source = self.origin + '0 0 16';
  79.     traceline (source, source + v_forward*64, FALSE, self);
  80.     if (trace_fraction == 1.0)
  81.         return;
  82.     
  83.     org = trace_endpos - v_forward*4;
  84.  
  85.     if (trace_ent.takedamage)
  86.     {
  87.         trace_ent.axhitme = 1;
  88.         SpawnBlood (org, '0 0 0', 20);
  89.                 sound (self, CHAN_WEAPON, "zombie/z_miss.wav", 1, ATTN_NORM);
  90.         T_Damage (trace_ent, self, self, 20);
  91.     }
  92.     else
  93.     {    // hit wall
  94.         sound (self, CHAN_WEAPON, "player/axhit2.wav", 1, ATTN_NORM);
  95.         WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  96.         WriteByte (MSG_BROADCAST, TE_GUNSHOT);
  97.         WriteCoord (MSG_BROADCAST, org_x);
  98.         WriteCoord (MSG_BROADCAST, org_y);
  99.         WriteCoord (MSG_BROADCAST, org_z);
  100.     }
  101. };
  102.  
  103.  
  104. //============================================================================
  105.  
  106.  
  107. vector() wall_velocity =
  108. {
  109.     local vector    vel;
  110.     
  111.     vel = normalize (self.velocity);
  112.     vel = normalize(vel + v_up*(random()- 0.5) + v_right*(random()- 0.5));
  113.     vel = vel + 2*trace_plane_normal;
  114.     vel = vel * 200;
  115.     
  116.     return vel;
  117. };
  118.  
  119.  
  120. /*
  121. ================
  122. SpawnMeatSpray
  123. ================
  124. */
  125. void(vector org, vector vel) SpawnMeatSpray =
  126. {
  127.     local    entity missile, mpuff;
  128.     local    vector    org;
  129.  
  130.     missile = spawn ();
  131.     missile.owner = self;
  132.     missile.movetype = MOVETYPE_BOUNCE;
  133.     missile.solid = SOLID_NOT;
  134.  
  135.     makevectors (self.angles);
  136.  
  137.     missile.velocity = vel;
  138.     missile.velocity_z = missile.velocity_z + 250 + 50*random();
  139.  
  140.     missile.avelocity = '3000 1000 2000';
  141.     
  142. // set missile duration
  143.     missile.nextthink = time + 1;
  144.     missile.think = SUB_Remove;
  145.  
  146.     setmodel (missile, "progs/zom_gib.mdl");
  147.     setsize (missile, '0 0 0', '0 0 0');        
  148.     setorigin (missile, org);
  149. };
  150.  
  151. /*
  152. ================
  153. SpawnBlood
  154. ================
  155. */
  156. void(vector org, vector vel, float damage) SpawnBlood =
  157. {
  158.     particle (org, vel*0.1, 73, damage*2);
  159. };
  160.  
  161. /*
  162. ================
  163. spawn_touchblood
  164. ================
  165. */
  166. void(float damage) spawn_touchblood =
  167. {
  168.     local vector    vel;
  169.  
  170.     vel = wall_velocity () * 0.2;
  171.     SpawnBlood (self.origin + vel*0.01, vel, damage);
  172. };
  173.  
  174.  
  175. /*
  176. ================
  177. SpawnChunk
  178. ================
  179. */
  180. void(vector org, vector vel) SpawnChunk =
  181. {
  182.     particle (org, vel*0.02, 0, 10);
  183. };
  184.  
  185. /*
  186. ==============================================================================
  187.  
  188. MULTI-DAMAGE
  189.  
  190. Collects multiple small damages into a single damage
  191.  
  192. ==============================================================================
  193. */
  194.  
  195. entity    multi_ent;
  196. float    multi_damage;
  197.  
  198. void() ClearMultiDamage =
  199. {
  200.     multi_ent = world;
  201.     multi_damage = 0;
  202. };
  203.  
  204. void() ApplyMultiDamage =
  205. {
  206.     if (!multi_ent)
  207.         return;
  208.     T_Damage (multi_ent, self, self, multi_damage);
  209. };
  210.  
  211. void(entity hit, float damage) AddMultiDamage =
  212. {
  213.     if (!hit)
  214.         return;
  215.     
  216.     if (hit != multi_ent)
  217.     {
  218.         ApplyMultiDamage ();
  219.         multi_damage = damage;
  220.         multi_ent = hit;
  221.     }
  222.     else
  223.         multi_damage = multi_damage + damage;
  224. };
  225.  
  226. /*
  227. ==============================================================================
  228.  
  229. BULLETS
  230.  
  231. ==============================================================================
  232. */
  233.  
  234. /*
  235. ================
  236. TraceAttack
  237. ================
  238. */
  239. void(float damage, vector dir) TraceAttack =
  240. {
  241.     local    vector    vel, org;
  242.     
  243.     vel = normalize(dir + v_up*crandom() + v_right*crandom());
  244.     vel = vel + 2*trace_plane_normal;
  245.     vel = vel * 200;
  246.  
  247.     org = trace_endpos - dir*4;
  248.  
  249.     if (trace_ent.takedamage)
  250.     {
  251.         SpawnBlood (org, vel*0.2, damage);
  252.         AddMultiDamage (trace_ent, damage);
  253.     }
  254.     else
  255.     {
  256.         WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  257.         WriteByte (MSG_BROADCAST, TE_GUNSHOT);
  258.         WriteCoord (MSG_BROADCAST, org_x);
  259.         WriteCoord (MSG_BROADCAST, org_y);
  260.         WriteCoord (MSG_BROADCAST, org_z);
  261.     }
  262. };
  263.  
  264. /*
  265. ================
  266. FireBullets
  267.  
  268. Used by shotgun, super shotgun, and enemy soldier firing
  269. Go to the trouble of combining multiple pellets into a single damage call.
  270. ================
  271. */
  272. void(float shotcount, vector dir, vector spread) FireBullets =
  273. {
  274.     local    vector direction;
  275.     local    vector    src;
  276.     
  277.     makevectors(self.v_angle);
  278.  
  279.     src = self.origin + v_forward*10;
  280.     src_z = self.absmin_z + self.size_z * 0.7;
  281.  
  282.     ClearMultiDamage ();
  283.     while (shotcount > 0)
  284.     {
  285.         direction = dir + crandom()*spread_x*v_right + crandom()*spread_y*v_up;
  286.  
  287.         traceline (src, src + direction*2048, FALSE, self);
  288.         if (trace_fraction != 1.0)
  289.             TraceAttack (4, direction);
  290.  
  291.         shotcount = shotcount - 1;
  292.     }
  293.     ApplyMultiDamage ();
  294. };
  295.  
  296. /*
  297. ================
  298. W_FireShotgun
  299. ================
  300. */
  301.  
  302. void() W_FireShotgun =
  303. {
  304.     local vector dir;
  305.  
  306.     sound (self, CHAN_WEAPON, "weapons/guncock.wav", 1, ATTN_NORM);    
  307.  
  308.     self.punchangle_x = -2;
  309.     
  310.     self.currentammo = self.ammo_shells = self.ammo_shells - 1;
  311.     dir = aim (self, 100000);
  312.  
  313.         eject_shell (self.origin + '0 0 16' + v_forward*3,dir); // ADDED FOR EJECT.QC
  314.  
  315.     FireBullets (6, dir, '0.04 0.04 0');
  316. };
  317.  
  318.  
  319.  
  320. /*
  321. ================
  322. W_FireSuperShotgun
  323. ================
  324. */
  325. void() W_FireSuperShotgun =
  326. {
  327.     local vector dir;
  328.  
  329.     if (self.currentammo == 1)
  330.     {
  331.         W_FireShotgun ();
  332.         return;
  333.     }
  334.         
  335.     sound (self ,CHAN_WEAPON, "weapons/shotgn2.wav", 1, ATTN_NORM);    
  336.  
  337.     self.punchangle_x = -4;
  338.     
  339.     self.currentammo = self.ammo_shells = self.ammo_shells - 2;
  340.     dir = aim (self, 100000);
  341.  
  342.     eject_shell (self.origin + '0 0 16' + v_forward*3,dir); // ADDED FOR EJECT.QC
  343.         eject_shell (self.origin + '0 0 16' + v_forward*3,dir); // ADDED FOR EJECT.QC
  344.  
  345.     FireBullets (14, dir, '0.14 0.08 0');
  346. };
  347.  
  348.  
  349. /*
  350. ==============================================================================
  351.  
  352. ROCKETS
  353.  
  354. ==============================================================================
  355. */
  356.  
  357. void()    s_explode1    =    [0,        s_explode2] {};
  358. void()    s_explode2    =    [1,        s_explode3] {};
  359. void()    s_explode3    =    [2,        s_explode4] {};
  360. void()    s_explode4    =    [3,        s_explode5] {};
  361. void()    s_explode5    =    [4,        s_explode6] {};
  362. void()    s_explode6    =    [5,        SUB_Remove] {};
  363.  
  364. void() BecomeExplosion =
  365. {
  366.     self.movetype = MOVETYPE_NONE;
  367.     self.velocity = '0 0 0';
  368.     self.touch = SUB_Null;
  369.     setmodel (self, "progs/s_explod.spr");
  370.     self.solid = SOLID_NOT;
  371.     s_explode1 ();
  372. };
  373.  
  374. void() T_MissileTouch =
  375. {
  376.     local float    damg;
  377.  
  378.     if (other == self.owner)
  379.         return;        // don't explode on owner
  380.  
  381.     if (pointcontents(self.origin) == CONTENT_SKY)
  382.     {
  383.         remove(self);
  384.         return;
  385.     }
  386.  
  387.     damg = 100 + random()*20;
  388.     
  389.     if (other.health)
  390.     {
  391.         if (other.classname == "monster_shambler")
  392.             damg = damg * 0.5;    // mostly immune
  393.         T_Damage (other, self, self.owner, damg );
  394.     }
  395.  
  396.     // don't do radius damage to the other, because all the damage
  397.     // was done in the impact
  398.     T_RadiusDamage (self, self.owner, 120, other);
  399.  
  400. //    sound (self, CHAN_WEAPON, "weapons/r_exp3.wav", 1, ATTN_NORM);
  401.     self.origin = self.origin - 8*normalize(self.velocity);
  402.  
  403.     WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  404.     WriteByte (MSG_BROADCAST, TE_EXPLOSION);
  405.     WriteCoord (MSG_BROADCAST, self.origin_x);
  406.     WriteCoord (MSG_BROADCAST, self.origin_y);
  407.     WriteCoord (MSG_BROADCAST, self.origin_z);
  408.  
  409.     BecomeExplosion ();
  410. };
  411.  
  412. /*
  413. ================
  414. W_FireRocket
  415. ================
  416. */
  417. void() W_FireRocket =
  418. {
  419.     local    entity missile, mpuff;
  420.     
  421.     self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
  422.     
  423.     sound (self, CHAN_WEAPON, "weapons/sgun1.wav", 1, ATTN_NORM);
  424.  
  425.     self.punchangle_x = -2;
  426.  
  427.     missile = spawn ();
  428.     missile.owner = self;
  429.     missile.movetype = MOVETYPE_FLYMISSILE;
  430.     missile.solid = SOLID_BBOX;
  431.         
  432. // set missile speed    
  433.  
  434.     makevectors (self.v_angle);
  435.     missile.velocity = aim(self, 1000);
  436.     missile.velocity = missile.velocity * 1000;
  437.     missile.angles = vectoangles(missile.velocity);
  438.     
  439.     missile.touch = T_MissileTouch;
  440.     
  441. // set missile duration
  442.     missile.nextthink = time + 5;
  443.     missile.think = SUB_Remove;
  444.  
  445.     setmodel (missile, "progs/missile.mdl");
  446.     setsize (missile, '0 0 0', '0 0 0');        
  447.     setorigin (missile, self.origin + v_forward*8 + '0 0 16');
  448. };
  449.  
  450.  
  451.  
  452. /*
  453. ================
  454. W_FireHomer
  455. ================
  456. */
  457. void()   HomeThink;
  458. entity() HomeFindTarget;
  459. float(entity targ) visible;
  460. float(entity targ) infront;
  461.  
  462. void() W_FireHomer =
  463.  
  464. {
  465.  
  466. // If player doesn't have 5 or more rockets, don't launch
  467.  
  468.     if (self.ammo_rockets < 5)
  469.  
  470.     {
  471.  
  472.     return;
  473.  
  474.     }
  475.  
  476.  
  477.  
  478.     local    entity missile, mpuff;
  479.  
  480.         if (self.currentammo < 5)
  481.                self.currentammo = self.ammo_rockets = 0;
  482.         else                
  483.                self.currentammo = self.ammo_rockets = self.ammo_rockets - 5;
  484.     
  485.     sound (self, CHAN_WEAPON, "weapons/sgun1.wav", 1, ATTN_NORM);
  486.  
  487.     self.punchangle_x = -2;
  488.  
  489.     missile = spawn ();
  490.     missile.owner = self;
  491.     missile.movetype = MOVETYPE_FLYMISSILE;
  492.     missile.solid = SOLID_BBOX;
  493.         missile.classname = "arocket";
  494.         
  495. // set missile speed    
  496.  
  497.     makevectors (self.v_angle);
  498.     missile.velocity = aim(self, 1000);
  499.     missile.velocity = missile.velocity * 300;
  500.     missile.angles = vectoangles(missile.velocity);
  501.     
  502.     missile.touch = T_MissileTouch;
  503.     
  504. // set missile duration
  505. //    missile.nextthink = time + 30;
  506. //    missile.think = SUB_Remove;
  507.  
  508.     missile.nextthink = time + 0.2;
  509.     missile.think = HomeThink;
  510.     missile.enemy = world;
  511.  
  512.     setmodel (missile, "progs/missile.mdl");
  513.     setsize (missile, '0 0 0', '0 0 0');        
  514.     setorigin (missile, self.origin + v_forward*8 + '0 0 16');
  515. };
  516.  
  517. entity() HomeFindTarget = 
  518. {
  519.     local entity head, selected;
  520.     local float dist;
  521.     dist = 100000;
  522.     selected = world;
  523.     head = findradius(self.origin, 100000);
  524.     while(head)
  525.     {
  526.                 if( (head.health > 1) && (head.classname != "misc_explobox") && (head != self) && (head != self.owner) && !(head.items & IT_INVISIBILITY) )
  527.         {
  528.             traceline(self.origin,head.origin,TRUE,self);
  529.             if ( (trace_fraction >= 1) && (vlen(head.origin - self.origin) < dist) )
  530.             {
  531.                 selected = head;
  532.                 dist = vlen(head.origin - self.origin);
  533.             }
  534.         }        
  535.         head = head.chain;
  536.     }
  537.     if (selected != world)
  538.     {
  539.         sprint (self.owner,"Homing->");
  540.         if (selected.classname == "player")
  541.         {
  542.             sprint (self.owner,selected.netname);
  543.             sprint (selected,self.owner.netname);
  544.             sprint (selected," has a HOMER on you!\n");
  545.         }
  546.         else
  547.             sprint (self.owner,selected.classname);
  548.         sprint (self.owner,"\n");
  549.     }
  550.     return selected;
  551. };
  552.  
  553. void() HomeThink =
  554. {
  555.         local vector dir, olddir, vtemp;
  556.         local float turnrate;
  557.  
  558.         turnrate= 0.2;
  559.     if ( !(self.enemy) || (self.enemy == world) || (self.enemy.health < 1) )
  560.         self.enemy = HomeFindTarget();
  561.  
  562.     if (self.enemy != world) // Arr.. don't be taken on da World!
  563.     {
  564.         vtemp = self.enemy.origin + '0 0 10';
  565.                 olddir = normalize(self.velocity);
  566.         dir = normalize(vtemp - self.origin);
  567.                 //Limits the turnrate of the rockets
  568.                 if (olddir_x - dir_x > turnrate)
  569.                         dir_x = olddir_x - turnrate;
  570.                 if (olddir_x - dir_x < -1 * turnrate)
  571.                         dir_x = olddir_x + turnrate;
  572.                 if (olddir_y - dir_y > turnrate)
  573.                         dir_y = olddir_y - turnrate;
  574.                 if (olddir_y - dir_y < -1 * turnrate)
  575.                         dir_y = olddir_y + turnrate;
  576.                 if (olddir_z - dir_z > turnrate)
  577.                         dir_z = olddir_z - turnrate;
  578.                 if (olddir_z - dir_z < -1 * turnrate)
  579.                         dir_z = olddir_z + turnrate;
  580.                 self.velocity = dir * 230;
  581.         self.angles = vectoangles(self.velocity);
  582.     }
  583.  
  584.     self.nextthink = time + 0.2;
  585.     self.think=HomeThink;
  586. };
  587. /*
  588. ===============================================================================
  589.  
  590. LIGHTNING
  591.  
  592. ===============================================================================
  593. */
  594.  
  595. /*
  596. =================
  597. LightningDamage
  598. =================
  599. */
  600. void(vector p1, vector p2, entity from, float damage) LightningDamage =
  601. {
  602.     local entity        e1, e2;
  603.     local vector        f;
  604.     
  605.     f = p2 - p1;
  606.     normalize (f);
  607.     f_x = 0 - f_y;
  608.     f_y = f_x;
  609.     f_z = 0;
  610.     f = f*16;
  611.  
  612.     e1 = e2 = world;
  613.  
  614.     traceline (p1, p2, FALSE, self);
  615.     if (trace_ent.takedamage)
  616.     {
  617.         particle (trace_endpos, '0 0 100', 225, damage*4);
  618.         T_Damage (trace_ent, from, from, damage);
  619.         if (self.classname == "player")
  620.         {
  621.             if (other.classname == "player")
  622.                 trace_ent.velocity_z = trace_ent.velocity_z + 400;
  623.         }
  624.     }
  625.     e1 = trace_ent;
  626.  
  627.     traceline (p1 + f, p2 + f, FALSE, self);
  628.     if (trace_ent != e1 && trace_ent.takedamage)
  629.     {
  630.         particle (trace_endpos, '0 0 100', 225, damage*4);
  631.         T_Damage (trace_ent, from, from, damage);
  632.     }
  633.     e2 = trace_ent;
  634.  
  635.     traceline (p1 - f, p2 - f, FALSE, self);
  636.     if (trace_ent != e1 && trace_ent != e2 && trace_ent.takedamage)
  637.     {
  638.         particle (trace_endpos, '0 0 100', 225, damage*4);
  639.         T_Damage (trace_ent, from, from, damage);
  640.     }
  641. };
  642.  
  643.  
  644. void() W_FireLightning =
  645. {
  646.     local    vector        org;
  647.  
  648.     if (self.ammo_cells < 1)
  649.     {
  650.         self.weapon = W_BestWeapon ();
  651.         W_SetCurrentAmmo ();
  652.         return;
  653.     }
  654.  
  655. // explode if under water
  656.     if (self.waterlevel > 1)
  657.     {
  658.         T_RadiusDamage (self, self, 35*self.ammo_cells, world);
  659.         self.ammo_cells = 0;
  660.         W_SetCurrentAmmo ();
  661.         return;
  662.     }
  663.  
  664.     if (self.t_width < time)
  665.     {
  666.         sound (self, CHAN_WEAPON, "weapons/lhit.wav", 1, ATTN_NORM);
  667.         self.t_width = time + 0.6;
  668.     }
  669.     self.punchangle_x = -2;
  670.  
  671.     self.currentammo = self.ammo_cells = self.ammo_cells - 1;
  672.  
  673.     org = self.origin + '0 0 16';
  674.     
  675.     traceline (org, org + v_forward*600, TRUE, self);
  676.  
  677.     WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  678.     WriteByte (MSG_BROADCAST, TE_LIGHTNING2);
  679.     WriteEntity (MSG_BROADCAST, self);
  680.     WriteCoord (MSG_BROADCAST, org_x);
  681.     WriteCoord (MSG_BROADCAST, org_y);
  682.     WriteCoord (MSG_BROADCAST, org_z);
  683.     WriteCoord (MSG_BROADCAST, trace_endpos_x);
  684.     WriteCoord (MSG_BROADCAST, trace_endpos_y);
  685.     WriteCoord (MSG_BROADCAST, trace_endpos_z);
  686.  
  687.     LightningDamage (self.origin, trace_endpos + v_forward*4, self, 30);
  688. };
  689.  
  690.  
  691. //=============================================================================
  692.  
  693.  
  694. void() GrenadeExplode =
  695. {
  696.     T_RadiusDamage (self, self.owner, 120, world);
  697.  
  698.     WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  699.     WriteByte (MSG_BROADCAST, TE_EXPLOSION);
  700.     WriteCoord (MSG_BROADCAST, self.origin_x);
  701.     WriteCoord (MSG_BROADCAST, self.origin_y);
  702.     WriteCoord (MSG_BROADCAST, self.origin_z);
  703.  
  704.     BecomeExplosion ();
  705. };
  706.  
  707. void() GrenadeTouch =
  708. {
  709.     if (other == self.owner)
  710.         return;        // don't explode on owner
  711.     if (other.takedamage == DAMAGE_AIM)
  712.     {
  713.         GrenadeExplode();
  714.         return;
  715.     }
  716.     sound (self, CHAN_WEAPON, "weapons/bounce.wav", 1, ATTN_NORM);    // bounce sound
  717.     if (self.velocity == '0 0 0')
  718.         self.avelocity = '0 0 0';
  719. };
  720.  
  721. /*
  722. ================
  723. W_FireGrenade
  724. ================
  725. */
  726. void() W_FireGrenade =
  727. {
  728.     local    entity missile, mpuff;
  729.  
  730.     
  731.     sound (self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
  732.  
  733.     self.punchangle_x = -2;
  734.  
  735.     missile = spawn ();
  736.     missile.owner = self;
  737.     missile.movetype = MOVETYPE_BOUNCE;
  738.     missile.solid = SOLID_BBOX;
  739.     missile.classname = "grenade";
  740.         missile.wait = time + 15 + 15*random();
  741.         
  742. // set missile speed    
  743.  
  744.     makevectors (self.v_angle);
  745.  
  746.     if (self.v_angle_x)
  747.         missile.velocity = v_forward*600 + v_up * 200 + crandom()*v_right*10 + crandom()*v_up*10;
  748.     else
  749.     {
  750.         missile.velocity = aim(self, 10000);
  751.         missile.velocity = missile.velocity * 600;
  752.         missile.velocity_z = 200;
  753.     }
  754.  
  755.     missile.avelocity = '300 300 300';
  756.  
  757.     missile.angles = vectoangles(missile.velocity);
  758.     
  759.     missile.touch = GrenadeTouch;
  760.  
  761.         // If we have enough for a cluster, fire a cluster, otherwise
  762.         // fire a bouncer.
  763.         // Uncomment this block for CBP
  764. /*        if (self.ammo_rockets > 4) {
  765.                 self.currentammo = self.ammo_rockets = self.ammo_rockets - 5;
  766.                 missile.nextthink = time + 2+(random()*3);
  767.                 missile.think = GrenadeDeploy;
  768.         }
  769.         else {*/
  770.                 self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
  771.                 missile.nextthink = time + 2.5;
  772.                 missile.think = GrenadeExplode;
  773.                 // Comment the above line and uncomment the next three below
  774.                 // to enable CBP Grenades.
  775.                 // missile.think = GrenadeThink;
  776.                 // missile.nextthink = time + 2+(random()*2);
  777. //        }
  778.  
  779.         setmodel (missile, "progs/grenade.mdl");
  780.     setsize (missile, '0 0 0', '0 0 0');        
  781.     setorigin (missile, self.origin);
  782. };
  783.  
  784.  
  785. //=============================================================================
  786.  
  787.  
  788. void() flare_touch;
  789. void() flare_bright;
  790. void() flare_dim;
  791.  
  792. void() spike_touch;
  793. void() superspike_touch;
  794.  
  795.  
  796.  
  797. /*
  798. =========================================================================
  799. Flares Code Begins Here.
  800. =========================================================================
  801. */
  802. /*
  803. ================================
  804. launch_flare
  805.  
  806. rework of id's launch_spike code
  807. ================================
  808. */
  809. void(vector org, vector dir) launch_flare =
  810. {
  811.     local   entity  missile;
  812.  
  813.     missile = spawn ();
  814.     missile.owner = self;
  815.     missile.movetype = MOVETYPE_FLYMISSILE;
  816.     missile.solid = SOLID_BBOX;
  817.  
  818.     missile.angles = vectoangles(dir);
  819.  
  820. // go to flare_touch if the flare touches anything
  821.     missile.touch = flare_touch;
  822.     missile.classname = "spike";
  823.  
  824. // go to flare_bright when the flare's think time is up    
  825.     missile.think = flare_bright;
  826.  
  827. // 3 seconds until flare goes bright
  828.     missile.nextthink = time + 3;
  829.  
  830. // The LASER.MDL makes a decent flare
  831.     setmodel (missile, "progs/laser.mdl");
  832.     setsize (missile, VEC_ORIGIN, VEC_ORIGIN);        setorigin (missile, org);
  833.     missile.velocity = dir * 1000;
  834.  
  835. // Make the flare dim. (.effects is an 8-bit register)
  836.     missile.effects=8;
  837.  
  838. };
  839. /*
  840. ============================
  841. flare_touch
  842. rework of id's spike_touch()
  843. ============================
  844. */
  845. void() flare_touch =
  846. {
  847. local float rand;
  848.     if (other == self.owner)    
  849.         return;
  850.  
  851.     if (other.solid == SOLID_TRIGGER)
  852.         return; // trigger field, do nothing
  853.  
  854.     if (pointcontents(self.origin) == CONTENT_SKY)
  855.     {
  856.         remove(self);
  857.         return;
  858.     }
  859.     
  860. // has the flare hit something that bleeds?
  861.     if (other.takedamage)
  862.     {
  863.         // If so, spawn some blood
  864.         spawn_touchblood (9);
  865.         // also do one point of damage
  866.         T_Damage (other, self, self.owner, 1);
  867.  
  868. /*
  869. Don't remove the flare unless it is still flying. Otherwise, monsters orother players can come up and 'pull' your flare out of the wall
  870. */
  871.           if (self.velocity != '0 0 0')
  872.             remove(self);
  873.     }
  874.     else
  875.     {
  876.         //Write information to the network
  877.         WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);        WriteByte (MSG_BROADCAST, TE_SPIKE);
  878.         WriteCoord (MSG_BROADCAST, self.origin_x);        WriteCoord (MSG_BROADCAST, self.origin_y);
  879.         WriteCoord (MSG_BROADCAST, self.origin_z);
  880.     }
  881.  
  882. //Stop the flare, but do not remove it.
  883.     self.movetype = MOVETYPE_NONE;
  884.     self.velocity = '0 0 0';
  885.     self.touch = SUB_Null;
  886.  
  887. };
  888. /*
  889. ==============================
  890. flare_bright()
  891. This function makes the flare
  892. emit brighter light
  893. ==============================
  894. */
  895. void() flare_bright =
  896. {
  897.     local vector    vel;
  898. // Make the flare get BRIGHT by setting .effects bit
  899.            self.effects=4;
  900. // Give it 10 seconds at maximum intensity
  901.     self.nextthink = time + 10;
  902. // After 10 seconds, call flare_dim
  903.     self.think = flare_dim;
  904. // Play a sound for flare ignition
  905.     sound (self, CHAN_WEAPON, "misc/power.wav", 1, ATTN_NORM);
  906.  
  907. // Set up some red and yellow sparks
  908.     vel = '0 0 150';
  909.     particle (self.origin+vel*0.01,vel,111,150);
  910.         vel = '0 0 120';
  911.     particle (self.origin+vel*0.01,vel,73,200);
  912. /*
  913. ==============================
  914. flare_dim()
  915. This function makes the flare
  916. go dim again
  917. ==============================
  918. */
  919. };
  920. void() flare_dim =
  921. {
  922. // Make the flare get dim by setting .effects bit
  923.         self.effects=8;
  924. // Give it 15 seconds before burnout
  925.     self.nextthink = time + 15;
  926. // After 15 seconds remove the flare from the game
  927.     self.think = SUB_Remove;
  928. };
  929.  
  930.  
  931. /*
  932. ===================================================================End of Flare Code  -    Steve Bond 8/1/96===================================================================
  933. */
  934.  
  935. /*
  936. ===============
  937. launch_spike
  938.  
  939. Used for both the player and the ogre
  940. ===============
  941. */
  942. void(vector org, vector dir) launch_spike =
  943. {
  944.     newmis = spawn ();
  945.     newmis.owner = self;
  946.     newmis.movetype = MOVETYPE_FLYMISSILE;
  947.     newmis.solid = SOLID_BBOX;
  948.  
  949.     newmis.angles = vectoangles(dir);
  950.     
  951.     newmis.touch = spike_touch;
  952.     newmis.classname = "spike";
  953.     //newmis.think = SUB_Remove;
  954.     newmis.nextthink = time + 6;
  955.     setmodel (newmis, "progs/spike.mdl");
  956.     setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);        
  957.     setorigin (newmis, org);
  958.  
  959.     newmis.velocity = dir * 1000;
  960. };
  961.  
  962. void() W_FireSuperSpikes =
  963. {
  964.     local vector    dir;
  965.     local entity    old;
  966.     
  967.     sound (self, CHAN_WEAPON, "weapons/spike2.wav", 1, ATTN_NORM);
  968.     self.attack_finished = time + 0.2;
  969.     self.currentammo = self.ammo_nails = self.ammo_nails - 2;
  970.     dir = aim (self, 1000);
  971.     launch_spike (self.origin + '0 0 16', dir);
  972.     newmis.touch = superspike_touch;
  973.     setmodel (newmis, "progs/s_spike.mdl");
  974.     setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);        
  975.     self.punchangle_x = -2;
  976. };
  977.  
  978. void(float ox) W_FireFlare =
  979. {
  980.     local vector    dir;
  981.     local entity    old;
  982.  
  983.     makevectors (self.v_angle);
  984.         sound (self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
  985.     self.attack_finished = time + 0.5;
  986.     dir = aim (self, 1000);
  987.     launch_flare (self.origin + '0 0 24' + v_right*ox, dir);
  988.     self.punchangle_x = -2;    dprint ("Flare Away!                      v.9");
  989. };
  990.  
  991.  
  992. void(float ox) W_FireSpikes =
  993. {
  994.     local vector    dir;
  995.     local entity    old;
  996.     
  997.     makevectors (self.v_angle);
  998.     
  999.     if (self.ammo_nails >= 2 && self.weapon == IT_SUPER_NAILGUN)
  1000.     {
  1001.         W_FireSuperSpikes ();
  1002.         return;
  1003.     }
  1004.  
  1005.     if (self.ammo_nails < 1)
  1006.     {
  1007.         self.weapon = W_BestWeapon ();
  1008.         W_SetCurrentAmmo ();
  1009.         return;
  1010.     }
  1011.  
  1012.     sound (self, CHAN_WEAPON, "weapons/rocket1i.wav", 1, ATTN_NORM);
  1013.     self.attack_finished = time + 0.2;
  1014.     self.currentammo = self.ammo_nails = self.ammo_nails - 1;
  1015.     dir = aim (self, 1000);
  1016.     launch_spike (self.origin + '0 0 16' + v_right*ox, dir);
  1017.  
  1018.     self.punchangle_x = -2;
  1019. };
  1020.  
  1021.  
  1022.  
  1023. .float hit_z;
  1024. void() spike_touch =
  1025. {
  1026. local float rand;
  1027.     if (other == self.owner)
  1028.         return;
  1029.  
  1030.     if (other.solid == SOLID_TRIGGER)
  1031.         return;    // trigger field, do nothing
  1032.  
  1033.     if (pointcontents(self.origin) == CONTENT_SKY)
  1034.     {
  1035.         remove(self);
  1036.         return;
  1037.     }
  1038.     
  1039. // hit something that bleeds
  1040.     if (other.takedamage)
  1041.     {
  1042.         spawn_touchblood (9);
  1043.         T_Damage (other, self, self.owner, 9);
  1044.     }
  1045.     else
  1046.     {
  1047.         WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  1048.         
  1049.         if (self.classname == "wizspike")
  1050.             WriteByte (MSG_BROADCAST, TE_WIZSPIKE);
  1051.         else if (self.classname == "knightspike")
  1052.             WriteByte (MSG_BROADCAST, TE_KNIGHTSPIKE);
  1053.         else
  1054.             WriteByte (MSG_BROADCAST, TE_SPIKE);
  1055.         WriteCoord (MSG_BROADCAST, self.origin_x);
  1056.         WriteCoord (MSG_BROADCAST, self.origin_y);
  1057.         WriteCoord (MSG_BROADCAST, self.origin_z);
  1058.     }
  1059.  
  1060.     remove(self);
  1061.  
  1062. };
  1063.  
  1064. void() superspike_touch =
  1065. {
  1066. local float rand;
  1067.     if (other == self.owner)
  1068.         return;
  1069.  
  1070.     if (other.solid == SOLID_TRIGGER)
  1071.         return;    // trigger field, do nothing
  1072.  
  1073.     if (pointcontents(self.origin) == CONTENT_SKY)
  1074.     {
  1075.         remove(self);
  1076.         return;
  1077.     }
  1078.     
  1079. // hit something that bleeds
  1080.     if (other.takedamage)
  1081.     {
  1082.         spawn_touchblood (18);
  1083.         T_Damage (other, self, self.owner, 18);
  1084.     }
  1085.     else
  1086.     {
  1087.         WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  1088.         WriteByte (MSG_BROADCAST, TE_SUPERSPIKE);
  1089.         WriteCoord (MSG_BROADCAST, self.origin_x);
  1090.         WriteCoord (MSG_BROADCAST, self.origin_y);
  1091.         WriteCoord (MSG_BROADCAST, self.origin_z);
  1092.     }
  1093.  
  1094.     remove(self);
  1095.  
  1096. };
  1097.  
  1098. /*
  1099.  ------------------------------------------
  1100.  Pipe Bombs
  1101.  ------------------------------------------
  1102. */
  1103.  
  1104. /*
  1105.  * Blow up the toys.  There is a range of 1000 units (pixels?), so you can't
  1106.  * go wandering off.
  1107.  */
  1108.  
  1109. void() DetPipeBombs =
  1110. {
  1111.         local entity    head;
  1112.  
  1113.         head = findradius (self.origin, 1000);
  1114.         while(head)
  1115.         {
  1116.                 if((head.classname == "pipebomb") && (head.owner == self))
  1117.                         head.nextthink = time;
  1118.                 head = head.chain;
  1119.         }
  1120. };
  1121.  
  1122. /*
  1123.  * What happens if it touches something
  1124.  */
  1125.  
  1126. void() PipeBombTouch =
  1127. {
  1128.     if (other == self.owner)
  1129.         return;        // don't explode on owner
  1130.     sound (self, CHAN_WEAPON, "weapons/bounce.wav", 1, ATTN_NORM);    // bounce sound
  1131.     if (self.velocity == '0 0 0')
  1132.         self.avelocity = '0 0 0';
  1133. };
  1134.  
  1135. /*
  1136.  * Fires a pipe bomb.  Can be detonated at any time.  Doesn't need a special
  1137.  * weapon selected.
  1138.  */
  1139.  
  1140. void() W_FirePipeBomb =
  1141. {
  1142.     local    entity missile, mpuff;
  1143.     
  1144.     if(self.ammo_rockets < 1)    // have to have ammo
  1145.       return;
  1146.     self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
  1147.     
  1148. //    sound (self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
  1149.  
  1150. //    self.punchangle_x = -2;
  1151.  
  1152.     missile = spawn ();
  1153.     missile.owner = self;
  1154.     missile.movetype = MOVETYPE_BOUNCE;
  1155.     missile.solid = SOLID_BBOX;
  1156.     missile.classname = "pipebomb";
  1157.         
  1158. // set missile speed    
  1159.  
  1160.     makevectors (self.v_angle);
  1161.  
  1162.     if (self.v_angle_x)
  1163.         missile.velocity = v_forward*600 + v_up * 200 + crandom()*v_right*10 + crandom()*v_up*10;
  1164.     else
  1165.     {
  1166.         missile.velocity = aim(self, 10000);
  1167.         missile.velocity = missile.velocity * 600;
  1168.         missile.velocity_z = 200;
  1169.     }
  1170.  
  1171.     missile.avelocity = '300 300 300';
  1172.  
  1173.     missile.angles = vectoangles(missile.velocity);
  1174.     
  1175.     missile.touch = PipeBombTouch;
  1176.     missile.think = GrenadeExplode;
  1177.     
  1178.         setmodel (missile, "progs/pipebomb.mdl");
  1179.     setsize (missile, '0 0 0', '0 0 0');        
  1180.     setorigin (missile, self.origin);
  1181. };
  1182.  
  1183. /*
  1184. =====================
  1185. LASER STUFF -- Shyft
  1186. =====================
  1187. */
  1188.  
  1189. void() Laser_Touch; //Enforcer.qc Laser_touch() modified to change player dmg
  1190.  
  1191. void(vector vec) PLaser = 
  1192. {   sound (self, CHAN_WEAPON, "enforcer/enfire.wav", 1, ATTN_NORM);
  1193.    
  1194.     vec = normalize(vec);
  1195.     
  1196.     newmis = spawn();
  1197.     newmis.owner = self;
  1198.     newmis.movetype = MOVETYPE_FLY;
  1199.     newmis.solid = SOLID_BBOX;
  1200.     newmis.effects = EF_DIMLIGHT;
  1201.  
  1202.     setmodel (newmis, "progs/laser.mdl");
  1203.     setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);  
  1204.         
  1205.     setorigin (newmis, self.origin + v_forward*8 + '0 0 16');
  1206.     newmis.velocity = aim(self, 1000);
  1207.     newmis.velocity = newmis.velocity * 600;
  1208.  
  1209.     newmis.angles = vectoangles(newmis.velocity);
  1210.  
  1211.     newmis.nextthink = time + 5;
  1212.     newmis.think = SUB_Remove;
  1213.     newmis.touch = Laser_Touch;
  1214.  
  1215. };
  1216.  
  1217. void() W_FireLaser =
  1218. {
  1219.        self.effects = self.effects | EF_MUZZLEFLASH;
  1220.     makevectors (self.v_angle);
  1221.     self.currentammo = self.ammo_cells = self.ammo_cells - 1;
  1222.     PLaser(self.enemy.origin - self.origin);
  1223. };
  1224.  
  1225.  
  1226.  
  1227.  
  1228. /*========================================================================
  1229.  
  1230. BOUNCING FRAGMENTATION GRENADE - Version .9
  1231.  
  1232. 7/28/96 - Steve Bond  email:wedge@nuc.net
  1233.  
  1234. http://www.nuc.net/quake
  1235.  
  1236. =======================================================================*/
  1237.  
  1238.  
  1239.  
  1240. //This code segment handles the impact of shrapnel
  1241.  
  1242. //this is merely id's superspike_touch code, reworked
  1243.  
  1244. void() shrapnel_touch =
  1245.  
  1246. {
  1247.  
  1248. local float rand;
  1249.  
  1250. // has the shrapnel hit a switch? 
  1251.  
  1252.     if (other.solid == SOLID_TRIGGER)
  1253.  
  1254.         return; // trigger field, do nothing
  1255.  
  1256.  
  1257.  
  1258. // has the shrapnel hit the sky?
  1259.  
  1260.     if (pointcontents(self.origin) == CONTENT_SKY)
  1261.  
  1262.     {
  1263.  
  1264.         remove(self);
  1265.  
  1266.         return;
  1267.  
  1268.     }
  1269.  
  1270.     
  1271.  
  1272. // has the shrapnel hit a living thing?
  1273.  
  1274.     if (other.takedamage)
  1275.  
  1276.     {
  1277.  
  1278.         spawn_touchblood (33);
  1279.  
  1280.         T_Damage (other, self, self.owner, 33);
  1281.  
  1282.     }
  1283.  
  1284.     else
  1285.  
  1286.     {
  1287.  
  1288.         WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  1289.  
  1290.         WriteByte (MSG_BROADCAST, TE_SUPERSPIKE);
  1291.  
  1292.         WriteCoord (MSG_BROADCAST, self.origin_x);
  1293.  
  1294.         WriteCoord (MSG_BROADCAST, self.origin_y);
  1295.  
  1296.         WriteCoord (MSG_BROADCAST, self.origin_z);
  1297.  
  1298.     }
  1299.  
  1300.     remove(self);
  1301.  
  1302. };
  1303.  
  1304.  
  1305.  
  1306. /*
  1307.  
  1308. Code to spawn ONE randomly directed piece of shrapnel
  1309.  
  1310. this is id's launch_spike code, reworked
  1311.  
  1312. Pass a vector to this function to determine the shrap's origin
  1313.  
  1314. */
  1315.  
  1316. void (vector org, float spin) launch_shrapnel=
  1317.  
  1318. {
  1319.  
  1320.     local float xdir,ydir,zdir;
  1321.  
  1322.     
  1323.  
  1324. //Assign a random direction for the shrapnel to fly in
  1325.  
  1326.     xdir = 110 * random() - 55;
  1327.  
  1328.     ydir = 110 * random() - 55;
  1329.  
  1330.     zdir = 50 * random() - 25;
  1331.  
  1332.  
  1333.  
  1334.     newmis = spawn ();
  1335.  
  1336.     newmis.owner = self;
  1337.  
  1338.     newmis.movetype = MOVETYPE_BOUNCE;
  1339.  
  1340.     self.touch = SUB_Null;
  1341.  
  1342.     newmis.solid = SOLID_BBOX;
  1343.  
  1344.  
  1345.  
  1346.     newmis.touch = shrapnel_touch;
  1347.  
  1348.     newmis.classname = "spike";
  1349.  
  1350.     newmis.think = SUB_Remove;
  1351.  
  1352.     
  1353.  
  1354. // this is how many seconds(?) the nails can exist.        
  1355.  
  1356.     newmis.nextthink = time + 6;
  1357.  
  1358.     
  1359.  
  1360. // speed at which to move the shrapnel        
  1361.  
  1362.     newmis.velocity_x = xdir * 5;
  1363.  
  1364.     newmis.velocity_y = ydir * 5;
  1365.  
  1366.     newmis.velocity_z = zdir * 4;
  1367.  
  1368.  
  1369.  
  1370. /*
  1371.  
  1372. as best I can figure, AVELOCITY means "attitude velocity"        
  1373.  
  1374. or something thereabouts. Anyway, it makes shit spin on 
  1375.  
  1376. the x,y,z axes by the given velocity for each axis. In this 
  1377.  
  1378. case, it makes the shrapnel spin in flight. Good stuff.
  1379.  
  1380. this segment assigns one of five preset attitudes for 
  1381.  
  1382. each piece of shrapnel, based on the number passed to the
  1383.  
  1384. function.
  1385.  
  1386. */        
  1387.  
  1388.     if (spin == 0)
  1389.  
  1390.     newmis.avelocity='250 300 400';
  1391.  
  1392.     if (spin == 1)
  1393.  
  1394.     newmis.avelocity='400 250 300';
  1395.  
  1396.     if (spin == 2)
  1397.  
  1398.     newmis.avelocity='300 400 250';
  1399.  
  1400.     if (spin == 3)
  1401.  
  1402.     newmis.avelocity='300 300 300';
  1403.  
  1404.     if (spin == 4) 
  1405.  
  1406.     newmis.avelocity='400 250 400';
  1407.  
  1408.  
  1409.  
  1410.     setmodel (newmis, "progs/s_spike.mdl");
  1411.  
  1412.     setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);
  1413.  
  1414.     setorigin (newmis, org);
  1415.  
  1416. };
  1417.  
  1418.  
  1419.  
  1420. // This code segment detonates the 'second stage' of the grenade
  1421.  
  1422. // (After it has popped up)
  1423.  
  1424. void()  BouncerExplode =
  1425.  
  1426. {
  1427.  
  1428.     
  1429.  
  1430. // Do the damage
  1431.  
  1432.     T_RadiusDamage (self, self.owner, 120, world);
  1433.  
  1434. // Tell the network
  1435.  
  1436.     WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  1437.  
  1438.     WriteByte (MSG_BROADCAST, TE_EXPLOSION);
  1439.  
  1440.     WriteCoord (MSG_BROADCAST, self.origin_x);
  1441.  
  1442.     WriteCoord (MSG_BROADCAST, self.origin_y);
  1443.  
  1444.     WriteCoord (MSG_BROADCAST, self.origin_z);
  1445.  
  1446.  
  1447.  
  1448. // Let Quake handle the explosion and deallocation of the grenade        
  1449.  
  1450.     self.solid=SOLID_NOT;
  1451.  
  1452.     BecomeExplosion ();
  1453.  
  1454.  
  1455.  
  1456. // Launch a hail (20 pieces) of shrapnel
  1457.  
  1458.     launch_shrapnel (self.origin + '0 0 -1',0);
  1459.  
  1460.     launch_shrapnel (self.origin + '0 0 -1',1);
  1461.  
  1462.     launch_shrapnel (self.origin + '0 0 -1',2);
  1463.  
  1464.     launch_shrapnel (self.origin + '0 0 -1',3);
  1465.  
  1466.     launch_shrapnel (self.origin + '0 0 -1',4);
  1467.  
  1468.     launch_shrapnel (self.origin + '0 0 -1',0);
  1469.  
  1470.     launch_shrapnel (self.origin + '0 0 -1',1);
  1471.  
  1472.     launch_shrapnel (self.origin + '0 0 -1',2);
  1473.  
  1474.     launch_shrapnel (self.origin + '0 0 -1',3);
  1475.  
  1476.     launch_shrapnel (self.origin + '0 0 -1',4);
  1477.  
  1478.     launch_shrapnel (self.origin + '0 0 -1',0);
  1479.  
  1480.     launch_shrapnel (self.origin + '0 0 -1',1);
  1481.  
  1482.     launch_shrapnel (self.origin + '0 0 -1',2);
  1483.  
  1484.     launch_shrapnel (self.origin + '0 0 -1',3);
  1485.  
  1486.     launch_shrapnel (self.origin + '0 0 -1',4);
  1487.  
  1488.     launch_shrapnel (self.origin + '0 0 -1',0);
  1489.  
  1490.     launch_shrapnel (self.origin + '0 0 -1',1);
  1491.  
  1492.     launch_shrapnel (self.origin + '0 0 -1',2);
  1493.  
  1494.     launch_shrapnel (self.origin + '0 0 -1',3);
  1495.  
  1496.     launch_shrapnel (self.origin + '0 0 -1',4);
  1497.  
  1498. };
  1499.  
  1500.  
  1501.  
  1502. /*
  1503.  
  1504. This code segment makes the 'first stage' of the bouncer pop upward
  1505.  
  1506. after it's time has expired.
  1507.  
  1508. */
  1509.  
  1510. void() BouncerPopUp=
  1511.  
  1512. {
  1513.  
  1514.     local entity missile, mpuff;
  1515.  
  1516.  
  1517.  
  1518. // Make the grenade stop
  1519.  
  1520.     self.movetype=MOVETYPE_NONE;
  1521.  
  1522.     self.velocity='0 0 0';
  1523.  
  1524. // Draw a tiny explosion (no particles)        
  1525.  
  1526.     setmodel (self, "progs/s_explod.spr");
  1527.  
  1528.     s_explode1 ();
  1529.  
  1530. // Make the :FOOMP: grenade launcher sound        
  1531.  
  1532.     sound (self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
  1533.  
  1534. // Spawn and animate the 'second stage'
  1535.  
  1536.     missile = spawn ();
  1537.  
  1538.     missile.owner = self;
  1539.  
  1540.     missile.movetype = MOVETYPE_BOUNCE;
  1541.  
  1542.     missile.solid = SOLID_BBOX;
  1543.  
  1544.     missile.classname = "grenade";
  1545.  
  1546. // Set speed
  1547.  
  1548.     missile.velocity = '0 0 650';
  1549.  
  1550.     missile.angles = vectoangles(missile.velocity);
  1551.  
  1552.     missile.touch = BouncerExplode;
  1553.  
  1554. // Set Duration
  1555.  
  1556.     missile.nextthink = time + 1;
  1557.  
  1558.     missile.think = BouncerExplode;
  1559.  
  1560.  
  1561.  
  1562.     setmodel (missile, "progs/missile.mdl");
  1563.  
  1564.     setsize (missile, '0 0 0', '0 0 0');
  1565.  
  1566.     setorigin (missile, self.origin);
  1567.  
  1568. };
  1569.  
  1570.  
  1571.  
  1572. // This code segment handles collisions for the 'first stage'
  1573.  
  1574. // Of the grenade (after launch and before popup)
  1575.  
  1576.  
  1577.  
  1578. void() BouncerTouch =
  1579.  
  1580. {
  1581.  
  1582. //Did the grenade hit a 'living' thing?
  1583.  
  1584.     if (other.takedamage)
  1585.  
  1586.     {
  1587.  
  1588. // yes, so play the bounce sound
  1589.  
  1590.     sound (self, CHAN_WEAPON, "weapons/bounce.wav", 1, ATTN_NORM);
  1591.  
  1592. // now, exit the function without cause damage to the thing        
  1593.  
  1594.     return;
  1595.  
  1596.     }
  1597.  
  1598.  
  1599.  
  1600. // This controls what happens when the grenade hits walls, etz        
  1601.  
  1602. // It just plays the sound and bounces on
  1603.  
  1604.     sound (self, CHAN_WEAPON, "weapons/bounce.wav", 1, ATTN_NORM);
  1605.  
  1606.     if (self.velocity == '0 0 0')
  1607.  
  1608.         self.avelocity = '0 0 0';
  1609.  
  1610. };
  1611.  
  1612.  
  1613.  
  1614. /*
  1615.  
  1616. This code segment handles the launching of the Bouncing Fragmentation Grenade
  1617.  
  1618. this is a reworked copy of id's W_launchgrenade code
  1619.  
  1620. */
  1621.  
  1622. void() W_LaunchBouncer =
  1623.  
  1624. {
  1625.  
  1626. // If player doesn't have 3 or more rockets, don't launch
  1627.  
  1628.     if (self.ammo_rockets < 3)
  1629.  
  1630.     {
  1631.  
  1632.     return;
  1633.  
  1634.     }
  1635.  
  1636.  
  1637.  
  1638.     local   entity missile, mpuff;
  1639.  
  1640.     
  1641.  
  1642. // Take 3 rockets from the player        
  1643.  
  1644.     self.currentammo = self.ammo_rockets = self.ammo_rockets - 3;
  1645.  
  1646.     
  1647.  
  1648.     //sound (self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
  1649.  
  1650. /*
  1651.  
  1652. self.punchangle_x (x, y, or z) defines how hard the weapon         
  1653.  
  1654. recoils (or 'punches' the player, making the screen shake)
  1655.  
  1656. */        
  1657.  
  1658.     self.punchangle_x = -2;
  1659.  
  1660.  
  1661.  
  1662. // This spawns the grenade - it is all id's standard grenade code        
  1663.  
  1664.     missile = spawn ();
  1665.  
  1666.     missile.owner = self;
  1667.  
  1668.     missile.movetype = MOVETYPE_BOUNCE;
  1669.  
  1670.     missile.solid = SOLID_BBOX;
  1671.  
  1672.     missile.classname = "grenade";
  1673.  
  1674.         
  1675.  
  1676. // set missile speed    
  1677.  
  1678.  
  1679.  
  1680.     makevectors (self.v_angle);
  1681.  
  1682.  
  1683.  
  1684.     if (self.v_angle_x)
  1685.  
  1686.         missile.velocity = v_forward*600 + v_up * 200 + crandom()*v_right*10 + crandom()*v_up*10;
  1687.  
  1688.     else
  1689.  
  1690.     {
  1691.  
  1692.         missile.velocity = aim(self, 10000);
  1693.  
  1694.         missile.velocity = missile.velocity * 600;
  1695.  
  1696.         missile.velocity_z = 200;
  1697.  
  1698.     }
  1699.  
  1700.  
  1701.  
  1702.     missile.avelocity = '300 300 300';
  1703.  
  1704.  
  1705.  
  1706.     missile.angles = vectoangles(missile.velocity);
  1707.  
  1708.     
  1709.  
  1710. // if the grenade touches anything, BouncerTouch() is called        
  1711.  
  1712.     missile.touch = BouncerTouch;
  1713.  
  1714.     
  1715.  
  1716. // Grenade has a maximum lifespan of 1.5 (seconds?)
  1717.  
  1718. // set missile duration
  1719.  
  1720.     missile.nextthink = time + 1.5;
  1721.  
  1722.     
  1723.  
  1724. // when the grenade's lifespan has expired, BouncerPopUp() is called        
  1725.  
  1726.     missile.think = BouncerPopUp;
  1727.  
  1728.  
  1729.  
  1730.     setmodel (missile, "progs/grenade.mdl");
  1731.  
  1732.     setsize (missile, '0 0 0', '0 0 0');            
  1733.  
  1734.     setorigin (missile, self.origin);
  1735.  
  1736. };
  1737.  
  1738. /*
  1739.  
  1740. ===============================================================================
  1741.  
  1742. End of Bouncing Fragmentation Grenade code.
  1743.  
  1744. ===============================================================================
  1745.  
  1746. */
  1747.  
  1748.  
  1749. /*
  1750. ===============================================================================
  1751.  
  1752. PLAYER WEAPON USE
  1753.  
  1754. ===============================================================================
  1755. */
  1756.  
  1757. void() W_SetCurrentAmmo =
  1758. {
  1759.     player_run ();        // get out of any weapon firing states
  1760.  
  1761.     self.items = self.items - ( self.items & (IT_SHELLS | IT_NAILS | IT_ROCKETS | IT_CELLS) );
  1762.  
  1763.  
  1764.         if (self.invincible_time)       // Fiend stuff
  1765.         {
  1766.         self.currentammo = 0;
  1767.                 self.weaponmodel = "";
  1768.         self.weaponframe = 0;
  1769.         }
  1770.  
  1771.     if (self.weapon == IT_AXE)
  1772.     {
  1773.         self.currentammo = 0;
  1774.         self.weaponmodel = "progs/v_axe.mdl";
  1775.         self.weaponframe = 0;
  1776.     }
  1777.  
  1778.     else if (self.weapon == IT_SHOTGUN)
  1779.  
  1780.     {
  1781.         self.currentammo = self.ammo_shells;
  1782.         self.weaponmodel = "progs/v_shot.mdl";
  1783.         self.weaponframe = 0;
  1784.         self.items = self.items | IT_SHELLS;
  1785.     }
  1786.  
  1787.     else if (self.weapon == IT_SUPER_SHOTGUN)
  1788.     {
  1789.         self.currentammo = self.ammo_shells;
  1790.         self.weaponmodel = "progs/v_shot2.mdl";
  1791.         self.weaponframe = 0;
  1792.         self.items = self.items | IT_SHELLS;
  1793.     }
  1794.  
  1795.     else if (self.weapon == IT_NAILGUN)
  1796.     {
  1797.         self.currentammo = self.ammo_nails;
  1798.         self.weaponmodel = "progs/v_nail.mdl";
  1799.         self.weaponframe = 0;
  1800.         self.items = self.items | IT_NAILS;
  1801.     }
  1802.     else if (self.weapon == IT_SUPER_NAILGUN)
  1803.     {
  1804.         self.currentammo = self.ammo_nails;
  1805.         self.weaponmodel = "progs/v_nail2.mdl";
  1806.         self.weaponframe = 0;
  1807.         self.items = self.items | IT_NAILS;
  1808.     }
  1809.     else if ((self.weapon == IT_GRENADE_LAUNCHER) || (self.weapon == IT_NAILBOMB))
  1810.     {
  1811.         self.currentammo = self.ammo_rockets;
  1812.         self.weaponmodel = "progs/v_rock.mdl";
  1813.         self.weaponframe = 0;
  1814.         self.items = self.items | IT_ROCKETS;
  1815.     }
  1816.  
  1817.     else if (self.weapon == IT_PIPEBOMB)
  1818.     {
  1819.         self.currentammo = self.ammo_rockets;
  1820.         self.weaponmodel = "progs/v_pipe.mdl";
  1821.         self.weaponframe = 0;
  1822.         self.items = self.items | IT_ROCKETS;
  1823.     }
  1824.  
  1825.     else if (self.weapon == IT_ROCKET_LAUNCHER || (self.weapon == IT_HOMER))
  1826.     {
  1827.         self.currentammo = self.ammo_rockets;
  1828.         self.weaponmodel = "progs/v_rock2.mdl";
  1829.         self.weaponframe = 0;
  1830.         self.items = self.items | IT_ROCKETS;
  1831.     }
  1832.     else if (self.weapon == IT_LIGHTNING)
  1833.     {
  1834.         self.currentammo = self.ammo_cells;
  1835.         self.weaponmodel = "progs/v_light.mdl";
  1836.         self.weaponframe = 0;
  1837.         self.items = self.items | IT_CELLS;
  1838.     }
  1839.     else if (self.weapon == IT_LASER)
  1840.     {
  1841.         self.currentammo = self.ammo_cells;
  1842.         self.weaponmodel = "progs/g_laser.mdl";
  1843.         self.weaponframe = 0;
  1844.         self.items = self.items | IT_CELLS;
  1845.     }
  1846.     else
  1847.     {
  1848.         self.currentammo = 0;
  1849.         self.weaponmodel = "";
  1850.         self.weaponframe = 0;
  1851.     }
  1852. };
  1853.  
  1854. float() W_BestWeapon =
  1855. {
  1856.     local    float    it;
  1857.     
  1858.     it = self.items;
  1859.  
  1860.     if(self.ammo_cells >= 1 && (it & IT_LIGHTNING) )
  1861.         return IT_LIGHTNING;
  1862.     else if(self.ammo_nails >= 2 && (it & IT_SUPER_NAILGUN) )
  1863.         return IT_SUPER_NAILGUN;
  1864.     else if(self.ammo_shells >= 2 && (it & IT_SUPER_SHOTGUN) )
  1865.         return IT_SUPER_SHOTGUN;
  1866.     else if(self.ammo_nails >= 1 && (it & IT_NAILGUN) )
  1867.         return IT_NAILGUN;
  1868.     else if(self.ammo_shells >= 1 && (it & IT_SHOTGUN) )
  1869.         return IT_SHOTGUN;
  1870.         
  1871. /*
  1872.     if(self.ammo_rockets >= 1 && (it & IT_ROCKET_LAUNCHER) )
  1873.         return IT_ROCKET_LAUNCHER;
  1874.     else if(self.ammo_rockets >= 1 && (it & IT_GRENADE_LAUNCHER) )
  1875.         return IT_GRENADE_LAUNCHER;
  1876.  
  1877. */
  1878.  
  1879.     return IT_AXE;
  1880. };
  1881.  
  1882. float() W_CheckNoAmmo =
  1883. {
  1884.     if (self.currentammo > 0)
  1885.         return TRUE;
  1886.  
  1887.     if (self.invincible_time)
  1888.         return TRUE;
  1889.  
  1890.     if (self.weapon == IT_AXE)
  1891.         return TRUE;
  1892.     
  1893.     self.weapon = W_BestWeapon ();
  1894.  
  1895.     W_SetCurrentAmmo ();
  1896.     
  1897. // drop the weapon down
  1898.     return FALSE;
  1899. };
  1900.  
  1901. /*
  1902. ============
  1903. W_Attack
  1904.  
  1905. An attack impulse can be triggered now
  1906. ============
  1907. */
  1908. void()    player_axe1;
  1909. void()    player_axeb1;
  1910. void()    player_axec1;
  1911. void()    player_axed1;
  1912. void()    player_shot1;
  1913. void()    player_nail1;
  1914. void()    player_light1;
  1915. void()    player_rocket1;
  1916. void()      player_dattack;
  1917.  
  1918. void() W_Attack =
  1919. {
  1920.     local    float    r;
  1921.  
  1922.     if (!W_CheckNoAmmo ())
  1923.         return;
  1924.  
  1925.     makevectors    (self.v_angle);            // calculate forward angle for velocity
  1926.     self.show_hostile = time + 1;    // wake monsters up
  1927.  
  1928.     if (self.invincible_time)    // Fiend stuff
  1929.         {
  1930.                 self.attack_finished = time + 1;
  1931.                 player_dattack();
  1932.         }
  1933.  
  1934.     else if (self.weapon == IT_AXE)
  1935.     {
  1936.         sound (self, CHAN_WEAPON, "weapons/ax1.wav", 1, ATTN_NORM);
  1937.         r = random();
  1938.         if (r < 0.25)
  1939.             player_axe1 ();
  1940.         else if (r<0.5)
  1941.             player_axeb1 ();
  1942.         else if (r<0.75)
  1943.             player_axec1 ();
  1944.         else
  1945.             player_axed1 ();
  1946.         self.attack_finished = time + 0.5;
  1947.     }
  1948.     else if (self.weapon == IT_SHOTGUN)
  1949.     {
  1950.         player_shot1 ();
  1951.         W_FireShotgun ();
  1952.         self.attack_finished = time + 0.5;
  1953.     }
  1954.     else if (self.weapon == IT_SUPER_SHOTGUN)
  1955.     {
  1956.         player_shot1 ();
  1957.         W_FireSuperShotgun ();
  1958.         self.attack_finished = time + 0.7;
  1959.     }
  1960.     else if (self.weapon == IT_NAILGUN)
  1961.     {
  1962.         player_nail1 ();
  1963.     }
  1964.     else if (self.weapon == IT_SUPER_NAILGUN)
  1965.     {
  1966.         player_nail1 ();
  1967.     }
  1968.     else if (self.weapon == IT_GRENADE_LAUNCHER)
  1969.     {
  1970.         player_rocket1();
  1971.         W_FireGrenade();
  1972.         self.attack_finished = time + 0.6;
  1973.     }
  1974.     else if (self.weapon == IT_ROCKET_LAUNCHER)
  1975.     {
  1976.         player_rocket1();
  1977.         W_FireRocket();
  1978.                 self.attack_finished = time + 0.8;
  1979.     }
  1980.     else if (self.weapon == IT_LIGHTNING)
  1981.     {
  1982.         player_light1();
  1983.         self.attack_finished = time + 0.1;
  1984.         sound (self, CHAN_AUTO, "weapons/lstart.wav", 1, ATTN_NORM);
  1985.     }
  1986.    else if (self.weapon == IT_LASER)         //SHYFT ADD
  1987.     {
  1988.         player_shot1();
  1989.         W_FireLaser();
  1990.         self.attack_finished = time + 0.2;
  1991.     }
  1992.     else if (self.weapon == IT_NAILBOMB)
  1993.     {
  1994.         W_LaunchBouncer();
  1995.         self.attack_finished = time + 0.4;
  1996.     }
  1997.     else if (self.weapon == IT_HOMER)
  1998.     {
  1999.         W_FireHomer();
  2000.         self.attack_finished = time + 0.6;
  2001.     }    
  2002.     else if (self.weapon == IT_PIPEBOMB)
  2003.     {
  2004.                 player_rocket1();
  2005.         W_FirePipeBomb();
  2006.                 self.attack_finished = time + 0.4;
  2007.     }
  2008.  
  2009.  
  2010. };
  2011.  
  2012. /*
  2013. ============
  2014. W_ChangeWeapon
  2015.  
  2016. ============
  2017. */
  2018. void() W_ChangeWeapon =
  2019. {
  2020.     local    float    it, am, fl;
  2021.     
  2022.     it = self.items;
  2023.     am = 0;
  2024.     
  2025.     if (self.impulse == 1)
  2026.     {
  2027.         fl = IT_AXE;
  2028.     }
  2029.     else if (self.impulse == 2)
  2030.     {
  2031.     if (self.weapon == IT_SHOTGUN)
  2032.         {
  2033.  
  2034.  
  2035.             fl = IT_SUPER_SHOTGUN;       // IT_SHOTGUN
  2036.                         if (!(self.items & fl))
  2037.                  {       // don't have the weapon or the ammo
  2038.                          sprint (self, "no weapon.\n");
  2039.                          return;
  2040.                   }
  2041.             self.weapon = IT_SUPER_SHOTGUN;
  2042.             centerprint(self,"Super Shotgun mode\n");
  2043.             return;
  2044.         }
  2045.  
  2046.         fl = IT_SHOTGUN;
  2047.         if (self.ammo_shells < 1)
  2048.             am = 1;
  2049.         if (!am) centerprint(self,"Shotgun Mode\n");
  2050.     }
  2051.     else if (self.impulse == 3)
  2052.     {
  2053.     if (self.weapon == IT_PIPEBOMB)
  2054.         {
  2055.             DetPipeBombs();
  2056.             centerprint(self,"Pipebomb triggered\n");
  2057.             return;
  2058.         }
  2059.  
  2060.         fl = IT_PIPEBOMB;
  2061.         if (self.ammo_rockets < 1)
  2062.             am = 1;
  2063.         if (!am) centerprint(self,"Pipebomb Mode\n");
  2064.     }
  2065.  
  2066.  
  2067.     else if (self.impulse == 4)
  2068.     {
  2069.         fl = IT_NAILGUN;
  2070.         if (self.ammo_nails < 1)
  2071.             am = 1;
  2072.     }
  2073.     else if (self.impulse == 5)
  2074.     {
  2075.         fl = IT_SUPER_NAILGUN;
  2076.         if (self.ammo_nails < 2)
  2077.             am = 1;
  2078.     }
  2079.     else if (self.impulse == 6)
  2080.     {
  2081.     if (self.weapon == IT_GRENADE_LAUNCHER)
  2082.         { 
  2083.             self.weapon = IT_NAILBOMB;
  2084.             centerprint(self,"Nailbomb mode\n");
  2085.             return;
  2086.         } 
  2087.  
  2088.         fl = IT_GRENADE_LAUNCHER;
  2089.         if (self.ammo_rockets < 1)
  2090.             am = 1;
  2091.         if (!am) centerprint(self,"Grenade Launcher Mode\n");
  2092.     }
  2093.     else if (self.impulse == 7)
  2094.     {
  2095.         if (self.weapon == IT_ROCKET_LAUNCHER)
  2096.         { 
  2097.             self.weapon = IT_HOMER;
  2098.             centerprint(self,"Homer mode\n");
  2099.             return;
  2100.         } 
  2101.     
  2102.         fl = IT_ROCKET_LAUNCHER;
  2103.         if (self.ammo_rockets < 1)
  2104.             am = 1;
  2105.         if (!am) centerprint(self,"Rocket Launcher Mode\n");
  2106.     }
  2107.     else if (self.impulse == 8)
  2108.     {
  2109.         fl = IT_LIGHTNING;
  2110.         if (self.ammo_cells < 1)
  2111.             am = 1;
  2112.     }
  2113.     else if (self.impulse == 9)       // SHYFT ADD
  2114.     {
  2115.         fl = IT_LASER;
  2116.         if (self.ammo_cells < 1)
  2117.             am = 1;
  2118.     }
  2119.     self.impulse = 0;
  2120.     
  2121.     if (!(self.items & fl))
  2122.     {    // don't have the weapon or the ammo
  2123.         sprint (self, "no weapon.\n");
  2124.         return;
  2125.     }
  2126.     
  2127.     if (am)
  2128.     {    // don't have the ammo
  2129.         sprint (self, "not enough ammo.\n");
  2130.         return;
  2131.     }
  2132.  
  2133. //
  2134. // set weapon, set ammo
  2135. //
  2136.     self.weapon = fl;        
  2137.     W_SetCurrentAmmo ();
  2138. };
  2139.  
  2140. /*
  2141. ============
  2142. CheatCommand
  2143. ============
  2144. */
  2145. void() CheatCommand =
  2146. {
  2147.     if (deathmatch || coop)
  2148.         return;
  2149.  
  2150.     self.ammo_rockets = 100;
  2151.     self.ammo_nails = 200;
  2152.     self.ammo_shells = 100;
  2153.     self.items = self.items | 
  2154.         IT_AXE |
  2155.         IT_SHOTGUN |
  2156.         IT_SUPER_SHOTGUN |
  2157.         IT_NAILGUN |
  2158.         IT_SUPER_NAILGUN |
  2159.         IT_GRENADE_LAUNCHER |
  2160.         IT_ROCKET_LAUNCHER |
  2161.             IT_LASER |
  2162.         IT_PIPEBOMB |
  2163.         IT_KEY1 | IT_KEY2;
  2164.  
  2165.     self.ammo_cells = 200;
  2166.     self.items = self.items | IT_LIGHTNING;
  2167.  
  2168.     self.weapon = IT_ROCKET_LAUNCHER;
  2169.     self.impulse = 0;
  2170.     W_SetCurrentAmmo ();
  2171. };
  2172.  
  2173. /*
  2174. ============
  2175. CycleWeaponCommand
  2176.  
  2177. Go to the next weapon with ammo
  2178. ============
  2179. */
  2180. void() CycleWeaponCommand =
  2181. {
  2182.     local    float    it, am;
  2183.     
  2184.     it = self.items;
  2185.     self.impulse = 0;
  2186.     
  2187.     while (1)
  2188.     {
  2189.         am = 0;
  2190.  
  2191.         if (self.weapon == IT_LIGHTNING)
  2192.         {
  2193.             self.weapon = IT_AXE;
  2194.         }
  2195.         else if (self.weapon == IT_AXE)
  2196.         {
  2197.             self.weapon = IT_SHOTGUN;
  2198.             if (self.ammo_shells < 1)
  2199.                 am = 1;
  2200.         }
  2201.         else if ((self.weapon == IT_SHOTGUN) || (self.weapon == IT_SUPER_SHOTGUN))
  2202.         {
  2203.             self.weapon = IT_PIPEBOMB;
  2204.             if (self.ammo_shells < 2)
  2205.                 am = 1;
  2206.         }        
  2207.  
  2208.         else if (self.weapon == IT_PIPEBOMB)
  2209.         {
  2210.             self.weapon = IT_NAILGUN;
  2211.             if (self.ammo_nails < 1)
  2212.                 am = 1;
  2213.         }
  2214.  
  2215.  
  2216.         else if (self.weapon == IT_NAILGUN)
  2217.         {
  2218.             self.weapon = IT_SUPER_NAILGUN;
  2219.             if (self.ammo_nails < 2)
  2220.                 am = 1;
  2221.         }
  2222.         else if (self.weapon == IT_SUPER_NAILGUN)
  2223.         {
  2224.             self.weapon = IT_GRENADE_LAUNCHER;
  2225.             if (self.ammo_rockets < 1)
  2226.                 am = 1;
  2227.         }
  2228.         else if ((self.weapon == IT_GRENADE_LAUNCHER) || (self.weapon == IT_NAILBOMB))
  2229.         {
  2230.             self.weapon = IT_ROCKET_LAUNCHER;
  2231.             if (self.ammo_rockets < 1)
  2232.                 am = 1;
  2233.         }
  2234.         else if ((self.weapon == IT_ROCKET_LAUNCHER) || (self.weapon == IT_HOMER))
  2235.         {
  2236.            self.weapon = IT_LASER;                   //SHYFT ADD
  2237.             if (self.ammo_cells < 1)
  2238.                 am = 1;
  2239.         }
  2240.         else if (self.weapon == IT_LASER)
  2241.         {
  2242.             self.weapon = IT_LIGHTNING;
  2243.             if (self.ammo_cells < 1)
  2244.                 am = 1;
  2245.         }
  2246.     
  2247.         if ( (self.items & self.weapon) && am == 0)
  2248.         {
  2249.             W_SetCurrentAmmo ();
  2250.             return;
  2251.         }
  2252.     }
  2253.  
  2254. };
  2255.  
  2256. /*
  2257. ============
  2258. ServerflagsCommand
  2259.  
  2260. Just for development
  2261. ============
  2262. */
  2263. void() ServerflagsCommand =
  2264. {
  2265.     serverflags = serverflags * 2 + 1;
  2266. };
  2267.  
  2268. void() QuadCheat =
  2269. {
  2270.     if (deathmatch || coop)
  2271.         return;
  2272.     self.super_time = 1;
  2273.     self.super_damage_finished = time + 30;
  2274.     self.items = self.items | IT_QUAD;
  2275.     dprint ("quad cheat\n");
  2276. };
  2277.  
  2278. void() FiendCheat =
  2279. {
  2280.         // No Cheating during net games.
  2281.         if (deathmatch || coop)
  2282.                 return;
  2283.         self.invincible_time = 1;
  2284.         self.invincible_finished = time + 120;
  2285.         self.weaponmodel = "";
  2286.         self.view_ofs = '0 0 4';
  2287.         self.items = self.items | IT_INVULNERABILITY;
  2288.         dprint ("You fiend!\n");
  2289. };
  2290.  
  2291. /*
  2292. =======================
  2293. ThrowBackpack by Vhold
  2294. =======================
  2295. */
  2296. void() ThrowBackpack =
  2297. {
  2298.     local entity     item;
  2299.  
  2300.     if ( (self.ammo_shells + self.ammo_nails + self.ammo_rockets + self.ammo_cells) == 0)
  2301.         return;
  2302.  
  2303.     item = spawn();
  2304.  
  2305.         if ( self.ammo_shells >= 20)
  2306.     {
  2307.         item.ammo_shells = 20;
  2308.         self.ammo_shells = self.ammo_shells - 20;
  2309.     }
  2310.     else
  2311.     {
  2312.         item.ammo_shells = self.ammo_shells;
  2313.         self.ammo_shells = 0;
  2314.     }
  2315.     
  2316.         if ( self.ammo_nails >= 20)
  2317.     {
  2318.         item.ammo_nails = 20;
  2319.                 self.ammo_nails = self.ammo_nails - 20;
  2320.     }
  2321.     else
  2322.     {
  2323.         item.ammo_nails = self.ammo_nails;
  2324.         self.ammo_nails = 0;
  2325.     }
  2326.  
  2327.     if ( self.ammo_rockets >= 10)
  2328.     {
  2329.         item.ammo_rockets = 10;
  2330.         self.ammo_rockets = self.ammo_rockets - 10;
  2331.     }
  2332.     else
  2333.     {
  2334.         item.ammo_rockets = self.ammo_rockets;
  2335.                 self.ammo_rockets = 0;
  2336.     }
  2337.  
  2338.     if (self.ammo_cells >= 20)
  2339.     {    
  2340.         item.ammo_cells = 20;
  2341.         self.ammo_cells = self.ammo_cells - 20;
  2342.     }
  2343.     else
  2344.     {
  2345.         item.ammo_cells = self.ammo_cells;
  2346.         self.ammo_cells = 0;
  2347.     }
  2348.  
  2349.     item.owner = self;
  2350.     makevectors(self.v_angle);
  2351.     setorigin(item, self.origin + '0 0 16');
  2352.     item.velocity = aim(self, 1000);
  2353.     item.velocity = item.velocity * 500;
  2354.     item.flags = FL_ITEM;
  2355.     item.solid = SOLID_TRIGGER;
  2356.     item.movetype = MOVETYPE_BOUNCE;
  2357.  
  2358.     setmodel (item, "progs/backpack.mdl");
  2359.     setsize(item, '-16 -16 0', '16 16 56');
  2360.     item.touch = BackpackTouch;
  2361.     item.nextthink = time + 120;    // remove after 2 minutes
  2362.     item.think = SUB_Remove;
  2363.  
  2364.     W_SetCurrentAmmo();
  2365. };
  2366. /*
  2367. ============
  2368. ImpulseCommands
  2369.  
  2370. ============
  2371. */
  2372. void() ImpulseCommands =
  2373. {
  2374.     CheckHoloCommand ();
  2375.  
  2376.     if (self.impulse >= 1 && self.impulse <= 9)
  2377.         W_ChangeWeapon ();
  2378.  
  2379.     if (self.impulse == 10)
  2380.         CycleWeaponCommand ();
  2381.  
  2382.     if (self.impulse == 10)
  2383.         CycleWeaponCommand ();
  2384.     if (self.impulse == 11)
  2385.         ServerflagsCommand ();
  2386.  
  2387.     if (self.impulse == 12)
  2388.         CheatCommand ();
  2389.  
  2390.  
  2391.         // Stove Bond's flare
  2392.     if (self.impulse == 13)
  2393.         W_FireFlare ();
  2394.  
  2395.     // Vhold's Backpack thing
  2396.     if (self.impulse == 20)
  2397.         ThrowBackpack();
  2398.  
  2399. // *************************************************************************
  2400. // **                                          **
  2401. // ** M U L T I S K I N  1.1  (start)                                     **
  2402. // **                                      **
  2403. // *************************************************************************
  2404.  
  2405.  
  2406.     if ((self.impulse == 200) || (self.impulse == 201))
  2407.     {
  2408.         if (self.impulse == 200)
  2409.         {
  2410.         self.skin = self.skin + 1;
  2411.                 if (self.skin == 48) self.skin = 0;
  2412.         } else
  2413.         if (self.impulse == 201)
  2414.         {
  2415.         self.skin = self.skin - 1;
  2416.                 if (self.skin == -1) self.skin = 47;
  2417.         }
  2418.         if (self.skin == 0) centerprint(self, "SKIN: Quake himself (1)"); else
  2419.         if (self.skin == 1) centerprint(self, "SKIN: Duke Nukem 3d (2)"); else
  2420.         if (self.skin == 2) centerprint(self, "SKIN: Mr. Toad (3)"); else
  2421.         if (self.skin == 3) centerprint(self, "SKIN: the Stormtrooper (4)"); else
  2422.         if (self.skin == 4) centerprint(self, "SKIN: Max (5)"); else
  2423.         if (self.skin == 5) centerprint(self, "SKIN: the Terminator (6)"); else
  2424.         if (self.skin == 6) centerprint(self, "SKIN: Judge Dredd (7)"); else
  2425.         if (self.skin == 7) centerprint(self, "SKIN: Camouflaged soldier (8)"); else
  2426.         if (self.skin == 8) centerprint(self, "SKIN: Captain Picard (9)"); else
  2427.         if (self.skin == 9) centerprint(self, "SKIN: the Wizzard (10)"); else
  2428.         if (self.skin == 10) centerprint(self,"SKIN: the Predator (11)"); else
  2429.         if (self.skin == 11) centerprint(self,"SKIN: Skeleton 12)"); else
  2430.         if (self.skin == 12) centerprint(self,"SKIN: Wan-Fu (13)"); else
  2431.         if (self.skin == 13) centerprint(self,"SKIN: Henry Rollins (14)"); else
  2432.         if (self.skin == 14) centerprint(self,"SKIN: He-Man (15)"); else
  2433.         if (self.skin == 15) centerprint(self,"SKIN: Boba (16)"); else
  2434.         if (self.skin == 16) centerprint(self,"SKIN: Superman (17)"); else
  2435.  
  2436.         if (self.skin == 17) centerprint(self,"SKIN: NYPD Cop (18)"); else
  2437.         if (self.skin == 18) centerprint(self,"SKIN: Red/Yellow women dude (19)"); else
  2438.  
  2439.         if (self.skin == 19) centerprint(self,"SKIN: Zombie (20)"); else
  2440.         if (self.skin == 20) centerprint(self,"SKIN: Homer Simpson (21)"); else
  2441.         if (self.skin == 21) centerprint(self,"SKIN: Mario (22)"); else
  2442.         if (self.skin == 22) centerprint(self,"SKIN: 311 soldier (23)"); else
  2443.         if (self.skin == 23) centerprint(self,"SKIN: Ninja guy 1 (24)"); else
  2444.         if (self.skin == 24) centerprint(self,"SKIN: Deadpool (25)"); else
  2445.         if (self.skin == 25) centerprint(self,"SKIN: Bonehead (26)"); else
  2446.         if (self.skin == 26) centerprint(self,"SKIN: Black spiderman (27)"); else
  2447.         if (self.skin == 27) centerprint(self,"SKIN: Old cop (28)"); else
  2448.         if (self.skin == 28) centerprint(self,"SKIN: The Punisher (29)"); else
  2449.         if (self.skin == 29) centerprint(self,"SKIN: Stormtrooper 2 (30)"); else
  2450.         if (self.skin == 30) centerprint(self,"SKIN: Evil Quake (31)"); else
  2451.         if (self.skin == 31) centerprint(self,"SKIN: Hans Solo (32)"); else
  2452.         if (self.skin == 32) centerprint(self,"SKIN: Batman (33)"); else
  2453.         if (self.skin == 33) centerprint(self,"SKIN: Biosuit (34)"); else
  2454.         if (self.skin == 34) centerprint(self,"SKIN: Bosk (35)"); else
  2455.         if (self.skin == 35) centerprint(self,"SKIN: Dark Flash Gordon (36)"); else
  2456.         if (self.skin == 36) centerprint(self,"SKIN: Doom soldier (37)"); else
  2457.         if (self.skin == 37) centerprint(self,"SKIN: Enforcer (38)"); else
  2458.         if (self.skin == 38) centerprint(self,"SKIN: Evil Eye (39)"); else
  2459.         if (self.skin == 39) centerprint(self,"SKIN: Flash Gordon (40)"); else
  2460.         if (self.skin == 40) centerprint(self,"SKIN: Hell Knight (41)"); else
  2461.         if (self.skin == 41) centerprint(self,"SKIN: Jason (42)"); else
  2462.         if (self.skin == 42) centerprint(self,"SKIN: Knight (43)"); else
  2463.         if (self.skin == 43) centerprint(self,"SKIN: The Incredible MoleMan! (44)"); else
  2464.         if (self.skin == 44) centerprint(self,"SKIN: Ogre (45)"); else
  2465.         if (self.skin == 45) centerprint(self,"SKIN: Ninja 2 (46)"); else
  2466.         if (self.skin == 46) centerprint(self,"SKIN: Rage Against The Machine! (47)"); else
  2467.         if (self.skin == 47) centerprint(self,"SKIN: Quake Spawn (48)");
  2468.     
  2469.     }
  2470.  
  2471. // *************************************************************************
  2472. // **                                          **
  2473. // ** M U L T I S K I N  1.1  (end)                                       **
  2474. // **                                      **
  2475. // *************************************************************************
  2476.  
  2477.     if (self.impulse == 254)
  2478.         FiendCheat ();
  2479.  
  2480.     if (self.impulse == 255)
  2481.         QuadCheat ();
  2482.         
  2483.     self.impulse = 0;
  2484. };
  2485.  
  2486. /*
  2487. ============
  2488. W_WeaponFrame
  2489.  
  2490. Called every frame so impulse events can be handled as well as possible
  2491. ============
  2492. */
  2493. void() W_WeaponFrame =
  2494. {
  2495.     if (time < self.attack_finished)
  2496.         return;
  2497.  
  2498.     ImpulseCommands ();
  2499.     
  2500. // check for attack
  2501.     if (self.button0)
  2502.     {
  2503.         SuperDamageSound ();
  2504.         W_Attack ();
  2505.     }
  2506. };
  2507.  
  2508. /*
  2509. ========
  2510. SuperDamageSound
  2511.  
  2512. Plays sound if needed
  2513. ========
  2514. */
  2515. void() SuperDamageSound =
  2516. {
  2517.     if (self.super_damage_finished > time)
  2518.     {
  2519.         if (self.super_sound < time)
  2520.         {
  2521.             self.super_sound = time + 1;
  2522.             sound (self, CHAN_BODY, "items/damage3.wav", 1, ATTN_NORM);
  2523.         }
  2524.     }
  2525.     return;
  2526. };
  2527.  
  2528.  
  2529.