2 // increments sprite frame, loops when end is hit.. simple
\r
5 void (vector vec) WriteVec =
\r
7 WriteCoord (MSG_BROADCAST, vec_x);
\r
8 WriteCoord (MSG_BROADCAST, vec_y);
\r
9 WriteCoord (MSG_BROADCAST, vec_z);
\r
11 void (vector org, vector dir, float counts) W_Smoke =
\r
13 WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
\r
14 WriteByte (MSG_BROADCAST, TE_SMOKE);
\r
17 WriteByte (MSG_BROADCAST, counts);
\r
20 // increments sprite frame, loops when end is hit.. simple
\r
21 void animate_sprite (float startframe, float frame_count)
\r
23 if ((self.frame - startframe) >= (frame_count - 1 ))
\r
24 self.frame = startframe;
\r
26 self.frame = self.frame + 1;
\r
29 void W_UpdateAmmo (void)
\r
32 self.items = self.items - (self.items & (IT_NAILS | IT_SHELLS | IT_ROCKETS | IT_CELLS));
\r
34 if (self.weapon == IT_LASER)
\r
35 self.currentammo = 1;
\r
36 else if (self.weapon == IT_SHOTGUN)
\r
38 self.currentammo = self.ammo_shells;
\r
39 self.items = self.items | IT_SHELLS;
\r
41 else if (self.weapon == IT_UZI)
\r
43 self.currentammo = self.ammo_nails;
\r
44 self.items = self.items | IT_NAILS;
\r
46 else if (self.weapon == IT_GRENADE_LAUNCHER || self.weapon == IT_HAGAR || self.weapon == IT_ROCKET_LAUNCHER)
\r
48 self.currentammo = self.ammo_rockets;
\r
49 self.items = self.items | IT_ROCKETS;
\r
51 else if (self.weapon == IT_ELECTRO || self.weapon == IT_NEX || self.weapon == IT_CRYLINK)
\r
53 self.currentammo = self.ammo_cells;
\r
54 self.items = self.items | IT_CELLS;
\r
59 void W_UpdateWeapon (void)
\r
62 if (self.weapon == IT_LASER)
\r
63 self.weaponmodel = "models/weapons/w_laser.zym";
\r
64 else if (self.weapon == IT_SHOTGUN)
\r
65 self.weaponmodel = "models/weapons/w_shotgun.zym";
\r
66 else if (self.weapon == IT_UZI)
\r
67 self.weaponmodel = "models/weapons/w_uzi.zym";
\r
68 else if (self.weapon == IT_GRENADE_LAUNCHER)
\r
69 self.weaponmodel = "models/weapons/w_gl.zym";
\r
70 else if (self.weapon == IT_ELECTRO)
\r
71 self.weaponmodel = "models/weapons/w_electro.zym";
\r
72 else if (self.weapon == IT_CRYLINK)
\r
73 self.weaponmodel = "models/weapons/w_crylink.zym";
\r
74 else if (self.weapon == IT_NEX)
\r
75 self.weaponmodel = "models/weapons/w_nex.zym";
\r
76 else if (self.weapon == IT_HAGAR)
\r
77 self.weaponmodel = "models/weapons/w_hagar.zym";
\r
78 else if (self.weapon == IT_ROCKET_LAUNCHER)
\r
79 self.weaponmodel = "models/weapons/w_rl.zym";
\r
81 objerror ("Illegal weapon - please register your guns please!");
\r
85 float W_GetBestWeapon (entity e)
\r
88 if ((e.items & IT_ROCKET_LAUNCHER) && e.ammo_rockets)
\r
89 return IT_ROCKET_LAUNCHER;
\r
90 else if ((e.items & IT_NEX) && e.ammo_cells)
\r
92 else if ((e.items & IT_HAGAR) && e.ammo_rockets)
\r
94 else if ((e.items & IT_GRENADE_LAUNCHER) && e.ammo_rockets)
\r
95 return IT_GRENADE_LAUNCHER;
\r
96 else if ((e.items & IT_ELECTRO) && e.ammo_cells)
\r
98 else if ((e.items & IT_CRYLINK) && e.ammo_cells)
\r
100 else if ((e.items & IT_UZI) && e.ammo_nails)
\r
102 else if ((e.items & IT_SHOTGUN) && e.ammo_shells)
\r
110 void ResetExtraWeapon()
\r
112 if(self.wpn5 == world)
\r
114 self.wpn5 = spawn();
\r
117 self.wpn5.weapon = 0;
\r
118 self.wpn5.mass = 0;
\r
119 self.items = self.items - (self.items & IT_WEP5);
\r
122 void W_GiveWeapon (entity e, float wep, string name, float wmass)
\r
129 //e.items = e.items | wep;
\r
134 self.wpn5.weapon = wep;
\r
135 self.wpn5.mass = wmass;
\r
137 self.items = self.items | IT_WEP5;
\r
139 weapon_action(self.weapon, WR_UPDATECOUNTS);
\r
140 if(self.weapon == WEP5) // if using carrying # 5 already
\r
142 //bprint("reset wep5\n");
\r
143 self.wpn = self.wpn5.weapon;
\r
144 self.switchweapon = WEP5;
\r
145 weapon_action(self.weapon, WR_DROP);
\r
147 //weapon_action(self.wpn, WR_SETUP); // update the weapon we're holding
\r
148 //weapon_action(self.wpn, WR_RAISE); // update the weapon we're holding
\r
151 if (other.classname == "player")
\r
153 sprint (other, "You got the ^2");
\r
154 sprint (other, name);
\r
155 sprint (other, "\n");
\r
167 void W_SwitchWeapon (float wep)
\r
170 var float noammo = FALSE;
\r
173 nextwep = IT_LASER;
\r
176 nextwep = IT_SHOTGUN;
\r
177 if (!self.ammo_shells)
\r
183 if (!self.ammo_nails)
\r
188 nextwep = IT_CRYLINK;
\r
189 if (!self.ammo_cells)
\r
194 nextwep = IT_ELECTRO;
\r
195 if (!self.ammo_cells)
\r
200 nextwep = IT_GRENADE_LAUNCHER;
\r
201 if (!self.ammo_rockets)
\r
206 nextwep = IT_HAGAR;
\r
207 if (!self.ammo_rockets)
\r
213 if (!self.ammo_cells)
\r
218 nextwep = IT_ROCKET_LAUNCHER;
\r
219 if (!self.ammo_rockets)
\r
224 if (!(self.items & nextwep))
\r
226 sprint (self, "You don't own that weapon\n");
\r
231 sprint (self, "You don't have any ammo for that weapon\n");
\r
235 self.weapon = nextwep;
\r
238 self.attack_finished = time + 0.2;
\r
239 if (self.viewzoom != 1)
\r
243 void W_NextWeapon (void)
\r
251 if (self.weapon == IT_ROCKET_LAUNCHER)
\r
252 self.weapon = IT_LASER;
\r
253 else if (self.weapon == IT_LASER)
\r
255 self.weapon = IT_SHOTGUN;
\r
256 if (!self.ammo_shells)
\r
259 else if (self.weapon == IT_SHOTGUN)
\r
261 self.weapon = IT_UZI;
\r
262 if (!self.ammo_nails)
\r
265 else if (self.weapon == IT_UZI)
\r
267 self.weapon = IT_CRYLINK;
\r
268 if (!self.ammo_cells)
\r
271 else if (self.weapon == IT_CRYLINK)
\r
273 self.weapon = IT_ELECTRO;
\r
274 if (!self.ammo_cells)
\r
277 else if (self.weapon == IT_ELECTRO)
\r
279 self.weapon = IT_GRENADE_LAUNCHER;
\r
280 if (!self.ammo_cells)
\r
283 else if (self.weapon == IT_GRENADE_LAUNCHER)
\r
285 self.weapon = IT_HAGAR;
\r
286 if (!self.ammo_rockets)
\r
289 else if (self.weapon == IT_HAGAR)
\r
291 self.weapon = IT_NEX;
\r
292 if (!self.ammo_rockets)
\r
295 else if (self.weapon == IT_NEX)
\r
297 self.weapon = IT_ROCKET_LAUNCHER;
\r
298 if (!self.ammo_cells)
\r
302 if ((self.items & self.weapon) && !noammo)
\r
311 void W_PreviousWeapon (void)
\r
319 if (self.weapon == IT_SHOTGUN)
\r
320 self.weapon = IT_LASER;
\r
321 else if (self.weapon == IT_UZI)
\r
323 self.weapon = IT_SHOTGUN;
\r
324 if (!self.ammo_shells)
\r
327 else if (self.weapon == IT_CRYLINK)
\r
329 self.weapon = IT_UZI;
\r
330 if (!self.ammo_nails)
\r
333 else if (self.weapon == IT_ELECTRO)
\r
335 self.weapon = IT_CRYLINK;
\r
336 if (!self.ammo_cells)
\r
339 else if (self.weapon == IT_GRENADE_LAUNCHER)
\r
341 self.weapon = IT_ELECTRO;
\r
342 if (!self.ammo_cells)
\r
345 else if (self.weapon == IT_HAGAR)
\r
347 self.weapon = IT_GRENADE_LAUNCHER;
\r
348 if (!self.ammo_rockets)
\r
351 else if (self.weapon == IT_NEX)
\r
353 self.weapon = IT_HAGAR;
\r
354 if (!self.ammo_rockets)
\r
357 else if (self.weapon == IT_ROCKET_LAUNCHER)
\r
359 self.weapon = IT_NEX;
\r
360 if (!self.ammo_cells)
\r
363 else if (self.weapon == IT_LASER)
\r
365 self.weapon = IT_ROCKET_LAUNCHER;
\r
366 if (!self.ammo_rockets)
\r
370 if ((self.items & self.weapon) && !noammo)
\r
379 float W_CheckAmmo (void)
\r
381 if ((cvar("g_instagib") == 1) | (cvar("g_rocketarena") == 1))
\r
385 if (self.weapon == IT_LASER)
\r
387 else if (self.currentammo)
\r
390 self.weapon = W_GetBestWeapon (self);
\r
397 void FireRailgunBullet (vector src, float bdamage, vector dir, float spread, float deathtype)
\r
400 entity saveself, last;
\r
402 org = self.origin + self.view_ofs;
\r
409 while (bdamage > 0)
\r
411 traceline_hitcorpse (self, org, org + v_forward * 4096 + v_right * crandom () * spread + v_up * crandom () * spread, FALSE, self);
\r
413 lastpos = trace_endpos;
\r
414 if (trace_fraction != 1.0)
\r
416 if (pointcontents(trace_endpos - dir*4) == CONTENT_SKY)
\r
419 if (trace_ent.takedamage || trace_ent.classname == "case")
\r
421 if (trace_ent.classname == "player" || trace_ent.classname == "corpse" || trace_ent.classname == "gib")
\r
422 te_blood (trace_endpos, dir * bdamage * 16, bdamage);
\r
423 Damage (trace_ent, self, self, bdamage, deathtype, trace_endpos, dir * bdamage);
\r
426 if (last.solid == SOLID_BSP)
\r
432 void FireRailgunBullet (vector start, vector end, float bdamage, float deathtype)
\r
434 local vector hitloc, force;
\r
436 //local entity explosion;
\r
438 force = normalize(end - start) * 800; //(bdamage * 10);
\r
440 // find how far the beam can go until it hits a wall
\r
441 traceline (start, end, MOVE_HITMODEL, self); // doing this enables checking against model
\r
442 // geometry -- leaving it disabled for now since
\r
444 //traceline (start, end, TRUE, self);
\r
445 // go a little bit into the wall because we need to hit this wall later
\r
446 end = trace_endpos + normalize(end - start);
\r
448 local float dam_mult;
\r
455 traceline_hitcorpse (self, start, end, FALSE, self);
\r
456 if (trace_ent/* && deathtype == WEP_RAILGUN*/) // Area damage!
\r
458 if ((trace_ent.classname == "player"))
\r
460 f = (trace_endpos - start);
\r
461 g_x = trace_endpos_x;
\r
462 g_y = trace_endpos_y;
\r
464 h_x = trace_ent.origin_x;
\r
465 h_y = trace_ent.origin_y;
\r
467 x = vlen ((g - h));
\r
468 f = ((normalize (f) * x) + trace_endpos);
\r
469 zdif = (f_z - trace_ent.origin_z);
\r
470 bprint(ftos(zdif));
\r
473 trace_ent.head_shot_vector = '0 0 0';
\r
474 if (trace_ent.crouch == 1) // Damage enemy that's crouching
\r
479 if ((trace_ent.team_no != self.team_no))
\r
481 trace_ent.leg_damage = (trace_ent.leg_damage + 1);
\r
482 TeamFortress_SetSpeed (trace_ent);
\r
483 deathmsg = RAILGUN_LEGSHOT;
\r
484 bdamage = bdamage * .8;
\r
486 if ((trace_ent.health > 0))
\r
488 if ((trace_ent.team_no == self.team_no))
\r
490 sprint (self, "Stop shooting team mates!!!\n");
\r
494 sprint (trace_ent, "Leg injury!\n");
\r
495 sprint (self, "Leg shot - that'll slow him down!\n");
\r
504 stuffcmd (trace_ent, "bf\n");
\r
506 if ((trace_ent.health > 0))
\r
508 if ((trace_ent.team_no == self.team_no))
\r
510 sprint (self, "Stop shooting team mates!!!\n");
\r
514 trace_ent.head_shot_vector = (trace_ent.origin - self.origin);
\r
518 bdamage = floor(bdamage * 4.0);
\r
519 deathmsg = RAILGUN_HEADSHOT;
\r
523 bdamage = floor(bdamage * 2.5);
\r
524 deathmsg = RAILGUN_CHESTSHOT;
\r
526 sound (self, 0, "speech/excelent.wav", 1, 0);
\r
531 deathmsg = RAILGUN_BODYSHOT;
\r
536 else { // Damage standing enemy
\r
540 if ((trace_ent.team_no != self.team_no))
\r
542 trace_ent.leg_damage = (trace_ent.leg_damage + 1);
\r
543 TeamFortress_SetSpeed (trace_ent);
\r
544 deathmsg = RAILGUN_LEGSHOT;
\r
545 bdamage = bdamage * .8;
\r
546 //T_Damage (trace_ent, self, self, (self.heat * dam_mult));
\r
548 if ((trace_ent.health > 0))
\r
550 if ((trace_ent.team_no == self.team_no))
\r
552 sprint (self, "Stop shooting team mates!!!\n");
\r
556 sprint (trace_ent, "Leg injury!\n");
\r
557 sprint (self, "Leg shot - that'll slow him down!\n");
\r
558 deathmsg = RAILGUN_LEGSHOT;
\r
568 stuffcmd (trace_ent, "bf\n");
\r
570 if ((trace_ent.health > 0))
\r
572 if ((trace_ent.team_no == self.team_no))
\r
574 sprint (self, "Stop shooting team mates!!!\n");
\r
578 trace_ent.head_shot_vector = (trace_ent.origin - self.origin);
\r
580 // bdamage = floor(bdamage * 3.5);
\r
583 bdamage = floor(bdamage * 15.5);
\r
584 deathmsg = RAILGUN_HEADSHOT;
\r
588 bdamage = floor(bdamage * 2.5);
\r
589 deathmsg = RAILGUN_CHESTSHOT;
\r
591 // T_Damage (trace_ent, self, self, (self.heat * dam_mult));
\r
592 sound (self, 0, "speech/excelent.wav", 1, 0);
\r
593 // if ((trace_ent.health > 0))
\r
595 // sprint (trace_ent, 0, "Head injury!\n");
\r
596 // sprint (self, 1, "Head shot - that's gotta hurt!\n");
\r
603 deathmsg = RAILGUN_BODYSHOT;
\r
611 // trace multiple times until we hit a wall, each obstacle will be made
\r
612 // non-solid so we can hit the next, while doing this we spawn effects and
\r
613 // note down which entities were hit so we can damage them later
\r
616 traceline_hitcorpse (self, start, end, FALSE, self);
\r
618 // if it is world we can't hurt it so stop now
\r
619 if (trace_ent == world || trace_fraction == 1)
\r
622 // make the entity non-solid so we can hit the next one
\r
623 trace_ent.railgunhit = TRUE;
\r
624 trace_ent.railgunhitloc = trace_endpos;
\r
625 trace_ent.railgunhitsolidbackup = trace_ent.solid;
\r
627 // stop if this is a wall
\r
628 if (trace_ent.solid == SOLID_BSP)
\r
631 // make the entity non-solid
\r
632 trace_ent.solid = SOLID_NOT;
\r
635 // find all the entities the railgun hit and restore their solid state
\r
636 ent = findfloat(world, railgunhit, TRUE);
\r
639 // restore their solid type
\r
640 ent.solid = ent.railgunhitsolidbackup;
\r
641 ent = findfloat(ent, railgunhit, TRUE);
\r
644 // spawn a temporary explosion entity for RadiusDamage calls
\r
645 //explosion = spawn();
\r
647 // find all the entities the railgun hit and hurt them
\r
648 ent = findfloat(world, railgunhit, TRUE);
\r
651 // get the details we need to call the damage function
\r
652 hitloc = ent.railgunhitloc;
\r
653 ent.railgunhitloc = '0 0 0';
\r
654 ent.railgunhitsolidbackup = SOLID_NOT;
\r
655 ent.railgunhit = FALSE;
\r
657 // apply the damage
\r
658 if (ent.takedamage || ent.classname == "case")
\r
659 // Damage (ent, self, self, bdamage, deathtype, hitloc, force);
\r
660 Damage (ent, self, self, bdamage, deathmsg, hitloc, force);
\r
662 // create a small explosion to throw gibs around (if applicable)
\r
663 //setorigin (explosion, hitloc);
\r
664 //RadiusDamage (explosion, self, 10, 0, 50, world, 300, deathtype);
\r
666 // advance to the next entity
\r
667 ent = findfloat(ent, railgunhit, TRUE);
\r
670 // we're done with the explosion entity, remove it
\r
671 //remove(explosion);
\r
674 // Area damage function --
\r
675 // added this so I dont have to paste this into every function I want area damage in.
\r
676 // Returns a value of LEGSHOT, BODYSHOT, CHESTSHOT, or HEADSHOT.
\r
677 float (entity a, vector start, vector end, float flt, entity b) FindBodyDamage =
\r
679 local float dam_mult;
\r
686 traceline_hitcorpse (a, start, end, flt, b);
\r
689 if ((trace_ent.classname == "player"))
\r
691 f = (trace_endpos - start);
\r
692 g_x = trace_endpos_x;
\r
693 g_y = trace_endpos_y;
\r
695 h_x = trace_ent.origin_x;
\r
696 h_y = trace_ent.origin_y;
\r
698 x = vlen ((g - h));
\r
699 f = ((normalize (f) * x) + trace_endpos);
\r
700 zdif = (f_z - trace_ent.origin_z);
\r
704 trace_ent.head_shot_vector = '0 0 0';
\r
705 if (trace_ent.crouch == 1) // Damage enemy that's crouching
\r
710 if ((trace_ent.team_no != self.team_no))
\r
712 trace_ent.leg_damage = (trace_ent.leg_damage + 1);
\r
713 // TeamFortress_SetSpeed (trace_ent);
\r
716 /* if ((trace_ent.health > 0))
\r
718 if ((trace_ent.team_no == self.team_no))
\r
720 sprint (self, "Stop shooting team mates!!!\n");
\r
724 sprint (trace_ent, "Leg injury!\n");
\r
725 sprint (self, "Leg shot - that'll slow him down!\n");
\r
734 stuffcmd (trace_ent, "bf\n");
\r
735 if ((trace_ent.health > 0))
\r
737 /*if ((trace_ent.team_no == self.team_no))
\r
739 sprint (self, "Stop shooting team mates!!!\n");
\r
743 trace_ent.head_shot_vector = (trace_ent.origin - self.origin);
\r
762 else { // Damage standing enemy
\r
767 if ((trace_ent.team_no != self.team_no))
\r
769 //trace_ent.leg_damage = (trace_ent.leg_damage + 1); // no leg dmg?
\r
770 // TeamFortress_SetSpeed (trace_ent);
\r
773 /* if ((trace_ent.health > 0))
\r
775 if ((trace_ent.team_no == self.team_no))
\r
777 sprint (self, "Stop shooting team mates!!!\n");
\r
781 sprint (trace_ent, "Leg injury!\n");
\r
782 sprint (self, "Leg shot - that'll slow him down!\n");
\r
791 stuffcmd (trace_ent, "bf\n");
\r
792 if ((trace_ent.health > 0))
\r
794 /*if ((trace_ent.team_no == self.team_no))
\r
796 sprint (self, "Stop shooting team mates!!!\n");
\r
800 trace_ent.head_shot_vector = (trace_ent.origin - self.origin);
\r
822 void fireBullet2 (vector start, vector dir, float spread, float damage, float dtype, float tracer, float force)
\r
827 local float bdamage;
\r
829 // use traceline_hitcorpse to make sure it can hit gibs and corpses too
\r
830 dir = dir + randomvec() * spread;
\r
831 end = start + dir * 4096;
\r
832 traceline_hitcorpse (self, start, end, FALSE, self);
\r
834 if (dtype == WEP_PISTOL) // if pistol weapon, apply area damage
\r
836 bdamage = FindBodyDamage (self, start, end, FALSE, self);
\r
837 if (bdamage == HEADSHOT)
\r
839 damage = damage * 2.5;
\r
840 dtype = PISTOL_HEADSHOT;
\r
842 else if (bdamage == LEGSHOT)
\r
844 damage = damage * .75;
\r
845 dtype = PISTOL_LEGSHOT;
\r
849 dtype = PISTOL_BODYSHOT;
\r
857 e.movetype = MOVETYPE_FLY;
\r
858 e.solid = SOLID_NOT;
\r
859 e.think = SUB_Remove;
\r
860 e.nextthink = time + vlen(trace_endpos - start) / 6000;
\r
861 if (dtype == WEP_PISTOL) // if pistol, show slower bullet
\r
862 e.velocity = dir * 1750;
\r
864 e.velocity = dir * 6000;
\r
865 e.angles = vectoangles(e.velocity);
\r
866 setmodel (e, "models/tracer.mdl");
\r
867 setsize (e, '0 0 0', '0 0 0');
\r
868 setorigin (e, start);
\r
869 e.effects = e.effects | EF_ADDITIVE;
\r
872 // FIXME - causes excessive 'tinking'. Hopefully remove "tink1.wav" from the ricochets with csqc
\r
873 if ((trace_fraction != 1.0) && (pointcontents (trace_endpos) != CONTENT_SKY))
\r
875 if (trace_ent.solid == SOLID_BSP)
\r
877 pointcontents (self.origin);
\r
878 te_gunshot (trace_endpos);
\r
881 PointSound (trace_endpos, "weapons/ric1.wav", 1, ATTN_NORM);
\r
883 PointSound (trace_endpos, "weapons/ric2.wav", 1, ATTN_NORM);
\r
885 PointSound (trace_endpos, "weapons/ric3.wav", 1, ATTN_NORM);
\r
887 else if (trace_ent.classname == "player" || trace_ent.classname == "corpse" || trace_ent.classname == "gib")
\r
888 sound (self, CHAN_BODY, "misc/hit.wav", 1, ATTN_NORM);
\r
889 Damage (trace_ent, self, self, damage, dtype, trace_endpos, dir * force);
\r
893 void fireBullet (vector start, vector dir, float spread, float damage, float dtype, float tracer)
\r
895 fireBullet2(start, dir, spread, damage, dtype, tracer, damage * 5); // default force value
\r
899 void W_Attack (void)
\r
901 if (self.deadflag != DEAD_NO)
\r
903 if (self.death_time < time)
\r
904 PutClientInServer();
\r
909 if (!W_CheckAmmo ())
\r
912 makevectors (self.v_angle);
\r
913 //if (self.weapon == IT_LASER)
\r
914 // W_Laser_Attack ();
\r
915 //if (self.weapon == IT_SHOTGUN)
\r
916 //W_Shotgun_Attack ();
\r
917 //else if (self.weapon == IT_UZI)
\r
919 if (self.weapon == IT_CRYLINK)
\r
920 W_Crylink_Attack ();
\r
921 else if (self.weapon == IT_ELECTRO)
\r
923 W_Electro_Attack (self.electrocount);
\r
924 self.electrocount = self.electrocount + 1;
\r
925 if (self.electrocount == 3)
\r
926 self.electrocount = 0;
\r
928 else if (self.weapon == IT_GRENADE_LAUNCHER)
\r
929 W_Grenade_Attack ();
\r
930 else if (self.weapon == IT_HAGAR)
\r
932 else if (self.weapon == IT_NEX)
\r
934 //else if (self.weapon == IT_ROCKET_LAUNCHER)
\r
935 // W_Rocket_Attack ();
\r
940 void W_SecondaryAttack (void)
\r
942 if (self.deadflag != DEAD_NO)
\r
944 if (self.death_time < time)
\r
945 PutClientInServer();
\r
950 if (!W_CheckAmmo ())
\r
953 makevectors (self.v_angle);
\r
954 //if (self.weapon == IT_LASER)
\r
955 //W_Laser_Attack2 ();
\r
956 //if (self.weapon == IT_SHOTGUN)
\r
957 //W_Shotgun_Attack2 ();
\r
958 //else if (self.weapon == IT_UZI)
\r
959 //W_Uzi_Attack2 ();
\r
960 else if (self.weapon == IT_CRYLINK)
\r
961 W_Crylink_Attack2 ();
\r
962 else if (self.weapon == IT_ELECTRO) {
\r
963 W_Electro_Attack2 (self.electrocount);
\r
964 self.electrocount = self.electrocount + 1;
\r
965 if (self.electrocount == 3)
\r
966 self.electrocount = 0;
\r
968 else if (self.weapon == IT_GRENADE_LAUNCHER)
\r
969 W_Grenade_Attack2 ();
\r
970 else if (self.weapon == IT_HAGAR)
\r
971 W_Hagar_Attack2 ();
\r
972 else if (self.weapon == IT_NEX)
\r
974 //else if (self.weapon == IT_ROCKET_LAUNCHER)
\r
975 //W_Rocket_Attack2 ();
\r
980 void W_ThirdAttack (void)
\r
982 if (self.deadflag != DEAD_NO)
\r
984 if (self.death_time < time)
\r
985 PutClientInServer();
\r
990 if (!W_CheckAmmo ())
\r
993 makevectors (self.v_angle);
\r
994 //if (self.weapon == IT_LASER)
\r
995 //W_Laser_Attack2 ();
\r
996 //if (self.weapon == IT_SHOTGUN)
\r
997 //W_Shotgun_Attack2 ();
\r
998 //else if (self.weapon == IT_UZI)
\r
999 //W_Uzi_Attack3 ();
\r
1000 else if (self.weapon == IT_CRYLINK)
\r
1001 W_Crylink_Attack2 ();
\r
1002 else if (self.weapon == IT_ELECTRO) {
\r
1003 W_Electro_Attack3 (self.electrocount);
\r
1004 self.electrocount = self.electrocount + 1;
\r
1005 if (self.electrocount == 3)
\r
1006 self.electrocount = 0;
\r
1008 else if (self.weapon == IT_GRENADE_LAUNCHER)
\r
1009 W_Grenade_Attack3 ();
\r
1010 else if (self.weapon == IT_HAGAR)
\r
1011 W_Hagar_Attack3 ();
\r
1012 else if (self.weapon == IT_NEX)
\r
1014 //else if (self.weapon == IT_ROCKET_LAUNCHER)
\r
1015 //W_Rocket_Attack3 ();
\r
1021 float RateFlameDamage(float flametime, float flamedmg, float flamerate)
\r
1023 // return (how much longer flame will last) * (how much to damage per think / how often to think)
\r
1024 return (flametime - time) * (flamedmg / flamerate);
\r
1027 /*void FlamePuffThink()
\r
1029 self.nextthink = time + self.cnt;
\r
1030 self.frame = self.frame + 1;
\r
1031 if(self.frame >= self.count)
\r
1032 self.think = SUB_Remove;
\r
1035 void FlameBurnTarget();
\r
1038 entity CreateFlame(entity targ, entity attacker)
\r
1041 f = targ.onfire = spawn();
\r
1042 f.classname = "burning";
\r
1043 f.owner = attacker;
\r
1048 f.think = FlameBurnTarget;
\r
1049 f.onfire = spawn();
\r
1051 f.effects = f.onfire.effects = EF_ADDITIVE;
\r
1052 f.scale = f.onfire.scale = 2;
\r
1054 setmodel(f, "models/sprites/fire_top.spr32");
\r
1055 setattachment(f, f.enemy, "");
\r
1056 setmodel(f.onfire, "models/sprites/fire_base.spr32");
\r
1058 setorigin(f.onfire, '0 0 -5' * f.scale);
\r
1059 setorigin(f, '0 0 2' * f.scale + '0 0 20');
\r
1060 setattachment(f.onfire, f, "");
\r
1065 entity IgniteTarget (entity targ, entity attacker, float flametime, float flamedmg, float flamerate, float rateflame)
\r
1069 //bprint("ignite targets?\n");
\r
1071 if(targ.class == CLASS_PYRO)
\r
1073 //flametime = flametime / 5; // pyros don't stay on fire for long
\r
1074 return world; // don't set pyros on fire
\r
1077 if(targ.class == CLASS_MEDIC)
\r
1079 //flametime = flametime / 3; // medics don't stay on fire for long
\r
1080 return world; // don't set medics on fire
\r
1086 f = CreateFlame(targ, attacker);
\r
1090 if(f.nextthink <= 0)
\r
1091 f.nextthink = time + flamerate;
\r
1095 // bprint(ftos(f.wait), ", ", ftos(f.dmg), ", ", ftos(f.ltime), "\n");
\r
1096 //bprint(ftos(flametime), ", ", ftos(flamedmg), ", ", ftos(flamerate), "\n");
\r
1097 // bprint(ftos(RateFlameDamage(f.wait, f.dmg, f.ltime)), ", ", ftos(RateFlameDamage(flametime, flamedmg, flamerate)), "\n");
\r
1099 if(rateflame && RateFlameDamage(f.wait, f.dmg, f.ltime) > RateFlameDamage(time + flametime, flamedmg, flamerate))
\r
1101 f.owner = attacker; // give the new attacker ownership of the burn damage
\r
1102 return f; // current damage rating is larger, don't replace it
\r
1105 //bprint("burning success: ", ftos(flametime), "\n");
\r
1108 f.ltime = flamerate;
\r
1109 f.wait = time + flametime;
\r
1111 if(!f.nextthink || f.nextthink > time + f.ltime)
\r
1112 f.nextthink = time + f.ltime;
\r
1117 void ExtinguishFlame(entity targ)
\r
1120 if(!targ.onfire)//targ.onfire.classname != "burning")
\r
1122 //bprint(strcat("ExtinguishFlame(", targ.classname, ") ", targ.onfire.classname, "\n"));
\r
1125 b = targ.onfire.onfire;
\r
1127 // fixme: hiss sound
\r
1131 b.think = SUB_Null;
\r
1133 setmodel(b, "models/sprites/null.spr");
\r
1134 setattachment(b, world, "");
\r
1135 remove(b); // remove base model
\r
1136 //targ.onfire.onfire.think = SUB_Remove;
\r
1137 //targ.onfire.onfire.nextthink = time + 0.1;
\r
1140 f.think = SUB_Null;
\r
1142 setmodel(f, "models/sprites/null.spr");
\r
1143 setattachment(f, world, "");
\r
1144 //targ.onfire.think = SUB_Remove;
\r
1145 //targ.onfire.nextthink = time + 0.1;
\r
1147 targ.onfire = world;
\r
1150 void FlameBurnTarget()
\r
1153 float flametime, flametimemax, radius, flameratio, distratio, edgeratio, damage;
\r
1154 //bprint("flame burn target\n");
\r
1156 if(self.enemy == world || self.enemy.classname == "gib")
\r
1158 if(self.enemy != world)
\r
1160 //bprint("on a gib, remove flame\n");
\r
1161 //self.enemy.onfire = world;
\r
1162 ExtinguishFlame(self.enemy);
\r
1165 //bprint("enemy is world, remove flame\n");
\r
1166 self.think = SUB_Null;
\r
1167 self.nextthink = -1;
\r
1168 setmodel(self, "models/sprites/null.spr");
\r
1169 setattachment(self, world, "");
\r
1172 self.onfire.think = SUB_Null;
\r
1173 self.onfire.nextthink = -1;
\r
1174 setmodel(self.onfire, "models/sprites/null.spr");
\r
1175 setattachment(self.onfire, world, "");
\r
1176 remove(self.onfire);
\r
1177 self.onfire = world;
\r
1183 if(self.wait < time || self.enemy.waterlevel > 2 || (!self.enemy.takedamage && self.enemy.classname != "grenade"))
\r
1185 /*if(self.enemy != world)
\r
1187 self.enemy.effects = self.enemy.effects - (self.enemy.effects & EF_FLAME);
\r
1188 self.enemy.onfire = world;
\r
1191 ExtinguishFlame(self.enemy);
\r
1194 self.nextthink = time + self.ltime;
\r
1196 Damage (self.enemy, self, self.owner, self.dmg, DEATH_BURNING, self.enemy.origin - '0 0 5', '0 0 0');//'0 0 -1' * self.dmg);
\r
1198 // flames spread to other targets
\r
1200 radius = cvar("g_balance_heat_radius");
\r
1201 head = findradius(self.enemy.origin, radius);
\r
1204 if((head.takedamage || head.classname == "grenade") && head != self.enemy)
\r
1206 //bprint(strcat("maybe burn ", head.classname, "\n"));
\r
1207 // don't harm or spread to allies or pyros
\r
1208 //if(!(head.classname == "player" && (head.team == self.owner.team || head.class == CLASS_PYRO)) )
\r
1209 if(head.classname == "player")
\r
1211 if(head.class == CLASS_PYRO || head.class == CLASS_MEDIC) // pyros & medics are mostly immune to fire
\r
1212 { head = head.chain; continue;}
\r
1213 if(head.team == self.owner.team && teamplay) // don't hurt teammates
\r
1214 { head = head.chain; continue;}
\r
1217 traceline(self.enemy.origin, head.origin, TRUE, self);
\r
1218 if(trace_fraction >= 1)
\r
1220 //bprint(strcat("burn ", head.classname, "\n"));
\r
1221 edgeratio = cvar("g_balance_heat_edgeratio");
\r
1222 distratio = ( 1 - (vlen(self.enemy.origin - head.origin) / radius) );
\r
1223 flameratio = edgeratio + distratio*(1 - edgeratio);
\r
1225 // increase the player's heat; if it goes over the max it'll get capped automatically by the cooldown code
\r
1226 //head.flame_heat = cvar("g_balance_maxheat");
\r
1227 head.flame_heat = head.flame_heat + flameratio * cvar("g_balance_heatup_rate") * self.ltime;
\r
1228 //head.flame_heat_time = time;
\r
1230 // deal direct damage from the heat radiated by the fire
\r
1231 damage = flameratio * self.dmg*cvar("g_balance_heat_damage");
\r
1232 Damage (head, self, self.owner, damage, DEATH_BURNING, self.enemy.origin, '0 0 0');
\r
1234 if(head.flame_heat >= 1.0 && head.takedamage == DAMAGE_AIM && head.health > 0)
\r
1236 flametimemax = cvar("g_balance_heat_timemax");
\r
1237 flametime = (self.wait - time) * cvar("g_balance_heat_transfer");
\r
1238 if(flametime > flametimemax)
\r
1239 flametime = flametimemax;
\r
1242 //bprint(ftos(time), " - flame transfer - ", ftos(flametime), "\n");
\r
1245 IgniteTarget(head, self.owner, flametime, self.dmg, self.ltime, TRUE);
\r
1249 head = head.chain;
\r
1254 void PoisonTarget(entity targ, float poisonDamage, float poisonTime, float ratepoison)
\r
1256 if(targ.class == CLASS_MEDIC)
\r
1258 return; // don't poison medics
\r
1261 if(ratepoison && targ.poison_damage > poisonDamage)
\r
1262 return; // current damage rating is larger, don't replace it
\r
1264 targ.poison_damage = poisonDamage;
\r
1265 targ.poison_rate = poisonDamage / poisonTime;
\r
1278 float W_LimitNumEnts(string clname, float num_allowed, void() DeathFunc)
\r
1280 float num, oldest;
\r
1281 local entity e, selected;
\r
1283 oldest = time + 1;
\r
1287 e = find(e, classname, clname);
\r
1288 if(e != world && e.owner == self)
\r
1291 if(e.create_time < oldest)
\r
1294 oldest = e.create_time;
\r
1299 if(num > num_allowed)
\r
1301 if(selected != world)
\r
1310 bprint("error (W_LimitNumEnts): cannot find oldest entity\n");
\r