home *** CD-ROM | disk | FTP | other *** search
/ Quake 'em / QUAKEEM.BIN / quake / programs / tf1_1src / weapons.qc < prev    next >
Encoding:
Text File  |  1996-08-30  |  37.8 KB  |  1,737 lines

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