2005-05-10 09:13:25 +02:00
|
|
|
|
2004-06-03 20:38:14 +02:00
|
|
|
#include "precompiled.h"
|
|
|
|
|
2004-05-22 01:46:16 +02:00
|
|
|
#include "EntityManager.h"
|
|
|
|
#include "BaseEntityCollection.h"
|
2004-07-22 18:18:12 +02:00
|
|
|
#include "ConfigDB.h"
|
2005-10-09 05:43:03 +02:00
|
|
|
#include "Profile.h"
|
2005-12-16 06:35:26 +01:00
|
|
|
#include "Terrain.h"
|
|
|
|
#include "Game.h"
|
2004-05-22 01:46:16 +02:00
|
|
|
|
2004-07-22 18:18:12 +02:00
|
|
|
int SELECTION_CIRCLE_POINTS;
|
|
|
|
int SELECTION_BOX_POINTS;
|
2004-07-23 12:56:52 +02:00
|
|
|
int SELECTION_SMOOTHNESS_UNIFIED = 9;
|
2004-05-22 01:46:16 +02:00
|
|
|
|
|
|
|
CEntityManager::CEntityManager()
|
2005-12-16 06:35:26 +01:00
|
|
|
: m_collisionPatches(0)
|
|
|
|
, m_entities() // janwas: default-initialize entire array;
|
2005-05-09 06:41:35 +02:00
|
|
|
// CHandle ctor sets m_entity and m_refcount to 0
|
2004-05-22 01:46:16 +02:00
|
|
|
{
|
|
|
|
m_nextalloc = 0;
|
|
|
|
m_extant = true;
|
2005-12-29 05:57:02 +01:00
|
|
|
m_death = false;
|
2005-05-09 06:41:35 +02:00
|
|
|
|
2004-07-22 18:18:12 +02:00
|
|
|
// Also load a couple of global entity settings
|
2004-10-23 16:39:28 +02:00
|
|
|
CConfigValue* cfg = g_ConfigDB.GetValue( CFG_USER, "selection.outline.quality" );
|
2004-07-22 18:18:12 +02:00
|
|
|
if( cfg ) cfg->GetInt( SELECTION_SMOOTHNESS_UNIFIED );
|
|
|
|
if( SELECTION_SMOOTHNESS_UNIFIED < 0 ) SELECTION_SMOOTHNESS_UNIFIED = 0;
|
|
|
|
SELECTION_CIRCLE_POINTS = 7 + 2 * SELECTION_SMOOTHNESS_UNIFIED;
|
|
|
|
SELECTION_BOX_POINTS = 1 + SELECTION_SMOOTHNESS_UNIFIED;
|
2004-05-22 01:46:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
CEntityManager::~CEntityManager()
|
2004-05-30 03:57:26 +02:00
|
|
|
{
|
2004-05-22 01:46:16 +02:00
|
|
|
m_extant = false;
|
2005-05-09 06:41:35 +02:00
|
|
|
|
2004-05-30 03:57:26 +02:00
|
|
|
for( int i = 0; i < MAX_HANDLES; i++ )
|
2005-12-16 06:35:26 +01:00
|
|
|
{
|
2004-05-30 03:57:26 +02:00
|
|
|
if( m_entities[i].m_refcount )
|
2005-05-09 06:41:35 +02:00
|
|
|
{
|
2004-05-30 03:57:26 +02:00
|
|
|
delete( m_entities[i].m_entity );
|
2005-05-09 06:41:35 +02:00
|
|
|
m_entities[i].m_entity = 0;
|
|
|
|
m_entities[i].m_refcount = 0;
|
|
|
|
}
|
2005-12-16 06:35:26 +01:00
|
|
|
}
|
2005-12-08 03:50:55 +01:00
|
|
|
|
|
|
|
// Delete entities that were killed, but not yet reaped by a call to updateAll,
|
|
|
|
// to avoid memory leak warnings upon exiting
|
|
|
|
std::vector<CEntity*>::iterator it;
|
|
|
|
for( it = m_reaper.begin(); it < m_reaper.end(); it++ )
|
|
|
|
delete( *it );
|
|
|
|
m_reaper.clear();
|
2005-12-16 06:35:26 +01:00
|
|
|
|
|
|
|
delete[] m_collisionPatches;
|
|
|
|
m_collisionPatches = 0;
|
2004-05-22 01:46:16 +02:00
|
|
|
}
|
|
|
|
|
2005-05-09 04:29:33 +02:00
|
|
|
void CEntityManager::deleteAll()
|
|
|
|
{
|
|
|
|
m_extant = false;
|
|
|
|
for( int i = 0; i < MAX_HANDLES; i++ )
|
|
|
|
if( m_entities[i].m_refcount )
|
|
|
|
{
|
|
|
|
delete( m_entities[i].m_entity );
|
2005-12-08 03:50:55 +01:00
|
|
|
m_entities[i].m_entity = 0;
|
2005-05-09 04:29:33 +02:00
|
|
|
m_entities[i].m_refcount = 0;
|
|
|
|
}
|
|
|
|
m_nextalloc = 0;
|
|
|
|
m_extant = true;
|
|
|
|
}
|
|
|
|
|
2004-05-22 01:46:16 +02:00
|
|
|
HEntity CEntityManager::create( CBaseEntity* base, CVector3D position, float orientation )
|
|
|
|
{
|
2005-06-28 06:06:25 +02:00
|
|
|
debug_assert( base );
|
2005-03-29 22:50:04 +02:00
|
|
|
if( !base )
|
2005-05-18 07:32:09 +02:00
|
|
|
return HEntity();
|
2005-03-29 22:50:04 +02:00
|
|
|
|
2004-05-22 01:46:16 +02:00
|
|
|
while( m_entities[m_nextalloc].m_refcount )
|
2005-05-09 06:41:35 +02:00
|
|
|
{
|
2004-05-22 01:46:16 +02:00
|
|
|
m_nextalloc++;
|
2005-12-13 09:05:30 +01:00
|
|
|
if(m_nextalloc == MAX_HANDLES)
|
2005-07-02 23:42:55 +02:00
|
|
|
{
|
|
|
|
debug_warn("Ran out of entity handles!");
|
|
|
|
return HEntity();
|
|
|
|
}
|
2005-05-09 06:41:35 +02:00
|
|
|
}
|
2005-12-13 09:05:30 +01:00
|
|
|
|
2004-05-22 01:46:16 +02:00
|
|
|
m_entities[m_nextalloc].m_entity = new CEntity( base, position, orientation );
|
2006-01-02 04:07:29 +01:00
|
|
|
if( m_collisionPatches)
|
|
|
|
m_entities[m_nextalloc].m_entity->updateCollisionPatch();
|
2004-05-22 01:46:16 +02:00
|
|
|
m_entities[m_nextalloc].m_entity->me = HEntity( m_nextalloc );
|
|
|
|
return( HEntity( m_nextalloc++ ) );
|
|
|
|
}
|
|
|
|
|
2004-08-03 01:14:54 +02:00
|
|
|
HEntity CEntityManager::create( CStrW templatename, CVector3D position, float orientation )
|
2004-05-22 01:46:16 +02:00
|
|
|
{
|
|
|
|
CBaseEntity* templateobj = g_EntityTemplateCollection.getTemplate( templatename );
|
|
|
|
return( create( templateobj, position, orientation ) );
|
|
|
|
}
|
|
|
|
|
2004-06-11 00:24:03 +02:00
|
|
|
HEntity* CEntityManager::getByHandle( u16 index )
|
|
|
|
{
|
|
|
|
if( index >= MAX_HANDLES ) return( NULL );
|
|
|
|
if( !m_entities[index].m_refcount ) return( NULL );
|
|
|
|
return( new HEntity( index ) );
|
|
|
|
}
|
2005-12-29 05:57:02 +01:00
|
|
|
CHandle *CEntityManager::getHandle( int index )
|
|
|
|
{
|
|
|
|
if (!m_entities[index].m_refcount )
|
|
|
|
return NULL;
|
|
|
|
return &m_entities[index];
|
|
|
|
}
|
2005-01-18 01:46:18 +01:00
|
|
|
|
2005-03-30 18:14:19 +02:00
|
|
|
std::vector<HEntity>* CEntityManager::matches( EntityPredicate predicate, void* userdata )
|
2005-01-18 01:46:18 +01:00
|
|
|
{
|
|
|
|
std::vector<HEntity>* matchlist = new std::vector<HEntity>;
|
|
|
|
for( int i = 0; i < MAX_HANDLES; i++ )
|
|
|
|
if( m_entities[i].m_refcount && !m_entities[i].m_entity->m_destroyed )
|
|
|
|
if( predicate( m_entities[i].m_entity, userdata ) )
|
|
|
|
matchlist->push_back( HEntity( i ) );
|
|
|
|
return( matchlist );
|
|
|
|
}
|
|
|
|
|
2004-07-20 21:30:35 +02:00
|
|
|
std::vector<HEntity>* CEntityManager::getExtant()
|
2004-05-26 22:57:25 +02:00
|
|
|
{
|
|
|
|
std::vector<HEntity>* activelist = new std::vector<HEntity>;
|
|
|
|
for( int i = 0; i < MAX_HANDLES; i++ )
|
2004-11-11 08:09:32 +01:00
|
|
|
if( m_entities[i].m_refcount && !m_entities[i].m_entity->m_destroyed )
|
2004-05-26 22:57:25 +02:00
|
|
|
activelist->push_back( HEntity( i ) );
|
|
|
|
return( activelist );
|
|
|
|
}
|
|
|
|
|
2005-05-10 09:13:25 +02:00
|
|
|
void CEntityManager::GetExtant( std::vector<CEntity*>& results )
|
|
|
|
{
|
|
|
|
results.clear();
|
|
|
|
for( int i = 0; i < MAX_HANDLES; i++ )
|
2005-12-12 00:28:50 +01:00
|
|
|
if( m_entities[i].m_refcount && !m_entities[i].m_entity->m_destroyed && m_entities[i].m_entity->m_extant )
|
2005-05-10 09:13:25 +02:00
|
|
|
results.push_back( m_entities[i].m_entity );
|
|
|
|
}
|
|
|
|
|
2005-12-13 09:05:30 +01:00
|
|
|
void CEntityManager::GetInRange( float x, float z, float radius, std::vector<CEntity*>& results )
|
|
|
|
{
|
|
|
|
results.clear();
|
2005-12-16 06:35:26 +01:00
|
|
|
|
|
|
|
int cx = (int) ( x / COLLISION_PATCH_SIZE );
|
|
|
|
int cz = (int) ( z / COLLISION_PATCH_SIZE );
|
|
|
|
|
|
|
|
int r = (int) ( radius / COLLISION_PATCH_SIZE + 1 );
|
|
|
|
|
|
|
|
int minX = MAX(cx-r, 0);
|
|
|
|
int minZ = MAX(cz-r, 0);
|
|
|
|
int maxX = MIN(cx+r, m_collisionPatchesPerSide-1);
|
|
|
|
int maxZ = MIN(cz+r, m_collisionPatchesPerSide-1);
|
|
|
|
|
|
|
|
for( int px = minX; px <= maxX; px++ )
|
|
|
|
{
|
|
|
|
for( int pz = minZ; pz <= maxZ; pz++ )
|
|
|
|
{
|
|
|
|
std::vector<CEntity*>& vec = m_collisionPatches[ px * m_collisionPatchesPerSide + pz ];
|
|
|
|
for( std::vector<CEntity*>::iterator it = vec.begin(); it != vec.end(); it++ )
|
|
|
|
{
|
|
|
|
CEntity* e = *it;
|
|
|
|
float dx = x - e->m_position.X;
|
|
|
|
float dz = z - e->m_position.Z;
|
|
|
|
if(dx*dx + dz*dz <= radius*radius)
|
|
|
|
{
|
|
|
|
results.push_back( e );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2005-12-13 09:05:30 +01:00
|
|
|
}
|
|
|
|
|
2004-11-11 08:09:32 +01:00
|
|
|
/*
|
2004-05-22 01:46:16 +02:00
|
|
|
void CEntityManager::dispatchAll( CMessage* msg )
|
|
|
|
{
|
|
|
|
for( int i = 0; i < MAX_HANDLES; i++ )
|
2004-07-20 21:30:35 +02:00
|
|
|
if( m_entities[i].m_refcount && m_entities[i].m_entity->m_extant )
|
2004-05-22 01:46:16 +02:00
|
|
|
m_entities[i].m_entity->dispatch( msg );
|
|
|
|
}
|
2004-11-11 08:09:32 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
void CEntityManager::InitializeAll()
|
|
|
|
{
|
2005-12-16 06:35:26 +01:00
|
|
|
CTerrain* terrain = g_Game->GetWorld()->GetTerrain();
|
|
|
|
int unitsPerSide = CELL_SIZE * ( terrain->GetVerticesPerSide() - 1 );
|
|
|
|
m_collisionPatchesPerSide = unitsPerSide / COLLISION_PATCH_SIZE + 1;
|
|
|
|
|
|
|
|
m_collisionPatches = new std::vector<CEntity*>[m_collisionPatchesPerSide * m_collisionPatchesPerSide];
|
|
|
|
|
2004-11-11 08:09:32 +01:00
|
|
|
for( int i = 0; i < MAX_HANDLES; i++ )
|
2005-12-16 06:35:26 +01:00
|
|
|
{
|
2004-11-11 08:09:32 +01:00
|
|
|
if( m_entities[i].m_refcount && !m_entities[i].m_entity->m_destroyed )
|
2005-12-16 06:35:26 +01:00
|
|
|
{
|
|
|
|
CEntity* e = m_entities[i].m_entity;
|
|
|
|
e->Initialize();
|
|
|
|
e->updateCollisionPatch();
|
|
|
|
}
|
|
|
|
}
|
2004-11-11 08:09:32 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void CEntityManager::TickAll()
|
|
|
|
{
|
|
|
|
for( int i = 0; i < MAX_HANDLES; i++ )
|
2005-12-16 06:35:26 +01:00
|
|
|
if( m_entities[i].m_refcount && !m_entities[i].m_entity->m_destroyed && m_entities[i].m_entity->m_extant )
|
2004-11-11 08:09:32 +01:00
|
|
|
m_entities[i].m_entity->Tick();
|
|
|
|
}
|
2004-05-22 01:46:16 +02:00
|
|
|
|
2004-07-27 23:00:53 +02:00
|
|
|
void CEntityManager::updateAll( size_t timestep )
|
2004-05-22 01:46:16 +02:00
|
|
|
{
|
2005-10-09 05:43:03 +02:00
|
|
|
PROFILE_START( "reaper" );
|
2004-07-20 21:30:35 +02:00
|
|
|
std::vector<CEntity*>::iterator it;
|
2004-05-29 05:32:33 +02:00
|
|
|
for( it = m_reaper.begin(); it < m_reaper.end(); it++ )
|
2004-07-20 21:30:35 +02:00
|
|
|
delete( *it );
|
2004-05-29 05:32:33 +02:00
|
|
|
m_reaper.clear();
|
2005-10-09 05:43:03 +02:00
|
|
|
PROFILE_END( "reaper" );
|
2004-05-29 05:32:33 +02:00
|
|
|
|
2005-11-06 00:10:54 +01:00
|
|
|
// PT: TickAll (which sends the 'Tick' event to all entities) has been
|
|
|
|
// disabled, because:
|
|
|
|
// * it's very slow (particularly when there are thousands of entities, e.g. trees);
|
|
|
|
// * no entity currently responds to tick events;
|
|
|
|
// * nobody can think of a situation where ticks would be required in the future;
|
|
|
|
// * if they ever are needed, they can be done more efficiently (e.g. by
|
|
|
|
// adding a per-entity 'wants tick' flag);
|
|
|
|
// * it's very slow.
|
|
|
|
/*
|
2005-10-09 05:43:03 +02:00
|
|
|
PROFILE_START( "tick all" );
|
2004-11-11 08:09:32 +01:00
|
|
|
TickAll();
|
2005-10-09 05:43:03 +02:00
|
|
|
PROFILE_END( "tick all" );
|
2005-11-06 00:10:54 +01:00
|
|
|
*/
|
2004-10-07 21:23:35 +02:00
|
|
|
|
2005-10-09 05:43:03 +02:00
|
|
|
PROFILE_START( "update all" );
|
2004-05-22 01:46:16 +02:00
|
|
|
for( int i = 0; i < MAX_HANDLES; i++ )
|
2004-11-11 08:09:32 +01:00
|
|
|
if( m_entities[i].m_refcount && !m_entities[i].m_entity->m_destroyed )
|
2004-05-22 01:46:16 +02:00
|
|
|
m_entities[i].m_entity->update( timestep );
|
2005-10-09 05:43:03 +02:00
|
|
|
PROFILE_END( "update all" );
|
2004-05-22 01:46:16 +02:00
|
|
|
}
|
|
|
|
|
2004-07-20 21:30:35 +02:00
|
|
|
void CEntityManager::interpolateAll( float relativeoffset )
|
|
|
|
{
|
|
|
|
for( int i = 0; i < MAX_HANDLES; i++ )
|
2004-11-11 08:09:32 +01:00
|
|
|
if( m_entities[i].m_refcount && !m_entities[i].m_entity->m_destroyed )
|
2004-07-20 21:30:35 +02:00
|
|
|
m_entities[i].m_entity->interpolate( relativeoffset );
|
|
|
|
}
|
|
|
|
|
2004-05-26 22:57:25 +02:00
|
|
|
void CEntityManager::renderAll()
|
|
|
|
{
|
|
|
|
for( int i = 0; i < MAX_HANDLES; i++ )
|
2004-11-11 08:09:32 +01:00
|
|
|
if( m_entities[i].m_refcount && !m_entities[i].m_entity->m_destroyed )
|
2004-05-26 22:57:25 +02:00
|
|
|
m_entities[i].m_entity->render();
|
|
|
|
}
|
|
|
|
|
2005-12-08 03:50:55 +01:00
|
|
|
void CEntityManager::invalidateAll()
|
|
|
|
{
|
|
|
|
for( int i = 0; i < MAX_HANDLES; i++ )
|
|
|
|
if( m_entities[i].m_refcount && !m_entities[i].m_entity->m_destroyed )
|
|
|
|
m_entities[i].m_entity->invalidateActor();
|
|
|
|
}
|
|
|
|
|
2004-05-29 05:32:33 +02:00
|
|
|
void CEntityManager::destroy( u16 handle )
|
|
|
|
{
|
2005-12-08 03:50:55 +01:00
|
|
|
m_reaper.push_back( m_entities[handle].m_entity );
|
|
|
|
m_entities[handle].m_entity->me.m_handle = INVALID_HANDLE;
|
2004-05-29 05:32:33 +02:00
|
|
|
}
|
|
|
|
|
2004-06-02 18:11:32 +02:00
|
|
|
bool CEntityManager::m_extant = false;
|
2005-12-16 06:35:26 +01:00
|
|
|
|
|
|
|
std::vector<CEntity*>* CEntityManager::getCollisionPatch( CEntity* e )
|
|
|
|
{
|
|
|
|
if( !e->m_extant )
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int ix = (int) ( e->m_position.X / COLLISION_PATCH_SIZE );
|
|
|
|
int iz = (int) ( e->m_position.Z / COLLISION_PATCH_SIZE );
|
|
|
|
return &m_collisionPatches[ ix * m_collisionPatchesPerSide + iz ];
|
|
|
|
}
|