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