Bläddra i källkod

Correct placement of subterranean gates.

DjWarmonger 11 år sedan
förälder
incheckning
d118fbffe8
5 ändrade filer med 83 tillägg och 25 borttagningar
  1. 8 8
      config/rmg.json
  2. 43 12
      lib/rmg/CMapGenerator.cpp
  3. 21 3
      lib/rmg/CRmgTemplateZone.cpp
  4. 4 1
      lib/rmg/CRmgTemplateZone.h
  5. 7 1
      lib/rmg/CZonePlacer.cpp

+ 8 - 8
config/rmg.json

@@ -8,7 +8,7 @@
 		{
 			"1" :
 			{
-				"type" : "playerStart", "size" : 1, "owner" : 1,
+				"type" : "playerStart", "size" : 2, "owner" : 1,
 				"playerTowns" : { "castles" : 1 }, "neutralTowns" : { "towns" : 1 }, "townsAreSameType" : true,
 				"monsters" : "normal",
 				"mines" : {"wood" : 1, "ore" : 1, "gems" : 1, "crystal" : 1, "sulfur" : 1, "mercury" : 1},
@@ -19,7 +19,7 @@
 			},
 			"2" :
 			{
-				"type" : "playerStart", "size" : 1, "owner" : 2,
+				"type" : "playerStart", "size" : 2, "owner" : 2,
 				"playerTowns" : { "castles" : 1 }, "neutralTowns" : { "towns" : 1 }, "townsAreSameType" : true,
 				"monsters" : "normal",
 				"minesLikeZone" : 1,
@@ -27,7 +27,7 @@
 			},
 			"3" :
 			{
-				"type" : "playerStart", "size" : 1, "owner" : 3,
+				"type" : "playerStart", "size" : 2, "owner" : 3,
 				"playerTowns" : { "castles" : 1 }, "neutralTowns" : { "towns" : 1 }, "townsAreSameType" : true,
 				"monsters" : "normal",
 				"minesLikeZone" : 1,
@@ -35,7 +35,7 @@
 			},
 			"4" :
 			{
-				"type" : "playerStart", "size" : 1, "owner" : 4,
+				"type" : "playerStart", "size" : 2, "owner" : 4,
 				"playerTowns" : { "castles" : 1 }, "neutralTowns" : { "towns" : 1 }, "townsAreSameType" : true,
 				"monsters" : "normal",
 				"minesLikeZone" : 1,
@@ -43,7 +43,7 @@
 			},
 			"5" :
 			{
-				"type" : "treasure", "size" : 2, "terrainTypes" : [ "sand" ], "matchTerrainToTown" : false,
+				"type" : "treasure", "size" : 3, "terrainTypes" : [ "sand" ], "matchTerrainToTown" : false,
 				"neutralTowns" : { "castles" : 1 },
 				"monsters" : "strong",
 				"mines" : {"gold" : 2},
@@ -132,7 +132,7 @@
 		{
 			"1" :
 			{
-				"type" : "playerStart", "size" : 3, "owner" : 1,
+				"type" : "playerStart", "size" : 2, "owner" : 1,
 				"playerTowns" : { "castles" : 1 },
 				"monsters" : "normal",
 				"mines" : {"wood" : 1, "ore" : 1},
@@ -143,7 +143,7 @@
 			},
 			"2" :
 			{
-				"type" : "playerStart", "size" : 3, "owner" : 2,
+				"type" : "playerStart", "size" : 2, "owner" : 2,
 				"playerTowns" : { "castles" : 1 },
 				"monsters" : "normal",
 				"minesLikeZone" : 1,
@@ -151,7 +151,7 @@
 			},
 			"3" :
 			{
-				"type" : "playerStart", "size" : 3, "owner" : 3,
+				"type" : "playerStart", "size" : 2, "owner" : 3,
 				"playerTowns" : { "castles" : 1 },
 				"monsters" : "normal",
 				"minesLikeZone" : 1,

+ 43 - 12
lib/rmg/CMapGenerator.cpp

@@ -241,21 +241,52 @@ void CMapGenerator::createConnections()
 		auto otherZoneTiles = zoneB->getTileInfo();
 		//auto otherZoneCenter = zoneB->getPos();
 
-		for (auto tile : tiles)
+		if (zoneA->getPos().z == zoneB->getPos().z)
 		{
-			foreach_neighbour (tile, [&guardPos, tile, &otherZoneTiles](int3 &pos)
+			for (auto tile : tiles)
 			{
-				if (vstd::contains(otherZoneTiles, pos))
-					guardPos = tile;
-			});
-			if (guardPos.valid())
+				if (isBlocked(tile)) //tiles may be occupied by subterranean gates already placed
+					continue;
+				foreach_neighbour (tile, [&guardPos, tile, &otherZoneTiles, this](int3 &pos)
+				{
+					if (vstd::contains(otherZoneTiles, pos) && !this->isBlocked(pos))
+						guardPos = tile;
+				});
+				if (guardPos.valid())
+				{
+					setOccupied (guardPos, ETileType::FREE); //just in case monster is too weak to spawn
+					zoneA->addMonster (this, guardPos, connection.getGuardStrength()); //TODO: set value according to template
+					//zones can make paths only in their own area
+					zoneA->crunchPath (this, guardPos, zoneA->getPos(), zoneA->getId(), zoneA->getFreePaths()); //make connection towards our zone center
+					zoneB->crunchPath (this, guardPos, zoneB->getPos(), zoneB->getId(), zoneB->getFreePaths()); //make connection towards other zone center
+					break; //we're done with this connection
+				}
+			}
+		}
+		else //create subterranean gates between two zones
+		{	
+			//find point just in the middle
+			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
+			//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 otherTile = tile;
+			otherTile.z = posB.z;
+
+			if (vstd::contains(tiles, tile) && vstd::contains(otherZoneTiles, otherTile))
 			{
-				setOccupied (guardPos, ETileType::FREE); //just in case monster is too weak to spawn
-				zoneA->addMonster (this, guardPos, connection.getGuardStrength()); //TODO: set value according to template
-				//zones can make paths only in their own area
-				zoneA->crunchPath (this, guardPos, zoneA->getPos(), zoneA->getId(), zoneA->getFreePaths()); //make connection towards our zone center
-				zoneB->crunchPath (this, guardPos, zoneB->getPos(), zoneB->getId(), zoneB->getFreePaths()); //make connection towards other zone center
-				break; //we're done with this connection
+				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
 			}
 		}
 		if (!guardPos.valid())

+ 21 - 3
lib/rmg/CRmgTemplateZone.cpp

@@ -354,8 +354,13 @@ std::set<int3> CRmgTemplateZone::getTileInfo () const
 	return tileinfo;
 }
 
-void CRmgTemplateZone::discardDistantTiles (int distance)
+void CRmgTemplateZone::discardDistantTiles (CMapGenerator* gen, int distance)
 {
+	for (auto tile : tileinfo)
+	{
+		if (tile.dist2d(this->pos) > distance)
+			gen->setOccupied(tile, ETileType::USED);
+	}
 	vstd::erase_if (tileinfo, [distance, this](const int3 &tile) -> bool
 	{
 		return tile.dist2d(this->pos) > distance;
@@ -828,6 +833,12 @@ void CRmgTemplateZone::initTerrainType (CMapGenerator* gen)
 		terrainType = *RandomGeneratorUtil::nextItem(terrainTypes, gen->rand);
 
 	//paint zone with matching terrain
+
+	paintZoneTerrain (gen, terrainType);
+}
+
+void CRmgTemplateZone::paintZoneTerrain (CMapGenerator* gen, ETerrainType terrainType)
+{
 	std::vector<int3> tiles;
 	for (auto tile : tileinfo)
 	{
@@ -1132,9 +1143,10 @@ void CRmgTemplateZone::checkAndPlaceObject(CMapGenerator* gen, CGObjectInstance*
 
 	if (object->appearance.id == Obj::NO_OBJ)
 	{
-		auto templates = VLC->objtypeh->getHandlerFor(object->ID, object->subID)->getTemplates(gen->map->getTile(pos).terType);
+		auto terrainType = gen->map->getTile(pos).terType;
+		auto templates = VLC->objtypeh->getHandlerFor(object->ID, object->subID)->getTemplates(terrainType);
 		if (templates.empty())
-			throw rmgException(boost::to_string(boost::format("Did not find graphics for object (%d,%d) at %s") %object->ID %object->subID %pos));
+			throw rmgException(boost::to_string(boost::format("Did not find graphics for object (%d,%d) at %s (terrain %d)") %object->ID %object->subID %pos %terrainType));
 	
 		object->appearance = templates.front();
 	}
@@ -1168,6 +1180,12 @@ void CRmgTemplateZone::placeObject(CMapGenerator* gen, CGObjectInstance* object,
 	}
 }
 
+void CRmgTemplateZone::placeAndGuardObject(CMapGenerator* gen, CGObjectInstance* object, const int3 &pos, si32 str)
+{
+	placeObject(gen, object, pos);
+	guardObject(gen, object, str);
+}
+
 std::vector<int3> CRmgTemplateZone::getAccessibleOffsets (CMapGenerator* gen, CGObjectInstance* object)
 {
 	//get all tiles from which this object can be accessed

+ 4 - 1
lib/rmg/CRmgTemplateZone.h

@@ -128,7 +128,7 @@ public:
 
 	void addTile (const int3 &pos);
 	std::set<int3> getTileInfo () const;
-	void discardDistantTiles (int distance);
+	void discardDistantTiles (CMapGenerator* gen, int distance);
 
 	void addRequiredObject(CGObjectInstance * obj, si32 guardStrength=0);
 	bool addMonster(CMapGenerator* gen, int3 &pos, si32 strength);
@@ -136,6 +136,7 @@ public:
 	bool fill (CMapGenerator* gen);
 	bool placeMines (CMapGenerator* gen);
 	void initTownType (CMapGenerator* gen);
+	void paintZoneTerrain (CMapGenerator* gen, ETerrainType terrainType);
 	void initTerrainType (CMapGenerator* gen);
 	void createBorder(CMapGenerator* gen);
 	void fractalize(CMapGenerator* gen);
@@ -155,6 +156,8 @@ public:
 
 	ObjectInfo getRandomObject (CMapGenerator* gen, ui32 value);
 
+	void placeAndGuardObject(CMapGenerator* gen, CGObjectInstance* object, const int3 &pos, si32 str);
+
 private:
 	//template info
 	TRmgTemplateZoneId id;

+ 7 - 1
lib/rmg/CZonePlacer.cpp

@@ -247,7 +247,13 @@ void CZonePlacer::assignZones(shared_ptr<CMapGenOptions> mapGenOptions)
 
 		//TODO: similiar for islands
 		if (zone.second->getPos().z)
-			zone.second->discardDistantTiles(zone.second->getSize());
+		{
+			zone.second->discardDistantTiles(gen, zone.second->getSize());
+
+			//make sure that terrain inside zone is not a rock
+			//FIXME: reorder actions?
+			zone.second->paintZoneTerrain (gen, ETerrainType::SUBTERRANEAN);
+		}
 	}
 	logGlobal->infoStream() << "Finished zone colouring";
 }