2021-10-19 23:18:36 +00:00
|
|
|
/*
|
2022-03-11 19:40:43 +00:00
|
|
|
* Copyright (c) 2016-2021 Marco Cawthorne <marco@icculus.org>
|
2021-10-19 23:18:36 +00:00
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
2022-04-02 07:10:25 +00:00
|
|
|
float
|
|
|
|
NSEntity::EntIndex(void)
|
|
|
|
{
|
|
|
|
return num_for_edict(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
droptofloorwrapper(entity foo)
|
|
|
|
{
|
|
|
|
entity old_self = self;
|
|
|
|
self = foo;
|
|
|
|
droptofloor();
|
|
|
|
self = old_self;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
NSEntity::DropToFloor(void)
|
|
|
|
{
|
|
|
|
droptofloorwrapper(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
vector
|
|
|
|
NSEntity::GetForward(void)
|
|
|
|
{
|
|
|
|
makevectors(angles);
|
|
|
|
return v_forward;
|
|
|
|
}
|
|
|
|
|
|
|
|
vector
|
|
|
|
NSEntity::GetRight(void)
|
|
|
|
{
|
|
|
|
makevectors(angles);
|
|
|
|
return v_right;
|
|
|
|
}
|
|
|
|
|
|
|
|
vector
|
|
|
|
NSEntity::GetUp(void)
|
|
|
|
{
|
|
|
|
makevectors(angles);
|
|
|
|
return v_up;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
============
|
|
|
|
NSEntity::WorldSpaceCenter
|
|
|
|
|
|
|
|
Returns the center of an entity's bounding boxes.
|
|
|
|
Useful on brush entities that have no real 'origin' defined.
|
|
|
|
============
|
|
|
|
*/
|
|
|
|
vector
|
|
|
|
NSEntity::WorldSpaceCenter(void)
|
|
|
|
{
|
|
|
|
return absmin + (0.5 * (absmax - absmin));
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
============
|
|
|
|
NSEntity::VisibleVec
|
|
|
|
|
|
|
|
Returns whether or not the entity is able to see a given position
|
|
|
|
============
|
|
|
|
*/
|
|
|
|
float
|
|
|
|
NSEntity::WaterLevel(void)
|
|
|
|
{
|
|
|
|
return waterlevel;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
============
|
|
|
|
NSEntity::VisibleVec
|
|
|
|
|
|
|
|
Returns whether or not the entity is able to see a given position
|
|
|
|
============
|
|
|
|
*/
|
|
|
|
bool
|
|
|
|
NSEntity::VisibleVec(vector org)
|
|
|
|
{
|
|
|
|
vector flDelta;
|
|
|
|
float flFoV;
|
|
|
|
|
|
|
|
makevectors(angles);
|
|
|
|
flDelta = normalize (org - origin);
|
|
|
|
flFoV = flDelta * v_forward;
|
|
|
|
|
|
|
|
if (flFoV > 0.3) {
|
|
|
|
traceline(origin, org, TRUE, this);
|
|
|
|
if (trace_fraction == 1.0) {
|
|
|
|
return (TRUE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return (FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
============
|
|
|
|
NSEntity::Visible
|
|
|
|
|
|
|
|
Returns whether or not the entity is able to see a given entity
|
|
|
|
============
|
|
|
|
*/
|
|
|
|
bool
|
|
|
|
NSEntity::Visible(entity ent)
|
|
|
|
{
|
|
|
|
vector flDelta;
|
|
|
|
float flFoV;
|
|
|
|
|
|
|
|
makevectors(angles);
|
|
|
|
flDelta = normalize (ent.origin - origin);
|
|
|
|
flFoV = flDelta * v_forward;
|
|
|
|
|
|
|
|
if (flFoV > 0.3) {
|
|
|
|
traceline(origin, ent.origin, MOVE_NORMAL, this);
|
|
|
|
if (trace_fraction == 1.0) {
|
|
|
|
return (true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return (false);
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2022-04-06 23:21:07 +00:00
|
|
|
bool
|
|
|
|
NSEntity::CreatedByMap(void)
|
|
|
|
{
|
|
|
|
return _mapspawned;
|
|
|
|
}
|
|
|
|
|
2022-04-02 07:10:25 +00:00
|
|
|
void
|
|
|
|
NSEntity::Blocked(entity eBlocker)
|
|
|
|
{
|
|
|
|
/* To be handled by sub-classes */
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2022-04-03 21:04:34 +00:00
|
|
|
NSEntity::BlockedHandler(void)
|
2022-04-02 07:10:25 +00:00
|
|
|
{
|
|
|
|
Blocked(other);
|
|
|
|
}
|
|
|
|
|
2022-04-03 21:04:34 +00:00
|
|
|
void
|
|
|
|
NSEntity::Touch(entity eToucher)
|
|
|
|
{
|
|
|
|
/* To be handled by sub-classes */
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
NSEntity::StartTouch(entity eToucher)
|
|
|
|
{
|
|
|
|
/* To be handled by sub-classes */
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
NSEntity::EndTouch(entity eToucher)
|
|
|
|
{
|
|
|
|
/* To be handled by sub-classes */
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
NSEntity::TouchHandler(void)
|
|
|
|
{
|
|
|
|
/* start touch in case we haven't */
|
|
|
|
if (m_beingTouched != true)
|
|
|
|
StartTouch(other);
|
|
|
|
|
|
|
|
Touch(other);
|
|
|
|
|
|
|
|
m_flTouchTime = time;
|
|
|
|
m_beingTouched = true;
|
|
|
|
m_eTouchLast = other;
|
|
|
|
}
|
|
|
|
|
2021-10-19 23:18:36 +00:00
|
|
|
#ifdef CLIENT
|
|
|
|
/*
|
|
|
|
============
|
|
|
|
NSEntity::RendererRestarted
|
|
|
|
|
|
|
|
make sure any child-classes precache their assets in here
|
|
|
|
for vid_reload calls or other sudden deaths (driver restarts)
|
|
|
|
============
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
NSEntity::RendererRestarted(void)
|
|
|
|
{
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
============
|
|
|
|
NSEntity::ReceiveEntity
|
|
|
|
============
|
|
|
|
*/
|
|
|
|
void
|
2022-01-21 00:23:29 +00:00
|
|
|
NSEntity::ReceiveEntity(float flNew, float flChanged)
|
2021-10-19 23:18:36 +00:00
|
|
|
{
|
|
|
|
if (flChanged & BASEFL_CHANGED_ORIGIN) {
|
|
|
|
origin[0] = readcoord();
|
|
|
|
origin[1] = readcoord();
|
|
|
|
origin[2] = readcoord();
|
|
|
|
}
|
|
|
|
if (flChanged & BASEFL_CHANGED_ANGLES) {
|
|
|
|
angles[0] = readshort() / (32767 / 360);
|
|
|
|
angles[1] = readshort() / (32767 / 360);
|
|
|
|
angles[2] = readshort() / (32767 / 360);
|
|
|
|
}
|
|
|
|
if (flChanged & BASEFL_CHANGED_MODELINDEX) {
|
|
|
|
setmodelindex(this, readshort());
|
|
|
|
}
|
|
|
|
if (flChanged & BASEFL_CHANGED_SOLID) {
|
|
|
|
solid = readbyte();
|
|
|
|
}
|
|
|
|
if (flChanged & BASEFL_CHANGED_MOVETYPE) {
|
|
|
|
movetype = readbyte();
|
|
|
|
|
|
|
|
if (movetype == MOVETYPE_PHYSICS) {
|
|
|
|
movetype = MOVETYPE_NONE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (flChanged & BASEFL_CHANGED_SIZE) {
|
|
|
|
mins[0] = readcoord();
|
|
|
|
mins[1] = readcoord();
|
|
|
|
mins[2] = readcoord();
|
|
|
|
maxs[0] = readcoord();
|
|
|
|
maxs[1] = readcoord();
|
|
|
|
maxs[2] = readcoord();
|
|
|
|
setsize(this, mins, maxs);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flChanged & BASEFL_CHANGED_VELOCITY) {
|
|
|
|
velocity[0] = readfloat();
|
|
|
|
velocity[1] = readfloat();
|
|
|
|
velocity[2] = readfloat();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (modelindex) {
|
|
|
|
drawmask = MASK_ENGINE;
|
|
|
|
} else {
|
|
|
|
drawmask = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (scale == 0.0)
|
|
|
|
scale = 1.0f;
|
|
|
|
|
|
|
|
setorigin(this, origin);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
============
|
|
|
|
NSEntity::postdraw
|
|
|
|
============
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
NSEntity::postdraw(void)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#else
|
|
|
|
void
|
|
|
|
NSEntity::Show(void)
|
|
|
|
{
|
|
|
|
alpha = 1.0f;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
NSEntity::Hide(void)
|
|
|
|
{
|
|
|
|
alpha = 0.0f;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Make sure StartFrame calls this */
|
|
|
|
float
|
|
|
|
NSEntity::SendEntity(entity ePEnt, float fChanged)
|
|
|
|
{
|
|
|
|
if (!modelindex)
|
|
|
|
return (0);
|
|
|
|
|
|
|
|
if (clienttype(ePEnt) != CLIENTTYPE_REAL)
|
|
|
|
return (0);
|
|
|
|
|
|
|
|
if (alpha == 0.0f)
|
|
|
|
return (0);
|
|
|
|
|
|
|
|
WriteByte(MSG_ENTITY, ENT_ENTITY);
|
|
|
|
|
|
|
|
/* newly popped into the PVS, sadly this is the only hacky way to check
|
|
|
|
* for this right now. convince the engine maintainer to make this more sensible */
|
|
|
|
if (fChanged == 0xFFFFFF) {
|
|
|
|
/* check for defaults. if these are predictable fields, don't even bother
|
|
|
|
* networking them! you're just wasting bandwidth. */
|
|
|
|
if (scale == 0.0 || scale == 1.0)
|
|
|
|
fChanged &= ~BASEFL_CHANGED_SCALE;
|
|
|
|
if (origin == [0,0,0])
|
|
|
|
fChanged &= ~BASEFL_CHANGED_ORIGIN;
|
|
|
|
if (angles == [0,0,0])
|
|
|
|
fChanged &= ~BASEFL_CHANGED_ANGLES;
|
|
|
|
if (velocity == [0,0,0])
|
|
|
|
fChanged &= ~BASEFL_CHANGED_VELOCITY;
|
|
|
|
if (mins == [0,0,0] && maxs == [0,0,0])
|
|
|
|
fChanged &= ~BASEFL_CHANGED_SIZE;
|
|
|
|
if (solid == SOLID_NOT)
|
|
|
|
fChanged &= ~BASEFL_CHANGED_SOLID;
|
|
|
|
if (movetype == MOVETYPE_NONE)
|
|
|
|
fChanged &= ~BASEFL_CHANGED_MOVETYPE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* don't network triggers unless provoked */
|
|
|
|
/*if (cvar("developer") == 0 && m_iRenderMode == RM_TRIGGER)
|
|
|
|
return (0);*/
|
|
|
|
|
|
|
|
/* broadcast how much data is expected to be read */
|
|
|
|
WriteFloat(MSG_ENTITY, fChanged);
|
|
|
|
|
|
|
|
/* really trying to get our moneys worth with 23 bits of mantissa */
|
|
|
|
if (fChanged & BASEFL_CHANGED_ORIGIN) {
|
|
|
|
WriteCoord(MSG_ENTITY, origin[0]);
|
|
|
|
WriteCoord(MSG_ENTITY, origin[1]);
|
|
|
|
WriteCoord(MSG_ENTITY, origin[2]);
|
|
|
|
}
|
|
|
|
if (fChanged & BASEFL_CHANGED_ANGLES) {
|
|
|
|
WriteShort(MSG_ENTITY, angles[0] * 32767 / 360);
|
|
|
|
WriteShort(MSG_ENTITY, angles[1] * 32767 / 360);
|
|
|
|
WriteShort(MSG_ENTITY, angles[2] * 32767 / 360);
|
|
|
|
}
|
|
|
|
if (fChanged & BASEFL_CHANGED_MODELINDEX) {
|
|
|
|
WriteShort(MSG_ENTITY, modelindex);
|
|
|
|
}
|
|
|
|
if (fChanged & BASEFL_CHANGED_SOLID) {
|
|
|
|
WriteByte(MSG_ENTITY, solid);
|
|
|
|
}
|
|
|
|
if (fChanged & BASEFL_CHANGED_MOVETYPE) {
|
|
|
|
WriteByte(MSG_ENTITY, movetype);
|
|
|
|
}
|
|
|
|
if (fChanged & BASEFL_CHANGED_SIZE) {
|
|
|
|
WriteCoord(MSG_ENTITY, mins[0]);
|
|
|
|
WriteCoord(MSG_ENTITY, mins[1]);
|
|
|
|
WriteCoord(MSG_ENTITY, mins[2]);
|
|
|
|
WriteCoord(MSG_ENTITY, maxs[0]);
|
|
|
|
WriteCoord(MSG_ENTITY, maxs[1]);
|
|
|
|
WriteCoord(MSG_ENTITY, maxs[2]);
|
|
|
|
}
|
|
|
|
if (fChanged & BASEFL_CHANGED_VELOCITY) {
|
|
|
|
WriteFloat(MSG_ENTITY, velocity[0]);
|
|
|
|
WriteFloat(MSG_ENTITY, velocity[1]);
|
|
|
|
WriteFloat(MSG_ENTITY, velocity[2]);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
NSEntity::EvaluateEntity(void)
|
|
|
|
{
|
|
|
|
/* while the engine is still handling physics for these, we can't
|
|
|
|
* predict when origin/angle might change */
|
2022-02-18 08:30:24 +00:00
|
|
|
if (ATTR_CHANGED(origin)) {
|
2021-10-19 23:18:36 +00:00
|
|
|
SetSendFlags(BASEFL_CHANGED_ORIGIN);
|
|
|
|
}
|
2022-02-18 08:30:24 +00:00
|
|
|
|
|
|
|
if (ATTR_CHANGED(angles)) {
|
2021-10-19 23:18:36 +00:00
|
|
|
angles[0] = Math_FixDelta(angles[0]);
|
|
|
|
angles[1] = Math_FixDelta(angles[1]);
|
|
|
|
angles[2] = Math_FixDelta(angles[2]);
|
|
|
|
SetSendFlags(BASEFL_CHANGED_ANGLES);
|
|
|
|
}
|
2022-02-18 08:30:24 +00:00
|
|
|
|
|
|
|
if (ATTR_CHANGED(modelindex)) {
|
|
|
|
SetSendFlags(BASEFL_CHANGED_MODELINDEX);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ATTR_CHANGED(size)) {
|
|
|
|
SetSendFlags(BASEFL_CHANGED_SIZE);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ATTR_CHANGED(solid)) {
|
|
|
|
SetSendFlags(BASEFL_CHANGED_SOLID);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ATTR_CHANGED(movetype)) {
|
|
|
|
SetSendFlags(BASEFL_CHANGED_MOVETYPE);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ATTR_CHANGED(scale)) {
|
|
|
|
SetSendFlags(BASEFL_CHANGED_SCALE);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ATTR_CHANGED(velocity)) {
|
2021-10-19 23:18:36 +00:00
|
|
|
SetSendFlags(BASEFL_CHANGED_VELOCITY);
|
|
|
|
}
|
2022-02-18 08:30:24 +00:00
|
|
|
|
|
|
|
SAVE_STATE(origin);
|
|
|
|
SAVE_STATE(angles);
|
|
|
|
SAVE_STATE(modelindex);
|
|
|
|
SAVE_STATE(size);
|
|
|
|
SAVE_STATE(solid);
|
|
|
|
SAVE_STATE(movetype);
|
|
|
|
SAVE_STATE(scale);
|
|
|
|
SAVE_STATE(velocity);
|
2021-10-19 23:18:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Make sure StartFrame calls this */
|
|
|
|
void
|
|
|
|
NSEntity::ParentUpdate(void)
|
|
|
|
{
|
|
|
|
EvaluateEntity();
|
|
|
|
|
|
|
|
frame1time += frametime;
|
|
|
|
|
|
|
|
if (m_parent) {
|
2022-03-25 00:59:30 +00:00
|
|
|
NSEntity parent;
|
2021-10-19 23:18:36 +00:00
|
|
|
entity p = find(world, ::targetname, m_parent);
|
|
|
|
|
2022-03-25 00:59:30 +00:00
|
|
|
if (p) {
|
|
|
|
if (!m_parent_attachment) {
|
|
|
|
parent = (NSEntity)p;
|
2022-03-29 03:20:29 +00:00
|
|
|
vector ofs = parent.origin - parent.GetSpawnOrigin();
|
|
|
|
SetOrigin(GetSpawnOrigin() + ofs);
|
2022-03-25 00:59:30 +00:00
|
|
|
} else if (m_parent_attachment == "origin") {
|
|
|
|
SetOrigin(p.origin);
|
|
|
|
}
|
|
|
|
}
|
2021-10-19 23:18:36 +00:00
|
|
|
}
|
2022-04-03 21:04:34 +00:00
|
|
|
|
|
|
|
/* handle end-touch */
|
|
|
|
if (m_beingTouched == true)
|
|
|
|
if (m_flTouchTime < time) {
|
|
|
|
EndTouch(m_eTouchLast);
|
|
|
|
m_beingTouched = false;
|
|
|
|
m_eTouchLast = __NULL__;
|
|
|
|
}
|
2021-10-19 23:18:36 +00:00
|
|
|
}
|
2022-04-02 07:10:25 +00:00
|
|
|
entity
|
|
|
|
NSEntity::GetParent(void)
|
|
|
|
{
|
|
|
|
return find(world, ::targetname, m_parent);
|
|
|
|
}
|
2021-10-19 23:18:36 +00:00
|
|
|
void
|
|
|
|
NSEntity::SetParent(string name)
|
|
|
|
{
|
|
|
|
m_parent = name;
|
|
|
|
}
|
|
|
|
void
|
2022-03-25 00:59:30 +00:00
|
|
|
NSEntity::SetParentAttachment(string name)
|
|
|
|
{
|
|
|
|
m_parent_attachment = name;
|
|
|
|
}
|
|
|
|
void
|
2021-10-19 23:18:36 +00:00
|
|
|
NSEntity::ClearParent(void)
|
|
|
|
{
|
|
|
|
m_parent = __NULL__;
|
2022-03-25 00:59:30 +00:00
|
|
|
m_parent_attachment = __NULL__;
|
2021-10-19 23:18:36 +00:00
|
|
|
}
|
2022-01-03 08:23:20 +00:00
|
|
|
|
|
|
|
void
|
|
|
|
NSEntity::RestoreAngles(void)
|
|
|
|
{
|
|
|
|
angles = GetSpawnAngles();
|
|
|
|
}
|
|
|
|
void
|
|
|
|
NSEntity::ClearAngles(void)
|
|
|
|
{
|
|
|
|
angles = [0,0,0];
|
|
|
|
}
|
2021-10-19 23:18:36 +00:00
|
|
|
#endif
|
|
|
|
|
2022-02-02 18:23:31 +00:00
|
|
|
void
|
|
|
|
NSEntity::SetOwner(entity newOwner)
|
|
|
|
{
|
|
|
|
owner = newOwner;
|
|
|
|
};
|
|
|
|
|
|
|
|
void
|
|
|
|
NSEntity::SetVelocity(vector vecNew)
|
|
|
|
{
|
|
|
|
velocity = vecNew;
|
|
|
|
};
|
|
|
|
|
|
|
|
void
|
|
|
|
NSEntity::SetTouch(void() newTouch)
|
|
|
|
{
|
|
|
|
touch = newTouch;
|
|
|
|
};
|
|
|
|
|
2021-10-19 23:18:36 +00:00
|
|
|
/* 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;
|
|
|
|
}
|
2022-04-03 21:04:34 +00:00
|
|
|
|
2021-10-19 23:18:36 +00:00
|
|
|
void
|
2022-04-03 21:04:34 +00:00
|
|
|
NSEntity::SetGravity(float newGrav)
|
2021-10-19 23:18:36 +00:00
|
|
|
{
|
2022-04-03 21:04:34 +00:00
|
|
|
gravity = newGrav;
|
|
|
|
}
|
2021-10-19 23:18:36 +00:00
|
|
|
|
2022-04-03 21:04:34 +00:00
|
|
|
void
|
|
|
|
NSEntity::SetSolid(float newSolid)
|
|
|
|
{
|
2021-10-19 23:18:36 +00:00
|
|
|
solid = newSolid;
|
|
|
|
}
|
2022-02-02 18:23:31 +00:00
|
|
|
void
|
|
|
|
NSEntity::SetScale(float newScale)
|
|
|
|
{
|
|
|
|
scale = newScale;
|
|
|
|
}
|
2021-10-19 23:18:36 +00:00
|
|
|
|
2022-01-20 20:18:24 +00:00
|
|
|
void
|
|
|
|
NSEntity::UpdateBounds(void)
|
|
|
|
{
|
2022-01-21 20:24:25 +00:00
|
|
|
vector newMins, newMaxs;
|
2022-01-20 20:18:24 +00:00
|
|
|
float flScale = 1.0f;
|
|
|
|
|
2022-02-01 21:37:21 +00:00
|
|
|
newMins = m_vecMins;
|
|
|
|
newMaxs = m_vecMaxs;
|
|
|
|
|
2022-01-20 20:18:24 +00:00
|
|
|
/* 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] = Math_RotateAroundPivot(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 */
|
2022-01-21 20:24:25 +00:00
|
|
|
if (scale != 0.0)
|
|
|
|
flScale = scale;
|
|
|
|
|
|
|
|
setsize(this, newMins * flScale, newMaxs * flScale);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
NSEntity::SetAngles(vector newAngles)
|
|
|
|
{
|
|
|
|
angles = newAngles;
|
|
|
|
}
|
|
|
|
|
2022-04-03 21:04:34 +00:00
|
|
|
void
|
|
|
|
NSEntity::SetAngularVelocity(vector newAvel)
|
|
|
|
{
|
|
|
|
avelocity = newAvel;
|
|
|
|
}
|
|
|
|
|
2022-01-21 20:24:25 +00:00
|
|
|
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 */
|
2021-11-10 02:00:09 +00:00
|
|
|
if (scale != 0.0)
|
2022-01-20 20:18:24 +00:00
|
|
|
flScale = scale;
|
2021-11-10 02:00:09 +00:00
|
|
|
|
2022-01-20 20:18:24 +00:00
|
|
|
setsize(this, newMins * flScale, newMaxs * flScale);
|
2021-10-19 23:18:36 +00:00
|
|
|
}
|
2022-01-20 20:18:24 +00:00
|
|
|
|
2021-10-19 23:18:36 +00:00
|
|
|
void
|
|
|
|
NSEntity::SetOrigin(vector newOrigin)
|
|
|
|
{
|
|
|
|
setorigin(this, newOrigin);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
NSEntity::SetModel(string newModel)
|
|
|
|
{
|
|
|
|
model = newModel;
|
|
|
|
setmodel(this, newModel);
|
2022-01-20 20:18:24 +00:00
|
|
|
|
|
|
|
/* mins/maxs have been updated by setmodel */
|
2021-11-10 01:33:31 +00:00
|
|
|
SetSize(mins, maxs);
|
2021-10-19 23:18:36 +00:00
|
|
|
}
|
|
|
|
void
|
|
|
|
NSEntity::SetModelindex(float newModelIndex)
|
|
|
|
{
|
|
|
|
if (newModelIndex == modelindex)
|
|
|
|
return;
|
|
|
|
|
|
|
|
modelindex = newModelIndex;
|
2021-11-10 01:33:31 +00:00
|
|
|
SetSize(mins, maxs);
|
2021-10-19 23:18:36 +00:00
|
|
|
}
|
|
|
|
|
2022-04-03 21:04:34 +00:00
|
|
|
void
|
|
|
|
NSEntity::AddFlags(float fl)
|
|
|
|
{
|
|
|
|
flags |= fl;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
NSEntity::RemoveFlags(float fl)
|
|
|
|
{
|
|
|
|
flags &= ~fl;
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-10-19 23:18:36 +00:00
|
|
|
#ifdef SERVER
|
|
|
|
vector
|
|
|
|
NSEntity::GetSpawnOrigin(void)
|
|
|
|
{
|
|
|
|
return m_oldOrigin;
|
|
|
|
}
|
|
|
|
vector
|
|
|
|
NSEntity::GetSpawnAngles(void)
|
|
|
|
{
|
|
|
|
return m_oldAngle;
|
|
|
|
}
|
|
|
|
string
|
|
|
|
NSEntity::GetSpawnModel(void)
|
|
|
|
{
|
|
|
|
return m_oldModel;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
NSEntity::Respawn(void)
|
|
|
|
{
|
|
|
|
NSTrigger::Respawn();
|
|
|
|
|
|
|
|
SetSolid(m_oldSolid);
|
|
|
|
SetAngles(GetSpawnAngles());
|
|
|
|
SetOrigin(GetSpawnOrigin());
|
|
|
|
SetModel(GetSpawnModel());
|
2021-10-22 23:00:15 +00:00
|
|
|
target = m_oldstrTarget; /* FIXME: Move into NSTrigger::Respawn */
|
2021-10-19 23:18:36 +00:00
|
|
|
}
|
|
|
|
|
2021-10-22 18:51:51 +00:00
|
|
|
void
|
|
|
|
NSEntity::Save(float handle)
|
|
|
|
{
|
2022-03-18 04:05:47 +00:00
|
|
|
SaveFloat(handle, "spawnflags", spawnflags);
|
2021-10-31 18:15:32 +00:00
|
|
|
SaveVector(handle, "origin", origin);
|
|
|
|
SaveVector(handle, "absmin", absmin);
|
|
|
|
SaveVector(handle, "absmax", absmax);
|
2021-10-22 23:00:15 +00:00
|
|
|
SaveVector(handle, "mins", mins);
|
|
|
|
SaveVector(handle, "maxs", maxs);
|
2021-10-31 18:15:32 +00:00
|
|
|
SaveString(handle, "model", model);
|
2021-10-22 23:00:15 +00:00
|
|
|
SaveVector(handle, "angles", angles);
|
2021-10-31 18:15:32 +00:00
|
|
|
SaveFloat(handle, "solid", solid);
|
|
|
|
SaveFloat(handle, "movetype", movetype);
|
|
|
|
SaveFloat(handle, "health", health);
|
2021-10-22 18:51:51 +00:00
|
|
|
SaveString(handle, "parentname", m_parent);
|
2021-10-31 18:15:32 +00:00
|
|
|
SaveFloat(handle, "pvsflags", pvsflags);
|
2022-04-06 23:21:07 +00:00
|
|
|
SaveFloat(handle, "_mapspawned", _mapspawned);
|
2021-10-22 18:51:51 +00:00
|
|
|
super::Save(handle);
|
|
|
|
}
|
|
|
|
void
|
|
|
|
NSEntity::Restore(string strKey, string strValue)
|
|
|
|
{
|
|
|
|
switch (strKey) {
|
2022-03-18 04:05:47 +00:00
|
|
|
case "spawnflags":
|
|
|
|
spawnflags = stof(strValue);
|
|
|
|
break;
|
2021-10-22 18:51:51 +00:00
|
|
|
case "origin":
|
|
|
|
origin = stov(strValue);
|
2021-10-22 23:00:15 +00:00
|
|
|
setorigin(this, origin);
|
2021-10-22 18:51:51 +00:00
|
|
|
break;
|
2021-10-22 19:20:22 +00:00
|
|
|
case "absmin":
|
|
|
|
absmin = stov(strValue);
|
|
|
|
break;
|
|
|
|
case "absmax":
|
|
|
|
absmax = stov(strValue);
|
|
|
|
break;
|
|
|
|
case "mins":
|
|
|
|
mins = stov(strValue);
|
2021-10-22 23:00:15 +00:00
|
|
|
setsize(this, mins, maxs);
|
2021-10-22 19:20:22 +00:00
|
|
|
break;
|
|
|
|
case "maxs":
|
|
|
|
maxs = stov(strValue);
|
2021-10-22 23:00:15 +00:00
|
|
|
setsize(this, mins, maxs);
|
2021-10-22 19:20:22 +00:00
|
|
|
break;
|
2021-10-22 18:51:51 +00:00
|
|
|
case "model":
|
|
|
|
model = strValue;
|
2021-10-22 23:00:15 +00:00
|
|
|
setmodel(this, model);
|
2021-10-22 18:51:51 +00:00
|
|
|
break;
|
|
|
|
case "angles":
|
|
|
|
angles = stov(strValue);
|
|
|
|
break;
|
|
|
|
case "solid":
|
|
|
|
solid = stof(strValue);
|
2021-11-03 20:54:43 +00:00
|
|
|
setorigin(this, origin);
|
2021-10-22 18:51:51 +00:00
|
|
|
break;
|
2021-10-22 19:20:22 +00:00
|
|
|
case "movetype":
|
|
|
|
movetype = stof(strValue);
|
|
|
|
break;
|
2021-10-22 18:51:51 +00:00
|
|
|
case "health":
|
|
|
|
health = stof(strValue);
|
|
|
|
break;
|
|
|
|
case "parentname":
|
2021-10-22 23:00:15 +00:00
|
|
|
if (strValue != "")
|
|
|
|
SetParent(strValue);
|
2021-10-22 18:51:51 +00:00
|
|
|
break;
|
2021-10-22 23:00:15 +00:00
|
|
|
case "pvsflags":
|
|
|
|
pvsflags = stof(strValue);
|
2021-10-22 18:51:51 +00:00
|
|
|
break;
|
2022-04-06 23:21:07 +00:00
|
|
|
case "_mapspawned":
|
|
|
|
_mapspawned = stof(strValue);
|
|
|
|
break;
|
2021-10-22 18:51:51 +00:00
|
|
|
default:
|
|
|
|
super::Restore(strKey, strValue);
|
|
|
|
}
|
|
|
|
}
|
2022-03-31 07:30:15 +00:00
|
|
|
void
|
|
|
|
NSEntity::RestoreComplete(void)
|
|
|
|
{
|
|
|
|
/* this is where we can handle anything post-loading */
|
|
|
|
}
|
2021-10-22 18:51:51 +00:00
|
|
|
|
2021-10-19 23:18:36 +00:00
|
|
|
void
|
|
|
|
NSEntity::Input(entity eAct, string strInput, string strData)
|
|
|
|
{
|
|
|
|
switch (strInput) {
|
|
|
|
case "Kill":
|
|
|
|
think = Util_Destroy;
|
|
|
|
nextthink = time;
|
|
|
|
break;
|
|
|
|
case "KillHierarchy":
|
|
|
|
/* this works because ents are basically just entnums */
|
|
|
|
for (entity e = world; (e=findfloat(e, ::owner, this));) {
|
|
|
|
e.think = Util_Destroy;
|
|
|
|
e.nextthink = time;
|
|
|
|
}
|
|
|
|
think = Util_Destroy;
|
|
|
|
nextthink = time;
|
|
|
|
break;
|
|
|
|
case "SetParent":
|
|
|
|
SetParent(strData);
|
|
|
|
break;
|
2022-03-25 00:59:30 +00:00
|
|
|
case "SetParentAttachment":
|
|
|
|
SetParentAttachment(strData);
|
|
|
|
break;
|
2021-10-19 23:18:36 +00:00
|
|
|
case "ClearParent":
|
|
|
|
ClearParent();
|
|
|
|
break;
|
2022-03-27 01:04:06 +00:00
|
|
|
case "Use":
|
|
|
|
eActivator = eAct;
|
|
|
|
|
|
|
|
if (PlayerUse)
|
|
|
|
PlayerUse();
|
|
|
|
break;
|
2021-10-19 23:18:36 +00:00
|
|
|
default:
|
|
|
|
NSTrigger::Input(eAct, strInput, strData);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
|
|
============
|
|
|
|
NSEntity::SpawnKey
|
|
|
|
|
|
|
|
note that the engine still likes to try and map key/value
|
|
|
|
pairs on its own, but we can at least undo some of that in
|
|
|
|
here if needed
|
|
|
|
============
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
NSEntity::SpawnKey(string strKey, string strValue)
|
|
|
|
{
|
|
|
|
/* 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) {
|
2022-03-18 04:05:47 +00:00
|
|
|
case "spawnflags":
|
|
|
|
spawnflags = stof(strValue);
|
|
|
|
break;
|
2021-10-19 23:18:36 +00:00
|
|
|
case "origin":
|
|
|
|
origin = stov(strValue);
|
|
|
|
break;
|
|
|
|
case "model":
|
|
|
|
model = strValue;
|
|
|
|
break;
|
|
|
|
case "angles":
|
|
|
|
angles = stov(strValue);
|
|
|
|
break;
|
|
|
|
case "angle":
|
|
|
|
angles[1] = stof(strValue);
|
|
|
|
break;
|
|
|
|
case "solid":
|
|
|
|
solid = stof(strValue);
|
|
|
|
break;
|
|
|
|
#ifdef SERVER
|
|
|
|
case "health":
|
|
|
|
health = stof(strValue);
|
|
|
|
break;
|
|
|
|
case "parentname":
|
|
|
|
SetParent(strValue);
|
|
|
|
break;
|
|
|
|
case "ignorepvs":
|
|
|
|
pvsflags = PVSF_IGNOREPVS;
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
default:
|
|
|
|
NSTrigger::SpawnKey(strKey, strValue);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-10 21:17:36 +00:00
|
|
|
|
2022-04-13 06:48:31 +00:00
|
|
|
/*
|
|
|
|
============
|
|
|
|
OnRemoveEntity
|
|
|
|
|
|
|
|
Empty method, meant for sub-classes to clean up their contents
|
|
|
|
============
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
NSEntity::OnRemoveEntity(void)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2022-01-10 21:17:36 +00:00
|
|
|
/*
|
|
|
|
============
|
|
|
|
NSEntity::Destroy
|
|
|
|
|
|
|
|
Call if the entity is to be removed the next possible frame.
|
|
|
|
If you want an entity to be purged immediately, you'll have to jump
|
|
|
|
through your own hoops. This however will be sufficient 99,99% of the time.
|
|
|
|
============
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
NSEntity::Destroy(void)
|
|
|
|
{
|
2022-04-13 06:48:31 +00:00
|
|
|
OnRemoveEntity();
|
|
|
|
|
2022-01-10 21:17:36 +00:00
|
|
|
think = Util_Destroy;
|
|
|
|
|
|
|
|
if (!time)
|
|
|
|
nextthink = time + 0.01;
|
|
|
|
else
|
|
|
|
nextthink = time;
|
|
|
|
};
|
|
|
|
|
2021-10-19 23:18:36 +00:00
|
|
|
/*
|
|
|
|
============
|
|
|
|
NSEntity::NSEntity
|
|
|
|
|
|
|
|
client doesn't have to do a whole lot here
|
|
|
|
============
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
NSEntity::NSEntity(void)
|
|
|
|
{
|
|
|
|
#ifdef SERVER
|
|
|
|
/* don't call this function more than once per entity */
|
|
|
|
if (identity == 1)
|
|
|
|
return;
|
|
|
|
|
|
|
|
identity = 1; /* .identity is a global ent field we abuse to let find() calls
|
|
|
|
reliably know that those are NSEntity class-based */
|
|
|
|
|
|
|
|
super::NSTrigger();
|
|
|
|
|
|
|
|
m_oldAngle = angles;
|
|
|
|
m_oldOrigin = origin;
|
|
|
|
m_oldSolid = solid;
|
|
|
|
m_oldModel = Util_FixModel(model);
|
2022-04-03 21:04:34 +00:00
|
|
|
blocked = BlockedHandler;
|
|
|
|
touch = TouchHandler;
|
2021-10-19 23:18:36 +00:00
|
|
|
|
|
|
|
/* Input/Output system */
|
|
|
|
m_strOnTrigger = CreateOutput(m_strOnTrigger);
|
|
|
|
|
|
|
|
m_oldstrTarget = target;
|
|
|
|
|
|
|
|
if (m_oldModel != "") {
|
|
|
|
precache_model(GetSpawnModel());
|
|
|
|
}
|
2022-02-22 20:01:31 +00:00
|
|
|
#else
|
|
|
|
isCSQC = 1;
|
2021-10-19 23:18:36 +00:00
|
|
|
#endif
|
|
|
|
}
|