upload "kind" alien swarm

This commit is contained in:
nillerusr
2023-10-03 17:23:56 +03:00
parent b7bd94c52e
commit 7d3c0d8b5a
4229 changed files with 462903 additions and 495158 deletions

View File

@@ -1,4 +1,4 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
@@ -17,6 +17,9 @@
#include "ai_initutils.h"
#include "globalstate.h"
#include "datacache/imdlcache.h"
#include "tier1/utlhash.h"
#ifdef HL2_DLL
#include "npc_playercompanion.h"
@@ -25,7 +28,6 @@
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
CBaseEntity *FindPickerEntity( CBasePlayer *pPlayer );
void SceneManager_ClientActive( CBasePlayer *player );
static CUtlVector<IServerNetworkable*> g_DeleteList;
@@ -75,6 +77,14 @@ public:
// IEntityListener
virtual void OnEntityCreated( CBaseEntity *pEntity ) {}
virtual void OnEntitySpawned( CBaseEntity *pEntity )
{
if ( ShouldAddEntity( pEntity ) )
{
RemoveEntity( pEntity );
AddEntity( pEntity );
}
}
virtual void OnEntityDeleted( CBaseEntity *pEntity )
{
if ( !(pEntity->GetFlags() & FL_AIMTARGET) )
@@ -95,6 +105,7 @@ public:
m_targetList.FastRemove( index );
}
}
int ListCount() { return m_targetList.Count(); }
int ListCopy( CBaseEntity *pList[], int listMax )
{
@@ -102,6 +113,10 @@ public:
memcpy( pList, m_targetList.Base(), sizeof(CBaseEntity *) * count );
return count;
}
CBaseEntity *ListElement( int iIndex )
{
return m_targetList[iIndex];
}
private:
CUtlVector<CBaseEntity *> m_targetList;
@@ -117,6 +132,10 @@ int AimTarget_ListCopy( CBaseEntity *pList[], int listMax )
{
return g_AimManager.ListCopy( pList, listMax );
}
CBaseEntity *AimTarget_ListElement( int iIndex )
{
return g_AimManager.ListElement( iIndex );
}
void AimTarget_ForceRepopulateList()
{
g_AimManager.ForceRepopulateList();
@@ -161,7 +180,6 @@ public:
void OnEntityCreated( CBaseEntity *pEntity )
{
Assert( m_entinfoIndex[pEntity->GetRefEHandle().GetEntryIndex()] == 0xFFFF );
}
void OnEntityDeleted( CBaseEntity *pEntity )
{
@@ -244,6 +262,7 @@ public:
}
else
{
Assert( m_simThinkList[m_entinfoIndex[index]].entEntry == index );
// updating existing entry - if no sim, reset think time
if ( pEntity->IsEFlagSet(EFL_NO_GAME_PHYSICS_SIMULATION) )
{
@@ -280,6 +299,39 @@ void SimThink_EntityChanged( CBaseEntity *pEntity )
g_SimThinkManager.EntityChanged( pEntity );
}
// This manages a list of entities queued up to receive PostClientMessages callbacks
class CPostClientMessageManager
{
public:
void LevelShutdownPostEntity()
{
m_list.Purge();
}
void AddEntity( CBaseEntity *pEntity )
{
MEM_ALLOC_CREDIT();
m_list.AddToTail( (unsigned short)pEntity->GetRefEHandle().GetEntryIndex() );
}
void PostClientMessagesSent()
{
for ( int i = m_list.Count()-1; i >= 0; --i )
{
CBaseEntity *pEntity = (CBaseEntity *)gEntList.GetEntInfoPtrByIndex( m_list[i] )->m_pEntity;
if ( pEntity )
{
pEntity->PostClientMessagesSent();
}
}
m_list.RemoveAll();
}
private:
// UNDONE: Need to use ehandles instead?
CUtlVector<unsigned short> m_list;
};
static CPostClientMessageManager g_PostClientManager;
static CBaseEntityClassList *s_pClassLists = NULL;
CBaseEntityClassList::CBaseEntityClassList()
{
@@ -290,6 +342,40 @@ CBaseEntityClassList::~CBaseEntityClassList()
{
}
//-----------------------------------------------------------------------------
// Entity hash tables
//-----------------------------------------------------------------------------
struct EntsByStringList_t
{
string_t iszStr;
CBaseEntity *pHead;
};
class CEntsByStringHashFuncs
{
public:
CEntsByStringHashFuncs( int ) {}
bool operator()( const EntsByStringList_t &lhs, const EntsByStringList_t &rhs ) const
{
return lhs.iszStr == rhs.iszStr;
}
unsigned int operator()( const EntsByStringList_t &item ) const
{
COMPILE_TIME_ASSERT( sizeof(char *) == sizeof(int) );
return HashInt( (int)item.iszStr.ToCStr() );
}
};
typedef CUtlHash<EntsByStringList_t , CEntsByStringHashFuncs, CEntsByStringHashFuncs > CEntsByStringTable;
//-------------------------------------
CEntsByStringTable g_EntsByClassname( 512 );
//-----------------------------------------------------------------------------
CGlobalEntityList::CGlobalEntityList()
{
m_iHighestEnt = m_iNumEnts = m_iNumEdicts = 0;
@@ -377,6 +463,16 @@ void CGlobalEntityList::Clear( void )
// free the memory
g_DeleteList.Purge();
#ifdef _DEBUG
for ( UtlHashHandle_t handle = g_EntsByClassname.GetFirstHandle(); g_EntsByClassname.IsValidHandle(handle); handle = g_EntsByClassname.GetNextHandle(handle) )
{
EntsByStringList_t &element = g_EntsByClassname[handle];
Assert( element.pHead == NULL );
}
#endif
g_EntsByClassname.RemoveAll();
CBaseEntity::m_nDebugPlayer = -1;
CBaseEntity::m_bInDebugSelect = false;
m_iHighestEnt = 0;
@@ -455,6 +551,15 @@ void CGlobalEntityList::ReportEntityFlagsChanged( CBaseEntity *pEntity, unsigned
}
}
void CGlobalEntityList::AddPostClientMessageEntity( CBaseEntity *pEntity )
{
g_PostClientManager.AddEntity( pEntity );
}
void CGlobalEntityList::PostClientMessagesSent()
{
g_PostClientManager.PostClientMessagesSent();
}
//-----------------------------------------------------------------------------
// Purpose: Used to confirm a pointer is a pointer to an entity, useful for
// asserts.
@@ -499,6 +604,23 @@ CBaseEntity *CGlobalEntityList::FindEntityByClassname( CBaseEntity *pStartEntity
return NULL;
}
CBaseEntity *CGlobalEntityList::FindEntityByClassnameFast( CBaseEntity *pStartEntity, string_t iszClassname )
{
if ( pStartEntity )
{
return pStartEntity->m_pNextByClass;
}
EntsByStringList_t key = { iszClassname };
UtlHashHandle_t hEntry = g_EntsByClassname.Find( key );
if ( hEntry != g_EntsByClassname.InvalidHandle() )
{
return g_EntsByClassname[hEntry].pHead;
}
return NULL;
}
//-----------------------------------------------------------------------------
// Purpose: Finds an entity given a procedural name.
@@ -551,12 +673,13 @@ CBaseEntity *CGlobalEntityList::FindEntityProcedural( const char *szName, CBaseE
}
else if ( FStrEq( pName, "picker" ) )
{
return FindPickerEntity( UTIL_PlayerByIndex(1) );
return UTIL_PlayerByIndex(1) ? UTIL_PlayerByIndex(1)->FindPickerEntity() : NULL;
}
else if ( FStrEq( pName, "self" ) )
{
return pSearchingEntity;
}
else
{
Warning( "Invalid entity search name %s\n", szName );
@@ -602,7 +725,7 @@ CBaseEntity *CGlobalEntityList::FindEntityByName( CBaseEntity *pStartEntity, con
continue;
}
if ( !ent->m_iName )
if ( !ent->m_iName.Get() )
continue;
if ( ent->NameMatches( szName ) )
@@ -617,6 +740,34 @@ CBaseEntity *CGlobalEntityList::FindEntityByName( CBaseEntity *pStartEntity, con
return NULL;
}
CBaseEntity *CGlobalEntityList::FindEntityByNameFast( CBaseEntity *pStartEntity, string_t iszName )
{
if ( iszName == NULL_STRING || STRING(iszName)[0] == 0 )
return NULL;
const CEntInfo *pInfo = pStartEntity ? GetEntInfoPtr( pStartEntity->GetRefEHandle() )->m_pNext : FirstEntInfo();
for ( ;pInfo; pInfo = pInfo->m_pNext )
{
CBaseEntity *ent = (CBaseEntity *)pInfo->m_pEntity;
if ( !ent )
{
DevWarning( "NULL entity in global entity list!\n" );
continue;
}
if ( !ent->m_iName.Get() )
continue;
if ( ent->m_iName.Get() == iszName )
{
return ent;
}
}
return NULL;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : pStartEntity -
@@ -676,6 +827,48 @@ CBaseEntity *CGlobalEntityList::FindEntityByTarget( CBaseEntity *pStartEntity, c
}
//-----------------------------------------------------------------------------
// Purpose: Iterates the entities with a given target.
// Input : pStartEntity -
// szName -
//-----------------------------------------------------------------------------
// FIXME: obsolete, remove
CBaseEntity *CGlobalEntityList::FindEntityByOutputTarget( CBaseEntity *pStartEntity, string_t iTarget )
{
const CEntInfo *pInfo = pStartEntity ? GetEntInfoPtr( pStartEntity->GetRefEHandle() )->m_pNext : FirstEntInfo();
for ( ;pInfo; pInfo = pInfo->m_pNext )
{
CBaseEntity *ent = (CBaseEntity *)pInfo->m_pEntity;
if ( !ent )
{
DevWarning( "NULL entity in global entity list!\n" );
continue;
}
datamap_t *dmap = ent->GetDataDescMap();
while ( dmap )
{
int fields = dmap->dataNumFields;
for ( int i = 0; i < fields; i++ )
{
typedescription_t *dataDesc = &dmap->dataDesc[i];
if ( ( dataDesc->fieldType == FIELD_CUSTOM ) && ( dataDesc->flags & FTYPEDESC_OUTPUT ) )
{
CBaseEntityOutput *pOutput = (CBaseEntityOutput *)((int)ent + (int)dataDesc->fieldOffset);
if ( pOutput->GetActionForTarget( iTarget ) )
return ent;
}
}
dmap = dmap->baseMap;
}
}
return NULL;
}
//-----------------------------------------------------------------------------
// Purpose: Used to iterate all the entities within a sphere.
// Input : pStartEntity -
@@ -834,6 +1027,78 @@ CBaseEntity *CGlobalEntityList::FindEntityByClassnameNearest( const char *szName
}
CBaseEntity *CGlobalEntityList::FindEntityByClassnameNearestFast( string_t iszName, const Vector &vecSrc, float flRadius )
{
CBaseEntity *pEntity = NULL;
//
// Check for matching class names within the search radius.
//
float flMaxDist2 = flRadius * flRadius;
if (flMaxDist2 == 0)
{
flMaxDist2 = MAX_TRACE_LENGTH * MAX_TRACE_LENGTH;
}
CBaseEntity *pSearch = NULL;
while ((pSearch = gEntList.FindEntityByClassnameFast( pSearch, iszName )) != NULL)
{
if ( !pSearch->edict() )
continue;
float flDist2 = (pSearch->GetAbsOrigin() - vecSrc).LengthSqr();
if (flMaxDist2 > flDist2)
{
pEntity = pSearch;
flMaxDist2 = flDist2;
}
}
return pEntity;
}
//-----------------------------------------------------------------------------
// Purpose: Finds the nearest entity by class name withing given search radius.
// Input : szName - Entity name to search for. Treated as a target name first,
// then as an entity class name, ie "info_target".
// vecSrc - Center of search radius.
// flRadius - Search radius for classname search, 0 to search everywhere.
// Output : Returns a pointer to the found entity, NULL if none.
//-----------------------------------------------------------------------------
CBaseEntity *CGlobalEntityList::FindEntityByClassnameNearest2D( const char *szName, const Vector &vecSrc, float flRadius )
{
CBaseEntity *pEntity = NULL;
//
// Check for matching class names within the search radius.
//
float flMaxDist2 = flRadius * flRadius;
if (flMaxDist2 == 0)
{
flMaxDist2 = MAX_TRACE_LENGTH * MAX_TRACE_LENGTH;
}
CBaseEntity *pSearch = NULL;
while ((pSearch = gEntList.FindEntityByClassname( pSearch, szName )) != NULL)
{
if ( !pSearch->edict() )
continue;
float flDist2 = (pSearch->GetAbsOrigin().AsVector2D() - vecSrc.AsVector2D()).LengthSqr();
if (flMaxDist2 > flDist2)
{
pEntity = pSearch;
flMaxDist2 = flDist2;
}
}
return pEntity;
}
//-----------------------------------------------------------------------------
// Purpose: Finds the first entity within radius distance by class name.
@@ -857,12 +1122,13 @@ CBaseEntity *CGlobalEntityList::FindEntityByClassnameWithin( CBaseEntity *pStart
while ((pEntity = gEntList.FindEntityByClassname( pEntity, szName )) != NULL)
{
if ( !pEntity->edict() )
if ( !pEntity->edict() && !pEntity->IsEFlagSet( EFL_SERVER_ONLY ) )
continue;
float flDist2 = (pEntity->GetAbsOrigin() - vecSrc).LengthSqr();
if (flMaxDist2 > flDist2)
// Instead of checking absorigin vs sphere, check if the obb intersects the sphere.
Vector vecRelativeCenter;
pEntity->CollisionProp()->WorldToCollisionSpace( vecSrc, &vecRelativeCenter );
if ( IsBoxIntersectingSphere( pEntity->CollisionProp()->OBBMins(), pEntity->CollisionProp()->OBBMaxs(), vecRelativeCenter, flRadius ) )
{
return pEntity;
}
@@ -1133,6 +1399,25 @@ void CGlobalEntityList::NotifyCreateEntity( CBaseEntity *pEnt )
if ( !pEnt )
return;
// Make sure no one is trying to build an entity without game strings.
Assert( MAKE_STRING( pEnt->GetClassname() ) == FindPooledString( pEnt->GetClassname() ) &&
( pEnt->GetEntityName() == NULL_STRING || pEnt->GetEntityName() == FindPooledString( pEnt->GetEntityName().ToCStr() ) ) );
Assert( pEnt->m_pPrevByClass == NULL && pEnt->m_pNextByClass == NULL && pEnt->m_ListByClass == g_EntsByClassname.InvalidHandle() );
EntsByStringList_t dummyEntry = { MAKE_STRING( pEnt->GetClassname() ), 0 };
UtlHashHandle_t hEntry = g_EntsByClassname.Insert( dummyEntry );
EntsByStringList_t *pEntry = &g_EntsByClassname[hEntry];
pEnt->m_ListByClass = hEntry;
if ( pEntry->pHead )
{
pEntry->pHead->m_pPrevByClass = pEnt;
pEnt->m_pNextByClass = pEntry->pHead;
Assert( pEnt->m_pPrevByClass == NULL );
}
pEntry->pHead = pEnt;
//DevMsg(2,"Deleted %s\n", pBaseEnt->GetClassname() );
for ( int i = m_entityListeners.Count()-1; i >= 0; i-- )
{
@@ -1155,9 +1440,8 @@ void CGlobalEntityList::NotifySpawn( CBaseEntity *pEnt )
// NOTE: This doesn't happen in OnRemoveEntity() specifically because
// listeners may want to reference the object as it's being deleted
// OnRemoveEntity isn't called until the destructor and all data is invalid.
void CGlobalEntityList::NotifyRemoveEntity( CBaseHandle hEnt )
void CGlobalEntityList::NotifyRemoveEntity( CBaseEntity *pBaseEnt )
{
CBaseEntity *pBaseEnt = GetBaseEntity( hEnt );
if ( !pBaseEnt )
return;
@@ -1166,6 +1450,31 @@ void CGlobalEntityList::NotifyRemoveEntity( CBaseHandle hEnt )
{
m_entityListeners[i]->OnEntityDeleted( pBaseEnt );
}
if ( pBaseEnt->m_ListByClass != g_EntsByClassname.InvalidHandle() )
{
EntsByStringList_t *pEntry = &g_EntsByClassname[pBaseEnt->m_ListByClass];
if ( pEntry->pHead == pBaseEnt )
{
pEntry->pHead = pBaseEnt->m_pNextByClass;
// Don't remove empty list, on the assumption that the number of classes that are not referenced again is small
// Plus during map load we get a lot of precache others that hit this [8/8/2008 tom]
}
Assert( g_EntsByClassname[pBaseEnt->m_ListByClass].pHead != pBaseEnt );
if ( pBaseEnt->m_pNextByClass )
{
pBaseEnt->m_pNextByClass->m_pPrevByClass = pBaseEnt->m_pPrevByClass;
}
if ( pBaseEnt->m_pPrevByClass )
{
pBaseEnt->m_pPrevByClass->m_pNextByClass = pBaseEnt->m_pNextByClass;
}
pBaseEnt->m_pPrevByClass = pBaseEnt->m_pNextByClass = NULL;
pBaseEnt->m_ListByClass = g_EntsByClassname.InvalidHandle();
}
}
@@ -1413,6 +1722,7 @@ public:
{
g_TouchManager.LevelShutdownPostEntity();
g_AimManager.LevelShutdownPostEntity();
g_PostClientManager.LevelShutdownPostEntity();
g_SimThinkManager.LevelShutdownPostEntity();
#ifdef HL2_DLL
OverrideMoveCache_LevelShutdownPostEntity();
@@ -1469,7 +1779,7 @@ public:
// Allocate a CBasePlayer for pev, and call spawn
if ( nPlayerIndex >= 0 )
{
edict_t *pEdict = engine->PEntityOfEntIndex( nPlayerIndex );
edict_t *pEdict = INDEXENT( nPlayerIndex );
ClientPutInServer( pEdict, "unnamed" );
ClientActive( pEdict, false );
@@ -1569,9 +1879,6 @@ private:
CON_COMMAND(report_entities, "Lists all entities")
{
if ( !UTIL_IsCommandIssuedByServerAdmin() )
return;
CSortedEntityList list;
CBaseEntity *pEntity = gEntList.FirstEnt();
while ( pEntity )
@@ -1585,9 +1892,6 @@ CON_COMMAND(report_entities, "Lists all entities")
CON_COMMAND(report_touchlinks, "Lists all touchlinks")
{
if ( !UTIL_IsCommandIssuedByServerAdmin() )
return;
CSortedEntityList list;
CBaseEntity *pEntity = gEntList.FirstEnt();
const char *pClassname = NULL;
@@ -1617,9 +1921,6 @@ CON_COMMAND(report_touchlinks, "Lists all touchlinks")
CON_COMMAND(report_simthinklist, "Lists all simulating/thinking entities")
{
if ( !UTIL_IsCommandIssuedByServerAdmin() )
return;
CBaseEntity *pTmp[NUM_ENT_ENTRIES];
int count = SimThink_ListCopy( pTmp, ARRAYSIZE(pTmp) );