Browse Source

Merge pull request #5770 from IvanSavenko/const_bonus

Make bonus limiters/updaters/propagators const
Ivan Savenko 4 tháng trước cách đây
mục cha
commit
43844e2371

+ 7 - 10
lib/bonuses/Bonus.cpp

@@ -274,17 +274,14 @@ std::shared_ptr<Bonus> Bonus::addLimiter(const TLimiterPtr & Limiter)
 {
 	if (limiter)
 	{
-		//If we already have limiter list, retrieve it
-		auto limiterList = std::dynamic_pointer_cast<AllOfLimiter>(limiter);
-		if(!limiterList)
-		{
-			//Create a new limiter list with old limiter and the new one will be pushed later
-			limiterList = std::make_shared<AllOfLimiter>();
-			limiterList->add(limiter);
-			limiter = limiterList;
-		}
+		auto newLimiterList = std::make_shared<AllOfLimiter>();
+		auto oldLimiterList = std::dynamic_pointer_cast<const AllOfLimiter>(limiter);
+
+		if(oldLimiterList)
+			newLimiterList->limiters = oldLimiterList->limiters;
 
-		limiterList->add(Limiter);
+		newLimiterList->add(Limiter);
+		limiter = newLimiterList;
 	}
 	else
 	{

+ 6 - 5
lib/bonuses/Bonus.h

@@ -33,9 +33,9 @@ using BonusSubtypeID = VariantIdentifier<BonusCustomSubtype, SpellID, CreatureID
 using BonusSourceID = VariantIdentifier<BonusCustomSource, SpellID, CreatureID, ArtifactID, CampaignScenarioID, SecondarySkill, HeroTypeID, Obj, ObjectInstanceID, BuildingTypeUniqueID, BattleField>;
 using TBonusListPtr = std::shared_ptr<BonusList>;
 using TConstBonusListPtr = std::shared_ptr<const BonusList>;
-using TLimiterPtr = std::shared_ptr<ILimiter>;
-using TPropagatorPtr = std::shared_ptr<IPropagator>;
-using TUpdaterPtr = std::shared_ptr<IUpdater>;
+using TLimiterPtr = std::shared_ptr<const ILimiter>;
+using TPropagatorPtr = std::shared_ptr<const IPropagator>;
+using TUpdaterPtr = std::shared_ptr<const IUpdater>;
 
 class DLL_LINKAGE CAddInfo : public std::vector<si32>
 {
@@ -59,15 +59,15 @@ public:
 struct DLL_LINKAGE Bonus : public std::enable_shared_from_this<Bonus>, public Serializeable
 {
 	BonusDuration::Type duration = BonusDuration::PERMANENT; //uses BonusDuration values - 2 bytes
-	si16 turnsRemain = 0; //used if duration is N_TURNS, N_DAYS or ONE_WEEK
 	si32 val = 0;
+	si16 turnsRemain = 0; //used if duration is N_TURNS, N_DAYS or ONE_WEEK
 
 	BonusValueType valType = BonusValueType::ADDITIVE_VALUE; // 1 byte
 	BonusSource source = BonusSource::OTHER; //source type" uses BonusSource values - what gave that bonus - 1 byte
 	BonusSource targetSourceType = BonusSource::OTHER;//Bonuses of what origin this amplifies, uses BonusSource values. Needed for PERCENT_TO_TARGET_TYPE. - 1 byte
 	BonusType type = BonusType::NONE; //uses BonusType values - says to what is this bonus - 1 byte
 	BonusLimitEffect effectRange = BonusLimitEffect::NO_LIMIT; // 1 byte
-	// 3 bytes padding
+	// 1 bytes padding
 
 	BonusSubtypeID subtype;
 	BonusSourceID sid; //source id: id of object/artifact/spell
@@ -82,6 +82,7 @@ struct DLL_LINKAGE Bonus : public std::enable_shared_from_this<Bonus>, public Se
 
 	ImagePath customIconPath;
 	MetaString description;
+	PlayerColor bonusOwner = PlayerColor::CANNOT_DETERMINE;
 
 	Bonus(BonusDuration::Type Duration, BonusType Type, BonusSource Src, si32 Val, BonusSourceID sourceID);
 	Bonus(BonusDuration::Type Duration, BonusType Type, BonusSource Src, si32 Val, BonusSourceID sourceID, BonusSubtypeID subtype);

+ 4 - 134
lib/bonuses/Limiters.cpp

@@ -97,13 +97,6 @@ JsonNode ILimiter::toJsonNode() const
 	return root;
 }
 
-void ILimiter::acceptUpdater(IUpdater& visitor) {}
-
-TLimiterPtr ILimiter::clone() const
-{
-	throw std::runtime_error("Clone not implemented for this limiter");
-}
-
 ILimiter::EDecision CCreatureTypeLimiter::limit(const BonusLimitationContext &context) const
 {
 	const CCreature *c = retrieveCreature(&context.node);
@@ -143,16 +136,6 @@ JsonNode CCreatureTypeLimiter::toJsonNode() const
 	return root;
 }
 
-void CCreatureTypeLimiter::acceptUpdater(IUpdater & visitor)
-{
-	visitor.visitLimiter(*this);
-}
-
-TLimiterPtr CCreatureTypeLimiter::clone() const
-{
-	return std::make_shared<CCreatureTypeLimiter>(*this);
-}
-
 HasAnotherBonusLimiter::HasAnotherBonusLimiter( BonusType bonus )
 	: type(bonus), isSubtypeRelevant(false), isSourceRelevant(false), isSourceIDRelevant(false)
 {
@@ -236,16 +219,6 @@ JsonNode HasAnotherBonusLimiter::toJsonNode() const
 	return root;
 }
 
-void HasAnotherBonusLimiter::acceptUpdater(IUpdater & visitor)
-{
-	visitor.visitLimiter(*this);
-}
-
-TLimiterPtr HasAnotherBonusLimiter::clone() const
-{
-	return std::make_shared<HasAnotherBonusLimiter>(*this);
-}
-
 ILimiter::EDecision UnitOnHexLimiter::limit(const BonusLimitationContext &context) const
 {
 	const auto * stack = retrieveStackBattle(&context.node);
@@ -276,16 +249,6 @@ JsonNode UnitOnHexLimiter::toJsonNode() const
 	return root;
 }
 
-void UnitOnHexLimiter::acceptUpdater(IUpdater& visitor)
-{
-	visitor.visitLimiter(*this);
-}
-
-TLimiterPtr UnitOnHexLimiter::clone() const
-{
-	return std::make_shared<UnitOnHexLimiter>(*this);
-}
-
 CreatureTerrainLimiter::CreatureTerrainLimiter()
 	: terrainType(ETerrainId::NATIVE_TERRAIN)
 {
@@ -365,16 +328,6 @@ JsonNode CreatureTerrainLimiter::toJsonNode() const
 	return root;
 }
 
-void CreatureTerrainLimiter::acceptUpdater(IUpdater & visitor)
-{
-	visitor.visitLimiter(*this);
-}
-
-TLimiterPtr CreatureTerrainLimiter::clone() const
-{
-	return std::make_shared<CreatureTerrainLimiter>(*this);
-}
-
 FactionLimiter::FactionLimiter(FactionID creatureFaction)
 	: faction(creatureFaction)
 {
@@ -420,16 +373,6 @@ JsonNode FactionLimiter::toJsonNode() const
 	return root;
 }
 
-void FactionLimiter::acceptUpdater(IUpdater & visitor)
-{
-	visitor.visitLimiter(*this);
-}
-
-TLimiterPtr FactionLimiter::clone() const
-{
-	return std::make_shared<FactionLimiter>(*this);
-}
-
 CreatureLevelLimiter::CreatureLevelLimiter(uint32_t minLevel, uint32_t maxLevel) :
 	minLevel(minLevel),
 	maxLevel(maxLevel)
@@ -464,16 +407,6 @@ JsonNode CreatureLevelLimiter::toJsonNode() const
 	return root;
 }
 
-void CreatureLevelLimiter::acceptUpdater(IUpdater& visitor)
-{
-	visitor.visitLimiter(*this);
-}
-
-TLimiterPtr CreatureLevelLimiter::clone() const
-{
-	return std::make_shared<CreatureLevelLimiter>(*this);
-}
-
 CreatureAlignmentLimiter::CreatureAlignmentLimiter(EAlignment Alignment)
 	: alignment(Alignment)
 {
@@ -513,16 +446,6 @@ JsonNode CreatureAlignmentLimiter::toJsonNode() const
 	return root;
 }
 
-void CreatureAlignmentLimiter::acceptUpdater(IUpdater & visitor)
-{
-	visitor.visitLimiter(*this);
-}
-
-TLimiterPtr CreatureAlignmentLimiter::clone() const
-{
-	return std::make_shared<CreatureAlignmentLimiter>(*this);
-}
-
 RankRangeLimiter::RankRangeLimiter(ui8 Min, ui8 Max)
 	:minRank(Min), maxRank(Max)
 {
@@ -548,41 +471,20 @@ ILimiter::EDecision RankRangeLimiter::limit(const BonusLimitationContext &contex
 	return ILimiter::EDecision::NOT_APPLICABLE;
 }
 
-void RankRangeLimiter::acceptUpdater(IUpdater & visitor)
-{
-	visitor.visitLimiter(*this);
-}
-
-TLimiterPtr RankRangeLimiter::clone() const
-{
-	return std::make_shared<RankRangeLimiter>(*this);
-}
-
-
-OppositeSideLimiter::OppositeSideLimiter(PlayerColor Owner):
-	owner(std::move(Owner))
+OppositeSideLimiter::OppositeSideLimiter()
 {
 }
 
 ILimiter::EDecision OppositeSideLimiter::limit(const BonusLimitationContext & context) const
 {
-	auto contextOwner = context.node.getOwner();
+	PlayerColor contextOwner = context.node.getOwner();
+	PlayerColor bonusOwner = context.b.bonusOwner;
 	if (contextOwner == PlayerColor::UNFLAGGABLE)
 		contextOwner = PlayerColor::NEUTRAL;
-	auto decision = (owner == contextOwner || owner == PlayerColor::CANNOT_DETERMINE) ? ILimiter::EDecision::DISCARD : ILimiter::EDecision::ACCEPT;
+	auto decision = (bonusOwner == contextOwner || bonusOwner == PlayerColor::CANNOT_DETERMINE) ? ILimiter::EDecision::DISCARD : ILimiter::EDecision::ACCEPT;
 	return decision;
 }
 
-void OppositeSideLimiter::acceptUpdater(IUpdater & visitor)
-{
-	visitor.visitLimiter(*this);
-}
-
-TLimiterPtr OppositeSideLimiter::clone() const
-{
-	return std::make_shared<OppositeSideLimiter>(*this);
-}
-
 // Aggregate/Boolean Limiters
 
 AggregateLimiter::AggregateLimiter(std::vector<TLimiterPtr> limiters):
@@ -605,11 +507,6 @@ JsonNode AggregateLimiter::toJsonNode() const
 	return result;
 }
 
-void AggregateLimiter::acceptUpdater(IUpdater & visitor)
-{
-	visitor.visitLimiter(*this);
-}
-
 const std::string AllOfLimiter::aggregator = "allOf";
 const std::string & AllOfLimiter::getAggregator() const
 {
@@ -637,15 +534,6 @@ ILimiter::EDecision AllOfLimiter::limit(const BonusLimitationContext & context)
 	return wasntSure ? ILimiter::EDecision::NOT_SURE : ILimiter::EDecision::ACCEPT;
 }
 
-TLimiterPtr AllOfLimiter::clone() const
-{
-	std::vector<TLimiterPtr> clonedLimiters;
-	clonedLimiters.reserve(limiters.size());
-	for (const auto& limiter : limiters)
-		clonedLimiters.push_back(limiter->clone());
-	return std::make_shared<AllOfLimiter>(clonedLimiters);
-}
-
 const std::string AnyOfLimiter::aggregator = "anyOf";
 const std::string & AnyOfLimiter::getAggregator() const
 {
@@ -673,15 +561,6 @@ ILimiter::EDecision AnyOfLimiter::limit(const BonusLimitationContext & context)
 	return wasntSure ? ILimiter::EDecision::NOT_SURE : ILimiter::EDecision::DISCARD;
 }
 
-TLimiterPtr AnyOfLimiter::clone() const
-{
-	std::vector<TLimiterPtr> clonedLimiters;
-	clonedLimiters.reserve(limiters.size());
-	for (const auto& limiter : limiters)
-		clonedLimiters.push_back(limiter->clone());
-	return std::make_shared<AnyOfLimiter>(clonedLimiters);
-}
-
 const std::string NoneOfLimiter::aggregator = "noneOf";
 const std::string & NoneOfLimiter::getAggregator() const
 {
@@ -711,13 +590,4 @@ ILimiter::EDecision NoneOfLimiter::limit(const BonusLimitationContext & context)
 	return wasntSure ? ILimiter::EDecision::NOT_SURE : ILimiter::EDecision::ACCEPT;
 }
 
-TLimiterPtr NoneOfLimiter::clone() const
-{
-	std::vector<TLimiterPtr> clonedLimiters;
-	clonedLimiters.reserve(limiters.size());
-	for (const auto& limiter : limiters)
-		clonedLimiters.push_back(limiter->clone());
-	return std::make_shared<NoneOfLimiter>(clonedLimiters);
-}
-
 VCMI_LIB_NAMESPACE_END

+ 6 - 27
lib/bonuses/Limiters.h

@@ -44,8 +44,6 @@ public:
 	virtual EDecision limit(const BonusLimitationContext &context) const; //0 - accept bonus; 1 - drop bonus; 2 - delay (drops eventually)
 	virtual std::string toString() const;
 	virtual JsonNode toJsonNode() const;
-	virtual void acceptUpdater(IUpdater & visitor);
-	virtual TLimiterPtr clone() const;
 
 	template <typename Handler> void serialize(Handler &h)
 	{
@@ -61,7 +59,6 @@ public:
 	std::vector<TLimiterPtr> limiters;
 	void add(const TLimiterPtr & limiter);
 	JsonNode toJsonNode() const override;
-	void acceptUpdater(IUpdater & visitor) override;
 
 	template <typename Handler> void serialize(Handler & h)
 	{
@@ -78,7 +75,6 @@ public:
 	AllOfLimiter(std::vector<TLimiterPtr> limiters = {});
 	static const std::string aggregator;
 	EDecision limit(const BonusLimitationContext & context) const override;
-	TLimiterPtr clone() const override;
 };
 
 class DLL_LINKAGE AnyOfLimiter : public AggregateLimiter
@@ -89,7 +85,6 @@ public:
 	AnyOfLimiter(std::vector<TLimiterPtr> limiters = {});
 	static const std::string aggregator;
 	EDecision limit(const BonusLimitationContext & context) const override;
-	TLimiterPtr clone() const override;
 };
 
 class DLL_LINKAGE NoneOfLimiter : public AggregateLimiter
@@ -100,7 +95,6 @@ public:
 	NoneOfLimiter(std::vector<TLimiterPtr> limiters = {});
 	static const std::string aggregator;
 	EDecision limit(const BonusLimitationContext & context) const override;
-	TLimiterPtr clone() const override;
 };
 
 class DLL_LINKAGE CCreatureTypeLimiter : public ILimiter //affect only stacks of given creature (and optionally it's upgrades)
@@ -116,8 +110,6 @@ public:
 	EDecision limit(const BonusLimitationContext &context) const override;
 	std::string toString() const override;
 	JsonNode toJsonNode() const override;
-	void acceptUpdater(IUpdater & visitor) override;
-	TLimiterPtr clone() const override;
 
 	template <typename Handler> void serialize(Handler &h)
 	{
@@ -146,8 +138,6 @@ public:
 	EDecision limit(const BonusLimitationContext &context) const override;
 	std::string toString() const override;
 	JsonNode toJsonNode() const override;
-	void acceptUpdater(IUpdater & visitor) override;
-	TLimiterPtr clone() const override;
 
 	template <typename Handler> void serialize(Handler &h)
 	{
@@ -172,8 +162,6 @@ public:
 	EDecision limit(const BonusLimitationContext &context) const override;
 	std::string toString() const override;
 	JsonNode toJsonNode() const override;
-	void acceptUpdater(IUpdater & visitor) override;
-	TLimiterPtr clone() const override;
 
 	template <typename Handler> void serialize(Handler &h)
 	{
@@ -193,8 +181,6 @@ public:
 	EDecision limit(const BonusLimitationContext &context) const override;
 	std::string toString() const override;
 	JsonNode toJsonNode() const override;
-	void acceptUpdater(IUpdater & visitor) override;
-	TLimiterPtr clone() const override;
 
 	template <typename Handler> void serialize(Handler &h)
 	{
@@ -213,8 +199,6 @@ public:
 	EDecision limit(const BonusLimitationContext &context) const override;
 	std::string toString() const override;
 	JsonNode toJsonNode() const override;
-	void acceptUpdater(IUpdater & visitor) override;
-	TLimiterPtr clone() const override;
 
 	template <typename Handler> void serialize(Handler &h)
 	{
@@ -232,8 +216,6 @@ public:
 	EDecision limit(const BonusLimitationContext &context) const override;
 	std::string toString() const override;
 	JsonNode toJsonNode() const override;
-	void acceptUpdater(IUpdater & visitor) override;
-	TLimiterPtr clone() const override;
 
 	template <typename Handler> void serialize(Handler &h)
 	{
@@ -245,17 +227,18 @@ public:
 class DLL_LINKAGE OppositeSideLimiter : public ILimiter //applies only to creatures of enemy army during combat
 {
 public:
-	PlayerColor owner;
-	OppositeSideLimiter(PlayerColor Owner = PlayerColor::CANNOT_DETERMINE);
+	OppositeSideLimiter();
 
 	EDecision limit(const BonusLimitationContext &context) const override;
-	void acceptUpdater(IUpdater & visitor) override;
-	TLimiterPtr clone() const override;
 
 	template <typename Handler> void serialize(Handler &h)
 	{
 		h & static_cast<ILimiter&>(*this);
-		h & owner;
+		if (!h.hasFeature(Handler::Version::OPPOSITE_SIDE_LIMITER_OWNER))
+		{
+			PlayerColor owner;
+			h & owner;
+		}
 	}
 };
 
@@ -268,8 +251,6 @@ public:
 	RankRangeLimiter();
 	RankRangeLimiter(ui8 Min, ui8 Max = 255);
 	EDecision limit(const BonusLimitationContext &context) const override;
-	void acceptUpdater(IUpdater & visitor) override;
-	TLimiterPtr clone() const override;
 
 	template <typename Handler> void serialize(Handler &h)
 	{
@@ -287,8 +268,6 @@ public:
 	UnitOnHexLimiter(const BattleHexArray & applicableHexes = {});
 	EDecision limit(const BonusLimitationContext &context) const override;
 	JsonNode toJsonNode() const override;
-	void acceptUpdater(IUpdater& visitor) override;
-	TLimiterPtr clone() const override;
 
 	template <typename Handler> void serialize(Handler &h)
 	{

+ 3 - 3
lib/bonuses/Propagators.cpp

@@ -24,7 +24,7 @@ const std::map<std::string, TPropagatorPtr> bonusPropagatorMap =
 	{"GLOBAL_EFFECT", std::make_shared<CPropagatorNodeType>(CBonusSystemNode::GLOBAL_EFFECTS)}
 }; //untested
 
-bool IPropagator::shouldBeAttached(CBonusSystemNode *dest)
+bool IPropagator::shouldBeAttached(CBonusSystemNode *dest) const
 {
 	return false;
 }
@@ -44,9 +44,9 @@ CBonusSystemNode::ENodeTypes CPropagatorNodeType::getPropagatorType() const
 	return nodeType;
 }
 
-bool CPropagatorNodeType::shouldBeAttached(CBonusSystemNode *dest)
+bool CPropagatorNodeType::shouldBeAttached(CBonusSystemNode *dest) const
 {
 	return nodeType == dest->getNodeType();
 }
 
-VCMI_LIB_NAMESPACE_END
+VCMI_LIB_NAMESPACE_END

+ 2 - 2
lib/bonuses/Propagators.h

@@ -22,7 +22,7 @@ class DLL_LINKAGE IPropagator : public Serializeable
 {
 public:
 	virtual ~IPropagator() = default;
-	virtual bool shouldBeAttached(CBonusSystemNode *dest);
+	virtual bool shouldBeAttached(CBonusSystemNode *dest) const;
 	virtual CBonusSystemNode::ENodeTypes getPropagatorType() const;
 
 	template <typename Handler> void serialize(Handler &h)
@@ -35,7 +35,7 @@ class DLL_LINKAGE CPropagatorNodeType : public IPropagator
 
 public:
 	CPropagatorNodeType(CBonusSystemNode::ENodeTypes NodeType = CBonusSystemNode::ENodeTypes::UNKNOWN);
-	bool shouldBeAttached(CBonusSystemNode *dest) override;
+	bool shouldBeAttached(CBonusSystemNode *dest) const override;
 	CBonusSystemNode::ENodeTypes getPropagatorType() const override;
 
 	template <typename Handler> void serialize(Handler &h)

+ 9 - 32
lib/bonuses/Updaters.cpp

@@ -18,7 +18,7 @@
 
 VCMI_LIB_NAMESPACE_BEGIN
 
-std::shared_ptr<Bonus> IUpdater::createUpdatedBonus(const std::shared_ptr<Bonus> & b, const CBonusSystemNode & context)
+std::shared_ptr<Bonus> IUpdater::createUpdatedBonus(const std::shared_ptr<Bonus> & b, const CBonusSystemNode & context) const
 {
 	return b;
 }
@@ -33,27 +33,11 @@ JsonNode IUpdater::toJsonNode() const
 	return JsonNode();
 }
 
-void IUpdater::visitLimiter(AggregateLimiter& limiter)
-{
-	for (auto& limit : limiter.limiters)
-		limit->acceptUpdater(*this);
-}
-
-void IUpdater::visitLimiter(CCreatureTypeLimiter& limiter) {}
-void IUpdater::visitLimiter(HasAnotherBonusLimiter& limiter) {}
-void IUpdater::visitLimiter(CreatureTerrainLimiter& limiter) {}
-void IUpdater::visitLimiter(CreatureLevelLimiter& limiter) {}
-void IUpdater::visitLimiter(FactionLimiter& limiter) {}
-void IUpdater::visitLimiter(CreatureAlignmentLimiter& limiter) {}
-void IUpdater::visitLimiter(OppositeSideLimiter& limiter) {}
-void IUpdater::visitLimiter(RankRangeLimiter& limiter) {}
-void IUpdater::visitLimiter(UnitOnHexLimiter& limiter) {}
-
 GrowsWithLevelUpdater::GrowsWithLevelUpdater(int valPer20, int stepSize) : valPer20(valPer20), stepSize(stepSize)
 {
 }
 
-std::shared_ptr<Bonus> GrowsWithLevelUpdater::createUpdatedBonus(const std::shared_ptr<Bonus> & b, const CBonusSystemNode & context)
+std::shared_ptr<Bonus> GrowsWithLevelUpdater::createUpdatedBonus(const std::shared_ptr<Bonus> & b, const CBonusSystemNode & context) const
 {
 	if(context.getNodeType() == CBonusSystemNode::HERO)
 	{
@@ -86,7 +70,7 @@ JsonNode GrowsWithLevelUpdater::toJsonNode() const
 	return root;
 }
 
-std::shared_ptr<Bonus> TimesHeroLevelUpdater::createUpdatedBonus(const std::shared_ptr<Bonus> & b, const CBonusSystemNode & context)
+std::shared_ptr<Bonus> TimesHeroLevelUpdater::createUpdatedBonus(const std::shared_ptr<Bonus> & b, const CBonusSystemNode & context) const
 {
 	if(context.getNodeType() == CBonusSystemNode::HERO)
 	{
@@ -108,7 +92,7 @@ JsonNode TimesHeroLevelUpdater::toJsonNode() const
 	return JsonNode("TIMES_HERO_LEVEL");
 }
 
-std::shared_ptr<Bonus> TimesHeroLevelDivideStackLevelUpdater::createUpdatedBonus(const std::shared_ptr<Bonus> & b, const CBonusSystemNode & context)
+std::shared_ptr<Bonus> TimesHeroLevelDivideStackLevelUpdater::createUpdatedBonus(const std::shared_ptr<Bonus> & b, const CBonusSystemNode & context) const
 {
 	if(context.getNodeType() == CBonusSystemNode::HERO)
 	{
@@ -137,7 +121,7 @@ std::shared_ptr<Bonus> TimesStackLevelUpdater::apply(const std::shared_ptr<Bonus
 	return newBonus;
 }
 
-std::shared_ptr<Bonus> TimesStackLevelUpdater::createUpdatedBonus(const std::shared_ptr<Bonus> & b, const CBonusSystemNode & context)
+std::shared_ptr<Bonus> TimesStackLevelUpdater::createUpdatedBonus(const std::shared_ptr<Bonus> & b, const CBonusSystemNode & context) const
 {
 	if(context.getNodeType() == CBonusSystemNode::STACK_INSTANCE || context.getNodeType() == CBonusSystemNode::COMMANDER)
 	{
@@ -181,7 +165,7 @@ std::shared_ptr<Bonus> DivideStackLevelUpdater::apply(const std::shared_ptr<Bonu
 	return newBonus;
 }
 
-std::shared_ptr<Bonus> DivideStackLevelUpdater::createUpdatedBonus(const std::shared_ptr<Bonus> & b, const CBonusSystemNode & context)
+std::shared_ptr<Bonus> DivideStackLevelUpdater::createUpdatedBonus(const std::shared_ptr<Bonus> & b, const CBonusSystemNode & context) const
 {
 	if(context.getNodeType() == CBonusSystemNode::STACK_INSTANCE || context.getNodeType() == CBonusSystemNode::COMMANDER)
 	{
@@ -223,24 +207,17 @@ JsonNode OwnerUpdater::toJsonNode() const
 	return JsonNode("BONUS_OWNER_UPDATER");
 }
 
-std::shared_ptr<Bonus> OwnerUpdater::createUpdatedBonus(const std::shared_ptr<Bonus> & b, const CBonusSystemNode & context)
+std::shared_ptr<Bonus> OwnerUpdater::createUpdatedBonus(const std::shared_ptr<Bonus> & b, const CBonusSystemNode & context) const
 {
-	owner = context.getOwner();
+	PlayerColor owner = context.getOwner();
 	
 	if(owner == PlayerColor::UNFLAGGABLE)
 		owner = PlayerColor::NEUTRAL;
 
 	std::shared_ptr<Bonus> updated =
 		std::make_shared<Bonus>(*b);
-	updated->limiter = b->limiter->clone();
-	if (updated->limiter)
-		updated->limiter->acceptUpdater(*this);
+	updated->bonusOwner = owner;
 	return updated;
 }
 
-void OwnerUpdater::visitLimiter(OppositeSideLimiter& limiter)
-{
-	limiter.owner = owner;
-}
-
 VCMI_LIB_NAMESPACE_END

+ 7 - 22
lib/bonuses/Updaters.h

@@ -32,21 +32,10 @@ class DLL_LINKAGE IUpdater : public Serializeable
 public:
 	virtual ~IUpdater() = default;
 
-	virtual std::shared_ptr<Bonus> createUpdatedBonus(const std::shared_ptr<Bonus> & b, const CBonusSystemNode & context);
+	virtual std::shared_ptr<Bonus> createUpdatedBonus(const std::shared_ptr<Bonus> & b, const CBonusSystemNode & context) const;
 	virtual std::string toString() const;
 	virtual JsonNode toJsonNode() const;
 
-	virtual void visitLimiter(AggregateLimiter & limiter);
-	virtual void visitLimiter(CCreatureTypeLimiter& limiter);
-	virtual void visitLimiter(HasAnotherBonusLimiter & limiter);
-	virtual void visitLimiter(CreatureTerrainLimiter & limiter);
-	virtual void visitLimiter(CreatureLevelLimiter & limiter);
-	virtual void visitLimiter(FactionLimiter & limiter);
-	virtual void visitLimiter(CreatureAlignmentLimiter & limiter) ;
-	virtual void visitLimiter(OppositeSideLimiter & limiter);
-	virtual void visitLimiter(RankRangeLimiter & limiter);
-	virtual void visitLimiter(UnitOnHexLimiter & limiter);
-
 	template <typename Handler> void serialize(Handler & h)
 	{
 	}
@@ -68,7 +57,7 @@ public:
 		h & stepSize;
 	}
 
-	std::shared_ptr<Bonus> createUpdatedBonus(const std::shared_ptr<Bonus> & b, const CBonusSystemNode & context) override;
+	std::shared_ptr<Bonus> createUpdatedBonus(const std::shared_ptr<Bonus> & b, const CBonusSystemNode & context) const override;
 	std::string toString() const override;
 	JsonNode toJsonNode() const override;
 };
@@ -81,7 +70,7 @@ public:
 		h & static_cast<IUpdater &>(*this);
 	}
 
-	std::shared_ptr<Bonus> createUpdatedBonus(const std::shared_ptr<Bonus> & b, const CBonusSystemNode & context) override;
+	std::shared_ptr<Bonus> createUpdatedBonus(const std::shared_ptr<Bonus> & b, const CBonusSystemNode & context) const override;
 	std::string toString() const override;
 	JsonNode toJsonNode() const override;
 };
@@ -95,7 +84,7 @@ public:
 		h & static_cast<IUpdater &>(*this);
 	}
 
-	std::shared_ptr<Bonus> createUpdatedBonus(const std::shared_ptr<Bonus> & b, const CBonusSystemNode & context) override;
+	std::shared_ptr<Bonus> createUpdatedBonus(const std::shared_ptr<Bonus> & b, const CBonusSystemNode & context) const override;
 	std::string toString() const override;
 	JsonNode toJsonNode() const override;
 };
@@ -109,7 +98,7 @@ public:
 		h & static_cast<IUpdater &>(*this);
 	}
 
-	std::shared_ptr<Bonus> createUpdatedBonus(const std::shared_ptr<Bonus> & b, const CBonusSystemNode & context) override;
+	std::shared_ptr<Bonus> createUpdatedBonus(const std::shared_ptr<Bonus> & b, const CBonusSystemNode & context) const override;
 	std::string toString() const override;
 	JsonNode toJsonNode() const override;
 };
@@ -128,26 +117,22 @@ public:
 		: divideStackLevel(std::make_shared<DivideStackLevelUpdater>())
 	{}
 
-	std::shared_ptr<Bonus> createUpdatedBonus(const std::shared_ptr<Bonus> & b, const CBonusSystemNode & context) override;
+	std::shared_ptr<Bonus> createUpdatedBonus(const std::shared_ptr<Bonus> & b, const CBonusSystemNode & context) const override;
 	std::string toString() const override;
 	JsonNode toJsonNode() const override;
 };
 
 class DLL_LINKAGE OwnerUpdater : public IUpdater
 {
-protected:
-	PlayerColor owner;
-
 public:
 	template <typename Handler> void serialize(Handler& h)
 	{
 		h & static_cast<IUpdater &>(*this);
 	}
 
-	std::shared_ptr<Bonus> createUpdatedBonus(const std::shared_ptr<Bonus>& b, const CBonusSystemNode& context) override;
+	std::shared_ptr<Bonus> createUpdatedBonus(const std::shared_ptr<Bonus>& b, const CBonusSystemNode& context) const override;
 	std::string toString() const override;
 	JsonNode toJsonNode() const override;
-	void visitLimiter(OppositeSideLimiter& limiter) override;
 };
 
 VCMI_LIB_NAMESPACE_END

+ 8 - 8
lib/json/JsonBonus.cpp

@@ -399,13 +399,13 @@ static BonusParams convertDeprecatedBonus(const JsonNode &ability)
 
 static TUpdaterPtr parseUpdater(const JsonNode & updaterJson)
 {
-	const std::map<std::string, std::function<TUpdaterPtr()>> bonusUpdaterMap =
+	const std::map<std::string, std::shared_ptr<IUpdater>> bonusUpdaterMap =
 	{
-			{"TIMES_HERO_LEVEL", std::make_shared<TimesHeroLevelUpdater>},
-			{"TIMES_HERO_LEVEL_DIVIDE_STACK_LEVEL", std::make_shared<TimesHeroLevelDivideStackLevelUpdater>},
-			{"DIVIDE_STACK_LEVEL", std::make_shared<DivideStackLevelUpdater>},
-			{"TIMES_STACK_LEVEL", std::make_shared<TimesStackLevelUpdater>},
-			{"BONUS_OWNER_UPDATER", std::make_shared<OwnerUpdater>}
+			{"TIMES_HERO_LEVEL", std::make_shared<TimesHeroLevelUpdater>()},
+			{"TIMES_HERO_LEVEL_DIVIDE_STACK_LEVEL", std::make_shared<TimesHeroLevelDivideStackLevelUpdater>()},
+			{"DIVIDE_STACK_LEVEL", std::make_shared<DivideStackLevelUpdater>()},
+			{"TIMES_STACK_LEVEL", std::make_shared<TimesStackLevelUpdater>()},
+			{"BONUS_OWNER_UPDATER", std::make_shared<OwnerUpdater>()}
 	};
 
 	switch(updaterJson.getType())
@@ -414,7 +414,7 @@ static TUpdaterPtr parseUpdater(const JsonNode & updaterJson)
 		{
 			auto it = bonusUpdaterMap.find(updaterJson.String());
 			if (it != bonusUpdaterMap.end())
-				return it->second();
+				return it->second;
 
 			logGlobal->error("Unknown bonus updater type '%s'", updaterJson.String());
 			return nullptr;
@@ -458,7 +458,7 @@ std::shared_ptr<Bonus> JsonUtils::parseBonus(const JsonVector & ability_vec)
 	return b;
 }
 
-std::shared_ptr<ILimiter> JsonUtils::parseLimiter(const JsonNode & limiter)
+std::shared_ptr<const ILimiter> JsonUtils::parseLimiter(const JsonNode & limiter)
 {
 	switch(limiter.getType())
 	{

+ 1 - 1
lib/json/JsonBonus.h

@@ -24,7 +24,7 @@ namespace JsonUtils
 	std::shared_ptr<Bonus> parseBonus(const JsonVector & ability_vec);
 	std::shared_ptr<Bonus> parseBonus(const JsonNode & ability, const TextIdentifier & descriptionID = "");
 	bool parseBonus(const JsonNode & ability, Bonus * placement, const TextIdentifier & descriptionID = "");
-	std::shared_ptr<ILimiter> parseLimiter(const JsonNode & limiter);
+	std::shared_ptr<const ILimiter> parseLimiter(const JsonNode & limiter);
 	CSelector parseSelector(const JsonNode &ability);
 }
 

+ 2 - 1
lib/serializer/ESerializationVersion.h

@@ -44,8 +44,9 @@ enum class ESerializationVersion : int32_t
 	RANDOMIZATION_REWORK, // random rolls logic has been moved to server
 	CUSTOM_BONUS_ICONS, // support for custom icons in bonuses
 	SERVER_STATISTICS, // statistics now only saved on server
+	OPPOSITE_SIDE_LIMITER_OWNER, // opposite side limiter no longer stores owner in itself
 
-	CURRENT = SERVER_STATISTICS,
+	CURRENT = OPPOSITE_SIDE_LIMITER_OWNER,
 };
 
 static_assert(ESerializationVersion::MINIMAL <= ESerializationVersion::CURRENT, "Invalid serialization version definition!");