2010-03-18 22:26:40 +01:00
|
|
|
// ==============================================================
|
|
|
|
// This file is part of Glest (www.glest.org)
|
|
|
|
//
|
2010-05-03 08:25:54 +02:00
|
|
|
// Copyright (C) 2001-2008 Martio Figueroa
|
2010-03-18 22:26:40 +01:00
|
|
|
//
|
|
|
|
// You can redistribute this code and/or modify it under
|
|
|
|
// the terms of the GNU General Public License as published
|
|
|
|
// by the Free Software Foundation; either version 2 of the
|
|
|
|
// License, or (at your option) any later version
|
|
|
|
// ==============================================================
|
|
|
|
|
|
|
|
#include "tech_tree.h"
|
|
|
|
|
|
|
|
#include <cassert>
|
|
|
|
|
|
|
|
#include "util.h"
|
|
|
|
#include "resource.h"
|
|
|
|
#include "faction_type.h"
|
|
|
|
#include "logger.h"
|
|
|
|
#include "xml_parser.h"
|
|
|
|
#include "platform_util.h"
|
2011-01-09 11:03:33 +01:00
|
|
|
#include "game_util.h"
|
2010-03-18 22:26:40 +01:00
|
|
|
#include "leak_dumper.h"
|
|
|
|
|
|
|
|
using namespace Shared::Util;
|
|
|
|
using namespace Shared::Xml;
|
|
|
|
|
|
|
|
namespace Glest{ namespace Game{
|
|
|
|
|
|
|
|
// =====================================================
|
|
|
|
// class TechTree
|
|
|
|
// =====================================================
|
|
|
|
|
2011-01-09 05:49:21 +01:00
|
|
|
Checksum TechTree::loadTech(const vector<string> pathList, const string &techName, set<string> &factions, Checksum* checksum) {
|
|
|
|
Checksum techtreeChecksum;
|
2010-03-18 22:26:40 +01:00
|
|
|
for(int idx = 0; idx < pathList.size(); idx++) {
|
|
|
|
string path = pathList[idx] + "/" + techName;
|
|
|
|
if(isdir(path.c_str()) == true) {
|
2011-01-09 05:49:21 +01:00
|
|
|
load(path, factions, checksum, &techtreeChecksum);
|
2010-03-18 22:26:40 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2011-01-09 05:49:21 +01:00
|
|
|
return techtreeChecksum;
|
2010-03-18 22:26:40 +01:00
|
|
|
}
|
|
|
|
|
2011-01-09 05:49:21 +01:00
|
|
|
void TechTree::load(const string &dir, set<string> &factions, Checksum* checksum, Checksum *techtreeChecksum) {
|
2010-05-03 08:25:54 +02:00
|
|
|
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
2010-03-18 22:26:40 +01:00
|
|
|
|
|
|
|
string str;
|
|
|
|
vector<string> filenames;
|
|
|
|
string name= lastDir(dir);
|
|
|
|
|
|
|
|
Logger::getInstance().add("TechTree: "+ formatString(name), true);
|
|
|
|
|
|
|
|
//load resources
|
|
|
|
str= dir+"/resources/*.";
|
|
|
|
|
|
|
|
try{
|
|
|
|
findAll(str, filenames);
|
|
|
|
resourceTypes.resize(filenames.size());
|
|
|
|
|
|
|
|
for(int i=0; i<filenames.size(); ++i){
|
|
|
|
str=dir+"/resources/"+filenames[i];
|
2011-01-09 05:49:21 +01:00
|
|
|
resourceTypes[i].load(str, checksum, &checksumValue);
|
2010-06-25 07:05:52 +02:00
|
|
|
SDL_PumpEvents();
|
2010-03-18 22:26:40 +01:00
|
|
|
}
|
2010-10-28 02:51:25 +02:00
|
|
|
|
|
|
|
// Cleanup pixmap memory
|
|
|
|
for(int i=0; i<filenames.size(); ++i) {
|
|
|
|
resourceTypes[i].deletePixels();
|
|
|
|
}
|
2010-03-18 22:26:40 +01:00
|
|
|
}
|
|
|
|
catch(const exception &e){
|
2010-10-06 22:22:06 +02:00
|
|
|
SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",__FILE__,__FUNCTION__,__LINE__,e.what());
|
2010-03-18 22:26:40 +01:00
|
|
|
throw runtime_error("Error loading Resource Types: "+ dir + "\n" + e.what());
|
|
|
|
}
|
|
|
|
|
2010-06-12 20:27:39 +02:00
|
|
|
// give CPU time to update other things to avoid apperance of hanging
|
|
|
|
sleep(0);
|
2010-06-25 07:05:52 +02:00
|
|
|
SDL_PumpEvents();
|
2010-06-12 20:27:39 +02:00
|
|
|
|
2010-03-18 22:26:40 +01:00
|
|
|
//load tech tree xml info
|
|
|
|
try{
|
|
|
|
XmlTree xmlTree;
|
|
|
|
string path= dir+"/"+lastDir(dir)+".xml";
|
|
|
|
|
2011-01-09 05:49:21 +01:00
|
|
|
checksum->addFile(path);
|
|
|
|
checksumValue.addFile(path);
|
2010-03-20 12:16:07 +01:00
|
|
|
|
|
|
|
xmlTree.load(path);
|
|
|
|
const XmlNode *techTreeNode= xmlTree.getRootNode();
|
|
|
|
|
|
|
|
//attack types
|
|
|
|
const XmlNode *attackTypesNode= techTreeNode->getChild("attack-types");
|
|
|
|
attackTypes.resize(attackTypesNode->getChildCount());
|
|
|
|
for(int i=0; i<attackTypes.size(); ++i){
|
|
|
|
const XmlNode *attackTypeNode= attackTypesNode->getChild("attack-type", i);
|
|
|
|
attackTypes[i].setName(attackTypeNode->getAttribute("name")->getRestrictedValue());
|
|
|
|
attackTypes[i].setId(i);
|
2010-06-25 07:05:52 +02:00
|
|
|
SDL_PumpEvents();
|
2010-03-20 12:16:07 +01:00
|
|
|
}
|
2010-03-18 22:26:40 +01:00
|
|
|
|
2010-06-12 20:27:39 +02:00
|
|
|
// give CPU time to update other things to avoid apperance of hanging
|
|
|
|
sleep(0);
|
2010-06-15 18:27:52 +02:00
|
|
|
//SDL_PumpEvents();
|
2010-06-12 20:27:39 +02:00
|
|
|
|
2010-03-20 12:16:07 +01:00
|
|
|
//armor types
|
|
|
|
const XmlNode *armorTypesNode= techTreeNode->getChild("armor-types");
|
|
|
|
armorTypes.resize(armorTypesNode->getChildCount());
|
|
|
|
for(int i=0; i<armorTypes.size(); ++i){
|
|
|
|
const XmlNode *armorTypeNode= armorTypesNode->getChild("armor-type", i);
|
|
|
|
armorTypes[i].setName(armorTypeNode->getAttribute("name")->getRestrictedValue());
|
|
|
|
armorTypes[i].setId(i);
|
2010-06-25 07:05:52 +02:00
|
|
|
SDL_PumpEvents();
|
2010-03-18 22:26:40 +01:00
|
|
|
}
|
|
|
|
|
2010-03-20 12:16:07 +01:00
|
|
|
//damage multipliers
|
|
|
|
damageMultiplierTable.init(attackTypes.size(), armorTypes.size());
|
|
|
|
const XmlNode *damageMultipliersNode= techTreeNode->getChild("damage-multipliers");
|
|
|
|
for(int i=0; i<damageMultipliersNode->getChildCount(); ++i){
|
|
|
|
const XmlNode *damageMultiplierNode= damageMultipliersNode->getChild("damage-multiplier", i);
|
|
|
|
const AttackType *attackType= getAttackType(damageMultiplierNode->getAttribute("attack")->getRestrictedValue());
|
|
|
|
const ArmorType *armorType= getArmorType(damageMultiplierNode->getAttribute("armor")->getRestrictedValue());
|
|
|
|
float multiplier= damageMultiplierNode->getAttribute("value")->getFloatValue();
|
|
|
|
damageMultiplierTable.setDamageMultiplier(attackType, armorType, multiplier);
|
2010-06-25 07:05:52 +02:00
|
|
|
SDL_PumpEvents();
|
2010-03-18 22:26:40 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
catch(const exception &e){
|
2010-10-06 22:22:06 +02:00
|
|
|
SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",__FILE__,__FUNCTION__,__LINE__,e.what());
|
2010-03-18 22:26:40 +01:00
|
|
|
throw runtime_error("Error loading Tech Tree: "+ dir + "\n" + e.what());
|
|
|
|
}
|
|
|
|
|
2010-06-12 20:27:39 +02:00
|
|
|
// give CPU time to update other things to avoid apperance of hanging
|
|
|
|
sleep(0);
|
2010-06-15 18:27:52 +02:00
|
|
|
//SDL_PumpEvents();
|
2010-06-12 20:27:39 +02:00
|
|
|
|
2010-03-18 22:26:40 +01:00
|
|
|
//load factions
|
2011-01-09 05:49:21 +01:00
|
|
|
str = dir + "/factions/*.";
|
2010-03-18 22:26:40 +01:00
|
|
|
try{
|
|
|
|
factionTypes.resize(factions.size());
|
|
|
|
|
|
|
|
int i=0;
|
|
|
|
for ( set<string>::iterator it = factions.begin(); it != factions.end(); ++it ) {
|
2010-07-17 22:10:16 +02:00
|
|
|
string factionName = *it;
|
2010-06-12 20:27:39 +02:00
|
|
|
|
|
|
|
char szBuf[1024]="";
|
2010-10-21 18:36:26 +02:00
|
|
|
sprintf(szBuf,"%s %s [%d / %d] - %s",Lang::getInstance().get("Loading").c_str(),Lang::getInstance().get("Faction").c_str(),i+1,(int)factions.size(),factionName.c_str());
|
2010-06-12 20:27:39 +02:00
|
|
|
Logger &logger= Logger::getInstance();
|
2011-01-09 11:03:33 +01:00
|
|
|
logger.setState(szBuf);
|
2011-01-09 13:41:08 +01:00
|
|
|
logger.setProgress((int)((((double)i) / (double)factions.size()) * 100.0));
|
2010-06-12 20:27:39 +02:00
|
|
|
|
2010-07-17 22:10:16 +02:00
|
|
|
str=dir+"/factions/" + factionName;
|
2011-01-09 05:49:21 +01:00
|
|
|
factionTypes[i++].load(str, this, checksum,&checksumValue);
|
2010-06-12 20:27:39 +02:00
|
|
|
|
|
|
|
// give CPU time to update other things to avoid apperance of hanging
|
|
|
|
sleep(0);
|
2010-06-25 07:05:52 +02:00
|
|
|
SDL_PumpEvents();
|
2010-03-18 22:26:40 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
catch(const exception &e){
|
2010-10-06 22:22:06 +02:00
|
|
|
SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",__FILE__,__FUNCTION__,__LINE__,e.what());
|
2010-03-18 22:26:40 +01:00
|
|
|
throw runtime_error("Error loading Faction Types: "+ dir + "\n" + e.what());
|
2011-01-09 05:49:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if(techtreeChecksum != NULL) {
|
|
|
|
*techtreeChecksum = checksumValue;
|
|
|
|
}
|
2010-03-18 22:26:40 +01:00
|
|
|
|
2011-01-09 05:49:21 +01:00
|
|
|
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
2010-03-18 22:26:40 +01:00
|
|
|
}
|
|
|
|
|
2011-01-09 05:49:21 +01:00
|
|
|
TechTree::~TechTree() {
|
2010-05-03 08:25:54 +02:00
|
|
|
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
2010-03-18 22:26:40 +01:00
|
|
|
Logger::getInstance().add("Tech tree", true);
|
|
|
|
}
|
|
|
|
|
2010-07-30 09:51:39 +02:00
|
|
|
std::vector<std::string> TechTree::validateFactionTypes() {
|
|
|
|
std::vector<std::string> results;
|
|
|
|
for (int i = 0; i < factionTypes.size(); ++i) {
|
|
|
|
std::vector<std::string> factionResults = factionTypes[i].validateFactionType();
|
|
|
|
results.insert(results.end(), factionResults.begin(), factionResults.end());
|
2010-07-30 20:20:20 +02:00
|
|
|
|
|
|
|
factionResults = factionTypes[i].validateFactionTypeUpgradeTypes();
|
|
|
|
results.insert(results.end(), factionResults.begin(), factionResults.end());
|
2010-07-30 09:51:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return results;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<std::string> TechTree::validateResourceTypes() {
|
|
|
|
std::vector<std::string> results;
|
|
|
|
for (int i = 0; i < factionTypes.size(); ++i) {
|
|
|
|
std::vector<std::string> factionResults = factionTypes[i].validateFactionTypeResourceTypes(resourceTypes);
|
|
|
|
results.insert(results.end(), factionResults.begin(), factionResults.end());
|
|
|
|
}
|
|
|
|
return results;
|
|
|
|
}
|
2010-03-18 22:26:40 +01:00
|
|
|
|
|
|
|
// ==================== get ====================
|
|
|
|
|
2010-10-28 02:51:25 +02:00
|
|
|
FactionType *TechTree::getTypeByName(const string &name) {
|
2011-01-17 17:31:25 +01:00
|
|
|
//SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
2010-10-28 02:51:25 +02:00
|
|
|
for(int i=0; i < factionTypes.size(); ++i) {
|
|
|
|
if(factionTypes[i].getName() == name) {
|
2011-01-17 17:31:25 +01:00
|
|
|
//SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
2010-03-18 22:26:40 +01:00
|
|
|
return &factionTypes[i];
|
|
|
|
}
|
2010-10-28 02:51:25 +02:00
|
|
|
}
|
2011-01-17 17:31:25 +01:00
|
|
|
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
2010-10-28 02:51:25 +02:00
|
|
|
throw runtime_error("Faction not found: "+name);
|
|
|
|
}
|
|
|
|
|
|
|
|
const FactionType *TechTree::getType(const string &name) const {
|
2011-01-17 17:31:25 +01:00
|
|
|
//SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
2010-10-28 02:51:25 +02:00
|
|
|
for(int i=0; i < factionTypes.size(); ++i) {
|
|
|
|
if(factionTypes[i].getName() == name) {
|
2011-01-17 17:31:25 +01:00
|
|
|
//SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
2010-10-28 02:51:25 +02:00
|
|
|
return &factionTypes[i];
|
|
|
|
}
|
|
|
|
}
|
2011-01-17 17:31:25 +01:00
|
|
|
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
|
2010-10-28 02:51:25 +02:00
|
|
|
throw runtime_error("Faction not found: "+name);
|
2010-03-18 22:26:40 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
const ResourceType *TechTree::getTechResourceType(int i) const{
|
2010-09-07 23:01:22 +02:00
|
|
|
for(int j=0; j < getResourceTypeCount(); ++j){
|
2010-03-18 22:26:40 +01:00
|
|
|
const ResourceType *rt= getResourceType(j);
|
2010-05-03 08:25:54 +02:00
|
|
|
assert(rt != NULL);
|
2010-09-07 23:01:22 +02:00
|
|
|
if(rt == NULL) {
|
|
|
|
throw runtime_error("rt == NULL");
|
|
|
|
}
|
|
|
|
if(rt->getResourceNumber() == i && rt->getClass() == rcTech)
|
2010-03-18 22:26:40 +01:00
|
|
|
return getResourceType(j);
|
|
|
|
}
|
|
|
|
|
|
|
|
return getFirstTechResourceType();
|
|
|
|
}
|
|
|
|
|
|
|
|
const ResourceType *TechTree::getFirstTechResourceType() const{
|
|
|
|
for(int i=0; i<getResourceTypeCount(); ++i){
|
|
|
|
const ResourceType *rt= getResourceType(i);
|
2010-05-03 08:25:54 +02:00
|
|
|
assert(rt != NULL);
|
2010-03-18 22:26:40 +01:00
|
|
|
if(rt->getResourceNumber()==1 && rt->getClass()==rcTech)
|
|
|
|
return getResourceType(i);
|
|
|
|
}
|
|
|
|
|
|
|
|
throw runtime_error("This tech tree has not tech resources, one at least is required");
|
|
|
|
}
|
|
|
|
|
|
|
|
const ResourceType *TechTree::getResourceType(const string &name) const{
|
|
|
|
|
|
|
|
for(int i=0; i<resourceTypes.size(); ++i){
|
|
|
|
if(resourceTypes[i].getName()==name){
|
|
|
|
return &resourceTypes[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
throw runtime_error("Resource Type not found: "+name);
|
|
|
|
}
|
|
|
|
|
|
|
|
const ArmorType *TechTree::getArmorType(const string &name) const{
|
|
|
|
for(int i=0; i<armorTypes.size(); ++i){
|
|
|
|
if(armorTypes[i].getName()==name){
|
|
|
|
return &armorTypes[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
throw runtime_error("Armor Type not found: "+name);
|
|
|
|
}
|
|
|
|
|
|
|
|
const AttackType *TechTree::getAttackType(const string &name) const{
|
|
|
|
for(int i=0; i<attackTypes.size(); ++i){
|
|
|
|
if(attackTypes[i].getName()==name){
|
|
|
|
return &attackTypes[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
throw runtime_error("Attack Type not found: "+name);
|
|
|
|
}
|
|
|
|
|
|
|
|
float TechTree::getDamageMultiplier(const AttackType *att, const ArmorType *art) const{
|
|
|
|
return damageMultiplierTable.getDamageMultiplier(att, art);
|
|
|
|
}
|
|
|
|
|
|
|
|
}}//end namespace
|