diff --git a/Mods/vcmi/Sprites/PortraitsSmall.json b/Mods/vcmi/Sprites/PortraitsSmall.json index 92e10d56e..8064ecf25 100644 --- a/Mods/vcmi/Sprites/PortraitsSmall.json +++ b/Mods/vcmi/Sprites/PortraitsSmall.json @@ -164,7 +164,7 @@ { "frame" : 160, "file" : "HPS134Nc.bmp"}, { "frame" : 161, "file" : "HPS135Wi.bmp"}, { "frame" : 162, "file" : "HPS136Wi.bmp"}, - { "frame" : 200, "file" : "HPSRAND1.bmp"}, //random hero - { "frame" : 201, "file" : "HPSRAND6.bmp"} //no hero + { "frame" : 163, "file" : "HPSRAND1.bmp"}, //random hero + { "frame" : 164, "file" : "HPSRAND6.bmp"} //no hero ] } diff --git a/client/CAnimation.cpp b/client/CAnimation.cpp index 087544c04..537ceb961 100644 --- a/client/CAnimation.cpp +++ b/client/CAnimation.cpp @@ -329,7 +329,7 @@ const std::map CDefFile::getEntries() const { std::map ret; - for (std::map >::const_iterator mapIt = offset.begin(); mapIt!=offset.end(); ++mapIt) + for (auto mapIt = offset.begin(); mapIt!=offset.end(); ++mapIt) ret[mapIt->first] = mapIt->second.size(); return ret; } @@ -935,10 +935,21 @@ bool CAnimation::loadFrame(CDefFile * file, size_t frame, size_t group) //try to get image from def if (source[group][frame].getType() == JsonNode::DATA_NULL) { - if (compressed) - images[group][frame] = new CompImage(file, frame, group); - else - images[group][frame] = new SDLImage(file, frame, group); + auto frameList = file->getEntries(); + + if (vstd::contains(frameList, group) && frameList.at(group) > frame) // frame is present + { + if (compressed) + images[group][frame] = new CompImage(file, frame, group); + else + images[group][frame] = new SDLImage(file, frame, group); + } + else // missing image + { + printError(frame, group, "LoadFrame"); + images[group][frame] = new SDLImage("DEFAULT", compressed); + } + } else //load from separate file { @@ -972,6 +983,38 @@ bool CAnimation::unloadFrame(size_t frame, size_t group) return false; } +void CAnimation::initFromJson(const JsonNode & config) +{ + std::string basepath; + basepath = config["basepath"].String(); + + BOOST_FOREACH(const JsonNode &group, config["sequences"].Vector()) + { + size_t groupID = group["group"].Float();//TODO: string-to-value conversion("moving" -> MOVING) + source[groupID].clear(); + + BOOST_FOREACH(const JsonNode &frame, group["frames"].Vector()) + { + source[groupID].push_back(JsonNode()); + std::string filename = frame.String(); + source[groupID].back()["file"].String() = basepath + filename; + } + } + + BOOST_FOREACH(const JsonNode &node, config["images"].Vector()) + { + size_t group = node["group"].Float(); + size_t frame = node["frame"].Float(); + + if (source[group].size() <= frame) + source[group].resize(frame+1); + + source[group][frame] = node; + std::string filename = node["file"].String(); + source[group][frame]["file"].String() = basepath + filename; + } +} + void CAnimation::init(CDefFile * file) { if (file) @@ -982,8 +1025,12 @@ void CAnimation::init(CDefFile * file) source[mapIt->first].resize(mapIt->second); } - auto & configList = CResourceHandler::get()->getResourcesWithName( - ResourceID(std::string("SPRITES/") + name, EResType::TEXT)); + ResourceID resID(std::string("SPRITES/") + name, EResType::TEXT); + + if (vstd::contains(graphics->imageLists, resID.getName())) + initFromJson(graphics->imageLists[resID.getName()]); + + auto & configList = CResourceHandler::get()->getResourcesWithName(resID); BOOST_FOREACH(auto & entry, configList) { @@ -993,34 +1040,7 @@ void CAnimation::init(CDefFile * file) const JsonNode config((char*)textData.get(), stream->getSize()); - std::string basepath; - basepath = config["basepath"].String(); - - BOOST_FOREACH(const JsonNode &group, config["sequences"].Vector()) - { - size_t groupID = group["group"].Float();//TODO: string-to-value conversion("moving" -> MOVING) - source[groupID].clear(); - - BOOST_FOREACH(const JsonNode &frame, group["frames"].Vector()) - { - source[groupID].push_back(JsonNode()); - std::string filename = frame.String(); - source[groupID].back()["file"].String() = basepath + filename; - } - } - - BOOST_FOREACH(const JsonNode &node, config["images"].Vector()) - { - size_t group = node["group"].Float(); - size_t frame = node["frame"].Float(); - - if (source[group].size() <= frame) - source[group].resize(frame+1); - - source[group][frame] = node; - std::string filename = node["file"].String(); - source[group][frame]["file"].String() = basepath + filename; - } + initFromJson(config); } } diff --git a/client/CAnimation.h b/client/CAnimation.h index 7db58fc23..b56321313 100644 --- a/client/CAnimation.h +++ b/client/CAnimation.h @@ -175,6 +175,7 @@ private: bool unloadFrame(size_t frame, size_t group); //initialize animation from file + void initFromJson(const JsonNode & input); void init(CDefFile * file); //try to open def file diff --git a/client/CMT.cpp b/client/CMT.cpp index 7afe847dc..ec4fc6795 100644 --- a/client/CMT.cpp +++ b/client/CMT.cpp @@ -139,11 +139,13 @@ void init() pomtime.getDiff(); CCS->curh = new CCursorHandler; + graphics = new Graphics(); // should be before curh->init() + CCS->curh->initCursor(); CCS->curh->show(); logGlobal->infoStream()<<"Screen handler: "<loadHeroAnims(); logGlobal->infoStream()<<"\tMain graphics: "<infoStream()<<"Initializing game graphics: "<existsResource(ResourceID("SPRITES/" + imageName, EResType::IMAGE))) + logGlobal->errorStream() << "Required image " << "SPRITES/" << imageName << " is missing!"; + + JsonNode entry; + entry["frame"].Float() = index; + entry["file"].String() = imageName; + + imageLists["SPRITES/" + listName]["images"].Vector().push_back(entry); + } +} + +void Graphics::initializeImageLists() +{ + BOOST_FOREACH(const CCreature * creature, CGI->creh->creatures) + { + addImageListEntry(creature->iconIndex, "CPRSMALL", creature->smallIconName); + addImageListEntry(creature->iconIndex, "TWCRPORT", creature->largeIconName); + } + + BOOST_FOREACH(const CHero * hero, CGI->heroh->heroes) + { + addImageListEntry(hero->imageIndex, "UN32", hero->iconSpecSmall); + addImageListEntry(hero->imageIndex, "UN44", hero->iconSpecLarge); + addImageListEntry(hero->imageIndex, "PORTRAITSLARGE", hero->portraitLarge); + addImageListEntry(hero->imageIndex, "PORTRAITSSMALL", hero->portraitSmall); + } + + BOOST_FOREACH(const CArtifact * art, CGI->arth->artifacts) + { + addImageListEntry(art->iconIndex, "ARTIFACT", art->image); + addImageListEntry(art->iconIndex, "ARTIFACTLARGE", art->large); + } + + BOOST_FOREACH(const CFaction * faction, CGI->townh->factions) + { + if (faction->town) + { + auto & info = faction->town->clientInfo; + addImageListEntry(info.icons[0][0], "ITPT", info.iconLarge[0][0]); + addImageListEntry(info.icons[0][1], "ITPT", info.iconLarge[0][1]); + addImageListEntry(info.icons[1][0], "ITPT", info.iconLarge[1][0]); + addImageListEntry(info.icons[1][1], "ITPT", info.iconLarge[1][1]); + + addImageListEntry(info.icons[0][0] + 2, "ITPA", info.iconSmall[0][0]); + addImageListEntry(info.icons[0][1] + 2, "ITPA", info.iconSmall[0][1]); + addImageListEntry(info.icons[1][0] + 2, "ITPA", info.iconSmall[1][0]); + addImageListEntry(info.icons[1][1] + 2, "ITPA", info.iconSmall[1][1]); + } + } +} diff --git a/client/Graphics.h b/client/Graphics.h index 027232764..de11b232a 100644 --- a/client/Graphics.h +++ b/client/Graphics.h @@ -35,6 +35,8 @@ enum EFonts /// Handles fonts, hero images, town images, various graphics class Graphics { + void addImageListEntry(size_t index, std::string listName, std::string imageName); + public: //Fonts static const int FONTS_NUMBER = 9; @@ -54,6 +56,8 @@ public: CDefHandler * FoWfullHide; //for Fog of War CDefHandler * FoWpartialHide; //for For of War + std::map imageLists; + std::map advmapobjGraphics; CDefEssential * getDef(const CGObjectInstance * obj); CDefEssential * getDef(const CGDefInfo * info); @@ -75,7 +79,9 @@ public: CDefEssential * loadHeroAnim(const std::string &name, const std::vector > &rotations); void loadErmuToPicture(); void blueToPlayersAdv(SDL_Surface * sur, PlayerColor player); //replaces blue interface colour with a color of player + void loadFonts(); + void initializeImageLists(); }; extern Graphics * graphics; diff --git a/config/factions/castle.json b/config/factions/castle.json index 8803bf338..c0345521c 100644 --- a/config/factions/castle.json +++ b/config/factions/castle.json @@ -114,11 +114,6 @@ "dwellingUpLvl6": { "id" : 42, "animation" : "TBCSUP_5.def", "x" : 160, "y" : 190, "z" : -1, "border" : "TOCSCAV2.bmp", "area" : "TZCSCAV2.bmp" }, "dwellingUpLvl7": { "id" : 43, "animation" : "TBCSUP_6.def", "x" : 303, "y" : 0, "z" : -1, "border" : "TOCSANG2.bmp", "area" : "TZCSANG2.bmp" } }, - "icons" : - { - "village" : {"normal" : 18, "built" : 19 }, - "fort" : {"normal" : 0, "built" : 1 } - }, "musicTheme" : "music/CstleTown", diff --git a/config/factions/conflux.json b/config/factions/conflux.json index 41d673029..5115a89d7 100644 --- a/config/factions/conflux.json +++ b/config/factions/conflux.json @@ -118,11 +118,7 @@ "dwellingUpLvl6": { "id" : 42, "animation" : "TBELUP_5.def", "x" : 394, "y" : 283, "z" : 2, "border" : "TOELUP_5.bmp", "area" : "TZELUP_5.bmp" }, "dwellingUpLvl7": { "id" : 43, "animation" : "TBELUP_6.def", "x" : 43, "y" : 0, "z" : -2, "border" : "TOELUP_6.bmp", "area" : "TZELUP_6.bmp" } }, - "icons" : - { - "village" : {"normal" : 34, "built" : 35 }, - "fort" : {"normal" : 16, "built" : 17 } - }, + "musicTheme" : "music/ElemTown", "townBackground": "TBELBACK.bmp", diff --git a/config/factions/dungeon.json b/config/factions/dungeon.json index ce62f8d5d..998924d5c 100644 --- a/config/factions/dungeon.json +++ b/config/factions/dungeon.json @@ -113,11 +113,7 @@ "dwellingUpLvl6": { "id" : 42, "animation" : "TBDNUP_5.def", "x" : 270, "y" : 253, "z" : -1, "border" : "TODMAN2.bmp", "area" : "TZDMAN2.bmp" }, "dwellingUpLvl7": { "id" : 43, "animation" : "TBDNUP_6.def", "x" : 550, "y" : 0, "z" : -1, "border" : "TODDRA2A.bmp", "area" : "TZDDRA2A.bmp" } }, - "icons" : - { - "village" : {"normal" : 28, "built" : 29 }, - "fort" : {"normal" : 10, "built" : 11 } - }, + "musicTheme" : "music/Dungeon", "townBackground": "TBDNBACK.bmp", diff --git a/config/factions/fortress.json b/config/factions/fortress.json index 1797ce927..87a4050bd 100644 --- a/config/factions/fortress.json +++ b/config/factions/fortress.json @@ -114,11 +114,7 @@ "dwellingUpLvl6": { "id" : 42, "animation" : "TBFRUP_5.def", "x" : 0, "y" : 4, "border" : "TOFWYV2.bmp", "area" : "TZFWYV2.bmp" }, "dwellingUpLvl7": { "id" : 43, "animation" : "TBFRUP_6.def", "x" : 587, "y" : 263, "z" : 5, "border" : "TOFHYD2A.bmp", "area" : "TZFHYD2A.bmp" } }, - "icons" : - { - "village" : {"normal" : 32, "built" : 33 }, - "fort" : {"normal" : 14, "built" : 15 } - }, + "musicTheme" : "music/FortressTown", "townBackground": "TBFRBACK.bmp", diff --git a/config/factions/inferno.json b/config/factions/inferno.json index 7a4f6c2ef..fc5db5c8a 100644 --- a/config/factions/inferno.json +++ b/config/factions/inferno.json @@ -114,11 +114,7 @@ "dwellingUpLvl6": { "id" : 42, "animation" : "TBINUP_5.def", "x" : 220, "y" : 282, "z" : 5, "border" : "TOIEFR2.bmp", "area" : "TZIEFR2.bmp" }, "dwellingUpLvl7": { "id" : 43, "animation" : "TBINUP_6.def", "x" : 420, "y" : 105, "z" : -1, "border" : "TOIDVL2.bmp", "area" : "TZIDVL2.bmp" } }, - "icons" : - { - "village" : {"normal" : 24, "built" : 25 }, - "fort" : {"normal" : 6, "built" : 7 } - }, + "musicTheme" : "music/InfernoTown", "townBackground": "TBINBACK.bmp", diff --git a/config/factions/necropolis.json b/config/factions/necropolis.json index 9084e4d74..298ab6663 100644 --- a/config/factions/necropolis.json +++ b/config/factions/necropolis.json @@ -118,11 +118,7 @@ "dwellingUpLvl6": { "id" : 42, "animation" : "TBNCUP_5.def", "x" : 0, "y" : 30, "border" : "TONBKN2.bmp", "area" : "TZNBKN2.bmp" }, "dwellingUpLvl7": { "id" : 43, "animation" : "TBNCUP_6.def", "x" : 662, "y" : 23, "border" : "TONBON2.bmp", "area" : "TZNBON2.bmp" } }, - "icons" : - { - "village" : {"normal" : 26, "built" : 27 }, - "fort" : {"normal" : 8, "built" : 9 } - }, + "musicTheme" : "music/NecroTown", "townBackground": "TBNCBACK.bmp", diff --git a/config/factions/rampart.json b/config/factions/rampart.json index 23f05c68e..4fe90994c 100644 --- a/config/factions/rampart.json +++ b/config/factions/rampart.json @@ -118,11 +118,6 @@ "dwellingUpLvl6": { "id" : 42, "animation" : "TBRMUP_5.def", "x" : 362, "y" : 90, "z" : -2, "border" : "TORUNI2.bmp", "area" : "TZRUNI2.bmp" }, "dwellingUpLvl7": { "id" : 43, "animation" : "TBRMUP_6.def", "x" : 502, "y" : 5, "z" : -5, "border" : "TORDR2AA.bmp", "area" : "TZRDR2AA.bmp" } }, - "icons" : - { - "village" : {"normal" : 20, "built" : 21 }, - "fort" : {"normal" : 2, "built" : 3 } - }, "musicTheme" : "music/Rampart", diff --git a/config/factions/stronghold.json b/config/factions/stronghold.json index c5bbf5a8d..0a0ff298b 100644 --- a/config/factions/stronghold.json +++ b/config/factions/stronghold.json @@ -112,11 +112,7 @@ "dwellingUpLvl6": { "id" : 42, "animation" : "TBSTUP_5.def", "x" : 616, "y" : 93, "z" : -2, "border" : "TOSCYC2A.bmp", "area" : "TZSCYC2A.bmp" }, "dwellingUpLvl7": { "id" : 43, "animation" : "TBSTUP_6.def", "x" : 604, "y" : 0, "border" : "TOSBEH2A.bmp", "area" : "TZSBEH2A.bmp" } }, - "icons" : - { - "village" : {"normal" : 30, "built" : 31 }, - "fort" : {"normal" : 12, "built" : 13 } - }, + "musicTheme" : "music/Stronghold", "townBackground": "TBSTBACK.bmp", diff --git a/config/factions/tower.json b/config/factions/tower.json index a8e060418..f4503331d 100644 --- a/config/factions/tower.json +++ b/config/factions/tower.json @@ -113,11 +113,6 @@ "dwellingUpLvl6": { "id" : 42, "animation" : "TBTWUP_5.def", "x" : 681, "y" : 157, "z" : 2, "border" : "TOTNAG2.bmp", "area" : "TZTNAG2.bmp" }, "dwellingUpLvl7": { "id" : 43, "animation" : "TBTWUP_6.def", "x" : 75, "y" : 91, "z" : -1, "border" : "TOTTIT2.bmp", "area" : "TZTTIT2.bmp" } }, - "icons" : - { - "village" : {"normal" : 22, "built" : 23 }, - "fort" : {"normal" : 4, "built" : 5 } - }, "musicTheme" : "music/TowerTown", diff --git a/config/schemas/artifact.json b/config/schemas/artifact.json index beefbd931..f608e291f 100644 --- a/config/schemas/artifact.json +++ b/config/schemas/artifact.json @@ -3,7 +3,7 @@ "$schema": "http://json-schema.org/draft-04/schema", "title" : "VCMI artifact format", "description" : "Format used to define new artifacts in VCMI", - "required" : [ "class", "graphics", "text", "type", "value" ], + "required" : [ "class", "text", "type", "value" ], "definitions" : { "growingBonusList" : { @@ -46,13 +46,8 @@ "type":"object", "additionalProperties" : false, "description": "Graphical files associated with the artifact", - //"required" : [ "iconIndex", "image", "map" ], - "required" : [ "iconIndex" ], + "required" : [ "image", "map" ], "properties":{ - "iconIndex": { - "type":"number", - "description": "index of icon of this artifact in .def file" - }, "image": { "type":"string", "description": "Base image for this artifact, used for example in hero screen" diff --git a/config/schemas/creature.json b/config/schemas/creature.json index e6ccb16e7..4b68bec26 100644 --- a/config/schemas/creature.json +++ b/config/schemas/creature.json @@ -166,8 +166,7 @@ "additionalProperties" : false, "description": "Describes how this creature looks like during battles", "required" : [ - "animationTime", "iconIndex", - "map", "animation", "timeBetweenFidgets" + "animationTime", "animation", "timeBetweenFidgets" ], "properties":{ "animationTime": { @@ -198,10 +197,6 @@ "type":"string", "description": "Small icon for this creature, used for example in exchange screen" }, - "iconIndex": { - "type":"number", - "description": "Index of icon of this creature in .def file" - }, "map": { "type":"string", diff --git a/config/schemas/faction.json b/config/schemas/faction.json index 3f24e6a78..c4dab925b 100644 --- a/config/schemas/faction.json +++ b/config/schemas/faction.json @@ -1,4 +1,32 @@ { + "definitions" : { + "townIcon" : + { + "type" : "object", + "additionalProperties" : false, + "required" : [ "small", "large" ], + "properties" : { + "small" : { "type" : "string" }, + "large" : { "type" : "string" } + } + }, + "townIconPair" : { + "type":"object", + "additionalProperties" : false, + "required" : [ "normal", "built" ], + "properties": { + "built": { + "$ref" : "#/definitions/townIcon", + "description": "Icon used after player build something in town" + }, + "normal": { + "$ref" : "#/definitions/townIcon", + "description": "Icon used normally" + } + } + } + }, + "type":"object", "$schema": "http://json-schema.org/draft-04/schema", "title" : "VCMI faction format", @@ -79,7 +107,7 @@ "additionalProperties" : false, "required" : [ "adventureMap", "buildingsIcons", "buildings", "creatures", "guildWindow", "names", - "hallBackground", "hallSlots", "horde", "icons", "mageGuild", "moatDamage", + "hallBackground", "hallSlots", "horde", "mageGuild", "moatDamage", "musicTheme", "siege", "structures", "townBackground", "warMachine" ], "description": "town", @@ -193,36 +221,12 @@ "required" : [ "fort", "village" ], "properties":{ "fort": { - "type":"object", - "additionalProperties" : false, - "required" : [ "normal", "built" ], - "description": "Icons for town with built fort", - "properties":{ - "built": { - "type":"number", - "description": "Icon used after player build something in town" - }, - "normal": { - "type":"number", - "description": "Icon used normally" - } - } + "$ref" : "#/definitions/townIconPair", + "description": "Icons for town with built fort" }, "village": { - "type":"object", - "additionalProperties" : false, - "required" : [ "normal", "built" ], - "description": "Icons for town without fort", - "properties":{ - "built": { - "type":"number", - "description": "Icon used after player build something in town" - }, - "normal": { - "type":"number", - "description": "Icon used normally" - } - } + "$ref" : "#/definitions/townIconPair", + "description": "Icons for town without fort" } } }, diff --git a/config/schemas/hero.json b/config/schemas/hero.json index 194a9cbb8..ce47faee3 100644 --- a/config/schemas/hero.json +++ b/config/schemas/hero.json @@ -3,7 +3,16 @@ "$schema": "http://json-schema.org/draft-04/schema", "title" : "VCMI hero format", "description" : "Format used to define new heroes in VCMI", - "required": [ "army", "class", "images", "skills", "texts" ], + "required": [ "army", "class", "skills", "texts" ], + + "oneOf" : [ + { + "required" : [ "images" ] + }, + { + "required" : [ "index" ] + } + ], "additionalProperties" : false, "properties":{ @@ -46,18 +55,14 @@ }, "female": { "type":"boolean", - "description": "This hero is female by default" + "description": "This hero is female (changeable via editor)" }, "images": { "type":"object", "additionalProperties" : false, "description": "images", - "required": [ "index" ], + "required": [ "large", "small", "specialtyLarge", "specialtySmall" ], "properties":{ - "index": { - "type":"number", - "description": "Index of image in portraitsLarge/portraitsSmall files" - }, "large": { "type":"string", "description": "Large version of portrait for use in hero screen" diff --git a/lib/CArtHandler.cpp b/lib/CArtHandler.cpp index 6197eed42..8a3f22975 100644 --- a/lib/CArtHandler.cpp +++ b/lib/CArtHandler.cpp @@ -173,7 +173,6 @@ std::vector CArtHandler::loadLegacyData(size_t dataSize) { JsonNode artData; - artData["graphics"]["iconIndex"].Float() = i; artData["text"]["name"].String() = parser.readString(); artData["text"]["event"].String() = events.readString(); artData["value"].Float() = parser.readNumber(); @@ -200,6 +199,10 @@ void CArtHandler::loadObject(std::string scope, std::string name, const JsonNode { auto object = loadFromJson(data); object->id = ArtifactID(artifacts.size()); + if (object->id < ArtifactID::ART_SELECTION) + object->iconIndex = object->id; + else + object->iconIndex = object->id + 2; artifacts.push_back(object); @@ -210,6 +213,10 @@ void CArtHandler::loadObject(std::string scope, std::string name, const JsonNode { auto object = loadFromJson(data); object->id = ArtifactID(index); + if (object->id < ArtifactID::ART_SELECTION) + object->iconIndex = object->id; + else + object->iconIndex = object->id + 2; assert(artifacts[index] == nullptr); // ensure that this id was not loaded before artifacts[index] = object; @@ -236,7 +243,6 @@ CArtifact * CArtHandler::loadFromJson(const JsonNode & node) art->eventText = text["event"].String(); const JsonNode & graphics = node["graphics"]; - art->iconIndex = graphics["iconIndex"].Float(); art->image = graphics["image"].String(); if (!graphics["large"].isNull()) diff --git a/lib/CArtHandler.h b/lib/CArtHandler.h index a4ad31ba9..9c0c1084e 100644 --- a/lib/CArtHandler.h +++ b/lib/CArtHandler.h @@ -51,7 +51,7 @@ public: std::string image; std::string large; // big image for cutom artifacts, used in drag & drop std::string advMapDef; //used for adventure map object - si32 iconIndex; //TODO: handle automatically + si32 iconIndex; const std::string &Name() const; //getter const std::string &Description() const; //getter diff --git a/lib/CCreatureHandler.cpp b/lib/CCreatureHandler.cpp index 75797ade0..53f3ce23d 100644 --- a/lib/CCreatureHandler.cpp +++ b/lib/CCreatureHandler.cpp @@ -282,8 +282,6 @@ std::vector CCreatureHandler::loadLegacyData(size_t dataSize) JsonNode data; - data["graphics"]["iconIndex"].Float() = h3Data.size() + 2; // +2 for empty\selection images - data["name"]["singular"].String() = parser.readString(); data["name"]["plural"].String() = parser.readString(); @@ -326,6 +324,7 @@ void CCreatureHandler::loadObject(std::string scope, std::string name, const Jso { auto object = loadFromJson(data); object->idNumber = CreatureID(creatures.size()); + object->iconIndex = object->idNumber + 2; creatures.push_back(object); @@ -341,6 +340,7 @@ void CCreatureHandler::loadObject(std::string scope, std::string name, const Jso { auto object = loadFromJson(data); object->idNumber = CreatureID(index); + object->iconIndex = object->idNumber + 2; assert(creatures[index] == nullptr); // ensure that this id was not loaded before creatures[index] = object; @@ -584,7 +584,8 @@ void CCreatureHandler::loadJsonAnimation(CCreature * cre, const JsonNode & graph cre->animation.missleFrameAngles = missile["frameAngles"].convertTo >(); cre->advMapDef = graphics["map"].String(); - cre->iconIndex = graphics["iconIndex"].Float(); + cre->smallIconName = graphics["iconSmall"].String(); + cre->largeIconName = graphics["iconLarge"].String(); } void CCreatureHandler::loadCreatureJson(CCreature * creature, const JsonNode & config) diff --git a/lib/CCreatureHandler.h b/lib/CCreatureHandler.h index 3141f93cd..d506e6c9a 100644 --- a/lib/CCreatureHandler.h +++ b/lib/CCreatureHandler.h @@ -49,6 +49,10 @@ public: std::string advMapDef; //for new creatures only, image for adventure map si32 iconIndex; // index of icon in files like twcrport + /// names of files with appropriate icons. Used only during loading + std::string smallIconName; + std::string largeIconName; + struct CreatureAnimation { double timeBetweenFidgets, walkAnimationTime, attackAnimationTime, flightAnimationDistance; @@ -123,7 +127,7 @@ public: & fightValue & AIValue & growth & hordeGrowth & ammMin & ammMax & level & abilityText & animDefName & advMapDef; - h & iconIndex; + h & iconIndex & smallIconName & largeIconName; h & idNumber & faction & sounds & animation; diff --git a/lib/CHeroHandler.cpp b/lib/CHeroHandler.cpp index be5738548..59299aa38 100644 --- a/lib/CHeroHandler.cpp +++ b/lib/CHeroHandler.cpp @@ -228,7 +228,6 @@ CHero * CHeroHandler::loadFromJson(const JsonNode & node) hero->specTooltip = node["texts"]["specialty"]["tooltip"].String(); hero->specDescr = node["texts"]["specialty"]["description"].String(); - hero->imageIndex = node["images"]["index"].Float(); hero->iconSpecSmall = node["images"]["specialtySmall"].String(); hero->iconSpecLarge = node["images"]["specialtyLarge"].String(); hero->portraitSmall = node["images"]["small"].String(); @@ -439,8 +438,6 @@ std::vector CHeroHandler::loadLegacyData(size_t dataSize) heroData["texts"]["specialty"]["tooltip"].String() = specParser.readString(); heroData["texts"]["specialty"]["description"].String() = specParser.readString(); - heroData["images"]["index"].Float() = i; - for(int x=0;x<3;x++) { JsonNode armySlot; @@ -463,6 +460,7 @@ void CHeroHandler::loadObject(std::string scope, std::string name, const JsonNod { auto object = loadFromJson(data); object->ID = heroes.size(); + object->imageIndex = heroes.size() + 8; // 2 special frames + some extra portraits heroes.push_back(object); @@ -473,6 +471,7 @@ void CHeroHandler::loadObject(std::string scope, std::string name, const JsonNod { auto object = loadFromJson(data); object->ID = index; + object->imageIndex = index; assert(heroes[index] == nullptr); // ensure that this id was not loaded before heroes[index] = object; diff --git a/lib/CObjectHandler.cpp b/lib/CObjectHandler.cpp index d340a67eb..a29d64729 100644 --- a/lib/CObjectHandler.cpp +++ b/lib/CObjectHandler.cpp @@ -70,11 +70,11 @@ static void showInfoDialog(const PlayerColor playerID, const ui32 txtID, const u IObjectInterface::cb->sendAndApply(&iw); } -static void showInfoDialog(const ObjectInstanceID heroID, const ui32 txtID, const ui16 soundID) +/*static void showInfoDialog(const ObjectInstanceID heroID, const ui32 txtID, const ui16 soundID) { const PlayerColor playerID = IObjectInterface::cb->getOwner(heroID); showInfoDialog(playerID,txtID,soundID); -} +}*/ static void showInfoDialog(const CGHeroInstance* h, const ui32 txtID, const ui16 soundID) { diff --git a/lib/CTownHandler.cpp b/lib/CTownHandler.cpp index 136d28658..95cfed8ba 100644 --- a/lib/CTownHandler.cpp +++ b/lib/CTownHandler.cpp @@ -428,32 +428,33 @@ void CTownHandler::loadSiegeScreen(CTown &town, const JsonNode & source) pos[1] = JsonToPoint(source["static"]["background"]); } +static void readIcon(JsonNode source, std::string & small, std::string & large) +{ + if (source.getType() == JsonNode::DATA_STRUCT) // don't crash on old format + { + small = source["small"].String(); + large = source["large"].String(); + } +} + void CTownHandler::loadClientData(CTown &town, const JsonNode & source) { - town.clientInfo.icons[0][0] = source["icons"]["village"]["normal"].Float(); - town.clientInfo.icons[0][1] = source["icons"]["village"]["built"].Float(); - town.clientInfo.icons[1][0] = source["icons"]["fort"]["normal"].Float(); - town.clientInfo.icons[1][1] = source["icons"]["fort"]["built"].Float(); + CTown::ClientInfo & info = town.clientInfo; - town.clientInfo.hallBackground = source["hallBackground"].String(); - town.clientInfo.musicTheme = source["musicTheme"].String(); - town.clientInfo.townBackground = source["townBackground"].String(); - town.clientInfo.guildWindow = source["guildWindow"].String(); - town.clientInfo.buildingsIcons = source["buildingsIcons"].String(); + readIcon(source["icons"]["village"]["normal"], info.iconSmall[0][0], info.iconLarge[0][0]); + readIcon(source["icons"]["village"]["built"], info.iconSmall[0][1], info.iconLarge[0][1]); + readIcon(source["icons"]["fort"]["normal"], info.iconSmall[1][0], info.iconLarge[1][0]); + readIcon(source["icons"]["fort"]["built"], info.iconSmall[1][1], info.iconLarge[1][1]); - town.clientInfo.advMapVillage = source["adventureMap"]["village"].String(); - town.clientInfo.advMapCastle = source["adventureMap"]["castle"].String(); - town.clientInfo.advMapCapitol = source["adventureMap"]["capitol"].String(); + info.hallBackground = source["hallBackground"].String(); + info.musicTheme = source["musicTheme"].String(); + info.townBackground = source["townBackground"].String(); + info.guildWindow = source["guildWindow"].String(); + info.buildingsIcons = source["buildingsIcons"].String(); - const JsonNode *value = &source["adventureMap"]["dwellings"]; - if (!value->isNull()) - { - BOOST_FOREACH (const JsonNode &d, value->Vector()) - { - town.dwellings.push_back (d["graphics"].String()); - town.dwellingNames.push_back (d["name"].String()); - } - } + info.advMapVillage = source["adventureMap"]["village"].String(); + info.advMapCastle = source["adventureMap"]["castle"].String(); + info.advMapCapitol = source["adventureMap"]["capitol"].String(); loadTownHall(town, source["hallSlots"]); loadStructures(town, source["structures"]); @@ -525,6 +526,12 @@ void CTownHandler::loadTown(CTown &town, const JsonNode & source) }); } + BOOST_FOREACH (const JsonNode &d, source["adventureMap"]["dwellings"].Vector()) + { + town.dwellings.push_back (d["graphics"].String()); + town.dwellingNames.push_back (d["name"].String()); + } + loadBuildings(town, source["buildings"]); loadClientData(town,source); } @@ -597,6 +604,14 @@ void CTownHandler::loadObject(std::string scope, std::string name, const JsonNod { auto object = loadFromJson(data); object->index = factions.size(); + if (object->town) + { + auto & info = object->town->clientInfo; + info.icons[0][0] = 8 + object->index * 4 + 0; + info.icons[0][1] = 8 + object->index * 4 + 1; + info.icons[1][0] = 8 + object->index * 4 + 2; + info.icons[1][1] = 8 + object->index * 4 + 3; + } factions.push_back(object); @@ -607,6 +622,14 @@ void CTownHandler::loadObject(std::string scope, std::string name, const JsonNod { auto object = loadFromJson(data); object->index = index; + if (object->town) + { + auto & info = object->town->clientInfo; + info.icons[0][0] = (GameConstants::F_NUMBER + object->index) * 2 + 0; + info.icons[0][1] = (GameConstants::F_NUMBER + object->index) * 2 + 1; + info.icons[1][0] = object->index * 2 + 0; + info.icons[1][1] = object->index * 2 + 1; + } assert(factions[index] == nullptr); // ensure that this id was not loaded before factions[index] = object; diff --git a/lib/CTownHandler.h b/lib/CTownHandler.h index 0af04e64e..7ea360131 100644 --- a/lib/CTownHandler.h +++ b/lib/CTownHandler.h @@ -163,6 +163,8 @@ public: //icons [fort is present?][build limit reached?] -> index of icon in def files int icons[2][2]; + std::string iconSmall[2][2]; /// icon names used during loading + std::string iconLarge[2][2]; std::string musicTheme; std::string townBackground; @@ -187,8 +189,8 @@ public: template void serialize(Handler &h, const int version) { - h & icons & musicTheme & townBackground & guildWindow & buildingsIcons & hallBackground & hallSlots & structures; - h & advMapVillage & advMapCastle & advMapCapitol; + h & icons & iconSmall & iconLarge & musicTheme & townBackground & guildWindow & buildingsIcons & hallBackground; + h & advMapVillage & advMapCastle & advMapCapitol & hallSlots & structures; h & siegePrefix & siegePositions & siegeShooter & siegeShooterCropHeight; } } clientInfo;