Sfoglia il codice sorgente

- First part of objects configuration
- split objects into 3 files (for now)
- integrated object class handler into mod handler

Ivan Savenko 11 anni fa
parent
commit
67f11b1a01

+ 7 - 0
config/gameConfig.json

@@ -45,6 +45,13 @@
 		"config/heroes/special.json"
 	],
 
+	"objects" :
+	[
+		"config/objects/generic.json",
+		"config/objects/moddables.json",
+		"config/objects/rewardable.json"
+	],
+
 	"artifacts" :
 	[
 		"config/artifacts.json"

+ 70 - 105
config/objects/generic.json

@@ -1,111 +1,98 @@
 {
+	/// These are objects that can not be configured, either due to
+	/// their hardcoded status or because they don't have any configurable functionality
+	
 	"altarOfSacrifice"				: { "id" :2,  "handler": "market" },
-	"arena"							: { "id" :4,  "handler": "oncePerHero" },
-	"artifact"						: { "id" :5,  "handler": "artifact" },
-	"pandoraBox"					: { "id" :6,  "handler": "pandora" },
+	"tradingPost"					: { "id" :221, "handler": "market" },
+	"tradingPost"					: { "id" :99, "handler": "market" },
+	"freelancer'SGuild"				: { "id" :213, "handler": "market" },
+
 	"blackMarket"					: { "id" :7,  "handler": "blackMarket" },
-	"boat"							: { "id" :8,  "handler": "boat" },
-	"borderGuard"					: { "id" :9,  "handler": "borderGuard" },
-	"keymasterTent"					: { "id" :10, "handler": "keymaster" },
-	"buoy"							: { "id" :11, "handler": "bonusingObject" },
-	"campfire"						: { "id" :12, "handler": "pickable" },
-	"cartographer"					: { "id" :13, "handler": "cartographer" },
-	"swanPond"						: { "id" :14, "handler": "bonusingObject" },
-	"coverOfDarkness"				: { "id" :15, "handler": "observatory" },
-	"creatureBank"					: { "id" :16, "handler": "bank" },
-	"creatureGeneratorCommon"		: { "id" :17, "handler": "dwelling" },
-	"creatureGeneratorSpecial"		: { "id" :20, "handler": "dwelling" },
-	"cursedGround"					: { "id" :21, "handler": "generic" },
-	"corpse"						: { "id" :22, "handler": "onceVisitable" },
-	"marlettoTower"					: { "id" :23, "handler": "oncePerHero" },
+
+	"crypt"							: { "id" :84, "handler": "bank" },
+	"shipwreck"						: { "id" :85, "handler": "bank" },
 	"derelictShip"					: { "id" :24, "handler": "bank" },
 	"dragonUtopia"					: { "id" :25, "handler": "bank" },
+
+	"pandoraBox"					: { "id" :6,  "handler": "pandora" },
 	"event"							: { "id" :26, "handler": "event" },
+
+	"redwoodObservatory"			: { "id" :58, "handler": "observatory" },
+	"pillarOfFire"					: { "id" :60, "handler": "observatory" },
+	"coverOfDarkness"				: { "id" :15, "handler": "observatory" },
+	
+	"subterraneanGate"				: { "id" :103, "handler": "teleport" },
+	"whirlpool"						: { "id" :111, "handler": "teleport" },
+
+	"refugeeCamp"					: { "id" :78, "handler": "dwelling" },
+	"warMachineFactory"				: { "id" :106, "handler": "dwelling" },
+
+	"shrineOfMagicLevel1"			: { "id" :88, "handler": "shrine" },
+	"shrineOfMagicLevel2"			: { "id" :89, "handler": "shrine" },
+	"shrineOfMagicLevel3"			: { "id" :90, "handler": "shrine" },
+
 	"eyeOfTheMagi"					: { "id" :27, "handler": "magi" },
-	"faerieRing"					: { "id" :28, "handler": "bonusingObject" },
-	"flotsam"						: { "id" :29, "handler": "pickable" },
-	"fountainOfFortune"				: { "id" :30, "handler": "bonusingObject" },
-	"fountainOfYouth"				: { "id" :31, "handler": "bonusingObject" },
-	"gardenOfRevelation"			: { "id" :32, "handler": "oncePerHero" },
-	"garrison"						: { "id" :33, "handler": "garrison" },
-	"hero"							: { "id" :34, "handler": "hero" },
-	"hillFort"						: { "id" :35, "handler": "generic" },
-	"grail"							: { "id" :36, "handler": "generic" },
 	"hutOfTheMagi"					: { "id" :37, "handler": "magi" },
-	"idolOfFortune"					: { "id" :38, "handler": "bonusingObject" },
-	"leanTo"						: { "id" :39, "handler": "onceVisitable" },
-	"libraryOfEnlightenment"		: { "id" :41, "handler": "oncePerHero" },
+
 	"lighthouse"					: { "id" :42, "handler": "lighthouse" },
-	"monolithOneWayEntrance"		: { "id" :43, "handler": "teleport" },
-	"monolithOneWayExit"			: { "id" :44, "handler": "teleport" },
-	"monolithTwoWay"				: { "id" :45, "handler": "teleport" },
-	"magicPlains"					: { "id" :46, "handler": "generic" },
-	"schoolOfMagic"					: { "id" :47, "handler": "oncePerHero" },
-	"magicSpring"					: { "id" :48, "handler": "magicSpring" },
 	"magicWell"						: { "id" :49, "handler": "magicWell" },
-	"mercenaryCamp"					: { "id" :51, "handler": "oncePerHero" },
-	"mermaids"						: { "id" :52, "handler": "bonusingObject" },
-	"mine"							: { "id" :53, "handler": "mine" },
-	"monster"						: { "id" :54, "handler": "monster" },
-	"mysticalGarden"				: { "id" :55, "handler": "oncePerWeek" },
-	"oasis"							: { "id" :56, "handler": "bonusingObject" },
 	"obelisk"						: { "id" :57, "handler": "obelisk" },
-	"redwoodObservatory"			: { "id" :58, "handler": "observatory" },
 	"oceanBottle"					: { "id" :59, "handler": "sign" },
-	"pillarOfFire"					: { "id" :60, "handler": "observatory" },
-	"starAxis"						: { "id" :61, "handler": "oncePerHero" },
 	"prison"						: { "id" :62, "handler": "hero" },
 	"pyramid"						: { "id" :63, "handler": "pyramid" },
-	"rallyFlag"						: { "id" :64, "handler": "bonusingObject" },
+	"scholar"						: { "id" :81, "handler": "scholar" },
+	"shipyard"						: { "id" :87, "handler": "shipyard" },
+	"sign"							: { "id" :91, "handler": "sign" },
+	"sirens"						: { "id" :92, "handler": "siren" },
+	"denOfThieves"					: { "id" :97, "handler": "denOfThieves" },
+	"university"					: { "id" :104, "handler": "university" },
+	"witchHut"						: { "id" :113, "handler": "witch" },
+	"questGuard"					: { "id" :215, "handler": "questGuard" },
+
+	/// Random objects
+	"randomResource"				: { "id" :76, "handler": "resource" },
+	"randomTown"					: { "id" :77, "handler": "town" },
+	"randomHero"					: { "id" :70, "handler": "hero" },
+	
+	"randomDwelling"				: { "id" :216, "handler": "dwelling" },
+
 	"randomArtifact"				: { "id" :65, "handler": "artifact" },
 	"randomArtifactTreasure"		: { "id" :66, "handler": "artifact" },
 	"randomArtifactMinor"			: { "id" :67, "handler": "artifact" },
 	"randomArtifactMajor"			: { "id" :68, "handler": "artifact" },
 	"randomArtifactRelic"			: { "id" :69, "handler": "artifact" },
-	"randomHero"					: { "id" :70, "handler": "hero" },
+
 	"randomMonster"					: { "id" :71, "handler": "monster" },
 	"randomMonsterLevel1"			: { "id" :72, "handler": "monster" },
 	"randomMonsterLevel2"			: { "id" :73, "handler": "monster" },
 	"randomMonsterLevel3"			: { "id" :74, "handler": "monster" },
 	"randomMonsterLevel4"			: { "id" :75, "handler": "monster" },
-	"randomResource"				: { "id" :76, "handler": "resource" },
-	"randomTown"					: { "id" :77, "handler": "town" },
-	"refugeeCamp"					: { "id" :78, "handler": "dwelling" },
-	"resource"						: { "id" :79, "handler": "resource" },
-	"sanctuary"						: { "id" :80, "handler": "generic" },
-	"scholar"						: { "id" :81, "handler": "scholar" },
-	"seaChest"						: { "id" :82, "handler": "pickable" },
-	"seerHut"						: { "id" :83, "handler": "seerHut" },
-	"crypt"							: { "id" :84, "handler": "bank" },
-	"shipwreck"						: { "id" :85, "handler": "bank" },
-	"shipwreckSurvivor"				: { "id" :86, "handler": "pickable" },
-	"shipyard"						: { "id" :87, "handler": "shipyard" },
-	"shrineOfMagicLevel1"			: { "id" :88, "handler": "shrine" },
-	"shrineOfMagicLevel2"			: { "id" :89, "handler": "shrine" },
-	"shrineOfMagicLevel3"			: { "id" :90, "handler": "shrine" },
-	"sign"							: { "id" :91, "handler": "sign" },
-	"sirens"						: { "id" :92, "handler": "siren" },
-	"spellScroll"					: { "id" :93, "handler": "artifact" },
-	"stables"						: { "id" :94, "handler": "bonusingObject" },
+	"randomMonsterLevel5"			: { "id" :162, "handler": "monster" },
+	"randomMonsterLevel6"			: { "id" :163, "handler": "monster" },
+	"randomMonsterLevel7"			: { "id" :164, "handler": "monster" },
+
+	/// Classes without dedicated object
+	"hillFort"						: { "id" :35, "handler": "generic" },
+	"grail"							: { "id" :36, "handler": "generic" },
 	"tavern"						: { "id" :95, "handler": "generic" },
-	"temple"						: { "id" :96, "handler": "bonusingObject" },
-	"denOfThieves"					: { "id" :97, "handler": "denOfThieves" },
-	"town"							: { "id" :98, "handler": "town" },
-	"tradingPost"					: { "id" :99, "handler": "market" },
-	"learningStone"					: { "id" :100, "handler": "oncePerHero" },
-	"treasureChest"					: { "id" :101, "handler": "pickable" },
-	"treeOfKnowledge"				: { "id" :102, "handler": "oncePerHero" },
-	"subterraneanGate"				: { "id" :103, "handler": "teleport" },
-	"university"					: { "id" :104, "handler": "university" },
-	"wagon"							: { "id" :105, "handler": "onceVisitable" },
-	"warMachineFactory"				: { "id" :106, "handler": "dwelling" },
-	"schoolOfWar"					: { "id" :107, "handler": "oncePerHero" },
-	"warriorTomb"					: { "id" :108, "handler": "onceVisitable" },
-	"waterWheel"					: { "id" :109, "handler": "oncePerWeek" },
-	"wateringHole"					: { "id" :110, "handler": "bonusingObject" },
-	"whirlpool"						: { "id" :111, "handler": "teleport" },
-	"windmill"						: { "id" :112, "handler": "oncePerWeek" },
-	"witchHut"						: { "id" :113, "handler": "witch" },
+	"sanctuary"						: { "id" :80, "handler": "generic" },
+
+	/// Passive objects, terrain overlays
+	"cursedGround"					: { "id" :21, "handler": "generic" },
+	"magicPlains"					: { "id" :46, "handler": "generic" },
+	"swampFoliage"					: { "id" :211, "handler": "generic" },
+	"cloverField"					: { "id" :222, "handler": "generic" },
+	"cursedGround"					: { "id" :223, "handler": "generic" },
+	"evilFog"						: { "id" :224, "handler": "generic" },
+	"favorableWinds"				: { "id" :225, "handler": "generic" },
+	"fieryFields"					: { "id" :226, "handler": "generic" },
+	"holyGround"					: { "id" :227, "handler": "generic" },
+	"lucidPools"					: { "id" :228, "handler": "generic" },
+	"magicClouds"					: { "id" :229, "handler": "generic" },
+	"magicPlains"					: { "id" :230, "handler": "generic" },
+	"rocklands"						: { "id" :231, "handler": "generic" }
+
+	/// Decorations
 	"cactus"						: { "id" :116, "handler": "generic" },
 	"canyon"						: { "id" :117, "handler": "generic" },
 	"crater"						: { "id" :118, "handler": "generic" },
@@ -136,9 +123,6 @@
 	"trees"							: { "id" :155, "handler": "generic" },
 	"volcano"						: { "id" :158, "handler": "generic" },
 	"reef"							: { "id" :161, "handler": "generic" },
-	"randomMonsterLevel5"			: { "id" :162, "handler": "monster" },
-	"randomMonsterLevel6"			: { "id" :163, "handler": "monster" },
-	"randomMonsterLevel7"			: { "id" :164, "handler": "monster" },
 	"lake"							: { "id" :177, "handler": "generic" },
 	"trees"							: { "id" :199, "handler": "generic" },
 	"desertHills"					: { "id" :206, "handler": "generic" },
@@ -146,23 +130,4 @@
 	"grassHills"					: { "id" :208, "handler": "generic" },
 	"roughHills"					: { "id" :209, "handler": "generic" },
 	"subterraneanRocks"				: { "id" :210, "handler": "generic" },
-	"swampFoliage"					: { "id" :211, "handler": "generic" },
-	"borderGate"					: { "id" :212, "handler": "borderGate" },
-	"freelancer'SGuild"				: { "id" :213, "handler": "market" },
-	"heroPlaceholder"				: { "id" :214, "handler": "heroPlaceholder" },
-	"questGuard"					: { "id" :215, "handler": "questGuard" },
-	"randomDwelling"				: { "id" :216, "handler": "dwelling" },
-	"garrison"						: { "id" :219, "handler": "garrison" },
-	"mine"							: { "id" :220, "handler": "mine" },
-	"tradingPost"					: { "id" :221, "handler": "market" },
-	"cloverField"					: { "id" :222, "handler": "generic" },
-	"cursedGround"					: { "id" :223, "handler": "generic" },
-	"evilFog"						: { "id" :224, "handler": "generic" },
-	"favorableWinds"				: { "id" :225, "handler": "generic" },
-	"fieryFields"					: { "id" :226, "handler": "generic" },
-	"holyGround"					: { "id" :227, "handler": "generic" },
-	"lucidPools"					: { "id" :228, "handler": "generic" },
-	"magicClouds"					: { "id" :229, "handler": "generic" },
-	"magicPlains"					: { "id" :230, "handler": "generic" },
-	"rocklands"						: { "id" :231, "handler": "generic" }
 }

+ 136 - 0
config/objects/moddables.json

@@ -0,0 +1,136 @@
+{
+	/// These are objects that have subtypes that change various aspects of their mechanics
+	/// Should be made configurable (either directly or via other parts of modding system ASAP)
+	/// Editing these objects either directly or via mod may have negative effect on game
+	
+	// subtype: artifact ID
+	"artifact" : {
+		"id" :5, 
+		"handler": "artifact",
+		"base" : {
+			"base" : {
+				"visitableFrom" : [ "+++", "+-+", "+++" ],
+				"mask" : [ "VV", "VA"]
+			}
+		}
+	},
+	
+	// subtype: hero CLASS (not hero).
+	"hero" : {
+		"id" :34,
+		"handler": "hero",
+		"base" : {
+			"base" : {
+				"visitableFrom" : [ "+++", "+-+", "+++" ],
+				"mask" : [ "VV", "AV"]
+			}
+		}
+	},
+	
+	// subtype: creatures
+	"monster" : {
+		"id" :54,
+		"handler": "monster"
+		"base" : {
+			"base" : {
+				"visitableFrom" : [ "+++", "+-+", "+++" ],
+				"mask" : [ "VV", "VA"]
+			}
+		}
+	},
+
+	// subtype: resource ID
+	"resource" : {
+		"id" :79,
+		"handler": "resource",
+		"base" : {
+			"base" : {
+				"visitableFrom" : [ "+++", "+-+", "+++" ],
+				"mask" : [ "VA" ]
+			}
+		}
+	},
+	
+	// subtype: faction
+	"town" : {
+		"id" :98,
+		"handler": "town",
+		"base" : {
+			"base" : {
+				"visitableFrom" : [ "---", "+++", "+++" ],
+				"mask" : [
+					"VVVVV", // a LOT of just visible rows due to towns like Tower
+					"VVVVV",
+					"VVVVV",
+					"VVBBBV",
+					"VBBBBB",
+					"VBBABB"
+				]
+			}
+		}
+	},
+
+	// subtype: one of 3 possible boats
+	"boat" : {
+		"id" :8,
+		"handler": "boat",
+		"base" : {
+			"base" : {
+				"visitableFrom" : [ "+++", "+-+", "+++" ],
+				"mask" : [ "VVV", "VAV" ]
+			}
+		}
+	},
+
+	// subtype: color of guard
+	"borderGuard"					: { "id" :9,  "handler": "borderGuard" },
+	"borderGate"					: { "id" :212, "handler": "borderGate" },
+	"keymasterTent"					: { "id" :10, "handler": "keymaster" },
+
+	// subtype: different content
+	"creatureBank"					: { "id" :16, "handler": "bank" },
+
+	// subtype: different revealed areas
+	"cartographer"					: { "id" :13, "handler": "cartographer" },
+
+	// subtype: 0 = normal, 1 = anti-magic
+	"garrisonHorizontal"			: { "id" :33, "handler": "garrison" },
+	"garrisonVertical"				: { "id" :219, "handler": "garrison" },
+
+	// Subtype: paired monoliths
+	"monolithOneWayEntrance"		: { "id" :43, "handler": "teleport" },
+	"monolithOneWayExit"			: { "id" :44, "handler": "teleport" },
+	"monolithTwoWay"				: { "id" :45, "handler": "teleport" },
+	
+	// subtype: resource ID
+	"mine"							: { "id" :53, "handler": "mine" },
+	"abandonedMine"					: { "id" :220, "handler": "mine" },
+
+	// subtype: different appearance. That's all?
+	"seerHut"						: { "id" :83, "handler": "seerHut" },
+
+	// subtype: level
+	"randomDwellingLvl"				: { "id" :217, "handler": "dwelling" },
+	
+	// subtype: faction ID
+	"randomDwellingFaction"			: { "id" :218, "handler": "dwelling" },
+
+	// subtype: not well defined, describes various dwellings that can be placed as random
+	"creatureGeneratorCommon" : {
+		"id" :17,
+		"handler": "dwelling",
+		"base" : {
+			"base" : {
+				"visitableFrom" : [ "---", "+++", "+++" ],
+				"mask" : [ "VVV", "VBB", "VAA" ]
+			}
+		}
+	},
+	
+	// subtype: unique special dwellings - golem factory, elemental conflux
+	"creatureGeneratorSpecial"		: { "id" :20, "handler": "dwelling" },
+	
+	// don't have subtypes (at least now), but closely connected to this objects
+	"spellScroll"					: { "id" :93, "handler": "artifact" },
+	"heroPlaceholder"				: { "id" :214, "handler": "heroPlaceholder" }
+}

+ 44 - 0
config/objects/rewardable.json

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

+ 3 - 2
lib/CModHandler.cpp

@@ -355,10 +355,11 @@ CContentHandler::CContentHandler()
 	handlers.insert(std::make_pair("artifacts", ContentTypeHandler(VLC->arth, "artifact")));
 	handlers.insert(std::make_pair("creatures", ContentTypeHandler(VLC->creh, "creature")));
 	handlers.insert(std::make_pair("factions", ContentTypeHandler(VLC->townh, "faction")));
+	handlers.insert(std::make_pair("objects", ContentTypeHandler(VLC->objtypeh, "object")));
 	handlers.insert(std::make_pair("heroes", ContentTypeHandler(VLC->heroh, "hero")));
-    handlers.insert(std::make_pair("spells", ContentTypeHandler(VLC->spellh, "spell")));
+	handlers.insert(std::make_pair("spells", ContentTypeHandler(VLC->spellh, "spell")));
 
-	//TODO: bonuses, something else?
+	//TODO: any other types of moddables?
 }
 
 bool CContentHandler::preloadModData(std::string modName, JsonNode modConfig, bool validate)

+ 15 - 25
lib/CObjectClassesHandler.cpp

@@ -330,28 +330,6 @@ bool ObjectTemplate::canBePlacedAt(ETerrainType terrain) const
 {
 	return allowedTerrains.count(terrain) != 0;
 }
-/*
-void CObjectClassesHandler::readTextFile(std::string path)
-{
-	CLegacyConfigParser parser(path);
-	size_t totalNumber = parser.readNumber(); // first line contains number of objects to read and nothing else
-	parser.endLine();
-
-	for (size_t i=0; i<totalNumber; i++)
-	{
-		ObjectTemplate templ;
-		templ.readTxt(parser);
-		parser.endLine();
-		objects.push_back(templ);
-	}
-}
-
-CObjectClassesHandler::CObjectClassesHandler()
-{
-	readTextFile("Data/Objects.txt");
-	readTextFile("Data/Heroes.txt");
-}
-*/
 
 CObjectClassesHandler::CObjectClassesHandler()
 {
@@ -417,6 +395,8 @@ static std::vector<JsonNode> readTextFile(std::string path)
 
 std::vector<JsonNode> CObjectClassesHandler::loadLegacyData(size_t dataSize)
 {
+	objects.resize(dataSize);
+
 	std::vector<JsonNode> ret(dataSize);// create storage for 256 objects
 
 	auto parseFile = [&](std::string filename)
@@ -436,8 +416,8 @@ std::vector<JsonNode> CObjectClassesHandler::loadLegacyData(size_t dataSize)
 		}
 	};
 
-	parseFile("Data/Objects.txt");
-	parseFile("Data/Heroes.txt");
+	//parseFile("Data/Objects.txt");
+	//parseFile("Data/Heroes.txt");
 
 	CLegacyConfigParser parser("Data/ObjNames.txt");
 	for (size_t i=0; i<256; i++)
@@ -464,12 +444,22 @@ CObjectClassesHandler::ObjectContainter * CObjectClassesHandler::loadFromJson(co
 
 void CObjectClassesHandler::loadObject(std::string scope, std::string name, const JsonNode & data)
 {
+	auto object = loadFromJson(data);
+	object->id = objects.size();
+	objects.push_back(object);
 
+	VLC->modh->identifiers.registerObject(scope, "object", name, object->id);
 }
 
 void CObjectClassesHandler::loadObject(std::string scope, std::string name, const JsonNode & data, size_t index)
 {
+	auto object = loadFromJson(data);
+	object->id = index;
+
+	assert(objects[index] == nullptr); // ensure that this id was not loaded before
+	objects[index] = object;
 
+	VLC->modh->identifiers.registerObject(scope, "object", name, object->id);
 }
 
 std::vector<bool> CObjectClassesHandler::getDefaultAllowed() const
@@ -479,7 +469,7 @@ std::vector<bool> CObjectClassesHandler::getDefaultAllowed() const
 
 TObjectTypeHandler CObjectClassesHandler::getHandlerFor(si32 type, si32 subtype) const
 {
-	if (objects.count(type))
+	if (objects.size() > type)
 	{
 		if (objects.at(type)->objects.count(subtype))
 			return objects.at(type)->objects.at(subtype);

+ 5 - 1
lib/CObjectClassesHandler.h

@@ -114,6 +114,9 @@ protected:
 
 	virtual bool objectFilter(const CGObjectInstance *, const ObjectTemplate &) const;
 public:
+	/// returns true if type is not configurable and new objects can be created without valid config
+	virtual bool confFree();
+
 	/// loads templates from Json structure using fields "base" and "templates"
 	virtual void init(const JsonNode & input);
 
@@ -145,6 +148,7 @@ public:
 	}
 };
 
+/// Class that is used for objects that do not have dedicated handler
 template<class ObjectType>
 class CDefaultObjectTypeHandler : public AObjectTypeHandler
 {
@@ -190,7 +194,7 @@ class DLL_LINKAGE CObjectClassesHandler : public IHandlerBase
 	};
 
 	/// list of object handlers, each of them handles only one type
-	std::map<si32, ObjectContainter * > objects;
+	std::vector<ObjectContainter * > objects;
 
 	/// map that is filled during contruction with all known handlers. Not serializeable
 	std::map<std::string, std::function<TObjectTypeHandler()> > handlerConstructors;