home *** CD-ROM | disk | FTP | other *** search
/ Phenomenon / Phenomenon.iso / quake / teamfort / sources / tf1_21sc / source / weapons.qc < prev    next >
Encoding:
Text File  |  1996-09-17  |  45.8 KB  |  2,042 lines

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