Browse Source

Merge pull request #175 from vmarkovtsev/feature/switch_retreat_no_troops

Feature/switch retreat no troops
ArseniyShestakov 9 years ago
parent
commit
3c84400262

+ 2 - 1
config/defaultMods.json

@@ -23,7 +23,8 @@
 		"ALL_CREATURES_GET_DOUBLE_MONTHS" : false,
 		"NEGATIVE_LUCK" : false,
 		"MAX_HEROES_AVAILABLE_PER_PLAYER" : 16,
-		"MAX_HEROES_ON_MAP_PER_PLAYER" : 8	
+		"MAX_HEROES_ON_MAP_PER_PLAYER" : 8,
+		"WINNING_HERO_WITH_NO_TROOPS_RETREATS": true
 
 	},
 	"modules":

+ 27 - 6
lib/CModHandler.cpp

@@ -101,9 +101,9 @@ void CIdentifierStorage::requestIdentifier(std::string scope, std::string type,
 
 void CIdentifierStorage::requestIdentifier(std::string scope, std::string fullName, const std::function<void(si32)>& callback)
 {
-	auto scopeAndFullName = splitString(fullName, ':');	
-	auto typeAndName = splitString(scopeAndFullName.second, '.');	
-	
+	auto scopeAndFullName = splitString(fullName, ':');
+	auto typeAndName = splitString(scopeAndFullName.second, '.');
+
 	requestIdentifier(ObjectCallback(scope, scopeAndFullName.first, typeAndName.first, typeAndName.second, callback, false));
 }
 
@@ -331,11 +331,11 @@ bool CContentHandler::ContentTypeHandler::loadMod(std::string modName, bool vali
 {
 	ModInfo & modInfo = modData[modName];
 	bool result = true;
-	
+
 	auto performValidate = [&,this](JsonNode & data, const std::string & name){
 		handler->beforeValidate(data);
 		if (validate)
-			result &= JsonUtils::validate(data, "vcmi:" + objectName, name);	
+			result &= JsonUtils::validate(data, "vcmi:" + objectName, name);
 	};
 
 	// apply patches
@@ -355,7 +355,7 @@ bool CContentHandler::ContentTypeHandler::loadMod(std::string modName, bool vali
 			if (originalData.size() > index)
 			{
 				JsonUtils::merge(originalData[index], data);
-				
+
 				performValidate(originalData[index],name);
 				handler->loadObject(modName, name, originalData[index], index);
 
@@ -550,21 +550,42 @@ CModHandler::CModHandler()
 
 void CModHandler::loadConfigFromFile (std::string name)
 {
+	std::string paths;
+	for(auto& p : CResourceHandler::get()->getResourceNames(ResourceID("config/" + name)))
+	{
+		paths += p + ", ";
+	}
+	paths = paths.substr(0, paths.size() - 2);
+	logGlobal->debugStream() << "Loading hardcoded features settings from [" << paths << "], result:";
 	settings.data = JsonUtils::assembleFromFiles("config/" + name);
 	const JsonNode & hardcodedFeatures = settings.data["hardcodedFeatures"];
 	settings.MAX_HEROES_AVAILABLE_PER_PLAYER = hardcodedFeatures["MAX_HEROES_AVAILABLE_PER_PLAYER"].Float();
+	logGlobal->debugStream() << "\tMAX_HEROES_AVAILABLE_PER_PLAYER\t" << settings.MAX_HEROES_AVAILABLE_PER_PLAYER;
 	settings.MAX_HEROES_ON_MAP_PER_PLAYER = hardcodedFeatures["MAX_HEROES_ON_MAP_PER_PLAYER"].Float();
+	logGlobal->debugStream() << "\tMAX_HEROES_ON_MAP_PER_PLAYER\t" << settings.MAX_HEROES_ON_MAP_PER_PLAYER;
 	settings.CREEP_SIZE = hardcodedFeatures["CREEP_SIZE"].Float();
+	logGlobal->debugStream() << "\tCREEP_SIZE\t" << settings.CREEP_SIZE;
 	settings.WEEKLY_GROWTH = hardcodedFeatures["WEEKLY_GROWTH_PERCENT"].Float();
+	logGlobal->debugStream() << "\tWEEKLY_GROWTH\t" << settings.WEEKLY_GROWTH;
 	settings.NEUTRAL_STACK_EXP = hardcodedFeatures["NEUTRAL_STACK_EXP_DAILY"].Float();
+	logGlobal->debugStream() << "\tNEUTRAL_STACK_EXP\t" << settings.NEUTRAL_STACK_EXP;
 	settings.MAX_BUILDING_PER_TURN = hardcodedFeatures["MAX_BUILDING_PER_TURN"].Float();
+	logGlobal->debugStream() << "\tMAX_BUILDING_PER_TURN\t" << settings.MAX_BUILDING_PER_TURN;
 	settings.DWELLINGS_ACCUMULATE_CREATURES = hardcodedFeatures["DWELLINGS_ACCUMULATE_CREATURES"].Bool();
+	logGlobal->debugStream() << "\tDWELLINGS_ACCUMULATE_CREATURES\t" << settings.DWELLINGS_ACCUMULATE_CREATURES;
 	settings.ALL_CREATURES_GET_DOUBLE_MONTHS = hardcodedFeatures["ALL_CREATURES_GET_DOUBLE_MONTHS"].Bool();
+	logGlobal->debugStream() << "\tALL_CREATURES_GET_DOUBLE_MONTHS\t" << settings.ALL_CREATURES_GET_DOUBLE_MONTHS;
+	settings.WINNING_HERO_WITH_NO_TROOPS_RETREATS = hardcodedFeatures["WINNING_HERO_WITH_NO_TROOPS_RETREATS"].Bool();
+	logGlobal->debugStream() << "\tWINNING_HERO_WITH_NO_TROOPS_RETREATS\t" << settings.WINNING_HERO_WITH_NO_TROOPS_RETREATS;
 	const JsonNode & gameModules = settings.data["modules"];
 	modules.STACK_EXP = gameModules["STACK_EXPERIENCE"].Bool();
+  logGlobal->debugStream() << "\tSTACK_EXP\t" << modules.STACK_EXP;
 	modules.STACK_ARTIFACT = gameModules["STACK_ARTIFACTS"].Bool();
+	logGlobal->debugStream() << "\tSTACK_ARTIFACT\t" << modules.STACK_ARTIFACT;
 	modules.COMMANDERS = gameModules["COMMANDERS"].Bool();
+	logGlobal->debugStream() << "\tCOMMANDERS\t" << modules.COMMANDERS;
 	modules.MITHRIL = gameModules["MITHRIL"].Bool();
+	logGlobal->debugStream() << "\tMITHRIL\t" << modules.MITHRIL;
 }
 
 // currentList is passed by value to get current list of depending mods

+ 13 - 3
lib/CModHandler.h

@@ -73,7 +73,7 @@ public:
 	/// Function callback will be called during ID resolution phase of loading
 	void requestIdentifier(std::string scope, std::string type, std::string name, const std::function<void(si32)> & callback);
 	///fullName = [remoteScope:]type.name
-	void requestIdentifier(std::string scope, std::string fullName, const std::function<void(si32)> & callback);	
+	void requestIdentifier(std::string scope, std::string fullName, const std::function<void(si32)> & callback);
 	void requestIdentifier(std::string type, const JsonNode & name, const std::function<void(si32)> & callback);
 	void requestIdentifier(const JsonNode & name, const std::function<void(si32)> & callback);
 
@@ -253,17 +253,27 @@ public:
 
 		int CREEP_SIZE; // neutral stacks won't grow beyond this number
 		int WEEKLY_GROWTH; //percent
-		int NEUTRAL_STACK_EXP; 
+		int NEUTRAL_STACK_EXP;
 		int MAX_BUILDING_PER_TURN;
 		bool DWELLINGS_ACCUMULATE_CREATURES;
 		bool ALL_CREATURES_GET_DOUBLE_MONTHS;
 		int MAX_HEROES_AVAILABLE_PER_PLAYER;
 		int MAX_HEROES_ON_MAP_PER_PLAYER;
+		bool WINNING_HERO_WITH_NO_TROOPS_RETREATS;
 
 		template <typename Handler> void serialize(Handler &h, const int version)
 		{
 			h & data & CREEP_SIZE & WEEKLY_GROWTH & NEUTRAL_STACK_EXP & MAX_BUILDING_PER_TURN;
-			h & DWELLINGS_ACCUMULATE_CREATURES & ALL_CREATURES_GET_DOUBLE_MONTHS & MAX_HEROES_AVAILABLE_PER_PLAYER & MAX_HEROES_ON_MAP_PER_PLAYER;
+			h & DWELLINGS_ACCUMULATE_CREATURES & ALL_CREATURES_GET_DOUBLE_MONTHS &
+			MAX_HEROES_AVAILABLE_PER_PLAYER & MAX_HEROES_ON_MAP_PER_PLAYER;
+			if(version >= 756)
+			{
+				h & WINNING_HERO_WITH_NO_TROOPS_RETREATS;
+			}
+			else if(!h.saving)
+			{
+				WINNING_HERO_WITH_NO_TROOPS_RETREATS = true;
+			}
 		}
 	} settings;
 

+ 1 - 1
lib/Connection.h

@@ -27,7 +27,7 @@
 #include "mapping/CCampaignHandler.h" //for CCampaignState
 #include "rmg/CMapGenerator.h" // for CMapGenOptions
 
-const ui32 version = 755;
+const ui32 version = 756;
 const ui32 minSupportedVersion = 753;
 
 class CISer;

+ 11 - 2
lib/JsonNode.cpp

@@ -56,6 +56,15 @@ JsonNode::JsonNode(ResourceID && fileURI):
 	*this = parser.parse(fileURI.getName());
 }
 
+JsonNode::JsonNode(const ResourceID & fileURI):
+	type(DATA_NULL)
+{
+	auto file = CResourceHandler::get()->load(fileURI)->readAll();
+
+	JsonParser parser(reinterpret_cast<char*>(file.first.get()), file.second);
+	*this = parser.parse(fileURI.getName());
+}
+
 JsonNode::JsonNode(ResourceID && fileURI, bool &isValidSyntax):
 	type(DATA_NULL)
 {
@@ -328,7 +337,7 @@ void JsonUtils::parseTypedBonusShort(const JsonVector& source, Bonus *dest)
 	resolveIdentifier(source[2],dest->subtype);
 	dest->additionalInfo = source[3].Float();
 	dest->duration = Bonus::PERMANENT; //TODO: handle flags (as integer)
-	dest->turnsRemain = 0;	
+	dest->turnsRemain = 0;
 }
 
 
@@ -343,7 +352,7 @@ Bonus * JsonUtils::parseBonus (const JsonVector &ability_vec) //TODO: merge with
 		return b;
 	}
 	b->type = it->second;
-	
+
 	parseTypedBonusShort(ability_vec, b);
 	return b;
 }

+ 10 - 9
lib/JsonNode.h

@@ -7,7 +7,7 @@
  * Full text of license available in license.txt file, in main folder
  *
  */
- 
+
 #pragma once
 
 class JsonNode;
@@ -55,6 +55,7 @@ public:
 	explicit JsonNode(const char * data, size_t datasize);
 	//Create tree from JSON file
  	explicit JsonNode(ResourceID && fileURI);
+ 	explicit JsonNode(const ResourceID & fileURI);
 	explicit JsonNode(ResourceID && fileURI, bool & isValidSyntax);
 	//Copy c-tor
 	JsonNode(const JsonNode &copy);
@@ -125,9 +126,9 @@ namespace JsonUtils
 	/**
 	 * @brief parse short bonus format, excluding type
 	 * @note sets duration to Permament
-	 */	
+	 */
 	DLL_LINKAGE void parseTypedBonusShort(const JsonVector &source, Bonus *dest);
-	
+
 	///
 	DLL_LINKAGE Bonus * parseBonus (const JsonVector &ability_vec);
 	DLL_LINKAGE Bonus * parseBonus (const JsonNode &bonus);
@@ -144,7 +145,7 @@ namespace JsonUtils
 	 * @note this function will destroy data in source
 	 */
 	DLL_LINKAGE void merge(JsonNode & dest, JsonNode & source);
-	
+
 	/**
 	 * @brief recursively merges source into dest, replacing identical fields
 	 * struct : recursively calls this function
@@ -152,12 +153,12 @@ namespace JsonUtils
 	 * values : value in source will replace value in dest
 	 * null   : if value in source is present but set to null it will delete entry in dest
 	 * @note this function will preserve data stored in source by creating copy
-	 */ 
+	 */
 	DLL_LINKAGE void mergeCopy(JsonNode & dest, JsonNode source);
-	
+
     /** @brief recursively merges descendant into copy of base node
      * Result emulates inheritance semantic
-     * 
+     *
      *
      */
 	DLL_LINKAGE void inherit(JsonNode & descendant, const JsonNode & base);
@@ -200,7 +201,7 @@ namespace JsonDetail
 {
 	// conversion helpers for JsonNode::convertTo (partial template function instantiation is illegal in c++)
 
-	template <typename T, int arithm> 
+	template <typename T, int arithm>
 	struct JsonConvImpl;
 
 	template <typename T>
@@ -229,7 +230,7 @@ namespace JsonDetail
 			///this should be triggered only for numeric types and enums
 			static_assert(boost::mpl::or_<std::is_arithmetic<Type>, std::is_enum<Type>, boost::is_class<Type> >::value, "Unsupported type for JsonNode::convertTo()!");
 			return JsonConvImpl<Type, boost::mpl::or_<std::is_enum<Type>, boost::is_class<Type> >::value >::convertImpl(node);
-				
+
 		}
 	};
 

+ 14 - 0
lib/filesystem/AdapterLoaders.cpp

@@ -87,6 +87,20 @@ boost::optional<std::string> CFilesystemList::getResourceName(const ResourceID &
 	return boost::optional<std::string>();
 }
 
+std::set<std::string> CFilesystemList::getResourceNames(const ResourceID & resourceName) const
+{
+	std::set<std::string> paths;
+	for(auto& loader : getResourcesWithName(resourceName))
+	{
+		auto rn = loader->getResourceName(resourceName);
+		if(rn)
+		{
+			paths.insert(*rn);
+		}
+	}
+	return std::move(paths);
+}
+
 std::unordered_set<ResourceID> CFilesystemList::getFilteredFiles(std::function<bool(const ResourceID &)> filter) const
 {
 	std::unordered_set<ResourceID> ret;

+ 4 - 10
lib/filesystem/AdapterLoaders.h

@@ -59,16 +59,9 @@ class DLL_LINKAGE CFilesystemList : public ISimpleResourceLoader
 	std::set<ISimpleResourceLoader *> writeableLoaders;
 
 	//FIXME: this is only compile fix, should be removed in the end
-	CFilesystemList(CFilesystemList &) 
-    { 
-		//class is not copyable 
-    } 
-    CFilesystemList &operator=(CFilesystemList &) 
-    { 
-        //class is not copyable 
-        return *this; 
-    }
-
+	CFilesystemList(CFilesystemList &) = delete;
+	CFilesystemList &operator=(CFilesystemList &) = delete;
+
 public:
 	CFilesystemList();
 	~CFilesystemList();
@@ -78,6 +71,7 @@ public:
 	bool existsResource(const ResourceID & resourceName) const override;
 	std::string getMountPoint() const override;
 	boost::optional<std::string> getResourceName(const ResourceID & resourceName) const override;
+	std::set<std::string> getResourceNames(const ResourceID & resourceName) const override;
 	std::unordered_set<ResourceID> getFilteredFiles(std::function<bool(const ResourceID &)> filter) const override;
 	bool createResource(std::string filename, bool update = false) override;
 	std::vector<const ISimpleResourceLoader *> getResourcesWithName(const ResourceID & resourceName) const override;

+ 16 - 0
lib/filesystem/ISimpleResourceLoader.h

@@ -53,6 +53,22 @@ public:
 		return boost::optional<std::string>();
 	}
 
+	/**
+	 * Gets all full names of matching resources, e.g. names of files in filesystem.
+	 *
+	 * @return std::set with names.
+	 */
+	virtual std::set<std::string> getResourceNames(const ResourceID & resourceName) const
+	{
+		std::set<std::string> result;
+		auto rn = getResourceName(resourceName);
+		if(rn)
+		{
+			result.insert(*rn);
+		}
+		return result;
+	}
+
 	/**
 	 * Get list of files that matches filter function
 	 *

+ 13 - 10
server/CGameHandler.cpp

@@ -757,18 +757,21 @@ void CGameHandler::battleAfterLevelUp( const BattleResult &result )
 		RemoveObject ro(finishingBattle->winnerHero->id);
 		sendAndApply(&ro);
 
-		SetAvailableHeroes sah;
-		sah.player = finishingBattle->victor;
-		sah.hid[0] = finishingBattle->winnerHero->subID;
-		sah.army[0].clear();
-		sah.army[0].setCreature(SlotID(0), finishingBattle->winnerHero->type->initialArmy.at(0).creature, 1);
+		if (VLC->modh->settings.WINNING_HERO_WITH_NO_TROOPS_RETREATS)
+		{
+			SetAvailableHeroes sah;
+			sah.player = finishingBattle->victor;
+			sah.hid[0] = finishingBattle->winnerHero->subID;
+			sah.army[0].clear();
+			sah.army[0].setCreature(SlotID(0), finishingBattle->winnerHero->type->initialArmy.at(0).creature, 1);
 
-		if(const CGHeroInstance *another =  getPlayer(finishingBattle->victor)->availableHeroes.at(0))
-			sah.hid[1] = another->subID;
-		else
-			sah.hid[1] = -1;
+			if(const CGHeroInstance *another =  getPlayer(finishingBattle->victor)->availableHeroes.at(0))
+				sah.hid[1] = another->subID;
+			else
+				sah.hid[1] = -1;
 
-		sendAndApply(&sah);
+			sendAndApply(&sah);
+		}
 	}
 }