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

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