GS-Entbase: Moving client/baseentity and server/baseentity into a shared

file... Optimisations forthcoming
This commit is contained in:
Marco Cawthorne 2020-11-24 13:55:57 +01:00
parent 8ab685b7b2
commit 2c1bd865c0
10 changed files with 549 additions and 544 deletions

View File

@ -8,7 +8,7 @@ decals.h
materials.h
client/defs.h
client/basefx.cpp
client/baseentity.cpp
shared/baseentity.cpp
client/env_cubemap.cpp
client/env_glow.cpp
client/env_sun.cpp

View File

@ -1,50 +0,0 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* 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.
*/
class CBaseEntity
{
#ifdef GS_RENDERFX
int m_iRenderFX;
float m_iRenderMode;
float m_flRenderAmt;
vector m_vecRenderColor;
#endif
int m_iBody;
float m_flSentenceTime;
sound_t *m_pSentenceQue;
int m_iSentenceCount;
int m_iSentencePos;
/* model events */
float m_flBaseTime;
void(void) CBaseEntity;
virtual void(void) Init;
virtual void(void) Initialized;
virtual void(string, string) SpawnKey;
virtual void(string) Sentence;
virtual void(void) ProcessWordQue;
virtual void(float flChanged) ReceiveEntity;
virtual float(void) predraw;
virtual void(void) postdraw;
virtual void(void) customphysics;
virtual void(float, int, string) ModelEvent;
#ifdef GS_RENDERFX
virtual void(void) RenderFXPass;
#endif
};

View File

@ -14,7 +14,7 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "baseentity.h"
#include "../shared/baseentity.h"
vector g_vecSunDir;

View File

@ -6,7 +6,7 @@
baseentity.h
decals.h
materials.h
server/baseentity.cpp
shared/baseentity.cpp
server/baseoutput.cpp
server/basetrigger.cpp
server/basemonster.cpp

View File

@ -1,443 +0,0 @@
/*
* Copyright (c) 2016-2020 Marco Hladik <marco@icculus.org>
*
* 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.
*/
/* 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
CBaseEntity::SetEffects(float newEffects)
{
if (newEffects == effects)
return;
effects = newEffects;
SendFlags |= BASEFL_CHANGED_EFFECTS;
}
void
CBaseEntity::SetFrame(float newFrame)
{
if (newFrame == frame)
return;
frame = newFrame;
frame1time = 0.0f;
SendFlags |= BASEFL_CHANGED_FRAME;
}
void
CBaseEntity::SetModel(string newModel)
{
model = newModel;
setmodel(this, newModel);
SendFlags |= BASEFL_CHANGED_MODELINDEX;
}
void
CBaseEntity::SetModelindex(float newModelIndex)
{
if (newModelIndex == modelindex)
return;
modelindex = newModelIndex;
SendFlags |= BASEFL_CHANGED_MODELINDEX;
}
void
CBaseEntity::SetMovetype(float newMovetype)
{
if (newMovetype == movetype)
return;
movetype = newMovetype;
SendFlags |= BASEFL_CHANGED_MOVETYPE;
}
void
CBaseEntity::SetSkin(float newSkin)
{
if (newSkin == skin)
return;
skin = newSkin;
SendFlags |= BASEFL_CHANGED_SKIN;
}
void
CBaseEntity::SetSolid(float newSolid)
{
if (newSolid == solid)
return;
solid = newSolid;
SendFlags |= BASEFL_CHANGED_SOLID;
}
void
CBaseEntity::SetBody(int newBody)
{
if (newBody == m_iBody)
return;
m_iBody = newBody;
SendFlags |= BASEFL_CHANGED_BODY;
}
void
CBaseEntity::SetScale(float newScale)
{
if (newScale == scale)
return;
scale = newScale;
SendFlags |= BASEFL_CHANGED_SCALE;
}
void
CBaseEntity::SetAngles(vector newAngles)
{
if (newAngles == angles)
return;
angles = newAngles;
SendFlags |= BASEFL_CHANGED_ANGLES;
}
void
CBaseEntity::SetSize(vector newMins, vector newMaxs)
{
if (newMins == mins && newMaxs == maxs)
return;
setsize(this, newMins, newMaxs);
SendFlags |= BASEFL_CHANGED_SIZE;
}
void
CBaseEntity::SetOrigin(vector newOrigin)
{
if (newOrigin == origin)
return;
setorigin(this, newOrigin);
SendFlags |= BASEFL_CHANGED_ORIGIN;
}
#ifdef GS_RENDERFX
void
CBaseEntity::SetRenderFX(int newFX)
{
if (newFX == m_iRenderFX)
return;
m_iRenderFX = newFX;
SendFlags |= BASEFL_CHANGED_RENDERFX;
}
void
CBaseEntity::SetRenderMode(float newMode)
{
if (newMode == m_iRenderMode)
return;
m_iRenderMode = newMode;
SendFlags |= BASEFL_CHANGED_RENDERMODE;
}
void
CBaseEntity::SetRenderAmt(float newAmt)
{
if (newAmt == m_flRenderAmt)
return;
m_flRenderAmt = newAmt;
SendFlags |= BASEFL_CHANGED_RENDERAMT;
}
void
CBaseEntity::SetRenderColor(vector newColor)
{
if (newColor == m_vecRenderColor)
return;
m_vecRenderColor = newColor;
SendFlags |= BASEFL_CHANGED_RENDERCOLOR;
}
#endif
/* Make sure StartFrame calls this */
float
CBaseEntity::SendEntity(entity ePEnt, float fChanged)
{
if (!modelindex) {
return FALSE;
}
WriteByte(MSG_ENTITY, ENT_ENTITY);
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) {
WriteFloat(MSG_ENTITY, angles[0]);
WriteFloat(MSG_ENTITY, angles[1]);
WriteFloat(MSG_ENTITY, angles[2]);
}
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_FRAME) {
WriteByte(MSG_ENTITY, frame);
}
if (fChanged & BASEFL_CHANGED_SKIN) {
WriteByte(MSG_ENTITY, skin + 128);
}
if (fChanged & BASEFL_CHANGED_EFFECTS) {
WriteFloat(MSG_ENTITY, effects);
}
if (fChanged & BASEFL_CHANGED_BODY) {
WriteByte(MSG_ENTITY, m_iBody);
}
if (fChanged & BASEFL_CHANGED_SCALE) {
WriteFloat(MSG_ENTITY, scale);
}
#ifdef GS_RENDERFX
if (fChanged & BASEFL_CHANGED_RENDERFX) {
WriteByte(MSG_ENTITY, m_iRenderFX);
}
if (fChanged & BASEFL_CHANGED_RENDERMODE) {
WriteByte(MSG_ENTITY, m_iRenderMode);
}
if (fChanged & BASEFL_CHANGED_RENDERCOLOR) {
WriteFloat(MSG_ENTITY, m_vecRenderColor[0]);
WriteFloat(MSG_ENTITY, m_vecRenderColor[1]);
WriteFloat(MSG_ENTITY, m_vecRenderColor[2]);
}
if (fChanged & BASEFL_CHANGED_RENDERAMT) {
WriteFloat(MSG_ENTITY, m_flRenderAmt);
}
#else
if (fChanged & BASEFL_CHANGED_ALPHA) {
WriteFloat(MSG_ENTITY, alpha);
}
#endif
return TRUE;
}
void
CBaseEntity::Pain(void)
{
}
void
CBaseEntity::Death(void)
{
}
/* Make sure StartFrame calls this */
void
CBaseEntity::ParentUpdate(void)
{
/* while the engine is still handling physics for these, we can't
* predict when origin/angle might change */
if (net_origin != origin) {
net_origin = origin;
SendFlags |= BASEFL_CHANGED_ORIGIN;
}
if (net_angles != angles) {
net_angles = angles;
SendFlags |= BASEFL_CHANGED_ANGLES;
}
if (m_parent) {
entity p = find(world, ::targetname, m_parent);
if (!p) {
return;
}
SetOrigin(p.origin);
}
}
void
CBaseEntity::SpawnInit(void)
{
for (int i = 1; i < (tokenize(__fullspawndata) - 1); i += 2) {
SpawnKey(argv(i), argv(i+1));
}
/* some entity might involuntarily call SpawnInit as part of being
a member of CBaseEntity. So we need to make sure that it doesn't
inherit stuff from the last previously loaded entity */
__fullspawndata = "";
}
void
CBaseEntity::Respawn(void)
{
health = m_oldHealth;
SetModel(m_oldModel);
SetSolid(m_oldSolid);
SetAngles(m_oldAngle);
SetOrigin(m_oldOrigin);
target = m_oldstrTarget;
#ifdef GS_RENDERFX
SetRenderFX(m_oldiRenderFX);
SetRenderMode(m_oldiRenderMode);
SetRenderAmt(m_oldflRenderAmt);
SetRenderColor(m_oldvecRenderColor);
#endif
}
void
CBaseEntity::Hide(void)
{
SetModelindex(0);
SetSolid(SOLID_NOT);
SetMovetype(MOVETYPE_NONE);
takedamage = DAMAGE_NO;
}
void
CBaseEntity::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) {
case "scale":
scale = stof(strValue);
break;
case "origin":
origin = stov(strValue);
break;
case "angles":
angles = stov(strValue);
break;
case "angle":
angles[1] = stof(strValue);
break;
case "solid":
solid = stof(strValue);
break;
case "health":
health = stof(strValue);
break;
case "shadows":
if (stof(strValue) == 1) {
effects &= ~EF_NOSHADOW;
}
break;
case "targetname":
targetname = strValue;
break;
case "target":
target = strValue;
break;
case "color":
#ifdef GS_RENDERFX
m_vecRenderColor = stov(strValue);
#else
colormod = stov(strValue);
#endif
break;
case "alpha":
#ifdef GS_RENDERFX
m_flRenderAmt = stof(strValue);
#else
alpha = stof(strValue);
#endif
break;
#ifdef GS_RENDERFX
case "renderamt":
m_flRenderAmt = stof(strValue) / 255;
break;
case "rendercolor":
m_vecRenderColor = stov(strValue) / 255;
break;
case "rendermode":
m_iRenderMode = stoi(strValue);
break;
case "renderfx":
m_iRenderFX = stoi(strValue);
break;
#endif
case "parentname":
m_parent = strValue;
break;
case "model":
model = strValue;
break;
case "classname":
case "spawnflags":
break;
case "ignorepvs":
pvsflags = PVSF_IGNOREPVS;
break;
default:
print(sprintf("^3%s^7::SpawnKey:: Unknown key '%s' with value '%s'\n",
classname, strKey, strValue));
break;
}
}
void
CBaseEntity::CBaseEntity(void)
{
/* Not in Deathmatch */
if (spawnflags & 2048) {
if (cvar("sv_playerslots") > 1) {
remove(this);
return;
}
}
identity = 1;
effects |= EF_NOSHADOW;
scale = 1.0f;
SpawnInit();
m_oldAngle = angles;
m_oldOrigin = origin;
m_oldSolid = solid;
m_oldHealth = health;
m_oldModel = Util_FixModel(model);
#ifdef GS_RENDERFX
m_oldiRenderFX = m_iRenderFX;
m_oldiRenderMode = m_iRenderMode;
m_oldvecRenderColor = m_vecRenderColor;
m_oldflRenderAmt = m_flRenderAmt;
m_oldvecRenderColor = m_vecRenderColor;
m_oldflRenderAmt = m_flRenderAmt;
#endif
m_oldstrTarget = target;
if (m_oldModel != "") {
precache_model(m_oldModel);
}
}

View File

@ -584,6 +584,23 @@ CBaseMonster::Respawn(void)
droptofloor();
}
void
CBaseMonster::SpawnKey(string strKey, string strValue)
{
switch (strKey) {
/* The legacy GoldSrc trigger condition system */
case "TriggerCondition":
m_iTriggerCondition = stoi(strValue);
break;
case "TriggerTarget":
m_strTriggerTarget = strValue;
break;
default:
CBaseEntity::SpawnKey(strKey, strValue);
break;
}
}
void
CBaseMonster::CBaseMonster(void)
{

View File

@ -14,34 +14,16 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* if this is changed, it needs to be changed in the engine (server/sv_move.c)
* as well. */
typedef struct
{
vector m_vecDest;
int m_iFlags;
} nodeslist_t;
/* movement states */
enum
{
MONSTER_IDLE,
MONSTER_FOLLOWING,
MONSTER_CHASING,
MONSTER_AIMING,
MONSTER_DEAD,
MONSTER_GIBBED
};
/* scripted sequence states */
enum
{
SEQUENCESTATE_NONE,
SEQUENCESTATE_IDLE,
SEQUENCESTATE_ACTIVE,
SEQUENCESTATE_ENDING
};
/* monster flags */
enumflags
/* monster flags, these are defined by the level designers */
typedef enumflags
{
MSF_WAITTILLSEEN,
MSF_GAG,
@ -54,17 +36,59 @@ enumflags
MSF_PREDISASTER,
MSF_FADECORPSE,
MSF_MULTIPLAYER
};
} monsterFlag_t;
/* movement states */
typedef enum
{
MONSTER_IDLE,
MONSTER_FOLLOWING,
MONSTER_CHASING,
MONSTER_AIMING,
MONSTER_DEAD,
MONSTER_GIBBED
} monsterState_t;
/* scripted sequence states */
typedef enum
{
SEQUENCESTATE_NONE,
SEQUENCESTATE_IDLE,
SEQUENCESTATE_ACTIVE,
SEQUENCESTATE_ENDING
} sequenceState_t;
/* alliance state */
enum
typedef enum
{
MAL_FRIEND, /* friendly towards the player */
MAL_ENEMY, /* unfriendly towards the player */
MAL_ALIEN, /* unfriendly towards anyone but themselves */
MAL_ROGUE /* no allies, not even amongst themselves */
};
} allianceState_t;
/* These numerations involve the m_iTriggerCondition attribute.
* Basically these conditions are being checked and triggered depending on what
* it's set to. If any of those checks are successful, we trigger our target
* under the m_strTriggerTarget attribute. */
typedef enum
{
MTRIG_NONE, /* nothing */
MTRIG_SEEPLAYER_ANGRY, /* we see an enemy player, that we want to harm */
MTRIG_PAIN, /* taken damage */
MTRIG_HALFHEALTH, /* lost half of our base_health */
MTRIG_DEATH, /* we have died. */
MTRIG_SQUADMEMBERDEAD, /* a squad member died */
MTRIG_SQUADLEADERDEAD, /* the squad leader died */
MTRIG_HEARNOISE, /* we hear some noise around the world. */
MTRIG_HEARENEMYPLAYER, /* we hear a player we are enemies with */
MTRIG_HEARWEAPONS, /* we hear weapons being fired */
MTRIG_SEEPLAYER, /* we see a player, don't have to be angry at him. */
MTRIG_SEEPLAYER_RELAXED, /* we see a player and we're currently attacking anything */
} triggerCondition_t;
/* FIXME: I'd like to move this into CBaseMonster, but our current IsFriend()
* check is currently only checking on a .takedamage basis. */
.int m_iAlliance;
class CBaseMonster:CBaseEntity
@ -87,6 +111,9 @@ class CBaseMonster:CBaseEntity
vector m_vecSequenceAngle;
vector m_vecTurnAngle;
int m_iTriggerCondition;
string m_strTriggerTarget;
/* model events */
float m_flBaseTime;
@ -115,6 +142,7 @@ class CBaseMonster:CBaseEntity
virtual void(void) Gib;
virtual void(string) Sound;
virtual void(float, int, string) ModelEvent;
virtual void(string, string) SpawnKey;
/* see/hear subsystem */
float m_flSeeTime;

View File

@ -14,7 +14,7 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "baseentity.h"
#include "../shared/baseentity.h"
#include "basetrigger.h"
#include "basemonster.h"
#include "basenpc.h"

View File

@ -14,10 +14,7 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* a lot of the rendering info is assembled with the following url:
* https://sites.google.com/site/svenmanor/rendermodes
* for reference. I thank thee fellow soldiers at sven manor! */
#ifdef CLIENT
var int autocvar_cl_showtriggers = FALSE;
var int autocvar_rm_unlit_additive = TRUE;
var int autocvar_rm_unlit_texture = TRUE;
@ -442,3 +439,432 @@ CBaseEntity_ParseSentence(void)
print(sprintf("^3CBaseNPC_ParseSentence^7: Entity %d not in PVS\n", e));
}
}
#else
/* 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
CBaseEntity::SetEffects(float newEffects)
{
if (newEffects == effects)
return;
effects = newEffects;
SendFlags |= BASEFL_CHANGED_EFFECTS;
}
void
CBaseEntity::SetFrame(float newFrame)
{
if (newFrame == frame)
return;
frame = newFrame;
frame1time = 0.0f;
SendFlags |= BASEFL_CHANGED_FRAME;
}
void
CBaseEntity::SetModel(string newModel)
{
model = newModel;
setmodel(this, newModel);
SendFlags |= BASEFL_CHANGED_MODELINDEX;
}
void
CBaseEntity::SetModelindex(float newModelIndex)
{
if (newModelIndex == modelindex)
return;
modelindex = newModelIndex;
SendFlags |= BASEFL_CHANGED_MODELINDEX;
}
void
CBaseEntity::SetMovetype(float newMovetype)
{
if (newMovetype == movetype)
return;
movetype = newMovetype;
SendFlags |= BASEFL_CHANGED_MOVETYPE;
}
void
CBaseEntity::SetSkin(float newSkin)
{
if (newSkin == skin)
return;
skin = newSkin;
SendFlags |= BASEFL_CHANGED_SKIN;
}
void
CBaseEntity::SetSolid(float newSolid)
{
if (newSolid == solid)
return;
solid = newSolid;
SendFlags |= BASEFL_CHANGED_SOLID;
}
void
CBaseEntity::SetBody(int newBody)
{
if (newBody == m_iBody)
return;
m_iBody = newBody;
SendFlags |= BASEFL_CHANGED_BODY;
}
void
CBaseEntity::SetScale(float newScale)
{
if (newScale == scale)
return;
scale = newScale;
SendFlags |= BASEFL_CHANGED_SCALE;
}
void
CBaseEntity::SetAngles(vector newAngles)
{
if (newAngles == angles)
return;
angles = newAngles;
SendFlags |= BASEFL_CHANGED_ANGLES;
}
void
CBaseEntity::SetSize(vector newMins, vector newMaxs)
{
if (newMins == mins && newMaxs == maxs)
return;
setsize(this, newMins, newMaxs);
SendFlags |= BASEFL_CHANGED_SIZE;
}
void
CBaseEntity::SetOrigin(vector newOrigin)
{
if (newOrigin == origin)
return;
setorigin(this, newOrigin);
SendFlags |= BASEFL_CHANGED_ORIGIN;
}
#ifdef GS_RENDERFX
void
CBaseEntity::SetRenderFX(int newFX)
{
if (newFX == m_iRenderFX)
return;
m_iRenderFX = newFX;
SendFlags |= BASEFL_CHANGED_RENDERFX;
}
void
CBaseEntity::SetRenderMode(float newMode)
{
if (newMode == m_iRenderMode)
return;
m_iRenderMode = newMode;
SendFlags |= BASEFL_CHANGED_RENDERMODE;
}
void
CBaseEntity::SetRenderAmt(float newAmt)
{
if (newAmt == m_flRenderAmt)
return;
m_flRenderAmt = newAmt;
SendFlags |= BASEFL_CHANGED_RENDERAMT;
}
void
CBaseEntity::SetRenderColor(vector newColor)
{
if (newColor == m_vecRenderColor)
return;
m_vecRenderColor = newColor;
SendFlags |= BASEFL_CHANGED_RENDERCOLOR;
}
#endif
/* Make sure StartFrame calls this */
float
CBaseEntity::SendEntity(entity ePEnt, float fChanged)
{
if (!modelindex) {
return FALSE;
}
WriteByte(MSG_ENTITY, ENT_ENTITY);
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) {
WriteFloat(MSG_ENTITY, angles[0]);
WriteFloat(MSG_ENTITY, angles[1]);
WriteFloat(MSG_ENTITY, angles[2]);
}
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_FRAME) {
WriteByte(MSG_ENTITY, frame);
}
if (fChanged & BASEFL_CHANGED_SKIN) {
WriteByte(MSG_ENTITY, skin + 128);
}
if (fChanged & BASEFL_CHANGED_EFFECTS) {
WriteFloat(MSG_ENTITY, effects);
}
if (fChanged & BASEFL_CHANGED_BODY) {
WriteByte(MSG_ENTITY, m_iBody);
}
if (fChanged & BASEFL_CHANGED_SCALE) {
WriteFloat(MSG_ENTITY, scale);
}
#ifdef GS_RENDERFX
if (fChanged & BASEFL_CHANGED_RENDERFX) {
WriteByte(MSG_ENTITY, m_iRenderFX);
}
if (fChanged & BASEFL_CHANGED_RENDERMODE) {
WriteByte(MSG_ENTITY, m_iRenderMode);
}
if (fChanged & BASEFL_CHANGED_RENDERCOLOR) {
WriteFloat(MSG_ENTITY, m_vecRenderColor[0]);
WriteFloat(MSG_ENTITY, m_vecRenderColor[1]);
WriteFloat(MSG_ENTITY, m_vecRenderColor[2]);
}
if (fChanged & BASEFL_CHANGED_RENDERAMT) {
WriteFloat(MSG_ENTITY, m_flRenderAmt);
}
#else
if (fChanged & BASEFL_CHANGED_ALPHA) {
WriteFloat(MSG_ENTITY, alpha);
}
#endif
return TRUE;
}
void
CBaseEntity::Pain(void)
{
}
void
CBaseEntity::Death(void)
{
}
/* Make sure StartFrame calls this */
void
CBaseEntity::ParentUpdate(void)
{
/* while the engine is still handling physics for these, we can't
* predict when origin/angle might change */
if (net_origin != origin) {
net_origin = origin;
SendFlags |= BASEFL_CHANGED_ORIGIN;
}
if (net_angles != angles) {
net_angles = angles;
SendFlags |= BASEFL_CHANGED_ANGLES;
}
if (m_parent) {
entity p = find(world, ::targetname, m_parent);
if (!p) {
return;
}
SetOrigin(p.origin);
}
}
void
CBaseEntity::SpawnInit(void)
{
for (int i = 1; i < (tokenize(__fullspawndata) - 1); i += 2) {
SpawnKey(argv(i), argv(i+1));
}
/* some entity might involuntarily call SpawnInit as part of being
a member of CBaseEntity. So we need to make sure that it doesn't
inherit stuff from the last previously loaded entity */
__fullspawndata = "";
}
void
CBaseEntity::Respawn(void)
{
health = m_oldHealth;
SetModel(m_oldModel);
SetSolid(m_oldSolid);
SetAngles(m_oldAngle);
SetOrigin(m_oldOrigin);
target = m_oldstrTarget;
#ifdef GS_RENDERFX
SetRenderFX(m_oldiRenderFX);
SetRenderMode(m_oldiRenderMode);
SetRenderAmt(m_oldflRenderAmt);
SetRenderColor(m_oldvecRenderColor);
#endif
}
void
CBaseEntity::Hide(void)
{
SetModelindex(0);
SetSolid(SOLID_NOT);
SetMovetype(MOVETYPE_NONE);
takedamage = DAMAGE_NO;
}
void
CBaseEntity::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) {
case "scale":
scale = stof(strValue);
break;
case "origin":
origin = stov(strValue);
break;
case "angles":
angles = stov(strValue);
break;
case "angle":
angles[1] = stof(strValue);
break;
case "solid":
solid = stof(strValue);
break;
case "health":
health = stof(strValue);
break;
case "shadows":
if (stof(strValue) == 1) {
effects &= ~EF_NOSHADOW;
}
break;
case "targetname":
targetname = strValue;
break;
case "target":
target = strValue;
break;
case "color":
#ifdef GS_RENDERFX
m_vecRenderColor = stov(strValue);
#else
colormod = stov(strValue);
#endif
break;
case "alpha":
#ifdef GS_RENDERFX
m_flRenderAmt = stof(strValue);
#else
alpha = stof(strValue);
#endif
break;
#ifdef GS_RENDERFX
case "renderamt":
m_flRenderAmt = stof(strValue) / 255;
break;
case "rendercolor":
m_vecRenderColor = stov(strValue) / 255;
break;
case "rendermode":
m_iRenderMode = stoi(strValue);
break;
case "renderfx":
m_iRenderFX = stoi(strValue);
break;
#endif
case "parentname":
m_parent = strValue;
break;
case "model":
model = strValue;
break;
case "classname":
case "spawnflags":
break;
case "ignorepvs":
pvsflags = PVSF_IGNOREPVS;
break;
default:
print(sprintf("^3%s^7::SpawnKey:: Unknown key '%s' with value '%s'\n",
classname, strKey, strValue));
break;
}
}
void
CBaseEntity::CBaseEntity(void)
{
/* Not in Deathmatch */
if (spawnflags & 2048) {
if (cvar("sv_playerslots") > 1) {
remove(this);
return;
}
}
identity = 1;
effects |= EF_NOSHADOW;
scale = 1.0f;
SpawnInit();
m_oldAngle = angles;
m_oldOrigin = origin;
m_oldSolid = solid;
m_oldHealth = health;
m_oldModel = Util_FixModel(model);
#ifdef GS_RENDERFX
m_oldiRenderFX = m_iRenderFX;
m_oldiRenderMode = m_iRenderMode;
m_oldvecRenderColor = m_vecRenderColor;
m_oldflRenderAmt = m_flRenderAmt;
m_oldvecRenderColor = m_vecRenderColor;
m_oldflRenderAmt = m_flRenderAmt;
#endif
m_oldstrTarget = target;
if (m_oldModel != "") {
precache_model(m_oldModel);
}
}
#endif

View File

@ -16,9 +16,33 @@
class CBaseEntity
{
string m_oldstrTarget; /* needed due to trigger_changetarget */
int m_iBody;
#ifdef CLIENT
float m_flSentenceTime;
sound_t *m_pSentenceQue;
int m_iSentenceCount;
int m_iSentencePos;
/* model events */
float m_flBaseTime;
void(void) CBaseEntity;
virtual void(void) Init;
virtual void(void) Initialized;
virtual void(string, string) SpawnKey;
virtual void(string) Sentence;
virtual void(void) ProcessWordQue;
virtual void(float flChanged) ReceiveEntity;
virtual float(void) predraw;
virtual void(void) postdraw;
virtual void(void) customphysics;
virtual void(float, int, string) ModelEvent;
#endif
#ifdef SERVER
string m_oldstrTarget; /* needed due to trigger_changetarget */
/* respawn */
string m_oldModel;
float m_oldSolid;
@ -30,19 +54,6 @@ class CBaseEntity
vector net_origin;
vector net_angles;
#ifdef GS_RENDERFX
int m_iRenderFX;
float m_iRenderMode;
float m_flRenderAmt;
vector m_vecRenderColor;
/* respawn */
int m_oldiRenderFX;
float m_oldiRenderMode;
float m_oldflRenderAmt;
vector m_oldvecRenderColor;
#endif
string m_parent;
void(void) CBaseEntity;
@ -67,11 +78,27 @@ class CBaseEntity
virtual void(vector, vector) SetSize;
virtual void(string, string) SpawnKey;
virtual void(void) SpawnInit;
#endif
#ifdef GS_RENDERFX
virtual void(int) SetRenderFX;
virtual void(float) SetRenderMode;
virtual void(float) SetRenderAmt;
virtual void(vector) SetRenderColor;
int m_iRenderFX;
float m_iRenderMode;
float m_flRenderAmt;
vector m_vecRenderColor;
#ifdef CLIENT
virtual void(void) RenderFXPass;
#else
/* respawn */
int m_oldiRenderFX;
float m_oldiRenderMode;
float m_oldflRenderAmt;
vector m_oldvecRenderColor;
virtual void(int) SetRenderFX;
virtual void(float) SetRenderMode;
virtual void(float) SetRenderAmt;
virtual void(vector) SetRenderColor;
#endif
#endif
};