diff --git a/lib/bonuses/Limiters.cpp b/lib/bonuses/Limiters.cpp index 984eb068c..e3137bb18 100644 --- a/lib/bonuses/Limiters.cpp +++ b/lib/bonuses/Limiters.cpp @@ -99,6 +99,11 @@ JsonNode ILimiter::toJsonNode() const 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,6 +148,11 @@ void CCreatureTypeLimiter::acceptUpdater(IUpdater & visitor) visitor.visitLimiter(*this); } +TLimiterPtr CCreatureTypeLimiter::clone() const +{ + return std::make_shared(*this); +} + HasAnotherBonusLimiter::HasAnotherBonusLimiter( BonusType bonus ) : type(bonus), isSubtypeRelevant(false), isSourceRelevant(false), isSourceIDRelevant(false) { @@ -231,6 +241,11 @@ void HasAnotherBonusLimiter::acceptUpdater(IUpdater & visitor) visitor.visitLimiter(*this); } +TLimiterPtr HasAnotherBonusLimiter::clone() const +{ + return std::make_shared(*this); +} + ILimiter::EDecision UnitOnHexLimiter::limit(const BonusLimitationContext &context) const { const auto * stack = retrieveStackBattle(&context.node); @@ -266,6 +281,10 @@ void UnitOnHexLimiter::acceptUpdater(IUpdater& visitor) visitor.visitLimiter(*this); } +TLimiterPtr UnitOnHexLimiter::clone() const +{ + return std::make_shared(*this); +} CreatureTerrainLimiter::CreatureTerrainLimiter() : terrainType(ETerrainId::NATIVE_TERRAIN) @@ -351,6 +370,11 @@ void CreatureTerrainLimiter::acceptUpdater(IUpdater & visitor) visitor.visitLimiter(*this); } +TLimiterPtr CreatureTerrainLimiter::clone() const +{ + return std::make_shared(*this); +} + FactionLimiter::FactionLimiter(FactionID creatureFaction) : faction(creatureFaction) { @@ -401,6 +425,11 @@ void FactionLimiter::acceptUpdater(IUpdater & visitor) visitor.visitLimiter(*this); } +TLimiterPtr FactionLimiter::clone() const +{ + return std::make_shared(*this); +} + CreatureLevelLimiter::CreatureLevelLimiter(uint32_t minLevel, uint32_t maxLevel) : minLevel(minLevel), maxLevel(maxLevel) @@ -440,6 +469,11 @@ void CreatureLevelLimiter::acceptUpdater(IUpdater& visitor) visitor.visitLimiter(*this); } +TLimiterPtr CreatureLevelLimiter::clone() const +{ + return std::make_shared(*this); +} + CreatureAlignmentLimiter::CreatureAlignmentLimiter(EAlignment Alignment) : alignment(Alignment) { @@ -484,6 +518,11 @@ void CreatureAlignmentLimiter::acceptUpdater(IUpdater & visitor) visitor.visitLimiter(*this); } +TLimiterPtr CreatureAlignmentLimiter::clone() const +{ + return std::make_shared(*this); +} + RankRangeLimiter::RankRangeLimiter(ui8 Min, ui8 Max) :minRank(Min), maxRank(Max) { @@ -514,6 +553,12 @@ void RankRangeLimiter::acceptUpdater(IUpdater & visitor) visitor.visitLimiter(*this); } +TLimiterPtr RankRangeLimiter::clone() const +{ + return std::make_shared(*this); +} + + OppositeSideLimiter::OppositeSideLimiter(PlayerColor Owner): owner(std::move(Owner)) { @@ -531,6 +576,11 @@ void OppositeSideLimiter::acceptUpdater(IUpdater & visitor) visitor.visitLimiter(*this); } +TLimiterPtr OppositeSideLimiter::clone() const +{ + return std::make_shared(*this); +} + // Aggregate/Boolean Limiters AggregateLimiter::AggregateLimiter(std::vector limiters): @@ -585,6 +635,15 @@ ILimiter::EDecision AllOfLimiter::limit(const BonusLimitationContext & context) return wasntSure ? ILimiter::EDecision::NOT_SURE : ILimiter::EDecision::ACCEPT; } +TLimiterPtr AllOfLimiter::clone() const +{ + std::vector clonedLimiters; + clonedLimiters.reserve(limiters.size()); + for (const auto& limiter : limiters) + clonedLimiters.push_back(limiter->clone()); + return std::make_shared(clonedLimiters); +} + const std::string AnyOfLimiter::aggregator = "anyOf"; const std::string & AnyOfLimiter::getAggregator() const { @@ -612,6 +671,15 @@ ILimiter::EDecision AnyOfLimiter::limit(const BonusLimitationContext & context) return wasntSure ? ILimiter::EDecision::NOT_SURE : ILimiter::EDecision::DISCARD; } +TLimiterPtr AnyOfLimiter::clone() const +{ + std::vector clonedLimiters; + clonedLimiters.reserve(limiters.size()); + for (const auto& limiter : limiters) + clonedLimiters.push_back(limiter->clone()); + return std::make_shared(clonedLimiters); +} + const std::string NoneOfLimiter::aggregator = "noneOf"; const std::string & NoneOfLimiter::getAggregator() const { @@ -641,4 +709,13 @@ ILimiter::EDecision NoneOfLimiter::limit(const BonusLimitationContext & context) return wasntSure ? ILimiter::EDecision::NOT_SURE : ILimiter::EDecision::ACCEPT; } +TLimiterPtr NoneOfLimiter::clone() const +{ + std::vector clonedLimiters; + clonedLimiters.reserve(limiters.size()); + for (const auto& limiter : limiters) + clonedLimiters.push_back(limiter->clone()); + return std::make_shared(clonedLimiters); +} + VCMI_LIB_NAMESPACE_END diff --git a/lib/bonuses/Limiters.h b/lib/bonuses/Limiters.h index 9e0c1f72f..211c53642 100644 --- a/lib/bonuses/Limiters.h +++ b/lib/bonuses/Limiters.h @@ -45,6 +45,7 @@ public: virtual std::string toString() const; virtual JsonNode toJsonNode() const; virtual void acceptUpdater(IUpdater & visitor); + virtual TLimiterPtr clone() const; template void serialize(Handler &h) { @@ -77,6 +78,7 @@ public: AllOfLimiter(std::vector limiters = {}); static const std::string aggregator; EDecision limit(const BonusLimitationContext & context) const override; + TLimiterPtr clone() const override; }; class DLL_LINKAGE AnyOfLimiter : public AggregateLimiter @@ -87,6 +89,7 @@ public: AnyOfLimiter(std::vector limiters = {}); static const std::string aggregator; EDecision limit(const BonusLimitationContext & context) const override; + TLimiterPtr clone() const override; }; class DLL_LINKAGE NoneOfLimiter : public AggregateLimiter @@ -97,6 +100,7 @@ public: NoneOfLimiter(std::vector 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) @@ -113,6 +117,7 @@ public: std::string toString() const override; JsonNode toJsonNode() const override; void acceptUpdater(IUpdater & visitor) override; + TLimiterPtr clone() const override; template void serialize(Handler &h) { @@ -142,6 +147,7 @@ public: std::string toString() const override; JsonNode toJsonNode() const override; void acceptUpdater(IUpdater & visitor) override; + TLimiterPtr clone() const override; template void serialize(Handler &h) { @@ -167,6 +173,7 @@ public: std::string toString() const override; JsonNode toJsonNode() const override; void acceptUpdater(IUpdater & visitor) override; + TLimiterPtr clone() const override; template void serialize(Handler &h) { @@ -187,6 +194,7 @@ public: std::string toString() const override; JsonNode toJsonNode() const override; void acceptUpdater(IUpdater & visitor) override; + TLimiterPtr clone() const override; template void serialize(Handler &h) { @@ -206,6 +214,7 @@ public: std::string toString() const override; JsonNode toJsonNode() const override; void acceptUpdater(IUpdater & visitor) override; + TLimiterPtr clone() const override; template void serialize(Handler &h) { @@ -224,6 +233,7 @@ public: std::string toString() const override; JsonNode toJsonNode() const override; void acceptUpdater(IUpdater & visitor) override; + TLimiterPtr clone() const override; template void serialize(Handler &h) { @@ -240,6 +250,7 @@ public: EDecision limit(const BonusLimitationContext &context) const override; void acceptUpdater(IUpdater & visitor) override; + TLimiterPtr clone() const override; template void serialize(Handler &h) { @@ -258,6 +269,7 @@ public: RankRangeLimiter(ui8 Min, ui8 Max = 255); EDecision limit(const BonusLimitationContext &context) const override; void acceptUpdater(IUpdater & visitor) override; + TLimiterPtr clone() const override; template void serialize(Handler &h) { @@ -276,6 +288,7 @@ public: EDecision limit(const BonusLimitationContext &context) const override; JsonNode toJsonNode() const override; void acceptUpdater(IUpdater& visitor) override; + TLimiterPtr clone() const override; template void serialize(Handler &h) { diff --git a/lib/bonuses/Updaters.cpp b/lib/bonuses/Updaters.cpp index 50b7989e4..e08feeac8 100644 --- a/lib/bonuses/Updaters.cpp +++ b/lib/bonuses/Updaters.cpp @@ -232,7 +232,7 @@ std::shared_ptr OwnerUpdater::createUpdatedBonus(const std::shared_ptr updated = std::make_shared(*b); - updated->limiter = b->limiter; + updated->limiter = b->limiter->clone(); if (updated->limiter) updated->limiter->acceptUpdater(*this); return updated;