From bbe6c415c25202e0eb7b82e6f98dfd2ed663131f Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Wed, 11 Jun 2025 14:15:30 +0300 Subject: [PATCH] Add TIMES_STACK_SIZE updater --- lib/bonuses/Updaters.cpp | 38 +++++++++++++++++++++++++++++++++++++- lib/bonuses/Updaters.h | 28 ++++++++++++++++++++++++++++ lib/json/JsonBonus.cpp | 27 ++++++++++++++++++++++----- 3 files changed, 87 insertions(+), 6 deletions(-) diff --git a/lib/bonuses/Updaters.cpp b/lib/bonuses/Updaters.cpp index 326cc4275..778e87ac7 100644 --- a/lib/bonuses/Updaters.cpp +++ b/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 TimesStackSizeUpdater::apply(const std::shared_ptr & b, int count) const +{ + auto newBonus = std::make_shared(*b); + newBonus->val *= std::clamp(count / stepSize, minimum, maximum); + newBonus->updater = nullptr; // prevent double-apply + return newBonus; +} + +std::shared_ptr TimesStackSizeUpdater::createUpdatedBonus(const std::shared_ptr & b, const CBonusSystemNode & context) const +{ + if(context.getNodeType() == CBonusSystemNode::STACK_INSTANCE || context.getNodeType() == CBonusSystemNode::COMMANDER) + { + int count = dynamic_cast(context).getCount(); + return apply(b, count); + } + + if(context.getNodeType() == CBonusSystemNode::STACK_BATTLE) + { + const auto & stack = dynamic_cast(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 TimesStackLevelUpdater::apply(const std::shared_ptr & b, int level) const { auto newBonus = std::make_shared(*b); diff --git a/lib/bonuses/Updaters.h b/lib/bonuses/Updaters.h index 962914182..f79bb4322 100644 --- a/lib/bonuses/Updaters.h +++ b/lib/bonuses/Updaters.h @@ -85,6 +85,34 @@ public: JsonNode toJsonNode() const override; }; +class DLL_LINKAGE TimesStackSizeUpdater : public IUpdater +{ + std::shared_ptr apply(const std::shared_ptr & 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 createUpdatedBonus(const std::shared_ptr & b, const CBonusSystemNode & context) const override; + std::string toString() const override; + JsonNode toJsonNode() const override; + + template void serialize(Handler & h) + { + h & static_cast(*this); + h & minimum; + h & maximum; + h & stepSize; + } +}; + class DLL_LINKAGE TimesStackLevelUpdater : public IUpdater { std::shared_ptr apply(const std::shared_ptr & b, int level) const; diff --git a/lib/json/JsonBonus.cpp b/lib/json/JsonBonus.cpp index ab0656610..0d7ef2866 100644 --- a/lib/json/JsonBonus.cpp +++ b/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(); + // MOD COMPATIBILITY - parameters is deprecated in 1.7 const JsonVector param = updaterJson["parameters"].Vector(); - updater->valPer20 = static_cast(param[0].Integer()); - if(param.size() > 1) - updater->stepSize = static_cast(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(valPer20, std::max(1, stepSize)); + } + if(updaterJson["type"].String() == "TIMES_HERO_LEVEL") + { + int stepSize = updaterJson["stepSize"].Integer(); + return std::make_shared(std::max(1, stepSize)); + } + if(updaterJson["type"].String() == "TIMES_STACK_SIZE") + { + int minimum = updaterJson["minimum"].isNull() ? std::numeric_limits::min() : updaterJson["minimum"].Integer(); + int maximum = updaterJson["maximum"].isNull() ? std::numeric_limits::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(maximum, minimum, std::max(1, stepSize)); + } + return std::make_shared(minimum, maximum, std::max(1, stepSize)); } else logMod->warn("Unknown updater type \"%s\"", updaterJson["type"].String());