Browse Source

- some groundwork for wog optionality
- moved wog artifacts to wog mod

Ivan Savenko 12 years ago
parent
commit
8297102350

+ 309 - 0
Mods/WoG/config/wog/artifacts.json

@@ -0,0 +1,309 @@
+{
+	"art144":
+	{
+		"index" : 144,
+		"type" : ["HERO"]
+	},
+	"art145":
+	{
+		"index" : 145,
+		"type" : ["HERO"]
+	},
+	"axeOfSmashing": //TODO: move growing bonuses to this config, someday
+	{
+		"bonuses" : [
+			{
+				"subtype" : "primSkill.attack",
+				"type" : "PRIMARY_SKILL",
+				"val" : 6,
+				"valueType" : "BASE_NUMBER"
+			}
+		],
+		"index" : 146,
+		"type" : ["COMMANDER"],
+		"growing":
+		{
+			"bonusesPerLevel":
+			[
+				{
+					"level": 6,
+					"bonus": 
+					{
+						"type" : "PRIMARY_SKILL",
+						"subtype" : "primSkill.attack",
+						"val" : 1
+					}
+				}
+			]
+		}
+	},
+	"mithrilMail":
+	{
+		"bonuses" : [
+			{
+				"type" : "STACK_HEALTH",
+				"val" : 12,
+				"valueType" : "PERCENT_TO_ALL"
+			}
+		],
+		"index" : 147,
+		"type" : ["COMMANDER"],
+		"growing":
+		{
+			"bonusesPerLevel":
+			[
+				{
+					"level": 1,
+					"bonus": 
+					{
+						"type" : "STACK_HEALTH",
+						"val" : 1
+					}
+				}
+			]
+		}
+	},
+	"swordOfSharpness":
+	{
+		"bonuses" : [
+			{
+				"subtype" : 0,
+				"type" : "CREATURE_DAMAGE",
+				"val" : 12,
+				"valueType" : "PERCENT_TO_ALL"
+			}
+		],
+		"index" : 148,
+		"type" : ["COMMANDER"],
+		"growing":
+		{
+			"bonusesPerLevel":
+			[
+				{
+					"level": 1,
+					"bonus": 
+					{
+						"type" : "CREATURE_DAMAGE",
+						"val" : 1
+					}
+				}
+			]
+		}
+	},
+	"helmOfImmortality": //TODO: implement
+	{
+		"index" : 149,
+		"type" : ["COMMANDER"]
+	},
+	"pendantOfSorcery":
+	{
+		"bonuses" : [
+			{
+				"type" : "CASTS",
+				"val" : 1,
+				"valueType" : "BASE_NUMBER"
+			}
+		],
+		"index" : 150,
+		"type" : ["COMMANDER"],
+		"growing":
+		{
+			"bonusesPerLevel":
+			[
+				{
+					"level": 10,
+					"bonus": 
+					{
+						"type" : "CREATURE_ENCHANT_POWER",
+						"val" : 1
+					}
+				}
+			]
+		}
+	},
+	"bootsOfHaste":
+	{
+		"bonuses" : [
+			{
+				"type" : "STACKS_SPEED",
+				"val" : 1,
+				"valueType" : "BASE_NUMBER"
+			}
+		],
+		"index" : 151,
+		"type" : ["COMMANDER"],
+		"growing":
+		{
+			"bonusesPerLevel":
+			[
+				{
+					"level": 10,
+					"bonus": 
+					{
+						"type" : "STACKS_SPEED",
+						"val" : 1
+					}
+				}
+			]
+		}
+	},
+	"bowOfSeeking":
+	{
+		"index" : 152,
+		"type" : ["COMMANDER"],
+		"growing":
+		{
+			"thresholdBonuses":
+			[
+				{
+					"level": 5,
+					"bonus":
+					{
+						"type" : "SHOOTER"
+					}
+				},
+				{
+					"level": 25,
+					"bonus": 
+					{
+						"type" : "NO_WALL_PENALTY"
+					}
+				},
+				{
+					"level": 50,
+					"bonus": 
+					{
+						"type" : "NO_DISTANCE_PENALTY"
+					}
+				}
+			]
+		}
+	},
+	"dragonEyeRing": //TODO: implement
+	{
+		"index" : 153,
+		"type" : ["COMMANDER"],
+	},
+	"hardenedShield":
+	{
+		"bonuses" : [
+			{
+				"subtype" : "primSkill.attack",
+				"type" : "PRIMARY_SKILL",
+				"val" : 6,
+				"valueType" : "BASE_NUMBER"
+			}
+		],
+		"index" : 154,
+		"type" : ["COMMANDER"],
+		"growing":
+		{
+			"bonusesPerLevel":
+			[
+				{
+					"level": 6,
+					"bonus": 
+					{
+						"type" : "PRIMARY_SKILL",
+						"subtype" : "primSkill.defence",
+						"val" : 1
+					}
+				}
+			]
+		}
+	},
+	"slavasRingOfPower": //TODO: implement if possible
+	{
+		"index" : 155,
+		"type" : ["COMMANDER"]
+	},
+	"warlordsBanner":
+	{
+		"bonuses" : [
+			{
+				"type" : "STACK_HEALTH",
+				"val" : 2,
+				"valueType" : "BASE_NUMBER"
+			}
+		],
+		"index" : 156,
+		"type" : ["CREATURE"]
+	},
+	"crimsonShieldOfRetribution": //TODO: implement
+	{
+		"index" : 157,
+		"type" : ["HERO"]
+	},
+	"barbarianLordsAxeOfFerocity": //TODO: implement
+	{
+		"index" : 158,
+		"type" : ["HERO"],
+		"components":
+		[
+			"ogresClubOfHavoc",
+			"targOfTheRampagingOgre",
+			"crownOfTheSupremeMagi",
+			"tunicOfTheCyclopsKing"
+		]
+	},
+	"dragonheart":
+	{
+		"index" : 159,
+		"type" : ["HERO"]
+	},
+	"gateKey":
+	{
+		"index" : 160,
+		"type" : ["HERO"]
+	},
+	"art161":
+	{
+		"index" : 161,
+		"type" : ["HERO"]
+	},
+	"art162":
+	{
+		"index" : 162,
+		"type" : ["HERO"]
+	},
+	"art163":
+	{
+		"index" : 163,
+		"type" : ["HERO"]
+	},
+	"art164":
+	{
+		"index" : 164,
+		"type" : ["HERO"]
+	},
+	"art165":
+	{
+		"index" : 165,
+		"type" : ["HERO"]
+	},
+	"art166":
+	{
+		"index" : 166,
+		"type" : ["HERO"]
+	},
+	"art167":
+	{
+		"index" : 167,
+		"type" : ["HERO"]
+	},
+	"art168":
+	{
+		"index" : 168,
+		"type" : ["HERO"]
+	},
+	"art169":
+	{
+		"index" : 169,
+		"type" : ["HERO"]
+	},
+	"art170":
+	{
+		"index" : 170,
+		"type" : ["HERO"]
+	}
+}

+ 5 - 0
Mods/WoG/mod.json

@@ -40,6 +40,11 @@
 	"name" : "In The Wake of Gods",
 	"name" : "In The Wake of Gods",
 	"description" : "Unnofficial addon for Heroes of Might and Magic III",
 	"description" : "Unnofficial addon for Heroes of Might and Magic III",
 
 
+	"artifacts" : 
+	[
+		"config/wog/artifacts.json"
+	],
+
 	"creatures" : 
 	"creatures" : 
 	[
 	[
 		"config/wog/creatures.json"
 		"config/wog/creatures.json"

+ 0 - 307
config/artifacts.json

@@ -2332,312 +2332,5 @@
 		],
 		],
 		"index" : 143,
 		"index" : 143,
 		"type" : ["CREATURE"]
 		"type" : ["CREATURE"]
-	},
-	"art144":
-	{
-		"index" : 144,
-		"type" : ["HERO"]
-	},
-	"art145":
-	{
-		"index" : 145,
-		"type" : ["HERO"]
-	},
-	"axeOfSmashing": //TODO: move growing bonuses to this config, someday
-	{
-		"bonuses" : [
-			{
-				"subtype" : "primSkill.attack",
-				"type" : "PRIMARY_SKILL",
-				"val" : 6,
-				"valueType" : "BASE_NUMBER"
-			}
-		],
-		"index" : 146,
-		"type" : ["COMMANDER"],
-		"growing":
-		{
-			"bonusesPerLevel":
-			[
-				{
-					"level": 6,
-					"bonus": 
-					{
-						"type" : "PRIMARY_SKILL",
-						"subtype" : "primSkill.attack",
-						"val" : 1
-					}
-				}
-			]
-		}
-	},
-	"mithrilMail":
-	{
-		"bonuses" : [
-			{
-				"type" : "STACK_HEALTH",
-				"val" : 12,
-				"valueType" : "PERCENT_TO_ALL"
-			}
-		],
-		"index" : 147,
-		"type" : ["COMMANDER"],
-		"growing":
-		{
-			"bonusesPerLevel":
-			[
-				{
-					"level": 1,
-					"bonus": 
-					{
-						"type" : "STACK_HEALTH",
-						"val" : 1
-					}
-				}
-			]
-		}
-	},
-	"swordOfSharpness":
-	{
-		"bonuses" : [
-			{
-				"subtype" : 0,
-				"type" : "CREATURE_DAMAGE",
-				"val" : 12,
-				"valueType" : "PERCENT_TO_ALL"
-			}
-		],
-		"index" : 148,
-		"type" : ["COMMANDER"],
-		"growing":
-		{
-			"bonusesPerLevel":
-			[
-				{
-					"level": 1,
-					"bonus": 
-					{
-						"type" : "CREATURE_DAMAGE",
-						"val" : 1
-					}
-				}
-			]
-		}
-	},
-	"helmOfImmortality": //TODO: implement
-	{
-		"index" : 149,
-		"type" : ["COMMANDER"]
-	},
-	"pendantOfSorcery":
-	{
-		"bonuses" : [
-			{
-				"type" : "CASTS",
-				"val" : 1,
-				"valueType" : "BASE_NUMBER"
-			}
-		],
-		"index" : 150,
-		"type" : ["COMMANDER"],
-		"growing":
-		{
-			"bonusesPerLevel":
-			[
-				{
-					"level": 10,
-					"bonus": 
-					{
-						"type" : "CREATURE_ENCHANT_POWER",
-						"val" : 1
-					}
-				}
-			]
-		}
-	},
-	"bootsOfHaste":
-	{
-		"bonuses" : [
-			{
-				"type" : "STACKS_SPEED",
-				"val" : 1,
-				"valueType" : "BASE_NUMBER"
-			}
-		],
-		"index" : 151,
-		"type" : ["COMMANDER"],
-		"growing":
-		{
-			"bonusesPerLevel":
-			[
-				{
-					"level": 10,
-					"bonus": 
-					{
-						"type" : "STACKS_SPEED",
-						"val" : 1
-					}
-				}
-			]
-		}
-	},
-	"bowOfSeeking":
-	{
-		"index" : 152,
-		"type" : ["COMMANDER"],
-		"growing":
-		{
-			"thresholdBonuses":
-			[
-				{
-					"level": 5,
-					"bonus":
-					{
-						"type" : "SHOOTER"
-					}
-				},
-				{
-					"level": 25,
-					"bonus": 
-					{
-						"type" : "NO_WALL_PENALTY"
-					}
-				},
-				{
-					"level": 50,
-					"bonus": 
-					{
-						"type" : "NO_DISTANCE_PENALTY"
-					}
-				}
-			]
-		}
-	},
-	"dragonEyeRing": //TODO: implement
-	{
-		"index" : 153,
-		"type" : ["COMMANDER"],
-	},
-	"hardenedShield":
-	{
-		"bonuses" : [
-			{
-				"subtype" : "primSkill.attack",
-				"type" : "PRIMARY_SKILL",
-				"val" : 6,
-				"valueType" : "BASE_NUMBER"
-			}
-		],
-		"index" : 154,
-		"type" : ["COMMANDER"],
-		"growing":
-		{
-			"bonusesPerLevel":
-			[
-				{
-					"level": 6,
-					"bonus": 
-					{
-						"type" : "PRIMARY_SKILL",
-						"subtype" : "primSkill.defence",
-						"val" : 1
-					}
-				}
-			]
-		}
-	},
-	"slavasRingOfPower": //TODO: implement if possible
-	{
-		"index" : 155,
-		"type" : ["COMMANDER"]
-	},
-	"warlordsBanner":
-	{
-		"bonuses" : [
-			{
-				"type" : "STACK_HEALTH",
-				"val" : 2,
-				"valueType" : "BASE_NUMBER"
-			}
-		],
-		"index" : 156,
-		"type" : ["CREATURE"]
-	},
-	"crimsonShieldOfRetribution": //TODO: implement
-	{
-		"index" : 157,
-		"type" : ["HERO"]
-	},
-	"barbarianLordsAxeOfFerocity": //TODO: implement
-	{
-		"index" : 158,
-		"type" : ["HERO"],
-		"components":
-		[
-			"ogresClubOfHavoc",
-			"targOfTheRampagingOgre",
-			"crownOfTheSupremeMagi",
-			"tunicOfTheCyclopsKing"
-		]
-	},
-	"dragonheart":
-	{
-		"index" : 159,
-		"type" : ["HERO"]
-	},
-	"gateKey":
-	{
-		"index" : 160,
-		"type" : ["HERO"]
-	},
-	"art161":
-	{
-		"index" : 161,
-		"type" : ["HERO"]
-	},
-	"art162":
-	{
-		"index" : 162,
-		"type" : ["HERO"]
-	},
-	"art163":
-	{
-		"index" : 163,
-		"type" : ["HERO"]
-	},
-	"art164":
-	{
-		"index" : 164,
-		"type" : ["HERO"]
-	},
-	"art165":
-	{
-		"index" : 165,
-		"type" : ["HERO"]
-	},
-	"art166":
-	{
-		"index" : 166,
-		"type" : ["HERO"]
-	},
-	"art167":
-	{
-		"index" : 167,
-		"type" : ["HERO"]
-	},
-	"art168":
-	{
-		"index" : 168,
-		"type" : ["HERO"]
-	},
-	"art169":
-	{
-		"index" : 169,
-		"type" : ["HERO"]
-	},
-	"art170":
-	{
-		"index" : 170,
-		"type" : ["HERO"]
 	}
 	}
 }
 }

+ 1 - 1
lib/CCreatureHandler.cpp

@@ -482,7 +482,7 @@ void CCreatureHandler::loadAnimationInfo(std::vector<JsonNode> &h3Data)
 	parser.endLine(); // header
 	parser.endLine(); // header
 	parser.endLine();
 	parser.endLine();
 
 
-	for(int dd=0; dd<GameConstants::CREATURES_COUNT; ++dd)
+	for(int dd=0; dd<VLC->modh->settings.data["textData"]["creature"].Float(); ++dd)
 	{
 	{
 		while (parser.isNextEntryEmpty() && parser.endLine()) // skip empty lines
 		while (parser.isNextEntryEmpty() && parser.endLine()) // skip empty lines
 			;
 			;

+ 3 - 0
lib/CGeneralTextHandler.cpp

@@ -4,6 +4,8 @@
 #include "filesystem/CResourceLoader.h"
 #include "filesystem/CResourceLoader.h"
 #include "filesystem/CInputStream.h"
 #include "filesystem/CInputStream.h"
 #include "GameConstants.h"
 #include "GameConstants.h"
+#include "CModHandler.h"
+#include "VCMI_Lib.h"
 
 
 // #include <locale> //needed?
 // #include <locale> //needed?
 
 
@@ -307,6 +309,7 @@ CGeneralTextHandler::CGeneralTextHandler()
 			while (parser.endLine() && !text.empty());
 			while (parser.endLine() && !text.empty());
 		}
 		}
 	}
 	}
+	if (VLC->modh->modules.STACK_EXP)
 	{
 	{
 		CLegacyConfigParser parser("DATA/ZCREXP.TXT");
 		CLegacyConfigParser parser("DATA/ZCREXP.TXT");
 		parser.endLine();//header
 		parser.endLine();//header

+ 1 - 1
lib/CHeroHandler.cpp

@@ -123,7 +123,7 @@ CHeroClass *CHeroClassHandler::loadFromJson(const JsonNode & node)
 
 
 std::vector<JsonNode> CHeroClassHandler::loadLegacyData(size_t dataSize)
 std::vector<JsonNode> CHeroClassHandler::loadLegacyData(size_t dataSize)
 {
 {
-	heroClasses.resize(GameConstants::F_NUMBER * 2);
+	heroClasses.resize(dataSize);
 	std::vector<JsonNode> h3Data;
 	std::vector<JsonNode> h3Data;
 	h3Data.reserve(dataSize);
 	h3Data.reserve(dataSize);
 
 

+ 15 - 11
lib/CModHandler.cpp

@@ -182,10 +182,10 @@ void CIdentifierStorage::finalize()
 	assert(errorsFound == false);
 	assert(errorsFound == false);
 }
 }
 
 
-CContentHandler::ContentTypeHandler::ContentTypeHandler(IHandlerBase * handler, size_t size, std::string objectName):
+CContentHandler::ContentTypeHandler::ContentTypeHandler(IHandlerBase * handler, std::string objectName):
     handler(handler),
     handler(handler),
     objectName(objectName),
     objectName(objectName),
-    originalData(handler->loadLegacyData(size))
+    originalData(handler->loadLegacyData(VLC->modh->settings.data["textData"][objectName].Float()))
 {
 {
 	BOOST_FOREACH(auto & node, originalData)
 	BOOST_FOREACH(auto & node, originalData)
 	{
 	{
@@ -262,11 +262,11 @@ void CContentHandler::ContentTypeHandler::loadMod(std::string modName)
 
 
 CContentHandler::CContentHandler()
 CContentHandler::CContentHandler()
 {
 {
-	handlers.insert(std::make_pair("heroClasses", ContentTypeHandler(&VLC->heroh->classes, GameConstants::F_NUMBER * 2, "heroClass")));
-	handlers.insert(std::make_pair("artifacts", ContentTypeHandler(VLC->arth, GameConstants::ARTIFACTS_QUANTITY, "artifact")));
-	handlers.insert(std::make_pair("creatures", ContentTypeHandler(VLC->creh, GameConstants::CREATURES_COUNT, "creature")));
-	handlers.insert(std::make_pair("factions", ContentTypeHandler(VLC->townh, GameConstants::F_NUMBER, "faction")));
-	handlers.insert(std::make_pair("heroes", ContentTypeHandler(VLC->heroh, GameConstants::HEROES_QUANTITY, "hero")));
+	handlers.insert(std::make_pair("heroClasses", ContentTypeHandler(&VLC->heroh->classes, "heroClass")));
+	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("heroes", ContentTypeHandler(VLC->heroh, "hero")));
 
 
 	//TODO: spells, bonuses, something else?
 	//TODO: spells, bonuses, something else?
 }
 }
@@ -297,13 +297,12 @@ CModHandler::CModHandler()
 	for(int i=0; i<GameConstants::PRIMARY_SKILLS; ++i)
 	for(int i=0; i<GameConstants::PRIMARY_SKILLS; ++i)
 		identifiers.registerObject("core", "primSkill", PrimarySkill::names[i], i);
 		identifiers.registerObject("core", "primSkill", PrimarySkill::names[i], i);
 
 
-	loadConfigFromFile ("defaultMods");
 }
 }
 
 
 void CModHandler::loadConfigFromFile (std::string name)
 void CModHandler::loadConfigFromFile (std::string name)
 {
 {
-	const JsonNode config(ResourceID("config/" + name + ".json"));
-	const JsonNode & hardcodedFeatures = config["hardcodedFeatures"];
+	settings.data = JsonUtils::assembleFromFiles("config/" + name);
+	const JsonNode & hardcodedFeatures = settings.data["hardcodedFeatures"];
 
 
 	settings.CREEP_SIZE = hardcodedFeatures["CREEP_SIZE"].Float();
 	settings.CREEP_SIZE = hardcodedFeatures["CREEP_SIZE"].Float();
 	settings.WEEKLY_GROWTH = hardcodedFeatures["WEEKLY_GROWTH_PERCENT"].Float();
 	settings.WEEKLY_GROWTH = hardcodedFeatures["WEEKLY_GROWTH_PERCENT"].Float();
@@ -312,11 +311,14 @@ void CModHandler::loadConfigFromFile (std::string name)
 	settings.DWELLINGS_ACCUMULATE_CREATURES = hardcodedFeatures["DWELLINGS_ACCUMULATE_CREATURES"].Bool();
 	settings.DWELLINGS_ACCUMULATE_CREATURES = hardcodedFeatures["DWELLINGS_ACCUMULATE_CREATURES"].Bool();
 	settings.ALL_CREATURES_GET_DOUBLE_MONTHS = hardcodedFeatures["ALL_CREATURES_GET_DOUBLE_MONTHS"].Bool();
 	settings.ALL_CREATURES_GET_DOUBLE_MONTHS = hardcodedFeatures["ALL_CREATURES_GET_DOUBLE_MONTHS"].Bool();
 
 
-	const JsonNode & gameModules = config["modules"];
+	const JsonNode & gameModules = settings.data["modules"];
 	modules.STACK_EXP = gameModules["STACK_EXPERIENCE"].Bool();
 	modules.STACK_EXP = gameModules["STACK_EXPERIENCE"].Bool();
 	modules.STACK_ARTIFACT = gameModules["STACK_ARTIFACTS"].Bool();
 	modules.STACK_ARTIFACT = gameModules["STACK_ARTIFACTS"].Bool();
 	modules.COMMANDERS = gameModules["COMMANDERS"].Bool();
 	modules.COMMANDERS = gameModules["COMMANDERS"].Bool();
 	modules.MITHRIL = gameModules["MITHRIL"].Bool();
 	modules.MITHRIL = gameModules["MITHRIL"].Bool();
+
+	logGlobal->errorStream() << "Selected configuration: ";
+	logGlobal->errorStream() << settings.data;
 }
 }
 
 
 // currentList is passed by value to get current list of depending mods
 // currentList is passed by value to get current list of depending mods
@@ -514,6 +516,8 @@ void CModHandler::handleData(Handler handler, const JsonNode & source, std::stri
 
 
 void CModHandler::loadGameContent()
 void CModHandler::loadGameContent()
 {
 {
+	loadConfigFromFile("defaultMods.json");
+
 	CStopWatch timer, totalTime;
 	CStopWatch timer, totalTime;
 
 
 	CContentHandler content;
 	CContentHandler content;

+ 4 - 2
lib/CModHandler.h

@@ -88,7 +88,7 @@ class CContentHandler
 		std::map<std::string, ModInfo> modData;
 		std::map<std::string, ModInfo> modData;
 
 
 	public:
 	public:
-		ContentTypeHandler(IHandlerBase * handler, size_t size, std::string objectName);
+		ContentTypeHandler(IHandlerBase * handler, std::string objectName);
 
 
 		/// local version of methods in ContentHandler
 		/// local version of methods in ContentHandler
 		void preloadModData(std::string modName, std::vector<std::string> fileList);
 		void preloadModData(std::string modName, std::vector<std::string> fileList);
@@ -177,6 +177,8 @@ public:
 
 
 	struct DLL_LINKAGE hardcodedFeatures
 	struct DLL_LINKAGE hardcodedFeatures
 	{
 	{
+		JsonNode data;
+
 		int CREEP_SIZE; // neutral stacks won't grow beyond this number
 		int CREEP_SIZE; // neutral stacks won't grow beyond this number
 		int WEEKLY_GROWTH; //percent
 		int WEEKLY_GROWTH; //percent
 		int NEUTRAL_STACK_EXP; 
 		int NEUTRAL_STACK_EXP; 
@@ -186,7 +188,7 @@ public:
 
 
 		template <typename Handler> void serialize(Handler &h, const int version)
 		template <typename Handler> void serialize(Handler &h, const int version)
 		{
 		{
-			h & CREEP_SIZE & WEEKLY_GROWTH & NEUTRAL_STACK_EXP;
+			h & data & CREEP_SIZE & WEEKLY_GROWTH & NEUTRAL_STACK_EXP;
 			h & DWELLINGS_ACCUMULATE_CREATURES & ALL_CREATURES_GET_DOUBLE_MONTHS;
 			h & DWELLINGS_ACCUMULATE_CREATURES & ALL_CREATURES_GET_DOUBLE_MONTHS;
 		}
 		}
 	} settings;
 	} settings;

+ 24 - 0
lib/JsonNode.cpp

@@ -15,6 +15,7 @@
 
 
 #include "HeroBonus.h"
 #include "HeroBonus.h"
 #include "filesystem/CResourceLoader.h"
 #include "filesystem/CResourceLoader.h"
+#include "filesystem/ISimpleResourceLoader.h"
 #include "VCMI_Lib.h" //for identifier resolution
 #include "VCMI_Lib.h" //for identifier resolution
 #include "CModHandler.h"
 #include "CModHandler.h"
 
 
@@ -387,6 +388,8 @@ void JsonWriter::writeNode(const JsonNode &node)
 			writeContainer(node.Struct().begin(), node.Struct().end());
 			writeContainer(node.Struct().begin(), node.Struct().end());
 			out << prefix << "}";
 			out << prefix << "}";
 	}
 	}
+	if (!node.meta.empty()) // write metainf as comment
+		out << " //" << node.meta;
 }
 }
 
 
 JsonWriter::JsonWriter(std::ostream &output, const JsonNode &node):
 JsonWriter::JsonWriter(std::ostream &output, const JsonNode &node):
@@ -1603,3 +1606,24 @@ JsonNode JsonUtils::assembleFromFiles(std::vector<std::string> files)
 	}
 	}
 	return result;
 	return result;
 }
 }
+
+JsonNode JsonUtils::assembleFromFiles(std::string filename)
+{
+	JsonNode result;
+
+	auto & configList = CResourceHandler::get()->getResourcesWithName(ResourceID(filename, EResType::TEXT));
+
+	BOOST_FOREACH(auto & entry, configList)
+	{
+		// FIXME: some way to make this code more readable
+		auto stream = entry.getLoader()->load(entry.getResourceName());
+		std::unique_ptr<ui8[]> textData(new ui8[stream->getSize()]);
+		stream->read(textData.get(), stream->getSize());
+
+		JsonNode section((char*)textData.get(), stream->getSize());
+		//for debug
+		//section.setMeta(entry.getLoader()->getOrigin());
+		merge(result, section);
+	}
+	return result;
+}

+ 3 - 0
lib/JsonNode.h

@@ -165,6 +165,9 @@ namespace JsonUtils
 	 */
 	 */
 	DLL_LINKAGE JsonNode assembleFromFiles(std::vector<std::string> files);
 	DLL_LINKAGE JsonNode assembleFromFiles(std::vector<std::string> files);
 
 
+	/// This version loads all files with same name (overriden by mods)
+	DLL_LINKAGE JsonNode assembleFromFiles(std::string filename);
+
 	/**
 	/**
 	 * @brief removes all nodes that are identical to default entry in schema
 	 * @brief removes all nodes that are identical to default entry in schema
 	 * @param node - JsonNode to minimize
 	 * @param node - JsonNode to minimize