Explorar o código

- H3M parser will create objects that don't have data in map file via
object handler.
- Added large number of missing objects to config

Ivan Savenko %!s(int64=11) %!d(string=hai) anos
pai
achega
955552488e

+ 118 - 99
config/objects/generic.json

@@ -8,126 +8,145 @@
 			"prison" : { "index" : 0 }
 			"prison" : { "index" : 0 }
 		}
 		}
 	},
 	},
-	
-	"altarOfSacrifice"				: { "index" :2,  "handler": "market" },
-	"tradingPost"					: { "index" :221, "handler": "market" },
-	"tradingPostDUPLICATE"			: { "index" :99, "handler": "market" },
-	"freelancersGuild"				: { "index" :213, "handler": "market" },
 
 
-	"blackMarket"					: { "index" :7,  "handler": "blackMarket" },
+	"altarOfSacrifice"				: { "index" :2,   "handler": "market", "types" : { "object" : { "index" : 0} } },
+	"tradingPost"					: { "index" :221, "handler": "market", "types" : { "object" : { "index" : 0} } },
+	"tradingPostDUPLICATE"			: { "index" :99,  "handler": "market", "types" : { "object" : { "index" : 0} } },
+	"freelancersGuild"				: { "index" :213, "handler": "market", "types" : { "object" : { "index" : 0} } },
+
+	"blackMarket"					: { "index" :7,   "handler": "blackMarket", "types" : { "object" : { "index" : 0} } },
 
 
-	"pandoraBox"					: { "index" :6,  "handler": "pandora" },
-	"event"							: { "index" :26, "handler": "event" },
+	"pandoraBox"					: { "index" :6,   "handler": "pandora", "types" : { "object" : { "index" : 0} } },
+	"event"							: { "index" :26,  "handler": "event", "types" : { "object" : { "index" : 0} } },
 
 
-	"redwoodObservatory"			: { "index" :58, "handler": "observatory" },
-	"pillarOfFire"					: { "index" :60, "handler": "observatory" },
-	"coverOfDarkness"				: { "index" :15, "handler": "observatory" },
+	"redwoodObservatory"			: { "index" :58,  "handler": "observatory", "types" : { "object" : { "index" : 0} } },
+	"pillarOfFire"					: { "index" :60,  "handler": "observatory", "types" : { "object" : { "index" : 0} } },
+	"coverOfDarkness"				: { "index" :15,  "handler": "observatory", "types" : { "object" : { "index" : 0} } },
 	
 	
-	"subterraneanGate"				: { "index" :103, "handler": "teleport" },
-	"whirlpool"						: { "index" :111, "handler": "teleport" },
+	"whirlpool"						: { "index" :111, "handler": "teleport", "types" : { "object" : { "index" : 0} } },
+	"subterraneanGate" : {
+		"index" :103,
+		"handler": "teleport",
+		"types" : {
+			"object" : { "index" : 0 },
+			"objectWoG" : { "index" : 1 } // WoG object? Present on VCMI Test 2011b
+		}
+	},
 
 
-	"refugeeCamp"					: { "index" :78, "handler": "dwelling" },
-	"warMachineFactory"				: { "index" :106, "handler": "dwelling" },
+	"refugeeCamp"					: { "index" :78,  "handler": "dwelling", "types" : { "object" : { "index" : 0} } },
+	"warMachineFactory"				: { "index" :106, "handler": "dwelling", "types" : { "object" : { "index" : 0} } },
 
 
-	"shrineOfMagicLevel1"			: { "index" :88, "handler": "shrine" },
-	"shrineOfMagicLevel2"			: { "index" :89, "handler": "shrine" },
-	"shrineOfMagicLevel3"			: { "index" :90, "handler": "shrine" },
+	"shrineOfMagicLevel1"			: { "index" :88,  "handler": "shrine", "types" : { "object" : { "index" : 0} } },
+	"shrineOfMagicLevel2"			: { "index" :89,  "handler": "shrine", "types" : { "object" : { "index" : 0} } },
+	"shrineOfMagicLevel3"			: { "index" :90,  "handler": "shrine", "types" : { "object" : { "index" : 0} } },
 
 
-	"eyeOfTheMagi"					: { "index" :27, "handler": "magi" },
-	"hutOfTheMagi"					: { "index" :37, "handler": "magi" },
+	"eyeOfTheMagi"					: { "index" :27,  "handler": "magi", "types" : { "object" : { "index" : 0} } },
+	"hutOfTheMagi"					: { "index" :37,  "handler": "magi", "types" : { "object" : { "index" : 0} } },
 
 
-	"lighthouse"					: { "index" :42, "handler": "lighthouse" },
-	"magicWell"						: { "index" :49, "handler": "magicWell" },
-	"obelisk"						: { "index" :57, "handler": "obelisk" },
-	"oceanBottle"					: { "index" :59, "handler": "sign" },
-	"scholar"						: { "index" :81, "handler": "scholar" },
-	"shipyard"						: { "index" :87, "handler": "shipyard" },
-	"sign"							: { "index" :91, "handler": "sign" },
-	"sirens"						: { "index" :92, "handler": "siren" },
-	"denOfThieves"					: { "index" :97, "handler": "denOfThieves" },
-	"university"					: { "index" :104, "handler": "university" },
-	"witchHut"						: { "index" :113, "handler": "witch" },
-	"questGuard"					: { "index" :215, "handler": "questGuard" },
+	"lighthouse"					: { "index" :42,  "handler": "lighthouse", "types" : { "object" : { "index" : 0} } },
+	"obelisk"						: { "index" :57,  "handler": "obelisk", "types" : { "object" : { "index" : 0} } },
+	"oceanBottle"					: { "index" :59,  "handler": "sign", "types" : { "object" : { "index" : 0} } },
+	"scholar"						: { "index" :81,  "handler": "scholar", "types" : { "object" : { "index" : 0} } },
+	"shipyard"						: { "index" :87,  "handler": "shipyard", "types" : { "object" : { "index" : 0} } },
+	"sign"							: { "index" :91,  "handler": "sign", "types" : { "object" : { "index" : 0} } },
+	"sirens"						: { "index" :92,  "handler": "siren", "types" : { "object" : { "index" : 0} } },
+	"denOfThieves"					: { "index" :97,  "handler": "denOfThieves", "types" : { "object" : { "index" : 0} } },
+	"university"					: { "index" :104, "handler": "university", "types" : { "object" : { "index" : 0} } },
+	"witchHut"						: { "index" :113, "handler": "witch", "types" : { "object" : { "index" : 0} } },
+	"questGuard"					: { "index" :215, "handler": "questGuard", "types" : { "object" : { "index" : 0} } },
+	"magicWell" : {
+		"index" :49,
+		"handler": "magicWell",
+		"types" : {
+			"object" : { "index" : 0},
+			"objectWoG" : { "index" : 1} // WoG object? Present on VCMI_Test 2011b
+		}
+	},
 
 
 	/// Random objects
 	/// Random objects
-	"randomResource"				: { "index" :76, "handler": "resource" },
-	"randomTown"					: { "index" :77, "handler": "town" },
-	"randomHero"					: { "index" :70, "handler": "hero" },
+	"randomResource"				: { "index" :76,  "handler": "resource" },
+	"randomTown"					: { "index" :77,  "handler": "town" },
+	"randomHero"					: { "index" :70,  "handler": "hero" },
 	
 	
 	"randomDwelling"				: { "index" :216, "handler": "dwelling" },
 	"randomDwelling"				: { "index" :216, "handler": "dwelling" },
 
 
-	"randomArtifact"				: { "index" :65, "handler": "artifact" },
-	"randomArtifactTreasure"		: { "index" :66, "handler": "artifact" },
-	"randomArtifactMinor"			: { "index" :67, "handler": "artifact" },
-	"randomArtifactMajor"			: { "index" :68, "handler": "artifact" },
-	"randomArtifactRelic"			: { "index" :69, "handler": "artifact" },
+	"randomArtifact"				: { "index" :65,  "handler": "artifact" },
+	"randomArtifactTreasure"		: { "index" :66,  "handler": "artifact" },
+	"randomArtifactMinor"			: { "index" :67,  "handler": "artifact" },
+	"randomArtifactMajor"			: { "index" :68,  "handler": "artifact" },
+	"randomArtifactRelic"			: { "index" :69,  "handler": "artifact" },
 
 
-	"randomMonster"					: { "index" :71, "handler": "monster" },
-	"randomMonsterLevel1"			: { "index" :72, "handler": "monster" },
-	"randomMonsterLevel2"			: { "index" :73, "handler": "monster" },
-	"randomMonsterLevel3"			: { "index" :74, "handler": "monster" },
-	"randomMonsterLevel4"			: { "index" :75, "handler": "monster" },
+	"randomMonster"					: { "index" :71,  "handler": "monster" },
+	"randomMonsterLevel1"			: { "index" :72,  "handler": "monster" },
+	"randomMonsterLevel2"			: { "index" :73,  "handler": "monster" },
+	"randomMonsterLevel3"			: { "index" :74,  "handler": "monster" },
+	"randomMonsterLevel4"			: { "index" :75,  "handler": "monster" },
 	"randomMonsterLevel5"			: { "index" :162, "handler": "monster" },
 	"randomMonsterLevel5"			: { "index" :162, "handler": "monster" },
 	"randomMonsterLevel6"			: { "index" :163, "handler": "monster" },
 	"randomMonsterLevel6"			: { "index" :163, "handler": "monster" },
 	"randomMonsterLevel7"			: { "index" :164, "handler": "monster" },
 	"randomMonsterLevel7"			: { "index" :164, "handler": "monster" },
 
 
 	/// Classes without dedicated object
 	/// Classes without dedicated object
-	"hillFort"						: { "index" :35, "handler": "generic" },
-	"grail"							: { "index" :36, "handler": "generic" },
-	"tavern"						: { "index" :95, "handler": "generic" },
-	"sanctuary"						: { "index" :80, "handler": "generic" },
+	"hillFort"						: { "index" :35,  "handler": "generic", "types" : { "object" : { "index" : 0} } },
+	"grail"							: { "index" :36,  "handler": "generic", "types" : { "object" : { "index" : 0} } },
+	"tavern"						: { "index" :95,  "handler": "generic", "types" : { "object" : { "index" : 0} } },
+	"sanctuary"						: { "index" :80,  "handler": "generic", "types" : { "object" : { "index" : 0} } },
 
 
 	/// Passive objects, terrain overlays
 	/// Passive objects, terrain overlays
-	"cursedGround"					: { "index" :21, "handler": "generic" },
-	"magicPlains"					: { "index" :46, "handler": "generic" },
-	"swampFoliage"					: { "index" :211, "handler": "generic" },
-	"cloverField"					: { "index" :222, "handler": "generic" },
-	"cursedGroundDUPLICATE"			: { "index" :223, "handler": "generic" },
-	"evilFog"						: { "index" :224, "handler": "generic" },
-	"favorableWinds"				: { "index" :225, "handler": "generic" },
-	"fieryFields"					: { "index" :226, "handler": "generic" },
-	"holyGround"					: { "index" :227, "handler": "generic" },
-	"lucidPools"					: { "index" :228, "handler": "generic" },
-	"magicClouds"					: { "index" :229, "handler": "generic" },
-	"magicPlainsDUPLICATE"			: { "index" :230, "handler": "generic" },
-	"rocklands"						: { "index" :231, "handler": "generic" },
+	"cursedGround"					: { "index" :21,  "handler": "generic", "types" : { "object" : { "index" : 0} } },
+	"magicPlains"					: { "index" :46,  "handler": "generic", "types" : { "object" : { "index" : 0} } },
+	"swampFoliage"					: { "index" :211, "handler": "generic", "types" : { "object" : { "index" : 0} } },
+	"cloverField"					: { "index" :222, "handler": "generic", "types" : { "object" : { "index" : 0} } },
+	"cursedGroundDUPLICATE"			: { "index" :223, "handler": "generic", "types" : { "object" : { "index" : 0} } },
+	"evilFog"						: { "index" :224, "handler": "generic", "types" : { "object" : { "index" : 0} } },
+	"favorableWinds"				: { "index" :225, "handler": "generic", "types" : { "object" : { "index" : 0} } },
+	"fieryFields"					: { "index" :226, "handler": "generic", "types" : { "object" : { "index" : 0} } },
+	"holyGround"					: { "index" :227, "handler": "generic", "types" : { "object" : { "index" : 0} } },
+	"lucidPools"					: { "index" :228, "handler": "generic", "types" : { "object" : { "index" : 0} } },
+	"magicClouds"					: { "index" :229, "handler": "generic", "types" : { "object" : { "index" : 0} } },
+	"magicPlainsDUPLICATE"			: { "index" :230, "handler": "generic", "types" : { "object" : { "index" : 0} } },
+	"rocklands"						: { "index" :231, "handler": "generic", "types" : { "object" : { "index" : 0} } },
 
 
 	/// Decorations
 	/// Decorations
-	"cactus"						: { "index" :116, "handler": "static" },
-	"canyon"						: { "index" :117, "handler": "static" },
-	"crater"						: { "index" :118, "handler": "static" },
-	"deadVegetation"				: { "index" :119, "handler": "static" },
-	"flowers"						: { "index" :120, "handler": "static" },
-	"frozenLake"					: { "index" :121, "handler": "static" },
-	"hole"							: { "index" :124, "handler": "static" },
-	"kelp"							: { "index" :125, "handler": "static" },
-	"lake"							: { "index" :126, "handler": "static" },
-	"lavaFlow"						: { "index" :127, "handler": "static" },
-	"lavaLake"						: { "index" :128, "handler": "static" },
-	"mushrooms"						: { "index" :129, "handler": "static" },
-	"log"							: { "index" :130, "handler": "static" },
-	"mandrake"						: { "index" :131, "handler": "static" },
-	"moss"							: { "index" :132, "handler": "static" },
-	"mound"							: { "index" :133, "handler": "static" },
-	"mountain"						: { "index" :134, "handler": "static" },
-	"oakTrees"						: { "index" :135, "handler": "static" },
-	"outcropping"					: { "index" :136, "handler": "static" },
-	"pineTrees"						: { "index" :137, "handler": "static" },
-	"riverDelta"					: { "index" :143, "handler": "static" },
-	"rock"							: { "index" :147, "handler": "static" },
-	"sandDune"						: { "index" :148, "handler": "static" },
-	"sandPit"						: { "index" :149, "handler": "static" },
-	"shrub"							: { "index" :150, "handler": "static" },
-	"skull"							: { "index" :151, "handler": "static" },
-	"stump"							: { "index" :153, "handler": "static" },
-	"trees"							: { "index" :155, "handler": "static" },
-	"volcano"						: { "index" :158, "handler": "static" },
-	"reef"							: { "index" :161, "handler": "static" },
-	"lakeDUPLICATE"					: { "index" :177, "handler": "static" },
-	"treesDUPLICATE"				: { "index" :199, "handler": "static" },
-	"desertHills"					: { "index" :206, "handler": "static" },
-	"dirtHills"						: { "index" :207, "handler": "static" },
-	"grassHills"					: { "index" :208, "handler": "static" },
-	"roughHills"					: { "index" :209, "handler": "static" },
-	"subterraneanRocks"				: { "index" :210, "handler": "static" }
+	"cactus"						: { "index" :116, "handler": "static", "types" : { "object" : { "index" : 0} } },
+	"canyon"						: { "index" :117, "handler": "static", "types" : { "object" : { "index" : 0} } },
+	"crater"						: { "index" :118, "handler": "static", "types" : { "object" : { "index" : 0} } },
+	"deadVegetation"				: { "index" :119, "handler": "static", "types" : { "object" : { "index" : 0} } },
+	"flowers"						: { "index" :120, "handler": "static", "types" : { "object" : { "index" : 0} } },
+	"frozenLake"					: { "index" :121, "handler": "static", "types" : { "object" : { "index" : 0} } },
+	"hole"							: { "index" :124, "handler": "static", "types" : { "object" : { "index" : 0} } },
+	"kelp"							: { "index" :125, "handler": "static", "types" : { "object" : { "index" : 0} } },
+	"lake"							: { "index" :126, "handler": "static", "types" : { "object" : { "index" : 0} } },
+	"lavaFlow"						: { "index" :127, "handler": "static", "types" : { "object" : { "index" : 0} } },
+	"lavaLake"						: { "index" :128, "handler": "static", "types" : { "object" : { "index" : 0} } },
+	"mushrooms"						: { "index" :129, "handler": "static", "types" : { "object" : { "index" : 0} } },
+	"log"							: { "index" :130, "handler": "static", "types" : { "object" : { "index" : 0} } },
+	"mandrake"						: { "index" :131, "handler": "static", "types" : { "object" : { "index" : 0} } },
+	"moss"							: { "index" :132, "handler": "static", "types" : { "object" : { "index" : 0} } },
+	"mound"							: { "index" :133, "handler": "static", "types" : { "object" : { "index" : 0} } },
+	"mountain"						: { "index" :134, "handler": "static", "types" : { "object" : { "index" : 0} } },
+	"oakTrees"						: { "index" :135, "handler": "static", "types" : { "object" : { "index" : 0} } },
+	"outcropping"					: { "index" :136, "handler": "static", "types" : { "object" : { "index" : 0} } },
+	"pineTrees"						: { "index" :137, "handler": "static", "types" : { "object" : { "index" : 0} } },
+	"riverDelta"					: { "index" :143, "handler": "static", "types" : { "object" : { "index" : 0} } },
+	"rock"							: { "index" :147, "handler": "static", "types" : { "object" : { "index" : 0} } },
+	"sandDune"						: { "index" :148, "handler": "static", "types" : { "object" : { "index" : 0} } },
+	"sandPit"						: { "index" :149, "handler": "static", "types" : { "object" : { "index" : 0} } },
+	"shrub"							: { "index" :150, "handler": "static", "types" : { "object" : { "index" : 0} } },
+	"skull"							: { "index" :151, "handler": "static", "types" : { "object" : { "index" : 0} } },
+	"stump"							: { "index" :153, "handler": "static", "types" : { "object" : { "index" : 0} } },
+	"trees"							: { "index" :155, "handler": "static", "types" : { "object" : { "index" : 0} } },
+	"volcano"						: { "index" :158, "handler": "static", "types" : { "object" : { "index" : 0} } },
+	"reef"							: { "index" :161, "handler": "static", "types" : { "object" : { "index" : 0} } },
+	"lakeDUPLICATE"					: { "index" :177, "handler": "static", "types" : { "object" : { "index" : 0} } },
+	"treesDUPLICATE"				: { "index" :199, "handler": "static", "types" : { "object" : { "index" : 0} } },
+	"desertHills"					: { "index" :206, "handler": "static", "types" : { "object" : { "index" : 0} } },
+	"dirtHills"						: { "index" :207, "handler": "static", "types" : { "object" : { "index" : 0} } },
+	"grassHills"					: { "index" :208, "handler": "static", "types" : { "object" : { "index" : 0} } },
+	"roughHills"					: { "index" :209, "handler": "static", "types" : { "object" : { "index" : 0} } },
+	"subterraneanRocks"				: { "index" :210, "handler": "static", "types" : { "object" : { "index" : 0} } },
+	
+	//These are WoG objects? They are not available in H3
+	"frozenLakeDUPLICATE"			: { "index" :172, "handler": "static", "types" : { "object" : { "index" : 0} } },
+	"oakTreesDUPLICATE"				: { "index" :186, "handler": "static", "types" : { "object" : { "index" : 0} } },
+	"plant"							: { "index" :189, "handler": "static", "types" : { "object" : { "index" : 0} } }
 }
 }

+ 42 - 3
config/objects/moddables.json

@@ -189,9 +189,48 @@
 	"garrisonVertical"				: { "index" :219, "handler": "garrison" },
 	"garrisonVertical"				: { "index" :219, "handler": "garrison" },
 
 
 	// Subtype: paired monoliths
 	// Subtype: paired monoliths
-	"monolithOneWayEntrance"		: { "index" :43, "handler": "teleport" },
-	"monolithOneWayExit"			: { "index" :44, "handler": "teleport" },
-	"monolithTwoWay"				: { "index" :45, "handler": "teleport" },
+	"monolithOneWayEntrance" : {
+		"index" :43,
+		"handler": "teleport",
+		"types" : {
+			"monolith1" : { "index" : 0 },
+			"monolith2" : { "index" : 1 },
+			"monolith3" : { "index" : 2 },
+			"monolith4" : { "index" : 3 },
+			"monolith5" : { "index" : 4 },
+			"monolith6" : { "index" : 5 },
+			"monolith7" : { "index" : 6 },
+			"monolith8" : { "index" : 7 }
+		}
+	},
+	"monolithOneWayExit" : {
+		"index" :44,
+		"handler": "teleport",
+		"types" : {
+			"monolith1" : { "index" : 0 },
+			"monolith2" : { "index" : 1 },
+			"monolith3" : { "index" : 2 },
+			"monolith4" : { "index" : 3 },
+			"monolith5" : { "index" : 4 },
+			"monolith6" : { "index" : 5 },
+			"monolith7" : { "index" : 6 },
+			"monolith8" : { "index" : 7 }
+		}
+	},
+	"monolithTwoWay" : {
+		"index" :45,
+		"handler": "teleport",
+		"types" : {
+			"monolith1" : { "index" : 0 },
+			"monolith2" : { "index" : 1 },
+			"monolith3" : { "index" : 2 },
+			"monolith4" : { "index" : 3 },
+			"monolith5" : { "index" : 4 },
+			"monolith6" : { "index" : 5 },
+			"monolith7" : { "index" : 6 },
+			"monolith8" : { "index" : 7 }
+		}
+	},
 
 
 	// subtype: different appearance. That's all?
 	// subtype: different appearance. That's all?
 	"seerHut" : { "index" :83, "handler": "seerHut" },
 	"seerHut" : { "index" :83, "handler": "seerHut" },

+ 43 - 36
config/objects/rewardable.json

@@ -1,44 +1,51 @@
 {
 {
 	/// These are objects that covered by concept of "configurable object"
 	/// These are objects that covered by concept of "configurable object"
 	/// Most or even all of their configuration located in this file
 	/// Most or even all of their configuration located in this file
-	"magicSpring"					: { "index" :48, "handler": "magicSpring" },
+	"magicSpring"					: { "index" :48, "handler": "magicSpring", "types" : { "object" : { "index" : 0} } },
 
 
-	"mysticalGarden"				: { "index" :55, "handler": "oncePerWeek" },
-	"windmill"						: { "index" :112, "handler": "oncePerWeek" },
-	"waterWheel"					: { "index" :109, "handler": "oncePerWeek" },
+	"mysticalGarden"				: { "index" :55, "handler": "oncePerWeek", "types" : { "object" : { "index" : 0} } },
+	"windmill"						: { "index" :112, "handler": "oncePerWeek", "types" : { "object" : { "index" : 0} } },
+	"waterWheel"					: { "index" :109, "handler": "oncePerWeek", "types" : { "object" : { "index" : 0} } },
 	
 	
-	"leanTo"						: { "index" :39, "handler": "onceVisitable" },
-	"corpse"						: { "index" :22, "handler": "onceVisitable" },
-	"wagon"							: { "index" :105, "handler": "onceVisitable" },
-	"warriorTomb"					: { "index" :108, "handler": "onceVisitable" },
+	"leanTo"						: { "index" :39, "handler": "onceVisitable", "types" : { "object" : { "index" : 0} } },
+	"corpse"						: { "index" :22, "handler": "onceVisitable", "types" : { "object" : { "index" : 0} } },
+	"wagon"							: { "index" :105, "handler": "onceVisitable", "types" : { "object" : { "index" : 0} } },
+	"warriorTomb"					: { "index" :108, "handler": "onceVisitable", "types" : { "object" : { "index" : 0} } },
 
 
-	"campfire"						: { "index" :12, "handler": "pickable" },
-	"flotsam"						: { "index" :29, "handler": "pickable" },
-	"seaChest"						: { "index" :82, "handler": "pickable" },
-	"shipwreckSurvivor"				: { "index" :86, "handler": "pickable" },
-	"treasureChest"					: { "index" :101, "handler": "pickable" },
+	"campfire"						: { "index" :12, "handler": "pickable", "types" : { "object" : { "index" : 0} } },
+	"flotsam"						: { "index" :29, "handler": "pickable", "types" : { "object" : { "index" : 0} } },
+	"seaChest"						: { "index" :82, "handler": "pickable", "types" : { "object" : { "index" : 0} } },
+	"shipwreckSurvivor"				: { "index" :86, "handler": "pickable", "types" : { "object" : { "index" : 0} } },
+	"treasureChest"					: { "index" :101, "handler": "pickable", "types" : { "object" : { "index" : 0} } },
 
 
-	"arena"							: { "index" :4,  "handler": "oncePerHero" },
-	"marlettoTower"					: { "index" :23, "handler": "oncePerHero" },
-	"gardenOfRevelation"			: { "index" :32, "handler": "oncePerHero" },
-	"libraryOfEnlightenment"		: { "index" :41, "handler": "oncePerHero" },
-	"mercenaryCamp"					: { "index" :51, "handler": "oncePerHero" },
-	"starAxis"						: { "index" :61, "handler": "oncePerHero" },
-	"learningStone"					: { "index" :100, "handler": "oncePerHero" },
-	"treeOfKnowledge"				: { "index" :102, "handler": "oncePerHero" },
-	"schoolOfMagic"					: { "index" :47, "handler": "oncePerHero" },
-	"schoolOfWar"					: { "index" :107, "handler": "oncePerHero" },
-	
-	"buoy"							: { "index" :11, "handler": "bonusingObject" },
-	"swanPond"						: { "index" :14, "handler": "bonusingObject" },
-	"faerieRing"					: { "index" :28, "handler": "bonusingObject" },
-	"fountainOfFortune"				: { "index" :30, "handler": "bonusingObject" },
-	"fountainOfYouth"				: { "index" :31, "handler": "bonusingObject" },
-	"idolOfFortune"					: { "index" :38, "handler": "bonusingObject" },
-	"mermaids"						: { "index" :52, "handler": "bonusingObject" },
-	"oasis"							: { "index" :56, "handler": "bonusingObject" },
-	"stables"						: { "index" :94, "handler": "bonusingObject" },
-	"temple"						: { "index" :96, "handler": "bonusingObject" },
-	"rallyFlag"						: { "index" :64, "handler": "bonusingObject" },
-	"wateringHole"					: { "index" :110, "handler": "bonusingObject" },	
+	"arena"							: { "index" :4,  "handler": "oncePerHero", "types" : { "object" : { "index" : 0} } },
+	"marlettoTower"					: { "index" :23, "handler": "oncePerHero", "types" : { "object" : { "index" : 0} } },
+	"gardenOfRevelation"			: { "index" :32, "handler": "oncePerHero", "types" : { "object" : { "index" : 0} } },
+	"libraryOfEnlightenment"		: { "index" :41, "handler": "oncePerHero", "types" : { "object" : { "index" : 0} } },
+	"mercenaryCamp"					: { "index" :51, "handler": "oncePerHero", "types" : { "object" : { "index" : 0} } },
+	"starAxis"						: { "index" :61, "handler": "oncePerHero", "types" : { "object" : { "index" : 0} } },
+	"treeOfKnowledge"				: { "index" :102, "handler": "oncePerHero", "types" : { "object" : { "index" : 0} } },
+	"schoolOfMagic"					: { "index" :47, "handler": "oncePerHero", "types" : { "object" : { "index" : 0} } },
+	"schoolOfWar"					: { "index" :107, "handler": "oncePerHero", "types" : { "object" : { "index" : 0} } },
+	"learningStone" : {
+		"index" :100,
+		"handler": "oncePerHero",
+		"types" : {
+			"object" : { "index" : 0},
+			"objectWoG" : { "index" : 1} // WoG object? Present on VCMI_Tests 2011
+		}
+	},
+
+	"buoy"							: { "index" :11, "handler": "bonusingObject", "types" : { "object" : { "index" : 0} } },
+	"swanPond"						: { "index" :14, "handler": "bonusingObject", "types" : { "object" : { "index" : 0} } },
+	"faerieRing"					: { "index" :28, "handler": "bonusingObject", "types" : { "object" : { "index" : 0} } },
+	"fountainOfFortune"				: { "index" :30, "handler": "bonusingObject", "types" : { "object" : { "index" : 0} } },
+	"fountainOfYouth"				: { "index" :31, "handler": "bonusingObject", "types" : { "object" : { "index" : 0} } },
+	"idolOfFortune"					: { "index" :38, "handler": "bonusingObject", "types" : { "object" : { "index" : 0} } },
+	"mermaids"						: { "index" :52, "handler": "bonusingObject", "types" : { "object" : { "index" : 0} } },
+	"oasis"							: { "index" :56, "handler": "bonusingObject", "types" : { "object" : { "index" : 0} } },
+	"stables"						: { "index" :94, "handler": "bonusingObject", "types" : { "object" : { "index" : 0} } },
+	"temple"						: { "index" :96, "handler": "bonusingObject", "types" : { "object" : { "index" : 0} } },
+	"rallyFlag"						: { "index" :64, "handler": "bonusingObject", "types" : { "object" : { "index" : 0} } },
+	"wateringHole"					: { "index" :110, "handler": "bonusingObject", "types" : { "object" : { "index" : 0} } }
 }
 }

+ 4 - 2
lib/mapObjects/CObjectClassesHandler.cpp

@@ -276,8 +276,10 @@ void CObjectClassesHandler::afterLoadFinalization()
 
 
 std::string CObjectClassesHandler::getObjectName(si32 type) const
 std::string CObjectClassesHandler::getObjectName(si32 type) const
 {
 {
-	assert(objects.count(type));
-	return objects.at(type)->name;
+	if (objects.count(type))
+		return objects.at(type)->name;
+	logGlobal->errorStream() << "Access to non existing object of type "  << type;
+	return "";
 }
 }
 
 
 void AObjectTypeHandler::setType(si32 type, si32 subtype)
 void AObjectTypeHandler::setType(si32 type, si32 subtype)

+ 10 - 161
lib/mapping/MapFormatH3M.cpp

@@ -1063,56 +1063,6 @@ void CMapLoaderH3M::readObjects()
 				nobj = readHero(idToBeGiven);
 				nobj = readHero(idToBeGiven);
 				break;
 				break;
 			}
 			}
-		case Obj::ARENA:
-		case Obj::MERCENARY_CAMP:
-		case Obj::MARLETTO_TOWER:
-		case Obj::STAR_AXIS:
-		case Obj::GARDEN_OF_REVELATION:
-		case Obj::LEARNING_STONE:
-		case Obj::TREE_OF_KNOWLEDGE:
-		case Obj::LIBRARY_OF_ENLIGHTENMENT:
-		case Obj::SCHOOL_OF_MAGIC:
-		case Obj::SCHOOL_OF_WAR:
-			{
-				nobj = new CGVisitableOPH();
-				break;
-			}
-		case Obj::MYSTICAL_GARDEN:
-		case Obj::WINDMILL:
-		case Obj::WATER_WHEEL:
-			{
-				nobj = new CGVisitableOPW();
-				break;
-			}
-		case Obj::MONOLITH_ONE_WAY_ENTRANCE:
-		case Obj::MONOLITH_ONE_WAY_EXIT:
-		case Obj::MONOLITH_TWO_WAY:
-		case Obj::SUBTERRANEAN_GATE:
-		case Obj::WHIRLPOOL:
-			{
-				nobj = new CGTeleport();
-				break;
-			}
-		case Obj::CAMPFIRE:
-		case Obj::FLOTSAM:
-		case Obj::SEA_CHEST:
-		case Obj::SHIPWRECK_SURVIVOR:
-			{
-				nobj = new CGPickable();
-				break;
-			}
-		case Obj::TREASURE_CHEST:
-				if(objTempl.subid == 0)
-				{
-					nobj = new CGPickable();
-				}
-				else
-				{
-					//WoG pickable object
-					//TODO: possible special handling
-					nobj = new CGObjectInstance();
-				}
-				break;
 		case Obj::MONSTER:  //Monster
 		case Obj::MONSTER:  //Monster
 		case Obj::RANDOM_MONSTER:
 		case Obj::RANDOM_MONSTER:
 		case Obj::RANDOM_MONSTER_L1:
 		case Obj::RANDOM_MONSTER_L1:
@@ -1330,12 +1280,6 @@ void CMapLoaderH3M::readObjects()
 				reader.skip(3);
 				reader.skip(3);
 				break;
 				break;
 			}
 			}
-		case Obj::REFUGEE_CAMP:
-		case Obj::WAR_MACHINE_FACTORY:
-			{
-				nobj = new CGDwelling();
-				break;
-			}
 		case Obj::SHRINE_OF_MAGIC_INCANTATION:
 		case Obj::SHRINE_OF_MAGIC_INCANTATION:
 		case Obj::SHRINE_OF_MAGIC_GESTURE:
 		case Obj::SHRINE_OF_MAGIC_GESTURE:
 		case Obj::SHRINE_OF_MAGIC_THOUGHT:
 		case Obj::SHRINE_OF_MAGIC_THOUGHT:
@@ -1458,52 +1402,6 @@ void CMapLoaderH3M::readObjects()
 				nobj = guard;
 				nobj = guard;
 				break;
 				break;
 			}
 			}
-		case Obj::FAERIE_RING:
-		case Obj::SWAN_POND:
-		case Obj::IDOL_OF_FORTUNE:
-		case Obj::FOUNTAIN_OF_FORTUNE:
-		case Obj::RALLY_FLAG:
-		case Obj::OASIS:
-		case Obj::TEMPLE:
-		case Obj::WATERING_HOLE:
-		case Obj::FOUNTAIN_OF_YOUTH:
-		case Obj::BUOY:
-		case Obj::MERMAID:
-		case Obj::STABLES:
-			{
-				nobj = new CGBonusingObject();
-				break;
-			}
-		case Obj::MAGIC_WELL:
-			{
-				nobj = new CGMagicWell();
-				break;
-			}
-		case Obj::COVER_OF_DARKNESS:
-		case Obj::REDWOOD_OBSERVATORY:
-		case Obj::PILLAR_OF_FIRE:
-			{
-				nobj = new CGObservatory();
-				break;
-			}
-		case Obj::CORPSE:
-		case Obj::LEAN_TO:
-		case Obj::WAGON:
-		case Obj::WARRIORS_TOMB:
-			{
-				nobj = new CGOnceVisitable();
-				break;
-			}
-		case Obj::BOAT:
-			{
-				nobj = new CGBoat();
-				break;
-			}
-		case Obj::SIRENS:
-			{
-				nobj = new CGSirens();
-				break;
-			}
 		case Obj::SHIPYARD:
 		case Obj::SHIPYARD:
 			{
 			{
 				nobj = new CGShipyard();
 				nobj = new CGShipyard();
@@ -1531,11 +1429,6 @@ void CMapLoaderH3M::readObjects()
 					hp->power = 0;
 					hp->power = 0;
 				}
 				}
 
 
-				break;
-			}
-		case Obj::KEYMASTER:
-			{
-				nobj = new CGKeymasterTent();
 				break;
 				break;
 			}
 			}
 		case Obj::BORDERGUARD:
 		case Obj::BORDERGUARD:
@@ -1550,21 +1443,6 @@ void CMapLoaderH3M::readObjects()
 				map->addQuest (nobj);
 				map->addQuest (nobj);
 				break;
 				break;
 			}
 			}
-		case Obj::EYE_OF_MAGI:
-		case Obj::HUT_OF_MAGI:
-			{
-				nobj = new CGMagi();
-				break;
-			}
-		case Obj::CREATURE_BANK:
-		case Obj::DERELICT_SHIP:
-		case Obj::DRAGON_UTOPIA:
-		case Obj::CRYPT:
-		case Obj::SHIPWRECK:
-			{
-				nobj = new CBank();
-				break;
-			}
 		case Obj::PYRAMID: //Pyramid of WoG object
 		case Obj::PYRAMID: //Pyramid of WoG object
 			{
 			{
 				if(objTempl.subid == 0)
 				if(objTempl.subid == 0)
@@ -1579,53 +1457,24 @@ void CMapLoaderH3M::readObjects()
 				}
 				}
 				break;
 				break;
 			}
 			}
-		case Obj::CARTOGRAPHER:
-			{
-				nobj = new CCartographer();
-				break;
-			}
-		case Obj::MAGIC_SPRING:
-			{
-				nobj = new CGMagicSpring();
-				break;
-			}
-		case Obj::DEN_OF_THIEVES:
-			{
-				nobj = new CGDenOfthieves();
-				break;
-			}
-		case Obj::OBELISK:
-			{
-				nobj = new CGObelisk();
-				break;
-			}
 		case Obj::LIGHTHOUSE: //Lighthouse
 		case Obj::LIGHTHOUSE: //Lighthouse
 			{
 			{
 				nobj = new CGLighthouse();
 				nobj = new CGLighthouse();
 				nobj->tempOwner = PlayerColor(reader.readUInt32());
 				nobj->tempOwner = PlayerColor(reader.readUInt32());
 				break;
 				break;
 			}
 			}
-		case Obj::ALTAR_OF_SACRIFICE:
-		case Obj::TRADING_POST:
-		case Obj::FREELANCERS_GUILD:
-		case Obj::TRADING_POST_SNOW:
-			{
-				nobj = new CGMarket();
-				break;
-			}
-		case Obj::UNIVERSITY:
-			{
-				nobj = new CGUniversity();
-				break;
-			}
-		case Obj::BLACK_MARKET:
-			{
-				nobj = new CGBlackMarket();
-				break;
-			}
 		default: //any other object
 		default: //any other object
 			{
 			{
-				nobj = new CGObjectInstance();
+				if (VLC->objtypeh->knownSubObjects(objTempl.id).count(objTempl.subid))
+				{
+					nobj = VLC->objtypeh->getHandlerFor(objTempl.id, objTempl.subid)->create(objTempl);
+				}
+				else
+				{
+					logGlobal->warnStream() << "Unrecognized object: " << objTempl.id << ":" << objTempl.subid << " at " << objPos
+											<< " on map " << map->name;
+					nobj = new CGObjectInstance();
+				}
 				break;
 				break;
 			}
 			}
 		}
 		}