376 lines
13 KiB
C
376 lines
13 KiB
C
|
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
|
|||
|
//
|
|||
|
// Purpose:
|
|||
|
//
|
|||
|
// $NoKeywords: $
|
|||
|
//
|
|||
|
//=============================================================================//
|
|||
|
|
|||
|
#ifndef ENTITYLIST_H
|
|||
|
#define ENTITYLIST_H
|
|||
|
|
|||
|
#ifdef _WIN32
|
|||
|
#pragma once
|
|||
|
#endif
|
|||
|
|
|||
|
#include "baseentity.h"
|
|||
|
|
|||
|
class IEntityListener;
|
|||
|
|
|||
|
abstract_class CBaseEntityClassList
|
|||
|
{
|
|||
|
public:
|
|||
|
CBaseEntityClassList();
|
|||
|
~CBaseEntityClassList();
|
|||
|
virtual void LevelShutdownPostEntity() = 0;
|
|||
|
|
|||
|
CBaseEntityClassList *m_pNextClassList;
|
|||
|
};
|
|||
|
|
|||
|
template< class T >
|
|||
|
class CEntityClassList : public CBaseEntityClassList
|
|||
|
{
|
|||
|
public:
|
|||
|
virtual void LevelShutdownPostEntity() { m_pClassList = NULL; }
|
|||
|
|
|||
|
void Insert( T *pEntity )
|
|||
|
{
|
|||
|
pEntity->m_pNext = m_pClassList;
|
|||
|
m_pClassList = pEntity;
|
|||
|
}
|
|||
|
|
|||
|
void Remove( T *pEntity )
|
|||
|
{
|
|||
|
T **pPrev = &m_pClassList;
|
|||
|
T *pCur = *pPrev;
|
|||
|
while ( pCur )
|
|||
|
{
|
|||
|
if ( pCur == pEntity )
|
|||
|
{
|
|||
|
*pPrev = pCur->m_pNext;
|
|||
|
return;
|
|||
|
}
|
|||
|
pPrev = &pCur->m_pNext;
|
|||
|
pCur = *pPrev;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
static T *m_pClassList;
|
|||
|
};
|
|||
|
|
|||
|
// Derive a class from this if you want to filter entity list searches
|
|||
|
abstract_class IEntityFindFilter
|
|||
|
{
|
|||
|
public:
|
|||
|
virtual bool ShouldFindEntity( CBaseEntity *pEntity ) = 0;
|
|||
|
virtual CBaseEntity *GetFilterResult( void ) = 0;
|
|||
|
};
|
|||
|
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
// Purpose: a global list of all the entities in the game. All iteration through
|
|||
|
// entities is done through this object.
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
class CGlobalEntityList : public CBaseEntityList
|
|||
|
{
|
|||
|
public:
|
|||
|
private:
|
|||
|
int m_iHighestEnt; // the topmost used array index
|
|||
|
int m_iNumEnts;
|
|||
|
int m_iNumEdicts;
|
|||
|
|
|||
|
bool m_bClearingEntities;
|
|||
|
CUtlVector<IEntityListener *> m_entityListeners;
|
|||
|
|
|||
|
public:
|
|||
|
IServerNetworkable* GetServerNetworkable( CBaseHandle hEnt ) const;
|
|||
|
CBaseNetworkable* GetBaseNetworkable( CBaseHandle hEnt ) const;
|
|||
|
CBaseEntity* GetBaseEntity( CBaseHandle hEnt ) const;
|
|||
|
edict_t* GetEdict( CBaseHandle hEnt ) const;
|
|||
|
|
|||
|
int NumberOfEntities( void );
|
|||
|
int NumberOfEdicts( void );
|
|||
|
|
|||
|
// mark an entity as deleted
|
|||
|
void AddToDeleteList( IServerNetworkable *ent );
|
|||
|
// call this before and after each frame to delete all of the marked entities.
|
|||
|
void CleanupDeleteList( void );
|
|||
|
int ResetDeleteList( void );
|
|||
|
|
|||
|
// frees all entities in the game
|
|||
|
void Clear( void );
|
|||
|
|
|||
|
// Returns true while in the Clear() call.
|
|||
|
bool IsClearingEntities() {return m_bClearingEntities;}
|
|||
|
|
|||
|
// add a class that gets notified of entity events
|
|||
|
void AddListenerEntity( IEntityListener *pListener );
|
|||
|
void RemoveListenerEntity( IEntityListener *pListener );
|
|||
|
|
|||
|
void ReportEntityFlagsChanged( CBaseEntity *pEntity, unsigned int flagsOld, unsigned int flagsNow );
|
|||
|
// Schedule this entity for notification once client messages have been sent
|
|||
|
void AddPostClientMessageEntity( CBaseEntity *pEntity );
|
|||
|
void PostClientMessagesSent();
|
|||
|
|
|||
|
// entity is about to be removed, notify the listeners
|
|||
|
void NotifyCreateEntity( CBaseEntity *pEnt );
|
|||
|
void NotifySpawn( CBaseEntity *pEnt );
|
|||
|
void NotifyRemoveEntity( CBaseEntity *pEnt );
|
|||
|
// iteration functions
|
|||
|
|
|||
|
// returns the next entity after pCurrentEnt; if pCurrentEnt is NULL, return the first entity
|
|||
|
CBaseEntity *NextEnt( CBaseEntity *pCurrentEnt );
|
|||
|
CBaseEntity *FirstEnt() { return NextEnt(NULL); }
|
|||
|
|
|||
|
// returns the next entity of the specified class, using RTTI
|
|||
|
template< class T >
|
|||
|
T *NextEntByClass( T *start )
|
|||
|
{
|
|||
|
for ( CBaseEntity *x = NextEnt( start ); x; x = NextEnt( x ) )
|
|||
|
{
|
|||
|
start = dynamic_cast<T*>( x );
|
|||
|
if ( start )
|
|||
|
return start;
|
|||
|
}
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
|
|||
|
// search functions
|
|||
|
bool IsEntityPtr( void *pTest );
|
|||
|
CBaseEntity *FindEntityByClassname( CBaseEntity *pStartEntity, const char *szName );
|
|||
|
CBaseEntity *FindEntityByName( CBaseEntity *pStartEntity, const char *szName, CBaseEntity *pSearchingEntity = NULL, CBaseEntity *pActivator = NULL, CBaseEntity *pCaller = NULL, IEntityFindFilter *pFilter = NULL );
|
|||
|
CBaseEntity *FindEntityByName( CBaseEntity *pStartEntity, string_t iszName, CBaseEntity *pSearchingEntity = NULL, CBaseEntity *pActivator = NULL, CBaseEntity *pCaller = NULL, IEntityFindFilter *pFilter = NULL )
|
|||
|
{
|
|||
|
return FindEntityByName( pStartEntity, STRING(iszName), pSearchingEntity, pActivator, pCaller, pFilter );
|
|||
|
}
|
|||
|
CBaseEntity *FindEntityInSphere( CBaseEntity *pStartEntity, const Vector &vecCenter, float flRadius );
|
|||
|
CBaseEntity *FindEntityByTarget( CBaseEntity *pStartEntity, const char *szName );
|
|||
|
CBaseEntity *FindEntityByModel( CBaseEntity *pStartEntity, const char *szModelName );
|
|||
|
CBaseEntity *FindEntityByOutputTarget( CBaseEntity *pStartEntity, string_t iTarget );
|
|||
|
|
|||
|
CBaseEntity *FindEntityByNameNearest( const char *szName, const Vector &vecSrc, float flRadius, CBaseEntity *pSearchingEntity = NULL, CBaseEntity *pActivator = NULL, CBaseEntity *pCaller = NULL );
|
|||
|
CBaseEntity *FindEntityByNameWithin( CBaseEntity *pStartEntity, const char *szName, const Vector &vecSrc, float flRadius, CBaseEntity *pSearchingEntity = NULL, CBaseEntity *pActivator = NULL, CBaseEntity *pCaller = NULL );
|
|||
|
CBaseEntity *FindEntityByClassnameNearest( const char *szName, const Vector &vecSrc, float flRadius );
|
|||
|
CBaseEntity *FindEntityByClassnameNearest2D( const char *szName, const Vector &vecSrc, float flRadius );
|
|||
|
CBaseEntity *FindEntityByClassnameWithin( CBaseEntity *pStartEntity , const char *szName, const Vector &vecSrc, float flRadius );
|
|||
|
CBaseEntity *FindEntityByClassnameWithin( CBaseEntity *pStartEntity , const char *szName, const Vector &vecMins, const Vector &vecMaxs );
|
|||
|
|
|||
|
CBaseEntity *FindEntityGeneric( CBaseEntity *pStartEntity, const char *szName, CBaseEntity *pSearchingEntity = NULL, CBaseEntity *pActivator = NULL, CBaseEntity *pCaller = NULL );
|
|||
|
CBaseEntity *FindEntityGenericWithin( CBaseEntity *pStartEntity, const char *szName, const Vector &vecSrc, float flRadius, CBaseEntity *pSearchingEntity = NULL, CBaseEntity *pActivator = NULL, CBaseEntity *pCaller = NULL );
|
|||
|
CBaseEntity *FindEntityGenericNearest( const char *szName, const Vector &vecSrc, float flRadius, CBaseEntity *pSearchingEntity = NULL, CBaseEntity *pActivator = NULL, CBaseEntity *pCaller = NULL );
|
|||
|
|
|||
|
CBaseEntity *FindEntityNearestFacing( const Vector &origin, const Vector &facing, float threshold);
|
|||
|
CBaseEntity *FindEntityClassNearestFacing( const Vector &origin, const Vector &facing, float threshold, char *classname);
|
|||
|
CBaseEntity *FindEntityByNetname( CBaseEntity *pStartEntity, const char *szModelName );
|
|||
|
|
|||
|
CBaseEntity *FindEntityProcedural( const char *szName, CBaseEntity *pSearchingEntity = NULL, CBaseEntity *pActivator = NULL, CBaseEntity *pCaller = NULL );
|
|||
|
|
|||
|
// Fast versions that require a (real) string_t, and won't do wildcarding
|
|||
|
CBaseEntity *FindEntityByClassnameFast( CBaseEntity *pStartEntity, string_t iszClassname );
|
|||
|
CBaseEntity *FindEntityByClassnameNearestFast( string_t iszClassname, const Vector &vecSrc, float flRadius );
|
|||
|
CBaseEntity *FindEntityByNameFast( CBaseEntity *pStartEntity, string_t iszName );
|
|||
|
|
|||
|
CGlobalEntityList();
|
|||
|
|
|||
|
// CBaseEntityList overrides.
|
|||
|
protected:
|
|||
|
|
|||
|
virtual void OnAddEntity( IHandleEntity *pEnt, CBaseHandle handle );
|
|||
|
virtual void OnRemoveEntity( IHandleEntity *pEnt, CBaseHandle handle );
|
|||
|
|
|||
|
};
|
|||
|
|
|||
|
extern CGlobalEntityList gEntList;
|
|||
|
|
|||
|
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
// Inlines.
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
inline edict_t* CGlobalEntityList::GetEdict( CBaseHandle hEnt ) const
|
|||
|
{
|
|||
|
IServerUnknown *pUnk = static_cast<IServerUnknown*>(LookupEntity( hEnt ));
|
|||
|
if ( pUnk )
|
|||
|
return pUnk->GetNetworkable()->GetEdict();
|
|||
|
else
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
|
|||
|
inline CBaseNetworkable* CGlobalEntityList::GetBaseNetworkable( CBaseHandle hEnt ) const
|
|||
|
{
|
|||
|
IServerUnknown *pUnk = static_cast<IServerUnknown*>(LookupEntity( hEnt ));
|
|||
|
if ( pUnk )
|
|||
|
return pUnk->GetNetworkable()->GetBaseNetworkable();
|
|||
|
else
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
|
|||
|
inline IServerNetworkable* CGlobalEntityList::GetServerNetworkable( CBaseHandle hEnt ) const
|
|||
|
{
|
|||
|
IServerUnknown *pUnk = static_cast<IServerUnknown*>(LookupEntity( hEnt ));
|
|||
|
if ( pUnk )
|
|||
|
return pUnk->GetNetworkable();
|
|||
|
else
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
|
|||
|
inline CBaseEntity* CGlobalEntityList::GetBaseEntity( CBaseHandle hEnt ) const
|
|||
|
{
|
|||
|
IServerUnknown *pUnk = static_cast<IServerUnknown*>(LookupEntity( hEnt ));
|
|||
|
if ( pUnk )
|
|||
|
return pUnk->GetBaseEntity();
|
|||
|
else
|
|||
|
return NULL;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
// Common finds
|
|||
|
#if 0
|
|||
|
|
|||
|
template <class ENT_TYPE>
|
|||
|
inline bool FindEntityByName( const char *pszName, ENT_TYPE **ppResult)
|
|||
|
{
|
|||
|
CBaseEntity *pBaseEntity = gEntList.FindEntityByName( NULL, pszName );
|
|||
|
|
|||
|
if ( pBaseEntity )
|
|||
|
*ppResult = dynamic_cast<ENT_TYPE *>( pBaseEntity );
|
|||
|
else
|
|||
|
*ppResult = NULL;
|
|||
|
|
|||
|
return ( *ppResult != NULL );
|
|||
|
}
|
|||
|
|
|||
|
template <>
|
|||
|
inline bool FindEntityByName<CBaseEntity>( const char *pszName, CBaseEntity **ppResult)
|
|||
|
{
|
|||
|
*ppResult = gEntList.FindEntityByName( NULL, pszName );
|
|||
|
return ( *ppResult != NULL );
|
|||
|
}
|
|||
|
|
|||
|
template <>
|
|||
|
inline bool FindEntityByName<CAI_BaseNPC>( const char *pszName, CAI_BaseNPC **ppResult)
|
|||
|
{
|
|||
|
CBaseEntity *pBaseEntity = gEntList.FindEntityByName( NULL, pszName );
|
|||
|
|
|||
|
if ( pBaseEntity )
|
|||
|
*ppResult = pBaseEntity->MyNPCPointer();
|
|||
|
else
|
|||
|
*ppResult = NULL;
|
|||
|
|
|||
|
return ( *ppResult != NULL );
|
|||
|
}
|
|||
|
#endif
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
// Purpose: Simple object for storing a list of objects
|
|||
|
//-----------------------------------------------------------------------------
|
|||
|
struct entitem_t
|
|||
|
{
|
|||
|
EHANDLE hEnt;
|
|||
|
struct entitem_t *pNext;
|
|||
|
|
|||
|
// uses pool memory
|
|||
|
static void* operator new( size_t stAllocateBlock );
|
|||
|
static void *operator new( size_t stAllocateBlock, int nBlockUse, const char *pFileName, int nLine );
|
|||
|
static void operator delete( void *pMem );
|
|||
|
static void operator delete( void *pMem, int nBlockUse, const char *pFileName, int nLine ) { operator delete( pMem ); }
|
|||
|
};
|
|||
|
|
|||
|
class CEntityList
|
|||
|
{
|
|||
|
public:
|
|||
|
CEntityList();
|
|||
|
~CEntityList();
|
|||
|
|
|||
|
int m_iNumItems;
|
|||
|
entitem_t *m_pItemList; // null terminated singly-linked list
|
|||
|
|
|||
|
void AddEntity( CBaseEntity * );
|
|||
|
void DeleteEntity( CBaseEntity * );
|
|||
|
};
|
|||
|
|
|||
|
enum notify_system_event_t
|
|||
|
{
|
|||
|
NOTIFY_EVENT_TELEPORT = 0,
|
|||
|
NOTIFY_EVENT_DESTROY,
|
|||
|
};
|
|||
|
|
|||
|
struct notify_teleport_params_t
|
|||
|
{
|
|||
|
Vector prevOrigin;
|
|||
|
QAngle prevAngles;
|
|||
|
bool physicsRotate;
|
|||
|
};
|
|||
|
|
|||
|
struct notify_destroy_params_t
|
|||
|
{
|
|||
|
};
|
|||
|
|
|||
|
struct notify_system_event_params_t
|
|||
|
{
|
|||
|
union
|
|||
|
{
|
|||
|
const notify_teleport_params_t *pTeleport;
|
|||
|
const notify_destroy_params_t *pDestroy;
|
|||
|
};
|
|||
|
notify_system_event_params_t( const notify_teleport_params_t *pInTeleport ) { pTeleport = pInTeleport; }
|
|||
|
notify_system_event_params_t( const notify_destroy_params_t *pInDestroy ) { pDestroy = pInDestroy; }
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
abstract_class INotify
|
|||
|
{
|
|||
|
public:
|
|||
|
// Add notification for an entity
|
|||
|
virtual void AddEntity( CBaseEntity *pNotify, CBaseEntity *pWatched ) = 0;
|
|||
|
|
|||
|
// Remove notification for an entity
|
|||
|
virtual void RemoveEntity( CBaseEntity *pNotify, CBaseEntity *pWatched ) = 0;
|
|||
|
|
|||
|
// Call the named input in each entity who is watching pEvent's status
|
|||
|
virtual void ReportNamedEvent( CBaseEntity *pEntity, const char *pEventName ) = 0;
|
|||
|
|
|||
|
// System events don't make sense as inputs, so are handled through a generic notify function
|
|||
|
virtual void ReportSystemEvent( CBaseEntity *pEntity, notify_system_event_t eventType, const notify_system_event_params_t ¶ms ) = 0;
|
|||
|
|
|||
|
inline void ReportDestroyEvent( CBaseEntity *pEntity )
|
|||
|
{
|
|||
|
notify_destroy_params_t destroy;
|
|||
|
ReportSystemEvent( pEntity, NOTIFY_EVENT_DESTROY, notify_system_event_params_t(&destroy) );
|
|||
|
}
|
|||
|
|
|||
|
inline void ReportTeleportEvent( CBaseEntity *pEntity, const Vector &prevOrigin, const QAngle &prevAngles, bool physicsRotate )
|
|||
|
{
|
|||
|
notify_teleport_params_t teleport;
|
|||
|
teleport.prevOrigin = prevOrigin;
|
|||
|
teleport.prevAngles = prevAngles;
|
|||
|
teleport.physicsRotate = physicsRotate;
|
|||
|
ReportSystemEvent( pEntity, NOTIFY_EVENT_TELEPORT, notify_system_event_params_t(&teleport) );
|
|||
|
}
|
|||
|
|
|||
|
// Remove this entity from the notify list
|
|||
|
virtual void ClearEntity( CBaseEntity *pNotify ) = 0;
|
|||
|
};
|
|||
|
|
|||
|
// Implement this class and register with gEntList to receive entity create/delete notification
|
|||
|
class IEntityListener
|
|||
|
{
|
|||
|
public:
|
|||
|
virtual void OnEntityCreated( CBaseEntity *pEntity ) {};
|
|||
|
virtual void OnEntitySpawned( CBaseEntity *pEntity ) {};
|
|||
|
virtual void OnEntityDeleted( CBaseEntity *pEntity ) {};
|
|||
|
};
|
|||
|
|
|||
|
// singleton
|
|||
|
extern INotify *g_pNotify;
|
|||
|
|
|||
|
void EntityTouch_Add( CBaseEntity *pEntity );
|
|||
|
int AimTarget_ListCount();
|
|||
|
int AimTarget_ListCopy( CBaseEntity *pList[], int listMax );
|
|||
|
CBaseEntity *AimTarget_ListElement( int iIndex );
|
|||
|
void AimTarget_ForceRepopulateList();
|
|||
|
|
|||
|
void SimThink_EntityChanged( CBaseEntity *pEntity );
|
|||
|
int SimThink_ListCount();
|
|||
|
int SimThink_ListCopy( CBaseEntity *pList[], int listMax );
|
|||
|
|
|||
|
#endif // ENTITYLIST_H
|