mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	Rmg water support (#745)
* RMG: water support and refactoring * Fix seers hut bug
This commit is contained in:
		
				
					committed by
					
						 Andrii Danylchenko
						Andrii Danylchenko
					
				
			
			
				
	
			
			
			
						parent
						
							b698f32557
						
					
				
				
					commit
					5c1a66ab69
				
			| @@ -86,7 +86,6 @@ set(lib_SRCS | ||||
| 		rmg/CRmgTemplate.cpp | ||||
| 		rmg/CRmgTemplateStorage.cpp | ||||
| 		rmg/CRmgTemplateZone.cpp | ||||
| 		rmg/CZoneGraphGenerator.cpp | ||||
| 		rmg/CZonePlacer.cpp | ||||
|  | ||||
| 		serializer/BinaryDeserializer.cpp | ||||
| @@ -292,7 +291,6 @@ set(lib_HEADERS | ||||
| 		rmg/CRmgTemplate.h | ||||
| 		rmg/CRmgTemplateStorage.h | ||||
| 		rmg/CRmgTemplateZone.h | ||||
| 		rmg/CZoneGraphGenerator.h | ||||
| 		rmg/CZonePlacer.h | ||||
| 		rmg/float3.h | ||||
|  | ||||
|   | ||||
| @@ -255,6 +255,7 @@ void ObjectTemplate::readJson(const JsonNode &node, const bool withTerrain) | ||||
| 			allowedTerrains.insert(ETerrainType((si32)i)); | ||||
|  | ||||
| 		allowedTerrains.erase(ETerrainType::ROCK); | ||||
| 		allowedTerrains.erase(ETerrainType::WATER); | ||||
| 	} | ||||
|  | ||||
| 	if(withTerrain && allowedTerrains.empty()) | ||||
| @@ -327,8 +328,8 @@ void ObjectTemplate::writeJson(JsonNode & node, const bool withTerrain) const | ||||
|  | ||||
| 	if(withTerrain) | ||||
| 	{ | ||||
| 		//assumed that ROCK terrain not included | ||||
| 		if(allowedTerrains.size() < (GameConstants::TERRAIN_TYPES - 1)) | ||||
| 		//assumed that ROCK and WATER terrains are not included | ||||
| 		if(allowedTerrains.size() < (GameConstants::TERRAIN_TYPES - 2)) | ||||
| 		{ | ||||
| 			JsonVector & data = node["allowedTerrains"].Vector(); | ||||
|  | ||||
|   | ||||
| @@ -14,6 +14,7 @@ | ||||
| #include "../mapping/CMap.h" | ||||
| #include "CRmgTemplateStorage.h" | ||||
| #include "CRmgTemplate.h" | ||||
| #include "CRandomGenerator.h" | ||||
| #include "../VCMI_Lib.h" | ||||
| #include "../CTownHandler.h" | ||||
|  | ||||
| @@ -390,9 +391,39 @@ bool CMapGenOptions::checkOptions() const | ||||
| const CRmgTemplate * CMapGenOptions::getPossibleTemplate(CRandomGenerator & rand) const | ||||
| { | ||||
| 	int3 tplSize(width, height, (hasTwoLevels ? 2 : 1)); | ||||
| 	auto humanPlayers = countHumanPlayers(); | ||||
| 	 | ||||
| 	auto templates = VLC->tplh->getTemplates(); | ||||
| 	 | ||||
| 	vstd::erase_if(templates, [this, &tplSize, humanPlayers](const CRmgTemplate * tmpl) | ||||
| 	{ | ||||
| 		if(!tmpl->matchesSize(tplSize)) | ||||
| 			return true; | ||||
| 		 | ||||
| 		if(!tmpl->isWaterContentAllowed(getWaterContent())) | ||||
| 			return true; | ||||
| 		 | ||||
| 		if(getPlayerCount() != -1) | ||||
| 		{ | ||||
| 			if (!tmpl->getPlayers().isInRange(getPlayerCount())) | ||||
| 				return true; | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			// Human players shouldn't be banned when playing with random player count | ||||
| 			if(humanPlayers > *boost::min_element(tmpl->getPlayers().getNumbers())) | ||||
| 				return true; | ||||
| 		} | ||||
| 		 | ||||
| 		if(compOnlyPlayerCount != -1) | ||||
| 		{ | ||||
| 			if (!tmpl->getCpuPlayers().isInRange(compOnlyPlayerCount)) | ||||
| 				return true; | ||||
| 		} | ||||
| 		 | ||||
| 		return false; | ||||
| 	}); | ||||
| 	 | ||||
| 	auto templates = VLC->tplh->getTemplates(tplSize, getPlayerCount(), countHumanPlayers(), compOnlyPlayerCount); | ||||
|  | ||||
| 	// Select tpl | ||||
| 	if(templates.empty()) | ||||
| 		return nullptr; | ||||
|   | ||||
| @@ -11,9 +11,9 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include "../GameConstants.h" | ||||
| #include "../CRandomGenerator.h" | ||||
|  | ||||
| class CRmgTemplate; | ||||
| class CRandomGenerator; | ||||
|  | ||||
| namespace EWaterContent | ||||
| { | ||||
|   | ||||
| @@ -285,17 +285,41 @@ void CMapGenerator::genZones() | ||||
| 	for(const auto & option : tmpl->getZones()) | ||||
| 	{ | ||||
| 		auto zone = std::make_shared<CRmgTemplateZone>(this); | ||||
| 		zone->setOptions(option.second.get()); | ||||
| 		zone->setOptions(*option.second.get()); | ||||
| 		zones[zone->getId()] = zone; | ||||
| 	} | ||||
|  | ||||
| 	CZonePlacer placer(this); | ||||
| 	placer.placeZones(&rand); | ||||
| 	placer.assignZones(); | ||||
| 	 | ||||
| 	//add special zone for water | ||||
| 	zoneWater.first = zones.size() + 1; | ||||
| 	zoneWater.second = std::make_shared<CRmgTemplateZone>(this); | ||||
| 	{ | ||||
| 		rmg::ZoneOptions options; | ||||
| 		options.setId(zoneWater.first); | ||||
| 		options.setType(ETemplateZoneType::WATER); | ||||
| 		zoneWater.second->setOptions(options); | ||||
| 	} | ||||
|  | ||||
| 	logGlobal->info("Zones generated successfully"); | ||||
| } | ||||
|  | ||||
| void CMapGenerator::createWaterTreasures() | ||||
| { | ||||
| 	//add treasures on water | ||||
| 	getZoneWater().second->addTreasureInfo(CTreasureInfo{100, 1000, 5}); | ||||
| 	getZoneWater().second->addTreasureInfo(CTreasureInfo{2000, 6000, 1}); | ||||
| } | ||||
|  | ||||
| void CMapGenerator::prepareWaterTiles() | ||||
| { | ||||
| 	for(auto & t : zoneWater.second->getTileInfo()) | ||||
| 		if(shouldBeBlocked(t)) | ||||
| 			setOccupied(t, ETileType::POSSIBLE); | ||||
| } | ||||
|  | ||||
| void CMapGenerator::fillZones() | ||||
| { | ||||
| 	//init native town count with 0 | ||||
| @@ -308,41 +332,67 @@ void CMapGenerator::fillZones() | ||||
|  | ||||
| 	//we need info about all town types to evaluate dwellings and pandoras with creatures properly | ||||
| 	//place main town in the middle | ||||
| 	for (auto it : zones) | ||||
| 	for(auto it : zones) | ||||
| 		it.second->initTownType(); | ||||
| 	 | ||||
| 	//make sure there are some free tiles in the zone | ||||
| 	for (auto it : zones) | ||||
| 	for(auto it : zones) | ||||
| 		it.second->initFreeTiles(); | ||||
| 	 | ||||
| 	createDirectConnections(); //direct | ||||
| 	 | ||||
| 	//make sure all connections are passable before creating borders | ||||
| 	for (auto it : zones) | ||||
| 	for(auto it : zones) | ||||
| 		it.second->createBorder(); //once direct connections are done | ||||
| 	 | ||||
| #ifdef _BETA | ||||
| 	dump(false); | ||||
| #endif | ||||
| 	 | ||||
| 	for(auto it : zones) | ||||
| 		it.second->createWater(getMapGenOptions().getWaterContent()); | ||||
| 	 | ||||
| 	zoneWater.second->waterInitFreeTiles(); | ||||
| 	 | ||||
| #ifdef _BETA | ||||
| 	dump(false); | ||||
| #endif | ||||
|  | ||||
| 	createDirectConnections(); //direct | ||||
| 	createConnections2(); //subterranean gates and monoliths | ||||
| 	 | ||||
| 	for(auto it : zones) | ||||
| 		zoneWater.second->waterConnection(*it.second); | ||||
| 	 | ||||
| 	createWaterTreasures(); | ||||
| 	zoneWater.second->initFreeTiles(); | ||||
| 	zoneWater.second->fill(); | ||||
|  | ||||
| 	std::vector<std::shared_ptr<CRmgTemplateZone>> treasureZones; | ||||
| 	for (auto it : zones) | ||||
| 	for(auto it : zones) | ||||
| 	{ | ||||
| 		it.second->fill(); | ||||
| 		if (it.second->getType() == ETemplateZoneType::TREASURE) | ||||
| 			treasureZones.push_back(it.second); | ||||
| 	} | ||||
| 	 | ||||
| #ifdef _BETA | ||||
| 	dump(false); | ||||
| #endif | ||||
| 		 | ||||
| 	//set apriopriate free/occupied tiles, including blocked underground rock | ||||
| 	createObstaclesCommon1(); | ||||
| 	//set back original terrain for underground zones | ||||
| 	for (auto it : zones) | ||||
| 	for(auto it : zones) | ||||
| 		it.second->createObstacles1(); | ||||
| 	 | ||||
| 	createObstaclesCommon2(); | ||||
| 	//place actual obstacles matching zone terrain | ||||
| 	for (auto it : zones) | ||||
| 	{ | ||||
| 	for(auto it : zones) | ||||
| 		it.second->createObstacles2(); | ||||
| 	} | ||||
| 		 | ||||
| 	zoneWater.second->createObstacles2(); | ||||
| 	 | ||||
| #ifdef _BETA | ||||
| 	dump(false); | ||||
| #endif | ||||
|  | ||||
| 	#define PRINT_MAP_BEFORE_ROADS false | ||||
| 	if (PRINT_MAP_BEFORE_ROADS) //enable to debug | ||||
| @@ -379,15 +429,15 @@ void CMapGenerator::fillZones() | ||||
| 		out << std::endl; | ||||
| 	} | ||||
|  | ||||
| 	for (auto it : zones) | ||||
| 	for(auto it : zones) | ||||
| 	{ | ||||
| 		it.second->connectRoads(); //draw roads after everything else has been placed | ||||
| 	} | ||||
|  | ||||
| 	//find place for Grail | ||||
| 	if (treasureZones.empty()) | ||||
| 	if(treasureZones.empty()) | ||||
| 	{ | ||||
| 		for (auto it : zones) | ||||
| 		for(auto it : zones) | ||||
| 			treasureZones.push_back(it.second); | ||||
| 	} | ||||
| 	auto grailZone = *RandomGeneratorUtil::nextItem(treasureZones, rand); | ||||
| @@ -503,30 +553,29 @@ void CMapGenerator::findZonesForQuestArts() | ||||
|  | ||||
| void CMapGenerator::createDirectConnections() | ||||
| { | ||||
| 	bool waterMode = getMapGenOptions().getWaterContent() != EWaterContent::NONE; | ||||
| 	 | ||||
| 	for (auto connection : mapGenOptions.getMapTemplate()->getConnections()) | ||||
| 	{ | ||||
| 		auto zoneA = zones[connection.getZoneA()]; | ||||
| 		auto zoneB = zones[connection.getZoneB()]; | ||||
|  | ||||
| 		//rearrange tiles in random order | ||||
| 		auto tilesCopy = zoneA->getTileInfo(); | ||||
| 		std::vector<int3> tiles(tilesCopy.begin(), tilesCopy.end()); | ||||
| 		const auto & tiles = zoneA->getTileInfo(); | ||||
|  | ||||
| 		int3 guardPos(-1,-1,-1); | ||||
|  | ||||
| 		auto otherZoneTiles = zoneB->getTileInfo(); | ||||
|  | ||||
| 		int3 posA = zoneA->getPos(); | ||||
| 		int3 posB = zoneB->getPos(); | ||||
| 		// auto zoneAid = zoneA->getId(); | ||||
| 		auto zoneBid = zoneB->getId(); | ||||
|  | ||||
| 		 | ||||
| 		if (posA.z == posB.z) | ||||
| 		{ | ||||
| 			std::vector<int3> middleTiles; | ||||
| 			for (auto tile : tilesCopy) | ||||
| 			for (const auto& tile : tiles) | ||||
| 			{ | ||||
| 				if (isBlocked(tile)) //tiles may be occupied by subterranean gates already placed | ||||
| 				if (isUsed(tile) || getZoneID(tile)==zoneWater.first) //tiles may be occupied by towns or water | ||||
| 					continue; | ||||
| 				foreachDirectNeighbour(tile, [tile, &middleTiles, this, zoneBid](int3 & pos) //must be direct since paths also also generated between direct neighbours | ||||
| 				{ | ||||
| @@ -559,8 +608,8 @@ void CMapGenerator::createDirectConnections() | ||||
| 				if (guardPos.valid()) | ||||
| 				{ | ||||
| 					//zones can make paths only in their own area | ||||
| 					zoneA->connectWithCenter(guardPos, true); | ||||
| 					zoneB->connectWithCenter(guardPos, true); | ||||
| 					zoneA->connectWithCenter(guardPos, true, true); | ||||
| 					zoneB->connectWithCenter(guardPos, true, true); | ||||
|  | ||||
| 					bool monsterPresent = zoneA->addMonster(guardPos, connection.getGuardStrength(), false, true); | ||||
| 					zoneB->updateDistances(guardPos); //place next objects away from guard in both zones | ||||
| @@ -575,9 +624,12 @@ void CMapGenerator::createDirectConnections() | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		 | ||||
| 		if (!guardPos.valid()) | ||||
| 			connectionsLeft.push_back(connection); | ||||
| 		{ | ||||
| 			if(!waterMode || posA.z != posB.z || !zoneWater.second->waterKeepConnection(connection.getZoneA(), connection.getZoneB())) | ||||
| 				connectionsLeft.push_back(connection); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -865,3 +917,48 @@ ui32 CMapGenerator::getTotalZoneCount() const | ||||
| { | ||||
| 	return zonesTotal; | ||||
| } | ||||
| CMapGenerator::Zones::value_type CMapGenerator::getZoneWater() const | ||||
| { | ||||
| 	return zoneWater; | ||||
| } | ||||
|  | ||||
| void CMapGenerator::dump(bool zoneId) | ||||
| { | ||||
| 	static int id = 0; | ||||
| 	std::ofstream out(boost::to_string(boost::format("zone_%d.txt") % id++)); | ||||
| 	int levels = map->twoLevel ? 2 : 1; | ||||
| 	int width =  map->width; | ||||
| 	int height = map->height; | ||||
| 	for (int k = 0; k < levels; k++) | ||||
| 	{ | ||||
| 		for(int j=0; j<height; j++) | ||||
| 		{ | ||||
| 			for (int i=0; i<width; i++) | ||||
| 			{ | ||||
| 				if(zoneId) | ||||
| 				{ | ||||
| 					out << getZoneID(int3(i, j, k)); | ||||
| 				} | ||||
| 				else | ||||
| 				{ | ||||
| 					char t = '?'; | ||||
| 					switch (getTile(int3(i, j, k)).getTileType()) | ||||
| 					{ | ||||
| 						case ETileType::FREE: | ||||
| 							t = ' '; break; | ||||
| 						case ETileType::BLOCKED: | ||||
| 							t = '#'; break; | ||||
| 						case ETileType::POSSIBLE: | ||||
| 							t = '-'; break; | ||||
| 						case ETileType::USED: | ||||
| 							t = 'O'; break; | ||||
| 					} | ||||
| 					out << t; | ||||
| 				} | ||||
| 			} | ||||
| 			out << std::endl; | ||||
| 		} | ||||
| 		out << std::endl; | ||||
| 	} | ||||
| 	out << std::endl; | ||||
| } | ||||
|   | ||||
| @@ -26,6 +26,8 @@ class JsonNode; | ||||
| class CMapGenerator; | ||||
| class CTileInfo; | ||||
|  | ||||
| //#define _BETA | ||||
|  | ||||
| typedef std::vector<JsonNode> JsonVector; | ||||
|  | ||||
| class rmgException : public std::exception | ||||
| @@ -96,18 +98,26 @@ public: | ||||
| 	void registerZone (TFaction faction); | ||||
| 	ui32 getZoneCount(TFaction faction); | ||||
| 	ui32 getTotalZoneCount() const; | ||||
| 	 | ||||
| 	Zones::value_type getZoneWater() const; | ||||
| 	void createWaterTreasures(); | ||||
| 	void prepareWaterTiles(); | ||||
|  | ||||
| 	TRmgTemplateZoneId getZoneID(const int3& tile) const; | ||||
| 	void setZoneID(const int3& tile, TRmgTemplateZoneId zid); | ||||
| 	 | ||||
| 	void dump(bool zoneId); | ||||
|  | ||||
| private: | ||||
| 	int randomSeed; | ||||
| 	CMapGenOptions& mapGenOptions; | ||||
| 	 | ||||
| 	std::list<rmg::ZoneConnection> connectionsLeft; | ||||
| 	std::vector<rmg::ZoneConnection> connectionsLeft; | ||||
| 	Zones zones; | ||||
| 	std::map<TFaction, ui32> zonesPerFaction; | ||||
| 	ui32 zonesTotal; //zones that have their main town only | ||||
| 	 | ||||
| 	std::pair<Zones::key_type, Zones::mapped_type> zoneWater; | ||||
|  | ||||
| 	CTileInfo*** tiles; | ||||
| 	boost::multi_array<TRmgTemplateZoneId, 3> zoneColouring; //[z][x][y] | ||||
|   | ||||
| @@ -39,6 +39,12 @@ CTreasureInfo::CTreasureInfo() | ||||
|  | ||||
| } | ||||
|  | ||||
| CTreasureInfo::CTreasureInfo(ui32 imin, ui32 imax, ui16 idensity) | ||||
| 	: min(imin), max(imax), density(idensity) | ||||
| { | ||||
| 	 | ||||
| } | ||||
|  | ||||
| bool CTreasureInfo::operator==(const CTreasureInfo & other) const | ||||
| { | ||||
| 	return (min == other.min) && (max == other.max) && (density == other.density); | ||||
| @@ -196,6 +202,11 @@ ETemplateZoneType::ETemplateZoneType ZoneOptions::getType() const | ||||
| { | ||||
| 	return type; | ||||
| } | ||||
| 	 | ||||
| void ZoneOptions::setType(ETemplateZoneType::ETemplateZoneType value) | ||||
| { | ||||
| 	type = value; | ||||
| } | ||||
|  | ||||
| int ZoneOptions::getSize() const | ||||
| { | ||||
| @@ -264,6 +275,11 @@ void ZoneOptions::setTreasureInfo(const std::vector<CTreasureInfo> & value) | ||||
| { | ||||
| 	treasureInfo = value; | ||||
| } | ||||
| 	 | ||||
| void ZoneOptions::addTreasureInfo(const CTreasureInfo & value) | ||||
| { | ||||
| 	treasureInfo.push_back(value); | ||||
| } | ||||
|  | ||||
| const std::vector<CTreasureInfo> & ZoneOptions::getTreasureInfo() const | ||||
| { | ||||
| @@ -302,7 +318,8 @@ void ZoneOptions::serializeJson(JsonSerializeFormat & handler) | ||||
| 		"playerStart", | ||||
| 		"cpuStart", | ||||
| 		"treasure", | ||||
| 		"junction" | ||||
| 		"junction", | ||||
| 		"water" | ||||
| 	}; | ||||
|  | ||||
| 	handler.serializeEnum("type", type, zoneTypes); | ||||
| @@ -421,6 +438,11 @@ bool CRmgTemplate::matchesSize(const int3 & value) const | ||||
| 	return minSquare <= square && square <= maxSquare; | ||||
| } | ||||
|  | ||||
| bool CRmgTemplate::isWaterContentAllowed(EWaterContent::EWaterContent waterContent) const | ||||
| { | ||||
| 	return waterContent == EWaterContent::EWaterContent::RANDOM || allowedWaterContent.count(waterContent); | ||||
| } | ||||
|  | ||||
| void CRmgTemplate::setId(const std::string & value) | ||||
| { | ||||
| 	id = value; | ||||
| @@ -623,6 +645,14 @@ void CRmgTemplate::afterLoad() | ||||
| 		zone1->addConnection(id2); | ||||
| 		zone2->addConnection(id1); | ||||
| 	} | ||||
| 	 | ||||
| 	if(allowedWaterContent.empty() || allowedWaterContent.count(EWaterContent::EWaterContent::RANDOM)) | ||||
| 	{ | ||||
| 		allowedWaterContent.insert(EWaterContent::EWaterContent::NONE); | ||||
| 		allowedWaterContent.insert(EWaterContent::EWaterContent::NORMAL); | ||||
| 		allowedWaterContent.insert(EWaterContent::EWaterContent::ISLANDS); | ||||
| 	} | ||||
| 	allowedWaterContent.erase(EWaterContent::EWaterContent::RANDOM); | ||||
| } | ||||
|  | ||||
| void CRmgTemplate::serializeSize(JsonSerializeFormat & handler, int3 & value, const std::string & fieldName) | ||||
|   | ||||
| @@ -24,7 +24,8 @@ namespace ETemplateZoneType | ||||
| 		PLAYER_START, | ||||
| 		CPU_START, | ||||
| 		TREASURE, | ||||
| 		JUNCTION | ||||
| 		JUNCTION, | ||||
| 		WATER | ||||
| 	}; | ||||
| } | ||||
|  | ||||
| @@ -35,6 +36,7 @@ public: | ||||
| 	ui32 max; | ||||
| 	ui16 density; | ||||
| 	CTreasureInfo(); | ||||
| 	CTreasureInfo(ui32 min, ui32 max, ui16 density); | ||||
|  | ||||
| 	bool operator ==(const CTreasureInfo & other) const; | ||||
|  | ||||
| @@ -93,6 +95,8 @@ public: | ||||
| 	void setId(TRmgTemplateZoneId value); | ||||
|  | ||||
| 	ETemplateZoneType::ETemplateZoneType getType() const; | ||||
| 	void setType(ETemplateZoneType::ETemplateZoneType value); | ||||
| 	 | ||||
| 	int getSize() const; | ||||
| 	void setSize(int value); | ||||
| 	boost::optional<int> getOwner() const; | ||||
| @@ -110,6 +114,7 @@ public: | ||||
| 	std::map<TResource, ui16> getMinesInfo() const; | ||||
|  | ||||
| 	void setTreasureInfo(const std::vector<CTreasureInfo> & value); | ||||
| 	void addTreasureInfo(const CTreasureInfo & value); | ||||
| 	const std::vector<CTreasureInfo> & getTreasureInfo() const; | ||||
|  | ||||
| 	TRmgTemplateZoneId getMinesLikeZone() const; | ||||
| @@ -175,6 +180,7 @@ public: | ||||
| 	~CRmgTemplate(); | ||||
|  | ||||
| 	bool matchesSize(const int3 & value) const; | ||||
| 	bool isWaterContentAllowed(EWaterContent::EWaterContent waterContent) const; | ||||
|  | ||||
| 	void setId(const std::string & value); | ||||
| 	const std::string & getName() const; | ||||
| @@ -195,6 +201,7 @@ private: | ||||
| 	CPlayerCountRange players, cpuPlayers; | ||||
| 	Zones zones; | ||||
| 	std::vector<rmg::ZoneConnection> connections; | ||||
| 	std::set<EWaterContent::EWaterContent> allowedWaterContent; | ||||
|  | ||||
| 	void afterLoad(); | ||||
| 	void serializeSize(JsonSerializeFormat & handler, int3 & value, const std::string & fieldName); | ||||
|   | ||||
| @@ -68,36 +68,3 @@ std::vector<const CRmgTemplate *> CRmgTemplateStorage::getTemplates() const | ||||
| 	} | ||||
| 	return result; | ||||
| } | ||||
|  | ||||
| std::vector<const CRmgTemplate *> CRmgTemplateStorage::getTemplates(const int3& filterSize, si8 filterPlayers, si8 filterHumanPlayers, si8 filterCpuPlayers) const | ||||
| { | ||||
| 	std::vector<const CRmgTemplate *> result; | ||||
| 	for(auto i=templates.cbegin(); i!=templates.cend(); ++i) | ||||
| 	{ | ||||
| 		auto& tmpl = i->second; | ||||
| 		 | ||||
| 		if (!tmpl.matchesSize(filterSize)) | ||||
| 			continue; | ||||
| 		 | ||||
| 		if (filterPlayers != -1) | ||||
| 		{ | ||||
| 			if (!tmpl.getPlayers().isInRange(filterPlayers)) | ||||
| 				continue; | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			// Human players shouldn't be banned when playing with random player count | ||||
| 			if (filterHumanPlayers > *boost::min_element(tmpl.getPlayers().getNumbers())) | ||||
| 				continue; | ||||
| 		} | ||||
| 		 | ||||
| 		if(filterCpuPlayers != -1) | ||||
| 		{ | ||||
| 			if (!tmpl.getCpuPlayers().isInRange(filterCpuPlayers)) | ||||
| 				continue; | ||||
| 		} | ||||
| 		 | ||||
| 		result.push_back(&i->second); | ||||
| 	} | ||||
| 	return result; | ||||
| } | ||||
|   | ||||
| @@ -29,9 +29,8 @@ public: | ||||
| 	virtual void loadObject(std::string scope, std::string name, const JsonNode & data) override; | ||||
| 	virtual void loadObject(std::string scope, std::string name, const JsonNode & data, size_t index) override; | ||||
| 	 | ||||
| 	const CRmgTemplate * getTemplate(const std::string & templateName) const; | ||||
| 	const CRmgTemplate* getTemplate(const std::string & templateName) const; | ||||
| 	std::vector<const CRmgTemplate *> getTemplates() const; | ||||
| 	std::vector<const CRmgTemplate *> getTemplates(const int3& filterSize, si8 filterPlayers, si8 filterHumanPlayers, si8 filterCpuPlayers) const; | ||||
|  | ||||
| private: | ||||
| 	std::map<std::string, CRmgTemplate> templates; | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -91,26 +91,29 @@ class DLL_LINKAGE CRmgTemplateZone : public rmg::ZoneOptions | ||||
| public: | ||||
| 	CRmgTemplateZone(CMapGenerator * Gen); | ||||
|  | ||||
| 	void setOptions(const rmg::ZoneOptions * options); | ||||
| 	void setOptions(const rmg::ZoneOptions & options); | ||||
| 	bool isUnderground() const; | ||||
|  | ||||
| 	float3 getCenter() const; | ||||
| 	void setCenter(const float3 &f); | ||||
| 	int3 getPos() const; | ||||
| 	void setPos(const int3 &pos); | ||||
| 	bool isAccessibleFromAnywhere(ObjectTemplate &appearance, int3 &tile) const; | ||||
| 	int3 getAccessibleOffset(ObjectTemplate &appearance, int3 &tile) const; | ||||
| 	bool isAccessibleFromSomewhere(ObjectTemplate & appearance, const int3 & tile) const; | ||||
| 	int3 getAccessibleOffset(ObjectTemplate & appearance, const int3 & tile) const; | ||||
|  | ||||
| 	void addTile (const int3 &pos); | ||||
| 	void addTile (const int3 & pos); | ||||
| 	void removeTile(const int3 & pos); | ||||
| 	void initFreeTiles (); | ||||
| 	std::set<int3> getTileInfo() const; | ||||
| 	std::set<int3> getPossibleTiles() const; | ||||
| 	void discardDistantTiles (float distance); | ||||
| 	std::set<int3> collectDistantTiles (float distance) const; | ||||
| 	void clearTiles(); | ||||
|  | ||||
| 	void addRequiredObject(CGObjectInstance * obj, si32 guardStrength=0); | ||||
| 	void addCloseObject(CGObjectInstance * obj, si32 guardStrength = 0); | ||||
| 	void addNearbyObject(CGObjectInstance * obj, CGObjectInstance * nearbyTarget); | ||||
| 	void addObjectAtPosition(CGObjectInstance * obj, const int3 & position, si32 guardStrength=0); | ||||
|  | ||||
| 	void addToConnectLater(const int3& src); | ||||
| 	bool addMonster(int3 &pos, si32 strength, bool clearSurroundingTiles = true, bool zoneGuard = false); | ||||
| 	bool createTreasurePile(int3 &pos, float minDistance, const CTreasureInfo& treasureInfo); | ||||
| @@ -123,21 +126,35 @@ public: | ||||
| 	void createBorder(); | ||||
| 	void fractalize(); | ||||
| 	void connectLater(); | ||||
| 	EObjectPlacingResult::EObjectPlacingResult tryToPlaceObjectAndConnectToPath(CGObjectInstance *obj, int3 &pos); //return true if the position cna be connected | ||||
| 	EObjectPlacingResult::EObjectPlacingResult tryToPlaceObjectAndConnectToPath(CGObjectInstance * obj, const int3 & pos); //return true if the position can be connected | ||||
| 	bool createRequiredObjects(); | ||||
| 	bool createShipyard(const int3 & pos, si32 guardStrength=0); | ||||
| 	int3 createShipyard(const std::set<int3> & lake, si32 guardStrength=0); | ||||
| 	bool makeBoat(TRmgTemplateZoneId land, const int3 & coast); | ||||
| 	int3 makeBoat(TRmgTemplateZoneId land, const std::set<int3> & lake); | ||||
| 	void createTreasures(); | ||||
| 	 | ||||
| 	void createWater(EWaterContent::EWaterContent waterContent, bool debug=false); | ||||
| 	void waterInitFreeTiles(); | ||||
| 	void waterConnection(CRmgTemplateZone& dst); | ||||
| 	bool waterKeepConnection(TRmgTemplateZoneId zoneA, TRmgTemplateZoneId zoneB); | ||||
| 	const std::set<int3>& getCoastTiles() const; | ||||
| 	bool isWaterConnected(TRmgTemplateZoneId zone, const int3 & tile) const; | ||||
| 	//void computeCoastTiles(); | ||||
| 	 | ||||
| 	void createObstacles1(); | ||||
| 	void createObstacles2(); | ||||
| 	bool crunchPath(const int3 &src, const int3 &dst, bool onlyStraight, std::set<int3>* clearedTiles = nullptr); | ||||
| 	bool connectPath(const int3& src, bool onlyStraight); | ||||
| 	bool connectWithCenter(const int3& src, bool onlyStraight); | ||||
| 	bool connectWithCenter(const int3& src, bool onlyStraight, bool passTroughBlocked = false); | ||||
| 	void updateDistances(const int3 & pos); | ||||
|  | ||||
| 	std::vector<int3> getAccessibleOffsets (const CGObjectInstance* object); | ||||
| 	bool areAllTilesAvailable(CGObjectInstance* obj, int3& tile, std::set<int3>& tilesBlockedByObject) const; | ||||
| 	bool areAllTilesAvailable(CGObjectInstance* obj, int3& tile, const std::set<int3>& tilesBlockedByObject) const; | ||||
|  | ||||
| 	void setQuestArtZone(std::shared_ptr<CRmgTemplateZone> otherZone); | ||||
| 	std::set<int3>* getFreePaths(); | ||||
| 	void addFreePath(const int3 &); | ||||
|  | ||||
| 	ObjectInfo getRandomObject (CTreasurePileInfo &info, ui32 desiredValue, ui32 maxValue, ui32 currentValue); | ||||
|  | ||||
| @@ -160,9 +177,20 @@ public: | ||||
| 	boost::heap::priority_queue<TDistance, boost::heap::compare<NodeComparer>> createPriorityQueue(); | ||||
|  | ||||
| private: | ||||
| 	 | ||||
| 	//subclass to store disconnected parts of water zone | ||||
| 	struct Lake | ||||
| 	{ | ||||
| 		std::set<int3> tiles; | ||||
| 		std::set<int3> coast; | ||||
| 		std::map<int3, int> distance; | ||||
| 		std::set<TRmgTemplateZoneId> connectedZones; | ||||
| 		std::set<TRmgTemplateZoneId> keepConnections; | ||||
| 	}; | ||||
| 	 | ||||
| 	CMapGenerator * gen; | ||||
| 	 | ||||
| 	//template info | ||||
|  | ||||
| 	si32 townType; | ||||
| 	ETerrainType terrainType; | ||||
| 	std::weak_ptr<CRmgTemplateZone> questArtZone; //artifacts required for Seer Huts will be placed here - or not if null | ||||
| @@ -173,8 +201,10 @@ private: | ||||
| 	//content info | ||||
| 	std::vector<std::pair<CGObjectInstance*, ui32>> requiredObjects; | ||||
| 	std::vector<std::pair<CGObjectInstance*, ui32>> closeObjects; | ||||
| 	std::vector<std::pair<CGObjectInstance*, int3>> instantObjects; | ||||
| 	std::vector<std::pair<CGObjectInstance*, CGObjectInstance*>> nearbyObjects; | ||||
| 	std::vector<CGObjectInstance*> objects; | ||||
| 	std::map<CGObjectInstance*, int3> requestedPositions; | ||||
|  | ||||
| 	//placement info | ||||
| 	int3 pos; | ||||
| @@ -182,11 +212,14 @@ private: | ||||
| 	std::set<int3> tileinfo; //irregular area assined to zone | ||||
| 	std::set<int3> possibleTiles; //optimization purposes for treasure generation | ||||
| 	std::set<int3> freePaths; //core paths of free tiles that all other objects will be linked to | ||||
| 	std::set<int3> coastTiles; //tiles bordered to water | ||||
|  | ||||
| 	std::set<int3> roadNodes; //tiles to be connected with roads | ||||
| 	std::set<int3> roads; //all tiles with roads | ||||
| 	std::set<int3> tilesToConnectLater; //will be connected after paths are fractalized | ||||
|  | ||||
| 	std::vector<Lake> lakes; //disconnected parts of zone. Used to work with water zones | ||||
| 	std::map<int3, int> lakeMap; //map tile on lakeId which is position of lake in lakes array +1 | ||||
| 	 | ||||
| 	bool createRoad(const int3 &src, const int3 &dst); | ||||
| 	void drawRoads(); //actually updates tiles | ||||
|  | ||||
| @@ -197,4 +230,6 @@ private: | ||||
| 	bool canObstacleBePlacedHere(ObjectTemplate &temp, int3 &pos); | ||||
| 	void setTemplateForObject(CGObjectInstance* obj); | ||||
| 	void checkAndPlaceObject(CGObjectInstance* object, const int3 &pos); | ||||
| 	 | ||||
| 	bool isGuardNeededForTreasure(int value); | ||||
| }; | ||||
|   | ||||
| @@ -1,33 +0,0 @@ | ||||
| /* | ||||
|  * CZoneGraphGenerator.cpp, part of VCMI engine | ||||
|  * | ||||
|  * Authors: listed in file AUTHORS in main folder | ||||
|  * | ||||
|  * License: GNU General Public License v2.0 or later | ||||
|  * Full text of license available in license.txt file, in main folder | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #include "StdInc.h" | ||||
| #include "CZoneGraphGenerator.h" | ||||
|  | ||||
| CZoneCell::CZoneCell(const CRmgTemplateZone * zone)// : zone(zone) | ||||
| { | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
| CZoneGraph::CZoneGraph() | ||||
| { | ||||
|  | ||||
| } | ||||
|  | ||||
| CZoneGraphGenerator::CZoneGraphGenerator()// : gen(nullptr) | ||||
| { | ||||
|  | ||||
| } | ||||
|  | ||||
| std::unique_ptr<CZoneGraph> CZoneGraphGenerator::generate(const CMapGenOptions & options, CRandomGenerator * gen) | ||||
| { | ||||
| 	return make_unique<CZoneGraph>(); | ||||
| } | ||||
| @@ -1,47 +0,0 @@ | ||||
| /* | ||||
|  * CZoneGraphGenerator.h, part of VCMI engine | ||||
|  * | ||||
|  * Authors: listed in file AUTHORS in main folder | ||||
|  * | ||||
|  * License: GNU General Public License v2.0 or later | ||||
|  * Full text of license available in license.txt file, in main folder | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| class CRmgTemplateZone; | ||||
| class CRandomGenerator; | ||||
| class CMapGenOptions; | ||||
|  | ||||
| class CZoneCell | ||||
| { | ||||
| public: | ||||
| 	explicit CZoneCell(const CRmgTemplateZone * zone); | ||||
|  | ||||
| private: | ||||
| 	//const CRmgTemplateZone * zone; | ||||
|  | ||||
| 	//TODO additional data | ||||
| }; | ||||
|  | ||||
| class CZoneGraph | ||||
| { | ||||
| public: | ||||
| 	CZoneGraph(); | ||||
|  | ||||
| private: | ||||
| 	//TODO zone graph storage | ||||
| }; | ||||
|  | ||||
| class CZoneGraphGenerator | ||||
| { | ||||
| public: | ||||
| 	CZoneGraphGenerator(); | ||||
|  | ||||
| 	std::unique_ptr<CZoneGraph> generate(const CMapGenOptions & options, CRandomGenerator * gen); | ||||
|  | ||||
| private: | ||||
| 	std::unique_ptr<CZoneGraph> graph; | ||||
| 	//CRandomGenerator * gen; | ||||
| }; | ||||
| @@ -13,8 +13,7 @@ | ||||
| #include "CZonePlacer.h" | ||||
| #include "CRmgTemplateZone.h" | ||||
| #include "../mapping/CMap.h" | ||||
|  | ||||
| #include "CZoneGraphGenerator.h" | ||||
| #include "../mapping/CMapEditManager.h" | ||||
|  | ||||
| class CRandomGenerator; | ||||
|  | ||||
| @@ -557,7 +556,11 @@ void CZonePlacer::assignZones() | ||||
| 		if (zone.second->isUnderground()) | ||||
| 		{ | ||||
| 			if (!CREATE_FULL_UNDERGROUND) | ||||
| 				zone.second->discardDistantTiles((float)(zone.second->getSize() + 1)); | ||||
| 			{ | ||||
| 				auto discardTile = zone.second->collectDistantTiles((float)(zone.second->getSize() + 1)); | ||||
| 				for(auto& t : discardTile) | ||||
| 					zone.second->removeTile(t); | ||||
| 			} | ||||
|  | ||||
| 			//make sure that terrain inside zone is not a rock | ||||
| 			//FIXME: reorder actions? | ||||
|   | ||||
		Reference in New Issue
	
	Block a user