1388 lines
27 KiB
C++
1388 lines
27 KiB
C++
/*
|
|
* Copyright (c) 2016-2024 Vera Visions LLC.
|
|
*
|
|
* Permission to use, copy, modify, and distribute this software for any
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
* copyright notice and this permission notice appear in all copies.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
* WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
|
|
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
|
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
*/
|
|
|
|
static bool
|
|
droptofloorwrapper(entity foo)
|
|
{
|
|
bool result;
|
|
entity old_self = self;
|
|
self = foo;
|
|
result = droptofloor();
|
|
self = old_self;
|
|
return result;
|
|
}
|
|
|
|
void
|
|
NSEntity::NSEntity(void)
|
|
{
|
|
identity = 1;
|
|
m_flSpawnTime = time;
|
|
m_vecEditorColor = [1,1,1];
|
|
}
|
|
|
|
void
|
|
NSEntity::Spawned(void)
|
|
{
|
|
super::Spawned();
|
|
|
|
m_oldAngle = angles;
|
|
m_oldOrigin = origin;
|
|
m_oldModel = Util_FixModel(model);
|
|
m_oldSolid = solid;
|
|
|
|
#ifdef SERVER
|
|
m_oldstrTarget = target;
|
|
|
|
if (m_oldModel && m_oldModel != "") {
|
|
precache_model(GetSpawnModel());
|
|
}
|
|
|
|
if (m_strOnTrigger) {
|
|
m_strOnTrigger = CreateOutput(m_strOnTrigger);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
float
|
|
NSEntity::EntIndex(void)
|
|
{
|
|
return (num_for_edict(this));
|
|
}
|
|
|
|
bool
|
|
NSEntity::DropToFloor(void)
|
|
{
|
|
return droptofloorwrapper(this);
|
|
}
|
|
|
|
vector
|
|
NSEntity::GetForward(void)
|
|
{
|
|
return anglesToForward(angles);
|
|
}
|
|
|
|
vector
|
|
NSEntity::GetRight(void)
|
|
{
|
|
return anglesToRight(angles);
|
|
}
|
|
|
|
vector
|
|
NSEntity::GetUp(void)
|
|
{
|
|
return anglesToUp(angles);
|
|
}
|
|
|
|
vector
|
|
NSEntity::WorldSpaceCenter(void)
|
|
{
|
|
return (absmin + (0.5 * (absmax - absmin)));
|
|
}
|
|
|
|
float
|
|
NSEntity::WaterLevel(void)
|
|
{
|
|
return (waterlevel);
|
|
}
|
|
|
|
bool
|
|
NSEntity::VisibleVec(vector org)
|
|
{
|
|
vector flDelta;
|
|
float flFoV;
|
|
|
|
flDelta = vectorNormalize(org - origin);
|
|
flFoV = flDelta * GetForward();
|
|
|
|
if (flFoV > 0.3f) {
|
|
traceline(origin, org, TRUE, this);
|
|
if (trace_fraction == 1.0f) {
|
|
return (true);
|
|
}
|
|
}
|
|
return (false);
|
|
}
|
|
|
|
bool
|
|
NSEntity::Visible(entity ent)
|
|
{
|
|
/* is it in our field of view? */
|
|
if (DistanceFromYaw(ent.origin) > 0.3f) {
|
|
traceline(origin, ent.origin, MOVE_NORMAL, this);
|
|
|
|
if (trace_fraction == 1.0f || trace_ent == ent) {
|
|
print(sprintf("%s can see %s\n", classname, ent.classname));
|
|
return (true);
|
|
}
|
|
}
|
|
|
|
print(sprintf("%s can not see %s\n", classname, ent.classname));
|
|
return (false);
|
|
}
|
|
|
|
float
|
|
NSEntity::DistanceFromYaw(vector targetPos)
|
|
{
|
|
return vectorNormalize(targetPos - origin) * GetForward();
|
|
}
|
|
|
|
bool
|
|
NSEntity::HasSpawnFlags(float sf)
|
|
{
|
|
return (spawnflags & sf) ? (true) : (false);
|
|
}
|
|
|
|
bool
|
|
NSEntity::IsOnGround(void)
|
|
{
|
|
return (flags & FL_ONGROUND) ? (true) : (false);
|
|
}
|
|
|
|
bool
|
|
NSEntity::IsSolid(void)
|
|
{
|
|
return (solid != SOLID_NOT) ? (true) : (false);
|
|
}
|
|
|
|
entity
|
|
NSEntity::GetGroundEntity(void)
|
|
{
|
|
return (groundentity);
|
|
}
|
|
|
|
bool
|
|
NSEntity::CreatedByMap(void)
|
|
{
|
|
return (_mapspawned);
|
|
}
|
|
|
|
#ifdef CLIENT
|
|
void
|
|
NSEntity::RendererRestarted(void)
|
|
{
|
|
|
|
}
|
|
|
|
void
|
|
NSEntity::ReceiveEntity(float flNew, float flChanged)
|
|
{
|
|
READENTITY_COORD(origin[0], BASEFL_CHANGED_ORIGIN_X)
|
|
READENTITY_COORD(origin[1], BASEFL_CHANGED_ORIGIN_Y)
|
|
READENTITY_COORD(origin[2], BASEFL_CHANGED_ORIGIN_Z)
|
|
READENTITY_ANGLE(angles[0], BASEFL_CHANGED_ANGLES_X)
|
|
READENTITY_ANGLE(angles[1], BASEFL_CHANGED_ANGLES_Y)
|
|
READENTITY_ANGLE(angles[2], BASEFL_CHANGED_ANGLES_Z)
|
|
READENTITY_SHORT(modelindex, BASEFL_CHANGED_MODELINDEX)
|
|
READENTITY_BYTE(solid, BASEFL_CHANGED_SOLID)
|
|
READENTITY_BYTE(movetype, BASEFL_CHANGED_FLAGS)
|
|
READENTITY_INT(flags, BASEFL_CHANGED_FLAGS)
|
|
READENTITY_INT(vv_flags, BASEFL_CHANGED_FLAGS)
|
|
READENTITY_COORD(mins[0], BASEFL_CHANGED_SIZE)
|
|
READENTITY_COORD(mins[1], BASEFL_CHANGED_SIZE)
|
|
READENTITY_COORD(mins[2], BASEFL_CHANGED_SIZE)
|
|
READENTITY_COORD(maxs[0], BASEFL_CHANGED_SIZE)
|
|
READENTITY_COORD(maxs[1], BASEFL_CHANGED_SIZE)
|
|
READENTITY_COORD(maxs[2], BASEFL_CHANGED_SIZE)
|
|
READENTITY_BYTE(frame, BASEFL_CHANGED_FRAME)
|
|
READENTITY_FLOAT(skin, BASEFL_CHANGED_SKIN)
|
|
READENTITY_FLOAT(effects, BASEFL_CHANGED_EFFECTS)
|
|
READENTITY_FLOAT(scale, BASEFL_CHANGED_SCALE)
|
|
READENTITY_COORD(velocity[0], BASEFL_CHANGED_VELOCITY_X)
|
|
READENTITY_COORD(velocity[1], BASEFL_CHANGED_VELOCITY_Y)
|
|
READENTITY_COORD(velocity[2], BASEFL_CHANGED_VELOCITY_Z)
|
|
READENTITY_COORD(avelocity[0], BASEFL_CHANGED_ANGULARVELOCITY)
|
|
READENTITY_COORD(avelocity[1], BASEFL_CHANGED_ANGULARVELOCITY)
|
|
READENTITY_COORD(avelocity[2], BASEFL_CHANGED_ANGULARVELOCITY)
|
|
|
|
drawmask = (modelindex != 0) ? MASK_ENGINE : 0;
|
|
|
|
if (scale == 0.0f)
|
|
scale = 1.0f;
|
|
|
|
if (flChanged & BASEFL_CHANGED_SIZE)
|
|
setsize(this, mins, maxs);
|
|
}
|
|
|
|
void
|
|
NSEntity::postdraw(void)
|
|
{
|
|
}
|
|
|
|
|
|
#else
|
|
void
|
|
NSEntity::DebugDraw(void)
|
|
{
|
|
DebugBox(GetOrigin(), GetMins(), GetMaxs(), m_vecEditorColor, 0.75f);
|
|
}
|
|
|
|
/* Make sure StartFrame calls this */
|
|
float
|
|
NSEntity::SendEntity(entity ePEnt, float flChanged)
|
|
{
|
|
if (!modelindex)
|
|
return (0);
|
|
|
|
if (clienttype(ePEnt) != CLIENTTYPE_REAL)
|
|
return (0);
|
|
|
|
if (alpha == 0.0f)
|
|
return (0);
|
|
|
|
WriteByte(MSG_ENTITY, ENT_ENTITY);
|
|
|
|
/* optimisation */
|
|
{
|
|
/* we'll never network these if we aren't moving. */
|
|
if (movetype == MOVETYPE_NONE) {
|
|
flChanged &= ~BASEFL_CHANGED_VELOCITY_X;
|
|
flChanged &= ~BASEFL_CHANGED_VELOCITY_Y;
|
|
flChanged &= ~BASEFL_CHANGED_VELOCITY_Z;
|
|
flChanged &= ~BASEFL_CHANGED_ANGULARVELOCITY;
|
|
}
|
|
|
|
if (m_bIsBrush == true) {
|
|
flChanged &= ~BASEFL_CHANGED_FLAGS;
|
|
flChanged &= ~BASEFL_CHANGED_SCALE;
|
|
}
|
|
}
|
|
|
|
/* broadcast how much data is expected to be read */
|
|
WriteFloat(MSG_ENTITY, flChanged);
|
|
|
|
SENDENTITY_COORD(origin[0], BASEFL_CHANGED_ORIGIN_X)
|
|
SENDENTITY_COORD(origin[1], BASEFL_CHANGED_ORIGIN_Y)
|
|
SENDENTITY_COORD(origin[2], BASEFL_CHANGED_ORIGIN_Z)
|
|
SENDENTITY_ANGLE(angles[0], BASEFL_CHANGED_ANGLES_X)
|
|
SENDENTITY_ANGLE(angles[1], BASEFL_CHANGED_ANGLES_Y)
|
|
SENDENTITY_ANGLE(angles[2], BASEFL_CHANGED_ANGLES_Z)
|
|
SENDENTITY_SHORT(modelindex, BASEFL_CHANGED_MODELINDEX)
|
|
SENDENTITY_BYTE(solid, BASEFL_CHANGED_SOLID)
|
|
SENDENTITY_BYTE(movetype, BASEFL_CHANGED_FLAGS)
|
|
SENDENTITY_INT(flags, BASEFL_CHANGED_FLAGS)
|
|
SENDENTITY_INT(vv_flags, BASEFL_CHANGED_FLAGS)
|
|
SENDENTITY_COORD(mins[0], BASEFL_CHANGED_SIZE)
|
|
SENDENTITY_COORD(mins[1], BASEFL_CHANGED_SIZE)
|
|
SENDENTITY_COORD(mins[2], BASEFL_CHANGED_SIZE)
|
|
SENDENTITY_COORD(maxs[0], BASEFL_CHANGED_SIZE)
|
|
SENDENTITY_COORD(maxs[1], BASEFL_CHANGED_SIZE)
|
|
SENDENTITY_COORD(maxs[2], BASEFL_CHANGED_SIZE)
|
|
SENDENTITY_BYTE(frame, BASEFL_CHANGED_FRAME)
|
|
SENDENTITY_FLOAT(skin, BASEFL_CHANGED_SKIN)
|
|
SENDENTITY_FLOAT(effects, BASEFL_CHANGED_EFFECTS)
|
|
SENDENTITY_FLOAT(scale, BASEFL_CHANGED_SCALE)
|
|
SENDENTITY_COORD(velocity[0], BASEFL_CHANGED_VELOCITY_X)
|
|
SENDENTITY_COORD(velocity[1], BASEFL_CHANGED_VELOCITY_Y)
|
|
SENDENTITY_COORD(velocity[2], BASEFL_CHANGED_VELOCITY_Z)
|
|
SENDENTITY_COORD(avelocity[0], BASEFL_CHANGED_ANGULARVELOCITY)
|
|
SENDENTITY_COORD(avelocity[1], BASEFL_CHANGED_ANGULARVELOCITY)
|
|
SENDENTITY_COORD(avelocity[2], BASEFL_CHANGED_ANGULARVELOCITY)
|
|
return (1);
|
|
}
|
|
|
|
void
|
|
NSEntity::EvaluateEntity(void)
|
|
{
|
|
EVALUATE_VECTOR(origin, 0, BASEFL_CHANGED_ORIGIN_X)
|
|
EVALUATE_VECTOR(origin, 1, BASEFL_CHANGED_ORIGIN_Y)
|
|
EVALUATE_VECTOR(origin, 2, BASEFL_CHANGED_ORIGIN_Z)
|
|
EVALUATE_VECTOR(angles, 0, BASEFL_CHANGED_ANGLES_X)
|
|
EVALUATE_VECTOR(angles, 1, BASEFL_CHANGED_ANGLES_Y)
|
|
EVALUATE_VECTOR(angles, 2, BASEFL_CHANGED_ANGLES_Z)
|
|
EVALUATE_FIELD(modelindex, BASEFL_CHANGED_MODELINDEX)
|
|
EVALUATE_FIELD(solid, BASEFL_CHANGED_SOLID)
|
|
EVALUATE_FIELD(movetype, BASEFL_CHANGED_FLAGS)
|
|
EVALUATE_FIELD(flags, BASEFL_CHANGED_FLAGS)
|
|
EVALUATE_FIELD(vv_flags, BASEFL_CHANGED_FLAGS)
|
|
EVALUATE_VECTOR(mins, 0, BASEFL_CHANGED_SIZE)
|
|
EVALUATE_VECTOR(mins, 1, BASEFL_CHANGED_SIZE)
|
|
EVALUATE_VECTOR(mins, 2, BASEFL_CHANGED_SIZE)
|
|
EVALUATE_VECTOR(maxs, 0, BASEFL_CHANGED_SIZE)
|
|
EVALUATE_VECTOR(maxs, 1, BASEFL_CHANGED_SIZE)
|
|
EVALUATE_VECTOR(maxs, 2, BASEFL_CHANGED_SIZE)
|
|
EVALUATE_FIELD(frame, BASEFL_CHANGED_FRAME)
|
|
EVALUATE_FIELD(skin, BASEFL_CHANGED_SKIN)
|
|
EVALUATE_FIELD(effects, BASEFL_CHANGED_EFFECTS)
|
|
EVALUATE_FIELD(scale, BASEFL_CHANGED_SCALE)
|
|
EVALUATE_VECTOR(velocity, 0, BASEFL_CHANGED_VELOCITY_X)
|
|
EVALUATE_VECTOR(velocity, 1, BASEFL_CHANGED_VELOCITY_Y)
|
|
EVALUATE_VECTOR(velocity, 2, BASEFL_CHANGED_VELOCITY_Z)
|
|
EVALUATE_VECTOR(avelocity, 0, BASEFL_CHANGED_ANGULARVELOCITY)
|
|
EVALUATE_VECTOR(avelocity, 1, BASEFL_CHANGED_ANGULARVELOCITY)
|
|
EVALUATE_VECTOR(avelocity, 2, BASEFL_CHANGED_ANGULARVELOCITY)
|
|
}
|
|
|
|
/* Make sure StartFrame calls this */
|
|
void
|
|
NSEntity::ParentUpdate(void)
|
|
{
|
|
EvaluateEntity();
|
|
|
|
frame1time += frametime;
|
|
|
|
/* handle end-touch */
|
|
if (m_beingTouched == true)
|
|
if (m_flTouchTime < GetTime()) {
|
|
EndTouch(m_eTouchLast);
|
|
m_beingTouched = false;
|
|
m_eTouchLast = __NULL__;
|
|
}
|
|
}
|
|
|
|
entity
|
|
NSEntity::GetParent(void)
|
|
{
|
|
return tag_entity;
|
|
}
|
|
|
|
void
|
|
NSEntity::SetParent(string name)
|
|
{
|
|
tag_entity = find(world, ::targetname, m_parent);
|
|
}
|
|
|
|
void
|
|
NSEntity::SetParentAttachment(string name)
|
|
{
|
|
if (name != "origin") {
|
|
tag_index = gettagindex(tag_entity, name);
|
|
} else {
|
|
tag_index = 0;
|
|
}
|
|
}
|
|
|
|
void
|
|
NSEntity::ClearParent(void)
|
|
{
|
|
tag_entity = world;
|
|
tag_index = 0;
|
|
}
|
|
|
|
void
|
|
NSEntity::RestoreAngles(void)
|
|
{
|
|
angles = GetSpawnAngles();
|
|
}
|
|
|
|
void
|
|
NSEntity::ClearAngles(void)
|
|
{
|
|
angles = [0, 0, 0];
|
|
}
|
|
|
|
void
|
|
NSEntity::ForceNetworkUpdate(void)
|
|
{
|
|
SendFlags = -1;
|
|
}
|
|
|
|
void
|
|
NSEntity::UseBy(entity ourActivator)
|
|
{
|
|
if (PlayerUse) {
|
|
eActivator = (NSEntity)ourActivator;
|
|
PlayerUse();
|
|
}
|
|
}
|
|
#endif
|
|
|
|
void
|
|
NSEntity::SetEffects(float newEffects)
|
|
{
|
|
effects = newEffects;
|
|
}
|
|
|
|
void
|
|
NSEntity::SetFrame(float newFrame)
|
|
{
|
|
if (newFrame == frame)
|
|
return;
|
|
|
|
frame = newFrame;
|
|
frame1time = 0.0f;
|
|
|
|
|
|
#ifdef SERVER
|
|
/* check if an event callback exists */
|
|
{
|
|
int eDefEvents;
|
|
string ourName;
|
|
|
|
if (modelframecount(modelindex) > 0) {
|
|
ourName = frametoname(modelindex, frame);
|
|
} else {
|
|
return;
|
|
}
|
|
|
|
eDefEvents = tokenize(m_strModelEventCB);
|
|
|
|
for (int i = 0; i < eDefEvents; i+=3) {
|
|
string testName = argv(i+0);
|
|
string testInput = argv(i+1);
|
|
string testData = argv(i+2);
|
|
|
|
if (ourName == testName) {
|
|
if (testData != "")
|
|
Input(this, testInput, testData);
|
|
else
|
|
Input(this, testInput, ""); /* no parms passed. */
|
|
|
|
tokenize(m_strModelEventCB); /* ensure argv() is 'rewound'... */
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void
|
|
NSEntity::SetSkin(float newSkin)
|
|
{
|
|
skin = newSkin;
|
|
}
|
|
|
|
void
|
|
NSEntity::SetOwner(entity newOwner)
|
|
{
|
|
owner = newOwner;
|
|
}
|
|
|
|
void
|
|
NSEntity::SetVelocity(vector vecNew)
|
|
{
|
|
velocity = vecNew;
|
|
}
|
|
|
|
void
|
|
NSEntity::SetTouch(void ()newTouch)
|
|
{
|
|
touch = newTouch;
|
|
}
|
|
|
|
/* we want to really use those set functions because they'll notify of any
|
|
* networking related changes. otherwise we'll have to keep track of copies
|
|
* that get updated every frame */
|
|
void
|
|
NSEntity::SetSendFlags(float flSendFlags)
|
|
{
|
|
#ifdef SERVER
|
|
SendFlags |= flSendFlags;
|
|
#endif
|
|
}
|
|
|
|
void
|
|
NSEntity::SetMovetype(float newMovetype)
|
|
{
|
|
movetype = newMovetype;
|
|
}
|
|
|
|
void
|
|
NSEntity::SetGravity(float newGrav)
|
|
{
|
|
gravity = newGrav;
|
|
}
|
|
|
|
void
|
|
NSEntity::SetSolid(float newSolid)
|
|
{
|
|
solid = newSolid;
|
|
}
|
|
|
|
void
|
|
NSEntity::SetScale(float newScale)
|
|
{
|
|
if (newScale == scale)
|
|
return;
|
|
|
|
scale = newScale;
|
|
setsize(this, m_vecMins * scale, m_vecMaxs * scale);
|
|
}
|
|
|
|
void
|
|
NSEntity::UpdateBounds(void)
|
|
{
|
|
vector newMins, newMaxs;
|
|
float flScale = 1.0f;
|
|
|
|
newMins = m_vecMins;
|
|
newMaxs = m_vecMaxs;
|
|
|
|
/* avoid useless computation */
|
|
if (angles !=[0, 0, 0]) {
|
|
/* adjust bbox according to rotation */
|
|
vector vecCorner[8];
|
|
|
|
newMins = newMaxs =[0, 0, 0];
|
|
for (int i = 0; i < 8; i++) {
|
|
vecCorner[i][0] = (i & 1) ? m_vecMins[0] : m_vecMaxs[0];
|
|
vecCorner[i][1] = (i & 2) ? m_vecMins[1] : m_vecMaxs[1];
|
|
vecCorner[i][2] = (i & 4) ? m_vecMins[2] : m_vecMaxs[2];
|
|
vecCorner[i] += origin;
|
|
vecCorner[i] = rotateAroundPoint(vecCorner[i], origin, angles[1]);
|
|
vecCorner[i] -= origin;
|
|
|
|
if (!(vecCorner[i][0] <= newMaxs[0]))
|
|
newMaxs[0] = vecCorner[i][0];
|
|
if (!(vecCorner[i][1] <= newMaxs[1]))
|
|
newMaxs[1] = vecCorner[i][1];
|
|
if (!(vecCorner[i][2] <= newMaxs[2]))
|
|
newMaxs[2] = vecCorner[i][2];
|
|
|
|
if (!(vecCorner[i][0] >= newMins[0]))
|
|
newMins[0] = vecCorner[i][0];
|
|
if (!(vecCorner[i][1] >= newMins[1]))
|
|
newMins[1] = vecCorner[i][1];
|
|
if (!(vecCorner[i][2] >= newMins[2]))
|
|
newMins[2] = vecCorner[i][2];
|
|
}
|
|
}
|
|
|
|
/* 0.0 is never valid, if you want it to disappear do something else */
|
|
if (scale != 0.0)
|
|
flScale = scale;
|
|
|
|
setsize(this, newMins * flScale, newMaxs * flScale);
|
|
}
|
|
|
|
void
|
|
NSEntity::SetAngles(vector newAngles)
|
|
{
|
|
angles = newAngles;
|
|
}
|
|
|
|
void
|
|
NSEntity::SetAngularVelocity(vector newAvel)
|
|
{
|
|
avelocity = newAvel;
|
|
}
|
|
|
|
void
|
|
NSEntity::SetSize(vector newMins, vector newMaxs)
|
|
{
|
|
float flScale = 1.0f;
|
|
|
|
m_vecMins = newMins;
|
|
m_vecMaxs = newMaxs;
|
|
|
|
/* 0.0 is never valid, if you want it to disappear do something else */
|
|
if (scale != 0.0f)
|
|
flScale = scale;
|
|
|
|
setsize(this, newMins * flScale, newMaxs * flScale);
|
|
}
|
|
|
|
void
|
|
NSEntity::SetOrigin(vector newOrigin) {
|
|
setorigin(this, newOrigin);
|
|
}
|
|
|
|
void
|
|
NSEntity::SetModel(string newModel) {
|
|
m_bIsBrush = substring(newModel, 0, 1) == "*" ? true : false;
|
|
model = newModel;
|
|
setmodel(this, newModel);
|
|
|
|
/* mins/maxs have been updated by setmodel */
|
|
SetSize(mins, maxs);
|
|
}
|
|
void
|
|
NSEntity::SetModelindex(float newModelIndex) {
|
|
if (newModelIndex == modelindex)
|
|
return;
|
|
|
|
modelindex = newModelIndex;
|
|
SetSize(mins, maxs);
|
|
|
|
}
|
|
|
|
void
|
|
NSEntity::AddAngularVelocity(vector addVel)
|
|
{
|
|
avelocity += addVel;
|
|
}
|
|
|
|
void
|
|
NSEntity::AddVelocity(vector addVel)
|
|
{
|
|
velocity += addVel;
|
|
}
|
|
|
|
void
|
|
NSEntity::AddEffects(float fl) {
|
|
effects |= fl;
|
|
}
|
|
|
|
void
|
|
NSEntity::RemoveEffects(float fl) {
|
|
effects &= ~fl;
|
|
}
|
|
|
|
|
|
void
|
|
NSEntity::AddFlags(float fl) {
|
|
flags |= fl;
|
|
}
|
|
|
|
void
|
|
NSEntity::RemoveFlags(float fl) {
|
|
flags &= ~fl;
|
|
}
|
|
|
|
|
|
void
|
|
NSEntity::AddVFlags(float fl) {
|
|
vv_flags |= fl;
|
|
}
|
|
|
|
void
|
|
NSEntity::RemoveVFlags(float fl) {
|
|
vv_flags &= ~fl;
|
|
}
|
|
|
|
void
|
|
NSEntity::TurnTo(float targetAngle) {
|
|
angles[1] = targetAngle;
|
|
}
|
|
|
|
void
|
|
NSEntity::TurnToPos(vector targetPos) {
|
|
angles = vectorToAngles(targetPos - WorldSpaceCenter());
|
|
}
|
|
|
|
void
|
|
NSEntity::SetThink(void (void) func) {
|
|
think = func;
|
|
}
|
|
|
|
void
|
|
NSEntity::SetNextThink(float fl) {
|
|
float flTime = GetTime() + fl;
|
|
|
|
/* HACK: to make sure things happen post-spawn */
|
|
if (flTime == 0.0f)
|
|
flTime = 0.001f;
|
|
|
|
if (flTime >= 0)
|
|
nextthink = flTime;
|
|
else
|
|
EntError("%s sets bogus nextthink value %f", classname, flTime);
|
|
}
|
|
|
|
void
|
|
NSEntity::ScheduleThink(void (void) func, float fl) {
|
|
SetThink(func);
|
|
SetNextThink(fl);
|
|
}
|
|
|
|
vector
|
|
NSEntity::GetSpawnOrigin(void) {
|
|
return (m_oldOrigin);
|
|
}
|
|
|
|
vector
|
|
NSEntity::GetSpawnAngles(void) {
|
|
return (m_oldAngle);
|
|
}
|
|
|
|
string
|
|
NSEntity::GetSpawnModel(void) {
|
|
return (m_oldModel);
|
|
}
|
|
|
|
float
|
|
NSEntity::GetEffects(void) {
|
|
return (effects);
|
|
}
|
|
|
|
float
|
|
NSEntity::GetFrame(void) {
|
|
return (frame);
|
|
}
|
|
|
|
float
|
|
NSEntity::GetSkin(void) {
|
|
return (skin);
|
|
}
|
|
|
|
float
|
|
NSEntity::GetScale(void) {
|
|
return (scale);
|
|
}
|
|
|
|
entity
|
|
NSEntity::GetOwner(void) {
|
|
return (owner);
|
|
}
|
|
|
|
vector
|
|
NSEntity::GetVelocity(void) {
|
|
return (velocity);
|
|
}
|
|
|
|
float
|
|
NSEntity::GetSolid(void) {
|
|
return (solid);
|
|
}
|
|
|
|
string
|
|
NSEntity::GetModel(void)
|
|
{
|
|
return (model);
|
|
}
|
|
|
|
float
|
|
NSEntity::GetModelindex(void)
|
|
{
|
|
return (modelindex);
|
|
}
|
|
|
|
float
|
|
NSEntity::GetMovetype(void)
|
|
{
|
|
return (movetype);
|
|
}
|
|
|
|
float
|
|
NSEntity::GetGravity(void)
|
|
{
|
|
return (gravity);
|
|
}
|
|
|
|
vector
|
|
NSEntity::GetAngles(void)
|
|
{
|
|
return (angles);
|
|
}
|
|
|
|
vector
|
|
NSEntity::GetAngularVelocity(void)
|
|
{
|
|
return (avelocity);
|
|
}
|
|
|
|
vector
|
|
NSEntity::GetOrigin(void)
|
|
{
|
|
return (origin);
|
|
}
|
|
|
|
vector
|
|
NSEntity::GetMins(void)
|
|
{
|
|
return (mins);
|
|
}
|
|
|
|
vector
|
|
NSEntity::GetMaxs(void)
|
|
{
|
|
return (maxs);
|
|
}
|
|
|
|
vector
|
|
NSEntity::GetRealMins(void)
|
|
{
|
|
return (m_vecMins);
|
|
}
|
|
|
|
vector
|
|
NSEntity::GetRealMaxs(void)
|
|
{
|
|
return (m_vecMaxs);
|
|
}
|
|
|
|
vector
|
|
NSEntity::GetAbsoluteMins(void)
|
|
{
|
|
return (absmin);
|
|
}
|
|
|
|
vector
|
|
NSEntity::GetAbsoluteMaxs(void)
|
|
{
|
|
return (absmax);
|
|
}
|
|
|
|
float
|
|
NSEntity::GetFlags(void)
|
|
{
|
|
return (flags);
|
|
}
|
|
|
|
float
|
|
NSEntity::GetVFlags(void)
|
|
{
|
|
return (vv_flags);
|
|
}
|
|
|
|
bool
|
|
NSEntity::HasFlags(float bits)
|
|
{
|
|
return (flags & bits) ? (true) : (false);
|
|
}
|
|
|
|
bool
|
|
NSEntity::HasVFlags(float bits)
|
|
{
|
|
return (vv_flags & bits) ? (true) : (false);
|
|
}
|
|
|
|
float
|
|
NSEntity::GetNextThinkTime(void)
|
|
{
|
|
return (nextthink);
|
|
}
|
|
|
|
bool
|
|
NSEntity::IsThinking(void)
|
|
{
|
|
return (nextthink > GetTime()) ? (true) : (false);
|
|
}
|
|
|
|
void
|
|
NSEntity::ReleaseThink(void)
|
|
{
|
|
think = __NULL__;
|
|
nextthink = 0.0f;
|
|
}
|
|
|
|
void
|
|
NSEntity::ThinkBusy(float busyTime)
|
|
{
|
|
static void ThinkBusy_Done(void) {
|
|
/* Guess we're done here... */
|
|
}
|
|
ScheduleThink(ThinkBusy_Done, busyTime);
|
|
}
|
|
|
|
void
|
|
NSEntity::ClearVelocity(void)
|
|
{
|
|
velocity = avelocity = [0.0f, 0.0f, 0.0f];
|
|
}
|
|
|
|
#ifdef SERVER
|
|
void
|
|
NSEntity::Respawn(void)
|
|
{
|
|
super::Respawn();
|
|
SetSolid(m_oldSolid);
|
|
SetAngles(GetSpawnAngles());
|
|
SetOrigin(GetSpawnOrigin());
|
|
SetModel(GetSpawnModel());
|
|
}
|
|
|
|
void
|
|
NSEntity::Save(float handle)
|
|
{
|
|
super::Save(handle);
|
|
SaveEntity(handle, "tag_entity", tag_entity);
|
|
SaveFloat(handle, "tag_index", tag_index);
|
|
SaveFloat(handle, "pvsflags", pvsflags);
|
|
SaveBool(handle, "_mapspawned", _mapspawned);
|
|
SaveFloat(handle, "scale", scale);
|
|
SaveFloat(handle, "vv_flags", vv_flags);
|
|
SaveFloat(handle, "friction", friction);
|
|
SaveVector(handle, "m_vecMins", m_vecMins);
|
|
SaveVector(handle, "m_vecMaxs", m_vecMaxs);
|
|
SaveVector(handle, "m_oldOrigin", m_oldOrigin);
|
|
SaveVector(handle, "m_oldAngle", m_oldAngle);
|
|
SaveString(handle, "m_oldModel", m_oldModel);
|
|
SaveFloat(handle, "m_oldSolid", m_oldSolid);
|
|
SaveFloat(handle, "m_flTouchTime", m_flTouchTime);
|
|
SaveBool(handle, "m_beingTouched", m_beingTouched);
|
|
SaveEntity(handle, "m_eTouchLast", m_eTouchLast);
|
|
SaveVector(handle, "m_vecEditorColor", m_vecEditorColor);
|
|
}
|
|
|
|
void
|
|
NSEntity::Restore(string strKey, string strValue)
|
|
{
|
|
switch (strKey) {
|
|
case "tag_entity":
|
|
tag_entity = ReadEntity(strValue);
|
|
break;
|
|
case "tag_index":
|
|
tag_index = ReadFloat(strValue);
|
|
break;
|
|
case "pvsflags":
|
|
pvsflags = ReadFloat(strValue);
|
|
break;
|
|
case "_mapspawned":
|
|
_mapspawned = ReadBool(strValue);
|
|
break;
|
|
case "scale":
|
|
scale = ReadFloat(strValue);
|
|
break;
|
|
case "vv_flags":
|
|
vv_flags = ReadFloat(strValue);
|
|
break;
|
|
case "friction":
|
|
friction = ReadFloat(strValue);
|
|
break;
|
|
case "m_vecMins":
|
|
m_vecMins = ReadVector(strValue);
|
|
break;
|
|
case "m_vecMaxs":
|
|
m_vecMaxs = ReadVector(strValue);
|
|
break;
|
|
case "m_oldOrigin":
|
|
m_oldOrigin = ReadVector(strValue);
|
|
break;
|
|
case "m_oldAngle":
|
|
m_oldAngle = ReadVector(strValue);
|
|
break;
|
|
case "m_oldModel":
|
|
m_oldModel = ReadString(strValue);
|
|
break;
|
|
case "m_oldSolid":
|
|
m_oldSolid = ReadFloat(strValue);
|
|
break;
|
|
case "m_flTouchTime":
|
|
m_flTouchTime = ReadFloat(strValue);
|
|
break;
|
|
case "m_beingTouched":
|
|
m_beingTouched = ReadBool(strValue);
|
|
break;
|
|
case "m_eTouchLast":
|
|
m_eTouchLast = ReadEntity(strValue);
|
|
break;
|
|
case "m_vecEditorColor":
|
|
m_vecEditorColor = ReadVector(strValue);
|
|
break;
|
|
default:
|
|
super::Restore(strKey, strValue);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void
|
|
NSEntity::Input(entity eAct, string strInput, string strData)
|
|
{
|
|
switch (strInput) {
|
|
case "Kill":
|
|
Destroy();
|
|
break;
|
|
case "KillHierarchy":
|
|
/* this works because ents are basically just entnums */
|
|
for (entity e = world; (e = findfloat(e, ::owner, this));) {
|
|
NSEntity ent = (NSEntity) e;
|
|
|
|
ent.Destroy();
|
|
}
|
|
Destroy();
|
|
break;
|
|
case "SetParent":
|
|
SetParent(strData);
|
|
break;
|
|
case "SetParentAttachment":
|
|
SetParentAttachment(strData);
|
|
break;
|
|
case "ClearParent":
|
|
ClearParent();
|
|
break;
|
|
case "Use":
|
|
eActivator = (NSEntity)eAct;
|
|
|
|
if (PlayerUse)
|
|
PlayerUse();
|
|
break;
|
|
case "SpawnDef":
|
|
break;
|
|
case "SpawnProjectileDef":
|
|
if (EntityDef_HasSpawnClass(strData)) {
|
|
NSProjectile_SpawnDefAttachment(strData, this, 0);
|
|
} else {
|
|
float rangedDmg = Skill_GetDefValue(EntityDef_GetKeyValue(strData, "damage"));
|
|
TraceAttack_FireBullets(1, origin + view_ofs, rangedDmg, [0.01,0.01], 0);
|
|
}
|
|
break;
|
|
case "StartSoundDef":
|
|
StartSoundDef(strData, CHAN_VOICE, true);
|
|
break;
|
|
case "AddVelocity":
|
|
vector velAdd = stov(strData);
|
|
velocity += GetForward() * velAdd[0];
|
|
velocity += GetRight() * velAdd[1];
|
|
velocity += GetUp() * velAdd[2];
|
|
break;
|
|
case "Shockwave":
|
|
int c = tokenize(strData);
|
|
|
|
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
|
|
WriteByte(MSG_MULTICAST, EV_BEAMCYLINDER);
|
|
WriteCoord(MSG_MULTICAST, origin[0]);
|
|
WriteCoord(MSG_MULTICAST, origin[1]);
|
|
WriteCoord(MSG_MULTICAST, origin[2]);
|
|
WriteCoord(MSG_MULTICAST, angles[0]);
|
|
WriteCoord(MSG_MULTICAST, stof(argv(1)));
|
|
WriteCoord(MSG_MULTICAST, angles[2]);
|
|
WriteShort(MSG_MULTICAST, getmodelindex(argv(0)));
|
|
WriteByte(MSG_MULTICAST, stof(argv(2)));
|
|
WriteByte(MSG_MULTICAST, stof(argv(3)));
|
|
WriteByte(MSG_MULTICAST, stof(argv(4)));
|
|
WriteByte(MSG_MULTICAST, stof(argv(5)));
|
|
WriteByte(MSG_MULTICAST, stof(argv(6)));
|
|
WriteByte(MSG_MULTICAST, stof(argv(7)));
|
|
WriteByte(MSG_MULTICAST, stof(argv(8)));
|
|
WriteByte(MSG_MULTICAST, stof(argv(9)));
|
|
WriteByte(MSG_MULTICAST, stof(argv(10)));
|
|
WriteByte(MSG_MULTICAST, stof(argv(11)));
|
|
|
|
msg_entity = this;
|
|
multicast(origin, MULTICAST_PVS);
|
|
break;
|
|
case "SetOrigin":
|
|
SetOrigin(stov(strData));
|
|
break;
|
|
case "SetSpawnOrigin":
|
|
m_oldOrigin = stov(strData);
|
|
break;
|
|
case "SetEditorColor":
|
|
m_vecEditorColor = ReadVector(strData);
|
|
break;
|
|
case "Respawn":
|
|
Respawn();
|
|
break;
|
|
default:
|
|
NSTrigger::Input(eAct, strInput, strData);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
void
|
|
NSEntity::SpawnKey(string strKey, string strValue)
|
|
{
|
|
bool tempCheck = false;
|
|
/* we do re-read a lot of the builtin fields in case we want to set
|
|
defaults. just in case anybody is wondering. */
|
|
switch (strKey) {
|
|
case "spawnflags":
|
|
spawnflags = ReadFloat(strValue);
|
|
break;
|
|
case "origin":
|
|
origin = ReadVector(strValue);
|
|
break;
|
|
case "model":
|
|
model = ReadString(strValue);
|
|
break;
|
|
case "angles":
|
|
angles = ReadVector(strValue);
|
|
break;
|
|
case "angle":
|
|
angles[1] = ReadFloat(strValue);
|
|
break;
|
|
case "solid":
|
|
solid = ReadFloat(strValue);
|
|
break;
|
|
case "friction":
|
|
friction = ReadFloat(strValue);
|
|
break;
|
|
case "editor_color":
|
|
m_vecEditorColor = ReadVector(strValue);
|
|
break;
|
|
#ifdef SERVER
|
|
case "health":
|
|
health = ReadFloat(strValue);
|
|
break;
|
|
case "movewith":
|
|
case "parentname":
|
|
SetParent(ReadString(strValue));
|
|
break;
|
|
case "ignorepvs":
|
|
tempCheck = ReadBool(strValue);
|
|
|
|
if (tempCheck == true)
|
|
pvsflags = PVSF_IGNOREPVS;
|
|
else
|
|
pvsflags &= ~PVSF_IGNOREPVS;
|
|
|
|
break;
|
|
#endif
|
|
case "editor_mins":
|
|
case "editor_maxs":
|
|
case "editor_usage":
|
|
case "editor_model":
|
|
case "_minlight":
|
|
break;
|
|
default:
|
|
super::SpawnKey(strKey, strValue);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void
|
|
NSEntity::OnRemoveEntity(void)
|
|
{
|
|
}
|
|
|
|
void
|
|
NSEntity::Destroy(void)
|
|
{
|
|
removed = 1; /* mark this as cleanly removed */
|
|
OnRemoveEntity();
|
|
customphysics = __NULL__;
|
|
modelindex = 0;
|
|
solid = 0;
|
|
movetype = 0;
|
|
classname = 0;
|
|
ScheduleThink(Util_Destroy, 0.0f);
|
|
}
|
|
|
|
void
|
|
NSEntity::Show(void)
|
|
{
|
|
effects &= ~EF_NODRAW;
|
|
}
|
|
|
|
void
|
|
NSEntity::Hide(void)
|
|
{
|
|
effects |= EF_NODRAW;
|
|
}
|
|
|
|
bool
|
|
NSEntity::IsHidden(void)
|
|
{
|
|
return (effects & EF_NODRAW) ? true : false;
|
|
}
|
|
|
|
void
|
|
NSEntity::Disappear(void)
|
|
{
|
|
modelindex = (0);
|
|
SetSolid(SOLID_NOT);
|
|
}
|
|
|
|
void
|
|
NSEntity::MakeStatic(void)
|
|
{
|
|
makestatic(this);
|
|
}
|
|
|
|
bool
|
|
NSEntity::CanSpawn(bool clientSide)
|
|
{
|
|
return !(clientSide);
|
|
}
|
|
|
|
bool
|
|
NSEntity::WithinBounds(entity check)
|
|
{
|
|
if not (check.absmin[0] >= absmin[0] && check.absmax[0] <= absmax[0])
|
|
return (false);
|
|
if not (check.absmin[1] >= absmin[1] && check.absmax[1] <= absmax[1])
|
|
return (false);
|
|
if not (check.absmin[2] >= absmin[2] && check.absmax[2] <= absmax[2])
|
|
return (false);
|
|
|
|
return (true);
|
|
}
|
|
|
|
bool
|
|
NSEntity::IntersectsWith(entity check)
|
|
{
|
|
if not (check.origin[0] >= absmin[0] && check.origin[0] <= absmax[0])
|
|
return (false);
|
|
if not (check.origin[1] >= absmin[1] && check.origin[1] <= absmax[1])
|
|
return (false);
|
|
if not (check.origin[2] >= absmin[2] && check.origin[2] <= absmax[2])
|
|
return (false);
|
|
|
|
return (true);
|
|
}
|
|
|
|
bool
|
|
NSEntity::StartSound(string strSample, float channel, float flags, bool broadcast)
|
|
{
|
|
if not (whichpack(strcat("sound/", strSample)))
|
|
return (false);
|
|
|
|
if (broadcast) {
|
|
sound(this, channel, strSample, 1.0f, ATTN_NORM, 0, SOUNDFLAG_FOLLOW);
|
|
} else {
|
|
#ifdef SERVER
|
|
msg_entity = this;
|
|
sound(this, channel, strSample, 1.0f, ATTN_NORM, 0, SOUNDFLAG_UNICAST | SOUNDFLAG_FOLLOW);
|
|
msg_entity = __NULL__;
|
|
#else
|
|
sound(this, channel, strSample, 1.0f, ATTN_NORM, 0, SOUNDFLAG_FOLLOW);
|
|
#endif
|
|
}
|
|
|
|
SndEntLog("%s (chan: %d bcast: %d) (%v)", strSample, channel, broadcast, origin);
|
|
|
|
return (true);
|
|
}
|
|
|
|
bool
|
|
NSEntity::StartSoundDef(string strSample, float channel, bool broadcast)
|
|
{
|
|
SndEntLog("%s (chan: %d bcast: %d)", strSample, channel, broadcast);
|
|
Sound_Play(this, channel, strSample);
|
|
return (true);
|
|
}
|
|
|
|
void
|
|
NSEntity::StopSound(float channel, bool broadcast)
|
|
{
|
|
if (broadcast) {
|
|
Sound_Stop(this, channel);
|
|
} else {
|
|
#ifdef SERVER
|
|
msg_entity = this;
|
|
sound(this, channel, "common/null.wav", 1.0f, ATTN_NORM, 100, SOUNDFLAG_UNICAST | SOUNDFLAG_FOLLOW, 0 );
|
|
msg_entity = __NULL__;
|
|
#else
|
|
Sound_Stop(this, channel);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
vector
|
|
NSEntity::NearestWallPointForRadius(float radius)
|
|
{
|
|
vector vecRadius = [radius, radius, radius];
|
|
tracebox(origin, -vecRadius, vecRadius, origin, MOVE_EVERYTHING, this);
|
|
return (trace_fraction <= 1.0) ? trace_endpos : origin;
|
|
}
|
|
|
|
void
|
|
NSEntity::HandleThink(void)
|
|
{
|
|
/* support for think/nextthink */
|
|
if (think && nextthink > 0.0f) {
|
|
if (nextthink < time) {
|
|
nextthink = 0.0f;
|
|
think();
|
|
}
|
|
}
|
|
}
|
|
|
|
bool
|
|
NSEntity::IsFacing(entity target)
|
|
{
|
|
vector vecDiff = vectorNormalize(target.origin - origin);
|
|
return ((vecDiff * GetForward()) > 0) ? true : false;
|
|
}
|
|
|
|
bool
|
|
NSEntity::IsFacingPosition(vector targetPos)
|
|
{
|
|
vector vecDiff = vectorNormalize(targetPos - origin);
|
|
return ((vecDiff * GetForward()) > 0) ? true : false;
|
|
}
|
|
|
|
float
|
|
NSEntity::GetSpawnAge(void)
|
|
{
|
|
return (time - m_flSpawnTime);
|
|
}
|
|
|
|
float
|
|
NSEntity::GetSpawnTime(void)
|
|
{
|
|
return (m_flSpawnTime);
|
|
}
|
|
|
|
void
|
|
NSEntity::Transport(vector new_pos, vector new_ang)
|
|
{
|
|
float flSpeed = length(this.GetVelocity());
|
|
SetVelocity(anglesToForward(new_ang) * flSpeed);
|
|
|
|
SetOrigin(new_pos);
|
|
SetAngles(new_ang);
|
|
|
|
#ifdef SERVER
|
|
if (flags & FL_CLIENT)
|
|
Client_FixAngle(this, new_ang);
|
|
#endif
|
|
}
|
|
|
|
void
|
|
NSEntity::Relink(void)
|
|
{
|
|
setorigin(this, origin);
|
|
}
|
|
|
|
vector
|
|
NSEntity::GetNearbySpot(void)
|
|
{
|
|
vector testPos;
|
|
float minDist = maxs[0];
|
|
vector fwdDir, rightDir, upDir;
|
|
|
|
fwdDir = anglesToForward([0,0,0]);
|
|
rightDir = anglesToRight([0,0,0]);
|
|
upDir = anglesToUp([0,0,0]);
|
|
|
|
/* space in front? */
|
|
testPos = GetOrigin() + fwdDir * minDist;
|
|
tracebox(testPos, mins, maxs, testPos, MOVE_NORMAL, this);
|
|
|
|
if (trace_fraction == 1.0f)
|
|
return testPos;
|
|
|
|
/* behind? */
|
|
testPos = GetOrigin() - fwdDir * minDist;
|
|
tracebox(testPos, mins, maxs, testPos, MOVE_NORMAL, this);
|
|
|
|
if (trace_fraction == 1.0f)
|
|
return testPos;
|
|
|
|
/* left? */
|
|
testPos = GetOrigin() - rightDir * minDist;
|
|
tracebox(testPos, mins, maxs, testPos, MOVE_NORMAL, this);
|
|
|
|
if (trace_fraction == 1.0f)
|
|
return testPos;
|
|
|
|
/* right? */
|
|
testPos = GetOrigin() + rightDir * minDist;
|
|
tracebox(testPos, mins, maxs, testPos, MOVE_NORMAL, this);
|
|
|
|
if (trace_fraction == 1.0f)
|
|
return testPos;
|
|
|
|
/* front left? */
|
|
testPos = GetOrigin() + fwdDir * minDist - rightDir * minDist;
|
|
tracebox(testPos, mins, maxs, testPos, MOVE_NORMAL, this);
|
|
|
|
if (trace_fraction == 1.0f)
|
|
return testPos;
|
|
|
|
/* front right? */
|
|
testPos = GetOrigin() + fwdDir * minDist + rightDir * minDist;
|
|
tracebox(testPos, mins, maxs, testPos, MOVE_NORMAL, this);
|
|
|
|
if (trace_fraction == 1.0f)
|
|
return testPos;
|
|
|
|
/* back left? */
|
|
testPos = GetOrigin() - fwdDir * minDist - rightDir * minDist;
|
|
tracebox(testPos, mins, maxs, testPos, MOVE_NORMAL, this);
|
|
|
|
if (trace_fraction == 1.0f)
|
|
return testPos;
|
|
|
|
/* back right? */
|
|
testPos = GetOrigin() - fwdDir * minDist + rightDir * minDist;
|
|
tracebox(testPos, mins, maxs, testPos, MOVE_NORMAL, this);
|
|
|
|
if (trace_fraction == 1.0f)
|
|
return testPos;
|
|
|
|
return g_vec_null;
|
|
}
|