2243 lines
78 KiB
C++
2243 lines
78 KiB
C++
//========= Copyright Valve Corporation, All rights reserved. ============//
|
|
//
|
|
// Purpose: A base class for the client-side representation of entities.
|
|
//
|
|
// This class encompasses both entities that are created on the
|
|
//server and networked to the client AND entities that are created on the
|
|
// client.
|
|
//
|
|
// $NoKeywords: $
|
|
//===========================================================================//
|
|
|
|
#ifndef C_BASEENTITY_H
|
|
#define C_BASEENTITY_H
|
|
#ifdef _WIN32
|
|
#pragma once
|
|
#endif
|
|
|
|
#include "../../public/client_class.h"
|
|
#include "../../public/engine/ivmodelinfo.h"
|
|
#include "../../public/engine/ivmodelrender.h"
|
|
#include "../../public/iclientunknown.h"
|
|
#include "../../public/mathlib/vector.h"
|
|
#include "../shared/ehandle.h"
|
|
#include "client_thinklist.h"
|
|
#include "icliententityinternal.h"
|
|
#include "iclientshadowmgr.h"
|
|
#if !defined(NO_ENTITY_PREDICTION)
|
|
#include "../shared/predictableid.h"
|
|
#endif
|
|
#include "../../public/networkvar.h"
|
|
#include "../../public/soundflags.h"
|
|
#include "../shared/shareddefs.h"
|
|
#include "collisionproperty.h"
|
|
#include "interpolatedvar.h"
|
|
#include "particle_property.h"
|
|
#include "tier0/threadtools.h"
|
|
#include "toolframework/itoolentity.h"
|
|
|
|
class C_Team;
|
|
class IPhysicsObject;
|
|
class IClientVehicle;
|
|
class CPredictionCopy;
|
|
class C_BasePlayer;
|
|
struct studiohdr_t;
|
|
class CStudioHdr;
|
|
class CDamageModifier;
|
|
class IRecipientFilter;
|
|
class CUserCmd;
|
|
struct solid_t;
|
|
class ISave;
|
|
class IRestore;
|
|
class C_BaseAnimating;
|
|
class C_AI_BaseNPC;
|
|
struct EmitSound_t;
|
|
class C_RecipientFilter;
|
|
class CTakeDamageInfo;
|
|
class C_BaseCombatCharacter;
|
|
class CEntityMapData;
|
|
class ConVar;
|
|
class CDmgAccumulator;
|
|
class IHasAttributes;
|
|
|
|
struct CSoundParameters;
|
|
|
|
typedef unsigned int AimEntsListHandle_t;
|
|
|
|
#define INVALID_AIMENTS_LIST_HANDLE (AimEntsListHandle_t) ~0
|
|
|
|
extern void RecvProxy_IntToColor32(const CRecvProxyData *pData, void *pStruct,
|
|
void *pOut);
|
|
extern void RecvProxy_LocalVelocity(const CRecvProxyData *pData, void *pStruct,
|
|
void *pOut);
|
|
|
|
enum CollideType_t {
|
|
ENTITY_SHOULD_NOT_COLLIDE = 0,
|
|
ENTITY_SHOULD_COLLIDE,
|
|
ENTITY_SHOULD_RESPOND
|
|
};
|
|
|
|
class VarMapEntry_t {
|
|
public:
|
|
unsigned short type;
|
|
unsigned short
|
|
m_bNeedsToInterpolate; // Set to false when this var doesn't
|
|
// need Interpolate() called on it anymore.
|
|
void *data;
|
|
IInterpolatedVar *watcher;
|
|
};
|
|
|
|
struct VarMapping_t {
|
|
VarMapping_t() { m_nInterpolatedEntries = 0; }
|
|
|
|
CUtlVector<VarMapEntry_t> m_Entries;
|
|
int m_nInterpolatedEntries;
|
|
float m_lastInterpolationTime;
|
|
};
|
|
|
|
#define DECLARE_INTERPOLATION()
|
|
|
|
// How many data slots to use when in multiplayer.
|
|
#define MULTIPLAYER_BACKUP 90
|
|
|
|
struct serialentity_t;
|
|
|
|
typedef CHandle<C_BaseEntity> EHANDLE; // The client's version of EHANDLE.
|
|
|
|
typedef void (C_BaseEntity::*BASEPTR)(void);
|
|
typedef void (C_BaseEntity::*ENTITYFUNCPTR)(C_BaseEntity *pOther);
|
|
|
|
// For entity creation on the client
|
|
typedef C_BaseEntity *(*DISPATCHFUNCTION)(void);
|
|
|
|
#include "groundlink.h"
|
|
#include "touchlink.h"
|
|
|
|
#if !defined(NO_ENTITY_PREDICTION)
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: For fully client side entities we use this information to determine
|
|
// authoritatively if the server has acknowledged creating this entity, etc.
|
|
//-----------------------------------------------------------------------------
|
|
struct PredictionContext {
|
|
PredictionContext() {
|
|
m_bActive = false;
|
|
m_nCreationCommandNumber = -1;
|
|
m_pszCreationModule = NULL;
|
|
m_nCreationLineNumber = 0;
|
|
m_hServerEntity = NULL;
|
|
}
|
|
|
|
// The command_number of the usercmd which created this entity
|
|
bool m_bActive;
|
|
int m_nCreationCommandNumber;
|
|
char const *m_pszCreationModule;
|
|
int m_nCreationLineNumber;
|
|
// The entity to whom we are attached
|
|
CHandle<C_BaseEntity> m_hServerEntity;
|
|
};
|
|
#endif
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: think contexts
|
|
//-----------------------------------------------------------------------------
|
|
struct thinkfunc_t {
|
|
BASEPTR m_pfnThink;
|
|
string_t m_iszContext;
|
|
int m_nNextThinkTick;
|
|
int m_nLastThinkTick;
|
|
};
|
|
|
|
#define CREATE_PREDICTED_ENTITY(className) \
|
|
C_BaseEntity::CreatePredictedEntityByName(className, __FILE__, __LINE__);
|
|
|
|
// Entity flags that only exist on the client.
|
|
#define ENTCLIENTFLAG_GETTINGSHADOWRENDERBOUNDS \
|
|
0x0001 // Tells us if we're getting the real ent render bounds or the
|
|
// shadow render bounds.
|
|
#define ENTCLIENTFLAG_DONTUSEIK \
|
|
0x0002 // Don't use IK on this entity even if its model has IK.
|
|
#define ENTCLIENTFLAG_ALWAYS_INTERPOLATE 0x0004 // Used by view models.
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Base client side entity object
|
|
//-----------------------------------------------------------------------------
|
|
class C_BaseEntity : public IClientEntity {
|
|
// Construction
|
|
DECLARE_CLASS_NOBASE(C_BaseEntity);
|
|
|
|
friend class CPrediction;
|
|
friend void cc_cl_interp_all_changed(IConVar *pConVar,
|
|
const char *pOldString,
|
|
float flOldValue);
|
|
|
|
public:
|
|
DECLARE_DATADESC();
|
|
DECLARE_CLIENTCLASS();
|
|
DECLARE_PREDICTABLE();
|
|
|
|
C_BaseEntity();
|
|
virtual ~C_BaseEntity();
|
|
|
|
static C_BaseEntity *CreatePredictedEntityByName(const char *classname,
|
|
const char *module,
|
|
int line,
|
|
bool persist = false);
|
|
|
|
// FireBullets uses shared code for prediction.
|
|
virtual void FireBullets(const FireBulletsInfo_t &info);
|
|
virtual void ModifyFireBulletsDamage(CTakeDamageInfo *dmgInfo) {}
|
|
virtual bool ShouldDrawUnderwaterBulletBubbles();
|
|
virtual bool ShouldDrawWaterImpacts(void) { return true; }
|
|
virtual bool HandleShotImpactingWater(const FireBulletsInfo_t &info,
|
|
const Vector &vecEnd,
|
|
ITraceFilter *pTraceFilter,
|
|
Vector *pVecTracerDest);
|
|
virtual ITraceFilter *GetBeamTraceFilter(void);
|
|
virtual void DispatchTraceAttack(const CTakeDamageInfo &info,
|
|
const Vector &vecDir, trace_t *ptr,
|
|
CDmgAccumulator *pAccumulator = NULL);
|
|
virtual void TraceAttack(const CTakeDamageInfo &info, const Vector &vecDir,
|
|
trace_t *ptr,
|
|
CDmgAccumulator *pAccumulator = NULL);
|
|
virtual void DoImpactEffect(trace_t &tr, int nDamageType);
|
|
virtual void MakeTracer(const Vector &vecTracerSrc, const trace_t &tr,
|
|
int iTracerType);
|
|
virtual int GetTracerAttachment(void);
|
|
void ComputeTracerStartPosition(const Vector &vecShotSrc,
|
|
Vector *pVecTracerStart);
|
|
void TraceBleed(float flDamage, const Vector &vecDir, trace_t *ptr,
|
|
int bitsDamageType);
|
|
virtual int BloodColor();
|
|
virtual const char *GetTracerType();
|
|
|
|
virtual void Spawn(void);
|
|
virtual void SpawnClientEntity(void);
|
|
virtual void Precache(void);
|
|
virtual void Activate();
|
|
|
|
virtual void ParseMapData(CEntityMapData *mapData);
|
|
virtual bool KeyValue(const char *szKeyName, const char *szValue);
|
|
virtual bool KeyValue(const char *szKeyName, float flValue);
|
|
virtual bool KeyValue(const char *szKeyName, const Vector &vecValue);
|
|
virtual bool GetKeyValue(const char *szKeyName, char *szValue, int iMaxLen);
|
|
|
|
// Entities block Line-Of-Sight for NPCs by default.
|
|
// Set this to false if you want to change this behavior.
|
|
void SetBlocksLOS(bool bBlocksLOS);
|
|
bool BlocksLOS(void);
|
|
void SetAIWalkable(bool bBlocksLOS);
|
|
bool IsAIWalkable(void);
|
|
|
|
void Interp_SetupMappings(VarMapping_t *map);
|
|
|
|
// Returns 1 if there are no more changes (ie: we could call
|
|
// RemoveFromInterpolationList).
|
|
int Interp_Interpolate(VarMapping_t *map, float currentTime);
|
|
|
|
void Interp_RestoreToLastNetworked(VarMapping_t *map);
|
|
void Interp_UpdateInterpolationAmounts(VarMapping_t *map);
|
|
void Interp_HierarchyUpdateInterpolationAmounts();
|
|
|
|
// Called by the CLIENTCLASS macros.
|
|
virtual bool Init(int entnum, int iSerialNum);
|
|
|
|
// Called in the destructor to shutdown everything.
|
|
void Term();
|
|
|
|
// memory handling, uses calloc so members are zero'd out on instantiation
|
|
void *operator new(size_t stAllocateBlock);
|
|
void *operator new[](size_t stAllocateBlock);
|
|
void *operator new(size_t stAllocateBlock, int nBlockUse,
|
|
const char *pFileName, int nLine);
|
|
void *operator new[](size_t stAllocateBlock, int nBlockUse,
|
|
const char *pFileName, int nLine);
|
|
void operator delete(void *pMem);
|
|
void operator delete(void *pMem, int nBlockUse, const char *pFileName,
|
|
int nLine) {
|
|
operator delete(pMem);
|
|
}
|
|
|
|
// This just picks one of the routes to IClientUnknown.
|
|
IClientUnknown *GetIClientUnknown() { return this; }
|
|
virtual C_BaseAnimating *GetBaseAnimating() { return NULL; }
|
|
virtual void SetClassname(const char *className);
|
|
|
|
string_t m_iClassname;
|
|
|
|
// IClientUnknown overrides.
|
|
public:
|
|
virtual void SetRefEHandle(const CBaseHandle &handle);
|
|
virtual const CBaseHandle &GetRefEHandle() const;
|
|
|
|
void SetToolHandle(HTOOLHANDLE handle);
|
|
HTOOLHANDLE GetToolHandle() const;
|
|
|
|
void EnableInToolView(bool bEnable);
|
|
bool IsEnabledInToolView() const;
|
|
|
|
void SetToolRecording(bool recording);
|
|
bool IsToolRecording() const;
|
|
bool HasRecordedThisFrame() const;
|
|
virtual void RecordToolMessage();
|
|
|
|
// used to exclude entities from being recorded in the SFM tools
|
|
void DontRecordInTools();
|
|
bool ShouldRecordInTools() const;
|
|
|
|
virtual void Release();
|
|
virtual ICollideable *GetCollideable() { return &m_Collision; }
|
|
virtual IClientNetworkable *GetClientNetworkable() { return this; }
|
|
virtual IClientRenderable *GetClientRenderable() { return this; }
|
|
virtual IClientEntity *GetIClientEntity() { return this; }
|
|
virtual C_BaseEntity *GetBaseEntity() { return this; }
|
|
virtual IClientThinkable *GetClientThinkable() { return this; }
|
|
|
|
// Methods of IClientRenderable
|
|
public:
|
|
virtual const Vector &GetRenderOrigin(void);
|
|
virtual const QAngle &GetRenderAngles(void);
|
|
virtual Vector GetObserverCamOrigin(void) {
|
|
return GetRenderOrigin();
|
|
} // Return the origin for player observers tracking this target
|
|
virtual const matrix3x4_t &RenderableToWorldTransform();
|
|
virtual bool IsTransparent(void);
|
|
virtual bool IsTwoPass(void);
|
|
virtual bool UsesPowerOfTwoFrameBufferTexture();
|
|
virtual bool UsesFullFrameBufferTexture();
|
|
virtual bool IgnoresZBuffer(void) const;
|
|
virtual const model_t *GetModel(void) const;
|
|
virtual int DrawModel(int flags);
|
|
virtual void ComputeFxBlend(void);
|
|
virtual int GetFxBlend(void);
|
|
virtual bool LODTest() { return true; } // NOTE: UNUSED
|
|
virtual void GetRenderBounds(Vector &mins, Vector &maxs);
|
|
virtual IPVSNotify *GetPVSNotifyInterface();
|
|
virtual void GetRenderBoundsWorldspace(Vector &absMins, Vector &absMaxs);
|
|
|
|
virtual void GetShadowRenderBounds(Vector &mins, Vector &maxs,
|
|
ShadowType_t shadowType);
|
|
|
|
// Determine the color modulation amount
|
|
virtual void GetColorModulation(float *color);
|
|
|
|
virtual void OnThreadedDrawSetup() {}
|
|
|
|
public:
|
|
virtual bool TestCollision(const Ray_t &ray, unsigned int fContentsMask,
|
|
trace_t &tr);
|
|
virtual bool TestHitboxes(const Ray_t &ray, unsigned int fContentsMask,
|
|
trace_t &tr);
|
|
|
|
// To mimic server call convention
|
|
C_BaseEntity *GetOwnerEntity(void) const;
|
|
void SetOwnerEntity(C_BaseEntity *pOwner);
|
|
|
|
C_BaseEntity *GetEffectEntity(void) const;
|
|
void SetEffectEntity(C_BaseEntity *pEffectEnt);
|
|
|
|
// This function returns a value that scales all damage done by this entity.
|
|
// Use CDamageModifier to hook in damage modifiers on a guy.
|
|
virtual float GetAttackDamageScale(void);
|
|
|
|
// IClientNetworkable implementation.
|
|
public:
|
|
virtual void NotifyShouldTransmit(ShouldTransmitState_t state);
|
|
|
|
// save out interpolated values
|
|
virtual void PreDataUpdate(DataUpdateType_t updateType);
|
|
virtual void PostDataUpdate(DataUpdateType_t updateType);
|
|
virtual void OnDataUnchangedInPVS();
|
|
|
|
virtual void ValidateModelIndex(void);
|
|
|
|
// pvs info. NOTE: Do not override these!!
|
|
virtual void SetDormant(bool bDormant);
|
|
virtual bool IsDormant(void);
|
|
|
|
// Tells the entity that it's about to be destroyed due to the client
|
|
// receiving an uncompressed update that's caused it to destroy all entities
|
|
// & recreate them.
|
|
virtual void SetDestroyedOnRecreateEntities(void);
|
|
|
|
virtual int GetEFlags() const;
|
|
virtual void SetEFlags(int iEFlags);
|
|
void AddEFlags(int nEFlagMask);
|
|
void RemoveEFlags(int nEFlagMask);
|
|
bool IsEFlagSet(int nEFlagMask) const;
|
|
|
|
// checks to see if the entity is marked for deletion
|
|
bool IsMarkedForDeletion(void);
|
|
|
|
virtual int entindex(void) const;
|
|
|
|
// This works for client-only entities and returns the GetEntryIndex() of
|
|
// the entity's handle, so the sound system can get an IClientEntity from
|
|
// it.
|
|
int GetSoundSourceIndex() const;
|
|
|
|
// Server to client message received
|
|
virtual void ReceiveMessage(int classID, bf_read &msg);
|
|
|
|
virtual void *GetDataTableBasePtr();
|
|
|
|
// IClientThinkable.
|
|
public:
|
|
// Called whenever you registered for a think message (with
|
|
// SetNextClientThink).
|
|
virtual void ClientThink();
|
|
|
|
virtual ClientThinkHandle_t GetThinkHandle();
|
|
virtual void SetThinkHandle(ClientThinkHandle_t hThink);
|
|
|
|
public:
|
|
void AddVar(void *data, IInterpolatedVar *watcher, int type,
|
|
bool bSetup = false);
|
|
void RemoveVar(void *data, bool bAssert = true);
|
|
VarMapping_t *GetVarMapping();
|
|
|
|
VarMapping_t m_VarMap;
|
|
|
|
public:
|
|
// An inline version the game code can use
|
|
CCollisionProperty *CollisionProp();
|
|
const CCollisionProperty *CollisionProp() const;
|
|
CParticleProperty *ParticleProp();
|
|
const CParticleProperty *ParticleProp() const;
|
|
|
|
// Simply here for game shared
|
|
bool IsFloating();
|
|
|
|
virtual bool ShouldSavePhysics();
|
|
|
|
// save/restore stuff
|
|
virtual void OnSave();
|
|
virtual void OnRestore();
|
|
// capabilities for save/restore
|
|
virtual int ObjectCaps(void);
|
|
// only overload these if you have special data to serialize
|
|
virtual int Save(ISave &save);
|
|
virtual int Restore(IRestore &restore);
|
|
|
|
private:
|
|
int SaveDataDescBlock(ISave &save, datamap_t *dmap);
|
|
int RestoreDataDescBlock(IRestore &restore, datamap_t *dmap);
|
|
|
|
// Called after restoring data into prediction slots. This function is used
|
|
// in place of proxies on the variables, so if some variable like
|
|
// m_nModelIndex needs to update other state (like the model pointer), it is
|
|
// done here.
|
|
void OnPostRestoreData();
|
|
|
|
public:
|
|
// Called after spawn, and in the case of self-managing objects, after load
|
|
virtual bool CreateVPhysics();
|
|
|
|
// Convenience routines to init the vphysics simulation for this object.
|
|
// This creates a static object. Something that behaves like world geometry
|
|
// - solid, but never moves
|
|
IPhysicsObject *VPhysicsInitStatic(void);
|
|
|
|
// This creates a normal vphysics simulated object
|
|
IPhysicsObject *VPhysicsInitNormal(SolidType_t solidType, int nSolidFlags,
|
|
bool createAsleep,
|
|
solid_t *pSolid = NULL);
|
|
|
|
// This creates a vphysics object with a shadow controller that follows the
|
|
// AI Move the object to where it should be and call
|
|
// UpdatePhysicsShadowToCurrentPosition()
|
|
IPhysicsObject *VPhysicsInitShadow(bool allowPhysicsMovement,
|
|
bool allowPhysicsRotation,
|
|
solid_t *pSolid = NULL);
|
|
|
|
private:
|
|
// called by all vphysics inits
|
|
bool VPhysicsInitSetup();
|
|
|
|
public:
|
|
void VPhysicsSetObject(IPhysicsObject *pPhysics);
|
|
// destroy and remove the physics object for this entity
|
|
virtual void VPhysicsDestroyObject(void);
|
|
|
|
// Purpose: My physics object has been updated, react or extract data
|
|
virtual void VPhysicsUpdate(IPhysicsObject *pPhysics);
|
|
inline IPhysicsObject *VPhysicsGetObject(void) const {
|
|
return m_pPhysicsObject;
|
|
}
|
|
virtual int VPhysicsGetObjectList(IPhysicsObject **pList, int listMax);
|
|
virtual bool VPhysicsIsFlesh(void);
|
|
|
|
// IClientEntity implementation.
|
|
public:
|
|
virtual bool SetupBones(matrix3x4_t *pBoneToWorldOut, int nMaxBones,
|
|
int boneMask, float currentTime);
|
|
virtual void SetupWeights(const matrix3x4_t *pBoneToWorld,
|
|
int nFlexWeightCount, float *pFlexWeights,
|
|
float *pFlexDelayedWeights);
|
|
virtual bool UsesFlexDelayedWeights() { return false; }
|
|
virtual void DoAnimationEvents(void);
|
|
|
|
// Add entity to visible entities list?
|
|
virtual void AddEntity(void);
|
|
|
|
virtual const Vector &GetAbsOrigin(void) const;
|
|
virtual const QAngle &GetAbsAngles(void) const;
|
|
|
|
const Vector &GetNetworkOrigin() const;
|
|
const QAngle &GetNetworkAngles() const;
|
|
|
|
void SetNetworkOrigin(const Vector &org);
|
|
void SetNetworkAngles(const QAngle &ang);
|
|
|
|
const Vector &GetLocalOrigin(void) const;
|
|
void SetLocalOrigin(const Vector &origin);
|
|
vec_t GetLocalOriginDim(int iDim)
|
|
const; // You can use the X_INDEX, Y_INDEX, and Z_INDEX defines here.
|
|
void SetLocalOriginDim(int iDim, vec_t flValue);
|
|
|
|
const QAngle &GetLocalAngles(void) const;
|
|
void SetLocalAngles(const QAngle &angles);
|
|
vec_t GetLocalAnglesDim(int iDim)
|
|
const; // You can use the X_INDEX, Y_INDEX, and Z_INDEX defines here.
|
|
void SetLocalAnglesDim(int iDim, vec_t flValue);
|
|
|
|
virtual const Vector &GetPrevLocalOrigin() const;
|
|
virtual const QAngle &GetPrevLocalAngles() const;
|
|
|
|
void SetLocalTransform(const matrix3x4_t &localTransform);
|
|
|
|
void SetModelName(string_t name);
|
|
string_t GetModelName(void) const;
|
|
|
|
int GetModelIndex(void) const;
|
|
void SetModelIndex(int index);
|
|
virtual int CalcOverrideModelIndex() { return -1; }
|
|
|
|
// These methods return a *world-aligned* box relative to the absorigin of
|
|
// the entity. This is used for collision purposes and is *not* guaranteed
|
|
// to surround the entire entity's visual representation
|
|
// NOTE: It is illegal to ask for the world-aligned bounds for
|
|
// SOLID_BSP objects
|
|
virtual const Vector &WorldAlignMins() const;
|
|
virtual const Vector &WorldAlignMaxs() const;
|
|
|
|
// This defines collision bounds *in whatever space is currently defined by
|
|
// the solid type*
|
|
// SOLID_BBOX: World Align
|
|
// SOLID_OBB: Entity space
|
|
// SOLID_BSP: Entity space
|
|
// SOLID_VPHYSICS Not used
|
|
void SetCollisionBounds(const Vector &mins, const Vector &maxs);
|
|
|
|
// NOTE: These use the collision OBB to compute a reasonable center point
|
|
// for the entity
|
|
virtual const Vector &WorldSpaceCenter() const;
|
|
|
|
// FIXME: Do we want this?
|
|
const Vector &WorldAlignSize() const;
|
|
bool IsPointSized() const;
|
|
|
|
// Returns a radius of a sphere
|
|
// *centered at the world space center* bounding the collision
|
|
// representation of the entity. NOTE: The world space center *may* move
|
|
// when the entity rotates.
|
|
float BoundingRadius() const;
|
|
|
|
// Used when the collision prop is told to ask game code for the world-space
|
|
// surrounding box
|
|
virtual void ComputeWorldSpaceSurroundingBox(Vector *pVecWorldMins,
|
|
Vector *pVecWorldMaxs);
|
|
virtual float GetHealthBarHeightOffset() const { return 0.f; }
|
|
|
|
// Returns the entity-to-world transform
|
|
matrix3x4_t &EntityToWorldTransform();
|
|
const matrix3x4_t &EntityToWorldTransform() const;
|
|
|
|
// Some helper methods that transform a point from entity space to world
|
|
// space + back
|
|
void EntityToWorldSpace(const Vector &in, Vector *pOut) const;
|
|
void WorldToEntitySpace(const Vector &in, Vector *pOut) const;
|
|
|
|
// This function gets your parent's transform. If you're parented to an
|
|
// attachment, this calculates the attachment's transform and gives you
|
|
// that.
|
|
//
|
|
// You must pass in tempMatrix for scratch space - it may need to fill that
|
|
// in and return it instead of pointing you right at a variable in your
|
|
// parent.
|
|
matrix3x4_t &GetParentToWorldTransform(matrix3x4_t &tempMatrix);
|
|
|
|
void GetVectors(Vector *forward, Vector *right, Vector *up) const;
|
|
|
|
// Sets abs angles, but also sets local angles to be appropriate
|
|
void SetAbsOrigin(const Vector &origin);
|
|
void SetAbsAngles(const QAngle &angles);
|
|
|
|
void AddFlag(int flags);
|
|
void RemoveFlag(int flagsToRemove);
|
|
void ToggleFlag(int flagToToggle);
|
|
int GetFlags(void) const;
|
|
void ClearFlags();
|
|
|
|
MoveType_t GetMoveType(void) const;
|
|
MoveCollide_t GetMoveCollide(void) const;
|
|
virtual SolidType_t GetSolid(void) const;
|
|
|
|
virtual int GetSolidFlags(void) const;
|
|
bool IsSolidFlagSet(int flagMask) const;
|
|
void SetSolidFlags(int nFlags);
|
|
void AddSolidFlags(int nFlags);
|
|
void RemoveSolidFlags(int nFlags);
|
|
bool IsSolid() const;
|
|
|
|
virtual class CMouthInfo *GetMouth(void);
|
|
|
|
// Retrieve sound spatialization info for the specified sound on this entity
|
|
// Return false to indicate sound is not audible
|
|
virtual bool GetSoundSpatialization(SpatializationInfo_t &info);
|
|
|
|
// Attachments
|
|
virtual int LookupAttachment(const char *pAttachmentName) { return -1; }
|
|
virtual bool GetAttachment(int number, matrix3x4_t &matrix);
|
|
virtual bool GetAttachment(int number, Vector &origin);
|
|
virtual bool GetAttachment(int number, Vector &origin, QAngle &angles);
|
|
virtual bool GetAttachmentVelocity(int number, Vector &originVel,
|
|
Quaternion &angleVel);
|
|
|
|
// Team handling
|
|
virtual C_Team *GetTeam(void);
|
|
virtual int GetTeamNumber(void) const;
|
|
virtual void ChangeTeam(int iTeamNum); // Assign this entity to a team.
|
|
virtual int GetRenderTeamNumber(void);
|
|
virtual bool InSameTeam(
|
|
C_BaseEntity *pEntity); // Returns true if the specified entity is on
|
|
// the same team as this one
|
|
virtual bool InLocalTeam(void);
|
|
|
|
// ID Target handling
|
|
virtual bool IsValidIDTarget(void) { return false; }
|
|
virtual const char *GetIDString(void) { return ""; };
|
|
|
|
// See CSoundEmitterSystem
|
|
virtual void ModifyEmitSoundParams(EmitSound_t ¶ms);
|
|
|
|
void EmitSound(
|
|
const char *soundname, float soundtime = 0.0f,
|
|
float *duration = NULL); // Override for doing the general case of
|
|
// CPASAttenuationFilter( this ), and
|
|
// EmitSound( filter, entindex(), etc. );
|
|
void EmitSound(
|
|
const char *soundname, HSOUNDSCRIPTHANDLE &handle,
|
|
float soundtime = 0.0f,
|
|
float *duration = NULL); // Override for doing the general case of
|
|
// CPASAttenuationFilter( this ), and
|
|
// EmitSound( filter, entindex(), etc. );
|
|
void StopSound(const char *soundname);
|
|
void StopSound(const char *soundname, HSOUNDSCRIPTHANDLE &handle);
|
|
void GenderExpandString(char const *in, char *out, int maxlen);
|
|
|
|
static float GetSoundDuration(const char *soundname,
|
|
char const *actormodel);
|
|
|
|
static bool GetParametersForSound(const char *soundname,
|
|
CSoundParameters ¶ms,
|
|
const char *actormodel);
|
|
static bool GetParametersForSound(const char *soundname,
|
|
HSOUNDSCRIPTHANDLE &handle,
|
|
CSoundParameters ¶ms,
|
|
const char *actormodel);
|
|
|
|
static void EmitSound(IRecipientFilter &filter, int iEntIndex,
|
|
const char *soundname, const Vector *pOrigin = NULL,
|
|
float soundtime = 0.0f, float *duration = NULL);
|
|
static void EmitSound(IRecipientFilter &filter, int iEntIndex,
|
|
const char *soundname, HSOUNDSCRIPTHANDLE &handle,
|
|
const Vector *pOrigin = NULL, float soundtime = 0.0f,
|
|
float *duration = NULL);
|
|
static void StopSound(int iEntIndex, const char *soundname);
|
|
static soundlevel_t LookupSoundLevel(const char *soundname);
|
|
static soundlevel_t LookupSoundLevel(const char *soundname,
|
|
HSOUNDSCRIPTHANDLE &handle);
|
|
|
|
static void EmitSound(IRecipientFilter &filter, int iEntIndex,
|
|
const EmitSound_t ¶ms);
|
|
static void EmitSound(IRecipientFilter &filter, int iEntIndex,
|
|
const EmitSound_t ¶ms,
|
|
HSOUNDSCRIPTHANDLE &handle);
|
|
|
|
static void StopSound(int iEntIndex, int iChannel, const char *pSample);
|
|
|
|
static void EmitAmbientSound(int entindex, const Vector &origin,
|
|
const char *soundname, int flags = 0,
|
|
float soundtime = 0.0f,
|
|
float *duration = NULL);
|
|
|
|
// These files need to be listed in scripts/game_sounds_manifest.txt
|
|
static HSOUNDSCRIPTHANDLE PrecacheScriptSound(const char *soundname);
|
|
static void PrefetchScriptSound(const char *soundname);
|
|
|
|
// For each client who appears to be a valid recipient, checks the client
|
|
// has disabled CC and if so, removes them from
|
|
// the recipient list.
|
|
static void RemoveRecipientsIfNotCloseCaptioning(C_RecipientFilter &filter);
|
|
static void EmitCloseCaption(IRecipientFilter &filter, int entindex,
|
|
char const *token,
|
|
CUtlVector<Vector> &soundorigins,
|
|
float duration, bool warnifmissing = false);
|
|
|
|
// Moves all aiments into their correct position for the frame
|
|
static void MarkAimEntsDirty();
|
|
static void CalcAimEntPositions();
|
|
|
|
static bool IsPrecacheAllowed();
|
|
static void SetAllowPrecache(bool allow);
|
|
|
|
static bool m_bAllowPrecache;
|
|
|
|
static bool IsSimulatingOnAlternateTicks();
|
|
|
|
// C_BaseEntity local functions
|
|
public:
|
|
void UpdatePartitionListEntry();
|
|
|
|
// This can be used to setup the entity as a client-only entity.
|
|
// Override this to perform per-entity clientside setup
|
|
virtual bool InitializeAsClientEntity(const char *pszModelName,
|
|
RenderGroup_t renderGroup);
|
|
|
|
// This function gets called on all client entities once per simulation
|
|
// phase. It dispatches events like OnDataChanged(), and calls the legacy
|
|
// function AddEntity().
|
|
virtual void Simulate();
|
|
|
|
// This event is triggered during the simulation phase if an entity's data
|
|
// has changed. It is better to hook this instead of PostDataUpdate()
|
|
// because in PostDataUpdate(), server entity origins are incorrect and
|
|
// attachment points can't be used.
|
|
virtual void OnDataChanged(DataUpdateType_t type);
|
|
|
|
// This is called once per frame before any data is read in from the server.
|
|
virtual void OnPreDataChanged(DataUpdateType_t type);
|
|
|
|
bool IsStandable() const;
|
|
bool IsBSPModel() const;
|
|
|
|
// If this is a vehicle, returns the vehicle interface
|
|
virtual IClientVehicle *GetClientVehicle() { return NULL; }
|
|
|
|
// Returns the aiment render origin + angles
|
|
virtual void GetAimEntOrigin(IClientEntity *pAttachedTo, Vector *pAbsOrigin,
|
|
QAngle *pAbsAngles);
|
|
|
|
// get network origin from previous update
|
|
virtual const Vector &GetOldOrigin();
|
|
|
|
// Methods relating to traversing hierarchy
|
|
C_BaseEntity *GetMoveParent(void) const;
|
|
C_BaseEntity *GetRootMoveParent();
|
|
C_BaseEntity *FirstMoveChild(void) const;
|
|
C_BaseEntity *NextMovePeer(void) const;
|
|
|
|
inline ClientEntityHandle_t GetClientHandle() const {
|
|
return ClientEntityHandle_t(m_RefEHandle);
|
|
}
|
|
inline bool IsServerEntity(void);
|
|
|
|
virtual RenderGroup_t GetRenderGroup();
|
|
|
|
virtual void GetToolRecordingState(KeyValues *msg);
|
|
virtual void CleanupToolRecordingState(KeyValues *msg);
|
|
|
|
// The value returned by here determines whether or not (and how) the entity
|
|
// is put into the spatial partition.
|
|
virtual CollideType_t GetCollideType(void);
|
|
|
|
virtual bool ShouldDraw();
|
|
inline bool IsVisible() const {
|
|
return m_hRender != INVALID_CLIENT_RENDER_HANDLE;
|
|
}
|
|
virtual void UpdateVisibility();
|
|
|
|
// Returns true if the entity changes its position every frame on the server
|
|
// but it doesn't set animtime. In that case, the client returns true here
|
|
// so it copies the server time to animtime in OnDataChanged and the
|
|
// position history is correct for interpolation.
|
|
virtual bool IsSelfAnimating();
|
|
|
|
// Set appropriate flags and store off data when these fields are about to
|
|
// change
|
|
virtual void OnLatchInterpolatedVariables(int flags);
|
|
// For predictable entities, stores last networked value
|
|
void OnStoreLastNetworkedValue();
|
|
|
|
// Initialize things given a new model.
|
|
virtual CStudioHdr *OnNewModel();
|
|
virtual void OnNewParticleEffect(const char *pszParticleName,
|
|
CNewParticleEffect *pNewParticleEffect);
|
|
|
|
bool IsSimulatedEveryTick() const;
|
|
bool IsAnimatedEveryTick() const;
|
|
void SetSimulatedEveryTick(bool sim);
|
|
void SetAnimatedEveryTick(bool anim);
|
|
|
|
void Interp_Reset(VarMapping_t *map);
|
|
virtual void ResetLatched();
|
|
|
|
float GetInterpolationAmount(int flags);
|
|
float GetLastChangeTime(int flags);
|
|
|
|
// Interpolate the position for rendering
|
|
virtual bool Interpolate(float currentTime);
|
|
|
|
// Did the object move so far that it shouldn't interpolate?
|
|
bool Teleported(void);
|
|
// Is this a submodel of the world ( *1 etc. in name ) ( brush models only )
|
|
virtual bool IsSubModel(void);
|
|
// Deal with EF_* flags
|
|
virtual void CreateLightEffects(void);
|
|
|
|
void AddToAimEntsList();
|
|
void RemoveFromAimEntsList();
|
|
|
|
// Reset internal fields
|
|
virtual void Clear(void);
|
|
// Helper to draw raw brush models
|
|
virtual int DrawBrushModel(bool bTranslucent, int nFlags, bool bTwoPass);
|
|
|
|
// returns the material animation start time
|
|
virtual float GetTextureAnimationStartTime();
|
|
// Indicates that a texture animation has wrapped
|
|
virtual void TextureAnimationWrapped();
|
|
|
|
// Set the next think time. Pass in CLIENT_THINK_ALWAYS to have Think()
|
|
// called each frame.
|
|
virtual void SetNextClientThink(float nextThinkTime);
|
|
|
|
// anything that has health can override this...
|
|
virtual void SetHealth(int iHealth) {}
|
|
virtual int GetHealth() const { return 0; }
|
|
virtual int GetMaxHealth() const { return 1; }
|
|
virtual bool IsVisibleToTargetID(void) const { return false; }
|
|
virtual bool IsHealthBarVisible(void) const { return false; }
|
|
|
|
// Returns the health fraction
|
|
float HealthFraction() const;
|
|
|
|
// Should this object cast shadows?
|
|
virtual ShadowType_t ShadowCastType();
|
|
|
|
// Should this object receive shadows?
|
|
virtual bool ShouldReceiveProjectedTextures(int flags);
|
|
|
|
// Shadow-related methods
|
|
virtual bool IsShadowDirty();
|
|
virtual void MarkShadowDirty(bool bDirty);
|
|
virtual IClientRenderable *GetShadowParent();
|
|
virtual IClientRenderable *FirstShadowChild();
|
|
virtual IClientRenderable *NextShadowPeer();
|
|
|
|
// Sets up a render handle so the leaf system will draw this entity.
|
|
void AddToLeafSystem();
|
|
void AddToLeafSystem(RenderGroup_t group);
|
|
// remove entity form leaf system again
|
|
void RemoveFromLeafSystem();
|
|
|
|
// A method to apply a decal to an entity
|
|
virtual void AddDecal(const Vector &rayStart, const Vector &rayEnd,
|
|
const Vector &decalCenter, int hitbox, int decalIndex,
|
|
bool doTrace, trace_t &tr,
|
|
int maxLODToDecal = ADDDECAL_TO_ALL_LODS);
|
|
|
|
virtual void AddColoredDecal(const Vector &rayStart, const Vector &rayEnd,
|
|
const Vector &decalCenter, int hitbox,
|
|
int decalIndex, bool doTrace, trace_t &tr,
|
|
Color cColor,
|
|
int maxLODToDecal = ADDDECAL_TO_ALL_LODS);
|
|
|
|
// A method to remove all decals from an entity
|
|
void RemoveAllDecals(void);
|
|
|
|
// Is this a brush model?
|
|
bool IsBrushModel() const;
|
|
|
|
// A random value 0-1 used by proxies to make sure they're not all in sync
|
|
float ProxyRandomValue() const { return m_flProxyRandomValue; }
|
|
|
|
// The spawn time of this entity
|
|
float SpawnTime() const { return m_flSpawnTime; }
|
|
|
|
virtual bool IsClientCreated(void) const;
|
|
|
|
virtual void UpdateOnRemove(void);
|
|
|
|
virtual void SUB_Remove(void);
|
|
|
|
// Prediction stuff
|
|
/////////////////
|
|
void CheckInitPredictable(const char *context);
|
|
|
|
void AllocateIntermediateData(void);
|
|
void DestroyIntermediateData(void);
|
|
void ShiftIntermediateDataForward(int slots_to_remove,
|
|
int previous_last_slot);
|
|
|
|
void *GetPredictedFrame(int framenumber);
|
|
void *GetOriginalNetworkDataObject(void);
|
|
bool IsIntermediateDataAllocated(void) const;
|
|
|
|
void InitPredictable(void);
|
|
void ShutdownPredictable(void);
|
|
|
|
virtual void SetPredictable(bool state);
|
|
bool GetPredictable(void) const;
|
|
void PreEntityPacketReceived(int commands_acknowledged);
|
|
void PostEntityPacketReceived(void);
|
|
bool PostNetworkDataReceived(int commands_acknowledged);
|
|
bool GetPredictionEligible(void) const;
|
|
void SetPredictionEligible(bool canpredict);
|
|
|
|
enum {
|
|
SLOT_ORIGINALDATA = -1,
|
|
};
|
|
|
|
int SaveData(const char *context, int slot, int type);
|
|
virtual int RestoreData(const char *context, int slot, int type);
|
|
|
|
virtual char const *DamageDecal(int bitsDamageType, int gameMaterial);
|
|
virtual void DecalTrace(trace_t *pTrace, char const *decalName);
|
|
virtual void ImpactTrace(trace_t *pTrace, int iDamageType,
|
|
const char *pCustomImpactName);
|
|
|
|
virtual bool ShouldPredict(void) { return false; };
|
|
// interface function pointers
|
|
void (C_BaseEntity::*m_pfnThink)(void);
|
|
virtual void Think(void) {
|
|
AssertMsg(m_pfnThink != &C_BaseEntity::Think,
|
|
"Infinite recursion is infinitely bad.");
|
|
|
|
if (m_pfnThink) {
|
|
(this->*m_pfnThink)();
|
|
}
|
|
}
|
|
|
|
void PhysicsDispatchThink(BASEPTR thinkFunc);
|
|
|
|
// Toggle the visualization of the entity's abs/bbox
|
|
enum {
|
|
VISUALIZE_COLLISION_BOUNDS = 0x1,
|
|
VISUALIZE_SURROUNDING_BOUNDS = 0x2,
|
|
VISUALIZE_RENDER_BOUNDS = 0x4,
|
|
};
|
|
|
|
void ToggleBBoxVisualization(int fVisFlags);
|
|
void DrawBBoxVisualizations(void);
|
|
|
|
// Methods implemented on both client and server
|
|
public:
|
|
void SetSize(const Vector &vecMin,
|
|
const Vector &vecMax); // UTIL_SetSize( pev, mins, maxs );
|
|
char const *GetClassname(void);
|
|
char const *GetDebugName(void);
|
|
static int PrecacheModel(const char *name);
|
|
static bool PrecacheSound(const char *name);
|
|
static void PrefetchSound(const char *name);
|
|
void Remove(); // UTIL_Remove( this );
|
|
|
|
public:
|
|
// Returns the attachment point index on our parent that our transform is
|
|
// relative to. 0 if we're relative to the parent's absorigin and absangles.
|
|
unsigned char GetParentAttachment() const;
|
|
|
|
// Externalized data objects ( see sharreddefs.h for DataObjectType_t )
|
|
bool HasDataObjectType(int type) const;
|
|
void AddDataObjectType(int type);
|
|
void RemoveDataObjectType(int type);
|
|
|
|
void *GetDataObject(int type);
|
|
void *CreateDataObject(int type);
|
|
void DestroyDataObject(int type);
|
|
void DestroyAllDataObjects(void);
|
|
|
|
// Determine approximate velocity based on updates from server
|
|
void EstimateAbsVelocity(Vector &vel);
|
|
|
|
#if !defined(NO_ENTITY_PREDICTION)
|
|
// The player drives simulation of this entity
|
|
void SetPlayerSimulated(C_BasePlayer *pOwner);
|
|
bool IsPlayerSimulated(void) const;
|
|
CBasePlayer *GetSimulatingPlayer(void);
|
|
void UnsetPlayerSimulated(void);
|
|
#endif
|
|
|
|
// Sorry folks, here lies TF2-specific stuff that really has no other place
|
|
// to go
|
|
virtual bool CanBePoweredUp(void) { return false; }
|
|
virtual bool AttemptToPowerup(int iPowerup, float flTime,
|
|
float flAmount = 0,
|
|
C_BaseEntity *pAttacker = NULL,
|
|
CDamageModifier *pDamageModifier = NULL) {
|
|
return false;
|
|
}
|
|
|
|
void SetCheckUntouch(bool check);
|
|
bool GetCheckUntouch() const;
|
|
|
|
virtual bool IsCurrentlyTouching(void) const;
|
|
|
|
virtual void StartTouch(C_BaseEntity *pOther);
|
|
virtual void Touch(C_BaseEntity *pOther);
|
|
virtual void EndTouch(C_BaseEntity *pOther);
|
|
|
|
void (C_BaseEntity ::*m_pfnTouch)(C_BaseEntity *pOther);
|
|
|
|
void PhysicsStep(void);
|
|
|
|
protected:
|
|
static bool sm_bDisableTouchFuncs; // Disables PhysicsTouch and
|
|
// PhysicsStartTouch function calls
|
|
|
|
public:
|
|
touchlink_t *PhysicsMarkEntityAsTouched(C_BaseEntity *other);
|
|
void PhysicsTouch(C_BaseEntity *pentOther);
|
|
void PhysicsStartTouch(C_BaseEntity *pentOther);
|
|
|
|
// HACKHACK:Get the trace_t from the last physics touch call (replaces the
|
|
// even-hackier global trace vars)
|
|
static const trace_t &GetTouchTrace(void);
|
|
|
|
// FIXME: Should be private, but I can't make em private just yet
|
|
void PhysicsImpact(C_BaseEntity *other, trace_t &trace);
|
|
void PhysicsMarkEntitiesAsTouching(C_BaseEntity *other, trace_t &trace);
|
|
void PhysicsMarkEntitiesAsTouchingEventDriven(C_BaseEntity *other,
|
|
trace_t &trace);
|
|
|
|
// Physics helper
|
|
static void PhysicsRemoveTouchedList(C_BaseEntity *ent);
|
|
static void PhysicsNotifyOtherOfUntouch(C_BaseEntity *ent,
|
|
C_BaseEntity *other);
|
|
static void PhysicsRemoveToucher(C_BaseEntity *other, touchlink_t *link);
|
|
|
|
groundlink_t *AddEntityToGroundList(CBaseEntity *other);
|
|
void PhysicsStartGroundContact(CBaseEntity *pentOther);
|
|
|
|
static void PhysicsNotifyOtherOfGroundRemoval(CBaseEntity *ent,
|
|
CBaseEntity *other);
|
|
static void PhysicsRemoveGround(CBaseEntity *other, groundlink_t *link);
|
|
static void PhysicsRemoveGroundList(CBaseEntity *ent);
|
|
|
|
void StartGroundContact(CBaseEntity *ground);
|
|
void EndGroundContact(CBaseEntity *ground);
|
|
|
|
void SetGroundChangeTime(float flTime);
|
|
float GetGroundChangeTime(void);
|
|
|
|
// Remove this as ground entity for all object resting on this object
|
|
void WakeRestingObjects();
|
|
bool HasNPCsOnIt();
|
|
|
|
bool PhysicsCheckWater(void);
|
|
void PhysicsCheckVelocity(void);
|
|
void PhysicsAddHalfGravity(float timestep);
|
|
void PhysicsAddGravityMove(Vector &move);
|
|
|
|
virtual unsigned int PhysicsSolidMaskForEntity(void) const;
|
|
|
|
void SetGroundEntity(C_BaseEntity *ground);
|
|
C_BaseEntity *GetGroundEntity(void);
|
|
|
|
void PhysicsPushEntity(const Vector &push, trace_t *pTrace);
|
|
void PhysicsCheckWaterTransition(void);
|
|
|
|
// Performs the collision resolution for fliers.
|
|
void PerformFlyCollisionResolution(trace_t &trace, Vector &move);
|
|
void ResolveFlyCollisionBounce(trace_t &trace, Vector &vecVelocity,
|
|
float flMinTotalElasticity = 0.0f);
|
|
void ResolveFlyCollisionSlide(trace_t &trace, Vector &vecVelocity);
|
|
void ResolveFlyCollisionCustom(trace_t &trace, Vector &vecVelocity);
|
|
|
|
void PhysicsCheckForEntityUntouch(void);
|
|
|
|
// Creates the shadow (if it doesn't already exist) based on shadow cast
|
|
// type
|
|
void CreateShadow();
|
|
|
|
// Destroys the shadow; causes its type to be recomputed if the entity
|
|
// doesn't go away immediately.
|
|
void DestroyShadow();
|
|
|
|
protected:
|
|
// think function handling
|
|
enum thinkmethods_t {
|
|
THINK_FIRE_ALL_FUNCTIONS,
|
|
THINK_FIRE_BASE_ONLY,
|
|
THINK_FIRE_ALL_BUT_BASE,
|
|
};
|
|
|
|
public:
|
|
// Unlinks from hierarchy
|
|
// Set the movement parent. Your local origin and angles will become
|
|
// relative to this parent. If iAttachment is a valid attachment on the
|
|
// parent, then your local origin and angles are relative to the attachment
|
|
// on this entity.
|
|
void SetParent(C_BaseEntity *pParentEntity, int iParentAttachment = 0);
|
|
|
|
bool PhysicsRunThink(thinkmethods_t thinkMethod = THINK_FIRE_ALL_FUNCTIONS);
|
|
bool PhysicsRunSpecificThink(int nContextIndex, BASEPTR thinkFunc);
|
|
|
|
virtual void PhysicsSimulate(void);
|
|
virtual bool IsAlive(void);
|
|
|
|
bool IsInWorld(void) { return true; }
|
|
|
|
bool IsWorld() { return entindex() == 0; }
|
|
/////////////////
|
|
|
|
virtual bool IsPlayer(void) const { return false; };
|
|
virtual bool IsBaseCombatCharacter(void) { return false; };
|
|
virtual C_BaseCombatCharacter *MyCombatCharacterPointer(void) {
|
|
return NULL;
|
|
}
|
|
virtual bool IsNPC(void) { return false; }
|
|
C_AI_BaseNPC *MyNPCPointer(void);
|
|
virtual bool IsNextBot() { return false; }
|
|
// TF2 specific
|
|
virtual bool IsBaseObject(void) const { return false; }
|
|
virtual bool IsBaseCombatWeapon(void) const { return false; }
|
|
virtual class C_BaseCombatWeapon *MyCombatWeaponPointer() { return NULL; }
|
|
virtual bool IsCombatItem(void) const { return false; }
|
|
|
|
virtual bool IsBaseTrain(void) const { return false; }
|
|
|
|
// Returns the eye point + angles (used for viewing + shooting)
|
|
virtual Vector EyePosition(void);
|
|
virtual const QAngle &EyeAngles(void); // Direction of eyes
|
|
virtual const QAngle &LocalEyeAngles(
|
|
void); // Direction of eyes in local space (pl.v_angle)
|
|
|
|
// position of ears
|
|
virtual Vector EarPosition(void);
|
|
|
|
Vector EyePosition(void) const; // position of eyes
|
|
const QAngle &EyeAngles(void) const; // Direction of eyes in world space
|
|
const QAngle &LocalEyeAngles(void) const; // Direction of eyes
|
|
Vector EarPosition(void) const; // position of ears
|
|
|
|
// Called by physics to see if we should avoid a collision test....
|
|
virtual bool ShouldCollide(int collisionGroup, int contentsMask) const;
|
|
|
|
// Sets physics parameters
|
|
void SetFriction(float flFriction);
|
|
|
|
void SetGravity(float flGravity);
|
|
float GetGravity(void) const;
|
|
|
|
// Sets the model from a model index
|
|
void SetModelByIndex(int nModelIndex);
|
|
|
|
// Set model... (NOTE: Should only be used by client-only entities
|
|
// Returns false if the model name is bogus or otherwise can't be loaded
|
|
bool SetModel(const char *pModelName);
|
|
|
|
void SetModelPointer(const model_t *pModel);
|
|
|
|
// Access movetype and solid.
|
|
void SetMoveType(
|
|
MoveType_t val,
|
|
MoveCollide_t moveCollide =
|
|
MOVECOLLIDE_DEFAULT); // Set to one of the MOVETYPE_ defines.
|
|
void SetMoveCollide(
|
|
MoveCollide_t val); // Set to one of the MOVECOLLIDE_ defines.
|
|
void SetSolid(SolidType_t val); // Set to one of the SOLID_ defines.
|
|
|
|
// NOTE: Setting the abs velocity in either space will cause a recomputation
|
|
// in the other space, so setting the abs velocity will also set the local
|
|
// vel
|
|
void SetLocalVelocity(const Vector &vecVelocity);
|
|
void SetAbsVelocity(const Vector &vecVelocity);
|
|
const Vector &GetLocalVelocity() const;
|
|
const Vector &GetAbsVelocity() const;
|
|
|
|
void ApplyLocalVelocityImpulse(const Vector &vecImpulse);
|
|
void ApplyAbsVelocityImpulse(const Vector &vecImpulse);
|
|
void ApplyLocalAngularVelocityImpulse(const AngularImpulse &angImpulse);
|
|
|
|
// NOTE: Setting the abs velocity in either space will cause a recomputation
|
|
// in the other space, so setting the abs velocity will also set the local
|
|
// vel
|
|
void SetLocalAngularVelocity(const QAngle &vecAngVelocity);
|
|
const QAngle &GetLocalAngularVelocity() const;
|
|
|
|
// void SetAbsAngularVelocity( const QAngle &vecAngAbsVelocity
|
|
//); const QAngle& GetAbsAngularVelocity( ) const;
|
|
|
|
const Vector &GetBaseVelocity() const;
|
|
void SetBaseVelocity(const Vector &v);
|
|
|
|
virtual const Vector &GetViewOffset() const;
|
|
virtual void SetViewOffset(const Vector &v);
|
|
|
|
#ifdef SIXENSE
|
|
const Vector &GetEyeOffset() const;
|
|
void SetEyeOffset(const Vector &v);
|
|
|
|
const QAngle &GetEyeAngleOffset() const;
|
|
void SetEyeAngleOffset(const QAngle &qa);
|
|
#endif
|
|
|
|
// Invalidates the abs state of all children
|
|
void InvalidatePhysicsRecursive(int nChangeFlags);
|
|
|
|
ClientRenderHandle_t GetRenderHandle() const;
|
|
|
|
void SetRemovalFlag(bool bRemove);
|
|
|
|
// Effects...
|
|
bool IsEffectActive(int nEffectMask) const;
|
|
void AddEffects(int nEffects);
|
|
void RemoveEffects(int nEffects);
|
|
int GetEffects(void) const;
|
|
void ClearEffects(void);
|
|
void SetEffects(int nEffects);
|
|
|
|
// Computes the abs position of a point specified in local space
|
|
void ComputeAbsPosition(const Vector &vecLocalPosition,
|
|
Vector *pAbsPosition);
|
|
|
|
// Computes the abs position of a direction specified in local space
|
|
void ComputeAbsDirection(const Vector &vecLocalDirection,
|
|
Vector *pAbsDirection);
|
|
|
|
// These methods encapsulate MOVETYPE_FOLLOW, which became obsolete
|
|
void FollowEntity(CBaseEntity *pBaseEntity, bool bBoneMerge = true);
|
|
void StopFollowingEntity(); // will also change to MOVETYPE_NONE
|
|
bool IsFollowingEntity();
|
|
CBaseEntity *GetFollowedEntity();
|
|
|
|
// For shadows rendering the correct body + sequence...
|
|
virtual int GetBody() { return 0; }
|
|
virtual int GetSkin() { return 0; }
|
|
|
|
// Stubs on client
|
|
void NetworkStateManualMode(bool activate) {}
|
|
void NetworkStateChanged() {}
|
|
void NetworkStateChanged(void *pVar) {}
|
|
void NetworkStateSetUpdateInterval(float N) {}
|
|
void NetworkStateForceUpdate() {}
|
|
|
|
// Think functions with contexts
|
|
int RegisterThinkContext(const char *szContext);
|
|
BASEPTR ThinkSet(BASEPTR func, float flNextThinkTime = 0,
|
|
const char *szContext = NULL);
|
|
void SetNextThink(float nextThinkTime, const char *szContext = NULL);
|
|
float GetNextThink(const char *szContext = NULL);
|
|
float GetLastThink(const char *szContext = NULL);
|
|
int GetNextThinkTick(const char *szContext = NULL);
|
|
int GetLastThinkTick(const char *szContext = NULL);
|
|
|
|
// These set entity flags (EFL_*) to help optimize queries
|
|
void CheckHasThinkFunction(bool isThinkingHint = false);
|
|
void CheckHasGamePhysicsSimulation();
|
|
bool WillThink();
|
|
bool WillSimulateGamePhysics();
|
|
int GetFirstThinkTick(); // get first tick thinking on any context
|
|
|
|
float GetAnimTime() const;
|
|
void SetAnimTime(float at);
|
|
|
|
float GetSimulationTime() const;
|
|
void SetSimulationTime(float st);
|
|
|
|
float GetCreateTime() { return m_flCreateTime; }
|
|
void SetCreateTime(float flCreateTime) { m_flCreateTime = flCreateTime; }
|
|
|
|
int GetCreationTick() const;
|
|
|
|
#ifdef _DEBUG
|
|
void FunctionCheck(void *pFunction, const char *name);
|
|
|
|
ENTITYFUNCPTR TouchSet(ENTITYFUNCPTR func, char *name) {
|
|
// COMPILE_TIME_ASSERT( sizeof(func) == 4 );
|
|
m_pfnTouch = func;
|
|
// FunctionCheck( *(reinterpret_cast<void **>(&m_pfnTouch)), name );
|
|
return func;
|
|
}
|
|
#endif
|
|
|
|
// Gets the model instance + shadow handle
|
|
virtual ModelInstanceHandle_t GetModelInstance() { return m_ModelInstance; }
|
|
void SetModelInstance(ModelInstanceHandle_t hInstance) {
|
|
m_ModelInstance = hInstance;
|
|
}
|
|
bool SnatchModelInstance(C_BaseEntity *pToEntity);
|
|
virtual ClientShadowHandle_t GetShadowHandle() const {
|
|
return m_ShadowHandle;
|
|
}
|
|
virtual ClientRenderHandle_t &RenderHandle();
|
|
|
|
void CreateModelInstance();
|
|
|
|
// Sets the origin + angles to match the last position received
|
|
void MoveToLastReceivedPosition(bool force = false);
|
|
|
|
// Return the IHasAttributes interface for this base entity. Removes the
|
|
// need for:
|
|
// dynamic_cast< IHasAttributes * >( pEntity );
|
|
// Which is remarkably slow.
|
|
// GetAttribInterface( CBaseEntity *pEntity ) in attribute_manager.h uses
|
|
// this function, tests for NULL, and Asserts m_pAttributes ==
|
|
// dynamic_cast.
|
|
inline IHasAttributes *GetHasAttributesInterfacePtr() const {
|
|
return m_pAttributes;
|
|
}
|
|
|
|
protected:
|
|
// NOTE: m_pAttributes needs to be set in the leaf class constructor.
|
|
IHasAttributes *m_pAttributes;
|
|
|
|
// Only meant to be called from subclasses
|
|
void DestroyModelInstance();
|
|
|
|
// Interpolate entity
|
|
static void ProcessTeleportList();
|
|
static void ProcessInterpolatedList();
|
|
static void CheckInterpolatedVarParanoidMeasurement();
|
|
|
|
// overrideable rules if an entity should interpolate
|
|
virtual bool ShouldInterpolate();
|
|
|
|
// Call this in OnDataChanged if you don't chain it down!
|
|
void MarkMessageReceived();
|
|
|
|
// Gets the last message time
|
|
float GetLastMessageTime() const { return m_flLastMessageTime; }
|
|
|
|
// For non-players
|
|
int PhysicsClipVelocity(const Vector &in, const Vector &normal, Vector &out,
|
|
float overbounce);
|
|
|
|
// Allow entities to perform client-side fades
|
|
virtual unsigned char GetClientSideFade() { return 255; }
|
|
|
|
protected:
|
|
// Two part guts of Interpolate(). Shared with C_BaseAnimating.
|
|
enum { INTERPOLATE_STOP = 0, INTERPOLATE_CONTINUE };
|
|
|
|
// Returns INTERPOLATE_STOP or INTERPOLATE_CONTINUE.
|
|
// bNoMoreChanges is set to 1 if you can call RemoveFromInterpolationList on
|
|
// the entity.
|
|
int BaseInterpolatePart1(float ¤tTime, Vector &oldOrigin,
|
|
QAngle &oldAngles, Vector &oldVel,
|
|
int &bNoMoreChanges);
|
|
void BaseInterpolatePart2(Vector &oldOrigin, QAngle &oldAngles,
|
|
Vector &oldVel, int nChangeFlags);
|
|
|
|
public:
|
|
// Accessors for above
|
|
static int GetPredictionRandomSeed(bool bUseUnSyncedServerPlatTime = false);
|
|
static void SetPredictionRandomSeed(const CUserCmd *cmd);
|
|
static C_BasePlayer *GetPredictionPlayer(void);
|
|
static void SetPredictionPlayer(C_BasePlayer *player);
|
|
static void CheckCLInterpChanged();
|
|
|
|
// Collision group accessors
|
|
int GetCollisionGroup() const;
|
|
void SetCollisionGroup(int collisionGroup);
|
|
void CollisionRulesChanged();
|
|
|
|
static C_BaseEntity *Instance(int iEnt);
|
|
// Doesn't do much, but helps with trace results
|
|
static C_BaseEntity *Instance(IClientEntity *ent);
|
|
static C_BaseEntity *Instance(CBaseHandle hEnt);
|
|
// For debugging shared code
|
|
static bool IsServer(void);
|
|
static bool IsClient(void);
|
|
static char const *GetDLLType(void);
|
|
static void SetAbsQueriesValid(bool bValid);
|
|
static bool IsAbsQueriesValid(void);
|
|
|
|
// Enable/disable abs recomputations on a stack.
|
|
static void PushEnableAbsRecomputations(bool bEnable);
|
|
static void PopEnableAbsRecomputations();
|
|
|
|
// This requires the abs recomputation stack to be empty and just sets the
|
|
// global state. It should only be used at the scope of the frame loop.
|
|
static void EnableAbsRecomputations(bool bEnable);
|
|
|
|
static bool IsAbsRecomputationsEnabled(void);
|
|
|
|
// Bloat the culling bbox past the parent ent's bbox in local space if
|
|
// EF_BONEMERGE_FASTCULL is set.
|
|
virtual void BoneMergeFastCullBloat(Vector &localMins, Vector &localMaxs,
|
|
const Vector &thisEntityMins,
|
|
const Vector &thisEntityMaxs) const;
|
|
|
|
// Accessors for color.
|
|
const color32 GetRenderColor() const;
|
|
void SetRenderColor(byte r, byte g, byte b);
|
|
void SetRenderColor(byte r, byte g, byte b, byte a);
|
|
void SetRenderColorR(byte r);
|
|
void SetRenderColorG(byte g);
|
|
void SetRenderColorB(byte b);
|
|
void SetRenderColorA(byte a);
|
|
|
|
void SetRenderMode(RenderMode_t nRenderMode, bool bForceUpdate = false);
|
|
RenderMode_t GetRenderMode() const;
|
|
|
|
public:
|
|
// Determine what entity this corresponds to
|
|
int index;
|
|
|
|
// Render information
|
|
unsigned char m_nRenderFX;
|
|
unsigned char m_nRenderFXBlend;
|
|
|
|
// Entity flags that are only for the client (ENTCLIENTFLAG_ defines).
|
|
unsigned short m_EntClientFlags;
|
|
|
|
CNetworkColor32(m_clrRender);
|
|
|
|
private:
|
|
// Model for rendering
|
|
const model_t *model;
|
|
|
|
public:
|
|
// Time animation sequence or frame was last changed
|
|
float m_flAnimTime;
|
|
float m_flOldAnimTime;
|
|
|
|
float m_flSimulationTime;
|
|
float m_flOldSimulationTime;
|
|
|
|
float m_flCreateTime;
|
|
|
|
byte m_ubInterpolationFrame;
|
|
byte m_ubOldInterpolationFrame;
|
|
|
|
private:
|
|
// Effects to apply
|
|
int m_fEffects;
|
|
unsigned char m_nRenderMode;
|
|
unsigned char m_nOldRenderMode;
|
|
|
|
public:
|
|
// Used to store the state we were added to the BSP as, so it can
|
|
// reinsert the entity if the state changes.
|
|
ClientRenderHandle_t m_hRender; // link into spatial partition
|
|
|
|
// Interpolation says don't draw yet
|
|
bool m_bReadyToDraw;
|
|
|
|
// Should we be interpolating?
|
|
static bool IsInterpolationEnabled();
|
|
|
|
// Should we interpolate this tick? (Used to be EF_NOINTERP)
|
|
bool IsNoInterpolationFrame();
|
|
|
|
//
|
|
int m_nNextThinkTick;
|
|
int m_nLastThinkTick;
|
|
|
|
// Object model index
|
|
short m_nModelIndex;
|
|
|
|
#ifdef TF_CLIENT_DLL
|
|
int m_nModelIndexOverrides[MAX_VISION_MODES];
|
|
#endif
|
|
|
|
char m_takedamage;
|
|
char m_lifeState;
|
|
|
|
int m_iHealth;
|
|
|
|
// was pev->speed
|
|
float m_flSpeed;
|
|
|
|
// Team Handling
|
|
int m_iTeamNum;
|
|
|
|
#if !defined(NO_ENTITY_PREDICTION)
|
|
// Certain entities (projectiles) can be created on the client
|
|
CPredictableId m_PredictableID;
|
|
PredictionContext *m_pPredictionContext;
|
|
#endif
|
|
|
|
// used so we know when things are no longer touching
|
|
int touchStamp;
|
|
|
|
// Called after predicted entity has been acknowledged so that no longer
|
|
// needed entity can
|
|
// be deleted
|
|
// Return true to force deletion right now, regardless of isbeingremoved
|
|
virtual bool OnPredictedEntityRemove(bool isbeingremoved,
|
|
C_BaseEntity *predicted);
|
|
|
|
bool IsDormantPredictable(void) const;
|
|
bool BecameDormantThisPacket(void) const;
|
|
void SetDormantPredictable(bool dormant);
|
|
|
|
int GetWaterLevel() const;
|
|
void SetWaterLevel(int nLevel);
|
|
int GetWaterType() const;
|
|
void SetWaterType(int nType);
|
|
|
|
float GetElasticity(void) const;
|
|
|
|
int GetTextureFrameIndex(void);
|
|
void SetTextureFrameIndex(int iIndex);
|
|
|
|
virtual bool GetShadowCastDistance(float *pDist,
|
|
ShadowType_t shadowType) const;
|
|
virtual bool GetShadowCastDirection(Vector *pDirection,
|
|
ShadowType_t shadowType) const;
|
|
virtual C_BaseEntity *GetShadowUseOtherEntity(void) const;
|
|
virtual void SetShadowUseOtherEntity(C_BaseEntity *pEntity);
|
|
|
|
CInterpolatedVar<QAngle> &GetRotationInterpolator();
|
|
CInterpolatedVar<Vector> &GetOriginInterpolator();
|
|
virtual bool AddRagdollToFadeQueue(void) { return true; }
|
|
|
|
// Dirty bits
|
|
void MarkRenderHandleDirty();
|
|
|
|
// used by SourceTV since move-parents may be missing when child spawns.
|
|
void HierarchyUpdateMoveParent();
|
|
|
|
virtual bool IsDeflectable() { return false; }
|
|
|
|
bool IsCombatCharacter() {
|
|
return MyCombatCharacterPointer() == NULL ? false : true;
|
|
}
|
|
|
|
protected:
|
|
int m_nFXComputeFrame;
|
|
|
|
// FIXME: Should I move the functions handling these out of C_ClientEntity
|
|
// and into C_BaseEntity? Then we could make these private.
|
|
// Client handle
|
|
CBaseHandle m_RefEHandle; // Reference ehandle. Used to generate ehandles
|
|
// off this entity.
|
|
|
|
private:
|
|
// Set by tools if this entity should route "info" to various tools
|
|
// listening to HTOOLENTITIES
|
|
#ifndef NO_TOOLFRAMEWORK
|
|
bool m_bEnabledInToolView;
|
|
bool m_bToolRecording;
|
|
HTOOLHANDLE m_ToolHandle;
|
|
int m_nLastRecordedFrame;
|
|
bool m_bRecordInTools; // should this entity be recorded in the tools (we
|
|
// exclude some things like models for menus)
|
|
#endif
|
|
|
|
protected:
|
|
// pointer to the entity's physics object (vphysics.dll)
|
|
IPhysicsObject *m_pPhysicsObject;
|
|
|
|
#if !defined(NO_ENTITY_PREDICTION)
|
|
bool m_bPredictionEligible;
|
|
#endif
|
|
|
|
int m_nSimulationTick;
|
|
|
|
// Think contexts
|
|
int GetIndexForThinkContext(const char *pszContext);
|
|
CUtlVector<thinkfunc_t> m_aThinkFunctions;
|
|
int m_iCurrentThinkContext;
|
|
|
|
// Object eye position
|
|
Vector m_vecViewOffset;
|
|
|
|
#if defined(SIXENSE)
|
|
Vector m_vecEyeOffset;
|
|
QAngle m_EyeAngleOffset;
|
|
#endif
|
|
// Allow studio models to tell us what their m_nBody value is
|
|
virtual int GetStudioBody(void) { return 0; }
|
|
|
|
public:
|
|
// This can be used to setup the entity as a client-only entity. It gets an
|
|
// entity handle, a render handle, and is put into the spatial partition.
|
|
bool InitializeAsClientEntityByIndex(int iIndex, RenderGroup_t renderGroup);
|
|
|
|
void TrackAngRotation(bool bTrack);
|
|
|
|
private:
|
|
friend void OnRenderStart();
|
|
|
|
// Figure out the smoothly interpolated origin for all server entities.
|
|
// Happens right before letting all entities simulate.
|
|
static void InterpolateServerEntities();
|
|
|
|
// Check which entities want to be drawn and add them to the leaf system.
|
|
static void AddVisibleEntities();
|
|
|
|
// For entities marked for recording, post bone messages to IToolSystems
|
|
static void ToolRecordEntities();
|
|
|
|
// Computes the base velocity
|
|
void UpdateBaseVelocity(void);
|
|
|
|
// Physics-related private methods
|
|
void PhysicsPusher(void);
|
|
void PhysicsNone(void);
|
|
void PhysicsNoclip(void);
|
|
void PhysicsParent(void);
|
|
void PhysicsStepRunTimestep(float timestep);
|
|
void PhysicsToss(void);
|
|
void PhysicsCustom(void);
|
|
|
|
// Simulation in local space of rigid children
|
|
void PhysicsRigidChild(void);
|
|
|
|
// Computes absolute position based on hierarchy
|
|
void CalcAbsolutePosition();
|
|
void CalcAbsoluteVelocity();
|
|
|
|
// Computes new angles based on the angular velocity
|
|
void SimulateAngles(float flFrameTime);
|
|
|
|
// Implement this if you use MOVETYPE_CUSTOM
|
|
virtual void PerformCustomPhysics(Vector *pNewPosition,
|
|
Vector *pNewVelocity, QAngle *pNewAngles,
|
|
QAngle *pNewAngVelocity);
|
|
|
|
// methods related to decal adding
|
|
void AddStudioDecal(const Ray_t &ray, int hitbox, int decalIndex,
|
|
bool doTrace, trace_t &tr,
|
|
int maxLODToDecal = ADDDECAL_TO_ALL_LODS);
|
|
void AddColoredStudioDecal(const Ray_t &ray, int hitbox, int decalIndex,
|
|
bool doTrace, trace_t &tr, Color cColor,
|
|
int maxLODToDecal);
|
|
void AddBrushModelDecal(const Ray_t &ray, const Vector &decalCenter,
|
|
int decalIndex, bool doTrace, trace_t &tr);
|
|
|
|
void ComputePackedOffsets(void);
|
|
int ComputePackedSize_R(datamap_t *map);
|
|
int GetIntermediateDataSize(void);
|
|
|
|
void UnlinkChild(C_BaseEntity *pParent, C_BaseEntity *pChild);
|
|
void LinkChild(C_BaseEntity *pParent, C_BaseEntity *pChild);
|
|
void HierarchySetParent(C_BaseEntity *pNewParent);
|
|
void UnlinkFromHierarchy();
|
|
|
|
// Computes the water level + type
|
|
void UpdateWaterState();
|
|
|
|
// Checks a sweep without actually performing the move
|
|
void PhysicsCheckSweep(const Vector &vecAbsStart, const Vector &vecAbsDelta,
|
|
trace_t *pTrace);
|
|
|
|
// FIXME: REMOVE!!!
|
|
void MoveToAimEnt();
|
|
|
|
// Sets/Gets the next think based on context index
|
|
void SetNextThink(int nContextIndex, float thinkTime);
|
|
void SetLastThink(int nContextIndex, float thinkTime);
|
|
float GetNextThink(int nContextIndex) const;
|
|
int GetNextThinkTick(int nContextIndex) const;
|
|
|
|
// Object velocity
|
|
Vector m_vecVelocity;
|
|
CInterpolatedVar<Vector> m_iv_vecVelocity;
|
|
|
|
Vector m_vecAbsVelocity;
|
|
|
|
// was pev->avelocity
|
|
QAngle m_vecAngVelocity;
|
|
|
|
// QAngle m_vecAbsAngVelocity;
|
|
|
|
#if !defined(NO_ENTITY_PREDICTION)
|
|
// It's still in the list for "fixup purposes" and simulation, but don't try
|
|
// to render it any more...
|
|
bool m_bDormantPredictable;
|
|
|
|
// So we can clean it up
|
|
int m_nIncomingPacketEntityBecameDormant;
|
|
#endif
|
|
|
|
// The spawn time of the entity
|
|
float m_flSpawnTime;
|
|
|
|
// Timestamp of message arrival
|
|
float m_flLastMessageTime;
|
|
|
|
// Base velocity
|
|
Vector m_vecBaseVelocity;
|
|
|
|
// Gravity multiplier
|
|
float m_flGravity;
|
|
|
|
// Model instance data..
|
|
ModelInstanceHandle_t m_ModelInstance;
|
|
|
|
// Shadow data
|
|
ClientShadowHandle_t m_ShadowHandle;
|
|
|
|
// A random value used by material proxies for each model instance.
|
|
float m_flProxyRandomValue;
|
|
|
|
ClientThinkHandle_t m_hThink;
|
|
|
|
int m_iEFlags; // entity flags EFL_*
|
|
|
|
// Object movetype
|
|
unsigned char m_MoveType;
|
|
unsigned char m_MoveCollide;
|
|
unsigned char m_iParentAttachment; // 0 if we're relative to the parent's
|
|
// absorigin and absangles.
|
|
unsigned char m_iOldParentAttachment;
|
|
|
|
unsigned char m_nWaterLevel;
|
|
unsigned char m_nWaterType;
|
|
// For client/server entities, true if the entity goes outside the PVS.
|
|
// Unused for client only entities.
|
|
bool m_bDormant;
|
|
// Prediction system
|
|
bool m_bPredictable;
|
|
|
|
// Hierarchy
|
|
CHandle<C_BaseEntity> m_pMoveParent;
|
|
CHandle<C_BaseEntity> m_pMoveChild;
|
|
CHandle<C_BaseEntity> m_pMovePeer;
|
|
CHandle<C_BaseEntity> m_pMovePrevPeer;
|
|
|
|
// The moveparent received from networking data
|
|
CHandle<C_BaseEntity> m_hNetworkMoveParent;
|
|
CHandle<C_BaseEntity> m_hOldMoveParent;
|
|
|
|
string_t m_ModelName;
|
|
|
|
CNetworkVarEmbedded(CCollisionProperty, m_Collision);
|
|
CNetworkVarEmbedded(CParticleProperty, m_Particles);
|
|
|
|
// Physics state
|
|
float m_flElasticity;
|
|
|
|
float m_flShadowCastDistance;
|
|
EHANDLE m_ShadowDirUseOtherEntity;
|
|
|
|
EHANDLE m_hGroundEntity;
|
|
float m_flGroundChangeTime;
|
|
|
|
// Friction.
|
|
float m_flFriction;
|
|
|
|
Vector m_vecAbsOrigin;
|
|
|
|
// Object orientation
|
|
QAngle m_angAbsRotation;
|
|
|
|
Vector m_vecOldOrigin;
|
|
QAngle m_vecOldAngRotation;
|
|
|
|
Vector m_vecOrigin;
|
|
CInterpolatedVar<Vector> m_iv_vecOrigin;
|
|
QAngle m_angRotation;
|
|
CInterpolatedVar<QAngle> m_iv_angRotation;
|
|
|
|
// Specifies the entity-to-world transform
|
|
matrix3x4_t m_rgflCoordinateFrame;
|
|
|
|
// Last values to come over the wire. Used for interpolation.
|
|
Vector m_vecNetworkOrigin;
|
|
QAngle m_angNetworkAngles;
|
|
|
|
// Behavior flags
|
|
int m_fFlags;
|
|
|
|
// used to cull collision tests
|
|
int m_CollisionGroup;
|
|
|
|
#if !defined(NO_ENTITY_PREDICTION)
|
|
// For storing prediction results and pristine network state
|
|
byte *m_pIntermediateData[MULTIPLAYER_BACKUP];
|
|
byte *m_pOriginalData;
|
|
int m_nIntermediateDataCount;
|
|
|
|
bool m_bIsPlayerSimulated;
|
|
#endif
|
|
|
|
CNetworkVar(bool, m_bSimulatedEveryTick);
|
|
CNetworkVar(bool, m_bAnimatedEveryTick);
|
|
CNetworkVar(bool, m_bAlternateSorting);
|
|
|
|
// Adrian
|
|
unsigned char m_iTextureFrameIndex;
|
|
|
|
// Bbox visualization
|
|
unsigned char m_fBBoxVisFlags;
|
|
|
|
// The list that holds OnDataChanged events uses this to make sure we don't
|
|
// get multiple OnDataChanged calls in the same frame if the client receives
|
|
// multiple packets.
|
|
int m_DataChangeEventRef;
|
|
|
|
#if !defined(NO_ENTITY_PREDICTION)
|
|
// Player who is driving my simulation
|
|
CHandle<CBasePlayer> m_hPlayerSimulationOwner;
|
|
#endif
|
|
|
|
// The owner!
|
|
EHANDLE m_hOwnerEntity;
|
|
EHANDLE m_hEffectEntity;
|
|
|
|
// This is a random seed used by the networking code to allow client - side
|
|
// prediction code
|
|
// randon number generators to spit out the same random numbers on both
|
|
// sides for a particular usercmd input.
|
|
static int m_nPredictionRandomSeed;
|
|
static C_BasePlayer *m_pPredictionPlayer;
|
|
static bool s_bAbsQueriesValid;
|
|
static bool s_bAbsRecomputationEnabled;
|
|
|
|
static bool s_bInterpolate;
|
|
|
|
int m_fDataObjectTypes;
|
|
|
|
AimEntsListHandle_t m_AimEntsListHandle;
|
|
int m_nCreationTick;
|
|
|
|
public:
|
|
float m_fRenderingClipPlane[4]; // world space clip plane when drawing
|
|
bool m_bEnableRenderingClipPlane; // true to use the custom clip plane when
|
|
// drawing
|
|
float *GetRenderClipPlane(
|
|
void); // Rendering clip plane, should be 4 floats, return value of
|
|
// NULL indicates a disabled render clip plane
|
|
|
|
protected:
|
|
void AddToInterpolationList();
|
|
void RemoveFromInterpolationList();
|
|
unsigned short
|
|
m_InterpolationListEntry; // Entry into g_InterpolationList (or
|
|
// g_InterpolationList.InvalidIndex if not in
|
|
// the list).
|
|
|
|
void AddToTeleportList();
|
|
void RemoveFromTeleportList();
|
|
unsigned short m_TeleportListEntry;
|
|
|
|
CThreadFastMutex m_CalcAbsolutePositionMutex;
|
|
CThreadFastMutex m_CalcAbsoluteVelocityMutex;
|
|
|
|
#ifdef TF_CLIENT_DLL
|
|
// TF prevents drawing of any entity attached to players that aren't items
|
|
// in the inventory of the player. This is to prevent servers creating fake
|
|
// cosmetic items and attaching them to players.
|
|
public:
|
|
virtual bool ValidateEntityAttachedToPlayer(bool &bShouldRetry);
|
|
bool EntityDeemedInvalid(void) {
|
|
return (m_bValidatedOwner && m_bDeemedInvalid);
|
|
}
|
|
|
|
protected:
|
|
bool m_bValidatedOwner;
|
|
bool m_bDeemedInvalid;
|
|
bool m_bWasDeemedInvalid;
|
|
RenderMode_t m_PreviousRenderMode;
|
|
color32 m_PreviousRenderColor;
|
|
#endif
|
|
};
|
|
|
|
EXTERN_RECV_TABLE(DT_BaseEntity);
|
|
|
|
inline bool FClassnameIs(C_BaseEntity *pEntity, const char *szClassname) {
|
|
Assert(pEntity);
|
|
if (pEntity == NULL) return false;
|
|
|
|
return !strcmp(pEntity->GetClassname(), szClassname) ? true : false;
|
|
}
|
|
|
|
#define SetThink(a) \
|
|
ThinkSet(static_cast<void (CBaseEntity::*)(void)>(a), 0, NULL)
|
|
#define SetContextThink(a, b, context) \
|
|
ThinkSet(static_cast<void (CBaseEntity::*)(void)>(a), (b), context)
|
|
|
|
#ifdef _DEBUG
|
|
#define SetTouch(a) \
|
|
TouchSet(static_cast<void (C_BaseEntity::*)(C_BaseEntity *)>(a), #a)
|
|
|
|
#else
|
|
#define SetTouch(a) \
|
|
m_pfnTouch = static_cast<void (C_BaseEntity::*)(C_BaseEntity *)>(a)
|
|
|
|
#endif
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// An inline version the game code can use
|
|
//-----------------------------------------------------------------------------
|
|
inline CCollisionProperty *C_BaseEntity::CollisionProp() {
|
|
return &m_Collision;
|
|
}
|
|
|
|
inline const CCollisionProperty *C_BaseEntity::CollisionProp() const {
|
|
return &m_Collision;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// An inline version the game code can use
|
|
//-----------------------------------------------------------------------------
|
|
inline CParticleProperty *C_BaseEntity::ParticleProp() { return &m_Particles; }
|
|
|
|
inline const CParticleProperty *C_BaseEntity::ParticleProp() const {
|
|
return &m_Particles;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Returns whether this entity was created on the client.
|
|
//-----------------------------------------------------------------------------
|
|
inline bool C_BaseEntity::IsServerEntity(void) { return index != -1; }
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Inline methods
|
|
//-----------------------------------------------------------------------------
|
|
inline matrix3x4_t &C_BaseEntity::EntityToWorldTransform() {
|
|
Assert(s_bAbsQueriesValid);
|
|
CalcAbsolutePosition();
|
|
return m_rgflCoordinateFrame;
|
|
}
|
|
|
|
inline const matrix3x4_t &C_BaseEntity::EntityToWorldTransform() const {
|
|
Assert(s_bAbsQueriesValid);
|
|
const_cast<C_BaseEntity *>(this)->CalcAbsolutePosition();
|
|
return m_rgflCoordinateFrame;
|
|
}
|
|
|
|
inline const Vector &C_BaseEntity::GetNetworkOrigin() const {
|
|
return m_vecNetworkOrigin;
|
|
}
|
|
|
|
inline const QAngle &C_BaseEntity::GetNetworkAngles() const {
|
|
return m_angNetworkAngles;
|
|
}
|
|
|
|
inline const model_t *C_BaseEntity::GetModel(void) const { return model; }
|
|
|
|
inline int C_BaseEntity::GetModelIndex(void) const { return m_nModelIndex; }
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Some helper methods that transform a point from entity space to world space +
|
|
// back
|
|
//-----------------------------------------------------------------------------
|
|
inline void C_BaseEntity::EntityToWorldSpace(const Vector &in,
|
|
Vector *pOut) const {
|
|
if (GetAbsAngles() == vec3_angle) {
|
|
VectorAdd(in, GetAbsOrigin(), *pOut);
|
|
} else {
|
|
VectorTransform(in, EntityToWorldTransform(), *pOut);
|
|
}
|
|
}
|
|
|
|
inline void C_BaseEntity::WorldToEntitySpace(const Vector &in,
|
|
Vector *pOut) const {
|
|
if (GetAbsAngles() == vec3_angle) {
|
|
VectorSubtract(in, GetAbsOrigin(), *pOut);
|
|
} else {
|
|
VectorITransform(in, EntityToWorldTransform(), *pOut);
|
|
}
|
|
}
|
|
|
|
inline const Vector &C_BaseEntity::GetAbsVelocity() const {
|
|
Assert(s_bAbsQueriesValid);
|
|
const_cast<C_BaseEntity *>(this)->CalcAbsoluteVelocity();
|
|
return m_vecAbsVelocity;
|
|
}
|
|
|
|
inline C_BaseEntity *C_BaseEntity::Instance(IClientEntity *ent) {
|
|
return ent ? ent->GetBaseEntity() : NULL;
|
|
}
|
|
|
|
// For debugging shared code
|
|
inline bool C_BaseEntity::IsServer(void) { return false; }
|
|
|
|
inline bool C_BaseEntity::IsClient(void) { return true; }
|
|
|
|
inline const char *C_BaseEntity::GetDLLType(void) { return "client"; }
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Methods relating to solid type + flags
|
|
//-----------------------------------------------------------------------------
|
|
inline void C_BaseEntity::SetSolidFlags(int nFlags) {
|
|
CollisionProp()->SetSolidFlags(nFlags);
|
|
}
|
|
|
|
inline bool C_BaseEntity::IsSolidFlagSet(int flagMask) const {
|
|
return CollisionProp()->IsSolidFlagSet(flagMask);
|
|
}
|
|
|
|
inline int C_BaseEntity::GetSolidFlags(void) const {
|
|
return CollisionProp()->GetSolidFlags();
|
|
}
|
|
|
|
inline void C_BaseEntity::AddSolidFlags(int nFlags) {
|
|
CollisionProp()->AddSolidFlags(nFlags);
|
|
}
|
|
|
|
inline void C_BaseEntity::RemoveSolidFlags(int nFlags) {
|
|
CollisionProp()->RemoveSolidFlags(nFlags);
|
|
}
|
|
|
|
inline bool C_BaseEntity::IsSolid() const { return CollisionProp()->IsSolid(); }
|
|
|
|
inline void C_BaseEntity::SetSolid(SolidType_t val) {
|
|
CollisionProp()->SetSolid(val);
|
|
}
|
|
|
|
inline SolidType_t C_BaseEntity::GetSolid() const {
|
|
return CollisionProp()->GetSolid();
|
|
}
|
|
|
|
inline void C_BaseEntity::SetCollisionBounds(const Vector &mins,
|
|
const Vector &maxs) {
|
|
CollisionProp()->SetCollisionBounds(mins, maxs);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Methods relating to bounds
|
|
//-----------------------------------------------------------------------------
|
|
inline const Vector &C_BaseEntity::WorldAlignMins() const {
|
|
Assert(!CollisionProp()->IsBoundsDefinedInEntitySpace());
|
|
Assert(CollisionProp()->GetCollisionAngles() == vec3_angle);
|
|
return CollisionProp()->OBBMins();
|
|
}
|
|
|
|
inline const Vector &C_BaseEntity::WorldAlignMaxs() const {
|
|
Assert(!CollisionProp()->IsBoundsDefinedInEntitySpace());
|
|
Assert(CollisionProp()->GetCollisionAngles() == vec3_angle);
|
|
return CollisionProp()->OBBMaxs();
|
|
}
|
|
|
|
inline const Vector &C_BaseEntity::WorldAlignSize() const {
|
|
Assert(!CollisionProp()->IsBoundsDefinedInEntitySpace());
|
|
Assert(CollisionProp()->GetCollisionAngles() == vec3_angle);
|
|
return CollisionProp()->OBBSize();
|
|
}
|
|
|
|
inline float CBaseEntity::BoundingRadius() const {
|
|
return CollisionProp()->BoundingRadius();
|
|
}
|
|
|
|
inline bool CBaseEntity::IsPointSized() const {
|
|
return CollisionProp()->BoundingRadius() == 0.0f;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Methods relating to traversing hierarchy
|
|
//-----------------------------------------------------------------------------
|
|
inline C_BaseEntity *C_BaseEntity::GetMoveParent(void) const {
|
|
return m_pMoveParent;
|
|
}
|
|
|
|
inline C_BaseEntity *C_BaseEntity::FirstMoveChild(void) const {
|
|
return m_pMoveChild;
|
|
}
|
|
|
|
inline C_BaseEntity *C_BaseEntity::NextMovePeer(void) const {
|
|
return m_pMovePeer;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Velocity
|
|
//-----------------------------------------------------------------------------
|
|
inline const Vector &C_BaseEntity::GetLocalVelocity() const {
|
|
return m_vecVelocity;
|
|
}
|
|
|
|
inline const QAngle &C_BaseEntity::GetLocalAngularVelocity() const {
|
|
return m_vecAngVelocity;
|
|
}
|
|
|
|
inline const Vector &C_BaseEntity::GetBaseVelocity() const {
|
|
return m_vecBaseVelocity;
|
|
}
|
|
|
|
inline void C_BaseEntity::SetBaseVelocity(const Vector &v) {
|
|
m_vecBaseVelocity = v;
|
|
}
|
|
|
|
inline void C_BaseEntity::SetFriction(float flFriction) {
|
|
m_flFriction = flFriction;
|
|
}
|
|
|
|
inline void C_BaseEntity::SetGravity(float flGravity) {
|
|
m_flGravity = flGravity;
|
|
}
|
|
|
|
inline float C_BaseEntity::GetGravity(void) const { return m_flGravity; }
|
|
|
|
inline int C_BaseEntity::GetWaterLevel() const { return m_nWaterLevel; }
|
|
|
|
inline void C_BaseEntity::SetWaterLevel(int nLevel) { m_nWaterLevel = nLevel; }
|
|
|
|
inline float C_BaseEntity::GetElasticity(void) const { return m_flElasticity; }
|
|
|
|
inline const color32 CBaseEntity::GetRenderColor() const {
|
|
return m_clrRender.Get();
|
|
}
|
|
|
|
inline void C_BaseEntity::SetRenderColor(byte r, byte g, byte b) {
|
|
color32 clr = {r, g, b, m_clrRender->a};
|
|
m_clrRender = clr;
|
|
}
|
|
|
|
inline void C_BaseEntity::SetRenderColor(byte r, byte g, byte b, byte a) {
|
|
color32 clr = {r, g, b, a};
|
|
m_clrRender = clr;
|
|
}
|
|
|
|
inline void C_BaseEntity::SetRenderColorR(byte r) {
|
|
SetRenderColor(r, GetRenderColor().g, GetRenderColor().b);
|
|
}
|
|
|
|
inline void C_BaseEntity::SetRenderColorG(byte g) {
|
|
SetRenderColor(GetRenderColor().r, g, GetRenderColor().b);
|
|
}
|
|
|
|
inline void C_BaseEntity::SetRenderColorB(byte b) {
|
|
SetRenderColor(GetRenderColor().r, GetRenderColor().g, b);
|
|
}
|
|
|
|
inline void C_BaseEntity::SetRenderColorA(byte a) {
|
|
SetRenderColor(GetRenderColor().r, GetRenderColor().g, GetRenderColor().b,
|
|
a);
|
|
}
|
|
|
|
inline RenderMode_t CBaseEntity::GetRenderMode() const {
|
|
return (RenderMode_t)m_nRenderMode;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// checks to see if the entity is marked for deletion
|
|
//-----------------------------------------------------------------------------
|
|
inline bool C_BaseEntity::IsMarkedForDeletion(void) {
|
|
return (m_iEFlags & EFL_KILLME);
|
|
}
|
|
|
|
inline void C_BaseEntity::AddEFlags(int nEFlagMask) { m_iEFlags |= nEFlagMask; }
|
|
|
|
inline void C_BaseEntity::RemoveEFlags(int nEFlagMask) {
|
|
m_iEFlags &= ~nEFlagMask;
|
|
}
|
|
|
|
inline bool CBaseEntity::IsEFlagSet(int nEFlagMask) const {
|
|
return (m_iEFlags & nEFlagMask) != 0;
|
|
}
|
|
|
|
inline unsigned char CBaseEntity::GetParentAttachment() const {
|
|
return m_iParentAttachment;
|
|
}
|
|
|
|
inline ClientRenderHandle_t CBaseEntity::GetRenderHandle() const {
|
|
return m_hRender;
|
|
}
|
|
|
|
inline ClientRenderHandle_t &CBaseEntity::RenderHandle() { return m_hRender; }
|
|
|
|
#ifdef SIXENSE
|
|
|
|
inline const Vector &CBaseEntity::GetEyeOffset() const {
|
|
return m_vecEyeOffset;
|
|
}
|
|
|
|
inline void CBaseEntity::SetEyeOffset(const Vector &v) { m_vecEyeOffset = v; }
|
|
|
|
inline const QAngle &CBaseEntity::GetEyeAngleOffset() const {
|
|
return m_EyeAngleOffset;
|
|
}
|
|
|
|
inline void CBaseEntity::SetEyeAngleOffset(const QAngle &qa) {
|
|
m_EyeAngleOffset = qa;
|
|
}
|
|
|
|
#endif
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Methods to cast away const
|
|
//-----------------------------------------------------------------------------
|
|
inline Vector C_BaseEntity::EyePosition(void) const {
|
|
return const_cast<C_BaseEntity *>(this)->EyePosition();
|
|
}
|
|
|
|
inline const QAngle &C_BaseEntity::EyeAngles(
|
|
void) const // Direction of eyes in world space
|
|
{
|
|
return const_cast<C_BaseEntity *>(this)->EyeAngles();
|
|
}
|
|
|
|
inline const QAngle &C_BaseEntity::LocalEyeAngles(
|
|
void) const // Direction of eyes
|
|
{
|
|
return const_cast<C_BaseEntity *>(this)->LocalEyeAngles();
|
|
}
|
|
|
|
inline Vector C_BaseEntity::EarPosition(void) const // position of ears
|
|
{
|
|
return const_cast<C_BaseEntity *>(this)->EarPosition();
|
|
}
|
|
|
|
inline VarMapping_t *C_BaseEntity::GetVarMapping() { return &m_VarMap; }
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Should we be interpolating?
|
|
//-----------------------------------------------------------------------------
|
|
inline bool C_BaseEntity::IsInterpolationEnabled() { return s_bInterpolate; }
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Should we be interpolating during this frame? (was EF_NOINTERP)
|
|
//-----------------------------------------------------------------------------
|
|
inline bool C_BaseEntity::IsNoInterpolationFrame() {
|
|
return m_ubOldInterpolationFrame != m_ubInterpolationFrame;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
// Input : handle -
|
|
// Output : inline void
|
|
//-----------------------------------------------------------------------------
|
|
inline void C_BaseEntity::SetToolHandle(HTOOLHANDLE handle) {
|
|
#ifndef NO_TOOLFRAMEWORK
|
|
m_ToolHandle = handle;
|
|
#endif
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
// Input : -
|
|
// Output : inline HTOOLHANDLE
|
|
//-----------------------------------------------------------------------------
|
|
inline HTOOLHANDLE C_BaseEntity::GetToolHandle() const {
|
|
#ifndef NO_TOOLFRAMEWORK
|
|
return m_ToolHandle;
|
|
#else
|
|
return (HTOOLHANDLE)0;
|
|
#endif
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
inline bool C_BaseEntity::IsEnabledInToolView() const {
|
|
#ifndef NO_TOOLFRAMEWORK
|
|
return m_bEnabledInToolView;
|
|
#else
|
|
return false;
|
|
#endif
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose:
|
|
// Input : -
|
|
// Output : inline bool
|
|
//-----------------------------------------------------------------------------
|
|
inline bool C_BaseEntity::ShouldRecordInTools() const {
|
|
#ifndef NO_TOOLFRAMEWORK
|
|
return m_bRecordInTools;
|
|
#else
|
|
return true;
|
|
#endif
|
|
}
|
|
|
|
C_BaseEntity *CreateEntityByName(const char *className);
|
|
|
|
#endif // C_BASEENTITY_H
|