From f9957569736d98ddbcbb64a31f31c94c105e72d4 Mon Sep 17 00:00:00 2001 From: DjWarmonger Date: Sat, 13 Aug 2016 19:48:44 +0200 Subject: [PATCH] First part of Subterranean Gates rework. Fixes #http://bugs.vcmi.eu/view.php?id=2450 --- lib/rmg/CMapGenerator.cpp | 69 ++++++++++++++++++++++++------------ lib/rmg/CMapGenerator.h | 5 ++- lib/rmg/CRmgTemplateZone.cpp | 4 +++ lib/rmg/CRmgTemplateZone.h | 4 ++- 4 files changed, 57 insertions(+), 25 deletions(-) diff --git a/lib/rmg/CMapGenerator.cpp b/lib/rmg/CMapGenerator.cpp index d3ed50662..42f17b6a6 100644 --- a/lib/rmg/CMapGenerator.cpp +++ b/lib/rmg/CMapGenerator.cpp @@ -272,19 +272,20 @@ void CMapGenerator::fillZones() //initialize possible tiles before any object is actually placed for (auto it : zones) - { it.second->initFreeTiles(this); - } findZonesForQuestArts(); - createConnections(); + createDirectConnections(); //direct //make sure all connections are passable before creating borders for (auto it : zones) - { - it.second->createBorder(this); - //we need info about all town types to evaluate dwellings and pandoras with creatures properly + it.second->createBorder(this); //once direct connections are done + + createConnections2(); //subterranean gates and monoliths + + //we need info about all town types to evaluate dwellings and pandoras with creatures properly + for (auto it : zones) it.second->initTownType(this); - } + std::vector treasureZones; for (auto it : zones) { @@ -462,7 +463,7 @@ void CMapGenerator::findZonesForQuestArts() } } -void CMapGenerator::createConnections() +void CMapGenerator::createDirectConnections() { for (auto connection : mapGenOptions->getMapTemplate()->getConnections()) { @@ -531,17 +532,40 @@ void CMapGenerator::createConnections() } } } - else //create subterranean gates between two zones + + if (!guardPos.valid()) + connectionsLeft.push_back(connection); + } +} + +void CMapGenerator::createConnections2() +{ + for (auto & connection : connectionsLeft) + { + auto zoneA = connection.getZoneA(); + auto zoneB = connection.getZoneB(); + + auto tileSetA = zoneA->getPossibleTiles(), + tileSetB = zoneB->getPossibleTiles(); + + std::vector tilesA(tileSetA.begin(), tileSetA.end()), + tilesB(tileSetB.begin(), tileSetB.end()); + + int3 guardPos(-1, -1, -1); + + int3 posA = zoneA->getPos(); + int3 posB = zoneB->getPos(); + auto zoneAid = zoneA->getId(); + auto zoneBid = zoneB->getId(); + + if (posA.z != posB.z) //try to place subterranean gates { //find common tiles for both zones std::vector commonTiles; - auto tileSetA = zoneA->getTileInfo(), - tileSetB = zoneB->getTileInfo(); - std::vector tilesA (tileSetA.begin(), tileSetA.end()), - tilesB (tileSetB.begin(), tileSetB.end()); + boost::sort(tilesA), - boost::sort(tilesB); + boost::sort(tilesB); boost::set_intersection(tilesA, tilesB, std::back_inserter(commonTiles), [](const int3 &lhs, const int3 &rhs) -> bool { @@ -572,25 +596,24 @@ void CMapGenerator::createConnections() if (distanceFromA > 5 && distanceFromB > 5) { //all neightbouring tiles also belong to zone - if (getZoneID(tile) == zoneAid && getZoneID(otherTile) == zoneBid) + if (getZoneID(tile) == zoneAid && getZoneID(otherTile) == zoneBid) { bool withinZone = true; - foreach_neighbour (tile, [&withinZone, &tiles, zoneAid, this](int3 &pos) + foreach_neighbour(tile, [&withinZone, zoneAid, this](int3 &pos) { if (getZoneID(pos) != zoneAid) withinZone = false; }); - foreach_neighbour (otherTile, [&withinZone, &otherZoneTiles, zoneBid, this](int3 &pos) + foreach_neighbour(otherTile, [&withinZone, zoneBid, this](int3 &pos) { if (getZoneID(pos) != zoneBid) withinZone = false; }); - - //make sure both gates has some free tiles below them - if (zoneA->getAccessibleOffset(this, sgt, tile).valid() && zoneB->getAccessibleOffset(this, sgt, otherTile).valid()) + if (withinZone) { - if (withinZone) + //make sure both gates has some free tiles below them + if (zoneA->getAccessibleOffset(this, sgt, tile).valid() && zoneB->getAccessibleOffset(this, sgt, otherTile).valid()) { zoneA->placeSubterraneanGate(this, tile, connection.getGuardStrength()); zoneB->placeSubterraneanGate(this, otherTile, connection.getGuardStrength()); @@ -609,8 +632,8 @@ void CMapGenerator::createConnections() auto teleport2 = factory->create(ObjectTemplate()); - zoneA->addRequiredObject (teleport1, connection.getGuardStrength()); - zoneB->addRequiredObject (teleport2, connection.getGuardStrength()); + zoneA->addRequiredObject(teleport1, connection.getGuardStrength()); + zoneB->addRequiredObject(teleport2, connection.getGuardStrength()); } } } diff --git a/lib/rmg/CMapGenerator.h b/lib/rmg/CMapGenerator.h index a52b0b67d..dc4acab3c 100644 --- a/lib/rmg/CMapGenerator.h +++ b/lib/rmg/CMapGenerator.h @@ -16,6 +16,7 @@ #include "CMapGenOptions.h" #include "CRmgTemplateZone.h" #include "../int3.h" +#include "CRmgTemplate.h" //for CRmgTemplateZoneConnection class CMap; class CRmgTemplate; @@ -63,7 +64,8 @@ public: CMapEditManager * editManager; std::map getZones() const; - void createConnections(); + void createDirectConnections(); + void createConnections2(); void findZonesForQuestArts(); void foreach_neighbour(const int3 &pos, std::function foo); void foreachDirectNeighbour(const int3 &pos, std::function foo); @@ -98,6 +100,7 @@ public: void setZoneID(const int3& tile, TRmgTemplateZoneId zid); private: + std::list connectionsLeft; std::map zones; std::map zonesPerFaction; ui32 zonesTotal; //zones that have their main town only diff --git a/lib/rmg/CRmgTemplateZone.cpp b/lib/rmg/CRmgTemplateZone.cpp index 5514921bc..32779aaf6 100644 --- a/lib/rmg/CRmgTemplateZone.cpp +++ b/lib/rmg/CRmgTemplateZone.cpp @@ -392,6 +392,10 @@ std::set CRmgTemplateZone::getTileInfo () const { return tileinfo; } +std::set CRmgTemplateZone::getPossibleTiles() const +{ + return possibleTiles; +} void CRmgTemplateZone::discardDistantTiles (CMapGenerator* gen, float distance) { diff --git a/lib/rmg/CRmgTemplateZone.h b/lib/rmg/CRmgTemplateZone.h index 9424cdc63..5adbf8d2d 100644 --- a/lib/rmg/CRmgTemplateZone.h +++ b/lib/rmg/CRmgTemplateZone.h @@ -23,6 +23,7 @@ class CTileInfo; class int3; class CGObjectInstance; class ObjectTemplate; +class CRmgTemplateZoneConnection; namespace ETemplateZoneType { @@ -161,7 +162,8 @@ public: void addTile (const int3 &pos); void initFreeTiles (CMapGenerator* gen); - std::set getTileInfo () const; + std::set getTileInfo() const; + std::set getPossibleTiles() const; void discardDistantTiles (CMapGenerator* gen, float distance); void clearTiles();