diff --git a/config/schemas/spell.json b/config/schemas/spell.json index 45010a75f..7d0084f38 100644 --- a/config/schemas/spell.json +++ b/config/schemas/spell.json @@ -231,20 +231,25 @@ "additionalProperties" : false, "required" : ["none", "basic", "advanced", "expert"], - "properties":{ - "none":{ - "$ref" : "#/definitions/levelInfo" - }, - "basic":{ - "$ref" : "#/definitions/levelInfo" - }, - "advanced":{ - "$ref" : "#/definitions/levelInfo" - }, - "expert":{ - "$ref" : "#/definitions/levelInfo" - } - } + "properties":{ + "base":{ + "type": "object", + "description": "will be merged with all levels", + "additionalProperties": true + }, + "none":{ + "$ref" : "#/definitions/levelInfo" + }, + "basic":{ + "$ref" : "#/definitions/levelInfo" + }, + "advanced":{ + "$ref" : "#/definitions/levelInfo" + }, + "expert":{ + "$ref" : "#/definitions/levelInfo" + } + } } } } diff --git a/lib/CModHandler.cpp b/lib/CModHandler.cpp index 94eb2cb1a..9b7701dee 100644 --- a/lib/CModHandler.cpp +++ b/lib/CModHandler.cpp @@ -296,6 +296,12 @@ bool CContentHandler::ContentTypeHandler::loadMod(std::string modName, bool vali { ModInfo & modInfo = modData[modName]; bool result = true; + + auto performValidate = [&,this](JsonNode & data, const std::string & name){ + handler->beforeValidate(data); + if (validate) + result &= JsonUtils::validate(data, "vcmi:" + objectName, name); + }; // apply patches if (!modInfo.patches.isNull()) @@ -314,8 +320,8 @@ bool CContentHandler::ContentTypeHandler::loadMod(std::string modName, bool vali if (originalData.size() > index) { JsonUtils::merge(originalData[index], data); - if (validate) - result &= JsonUtils::validate(originalData[index], "vcmi:" + objectName, name); + + performValidate(originalData[index],name); handler->loadObject(modName, name, originalData[index], index); originalData[index].clear(); // do not use same data twice (same ID) @@ -324,8 +330,7 @@ bool CContentHandler::ContentTypeHandler::loadMod(std::string modName, bool vali } } // normal new object or one with index bigger that data size - if (validate) - result &= JsonUtils::validate(data, "vcmi:" + objectName, name); + performValidate(data,name); handler->loadObject(modName, name, data); } return result; diff --git a/lib/CSpellHandler.cpp b/lib/CSpellHandler.cpp index 00d1dc2df..95493d7bd 100644 --- a/lib/CSpellHandler.cpp +++ b/lib/CSpellHandler.cpp @@ -864,6 +864,22 @@ void CSpellHandler::afterLoadFinalization() bonus.sid = spell->id; } +void CSpellHandler::beforeValidate(JsonNode & object) +{ + //handle "base" level info + + JsonNode levels = object["levels"]; + + if(levels["base"].getType() == JsonNode::DATA_STRUCT) + { + JsonUtils::mergeCopy(levels["none"],levels["base"]); + JsonUtils::mergeCopy(levels["basic"],levels["base"]); + JsonUtils::mergeCopy(levels["advanced"],levels["base"]); + JsonUtils::mergeCopy(levels["expert"],levels["base"]); + } + + +} CSpellHandler::~CSpellHandler() diff --git a/lib/CSpellHandler.h b/lib/CSpellHandler.h index 5c2797eb9..e516973b7 100644 --- a/lib/CSpellHandler.h +++ b/lib/CSpellHandler.h @@ -205,6 +205,7 @@ public: std::vector loadLegacyData(size_t dataSize) override; void afterLoadFinalization() override; + void beforeValidate(JsonNode & object) override; /** * Gets a list of default allowed spells. OH3 spells are all allowed by default. diff --git a/lib/IHandlerBase.h b/lib/IHandlerBase.h index 8c570e8ac..2ae74235e 100644 --- a/lib/IHandlerBase.h +++ b/lib/IHandlerBase.h @@ -32,6 +32,9 @@ public: virtual void loadObject(std::string scope, std::string name, const JsonNode & data) = 0; virtual void loadObject(std::string scope, std::string name, const JsonNode & data, size_t index) = 0; + /// allows handlers to alter object configuration before validation and actual load + virtual void beforeValidate(JsonNode & object){}; + /// allows handler to do post-loading step for validation or integration of loaded data virtual void afterLoadFinalization(){};