mirror of
https://github.com/vcmi/vcmi.git
synced 2025-08-13 19:54:17 +02:00
Merge pull request #1698 from vcmi/object_placement_tweaks
No objections, works fine for me as well.
This commit is contained in:
@@ -100,15 +100,20 @@ void ConnectionsPlacer::selfSideDirectConnection(const rmg::ZoneConnection & con
|
|||||||
borderPos = *RandomGeneratorUtil::nextItem(directConnectionIterator->second, generator.rand);
|
borderPos = *RandomGeneratorUtil::nextItem(directConnectionIterator->second, generator.rand);
|
||||||
guardPos = zone.areaPossible().nearest(borderPos);
|
guardPos = zone.areaPossible().nearest(borderPos);
|
||||||
assert(borderPos != guardPos);
|
assert(borderPos != guardPos);
|
||||||
|
|
||||||
auto safetyGap = rmg::Area({guardPos});
|
float dist = map.getTile(guardPos).getNearestObjectDistance();
|
||||||
safetyGap.unite(safetyGap.getBorderOutside());
|
if (dist >= 3) //Don't place guards at adjacent tiles
|
||||||
safetyGap.intersect(zone.areaPossible());
|
|
||||||
if(!safetyGap.empty())
|
|
||||||
{
|
{
|
||||||
safetyGap.intersect(otherZone->areaPossible());
|
|
||||||
if(safetyGap.empty())
|
auto safetyGap = rmg::Area({ guardPos });
|
||||||
break; //successfull position
|
safetyGap.unite(safetyGap.getBorderOutside());
|
||||||
|
safetyGap.intersect(zone.areaPossible());
|
||||||
|
if (!safetyGap.empty())
|
||||||
|
{
|
||||||
|
safetyGap.intersect(otherZone->areaPossible());
|
||||||
|
if (safetyGap.empty())
|
||||||
|
break; //successfull position
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//failed position
|
//failed position
|
||||||
@@ -150,6 +155,8 @@ void ConnectionsPlacer::selfSideDirectConnection(const rmg::ZoneConnection & con
|
|||||||
rmg::Object monster(*monsterType);
|
rmg::Object monster(*monsterType);
|
||||||
monster.setPosition(guardPos);
|
monster.setPosition(guardPos);
|
||||||
manager.placeObject(monster, false, true);
|
manager.placeObject(monster, false, true);
|
||||||
|
//Place objects away from the monster in the other zone, too
|
||||||
|
otherZone->getModificator<ObjectManager>()->updateDistances(monster);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -225,8 +232,10 @@ void ConnectionsPlacer::selfSideIndirectConnection(const rmg::ZoneConnection & c
|
|||||||
rmg::Path path1 = manager.placeAndConnectObject(commonArea, rmgGate1, [this, minDist, &path2, &rmgGate1, &zShift, guarded2, &managerOther, &rmgGate2 ](const int3 & tile)
|
rmg::Path path1 = manager.placeAndConnectObject(commonArea, rmgGate1, [this, minDist, &path2, &rmgGate1, &zShift, guarded2, &managerOther, &rmgGate2 ](const int3 & tile)
|
||||||
{
|
{
|
||||||
auto ti = map.getTile(tile);
|
auto ti = map.getTile(tile);
|
||||||
|
auto otherTi = map.getTile(tile - zShift);
|
||||||
float dist = ti.getNearestObjectDistance();
|
float dist = ti.getNearestObjectDistance();
|
||||||
if(dist < minDist)
|
float otherDist = otherTi.getNearestObjectDistance();
|
||||||
|
if(dist < minDist || otherDist < minDist)
|
||||||
return -1.f;
|
return -1.f;
|
||||||
|
|
||||||
rmg::Area toPlace(rmgGate1.getArea() + rmgGate1.getAccessibleArea());
|
rmg::Area toPlace(rmgGate1.getArea() + rmgGate1.getAccessibleArea());
|
||||||
@@ -234,8 +243,8 @@ void ConnectionsPlacer::selfSideIndirectConnection(const rmg::ZoneConnection & c
|
|||||||
|
|
||||||
path2 = managerOther.placeAndConnectObject(toPlace, rmgGate2, minDist, guarded2, true, ObjectManager::OptimizeType::NONE);
|
path2 = managerOther.placeAndConnectObject(toPlace, rmgGate2, minDist, guarded2, true, ObjectManager::OptimizeType::NONE);
|
||||||
|
|
||||||
return path2.valid() ? 1.f : -1.f;
|
return path2.valid() ? (dist + otherDist) : -1.f;
|
||||||
}, guarded1, true, ObjectManager::OptimizeType::NONE);
|
}, guarded1, true, ObjectManager::OptimizeType::DISTANCE);
|
||||||
|
|
||||||
if(path1.valid() && path2.valid())
|
if(path1.valid() && path2.valid())
|
||||||
{
|
{
|
||||||
|
@@ -209,24 +209,28 @@ bool WaterProxy::placeBoat(Zone & land, const Lake & lake, RouteInfo & info)
|
|||||||
auto * manager = zone.getModificator<ObjectManager>();
|
auto * manager = zone.getModificator<ObjectManager>();
|
||||||
if(!manager)
|
if(!manager)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
auto subObjects = VLC->objtypeh->knownSubObjects(Obj::BOAT);
|
auto subObjects = VLC->objtypeh->knownSubObjects(Obj::BOAT);
|
||||||
auto * boat = dynamic_cast<CGBoat *>(VLC->objtypeh->getHandlerFor(Obj::BOAT, *RandomGeneratorUtil::nextItem(subObjects, generator.rand))->create());
|
auto * boat = dynamic_cast<CGBoat *>(VLC->objtypeh->getHandlerFor(Obj::BOAT, *RandomGeneratorUtil::nextItem(subObjects, generator.rand))->create());
|
||||||
|
|
||||||
rmg::Object rmgObject(*boat);
|
rmg::Object rmgObject(*boat);
|
||||||
rmgObject.setTemplate(zone.getTerrainType());
|
rmgObject.setTemplate(zone.getTerrainType());
|
||||||
|
|
||||||
auto waterAvailable = zone.areaPossible() + zone.freePaths();
|
auto waterAvailable = zone.areaPossible() + zone.freePaths();
|
||||||
rmg::Area coast = lake.neighbourZones.at(land.getId()); //having land tiles
|
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.areaPossible() + land.freePaths()); //having only available land tiles
|
||||||
auto boardingPositions = coast.getSubarea([&waterAvailable](const int3 & tile) //tiles where boarding is possible
|
auto boardingPositions = coast.getSubarea([&waterAvailable, this](const int3 & tile) //tiles where boarding is possible
|
||||||
{
|
{
|
||||||
rmg::Area a({tile});
|
//We don't want place boat right to any land object, especiallly the zone guard
|
||||||
a = a.getBorderOutside();
|
if (map.getTile(tile).getNearestObjectDistance() <= 3)
|
||||||
a.intersect(waterAvailable);
|
return false;
|
||||||
return !a.empty();
|
|
||||||
});
|
rmg::Area a({tile});
|
||||||
|
a = a.getBorderOutside();
|
||||||
|
a.intersect(waterAvailable);
|
||||||
|
return !a.empty();
|
||||||
|
});
|
||||||
|
|
||||||
while(!boardingPositions.empty())
|
while(!boardingPositions.empty())
|
||||||
{
|
{
|
||||||
auto boardingPosition = *boardingPositions.getTiles().begin();
|
auto boardingPosition = *boardingPositions.getTiles().begin();
|
||||||
@@ -239,27 +243,28 @@ bool WaterProxy::placeBoat(Zone & land, const Lake & lake, RouteInfo & info)
|
|||||||
boardingPositions.erase(boardingPosition);
|
boardingPositions.erase(boardingPosition);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
//try to place boat at water, create paths on water and land
|
//try to place boat at water, create paths on water and land
|
||||||
auto path = manager->placeAndConnectObject(shipPositions, rmgObject, 2, false, true, ObjectManager::OptimizeType::NONE);
|
auto path = manager->placeAndConnectObject(shipPositions, rmgObject, 4, false, true, ObjectManager::OptimizeType::NONE);
|
||||||
auto landPath = land.searchPath(boardingPosition, false);
|
auto landPath = land.searchPath(boardingPosition, false);
|
||||||
if(!path.valid() || !landPath.valid())
|
if(!path.valid() || !landPath.valid())
|
||||||
{
|
{
|
||||||
boardingPositions.erase(boardingPosition);
|
boardingPositions.erase(boardingPosition);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
info.blocked = rmgObject.getArea();
|
info.blocked = rmgObject.getArea();
|
||||||
info.visitable = rmgObject.getVisitablePosition();
|
info.visitable = rmgObject.getVisitablePosition();
|
||||||
info.boarding = boardingPosition;
|
info.boarding = boardingPosition;
|
||||||
info.water = shipPositions;
|
info.water = shipPositions;
|
||||||
|
|
||||||
zone.connectPath(path);
|
zone.connectPath(path);
|
||||||
land.connectPath(landPath);
|
land.connectPath(landPath);
|
||||||
manager->placeObject(rmgObject, false, true);
|
manager->placeObject(rmgObject, false, true);
|
||||||
|
land.getModificator<ObjectManager>()->updateDistances(rmgObject); //Keep land objects away from the boat
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return !boardingPositions.empty();
|
return !boardingPositions.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user