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