diff --git a/client/widgets/MiscWidgets.cpp b/client/widgets/MiscWidgets.cpp index 01c9a927b..5d0036b67 100644 --- a/client/widgets/MiscWidgets.cpp +++ b/client/widgets/MiscWidgets.cpp @@ -361,40 +361,35 @@ void MoraleLuckBox::set(const IBonusBearer *node) const int hoverTextBase[] = {7, 4}; const Bonus::BonusType bonusType[] = {Bonus::LUCK, Bonus::MORALE}; int (IBonusBearer::*getValue[])() const = {&IBonusBearer::LuckVal, &IBonusBearer::MoraleVal}; - - int mrlt = -9; - TModDescr mrl; + TBonusListPtr modifierList(new BonusList()); if (node) { - node->getModifiersWDescr(mrl, bonusType[morale]); + modifierList = node->getBonuses(Selector::type(bonusType[morale])); bonusValue = (node->*getValue[morale])(); } else bonusValue = 0; - mrlt = (bonusValue>0)-(bonusValue<0); //signum: -1 - bad luck / morale, 0 - neutral, 1 - good + int mrlt = (bonusValue>0)-(bonusValue<0); //signum: -1 - bad luck / morale, 0 - neutral, 1 - good hoverText = CGI->generaltexth->heroscrn[hoverTextBase[morale] - mrlt]; baseType = componentType[morale]; text = CGI->generaltexth->arraytxt[textId[morale]]; boost::algorithm::replace_first(text,"%s",CGI->generaltexth->arraytxt[neutralDescr[morale]-mrlt]); - if (!mrl.size()) - text += CGI->generaltexth->arraytxt[noneTxtId]; + + if (morale && node && (node->hasBonusOfType(Bonus::UNDEAD) + || node->hasBonusOfType(Bonus::BLOCK_MORALE) + || node->hasBonusOfType(Bonus::NON_LIVING))) + text += CGI->generaltexth->arraytxt[113]; //unaffected by morale + else if(modifierList->empty()) + text += CGI->generaltexth->arraytxt[noneTxtId];//no modifiers else { - //it's a creature window - if ((morale && node && node->hasBonusOfType(Bonus::UNDEAD)) || - node->hasBonusOfType(Bonus::BLOCK_MORALE) || node->hasBonusOfType(Bonus::NON_LIVING)) + for(const Bonus * elem : *modifierList) { - text += CGI->generaltexth->arraytxt[113]; //unaffected by morale - } - else - { - for(auto & elem : mrl) - { - if (elem.first) //no bonuses with value 0 - text += "\n" + elem.second; - } + if(elem->val != 0) + //no bonuses with value 0 + text += "\n" + elem->Description(); } } diff --git a/lib/HeroBonus.cpp b/lib/HeroBonus.cpp index 988cd92b8..c0a5c752c 100644 --- a/lib/HeroBonus.cpp +++ b/lib/HeroBonus.cpp @@ -211,21 +211,8 @@ Bonus * BonusList::getFirst(const CSelector &select) return nullptr; } -void BonusList::getModifiersWDescr(TModDescr &out) const -{ - for (auto & elem : bonuses) - { - Bonus *b = elem; - out.push_back(std::make_pair(b->val, b->Description())); - } -} - void BonusList::getBonuses(BonusList & out, const CSelector &selector) const { -// for(Bonus *i : *this) -// if(selector(i) && i->effectRange == Bonus::NO_LIMIT) -// out.push_back(i); - getBonuses(out, selector, nullptr); } @@ -359,17 +346,6 @@ bool IBonusBearer::hasBonusOfType(Bonus::BonusType type, int subtype /*= -1*/) c return hasBonus(s, cachingStr.str()); } -void IBonusBearer::getModifiersWDescr(TModDescr &out, Bonus::BonusType type, int subtype /*= -1 */) const -{ - std::stringstream cachingStr; - cachingStr << "type_" << type << "s_" << subtype; - getModifiersWDescr(out, subtype != -1 ? Selector::typeSubtype(type, subtype) : Selector::type(type), cachingStr.str()); -} - -void IBonusBearer::getModifiersWDescr(TModDescr &out, const CSelector &selector, const std::string &cachingStr /* =""*/) const -{ - getBonuses(selector, cachingStr)->getModifiersWDescr(out); -} int IBonusBearer::getBonusesCount(Bonus::BonusSource from, int id) const { std::stringstream cachingStr; @@ -1105,12 +1081,6 @@ bool NBonus::hasOfType(const CBonusSystemNode *obj, Bonus::BonusType type, int s return false; } -void NBonus::getModifiersWDescr(const CBonusSystemNode *obj, TModDescr &out, Bonus::BonusType type, int subtype /*= -1 */) -{ - if(obj) - return obj->getModifiersWDescr(out, type, subtype); -} - int NBonus::getCount(const CBonusSystemNode *obj, Bonus::BonusSource from, int id) { if(obj) @@ -1127,28 +1097,34 @@ const CSpell * Bonus::sourceSpell() const std::string Bonus::Description() const { - if(description.size()) - return description; - std::ostringstream str; - str << std::showpos << val << " "; - - switch(source) - { - case ARTIFACT: - str << VLC->arth->artifacts[sid]->Name(); - break;; - case SPELL_EFFECT: - str << SpellID(sid).toSpell()->name; - break; - case CREATURE_ABILITY: - str << VLC->creh->creatures[sid]->namePl; - break; - case SECONDARY_SKILL: - str << VLC->generaltexth->skillName[sid]/* << " secondary skill"*/; - break; - } - + + if(description.empty()) + switch(source) + { + case ARTIFACT: + str << VLC->arth->artifacts[sid]->Name(); + break;; + case SPELL_EFFECT: + str << SpellID(sid).toSpell()->name; + break; + case CREATURE_ABILITY: + str << VLC->creh->creatures[sid]->namePl; + break; + case SECONDARY_SKILL: + str << VLC->generaltexth->skillName[sid]/* << " secondary skill"*/; + break; + default: + //todo: handle all possible sources + str << "Unknown"; + break; + } + else + str << description; + + if(val != 0) + str << " " << std::showpos << val; + return str.str(); } diff --git a/lib/HeroBonus.h b/lib/HeroBonus.h index 5ab51af3e..a5eed502a 100644 --- a/lib/HeroBonus.h +++ b/lib/HeroBonus.h @@ -23,7 +23,6 @@ class BonusList; typedef shared_ptr TBonusListPtr; typedef shared_ptr TLimiterPtr; typedef shared_ptr TPropagatorPtr; -typedef std::vector > TModDescr; //modifiers values and their descriptions typedef std::set TNodes; typedef std::set TCNodes; typedef std::vector TNodesVector; @@ -448,7 +447,6 @@ public: int totalValue() const; //subtype -> subtype of bonus, if -1 then any void getBonuses(BonusList &out, const CSelector &selector, const CSelector &limit) const; void getAllBonuses(BonusList &out) const; - void getModifiersWDescr(TModDescr &out) const; void getBonuses(BonusList & out, const CSelector &selector) const; @@ -579,7 +577,6 @@ public: // * root is node on which call was made (nullptr will be replaced with this) //interface virtual const TBonusListPtr getAllBonuses(const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root = nullptr, const std::string &cachingStr = "") const = 0; - void getModifiersWDescr(TModDescr &out, const CSelector &selector, const std::string &cachingStr = "") const; //out: pairs int getBonusesCount(const CSelector &selector, const std::string &cachingStr = "") const; int valOfBonuses(const CSelector &selector, const std::string &cachingStr = "") const; bool hasBonus(const CSelector &selector, const std::string &cachingStr = "") const; @@ -594,7 +591,6 @@ public: int valOfBonuses(Bonus::BonusType type, int subtype = -1) const; //subtype -> subtype of bonus, if -1 then anyt; bool hasBonusOfType(Bonus::BonusType type, int subtype = -1) const;//determines if hero has a bonus of given type (and optionally subtype) bool hasBonusFrom(Bonus::BonusSource source, ui32 sourceID) const; - void getModifiersWDescr( TModDescr &out, Bonus::BonusType type, int subtype = -1 ) const; //out: pairs int getBonusesCount(Bonus::BonusSource from, int id) const; //various hlp functions for non-trivial values @@ -722,8 +718,6 @@ namespace NBonus //set of methods that may be safely called with nullptr objs DLL_LINKAGE int valOf(const CBonusSystemNode *obj, Bonus::BonusType type, int subtype = -1); //subtype -> subtype of bonus, if -1 then any DLL_LINKAGE bool hasOfType(const CBonusSystemNode *obj, Bonus::BonusType type, int subtype = -1);//determines if hero has a bonus of given type (and optionally subtype) - //DLL_LINKAGE const HeroBonus * get(const CBonusSystemNode *obj, int from, int id ); - DLL_LINKAGE void getModifiersWDescr(const CBonusSystemNode *obj, TModDescr &out, Bonus::BonusType type, int subtype = -1 ); //out: pairs DLL_LINKAGE int getCount(const CBonusSystemNode *obj, Bonus::BonusSource from, int id); } diff --git a/lib/mapObjects/CArmedInstance.cpp b/lib/mapObjects/CArmedInstance.cpp index c0d6ffdef..d6d879b7e 100644 --- a/lib/mapObjects/CArmedInstance.cpp +++ b/lib/mapObjects/CArmedInstance.cpp @@ -86,11 +86,13 @@ void CArmedInstance::updateMoraleBonusFromArmy() { b->val = +1; b->description = VLC->generaltexth->arraytxt[115]; //All troops of one alignment +1 + b->description = b->description.substr(0, b->description.size()-3);//trim "+1" } else if (!factions.empty()) // no bonus from empty garrison { b->val = 2 - factionsInArmy; b->description = boost::str(boost::format(VLC->generaltexth->arraytxt[114]) % factionsInArmy % b->val); //Troops of %d alignments %d + b->description = b->description.substr(0, b->description.size()-2);//trim value } boost::algorithm::trim(b->description); @@ -100,7 +102,11 @@ void CArmedInstance::updateMoraleBonusFromArmy() if(hasUndead) { if(!undeadModifier) - addNewBonus(new Bonus(Bonus::PERMANENT, Bonus::MORALE, Bonus::ARMY, -1, UNDEAD_MODIFIER_ID, VLC->generaltexth->arraytxt[116])); + { + undeadModifier = new Bonus(Bonus::PERMANENT, Bonus::MORALE, Bonus::ARMY, -1, UNDEAD_MODIFIER_ID, VLC->generaltexth->arraytxt[116]); + undeadModifier->description = undeadModifier->description.substr(0, undeadModifier->description.size()-2);//trim value + addNewBonus(undeadModifier); + } } else if(undeadModifier) removeBonus(undeadModifier); diff --git a/lib/mapObjects/CGTownInstance.cpp b/lib/mapObjects/CGTownInstance.cpp index ceed3fa55..b0a08a3a2 100644 --- a/lib/mapObjects/CGTownInstance.cpp +++ b/lib/mapObjects/CGTownInstance.cpp @@ -436,12 +436,12 @@ GrowthInfo CGTownInstance::getGrowthInfo(int level) const //other *-of-legion-like bonuses (%d to growth cumulative with grail) TBonusListPtr bonuses = getBonuses(Selector::type(Bonus::CREATURE_GROWTH).And(Selector::subtype(level))); for(const Bonus *b : *bonuses) - ret.entries.push_back(GrowthInfo::Entry(b->Description() + " %+d", b->val)); + ret.entries.push_back(GrowthInfo::Entry(b->val, b->Description())); //statue-of-legion-like bonus: % to base+castle TBonusListPtr bonuses2 = getBonuses(Selector::type(Bonus::CREATURE_GROWTH_PERCENT)); for(const Bonus *b : *bonuses2) - ret.entries.push_back(GrowthInfo::Entry(b->Description() + " %+d", b->val * (base + castleBonus) / 100)); + ret.entries.push_back(GrowthInfo::Entry(b->val * (base + castleBonus) / 100, b->Description())); if(hasBuilt(BuildingID::GRAIL)) //grail - +50% to ALL (so far added) growth ret.entries.push_back(GrowthInfo::Entry(subID, BuildingID::GRAIL, ret.totalGrowth() / 2)); @@ -1244,6 +1244,12 @@ GrowthInfo::Entry::Entry(int subID, BuildingID building, int _count) description = boost::str(boost::format("%s %+d") % VLC->townh->factions[subID]->town->buildings.at(building)->Name() % count); } +GrowthInfo::Entry::Entry(int _count, const std::string &fullDescription) + : count(_count) +{ + description = fullDescription; +} + CTownAndVisitingHero::CTownAndVisitingHero() { setNodeType(TOWN_AND_VISITOR); diff --git a/lib/mapObjects/CGTownInstance.h b/lib/mapObjects/CGTownInstance.h index 74e28dd9a..e7b7cd28e 100644 --- a/lib/mapObjects/CGTownInstance.h +++ b/lib/mapObjects/CGTownInstance.h @@ -130,6 +130,7 @@ struct DLL_LINKAGE GrowthInfo std::string description; Entry(const std::string &format, int _count); Entry(int subID, BuildingID building, int _count); + Entry(int _count, const std::string &fullDescription); }; std::vector entries;