nuclide/src/shared/NSEntity.qc

1603 lines
31 KiB
C++
Raw Normal View History

/*
* 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.
*/
2024-04-22 22:11:12 +00:00
static bool
droptofloorwrapper(entity foo)
{
bool result;
entity old_self = self;
self = foo;
result = droptofloor();
self = old_self;
return result;
}
2024-04-22 22:11:12 +00:00
void
ncEntity::ncEntity(void)
2024-04-22 22:11:12 +00:00
{
identity = 1;
m_flSpawnTime = time;
2024-04-22 22:11:12 +00:00
m_vecEditorColor = [1,1,1];
m_holdingPlayer = __NULL__;
}
void
ncEntity::Spawn(void)
{
Spawned();
if (wasfreed(this)) {
return;
}
/* only precache at start time... */
if (time == 0.0f) {
Precache();
}
Respawn();
}
2024-04-22 22:11:12 +00:00
void
ncEntity::Precache(void)
2024-04-22 22:11:12 +00:00
{
if (STRING_SET(model)) {
2024-06-22 07:24:13 +00:00
precache_model(model);
}
#ifdef SERVER
if (STRING_SET(m_strOnTrigger)) {
2024-04-22 22:11:12 +00:00
m_strOnTrigger = CreateOutput(m_strOnTrigger);
}
#endif
}
2024-06-22 07:24:13 +00:00
void
ncEntity::Spawned(void)
{
super::Spawned();
#ifdef SERVER
2024-06-22 07:24:13 +00:00
/* used to network our shared ID */
entityDefID = EntityDef_NetIDFromName(classname);
#endif
}
bool
ncEntity::HasModel(void)
{
return (modelindex == 0) ? (false) : (true);
}
2024-04-22 22:11:12 +00:00
float
ncEntity::EntIndex(void)
2024-04-22 22:11:12 +00:00
{
return (num_for_edict(this));
}
2024-04-22 22:11:12 +00:00
bool
ncEntity::DropToFloor(void)
2024-04-22 22:11:12 +00:00
{
return droptofloorwrapper(this);
}
2024-04-22 22:11:12 +00:00
vector
ncEntity::GetForward(void)
2024-04-22 22:11:12 +00:00
{
return anglesToForward(angles);
}
2024-04-22 22:11:12 +00:00
vector
ncEntity::GetRight(void)
2024-04-22 22:11:12 +00:00
{
return anglesToRight(angles);
}
2024-04-22 22:11:12 +00:00
vector
ncEntity::GetUp(void)
2024-04-22 22:11:12 +00:00
{
return anglesToUp(angles);
}
2024-04-22 22:11:12 +00:00
vector
ncEntity::WorldSpaceCenter(void)
2024-04-22 22:11:12 +00:00
{
return (absmin + (0.5 * (absmax - absmin)));
}
2024-04-22 22:11:12 +00:00
float
ncEntity::WaterLevel(void)
2024-04-22 22:11:12 +00:00
{
return (waterlevel);
}
2024-04-22 22:11:12 +00:00
bool
ncEntity::VisibleVec(vector org)
2024-04-22 22:11:12 +00:00
{
vector flDelta;
float flFoV;
2024-04-22 22:11:12 +00:00
flDelta = vectorNormalize(org - origin);
flFoV = flDelta * GetForward();
2024-04-22 22:11:12 +00:00
if (flFoV > 0.3f) {
traceline(origin, org, TRUE, this);
2024-09-17 19:46:31 +00:00
2024-04-22 22:11:12 +00:00
if (trace_fraction == 1.0f) {
return (true);
}
}
2024-09-17 19:46:31 +00:00
2024-04-22 22:11:12 +00:00
return (false);
}
2024-04-22 22:11:12 +00:00
bool
ncEntity::Visible(entity ent)
2024-04-22 22:11:12 +00:00
{
/* is it in our field of view? */
2024-04-22 22:11:12 +00:00
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));*/
2024-04-22 22:11:12 +00:00
return (true);
}
}
/*print(sprintf("%s can not see %s\n", classname, ent.classname));*/
2024-04-22 22:11:12 +00:00
return (false);
2023-05-31 17:08:00 +00:00
}
2024-04-22 22:11:12 +00:00
float
ncEntity::DistanceFromYaw(vector targetPos)
2024-04-22 22:11:12 +00:00
{
return vectorNormalize(targetPos - origin) * GetForward();
}
2024-04-22 22:11:12 +00:00
bool
ncEntity::HasSpawnFlags(float sf)
2024-04-22 22:11:12 +00:00
{
return (spawnflags & sf) ? (true) : (false);
}
2024-04-22 22:11:12 +00:00
bool
ncEntity::IsOnGround(void)
2024-04-22 22:11:12 +00:00
{
return (flags & FL_ONGROUND) ? (true) : (false);
}
2024-04-22 22:11:12 +00:00
bool
ncEntity::IsSolid(void)
2024-04-22 22:11:12 +00:00
{
return (solid != SOLID_NOT) ? (true) : (false);
}
2024-04-22 22:11:12 +00:00
entity
ncEntity::GetGroundEntity(void)
2024-04-22 22:11:12 +00:00
{
return (groundentity);
}
2024-04-22 22:11:12 +00:00
bool
ncEntity::CreatedByMap(void)
2024-04-22 22:11:12 +00:00
{
return (_mapspawned);
}
bool
ncEntity::HeldByPlayer(void)
{
return (m_holdingPlayer) ? (true) : (false);
}
#ifdef CLIENT
2024-04-22 22:11:12 +00:00
void
ncEntity::RendererRestarted(void)
2024-04-22 22:11:12 +00:00
{
}
2024-06-22 07:24:13 +00:00
float
ncEntity::predraw(void)
2024-06-22 07:24:13 +00:00
{
if (GetModelindex() == 0 || IsHidden()) {
return (PREDRAW_NEXT);
}
addentity(this);
return (PREDRAW_NEXT);
}
2024-04-22 22:11:12 +00:00
void
ncEntity::ReceiveEntity(float flNew, float flChanged)
2024-04-22 22:11:12 +00:00
{
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_INT(effects, BASEFL_CHANGED_EFFECTS)
2024-04-22 22:11:12 +00:00
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;
2024-09-17 19:46:31 +00:00
if (scale == 0.0f) {
scale = 1.0f;
2024-09-17 19:46:31 +00:00
}
2024-09-17 19:46:31 +00:00
if (flChanged & BASEFL_CHANGED_SIZE) {
2024-04-22 22:11:12 +00:00
setsize(this, mins, maxs);
2024-09-17 19:46:31 +00:00
}
}
void
ncEntity::_ReceiveComplete(float flNew, float flChanged)
{
}
2024-06-22 07:24:13 +00:00
void
ncEntity::ReceiveEvent(float eventType)
2024-06-22 07:24:13 +00:00
{
switch (eventType) {
default:
EntError("Unknown event %d", eventType);
}
}
2024-04-22 22:11:12 +00:00
void
ncEntity::postdraw(void)
2024-04-22 22:11:12 +00:00
{
}
#else
void
ncEntity::DebugDraw(void)
{
2024-04-22 22:11:12 +00:00
DebugBox(GetOrigin(), GetMins(), GetMaxs(), m_vecEditorColor, 0.75f);
}
2024-04-22 22:11:12 +00:00
float
ncEntity::SendEntity(entity ePEnt, float flChanged)
2024-04-22 22:11:12 +00:00
{
2024-09-17 19:46:31 +00:00
if (!modelindex) {
2024-04-22 22:11:12 +00:00
return (0);
2024-09-17 19:46:31 +00:00
}
2024-09-17 19:46:31 +00:00
if (clienttype(ePEnt) != CLIENTTYPE_REAL) {
2024-04-22 22:11:12 +00:00
return (0);
2024-09-17 19:46:31 +00:00
}
2024-04-22 22:11:12 +00:00
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 */
2024-04-22 22:11:12 +00:00
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_INT(effects, BASEFL_CHANGED_EFFECTS)
2024-04-22 22:11:12 +00:00
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
ncEntity::EvaluateEntity(void)
2024-04-22 22:11:12 +00:00
{
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 */
2024-04-22 22:11:12 +00:00
void
ncEntity::ParentUpdate(void)
2024-04-22 22:11:12 +00:00
{
if (tag_entity) {
makevectors(tag_entity.angles);
origin = tag_entity.origin + v_forward * m_parentPosOffs[0];
origin += v_right * m_parentPosOffs[1];
origin += v_up * m_parentPosOffs[2];
angles = v_forward * m_parentPosOffs[0];
angles += v_right * m_parentPosOffs[1];
angles += v_up * m_parentPosOffs[2];
angles = vectoangles(angles);
}
EvaluateEntity();
if (!(vv_flags & VFL_NOFRAMEADVANCE)) {
frame1time += frametime;
}
/* handle end-touch */
2024-09-17 19:46:31 +00:00
if (m_beingTouched == true) {
2024-04-22 22:11:12 +00:00
if (m_flTouchTime < GetTime()) {
EndTouch(m_eTouchLast);
m_beingTouched = false;
m_eTouchLast = __NULL__;
}
2024-09-17 19:46:31 +00:00
}
}
bool
ncEntity::SharesPVSWithPlayer(void)
{
entity entLoop = world;
for (entLoop = world; ((entLoop = find(entLoop, ::classname, "player")));) {
ncActor testPlayer = (ncActor)entLoop;
/* players are first N entity slots after world, so exit when they're done */
if (entLoop.classname != "player") {
return (false);
}
if (checkpvs(testPlayer.GetEyePos(), this) == true) {
return (true);
}
}
return (false);
}
2024-04-22 22:11:12 +00:00
entity
ncEntity::GetParent(void)
2024-04-22 22:11:12 +00:00
{
return tag_entity;
}
2024-04-22 22:11:12 +00:00
void
ncEntity::SetParent(string name)
2024-04-22 22:11:12 +00:00
{
vector parentOffset, angleOffset;
2024-09-17 19:46:31 +00:00
tag_entity = find(world, ::targetname, name);
parentOffset = origin - tag_entity.origin;
angleOffset = anglesToForward(angles) - anglesToForward(tag_entity.angles);
makevectors(tag_entity.angles);
m_parentPosOffs[0] = dotproduct(parentOffset, v_forward);
m_parentPosOffs[1] = dotproduct(parentOffset, v_right);
m_parentPosOffs[2] = dotproduct(parentOffset, v_up);
m_parentAngOffs[0] = dotproduct(angleOffset, v_forward);
m_parentAngOffs[1] = dotproduct(angleOffset, v_right);
m_parentAngOffs[2] = dotproduct(angleOffset, v_up);
}
2024-04-22 22:11:12 +00:00
void
ncEntity::SetParentAttachment(string name)
2024-04-22 22:11:12 +00:00
{
if (name != "origin") {
tag_index = gettagindex(tag_entity, name);
} else {
tag_index = 0;
}
}
2024-04-22 22:11:12 +00:00
void
ncEntity::ClearParent(void)
2024-04-22 22:11:12 +00:00
{
tag_entity = world;
tag_index = 0;
}
2024-04-22 22:11:12 +00:00
void
ncEntity::RestoreAngles(void)
2024-04-22 22:11:12 +00:00
{
2024-06-22 07:24:13 +00:00
vector spawnAngles = g_vec_null;
string spawnAngleString = GetSpawnString("angles");
if (spawnAngleString == "") {
spawnAngles[1] = GetSpawnFloat("angle");
} else {
spawnAngles = stov(spawnAngleString);
}
SetAngles(spawnAngles);
}
2024-04-22 22:11:12 +00:00
void
ncEntity::ClearAngles(void)
2024-04-22 22:11:12 +00:00
{
2024-06-22 07:24:13 +00:00
SetAngles(g_vec_null);
}
2024-04-22 22:11:12 +00:00
void
ncEntity::ForceNetworkUpdate(void)
2024-04-22 22:11:12 +00:00
{
SendFlags = -1;
}
2024-04-22 22:11:12 +00:00
void
ncEntity::UseBy(entity ourActivator)
2024-04-22 22:11:12 +00:00
{
if (PlayerUse) {
eActivator = (ncEntity)ourActivator;
2024-04-22 22:11:12 +00:00
PlayerUse();
}
}
#endif
2024-04-22 22:11:12 +00:00
void
ncEntity::SetEffects(__int32 newEffects)
2024-04-22 22:11:12 +00:00
{
effects = newEffects;
}
2024-04-22 22:11:12 +00:00
void
ncEntity::SetFrame(float newFrame)
2024-04-22 22:11:12 +00:00
{
2024-09-17 19:46:31 +00:00
if (newFrame == frame) {
return;
2024-09-17 19:46:31 +00:00
}
frame = newFrame;
frame1time = 0.0f;
#ifdef SERVER
/* check if an event callback exists */
{
2024-04-22 22:11:12 +00:00
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) {
2024-09-17 19:46:31 +00:00
if (testData != "") {
Input(this, testInput, testData);
2024-09-17 19:46:31 +00:00
} else {
Input(this, testInput, ""); /* no parms passed. */
2024-09-17 19:46:31 +00:00
}
tokenize(m_strModelEventCB); /* ensure argv() is 'rewound'... */
}
}
}
#endif
}
2024-04-22 22:11:12 +00:00
void
ncEntity::SetSkin(float newSkin)
2024-04-22 22:11:12 +00:00
{
skin = newSkin;
}
2024-04-22 22:11:12 +00:00
void
ncEntity::SetOwner(entity newOwner)
2024-04-22 22:11:12 +00:00
{
owner = newOwner;
}
2024-04-22 22:11:12 +00:00
void
ncEntity::SetVelocity(vector vecNew)
2024-04-22 22:11:12 +00:00
{
velocity = vecNew;
}
2024-04-22 22:11:12 +00:00
void
ncEntity::SetTouch(void ()newTouch)
2024-04-22 22:11:12 +00:00
{
touch = newTouch;
}
2024-04-22 22:11:12 +00:00
void
ncEntity::SetSendFlags(float flSendFlags)
2024-04-22 22:11:12 +00:00
{
#ifdef SERVER
SendFlags |= flSendFlags;
#endif
}
2024-04-22 22:11:12 +00:00
void
ncEntity::SetMovetype(float newMovetype)
2024-04-22 22:11:12 +00:00
{
movetype = newMovetype;
}
2024-04-22 22:11:12 +00:00
void
ncEntity::SetGravity(float newGrav)
2024-04-22 22:11:12 +00:00
{
gravity = newGrav;
}
2024-04-22 22:11:12 +00:00
void
ncEntity::SetSolid(float newSolid)
2024-04-22 22:11:12 +00:00
{
solid = newSolid;
}
2024-04-22 22:11:12 +00:00
void
ncEntity::SetScale(float newScale)
2024-04-22 22:11:12 +00:00
{
2024-09-17 19:46:31 +00:00
if (newScale == scale) {
return;
2024-09-17 19:46:31 +00:00
}
scale = newScale;
2024-04-22 22:11:12 +00:00
setsize(this, m_vecMins * scale, m_vecMaxs * scale);
}
2024-06-22 07:24:13 +00:00
vector
ncEntity::GetViewAngle(void)
2024-06-22 07:24:13 +00:00
{
if (isSentient(this)) {
return (v_angle);
} else {
return (angles);
}
}
void
ncEntity::SetEyePos(vector value)
2024-06-22 07:24:13 +00:00
{
view_ofs = value;
}
vector
ncEntity::GetEyePos(void)
2024-06-22 07:24:13 +00:00
{
if (HasVFlags(VFL_FAKESPEC)) {
return (origin);
}
return (origin + view_ofs);
}
2024-04-22 22:11:12 +00:00
void
ncEntity::UpdateBounds(void)
2024-04-22 22:11:12 +00:00
{
vector newMins, newMaxs;
float flScale = 1.0f;
2022-02-01 21:37:21 +00:00
newMins = m_vecMins;
newMaxs = m_vecMaxs;
/* avoid useless computation */
2024-09-17 19:46:31 +00:00
if (angles != [0, 0, 0]) {
/* adjust bbox according to rotation */
vector vecCorner[8];
newMins = newMaxs =[0, 0, 0];
2024-04-22 22:11:12 +00:00
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;
2024-04-22 22:11:12 +00:00
vecCorner[i] = rotateAroundPoint(vecCorner[i], origin, angles[1]);
vecCorner[i] -= origin;
2024-04-22 22:11:12 +00:00
if (!(vecCorner[i][0] <= newMaxs[0]))
newMaxs[0] = vecCorner[i][0];
2024-04-22 22:11:12 +00:00
if (!(vecCorner[i][1] <= newMaxs[1]))
newMaxs[1] = vecCorner[i][1];
2024-04-22 22:11:12 +00:00
if (!(vecCorner[i][2] <= newMaxs[2]))
newMaxs[2] = vecCorner[i][2];
2024-04-22 22:11:12 +00:00
if (!(vecCorner[i][0] >= newMins[0]))
newMins[0] = vecCorner[i][0];
2024-04-22 22:11:12 +00:00
if (!(vecCorner[i][1] >= newMins[1]))
newMins[1] = vecCorner[i][1];
2024-04-22 22:11:12 +00:00
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 */
2024-09-17 19:46:31 +00:00
if (scale != 0.0) {
flScale = scale;
2024-09-17 19:46:31 +00:00
}
2024-04-22 22:11:12 +00:00
setsize(this, newMins * flScale, newMaxs * flScale);
}
2024-04-22 22:11:12 +00:00
void
ncEntity::SetAngles(vector newAngles)
2024-04-22 22:11:12 +00:00
{
angles = newAngles;
}
2024-04-22 22:11:12 +00:00
void
ncEntity::SetAngularVelocity(vector newAvel)
2024-04-22 22:11:12 +00:00
{
avelocity = newAvel;
}
2024-04-22 22:11:12 +00:00
void
ncEntity::SetSize(vector newMins, vector newMaxs)
2024-04-22 22:11:12 +00:00
{
float flScale = 1.0f;
m_vecMins = newMins;
m_vecMaxs = newMaxs;
/* 0.0 is never valid, if you want it to disappear do something else */
2024-09-17 19:46:31 +00:00
if (scale != 0.0f) {
flScale = scale;
2024-09-17 19:46:31 +00:00
}
2024-04-22 22:11:12 +00:00
setsize(this, newMins * flScale, newMaxs * flScale);
}
2024-04-22 22:11:12 +00:00
void
ncEntity::SetOrigin(vector newOrigin)
2024-09-17 19:46:31 +00:00
{
2024-04-22 22:11:12 +00:00
setorigin(this, newOrigin);
}
void
ncEntity::SetOriginUnstick(vector newOrigin)
2024-09-17 19:46:31 +00:00
{
setorigin_safe(this, newOrigin);
}
bool
ncEntity::IsBrush(void)
{
return (m_bIsBrush);
}
2024-04-22 22:11:12 +00:00
void
ncEntity::SetModel(string newModel)
2024-09-17 19:46:31 +00:00
{
m_bIsBrush = substring(newModel, 0, 1) == "*" ? true : false;
model = Util_FixModel(newModel);
setmodel(this, model);
#ifdef SERVER
m_vecModelMins = mins;
m_vecModelMaxs = maxs;
#endif
/* mins/maxs have been updated by setmodel */
2024-04-22 22:11:12 +00:00
SetSize(mins, maxs);
}
2024-09-17 19:46:31 +00:00
2024-04-22 22:11:12 +00:00
void
ncEntity::SetModelindex(float newModelIndex)
2024-09-17 19:46:31 +00:00
{
if (newModelIndex == modelindex) {
return;
2024-09-17 19:46:31 +00:00
}
modelindex = newModelIndex;
2024-04-22 22:11:12 +00:00
SetSize(mins, maxs);
}
void
ncEntity::AddAngularVelocity(vector addVel)
{
avelocity += addVel;
}
void
ncEntity::AddVelocity(vector addVel)
{
velocity += addVel;
}
2024-04-22 22:11:12 +00:00
void
ncEntity::AddEffects(__int32 fl) {
effects |= fl;
}
2024-04-22 22:11:12 +00:00
void
ncEntity::RemoveEffects(__int32 fl) {
effects &= ~fl;
}
2024-04-22 22:11:12 +00:00
void
ncEntity::AddFlags(float fl) {
flags |= fl;
}
2024-04-22 22:11:12 +00:00
void
ncEntity::RemoveFlags(float fl) {
flags &= ~fl;
}
2024-04-22 22:11:12 +00:00
void
ncEntity::AddVFlags(float fl) {
2024-04-22 22:11:12 +00:00
vv_flags |= fl;
}
void
ncEntity::RemoveVFlags(float fl) {
2024-04-22 22:11:12 +00:00
vv_flags &= ~fl;
}
void
ncEntity::TurnTo(float targetAngle) {
angles[1] = targetAngle;
}
2024-04-22 22:11:12 +00:00
void
ncEntity::TurnToPos(vector targetPos) {
2024-04-22 22:11:12 +00:00
angles = vectorToAngles(targetPos - WorldSpaceCenter());
}
__int32
ncEntity::GetEffects(void) {
2024-04-22 22:11:12 +00:00
return (effects);
}
2024-04-22 22:11:12 +00:00
float
ncEntity::GetFrame(void) {
2024-04-22 22:11:12 +00:00
return (frame);
}
2024-04-22 22:11:12 +00:00
float
ncEntity::GetSkin(void) {
2024-04-22 22:11:12 +00:00
return (skin);
}
2024-04-22 22:11:12 +00:00
float
ncEntity::GetScale(void) {
2024-04-22 22:11:12 +00:00
return (scale);
}
2024-04-22 22:11:12 +00:00
entity
ncEntity::GetOwner(void) {
2024-04-22 22:11:12 +00:00
return (owner);
}
2024-04-22 22:11:12 +00:00
vector
ncEntity::GetVelocity(void) {
2024-04-22 22:11:12 +00:00
return (velocity);
}
2024-04-22 22:11:12 +00:00
float
ncEntity::GetSolid(void) {
2024-04-22 22:11:12 +00:00
return (solid);
}
2024-04-22 22:11:12 +00:00
string
ncEntity::GetModel(void)
2024-04-22 22:11:12 +00:00
{
return (model);
}
2024-04-22 22:11:12 +00:00
float
ncEntity::GetModelindex(void)
2024-04-22 22:11:12 +00:00
{
return (modelindex);
}
float
ncEntity::GetMovetype(void)
2024-04-22 22:11:12 +00:00
{
return (movetype);
}
2024-04-22 22:11:12 +00:00
float
ncEntity::GetGravity(void)
2024-04-22 22:11:12 +00:00
{
return (gravity);
}
2024-04-22 22:11:12 +00:00
vector
ncEntity::GetAngles(void)
2024-04-22 22:11:12 +00:00
{
return (angles);
}
2024-04-22 22:11:12 +00:00
vector
ncEntity::GetAngularVelocity(void)
2024-04-22 22:11:12 +00:00
{
return (avelocity);
}
2024-04-22 22:11:12 +00:00
vector
ncEntity::GetOrigin(void)
2024-04-22 22:11:12 +00:00
{
return (origin);
}
2024-04-22 22:11:12 +00:00
vector
ncEntity::GetSize(void)
{
return (size);
}
vector
ncEntity::GetMins(void)
2024-04-22 22:11:12 +00:00
{
return (mins);
}
2024-04-22 22:11:12 +00:00
vector
ncEntity::GetMaxs(void)
2024-04-22 22:11:12 +00:00
{
return (maxs);
}
2024-04-22 22:11:12 +00:00
vector
ncEntity::GetRealMins(void)
2024-04-22 22:11:12 +00:00
{
return (m_vecMins);
}
2024-04-22 22:11:12 +00:00
vector
ncEntity::GetRealMaxs(void)
2024-04-22 22:11:12 +00:00
{
return (m_vecMaxs);
}
2024-04-22 22:11:12 +00:00
vector
ncEntity::GetAbsoluteMins(void)
2024-04-22 22:11:12 +00:00
{
return (absmin);
}
2024-04-22 22:11:12 +00:00
vector
ncEntity::GetAbsoluteMaxs(void)
2024-04-22 22:11:12 +00:00
{
return (absmax);
}
2024-04-22 22:11:12 +00:00
float
ncEntity::GetFlags(void)
2024-04-22 22:11:12 +00:00
{
return (flags);
}
2024-04-22 22:11:12 +00:00
float
ncEntity::GetVFlags(void)
2024-04-22 22:11:12 +00:00
{
return (vv_flags);
}
2024-04-22 22:11:12 +00:00
bool
ncEntity::HasFlags(float bits)
2024-04-22 22:11:12 +00:00
{
return (flags & bits) ? (true) : (false);
}
2024-04-22 22:11:12 +00:00
bool
ncEntity::HasVFlags(float bits)
2024-04-22 22:11:12 +00:00
{
return (vv_flags & bits) ? (true) : (false);
}
void
ncEntity::ClearVelocity(void)
2024-04-22 22:11:12 +00:00
{
velocity = avelocity = [0.0f, 0.0f, 0.0f];
}
#ifdef SERVER
vector
ncEntity::GetModelMins(void)
2024-04-22 22:11:12 +00:00
{
return (m_vecModelMins);
}
vector
ncEntity::GetModelMaxs(void)
2024-04-22 22:11:12 +00:00
{
return (m_vecModelMaxs);
}
2024-04-22 22:11:12 +00:00
void
ncEntity::Respawn(void)
2024-04-22 22:11:12 +00:00
{
super::Respawn();
2024-06-22 07:24:13 +00:00
2024-09-17 19:46:31 +00:00
if (CreatedByMap()) {
SetOrigin(GetSpawnVector("origin"));
}
2024-06-22 07:24:13 +00:00
SetAngles(GetSpawnVector("angles"));
SetModel(GetSpawnString("model"));
if (STRING_SET(m_parent)) {
SetParent(m_parent);
}
2024-04-22 22:11:12 +00:00
}
void
ncEntity::Save(float handle)
2024-04-22 22:11:12 +00:00
{
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);
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
ncEntity::Restore(string strKey, string strValue)
2024-04-22 22:11:12 +00:00
{
switch (strKey) {
case "tag_entity":
tag_entity = ReadEntity(strValue);
break;
case "tag_index":
tag_index = ReadFloat(strValue);
break;
case "pvsflags":
2024-04-22 22:11:12 +00:00
pvsflags = ReadFloat(strValue);
break;
case "_mapspawned":
2024-04-22 22:11:12 +00:00
_mapspawned = ReadBool(strValue);
break;
case "scale":
2024-04-22 22:11:12 +00:00
scale = ReadFloat(strValue);
break;
case "vv_flags":
vv_flags = ReadFloat(strValue);
break;
case "friction":
2024-04-22 22:11:12 +00:00
friction = ReadFloat(strValue);
break;
case "m_vecMins":
2024-04-22 22:11:12 +00:00
m_vecMins = ReadVector(strValue);
break;
case "m_vecMaxs":
2024-04-22 22:11:12 +00:00
m_vecMaxs = ReadVector(strValue);
break;
case "m_flTouchTime":
2024-04-22 22:11:12 +00:00
m_flTouchTime = ReadFloat(strValue);
break;
case "m_beingTouched":
2024-04-22 22:11:12 +00:00
m_beingTouched = ReadBool(strValue);
break;
case "m_eTouchLast":
2024-04-22 22:11:12 +00:00
m_eTouchLast = ReadEntity(strValue);
break;
2024-04-22 22:11:12 +00:00
case "m_vecEditorColor":
m_vecEditorColor = ReadVector(strValue);
break;
default:
2024-04-22 22:11:12 +00:00
super::Restore(strKey, strValue);
break;
}
}
void
ncEntity::Event_SpawnDefRelative(string classDef, float xOfs, float yOfs, float zOfs)
{
vector posOffset;
posOffset = anglesToForward(GetAngles()) * xOfs;
posOffset += anglesToRight(GetAngles()) * yOfs;
posOffset += anglesToUp(GetAngles()) * zOfs;
ncEntity rocket = EntityDef_NewClassname(classDef);
rocket.SetOrigin(GetOrigin() + posOffset);
rocket.SetAngles(GetAngles());
rocket.owner = this;
rocket.Spawn();
EntLog("Spawned decl %S at relative offset %v (%v)", classDef, posOffset, rocket.origin);
}
2024-04-22 22:11:12 +00:00
void
ncEntity::Input(entity eAct, string strInput, string strData)
2024-04-22 22:11:12 +00:00
{
switch (strInput) {
case "Kill":
Destroy();
break;
case "KillHierarchy":
/* this works because ents are basically just entnums */
2024-04-22 22:11:12 +00:00
for (entity e = world; (e = findfloat(e, ::owner, this));) {
ncEntity ent = (ncEntity) e;
ent.Destroy();
}
Destroy();
break;
case "SetParent":
2024-04-22 22:11:12 +00:00
SetParent(strData);
break;
case "SetParentAttachment":
2024-04-22 22:11:12 +00:00
SetParentAttachment(strData);
break;
case "ClearParent":
ClearParent();
break;
2022-03-27 01:04:06 +00:00
case "Use":
eActivator = (ncEntity)eAct;
2022-03-27 01:04:06 +00:00
2024-04-22 22:11:12 +00:00
if (PlayerUse)
2022-03-27 01:04:06 +00:00
PlayerUse();
break;
case "ShootGib":
tokenize_console(strData);
string breakModel = argv(0);
float breakSpeed = stof(argv(1));
int breakCount = stoi(argv(2));
BreakModel_Spawn(origin, origin, v_angle, breakSpeed, breakCount, breakModel);
break;
case "SpawnDef":
break;
case "SpawnDefOffset":
#ifdef SERVER
tokenize_console(strData);
Event_SpawnDefRelative(argv(0), stof(argv(1)), stof(argv(2)), stof(argv(3)));
#endif
break;
case "KillChildClass":
for (entity e = world; (e = findfloat(e, ::owner, this));) {
if (strData == e.classname) {
ncEntity ent = (ncEntity) e;
ent.Destroy();
}
}
break;
case "SpawnProjectileOffset":
vector launchOffset;
tokenize_console(strData);
string defName = argv(0);
launchOffset[0]= stof(argv(1));
launchOffset[1]= stof(argv(2));
launchOffset[2]= stof(argv(3));
if (EntityDef_HasSpawnClass(defName)) {
ncProjectile_SpawnDefAtPosition(defName, (ncActor)this, GetOrigin() + launchOffset, GetViewAngle());
}
break;
case "SpawnProjectileDef":
if (EntityDef_HasSpawnClass(strData)) {
ncProjectile_SpawnDefAttachment(strData, (ncActor)this, 0);
}
break;
case "StartSoundDef":
StartSoundDef(strData, CHAN_VOICE, true);
break;
case "AddVelocity":
vector velAdd = stov(strData);
2024-04-22 22:11:12 +00:00
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;
2024-04-22 22:11:12 +00:00
case "SetOrigin":
SetOrigin(stov(strData));
break;
case "SetEditorColor":
m_vecEditorColor = ReadVector(strData);
break;
case "Respawn":
Respawn();
break;
default:
ncTrigger::Input(eAct, strInput, strData);
}
}
#endif
2024-04-22 22:11:12 +00:00
void
ncEntity::SpawnKey(string strKey, string strValue)
2024-04-22 22:11:12 +00:00
{
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. */
2024-04-22 22:11:12 +00:00
switch (strKey) {
case "spawnflags":
2024-04-22 22:11:12 +00:00
spawnflags = ReadFloat(strValue);
break;
case "origin":
2024-04-22 22:11:12 +00:00
origin = ReadVector(strValue);
break;
case "model":
model = ReadString(strValue);
break;
case "angles":
2024-04-22 22:11:12 +00:00
angles = ReadVector(strValue);
break;
case "angle":
2024-04-22 22:11:12 +00:00
angles[1] = ReadFloat(strValue);
break;
case "solid":
2024-04-22 22:11:12 +00:00
solid = ReadFloat(strValue);
break;
case "friction":
2024-04-22 22:11:12 +00:00
friction = ReadFloat(strValue);
break;
case "editor_color":
m_vecEditorColor = ReadVector(strValue);
break;
#ifdef SERVER
case "health":
2024-04-22 22:11:12 +00:00
health = ReadFloat(strValue);
break;
case "movewith":
case "parentname":
m_parent = ReadString(strValue);
break;
case "ignorepvs":
tempCheck = ReadBool(strValue);
if (tempCheck == true)
pvsflags = PVSF_IGNOREPVS;
else
pvsflags &= ~PVSF_IGNOREPVS;
break;
#endif
2024-04-22 22:11:12 +00:00
case "editor_mins":
case "editor_maxs":
case "editor_usage":
case "editor_model":
2024-06-22 07:24:13 +00:00
case "editor_rotatable":
case "editor_description":
case "_minlight":
break;
default:
2024-04-22 22:11:12 +00:00
super::SpawnKey(strKey, strValue);
break;
}
}
2024-04-22 22:11:12 +00:00
void
ncEntity::Show(void)
2024-04-22 22:11:12 +00:00
{
effects &= ~EF_NODRAW;
}
2024-04-22 22:11:12 +00:00
void
ncEntity::Hide(void)
2024-04-22 22:11:12 +00:00
{
effects |= EF_NODRAW;
}
2024-04-22 22:11:12 +00:00
bool
ncEntity::IsHidden(void)
2024-04-22 22:11:12 +00:00
{
return (effects & EF_NODRAW) ? true : false;
}
2024-04-22 22:11:12 +00:00
void
ncEntity::Disappear(void)
2024-04-22 22:11:12 +00:00
{
modelindex = (0);
SetSolid(SOLID_NOT);
}
2024-04-22 22:11:12 +00:00
void
ncEntity::MakeStatic(void)
2024-04-22 22:11:12 +00:00
{
makestatic(this);
}
bool
ncEntity::CanSpawn(bool clientSide)
{
2024-04-22 22:11:12 +00:00
return !(clientSide);
}
2024-04-22 22:11:12 +00:00
bool
ncEntity::WithinBounds(entity check)
2024-04-22 22:11:12 +00:00
{
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);
2024-04-22 22:11:12 +00:00
return (true);
}
2024-04-22 22:11:12 +00:00
bool
ncEntity::IntersectsWith(entity check)
2024-04-22 22:11:12 +00:00
{
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);
2024-04-22 22:11:12 +00:00
return (true);
}
2024-04-22 22:11:12 +00:00
bool
ncEntity::StartSound(string strSample, float channel, float flags, bool broadcast)
2024-04-22 22:11:12 +00:00
{
if not (whichpack(strcat("sound/", strSample)))
return (false);
2024-04-22 22:11:12 +00:00
if (broadcast) {
sound(this, channel, strSample, 1.0f, ATTN_NORM, 0, SOUNDFLAG_FOLLOW);
} else {
#ifdef SERVER
msg_entity = this;
2024-04-22 22:11:12 +00:00
sound(this, channel, strSample, 1.0f, ATTN_NORM, 0, SOUNDFLAG_UNICAST | SOUNDFLAG_FOLLOW);
msg_entity = __NULL__;
#else
2024-04-22 22:11:12 +00:00
sound(this, channel, strSample, 1.0f, ATTN_NORM, 0, SOUNDFLAG_FOLLOW);
#endif
}
2024-04-22 22:11:12 +00:00
SndEntLog("%s (chan: %d bcast: %d) (%v)", strSample, channel, broadcast, origin);
2024-04-22 22:11:12 +00:00
return (true);
}
2024-04-22 22:11:12 +00:00
bool
ncEntity::StartSoundDef(string strSample, float channel, bool broadcast)
2024-04-22 22:11:12 +00:00
{
SndEntLog("%s (chan: %d bcast: %d)", strSample, channel, broadcast);
Sound_Play(this, channel, strSample);
return (true);
}
2024-04-22 22:11:12 +00:00
void
ncEntity::StopSound(float channel, bool broadcast)
2024-04-22 22:11:12 +00:00
{
if (broadcast) {
Sound_Stop(this, channel);
} else {
#ifdef SERVER
msg_entity = this;
sound(this, channel, "common/null.wav", 0.1f, ATTN_NORM, 100, SOUNDFLAG_UNICAST | SOUNDFLAG_FOLLOW, 0 );
2024-04-22 22:11:12 +00:00
msg_entity = __NULL__;
#else
Sound_Stop(this, channel);
#endif
}
}
2024-04-22 22:11:12 +00:00
vector
ncEntity::NearestWallPointForRadius(float radius)
{
vector vecRadius = [radius, radius, radius];
tracebox(origin, -vecRadius, vecRadius, origin, MOVE_EVERYTHING, this);
2024-09-17 19:46:31 +00:00
return (trace_fraction <= 1.0) ? (trace_endpos) : (origin);
}
2024-04-22 22:11:12 +00:00
void
ncEntity::HandleThink(void)
2024-04-22 22:11:12 +00:00
{
/* support for think/nextthink */
2024-04-22 22:11:12 +00:00
if (think && nextthink > 0.0f) {
if (nextthink < time) {
nextthink = 0.0f;
think();
}
}
}
2024-04-22 22:11:12 +00:00
bool
ncEntity::IsFacing(entity target)
{
2024-04-22 22:11:12 +00:00
vector vecDiff = vectorNormalize(target.origin - origin);
return ((vecDiff * GetForward()) > 0) ? true : false;
}
2024-04-22 22:11:12 +00:00
bool
ncEntity::IsFacingPosition(vector targetPos)
{
2024-04-22 22:11:12 +00:00
vector vecDiff = vectorNormalize(targetPos - origin);
return ((vecDiff * GetForward()) > 0) ? true : false;
}
float
ncEntity::GetSpawnAge(void)
{
2024-04-22 22:11:12 +00:00
return (time - m_flSpawnTime);
}
float
ncEntity::GetSpawnTime(void)
{
2024-04-22 22:11:12 +00:00
return (m_flSpawnTime);
}
void
ncEntity::Transport(vector new_pos, vector new_ang)
{
2024-04-22 22:11:12 +00:00
float flSpeed = length(this.GetVelocity());
SetVelocity(anglesToForward(new_ang) * flSpeed);
SetOrigin(new_pos);
SetAngles(new_ang);
#ifdef SERVER
2024-09-17 19:46:31 +00:00
if (isClient(this)) {
Client_FixAngle(this, new_ang);
2024-06-22 07:24:13 +00:00
}
#endif
2023-09-21 03:50:54 +00:00
}
void
ncEntity::Relink(void)
2023-09-21 03:50:54 +00:00
{
setorigin(this, origin);
}
vector
ncEntity::GetNearbySpot(void)
{
vector testPos;
float minDist = maxs[0];
2024-04-22 22:11:12 +00:00
vector fwdDir, rightDir, upDir;
fwdDir = anglesToForward([0,0,0]);
rightDir = anglesToRight([0,0,0]);
upDir = anglesToUp([0,0,0]);
/* space in front? */
2024-04-22 22:11:12 +00:00
testPos = GetOrigin() + fwdDir * minDist;
tracebox(testPos, mins, maxs, testPos, MOVE_NORMAL, this);
2024-09-17 19:46:31 +00:00
if (trace_fraction == 1.0f) {
2024-06-22 07:24:13 +00:00
return (testPos);
2024-09-17 19:46:31 +00:00
}
/* behind? */
2024-04-22 22:11:12 +00:00
testPos = GetOrigin() - fwdDir * minDist;
tracebox(testPos, mins, maxs, testPos, MOVE_NORMAL, this);
2024-09-17 19:46:31 +00:00
if (trace_fraction == 1.0f) {
2024-06-22 07:24:13 +00:00
return (testPos);
2024-09-17 19:46:31 +00:00
}
2024-04-22 22:11:12 +00:00
/* left? */
2024-04-22 22:11:12 +00:00
testPos = GetOrigin() - rightDir * minDist;
tracebox(testPos, mins, maxs, testPos, MOVE_NORMAL, this);
2024-09-17 19:46:31 +00:00
if (trace_fraction == 1.0f) {
2024-06-22 07:24:13 +00:00
return (testPos);
2024-09-17 19:46:31 +00:00
}
/* right? */
2024-04-22 22:11:12 +00:00
testPos = GetOrigin() + rightDir * minDist;
tracebox(testPos, mins, maxs, testPos, MOVE_NORMAL, this);
2024-09-17 19:46:31 +00:00
if (trace_fraction == 1.0f) {
2024-06-22 07:24:13 +00:00
return (testPos);
2024-09-17 19:46:31 +00:00
}
/* front left? */
2024-04-22 22:11:12 +00:00
testPos = GetOrigin() + fwdDir * minDist - rightDir * minDist;
tracebox(testPos, mins, maxs, testPos, MOVE_NORMAL, this);
2024-09-17 19:46:31 +00:00
if (trace_fraction == 1.0f) {
2024-06-22 07:24:13 +00:00
return (testPos);
2024-09-17 19:46:31 +00:00
}
/* front right? */
2024-04-22 22:11:12 +00:00
testPos = GetOrigin() + fwdDir * minDist + rightDir * minDist;
tracebox(testPos, mins, maxs, testPos, MOVE_NORMAL, this);
2024-09-17 19:46:31 +00:00
if (trace_fraction == 1.0f) {
2024-06-22 07:24:13 +00:00
return (testPos);
2024-09-17 19:46:31 +00:00
}
/* back left? */
2024-04-22 22:11:12 +00:00
testPos = GetOrigin() - fwdDir * minDist - rightDir * minDist;
tracebox(testPos, mins, maxs, testPos, MOVE_NORMAL, this);
2024-09-17 19:46:31 +00:00
if (trace_fraction == 1.0f) {
2024-06-22 07:24:13 +00:00
return (testPos);
2024-09-17 19:46:31 +00:00
}
/* back right? */
2024-04-22 22:11:12 +00:00
testPos = GetOrigin() - fwdDir * minDist + rightDir * minDist;
tracebox(testPos, mins, maxs, testPos, MOVE_NORMAL, this);
2024-09-17 19:46:31 +00:00
if (trace_fraction == 1.0f) {
2024-06-22 07:24:13 +00:00
return (testPos);
2024-09-17 19:46:31 +00:00
}
2024-06-22 07:24:13 +00:00
return (g_vec_null);
}
bool
ncEntity::_ProjectileAttack(string defName, bool wasReleased)
2024-06-22 07:24:13 +00:00
{
#ifdef SERVER
string attackDef;
2024-07-18 20:04:42 +00:00
int numProjectiles = GetSubDefInt(defName, "numProjectiles");
float sX = GetSubDefFloat(defName, "spread_x");
float sY = GetSubDefFloat(defName, "spread_y");
2024-06-22 07:24:13 +00:00
/* always fire at least 1 */
if (numProjectiles <= 0i) {
numProjectiles = 1i;
}
2024-06-22 07:24:13 +00:00
if (wasReleased == true) {
2024-07-18 20:04:42 +00:00
attackDef = GetSubDefString(defName, "def_onRelease");
2024-06-22 07:24:13 +00:00
} else {
2024-07-18 20:04:42 +00:00
attackDef = GetSubDefString(defName, "def_onFire");
2024-06-22 07:24:13 +00:00
}
for (int i = 0i; i < numProjectiles; i++) {
EntLog("Launching %S at %v towards %v", attackDef, GetEyePos(), GetViewAngle());
ncAttack_SpawnDefAtPosition(attackDef, (ncActor)this, GetEyePos(), GetViewAngle());
2024-06-22 07:24:13 +00:00
}
#endif
return (true);
}
bool
ncEntity::AttackByDef(string defName, bool wasReleased)
2024-06-22 07:24:13 +00:00
{
if (!defName) {
return (false);
}
#ifdef SERVER
_ProjectileAttack(defName, wasReleased);
#endif
return (true);
}
void
ncEntity::SetBotTag(botInfo_t newTag)
{
#ifdef SERVER
botinfo = newTag;
#endif
}
2024-06-22 07:24:13 +00:00
int
ncEntity::GetSharedID(void)
2024-06-22 07:24:13 +00:00
{
#ifdef CLIENT
return (int)(entnum);
#else
return (int)num_for_edict(this);
#endif
}
2024-09-17 19:46:31 +00:00
void
ncEntity::EnablePlayerCollision(void)
2024-09-17 19:46:31 +00:00
{
dimension_solid = 255;
dimension_hit = 255;
}
void
ncEntity::DisablePlayerCollision(void)
2024-09-17 19:46:31 +00:00
{
dimension_solid = 1;
dimension_hit = 1;
}