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