fix(Core/Travel): Revert AC-side 'improvements' over reference — hearthstone deathCount underflow, A* iteration cap, endPath tolerance

This commit is contained in:
bash 2026-05-31 13:45:33 +02:00
parent 1f9fa42082
commit 7772dc4c0d

View File

@ -1472,13 +1472,12 @@ TravelNodeRoute TravelNodeMap::GetNodeRoute(TravelNode* start, TravelNode* goal,
TravelNodeStub* hsStub = &m_stubs.insert(std::make_pair( TravelNodeStub* hsStub = &m_stubs.insert(std::make_pair(
static_cast<TravelNode*>(portNode), TravelNodeStub(portNode))).first->second; static_cast<TravelNode*>(portNode), TravelNodeStub(portNode))).first->second;
// Cost: max(2 seconds, (10 - deathCount) * MINUTE). // Cost: max(2, (10 - deathCount) * MINUTE) — matches
// Fresh bot → 10 minutes (walks if anything's closer); // reference exactly, including the uint32 underflow at
// recently-died bot → drops toward 2 seconds (hearth wins). // deathCount > 10 (which makes hearthstone prohibitive
// Clamp deathCount to 10 to avoid uint32 underflow that // for very-dead bots — apparently intentional).
// the reference implementation has at deathCount > 10. hsStub->costFromStart = std::max<uint32>(2,
uint32 const dc = std::min<uint32>(10, AI_VALUE(uint32, "death count")); (10 - AI_VALUE(uint32, "death count")) * MINUTE);
hsStub->costFromStart = std::max<uint32>(2, (10 - dc) * MINUTE);
hsStub->heuristic = hsStub->dataNode->fDist(goal) / botSpeed; hsStub->heuristic = hsStub->dataNode->fDist(goal) / botSpeed;
hsStub->totalCost = hsStub->costFromStart + hsStub->heuristic; hsStub->totalCost = hsStub->costFromStart + hsStub->heuristic;
@ -1548,18 +1547,8 @@ TravelNodeRoute TravelNodeMap::GetNodeRoute(TravelNode* start, TravelNode* goal,
// PortalNode stubs injected above. // PortalNode stubs injected above.
std::make_heap(open.begin(), open.end(), heapComp); std::make_heap(open.begin(), open.end(), heapComp);
constexpr uint32 MAX_A_STAR_EXPLORED = 500;
uint32 nodesExplored = 0;
while (!open.empty()) while (!open.empty())
{ {
if (++nodesExplored > MAX_A_STAR_EXPLORED)
{
for (auto* p : portNodes)
delete p;
return TravelNodeRoute();
}
std::pop_heap(open.begin(), open.end(), heapComp); std::pop_heap(open.begin(), open.end(), heapComp);
currentNode = open.back(); currentNode = open.back();
open.pop_back(); open.pop_back();
@ -1776,19 +1765,17 @@ TravelPath TravelNodeMap::GetFullPath(WorldPosition botPos, [[maybe_unused]] uin
continue; continue;
WorldPosition endNodePos = *e->getPosition(); WorldPosition endNodePos = *e->getPosition();
// Validate endNode -> destination is pathable. Reference uses 1y // Validate endNode -> destination is pathable within 1y (matches
// strict tolerance, but that rejects valid cave-interior nodes // reference exactly). Off-mesh destinations that fail this check
// when the destination (quest GO, mob, item) is slightly off the // need a fix at the data layer (node placement, quest dest coords),
// navmesh (small shelf, alcove). Use INTERACTION_DISTANCE so any // not a loosened threshold here.
// endNode whose mmap can reach close enough for the bot to
// interact with the destination is accepted.
std::vector<WorldPosition> endProbe; std::vector<WorldPosition> endProbe;
bool endPathOk = false; bool endPathOk = false;
if (endNodePos.GetMapId() == destination.GetMapId()) if (endNodePos.GetMapId() == destination.GetMapId())
{ {
Unit* pathBot = (bot && bot->GetMapId() == destination.GetMapId()) ? bot : nullptr; Unit* pathBot = (bot && bot->GetMapId() == destination.GetMapId()) ? bot : nullptr;
endProbe = endNodePos.getPathTo(destination, pathBot); endProbe = endNodePos.getPathTo(destination, pathBot);
endPathOk = destination.isPathTo(endProbe, INTERACTION_DISTANCE); endPathOk = destination.isPathTo(endProbe, 1.0f);
} }
else else
{ {