1
0
forked from 0ad/0ad
0ad/source/simulation/Formation.cpp
Matei 8d06d8601b A few organization changes:
- Removed "Base" from the Technology and Formation class names (it
doesn't make sense because these don't use inheritance).
- Modified the tech methods a little so a player ID is passed to
applyEffects, not getTechnology.

Also added a game startup script which will eventually set up player
resource pools and give them their civ techs.

This was SVN commit r3996.
2006-06-09 23:07:11 +00:00

209 lines
5.7 KiB
C++

#include "precompiled.h"
#include "Formation.h"
#include "ps/CLogger.h"
#include "ps/CStr.h"
#include "maths/MathUtil.h"
#define LOG_CATEGORY "Formation"
CFormation::CFormation()
{
m_numSlots = 0;
}
bool CFormation::loadXML(CStr filename)
{
CXeromyces XeroFile;
if (XeroFile.Load(filename) != PSRETURN_OK)
return false;
#define EL(x) int el_##x = XeroFile.getElementID(#x)
#define AT(x) int at_##x = XeroFile.getAttributeID(#x)
EL(formation);
EL(fl);
EL(rk);
EL(blank);
AT(tag);
AT(bonus);
AT(bonusbase);
AT(bonustype);
AT(bonusval);
AT(penalty);
AT(penaltybase);
AT(penaltytype);
AT(penaltyval);
AT(anglepenalty);
AT(anglepenaltydivs);
AT(anglepenaltytype);
AT(anglepenaltyval);
AT(required);
AT(next);
AT(prior);
AT(movement);
AT(filespacing);
AT(rankspacing);
AT(category);
AT(order);
#undef AT
#undef EL
XMBElement Root = XeroFile.getRoot();
if( Root.getNodeName() != el_formation )
{
LOG( ERROR, LOG_CATEGORY, "CFormation::LoadXML: XML root was not \"Formation\" in file %s. Load failed.", filename.c_str() );
return( false );
}
//Load in single attributes
XMBAttributeList Attributes = Root.getAttributes();
for ( int i=0; i<Attributes.Count; ++i )
{
XMBAttribute Attr = Attributes.item(i);
if ( Attr.Name == at_tag )
m_tag = CStr(Attr.Value);
else if ( Attr.Name == at_bonus )
m_bonus = CStr(Attr.Value);
else if ( Attr.Name == at_bonusbase )
m_bonusBase = CStr(Attr.Value);
else if ( Attr.Name == at_bonustype )
m_bonusType = CStr(Attr.Value);
else if ( Attr.Name == at_bonusval )
m_bonusVal = CStr(Attr.Value).ToFloat();
else if ( Attr.Name == at_penalty )
m_penalty = CStr(Attr.Value);
else if ( Attr.Name == at_penaltybase )
m_penaltyBase = CStr(Attr.Value);
else if ( Attr.Name == at_penaltytype )
m_penaltyType = CStr(Attr.Value);
else if ( Attr.Name == at_penaltyval )
m_penaltyVal = CStr(Attr.Value).ToFloat();
else if ( Attr.Name == at_anglepenalty )
m_anglePenalty = CStr(Attr.Value);
else if ( Attr.Name == at_anglepenaltydivs )
m_anglePenaltyDivs = CStr(Attr.Value).ToInt();
else if ( Attr.Name == at_anglepenaltytype )
m_anglePenaltyType = CStr(Attr.Value);
else if ( Attr.Name == at_anglepenaltyval )
m_anglePenaltyVal = CStr(Attr.Value).ToFloat();
else if ( Attr.Name == at_required)
m_required = CStr(Attr.Value).ToInt();
else if ( Attr.Name == at_next )
m_next = CStr(Attr.Value);
else if ( Attr.Name == at_prior )
m_prior = CStr(Attr.Value);
else if ( Attr.Name == at_movement )
m_movement = CStr(Attr.Value);
else if ( Attr.Name == at_rankspacing )
m_rankSpacing = CStr(Attr.Value).ToFloat();
else if ( Attr.Name == at_filespacing )
m_fileSpacing = CStr(Attr.Value).ToFloat();
else
{
const char* invAttr = XeroFile.getAttributeString(Attr.Name).c_str();
LOG( ERROR, LOG_CATEGORY, "CFormation::LoadXML: Invalid attribute %s defined in formation file %s. Load failed.", invAttr, filename.c_str() );
return( false );
}
}
XMBElementList RootChildren = Root.getChildNodes();
int file=0;
int rank=0;
int maxrank=0;
//Read in files and ranks
for (int i = 0; i < RootChildren.Count; ++i)
{
XMBElement RootChild = RootChildren.item(i);
int ChildName = RootChild.getNodeName();
if ( ChildName == el_fl )
{
rank = 0;
XMBAttributeList FileAttribList = RootChild.getAttributes();
//Load default category
CStr FileCatValue = FileAttribList.getNamedItem(at_category);
//Specific slots in this file (row)
XMBElementList RankNodes = RootChild.getChildNodes();
for ( int r=0; r<RankNodes.Count; ++r )
{
XMBElement Rank = RankNodes.item(r);
if ( Rank.getNodeName() == el_blank )
{
++rank;
continue;
}
else if ( Rank.getNodeName() != el_rk )
return false;
//error
XMBAttributeList RankAttribList = Rank.getAttributes();
int order = CStr( RankAttribList.getNamedItem(at_order) ).ToInt();
CStr category = CStr( RankAttribList.getNamedItem(at_category) );
if( order <= 0 )
{
LOG( ERROR, LOG_CATEGORY, "CFormation::LoadXML: Invalid (negative number or 0) order defined in formation file %s. The game will try to continue anyway.", filename.c_str() );
continue;
}
--order; //We need this to be in line with arrays, so start at 0
//if ( category.length() )
//AssignCategory(order, category);
//else
AssignCategory(order, FileCatValue);
m_slots[order].fileOff = file * m_fileSpacing;
m_slots[order].rankOff = rank * m_rankSpacing;
++m_numSlots;
++rank;
}
if ( rank > maxrank )
maxrank = rank;
++file;
} //if el_fl
else if ( ChildName == el_blank )
++file;
}
float centerx = maxrank * m_rankSpacing / 2.0f;
float centery = file * m_fileSpacing / 2.0f;
//Here we check to make sure no order was skipped over. If so, failure, because we rely
//on a linearly accessible slots in entityformation.cpp.
for ( int i=0; i<m_numSlots; ++i )
{
if ( m_slots.find(i) == m_slots.end() )
{
LOG( ERROR, LOG_CATEGORY, "CFormation::LoadXML: Missing orders in %s. Load failed.", filename.c_str() );
return false;
}
else
{
m_slots[i].rankOff = m_slots[i].rankOff - centerx;
m_slots[i].fileOff = m_slots[i].fileOff - centery;
}
}
return true;
}
void CFormation::AssignCategory(int order, CStr category)
{
category.Remove( CStr(",") );
category = category + " "; //So the final word will be pushed as well
CStr temp;
//Push categories until last space
while ( ( temp = category.BeforeFirst(" ") ) != "" )
{
m_slots[order].category.push_back(temp);
//Don't use remove because certain categories could be substrings of others
size_t off = category.find(temp);
category.erase( off, temp.length() );
}
}