浏览代码

Add TIMES_STACK_SIZE updater

Ivan Savenko 4 月之前
父节点
当前提交
bbe6c415c2
共有 3 个文件被更改,包括 87 次插入6 次删除
  1. 37 1
      lib/bonuses/Updaters.cpp
  2. 28 0
      lib/bonuses/Updaters.h
  3. 22 5
      lib/json/JsonBonus.cpp

+ 37 - 1
lib/bonuses/Updaters.cpp

@@ -33,7 +33,9 @@ JsonNode IUpdater::toJsonNode() const
 	return JsonNode();
 }
 
-GrowsWithLevelUpdater::GrowsWithLevelUpdater(int valPer20, int stepSize) : valPer20(valPer20), stepSize(stepSize)
+GrowsWithLevelUpdater::GrowsWithLevelUpdater(int valPer20, int stepSize)
+	: valPer20(valPer20)
+	, stepSize(stepSize)
 {
 }
 
@@ -113,6 +115,40 @@ JsonNode TimesHeroLevelDivideStackLevelUpdater::toJsonNode() const
 	return JsonNode("TIMES_HERO_LEVEL_DIVIDE_STACK_LEVEL");
 }
 
+std::shared_ptr<Bonus> TimesStackSizeUpdater::apply(const std::shared_ptr<Bonus> & b, int count) const
+{
+	auto newBonus = std::make_shared<Bonus>(*b);
+	newBonus->val *= std::clamp(count / stepSize, minimum, maximum);
+	newBonus->updater = nullptr; // prevent double-apply
+	return newBonus;
+}
+
+std::shared_ptr<Bonus> TimesStackSizeUpdater::createUpdatedBonus(const std::shared_ptr<Bonus> & b, const CBonusSystemNode & context) const
+{
+	if(context.getNodeType() == CBonusSystemNode::STACK_INSTANCE || context.getNodeType() == CBonusSystemNode::COMMANDER)
+	{
+		int count = dynamic_cast<const CStackInstance &>(context).getCount();
+		return apply(b, count);
+	}
+
+	if(context.getNodeType() == CBonusSystemNode::STACK_BATTLE)
+	{
+		const auto & stack = dynamic_cast<const CStack &>(context);
+		return apply(b, stack.getCount());
+	}
+	return b;
+}
+
+std::string TimesStackSizeUpdater::toString() const
+{
+	return "TimesStackSizeUpdater";
+}
+
+JsonNode TimesStackSizeUpdater::toJsonNode() const
+{
+	return JsonNode("TIMES_STACK_SIZE");
+}
+
 std::shared_ptr<Bonus> TimesStackLevelUpdater::apply(const std::shared_ptr<Bonus> & b, int level) const
 {
 	auto newBonus = std::make_shared<Bonus>(*b);

+ 28 - 0
lib/bonuses/Updaters.h

@@ -85,6 +85,34 @@ public:
 	JsonNode toJsonNode() const override;
 };
 
+class DLL_LINKAGE TimesStackSizeUpdater : public IUpdater
+{
+	std::shared_ptr<Bonus> apply(const std::shared_ptr<Bonus> & b, int count) const;
+
+	int minimum;
+	int maximum;
+	int stepSize;
+public:
+	TimesStackSizeUpdater() = default;
+	TimesStackSizeUpdater(int minimum, int maximum, int stepSize)
+		: minimum(minimum)
+		, maximum(maximum)
+		, stepSize(stepSize)
+	{}
+
+	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;
+
+	template <typename Handler> void serialize(Handler & h)
+	{
+		h & static_cast<IUpdater &>(*this);
+		h & minimum;
+		h & maximum;
+		h & stepSize;
+	}
+};
+
 class DLL_LINKAGE TimesStackLevelUpdater : public IUpdater
 {
 	std::shared_ptr<Bonus> apply(const std::shared_ptr<Bonus> & b, int level) const;

+ 22 - 5
lib/json/JsonBonus.cpp

@@ -396,12 +396,29 @@ static TUpdaterPtr parseUpdater(const JsonNode & updaterJson)
 	case JsonNode::JsonType::DATA_STRUCT:
 		if(updaterJson["type"].String() == "GROWS_WITH_LEVEL")
 		{
-			auto updater = std::make_shared<GrowsWithLevelUpdater>();
+			// MOD COMPATIBILITY - parameters is deprecated in 1.7
 			const JsonVector param = updaterJson["parameters"].Vector();
-			updater->valPer20 = static_cast<int>(param[0].Integer());
-			if(param.size() > 1)
-				updater->stepSize = static_cast<int>(param[1].Integer());
-			return updater;
+			int valPer20 = updaterJson["valPer20"].isNull() ? param[0].Integer() : updaterJson["valPer20"].Integer();
+			int stepSize = updaterJson["stepSize"].isNull() ? param[1].Integer() : updaterJson["stepSize"].Integer();
+
+			return std::make_shared<GrowsWithLevelUpdater>(valPer20, std::max(1, stepSize));
+		}
+		if(updaterJson["type"].String() == "TIMES_HERO_LEVEL")
+		{
+			int stepSize = updaterJson["stepSize"].Integer();
+			return std::make_shared<TimesHeroLevelUpdater>(std::max(1, stepSize));
+		}
+		if(updaterJson["type"].String() == "TIMES_STACK_SIZE")
+		{
+			int minimum = updaterJson["minimum"].isNull() ? std::numeric_limits<int>::min() : updaterJson["minimum"].Integer();
+			int maximum = updaterJson["maximum"].isNull() ? std::numeric_limits<int>::max() : updaterJson["maximum"].Integer();
+			int stepSize = updaterJson["stepSize"].Integer();
+			if (minimum > maximum)
+			{
+				logMod->warn("TIMES_STACK_SIZE updater: minimum value (%d) is above maximum value(%d)!", minimum, maximum);
+				return std::make_shared<TimesStackSizeUpdater>(maximum, minimum, std::max(1, stepSize));
+			}
+			return std::make_shared<TimesStackSizeUpdater>(minimum, maximum, std::max(1, stepSize));
 		}
 		else
 			logMod->warn("Unknown updater type \"%s\"", updaterJson["type"].String());