浏览代码

vcmi: add UnitOnHex limiter

Bonus will be accepted, if unit stands in listed hexes
Konstantin 2 年之前
父节点
当前提交
4c08e6a0f9
共有 4 个文件被更改,包括 61 次插入1 次删除
  1. 31 1
      lib/HeroBonus.cpp
  2. 17 0
      lib/HeroBonus.h
  3. 12 0
      lib/JsonNode.cpp
  4. 1 0
      lib/registerTypes/RegisterTypes.h

+ 31 - 1
lib/HeroBonus.cpp

@@ -76,7 +76,8 @@ 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>()},
-	{"OPPOSITE_SIDE", std::make_shared<OppositeSideLimiter>()}
+	{"OPPOSITE_SIDE", std::make_shared<OppositeSideLimiter>()},
+	{"UNIT_ON_HEXES", std::make_shared<UnitOnHexLimiter>()}
 };
 
 const std::map<std::string, TPropagatorPtr> bonusPropagatorMap =
@@ -2268,6 +2269,35 @@ JsonNode HasAnotherBonusLimiter::toJsonNode() const
 	return root;
 }
 
+ILimiter::EDecision UnitOnHexLimiter::limit(const BonusLimitationContext &context) const
+{
+	const auto * stack = retrieveStackBattle(&context.node);
+	if(!stack)
+		return ILimiter::EDecision::DISCARD;
+
+	auto accept = false;
+	for (const auto & hex : stack->getHexes())
+		accept |= !!applicableHexes.count(hex);
+
+	return accept ? ILimiter::EDecision::ACCEPT : ILimiter::EDecision::DISCARD;
+}
+
+UnitOnHexLimiter::UnitOnHexLimiter(const std::set<BattleHex> & applicableHexes):
+	applicableHexes(applicableHexes)
+{
+}
+
+JsonNode UnitOnHexLimiter::toJsonNode() const
+{
+	JsonNode root(JsonNode::JsonType::DATA_STRUCT);
+
+	root["type"].String() = "UNIT_ON_HEXES";
+	for(const auto & hex : applicableHexes)
+		root["parameters"].Vector().push_back(JsonUtils::intNode(hex));
+
+	return root;
+}
+
 bool IPropagator::shouldBeAttached(CBonusSystemNode *dest)
 {
 	return false;

+ 17 - 0
lib/HeroBonus.h

@@ -11,6 +11,7 @@
 
 #include "GameConstants.h"
 #include "JsonNode.h"
+#include "battle/BattleHex.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 
@@ -1191,6 +1192,22 @@ public:
 	}
 };
 
+class DLL_LINKAGE UnitOnHexLimiter : public ILimiter //works only on selected hexes
+{
+public:
+	std::set<BattleHex> applicableHexes;
+
+	UnitOnHexLimiter(const std::set<BattleHex> & applicableHexes = {});
+	EDecision limit(const BonusLimitationContext &context) const override;
+	JsonNode toJsonNode() const override;
+
+	template <typename Handler> void serialize(Handler &h, const int version)
+	{
+		h & static_cast<ILimiter&>(*this);
+		h & applicableHexes;
+	}
+};
+
 namespace Selector
 {
 	extern DLL_LINKAGE CSelectFieldEqual<Bonus::BonusType> & type();

+ 12 - 0
lib/JsonNode.cpp

@@ -20,6 +20,7 @@
 #include "CGeneralTextHandler.h"
 #include "JsonDetail.h"
 #include "StringConstants.h"
+#include "battle/BattleHex.h"
 
 namespace
 {
@@ -770,6 +771,17 @@ std::shared_ptr<ILimiter> JsonUtils::parseLimiter(const JsonNode & limiter)
 				}
 				return terrainLimiter;
 			}
+			else if(limiterType == "UNIT_ON_HEXES") {
+				auto hexLimiter = std::make_shared<UnitOnHexLimiter>();
+				if(!parameters.empty())
+				{
+					for (const auto & parameter: parameters){
+						if(parameter.isNumber())
+							hexLimiter->applicableHexes.insert(BattleHex(parameter.Integer()));
+					}
+				}
+				return hexLimiter;
+			}
 			else
 			{
 				logMod->error("Error: invalid customizable limiter type %s.", limiterType);

+ 1 - 0
lib/registerTypes/RegisterTypes.h

@@ -183,6 +183,7 @@ void registerTypesMapObjects2(Serializer &s)
 	s.template registerType<ILimiter, CreatureAlignmentLimiter>();
 	s.template registerType<ILimiter, RankRangeLimiter>();
 	s.template registerType<ILimiter, StackOwnerLimiter>();
+	s.template registerType<ILimiter, UnitOnHexLimiter>();
 
 //	s.template registerType<CBonusSystemNode>();
 	s.template registerType<CBonusSystemNode, CArtifact>();