diff options
Diffstat (limited to 'game/server/baseentity.h')
| -rw-r--r-- | game/server/baseentity.h | 2693 |
1 files changed, 2693 insertions, 0 deletions
diff --git a/game/server/baseentity.h b/game/server/baseentity.h new file mode 100644 index 0000000..042c18c --- /dev/null +++ b/game/server/baseentity.h @@ -0,0 +1,2693 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef BASEENTITY_H +#define BASEENTITY_H +#ifdef _WIN32 +#pragma once +#endif + +#define TEAMNUM_NUM_BITS 6 + +#include "entitylist.h" +#include "entityoutput.h" +#include "networkvar.h" +#include "collisionproperty.h" +#include "ServerNetworkProperty.h" +#include "shareddefs.h" +#include "engine/ivmodelinfo.h" + +class CDamageModifier; +class CDmgAccumulator; + +struct CSoundParameters; + +class AI_CriteriaSet; +class IResponseSystem; +class IEntitySaveUtils; +class CRecipientFilter; +class CStudioHdr; + +// Matching the high level concept is significantly better than other criteria +// FIXME: Could do this in the script file by making it required and bumping up weighting there instead... +#define CONCEPT_WEIGHT 5.0f + +typedef CHandle<CBaseEntity> EHANDLE; + +#define MANUALMODE_GETSET_PROP(type, accessorName, varName) \ + private:\ + type varName;\ + public:\ + inline const type& Get##accessorName##() const { return varName; } \ + inline type& Get##accessorName##() { return varName; } \ + inline void Set##accessorName##( const type &val ) { varName = val; m_NetStateMgr.StateChanged(); } + +#define MANUALMODE_GETSET_EHANDLE(type, accessorName, varName) \ + private:\ + CHandle<type> varName;\ + public:\ + inline type* Get##accessorName##() { return varName.Get(); } \ + inline void Set##accessorName##( type *pType ) { varName = pType; m_NetStateMgr.StateChanged(); } + + +// saverestore.h declarations +class CSaveRestoreData; +struct typedescription_t; +class ISave; +class IRestore; +class CBaseEntity; +class CEntityMapData; +class CBaseCombatWeapon; +class IPhysicsObject; +class IPhysicsShadowController; +class CBaseCombatCharacter; +class CTeam; +class Vector; +struct gamevcollisionevent_t; +class CBaseAnimating; +class CBasePlayer; +class IServerVehicle; +struct solid_t; +struct notify_system_event_params_t; +class CAI_BaseNPC; +class CAI_Senses; +class CSquadNPC; +class variant_t; +class CEventAction; +typedef struct KeyValueData_s KeyValueData; +class CUserCmd; +class CSkyCamera; +class CEntityMapData; +class INextBot; +class IHasAttributes; + +typedef CUtlVector< CBaseEntity* > EntityList_t; + +#if defined( HL2_DLL ) + +// For CLASSIFY +enum Class_T +{ + CLASS_NONE=0, + CLASS_PLAYER, + CLASS_PLAYER_ALLY, + CLASS_PLAYER_ALLY_VITAL, + CLASS_ANTLION, + CLASS_BARNACLE, + CLASS_BULLSEYE, + //CLASS_BULLSQUID, + CLASS_CITIZEN_PASSIVE, + CLASS_CITIZEN_REBEL, + CLASS_COMBINE, + CLASS_COMBINE_GUNSHIP, + CLASS_CONSCRIPT, + CLASS_HEADCRAB, + //CLASS_HOUNDEYE, + CLASS_MANHACK, + CLASS_METROPOLICE, + CLASS_MILITARY, + CLASS_SCANNER, + CLASS_STALKER, + CLASS_VORTIGAUNT, + CLASS_ZOMBIE, + CLASS_PROTOSNIPER, + CLASS_MISSILE, + CLASS_FLARE, + CLASS_EARTH_FAUNA, + CLASS_HACKED_ROLLERMINE, + CLASS_COMBINE_HUNTER, + + NUM_AI_CLASSES +}; + +#elif defined( HL1_DLL ) + +enum Class_T +{ + CLASS_NONE = 0, + CLASS_MACHINE, + CLASS_PLAYER, + CLASS_HUMAN_PASSIVE, + CLASS_HUMAN_MILITARY, + CLASS_ALIEN_MILITARY, + CLASS_ALIEN_MONSTER, + CLASS_ALIEN_PREY, + CLASS_ALIEN_PREDATOR, + CLASS_INSECT, + CLASS_PLAYER_ALLY, + CLASS_PLAYER_BIOWEAPON, + CLASS_ALIEN_BIOWEAPON, + + NUM_AI_CLASSES +}; + +#elif defined( INVASION_DLL ) + +enum Class_T +{ + CLASS_NONE = 0, + CLASS_PLAYER, + CLASS_PLAYER_ALLY, + CLASS_PLAYER_ALLY_VITAL, + CLASS_ANTLION, + CLASS_BARNACLE, + CLASS_BULLSEYE, + //CLASS_BULLSQUID, + CLASS_CITIZEN_PASSIVE, + CLASS_CITIZEN_REBEL, + CLASS_COMBINE, + CLASS_COMBINE_GUNSHIP, + CLASS_CONSCRIPT, + CLASS_HEADCRAB, + //CLASS_HOUNDEYE, + CLASS_MANHACK, + CLASS_METROPOLICE, + CLASS_MILITARY, + CLASS_SCANNER, + CLASS_STALKER, + CLASS_VORTIGAUNT, + CLASS_ZOMBIE, + CLASS_PROTOSNIPER, + CLASS_MISSILE, + CLASS_FLARE, + CLASS_EARTH_FAUNA, + NUM_AI_CLASSES +}; + +#elif defined( CSTRIKE_DLL ) + +enum Class_T +{ + CLASS_NONE = 0, + CLASS_PLAYER, + CLASS_PLAYER_ALLY, + NUM_AI_CLASSES +}; + +#else + +enum Class_T +{ + CLASS_NONE = 0, + CLASS_PLAYER, + CLASS_PLAYER_ALLY, + NUM_AI_CLASSES +}; + +#endif + +// +// Structure passed to input handlers. +// +struct inputdata_t +{ + CBaseEntity *pActivator; // The entity that initially caused this chain of output events. + CBaseEntity *pCaller; // The entity that fired this particular output. + variant_t value; // The data parameter for this output. + int nOutputID; // The unique ID of the output that was fired. +}; + +// Serializable list of context as set by entity i/o and used for deducing proper +// speech state, et al. +struct ResponseContext_t +{ + DECLARE_SIMPLE_DATADESC(); + + string_t m_iszName; + string_t m_iszValue; + float m_fExpirationTime; // when to expire context (0 == never) +}; + + +//----------------------------------------------------------------------------- +// Entity events... targetted to a particular entity +// Each event has a well defined structure to use for parameters +//----------------------------------------------------------------------------- +enum EntityEvent_t +{ + ENTITY_EVENT_WATER_TOUCH = 0, // No data needed + ENTITY_EVENT_WATER_UNTOUCH, // No data needed + ENTITY_EVENT_PARENT_CHANGED, // No data needed +}; + + +//----------------------------------------------------------------------------- + +typedef void (CBaseEntity::*BASEPTR)(void); +typedef void (CBaseEntity::*ENTITYFUNCPTR)(CBaseEntity *pOther ); +typedef void (CBaseEntity::*USEPTR)( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); + +#define DEFINE_THINKFUNC( function ) DEFINE_FUNCTION_RAW( function, BASEPTR ) +#define DEFINE_ENTITYFUNC( function ) DEFINE_FUNCTION_RAW( function, ENTITYFUNCPTR ) +#define DEFINE_USEFUNC( function ) DEFINE_FUNCTION_RAW( function, USEPTR ) + +// Things that toggle (buttons/triggers/doors) need this +enum TOGGLE_STATE +{ + TS_AT_TOP, + TS_AT_BOTTOM, + TS_GOING_UP, + TS_GOING_DOWN +}; + + +// Debug overlay bits +enum DebugOverlayBits_t +{ + OVERLAY_TEXT_BIT = 0x00000001, // show text debug overlay for this entity + OVERLAY_NAME_BIT = 0x00000002, // show name debug overlay for this entity + OVERLAY_BBOX_BIT = 0x00000004, // show bounding box overlay for this entity + OVERLAY_PIVOT_BIT = 0x00000008, // show pivot for this entity + OVERLAY_MESSAGE_BIT = 0x00000010, // show messages for this entity + OVERLAY_ABSBOX_BIT = 0x00000020, // show abs bounding box overlay + OVERLAY_RBOX_BIT = 0x00000040, // show the rbox overlay + OVERLAY_SHOW_BLOCKSLOS = 0x00000080, // show entities that block NPC LOS + OVERLAY_ATTACHMENTS_BIT = 0x00000100, // show attachment points + OVERLAY_AUTOAIM_BIT = 0x00000200, // Display autoaim radius + + OVERLAY_NPC_SELECTED_BIT = 0x00001000, // the npc is current selected + OVERLAY_NPC_NEAREST_BIT = 0x00002000, // show the nearest node of this npc + OVERLAY_NPC_ROUTE_BIT = 0x00004000, // draw the route for this npc + OVERLAY_NPC_TRIANGULATE_BIT = 0x00008000, // draw the triangulation for this npc + OVERLAY_NPC_ZAP_BIT = 0x00010000, // destroy the NPC + OVERLAY_NPC_ENEMIES_BIT = 0x00020000, // show npc's enemies + OVERLAY_NPC_CONDITIONS_BIT = 0x00040000, // show NPC's current conditions + OVERLAY_NPC_SQUAD_BIT = 0x00080000, // show npc squads + OVERLAY_NPC_TASK_BIT = 0x00100000, // show npc task details + OVERLAY_NPC_FOCUS_BIT = 0x00200000, // show line to npc's enemy and target + OVERLAY_NPC_VIEWCONE_BIT = 0x00400000, // show npc's viewcone + OVERLAY_NPC_KILL_BIT = 0x00800000, // kill the NPC, running all appropriate AI. + + OVERLAY_WC_CHANGE_ENTITY = 0x01000000, // object changed during WC edit + OVERLAY_BUDDHA_MODE = 0x02000000, // take damage but don't die + + OVERLAY_NPC_STEERING_REGULATIONS = 0x04000000, // Show the steering regulations associated with the NPC + + OVERLAY_TASK_TEXT_BIT = 0x08000000, // show task and schedule names when they start + + OVERLAY_PROP_DEBUG = 0x10000000, + + OVERLAY_NPC_RELATION_BIT = 0x20000000, // show relationships between target and all children + + OVERLAY_VIEWOFFSET = 0x40000000, // show view offset +}; + +struct TimedOverlay_t; + +/* ========= CBaseEntity ======== + + All objects in the game are derived from this. + +a list of all CBaseEntitys is kept in gEntList +================================ */ + +// creates an entity by string name, but does not spawn it +// If iForceEdictIndex is not -1, then it will use the edict by that index. If the index is +// invalid or there is already an edict using that index, it will error out. +CBaseEntity *CreateEntityByName( const char *className, int iForceEdictIndex = -1 ); +CBaseNetworkable *CreateNetworkableByName( const char *className ); + +// creates an entity and calls all the necessary spawn functions +extern void SpawnEntityByName( const char *className, CEntityMapData *mapData = NULL ); + +// calls the spawn functions for an entity +extern int DispatchSpawn( CBaseEntity *pEntity ); + +inline CBaseEntity *GetContainingEntity( edict_t *pent ); + +//----------------------------------------------------------------------------- +// Purpose: think contexts +//----------------------------------------------------------------------------- +struct thinkfunc_t +{ + BASEPTR m_pfnThink; + string_t m_iszContext; + int m_nNextThinkTick; + int m_nLastThinkTick; + + DECLARE_SIMPLE_DATADESC(); +}; + +struct EmitSound_t; +struct rotatingpushmove_t; + +#define CREATE_PREDICTED_ENTITY( className ) \ + CBaseEntity::CreatePredictedEntityByName( className, __FILE__, __LINE__ ); + +// +// 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( const 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; } + + virtual bool ShouldForceTransmitsForTeam( int iTeam ) { return false; } + + void SetTruceValidForEnt( bool bTruceValidForEnt ) { m_bTruceValidForEnt = bTruceValidForEnt; } + virtual bool IsTruceValidForEnt( void ) const { return m_bTruceValidForEnt; } + +private: + CThreadFastMutex m_CalcAbsolutePositionMutex; + + bool m_bTruceValidForEnt; +}; + +// Send tables exposed in this module. +EXTERN_SEND_TABLE(DT_Edict); +EXTERN_SEND_TABLE(DT_BaseEntity); + + + +// Ugly technique to override base member functions +// Normally it's illegal to cast a pointer to a member function of a derived class to a pointer to a +// member function of a base class. static_cast is a sleezy way around that problem. + +#ifdef _DEBUG + +#define SetTouch( a ) TouchSet( static_cast <void (CBaseEntity::*)(CBaseEntity *)> (a), #a ) +#define SetUse( a ) UseSet( static_cast <void (CBaseEntity::*)( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )> (a), #a ) +#define SetBlocked( a ) BlockedSet( static_cast <void (CBaseEntity::*)(CBaseEntity *)> (a), #a ) + +#else + +#define SetTouch( a ) m_pfnTouch = static_cast <void (CBaseEntity::*)(CBaseEntity *)> (a) +#define SetUse( a ) m_pfnUse = static_cast <void (CBaseEntity::*)( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )> (a) +#define SetBlocked( a ) m_pfnBlocked = static_cast <void (CBaseEntity::*)(CBaseEntity *)> (a) + +#endif + +// handling entity/edict transforms +inline CBaseEntity *GetContainingEntity( edict_t *pent ) +{ + if ( pent && pent->GetUnknown() ) + { + return pent->GetUnknown()->GetBaseEntity(); + } + + return NULL; +} + +//----------------------------------------------------------------------------- +// Purpose: Pauses or resumes entity i/o events. When paused, no outputs will +// fire unless Debug_SetSteps is called with a nonzero step value. +// Input : bPause - true to pause, false to resume. +//----------------------------------------------------------------------------- +inline void CBaseEntity::Debug_Pause(bool bPause) +{ + CBaseEntity::m_bDebugPause = bPause; +} + + +//----------------------------------------------------------------------------- +// Purpose: Returns true if entity i/o is paused, false if not. +//----------------------------------------------------------------------------- +inline bool CBaseEntity::Debug_IsPaused(void) +{ + return(CBaseEntity::m_bDebugPause); +} + + +//----------------------------------------------------------------------------- +// Purpose: Decrements the debug step counter. Used when the entity i/o system +// is in single step mode, this is called every time an output is fired. +// Output : Returns true on to continue firing outputs, false to stop. +//----------------------------------------------------------------------------- +inline bool CBaseEntity::Debug_Step(void) +{ + if (CBaseEntity::m_nDebugSteps > 0) + { + CBaseEntity::m_nDebugSteps--; + } + return(CBaseEntity::m_nDebugSteps > 0); +} + + +//----------------------------------------------------------------------------- +// Purpose: Sets the number of entity outputs to allow to fire before pausing +// the entity i/o system. +// Input : nSteps - Number of steps to execute. +//----------------------------------------------------------------------------- +inline void CBaseEntity::Debug_SetSteps(int nSteps) +{ + CBaseEntity::m_nDebugSteps = nSteps; +} + + +//----------------------------------------------------------------------------- +// Purpose: Returns true if we should allow outputs to be fired, false if not. +//----------------------------------------------------------------------------- +inline bool CBaseEntity::Debug_ShouldStep(void) +{ + return(!CBaseEntity::m_bDebugPause || CBaseEntity::m_nDebugSteps > 0); +} + +//----------------------------------------------------------------------------- +// Methods relating to traversing hierarchy +//----------------------------------------------------------------------------- +inline CBaseEntity *CBaseEntity::GetMoveParent( void ) +{ + return m_hMoveParent.Get(); +} + +inline CBaseEntity *CBaseEntity::FirstMoveChild( void ) +{ + return m_hMoveChild.Get(); +} + +inline CBaseEntity *CBaseEntity::NextMovePeer( void ) +{ + return m_hMovePeer.Get(); +} + +// FIXME: Remove this! There shouldn't be a difference between moveparent + parent +inline CBaseEntity* CBaseEntity::GetParent() +{ + return m_pParent.Get(); +} + +inline int CBaseEntity::GetParentAttachment() +{ + return m_iParentAttachment; +} + +//----------------------------------------------------------------------------- +// Inline methods +//----------------------------------------------------------------------------- +inline string_t CBaseEntity::GetEntityName() +{ + return m_iName; +} + +inline void CBaseEntity::SetName( string_t newName ) +{ + m_iName = newName; +} + + +inline bool CBaseEntity::NameMatches( const char *pszNameOrWildcard ) +{ + if ( IDENT_STRINGS(m_iName, pszNameOrWildcard) ) + return true; + return NameMatchesComplex( pszNameOrWildcard ); +} + +inline bool CBaseEntity::NameMatches( string_t nameStr ) +{ + if ( IDENT_STRINGS(m_iName, nameStr) ) + return true; + return NameMatchesComplex( STRING(nameStr) ); +} + +inline bool CBaseEntity::ClassMatches( const char *pszClassOrWildcard ) +{ + if ( IDENT_STRINGS(m_iClassname, pszClassOrWildcard ) ) + return true; + return ClassMatchesComplex( pszClassOrWildcard ); +} + +inline const char* CBaseEntity::GetClassname() +{ + return STRING(m_iClassname); +} + + +inline bool CBaseEntity::ClassMatches( string_t nameStr ) +{ + if ( IDENT_STRINGS(m_iClassname, nameStr ) ) + return true; + return ClassMatchesComplex( STRING(nameStr) ); +} + +inline int CBaseEntity::GetSpawnFlags( void ) const +{ + return m_spawnflags; +} + +inline void CBaseEntity::AddSpawnFlags( int nFlags ) +{ + m_spawnflags |= nFlags; +} +inline void CBaseEntity::RemoveSpawnFlags( int nFlags ) +{ + m_spawnflags &= ~nFlags; +} + +inline void CBaseEntity::ClearSpawnFlags( void ) +{ + m_spawnflags = 0; +} + +inline bool CBaseEntity::HasSpawnFlags( int nFlags ) const +{ + return (m_spawnflags & nFlags) != 0; +} + +//----------------------------------------------------------------------------- +// checks to see if the entity is marked for deletion +//----------------------------------------------------------------------------- +inline bool CBaseEntity::IsMarkedForDeletion( void ) +{ + return (m_iEFlags & EFL_KILLME); +} + +//----------------------------------------------------------------------------- +// EFlags +//----------------------------------------------------------------------------- +inline int CBaseEntity::GetEFlags() const +{ + return m_iEFlags; +} + +inline void CBaseEntity::SetEFlags( int iEFlags ) +{ + m_iEFlags = iEFlags; + + if ( iEFlags & ( EFL_FORCE_CHECK_TRANSMIT | EFL_IN_SKYBOX ) ) + { + DispatchUpdateTransmitState(); + } +} + +inline void CBaseEntity::AddEFlags( int nEFlagMask ) +{ + m_iEFlags |= nEFlagMask; + + if ( nEFlagMask & ( EFL_FORCE_CHECK_TRANSMIT | EFL_IN_SKYBOX ) ) + { + DispatchUpdateTransmitState(); + } +} + +inline void CBaseEntity::RemoveEFlags( int nEFlagMask ) +{ + m_iEFlags &= ~nEFlagMask; + + if ( nEFlagMask & ( EFL_FORCE_CHECK_TRANSMIT | EFL_IN_SKYBOX ) ) + DispatchUpdateTransmitState(); +} + +inline bool CBaseEntity::IsEFlagSet( int nEFlagMask ) const +{ + return (m_iEFlags & nEFlagMask) != 0; +} + +inline void CBaseEntity::SetNavIgnore( float duration ) +{ + float flNavIgnoreUntilTime = ( duration == FLT_MAX ) ? FLT_MAX : gpGlobals->curtime + duration; + if ( flNavIgnoreUntilTime > m_flNavIgnoreUntilTime ) + m_flNavIgnoreUntilTime = flNavIgnoreUntilTime; +} + +inline void CBaseEntity::ClearNavIgnore() +{ + m_flNavIgnoreUntilTime = 0; +} + +inline bool CBaseEntity::IsNavIgnored() const +{ + return ( gpGlobals->curtime <= m_flNavIgnoreUntilTime ); +} + +inline bool CBaseEntity::GetCheckUntouch() const +{ + return IsEFlagSet( EFL_CHECK_UNTOUCH ); +} + +//----------------------------------------------------------------------------- +// Network state optimization +//----------------------------------------------------------------------------- +inline CBaseCombatCharacter *ToBaseCombatCharacter( CBaseEntity *pEntity ) +{ + if ( !pEntity ) + return NULL; + + return pEntity->MyCombatCharacterPointer(); +} + + +//----------------------------------------------------------------------------- +// Physics state accessor methods +//----------------------------------------------------------------------------- +inline const Vector& CBaseEntity::GetLocalOrigin( void ) const +{ + return m_vecOrigin.Get(); +} + +inline const QAngle& CBaseEntity::GetLocalAngles( void ) const +{ + return m_angRotation.Get(); +} + +inline const Vector& CBaseEntity::GetAbsOrigin( void ) const +{ + Assert( CBaseEntity::IsAbsQueriesValid() ); + + if (IsEFlagSet(EFL_DIRTY_ABSTRANSFORM)) + { + const_cast<CBaseEntity*>(this)->CalcAbsolutePosition(); + } + return m_vecAbsOrigin; +} + +inline const QAngle& CBaseEntity::GetAbsAngles( void ) const +{ + Assert( CBaseEntity::IsAbsQueriesValid() ); + + if (IsEFlagSet(EFL_DIRTY_ABSTRANSFORM)) + { + const_cast<CBaseEntity*>(this)->CalcAbsolutePosition(); + } + return m_angAbsRotation; +} + + + +//----------------------------------------------------------------------------- +// Returns the entity-to-world transform +//----------------------------------------------------------------------------- +inline matrix3x4_t &CBaseEntity::EntityToWorldTransform() +{ + Assert( CBaseEntity::IsAbsQueriesValid() ); + + if (IsEFlagSet(EFL_DIRTY_ABSTRANSFORM)) + { + CalcAbsolutePosition(); + } + return m_rgflCoordinateFrame; +} + +inline const matrix3x4_t &CBaseEntity::EntityToWorldTransform() const +{ + Assert( CBaseEntity::IsAbsQueriesValid() ); + + if (IsEFlagSet(EFL_DIRTY_ABSTRANSFORM)) + { + const_cast<CBaseEntity*>(this)->CalcAbsolutePosition(); + } + return m_rgflCoordinateFrame; +} + + +//----------------------------------------------------------------------------- +// Some helper methods that transform a point from entity space to world space + back +//----------------------------------------------------------------------------- +inline void CBaseEntity::EntityToWorldSpace( const Vector &in, Vector *pOut ) const +{ + if ( GetAbsAngles() == vec3_angle ) + { + VectorAdd( in, GetAbsOrigin(), *pOut ); + } + else + { + VectorTransform( in, EntityToWorldTransform(), *pOut ); + } +} + +inline void CBaseEntity::WorldToEntitySpace( const Vector &in, Vector *pOut ) const +{ + if ( GetAbsAngles() == vec3_angle ) + { + VectorSubtract( in, GetAbsOrigin(), *pOut ); + } + else + { + VectorITransform( in, EntityToWorldTransform(), *pOut ); + } +} + + +//----------------------------------------------------------------------------- +// Velocity +//----------------------------------------------------------------------------- +inline Vector CBaseEntity::GetSmoothedVelocity( void ) +{ + Vector vel; + GetVelocity( &vel, NULL ); + return vel; +} + +inline const Vector &CBaseEntity::GetLocalVelocity( ) const +{ + return m_vecVelocity.Get(); +} + +inline const Vector &CBaseEntity::GetAbsVelocity( ) const +{ + Assert( CBaseEntity::IsAbsQueriesValid() ); + + if (IsEFlagSet(EFL_DIRTY_ABSVELOCITY)) + { + const_cast<CBaseEntity*>(this)->CalcAbsoluteVelocity(); + } + return m_vecAbsVelocity; +} + +inline const QAngle &CBaseEntity::GetLocalAngularVelocity( ) const +{ + return m_vecAngVelocity; +} + +/* +// FIXME: While we're using (dPitch, dYaw, dRoll) as our local angular velocity +// representation, we can't actually solve this problem +inline const QAngle &CBaseEntity::GetAbsAngularVelocity( ) const +{ + if (IsEFlagSet(EFL_DIRTY_ABSANGVELOCITY)) + { + const_cast<CBaseEntity*>(this)->CalcAbsoluteAngularVelocity(); + } + + return m_vecAbsAngVelocity; +} +*/ + +inline const Vector& CBaseEntity::GetBaseVelocity() const +{ + return m_vecBaseVelocity.Get(); +} + +inline void CBaseEntity::SetBaseVelocity( const Vector& v ) +{ + m_vecBaseVelocity = v; +} + +inline float CBaseEntity::GetGravity( void ) const +{ + return m_flGravity; +} + +inline void CBaseEntity::SetGravity( float gravity ) +{ + m_flGravity = gravity; +} + +inline float CBaseEntity::GetFriction( void ) const +{ + return m_flFriction; +} + +inline void CBaseEntity::SetFriction( float flFriction ) +{ + m_flFriction = flFriction; +} + +inline void CBaseEntity::SetElasticity( float flElasticity ) +{ + m_flElasticity = flElasticity; +} + +inline float CBaseEntity::GetElasticity( void ) const +{ + return m_flElasticity; +} + +inline void CBaseEntity::SetShadowCastDistance( float flDistance ) +{ + m_flShadowCastDistance = flDistance; +} + +inline float CBaseEntity::GetShadowCastDistance( void ) const +{ + return m_flShadowCastDistance; +} + +inline float CBaseEntity::GetLocalTime( void ) const +{ + return m_flLocalTime; +} + +inline void CBaseEntity::IncrementLocalTime( float flTimeDelta ) +{ + m_flLocalTime += flTimeDelta; +} + +inline float CBaseEntity::GetMoveDoneTime( ) const +{ + return (m_flMoveDoneTime >= 0) ? m_flMoveDoneTime - GetLocalTime() : -1; +} + +inline CBaseEntity *CBaseEntity::Instance( const edict_t *pent ) +{ + return GetContainingEntity( const_cast<edict_t*>(pent) ); +} + +inline CBaseEntity *CBaseEntity::Instance( edict_t *pent ) +{ + if ( !pent ) + { + pent = INDEXENT(0); + } + return GetContainingEntity( pent ); +} + +inline CBaseEntity* CBaseEntity::Instance( int iEnt ) +{ + return Instance( INDEXENT( iEnt ) ); +} + +inline int CBaseEntity::GetWaterLevel() const +{ + return m_nWaterLevel; +} + +inline void CBaseEntity::SetWaterLevel( int nLevel ) +{ + m_nWaterLevel = nLevel; +} + +inline const color32 CBaseEntity::GetRenderColor() const +{ + return m_clrRender.Get(); +} + +inline void CBaseEntity::SetRenderColor( byte r, byte g, byte b ) +{ + m_clrRender.Init( r, g, b ); +} + +inline void CBaseEntity::SetRenderColor( byte r, byte g, byte b, byte a ) +{ + m_clrRender.Init( r, g, b, a ); +} + +inline void CBaseEntity::SetRenderColorR( byte r ) +{ + m_clrRender.SetR( r ); +} + +inline void CBaseEntity::SetRenderColorG( byte g ) +{ + m_clrRender.SetG( g ); +} + +inline void CBaseEntity::SetRenderColorB( byte b ) +{ + m_clrRender.SetB( b ); +} + +inline void CBaseEntity::SetRenderColorA( byte a ) +{ + m_clrRender.SetA( a ); +} + +inline void CBaseEntity::SetMoveCollide( MoveCollide_t val ) +{ + m_MoveCollide = val; +} + +inline bool CBaseEntity::IsTransparent() const +{ + return m_nRenderMode != kRenderNormal; +} + +inline int CBaseEntity::GetTextureFrameIndex( void ) +{ + return m_iTextureFrameIndex; +} + +inline void CBaseEntity::SetTextureFrameIndex( int iIndex ) +{ + m_iTextureFrameIndex = iIndex; +} + +//----------------------------------------------------------------------------- +// An inline version the game code can use +//----------------------------------------------------------------------------- +inline CCollisionProperty *CBaseEntity::CollisionProp() +{ + return &m_Collision; +} + +inline const CCollisionProperty *CBaseEntity::CollisionProp() const +{ + return &m_Collision; +} + +inline CServerNetworkProperty *CBaseEntity::NetworkProp() +{ + return &m_Network; +} + +inline const CServerNetworkProperty *CBaseEntity::NetworkProp() const +{ + return &m_Network; +} + +inline void CBaseEntity::ClearSolidFlags( void ) +{ + CollisionProp()->ClearSolidFlags(); +} + +inline void CBaseEntity::RemoveSolidFlags( int flags ) +{ + CollisionProp()->RemoveSolidFlags( flags ); +} + +inline void CBaseEntity::AddSolidFlags( int flags ) +{ + CollisionProp()->AddSolidFlags( flags ); +} + +inline int CBaseEntity::GetSolidFlags( void ) const +{ + return CollisionProp()->GetSolidFlags(); +} + +inline bool CBaseEntity::IsSolidFlagSet( int flagMask ) const +{ + return CollisionProp()->IsSolidFlagSet( flagMask ); +} + +inline bool CBaseEntity::IsSolid() const +{ + return CollisionProp()->IsSolid( ); +} + +inline void CBaseEntity::SetSolid( SolidType_t val ) +{ + CollisionProp()->SetSolid( val ); +} + +inline void CBaseEntity::SetSolidFlags( int flags ) +{ + CollisionProp()->SetSolidFlags( flags ); +} + +inline SolidType_t CBaseEntity::GetSolid() const +{ + return CollisionProp()->GetSolid(); +} + + +//----------------------------------------------------------------------------- +// Methods related to IServerUnknown +//----------------------------------------------------------------------------- +inline ICollideable *CBaseEntity::GetCollideable() +{ + return &m_Collision; +} + +inline IServerNetworkable *CBaseEntity::GetNetworkable() +{ + return &m_Network; +} + +inline CBaseEntity *CBaseEntity::GetBaseEntity() +{ + return this; +} + + +//----------------------------------------------------------------------------- +// Model related methods +//----------------------------------------------------------------------------- +inline void CBaseEntity::SetModelName( string_t name ) +{ + m_ModelName = name; + DispatchUpdateTransmitState(); +} + +inline string_t CBaseEntity::GetModelName( void ) const +{ + return m_ModelName; +} + +inline int CBaseEntity::GetModelIndex( void ) const +{ + return m_nModelIndex; +} + + + +//----------------------------------------------------------------------------- +// Methods relating to bounds +//----------------------------------------------------------------------------- +inline const Vector& CBaseEntity::WorldAlignMins( ) const +{ + Assert( !CollisionProp()->IsBoundsDefinedInEntitySpace() ); + Assert( CollisionProp()->GetCollisionAngles() == vec3_angle ); + return CollisionProp()->OBBMins(); +} + +inline const Vector& CBaseEntity::WorldAlignMaxs( ) const +{ + Assert( !CollisionProp()->IsBoundsDefinedInEntitySpace() ); + Assert( CollisionProp()->GetCollisionAngles() == vec3_angle ); + return CollisionProp()->OBBMaxs(); +} + +inline const Vector& CBaseEntity::WorldAlignSize( ) const +{ + Assert( !CollisionProp()->IsBoundsDefinedInEntitySpace() ); + Assert( CollisionProp()->GetCollisionAngles() == vec3_angle ); + return CollisionProp()->OBBSize(); +} + +// Returns a radius of a sphere *centered at the world space center* +// bounding the collision representation of the entity +inline float CBaseEntity::BoundingRadius() const +{ + return CollisionProp()->BoundingRadius(); +} + +inline bool CBaseEntity::IsPointSized() const +{ + return CollisionProp()->BoundingRadius() == 0.0f; +} + +inline void CBaseEntity::SetRenderMode( RenderMode_t nRenderMode ) +{ + m_nRenderMode = nRenderMode; +} + +inline RenderMode_t CBaseEntity::GetRenderMode() const +{ + return (RenderMode_t)m_nRenderMode.Get(); +} + + +//----------------------------------------------------------------------------- +// Methods to cast away const +//----------------------------------------------------------------------------- +inline Vector CBaseEntity::EyePosition( void ) const +{ + return const_cast<CBaseEntity*>(this)->EyePosition(); +} + +inline const QAngle &CBaseEntity::EyeAngles( void ) const // Direction of eyes in world space +{ + return const_cast<CBaseEntity*>(this)->EyeAngles(); +} + +inline const QAngle &CBaseEntity::LocalEyeAngles( void ) const // Direction of eyes +{ + return const_cast<CBaseEntity*>(this)->LocalEyeAngles(); +} + +inline Vector CBaseEntity::EarPosition( void ) const // position of ears +{ + return const_cast<CBaseEntity*>(this)->EarPosition(); +} + + +//----------------------------------------------------------------------------- +// Methods relating to networking +//----------------------------------------------------------------------------- +inline void CBaseEntity::NetworkStateChanged() +{ + NetworkProp()->NetworkStateChanged(); +} + + +inline void CBaseEntity::NetworkStateChanged( void *pVar ) +{ + // Make sure it's a semi-reasonable pointer. + Assert( (char*)pVar > (char*)this ); + Assert( (char*)pVar - (char*)this < 32768 ); + + // Good, they passed an offset so we can track this variable's change + // and avoid sending the whole entity. + NetworkProp()->NetworkStateChanged( (char*)pVar - (char*)this ); +} + + +//----------------------------------------------------------------------------- +// IHandleEntity overrides. +//----------------------------------------------------------------------------- +inline const CBaseHandle& CBaseEntity::GetRefEHandle() const +{ + return m_RefEHandle; +} + +inline void CBaseEntity::IncrementTransmitStateOwnedCounter() +{ + Assert( m_nTransmitStateOwnedCounter != 255 ); + m_nTransmitStateOwnedCounter++; +} + +inline void CBaseEntity::DecrementTransmitStateOwnedCounter() +{ + Assert( m_nTransmitStateOwnedCounter != 0 ); + m_nTransmitStateOwnedCounter--; +} + + +//----------------------------------------------------------------------------- +// Bullet firing (legacy)... +//----------------------------------------------------------------------------- +inline void CBaseEntity::FireBullets( int cShots, const Vector &vecSrc, + const Vector &vecDirShooting, const Vector &vecSpread, float flDistance, + int iAmmoType, int iTracerFreq, int firingEntID, int attachmentID, + int iDamage, CBaseEntity *pAttacker, bool bFirstShotAccurate, bool bPrimaryAttack ) +{ + FireBulletsInfo_t info; + info.m_iShots = cShots; + info.m_vecSrc = vecSrc; + info.m_vecDirShooting = vecDirShooting; + info.m_vecSpread = vecSpread; + info.m_flDistance = flDistance; + info.m_iAmmoType = iAmmoType; + info.m_iTracerFreq = iTracerFreq; + info.m_flDamage = iDamage; + info.m_pAttacker = pAttacker; + info.m_nFlags = bFirstShotAccurate ? FIRE_BULLETS_FIRST_SHOT_ACCURATE : 0; + info.m_bPrimaryAttack = bPrimaryAttack; + + FireBullets( info ); +} + +// Ugly technique to override base member functions +// Normally it's illegal to cast a pointer to a member function of a derived class to a pointer to a +// member function of a base class. static_cast is a sleezy way around that problem. + +#define SetThink( a ) ThinkSet( static_cast <void (CBaseEntity::*)(void)> (a), 0, NULL ) +#define SetContextThink( a, b, context ) ThinkSet( static_cast <void (CBaseEntity::*)(void)> (a), (b), context ) + +#ifdef _DEBUG +#define SetMoveDone( a ) \ + do \ + { \ + m_pfnMoveDone = static_cast <void (CBaseEntity::*)(void)> (a); \ + FunctionCheck( (void *)*((int *)((char *)this + ( offsetof(CBaseEntity,m_pfnMoveDone)))), "BaseMoveFunc" ); \ + } while ( 0 ) +#else +#define SetMoveDone( a ) \ + (void)(m_pfnMoveDone = static_cast <void (CBaseEntity::*)(void)> (a)) +#endif + + +inline bool FClassnameIs(CBaseEntity *pEntity, const char *szClassname) +{ + return pEntity->ClassMatches(szClassname); +} + +class CPointEntity : public CBaseEntity +{ +public: + DECLARE_CLASS( CPointEntity, CBaseEntity ); + + void Spawn( void ); + virtual int ObjectCaps( void ) { return BaseClass::ObjectCaps() & ~FCAP_ACROSS_TRANSITION; } + virtual bool KeyValue( const char *szKeyName, const char *szValue ); +private: +}; + +// Has a position + size +class CServerOnlyEntity : public CBaseEntity +{ + DECLARE_CLASS( CServerOnlyEntity, CBaseEntity ); +public: + CServerOnlyEntity() : CBaseEntity( true ) {} + + virtual int ObjectCaps( void ) { return (BaseClass::ObjectCaps() & ~FCAP_ACROSS_TRANSITION); } +}; + +// Has only a position, no size +class CServerOnlyPointEntity : public CServerOnlyEntity +{ + DECLARE_CLASS( CServerOnlyPointEntity, CServerOnlyEntity ); + +public: + virtual bool KeyValue( const char *szKeyName, const char *szValue ); +}; + +// Has no position or size +class CLogicalEntity : public CServerOnlyEntity +{ + DECLARE_CLASS( CLogicalEntity, CServerOnlyEntity ); + +public: + virtual bool KeyValue( const char *szKeyName, const char *szValue ); +}; + + +// Network proxy functions + +void SendProxy_Origin( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID ); +void SendProxy_OriginXY( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID ); +void SendProxy_OriginZ( const SendProp *pProp, const void *pStruct, const void *pData, DVariant *pOut, int iElement, int objectID ); + + +#endif // BASEENTITY_H |