mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	- Implementation of overrides for towns
- Converted dwellings.json into new format - Implemented "mapObject" entry in town format - Removed capital/fort/village fields from town in favor of overrides
This commit is contained in:
		| @@ -500,7 +500,7 @@ void CKingdomInterface::generateObjectsList(const std::vector<const CGObjectInst | |||||||
| 			OwnedObjectInfo &info = visibleObjects[object->subID]; | 			OwnedObjectInfo &info = visibleObjects[object->subID]; | ||||||
| 			if (info.count++ == 0) | 			if (info.count++ == 0) | ||||||
| 			{ | 			{ | ||||||
| 				info.hoverText = CGI->creh->creatures[CGI->objh->cregens.find(object->subID)->second]->namePl; | 				info.hoverText = object->getHoverText(); | ||||||
| 				info.imageID = object->subID; | 				info.imageID = object->subID; | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|   | |||||||
| @@ -1,108 +0,0 @@ | |||||||
| { |  | ||||||
| 	// Indicate which dwelling produces which creature |  | ||||||
| 	// Note that it is 1<->n connection since |  | ||||||
| 	// a creature can be produced by more than one dwelling. |  | ||||||
| 	"dwellings": [ |  | ||||||
| 		{ "dwelling": 0, "creature": 106 }, |  | ||||||
| 		{ "dwelling": 1, "creature": 96 }, |  | ||||||
| 		{ "dwelling": 2, "creature": 74 }, |  | ||||||
| 		{ "dwelling": 3, "creature": 66 }, |  | ||||||
| 		{ "dwelling": 4, "creature": 68 }, |  | ||||||
| 		{ "dwelling": 5, "creature": 10 }, |  | ||||||
| 		{ "dwelling": 6, "creature": 14 }, |  | ||||||
| 		{ "dwelling": 7, "creature": 112 }, |  | ||||||
| 		{ "dwelling": 8, "creature": 12 }, |  | ||||||
| 		{ "dwelling": 9, "creature": 94 }, |  | ||||||
| 		{ "dwelling": 10, "creature": 54 }, |  | ||||||
| 		{ "dwelling": 11, "creature": 104 }, |  | ||||||
| 		{ "dwelling": 12, "creature": 16 }, |  | ||||||
| 		{ "dwelling": 13, "creature": 113 }, |  | ||||||
| 		{ "dwelling": 14, "creature": 52 }, |  | ||||||
| 		{ "dwelling": 15, "creature": 18 }, |  | ||||||
| 		{ "dwelling": 16, "creature": 114 }, |  | ||||||
| 		{ "dwelling": 17, "creature": 30 }, |  | ||||||
| 		{ "dwelling": 18, "creature": 36 }, |  | ||||||
| 		{ "dwelling": 19, "creature": 86 }, |  | ||||||
| 		{ "dwelling": 20, "creature": 98 }, |  | ||||||
| 		{ "dwelling": 21, "creature": 84 }, |  | ||||||
| 		{ "dwelling": 22, "creature": 44 }, |  | ||||||
| 		{ "dwelling": 23, "creature": 102 }, |  | ||||||
| 		{ "dwelling": 24, "creature": 26 }, |  | ||||||
| 		{ "dwelling": 25, "creature": 4 }, |  | ||||||
| 		{ "dwelling": 26, "creature": 72 }, |  | ||||||
| 		{ "dwelling": 27, "creature": 46 }, |  | ||||||
| 		{ "dwelling": 28, "creature": 110 }, |  | ||||||
| 		{ "dwelling": 29, "creature": 42 }, |  | ||||||
| 		{ "dwelling": 30, "creature": 100 }, |  | ||||||
| 		{ "dwelling": 31, "creature": 34 }, |  | ||||||
| 		{ "dwelling": 32, "creature": 80 }, |  | ||||||
| 		{ "dwelling": 33, "creature": 76 }, |  | ||||||
| 		{ "dwelling": 34, "creature": 78 }, |  | ||||||
| 		{ "dwelling": 35, "creature": 8 }, |  | ||||||
| 		{ "dwelling": 36, "creature": 38 }, |  | ||||||
| 		{ "dwelling": 37, "creature": 48 }, |  | ||||||
| 		{ "dwelling": 38, "creature": 90 }, |  | ||||||
| 		{ "dwelling": 39, "creature": 88 }, |  | ||||||
| 		{ "dwelling": 40, "creature": 50 }, |  | ||||||
| 		{ "dwelling": 41, "creature": 82 }, |  | ||||||
| 		{ "dwelling": 42, "creature": 92 }, |  | ||||||
| 		{ "dwelling": 43, "creature": 28 }, |  | ||||||
| 		{ "dwelling": 44, "creature": 40 }, |  | ||||||
| 		{ "dwelling": 45, "creature": 22 }, |  | ||||||
| 		{ "dwelling": 46, "creature": 70 }, |  | ||||||
| 		{ "dwelling": 47, "creature": 115 }, |  | ||||||
| 		{ "dwelling": 48, "creature": 60 }, |  | ||||||
| 		{ "dwelling": 49, "creature": 108 }, |  | ||||||
| 		{ "dwelling": 50, "creature": 20 }, |  | ||||||
| 		{ "dwelling": 51, "creature": 24 }, |  | ||||||
| 		{ "dwelling": 52, "creature": 64 }, |  | ||||||
| 		{ "dwelling": 53, "creature": 62 }, |  | ||||||
| 		{ "dwelling": 54, "creature": 56 }, |  | ||||||
| 		{ "dwelling": 55, "creature": 58 }, |  | ||||||
| 		{ "dwelling": 56, "creature": 0 }, |  | ||||||
| 		{ "dwelling": 57, "creature": 2 }, |  | ||||||
| 		{ "dwelling": 58, "creature": 6 }, |  | ||||||
| 		{ "dwelling": 59, "creature": 118 }, |  | ||||||
| 		{ "dwelling": 60, "creature": 120 }, |  | ||||||
| 		{ "dwelling": 61, "creature": 130 }, |  | ||||||
| 		{ "dwelling": 62, "creature": 132 }, |  | ||||||
| 		{ "dwelling": 63, "creature": 133 }, |  | ||||||
| 		{ "dwelling": 64, "creature": 134 }, |  | ||||||
| 		{ "dwelling": 65, "creature": 135 }, |  | ||||||
| 		{ "dwelling": 66, "creature": 136 }, |  | ||||||
| 		{ "dwelling": 67, "creature": 137 }, |  | ||||||
| 		{ "dwelling": 68, "creature": 24 }, |  | ||||||
| 		{ "dwelling": 69, "creature": 112 }, |  | ||||||
| 		{ "dwelling": 70, "creature": 113 }, |  | ||||||
| 		{ "dwelling": 71, "creature": 114 }, |  | ||||||
| 		{ "dwelling": 72, "creature": 115 }, |  | ||||||
| 		{ "dwelling": 73, "creature": 138 }, |  | ||||||
| 		{ "dwelling": 74, "creature": 139 }, |  | ||||||
| 		{ "dwelling": 75, "creature": 140 }, |  | ||||||
| 		{ "dwelling": 76, "creature": 141 }, |  | ||||||
| 		{ "dwelling": 77, "creature": 142 }, |  | ||||||
| 		{ "dwelling": 78, "creature": 143 }, |  | ||||||
| 		{ "dwelling": 79, "creature": 144 }, |  | ||||||
| 		{ "dwelling": 80, "creature": 150 }, |  | ||||||
| 		{ "dwelling": 81, "creature": 151 }, |  | ||||||
| 		{ "dwelling": 82, "creature": 152 }, |  | ||||||
| 		{ "dwelling": 83, "creature": 153 }, |  | ||||||
| 		{ "dwelling": 84, "creature": 154 }, |  | ||||||
| 		{ "dwelling": 85, "creature": 155 }, |  | ||||||
| 		{ "dwelling": 86, "creature": 156 }, |  | ||||||
| 		{ "dwelling": 87, "creature": 157 }, |  | ||||||
| 		{ "dwelling": 88, "creature": 158 }, |  | ||||||
| 		{ "dwelling": 89, "creature": 171 }, |  | ||||||
| 		{ "dwelling": 90, "creature": 170 }, |  | ||||||
| 		{ "dwelling": 91, "creature": 168 }, |  | ||||||
| 		{ "dwelling": 92, "creature": 172 }, |  | ||||||
| 		{ "dwelling": 93, "creature": 164 }, |  | ||||||
| 		{ "dwelling": 94, "creature": 169 }, |  | ||||||
| 		{ "dwelling": 95, "creature": 173 }, |  | ||||||
| 		{ "dwelling": 96, "creature": 192 }, |  | ||||||
| 		{ "dwelling": 97, "creature": 193 }, |  | ||||||
| 		{ "dwelling": 98, "creature": 194 }, |  | ||||||
| 		{ "dwelling": 99, "creature": 195 }, |  | ||||||
| 		{ "dwelling": 100, "creature": 196 } |  | ||||||
| 	] |  | ||||||
| } |  | ||||||
| @@ -66,11 +66,13 @@ | |||||||
| 		}, | 		}, | ||||||
| 		"town" : | 		"town" : | ||||||
| 		{ | 		{ | ||||||
| 			"adventureMap" : | 			"mapObject" : | ||||||
| 			{ | 			{ | ||||||
| 				"castle" : "AVCcasx0.def", | 				"templates" : { | ||||||
| 				"village" : "AVCCAST0.DEF", | 					"castle" :  { "animation" : "AVCcasx0.def" }, | ||||||
| 				"capitol" : "AVCCASZ0.DEF" | 					"village" : { "animation" : "AVCCAST0.DEF" }, | ||||||
|  | 					"capitol" : { "animation" : "AVCCASZ0.DEF" } | ||||||
|  | 				} | ||||||
| 			}, | 			}, | ||||||
| 			"structures" : | 			"structures" : | ||||||
| 			{ | 			{ | ||||||
|   | |||||||
| @@ -66,11 +66,13 @@ | |||||||
| 		}, | 		}, | ||||||
| 		"town" : | 		"town" : | ||||||
| 		{ | 		{ | ||||||
| 			"adventureMap" : | 			"mapObject" : | ||||||
| 			{ | 			{ | ||||||
| 				"castle" : "avchforx.def", | 				"templates" : { | ||||||
| 				"village" : "AVCHFOR0.DEF", | 					"castle" :  { "animation" : "avchforx.def" }, | ||||||
| 				"capitol" : "AVCHFORZ.DEF" | 					"village" : { "animation" : "AVCHFOR0.DEF" }, | ||||||
|  | 					"capitol" : { "animation" : "AVCHFORZ.DEF" } | ||||||
|  | 				} | ||||||
| 			}, | 			}, | ||||||
| 			"structures" : | 			"structures" : | ||||||
| 			{ | 			{ | ||||||
|   | |||||||
| @@ -66,11 +66,13 @@ | |||||||
| 		}, | 		}, | ||||||
| 		"town" : | 		"town" : | ||||||
| 		{ | 		{ | ||||||
| 			"adventureMap" : | 			"mapObject" : | ||||||
| 			{ | 			{ | ||||||
| 				"castle" : "AVCdunx0.def", | 				"templates" : { | ||||||
| 				"village" : "AVCDUNG0.DEF", | 					"castle" :  { "animation" : "AVCdunx0.def" }, | ||||||
| 				"capitol" : "AVCDUNZ0.DEF" | 					"village" : { "animation" : "AVCDUNG0.DEF" }, | ||||||
|  | 					"capitol" : { "animation" : "AVCDUNZ0.DEF" } | ||||||
|  | 				} | ||||||
| 			}, | 			}, | ||||||
| 			"structures" : | 			"structures" : | ||||||
| 			{ | 			{ | ||||||
|   | |||||||
| @@ -66,11 +66,13 @@ | |||||||
| 		}, | 		}, | ||||||
| 		"town" : | 		"town" : | ||||||
| 		{ | 		{ | ||||||
| 			"adventureMap" : | 			"mapObject" : | ||||||
| 			{ | 			{ | ||||||
| 				"castle" : "AVCftrx0.def", | 				"templates" : { | ||||||
| 				"village" : "AVCFTRT0.DEF", | 					"castle" :  { "animation" : "AVCftrx0.def" }, | ||||||
| 				"capitol" : "AVCFORZ0.DEF" | 					"village" : { "animation" : "AVCFTRT0.DEF" }, | ||||||
|  | 					"capitol" : { "animation" : "AVCFORZ0.DEF" } | ||||||
|  | 				} | ||||||
| 			}, | 			}, | ||||||
| 			"structures" : | 			"structures" : | ||||||
| 			{ | 			{ | ||||||
|   | |||||||
| @@ -66,11 +66,13 @@ | |||||||
| 		}, | 		}, | ||||||
| 		"town" : | 		"town" : | ||||||
| 		{ | 		{ | ||||||
| 			"adventureMap" : | 			"mapObject" : | ||||||
| 			{ | 			{ | ||||||
| 				"castle" : "AVCinfx0.def", | 				"templates" : { | ||||||
| 				"village" : "AVCINFT0.DEF", | 					"castle" :  { "animation" : "AVCinfx0.def" }, | ||||||
| 				"capitol" : "AVCINFZ0.DEF" | 					"village" : { "animation" : "AVCINFT0.DEF" }, | ||||||
|  | 					"capitol" : { "animation" : "AVCINFZ0.DEF" } | ||||||
|  | 				} | ||||||
| 			}, | 			}, | ||||||
| 			"structures" : | 			"structures" : | ||||||
| 			{ | 			{ | ||||||
|   | |||||||
| @@ -66,11 +66,13 @@ | |||||||
| 		}, | 		}, | ||||||
| 		"town" : | 		"town" : | ||||||
| 		{ | 		{ | ||||||
| 			"adventureMap" : | 			"mapObject" : | ||||||
| 			{ | 			{ | ||||||
| 				"castle" : "AVCnecx0.def", | 				"templates" : { | ||||||
| 				"village" : "AVCNECR0.DEF", | 					"castle" :  { "animation" : "AVCnecx0.def" }, | ||||||
| 				"capitol" : "AVCNECZ0.DEF" | 					"village" : { "animation" : "AVCNECR0.DEF" }, | ||||||
|  | 					"capitol" : { "animation" : "AVCNECZ0.DEF" } | ||||||
|  | 				} | ||||||
| 			}, | 			}, | ||||||
| 			"structures" : | 			"structures" : | ||||||
| 			{ | 			{ | ||||||
|   | |||||||
| @@ -66,11 +66,13 @@ | |||||||
| 		}, | 		}, | ||||||
| 		"town" : | 		"town" : | ||||||
| 		{ | 		{ | ||||||
| 			"adventureMap" : | 			"mapObject" : | ||||||
| 			{ | 			{ | ||||||
| 				"castle" : "AVCramx0.def", | 				"templates" : { | ||||||
| 				"village" : "AVCRAMP0.DEF", | 					"castle" :  { "animation" : "AVCramx0.def" }, | ||||||
| 				"capitol" : "AVCRAMZ0.DEF" | 					"village" : { "animation" : "AVCRAMP0.DEF" }, | ||||||
|  | 					"capitol" : { "animation" : "AVCRAMZ0.DEF" } | ||||||
|  | 				} | ||||||
| 			}, | 			}, | ||||||
| 			"structures" : | 			"structures" : | ||||||
| 			{ | 			{ | ||||||
|   | |||||||
| @@ -66,11 +66,13 @@ | |||||||
| 		}, | 		}, | ||||||
| 		"town" : | 		"town" : | ||||||
| 		{ | 		{ | ||||||
| 			"adventureMap" : | 			"mapObject" : | ||||||
| 			{ | 			{ | ||||||
| 				"castle" : "AVCstrx0.def", | 				"templates" : { | ||||||
| 				"village" : "AVCSTRO0.DEF", | 					"castle" :  { "animation" : "AVCstrx0.def" }, | ||||||
| 				"capitol" : "AVCSTRZ0.DEF" | 					"village" : { "animation" : "AVCSTRO0.DEF" }, | ||||||
|  | 					"capitol" : { "animation" : "AVCSTRZ0.DEF" } | ||||||
|  | 				} | ||||||
| 			}, | 			}, | ||||||
| 			"structures" : | 			"structures" : | ||||||
| 			{ | 			{ | ||||||
|   | |||||||
| @@ -66,11 +66,13 @@ | |||||||
| 		}, | 		}, | ||||||
| 		"town" : | 		"town" : | ||||||
| 		{ | 		{ | ||||||
| 			"adventureMap" : | 			"mapObject" : | ||||||
| 			{ | 			{ | ||||||
| 				"castle" : "AVCtowx0.def", | 				"templates" : { | ||||||
| 				"village" : "AVCTOWR0.DEF", | 					"castle" :  { "animation" : "AVCtowx0.def" }, | ||||||
| 				"capitol" : "AVCTOWZ0.DEF" | 					"village" : { "animation" : "AVCTOWR0.DEF" }, | ||||||
|  | 					"capitol" : { "animation" : "AVCTOWZ0.DEF" } | ||||||
|  | 				} | ||||||
| 			}, | 			}, | ||||||
| 			"structures" : | 			"structures" : | ||||||
| 			{ | 			{ | ||||||
|   | |||||||
| @@ -49,6 +49,7 @@ | |||||||
| 	[ | 	[ | ||||||
| 		"config/objects/generic.json", | 		"config/objects/generic.json", | ||||||
| 		"config/objects/moddables.json", | 		"config/objects/moddables.json", | ||||||
|  | 		"config/objects/dwellings.json", | ||||||
| 		"config/objects/rewardable.json" | 		"config/objects/rewardable.json" | ||||||
| 	], | 	], | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										126
									
								
								config/objects/dwellings.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										126
									
								
								config/objects/dwellings.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,126 @@ | |||||||
|  | { | ||||||
|  | 	"creatureGeneratorCommon" : { | ||||||
|  | 		"index" :17, | ||||||
|  | 		"handler": "dwelling", | ||||||
|  | 		"base" : { | ||||||
|  | 			"base" : { | ||||||
|  | 				"visitableFrom" : [ "---", "+++", "+++" ], | ||||||
|  | 				"mask" : [ "VVV", "VBB", "VAA" ] | ||||||
|  | 			} | ||||||
|  | 		}, | ||||||
|  | 		"types" : { | ||||||
|  | 			"basiliskPit" :      { "index" : 0,  "creatures" :  [ [ "basilisk" ] ] }, | ||||||
|  | 			"behemothCrag" :     { "index" : 1,  "creatures" :  [ [ "behemoth" ] ], "guards" : true }, | ||||||
|  | 			"pillarOfEyes" :     { "index" : 2,  "creatures" :  [ [ "beholder" ] ] }, | ||||||
|  | 			"hallOfDarkness" :   { "index" : 3,  "creatures" :  [ [ "blackKnight" ] ], "guards" : true }, | ||||||
|  | 			"dragonVault" :      { "index" : 4,  "creatures" :  [ [ "boneDragon" ] ], "guards" : true }, | ||||||
|  | 			"trainingGrounds" :  { "index" : 5,  "creatures" :  [ [ "cavalier" ] ], "guards" : true }, | ||||||
|  | 			"centaurStables" :   { "index" : 6,  "creatures" :  [ [ "centaur" ] ] }, | ||||||
|  | 			"airConflux" :       { "index" : 7,  "creatures" :  [ [ "airElemental" ] ] }, | ||||||
|  | 			"portalOfGlory" :    { "index" : 8,  "creatures" :  [ [ "angel" ] ], "guards" : true }, | ||||||
|  | 			"cyclopsCave" :      { "index" : 9,  "creatures" :  [ [ "cyclop" ] ], "guards" : true }, | ||||||
|  | 			"forsakenPalace" :   { "index" : 10, "creatures" : [ [ "devil" ] ], "guards" : true }, | ||||||
|  | 			"serpentFlyHive" :   { "index" : 11, "creatures" : [ [ "serpentFly" ] ] }, | ||||||
|  | 			"dwarfCottage" :     { "index" : 12, "creatures" : [ [ "dwarf" ] ] }, | ||||||
|  | 			"earthConflux" :     { "index" : 13, "creatures" : [ [ "earthElemental" ] ], "guards" : true }, | ||||||
|  | 			"fireLake" :         { "index" : 14, "creatures" : [ [ "efreet" ] ], "guards" : true }, | ||||||
|  | 			"homestead" :        { "index" : 15, "creatures" : [ [ "woodElf" ] ] }, | ||||||
|  | 			"fireConflux" :      { "index" : 16, "creatures" : [ [ "fireElemental" ] ] }, | ||||||
|  | 			"parapet" :          { "index" : 17, "creatures" : [ [ "stoneGargoyle" ] ] }, | ||||||
|  | 			"altarOfWishes" :    { "index" : 18, "creatures" : [ [ "genie" ] ], "guards" : true }, | ||||||
|  | 			"wolfPen" :          { "index" : 19, "creatures" : [ [ "goblinWolfRider" ] ] }, | ||||||
|  | 			"gnollHut" :         { "index" : 20, "creatures" : [ [ "gnoll" ] ] }, | ||||||
|  | 			"goblinBarracks" :   { "index" : 21, "creatures" : [ [ "goblin" ] ] }, | ||||||
|  | 			"hallOfSins" :       { "index" : 22, "creatures" : [ [ "gog" ] ] }, | ||||||
|  | 			"gorgonLair" :       { "index" : 23, "creatures" : [ [ "gorgon" ] ], "guards" : true }, | ||||||
|  | 			"dragonCliffs" :     { "index" : 24, "creatures" : [ [ "greenDragon" ] ], "guards" : true }, | ||||||
|  | 			"griffinTower" :     { "index" : 25, "creatures" : [ [ "griffin" ] ] }, | ||||||
|  | 			"harpyLoft" :        { "index" : 26, "creatures" : [ [ "harpy" ] ] }, | ||||||
|  | 			"kennels" :          { "index" : 27, "creatures" : [ [ "hellHound" ] ] }, | ||||||
|  | 			"hydraPond" :        { "index" : 28, "creatures" : [ [ "hydra" ] ], "guards" : true }, | ||||||
|  | 			"impCrucible" :      { "index" : 29, "creatures" : [ [ "imp" ] ] }, | ||||||
|  | 			"lizardDen" :        { "index" : 30, "creatures" : [ [ "lizardman" ] ] }, | ||||||
|  | 			"mageTower" :        { "index" : 31, "creatures" : [ [ "mage" ] ] }, | ||||||
|  | 			"manticoreLair" :    { "index" : 32, "creatures" : [ [ "manticore" ] ], "guards" : true }, | ||||||
|  | 			"medusaChapel" :     { "index" : 33, "creatures" : [ [ "medusa" ] ] }, | ||||||
|  | 			"labyrinth" :        { "index" : 34, "creatures" : [ [ "minotaur" ] ], "guards" : true }, | ||||||
|  | 			"monastery" :        { "index" : 35, "creatures" : [ [ "monk" ] ], "guards" : true }, | ||||||
|  | 			"goldenPavilion" :   { "index" : 36, "creatures" : [ [ "naga" ] ], "guards" : true }, | ||||||
|  | 			"demonGate" :        { "index" : 37, "creatures" : [ [ "demon" ] ] }, | ||||||
|  | 			"ogreFort" :         { "index" : 38, "creatures" : [ [ "ogre" ] ] }, | ||||||
|  | 			"orcTower" :         { "index" : 39, "creatures" : [ [ "orc" ] ] }, | ||||||
|  | 			"hellHole" :         { "index" : 40, "creatures" : [ [ "pitFiend" ] ], "guards" : true }, | ||||||
|  | 			"dragonCave" :       { "index" : 41, "creatures" : [ [ "redDragon" ] ], "guards" : true }, | ||||||
|  | 			"cliffNest" :        { "index" : 42, "creatures" : [ [ "roc" ] ], "guards" : true }, | ||||||
|  | 			"workshop" :         { "index" : 43, "creatures" : [ [ "gremlin" ] ] }, | ||||||
|  | 			"cloudTemple" :      { "index" : 44, "creatures" : [ [ "giant" ] ], "guards" : true }, | ||||||
|  | 			"dendroidArches" :   { "index" : 45, "creatures" : [ [ "dendroidGuard" ] ], "guards" : true }, | ||||||
|  | 			"warren" :           { "index" : 46, "creatures" : [ [ "troglodyte" ] ] }, | ||||||
|  | 			"waterConflux" :     { "index" : 47, "creatures" : [ [ "waterElemental" ] ] }, | ||||||
|  | 			"tombOfSouls" :      { "index" : 48, "creatures" : [ [ "wight" ] ] }, | ||||||
|  | 			"wyvernNest" :       { "index" : 49, "creatures" : [ [ "wyvern" ] ], "guards" : true }, | ||||||
|  | 			"enchantedSpring" :  { "index" : 50, "creatures" : [ [ "pegasus" ] ] }, | ||||||
|  | 			"unicornGladeBig" :  { "index" : 51, "creatures" : [ [ "unicorn" ] ], "guards" : true }, | ||||||
|  | 			"mausoleum" :        { "index" : 52, "creatures" : [ [ "lich" ] ], "guards" : true }, | ||||||
|  | 			"estate" :           { "index" : 53, "creatures" : [ [ "vampire" ] ] }, | ||||||
|  | 			"cursedTemple" :     { "index" : 54, "creatures" : [ [ "skeleton" ] ] }, | ||||||
|  | 			"graveyard" :        { "index" : 55, "creatures" : [ [ "walkingDead" ] ] }, | ||||||
|  | 			"guardhouse" :       { "index" : 56, "creatures" : [ [ "pikeman" ] ] }, | ||||||
|  | 			"archersTower" :     { "index" : 57, "creatures" : [ [ "archer" ] ] }, | ||||||
|  | 			"barracks" :         { "index" : 58, "creatures" : [ [ "swordsman" ] ] }, | ||||||
|  | 			"magicLantern" :     { "index" : 59, "creatures" : [ [ "pixie" ] ] }, | ||||||
|  | 			"altarOfThought" :   { "index" : 60, "creatures" : [ [ "psychicElemental" ] ], "guards" : true }, | ||||||
|  | 			"pyre" :             { "index" : 61, "creatures" : [ [ "firebird" ] ], "guards" : true }, | ||||||
|  | 			"frozenCliffs" :     { "index" : 62, "creatures" : [ [ "azureDragon" ] ], "guards" : true }, | ||||||
|  | 			"crystalCavern" :    { "index" : 63, "creatures" : [ [ "crystalDragon" ] ], "guards" : true }, | ||||||
|  | 			"magicForest" :      { "index" : 64, "creatures" : [ [ "fairieDragon" ] ], "guards" : true }, | ||||||
|  | 			"sulfurousLair" :    { "index" : 65, "creatures" : [ [ "rustDragon" ] ], "guards" : true }, | ||||||
|  | 			"enchantersHollow" : { "index" : 66, "creatures" : [ [ "enchanter" ] ], "guards" : true }, | ||||||
|  | 			"treetopTower" :     { "index" : 67, "creatures" : [ [ "sharpshooter" ] ], "guards" : true }, | ||||||
|  | 			"unicornGlade" :     { "index" : 68, "creatures" : [ [ "unicorn" ] ], "guards" : true }, | ||||||
|  | 			"altarOfAir" :       { "index" : 69, "creatures" : [ [ "airElemental" ] ] }, | ||||||
|  | 			"altarOfEarth" :     { "index" : 70, "creatures" : [ [ "earthElemental" ] ], "guards" : true }, | ||||||
|  | 			"altarOfFire" :      { "index" : 71, "creatures" : [ [ "fireElemental" ] ] }, | ||||||
|  | 			"altarOfWater" :     { "index" : 72, "creatures" : [ [ "waterElemental" ] ] }, | ||||||
|  | 			"thatchedHut" :      { "index" : 73, "creatures" : [ [ "halfling" ] ] }, | ||||||
|  | 			"hovel" :            { "index" : 74, "creatures" : [ [ "peasant" ] ] }, | ||||||
|  | 			"boarGlen" :         { "index" : 75, "creatures" : [ [ "boar" ] ] }, | ||||||
|  | 			"tombOfCurses" :     { "index" : 76, "creatures" : [ [ "mummy" ] ] }, | ||||||
|  | 			"nomadTent" :        { "index" : 77, "creatures" : [ [ "nomad" ] ] }, | ||||||
|  | 			"rogueCavern" :      { "index" : 78, "creatures" : [ [ "rogue" ] ] }, | ||||||
|  | 			"trollBridge" :      { "index" : 79, "creatures" : [ [ "troll" ] ], "guards" : true } | ||||||
|  | 		} | ||||||
|  | 	}, | ||||||
|  | 	// subtype: unique special dwellings - golem factory and elemental conflux | ||||||
|  | 	"creatureGeneratorSpecial" : { | ||||||
|  | 		"index" :20, | ||||||
|  | 		"handler": "dwelling", | ||||||
|  | 		"types" : { | ||||||
|  | 			"elementalConflux" : { | ||||||
|  | 				"index" : 0, | ||||||
|  | 				"creatures" : [ // 4 separate "levels" to give them separate growth | ||||||
|  | 					[ "airElemental" ], | ||||||
|  | 					[ "waterElemental" ], | ||||||
|  | 					[ "fireElemental" ], | ||||||
|  | 					[ "earthElemental" ] | ||||||
|  | 				], | ||||||
|  | 				"guards" : { | ||||||
|  | 					"earthElemental" : 12 | ||||||
|  | 				} | ||||||
|  | 			}, | ||||||
|  | 			"golemFactory" : { | ||||||
|  | 				"index" : 1, | ||||||
|  | 				"creatures" : [ // 4 separate "levels" to give them separate growth | ||||||
|  | 					[ "ironGolem" ], | ||||||
|  | 					[ "stoneGolem" ], | ||||||
|  | 					[ "goldGolem" ], | ||||||
|  | 					[ "diamondGolem" ] | ||||||
|  | 				], | ||||||
|  | 				"guards" : { | ||||||
|  | 					"goldGolem" : 9, | ||||||
|  | 					"diamondGolem" : 6 | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	}, | ||||||
|  | } | ||||||
| @@ -48,6 +48,16 @@ | |||||||
| 				"visitableFrom" : [ "+++", "+-+", "+++" ], | 				"visitableFrom" : [ "+++", "+-+", "+++" ], | ||||||
| 				"mask" : [ "VA" ] | 				"mask" : [ "VA" ] | ||||||
| 			} | 			} | ||||||
|  | 		}, | ||||||
|  | 		"types" : { | ||||||
|  | 			"wood" :    { "index" : 0 }, | ||||||
|  | 			"mercury" : { "index" : 1 }, | ||||||
|  | 			"ore" :     { "index" : 2 }, | ||||||
|  | 			"sulfur" :  { "index" : 3 }, | ||||||
|  | 			"crystal" : { "index" : 4 }, | ||||||
|  | 			"gems" :    { "index" : 5 }, | ||||||
|  | 			"gold" :    { "index" : 6 }, | ||||||
|  | 			"mithril" : { "index" : 7 } // TODO: move to WoG? | ||||||
| 		} | 		} | ||||||
| 	}, | 	}, | ||||||
| 	 | 	 | ||||||
| @@ -56,7 +66,7 @@ | |||||||
| 		"index" :98, | 		"index" :98, | ||||||
| 		"handler": "town", | 		"handler": "town", | ||||||
| 		"base" : { | 		"base" : { | ||||||
| 			"filter" : { | 			"filters" : { | ||||||
| 				// village image - fort not present | 				// village image - fort not present | ||||||
| 				"village" : [ "noneOf", [ "fort" ] ], | 				"village" : [ "noneOf", [ "fort" ] ], | ||||||
| 				// fort image - fort is here but not capitol | 				// fort image - fort is here but not capitol | ||||||
| @@ -125,21 +135,6 @@ | |||||||
| 	// subtype: faction ID | 	// subtype: faction ID | ||||||
| 	"randomDwellingFaction"			: { "index" :218, "handler": "dwelling" }, | 	"randomDwellingFaction"			: { "index" :218, "handler": "dwelling" }, | ||||||
|  |  | ||||||
| 	// subtype: not well defined, describes various dwellings that can be placed as random |  | ||||||
| 	"creatureGeneratorCommon" : { |  | ||||||
| 		"index" :17, |  | ||||||
| 		"handler": "dwelling", |  | ||||||
| 		"base" : { |  | ||||||
| 			"base" : { |  | ||||||
| 				"visitableFrom" : [ "---", "+++", "+++" ], |  | ||||||
| 				"mask" : [ "VVV", "VBB", "VAA" ] |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	}, |  | ||||||
| 	 |  | ||||||
| 	// subtype: unique special dwellings - golem factory, elemental conflux |  | ||||||
| 	"creatureGeneratorSpecial"		: { "index" :20, "handler": "dwelling" }, |  | ||||||
| 	 |  | ||||||
| 	// don't have subtypes (at least now), but closely connected to this objects | 	// don't have subtypes (at least now), but closely connected to this objects | ||||||
| 	"spellScroll"					: { "index" :93, "handler": "artifact" }, | 	"spellScroll"					: { "index" :93, "handler": "artifact" }, | ||||||
| 	"heroPlaceholder"				: { "index" :214, "handler": "heroPlaceholder" } | 	"heroPlaceholder"				: { "index" :214, "handler": "heroPlaceholder" } | ||||||
|   | |||||||
| @@ -622,23 +622,28 @@ std::pair<Obj,int> CGameState::pickObject (CGObjectInstance *obj) | |||||||
| 			std::pair<Obj, int> result(Obj::NO_OBJ, -1); | 			std::pair<Obj, int> result(Obj::NO_OBJ, -1); | ||||||
| 			CreatureID cid = VLC->townh->factions[faction]->town->creatures[level][0]; | 			CreatureID cid = VLC->townh->factions[faction]->town->creatures[level][0]; | ||||||
|  |  | ||||||
| 			//golem factory is not in list of cregens but can be placed as random object |  | ||||||
| 			static const CreatureID factoryCreatures[] = {CreatureID::STONE_GOLEM, CreatureID::IRON_GOLEM, |  | ||||||
| 				CreatureID::GOLD_GOLEM, CreatureID::DIAMOND_GOLEM}; |  | ||||||
| 			std::vector<CreatureID> factory(factoryCreatures, factoryCreatures + ARRAY_COUNT(factoryCreatures)); |  | ||||||
| 			if (vstd::contains(factory, cid)) |  | ||||||
| 				result = std::make_pair(Obj::CREATURE_GENERATOR4, 1); |  | ||||||
|  |  | ||||||
| 			//NOTE: this will pick last dwelling with this creature (Mantis #900) | 			//NOTE: this will pick last dwelling with this creature (Mantis #900) | ||||||
| 			//check for block map equality is better but more complex solution | 			//check for block map equality is better but more complex solution | ||||||
| 			for(auto &iter : VLC->objh->cregens) | 			auto testID = [&](Obj primaryID) -> void | ||||||
| 				if (iter.second == cid) | 			{ | ||||||
| 					result = std::make_pair(Obj::CREATURE_GENERATOR1, iter.first); | 				auto dwellingIDs = VLC->objtypeh->knownSubObjects(primaryID); | ||||||
|  | 				for (si32 entry : dwellingIDs) | ||||||
|  | 				{ | ||||||
|  | 					auto handler = dynamic_cast<const CDwellingInstanceConstructor*>(VLC->objtypeh->getHandlerFor(primaryID, entry).get()); | ||||||
|  |  | ||||||
|  | 					if (handler->producesCreature(VLC->creh->creatures[cid])) | ||||||
|  | 						result = std::make_pair(primaryID, entry); | ||||||
|  | 				} | ||||||
|  | 			}; | ||||||
|  |  | ||||||
|  | 			testID(Obj::CREATURE_GENERATOR1); | ||||||
|  | 			if (result.first == Obj::NO_OBJ) | ||||||
|  | 				testID(Obj::CREATURE_GENERATOR4); | ||||||
|  |  | ||||||
| 			if (result.first == Obj::NO_OBJ) | 			if (result.first == Obj::NO_OBJ) | ||||||
| 			{ | 			{ | ||||||
|                 logGlobal->errorStream() << "Error: failed to find creature for dwelling of "<< int(faction) << " of level " << int(level); | 				logGlobal->errorStream() << "Error: failed to find dwelling for "<< VLC->townh->factions[faction]->name << " of level " << int(level); | ||||||
| 				result = std::make_pair(Obj::CREATURE_GENERATOR1, RandomGeneratorUtil::nextItem(VLC->objh->cregens, rand)->first); | 				result = std::make_pair(Obj::CREATURE_GENERATOR1, *RandomGeneratorUtil::nextItem(VLC->objtypeh->knownSubObjects(Obj::CREATURE_GENERATOR1), rand)); | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
| 			return result; | 			return result; | ||||||
|   | |||||||
| @@ -128,7 +128,7 @@ boost::optional<si32> CIdentifierStorage::getIdentifier(std::string scope, std:: | |||||||
| 	if (idList.size() == 1) | 	if (idList.size() == 1) | ||||||
| 		return idList.front().id; | 		return idList.front().id; | ||||||
| 	if (!silent) | 	if (!silent) | ||||||
| 		logGlobal->errorStream() << "Failed to resolve identifier " << name << " from mod " << scope; | 		logGlobal->errorStream() << "Failed to resolve identifier " << name << " of type " << type << " from mod " << scope; | ||||||
|  |  | ||||||
| 	return boost::optional<si32>(); | 	return boost::optional<si32>(); | ||||||
| } | } | ||||||
| @@ -141,7 +141,7 @@ boost::optional<si32> CIdentifierStorage::getIdentifier(std::string type, const | |||||||
| 	if (idList.size() == 1) | 	if (idList.size() == 1) | ||||||
| 		return idList.front().id; | 		return idList.front().id; | ||||||
| 	if (!silent) | 	if (!silent) | ||||||
| 		logGlobal->errorStream() << "Failed to resolve identifier " << name.String() << " from mod " << type; | 		logGlobal->errorStream() << "Failed to resolve identifier " << name.String() << " of type " << type << " from mod " << name.meta; | ||||||
|  |  | ||||||
| 	return boost::optional<si32>(); | 	return boost::optional<si32>(); | ||||||
| } | } | ||||||
| @@ -155,7 +155,7 @@ boost::optional<si32> CIdentifierStorage::getIdentifier(const JsonNode & name, b | |||||||
| 	if (idList.size() == 1) | 	if (idList.size() == 1) | ||||||
| 		return idList.front().id; | 		return idList.front().id; | ||||||
| 	if (!silent) | 	if (!silent) | ||||||
| 		logGlobal->errorStream() << "Failed to resolve identifier " << name.String() << " from mod " << name.meta; | 		logGlobal->errorStream() << "Failed to resolve identifier " << name.String() << " of type " << pair2.first << " from mod " << name.meta; | ||||||
|  |  | ||||||
| 	return boost::optional<si32>(); | 	return boost::optional<si32>(); | ||||||
| } | } | ||||||
| @@ -223,7 +223,9 @@ bool CIdentifierStorage::resolveIdentifier(const ObjectCallback & request) | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if (request.optional && identifiers.empty()) // failed to resolve optinal ID | 	if (request.optional && identifiers.empty()) // failed to resolve optinal ID | ||||||
|  | 	{ | ||||||
| 		return true; | 		return true; | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	// error found. Try to generate some debug info | 	// error found. Try to generate some debug info | ||||||
| 	if (identifiers.size() == 0) | 	if (identifiers.size() == 0) | ||||||
| @@ -244,16 +246,17 @@ void CIdentifierStorage::finalize() | |||||||
| { | { | ||||||
| 	bool errorsFound = false; | 	bool errorsFound = false; | ||||||
|  |  | ||||||
| 	for(const ObjectCallback & request : scheduledRequests) | 	//Note: we may receive new requests during resolution phase -> end may change -> range for can't be used | ||||||
|  | 	for(auto it = scheduledRequests.begin(); it != scheduledRequests.end(); it++) | ||||||
| 	{ | 	{ | ||||||
| 		errorsFound |= !resolveIdentifier(request); | 		errorsFound |= !resolveIdentifier(*it); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if (errorsFound) | 	if (errorsFound) | ||||||
| 	{ | 	{ | ||||||
| 		for(auto object : registeredObjects) | 		for(auto object : registeredObjects) | ||||||
| 		{ | 		{ | ||||||
| 			logGlobal->traceStream() << object.first << " -> " << object.second.id; | 			logGlobal->traceStream() << object.second.scope << " : " << object.first << " -> " << object.second.id; | ||||||
| 		} | 		} | ||||||
| 		logGlobal->errorStream() << "All known identifiers were dumped into log file"; | 		logGlobal->errorStream() << "All known identifiers were dumped into log file"; | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -554,10 +554,6 @@ void CTownHandler::loadClientData(CTown &town, const JsonNode & source) | |||||||
| 		info.tavernVideo = "TAVERN.BIK"; | 		info.tavernVideo = "TAVERN.BIK"; | ||||||
| 	//end of legacy assignment  | 	//end of legacy assignment  | ||||||
|  |  | ||||||
| 	info.advMapVillage = source["adventureMap"]["village"].String(); |  | ||||||
| 	info.advMapCastle  = source["adventureMap"]["castle"].String(); |  | ||||||
| 	info.advMapCapitol = source["adventureMap"]["capitol"].String(); |  | ||||||
|  |  | ||||||
| 	loadTownHall(town,   source["hallSlots"]); | 	loadTownHall(town,   source["hallSlots"]); | ||||||
| 	loadStructures(town, source["structures"]); | 	loadStructures(town, source["structures"]); | ||||||
| 	loadSiegeScreen(town, source["siege"]); | 	loadSiegeScreen(town, source["siege"]); | ||||||
| @@ -723,6 +719,8 @@ void CTownHandler::loadObject(std::string scope, std::string name, const JsonNod | |||||||
| 	auto object = loadFromJson(data, name); | 	auto object = loadFromJson(data, name); | ||||||
|  |  | ||||||
| 	object->index = factions.size(); | 	object->index = factions.size(); | ||||||
|  | 	factions.push_back(object); | ||||||
|  |  | ||||||
| 	if (object->town) | 	if (object->town) | ||||||
| 	{ | 	{ | ||||||
| 		auto & info = object->town->clientInfo; | 		auto & info = object->town->clientInfo; | ||||||
| @@ -730,9 +728,16 @@ void CTownHandler::loadObject(std::string scope, std::string name, const JsonNod | |||||||
| 		info.icons[0][1] = 8 + object->index * 4 + 1; | 		info.icons[0][1] = 8 + object->index * 4 + 1; | ||||||
| 		info.icons[1][0] = 8 + object->index * 4 + 2; | 		info.icons[1][0] = 8 + object->index * 4 + 2; | ||||||
| 		info.icons[1][1] = 8 + object->index * 4 + 3; | 		info.icons[1][1] = 8 + object->index * 4 + 3; | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	factions.push_back(object); | 		VLC->modh->identifiers.requestIdentifier(scope, "object", "town", [=](si32 index) | ||||||
|  | 		{ | ||||||
|  | 			// register town once objects are loaded | ||||||
|  | 			JsonNode config = data["town"]["mapObject"]; | ||||||
|  | 			config["faction"].String() = object->identifier; | ||||||
|  | 			config["faction"].meta = scope; | ||||||
|  | 			VLC->objtypeh->loadSubObject(object->identifier, config, index, object->index); | ||||||
|  | 		}); | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	VLC->modh->identifiers.registerObject(scope, "faction", name, object->index); | 	VLC->modh->identifiers.registerObject(scope, "faction", name, object->index); | ||||||
| } | } | ||||||
| @@ -741,6 +746,9 @@ void CTownHandler::loadObject(std::string scope, std::string name, const JsonNod | |||||||
| { | { | ||||||
| 	auto object = loadFromJson(data, name); | 	auto object = loadFromJson(data, name); | ||||||
| 	object->index = index; | 	object->index = index; | ||||||
|  | 	assert(factions[index] == nullptr); // ensure that this id was not loaded before | ||||||
|  | 	factions[index] = object; | ||||||
|  |  | ||||||
| 	if (object->town) | 	if (object->town) | ||||||
| 	{ | 	{ | ||||||
| 		auto & info = object->town->clientInfo; | 		auto & info = object->town->clientInfo; | ||||||
| @@ -748,10 +756,16 @@ void CTownHandler::loadObject(std::string scope, std::string name, const JsonNod | |||||||
| 		info.icons[0][1] = (GameConstants::F_NUMBER + object->index) * 2 + 1; | 		info.icons[0][1] = (GameConstants::F_NUMBER + object->index) * 2 + 1; | ||||||
| 		info.icons[1][0] = object->index * 2 + 0; | 		info.icons[1][0] = object->index * 2 + 0; | ||||||
| 		info.icons[1][1] = object->index * 2 + 1; | 		info.icons[1][1] = object->index * 2 + 1; | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	assert(factions[index] == nullptr); // ensure that this id was not loaded before | 		VLC->modh->identifiers.requestIdentifier(scope, "object", "town", [=](si32 index) | ||||||
| 	factions[index] = object; | 		{ | ||||||
|  | 			// register town once objects are loaded | ||||||
|  | 			JsonNode config = data["town"]["mapObject"]; | ||||||
|  | 			config["faction"].String() = object->identifier; | ||||||
|  | 			config["faction"].meta = scope; | ||||||
|  | 			VLC->objtypeh->loadSubObject(object->identifier, config, index, object->index); | ||||||
|  | 		}); | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	VLC->modh->identifiers.registerObject(scope, "faction", name, object->index); | 	VLC->modh->identifiers.registerObject(scope, "faction", name, object->index); | ||||||
| } | } | ||||||
| @@ -761,31 +775,20 @@ void CTownHandler::afterLoadFinalization() | |||||||
| 	initializeRequirements(); | 	initializeRequirements(); | ||||||
| 	for (CFaction * fact : factions) | 	for (CFaction * fact : factions) | ||||||
| 	{ | 	{ | ||||||
|  | 		// MODS COMPATIBILITY FOR 0.96 | ||||||
| 		if (fact->town) | 		if (fact->town) | ||||||
| 		{ | 		{ | ||||||
| 			VLC->objtypeh->loadSubObject(fact->identifier, JsonNode(), Obj::TOWN, fact->index); |  | ||||||
| 			if (!fact->town->clientInfo.advMapCastle.empty()) |  | ||||||
| 			{ |  | ||||||
| 				JsonNode templ; |  | ||||||
| 				templ["animation"].String() = fact->town->clientInfo.advMapCastle; |  | ||||||
| 				VLC->objtypeh->getHandlerFor(Obj::TOWN, fact->index)->addTemplate(templ); |  | ||||||
| 			} |  | ||||||
|  |  | ||||||
| 			assert(fact->town->dwellings.size() == fact->town->dwellingNames.size()); | 			assert(fact->town->dwellings.size() == fact->town->dwellingNames.size()); | ||||||
| 			for (size_t i=0; i<fact->town->dwellings.size(); i++) | 			for (size_t i=0; i<fact->town->dwellings.size(); i++) | ||||||
| 			{ | 			{ | ||||||
| 				//both unupgraded and upgraded get same dwelling | 				//both unupgraded and upgraded get same dwelling | ||||||
| 				for (auto cre : fact->town->creatures[i]) | 				for (auto cre : fact->town->creatures[i]) | ||||||
| 				{ | 				{ | ||||||
| 					if (VLC->objh->cregens.count(cre) == 0) | 					JsonNode templ; | ||||||
| 					{ | 					templ["animation"].String() = fact->town->dwellings[i]; | ||||||
| 						JsonNode templ; |  | ||||||
| 						templ["animation"].String() = fact->town->dwellings[i]; |  | ||||||
|  |  | ||||||
| 						VLC->objtypeh->loadSubObject("", JsonNode(), Obj::CREATURE_GENERATOR1, 80 + cre); | 					VLC->objtypeh->loadSubObject("", JsonNode(), Obj::CREATURE_GENERATOR1, 100 + cre); | ||||||
| 						VLC->objtypeh->getHandlerFor(Obj::CREATURE_GENERATOR1, 80 + cre)->addTemplate(templ); | 					VLC->objtypeh->getHandlerFor(Obj::CREATURE_GENERATOR1, 100 + cre)->addTemplate(templ); | ||||||
| 						VLC->objh->cregens[80 + cre] = cre; //map of dwelling -> creature id |  | ||||||
| 					} |  | ||||||
| 				 } | 				 } | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|   | |||||||
| @@ -190,10 +190,6 @@ public: | |||||||
| 		/// NOTE: index in vector is meaningless. Vector used instead of list for a bit faster access | 		/// NOTE: index in vector is meaningless. Vector used instead of list for a bit faster access | ||||||
| 		std::vector<ConstTransitivePtr<CStructure> > structures; | 		std::vector<ConstTransitivePtr<CStructure> > structures; | ||||||
|  |  | ||||||
| 		std::string advMapVillage; |  | ||||||
| 		std::string advMapCastle; |  | ||||||
| 		std::string advMapCapitol; |  | ||||||
|  |  | ||||||
| 		std::string siegePrefix; | 		std::string siegePrefix; | ||||||
| 		std::vector<Point> siegePositions; | 		std::vector<Point> siegePositions; | ||||||
| 		CreatureID siegeShooter; // shooter creature ID | 		CreatureID siegeShooter; // shooter creature ID | ||||||
| @@ -201,7 +197,7 @@ public: | |||||||
| 		template <typename Handler> void serialize(Handler &h, const int version) | 		template <typename Handler> void serialize(Handler &h, const int version) | ||||||
| 		{ | 		{ | ||||||
| 			h & icons & iconSmall & iconLarge & tavernVideo & musicTheme & townBackground & guildBackground & guildWindow & buildingsIcons & hallBackground; | 			h & icons & iconSmall & iconLarge & tavernVideo & musicTheme & townBackground & guildBackground & guildWindow & buildingsIcons & hallBackground; | ||||||
| 			h & advMapVillage & advMapCastle & advMapCapitol & hallSlots & structures; | 			h & hallSlots & structures; | ||||||
| 			h & siegePrefix & siegePositions & siegeShooter; | 			h & siegePrefix & siegePositions & siegeShooter; | ||||||
| 		} | 		} | ||||||
| 	} clientInfo; | 	} clientInfo; | ||||||
|   | |||||||
| @@ -737,7 +737,7 @@ void JsonUtils::mergeCopy(JsonNode & dest, JsonNode source) | |||||||
|  |  | ||||||
| void JsonUtils::inherit(JsonNode & descendant, const JsonNode & base) | void JsonUtils::inherit(JsonNode & descendant, const JsonNode & base) | ||||||
| { | { | ||||||
| 	JsonNode inheritedNode(base);		 | 	JsonNode inheritedNode(base); | ||||||
| 	merge(inheritedNode,descendant); | 	merge(inheritedNode,descendant); | ||||||
| 	descendant.swap(inheritedNode); | 	descendant.swap(inheritedNode); | ||||||
| } | } | ||||||
|   | |||||||
| @@ -45,11 +45,11 @@ DLL_LINKAGE void preinitDLL(CConsoleHandler *Console) | |||||||
|  |  | ||||||
| DLL_LINKAGE void loadDLLClasses() | DLL_LINKAGE void loadDLLClasses() | ||||||
| { | { | ||||||
| 	try | //	try | ||||||
| 	{ | 	{ | ||||||
| 		VLC->init(); | 		VLC->init(); | ||||||
| 	} | 	} | ||||||
| 	HANDLE_EXCEPTION; | //	HANDLE_EXCEPTION; | ||||||
| } | } | ||||||
|  |  | ||||||
| const IBonusTypeHandler * LibClasses::getBth() const | const IBonusTypeHandler * LibClasses::getBth() const | ||||||
|   | |||||||
| @@ -13,6 +13,7 @@ | |||||||
|  |  | ||||||
| #include "../NetPacks.h" | #include "../NetPacks.h" | ||||||
| #include "../CGeneralTextHandler.h" | #include "../CGeneralTextHandler.h" | ||||||
|  | #include "../mapObjects/CObjectClassesHandler.h" | ||||||
|  |  | ||||||
| using namespace boost::assign; | using namespace boost::assign; | ||||||
|  |  | ||||||
| @@ -24,54 +25,18 @@ void CGDwelling::initObj() | |||||||
| 	switch(ID) | 	switch(ID) | ||||||
| 	{ | 	{ | ||||||
| 	case Obj::CREATURE_GENERATOR1: | 	case Obj::CREATURE_GENERATOR1: | ||||||
|  | 	case Obj::CREATURE_GENERATOR4: | ||||||
| 		{ | 		{ | ||||||
| 			CreatureID crid = VLC->objh->cregens[subID]; | 			VLC->objtypeh->getHandlerFor(ID, subID)->configureObject(this, cb->gameState()->getRandomGenerator()); | ||||||
| 			const CCreature *crs = VLC->creh->creatures[crid]; |  | ||||||
|  |  | ||||||
| 			creatures.resize(1); |  | ||||||
| 			creatures[0].second.push_back(crid); |  | ||||||
| 			if (subID >= VLC->generaltexth->creGens.size()) //very messy workaround |  | ||||||
| 			{ |  | ||||||
| 				auto & dwellingNames = VLC->townh->factions[crs->faction]->town->dwellingNames; |  | ||||||
| 				assert (dwellingNames.size() > crs->level - 1); |  | ||||||
| 				hoverName = dwellingNames[crs->level - 1]; |  | ||||||
| 			} |  | ||||||
| 			else |  | ||||||
| 				hoverName = VLC->generaltexth->creGens[subID]; |  | ||||||
| 			if(crs->level > 4) |  | ||||||
| 				putStack(SlotID(0), new CStackInstance(crs, (crs->growth) * 3)); |  | ||||||
| 			if (getOwner() != PlayerColor::NEUTRAL) | 			if (getOwner() != PlayerColor::NEUTRAL) | ||||||
| 				cb->gameState()->players[getOwner()].dwellings.push_back (this); | 				cb->gameState()->players[getOwner()].dwellings.push_back (this); | ||||||
| 		} | 		} | ||||||
| 		break; | 			//putStack(SlotID(0), new CStackInstance(CreatureID::GOLD_GOLEM, 9)); | ||||||
|  | 			//putStack(SlotID(1), new CStackInstance(CreatureID::DIAMOND_GOLEM, 6)); | ||||||
|  |  | ||||||
| 	case Obj::CREATURE_GENERATOR4: | 			//putStack(SlotID(0), new CStackInstance(CreatureID::EARTH_ELEMENTAL, 12)); | ||||||
| 		creatures.resize(4); | 			break; | ||||||
| 		if(subID == 1) //Golem Factory |  | ||||||
| 		{ |  | ||||||
| 			creatures[0].second.push_back(CreatureID::STONE_GOLEM); |  | ||||||
| 			creatures[1].second.push_back(CreatureID::IRON_GOLEM); |  | ||||||
| 			creatures[2].second.push_back(CreatureID::GOLD_GOLEM); |  | ||||||
| 			creatures[3].second.push_back(CreatureID::DIAMOND_GOLEM); |  | ||||||
| 			//guards |  | ||||||
| 			putStack(SlotID(0), new CStackInstance(CreatureID::GOLD_GOLEM, 9)); |  | ||||||
| 			putStack(SlotID(1), new CStackInstance(CreatureID::DIAMOND_GOLEM, 6)); |  | ||||||
| 		} |  | ||||||
| 		else if(subID == 0) // Elemental Conflux |  | ||||||
| 		{ |  | ||||||
| 			creatures[0].second.push_back(CreatureID::AIR_ELEMENTAL); |  | ||||||
| 			creatures[1].second.push_back(CreatureID::FIRE_ELEMENTAL); |  | ||||||
| 			creatures[2].second.push_back(CreatureID::EARTH_ELEMENTAL); |  | ||||||
| 			creatures[3].second.push_back(CreatureID::WATER_ELEMENTAL); |  | ||||||
| 			//guards |  | ||||||
| 			putStack(SlotID(0), new CStackInstance(CreatureID::EARTH_ELEMENTAL, 12)); |  | ||||||
| 		} |  | ||||||
| 		else |  | ||||||
| 		{ |  | ||||||
| 			assert(0); |  | ||||||
| 		} |  | ||||||
| 		hoverName = VLC->generaltexth->creGens4[subID]; |  | ||||||
| 		break; |  | ||||||
|  |  | ||||||
| 	case Obj::REFUGEE_CAMP: | 	case Obj::REFUGEE_CAMP: | ||||||
| 		//is handled within newturn func | 		//is handled within newturn func | ||||||
| @@ -811,12 +776,10 @@ void CGTownInstance::setType(si32 ID, si32 subID) | |||||||
|  |  | ||||||
| void CGTownInstance::updateAppearance() | void CGTownInstance::updateAppearance() | ||||||
| { | { | ||||||
| 	if (!hasFort()) | 	//FIXME: not the best way to do this | ||||||
| 		appearance.animationFile = town->clientInfo.advMapVillage; | 	auto app = VLC->objtypeh->getHandlerFor(ID, subID)->getOverride(cb->gameState()->getTile(visitablePos())->terType, this); | ||||||
| 	else if(hasCapitol()) | 	if (app) | ||||||
| 		appearance.animationFile = town->clientInfo.advMapCapitol; | 		appearance = app.get(); | ||||||
| 	else |  | ||||||
| 		appearance.animationFile = town->clientInfo.advMapCastle; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| std::string CGTownInstance::nodeName() const | std::string CGTownInstance::nodeName() const | ||||||
|   | |||||||
| @@ -153,6 +153,7 @@ void CObjectClassesHandler::loadObjectEntry(const JsonNode & entry, ObjectContai | |||||||
| 	} | 	} | ||||||
| 	 | 	 | ||||||
| 	obj->objects[id] = handler; | 	obj->objects[id] = handler; | ||||||
|  | 	logGlobal->debugStream() << "Loaded object " << obj->id << ":" << id; | ||||||
| } | } | ||||||
|  |  | ||||||
| CObjectClassesHandler::ObjectContainter * CObjectClassesHandler::loadFromJson(const JsonNode & json) | CObjectClassesHandler::ObjectContainter * CObjectClassesHandler::loadFromJson(const JsonNode & json) | ||||||
| @@ -198,8 +199,9 @@ void CObjectClassesHandler::loadSubObject(std::string name, JsonNode config, si3 | |||||||
| 		config["index"].Float() = subID.get(); | 		config["index"].Float() = subID.get(); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	std::string oldMeta = config.meta; // FIXME: move into inheritNode? | ||||||
| 	JsonUtils::inherit(config, objects.at(ID)->base); | 	JsonUtils::inherit(config, objects.at(ID)->base); | ||||||
| 	logGlobal->errorStream() << "JSON: " << config; | 	config.setMeta(oldMeta); | ||||||
| 	loadObjectEntry(config, objects[ID]); | 	loadObjectEntry(config, objects[ID]); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -339,9 +341,6 @@ void AObjectTypeHandler::addTemplate(ObjectTemplate templ) | |||||||
|  |  | ||||||
| void AObjectTypeHandler::addTemplate(JsonNode config) | void AObjectTypeHandler::addTemplate(JsonNode config) | ||||||
| { | { | ||||||
| 	logGlobal->errorStream() << "INPUT  FOR: " << type << ":" << subtype << " " << config; |  | ||||||
| 	logGlobal->errorStream() << "BASE   FOR: " << type << ":" << subtype << " " << base; |  | ||||||
|  |  | ||||||
| 	config.setType(JsonNode::DATA_STRUCT); // ensure that input is not null | 	config.setType(JsonNode::DATA_STRUCT); // ensure that input is not null | ||||||
| 	JsonUtils::inherit(config, base); | 	JsonUtils::inherit(config, base); | ||||||
| 	ObjectTemplate tmpl; | 	ObjectTemplate tmpl; | ||||||
| @@ -349,7 +348,6 @@ void AObjectTypeHandler::addTemplate(JsonNode config) | |||||||
| 	tmpl.subid = subtype; | 	tmpl.subid = subtype; | ||||||
| 	tmpl.stringID = ""; // TODO? | 	tmpl.stringID = ""; // TODO? | ||||||
| 	tmpl.readJson(config); | 	tmpl.readJson(config); | ||||||
| 	logGlobal->errorStream() << "DATA  FOR: " << type << ":" << subtype << " " << config; |  | ||||||
| 	addTemplate(tmpl); | 	addTemplate(tmpl); | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -68,7 +68,7 @@ public: | |||||||
|  |  | ||||||
| class CGObjectInstance; | class CGObjectInstance; | ||||||
|  |  | ||||||
| class AObjectTypeHandler | class AObjectTypeHandler : public boost::noncopyable | ||||||
| { | { | ||||||
| 	RandomMapInfo rmgInfo; | 	RandomMapInfo rmgInfo; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -157,15 +157,6 @@ static void readBankLevel(const JsonNode &level, BankConfig &bc) | |||||||
|  |  | ||||||
| CObjectHandler::CObjectHandler() | CObjectHandler::CObjectHandler() | ||||||
| { | { | ||||||
|     logGlobal->traceStream() << "\t\tReading cregens "; |  | ||||||
|  |  | ||||||
| 	const JsonNode config(ResourceID("config/dwellings.json")); |  | ||||||
| 	for(const JsonNode &dwelling : config["dwellings"].Vector()) |  | ||||||
| 	{ |  | ||||||
| 		cregens[dwelling["dwelling"].Float()] = CreatureID((si32)dwelling["creature"].Float()); |  | ||||||
| 	} |  | ||||||
|     logGlobal->traceStream() << "\t\tDone loading cregens!"; |  | ||||||
|  |  | ||||||
|     logGlobal->traceStream() << "\t\tReading resources prices "; |     logGlobal->traceStream() << "\t\tReading resources prices "; | ||||||
| 	const JsonNode config2(ResourceID("config/resources.json")); | 	const JsonNode config2(ResourceID("config/resources.json")); | ||||||
| 	for(const JsonNode &price : config2["resources_prices"].Vector()) | 	for(const JsonNode &price : config2["resources_prices"].Vector()) | ||||||
| @@ -342,10 +333,10 @@ void CGObjectInstance::setType(si32 ID, si32 subID) | |||||||
|  |  | ||||||
| 	this->ID = Obj(ID); | 	this->ID = Obj(ID); | ||||||
| 	this->subID = subID; | 	this->subID = subID; | ||||||
| 	this->appearance = VLC->objtypeh->getHandlerFor(ID, subID)->getTemplates(tile.terType).front(); |  | ||||||
|  |  | ||||||
| 	//recalculate blockvis tiles - new appearance might have different blockmap than before | 	//recalculate blockvis tiles - new appearance might have different blockmap than before | ||||||
| 	cb->gameState()->map->removeBlockVisTiles(this, true); | 	cb->gameState()->map->removeBlockVisTiles(this, true); | ||||||
|  | 	this->appearance = VLC->objtypeh->getHandlerFor(ID, subID)->getTemplates(tile.terType).at(0); | ||||||
| 	cb->gameState()->map->addBlockVisTiles(this); | 	cb->gameState()->map->addBlockVisTiles(this); | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -187,7 +187,6 @@ struct BankConfig | |||||||
| class DLL_LINKAGE CObjectHandler | class DLL_LINKAGE CObjectHandler | ||||||
| { | { | ||||||
| public: | public: | ||||||
| 	std::map<si32, CreatureID> cregens; //type 17. dwelling subid -> creature ID |  | ||||||
| 	std::map <ui32, std::vector < ConstTransitivePtr<BankConfig> > > banksInfo; //[index][preset] | 	std::map <ui32, std::vector < ConstTransitivePtr<BankConfig> > > banksInfo; //[index][preset] | ||||||
| 	std::map <ui32, std::string> creBanksNames; //[crebank index] -> name of this creature bank | 	std::map <ui32, std::string> creBanksNames; //[crebank index] -> name of this creature bank | ||||||
| 	std::vector<ui32> resVals; //default values of resources in gold | 	std::vector<ui32> resVals; //default values of resources in gold | ||||||
| @@ -199,6 +198,6 @@ public: | |||||||
|  |  | ||||||
| 	template <typename Handler> void serialize(Handler &h, const int version) | 	template <typename Handler> void serialize(Handler &h, const int version) | ||||||
| 	{ | 	{ | ||||||
| 		h & cregens & banksInfo & creBanksNames & resVals; | 		h & banksInfo & creBanksNames & resVals; | ||||||
| 	} | 	} | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -26,23 +26,27 @@ bool CObstacleConstructor::isStaticObject() | |||||||
| 	return true; | 	return true; | ||||||
| } | } | ||||||
|  |  | ||||||
| CTownInstanceConstructor::CTownInstanceConstructor() | CTownInstanceConstructor::CTownInstanceConstructor(): | ||||||
|  | 	faction(nullptr) | ||||||
| { | { | ||||||
| } | } | ||||||
|  |  | ||||||
| void CTownInstanceConstructor::initTypeData(const JsonNode & input) | void CTownInstanceConstructor::initTypeData(const JsonNode & input) | ||||||
| { | { | ||||||
| 	VLC->modh->identifiers.requestIdentifier("faction", input["faction"], | 	VLC->modh->identifiers.requestIdentifier("faction", input["faction"], [&](si32 index) | ||||||
| 			[&](si32 index) { faction = VLC->townh->factions[index]; }); | 	{ | ||||||
|  | 		faction = VLC->townh->factions[index]; | ||||||
|  | 	}); | ||||||
|  |  | ||||||
| 	filtersJson = input["filters"]; | 	filtersJson = input["filters"]; | ||||||
| } | } | ||||||
|  |  | ||||||
| void CTownInstanceConstructor::afterLoadFinalization() | void CTownInstanceConstructor::afterLoadFinalization() | ||||||
| { | { | ||||||
|  | 	assert(faction); | ||||||
| 	for (auto entry : filtersJson.Struct()) | 	for (auto entry : filtersJson.Struct()) | ||||||
| 	{ | 	{ | ||||||
| 		filters[entry.first] = LogicalExpression<BuildingID>(entry.second, [&](const JsonNode & node) | 		filters[entry.first] = LogicalExpression<BuildingID>(entry.second, [this](const JsonNode & node) | ||||||
| 		{ | 		{ | ||||||
| 			return BuildingID(VLC->modh->identifiers.getIdentifier("building." + faction->identifier, node.Vector()[0]).get()); | 			return BuildingID(VLC->modh->identifiers.getIdentifier("building." + faction->identifier, node.Vector()[0]).get()); | ||||||
| 		}); | 		}); | ||||||
| @@ -121,12 +125,13 @@ void CDwellingInstanceConstructor::initTypeData(const JsonNode & input) | |||||||
| 		availableCreatures[i].resize(creatures.size()); | 		availableCreatures[i].resize(creatures.size()); | ||||||
| 		for (size_t j=0; j<creatures.size(); j++) | 		for (size_t j=0; j<creatures.size(); j++) | ||||||
| 		{ | 		{ | ||||||
| 			VLC->modh->identifiers.requestIdentifier("creature", creatures[j], [&] (si32 index) | 			VLC->modh->identifiers.requestIdentifier("creature", creatures[j], [=] (si32 index) | ||||||
| 			{ | 			{ | ||||||
| 				availableCreatures[i][j] = VLC->creh->creatures[index]; | 				availableCreatures[i][j] = VLC->creh->creatures[index]; | ||||||
| 			}); | 			}); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | 	guards = input["guards"]; | ||||||
| } | } | ||||||
|  |  | ||||||
| bool CDwellingInstanceConstructor::objectFilter(const CGObjectInstance *, const ObjectTemplate &) const | bool CDwellingInstanceConstructor::objectFilter(const CGObjectInstance *, const ObjectTemplate &) const | ||||||
| @@ -137,17 +142,69 @@ bool CDwellingInstanceConstructor::objectFilter(const CGObjectInstance *, const | |||||||
| CGObjectInstance * CDwellingInstanceConstructor::create(ObjectTemplate tmpl) const | CGObjectInstance * CDwellingInstanceConstructor::create(ObjectTemplate tmpl) const | ||||||
| { | { | ||||||
| 	CGDwelling * obj = createTyped(tmpl); | 	CGDwelling * obj = createTyped(tmpl); | ||||||
| 	for (auto entry : availableCreatures) |  | ||||||
| 	{ |  | ||||||
| 		obj->creatures.resize(obj->creatures.size()+1); |  | ||||||
|  |  | ||||||
|  | 	obj->creatures.resize(availableCreatures.size()); | ||||||
|  | 	for (auto & entry : availableCreatures) | ||||||
|  | 	{ | ||||||
| 		for (const CCreature * cre : entry) | 		for (const CCreature * cre : entry) | ||||||
| 			obj->creatures.back().second.push_back(cre->idNumber); | 			obj->creatures.back().second.push_back(cre->idNumber); | ||||||
| 	} | 	} | ||||||
| 	return obj; | 	return obj; | ||||||
| } | } | ||||||
|  |  | ||||||
| void CDwellingInstanceConstructor::configureObject(CGObjectInstance * object, CRandomGenerator & rng) const | namespace | ||||||
| { | { | ||||||
|  | 	si32 loadValue(const JsonNode & value, CRandomGenerator & rng, si32 defaultValue = 0) | ||||||
|  | 	{ | ||||||
|  | 		if (value.isNull()) | ||||||
|  | 			return defaultValue; | ||||||
|  | 		if (value.getType() == JsonNode::DATA_FLOAT) | ||||||
|  | 			return value.Float(); | ||||||
|  | 		si32 min = value["min"].Float(); | ||||||
|  | 		si32 max = value["max"].Float(); | ||||||
|  | 		return rng.getIntRange(min, max)(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	std::vector<CStackBasicDescriptor> loadCreatures(const JsonNode & value, CRandomGenerator & rng) | ||||||
|  | 	{ | ||||||
|  | 		std::vector<CStackBasicDescriptor> ret; | ||||||
|  | 		for (auto & pair : value.Struct()) | ||||||
|  | 		{ | ||||||
|  | 			CStackBasicDescriptor stack; | ||||||
|  | 			stack.type = VLC->creh->creatures[VLC->modh->identifiers.getIdentifier(pair.second.meta, "creature", pair.first).get()]; | ||||||
|  | 			stack.count = loadValue(pair.second, rng); | ||||||
|  | 			ret.push_back(stack); | ||||||
|  | 		} | ||||||
|  | 		return ret; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void CDwellingInstanceConstructor::configureObject(CGObjectInstance * object, CRandomGenerator &rng) const | ||||||
|  | { | ||||||
|  | 	CGDwelling * dwelling = dynamic_cast<CGDwelling*>(object); | ||||||
|  |  | ||||||
|  | 	dwelling->creatures.clear(); | ||||||
|  | 	dwelling->creatures.resize(availableCreatures.size()); | ||||||
|  |  | ||||||
|  | 	for (auto & entry : availableCreatures) | ||||||
|  | 	{ | ||||||
|  | 		for (const CCreature * cre : entry) | ||||||
|  | 			dwelling->creatures.back().second.push_back(cre->idNumber); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	for (auto & stack : loadCreatures(guards, rng)) | ||||||
|  | 	{ | ||||||
|  | 		dwelling->putStack(SlotID(dwelling->stacksCount()), new CStackInstance(stack.type->idNumber, stack.count)); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | bool CDwellingInstanceConstructor::producesCreature(const CCreature * crea) const | ||||||
|  | { | ||||||
|  | 	for (auto & entry : availableCreatures) | ||||||
|  | 	{ | ||||||
|  | 		for (const CCreature * cre : entry) | ||||||
|  | 			if (crea == cre) | ||||||
|  | 				return true; | ||||||
|  | 	} | ||||||
|  | 	return false; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -91,14 +91,19 @@ public: | |||||||
|  |  | ||||||
| class CDwellingInstanceConstructor : public CDefaultObjectTypeHandler<CGDwelling> | class CDwellingInstanceConstructor : public CDefaultObjectTypeHandler<CGDwelling> | ||||||
| { | { | ||||||
|  | 	std::vector<std::vector<const CCreature *>> availableCreatures; | ||||||
|  |  | ||||||
|  | 	JsonNode guards; | ||||||
|  |  | ||||||
| protected: | protected: | ||||||
| 	bool objectFilter(const CGObjectInstance *, const ObjectTemplate &) const; | 	bool objectFilter(const CGObjectInstance *, const ObjectTemplate &) const; | ||||||
|  |  | ||||||
| public: | public: | ||||||
| 	std::vector<std::vector<CCreature *>> availableCreatures; |  | ||||||
|  |  | ||||||
| 	CDwellingInstanceConstructor(); | 	CDwellingInstanceConstructor(); | ||||||
| 	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; | ||||||
|  |  | ||||||
|  | 	bool producesCreature(const CCreature * crea) const; | ||||||
| }; | }; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user