tags feature
Tags feature ( manually merged ) from Omegas pullrequest 25 https://github.com/MegaGlest/megaglest-source/pull/25/ see forum discussion: https://forum.megaglest.org/index.php?topic=9543.0
This commit is contained in:
parent
6ebe0a197c
commit
feb31e27d9
|
@ -61,34 +61,16 @@ bool AttackBoost::isAffected(const Unit *source, const Unit *dest) const {
|
||||||
else {
|
else {
|
||||||
// All units are affected (including enemies)
|
// All units are affected (including enemies)
|
||||||
if(targetType == abtAll) {
|
if(targetType == abtAll) {
|
||||||
destUnitMightApply = (boostUnitList.empty() == true);
|
destUnitMightApply = (boostUnitList.empty() && tags.empty());
|
||||||
|
destUnitMightApply = isInUnitListOrTags(dest->getType());
|
||||||
// Specify which units are affected
|
|
||||||
for(unsigned int i = 0; i < boostUnitList.size(); ++i) {
|
|
||||||
const UnitType *ut = boostUnitList[i];
|
|
||||||
if(dest->getType()->getId() == ut->getId()) {
|
|
||||||
destUnitMightApply = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
// Only same faction units are affected
|
// Only same faction units are affected
|
||||||
else if(targetType == abtFaction) {
|
else if(targetType == abtFaction) {
|
||||||
//if(boostUnitList.empty() == true) {
|
//if(boostUnitList.empty() == true) {
|
||||||
if(source->getFactionIndex() == dest->getFactionIndex()) {
|
if(source->getFactionIndex() == dest->getFactionIndex()) {
|
||||||
//destUnitMightApply = true;
|
//destUnitMightApply = true;
|
||||||
destUnitMightApply = (boostUnitList.empty() == true);
|
destUnitMightApply = (boostUnitList.empty() && tags.empty());
|
||||||
|
destUnitMightApply = isInUnitListOrTags(dest->getType());
|
||||||
// Specify which units are affected
|
|
||||||
for(unsigned int i = 0; i < boostUnitList.size(); ++i) {
|
|
||||||
const UnitType *ut = boostUnitList[i];
|
|
||||||
if(dest->getType()->getId() == ut->getId()) {
|
|
||||||
destUnitMightApply = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
|
@ -97,16 +79,8 @@ bool AttackBoost::isAffected(const Unit *source, const Unit *dest) const {
|
||||||
//if(boostUnitList.empty() == true) {
|
//if(boostUnitList.empty() == true) {
|
||||||
if(source->isAlly(dest) == true) {
|
if(source->isAlly(dest) == true) {
|
||||||
//destUnitMightApply = true;
|
//destUnitMightApply = true;
|
||||||
destUnitMightApply = (boostUnitList.empty() == true);
|
destUnitMightApply = (boostUnitList.empty() && tags.empty());
|
||||||
|
destUnitMightApply = isInUnitListOrTags(dest->getType());
|
||||||
// Specify which units are affected
|
|
||||||
for(unsigned int i = 0; i < boostUnitList.size(); ++i) {
|
|
||||||
const UnitType *ut = boostUnitList[i];
|
|
||||||
if(dest->getType()->getId() == ut->getId()) {
|
|
||||||
destUnitMightApply = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
|
@ -115,28 +89,13 @@ bool AttackBoost::isAffected(const Unit *source, const Unit *dest) const {
|
||||||
//if(boostUnitList.empty() == true) {
|
//if(boostUnitList.empty() == true) {
|
||||||
if(source->isAlly(dest) == false) {
|
if(source->isAlly(dest) == false) {
|
||||||
//destUnitMightApply = true;
|
//destUnitMightApply = true;
|
||||||
destUnitMightApply = (boostUnitList.empty() == true);
|
destUnitMightApply = (boostUnitList.empty() && tags.empty());
|
||||||
|
destUnitMightApply = isInUnitListOrTags(dest->getType());
|
||||||
// Specify which units are affected
|
|
||||||
for(unsigned int i = 0; i < boostUnitList.size(); ++i) {
|
|
||||||
const UnitType *ut = boostUnitList[i];
|
|
||||||
if(dest->getType()->getId() == ut->getId()) {
|
|
||||||
destUnitMightApply = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
//}
|
//}
|
||||||
}
|
}
|
||||||
else if(targetType == abtUnitTypes) {
|
else if(targetType == abtUnitTypes) {
|
||||||
// Specify which units are affected
|
destUnitMightApply = isInUnitListOrTags(dest->getType());
|
||||||
for(unsigned int i = 0; i < boostUnitList.size(); ++i) {
|
|
||||||
const UnitType *ut = boostUnitList[i];
|
|
||||||
if(dest->getType()->getId() == ut->getId()) {
|
|
||||||
destUnitMightApply = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,6 +110,32 @@ bool AttackBoost::isAffected(const Unit *source, const Unit *dest) const {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AttackBoost::isInUnitListOrTags(const UnitType *unitType) const {
|
||||||
|
// Specify which units are affected
|
||||||
|
std::set<const UnitType*>::iterator it;
|
||||||
|
for (it = boostUnitList.begin(); it != boostUnitList.end(); ++it) {
|
||||||
|
const UnitType *boostUnit = *it;
|
||||||
|
if(unitType->getId() == boostUnit->getId()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set<string> unitTags = unitType->getTags();
|
||||||
|
set<string> intersect;
|
||||||
|
set_intersection(tags.begin(),tags.end(),unitTags.begin(),unitTags.end(),
|
||||||
|
std::inserter(intersect,intersect.begin()));
|
||||||
|
if(!intersect.empty()) return true;
|
||||||
|
|
||||||
|
// Otherwise no match
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
string AttackBoost::getTagName(string tag, bool translatedValue) const {
|
||||||
|
if(translatedValue == false) return tag;
|
||||||
|
|
||||||
|
Lang &lang = Lang::getInstance();
|
||||||
|
return lang.getTechTreeString("TagName_" + tag, tag.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
string AttackBoost::getDesc(bool translatedValue) const{
|
string AttackBoost::getDesc(bool translatedValue) const{
|
||||||
Lang &lang= Lang::getInstance();
|
Lang &lang= Lang::getInstance();
|
||||||
string str= "";
|
string str= "";
|
||||||
|
@ -190,14 +175,31 @@ string AttackBoost::getDesc(bool translatedValue) const{
|
||||||
str+= lang.getString("AffectedUnitsFromAll") +":\n";
|
str+= lang.getString("AffectedUnitsFromAll") +":\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
if(boostUnitList.empty() == false) {
|
if(boostUnitList.empty() && tags.empty()) {
|
||||||
for(int i=0; i < (int)boostUnitList.size(); ++i){
|
str+= lang.getString("All")+"\n";
|
||||||
str+= " "+boostUnitList[i]->getName(translatedValue)+"\n";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
str+= lang.getString("All")+"\n";
|
// We want the output to be sorted, so convert the set to a vector and sort that
|
||||||
|
std::vector<const UnitType*> outputUnits(boostUnitList.begin(), boostUnitList.end());
|
||||||
|
std::sort(outputUnits.begin(), outputUnits.end(), UnitTypeSorter());
|
||||||
|
|
||||||
|
vector<const UnitType*>::iterator unitIter;
|
||||||
|
for (unitIter = outputUnits.begin(); unitIter != outputUnits.end(); ++unitIter) {
|
||||||
|
const UnitType *unit = *unitIter;
|
||||||
|
str+= indent+unit->getName(translatedValue)+"\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do the same for tags
|
||||||
|
std::vector<string> outputTags(tags.begin(), tags.end());
|
||||||
|
std::sort(outputTags.begin(), outputTags.end());
|
||||||
|
|
||||||
|
vector<string>::iterator tagIter;
|
||||||
|
for (tagIter = outputTags.begin(); tagIter != outputTags.end(); ++tagIter) {
|
||||||
|
string tag = *tagIter;
|
||||||
|
str+= indent + lang.getString("TagDesc", (translatedValue == true ? "" : "english")) +
|
||||||
|
" " + getTagName(tag,translatedValue) + "\n";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return str;
|
return str;
|
||||||
|
@ -222,10 +224,18 @@ void AttackBoost::loadGame(const XmlNode *rootNode, Faction *faction, const Skil
|
||||||
string unitTypeName = node->getAttribute("name")->getValue();
|
string unitTypeName = node->getAttribute("name")->getValue();
|
||||||
const UnitType *unitType = faction->getType()->getUnitType(unitTypeName);
|
const UnitType *unitType = faction->getType()->getUnitType(unitTypeName);
|
||||||
if(unitType != NULL) {
|
if(unitType != NULL) {
|
||||||
boostUnitList.push_back(unitType);
|
boostUnitList.insert(unitType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(attackBoostNode->hasChild("tag")) {
|
||||||
|
vector<XmlNode *> tagNodeList = attackBoostNode->getChildList("tag");
|
||||||
|
for(unsigned int i = 0; i < tagNodeList.size(); ++i) {
|
||||||
|
XmlNode *node = tagNodeList[i];
|
||||||
|
string tagName = node->getAttribute("name")->getValue();
|
||||||
|
tags.insert(tagName);
|
||||||
|
}
|
||||||
|
}
|
||||||
//boostUpgrade.loadGame(attackBoostNode,faction);
|
//boostUpgrade.loadGame(attackBoostNode,faction);
|
||||||
boostUpgrade = skillType->getAttackBoost()->boostUpgrade;
|
boostUpgrade = skillType->getAttackBoost()->boostUpgrade;
|
||||||
|
|
||||||
|
@ -252,10 +262,17 @@ void AttackBoost::saveGame(XmlNode *rootNode) const {
|
||||||
// AttackBoostTargetType targetType;
|
// AttackBoostTargetType targetType;
|
||||||
attackBoostNode->addAttribute("targetType",intToStr(targetType), mapTagReplacements);
|
attackBoostNode->addAttribute("targetType",intToStr(targetType), mapTagReplacements);
|
||||||
// vector<const UnitType *> boostUnitList;
|
// vector<const UnitType *> boostUnitList;
|
||||||
for(unsigned int i = 0; i < boostUnitList.size(); ++i) {
|
std::set<const UnitType*>::iterator unitIter;
|
||||||
const UnitType *ut = boostUnitList[i];
|
for (unitIter = boostUnitList.begin(); unitIter != boostUnitList.end(); ++unitIter) {
|
||||||
|
const UnitType *unit = *unitIter;
|
||||||
XmlNode *unitTypeNode = attackBoostNode->addChild("UnitType");
|
XmlNode *unitTypeNode = attackBoostNode->addChild("UnitType");
|
||||||
unitTypeNode->addAttribute("name",ut->getName(false), mapTagReplacements);
|
unitTypeNode->addAttribute("name",unit->getName(false), mapTagReplacements);
|
||||||
|
}
|
||||||
|
std::set<string>::iterator tagIter;
|
||||||
|
for (tagIter = tags.begin(); tagIter != tags.end(); ++tagIter) {
|
||||||
|
string tag = *tagIter;
|
||||||
|
XmlNode *unitTypeNode = attackBoostNode->addChild("tag");
|
||||||
|
unitTypeNode->addAttribute("name", tag, mapTagReplacements);
|
||||||
}
|
}
|
||||||
// UpgradeTypeBase boostUpgrade;
|
// UpgradeTypeBase boostUpgrade;
|
||||||
boostUpgrade.saveGame(attackBoostNode);
|
boostUpgrade.saveGame(attackBoostNode);
|
||||||
|
@ -352,38 +369,18 @@ void SkillType::loadAttackBoost(const XmlNode *attackBoostsNode, const XmlNode *
|
||||||
|
|
||||||
if(targetType == "ally") {
|
if(targetType == "ally") {
|
||||||
attackBoost.targetType = abtAlly;
|
attackBoost.targetType = abtAlly;
|
||||||
for(int i = 0;i < (int)attackBoostNode->getChild("target")->getChildCount();++i) {
|
|
||||||
const XmlNode *boostUnitNode = attackBoostNode->getChild("target")->getChild("unit-type", i);
|
|
||||||
attackBoost.boostUnitList.push_back(ft->getUnitType(boostUnitNode->getAttribute("name")->getRestrictedValue()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if(targetType == "foe") {
|
else if(targetType == "foe") {
|
||||||
attackBoost.targetType = abtFoe;
|
attackBoost.targetType = abtFoe;
|
||||||
for(int i = 0;i < (int)attackBoostNode->getChild("target")->getChildCount();++i) {
|
|
||||||
const XmlNode *boostUnitNode = attackBoostNode->getChild("target")->getChild("unit-type", i);
|
|
||||||
attackBoost.boostUnitList.push_back(ft->getUnitType(boostUnitNode->getAttribute("name")->getRestrictedValue()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if(targetType == "faction") {
|
else if(targetType == "faction") {
|
||||||
attackBoost.targetType = abtFaction;
|
attackBoost.targetType = abtFaction;
|
||||||
for(int i = 0;i < (int)attackBoostNode->getChild("target")->getChildCount();++i) {
|
|
||||||
const XmlNode *boostUnitNode = attackBoostNode->getChild("target")->getChild("unit-type", i);
|
|
||||||
attackBoost.boostUnitList.push_back(ft->getUnitType(boostUnitNode->getAttribute("name")->getRestrictedValue()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if(targetType == "unit-types") {
|
else if(targetType == "unit-types") {
|
||||||
attackBoost.targetType = abtUnitTypes;
|
attackBoost.targetType = abtUnitTypes;
|
||||||
for(int i = 0;i < (int)attackBoostNode->getChild("target")->getChildCount();++i) {
|
|
||||||
const XmlNode *boostUnitNode = attackBoostNode->getChild("target")->getChild("unit-type", i);
|
|
||||||
attackBoost.boostUnitList.push_back(ft->getUnitType(boostUnitNode->getAttribute("name")->getRestrictedValue()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if(targetType == "all") {
|
else if(targetType == "all") {
|
||||||
attackBoost.targetType = abtAll;
|
attackBoost.targetType = abtAll;
|
||||||
for(int i = 0;i < (int)attackBoostNode->getChild("target")->getChildCount();++i) {
|
|
||||||
const XmlNode *boostUnitNode = attackBoostNode->getChild("target")->getChild("unit-type", i);
|
|
||||||
attackBoost.boostUnitList.push_back(ft->getUnitType(boostUnitNode->getAttribute("name")->getRestrictedValue()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
char szBuf[8096] = "";
|
char szBuf[8096] = "";
|
||||||
|
@ -391,6 +388,21 @@ void SkillType::loadAttackBoost(const XmlNode *attackBoostsNode, const XmlNode *
|
||||||
throw megaglest_runtime_error(szBuf);
|
throw megaglest_runtime_error(szBuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Load the regular targets
|
||||||
|
const XmlNode *targetNode = attackBoostNode->getChild("target");
|
||||||
|
vector<XmlNode*> targetNodes = targetNode->getChildList("unit-type");
|
||||||
|
for(size_t i = 0;i < targetNodes.size(); ++i) {
|
||||||
|
string unitName = targetNodes.at(i)->getAttribute("name")->getRestrictedValue();
|
||||||
|
attackBoost.boostUnitList.insert(ft->getUnitType(unitName));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load tags
|
||||||
|
vector<XmlNode*> tagNodes = targetNode->getChildList("tag");
|
||||||
|
for(size_t i = 0;i < tagNodes.size(); ++i) {
|
||||||
|
string unitName = tagNodes.at(i)->getAttribute("name")->getRestrictedValue();
|
||||||
|
attackBoost.tags.insert(unitName);
|
||||||
|
}
|
||||||
|
|
||||||
attackBoost.boostUpgrade.load(attackBoostNode,attackBoost.name);
|
attackBoost.boostUpgrade.load(attackBoostNode,attackBoost.name);
|
||||||
if(attackBoostNode->hasChild("particles") == true) {
|
if(attackBoostNode->hasChild("particles") == true) {
|
||||||
const XmlNode *particleNode = attackBoostNode->getChild("particles");
|
const XmlNode *particleNode = attackBoostNode->getChild("particles");
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#include "projectile_type.h"
|
#include "projectile_type.h"
|
||||||
#include "upgrade_type.h"
|
#include "upgrade_type.h"
|
||||||
#include "leak_dumper.h"
|
#include "leak_dumper.h"
|
||||||
|
#include <set>
|
||||||
|
|
||||||
using Shared::Sound::StaticSound;
|
using Shared::Sound::StaticSound;
|
||||||
using Shared::Xml::XmlNode;
|
using Shared::Xml::XmlNode;
|
||||||
|
@ -98,7 +99,8 @@ public:
|
||||||
bool allowMultipleBoosts;
|
bool allowMultipleBoosts;
|
||||||
int radius;
|
int radius;
|
||||||
AttackBoostTargetType targetType;
|
AttackBoostTargetType targetType;
|
||||||
vector<const UnitType *> boostUnitList;
|
std::set<const UnitType *> boostUnitList;
|
||||||
|
std::set<string> tags;
|
||||||
UpgradeTypeBase boostUpgrade;
|
UpgradeTypeBase boostUpgrade;
|
||||||
|
|
||||||
UnitParticleSystemType *unitParticleSystemTypeForSourceUnit;
|
UnitParticleSystemType *unitParticleSystemTypeForSourceUnit;
|
||||||
|
@ -109,9 +111,20 @@ public:
|
||||||
|
|
||||||
bool isAffected(const Unit *source, const Unit *dest) const;
|
bool isAffected(const Unit *source, const Unit *dest) const;
|
||||||
virtual string getDesc(bool translatedValue) const;
|
virtual string getDesc(bool translatedValue) const;
|
||||||
|
string getTagName(string tag, bool translatedValue=false) const;
|
||||||
|
|
||||||
virtual void saveGame(XmlNode *rootNode) const;
|
virtual void saveGame(XmlNode *rootNode) const;
|
||||||
virtual void loadGame(const XmlNode *rootNode, Faction *faction, const SkillType *skillType);
|
virtual void loadGame(const XmlNode *rootNode, Faction *faction, const SkillType *skillType);
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* Checks if a unit is affected by the attack boost by checking if either the UnitType is in
|
||||||
|
* the #boostUnitList or shares a tag with #tags.
|
||||||
|
* @param unitType The unit type to check.
|
||||||
|
* @return True if the unit *might* be affected by the attack boost (still have to check if it's
|
||||||
|
* in range), false otherwise.
|
||||||
|
*/
|
||||||
|
bool isInUnitListOrTags(const UnitType *unitType) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class AnimationAttributes {
|
class AnimationAttributes {
|
||||||
|
|
|
@ -602,7 +602,7 @@ void UnitType::loaddd(int id,const string &dir, const TechTree *techTree,
|
||||||
if(parametersNode->hasChild("resources-death")) {
|
if(parametersNode->hasChild("resources-death")) {
|
||||||
const XmlNode *deathResourcesNode= parametersNode->getChild("resources-death");
|
const XmlNode *deathResourcesNode= parametersNode->getChild("resources-death");
|
||||||
|
|
||||||
for(int i=0; i < deathResourcesNode->getChildCount(); ++i){
|
for(size_t i=0; i < deathResourcesNode->getChildCount(); ++i){
|
||||||
const XmlNode *resourceNode= deathResourcesNode->getChild("resource", i);
|
const XmlNode *resourceNode= deathResourcesNode->getChild("resource", i);
|
||||||
string name= resourceNode->getAttribute("name")->getRestrictedValue();
|
string name= resourceNode->getAttribute("name")->getRestrictedValue();
|
||||||
|
|
||||||
|
@ -656,6 +656,17 @@ void UnitType::loaddd(int id,const string &dir, const TechTree *techTree,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tags
|
||||||
|
if(parametersNode->hasChild("tags")) {
|
||||||
|
const XmlNode *tagsNode= parametersNode->getChild("tags");
|
||||||
|
|
||||||
|
for(size_t i=0; i < tagsNode->getChildCount(); ++i){
|
||||||
|
const XmlNode *resourceNode= tagsNode->getChild("tag", i);
|
||||||
|
string tag= resourceNode->getAttribute("value")->getRestrictedValue();
|
||||||
|
tags.insert(tag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//image
|
//image
|
||||||
const XmlNode *imageNode= parametersNode->getChild("image");
|
const XmlNode *imageNode= parametersNode->getChild("image");
|
||||||
image= Renderer::getInstance().newTexture2D(rsGame);
|
image= Renderer::getInstance().newTexture2D(rsGame);
|
||||||
|
|
|
@ -193,6 +193,7 @@ private:
|
||||||
StoredResources storedResources;
|
StoredResources storedResources;
|
||||||
Levels levels;
|
Levels levels;
|
||||||
LootableResources lootableResources;
|
LootableResources lootableResources;
|
||||||
|
std::set<string> tags;
|
||||||
|
|
||||||
//meeting point
|
//meeting point
|
||||||
bool meetingPoint;
|
bool meetingPoint;
|
||||||
|
@ -265,6 +266,7 @@ public:
|
||||||
inline const Resource *getStoredResource(int i) const {return &storedResources[i];}
|
inline const Resource *getStoredResource(int i) const {return &storedResources[i];}
|
||||||
int getLootableResourceCount() const {return lootableResources.size();}
|
int getLootableResourceCount() const {return lootableResources.size();}
|
||||||
inline const LootableResource getLootableResource(int i) const {return lootableResources.at(i);}
|
inline const LootableResource getLootableResource(int i) const {return lootableResources.at(i);}
|
||||||
|
const set<string> &getTags() const {return tags;}
|
||||||
bool getCellMapCell(int x, int y, CardinalDir facing) const;
|
bool getCellMapCell(int x, int y, CardinalDir facing) const;
|
||||||
inline bool getMeetingPoint() const {return meetingPoint;}
|
inline bool getMeetingPoint() const {return meetingPoint;}
|
||||||
inline bool getCountUnitDeathInStats() const {return countUnitDeathInStats;}
|
inline bool getCountUnitDeathInStats() const {return countUnitDeathInStats;}
|
||||||
|
@ -329,6 +331,17 @@ private:
|
||||||
void computeFirstCtOfClass();
|
void computeFirstCtOfClass();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to sort UnitType. Sorts by *translated* unit name. Sorting is case sensitive and done in
|
||||||
|
* lexical order.
|
||||||
|
*/
|
||||||
|
struct UnitTypeSorter
|
||||||
|
{
|
||||||
|
bool operator()( const UnitType *left, const UnitType *right ) const {
|
||||||
|
return left->getName(true) < right->getName(true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
}}//end namespace
|
}}//end namespace
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -601,18 +601,43 @@ string UpgradeType::getName(bool translatedValue) const {
|
||||||
return lang.getTechTreeString("UpgradeTypeName_" + name,name.c_str());
|
return lang.getTechTreeString("UpgradeTypeName_" + name,name.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string UpgradeType::getTagName(string tag, bool translatedValue) const {
|
||||||
|
if(translatedValue == false) return tag;
|
||||||
|
|
||||||
|
Lang &lang = Lang::getInstance();
|
||||||
|
return lang.getTechTreeString("TagName_" + tag, tag.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
string UpgradeType::getReqDesc(bool translatedValue) const{
|
string UpgradeType::getReqDesc(bool translatedValue) const{
|
||||||
Lang &lang= Lang::getInstance();
|
Lang &lang= Lang::getInstance();
|
||||||
string str= ProducibleType::getReqDesc(translatedValue);
|
string str= ProducibleType::getReqDesc(translatedValue);
|
||||||
string indent=" ";
|
string indent=" ";
|
||||||
if(getEffectCount()>0){
|
if(!effects.empty() || !tags.empty()){
|
||||||
str+= "\n"+ lang.getString("Upgrades",(translatedValue == true ? "" : "english"))+"\n";
|
str+= "\n"+ lang.getString("Upgrades",(translatedValue == true ? "" : "english"))+"\n";
|
||||||
}
|
}
|
||||||
str+=UpgradeTypeBase::getDesc(translatedValue);
|
str+=UpgradeTypeBase::getDesc(translatedValue);
|
||||||
if(getEffectCount()>0){
|
if(!effects.empty() || !tags.empty()){
|
||||||
str+= lang.getString("AffectedUnits",(translatedValue == true ? "" : "english"))+"\n";
|
str+= lang.getString("AffectedUnits",(translatedValue == true ? "" : "english"))+"\n";
|
||||||
for(int i=0; i<getEffectCount(); ++i){
|
|
||||||
str+= indent+getEffect(i)->getName(translatedValue)+"\n";
|
// We want the output to be sorted, so convert the set to a vector and sort that
|
||||||
|
std::vector<const UnitType*> outputUnits(effects.begin(), effects.end());
|
||||||
|
std::sort(outputUnits.begin(), outputUnits.end(), UnitTypeSorter());
|
||||||
|
|
||||||
|
vector<const UnitType*>::iterator unitIter;
|
||||||
|
for (unitIter = outputUnits.begin(); unitIter != outputUnits.end(); ++unitIter) {
|
||||||
|
const UnitType *unit = *unitIter;
|
||||||
|
str+= indent+unit->getName(translatedValue)+"\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do the same for tags
|
||||||
|
std::vector<string> outputTags(tags.begin(), tags.end());
|
||||||
|
std::sort(outputTags.begin(), outputTags.end());
|
||||||
|
|
||||||
|
vector<string>::iterator tagIter;
|
||||||
|
for (tagIter = outputTags.begin(); tagIter != outputTags.end(); ++tagIter) {
|
||||||
|
string tag = *tagIter;
|
||||||
|
str+= indent + lang.getString("TagDesc", (translatedValue == true ? "" : "english")) +
|
||||||
|
" " + getTagName(tag,translatedValue) + "\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return str;
|
return str;
|
||||||
|
@ -757,29 +782,24 @@ void UpgradeType::load(const string &dir, const TechTree *techTree,
|
||||||
sortedItems.clear();
|
sortedItems.clear();
|
||||||
hasDup = false;
|
hasDup = false;
|
||||||
|
|
||||||
//effects
|
//effects -- get list of affected units
|
||||||
const XmlNode *effectsNode= upgradeNode->getChild("effects");
|
const XmlNode *effectsNode= upgradeNode->getChild("effects");
|
||||||
for(int i = 0; i < (int)effectsNode->getChildCount(); ++i) {
|
vector<XmlNode*> unitNodes= effectsNode->getChildList("unit");
|
||||||
const XmlNode *unitNode= effectsNode->getChild("unit", i);
|
for(size_t i = 0; i < unitNodes.size(); ++i) {
|
||||||
|
const XmlNode *unitNode= unitNodes.at(i);
|
||||||
string name= unitNode->getAttribute("name")->getRestrictedValue();
|
string name= unitNode->getAttribute("name")->getRestrictedValue();
|
||||||
|
|
||||||
if(sortedItems.find(name) != sortedItems.end()) {
|
effects.insert(factionType->getUnitType(name));
|
||||||
hasDup = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
sortedItems[name] = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(hasDup) {
|
//effects -- convert tags into units
|
||||||
printf("WARNING, upgrade type [%s] has one or more duplicate effects\n",this->getName().c_str());
|
vector<XmlNode*> tagNodes= effectsNode->getChildList("tag");
|
||||||
|
for(size_t i = 0; i < tagNodes.size(); ++i) {
|
||||||
|
const XmlNode *tagNode= tagNodes.at(i);
|
||||||
|
string name= tagNode->getAttribute("name")->getRestrictedValue();
|
||||||
|
tags.insert(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(std::map<string,int>::iterator iterMap = sortedItems.begin();
|
|
||||||
iterMap != sortedItems.end(); ++iterMap) {
|
|
||||||
effects.push_back(factionType->getUnitType(iterMap->first));
|
|
||||||
}
|
|
||||||
sortedItems.clear();
|
|
||||||
|
|
||||||
//values
|
//values
|
||||||
UpgradeTypeBase::load(upgradeNode,name);
|
UpgradeTypeBase::load(upgradeNode,name);
|
||||||
}
|
}
|
||||||
|
@ -792,7 +812,15 @@ void UpgradeType::load(const string &dir, const TechTree *techTree,
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UpgradeType::isAffected(const UnitType *unitType) const{
|
bool UpgradeType::isAffected(const UnitType *unitType) const{
|
||||||
return find(effects.begin(), effects.end(), unitType)!=effects.end();
|
if(std::find(effects.begin(), effects.end(), unitType)!=effects.end()) return true;
|
||||||
|
|
||||||
|
const set<string> unitTags = unitType->getTags();
|
||||||
|
set<string> intersect;
|
||||||
|
set_intersection(tags.begin(),tags.end(),unitTags.begin(),unitTags.end(),
|
||||||
|
std::inserter(intersect,intersect.begin()));
|
||||||
|
if(!intersect.empty()) return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//void UpgradeType::saveGame(XmlNode *rootNode) const {
|
//void UpgradeType::saveGame(XmlNode *rootNode) const {
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#include "conversion.h"
|
#include "conversion.h"
|
||||||
#include "xml_parser.h"
|
#include "xml_parser.h"
|
||||||
#include "leak_dumper.h"
|
#include "leak_dumper.h"
|
||||||
|
#include <set>
|
||||||
|
|
||||||
using Shared::Util::Checksum;
|
using Shared::Util::Checksum;
|
||||||
using namespace Shared::Util;
|
using namespace Shared::Util;
|
||||||
|
@ -266,9 +267,10 @@ public:
|
||||||
class UpgradeType: public UpgradeTypeBase, public ProducibleType {
|
class UpgradeType: public UpgradeTypeBase, public ProducibleType {
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* List of unit types (the "classes" of units, eg, swordman) that are affected by this upgrade.
|
* Set of unit types (the "classes" of units, eg, swordman) that are affected by this upgrade.
|
||||||
*/
|
*/
|
||||||
vector<const UnitType*> effects;
|
std::set<const UnitType*> effects;
|
||||||
|
std::set<string> tags;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
|
@ -301,17 +303,7 @@ public:
|
||||||
* appears in the XMLs.
|
* appears in the XMLs.
|
||||||
*/
|
*/
|
||||||
virtual string getName(bool translatedValue=false) const;
|
virtual string getName(bool translatedValue=false) const;
|
||||||
|
string getTagName(string tag, bool translatedValue=false) const;
|
||||||
/**
|
|
||||||
* Returns the number of UnitTypes affected by this upgrade.
|
|
||||||
*/
|
|
||||||
int getEffectCount() const {return (int)effects.size();}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a particular unit type affected by this upgrade.
|
|
||||||
* @param i Index of the unit type in the #effects list.
|
|
||||||
*/
|
|
||||||
const UnitType * getEffect(int i) const {return effects[i];}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines if a unit is affected by this upgrade.
|
* Determines if a unit is affected by this upgrade.
|
||||||
|
|
Loading…
Reference in New Issue