prozac-qfcc/sentry.qc

808 lines
24 KiB
C++
Raw Normal View History

#include "defs.qh"
2001-07-17 05:58:10 +00:00
/*======================================================
SENTRY.QC Custom TeamFortress v2.1
(c) TeamFortress Software Pty Ltd 29/2/97
(c) William Kerney 21/10/99
(c) Craig Hauser 19/3/00
========================================================
Weapons and functions for the Sentry Guns
======================================================*/
// This is a temporary hack... they'll be replaced with real bots when
// the bot code is in (should that be if? :)
// WK If is right. :)
// SentryGun AI Functions
void() Sentry_Rotate;
float() Sentry_FindTarget;
void() Sentry_FoundTarget;
void() Sentry_HuntTarget;
void(entity attacker, float damage) Sentry_Pain;
2001-07-17 05:58:10 +00:00
void() Sentry_Die;
float() Sentry_Fire;
//WK - Will kill enemies on touch, and adds support for flying.
void() Sentry_Touch;
/* WK==============================================
#ifndef COOP_MODE
2001-07-17 05:58:10 +00:00
void() ai_face =
{
local vector temp_vect,temp_ang;
self.ideal_yaw = vectoyaw(self.enemy.origin - self.origin);
self.ideal_yaw = anglemod(self.ideal_yaw);
//WK Turrets swivel instanter
if (self.tf_items & NIT_TURRET) { //Auto-swivel
2001-07-17 05:58:10 +00:00
self.angles_y = self.ideal_yaw;
}
else
ChangeYaw ();
};
#endif
*/
//==============================================
$cd /quake/fortress/progs/turrgun
$origin 0 -6 24
$base base
$skin skin
$frame lvl1_stand1
$frame lvl1_shoot1 lvl1_shoot2
$frame lvl2_stand1
$frame lvl2_shoot1 lvl2_shoot2
$frame lvl3_stand1
$frame lvl3_shoot1 lvl3_shoot2
/* WK -- This is how you unhack the turret's position :<3A>
if (self.tf_items & NIT_TURRET) self.origin_z = self.origin_z + 40;
2001-07-17 05:58:10 +00:00
*/
void() RemoveGlow = {
self.effects = self.effects - (self.effects & EF_DIMLIGHT);
2001-07-17 05:58:10 +00:00
};
//===========================
// Level 1 Sentry Gun Frames
void() lvl1_sentry_atk3;
void() lvl1_sentry_stand =[ $lvl1_stand1, lvl1_sentry_stand ] {RemoveGlow(); Sentry_Rotate();};
void() lvl1_sentry_atk1 =[ $lvl1_shoot1, lvl1_sentry_atk3 ]
{
ai_face();
if (!self.enemy || self.enemy.health <= 0 || /* !visible(self.enemy) || */ self.enemy.has_disconnected == TRUE) //CH
2001-07-17 05:58:10 +00:00
lvl1_sentry_stand();
else if (self.ammo_shells <= 0)
lvl1_sentry_stand();
else if (Sentry_Fire() == FALSE)
2001-07-17 05:58:10 +00:00
//WK lvl1_sentry_atk3();
lvl1_sentry_stand();
};
void() lvl1_sentry_atk2 =[ $lvl1_shoot2, lvl1_sentry_atk3 ]
{
ai_face();
Sentry_Fire();
};
void() lvl1_sentry_atk3 =[ $lvl1_stand1, lvl1_sentry_atk1 ] {ai_face();};
//===========================
// Level 2 Sentry Gun Frames
void() lvl2_sentry_atk3;
void() lvl2_sentry_stand= [ $lvl2_stand1, lvl2_sentry_stand ] {RemoveGlow(); Sentry_Rotate();};
void() lvl2_sentry_atk1 = [ $lvl2_shoot1, lvl2_sentry_atk2 ]
{
ai_face();
if (!self.enemy || self.enemy.health <= 0 || /* !visible(self.enemy) || */ self.enemy.has_disconnected == TRUE) //CH
2001-07-17 05:58:10 +00:00
lvl2_sentry_stand();
else if (self.ammo_shells <= 0)
lvl2_sentry_stand();
else if (Sentry_Fire() == FALSE)
2001-07-17 05:58:10 +00:00
//WK lvl2_sentry_atk3();
lvl2_sentry_stand();
};
void() lvl2_sentry_atk2 =[ $lvl2_shoot2, lvl2_sentry_atk3 ]
{
ai_face();
Sentry_Fire();
};
void() lvl2_sentry_atk3 =[ $lvl2_stand1, lvl2_sentry_atk1 ]
{
ai_face();
Sentry_Fire();
};
//===========================
// Level 3 Sentry Gun Frames
void() lvl3_sentry_atk3;
void() lvl3_sentry_atk4;
void() lvl3_sentry_stand= [ $lvl3_stand1, lvl3_sentry_stand ] {RemoveGlow(); Sentry_Rotate();};
void() lvl3_sentry_atk1 = [ $lvl3_shoot1, lvl3_sentry_atk2 ]
{
ai_face();
if (!self.enemy || self.enemy.health <= 0 || /* !visible(self.enemy) || */ self.enemy.has_disconnected == TRUE) //CH
2001-07-17 05:58:10 +00:00
lvl3_sentry_stand();
else if (self.ammo_shells <= 0 && self.ammo_rockets <= 0)
lvl3_sentry_stand();
else if (self.ammo_shells <= 0 && self.ammo_rockets > 0) //CH rocket check
{
RemoveGlow();
lvl3_sentry_atk4();
}
else if (Sentry_Fire() == FALSE)
2001-07-17 05:58:10 +00:00
//WK lvl3_sentry_atk3();
lvl3_sentry_stand();
};
void() lvl3_sentry_atk2 =[ $lvl3_shoot2, lvl3_sentry_atk3 ]
{
ai_face();
Sentry_Fire();
};
void() lvl3_sentry_atk3 =[ $lvl3_stand1, lvl3_sentry_atk1 ]
{
ai_face();
Sentry_Fire();
};
void() lvl3_sentry_atk4 = [ $lvl3_stand1, lvl3_sentry_atk5 ]
{
ai_face();
if (!self.enemy || self.enemy.health <= 0 || /* !visible(self.enemy) || */ self.enemy.has_disconnected == TRUE) //CH
2001-07-17 05:58:10 +00:00
lvl3_sentry_stand();
else if (self.ammo_shells <= 0 && self.ammo_rockets <= 0)
lvl3_sentry_stand();
else if (Sentry_Fire() == FALSE)
2001-07-17 05:58:10 +00:00
//WK lvl3_sentry_atk3();
lvl3_sentry_stand();
};
void() lvl3_sentry_atk5 =[ $lvl3_stand1, lvl3_sentry_atk4 ]
{
ai_face();
Sentry_Fire();
};
//=============
void() Sentry_Rotate =
{
/*
// don't let them exist in walls/doors
// FIXME: pointcontents is wrong for doors
local vector testpoint = self.origin;
if (self.tf_items & NIT_TURRET)
testpoint_z -= 40;
if (pointcontents (testpoint) == CONTENTS_SOLID) {
TF_T_Damage (self, NIL, NIL, self.health + 100,
TF_TD_IGNOREARMOUR, TF_TD_OTHER);
return;
}
*/
if (self.is_malfunctioning & SCREWUP_ONE)
2001-07-17 05:58:10 +00:00
{
self.ideal_yaw = self.ideal_yaw + 10;
ChangeYaw();
return;
}
if (Sentry_FindTarget())
return;
//- OfN this does the sentry to not return to rotate status after enemy becomes not visible or died
// it doesn't alter the real behaviour only the look
if (self.attack_finished > time)
{
self.has_holo=1;
return;
}
if (self.has_holo==1)
{
self.has_holo=0;
sound (self, CHAN_ITEM, "weapons/trr2lost.wav", 0.25, ATTN_NORM);
2001-07-17 05:58:10 +00:00
}
if (self.heat == 0)
{
self.ideal_yaw = anglemod(self.waitmin);
ChangeYaw();
// 15 // 16 or 14
//was if ((anglemod(self.angles_y) <= (self.waitmin + 1)) && (anglemod(self.angles_y) >= (self.waitmin - 2))) //CH after the && fixed spaz sent!!
if ((anglemod(self.angles_y) <= (self.waitmin + 1)) && (anglemod(self.angles_y) >= (self.waitmin - 2))) //CH after the && fixed spaz sent!!
{
self.heat = 1;
if (random() < 0.1)
sound (self, CHAN_ITEM, "weapons/turridle.wav", 1, ATTN_NORM);
2001-07-17 05:58:10 +00:00
}
}
else
{
self.ideal_yaw = anglemod(self.waitmax);
ChangeYaw();
//was if ((anglemod(self.angles_y) >= (self.waitmax - 1 )) && (anglemod(self.angles_y) <= (self.waitmax + 2))) //CH after the && fixed spaz sent!!
if ((anglemod(self.angles_y) >= (self.waitmax - 1 )) && (anglemod(self.angles_y) <= (self.waitmax + 2))) //CH after the && fixed spaz sent!!
self.heat = 0;
}
};
//================================================0
// new RANGE_VERYFAR hacked sentries can shot at it
float(entity targ) rangesentry =
{
local vector spot1, spot2;
local float r;
spot1 = self.origin + self.view_ofs;
spot2 = targ.origin + targ.view_ofs;
r = vlen (spot1 - spot2);
if (r < 120)
return RANGE_MELEE;
2001-07-17 05:58:10 +00:00
if (r < 500)
return RANGE_NEAR;
2001-07-17 05:58:10 +00:00
if (r < 1000)
return RANGE_MID;
2001-07-17 05:58:10 +00:00
if (r < 2000)
return RANGE_FAR;
return RANGE_VERYFAR;
2001-07-17 05:58:10 +00:00
};
float() Sentry_FindTarget =
{
self.enemy = NIL; //CH for sbar
2001-07-17 05:58:10 +00:00
if (infokey(NIL,"ceasefire")=="on")
return FALSE;
2001-07-17 05:58:10 +00:00
local entity client = NIL;
2001-07-17 05:58:10 +00:00
local float r, gotone, loopc;
//WK Hack to get floating sentry working
if (self.tf_items & NIT_TURRET) {
2001-07-17 05:58:10 +00:00
self.origin_z = self.origin_z - 40;
}
// Try a few checks to make it react faster
r = 0;
loopc = 0;
gotone = FALSE;
2001-07-17 05:58:10 +00:00
//WK Theortetically this will check every client on the server now
while (loopc < 32 && gotone == FALSE) //WK 3
2001-07-17 05:58:10 +00:00
{
client = checkclient();
gotone = TRUE;
2001-07-17 05:58:10 +00:00
if (!client)
gotone = FALSE;
2001-07-17 05:58:10 +00:00
if (!Pharse_Client(client, self, 1, 0, 0, 1))
gotone = FALSE;
2001-07-17 05:58:10 +00:00
r = rangesentry (client);
//- ofn
//if (r == RANGE_FAR)
// gotone = FALSE;
2001-07-17 05:58:10 +00:00
//WK Hack, turret should be able to see in all directions...
if (!(self.tf_items & NIT_TURRET)) {
2001-07-17 05:58:10 +00:00
if (r == RANGE_NEAR)
2001-07-17 05:58:10 +00:00
{
if (client.show_hostile < time && !infront (client))
gotone = FALSE;
2001-07-17 05:58:10 +00:00
}
else if (r == RANGE_MID)
2001-07-17 05:58:10 +00:00
{
if (!infront (client))
gotone = FALSE;
2001-07-17 05:58:10 +00:00
}
else if (r == RANGE_FAR) //- OfN - Sentries with enhanced circuits can shot at far range
2001-07-17 05:58:10 +00:00
{
if (!(self.num_mines & IMPROVED_FOUR) || !infront (client))
gotone = FALSE;
2001-07-17 05:58:10 +00:00
}
}
else //- OfN - a turretized sentry gun...
{
if (r == RANGE_FAR && !(self.num_mines & IMPROVED_FOUR))
gotone = FALSE;
2001-07-17 05:58:10 +00:00
}
//- OfN ----------------//
if (r == RANGE_VERYFAR)
gotone = FALSE;
2001-07-17 05:58:10 +00:00
//----------------------//
loopc = loopc + 1;
//WK Solve a bug in sentry targetting?
if (gotone) loopc = 1000;
}
if (!gotone) //if no player target found lets scan for monsters and army..
{
local entity te;
te = find(NIL, message,"XX");
2001-07-17 05:58:10 +00:00
while (te && gotone == FALSE)
2001-07-17 05:58:10 +00:00
{
gotone = TRUE;
2001-07-17 05:58:10 +00:00
if (Teammate(self.real_owner.team_no,te.real_owner.team_no))
gotone = FALSE;
2001-07-17 05:58:10 +00:00
else if (!IsMonster(te))
gotone = FALSE;
2001-07-17 05:58:10 +00:00
else if (te.health <= 0)
gotone = FALSE;
else if ( (!(self.tf_items & NIT_TURRET) && !visible2x(self,te)) || ((self.tf_items & NIT_TURRET) && !visible2(self,te)))
gotone = FALSE;
2001-07-17 05:58:10 +00:00
else
{
r = rangesentry(te);
//WK Hack, turret should be able to see in all directions...
if (!(self.tf_items & NIT_TURRET)) {
2001-07-17 05:58:10 +00:00
if (r == RANGE_NEAR)
2001-07-17 05:58:10 +00:00
{
if (!infront (te))
gotone = FALSE;
2001-07-17 05:58:10 +00:00
}
else if (r == RANGE_MID)
2001-07-17 05:58:10 +00:00
{
if (!infront (te))
gotone = FALSE;
2001-07-17 05:58:10 +00:00
}
else if (r == RANGE_FAR) //- OfN - Sentries with enhanced circuits can shot at far range
2001-07-17 05:58:10 +00:00
{
if (!(self.num_mines & IMPROVED_FOUR) || !infront (te))
gotone = FALSE;
2001-07-17 05:58:10 +00:00
}
}
else //- OfN - a turretized sentry gun...
{
if (r == RANGE_FAR && !(self.num_mines & IMPROVED_FOUR))
gotone = FALSE;
2001-07-17 05:58:10 +00:00
}
//- OfN ----------------//
if (r == RANGE_VERYFAR)
gotone = FALSE;
2001-07-17 05:58:10 +00:00
//----------------------//
} // this is the ELSE of !isMonster()
if (gotone)
client=te;
te = find(te, message, "XX");
} // while
} //monster scanning
//WK Unhack our hack
if (self.tf_items & NIT_TURRET) {
2001-07-17 05:58:10 +00:00
self.origin_z = self.origin_z + 40;
}
if (!gotone)
return FALSE;
2001-07-17 05:58:10 +00:00
// Found a Target
self.enemy = client;
//- OfN - what was this for??
/*if (self.enemy.classname != "player")
{
self.enemy = self.enemy.enemy;
if (self.enemy.classname != "player")
{
self.enemy = NIL;
return FALSE;
2001-07-17 05:58:10 +00:00
}
}*/
Sentry_FoundTarget ();
return TRUE;
2001-07-17 05:58:10 +00:00
};
void() Sentry_FoundTarget =
{
// Cannon Powerup Sound?
if (self.ammo_shells > 0 || (self.ammo_rockets > 0 && self.weapon == 3))
{
if (self.attack_finished < time) //- OfN -
sound (self, CHAN_VOICE, "weapons/turrspot.wav", 1, ATTN_NORM);
2001-07-17 05:58:10 +00:00
}
Sentry_HuntTarget ();
if (self.super_damage_finished < time)
{
self.super_damage_finished = time + 1.0; //WK Was at .5, which was too fast
if (self.num_mines & IMPROVED_FOUR)
2001-07-17 05:58:10 +00:00
self.super_damage_finished = time + 0.65; //- OfN - improved circuits! heh
}
};
void() Sentry_HuntTarget =
{
self.goalentity = self.enemy;
if (self.weapon == 1)
self.think = lvl1_sentry_atk1;
else if (self.weapon == 2)
self.think = lvl2_sentry_atk1;
else // if (self.weapon == 3)
{
if (self.ammo_shells <= 0 && self.ammo_rockets > 0) //CH has rockets but no shells
self.think = lvl3_sentry_atk4;
else
self.think = lvl3_sentry_atk1;
}
self.ideal_yaw = vectoyaw(self.enemy.origin - self.origin);
self.nextthink = time + 0.1;
//SUB_AttackFinished (0.5); // WK Does this do anything?
// - OfN - Nope lol it didnt
local float tfactor;
tfactor=1;
//- OfN - Does this sentry has enhanced circuits? if so.. cut down lock time
if (self.num_mines & IMPROVED_FOUR) tfactor=0.5;
2001-07-17 05:58:10 +00:00
//WK --- Invisible people take longer for sentries to lock onto
// because they have to use their heat sensors
if (self.enemy.modelindex == modelindex_null)
self.nextthink = time + (2*tfactor); // Must acquire a heat signal
else if (self.enemy.modelindex == modelindex_eyes)
self.nextthink = time + (1.5*tfactor); // Some visual, so its a little easier
else
self.nextthink = time + (0.5*tfactor); // Some visual, so its a little easier
};
void(entity attacker, float damage) Sentry_Pain =
2001-07-17 05:58:10 +00:00
{
// Update the owner's status bar
self.real_owner.StatusRefreshTime = time + 0.2;
//CH special sbar for eng.
self.real_owner.StatusBarScreen = 1;
};
void() Sentry_Die =
{
sprint(self.real_owner, PRINT_HIGH, "Your sentry gun was destroyed.\n");
2001-07-17 05:58:10 +00:00
self.real_owner.has_sentry = self.real_owner.has_sentry - 1;
if (self.real_owner.has_sentry < 0)
self.real_owner.has_sentry = 0;
ThrowGib("progs/t2gib1.mdl", -70);
ThrowGib("progs/t2gib2.mdl", -70);
ThrowGib("progs/t2gib3.mdl", -70);
ThrowGib("progs/t2gib4.mdl", self.skin);
if (self.classname == "building_sentrygun_base")
{
if (self.oldenemy)
dremove(self.oldenemy);
}
else
{
if (self.trigger_field)
dremove(self.trigger_field);
}
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);
2001-07-17 05:58:10 +00:00
dremove(self);
};
float() Sentry_Fire =
{
local vector dir;
local vector miss_factor;
//- OfN -
local vector soffset;
soffset = '0 0 0';
if (!(self.tf_items & NIT_TURRET))
2001-07-17 05:58:10 +00:00
soffset = '0 0 20';
// this on the end..
//self.attack_finished = time + SENTRY_UNLOCKTIME; // don't rotate immediately after target invisible or dead
2001-07-17 05:58:10 +00:00
if (infokey(NIL,"ceasefire")=="on") //Cyto
return FALSE;
2001-07-17 05:58:10 +00:00
//WK Stop gun from shooting at dead spies
if (self.enemy.is_feigning)
return FALSE;
2001-07-17 05:58:10 +00:00
//WK Hack to get floating sentry working - reset before all the returns
if (self.tf_items & NIT_TURRET) self.origin_z = self.origin_z - 40;
2001-07-17 05:58:10 +00:00
// Only fire if they're within sight
dir = self.enemy.origin - self.origin;
if (vlen(dir) > 2048) //WK Don't fire if they're too far away
{
if (self.tf_items & NIT_TURRET) self.origin_z = self.origin_z + 40;
return FALSE;
2001-07-17 05:58:10 +00:00
}
dir = normalize(dir);
//WK Turret can shoot in any direction
if (!(self.tf_items & NIT_TURRET)) {
2001-07-17 05:58:10 +00:00
if ((self.ideal_yaw - anglemod(self.angles_y)) < -10 || (self.ideal_yaw - anglemod(self.angles_y)) > 10) {
return FALSE;
2001-07-17 05:58:10 +00:00
}
}
if (self.ammo_shells >= 1)
self.ammo_shells = self.ammo_shells - 1;
if (self.ammo_shells < 1) //WK Disallow half-shells
self.ammo_shells = 0;
if ((self.ammo_shells <= 0 && self.weapon != 3) || (self.ammo_shells <= 0 && self.ammo_rockets <= 0 && self.weapon == 3)) //CH stay on target if have rockets
{
if (self.tf_items & NIT_TURRET) self.origin_z = self.origin_z + 40;
return FALSE;
2001-07-17 05:58:10 +00:00
}
//CH this further checks while firing
traceline (self.origin + soffset, self.enemy.origin, TRUE, self);
2001-07-17 05:58:10 +00:00
if (trace_fraction != 1 || trace_endpos != self.enemy.origin)
{
if (self.tf_items & NIT_TURRET) self.origin_z = self.origin_z + 40;
return FALSE;
2001-07-17 05:58:10 +00:00
}
if (self.ammo_shells > 0)
{
//WK muzzleflash();
self.effects = self.effects | EF_DIMLIGHT;
/* if (self.tf_items & NIT_TURRET)
sound (self ,CHAN_WEAPON, "weapons/asscan2.wav", 1, ATTN_NORM);
2001-07-17 05:58:10 +00:00
else */
//sound (self ,CHAN_WEAPON, "weapons/sniper.wav", 1, ATTN_NORM);
sound (self ,CHAN_WEAPON, "weapons/sntr666.wav", 1, ATTN_NORM);
deathmsg = DMSG_SENTRYGUN_BULLET;
2001-07-17 05:58:10 +00:00
}
////////////
//WK Our hacked attempt to make sentries shoot right
//Make base not shootable //CH if its not floating it needs this
if (!(self.tf_items & NIT_TURRET))
2001-07-17 05:58:10 +00:00
{
if (self.trigger_field) self.trigger_field.solid = SOLID_NOT;
2001-07-17 05:58:10 +00:00
//soffset = '0 0 20'; // non-turretized sentries correction
}
if (self.is_malfunctioning & SCREWUP_TWO)
2001-07-17 05:58:10 +00:00
{
miss_factor_z = random() * 200 - 100;
miss_factor_y = random() * 200 - 100;
miss_factor_x = random() * 200 - 100;
traceline (self.origin + soffset, self.enemy.origin + miss_factor, FALSE, self);
2001-07-17 05:58:10 +00:00
}
else
traceline (self.origin + soffset, self.enemy.origin, FALSE, self);
2001-07-17 05:58:10 +00:00
if (trace_fraction != 1.0 && trace_ent.takedamage && self.ammo_shells > 0) //Hit something and has shells
{
SpawnBlood (trace_endpos, 50);
local float thedmg;
local float therange;
therange = rangesentry(trace_ent);
thedmg = 6;
// OfN - damage now depends on distance to target
if (therange == RANGE_MELEE)
2001-07-17 05:58:10 +00:00
thedmg = 12;
else if (therange == RANGE_NEAR)
2001-07-17 05:58:10 +00:00
thedmg = 6;
else if (therange == RANGE_MID)
2001-07-17 05:58:10 +00:00
thedmg = 4;
else if (therange == RANGE_FAR) // only circuit hacked sentries shot at this range
2001-07-17 05:58:10 +00:00
thedmg = 3;
else thedmg = 2; // this shouldnt happen ever (RANGE_VERYFAR)
// OfN - hacked sentries do more damage (improved circuits)
if (self.num_mines & IMPROVED_FOUR)
2001-07-17 05:58:10 +00:00
thedmg = thedmg * 1.25; // 1.25 too high?
TF_T_Damage (trace_ent, self, self, thedmg, TF_TD_NOTTEAM, TF_TD_SHOT);
2001-07-17 05:58:10 +00:00
}
else if (trace_fraction != 1.0 && trace_ent.classname == "force_field")
{
FieldExplosion(trace_ent,trace_endpos,trace_ent);
PutFieldWork(trace_ent);
}
//FireBullets (1, dir, '0.1 0.1 0');
//CH if its not floating it needs this
if (!(self.tf_items & NIT_TURRET))
2001-07-17 05:58:10 +00:00
{
if (self.trigger_field) self.trigger_field.solid = SOLID_BBOX;
2001-07-17 05:58:10 +00:00
}
/////////////
// Level 3 Turrets fire rockets every 3 seconds
if (self.weapon == 3 && self.ammo_rockets > 0 && self.super_damage_finished < time)
{
//sound (self, CHAN_WEAPON, "weapons/rocket1i.wav", 1, ATTN_NORM); UGLY AND STOPS COOL SOUND
2001-07-17 05:58:10 +00:00
// wtf happens here, why is this the supernailgun sound?
if (self.is_malfunctioning & SCREWUP_THREE)
2001-07-17 05:58:10 +00:00
{
local float damg;
damg = random() * 50 + 120;
T_RadiusDamage(self, self, damg, 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);
if (self.tf_items & NIT_TURRET)
2001-07-17 05:58:10 +00:00
self.origin_z = self.origin_z + 40;
return FALSE;
2001-07-17 05:58:10 +00:00
}
newmis = spawn ();
newmis.owner = self;
newmis.movetype = MOVETYPE_FLYMISSILE;
newmis.solid = SOLID_BBOX;
2001-07-17 05:58:10 +00:00
// set newmis speed
if (self.is_malfunctioning & SCREWUP_TWO) // SB - oh no we've been hax0red
2001-07-17 05:58:10 +00:00
{
miss_factor_z = random() * 200 - 100;
miss_factor_y = random() * 200 - 100;
miss_factor_x = random() * 200 - 100;
}
else
{
miss_factor_z = 0;
miss_factor_y = 0;
miss_factor_x = 0;
}
if (self.tf_items & NIT_TURRET)
2001-07-17 05:58:10 +00:00
newmis.velocity = normalize(self.enemy.origin + miss_factor - (self.origin - '0 0 16')) * 800;
else
newmis.velocity = normalize(self.enemy.origin + miss_factor - (self.origin + '0 0 16')) * 800;
newmis.angles = vectoangles(newmis.velocity);
newmis.weapon = DMSG_SENTRYGUN_ROCKET;
2001-07-17 05:58:10 +00:00
newmis.touch = T_MissileTouch;
// set newmis duration
newmis.nextthink = time + 5;
newmis.think = SUB_Remove;
setmodel (newmis, "progs/missile.mdl");
setsize (newmis, '0 0 0', '0 0 0');
if (self.tf_items & NIT_TURRET) //Determines if rocket should spawn above or below sent
2001-07-17 05:58:10 +00:00
setorigin (newmis, self.origin + v_forward*8 - '0 0 16'); //CH make rocket 16 below
else
setorigin (newmis, self.origin + v_forward*8 + '0 0 16'); //CH make rocket 16 above
self.super_damage_finished = time + 3;
// - OfN - if this sentry has enhanced circuits then delay between rockets firing is cut half
if (self.num_mines & IMPROVED_FOUR) self.super_damage_finished = time + 1.5;
2001-07-17 05:58:10 +00:00
self.ammo_rockets = self.ammo_rockets - 1;
if (self.ammo_rockets == 5) //CH 10 was too high
sprint(self.real_owner, PRINT_HIGH, "Sentry Gun is low on rockets.\n");
2001-07-17 05:58:10 +00:00
}
// Warn owner that it's low on ammo
//WK if (self.ammo_shells == 0 && (random() < 0.1))
if ((self.ammo_shells == 0 && self.weapon != 3) || (self.ammo_shells == 0 && self.weapon == 3 && self.ammo_rockets > 0 && (random() < 0.05))) //CH .05 seems to be good.
sprint(self.real_owner, PRINT_HIGH, "Sentry Gun is out of shells.\n");
2001-07-17 05:58:10 +00:00
else if (self.ammo_shells == 20)
sprint(self.real_owner, PRINT_HIGH, "Sentry Gun is low on shells.\n");
2001-07-17 05:58:10 +00:00
//WK < 0.1
if (self.ammo_rockets == 0 && self.weapon == 3 && (random() <= 0.1))
sprint(self.real_owner, PRINT_HIGH, "Sentry Gun is out of rockets.\n");
2001-07-17 05:58:10 +00:00
if (self.tf_items & NIT_TURRET) self.origin_z = self.origin_z + 40;
2001-07-17 05:58:10 +00:00
self.attack_finished = time + SENTRY_UNLOCKTIME + 2 * random() - 1; // don't rotate immediately after target invisible or dead
2001-07-17 05:58:10 +00:00
return TRUE;
2001-07-17 05:58:10 +00:00
};
//WK Returns TRUE if the vector is not a spot a turret can attach to
2001-07-17 05:58:10 +00:00
float(vector vec) BadSpot =
{
/*
if (pointcontents(vec) == CONTENTS_SOLID)
sprint(self.real_owner,PRINT_HIGH,"SOLID Point\n");
else if (pointcontents(vec) == CONTENTS_EMPTY)
sprint(self.real_owner,PRINT_HIGH,"EMPTY Point\n");
else if (pointcontents(vec) == CONTENTS_SKY)
sprint(self.real_owner,PRINT_HIGH,"SKY Point\n");
else if (pointcontents(vec) == CONTENTS_WATER)
sprint(self.real_owner,PRINT_HIGH,"WATER Point\n");
2001-07-17 05:58:10 +00:00
else
sprint(self.real_owner,PRINT_HIGH,"BUG: Other Point\n");
2001-07-17 05:58:10 +00:00
*/
if (pointcontents(vec) == CONTENTS_SKY)
return TRUE;
return FALSE;
2001-07-17 05:58:10 +00:00
};
//WK Sentry Touch function
//Will kill bad guy
void() Sentry_Touch =
{
//WK Check for blockage
if (pointcontents(self.origin) == CONTENTS_SKY)
2001-07-17 05:58:10 +00:00
{
sprint(self.real_owner, PRINT_HIGH, "Your sentry gun flew away.\n");
2001-07-17 05:58:10 +00:00
Sentry_Die();
return;
}
if (other.takedamage && !(self.tf_items & NIT_TURRET)) // OfN - fixme: doesn't check for enemy disguised spies
2001-07-17 05:58:10 +00:00
{
deathmsg = DMSG_BUG_ZAPPER;
2001-07-17 05:58:10 +00:00
if (IsMonster(other))
{
if (!Teammate(other.real_owner.team_no, self.real_owner.team_no))
{
TF_T_Damage (other, self, self, 400, TF_TD_NOTTEAM, TF_TD_ELECTRICITY);
2001-07-17 05:58:10 +00:00
return;
}
return;
}
if (!Teammate(other.team_no,self.real_owner.team_no) && (other.is_undercover != 1)) // <== FIXME
//TF_T_Damage (other, self, self.real_owner, 400, TF_TD_NOTTEAM, TF_TD_ELECTRICITY);
TF_T_Damage (other, self, self, 400, TF_TD_NOTTEAM, TF_TD_ELECTRICITY);
2001-07-17 05:58:10 +00:00
return;
}
//I'm in midflight and hit something
if (self.tf_items & NIT_TURRET && self.movetype == MOVETYPE_FLY)
2001-07-17 05:58:10 +00:00
{
//WK Check to see if we are blocked
//WK These numbers seem to be about right
if ( BadSpot(self.origin + '0 0 20') || BadSpot(self.origin + '0 0 22'))
{
sprint(self.real_owner, PRINT_HIGH, "Your sentry gun flew away.\n");
2001-07-17 05:58:10 +00:00
Sentry_Die();
return;
}
if (!other) { //The eagle has landed!
// sprint(self.real_owner, PRINT_HIGH, "The eagle has landed!\n");
self.flags = self.flags | FL_ONGROUND;
self.movetype = MOVETYPE_STEP;
2001-07-17 05:58:10 +00:00
self.origin_z = self.origin_z + 32;//32; // was 40, old custom bug? fixed
return;
}
else if (other.classname == "player")
{
deathmsg = DMSG_BUG_ZAPPER;
//TF_T_Damage (other, self, self.real_owner, 400, TF_TD_NOTTEAM, TF_TD_ELECTRICITY);
TF_T_Damage (other, self, self, 400, TF_TD_NOTTEAM, TF_TD_ELECTRICITY);
2001-07-17 05:58:10 +00:00
self.velocity_z = 200; //- OfN reset velocity, not stop
}
else
{
deathmsg = DMSG_BUG_ZAPPER;
//TF_T_Damage (other, self, self.real_owner, 400, TF_TD_NOTTEAM, TF_TD_ELECTRICITY);
2001-07-17 05:58:10 +00:00
if (!Teammate(other.real_owner.team_no,self.real_owner.team_no))
TF_T_Damage (other, self, self, 400, TF_TD_NOTTEAM, TF_TD_ELECTRICITY);
2001-07-17 05:58:10 +00:00
Sentry_Die();
}
//sprint(self.real_owner, PRINT_HIGH, "The eagle has died.\n");
2001-07-17 05:58:10 +00:00
}
};