1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-11-24 08:32:34 +02:00

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.
This commit is contained in:
Konstantin 2023-03-09 02:20:21 +03:00
parent 0540e1531d
commit 1e7875cb36
2 changed files with 61 additions and 12 deletions

View File

@ -57,22 +57,34 @@ protected:
virtual bool check(const Mechanics * m, const battle::Unit * target) const = 0;
};
class BonusCondition : public TargetConditionItemBase
class SelectorCondition : public TargetConditionItemBase
{
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:
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:
BonusTypeID type;
CSelector sel;
si32 minVal = std::numeric_limits<si32>::min();
si32 maxVal = std::numeric_limits<si32>::max();
};
class CreatureCondition : public TargetConditionItemBase
@ -318,8 +330,16 @@ public:
auto it = bonusNameMap.find(identifier);
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);
}
else if(type == "creature")
@ -352,6 +372,26 @@ public:
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
{
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;
else if(value.String() == "normal")
isAbsolute = false;
else if(value.isStruct()) //assume conditions have a new struct format
isAbsolute = value["absolute"].Bool();
else
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)
{

View File

@ -51,6 +51,7 @@ public:
virtual Object createNormalSpell() 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 createImmunityNegation() const = 0;