mirror of
https://github.com/liyunfan1223/mod-playerbots.git
synced 2026-06-20 15:39:25 +02:00
Compare commits
2 Commits
899f2cba94
...
7772dc4c0d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7772dc4c0d | ||
|
|
1f9fa42082 |
@ -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();
|
||||||
@ -1713,36 +1702,17 @@ TravelPath TravelNodeMap::GetFullPath(WorldPosition botPos, [[maybe_unused]] uin
|
|||||||
{
|
{
|
||||||
TravelPath path;
|
TravelPath path;
|
||||||
|
|
||||||
// AC-side workaround that reference doesn't have: if a 40-step mmap
|
// Probe-first short-circuit (matches reference exactly): if a 40-step
|
||||||
// probe from bot to destination either reaches close to dest OR
|
// mmap probe from bot to destination reaches within spellDistance of
|
||||||
// makes any meaningful forward progress (>30y absolute), prefer
|
// dest, use the probe directly and skip graph routing. Otherwise
|
||||||
// that direct path over the graph. The graph's K=5 endNode pick +
|
// fall through to the graph A* below — the failed probe waypoints
|
||||||
// strict 1y endPath validation rejects destinations that are
|
// would ideally feed into getRoute as startPath (reference does
|
||||||
// slightly off-mesh (cave shelves, alcoves), so without this the
|
// this; we don't yet — TODO).
|
||||||
// bot falls to a single-point MoveTo fallback and wiggles in place.
|
|
||||||
// Loosened from "50% AND >30y" to just ">30y" so a partial probe
|
|
||||||
// toward the cave entrance gets accepted; the next tick's
|
|
||||||
// re-resolve from the new bot position can extend further.
|
|
||||||
if (botPos.GetMapId() == destination.GetMapId())
|
if (botPos.GetMapId() == destination.GetMapId())
|
||||||
{
|
{
|
||||||
std::vector<WorldPosition> probe = destination.getPathFromPath({botPos}, bot, 40);
|
std::vector<WorldPosition> probe = destination.getPathFromPath({botPos}, bot, 40);
|
||||||
if (probe.size() >= 2)
|
if (destination.isPathTo(probe, sPlayerbotAIConfig.spellDistance))
|
||||||
{
|
return TravelPath(probe);
|
||||||
float const totalDist = botPos.distance(destination);
|
|
||||||
float const probeEndToDest = destination.distance(probe.back());
|
|
||||||
float const probeProgress = totalDist - probeEndToDest;
|
|
||||||
|
|
||||||
bool const closeEnough = probeEndToDest < 30.0f;
|
|
||||||
bool const meaningfulProgress = probeProgress > 30.0f;
|
|
||||||
|
|
||||||
if (closeEnough || meaningfulProgress)
|
|
||||||
{
|
|
||||||
path.addPoint(botPos, PathNodeType::NODE_PREPATH);
|
|
||||||
for (size_t i = 1; i < probe.size(); ++i)
|
|
||||||
path.addPoint(probe[i], PathNodeType::NODE_PATH);
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_lock<std::shared_timed_mutex> guard(m_nMapMtx);
|
std::shared_lock<std::shared_timed_mutex> guard(m_nMapMtx);
|
||||||
@ -1795,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
|
||||||
{
|
{
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user