瀏覽代碼

Actually copy zone data from map generator template
* fixes https://bugs.vcmi.eu/view.php?id=2482

AlexVinS 7 年之前
父節點
當前提交
26aad17295

+ 16 - 10
lib/rmg/CMapGenerator.cpp

@@ -18,6 +18,7 @@
 #include "../StringConstants.h"
 #include "../filesystem/Filesystem.h"
 #include "CZonePlacer.h"
+#include "CRmgTemplateZone.h"
 #include "../mapObjects/CObjectClassesHandler.h"
 
 static const int3 dirs4[] = {int3(0,1,0),int3(0,-1,0),int3(-1,0,0),int3(+1,0,0)};
@@ -273,10 +274,15 @@ void CMapGenerator::genZones()
 	editManager->drawTerrain(ETerrainType::GRASS, &rand);
 
 	auto tmpl = mapGenOptions->getMapTemplate();
-	zones = tmpl->getZones(); //copy from template (refactor?)
-	//immediately set gen pointer before taking any actions on zones
-	for (auto zone : zones)
-		zone.second->setGenPtr(this);
+	zones.clear();
+	for(const auto & option : tmpl->getZones())
+	{
+		auto zone = new CRmgTemplateZone();
+		zone->setOptions(option.second);
+		zones[zone->getId()] = zone;
+		//todo: move to CRmgTemplateZone constructor
+		zone->setGenPtr(this);//immediately set gen pointer before taking any actions on zones
+	}
 
 	CZonePlacer placer(this);
 	placer.placeZones(mapGenOptions, &rand);
@@ -474,8 +480,8 @@ void CMapGenerator::findZonesForQuestArts()
 
 	for (auto connection : mapGenOptions->getMapTemplate()->getConnections())
 	{
-		auto zoneA = connection.getZoneA();
-		auto zoneB = connection.getZoneB();
+		auto zoneA = zones[connection.getZoneA()];
+		auto zoneB = zones[connection.getZoneB()];
 
 		if (zoneA->getId() > zoneB->getId())
 		{
@@ -492,8 +498,8 @@ void CMapGenerator::createDirectConnections()
 {
 	for (auto connection : mapGenOptions->getMapTemplate()->getConnections())
 	{
-		auto zoneA = connection.getZoneA();
-		auto zoneB = connection.getZoneB();
+		auto zoneA = zones[connection.getZoneA()];
+		auto zoneB = zones[connection.getZoneB()];
 
 		//rearrange tiles in random order
 		auto tilesCopy = zoneA->getTileInfo();
@@ -572,8 +578,8 @@ void CMapGenerator::createConnections2()
 {
 	for (auto & connection : connectionsLeft)
 	{
-		auto zoneA = connection.getZoneA();
-		auto zoneB = connection.getZoneB();
+		auto zoneA = zones[connection.getZoneA()];
+		auto zoneB = zones[connection.getZoneB()];
 
 		int3 guardPos(-1, -1, -1);
 

+ 2 - 3
lib/rmg/CMapGenerator.h

@@ -13,9 +13,8 @@
 #include "../GameConstants.h"
 #include "../CRandomGenerator.h"
 #include "CMapGenOptions.h"
-#include "CRmgTemplateZone.h"
 #include "../int3.h"
-#include "CRmgTemplate.h" //for CRmgTemplateZoneConnection
+#include "CRmgTemplate.h"
 
 class CMap;
 class CRmgTemplate;
@@ -100,7 +99,7 @@ public:
 	void setZoneID(const int3& tile, TRmgTemplateZoneId zid);
 
 private:
-	std::list<CRmgTemplateZoneConnection> connectionsLeft;
+	std::list<rmg::ZoneConnection> connectionsLeft;
 	std::map<TRmgTemplateZoneId, CRmgTemplateZone*> zones;
 	std::map<TFaction, ui32> zonesPerFaction;
 	ui32 zonesTotal; //zones that have their main town only

+ 290 - 12
lib/rmg/CRmgTemplate.cpp

@@ -11,45 +11,323 @@
 #include "StdInc.h"
 #include "CRmgTemplate.h"
 
-#include "CRmgTemplateZone.h"
 #include "../mapping/CMap.h"
+#include "../VCMI_Lib.h"
+#include "../CTownHandler.h"
 
-CRmgTemplateZoneConnection::CRmgTemplateZoneConnection() : zoneA(nullptr), zoneB(nullptr), guardStrength(0)
+namespace rmg
 {
 
+const std::set<ETerrainType> ZoneOptions::DEFAULT_TERRAIN_TYPES =
+{
+	ETerrainType::DIRT,
+	ETerrainType::SAND,
+	ETerrainType::GRASS,
+	ETerrainType::SNOW,
+	ETerrainType::SWAMP,
+	ETerrainType::ROUGH,
+	ETerrainType::SUBTERRANEAN,
+	ETerrainType::LAVA
+};
+
+ZoneOptions::CTownInfo::CTownInfo()
+	: townCount(0),
+	castleCount(0),
+	townDensity(0),
+	castleDensity(0)
+{
+
+}
+
+int ZoneOptions::CTownInfo::getTownCount() const
+{
+	return townCount;
+}
+
+void ZoneOptions::CTownInfo::setTownCount(int value)
+{
+	if(value < 0)
+		throw std::runtime_error("Negative value for town count not allowed.");
+	townCount = value;
+}
+
+int ZoneOptions::CTownInfo::getCastleCount() const
+{
+	return castleCount;
+}
+
+void ZoneOptions::CTownInfo::setCastleCount(int value)
+{
+	if(value < 0)
+		throw std::runtime_error("Negative value for castle count not allowed.");
+	castleCount = value;
+}
+
+int ZoneOptions::CTownInfo::getTownDensity() const
+{
+	return townDensity;
+}
+
+void ZoneOptions::CTownInfo::setTownDensity(int value)
+{
+	if(value < 0)
+		throw std::runtime_error("Negative value for town density not allowed.");
+	townDensity = value;
+}
+
+int ZoneOptions::CTownInfo::getCastleDensity() const
+{
+	return castleDensity;
+}
+
+void ZoneOptions::CTownInfo::setCastleDensity(int value)
+{
+	if(value < 0)
+		throw std::runtime_error("Negative value for castle density not allowed.");
+	castleDensity = value;
+}
+
+ZoneOptions::ZoneOptions()
+	: id(0),
+	type(ETemplateZoneType::PLAYER_START),
+	size(1),
+	owner(boost::none),
+	playerTowns(),
+	neutralTowns(),
+	matchTerrainToTown(true),
+	terrainTypes(DEFAULT_TERRAIN_TYPES),
+	townsAreSameType(false),
+	townTypes(),
+	monsterTypes(),
+	zoneMonsterStrength(EMonsterStrength::ZONE_NORMAL),
+	mines(),
+	treasureInfo(),
+	connections()
+{
+
+}
+
+ZoneOptions & ZoneOptions::operator=(const ZoneOptions & other)
+{
+	id = other.id;
+	type = other.type;
+	size = other.size;
+	owner = other.owner;
+	playerTowns = other.playerTowns;
+	neutralTowns = other.neutralTowns;
+	matchTerrainToTown = other.matchTerrainToTown;
+	terrainTypes = other.terrainTypes;
+	townsAreSameType = other.townsAreSameType;
+	townTypes = other.townTypes;
+	monsterTypes = other.monsterTypes;
+	zoneMonsterStrength = other.zoneMonsterStrength;
+	mines = other.mines;
+	treasureInfo = other.treasureInfo;
+	connections = other.connections;
+	return *this;
+}
+
+TRmgTemplateZoneId ZoneOptions::getId() const
+{
+	return id;
 }
 
-CRmgTemplateZone * CRmgTemplateZoneConnection::getZoneA() const
+void ZoneOptions::setId(TRmgTemplateZoneId value)
+{
+	if(value <= 0)
+		throw std::runtime_error(boost::to_string(boost::format("Zone %d id should be greater than 0.") % id));
+	id = value;
+}
+
+ETemplateZoneType::ETemplateZoneType ZoneOptions::getType() const
+{
+	return type;
+}
+void ZoneOptions::setType(ETemplateZoneType::ETemplateZoneType value)
+{
+	type = value;
+}
+
+int ZoneOptions::getSize() const
+{
+	return size;
+}
+
+void ZoneOptions::setSize(int value)
+{
+	if(value <= 0)
+		throw std::runtime_error(boost::to_string(boost::format("Zone %d size needs to be greater than 0.") % id));
+	size = value;
+}
+
+boost::optional<int> ZoneOptions::getOwner() const
+{
+	return owner;
+}
+
+void ZoneOptions::setOwner(boost::optional<int> value)
+{
+	if(value && !(*value >= 0 && *value <= PlayerColor::PLAYER_LIMIT_I))
+		throw std::runtime_error(boost::to_string(boost::format ("Owner of zone %d has to be in range 0 to max player count.") % id));
+	owner = value;
+}
+
+const ZoneOptions::CTownInfo & ZoneOptions::getPlayerTowns() const
+{
+	return playerTowns;
+}
+
+void ZoneOptions::setPlayerTowns(const CTownInfo & value)
+{
+	playerTowns = value;
+}
+
+const ZoneOptions::CTownInfo & ZoneOptions::getNeutralTowns() const
+{
+	return neutralTowns;
+}
+
+void ZoneOptions::setNeutralTowns(const CTownInfo & value)
+{
+	neutralTowns = value;
+}
+
+bool ZoneOptions::getMatchTerrainToTown() const
+{
+	return matchTerrainToTown;
+}
+
+void ZoneOptions::setMatchTerrainToTown(bool value)
+{
+	matchTerrainToTown = value;
+}
+
+const std::set<ETerrainType> & ZoneOptions::getTerrainTypes() const
+{
+	return terrainTypes;
+}
+
+void ZoneOptions::setTerrainTypes(const std::set<ETerrainType> & value)
+{
+	assert(value.find(ETerrainType::WRONG) == value.end() && value.find(ETerrainType::BORDER) == value.end() &&
+		   value.find(ETerrainType::WATER) == value.end() && value.find(ETerrainType::ROCK) == value.end());
+	terrainTypes = value;
+}
+
+bool ZoneOptions::getTownsAreSameType() const
+{
+	return townsAreSameType;
+}
+
+void ZoneOptions::setTownsAreSameType(bool value)
+{
+	townsAreSameType = value;
+}
+
+std::set<TFaction> ZoneOptions::getDefaultTownTypes() const
+{
+	std::set<TFaction> defaultTowns;
+	auto towns = VLC->townh->getDefaultAllowed();
+	for(int i = 0; i < towns.size(); ++i)
+	{
+		if(towns[i]) defaultTowns.insert(i);
+	}
+	return defaultTowns;
+}
+
+const std::set<TFaction> & ZoneOptions::getTownTypes() const
+{
+	return townTypes;
+}
+
+void ZoneOptions::setTownTypes(const std::set<TFaction> & value)
+{
+	townTypes = value;
+}
+
+void ZoneOptions::setMonsterTypes(const std::set<TFaction> & value)
+{
+	monsterTypes = value;
+}
+
+void ZoneOptions::setMonsterStrength(EMonsterStrength::EMonsterStrength val)
+{
+	assert (vstd::iswithin(val, EMonsterStrength::ZONE_WEAK, EMonsterStrength::ZONE_STRONG));
+	zoneMonsterStrength = val;
+}
+
+void ZoneOptions::setMinesAmount(TResource res, ui16 amount)
+{
+	mines[res] = amount;
+}
+
+std::map<TResource, ui16> ZoneOptions::getMinesInfo() const
+{
+	return mines;
+}
+
+void ZoneOptions::addTreasureInfo(const CTreasureInfo & info)
+{
+	treasureInfo.push_back(info);
+}
+
+const std::vector<CTreasureInfo> & ZoneOptions::getTreasureInfo() const
+{
+	return treasureInfo;
+}
+
+void ZoneOptions::addConnection(TRmgTemplateZoneId otherZone)
+{
+	connections.push_back (otherZone);
+}
+
+
+ZoneConnection::ZoneConnection()
+	: zoneA(-1),
+	zoneB(-1),
+	guardStrength(0)
+{
+
+}
+
+
+TRmgTemplateZoneId ZoneConnection::getZoneA() const
 {
 	return zoneA;
 }
 
-void CRmgTemplateZoneConnection::setZoneA(CRmgTemplateZone * value)
+void ZoneConnection::setZoneA(TRmgTemplateZoneId value)
 {
 	zoneA = value;
 }
 
-CRmgTemplateZone * CRmgTemplateZoneConnection::getZoneB() const
+TRmgTemplateZoneId ZoneConnection::getZoneB() const
 {
 	return zoneB;
 }
 
-void CRmgTemplateZoneConnection::setZoneB(CRmgTemplateZone * value)
+void ZoneConnection::setZoneB(TRmgTemplateZoneId value)
 {
 	zoneB = value;
 }
 
-int CRmgTemplateZoneConnection::getGuardStrength() const
+int ZoneConnection::getGuardStrength() const
 {
 	return guardStrength;
 }
 
-void CRmgTemplateZoneConnection::setGuardStrength(int value)
+void ZoneConnection::setGuardStrength(int value)
 {
 	if(value < 0) throw std::runtime_error("Negative value for guard strength not allowed.");
 	guardStrength = value;
 }
 
+}
+
+
+using namespace rmg;//todo: remove
+
+
 CRmgTemplate::CSize::CSize() : width(CMapHeader::MAP_SIZE_MIDDLE), height(CMapHeader::MAP_SIZE_MIDDLE), under(true)
 {
 
@@ -185,22 +463,22 @@ void CRmgTemplate::setCpuPlayers(const CPlayerCountRange & value)
 	cpuPlayers = value;
 }
 
-const std::map<TRmgTemplateZoneId, CRmgTemplateZone *> & CRmgTemplate::getZones() const
+const std::map<TRmgTemplateZoneId, ZoneOptions *> & CRmgTemplate::getZones() const
 {
 	return zones;
 }
 
-void CRmgTemplate::setZones(const std::map<TRmgTemplateZoneId, CRmgTemplateZone *> & value)
+void CRmgTemplate::setZones(const std::map<TRmgTemplateZoneId, ZoneOptions *> & value)
 {
 	zones = value;
 }
 
-const std::list<CRmgTemplateZoneConnection> & CRmgTemplate::getConnections() const
+const std::list<ZoneConnection> & CRmgTemplate::getConnections() const
 {
 	return connections;
 }
 
-void CRmgTemplate::setConnections(const std::list<CRmgTemplateZoneConnection> & value)
+void CRmgTemplate::setConnections(const std::list<ZoneConnection> & value)
 {
 	connections = value;
 }

+ 133 - 15
lib/rmg/CRmgTemplate.h

@@ -11,27 +11,145 @@
 #pragma once
 
 #include "../GameConstants.h"
+#include "../ResourceSet.h"
+#include "CMapGenOptions.h"
 
-class CRmgTemplateZone;
+class JsonSerializeFormat;
 
-/// The CRmgTemplateZoneConnection describes the connection between two zones.
-class DLL_LINKAGE CRmgTemplateZoneConnection
+namespace ETemplateZoneType
+{
+	enum ETemplateZoneType
+	{
+		PLAYER_START,
+		CPU_START,
+		TREASURE,
+		JUNCTION
+	};
+}
+
+class DLL_LINKAGE CTreasureInfo
 {
 public:
-	CRmgTemplateZoneConnection();
+	ui32 min;
+	ui32 max;
+	ui16 density;
+};
 
-	CRmgTemplateZone * getZoneA() const;
-	void setZoneA(CRmgTemplateZone * value);
-	CRmgTemplateZone * getZoneB() const;
-	void setZoneB(CRmgTemplateZone * value);
+namespace rmg
+{
+
+class DLL_LINKAGE ZoneConnection
+{
+public:
+	ZoneConnection();
+
+	TRmgTemplateZoneId getZoneA() const;
+	void setZoneA(TRmgTemplateZoneId value);
+	TRmgTemplateZoneId getZoneB() const;
+	void setZoneB(TRmgTemplateZoneId value);
 	int getGuardStrength() const; /// Default: 0
 	void setGuardStrength(int value);
 
 private:
-	CRmgTemplateZone * zoneA, * zoneB;
+	TRmgTemplateZoneId zoneA;
+	TRmgTemplateZoneId zoneB;
 	int guardStrength;
 };
 
+class DLL_LINKAGE ZoneOptions
+{
+public:
+	static const std::set<ETerrainType> DEFAULT_TERRAIN_TYPES;
+
+	class DLL_LINKAGE CTownInfo
+	{
+	public:
+		CTownInfo();
+
+		int getTownCount() const; /// Default: 0
+		void setTownCount(int value);
+		int getCastleCount() const; /// Default: 0
+		void setCastleCount(int value);
+		int getTownDensity() const; /// Default: 0
+		void setTownDensity(int value);
+		int getCastleDensity() const; /// Default: 0
+		void setCastleDensity(int value);
+
+	private:
+		int townCount, castleCount, townDensity, castleDensity;
+	};
+
+	ZoneOptions();
+
+	ZoneOptions & operator=(const ZoneOptions & other);
+
+	TRmgTemplateZoneId getId() const;
+	void setId(TRmgTemplateZoneId value);
+
+	ETemplateZoneType::ETemplateZoneType getType() const; /// Default: ETemplateZoneType::PLAYER_START
+	void setType(ETemplateZoneType::ETemplateZoneType value);
+
+	int getSize() const; /// Default: 1
+	void setSize(int value);
+
+	boost::optional<int> getOwner() const;
+	void setOwner(boost::optional<int> value);
+
+	const CTownInfo & getPlayerTowns() const;
+	void setPlayerTowns(const CTownInfo & value);
+	const CTownInfo & getNeutralTowns() const;
+	void setNeutralTowns(const CTownInfo & value);
+
+	bool getMatchTerrainToTown() const; /// Default: true
+	void setMatchTerrainToTown(bool value);
+
+	const std::set<ETerrainType> & getTerrainTypes() const; /// Default: all
+	void setTerrainTypes(const std::set<ETerrainType> & value);
+
+	bool getTownsAreSameType() const; /// Default: false
+	void setTownsAreSameType(bool value);
+
+	std::set<TFaction> getDefaultTownTypes() const;
+
+	const std::set<TFaction> & getTownTypes() const; /// Default: all
+	void setTownTypes(const std::set<TFaction> & value);
+	void setMonsterTypes(const std::set<TFaction> & value);
+
+	void setMonsterStrength(EMonsterStrength::EMonsterStrength val);
+
+	void setMinesAmount (TResource res, ui16 amount);
+	std::map<TResource, ui16> getMinesInfo() const;
+
+	void addTreasureInfo(const CTreasureInfo & info);
+	const std::vector<CTreasureInfo> & getTreasureInfo() const;
+
+	void addConnection(TRmgTemplateZoneId otherZone);
+
+protected:
+	TRmgTemplateZoneId id;
+	ETemplateZoneType::ETemplateZoneType type;
+	int size;
+	boost::optional<int> owner;
+	CTownInfo playerTowns;
+	CTownInfo neutralTowns;
+	bool matchTerrainToTown;
+	std::set<ETerrainType> terrainTypes;
+	bool townsAreSameType;
+
+	std::set<TFaction> townTypes;
+	std::set<TFaction> monsterTypes;
+
+	EMonsterStrength::EMonsterStrength zoneMonsterStrength;
+
+	std::map<TResource, ui16> mines; //obligatory mines to spawn in this zone
+
+	std::vector<CTreasureInfo> treasureInfo;
+
+	std::vector<TRmgTemplateZoneId> connections; //list of adjacent zones
+};
+
+}
+
 /// The CRmgTemplate describes a random map template.
 class DLL_LINKAGE CRmgTemplate
 {
@@ -81,10 +199,10 @@ public:
 	void setPlayers(const CPlayerCountRange & value);
 	const CPlayerCountRange & getCpuPlayers() const;
 	void setCpuPlayers(const CPlayerCountRange & value);
-	const std::map<TRmgTemplateZoneId, CRmgTemplateZone *> & getZones() const;
-	void setZones(const std::map<TRmgTemplateZoneId, CRmgTemplateZone *> & value);
-	const std::list<CRmgTemplateZoneConnection> & getConnections() const;
-	void setConnections(const std::list<CRmgTemplateZoneConnection> & value);
+	const std::map<TRmgTemplateZoneId, rmg::ZoneOptions *> & getZones() const;
+	void setZones(const std::map<TRmgTemplateZoneId, rmg::ZoneOptions *> & value);
+	const std::list<rmg::ZoneConnection> & getConnections() const;
+	void setConnections(const std::list<rmg::ZoneConnection> & value);
 
 	void validate() const; /// Tests template on validity and throws exception on failure
 
@@ -92,6 +210,6 @@ private:
 	std::string name;
 	CSize minSize, maxSize;
 	CPlayerCountRange players, cpuPlayers;
-	std::map<TRmgTemplateZoneId, CRmgTemplateZone *> zones;
-	std::list<CRmgTemplateZoneConnection> connections;
+	std::map<TRmgTemplateZoneId, rmg::ZoneOptions *> zones;
+	std::list<rmg::ZoneConnection> connections;
 };

+ 14 - 12
lib/rmg/CRmgTemplateStorage.cpp

@@ -20,6 +20,8 @@
 #include "../GameConstants.h"
 #include "../StringConstants.h"
 
+using namespace rmg;
+
 const std::map<std::string, CRmgTemplate *> & CRmgTemplateStorage::getTemplates() const
 {
 	return templates;
@@ -49,10 +51,10 @@ void CRmgTemplateStorage::loadObject(std::string scope, std::string name, const
 		tpl->setCpuPlayers(parsePlayers(templateNode["cpu"].String()));
 
 		// Parse zones
-		std::map<TRmgTemplateZoneId, CRmgTemplateZone *> zones;
+		std::map<TRmgTemplateZoneId, ZoneOptions *> zones;
 		for (const auto & zonePair : templateNode["zones"].Struct())
 		{
-			auto zone = new CRmgTemplateZone();
+			auto zone = new ZoneOptions();
 			auto zoneId = boost::lexical_cast<TRmgTemplateZoneId>(zonePair.first);
 			zone->setId(zoneId);
 
@@ -65,7 +67,7 @@ void CRmgTemplateStorage::loadObject(std::string scope, std::string name, const
 			zone->setNeutralTowns(parseTemplateZoneTowns(zoneNode["neutralTowns"]));
 			if (!zoneNode["matchTerrainToTown"].isNull()) //default : true
 				zone->setMatchTerrainToTown(zoneNode["matchTerrainToTown"].Bool());
-			zone->setTerrainTypes(parseTerrainTypes(zoneNode["terrainTypes"].Vector(), zone->getDefaultTerrainTypes()));
+			zone->setTerrainTypes(parseTerrainTypes(zoneNode["terrainTypes"].Vector(), ZoneOptions::DEFAULT_TERRAIN_TYPES));
 
 			if (!zoneNode["townsAreSameType"].isNull()) //default : false
 				zone->setTownsAreSameType((zoneNode["townsAreSameType"].Bool()));
@@ -119,7 +121,7 @@ void CRmgTemplateStorage::loadObject(std::string scope, std::string name, const
 			else
 			{
 				delete zone;
-				throw (rmgException("incorrect monster power"));
+				throw (std::runtime_error("incorrect monster power"));
 			}
 
 			if (!zoneNode["mines"].isNull())
@@ -206,12 +208,12 @@ void CRmgTemplateStorage::loadObject(std::string scope, std::string name, const
 		tpl->setZones(zones);
 
 		// Parse connections
-		std::list<CRmgTemplateZoneConnection> connections;
+		std::list<ZoneConnection> connections;
 		for(const auto & connPair : templateNode["connections"].Vector())
 		{
-			CRmgTemplateZoneConnection conn;
-			conn.setZoneA(zones.find(boost::lexical_cast<TRmgTemplateZoneId>(connPair["a"].String()))->second);
-			conn.setZoneB(zones.find(boost::lexical_cast<TRmgTemplateZoneId>(connPair["b"].String()))->second);
+			ZoneConnection conn;
+			conn.setZoneA(zones.find(boost::lexical_cast<TRmgTemplateZoneId>(connPair["a"].String()))->second->getId());
+			conn.setZoneB(zones.find(boost::lexical_cast<TRmgTemplateZoneId>(connPair["b"].String()))->second->getId());
 			conn.setGuardStrength(connPair["guard"].Float());
 			connections.push_back(conn);
 		}
@@ -220,8 +222,8 @@ void CRmgTemplateStorage::loadObject(std::string scope, std::string name, const
 			auto zones = tpl->getZones();
 			for (auto con : tpl->getConnections())
 			{
-				auto idA = con.getZoneA()->getId();
-				auto idB = con.getZoneB()->getId();
+				auto idA = con.getZoneA();
+				auto idB = con.getZoneB();
 				zones[idA]->addConnection(idB);
 				zones[idB]->addConnection(idA);
 			}
@@ -284,9 +286,9 @@ ETemplateZoneType::ETemplateZoneType CRmgTemplateStorage::parseZoneType(const st
 	return it->second;
 }
 
-CRmgTemplateZone::CTownInfo CRmgTemplateStorage::parseTemplateZoneTowns(const JsonNode & node) const
+ZoneOptions::CTownInfo CRmgTemplateStorage::parseTemplateZoneTowns(const JsonNode & node) const
 {
-	CRmgTemplateZone::CTownInfo towns;
+	ZoneOptions::CTownInfo towns;
 	towns.setTownCount(node["towns"].Float());
 	towns.setCastleCount(node["castles"].Float());
 	towns.setTownDensity(node["townDensity"].Float());

+ 1 - 2
lib/rmg/CRmgTemplateStorage.h

@@ -11,7 +11,6 @@
 #pragma once
 
 #include "CRmgTemplate.h"
-#include "CRmgTemplateZone.h"
 #include "../IHandlerBase.h"
 
 class JsonNode;
@@ -36,7 +35,7 @@ public:
 
 private:
 	CRmgTemplate::CSize parseMapTemplateSize(const std::string & text) const;
-	CRmgTemplateZone::CTownInfo parseTemplateZoneTowns(const JsonNode & node) const;
+	rmg::ZoneOptions::CTownInfo parseTemplateZoneTowns(const JsonNode & node) const;
 	ETemplateZoneType::ETemplateZoneType parseZoneType(const std::string & type) const;
 	std::set<TFaction> parseTownTypes(const JsonVector & townTypesVector, const std::set<TFaction> & defaultTownTypes) const;
 	std::set<ETerrainType> parseTerrainTypes(const JsonVector & terTypeStrings, const std::set<ETerrainType> & defaultTerrainTypes) const;

+ 8 - 222
lib/rmg/CRmgTemplateZone.cpp

@@ -27,64 +27,15 @@ class CMap;
 class CMapEditManager;
 //class CGObjectInstance;
 
-CRmgTemplateZone::CTownInfo::CTownInfo() : townCount(0), castleCount(0), townDensity(0), castleDensity(0)
-{
+using namespace rmg; //TODO: move all to namespace
+
 
-}
 
 void CRmgTemplateZone::addRoadNode(const int3& node)
 {
 	roadNodes.insert(node);
 }
 
-int CRmgTemplateZone::CTownInfo::getTownCount() const
-{
-	return townCount;
-}
-
-void CRmgTemplateZone::CTownInfo::setTownCount(int value)
-{
-	if(value < 0)
-		throw rmgException("Negative value for town count not allowed.");
-	townCount = value;
-}
-
-int CRmgTemplateZone::CTownInfo::getCastleCount() const
-{
-	return castleCount;
-}
-
-void CRmgTemplateZone::CTownInfo::setCastleCount(int value)
-{
-	if(value < 0)
-		throw rmgException("Negative value for castle count not allowed.");
-	castleCount = value;
-}
-
-int CRmgTemplateZone::CTownInfo::getTownDensity() const
-{
-	return townDensity;
-}
-
-void CRmgTemplateZone::CTownInfo::setTownDensity(int value)
-{
-	if(value < 0)
-		throw rmgException("Negative value for town density not allowed.");
-	townDensity = value;
-}
-
-int CRmgTemplateZone::CTownInfo::getCastleDensity() const
-{
-	return castleDensity;
-}
-
-void CRmgTemplateZone::CTownInfo::setCastleDensity(int value)
-{
-	if(value < 0)
-		throw rmgException("Negative value for castle density not allowed.");
-	castleDensity = value;
-}
-
 CTileInfo::CTileInfo():nearestObjectDistance(INT_MAX), terrain(ETerrainType::WRONG),roadType(ERoadType::NO_ROAD)
 {
 	occupied = ETileType::POSSIBLE; //all tiles are initially possible to place objects or passages
@@ -152,174 +103,25 @@ void CTileInfo::setRoadType(ERoadType::ERoadType value)
 }
 
 
-CRmgTemplateZone::CRmgTemplateZone() :
-	id(0),
-	type(ETemplateZoneType::PLAYER_START),
-	owner(boost::none),
-	size(1),
-	townsAreSameType(false),
-	matchTerrainToTown(true),
+CRmgTemplateZone::CRmgTemplateZone()
+	: ZoneOptions(),
 	townType(ETownType::NEUTRAL),
 	terrainType (ETerrainType::GRASS),
-	zoneMonsterStrength(EMonsterStrength::ZONE_NORMAL),
 	minGuardedValue(0),
 	questArtZone(nullptr),
 	gen(nullptr)
 {
-	terrainTypes = getDefaultTerrainTypes();
-}
-
-void CRmgTemplateZone::setGenPtr(CMapGenerator * Gen)
-{
-	gen = Gen;
-}
 
-TRmgTemplateZoneId CRmgTemplateZone::getId() const
-{
-	return id;
 }
 
-void CRmgTemplateZone::setId(TRmgTemplateZoneId value)
+void CRmgTemplateZone::setOptions(const ZoneOptions * options)
 {
-	if(value <= 0)
-		throw rmgException(boost::to_string(boost::format("Zone %d id should be greater than 0.") %id));
-	id = value;
+	ZoneOptions::operator=(*options);
 }
 
-ETemplateZoneType::ETemplateZoneType CRmgTemplateZone::getType() const
-{
-	return type;
-}
-void CRmgTemplateZone::setType(ETemplateZoneType::ETemplateZoneType value)
-{
-	type = value;
-}
-
-int CRmgTemplateZone::getSize() const
-{
-	return size;
-}
-
-void CRmgTemplateZone::setSize(int value)
-{
-	if(value <= 0)
-		throw rmgException(boost::to_string(boost::format("Zone %d size needs to be greater than 0.") % id));
-	size = value;
-}
-
-boost::optional<int> CRmgTemplateZone::getOwner() const
-{
-	return owner;
-}
-
-void CRmgTemplateZone::setOwner(boost::optional<int> value)
-{
-	if(!(*value >= 0 && *value <= PlayerColor::PLAYER_LIMIT_I))
-		throw rmgException(boost::to_string(boost::format ("Owner of zone %d has to be in range 0 to max player count.") %id));
-	owner = value;
-}
-
-const CRmgTemplateZone::CTownInfo & CRmgTemplateZone::getPlayerTowns() const
-{
-	return playerTowns;
-}
-
-void CRmgTemplateZone::setPlayerTowns(const CTownInfo & value)
-{
-	playerTowns = value;
-}
-
-const CRmgTemplateZone::CTownInfo & CRmgTemplateZone::getNeutralTowns() const
-{
-	return neutralTowns;
-}
-
-void CRmgTemplateZone::setNeutralTowns(const CTownInfo & value)
-{
-	neutralTowns = value;
-}
-
-bool CRmgTemplateZone::getTownsAreSameType() const
-{
-	return townsAreSameType;
-}
-
-void CRmgTemplateZone::setTownsAreSameType(bool value)
-{
-	townsAreSameType = value;
-}
-
-const std::set<TFaction> & CRmgTemplateZone::getTownTypes() const
-{
-	return townTypes;
-}
-
-void CRmgTemplateZone::setTownTypes(const std::set<TFaction> & value)
-{
-	townTypes = value;
-}
-void CRmgTemplateZone::setMonsterTypes(const std::set<TFaction> & value)
-{
-	monsterTypes = value;
-}
-
-std::set<TFaction> CRmgTemplateZone::getDefaultTownTypes() const
-{
-	std::set<TFaction> defaultTowns;
-	auto towns = VLC->townh->getDefaultAllowed();
-	for(int i = 0; i < towns.size(); ++i)
-	{
-		if(towns[i]) defaultTowns.insert(i);
-	}
-	return defaultTowns;
-}
-
-bool CRmgTemplateZone::getMatchTerrainToTown() const
-{
-	return matchTerrainToTown;
-}
-
-void CRmgTemplateZone::setMatchTerrainToTown(bool value)
-{
-	matchTerrainToTown = value;
-}
-
-const std::set<ETerrainType> & CRmgTemplateZone::getTerrainTypes() const
-{
-	return terrainTypes;
-}
-
-void CRmgTemplateZone::setTerrainTypes(const std::set<ETerrainType> & value)
-{
-	assert(value.find(ETerrainType::WRONG) == value.end() && value.find(ETerrainType::BORDER) == value.end() &&
-		   value.find(ETerrainType::WATER) == value.end() && value.find(ETerrainType::ROCK) == value.end());
-	terrainTypes = value;
-}
-
-std::set<ETerrainType> CRmgTemplateZone::getDefaultTerrainTypes() const
-{
-	std::set<ETerrainType> terTypes;
-	static const ETerrainType::EETerrainType allowedTerTypes[] = {ETerrainType::DIRT, ETerrainType::SAND, ETerrainType::GRASS, ETerrainType::SNOW,
-												   ETerrainType::SWAMP, ETerrainType::ROUGH, ETerrainType::SUBTERRANEAN, ETerrainType::LAVA};
-	for (auto & allowedTerType : allowedTerTypes)
-		terTypes.insert(allowedTerType);
-
-	return terTypes;
-}
-
-void CRmgTemplateZone::setMinesAmount (TResource res, ui16 amount)
-{
-	mines[res] = amount;
-}
-
-std::map<TResource, ui16> CRmgTemplateZone::getMinesInfo() const
-{
-	return mines;
-}
-
-void CRmgTemplateZone::addConnection(TRmgTemplateZoneId otherZone)
+void CRmgTemplateZone::setGenPtr(CMapGenerator * Gen)
 {
-	connections.push_back (otherZone);
+	gen = Gen;
 }
 
 void CRmgTemplateZone::setQuestArtZone(CRmgTemplateZone * otherZone)
@@ -332,22 +134,6 @@ std::vector<TRmgTemplateZoneId> CRmgTemplateZone::getConnections() const
 	return connections;
 }
 
-void CRmgTemplateZone::setMonsterStrength (EMonsterStrength::EMonsterStrength val)
-{
-	assert (vstd::iswithin(val, EMonsterStrength::ZONE_WEAK, EMonsterStrength::ZONE_STRONG));
-	zoneMonsterStrength = val;
-}
-
-void CRmgTemplateZone::addTreasureInfo(CTreasureInfo & info)
-{
-	treasureInfo.push_back(info);
-}
-
-std::vector<CTreasureInfo> CRmgTemplateZone::getTreasureInfo()
-{
-	return treasureInfo;
-}
-
 std::set<int3>* CRmgTemplateZone::getFreePaths()
 {
 	return &freePaths;

+ 4 - 84
lib/rmg/CRmgTemplateZone.h

@@ -14,7 +14,7 @@
 #include "CMapGenerator.h"
 #include "float3.h"
 #include "../int3.h"
-#include "../ResourceSet.h" //for TResource (?)
+#include "CRmgTemplate.h"
 #include "../mapObjects/ObjectTemplate.h"
 #include <boost/heap/priority_queue.hpp> //A*
 
@@ -23,18 +23,7 @@ class CTileInfo;
 class int3;
 class CGObjectInstance;
 class ObjectTemplate;
-class CRmgTemplateZoneConnection;
 
-namespace ETemplateZoneType
-{
-	enum ETemplateZoneType
-	{
-		PLAYER_START,
-		CPU_START,
-		TREASURE,
-		JUNCTION
-	};
-}
 namespace EObjectPlacingResult
 {
 	enum EObjectPlacingResult
@@ -71,14 +60,6 @@ private:
 	ERoadType::ERoadType roadType;
 };
 
-class DLL_LINKAGE CTreasureInfo
-{
-public:
-	ui32 min;
-	ui32 max;
-	ui16 density;
-};
-
 struct DLL_LINKAGE ObjectInfo
 {
 	ObjectTemplate templ;
@@ -105,57 +86,14 @@ struct DLL_LINKAGE CTreasurePileInfo
 };
 
 /// The CRmgTemplateZone describes a zone in a template.
-class DLL_LINKAGE CRmgTemplateZone
+class DLL_LINKAGE CRmgTemplateZone : public rmg::ZoneOptions
 {
 public:
-	class DLL_LINKAGE CTownInfo
-	{
-	public:
-		CTownInfo();
-
-		int getTownCount() const; /// Default: 0
-		void setTownCount(int value);
-		int getCastleCount() const; /// Default: 0
-		void setCastleCount(int value);
-		int getTownDensity() const; /// Default: 0
-		void setTownDensity(int value);
-		int getCastleDensity() const; /// Default: 0
-		void setCastleDensity(int value);
-
-	private:
-		int townCount, castleCount, townDensity, castleDensity;
-	};
-
 	CRmgTemplateZone();
 
-	void setGenPtr(CMapGenerator * Gen);
+	void setOptions(const rmg::ZoneOptions * options);
 
-	TRmgTemplateZoneId getId() const; /// Default: 0
-	void setId(TRmgTemplateZoneId value);
-	ETemplateZoneType::ETemplateZoneType getType() const; /// Default: ETemplateZoneType::PLAYER_START
-	void setType(ETemplateZoneType::ETemplateZoneType value);
-	int getSize() const; /// Default: 1
-	void setSize(int value);
-	boost::optional<int> getOwner() const;
-	void setOwner(boost::optional<int> value);
-	const CTownInfo & getPlayerTowns() const;
-	void setPlayerTowns(const CTownInfo & value);
-	const CTownInfo & getNeutralTowns() const;
-	void setNeutralTowns(const CTownInfo & value);
-	bool getTownsAreSameType() const; /// Default: false
-	void setTownsAreSameType(bool value);
-	const std::set<TFaction> & getTownTypes() const; /// Default: all
-	void setTownTypes(const std::set<TFaction> & value);
-	void setMonsterTypes(const std::set<TFaction> & value);
-	std::set<TFaction> getDefaultTownTypes() const;
-	bool getMatchTerrainToTown() const; /// Default: true
-	void setMatchTerrainToTown(bool value);
-	const std::set<ETerrainType> & getTerrainTypes() const; /// Default: all
-	void setTerrainTypes(const std::set<ETerrainType> & value);
-	std::set<ETerrainType> getDefaultTerrainTypes() const;
-	void setMinesAmount (TResource res, ui16 amount);
-	std::map<TResource, ui16> getMinesInfo() const;
-	void setMonsterStrength (EMonsterStrength::EMonsterStrength val);
+	void setGenPtr(CMapGenerator * Gen);
 
 	float3 getCenter() const;
 	void setCenter(const float3 &f);
@@ -198,11 +136,8 @@ public:
 	std::vector<int3> getAccessibleOffsets (const CGObjectInstance* object);
 	bool areAllTilesAvailable(CGObjectInstance* obj, int3& tile, std::set<int3>& tilesBlockedByObject) const;
 
-	void addConnection(TRmgTemplateZoneId otherZone);
 	void setQuestArtZone(CRmgTemplateZone * otherZone);
 	std::vector<TRmgTemplateZoneId> getConnections() const;
-	void addTreasureInfo(CTreasureInfo & info);
-	std::vector<CTreasureInfo> getTreasureInfo();
 	std::set<int3>* getFreePaths();
 
 	ObjectInfo getRandomObject (CTreasurePileInfo &info, ui32 desiredValue, ui32 maxValue, ui32 currentValue);
@@ -226,27 +161,13 @@ public:
 	boost::heap::priority_queue<TDistance, boost::heap::compare<NodeComparer>> createPiorityQueue();
 
 private:
-
 	CMapGenerator * gen;
 	//template info
-	TRmgTemplateZoneId id;
-	ETemplateZoneType::ETemplateZoneType type;
-	int size;
-	boost::optional<int> owner;
-	CTownInfo playerTowns, neutralTowns;
-	bool townsAreSameType;
-	std::set<TFaction> townTypes;
-	std::set<TFaction> monsterTypes;
-	bool matchTerrainToTown;
-	std::set<ETerrainType> terrainTypes;
-	std::map<TResource, ui16> mines; //obligatory mines to spawn in this zone
 
 	si32 townType;
 	ETerrainType terrainType;
 	CRmgTemplateZone * questArtZone; //artifacts required for Seer Huts will be placed here - or not if null
 
-	EMonsterStrength::EMonsterStrength zoneMonsterStrength;
-	std::vector<CTreasureInfo> treasureInfo;
 	std::vector<ObjectInfo> possibleObjects;
 	int minGuardedValue;
 
@@ -260,7 +181,6 @@ private:
 	float3 center;
 	std::set<int3> tileinfo; //irregular area assined to zone
 	std::set<int3> possibleTiles; //optimization purposes for treasure generation
-	std::vector<TRmgTemplateZoneId> connections; //list of adjacent zones
 	std::set<int3> freePaths; //core paths of free tiles that all other objects will be linked to
 
 	std::set<int3> roadNodes; //tiles to be connected with roads