From 1760d2295cd6344f79c8a69a66145b6b1cb745e3 Mon Sep 17 00:00:00 2001 From: Konstantin <ria.freelander@gmail.com> Date: Thu, 6 Apr 2023 18:28:02 +0300 Subject: [PATCH] HeroBonus: add CreatureLevelLimiter --- lib/HeroBonus.cpp | 32 +++++++++++++++++++++++++++++++ lib/HeroBonus.h | 21 ++++++++++++++++++++ lib/JsonNode.cpp | 11 +++++++++++ lib/mapObjects/JsonRandom.h | 2 +- lib/registerTypes/RegisterTypes.h | 1 + 5 files changed, 66 insertions(+), 1 deletion(-) diff --git a/lib/HeroBonus.cpp b/lib/HeroBonus.cpp index 28b4f717e..9badb95ca 100644 --- a/lib/HeroBonus.cpp +++ b/lib/HeroBonus.cpp @@ -76,6 +76,7 @@ const std::map<std::string, TLimiterPtr> bonusLimiterMap = {"IS_UNDEAD", std::make_shared<HasAnotherBonusLimiter>(Bonus::UNDEAD)}, {"CREATURE_NATIVE_TERRAIN", std::make_shared<CreatureTerrainLimiter>()}, {"CREATURE_FACTION", std::make_shared<CreatureFactionLimiter>()}, + {"CREATURE_LEVEL", std::make_shared<CreatureLevelLimiter>()}, {"OPPOSITE_SIDE", std::make_shared<OppositeSideLimiter>()}, {"UNIT_ON_HEXES", std::make_shared<UnitOnHexLimiter>()} }; @@ -2401,6 +2402,37 @@ JsonNode CreatureFactionLimiter::toJsonNode() const return root; } +CreatureLevelLimiter::CreatureLevelLimiter(uint32_t minLevel, uint32_t maxLevel) : + minLevel(minLevel), + maxLevel(maxLevel) +{ +} + +ILimiter::EDecision CreatureLevelLimiter::limit(const BonusLimitationContext &context) const +{ + const auto *c = retrieveCreature(&context.node); + auto accept = c && (c->getLevel() < maxLevel && c->getLevel() >= minLevel); + return accept ? ILimiter::EDecision::ACCEPT : ILimiter::EDecision::DISCARD; //drop bonus for non-creatures or non-native residents +} + +std::string CreatureLevelLimiter::toString() const +{ + boost::format fmt("CreatureLevelLimiter(minLevel=%d,maxLevel=%d)"); + fmt % minLevel % maxLevel; + return fmt.str(); +} + +JsonNode CreatureLevelLimiter::toJsonNode() const +{ + JsonNode root(JsonNode::JsonType::DATA_STRUCT); + + root["type"].String() = "CREATURE_LEVEL_LIMITER"; + root["parameters"].Vector().push_back(JsonUtils::intNode(minLevel)); + root["parameters"].Vector().push_back(JsonUtils::intNode(maxLevel)); + + return root; +} + CreatureAlignmentLimiter::CreatureAlignmentLimiter(EAlignment Alignment) : alignment(Alignment) { diff --git a/lib/HeroBonus.h b/lib/HeroBonus.h index b1ecc435b..8e8d55ff5 100644 --- a/lib/HeroBonus.h +++ b/lib/HeroBonus.h @@ -12,6 +12,7 @@ #include "GameConstants.h" #include "JsonNode.h" #include "battle/BattleHex.h" +#include <limits> VCMI_LIB_NAMESPACE_BEGIN @@ -1106,6 +1107,26 @@ public: } }; +class DLL_LINKAGE CreatureLevelLimiter : public ILimiter //applies only to creatures of given faction +{ +public: + uint32_t minLevel; + uint32_t maxLevel; + //accept all levels by default, accept creatures of minLevel <= creature->getLevel() < maxLevel + CreatureLevelLimiter(uint32_t minLevel = std::numeric_limits<uint32_t>::min(), uint32_t maxLevel = std::numeric_limits<uint32_t>::max()); + + EDecision limit(const BonusLimitationContext &context) const override; + std::string toString() const override; + JsonNode toJsonNode() const override; + + template <typename Handler> void serialize(Handler &h, const int version) + { + h & static_cast<ILimiter&>(*this); + h & minLevel; + h & maxLevel; + } +}; + class DLL_LINKAGE CreatureFactionLimiter : public ILimiter //applies only to creatures of given faction { public: diff --git a/lib/JsonNode.cpp b/lib/JsonNode.cpp index 37f80199f..fc2bdce52 100644 --- a/lib/JsonNode.cpp +++ b/lib/JsonNode.cpp @@ -758,6 +758,17 @@ std::shared_ptr<ILimiter> JsonUtils::parseLimiter(const JsonNode & limiter) }); return factionLimiter; } + else if(limiterType == "CREATURE_LEVEL_LIMITER") + { + auto levelLimiter = std::make_shared<CreatureLevelLimiter>(); + if(!parameters.empty()) //If parameters is empty, level limiter works as CREATURES_ONLY limiter + { + levelLimiter->minLevel = parameters[0].Integer(); + if(parameters[1].isNumber()) + levelLimiter->maxLevel = parameters[1].Integer(); + } + return levelLimiter; + } else if(limiterType == "CREATURE_TERRAIN_LIMITER") { std::shared_ptr<CreatureTerrainLimiter> terrainLimiter = std::make_shared<CreatureTerrainLimiter>(); diff --git a/lib/mapObjects/JsonRandom.h b/lib/mapObjects/JsonRandom.h index ee0dd6299..3b1d016eb 100644 --- a/lib/mapObjects/JsonRandom.h +++ b/lib/mapObjects/JsonRandom.h @@ -15,7 +15,7 @@ VCMI_LIB_NAMESPACE_BEGIN class JsonNode; -typedef std::vector<JsonNode> JsonVector; +using JsonVector = std::vector<JsonNode>; class CRandomGenerator; struct Bonus; diff --git a/lib/registerTypes/RegisterTypes.h b/lib/registerTypes/RegisterTypes.h index 2add5fc3f..8e670cd00 100644 --- a/lib/registerTypes/RegisterTypes.h +++ b/lib/registerTypes/RegisterTypes.h @@ -180,6 +180,7 @@ void registerTypesMapObjects2(Serializer &s) s.template registerType<ILimiter, HasAnotherBonusLimiter>(); s.template registerType<ILimiter, CreatureTerrainLimiter>(); s.template registerType<ILimiter, CreatureFactionLimiter>(); + s.template registerType<ILimiter, CreatureLevelLimiter>(); s.template registerType<ILimiter, CreatureAlignmentLimiter>(); s.template registerType<ILimiter, RankRangeLimiter>(); s.template registerType<ILimiter, StackOwnerLimiter>();