diff --git a/config/schemas/object.json b/config/schemas/object.json index f20358bc0..82e743798 100644 --- a/config/schemas/object.json +++ b/config/schemas/object.json @@ -19,7 +19,7 @@ }, "base": { - "$ref" : "vcmi:objectType" + "type" : "object" }, "types": { "type":"object", diff --git a/config/schemas/objectType.json b/config/schemas/objectType.json index db60d6c91..d4923e374 100644 --- a/config/schemas/objectType.json +++ b/config/schemas/objectType.json @@ -15,7 +15,7 @@ }, "base": { - "$ref" : "vcmi:objectTemplate" + "type" : "object" }, "types": { "type":"object", diff --git a/lib/CArtHandler.cpp b/lib/CArtHandler.cpp index 1cc1f7e77..b5505e224 100644 --- a/lib/CArtHandler.cpp +++ b/lib/CArtHandler.cpp @@ -647,19 +647,18 @@ void CArtHandler::afterLoadFinalization() } } - //Note: "10" is used here because H3 text files don't define any template for art with ID 0 - ObjectTemplate base = VLC->objtypeh->getHandlerFor(Obj::ARTIFACT, 10)->getTemplates().front(); for (CArtifact * art : artifacts) { + VLC->objtypeh->createObject(art->Name(), JsonNode(), Obj::ARTIFACT, art->id.num); + if (!art->advMapDef.empty()) { - base.animationFile = art->advMapDef; - base.subid = art->id; + JsonNode templ; + templ["animation"].String() = art->advMapDef; // add new template. // Necessary for objects added via mods that don't have any templates in H3 - VLC->objtypeh->createObject(art->Name(), JsonNode(), Obj::ARTIFACT, art->id.num); - VLC->objtypeh->getHandlerFor(Obj::ARTIFACT, art->id)->addTemplate(base); + VLC->objtypeh->getHandlerFor(Obj::ARTIFACT, art->id)->addTemplate(templ); } } } diff --git a/lib/CCreatureHandler.cpp b/lib/CCreatureHandler.cpp index 3f8bd9397..610c78258 100644 --- a/lib/CCreatureHandler.cpp +++ b/lib/CCreatureHandler.cpp @@ -1114,17 +1114,14 @@ void CCreatureHandler::buildBonusTreeForTiers() void CCreatureHandler::afterLoadFinalization() { - ObjectTemplate base = VLC->objtypeh->getHandlerFor(Obj::MONSTER, 0)->getTemplates().front(); for (CCreature * crea : creatures) { + VLC->objtypeh->createObject(crea->nameSing, JsonNode(), Obj::MONSTER, crea->idNumber.num); if (!crea->advMapDef.empty()) { - base.animationFile = crea->advMapDef; - base.subid = crea->idNumber; - - // replace existing (if any) and add new template. - // Necessary for objects added via mods that don't have any templates in H3 - VLC->objtypeh->getHandlerFor(Obj::MONSTER, crea->idNumber)->addTemplate(base); + JsonNode templ; + templ["animation"].String() = crea->advMapDef; + VLC->objtypeh->getHandlerFor(Obj::MONSTER, crea->idNumber)->addTemplate(templ); } } } diff --git a/lib/CHeroHandler.cpp b/lib/CHeroHandler.cpp index ca5efc556..0e26bdd4e 100644 --- a/lib/CHeroHandler.cpp +++ b/lib/CHeroHandler.cpp @@ -231,15 +231,15 @@ void CHeroClassHandler::afterLoadFinalization() } } - ObjectTemplate base = VLC->objtypeh->getHandlerFor(Obj::HERO, 0)->getTemplates().front(); for (CHeroClass * hc : heroClasses) { - base.animationFile = hc->imageMapMale; - base.subid = hc->id; - - // replace existing (if any) and add new template. - // Necessary for objects added via mods that don't have any templates in H3 - VLC->objtypeh->getHandlerFor(Obj::HERO, base.subid)->addTemplate(base); + VLC->objtypeh->createObject(hc->identifier, JsonNode(), Obj::HERO, hc->id); + if (!hc->imageMapMale.empty()) + { + JsonNode templ; + templ["animation"].String() = hc->imageMapMale; + VLC->objtypeh->getHandlerFor(Obj::HERO, hc->id)->addTemplate(templ); + } } } diff --git a/lib/CObjectClassesHandler.cpp b/lib/CObjectClassesHandler.cpp index 146ebae9e..4126c8ceb 100644 --- a/lib/CObjectClassesHandler.cpp +++ b/lib/CObjectClassesHandler.cpp @@ -444,7 +444,7 @@ void CObjectClassesHandler::loadObjectEntry(const JsonNode & entry, ObjectContai auto handler = handlerConstructors.at(obj->handlerName)(); handler->init(entry); - si32 id = selectNextID(entry["index"], obj->objects, 256); + si32 id = selectNextID(entry["index"], obj->objects, 1000); handler->setType(obj->id, id); if (handler->getTemplates().empty()) @@ -517,6 +517,18 @@ TObjectTypeHandler CObjectClassesHandler::getHandlerFor(si32 type, si32 subtype) return nullptr; } +void CObjectClassesHandler::beforeValidate(JsonNode & object) +{ + for (auto & entry : object["types"].Struct()) + { + JsonUtils::inherit(entry.second, object["base"]); + for (auto & templ : entry.second["templates"].Struct()) + { + JsonUtils::inherit(templ.second, entry.second["base"]); + } + } +} + void CObjectClassesHandler::afterLoadFinalization() { legacyTemplates.clear(); // whatever left there is no longer needed @@ -555,11 +567,24 @@ bool AObjectTypeHandler::objectFilter(const CGObjectInstance *, const ObjectTemp return true; // by default - accept all. } -void AObjectTypeHandler::addTemplate(const ObjectTemplate & templ) +void AObjectTypeHandler::addTemplate(ObjectTemplate templ) { + templ.id = Obj(type); + templ.subid = subtype; templates.push_back(templ); } +void AObjectTypeHandler::addTemplate(JsonNode config) +{ + JsonUtils::inherit(config, base); + ObjectTemplate tmpl; + tmpl.id = Obj(type); + tmpl.subid = subtype; + tmpl.stringID = ""; // TODO? + tmpl.readJson(config); + addTemplate(tmpl); +} + std::vector AObjectTypeHandler::getTemplates() const { return templates; diff --git a/lib/CObjectClassesHandler.h b/lib/CObjectClassesHandler.h index 50bc1936d..57ecd07c7 100644 --- a/lib/CObjectClassesHandler.h +++ b/lib/CObjectClassesHandler.h @@ -118,7 +118,8 @@ public: /// loads templates from Json structure using fields "base" and "templates" virtual void init(const JsonNode & input); - void addTemplate(const ObjectTemplate & templ); + void addTemplate(ObjectTemplate templ); + void addTemplate(JsonNode config); /// returns all templates, without any filters std::vector getTemplates() const; @@ -207,16 +208,17 @@ class DLL_LINKAGE CObjectClassesHandler : public IHandlerBase public: CObjectClassesHandler(); - virtual std::vector loadLegacyData(size_t dataSize); + std::vector loadLegacyData(size_t dataSize) override; - virtual void loadObject(std::string scope, std::string name, const JsonNode & data); - virtual void loadObject(std::string scope, std::string name, const JsonNode & data, size_t index); + void loadObject(std::string scope, std::string name, const JsonNode & data) override; + void loadObject(std::string scope, std::string name, const JsonNode & data, size_t index) override; void createObject(std::string name, JsonNode config, si32 ID, boost::optional subID = boost::optional()); - virtual void afterLoadFinalization(); + void beforeValidate(JsonNode & object) override; + void afterLoadFinalization() override; - virtual std::vector getDefaultAllowed() const; + std::vector getDefaultAllowed() const override; /// returns handler for specified object (ID-based). ObjectHandler keeps ownership TObjectTypeHandler getHandlerFor(si32 type, si32 subtype) const; diff --git a/lib/CTownHandler.cpp b/lib/CTownHandler.cpp index 625033b8c..d183039e2 100644 --- a/lib/CTownHandler.cpp +++ b/lib/CTownHandler.cpp @@ -759,31 +759,31 @@ void CTownHandler::loadObject(std::string scope, std::string name, const JsonNod void CTownHandler::afterLoadFinalization() { initializeRequirements(); - ObjectTemplate base = VLC->objtypeh->getHandlerFor(Obj::TOWN, 0)->getTemplates().front(); for (CFaction * fact : factions) { if (fact->town) { - base.animationFile = fact->town->clientInfo.advMapCastle; - base.subid = fact->index; - - // replace existing (if any) and add new template. - // Necessary for objects added via mods that don't have any templates in H3 - VLC->objtypeh->getHandlerFor(Obj::TOWN, fact->index)->addTemplate(base); + VLC->objtypeh->createObject(fact->identifier, JsonNode(), Obj::TOWN, fact->index); + if (!fact->town->clientInfo.advMapCastle.empty()) + { + JsonNode templ; + templ["animation"].String() = fact->town->clientInfo.advMapCastle; + VLC->objtypeh->getHandlerFor(Obj::TOWN, fact->index)->addTemplate(templ); + } assert(fact->town->dwellings.size() == fact->town->dwellingNames.size()); for (size_t i=0; itown->dwellings.size(); i++) { - ObjectTemplate base = VLC->objtypeh->getHandlerFor(Obj::CREATURE_GENERATOR1, 0)->getTemplates().front(); - //both unupgraded and upgraded get same dwelling - for (auto cre : fact->town->creatures[i]) - { - base.subid = 80 + cre; - base.animationFile = fact->town->dwellings[i]; + for (auto cre : fact->town->creatures[i]) + { if (VLC->objh->cregens.count(cre) == 0) { - VLC->objtypeh->getHandlerFor(Obj::CREATURE_GENERATOR1, 80 + cre)->addTemplate(base); + JsonNode templ; + templ["animation"].String() = fact->town->dwellings[i]; + + VLC->objtypeh->createObject("", JsonNode(), Obj::CREATURE_GENERATOR1, 80 + cre); + VLC->objtypeh->getHandlerFor(Obj::CREATURE_GENERATOR1, 80 + cre)->addTemplate(templ); VLC->objh->cregens[80 + cre] = cre; //map of dwelling -> creature id } } @@ -823,4 +823,4 @@ std::set CTownHandler::getAllowedFactions() const allowedFactions.insert(i); return allowedFactions; -} +}