瀏覽代碼

Merge pull request #3596 from vcmi/fixes_for_water

Fixes for RMG water
Ivan Savenko 1 年之前
父節點
當前提交
f1a8e78f0b
共有 4 個文件被更改,包括 34 次插入19 次删除
  1. 3 2
      config/randomMap.json
  2. 3 3
      lib/rmg/CZonePlacer.cpp
  3. 20 10
      lib/rmg/Zone.cpp
  4. 8 4
      lib/rmg/modificators/ObjectManager.cpp

+ 3 - 2
config/randomMap.json

@@ -3,8 +3,9 @@
   {
     "treasure" :
     [
-        { "min" : 2000, "max" : 6000, "density" : 1 },
-        { "min" : 100, "max" : 1000, "density" : 5 }
+        { "min" : 4000, "max" : 12000, "density" : 1 },
+        { "min" : 1000, "max" : 4000, "density" : 3 },
+        { "min" : 100, "max" : 1000, "density" : 6 }
     ],
     "shipyard" :
     {

+ 3 - 3
lib/rmg/CZonePlacer.cpp

@@ -908,7 +908,7 @@ void CZonePlacer::assignZones(CRandomGenerator * rand)
 		vertexMapping[closestZone].insert(int3(vertex.x() * width, vertex.y() * height, closestZone->getPos().z)); //Closest vertex belongs to zone
 	}
 
-	//Assign actual tiles to each zone using nonlinear norm for fine edges
+	//Assign actual tiles to each zone
 	for (pos.z = 0; pos.z < levels; pos.z++)
 	{
 		for (pos.x = 0; pos.x < width; pos.x++)
@@ -918,7 +918,6 @@ void CZonePlacer::assignZones(CRandomGenerator * rand)
 				distances.clear();
 				for(const auto & zoneVertex : vertexMapping)
 				{
-					// FIXME: Find closest vertex, not closest zone
 					auto zone = zoneVertex.first;
 					for (const auto & vertex : zoneVertex.second)
 					{
@@ -929,7 +928,8 @@ void CZonePlacer::assignZones(CRandomGenerator * rand)
 					}
 				}
 
-				auto closestZone = boost::min_element(distances, simpleCompareByDistance)->first; //closest tile belongs to zone
+				//Tile closes to vertex belongs to zone
+				auto closestZone = boost::min_element(distances, simpleCompareByDistance)->first;
 				closestZone->area().add(pos);
 				map.setZoneID(pos, closestZone->getId());
 			}

+ 20 - 10
lib/rmg/Zone.cpp

@@ -116,6 +116,7 @@ void Zone::initFreeTiles()
 	
 	if(dAreaFree.empty())
 	{
+		// Fixme: This might fail fot water zone, which doesn't need to have a tile in its center of the mass
 		dAreaPossible.erase(pos);
 		dAreaFree.add(pos); //zone must have at least one free tile where other paths go - for instance in the center
 	}
@@ -250,21 +251,30 @@ void Zone::fractalize()
 		treasureDensity += t.density;
 	}
 
-	if (treasureValue > 400)
+	if (getType() == ETemplateZoneType::WATER)
 	{
-		// A quater at max density
-		marginFactor = (0.25f + ((std::max(0, (600 - treasureValue))) / (600.f - 400)) * 0.75f);
+		// Set very little obstacles on water
+		spanFactor = 0.2;
 	}
-	else if (treasureValue < 125)
+	else //Scale with treasure density
 	{
-		//Dense obstacles
-		spanFactor *= (treasureValue / 125.f);
-		vstd::amax(spanFactor, 0.15f);
+		if (treasureValue > 400)
+		{
+			// A quater at max density
+			marginFactor = (0.25f + ((std::max(0, (600 - treasureValue))) / (600.f - 400)) * 0.75f);
+		}
+		else if (treasureValue < 125)
+		{
+			//Dense obstacles
+			spanFactor *= (treasureValue / 125.f);
+			vstd::amax(spanFactor, 0.15f);
+		}
+		if (treasureDensity <= 10)
+		{
+			vstd::amin(spanFactor, 0.1f + 0.01f * treasureDensity); //Add extra obstacles to fill up space
 	}
-	if (treasureDensity <= 10)
-	{
-		vstd::amin(spanFactor, 0.1f + 0.01f * treasureDensity); //Add extra obstacles to fill up space
 	}
+
 	float blockDistance = minDistance * spanFactor; //More obstacles in the Underground
 	freeDistance = freeDistance * marginFactor;
 	vstd::amax(freeDistance, 4 * 4);

+ 8 - 4
lib/rmg/modificators/ObjectManager.cpp

@@ -579,11 +579,15 @@ void ObjectManager::placeObject(rmg::Object & object, bool guarded, bool updateD
 
 		for (auto id : adjacentZones)
 		{
-			auto manager = map.getZones().at(id)->getModificator<ObjectManager>();
-			if (manager)
+			auto otherZone = map.getZones().at(id);
+			if ((otherZone->getType() == ETemplateZoneType::WATER) == (zone.getType()	== ETemplateZoneType::WATER))
 			{
-				// TODO: Update distances for perimeter of guarded object, not just treasures
-				manager->updateDistances(object);
+				// Do not update other zone if only one is water
+				auto manager = otherZone->getModificator<ObjectManager>();
+				if (manager)
+				{
+					manager->updateDistances(object);
+				}
 			}
 		}
 	}