1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

vcmi: add sourceType to HasAnotherBonusLimiter

Now we can filter bonuses by sourceType, hence,
checking, for example, specific secondary skills.

Also fix archery artifacts working without Archery skill.
This commit is contained in:
Konstantin 2023-03-02 00:54:10 +03:00
parent 7e9a15c20b
commit a943d2cb12
4 changed files with 102 additions and 10 deletions

View File

@ -915,7 +915,20 @@
"subtype" : "skill.archery", "subtype" : "skill.archery",
"type" : "SECONDARY_SKILL_PREMY", "type" : "SECONDARY_SKILL_PREMY",
"val" : 5, "val" : 5,
"valueType" : "ADDITIVE_VALUE" "valueType" : "ADDITIVE_VALUE",
"limiters" : [
{
"type" : "HAS_ANOTHER_BONUS_LIMITER",
"parameters" : [
"PERCENTAGE_DAMAGE_BOOST",
1,
{
"type" : "SECONDARY_SKILL",
"id" : "skill.archery"
}
]
}
]
} }
], ],
"index" : 60, "index" : 60,
@ -928,7 +941,20 @@
"subtype" : "skill.archery", "subtype" : "skill.archery",
"type" : "SECONDARY_SKILL_PREMY", "type" : "SECONDARY_SKILL_PREMY",
"val" : 10, "val" : 10,
"valueType" : "ADDITIVE_VALUE" "valueType" : "ADDITIVE_VALUE",
"limiters" : [
{
"type" : "HAS_ANOTHER_BONUS_LIMITER",
"parameters" : [
"PERCENTAGE_DAMAGE_BOOST",
1,
{
"type" : "SECONDARY_SKILL",
"id" : "skill.archery"
}
]
}
]
} }
], ],
"index" : 61, "index" : 61,
@ -941,7 +967,20 @@
"subtype" : "skill.archery", "subtype" : "skill.archery",
"type" : "SECONDARY_SKILL_PREMY", "type" : "SECONDARY_SKILL_PREMY",
"val" : 15, "val" : 15,
"valueType" : "ADDITIVE_VALUE" "valueType" : "ADDITIVE_VALUE",
"limiters" : [
{
"type" : "HAS_ANOTHER_BONUS_LIMITER",
"parameters" : [
"PERCENTAGE_DAMAGE_BOOST",
1,
{
"type" : "SECONDARY_SKILL",
"id" : "skill.archery"
}
]
}
]
} }
], ],
"index" : 62, "index" : 62,

View File

@ -2044,20 +2044,36 @@ JsonNode CCreatureTypeLimiter::toJsonNode() const
} }
HasAnotherBonusLimiter::HasAnotherBonusLimiter( Bonus::BonusType bonus ) HasAnotherBonusLimiter::HasAnotherBonusLimiter( Bonus::BonusType bonus )
: type(bonus), subtype(0), isSubtypeRelevant(false) : type(bonus), subtype(0), isSubtypeRelevant(false), isSourceRelevant(false), isSourceIDRelevant(false)
{ {
} }
HasAnotherBonusLimiter::HasAnotherBonusLimiter( Bonus::BonusType bonus, TBonusSubtype _subtype ) HasAnotherBonusLimiter::HasAnotherBonusLimiter( Bonus::BonusType bonus, TBonusSubtype _subtype )
: type(bonus), subtype(_subtype), isSubtypeRelevant(true) : type(bonus), subtype(_subtype), isSubtypeRelevant(true), isSourceRelevant(false), isSourceIDRelevant(false)
{
}
HasAnotherBonusLimiter::HasAnotherBonusLimiter(Bonus::BonusType bonus, Bonus::BonusSource src)
: type(bonus), source(src), isSubtypeRelevant(false), isSourceRelevant(true), isSourceIDRelevant(false)
{
}
HasAnotherBonusLimiter::HasAnotherBonusLimiter(Bonus::BonusType bonus, TBonusSubtype _subtype, Bonus::BonusSource src)
: type(bonus), subtype(_subtype), isSubtypeRelevant(true), source(src), isSourceRelevant(true), isSourceIDRelevant(false)
{ {
} }
int HasAnotherBonusLimiter::limit(const BonusLimitationContext &context) const int HasAnotherBonusLimiter::limit(const BonusLimitationContext &context) const
{ {
CSelector mySelector = isSubtypeRelevant //TODO: proper selector config with parsing of JSON
? Selector::typeSubtype(type, subtype) auto mySelector = Selector::type()(type);
: Selector::type()(type);
if(isSubtypeRelevant)
mySelector = mySelector.And(Selector::subtype()(subtype));
if(isSourceRelevant && isSourceIDRelevant)
mySelector = mySelector.And(Selector::source(source, sid));
else if (isSourceRelevant)
mySelector = mySelector.And(Selector::sourceTypeSel(source));
//if we have a bonus of required type accepted, limiter should accept also this bonus //if we have a bonus of required type accepted, limiter should accept also this bonus
if(context.alreadyAccepted.getFirst(mySelector)) if(context.alreadyAccepted.getFirst(mySelector))
@ -2092,11 +2108,14 @@ JsonNode HasAnotherBonusLimiter::toJsonNode() const
{ {
JsonNode root(JsonNode::JsonType::DATA_STRUCT); JsonNode root(JsonNode::JsonType::DATA_STRUCT);
std::string typeName = vstd::findKey(bonusNameMap, type); std::string typeName = vstd::findKey(bonusNameMap, type);
auto sourceTypeName = vstd::findKey(bonusSourceMap, source);
root["type"].String() = "HAS_ANOTHER_BONUS_LIMITER"; root["type"].String() = "HAS_ANOTHER_BONUS_LIMITER";
root["parameters"].Vector().push_back(JsonUtils::stringNode(typeName)); root["parameters"].Vector().push_back(JsonUtils::stringNode(typeName));
if(isSubtypeRelevant) if(isSubtypeRelevant)
root["parameters"].Vector().push_back(JsonUtils::intNode(subtype)); root["parameters"].Vector().push_back(JsonUtils::intNode(subtype));
if(isSourceRelevant)
root["parameters"].Vector().push_back(JsonUtils::stringNode(sourceTypeName));
return root; return root;
} }

View File

@ -1052,10 +1052,16 @@ class DLL_LINKAGE HasAnotherBonusLimiter : public ILimiter //applies only to nod
public: public:
Bonus::BonusType type; Bonus::BonusType type;
TBonusSubtype subtype; TBonusSubtype subtype;
Bonus::BonusSource source;
si32 sid;
bool isSubtypeRelevant; //check for subtype only if this is true bool isSubtypeRelevant; //check for subtype only if this is true
bool isSourceRelevant; //check for bonus source only if this is true
bool isSourceIDRelevant; //check for bonus source only if this is true
HasAnotherBonusLimiter(Bonus::BonusType bonus = Bonus::NONE); HasAnotherBonusLimiter(Bonus::BonusType bonus = Bonus::NONE);
HasAnotherBonusLimiter(Bonus::BonusType bonus, TBonusSubtype _subtype); HasAnotherBonusLimiter(Bonus::BonusType bonus, TBonusSubtype _subtype);
HasAnotherBonusLimiter(Bonus::BonusType bonus, Bonus::BonusSource src);
HasAnotherBonusLimiter(Bonus::BonusType bonus, TBonusSubtype _subtype, Bonus::BonusSource src);
int limit(const BonusLimitationContext &context) const override; int limit(const BonusLimitationContext &context) const override;
virtual std::string toString() const override; virtual std::string toString() const override;
@ -1067,6 +1073,10 @@ public:
h & type; h & type;
h & subtype; h & subtype;
h & isSubtypeRelevant; h & isSubtypeRelevant;
h & source;
h & isSourceRelevant;
h & sid;
h & isSourceIDRelevant;
} }
}; };

View File

@ -708,10 +708,34 @@ std::shared_ptr<ILimiter> JsonUtils::parseLimiter(const JsonNode & limiter)
{ {
std::shared_ptr<HasAnotherBonusLimiter> bonusLimiter = std::make_shared<HasAnotherBonusLimiter>(); std::shared_ptr<HasAnotherBonusLimiter> bonusLimiter = std::make_shared<HasAnotherBonusLimiter>();
bonusLimiter->type = it->second; bonusLimiter->type = it->second;
auto findSource = [&](const JsonNode & parameter)
{
if(parameter.getType() == JsonNode::JsonType::DATA_STRUCT)
{
auto sourceIt = bonusSourceMap.find(parameter["type"].String());
if(sourceIt != bonusSourceMap.end())
{
bonusLimiter->source = sourceIt->second;
bonusLimiter->isSourceRelevant = true;
if(!parameter["id"].isNull()) {
resolveIdentifier(parameter["id"], bonusLimiter->sid);
bonusLimiter->isSourceIDRelevant = true;
}
}
}
return false;
};
if(parameters.size() > 1) if(parameters.size() > 1)
{ {
resolveIdentifier(parameters[1], bonusLimiter->subtype); if(findSource(parameters[1]) && parameters.size() == 2)
bonusLimiter->isSubtypeRelevant = true; return bonusLimiter;
else
{
resolveIdentifier(parameters[1], bonusLimiter->subtype);
bonusLimiter->isSubtypeRelevant = true;
if(parameters.size() > 2)
findSource(parameters[2]);
}
} }
return bonusLimiter; return bonusLimiter;
} }