2022-08-09 07:54:32 +02:00
|
|
|
/*
|
|
|
|
* RoadPlacer.cpp, part of VCMI engine
|
|
|
|
*
|
|
|
|
* Authors: listed in file AUTHORS in main folder
|
|
|
|
*
|
|
|
|
* License: GNU General Public License v2.0 or later
|
|
|
|
* Full text of license available in license.txt file, in main folder
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "StdInc.h"
|
|
|
|
#include "RoadPlacer.h"
|
2022-09-04 08:54:06 +02:00
|
|
|
#include "ObjectManager.h"
|
2022-08-09 07:54:32 +02:00
|
|
|
#include "Functions.h"
|
|
|
|
#include "CMapGenerator.h"
|
|
|
|
#include "RmgMap.h"
|
|
|
|
#include "../mapping/CMap.h"
|
|
|
|
#include "../mapping/CMapEditManager.h"
|
|
|
|
#include "RmgPath.h"
|
|
|
|
|
2022-07-26 15:07:42 +02:00
|
|
|
VCMI_LIB_NAMESPACE_BEGIN
|
|
|
|
|
2022-08-09 07:54:32 +02:00
|
|
|
void RoadPlacer::process()
|
|
|
|
{
|
|
|
|
connectRoads();
|
|
|
|
}
|
|
|
|
|
|
|
|
rmg::Area & RoadPlacer::areaForRoads()
|
|
|
|
{
|
|
|
|
return areaRoads;
|
|
|
|
}
|
|
|
|
|
|
|
|
rmg::Area & RoadPlacer::areaIsolated()
|
|
|
|
{
|
|
|
|
return isolated;
|
|
|
|
}
|
|
|
|
|
|
|
|
const rmg::Area & RoadPlacer::getRoads() const
|
|
|
|
{
|
|
|
|
return roads;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool RoadPlacer::createRoad(const int3 & dst)
|
|
|
|
{
|
|
|
|
auto searchArea = zone.areaPossible() + areaRoads + zone.freePaths() - isolated + roads;
|
|
|
|
|
|
|
|
rmg::Path path(searchArea);
|
|
|
|
path.connect(roads);
|
|
|
|
|
|
|
|
auto res = path.search(dst, true);
|
|
|
|
if(!res.valid())
|
|
|
|
{
|
|
|
|
res = path.search(dst, false, [](const int3 & src, const int3 & dst)
|
|
|
|
{
|
|
|
|
float weight = dst.dist2dSQ(src);
|
|
|
|
return weight * weight;
|
|
|
|
});
|
|
|
|
if(!res.valid())
|
|
|
|
{
|
|
|
|
logGlobal->warn("Failed to create road");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
roads.unite(res.getPathArea());
|
|
|
|
return true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2022-09-04 08:54:06 +02:00
|
|
|
void RoadPlacer::drawRoads(bool secondary)
|
2022-08-09 07:54:32 +02:00
|
|
|
{
|
|
|
|
zone.areaPossible().subtract(roads);
|
|
|
|
zone.freePaths().unite(roads);
|
|
|
|
map.getEditManager()->getTerrainSelection().setSelection(roads.getTilesVector());
|
2022-09-23 16:24:01 +02:00
|
|
|
std::string roadCode = (secondary ? generator.getConfig().secondaryRoadType : generator.getConfig().defaultRoadType);
|
2022-09-29 11:44:46 +02:00
|
|
|
RoadId roadType = VLC->terrainTypeHandler->getRoadByCode(roadCode)->id;
|
2022-09-04 08:54:06 +02:00
|
|
|
map.getEditManager()->drawRoad(roadType, &generator.rand);
|
2022-08-09 07:54:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void RoadPlacer::addRoadNode(const int3& node)
|
|
|
|
{
|
|
|
|
roadNodes.insert(node);
|
|
|
|
}
|
|
|
|
|
|
|
|
void RoadPlacer::connectRoads()
|
|
|
|
{
|
2022-09-04 08:54:06 +02:00
|
|
|
bool noRoadNodes = false;
|
|
|
|
//Assumes objects are already placed
|
|
|
|
if (roadNodes.size() < 2)
|
|
|
|
{
|
|
|
|
//If there are no nodes, draw roads to mines
|
|
|
|
noRoadNodes = true;
|
|
|
|
if (auto* m = zone.getModificator<ObjectManager>())
|
|
|
|
{
|
|
|
|
for (auto object : m->getMines())
|
|
|
|
{
|
|
|
|
addRoadNode(object->visitablePos());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(roadNodes.size() < 2)
|
2022-08-09 07:54:32 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
//take any tile from road nodes as destination zone for all other road nodes
|
|
|
|
if(roads.empty())
|
|
|
|
roads.add(*roadNodes.begin());
|
|
|
|
|
|
|
|
for(auto & node : roadNodes)
|
|
|
|
{
|
|
|
|
createRoad(node);
|
|
|
|
}
|
|
|
|
|
2022-09-04 08:54:06 +02:00
|
|
|
//Draw dirt roads if there are only mines
|
|
|
|
drawRoads(noRoadNodes);
|
2022-08-09 07:54:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
char RoadPlacer::dump(const int3 & t)
|
|
|
|
{
|
|
|
|
if(roadNodes.count(t))
|
|
|
|
return '@';
|
|
|
|
if(roads.contains(t))
|
|
|
|
return '+';
|
|
|
|
if(isolated.contains(t))
|
|
|
|
return 'i';
|
|
|
|
return Modificator::dump(t);
|
|
|
|
}
|
2022-07-26 15:07:42 +02:00
|
|
|
|
|
|
|
VCMI_LIB_NAMESPACE_END
|