fiexed virtuel entry nodes so they will be considered equal to all other Nodes
clang PCH / build (push) Canceled after 0s
GCC PCH / build (push) Canceled after 0s

This commit is contained in:
Nico committed 2026-10-17 21:10:53 +00:00
1 parent ae2a4a0f08
commit 2bcffa5131
4 files changed
+80 -32

No files matched your search

@@ -551,14 +551,9 @@ bool ClientlessActionExecutorMgr::StartTravelToNode(
record.TaxiSourceNodeId = 0;
record.TaxiDestinationNodeId = 0;
std::string error;
if (sClientlessTravelGraphMgr->PlanRoute(
player, destinationNode, startRadius, record.Route, error,
&record.FailedEdgeDatabaseIds))
{
record.RouteComplete = true;
record.AdaptiveReachedNode = destinationNode;
}
else if (!sClientlessTravelGraphMgr->PlanAdaptiveRoute(
// VCORE_VIRTUAL_EDGE_V11_PORTAL_APPROACH: adaptive planning is primary.
// This considers MMAP-reachable ordinary and virtual ground entry points together.
if (!sClientlessTravelGraphMgr->PlanAdaptiveRoute(
player, destinationNode, startRadius, record.LocalBridgeRadius,
record.Route, record.RouteComplete, record.AdaptiveReachedNode, error,
&record.FailedEdgeDatabaseIds, &record.FailedBridgeKeys))
@@ -1279,7 +1274,11 @@ bool ClientlessActionExecutorMgr::StartRouteStep(
Position destination;
destination.Relocate(step.X, step.Y, step.Z, step.O);
if (!sClientlessTravelMgr->StartTravel(player, destination, true))
bool const portalSourceApproach =
step.NodeKey.rfind("portal_at_", 0) == 0 &&
step.NodeKey.find("_source") != std::string::npos;
if (!sClientlessTravelMgr->StartTravel(player, destination, !portalSourceApproach,
portalSourceApproach))
{
record.Status.State = ClientlessActionExecutionState::Failed;
record.Status.Detail = "travel start failed for route node " + step.NodeKey;
@@ -1466,6 +1465,18 @@ bool ClientlessActionExecutorMgr::RecoverTravel(
if (failedEdgeDatabaseId)
record.FailedEdgeDatabaseIds.insert(failedEdgeDatabaseId);
// A failed initial local approach must not be tried five times at the same spot.
if (!failedEdgeDatabaseId && record.RouteStep == 0 && !record.Route.empty() &&
reason.rfind("route-local-", 0) == 0)
{
std::string const& badStart = record.Route.front().NodeKey;
if (badStart != "virtual_ground_entry")
{
record.FailedBridgeKeys.insert("start:" + badStart);
TC_LOG_WARN("server.adventurebot.navigation",
"START_NODE_BLOCK node='%s' reason='%s'", badStart.c_str(), reason.c_str());
}
}
bool const bridgeFailure = reason.rfind("local-bridge-", 0) == 0;
@@ -1561,24 +1572,11 @@ bool ClientlessActionExecutorMgr::RecoverTravel(
}
else if (record.Status.ActionName == "travel_to_node")
{
planned = sClientlessTravelGraphMgr->PlanRoute(
player,
record.PlannedDestinationNode,
radius,
record.Route,
error,
&record.FailedEdgeDatabaseIds);
if (planned)
{
record.RouteComplete = true;
record.AdaptiveReachedNode = record.PlannedDestinationNode;
}
else
planned = sClientlessTravelGraphMgr->PlanAdaptiveRoute(
player, record.PlannedDestinationNode, radius, record.LocalBridgeRadius,
record.Route, record.RouteComplete, record.AdaptiveReachedNode, error,
&record.FailedEdgeDatabaseIds, &record.FailedBridgeKeys);
// VCORE_VIRTUAL_EDGE_V11_PORTAL_APPROACH: adaptive recovery only.
planned = sClientlessTravelGraphMgr->PlanAdaptiveRoute(
player, record.PlannedDestinationNode, radius, record.LocalBridgeRadius,
record.Route, record.RouteComplete, record.AdaptiveReachedNode, error,
&record.FailedEdgeDatabaseIds, &record.FailedBridgeKeys);
if (planned)
TC_LOG_WARN("server.adventurebot.navigation",
@@ -470,6 +470,25 @@ bool ClientlessTravelGraphMgr::PlanAdaptiveRoute(
if (localDistance > startRadius)
continue;
// VCORE_VIRTUAL_EDGE_V11_PORTAL_APPROACH: never seed an unreachable node.
if (blockedBridgeKeys && blockedBridgeKeys->count("start:" + node.Key))
continue;
if (localDistance > 1.5f)
{
Position entryTarget;
entryTarget.Relocate(node.X, node.Y, node.Z, node.O);
ClientlessPathDiagnostics entryNav;
sClientlessTravelMgr->AnalyzePath(const_cast<Player*>(player), entryTarget, entryNav);
if (!entryNav.Calculated || !entryNav.Complete || entryNav.FinalDistance > 1.5f ||
entryNav.MaxSegmentLength > 8.0f || entryNav.MaxZDelta > 5.0f ||
entryNav.PathLength > 500.0f)
{
TC_LOG_INFO("server.adventurebot.navigation",
"START_NODE_REJECT node='%s' distance=%.2f reason='%s'",
node.Key.c_str(), localDistance, entryNav.Reason.c_str());
continue;
}
}
State state{ node.Key, false };
std::string const key = stateKey(state);
auto found = distance.find(key);
@@ -575,6 +594,8 @@ bool ClientlessTravelGraphMgr::PlanAdaptiveRoute(
State state{ candidate.Edge.ToNode, false };
std::string key = stateKey(state);
if (blockedBridgeKeys && blockedBridgeKeys->count("start:" + candidate.Edge.ToNode))
continue;
float remainingFraction = candidate.Edge.Reverse
? float(candidate.Index) / float(candidate.Count - 1)
: float(candidate.Count - candidate.Index - 1) / float(candidate.Count - 1);
@@ -591,7 +612,7 @@ bool ClientlessTravelGraphMgr::PlanAdaptiveRoute(
open.push({ newCost, state });
++accepted;
}
if (accepted)
if (validated)
TC_LOG_INFO("server.adventurebot.navigation",
"VIRTUAL_EDGE_CANDIDATES map=%u tested=%u accepted=%u",
player->GetMapId(), validated, accepted);
+30 -3
View File
@@ -242,7 +242,16 @@ bool ClientlessTravelMgr::LaunchPath(Player* player, TravelRecord& record)
nav.MaxZDelta, nav.FinalDistance, record.Status.RepathCount,
nav.Reason.c_str());
if (!nav.Calculated || !nav.Complete || nav.PointCount < 2 || nav.FinalDistance > MAX_PATH_FINAL_ERROR)
// VCORE_VIRTUAL_EDGE_V11_PORTAL_APPROACH: execute only a validated partial
// MMAP corridor. Never turn this exception on for normal ground navigation.
bool const portalPartial = record.PortalApproach && nav.Calculated &&
(nav.PathType & uint32(PATHFIND_INCOMPLETE)) != 0 &&
(nav.PathType & uint32(PATHFIND_NOPATH)) == 0 &&
nav.PointCount >= 2 && nav.FinalDistance <= 6.0f &&
nav.PathLength <= 100.0f && nav.MaxSegmentLength <= 6.0f &&
nav.MaxZDelta <= 4.0f;
if (!nav.Calculated || (!nav.Complete && !portalPartial) || nav.PointCount < 2 ||
(nav.FinalDistance > MAX_PATH_FINAL_ERROR && !portalPartial))
{
record.Status.State = ClientlessTravelState::PathRejected;
record.Status.NoProgressMs = 0;
@@ -299,9 +308,15 @@ bool ClientlessTravelMgr::LaunchPath(Player* player, TravelRecord& record)
"NAV_SHORT_INCOMPLETE_ACCEPT guid=%u name='%s' path=%.2f final=%.2f",
player->GetGUID().GetCounter(), player->GetName().c_str(),
executionLength, executionFinalDistance);
bool const portalExecutionPartial = record.PortalApproach && portalPartial &&
(executionType & uint32(PATHFIND_INCOMPLETE)) != 0 &&
(executionType & uint32(PATHFIND_NOPATH)) == 0 &&
points.size() >= 2 && executionFinalDistance <= 6.0f &&
executionLength <= 100.0f && executionMaxSegment <= 6.0f && executionMaxZ <= 4.0f;
if (points.size() < 2 ||
(executionType & uint32(PATHFIND_NOPATH)) != 0 ||
((executionType & uint32(PATHFIND_INCOMPLETE)) != 0 && !executionShortEndReached))
((executionType & uint32(PATHFIND_INCOMPLETE)) != 0 &&
!executionShortEndReached && !portalExecutionPartial))
{
record.Status.State = ClientlessTravelState::PathRejected;
TC_LOG_WARN("server.adventurebot.navigation",
@@ -312,6 +327,17 @@ bool ClientlessTravelMgr::LaunchPath(Player* player, TravelRecord& record)
return false;
}
if (portalExecutionPartial)
{
// Mark local traversal arrived at the actual MMAP endpoint only;
// the portal executor still checks IsInAreaTriggerRadius and actual map transition.
Position endpoint;
endpoint.Relocate(points.back().x, points.back().y, points.back().z, player->GetOrientation());
record.Status.Target = endpoint;
TC_LOG_INFO("server.adventurebot.navigation",
"NAV_PORTAL_PARTIAL_APPROACH guid=%u remainingToTrigger=%.2f path=%.2f",
player->GetGUID().GetCounter(), executionFinalDistance, executionLength);
}
std::vector<Position> spline;
spline.reserve(points.size() + 1);
@@ -406,7 +432,7 @@ bool ClientlessTravelMgr::LaunchPath(Player* player, TravelRecord& record)
return true;
}
bool ClientlessTravelMgr::StartTravel(Player* player, Position const& target, bool allowGroundMount)
bool ClientlessTravelMgr::StartTravel(Player* player, Position const& target, bool allowGroundMount, bool portalApproach)
{
if (!player || !player->IsInWorld())
return false;
@@ -419,6 +445,7 @@ bool ClientlessTravelMgr::StartTravel(Player* player, Position const& target, bo
record.Status.MapId = player->GetMapId();
record.Status.Target = target;
record.AllowGroundMount = allowGroundMount;
record.PortalApproach = portalApproach;
LaunchPath(player, record);
+3 -1
View File
@@ -57,7 +57,7 @@ class TC_GAME_API ClientlessTravelMgr
public:
static ClientlessTravelMgr* instance();
bool StartTravel(Player* player, Position const& target, bool allowGroundMount = false);
bool StartTravel(Player* player, Position const& target, bool allowGroundMount = false, bool portalApproach = false);
bool AnalyzePath(Player* player, Position const& target, ClientlessPathDiagnostics& diagnostics) const;
void CancelTravel(uint32 characterGuid);
ClientlessTravelStatus const* GetStatus(uint32 characterGuid) const;
@@ -76,6 +76,8 @@ private:
uint32 CheckTimerMs = 0;
std::vector<Position> ActiveSpline;
bool AllowGroundMount = false;
// VCORE_VIRTUAL_EDGE_V11_PORTAL_APPROACH: only actual portal source steps.
bool PortalApproach = false;
};
bool LaunchPath(Player* player, TravelRecord& record);