From 666136ab3481a8527d78d25c4c88737b7b9725b3 Mon Sep 17 00:00:00 2001 From: bash Date: Sun, 31 May 2026 15:17:20 +0200 Subject: [PATCH] feat(Core/Travel): Add transportTeleportType config + teleport-across-water branch in UpcommingSpecialMovement --- conf/playerbots.conf.dist | 9 +++++++++ src/Mgr/Travel/TravelNode.cpp | 28 +++++++++++++++++++++++----- src/PlayerbotAIConfig.cpp | 1 + src/PlayerbotAIConfig.h | 5 +++++ 4 files changed, 38 insertions(+), 5 deletions(-) diff --git a/conf/playerbots.conf.dist b/conf/playerbots.conf.dist index 7d91f1c6e..76ebb971b 100644 --- a/conf/playerbots.conf.dist +++ b/conf/playerbots.conf.dist @@ -1038,6 +1038,15 @@ AiPlayerbot.EnableNewRpgStrategy = 1 # Default: 0 (disabled) AiPlayerbot.EnableTravelNodes = 0 +# Transport handling mode (travel node graph only): +# 0 = bot walks to dock, boards transport, rides, walks off (fully physical) +# 1 = same as 0, but if walk-on/off fails the boarding teleports the bot +# 2 = bot teleports across the route, skipping the ride entirely +# Reference default is 0; raise only if invisible/random-bot mass travel +# performance becomes an issue. +# Default: 0 +AiPlayerbot.TransportTeleportType = 0 + # Control probability weights for RPG status of bots. Takes effect only when the status meets its premise.​ # Sum of weights need not be 100. Set to 0 to disable the status. # diff --git a/src/Mgr/Travel/TravelNode.cpp b/src/Mgr/Travel/TravelNode.cpp index d0cf80c61..a68109986 100644 --- a/src/Mgr/Travel/TravelNode.cpp +++ b/src/Mgr/Travel/TravelNode.cpp @@ -927,12 +927,12 @@ bool TravelPath::UpcommingSpecialMovement(WorldPosition startPos, return true; } - // Transport boarding/disembark. We don't expose a teleport-vs-walk - // toggle yet, so always take the walk-on-board path: cut to dock if - // off-transport, traverse to disembark if on-transport. - if (startP->type == PathNodeType::NODE_TRANSPORT) + // Walk-on / teleport-to-transport boarding mode (modes 0 and 1). + // Cut to dock if off-transport, traverse to disembark if on-transport. + if (sPlayerbotAIConfig.transportTeleportType < 2 && + startP->type == PathNodeType::NODE_TRANSPORT) { - uint32 entry = nextP->entry; + uint32 const entry = nextP->entry; if (!onTransport) { @@ -954,6 +954,24 @@ bool TravelPath::UpcommingSpecialMovement(WorldPosition startPos, } } + // Teleport-across mode (mode 2): bot is approaching a transport + // node — walk forward to find the first non-transport node (the + // disembark side), cut to prevP (last transport node) so + // HandleSpecialMovement teleports the bot across directly. + if (sPlayerbotAIConfig.transportTeleportType == 2 && + nextP->type == PathNodeType::NODE_TRANSPORT) + { + for (auto p = std::next(startP); p != fullPath.end(); ++p) + { + if (p->type != PathNodeType::NODE_TRANSPORT) + { + cutTo(*prevP, false); + return true; + } + prevP = p; + } + } + return false; } diff --git a/src/PlayerbotAIConfig.cpp b/src/PlayerbotAIConfig.cpp index 8afebf9f1..047bbbd66 100644 --- a/src/PlayerbotAIConfig.cpp +++ b/src/PlayerbotAIConfig.cpp @@ -88,6 +88,7 @@ bool PlayerbotAIConfig::Initialize() farDistance = sConfigMgr->GetOption("AiPlayerbot.FarDistance", 20.0f); sightDistance = sConfigMgr->GetOption("AiPlayerbot.SightDistance", 100.0f); + transportTeleportType = sConfigMgr->GetOption("AiPlayerbot.TransportTeleportType", 0); spellDistance = sConfigMgr->GetOption("AiPlayerbot.SpellDistance", 28.5f); shootDistance = sConfigMgr->GetOption("AiPlayerbot.ShootDistance", 5.0f); healDistance = sConfigMgr->GetOption("AiPlayerbot.HealDistance", 38.5f); diff --git a/src/PlayerbotAIConfig.h b/src/PlayerbotAIConfig.h index 84c8aec99..405c41383 100644 --- a/src/PlayerbotAIConfig.h +++ b/src/PlayerbotAIConfig.h @@ -93,6 +93,11 @@ public: bool randomBotGuildNearby, randomBotInvitePlayer, inviteChat; uint32 globalCoolDown, reactDelay, maxWaitForMove, disableMoveSplinePath, expireActionTime, dispelAuraDuration, passiveDelay, repeatDelay, errorDelay, rpgDelay, sitDelay, returnDelay, lootDelay; + // Transport handling mode (matches reference `transportTeleportType`): + // 0 = walk on board, walk off (default, fully physical) + // 1 = walk on board, but UseTransport teleports on/off if walk fails + // 2 = skip the ride entirely — teleport directly across the route + uint32 transportTeleportType; bool dynamicReactDelay; float sightDistance, spellDistance, reactDistance, grindDistance, lootDistance, shootDistance, fleeDistance, tooCloseDistance, meleeDistance, followDistance, whisperDistance, contactDistance, aoeRadius, rpgDistance,