Преглед на файлове

vcmi: selector-based target conditions

For now, allows us to define target conditions by selector and even
by minimal and maximal value of bonuses. Convert Bonus condition
to Selector condition.
Allow structures inside TargetCondition struct.
Konstantin преди 2 години
родител
ревизия
1e7875cb36
променени са 2 файла, в които са добавени 61 реда и са изтрити 12 реда
  1. 60 12
      lib/spells/TargetCondition.cpp
  2. 1 0
      lib/spells/TargetCondition.h

+ 60 - 12
lib/spells/TargetCondition.cpp

@@ -57,22 +57,34 @@ protected:
 	virtual bool check(const Mechanics * m, const battle::Unit * target) const = 0;
 	virtual bool check(const Mechanics * m, const battle::Unit * target) const = 0;
 };
 };
 
 
-class BonusCondition : public TargetConditionItemBase
+class SelectorCondition : public TargetConditionItemBase
 {
 {
 public:
 public:
-	BonusCondition(BonusTypeID type_)
-		: type(type_)
+	SelectorCondition(const CSelector & csel):
+		sel(csel)
+	{
+	}
+	SelectorCondition(const CSelector & csel, si32 minVal, si32 maxVal):
+		sel(csel),
+		minVal(minVal),
+		maxVal(maxVal)
 	{
 	{
 	}
 	}
 
 
 protected:
 protected:
 	bool check(const Mechanics * m, const battle::Unit * target) const override
 	bool check(const Mechanics * m, const battle::Unit * target) const override
 	{
 	{
-		return target->hasBonus(Selector::type()(type));
+		if(target->hasBonus(sel)) {
+			auto b = target->valOfBonuses(sel,"");
+			return b >= minVal && b <= maxVal;
+		}
+		return false;
 	}
 	}
 
 
 private:
 private:
-	BonusTypeID type;
+	CSelector sel;
+	si32 minVal = std::numeric_limits<si32>::min();
+	si32 maxVal = std::numeric_limits<si32>::max();
 };
 };
 
 
 class CreatureCondition : public TargetConditionItemBase
 class CreatureCondition : public TargetConditionItemBase
@@ -318,8 +330,16 @@ public:
 
 
 			auto it = bonusNameMap.find(identifier);
 			auto it = bonusNameMap.find(identifier);
 			if(it != bonusNameMap.end())
 			if(it != bonusNameMap.end())
-				return std::make_shared<BonusCondition>(it->second);
-			else
+				return std::make_shared<SelectorCondition>(Selector::type()(it->second));
+			
+			auto params = BonusParams(identifier, "", -1);
+			if(params.isConverted)
+			{
+				if(params.valRelevant)
+					return std::make_shared<SelectorCondition>(params.toSelector(), params.val, params.val);
+				return std::make_shared<SelectorCondition>(params.toSelector());
+			}
+
 				logMod->error("Invalid bonus type %s in spell target condition.", identifier);
 				logMod->error("Invalid bonus type %s in spell target condition.", identifier);
 		}
 		}
 		else if(type == "creature")
 		else if(type == "creature")
@@ -352,6 +372,26 @@ public:
 		return Object();
 		return Object();
 	}
 	}
 
 
+	Object createFromJsonStruct(const JsonNode & jsonStruct) const override
+	{	
+		auto type = jsonStruct["type"].String();
+		auto parameters = jsonStruct["parameters"];
+		if(type == "selector")
+		{
+			auto minVal = std::numeric_limits<si32>::min();
+			auto maxVal = std::numeric_limits<si32>::max();
+			if(parameters["minVal"].isNumber())
+				minVal = parameters["minVal"].Integer();
+			if(parameters["maxVal"].isNumber())
+				maxVal = parameters["maxVal"].Integer();
+			auto sel = JsonUtils::parseSelector(parameters);
+			return std::make_shared<SelectorCondition>(sel, minVal, maxVal);
+		}
+
+		logMod->error("Invalid type %s in spell target condition.", type);
+		return Object();
+	}
+
 	Object createReceptiveFeature() const override
 	Object createReceptiveFeature() const override
 	{
 	{
 		static std::shared_ptr<TargetConditionItem> condition = std::make_shared<ReceptiveFeatureCondition>();
 		static std::shared_ptr<TargetConditionItem> condition = std::make_shared<ReceptiveFeatureCondition>();
@@ -463,16 +503,24 @@ void TargetCondition::loadConditions(const JsonNode & source, bool exclusive, bo
 			isAbsolute = true;
 			isAbsolute = true;
 		else if(value.String() == "normal")
 		else if(value.String() == "normal")
 			isAbsolute = false;
 			isAbsolute = false;
+		else if(value.isStruct()) //assume conditions have a new struct format
+			isAbsolute = value["absolute"].Bool();
 		else
 		else
 			continue;
 			continue;
 
 
-		std::string scope;
-		std::string type;
-		std::string identifier;
+		std::shared_ptr<TargetConditionItem> item;
+		if(value.isStruct())
+			item = itemFactory->createFromJsonStruct(value);
+		else
+		{
+			std::string scope;
+			std::string type;
+			std::string identifier;
 
 
-		CModHandler::parseIdentifier(keyValue.first, scope, type, identifier);
+			CModHandler::parseIdentifier(keyValue.first, scope, type, identifier);
 
 
-		std::shared_ptr<TargetConditionItem> item = itemFactory->createConfigurable(scope, type, identifier);
+			std::shared_ptr<TargetConditionItem> item = itemFactory->createConfigurable(scope, type, identifier);
+		}
 
 
 		if(item)
 		if(item)
 		{
 		{

+ 1 - 0
lib/spells/TargetCondition.h

@@ -51,6 +51,7 @@ public:
 	virtual Object createNormalSpell() const = 0;
 	virtual Object createNormalSpell() const = 0;
 
 
 	virtual Object createConfigurable(std::string scope, std::string type, std::string identifier) const = 0;
 	virtual Object createConfigurable(std::string scope, std::string type, std::string identifier) const = 0;
+	virtual Object createFromJsonStruct(const JsonNode & jsonStruct) const = 0;
 
 
 	virtual Object createReceptiveFeature() const = 0;
 	virtual Object createReceptiveFeature() const = 0;
 	virtual Object createImmunityNegation() const = 0;
 	virtual Object createImmunityNegation() const = 0;