mirror of
https://github.com/vcmi/vcmi.git
synced 2025-04-15 11:46:56 +02:00
Merge pull request #4341 from vcmi/force_portal_connection
Add RMG connection option "forcePortal"
This commit is contained in:
commit
65af198fbf
@ -99,7 +99,7 @@
|
|||||||
"type":
|
"type":
|
||||||
{
|
{
|
||||||
"type" : "string",
|
"type" : "string",
|
||||||
"enum" : ["wide", "fictive", "repulsive"]
|
"enum" : ["wide", "fictive", "repulsive", "forcePortal"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -38,7 +38,7 @@
|
|||||||
{ "a" : "zoneA", "b" : "zoneB", "guard" : 5000, "road" : "false" },
|
{ "a" : "zoneA", "b" : "zoneB", "guard" : 5000, "road" : "false" },
|
||||||
{ "a" : "zoneA", "b" : "zoneC", "guard" : 5000, "road" : "random" },
|
{ "a" : "zoneA", "b" : "zoneC", "guard" : 5000, "road" : "random" },
|
||||||
{ "a" : "zoneB", "b" : "zoneC", "type" : "wide" }
|
{ "a" : "zoneB", "b" : "zoneC", "type" : "wide" }
|
||||||
//"type" can be "guarded" (default), "wide", "fictive" or "repulsive"
|
//"type" can be "guarded" (default), "wide", "fictive", "repulsive" or "forcePortal"
|
||||||
//"wide" connections have no border, or guard. "fictive" and "repulsive" connections are virtual -
|
//"wide" connections have no border, or guard. "fictive" and "repulsive" connections are virtual -
|
||||||
//they do not create actual path, but only attract or repulse zones, respectively
|
//they do not create actual path, but only attract or repulse zones, respectively
|
||||||
]
|
]
|
||||||
|
@ -463,7 +463,8 @@ void ZoneConnection::serializeJson(JsonSerializeFormat & handler)
|
|||||||
"guarded",
|
"guarded",
|
||||||
"fictive",
|
"fictive",
|
||||||
"repulsive",
|
"repulsive",
|
||||||
"wide"
|
"wide",
|
||||||
|
"forcePortal"
|
||||||
};
|
};
|
||||||
|
|
||||||
static const std::vector<std::string> roadOptions =
|
static const std::vector<std::string> roadOptions =
|
||||||
|
@ -75,7 +75,8 @@ enum class EConnectionType
|
|||||||
GUARDED = 0, //default
|
GUARDED = 0, //default
|
||||||
FICTIVE,
|
FICTIVE,
|
||||||
REPULSIVE,
|
REPULSIVE,
|
||||||
WIDE
|
WIDE,
|
||||||
|
FORCE_PORTAL
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class ERoadOption
|
enum class ERoadOption
|
||||||
|
@ -80,12 +80,21 @@ void CZonePlacer::findPathsBetweenZones()
|
|||||||
|
|
||||||
for (auto & connection : connectedZoneIds)
|
for (auto & connection : connectedZoneIds)
|
||||||
{
|
{
|
||||||
if (connection.getConnectionType() == rmg::EConnectionType::REPULSIVE)
|
switch (connection.getConnectionType())
|
||||||
{
|
{
|
||||||
//Do not consider virtual connections for graph distance
|
//Do not consider virtual connections for graph distance
|
||||||
continue;
|
case rmg::EConnectionType::REPULSIVE:
|
||||||
|
case rmg::EConnectionType::FORCE_PORTAL:
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
auto neighbor = connection.getOtherZoneId(current);
|
auto neighbor = connection.getOtherZoneId(current);
|
||||||
|
|
||||||
|
if (current == neighbor)
|
||||||
|
{
|
||||||
|
//Do not consider self-connections
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (!visited[neighbor])
|
if (!visited[neighbor])
|
||||||
{
|
{
|
||||||
visited[neighbor] = true;
|
visited[neighbor] = true;
|
||||||
@ -552,8 +561,16 @@ void CZonePlacer::attractConnectedZones(TZoneMap & zones, TForceVector & forces,
|
|||||||
|
|
||||||
for (const auto & connection : zone.second->getConnections())
|
for (const auto & connection : zone.second->getConnections())
|
||||||
{
|
{
|
||||||
if (connection.getConnectionType() == rmg::EConnectionType::REPULSIVE)
|
switch (connection.getConnectionType())
|
||||||
{
|
{
|
||||||
|
//Do not consider virtual connections for graph distance
|
||||||
|
case rmg::EConnectionType::REPULSIVE:
|
||||||
|
case rmg::EConnectionType::FORCE_PORTAL:
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (connection.getZoneA() == connection.getZoneB())
|
||||||
|
{
|
||||||
|
//Do not consider self-connections
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -710,11 +727,19 @@ void CZonePlacer::moveOneZone(TZoneMap& zones, TForceVector& totalForces, TDista
|
|||||||
std::set<TRmgTemplateZoneId> connectedZones;
|
std::set<TRmgTemplateZoneId> connectedZones;
|
||||||
for (const auto& connection : firstZone->getConnections())
|
for (const auto& connection : firstZone->getConnections())
|
||||||
{
|
{
|
||||||
//FIXME: Should we also exclude fictive connections?
|
switch (connection.getConnectionType())
|
||||||
if (connection.getConnectionType() != rmg::EConnectionType::REPULSIVE)
|
|
||||||
{
|
{
|
||||||
connectedZones.insert(connection.getOtherZoneId(firstZone->getId()));
|
//Do not consider virtual connections for graph distance
|
||||||
|
case rmg::EConnectionType::REPULSIVE:
|
||||||
|
case rmg::EConnectionType::FORCE_PORTAL:
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
if (connection.getZoneA() == connection.getZoneB())
|
||||||
|
{
|
||||||
|
//Do not consider self-connections
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
connectedZones.insert(connection.getOtherZoneId(firstZone->getId()));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto level = firstZone->getCenter().z;
|
auto level = firstZone->getCenter().z;
|
||||||
|
@ -55,6 +55,17 @@ void ConnectionsPlacer::process()
|
|||||||
{
|
{
|
||||||
for (auto& c : dConnections)
|
for (auto& c : dConnections)
|
||||||
{
|
{
|
||||||
|
if (c.getZoneA() == c.getZoneB())
|
||||||
|
{
|
||||||
|
// Zone can always be connected to itself, but only by monolith pair
|
||||||
|
RecursiveLock lock(externalAccessMutex);
|
||||||
|
if (!vstd::contains(dCompleted, c))
|
||||||
|
{
|
||||||
|
placeMonolithConnection(c);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
auto otherZone = map.getZones().at(c.getZoneB());
|
auto otherZone = map.getZones().at(c.getZoneB());
|
||||||
auto* cp = otherZone->getModificator<ConnectionsPlacer>();
|
auto* cp = otherZone->getModificator<ConnectionsPlacer>();
|
||||||
|
|
||||||
@ -74,6 +85,11 @@ void ConnectionsPlacer::process()
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
diningPhilosophers([this](const rmg::ZoneConnection& c)
|
||||||
|
{
|
||||||
|
forcePortalConnection(c);
|
||||||
|
});
|
||||||
|
|
||||||
diningPhilosophers([this](const rmg::ZoneConnection& c)
|
diningPhilosophers([this](const rmg::ZoneConnection& c)
|
||||||
{
|
{
|
||||||
selfSideDirectConnection(c);
|
selfSideDirectConnection(c);
|
||||||
@ -115,6 +131,15 @@ void ConnectionsPlacer::otherSideConnection(const rmg::ZoneConnection & connecti
|
|||||||
dCompleted.push_back(connection);
|
dCompleted.push_back(connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ConnectionsPlacer::forcePortalConnection(const rmg::ZoneConnection & connection)
|
||||||
|
{
|
||||||
|
// This should always succeed
|
||||||
|
if (connection.getConnectionType() == rmg::EConnectionType::FORCE_PORTAL)
|
||||||
|
{
|
||||||
|
placeMonolithConnection(connection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ConnectionsPlacer::selfSideDirectConnection(const rmg::ZoneConnection & connection)
|
void ConnectionsPlacer::selfSideDirectConnection(const rmg::ZoneConnection & connection)
|
||||||
{
|
{
|
||||||
bool success = false;
|
bool success = false;
|
||||||
@ -410,23 +435,30 @@ void ConnectionsPlacer::selfSideIndirectConnection(const rmg::ZoneConnection & c
|
|||||||
//4. place monoliths/portals
|
//4. place monoliths/portals
|
||||||
if(!success)
|
if(!success)
|
||||||
{
|
{
|
||||||
auto factory = VLC->objtypeh->getHandlerFor(Obj::MONOLITH_TWO_WAY, generator.getNextMonlithIndex());
|
placeMonolithConnection(connection);
|
||||||
auto * teleport1 = factory->create(map.mapInstance->cb, nullptr);
|
|
||||||
auto * teleport2 = factory->create(map.mapInstance->cb, nullptr);
|
|
||||||
|
|
||||||
RequiredObjectInfo obj1(teleport1, connection.getGuardStrength(), allowRoad);
|
|
||||||
RequiredObjectInfo obj2(teleport2, connection.getGuardStrength(), allowRoad);
|
|
||||||
zone.getModificator<ObjectManager>()->addRequiredObject(obj1);
|
|
||||||
otherZone->getModificator<ObjectManager>()->addRequiredObject(obj2);
|
|
||||||
|
|
||||||
assert(otherZone->getModificator<ConnectionsPlacer>());
|
|
||||||
otherZone->getModificator<ConnectionsPlacer>()->otherSideConnection(connection);
|
|
||||||
|
|
||||||
success = true;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConnectionsPlacer::placeMonolithConnection(const rmg::ZoneConnection & connection)
|
||||||
|
{
|
||||||
|
auto otherZoneId = (connection.getZoneA() == zone.getId() ? connection.getZoneB() : connection.getZoneA());
|
||||||
|
auto & otherZone = map.getZones().at(otherZoneId);
|
||||||
|
|
||||||
|
bool allowRoad = shouldGenerateRoad(connection);
|
||||||
|
|
||||||
|
auto factory = VLC->objtypeh->getHandlerFor(Obj::MONOLITH_TWO_WAY, generator.getNextMonlithIndex());
|
||||||
|
auto * teleport1 = factory->create(map.mapInstance->cb, nullptr);
|
||||||
|
auto * teleport2 = factory->create(map.mapInstance->cb, nullptr);
|
||||||
|
|
||||||
|
RequiredObjectInfo obj1(teleport1, connection.getGuardStrength(), allowRoad);
|
||||||
|
RequiredObjectInfo obj2(teleport2, connection.getGuardStrength(), allowRoad);
|
||||||
|
zone.getModificator<ObjectManager>()->addRequiredObject(obj1);
|
||||||
|
otherZone->getModificator<ObjectManager>()->addRequiredObject(obj2);
|
||||||
|
|
||||||
|
dCompleted.push_back(connection);
|
||||||
|
|
||||||
if(success)
|
assert(otherZone->getModificator<ConnectionsPlacer>());
|
||||||
dCompleted.push_back(connection);
|
otherZone->getModificator<ConnectionsPlacer>()->otherSideConnection(connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConnectionsPlacer::collectNeighbourZones()
|
void ConnectionsPlacer::collectNeighbourZones()
|
||||||
|
@ -23,7 +23,8 @@ public:
|
|||||||
void init() override;
|
void init() override;
|
||||||
|
|
||||||
void addConnection(const rmg::ZoneConnection& connection);
|
void addConnection(const rmg::ZoneConnection& connection);
|
||||||
|
void placeMonolithConnection(const rmg::ZoneConnection& connection);
|
||||||
|
void forcePortalConnection(const rmg::ZoneConnection & connection);
|
||||||
void selfSideDirectConnection(const rmg::ZoneConnection & connection);
|
void selfSideDirectConnection(const rmg::ZoneConnection & connection);
|
||||||
void selfSideIndirectConnection(const rmg::ZoneConnection & connection);
|
void selfSideIndirectConnection(const rmg::ZoneConnection & connection);
|
||||||
void otherSideConnection(const rmg::ZoneConnection & connection);
|
void otherSideConnection(const rmg::ZoneConnection & connection);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user