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
477 if ((trace_ent.team_no != self.team_no))
\r
479 trace_ent.leg_damage = (trace_ent.leg_damage + 1);
\r
480 TeamFortress_SetSpeed (trace_ent);
\r
482 bdamage = bdamage * .8;
\r
483 //T_Damage (trace_ent, self, self, (self.heat * dam_mult));
\r
485 if ((trace_ent.health > 0))
\r
487 if ((trace_ent.team_no == self.team_no))
\r
489 sprint (self, "Stop shooting team mates!!!\n");
\r
493 sprint (trace_ent, "Leg injury!\n");
\r
494 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
516 // bdamage = floor(bdamage * 3.5);
\r
518 bdamage = floor(bdamage * 15.5);
\r
520 bdamage = floor(bdamage * 2.5);
\r
521 // T_Damage (trace_ent, self, self, (self.heat * dam_mult));
\r
522 sound (self, 0, "speech/excelent.wav", 1, 0);
\r
523 // if ((trace_ent.health > 0))
\r
525 // sprint (trace_ent, 0, "Head injury!\n");
\r
526 // sprint (self, 1, "Head shot - that's gotta hurt!\n");
\r
540 // trace multiple times until we hit a wall, each obstacle will be made
\r
541 // non-solid so we can hit the next, while doing this we spawn effects and
\r
542 // note down which entities were hit so we can damage them later
\r
545 traceline_hitcorpse (self, start, end, FALSE, self);
\r
547 // if it is world we can't hurt it so stop now
\r
548 if (trace_ent == world || trace_fraction == 1)
\r
551 // make the entity non-solid so we can hit the next one
\r
552 trace_ent.railgunhit = TRUE;
\r
553 trace_ent.railgunhitloc = trace_endpos;
\r
554 trace_ent.railgunhitsolidbackup = trace_ent.solid;
\r
556 // stop if this is a wall
\r
557 if (trace_ent.solid == SOLID_BSP)
\r
560 // make the entity non-solid
\r
561 trace_ent.solid = SOLID_NOT;
\r
564 // find all the entities the railgun hit and restore their solid state
\r
565 ent = findfloat(world, railgunhit, TRUE);
\r
568 // restore their solid type
\r
569 ent.solid = ent.railgunhitsolidbackup;
\r
570 ent = findfloat(ent, railgunhit, TRUE);
\r
573 // spawn a temporary explosion entity for RadiusDamage calls
\r
574 //explosion = spawn();
\r
576 // find all the entities the railgun hit and hurt them
\r
577 ent = findfloat(world, railgunhit, TRUE);
\r
580 // get the details we need to call the damage function
\r
581 hitloc = ent.railgunhitloc;
\r
582 ent.railgunhitloc = '0 0 0';
\r
583 ent.railgunhitsolidbackup = SOLID_NOT;
\r
584 ent.railgunhit = FALSE;
\r
586 // apply the damage
\r
587 if (ent.takedamage || ent.classname == "case")
\r
588 Damage (ent, self, self, bdamage, deathtype, hitloc, force);
\r
590 // create a small explosion to throw gibs around (if applicable)
\r
591 //setorigin (explosion, hitloc);
\r
592 //RadiusDamage (explosion, self, 10, 0, 50, world, 300, deathtype);
\r
594 // advance to the next entity
\r
595 ent = findfloat(ent, railgunhit, TRUE);
\r
598 // we're done with the explosion entity, remove it
\r
599 //remove(explosion);
\r
602 void fireBullet2 (vector start, vector dir, float spread, float damage, float dtype, float tracer, float force)
\r
608 // use traceline_hitcorpse to make sure it can hit gibs and corpses too
\r
609 dir = dir + randomvec() * spread;
\r
610 end = start + dir * 4096;
\r
611 traceline_hitcorpse (self, start, end, FALSE, self);
\r
617 e.movetype = MOVETYPE_FLY;
\r
618 e.solid = SOLID_NOT;
\r
619 e.think = SUB_Remove;
\r
620 e.nextthink = time + vlen(trace_endpos - start) / 6000;
\r
621 e.velocity = dir * 6000;
\r
622 e.angles = vectoangles(e.velocity);
\r
623 setmodel (e, "models/tracer.mdl");
\r
624 setsize (e, '0 0 0', '0 0 0');
\r
625 setorigin (e, start);
\r
626 e.effects = e.effects | EF_ADDITIVE;
\r
629 // FIXME - causes excessive 'tinking'. Hopefully remove "tink1.wav" from the ricochets with csqc
\r
630 if ((trace_fraction != 1.0) && (pointcontents (trace_endpos) != CONTENT_SKY))
\r
632 if (trace_ent.solid == SOLID_BSP)
\r
634 pointcontents (self.origin);
\r
635 te_gunshot (trace_endpos);
\r
638 PointSound (trace_endpos, "weapons/ric1.wav", 1, ATTN_NORM);
\r
640 PointSound (trace_endpos, "weapons/ric2.wav", 1, ATTN_NORM);
\r
642 PointSound (trace_endpos, "weapons/ric3.wav", 1, ATTN_NORM);
\r
644 else if (trace_ent.classname == "player" || trace_ent.classname == "corpse" || trace_ent.classname == "gib")
\r
645 sound (self, CHAN_BODY, "misc/hit.wav", 1, ATTN_NORM);
\r
646 Damage (trace_ent, self, self, damage, dtype, trace_endpos, dir * force);
\r
650 void fireBullet (vector start, vector dir, float spread, float damage, float dtype, float tracer)
\r
652 fireBullet2(start, dir, spread, damage, dtype, tracer, damage * 5); // default force value
\r
656 void W_Attack (void)
\r
658 if (self.deadflag != DEAD_NO)
\r
660 if (self.death_time < time)
\r
661 PutClientInServer();
\r
666 if (!W_CheckAmmo ())
\r
669 makevectors (self.v_angle);
\r
670 //if (self.weapon == IT_LASER)
\r
671 // W_Laser_Attack ();
\r
672 //if (self.weapon == IT_SHOTGUN)
\r
673 //W_Shotgun_Attack ();
\r
674 //else if (self.weapon == IT_UZI)
\r
676 if (self.weapon == IT_CRYLINK)
\r
677 W_Crylink_Attack ();
\r
678 else if (self.weapon == IT_ELECTRO)
\r
680 W_Electro_Attack (self.electrocount);
\r
681 self.electrocount = self.electrocount + 1;
\r
682 if (self.electrocount == 3)
\r
683 self.electrocount = 0;
\r
685 else if (self.weapon == IT_GRENADE_LAUNCHER)
\r
686 W_Grenade_Attack ();
\r
687 else if (self.weapon == IT_HAGAR)
\r
689 else if (self.weapon == IT_NEX)
\r
691 //else if (self.weapon == IT_ROCKET_LAUNCHER)
\r
692 // W_Rocket_Attack ();
\r
697 void W_SecondaryAttack (void)
\r
699 if (self.deadflag != DEAD_NO)
\r
701 if (self.death_time < time)
\r
702 PutClientInServer();
\r
707 if (!W_CheckAmmo ())
\r
710 makevectors (self.v_angle);
\r
711 //if (self.weapon == IT_LASER)
\r
712 //W_Laser_Attack2 ();
\r
713 //if (self.weapon == IT_SHOTGUN)
\r
714 //W_Shotgun_Attack2 ();
\r
715 //else if (self.weapon == IT_UZI)
\r
716 //W_Uzi_Attack2 ();
\r
717 else if (self.weapon == IT_CRYLINK)
\r
718 W_Crylink_Attack2 ();
\r
719 else if (self.weapon == IT_ELECTRO) {
\r
720 W_Electro_Attack2 (self.electrocount);
\r
721 self.electrocount = self.electrocount + 1;
\r
722 if (self.electrocount == 3)
\r
723 self.electrocount = 0;
\r
725 else if (self.weapon == IT_GRENADE_LAUNCHER)
\r
726 W_Grenade_Attack2 ();
\r
727 else if (self.weapon == IT_HAGAR)
\r
728 W_Hagar_Attack2 ();
\r
729 else if (self.weapon == IT_NEX)
\r
731 //else if (self.weapon == IT_ROCKET_LAUNCHER)
\r
732 //W_Rocket_Attack2 ();
\r
737 void W_ThirdAttack (void)
\r
739 if (self.deadflag != DEAD_NO)
\r
741 if (self.death_time < time)
\r
742 PutClientInServer();
\r
747 if (!W_CheckAmmo ())
\r
750 makevectors (self.v_angle);
\r
751 //if (self.weapon == IT_LASER)
\r
752 //W_Laser_Attack2 ();
\r
753 //if (self.weapon == IT_SHOTGUN)
\r
754 //W_Shotgun_Attack2 ();
\r
755 //else if (self.weapon == IT_UZI)
\r
756 //W_Uzi_Attack3 ();
\r
757 else if (self.weapon == IT_CRYLINK)
\r
758 W_Crylink_Attack2 ();
\r
759 else if (self.weapon == IT_ELECTRO) {
\r
760 W_Electro_Attack3 (self.electrocount);
\r
761 self.electrocount = self.electrocount + 1;
\r
762 if (self.electrocount == 3)
\r
763 self.electrocount = 0;
\r
765 else if (self.weapon == IT_GRENADE_LAUNCHER)
\r
766 W_Grenade_Attack3 ();
\r
767 else if (self.weapon == IT_HAGAR)
\r
768 W_Hagar_Attack3 ();
\r
769 else if (self.weapon == IT_NEX)
\r
771 //else if (self.weapon == IT_ROCKET_LAUNCHER)
\r
772 //W_Rocket_Attack3 ();
\r
778 float RateFlameDamage(float flametime, float flamedmg, float flamerate)
\r
780 // return (how much longer flame will last) * (how much to damage per think / how often to think)
\r
781 return (flametime - time) * (flamedmg / flamerate);
\r
784 /*void FlamePuffThink()
\r
786 self.nextthink = time + self.cnt;
\r
787 self.frame = self.frame + 1;
\r
788 if(self.frame >= self.count)
\r
789 self.think = SUB_Remove;
\r
792 void FlameBurnTarget();
\r
795 entity CreateFlame(entity targ, entity attacker)
\r
798 f = targ.onfire = spawn();
\r
799 f.classname = "burning";
\r
800 f.owner = attacker;
\r
805 f.think = FlameBurnTarget;
\r
806 f.onfire = spawn();
\r
808 f.effects = f.onfire.effects = EF_ADDITIVE;
\r
809 f.scale = f.onfire.scale = 2;
\r
811 setmodel(f, "models/sprites/fire_top.spr32");
\r
812 setattachment(f, f.enemy, "");
\r
813 setmodel(f.onfire, "models/sprites/fire_base.spr32");
\r
815 setorigin(f.onfire, '0 0 -5' * f.scale);
\r
816 setorigin(f, '0 0 2' * f.scale + '0 0 20');
\r
817 setattachment(f.onfire, f, "");
\r
822 entity IgniteTarget (entity targ, entity attacker, float flametime, float flamedmg, float flamerate, float rateflame)
\r
826 //bprint("ignite targets?\n");
\r
828 if(targ.class == CLASS_PYRO)
\r
830 //flametime = flametime / 5; // pyros don't stay on fire for long
\r
831 return world; // don't set pyros on fire
\r
834 if(targ.class == CLASS_MEDIC)
\r
836 //flametime = flametime / 3; // medics don't stay on fire for long
\r
837 return world; // don't set medics on fire
\r
843 f = CreateFlame(targ, attacker);
\r
847 if(f.nextthink <= 0)
\r
848 f.nextthink = time + flamerate;
\r
852 // bprint(ftos(f.wait), ", ", ftos(f.dmg), ", ", ftos(f.ltime), "\n");
\r
853 //bprint(ftos(flametime), ", ", ftos(flamedmg), ", ", ftos(flamerate), "\n");
\r
854 // bprint(ftos(RateFlameDamage(f.wait, f.dmg, f.ltime)), ", ", ftos(RateFlameDamage(flametime, flamedmg, flamerate)), "\n");
\r
856 if(rateflame && RateFlameDamage(f.wait, f.dmg, f.ltime) > RateFlameDamage(time + flametime, flamedmg, flamerate))
\r
858 f.owner = attacker; // give the new attacker ownership of the burn damage
\r
859 return f; // current damage rating is larger, don't replace it
\r
862 //bprint("burning success: ", ftos(flametime), "\n");
\r
865 f.ltime = flamerate;
\r
866 f.wait = time + flametime;
\r
868 if(!f.nextthink || f.nextthink > time + f.ltime)
\r
869 f.nextthink = time + f.ltime;
\r
874 void ExtinguishFlame(entity targ)
\r
877 if(!targ.onfire)//targ.onfire.classname != "burning")
\r
879 //bprint(strcat("ExtinguishFlame(", targ.classname, ") ", targ.onfire.classname, "\n"));
\r
882 b = targ.onfire.onfire;
\r
884 // fixme: hiss sound
\r
888 b.think = SUB_Null;
\r
890 setmodel(b, "models/sprites/null.spr");
\r
891 setattachment(b, world, "");
\r
892 remove(b); // remove base model
\r
893 //targ.onfire.onfire.think = SUB_Remove;
\r
894 //targ.onfire.onfire.nextthink = time + 0.1;
\r
897 f.think = SUB_Null;
\r
899 setmodel(f, "models/sprites/null.spr");
\r
900 setattachment(f, world, "");
\r
901 //targ.onfire.think = SUB_Remove;
\r
902 //targ.onfire.nextthink = time + 0.1;
\r
904 targ.onfire = world;
\r
907 void FlameBurnTarget()
\r
910 float flametime, flametimemax, radius, flameratio, distratio, edgeratio, damage;
\r
911 //bprint("flame burn target\n");
\r
913 if(self.enemy == world || self.enemy.classname == "gib")
\r
915 if(self.enemy != world)
\r
917 //bprint("on a gib, remove flame\n");
\r
918 //self.enemy.onfire = world;
\r
919 ExtinguishFlame(self.enemy);
\r
922 //bprint("enemy is world, remove flame\n");
\r
923 self.think = SUB_Null;
\r
924 self.nextthink = -1;
\r
925 setmodel(self, "models/sprites/null.spr");
\r
926 setattachment(self, world, "");
\r
929 self.onfire.think = SUB_Null;
\r
930 self.onfire.nextthink = -1;
\r
931 setmodel(self.onfire, "models/sprites/null.spr");
\r
932 setattachment(self.onfire, world, "");
\r
933 remove(self.onfire);
\r
934 self.onfire = world;
\r
940 if(self.wait < time || self.enemy.waterlevel > 2 || (!self.enemy.takedamage && self.enemy.classname != "grenade"))
\r
942 /*if(self.enemy != world)
\r
944 self.enemy.effects = self.enemy.effects - (self.enemy.effects & EF_FLAME);
\r
945 self.enemy.onfire = world;
\r
948 ExtinguishFlame(self.enemy);
\r
951 self.nextthink = time + self.ltime;
\r
953 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
955 // flames spread to other targets
\r
957 radius = cvar("g_balance_heat_radius");
\r
958 head = findradius(self.enemy.origin, radius);
\r
961 if((head.takedamage || head.classname == "grenade") && head != self.enemy)
\r
963 //bprint(strcat("maybe burn ", head.classname, "\n"));
\r
964 // don't harm or spread to allies or pyros
\r
965 //if(!(head.classname == "player" && (head.team == self.owner.team || head.class == CLASS_PYRO)) )
\r
966 if(head.classname == "player")
\r
968 if(head.class == CLASS_PYRO || head.class == CLASS_MEDIC) // pyros & medics are mostly immune to fire
\r
969 { head = head.chain; continue;}
\r
970 if(head.team == self.owner.team && teamplay) // don't hurt teammates
\r
971 { head = head.chain; continue;}
\r
974 traceline(self.enemy.origin, head.origin, TRUE, self);
\r
975 if(trace_fraction >= 1)
\r
977 //bprint(strcat("burn ", head.classname, "\n"));
\r
978 edgeratio = cvar("g_balance_heat_edgeratio");
\r
979 distratio = ( 1 - (vlen(self.enemy.origin - head.origin) / radius) );
\r
980 flameratio = edgeratio + distratio*(1 - edgeratio);
\r
982 // increase the player's heat; if it goes over the max it'll get capped automatically by the cooldown code
\r
983 //head.flame_heat = cvar("g_balance_maxheat");
\r
984 head.flame_heat = head.flame_heat + flameratio * cvar("g_balance_heatup_rate") * self.ltime;
\r
985 //head.flame_heat_time = time;
\r
987 // deal direct damage from the heat radiated by the fire
\r
988 damage = flameratio * self.dmg*cvar("g_balance_heat_damage");
\r
989 Damage (head, self, self.owner, damage, DEATH_BURNING, self.enemy.origin, '0 0 0');
\r
991 if(head.flame_heat >= 1.0 && head.takedamage == DAMAGE_AIM && head.health > 0)
\r
993 flametimemax = cvar("g_balance_heat_timemax");
\r
994 flametime = (self.wait - time) * cvar("g_balance_heat_transfer");
\r
995 if(flametime > flametimemax)
\r
996 flametime = flametimemax;
\r
999 //bprint(ftos(time), " - flame transfer - ", ftos(flametime), "\n");
\r
1002 IgniteTarget(head, self.owner, flametime, self.dmg, self.ltime, TRUE);
\r
1006 head = head.chain;
\r
1011 void PoisonTarget(entity targ, float poisonDamage, float poisonTime, float ratepoison)
\r
1013 if(targ.class == CLASS_MEDIC)
\r
1015 return; // don't poison medics
\r
1018 if(ratepoison && targ.poison_damage > poisonDamage)
\r
1019 return; // current damage rating is larger, don't replace it
\r
1021 targ.poison_damage = poisonDamage;
\r
1022 targ.poison_rate = poisonDamage / poisonTime;
\r
1035 float W_LimitNumEnts(string clname, float num_allowed, void() DeathFunc)
\r
1037 float num, oldest;
\r
1038 local entity e, selected;
\r
1040 oldest = time + 1;
\r
1044 e = find(e, classname, clname);
\r
1045 if(e != world && e.owner == self)
\r
1048 if(e.create_time < oldest)
\r
1051 oldest = e.create_time;
\r
1056 if(num > num_allowed)
\r
1058 if(selected != world)
\r
1067 bprint("error (W_LimitNumEnts): cannot find oldest entity\n");
\r