|
|
@@ -26,9 +26,7 @@
|
|
|
#include "battle/BattleInfo.h"
|
|
|
|
|
|
#define FOREACH_PARENT(pname) TNodes lparents; getParents(lparents); for(CBonusSystemNode *pname : lparents)
|
|
|
-#define FOREACH_CPARENT(pname) TCNodes lparents; getParents(lparents); for(const CBonusSystemNode *pname : lparents)
|
|
|
#define FOREACH_RED_CHILD(pname) TNodes lchildren; getRedChildren(lchildren); for(CBonusSystemNode *pname : lchildren)
|
|
|
-#define FOREACH_RED_PARENT(pname) TNodes lparents; getRedParents(lparents); for(CBonusSystemNode *pname : lparents)
|
|
|
|
|
|
#define BONUS_NAME(x) { #x, Bonus::x },
|
|
|
const std::map<std::string, Bonus::BonusType> bonusNameMap = { BONUS_LIST };
|
|
|
@@ -73,7 +71,8 @@ const std::map<std::string, TLimiterPtr> bonusLimiterMap =
|
|
|
{"DRAGON_NATURE", std::make_shared<HasAnotherBonusLimiter>(Bonus::DRAGON_NATURE)},
|
|
|
{"IS_UNDEAD", std::make_shared<HasAnotherBonusLimiter>(Bonus::UNDEAD)},
|
|
|
{"CREATURE_NATIVE_TERRAIN", std::make_shared<CreatureTerrainLimiter>()},
|
|
|
- {"CREATURE_FACTION", std::make_shared<CreatureFactionLimiter>()}
|
|
|
+ {"CREATURE_FACTION", std::make_shared<CreatureFactionLimiter>()},
|
|
|
+ {"OPPOSITE_SIDE", std::make_shared<OppositeSideLimiter>()}
|
|
|
};
|
|
|
|
|
|
const std::map<std::string, TPropagatorPtr> bonusPropagatorMap =
|
|
|
@@ -452,7 +451,6 @@ int BonusList::totalValue() const
|
|
|
{
|
|
|
vstd::amax(indepMax, b->val);
|
|
|
}
|
|
|
-
|
|
|
break;
|
|
|
case Bonus::INDEPENDENT_MIN:
|
|
|
if (!hasIndepMin)
|
|
|
@@ -464,7 +462,6 @@ int BonusList::totalValue() const
|
|
|
{
|
|
|
vstd::amin(indepMin, b->val);
|
|
|
}
|
|
|
-
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
@@ -528,7 +525,8 @@ void BonusList::getBonuses(BonusList & out, const CSelector &selector, const CSe
|
|
|
for (auto & b : bonuses)
|
|
|
{
|
|
|
//add matching bonuses that matches limit predicate or have NO_LIMIT if no given predicate
|
|
|
- if(selector(b.get()) && ((!limit && b->effectRange == Bonus::NO_LIMIT) || ((bool)limit && limit(b.get()))))
|
|
|
+ auto noFightLimit = b->effectRange == Bonus::NO_LIMIT || b->effectRange == Bonus::ONLY_ENEMY_ARMY;
|
|
|
+ if(selector(b.get()) && ((!limit && noFightLimit) || ((bool)limit && limit(b.get()))))
|
|
|
out.push_back(b);
|
|
|
}
|
|
|
}
|
|
|
@@ -595,11 +593,12 @@ void BonusList::insert(BonusList::TInternalContainer::iterator position, BonusLi
|
|
|
changed();
|
|
|
}
|
|
|
|
|
|
-CSelector IBonusBearer::anaffectedByMoraleSelector
|
|
|
- = Selector::type()(Bonus::NON_LIVING)
|
|
|
- .Or(Selector::type()(Bonus::UNDEAD))
|
|
|
- .Or(Selector::type()(Bonus::NO_MORALE))
|
|
|
- .Or(Selector::type()(Bonus::SIEGE_WEAPON));
|
|
|
+CSelector IBonusBearer::anaffectedByMoraleSelector =
|
|
|
+Selector::type()(Bonus::NON_LIVING)
|
|
|
+.Or(Selector::type()(Bonus::UNDEAD))
|
|
|
+.Or(Selector::type()(Bonus::SIEGE_WEAPON))
|
|
|
+.Or(Selector::type()(Bonus::NO_MORALE))
|
|
|
+.Or(Selector::type()(Bonus::BLOCK_MORALE));
|
|
|
|
|
|
CSelector IBonusBearer::moraleSelector = Selector::type()(Bonus::MORALE);
|
|
|
CSelector IBonusBearer::luckSelector = Selector::type()(Bonus::LUCK);
|
|
|
@@ -789,6 +788,8 @@ int IBonusBearer::getPrimSkillLevel(PrimarySkill::PrimarySkill id) const
|
|
|
static const std::string keyAllSkills = "type_PRIMARY_SKILL";
|
|
|
auto allSkills = getBonuses(selectorAllSkills, keyAllSkills);
|
|
|
auto ret = allSkills->valOfBonuses(Selector::subtype()(id));
|
|
|
+ auto minSkillValue = (id == PrimarySkill::SPELL_POWER || id == PrimarySkill::KNOWLEDGE) ? 1 : 0;
|
|
|
+ vstd::amax(ret, minSkillValue); //otherwise, some artifacts may cause negative skill value effect
|
|
|
return ret; //sp=0 works in old saves
|
|
|
}
|
|
|
|
|
|
@@ -830,7 +831,36 @@ std::shared_ptr<const Bonus> IBonusBearer::getBonus(const CSelector &selector) c
|
|
|
return bonuses->getFirst(Selector::all);
|
|
|
}
|
|
|
|
|
|
-std::shared_ptr<Bonus> CBonusSystemNode::getBonusLocalFirst(const CSelector &selector)
|
|
|
+const CStack * retrieveStackBattle(const CBonusSystemNode * node)
|
|
|
+{
|
|
|
+ switch(node->getNodeType())
|
|
|
+ {
|
|
|
+ case CBonusSystemNode::STACK_BATTLE:
|
|
|
+ return static_cast<const CStack*>(node);
|
|
|
+ default:
|
|
|
+ return nullptr;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+const CStackInstance * retrieveStackInstance(const CBonusSystemNode * node)
|
|
|
+{
|
|
|
+ switch(node->getNodeType())
|
|
|
+ {
|
|
|
+ case CBonusSystemNode::STACK_INSTANCE:
|
|
|
+ return (static_cast<const CStackInstance *>(node));
|
|
|
+ case CBonusSystemNode::STACK_BATTLE:
|
|
|
+ return (static_cast<const CStack*>(node))->base;
|
|
|
+ default:
|
|
|
+ return nullptr;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+PlayerColor CBonusSystemNode::retrieveNodeOwner(const CBonusSystemNode * node)
|
|
|
+{
|
|
|
+ return node ? node->getOwner() : PlayerColor::CANNOT_DETERMINE;
|
|
|
+}
|
|
|
+
|
|
|
+std::shared_ptr<Bonus> CBonusSystemNode::getBonusLocalFirst(const CSelector & selector)
|
|
|
{
|
|
|
auto ret = bonuses.getFirst(selector);
|
|
|
if(ret)
|
|
|
@@ -846,7 +876,7 @@ std::shared_ptr<Bonus> CBonusSystemNode::getBonusLocalFirst(const CSelector &sel
|
|
|
return nullptr;
|
|
|
}
|
|
|
|
|
|
-std::shared_ptr<const Bonus> CBonusSystemNode::getBonusLocalFirst( const CSelector &selector ) const
|
|
|
+std::shared_ptr<const Bonus> CBonusSystemNode::getBonusLocalFirst(const CSelector & selector) const
|
|
|
{
|
|
|
return (const_cast<CBonusSystemNode*>(this))->getBonusLocalFirst(selector);
|
|
|
}
|
|
|
@@ -869,30 +899,33 @@ void CBonusSystemNode::getParents(TNodes &out)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-void CBonusSystemNode::getBonusesRec(BonusList &out, const CSelector &selector, const CSelector &limit) const
|
|
|
+void CBonusSystemNode::getAllParents(TCNodes & out) const //retrieves list of parent nodes (nodes to inherit bonuses from)
|
|
|
{
|
|
|
- BonusList beforeUpdate;
|
|
|
- FOREACH_CPARENT(p)
|
|
|
+ for(auto parent : parents)
|
|
|
{
|
|
|
- p->getBonusesRec(beforeUpdate, selector, limit);
|
|
|
+ out.insert(parent);
|
|
|
+ parent->getAllParents(out);
|
|
|
}
|
|
|
- bonuses.getBonuses(beforeUpdate, selector, limit);
|
|
|
-
|
|
|
- for(auto b : beforeUpdate)
|
|
|
- out.push_back(update(b));
|
|
|
}
|
|
|
|
|
|
void CBonusSystemNode::getAllBonusesRec(BonusList &out) const
|
|
|
{
|
|
|
BonusList beforeUpdate;
|
|
|
- FOREACH_CPARENT(p)
|
|
|
- {
|
|
|
- p->getAllBonusesRec(beforeUpdate);
|
|
|
- }
|
|
|
+ TCNodes lparents;
|
|
|
+ getAllParents(lparents);
|
|
|
+
|
|
|
+ for(auto parent : lparents)
|
|
|
+ parent->bonuses.getAllBonuses(beforeUpdate);
|
|
|
+
|
|
|
bonuses.getAllBonuses(beforeUpdate);
|
|
|
|
|
|
for(auto b : beforeUpdate)
|
|
|
- out.push_back(update(b));
|
|
|
+ {
|
|
|
+ auto updated = b->updater
|
|
|
+ ? getUpdatedBonus(b, b->updater)
|
|
|
+ : b;
|
|
|
+ out.push_back(updated);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
TConstBonusListPtr CBonusSystemNode::getAllBonuses(const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root, const std::string &cachingStr) const
|
|
|
@@ -981,11 +1014,10 @@ TConstBonusListPtr CBonusSystemNode::getAllBonusesWithoutCaching(const CSelector
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
-std::shared_ptr<Bonus> CBonusSystemNode::update(const std::shared_ptr<Bonus> & b) const
|
|
|
+std::shared_ptr<Bonus> CBonusSystemNode::getUpdatedBonus(const std::shared_ptr<Bonus> & b, const TUpdaterPtr updater) const
|
|
|
{
|
|
|
- if(b->updater)
|
|
|
- return b->updater->update(b, *this);
|
|
|
- return b;
|
|
|
+ assert(updater);
|
|
|
+ return updater->createUpdatedBonus(b, * this);
|
|
|
}
|
|
|
|
|
|
CBonusSystemNode::CBonusSystemNode()
|
|
|
@@ -1089,13 +1121,20 @@ void CBonusSystemNode::detachFrom(CBonusSystemNode *parent)
|
|
|
removedRedDescendant(parent);
|
|
|
}
|
|
|
|
|
|
- parents -= parent;
|
|
|
+ if (vstd::contains(parents, parent))
|
|
|
+ {
|
|
|
+ parents -= parent;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ logBonus->error("Error on Detach. Node %s (nodeType=%d) has not parent %s (nodeType=%d)"
|
|
|
+ , nodeShortInfo(), nodeType, parent->nodeShortInfo(), parent->nodeType);
|
|
|
+ }
|
|
|
|
|
|
if(!isHypothetic())
|
|
|
{
|
|
|
parent->childDetached(this);
|
|
|
}
|
|
|
-
|
|
|
CBonusSystemNode::treeHasChanged();
|
|
|
}
|
|
|
|
|
|
@@ -1175,16 +1214,19 @@ bool CBonusSystemNode::actsAsBonusSourceOnly() const
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-void CBonusSystemNode::propagateBonus(std::shared_ptr<Bonus> b)
|
|
|
+void CBonusSystemNode::propagateBonus(std::shared_ptr<Bonus> b, const CBonusSystemNode & source)
|
|
|
{
|
|
|
if(b->propagator->shouldBeAttached(this))
|
|
|
{
|
|
|
- bonuses.push_back(b);
|
|
|
- logBonus->trace("#$# %s #propagated to# %s", b->Description(), nodeName());
|
|
|
+ auto propagated = b->propagationUpdater
|
|
|
+ ? source.getUpdatedBonus(b, b->propagationUpdater)
|
|
|
+ : b;
|
|
|
+ bonuses.push_back(propagated);
|
|
|
+ logBonus->trace("#$# %s #propagated to# %s", propagated->Description(), nodeName());
|
|
|
}
|
|
|
|
|
|
FOREACH_RED_CHILD(child)
|
|
|
- child->propagateBonus(b);
|
|
|
+ child->propagateBonus(b, source);
|
|
|
}
|
|
|
|
|
|
void CBonusSystemNode::unpropagateBonus(std::shared_ptr<Bonus> b)
|
|
|
@@ -1207,12 +1249,12 @@ void CBonusSystemNode::newChildAttached(CBonusSystemNode *child)
|
|
|
|
|
|
void CBonusSystemNode::childDetached(CBonusSystemNode *child)
|
|
|
{
|
|
|
- if (vstd::contains(children, child))
|
|
|
+ if(vstd::contains(children, child))
|
|
|
children -= child;
|
|
|
else
|
|
|
{
|
|
|
- logBonus->error("Error! %s #cannot be detached from# %s", child->nodeName(), nodeName());
|
|
|
- throw std::runtime_error("internal error");
|
|
|
+ logBonus->error("Error on Detach. Node %s (nodeType=%d) is not a child of %s (nodeType=%d)"
|
|
|
+ , child->nodeShortInfo(), child->nodeType, nodeShortInfo(), nodeType);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -1234,13 +1276,23 @@ std::string CBonusSystemNode::nodeName() const
|
|
|
: std::string("Bonus system node of type ") + typeid(*this).name();
|
|
|
}
|
|
|
|
|
|
+std::string CBonusSystemNode::nodeShortInfo() const
|
|
|
+{
|
|
|
+ std::ostringstream str;
|
|
|
+ str << "'" << typeid(* this).name() << "'";
|
|
|
+ description.length() > 0
|
|
|
+ ? str << " (" << description << ")"
|
|
|
+ : str << " (no description)";
|
|
|
+ return str.str();
|
|
|
+}
|
|
|
+
|
|
|
void CBonusSystemNode::deserializationFix()
|
|
|
{
|
|
|
exportBonuses();
|
|
|
|
|
|
}
|
|
|
|
|
|
-void CBonusSystemNode::getRedParents(TNodes &out)
|
|
|
+void CBonusSystemNode::getRedParents(TNodes & out)
|
|
|
{
|
|
|
FOREACH_PARENT(pname)
|
|
|
{
|
|
|
@@ -1278,14 +1330,24 @@ void CBonusSystemNode::getRedChildren(TNodes &out)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-void CBonusSystemNode::newRedDescendant(CBonusSystemNode *descendant)
|
|
|
+void CBonusSystemNode::newRedDescendant(CBonusSystemNode * descendant)
|
|
|
{
|
|
|
for(auto b : exportedBonuses)
|
|
|
+ {
|
|
|
if(b->propagator)
|
|
|
- descendant->propagateBonus(b);
|
|
|
+ descendant->propagateBonus(b, *this);
|
|
|
+ }
|
|
|
+ TNodes redParents;
|
|
|
+ getRedAncestors(redParents); //get all red parents recursively
|
|
|
|
|
|
- FOREACH_RED_PARENT(parent)
|
|
|
- parent->newRedDescendant(descendant);
|
|
|
+ for(auto parent : redParents)
|
|
|
+ {
|
|
|
+ for(auto b : parent->exportedBonuses)
|
|
|
+ {
|
|
|
+ if(b->propagator)
|
|
|
+ descendant->propagateBonus(b, *this);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
void CBonusSystemNode::removedRedDescendant(CBonusSystemNode *descendant)
|
|
|
@@ -1294,15 +1356,26 @@ void CBonusSystemNode::removedRedDescendant(CBonusSystemNode *descendant)
|
|
|
if(b->propagator)
|
|
|
descendant->unpropagateBonus(b);
|
|
|
|
|
|
- FOREACH_RED_PARENT(parent)
|
|
|
- parent->removedRedDescendant(descendant);
|
|
|
+ TNodes redParents;
|
|
|
+ getRedAncestors(redParents); //get all red parents recursively
|
|
|
+
|
|
|
+ for(auto parent : redParents)
|
|
|
+ {
|
|
|
+ for(auto b : parent->exportedBonuses)
|
|
|
+ if(b->propagator)
|
|
|
+ descendant->unpropagateBonus(b);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
void CBonusSystemNode::getRedAncestors(TNodes &out)
|
|
|
{
|
|
|
getRedParents(out);
|
|
|
- FOREACH_RED_PARENT(p)
|
|
|
- p->getRedAncestors(out);
|
|
|
+
|
|
|
+ TNodes redParents;
|
|
|
+ getRedParents(redParents);
|
|
|
+
|
|
|
+ for(CBonusSystemNode * parent : redParents)
|
|
|
+ parent->getRedAncestors(out);
|
|
|
}
|
|
|
|
|
|
void CBonusSystemNode::getRedDescendants(TNodes &out)
|
|
|
@@ -1315,7 +1388,7 @@ void CBonusSystemNode::getRedDescendants(TNodes &out)
|
|
|
void CBonusSystemNode::exportBonus(std::shared_ptr<Bonus> b)
|
|
|
{
|
|
|
if(b->propagator)
|
|
|
- propagateBonus(b);
|
|
|
+ propagateBonus(b, *this);
|
|
|
else
|
|
|
bonuses.push_back(b);
|
|
|
|
|
|
@@ -1736,30 +1809,6 @@ namespace Selector
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-const CStack * retrieveStackBattle(const CBonusSystemNode * node)
|
|
|
-{
|
|
|
- switch(node->getNodeType())
|
|
|
- {
|
|
|
- case CBonusSystemNode::STACK_BATTLE:
|
|
|
- return static_cast<const CStack*>(node);
|
|
|
- default:
|
|
|
- return nullptr;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-const CStackInstance * retrieveStackInstance(const CBonusSystemNode * node)
|
|
|
-{
|
|
|
- switch(node->getNodeType())
|
|
|
- {
|
|
|
- case CBonusSystemNode::STACK_INSTANCE:
|
|
|
- return (static_cast<const CStackInstance *>(node));
|
|
|
- case CBonusSystemNode::STACK_BATTLE:
|
|
|
- return (static_cast<const CStack*>(node))->base;
|
|
|
- default:
|
|
|
- return nullptr;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
const CCreature * retrieveCreature(const CBonusSystemNode *node)
|
|
|
{
|
|
|
switch(node->getNodeType())
|
|
|
@@ -2161,6 +2210,23 @@ StackOwnerLimiter::StackOwnerLimiter(PlayerColor Owner)
|
|
|
{
|
|
|
}
|
|
|
|
|
|
+OppositeSideLimiter::OppositeSideLimiter()
|
|
|
+ : owner(PlayerColor::CANNOT_DETERMINE)
|
|
|
+{
|
|
|
+}
|
|
|
+
|
|
|
+OppositeSideLimiter::OppositeSideLimiter(PlayerColor Owner)
|
|
|
+ : owner(Owner)
|
|
|
+{
|
|
|
+}
|
|
|
+
|
|
|
+int OppositeSideLimiter::limit(const BonusLimitationContext & context) const
|
|
|
+{
|
|
|
+ auto contextOwner = CBonusSystemNode::retrieveNodeOwner(& context.node);
|
|
|
+ auto decision = (owner == contextOwner || owner == PlayerColor::CANNOT_DETERMINE) ? ILimiter::DISCARD : ILimiter::ACCEPT;
|
|
|
+ return decision;
|
|
|
+}
|
|
|
+
|
|
|
// Aggregate/Boolean Limiters
|
|
|
|
|
|
void AggregateLimiter::add(TLimiterPtr limiter)
|
|
|
@@ -2252,11 +2318,45 @@ std::shared_ptr<Bonus> Bonus::addUpdater(TUpdaterPtr Updater)
|
|
|
return this->shared_from_this();
|
|
|
}
|
|
|
|
|
|
+// Update ONLY_ENEMY_ARMY bonuses from old saves to make them workable.
|
|
|
+// Also, we should foreseen possible errors in bonus configuration and fix them.
|
|
|
+void Bonus::updateOppositeBonuses()
|
|
|
+{
|
|
|
+ if(effectRange != Bonus::ONLY_ENEMY_ARMY)
|
|
|
+ return;
|
|
|
+
|
|
|
+ if(propagator)
|
|
|
+ {
|
|
|
+ if(propagator->getPropagatorType() != CBonusSystemNode::BATTLE)
|
|
|
+ {
|
|
|
+ logMod->error("Wrong Propagator will be ignored: The 'ONLY_ENEMY_ARMY' effectRange is only compatible with the 'BATTLE_WIDE' propagator.");
|
|
|
+ propagator.reset(new CPropagatorNodeType(CBonusSystemNode::BATTLE));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ propagator = std::make_shared<CPropagatorNodeType>(CBonusSystemNode::BATTLE);
|
|
|
+ }
|
|
|
+ if(limiter)
|
|
|
+ {
|
|
|
+ if(!dynamic_cast<OppositeSideLimiter*>(limiter.get()))
|
|
|
+ {
|
|
|
+ logMod->error("Wrong Limiter will be ignored: The 'ONLY_ENEMY_ARMY' effectRange is only compatible with the 'OPPOSITE_SIDE' limiter.");
|
|
|
+ limiter.reset(new OppositeSideLimiter());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ limiter = std::make_shared<OppositeSideLimiter>();
|
|
|
+ }
|
|
|
+ propagationUpdater = std::make_shared<OwnerUpdater>();
|
|
|
+}
|
|
|
+
|
|
|
IUpdater::~IUpdater()
|
|
|
{
|
|
|
}
|
|
|
|
|
|
-std::shared_ptr<Bonus> IUpdater::update(const std::shared_ptr<Bonus> & b, const CBonusSystemNode & context) const
|
|
|
+std::shared_ptr<Bonus> IUpdater::createUpdatedBonus(const std::shared_ptr<Bonus> & b, const CBonusSystemNode & context) const
|
|
|
{
|
|
|
return b;
|
|
|
}
|
|
|
@@ -2279,7 +2379,7 @@ GrowsWithLevelUpdater::GrowsWithLevelUpdater(int valPer20, int stepSize) : valPe
|
|
|
{
|
|
|
}
|
|
|
|
|
|
-std::shared_ptr<Bonus> GrowsWithLevelUpdater::update(const std::shared_ptr<Bonus> & b, const CBonusSystemNode & context) const
|
|
|
+std::shared_ptr<Bonus> GrowsWithLevelUpdater::createUpdatedBonus(const std::shared_ptr<Bonus> & b, const CBonusSystemNode & context) const
|
|
|
{
|
|
|
if(context.getNodeType() == CBonusSystemNode::HERO)
|
|
|
{
|
|
|
@@ -2316,7 +2416,7 @@ TimesHeroLevelUpdater::TimesHeroLevelUpdater()
|
|
|
{
|
|
|
}
|
|
|
|
|
|
-std::shared_ptr<Bonus> TimesHeroLevelUpdater::update(const std::shared_ptr<Bonus> & b, const CBonusSystemNode & context) const
|
|
|
+std::shared_ptr<Bonus> TimesHeroLevelUpdater::createUpdatedBonus(const std::shared_ptr<Bonus> & b, const CBonusSystemNode & context) const
|
|
|
{
|
|
|
if(context.getNodeType() == CBonusSystemNode::HERO)
|
|
|
{
|
|
|
@@ -2342,7 +2442,7 @@ TimesStackLevelUpdater::TimesStackLevelUpdater()
|
|
|
{
|
|
|
}
|
|
|
|
|
|
-std::shared_ptr<Bonus> TimesStackLevelUpdater::update(const std::shared_ptr<Bonus> & b, const CBonusSystemNode & context) const
|
|
|
+std::shared_ptr<Bonus> TimesStackLevelUpdater::createUpdatedBonus(const std::shared_ptr<Bonus> & b, const CBonusSystemNode & context) const
|
|
|
{
|
|
|
if(context.getNodeType() == CBonusSystemNode::STACK_INSTANCE)
|
|
|
{
|
|
|
@@ -2376,3 +2476,30 @@ JsonNode TimesStackLevelUpdater::toJsonNode() const
|
|
|
{
|
|
|
return JsonUtils::stringNode("TIMES_STACK_LEVEL");
|
|
|
}
|
|
|
+
|
|
|
+OwnerUpdater::OwnerUpdater()
|
|
|
+{
|
|
|
+}
|
|
|
+
|
|
|
+std::string OwnerUpdater::toString() const
|
|
|
+{
|
|
|
+ return "OwnerUpdater";
|
|
|
+}
|
|
|
+
|
|
|
+JsonNode OwnerUpdater::toJsonNode() const
|
|
|
+{
|
|
|
+ return JsonUtils::stringNode("BONUS_OWNER_UPDATER");
|
|
|
+}
|
|
|
+
|
|
|
+std::shared_ptr<Bonus> OwnerUpdater::createUpdatedBonus(const std::shared_ptr<Bonus> & b, const CBonusSystemNode & context) const
|
|
|
+{
|
|
|
+ auto owner = CBonusSystemNode::retrieveNodeOwner(&context);
|
|
|
+
|
|
|
+ if(owner == PlayerColor::UNFLAGGABLE)
|
|
|
+ owner = PlayerColor::NEUTRAL;
|
|
|
+
|
|
|
+ std::shared_ptr<Bonus> updated = std::make_shared<Bonus>(
|
|
|
+ (Bonus::BonusDuration)b->duration, b->type, b->source, b->val, b->sid, b->subtype, b->valType);
|
|
|
+ updated->limiter = std::make_shared<OppositeSideLimiter>(owner);
|
|
|
+ return updated;
|
|
|
+}
|