Small improvments.

This commit is contained in:
Keleborn 2026-04-17 12:24:33 -07:00
parent 233790a430
commit 8cf684a141
5 changed files with 47 additions and 34 deletions

View File

@ -6,10 +6,10 @@
#include "CheckValuesAction.h"
#include "Event.h"
#include "ObjectGuid.h"
#include "ServerFacade.h"
#include "PlayerbotAI.h"
#include "TravelNode.h"
#include "AiObjectContext.h"
CheckValuesAction::CheckValuesAction(PlayerbotAI* botAI) : Action(botAI, "check values") {}
@ -21,11 +21,6 @@ bool CheckValuesAction::Execute(Event /*event*/)
botAI->Ping(bot->GetPositionX(), bot->GetPositionY());
}
if (botAI->HasStrategy("map", BOT_STATE_NON_COMBAT) || botAI->HasStrategy("map full", BOT_STATE_NON_COMBAT))
{
TravelNodeMap::instance().manageNodes(bot, botAI->HasStrategy("map full", BOT_STATE_NON_COMBAT));
}
GuidVector possible_targets = *context->GetValue<GuidVector>("possible targets");
GuidVector all_targets = *context->GetValue<GuidVector>("all targets");
GuidVector npcs = *context->GetValue<GuidVector>("nearest npcs");

View File

@ -76,7 +76,7 @@ bool DebugAction::Execute(Event event)
return false;
std::vector<WorldPosition> beginPath, endPath;
TravelNodeRoute route = TravelNodeMap::instance().GetNearestNodes(botPos, *points.front(), beginPath, bot);
TravelNodeRoute route = TravelNodeMap::instance().FindRouteNearestNodes(botPos, *points.front(), beginPath, bot);
std::ostringstream out;
out << "Traveling to " << dest->getTitle() << ": ";

View File

@ -2997,6 +2997,14 @@ bool MovementAction::CheckSplineProgress(TravelPlan& state)
if (!state.splineActive)
return false;
// walkPoints may have been cleared by a map transfer or external reset
// while the spline was still flagged active; bail out safely.
if (state.walkPoints.empty())
{
state.splineActive = false;
return false;
}
if (bot->movespline->Finalized())
{
G3D::Vector3 const& endPt = state.walkPoints.back();
@ -3009,7 +3017,7 @@ bool MovementAction::CheckSplineProgress(TravelPlan& state)
return true; // Arrived
}
// If we havent arrived to destination, but are done moving then something interrupted it.
// If we haven't arrived to destination, but are done moving then something interrupted it.
// Need to restart. Reset state
state.splineActive = false;
return false;
@ -3226,7 +3234,7 @@ bool MovementAction::ExecuteTravelPlan(TravelPlan& state)
if (dist > INTERACTION_DISTANCE)
return MoveTo(src.point.GetMapId(), src.point.GetPositionX(), src.point.GetPositionY(), src.point.GetPositionZ());
// At portal, but havent teleported though
// At portal, but haven't teleported through
TeleportFallback(state, dst.point, "portal walk-through");
state.stepIdx += 2;
return true;
@ -3369,6 +3377,14 @@ bool MovementAction::ExecuteTravelPlan(TravelPlan& state)
state.stepIdx += 2;
return true;
}
default:
{
LOG_ERROR("playerbots",
"[TravelPlan] Bot {} encountered unknown PathNodeType ({}); resetting plan",
bot->GetName(), static_cast<uint32>(pt.type));
state.Reset();
return false;
}
}
return false;
}

View File

@ -115,25 +115,25 @@ float TravelNodePath::getCost(Player* bot, uint32 cGold)
if (getPathType() == TravelNodePathType::flightPath && pathObject)
{
if (!bot->IsAlive())
return -1;
return -1.0f;
TaxiPathEntry const* taxiPath = sTaxiPathStore.LookupEntry(pathObject);
if (!taxiPath)
return -1;
return -1.0f;
if (!bot->isTaxiCheater() && taxiPath->price > cGold)
return -1;
return -1.0f;
if (!bot->isTaxiCheater() && !bot->m_taxi.IsTaximaskNodeKnown(taxiPath->to))
return -1;
return -1.0f;
TaxiNodesEntry const* startTaxiNode = sTaxiNodesStore.LookupEntry(taxiPath->from);
TaxiNodesEntry const* endTaxiNode = sTaxiNodesStore.LookupEntry(taxiPath->to);
if (!startTaxiNode || !endTaxiNode ||
!startTaxiNode->MountCreatureID[bot->GetTeamId() == TEAM_ALLIANCE ? 1 : 0] ||
!endTaxiNode->MountCreatureID[bot->GetTeamId() == TEAM_ALLIANCE ? 1 : 0])
return -1;
return -1.0f;
}
speed = bot->GetSpeed(MOVE_RUN);
@ -164,7 +164,7 @@ float TravelNodePath::getCost(Player* bot, uint32 cGold)
if (getPathType() == TravelNodePathType::flyingMount)
{
if (!bot->IsAlive() || bot->GetLevel() < 70 || !bot->CanFly())
return -1;
return -1.0f;
float flySpeed = bot->GetSpeed(MOVE_FLIGHT);
if (flySpeed < 1.0f)
@ -173,7 +173,7 @@ float TravelNodePath::getCost(Player* bot, uint32 cGold)
}
}
else if (getPathType() == TravelNodePathType::flightPath || getPathType() == TravelNodePathType::flyingMount)
return -1;
return -1.0f;
if (getPathType() != TravelNodePathType::walk)
timeCost = extraCost * modifier;
@ -1097,7 +1097,12 @@ TravelNodeRoute TravelNodeMap::GetNodeRoute(TravelNode* start, TravelNode* goal,
while (!open.empty())
{
if (++nodesExplored > MAX_A_STAR_EXPLORED)
{
LOG_DEBUG("playerbots",
"[TravelNode A*] Exceeded MAX_A_STAR_EXPLORED ({}); truncating route from '{}' to '{}'",
MAX_A_STAR_EXPLORED, start->getName(), goal->getName());
return TravelNodeRoute();
}
std::pop_heap(open.begin(), open.end(), heapComp);
currentNode = open.back();
@ -1164,7 +1169,7 @@ TravelNodeRoute TravelNodeMap::GetNodeRoute(TravelNode* start, TravelNode* goal,
return TravelNodeRoute();
}
TravelNodeRoute TravelNodeMap::GetNearestNodes(WorldPosition startPos, WorldPosition endPos,
TravelNodeRoute TravelNodeMap::FindRouteNearestNodes(WorldPosition startPos, WorldPosition endPos,
std::vector<WorldPosition>& startPath, Player* bot)
{
if (nodes.empty() || !bot)
@ -1375,14 +1380,6 @@ TravelNode* TravelNodeMap::addRandomExtNode(TravelNode* startNode)
return nullptr;
}
void TravelNodeMap::manageNodes(Unit* bot, bool mapFull)
{
// Runtime node mutation disabled — the graph is fully built at startup via Init()
// and .generate. Taking a unique_lock here caused 100-250ms contention spikes for
// all bot threads holding shared_locks in TravelPlan.
// Node pruning/creation is still available via the .generate console command.
}
void TravelNodeMap::generateNpcNodes()
{
std::unordered_map<uint32, std::pair<CreatureTemplate const*, WorldPosition>> bossMap;
@ -1943,6 +1940,14 @@ void TravelNodeMap::generateAll()
void TravelNodeMap::Init()
{
InitTaxiGraph();
if (!sPlayerbotAIConfig.enableTravelNodes)
{
LOG_INFO("playerbots", "TravelNodeMap: travel node system disabled via AiPlayerbot.EnableTravelNodes=0 — skipping node load/generate/index.");
return;
}
LoadNodeStore();
calcMapOffset();
@ -1961,7 +1966,6 @@ void TravelNodeMap::Init()
BuildZoneIndex();
PrecomputeReachability();
InitTaxiGraph();
LOG_INFO("playerbots", "TravelNodeMap initialized: {} nodes, zone index and reachability built.",
nodes.size());
}

View File

@ -647,15 +647,13 @@ public:
TravelNodeRoute GetNodeRoute(TravelNode* start, TravelNode* goal,
Player* bot);
// Find the nearest start/end nodes for two world positions
TravelNodeRoute GetNearestNodes(WorldPosition startPos,
// Picks the nearest start/end nodes for two world positions and runs A*
// over the node graph to return a full route between them.
TravelNodeRoute FindRouteNearestNodes(WorldPosition startPos,
WorldPosition endPos,
std::vector<WorldPosition>& startPath,
Player* bot = nullptr);
// Manage/update nodes
void manageNodes(Unit* bot, bool mapFull = false);
void setHasToGen() { hasToGen = true; }
void generateNpcNodes();