浏览代码

- Implemented "mapObject" entry for hero classes
- Updated schemas
- Some bugfixing

Ivan Savenko 11 年之前
父节点
当前提交
09d595e385

+ 6 - 7
client/Graphics.cpp

@@ -22,6 +22,7 @@
 #include "../lib/GameConstants.h"
 #include "../lib/GameConstants.h"
 #include "../lib/CStopWatch.h"
 #include "../lib/CStopWatch.h"
 #include "CAnimation.h"
 #include "CAnimation.h"
+#include "../lib/mapObjects/CObjectClassesHandler.h"
 
 
 using namespace boost::assign;
 using namespace boost::assign;
 using namespace CSDL_Ext;
 using namespace CSDL_Ext;
@@ -145,13 +146,11 @@ void Graphics::loadHeroAnims()
 
 
 	for(auto & elem : CGI->heroh->classes.heroClasses)
 	for(auto & elem : CGI->heroh->classes.heroClasses)
 	{
 	{
-		const CHeroClass * hc = elem;
-
-		if (!vstd::contains(heroAnims, hc->imageMapFemale))
-			heroAnims[hc->imageMapFemale] = loadHeroAnim(hc->imageMapFemale, rotations);
-
-		if (!vstd::contains(heroAnims, hc->imageMapMale))
-			heroAnims[hc->imageMapMale] = loadHeroAnim(hc->imageMapMale, rotations);
+		for (auto & templ : VLC->objtypeh->getHandlerFor(Obj::HERO, elem->id)->getTemplates())
+		{
+			if (!heroAnims.count(templ.animationFile))
+			heroAnims[templ.animationFile] = loadHeroAnim(templ.animationFile, rotations);
+		}
 	}
 	}
 
 
 	boatAnims.push_back(loadHeroAnim("AB01_.DEF", rotations));
 	boatAnims.push_back(loadHeroAnim("AB01_.DEF", rotations));

+ 1 - 3
client/mapHandler.cpp

@@ -541,10 +541,8 @@ void CMapHandler::terrainRect( int3 top_tile, ui8 anim, const std::vector< std::
 						//pick graphics of hero (or boat if hero is sailing)
 						//pick graphics of hero (or boat if hero is sailing)
 						if (themp->boat)
 						if (themp->boat)
 							iv = &graphics->boatAnims[themp->boat->subID]->ourImages;
 							iv = &graphics->boatAnims[themp->boat->subID]->ourImages;
-						else if (themp->sex)
-							iv = &graphics->heroAnims[themp->type->heroClass->imageMapFemale]->ourImages;
 						else
 						else
-							iv = &graphics->heroAnims[themp->type->heroClass->imageMapMale]->ourImages;
+							iv = &graphics->heroAnims[themp->appearance.animationFile]->ourImages;
 
 
 						//pick appropriate flag set
 						//pick appropriate flag set
 						if(themp->boat)
 						if(themp->boat)

+ 36 - 90
config/heroClasses.json

@@ -6,11 +6,8 @@
 		"defaultTavern" : 5,
 		"defaultTavern" : 5,
 		"affinity" : "might",
 		"affinity" : "might",
 		"commander" : "zealot",
 		"commander" : "zealot",
-		"animation":
-		{
-			"battle" : { "male" : "CH00.DEF",  "female" : "CH01.DEF" },
-			"map":     { "male" : "AH00_.def", "female" : "AH00_.def" }
-		}
+		"mapObject" : { "templates" : { "default" : { "animation" : "AH00_.def" } } },
+		"animation":  { "battle" : { "male" : "CH00.DEF",  "female" : "CH01.DEF" } }
 	},
 	},
 	"cleric" :
 	"cleric" :
 	{
 	{
@@ -19,11 +16,8 @@
 		"defaultTavern" : 5,
 		"defaultTavern" : 5,
 		"affinity" : "magic",
 		"affinity" : "magic",
 		"commander" : "zealot",
 		"commander" : "zealot",
-		"animation":
-		{
-			"battle" : { "male" : "CH00.DEF",  "female" : "CH01.DEF" },
-			"map":     { "male" : "AH01_.def", "female" : "AH01_.def" }
-		}
+		"mapObject" : { "templates" : { "default" : { "animation" : "AH01_.def" } } },
+		"animation":  { "battle" : { "male" : "CH00.DEF",  "female" : "CH01.DEF" } }
 	},
 	},
 	"ranger" :
 	"ranger" :
 	{
 	{
@@ -32,11 +26,8 @@
 		"defaultTavern" : 5,
 		"defaultTavern" : 5,
 		"affinity" : "might",
 		"affinity" : "might",
 		"commander" : "grandElf",
 		"commander" : "grandElf",
-		"animation":
-		{
-			"battle" : { "male" : "CH02.DEF",  "female" : "CH03.DEF" },
-			"map":     { "male" : "AH02_.def", "female" : "AH02_.def" }
-		}
+		"mapObject" : { "templates" : { "default" : { "animation" : "AH02_.def" } } },
+		"animation":  { "battle" : { "male" : "CH02.DEF",  "female" : "CH03.DEF" } }
 	},
 	},
 	"druid" :
 	"druid" :
 	{
 	{
@@ -45,11 +36,8 @@
 		"defaultTavern" : 5,
 		"defaultTavern" : 5,
 		"affinity" : "magic",
 		"affinity" : "magic",
 		"commander" : "grandElf",
 		"commander" : "grandElf",
-		"animation":
-		{
-			"battle" : { "male" : "CH02.DEF",  "female" : "CH03.DEF" },
-			"map":     { "male" : "AH03_.def", "female" : "AH03_.def" }
-		}
+		"mapObject" : { "templates" : { "default" : { "animation" : "AH03_.def" } } },
+		"animation":  { "battle" : { "male" : "CH02.DEF",  "female" : "CH03.DEF" } }
 	},
 	},
 	"alchemist" :
 	"alchemist" :
 	{
 	{
@@ -58,11 +46,8 @@
 		"defaultTavern" : 5,
 		"defaultTavern" : 5,
 		"affinity" : "might",
 		"affinity" : "might",
 		"commander" : "archMage",
 		"commander" : "archMage",
-		"animation":
-		{
-			"battle" : { "male" : "CH05.DEF",  "female" : "CH04.DEF" },
-			"map":     { "male" : "AH04_.def", "female" : "AH04_.def" }
-		}
+		"mapObject" : { "templates" : { "default" : { "animation" : "AH04_.def" } } },
+		"animation":  { "battle" : { "male" : "CH05.DEF",  "female" : "CH04.DEF" } }
 	},
 	},
 	"wizard" :
 	"wizard" :
 	{
 	{
@@ -71,11 +56,8 @@
 		"defaultTavern" : 5,
 		"defaultTavern" : 5,
 		"affinity" : "magic",
 		"affinity" : "magic",
 		"commander" : "archMage",
 		"commander" : "archMage",
-		"animation":
-		{
-			"battle" : { "male" : "CH05.DEF",  "female" : "CH04.DEF" },
-			"map":     { "male" : "AH05_.def", "female" : "AH05_.def" }
-		}
+		"mapObject" : { "templates" : { "default" : { "animation" : "AH05_.def" } } },
+		"animation":  { "battle" : { "male" : "CH05.DEF",  "female" : "CH04.DEF" } }
 	},
 	},
 	"demoniac" :
 	"demoniac" :
 	{
 	{
@@ -84,11 +66,8 @@
 		"defaultTavern" : 5,
 		"defaultTavern" : 5,
 		"affinity" : "might",
 		"affinity" : "might",
 		"commander" : "magog",
 		"commander" : "magog",
-		"animation":
-		{
-			"battle" : { "male" : "CH06.DEF",  "female" : "CH07.DEF" },
-			"map":     { "male" : "AH06_.def", "female" : "AH06_.def" }
-		}
+		"mapObject" : { "templates" : { "default" : { "animation" : "AH06_.def" } } },
+		"animation":  { "battle" : { "male" : "CH06.DEF",  "female" : "CH07.DEF" } }
 	},
 	},
 	"heretic" :
 	"heretic" :
 	{
 	{
@@ -97,11 +76,8 @@
 		"defaultTavern" : 5,
 		"defaultTavern" : 5,
 		"affinity" : "magic",
 		"affinity" : "magic",
 		"commander" : "magog",
 		"commander" : "magog",
-		"animation":
-		{
-			"battle" : { "male" : "CH06.DEF",  "female" : "CH07.DEF" },
-			"map":     { "male" : "AH07_.def", "female" : "AH07_.def" }
-		}
+		"mapObject" : { "templates" : { "default" : { "animation" : "AH07_.def" } } },
+		"animation":  { "battle" : { "male" : "CH06.DEF",  "female" : "CH07.DEF" } }
 	},
 	},
 	"deathknight" :
 	"deathknight" :
 	{
 	{
@@ -110,11 +86,8 @@
 		"defaultTavern" : 5,
 		"defaultTavern" : 5,
 		"affinity" : "might",
 		"affinity" : "might",
 		"commander" : "powerLich",
 		"commander" : "powerLich",
-		"animation":
-		{
-			"battle" : { "male" : "CH08.DEF",  "female" : "CH09.DEF" },
-			"map":     { "male" : "AH08_.def", "female" : "AH08_.def" }
-		}
+		"mapObject" : { "templates" : { "default" : { "animation" : "AH08_.def" } } },
+		"animation":  { "battle" : { "male" : "CH08.DEF",  "female" : "CH09.DEF" } }
 	},
 	},
 	"necromancer" :
 	"necromancer" :
 	{
 	{
@@ -123,11 +96,8 @@
 		"defaultTavern" : 5,
 		"defaultTavern" : 5,
 		"affinity" : "magic",
 		"affinity" : "magic",
 		"commander" : "powerLich",
 		"commander" : "powerLich",
-		"animation":
-		{
-			"battle" : { "male" : "CH08.DEF",  "female" : "CH09.DEF" },
-			"map":     { "male" : "AH09_.def", "female" : "AH09_.def" }
-		}
+		"mapObject" : { "templates" : { "default" : { "animation" : "AH09_.def" } } },
+		"animation":  { "battle" : { "male" : "CH08.DEF",  "female" : "CH09.DEF" } }
 	},
 	},
 	"warlock" :
 	"warlock" :
 	{
 	{
@@ -136,11 +106,8 @@
 		"defaultTavern" : 5,
 		"defaultTavern" : 5,
 		"affinity" : "might",
 		"affinity" : "might",
 		"commander" : "medusaQueen",
 		"commander" : "medusaQueen",
-		"animation":
-		{
-			"battle" : { "male" : "CH010.DEF", "female" : "CH11.DEF" },
-			"map":     { "male" : "AH10_.def", "female" : "AH10_.def" }
-		}
+		"mapObject" : { "templates" : { "default" : { "animation" : "AH10_.def" } } },
+		"animation":  { "battle" : { "male" : "CH010.DEF",  "female" : "CH11.DEF" } }
 	},
 	},
 	"overlord" :
 	"overlord" :
 	{
 	{
@@ -149,11 +116,8 @@
 		"defaultTavern" : 5,
 		"defaultTavern" : 5,
 		"affinity" : "magic",
 		"affinity" : "magic",
 		"commander" : "medusaQueen",
 		"commander" : "medusaQueen",
-		"animation":
-		{
-			"battle" : { "male" : "CH010.DEF", "female" : "CH11.DEF" },
-			"map":     { "male" : "AH11_.def", "female" : "AH11_.def" }
-		}
+		"mapObject" : { "templates" : { "default" : { "animation" : "AH11_.def" } } },
+		"animation":  { "battle" : { "male" : "CH010.DEF",  "female" : "CH11.DEF" } }
 	},
 	},
 	"barbarian" :
 	"barbarian" :
 	{
 	{
@@ -162,11 +126,8 @@
 		"defaultTavern" : 5,
 		"defaultTavern" : 5,
 		"affinity" : "might",
 		"affinity" : "might",
 		"commander" : "orcChieftain",
 		"commander" : "orcChieftain",
-		"animation":
-		{
-			"battle" : { "male" : "CH013.DEF", "female" : "CH012.DEF" },
-			"map":     { "male" : "AH12_.def", "female" : "AH12_.def" }
-		}
+		"mapObject" : { "templates" : { "default" : { "animation" : "AH12_.def" } } },
+		"animation":  { "battle" : { "male" : "CH013.DEF",  "female" : "CH012.DEF" } }
 	},
 	},
 	"battlemage" :
 	"battlemage" :
 	{
 	{
@@ -175,11 +136,8 @@
 		"defaultTavern" : 5,
 		"defaultTavern" : 5,
 		"affinity" : "magic",
 		"affinity" : "magic",
 		"commander" : "orcChieftain",
 		"commander" : "orcChieftain",
-		"animation":
-		{
-			"battle" : { "male" : "CH013.DEF", "female" : "CH012.DEF" },
-			"map":     { "male" : "AH13_.def", "female" : "AH13_.def" }
-		}
+		"mapObject" : { "templates" : { "default" : { "animation" : "AH13_.def" } } },
+		"animation":  { "battle" : { "male" : "CH013.DEF",  "female" : "CH012.DEF" } }
 	},
 	},
 	"beastmaster" :
 	"beastmaster" :
 	{
 	{
@@ -188,11 +146,8 @@
 		"defaultTavern" : 5,
 		"defaultTavern" : 5,
 		"affinity" : "might",
 		"affinity" : "might",
 		"commander" : "lizardWarrior",
 		"commander" : "lizardWarrior",
-		"animation":
-		{
-			"battle" : { "male" : "CH014.DEF", "female" : "CH015.DEF" },
-			"map":     { "male" : "AH14_.def", "female" : "AH14_.def" }
-		}
+		"mapObject" : { "templates" : { "default" : { "animation" : "AH14_.def" } } },
+		"animation":  { "battle" : { "male" : "CH014.DEF",  "female" : "CH015.DEF" } }
 	},
 	},
 	"witch" :
 	"witch" :
 	{
 	{
@@ -201,11 +156,8 @@
 		"defaultTavern" : 5,
 		"defaultTavern" : 5,
 		"affinity" : "magic",
 		"affinity" : "magic",
 		"commander" : "lizardWarrior",
 		"commander" : "lizardWarrior",
-		"animation":
-		{
-			"battle" : { "male" : "CH014.DEF", "female" : "CH015.DEF" },
-			"map":     { "male" : "AH15_.def", "female" : "AH15_.def" }
-		}
+		"mapObject" : { "templates" : { "default" : { "animation" : "AH15_.def" } } },
+		"animation":  { "battle" : { "male" : "CH014.DEF",  "female" : "CH015.DEF" } }
 	},
 	},
 	"planeswalker" :
 	"planeswalker" :
 	{
 	{
@@ -214,11 +166,8 @@
 		"defaultTavern" : 5,
 		"defaultTavern" : 5,
 		"affinity" : "might",
 		"affinity" : "might",
 		"commander" : "iceElemental",
 		"commander" : "iceElemental",
-		"animation":
-		{
-			"battle" : { "male" : "CH16.DEF",  "female" : "CH16.DEF" },
-			"map":     { "male" : "AH16_.def", "female" : "AH16_.def" }
-		}
+		"mapObject" : { "templates" : { "default" : { "animation" : "AH16_.def" } } },
+		"animation":  { "battle" : { "male" : "CH16.DEF",  "female" : "CH16.DEF" } }
 	},
 	},
 	"elementalist" :
 	"elementalist" :
 	{
 	{
@@ -227,10 +176,7 @@
 		"defaultTavern" : 5,
 		"defaultTavern" : 5,
 		"affinity" : "magic",
 		"affinity" : "magic",
 		"commander" : "iceElemental",
 		"commander" : "iceElemental",
-		"animation":
-		{
-			"battle" : { "male" : "CH17.DEF",  "female" : "CH17.DEF" },
-			"map":     { "male" : "AH17_.def", "female" : "AH17_.def" }
-		}
+		"mapObject" : { "templates" : { "default" : { "animation" : "AH17_.def" } } },
+		"animation":  { "battle" : { "male" : "CH17.DEF",  "female" : "CH17.DEF" } }
 	}
 	}
 }
 }

+ 6 - 36
config/schemas/faction.json

@@ -104,46 +104,16 @@
 			"type":"object",
 			"type":"object",
 			"additionalProperties" : false,
 			"additionalProperties" : false,
 			"required" : [
 			"required" : [
-				"adventureMap", "buildingsIcons", "buildings", "creatures", "guildWindow", "names",
+				"mapObject", "buildingsIcons", "buildings", "creatures", "guildWindow", "names",
 				"hallBackground", "hallSlots", "horde", "mageGuild", "moatDamage", "defaultTavern", "tavernVideo", "guildBackground", "musicTheme", "siege", "structures", "townBackground", "warMachine"
 				"hallBackground", "hallSlots", "horde", "mageGuild", "moatDamage", "defaultTavern", "tavernVideo", "guildBackground", "musicTheme", "siege", "structures", "townBackground", "warMachine"
 			],
 			],
 			"description": "town",
 			"description": "town",
 			"properties":{
 			"properties":{
-				"adventureMap": {
-					"type":"object",
-					"additionalProperties" : false,
-					"description": "Paths to images of object on adventure map",
-					"required" : [ "capitol", "castle", "village" ],
-					"properties":{
-						"capitol": {
-							"type":"string",
-							"description": "Town with capitol",
-							"format" : "defFile"
-						},
-						"castle": {
-							"type":"string",
-							"description": "Town with built fort",
-							"format" : "defFile"
-						},
-						"village": {
-							"type":"string",
-							"description": "Village without built fort",
-							"format" : "defFile"
-						},
-						"dwellings" : {
-							"type" : "array",
-							"minItems" : 7,
-							"maxItems" : 7,
-							"description" : "Dwellings on adventure map",
-							"items" : {
-								"type" : "object",
-								"additionalProperties" : false,
-								"required" : [ "name", "graphics" ],
-								"properties" : {
-									"name":     { "type":"string" },
-									"graphics": { "type":"string", "format" : "defFile" }
-								}
-							}
+				"mapObject" : {
+					"properties" : {
+						"filters" : {
+							"type" : "object",
+							"additionalProperties" : { "type" : "array" }
 						}
 						}
 					}
 					}
 				},
 				},

+ 10 - 20
config/schemas/heroClass.json

@@ -6,7 +6,7 @@
 	"required" : [
 	"required" : [
 		"animation", "faction", "highLevelChance", "lowLevelChance",
 		"animation", "faction", "highLevelChance", "lowLevelChance",
 		"name", "primarySkills", "secondarySkills", "tavern", "defaultTavern",
 		"name", "primarySkills", "secondarySkills", "tavern", "defaultTavern",
-		"affinity", "commander"
+		"affinity", "commander", "mapObject"
 	],
 	],
 
 
 	"additionalProperties" : false,
 	"additionalProperties" : false,
@@ -15,7 +15,7 @@
 			"type":"object",
 			"type":"object",
 			"additionalProperties" : false,
 			"additionalProperties" : false,
 			"description": "Files related to hero animation",
 			"description": "Files related to hero animation",
-			"required": [ "battle", "map" ],
+			"required": [ "battle" ],
 			"properties":{
 			"properties":{
 				"battle": {
 				"battle": {
 					"type":"object",
 					"type":"object",
@@ -34,24 +34,14 @@
 							"format" : "defFile"
 							"format" : "defFile"
 						}
 						}
 					}
 					}
-				},
-				"map": {
-					"type":"object",
-					"additionalProperties" : false,
-					"description": "Hero animations for adventure map",
-					"required": [ "female", "male" ],
-					"properties":{
-						"female": {
-							"type":"string",
-							"description": "Female version. Warning: not implemented!",
-							"format" : "defFile"
-						},
-						"male": {
-							"type":"string",
-							"description": "Male version",
-							"format" : "defFile"
-						}
-					}
+				}
+			}
+		},
+		"mapObject" : {
+			"properties" : {
+				"filters" : {
+					"type" : "object",
+					"additionalProperties" : { "type" : "array" }
 				}
 				}
 			}
 			}
 		},
 		},

+ 1 - 1
config/schemas/objectType.json

@@ -17,7 +17,7 @@
 		"base": {
 		"base": {
 			"type" : "object"
 			"type" : "object"
 		},
 		},
-		"types": {
+		"templates": {
 			"type":"object",
 			"type":"object",
 			"additionalProperties": {
 			"additionalProperties": {
 				"$ref" : "vcmi:objectTemplate"
 				"$ref" : "vcmi:objectTemplate"

+ 2 - 1
lib/CHeroHandler.cpp

@@ -104,6 +104,7 @@ CHeroClass *CHeroClassHandler::loadFromJson(const JsonNode & node)
 
 
 	heroClass->imageBattleFemale = node["animation"]["battle"]["female"].String();
 	heroClass->imageBattleFemale = node["animation"]["battle"]["female"].String();
 	heroClass->imageBattleMale   = node["animation"]["battle"]["male"].String();
 	heroClass->imageBattleMale   = node["animation"]["battle"]["male"].String();
+	//MODS COMPATIBILITY FOR 0.96
 	heroClass->imageMapFemale    = node["animation"]["map"]["female"].String();
 	heroClass->imageMapFemale    = node["animation"]["map"]["female"].String();
 	heroClass->imageMapMale      = node["animation"]["map"]["male"].String();
 	heroClass->imageMapMale      = node["animation"]["map"]["male"].String();
 
 
@@ -223,7 +224,7 @@ void CHeroClassHandler::loadObject(std::string scope, std::string name, const Js
 
 
 	VLC->modh->identifiers.requestIdentifier(scope, "object", "hero", [=](si32 index)
 	VLC->modh->identifiers.requestIdentifier(scope, "object", "hero", [=](si32 index)
 	{
 	{
-		JsonNode classConf;
+		JsonNode classConf = data["mapObject"];
 		classConf["heroClass"].String() = name;
 		classConf["heroClass"].String() = name;
 		classConf.setMeta(scope);
 		classConf.setMeta(scope);
 		VLC->objtypeh->loadSubObject(name, classConf, index, object->id);
 		VLC->objtypeh->loadSubObject(name, classConf, index, object->id);

+ 9 - 0
lib/CTownHandler.cpp

@@ -764,6 +764,15 @@ void CTownHandler::loadObject(std::string scope, std::string name, const JsonNod
 			config["faction"].String() = object->identifier;
 			config["faction"].String() = object->identifier;
 			config["faction"].meta = scope;
 			config["faction"].meta = scope;
 			VLC->objtypeh->loadSubObject(object->identifier, config, index, object->index);
 			VLC->objtypeh->loadSubObject(object->identifier, config, index, object->index);
+
+			// MODS COMPATIBILITY FOR 0.96
+			auto & advMap = data["town"]["adventureMap"];
+			if (!advMap["fort"].isNull())
+			{
+				JsonNode config;
+				config["appearance"] = advMap["fort"];
+				VLC->objtypeh->getHandlerFor(index, object->index)->addTemplate(config);
+			}
 		});
 		});
 	}
 	}
 
 

+ 5 - 1
lib/mapObjects/CGHeroInstance.cpp

@@ -232,9 +232,9 @@ void CGHeroInstance::initHero(HeroTypeID SUBID)
 void CGHeroInstance::setType(si32 ID, si32 subID)
 void CGHeroInstance::setType(si32 ID, si32 subID)
 {
 {
 	assert(ID == Obj::HERO); // just in case
 	assert(ID == Obj::HERO); // just in case
-	CGObjectInstance::setType(ID, subID);
 	type = VLC->heroh->heroes[subID];
 	type = VLC->heroh->heroes[subID];
 	portrait = type->imageIndex;
 	portrait = type->imageIndex;
+	CGObjectInstance::setType(ID, type->heroClass->id);
 	randomizeArmy(type->heroClass->faction);
 	randomizeArmy(type->heroClass->faction);
 }
 }
 
 
@@ -472,6 +472,10 @@ void CGHeroInstance::initObj()
 	skillsInfo.resetMagicSchoolCounter();
 	skillsInfo.resetMagicSchoolCounter();
 	skillsInfo.resetWisdomCounter();
 	skillsInfo.resetWisdomCounter();
 
 
+	auto customApp = VLC->objtypeh->getHandlerFor(ID, type->heroClass->id)->getOverride(cb->gameState()->getTile(visitablePos())->terType, this);
+	if (customApp)
+		appearance = customApp.get();
+
 	for(const auto &spec : type->spec) //TODO: unfity with bonus system
 	for(const auto &spec : type->spec) //TODO: unfity with bonus system
 	{
 	{
 		auto bonus = new Bonus();
 		auto bonus = new Bonus();

+ 1 - 0
lib/mapObjects/CGTownInstance.cpp

@@ -563,6 +563,7 @@ void CGTownInstance::initObj()
 	//add special bonuses from buildings
 	//add special bonuses from buildings
 
 
 	recreateBuildingsBonuses();
 	recreateBuildingsBonuses();
+	updateAppearance();
 }
 }
 
 
 void CGTownInstance::newTurn() const
 void CGTownInstance::newTurn() const

+ 2 - 2
lib/mapObjects/CObjectClassesHandler.cpp

@@ -105,7 +105,7 @@ void readTextFile(Container & objects, std::string path)
 std::vector<JsonNode> CObjectClassesHandler::loadLegacyData(size_t dataSize)
 std::vector<JsonNode> CObjectClassesHandler::loadLegacyData(size_t dataSize)
 {
 {
 	readTextFile(legacyTemplates, "Data/Objects.txt");
 	readTextFile(legacyTemplates, "Data/Objects.txt");
-	readTextFile(legacyTemplates, "Data/Heroes.txt");
+	//readTextFile(legacyTemplates, "Data/Heroes.txt");
 
 
 	std::vector<JsonNode> ret(dataSize);// create storage for 256 objects
 	std::vector<JsonNode> ret(dataSize);// create storage for 256 objects
 	assert(dataSize == 256);
 	assert(dataSize == 256);
@@ -161,7 +161,7 @@ CObjectClassesHandler::ObjectContainter * CObjectClassesHandler::loadFromJson(co
 	auto obj = new ObjectContainter();
 	auto obj = new ObjectContainter();
 	obj->name = json["name"].String();
 	obj->name = json["name"].String();
 	obj->handlerName = json["handler"].String();
 	obj->handlerName = json["handler"].String();
-	obj->base = json["base"]; // FIXME: when this data will be actually merged?
+	obj->base = json["base"];
 	obj->id = selectNextID(json["index"], objects, 256);
 	obj->id = selectNextID(json["index"], objects, 256);
 	for (auto entry : json["types"].Struct())
 	for (auto entry : json["types"].Struct())
 	{
 	{

+ 1 - 1
lib/mapObjects/CObjectHandler.h

@@ -130,7 +130,7 @@ public:
 	//CGObjectInstance& operator=(const CGObjectInstance & right);
 	//CGObjectInstance& operator=(const CGObjectInstance & right);
 	virtual const std::string & getHoverText() const;
 	virtual const std::string & getHoverText() const;
 
 
-	void setType(si32 ID, si32 subID);
+	virtual void setType(si32 ID, si32 subID);
 
 
 	///IObjectInterface
 	///IObjectInterface
 	void initObj() override;
 	void initObj() override;

+ 24 - 0
lib/mapObjects/CommonConstructors.cpp

@@ -91,10 +91,34 @@ void CHeroInstanceConstructor::initTypeData(const JsonNode & input)
 {
 {
 	VLC->modh->identifiers.requestIdentifier("heroClass", input["heroClass"],
 	VLC->modh->identifiers.requestIdentifier("heroClass", input["heroClass"],
 			[&](si32 index) { heroClass = VLC->heroh->classes.heroClasses[index]; });
 			[&](si32 index) { heroClass = VLC->heroh->classes.heroClasses[index]; });
+
+	filtersJson = input["filters"];
+}
+
+void CHeroInstanceConstructor::afterLoadFinalization()
+{
+	for (auto entry : filtersJson.Struct())
+	{
+		filters[entry.first] = LogicalExpression<HeroTypeID>(entry.second, [this](const JsonNode & node)
+		{
+			return HeroTypeID(VLC->modh->identifiers.getIdentifier("hero", node.Vector()[0]).get());
+		});
+	}
 }
 }
 
 
 bool CHeroInstanceConstructor::objectFilter(const CGObjectInstance * object, const ObjectTemplate & templ) const
 bool CHeroInstanceConstructor::objectFilter(const CGObjectInstance * object, const ObjectTemplate & templ) const
 {
 {
+	auto hero = dynamic_cast<const CGHeroInstance *>(object);
+
+	auto heroTest = [&](const HeroTypeID & id)
+	{
+		return hero->type->ID == id;
+	};
+
+	if (filters.count(templ.stringID))
+	{
+		return filters.at(templ.stringID).test(heroTest);
+	}
 	return false;
 	return false;
 }
 }
 
 

+ 21 - 0
lib/mapObjects/CommonConstructors.h

@@ -73,20 +73,35 @@ public:
 	void initTypeData(const JsonNode & input);
 	void initTypeData(const JsonNode & input);
 	void configureObject(CGObjectInstance * object, CRandomGenerator & rng) const;
 	void configureObject(CGObjectInstance * object, CRandomGenerator & rng) const;
 	void afterLoadFinalization();
 	void afterLoadFinalization();
+
+	template <typename Handler> void serialize(Handler &h, const int version)
+	{
+		h & filtersJson & faction & filters;
+		h & static_cast<CDefaultObjectTypeHandler<CGTownInstance>&>(*this);
+	}
 };
 };
 
 
 class CHeroInstanceConstructor : public CDefaultObjectTypeHandler<CGHeroInstance>
 class CHeroInstanceConstructor : public CDefaultObjectTypeHandler<CGHeroInstance>
 {
 {
+	JsonNode filtersJson;
 protected:
 protected:
 	bool objectFilter(const CGObjectInstance *, const ObjectTemplate &) const;
 	bool objectFilter(const CGObjectInstance *, const ObjectTemplate &) const;
 
 
 public:
 public:
 	CHeroClass * heroClass;
 	CHeroClass * heroClass;
+	std::map<std::string, LogicalExpression<HeroTypeID>> filters;
 
 
 	CHeroInstanceConstructor();
 	CHeroInstanceConstructor();
 	CGObjectInstance * create(ObjectTemplate tmpl) const;
 	CGObjectInstance * create(ObjectTemplate tmpl) const;
 	void initTypeData(const JsonNode & input);
 	void initTypeData(const JsonNode & input);
 	void configureObject(CGObjectInstance * object, CRandomGenerator & rng) const;
 	void configureObject(CGObjectInstance * object, CRandomGenerator & rng) const;
+	void afterLoadFinalization();
+
+	template <typename Handler> void serialize(Handler &h, const int version)
+	{
+		h & filtersJson & heroClass & filters;
+		h & static_cast<CDefaultObjectTypeHandler<CGHeroInstance>&>(*this);
+	}
 };
 };
 
 
 class CDwellingInstanceConstructor : public CDefaultObjectTypeHandler<CGDwelling>
 class CDwellingInstanceConstructor : public CDefaultObjectTypeHandler<CGDwelling>
@@ -106,4 +121,10 @@ public:
 	void configureObject(CGObjectInstance * object, CRandomGenerator & rng) const;
 	void configureObject(CGObjectInstance * object, CRandomGenerator & rng) const;
 
 
 	bool producesCreature(const CCreature * crea) const;
 	bool producesCreature(const CCreature * crea) const;
+
+	template <typename Handler> void serialize(Handler &h, const int version)
+	{
+		h & availableCreatures & guards;
+		h & static_cast<CDefaultObjectTypeHandler<CGDwelling>&>(*this);
+	}
 };
 };

+ 0 - 2
lib/mapObjects/ObjectTemplate.cpp

@@ -185,8 +185,6 @@ void ObjectTemplate::readMap(CBinaryReader & reader)
 
 
 void ObjectTemplate::readJson(const JsonNode &node)
 void ObjectTemplate::readJson(const JsonNode &node)
 {
 {
-	//id = Obj(node["basebase"].Float()); // temporary, should be removed and determined indirectly via object type parent (e.g. base->base)
-	//subid = node["base"].Float();
 	animationFile = node["animation"].String();
 	animationFile = node["animation"].String();
 
 
 	const JsonVector & visitDirs = node["visitableFrom"].Vector();
 	const JsonVector & visitDirs = node["visitableFrom"].Vector();