home *** CD-ROM | disk | FTP | other *** search
/ PC/CD Gamer UK 42 / PCGAMER42.bin / quake / chasecam / weapons.qc < prev   
Text File  |  1996-09-26  |  39KB  |  1,834 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. /*
  11.    #####################
  12.    ### chase cam mod ###
  13. (start date, more new functions, also lines added in client.qc
  14. they all are seperated with blank lines and have // ### chase cam mod ###
  15. lines above them)
  16. Rob Albin, 09 Sep 96
  17. orig functions modified:
  18.      none
  19. orig functions with added code:
  20.     void() W_SetCurrentAmmo =
  21.     void() ImpulseCommands =
  22. new functions:
  23.     void() Start_chase_cam =
  24.     void() Remove_chase_cam =
  25.     void() Keep_cam_chasing_owner =
  26.     void() Toggle_chase_cam =
  27. */
  28.  
  29. // message protocol defines
  30. float SVC_SETVIEWPORT    = 5;
  31. float SVC_SETVIEWANGLES    = 10;
  32.  
  33. // free player entity variable
  34. // '.float speed'  bit-flag defines:
  35. float CHSCAM_ALT    = 4;
  36. float CHSCAM_ON     = 2;
  37. float LASERTARG_ON  = 1;
  38.  
  39. // #####################
  40.  
  41.  
  42. // called by worldspawn
  43. void() W_Precache =
  44. {
  45.     precache_sound ("weapons/r_exp3.wav");    // new rocket explosion
  46.     precache_sound ("weapons/rocket1i.wav");    // spike gun
  47.     precache_sound ("weapons/sgun1.wav");
  48.     precache_sound ("weapons/guncock.wav");    // player shotgun
  49.     precache_sound ("weapons/ric1.wav");    // ricochet (used in c code)
  50.     precache_sound ("weapons/ric2.wav");    // ricochet (used in c code)
  51.     precache_sound ("weapons/ric3.wav");    // ricochet (used in c code)
  52.     precache_sound ("weapons/spike2.wav");    // super spikes
  53.     precache_sound ("weapons/tink1.wav");    // spikes tink (used in c code)
  54.     precache_sound ("weapons/grenade.wav");    // grenade launcher
  55.     precache_sound ("weapons/bounce.wav");        // grenade bounce
  56.     precache_sound ("weapons/shotgn2.wav");    // super shotgun
  57.  
  58.    // ### chase cam mod ###
  59.    // precache_sound( "misc/talk.wav" );
  60. };
  61.  
  62. float() crandom =
  63. {
  64.     return 2*(random() - 0.5);
  65. };
  66.  
  67. /*
  68. ================
  69. W_FireAxe
  70. ================
  71. */
  72. void() W_FireAxe =
  73. {
  74.     local    vector    source;
  75.     local    vector    org;
  76.  
  77.     source = self.origin + '0 0 16';
  78.     traceline (source, source + v_forward*64, FALSE, self);
  79.     if (trace_fraction == 1.0)
  80.         return;
  81.     
  82.     org = trace_endpos - v_forward*4;
  83.  
  84.     if (trace_ent.takedamage)
  85.     {
  86.         trace_ent.axhitme = 1;
  87.         SpawnBlood (org, '0 0 0', 20);
  88.         T_Damage (trace_ent, self, self, 20);
  89.     }
  90.     else
  91.     {    // hit wall
  92.         sound (self, CHAN_WEAPON, "player/axhit2.wav", 1, ATTN_NORM);
  93.         WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  94.         WriteByte (MSG_BROADCAST, TE_GUNSHOT);
  95.         WriteCoord (MSG_BROADCAST, org_x);
  96.         WriteCoord (MSG_BROADCAST, org_y);
  97.         WriteCoord (MSG_BROADCAST, org_z);
  98.     }
  99. };
  100.  
  101.  
  102. //============================================================================
  103.  
  104.  
  105. vector() wall_velocity =
  106. {
  107.     local vector    vel;
  108.     
  109.     vel = normalize (self.velocity);
  110.     vel = normalize(vel + v_up*(random()- 0.5) + v_right*(random()- 0.5));
  111.     vel = vel + 2*trace_plane_normal;
  112.     vel = vel * 200;
  113.     
  114.     return vel;
  115. };
  116.  
  117.  
  118. /*
  119. ================
  120. SpawnMeatSpray
  121. ================
  122. */
  123. void(vector org, vector vel) SpawnMeatSpray =
  124. {
  125.     local    entity missile, mpuff;
  126.     local    vector    org;
  127.  
  128.     missile = spawn ();
  129.     missile.owner = self;
  130.     missile.movetype = MOVETYPE_BOUNCE;
  131.     missile.solid = SOLID_NOT;
  132.  
  133.     makevectors (self.angles);
  134.  
  135.     missile.velocity = vel;
  136.     missile.velocity_z = missile.velocity_z + 250 + 50*random();
  137.  
  138.     missile.avelocity = '3000 1000 2000';
  139.     
  140. // set missile duration
  141.     missile.nextthink = time + 1;
  142.     missile.think = SUB_Remove;
  143.  
  144.     setmodel (missile, "progs/zom_gib.mdl");
  145.     setsize (missile, '0 0 0', '0 0 0');        
  146.     setorigin (missile, org);
  147. };
  148.  
  149. /*
  150. ================
  151. SpawnBlood
  152. ================
  153. */
  154. void(vector org, vector vel, float damage) SpawnBlood =
  155. {
  156.     particle (org, vel*0.1, 73, damage*2);
  157. };
  158.  
  159. /*
  160. ================
  161. spawn_touchblood
  162. ================
  163. */
  164. void(float damage) spawn_touchblood =
  165. {
  166.     local vector    vel;
  167.  
  168.     vel = wall_velocity () * 0.2;
  169.     SpawnBlood (self.origin + vel*0.01, vel, damage);
  170. };
  171.  
  172.  
  173. /*
  174. ================
  175. SpawnChunk
  176. ================
  177. */
  178. void(vector org, vector vel) SpawnChunk =
  179. {
  180.     particle (org, vel*0.02, 0, 10);
  181. };
  182.  
  183. /*
  184. ==============================================================================
  185.  
  186. MULTI-DAMAGE
  187.  
  188. Collects multiple small damages into a single damage
  189.  
  190. ==============================================================================
  191. */
  192.  
  193. entity    multi_ent;
  194. float    multi_damage;
  195.  
  196. void() ClearMultiDamage =
  197. {
  198.     multi_ent = world;
  199.     multi_damage = 0;
  200. };
  201.  
  202. void() ApplyMultiDamage =
  203. {
  204.     if (!multi_ent)
  205.         return;
  206.     T_Damage (multi_ent, self, self, multi_damage);
  207. };
  208.  
  209. void(entity hit, float damage) AddMultiDamage =
  210. {
  211.     if (!hit)
  212.         return;
  213.     
  214.     if (hit != multi_ent)
  215.     {
  216.         ApplyMultiDamage ();
  217.         multi_damage = damage;
  218.         multi_ent = hit;
  219.     }
  220.     else
  221.         multi_damage = multi_damage + damage;
  222. };
  223.  
  224. /*
  225. ==============================================================================
  226.  
  227. BULLETS
  228.  
  229. ==============================================================================
  230. */
  231.  
  232. /*
  233. ================
  234. TraceAttack
  235. ================
  236. */
  237. void(float damage, vector dir) TraceAttack =
  238. {
  239.     local    vector    vel, org;
  240.     
  241.     vel = normalize(dir + v_up*crandom() + v_right*crandom());
  242.     vel = vel + 2*trace_plane_normal;
  243.     vel = vel * 200;
  244.  
  245.     org = trace_endpos - dir*4;
  246.  
  247.     if (trace_ent.takedamage)
  248.     {
  249.         SpawnBlood (org, vel*0.2, damage);
  250.         AddMultiDamage (trace_ent, damage);
  251.     }
  252.     else
  253.     {
  254.         WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  255.         WriteByte (MSG_BROADCAST, TE_GUNSHOT);
  256.         WriteCoord (MSG_BROADCAST, org_x);
  257.         WriteCoord (MSG_BROADCAST, org_y);
  258.         WriteCoord (MSG_BROADCAST, org_z);
  259.     }
  260. };
  261.  
  262. /*
  263. ================
  264. FireBullets
  265.  
  266. Used by shotgun, super shotgun, and enemy soldier firing
  267. Go to the trouble of combining multiple pellets into a single damage call.
  268. ================
  269. */
  270. void(float shotcount, vector dir, vector spread) FireBullets =
  271. {
  272.     local    vector direction;
  273.     local    vector    src;
  274.     
  275.     makevectors(self.v_angle);
  276.  
  277.     src = self.origin + v_forward*10;
  278.     src_z = self.absmin_z + self.size_z * 0.7;
  279.  
  280.     ClearMultiDamage ();
  281.     while (shotcount > 0)
  282.     {
  283.         direction = dir + crandom()*spread_x*v_right + crandom()*spread_y*v_up;
  284.  
  285.         traceline (src, src + direction*2048, FALSE, self);
  286.         if (trace_fraction != 1.0)
  287.             TraceAttack (4, direction);
  288.  
  289.         shotcount = shotcount - 1;
  290.     }
  291.     ApplyMultiDamage ();
  292. };
  293.  
  294. /*
  295. ================
  296. W_FireShotgun
  297. ================
  298. */
  299. void() W_FireShotgun =
  300. {
  301.     local vector dir;
  302.  
  303.     sound (self, CHAN_WEAPON, "weapons/guncock.wav", 1, ATTN_NORM);    
  304.  
  305.     self.punchangle_x = -2;
  306.     
  307.     self.currentammo = self.ammo_shells = self.ammo_shells - 1;
  308.     dir = aim (self, 100000);
  309.     FireBullets (6, dir, '0.04 0.04 0');
  310. };
  311.  
  312.  
  313. /*
  314. ================
  315. W_FireSuperShotgun
  316. ================
  317. */
  318. void() W_FireSuperShotgun =
  319. {
  320.     local vector dir;
  321.  
  322.     if (self.currentammo == 1)
  323.     {
  324.         W_FireShotgun ();
  325.         return;
  326.     }
  327.         
  328.     sound (self ,CHAN_WEAPON, "weapons/shotgn2.wav", 1, ATTN_NORM);    
  329.  
  330.     self.punchangle_x = -4;
  331.     
  332.     self.currentammo = self.ammo_shells = self.ammo_shells - 2;
  333.     dir = aim (self, 100000);
  334.     FireBullets (14, dir, '0.14 0.08 0');
  335. };
  336.  
  337.  
  338. /*
  339. ==============================================================================
  340.  
  341. ROCKETS
  342.  
  343. ==============================================================================
  344. */
  345.  
  346. void()    s_explode1    =    [0,        s_explode2] {};
  347. void()    s_explode2    =    [1,        s_explode3] {};
  348. void()    s_explode3    =    [2,        s_explode4] {};
  349. void()    s_explode4    =    [3,        s_explode5] {};
  350. void()    s_explode5    =    [4,        s_explode6] {};
  351. void()    s_explode6    =    [5,        SUB_Remove] {};
  352.  
  353. void() BecomeExplosion =
  354. {
  355.     self.movetype = MOVETYPE_NONE;
  356.     self.velocity = '0 0 0';
  357.     self.touch = SUB_Null;
  358.     setmodel (self, "progs/s_explod.spr");
  359.     self.solid = SOLID_NOT;
  360.     s_explode1 ();
  361. };
  362.  
  363. void() T_MissileTouch =
  364. {
  365.     local float    damg;
  366.  
  367.     if (other == self.owner)
  368.         return;        // don't explode on owner
  369.  
  370.     if (pointcontents(self.origin) == CONTENT_SKY)
  371.     {
  372.         remove(self);
  373.         return;
  374.     }
  375.  
  376.     damg = 100 + random()*20;
  377.     
  378.     if (other.health)
  379.     {
  380.         if (other.classname == "monster_shambler")
  381.             damg = damg * 0.5;    // mostly immune
  382.         T_Damage (other, self, self.owner, damg );
  383.     }
  384.  
  385.     // don't do radius damage to the other, because all the damage
  386.     // was done in the impact
  387.     T_RadiusDamage (self, self.owner, 120, other);
  388.  
  389. //    sound (self, CHAN_WEAPON, "weapons/r_exp3.wav", 1, ATTN_NORM);
  390.     self.origin = self.origin - 8*normalize(self.velocity);
  391.  
  392.     WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  393.     WriteByte (MSG_BROADCAST, TE_EXPLOSION);
  394.     WriteCoord (MSG_BROADCAST, self.origin_x);
  395.     WriteCoord (MSG_BROADCAST, self.origin_y);
  396.     WriteCoord (MSG_BROADCAST, self.origin_z);
  397.  
  398.     BecomeExplosion ();
  399. };
  400.  
  401. /*
  402. ================
  403. W_FireRocket
  404. ================
  405. */
  406. void() W_FireRocket =
  407. {
  408.     local    entity missile, mpuff;
  409.     
  410.     self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
  411.     
  412.     sound (self, CHAN_WEAPON, "weapons/sgun1.wav", 1, ATTN_NORM);
  413.  
  414.     self.punchangle_x = -2;
  415.  
  416.     missile = spawn ();
  417.     missile.owner = self;
  418.     missile.movetype = MOVETYPE_FLYMISSILE;
  419.     missile.solid = SOLID_BBOX;
  420.         
  421. // set missile speed    
  422.  
  423.     makevectors (self.v_angle);
  424.     missile.velocity = aim(self, 1000);
  425.     missile.velocity = missile.velocity * 1000;
  426.     missile.angles = vectoangles(missile.velocity);
  427.     
  428.     missile.touch = T_MissileTouch;
  429.     
  430. // set missile duration
  431.     missile.nextthink = time + 5;
  432.     missile.think = SUB_Remove;
  433.  
  434.     setmodel (missile, "progs/missile.mdl");
  435.     setsize (missile, '0 0 0', '0 0 0');        
  436.     setorigin (missile, self.origin + v_forward*8 + '0 0 16');
  437. };
  438.  
  439. /*
  440. ===============================================================================
  441.  
  442. LIGHTNING
  443.  
  444. ===============================================================================
  445. */
  446.  
  447. /*
  448. =================
  449. LightningDamage
  450. =================
  451. */
  452. void(vector p1, vector p2, entity from, float damage) LightningDamage =
  453. {
  454.     local entity        e1, e2;
  455.     local vector        f;
  456.     
  457.     f = p2 - p1;
  458.     normalize (f);
  459.     f_x = 0 - f_y;
  460.     f_y = f_x;
  461.     f_z = 0;
  462.     f = f*16;
  463.  
  464.     e1 = e2 = world;
  465.  
  466.     traceline (p1, p2, FALSE, self);
  467.     if (trace_ent.takedamage)
  468.     {
  469.         particle (trace_endpos, '0 0 100', 225, damage*4);
  470.         T_Damage (trace_ent, from, from, damage);
  471.         if (self.classname == "player")
  472.         {
  473.             if (other.classname == "player")
  474.                 trace_ent.velocity_z = trace_ent.velocity_z + 400;
  475.         }
  476.     }
  477.     e1 = trace_ent;
  478.  
  479.     traceline (p1 + f, p2 + f, FALSE, self);
  480.     if (trace_ent != e1 && trace_ent.takedamage)
  481.     {
  482.         particle (trace_endpos, '0 0 100', 225, damage*4);
  483.         T_Damage (trace_ent, from, from, damage);
  484.     }
  485.     e2 = trace_ent;
  486.  
  487.     traceline (p1 - f, p2 - f, FALSE, self);
  488.     if (trace_ent != e1 && trace_ent != e2 && trace_ent.takedamage)
  489.     {
  490.         particle (trace_endpos, '0 0 100', 225, damage*4);
  491.         T_Damage (trace_ent, from, from, damage);
  492.     }
  493. };
  494.  
  495.  
  496. void() W_FireLightning =
  497. {
  498.     local    vector        org;
  499.  
  500.     if (self.ammo_cells < 1)
  501.     {
  502.         self.weapon = W_BestWeapon ();
  503.         W_SetCurrentAmmo ();
  504.         return;
  505.     }
  506.  
  507. // explode if under water
  508.     if (self.waterlevel > 1)
  509.     {
  510.         T_RadiusDamage (self, self, 35*self.ammo_cells, world);
  511.         self.ammo_cells = 0;
  512.         W_SetCurrentAmmo ();
  513.         return;
  514.     }
  515.  
  516.     if (self.t_width < time)
  517.     {
  518.         sound (self, CHAN_WEAPON, "weapons/lhit.wav", 1, ATTN_NORM);
  519.         self.t_width = time + 0.6;
  520.     }
  521.     self.punchangle_x = -2;
  522.  
  523.     self.currentammo = self.ammo_cells = self.ammo_cells - 1;
  524.  
  525.     org = self.origin + '0 0 16';
  526.     
  527.     traceline (org, org + v_forward*600, TRUE, self);
  528.  
  529.     WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  530.     WriteByte (MSG_BROADCAST, TE_LIGHTNING2);
  531.     WriteEntity (MSG_BROADCAST, self);
  532.     WriteCoord (MSG_BROADCAST, org_x);
  533.     WriteCoord (MSG_BROADCAST, org_y);
  534.     WriteCoord (MSG_BROADCAST, org_z);
  535.     WriteCoord (MSG_BROADCAST, trace_endpos_x);
  536.     WriteCoord (MSG_BROADCAST, trace_endpos_y);
  537.     WriteCoord (MSG_BROADCAST, trace_endpos_z);
  538.  
  539.     LightningDamage (self.origin, trace_endpos + v_forward*4, self, 30);
  540. };
  541.  
  542.  
  543. //=============================================================================
  544.  
  545.  
  546. void() GrenadeExplode =
  547. {
  548.     T_RadiusDamage (self, self.owner, 120, world);
  549.  
  550.     WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  551.     WriteByte (MSG_BROADCAST, TE_EXPLOSION);
  552.     WriteCoord (MSG_BROADCAST, self.origin_x);
  553.     WriteCoord (MSG_BROADCAST, self.origin_y);
  554.     WriteCoord (MSG_BROADCAST, self.origin_z);
  555.  
  556.     BecomeExplosion ();
  557. };
  558.  
  559. void() GrenadeTouch =
  560. {
  561.     if (other == self.owner)
  562.         return;        // don't explode on owner
  563.     if (other.takedamage == DAMAGE_AIM)
  564.     {
  565.         GrenadeExplode();
  566.         return;
  567.     }
  568.     sound (self, CHAN_WEAPON, "weapons/bounce.wav", 1, ATTN_NORM);    // bounce sound
  569.     if (self.velocity == '0 0 0')
  570.         self.avelocity = '0 0 0';
  571. };
  572.  
  573. /*
  574. ================
  575. W_FireGrenade
  576. ================
  577. */
  578. void() W_FireGrenade =
  579. {
  580.     local    entity missile, mpuff;
  581.     
  582.     self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
  583.     
  584.     sound (self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
  585.  
  586.     self.punchangle_x = -2;
  587.  
  588.     missile = spawn ();
  589.     missile.owner = self;
  590.     missile.movetype = MOVETYPE_BOUNCE;
  591.     missile.solid = SOLID_BBOX;
  592.     missile.classname = "grenade";
  593.         
  594. // set missile speed    
  595.  
  596.     makevectors (self.v_angle);
  597.  
  598.     if (self.v_angle_x)
  599.         missile.velocity = v_forward*600 + v_up * 200 + crandom()*v_right*10 + crandom()*v_up*10;
  600.     else
  601.     {
  602.         missile.velocity = aim(self, 10000);
  603.         missile.velocity = missile.velocity * 600;
  604.         missile.velocity_z = 200;
  605.     }
  606.  
  607.     missile.avelocity = '300 300 300';
  608.  
  609.     missile.angles = vectoangles(missile.velocity);
  610.     
  611.     missile.touch = GrenadeTouch;
  612.     
  613. // set missile duration
  614.     missile.nextthink = time + 2.5;
  615.     missile.think = GrenadeExplode;
  616.  
  617.     setmodel (missile, "progs/grenade.mdl");
  618.     setsize (missile, '0 0 0', '0 0 0');        
  619.     setorigin (missile, self.origin);
  620. };
  621.  
  622.  
  623. //=============================================================================
  624.  
  625. void() spike_touch;
  626. void() superspike_touch;
  627.  
  628.  
  629. /*
  630. ===============
  631. launch_spike
  632.  
  633. Used for both the player and the ogre
  634. ===============
  635. */
  636. void(vector org, vector dir) launch_spike =
  637. {
  638.     newmis = spawn ();
  639.     newmis.owner = self;
  640.     newmis.movetype = MOVETYPE_FLYMISSILE;
  641.     newmis.solid = SOLID_BBOX;
  642.  
  643.     newmis.angles = vectoangles(dir);
  644.     
  645.     newmis.touch = spike_touch;
  646.     newmis.classname = "spike";
  647.     newmis.think = SUB_Remove;
  648.     newmis.nextthink = time + 6;
  649.     setmodel (newmis, "progs/spike.mdl");
  650.     setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);        
  651.     setorigin (newmis, org);
  652.  
  653.     newmis.velocity = dir * 1000;
  654. };
  655.  
  656. void() W_FireSuperSpikes =
  657. {
  658.     local vector    dir;
  659.     local entity    old;
  660.     
  661.     sound (self, CHAN_WEAPON, "weapons/spike2.wav", 1, ATTN_NORM);
  662.     self.attack_finished = time + 0.2;
  663.     self.currentammo = self.ammo_nails = self.ammo_nails - 2;
  664.     dir = aim (self, 1000);
  665.     launch_spike (self.origin + '0 0 16', dir);
  666.     newmis.touch = superspike_touch;
  667.     setmodel (newmis, "progs/s_spike.mdl");
  668.     setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);        
  669.     self.punchangle_x = -2;
  670. };
  671.  
  672. void(float ox) W_FireSpikes =
  673. {
  674.     local vector    dir;
  675.     local entity    old;
  676.     
  677.     makevectors (self.v_angle);
  678.     
  679.     if (self.ammo_nails >= 2 && self.weapon == IT_SUPER_NAILGUN)
  680.     {
  681.         W_FireSuperSpikes ();
  682.         return;
  683.     }
  684.  
  685.     if (self.ammo_nails < 1)
  686.     {
  687.         self.weapon = W_BestWeapon ();
  688.         W_SetCurrentAmmo ();
  689.         return;
  690.     }
  691.  
  692.     sound (self, CHAN_WEAPON, "weapons/rocket1i.wav", 1, ATTN_NORM);
  693.     self.attack_finished = time + 0.2;
  694.     self.currentammo = self.ammo_nails = self.ammo_nails - 1;
  695.     dir = aim (self, 1000);
  696.     launch_spike (self.origin + '0 0 16' + v_right*ox, dir);
  697.  
  698.     self.punchangle_x = -2;
  699. };
  700.  
  701.  
  702.  
  703. .float hit_z;
  704. void() spike_touch =
  705. {
  706. local float rand;
  707.     if (other == self.owner)
  708.         return;
  709.  
  710.     if (other.solid == SOLID_TRIGGER)
  711.         return;    // trigger field, do nothing
  712.  
  713.     if (pointcontents(self.origin) == CONTENT_SKY)
  714.     {
  715.         remove(self);
  716.         return;
  717.     }
  718.     
  719. // hit something that bleeds
  720.     if (other.takedamage)
  721.     {
  722.         spawn_touchblood (9);
  723.         T_Damage (other, self, self.owner, 9);
  724.     }
  725.     else
  726.     {
  727.         WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  728.         
  729.         if (self.classname == "wizspike")
  730.             WriteByte (MSG_BROADCAST, TE_WIZSPIKE);
  731.         else if (self.classname == "knightspike")
  732.             WriteByte (MSG_BROADCAST, TE_KNIGHTSPIKE);
  733.         else
  734.             WriteByte (MSG_BROADCAST, TE_SPIKE);
  735.         WriteCoord (MSG_BROADCAST, self.origin_x);
  736.         WriteCoord (MSG_BROADCAST, self.origin_y);
  737.         WriteCoord (MSG_BROADCAST, self.origin_z);
  738.     }
  739.  
  740.     remove(self);
  741.  
  742. };
  743.  
  744. void() superspike_touch =
  745. {
  746. local float rand;
  747.     if (other == self.owner)
  748.         return;
  749.  
  750.     if (other.solid == SOLID_TRIGGER)
  751.         return;    // trigger field, do nothing
  752.  
  753.     if (pointcontents(self.origin) == CONTENT_SKY)
  754.     {
  755.         remove(self);
  756.         return;
  757.     }
  758.     
  759. // hit something that bleeds
  760.     if (other.takedamage)
  761.     {
  762.         spawn_touchblood (18);
  763.         T_Damage (other, self, self.owner, 18);
  764.     }
  765.     else
  766.     {
  767.         WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  768.         WriteByte (MSG_BROADCAST, TE_SUPERSPIKE);
  769.         WriteCoord (MSG_BROADCAST, self.origin_x);
  770.         WriteCoord (MSG_BROADCAST, self.origin_y);
  771.         WriteCoord (MSG_BROADCAST, self.origin_z);
  772.     }
  773.  
  774.     remove(self);
  775.  
  776. };
  777.  
  778.  
  779. /*
  780. ===============================================================================
  781.  
  782. PLAYER WEAPON USE
  783.  
  784. ===============================================================================
  785. */
  786.  
  787. void() W_SetCurrentAmmo =
  788. {
  789.     player_run ();        // get out of any weapon firing states
  790.  
  791.     self.items = self.items - ( self.items & (IT_SHELLS | IT_NAILS | IT_ROCKETS | IT_CELLS) );
  792.     
  793.     if (self.weapon == IT_AXE)
  794.     {
  795.         self.currentammo = 0;
  796.         self.weaponmodel = "progs/v_axe.mdl";
  797.         self.weaponframe = 0;
  798.     }
  799.     else if (self.weapon == IT_SHOTGUN)
  800.     {
  801.         self.currentammo = self.ammo_shells;
  802.         self.weaponmodel = "progs/v_shot.mdl";
  803.         self.weaponframe = 0;
  804.         self.items = self.items | IT_SHELLS;
  805.     }
  806.     else if (self.weapon == IT_SUPER_SHOTGUN)
  807.     {
  808.         self.currentammo = self.ammo_shells;
  809.         self.weaponmodel = "progs/v_shot2.mdl";
  810.         self.weaponframe = 0;
  811.         self.items = self.items | IT_SHELLS;
  812.     }
  813.     else if (self.weapon == IT_NAILGUN)
  814.     {
  815.         self.currentammo = self.ammo_nails;
  816.         self.weaponmodel = "progs/v_nail.mdl";
  817.         self.weaponframe = 0;
  818.         self.items = self.items | IT_NAILS;
  819.     }
  820.     else if (self.weapon == IT_SUPER_NAILGUN)
  821.     {
  822.         self.currentammo = self.ammo_nails;
  823.         self.weaponmodel = "progs/v_nail2.mdl";
  824.         self.weaponframe = 0;
  825.         self.items = self.items | IT_NAILS;
  826.     }
  827.     else if (self.weapon == IT_GRENADE_LAUNCHER)
  828.     {
  829.         self.currentammo = self.ammo_rockets;
  830.         self.weaponmodel = "progs/v_rock.mdl";
  831.         self.weaponframe = 0;
  832.         self.items = self.items | IT_ROCKETS;
  833.     }
  834.     else if (self.weapon == IT_ROCKET_LAUNCHER)
  835.     {
  836.         self.currentammo = self.ammo_rockets;
  837.         self.weaponmodel = "progs/v_rock2.mdl";
  838.         self.weaponframe = 0;
  839.         self.items = self.items | IT_ROCKETS;
  840.     }
  841.     else if (self.weapon == IT_LIGHTNING)
  842.     {
  843.         self.currentammo = self.ammo_cells;
  844.         self.weaponmodel = "progs/v_light.mdl";
  845.         self.weaponframe = 0;
  846.         self.items = self.items | IT_CELLS;
  847.     }
  848.     else
  849.     {
  850.         self.currentammo = 0;
  851.         self.weaponmodel = "";
  852.         self.weaponframe = 0;
  853.     }
  854.  
  855.     // ### chase cam mod ###
  856.     if ( (self.speed & CHSCAM_ON) )
  857.     {
  858.         self.weaponmodel = "";
  859.         self.weaponframe = 0;
  860.     }
  861.  
  862.  
  863.  
  864. };
  865.  
  866. float() W_BestWeapon =
  867. {
  868.     local    float    it;
  869.     
  870.     it = self.items;
  871.  
  872.     if(self.ammo_cells >= 1 && (it & IT_LIGHTNING) )
  873.         return IT_LIGHTNING;
  874.     else if(self.ammo_nails >= 2 && (it & IT_SUPER_NAILGUN) )
  875.         return IT_SUPER_NAILGUN;
  876.     else if(self.ammo_shells >= 2 && (it & IT_SUPER_SHOTGUN) )
  877.         return IT_SUPER_SHOTGUN;
  878.     else if(self.ammo_nails >= 1 && (it & IT_NAILGUN) )
  879.         return IT_NAILGUN;
  880.     else if(self.ammo_shells >= 1 && (it & IT_SHOTGUN) )
  881.         return IT_SHOTGUN;
  882.         
  883. /*
  884.     if(self.ammo_rockets >= 1 && (it & IT_ROCKET_LAUNCHER) )
  885.         return IT_ROCKET_LAUNCHER;
  886.     else if(self.ammo_rockets >= 1 && (it & IT_GRENADE_LAUNCHER) )
  887.         return IT_GRENADE_LAUNCHER;
  888.  
  889. */
  890.  
  891.     return IT_AXE;
  892. };
  893.  
  894. float() W_CheckNoAmmo =
  895. {
  896.     if (self.currentammo > 0)
  897.         return TRUE;
  898.  
  899.     if (self.weapon == IT_AXE)
  900.         return TRUE;
  901.     
  902.     self.weapon = W_BestWeapon ();
  903.  
  904.     W_SetCurrentAmmo ();
  905.     
  906. // drop the weapon down
  907.     return FALSE;
  908. };
  909.  
  910. /*
  911. ============
  912. W_Attack
  913.  
  914. An attack impulse can be triggered now
  915. ============
  916. */
  917. void()    player_axe1;
  918. void()    player_axeb1;
  919. void()    player_axec1;
  920. void()    player_axed1;
  921. void()    player_shot1;
  922. void()    player_nail1;
  923. void()    player_light1;
  924. void()    player_rocket1;
  925.  
  926. void() W_Attack =
  927. {
  928.     local    float    r;
  929.  
  930.     if (!W_CheckNoAmmo ())
  931.         return;
  932.  
  933.     makevectors    (self.v_angle);            // calculate forward angle for velocity
  934.     self.show_hostile = time + 1;    // wake monsters up
  935.  
  936.     if (self.weapon == IT_AXE)
  937.     {
  938.         sound (self, CHAN_WEAPON, "weapons/ax1.wav", 1, ATTN_NORM);
  939.         r = random();
  940.         if (r < 0.25)
  941.             player_axe1 ();
  942.         else if (r<0.5)
  943.             player_axeb1 ();
  944.         else if (r<0.75)
  945.             player_axec1 ();
  946.         else
  947.             player_axed1 ();
  948.         self.attack_finished = time + 0.5;
  949.     }
  950.     else if (self.weapon == IT_SHOTGUN)
  951.     {
  952.         player_shot1 ();
  953.         W_FireShotgun ();
  954.         self.attack_finished = time + 0.5;
  955.     }
  956.     else if (self.weapon == IT_SUPER_SHOTGUN)
  957.     {
  958.         player_shot1 ();
  959.         W_FireSuperShotgun ();
  960.         self.attack_finished = time + 0.7;
  961.     }
  962.     else if (self.weapon == IT_NAILGUN)
  963.     {
  964.         player_nail1 ();
  965.     }
  966.     else if (self.weapon == IT_SUPER_NAILGUN)
  967.     {
  968.         player_nail1 ();
  969.     }
  970.     else if (self.weapon == IT_GRENADE_LAUNCHER)
  971.     {
  972.         player_rocket1();
  973.         W_FireGrenade();
  974.         self.attack_finished = time + 0.6;
  975.     }
  976.     else if (self.weapon == IT_ROCKET_LAUNCHER)
  977.     {
  978.         player_rocket1();
  979.         W_FireRocket();
  980.         self.attack_finished = time + 0.8;
  981.     }
  982.     else if (self.weapon == IT_LIGHTNING)
  983.     {
  984.         player_light1();
  985.         self.attack_finished = time + 0.1;
  986.         sound (self, CHAN_AUTO, "weapons/lstart.wav", 1, ATTN_NORM);
  987.     }
  988. };
  989.  
  990. /*
  991. ============
  992. W_ChangeWeapon
  993.  
  994. ============
  995. */
  996. void() W_ChangeWeapon =
  997. {
  998.     local    float    it, am, fl;
  999.     
  1000.     it = self.items;
  1001.     am = 0;
  1002.     
  1003.     if (self.impulse == 1)
  1004.     {
  1005.         fl = IT_AXE;
  1006.     }
  1007.     else if (self.impulse == 2)
  1008.     {
  1009.         fl = IT_SHOTGUN;
  1010.         if (self.ammo_shells < 1)
  1011.             am = 1;
  1012.     }
  1013.     else if (self.impulse == 3)
  1014.     {
  1015.         fl = IT_SUPER_SHOTGUN;
  1016.         if (self.ammo_shells < 2)
  1017.             am = 1;
  1018.     }        
  1019.     else if (self.impulse == 4)
  1020.     {
  1021.         fl = IT_NAILGUN;
  1022.         if (self.ammo_nails < 1)
  1023.             am = 1;
  1024.     }
  1025.     else if (self.impulse == 5)
  1026.     {
  1027.         fl = IT_SUPER_NAILGUN;
  1028.         if (self.ammo_nails < 2)
  1029.             am = 1;
  1030.     }
  1031.     else if (self.impulse == 6)
  1032.     {
  1033.         fl = IT_GRENADE_LAUNCHER;
  1034.         if (self.ammo_rockets < 1)
  1035.             am = 1;
  1036.     }
  1037.     else if (self.impulse == 7)
  1038.     {
  1039.         fl = IT_ROCKET_LAUNCHER;
  1040.         if (self.ammo_rockets < 1)
  1041.             am = 1;
  1042.     }
  1043.     else if (self.impulse == 8)
  1044.     {
  1045.         fl = IT_LIGHTNING;
  1046.         if (self.ammo_cells < 1)
  1047.             am = 1;
  1048.     }
  1049.  
  1050.     self.impulse = 0;
  1051.     
  1052.     if (!(self.items & fl))
  1053.     {    // don't have the weapon or the ammo
  1054.         sprint (self, "no weapon.\n");
  1055.         return;
  1056.     }
  1057.     
  1058.     if (am)
  1059.     {    // don't have the ammo
  1060.         sprint (self, "not enough ammo.\n");
  1061.         return;
  1062.     }
  1063.  
  1064. //
  1065. // set weapon, set ammo
  1066. //
  1067.     self.weapon = fl;        
  1068.     W_SetCurrentAmmo ();
  1069. };
  1070.  
  1071. /*
  1072. ============
  1073. CheatCommand
  1074. ============
  1075. */
  1076. void() CheatCommand =
  1077. {
  1078.     if (deathmatch || coop)
  1079.         return;
  1080.  
  1081.     self.ammo_rockets = 100;
  1082.     self.ammo_nails = 200;
  1083.     self.ammo_shells = 100;
  1084.     self.items = self.items | 
  1085.         IT_AXE |
  1086.         IT_SHOTGUN |
  1087.         IT_SUPER_SHOTGUN |
  1088.         IT_NAILGUN |
  1089.         IT_SUPER_NAILGUN |
  1090.         IT_GRENADE_LAUNCHER |
  1091.         IT_ROCKET_LAUNCHER |
  1092.         IT_KEY1 | IT_KEY2;
  1093.  
  1094.     self.ammo_cells = 200;
  1095.     self.items = self.items | IT_LIGHTNING;
  1096.  
  1097.     self.weapon = IT_ROCKET_LAUNCHER;
  1098.     self.impulse = 0;
  1099.     W_SetCurrentAmmo ();
  1100. };
  1101.  
  1102. /*
  1103. ============
  1104. CycleWeaponCommand
  1105.  
  1106. Go to the next weapon with ammo
  1107. ============
  1108. */
  1109. void() CycleWeaponCommand =
  1110. {
  1111.     local    float    it, am;
  1112.     
  1113.     it = self.items;
  1114.     self.impulse = 0;
  1115.     
  1116.     while (1)
  1117.     {
  1118.         am = 0;
  1119.  
  1120.         if (self.weapon == IT_LIGHTNING)
  1121.         {
  1122.             self.weapon = IT_AXE;
  1123.         }
  1124.         else if (self.weapon == IT_AXE)
  1125.         {
  1126.             self.weapon = IT_SHOTGUN;
  1127.             if (self.ammo_shells < 1)
  1128.                 am = 1;
  1129.         }
  1130.         else if (self.weapon == IT_SHOTGUN)
  1131.         {
  1132.             self.weapon = IT_SUPER_SHOTGUN;
  1133.             if (self.ammo_shells < 2)
  1134.                 am = 1;
  1135.         }        
  1136.         else if (self.weapon == IT_SUPER_SHOTGUN)
  1137.         {
  1138.             self.weapon = IT_NAILGUN;
  1139.             if (self.ammo_nails < 1)
  1140.                 am = 1;
  1141.         }
  1142.         else if (self.weapon == IT_NAILGUN)
  1143.         {
  1144.             self.weapon = IT_SUPER_NAILGUN;
  1145.             if (self.ammo_nails < 2)
  1146.                 am = 1;
  1147.         }
  1148.         else if (self.weapon == IT_SUPER_NAILGUN)
  1149.         {
  1150.             self.weapon = IT_GRENADE_LAUNCHER;
  1151.             if (self.ammo_rockets < 1)
  1152.                 am = 1;
  1153.         }
  1154.         else if (self.weapon == IT_GRENADE_LAUNCHER)
  1155.         {
  1156.             self.weapon = IT_ROCKET_LAUNCHER;
  1157.             if (self.ammo_rockets < 1)
  1158.                 am = 1;
  1159.         }
  1160.         else if (self.weapon == IT_ROCKET_LAUNCHER)
  1161.         {
  1162.             self.weapon = IT_LIGHTNING;
  1163.             if (self.ammo_cells < 1)
  1164.                 am = 1;
  1165.         }
  1166.     
  1167.         if ( (self.items & self.weapon) && am == 0)
  1168.         {
  1169.             W_SetCurrentAmmo ();
  1170.             return;
  1171.         }
  1172.     }
  1173.  
  1174. };
  1175.  
  1176. /*
  1177. ============
  1178. ServerflagsCommand
  1179.  
  1180. Just for development
  1181. ============
  1182. */
  1183. void() ServerflagsCommand =
  1184. {
  1185.     serverflags = serverflags * 2 + 1;
  1186. };
  1187.  
  1188. void() QuadCheat =
  1189. {
  1190.     if (deathmatch || coop)
  1191.         return;
  1192.     self.super_time = 1;
  1193.     self.super_damage_finished = time + 30;
  1194.     self.items = self.items | IT_QUAD;
  1195.     dprint ("quad cheat\n");
  1196. };
  1197.  
  1198. void() ID =
  1199. {
  1200. };
  1201.  
  1202.  
  1203. // #####################
  1204. // ### chase cam mod ###
  1205. // main code block
  1206.  
  1207. void() Keep_cam_chasing_owner;
  1208. void( float opt ) Remove_chase_cam;
  1209.  
  1210. // defaults reset every time level starts
  1211. float chasecam_alt, chasecam_dist = 72, chasecam_zofs = 24;
  1212.  
  1213.  
  1214. // Resets weapon model after changing view
  1215. // called by chase cam or player entities
  1216. void( entity player_ent ) Chase_cam_setweapon =
  1217. {
  1218.    local entity e;
  1219.  
  1220.     e = self;
  1221.    self = player_ent;
  1222.    W_SetCurrentAmmo ();
  1223.     self = e;    
  1224.  
  1225. };
  1226.  
  1227. // called either by player or chase cam entities (to restart)
  1228. void( entity cam_owner ) Start_chase_cam =
  1229. {
  1230.  
  1231.     local entity    chase_cam;
  1232.  
  1233.     chase_cam = spawn();
  1234.  
  1235.    chase_cam.owner=cam_owner;
  1236.  
  1237.     // turn on bit-flag
  1238.    chase_cam.owner.speed = chase_cam.owner.speed | CHSCAM_ON;
  1239.     
  1240.    chase_cam.solid = SOLID_NOT;
  1241.     chase_cam.movetype = MOVETYPE_FLYMISSILE;
  1242.     
  1243.  
  1244.    chase_cam.angles = chase_cam.owner.angles;
  1245.  
  1246.     setmodel (chase_cam, "progs/eyes.mdl" );
  1247.     setsize (chase_cam, '0 0 0', '0 0 0');
  1248.    setorigin( chase_cam, chase_cam.owner.origin );
  1249.     chase_cam.classname = "chase_cam";
  1250.     
  1251.     chase_cam.nextthink = time + 0.1;    
  1252.     chase_cam.think = Keep_cam_chasing_owner;
  1253.  
  1254.    msg_entity = chase_cam.owner;                         // target of message
  1255.     WriteByte (MSG_ONE, SVC_SETVIEWPORT);  
  1256.     WriteEntity (MSG_ONE, chase_cam);           // view port
  1257.  
  1258.    Chase_cam_setweapon( cam_owner );
  1259.  
  1260.    // distance clipping
  1261.    chase_cam.ammo_shells = chasecam_dist;
  1262.    // offset choice
  1263.    chase_cam.ammo_cells = 0;
  1264.  
  1265. };
  1266.  
  1267. // secondary think for cam entities
  1268. void() Reable_chase_cam =
  1269. {
  1270.    self.nextthink = time + 0.1;
  1271.  
  1272.    // debug
  1273.    // sprint( self.owner, "Reable_chase_cam was called\n" );
  1274.  
  1275.    // clears bug of not being able to hit fire to restart
  1276.    // after dying in water
  1277.    if (self.owner.health <= 0)
  1278.    {
  1279.       remove( self );
  1280.       return;
  1281.    }
  1282.  
  1283.    if (  self.owner.waterlevel )
  1284.       return;
  1285.  
  1286.    Start_chase_cam( self.owner );
  1287.    remove( self );
  1288.  
  1289. };
  1290.  
  1291. // called only by chase cam entities
  1292. // opt values
  1293. // TRUE = remove completely
  1294. // FALSE = remove view but keep alive with Reable_chase_cam();
  1295. void( float opt ) Remove_chase_cam =
  1296. {
  1297.     // turn off bit-flag
  1298.    if ( (self.owner.speed & CHSCAM_ON) )
  1299.       self.owner.speed = self.owner.speed - CHSCAM_ON;
  1300.  
  1301.    // makes entity appear gone even if going into keep alive state
  1302.    setmodel( self, "" );
  1303.    self.velocity = '0 0 0';
  1304.     
  1305.    // set view-point back to normal
  1306.     msg_entity = self.owner;      // target of message
  1307.     WriteByte (MSG_ONE, SVC_SETVIEWPORT);  
  1308.     WriteEntity (MSG_ONE, self.owner);           // view port
  1309.  
  1310.    Chase_cam_setweapon( self.owner );
  1311.  
  1312.    if ( !opt )
  1313.    {
  1314.       self.nextthink = time + 0.1;
  1315.       self.think = Reable_chase_cam;
  1316.    }
  1317.    else
  1318.       remove( self );
  1319.  
  1320. };
  1321.  
  1322. /*
  1323. ###########
  1324. main think function for cam entities
  1325.  self.ammo_shells = distance clipping
  1326.  self.ammo_nails = hang-up flag
  1327.  self.ammo_cells = view offset direction
  1328.    0 = up
  1329.    1 = left
  1330.    2 = right
  1331. ###########
  1332. */
  1333. void() Keep_cam_chasing_owner =
  1334. {
  1335.     local vector    spot2, dir;
  1336.    local float dist, cap;
  1337.  
  1338.    local float  f_f, f_r;
  1339.  
  1340.    self.nextthink = time + 0.1; 
  1341.  
  1342.    // check if player turned off
  1343.     // or in water
  1344.    if (! (self.owner.speed & CHSCAM_ON))
  1345.     {
  1346.       Remove_chase_cam( TRUE );
  1347.         return;
  1348.     }
  1349.    if ( self.owner.waterlevel )
  1350.    {
  1351.       if (self.owner.health > 0)
  1352.       {
  1353.          Remove_chase_cam( FALSE );
  1354.          return;
  1355.       }
  1356.    }
  1357.     
  1358.    // get player velocity relative to player's
  1359.    // current yaw
  1360.    // f_f (based on running calcs (maxspeed = 400)
  1361.    //  (back ~= 640, forward ~= 0)
  1362.    // f_r
  1363.    //  (left ~= 640, right ~= 0)
  1364.    dir_y = self.owner.v_angle_y;
  1365.    makevectors( dir );
  1366.    f_f = vlen( (v_forward * 320) - self.owner.velocity );
  1367.    f_r = vlen( (v_right * 320) - self.owner.velocity );
  1368.  
  1369.    // held for use after second makevectors call for
  1370.    // v_forward based only on yaw
  1371.    dir = v_forward;
  1372.  
  1373.    /*
  1374.    local string s;
  1375.    sprint( self.owner, "\n\n f_f = " );
  1376.    s = ftos( f_f );
  1377.    sprint( self.owner, s );
  1378.    sprint( self.owner, "\n f_r = " );
  1379.    s = ftos( f_r );
  1380.    sprint( self.owner, s );
  1381.    sprint( self.owner, "\n" );
  1382.    */
  1383.  
  1384.    if (self.owner.speed & CHSCAM_ALT)
  1385.    {
  1386.       if (f_f < 160 || self.owner.v_angle_x < -45)
  1387.          self.ammo_cells = 0;
  1388.       else if (f_r < 80)
  1389.          self.ammo_cells = 1;
  1390.       else if (f_r > 560)
  1391.          self.ammo_cells = 2;
  1392.    }
  1393.    else
  1394.       self.ammo_cells = 0;
  1395.  
  1396.  
  1397.    makevectors( self.owner.v_angle );
  1398.  
  1399.    // set spot before clipping
  1400.    spot2 = self.owner.origin - (v_forward * self.ammo_shells);
  1401.  
  1402.    if (!self.ammo_cells)
  1403.    {
  1404.       if (self.owner.v_angle_x > 16)
  1405.       {
  1406.          // dir is first v_forward based on yaw only
  1407.          spot2 = spot2 + (dir * (self.owner.v_angle_x - 16) );
  1408.          cap = chasecam_zofs - ((self.owner.v_angle_x - 16) * 0.2);
  1409.          if (cap < 0) cap = 0;
  1410.          spot2_z = spot2_z + cap;
  1411.       }
  1412.       else
  1413.          spot2_z = spot2_z + chasecam_zofs;
  1414.    }
  1415.    else if (self.ammo_cells == 1)
  1416.       spot2 = spot2 - (v_right * (chasecam_zofs));
  1417.    else
  1418.       spot2 = spot2 + (v_right * (chasecam_zofs));
  1419.  
  1420.  
  1421.    traceline (self.owner.origin, spot2, FALSE, self.owner);
  1422.  
  1423.    // avoids most hang-ups along walls
  1424.    spot2 = trace_endpos + ( v_forward * 2 );
  1425.  
  1426.    // for fading from walls and up-aim auto rising
  1427.    self.ammo_shells = 10 + vlen(trace_endpos - self.owner.origin);
  1428.  
  1429.  
  1430.    // clip from ceiling if too close
  1431.    traceline (spot2, spot2 + '0 0 32', FALSE, self.owner );
  1432.    if (trace_fraction < 1 )
  1433.    {
  1434.       dir = trace_endpos - '0 0 32';
  1435.  
  1436.       traceline (spot2, spot2 - '0 0 32', FALSE, self.owner );
  1437.       if (trace_fraction == 1)
  1438.          spot2 = dir;
  1439.    }
  1440.  
  1441.  
  1442.    dir = normalize(spot2 - self.origin);
  1443.    dist = vlen(spot2 - self.origin);
  1444.  
  1445.    
  1446.    traceline( self.origin, spot2, FALSE, self.owner );
  1447.    if ( trace_fraction == 1 )
  1448.     {
  1449.       self.angles = self.owner.angles;
  1450.  
  1451.       cap = dist * 0.2;
  1452.  
  1453.       if (cap > 5.2)
  1454.          self.velocity = dir * dist * 5.2;
  1455.       else if (cap > 1)
  1456.          self.velocity = dir * dist * cap;
  1457.       else
  1458.          self.velocity = dir * dist;
  1459.  
  1460.       // tighten up if owner running backwards
  1461.       if ( f_f > 560)
  1462.       {
  1463.          self.velocity = self.velocity * 2;
  1464.       }
  1465.       
  1466.    }
  1467.     else
  1468.         setorigin( self, spot2 );
  1469.  
  1470.  
  1471.    // fade back from walls
  1472.    self.ammo_shells = self.ammo_shells + 4;
  1473.    if (self.ammo_shells > chasecam_dist)
  1474.       self.ammo_shells = chasecam_dist;
  1475.  
  1476.    // respawn if missile ent. get's hung up
  1477.    if( self.oldorigin == self.origin )
  1478.    {
  1479.       if( dist > 30 )
  1480.          self.ammo_nails = self.ammo_nails + 1;
  1481.  
  1482.    }
  1483.    if( self.ammo_nails > 3 )
  1484.    {
  1485.       Start_chase_cam( self.owner );
  1486.       remove( self );
  1487.       return;
  1488.    }
  1489.    self.oldorigin = self.origin;
  1490.  
  1491. };
  1492.  
  1493. // called by player only
  1494. void() Toggle_chase_cam =
  1495. {
  1496.  
  1497.    if( (self.speed & CHSCAM_ON) )
  1498.     {
  1499.         // will be noticed by next think
  1500.         // of player's chase cam entity
  1501.       self.speed = self.speed - CHSCAM_ON;
  1502.     }
  1503.     else
  1504.     {
  1505.       Start_chase_cam( self );
  1506.     }
  1507.         
  1508. };
  1509.  
  1510. // called by player only
  1511. void() Toggle_chase_type =
  1512. {
  1513.  
  1514.    if( (self.speed & CHSCAM_ALT) )
  1515.    {
  1516.       self.speed = self.speed - CHSCAM_ALT;
  1517.       sprint( self, "View tracking: normal\n" );
  1518.    }
  1519.    else
  1520.    {
  1521.       self.speed = self.speed | CHSCAM_ALT;
  1522.       sprint( self, "View tracking: strafeing\n" );
  1523.    }
  1524.         
  1525. };
  1526.  
  1527. ////////////////////////////////////////////
  1528. // laser targeter functions
  1529.  
  1530. /*
  1531. void () SDR_SightThink =
  1532. {
  1533.     local vector org;
  1534.  
  1535.         makevectors(self.owner.v_angle);
  1536.     org = self.owner.origin + v_up*16;
  1537.  
  1538.         traceline (org, org + v_forward*2048, FALSE, self);
  1539.  
  1540.         if (trace_fraction == 1.0)
  1541.     {
  1542.         // move sight inside player if can hit anything
  1543.             setorigin(self, self.owner.origin );
  1544.         return;
  1545.     }
  1546.  
  1547.     // check if target is damageable and set proper model
  1548.     if (trace_ent.takedamage)
  1549.         setmodel (self, "progs/cross2.mdl");
  1550.     else
  1551.         setmodel (self, "progs/cross1.mdl");
  1552.  
  1553.     // move sight at line of sight collision
  1554.     self.angles = vectoangles(v_forward);
  1555.         setorigin(self, trace_endpos );
  1556.  
  1557.     // mark think to update sight position
  1558.     self.nextthink = time + 0.05;
  1559. };
  1560. */
  1561.  
  1562.  
  1563. /*
  1564. void ()    SDR_SightMake =
  1565. {
  1566.     local entity cross;
  1567.  
  1568.         self.sight_out = TRUE;
  1569.  
  1570.     cross = spawn ();
  1571.     cross.owner = self;
  1572.     cross.movetype = MOVETYPE_NOCLIP;
  1573.     cross.solid = SOLID_NOT;
  1574.  
  1575.     setmodel (cross, "progs/cross1.mdl");
  1576.     cross.classname = "laser_sight";
  1577.  
  1578.     setorigin( cross, self.origin );
  1579.  
  1580.     cross.think = SDR_SightThink;
  1581.     cross.nextthink = time + 0.05;
  1582. };
  1583. */
  1584.  
  1585. // targeter ent. think function
  1586. void() LaserTargeterTrack = {
  1587.    local vector dir, src;
  1588.  
  1589.    if (! (self.owner.speed & LASERTARG_ON))
  1590.    {
  1591.       remove( self );
  1592.       return;
  1593.    }
  1594.  
  1595.    makevectors( self.owner.v_angle );
  1596.     
  1597.    src = self.owner.origin;
  1598.  
  1599.    src = self.owner.origin + v_forward * 10;
  1600.    src_z = self.owner.absmin_z + self.owner.size_z * 0.7;
  1601.  
  1602.    dir = aim( self.owner, 100000 );
  1603.    traceline( src,  src + dir * 320, FALSE, self.owner);
  1604.  
  1605.    src = 0.1 * src + 0.9 * trace_endpos;
  1606.  
  1607.    setorigin( self, src );
  1608.  
  1609.    self.nextthink = time + 0.1;
  1610. };
  1611.  
  1612. void( entity targ_owner ) LaserTargeterToggle =
  1613. {
  1614.  
  1615.    local entity e;
  1616.  
  1617.    if( (targ_owner.speed & LASERTARG_ON) )
  1618.       targ_owner.speed = targ_owner.speed - LASERTARG_ON;
  1619.    else
  1620.    {
  1621.       targ_owner.speed = targ_owner.speed | LASERTARG_ON;
  1622.       
  1623.       e = spawn();
  1624.       e.owner = targ_owner;
  1625.  
  1626.       e.movetype = MOVETYPE_NONE;
  1627.       e.solid = SOLID_NOT;
  1628.  
  1629.       setmodel( e, "progs/s_bubble.spr" );
  1630.       setsize( e, VEC_ORIGIN, VEC_ORIGIN );    
  1631.       setorigin( e, e.owner.origin );
  1632.  
  1633.       e.nextthink = time + 0.1;
  1634.       e.think = LaserTargeterTrack;
  1635.  
  1636.     }
  1637.  
  1638. };
  1639. ////////////////////////////////////////////
  1640.  
  1641.  
  1642. void() Chase_cam_lvlstart_think =
  1643. {
  1644.  
  1645.    local string s;
  1646.  
  1647.    if ( (self.owner.speed & CHSCAM_ON) )
  1648.       Start_chase_cam( self.owner );
  1649.    if ( (self.owner.speed & LASERTARG_ON) )
  1650.    {
  1651.       self.owner.speed = self.owner.speed - LASERTARG_ON;
  1652.       LaserTargeterToggle( self.owner );
  1653.    }
  1654.  
  1655.    remove( self );
  1656.  
  1657. };
  1658.  
  1659.  
  1660. // called in CLIENT.QC by void() PutClientInServer
  1661. // player.speed is set and saved between levels using parm16
  1662. // in CLIENT.QC
  1663. void() Chase_cam_level_start =
  1664. {
  1665.  
  1666.    local entity e;
  1667.  
  1668.       e = spawn();
  1669.       e.owner = self;
  1670.  
  1671.       e.movetype = MOVETYPE_NONE;
  1672.       e.solid = SOLID_NOT;
  1673.  
  1674.       setmodel( e, "" );
  1675.       setsize( e, VEC_ORIGIN, VEC_ORIGIN );    
  1676.       setorigin( e, e.owner.origin );
  1677.  
  1678.       e.nextthink = time + 0.2;
  1679.       e.think = Chase_cam_lvlstart_think;
  1680.  
  1681. };
  1682.  
  1683.  
  1684. // ### chase cam mod ###
  1685. // #####################
  1686.  
  1687.  
  1688.  
  1689.  
  1690. // ######################
  1691. // ### Multiskin v1.1 ###
  1692.  
  1693. void( float imp ) Choose_multiskin =
  1694. {
  1695.    if (imp == 200)
  1696.    {
  1697.         self.skin = self.skin + 1;
  1698.         if (self.skin == 19)
  1699.          self.skin = 0;
  1700.    }
  1701.    else
  1702.    {
  1703.         self.skin = self.skin - 1;
  1704.       if (self.skin == -1)
  1705.          self.skin = 18;
  1706.    }
  1707.  
  1708.    if (self.skin == 0)
  1709.       centerprint(self, "SKIN: the Good Guy Himself (1)");
  1710.    else if (self.skin == 1)
  1711.       centerprint(self, "SKIN: Duke Nukem 3d (2)");
  1712.    else if (self.skin == 2)
  1713.       centerprint(self, "SKIN: Mr. Toad (3)");
  1714.    else if (self.skin == 3)
  1715.       centerprint(self, "SKIN: the Stormtrooper (4)");
  1716.    else if (self.skin == 4)
  1717.       centerprint(self, "SKIN: Max (5)");
  1718.    else if (self.skin == 5)
  1719.       centerprint(self, "SKIN: the Terminator (6)");
  1720.    else if (self.skin == 6)
  1721.       centerprint(self, "SKIN: Judge Dredd (7)");
  1722.    else if (self.skin == 7)
  1723.       centerprint(self, "SKIN: Camouflaged soldier (8)");
  1724.    else if (self.skin == 8)
  1725.       centerprint(self, "SKIN: Captain Picard (9)");
  1726.    else if (self.skin == 9)
  1727.       centerprint(self, "SKIN: the Wizzard (10)");
  1728.    else if (self.skin == 10)
  1729.       centerprint(self,"SKIN: the Predator (11)");
  1730.    else if (self.skin == 11)
  1731.       centerprint(self,"SKIN: Skeleton (12)");
  1732.    else if (self.skin == 12)
  1733.       centerprint(self,"SKIN: Wan-Fu (13)");
  1734.    else if (self.skin == 13)
  1735.       centerprint(self,"SKIN: Henry Rollins (14)");
  1736.    else if (self.skin == 14)
  1737.       centerprint(self,"SKIN: He-Man (15)");
  1738.    else if (self.skin == 15)
  1739.       centerprint(self,"SKIN: Boba (16)");
  1740.    else if (self.skin == 16)
  1741.       centerprint(self,"SKIN: Superman (17)");
  1742.    else if (self.skin == 17)
  1743.       centerprint(self,"SKIN: NYPD Cop (18)");
  1744.    else if (self.skin == 18)
  1745.       centerprint(self,"SKIN: Red/Yellow women dude (19)");
  1746. };
  1747.  
  1748. // ### Multiskin v1.1 ###
  1749. // ######################
  1750.  
  1751.  
  1752.  
  1753. /*
  1754. ============
  1755. ImpulseCommands
  1756.  
  1757. ============
  1758. */
  1759. void() ImpulseCommands =
  1760. {
  1761.    if (self.impulse >= 1 && self.impulse <= 8)
  1762.         W_ChangeWeapon ();
  1763.  
  1764.    else if (self.impulse == 9)
  1765.         CheatCommand ();
  1766.    else if (self.impulse == 10)
  1767.         CycleWeaponCommand ();
  1768.    else if (self.impulse == 11)
  1769.         ServerflagsCommand ();
  1770.  
  1771.    // ### chase cam mods ###
  1772.    else if ( self.impulse == 30)
  1773.       Toggle_chase_cam(); // Toggle view
  1774.    else if ( self.impulse == 31)  // laser targeter toggle
  1775.       LaserTargeterToggle( self );
  1776.    else if ( self.impulse == 32)
  1777.       Toggle_chase_type();  // Toggle alternate 'strafe' style
  1778.                             // tracking
  1779.  
  1780.  
  1781.    // ### Multiskin v1.1 ###
  1782.    else if ( self.impulse == 200 || self.impulse == 201 )
  1783.       Choose_multiskin( self.impulse );
  1784.  
  1785.    else if (self.impulse == 255)
  1786.         QuadCheat ();
  1787.         
  1788.     self.impulse = 0;
  1789. };
  1790.  
  1791. /*
  1792. ============
  1793. W_WeaponFrame
  1794.  
  1795. Called every frame so impulse events can be handled as well as possible
  1796. ============
  1797. */
  1798. void() W_WeaponFrame =
  1799. {
  1800.     if (time < self.attack_finished)
  1801.         return;
  1802.  
  1803.     ImpulseCommands ();
  1804.     
  1805. // check for attack
  1806.     if (self.button0)
  1807.     {
  1808.         SuperDamageSound ();
  1809.         W_Attack ();
  1810.     }
  1811. };
  1812.  
  1813. /*
  1814. ========
  1815. SuperDamageSound
  1816.  
  1817. Plays sound if needed
  1818. ========
  1819. */
  1820. void() SuperDamageSound =
  1821. {
  1822.     if (self.super_damage_finished > time)
  1823.     {
  1824.         if (self.super_sound < time)
  1825.         {
  1826.             self.super_sound = time + 1;
  1827.             sound (self, CHAN_BODY, "items/damage3.wav", 1, ATTN_NORM);
  1828.         }
  1829.     }
  1830.     return;
  1831. };
  1832.  
  1833.  
  1834.