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