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