home *** CD-ROM | disk | FTP | other *** search
/ Superpower (Alt) / SUPERPOWER.iso / q / patch / mbq067 / weapons.qc < prev    next >
Encoding:
Text File  |  1996-08-27  |  58.0 KB  |  2,497 lines

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