1
0
forked from 0ad/0ad
0ad/source/simulation/EntityFormation.cpp
Ykkrosh ee3243ff92 # Fixes for simulation speed in scenario edtior. Various code cleanups.
Game, Simulation, etc: Separated 'update' and 'interpolate', and made
'update' return whether it's going fast enough (so callers can decide to
do more updates per render). Changed some time variables to 'double' so
they have enough precision in long games.
Atlas: Added "Fast" playback button. Made simulation sometimes go at
real-time speed, if it's just slightly too slow at rendering.
VertexBuffer: Removed some non-useful glGetError calls.
Entity: Commented out redundant Tick code. Fixed syntax error in
disabled code that confused the IDE.
Aura: Changed string code again, to simply use ASCII instead of UTF-16.
(SpiderMonkey seems to handle it just as efficiently, for small
strings.)
Misc: Some more minor header-file cleanup.
SVN log: Added feed link.

This was SVN commit r4807.
2007-01-24 20:17:28 +00:00

238 lines
5.5 KiB
C++

#include "precompiled.h"
#include "EntityFormation.h"
#include "Entity.h"
#include "FormationCollection.h"
#include "FormationManager.h"
#include "Simulation.h"
#include "ps/Game.h"
#include "ps/Interact.h"
#include "network/NetMessage.h"
CEntityFormation::CEntityFormation( CFormation*& base, size_t index )
{
if (!base)
return;
m_self = m_base = base;
m_numEntities=0;
m_speed=0.0f;
m_orientation = 0.0f;
m_position.x = m_position.y = -1.0f;
m_duplication=false;
m_entities.resize(m_base->m_numSlots);
m_index = (int)index;
}
CEntityFormation::~CEntityFormation()
{
for ( int i=0; i<m_base->m_numSlots; ++i )
{
if ( m_entities[i] )
{
m_entities[i]->m_formation = -1;
m_entities[i]->m_formationSlot = -1;
m_entities[i] = NULL;
}
}
}
int CEntityFormation::GetSlotCount()
{
return m_base->m_numSlots;
}
void CEntityFormation::SwitchBase( CFormation*& base )
{
std::vector<CEntity*> copy;
copy.resize( m_base->m_numSlots );
for ( int i=0; i < m_base->m_numSlots; ++i )
{
if ( !m_entities[i] )
continue;
copy.push_back( m_entities[i] );
RemoveUnit( m_entities[i] );
}
m_self = m_base = base;
m_entities.resize(m_base->m_numSlots);
ResetAllEntities();
for ( std::vector<CEntity*>::iterator it=copy.begin(); it != copy.end(); it++ )
g_FormationManager.AddUnit(*it, m_index);
}
bool CEntityFormation::AddUnit( CEntity*& entity )
{
debug_assert( entity );
//Add the unit to the most appropriate slot
for (int i=0; i<m_base->m_numSlots; ++i)
{
if ( IsBetterUnit( i, entity ) )
{
if ( m_entities[i] )
{
CEntity* prev = m_entities[i];
RemoveUnit( m_entities[i] );
m_entities[i] = entity;
AddUnit( prev );
}
m_entities[i] = entity;
++m_numEntities;
entity->m_formation = m_index;
entity->m_formationSlot = i;
return true;
}
}
return false;
}
void CEntityFormation::RemoveUnit( CEntity*& entity )
{
if ( !(IsValidOrder(entity->m_formationSlot) && entity) )
return;
m_entities[entity->m_formationSlot] = NULL;
entity->m_formation = -1;
entity->m_formationSlot = -1;
--m_numEntities;
//UpdateFormation();
}
bool CEntityFormation::IsSlotAppropriate( int order, CEntity* entity )
{
debug_assert( entity );
if ( !IsValidOrder(order) )
return false;
for ( size_t idx=0; idx < m_base->m_slots[order].category.size(); ++idx )
{
CStr tmp( m_base->m_slots[order].category[idx] );
if ( entity->m_classes.IsMember( tmp ) )
return true;
}
return false;
}
bool CEntityFormation::IsBetterUnit( int order, CEntity* entity )
{
if ( !( IsValidOrder(order) && entity ) )
return false;
//Adding to an empty slot, check if we're elligible
if ( !m_entities[order] )
return IsSlotAppropriate(order, entity);
//Go through each category and check both units' classes. Must be done in order
//because categories are listed in order of importance
for ( size_t idx=0; idx < m_base->m_slots[order].category.size(); ++idx )
{
CStr cat = m_base->m_slots[order].category[idx];
bool current=false;
bool newEnt=false;
current = m_entities[order]->m_classes.IsMember( cat );
newEnt = entity->m_classes.IsMember( cat );
if ( current != newEnt )
return newEnt;
}
return false;
}
void CEntityFormation::UpdateFormation()
{
//Get the entities in the right order (as in, ordered correctly and in the right order/slot)
for ( int i=1; i<m_base->m_numSlots; ++i )
{
if ( !m_entities[i] )
continue;
//Go through slots with higher order
for ( int j=i-1; j > 0; --j )
{
if ( IsBetterUnit( j, m_entities[i] ) )
{
CEntity* temp = m_entities[j];
m_entities[j] = m_entities[i];
m_entities[i] = temp;
int tmpSlot = m_entities[i]->m_formationSlot;
m_entities[i]->m_formationSlot = m_entities[j]->m_formationSlot;
m_entities[j]->m_formationSlot = tmpSlot;
--i;
}
}
}
CEntityList entities = GetEntityList();
CNetMessage* msg = CNetMessage::CreatePositionMessage( entities, NMT_FormationGoto, m_position );
g_Game->GetSimulation()->QueueLocalCommand(msg);
}
void CEntityFormation::ResetAllEntities()
{
for ( int i=0; i<m_base->m_numSlots; ++i )
m_entities[i] = NULL;
}
void CEntityFormation::ResetAngleDivs()
{
for ( int i=0; i<m_base->m_anglePenaltyDivs; ++i )
m_angleDivs[i] = false;
}
void CEntityFormation::SelectAllUnits()
{
for ( int i=0; i<m_base->m_numSlots; ++i )
{
if ( m_entities[i] && !g_Selection.isSelected(m_entities[i]->me) )
g_Selection.addSelection( m_entities[i]->me );
}
}
CEntityList CEntityFormation::GetEntityList()
{
CEntityList ret;
for ( int i=0; i<m_base->m_numSlots; i++ )
{
if ( m_entities[i] )
ret.push_back( m_entities[i]->me);
}
return ret;
}
CVector2D CEntityFormation::GetSlotPosition( int order )
{
if ( IsValidOrder(order) )
return CVector2D ( m_base->m_slots[order].rankOff, m_base->m_slots[order].fileOff );
return CVector2D(-1, -1);
}
void CEntityFormation::BaseToMovement()
{
CFormation* tmp = m_self;
CFormation* move = g_EntityFormationCollection.getTemplate( m_base->m_movement );
if (!move)
return;
SwitchBase( move );
//SwitchBase resets m_self, so reset it so we can return to the correct base later
m_self = tmp;
}
void CEntityFormation::ResetIndex( size_t index )
{
m_index = (int)index;
for ( size_t i=0; i< m_entities.size(); ++i )
{
if ( m_entities[i] )
m_entities[i]->m_formation = m_index;
}
}
/*
inline void CEntityFormation::SetDuplication( JSContext* UNUSED(cx), uintN UNUSED(argc), jsval* argv )
{
m_duplication=ToPrimitive<bool>( argv[0] );
}
inline bool CEntityFormation::IsDuplication( JSContext* UNUSED(cx), uintN UNUSED(argc), jsval* UNUSED(argv))
{
return m_duplication;
}*/