CBaseEntity/definitions: Difference between revisions
Jump to navigation
Jump to search
(Created page with "=== Shared === ==== [https://github.com/ValveSoftware/source-sdk-2013/blob/master/mp/src/game/shared/baseentity_shared.h baseentity_shared.h] ==== <syntaxhighlight lang=cpp> <...") |
No edit summary |
||
(6 intermediate revisions by 3 users not shown) | |||
Line 1: | Line 1: | ||
<noinclude>[[Category:Definitions]]</noinclude> | |||
=== Shared === | === Shared === | ||
==== [https://github.com/ValveSoftware/source-sdk-2013/blob/master/mp/src/game/shared/baseentity_shared.h baseentity_shared.h] ==== | ==== [https://github.com/ValveSoftware/source-sdk-2013/blob/master/mp/src/game/shared/baseentity_shared.h baseentity_shared.h] ==== | ||
Line 11: | Line 12: | ||
==== [https://github.com/ValveSoftware/source-sdk-2013/blob/master/mp/src/game/server/baseentity.h baseentity.h] ==== | ==== [https://github.com/ValveSoftware/source-sdk-2013/blob/master/mp/src/game/server/baseentity.h baseentity.h] ==== | ||
<syntaxhighlight lang=cpp> | :{{expand|<syntaxhighlight lang=cpp> | ||
</syntaxhighlight> | //----------------------------------------------------------------------------- | ||
// Purpose: think contexts | |||
//----------------------------------------------------------------------------- | |||
struct thinkfunc_t | |||
{ | |||
BASEPTR m_pfnThink; | |||
string_t m_iszContext; | |||
int m_nNextThinkTick; | |||
int m_nLastThinkTick; | |||
DECLARE_SIMPLE_DATADESC(); | |||
}; | |||
// | |||
// Base Entity. All entity types derive from this | |||
// | |||
class CBaseEntity : public IServerEntity | |||
{ | |||
public: | |||
DECLARE_CLASS_NOBASE( CBaseEntity ); | |||
//---------------------------------------- | |||
// Class vars and functions | |||
//---------------------------------------- | |||
static inline void Debug_Pause(bool bPause); | |||
static inline bool Debug_IsPaused(void); | |||
static inline void Debug_SetSteps(int nSteps); | |||
static inline bool Debug_ShouldStep(void); | |||
static inline bool Debug_Step(void); | |||
static bool m_bInDebugSelect; | |||
static int m_nDebugPlayer; | |||
protected: | |||
static bool m_bDebugPause; // Whether entity i/o is paused for debugging. | |||
static int m_nDebugSteps; // Number of entity outputs to fire before pausing again. | |||
static bool sm_bDisableTouchFuncs; // Disables PhysicsTouch and PhysicsStartTouch function calls | |||
public: | |||
static bool sm_bAccurateTriggerBboxChecks; // SOLID_BBOX entities do a fully accurate trigger vs bbox check when this is set | |||
public: | |||
// If bServerOnly is true, then the ent never goes to the client. This is used | |||
// by logical entities. | |||
CBaseEntity( bool bServerOnly=false ); | |||
virtual ~CBaseEntity(); | |||
// prediction system | |||
DECLARE_PREDICTABLE(); | |||
// network data | |||
DECLARE_SERVERCLASS(); | |||
// data description | |||
DECLARE_DATADESC(); | |||
// memory handling | |||
void *operator new( size_t stAllocateBlock ); | |||
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); } | |||
// Class factory | |||
static CBaseEntity *CreatePredictedEntityByName( const char *classname, const char *module, int line, bool persist = false ); | |||
// IHandleEntity overrides. | |||
public: | |||
virtual void SetRefEHandle( const CBaseHandle &handle ); | |||
virtual const CBaseHandle& GetRefEHandle() const; | |||
// IServerUnknown overrides | |||
virtual ICollideable *GetCollideable(); | |||
virtual IServerNetworkable *GetNetworkable(); | |||
virtual CBaseEntity *GetBaseEntity(); | |||
// IServerEntity overrides. | |||
public: | |||
virtual void SetModelIndex( int index ); | |||
virtual int GetModelIndex( void ) const; | |||
virtual string_t GetModelName( void ) const; | |||
void ClearModelIndexOverrides( void ); | |||
virtual void SetModelIndexOverride( int index, int nValue ); | |||
public: | |||
// virtual methods for derived classes to override | |||
virtual bool TestCollision( const Ray_t& ray, unsigned int mask, trace_t& trace ); | |||
virtual bool TestHitboxes( const Ray_t &ray, unsigned int fContentsMask, trace_t& tr ); | |||
virtual void ComputeWorldSpaceSurroundingBox( Vector *pWorldMins, Vector *pWorldMaxs ); | |||
// non-virtual methods. Don't override these! | |||
public: | |||
// An inline version the game code can use | |||
CCollisionProperty *CollisionProp(); | |||
const CCollisionProperty*CollisionProp() const; | |||
CServerNetworkProperty *NetworkProp(); | |||
const CServerNetworkProperty *NetworkProp() const; | |||
bool IsCurrentlyTouching( void ) const; | |||
const Vector& GetAbsOrigin( void ) const; | |||
const QAngle& GetAbsAngles( void ) const; | |||
SolidType_t GetSolid() const; | |||
int GetSolidFlags( void ) const; | |||
int GetEFlags() const; | |||
void SetEFlags( int iEFlags ); | |||
void AddEFlags( int nEFlagMask ); | |||
void RemoveEFlags( int nEFlagMask ); | |||
bool IsEFlagSet( int nEFlagMask ) const; | |||
// Quick way to ask if we have a player entity as a child anywhere in our hierarchy. | |||
void RecalcHasPlayerChildBit(); | |||
bool DoesHavePlayerChild(); | |||
bool IsTransparent() const; | |||
void SetNavIgnore( float duration = FLT_MAX ); | |||
void ClearNavIgnore(); | |||
bool IsNavIgnored() const; | |||
// Is the entity floating? | |||
bool IsFloating(); | |||
// Called by physics to see if we should avoid a collision test.... | |||
virtual bool ShouldCollide( int collisionGroup, int contentsMask ) const; | |||
// Move type / move collide | |||
MoveType_t GetMoveType() const; | |||
MoveCollide_t GetMoveCollide() const; | |||
void SetMoveType( MoveType_t val, MoveCollide_t moveCollide = MOVECOLLIDE_DEFAULT ); | |||
void SetMoveCollide( MoveCollide_t val ); | |||
// 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 ); | |||
// 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 ); | |||
public: | |||
void SetScaledPhysics( IPhysicsObject *pNewObject ); | |||
// virtual methods; you can override these | |||
public: | |||
// Owner entity. | |||
// FIXME: These are virtual only because of CNodeEnt | |||
CBaseEntity *GetOwnerEntity() const; | |||
virtual void SetOwnerEntity( CBaseEntity* pOwner ); | |||
void SetEffectEntity( CBaseEntity *pEffectEnt ); | |||
CBaseEntity *GetEffectEntity() const; | |||
// Only CBaseEntity implements these. CheckTransmit calls the virtual ShouldTransmit to see if the | |||
// entity wants to be sent. If so, it calls SetTransmit, which will mark any dependents for transmission too. | |||
virtual int ShouldTransmit( const CCheckTransmitInfo *pInfo ); | |||
// update the global transmit state if a transmission rule changed | |||
int SetTransmitState( int nFlag); | |||
int GetTransmitState( void ); | |||
int DispatchUpdateTransmitState(); | |||
// Do NOT call this directly. Use DispatchUpdateTransmitState. | |||
virtual int UpdateTransmitState(); | |||
// Entities (like ropes) use this to own the transmit state of another entity | |||
// by forcing it to not call UpdateTransmitState. | |||
void IncrementTransmitStateOwnedCounter(); | |||
void DecrementTransmitStateOwnedCounter(); | |||
// This marks the entity for transmission and passes the SetTransmit call to any dependents. | |||
virtual void SetTransmit( CCheckTransmitInfo *pInfo, bool bAlways ); | |||
// This function finds out if the entity is in the 3D skybox. If so, it sets the EFL_IN_SKYBOX | |||
// flag so the entity gets transmitted to all the clients. | |||
// Entities usually call this during their Activate(). | |||
// Returns true if the entity is in the skybox (and EFL_IN_SKYBOX was set). | |||
bool DetectInSkybox(); | |||
// Returns which skybox the entity is in | |||
CSkyCamera *GetEntitySkybox(); | |||
bool IsSimulatedEveryTick() const; | |||
bool IsAnimatedEveryTick() const; | |||
void SetSimulatedEveryTick( bool sim ); | |||
void SetAnimatedEveryTick( bool anim ); | |||
public: | |||
virtual const char *GetTracerType( void ); | |||
// returns a pointer to the entities edict, if it has one. should be removed! | |||
inline edict_t *edict( void ) { return NetworkProp()->edict(); } | |||
inline const edict_t *edict( void ) const { return NetworkProp()->edict(); } | |||
inline int entindex( ) const { return m_Network.entindex(); }; | |||
inline int GetSoundSourceIndex() const { return entindex(); } | |||
// 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(); | |||
// initialization | |||
virtual void Spawn( void ); | |||
virtual void Precache( void ) {} | |||
virtual void SetModel( const char *szModelName ); | |||
protected: | |||
// Notification on model load. May be called multiple times for dynamic models. | |||
// Implementations must call BaseClass::OnNewModel and pass return value through. | |||
virtual CStudioHdr *OnNewModel(); | |||
public: | |||
virtual void PostConstructor( const char *szClassname ); | |||
virtual void PostClientActive( void ); | |||
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 ); | |||
void ValidateEntityConnections(); | |||
void FireNamedOutput( const char *pszOutput, variant_t variant, CBaseEntity *pActivator, CBaseEntity *pCaller, float flDelay = 0.0f ); | |||
// Activate - called for each entity after each load game and level load | |||
virtual void Activate( void ); | |||
// Hierarchy traversal | |||
CBaseEntity *GetMoveParent( void ); | |||
CBaseEntity *GetRootMoveParent(); | |||
CBaseEntity *FirstMoveChild( void ); | |||
CBaseEntity *NextMovePeer( void ); | |||
void SetName( string_t newTarget ); | |||
void SetParent( string_t newParent, CBaseEntity *pActivator, int iAttachment = -1 ); | |||
// 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. If iAttachment == -1, it'll preserve the | |||
// current m_iParentAttachment. | |||
virtual void SetParent( CBaseEntity* pNewParent, int iAttachment = -1 ); | |||
CBaseEntity* GetParent(); | |||
int GetParentAttachment(); | |||
string_t GetEntityName(); | |||
bool NameMatches( const char *pszNameOrWildcard ); | |||
bool ClassMatches( const char *pszClassOrWildcard ); | |||
bool NameMatches( string_t nameStr ); | |||
bool ClassMatches( string_t nameStr ); | |||
private: | |||
bool NameMatchesComplex( const char *pszNameOrWildcard ); | |||
bool ClassMatchesComplex( const char *pszClassOrWildcard ); | |||
void TransformStepData_WorldToParent( CBaseEntity *pParent ); | |||
void TransformStepData_ParentToParent( CBaseEntity *pOldParent, CBaseEntity *pNewParent ); | |||
void TransformStepData_ParentToWorld( CBaseEntity *pParent ); | |||
public: | |||
int GetSpawnFlags( void ) const; | |||
void AddSpawnFlags( int nFlags ); | |||
void RemoveSpawnFlags( int nFlags ); | |||
void ClearSpawnFlags( void ); | |||
bool HasSpawnFlags( int nFlags ) const; | |||
int GetEffects( void ) const; | |||
void AddEffects( int nEffects ); | |||
void RemoveEffects( int nEffects ); | |||
void ClearEffects( void ); | |||
void SetEffects( int nEffects ); | |||
bool IsEffectActive( int nEffects ) const; | |||
// makes the entity inactive | |||
void MakeDormant( void ); | |||
int IsDormant( void ); | |||
void RemoveDeferred( void ); // Sets the entity invisible, and makes it remove itself on the next frame | |||
// checks to see if the entity is marked for deletion | |||
bool IsMarkedForDeletion( void ); | |||
// capabilities | |||
virtual int ObjectCaps( void ); | |||
// Verifies that the data description is valid in debug builds. | |||
#ifdef _DEBUG | |||
void ValidateDataDescription(void); | |||
#endif // _DEBUG | |||
// handles an input (usually caused by outputs) | |||
// returns true if the the value in the pass in should be set, false if the input is to be ignored | |||
virtual bool AcceptInput( const char *szInputName, CBaseEntity *pActivator, CBaseEntity *pCaller, variant_t Value, int outputID ); | |||
// | |||
// Input handlers. | |||
// | |||
void InputAlternativeSorting( inputdata_t &inputdata ); | |||
void InputAlpha( inputdata_t &inputdata ); | |||
void InputColor( inputdata_t &inputdata ); | |||
void InputSetParent( inputdata_t &inputdata ); | |||
void SetParentAttachment( const char *szInputName, const char *szAttachment, bool bMaintainOffset ); | |||
void InputSetParentAttachment( inputdata_t &inputdata ); | |||
void InputSetParentAttachmentMaintainOffset( inputdata_t &inputdata ); | |||
void InputClearParent( inputdata_t &inputdata ); | |||
void InputSetTeam( inputdata_t &inputdata ); | |||
void InputUse( inputdata_t &inputdata ); | |||
void InputKill( inputdata_t &inputdata ); | |||
void InputKillHierarchy( inputdata_t &inputdata ); | |||
void InputSetDamageFilter( inputdata_t &inputdata ); | |||
void InputDispatchEffect( inputdata_t &inputdata ); | |||
void InputEnableDamageForces( inputdata_t &inputdata ); | |||
void InputDisableDamageForces( inputdata_t &inputdata ); | |||
void InputAddContext( inputdata_t &inputdata ); | |||
void InputRemoveContext( inputdata_t &inputdata ); | |||
void InputClearContext( inputdata_t &inputdata ); | |||
void InputDispatchResponse( inputdata_t& inputdata ); | |||
void InputDisableShadow( inputdata_t &inputdata ); | |||
void InputEnableShadow( inputdata_t &inputdata ); | |||
void InputAddOutput( inputdata_t &inputdata ); | |||
void InputFireUser1( inputdata_t &inputdata ); | |||
void InputFireUser2( inputdata_t &inputdata ); | |||
void InputFireUser3( inputdata_t &inputdata ); | |||
void InputFireUser4( inputdata_t &inputdata ); | |||
// Returns the origin at which to play an inputted dispatcheffect | |||
virtual void GetInputDispatchEffectPosition( const char *sInputString, Vector &pOrigin, QAngle &pAngles ); | |||
// tries to read a field from the entities data description - result is placed in variant_t | |||
bool ReadKeyField( const char *varName, variant_t *var ); | |||
// classname access | |||
void SetClassname( const char *className ); | |||
const char* GetClassname(); | |||
// Debug Overlays | |||
void EntityText( int text_offset, const char *text, float flDuration, int r = 255, int g = 255, int b = 255, int a = 255 ); | |||
const char *GetDebugName(void); // do not make this virtual -- designed to handle NULL this | |||
virtual void DrawDebugGeometryOverlays(void); | |||
virtual int DrawDebugTextOverlays(void); | |||
void DrawTimedOverlays( void ); | |||
void DrawBBoxOverlay( float flDuration = 0.0f ); | |||
void DrawAbsBoxOverlay(); | |||
void DrawRBoxOverlay(); | |||
void DrawInputOverlay(const char *szInputName, CBaseEntity *pCaller, variant_t Value); | |||
void DrawOutputOverlay(CEventAction *ev); | |||
void SendDebugPivotOverlay( void ); | |||
void AddTimedOverlay( const char *msg, int endTime ); | |||
void SetSolid( SolidType_t val ); | |||
// save/restore | |||
// only overload these if you have special data to serialize | |||
virtual int Save( ISave &save ); | |||
virtual int Restore( IRestore &restore ); | |||
virtual bool ShouldSavePhysics(); | |||
// handler to reset stuff before you are restored | |||
// NOTE: Always chain to base class when implementing this! | |||
virtual void OnSave( IEntitySaveUtils *pSaveUtils ); | |||
// handler to reset stuff after you are restored | |||
// called after all entities have been loaded from all affected levels | |||
// called before activate | |||
// NOTE: Always chain to base class when implementing this! | |||
virtual void OnRestore(); | |||
int GetTextureFrameIndex( void ); | |||
void SetTextureFrameIndex( int iIndex ); | |||
// 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 ); | |||
private: | |||
int SaveDataDescBlock( ISave &save, datamap_t *dmap ); | |||
int RestoreDataDescBlock( IRestore &restore, datamap_t *dmap ); | |||
public: | |||
// Networking related methods | |||
void NetworkStateChanged(); | |||
void NetworkStateChanged( void *pVar ); | |||
public: | |||
void CalcAbsolutePosition(); | |||
// returns the edict index the entity requires when used in save/restore (eg players, world) | |||
// -1 means it doesn't require any special index | |||
virtual int RequiredEdictIndex( void ) { return -1; } | |||
// interface function pts | |||
void (CBaseEntity::*m_pfnMoveDone)(void); | |||
virtual void MoveDone( void ) { if (m_pfnMoveDone) (this->*m_pfnMoveDone)();}; | |||
// Why do we have two separate static Instance functions? | |||
static CBaseEntity *Instance( const CBaseHandle &hEnt ); | |||
static CBaseEntity *Instance( const edict_t *pent ); | |||
static CBaseEntity *Instance( edict_t *pent ); | |||
static CBaseEntity* Instance( int iEnt ); | |||
// Think function handling | |||
void (CBaseEntity::*m_pfnThink)(void); | |||
virtual void Think( void ) { if (m_pfnThink) (this->*m_pfnThink)();}; | |||
// 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 ); | |||
float GetAnimTime() const; | |||
void SetAnimTime( float at ); | |||
float GetSimulationTime() const; | |||
void SetSimulationTime( float st ); | |||
void SetRenderMode( RenderMode_t nRenderMode ); | |||
RenderMode_t GetRenderMode() const; | |||
private: | |||
// NOTE: Keep this near vtable so it's in cache with vtable. | |||
CServerNetworkProperty m_Network; | |||
public: | |||
// members | |||
string_t m_iClassname; // identifier for entity creation and save/restore | |||
string_t m_iGlobalname; // identifier for carrying entity across level transitions | |||
string_t m_iParent; // the name of the entities parent; linked into m_pParent during Activate() | |||
int m_iHammerID; // Hammer unique edit id number | |||
public: | |||
// was pev->speed | |||
float m_flSpeed; | |||
// was pev->renderfx | |||
CNetworkVar( unsigned char, m_nRenderFX ); | |||
// was pev->rendermode | |||
CNetworkVar( unsigned char, m_nRenderMode ); | |||
CNetworkVar( short, m_nModelIndex ); | |||
#ifdef TF_DLL | |||
CNetworkArray( int, m_nModelIndexOverrides, MAX_VISION_MODES ); // used to override the base model index on the client if necessary | |||
#endif | |||
// was pev->rendercolor | |||
CNetworkColor32( m_clrRender ); | |||
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 ); | |||
// was pev->animtime: consider moving to CBaseAnimating | |||
float m_flPrevAnimTime; | |||
CNetworkVar( float, m_flAnimTime ); // this is the point in time that the client will interpolate to position,angle,frame,etc. | |||
CNetworkVar( float, m_flSimulationTime ); | |||
void IncrementInterpolationFrame(); // Call this to cause a discontinuity (teleport) | |||
CNetworkVar( int, m_ubInterpolationFrame ); | |||
int m_nLastThinkTick; | |||
#if !defined( NO_ENTITY_PREDICTION ) | |||
// Certain entities (projectiles) can be created on the client and thus need a matching id number | |||
CNetworkVar( CPredictableId, m_PredictableID ); | |||
#endif | |||
// used so we know when things are no longer touching | |||
int touchStamp; | |||
protected: | |||
// think function handling | |||
enum thinkmethods_t | |||
{ | |||
THINK_FIRE_ALL_FUNCTIONS, | |||
THINK_FIRE_BASE_ONLY, | |||
THINK_FIRE_ALL_BUT_BASE, | |||
}; | |||
int GetIndexForThinkContext( const char *pszContext ); | |||
CUtlVector< thinkfunc_t > m_aThinkFunctions; | |||
#ifdef _DEBUG | |||
int m_iCurrentThinkContext; | |||
#endif | |||
void RemoveExpiredConcepts( void ); | |||
int GetContextCount() const; // Call RemoveExpiredConcepts to clean out expired concepts | |||
const char *GetContextName( int index ) const; // note: context may be expired | |||
const char *GetContextValue( int index ) const; // note: context may be expired | |||
bool ContextExpired( int index ) const; | |||
int FindContextByName( const char *name ) const; | |||
public: | |||
void AddContext( const char *nameandvalue ); | |||
protected: | |||
CUtlVector< ResponseContext_t > m_ResponseContexts; | |||
// Map defined context sets | |||
string_t m_iszResponseContext; | |||
private: | |||
CBaseEntity( CBaseEntity& ); | |||
// list handling | |||
friend class CGlobalEntityList; | |||
friend class CThinkSyncTester; | |||
// was pev->nextthink | |||
CNetworkVarForDerived( int, m_nNextThinkTick ); | |||
// was pev->effects | |||
CNetworkVar( int, m_fEffects ); | |||
//////////////////////////////////////////////////////////////////////////// | |||
public: | |||
// Returns a CBaseAnimating if the entity is derived from CBaseAnimating. | |||
virtual CBaseAnimating* GetBaseAnimating() { return 0; } | |||
virtual IResponseSystem *GetResponseSystem(); | |||
virtual void DispatchResponse( const char *conceptName ); | |||
// Classify - returns the type of group (i.e, "houndeye", or "human military" so that NPCs with different classnames | |||
// still realize that they are teammates. (overridden for NPCs that form groups) | |||
virtual Class_T Classify ( void ); | |||
virtual void DeathNotice ( CBaseEntity *pVictim ) {}// NPC maker children use this to tell the NPC maker that they have died. | |||
virtual bool ShouldAttractAutoAim( CBaseEntity *pAimingEnt ) { return ((GetFlags() & FL_AIMTARGET) != 0); } | |||
virtual float GetAutoAimRadius(); | |||
virtual Vector GetAutoAimCenter() { return WorldSpaceCenter(); } | |||
virtual ITraceFilter* GetBeamTraceFilter( void ); | |||
// Call this to do a TraceAttack on an entity, performs filtering. Don't call TraceAttack() directly except when chaining up to base class | |||
void DispatchTraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr, CDmgAccumulator *pAccumulator = NULL ); | |||
virtual bool PassesDamageFilter( const CTakeDamageInfo &info ); | |||
protected: | |||
virtual void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr, CDmgAccumulator *pAccumulator = NULL ); | |||
public: | |||
virtual bool CanBeHitByMeleeAttack( CBaseEntity *pAttacker ) { return true; } | |||
// returns the amount of damage inflicted | |||
virtual int OnTakeDamage( const CTakeDamageInfo &info ); | |||
// This is what you should call to apply damage to an entity. | |||
int TakeDamage( const CTakeDamageInfo &info ); | |||
virtual void AdjustDamageDirection( const CTakeDamageInfo &info, Vector &dir, CBaseEntity *pEnt ) {} | |||
virtual int TakeHealth( float flHealth, int bitsDamageType ); | |||
virtual bool IsAlive( void ); | |||
// Entity killed (only fired once) | |||
virtual void Event_Killed( const CTakeDamageInfo &info ); | |||
void SendOnKilledGameEvent( const CTakeDamageInfo &info ); | |||
// Notifier that I've killed some other entity. (called from Victim's Event_Killed). | |||
virtual void Event_KilledOther( CBaseEntity *pVictim, const CTakeDamageInfo &info ) { return; } | |||
// UNDONE: Make this data? | |||
virtual int BloodColor( void ); | |||
void TraceBleed( float flDamage, const Vector &vecDir, trace_t *ptr, int bitsDamageType ); | |||
virtual bool IsTriggered( CBaseEntity *pActivator ) {return true;} | |||
virtual bool IsNPC( void ) const { return false; } | |||
CAI_BaseNPC *MyNPCPointer( void ); | |||
virtual CBaseCombatCharacter *MyCombatCharacterPointer( void ) { return NULL; } | |||
virtual INextBot *MyNextBotPointer( void ) { return NULL; } | |||
virtual float GetDelay( void ) { return 0; } | |||
virtual bool IsMoving( void ); | |||
bool IsWorld() { return entindex() == 0; } | |||
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 = NULL ); | |||
void AddPoints( int score, bool bAllowNegativeScore ); | |||
void AddPointsToTeam( int score, bool bAllowNegativeScore ); | |||
void RemoveAllDecals( void ); | |||
virtual bool OnControls( CBaseEntity *pControls ) { return false; } | |||
virtual bool HasTarget( string_t targetname ); | |||
virtual bool IsPlayer( void ) const { return false; } | |||
virtual bool IsNetClient( void ) const { return false; } | |||
virtual bool IsTemplate( void ) { return false; } | |||
virtual bool IsBaseObject( void ) const { return false; } | |||
virtual bool IsBaseTrain( void ) const { return false; } | |||
bool IsBSPModel() const; | |||
bool IsCombatCharacter() { return MyCombatCharacterPointer() == NULL ? false : true; } | |||
bool IsInWorld( void ) const; | |||
virtual bool IsCombatItem( void ) const { return false; } | |||
virtual bool IsBaseCombatWeapon( void ) const { return false; } | |||
virtual bool IsWearable( void ) const { return false; } | |||
virtual CBaseCombatWeapon *MyCombatWeaponPointer( void ) { return NULL; } | |||
// If this is a vehicle, returns the vehicle interface | |||
virtual IServerVehicle* GetServerVehicle() { return NULL; } | |||
// UNDONE: Make this data instead of procedural? | |||
virtual bool IsViewable( void ); // is this something that would be looked at (model, sprite, etc.)? | |||
// Team Handling | |||
CTeam *GetTeam( void ) const; // Get the Team this entity is on | |||
int GetTeamNumber( void ) const; // Get the Team number of the team this entity is on | |||
virtual void ChangeTeam( int iTeamNum ); // Assign this entity to a team. | |||
bool IsInTeam( CTeam *pTeam ) const; // Returns true if this entity's in the specified team | |||
bool InSameTeam( CBaseEntity *pEntity ) const; // Returns true if the specified entity is on the same team as this one | |||
bool IsInAnyTeam( void ) const; // Returns true if this entity is in any team | |||
const char *TeamID( void ) const; // Returns the name of the team this entity is on. | |||
// Entity events... these are events targetted to a particular entity | |||
// Each event defines its own well-defined event data structure | |||
virtual void OnEntityEvent( EntityEvent_t event, void *pEventData ); | |||
// can stand on this entity? | |||
bool IsStandable() const; | |||
// UNDONE: Do these three functions actually need to be virtual??? | |||
virtual bool CanStandOn( CBaseEntity *pSurface ) const { return (pSurface && !pSurface->IsStandable()) ? false : true; } | |||
virtual bool CanStandOn( edict_t *ent ) const { return CanStandOn( GetContainingEntity( ent ) ); } | |||
virtual CBaseEntity *GetEnemy( void ) { return NULL; } | |||
virtual CBaseEntity *GetEnemy( void ) const { return NULL; } | |||
void ViewPunch( const QAngle &angleOffset ); | |||
void VelocityPunch( const Vector &vecForce ); | |||
CBaseEntity *GetNextTarget( void ); | |||
// fundamental callbacks | |||
void (CBaseEntity ::*m_pfnTouch)( CBaseEntity *pOther ); | |||
void (CBaseEntity ::*m_pfnUse)( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); | |||
void (CBaseEntity ::*m_pfnBlocked)( CBaseEntity *pOther ); | |||
virtual void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); | |||
virtual void StartTouch( CBaseEntity *pOther ); | |||
virtual void Touch( CBaseEntity *pOther ); | |||
virtual void EndTouch( CBaseEntity *pOther ); | |||
virtual void StartBlocked( CBaseEntity *pOther ) {} | |||
virtual void Blocked( CBaseEntity *pOther ); | |||
virtual void EndBlocked( void ) {} | |||
// Physics simulation | |||
virtual void PhysicsSimulate( void ); | |||
public: | |||
// 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( CBaseEntity *other, trace_t &trace ); | |||
void PhysicsMarkEntitiesAsTouching( CBaseEntity *other, trace_t &trace ); | |||
void PhysicsMarkEntitiesAsTouchingEventDriven( CBaseEntity *other, trace_t &trace ); | |||
void PhysicsTouchTriggers( const Vector *pPrevAbsOrigin = NULL ); | |||
// Physics helper | |||
static void PhysicsRemoveTouchedList( CBaseEntity *ent ); | |||
static void PhysicsNotifyOtherOfUntouch( CBaseEntity *ent, CBaseEntity *other ); | |||
static void PhysicsRemoveToucher( CBaseEntity *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(); | |||
virtual void UpdateOnRemove( void ); | |||
virtual void StopLoopingSounds( void ) {} | |||
// common member functions | |||
void SUB_Remove( void ); | |||
void SUB_DoNothing( void ); | |||
void SUB_StartFadeOut( float delay = 10.0f, bool bNotSolid = true ); | |||
void SUB_StartFadeOutInstant(); | |||
void SUB_FadeOut ( void ); | |||
void SUB_Vanish( void ); | |||
void SUB_CallUseToggle( void ) { this->Use( this, this, USE_TOGGLE, 0 ); } | |||
void SUB_PerformFadeOut( void ); | |||
virtual bool SUB_AllowedToFade( void ); | |||
// change position, velocity, orientation instantly | |||
// passing NULL means no change | |||
virtual void Teleport( const Vector *newPosition, const QAngle *newAngles, const Vector *newVelocity ); | |||
// notify that another entity (that you were watching) was teleported | |||
virtual void NotifySystemEvent( CBaseEntity *pNotify, notify_system_event_t eventType, const notify_system_event_params_t ¶ms ); | |||
int ShouldToggle( USE_TYPE useType, int currentState ); | |||
// UNDONE: Move these virtuals to CBaseCombatCharacter? | |||
virtual void MakeTracer( const Vector &vecTracerSrc, const trace_t &tr, int iTracerType ); | |||
virtual int GetTracerAttachment( void ); | |||
virtual void FireBullets( const FireBulletsInfo_t &info ); | |||
virtual void DoImpactEffect( trace_t &tr, int nDamageType ); // give shooter a chance to do a custom impact. | |||
// OLD VERSION! Use the struct version | |||
void FireBullets( int cShots, const Vector &vecSrc, const Vector &vecDirShooting, | |||
const Vector &vecSpread, float flDistance, int iAmmoType, int iTracerFreq = 4, | |||
int firingEntID = -1, int attachmentID = -1, int iDamage = 0, | |||
CBaseEntity *pAttacker = NULL, bool bFirstShotAccurate = false, bool bPrimaryAttack = true ); | |||
virtual void ModifyFireBulletsDamage( CTakeDamageInfo* dmgInfo ) {} | |||
virtual CBaseEntity *Respawn( void ) { return NULL; } | |||
// Method used to deal with attacks passing through triggers | |||
void TraceAttackToTriggers( const CTakeDamageInfo &info, const Vector& start, const Vector& end, const Vector& dir ); | |||
// Do the bounding boxes of these two intersect? | |||
bool Intersects( CBaseEntity *pOther ); | |||
virtual bool IsLockedByMaster( void ) { return false; } | |||
// Health accessors. | |||
virtual int GetMaxHealth() const { return m_iMaxHealth; } | |||
void SetMaxHealth( int amt ) { m_iMaxHealth = amt; } | |||
int GetHealth() const { return m_iHealth; } | |||
void SetHealth( int amt ) { m_iHealth = amt; } | |||
float HealthFraction() const; | |||
// Ugly code to lookup all functions to make sure they are in the table when set. | |||
#ifdef _DEBUG | |||
#ifdef GNUC | |||
#define ENTITYFUNCPTR_SIZE 8 | |||
#else | |||
#define ENTITYFUNCPTR_SIZE 4 | |||
#endif | |||
void FunctionCheck( void *pFunction, const char *name ); | |||
ENTITYFUNCPTR TouchSet( ENTITYFUNCPTR func, char *name ) | |||
{ | |||
COMPILE_TIME_ASSERT( sizeof(func) == ENTITYFUNCPTR_SIZE ); | |||
m_pfnTouch = func; | |||
FunctionCheck( *(reinterpret_cast<void **>(&m_pfnTouch)), name ); | |||
return func; | |||
} | |||
USEPTR UseSet( USEPTR func, char *name ) | |||
{ | |||
COMPILE_TIME_ASSERT( sizeof(func) == ENTITYFUNCPTR_SIZE ); | |||
m_pfnUse = func; | |||
FunctionCheck( *(reinterpret_cast<void **>(&m_pfnUse)), name ); | |||
return func; | |||
} | |||
ENTITYFUNCPTR BlockedSet( ENTITYFUNCPTR func, char *name ) | |||
{ | |||
COMPILE_TIME_ASSERT( sizeof(func) == ENTITYFUNCPTR_SIZE ); | |||
m_pfnBlocked = func; | |||
FunctionCheck( *(reinterpret_cast<void **>(&m_pfnBlocked)), name ); | |||
return func; | |||
} | |||
#endif // _DEBUG | |||
virtual void ModifyOrAppendCriteria( AI_CriteriaSet& set ); | |||
void AppendContextToCriteria( AI_CriteriaSet& set, const char *prefix = "" ); | |||
void DumpResponseCriteria( void ); | |||
// 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; | |||
private: | |||
friend class CAI_Senses; | |||
CBaseEntity *m_pLink;// used for temporary link-list operations. | |||
public: | |||
// variables promoted from edict_t | |||
string_t m_target; | |||
CNetworkVarForDerived( int, m_iMaxHealth ); // CBaseEntity doesn't care about changes to this variable, but there are derived classes that do. | |||
CNetworkVarForDerived( int, m_iHealth ); | |||
CNetworkVarForDerived( char, m_lifeState ); | |||
CNetworkVarForDerived( char , m_takedamage ); | |||
// Damage filtering | |||
string_t m_iszDamageFilterName; // The name of the entity to use as our damage filter. | |||
EHANDLE m_hDamageFilter; // The entity that controls who can damage us. | |||
// Debugging / devolopment fields | |||
int m_debugOverlays; // For debug only (bitfields) | |||
TimedOverlay_t* m_pTimedOverlay; // For debug only | |||
// virtual functions used by a few classes | |||
// creates an entity of a specified class, by name | |||
static CBaseEntity *Create( const char *szName, const Vector &vecOrigin, const QAngle &vecAngles, CBaseEntity *pOwner = NULL ); | |||
static CBaseEntity *CreateNoSpawn( const char *szName, const Vector &vecOrigin, const QAngle &vecAngles, CBaseEntity *pOwner = NULL ); | |||
// Collision group accessors | |||
int GetCollisionGroup() const; | |||
void SetCollisionGroup( int collisionGroup ); | |||
void CollisionRulesChanged(); | |||
// Damage accessors | |||
virtual int GetDamageType() const; | |||
virtual float GetDamage() { return 0; } | |||
virtual void SetDamage(float flDamage) {} | |||
virtual Vector EyePosition( void ); // position of eyes | |||
virtual const QAngle &EyeAngles( void ); // Direction of eyes in world space | |||
virtual const QAngle &LocalEyeAngles( void ); // Direction of eyes | |||
virtual Vector EarPosition( void ); // position of ears | |||
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 | |||
virtual Vector BodyTarget( const Vector &posSrc, bool bNoisy = true); // position to shoot at | |||
virtual Vector HeadTarget( const Vector &posSrc ); | |||
virtual void GetVectors(Vector* forward, Vector* right, Vector* up) const; | |||
virtual const Vector &GetViewOffset() const; | |||
virtual void SetViewOffset( const Vector &v ); | |||
// 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 ApplyLocalVelocityImpulse( const Vector &vecImpulse ); | |||
void SetAbsVelocity( const Vector &vecVelocity ); | |||
void ApplyAbsVelocityImpulse( const Vector &vecImpulse ); | |||
void ApplyLocalAngularVelocityImpulse( const AngularImpulse &angImpulse ); | |||
const Vector& GetLocalVelocity( ) const; | |||
const Vector& GetAbsVelocity( ) const; | |||
// 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; | |||
// FIXME: While we're using (dPitch, dYaw, dRoll) as our local angular velocity | |||
// representation, we can't actually solve this problem | |||
// void SetAbsAngularVelocity( const QAngle &vecAngVelocity ); | |||
// const QAngle& GetAbsAngularVelocity( ) const; | |||
const Vector& GetBaseVelocity() const; | |||
void SetBaseVelocity( const Vector& v ); | |||
virtual Vector GetSmoothedVelocity( void ); | |||
// FIXME: Figure out what to do about this | |||
virtual void GetVelocity(Vector *vVelocity, AngularImpulse *vAngVelocity = NULL); | |||
float GetGravity( void ) const; | |||
void SetGravity( float gravity ); | |||
float GetFriction( void ) const; | |||
void SetFriction( float flFriction ); | |||
virtual bool FVisible ( CBaseEntity *pEntity, int traceMask = MASK_BLOCKLOS, CBaseEntity **ppBlocker = NULL ); | |||
virtual bool FVisible( const Vector &vecTarget, int traceMask = MASK_BLOCKLOS, CBaseEntity **ppBlocker = NULL ); | |||
virtual bool CanBeSeenBy( CAI_BaseNPC *pNPC ) { return true; } // allows entities to be 'invisible' to NPC senses. | |||
// 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( CBaseEntity *pVictim ); | |||
// This returns a value that scales all damage done to this entity | |||
// Use CDamageModifier to hook in damage modifiers on a guy. | |||
virtual float GetReceivedDamageScale( CBaseEntity *pAttacker ); | |||
void SetCheckUntouch( bool check ); | |||
bool GetCheckUntouch() const; | |||
void SetGroundEntity( CBaseEntity *ground ); | |||
CBaseEntity *GetGroundEntity( void ); | |||
CBaseEntity *GetGroundEntity( void ) const { return const_cast<CBaseEntity *>(this)->GetGroundEntity(); } | |||
// Gets the velocity we impart to a player standing on us | |||
virtual void GetGroundVelocityToApply( Vector &vecGroundVel ) { vecGroundVel = vec3_origin; } | |||
int GetWaterLevel() const; | |||
void SetWaterLevel( int nLevel ); | |||
int GetWaterType() const; | |||
void SetWaterType( int nType ); | |||
virtual bool PhysicsSplash( const Vector ¢erPoint, const Vector &normal, float rawSpeed, float scaledSpeed ) { return false; } | |||
virtual void Splash() {} | |||
void ClearSolidFlags( void ); | |||
void RemoveSolidFlags( int flags ); | |||
void AddSolidFlags( int flags ); | |||
bool IsSolidFlagSet( int flagMask ) const; | |||
void SetSolidFlags( int flags ); | |||
bool IsSolid() const; | |||
void SetModelName( string_t name ); | |||
model_t *GetModel( void ); | |||
// 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 | |||
const Vector& WorldAlignMins( ) const; | |||
const Vector& WorldAlignMaxs( ) const; | |||
// This defines collision bounds in OBB space | |||
void SetCollisionBounds( const Vector& mins, const Vector &maxs ); | |||
// NOTE: The world space center *may* move when the entity rotates. | |||
virtual const Vector& WorldSpaceCenter( ) const; | |||
const Vector& WorldAlignSize( ) 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; | |||
bool IsPointSized() const; | |||
// NOTE: Setting the abs origin or angles will cause the local origin + angles to be set also | |||
void SetAbsOrigin( const Vector& origin ); | |||
void SetAbsAngles( const QAngle& angles ); | |||
// Origin and angles in local space ( relative to parent ) | |||
// NOTE: Setting the local origin or angles will cause the abs origin + angles to be set also | |||
void SetLocalOrigin( const Vector& origin ); | |||
const Vector& GetLocalOrigin( void ) const; | |||
void SetLocalAngles( const QAngle& angles ); | |||
const QAngle& GetLocalAngles( void ) const; | |||
void SetElasticity( float flElasticity ); | |||
float GetElasticity( void ) const; | |||
void SetShadowCastDistance( float flDistance ); | |||
float GetShadowCastDistance( void ) const; | |||
void SetShadowCastDistance( float flDesiredDistance, float flDelay ); | |||
float GetLocalTime( void ) const; | |||
void IncrementLocalTime( float flTimeDelta ); | |||
float GetMoveDoneTime( ) const; | |||
void SetMoveDoneTime( float flTime ); | |||
// Used by the PAS filters to ask the entity where in world space the sounds it emits come from. | |||
// This is used right now because if you have something sitting on an incline, using our axis-aligned | |||
// bounding boxes can return a position in solid space, so you won't hear sounds emitted by the object. | |||
// For now, we're hacking around it by moving the sound emission origin up on certain objects like vehicles. | |||
// | |||
// When OBBs get in, this can probably go away. | |||
virtual Vector GetSoundEmissionOrigin() const; | |||
void AddFlag( int flags ); | |||
void RemoveFlag( int flagsToRemove ); | |||
void ToggleFlag( int flagToToggle ); | |||
int GetFlags( void ) const; | |||
void ClearFlags( void ); | |||
// Sets the local position from a transform | |||
void SetLocalTransform( const matrix3x4_t &localTransform ); | |||
// See CSoundEmitterSystem | |||
void EmitSound( const char *soundname, float soundtime = 0.0f, float *duration = NULL ); // Override for doing the general case of CPASAttenuationFilter filter( 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 filter( 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 ); | |||
virtual void ModifyEmitSoundParams( EmitSound_t ¶ms ); | |||
static float GetSoundDuration( const char *soundname, char const *actormodel ); | |||
static bool GetParametersForSound( const char *soundname, CSoundParameters ¶ms, char const *actormodel ); | |||
static bool GetParametersForSound( const char *soundname, HSOUNDSCRIPTHANDLE& handle, CSoundParameters ¶ms, char const *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 & params ); | |||
static void EmitSound( IRecipientFilter& filter, int iEntIndex, const EmitSound_t & params, 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( CRecipientFilter& filter ); | |||
static void EmitCloseCaption( IRecipientFilter& filter, int entindex, char const *token, CUtlVector< Vector >& soundorigins, float duration, bool warnifmissing = false ); | |||
static void EmitSentenceByIndex( IRecipientFilter& filter, int iEntIndex, int iChannel, int iSentenceIndex, | |||
float flVolume, soundlevel_t iSoundlevel, int iFlags = 0, int iPitch = PITCH_NORM, | |||
const Vector *pOrigin = NULL, const Vector *pDirection = NULL, bool bUpdatePositions = true, float soundtime = 0.0f ); | |||
static bool IsPrecacheAllowed(); | |||
static void SetAllowPrecache( bool allow ); | |||
static bool m_bAllowPrecache; | |||
static bool IsSimulatingOnAlternateTicks(); | |||
virtual bool IsDeflectable() { return false; } | |||
virtual void Deflected( CBaseEntity *pDeflectedBy, Vector &vecDir ) {} | |||
// void Relink() {} | |||
public: | |||
// VPHYSICS Integration ----------------------------------------------- | |||
// | |||
// -------------------------------------------------------------------- | |||
// UNDONE: Move to IEntityVPhysics? or VPhysicsProp() ? | |||
// 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 - physics determines where it goes (gravity, friction, etc) | |||
// and the entity receives updates from vphysics. SetAbsOrigin(), etc do not affect the 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 ); | |||
// Force a non-solid (ie. solid_trigger) physics object to collide with other entities. | |||
virtual bool ForceVPhysicsCollide( CBaseEntity *pEntity ) { return false; } | |||
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 ); | |||
void VPhysicsSwapObject( IPhysicsObject *pSwap ); | |||
inline IPhysicsObject *VPhysicsGetObject( void ) const { return m_pPhysicsObject; } | |||
virtual void VPhysicsUpdate( IPhysicsObject *pPhysics ); | |||
void VPhysicsUpdatePusher( IPhysicsObject *pPhysics ); | |||
// react physically to damage (called from CBaseEntity::OnTakeDamage() by default) | |||
virtual int VPhysicsTakeDamage( const CTakeDamageInfo &info ); | |||
virtual void VPhysicsShadowCollision( int index, gamevcollisionevent_t *pEvent ); | |||
virtual void VPhysicsShadowUpdate( IPhysicsObject *pPhysics ) {} | |||
virtual void VPhysicsCollision( int index, gamevcollisionevent_t *pEvent ); | |||
virtual void VPhysicsFriction( IPhysicsObject *pObject, float energy, int surfaceProps, int surfacePropsHit ); | |||
// update the shadow so it will coincide with the current AI position at some time | |||
// in the future (or 0 for now) | |||
virtual void UpdatePhysicsShadowToCurrentPosition( float deltaTime ); | |||
virtual int VPhysicsGetObjectList( IPhysicsObject **pList, int listMax ); | |||
virtual bool VPhysicsIsFlesh( void ); | |||
// -------------------------------------------------------------------- | |||
public: | |||
#if !defined( NO_ENTITY_PREDICTION ) | |||
// The player drives simulation of this entity | |||
void SetPlayerSimulated( CBasePlayer *pOwner ); | |||
void UnsetPlayerSimulated( void ); | |||
bool IsPlayerSimulated( void ) const; | |||
CBasePlayer *GetSimulatingPlayer( void ); | |||
#endif | |||
// FIXME: Make these private! | |||
void PhysicsCheckForEntityUntouch( void ); | |||
bool PhysicsRunThink( thinkmethods_t thinkMethod = THINK_FIRE_ALL_FUNCTIONS ); | |||
bool PhysicsRunSpecificThink( int nContextIndex, BASEPTR thinkFunc ); | |||
bool PhysicsTestEntityPosition( CBaseEntity **ppEntity = NULL ); | |||
void PhysicsPushEntity( const Vector& push, trace_t *pTrace ); | |||
bool PhysicsCheckWater( void ); | |||
void PhysicsCheckWaterTransition( void ); | |||
void PhysicsStepRecheckGround(); | |||
// Computes the water level + type | |||
void UpdateWaterState(); | |||
bool IsEdictFree() const { return edict()->IsFree(); } | |||
// Callbacks for the physgun/cannon picking up an entity | |||
virtual CBasePlayer *HasPhysicsAttacker( float dt ) { return NULL; } | |||
// UNDONE: Make this data? | |||
virtual unsigned int PhysicsSolidMaskForEntity( void ) const; | |||
// 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 ); | |||
void SetPredictionEligible( bool canpredict ); | |||
protected: | |||
// Invalidates the abs state of all children | |||
void InvalidatePhysicsRecursive( int nChangeFlags ); | |||
int PhysicsClipVelocity (const Vector& in, const Vector& normal, Vector& out, float overbounce ); | |||
void PhysicsRelinkChildren( float dt ); | |||
// 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 ); | |||
virtual void ResolveFlyCollisionCustom( trace_t &trace, Vector &vecVelocity ); | |||
private: | |||
// Physics-related private methods | |||
void PhysicsStep( void ); | |||
void PhysicsPusher( void ); | |||
void PhysicsNone( void ); | |||
void PhysicsNoclip( void ); | |||
void PhysicsStepRunTimestep( float timestep ); | |||
void PhysicsToss( void ); | |||
void PhysicsCustom( void ); | |||
void PerformPush( float movetime ); | |||
// Simulation in local space of rigid children | |||
void PhysicsRigidChild( void ); | |||
// Computes the base velocity | |||
void UpdateBaseVelocity( void ); | |||
// Implement this if you use MOVETYPE_CUSTOM | |||
virtual void PerformCustomPhysics( Vector *pNewPosition, Vector *pNewVelocity, QAngle *pNewAngles, QAngle *pNewAngVelocity ); | |||
void PhysicsDispatchThink( BASEPTR thinkFunc ); | |||
touchlink_t *PhysicsMarkEntityAsTouched( CBaseEntity *other ); | |||
void PhysicsTouch( CBaseEntity *pentOther ); | |||
void PhysicsStartTouch( CBaseEntity *pentOther ); | |||
CBaseEntity *PhysicsPushMove( float movetime ); | |||
CBaseEntity *PhysicsPushRotate( float movetime ); | |||
CBaseEntity *PhysicsCheckRotateMove( rotatingpushmove_t &rotPushmove, CBaseEntity **pPusherList, int pusherListCount ); | |||
CBaseEntity *PhysicsCheckPushMove( const Vector& move, CBaseEntity **pPusherList, int pusherListCount ); | |||
int PhysicsTryMove( float flTime, trace_t *steptrace ); | |||
void PhysicsCheckVelocity( void ); | |||
void PhysicsAddHalfGravity( float timestep ); | |||
void PhysicsAddGravityMove( Vector &move ); | |||
void CalcAbsoluteVelocity(); | |||
void CalcAbsoluteAngularVelocity(); | |||
// Checks a sweep without actually performing the move | |||
void PhysicsCheckSweep( const Vector& vecAbsStart, const Vector &vecAbsDelta, trace_t *pTrace ); | |||
// Computes new angles based on the angular velocity | |||
void SimulateAngles( float flFrameTime ); | |||
void CheckStepSimulationChanged(); | |||
// Run regular think and latch off angle/origin changes so we can interpolate them on the server to fake simulation | |||
void StepSimulationThink( float dt ); | |||
// Compute network origin | |||
private: | |||
void ComputeStepSimulationNetwork( StepSimulationData *step ); | |||
public: | |||
bool UseStepSimulationNetworkOrigin( const Vector **out_v ); | |||
bool UseStepSimulationNetworkAngles( const QAngle **out_a ); | |||
public: | |||
// Add a discontinuity to a step | |||
bool AddStepDiscontinuity( float flTime, const Vector &vecOrigin, const QAngle &vecAngles ); | |||
int GetFirstThinkTick(); // get first tick thinking on any context | |||
private: | |||
// origin and angles to use in step calculations | |||
virtual Vector GetStepOrigin( void ) const; | |||
virtual QAngle GetStepAngles( void ) const; | |||
// These set entity flags (EFL_*) to help optimize queries | |||
void CheckHasThinkFunction( bool isThinkingHint = false ); | |||
void CheckHasGamePhysicsSimulation(); | |||
bool WillThink(); | |||
bool WillSimulateGamePhysics(); | |||
friend class CPushBlockerEnum; | |||
// 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; | |||
// Shot statistics | |||
void UpdateShotStatistics( const trace_t &tr ); | |||
// Handle shot entering water | |||
bool HandleShotImpactingWater( const FireBulletsInfo_t &info, const Vector &vecEnd, ITraceFilter *pTraceFilter, Vector *pVecTracerDest ); | |||
// Handle shot entering water | |||
void HandleShotImpactingGlass( const FireBulletsInfo_t &info, const trace_t &tr, const Vector &vecDir, ITraceFilter *pTraceFilter ); | |||
// Should we draw bubbles underwater? | |||
bool ShouldDrawUnderwaterBulletBubbles(); | |||
// Computes the tracer start position | |||
void ComputeTracerStartPosition( const Vector &vecShotSrc, Vector *pVecTracerStart ); | |||
// Computes the tracer start position | |||
void CreateBubbleTrailTracer( const Vector &vecShotSrc, const Vector &vecShotEnd, const Vector &vecShotDir ); | |||
virtual bool ShouldDrawWaterImpacts() { return true; } | |||
// Changes shadow cast distance over time | |||
void ShadowCastDistThink( ); | |||
// Precache model sounds + particles | |||
static void PrecacheModelComponents( int nModelIndex ); | |||
static void PrecacheSoundHelper( const char *pName ); | |||
protected: | |||
// Which frame did I simulate? | |||
int m_nSimulationTick; | |||
// FIXME: Make this private! Still too many references to do so... | |||
CNetworkVar( int, m_spawnflags ); | |||
private: | |||
int m_iEFlags; // entity flags EFL_* | |||
// was pev->flags | |||
CNetworkVarForDerived( int, m_fFlags ); | |||
string_t m_iName; // name used to identify this entity | |||
// Damage modifiers | |||
friend class CDamageModifier; | |||
CUtlLinkedList<CDamageModifier*,int> m_DamageModifiers; | |||
EHANDLE m_pParent; // for movement hierarchy | |||
byte m_nTransmitStateOwnedCounter; | |||
CNetworkVar( unsigned char, m_iParentAttachment ); // 0 if we're relative to the parent's absorigin and absangles. | |||
CNetworkVar( unsigned char, m_MoveType ); // One of the MOVETYPE_ defines. | |||
CNetworkVar( unsigned char, m_MoveCollide ); | |||
// Our immediate parent in the movement hierarchy. | |||
// FIXME: clarify m_pParent vs. m_pMoveParent | |||
CNetworkHandle( CBaseEntity, m_hMoveParent ); | |||
// cached child list | |||
EHANDLE m_hMoveChild; | |||
// generated from m_pMoveParent | |||
EHANDLE m_hMovePeer; | |||
friend class CCollisionProperty; | |||
friend class CServerNetworkProperty; | |||
CNetworkVarEmbedded( CCollisionProperty, m_Collision ); | |||
CNetworkHandle( CBaseEntity, m_hOwnerEntity ); // only used to point to an edict it won't collide with | |||
CNetworkHandle( CBaseEntity, m_hEffectEntity ); // Fire/Dissolve entity. | |||
CNetworkVar( int, m_CollisionGroup ); // used to cull collision tests | |||
IPhysicsObject *m_pPhysicsObject; // pointer to the entity's physics object (vphysics.dll) | |||
CNetworkVar( float, m_flShadowCastDistance ); | |||
float m_flDesiredShadowCastDistance; | |||
// Team handling | |||
int m_iInitialTeamNum; // Team number of this entity's team read from file | |||
CNetworkVar( int, m_iTeamNum ); // Team number of this entity's team. | |||
// Sets water type + level for physics objects | |||
unsigned char m_nWaterTouch; | |||
unsigned char m_nSlimeTouch; | |||
unsigned char m_nWaterType; | |||
CNetworkVarForDerived( unsigned char, m_nWaterLevel ); | |||
float m_flNavIgnoreUntilTime; | |||
CNetworkHandleForDerived( CBaseEntity, m_hGroundEntity ); | |||
float m_flGroundChangeTime; // Time that the ground entity changed | |||
string_t m_ModelName; | |||
// Velocity of the thing we're standing on (world space) | |||
CNetworkVarForDerived( Vector, m_vecBaseVelocity ); | |||
// Global velocity | |||
Vector m_vecAbsVelocity; | |||
// Local angular velocity | |||
QAngle m_vecAngVelocity; | |||
// Global angular velocity | |||
// QAngle m_vecAbsAngVelocity; | |||
// local coordinate frame of entity | |||
matrix3x4_t m_rgflCoordinateFrame; | |||
// Physics state | |||
EHANDLE m_pBlocker; | |||
// was pev->gravity; | |||
float m_flGravity; // rename to m_flGravityScale; | |||
// was pev->friction | |||
CNetworkVarForDerived( float, m_flFriction ); | |||
CNetworkVar( float, m_flElasticity ); | |||
// was pev->ltime | |||
float m_flLocalTime; | |||
// local time at the beginning of this frame | |||
float m_flVPhysicsUpdateLocalTime; | |||
// local time the movement has ended | |||
float m_flMoveDoneTime; | |||
// A counter to help quickly build a list of potentially pushed objects for physics | |||
int m_nPushEnumCount; | |||
Vector m_vecAbsOrigin; | |||
CNetworkVectorForDerived( m_vecVelocity ); | |||
//Adrian | |||
CNetworkVar( unsigned char, m_iTextureFrameIndex ); | |||
CNetworkVar( bool, m_bSimulatedEveryTick ); | |||
CNetworkVar( bool, m_bAnimatedEveryTick ); | |||
CNetworkVar( bool, m_bAlternateSorting ); | |||
// User outputs. Fired when the "FireInputX" input is triggered. | |||
COutputEvent m_OnUser1; | |||
COutputEvent m_OnUser2; | |||
COutputEvent m_OnUser3; | |||
COutputEvent m_OnUser4; | |||
QAngle m_angAbsRotation; | |||
CNetworkVector( m_vecOrigin ); | |||
CNetworkQAngle( m_angRotation ); | |||
CBaseHandle m_RefEHandle; | |||
// was pev->view_ofs ( FIXME: Move somewhere up the hierarch, CBaseAnimating, etc. ) | |||
CNetworkVectorForDerived( m_vecViewOffset ); | |||
private: | |||
// dynamic model state tracking | |||
bool m_bDynamicModelAllowed; | |||
bool m_bDynamicModelPending; | |||
bool m_bDynamicModelSetBounds; | |||
void OnModelLoadComplete( const model_t* model ); | |||
friend class CBaseEntityModelLoadProxy; | |||
protected: | |||
void EnableDynamicModels() { m_bDynamicModelAllowed = true; } | |||
public: | |||
bool IsDynamicModelLoading() const { return m_bDynamicModelPending; } | |||
void SetCollisionBoundsFromModel(); | |||
#if !defined( NO_ENTITY_PREDICTION ) | |||
CNetworkVar( bool, m_bIsPlayerSimulated ); | |||
// Player who is driving my simulation | |||
CHandle< CBasePlayer > m_hPlayerSimulationOwner; | |||
#endif | |||
int m_fDataObjectTypes; | |||
// So it can get at the physics methods | |||
friend class CCollisionEvent; | |||
// Methods shared by client and server | |||
public: | |||
void SetSize( const Vector &vecMin, const Vector &vecMax ); // UTIL_SetSize( this, mins, maxs ); | |||
static int PrecacheModel( const char *name, bool bPreload = true ); | |||
static bool PrecacheSound( const char *name ); | |||
static void PrefetchSound( const char *name ); | |||
void Remove( ); // UTIL_Remove( this ); | |||
private: | |||
// 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 int m_nPredictionRandomSeedServer; | |||
static CBasePlayer *m_pPredictionPlayer; | |||
// FIXME: Make hierarchy a member of CBaseEntity | |||
// or a contained private class... | |||
friend void UnlinkChild( CBaseEntity *pParent, CBaseEntity *pChild ); | |||
friend void LinkChild( CBaseEntity *pParent, CBaseEntity *pChild ); | |||
friend void ClearParent( CBaseEntity *pEntity ); | |||
friend void UnlinkAllChildren( CBaseEntity *pParent ); | |||
friend void UnlinkFromParent( CBaseEntity *pRemove ); | |||
friend void TransferChildren( CBaseEntity *pOldParent, CBaseEntity *pNewParent ); | |||
public: | |||
// Accessors for above | |||
static int GetPredictionRandomSeed( bool bUseUnSyncedServerPlatTime = false ); | |||
static void SetPredictionRandomSeed( const CUserCmd *cmd ); | |||
static CBasePlayer *GetPredictionPlayer( void ); | |||
static void SetPredictionPlayer( CBasePlayer *player ); | |||
// For debugging shared code | |||
static bool IsServer( void ) | |||
{ | |||
return true; | |||
} | |||
static bool IsClient( void ) | |||
{ | |||
return false; | |||
} | |||
static char const *GetDLLType( void ) | |||
{ | |||
return "server"; | |||
} | |||
// Used to access m_vecAbsOrigin during restore when it's unsafe to call GetAbsOrigin. | |||
friend class CPlayerRestoreHelper; | |||
static bool s_bAbsQueriesValid; | |||
// Call this when hierarchy is not completely set up (such as during Restore) to throw asserts | |||
// when people call GetAbsAnything. | |||
static inline void SetAbsQueriesValid( bool bValid ) | |||
{ | |||
s_bAbsQueriesValid = bValid; | |||
} | |||
static inline bool IsAbsQueriesValid() | |||
{ | |||
return s_bAbsQueriesValid; | |||
} | |||
virtual bool ShouldBlockNav() const { return true; } | |||
}; | |||
// Send tables exposed in this module. | |||
EXTERN_SEND_TABLE(DT_Edict); | |||
EXTERN_SEND_TABLE(DT_BaseEntity); | |||
</syntaxhighlight>}} | |||
==== [https://github.com/ValveSoftware/source-sdk-2013/blob/master/mp/src/game/server/baseentity.cpp baseentity.cpp] ==== | ==== [https://github.com/ValveSoftware/source-sdk-2013/blob/master/mp/src/game/server/baseentity.cpp baseentity.cpp] ==== | ||
<syntaxhighlight lang=cpp> | :{{expand|<syntaxhighlight lang=cpp> | ||
</syntaxhighlight> | BEGIN_SIMPLE_DATADESC( thinkfunc_t ) | ||
DEFINE_FIELD( m_iszContext, FIELD_STRING ), | |||
// DEFINE_FIELD( m_pfnThink, FIELD_FUNCTION ), // Manually written | |||
DEFINE_FIELD( m_nNextThinkTick, FIELD_TICK ), | |||
DEFINE_FIELD( m_nLastThinkTick, FIELD_TICK ), | |||
END_DATADESC() | |||
BEGIN_SIMPLE_DATADESC( ResponseContext_t ) | |||
DEFINE_FIELD( m_iszName, FIELD_STRING ), | |||
DEFINE_FIELD( m_iszValue, FIELD_STRING ), | |||
DEFINE_FIELD( m_fExpirationTime, FIELD_TIME ), | |||
END_DATADESC() | |||
BEGIN_DATADESC_NO_BASE( CBaseEntity ) | |||
DEFINE_KEYFIELD( m_iClassname, FIELD_STRING, "classname" ), | |||
DEFINE_GLOBAL_KEYFIELD( m_iGlobalname, FIELD_STRING, "globalname" ), | |||
DEFINE_KEYFIELD( m_iParent, FIELD_STRING, "parentname" ), | |||
DEFINE_KEYFIELD( m_iHammerID, FIELD_INTEGER, "hammerid" ), // save ID numbers so that entities can be tracked between save/restore and vmf | |||
DEFINE_KEYFIELD( m_flSpeed, FIELD_FLOAT, "speed" ), | |||
DEFINE_KEYFIELD( m_nRenderFX, FIELD_CHARACTER, "renderfx" ), | |||
DEFINE_KEYFIELD( m_nRenderMode, FIELD_CHARACTER, "rendermode" ), | |||
// Consider moving to CBaseAnimating? | |||
DEFINE_FIELD( m_flPrevAnimTime, FIELD_TIME ), | |||
DEFINE_FIELD( m_flAnimTime, FIELD_TIME ), | |||
DEFINE_FIELD( m_flSimulationTime, FIELD_TIME ), | |||
DEFINE_FIELD( m_nLastThinkTick, FIELD_TICK ), | |||
DEFINE_KEYFIELD( m_nNextThinkTick, FIELD_TICK, "nextthink" ), | |||
DEFINE_KEYFIELD( m_fEffects, FIELD_INTEGER, "effects" ), | |||
DEFINE_KEYFIELD( m_clrRender, FIELD_COLOR32, "rendercolor" ), | |||
DEFINE_GLOBAL_KEYFIELD( m_nModelIndex, FIELD_SHORT, "modelindex" ), | |||
#if !defined( NO_ENTITY_PREDICTION ) | |||
// DEFINE_FIELD( m_PredictableID, CPredictableId ), | |||
#endif | |||
DEFINE_FIELD( touchStamp, FIELD_INTEGER ), | |||
DEFINE_CUSTOM_FIELD( m_aThinkFunctions, thinkcontextFuncs ), | |||
// m_iCurrentThinkContext (not saved, debug field only, and think transient to boot) | |||
DEFINE_UTLVECTOR(m_ResponseContexts, FIELD_EMBEDDED), | |||
DEFINE_KEYFIELD( m_iszResponseContext, FIELD_STRING, "ResponseContext" ), | |||
DEFINE_FIELD( m_pfnThink, FIELD_FUNCTION ), | |||
DEFINE_FIELD( m_pfnTouch, FIELD_FUNCTION ), | |||
DEFINE_FIELD( m_pfnUse, FIELD_FUNCTION ), | |||
DEFINE_FIELD( m_pfnBlocked, FIELD_FUNCTION ), | |||
DEFINE_FIELD( m_pfnMoveDone, FIELD_FUNCTION ), | |||
DEFINE_FIELD( m_lifeState, FIELD_CHARACTER ), | |||
DEFINE_FIELD( m_takedamage, FIELD_CHARACTER ), | |||
DEFINE_KEYFIELD( m_iMaxHealth, FIELD_INTEGER, "max_health" ), | |||
DEFINE_KEYFIELD( m_iHealth, FIELD_INTEGER, "health" ), | |||
// DEFINE_FIELD( m_pLink, FIELD_CLASSPTR ), | |||
DEFINE_KEYFIELD( m_target, FIELD_STRING, "target" ), | |||
DEFINE_KEYFIELD( m_iszDamageFilterName, FIELD_STRING, "damagefilter" ), | |||
DEFINE_FIELD( m_hDamageFilter, FIELD_EHANDLE ), | |||
DEFINE_FIELD( m_debugOverlays, FIELD_INTEGER ), | |||
DEFINE_GLOBAL_FIELD( m_pParent, FIELD_EHANDLE ), | |||
DEFINE_FIELD( m_iParentAttachment, FIELD_CHARACTER ), | |||
DEFINE_GLOBAL_FIELD( m_hMoveParent, FIELD_EHANDLE ), | |||
DEFINE_GLOBAL_FIELD( m_hMoveChild, FIELD_EHANDLE ), | |||
DEFINE_GLOBAL_FIELD( m_hMovePeer, FIELD_EHANDLE ), | |||
DEFINE_FIELD( m_iEFlags, FIELD_INTEGER ), | |||
DEFINE_FIELD( m_iName, FIELD_STRING ), | |||
DEFINE_EMBEDDED( m_Collision ), | |||
DEFINE_EMBEDDED( m_Network ), | |||
DEFINE_FIELD( m_MoveType, FIELD_CHARACTER ), | |||
DEFINE_FIELD( m_MoveCollide, FIELD_CHARACTER ), | |||
DEFINE_FIELD( m_hOwnerEntity, FIELD_EHANDLE ), | |||
DEFINE_FIELD( m_CollisionGroup, FIELD_INTEGER ), | |||
DEFINE_PHYSPTR( m_pPhysicsObject), | |||
DEFINE_FIELD( m_flElasticity, FIELD_FLOAT ), | |||
DEFINE_KEYFIELD( m_flShadowCastDistance, FIELD_FLOAT, "shadowcastdist" ), | |||
DEFINE_FIELD( m_flDesiredShadowCastDistance, FIELD_FLOAT ), | |||
DEFINE_INPUT( m_iInitialTeamNum, FIELD_INTEGER, "TeamNum" ), | |||
DEFINE_FIELD( m_iTeamNum, FIELD_INTEGER ), | |||
// DEFINE_FIELD( m_bSentLastFrame, FIELD_INTEGER ), | |||
DEFINE_FIELD( m_hGroundEntity, FIELD_EHANDLE ), | |||
DEFINE_FIELD( m_flGroundChangeTime, FIELD_TIME ), | |||
DEFINE_GLOBAL_KEYFIELD( m_ModelName, FIELD_MODELNAME, "model" ), | |||
DEFINE_KEYFIELD( m_vecBaseVelocity, FIELD_VECTOR, "basevelocity" ), | |||
DEFINE_FIELD( m_vecAbsVelocity, FIELD_VECTOR ), | |||
DEFINE_KEYFIELD( m_vecAngVelocity, FIELD_VECTOR, "avelocity" ), | |||
// DEFINE_FIELD( m_vecAbsAngVelocity, FIELD_VECTOR ), | |||
DEFINE_ARRAY( m_rgflCoordinateFrame, FIELD_FLOAT, 12 ), // NOTE: MUST BE IN LOCAL SPACE, NOT POSITION_VECTOR!!! (see CBaseEntity::Restore) | |||
DEFINE_KEYFIELD( m_nWaterLevel, FIELD_CHARACTER, "waterlevel" ), | |||
DEFINE_FIELD( m_nWaterType, FIELD_CHARACTER ), | |||
DEFINE_FIELD( m_pBlocker, FIELD_EHANDLE ), | |||
DEFINE_KEYFIELD( m_flGravity, FIELD_FLOAT, "gravity" ), | |||
DEFINE_KEYFIELD( m_flFriction, FIELD_FLOAT, "friction" ), | |||
// Local time is local to each object. It doesn't need to be re-based if the clock | |||
// changes. Therefore it is saved as a FIELD_FLOAT, not a FIELD_TIME | |||
DEFINE_KEYFIELD( m_flLocalTime, FIELD_FLOAT, "ltime" ), | |||
DEFINE_FIELD( m_flVPhysicsUpdateLocalTime, FIELD_FLOAT ), | |||
DEFINE_FIELD( m_flMoveDoneTime, FIELD_FLOAT ), | |||
// DEFINE_FIELD( m_nPushEnumCount, FIELD_INTEGER ), | |||
DEFINE_FIELD( m_vecAbsOrigin, FIELD_POSITION_VECTOR ), | |||
DEFINE_KEYFIELD( m_vecVelocity, FIELD_VECTOR, "velocity" ), | |||
DEFINE_KEYFIELD( m_iTextureFrameIndex, FIELD_CHARACTER, "texframeindex" ), | |||
DEFINE_FIELD( m_bSimulatedEveryTick, FIELD_BOOLEAN ), | |||
DEFINE_FIELD( m_bAnimatedEveryTick, FIELD_BOOLEAN ), | |||
DEFINE_FIELD( m_bAlternateSorting, FIELD_BOOLEAN ), | |||
DEFINE_KEYFIELD( m_spawnflags, FIELD_INTEGER, "spawnflags" ), | |||
DEFINE_FIELD( m_nTransmitStateOwnedCounter, FIELD_CHARACTER ), | |||
DEFINE_FIELD( m_angAbsRotation, FIELD_VECTOR ), | |||
DEFINE_FIELD( m_vecOrigin, FIELD_VECTOR ), // NOTE: MUST BE IN LOCAL SPACE, NOT POSITION_VECTOR!!! (see CBaseEntity::Restore) | |||
DEFINE_FIELD( m_angRotation, FIELD_VECTOR ), | |||
DEFINE_KEYFIELD( m_vecViewOffset, FIELD_VECTOR, "view_ofs" ), | |||
DEFINE_FIELD( m_fFlags, FIELD_INTEGER ), | |||
#if !defined( NO_ENTITY_PREDICTION ) | |||
// DEFINE_FIELD( m_bIsPlayerSimulated, FIELD_INTEGER ), | |||
// DEFINE_FIELD( m_hPlayerSimulationOwner, FIELD_EHANDLE ), | |||
#endif | |||
// DEFINE_FIELD( m_pTimedOverlay, TimedOverlay_t* ), | |||
DEFINE_FIELD( m_nSimulationTick, FIELD_TICK ), | |||
// DEFINE_FIELD( m_RefEHandle, CBaseHandle ), | |||
// DEFINE_FIELD( m_nWaterTouch, FIELD_INTEGER ), | |||
// DEFINE_FIELD( m_nSlimeTouch, FIELD_INTEGER ), | |||
DEFINE_FIELD( m_flNavIgnoreUntilTime, FIELD_TIME ), | |||
// DEFINE_FIELD( m_bToolRecording, FIELD_BOOLEAN ), | |||
// DEFINE_FIELD( m_ToolHandle, FIELD_INTEGER ), | |||
// NOTE: This is tricky. TeamNum must be saved, but we can't directly | |||
// read it in, because we can only set it after the team entity has been read in, | |||
// which may or may not actually occur before the entity is parsed. | |||
// Therefore, we set the TeamNum from the InitialTeamNum in Activate | |||
DEFINE_INPUTFUNC( FIELD_INTEGER, "SetTeam", InputSetTeam ), | |||
DEFINE_INPUTFUNC( FIELD_VOID, "Kill", InputKill ), | |||
DEFINE_INPUTFUNC( FIELD_VOID, "KillHierarchy", InputKillHierarchy ), | |||
DEFINE_INPUTFUNC( FIELD_VOID, "Use", InputUse ), | |||
DEFINE_INPUTFUNC( FIELD_INTEGER, "Alpha", InputAlpha ), | |||
DEFINE_INPUTFUNC( FIELD_BOOLEAN, "AlternativeSorting", InputAlternativeSorting ), | |||
DEFINE_INPUTFUNC( FIELD_COLOR32, "Color", InputColor ), | |||
DEFINE_INPUTFUNC( FIELD_STRING, "SetParent", InputSetParent ), | |||
DEFINE_INPUTFUNC( FIELD_STRING, "SetParentAttachment", InputSetParentAttachment ), | |||
DEFINE_INPUTFUNC( FIELD_STRING, "SetParentAttachmentMaintainOffset", InputSetParentAttachmentMaintainOffset ), | |||
DEFINE_INPUTFUNC( FIELD_VOID, "ClearParent", InputClearParent ), | |||
DEFINE_INPUTFUNC( FIELD_STRING, "SetDamageFilter", InputSetDamageFilter ), | |||
DEFINE_INPUTFUNC( FIELD_VOID, "EnableDamageForces", InputEnableDamageForces ), | |||
DEFINE_INPUTFUNC( FIELD_VOID, "DisableDamageForces", InputDisableDamageForces ), | |||
DEFINE_INPUTFUNC( FIELD_STRING, "DispatchEffect", InputDispatchEffect ), | |||
DEFINE_INPUTFUNC( FIELD_STRING, "DispatchResponse", InputDispatchResponse ), | |||
// Entity I/O methods to alter context | |||
DEFINE_INPUTFUNC( FIELD_STRING, "AddContext", InputAddContext ), | |||
DEFINE_INPUTFUNC( FIELD_STRING, "RemoveContext", InputRemoveContext ), | |||
DEFINE_INPUTFUNC( FIELD_STRING, "ClearContext", InputClearContext ), | |||
DEFINE_INPUTFUNC( FIELD_VOID, "DisableShadow", InputDisableShadow ), | |||
DEFINE_INPUTFUNC( FIELD_VOID, "EnableShadow", InputEnableShadow ), | |||
DEFINE_INPUTFUNC( FIELD_STRING, "AddOutput", InputAddOutput ), | |||
DEFINE_INPUTFUNC( FIELD_STRING, "FireUser1", InputFireUser1 ), | |||
DEFINE_INPUTFUNC( FIELD_STRING, "FireUser2", InputFireUser2 ), | |||
DEFINE_INPUTFUNC( FIELD_STRING, "FireUser3", InputFireUser3 ), | |||
DEFINE_INPUTFUNC( FIELD_STRING, "FireUser4", InputFireUser4 ), | |||
DEFINE_OUTPUT( m_OnUser1, "OnUser1" ), | |||
DEFINE_OUTPUT( m_OnUser2, "OnUser2" ), | |||
DEFINE_OUTPUT( m_OnUser3, "OnUser3" ), | |||
DEFINE_OUTPUT( m_OnUser4, "OnUser4" ), | |||
// Function Pointers | |||
DEFINE_FUNCTION( SUB_Remove ), | |||
DEFINE_FUNCTION( SUB_DoNothing ), | |||
DEFINE_FUNCTION( SUB_StartFadeOut ), | |||
DEFINE_FUNCTION( SUB_StartFadeOutInstant ), | |||
DEFINE_FUNCTION( SUB_FadeOut ), | |||
DEFINE_FUNCTION( SUB_Vanish ), | |||
DEFINE_FUNCTION( SUB_CallUseToggle ), | |||
DEFINE_THINKFUNC( ShadowCastDistThink ), | |||
DEFINE_FIELD( m_hEffectEntity, FIELD_EHANDLE ), | |||
//DEFINE_FIELD( m_DamageModifiers, FIELD_?? ), // can't save? | |||
// DEFINE_FIELD( m_fDataObjectTypes, FIELD_INTEGER ), | |||
#ifdef TF_DLL | |||
DEFINE_ARRAY( m_nModelIndexOverrides, FIELD_INTEGER, MAX_VISION_MODES ), | |||
#endif | |||
END_DATADESC() | |||
// This table encodes the CBaseEntity data. | |||
IMPLEMENT_SERVERCLASS_ST_NOBASE( CBaseEntity, DT_BaseEntity ) | |||
SendPropDataTable( "AnimTimeMustBeFirst", 0, &REFERENCE_SEND_TABLE(DT_AnimTimeMustBeFirst), SendProxy_ClientSideAnimation ), | |||
SendPropInt (SENDINFO(m_flSimulationTime), SIMULATION_TIME_WINDOW_BITS, SPROP_UNSIGNED|SPROP_CHANGES_OFTEN|SPROP_ENCODED_AGAINST_TICKCOUNT, SendProxy_SimulationTime), | |||
#if PREDICTION_ERROR_CHECK_LEVEL > 1 | |||
SendPropVector (SENDINFO(m_vecOrigin), -1, SPROP_NOSCALE|SPROP_CHANGES_OFTEN, 0.0f, HIGH_DEFAULT, SendProxy_Origin ), | |||
#else | |||
SendPropVector (SENDINFO(m_vecOrigin), -1, SPROP_COORD|SPROP_CHANGES_OFTEN, 0.0f, HIGH_DEFAULT, SendProxy_Origin ), | |||
#endif | |||
SendPropInt (SENDINFO( m_ubInterpolationFrame ), NOINTERP_PARITY_MAX_BITS, SPROP_UNSIGNED ), | |||
SendPropModelIndex(SENDINFO(m_nModelIndex)), | |||
SendPropDataTable( SENDINFO_DT( m_Collision ), &REFERENCE_SEND_TABLE(DT_CollisionProperty) ), | |||
SendPropInt (SENDINFO(m_nRenderFX), 8, SPROP_UNSIGNED ), | |||
SendPropInt (SENDINFO(m_nRenderMode), 8, SPROP_UNSIGNED ), | |||
SendPropInt (SENDINFO(m_fEffects), EF_MAX_BITS, SPROP_UNSIGNED), | |||
SendPropInt (SENDINFO(m_clrRender), 32, SPROP_UNSIGNED), | |||
SendPropInt (SENDINFO(m_iTeamNum), TEAMNUM_NUM_BITS, 0), | |||
SendPropInt (SENDINFO(m_CollisionGroup), 5, SPROP_UNSIGNED), | |||
SendPropFloat (SENDINFO(m_flElasticity), 0, SPROP_COORD), | |||
SendPropFloat (SENDINFO(m_flShadowCastDistance), 12, SPROP_UNSIGNED ), | |||
SendPropEHandle (SENDINFO(m_hOwnerEntity)), | |||
SendPropEHandle (SENDINFO(m_hEffectEntity)), | |||
SendPropEHandle (SENDINFO_NAME(m_hMoveParent, moveparent)), | |||
SendPropInt (SENDINFO(m_iParentAttachment), NUM_PARENTATTACHMENT_BITS, SPROP_UNSIGNED), | |||
SendPropInt (SENDINFO_NAME( m_MoveType, movetype ), MOVETYPE_MAX_BITS, SPROP_UNSIGNED ), | |||
SendPropInt (SENDINFO_NAME( m_MoveCollide, movecollide ), MOVECOLLIDE_MAX_BITS, SPROP_UNSIGNED ), | |||
#if PREDICTION_ERROR_CHECK_LEVEL > 1 | |||
SendPropVector (SENDINFO(m_angRotation), -1, SPROP_NOSCALE|SPROP_CHANGES_OFTEN, 0, HIGH_DEFAULT, SendProxy_Angles ), | |||
#else | |||
SendPropQAngles (SENDINFO(m_angRotation), 13, SPROP_CHANGES_OFTEN, SendProxy_Angles ), | |||
#endif | |||
SendPropInt ( SENDINFO( m_iTextureFrameIndex ), 8, SPROP_UNSIGNED ), | |||
#if !defined( NO_ENTITY_PREDICTION ) | |||
SendPropDataTable( "predictable_id", 0, &REFERENCE_SEND_TABLE( DT_PredictableId ), SendProxy_SendPredictableId ), | |||
#endif | |||
// FIXME: Collapse into another flag field? | |||
SendPropInt (SENDINFO(m_bSimulatedEveryTick), 1, SPROP_UNSIGNED ), | |||
SendPropInt (SENDINFO(m_bAnimatedEveryTick), 1, SPROP_UNSIGNED ), | |||
SendPropBool( SENDINFO( m_bAlternateSorting )), | |||
#ifdef TF_DLL | |||
SendPropArray3( SENDINFO_ARRAY3(m_nModelIndexOverrides), SendPropInt( SENDINFO_ARRAY(m_nModelIndexOverrides), SP_MODEL_INDEX_BITS, 0 ) ), | |||
#endif | |||
END_SEND_TABLE() | |||
BEGIN_SEND_TABLE_NOBASE( CBaseEntity, DT_AnimTimeMustBeFirst ) | |||
// NOTE: Animtime must be sent before origin and angles ( from pev ) because it has a | |||
// proxy on the client that stores off the old values before writing in the new values and | |||
// if it is sent after the new values, then it will only have the new origin and studio model, etc. | |||
// interpolation will be busted | |||
SendPropInt (SENDINFO(m_flAnimTime), 8, SPROP_UNSIGNED|SPROP_CHANGES_OFTEN|SPROP_ENCODED_AGAINST_TICKCOUNT, SendProxy_AnimTime), | |||
END_SEND_TABLE() | |||
#if !defined( NO_ENTITY_PREDICTION ) | |||
BEGIN_SEND_TABLE_NOBASE( CBaseEntity, DT_PredictableId ) | |||
SendPropPredictableId( SENDINFO( m_PredictableID ) ), | |||
SendPropInt( SENDINFO( m_bIsPlayerSimulated ), 1, SPROP_UNSIGNED ), | |||
END_SEND_TABLE() | |||
</syntaxhighlight>}} | |||
=== Clientside === | === Clientside === |
Latest revision as of 10:56, 17 July 2025
Serverside
baseentity.h
//----------------------------------------------------------------------------- // Purpose: think contexts //----------------------------------------------------------------------------- struct thinkfunc_t { BASEPTR m_pfnThink; string_t m_iszContext; int m_nNextThinkTick; int m_nLastThinkTick; DECLARE_SIMPLE_DATADESC(); }; // // Base Entity. All entity types derive from this // class CBaseEntity : public IServerEntity { public: DECLARE_CLASS_NOBASE( CBaseEntity ); //---------------------------------------- // Class vars and functions //---------------------------------------- static inline void Debug_Pause(bool bPause); static inline bool Debug_IsPaused(void); static inline void Debug_SetSteps(int nSteps); static inline bool Debug_ShouldStep(void); static inline bool Debug_Step(void); static bool m_bInDebugSelect; static int m_nDebugPlayer; protected: static bool m_bDebugPause; // Whether entity i/o is paused for debugging. static int m_nDebugSteps; // Number of entity outputs to fire before pausing again. static bool sm_bDisableTouchFuncs; // Disables PhysicsTouch and PhysicsStartTouch function calls public: static bool sm_bAccurateTriggerBboxChecks; // SOLID_BBOX entities do a fully accurate trigger vs bbox check when this is set public: // If bServerOnly is true, then the ent never goes to the client. This is used // by logical entities. CBaseEntity( bool bServerOnly=false ); virtual ~CBaseEntity(); // prediction system DECLARE_PREDICTABLE(); // network data DECLARE_SERVERCLASS(); // data description DECLARE_DATADESC(); // memory handling void *operator new( size_t stAllocateBlock ); 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); } // Class factory static CBaseEntity *CreatePredictedEntityByName( const char *classname, const char *module, int line, bool persist = false ); // IHandleEntity overrides. public: virtual void SetRefEHandle( const CBaseHandle &handle ); virtual const CBaseHandle& GetRefEHandle() const; // IServerUnknown overrides virtual ICollideable *GetCollideable(); virtual IServerNetworkable *GetNetworkable(); virtual CBaseEntity *GetBaseEntity(); // IServerEntity overrides. public: virtual void SetModelIndex( int index ); virtual int GetModelIndex( void ) const; virtual string_t GetModelName( void ) const; void ClearModelIndexOverrides( void ); virtual void SetModelIndexOverride( int index, int nValue ); public: // virtual methods for derived classes to override virtual bool TestCollision( const Ray_t& ray, unsigned int mask, trace_t& trace ); virtual bool TestHitboxes( const Ray_t &ray, unsigned int fContentsMask, trace_t& tr ); virtual void ComputeWorldSpaceSurroundingBox( Vector *pWorldMins, Vector *pWorldMaxs ); // non-virtual methods. Don't override these! public: // An inline version the game code can use CCollisionProperty *CollisionProp(); const CCollisionProperty*CollisionProp() const; CServerNetworkProperty *NetworkProp(); const CServerNetworkProperty *NetworkProp() const; bool IsCurrentlyTouching( void ) const; const Vector& GetAbsOrigin( void ) const; const QAngle& GetAbsAngles( void ) const; SolidType_t GetSolid() const; int GetSolidFlags( void ) const; int GetEFlags() const; void SetEFlags( int iEFlags ); void AddEFlags( int nEFlagMask ); void RemoveEFlags( int nEFlagMask ); bool IsEFlagSet( int nEFlagMask ) const; // Quick way to ask if we have a player entity as a child anywhere in our hierarchy. void RecalcHasPlayerChildBit(); bool DoesHavePlayerChild(); bool IsTransparent() const; void SetNavIgnore( float duration = FLT_MAX ); void ClearNavIgnore(); bool IsNavIgnored() const; // Is the entity floating? bool IsFloating(); // Called by physics to see if we should avoid a collision test.... virtual bool ShouldCollide( int collisionGroup, int contentsMask ) const; // Move type / move collide MoveType_t GetMoveType() const; MoveCollide_t GetMoveCollide() const; void SetMoveType( MoveType_t val, MoveCollide_t moveCollide = MOVECOLLIDE_DEFAULT ); void SetMoveCollide( MoveCollide_t val ); // 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 ); // 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 ); public: void SetScaledPhysics( IPhysicsObject *pNewObject ); // virtual methods; you can override these public: // Owner entity. // FIXME: These are virtual only because of CNodeEnt CBaseEntity *GetOwnerEntity() const; virtual void SetOwnerEntity( CBaseEntity* pOwner ); void SetEffectEntity( CBaseEntity *pEffectEnt ); CBaseEntity *GetEffectEntity() const; // Only CBaseEntity implements these. CheckTransmit calls the virtual ShouldTransmit to see if the // entity wants to be sent. If so, it calls SetTransmit, which will mark any dependents for transmission too. virtual int ShouldTransmit( const CCheckTransmitInfo *pInfo ); // update the global transmit state if a transmission rule changed int SetTransmitState( int nFlag); int GetTransmitState( void ); int DispatchUpdateTransmitState(); // Do NOT call this directly. Use DispatchUpdateTransmitState. virtual int UpdateTransmitState(); // Entities (like ropes) use this to own the transmit state of another entity // by forcing it to not call UpdateTransmitState. void IncrementTransmitStateOwnedCounter(); void DecrementTransmitStateOwnedCounter(); // This marks the entity for transmission and passes the SetTransmit call to any dependents. virtual void SetTransmit( CCheckTransmitInfo *pInfo, bool bAlways ); // This function finds out if the entity is in the 3D skybox. If so, it sets the EFL_IN_SKYBOX // flag so the entity gets transmitted to all the clients. // Entities usually call this during their Activate(). // Returns true if the entity is in the skybox (and EFL_IN_SKYBOX was set). bool DetectInSkybox(); // Returns which skybox the entity is in CSkyCamera *GetEntitySkybox(); bool IsSimulatedEveryTick() const; bool IsAnimatedEveryTick() const; void SetSimulatedEveryTick( bool sim ); void SetAnimatedEveryTick( bool anim ); public: virtual const char *GetTracerType( void ); // returns a pointer to the entities edict, if it has one. should be removed! inline edict_t *edict( void ) { return NetworkProp()->edict(); } inline const edict_t *edict( void ) const { return NetworkProp()->edict(); } inline int entindex( ) const { return m_Network.entindex(); }; inline int GetSoundSourceIndex() const { return entindex(); } // 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(); // initialization virtual void Spawn( void ); virtual void Precache( void ) {} virtual void SetModel( const char *szModelName ); protected: // Notification on model load. May be called multiple times for dynamic models. // Implementations must call BaseClass::OnNewModel and pass return value through. virtual CStudioHdr *OnNewModel(); public: virtual void PostConstructor( const char *szClassname ); virtual void PostClientActive( void ); 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 ); void ValidateEntityConnections(); void FireNamedOutput( const char *pszOutput, variant_t variant, CBaseEntity *pActivator, CBaseEntity *pCaller, float flDelay = 0.0f ); // Activate - called for each entity after each load game and level load virtual void Activate( void ); // Hierarchy traversal CBaseEntity *GetMoveParent( void ); CBaseEntity *GetRootMoveParent(); CBaseEntity *FirstMoveChild( void ); CBaseEntity *NextMovePeer( void ); void SetName( string_t newTarget ); void SetParent( string_t newParent, CBaseEntity *pActivator, int iAttachment = -1 ); // 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. If iAttachment == -1, it'll preserve the // current m_iParentAttachment. virtual void SetParent( CBaseEntity* pNewParent, int iAttachment = -1 ); CBaseEntity* GetParent(); int GetParentAttachment(); string_t GetEntityName(); bool NameMatches( const char *pszNameOrWildcard ); bool ClassMatches( const char *pszClassOrWildcard ); bool NameMatches( string_t nameStr ); bool ClassMatches( string_t nameStr ); private: bool NameMatchesComplex( const char *pszNameOrWildcard ); bool ClassMatchesComplex( const char *pszClassOrWildcard ); void TransformStepData_WorldToParent( CBaseEntity *pParent ); void TransformStepData_ParentToParent( CBaseEntity *pOldParent, CBaseEntity *pNewParent ); void TransformStepData_ParentToWorld( CBaseEntity *pParent ); public: int GetSpawnFlags( void ) const; void AddSpawnFlags( int nFlags ); void RemoveSpawnFlags( int nFlags ); void ClearSpawnFlags( void ); bool HasSpawnFlags( int nFlags ) const; int GetEffects( void ) const; void AddEffects( int nEffects ); void RemoveEffects( int nEffects ); void ClearEffects( void ); void SetEffects( int nEffects ); bool IsEffectActive( int nEffects ) const; // makes the entity inactive void MakeDormant( void ); int IsDormant( void ); void RemoveDeferred( void ); // Sets the entity invisible, and makes it remove itself on the next frame // checks to see if the entity is marked for deletion bool IsMarkedForDeletion( void ); // capabilities virtual int ObjectCaps( void ); // Verifies that the data description is valid in debug builds. #ifdef _DEBUG void ValidateDataDescription(void); #endif // _DEBUG // handles an input (usually caused by outputs) // returns true if the the value in the pass in should be set, false if the input is to be ignored virtual bool AcceptInput( const char *szInputName, CBaseEntity *pActivator, CBaseEntity *pCaller, variant_t Value, int outputID ); // // Input handlers. // void InputAlternativeSorting( inputdata_t &inputdata ); void InputAlpha( inputdata_t &inputdata ); void InputColor( inputdata_t &inputdata ); void InputSetParent( inputdata_t &inputdata ); void SetParentAttachment( const char *szInputName, const char *szAttachment, bool bMaintainOffset ); void InputSetParentAttachment( inputdata_t &inputdata ); void InputSetParentAttachmentMaintainOffset( inputdata_t &inputdata ); void InputClearParent( inputdata_t &inputdata ); void InputSetTeam( inputdata_t &inputdata ); void InputUse( inputdata_t &inputdata ); void InputKill( inputdata_t &inputdata ); void InputKillHierarchy( inputdata_t &inputdata ); void InputSetDamageFilter( inputdata_t &inputdata ); void InputDispatchEffect( inputdata_t &inputdata ); void InputEnableDamageForces( inputdata_t &inputdata ); void InputDisableDamageForces( inputdata_t &inputdata ); void InputAddContext( inputdata_t &inputdata ); void InputRemoveContext( inputdata_t &inputdata ); void InputClearContext( inputdata_t &inputdata ); void InputDispatchResponse( inputdata_t& inputdata ); void InputDisableShadow( inputdata_t &inputdata ); void InputEnableShadow( inputdata_t &inputdata ); void InputAddOutput( inputdata_t &inputdata ); void InputFireUser1( inputdata_t &inputdata ); void InputFireUser2( inputdata_t &inputdata ); void InputFireUser3( inputdata_t &inputdata ); void InputFireUser4( inputdata_t &inputdata ); // Returns the origin at which to play an inputted dispatcheffect virtual void GetInputDispatchEffectPosition( const char *sInputString, Vector &pOrigin, QAngle &pAngles ); // tries to read a field from the entities data description - result is placed in variant_t bool ReadKeyField( const char *varName, variant_t *var ); // classname access void SetClassname( const char *className ); const char* GetClassname(); // Debug Overlays void EntityText( int text_offset, const char *text, float flDuration, int r = 255, int g = 255, int b = 255, int a = 255 ); const char *GetDebugName(void); // do not make this virtual -- designed to handle NULL this virtual void DrawDebugGeometryOverlays(void); virtual int DrawDebugTextOverlays(void); void DrawTimedOverlays( void ); void DrawBBoxOverlay( float flDuration = 0.0f ); void DrawAbsBoxOverlay(); void DrawRBoxOverlay(); void DrawInputOverlay(const char *szInputName, CBaseEntity *pCaller, variant_t Value); void DrawOutputOverlay(CEventAction *ev); void SendDebugPivotOverlay( void ); void AddTimedOverlay( const char *msg, int endTime ); void SetSolid( SolidType_t val ); // save/restore // only overload these if you have special data to serialize virtual int Save( ISave &save ); virtual int Restore( IRestore &restore ); virtual bool ShouldSavePhysics(); // handler to reset stuff before you are restored // NOTE: Always chain to base class when implementing this! virtual void OnSave( IEntitySaveUtils *pSaveUtils ); // handler to reset stuff after you are restored // called after all entities have been loaded from all affected levels // called before activate // NOTE: Always chain to base class when implementing this! virtual void OnRestore(); int GetTextureFrameIndex( void ); void SetTextureFrameIndex( int iIndex ); // 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 ); private: int SaveDataDescBlock( ISave &save, datamap_t *dmap ); int RestoreDataDescBlock( IRestore &restore, datamap_t *dmap ); public: // Networking related methods void NetworkStateChanged(); void NetworkStateChanged( void *pVar ); public: void CalcAbsolutePosition(); // returns the edict index the entity requires when used in save/restore (eg players, world) // -1 means it doesn't require any special index virtual int RequiredEdictIndex( void ) { return -1; } // interface function pts void (CBaseEntity::*m_pfnMoveDone)(void); virtual void MoveDone( void ) { if (m_pfnMoveDone) (this->*m_pfnMoveDone)();}; // Why do we have two separate static Instance functions? static CBaseEntity *Instance( const CBaseHandle &hEnt ); static CBaseEntity *Instance( const edict_t *pent ); static CBaseEntity *Instance( edict_t *pent ); static CBaseEntity* Instance( int iEnt ); // Think function handling void (CBaseEntity::*m_pfnThink)(void); virtual void Think( void ) { if (m_pfnThink) (this->*m_pfnThink)();}; // 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 ); float GetAnimTime() const; void SetAnimTime( float at ); float GetSimulationTime() const; void SetSimulationTime( float st ); void SetRenderMode( RenderMode_t nRenderMode ); RenderMode_t GetRenderMode() const; private: // NOTE: Keep this near vtable so it's in cache with vtable. CServerNetworkProperty m_Network; public: // members string_t m_iClassname; // identifier for entity creation and save/restore string_t m_iGlobalname; // identifier for carrying entity across level transitions string_t m_iParent; // the name of the entities parent; linked into m_pParent during Activate() int m_iHammerID; // Hammer unique edit id number public: // was pev->speed float m_flSpeed; // was pev->renderfx CNetworkVar( unsigned char, m_nRenderFX ); // was pev->rendermode CNetworkVar( unsigned char, m_nRenderMode ); CNetworkVar( short, m_nModelIndex ); #ifdef TF_DLL CNetworkArray( int, m_nModelIndexOverrides, MAX_VISION_MODES ); // used to override the base model index on the client if necessary #endif // was pev->rendercolor CNetworkColor32( m_clrRender ); 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 ); // was pev->animtime: consider moving to CBaseAnimating float m_flPrevAnimTime; CNetworkVar( float, m_flAnimTime ); // this is the point in time that the client will interpolate to position,angle,frame,etc. CNetworkVar( float, m_flSimulationTime ); void IncrementInterpolationFrame(); // Call this to cause a discontinuity (teleport) CNetworkVar( int, m_ubInterpolationFrame ); int m_nLastThinkTick; #if !defined( NO_ENTITY_PREDICTION ) // Certain entities (projectiles) can be created on the client and thus need a matching id number CNetworkVar( CPredictableId, m_PredictableID ); #endif // used so we know when things are no longer touching int touchStamp; protected: // think function handling enum thinkmethods_t { THINK_FIRE_ALL_FUNCTIONS, THINK_FIRE_BASE_ONLY, THINK_FIRE_ALL_BUT_BASE, }; int GetIndexForThinkContext( const char *pszContext ); CUtlVector< thinkfunc_t > m_aThinkFunctions; #ifdef _DEBUG int m_iCurrentThinkContext; #endif void RemoveExpiredConcepts( void ); int GetContextCount() const; // Call RemoveExpiredConcepts to clean out expired concepts const char *GetContextName( int index ) const; // note: context may be expired const char *GetContextValue( int index ) const; // note: context may be expired bool ContextExpired( int index ) const; int FindContextByName( const char *name ) const; public: void AddContext( const char *nameandvalue ); protected: CUtlVector< ResponseContext_t > m_ResponseContexts; // Map defined context sets string_t m_iszResponseContext; private: CBaseEntity( CBaseEntity& ); // list handling friend class CGlobalEntityList; friend class CThinkSyncTester; // was pev->nextthink CNetworkVarForDerived( int, m_nNextThinkTick ); // was pev->effects CNetworkVar( int, m_fEffects ); //////////////////////////////////////////////////////////////////////////// public: // Returns a CBaseAnimating if the entity is derived from CBaseAnimating. virtual CBaseAnimating* GetBaseAnimating() { return 0; } virtual IResponseSystem *GetResponseSystem(); virtual void DispatchResponse( const char *conceptName ); // Classify - returns the type of group (i.e, "houndeye", or "human military" so that NPCs with different classnames // still realize that they are teammates. (overridden for NPCs that form groups) virtual Class_T Classify ( void ); virtual void DeathNotice ( CBaseEntity *pVictim ) {}// NPC maker children use this to tell the NPC maker that they have died. virtual bool ShouldAttractAutoAim( CBaseEntity *pAimingEnt ) { return ((GetFlags() & FL_AIMTARGET) != 0); } virtual float GetAutoAimRadius(); virtual Vector GetAutoAimCenter() { return WorldSpaceCenter(); } virtual ITraceFilter* GetBeamTraceFilter( void ); // Call this to do a TraceAttack on an entity, performs filtering. Don't call TraceAttack() directly except when chaining up to base class void DispatchTraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr, CDmgAccumulator *pAccumulator = NULL ); virtual bool PassesDamageFilter( const CTakeDamageInfo &info ); protected: virtual void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr, CDmgAccumulator *pAccumulator = NULL ); public: virtual bool CanBeHitByMeleeAttack( CBaseEntity *pAttacker ) { return true; } // returns the amount of damage inflicted virtual int OnTakeDamage( const CTakeDamageInfo &info ); // This is what you should call to apply damage to an entity. int TakeDamage( const CTakeDamageInfo &info ); virtual void AdjustDamageDirection( const CTakeDamageInfo &info, Vector &dir, CBaseEntity *pEnt ) {} virtual int TakeHealth( float flHealth, int bitsDamageType ); virtual bool IsAlive( void ); // Entity killed (only fired once) virtual void Event_Killed( const CTakeDamageInfo &info ); void SendOnKilledGameEvent( const CTakeDamageInfo &info ); // Notifier that I've killed some other entity. (called from Victim's Event_Killed). virtual void Event_KilledOther( CBaseEntity *pVictim, const CTakeDamageInfo &info ) { return; } // UNDONE: Make this data? virtual int BloodColor( void ); void TraceBleed( float flDamage, const Vector &vecDir, trace_t *ptr, int bitsDamageType ); virtual bool IsTriggered( CBaseEntity *pActivator ) {return true;} virtual bool IsNPC( void ) const { return false; } CAI_BaseNPC *MyNPCPointer( void ); virtual CBaseCombatCharacter *MyCombatCharacterPointer( void ) { return NULL; } virtual INextBot *MyNextBotPointer( void ) { return NULL; } virtual float GetDelay( void ) { return 0; } virtual bool IsMoving( void ); bool IsWorld() { return entindex() == 0; } 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 = NULL ); void AddPoints( int score, bool bAllowNegativeScore ); void AddPointsToTeam( int score, bool bAllowNegativeScore ); void RemoveAllDecals( void ); virtual bool OnControls( CBaseEntity *pControls ) { return false; } virtual bool HasTarget( string_t targetname ); virtual bool IsPlayer( void ) const { return false; } virtual bool IsNetClient( void ) const { return false; } virtual bool IsTemplate( void ) { return false; } virtual bool IsBaseObject( void ) const { return false; } virtual bool IsBaseTrain( void ) const { return false; } bool IsBSPModel() const; bool IsCombatCharacter() { return MyCombatCharacterPointer() == NULL ? false : true; } bool IsInWorld( void ) const; virtual bool IsCombatItem( void ) const { return false; } virtual bool IsBaseCombatWeapon( void ) const { return false; } virtual bool IsWearable( void ) const { return false; } virtual CBaseCombatWeapon *MyCombatWeaponPointer( void ) { return NULL; } // If this is a vehicle, returns the vehicle interface virtual IServerVehicle* GetServerVehicle() { return NULL; } // UNDONE: Make this data instead of procedural? virtual bool IsViewable( void ); // is this something that would be looked at (model, sprite, etc.)? // Team Handling CTeam *GetTeam( void ) const; // Get the Team this entity is on int GetTeamNumber( void ) const; // Get the Team number of the team this entity is on virtual void ChangeTeam( int iTeamNum ); // Assign this entity to a team. bool IsInTeam( CTeam *pTeam ) const; // Returns true if this entity's in the specified team bool InSameTeam( CBaseEntity *pEntity ) const; // Returns true if the specified entity is on the same team as this one bool IsInAnyTeam( void ) const; // Returns true if this entity is in any team const char *TeamID( void ) const; // Returns the name of the team this entity is on. // Entity events... these are events targetted to a particular entity // Each event defines its own well-defined event data structure virtual void OnEntityEvent( EntityEvent_t event, void *pEventData ); // can stand on this entity? bool IsStandable() const; // UNDONE: Do these three functions actually need to be virtual??? virtual bool CanStandOn( CBaseEntity *pSurface ) const { return (pSurface && !pSurface->IsStandable()) ? false : true; } virtual bool CanStandOn( edict_t *ent ) const { return CanStandOn( GetContainingEntity( ent ) ); } virtual CBaseEntity *GetEnemy( void ) { return NULL; } virtual CBaseEntity *GetEnemy( void ) const { return NULL; } void ViewPunch( const QAngle &angleOffset ); void VelocityPunch( const Vector &vecForce ); CBaseEntity *GetNextTarget( void ); // fundamental callbacks void (CBaseEntity ::*m_pfnTouch)( CBaseEntity *pOther ); void (CBaseEntity ::*m_pfnUse)( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); void (CBaseEntity ::*m_pfnBlocked)( CBaseEntity *pOther ); virtual void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); virtual void StartTouch( CBaseEntity *pOther ); virtual void Touch( CBaseEntity *pOther ); virtual void EndTouch( CBaseEntity *pOther ); virtual void StartBlocked( CBaseEntity *pOther ) {} virtual void Blocked( CBaseEntity *pOther ); virtual void EndBlocked( void ) {} // Physics simulation virtual void PhysicsSimulate( void ); public: // 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( CBaseEntity *other, trace_t &trace ); void PhysicsMarkEntitiesAsTouching( CBaseEntity *other, trace_t &trace ); void PhysicsMarkEntitiesAsTouchingEventDriven( CBaseEntity *other, trace_t &trace ); void PhysicsTouchTriggers( const Vector *pPrevAbsOrigin = NULL ); // Physics helper static void PhysicsRemoveTouchedList( CBaseEntity *ent ); static void PhysicsNotifyOtherOfUntouch( CBaseEntity *ent, CBaseEntity *other ); static void PhysicsRemoveToucher( CBaseEntity *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(); virtual void UpdateOnRemove( void ); virtual void StopLoopingSounds( void ) {} // common member functions void SUB_Remove( void ); void SUB_DoNothing( void ); void SUB_StartFadeOut( float delay = 10.0f, bool bNotSolid = true ); void SUB_StartFadeOutInstant(); void SUB_FadeOut ( void ); void SUB_Vanish( void ); void SUB_CallUseToggle( void ) { this->Use( this, this, USE_TOGGLE, 0 ); } void SUB_PerformFadeOut( void ); virtual bool SUB_AllowedToFade( void ); // change position, velocity, orientation instantly // passing NULL means no change virtual void Teleport( const Vector *newPosition, const QAngle *newAngles, const Vector *newVelocity ); // notify that another entity (that you were watching) was teleported virtual void NotifySystemEvent( CBaseEntity *pNotify, notify_system_event_t eventType, const notify_system_event_params_t ¶ms ); int ShouldToggle( USE_TYPE useType, int currentState ); // UNDONE: Move these virtuals to CBaseCombatCharacter? virtual void MakeTracer( const Vector &vecTracerSrc, const trace_t &tr, int iTracerType ); virtual int GetTracerAttachment( void ); virtual void FireBullets( const FireBulletsInfo_t &info ); virtual void DoImpactEffect( trace_t &tr, int nDamageType ); // give shooter a chance to do a custom impact. // OLD VERSION! Use the struct version void FireBullets( int cShots, const Vector &vecSrc, const Vector &vecDirShooting, const Vector &vecSpread, float flDistance, int iAmmoType, int iTracerFreq = 4, int firingEntID = -1, int attachmentID = -1, int iDamage = 0, CBaseEntity *pAttacker = NULL, bool bFirstShotAccurate = false, bool bPrimaryAttack = true ); virtual void ModifyFireBulletsDamage( CTakeDamageInfo* dmgInfo ) {} virtual CBaseEntity *Respawn( void ) { return NULL; } // Method used to deal with attacks passing through triggers void TraceAttackToTriggers( const CTakeDamageInfo &info, const Vector& start, const Vector& end, const Vector& dir ); // Do the bounding boxes of these two intersect? bool Intersects( CBaseEntity *pOther ); virtual bool IsLockedByMaster( void ) { return false; } // Health accessors. virtual int GetMaxHealth() const { return m_iMaxHealth; } void SetMaxHealth( int amt ) { m_iMaxHealth = amt; } int GetHealth() const { return m_iHealth; } void SetHealth( int amt ) { m_iHealth = amt; } float HealthFraction() const; // Ugly code to lookup all functions to make sure they are in the table when set. #ifdef _DEBUG #ifdef GNUC #define ENTITYFUNCPTR_SIZE 8 #else #define ENTITYFUNCPTR_SIZE 4 #endif void FunctionCheck( void *pFunction, const char *name ); ENTITYFUNCPTR TouchSet( ENTITYFUNCPTR func, char *name ) { COMPILE_TIME_ASSERT( sizeof(func) == ENTITYFUNCPTR_SIZE ); m_pfnTouch = func; FunctionCheck( *(reinterpret_cast<void **>(&m_pfnTouch)), name ); return func; } USEPTR UseSet( USEPTR func, char *name ) { COMPILE_TIME_ASSERT( sizeof(func) == ENTITYFUNCPTR_SIZE ); m_pfnUse = func; FunctionCheck( *(reinterpret_cast<void **>(&m_pfnUse)), name ); return func; } ENTITYFUNCPTR BlockedSet( ENTITYFUNCPTR func, char *name ) { COMPILE_TIME_ASSERT( sizeof(func) == ENTITYFUNCPTR_SIZE ); m_pfnBlocked = func; FunctionCheck( *(reinterpret_cast<void **>(&m_pfnBlocked)), name ); return func; } #endif // _DEBUG virtual void ModifyOrAppendCriteria( AI_CriteriaSet& set ); void AppendContextToCriteria( AI_CriteriaSet& set, const char *prefix = "" ); void DumpResponseCriteria( void ); // 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; private: friend class CAI_Senses; CBaseEntity *m_pLink;// used for temporary link-list operations. public: // variables promoted from edict_t string_t m_target; CNetworkVarForDerived( int, m_iMaxHealth ); // CBaseEntity doesn't care about changes to this variable, but there are derived classes that do. CNetworkVarForDerived( int, m_iHealth ); CNetworkVarForDerived( char, m_lifeState ); CNetworkVarForDerived( char , m_takedamage ); // Damage filtering string_t m_iszDamageFilterName; // The name of the entity to use as our damage filter. EHANDLE m_hDamageFilter; // The entity that controls who can damage us. // Debugging / devolopment fields int m_debugOverlays; // For debug only (bitfields) TimedOverlay_t* m_pTimedOverlay; // For debug only // virtual functions used by a few classes // creates an entity of a specified class, by name static CBaseEntity *Create( const char *szName, const Vector &vecOrigin, const QAngle &vecAngles, CBaseEntity *pOwner = NULL ); static CBaseEntity *CreateNoSpawn( const char *szName, const Vector &vecOrigin, const QAngle &vecAngles, CBaseEntity *pOwner = NULL ); // Collision group accessors int GetCollisionGroup() const; void SetCollisionGroup( int collisionGroup ); void CollisionRulesChanged(); // Damage accessors virtual int GetDamageType() const; virtual float GetDamage() { return 0; } virtual void SetDamage(float flDamage) {} virtual Vector EyePosition( void ); // position of eyes virtual const QAngle &EyeAngles( void ); // Direction of eyes in world space virtual const QAngle &LocalEyeAngles( void ); // Direction of eyes virtual Vector EarPosition( void ); // position of ears 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 virtual Vector BodyTarget( const Vector &posSrc, bool bNoisy = true); // position to shoot at virtual Vector HeadTarget( const Vector &posSrc ); virtual void GetVectors(Vector* forward, Vector* right, Vector* up) const; virtual const Vector &GetViewOffset() const; virtual void SetViewOffset( const Vector &v ); // 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 ApplyLocalVelocityImpulse( const Vector &vecImpulse ); void SetAbsVelocity( const Vector &vecVelocity ); void ApplyAbsVelocityImpulse( const Vector &vecImpulse ); void ApplyLocalAngularVelocityImpulse( const AngularImpulse &angImpulse ); const Vector& GetLocalVelocity( ) const; const Vector& GetAbsVelocity( ) const; // 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; // FIXME: While we're using (dPitch, dYaw, dRoll) as our local angular velocity // representation, we can't actually solve this problem // void SetAbsAngularVelocity( const QAngle &vecAngVelocity ); // const QAngle& GetAbsAngularVelocity( ) const; const Vector& GetBaseVelocity() const; void SetBaseVelocity( const Vector& v ); virtual Vector GetSmoothedVelocity( void ); // FIXME: Figure out what to do about this virtual void GetVelocity(Vector *vVelocity, AngularImpulse *vAngVelocity = NULL); float GetGravity( void ) const; void SetGravity( float gravity ); float GetFriction( void ) const; void SetFriction( float flFriction ); virtual bool FVisible ( CBaseEntity *pEntity, int traceMask = MASK_BLOCKLOS, CBaseEntity **ppBlocker = NULL ); virtual bool FVisible( const Vector &vecTarget, int traceMask = MASK_BLOCKLOS, CBaseEntity **ppBlocker = NULL ); virtual bool CanBeSeenBy( CAI_BaseNPC *pNPC ) { return true; } // allows entities to be 'invisible' to NPC senses. // 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( CBaseEntity *pVictim ); // This returns a value that scales all damage done to this entity // Use CDamageModifier to hook in damage modifiers on a guy. virtual float GetReceivedDamageScale( CBaseEntity *pAttacker ); void SetCheckUntouch( bool check ); bool GetCheckUntouch() const; void SetGroundEntity( CBaseEntity *ground ); CBaseEntity *GetGroundEntity( void ); CBaseEntity *GetGroundEntity( void ) const { return const_cast<CBaseEntity *>(this)->GetGroundEntity(); } // Gets the velocity we impart to a player standing on us virtual void GetGroundVelocityToApply( Vector &vecGroundVel ) { vecGroundVel = vec3_origin; } int GetWaterLevel() const; void SetWaterLevel( int nLevel ); int GetWaterType() const; void SetWaterType( int nType ); virtual bool PhysicsSplash( const Vector ¢erPoint, const Vector &normal, float rawSpeed, float scaledSpeed ) { return false; } virtual void Splash() {} void ClearSolidFlags( void ); void RemoveSolidFlags( int flags ); void AddSolidFlags( int flags ); bool IsSolidFlagSet( int flagMask ) const; void SetSolidFlags( int flags ); bool IsSolid() const; void SetModelName( string_t name ); model_t *GetModel( void ); // 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 const Vector& WorldAlignMins( ) const; const Vector& WorldAlignMaxs( ) const; // This defines collision bounds in OBB space void SetCollisionBounds( const Vector& mins, const Vector &maxs ); // NOTE: The world space center *may* move when the entity rotates. virtual const Vector& WorldSpaceCenter( ) const; const Vector& WorldAlignSize( ) 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; bool IsPointSized() const; // NOTE: Setting the abs origin or angles will cause the local origin + angles to be set also void SetAbsOrigin( const Vector& origin ); void SetAbsAngles( const QAngle& angles ); // Origin and angles in local space ( relative to parent ) // NOTE: Setting the local origin or angles will cause the abs origin + angles to be set also void SetLocalOrigin( const Vector& origin ); const Vector& GetLocalOrigin( void ) const; void SetLocalAngles( const QAngle& angles ); const QAngle& GetLocalAngles( void ) const; void SetElasticity( float flElasticity ); float GetElasticity( void ) const; void SetShadowCastDistance( float flDistance ); float GetShadowCastDistance( void ) const; void SetShadowCastDistance( float flDesiredDistance, float flDelay ); float GetLocalTime( void ) const; void IncrementLocalTime( float flTimeDelta ); float GetMoveDoneTime( ) const; void SetMoveDoneTime( float flTime ); // Used by the PAS filters to ask the entity where in world space the sounds it emits come from. // This is used right now because if you have something sitting on an incline, using our axis-aligned // bounding boxes can return a position in solid space, so you won't hear sounds emitted by the object. // For now, we're hacking around it by moving the sound emission origin up on certain objects like vehicles. // // When OBBs get in, this can probably go away. virtual Vector GetSoundEmissionOrigin() const; void AddFlag( int flags ); void RemoveFlag( int flagsToRemove ); void ToggleFlag( int flagToToggle ); int GetFlags( void ) const; void ClearFlags( void ); // Sets the local position from a transform void SetLocalTransform( const matrix3x4_t &localTransform ); // See CSoundEmitterSystem void EmitSound( const char *soundname, float soundtime = 0.0f, float *duration = NULL ); // Override for doing the general case of CPASAttenuationFilter filter( 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 filter( 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 ); virtual void ModifyEmitSoundParams( EmitSound_t ¶ms ); static float GetSoundDuration( const char *soundname, char const *actormodel ); static bool GetParametersForSound( const char *soundname, CSoundParameters ¶ms, char const *actormodel ); static bool GetParametersForSound( const char *soundname, HSOUNDSCRIPTHANDLE& handle, CSoundParameters ¶ms, char const *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 & params ); static void EmitSound( IRecipientFilter& filter, int iEntIndex, const EmitSound_t & params, 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( CRecipientFilter& filter ); static void EmitCloseCaption( IRecipientFilter& filter, int entindex, char const *token, CUtlVector< Vector >& soundorigins, float duration, bool warnifmissing = false ); static void EmitSentenceByIndex( IRecipientFilter& filter, int iEntIndex, int iChannel, int iSentenceIndex, float flVolume, soundlevel_t iSoundlevel, int iFlags = 0, int iPitch = PITCH_NORM, const Vector *pOrigin = NULL, const Vector *pDirection = NULL, bool bUpdatePositions = true, float soundtime = 0.0f ); static bool IsPrecacheAllowed(); static void SetAllowPrecache( bool allow ); static bool m_bAllowPrecache; static bool IsSimulatingOnAlternateTicks(); virtual bool IsDeflectable() { return false; } virtual void Deflected( CBaseEntity *pDeflectedBy, Vector &vecDir ) {} // void Relink() {} public: // VPHYSICS Integration ----------------------------------------------- // // -------------------------------------------------------------------- // UNDONE: Move to IEntityVPhysics? or VPhysicsProp() ? // 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 - physics determines where it goes (gravity, friction, etc) // and the entity receives updates from vphysics. SetAbsOrigin(), etc do not affect the 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 ); // Force a non-solid (ie. solid_trigger) physics object to collide with other entities. virtual bool ForceVPhysicsCollide( CBaseEntity *pEntity ) { return false; } 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 ); void VPhysicsSwapObject( IPhysicsObject *pSwap ); inline IPhysicsObject *VPhysicsGetObject( void ) const { return m_pPhysicsObject; } virtual void VPhysicsUpdate( IPhysicsObject *pPhysics ); void VPhysicsUpdatePusher( IPhysicsObject *pPhysics ); // react physically to damage (called from CBaseEntity::OnTakeDamage() by default) virtual int VPhysicsTakeDamage( const CTakeDamageInfo &info ); virtual void VPhysicsShadowCollision( int index, gamevcollisionevent_t *pEvent ); virtual void VPhysicsShadowUpdate( IPhysicsObject *pPhysics ) {} virtual void VPhysicsCollision( int index, gamevcollisionevent_t *pEvent ); virtual void VPhysicsFriction( IPhysicsObject *pObject, float energy, int surfaceProps, int surfacePropsHit ); // update the shadow so it will coincide with the current AI position at some time // in the future (or 0 for now) virtual void UpdatePhysicsShadowToCurrentPosition( float deltaTime ); virtual int VPhysicsGetObjectList( IPhysicsObject **pList, int listMax ); virtual bool VPhysicsIsFlesh( void ); // -------------------------------------------------------------------- public: #if !defined( NO_ENTITY_PREDICTION ) // The player drives simulation of this entity void SetPlayerSimulated( CBasePlayer *pOwner ); void UnsetPlayerSimulated( void ); bool IsPlayerSimulated( void ) const; CBasePlayer *GetSimulatingPlayer( void ); #endif // FIXME: Make these private! void PhysicsCheckForEntityUntouch( void ); bool PhysicsRunThink( thinkmethods_t thinkMethod = THINK_FIRE_ALL_FUNCTIONS ); bool PhysicsRunSpecificThink( int nContextIndex, BASEPTR thinkFunc ); bool PhysicsTestEntityPosition( CBaseEntity **ppEntity = NULL ); void PhysicsPushEntity( const Vector& push, trace_t *pTrace ); bool PhysicsCheckWater( void ); void PhysicsCheckWaterTransition( void ); void PhysicsStepRecheckGround(); // Computes the water level + type void UpdateWaterState(); bool IsEdictFree() const { return edict()->IsFree(); } // Callbacks for the physgun/cannon picking up an entity virtual CBasePlayer *HasPhysicsAttacker( float dt ) { return NULL; } // UNDONE: Make this data? virtual unsigned int PhysicsSolidMaskForEntity( void ) const; // 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 ); void SetPredictionEligible( bool canpredict ); protected: // Invalidates the abs state of all children void InvalidatePhysicsRecursive( int nChangeFlags ); int PhysicsClipVelocity (const Vector& in, const Vector& normal, Vector& out, float overbounce ); void PhysicsRelinkChildren( float dt ); // 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 ); virtual void ResolveFlyCollisionCustom( trace_t &trace, Vector &vecVelocity ); private: // Physics-related private methods void PhysicsStep( void ); void PhysicsPusher( void ); void PhysicsNone( void ); void PhysicsNoclip( void ); void PhysicsStepRunTimestep( float timestep ); void PhysicsToss( void ); void PhysicsCustom( void ); void PerformPush( float movetime ); // Simulation in local space of rigid children void PhysicsRigidChild( void ); // Computes the base velocity void UpdateBaseVelocity( void ); // Implement this if you use MOVETYPE_CUSTOM virtual void PerformCustomPhysics( Vector *pNewPosition, Vector *pNewVelocity, QAngle *pNewAngles, QAngle *pNewAngVelocity ); void PhysicsDispatchThink( BASEPTR thinkFunc ); touchlink_t *PhysicsMarkEntityAsTouched( CBaseEntity *other ); void PhysicsTouch( CBaseEntity *pentOther ); void PhysicsStartTouch( CBaseEntity *pentOther ); CBaseEntity *PhysicsPushMove( float movetime ); CBaseEntity *PhysicsPushRotate( float movetime ); CBaseEntity *PhysicsCheckRotateMove( rotatingpushmove_t &rotPushmove, CBaseEntity **pPusherList, int pusherListCount ); CBaseEntity *PhysicsCheckPushMove( const Vector& move, CBaseEntity **pPusherList, int pusherListCount ); int PhysicsTryMove( float flTime, trace_t *steptrace ); void PhysicsCheckVelocity( void ); void PhysicsAddHalfGravity( float timestep ); void PhysicsAddGravityMove( Vector &move ); void CalcAbsoluteVelocity(); void CalcAbsoluteAngularVelocity(); // Checks a sweep without actually performing the move void PhysicsCheckSweep( const Vector& vecAbsStart, const Vector &vecAbsDelta, trace_t *pTrace ); // Computes new angles based on the angular velocity void SimulateAngles( float flFrameTime ); void CheckStepSimulationChanged(); // Run regular think and latch off angle/origin changes so we can interpolate them on the server to fake simulation void StepSimulationThink( float dt ); // Compute network origin private: void ComputeStepSimulationNetwork( StepSimulationData *step ); public: bool UseStepSimulationNetworkOrigin( const Vector **out_v ); bool UseStepSimulationNetworkAngles( const QAngle **out_a ); public: // Add a discontinuity to a step bool AddStepDiscontinuity( float flTime, const Vector &vecOrigin, const QAngle &vecAngles ); int GetFirstThinkTick(); // get first tick thinking on any context private: // origin and angles to use in step calculations virtual Vector GetStepOrigin( void ) const; virtual QAngle GetStepAngles( void ) const; // These set entity flags (EFL_*) to help optimize queries void CheckHasThinkFunction( bool isThinkingHint = false ); void CheckHasGamePhysicsSimulation(); bool WillThink(); bool WillSimulateGamePhysics(); friend class CPushBlockerEnum; // 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; // Shot statistics void UpdateShotStatistics( const trace_t &tr ); // Handle shot entering water bool HandleShotImpactingWater( const FireBulletsInfo_t &info, const Vector &vecEnd, ITraceFilter *pTraceFilter, Vector *pVecTracerDest ); // Handle shot entering water void HandleShotImpactingGlass( const FireBulletsInfo_t &info, const trace_t &tr, const Vector &vecDir, ITraceFilter *pTraceFilter ); // Should we draw bubbles underwater? bool ShouldDrawUnderwaterBulletBubbles(); // Computes the tracer start position void ComputeTracerStartPosition( const Vector &vecShotSrc, Vector *pVecTracerStart ); // Computes the tracer start position void CreateBubbleTrailTracer( const Vector &vecShotSrc, const Vector &vecShotEnd, const Vector &vecShotDir ); virtual bool ShouldDrawWaterImpacts() { return true; } // Changes shadow cast distance over time void ShadowCastDistThink( ); // Precache model sounds + particles static void PrecacheModelComponents( int nModelIndex ); static void PrecacheSoundHelper( const char *pName ); protected: // Which frame did I simulate? int m_nSimulationTick; // FIXME: Make this private! Still too many references to do so... CNetworkVar( int, m_spawnflags ); private: int m_iEFlags; // entity flags EFL_* // was pev->flags CNetworkVarForDerived( int, m_fFlags ); string_t m_iName; // name used to identify this entity // Damage modifiers friend class CDamageModifier; CUtlLinkedList<CDamageModifier*,int> m_DamageModifiers; EHANDLE m_pParent; // for movement hierarchy byte m_nTransmitStateOwnedCounter; CNetworkVar( unsigned char, m_iParentAttachment ); // 0 if we're relative to the parent's absorigin and absangles. CNetworkVar( unsigned char, m_MoveType ); // One of the MOVETYPE_ defines. CNetworkVar( unsigned char, m_MoveCollide ); // Our immediate parent in the movement hierarchy. // FIXME: clarify m_pParent vs. m_pMoveParent CNetworkHandle( CBaseEntity, m_hMoveParent ); // cached child list EHANDLE m_hMoveChild; // generated from m_pMoveParent EHANDLE m_hMovePeer; friend class CCollisionProperty; friend class CServerNetworkProperty; CNetworkVarEmbedded( CCollisionProperty, m_Collision ); CNetworkHandle( CBaseEntity, m_hOwnerEntity ); // only used to point to an edict it won't collide with CNetworkHandle( CBaseEntity, m_hEffectEntity ); // Fire/Dissolve entity. CNetworkVar( int, m_CollisionGroup ); // used to cull collision tests IPhysicsObject *m_pPhysicsObject; // pointer to the entity's physics object (vphysics.dll) CNetworkVar( float, m_flShadowCastDistance ); float m_flDesiredShadowCastDistance; // Team handling int m_iInitialTeamNum; // Team number of this entity's team read from file CNetworkVar( int, m_iTeamNum ); // Team number of this entity's team. // Sets water type + level for physics objects unsigned char m_nWaterTouch; unsigned char m_nSlimeTouch; unsigned char m_nWaterType; CNetworkVarForDerived( unsigned char, m_nWaterLevel ); float m_flNavIgnoreUntilTime; CNetworkHandleForDerived( CBaseEntity, m_hGroundEntity ); float m_flGroundChangeTime; // Time that the ground entity changed string_t m_ModelName; // Velocity of the thing we're standing on (world space) CNetworkVarForDerived( Vector, m_vecBaseVelocity ); // Global velocity Vector m_vecAbsVelocity; // Local angular velocity QAngle m_vecAngVelocity; // Global angular velocity // QAngle m_vecAbsAngVelocity; // local coordinate frame of entity matrix3x4_t m_rgflCoordinateFrame; // Physics state EHANDLE m_pBlocker; // was pev->gravity; float m_flGravity; // rename to m_flGravityScale; // was pev->friction CNetworkVarForDerived( float, m_flFriction ); CNetworkVar( float, m_flElasticity ); // was pev->ltime float m_flLocalTime; // local time at the beginning of this frame float m_flVPhysicsUpdateLocalTime; // local time the movement has ended float m_flMoveDoneTime; // A counter to help quickly build a list of potentially pushed objects for physics int m_nPushEnumCount; Vector m_vecAbsOrigin; CNetworkVectorForDerived( m_vecVelocity ); //Adrian CNetworkVar( unsigned char, m_iTextureFrameIndex ); CNetworkVar( bool, m_bSimulatedEveryTick ); CNetworkVar( bool, m_bAnimatedEveryTick ); CNetworkVar( bool, m_bAlternateSorting ); // User outputs. Fired when the "FireInputX" input is triggered. COutputEvent m_OnUser1; COutputEvent m_OnUser2; COutputEvent m_OnUser3; COutputEvent m_OnUser4; QAngle m_angAbsRotation; CNetworkVector( m_vecOrigin ); CNetworkQAngle( m_angRotation ); CBaseHandle m_RefEHandle; // was pev->view_ofs ( FIXME: Move somewhere up the hierarch, CBaseAnimating, etc. ) CNetworkVectorForDerived( m_vecViewOffset ); private: // dynamic model state tracking bool m_bDynamicModelAllowed; bool m_bDynamicModelPending; bool m_bDynamicModelSetBounds; void OnModelLoadComplete( const model_t* model ); friend class CBaseEntityModelLoadProxy; protected: void EnableDynamicModels() { m_bDynamicModelAllowed = true; } public: bool IsDynamicModelLoading() const { return m_bDynamicModelPending; } void SetCollisionBoundsFromModel(); #if !defined( NO_ENTITY_PREDICTION ) CNetworkVar( bool, m_bIsPlayerSimulated ); // Player who is driving my simulation CHandle< CBasePlayer > m_hPlayerSimulationOwner; #endif int m_fDataObjectTypes; // So it can get at the physics methods friend class CCollisionEvent; // Methods shared by client and server public: void SetSize( const Vector &vecMin, const Vector &vecMax ); // UTIL_SetSize( this, mins, maxs ); static int PrecacheModel( const char *name, bool bPreload = true ); static bool PrecacheSound( const char *name ); static void PrefetchSound( const char *name ); void Remove( ); // UTIL_Remove( this ); private: // 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 int m_nPredictionRandomSeedServer; static CBasePlayer *m_pPredictionPlayer; // FIXME: Make hierarchy a member of CBaseEntity // or a contained private class... friend void UnlinkChild( CBaseEntity *pParent, CBaseEntity *pChild ); friend void LinkChild( CBaseEntity *pParent, CBaseEntity *pChild ); friend void ClearParent( CBaseEntity *pEntity ); friend void UnlinkAllChildren( CBaseEntity *pParent ); friend void UnlinkFromParent( CBaseEntity *pRemove ); friend void TransferChildren( CBaseEntity *pOldParent, CBaseEntity *pNewParent ); public: // Accessors for above static int GetPredictionRandomSeed( bool bUseUnSyncedServerPlatTime = false ); static void SetPredictionRandomSeed( const CUserCmd *cmd ); static CBasePlayer *GetPredictionPlayer( void ); static void SetPredictionPlayer( CBasePlayer *player ); // For debugging shared code static bool IsServer( void ) { return true; } static bool IsClient( void ) { return false; } static char const *GetDLLType( void ) { return "server"; } // Used to access m_vecAbsOrigin during restore when it's unsafe to call GetAbsOrigin. friend class CPlayerRestoreHelper; static bool s_bAbsQueriesValid; // Call this when hierarchy is not completely set up (such as during Restore) to throw asserts // when people call GetAbsAnything. static inline void SetAbsQueriesValid( bool bValid ) { s_bAbsQueriesValid = bValid; } static inline bool IsAbsQueriesValid() { return s_bAbsQueriesValid; } virtual bool ShouldBlockNav() const { return true; } }; // Send tables exposed in this module. EXTERN_SEND_TABLE(DT_Edict); EXTERN_SEND_TABLE(DT_BaseEntity);
baseentity.cpp
BEGIN_SIMPLE_DATADESC( thinkfunc_t ) DEFINE_FIELD( m_iszContext, FIELD_STRING ), // DEFINE_FIELD( m_pfnThink, FIELD_FUNCTION ), // Manually written DEFINE_FIELD( m_nNextThinkTick, FIELD_TICK ), DEFINE_FIELD( m_nLastThinkTick, FIELD_TICK ), END_DATADESC() BEGIN_SIMPLE_DATADESC( ResponseContext_t ) DEFINE_FIELD( m_iszName, FIELD_STRING ), DEFINE_FIELD( m_iszValue, FIELD_STRING ), DEFINE_FIELD( m_fExpirationTime, FIELD_TIME ), END_DATADESC() BEGIN_DATADESC_NO_BASE( CBaseEntity ) DEFINE_KEYFIELD( m_iClassname, FIELD_STRING, "classname" ), DEFINE_GLOBAL_KEYFIELD( m_iGlobalname, FIELD_STRING, "globalname" ), DEFINE_KEYFIELD( m_iParent, FIELD_STRING, "parentname" ), DEFINE_KEYFIELD( m_iHammerID, FIELD_INTEGER, "hammerid" ), // save ID numbers so that entities can be tracked between save/restore and vmf DEFINE_KEYFIELD( m_flSpeed, FIELD_FLOAT, "speed" ), DEFINE_KEYFIELD( m_nRenderFX, FIELD_CHARACTER, "renderfx" ), DEFINE_KEYFIELD( m_nRenderMode, FIELD_CHARACTER, "rendermode" ), // Consider moving to CBaseAnimating? DEFINE_FIELD( m_flPrevAnimTime, FIELD_TIME ), DEFINE_FIELD( m_flAnimTime, FIELD_TIME ), DEFINE_FIELD( m_flSimulationTime, FIELD_TIME ), DEFINE_FIELD( m_nLastThinkTick, FIELD_TICK ), DEFINE_KEYFIELD( m_nNextThinkTick, FIELD_TICK, "nextthink" ), DEFINE_KEYFIELD( m_fEffects, FIELD_INTEGER, "effects" ), DEFINE_KEYFIELD( m_clrRender, FIELD_COLOR32, "rendercolor" ), DEFINE_GLOBAL_KEYFIELD( m_nModelIndex, FIELD_SHORT, "modelindex" ), #if !defined( NO_ENTITY_PREDICTION ) // DEFINE_FIELD( m_PredictableID, CPredictableId ), #endif DEFINE_FIELD( touchStamp, FIELD_INTEGER ), DEFINE_CUSTOM_FIELD( m_aThinkFunctions, thinkcontextFuncs ), // m_iCurrentThinkContext (not saved, debug field only, and think transient to boot) DEFINE_UTLVECTOR(m_ResponseContexts, FIELD_EMBEDDED), DEFINE_KEYFIELD( m_iszResponseContext, FIELD_STRING, "ResponseContext" ), DEFINE_FIELD( m_pfnThink, FIELD_FUNCTION ), DEFINE_FIELD( m_pfnTouch, FIELD_FUNCTION ), DEFINE_FIELD( m_pfnUse, FIELD_FUNCTION ), DEFINE_FIELD( m_pfnBlocked, FIELD_FUNCTION ), DEFINE_FIELD( m_pfnMoveDone, FIELD_FUNCTION ), DEFINE_FIELD( m_lifeState, FIELD_CHARACTER ), DEFINE_FIELD( m_takedamage, FIELD_CHARACTER ), DEFINE_KEYFIELD( m_iMaxHealth, FIELD_INTEGER, "max_health" ), DEFINE_KEYFIELD( m_iHealth, FIELD_INTEGER, "health" ), // DEFINE_FIELD( m_pLink, FIELD_CLASSPTR ), DEFINE_KEYFIELD( m_target, FIELD_STRING, "target" ), DEFINE_KEYFIELD( m_iszDamageFilterName, FIELD_STRING, "damagefilter" ), DEFINE_FIELD( m_hDamageFilter, FIELD_EHANDLE ), DEFINE_FIELD( m_debugOverlays, FIELD_INTEGER ), DEFINE_GLOBAL_FIELD( m_pParent, FIELD_EHANDLE ), DEFINE_FIELD( m_iParentAttachment, FIELD_CHARACTER ), DEFINE_GLOBAL_FIELD( m_hMoveParent, FIELD_EHANDLE ), DEFINE_GLOBAL_FIELD( m_hMoveChild, FIELD_EHANDLE ), DEFINE_GLOBAL_FIELD( m_hMovePeer, FIELD_EHANDLE ), DEFINE_FIELD( m_iEFlags, FIELD_INTEGER ), DEFINE_FIELD( m_iName, FIELD_STRING ), DEFINE_EMBEDDED( m_Collision ), DEFINE_EMBEDDED( m_Network ), DEFINE_FIELD( m_MoveType, FIELD_CHARACTER ), DEFINE_FIELD( m_MoveCollide, FIELD_CHARACTER ), DEFINE_FIELD( m_hOwnerEntity, FIELD_EHANDLE ), DEFINE_FIELD( m_CollisionGroup, FIELD_INTEGER ), DEFINE_PHYSPTR( m_pPhysicsObject), DEFINE_FIELD( m_flElasticity, FIELD_FLOAT ), DEFINE_KEYFIELD( m_flShadowCastDistance, FIELD_FLOAT, "shadowcastdist" ), DEFINE_FIELD( m_flDesiredShadowCastDistance, FIELD_FLOAT ), DEFINE_INPUT( m_iInitialTeamNum, FIELD_INTEGER, "TeamNum" ), DEFINE_FIELD( m_iTeamNum, FIELD_INTEGER ), // DEFINE_FIELD( m_bSentLastFrame, FIELD_INTEGER ), DEFINE_FIELD( m_hGroundEntity, FIELD_EHANDLE ), DEFINE_FIELD( m_flGroundChangeTime, FIELD_TIME ), DEFINE_GLOBAL_KEYFIELD( m_ModelName, FIELD_MODELNAME, "model" ), DEFINE_KEYFIELD( m_vecBaseVelocity, FIELD_VECTOR, "basevelocity" ), DEFINE_FIELD( m_vecAbsVelocity, FIELD_VECTOR ), DEFINE_KEYFIELD( m_vecAngVelocity, FIELD_VECTOR, "avelocity" ), // DEFINE_FIELD( m_vecAbsAngVelocity, FIELD_VECTOR ), DEFINE_ARRAY( m_rgflCoordinateFrame, FIELD_FLOAT, 12 ), // NOTE: MUST BE IN LOCAL SPACE, NOT POSITION_VECTOR!!! (see CBaseEntity::Restore) DEFINE_KEYFIELD( m_nWaterLevel, FIELD_CHARACTER, "waterlevel" ), DEFINE_FIELD( m_nWaterType, FIELD_CHARACTER ), DEFINE_FIELD( m_pBlocker, FIELD_EHANDLE ), DEFINE_KEYFIELD( m_flGravity, FIELD_FLOAT, "gravity" ), DEFINE_KEYFIELD( m_flFriction, FIELD_FLOAT, "friction" ), // Local time is local to each object. It doesn't need to be re-based if the clock // changes. Therefore it is saved as a FIELD_FLOAT, not a FIELD_TIME DEFINE_KEYFIELD( m_flLocalTime, FIELD_FLOAT, "ltime" ), DEFINE_FIELD( m_flVPhysicsUpdateLocalTime, FIELD_FLOAT ), DEFINE_FIELD( m_flMoveDoneTime, FIELD_FLOAT ), // DEFINE_FIELD( m_nPushEnumCount, FIELD_INTEGER ), DEFINE_FIELD( m_vecAbsOrigin, FIELD_POSITION_VECTOR ), DEFINE_KEYFIELD( m_vecVelocity, FIELD_VECTOR, "velocity" ), DEFINE_KEYFIELD( m_iTextureFrameIndex, FIELD_CHARACTER, "texframeindex" ), DEFINE_FIELD( m_bSimulatedEveryTick, FIELD_BOOLEAN ), DEFINE_FIELD( m_bAnimatedEveryTick, FIELD_BOOLEAN ), DEFINE_FIELD( m_bAlternateSorting, FIELD_BOOLEAN ), DEFINE_KEYFIELD( m_spawnflags, FIELD_INTEGER, "spawnflags" ), DEFINE_FIELD( m_nTransmitStateOwnedCounter, FIELD_CHARACTER ), DEFINE_FIELD( m_angAbsRotation, FIELD_VECTOR ), DEFINE_FIELD( m_vecOrigin, FIELD_VECTOR ), // NOTE: MUST BE IN LOCAL SPACE, NOT POSITION_VECTOR!!! (see CBaseEntity::Restore) DEFINE_FIELD( m_angRotation, FIELD_VECTOR ), DEFINE_KEYFIELD( m_vecViewOffset, FIELD_VECTOR, "view_ofs" ), DEFINE_FIELD( m_fFlags, FIELD_INTEGER ), #if !defined( NO_ENTITY_PREDICTION ) // DEFINE_FIELD( m_bIsPlayerSimulated, FIELD_INTEGER ), // DEFINE_FIELD( m_hPlayerSimulationOwner, FIELD_EHANDLE ), #endif // DEFINE_FIELD( m_pTimedOverlay, TimedOverlay_t* ), DEFINE_FIELD( m_nSimulationTick, FIELD_TICK ), // DEFINE_FIELD( m_RefEHandle, CBaseHandle ), // DEFINE_FIELD( m_nWaterTouch, FIELD_INTEGER ), // DEFINE_FIELD( m_nSlimeTouch, FIELD_INTEGER ), DEFINE_FIELD( m_flNavIgnoreUntilTime, FIELD_TIME ), // DEFINE_FIELD( m_bToolRecording, FIELD_BOOLEAN ), // DEFINE_FIELD( m_ToolHandle, FIELD_INTEGER ), // NOTE: This is tricky. TeamNum must be saved, but we can't directly // read it in, because we can only set it after the team entity has been read in, // which may or may not actually occur before the entity is parsed. // Therefore, we set the TeamNum from the InitialTeamNum in Activate DEFINE_INPUTFUNC( FIELD_INTEGER, "SetTeam", InputSetTeam ), DEFINE_INPUTFUNC( FIELD_VOID, "Kill", InputKill ), DEFINE_INPUTFUNC( FIELD_VOID, "KillHierarchy", InputKillHierarchy ), DEFINE_INPUTFUNC( FIELD_VOID, "Use", InputUse ), DEFINE_INPUTFUNC( FIELD_INTEGER, "Alpha", InputAlpha ), DEFINE_INPUTFUNC( FIELD_BOOLEAN, "AlternativeSorting", InputAlternativeSorting ), DEFINE_INPUTFUNC( FIELD_COLOR32, "Color", InputColor ), DEFINE_INPUTFUNC( FIELD_STRING, "SetParent", InputSetParent ), DEFINE_INPUTFUNC( FIELD_STRING, "SetParentAttachment", InputSetParentAttachment ), DEFINE_INPUTFUNC( FIELD_STRING, "SetParentAttachmentMaintainOffset", InputSetParentAttachmentMaintainOffset ), DEFINE_INPUTFUNC( FIELD_VOID, "ClearParent", InputClearParent ), DEFINE_INPUTFUNC( FIELD_STRING, "SetDamageFilter", InputSetDamageFilter ), DEFINE_INPUTFUNC( FIELD_VOID, "EnableDamageForces", InputEnableDamageForces ), DEFINE_INPUTFUNC( FIELD_VOID, "DisableDamageForces", InputDisableDamageForces ), DEFINE_INPUTFUNC( FIELD_STRING, "DispatchEffect", InputDispatchEffect ), DEFINE_INPUTFUNC( FIELD_STRING, "DispatchResponse", InputDispatchResponse ), // Entity I/O methods to alter context DEFINE_INPUTFUNC( FIELD_STRING, "AddContext", InputAddContext ), DEFINE_INPUTFUNC( FIELD_STRING, "RemoveContext", InputRemoveContext ), DEFINE_INPUTFUNC( FIELD_STRING, "ClearContext", InputClearContext ), DEFINE_INPUTFUNC( FIELD_VOID, "DisableShadow", InputDisableShadow ), DEFINE_INPUTFUNC( FIELD_VOID, "EnableShadow", InputEnableShadow ), DEFINE_INPUTFUNC( FIELD_STRING, "AddOutput", InputAddOutput ), DEFINE_INPUTFUNC( FIELD_STRING, "FireUser1", InputFireUser1 ), DEFINE_INPUTFUNC( FIELD_STRING, "FireUser2", InputFireUser2 ), DEFINE_INPUTFUNC( FIELD_STRING, "FireUser3", InputFireUser3 ), DEFINE_INPUTFUNC( FIELD_STRING, "FireUser4", InputFireUser4 ), DEFINE_OUTPUT( m_OnUser1, "OnUser1" ), DEFINE_OUTPUT( m_OnUser2, "OnUser2" ), DEFINE_OUTPUT( m_OnUser3, "OnUser3" ), DEFINE_OUTPUT( m_OnUser4, "OnUser4" ), // Function Pointers DEFINE_FUNCTION( SUB_Remove ), DEFINE_FUNCTION( SUB_DoNothing ), DEFINE_FUNCTION( SUB_StartFadeOut ), DEFINE_FUNCTION( SUB_StartFadeOutInstant ), DEFINE_FUNCTION( SUB_FadeOut ), DEFINE_FUNCTION( SUB_Vanish ), DEFINE_FUNCTION( SUB_CallUseToggle ), DEFINE_THINKFUNC( ShadowCastDistThink ), DEFINE_FIELD( m_hEffectEntity, FIELD_EHANDLE ), //DEFINE_FIELD( m_DamageModifiers, FIELD_?? ), // can't save? // DEFINE_FIELD( m_fDataObjectTypes, FIELD_INTEGER ), #ifdef TF_DLL DEFINE_ARRAY( m_nModelIndexOverrides, FIELD_INTEGER, MAX_VISION_MODES ), #endif END_DATADESC() // This table encodes the CBaseEntity data. IMPLEMENT_SERVERCLASS_ST_NOBASE( CBaseEntity, DT_BaseEntity ) SendPropDataTable( "AnimTimeMustBeFirst", 0, &REFERENCE_SEND_TABLE(DT_AnimTimeMustBeFirst), SendProxy_ClientSideAnimation ), SendPropInt (SENDINFO(m_flSimulationTime), SIMULATION_TIME_WINDOW_BITS, SPROP_UNSIGNED|SPROP_CHANGES_OFTEN|SPROP_ENCODED_AGAINST_TICKCOUNT, SendProxy_SimulationTime), #if PREDICTION_ERROR_CHECK_LEVEL > 1 SendPropVector (SENDINFO(m_vecOrigin), -1, SPROP_NOSCALE|SPROP_CHANGES_OFTEN, 0.0f, HIGH_DEFAULT, SendProxy_Origin ), #else SendPropVector (SENDINFO(m_vecOrigin), -1, SPROP_COORD|SPROP_CHANGES_OFTEN, 0.0f, HIGH_DEFAULT, SendProxy_Origin ), #endif SendPropInt (SENDINFO( m_ubInterpolationFrame ), NOINTERP_PARITY_MAX_BITS, SPROP_UNSIGNED ), SendPropModelIndex(SENDINFO(m_nModelIndex)), SendPropDataTable( SENDINFO_DT( m_Collision ), &REFERENCE_SEND_TABLE(DT_CollisionProperty) ), SendPropInt (SENDINFO(m_nRenderFX), 8, SPROP_UNSIGNED ), SendPropInt (SENDINFO(m_nRenderMode), 8, SPROP_UNSIGNED ), SendPropInt (SENDINFO(m_fEffects), EF_MAX_BITS, SPROP_UNSIGNED), SendPropInt (SENDINFO(m_clrRender), 32, SPROP_UNSIGNED), SendPropInt (SENDINFO(m_iTeamNum), TEAMNUM_NUM_BITS, 0), SendPropInt (SENDINFO(m_CollisionGroup), 5, SPROP_UNSIGNED), SendPropFloat (SENDINFO(m_flElasticity), 0, SPROP_COORD), SendPropFloat (SENDINFO(m_flShadowCastDistance), 12, SPROP_UNSIGNED ), SendPropEHandle (SENDINFO(m_hOwnerEntity)), SendPropEHandle (SENDINFO(m_hEffectEntity)), SendPropEHandle (SENDINFO_NAME(m_hMoveParent, moveparent)), SendPropInt (SENDINFO(m_iParentAttachment), NUM_PARENTATTACHMENT_BITS, SPROP_UNSIGNED), SendPropInt (SENDINFO_NAME( m_MoveType, movetype ), MOVETYPE_MAX_BITS, SPROP_UNSIGNED ), SendPropInt (SENDINFO_NAME( m_MoveCollide, movecollide ), MOVECOLLIDE_MAX_BITS, SPROP_UNSIGNED ), #if PREDICTION_ERROR_CHECK_LEVEL > 1 SendPropVector (SENDINFO(m_angRotation), -1, SPROP_NOSCALE|SPROP_CHANGES_OFTEN, 0, HIGH_DEFAULT, SendProxy_Angles ), #else SendPropQAngles (SENDINFO(m_angRotation), 13, SPROP_CHANGES_OFTEN, SendProxy_Angles ), #endif SendPropInt ( SENDINFO( m_iTextureFrameIndex ), 8, SPROP_UNSIGNED ), #if !defined( NO_ENTITY_PREDICTION ) SendPropDataTable( "predictable_id", 0, &REFERENCE_SEND_TABLE( DT_PredictableId ), SendProxy_SendPredictableId ), #endif // FIXME: Collapse into another flag field? SendPropInt (SENDINFO(m_bSimulatedEveryTick), 1, SPROP_UNSIGNED ), SendPropInt (SENDINFO(m_bAnimatedEveryTick), 1, SPROP_UNSIGNED ), SendPropBool( SENDINFO( m_bAlternateSorting )), #ifdef TF_DLL SendPropArray3( SENDINFO_ARRAY3(m_nModelIndexOverrides), SendPropInt( SENDINFO_ARRAY(m_nModelIndexOverrides), SP_MODEL_INDEX_BITS, 0 ) ), #endif END_SEND_TABLE() BEGIN_SEND_TABLE_NOBASE( CBaseEntity, DT_AnimTimeMustBeFirst ) // NOTE: Animtime must be sent before origin and angles ( from pev ) because it has a // proxy on the client that stores off the old values before writing in the new values and // if it is sent after the new values, then it will only have the new origin and studio model, etc. // interpolation will be busted SendPropInt (SENDINFO(m_flAnimTime), 8, SPROP_UNSIGNED|SPROP_CHANGES_OFTEN|SPROP_ENCODED_AGAINST_TICKCOUNT, SendProxy_AnimTime), END_SEND_TABLE() #if !defined( NO_ENTITY_PREDICTION ) BEGIN_SEND_TABLE_NOBASE( CBaseEntity, DT_PredictableId ) SendPropPredictableId( SENDINFO( m_PredictableID ) ), SendPropInt( SENDINFO( m_bIsPlayerSimulated ), 1, SPROP_UNSIGNED ), END_SEND_TABLE()