home *** CD-ROM | disk | FTP | other *** search
/ CD Shareware Magazine 1997 January / CD_shareware_1-97.iso / DOS / JUEGOS / QPLUS15.ZIP / WEAPONS.QC < prev    next >
Encoding:
Text File  |  1996-09-27  |  46.5 KB  |  1,985 lines

  1. void (entity targ, entity inflictor, entity attacker, float damage) T_Damage;
  2. void () player_run;
  3. void (entity bomb, entity attacker, float rad, entity ignore) T_RadiusDamage;
  4. void (vector org, vector vel, float damage) SpawnBlood;
  5. void () SuperDamageSound;
  6. void () W_FireTeleportBomb;                //ws...
  7. void () Teleport_to_bomb;
  8. void () W_FireFlame;
  9. void () BurnSelf;
  10. void () DisplayCompass;
  11. void () ServerNews;
  12. void (vector org) spawn_tfog;
  13. void (vector org, entity death_owner) spawn_tdeath;        //...ws
  14.  
  15. // called by worldspawn
  16. void() W_Precache =
  17. {
  18.     precache_sound ("weapons/r_exp3.wav");    // new rocket explosion
  19.     precache_sound ("weapons/rocket1i.wav");    // spike gun
  20.     precache_sound ("weapons/sgun1.wav");
  21.     precache_sound ("weapons/guncock.wav");    // player shotgun
  22.     precache_sound ("weapons/ric1.wav");    // ricochet (used in c code)
  23.     precache_sound ("weapons/ric2.wav");    // ricochet (used in c code)
  24.     precache_sound ("weapons/ric3.wav");    // ricochet (used in c code)
  25.     precache_sound ("weapons/spike2.wav");    // super spikes
  26.     precache_sound ("weapons/tink1.wav");    // spikes tink (used in c code)
  27.     precache_sound ("weapons/grenade.wav");    // grenade launcher
  28.     precache_sound ("weapons/bounce.wav");    // grenade bounce
  29.     precache_sound ("weapons/shotgn2.wav");    // super shotgun
  30.     precache_sound ("zombie/z_hit.wav");        // Axe
  31.  
  32.         precache_sound ("items/damage.wav");        // MOD: Quad damage     //ws...
  33.         precache_sound ("items/protect.wav");      // MOD: Invulnerability 
  34.         precache_sound ("items/inv1.wav");              // MOD: Invisibility
  35.         precache_sound ("items/suit.wav");             // MOD: Suit 
  36.     precache_sound ("hknight/hit.wav");      // flamethrower
  37.     precache_sound("buttons/Switch21.wav");    //flashlight
  38.     
  39.     precache_sound ("items/protect2.wav");
  40.     precache_sound ("items/protect3.wav");
  41.     precache_sound ("items/suit2.wav");
  42.     precache_sound ("items/inv2.wav");
  43.     precache_sound ("items/inv3.wav");
  44.     precache_sound ("items/damage2.wav");
  45.     precache_sound ("items/damage3.wav");                //...ws
  46.         
  47.     precache_model ("progs/w_s_key.mdl");
  48.     precache_model ("progs/m_s_key.mdl");
  49. //ws    precache_model2 ("progs/b_s_key.mdl");
  50.     precache_model ("progs/w_g_key.mdl");
  51.     precache_model ("progs/m_g_key.mdl");
  52. //ws    precache_model2 ("progs/b_g_key.mdl");
  53.  
  54.     precache_model ("progs/g_shot.mdl");
  55.     precache_model ("progs/g_nail.mdl");
  56.     precache_model ("progs/g_nail2.mdl");
  57.     precache_model ("progs/g_rock.mdl");
  58.     precache_model ("progs/g_rock2.mdl");
  59.     precache_model ("progs/g_light.mdl");
  60.  
  61. };
  62.  
  63. float() crandom =
  64. {
  65.     return 2*(random() - 0.5);
  66. };
  67.  
  68. /*
  69. ================
  70. W_FireAxe
  71. ================
  72. */
  73. void(entity newfriend) player_addfriend;        //ws
  74.  
  75. void() W_FireAxe =
  76. {
  77.     local    vector    source;
  78.     local    vector    org;
  79.     local     entity    trace_ent, oldself;    //ws
  80.  
  81.     source = self.origin + '0 0 16';
  82.     traceline (source, source + v_forward*64, FALSE, self);
  83.     if (trace_fraction == 1.0)
  84.         return;
  85.     
  86.     org = trace_endpos - v_forward*4;
  87.  
  88.     if (trace_ent.takedamage)
  89.     {
  90.         sound (self, CHAN_WEAPON, "zombie/z_hit.wav", 1, ATTN_NORM);
  91.         // Some sort of thunking sound ...
  92.         trace_ent.axhitme = 1;
  93.         if (trace_ent.classname == "monster_dog" || trace_ent.classname == "monster_army")    //ws... friend
  94.         {                                    
  95.         trace_ent.flags & FL_FRIENDLY;
  96.         trace_ent.touch=FriendMove;
  97.         trace_ent.friend=trace_ent.enemy;
  98.         oldself=trace_ent;
  99.         trace_ent=trace_ent.friend;
  100.         player_addfriend(oldself);
  101.         trace_ent=oldself;
  102.         }
  103.         else                    //...ws                
  104.         SpawnBlood (org, '0 0 0', 20);        
  105.         T_Damage (trace_ent, self, self, 20);
  106.     }
  107.     else
  108.     {    // hit wall
  109.         sound (self, CHAN_WEAPON, "player/axhit2.wav", 1, ATTN_NORM);
  110.         WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  111.         WriteByte (MSG_BROADCAST, TE_GUNSHOT);
  112.         WriteCoord (MSG_BROADCAST, org_x);
  113.         WriteCoord (MSG_BROADCAST, org_y);
  114.         WriteCoord (MSG_BROADCAST, org_z);
  115.     }
  116. };
  117.  
  118.  
  119. //============================================================================
  120.  
  121.  
  122. vector() wall_velocity =
  123. {
  124.     local vector    vel;
  125.     
  126.     vel = normalize (self.velocity);
  127.     vel = normalize(vel + v_up*(random()- 0.5) + v_right*(random()- 0.5));
  128.     vel = vel + 2*trace_plane_normal;
  129.     vel = vel * 200;
  130.     
  131.     return vel;
  132. };
  133.  
  134.  
  135. /*
  136. ================
  137. SpawnMeatSpray
  138. ================
  139. */
  140. void(vector org, vector vel) SpawnMeatSpray =
  141. {
  142.     local    entity missile, mpuff;
  143.     local    vector    org;
  144.  
  145.     missile = spawn ();
  146.     missile.owner = self;
  147.     missile.movetype = MOVETYPE_BOUNCE;
  148.     missile.solid = SOLID_NOT;
  149.  
  150.     makevectors (self.angles);
  151.  
  152.     missile.velocity = vel;
  153.     missile.velocity_z = missile.velocity_z + 250 + 50*random();
  154.  
  155.     missile.avelocity = '3000 1000 2000';
  156.     
  157. // set missile duration
  158.     missile.nextthink = time + 30;
  159.     missile.think = SUB_Remove;
  160.  
  161.     setmodel (missile, "progs/zom_gib.mdl");
  162.     setsize (missile, '0 0 0', '0 0 0');        
  163.     setorigin (missile, org);
  164. };
  165.  
  166. /*
  167. ================
  168. SpawnBlood
  169. ================
  170. */
  171. void(vector org, vector vel, float damage) SpawnBlood =
  172. {
  173.     if (trace_ent.flags & FL_OBJECT || self.flags & FL_OBJECT || other.flags & FL_OBJECT )    //ws... solid objects
  174.             particle (org, vel*0.1, 10, damage*2);    
  175.     else particle (org, vel*0.1, 73, damage*2);                        //...ws
  176. };
  177.  
  178. /*
  179. ================
  180. spawn_touchblood
  181. ================
  182. */
  183. void(float damage) spawn_touchblood =
  184. {
  185.     local vector    vel;
  186.  
  187.     vel = wall_velocity () * 0.2;
  188.     SpawnBlood (self.origin + vel*0.01, vel, damage);
  189. };
  190.  
  191.  
  192. /*
  193. ================
  194. SpawnChunk
  195. ================
  196. */
  197. void(vector org, vector vel) SpawnChunk =
  198. {
  199.     particle (org, vel*0.02, 0, 10);
  200. };
  201.  
  202. /*
  203. ==============================================================================
  204.  
  205. MULTI-DAMAGE
  206.  
  207. Collects multiple small damages into a single damage
  208.  
  209. ==============================================================================
  210. */
  211.  
  212. entity    multi_ent;
  213. float    multi_damage;
  214.  
  215. void() ClearMultiDamage =
  216. {
  217.     multi_ent = world;
  218.     multi_damage = 0;
  219. };
  220.  
  221. void() ApplyMultiDamage =
  222. {
  223.     if (!multi_ent)
  224.         return;
  225.     T_Damage (multi_ent, self, self, multi_damage);
  226. };
  227.  
  228. void(entity hit, float damage) AddMultiDamage =
  229. {
  230.     if (!hit)
  231.         return;
  232.     
  233.     if (hit != multi_ent)
  234.     {
  235.         ApplyMultiDamage ();
  236.         multi_damage = damage;
  237.         multi_ent = hit;
  238.     }
  239.     else
  240.         multi_damage = multi_damage + damage;
  241. };
  242.  
  243. /*
  244. ==============================================================================
  245.  
  246. BULLETS
  247.  
  248. ==============================================================================
  249. */
  250.  
  251. /*
  252. ================
  253. TraceAttack
  254. ================
  255. */
  256. void(float damage, vector dir) TraceAttack =
  257. {
  258.     local    vector    vel, org;
  259.     local     entity     mark;
  260.     
  261.     vel = normalize(dir + v_up*crandom() + v_right*crandom());
  262.     vel = vel + 2*trace_plane_normal;
  263.     vel = vel * 200;
  264.  
  265.     org = trace_endpos - dir*4;
  266.  
  267.     if (trace_ent.takedamage)
  268.     {
  269.         SpawnBlood (org, vel*0.2, damage);
  270.         AddMultiDamage (trace_ent, damage);
  271.     }
  272.     else
  273.     {
  274.         WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  275.         WriteByte (MSG_BROADCAST, TE_GUNSHOT);
  276.         WriteCoord (MSG_BROADCAST, org_x);
  277.         WriteCoord (MSG_BROADCAST, org_y);
  278.         WriteCoord (MSG_BROADCAST, org_z);
  279.  
  280.     if (trace_ent.classname == "door" || trace_ent.classname == "plat")    //ws... marks
  281.         return;
  282.     else    {
  283.     mark= spawn ();
  284.     mark.movetype = MOVETYPE_NONE;
  285.     mark.solid = SOLID_NOT;
  286.     mark.touch = SUB_Null;
  287.     mark.velocity = '0 0 0';
  288.     mark.angles = vectoangles(dir);
  289.     
  290.     setmodel (mark, "progs/spike.mdl");
  291.     setsize (mark, VEC_ORIGIN, VEC_ORIGIN);
  292.     setorigin (mark, org - vel * 0.015 );
  293.     
  294.     mark.think = SUB_Remove;                
  295.     mark.nextthink = time + 10;
  296.         }                            //...ws
  297.     }
  298. };
  299.  
  300. /*
  301. ================
  302. FireBullets
  303.  
  304. Used by shotgun, super shotgun, and enemy soldier firing
  305. Go to the trouble of combining multiple pellets into a single damage call.
  306. ================
  307. */
  308. void(float shotcount, vector dir, vector spread) FireBullets =
  309. {
  310.     local    vector direction;
  311.     local    vector    src;
  312.     
  313.     makevectors(self.v_angle);
  314.  
  315.     src = self.origin + v_forward*10;
  316.     src_z = self.absmin_z + self.size_z * 0.7;
  317.  
  318.     ClearMultiDamage ();
  319.     while (shotcount > 0)
  320.     {
  321.         direction = dir + crandom()*spread_x*v_right + crandom()*spread_y*v_up;
  322.  
  323.         traceline (src, src + direction*2048, FALSE, self);
  324.         if (trace_fraction != 1.0)
  325.             TraceAttack (4, direction);
  326.  
  327.         shotcount = shotcount - 1;
  328.     }
  329.     ApplyMultiDamage ();
  330. };
  331.  
  332. /*
  333. ================
  334. W_FireShotgun
  335. ================
  336. */
  337. void() W_FireShotgun =
  338. {
  339.     local vector dir;
  340.  
  341.     sound (self, CHAN_WEAPON, "weapons/guncock.wav", 1, ATTN_NORM);    
  342.  
  343.     self.punchangle_x = -2;
  344.     
  345.     self.currentammo = self.ammo_shells = self.ammo_shells - 1;
  346.     dir = aim (self, 100000);
  347.     FireBullets (6, dir, '0.04 0.04 0');
  348. };
  349.  
  350.  
  351. /*
  352. ================
  353. W_FireSuperShotgun
  354. ================
  355. */
  356. void() W_FireSuperShotgun =
  357. {
  358.     local vector dir;
  359.  
  360.     if (self.currentammo == 1)
  361.     {
  362.         W_FireShotgun ();
  363.         return;
  364.     }
  365.         
  366.     sound (self ,CHAN_WEAPON, "weapons/shotgn2.wav", 1, ATTN_NORM);    
  367.  
  368.     self.punchangle_x = -4;
  369.     self.velocity = self.velocity + v_forward * -30;    //ws backkick
  370.     
  371.     self.currentammo = self.ammo_shells = self.ammo_shells - 2;
  372.     dir = aim (self, 100000);
  373.     FireBullets (14, dir, '0.14 0.08 0');
  374. };
  375.  
  376.  
  377. /*
  378. ==============================================================================
  379.  
  380. ROCKETS
  381.  
  382. ==============================================================================
  383. */
  384. void() flare_bright;
  385. void() flare_dim;
  386.  
  387. void()    s_explode1    =    [0,        s_explode2] {};
  388. void()    s_explode2    =    [1,        s_explode3] {};
  389. void()    s_explode3    =    [2,        s_explode4] {};
  390. void()    s_explode4    =    [3,        s_explode5] {};
  391. void()    s_explode5    =    [4,        s_explode6] {};
  392. void()    s_explode6    =    [5,        SUB_Remove] {};
  393.  
  394. void() BecomeExplosion =
  395. {
  396.     self.movetype = MOVETYPE_NONE;
  397.     self.velocity = '0 0 0';
  398.     self.touch = SUB_Null;
  399.     setmodel (self, "progs/s_explod.spr");
  400.     self.solid = SOLID_NOT;
  401.     s_explode1 ();
  402. };
  403.  
  404. /*ws... flare
  405. ==============================
  406. flare_bright()
  407. This function makes the flare
  408. emit brighter light
  409. ==============================
  410. */
  411.  
  412. void() flare_bright =
  413. {
  414.     local vector    vel;
  415.     self.effects=EF_BRIGHTLIGHT;
  416.     self.nextthink = time + 5;
  417.     self.think = flare_dim;
  418.     sound (self, CHAN_WEAPON, "misc/power.wav", 1, ATTN_NORM);
  419. // Set up some red and yellow sparks
  420.     vel = '0 0 150';
  421.     particle (self.origin+vel*0.01,vel,111,150);
  422.     vel = '0 0 120';
  423.     particle (self.origin+vel*0.01,vel,73,200);
  424. };
  425.  
  426. /*
  427. ==============================
  428. flare_dim()
  429. This function makes the flare
  430. go dim again
  431. ==============================
  432. */
  433.  
  434. void() flare_dim =
  435. {
  436.     self.effects=EF_DIMLIGHT;
  437.     self.nextthink = time + 3;
  438.     self.think = SUB_Remove;
  439. };                    //...ws
  440.  
  441. void() T_MissileTouch =
  442. {
  443.     local float    damg;
  444.  
  445.     if (other == self.owner)
  446.         return;        // don't explode on owner
  447.  
  448.     if (pointcontents(self.origin) == CONTENT_SKY)
  449.     {
  450.         remove(self);
  451.         return;
  452.     }
  453.  
  454.     damg = 100 + random()*20;
  455.     
  456.     if ((other.health) || (other.classname == "door" || other.classname == "plat"))
  457.     {
  458.         if (other.classname == "monster_shambler")
  459.             damg = damg * 0.5;    // mostly immune
  460.         T_Damage (other, self, self.owner, damg );
  461.  
  462. // don't do radius damage to the other, because all the damage    //ws...
  463. // was done in the impact                    
  464.     T_RadiusDamage (self, self.owner, 120, other);
  465. //    sound (self, CHAN_WEAPON, "weapons/r_exp3.wav", 1, ATTN_NORM);
  466.     self.origin = self.origin - 8*normalize(self.velocity);
  467.  
  468.     WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  469.     WriteByte (MSG_BROADCAST, TE_EXPLOSION);
  470.     WriteCoord (MSG_BROADCAST, self.origin_x);
  471.     WriteCoord (MSG_BROADCAST, self.origin_y);
  472.     WriteCoord (MSG_BROADCAST, self.origin_z);
  473.  
  474.     BecomeExplosion ();
  475.     }
  476.     else                        //ws... flare
  477.     {
  478.     if (other.solid == SOLID_TRIGGER)
  479.         return; // trigger field, do nothing
  480.  
  481.     self.movetype = MOVETYPE_NONE;        
  482. // Fix it so that flare only partially embeds itself (thanks, Luke)    
  483.             self.origin = self.origin - self.velocity * 0.001;        //ws
  484.          self.velocity = '0 0 0';
  485.     self.touch = SUB_Null;
  486.     
  487.     self.think = flare_bright;                
  488.     self.nextthink = time + 1;                //...ws
  489.     }
  490. };
  491.  
  492. /*
  493. ================
  494. W_FireRocket
  495. ================
  496. */
  497. void()   HomeThink;    //ws... homing
  498. entity() HomeFindTarget;
  499. float(entity targ) visible;
  500. float(entity targ) infront;    //...ws
  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.     self.velocity = self.velocity + v_forward * -150;    //ws backkick
  521.  
  522.     missile.velocity = aim(self, 1000);
  523.     missile.velocity = missile.velocity * 700;    //ws
  524.     missile.angles = vectoangles(missile.velocity);
  525.     
  526.     missile.touch = T_MissileTouch;
  527.     
  528.     missile.nextthink = time + 0.2;    //ws... homing
  529.     missile.think = HomeThink;
  530.     missile.enemy = world;        //...ws
  531.  
  532.     setmodel (missile, "progs/missile.mdl");
  533.     setsize (missile, '0 0 0', '0 0 0');        
  534.     setorigin (missile, self.origin + v_forward*8 + '0 0 16');
  535. };
  536.  
  537. entity() HomeFindTarget =         //ws... homing
  538. {
  539.     local entity head, selected;
  540.     local float dist;
  541.     dist = 10000;
  542.     selected = world;
  543.     head = findradius(self.origin, 100);
  544.     while(head)
  545.     {
  546.                 if( (head.health > 1) && (head != self) && (head != self.owner) && !(head.items & IT_INVISIBILITY) )
  547.         {
  548.             traceline(self.origin,head.origin,TRUE,self);
  549.             if ( (trace_fraction >= 1) && (vlen(head.origin - self.origin) < dist) )
  550.             {
  551.                 selected = head;
  552.                 dist = vlen(head.origin - self.origin);
  553.             }
  554.         }        
  555.         head = head.chain;
  556.     }
  557.     return selected;
  558. };
  559.  
  560. void() HomeThink =
  561. {
  562.         local vector dir, olddir, vtemp;
  563.         local float turnrate;
  564.  
  565.         turnrate= 0.2;
  566.     if ( !(self.enemy) || (self.enemy == world) || (self.enemy.health < 1) )
  567.         self.enemy = HomeFindTarget();
  568.  
  569.     if (self.enemy != world) // Arr.. don't be taken on da World!
  570.     {
  571.         vtemp = self.enemy.origin + '0 0 10';
  572.                 olddir = normalize(self.velocity);
  573.         dir = normalize(vtemp - self.origin);
  574.                 //Limits the turnrate of the rockets
  575.                 if (olddir_x - dir_x > turnrate)
  576.                         dir_x = olddir_x - turnrate;
  577.                 if (olddir_x - dir_x < -1 * turnrate)
  578.                         dir_x = olddir_x + turnrate;
  579.                 if (olddir_y - dir_y > turnrate)
  580.                         dir_y = olddir_y - turnrate;
  581.                 if (olddir_y - dir_y < -1 * turnrate)
  582.                         dir_y = olddir_y + turnrate;
  583.                 if (olddir_z - dir_z > turnrate)
  584.                         dir_z = olddir_z - turnrate;
  585.                 if (olddir_z - dir_z < -1 * turnrate)
  586.                         dir_z = olddir_z + turnrate;
  587.                 self.velocity = dir * 230;
  588.         self.angles = vectoangles(self.velocity);
  589.     }
  590.  
  591.     self.nextthink = time + 0.2;
  592.     self.think=HomeThink;
  593. };                        //...ws
  594.  
  595. /*
  596. ===============================================================================
  597.  
  598. LIGHTNING
  599.  
  600. ===============================================================================
  601. */
  602.  
  603. /*
  604. =================
  605. LightningDamage
  606. =================
  607. */
  608. void(vector p1, vector p2, entity from, float damage) LightningDamage =
  609. {
  610.     local entity        e1, e2;
  611.     local vector        f;
  612.     
  613.     f = p2 - p1;
  614.     normalize (f);
  615.     f_x = 0 - f_y;
  616.     f_y = f_x;
  617.     f_z = 0;
  618.     f = f*16;
  619.  
  620.     e1 = e2 = world;
  621.  
  622.     traceline (p1, p2, FALSE, self);
  623.     if (trace_ent.takedamage)
  624.     {
  625.     if (trace_ent.flags & FL_OBJECT || self.flags & FL_OBJECT || other.flags & FL_OBJECT )    //ws... solid objects
  626.             particle (trace_endpos, '0 0 100', 10, damage*4);
  627.     else particle (trace_endpos, '0 0 100', 225, damage*4);                    //...ws
  628.         T_Damage (trace_ent, from, from, damage);
  629.         if (self.classname == "player")
  630.         {
  631.             if (other.classname == "player")
  632.                 trace_ent.velocity_z = trace_ent.velocity_z + 400;
  633.         }
  634.     }
  635.     e1 = trace_ent;
  636.  
  637.     traceline (p1 + f, p2 + f, FALSE, self);
  638.     if (trace_ent != e1 && trace_ent.takedamage)
  639.     {
  640.     if (trace_ent.flags & FL_OBJECT || self.flags & FL_OBJECT || other.flags & FL_OBJECT )    //ws... solid objects
  641.             particle (trace_endpos, '0 0 100', 10, damage*4);
  642.     else particle (trace_endpos, '0 0 100', 225, damage*4);                    //...ws
  643.         T_Damage (trace_ent, from, from, damage);
  644.     }
  645.     e2 = trace_ent;
  646.  
  647.     traceline (p1 - f, p2 - f, FALSE, self);
  648.     if (trace_ent != e1 && trace_ent != e2 && trace_ent.takedamage)
  649.     {
  650.     if (trace_ent.flags & FL_OBJECT || self.flags & FL_OBJECT || other.flags & FL_OBJECT )    //ws... solid objects
  651.             particle (trace_endpos, '0 0 100', 10, damage*4);
  652.     else particle (trace_endpos, '0 0 100', 225, damage*4);                    //...ws
  653.         T_Damage (trace_ent, from, from, damage);
  654.     }
  655. };
  656.  
  657. void() W_FireLightning =
  658. {
  659.     local    vector        org;
  660.  
  661.     if (self.ammo_cells < 1)
  662.     {
  663.         self.weapon = W_BestWeapon ();
  664.         W_SetCurrentAmmo ();
  665.         return;
  666.     }
  667.  
  668. // explode if under water
  669.     if (self.waterlevel > 1)
  670.     {
  671.         T_RadiusDamage (self, self, 35*self.ammo_cells, world);
  672.         self.ammo_cells = 0;
  673.         W_SetCurrentAmmo ();
  674.         return;
  675.     }
  676.  
  677.     if (self.t_width < time)
  678.     {
  679.         sound (self, CHAN_WEAPON, "weapons/lhit.wav", 1, ATTN_NORM);
  680.         self.t_width = time + 0.6;
  681.     }
  682.     self.punchangle_x = -2;
  683.  
  684.     self.currentammo = self.ammo_cells = self.ammo_cells - 1;
  685.  
  686.     org = self.origin + '0 0 16';
  687.     
  688.     traceline (org, org + v_forward*600, TRUE, self);
  689.  
  690.     WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  691.     WriteByte (MSG_BROADCAST, TE_LIGHTNING2);
  692.     WriteEntity (MSG_BROADCAST, self);
  693.     WriteCoord (MSG_BROADCAST, org_x);
  694.     WriteCoord (MSG_BROADCAST, org_y);
  695.     WriteCoord (MSG_BROADCAST, org_z);
  696.     WriteCoord (MSG_BROADCAST, trace_endpos_x);
  697.     WriteCoord (MSG_BROADCAST, trace_endpos_y);
  698.     WriteCoord (MSG_BROADCAST, trace_endpos_z);
  699.  
  700.     LightningDamage (self.origin, trace_endpos + v_forward*4, self, 30);
  701. };
  702.  
  703. /*
  704. ===============================================================================
  705.  
  706. GRENADES
  707.  
  708. ===============================================================================
  709. */
  710.  
  711. void() GrenadeExplode =
  712. {
  713.     T_RadiusDamage (self, self.owner, 120, world);
  714.  
  715.     WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  716.     WriteByte (MSG_BROADCAST, TE_EXPLOSION);
  717.     WriteCoord (MSG_BROADCAST, self.origin_x);
  718.     WriteCoord (MSG_BROADCAST, self.origin_y);
  719.     WriteCoord (MSG_BROADCAST, self.origin_z);
  720.  
  721.     BecomeExplosion ();
  722. };
  723.  
  724. void() GrenadeTouch =
  725. {
  726.     if (other == self.owner)
  727.         return;        // don't explode on owner
  728.     if (other.takedamage == DAMAGE_AIM)
  729.     {
  730.         GrenadeExplode();
  731.         return;
  732.     }
  733.     sound (self, CHAN_WEAPON, "weapons/bounce.wav", 1, ATTN_NORM);    // bounce sound
  734.     if (self.velocity == '0 0 0')
  735.         self.avelocity = '0 0 0';
  736. };
  737.  
  738. /*
  739. ================
  740. W_FireGrenade
  741. ================
  742. */
  743. void() CheckProximity;        //ws
  744. void() T_ProximityBlowUp;    //ws
  745.  
  746. void() W_FireGrenade =
  747. {
  748.     local    entity missile, mpuff;
  749.     
  750.     self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
  751.     
  752.     sound (self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
  753.  
  754.     self.punchangle_x = -2;
  755.  
  756.     missile = spawn ();
  757.     missile.owner = self;
  758.     missile.movetype = MOVETYPE_BOUNCE;
  759.     missile.solid = SOLID_BBOX;
  760.     missile.classname = "grenade";
  761.         
  762. // set missile speed    
  763.  
  764.     makevectors (self.v_angle);
  765.     self.velocity = self.velocity + v_forward * -100;    //ws backkick
  766.  
  767.     if (self.v_angle_x)
  768.         missile.velocity = v_forward*600 + v_up * 200 + crandom()*v_right*10 + crandom()*v_up*10;
  769.     else
  770.     {
  771.         missile.velocity = aim(self, 10000);
  772.         missile.velocity = missile.velocity * 600;
  773.         missile.velocity_z = 200;
  774.     }
  775.  
  776.     missile.avelocity = '300 300 300';
  777.     missile.angles = vectoangles(missile.velocity);
  778.     missile.touch = GrenadeTouch;
  779.     
  780. // set missile duration
  781.     missile.nextthink = time + 1;
  782.     missile.think = CheckProximity;        //ws mines
  783.  
  784.     setmodel (missile, "progs/missile.mdl");    //ws
  785.     setsize (missile, '0 0 0', '4 4 4');        //ws        
  786.     setorigin (missile, self.origin);
  787. };
  788.  
  789. void() CheckProximity =            //ws... mines
  790. {
  791.     local entity head, selected;
  792.     local float dist;
  793.     dist = 128;
  794.     selected = world;
  795.     head = findradius(self.origin, 128);
  796.     while(head)
  797.     {
  798.                 if( (head.health > 1) && (head != self) )
  799.         {
  800.             traceline(self.origin,head.origin,TRUE,self);
  801.             if ( (vlen(head.origin - self.origin) < dist) )
  802.             {
  803.                 selected = head;
  804.                 dist = vlen(head.origin - self.origin);
  805.             }
  806.         }
  807.         head = head.chain;
  808.     }
  809.     if (dist<128)
  810.         {
  811.         T_ProximityBlowUp();
  812.         return;
  813.         }
  814.     self.nextthink = 0.5;
  815.     self.think = CheckProximity;
  816.  
  817.     self.health = 1;                //ws...
  818.     self.th_die = T_ProximityBlowUp;
  819.     self.takedamage = DAMAGE_AIM;        //...ws
  820. };
  821. void() T_ProximityBlowUp =
  822. {
  823.     local float    damg;
  824.  
  825.     if (pointcontents(self.origin) == CONTENT_SKY)
  826.     {
  827.         remove(self);
  828.         return;
  829.     }
  830.  
  831.     damg = 100 + random()*20;
  832.  
  833.     if (other.health)
  834.     {
  835.         if (other.classname == "monster_shambler")
  836.             damg = damg * 0.5;    // mostly immune
  837.         T_Damage (other, self, self.owner, damg );
  838.     }
  839.  
  840.     // don't do radius damage to the other, because all the damage
  841.     // was done in the impact
  842.     T_RadiusDamage (self, self.owner, 256, other);
  843.  
  844. //    sound (self, CHAN_WEAPON, "weapons/r_exp3.wav", 1, ATTN_NORM);
  845.     self.origin = self.origin - 8*normalize(self.velocity);
  846.  
  847.     WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  848.     WriteByte (MSG_BROADCAST, TE_EXPLOSION);
  849.     WriteCoord (MSG_BROADCAST, self.origin_x);
  850.     WriteCoord (MSG_BROADCAST, self.origin_y);
  851.     WriteCoord (MSG_BROADCAST, self.origin_z);
  852.  
  853.     BecomeExplosion ();
  854. };                //...ws
  855.  
  856. /*
  857. ===============================================================================
  858.  
  859. NAILS
  860.  
  861. ===============================================================================
  862. */
  863.  
  864. void() spike_touch;
  865. void() superspike_touch;
  866.  
  867.  
  868. /*
  869. ===============
  870. launch_spike
  871. ===============
  872. */
  873. void(vector org, vector dir) launch_spike =
  874. {
  875.     newmis = spawn ();
  876.     newmis.owner = self;
  877.     newmis.movetype = MOVETYPE_FLYMISSILE;
  878.     newmis.solid = SOLID_BBOX;
  879.  
  880.     newmis.angles = vectoangles(dir);
  881.     self.velocity = self.velocity + v_forward * -10;    //ws backkick
  882.     
  883.     newmis.touch = spike_touch;
  884.     newmis.classname = "spike";
  885.     newmis.think = SUB_Remove;
  886.     newmis.nextthink = time + 6;
  887.     setmodel (newmis, "progs/s_spike.mdl");        //ws spike model
  888.     setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);        
  889.     setorigin (newmis, org);
  890.  
  891.     newmis.velocity = dir * 1000;
  892. };
  893.  
  894. void() W_FireSuperSpikes =
  895. {
  896.     local vector    dir;
  897.     local entity    old;
  898.     
  899.     sound (self, CHAN_WEAPON, "weapons/spike2.wav", 1, ATTN_NORM);
  900.     self.attack_finished = time + 0.2;
  901.     self.currentammo = self.ammo_nails = self.ammo_nails - 2;
  902.     dir = aim (self, 1000);
  903.     launch_spike (self.origin + '0 0 16', dir);
  904.     newmis.touch = superspike_touch;
  905.     setmodel (newmis, "progs/s_spike.mdl");
  906.     setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);        
  907.     self.punchangle_x = -2;
  908. };
  909.  
  910. void(float ox) W_FireSpikes =
  911. {
  912.     local vector    dir;
  913.     local entity    old;
  914.     
  915.     makevectors (self.v_angle);
  916.     
  917.     if (self.ammo_nails >= 2 && self.weapon == IT_SUPER_NAILGUN)
  918.     {
  919.         W_FireSuperSpikes ();
  920.         return;
  921.     }
  922.  
  923.     if (self.ammo_nails < 1)
  924.     {
  925.         self.weapon = W_BestWeapon ();
  926.         W_SetCurrentAmmo ();
  927.         return;
  928.     }
  929.  
  930.     sound (self, CHAN_WEAPON, "weapons/rocket1i.wav", 1, ATTN_NORM);
  931.     self.attack_finished = time + 0.2;
  932.     self.currentammo = self.ammo_nails = self.ammo_nails - 1;
  933.     dir = aim (self, 1000);
  934.     launch_spike (self.origin + '0 0 16' + v_right*ox, dir);
  935.  
  936.     self.punchangle_x = -2;
  937. };
  938.  
  939. .float hit_z;
  940. void() spike_touch =
  941. {
  942. local float rand;
  943.     if (other == self.owner)
  944.         return;
  945.  
  946.     if (other.solid == SOLID_TRIGGER)
  947.         return;    // trigger field, do nothing
  948.  
  949.     if (pointcontents(self.origin) == CONTENT_SKY)
  950.     {
  951.         remove(self);
  952.         return;
  953.     }
  954.     
  955. // hit something that bleeds
  956.     if (other.takedamage)
  957.     {        
  958.         spawn_touchblood (9);
  959.         T_Damage (other, self, self.owner, 9);
  960.         remove(self);                    //ws
  961.     }
  962.     else
  963.     {
  964.         WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  965.         
  966.         if (self.classname == "wizspike")
  967.             WriteByte (MSG_BROADCAST, TE_WIZSPIKE);
  968.         else if (self.classname == "knightspike")
  969.             WriteByte (MSG_BROADCAST, TE_KNIGHTSPIKE);
  970.         else
  971.             WriteByte (MSG_BROADCAST, TE_SPIKE);
  972.         WriteCoord (MSG_BROADCAST, self.origin_x);
  973.         WriteCoord (MSG_BROADCAST, self.origin_y);
  974.         WriteCoord (MSG_BROADCAST, self.origin_z);
  975.  
  976.     if (other.classname == "door" || other.classname == "plat")    //ws... marks
  977.         remove(self);
  978.     else    {
  979.     self.movetype = MOVETYPE_NONE;
  980.     self.origin = self.origin - self.velocity * 0.004;    
  981.          self.velocity = '0 0 0';
  982.     self.touch = SUB_Null;
  983.  
  984.     self.think = SUB_Remove;                
  985.     self.nextthink = time + 10;
  986.         }                        //...ws
  987.     }
  988. };
  989.  
  990. void() superspike_touch =
  991. {
  992. local float rand;
  993.     if (other == self.owner)
  994.         return;
  995.  
  996.     if (other.solid == SOLID_TRIGGER)
  997.         return;    // trigger field, do nothing
  998.  
  999.     if (pointcontents(self.origin) == CONTENT_SKY)
  1000.     {
  1001.         remove(self);
  1002.         return;
  1003.     }
  1004.     
  1005. // hit something that bleeds
  1006.     if (other.takedamage)
  1007.     {
  1008.         spawn_touchblood (18);
  1009.         T_Damage (other, self, self.owner, 18);
  1010.         remove(self);                    //ws
  1011.     }
  1012.     else
  1013.     {
  1014.         WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  1015.         WriteByte (MSG_BROADCAST, TE_SUPERSPIKE);
  1016.         WriteCoord (MSG_BROADCAST, self.origin_x);
  1017.         WriteCoord (MSG_BROADCAST, self.origin_y);
  1018.         WriteCoord (MSG_BROADCAST, self.origin_z);
  1019.  
  1020.     if (other.classname == "door" || other.classname == "plat")    //ws... marks
  1021.         remove(self);
  1022.     else    {
  1023.     self.movetype = MOVETYPE_NONE;    
  1024.             self.origin = self.origin - self.velocity * 0.002;    
  1025.          self.velocity = '0 0 0';
  1026.     self.touch = SUB_Null;
  1027.     
  1028.     self.think = SUB_Remove;                
  1029.     self.nextthink = time + 10;
  1030.         }                        //...ws
  1031.     }
  1032. };
  1033.  
  1034. /*
  1035. ===============================================================================
  1036.  
  1037. PLAYER WEAPON USE
  1038.  
  1039. ===============================================================================
  1040. */
  1041.  
  1042. void() W_SetCurrentAmmo =
  1043. {
  1044.     player_run ();        // get out of any weapon firing states
  1045.  
  1046.     self.items = self.items - ( self.items & (IT_SHELLS | IT_NAILS | IT_ROCKETS | IT_CELLS) );
  1047.     
  1048.     if (self.weapon == IT_AXE)
  1049.     {
  1050.         self.currentammo = 0;
  1051.         self.weaponmodel = "progs/v_axe.mdl";
  1052.         self.weaponframe = 0;
  1053.     }
  1054.     else if (self.weapon == IT_SHOTGUN)
  1055.     {
  1056.         self.currentammo = self.ammo_shells;
  1057.         self.weaponmodel = "progs/v_shot.mdl";
  1058.         self.weaponframe = 0;
  1059.         self.items = self.items | IT_SHELLS;
  1060.     }
  1061.     else if (self.weapon == IT_SUPER_SHOTGUN)
  1062.     {
  1063.         self.currentammo = self.ammo_shells;
  1064.         self.weaponmodel = "progs/v_shot2.mdl";
  1065.         self.weaponframe = 0;
  1066.         self.items = self.items | IT_SHELLS;
  1067.     }
  1068.     else if (self.weapon == IT_NAILGUN)
  1069.     {
  1070.         self.currentammo = self.ammo_nails;
  1071.         self.weaponmodel = "progs/v_nail.mdl";
  1072.         self.weaponframe = 0;
  1073.         self.items = self.items | IT_NAILS;
  1074.     }
  1075.     else if (self.weapon == IT_SUPER_NAILGUN)
  1076.     {
  1077.         self.currentammo = self.ammo_nails;
  1078.         self.weaponmodel = "progs/v_nail2.mdl";
  1079.         self.weaponframe = 0;
  1080.         self.items = self.items | IT_NAILS;
  1081.     }
  1082.     else if (self.weapon == IT_GRENADE_LAUNCHER)
  1083.     {
  1084.         self.currentammo = self.ammo_rockets;
  1085.         self.weaponmodel = "progs/v_rock.mdl";
  1086.         self.weaponframe = 0;
  1087.         self.items = self.items | IT_ROCKETS;
  1088.     }
  1089.     else if (self.weapon == IT_ROCKET_LAUNCHER)
  1090.     {
  1091.         self.currentammo = self.ammo_rockets;
  1092.         self.weaponmodel = "progs/v_rock2.mdl";
  1093.         self.weaponframe = 0;
  1094.         self.items = self.items | IT_ROCKETS;
  1095.     }
  1096.     else if (self.weapon == IT_LIGHTNING)
  1097.     {
  1098.         self.currentammo = self.ammo_cells;
  1099.         self.weaponmodel = "progs/v_light.mdl";
  1100.         self.weaponframe = 0;
  1101.         self.items = self.items | IT_CELLS;
  1102.     }
  1103.     else
  1104.     {
  1105.         self.currentammo = 0;
  1106.         self.weaponmodel = "";
  1107.         self.weaponframe = 0;
  1108.     }
  1109. };
  1110.  
  1111. float() W_BestWeapon =
  1112. {
  1113.     local    float    it;
  1114.     
  1115.     it = self.items;
  1116.  
  1117.     if(self.ammo_cells >= 1 && (it & IT_LIGHTNING) )
  1118.         return IT_LIGHTNING;
  1119.     else if(self.ammo_nails >= 2 && (it & IT_SUPER_NAILGUN) )
  1120.         return IT_SUPER_NAILGUN;
  1121.     else if(self.ammo_shells >= 2 && (it & IT_SUPER_SHOTGUN) )
  1122.         return IT_SUPER_SHOTGUN;
  1123.     else if(self.ammo_nails >= 1 && (it & IT_NAILGUN) )
  1124.         return IT_NAILGUN;
  1125.     else if(self.ammo_shells >= 1 && (it & IT_SHOTGUN) )
  1126.         return IT_SHOTGUN;
  1127.         
  1128. /*
  1129.     if(self.ammo_rockets >= 1 && (it & IT_ROCKET_LAUNCHER) )
  1130.         return IT_ROCKET_LAUNCHER;
  1131.     else if(self.ammo_rockets >= 1 && (it & IT_GRENADE_LAUNCHER) )
  1132.         return IT_GRENADE_LAUNCHER;
  1133.  
  1134. */
  1135.  
  1136.     return IT_AXE;
  1137. };
  1138.  
  1139. float() W_CheckNoAmmo =
  1140. {
  1141.     if (self.currentammo > 0)
  1142.         return TRUE;
  1143.  
  1144.     if (self.weapon == IT_AXE)
  1145.         return TRUE;
  1146.     
  1147.     self.weapon = W_BestWeapon ();
  1148.  
  1149.     W_SetCurrentAmmo ();
  1150.     
  1151. // drop the weapon down
  1152.     return FALSE;
  1153. };
  1154.  
  1155. /*
  1156. ============
  1157. W_Attack
  1158.  
  1159. An attack impulse can be triggered now
  1160. ============
  1161. */
  1162. void()    player_axe1;
  1163. void()    player_axeb1;
  1164. void()    player_axec1;
  1165. void()    player_axed1;
  1166. void()    player_shot1;
  1167. void()    player_nail1;
  1168. void()    player_light1;
  1169. void()    player_rocket1;
  1170.  
  1171. void() W_Attack =
  1172. {
  1173.     local    float    r;
  1174.  
  1175.     if (!W_CheckNoAmmo ())
  1176.         return;
  1177.  
  1178.     makevectors    (self.v_angle);            // calculate forward angle for velocity
  1179.     self.show_hostile = time + 1;    // wake monsters up
  1180.  
  1181.     if (self.weapon == IT_AXE)
  1182.     {
  1183.         sound (self, CHAN_WEAPON, "weapons/ax1.wav", 1, ATTN_NORM);
  1184.         r = random();
  1185.         if (r < 0.25)
  1186.             player_axe1 ();
  1187.         else if (r<0.5)
  1188.             player_axeb1 ();
  1189.         else if (r<0.75)
  1190.             player_axec1 ();
  1191.         else
  1192.             player_axed1 ();
  1193.         self.attack_finished = time + 0.5;
  1194.     }
  1195.     else if (self.weapon == IT_SHOTGUN)
  1196.     {
  1197.         player_shot1 ();
  1198.         W_FireShotgun ();
  1199.         self.attack_finished = time + 0.5;    //ws
  1200.     }
  1201.     else if (self.weapon == IT_SUPER_SHOTGUN)
  1202.     {
  1203.         player_shot1 ();
  1204.         W_FireSuperShotgun ();
  1205.         self.attack_finished = time + 1;    //ws
  1206.     }
  1207.     else if (self.weapon == IT_NAILGUN)
  1208.     {
  1209.         player_nail1 ();
  1210.     }
  1211.     else if (self.weapon == IT_SUPER_NAILGUN)
  1212.     {
  1213.         player_nail1 ();
  1214.     }
  1215.     else if (self.weapon == IT_GRENADE_LAUNCHER)
  1216.     {
  1217.         player_rocket1();
  1218.         W_FireGrenade();
  1219.         self.attack_finished = time + 1;    //ws
  1220.     }
  1221.     else if (self.weapon == IT_ROCKET_LAUNCHER)
  1222.     {
  1223.         player_rocket1();
  1224.         W_FireRocket();
  1225.         self.attack_finished = time + 1.5;    //ws
  1226.     }
  1227.     else if (self.weapon == IT_LIGHTNING)
  1228.     {
  1229.         player_shot1();
  1230.                     W_FireFlame();
  1231.                     if (self.waterlevel >2)
  1232.                                 self.attack_finished = time + 1;
  1233.                         else
  1234.                                 self.attack_finished = time + 0.1;
  1235. /*
  1236.         player_light1();
  1237.         self.attack_finished = time + 0.1;
  1238.         sound (self, CHAN_AUTO, "weapons/lstart.wav", 1, ATTN_NORM);
  1239. */
  1240.     }
  1241. };
  1242.  
  1243. /*
  1244. ============
  1245. W_ChangeWeapon
  1246.  
  1247. ============
  1248. */
  1249. void() W_ChangeWeapon =
  1250. {
  1251.     local    float    it, am, fl;
  1252.     
  1253.     it = self.items;
  1254.     am = 0;
  1255.     
  1256.     if (self.impulse == 1)
  1257.     {
  1258.         fl = IT_AXE;
  1259.     }
  1260.     else if (self.impulse == 2)
  1261.     {
  1262.         fl = IT_SHOTGUN;
  1263.         if (self.ammo_shells < 1)
  1264.             am = 1;
  1265.     }
  1266.     else if (self.impulse == 3)
  1267.     {
  1268.         fl = IT_SUPER_SHOTGUN;
  1269.         if (self.ammo_shells < 2)
  1270.             am = 1;
  1271.     }        
  1272.     else if (self.impulse == 4)
  1273.     {
  1274.         fl = IT_NAILGUN;
  1275.         if (self.ammo_nails < 1)
  1276.             am = 1;
  1277.     }
  1278.     else if (self.impulse == 5)
  1279.     {
  1280.         fl = IT_SUPER_NAILGUN;
  1281.         if (self.ammo_nails < 2)
  1282.             am = 1;
  1283.     }
  1284.     else if (self.impulse == 6)
  1285.     {
  1286.         fl = IT_GRENADE_LAUNCHER;
  1287.         if (self.ammo_rockets < 1)
  1288.             am = 1;
  1289.     }
  1290.     else if (self.impulse == 7)
  1291.     {
  1292.         fl = IT_ROCKET_LAUNCHER;
  1293.         if (self.ammo_rockets < 1)
  1294.             am = 1;
  1295.     }
  1296.     else if (self.impulse == 8)
  1297.     {
  1298.         fl = IT_LIGHTNING;
  1299.         if (self.ammo_cells < 1)
  1300.             am = 1;
  1301.     }
  1302.  
  1303.     self.impulse = 0;
  1304.     
  1305.     if (!(self.items & fl))
  1306.     {    // don't have the weapon or the ammo
  1307.         sprint (self, "no weapon.\n");
  1308.         return;
  1309.     }
  1310.     
  1311.     if (am)
  1312.     {    // don't have the ammo
  1313.         sprint (self, "not enough ammo.\n");
  1314.         return;
  1315.     }
  1316.  
  1317. //
  1318. // set weapon, set ammo
  1319. //
  1320.     self.weapon = fl;        
  1321.     W_SetCurrentAmmo ();
  1322. };
  1323. /*
  1324. ============
  1325. CheatCommand
  1326. ============
  1327. */
  1328. void() CheatCommand =
  1329. {
  1330.     if (deathmatch || coop)
  1331.         return;
  1332.  
  1333.     self.ammo_rockets = 100;
  1334.     self.ammo_nails = 200;
  1335.     self.ammo_shells = 100;
  1336.     self.items = self.items | 
  1337.         IT_AXE |
  1338.         IT_SHOTGUN |
  1339.         IT_SUPER_SHOTGUN |
  1340.         IT_NAILGUN |
  1341.         IT_SUPER_NAILGUN |
  1342.         IT_GRENADE_LAUNCHER |
  1343.         IT_ROCKET_LAUNCHER |
  1344.         IT_KEY1 | IT_KEY2;
  1345.  
  1346.     self.ammo_cells = 200;
  1347.     self.items = self.items | IT_LIGHTNING;
  1348.  
  1349.     self.weapon = IT_ROCKET_LAUNCHER;
  1350.     self.impulse = 0;
  1351.     W_SetCurrentAmmo ();
  1352. };
  1353.  
  1354. /*
  1355. ============
  1356. CycleWeaponCommand
  1357.  
  1358. Go to the next weapon with ammo
  1359. ============
  1360. */
  1361. void() CycleWeaponCommand =
  1362. {
  1363.     local    float    it, am;
  1364.     
  1365.     it = self.items;
  1366.     self.impulse = 0;
  1367.     
  1368.     while (1)
  1369.     {
  1370.         am = 0;
  1371.  
  1372.         if (self.weapon == IT_LIGHTNING)
  1373.         {
  1374.             self.weapon = IT_AXE;
  1375.         }
  1376.         else if (self.weapon == IT_AXE)
  1377.         {
  1378.             self.weapon = IT_SHOTGUN;
  1379.             if (self.ammo_shells < 1)
  1380.                 am = 1;
  1381.         }
  1382.         else if (self.weapon == IT_SHOTGUN)
  1383.         {
  1384.             self.weapon = IT_SUPER_SHOTGUN;
  1385.             if (self.ammo_shells < 2)
  1386.                 am = 1;
  1387.         }        
  1388.         else if (self.weapon == IT_SUPER_SHOTGUN)
  1389.         {
  1390.             self.weapon = IT_NAILGUN;
  1391.             if (self.ammo_nails < 1)
  1392.                 am = 1;
  1393.         }
  1394.         else if (self.weapon == IT_NAILGUN)
  1395.         {
  1396.             self.weapon = IT_SUPER_NAILGUN;
  1397.             if (self.ammo_nails < 2)
  1398.                 am = 1;
  1399.         }
  1400.         else if (self.weapon == IT_SUPER_NAILGUN)
  1401.         {
  1402.             self.weapon = IT_GRENADE_LAUNCHER;
  1403.             if (self.ammo_rockets < 1)
  1404.                 am = 1;
  1405.         }
  1406.         else if (self.weapon == IT_GRENADE_LAUNCHER)
  1407.         {
  1408.             self.weapon = IT_ROCKET_LAUNCHER;
  1409.             if (self.ammo_rockets < 1)
  1410.                 am = 1;
  1411.         }
  1412.         else if (self.weapon == IT_ROCKET_LAUNCHER)
  1413.         {
  1414.             self.weapon = IT_LIGHTNING;
  1415.             if (self.ammo_cells < 1)
  1416.                 am = 1;
  1417.         }
  1418.     
  1419.         if ( (self.items & self.weapon) && am == 0)
  1420.         {
  1421.             W_SetCurrentAmmo ();
  1422.             return;
  1423.         }
  1424.     }
  1425.  
  1426. };
  1427.  
  1428. void() it_flashlight_aim = {                    //ws... flashlight
  1429.     local vector direction, src;
  1430.     local entity pl;
  1431.     local float temp;
  1432.     pl=self.owner;
  1433.     makevectors(pl.v_angle);
  1434.     
  1435.     src = pl.origin + v_forward*10;
  1436.     src_z = pl.absmin_z + pl.size_z * 0.7;
  1437.  
  1438.     direction=aim(pl, 100000);
  1439.     traceline(src, src + direction * 2048, FALSE, pl);
  1440.     src=0.1*src + 0.9*trace_endpos;            //ws
  1441.     setorigin(self, src);
  1442.     if (!pl.deadflag&&trace_ent.flags&FL_MONSTER&&!trace_ent.enemy)        //ws... wake
  1443.         {
  1444.         trace_ent.enemy=pl;
  1445.         trace_ent.nextthink=time+0.2;
  1446.         trace_ent.think=FoundTarget;
  1447.         }                                //...ws
  1448.     self.nextthink=time+0.05;
  1449. };
  1450.  
  1451. void() I_FlashlightToggle =
  1452. {
  1453.     local entity oldself;
  1454.     if (self.it_flashlight_on) 
  1455.         {
  1456.         if (self.it_flashlight_entity)    
  1457.             remove (self.it_flashlight_entity);
  1458.         self.it_flashlight_entity=world;
  1459.         self.it_flashlight_on=0;
  1460.         self.effects = self.effects - (self.effects & EF_DIMLIGHT);            //ws
  1461.         sound(self,CHAN_WEAPON,"buttons/Switch21.wav",1,ATTN_NORM);    //ws
  1462.         }
  1463.     else
  1464.         {
  1465.         self.it_flashlight_on=1;
  1466.         self.effects = self.effects | EF_DIMLIGHT;                    //ws
  1467.         oldself=self;
  1468.         self.it_flashlight_entity=spawn();
  1469.         self=self.it_flashlight_entity;
  1470.  
  1471.         self.movetype= MOVETYPE_NONE;
  1472.         self.solid = SOLID_NOT;
  1473.         setmodel(self, "progs/s_bubble.spr");                    //ws
  1474.         setsize (self, '0 0 0', '0 0 0');        
  1475.         
  1476.         self.effects=self.flags=EF_DIMLIGHT;
  1477.         self.owner=oldself;
  1478.         self.nextthink=time+1;
  1479.         self.think=it_flashlight_aim;
  1480.         it_flashlight_aim();
  1481.         self=oldself;
  1482.         sound(self,CHAN_WEAPON,"buttons/Switch21.wav",1,ATTN_NORM);    //ws
  1483.         }                    //...ws
  1484. };
  1485.  
  1486. void() Teleport_to_bomb =            //ws... tele
  1487. {
  1488.     local entity oldself,bdest;
  1489.  
  1490.     bdest=spawn();
  1491.     bdest.origin = self.telebomb.origin + '0 0 27';
  1492.  
  1493.     oldself=self;
  1494.     self=self.telebomb;
  1495.     SUB_Remove();
  1496.     self=oldself;
  1497.  
  1498.     // Teleport to the bomb's old location
  1499.  
  1500.     if(self.health <= 0)  {
  1501.         remove(bdest);
  1502.         return;
  1503.     }
  1504.  
  1505.     // Recreating the "teleport_touch" function here, once again
  1506.  
  1507.     spawn_tfog (bdest.origin);
  1508.     spawn_tdeath (bdest.origin,self);
  1509.  
  1510.     setorigin (self, bdest.origin);
  1511.     self.teleport_time = time + 1;  // Longer teleport recovery time
  1512.     self.flags = self.flags - self.flags & FL_ONGROUND;
  1513.  
  1514.     remove(bdest);
  1515. };
  1516.  
  1517. void() W_FireTeleportBomb =
  1518. {
  1519.     local   entity missile;
  1520.     
  1521.     // This uses no ammo.    
  1522.  
  1523.     self.telebomb = spawn ();
  1524.     self.telebomb.owner = self;
  1525.     self.telebomb.movetype = MOVETYPE_BOUNCE;
  1526.     self.telebomb.solid = SOLID_BBOX;
  1527.     self.telebomb.classname = "telebomb";
  1528.     self.telebomb.flags = FL_ITEM;                //ws... tele
  1529.     self.telebomb.health = 100;
  1530.     self.telebomb.flags = FL_OBJECT;
  1531.     self.telebomb.th_die = item_destroy;
  1532.     self.telebomb.takedamage = DAMAGE_AIM;        
  1533.     self.telebomb.angles = self.angles;
  1534.     setsize (self.telebomb, '0 0 0', '4 4 4');        
  1535.     sprint (self, "Teleport device dropped\n");
  1536.     setmodel (self.telebomb, "progs/grenade.mdl");
  1537.     setorigin (self.telebomb, (self.origin + v_forward*50));        //...ws
  1538. };                            //...ws
  1539.  
  1540. /*
  1541. ============
  1542. ServerflagsCommand
  1543.  
  1544. Just for development
  1545. ============
  1546. */
  1547. void() ServerflagsCommand =
  1548. {
  1549.     serverflags = serverflags * 2 + 1;
  1550. };
  1551.  
  1552. void() QuadCheat =
  1553. {
  1554.     if (deathmatch || coop)
  1555.         return;
  1556.     self.super_time = 1;
  1557.     self.super_damage_finished = time + 30;
  1558.     self.items = self.items | IT_QUAD;
  1559.     dprint ("quad cheat\n");
  1560. };
  1561.  
  1562. /*
  1563. ============
  1564. ImpulseCommands
  1565. ============
  1566. */
  1567.  
  1568. void() ImpulseCommands =
  1569. {
  1570.     if (self.impulse >= 1 && self.impulse <= 8)
  1571.         W_ChangeWeapon ();
  1572.  
  1573.     if (self.impulse == 9)
  1574.         CheatCommand ();
  1575.     if (self.impulse == 10)
  1576.         CycleWeaponCommand ();
  1577.     if (self.impulse == 11)
  1578.         ServerflagsCommand ();
  1579.  
  1580.     if (self.impulse == 12)                 //ws... impulse
  1581.         I_FlashlightToggle ();
  1582.  
  1583.     if (self.impulse == 13)
  1584.         if (self.radar_on)
  1585.             self.radar_on = 0;
  1586.         else 
  1587.             {
  1588.             self.radar_on =1;
  1589.             DisplayCompass();
  1590.             }
  1591.  
  1592.     if (self.impulse == 14)
  1593.         if (useget > 5)
  1594.             {
  1595.             DropStuff ();
  1596.             useget = 0;
  1597.             }
  1598.         else useget = useget + 1;
  1599.  
  1600.      if (self.impulse == 19)
  1601.         ServerNews();
  1602.  
  1603.     if ((self.impulse == 15) && (self.camo_time > 0) && (self.invisible_time == 1))
  1604.         if (self.items & IT_INVISIBILITY)
  1605.             {
  1606.             self.items = self.items - IT_INVISIBILITY;
  1607.             self.camo_time = self.invisible_finished - time;
  1608.             self.invisible_finished = 0;
  1609.             }
  1610.             else 
  1611.             {
  1612.             self.items = self.items | IT_INVISIBILITY;
  1613.             self.invisible_finished = time + self.camo_time;
  1614.             }
  1615.  
  1616.     if ((self.impulse == 16) && (self.suit_time > 0) && (self.rad_time == 1))
  1617.         if (self.items & IT_SUIT)
  1618.             {
  1619.             self.items = self.items - IT_SUIT;
  1620.             self.suit_time = self.radsuit_finished - time;
  1621.             self.radsuit_finished = 0;
  1622.             stuffcmd (self, "fly");
  1623.             }
  1624.         else 
  1625.             {
  1626.             self.items = self.items | IT_SUIT;
  1627.             self.radsuit_finished = time + self.suit_time;
  1628.             stuffcmd (self, "fly");
  1629.             }
  1630.  
  1631.     if ((self.impulse == 17) && (self.holo_time > 0))
  1632.         if (self.items & IT_QUAD)
  1633.             return;
  1634.             else
  1635.             {
  1636.             self.items = self.items | IT_QUAD;
  1637.             self.super_damage_finished = time + self.holo_time;
  1638.             ActivateHolo ();
  1639.             }
  1640.  
  1641.     if ((self.impulse == 18) && (self.tele_time > 0) && (self.invincible_time == 1))
  1642.         if (self.items & IT_INVULNERABILITY)
  1643.             {
  1644.             self.items = self.items - IT_INVULNERABILITY;
  1645.             self.tele_time = self.invincible_finished - time;
  1646.             self.invincible_finished = 0;
  1647.             Teleport_to_bomb ();
  1648.             }
  1649.             else 
  1650.             {
  1651.             self.items = self.items | IT_INVULNERABILITY;
  1652.             self.invincible_finished = time + self.tele_time;
  1653.             W_FireTeleportBomb ();
  1654.             }                //...ws
  1655.     
  1656. //ws    if (self.impulse == 255)
  1657. //ws        QuadCheat ();
  1658.     
  1659.     self.impulse = 0;
  1660. };
  1661.  
  1662. /*
  1663. ============
  1664. W_WeaponFrame
  1665.  
  1666. Called every frame so impulse events can be handled as well as possible
  1667. ============
  1668. */
  1669. float radar_time;
  1670.  
  1671. void() W_WeaponFrame =
  1672. {
  1673.     if (time < self.attack_finished)
  1674.         return;
  1675.  
  1676.     ImpulseCommands ();
  1677.  
  1678. //Added: by frank@aerre.it                //ws... radar
  1679.         if (self.radar_on)                //ws
  1680.         {
  1681.                 local entity head,selected;
  1682.                 local float min,dist;
  1683.  
  1684.                 if (radar_time==0) radar_time=time;
  1685.                 if (time>=radar_time) 
  1686.                 {
  1687.                         min=2000;
  1688.                         head = findradius(self.origin,1000);
  1689.                         selected = world;
  1690.                         
  1691.                         while (head)
  1692.                         {
  1693.                                 dist = vlen(self.origin - head.origin);
  1694.                                 if( (head.health > 1) && (head != self) && (head != self.owner) && (dist<min)  && 
  1695.         (head.flags & FL_MONSTER))    //ws solid corpses
  1696.                                 {          
  1697.                                         min=dist;
  1698.                                         selected=head;
  1699.                                 }
  1700.                                 head = head.chain;
  1701.                         }
  1702.                         sound (selected, CHAN_AUTO, "weapons/tink1.wav", 1, ATTN_NORM);
  1703.                         radar_time = min / 600;
  1704.                         radar_time = radar_time + time;
  1705.                 }
  1706.         }                    //...ws
  1707.     
  1708. // check for attack
  1709.     if (self.button0)
  1710.     {
  1711.         SuperDamageSound ();
  1712.         W_Attack ();
  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. ============================================================================
  1738.  
  1739. Quake Flamethrower 1.0
  1740.  
  1741. Another groovy patch from Quake Command - http://www.nuc.net/quake
  1742.  
  1743. QC Code By : Steve Bond         wedge@nuc.net
  1744.  
  1745. Apologies in advance... I was unable to comment this as well as I'd have
  1746. liked to. (I used some weird variable names - hope they don't cause problems.
  1747.  
  1748. ============================================================================
  1749. */
  1750.  
  1751. // Internal declaration
  1752.         void (vector fireorg) SpawnTouchFlame;
  1753.         void () BurnThem;
  1754.  
  1755. // Player.qc declaration
  1756.         void () DeathBubblesSpawn;
  1757.  
  1758.  
  1759.  
  1760. // Slightly varied version of DEATHBUBBLES
  1761. void(float num_bubbles, vector bub_origin) NewBubbles =
  1762. {
  1763. local entity    bubble_spawner;
  1764.     
  1765.     bubble_spawner = spawn();
  1766.         setorigin (bubble_spawner, bub_origin);
  1767.     bubble_spawner.movetype = MOVETYPE_NONE;
  1768.     bubble_spawner.solid = SOLID_NOT;
  1769.     bubble_spawner.nextthink = time + 0.1;
  1770.  
  1771.         if (self.classname == "player")
  1772.                 bubble_spawner.owner = self;
  1773.         else
  1774.                 bubble_spawner.owner = self.firewood;
  1775.  
  1776.         bubble_spawner.think = DeathBubblesSpawn;
  1777.     bubble_spawner.bubble_count = num_bubbles;
  1778.     return;
  1779. };
  1780.  
  1781.  
  1782. /*
  1783. ===============
  1784. BurnSelf 
  1785. ===============
  1786. */
  1787. void () BurnSelf =
  1788. {
  1789.         local entity    flame;
  1790.  
  1791.         flame = spawn ();
  1792.         flame.owner = self;
  1793.         flame.movetype = MOVETYPE_FLYMISSILE;
  1794.         flame.velocity = '0 0 75';
  1795.         flame.solid = SOLID_NOT;
  1796.         flame.classname = "fire";
  1797.         flame.origin = self.origin;
  1798.         self.onfire = TRUE;
  1799.         flame.firewood = self;
  1800.         flame.think = BurnThem;
  1801.         flame.nextthink = time;
  1802.         setmodel (flame, "progs/s_explo.spr");
  1803.         setsize (flame, '0 0 0', '0 0 0');            
  1804. };
  1805.  
  1806. /*
  1807. ===============
  1808. Burn Them!
  1809. ===============
  1810. */
  1811. void () BurnThem =
  1812. {
  1813.         // CHECK FOR WATER *FIRST*
  1814.         if (self.firewood.waterlevel >= 1)
  1815.         {
  1816.                 NewBubbles(6,self.firewood.origin);
  1817.                 self.firewood.onfire = FALSE;
  1818.                 self.firewood.effects = self.firewood.effects - EF_DIMLIGHT;
  1819.                 remove(self);
  1820.                 return;
  1821.         }
  1822.         else if (self.firewood.health > 0)
  1823.         {
  1824.                 SpawnTouchFlame(self.firewood.origin);
  1825.                 T_Damage (self.firewood, self, self.owner, 1);
  1826.                 self.nextthink = time + 0.25;
  1827.         }
  1828. };
  1829.  
  1830.  
  1831. /*
  1832. ================
  1833. SpawnTouchFlame
  1834. ================
  1835. */
  1836.  
  1837. void (vector fireorg) SpawnTouchFlame =
  1838. {
  1839.         local entity    flame;
  1840.         local   float   rn;
  1841.  
  1842.         flame = spawn ();
  1843.         flame.owner = self;
  1844.         flame.movetype = MOVETYPE_FLYMISSILE;
  1845.         flame.velocity = '0 0 75';
  1846.         flame.solid = SOLID_NOT;
  1847.         flame.classname = "fire";
  1848.         flame.origin = fireorg;
  1849.         flame.think = s_explode1;
  1850.         flame.nextthink = time;
  1851.         setmodel (flame, "progs/s_explod.spr");
  1852.         setsize (flame, '0 0 0', '0 0 0');            
  1853. };
  1854.  
  1855. /*ws... flames
  1856. ================
  1857. FlameTouch
  1858. ================
  1859. */
  1860. void () FlameTouch =
  1861. {
  1862.         local   float   rn;
  1863.  
  1864.         if (other == self.owner)
  1865.                 return;
  1866.  
  1867.         if (other.takedamage)
  1868.         {
  1869.                 rn = random();
  1870.                 // 20% chance
  1871.     if (rn <= 0.2 && !other.onfire)    //ws
  1872.                 {
  1873.                         // Fire stays with whatever it hits
  1874.                         if (other.classname == "player")
  1875.                         {
  1876.                                 centerprint(other,"You are on fire! Find WATER!\n");
  1877.                                 stuffcmd (other,"bf\n");
  1878.                         }
  1879.                         other.onfire = TRUE;
  1880.                         self.firewood = other;
  1881.                         self.think = BurnThem;
  1882.                         self.nextthink = time;
  1883.                         self.solid = SOLID_NOT;
  1884.                         setmodel (self,"");
  1885.                         other.effects = other.effects | EF_DIMLIGHT;
  1886.                 }
  1887.                 else
  1888.                 {
  1889.                         SpawnTouchFlame(other.origin);
  1890.                         T_Damage (other, self, self.owner, 10 );
  1891.                         remove (self);
  1892.                 }
  1893.         }
  1894.         else if (other.classname == "worldspawn")
  1895.         {
  1896.                 self.velocity = '0 0 0';
  1897.         }
  1898. };
  1899.  
  1900. /*
  1901. ================
  1902. W_FireFlame
  1903. ================
  1904. */
  1905. void() W_FireFlame =
  1906. {
  1907.         local   entity flame;
  1908.         local   float rn;
  1909.  
  1910.         if (self.waterlevel > 2)
  1911.         {
  1912.                 makevectors (self.v_angle);
  1913.                 NewBubbles(2, self.origin+v_forward*64);
  1914.  
  1915.                 rn = random();
  1916.                 if (rn < 0.5)
  1917.                         sound (self, CHAN_WEAPON, "misc/water1.wav", 1, ATTN_NORM);
  1918.                 else
  1919.                         sound (self, CHAN_WEAPON, "misc/water2.wav", 1, ATTN_NORM);
  1920.  
  1921.                 return;
  1922.         }
  1923.  
  1924.     // Take away a shell
  1925.     self.currentammo = self.ammo_cells = self.ammo_cells - 1;    //ws
  1926.  
  1927.         sound (self, CHAN_WEAPON, "hknight/hit.wav", 1, ATTN_NORM);
  1928.  
  1929.         flame = spawn ();
  1930.         flame.owner = self;
  1931.         flame.movetype = MOVETYPE_FLYMISSILE;
  1932.         flame.solid = SOLID_BBOX;
  1933.         flame.classname = "fire";
  1934.         
  1935. // set flame speed    
  1936.  
  1937.     makevectors (self.v_angle);
  1938.     self.velocity = self.velocity + v_forward * -5;        //ws backkick
  1939.  
  1940.                 flame.velocity = aim(self, 10000);
  1941.                 flame.velocity = flame.velocity * 300;
  1942.  
  1943.         flame.touch = FlameTouch;
  1944.     
  1945.         flame.think = s_explode1;
  1946.         flame.nextthink = time + 0.5;    //ws
  1947.  
  1948.         setmodel (flame, "progs/s_explod.spr");
  1949.         setsize (flame, '0 0 0', '0 0 0');            
  1950.         setorigin (flame, self.origin + v_forward * 32 + '0 0 7');    //ws
  1951. };        //...ws
  1952.  
  1953. /*            ws... compass
  1954. ============
  1955. Display Compass
  1956. ============
  1957. */
  1958. void() DisplayCompass =
  1959. {
  1960.     local float dir;
  1961.     local string str;
  1962.  
  1963.         dir = self.v_angle_y;
  1964.     if (dir > -22.5 && dir <= 22.5)
  1965.         str = "North";
  1966.     else if (dir > 22.5 && dir <= 67.5)
  1967.         str = "Northwest";
  1968.     else if (dir > 67.5 && dir <= 112.5)
  1969.         str = "West";
  1970.     else if (dir > 112.5 && dir <= 157.5)
  1971.         str = "Southwest";
  1972.     else if (dir > 157.5 || dir <= -157.5)
  1973.         str = "South";
  1974.     else if (dir > -157.5 && dir <= -112.5)
  1975.         str = "Southeast";
  1976.     else if (dir > -112.5 && dir <= -67.5)
  1977.         str = "East";
  1978.     else 
  1979.         str = "Northeast";
  1980.  
  1981.     sprint(self, "Your are looking ");
  1982.     sprint(self, str);
  1983.     sprint(self, "\n");        //...ws
  1984. };
  1985.