mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	- finally, solution for imageIndex fields. All image lists will be generated in runtime
- iconIndex fields from json are no longer used - simple check for missing icons on startup
This commit is contained in:
		| @@ -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 | ||||
| 	] | ||||
| } | ||||
|   | ||||
| @@ -329,7 +329,7 @@ const std::map<size_t, size_t > CDefFile::getEntries() const | ||||
| { | ||||
| 	std::map<size_t, size_t > ret; | ||||
|  | ||||
| 	for (std::map<size_t, std::vector <size_t> >::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); | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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: "<<pomtime.getDiff(); | ||||
| 	pomtime.getDiff(); | ||||
| 	graphics = new Graphics(); | ||||
|  | ||||
| 	graphics->loadHeroAnims(); | ||||
|     logGlobal->infoStream()<<"\tMain graphics: "<<tmh.getDiff(); | ||||
|     logGlobal->infoStream()<<"Initializing game graphics: "<<tmh.getDiff(); | ||||
|   | ||||
| @@ -2633,7 +2633,7 @@ size_t OptionsTab::CPlayerSettingsHelper::getImageIndex() | ||||
| 		WOOD = 0,       ORE     = 0,    MITHRIL = 10, // resources unavailable in bonuses file | ||||
|  | ||||
| 		TOWN_RANDOM = 38,  TOWN_NONE = 39, // Special frames in ITPA | ||||
| 		HERO_RANDOM = 200, HERO_NONE = 201 // Special frames in PortraitsSmall | ||||
| 		HERO_RANDOM = 163, HERO_NONE = 164 // Special frames in PortraitsSmall | ||||
| 	}; | ||||
|  | ||||
| 	switch(type) | ||||
|   | ||||
| @@ -126,6 +126,7 @@ Graphics::Graphics() | ||||
| 	tasks += boost::bind(&Graphics::loadHeroFlags,this); | ||||
| 	tasks += boost::bind(&Graphics::initializeBattleGraphics,this); | ||||
| 	tasks += boost::bind(&Graphics::loadErmuToPicture,this); | ||||
| 	tasks += boost::bind(&Graphics::initializeImageLists,this); | ||||
| 	tasks += GET_DEF_ESS(resources32,"RESOURCE.DEF"); | ||||
| 	tasks += GET_DEF_ESS(spellscr,"SPELLSCR.DEF"); | ||||
| 	tasks += GET_DEF_ESS(heroMoveArrows,"ADAG.DEF"); | ||||
| @@ -417,3 +418,58 @@ void Graphics::loadErmuToPicture() | ||||
| 	} | ||||
| 	assert (etp_idx == 44); | ||||
| } | ||||
|  | ||||
| void Graphics::addImageListEntry(size_t index, std::string listName, std::string imageName) | ||||
| { | ||||
| 	if (!imageName.empty()) | ||||
| 	{ | ||||
| 		if (!CResourceHandler::get()->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]); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -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<std::string, JsonNode> imageLists; | ||||
|  | ||||
| 	std::map<std::string, CDefEssential *> 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<std::pair<int,int> > &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; | ||||
|   | ||||
| @@ -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", | ||||
|  | ||||
|   | ||||
| @@ -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", | ||||
|   | ||||
| @@ -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", | ||||
|   | ||||
| @@ -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", | ||||
|   | ||||
| @@ -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", | ||||
|   | ||||
| @@ -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", | ||||
|   | ||||
| @@ -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", | ||||
|  | ||||
|   | ||||
| @@ -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", | ||||
|   | ||||
| @@ -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", | ||||
|  | ||||
|   | ||||
| @@ -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" | ||||
|   | ||||
| @@ -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", | ||||
|   | ||||
| @@ -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" | ||||
| 						} | ||||
| 					} | ||||
| 				}, | ||||
|   | ||||
| @@ -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" | ||||
|   | ||||
| @@ -173,7 +173,6 @@ std::vector<JsonNode> 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()) | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -282,8 +282,6 @@ std::vector<JsonNode> 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<std::vector<double> >(); | ||||
|  | ||||
| 	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) | ||||
|   | ||||
| @@ -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; | ||||
|  | ||||
|   | ||||
| @@ -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<JsonNode> 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; | ||||
|   | ||||
| @@ -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) | ||||
| { | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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 <typename Handler> 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; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user