2001-07-23 20:52:47 +00:00
|
|
|
|
#include "defs.qh"
|
|
|
|
|
#include "menu.qh"
|
2001-07-17 05:58:10 +00:00
|
|
|
|
/*=======================================================//
|
2001-07-27 20:27:58 +00:00
|
|
|
|
// field.QC - CustomTF 3.2.OfN - 30/1/2001 - //
|
2001-07-17 05:58:10 +00:00
|
|
|
|
// by Sergio Fuma<6D>a Grunwaldt - OfteN aka superCOCK2000 //
|
|
|
|
|
=========================================================//
|
|
|
|
|
Field generator stuff - Written all by myself! :)
|
|
|
|
|
I took the model and some sounds from deadlode mod
|
|
|
|
|
One sound is from megaTF
|
|
|
|
|
=========================================================*/
|
|
|
|
|
|
|
|
|
|
// field generator flags, DO NOT MODIFY
|
|
|
|
|
|
2001-07-27 20:27:58 +00:00
|
|
|
|
#define FIELDGEN_ISOFF 0 // no field, not linked, and its not trying to link (several possible reasons)
|
|
|
|
|
#define FIELDGEN_ISIDLE 1 // no field, not linked, trying to link with other generator
|
2001-07-17 05:58:10 +00:00
|
|
|
|
#define FIELDGEN_ISDISABLED 2 // no field, linked, its disabled temporary (teammate passing thru field)
|
2001-07-27 20:27:58 +00:00
|
|
|
|
#define FIELDGEN_ISENABLED 3 // field, linked, and cells enough, waiting for shock, only hum sound
|
|
|
|
|
#define FIELDGEN_ISWORKING 4 // field, linked, glowing and all the field visual/sound effects are on
|
2001-07-17 05:58:10 +00:00
|
|
|
|
|
|
|
|
|
// field generator settings
|
|
|
|
|
|
2001-07-27 20:48:54 +00:00
|
|
|
|
#define FIELDGEN_SHOCKTIME 3 // seconds the generators remains glowing and doing lightning after a shock
|
2001-07-27 20:27:58 +00:00
|
|
|
|
#define FIELDGEN_LINKTIME 3.5 // seconds between tries to link with other generator
|
2001-07-27 20:48:54 +00:00
|
|
|
|
#define FIELDGEN_TIMEDISABLED 1.5 // was 3 // then 2
|
2001-07-27 20:27:58 +00:00
|
|
|
|
#define FIELDGEN_CELLSCOST 2 // cells cost for each "FIELDGEN_ISWORKING" pass
|
|
|
|
|
#define FIELDGEN_DMG 80 // normal damag when touching
|
|
|
|
|
#define FIELDGEN_DMGINSIDE 120 // damage when trapped inside field
|
2001-08-12 12:40:29 +00:00
|
|
|
|
#define FIELDGEN_MAXZ 10
|
2001-07-17 05:58:10 +00:00
|
|
|
|
|
|
|
|
|
/*===============================================================================================
|
|
|
|
|
|
|
|
|
|
EXPLANATION OF HOW THE ENTITY FIELDS ARE USED ( thnx? np.. =) )
|
|
|
|
|
---------------------------------------------
|
|
|
|
|
|
|
|
|
|
For field generator entity:
|
|
|
|
|
---------------------------
|
|
|
|
|
|
2001-07-19 14:48:59 +00:00
|
|
|
|
.fieldgen_status - Holds current status of every field generator, FIELDGEN_XXXX determines
|
|
|
|
|
.fieldgen_hasfield - Boolean value, determines if field generator is currently supporting a force field
|
2001-11-02 17:00:52 +00:00
|
|
|
|
.fieldgen_field - This points to the force field, if none its always 'NIL'
|
2001-07-27 20:27:58 +00:00
|
|
|
|
.no_grenades_1 - Controls delay between tries to link (only affects sound currently, it tries to link every frame)
|
|
|
|
|
.no_grenades_1 - Controls delay for field to go up again after beeing disabled
|
|
|
|
|
.tp_grenades_1 - Controls delay of the WORKING status
|
2001-07-17 05:58:10 +00:00
|
|
|
|
.has_teleporter - Used to flash generators when field is activated
|
2001-07-27 20:27:58 +00:00
|
|
|
|
.has_camera - Controls delay between cells take
|
|
|
|
|
.has_tesla - Boolean, forced status.
|
2001-07-17 05:58:10 +00:00
|
|
|
|
|
|
|
|
|
For force field entity:
|
|
|
|
|
-----------------------
|
|
|
|
|
|
2001-07-27 20:27:58 +00:00
|
|
|
|
.demon_one - Points to the first field generator
|
|
|
|
|
.demon_two - Points to the 2nd generator
|
|
|
|
|
.fieldgen_status - Hum sound running, boolean
|
|
|
|
|
.fieldgen_hasfield - Shield sound running, boolean
|
|
|
|
|
.has_tesla - Controls delay between hums
|
|
|
|
|
.has_sentry - Controls delay between shield sounds
|
|
|
|
|
.dmg - Next damage the field will do
|
|
|
|
|
.has_camera - Used to control the rate at which the field touch sound/visual effects are done (4hz)
|
|
|
|
|
.forcefield_offset - Offset to one of the gens from origin, used for lightning effects
|
2001-07-17 05:58:10 +00:00
|
|
|
|
|
|
|
|
|
================================================================================================*/
|
|
|
|
|
|
|
|
|
|
void() CheckDistance;
|
|
|
|
|
entity(entity fieldgen) Find_OtherGen;
|
|
|
|
|
float(entity fieldgen1, entity fieldgen2) FieldGens_CanLink;
|
|
|
|
|
float(entity fieldgen) FieldGen_CanIdle;
|
|
|
|
|
float(entity field) IsValidFieldGen;
|
|
|
|
|
float (vector targ, vector check) vis2orig;
|
|
|
|
|
float(entity field) IsValidField;
|
|
|
|
|
void(entity tfield, entity gen1) Field_UpdateSounds;
|
|
|
|
|
void(entity tfield) Field_MakeVisual;
|
|
|
|
|
float(entity tfield) FieldIsImproved;
|
|
|
|
|
float(entity tfield) FieldIsMalfunctioning;
|
|
|
|
|
void() Field_touch;
|
|
|
|
|
void() Field_touch_SUB;
|
|
|
|
|
float(entity e1, entity e2) EntsTouching2;
|
|
|
|
|
void(entity tfield, vector where, entity thing) FieldExplosion;
|
|
|
|
|
float(entity tfield, entity who) Field_ItCanPass;
|
|
|
|
|
float(entity tfield, entity who) Field_ShouldDamage;
|
|
|
|
|
|
|
|
|
|
#ifdef FIELD_FORCEMODE
|
|
|
|
|
|
|
|
|
|
entity(entity myself) GetMyFieldGen;
|
|
|
|
|
float(entity tfield) Field_GetForcedStatus;
|
|
|
|
|
void(float value) SetFieldForcedStatus; // player function (self = player) cuts disabled time also
|
|
|
|
|
float() GetFieldForcedStatus; // player
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
//=========================================================================================
|
|
|
|
|
// field generator model and sounds
|
|
|
|
|
|
|
|
|
|
void() Field_Precache =
|
|
|
|
|
{
|
2001-07-27 20:27:58 +00:00
|
|
|
|
precache_sound ("misc/null.wav");
|
|
|
|
|
precache_sound2("misc/ffhum.wav");
|
|
|
|
|
precache_sound2("misc/ffbeep.wav");
|
|
|
|
|
precache_sound2("misc/ffield.wav");
|
|
|
|
|
precache_sound2("misc/ffact.wav");
|
|
|
|
|
precache_sound2("misc/fffail.wav");
|
|
|
|
|
precache_model2("progs/ffgen2.mdl");
|
2001-07-17 05:58:10 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//================================================================================================
|
|
|
|
|
// checks for field generators and removes itself if needed, checks for stuck entities on field
|
|
|
|
|
|
|
|
|
|
void() Field_think =
|
|
|
|
|
{
|
2001-07-27 20:27:58 +00:00
|
|
|
|
if (self.classname != "force_field")
|
|
|
|
|
{
|
|
|
|
|
RPrint("BUG: Not a force field entity was in 'FieldThink()'!\n");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
self.has_camera = FALSE;
|
|
|
|
|
|
|
|
|
|
// checks for removal...
|
|
|
|
|
if (!IsValidFieldGen(self.demon_one) || !IsValidFieldGen(self.demon_two))
|
|
|
|
|
{
|
|
|
|
|
if (IsValidFieldGen(self.demon_one))
|
|
|
|
|
{
|
|
|
|
|
self.demon_one.fieldgen_hasfield = FALSE;
|
2001-11-02 17:00:52 +00:00
|
|
|
|
self.demon_one.fieldgen_field = NIL;
|
2001-07-27 20:27:58 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (IsValidFieldGen(self.demon_two))
|
|
|
|
|
{
|
|
|
|
|
self.demon_two.fieldgen_hasfield = FALSE;
|
2001-11-02 17:00:52 +00:00
|
|
|
|
self.demon_two.fieldgen_field = NIL;
|
2001-07-27 20:27:58 +00:00
|
|
|
|
}
|
|
|
|
|
|
2001-11-02 17:00:52 +00:00
|
|
|
|
self.demon_one = NIL;
|
|
|
|
|
self.demon_two = NIL;
|
2001-07-27 20:27:58 +00:00
|
|
|
|
|
|
|
|
|
dremove(self);
|
|
|
|
|
|
|
|
|
|
RPrint("Debug: Field entity removed in Field_think()\n"); //shouldnt happen
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
self.nextthink = time + 0.25; // 4hz check
|
|
|
|
|
|
|
|
|
|
if (IsValidFieldGen(self.demon_one))
|
|
|
|
|
if (self.demon_one.fieldgen_status == FIELDGEN_ISWORKING)
|
|
|
|
|
Field_MakeVisual(self);
|
2001-07-30 20:21:44 +00:00
|
|
|
|
|
2001-07-27 20:27:58 +00:00
|
|
|
|
// checks for anything stuck in field :)
|
|
|
|
|
local entity te;
|
|
|
|
|
local float frange;
|
2001-07-17 05:58:10 +00:00
|
|
|
|
|
2001-07-27 20:27:58 +00:00
|
|
|
|
frange = FIELDGEN_RANGE;
|
2001-07-17 05:58:10 +00:00
|
|
|
|
|
2001-07-27 20:27:58 +00:00
|
|
|
|
if (FieldIsImproved(self) & IMPROVED_FOUR)
|
|
|
|
|
frange = FIELDGEN_HACKEDRANGE;
|
2001-07-17 05:58:10 +00:00
|
|
|
|
|
2001-07-27 20:27:58 +00:00
|
|
|
|
te = findradius(self.origin,frange);
|
|
|
|
|
while (te)
|
2001-07-17 05:58:10 +00:00
|
|
|
|
{
|
|
|
|
|
if (te != self)
|
2001-07-27 20:27:58 +00:00
|
|
|
|
if (te != self.demon_one)
|
|
|
|
|
if (te != self.demon_two)
|
|
|
|
|
if (te.velocity == '0 0 0')
|
2001-07-19 14:48:59 +00:00
|
|
|
|
// if (!IsBuilding(te)) // no screwing with the buildings :)
|
|
|
|
|
if (te.classname != "force_field")
|
2001-07-30 16:01:31 +00:00
|
|
|
|
if (EntsTouching2(te,self))
|
2001-07-27 20:27:58 +00:00
|
|
|
|
{
|
2001-07-30 20:21:44 +00:00
|
|
|
|
other = te;
|
|
|
|
|
deathmsg = DMSG_STUCK_FORCEFIELD;
|
|
|
|
|
self.dmg = FIELDGEN_DMGINSIDE; // this gonna hurt
|
|
|
|
|
Field_touch_SUB();
|
2001-07-17 05:58:10 +00:00
|
|
|
|
}
|
|
|
|
|
te = te.chain;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//=============================================================================================
|
|
|
|
|
// is one entity actually inside the other one? (this avoids using a stupid trigger)
|
|
|
|
|
|
|
|
|
|
float(entity e1, entity e2) EntsTouching2 =
|
|
|
|
|
{
|
2001-07-31 17:08:59 +00:00
|
|
|
|
if (hullpointcontents (e2, e1.mins, e1.maxs, e1.origin) != CONTENTS_SOLID)
|
|
|
|
|
return FALSE;
|
2001-07-27 20:27:58 +00:00
|
|
|
|
return TRUE;
|
2001-07-17 05:58:10 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//=================================================================================
|
|
|
|
|
// these 2 functions return the current hacks that should apply to the field
|
|
|
|
|
|
|
|
|
|
float(entity tfield) FieldIsImproved =
|
|
|
|
|
{
|
2001-07-27 20:27:58 +00:00
|
|
|
|
if (IsValidFieldGen(tfield.demon_one) && IsValidFieldGen(tfield.demon_two))
|
|
|
|
|
return tfield.demon_one.num_mines | tfield.demon_two.num_mines;
|
2001-07-17 05:58:10 +00:00
|
|
|
|
|
2001-07-27 20:27:58 +00:00
|
|
|
|
if (IsValidFieldGen(tfield.demon_one))
|
|
|
|
|
return tfield.demon_one.num_mines;
|
2001-07-17 05:58:10 +00:00
|
|
|
|
|
2001-07-27 20:27:58 +00:00
|
|
|
|
if (IsValidFieldGen(tfield.demon_two))
|
|
|
|
|
return tfield.demon_two.num_mines;
|
2001-07-17 05:58:10 +00:00
|
|
|
|
|
2001-07-27 20:27:58 +00:00
|
|
|
|
return 0;
|
2001-07-17 05:58:10 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
float(entity tfield) FieldIsMalfunctioning =
|
|
|
|
|
{
|
2001-07-27 20:27:58 +00:00
|
|
|
|
if (IsValidFieldGen(tfield.demon_one) && IsValidFieldGen(tfield.demon_two))
|
|
|
|
|
return tfield.demon_one.is_malfunctioning | tfield.demon_two.is_malfunctioning;
|
2001-07-17 05:58:10 +00:00
|
|
|
|
|
2001-07-27 20:27:58 +00:00
|
|
|
|
if (IsValidFieldGen(tfield.demon_one))
|
|
|
|
|
return tfield.demon_one.is_malfunctioning;
|
2001-07-17 05:58:10 +00:00
|
|
|
|
|
2001-07-27 20:27:58 +00:00
|
|
|
|
if (IsValidFieldGen(tfield.demon_two))
|
|
|
|
|
return tfield.demon_two.is_malfunctioning;
|
2001-07-17 05:58:10 +00:00
|
|
|
|
|
2001-07-27 20:27:58 +00:00
|
|
|
|
return 0;
|
2001-07-17 05:58:10 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//=================================================================
|
|
|
|
|
// self is the field, disables it
|
|
|
|
|
|
|
|
|
|
void() DisableField =
|
|
|
|
|
{
|
2001-07-27 20:27:58 +00:00
|
|
|
|
if (IsValidFieldGen(self.demon_one))
|
|
|
|
|
{
|
|
|
|
|
self.demon_one.fieldgen_status = FIELDGEN_ISDISABLED;
|
|
|
|
|
self.demon_one.no_grenades_2 = time + FIELDGEN_TIMEDISABLED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (IsValidFieldGen(self.demon_two))
|
|
|
|
|
{
|
|
|
|
|
self.demon_two.fieldgen_status = FIELDGEN_ISDISABLED;
|
|
|
|
|
self.demon_two.no_grenades_2 = time + FIELDGEN_TIMEDISABLED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sound (self, CHAN_VOICE, "misc/ffbeep.wav", 0.4, ATTN_IDLE);
|
2001-07-17 05:58:10 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//=========================================================================================
|
|
|
|
|
// applies damage and makes the sound and visual effect for the forcefield shock
|
|
|
|
|
|
|
|
|
|
void() Field_touch_SUB =
|
|
|
|
|
{
|
2001-07-27 20:27:58 +00:00
|
|
|
|
local float doFX;
|
2001-07-27 05:11:51 +00:00
|
|
|
|
local float shoulddamage;
|
2001-07-27 20:27:58 +00:00
|
|
|
|
doFX = TRUE;
|
|
|
|
|
|
|
|
|
|
if (FieldIsMalfunctioning(self) & SCREWUP_THREE) // reduce output
|
|
|
|
|
self.dmg = 1;
|
|
|
|
|
|
|
|
|
|
if (other.classname == "player") // PLAYERS
|
|
|
|
|
{
|
2001-07-28 17:48:57 +00:00
|
|
|
|
//dprint (vtos (other.origin) + "\n");
|
2001-07-27 20:27:58 +00:00
|
|
|
|
if (other.playerclass == PC_UNDEFINED) // Observers
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (Field_ItCanPass(self, other))
|
|
|
|
|
{
|
|
|
|
|
DisableField();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
self.velocity = self.velocity - (self.velocity*4) + '0 0 1';
|
2001-07-27 05:11:51 +00:00
|
|
|
|
|
|
|
|
|
shoulddamage = Field_ShouldDamage(self,other);
|
|
|
|
|
if (shoulddamage == 1)
|
|
|
|
|
TF_T_Damage (other, self, self.real_owner, self.dmg, TF_TD_NOTTEAM, TF_TD_ELECTRICITY);
|
|
|
|
|
else if (shoulddamage == 2) // hacked to hurt teammates
|
2001-07-27 20:48:54 +00:00
|
|
|
|
{
|
|
|
|
|
if (deathmsg == DMSG_FORCEFIELD)
|
|
|
|
|
deathmsg = DMSG_FF_HACKED;
|
|
|
|
|
else /* if (deathmsg == DMSG_FORCEFIELD_STUCK) */
|
|
|
|
|
deathmsg = DMSG_FF_STUCK_HACKED;
|
1) Attempted to give players positive frags whenever possible. You now
should get frags for blowing people up with others' dispensers/mines/expbody,
airfisting rockets, etc.
2) Redid Give_Frags_Out
3) Changed many uses of pointcontents and ugly hacks to use hullpointcontents
and checkmove, now a lot cleaner and less buggy
4) You can grapple builds again. This caused really odd bugs.
5) You can now damage your own buildings again (gasp). Any time a tesla or sentry
is damaged it turns on its attacker, friendly or otherwise. This is both a counter-TK
and counter-spy mechanism.
6) Teslas are now entirely inside their bounding box
7) Now check every frame for players startsolid and for outside of the map cube.
8) #define WALL_HURT to make it hurt when you hit a wall
9) Used some cool ideas (aka laws of physics) to make the airfist a little less annoying
10) You now only get 1 mirv per slot without bandolier. Demoman and hwguy gain bandolier.
demoman loses his extra mirv but gains an extra grenade and pair of detpacks. Hwguy
gets extra grenade.
11) New and improved EMP grenade now does damage based on range. no longer blows up shells.
Doesn't directly damage sentries anymore, but does significant damage to dispensers.
EMP someone who's setting a det and it blows up in their face.
12) Players now do radius damage from getting EMPed (again)
13) EMPs now go through walls (again)
14) EMP number lowered by one (3 without, 4 with bandolier) and cost raised by $100
15) You can only have 2 frag grens, 3 with bandolier now.
16) Hover boots will now eat cells if they get low on charge. In addition, the silly bug
where their charge wasn't restored when you die is fixed now.
17) EMPing a detpack now sets its timer to anywhere between 1 and 121 seconds from current time,
with a logarithmic probability of it being lower. (random() * random() * 120 + 1). Also, probably
more time the closer it is to the EMP.
18) Judo can now be blocked by people with close combat, knife or judo. Blocked judo means that the
attacker loses 3 seconds of attack.
19) Judo missing now makes them unable to fire.
20) Shortened judo range (back to normal if w/ close combat)
21) Attempted to rework the railgun. Seems to be okay now.
Probably still a lot of bugs in here, but since this is the devel version I thought I would commit
all my changes so people could start testing it. I'll commit fixes as soon as I find the bugs.
2003-11-26 08:53:44 +00:00
|
|
|
|
TF_T_Damage (other, self, self.martyr_enemy, self.dmg, TF_TD_NOTTEAM, TF_TD_ELECTRICITY);
|
2001-07-27 20:48:54 +00:00
|
|
|
|
}
|
1) Attempted to give players positive frags whenever possible. You now
should get frags for blowing people up with others' dispensers/mines/expbody,
airfisting rockets, etc.
2) Redid Give_Frags_Out
3) Changed many uses of pointcontents and ugly hacks to use hullpointcontents
and checkmove, now a lot cleaner and less buggy
4) You can grapple builds again. This caused really odd bugs.
5) You can now damage your own buildings again (gasp). Any time a tesla or sentry
is damaged it turns on its attacker, friendly or otherwise. This is both a counter-TK
and counter-spy mechanism.
6) Teslas are now entirely inside their bounding box
7) Now check every frame for players startsolid and for outside of the map cube.
8) #define WALL_HURT to make it hurt when you hit a wall
9) Used some cool ideas (aka laws of physics) to make the airfist a little less annoying
10) You now only get 1 mirv per slot without bandolier. Demoman and hwguy gain bandolier.
demoman loses his extra mirv but gains an extra grenade and pair of detpacks. Hwguy
gets extra grenade.
11) New and improved EMP grenade now does damage based on range. no longer blows up shells.
Doesn't directly damage sentries anymore, but does significant damage to dispensers.
EMP someone who's setting a det and it blows up in their face.
12) Players now do radius damage from getting EMPed (again)
13) EMPs now go through walls (again)
14) EMP number lowered by one (3 without, 4 with bandolier) and cost raised by $100
15) You can only have 2 frag grens, 3 with bandolier now.
16) Hover boots will now eat cells if they get low on charge. In addition, the silly bug
where their charge wasn't restored when you die is fixed now.
17) EMPing a detpack now sets its timer to anywhere between 1 and 121 seconds from current time,
with a logarithmic probability of it being lower. (random() * random() * 120 + 1). Also, probably
more time the closer it is to the EMP.
18) Judo can now be blocked by people with close combat, knife or judo. Blocked judo means that the
attacker loses 3 seconds of attack.
19) Judo missing now makes them unable to fire.
20) Shortened judo range (back to normal if w/ close combat)
21) Attempted to rework the railgun. Seems to be okay now.
Probably still a lot of bugs in here, but since this is the devel version I thought I would commit
all my changes so people could start testing it. I'll commit fixes as soon as I find the bugs.
2003-11-26 08:53:44 +00:00
|
|
|
|
if (shoulddamage)
|
|
|
|
|
self.demon_one.has_camera = self.demon_two.has_camera = 0;
|
|
|
|
|
}
|
2001-07-27 20:27:58 +00:00
|
|
|
|
|
|
|
|
|
}
|
2001-08-13 12:20:39 +00:00
|
|
|
|
else if (other.classname != "force_field") // non player entities
|
2001-07-27 20:27:58 +00:00
|
|
|
|
{
|
|
|
|
|
if (IsMonster(other))
|
|
|
|
|
{
|
|
|
|
|
if (Field_ItCanPass(self, other))
|
|
|
|
|
{
|
|
|
|
|
DisableField();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
else
|
2001-07-27 05:11:51 +00:00
|
|
|
|
{
|
|
|
|
|
shoulddamage = Field_ShouldDamage(self,other);
|
|
|
|
|
if (shoulddamage == 1)
|
|
|
|
|
TF_T_Damage (other, self, self.real_owner, self.dmg, TF_TD_NOTTEAM, TF_TD_ELECTRICITY);
|
|
|
|
|
else if (shoulddamage == 2) // hacked to hurt teammates
|
2001-07-27 20:48:54 +00:00
|
|
|
|
{
|
|
|
|
|
if (deathmsg == DMSG_FORCEFIELD)
|
|
|
|
|
deathmsg = DMSG_FF_HACKED;
|
|
|
|
|
else /* if (deathmsg == DMSG_FORCEFIELD_STUCK) */
|
|
|
|
|
deathmsg = DMSG_FF_STUCK_HACKED;
|
1) Attempted to give players positive frags whenever possible. You now
should get frags for blowing people up with others' dispensers/mines/expbody,
airfisting rockets, etc.
2) Redid Give_Frags_Out
3) Changed many uses of pointcontents and ugly hacks to use hullpointcontents
and checkmove, now a lot cleaner and less buggy
4) You can grapple builds again. This caused really odd bugs.
5) You can now damage your own buildings again (gasp). Any time a tesla or sentry
is damaged it turns on its attacker, friendly or otherwise. This is both a counter-TK
and counter-spy mechanism.
6) Teslas are now entirely inside their bounding box
7) Now check every frame for players startsolid and for outside of the map cube.
8) #define WALL_HURT to make it hurt when you hit a wall
9) Used some cool ideas (aka laws of physics) to make the airfist a little less annoying
10) You now only get 1 mirv per slot without bandolier. Demoman and hwguy gain bandolier.
demoman loses his extra mirv but gains an extra grenade and pair of detpacks. Hwguy
gets extra grenade.
11) New and improved EMP grenade now does damage based on range. no longer blows up shells.
Doesn't directly damage sentries anymore, but does significant damage to dispensers.
EMP someone who's setting a det and it blows up in their face.
12) Players now do radius damage from getting EMPed (again)
13) EMPs now go through walls (again)
14) EMP number lowered by one (3 without, 4 with bandolier) and cost raised by $100
15) You can only have 2 frag grens, 3 with bandolier now.
16) Hover boots will now eat cells if they get low on charge. In addition, the silly bug
where their charge wasn't restored when you die is fixed now.
17) EMPing a detpack now sets its timer to anywhere between 1 and 121 seconds from current time,
with a logarithmic probability of it being lower. (random() * random() * 120 + 1). Also, probably
more time the closer it is to the EMP.
18) Judo can now be blocked by people with close combat, knife or judo. Blocked judo means that the
attacker loses 3 seconds of attack.
19) Judo missing now makes them unable to fire.
20) Shortened judo range (back to normal if w/ close combat)
21) Attempted to rework the railgun. Seems to be okay now.
Probably still a lot of bugs in here, but since this is the devel version I thought I would commit
all my changes so people could start testing it. I'll commit fixes as soon as I find the bugs.
2003-11-26 08:53:44 +00:00
|
|
|
|
TF_T_Damage (other, self, self.martyr_enemy, self.dmg, TF_TD_NOTTEAM, TF_TD_ELECTRICITY);
|
2001-07-27 20:48:54 +00:00
|
|
|
|
}
|
2001-07-27 05:11:51 +00:00
|
|
|
|
}
|
2001-07-27 20:27:58 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// excludes entities that shouldnt be moved, doors plats etc..
|
|
|
|
|
if(other.movetype == MOVETYPE_NONE
|
|
|
|
|
|| other.movetype == MOVETYPE_PUSH)
|
|
|
|
|
//|| other.movetype == MOVETYPE_NOCLIP
|
|
|
|
|
return;
|
2001-07-19 14:48:59 +00:00
|
|
|
|
if (IsBuilding(other))
|
|
|
|
|
return;
|
2001-07-17 05:58:10 +00:00
|
|
|
|
|
2001-07-27 20:27:58 +00:00
|
|
|
|
}
|
2001-07-17 05:58:10 +00:00
|
|
|
|
|
1) Attempted to give players positive frags whenever possible. You now
should get frags for blowing people up with others' dispensers/mines/expbody,
airfisting rockets, etc.
2) Redid Give_Frags_Out
3) Changed many uses of pointcontents and ugly hacks to use hullpointcontents
and checkmove, now a lot cleaner and less buggy
4) You can grapple builds again. This caused really odd bugs.
5) You can now damage your own buildings again (gasp). Any time a tesla or sentry
is damaged it turns on its attacker, friendly or otherwise. This is both a counter-TK
and counter-spy mechanism.
6) Teslas are now entirely inside their bounding box
7) Now check every frame for players startsolid and for outside of the map cube.
8) #define WALL_HURT to make it hurt when you hit a wall
9) Used some cool ideas (aka laws of physics) to make the airfist a little less annoying
10) You now only get 1 mirv per slot without bandolier. Demoman and hwguy gain bandolier.
demoman loses his extra mirv but gains an extra grenade and pair of detpacks. Hwguy
gets extra grenade.
11) New and improved EMP grenade now does damage based on range. no longer blows up shells.
Doesn't directly damage sentries anymore, but does significant damage to dispensers.
EMP someone who's setting a det and it blows up in their face.
12) Players now do radius damage from getting EMPed (again)
13) EMPs now go through walls (again)
14) EMP number lowered by one (3 without, 4 with bandolier) and cost raised by $100
15) You can only have 2 frag grens, 3 with bandolier now.
16) Hover boots will now eat cells if they get low on charge. In addition, the silly bug
where their charge wasn't restored when you die is fixed now.
17) EMPing a detpack now sets its timer to anywhere between 1 and 121 seconds from current time,
with a logarithmic probability of it being lower. (random() * random() * 120 + 1). Also, probably
more time the closer it is to the EMP.
18) Judo can now be blocked by people with close combat, knife or judo. Blocked judo means that the
attacker loses 3 seconds of attack.
19) Judo missing now makes them unable to fire.
20) Shortened judo range (back to normal if w/ close combat)
21) Attempted to rework the railgun. Seems to be okay now.
Probably still a lot of bugs in here, but since this is the devel version I thought I would commit
all my changes so people could start testing it. I'll commit fixes as soon as I find the bugs.
2003-11-26 08:53:44 +00:00
|
|
|
|
other.velocity_x = -other.velocity_x;
|
|
|
|
|
other.velocity_y = -other.velocity_y;
|
|
|
|
|
|
|
|
|
|
other.velocity += 200*normalize(other.velocity);
|
|
|
|
|
|
2001-07-27 20:27:58 +00:00
|
|
|
|
FieldExplosion(self,other.origin,other);
|
|
|
|
|
PutFieldWork(self);
|
2001-07-17 05:58:10 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#ifdef FIELD_FORCEMODE
|
|
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
|
// gets one of our field generators
|
|
|
|
|
|
|
|
|
|
entity(entity myself) GetMyFieldGen =
|
|
|
|
|
{
|
2001-07-27 20:27:58 +00:00
|
|
|
|
local entity te;
|
|
|
|
|
local float foundit;
|
2001-11-02 17:00:52 +00:00
|
|
|
|
te = NIL;
|
2001-07-27 20:27:58 +00:00
|
|
|
|
foundit = FALSE;
|
|
|
|
|
|
2001-11-02 17:00:52 +00:00
|
|
|
|
te = find(NIL, classname, "building_fieldgen");
|
|
|
|
|
while (te && foundit == FALSE)
|
2001-07-27 20:27:58 +00:00
|
|
|
|
{
|
|
|
|
|
if (te.real_owner == myself) // is it ours?
|
|
|
|
|
foundit = TRUE; // yeah, found it
|
|
|
|
|
|
|
|
|
|
if (foundit == FALSE) // our search must continue...
|
|
|
|
|
te = find(te, classname, "building_fieldgen");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return te;
|
2001-07-17 05:58:10 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//=========================================================================
|
|
|
|
|
// these functions retrieve and set the current 'forced status' on a field
|
|
|
|
|
|
|
|
|
|
float(entity tfield) Field_GetForcedStatus =
|
|
|
|
|
{
|
2001-07-27 20:27:58 +00:00
|
|
|
|
if (IsValidFieldGen(tfield.demon_one) && IsValidFieldGen(tfield.demon_two))
|
|
|
|
|
{
|
|
|
|
|
if (tfield.demon_two.has_tesla || tfield.demon_one.has_tesla)
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
else if (IsValidFieldGen(tfield.demon_one))
|
|
|
|
|
{
|
|
|
|
|
if (tfield.demon_one.has_tesla)
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
else if (IsValidFieldGen(tfield.demon_two))
|
|
|
|
|
{
|
|
|
|
|
if (tfield.demon_two.has_tesla)
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return FALSE;
|
2001-07-17 05:58:10 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//==============================================================================
|
|
|
|
|
// player functions called on menu.qc to disable/enable forced status on field
|
|
|
|
|
|
|
|
|
|
void(float value) SetFieldForcedStatus =
|
|
|
|
|
{
|
2001-07-27 20:27:58 +00:00
|
|
|
|
local entity gen1, gen2;
|
|
|
|
|
gen1 = GetMyFieldGen(self);
|
|
|
|
|
gen2 = Find_OtherGen(gen1);
|
|
|
|
|
|
|
|
|
|
if (IsValidFieldGen(gen1))
|
|
|
|
|
{
|
|
|
|
|
gen1.has_tesla = value;
|
|
|
|
|
if (value)
|
|
|
|
|
gen1.no_grenades_2 = time;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (IsValidFieldGen(gen2))
|
|
|
|
|
{
|
|
|
|
|
gen2.has_tesla = value;
|
|
|
|
|
if (value)
|
|
|
|
|
gen2.no_grenades_2 = time;
|
|
|
|
|
}
|
2001-07-17 05:58:10 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
float() GetFieldForcedStatus =
|
|
|
|
|
{
|
2001-07-27 20:27:58 +00:00
|
|
|
|
local entity gen1, gen2;
|
|
|
|
|
gen1 = GetMyFieldGen(self);
|
|
|
|
|
gen2 = Find_OtherGen(gen1);
|
|
|
|
|
|
|
|
|
|
if (IsValidFieldGen(gen1) && IsValidFieldGen(gen2))
|
|
|
|
|
{
|
|
|
|
|
if (gen1.has_tesla || gen2.has_tesla)
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
else if (IsValidFieldGen(gen1))
|
|
|
|
|
return gen1.has_tesla;
|
|
|
|
|
else if (IsValidFieldGen(gen2))
|
|
|
|
|
return gen2.has_tesla;
|
|
|
|
|
|
|
|
|
|
return FALSE;
|
2001-07-17 05:58:10 +00:00
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
//=========================================================================
|
|
|
|
|
// returns TRUE if 'who' entity should be able to pass thru the field
|
|
|
|
|
|
|
|
|
|
float(entity tfield, entity who) Field_ItCanPass =
|
|
|
|
|
{
|
2001-07-27 20:27:58 +00:00
|
|
|
|
if (FieldIsMalfunctioning(tfield) & SCREWUP_ONE)
|
|
|
|
|
return FALSE;
|
2001-07-17 05:58:10 +00:00
|
|
|
|
|
2001-07-26 18:43:38 +00:00
|
|
|
|
/*
|
2001-07-27 20:27:58 +00:00
|
|
|
|
if (who == tfield.real_owner) // field owner - always pass
|
|
|
|
|
return TRUE;
|
2001-07-26 18:43:38 +00:00
|
|
|
|
*/
|
2001-07-27 20:27:58 +00:00
|
|
|
|
if (Field_GetForcedStatus(tfield))
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
if (who.classname == "player") // PLAYERS
|
|
|
|
|
{
|
|
|
|
|
if (Teammate(who.team_no, tfield.real_owner.team_no)) // teammate
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
|
|
if (Teammate(who.undercover_team, tfield.real_owner.team_no)) // spies disguised as our team
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
else if (IsMonster(who)) // MONSTERS/ARMY
|
|
|
|
|
{
|
|
|
|
|
if (Teammate(who.real_owner.team_no, tfield.real_owner.team_no)) // team monster
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return FALSE;
|
2001-07-17 05:58:10 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//=========================================================================
|
2001-07-27 05:11:51 +00:00
|
|
|
|
// returns 1 or 2 if 'who' entity should be damaged by the field
|
|
|
|
|
// 1 if it's an enemy, 2 if a friendly and has been hacked
|
2001-07-17 05:58:10 +00:00
|
|
|
|
|
|
|
|
|
float(entity tfield, entity who) Field_ShouldDamage =
|
|
|
|
|
{
|
2001-07-27 05:11:51 +00:00
|
|
|
|
local float fr;
|
|
|
|
|
if (FieldIsMalfunctioning(tfield) & SCREWUP_ONE)
|
|
|
|
|
fr = 2;
|
|
|
|
|
else
|
|
|
|
|
fr = 0;
|
2001-07-17 05:58:10 +00:00
|
|
|
|
|
2001-07-27 05:11:51 +00:00
|
|
|
|
if (who.classname == "player") // PLAYERS
|
|
|
|
|
{
|
|
|
|
|
if (who == tfield.real_owner) // field owner
|
|
|
|
|
return fr;
|
2001-07-17 05:58:10 +00:00
|
|
|
|
|
2001-07-27 05:11:51 +00:00
|
|
|
|
if (Teammate(who.team_no, tfield.real_owner.team_no)) // teammate
|
|
|
|
|
return fr;
|
2001-07-17 05:58:10 +00:00
|
|
|
|
|
2001-07-27 05:11:51 +00:00
|
|
|
|
if (Teammate(who.undercover_team, tfield.real_owner.team_no)) // spies disguised as our team
|
|
|
|
|
return fr;
|
|
|
|
|
}
|
|
|
|
|
else if (IsMonster(who)) // MONSTERS/ARMY
|
|
|
|
|
{
|
|
|
|
|
if (Teammate(who.real_owner.team_no, tfield.real_owner.team_no)) // team monster
|
|
|
|
|
return fr;
|
|
|
|
|
}
|
2001-07-17 05:58:10 +00:00
|
|
|
|
|
2001-07-27 05:11:51 +00:00
|
|
|
|
return 1;
|
2001-07-17 05:58:10 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//=============================================================================
|
|
|
|
|
// applies the particle effect and electric sound (at max 4hz rate)
|
|
|
|
|
|
|
|
|
|
void(entity tfield, vector where, entity thing) FieldExplosion =
|
|
|
|
|
{
|
2001-07-27 20:27:58 +00:00
|
|
|
|
if (!tfield.has_camera)
|
|
|
|
|
{
|
2001-11-02 17:00:52 +00:00
|
|
|
|
if (!thing || thing.is_removed) return;
|
2001-07-17 05:58:10 +00:00
|
|
|
|
|
2001-07-27 20:27:58 +00:00
|
|
|
|
local vector whereFX;
|
|
|
|
|
whereFX = where;
|
|
|
|
|
whereFX_z = tfield.origin_z;
|
2001-07-17 05:58:10 +00:00
|
|
|
|
|
2001-07-27 20:27:58 +00:00
|
|
|
|
spawnFOG(whereFX);
|
|
|
|
|
sound(tfield,CHAN_BODY,"effects/crunch.wav",0.5,ATTN_NORM);
|
2001-07-17 05:58:10 +00:00
|
|
|
|
|
2001-07-27 20:27:58 +00:00
|
|
|
|
tfield.has_camera = TRUE; // cya soon
|
|
|
|
|
}
|
2001-07-17 05:58:10 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
void(entity field) PutFieldWork =
|
|
|
|
|
{
|
2001-07-27 20:27:58 +00:00
|
|
|
|
if (IsValidFieldGen(field.demon_one))
|
|
|
|
|
field.demon_one.tp_grenades_1 = time + FIELDGEN_SHOCKTIME;
|
|
|
|
|
if (IsValidFieldGen(field.demon_two))
|
|
|
|
|
field.demon_two.tp_grenades_1 = time + FIELDGEN_SHOCKTIME;
|
2001-07-17 05:58:10 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
void() Field_touch =
|
|
|
|
|
{
|
2001-07-27 20:27:58 +00:00
|
|
|
|
if (other.classname == "force_field") return; //avoid weird loops with other fields
|
2001-07-17 05:58:10 +00:00
|
|
|
|
|
2001-07-27 20:27:58 +00:00
|
|
|
|
deathmsg = DMSG_FORCEFIELD;
|
1) Attempted to give players positive frags whenever possible. You now
should get frags for blowing people up with others' dispensers/mines/expbody,
airfisting rockets, etc.
2) Redid Give_Frags_Out
3) Changed many uses of pointcontents and ugly hacks to use hullpointcontents
and checkmove, now a lot cleaner and less buggy
4) You can grapple builds again. This caused really odd bugs.
5) You can now damage your own buildings again (gasp). Any time a tesla or sentry
is damaged it turns on its attacker, friendly or otherwise. This is both a counter-TK
and counter-spy mechanism.
6) Teslas are now entirely inside their bounding box
7) Now check every frame for players startsolid and for outside of the map cube.
8) #define WALL_HURT to make it hurt when you hit a wall
9) Used some cool ideas (aka laws of physics) to make the airfist a little less annoying
10) You now only get 1 mirv per slot without bandolier. Demoman and hwguy gain bandolier.
demoman loses his extra mirv but gains an extra grenade and pair of detpacks. Hwguy
gets extra grenade.
11) New and improved EMP grenade now does damage based on range. no longer blows up shells.
Doesn't directly damage sentries anymore, but does significant damage to dispensers.
EMP someone who's setting a det and it blows up in their face.
12) Players now do radius damage from getting EMPed (again)
13) EMPs now go through walls (again)
14) EMP number lowered by one (3 without, 4 with bandolier) and cost raised by $100
15) You can only have 2 frag grens, 3 with bandolier now.
16) Hover boots will now eat cells if they get low on charge. In addition, the silly bug
where their charge wasn't restored when you die is fixed now.
17) EMPing a detpack now sets its timer to anywhere between 1 and 121 seconds from current time,
with a logarithmic probability of it being lower. (random() * random() * 120 + 1). Also, probably
more time the closer it is to the EMP.
18) Judo can now be blocked by people with close combat, knife or judo. Blocked judo means that the
attacker loses 3 seconds of attack.
19) Judo missing now makes them unable to fire.
20) Shortened judo range (back to normal if w/ close combat)
21) Attempted to rework the railgun. Seems to be okay now.
Probably still a lot of bugs in here, but since this is the devel version I thought I would commit
all my changes so people could start testing it. I'll commit fixes as soon as I find the bugs.
2003-11-26 08:53:44 +00:00
|
|
|
|
if (self.dmg == FIELDGEN_DMGINSIDE)
|
|
|
|
|
deathmsg = DMSG_STUCK_FORCEFIELD;
|
|
|
|
|
else
|
|
|
|
|
self.dmg = FIELDGEN_DMG;
|
|
|
|
|
|
2001-07-27 20:27:58 +00:00
|
|
|
|
Field_touch_SUB();
|
2001-07-17 05:58:10 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//===================================================================================
|
|
|
|
|
// creates the force field between the 2 generators (only if none currently on)
|
|
|
|
|
|
|
|
|
|
void(entity gen1, entity gen2) Create_Field =
|
|
|
|
|
{
|
2001-07-28 17:48:57 +00:00
|
|
|
|
//local string foo;
|
|
|
|
|
|
2001-07-27 20:27:58 +00:00
|
|
|
|
if (gen1.fieldgen_hasfield || gen2.fieldgen_hasfield)
|
|
|
|
|
return;
|
2001-07-17 05:58:10 +00:00
|
|
|
|
|
2001-07-28 17:48:57 +00:00
|
|
|
|
//foo = "gen1: " + vtos (gen1.origin) + " " + vtos (gen1.absmin) + " " + vtos (gen1.absmax);
|
|
|
|
|
//dprint(foo + "\n");
|
|
|
|
|
//foo = "gen2: " + vtos (gen2.origin) + " " + vtos (gen2.absmin) + " " + vtos (gen2.absmax);
|
|
|
|
|
//dprint(foo + "\n");
|
2001-07-19 05:46:41 +00:00
|
|
|
|
/* dprint("gen1:\n");
|
|
|
|
|
eprint(gen1.fieldgen_field);
|
|
|
|
|
dprint("gen2:\n");
|
|
|
|
|
eprint(gen2.fieldgen_field);
|
|
|
|
|
dprint("done\n"); */
|
|
|
|
|
|
2001-11-02 17:00:52 +00:00
|
|
|
|
if (gen1.fieldgen_field || gen2.fieldgen_field) // CHECK
|
2001-07-27 20:27:58 +00:00
|
|
|
|
return;
|
2001-07-17 05:58:10 +00:00
|
|
|
|
|
2001-07-27 20:27:58 +00:00
|
|
|
|
// already checked b4 on CanLink -> CanIdle
|
|
|
|
|
/*if (!IsValidFieldGen(gen1) || !IsValidFieldGen(gen2))
|
|
|
|
|
return;*/
|
2001-07-30 20:21:44 +00:00
|
|
|
|
|
2001-07-27 20:27:58 +00:00
|
|
|
|
gen1.fieldgen_status = FIELDGEN_ISENABLED;
|
|
|
|
|
gen2.fieldgen_status = FIELDGEN_ISENABLED;
|
2001-07-17 05:58:10 +00:00
|
|
|
|
|
2001-07-27 20:27:58 +00:00
|
|
|
|
gen1.fieldgen_hasfield = TRUE;
|
|
|
|
|
gen2.fieldgen_hasfield = TRUE;
|
2001-07-17 05:58:10 +00:00
|
|
|
|
|
2001-07-27 20:27:58 +00:00
|
|
|
|
local entity tfield;
|
2001-07-17 05:58:10 +00:00
|
|
|
|
|
2001-07-27 20:27:58 +00:00
|
|
|
|
// generate field
|
|
|
|
|
tfield = spawn();
|
|
|
|
|
tfield.classname = "force_field";
|
2001-11-02 17:00:52 +00:00
|
|
|
|
tfield.owner = NIL;
|
2001-07-27 20:27:58 +00:00
|
|
|
|
tfield.real_owner = gen1.real_owner; // --> player
|
2001-07-17 05:58:10 +00:00
|
|
|
|
|
2001-07-27 20:27:58 +00:00
|
|
|
|
tfield.think = Field_think;
|
|
|
|
|
tfield.touch = Field_touch;
|
|
|
|
|
tfield.nextthink = time + 0.25;
|
2001-07-17 05:58:10 +00:00
|
|
|
|
|
2001-07-25 17:09:45 +00:00
|
|
|
|
// set pos and size
|
2001-07-26 18:22:56 +00:00
|
|
|
|
tfield.size_x = vlen (gen1.origin - gen2.origin) - 10;
|
|
|
|
|
tfield.size_y = 4;
|
2001-07-27 15:32:03 +00:00
|
|
|
|
tfield.size_z = 48; // was 64, but 48 is more realistic
|
2001-07-25 17:09:45 +00:00
|
|
|
|
tfield.maxs = tfield.size * 0.5; // FIXME: / 2 is broken
|
2001-07-27 06:39:42 +00:00
|
|
|
|
tfield.mins = -tfield.maxs;
|
2001-07-28 17:48:57 +00:00
|
|
|
|
tfield.origin = AVG (gen1.origin, gen2.origin);
|
2001-07-25 19:23:26 +00:00
|
|
|
|
tfield.origin_z = AVG (gen1.absmax_z, gen2.absmax_z) - tfield.maxs_z;
|
2001-07-27 05:11:51 +00:00
|
|
|
|
tfield.forcefield_offset = (gen2.origin - gen1.origin);
|
2001-07-26 18:22:56 +00:00
|
|
|
|
|
|
|
|
|
local vector right, forward, up;
|
|
|
|
|
|
|
|
|
|
up = '0 0 1';
|
|
|
|
|
right = normalize (gen2.origin - gen1.origin);
|
|
|
|
|
forward = crossproduct (up, right);
|
|
|
|
|
|
2001-07-27 06:39:42 +00:00
|
|
|
|
// local string foo;
|
2001-07-28 17:48:57 +00:00
|
|
|
|
// foo = "right: " + vtos (right) + "\nforward: " + vtos (forward)
|
|
|
|
|
// + "\nup: " + vtos (up) + "\nmins: " + vtos (tfield.mins)
|
|
|
|
|
// + " maxs: " + vtos (tfield.maxs) + "\norigin: " + vtos (tfield.origin) + "\n";
|
2001-07-26 18:22:56 +00:00
|
|
|
|
// dprint (foo);
|
|
|
|
|
tfield.rotated_bbox = getboxhull();
|
|
|
|
|
rotate_bbox (tfield.rotated_bbox, right, forward, up, tfield.mins,
|
|
|
|
|
tfield.maxs);
|
2001-07-27 20:27:58 +00:00
|
|
|
|
|
|
|
|
|
local vector mins, maxs;
|
|
|
|
|
mins = getboxbounds (tfield.rotated_bbox, 0);
|
|
|
|
|
maxs = getboxbounds (tfield.rotated_bbox, 1);
|
|
|
|
|
|
|
|
|
|
// apply stuff
|
|
|
|
|
tfield.movetype = MOVETYPE_NONE;
|
|
|
|
|
tfield.solid = SOLID_BBOX;
|
|
|
|
|
setsize(tfield, mins, maxs);
|
|
|
|
|
setorigin(tfield, tfield.origin);
|
|
|
|
|
// foo = "min: " + vtos (mins) + "\n" +
|
|
|
|
|
// "max: " + vtos (maxs) + "\n" +
|
|
|
|
|
// "absmin: " + vtos (tfield.absmin) + "\n" +
|
|
|
|
|
// "absmax: " + vtos (tfield.absmax) + "\n";
|
|
|
|
|
// dprint (foo + "\n");
|
|
|
|
|
|
|
|
|
|
// assign the pointers on the field generators
|
|
|
|
|
gen1.fieldgen_field = tfield;
|
|
|
|
|
gen2.fieldgen_field = tfield;
|
|
|
|
|
|
|
|
|
|
// assign the pointers to generators on ourselves
|
|
|
|
|
tfield.demon_one = gen1;
|
|
|
|
|
tfield.demon_two = gen2;
|
|
|
|
|
|
|
|
|
|
//make activating sound
|
|
|
|
|
sound (tfield, CHAN_VOICE, "misc/ffact.wav", 0.2, ATTN_NORM);
|
|
|
|
|
|
|
|
|
|
// flash generators
|
|
|
|
|
gen1.effects = EF_DIMLIGHT;
|
|
|
|
|
gen1.has_teleporter = TRUE;
|
|
|
|
|
gen1.skin = 2;
|
|
|
|
|
gen2.effects = EF_DIMLIGHT;
|
|
|
|
|
gen2.has_teleporter = TRUE;
|
|
|
|
|
gen2.skin = 2;
|
2001-07-27 20:48:54 +00:00
|
|
|
|
|
2001-07-28 16:46:29 +00:00
|
|
|
|
if (gen1.martyr_enemy)
|
|
|
|
|
tfield.martyr_enemy = gen1.martyr_enemy;
|
|
|
|
|
else if (gen1.martyr_enemy)
|
|
|
|
|
tfield.martyr_enemy = gen2.martyr_enemy;
|
|
|
|
|
else
|
2001-11-02 17:00:52 +00:00
|
|
|
|
tfield.martyr_enemy = NIL;
|
2001-07-28 16:46:29 +00:00
|
|
|
|
|
2001-07-27 20:48:54 +00:00
|
|
|
|
/* // make sure the field goes off instantly if there's somebody in it
|
|
|
|
|
local entity oldself;
|
|
|
|
|
oldself = self;
|
|
|
|
|
self = tfield;
|
|
|
|
|
self.think ();
|
|
|
|
|
self = oldself; */
|
2001-07-17 05:58:10 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//=================================================================0
|
|
|
|
|
// removes the force field (if any)
|
|
|
|
|
|
|
|
|
|
void(entity gen1, entity gen2) Remove_Field =
|
|
|
|
|
{
|
2001-07-26 18:22:56 +00:00
|
|
|
|
if (IsValidFieldGen(gen1))
|
2001-07-27 20:27:58 +00:00
|
|
|
|
{
|
2001-07-26 18:22:56 +00:00
|
|
|
|
if (IsValidField(gen1.fieldgen_field))
|
|
|
|
|
{
|
|
|
|
|
freeboxhull (gen1.fieldgen_field.rotated_bbox);
|
|
|
|
|
dremove(gen1.fieldgen_field);
|
|
|
|
|
}
|
|
|
|
|
gen1.fieldgen_hasfield = FALSE;
|
2001-11-02 17:00:52 +00:00
|
|
|
|
gen1.fieldgen_field = NIL;
|
2001-07-26 18:22:56 +00:00
|
|
|
|
if (IsValidFieldGen(gen2))
|
|
|
|
|
{
|
|
|
|
|
gen2.fieldgen_hasfield = FALSE;
|
2001-11-02 17:00:52 +00:00
|
|
|
|
gen2.fieldgen_field = NIL;
|
2001-07-26 18:22:56 +00:00
|
|
|
|
}
|
2001-07-19 05:46:41 +00:00
|
|
|
|
}
|
2001-07-26 18:22:56 +00:00
|
|
|
|
else if (IsValidFieldGen(gen2))
|
2001-07-19 05:46:41 +00:00
|
|
|
|
{
|
2001-07-26 18:22:56 +00:00
|
|
|
|
if (IsValidField(gen2.fieldgen_field))
|
|
|
|
|
{
|
|
|
|
|
freeboxhull (gen2.fieldgen_field.rotated_bbox);
|
|
|
|
|
dremove(gen2.fieldgen_field);
|
|
|
|
|
}
|
|
|
|
|
gen2.fieldgen_hasfield = FALSE;
|
2001-11-02 17:00:52 +00:00
|
|
|
|
gen2.fieldgen_field = NIL;
|
2001-07-19 05:46:41 +00:00
|
|
|
|
}
|
2001-07-17 05:58:10 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
float(entity field) IsValidField =
|
|
|
|
|
{
|
2001-11-02 17:00:52 +00:00
|
|
|
|
if (!field)
|
2001-07-27 20:27:58 +00:00
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
if (field.classname != "force_field")
|
|
|
|
|
return FALSE;
|
2001-07-17 05:58:10 +00:00
|
|
|
|
|
2001-07-27 20:27:58 +00:00
|
|
|
|
return TRUE;
|
2001-07-17 05:58:10 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
float(entity field) IsValidFieldGen =
|
|
|
|
|
{
|
2001-11-02 17:00:52 +00:00
|
|
|
|
if (!field)
|
2001-07-27 20:27:58 +00:00
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
if (field.classname != "building_fieldgen")
|
|
|
|
|
return FALSE;
|
2001-07-17 05:58:10 +00:00
|
|
|
|
|
2001-07-27 20:27:58 +00:00
|
|
|
|
return TRUE;
|
2001-07-17 05:58:10 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//========================================================
|
|
|
|
|
// starts or removes sounds on the field
|
|
|
|
|
|
|
|
|
|
void(entity tfield, entity gen1) Field_UpdateSounds =
|
|
|
|
|
{
|
2001-07-27 20:27:58 +00:00
|
|
|
|
//fieldgen_status : hum
|
|
|
|
|
//fieldgen_hasfield : shield
|
|
|
|
|
|
|
|
|
|
if (IsValidField(tfield)) // only if there is a field currently
|
|
|
|
|
{
|
|
|
|
|
local float playhum, playshield;
|
|
|
|
|
playhum = FALSE; playshield = FALSE;
|
|
|
|
|
|
|
|
|
|
/*if (gen1.fieldgen_status == FIELDGEN_ISOFF) // for some reason we r not working
|
|
|
|
|
{
|
|
|
|
|
playhum = FALSE;
|
|
|
|
|
playshield = FALSE;
|
|
|
|
|
}
|
|
|
|
|
else if (gen1.fieldgen_status == FIELDGEN_ISIDLE) // awaiting for link
|
|
|
|
|
{
|
|
|
|
|
playhum = FALSE;
|
|
|
|
|
playshield = FALSE;
|
|
|
|
|
}
|
|
|
|
|
else if (gen1.fieldgen_status == FIELDGEN_ISDISABLED) // teammate passing thru the field?
|
|
|
|
|
{
|
|
|
|
|
playhum = FALSE;
|
|
|
|
|
playshield = FALSE;
|
|
|
|
|
}
|
|
|
|
|
else*/
|
|
|
|
|
|
|
|
|
|
if (gen1.fieldgen_status == FIELDGEN_ISENABLED)
|
|
|
|
|
{
|
|
|
|
|
playhum = TRUE;
|
|
|
|
|
playshield = FALSE;
|
|
|
|
|
}
|
|
|
|
|
else if (gen1.fieldgen_status == FIELDGEN_ISWORKING)
|
|
|
|
|
{
|
|
|
|
|
playhum = TRUE;
|
|
|
|
|
playshield = TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// MAKE THE SHIT SOUND !
|
|
|
|
|
if (!playhum)
|
|
|
|
|
{
|
|
|
|
|
if (tfield.fieldgen_status)
|
|
|
|
|
{
|
|
|
|
|
sound(tfield,CHAN_MISC,"misc/null.wav",0.5,ATTN_NORM);
|
|
|
|
|
tfield.fieldgen_status = FALSE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (!tfield.fieldgen_status || tfield.has_tesla < time)
|
|
|
|
|
{
|
|
|
|
|
sound(tfield,CHAN_MISC,"misc/ffhum.wav",0.3,ATTN_NORM);
|
|
|
|
|
tfield.has_tesla = time + 1;
|
|
|
|
|
tfield.fieldgen_status = TRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(!playshield)
|
|
|
|
|
{
|
|
|
|
|
if (tfield.fieldgen_hasfield)
|
|
|
|
|
{
|
|
|
|
|
sound(tfield,CHAN_ITEM,"misc/null.wav",0.2,ATTN_NORM);
|
|
|
|
|
tfield.fieldgen_hasfield = FALSE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (!tfield.fieldgen_hasfield || tfield.has_sentry < time)
|
|
|
|
|
{
|
|
|
|
|
//TODO?: lower volume as (FIELDGEN_SHOCKTIME - time) decreases
|
|
|
|
|
|
|
|
|
|
sound(tfield,CHAN_ITEM,"misc/ffield.wav",0.4,ATTN_NORM);
|
|
|
|
|
tfield.has_sentry = time + 1;
|
|
|
|
|
tfield.fieldgen_hasfield = TRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
2001-07-17 05:58:10 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//====================================================================
|
|
|
|
|
// do the lightning stuff while field is FIELDGEN_ISWORKING
|
|
|
|
|
|
|
|
|
|
void(entity tfield) Field_MakeVisual =
|
|
|
|
|
{
|
2001-07-27 20:27:58 +00:00
|
|
|
|
if (IsValidField(tfield))
|
|
|
|
|
{
|
|
|
|
|
local vector f;
|
|
|
|
|
|
2001-07-26 19:09:24 +00:00
|
|
|
|
f = tfield.origin + (tfield.forcefield_offset * 0.5 * (random() * 2 - 1));
|
2001-07-17 05:58:10 +00:00
|
|
|
|
|
2001-10-13 23:02:22 +00:00
|
|
|
|
WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
|
2001-07-27 20:27:58 +00:00
|
|
|
|
if (random() > 0.5)
|
2001-10-13 23:02:22 +00:00
|
|
|
|
WriteByte (MSG_MULTICAST, TE_LIGHTNING2);
|
2001-07-27 20:27:58 +00:00
|
|
|
|
else
|
2001-10-13 23:02:22 +00:00
|
|
|
|
WriteByte (MSG_MULTICAST, TE_LIGHTNING1);
|
|
|
|
|
WriteEntity (MSG_MULTICAST, tfield);
|
|
|
|
|
WriteCoord (MSG_MULTICAST, f_x);
|
|
|
|
|
WriteCoord (MSG_MULTICAST, f_y);
|
|
|
|
|
WriteCoord (MSG_MULTICAST, tfield.origin_z + tfield.mins_z);
|
|
|
|
|
WriteCoord (MSG_MULTICAST, f_x);
|
|
|
|
|
WriteCoord (MSG_MULTICAST, f_y);
|
|
|
|
|
WriteCoord (MSG_MULTICAST, tfield.origin_z + tfield.maxs_z);
|
2001-07-27 20:27:58 +00:00
|
|
|
|
}
|
2001-07-17 05:58:10 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//==================================================
|
|
|
|
|
// called every frame by the field generators
|
|
|
|
|
|
|
|
|
|
void() FieldGen_think =
|
|
|
|
|
{
|
2001-07-27 20:27:58 +00:00
|
|
|
|
local entity othergen;
|
|
|
|
|
othergen = Find_OtherGen(self); // get our brother
|
|
|
|
|
|
|
|
|
|
if (FieldGens_CanLink(self,othergen))
|
|
|
|
|
Create_Field(self,othergen); // checks redundancy itself
|
|
|
|
|
else
|
|
|
|
|
Remove_Field(self,othergen); // checks redundancy itself
|
|
|
|
|
|
|
|
|
|
// field main loop (ai? heh.. my cat is smarter than these force fields)
|
|
|
|
|
if (self.fieldgen_status == FIELDGEN_ISOFF) // for some reason we r not working
|
|
|
|
|
{
|
|
|
|
|
self.effects = 0;
|
|
|
|
|
self.skin = 0;
|
|
|
|
|
|
|
|
|
|
if (FieldGen_CanIdle(self)) // can we go idle?
|
|
|
|
|
self.fieldgen_status = FIELDGEN_ISIDLE;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
else if (self.fieldgen_status == FIELDGEN_ISIDLE) // awaiting for link
|
|
|
|
|
{
|
|
|
|
|
self.effects = 0;
|
|
|
|
|
self.skin = 0;
|
|
|
|
|
|
|
|
|
|
if (self.no_grenades_1 < time) // trying to link sound/flash time
|
|
|
|
|
{
|
|
|
|
|
sound (self, CHAN_WEAPON, "misc/fffail.wav", 0.5, ATTN_IDLE);
|
|
|
|
|
self.skin = 1;
|
|
|
|
|
self.effects = EF_DIMLIGHT;
|
|
|
|
|
self.no_grenades_1 = time + FIELDGEN_LINKTIME;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
else if (self.fieldgen_status == FIELDGEN_ISDISABLED) // teammate passing thru the field?
|
|
|
|
|
{
|
|
|
|
|
self.effects = 0;
|
|
|
|
|
self.skin = 0;
|
|
|
|
|
|
|
|
|
|
// time check
|
|
|
|
|
if (self.no_grenades_2 < time) // can we go idle?
|
|
|
|
|
{
|
|
|
|
|
self.fieldgen_status = FIELDGEN_ISIDLE;
|
|
|
|
|
self.tp_grenades_1 = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
else if (self.fieldgen_status == FIELDGEN_ISENABLED)
|
|
|
|
|
{
|
|
|
|
|
if (!self.has_teleporter)
|
|
|
|
|
{
|
|
|
|
|
self.effects = 0;
|
|
|
|
|
self.skin = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (self.fieldgen_hasfield == FALSE)
|
|
|
|
|
self.fieldgen_status = FIELDGEN_ISIDLE;
|
|
|
|
|
|
|
|
|
|
if (self.tp_grenades_1 >= time)
|
|
|
|
|
self.fieldgen_status = FIELDGEN_ISWORKING;
|
|
|
|
|
}
|
|
|
|
|
else if (self.fieldgen_status == FIELDGEN_ISWORKING)
|
|
|
|
|
{
|
|
|
|
|
self.effects = EF_DIMLIGHT;
|
|
|
|
|
self.skin = 2;
|
|
|
|
|
|
|
|
|
|
if (self.has_camera <= time)
|
|
|
|
|
{
|
|
|
|
|
self.ammo_cells = self.ammo_cells - FIELDGEN_CELLSCOST;
|
|
|
|
|
self.has_camera = time + 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (self.fieldgen_hasfield == FALSE)
|
|
|
|
|
self.fieldgen_status = FIELDGEN_ISIDLE;
|
|
|
|
|
else if (self.tp_grenades_1 <= time)
|
|
|
|
|
self.fieldgen_status = FIELDGEN_ISENABLED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Field_UpdateSounds(self.fieldgen_field, self); // update force field sounds
|
|
|
|
|
|
|
|
|
|
if (!FieldGen_CanIdle(self)) // turn us off if needed
|
|
|
|
|
self.fieldgen_status = FIELDGEN_ISOFF;
|
2001-07-17 05:58:10 +00:00
|
|
|
|
|
2001-07-27 20:27:58 +00:00
|
|
|
|
self.has_teleporter = FALSE; // resets 'flash' status bypass
|
|
|
|
|
self.nextthink = time + 0.1;
|
2001-07-17 05:58:10 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//=======================================================================
|
|
|
|
|
// returns TRUE if the generator could currently go to idle status
|
|
|
|
|
|
|
|
|
|
float(entity fieldgen) FieldGen_CanIdle =
|
|
|
|
|
{
|
2001-07-27 20:27:58 +00:00
|
|
|
|
if (!(IsValidFieldGen(fieldgen)))
|
|
|
|
|
return FALSE;
|
2001-07-17 05:58:10 +00:00
|
|
|
|
|
2001-07-27 20:27:58 +00:00
|
|
|
|
if (fieldgen.ammo_cells >= FIELDGEN_CELLSCOST &&
|
|
|
|
|
!(fieldgen.is_malfunctioning & SCREWUP_FOUR)
|
|
|
|
|
&& fieldgen.health > 0)
|
|
|
|
|
return TRUE;
|
2001-07-17 05:58:10 +00:00
|
|
|
|
|
2001-07-27 20:27:58 +00:00
|
|
|
|
return FALSE;
|
2001-07-17 05:58:10 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//=======================================================================
|
|
|
|
|
// returns TRUE if both generators could currently generate the field
|
|
|
|
|
|
|
|
|
|
float(entity fieldgen1, entity fieldgen2) FieldGens_CanLink =
|
|
|
|
|
{
|
2001-07-27 20:27:58 +00:00
|
|
|
|
if (!(IsValidFieldGen(fieldgen1)) || !(IsValidFieldGen(fieldgen2)))
|
|
|
|
|
return FALSE;
|
2001-07-17 05:58:10 +00:00
|
|
|
|
|
2001-07-27 20:27:58 +00:00
|
|
|
|
if (!visible2(fieldgen1,fieldgen2))
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
local float r;
|
|
|
|
|
r = vlen(fieldgen1.origin - fieldgen2.origin); // get distance between generators
|
2001-07-17 05:58:10 +00:00
|
|
|
|
|
2001-07-27 20:27:58 +00:00
|
|
|
|
// if ((fieldgen1.num_mines & IMPROVED_FOUR && fieldgen2.num_mines & IMPROVED_FOUR) && r > FIELDGEN_HACKEDRANGE2)
|
|
|
|
|
// return FALSE;
|
2001-07-17 05:58:10 +00:00
|
|
|
|
|
2001-07-27 20:27:58 +00:00
|
|
|
|
/*if (fieldgen1.num_mines & IMPROVED_FOUR || fieldgen2.num_mines & IMPROVED_FOUR)
|
|
|
|
|
{
|
|
|
|
|
if ((fieldgen1.num_mines & IMPROVED_FOUR && fieldgen2.num_mines & IMPROVED_FOUR) && r > FIELDGEN_HACKEDRANGE2)
|
|
|
|
|
return FALSE;
|
|
|
|
|
else
|
|
|
|
|
if ((fieldgen1.num_mines & IMPROVED_FOUR || fieldgen2.num_mines & IMPROVED_FOUR) && r > FIELDGEN_HACKEDRANGE)
|
|
|
|
|
return FALSE;
|
|
|
|
|
}*/
|
|
|
|
|
|
|
|
|
|
if ((fieldgen1.num_mines & IMPROVED_FOUR || fieldgen2.num_mines & IMPROVED_FOUR) && r > FIELDGEN_HACKEDRANGE)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
if (r > FIELDGEN_RANGE && !(fieldgen1.num_mines & IMPROVED_FOUR || fieldgen2.num_mines & IMPROVED_FOUR))
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
2001-08-12 12:40:29 +00:00
|
|
|
|
if (fabs(fieldgen1.origin_z - fieldgen2.origin_z) > FIELDGEN_MAXZ)
|
2001-07-27 20:27:58 +00:00
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
if (fieldgen1.fieldgen_status == FIELDGEN_ISDISABLED || fieldgen2.fieldgen_status == FIELDGEN_ISDISABLED)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
if (fieldgen1.fieldgen_status == FIELDGEN_ISOFF || fieldgen2.fieldgen_status == FIELDGEN_ISOFF)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
if (FieldGen_CanIdle(fieldgen1) && FieldGen_CanIdle(fieldgen2))
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
|
|
return FALSE;
|
2001-07-17 05:58:10 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//=============================================================================================
|
|
|
|
|
// initialize field generator stuff just after beeing built, called on engineer.qc
|
|
|
|
|
|
|
|
|
|
void(entity field) Field_Built =
|
|
|
|
|
{
|
2001-10-17 07:48:11 +00:00
|
|
|
|
field.touch = NIL;
|
2001-07-27 20:27:58 +00:00
|
|
|
|
field.think = FieldGen_think;
|
|
|
|
|
field.nextthink = time + 0.1;
|
|
|
|
|
field.fieldgen_status = FIELDGEN_ISIDLE; // we start on IDLE status (searching for other gen to link)
|
|
|
|
|
field.fieldgen_hasfield = FALSE;
|
|
|
|
|
field.no_grenades_1 = time + 3;
|
2001-11-02 17:00:52 +00:00
|
|
|
|
field.fieldgen_field = NIL;
|
|
|
|
|
field.martyr_enemy = NIL;
|
2001-07-17 05:58:10 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//==============================================================
|
|
|
|
|
// returns our other generator (if any)
|
|
|
|
|
|
|
|
|
|
entity(entity fieldgen) Find_OtherGen =
|
|
|
|
|
{
|
2001-07-27 20:27:58 +00:00
|
|
|
|
local entity te;
|
|
|
|
|
local float foundit;
|
2001-11-02 17:00:52 +00:00
|
|
|
|
te = NIL;
|
2001-07-27 20:27:58 +00:00
|
|
|
|
foundit = FALSE;
|
|
|
|
|
|
2001-11-02 17:00:52 +00:00
|
|
|
|
te = find(NIL, classname, "building_fieldgen");
|
|
|
|
|
while (te && foundit == FALSE)
|
2001-07-27 20:27:58 +00:00
|
|
|
|
{
|
|
|
|
|
if (te.real_owner == fieldgen.real_owner) // is it ours?
|
|
|
|
|
if (te != fieldgen) // and not the same generator..
|
|
|
|
|
foundit = TRUE; // yeah, found it
|
|
|
|
|
|
|
|
|
|
if (foundit == FALSE) // our search must continue...
|
|
|
|
|
te = find(te, classname, "building_fieldgen");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return te;
|
2001-07-17 05:58:10 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//=========================================================================================
|
|
|
|
|
// returns the place where field gen could be built related to player current pos and yaw
|
|
|
|
|
// called on engineer.qc, place is the origin passed where other kind of buildings are built
|
2001-08-12 12:40:29 +00:00
|
|
|
|
// FIXME: changed to allow placing anywhere. comments need updating
|
2001-07-17 05:58:10 +00:00
|
|
|
|
|
2001-08-12 12:40:29 +00:00
|
|
|
|
void (vector place) WhereGen =
|
2001-07-17 05:58:10 +00:00
|
|
|
|
{
|
2001-07-27 20:27:58 +00:00
|
|
|
|
// if we have no field generator currently, it can be placed anywhere
|
2001-08-12 12:40:29 +00:00
|
|
|
|
if (self.has_fieldgen == 0)
|
|
|
|
|
return;
|
2001-07-27 20:27:58 +00:00
|
|
|
|
|
2001-08-12 12:40:29 +00:00
|
|
|
|
local float r, foundit;
|
2001-11-02 17:00:52 +00:00
|
|
|
|
local entity te = NIL;
|
2001-07-27 20:27:58 +00:00
|
|
|
|
|
|
|
|
|
foundit = FALSE;
|
|
|
|
|
|
|
|
|
|
// find the other generator
|
2001-08-12 12:40:29 +00:00
|
|
|
|
do {
|
|
|
|
|
te = find (te, classname, "building_fieldgen");
|
|
|
|
|
if (te.real_owner == self)
|
|
|
|
|
foundit = TRUE;
|
2001-11-02 17:00:52 +00:00
|
|
|
|
} while (te && foundit == FALSE);
|
2001-08-12 12:40:29 +00:00
|
|
|
|
/*
|
2001-11-02 17:00:52 +00:00
|
|
|
|
te = find (NIL, classname, "building_fieldgen");
|
|
|
|
|
while (te && foundit == FALSE)
|
2001-07-27 20:27:58 +00:00
|
|
|
|
{
|
|
|
|
|
if (te.real_owner == self) // is it ours?
|
|
|
|
|
foundit = TRUE; // yeah, found it
|
|
|
|
|
|
|
|
|
|
if (foundit == FALSE) // our search must continue...
|
2001-08-12 12:40:29 +00:00
|
|
|
|
te = find (te, classname, "building_fieldgen");
|
|
|
|
|
}*/
|
2001-07-27 20:27:58 +00:00
|
|
|
|
|
|
|
|
|
// check for error getting the other gen
|
2001-11-02 17:00:52 +00:00
|
|
|
|
if (!te || te.classname != "building_fieldgen" || foundit == FALSE)
|
2001-07-27 20:27:58 +00:00
|
|
|
|
{
|
|
|
|
|
RPrint("BUG: Error on field generator placement routine. 'WhereGen()'\n");
|
2001-08-12 12:40:29 +00:00
|
|
|
|
return;
|
2001-07-27 20:27:58 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// print message if they wont link
|
2001-08-12 12:40:29 +00:00
|
|
|
|
if (!vis2orig (te.origin,place))
|
|
|
|
|
sprint (self, PRINT_HIGH,
|
|
|
|
|
"Your field generators won't link, there are obstacles between them!\n");
|
2001-07-27 20:27:58 +00:00
|
|
|
|
|
2001-08-12 12:40:29 +00:00
|
|
|
|
r = vlen(te.origin - place); // get distance between generators
|
|
|
|
|
|
|
|
|
|
if (r > FIELDGEN_HACKEDRANGE && te.num_mines & IMPROVED_FOUR)
|
|
|
|
|
sprint (self, PRINT_HIGH,
|
|
|
|
|
"Your field generators are too far away to link, even hacked\n");
|
2001-07-27 20:27:58 +00:00
|
|
|
|
|
|
|
|
|
if (r > FIELDGEN_RANGE && !(te.num_mines & IMPROVED_FOUR))
|
2001-08-12 12:40:29 +00:00
|
|
|
|
sprint (self, PRINT_HIGH,
|
|
|
|
|
"Your field generators are too far away to link\n");
|
|
|
|
|
|
|
|
|
|
if (fabs (place_z - te.origin_z) > FIELDGEN_MAXZ)
|
|
|
|
|
sprint (self, PRINT_HIGH,
|
|
|
|
|
"Your field generators are at different heights, they won't link\n");
|
2001-07-27 20:27:58 +00:00
|
|
|
|
|
|
|
|
|
// return the final building place
|
2001-08-12 12:40:29 +00:00
|
|
|
|
return;
|
2001-07-17 05:58:10 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//======================================================================
|
|
|
|
|
// damn! our field generator was destroyed. Force field must go down..
|
|
|
|
|
|
|
|
|
|
void() FieldGen_Die =
|
|
|
|
|
{
|
2001-07-27 20:27:58 +00:00
|
|
|
|
self.real_owner.has_fieldgen = self.real_owner.has_fieldgen - 1;
|
|
|
|
|
if (self.real_owner.has_fieldgen < 0) self.real_owner.has_fieldgen = 0;
|
2001-07-17 05:58:10 +00:00
|
|
|
|
|
2001-10-13 23:02:22 +00:00
|
|
|
|
WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
|
|
|
|
|
WriteByte (MSG_MULTICAST, TE_EXPLOSION);
|
|
|
|
|
WriteCoord (MSG_MULTICAST, self.origin_x);
|
|
|
|
|
WriteCoord (MSG_MULTICAST, self.origin_y);
|
|
|
|
|
WriteCoord (MSG_MULTICAST, self.origin_z);
|
2001-07-23 20:52:47 +00:00
|
|
|
|
multicast (self.origin, MULTICAST_PHS);
|
2001-07-17 05:58:10 +00:00
|
|
|
|
|
2001-07-27 20:27:58 +00:00
|
|
|
|
// check if field should be removed..
|
|
|
|
|
local entity othergen;
|
|
|
|
|
othergen = Find_OtherGen(self);
|
|
|
|
|
if (IsValidFieldGen(othergen))
|
|
|
|
|
{
|
|
|
|
|
Remove_Field(self, othergen);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2001-11-02 17:00:52 +00:00
|
|
|
|
Remove_Field(self, NIL); // extra removal, not needed i think...
|
2001-07-27 20:27:58 +00:00
|
|
|
|
}
|
2001-07-17 05:58:10 +00:00
|
|
|
|
|
2001-07-27 20:27:58 +00:00
|
|
|
|
sprint(self.real_owner, PRINT_HIGH, "Your field generator was destroyed.\n");
|
2001-07-17 05:58:10 +00:00
|
|
|
|
|
2001-07-27 20:27:58 +00:00
|
|
|
|
//TODO: gibs, one of the tesla, one custom
|
2001-07-17 05:58:10 +00:00
|
|
|
|
|
2001-07-27 20:27:58 +00:00
|
|
|
|
dremove(self);
|
2001-07-17 05:58:10 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//=========================================================================
|
|
|
|
|
// Engineer has used a Spanner on the field generator
|
|
|
|
|
|
|
|
|
|
void(entity field) Engineer_UseFieldGen =
|
|
|
|
|
{
|
|
|
|
|
self.building = field;
|
2001-07-27 20:27:58 +00:00
|
|
|
|
|
|
|
|
|
if (Teammate(self.building.real_owner.team_no,self.team_no) && self.building.is_malfunctioning & SCREWUP_THREE)
|
|
|
|
|
{
|
|
|
|
|
//if (self.building.is_malfunctioning & SCREWUP_FOUR)
|
|
|
|
|
//{
|
|
|
|
|
sprint(self,PRINT_HIGH,"Trapped field generator, have a nice day!\n");
|
|
|
|
|
|
|
|
|
|
deathmsg = DMSG_FGTRAP;
|
1) Attempted to give players positive frags whenever possible. You now
should get frags for blowing people up with others' dispensers/mines/expbody,
airfisting rockets, etc.
2) Redid Give_Frags_Out
3) Changed many uses of pointcontents and ugly hacks to use hullpointcontents
and checkmove, now a lot cleaner and less buggy
4) You can grapple builds again. This caused really odd bugs.
5) You can now damage your own buildings again (gasp). Any time a tesla or sentry
is damaged it turns on its attacker, friendly or otherwise. This is both a counter-TK
and counter-spy mechanism.
6) Teslas are now entirely inside their bounding box
7) Now check every frame for players startsolid and for outside of the map cube.
8) #define WALL_HURT to make it hurt when you hit a wall
9) Used some cool ideas (aka laws of physics) to make the airfist a little less annoying
10) You now only get 1 mirv per slot without bandolier. Demoman and hwguy gain bandolier.
demoman loses his extra mirv but gains an extra grenade and pair of detpacks. Hwguy
gets extra grenade.
11) New and improved EMP grenade now does damage based on range. no longer blows up shells.
Doesn't directly damage sentries anymore, but does significant damage to dispensers.
EMP someone who's setting a det and it blows up in their face.
12) Players now do radius damage from getting EMPed (again)
13) EMPs now go through walls (again)
14) EMP number lowered by one (3 without, 4 with bandolier) and cost raised by $100
15) You can only have 2 frag grens, 3 with bandolier now.
16) Hover boots will now eat cells if they get low on charge. In addition, the silly bug
where their charge wasn't restored when you die is fixed now.
17) EMPing a detpack now sets its timer to anywhere between 1 and 121 seconds from current time,
with a logarithmic probability of it being lower. (random() * random() * 120 + 1). Also, probably
more time the closer it is to the EMP.
18) Judo can now be blocked by people with close combat, knife or judo. Blocked judo means that the
attacker loses 3 seconds of attack.
19) Judo missing now makes them unable to fire.
20) Shortened judo range (back to normal if w/ close combat)
21) Attempted to rework the railgun. Seems to be okay now.
Probably still a lot of bugs in here, but since this is the devel version I thought I would commit
all my changes so people could start testing it. I'll commit fixes as soon as I find the bugs.
2003-11-26 08:53:44 +00:00
|
|
|
|
//used to do radius damage
|
|
|
|
|
TF_T_Damage(self, self.building, self.building.martyr_enemy, FGTRAP_DMG, 0, TF_TD_ELECTRICITY);
|
2001-07-27 20:27:58 +00:00
|
|
|
|
return;
|
|
|
|
|
//}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
local entity dist_checker;
|
2001-07-17 05:58:10 +00:00
|
|
|
|
local string st;
|
|
|
|
|
|
2001-07-23 20:52:47 +00:00
|
|
|
|
sprint(self, PRINT_HIGH, "Field Generator has ");
|
2001-07-17 05:58:10 +00:00
|
|
|
|
st = ftos(field.health);
|
2001-07-23 20:52:47 +00:00
|
|
|
|
sprint(self, PRINT_HIGH, st);
|
2001-07-27 20:27:58 +00:00
|
|
|
|
sprint(self, PRINT_HIGH, "<EFBFBD>");
|
2001-07-17 05:58:10 +00:00
|
|
|
|
st = ftos(field.max_health);
|
2001-07-27 20:27:58 +00:00
|
|
|
|
sprint(self, PRINT_HIGH, st);
|
2001-07-23 20:52:47 +00:00
|
|
|
|
sprint(self, PRINT_HIGH, " <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, ");
|
2001-07-17 05:58:10 +00:00
|
|
|
|
st = ftos(field.ammo_cells);
|
2001-07-23 20:52:47 +00:00
|
|
|
|
sprint(self, PRINT_HIGH, st);
|
|
|
|
|
sprint(self, PRINT_HIGH, "<EFBFBD>");
|
2001-07-17 05:58:10 +00:00
|
|
|
|
st = ftos(field.maxammo_cells);
|
2001-07-27 20:27:58 +00:00
|
|
|
|
sprint(self, PRINT_HIGH, st);
|
2001-07-23 20:52:47 +00:00
|
|
|
|
sprint(self, PRINT_HIGH, " <20><><EFBFBD><EFBFBD><EFBFBD>\n");
|
2001-07-17 05:58:10 +00:00
|
|
|
|
|
2001-07-27 20:27:58 +00:00
|
|
|
|
// Pop up the menu
|
2001-07-23 20:52:47 +00:00
|
|
|
|
self.current_menu = MENU_ENGINEER_FIX_FIELDGEN;
|
|
|
|
|
self.menu_count = MENU_REFRESH_RATE;
|
2001-07-17 05:58:10 +00:00
|
|
|
|
|
|
|
|
|
//dodgy
|
|
|
|
|
if (teamplay != 0 && !Teammate(self.building.real_owner.team_no,self.team_no)) {
|
|
|
|
|
Menu_EngineerFix_FieldGen_Input(4);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Start a Distance checker, which removes the menu if the player
|
|
|
|
|
// gets too far away from the sentry.
|
|
|
|
|
dist_checker = spawn();
|
|
|
|
|
dist_checker.classname = "timer";
|
|
|
|
|
dist_checker.owner = self;
|
|
|
|
|
dist_checker.enemy = field;
|
|
|
|
|
dist_checker.think = CheckDistance;
|
|
|
|
|
dist_checker.nextthink = time + 0.3;
|
|
|
|
|
};
|