Przeglądaj źródła

Merge pull request #5593 from kdmcser/limiter

make OwnerUpdater not hardcode OppositeSideLimiter
Ivan Savenko 6 miesięcy temu
rodzic
commit
f3ca06c3d0
4 zmienionych plików z 129 dodań i 17 usunięć
  1. 54 0
      lib/bonuses/Limiters.cpp
  2. 12 1
      lib/bonuses/Limiters.h
  3. 31 10
      lib/bonuses/Updaters.cpp
  4. 32 6
      lib/bonuses/Updaters.h

+ 54 - 0
lib/bonuses/Limiters.cpp

@@ -10,6 +10,7 @@
 
 #include "StdInc.h"
 #include "Limiters.h"
+#include "Updaters.h"
 
 #include "../GameLibrary.h"
 #include "../entities/faction/CFaction.h"
@@ -97,6 +98,8 @@ JsonNode ILimiter::toJsonNode() const
 	return root;
 }
 
+void ILimiter::acceptUpdater(IUpdater& visitor) {}
+
 ILimiter::EDecision CCreatureTypeLimiter::limit(const BonusLimitationContext &context) const
 {
 	const CCreature *c = retrieveCreature(&context.node);
@@ -136,6 +139,11 @@ JsonNode CCreatureTypeLimiter::toJsonNode() const
 	return root;
 }
 
+void CCreatureTypeLimiter::acceptUpdater(IUpdater & visitor)
+{
+	visitor.visitLimiter(*this);
+}
+
 HasAnotherBonusLimiter::HasAnotherBonusLimiter( BonusType bonus )
 	: type(bonus), isSubtypeRelevant(false), isSourceRelevant(false), isSourceIDRelevant(false)
 {
@@ -213,6 +221,11 @@ JsonNode HasAnotherBonusLimiter::toJsonNode() const
 	return root;
 }
 
+void HasAnotherBonusLimiter::acceptUpdater(IUpdater & visitor)
+{
+	visitor.visitLimiter(*this);
+}
+
 ILimiter::EDecision UnitOnHexLimiter::limit(const BonusLimitationContext &context) const
 {
 	const auto * stack = retrieveStackBattle(&context.node);
@@ -243,6 +256,12 @@ JsonNode UnitOnHexLimiter::toJsonNode() const
 	return root;
 }
 
+void UnitOnHexLimiter::acceptUpdater(IUpdater& visitor)
+{
+	visitor.visitLimiter(*this);
+}
+
+
 CreatureTerrainLimiter::CreatureTerrainLimiter()
 	: terrainType(ETerrainId::NATIVE_TERRAIN)
 {
@@ -288,6 +307,11 @@ JsonNode CreatureTerrainLimiter::toJsonNode() const
 	return root;
 }
 
+void CreatureTerrainLimiter::acceptUpdater(IUpdater & visitor)
+{
+	visitor.visitLimiter(*this);
+}
+
 FactionLimiter::FactionLimiter(FactionID creatureFaction)
 	: faction(creatureFaction)
 {
@@ -333,6 +357,11 @@ JsonNode FactionLimiter::toJsonNode() const
 	return root;
 }
 
+void FactionLimiter::acceptUpdater(IUpdater & visitor)
+{
+	visitor.visitLimiter(*this);
+}
+
 CreatureLevelLimiter::CreatureLevelLimiter(uint32_t minLevel, uint32_t maxLevel) :
 	minLevel(minLevel),
 	maxLevel(maxLevel)
@@ -364,6 +393,11 @@ JsonNode CreatureLevelLimiter::toJsonNode() const
 	return root;
 }
 
+void CreatureLevelLimiter::acceptUpdater(IUpdater& visitor)
+{
+	visitor.visitLimiter(*this);
+}
+
 CreatureAlignmentLimiter::CreatureAlignmentLimiter(EAlignment Alignment)
 	: alignment(Alignment)
 {
@@ -401,6 +435,11 @@ JsonNode CreatureAlignmentLimiter::toJsonNode() const
 	return root;
 }
 
+void CreatureAlignmentLimiter::acceptUpdater(IUpdater & visitor)
+{
+	visitor.visitLimiter(*this);
+}
+
 RankRangeLimiter::RankRangeLimiter(ui8 Min, ui8 Max)
 	:minRank(Min), maxRank(Max)
 {
@@ -424,6 +463,11 @@ ILimiter::EDecision RankRangeLimiter::limit(const BonusLimitationContext &contex
 	return ILimiter::EDecision::DISCARD;
 }
 
+void RankRangeLimiter::acceptUpdater(IUpdater & visitor)
+{
+	visitor.visitLimiter(*this);
+}
+
 OppositeSideLimiter::OppositeSideLimiter(PlayerColor Owner):
 	owner(std::move(Owner))
 {
@@ -436,6 +480,11 @@ ILimiter::EDecision OppositeSideLimiter::limit(const BonusLimitationContext & co
 	return decision;
 }
 
+void OppositeSideLimiter::acceptUpdater(IUpdater & visitor)
+{
+	visitor.visitLimiter(*this);
+}
+
 // Aggregate/Boolean Limiters
 
 AggregateLimiter::AggregateLimiter(std::vector<TLimiterPtr> limiters):
@@ -458,6 +507,11 @@ 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
 {

+ 12 - 1
lib/bonuses/Limiters.h

@@ -38,6 +38,7 @@ 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);
 
 	template <typename Handler> void serialize(Handler &h)
 	{
@@ -47,12 +48,13 @@ public:
 class DLL_LINKAGE AggregateLimiter : public ILimiter
 {
 protected:
-	std::vector<TLimiterPtr> limiters;
 	virtual const std::string & getAggregator() const = 0;
 	AggregateLimiter(std::vector<TLimiterPtr> limiters = {});
 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)
 	{
@@ -104,6 +106,7 @@ public:
 	EDecision limit(const BonusLimitationContext &context) const override;
 	std::string toString() const override;
 	JsonNode toJsonNode() const override;
+	void acceptUpdater(IUpdater & visitor) override;
 
 	template <typename Handler> void serialize(Handler &h)
 	{
@@ -132,6 +135,7 @@ public:
 	EDecision limit(const BonusLimitationContext &context) const override;
 	std::string toString() const override;
 	JsonNode toJsonNode() const override;
+	void acceptUpdater(IUpdater & visitor) override;
 
 	template <typename Handler> void serialize(Handler &h)
 	{
@@ -156,6 +160,7 @@ public:
 	EDecision limit(const BonusLimitationContext &context) const override;
 	std::string toString() const override;
 	JsonNode toJsonNode() const override;
+	void acceptUpdater(IUpdater & visitor) override;
 
 	template <typename Handler> void serialize(Handler &h)
 	{
@@ -175,6 +180,7 @@ public:
 	EDecision limit(const BonusLimitationContext &context) const override;
 	std::string toString() const override;
 	JsonNode toJsonNode() const override;
+	void acceptUpdater(IUpdater & visitor) override;
 
 	template <typename Handler> void serialize(Handler &h)
 	{
@@ -193,6 +199,7 @@ public:
 	EDecision limit(const BonusLimitationContext &context) const override;
 	std::string toString() const override;
 	JsonNode toJsonNode() const override;
+	void acceptUpdater(IUpdater & visitor) override;
 
 	template <typename Handler> void serialize(Handler &h)
 	{
@@ -210,6 +217,7 @@ public:
 	EDecision limit(const BonusLimitationContext &context) const override;
 	std::string toString() const override;
 	JsonNode toJsonNode() const override;
+	void acceptUpdater(IUpdater & visitor) override;
 
 	template <typename Handler> void serialize(Handler &h)
 	{
@@ -225,6 +233,7 @@ public:
 	OppositeSideLimiter(PlayerColor Owner = PlayerColor::CANNOT_DETERMINE);
 
 	EDecision limit(const BonusLimitationContext &context) const override;
+	void acceptUpdater(IUpdater & visitor) override;
 
 	template <typename Handler> void serialize(Handler &h)
 	{
@@ -242,6 +251,7 @@ public:
 	RankRangeLimiter();
 	RankRangeLimiter(ui8 Min, ui8 Max = 255);
 	EDecision limit(const BonusLimitationContext &context) const override;
+	void acceptUpdater(IUpdater & visitor) override;
 
 	template <typename Handler> void serialize(Handler &h)
 	{
@@ -259,6 +269,7 @@ public:
 	UnitOnHexLimiter(const BattleHexArray & applicableHexes = {});
 	EDecision limit(const BonusLimitationContext &context) const override;
 	JsonNode toJsonNode() const override;
+	void acceptUpdater(IUpdater& visitor) override;
 
 	template <typename Handler> void serialize(Handler &h)
 	{

+ 31 - 10
lib/bonuses/Updaters.cpp

@@ -12,14 +12,13 @@
 
 #include "Updaters.h"
 #include "Limiters.h"
-
 #include "../json/JsonNode.h"
 #include "../mapObjects/CGHeroInstance.h"
 #include "../CStack.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 
-std::shared_ptr<Bonus> IUpdater::createUpdatedBonus(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)
 {
 	return b;
 }
@@ -34,11 +33,27 @@ 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) const
+std::shared_ptr<Bonus> GrowsWithLevelUpdater::createUpdatedBonus(const std::shared_ptr<Bonus> & b, const CBonusSystemNode & context)
 {
 	if(context.getNodeType() == CBonusSystemNode::HERO)
 	{
@@ -71,7 +86,7 @@ JsonNode GrowsWithLevelUpdater::toJsonNode() const
 	return root;
 }
 
-std::shared_ptr<Bonus> TimesHeroLevelUpdater::createUpdatedBonus(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)
 {
 	if(context.getNodeType() == CBonusSystemNode::HERO)
 	{
@@ -109,7 +124,7 @@ ArmyMovementUpdater::ArmyMovementUpdater(int base, int divider, int multiplier,
 {
 }
 
-std::shared_ptr<Bonus> ArmyMovementUpdater::createUpdatedBonus(const std::shared_ptr<Bonus> & b, const CBonusSystemNode & context) const
+std::shared_ptr<Bonus> ArmyMovementUpdater::createUpdatedBonus(const std::shared_ptr<Bonus> & b, const CBonusSystemNode & context)
 {
 	return b;
 }
@@ -131,7 +146,7 @@ JsonNode ArmyMovementUpdater::toJsonNode() const
 
 	return root;
 }
-std::shared_ptr<Bonus> TimesStackLevelUpdater::createUpdatedBonus(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)
 {
 	if(context.getNodeType() == CBonusSystemNode::STACK_INSTANCE || context.getNodeType() == CBonusSystemNode::COMMANDER)
 	{
@@ -183,17 +198,23 @@ JsonNode OwnerUpdater::toJsonNode() const
 	return JsonNode("BONUS_OWNER_UPDATER");
 }
 
-std::shared_ptr<Bonus> OwnerUpdater::createUpdatedBonus(const std::shared_ptr<Bonus> & b, const CBonusSystemNode & context) const
+std::shared_ptr<Bonus> OwnerUpdater::createUpdatedBonus(const std::shared_ptr<Bonus> & b, const CBonusSystemNode & context)
 {
-	auto owner = context.getOwner();
-
+	owner = context.getOwner();
+	
 	if(owner == PlayerColor::UNFLAGGABLE)
 		owner = PlayerColor::NEUTRAL;
 
 	std::shared_ptr<Bonus> updated =
 		std::make_shared<Bonus>(*b);
-	updated->limiter = std::make_shared<OppositeSideLimiter>(owner);
+	updated->limiter = b->limiter;
+	updated->limiter->acceptUpdater(*this);
 	return updated;
 }
 
+void OwnerUpdater::visitLimiter(OppositeSideLimiter& limiter)
+{
+	limiter.owner = owner;
+}
+
 VCMI_LIB_NAMESPACE_END

+ 32 - 6
lib/bonuses/Updaters.h

@@ -14,6 +14,17 @@
 
 VCMI_LIB_NAMESPACE_BEGIN
 
+class AggregateLimiter;
+class CCreatureTypeLimiter;
+class HasAnotherBonusLimiter;
+class CreatureTerrainLimiter;
+class CreatureLevelLimiter;
+class FactionLimiter;
+class CreatureAlignmentLimiter;
+class OppositeSideLimiter;
+class RankRangeLimiter;
+class UnitOnHexLimiter;
+
 // observers for updating bonuses based on certain events (e.g. hero gaining level)
 
 class DLL_LINKAGE IUpdater : public Serializeable
@@ -21,10 +32,21 @@ 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) const;
+	virtual std::shared_ptr<Bonus> createUpdatedBonus(const std::shared_ptr<Bonus> & b, const CBonusSystemNode & context);
 	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)
 	{
 	}
@@ -46,7 +68,7 @@ public:
 		h & stepSize;
 	}
 
-	std::shared_ptr<Bonus> createUpdatedBonus(const std::shared_ptr<Bonus> & b, const CBonusSystemNode & context) const override;
+	std::shared_ptr<Bonus> createUpdatedBonus(const std::shared_ptr<Bonus> & b, const CBonusSystemNode & context) override;
 	std::string toString() const override;
 	JsonNode toJsonNode() const override;
 };
@@ -59,7 +81,7 @@ public:
 		h & static_cast<IUpdater &>(*this);
 	}
 
-	std::shared_ptr<Bonus> createUpdatedBonus(const std::shared_ptr<Bonus> & b, const CBonusSystemNode & context) const override;
+	std::shared_ptr<Bonus> createUpdatedBonus(const std::shared_ptr<Bonus> & b, const CBonusSystemNode & context) override;
 	std::string toString() const override;
 	JsonNode toJsonNode() const override;
 };
@@ -72,7 +94,7 @@ public:
 		h & static_cast<IUpdater &>(*this);
 	}
 
-	std::shared_ptr<Bonus> createUpdatedBonus(const std::shared_ptr<Bonus> & b, const CBonusSystemNode & context) const override;
+	std::shared_ptr<Bonus> createUpdatedBonus(const std::shared_ptr<Bonus> & b, const CBonusSystemNode & context) override;
 	std::string toString() const override;
 	JsonNode toJsonNode() const override;
 };
@@ -95,22 +117,26 @@ public:
 		h & max;
 	}
 
-	std::shared_ptr<Bonus> createUpdatedBonus(const std::shared_ptr<Bonus> & b, const CBonusSystemNode & context) const override;
+	std::shared_ptr<Bonus> createUpdatedBonus(const std::shared_ptr<Bonus> & b, const CBonusSystemNode & context) 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) const override;
+	std::shared_ptr<Bonus> createUpdatedBonus(const std::shared_ptr<Bonus>& b, const CBonusSystemNode& context) override;
 	std::string toString() const override;
 	JsonNode toJsonNode() const override;
+	void visitLimiter(OppositeSideLimiter& limiter) override;
 };
 
 VCMI_LIB_NAMESPACE_END