home *** CD-ROM | disk | FTP | other *** search
/ Quake 'em / QUAKEEM.BIN / quake / programs / plusgren / na_weap.qc < prev    next >
Encoding:
Text File  |  1996-08-10  |  26.5 KB  |  1,279 lines

  1. /*
  2.  
  3.  weapons.qc modified for PLUSGrenade. Changed parts has a 'NiAn' comment before
  4.  or around it.
  5.  
  6.  PLUSGrenade 1.0 Copyright 1996 Niklas Angare (NiAn on undernet) angare@kuai.se.
  7.  
  8.  This code is released for all to learn from, but please do not abuse my
  9.  goodwill by copying large chunks of it. If you want to distribute my code as a
  10.  part of a package, ask me first!
  11.  
  12. */
  13.  
  14. void (entity targ, entity inflictor, entity attacker, float damage) T_Damage;
  15. void () player_run;
  16. void(entity bomb, entity attacker, float rad, entity ignore) T_RadiusDamage;
  17. void(vector org, vector vel, float damage) SpawnBlood;
  18. void() SuperDamageSound;
  19.  
  20.  
  21. // missile.angles=vectoangles(missile.velocity);
  22. // called by worldspawn
  23. void() W_Precache =
  24. {
  25.     precache_sound ("weapons/r_exp3.wav");    // new rocket explosion
  26.     precache_sound ("weapons/rocket1i.wav");    // spike gun
  27.     precache_sound ("weapons/sgun1.wav");
  28.     precache_sound ("weapons/guncock.wav");    // player shotgun
  29.     precache_sound ("weapons/ric1.wav");    // ricochet (used in c code)
  30.     precache_sound ("weapons/ric2.wav");    // ricochet (used in c code)
  31.     precache_sound ("weapons/ric3.wav");    // ricochet (used in c code)
  32.     precache_sound ("weapons/spike2.wav");    // super spikes
  33.     precache_sound ("weapons/tink1.wav");    // spikes tink (used in c code)
  34.     precache_sound ("weapons/grenade.wav");    // grenade launcher
  35.     precache_sound ("weapons/bounce.wav");        // grenade bounce
  36.     precache_sound ("weapons/shotgn2.wav");    // super shotgun
  37.         precache_model ("progs/lavaball.mdl");
  38. };
  39. float() crandom =
  40. {
  41.     return 2*(random() - 0.5);
  42. };
  43.  
  44. /*
  45. ================
  46. W_FireAxe
  47. ================
  48. */
  49. void() W_FireAxe =
  50. {
  51.     local    vector    source;
  52.     local    vector    org;
  53.  
  54.     source = self.origin + '0 0 16';
  55.     traceline (source, source + v_forward*64, FALSE, self);
  56.     if (trace_fraction == 1.0)
  57.         return;
  58.     
  59.     org = trace_endpos - v_forward*4;
  60.  
  61.     if (trace_ent.takedamage)
  62.     {
  63.         trace_ent.axhitme = 1;
  64.         SpawnBlood (org, '0 0 0', 20);
  65.         T_Damage (trace_ent, self, self, 20);
  66.     }
  67.     else
  68.     {    // hit wall
  69.         sound (self, CHAN_WEAPON, "player/axhit2.wav", 1, ATTN_NORM);
  70.         WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  71.         WriteByte (MSG_BROADCAST, TE_GUNSHOT);
  72.         WriteCoord (MSG_BROADCAST, org_x);
  73.         WriteCoord (MSG_BROADCAST, org_y);
  74.         WriteCoord (MSG_BROADCAST, org_z);
  75.     }
  76. };
  77.  
  78.  
  79. //============================================================================
  80.  
  81.  
  82. vector() wall_velocity =
  83. {
  84.     local vector    vel;
  85.     
  86.     vel = normalize (self.velocity);
  87.     vel = normalize(vel + v_up*(random()- 0.5) + v_right*(random()- 0.5));
  88.     vel = vel + 2*trace_plane_normal;
  89.     vel = vel * 200;
  90.     
  91.     return vel;
  92. };
  93.  
  94.  
  95. /*
  96. ================
  97. SpawnMeatSpray
  98. ================
  99. */
  100. void(vector org, vector vel) SpawnMeatSpray =
  101. {
  102.     local    entity missile, mpuff;
  103.     local    vector    org;
  104.  
  105.     missile = spawn ();
  106.     missile.owner = self;
  107.     missile.movetype = MOVETYPE_BOUNCE;
  108.     missile.solid = SOLID_NOT;
  109.  
  110.     makevectors (self.angles);
  111.  
  112.     missile.velocity = vel;
  113.     missile.velocity_z = missile.velocity_z + 250 + 50*random();
  114.  
  115.     missile.avelocity = '3000 1000 2000';
  116.     
  117. // set missile duration
  118.     missile.nextthink = time + 1;
  119.     missile.think = SUB_Remove;
  120.  
  121.     setmodel (missile, "progs/zom_gib.mdl");
  122.     setsize (missile, '0 0 0', '0 0 0');        
  123.     setorigin (missile, org);
  124. };
  125.  
  126. /*
  127. ================
  128. SpawnBlood
  129. ================
  130. */
  131. void(vector org, vector vel, float damage) SpawnBlood =
  132. {
  133.     particle (org, vel*0.1, 73, damage*2);
  134. };
  135.  
  136. /*
  137. ================
  138. spawn_touchblood
  139. ================
  140. */
  141. void(float damage) spawn_touchblood =
  142. {
  143.     local vector    vel;
  144.  
  145.     vel = wall_velocity () * 0.2;
  146.     SpawnBlood (self.origin + vel*0.01, vel, damage);
  147. };
  148.  
  149.  
  150. /*
  151. ================
  152. SpawnChunk
  153. ================
  154. */
  155. void(vector org, vector vel) SpawnChunk =
  156. {
  157.     particle (org, vel*0.02, 0, 10);
  158. };
  159.  
  160. /*
  161. ==============================================================================
  162.  
  163. MULTI-DAMAGE
  164.  
  165. Collects multiple small damages into a single damage
  166.  
  167. ==============================================================================
  168. */
  169.  
  170. entity    multi_ent;
  171. float    multi_damage;
  172.  
  173. void() ClearMultiDamage =
  174. {
  175.     multi_ent = world;
  176.     multi_damage = 0;
  177. };
  178.  
  179. void() ApplyMultiDamage =
  180. {
  181.     if (!multi_ent)
  182.         return;
  183.     T_Damage (multi_ent, self, self, multi_damage);
  184. };
  185.  
  186. void(entity hit, float damage) AddMultiDamage =
  187. {
  188.     if (!hit)
  189.         return;
  190.     
  191.     if (hit != multi_ent)
  192.     {
  193.         ApplyMultiDamage ();
  194.         multi_damage = damage;
  195.         multi_ent = hit;
  196.     }
  197.     else
  198.         multi_damage = multi_damage + damage;
  199. };
  200.  
  201. /*
  202. ==============================================================================
  203.  
  204. BULLETS
  205.  
  206. ==============================================================================
  207. */
  208.  
  209. /*
  210. ================
  211. TraceAttack
  212. ================
  213. */
  214. void(float damage, vector dir) TraceAttack =
  215. {
  216.     local    vector    vel, org;
  217.     
  218.     vel = normalize(dir + v_up*crandom() + v_right*crandom());
  219.     vel = vel + 2*trace_plane_normal;
  220.     vel = vel * 200;
  221.  
  222.     org = trace_endpos - dir*4;
  223.  
  224.     if (trace_ent.takedamage)
  225.     {
  226.         SpawnBlood (org, vel*0.2, damage);
  227.         AddMultiDamage (trace_ent, damage);
  228.     }
  229.     else
  230.     {
  231.         WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  232.         WriteByte (MSG_BROADCAST, TE_GUNSHOT);
  233.         WriteCoord (MSG_BROADCAST, org_x);
  234.         WriteCoord (MSG_BROADCAST, org_y);
  235.         WriteCoord (MSG_BROADCAST, org_z);
  236.     }
  237. };
  238.  
  239. /*
  240. ================
  241. FireBullets
  242.  
  243. Used by shotgun, super shotgun, and enemy soldier firing
  244. Go to the trouble of combining multiple pellets into a single damage call.
  245. ================
  246. */
  247. void(float shotcount, vector dir, vector spread) FireBullets =
  248. {
  249.     local    vector direction;
  250.     local    vector    src;
  251.     
  252.     makevectors(self.v_angle);
  253.  
  254.     src = self.origin + v_forward*10;
  255.     src_z = self.absmin_z + self.size_z * 0.7;
  256.  
  257.     ClearMultiDamage ();
  258.     while (shotcount > 0)
  259.     {
  260.         direction = dir + crandom()*spread_x*v_right + crandom()*spread_y*v_up;
  261.  
  262.         traceline (src, src + direction*2048, FALSE, self);
  263.         if (trace_fraction != 1.0)
  264.             TraceAttack (4, direction);
  265.  
  266.         shotcount = shotcount - 1;
  267.     }
  268.     ApplyMultiDamage ();
  269. };
  270.  
  271. /*
  272. ================
  273. W_FireShotgun
  274. ================
  275. */
  276. void() W_FireShotgun =
  277. {
  278.     local vector dir;
  279.  
  280.     sound (self, CHAN_WEAPON, "weapons/guncock.wav", 1, ATTN_NORM);    
  281.  
  282.     self.punchangle_x = -2;
  283.     
  284.     self.currentammo = self.ammo_shells = self.ammo_shells - 1;
  285.     dir = aim (self, 100000);
  286.     FireBullets (6, dir, '0.04 0.04 0');
  287. };
  288.  
  289.  
  290. /*
  291. ================
  292. W_FireSuperShotgun
  293. ================
  294. */
  295. void() W_FireSuperShotgun =
  296. {
  297.     local vector dir;
  298.  
  299.     if (self.currentammo == 1)
  300.     {
  301.         W_FireShotgun ();
  302.         return;
  303.     }
  304.         
  305.     sound (self ,CHAN_WEAPON, "weapons/shotgn2.wav", 1, ATTN_NORM);    
  306.  
  307.     self.punchangle_x = -4;
  308.     
  309.     self.currentammo = self.ammo_shells = self.ammo_shells - 2;
  310.     dir = aim (self, 100000);
  311.     FireBullets (14, dir, '0.14 0.08 0');
  312. };
  313.  
  314.  
  315. /*
  316. ==============================================================================
  317.  
  318. ROCKETS
  319.  
  320. ==============================================================================
  321. */
  322.  
  323. void()    s_explode1    =    [0,        s_explode2] {};
  324. void()    s_explode2    =    [1,        s_explode3] {};
  325. void()    s_explode3    =    [2,        s_explode4] {};
  326. void()    s_explode4    =    [3,        s_explode5] {};
  327. void()    s_explode5    =    [4,        s_explode6] {};
  328. void()    s_explode6    =    [5,        SUB_Remove] {};
  329.  
  330. void() BecomeExplosion =
  331. {
  332.     self.movetype = MOVETYPE_NONE;
  333.     self.velocity = '0 0 0';
  334.     self.touch = SUB_Null;
  335.     setmodel (self, "progs/s_explod.spr");
  336.     self.solid = SOLID_NOT;
  337.     s_explode1 ();
  338. };
  339.  
  340. void() T_MissileTouch =
  341. {
  342.     local float    damg;
  343.  
  344.     if (other == self.owner)
  345.         return;        // don't explode on owner
  346.  
  347.     if (pointcontents(self.origin) == CONTENT_SKY)
  348.     {
  349.         remove(self);
  350.         return;
  351.     }
  352.  
  353.     damg = 100 + random()*20;
  354.     
  355.     if (other.health)
  356.     {
  357.         if (other.classname == "monster_shambler")
  358.             damg = damg * 0.5;    // mostly immune
  359.         T_Damage (other, self, self.owner, damg );
  360.     }
  361.  
  362.     // don't do radius damage to the other, because all the damage
  363.     // was done in the impact
  364.     T_RadiusDamage (self, self.owner, 120, other);
  365.  
  366. //    sound (self, CHAN_WEAPON, "weapons/r_exp3.wav", 1, ATTN_NORM);
  367.     self.origin = self.origin - 8*normalize(self.velocity);
  368.  
  369.     WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  370.     WriteByte (MSG_BROADCAST, TE_EXPLOSION);
  371.     WriteCoord (MSG_BROADCAST, self.origin_x);
  372.     WriteCoord (MSG_BROADCAST, self.origin_y);
  373.     WriteCoord (MSG_BROADCAST, self.origin_z);
  374.  
  375.     BecomeExplosion ();
  376. };
  377.  
  378.  
  379.  
  380. /*
  381. ================
  382. W_FireRocket
  383. ================
  384. */
  385. void() W_FireRocket =
  386. {
  387.     local    entity missile, mpuff;
  388.     
  389.     self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
  390.     
  391.     sound (self, CHAN_WEAPON, "weapons/sgun1.wav", 1, ATTN_NORM);
  392.  
  393.     self.punchangle_x = -2;
  394.  
  395.     missile = spawn ();
  396.     missile.owner = self;
  397.     missile.movetype = MOVETYPE_FLYMISSILE;
  398.     missile.solid = SOLID_BBOX;
  399.         
  400. // set missile speed    
  401.  
  402.     makevectors (self.v_angle);
  403.     missile.velocity = aim(self, 1000);
  404.     missile.velocity = missile.velocity * 1000;
  405.     missile.angles = vectoangles(missile.velocity);
  406.     
  407.     missile.touch = T_MissileTouch;
  408.     
  409. // set missile duration
  410.     missile.nextthink = time + 5;
  411.     missile.think = SUB_Remove;
  412.  
  413.     setmodel (missile, "progs/missile.mdl");
  414.     setsize (missile, '0 0 0', '0 0 0');        
  415.     setorigin (missile, self.origin + v_forward*8 + '0 0 16');
  416. };
  417.  
  418. /*
  419. ===============================================================================
  420.  
  421. LIGHTNING
  422.  
  423. ===============================================================================
  424. */
  425.  
  426. /*
  427. =================
  428. LightningDamage
  429. =================
  430. */
  431. void(vector p1, vector p2, entity from, float damage) LightningDamage =
  432. {
  433.     local entity        e1, e2;
  434.     local vector        f;
  435.     
  436.     f = p2 - p1;
  437.     normalize (f);
  438.     f_x = 0 - f_y;
  439.     f_y = f_x;
  440.     f_z = 0;
  441.     f = f*16;
  442.  
  443.     e1 = e2 = world;
  444.  
  445.     traceline (p1, p2, FALSE, self);
  446.     if (trace_ent.takedamage)
  447.     {
  448.         particle (trace_endpos, '0 0 100', 225, damage*4);
  449.         T_Damage (trace_ent, from, from, damage);
  450.         if (self.classname == "player")
  451.         {
  452.             if (other.classname == "player")
  453.                 trace_ent.velocity_z = trace_ent.velocity_z + 400;
  454.         }
  455.     }
  456.     e1 = trace_ent;
  457.  
  458.     traceline (p1 + f, p2 + f, FALSE, self);
  459.     if (trace_ent != e1 && trace_ent.takedamage)
  460.     {
  461.         particle (trace_endpos, '0 0 100', 225, damage*4);
  462.         T_Damage (trace_ent, from, from, damage);
  463.     }
  464.     e2 = trace_ent;
  465.  
  466.     traceline (p1 - f, p2 - f, FALSE, self);
  467.     if (trace_ent != e1 && trace_ent != e2 && trace_ent.takedamage)
  468.     {
  469.         particle (trace_endpos, '0 0 100', 225, damage*4);
  470.         T_Damage (trace_ent, from, from, damage);
  471.     }
  472. };
  473.  
  474.  
  475. void() W_FireLightning =
  476. {
  477.     local    vector        org;
  478.  
  479.     if (self.ammo_cells < 1)
  480.     {
  481.         self.weapon = W_BestWeapon ();
  482.         W_SetCurrentAmmo ();
  483.         return;
  484.     }
  485.  
  486. // explode if under water
  487.     if (self.waterlevel > 1)
  488.     {
  489.         T_RadiusDamage (self, self, 35*self.ammo_cells, world);
  490.         self.ammo_cells = 0;
  491.         W_SetCurrentAmmo ();
  492.         return;
  493.     }
  494.  
  495.     if (self.t_width < time)
  496.     {
  497.         sound (self, CHAN_WEAPON, "weapons/lhit.wav", 1, ATTN_NORM);
  498.         self.t_width = time + 0.6;
  499.     }
  500.     self.punchangle_x = -2;
  501.  
  502.     self.currentammo = self.ammo_cells = self.ammo_cells - 1;
  503.  
  504.     org = self.origin + '0 0 16';
  505.     
  506.     traceline (org, org + v_forward*600, TRUE, self);
  507.  
  508.     WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  509.     WriteByte (MSG_BROADCAST, TE_LIGHTNING2);
  510.     WriteEntity (MSG_BROADCAST, self);
  511.     WriteCoord (MSG_BROADCAST, org_x);
  512.     WriteCoord (MSG_BROADCAST, org_y);
  513.     WriteCoord (MSG_BROADCAST, org_z);
  514.     WriteCoord (MSG_BROADCAST, trace_endpos_x);
  515.     WriteCoord (MSG_BROADCAST, trace_endpos_y);
  516.     WriteCoord (MSG_BROADCAST, trace_endpos_z);
  517.  
  518.     LightningDamage (self.origin, trace_endpos + v_forward*4, self, 30);
  519. };
  520.  
  521. //=============================================================================
  522.  
  523.  
  524. void() GrenadeExplode =
  525. {
  526.     T_RadiusDamage (self, self.owner, 120, world);
  527.  
  528.     WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  529.     WriteByte (MSG_BROADCAST, TE_EXPLOSION);
  530.     WriteCoord (MSG_BROADCAST, self.origin_x);
  531.     WriteCoord (MSG_BROADCAST, self.origin_y);
  532.     WriteCoord (MSG_BROADCAST, self.origin_z);
  533.  
  534.     BecomeExplosion ();
  535. };
  536.  
  537. void() GrenadeTouch =
  538. {
  539.     if (other == self.owner)
  540.         return;        // don't explode on owner
  541.     if (other.takedamage == DAMAGE_AIM)
  542.     {
  543.         GrenadeExplode();
  544.         return;
  545.     }
  546.     sound (self, CHAN_WEAPON, "weapons/bounce.wav", 1, ATTN_NORM);    // bounce sound
  547.     if (self.velocity == '0 0 0')
  548.         self.avelocity = '0 0 0';
  549. };
  550.  
  551. /*
  552. ================
  553. W_FireGrenade
  554. ================
  555. */
  556. void() W_FireGrenade =
  557. {
  558.     local    entity missile, mpuff;
  559.     
  560.     self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
  561.     
  562.     sound (self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
  563.  
  564.     self.punchangle_x = -2;
  565.  
  566.     missile = spawn ();
  567.     missile.owner = self;
  568.     missile.movetype = MOVETYPE_BOUNCE;
  569.     missile.solid = SOLID_BBOX;
  570.     missile.classname = "grenade";
  571.         
  572. // set missile speed    
  573.  
  574.     makevectors (self.v_angle);
  575.  
  576.     if (self.v_angle_x)
  577.         missile.velocity = v_forward*600 + v_up * 200 + crandom()*v_right*10 + crandom()*v_up*10;
  578.     else
  579.     {
  580.         missile.velocity = aim(self, 10000);
  581.         missile.velocity = missile.velocity * 600;
  582.         missile.velocity_z = 200;
  583.     }
  584.  
  585.     missile.avelocity = '300 300 300';
  586.  
  587.     missile.angles = vectoangles(missile.velocity);
  588.     
  589.     missile.touch = GrenadeTouch;
  590.     
  591. // set missile duration
  592.     missile.nextthink = time + 2.5;
  593.     missile.think = GrenadeExplode;
  594.  
  595.     setmodel (missile, "progs/grenade.mdl");
  596.     setsize (missile, '0 0 0', '0 0 0');        
  597.     setorigin (missile, self.origin);
  598. };
  599.  
  600.  
  601. //=============================================================================
  602.  
  603. void() spike_touch;
  604. void() superspike_touch;
  605.  
  606.  
  607. /*
  608. ===============
  609. launch_spike
  610.  
  611. Used for both the player and the ogre
  612. ===============
  613. */
  614. void(vector org, vector dir) launch_spike =
  615. {
  616.     newmis = spawn ();
  617.     newmis.owner = self;
  618.     newmis.movetype = MOVETYPE_FLYMISSILE;
  619.     newmis.solid = SOLID_BBOX;
  620.  
  621.     newmis.angles = vectoangles(dir);
  622.     
  623.     newmis.touch = spike_touch;
  624.     newmis.classname = "spike";
  625.     newmis.think = SUB_Remove;
  626.     newmis.nextthink = time + 6;
  627.     setmodel (newmis, "progs/spike.mdl");
  628.     setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);        
  629.     setorigin (newmis, org);
  630.  
  631.     newmis.velocity = dir * 1000;
  632. };
  633.  
  634. void() W_FireSuperSpikes =
  635. {
  636.     local vector    dir;
  637.     local entity    old;
  638.     
  639.     sound (self, CHAN_WEAPON, "weapons/spike2.wav", 1, ATTN_NORM);
  640.     self.attack_finished = time + 0.2;
  641.     self.currentammo = self.ammo_nails = self.ammo_nails - 2;
  642.     dir = aim (self, 1000);
  643.     launch_spike (self.origin + '0 0 16', dir);
  644.     newmis.touch = superspike_touch;
  645.     setmodel (newmis, "progs/s_spike.mdl");
  646.     setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);        
  647.     self.punchangle_x = -2;
  648. };
  649.  
  650. void(float ox) W_FireSpikes =
  651. {
  652.     local vector    dir;
  653.     local entity    old;
  654.     
  655.     makevectors (self.v_angle);
  656.     
  657.     if (self.ammo_nails >= 2 && self.weapon == IT_SUPER_NAILGUN)
  658.     {
  659.         W_FireSuperSpikes ();
  660.         return;
  661.     }
  662.  
  663.     if (self.ammo_nails < 1)
  664.     {
  665.         self.weapon = W_BestWeapon ();
  666.         W_SetCurrentAmmo ();
  667.         return;
  668.     }
  669.  
  670.     sound (self, CHAN_WEAPON, "weapons/rocket1i.wav", 1, ATTN_NORM);
  671.     self.attack_finished = time + 0.2;
  672.     self.currentammo = self.ammo_nails = self.ammo_nails - 1;
  673.     dir = aim (self, 1000);
  674.     launch_spike (self.origin + '0 0 16' + v_right*ox, dir);
  675.  
  676.     self.punchangle_x = -2;
  677. };
  678.  
  679.  
  680.  
  681. .float hit_z;
  682. void() spike_touch =
  683. {
  684. local float rand;
  685.     if (other == self.owner)
  686.         return;
  687.  
  688.     if (other.solid == SOLID_TRIGGER)
  689.         return;    // trigger field, do nothing
  690.  
  691.     if (pointcontents(self.origin) == CONTENT_SKY)
  692.     {
  693.         remove(self);
  694.         return;
  695.     }
  696.     
  697. // hit something that bleeds
  698.     if (other.takedamage)
  699.     {
  700.         spawn_touchblood (9);
  701.         T_Damage (other, self, self.owner, 9);
  702.     }
  703.     else
  704.     {
  705.         WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  706.         
  707.         if (self.classname == "wizspike")
  708.             WriteByte (MSG_BROADCAST, TE_WIZSPIKE);
  709.         else if (self.classname == "knightspike")
  710.             WriteByte (MSG_BROADCAST, TE_KNIGHTSPIKE);
  711.         else
  712.             WriteByte (MSG_BROADCAST, TE_SPIKE);
  713.         WriteCoord (MSG_BROADCAST, self.origin_x);
  714.         WriteCoord (MSG_BROADCAST, self.origin_y);
  715.         WriteCoord (MSG_BROADCAST, self.origin_z);
  716.     }
  717.  
  718.     remove(self);
  719.  
  720. };
  721.  
  722. void() superspike_touch =
  723. {
  724. local float rand;
  725.     if (other == self.owner)
  726.         return;
  727.  
  728.     if (other.solid == SOLID_TRIGGER)
  729.         return;    // trigger field, do nothing
  730.  
  731.     if (pointcontents(self.origin) == CONTENT_SKY)
  732.     {
  733.         remove(self);
  734.         return;
  735.     }
  736.     
  737. // hit something that bleeds
  738.     if (other.takedamage)
  739.     {
  740.         spawn_touchblood (18);
  741.         T_Damage (other, self, self.owner, 18);
  742.     }
  743.     else
  744.     {
  745.         WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  746.         WriteByte (MSG_BROADCAST, TE_SUPERSPIKE);
  747.         WriteCoord (MSG_BROADCAST, self.origin_x);
  748.         WriteCoord (MSG_BROADCAST, self.origin_y);
  749.         WriteCoord (MSG_BROADCAST, self.origin_z);
  750.     }
  751.  
  752.     remove(self);
  753.  
  754. };
  755.  
  756.  
  757. /*
  758. ===============================================================================
  759.  
  760. PLAYER WEAPON USE
  761.  
  762. ===============================================================================
  763. */
  764.  
  765. void() W_SetCurrentAmmo =
  766. {
  767.     player_run ();        // get out of any weapon firing states
  768.  
  769.     self.items = self.items - ( self.items & (IT_SHELLS | IT_NAILS | IT_ROCKETS | IT_CELLS) );
  770.     
  771.     if (self.weapon == IT_AXE)
  772.     {
  773.         self.currentammo = 0;
  774.         self.weaponmodel = "progs/v_axe.mdl";
  775.         self.weaponframe = 0;
  776.     }
  777.     else if (self.weapon == IT_SHOTGUN)
  778.     {
  779.         self.currentammo = self.ammo_shells;
  780.         self.weaponmodel = "progs/v_shot.mdl";
  781.         self.weaponframe = 0;
  782.         self.items = self.items | IT_SHELLS;
  783.     }
  784.     else if (self.weapon == IT_SUPER_SHOTGUN)
  785.     {
  786.         self.currentammo = self.ammo_shells;
  787.         self.weaponmodel = "progs/v_shot2.mdl";
  788.         self.weaponframe = 0;
  789.         self.items = self.items | IT_SHELLS;
  790.     }
  791.     else if (self.weapon == IT_NAILGUN)
  792.     {
  793.         self.currentammo = self.ammo_nails;
  794.         self.weaponmodel = "progs/v_nail.mdl";
  795.         self.weaponframe = 0;
  796.         self.items = self.items | IT_NAILS;
  797.     }
  798.     else if (self.weapon == IT_SUPER_NAILGUN)
  799.     {
  800.         self.currentammo = self.ammo_nails;
  801.         self.weaponmodel = "progs/v_nail2.mdl";
  802.         self.weaponframe = 0;
  803.         self.items = self.items | IT_NAILS;
  804.     }
  805.     else if (self.weapon == IT_GRENADE_LAUNCHER)
  806.     {
  807.         self.currentammo = self.ammo_rockets;
  808.         self.weaponmodel = "progs/v_rock.mdl";
  809.         self.weaponframe = 0;
  810.         self.items = self.items | IT_ROCKETS;
  811.     }
  812.     else if (self.weapon == IT_ROCKET_LAUNCHER)
  813.     {
  814.         self.currentammo = self.ammo_rockets;
  815.         self.weaponmodel = "progs/v_rock2.mdl";
  816.         self.weaponframe = 0;
  817.         self.items = self.items | IT_ROCKETS;
  818.     }
  819.     else if (self.weapon == IT_LIGHTNING)
  820.     {
  821.         self.currentammo = self.ammo_cells;
  822.         self.weaponmodel = "progs/v_light.mdl";
  823.         self.weaponframe = 0;
  824.         self.items = self.items | IT_CELLS;
  825.     }
  826.     else
  827.     {
  828.         self.currentammo = 0;
  829.         self.weaponmodel = "";
  830.         self.weaponframe = 0;
  831.     }
  832. };
  833.  
  834. float() W_BestWeapon =
  835. {
  836.     local    float    it;
  837.     
  838.     it = self.items;
  839.  
  840.     if(self.ammo_cells >= 1 && (it & IT_LIGHTNING) )
  841.         return IT_LIGHTNING;
  842.     else if(self.ammo_nails >= 2 && (it & IT_SUPER_NAILGUN) )
  843.         return IT_SUPER_NAILGUN;
  844.     else if(self.ammo_shells >= 2 && (it & IT_SUPER_SHOTGUN) )
  845.         return IT_SUPER_SHOTGUN;
  846.     else if(self.ammo_nails >= 1 && (it & IT_NAILGUN) )
  847.         return IT_NAILGUN;
  848.     else if(self.ammo_shells >= 1 && (it & IT_SHOTGUN) )
  849.         return IT_SHOTGUN;
  850.         
  851. /*
  852.     if(self.ammo_rockets >= 1 && (it & IT_ROCKET_LAUNCHER) )
  853.         return IT_ROCKET_LAUNCHER;
  854.     else if(self.ammo_rockets >= 1 && (it & IT_GRENADE_LAUNCHER) )
  855.         return IT_GRENADE_LAUNCHER;
  856.  
  857. */
  858.  
  859.     return IT_AXE;
  860. };
  861.  
  862. float() W_CheckNoAmmo =
  863. {
  864.     if (self.currentammo > 0)
  865.         return TRUE;
  866.  
  867.     if (self.weapon == IT_AXE)
  868.         return TRUE;
  869.     
  870.     self.weapon = W_BestWeapon ();
  871.  
  872.     W_SetCurrentAmmo ();
  873.     
  874. // drop the weapon down
  875.     return FALSE;
  876. };
  877.  
  878. /*
  879. ============
  880. W_Attack
  881.  
  882. An attack impulse can be triggered now
  883. ============
  884. */
  885. void()    player_axe1;
  886. void()    player_axeb1;
  887. void()    player_axec1;
  888. void()    player_axed1;
  889. void()    player_shot1;
  890. void()    player_nail1;
  891. void()    player_light1;
  892. void()    player_rocket1;
  893.  
  894. /*NiAn modification start*/
  895. // grenade types for .grentype
  896. float    GT_NORMAL            = 0;
  897. float    GT_PROX                = 1;
  898. float    GT_LAVA                = 2;
  899. float    GT_NUMTYPES            = 3; // how many types there are
  900. /*NiAn modification end*/
  901.  
  902.  
  903. void() W_Attack =
  904. {
  905.     local    float    r;
  906.  
  907.     if (!W_CheckNoAmmo ())
  908.         return;
  909.  
  910.     makevectors    (self.v_angle);            // calculate forward angle for velocity
  911.     self.show_hostile = time + 1;    // wake monsters up
  912.  
  913.     if (self.weapon == IT_AXE)
  914.     {
  915.         sound (self, CHAN_WEAPON, "weapons/ax1.wav", 1, ATTN_NORM);
  916.         r = random();
  917.         if (r < 0.25)
  918.             player_axe1 ();
  919.         else if (r<0.5)
  920.             player_axeb1 ();
  921.         else if (r<0.75)
  922.             player_axec1 ();
  923.         else
  924.             player_axed1 ();
  925.         self.attack_finished = time + 0.5;
  926.     }
  927.     else if (self.weapon == IT_SHOTGUN)
  928.     {
  929.         player_shot1 ();
  930.         W_FireShotgun ();
  931.         self.attack_finished = time + 0.5;
  932.     }
  933.     else if (self.weapon == IT_SUPER_SHOTGUN)
  934.     {
  935.         player_shot1 ();
  936.         W_FireSuperShotgun ();
  937.         self.attack_finished = time + 0.7;
  938.     }
  939.     else if (self.weapon == IT_NAILGUN)
  940.     {
  941.         player_nail1 ();
  942.     }
  943.     else if (self.weapon == IT_SUPER_NAILGUN)
  944.     {
  945.         player_nail1 ();
  946.     }
  947.     else if (self.weapon == IT_GRENADE_LAUNCHER)
  948.     {
  949.         player_rocket1();
  950. /*NiAn*/    if (self.grentype == GT_NORMAL)
  951.             W_FireGrenade();
  952. /*NiAn*/    if (self.grentype == GT_PROX)
  953. /*NiAn*/        W_FireProxGrenade();
  954. /*NiAn*/    if (self.grentype == GT_LAVA)
  955. /*NiAn*/        W_FireLavaGrenade();
  956.         self.attack_finished = time + 0.6;
  957.     }
  958.     else if (self.weapon == IT_ROCKET_LAUNCHER)
  959.     {
  960.         player_rocket1();
  961.         W_FireRocket();
  962.         self.attack_finished = time + 0.8;
  963.     }
  964.     else if (self.weapon == IT_LIGHTNING)
  965.     {
  966.         player_light1();
  967.         self.attack_finished = time + 0.1;
  968.         sound (self, CHAN_AUTO, "weapons/lstart.wav", 1, ATTN_NORM);
  969.     }
  970. };
  971.  
  972. /*
  973. ============
  974. W_ChangeWeapon
  975.  
  976. ============
  977. */
  978. void() W_ChangeWeapon =
  979. {
  980.     local    float    it, am, fl;
  981.     
  982.     it = self.items;
  983.     am = 0;
  984.     
  985.     if (self.impulse == 1)
  986.     {
  987.         fl = IT_AXE;
  988.     }
  989.     else if (self.impulse == 2)
  990.     {
  991.         fl = IT_SHOTGUN;
  992.         if (self.ammo_shells < 1)
  993.             am = 1;
  994.     }
  995.     else if (self.impulse == 3)
  996.     {
  997.         fl = IT_SUPER_SHOTGUN;
  998.         if (self.ammo_shells < 2)
  999.             am = 1;
  1000.     }        
  1001.     else if (self.impulse == 4)
  1002.     {
  1003.         fl = IT_NAILGUN;
  1004.         if (self.ammo_nails < 1)
  1005.             am = 1;
  1006.     }
  1007.     else if (self.impulse == 5)
  1008.     {
  1009.         fl = IT_SUPER_NAILGUN;
  1010.         if (self.ammo_nails < 2)
  1011.             am = 1;
  1012.     }
  1013.     else if (self.impulse == 6)
  1014.     {
  1015.         fl = IT_GRENADE_LAUNCHER;
  1016. /*NiAn*/        if (self.weapon == IT_GRENADE_LAUNCHER) {
  1017. /*NiAn*/                self.grentype = self.grentype + 1;
  1018. /*NiAn*/                if (self.grentype == 3)
  1019. /*NiAn*/                        self.grentype = 0;
  1020. /*NiAn*/    if (self.grentype == GT_NORMAL)
  1021. /*NiAn*/        sprint(self, "Normal grenade selected\n");
  1022. /*NiAn*/    if (self.grentype == GT_PROX)
  1023. /*NiAn*/        sprint(self, "ProxGrenade selected\n");
  1024. /*NiAn*/    if (self.grentype == GT_LAVA)
  1025. /*NiAn*/        sprint(self, "LavaGrenade selected\n");
  1026. /*NiAn*/    }
  1027.         if (self.ammo_rockets < 1)
  1028.             am = 1;
  1029.     }
  1030.     else if (self.impulse == 7)
  1031.     {
  1032.         fl = IT_ROCKET_LAUNCHER;
  1033.         if (self.ammo_rockets < 1)
  1034.             am = 1;
  1035.     }
  1036.     else if (self.impulse == 8)
  1037.     {
  1038.         fl = IT_LIGHTNING;
  1039.         if (self.ammo_cells < 1)
  1040.             am = 1;
  1041.     }
  1042.  
  1043.     self.impulse = 0;
  1044.     
  1045.     if (!(self.items & fl))
  1046.     {    // don't have the weapon or the ammo
  1047.         sprint (self, "no weapon.\n");
  1048.         return;
  1049.     }
  1050.     
  1051.     if (am)
  1052.     {    // don't have the ammo
  1053.         sprint (self, "not enough ammo.\n");
  1054.         return;
  1055.     }
  1056.  
  1057. //
  1058. // set weapon, set ammo
  1059. //
  1060.     self.weapon = fl;        
  1061.     W_SetCurrentAmmo ();
  1062. };
  1063.  
  1064. /*
  1065. ============
  1066. CheatCommand
  1067. ============
  1068. */
  1069. void() CheatCommand =
  1070. {
  1071.     if (deathmatch || coop)
  1072.         return;
  1073.  
  1074.     self.ammo_rockets = 100;
  1075.     self.ammo_nails = 200;
  1076.     self.ammo_shells = 100;
  1077.     self.items = self.items | 
  1078.         IT_AXE |
  1079.         IT_SHOTGUN |
  1080.         IT_SUPER_SHOTGUN |
  1081.         IT_NAILGUN |
  1082.         IT_SUPER_NAILGUN |
  1083.         IT_GRENADE_LAUNCHER |
  1084.         IT_ROCKET_LAUNCHER |
  1085.         IT_KEY1 | IT_KEY2;
  1086.  
  1087.     self.ammo_cells = 200;
  1088.     self.items = self.items | IT_LIGHTNING;
  1089.  
  1090.     self.weapon = IT_ROCKET_LAUNCHER;
  1091.     self.impulse = 0;
  1092.     W_SetCurrentAmmo ();
  1093. };
  1094.  
  1095. /*
  1096. ============
  1097. CycleWeaponCommand
  1098.  
  1099. Go to the next weapon with ammo
  1100. ============
  1101. */
  1102. void() CycleWeaponCommand =
  1103. {
  1104.     local    float    it, am;
  1105.     
  1106.     it = self.items;
  1107.     self.impulse = 0;
  1108.     
  1109.     while (1)
  1110.     {
  1111.         am = 0;
  1112.  
  1113.         if (self.weapon == IT_LIGHTNING)
  1114.         {
  1115.             self.weapon = IT_AXE;
  1116.         }
  1117.         else if (self.weapon == IT_AXE)
  1118.         {
  1119.             self.weapon = IT_SHOTGUN;
  1120.             if (self.ammo_shells < 1)
  1121.                 am = 1;
  1122.         }
  1123.         else if (self.weapon == IT_SHOTGUN)
  1124.         {
  1125.             self.weapon = IT_SUPER_SHOTGUN;
  1126.             if (self.ammo_shells < 2)
  1127.                 am = 1;
  1128.         }        
  1129.         else if (self.weapon == IT_SUPER_SHOTGUN)
  1130.         {
  1131.             self.weapon = IT_NAILGUN;
  1132.             if (self.ammo_nails < 1)
  1133.                 am = 1;
  1134.         }
  1135.         else if (self.weapon == IT_NAILGUN)
  1136.         {
  1137.             self.weapon = IT_SUPER_NAILGUN;
  1138.             if (self.ammo_nails < 2)
  1139.                 am = 1;
  1140.         }
  1141.         else if (self.weapon == IT_SUPER_NAILGUN)
  1142.         {
  1143.             self.weapon = IT_GRENADE_LAUNCHER;
  1144.             if (self.ammo_rockets < 1)
  1145.                 am = 1;
  1146.         }
  1147.         else if (self.weapon == IT_GRENADE_LAUNCHER)
  1148.         {
  1149.             self.weapon = IT_ROCKET_LAUNCHER;
  1150.             if (self.ammo_rockets < 1)
  1151.                 am = 1;
  1152.         }
  1153.         else if (self.weapon == IT_ROCKET_LAUNCHER)
  1154.         {
  1155.             self.weapon = IT_LIGHTNING;
  1156.             if (self.ammo_cells < 1)
  1157.                 am = 1;
  1158.         }
  1159.     
  1160.         if ( (self.items & self.weapon) && am == 0)
  1161.         {
  1162.             W_SetCurrentAmmo ();
  1163.             return;
  1164.         }
  1165.     }
  1166.  
  1167. };
  1168.  
  1169. /*
  1170. ============
  1171. ServerflagsCommand
  1172.  
  1173. Just for development
  1174. ============
  1175. */
  1176. void() ServerflagsCommand =
  1177. {
  1178.     serverflags = serverflags * 2 + 1;
  1179. };
  1180.  
  1181. void() QuadCheat =
  1182. {
  1183.     if (deathmatch || coop)
  1184.         return;
  1185.     self.super_time = 1;
  1186.     self.super_damage_finished = time + 30;
  1187.     self.items = self.items | IT_QUAD;
  1188.     dprint ("quad cheat\n");
  1189. };
  1190.  
  1191. /*
  1192. ============
  1193. ImpulseCommands
  1194.  
  1195. ============
  1196. */
  1197.  
  1198. void() testprint =
  1199. {
  1200.     local float fff;
  1201.     local string sss;
  1202.     fff = self.lavaball_amount;
  1203. //    sss = ftos(fff);
  1204. //    sprint(self,sss);
  1205.     sprint(self,ftos(fff));
  1206. };
  1207.  
  1208. void() ImpulseCommands =
  1209. {
  1210.     if (self.impulse >= 1 && self.impulse <= 8)
  1211.         W_ChangeWeapon ();
  1212.  
  1213.     if (self.impulse == 9)
  1214.         CheatCommand ();
  1215.     if (self.impulse == 10)
  1216.         CycleWeaponCommand ();
  1217.     if (self.impulse == 11)
  1218.         ServerflagsCommand ();
  1219.  
  1220.     if (self.impulse == 255)
  1221.         QuadCheat ();
  1222.  
  1223. /*NiAn*/if (self.impulse >= 230 && self.impulse <= 239) {
  1224. /*NiAn*/    self.lavaball_amount = self.impulse - 230;
  1225. /*NiAn*/    self.lavaball_set = TRUE;
  1226. /*NiAn*/    sprint(self, "Amount of lava balls set to ");
  1227. /*NiAn*/    local string tempstring;
  1228. /*NiAn*/    tempstring = ftos(self.lavaball_amount);
  1229. /*NiAn*/    sprint(self, tempstring);
  1230. /*NiAn*/    sprint(self, "\n");
  1231. /*NiAn*/}
  1232.  
  1233.     self.impulse = 0;
  1234. };
  1235.  
  1236. /*
  1237. ============
  1238. W_WeaponFrame
  1239.  
  1240. Called every frame so impulse events can be handled as well as possible
  1241. ============
  1242. */
  1243. void() W_WeaponFrame =
  1244. {
  1245.     if (time < self.attack_finished)
  1246.         return;
  1247.  
  1248.     ImpulseCommands ();
  1249.     
  1250. // check for attack
  1251.     if (self.button0)
  1252.     {
  1253.         SuperDamageSound ();
  1254.         W_Attack ();
  1255.     }
  1256. };
  1257.  
  1258. /*
  1259. ========
  1260. SuperDamageSound
  1261.  
  1262. Plays sound if needed
  1263. ========
  1264. */
  1265. void() SuperDamageSound =
  1266. {
  1267.     if (self.super_damage_finished > time)
  1268.     {
  1269.         if (self.super_sound < time)
  1270.         {
  1271.             self.super_sound = time + 1;
  1272.             sound (self, CHAN_BODY, "items/damage3.wav", 1, ATTN_NORM);
  1273.         }
  1274.     }
  1275.     return;
  1276. };
  1277.  
  1278.  
  1279.