home *** CD-ROM | disk | FTP | other *** search
/ Quake 'em / QUAKEEM.BIN / quake / programs / terorist / weapons.qc < prev   
Encoding:
Text File  |  1996-08-02  |  32.5 KB  |  1,542 lines

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