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
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
517 bdamage = floor(bdamage * 15.5);
\r
519 bdamage = floor(bdamage * 2.5);
\r
520 sound (self, 0, "speech/excelent.wav", 1, 0);
\r
530 else { // Damage standing enemy
\r
534 if ((trace_ent.team_no != self.team_no))
\r
536 trace_ent.leg_damage = (trace_ent.leg_damage + 1);
\r
537 TeamFortress_SetSpeed (trace_ent);
\r
539 bdamage = bdamage * .8;
\r
540 //T_Damage (trace_ent, self, self, (self.heat * dam_mult));
\r
542 if ((trace_ent.health > 0))
\r
544 if ((trace_ent.team_no == self.team_no))
\r
546 sprint (self, "Stop shooting team mates!!!\n");
\r
550 sprint (trace_ent, "Leg injury!\n");
\r
551 sprint (self, "Leg shot - that'll slow him down!\n");
\r
561 stuffcmd (trace_ent, "bf\n");
\r
563 if ((trace_ent.health > 0))
\r
565 if ((trace_ent.team_no == self.team_no))
\r
567 sprint (self, "Stop shooting team mates!!!\n");
\r
571 trace_ent.head_shot_vector = (trace_ent.origin - self.origin);
\r
573 // bdamage = floor(bdamage * 3.5);
\r
575 bdamage = floor(bdamage * 15.5);
\r
577 bdamage = floor(bdamage * 2.5);
\r
578 // T_Damage (trace_ent, self, self, (self.heat * dam_mult));
\r
579 sound (self, 0, "speech/excelent.wav", 1, 0);
\r
580 // if ((trace_ent.health > 0))
\r
582 // sprint (trace_ent, 0, "Head injury!\n");
\r
583 // sprint (self, 1, "Head shot - that's gotta hurt!\n");
\r
598 // trace multiple times until we hit a wall, each obstacle will be made
\r
599 // non-solid so we can hit the next, while doing this we spawn effects and
\r
600 // note down which entities were hit so we can damage them later
\r
603 traceline_hitcorpse (self, start, end, FALSE, self);
\r
605 // if it is world we can't hurt it so stop now
\r
606 if (trace_ent == world || trace_fraction == 1)
\r
609 // make the entity non-solid so we can hit the next one
\r
610 trace_ent.railgunhit = TRUE;
\r
611 trace_ent.railgunhitloc = trace_endpos;
\r
612 trace_ent.railgunhitsolidbackup = trace_ent.solid;
\r
614 // stop if this is a wall
\r
615 if (trace_ent.solid == SOLID_BSP)
\r
618 // make the entity non-solid
\r
619 trace_ent.solid = SOLID_NOT;
\r
622 // find all the entities the railgun hit and restore their solid state
\r
623 ent = findfloat(world, railgunhit, TRUE);
\r
626 // restore their solid type
\r
627 ent.solid = ent.railgunhitsolidbackup;
\r
628 ent = findfloat(ent, railgunhit, TRUE);
\r
631 // spawn a temporary explosion entity for RadiusDamage calls
\r
632 //explosion = spawn();
\r
634 // find all the entities the railgun hit and hurt them
\r
635 ent = findfloat(world, railgunhit, TRUE);
\r
638 // get the details we need to call the damage function
\r
639 hitloc = ent.railgunhitloc;
\r
640 ent.railgunhitloc = '0 0 0';
\r
641 ent.railgunhitsolidbackup = SOLID_NOT;
\r
642 ent.railgunhit = FALSE;
\r
644 // apply the damage
\r
645 if (ent.takedamage || ent.classname == "case")
\r
646 Damage (ent, self, self, bdamage, deathtype, hitloc, force);
\r
648 // create a small explosion to throw gibs around (if applicable)
\r
649 //setorigin (explosion, hitloc);
\r
650 //RadiusDamage (explosion, self, 10, 0, 50, world, 300, deathtype);
\r
652 // advance to the next entity
\r
653 ent = findfloat(ent, railgunhit, TRUE);
\r
656 // we're done with the explosion entity, remove it
\r
657 //remove(explosion);
\r
660 void fireBullet2 (vector start, vector dir, float spread, float damage, float dtype, float tracer, float force)
\r
666 // use traceline_hitcorpse to make sure it can hit gibs and corpses too
\r
667 dir = dir + randomvec() * spread;
\r
668 end = start + dir * 4096;
\r
669 traceline_hitcorpse (self, start, end, FALSE, self);
\r
675 e.movetype = MOVETYPE_FLY;
\r
676 e.solid = SOLID_NOT;
\r
677 e.think = SUB_Remove;
\r
678 e.nextthink = time + vlen(trace_endpos - start) / 6000;
\r
679 if (dtype == WEP_PISTOL) // if pistol, show slower bullet
\r
680 e.velocity = dir * 1750;
\r
682 e.velocity = dir * 6000;
\r
683 e.angles = vectoangles(e.velocity);
\r
684 setmodel (e, "models/tracer.mdl");
\r
685 setsize (e, '0 0 0', '0 0 0');
\r
686 setorigin (e, start);
\r
687 e.effects = e.effects | EF_ADDITIVE;
\r
690 // FIXME - causes excessive 'tinking'. Hopefully remove "tink1.wav" from the ricochets with csqc
\r
691 if ((trace_fraction != 1.0) && (pointcontents (trace_endpos) != CONTENT_SKY))
\r
693 if (trace_ent.solid == SOLID_BSP)
\r
695 pointcontents (self.origin);
\r
696 te_gunshot (trace_endpos);
\r
699 PointSound (trace_endpos, "weapons/ric1.wav", 1, ATTN_NORM);
\r
701 PointSound (trace_endpos, "weapons/ric2.wav", 1, ATTN_NORM);
\r
703 PointSound (trace_endpos, "weapons/ric3.wav", 1, ATTN_NORM);
\r
705 else if (trace_ent.classname == "player" || trace_ent.classname == "corpse" || trace_ent.classname == "gib")
\r
706 sound (self, CHAN_BODY, "misc/hit.wav", 1, ATTN_NORM);
\r
707 Damage (trace_ent, self, self, damage, dtype, trace_endpos, dir * force);
\r
711 void fireBullet (vector start, vector dir, float spread, float damage, float dtype, float tracer)
\r
713 fireBullet2(start, dir, spread, damage, dtype, tracer, damage * 5); // default force value
\r
717 void W_Attack (void)
\r
719 if (self.deadflag != DEAD_NO)
\r
721 if (self.death_time < time)
\r
722 PutClientInServer();
\r
727 if (!W_CheckAmmo ())
\r
730 makevectors (self.v_angle);
\r
731 //if (self.weapon == IT_LASER)
\r
732 // W_Laser_Attack ();
\r
733 //if (self.weapon == IT_SHOTGUN)
\r
734 //W_Shotgun_Attack ();
\r
735 //else if (self.weapon == IT_UZI)
\r
737 if (self.weapon == IT_CRYLINK)
\r
738 W_Crylink_Attack ();
\r
739 else if (self.weapon == IT_ELECTRO)
\r
741 W_Electro_Attack (self.electrocount);
\r
742 self.electrocount = self.electrocount + 1;
\r
743 if (self.electrocount == 3)
\r
744 self.electrocount = 0;
\r
746 else if (self.weapon == IT_GRENADE_LAUNCHER)
\r
747 W_Grenade_Attack ();
\r
748 else if (self.weapon == IT_HAGAR)
\r
750 else if (self.weapon == IT_NEX)
\r
752 //else if (self.weapon == IT_ROCKET_LAUNCHER)
\r
753 // W_Rocket_Attack ();
\r
758 void W_SecondaryAttack (void)
\r
760 if (self.deadflag != DEAD_NO)
\r
762 if (self.death_time < time)
\r
763 PutClientInServer();
\r
768 if (!W_CheckAmmo ())
\r
771 makevectors (self.v_angle);
\r
772 //if (self.weapon == IT_LASER)
\r
773 //W_Laser_Attack2 ();
\r
774 //if (self.weapon == IT_SHOTGUN)
\r
775 //W_Shotgun_Attack2 ();
\r
776 //else if (self.weapon == IT_UZI)
\r
777 //W_Uzi_Attack2 ();
\r
778 else if (self.weapon == IT_CRYLINK)
\r
779 W_Crylink_Attack2 ();
\r
780 else if (self.weapon == IT_ELECTRO) {
\r
781 W_Electro_Attack2 (self.electrocount);
\r
782 self.electrocount = self.electrocount + 1;
\r
783 if (self.electrocount == 3)
\r
784 self.electrocount = 0;
\r
786 else if (self.weapon == IT_GRENADE_LAUNCHER)
\r
787 W_Grenade_Attack2 ();
\r
788 else if (self.weapon == IT_HAGAR)
\r
789 W_Hagar_Attack2 ();
\r
790 else if (self.weapon == IT_NEX)
\r
792 //else if (self.weapon == IT_ROCKET_LAUNCHER)
\r
793 //W_Rocket_Attack2 ();
\r
798 void W_ThirdAttack (void)
\r
800 if (self.deadflag != DEAD_NO)
\r
802 if (self.death_time < time)
\r
803 PutClientInServer();
\r
808 if (!W_CheckAmmo ())
\r
811 makevectors (self.v_angle);
\r
812 //if (self.weapon == IT_LASER)
\r
813 //W_Laser_Attack2 ();
\r
814 //if (self.weapon == IT_SHOTGUN)
\r
815 //W_Shotgun_Attack2 ();
\r
816 //else if (self.weapon == IT_UZI)
\r
817 //W_Uzi_Attack3 ();
\r
818 else if (self.weapon == IT_CRYLINK)
\r
819 W_Crylink_Attack2 ();
\r
820 else if (self.weapon == IT_ELECTRO) {
\r
821 W_Electro_Attack3 (self.electrocount);
\r
822 self.electrocount = self.electrocount + 1;
\r
823 if (self.electrocount == 3)
\r
824 self.electrocount = 0;
\r
826 else if (self.weapon == IT_GRENADE_LAUNCHER)
\r
827 W_Grenade_Attack3 ();
\r
828 else if (self.weapon == IT_HAGAR)
\r
829 W_Hagar_Attack3 ();
\r
830 else if (self.weapon == IT_NEX)
\r
832 //else if (self.weapon == IT_ROCKET_LAUNCHER)
\r
833 //W_Rocket_Attack3 ();
\r
839 float RateFlameDamage(float flametime, float flamedmg, float flamerate)
\r
841 // return (how much longer flame will last) * (how much to damage per think / how often to think)
\r
842 return (flametime - time) * (flamedmg / flamerate);
\r
845 /*void FlamePuffThink()
\r
847 self.nextthink = time + self.cnt;
\r
848 self.frame = self.frame + 1;
\r
849 if(self.frame >= self.count)
\r
850 self.think = SUB_Remove;
\r
853 void FlameBurnTarget();
\r
856 entity CreateFlame(entity targ, entity attacker)
\r
859 f = targ.onfire = spawn();
\r
860 f.classname = "burning";
\r
861 f.owner = attacker;
\r
866 f.think = FlameBurnTarget;
\r
867 f.onfire = spawn();
\r
869 f.effects = f.onfire.effects = EF_ADDITIVE;
\r
870 f.scale = f.onfire.scale = 2;
\r
872 setmodel(f, "models/sprites/fire_top.spr32");
\r
873 setattachment(f, f.enemy, "");
\r
874 setmodel(f.onfire, "models/sprites/fire_base.spr32");
\r
876 setorigin(f.onfire, '0 0 -5' * f.scale);
\r
877 setorigin(f, '0 0 2' * f.scale + '0 0 20');
\r
878 setattachment(f.onfire, f, "");
\r
883 entity IgniteTarget (entity targ, entity attacker, float flametime, float flamedmg, float flamerate, float rateflame)
\r
887 //bprint("ignite targets?\n");
\r
889 if(targ.class == CLASS_PYRO)
\r
891 //flametime = flametime / 5; // pyros don't stay on fire for long
\r
892 return world; // don't set pyros on fire
\r
895 if(targ.class == CLASS_MEDIC)
\r
897 //flametime = flametime / 3; // medics don't stay on fire for long
\r
898 return world; // don't set medics on fire
\r
904 f = CreateFlame(targ, attacker);
\r
908 if(f.nextthink <= 0)
\r
909 f.nextthink = time + flamerate;
\r
913 // bprint(ftos(f.wait), ", ", ftos(f.dmg), ", ", ftos(f.ltime), "\n");
\r
914 //bprint(ftos(flametime), ", ", ftos(flamedmg), ", ", ftos(flamerate), "\n");
\r
915 // bprint(ftos(RateFlameDamage(f.wait, f.dmg, f.ltime)), ", ", ftos(RateFlameDamage(flametime, flamedmg, flamerate)), "\n");
\r
917 if(rateflame && RateFlameDamage(f.wait, f.dmg, f.ltime) > RateFlameDamage(time + flametime, flamedmg, flamerate))
\r
919 f.owner = attacker; // give the new attacker ownership of the burn damage
\r
920 return f; // current damage rating is larger, don't replace it
\r
923 //bprint("burning success: ", ftos(flametime), "\n");
\r
926 f.ltime = flamerate;
\r
927 f.wait = time + flametime;
\r
929 if(!f.nextthink || f.nextthink > time + f.ltime)
\r
930 f.nextthink = time + f.ltime;
\r
935 void ExtinguishFlame(entity targ)
\r
938 if(!targ.onfire)//targ.onfire.classname != "burning")
\r
940 //bprint(strcat("ExtinguishFlame(", targ.classname, ") ", targ.onfire.classname, "\n"));
\r
943 b = targ.onfire.onfire;
\r
945 // fixme: hiss sound
\r
949 b.think = SUB_Null;
\r
951 setmodel(b, "models/sprites/null.spr");
\r
952 setattachment(b, world, "");
\r
953 remove(b); // remove base model
\r
954 //targ.onfire.onfire.think = SUB_Remove;
\r
955 //targ.onfire.onfire.nextthink = time + 0.1;
\r
958 f.think = SUB_Null;
\r
960 setmodel(f, "models/sprites/null.spr");
\r
961 setattachment(f, world, "");
\r
962 //targ.onfire.think = SUB_Remove;
\r
963 //targ.onfire.nextthink = time + 0.1;
\r
965 targ.onfire = world;
\r
968 void FlameBurnTarget()
\r
971 float flametime, flametimemax, radius, flameratio, distratio, edgeratio, damage;
\r
972 //bprint("flame burn target\n");
\r
974 if(self.enemy == world || self.enemy.classname == "gib")
\r
976 if(self.enemy != world)
\r
978 //bprint("on a gib, remove flame\n");
\r
979 //self.enemy.onfire = world;
\r
980 ExtinguishFlame(self.enemy);
\r
983 //bprint("enemy is world, remove flame\n");
\r
984 self.think = SUB_Null;
\r
985 self.nextthink = -1;
\r
986 setmodel(self, "models/sprites/null.spr");
\r
987 setattachment(self, world, "");
\r
990 self.onfire.think = SUB_Null;
\r
991 self.onfire.nextthink = -1;
\r
992 setmodel(self.onfire, "models/sprites/null.spr");
\r
993 setattachment(self.onfire, world, "");
\r
994 remove(self.onfire);
\r
995 self.onfire = world;
\r
1001 if(self.wait < time || self.enemy.waterlevel > 2 || (!self.enemy.takedamage && self.enemy.classname != "grenade"))
\r
1003 /*if(self.enemy != world)
\r
1005 self.enemy.effects = self.enemy.effects - (self.enemy.effects & EF_FLAME);
\r
1006 self.enemy.onfire = world;
\r
1009 ExtinguishFlame(self.enemy);
\r
1012 self.nextthink = time + self.ltime;
\r
1014 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
1016 // flames spread to other targets
\r
1018 radius = cvar("g_balance_heat_radius");
\r
1019 head = findradius(self.enemy.origin, radius);
\r
1022 if((head.takedamage || head.classname == "grenade") && head != self.enemy)
\r
1024 //bprint(strcat("maybe burn ", head.classname, "\n"));
\r
1025 // don't harm or spread to allies or pyros
\r
1026 //if(!(head.classname == "player" && (head.team == self.owner.team || head.class == CLASS_PYRO)) )
\r
1027 if(head.classname == "player")
\r
1029 if(head.class == CLASS_PYRO || head.class == CLASS_MEDIC) // pyros & medics are mostly immune to fire
\r
1030 { head = head.chain; continue;}
\r
1031 if(head.team == self.owner.team && teamplay) // don't hurt teammates
\r
1032 { head = head.chain; continue;}
\r
1035 traceline(self.enemy.origin, head.origin, TRUE, self);
\r
1036 if(trace_fraction >= 1)
\r
1038 //bprint(strcat("burn ", head.classname, "\n"));
\r
1039 edgeratio = cvar("g_balance_heat_edgeratio");
\r
1040 distratio = ( 1 - (vlen(self.enemy.origin - head.origin) / radius) );
\r
1041 flameratio = edgeratio + distratio*(1 - edgeratio);
\r
1043 // increase the player's heat; if it goes over the max it'll get capped automatically by the cooldown code
\r
1044 //head.flame_heat = cvar("g_balance_maxheat");
\r
1045 head.flame_heat = head.flame_heat + flameratio * cvar("g_balance_heatup_rate") * self.ltime;
\r
1046 //head.flame_heat_time = time;
\r
1048 // deal direct damage from the heat radiated by the fire
\r
1049 damage = flameratio * self.dmg*cvar("g_balance_heat_damage");
\r
1050 Damage (head, self, self.owner, damage, DEATH_BURNING, self.enemy.origin, '0 0 0');
\r
1052 if(head.flame_heat >= 1.0 && head.takedamage == DAMAGE_AIM && head.health > 0)
\r
1054 flametimemax = cvar("g_balance_heat_timemax");
\r
1055 flametime = (self.wait - time) * cvar("g_balance_heat_transfer");
\r
1056 if(flametime > flametimemax)
\r
1057 flametime = flametimemax;
\r
1060 //bprint(ftos(time), " - flame transfer - ", ftos(flametime), "\n");
\r
1063 IgniteTarget(head, self.owner, flametime, self.dmg, self.ltime, TRUE);
\r
1067 head = head.chain;
\r
1072 void PoisonTarget(entity targ, float poisonDamage, float poisonTime, float ratepoison)
\r
1074 if(targ.class == CLASS_MEDIC)
\r
1076 return; // don't poison medics
\r
1079 if(ratepoison && targ.poison_damage > poisonDamage)
\r
1080 return; // current damage rating is larger, don't replace it
\r
1082 targ.poison_damage = poisonDamage;
\r
1083 targ.poison_rate = poisonDamage / poisonTime;
\r
1096 float W_LimitNumEnts(string clname, float num_allowed, void() DeathFunc)
\r
1098 float num, oldest;
\r
1099 local entity e, selected;
\r
1101 oldest = time + 1;
\r
1105 e = find(e, classname, clname);
\r
1106 if(e != world && e.owner == self)
\r
1109 if(e.create_time < oldest)
\r
1112 oldest = e.create_time;
\r
1117 if(num > num_allowed)
\r
1119 if(selected != world)
\r
1128 bprint("error (W_LimitNumEnts): cannot find oldest entity\n");
\r