diff --git a/lib/HeroBonus.cpp b/lib/HeroBonus.cpp index 70af0144f..99e432f73 100644 --- a/lib/HeroBonus.cpp +++ b/lib/HeroBonus.cpp @@ -1543,3 +1543,20 @@ void LimiterList::add( TLimiterPtr limiter ) { limiters.push_back(limiter); } + +void ScalingUpdater::update(BonusUpdateContext & context) +{ + if(context.node.getNodeType() == CBonusSystemNode::HERO) + { + int level = static_cast(context.node).level; + int steps = stepSize ? level / stepSize : level; + //rounding follows format for HMM3 creature specialty bonus + context.b->val = (valPer20 * steps + 19) / 20; + } +} + +std::shared_ptr Bonus::addUpdater(TUpdaterPtr Updater) +{ + updater = Updater; + return this->shared_from_this(); +} diff --git a/lib/HeroBonus.h b/lib/HeroBonus.h index 9446f1e13..ac5ecfcc4 100644 --- a/lib/HeroBonus.h +++ b/lib/HeroBonus.h @@ -17,11 +17,13 @@ class IBonusBearer; class CBonusSystemNode; class ILimiter; class IPropagator; +class IUpdater; class BonusList; typedef std::shared_ptr TBonusListPtr; typedef std::shared_ptr TLimiterPtr; typedef std::shared_ptr TPropagatorPtr; +typedef std::shared_ptr TUpdaterPtr; typedef std::set TNodes; typedef std::set TCNodes; typedef std::vector TNodesVector; @@ -340,6 +342,7 @@ struct DLL_LINKAGE Bonus : public std::enable_shared_from_this TLimiterPtr limiter; TPropagatorPtr propagator; + TUpdaterPtr updater; std::string description; @@ -422,6 +425,7 @@ struct DLL_LINKAGE Bonus : public std::enable_shared_from_this std::shared_ptr addLimiter(TLimiterPtr Limiter); //returns this for convenient chain-calls std::shared_ptr addPropagator(TPropagatorPtr Propagator); //returns this for convenient chain-calls + std::shared_ptr addUpdater(TUpdaterPtr Updater); //returns this for convenient chain-calls }; DLL_LINKAGE std::ostream & operator<<(std::ostream &out, const Bonus &bonus); @@ -1006,3 +1010,36 @@ void BonusList::insert(const int position, InputIterator first, InputIterator la bonuses.insert(bonuses.begin() + position, first, last); changed(); } + +// bonus decorators for updating bonuses based on events (e.g. hero gaining level) + +struct BonusUpdateContext +{ + std::shared_ptr b; + const CBonusSystemNode & node; +}; + +class DLL_LINKAGE IUpdater +{ +public: + virtual void update(BonusUpdateContext & context) const = 0; + + template void serialize(Handler &h, const int version) + { + } +}; + +struct DLL_LINKAGE ScalingUpdater : public IUpdater +{ + int valPer20 = 0; + int stepSize = 1; + + template void serialize(Handler &h, const int version) + { + IUpdater::serialize(h, version); + h & valPer20; + h & stepSize; + } + + void update(BonusUpdateContext & context); +};