1 // ==============================================================
2 // This file is part of Glest (www.glest.org)
3 //
4 // Copyright (C) 2001-2008 Martiño Figueroa
5 //
6 // You can redistribute this code and/or modify it under
7 // the terms of the GNU General Public License as published
8 // by the Free Software Foundation; either version 2 of the
9 // License, or (at your option) any later version
10 // ==============================================================
11
12 #include "faction_type.h"
13
14 #include "logger.h"
15 #include "util.h"
16 #include "xml_parser.h"
17 #include "tech_tree.h"
18 #include "resource.h"
19 #include "renderer.h"
20 #include "platform_util.h"
21 #include "game_util.h"
22 #include "conversion.h"
23 #include "leak_dumper.h"
24
25 using namespace Shared::Util;
26 using namespace Shared::Xml;
27
28 namespace Glest{ namespace Game{
29
30 // ======================================================
31 // Class FactionType
32 // ======================================================
33
FactionType()34 FactionType::FactionType() {
35 music = NULL;
36 personalityType = fpt_Normal;
37 isLinked = false;
38 healthbarheight= -100.0f;
39 healthbarthickness= 0.11f;
40 healthbarVisible=hbvUndefined;
41 healthbarBorderTextureEnabled=false;
42 healthbarBackgroundTextureEnabled=false;
43 healthbarLineBorder=true;
44 healthbarTexture=NULL;
45 healthbarBackgroundTexture=NULL;
46 flatParticlePositions=false;
47 }
48
49 //load a faction, given a directory
load(const string & factionName,const TechTree * techTree,Checksum * checksum,Checksum * techtreeChecksum,std::map<string,vector<pair<string,string>>> & loadedFileList,bool validationMode)50 void FactionType::load(const string &factionName, const TechTree *techTree, Checksum* checksum,
51 Checksum *techtreeChecksum,
52 std::map<string,vector<pair<string, string> > > &loadedFileList,
53 bool validationMode) {
54
55 if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
56
57 string techTreePath = techTree->getPath();
58 string techTreeName=techTree->getNameUntranslated();
59 string currentPath = "";
60
61 //open xml file
62 string path="";
63 XmlTree xmlTree;
64 const XmlNode *factionNode;
65
66 //printf("\n>>> factionname=%s\n",factionName.c_str());
67 for(bool realFactionPathFound=false;realFactionPathFound == false;) {
68 currentPath = techTreePath + "factions/" + factionName;
69 endPathWithSlash(currentPath);
70
71 name= lastDir(currentPath);
72
73 // Add special Observer Faction
74 //Lang &lang= Lang::getInstance();
75 if(name == formatString(GameConstants::OBSERVER_SLOTNAME)) {
76 personalityType = fpt_Observer;
77 }
78
79 if(personalityType == fpt_Normal) {
80 string tmppath= currentPath + factionName +".xml";
81 std::map<string,string> mapExtraTagReplacementValues;
82 // mapExtraTagReplacementValues["$COMMONDATAPATH"] = techTreePath + "/commondata/";
83 //printf("current $COMMONDATAPATH = %s\n",mapExtraTagReplacementValues["$COMMONDATAPATH"].c_str());
84 XmlTree xmlTree;
85 xmlTree.load(tmppath, Properties::getTagReplacementValues(&mapExtraTagReplacementValues));
86
87
88 const XmlNode *rootNode= xmlTree.getRootNode();
89
90 if(rootNode->getName()=="link") {
91 if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"Faction [%s] is a linked faction\n",name.c_str());
92
93 isLinked = true;
94 const XmlNode *techTreeNode= rootNode->getChild("techtree");
95 const string linkedTechTreeName=techTreeNode->getAttribute("name")->getRestrictedValue();
96 // const XmlNode *factionLinkNode= rootNode->getChild("faction");
97 // string linkedFactionName=factionLinkNode->getAttribute("name")->getRestrictedValue();
98 string linkedTechTreePath=techTree->findPath(linkedTechTreeName);
99 techTreePath=linkedTechTreePath;
100 endPathWithSlash(techTreePath);
101 techTreeName=linkedTechTreeName;
102
103 string linkedCurrentPath = techTreePath + "factions/" + factionName;
104 endPathWithSlash(linkedCurrentPath);
105 string linkedTmppath= linkedCurrentPath + factionName +".xml";
106
107 //printf("linkedTmppath [%s] linkedCurrentPath [%s]\n",linkedTmppath.c_str(),linkedCurrentPath.c_str());
108
109 loadedFileList[linkedTmppath].push_back(make_pair(linkedCurrentPath,linkedCurrentPath));
110 loadedFileList[tmppath].push_back(make_pair(currentPath,currentPath));
111 if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"techTreePath [%s] techTreeName [%s]\n",techTreePath.c_str(),techTreeName.c_str());
112 }
113 else {
114 // stop looking for new path, no more links ...
115 //xmlTree.load(tmppath, Properties::getTagReplacementValues(&mapExtraTagReplacementValues));
116
117 loadedFileList[tmppath].push_back(make_pair(currentPath,currentPath));
118
119 realFactionPathFound=true;
120 //printf("techPath found! %s\n",tmppath.c_str());
121
122 path=tmppath;
123 }
124 }
125 else {
126 break;
127 }
128 }
129
130 char szBuf[8096]="";
131 snprintf(szBuf,8096,Lang::getInstance().getString("LogScreenGameLoadingFactionType","",true).c_str(),formatString(this->getName()).c_str());
132 Logger::getInstance().add(szBuf, true);
133
134 if(personalityType == fpt_Normal) {
135 if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"Loading faction [%s] currentPath [%s]\n",path.c_str(),currentPath.c_str());
136
137 checksum->addFile(path);
138 techtreeChecksum->addFile(path);
139
140 // a1) preload units
141 //string unitsPath= currentPath + "units/*.";
142 string unitsPath= currentPath + "units/";
143 vector<string> unitFilenames;
144 //findAll(unitsPath, unitFilenames);
145 findDirs(unitsPath, unitFilenames,false,false);
146
147 unitTypes.resize(unitFilenames.size());
148
149 for(int i = 0; i < (int)unitTypes.size(); ++i) {
150 string str= currentPath + "units/" + unitFilenames[i];
151 unitTypes[i].preLoad(str);
152
153 SDL_PumpEvents();
154 }
155
156 // a2) preload upgrades
157 //string upgradesPath= currentPath + "upgrades/*.";
158 string upgradesPath= currentPath + "upgrades/";
159 vector<string> upgradeFilenames;
160 //findAll(upgradesPath, upgradeFilenames, false, false);
161 findDirs(upgradesPath, upgradeFilenames,false,false);
162
163 upgradeTypes.resize(upgradeFilenames.size());
164 for(int i = 0; i < (int)upgradeTypes.size(); ++i) {
165 string str= currentPath + "upgrades/" + upgradeFilenames[i];
166 upgradeTypes[i].preLoad(str);
167
168 SDL_PumpEvents();
169 }
170
171 // b1) load units
172 try {
173 Logger &logger= Logger::getInstance();
174 int progressBaseValue=logger.getProgress();
175 for(int i = 0; i < (int)unitTypes.size(); ++i) {
176 string str= currentPath + "units/" + unitTypes[i].getName();
177
178 try {
179 unitTypes[i].loaddd(i, str, techTree,techTreePath, this, checksum,techtreeChecksum,
180 loadedFileList,validationMode);
181 logger.setProgress(progressBaseValue+(int)((((double)i + 1.0) / (double)unitTypes.size()) * 100.0/techTree->getTypeCount()));
182 SDL_PumpEvents();
183 }
184 catch(megaglest_runtime_error& ex) {
185 if(validationMode == false) {
186 throw;
187 }
188 else {
189 SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,ex.what());
190 }
191 }
192 }
193 }
194 catch(megaglest_runtime_error& ex) {
195 SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,ex.what());
196 throw megaglest_runtime_error("Error loading units: "+ currentPath + "\nMessage: " + ex.what(),!ex.wantStackTrace());
197 }
198 catch(const exception &e) {
199 SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,e.what());
200 throw megaglest_runtime_error("Error loading units: "+ currentPath + "\nMessage: " + e.what());
201 }
202
203 // b2) load upgrades
204 try{
205 for(int i = 0; i < (int)upgradeTypes.size(); ++i) {
206 string str= currentPath + "upgrades/" + upgradeTypes[i].getName();
207
208 try {
209 upgradeTypes[i].load(str, techTree, this, checksum,
210 techtreeChecksum,loadedFileList,validationMode);
211 }
212 catch(megaglest_runtime_error& ex) {
213 if(validationMode == false) {
214 throw;
215 }
216 else {
217 SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,ex.what());
218 }
219 }
220
221 SDL_PumpEvents();
222 }
223 }
224 catch(const exception &e){
225 SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,e.what());
226 throw megaglest_runtime_error("Error loading upgrades: "+ currentPath + "\n" + e.what());
227 }
228
229 string tmppath= currentPath + factionName +".xml";
230
231 if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"Loading faction xml [%s]\n",tmppath.c_str());
232
233 std::map<string,string> mapExtraTagReplacementValues;
234 mapExtraTagReplacementValues["$COMMONDATAPATH"] = techTreePath + "/commondata/";
235 //printf("current $COMMONDATAPATH = %s\n",mapExtraTagReplacementValues["$COMMONDATAPATH"].c_str());
236 xmlTree.load(tmppath, Properties::getTagReplacementValues(&mapExtraTagReplacementValues));
237
238
239 factionNode=xmlTree.getRootNode();
240 //read starting resources
241 //printf("factionNode->getName()=%s",factionNode->getName().c_str());
242 const XmlNode *startingResourcesNode= factionNode->getChild("starting-resources");
243
244 startingResources.resize(startingResourcesNode->getChildCount());
245 for(int i = 0; i < (int)startingResources.size(); ++i) {
246 const XmlNode *resourceNode= startingResourcesNode->getChild("resource", i);
247 string name= resourceNode->getAttribute("name")->getRestrictedValue();
248 int amount= resourceNode->getAttribute("amount")->getIntValue();
249
250 try {
251 startingResources[i].init(techTree->getResourceType(name), amount);
252 }
253 catch(megaglest_runtime_error& ex) {
254 if(validationMode == false) {
255 throw;
256 }
257 else {
258 SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\nFor FactionType: %s for StartResource: %s\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,ex.what(),this->name.c_str(),name.c_str());
259 }
260 }
261
262 SDL_PumpEvents();
263 }
264
265 //read starting units
266 const XmlNode *startingUnitsNode= factionNode->getChild("starting-units");
267 for(int i = 0; i < (int)startingUnitsNode->getChildCount(); ++i) {
268 const XmlNode *unitNode= startingUnitsNode->getChild("unit", i);
269 string name= unitNode->getAttribute("name")->getRestrictedValue();
270 int amount= unitNode->getAttribute("amount")->getIntValue();
271 startingUnits.push_back(PairPUnitTypeInt(getUnitType(name), amount));
272
273 SDL_PumpEvents();
274 }
275
276 //read music
277 const XmlNode *musicNode= factionNode->getChild("music");
278 bool value= musicNode->getAttribute("value")->getBoolValue();
279 if(value) {
280 music= new StrSound();
281 music->open(musicNode->getAttribute("path")->getRestrictedValue(currentPath));
282 loadedFileList[musicNode->getAttribute("path")->getRestrictedValue(currentPath)].push_back(make_pair(path,musicNode->getAttribute("path")->getRestrictedValue()));
283 }
284
285 if(factionNode->hasChild("flat-particle-positions")) {
286 const XmlNode *node= factionNode->getChild("flat-particle-positions");
287 flatParticlePositions = node->getAttribute("value")->getBoolValue();
288 }
289
290 //healthbar
291 if(factionNode->hasChild("healthbar")) {
292 const XmlNode *healthbarNode= factionNode->getChild("healthbar");
293 if(healthbarNode->hasChild("height")) {
294 healthbarheight= healthbarNode->getChild("height")->getAttribute("value")->getFloatValue();
295 }
296 if(healthbarNode->hasChild("thickness")) {
297 healthbarthickness= healthbarNode->getChild("thickness")->getAttribute("value")->getFloatValue(0.f, 1.f);
298 }
299 if(healthbarNode->hasChild("visible")) {
300 string healthbarVisibleString=healthbarNode->getChild("visible")->getAttribute("value")->getValue();
301 vector<string> v=split(healthbarVisibleString,"|");
302 for (int i = 0; i < (int)v.size(); ++i) {
303 string current=trim(v[i]);
304 if(current=="always") {
305 healthbarVisible=healthbarVisible|hbvAlways;
306 } else if(current=="selected") {
307 healthbarVisible=healthbarVisible|hbvSelected;
308 } else if(current=="ifNeeded") {
309 healthbarVisible=healthbarVisible|hbvIfNeeded;
310 } else if(current=="off") {
311 healthbarVisible=healthbarVisible|hbvOff;
312 } else {
313 throw megaglest_runtime_error("Unknown Healthbar Visible Option: " + current, true);
314 }
315 }
316 }
317 if(healthbarNode->hasChild("borderTexture")) {
318 healthbarBorderTextureEnabled=healthbarNode->getChild("borderTexture")->getAttribute("enabled")->getBoolValue();
319 if(healthbarBorderTextureEnabled && healthbarNode->getChild("borderTexture")->hasAttribute("path")) {
320 healthbarTexture= Renderer::getInstance().newTexture2D(rsGame);
321 if(healthbarTexture) {
322 healthbarTexture->load(healthbarNode->getChild("borderTexture")->getAttribute("path")->getRestrictedValue(currentPath));
323 }
324 loadedFileList[healthbarNode->getChild("borderTexture")->getAttribute("path")->getRestrictedValue(currentPath)].push_back(make_pair(path,healthbarNode->getChild("borderTexture")->getAttribute("path")->getRestrictedValue()));
325 }
326 }
327 if(healthbarNode->hasChild("backgroundTexture")) {
328 healthbarBackgroundTextureEnabled=healthbarNode->getChild("backgroundTexture")->getAttribute("enabled")->getBoolValue();
329 if(healthbarBackgroundTextureEnabled && healthbarNode->getChild("backgroundTexture")->hasAttribute("path")) {
330 healthbarBackgroundTexture= Renderer::getInstance().newTexture2D(rsGame);
331 if(healthbarBackgroundTexture) {
332 healthbarBackgroundTexture->load(healthbarNode->getChild("backgroundTexture")->getAttribute("path")->getRestrictedValue(currentPath));
333 }
334 loadedFileList[healthbarNode->getChild("backgroundTexture")->getAttribute("path")->getRestrictedValue(currentPath)].push_back(make_pair(path,healthbarNode->getChild("backgroundTexture")->getAttribute("path")->getRestrictedValue()));
335 }
336 }
337 if(healthbarNode->hasChild("lineBorder")) {
338 healthbarLineBorder= healthbarNode->getChild("lineBorder")->getAttribute("enabled")->getBoolValue();
339 }
340
341 }
342
343 //read ai behavior
344 if(factionNode->hasChild("ai-behavior") == true) {
345 const XmlNode *aiNode= factionNode->getChild("ai-behavior");
346 if(aiNode->hasAttribute("min-static-resource-count") == true) {
347 mapAIBehaviorStaticOverrideValues[aibsvcMinStaticResourceCount] = aiNode->getAttribute("min-static-resource-count")->getIntValue();
348 }
349
350 if(aiNode->hasChild("static-values") == true) {
351 const XmlNode *aiNodeUnits= aiNode->getChild("static-values");
352 for(int i = 0; i < (int)aiNodeUnits->getChildCount(); ++i) {
353 const XmlNode *unitNode= aiNodeUnits->getChild("static", i);
354 AIBehaviorStaticValueCategory type = aibsvcMaxBuildRadius;
355 if(unitNode->hasAttribute("type") == true) {
356 type = static_cast<AIBehaviorStaticValueCategory>(
357 unitNode->getAttribute("type")->getIntValue());
358 }
359 else {
360 type = EnumParser<AIBehaviorStaticValueCategory>::getEnum(
361 unitNode->getAttribute("type-name")->getValue());
362 //printf("Discovered overriden static value for AI, type = %d, value = %d\n",type,value);
363 }
364
365 int value = unitNode->getAttribute("value")->getIntValue();
366 mapAIBehaviorStaticOverrideValues[type]=value;
367 //printf("Discovered overriden static value for AI, type = %d, value = %d\n",type,value);
368 }
369 }
370
371 if(aiNode->hasChild("worker-units") == true) {
372 const XmlNode *aiNodeUnits= aiNode->getChild("worker-units");
373 for(int i = 0; i < (int)aiNodeUnits->getChildCount(); ++i) {
374 const XmlNode *unitNode= aiNodeUnits->getChild("unit", i);
375 string name= unitNode->getAttribute("name")->getRestrictedValue();
376 int minimum= unitNode->getAttribute("minimum")->getIntValue();
377
378 mapAIBehaviorUnitCategories[aibcWorkerUnits].push_back(PairPUnitTypeInt(getUnitType(name), minimum));
379 }
380 }
381 if(aiNode->hasChild("warrior-units") == true) {
382 const XmlNode *aiNodeUnits= aiNode->getChild("warrior-units");
383 for(int i = 0; i < (int)aiNodeUnits->getChildCount(); ++i) {
384 const XmlNode *unitNode= aiNodeUnits->getChild("unit", i);
385 string name= unitNode->getAttribute("name")->getRestrictedValue();
386 int minimum= unitNode->getAttribute("minimum")->getIntValue();
387
388 mapAIBehaviorUnitCategories[aibcWarriorUnits].push_back(PairPUnitTypeInt(getUnitType(name), minimum));
389 }
390 }
391 if(aiNode->hasChild("resource-producer-units") == true) {
392 const XmlNode *aiNodeUnits= aiNode->getChild("resource-producer-units");
393 for(int i = 0; i < (int)aiNodeUnits->getChildCount(); ++i) {
394 const XmlNode *unitNode= aiNodeUnits->getChild("unit", i);
395 string name= unitNode->getAttribute("name")->getRestrictedValue();
396 int minimum= unitNode->getAttribute("minimum")->getIntValue();
397
398 mapAIBehaviorUnitCategories[aibcResourceProducerUnits].push_back(PairPUnitTypeInt(getUnitType(name), minimum));
399 }
400 }
401 if(aiNode->hasChild("building-units") == true) {
402 const XmlNode *aiNodeUnits= aiNode->getChild("building-units");
403 for(int i = 0; i < (int)aiNodeUnits->getChildCount(); ++i) {
404 const XmlNode *unitNode= aiNodeUnits->getChild("unit", i);
405 string name= unitNode->getAttribute("name")->getRestrictedValue();
406 int minimum= unitNode->getAttribute("minimum")->getIntValue();
407
408 mapAIBehaviorUnitCategories[aibcBuildingUnits].push_back(PairPUnitTypeInt(getUnitType(name), minimum));
409 }
410 }
411
412 if(aiNode->hasChild("upgrades") == true) {
413 const XmlNode *aiNodeUpgrades= aiNode->getChild("upgrades");
414 for(int i = 0; i < (int)aiNodeUpgrades->getChildCount(); ++i) {
415 const XmlNode *upgradeNode= aiNodeUpgrades->getChild("upgrade", i);
416 string name= upgradeNode->getAttribute("name")->getRestrictedValue();
417
418 vctAIBehaviorUpgrades.push_back(getUpgradeType(name));
419 }
420 }
421 }
422 }
423 if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__);
424 }
425
getAIBehaviorStaticOverideValue(AIBehaviorStaticValueCategory type) const426 int FactionType::getAIBehaviorStaticOverideValue(AIBehaviorStaticValueCategory type) const {
427 int result = INT_MAX;
428 std::map<AIBehaviorStaticValueCategory, int >::const_iterator iterFind =
429 mapAIBehaviorStaticOverrideValues.find(type);
430 if(iterFind != mapAIBehaviorStaticOverrideValues.end()) {
431 result = iterFind->second;
432 }
433 return result;
434 }
435
getAIBehaviorUnits(AIBehaviorUnitCategory category) const436 const std::vector<FactionType::PairPUnitTypeInt> FactionType::getAIBehaviorUnits(AIBehaviorUnitCategory category) const {
437 std::map<AIBehaviorUnitCategory, std::vector<PairPUnitTypeInt> >::const_iterator iterFind = mapAIBehaviorUnitCategories.find(category);
438 if(iterFind != mapAIBehaviorUnitCategories.end()) {
439 return iterFind->second;
440 }
441 return std::vector<FactionType::PairPUnitTypeInt>();
442 }
443
~FactionType()444 FactionType::~FactionType(){
445 delete music;
446 music = NULL;
447 }
448
validateFactionType()449 std::vector<std::string> FactionType::validateFactionType() {
450 std::vector<std::string> results;
451
452 const uint32 MAX_BITRATE_WARNING = 200000;
453 StrSound *factionMusic = getMusic();
454 if(factionMusic != NULL && factionMusic->getInfo()->getBitRate() > MAX_BITRATE_WARNING) {
455 char szBuf[8096]="";
456 snprintf(szBuf,8096,"The Faction [%s] has the music [%s]\nwhich has a bitrate of [%u] which may cause some sound drivers to crash, please use a bitrate of %d or less!",this->getName().c_str(),factionMusic->getFileName().c_str(),factionMusic->getInfo()->getBitRate(),MAX_BITRATE_WARNING);
457 results.push_back(szBuf);
458 }
459
460 for(int i=0; i < (int)unitTypes.size(); ++i){
461 UnitType &unitType = unitTypes[i];
462
463 for(int i = 0; i < (int)unitType.getSelectionSounds().getSounds().size(); ++i) {
464 StaticSound *sound = unitType.getSelectionSounds().getSounds()[i];
465 if(sound != NULL && sound->getInfo()->getBitRate() > MAX_BITRATE_WARNING) {
466 char szBuf[8096]="";
467 snprintf(szBuf,8096,"The Unit [%s] in Faction [%s] has the sound [%s]\nwhich has a bitrate of [%u] which may cause some sound drivers to crash, please use a bitrate of %d or less!",unitType.getName().c_str(),this->getName().c_str(),sound->getFileName().c_str(),sound->getInfo()->getBitRate(),MAX_BITRATE_WARNING);
468 results.push_back(szBuf);
469 }
470 }
471 for(int i = 0; i < (int)unitType.getCommandSounds().getSounds().size(); ++i) {
472 StaticSound *sound = unitType.getCommandSounds().getSounds()[i];
473 if(sound != NULL && sound->getInfo()->getBitRate() > MAX_BITRATE_WARNING) {
474 char szBuf[8096]="";
475 snprintf(szBuf,8096,"The Unit [%s] in Faction [%s] has the sound [%s]\nwhich has a bitrate of [%u] which may cause some sound drivers to crash, please use a bitrate of %d or less!",unitType.getName().c_str(),this->getName().c_str(),sound->getFileName().c_str(),sound->getInfo()->getBitRate(),MAX_BITRATE_WARNING);
476 results.push_back(szBuf);
477 }
478 }
479
480 int morphCommandCount = 0;
481 for(int j = 0; j < (int)unitType.getCommandTypeCount(); ++j) {
482 const CommandType *cmdType = unitType.getCommandType(j);
483 if(cmdType != NULL) {
484 // Check every unit's commands to validate that for every upgrade-requirements
485 // upgrade we have a unit that can do the upgrade in the faction.
486 for(int k = 0; k < cmdType->getUpgradeReqCount(); ++k) {
487 const UpgradeType *upgradeType = cmdType->getUpgradeReq(k);
488
489 if(upgradeType != NULL) {
490 // Now lets find a unit that can produced-upgrade this upgrade
491 bool foundUpgraderUnit = false;
492 for(int l=0; l < (int)unitTypes.size() && foundUpgraderUnit == false; ++l){
493 UnitType &unitType2 = unitTypes[l];
494 for(int m = 0; m < unitType2.getCommandTypeCount() && foundUpgraderUnit == false; ++m) {
495 const CommandType *cmdType2 = unitType2.getCommandType(m);
496 if(cmdType2 != NULL && dynamic_cast<const UpgradeCommandType *>(cmdType2) != NULL) {
497 const UpgradeCommandType *uct = dynamic_cast<const UpgradeCommandType *>(cmdType2);
498 if(uct != NULL) {
499 const UpgradeType *upgradeType2 = uct->getProducedUpgrade();
500 if(upgradeType2 != NULL && upgradeType2->getName() == upgradeType->getName()) {
501 foundUpgraderUnit = true;
502 break;
503 }
504 }
505 }
506 }
507 }
508
509 if(foundUpgraderUnit == false) {
510 char szBuf[8096]="";
511 snprintf(szBuf,8096,"The Unit [%s] in Faction [%s] has the command [%s]\nwhich has upgrade requirement [%s] but there are no units able to perform the upgrade!",unitType.getName().c_str(),this->getName().c_str(),cmdType->getName().c_str(),upgradeType->getName().c_str());
512 results.push_back(szBuf);
513 }
514 }
515 }
516
517 // Ensure for each build type command that the build units
518 // exist in this faction
519 if(cmdType->getClass() == ccBuild) {
520 const BuildCommandType *build = dynamic_cast<const BuildCommandType *>(cmdType);
521 if(build == NULL) {
522 throw megaglest_runtime_error("build == NULL");
523 }
524 for(int k = 0; k < build->getBuildingCount(); ++k) {
525 const UnitType *buildUnit = build->getBuilding(k);
526
527 // Now lets find the unit that we should be able to build
528 bool foundUnit = false;
529 for(int l=0; l < (int)unitTypes.size() && foundUnit == false; ++l){
530 UnitType &unitType2 = unitTypes[l];
531 if(unitType2.getName() == buildUnit->getName()) {
532 foundUnit = true;
533
534 // Now also validate the the unit to be built
535 // has a be_built_skill
536 if(buildUnit->hasSkillClass(scBeBuilt) == false) {
537 char szBuf[8096]="";
538 snprintf(szBuf,8096,"The Unit [%s] in Faction [%s] has the command [%s]\nwhich can build the Unit [%s] but the Unit to be built\ndoes not have the skill class [be_built_skill] in this faction!",unitType.getName().c_str(),this->getName().c_str(),cmdType->getName().c_str(),buildUnit->getName().c_str());
539 results.push_back(szBuf);
540 }
541
542 break;
543 }
544 }
545
546 if(foundUnit == false) {
547 char szBuf[8096]="";
548 snprintf(szBuf,8096,"The Unit [%s] in Faction [%s] has the command [%s]\nwhich can build the Unit [%s] but the Unit to be built does not exist in this faction!",unitType.getName().c_str(),this->getName().c_str(),cmdType->getName().c_str(),buildUnit->getName().c_str());
549 results.push_back(szBuf);
550 }
551 }
552 }
553 // Ensure for each repair type command that the repair units
554 // exist in this faction
555 if(cmdType->getClass() == ccRepair) {
556 const RepairCommandType *repair = dynamic_cast<const RepairCommandType *>(cmdType);
557 if(repair == NULL) {
558 throw megaglest_runtime_error("repair == NULL");
559 }
560 for(int k = 0; k < repair->getRepairCount(); ++k) {
561 const UnitType *repairUnit = repair->getRepair(k);
562
563 // Now lets find the unit that we should be able to repair
564 bool foundUnit = false;
565 for(int l=0; l < (int)unitTypes.size() && foundUnit == false; ++l){
566 UnitType &unitType2 = unitTypes[l];
567 if(unitType2.getName() == repairUnit->getName()) {
568 foundUnit = true;
569 break;
570 }
571 }
572
573 if(foundUnit == false) {
574 char szBuf[8096]="";
575 snprintf(szBuf,8096,"The Unit [%s] in Faction [%s] has the command [%s]\nwhich can repair the Unit [%s] but the Unit to be repaired does not exist in this faction!",unitType.getName().c_str(),this->getName().c_str(),cmdType->getName().c_str(),repairUnit->getName().c_str());
576 results.push_back(szBuf);
577 }
578 }
579 }
580 // Ensure for each morph type command that the morph units
581 // exist in this faction
582 if(cmdType->getClass() == ccMorph) {
583 const MorphCommandType *morph = dynamic_cast<const MorphCommandType *>(cmdType);
584 if(morph != NULL) {
585 morphCommandCount++;
586 const UnitType *morphUnit = morph->getMorphUnit();
587
588 // Now lets find the unit that we should be able to morph
589 // to
590 bool foundUnit = false;
591 for(int l=0; l < (int)unitTypes.size() && foundUnit == false; ++l){
592 UnitType &unitType2 = unitTypes[l];
593 if(unitType2.getName() == morphUnit->getName()) {
594 foundUnit = true;
595 break;
596 }
597 }
598
599 if(foundUnit == false) {
600 char szBuf[8096]="";
601 snprintf(szBuf,8096,"The Unit [%s] in Faction [%s] has the command [%s]\nwhich can morph into the Unit [%s] but the Unit to be morphed to does not exist in this faction!",unitType.getName().c_str(),this->getName().c_str(),cmdType->getName().c_str(),morphUnit->getName().c_str());
602 results.push_back(szBuf);
603 }
604 }
605 }
606 }
607 }
608
609 const int maxMorphsAllowed = 6;
610 if(morphCommandCount > maxMorphsAllowed) {
611 char szBuf[8096]="";
612 snprintf(szBuf,8096,"The Unit [%s] in Faction [%s] has more than %d morph commands which is too many to display in the UI!",unitType.getName().c_str(),this->getName().c_str(),maxMorphsAllowed);
613 results.push_back(szBuf);
614 }
615
616 // Check every unit's unit requirements to validate that for every unit-requirements
617 // we have the units required in the faction.
618 for(int j = 0; j < unitType.getUnitReqCount(); ++j) {
619 const UnitType *unitType2 = unitType.getUnitReq(j);
620 if(unitType2 != NULL) {
621 // Now lets find the required unit
622 bool foundUnit = false;
623 for(int l=0; l < (int)unitTypes.size() && foundUnit == false; ++l){
624 UnitType &unitType3 = unitTypes[l];
625
626 if(unitType2->getName() == unitType3.getName()) {
627 foundUnit = true;
628 break;
629 }
630 }
631
632 if(foundUnit == false) {
633 char szBuf[8096]="";
634 snprintf(szBuf,8096,"The Unit [%s] in Faction [%s] has the required Unit [%s]\nbut the required unit does not exist in this faction!",unitType.getName().c_str(),this->getName().c_str(),unitType2->getName().c_str());
635 results.push_back(szBuf);
636 }
637 }
638 }
639
640 // Now check that at least 1 other unit can produce, build or morph this unit
641 bool foundUnit = false;
642 for(int l=0; l < (int)unitTypes.size() && foundUnit == false; ++l){
643 UnitType &unitType2 = unitTypes[l];
644
645 for(int j = 0; j < unitType2.getCommandTypeCount() && foundUnit == false; ++j) {
646 const CommandType *cmdType = unitType2.getCommandType(j);
647 if(cmdType != NULL) {
648 // Check if this is a produce command
649 if(cmdType->getClass() == ccProduce) {
650 const ProduceCommandType *produce = dynamic_cast<const ProduceCommandType *>(cmdType);
651 if(produce != NULL) {
652 const UnitType *produceUnit = produce->getProducedUnit();
653
654 if( produceUnit != NULL &&
655 unitType.getId() != unitType2.getId() &&
656 unitType.getName() == produceUnit->getName()) {
657 foundUnit = true;
658 break;
659 }
660 }
661 }
662 // Check if this is a build command
663 if(cmdType->getClass() == ccBuild) {
664 const BuildCommandType *build = dynamic_cast<const BuildCommandType *>(cmdType);
665 if(build == NULL) {
666 throw megaglest_runtime_error("build == NULL");
667 }
668 for(int k = 0; k < build->getBuildingCount() && foundUnit == false; ++k) {
669 const UnitType *buildUnit = build->getBuilding(k);
670
671 if( buildUnit != NULL &&
672 unitType.getId() != unitType2.getId() &&
673 unitType.getName() == buildUnit->getName()) {
674 foundUnit = true;
675 break;
676 }
677 }
678 if(foundUnit == true) {
679 break;
680 }
681 }
682 // Check if this is a morph command
683 if(cmdType->getClass() == ccMorph) {
684 const MorphCommandType *morph = dynamic_cast<const MorphCommandType *>(cmdType);
685 if(morph == NULL) {
686 throw megaglest_runtime_error("morph == NULL");
687 }
688 const UnitType *morphUnit = morph->getMorphUnit();
689
690 if( morphUnit != NULL &&
691 unitType.getId() != unitType2.getId() &&
692 unitType.getName() == morphUnit->getName()) {
693 foundUnit = true;
694 break;
695 }
696 }
697
698 // Check if this is an attack command with spawned units on attack
699 if(cmdType->getClass() == ccAttack) {
700 const AttackCommandType *act= dynamic_cast<const AttackCommandType*>(cmdType);
701 if( act != NULL && act->getAttackSkillType() != NULL &&
702 act->getAttackSkillType()->getSpawnUnit() != "" && act->getAttackSkillType()->getSpawnUnitCount() > 0) {
703
704 if( unitType.getId() != unitType2.getId() &&
705 unitType.getName() == act->getAttackSkillType()->getSpawnUnit()) {
706 foundUnit = true;
707 break;
708 }
709 }
710 }
711 }
712 }
713 }
714
715 if(foundUnit == false) {
716 //printf("Problem for unit [%s] unitTypes.size() = " MG_SIZE_T_SPECIFIER "\n",unitType.getName().c_str(),unitTypes.size());
717
718 char szBuf[8096]="";
719 snprintf(szBuf,8096,"The Unit [%s] in Faction [%s] has no other units that can produce, build or morph into it in this faction!",unitType.getName().c_str(),this->getName().c_str());
720 results.push_back(szBuf);
721 }
722
723 // Ensure that all attack skill types have valid values
724 if(unitType.hasSkillClass(scAttack) == true) {
725 for(int j = 0; j < unitType.getSkillTypeCount(); ++j) {
726 const SkillType *st = unitType.getSkillType(j);
727 if(st != NULL && dynamic_cast<const AttackSkillType *>(st) != NULL) {
728 const AttackSkillType *ast = dynamic_cast<const AttackSkillType *>(st);
729 if(ast != NULL && ast->getAttackVar() < 0) {
730 char szBuf[8096]="";
731 snprintf(szBuf,8096,"The Unit [%s] in Faction [%s] has the skill [%s] with an INVALID attack var value which is < 0 [%d]!",unitType.getName().c_str(),this->getName().c_str(),ast->getName().c_str(),ast->getAttackVar());
732 results.push_back(szBuf);
733 }
734 }
735 }
736 }
737 // end
738
739 // Check if the unit has both be_built and harvest skills, this may cause issues
740 // with the AI
741 if(unitType.hasSkillClass(scBeBuilt) == true && unitType.hasSkillClass(scHarvest) == true) {
742 char szBuf[8096]="";
743 snprintf(szBuf,8096,"The Unit [%s] in Faction [%s] has both a bebuilt and harvest skill which will cause AI problems for CPU players!",unitType.getName().c_str(),this->getName().c_str());
744 results.push_back(szBuf);
745 }
746 // end
747
748 // Check if the unit has harvest skills but not move, meaning they cannot
749 // harvest the resource
750 if(unitType.hasSkillClass(scHarvest) == true && unitType.hasSkillClass(scMove) == false) {
751 char szBuf[8096]="";
752 snprintf(szBuf,8096,"The Unit [%s] in Faction [%s] has a harvest skill but no move skill so it cannot harvest!",unitType.getName().c_str(),this->getName().c_str());
753 results.push_back(szBuf);
754 }
755 // end
756
757 }
758
759 return results;
760 }
761
validateFactionTypeResourceTypes(vector<ResourceType> & resourceTypes)762 std::vector<std::string> FactionType::validateFactionTypeResourceTypes(vector<ResourceType> &resourceTypes) {
763 std::vector<std::string> results;
764
765 for(int i=0; i < (int)unitTypes.size(); ++i) {
766 UnitType &unitType = unitTypes[i];
767
768 // Check every unit's required resources to validate that for every resource-requirements
769 // we have a resource in the faction.
770 for(int j = 0; j < unitType.getCostCount() ; ++j) {
771 const Resource *r = unitType.getCost(j);
772 if(r != NULL && r->getType() != NULL) {
773 bool foundResourceType = false;
774 // Now lets find a matching faction resource type for the unit
775 for(int k=0; k < (int)resourceTypes.size(); ++k){
776 ResourceType &rt = resourceTypes[k];
777
778 if(r->getType()->getName() == rt.getName()) {
779 foundResourceType = true;
780 break;
781 }
782 }
783
784 if(foundResourceType == false) {
785 char szBuf[8096]="";
786 snprintf(szBuf,8096,"The Unit [%s] in Faction [%s] has the resource req [%s]\nbut there are no such resources in this tech!",unitType.getName().c_str(),this->getName().c_str(),r->getType()->getName().c_str());
787 results.push_back(szBuf);
788 }
789 }
790 }
791
792 // Check every unit's stored resources to validate that for every resources-stored
793 // we have a resource in the faction.
794 for(int j = 0; j < unitType.getStoredResourceCount() ; ++j) {
795 const Resource *r = unitType.getStoredResource(j);
796 if(r != NULL && r->getType() != NULL) {
797 bool foundResourceType = false;
798 // Now lets find a matching faction resource type for the unit
799 for(int k=0; k < (int)resourceTypes.size(); ++k){
800 ResourceType &rt = resourceTypes[k];
801
802 if(r->getType()->getName() == rt.getName()) {
803 foundResourceType = true;
804 break;
805 }
806 }
807
808 if(foundResourceType == false) {
809 char szBuf[8096]="";
810 snprintf(szBuf,8096,"The Unit [%s] in Faction [%s] has the stored resource [%s]\nbut there are no such resources in this tech!",unitType.getName().c_str(),this->getName().c_str(),r->getType()->getName().c_str());
811 results.push_back(szBuf);
812 }
813 }
814 }
815
816 for(int j = 0; j < unitType.getCommandTypeCount(); ++j) {
817 const CommandType *cmdType = unitType.getCommandType(j);
818 if(cmdType != NULL) {
819 // Ensure for each harvest type command that the resource
820 // exist in this faction
821 if(cmdType->getClass() == ccHarvest) {
822 const HarvestCommandType *harvest = dynamic_cast<const HarvestCommandType *>(cmdType);
823 if(harvest == NULL) {
824 throw megaglest_runtime_error("harvest == NULL");
825 }
826 for(int k = 0; k < harvest->getHarvestedResourceCount(); ++k) {
827 const ResourceType *harvestResource = harvest->getHarvestedResource(k);
828
829 bool foundResourceType = false;
830 // Now lets find a matching faction resource type for the unit
831 for(int k=0; k < (int)resourceTypes.size(); ++k){
832 ResourceType &rt = resourceTypes[k];
833
834 if(harvestResource->getName() == rt.getName()) {
835 foundResourceType = true;
836 break;
837 }
838 }
839
840 if(foundResourceType == false) {
841 char szBuf[8096]="";
842 snprintf(szBuf,8096,"The Unit [%s] in Faction [%s] has the command [%s] which can harvest the resource [%s]\nbut there are no such resources in this tech!",unitType.getName().c_str(),this->getName().c_str(),cmdType->getName().c_str(),harvestResource->getName().c_str());
843 results.push_back(szBuf);
844 }
845 }
846 }
847 }
848 }
849 }
850
851 return results;
852 }
853
validateFactionTypeUpgradeTypes()854 std::vector<std::string> FactionType::validateFactionTypeUpgradeTypes() {
855 std::vector<std::string> results;
856
857 // For each upgrade type make sure there is at least 1 unit that can produce
858 // the upgrade
859 for(int i = 0; i < (int)upgradeTypes.size(); ++i) {
860 const UpgradeType &upgradeType = upgradeTypes[i];
861
862 // First find a unit with a command type to upgrade to this Upgrade type
863 bool foundUnit = false;
864 for(int j=0; j < (int)unitTypes.size() && foundUnit == false; ++j){
865 UnitType &unitType = unitTypes[j];
866 for(int k = 0; k < unitType.getCommandTypeCount() && foundUnit == false; ++k) {
867 const CommandType *cmdType = unitType.getCommandType(k);
868 if(cmdType != NULL) {
869 // Ensure for each build type command that the build units
870 // exist in this faction
871 if(cmdType->getClass() == ccUpgrade) {
872 const UpgradeCommandType *upgrade = dynamic_cast<const UpgradeCommandType *>(cmdType);
873 if(upgrade != NULL) {
874 const UpgradeType *upgradeType2 = upgrade->getProducedUpgrade();
875
876 if(upgradeType2 != NULL && upgradeType.getName() == upgradeType2->getName()) {
877 foundUnit = true;
878 break;
879 }
880 }
881 }
882 }
883 }
884 }
885
886 if(foundUnit == false) {
887 char szBuf[8096]="";
888 snprintf(szBuf,8096,"The Upgrade Type [%s] in Faction [%s] has no Unit able to produce this upgrade in this faction!",upgradeType.getName().c_str(),this->getName().c_str());
889 results.push_back(szBuf);
890 }
891 }
892
893 return results;
894 }
895
896 // ==================== get ====================
897
getUnitType(const string & name) const898 const UnitType *FactionType::getUnitType(const string &name) const{
899 for(int i=0; i < (int)unitTypes.size();i++){
900 if(unitTypes[i].getName(false)==name){
901 return &unitTypes[i];
902 }
903 }
904
905 printf("In [%s::%s Line: %d] scanning [%s] size = " MG_SIZE_T_SPECIFIER "\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,name.c_str(),unitTypes.size());
906 for(int i=0; i < (int)unitTypes.size();i++){
907 printf("In [%s::%s Line: %d] scanning [%s] idx = %d [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,name.c_str(),i,unitTypes[i].getName(false).c_str());
908 }
909
910 if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] scanning [%s] size = %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,name.c_str(),unitTypes.size());
911 for(int i=0; i < (int)unitTypes.size();i++){
912 if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] scanning [%s] idx = %d [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,name.c_str(),i,unitTypes[i].getName(false).c_str());
913 }
914
915 throw megaglest_runtime_error("Unit type not found: [" + name + "] in faction type [" + this->name + "]",true);
916 }
917
getUnitTypeById(int id) const918 const UnitType *FactionType::getUnitTypeById(int id) const{
919 for(int i=0; i < (int)unitTypes.size();i++){
920 if(unitTypes[i].getId() == id) {
921 return &unitTypes[i];
922 }
923 }
924
925 printf("In [%s::%s Line: %d] scanning [%d] size = " MG_SIZE_T_SPECIFIER "\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,id,unitTypes.size());
926 for(int i=0; i < (int)unitTypes.size();i++){
927 printf("In [%s::%s Line: %d] scanning [%s] idx = %d [%s][%d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,name.c_str(),i,unitTypes[i].getName(false).c_str(),unitTypes[i].getId());
928 }
929
930 if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] scanning [%s] size = %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,name.c_str(),unitTypes.size());
931 for(int i=0; i < (int)unitTypes.size();i++){
932 if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] scanning [%s] idx = %d [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,name.c_str(),i,unitTypes[i].getName(false).c_str());
933 }
934
935 throw megaglest_runtime_error("Unit type not found: [" + intToStr(id) + "] in faction type [" + this->name + "]",true);
936 }
937
getUpgradeType(const string & name) const938 const UpgradeType *FactionType::getUpgradeType(const string &name) const{
939 for(int i=0; i < (int)upgradeTypes.size();i++){
940 if(upgradeTypes[i].getName()==name){
941 return &upgradeTypes[i];
942 }
943 }
944
945 printf("In [%s::%s Line: %d] scanning [%s] size = " MG_SIZE_T_SPECIFIER "\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,name.c_str(),unitTypes.size());
946 for(int i=0; i < (int)upgradeTypes.size();i++){
947 printf("In [%s::%s Line: %d] scanning [%s] idx = %d [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,name.c_str(),i,upgradeTypes[i].getName().c_str());
948 }
949
950 if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] scanning [%s] size = %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,name.c_str(),unitTypes.size());
951 for(int i=0; i < (int)upgradeTypes.size();i++){
952 if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] scanning [%s] idx = %d [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,name.c_str(),i,upgradeTypes[i].getName().c_str());
953 }
954
955 throw megaglest_runtime_error("Upgrade type not found: [" + name + "] in faction type [" + this->name + "]",true);
956 }
957
getStartingResourceAmount(const ResourceType * resourceType) const958 int FactionType::getStartingResourceAmount(const ResourceType *resourceType) const{
959 for(int i=0; i < (int)startingResources.size(); ++i){
960 if(startingResources[i].getType()==resourceType){
961 return startingResources[i].getAmount();
962 }
963 }
964 return 0;
965 }
966
deletePixels()967 void FactionType::deletePixels() {
968 for(int i = 0; i < (int)unitTypes.size(); ++i) {
969 UnitType &unitType = unitTypes[i];
970 Texture2D *texture = unitType.getMeetingPointImage();
971 if(texture != NULL) {
972 texture->deletePixels();
973 }
974 }
975 }
976
factionUsesResourceType(const ResourceType * rt) const977 bool FactionType::factionUsesResourceType(const ResourceType *rt) const {
978 bool factionUsesResourceType = false;
979 if(rt != NULL) {
980 for(unsigned int j = 0; factionUsesResourceType == false && j < (unsigned int)this->getUnitTypeCount(); ++j) {
981 const UnitType *ut= this->getUnitType(j);
982 for(int k = 0; factionUsesResourceType == false && k < ut->getCostCount(); ++k) {
983 const Resource *costResource = ut->getCost(k);
984 //printf("#1 factionUsesResourceType, unit [%s] resource [%s] cost [%s]\n",ut->getName().c_str(),rt->getName().c_str(),costResource->getType()->getName().c_str());
985
986 if(costResource != NULL && costResource->getType() != NULL &&
987 costResource->getType()->getName() == rt->getName()) {
988 factionUsesResourceType = true;
989 break;
990 }
991 }
992 if(factionUsesResourceType == false) {
993 for(unsigned int k = 0; factionUsesResourceType == false && k < (unsigned int)ut->getCommandTypeCount(); ++k) {
994 const CommandType *commandType = ut->getCommandType(k);
995 if(commandType != NULL && commandType->getClass() == ccHarvest) {
996 const HarvestCommandType *hct = dynamic_cast<const HarvestCommandType *>(commandType);
997 if(hct != NULL && hct->getHarvestedResourceCount() > 0) {
998 for(unsigned int l = 0; factionUsesResourceType == false && l < (unsigned int)hct->getHarvestedResourceCount(); ++l) {
999 //printf("#2 factionUsesResourceType, unit [%s] resource [%s] harvest [%s]\n",ut->getName().c_str(),rt->getName().c_str(),hct->getHarvestedResource(l)->getName().c_str());
1000
1001 if(hct->getHarvestedResource(l)->getName() == rt->getName()) {
1002 factionUsesResourceType = true;
1003 break;
1004 }
1005 }
1006 }
1007 }
1008 }
1009 }
1010 }
1011 }
1012 return factionUsesResourceType;
1013 }
1014
toString() const1015 std::string FactionType::toString() const {
1016 std::string result = "Faction Name: " + name + "\n";
1017
1018 result += "Unit Type List count = " + intToStr(this->getUnitTypeCount()) + "\n";
1019 for(int i=0; i < (int)unitTypes.size();i++) {
1020 result += unitTypes[i].toString() + "\n";
1021 }
1022
1023 result += "Upgrade Type List count = " + intToStr(this->getUpgradeTypeCount()) + "\n";
1024 for(int i=0; i < (int)upgradeTypes.size();i++) {
1025 result += "index: " + intToStr(i) + " " + upgradeTypes[i].getReqDesc(false) + "\n";
1026 }
1027
1028 return result;
1029 }
1030
getName(bool translatedValue) const1031 string FactionType::getName(bool translatedValue) const {
1032 if(translatedValue == false) return name;
1033
1034 Lang &lang = Lang::getInstance();
1035 return lang.getTechTreeString("FactionName_" + name,name.c_str());
1036 }
1037
1038
1039 }}//end namespace
1040