浏览代码

Merge pull request #5708 from kdmcser/limit_fix

OppositeLimiter fix and boat creation fix when loading map
Ivan Savenko 5 月之前
父节点
当前提交
f26dca2026
共有 4 个文件被更改,包括 94 次插入1 次删除
  1. 79 0
      lib/bonuses/Limiters.cpp
  2. 13 0
      lib/bonuses/Limiters.h
  3. 1 1
      lib/bonuses/Updaters.cpp
  4. 1 0
      lib/gameState/CGameState.cpp

+ 79 - 0
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<CCreatureTypeLimiter>(*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<HasAnotherBonusLimiter>(*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<UnitOnHexLimiter>(*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<CreatureTerrainLimiter>(*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<FactionLimiter>(*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<CreatureLevelLimiter>(*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<CreatureAlignmentLimiter>(*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<RankRangeLimiter>(*this);
+}
+
+
 OppositeSideLimiter::OppositeSideLimiter(PlayerColor Owner):
 	owner(std::move(Owner))
 {
@@ -522,6 +567,8 @@ OppositeSideLimiter::OppositeSideLimiter(PlayerColor Owner):
 ILimiter::EDecision OppositeSideLimiter::limit(const BonusLimitationContext & context) const
 {
 	auto contextOwner = context.node.getOwner();
+	if (contextOwner == PlayerColor::UNFLAGGABLE)
+		contextOwner = PlayerColor::NEUTRAL;
 	auto decision = (owner == contextOwner || owner == PlayerColor::CANNOT_DETERMINE) ? ILimiter::EDecision::DISCARD : ILimiter::EDecision::ACCEPT;
 	return decision;
 }
@@ -531,6 +578,11 @@ 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):
@@ -585,6 +637,15 @@ 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
 {
@@ -612,6 +673,15 @@ 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
 {
@@ -641,4 +711,13 @@ 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

+ 13 - 0
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 <typename Handler> void serialize(Handler &h)
 	{
@@ -77,6 +78,7 @@ 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
@@ -87,6 +89,7 @@ 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
@@ -97,6 +100,7 @@ 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)
@@ -113,6 +117,7 @@ public:
 	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)
 	{
@@ -142,6 +147,7 @@ public:
 	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)
 	{
@@ -167,6 +173,7 @@ public:
 	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)
 	{
@@ -187,6 +194,7 @@ public:
 	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)
 	{
@@ -206,6 +214,7 @@ public:
 	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)
 	{
@@ -224,6 +233,7 @@ public:
 	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)
 	{
@@ -240,6 +250,7 @@ public:
 
 	EDecision limit(const BonusLimitationContext &context) const override;
 	void acceptUpdater(IUpdater & visitor) override;
+	TLimiterPtr clone() const override;
 
 	template <typename Handler> 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 <typename Handler> 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 <typename Handler> void serialize(Handler &h)
 	{

+ 1 - 1
lib/bonuses/Updaters.cpp

@@ -232,7 +232,7 @@ std::shared_ptr<Bonus> OwnerUpdater::createUpdatedBonus(const std::shared_ptr<Bo
 
 	std::shared_ptr<Bonus> updated =
 		std::make_shared<Bonus>(*b);
-	updated->limiter = b->limiter;
+	updated->limiter = b->limiter->clone();
 	if (updated->limiter)
 		updated->limiter->acceptUpdater(*this);
 	return updated;

+ 1 - 0
lib/gameState/CGameState.cpp

@@ -625,6 +625,7 @@ void CGameState::initHeroes()
 
 			boat->setAnchorPos(hero->anchorPos());
 			boat->appearance = handler->getTemplates().front();
+			map->generateUniqueInstanceName(boat.get());
 			map->addNewObject(boat);
 			hero->setBoat(boat.get());
 		}