summaryrefslogtreecommitdiff
path: root/game/server/tf/tf_entity_spawner.cpp
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /game/server/tf/tf_entity_spawner.cpp
downloadarchived-source-engine-2018-hl2-src-3bf9df6b2785fa6d951086978a3e66f49427166a.tar.xz
archived-source-engine-2018-hl2-src-3bf9df6b2785fa6d951086978a3e66f49427166a.zip
Diffstat (limited to 'game/server/tf/tf_entity_spawner.cpp')
-rw-r--r--game/server/tf/tf_entity_spawner.cpp261
1 files changed, 261 insertions, 0 deletions
diff --git a/game/server/tf/tf_entity_spawner.cpp b/game/server/tf/tf_entity_spawner.cpp
new file mode 100644
index 0000000..46e9f0d
--- /dev/null
+++ b/game/server/tf/tf_entity_spawner.cpp
@@ -0,0 +1,261 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// TF Entity Spawner
+//
+//=============================================================================
+
+#include "cbase.h"
+#include "tf_entity_spawner.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+
+//-----------------------------------------------------------------------------
+// CEntitySpawnManager
+//-----------------------------------------------------------------------------
+BEGIN_DATADESC( CEntitySpawnManager )
+
+ // Fields
+ DEFINE_KEYFIELD( m_iszEntityName, FIELD_STRING, "entity_name" ),
+ DEFINE_KEYFIELD( m_iEntityCount, FIELD_INTEGER, "entity_count" ),
+ DEFINE_KEYFIELD( m_iRespawnTime, FIELD_INTEGER, "respawn_time" ),
+ DEFINE_KEYFIELD( m_bDropToGround, FIELD_BOOLEAN, "drop_to_ground" ),
+ DEFINE_KEYFIELD( m_bRandomRotation, FIELD_BOOLEAN, "random_rotation" ),
+
+ // Outputs
+ // ON RESPAWN ?
+
+END_DATADESC()
+
+LINK_ENTITY_TO_CLASS( entity_spawn_manager, CEntitySpawnManager );
+
+//-----------------------------------------------------------------------------
+//
+//-----------------------------------------------------------------------------
+void CEntitySpawnManager::Spawn( void )
+{
+ BaseClass::Spawn();
+
+ SetNextThink( TICK_NEVER_THINK );
+ SetThink( NULL );
+}
+
+//-----------------------------------------------------------------------------
+// Stores related spawn points.
+//-----------------------------------------------------------------------------
+void CEntitySpawnManager::RegisterSpawnPoint( CEntitySpawnPoint* pNewPoint )
+{
+ m_SpawnPoints.AddToHead( pNewPoint );
+}
+
+//-----------------------------------------------------------------------------
+//
+//-----------------------------------------------------------------------------
+void CEntitySpawnManager::Activate( void )
+{
+ BaseClass::Activate();
+
+// AssertMsg1( 0, ("entity_spawn_manager active with %i points!"), m_SpawnPoints.Count() );
+
+ // Don't spawn more objects than we have points.
+ m_iMaxSpawnedEntities = MIN( m_SpawnPoints.Count(), m_iEntityCount );
+
+ if ( !m_iszEntityName || (m_iMaxSpawnedEntities == 0) )
+ {
+ AssertMsg1( 0, ("entity_spawn_manager %s active with nothing to spawn!"), GetEntityName().ToCStr() );
+ return;
+ }
+
+ // Perform initial spawn.
+ SpawnAllEntities();
+}
+
+//-----------------------------------------------------------------------------
+// Populates a random set of spawn points with objects, up to our max.
+//-----------------------------------------------------------------------------
+void CEntitySpawnManager::SpawnAllEntities()
+{
+ int iNumUsed = 0;
+ for ( int i=0; i<m_SpawnPoints.Count(); ++i )
+ {
+ if ( m_SpawnPoints[i]->IsUsed() )
+ {
+ iNumUsed++;
+ }
+ }
+
+ int iNumToSpawn = m_iMaxSpawnedEntities - iNumUsed;
+ if ( iNumToSpawn <= 0 )
+ return;
+
+ while ( iNumToSpawn )
+ {
+ SpawnEntity();
+ iNumToSpawn--;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Spawns a single entity at a random location.
+//-----------------------------------------------------------------------------
+bool CEntitySpawnManager::SpawnEntity()
+{
+ return SpawnEntityAt( GetRandomUnusedIndex() );
+}
+
+//-----------------------------------------------------------------------------
+// Returns a random unused point.
+//-----------------------------------------------------------------------------
+int CEntitySpawnManager::GetRandomUnusedIndex()
+{
+ int iStartIndex = rand() % m_SpawnPoints.Count();
+
+ for ( int i=0; i<m_SpawnPoints.Count(); ++i )
+ {
+ int index = i+iStartIndex;
+ if ( index >= m_SpawnPoints.Count() )
+ index -= m_SpawnPoints.Count();
+ CEntitySpawnPoint *pPoint = m_SpawnPoints[index];
+ if ( !pPoint || pPoint->IsUsed() )
+ continue;
+ else
+ return index;
+ }
+
+ return -1;
+}
+
+//-----------------------------------------------------------------------------
+// Creates the entity.
+//-----------------------------------------------------------------------------
+bool CEntitySpawnManager::SpawnEntityAt( int iIndex )
+{
+ if ( iIndex == -1 )
+ return false;
+
+ CEntitySpawnPoint *pPoint = m_SpawnPoints[iIndex];
+ if ( !pPoint )
+ return false;
+
+ CBaseEntity *pEnt = CreateEntityByName( m_iszEntityName.ToCStr() );
+ if ( !pEnt )
+ return false;
+
+ Vector origin = pPoint->GetAbsOrigin();
+ Vector mins, maxs, mins_o, maxs_o;
+ pEnt->CollisionProp()->WorldSpaceAABB( &mins, &maxs );
+ mins_o = origin + mins;
+ maxs_o = origin + mins;
+ if ( !UTIL_IsSpaceEmpty( pEnt, mins_o, maxs_o ) )
+ {
+ UTIL_Remove( pEnt );
+ return false;
+ }
+
+ if ( m_bDropToGround )
+ {
+ trace_t trace;
+ UTIL_TraceHull( origin, origin + Vector( 0, 0, -500 ), mins, maxs, MASK_SOLID, pEnt, COLLISION_GROUP_NONE, &trace );
+ origin = trace.endpos;
+ }
+
+ pEnt->SetAbsOrigin( origin );
+ DispatchSpawn( pEnt );
+
+ if ( m_bRandomRotation )
+ {
+ pEnt->SetAbsAngles( QAngle( 0, random->RandomFloat( 0, 360 ), 0 ) );
+ }
+ else
+ {
+ pEnt->SetAbsAngles( pPoint->GetAbsAngles() );
+ }
+
+ pPoint->SetEntity( pEnt );
+
+ return true;
+}
+
+
+//-----------------------------------------------------------------------------
+// CEntitySpawnPoint
+//-----------------------------------------------------------------------------
+BEGIN_DATADESC( CEntitySpawnPoint )
+
+ // Fields
+ DEFINE_KEYFIELD( m_iszSpawnManagerName, FIELD_STRING, "spawn_manager_name" ),
+
+END_DATADESC()
+
+LINK_ENTITY_TO_CLASS( entity_spawn_point, CEntitySpawnPoint );
+
+//-----------------------------------------------------------------------------
+// Initializes the spawn point and registers it with its manager.
+//-----------------------------------------------------------------------------
+void CEntitySpawnPoint::Spawn( void )
+{
+ BaseClass::Spawn();
+
+ SetNextThink( TICK_NEVER_THINK );
+ SetThink( NULL );
+
+ if ( !m_iszSpawnManagerName )
+ {
+ AssertMsg( 0, ("entity_spawn_point with no spawn_manager_name!") );
+ return;
+ }
+
+ m_hSpawnManager = dynamic_cast<CEntitySpawnManager*>( gEntList.FindEntityByName( NULL, m_iszSpawnManagerName ) );
+ if ( !m_hSpawnManager )
+ {
+ AssertMsg2( 0, ("entity_spawn_point %s unable to find spawn_manager_name %s!"), GetEntityName().ToCStr(), m_iszSpawnManagerName.ToCStr() );
+ return;
+ }
+
+ m_hSpawnManager->RegisterSpawnPoint( this );
+
+ gEntList.AddListenerEntity( this );
+}
+
+//-----------------------------------------------------------------------------
+//
+//-----------------------------------------------------------------------------
+void CEntitySpawnPoint::UpdateOnRemove(void)
+{
+ gEntList.RemoveListenerEntity( this );
+
+ BaseClass::UpdateOnRemove();
+}
+
+//-----------------------------------------------------------------------------
+// When our entity is deleted, we become responsible for indicating when a new one should spawn.
+//-----------------------------------------------------------------------------
+
+void CEntitySpawnPoint::OnEntityDeleted( CBaseEntity *pEntity )
+{
+ if ( !m_hSpawnManager )
+ return;
+
+ if ( pEntity == m_hMyEntity )
+ {
+ m_flNodeFree = gpGlobals->curtime + 10.f;
+ m_hMyEntity = NULL;
+ SetNextThink( gpGlobals->curtime + m_hSpawnManager->GetRespawnTime() );
+ SetThink( &CEntitySpawnPoint::RespawnNotifyThink );
+ }
+}
+
+void CEntitySpawnPoint::RespawnNotifyThink( void )
+{
+ if ( (gpGlobals->curtime > m_flNodeFree) && m_hSpawnManager->SpawnEntity() )
+ {
+ SetThink( NULL );
+ SetNextThink( TICK_NEVER_THINK );
+ }
+ else
+ {
+ SetNextThink( gpGlobals->curtime + 5.f );
+ SetThink( &CEntitySpawnPoint::RespawnNotifyThink );
+ }
+}