Переглянути джерело

Checking flags and conditions

Tomasz Zieliński 2 роки тому
батько
коміт
700d8459ac

+ 3 - 0
lib/CHeroHandler.cpp

@@ -424,6 +424,9 @@ CHero * CHeroHandler::loadFromJson(const std::string & scope, const JsonNode & n
 	hero->modScope = scope;
 	hero->gender = node["female"].Bool() ? EHeroGender::FEMALE : EHeroGender::MALE;
 	hero->special = node["special"].Bool();
+	//Default - both false
+	hero->onlyOnWaterMap = node["onlyOnWaterMap"].Bool();
+	hero->onlyOnMapWithoutWater = node["onlyOnMapWithoutWater"].Bool();
 
 	VLC->generaltexth->registerString(scope, hero->getNameTextID(), node["texts"]["name"].String());
 	VLC->generaltexth->registerString(scope, hero->getBiographyTextID(), node["texts"]["biography"].String());

+ 4 - 0
lib/CHeroHandler.h

@@ -69,6 +69,8 @@ public:
 	std::set<SpellID> spells;
 	bool haveSpellBook = false;
 	bool special = false; // hero is special and won't be placed in game (unless preset on map), e.g. campaign heroes
+	bool onlyOnWaterMap; // hero will be placed only if the map contains water
+	bool onlyOnMapWithoutWater; // hero will be placed only if the map does not contain water
 	EHeroGender gender = EHeroGender::MALE; // default sex: 0=male, 1=female
 
 	/// Graphics
@@ -114,6 +116,8 @@ public:
 		h & haveSpellBook;
 		h & gender;
 		h & special;
+		h & onlyOnWaterMap;
+		h & onlyOnMapWithoutWater;
 		h & iconSpecSmall;
 		h & iconSpecLarge;
 		h & portraitSmall;

+ 26 - 0
lib/mapping/CMap.cpp

@@ -554,6 +554,32 @@ void CMap::removeObject(CGObjectInstance * obj)
 	//TOOD: Clean artifact instances (mostly worn by hero?) and quests related to this object
 }
 
+bool CMap::isWaterMap() const
+{
+	return waterMap;
+}
+
+bool CMap::calculateWaterContent()
+{
+	size_t totalTiles = height * width * levels();
+	size_t waterTiles = 0;
+
+	for(auto tile = terrain.origin(); tile < (terrain.origin() + terrain.num_elements()); ++tile) 
+	{
+		if (tile->isWater())
+		{
+			waterTiles++;
+		}
+	}
+
+	if (waterTiles >= totalTiles / 100) //At least 1% of area is water
+	{
+		waterMap = true;
+	}
+
+	return waterMap;
+}
+
 void CMap::initTerrain()
 {
 	terrain.resize(boost::extents[levels()][width][height]);

+ 4 - 0
lib/mapping/CMap.h

@@ -106,6 +106,8 @@ public:
 	void moveObject(CGObjectInstance * obj, const int3 & dst);
 	void removeObject(CGObjectInstance * obj);
 
+	bool isWaterMap() const;
+	bool calculateWaterContent();
 
 	/// Gets object of specified type on requested position
 	const CGObjectInstance * getObjectiveObjectFrom(const int3 & pos, Obj::EObj type);
@@ -146,6 +148,8 @@ public:
 
 	std::map<std::string, ConstTransitivePtr<CGObjectInstance> > instanceNames;
 
+	bool waterMap;
+
 private:
 	/// a 3-dimensional array of terrain tiles, access is as follows: x, y, level. where level=1 is underground
 	boost::multi_array<TerrainTile, 3> terrain;

+ 1 - 0
lib/mapping/MapFormatH3M.cpp

@@ -969,6 +969,7 @@ void CMapLoaderH3M::readTerrain()
 			}
 		}
 	}
+	map->calculateWaterContent();
 }
 
 void CMapLoaderH3M::readObjectTemplates()

+ 1 - 0
lib/mapping/MapFormatJson.cpp

@@ -1115,6 +1115,7 @@ void CMapLoaderJson::readTerrain()
 		readTerrainLevel(underground, 1);
 	}
 
+	map->calculateWaterContent();
 }
 
 CMapLoaderJson::MapObjectLoader::MapObjectLoader(CMapLoaderJson * _owner, JsonMap::value_type & json):

+ 14 - 1
lib/rmg/CMapGenerator.cpp

@@ -18,6 +18,7 @@
 #include "../mapObjectConstructors/CObjectClassesHandler.h"
 #include "../mapping/CMapEditManager.h"
 #include "../CTownHandler.h"
+#include "../CHeroHandler.h"
 #include "../StringConstants.h"
 #include "../filesystem/Filesystem.h"
 #include "CZonePlacer.h"
@@ -411,6 +412,7 @@ void CMapGenerator::addHeaderInfo()
 	m.description = getMapDescription();
 	m.difficulty = 1;
 	addPlayerInfo();
+	m.waterMap = (mapGenOptions.getWaterContent() != EWaterContent::EWaterContent::NONE);
 }
 
 int CMapGenerator::getNextMonlithIndex()
@@ -452,12 +454,23 @@ const std::vector<ArtifactID> & CMapGenerator::getAllPossibleQuestArtifacts() co
 
 const std::vector<HeroTypeID> CMapGenerator::getAllPossibleHeroes() const
 {
+	auto isWaterMap = map->getMap(this).isWaterMap();
 	//Skip heroes that were banned, including the ones placed in prisons
 	std::vector<HeroTypeID> ret;
 	for (int j = 0; j < map->getMap(this).allowedHeroes.size(); j++)
 	{
 		if (map->getMap(this).allowedHeroes[j])
-			ret.push_back(HeroTypeID(j));
+		{
+			auto * h = dynamic_cast<const CHero*>(VLC->heroTypes()->getByIndex(j));
+			if ((h->onlyOnWaterMap && !isWaterMap) || (h->onlyOnMapWithoutWater && isWaterMap))
+			{
+				continue;
+			}
+			else
+			{
+				ret.push_back(HeroTypeID(j));
+			}
+		}
 	}
 	return ret;
 }