prozac-qfcc/engineer.qc
Finny Merrill db4e96e70a Engineer tweaks:
1) added checkmove forward so it's easier to build against walls
2) Can't build sentries on top of forcefields anymore (they get bounced off)
3) fieldgens are now one unit taller than their fields, so you CAN build on the gen
4) forcefields bounce everything (including buildings) away now.
5) added #ifdef DISALLOW_BLOCKED_TELE around tele block checks. didn't get the point

Debug tweaks:
1) added #ifdef DEBUG, which enables RPrint(), dremove(), and printtrace(), as well
   as the warlock cheat and origin reporting.
2) replaced EVERY dprint with RPrint.
3) changed makefile so that all = no DEBUG and no .sym
2003-11-27 07:07:26 +00:00

1614 lines
45 KiB
C++
Raw Blame History

/*======================================================
ENGINEER.QC Custom TeamFortress v3.1
(c) TeamFortress Software Pty Ltd 2/3/97
(c) William Kerney 4/14/00
(c) Craig Hauser 4/14/00
========================================================
Weapons and functions for the ENGINEER class and associated weaponry
=======================================================*/
#include "defs.qh"
#include "menu.qh"
float modelindex_tesla; //CH
// Weapon Functions
void() LaserBolt_Touch;
void() LaserBolt_Think;
void() W_FireLaser;
// EMP Grenade Functions
void() EMPExplode;
void() EMPGrenadeTouch;
void() EMPGrenadeExplode;
// Building Functions
void() TeamFortress_EngineerBuild;
void(float objtobuild) TeamFortress_Build;
void() TeamFortress_FinishedBuilding;
void() T_Dispenser;
void(entity atk, float dmg) Dispenser_Pain;
void() Dispenser_Die;
void(entity disp) Engineer_UseDispenser;
void(entity gun) Engineer_UseSentryGun;
void(entity cam) Engineer_UseCamera;
void() CheckDistance;
//WK
void() Sentry_Touch;
float(float myteam) HasFlag;
//- OfN
void(entity field) Field_Built;
//=========================================================================
// Laserbolt think function
void() LaserBolt_Think =
{
if (time > self.heat) {
if (self.demon_one)
dremove(self.demon_one);
dremove(self);
return;
}
self.velocity = self.oldorigin;
if (!self.demon_one) {
newmis = spawn();
setorigin(newmis, self.origin);
setsize(newmis, '0 0 0', '0 0 0');
setmodel(newmis, "");
newmis.solid = SOLID_TRIGGER;
newmis.movetype = MOVETYPE_FLYMISSILE;
newmis.touch = LaserBolt_Touch;
newmis.real_owner = self.owner;
newmis.owner = self;
newmis.heat = self.heat;
self.demon_one = newmis;
}
setorigin(self.demon_one, self.origin);
self.demon_one.velocity = self.velocity;
self.movetype = MOVETYPE_NOCLIP;
self.nextthink = time + 0.1;
self.think = LaserBolt_Think;
};
//=========================================================================
// Laserbolt touch function. Just moves through the player and comes out
// the other side.
void() LaserBolt_Touch =
{
local vector org;
if (time > self.heat) {
dremove(self.owner);
dremove(self);
return;
}
if (pointcontents(self.origin)==CONTENTS_SKY) {
dremove(self.owner);
dremove(self);
return;
}
if (other.classname == "force_field") { // ff can block rails, but not easily, loses cells
other.demon_one.ammo_cells -= 15;
other.demon_two.ammo_cells -= 15;
if (other.demon_one.ammo_cells < 0)
other.demon_one.ammo_cells = 0;
if (other.demon_two.ammo_cells < 0)
other.demon_two.ammo_cells = 0;
FieldExplosion(other, self.origin, self);
PutFieldWork(other);
dremove(self.owner);
dremove(self);
return;
}
if (other == self.real_owner || other == self.enemy)
return; // don't explode on same person twice
self.enemy = other;
//WK Sweep mines at point of impact
GuerillaMineSweep(self.origin);
org = self.origin - 8*normalize(self.velocity);
if (other && other.takedamage)
{
SpawnBlood (org, 15);
deathmsg = DMSG_LASERBOLT;
TF_T_Damage (other, self, self.real_owner, 25, 0, TF_TD_NAIL); // was electricity... WTF?
setmodel(self.owner, "progs/e_spike2.mdl");
}
};
//=========================================================================
// Fire a laserbolt
void() W_FireLaser =
{
local vector vec, org;
self.currentammo = self.ammo_nails = self.ammo_nails - 1;
makevectors(self.v_angle);
org = self.origin + (v_forward * 8);
vec = aim(self, 10000);
vec = normalize(vec);
newmis = spawn();
newmis.owner = self;
newmis.enemy = NIL; // The real owner GR uh no
newmis.movetype = MOVETYPE_NOCLIP; //was noclip. Oh well.
newmis.solid = SOLID_TRIGGER;
setmodel (newmis, "progs/e_spike1.mdl");
setsize (newmis, '0 0 0', '0 0 0');
setorigin (newmis, org + '0 0 16');
newmis.velocity = '0 0 0';
newmis.oldorigin = vec*800;
newmis.angles = vectoangles(newmis.oldorigin);
newmis.heat = time + 5;
newmis.nextthink = time + 0.1;
newmis.think = LaserBolt_Think;
};
//=========================================================================
// Ammo/Weapon exploded by the EMP grenade
void() EMPExplode =
{
local float expsize;
expsize = 10;
// Weapon?
if (self.touch == weapon_touch)
expsize = 60;
else if (self.classname == "item_shells")
expsize = 50 + self.aflag;
else if (self.classname == "item_spikes")
expsize = 40;
else if (self.classname == "item_rockets")
expsize = 100 + (self.aflag * 4);
else if (self.classname == "item_cells")
expsize = 100 + (self.aflag * 3);
else if (self.classname == "item_weapon")
expsize = 60;
else
{
RPrint("EMPExplode: Attempting to explode a ");
RPrint(self.classname);
RPrint("\n");
return;
}
deathmsg = DMSG_GREN_EMP_AMMO;
T_RadiusDamage (self, self.enemy, expsize, NIL);
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);
multicast (self.origin, MULTICAST_PHS);
// Respawn
Respawn_Item(self, self.enemy);
};
//=========================================================================
// Touch Function for EMP Grenade
void() EMPGrenadeTouch =
{
// If the EMP Grenade hits a player, it just bounces off
sound (self, CHAN_WEAPON, "weapons/bounce.wav", 1, ATTN_NORM);
if (self.velocity == '0 0 0')
self.avelocity = '0 0 0';
};
//=========================================================================
// EMP Scrambling effect (on players and buildings
void() EMPScramble =
{
#if 0
te = findradius(self.origin, 500);
while (te)
{
local float dist = vlen(te.origin - self.origin);
local float mult = 0.25 + (0.65 * dist / 500) + 0.15 * random();
te = te.chain;
}
#endif
dremove(self);
};
//=========================================================================
// EMP Grenade explode function, for when the PRIMETIME runs out
void() EMPGrenadeExplode =
{
local float expsize;
local entity te, oldself;
local float total_exp;
local float dist, mult;
//CH Slice gave idea of an emp gren getting rated based on blast so i added..
total_exp = 0;
WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
WriteByte (MSG_MULTICAST, TE_TAREXPLOSION);
WriteCoord (MSG_MULTICAST, self.origin_x);
WriteCoord (MSG_MULTICAST, self.origin_y);
WriteCoord (MSG_MULTICAST, self.origin_z);
multicast (self.origin, MULTICAST_PHS);
// Find all ammo in the area
te = findradius(self.origin, 300); // was 240
while (te)
{
dist = vlen(self.origin - te.origin);
mult = 0.85 - (0.65 * dist / 300) + (0.15 * random());
if (te.touch == ammo_touch || te.touch == weapon_touch) // Ammo/Weapon?
{
// Make sure it isn't picked up in the next second
te.solid = SOLID_NOT;
te.enemy = self.owner;
te.nextthink = time + 1 + (random() * 2);
te.think = EMPExplode;
}
// Detpack?
else if (te.think == TeamFortress_DetpackExplode)
{
//te.solid = SOLID_NOT;
local float rnd = (dist * (0.6 + random() * 0.4)) / 240;
te.nextthink = time + 1 + 120 * rnd*rnd; //chance of either exploding or lengthening timer
dremove(te.oldenemy); // Countdown ent
}
// Pipebomb?
else if (te.classname == "pipebomb")
{
te.nextthink = time + 0.1 + random();
}
// Mine/grenade?
else if (te.classname == "grenade")
{
if (te.netname == "land_mine")
te.think = GuerillaExplode;
te.nextthink = time + 0.1 + random();
}
// just hurt dispensers now
else if (te.classname == "building_dispenser") {
TF_T_Damage(te, self, self.owner, 300 - dist, 0, TF_TD_OTHER);
}
// Ammobox?
else if (te.classname == "ammobox")
{
expsize = 0;
expsize = expsize + (te.ammo_rockets * 3);
expsize = expsize + (te.ammo_cells * 0.75);
expsize *= mult;
if (expsize > 0)
{
te.solid = SOLID_NOT;
// Damage player and explode
deathmsg = DMSG_GREN_EMP;
total_exp = total_exp + expsize;
if (expsize > 300) //CH so they are not too powerfull //WK was 500
expsize = 300;
T_RadiusDamage (te, self.owner, expsize, te);
te.think = SUB_Remove;
te.nextthink = time + 0.1;
WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
WriteByte (MSG_MULTICAST, TE_EXPLOSION);
WriteCoord (MSG_MULTICAST, te.origin_x);
WriteCoord (MSG_MULTICAST, te.origin_y);
WriteCoord (MSG_MULTICAST, te.origin_z);
multicast (te.origin, MULTICAST_PHS);
}
}
// Backpack/Player?
else if ((te.classname == "player") || (te.classname=="monster_army") || (te.touch == BackpackTouch))
{
expsize = 0;
// calculate explosion size
expsize = expsize + te.ammo_rockets * 3; // ouch, this hurts
// < 200 cells for eng = metal, so don't explode
if (!(te.weapons_carried & WEAP_SPANNER) || te.touch == BackpackTouch)
expsize += te.ammo_cells;
else
expsize += ceil(te.ammo_cells * (1 - 200 / te.maxammo_cells));
if (te.classname == "player")
{
if (te.tp_grenades_1 == GR_TYPE_MIRV)
expsize += te.no_grenades_1 * 100; // arggh, lots of damage
if (te.tp_grenades_2 == GR_TYPE_MIRV)
expsize += te.no_grenades_2 * 100; // gotta get hwguys somehow
}
expsize *= mult;
if (te.is_detpacking || te.is_toffingadet) // detpack go off in yo face
expsize += 300;
if (expsize > 0)
{
// Damage player and explode
deathmsg = DMSG_GREN_EMP_RADIUS;
total_exp = total_exp + expsize;
//WK Make players not explode radially! GR why not?
if (te.touch != BackpackTouch)
{
T_RadiusDamage (te, self.owner, expsize * 0.5, te);
deathmsg = DMSG_GREN_EMP;
TF_T_Damage (te, te, self.owner, expsize, 0, TF_TD_EXPLOSION);
// Remove ammo
te.ammo_rockets = ceil(te.ammo_rockets * (1 - mult));
if (!(te.weapons_carried & WEAP_SPANNER))
te.ammo_cells = ceil(te.ammo_cells * (1 - mult));
else // cells under 200 max don't count for eng
{
te.ammo_cells *= 1 - 200 / te.maxammo_cells;
te.ammo_cells *= 1 - mult;
te.ammo_cells = ceil(te.ammo_cells * te.maxammo_cells / 200);
}
if (te.tp_grenades_1 == GR_TYPE_MIRV)
te.no_grenades_1 = ceil(te.no_grenades_1 *(1 - mult));
if (te.tp_grenades_2 == GR_TYPE_MIRV)
te.no_grenades_2 = ceil(te.no_grenades_2 * (1 - mult));
if (te.classname=="player")
{
// Update console
oldself = self;
self = te;
W_SetCurrentAmmo();
self = oldself;
WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
WriteByte (MSG_MULTICAST, TE_EXPLOSION);
WriteCoord (MSG_MULTICAST, te.origin_x);
WriteCoord (MSG_MULTICAST, te.origin_y);
WriteCoord (MSG_MULTICAST, te.origin_z);
multicast (te.origin, MULTICAST_PHS);
}
}
else
{
T_RadiusDamage(te, self.owner, expsize / 2, te);
if (te.classname != "player")
{
te.think = SUB_Remove;
te.nextthink = time + 0.1;
}
}
WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
WriteByte (MSG_MULTICAST, TE_EXPLOSION);
WriteCoord (MSG_MULTICAST, te.origin_x);
WriteCoord (MSG_MULTICAST, te.origin_y);
WriteCoord (MSG_MULTICAST, te.origin_z);
multicast (te.origin, MULTICAST_PHS);
}
}
te = te.chain;
}
sound (self, CHAN_WEAPON, "weapons/gren_emp.wav", 1, ATTN_NORM); //- OfN - cool sound! :)
if (total_exp > 0) {//CH Thanks Slice for the idea :)
sprint(self.owner,PRINT_HIGH, "Your EMP grenade inflicted ");
local string st;
st = ftos(total_exp);
sprint(self.owner,PRINT_HIGH, st);
sprint(self.owner,PRINT_HIGH, " damage\n");
}
#ifdef DEMO_STUFF
// Remove any camera's locks on this missile
if (self.enemy)
CamProjectileLockOff();
#endif
self.nextthink = time + 0.5;
self.think = EMPScramble;
self.movetype = MOVETYPE_NONE;
self.solid = SOLID_NOT;
setmodel(self, "");
setorigin(self, self.origin);
};
//=========================================================================
// Tests whether a team is allowed to build or not
float(float myteam) HasFlag =
{
if ( mapname != "steal4d" )
return TRUE;
if (myteam == team_with_flag){
return TRUE;
}
return FALSE;
};
//=========================================================================
// Function handling the Engineer's build impulse
void() TeamFortress_EngineerBuild =
{
local entity te;
// Can't build in the air
// WK Yes you can, why not? You can do it by pulling up this menu anyway
/*
if (!(self.flags & FL_ONGROUND))
{
CenterPrint(self, "You can't build in the air!\n\n");
return;
}
*/
if (self.is_detpacking == 1) {
CenterPrint(self, "You can't build while detpacking\n");
return;
}
if (self.is_feigning == 1) {
CenterPrint(self, "You can't build while feigning\n");
return;
}
// Pop up the menu
if (self.is_building == 0)
{
// Check to see if they've got enuf metal to build anything
if (self.ammo_cells < BUILD_COST_CAMERA && self.has_dispenser == FALSE && self.has_sentry == FALSE && self.has_tesla == FALSE && self.has_camera == FALSE && self.has_teleporter == FALSE && self.has_sensor == FALSE && self.has_fieldgen == FALSE)
{
CenterPrint(self, "You don't have enough metal to \nbuild anything.\n\n");
return;
}
self.current_menu = MENU_ENGINEER;
self.menu_count = MENU_REFRESH_RATE;
}
else if (self.is_building == 1)
{
sprint(self, PRINT_HIGH, "You stop building.\n");
self.is_building = 0;
self.tfstate = self.tfstate - (self.tfstate & TFSTATE_CANT_MOVE);
TeamFortress_SetSpeed(self);
// Remove the timer
te = find(NIL, netname, "build_timer");
while (te)
{
if (te.owner == self)
{
dremove(te);
te = NIL;
}
else
{
te = find(te, netname, "build_timer");
}
}
self.current_weapon = self.weapon;
W_SetCurrentAmmo();
}
};
float(entity obj, entity builder) CheckArea =
{
local integer pos;
// Check the hull
pos = entpointcontents(obj);
if (pos == CONTENTS_SOLID || pos == CONTENTS_SKY)
return FALSE;
// Trace a line from the player to the object too
traceline(builder.origin, obj.origin, TRUE, builder);
if (trace_fraction != 1)
return FALSE;
// may add in more checks later
return TRUE;
};
//////////////////////////////////////////////////////////////////////////
// rehashed version of TF_Build
void(float objtobuild) TeamFortress_Build =
{
local float btime = time - 0.1;
local entity obj;
obj = spawn();
// get an origin
makevectors(self.v_angle);
v_forward_z = 0;
v_forward = normalize(v_forward);
obj.origin = self.origin + v_forward * 35;
//WK Cheat Fix
if (self.is_feigning) {
sprint(self, PRINT_HIGH, "Try standing up first.\n");
return;
}
//OfN - Cheat Fix, heh
if (self.is_haxxxoring) {
sprint(self, PRINT_HIGH, "You can't build while hacking.\n");
return;
}
if (objtobuild == BUILD_DISPENSER)
{
if (self.has_dispenser)
{
sprint(self, PRINT_HIGH, "You can only have one dispenser.\nTry dismantling your old one.\n");
return;
}
if (!(self.cutf_items & CUTF_DISPENSER))
{
sprint(self, PRINT_HIGH, "You must buy the dispenser before you can build it.\n");
return;
}
obj.mins = '-8 -8 0';
obj.maxs = '8 8 40';
#ifdef no_new_dispenser
obj.mdl = "progs/disp.mdl";
#else
obj.mdl = "progs/disp2.mdl";
#endif
obj.netname = "dispenser";
btime = time + BUILD_TIME_DISPENSER;
}
else if (objtobuild == BUILD_SENTRYGUN)
{
if (self.has_sentry)
{
sprint(self, PRINT_HIGH, "You can only have one sentry gun.\nTry dismantling your old one.\n");
return;
}
if (!(self.cutf_items & CUTF_SENTRYGUN))
{
sprint(self, PRINT_HIGH, "You must buy a sentrygun before you can build one.\n");
return;
}
obj.mins = '-16 -16 0';
obj.maxs = '16 16 48';
//obj.mdl = "progs/turrbase.mdl";
obj.mdl = "progs/trrbs2.mdl";
obj.netname = "sentrygun";
btime = time + BUILD_TIME_SENTRYGUN;
}
else if (objtobuild == BUILD_TESLA)
{
if (self.has_tesla)
{
sprint(self, PRINT_HIGH, "You can only have one tesla gun.\nTry dismantling your old one.\n");
return;
}
if (!(self.tf_items & NIT_TESLA))
{
sprint(self, PRINT_HIGH, "You must buy a tesla sentry before you can build one.\n");
return;
}
// obj.mins = '-16 -16 0'; //- OfN commented by
obj.mins = '-16 -16 -25';
// obj.maxs = '16 16 48'; //WK 62 is better, but crashes?
obj.maxs = '16 16 62';
//obj.mdl = "progs/newtesla.mdl";
obj.mdl = "progs/coil.mdl";
obj.netname = "tesla";
// obj.origin = obj.origin + '0 0 25';
btime = time + BUILD_TIME_TESLA;
}
else if (objtobuild == BUILD_SECURITY_CAMERA)
{
if (self.has_camera)
{
sprint(self, PRINT_HIGH, "You can only have one security camera.\nTry dismantling your old one.\n");
return;
}
if (!(self.tf_items & NIT_SECURITY_CAMERA))
{
sprint(self, PRINT_HIGH, "You must buy a security camera before you can build one.\n");
return;
}
Security_Camera_Spawn();
}
else if (objtobuild == BUILD_TELEPORTER)
{
if (self.has_teleporter >= 2)
{
sprint(self, PRINT_HIGH, "You can only have 2 teleporters.\nTry dismantling an old one.\n");
return;
}
if (!(self.tf_items & NIT_TELEPORTER))
{
sprint(self, PRINT_HIGH, "You must buy a teleporter before you can build one.\n");
return;
}
obj.mins = '-16 -16 0';
obj.maxs = '16 16 4';
obj.mdl = "progs/telepad.mdl";
obj.netname = "teleporter";
btime = time + BUILD_TIME_TELEPORTER;
}
else if (objtobuild == BUILD_FIELDGEN)
{
if (self.has_fieldgen >= 2)
{
sprint(self, PRINT_HIGH, "You already have 2 field generators.\nTry dismantling an old one.\n");
return;
}
if (!(self.cutf_items & CUTF_FIELDGEN))
{
sprint(self, PRINT_HIGH, "You must buy a field generator before you can build one.\n");
return;
}
obj.mins = '-6 -6 0';
obj.maxs = '6 6 54';
obj.mdl = "progs/ffgen2.mdl";
obj.netname = "field generator";
btime = time + BUILD_TIME_FIELDGEN;
}
if (objtobuild == BUILD_SECURITY_CAMERA)
return;
local vector startpos, endpos;
startpos = obj.origin;
startpos_z = self.absmin_z - obj.mins_z + 60;
// build right up against the wall if there's a wall there
checkmove(startpos, obj.mins, obj.maxs, startpos + v_forward*30, MOVE_NORMAL, obj);
RPrint ("Builder origin: " + vtos(self.origin) + "\n");
RPrint ("First checkmove: ");
printtrace( 1 );
RPrint ("Distance from builder: ");
RPrint (ftos(vlen(trace_endpos - self.origin)));
RPrint ("\n");
startpos = trace_endpos;
endpos = obj.origin;
endpos_z = self.absmin_z - obj.mins_z - 40;
checkmove(startpos, obj.mins, obj.maxs, endpos, MOVE_NORMAL, obj);
RPrint("Second checkmove: ");
printtrace( 1 );
RPrint("Distance from builder: ");
RPrint(ftos(vlen(trace_endpos - self.origin)));
RPrint("\n");
if (trace_fraction == 1 && !trace_allsolid) {
sprint (self, PRINT_HIGH, "No buildable surfaces\n");
dremove (obj);
return;
}
if (trace_allsolid || trace_fraction == 0) {
sprint (self, PRINT_HIGH, "Not enough room to build\n");
dremove (obj);
return;
}
if (trace_ent.classname == "force_field") // make it collide with ff
trace_endpos_z--;
obj.origin = trace_endpos;
obj.flags = obj.flags | FL_ONGROUND;
obj.movetype = MOVETYPE_TOSS;
#ifdef DISALLOW_BLOCKED_TELE
if (objtobuild == BUILD_TELEPORTER) {
checkmove (obj.origin + '0 0 32', '-16 -16 -24', '16 16 32',
obj.origin + '0 0 30', MOVE_NOMONSTERS, self);
if (trace_startsolid || trace_fraction != 1) {
sprint (self, PRINT_HIGH, "Not enough room for teleportation\n");
dremove (obj);
return;
}
}
#endif
obj.owner = self;
obj.classname = "timer";
obj.netname = "build_timer";
obj.nextthink = btime;
obj.think = TeamFortress_FinishedBuilding;
obj.colormap = self.colormap;
obj.weapon = objtobuild;
obj.angles_y = anglemod(self.angles_y + 180);
obj.solid = SOLID_BBOX;
setmodel (obj, obj.mdl);
setsize (obj, obj.mins, obj.maxs);
setorigin (obj, obj.origin);
#ifdef DISALLOW_BLOCKED_TELE
if (objtobuild == BUILD_TELEPORTER)
if (Teleporter_CheckBlocked (obj)) {
sprint (self, PRINT_HIGH, "Not enough room for teleportation.\n");
dremove (obj);
return;
}
#endif
if (objtobuild==BUILD_TESLA)
{
obj.skin = self.team_no;
if (self.team_no==3) obj.skin=0;
else if (self.team_no==4) obj.skin=3;
}
self.is_building = 1;
makeImmune(self,time + 2);
//self.immune_to_check = time + 2;
self.tfstate = self.tfstate | TFSTATE_CANT_MOVE;
// Save the current weapon and remove it
self.weapon = self.current_weapon;
self.current_weapon = 0;
self.weaponmodel = "";
self.weaponframe = 0;
TeamFortress_SetSpeed(self);
if (objtobuild == BUILD_FIELDGEN)
WhereGen(obj.origin);
};
void() DispenserThink =
{
local float iI; // is Improved?
iI=1;
if (self.num_mines & IMPROVED_ONE)
iI=2;
// dispenser refilling itself 5%
if (!(self.is_malfunctioning & SCREWUP_THREE)) // SB
{
self.ammo_shells = self.ammo_shells + rint((BUILD_DISPENSER_MAX_SHELLS*iI) / 10);
self.ammo_cells = self.ammo_cells + rint((BUILD_DISPENSER_MAX_CELLS*iI) / 10);
self.ammo_nails = self.ammo_nails + rint((BUILD_DISPENSER_MAX_NAILS*iI) / 10);
self.ammo_rockets = self.ammo_rockets + rint((BUILD_DISPENSER_MAX_ROCKETS*iI) / 10);
self.armorvalue = self.armorvalue + rint((BUILD_DISPENSER_MAX_ARMOR*iI) / 10);
if (self.ammo_shells > BUILD_DISPENSER_MAX_SHELLS*iI)
self.ammo_shells = BUILD_DISPENSER_MAX_SHELLS*iI;
if (self.ammo_nails > BUILD_DISPENSER_MAX_NAILS*iI)
self.ammo_nails = BUILD_DISPENSER_MAX_NAILS*iI;
if (self.ammo_rockets > BUILD_DISPENSER_MAX_ROCKETS*iI)
self.ammo_rockets = BUILD_DISPENSER_MAX_ROCKETS*iI;
if (self.ammo_cells > BUILD_DISPENSER_MAX_CELLS*iI)
self.ammo_cells = BUILD_DISPENSER_MAX_CELLS*iI;
if (self.armorvalue > BUILD_DISPENSER_MAX_ARMOR*iI)
self.armorvalue = BUILD_DISPENSER_MAX_ARMOR*iI;
}
self.nextthink = time + 10;
};
void() TeamFortress_FinishedBuilding =
{
local entity oldself;
if (self.owner.is_building != 1)
return;
oldself = self;
self = self.owner;
oldself.owner = NIL;
oldself.real_owner = self;
self.is_building = 0;
self.tfstate = self.tfstate - (self.tfstate & TFSTATE_CANT_MOVE);
self.current_weapon = self.weapon;
self.StatusRefreshTime = time + 0.1;
TeamFortress_SetSpeed(self);
if (oldself.weapon == BUILD_DISPENSER)
{
self.has_dispenser = TRUE;
sprint (self, PRINT_HIGH, "You finish building the dispenser.\n");
teamprefixsprint(self.team_no,self); //- OfN
teamsprint(self.team_no, self, self.netname);
teamsprint(self.team_no, self, " has built a Dispenser.\n");
self.ammo_cells = self.ammo_cells - BUILD_COST_DISPENSER;
// Create the dispenser
oldself.classname = "building_dispenser";
oldself.netname = "dispenser";
oldself.blocked = T_Dispenser; // Actual touch function
oldself.touch = T_Dispenser;
oldself.max_health = BUILD_HEALTH_DISPENSER;
oldself.health = BUILD_HEALTH_DISPENSER;
oldself.think = DispenserThink;
oldself.nextthink = time + 5;
oldself.th_die = Dispenser_Die; // Death function
oldself.th_pain = Dispenser_Pain;
#ifdef no_new_dispenser
oldself.mdl = "progs/disp.mdl"; // Actual mdl
#else
oldself.mdl = "progs/disp2.mdl"; // Actual mdl
#endif
oldself.team_no = self.team_no;
oldself.num_mines=0; // OfN - reset HACKER improvements
oldself.real_owner = self; // The Engineer owns this item
oldself.colormap = self.colormap; // Set the Color
oldself.takedamage = DAMAGE_AIM;
oldself.owner = NIL;
// Put some ammo in the Dispenser
oldself.ammo_shells = ceil(self.ammo_shells * 0.25);
oldself.ammo_nails = ceil(self.ammo_nails * 0.25);
oldself.ammo_rockets = ceil(self.ammo_rockets * 0.25);
oldself.ammo_cells = ceil(self.ammo_cells * 0.25);
oldself.armorvalue = ceil(self.armorvalue * 0.25);
// Remove ours
self.ammo_shells = ceil(self.ammo_shells * 0.75);
self.ammo_nails = ceil(self.ammo_nails * 0.75);
self.ammo_rockets = ceil(self.ammo_rockets * 0.75);
self.ammo_cells = ceil(self.ammo_cells * 0.75);
self.armorvalue = ceil(self.armorvalue * 0.75);
oldself.solid = SOLID_BBOX;
setmodel(oldself, oldself.mdl);
}
else if (oldself.weapon == BUILD_SENTRYGUN)
{
//CH special sbar for eng.
self.StatusBarScreen = 1;
self.has_sentry = TRUE;
sprint (self, PRINT_HIGH, "You finish building the sentry gun.\n");
teamprefixsprint(self.team_no,self); //- OfN
teamsprint(self.team_no, self, self.netname);
teamsprint(self.team_no, self, " has built a Sentry Gun.\n");
oldself.classname = "building_sentrygun_base";
oldself.netname = "sentry gun";
oldself.takedamage = 0;
oldself.th_die = Sentry_Die; // Death function
self.ammo_cells = self.ammo_cells - BUILD_COST_SENTRYGUN;
setsize (oldself, '-16 -16 0', '16 16 4'); // '-16 -16 0' '16 16 4'
newmis = spawn();
newmis.classname = "building_sentrygun";
newmis.health = BUILD_HEALTH_SENTRYGUN;
newmis.max_health = newmis.health;
newmis.tf_items = NIT_KEVLAR; //Start with kevlar armor
newmis.armorclass = AT_SAVESHOT; //kevlar armor
newmis.weapon = 1; // Level 1 Turret
newmis.th_die = Sentry_Die; // Death function
newmis.th_pain = Sentry_Pain;
//newmis.mdl = "progs/turrgun.mdl";
newmis.mdl = "progs/trrgn2.mdl";
sound (oldself, CHAN_ITEM, "weapons/turrset.wav", 1, ATTN_NORM);
newmis.solid = SOLID_BBOX;
setmodel(newmis, newmis.mdl);
setsize (newmis, '-16 -16 4', '16 16 48'); //don't make it encompass the base
setorigin(newmis, oldself.origin + '0 0 8');
newmis.real_owner = oldself.real_owner; // The Engineer owns this item
newmis.trigger_field = oldself;
oldself.oldenemy = newmis;
newmis.movetype = MOVETYPE_STEP;
oldself.colormap = self.colormap; // Set the Base Color
newmis.colormap = self.colormap; // Set the Color
newmis.skin = self.team_no - 1;
newmis.takedamage = DAMAGE_AIM;
newmis.velocity = '0 0 -8';
newmis.frags = 0; //CH how many people has your sent killed?
newmis.team_no = self.team_no;
newmis.think = lvl1_sentry_stand;
newmis.nextthink = time + 0.5;
newmis.touch = Sentry_Touch;
// Rotate Details
newmis.yaw_speed = 10; //Turn rate
newmis.heat = 0; // Turn Right
newmis.angles_x = 0;
newmis.angles_y = ceil(oldself.angles_y); //CH remove decimal
newmis.angles_z = 0;
newmis.angles_y = ((ceil(newmis.angles_y / 10)) * 10); //CH set last int to 0
newmis.waitmin = anglemod(newmis.angles_y - 50);
newmis.waitmax = anglemod(newmis.angles_y + 50);
// Give the Gun some ammo
newmis.ammo_shells = 75; //WK
newmis.maxammo_shells = 100;
newmis.maxammo_rockets = 20;
newmis.num_mines=0; // OfN - reset HACKER improvements
newmis.attack_finished=time; //- controls time after loosing track of enemy to not be rotating
newmis.has_holo=0;
}
else if (oldself.weapon == BUILD_TESLA)
{
//CH special sbar for eng.
self.StatusBarScreen = 4;
self.has_tesla = TRUE;
sprint (self, PRINT_HIGH, "You finish building the tesla.\n");
teamprefixsprint(self.team_no,self); //- OfN
teamsprint(self.team_no, self, self.netname);
teamsprint(self.team_no, self, " has built a tesla.\n");
sound (oldself, CHAN_ITEM, "weapons/guerilla_set.wav", 1, ATTN_NORM);
oldself.classname = "building_tesla";
oldself.netname = "tesla";
oldself.takedamage = DAMAGE_AIM;
oldself.solid = SOLID_BBOX;
oldself.th_die = Tesla_Die; // Death function
oldself.th_pain = Tesla_Pain;
self.ammo_cells = self.ammo_cells - BUILD_COST_TESLA;
oldself.health = BUILD_HEALTH_TESLA;
oldself.movetype = MOVETYPE_TOSS;
oldself.colormap = self.colormap; // Set the Base Color
oldself.team_no = self.team_no;
//- OfN -
//oldself.think = Tesla_Idle;
oldself.think = tsla_on1;
//oldself.nextthink = time + 2;
oldself.nextthink = time + 0.1;
oldself.has_holo = time + 2; // next Tesla_Idle run
oldself.job = 0; // this flag will determine which frame animation is currently on
//oldself.job_finished = time; // change for frame animation purposes, instead of increasing its nextthing during charging
oldself.no_grenades_1 = FALSE; // first think reset
oldself.no_grenades_2 = 0; // cloak touch delay reset
oldself.touch = Tesla_Touch;
oldself.enemy = NIL;
oldself.oldenemy = NIL; //CH for sbar
//Set all initial tesla values here
oldself.maxammo_shells = 0; //Voltage == 0
oldself.maxammo_nails = 0; //Amps == 0
oldself.maxammo_rockets = 0; //Battery == 0
oldself.max_health = 150;
oldself.ammo_cells = MAXCELLS0; //Initial ammo allocation
oldself.maxammo_cells = MAXCELLS0; //Initial maxammo
oldself.tf_items = NIT_CERAMIC; //Start with shock armor
oldself.armorclass = AT_SAVEELECTRICITY; //Shock armor
if (self.tf_items & NIT_TESLA_UPGRADE) {
oldself.has_sentry = 6; //Normal Upgrades
oldself.has_tesla = 2; //Misc Upgrade
}
else
{
oldself.has_sentry = 4; //Normal Upgrades
oldself.has_tesla = 1; //Misc Upgrade
}
oldself.has_teleporter = 0; //CH for frag related upgrades
if (!(self.weapons_carried & WEAP_SPANNER)) { //No spanner
oldself.ammo_shells = 1;
oldself.ammo_nails = 2;
oldself.ammo_rockets = 1;
oldself.has_sentry = oldself.has_sentry - 4; //Take away 3
oldself.max_health = 225;
oldself.ammo_cells = MAXCELLS1; //Initial ammo allocation
oldself.maxammo_cells = MAXCELLS1;
}
oldself.health = oldself.max_health;
oldself.waitmin = (oldself.ammo_shells + 2) * (oldself.ammo_nails + 2);
oldself.waitmax = FALSE; //No target yet
oldself.frags = 0; //CH how many people has your sent killed?
oldself.lip = 0; //WK How many tinkers have been done
modelindex_tesla = oldself.modelindex; //CH
oldself.num_mines=0; // OfN - reset HACKER improvements
oldself.is_haxxxoring=0; // isnt flying
}
else if (oldself.weapon == BUILD_TELEPORTER)
{
self.has_teleporter = (self.has_teleporter + 1);
sprint (self, PRINT_HIGH, "You finish building the Teleporter Pad.\n");
teamprefixsprint(self.team_no,self); //- OfN
teamsprint(self.team_no, self, self.netname);
teamsprint(self.team_no, self, " has built a Teleporter Pad.\n");
sound (oldself, CHAN_ITEM, "weapons/guerilla_set.wav", 1, ATTN_NORM);
self.ammo_cells = self.ammo_cells - BUILD_COST_TELEPORTER;
// Create the teleporter
oldself.classname = "building_teleporter";
oldself.netname = "teleporter";
// oldself.blocked = Teleporter_touch; // Actual touch function
oldself.touch = Teleporter_touch;
oldself.max_health = BUILD_HEALTH_TELEPORTER;
oldself.health = BUILD_HEALTH_TELEPORTER;
oldself.th_die = Teleporter_Die; // Death function
oldself.mdl = "progs/telepad.mdl"; // Actual mdl
oldself.team_no = self.team_no;
oldself.maxammo_cells = 200; //CH Max of 20 teleports
oldself.ammo_cells = 100; //CH start not at full
oldself.real_owner = self; // The Engineer owns this item
oldself.colormap = self.colormap; // Set the Color
oldself.takedamage = DAMAGE_AIM;
oldself.owner = NIL;
oldself.movetype = MOVETYPE_TOSS;
oldself.solid = SOLID_BBOX;
setmodel(oldself, oldself.mdl);
setsize (oldself, '-16 -16 0', '16 16 4');
setorigin(oldself, oldself.origin); //CH does jump
oldself.heat = 4; //dont come on for 4 seconds
oldself.think = Teleporter_heat_think;
oldself.nextthink = time + 1;
oldself.spawnflags = 4; //CH cause extensive checks for height
oldself.num_mines=0; // OfN - reset HACKER improvements
}
else if (oldself.weapon == BUILD_FIELDGEN)
{
self.has_fieldgen = (self.has_fieldgen + 1);
sprint (self, PRINT_HIGH, "You finish building the Field Generator.\n");
teamprefixsprint(self.team_no,self); //- OfN
teamsprint(self.team_no, self, self.netname);
teamsprint(self.team_no, self, " has built a Field Generator.\n");
sound (oldself, CHAN_ITEM, "weapons/guerilla_set.wav", 1, ATTN_NORM);
self.ammo_cells = self.ammo_cells - BUILD_COST_FIELDGEN;
// Create the teleporter
oldself.classname = "building_fieldgen";
oldself.netname = "field generator";
// oldself.blocked = Teleporter_touch; // Actual touch function
//oldself.touch = Teleporter_touch;
oldself.max_health = BUILD_HEALTH_FIELDGEN;
oldself.health = BUILD_HEALTH_FIELDGEN;
oldself.th_die = FieldGen_Die; // Death function
oldself.mdl = "progs/ffgen2.mdl"; // Actual mdl
oldself.team_no = self.team_no;
oldself.maxammo_cells = 100; //CH Max of 20 field recharges
oldself.ammo_cells = 75; //CH start not at full*/
oldself.real_owner = self; // The Engineer owns this item
oldself.colormap = self.colormap; // Set the Color
oldself.takedamage = DAMAGE_AIM;
oldself.owner = NIL;
oldself.movetype = MOVETYPE_TOSS;
oldself.solid = SOLID_BBOX;
setmodel(oldself, oldself.mdl);
oldself.spawnflags = 4; //CH cause extensive checks for height
oldself.is_malfunctioning = 0;
oldself.num_mines=0; // OfN - reset HACKER improvements
Field_Built(oldself);
}
W_SetCurrentAmmo();
};
//=========================================================================
// Dispenser Touch function. Allows players to get stuff from the Dispenser.
void() T_Dispenser =
{
local entity dist_checker;
if (other.classname != "player")
return;
if (self.is_malfunctioning & SCREWUP_ONE)
return;
if (self.is_malfunctioning & SCREWUP_TWO)
TF_T_Damage(self, self, self, 200, 0, TF_TD_OTHER);
// Ignore any engineer working on this dispenser
if (!other.building && other.building_wait < time)
{
// Pop up the menu
other.current_menu = MENU_DISPENSER;
other.menu_count = MENU_REFRESH_RATE;
other.building = self;
// Start a Distance checker, which removes the menu if the player
// gets too far away from the Dispenser.
dist_checker = spawn();
dist_checker.classname = "timer";
dist_checker.owner = other;
dist_checker.enemy = self;
dist_checker.think = CheckDistance;
dist_checker.nextthink = time + 0.3;
}
};
//============================================================
// this is needed to avoid stack overflow
void() Dispenser_Explode =
{
T_RadiusDamage(self.demon_one, self.demon_one, self.has_holo, NIL);
WriteByte (MSG_MULTICAST, SVC_TEMPENTITY);
WriteByte (MSG_MULTICAST, TE_EXPLOSION);
WriteCoord (MSG_MULTICAST, self.demon_one.origin_x);
WriteCoord (MSG_MULTICAST, self.demon_one.origin_y);
WriteCoord (MSG_MULTICAST, self.demon_one.origin_z);
multicast (self.demon_one.origin, MULTICAST_PHS);
dremove(self.demon_one);
dremove(self); // remove explosion timer for this dispenser
};
void(entity atk, float dmg) Dispenser_Pain =
{
if (self.health < 0)
{
// give credit to the guy blowing up the disp
self.martyr_enemy = atk;
self.is_malfunctioning = 0;
}
};
void() Dispenser_Die =
{
local float damg;
self.real_owner.has_dispenser = FALSE;
damg = self.ammo_cells * 0.25;
damg = damg + self.ammo_nails * 0.1;
damg = damg + self.ammo_shells * 0.2;
damg = damg + self.ammo_rockets / 2;
//- OfN causes overflow so we need a timer for dispenser explosion
newmis = spawn();
newmis.has_holo = damg;
newmis.demon_one = self;
newmis.nextthink = time + 0.1;
newmis.think = Dispenser_Explode;
/*T_RadiusDamage(self, self, damg, NIL); // OfN - Fixme, stack overflow??*/
sprint(self.real_owner, PRINT_HIGH, "Your dispenser was destroyed.\n");
#ifdef no_new_dispenser
ThrowGib("progs/dgib1.mdl", -30);
ThrowGib("progs/dgib2.mdl", -50);
ThrowGib("progs/dgib3.mdl", -50);
#else
ThrowGib("progs/d2gib1.mdl", -30);
ThrowGib("progs/d2gib2.mdl", -50);
ThrowGib("progs/d2gib3.mdl", -50);
#endif
};
//=========================================================================
// Engineer has used a Spanner on the Dispenser
void(entity disp) Engineer_UseDispenser =
{
local entity dist_checker;
local string st;
// Print the dispenser's details
sprint (self, PRINT_HIGH, "Dispenser has ");
st = ftos(disp.health);
sprint(self, PRINT_HIGH, st);
sprint(self, PRINT_HIGH, "<EFBFBD>");
st = ftos(disp.max_health);
sprint(self, PRINT_HIGH, st);
sprint (self, PRINT_HIGH, " <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>\n");
st = ftos(disp.ammo_shells);
sprint (self, PRINT_HIGH, st);
sprint (self, PRINT_HIGH, " <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, ");
st = ftos(disp.ammo_nails);
sprint (self, PRINT_HIGH, st);
sprint (self, PRINT_HIGH, " <20><><EFBFBD><EFBFBD><EFBFBD>, ");
st = ftos(disp.ammo_rockets);
sprint (self, PRINT_HIGH, st);
sprint (self, PRINT_HIGH, " <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>\n");
st = ftos(disp.ammo_cells);
sprint (self, PRINT_HIGH, st);
sprint (self, PRINT_HIGH, " <20><><EFBFBD><EFBFBD><EFBFBD>, and ");
st = ftos(disp.armorvalue);
sprint (self, PRINT_HIGH, st);
sprint (self, PRINT_HIGH, " <20><><EFBFBD><EFBFBD><EFBFBD>\n");
// Pop up the menu
self.current_menu = MENU_ENGINEER_FIX_DISPENSER;
self.menu_count = MENU_REFRESH_RATE;
self.building = disp;
// Start a Distance checker, which removes the menu if the player
// gets too far away from the Dispenser.
dist_checker = spawn();
dist_checker.classname = "timer";
dist_checker.owner = self;
dist_checker.enemy = disp;
dist_checker.think = CheckDistance;
dist_checker.nextthink = time + 0.3;
};
//=========================================================================
// Engineer has used a Spanner on the SentryGun
void(entity gun) Engineer_UseSentryGun =
{
local entity dist_checker;
local string st;
// Print the gun's details
sprint(self, PRINT_HIGH, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ");
st = Return_Colored_Num(gun.weapon);
sprint(self, PRINT_HIGH, st);
sprint(self, PRINT_HIGH, " Sentry Gun has ");
st = ftos(gun.health);
sprint(self, PRINT_HIGH, st);
sprint(self, PRINT_HIGH, "<EFBFBD>");
st = ftos(gun.max_health);
sprint(self, PRINT_HIGH, st);
sprint(self, PRINT_HIGH, " <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, ");
st = ftos(gun.ammo_shells);
sprint(self, PRINT_HIGH, st);
sprint(self, PRINT_HIGH, " <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>");
if (gun.weapon == 3)
{
st = ftos(gun.ammo_rockets);
sprint(self, PRINT_HIGH, ", ");
sprint(self, PRINT_HIGH, st);
sprint(self, PRINT_HIGH, " <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>");
}
sprint(self, PRINT_HIGH, "\n");
sprint(self, PRINT_HIGH, "Sentry Gun <20><><EFBFBD><EFBFBD><EFBFBD>: "); //CH Displays kills of sent
st = ftos(gun.frags);
sprint(self, PRINT_HIGH, st);
sprint(self, PRINT_HIGH, "\n");
// Pop up the menu
self.current_menu = MENU_ENGINEER_FIX_SENTRYGUN;
self.menu_count = MENU_REFRESH_RATE;
self.building = gun;
//dodgy
if (teamplay != 0 && !Teammate(self.building.real_owner.team_no,self.team_no)) {
Menu_EngineerFix_SentryGun_Input(5);
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 = gun;
dist_checker.think = CheckDistance;
dist_checker.nextthink = time + 0.3;
};
////////////////////////////////////////////////
// Engineer has used a Spanner on the Tesla
void(entity gun) Engineer_UseTesla =
{
local entity dist_checker;
local string st;
// Print the gun's details
sprint(self, PRINT_HIGH, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:");
st = ftos(gun.health);
sprint(self, PRINT_HIGH, st);
sprint(self, PRINT_HIGH, "<EFBFBD>");
st = ftos(gun.max_health);
sprint(self, PRINT_HIGH, st);
sprint(self, PRINT_HIGH, " <20><><EFBFBD><EFBFBD><EFBFBD>:");
st = ftos(gun.ammo_cells);
sprint(self, PRINT_HIGH, st);
sprint(self, PRINT_HIGH, "<EFBFBD>");
st = ftos(gun.maxammo_cells);
sprint(self, PRINT_HIGH, st);
st = ftos(gun.has_sentry);
sprint(self, PRINT_HIGH, " <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Ups Left:");
sprint(self, PRINT_HIGH, st);
st = ftos(gun.has_tesla);
sprint(self, PRINT_HIGH, " <20><><EFBFBD><EFBFBD> Ups Left:");
sprint(self, PRINT_HIGH, st);
sprint(self, PRINT_HIGH, "\n");
sprint(self, PRINT_HIGH, "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:");
st = ftos(gun.ammo_shells);
sprint(self, PRINT_HIGH, st);
sprint(self, PRINT_HIGH, " <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:");
st = ftos(gun.ammo_nails);
sprint(self, PRINT_HIGH, st);
sprint(self, PRINT_HIGH, " <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:");
st = ftos(gun.ammo_rockets);
sprint(self, PRINT_HIGH, st);
sprint(self, PRINT_HIGH, "\n");
if (gun.tf_items) {
local float num;
num = 0;
if (gun.tf_items & NIT_TURRET) {
sprint(self, PRINT_HIGH, "TeslaTurret(tm). ");
num = num + 1;
}
if (gun.tf_items & NIT_SCANNER) {
sprint(self, PRINT_HIGH, "Improved Targeter. ");
num = num + 1;
}
if (gun.tf_items & NIT_AUTOID) {
sprint(self, PRINT_HIGH, "Spy Detector. ");
num = num + 1;
}
if (gun.tf_items & NIT_KEVLAR) {
sprint(self, PRINT_HIGH, "Kevlar Armor. ");
num = num + 1;
}
if (gun.tf_items & NIT_BLAST) {
sprint(self, PRINT_HIGH, "Blast Armor. ");
num = num + 1;
}
if (gun.tf_items & NIT_ASBESTOS) {
sprint(self, PRINT_HIGH, "Asbestos Armor. ");
num = num + 1;
}
if (gun.tf_items & NIT_TELEPORTER) {
sprint(self, PRINT_HIGH, "Upgrades from frags. ");
num = num + 1;
}
if (gun.tf_items & NIT_TESLA_CLOAKING) {
sprint(self, PRINT_HIGH, "Cloaking Device. ");
num = num + 1;
}
if (num != 0)
sprint(self, PRINT_HIGH, "\n");
}
sprint(self, PRINT_HIGH, "Tesla Sentry <20><><EFBFBD><EFBFBD><EFBFBD>: "); //CH Displays kills of tesla
st = ftos(gun.frags);
sprint(self, PRINT_HIGH, st);
sprint(self, PRINT_HIGH, "\n");
// Pop up the menu
self.current_menu = MENU_ENGINEER_FIX_TESLA;
self.menu_count = MENU_REFRESH_RATE;
self.building = gun;
// dodgy
if (teamplay != 0 && !Teammate(self.building.real_owner.team_no, self.team_no)) {
Menu_EngineerFix_Tesla_Input(8);
return;
}
// Start a Distance checker, which removes the menu if the player
// gets too far away from the tesla.
dist_checker = spawn();
dist_checker.classname = "timer";
dist_checker.owner = self;
dist_checker.enemy = gun;
dist_checker.think = CheckDistance;
dist_checker.nextthink = time + 0.3;
};
//=================
void(entity cam) Engineer_UseSensor =
{
local entity dist_checker;
local string st;
sprint(self, PRINT_HIGH, "Motion Sensor has ");
st = ftos(cam.health);
sprint(self, PRINT_HIGH, st);
sprint(self, PRINT_HIGH, "<EFBFBD>");
st = ftos(ceil(cam.max_health));
sprint(self, PRINT_HIGH, st);
sprint(self, PRINT_HIGH, " <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>\n");
// Pop up the menu
self.current_menu = MENU_ENGINEER_FIX_SENSOR;
self.menu_count = MENU_REFRESH_RATE;
self.building = cam;
if (teamplay != 0 && !Teammate(self.building.real_owner.team_no, self.team_no)) {
Menu_EngineerFix_Sensor_Input(3);
return;
}
// Start a Distance checker, which removes the menu if the player
// gets too far away from the camera.
dist_checker = spawn();
dist_checker.classname = "timer";
dist_checker.owner = self;
dist_checker.enemy = cam;
dist_checker.think = CheckDistance;
dist_checker.nextthink = time + 0.3;
};
//=================
void(entity cam) Engineer_UseCamera =
{
local entity dist_checker;
local string st;
sprint(self, PRINT_HIGH, "Security Camera has ");
st = ftos(cam.health);
sprint(self, PRINT_HIGH, st);
sprint(self, PRINT_HIGH, "<EFBFBD>");
st = ftos(ceil(cam.max_health));
sprint(self, PRINT_HIGH, st);
sprint(self, PRINT_HIGH, " <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>\n");
// Pop up the menu
self.current_menu = MENU_ENGINEER_FIX_CAMERA;
self.menu_count = MENU_REFRESH_RATE;
self.building = cam;
if (teamplay != 0 && !Teammate(self.building.real_owner.team_no,self.team_no)) {
Menu_EngineerFix_Camera_Input(3);
return;
}
// Start a Distance checker, which removes the menu if the player
// gets too far away from the camera.
dist_checker = spawn();
dist_checker.classname = "timer";
dist_checker.owner = self;
dist_checker.enemy = cam;
dist_checker.think = CheckDistance;
dist_checker.nextthink = time + 0.3;
};
//=================
void(entity tele) Engineer_UseTeleporter =
{
local entity dist_checker;
local string st;
sprint(self, PRINT_HIGH, "Teleporter Pad has ");
st = ftos(tele.health);
sprint(self, PRINT_HIGH, st);
sprint(self, PRINT_HIGH, "<EFBFBD>");
st = ftos(ceil(tele.max_health));
sprint(self, PRINT_HIGH, st);
sprint(self, PRINT_HIGH, " <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ");
st = ftos(tele.ammo_cells);
sprint(self, PRINT_HIGH, st);
sprint(self, PRINT_HIGH, "<EFBFBD>");
st = ftos(ceil(tele.maxammo_cells));
sprint(self, PRINT_HIGH, st);
sprint(self, PRINT_HIGH, " <20><><EFBFBD><EFBFBD><EFBFBD>\n");
// Pop up the menu
self.current_menu = MENU_ENGINEER_FIX_TELEPORTER;
self.menu_count = MENU_REFRESH_RATE;
self.building = tele;
if (teamplay != 0 && !Teammate(self.building.real_owner.team_no,self.team_no)) {
Menu_EngineerFix_Teleporter_Input(4);
return;
}
// Start a Distance checker, which removes the menu if the player
// gets too far away from the teleporter.
dist_checker = spawn();
dist_checker.classname = "timer";
dist_checker.owner = self;
dist_checker.enemy = tele;
dist_checker.think = CheckDistance;
dist_checker.nextthink = time + 0.3;
};
//=========================================================================
// Think function for the timer which checks the distance between the
// Engineer and the building he's using
void() CheckDistance =
{
local vector dist;
// Check to see if the Engineer's spanner'ed a different building
// without leaving the area of this one.
if (self.owner.building != self.enemy)
{
dremove(self);
return;
}
dist = self.enemy.origin - self.owner.origin;
//WK if (vlen(dist) > 64)
if (vlen(dist) > 98)
{
CenterPrint(self.owner, "\n");
self.owner.menu_count = MENU_REFRESH_RATE;
self.owner.current_menu = MENU_DEFAULT;
self.owner.building = NIL;
dremove(self);
return;
}
self.nextthink = time + 0.3;
};