1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
|
//========= Copyright 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 );
// entity is about to be removed, notify the listeners
void NotifyCreateEntity( CBaseEntity *pEnt );
void NotifySpawn( CBaseEntity *pEnt );
void NotifyRemoveEntity( CBaseHandle hEnt );
// 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 *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 *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 *FindEntityProcedural( const char *szName, CBaseEntity *pSearchingEntity = NULL, CBaseEntity *pActivator = NULL, CBaseEntity *pCaller = NULL );
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 );
void AimTarget_ForceRepopulateList();
void SimThink_EntityChanged( CBaseEntity *pEntity );
int SimThink_ListCount();
int SimThink_ListCopy( CBaseEntity *pList[], int listMax );
#endif // ENTITYLIST_H
|