diff --git a/lib/CHeroHandler.cpp b/lib/CHeroHandler.cpp index 6dad095c8..c0591807c 100644 --- a/lib/CHeroHandler.cpp +++ b/lib/CHeroHandler.cpp @@ -766,7 +766,8 @@ void CHeroHandler::afterLoadFinalization() if(!base.isEmpty()) { specNode["base"] = base; - //TODO: subtract base from bonuses + for(JsonNode & node : specVec) + node = JsonUtils::difference(node, base); } } // add json for bonuses diff --git a/lib/HeroBonus.cpp b/lib/HeroBonus.cpp index df33c1ba4..a6bf5262c 100644 --- a/lib/HeroBonus.cpp +++ b/lib/HeroBonus.cpp @@ -1736,6 +1736,8 @@ std::string nameForBonus(const Bonus & bonus) return CreatureID::encode(bonus.subtype) + "2" + CreatureID::encode(bonus.additionalInfo); case Bonus::GENERATE_RESOURCE: return GameConstants::RESOURCE_NAMES[bonus.subtype]; + case Bonus::STACKS_SPEED: + return "speed"; default: return vstd::findKey(bonusNameMap, bonus.type); } diff --git a/lib/JsonNode.cpp b/lib/JsonNode.cpp index d8f21596a..0a17892f1 100644 --- a/lib/JsonNode.cpp +++ b/lib/JsonNode.cpp @@ -899,6 +899,36 @@ JsonNode JsonUtils::intersect(const JsonNode & a, const JsonNode & b, bool prune return nullNode; } +JsonNode JsonUtils::difference(const JsonNode & node, const JsonNode & base) +{ + if(node.getType() == JsonNode::DATA_STRUCT && base.getType() == JsonNode::DATA_STRUCT) + { + // subtract individual properties + JsonNode result(JsonNode::DATA_STRUCT); + for(auto property : node.Struct()) + { + if(vstd::contains(base.Struct(), property.first)) + { + JsonNode propertyDifference = JsonUtils::difference(property.second, base.Struct().find(property.first)->second); + if(propertyDifference.isEmpty()) + continue; + result[property.first] = propertyDifference; + } + else + { + result[property.first] = property.second; + } + } + return result; + } + else + { + if(node == base) + return nullNode; + } + return node; +} + JsonNode JsonUtils::assembleFromFiles(std::vector files) { bool isValid; diff --git a/lib/JsonNode.h b/lib/JsonNode.h index 8ad43197b..a6d666c88 100644 --- a/lib/JsonNode.h +++ b/lib/JsonNode.h @@ -199,6 +199,12 @@ namespace JsonUtils DLL_LINKAGE JsonNode intersect(const JsonNode & a, const JsonNode & b, bool pruneEmpty = true); DLL_LINKAGE JsonNode intersect(const std::vector & nodes, bool pruneEmpty = true); + /** + * @brief construct node representing the difference "node - base" + * merging difference with base gives node + */ + DLL_LINKAGE JsonNode difference(const JsonNode & node, const JsonNode & base); + /** * @brief generate one Json structure from multiple files * @param files - list of filenames with parts of json structure