mirror of
https://github.com/liyunfan1223/mod-playerbots.git
synced 2026-06-20 15:39:25 +02:00
refactor(Core/Travel): Simplify transport config to TransportSkipRide bool; drop mode-0 deck-walk approximations
This commit is contained in:
parent
f90f365e94
commit
6079863fce
@ -1038,14 +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.
|
||||
# Transport ride mode (travel node graph only):
|
||||
# 0 = bot walks to dock, teleport-snaps onto transport, rides, teleport-snaps off
|
||||
# 1 = bot teleports directly across the transport route, skipping the ride
|
||||
# Default 0 is the visible behavior. Set to 1 for invisible/random-bot mass
|
||||
# travel performance — the bot never actually boards anything.
|
||||
# (AC has no transport-surface mmap, so an on-deck walking mode can't be
|
||||
# faithfully implemented; the on-board phase always teleport-snaps.)
|
||||
# Default: 0
|
||||
AiPlayerbot.TransportTeleportType = 0
|
||||
AiPlayerbot.TransportSkipRide = 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.
|
||||
|
||||
@ -3145,20 +3145,12 @@ bool MovementAction::WaitForTransport()
|
||||
return false;
|
||||
|
||||
// Disembark: head is the transport node where we should get off,
|
||||
// next is the world-position dock to land at. Reference UseTransport
|
||||
// with doTeleport=(transportTeleportType > 0) routes to either
|
||||
// MoveOffTransport-teleport (mode 1+) or MoveOffTransport-walk (mode 0).
|
||||
PathNodePoint const& dock = path[0];
|
||||
// next is the world-position dock to land at.
|
||||
if (path.size() < 2)
|
||||
return true; // no telePoint to land at; keep waiting
|
||||
PathNodePoint const& tele = path[1];
|
||||
(void)dock; // kept for reference parity (UseTransport signature)
|
||||
|
||||
transport->RemovePassenger(bot);
|
||||
|
||||
if (sPlayerbotAIConfig.transportTeleportType > 0)
|
||||
{
|
||||
// Mode 1+: teleport directly to exit.
|
||||
bot->StopMovingOnCurrentPos();
|
||||
bool const teleported = bot->TeleportTo(tele.point.GetMapId(),
|
||||
tele.point.GetPositionX(),
|
||||
@ -3167,25 +3159,6 @@ bool MovementAction::WaitForTransport()
|
||||
bot->GetOrientation());
|
||||
if (!teleported)
|
||||
return true; // try again next tick
|
||||
lastMove.lastTransportEntry = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Mode 0: NearTeleportTo current world position (drops bot off
|
||||
// transport plane to world coords without unloading client), then
|
||||
// walk to the exit position. Matches reference MoveOffTransport
|
||||
// with doTeleport=false.
|
||||
bot->NearTeleportTo(bot->GetPositionX(), bot->GetPositionY(),
|
||||
bot->GetPositionZ(), bot->GetOrientation());
|
||||
|
||||
if (MotionMaster* mm = bot->GetMotionMaster())
|
||||
{
|
||||
mm->Clear();
|
||||
mm->MovePoint(0, tele.point.GetPositionX(),
|
||||
tele.point.GetPositionY(),
|
||||
tele.point.GetPositionZ(),
|
||||
FORCED_MOVEMENT_RUN, 0.0f, 0.0f, true, false);
|
||||
}
|
||||
|
||||
lastMove.lastTransportEntry = 0;
|
||||
return false;
|
||||
@ -3274,10 +3247,7 @@ bool MovementAction::HandleSpecialMovement(TravelPath& path)
|
||||
case PathNodeType::NODE_TRANSPORT:
|
||||
{
|
||||
// Disembark: head is a transport node and bot is on one.
|
||||
// Reference dispatch: MoveOffTransport(exit, doTeleport) where
|
||||
// doTeleport = (transportTeleportType > 0). Mode 1+ teleports
|
||||
// straight to exit; mode 0 NearTeleports off transport plane
|
||||
// then walks to exit.
|
||||
// RemovePassenger + TeleportTo the next-step world position.
|
||||
if (!hasNext)
|
||||
return false;
|
||||
|
||||
@ -3287,9 +3257,6 @@ bool MovementAction::HandleSpecialMovement(TravelPath& path)
|
||||
|
||||
PathNodePoint const& dst = path[1];
|
||||
transport->RemovePassenger(bot);
|
||||
|
||||
if (sPlayerbotAIConfig.transportTeleportType > 0)
|
||||
{
|
||||
bot->StopMovingOnCurrentPos();
|
||||
bool const teleported = bot->TeleportTo(dst.point.GetMapId(),
|
||||
dst.point.GetPositionX(),
|
||||
@ -3300,24 +3267,6 @@ bool MovementAction::HandleSpecialMovement(TravelPath& path)
|
||||
return teleported;
|
||||
}
|
||||
|
||||
// Mode 0: NearTeleportTo current world pos (drops bot off
|
||||
// transport plane without unloading the client), then walk
|
||||
// to the exit.
|
||||
bot->NearTeleportTo(bot->GetPositionX(), bot->GetPositionY(),
|
||||
bot->GetPositionZ(), bot->GetOrientation());
|
||||
|
||||
if (MotionMaster* mm = bot->GetMotionMaster())
|
||||
{
|
||||
mm->Clear();
|
||||
mm->MovePoint(0, dst.point.GetPositionX(),
|
||||
dst.point.GetPositionY(),
|
||||
dst.point.GetPositionZ(),
|
||||
FORCED_MOVEMENT_RUN, 0.0f, 0.0f, true, false);
|
||||
}
|
||||
AI_VALUE(LastMovement&, "last movement").lastTransportEntry = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -3527,87 +3476,29 @@ bool MovementAction::BoardTransport(Transport* transport)
|
||||
return true;
|
||||
}
|
||||
|
||||
// Teleport-onto mode (transportTeleportType >= 1): skip the walk-toward
|
||||
// phase and jump directly to a boarding edge. Matches reference's
|
||||
// MoveOnTransport(doTeleport=true) — PlayerRelocation + AddPassenger.
|
||||
if (sPlayerbotAIConfig.transportTeleportType >= 1)
|
||||
{
|
||||
// Bot off transport: find a boarding edge and teleport-snap directly
|
||||
// onto it, then AddPassenger. We can't walk on the deck (no transport-
|
||||
// surface mmap), so the snap-board is the only universal approach.
|
||||
float edgeX, edgeY, edgeZ;
|
||||
if (FindBoardingPointOnTransport(map, transport, transport,
|
||||
if (!FindBoardingPointOnTransport(map, transport, transport,
|
||||
transport->GetPositionX(), transport->GetPositionY(),
|
||||
transport->GetPositionZ(),
|
||||
bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ(),
|
||||
edgeX, edgeY, edgeZ))
|
||||
{
|
||||
if (bot->TeleportTo(map->GetId(), edgeX, edgeY, edgeZ, bot->GetOrientation()))
|
||||
{
|
||||
// No boarding edge found — wait a tick. Caller's WaitForReach
|
||||
// upstream throttles the retry.
|
||||
EmitDebugMove("Transport:board", "no-edge",
|
||||
transport->GetPositionX(), transport->GetPositionY(),
|
||||
transport->GetPositionZ());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!bot->TeleportTo(map->GetId(), edgeX, edgeY, edgeZ, bot->GetOrientation()))
|
||||
return false;
|
||||
|
||||
transport->AddPassenger(bot, true);
|
||||
bot->StopMovingOnCurrentPos();
|
||||
EmitDebugMove("Transport:board", "teleport-skip-walk",
|
||||
edgeX, edgeY, edgeZ);
|
||||
EmitDebugMove("Transport:board", "snap", edgeX, edgeY, edgeZ);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// Fall through to mode-0 if no boarding point — better than refusing.
|
||||
}
|
||||
|
||||
// Mode 0: reference MoveOnTransport(doTeleport=false) — AddPassenger
|
||||
// FIRST (snaps bot onto transport plane), then walk a path on deck.
|
||||
// We don't have RandomPointOnTrans / transport-surface mmap, so when
|
||||
// the bot is within INTERACTION_DISTANCE of the transport's boarding
|
||||
// edge we approximate: AddPassenger + MovePoint toward the transport
|
||||
// center as a "deck destination." Bot motion is then transport-
|
||||
// relative because of the AddPassenger.
|
||||
float boardX = transport->GetPositionX();
|
||||
float boardY = transport->GetPositionY();
|
||||
float boardZ = transport->GetPositionZ();
|
||||
|
||||
float edgeX, edgeY, edgeZ;
|
||||
bool haveEdge = FindBoardingPointOnTransport(map, transport, transport,
|
||||
transport->GetPositionX(), transport->GetPositionY(),
|
||||
transport->GetPositionZ(), bot->GetPositionX(), bot->GetPositionY(),
|
||||
bot->GetPositionZ(), edgeX, edgeY, edgeZ);
|
||||
if (haveEdge)
|
||||
{
|
||||
boardX = edgeX;
|
||||
boardY = edgeY;
|
||||
boardZ = edgeZ;
|
||||
}
|
||||
|
||||
float const dxBoard = bot->GetPositionX() - boardX;
|
||||
float const dyBoard = bot->GetPositionY() - boardY;
|
||||
bool const nearBoardingPoint =
|
||||
(dxBoard * dxBoard + dyBoard * dyBoard) <
|
||||
INTERACTION_DISTANCE * INTERACTION_DISTANCE;
|
||||
|
||||
if (nearBoardingPoint)
|
||||
{
|
||||
// Snap onto transport plane, then walk a short deck path so the
|
||||
// bot is visibly on the boat (mirrors reference mode-0 deck walk).
|
||||
transport->AddPassenger(bot, true);
|
||||
if (MotionMaster* mm = bot->GetMotionMaster())
|
||||
{
|
||||
if (!bot->IsStandState())
|
||||
bot->SetStandState(UNIT_STAND_STATE_STAND);
|
||||
mm->Clear();
|
||||
mm->MovePoint(0, transport->GetPositionX(), transport->GetPositionY(),
|
||||
transport->GetPositionZ(),
|
||||
FORCED_MOVEMENT_RUN, 0.0f, 0.0f, false, false);
|
||||
}
|
||||
EmitDebugMove("Transport:board", "snap-and-deck-walk",
|
||||
boardX, boardY, boardZ);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Too far to snap — walk toward boarding edge.
|
||||
if (MotionMaster* mm = bot->GetMotionMaster())
|
||||
{
|
||||
if (!bot->IsStandState())
|
||||
bot->SetStandState(UNIT_STAND_STATE_STAND);
|
||||
mm->MovePoint(0, boardX, boardY, boardZ,
|
||||
FORCED_MOVEMENT_NONE, 0.0f, 0.0f, false, false);
|
||||
EmitDebugMove("Transport:walk", "approach-boarding", boardX, boardY, boardZ);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -927,9 +927,9 @@ bool TravelPath::UpcommingSpecialMovement(WorldPosition startPos,
|
||||
return true;
|
||||
}
|
||||
|
||||
// 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 &&
|
||||
// Board-and-ride mode (transportSkipRide == false). Cut to dock if
|
||||
// off-transport, traverse to disembark if on-transport.
|
||||
if (!sPlayerbotAIConfig.transportSkipRide &&
|
||||
startP->type == PathNodeType::NODE_TRANSPORT)
|
||||
{
|
||||
uint32 const entry = nextP->entry;
|
||||
@ -954,11 +954,11 @@ 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
|
||||
// Skip-ride mode (transportSkipRide == true): 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 &&
|
||||
if (sPlayerbotAIConfig.transportSkipRide &&
|
||||
nextP->type == PathNodeType::NODE_TRANSPORT)
|
||||
{
|
||||
for (auto p = std::next(startP); p != fullPath.end(); ++p)
|
||||
|
||||
@ -88,7 +88,7 @@ bool PlayerbotAIConfig::Initialize()
|
||||
|
||||
farDistance = sConfigMgr->GetOption<float>("AiPlayerbot.FarDistance", 20.0f);
|
||||
sightDistance = sConfigMgr->GetOption<float>("AiPlayerbot.SightDistance", 100.0f);
|
||||
transportTeleportType = sConfigMgr->GetOption<uint32>("AiPlayerbot.TransportTeleportType", 0);
|
||||
transportSkipRide = sConfigMgr->GetOption<bool>("AiPlayerbot.TransportSkipRide", false);
|
||||
spellDistance = sConfigMgr->GetOption<float>("AiPlayerbot.SpellDistance", 28.5f);
|
||||
shootDistance = sConfigMgr->GetOption<float>("AiPlayerbot.ShootDistance", 5.0f);
|
||||
healDistance = sConfigMgr->GetOption<float>("AiPlayerbot.HealDistance", 38.5f);
|
||||
|
||||
@ -93,11 +93,12 @@ 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;
|
||||
// Transport handling:
|
||||
// false (default) = teleport-board, ride the transport, teleport-disembark
|
||||
// true = skip the ride entirely (teleport directly across)
|
||||
// AC has no transport-surface mmap so an in-deck walking mode can't be
|
||||
// faithfully implemented — the on-board phase always teleport-snaps.
|
||||
bool transportSkipRide;
|
||||
bool dynamicReactDelay;
|
||||
float sightDistance, spellDistance, reactDistance, grindDistance, lootDistance, shootDistance, fleeDistance,
|
||||
tooCloseDistance, meleeDistance, followDistance, whisperDistance, contactDistance, aoeRadius, rpgDistance,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user