mirror of
https://github.com/vcmi/vcmi.git
synced 2025-03-19 21:10:12 +02:00
Implement curved paths for all road node objects
This commit is contained in:
parent
9277c5f4e7
commit
f95bb58433
@ -24,6 +24,23 @@
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
void replaceWithCurvedPath(rmg::Path & path, const Zone & zone, const int3 & src)
|
||||
{
|
||||
auto costFunction = rmg::Path::createCurvedCostFunction(zone.area()->getBorder());
|
||||
auto pathArea = zone.areaForRoads();
|
||||
rmg::Path curvedPath(pathArea);
|
||||
curvedPath.connect(zone.freePaths().get());
|
||||
curvedPath = curvedPath.search(src, false, costFunction);
|
||||
if (curvedPath.valid())
|
||||
{
|
||||
path = curvedPath;
|
||||
}
|
||||
else
|
||||
{
|
||||
logGlobal->warn("Failed to create curved path to %s", src.toString());
|
||||
}
|
||||
}
|
||||
|
||||
rmg::Tileset collectDistantTiles(const Zone& zone, int distance)
|
||||
{
|
||||
uint32_t distanceSq = distance * distance;
|
||||
|
@ -34,6 +34,8 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
void replaceWithCurvedPath(rmg::Path & path, const Zone & zone, const int3 & src);
|
||||
|
||||
rmg::Tileset collectDistantTiles(const Zone & zone, int distance);
|
||||
|
||||
int chooseRandomAppearance(vstd::RNG & generator, si32 ObjID, TerrainId terrain);
|
||||
|
@ -121,6 +121,11 @@ ThreadSafeProxy<const rmg::Area> Zone::areaUsed() const
|
||||
return ThreadSafeProxy<const rmg::Area>(dAreaUsed, areaMutex);
|
||||
}
|
||||
|
||||
rmg::Area Zone::areaForRoads() const
|
||||
{
|
||||
return areaPossible() + freePaths();
|
||||
}
|
||||
|
||||
void Zone::clearTiles()
|
||||
{
|
||||
Lock lock(areaMutex);
|
||||
|
@ -92,6 +92,8 @@ public:
|
||||
ThreadSafeProxy<const rmg::Area> freePaths() const;
|
||||
ThreadSafeProxy<rmg::Area> areaUsed();
|
||||
ThreadSafeProxy<const rmg::Area> areaUsed() const;
|
||||
|
||||
rmg::Area areaForRoads() const;
|
||||
|
||||
void initFreeTiles();
|
||||
void clearTiles();
|
||||
|
@ -185,8 +185,8 @@ void ConnectionsPlacer::selfSideDirectConnection(const rmg::ZoneConnection & con
|
||||
return 1.f / (1.f + border.distanceSqr(d));
|
||||
};
|
||||
|
||||
auto ourArea = zone.areaPossible() + zone.freePaths();
|
||||
auto theirArea = otherZone->areaPossible() + otherZone->freePaths();
|
||||
auto ourArea = zone.areaForRoads();
|
||||
auto theirArea = otherZone->areaForRoads();
|
||||
theirArea.add(potentialPos);
|
||||
rmg::Path ourPath(ourArea);
|
||||
rmg::Path theirPath(theirArea);
|
||||
@ -285,9 +285,8 @@ void ConnectionsPlacer::selfSideDirectConnection(const rmg::ZoneConnection & con
|
||||
auto localCostFunction = rmg::Path::createCurvedCostFunction(zone.area()->getBorder());
|
||||
auto otherCostFunction = rmg::Path::createCurvedCostFunction(otherZone->area()->getBorder());
|
||||
|
||||
// TODO: helper function for this sum?
|
||||
auto ourArea = zone.areaPossible() + zone.freePaths();
|
||||
auto theirArea = otherZone->areaPossible() + otherZone->freePaths();
|
||||
auto ourArea = zone.areaForRoads();
|
||||
auto theirArea = otherZone->areaForRoads();
|
||||
theirArea.add(guardPos);
|
||||
rmg::Path ourPath(ourArea);
|
||||
rmg::Path theirPath(theirArea);
|
||||
@ -417,11 +416,15 @@ void ConnectionsPlacer::selfSideIndirectConnection(const rmg::ZoneConnection & c
|
||||
|
||||
if(path1.valid() && path2.valid())
|
||||
{
|
||||
zone.connectPath(path1);
|
||||
otherZone->connectPath(path2);
|
||||
|
||||
manager.placeObject(rmgGate1, guarded1, true, allowRoad);
|
||||
managerOther.placeObject(rmgGate2, guarded2, true, allowRoad);
|
||||
|
||||
// FIXME: Guard can still be placed on the object
|
||||
replaceWithCurvedPath(path1, zone, rmgGate1.getVisitablePosition());
|
||||
replaceWithCurvedPath(path2, *otherZone, rmgGate2.getVisitablePosition());
|
||||
|
||||
zone.connectPath(path1);
|
||||
otherZone->connectPath(path2);
|
||||
|
||||
assert(otherZone->getModificator<ConnectionsPlacer>());
|
||||
otherZone->getModificator<ConnectionsPlacer>()->otherSideConnection(connection);
|
||||
|
@ -344,7 +344,7 @@ rmg::Path ObjectManager::placeAndConnectObject(const rmg::Area & searchArea, rmg
|
||||
{
|
||||
int3 pos;
|
||||
auto possibleArea = searchArea;
|
||||
auto cachedArea = zone.areaPossible() + zone.freePaths();
|
||||
auto cachedArea = zone.areaForRoads();
|
||||
while(true)
|
||||
{
|
||||
pos = findPlaceForObject(possibleArea, obj, weightFunction, optimizer);
|
||||
@ -420,9 +420,7 @@ bool ObjectManager::createMonoliths()
|
||||
}
|
||||
|
||||
// Once it can be created, replace with curved path
|
||||
auto costFunction = rmg::Path::createCurvedCostFunction(zone.area()->getBorder());
|
||||
rmg::Path curvedPath(zone.areaPossible() + zone.freePaths());
|
||||
path = curvedPath.search(rmgObject.getVisitablePosition(), true, costFunction);
|
||||
replaceWithCurvedPath(path, zone, rmgObject.getVisitablePosition());
|
||||
|
||||
zone.connectPath(path);
|
||||
placeObject(rmgObject, guarded, true, objInfo.createRoad);
|
||||
@ -457,20 +455,7 @@ bool ObjectManager::createRequiredObjects()
|
||||
if (objInfo.createRoad)
|
||||
{
|
||||
// Once valid path can be created, replace with curved path
|
||||
|
||||
auto costFunction = rmg::Path::createCurvedCostFunction(zone.area()->getBorder());
|
||||
auto pathArea = zone.areaPossible() + zone.freePaths();
|
||||
rmg::Path curvedPath(pathArea);
|
||||
curvedPath.connect(zone.freePaths().get());
|
||||
curvedPath = curvedPath.search(rmgObject.getVisitablePosition(), false, costFunction);
|
||||
if (curvedPath.valid())
|
||||
{
|
||||
path = curvedPath;
|
||||
}
|
||||
else
|
||||
{
|
||||
logGlobal->warn("Failed to create curved path for required object at %s", rmgObject.getPosition().toString());
|
||||
}
|
||||
replaceWithCurvedPath(path, zone, rmgObject.getVisitablePosition());
|
||||
}
|
||||
|
||||
zone.connectPath(path);
|
||||
|
@ -212,7 +212,7 @@ void RiverPlacer::preprocess()
|
||||
{
|
||||
auto river = VLC->terrainTypeHandler->getById(zone.getTerrainType())->river;
|
||||
auto & a = neighbourZonesTiles[connectedToWaterZoneId];
|
||||
auto availableArea = zone.areaPossible() + zone.freePaths();
|
||||
auto availableArea = zone.areaForRoads();
|
||||
for(const auto & tileToProcess : availableArea.getTilesVector())
|
||||
{
|
||||
int templateId = -1;
|
||||
|
@ -266,9 +266,9 @@ bool WaterProxy::placeBoat(Zone & land, const Lake & lake, bool createRoad, Rout
|
||||
rmg::Object rmgObject(*boat);
|
||||
rmgObject.setTemplate(zone.getTerrainType(), zone.getRand());
|
||||
|
||||
auto waterAvailable = zone.areaPossible() + zone.freePaths();
|
||||
auto waterAvailable = zone.areaForRoads();
|
||||
rmg::Area coast = lake.neighbourZones.at(land.getId()); //having land tiles
|
||||
coast.intersect(land.areaPossible() + land.freePaths()); //having only available land tiles
|
||||
coast.intersect(land.areaForRoads()); //having only available land tiles
|
||||
auto boardingPositions = coast.getSubarea([&waterAvailable, this](const int3 & tile) //tiles where boarding is possible
|
||||
{
|
||||
//We don't want place boat right to any land object, especiallly the zone guard
|
||||
@ -332,10 +332,10 @@ bool WaterProxy::placeShipyard(Zone & land, const Lake & lake, si32 guard, bool
|
||||
rmgObject.setTemplate(land.getTerrainType(), zone.getRand());
|
||||
bool guarded = manager->addGuard(rmgObject, guard);
|
||||
|
||||
auto waterAvailable = zone.areaPossible() + zone.freePaths();
|
||||
auto waterAvailable = zone.areaForRoads();
|
||||
waterAvailable.intersect(lake.area);
|
||||
rmg::Area coast = lake.neighbourZones.at(land.getId()); //having land tiles
|
||||
coast.intersect(land.areaPossible() + land.freePaths()); //having only available land tiles
|
||||
coast.intersect(land.areaForRoads()); //having only available land tiles
|
||||
auto boardingPositions = coast.getSubarea([&waterAvailable](const int3 & tile) //tiles where boarding is possible
|
||||
{
|
||||
rmg::Area a({tile});
|
||||
|
Loading…
x
Reference in New Issue
Block a user