1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-11-23 22:37:55 +02:00

Fix parsing of HAS_ANOTHER_BONUS_LIMITER parameters

This commit is contained in:
Ivan Savenko
2025-06-17 16:56:01 +03:00
parent 3b6f93c365
commit da0841dc9c
2 changed files with 31 additions and 37 deletions

View File

@@ -28,8 +28,8 @@ Bonus is only active if affected entity has another bonus that meets conditions
Parameters: Parameters:
- Bonus type - Bonus type
- bonus subtype - Bonus subtype (only used if bonus type is set)
- bonus sourceType and sourceId in struct - Bonus source type and bonus source ID
All parameters are optional. Values that don't need checking can be replaces with `null` All parameters are optional. Values that don't need checking can be replaces with `null`
@@ -42,11 +42,11 @@ Examples:
{ {
"type" : "HAS_ANOTHER_BONUS_LIMITER", "type" : "HAS_ANOTHER_BONUS_LIMITER",
"parameters" : [ "parameters" : [
null, null, // bonus type is ignored
null, null, // bonus subtype is also ignored
{ {
"type" : "SPELL_EFFECT", "type" : "SPELL_EFFECT", // look for bonus of type SPELL_EFFECT
"id" : "spell.bless" "id" : "spell.bless" // ... from spell "Bless"
} }
] ]
} }

View File

@@ -502,7 +502,7 @@ std::shared_ptr<const ILimiter> JsonUtils::parseLimiter(const JsonNode & limiter
case JsonNode::JsonType::DATA_STRUCT: //customizable limiters case JsonNode::JsonType::DATA_STRUCT: //customizable limiters
{ {
std::string limiterType = limiter["type"].String(); std::string limiterType = limiter["type"].String();
const JsonVector & parameters = limiter["parameters"].Vector(); const JsonNode & parameters = limiter["parameters"];
if(limiterType == "CREATURE_TYPE_LIMITER") if(limiterType == "CREATURE_TYPE_LIMITER")
{ {
auto creatureLimiter = std::make_shared<CCreatureTypeLimiter>(); auto creatureLimiter = std::make_shared<CCreatureTypeLimiter>();
@@ -512,7 +512,7 @@ std::shared_ptr<const ILimiter> JsonUtils::parseLimiter(const JsonNode & limiter
}); });
auto includeUpgrades = false; auto includeUpgrades = false;
if(parameters.size() > 1) if(parameters.Vector().size() > 1)
{ {
bool success = true; bool success = true;
includeUpgrades = parameters[1].TryBoolFromString(success); includeUpgrades = parameters[1].TryBoolFromString(success);
@@ -527,43 +527,37 @@ std::shared_ptr<const ILimiter> JsonUtils::parseLimiter(const JsonNode & limiter
{ {
auto bonusLimiter = std::make_shared<HasAnotherBonusLimiter>(); auto bonusLimiter = std::make_shared<HasAnotherBonusLimiter>();
if (!parameters[0].isNull()) static const JsonNode nullNode;
const JsonNode & jsonType = parameters[0];
const JsonNode & jsonSubtype = parameters.Vector().size() > 2 ? parameters[1] : nullNode;
const JsonNode & jsonSource = parameters.Vector().size() > 2 ? parameters[2] : parameters[1];
if (!jsonType.isNull())
{ {
LIBRARY->identifiers()->requestIdentifier("bonus", parameters[0], [bonusLimiter](si32 bonusID) LIBRARY->identifiers()->requestIdentifier("bonus", jsonType, [bonusLimiter, jsonSubtype](si32 bonusID)
{ {
bonusLimiter->type = static_cast<BonusType>(bonusID); bonusLimiter->type = static_cast<BonusType>(bonusID);
if (jsonSubtype.isNull())
loadBonusSubtype(bonusLimiter->subtype, bonusLimiter->type, jsonSubtype);
}); });
} }
auto findSource = [&](const JsonNode & parameter) if(!jsonSource.isNull())
{ {
if(parameter.getType() == JsonNode::JsonType::DATA_STRUCT) auto sourceIt = bonusSourceMap.find(jsonSource["type"].String());
{
auto sourceIt = bonusSourceMap.find(parameter["type"].String());
if(sourceIt != bonusSourceMap.end()) if(sourceIt != bonusSourceMap.end())
{ {
bonusLimiter->source = sourceIt->second; bonusLimiter->source = sourceIt->second;
bonusLimiter->isSourceRelevant = true; bonusLimiter->isSourceRelevant = true;
if(!parameter["id"].isNull()) { if(!jsonSource["id"].isNull()) {
loadBonusSourceInstance(bonusLimiter->sid, bonusLimiter->source, parameter["id"]); loadBonusSourceInstance(bonusLimiter->sid, bonusLimiter->source, jsonSource["id"]);
bonusLimiter->isSourceIDRelevant = true; bonusLimiter->isSourceIDRelevant = true;
} }
} }
}
return false;
};
if(parameters.size() > 1)
{
if(findSource(parameters[1]) && parameters.size() == 2)
return bonusLimiter;
else else
{ logMod->warn("HAS_ANOTHER_BONUS_LIMITER: unknown bonus source type '%s'!", jsonSource["type"].String());
loadBonusSubtype(bonusLimiter->subtype, bonusLimiter->type, parameters[1]);
bonusLimiter->isSubtypeRelevant = true;
if(parameters.size() > 2)
findSource(parameters[2]);
}
} }
return bonusLimiter; return bonusLimiter;
} }
else if(limiterType == "CREATURE_ALIGNMENT_LIMITER") else if(limiterType == "CREATURE_ALIGNMENT_LIMITER")
@@ -586,7 +580,7 @@ std::shared_ptr<const ILimiter> JsonUtils::parseLimiter(const JsonNode & limiter
else if(limiterType == "CREATURE_LEVEL_LIMITER") else if(limiterType == "CREATURE_LEVEL_LIMITER")
{ {
auto levelLimiter = std::make_shared<CreatureLevelLimiter>(); auto levelLimiter = std::make_shared<CreatureLevelLimiter>();
if(!parameters.empty()) //If parameters is empty, level limiter works as CREATURES_ONLY limiter if(!parameters.Vector().empty()) //If parameters is empty, level limiter works as CREATURES_ONLY limiter
{ {
levelLimiter->minLevel = parameters[0].Integer(); levelLimiter->minLevel = parameters[0].Integer();
if(parameters[1].isNumber()) if(parameters[1].isNumber())
@@ -597,7 +591,7 @@ std::shared_ptr<const ILimiter> JsonUtils::parseLimiter(const JsonNode & limiter
else if(limiterType == "CREATURE_TERRAIN_LIMITER") else if(limiterType == "CREATURE_TERRAIN_LIMITER")
{ {
auto terrainLimiter = std::make_shared<CreatureTerrainLimiter>(); auto terrainLimiter = std::make_shared<CreatureTerrainLimiter>();
if(!parameters.empty()) if(!parameters.Vector().empty())
{ {
LIBRARY->identifiers()->requestIdentifier("terrain", parameters[0], [terrainLimiter](si32 terrain) LIBRARY->identifiers()->requestIdentifier("terrain", parameters[0], [terrainLimiter](si32 terrain)
{ {
@@ -608,9 +602,9 @@ std::shared_ptr<const ILimiter> JsonUtils::parseLimiter(const JsonNode & limiter
} }
else if(limiterType == "UNIT_ON_HEXES") { else if(limiterType == "UNIT_ON_HEXES") {
auto hexLimiter = std::make_shared<UnitOnHexLimiter>(); auto hexLimiter = std::make_shared<UnitOnHexLimiter>();
if(!parameters.empty()) if(!parameters.Vector().empty())
{ {
for (const auto & parameter: parameters){ for (const auto & parameter : parameters.Vector()){
if(parameter.isNumber()) if(parameter.isNumber())
hexLimiter->applicableHexes.insert(BattleHex(parameter.Integer())); hexLimiter->applicableHexes.insert(BattleHex(parameter.Integer()));
} }