浏览代码

Somewhat better gate placement, attempt to add rocky tiles to underground zones.

DjWarmonger 11 年之前
父节点
当前提交
ab748ae221
共有 4 个文件被更改,包括 85 次插入15 次删除
  1. 42 14
      lib/rmg/CMapGenerator.cpp
  2. 1 0
      lib/rmg/CMapGenerator.h
  3. 41 1
      lib/rmg/CRmgTemplateZone.cpp
  4. 1 0
      lib/rmg/CRmgTemplateZone.h

+ 42 - 14
lib/rmg/CMapGenerator.cpp

@@ -265,29 +265,50 @@ void CMapGenerator::createConnections()
 		}
 		else //create subterranean gates between two zones
 		{	
-			//find point just in the middle
+			//find point on the path between zones
 			int3 posA = zoneA->getPos();
 			int3 posB = zoneB->getPos();
 			float3 offset (posB.x - posA.x, posB.y - posA.y, 0);
 
-			offset /= posB.dist2d(posA); //get unit vector
+			float distance = posB.dist2d(posA);
+			offset /= distance; //get unit vector
+			float3 vec (0, 0, 0);
 			//use reduced size of underground zone - make sure gate does not stand on rock
-			offset *= ((posA.z ? zoneA->getSize() : zoneB->getSize()) - 2);
-			int3 tile = posA + int3(offset.x, offset.y, 0);
+			int3 tile = posA;
 			int3 otherTile = tile;
-			otherTile.z = posB.z;
 
-			if (vstd::contains(tiles, tile) && vstd::contains(otherZoneTiles, otherTile))
+			bool stop = false;
+			while (!stop)
 			{
-				auto gate1 = new CGTeleport;
-				gate1->ID = Obj::SUBTERRANEAN_GATE;
-				gate1->subID = 0;
-				zoneA->placeAndGuardObject(this, gate1, tile, connection.getGuardStrength());
-				auto gate2 = new CGTeleport(*gate1);
-				zoneB->placeAndGuardObject(this, gate2, otherTile, connection.getGuardStrength());
-
-				continue; //we are done, go to next connection
+				vec += offset;
+				tile = posA + int3(vec.x, vec.y, 0);
+				float distanceFromA = posA.dist2d(tile);
+				float distanceFromB = posB.dist2d(tile);
+				if (distanceFromA >= distance)
+					break;
+
+				//if zone is underground, gate must lay withing its (reduced) radius
+				if (distanceFromA > 3 && (!posA.z || distanceFromA < zoneA->getSize() - 2)
+					&& distanceFromB > 3 && (!posB.z ||distanceFromB < zoneB->getSize() - 2))
+				{
+					otherTile = tile;
+					otherTile.z = posB.z;
+
+					if (vstd::contains(tiles, tile) && vstd::contains(otherZoneTiles, otherTile))
+					{
+						auto gate1 = new CGTeleport;
+						gate1->ID = Obj::SUBTERRANEAN_GATE;
+						gate1->subID = 0;
+						zoneA->placeAndGuardObject(this, gate1, tile, connection.getGuardStrength());
+						auto gate2 = new CGTeleport(*gate1);
+						zoneB->placeAndGuardObject(this, gate2, otherTile, connection.getGuardStrength());
+
+						stop = true; //we are done, go to next connection
+					}
+				}
 			}
+			if (stop)
+				continue;
 		}
 		if (!guardPos.valid())
 		{
@@ -348,6 +369,13 @@ bool CMapGenerator::isFree(const int3 &tile) const
 
 	return tiles[tile.x][tile.y][tile.z].isFree();
 }
+bool CMapGenerator::isUsed(const int3 &tile) const
+{
+	if (!map->isInTheMap(tile))
+		throw  rmgException(boost::to_string(boost::format("Tile %s is outside the map") % tile));
+
+	return tiles[tile.x][tile.y][tile.z].isUsed();
+}
 void CMapGenerator::setOccupied(const int3 &tile, ETileType::ETileType state)
 {
 	if (!map->isInTheMap(tile))

+ 1 - 0
lib/rmg/CMapGenerator.h

@@ -70,6 +70,7 @@ public:
 	bool shouldBeBlocked(const int3 &tile) const;
 	bool isPossible(const int3 &tile) const;
 	bool isFree(const int3 &tile) const;
+	bool isUsed(const int3 &tile) const;
 	void setOccupied(const int3 &tile, ETileType::ETileType state);
 	CTileInfo getTile(const int3 & tile) const;
 

+ 41 - 1
lib/rmg/CRmgTemplateZone.cpp

@@ -109,6 +109,10 @@ bool CTileInfo::isFree() const
 {
 	return occupied == ETileType::FREE;
 }
+bool CTileInfo::isUsed() const
+{
+	return occupied == ETileType::USED;
+}
 void CTileInfo::setOccupied(ETileType::ETileType value)
 {
 	occupied = value;
@@ -359,7 +363,10 @@ void CRmgTemplateZone::discardDistantTiles (CMapGenerator* gen, int distance)
 	for (auto tile : tileinfo)
 	{
 		if (tile.dist2d(this->pos) > distance)
+		{
 			gen->setOccupied(tile, ETileType::USED);
+			//gen->setOccupied(tile, ETileType::BLOCKED); //fixme: crash at rendering?
+		}
 	}
 	vstd::erase_if (tileinfo, [distance, this](const int3 &tile) -> bool
 	{
@@ -935,7 +942,40 @@ void CRmgTemplateZone::createTreasures(CMapGenerator* gen)
 }
 
 void CRmgTemplateZone::createObstacles(CMapGenerator* gen)
-{
+{ 
+	if (pos.z) //underground
+	{
+		std::vector<int3> rockTiles;
+
+		for (auto tile : tileinfo)
+		{
+			bool placeRock = true;
+			if (gen->shouldBeBlocked(tile))
+			{
+				gen->foreach_neighbour (tile, [gen, &placeRock](int3 &pos)
+				{
+					if (!(gen->shouldBeBlocked(pos) || gen->isPossible(pos)))
+						placeRock = false;
+				});
+				if (placeRock)
+				{
+					rockTiles.push_back(tile);
+				}
+			}
+		}
+		gen->editManager->getTerrainSelection().setSelection(rockTiles);
+		gen->editManager->drawTerrain(ETerrainType::ROCK, &gen->rand);
+		//for (auto tile : rockTiles)
+		//{
+		//	gen->setOccupied (tile, ETileType::USED);
+		//	gen->foreach_neighbour (tile, [gen](int3 &pos)
+		//	{
+		//		if (!gen->isUsed(pos))
+		//			gen->setOccupied (pos, ETileType::BLOCKED);
+		//	});
+		//}
+	}
+
 	//get all possible obstacles for this terrain
 	for (auto primaryID : VLC->objtypeh->knownObjects()) 
 	{ 

+ 1 - 0
lib/rmg/CRmgTemplateZone.h

@@ -45,6 +45,7 @@ public:
 	bool shouldBeBlocked() const;
 	bool isPossible() const;
 	bool isFree() const;
+	bool isUsed() const;
 	void setOccupied(ETileType::ETileType value);
 	ETerrainType getTerrainType() const;
 	void setTerrainType(ETerrainType value);