From 00f51e0f9894b27aa3edde40f8e71d79a199cd14 Mon Sep 17 00:00:00 2001 From: Henning Koehler Date: Sat, 16 Sep 2017 12:26:48 +1200 Subject: [PATCH] Updaters replace bonuses during inheritance --- lib/HeroBonus.cpp | 55 +++++++++++++------------------ lib/HeroBonus.h | 8 ++--- lib/mapObjects/CGHeroInstance.cpp | 5 ++- 3 files changed, 28 insertions(+), 40 deletions(-) diff --git a/lib/HeroBonus.cpp b/lib/HeroBonus.cpp index 410158d9a..327055d3a 100644 --- a/lib/HeroBonus.cpp +++ b/lib/HeroBonus.cpp @@ -319,17 +319,6 @@ void BonusList::eliminateDuplicates() bonuses.erase( unique( bonuses.begin(), bonuses.end() ), bonuses.end() ); } -bool BonusList::updateBonuses(const CBonusSystemNode & context) -{ - bool updated = false; - for(std::shared_ptr b : *this) - { - if(b->updater) - updated = b->updater->update(*b, context) || updated; - } - return updated; -} - void BonusList::push_back(std::shared_ptr x) { bonuses.push_back(x); @@ -591,22 +580,28 @@ void CBonusSystemNode::getParents(TNodes &out) void CBonusSystemNode::getBonusesRec(BonusList &out, const CSelector &selector, const CSelector &limit) const { + BonusList beforeUpdate; FOREACH_CPARENT(p) { - p->getBonusesRec(out, selector, limit); + p->getBonusesRec(beforeUpdate, selector, limit); } + bonuses.getBonuses(beforeUpdate, selector, limit); - bonuses.getBonuses(out, selector, limit); + for(auto b : beforeUpdate) + out.push_back(update(b)); } void CBonusSystemNode::getAllBonusesRec(BonusList &out) const { + BonusList beforeUpdate; FOREACH_CPARENT(p) { - p->getAllBonusesRec(out); + p->getAllBonusesRec(beforeUpdate); } + bonuses.getAllBonuses(beforeUpdate); - bonuses.getAllBonuses(out); + for(auto b : beforeUpdate) + out.push_back(update(b)); } const TBonusListPtr CBonusSystemNode::getAllBonuses(const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root, const std::string &cachingStr) const @@ -698,6 +693,13 @@ const TBonusListPtr CBonusSystemNode::getAllBonusesWithoutCaching(const CSelecto return ret; } +const std::shared_ptr CBonusSystemNode::update(const std::shared_ptr b) const +{ + if(b->updater) + return b->updater->update(b, *this); + return b; +} + CBonusSystemNode::CBonusSystemNode() : bonuses(true), exportedBonuses(true), @@ -809,14 +811,6 @@ void CBonusSystemNode::reduceBonusDurations(const CSelector &s) child->reduceBonusDurations(s); } -void CBonusSystemNode::updateBonuses() -{ - bool updated = bonuses.updateBonuses(*this); - updated = exportedBonuses.updateBonuses(*this) || updated; - if(updated) - treeHasChanged(); -} - void CBonusSystemNode::addNewBonus(const std::shared_ptr& b) { //turnsRemain shouldn't be zero for following durations @@ -828,8 +822,6 @@ void CBonusSystemNode::addNewBonus(const std::shared_ptr& b) assert(!vstd::contains(exportedBonuses, b)); exportedBonuses.push_back(b); exportBonus(b); - if(b->updater) - b->updater->update(*b, *this); CBonusSystemNode::treeHasChanged(); } @@ -1707,7 +1699,7 @@ ScalingUpdater::ScalingUpdater(int valPer20, int stepSize) : valPer20(valPer20), { } -bool ScalingUpdater::update(Bonus & b, const CBonusSystemNode & context) const +const std::shared_ptr ScalingUpdater::update(const std::shared_ptr b, const CBonusSystemNode & context) const { if(context.getNodeType() == CBonusSystemNode::HERO) { @@ -1715,13 +1707,12 @@ bool ScalingUpdater::update(Bonus & b, const CBonusSystemNode & context) const int steps = stepSize ? level / stepSize : level; //rounding follows format for HMM3 creature specialty bonus int newVal = (valPer20 * steps + 19) / 20; - if(b.val != newVal) - { - b.val = newVal; - return true; - } + //return copy of bonus with updated val + std::shared_ptr newBonus = std::make_shared(*b); + newBonus->val = newVal; + return newBonus; } - return false; + return b; } std::string ScalingUpdater::toString() const diff --git a/lib/HeroBonus.h b/lib/HeroBonus.h index 7dafcc670..1a981d078 100644 --- a/lib/HeroBonus.h +++ b/lib/HeroBonus.h @@ -490,7 +490,6 @@ public: int valOfBonuses(const CSelector &select) const; void eliminateDuplicates(); - bool updateBonuses(const CBonusSystemNode & node); // remove_if implementation for STL vector types template @@ -675,6 +674,7 @@ private: void getBonusesRec(BonusList &out, const CSelector &selector, const CSelector &limit) const; void getAllBonusesRec(BonusList &out) const; const TBonusListPtr getAllBonusesWithoutCaching(const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root = nullptr) const; + const std::shared_ptr update(const std::shared_ptr b) const; public: explicit CBonusSystemNode(); @@ -716,8 +716,6 @@ public: void popBonuses(const CSelector &s); ///updates count of remaining turns and removes outdated bonuses by selector void reduceBonusDurations(const CSelector &s); - //run updaters attached to bonuses - void updateBonuses(); virtual std::string bonusToString(const std::shared_ptr& bonus, bool description) const {return "";}; //description or bonus name virtual std::string nodeName() const; @@ -1030,7 +1028,7 @@ class DLL_LINKAGE IUpdater public: virtual ~IUpdater(); - virtual bool update(Bonus & b, const CBonusSystemNode & context) const = 0; + virtual const std::shared_ptr update(const std::shared_ptr b, const CBonusSystemNode & context) const = 0; virtual std::string toString() const; virtual JsonNode toJsonNode() const = 0; @@ -1055,7 +1053,7 @@ public: h & stepSize; } - bool update(Bonus & b, const CBonusSystemNode & context) const override; + const std::shared_ptr update(const std::shared_ptr b, const CBonusSystemNode & context) const override; virtual std::string toString() const override; virtual JsonNode toJsonNode() const override; }; diff --git a/lib/mapObjects/CGHeroInstance.cpp b/lib/mapObjects/CGHeroInstance.cpp index 2733f0d09..e64f8d0ff 100644 --- a/lib/mapObjects/CGHeroInstance.cpp +++ b/lib/mapObjects/CGHeroInstance.cpp @@ -524,7 +524,6 @@ void CGHeroInstance::initObj(CRandomGenerator & rand) //initialize bonuses recreateSecondarySkillsBonuses(); - updateBonuses(); mana = manaLimit(); //after all bonuses are taken into account, make sure this line is the last one type->name = name; @@ -1255,8 +1254,8 @@ void CGHeroInstance::levelUp(std::vector skills) } } - //specialty and other bonuses that scale with level - updateBonuses(); + //update specialty and other bonuses that scale with level + treeHasChanged(); } void CGHeroInstance::levelUpAutomatically(CRandomGenerator & rand)