1
0
forked from 0ad/0ad
0ad/source/simulation/FormationManager.cpp
pyrolink 3408b078b7 #Unit formations and rank textures
-Added functionality for "casting" and creating net messages (without
JS)
-Rank textures-specified in XML
-Formations-currently don't attack correctly (i.e. travel like mobs) and
don't switch to their movement formations when tasked to go somewhere
(the pathfinder doesn't give any heads up about destination reached, so
there's no way to change back to the original).  Also, base switching is
untested so no garuntees for next and prior formation things.

This was SVN commit r3710.
2006-03-31 03:30:34 +00:00

133 lines
3.7 KiB
C++

#include "precompiled.h"
#include "FormationManager.h"
#include "Entity.h"
#include "CStr.h"
#include "BaseFormation.h"
#include "EntityFormation.h"
#include "ps/Vector2D.h"
CFormationManager::~CFormationManager()
{
for ( size_t i=0; i<m_formations.size(); i++ )
delete m_formations[i];
}
void CFormationManager::CreateFormation( CStrW& name, CEntityList& entities )
{
if ( entities.empty() )
{
debug_warn("Attempting to create a formation with no entities");
return;
}
CBaseFormation* base = g_EntityFormationCollection.getTemplate(name);
if (!base)
return;
if ( entities.size() < (size_t)base->m_required )
return;
CEntityFormation* tmp = new CEntityFormation( base, m_formations.size() );
m_formations.push_back( tmp );
CEntityList accepted = AddUnitList( entities, (int)m_formations.size()-1 );
//Find average position
CVector3D average( 0.0f, 0.0f, 0.0f );
for ( CEntityList::iterator it=accepted.begin(); it != accepted.end(); it++ )
average += (*it)->m_position;
average = average * ( 1.0f / (float)entities.size() );
CVector2D average2D(average.X, average.Z);
m_formations.back()->m_position = average2D;
m_formations.back()->UpdateFormation();
if ( accepted.size() < (size_t)base->m_required )
DestroyFormation( m_formations.size()-1 );
}
void CFormationManager::DestroyFormation( size_t form )
{
if ( form < 0 || form >= m_formations.size())
{
debug_warn("CFormationManager::DestroyFormation--invalid entity");
return;
}
FormIterator it=m_formations.begin() + form;
CEntityList entities = (*it)->GetEntityList();
//Notify the script that we've "left" the formation
for ( size_t i=0; i<entities.size(); i++ )
{
CEntity* entity = entities[i];
entity->DispatchFormationEvent( CFormationEvent::FORMATION_LEAVE );
(*it)->RemoveUnit(entity);
}
delete *it;
*it = NULL;
m_formations.erase( it );
UpdateIndexes( form );
}
bool CFormationManager::AddUnit( CEntity*& entity, int& form )
{
if ( !IsValidFormation(form) )
return false;
if ( entity->m_formation > -1 )
{
if ( !RemoveUnit( entity ) )
--form;
}
FormIterator it = m_formations.begin() + form;
//Adding too many?
if ( (*it)->m_numEntities == (*it)->m_base->m_numSlots )
{
CBaseFormation* next = g_EntityFormationCollection.getTemplate((*it)->m_base->m_next);
if (next)
(*it)->SwitchBase( next );
}
if ( (*it)->AddUnit(entity) ) //This unit might be better
{
entity->DispatchFormationEvent( CFormationEvent::FORMATION_ENTER );
return true;
}
return false;
}
CEntityList CFormationManager::AddUnitList( CEntityList& entities, int form )
{
CEntityList accepted;
for ( CEntityList::iterator it=entities.begin(); it != entities.end(); it++ )
{
CEntity* entity = *it;
if ( AddUnit( entity, form ) )
accepted.push_back( *it );
}
return accepted;
}
bool CFormationManager::RemoveUnit( CEntity*& entity )
{
if ( !IsValidFormation(entity->m_formation) )
return true;
FormIterator it = m_formations.begin() + entity->m_formation;
if ( (*it)->m_numEntities == (*it)->m_base->m_required )
{
CBaseFormation* prior = g_EntityFormationCollection.getTemplate((*it)->m_base->m_prior);
//Disband formation
if (!prior)
{
DestroyFormation( entity->m_formation );
return false;
}
}
entity->DispatchFormationEvent( CFormationEvent::FORMATION_LEAVE );
(*it)->RemoveUnit( entity );
return true;
}
CEntityFormation* CFormationManager::GetFormation(int form)
{
if ( IsValidFormation(form) )
return m_formations[form];
return NULL;
}
void CFormationManager::UpdateIndexes( size_t update )
{
for ( ; update < m_formations.size(); update++ )
m_formations[update]->ResetIndex( update );
}