Browse Source

- Remove obstacle in front of player-owned towns
- Allow obstacles to touch town object

DjWarmonger 8 years ago
parent
commit
f78b524731
3 changed files with 26 additions and 27 deletions
  1. 15 10
      lib/rmg/CMapGenerator.cpp
  2. 10 16
      lib/rmg/CRmgTemplateZone.cpp
  3. 1 1
      lib/rmg/CRmgTemplateZone.h

+ 15 - 10
lib/rmg/CMapGenerator.cpp

@@ -283,7 +283,12 @@ void CMapGenerator::fillZones()
 
 	logGlobal->infoStream() << "Started filling zones";
 
-	//initialize possible tiles before any object is actually placed
+	//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)
+		it.second->initTownType(this);
+
+	//make sure there are some free tiles in the zone
 	for (auto it : zones)
 		it.second->initFreeTiles(this);
 
@@ -294,10 +299,6 @@ void CMapGenerator::fillZones()
 
 	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<CRmgTemplateZone*> treasureZones;
 	for (auto it : zones)
 	{
@@ -532,12 +533,16 @@ void CMapGenerator::createDirectConnections()
 				guardPos = tile;
 				if (guardPos.valid())
 				{
-					setOccupied(guardPos, ETileType::FREE); //just in case monster is too weak to spawn
-					zoneA->addMonster(this, guardPos, connection.getGuardStrength(), false, true);
-					zoneB->updateDistances(this, guardPos); //place next objects away from guard in both zones
 					//zones can make paths only in their own area
-					zoneA->crunchPath(this, guardPos, posA, true, zoneA->getFreePaths()); //make connection towards our zone center
-					zoneB->crunchPath(this, guardPos, posB, true, zoneB->getFreePaths()); //make connection towards other zone center
+					zoneA->connectWithCenter(this, guardPos, true);
+					zoneB->connectWithCenter(this, guardPos, true);
+
+					bool monsterPresent = zoneA->addMonster(this, guardPos, connection.getGuardStrength(), false, true);
+					zoneB->updateDistances(this, guardPos); //place next objects away from guard in both zones
+
+					//set free tile only after connection is made to the center of the zone
+					if (!monsterPresent)
+						setOccupied(guardPos, ETileType::FREE); //just in case monster is too weak to spawn
 
 					zoneA->addRoadNode(guardPos);
 					zoneB->addRoadNode(guardPos);

+ 10 - 16
lib/rmg/CRmgTemplateZone.cpp

@@ -1319,17 +1319,11 @@ void CRmgTemplateZone::initTownType (CMapGenerator* gen)
 
 	auto cutPathAroundTown = [gen, this](const CGTownInstance * town)
 	{
-		//cut contour around town in case it was placed in a middle of path. TODO: find better solution
-		for (auto tile : town->getBlockedPos())
+		//cut contour around town entrance
+		for (auto pos: getAccessibleOffsets(gen, town))
 		{
-			gen->foreach_neighbour(tile, [gen, &tile](int3& pos)
-			{
-				if (gen->isPossible(pos))
-				{
-					gen->setOccupied(pos, ETileType::FREE);
-				}
-			});
-		}
+			gen->setOccupied(pos, ETileType::FREE);
+		};
 	};
 
 	auto addNewTowns = [&totalTowns, gen, this, &cutPathAroundTown](int count, bool hasFort, PlayerColor player)
@@ -1369,9 +1363,9 @@ void CRmgTemplateZone::initTownType (CMapGenerator* gen)
 				//register MAIN town of zone
 				gen->registerZone(town->subID);
 				//first town in zone goes in the middle
-				placeAndGuardObject(gen, town, getPos() + town->getVisitableOffset(), 0);
+				placeObject(gen, town, getPos() + town->getVisitableOffset(), true);
 				cutPathAroundTown(town);
-				setPos(town->visitablePos() + int3(0, 1, 0)); //new center of zone that paths connect to
+				setPos(town->pos + int3(0, 1, 0)); //roads lead to tile below the town
 			}
 			else
 				addRequiredObject (town);
@@ -1414,9 +1408,9 @@ void CRmgTemplateZone::initTownType (CMapGenerator* gen)
 				town->possibleSpells.push_back(spell->id);
 		}
 		//towns are big objects and should be centered around visitable position
-		placeAndGuardObject(gen, town, getPos() + town->getVisitableOffset(), 0); //generate no guards, but free path to entrance
+		placeObject(gen, town, getPos() + town->getVisitableOffset(), true);
 		cutPathAroundTown(town);
-		setPos(town->visitablePos() + int3(0, 1, 0)); //new center of zone that paths connect to
+		setPos(town->pos + int3(0, 1, 0)); //roads lead to tile below the town
 
 		totalTowns++;
 		//register MAIN town of zone only
@@ -1902,7 +1896,7 @@ bool CRmgTemplateZone::fill(CMapGenerator* gen)
 	initTerrainType(gen);
 
 	//zone center should be always clear to allow other tiles to connect
-	gen->setOccupied(this->getPos(), ETileType::FREE);
+	gen->setOccupied(pos, ETileType::FREE);
 	freePaths.insert(pos);
 
 	addAllPossibleObjects (gen);
@@ -2156,7 +2150,7 @@ void CRmgTemplateZone::placeSubterraneanGate(CMapGenerator* gen, int3 pos, si32
 	guardObject (gen, gate, guardStrength, true);
 }
 
-std::vector<int3> CRmgTemplateZone::getAccessibleOffsets (CMapGenerator* gen, CGObjectInstance* object)
+std::vector<int3> CRmgTemplateZone::getAccessibleOffsets (CMapGenerator* gen, const CGObjectInstance* object)
 {
 	//get all tiles from which this object can be accessed
 	int3 visitable = object->visitablePos();

+ 1 - 1
lib/rmg/CRmgTemplateZone.h

@@ -194,7 +194,7 @@ public:
 	bool connectWithCenter(CMapGenerator* gen, const int3& src, bool onlyStraight);
 	void updateDistances(CMapGenerator* gen, const int3 & pos);
 
-	std::vector<int3> getAccessibleOffsets (CMapGenerator* gen, CGObjectInstance* object);
+	std::vector<int3> getAccessibleOffsets (CMapGenerator* gen, const CGObjectInstance* object);
 	bool areAllTilesAvailable(CMapGenerator* gen, CGObjectInstance* obj, int3& tile, std::set<int3>& tilesBlockedByObject) const;
 
 	void addConnection(TRmgTemplateZoneId otherZone);