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

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