mirror of
https://github.com/liyunfan1223/mod-playerbots.git
synced 2026-06-20 15:39:25 +02:00
feat(Core/Movement): Mode-0 transport board/disembark — snap-and-deck-walk on board, NearTeleport+walk on disembark
This commit is contained in:
parent
343ab7ac30
commit
f90f365e94
@ -3145,15 +3145,20 @@ 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 uses
|
||||
// UseTransport(ai, dock.entry, dock.point, tele.point, type>0)
|
||||
// — we don't have UseTransport, so inline the equivalent.
|
||||
// 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];
|
||||
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(),
|
||||
@ -3162,11 +3167,27 @@ 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;
|
||||
// Suppress unused-variable on `dock` — kept for parity with reference's
|
||||
// UseTransport(entry, dockPoint, telePoint, ...) signature shape.
|
||||
(void)dock;
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -3253,9 +3274,10 @@ bool MovementAction::HandleSpecialMovement(TravelPath& path)
|
||||
case PathNodeType::NODE_TRANSPORT:
|
||||
{
|
||||
// Disembark: head is a transport node and bot is on one.
|
||||
// Remove passenger + teleport to the next-step world position
|
||||
// (cmangos uses UseTransport with current→next teleport here;
|
||||
// our equivalent is RemovePassenger + TeleportTo).
|
||||
// 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.
|
||||
if (!hasNext)
|
||||
return false;
|
||||
|
||||
@ -3265,6 +3287,9 @@ 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(),
|
||||
@ -3275,6 +3300,24 @@ 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;
|
||||
}
|
||||
@ -3479,15 +3522,14 @@ bool MovementAction::BoardTransport(Transport* transport)
|
||||
{
|
||||
transport->AddPassenger(bot, true);
|
||||
bot->StopMovingOnCurrentPos();
|
||||
EmitDebugMove("Transport:board", "teleport", transport->GetPositionX(),
|
||||
EmitDebugMove("Transport:board", "on-surface", transport->GetPositionX(),
|
||||
transport->GetPositionY(), transport->GetPositionZ());
|
||||
return true;
|
||||
}
|
||||
|
||||
// Teleport-onto mode (transportTeleportType >= 1): skip the walk-toward
|
||||
// phase and jump directly to a boarding edge. Matches reference's
|
||||
// `UseTransport(...telep=true)` shortcut for invisible / random bots
|
||||
// and any caller that doesn't want the visible boarding sequence.
|
||||
// MoveOnTransport(doTeleport=true) — PlayerRelocation + AddPassenger.
|
||||
if (sPlayerbotAIConfig.transportTeleportType >= 1)
|
||||
{
|
||||
float edgeX, edgeY, edgeZ;
|
||||
@ -3506,33 +3548,65 @@ bool MovementAction::BoardTransport(Transport* transport)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// Fall through to walk-toward if no boarding point or teleport
|
||||
// failed — better than refusing the board outright.
|
||||
// Fall through to mode-0 if no boarding point — better than refusing.
|
||||
}
|
||||
|
||||
// Walk-toward mode (transportTeleportType == 0, or mode>=1 fallback).
|
||||
float destX = transport->GetPositionX();
|
||||
float destY = transport->GetPositionY();
|
||||
float destZ = transport->GetPositionZ();
|
||||
// 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();
|
||||
|
||||
// Try to find nearest boarding edge
|
||||
float edgeX, edgeY, edgeZ;
|
||||
if (FindBoardingPointOnTransport(map, transport, transport, transport->GetPositionX(), transport->GetPositionY(),
|
||||
transport->GetPositionZ(), bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ(), 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)
|
||||
{
|
||||
destX = edgeX;
|
||||
destY = edgeY;
|
||||
destZ = edgeZ;
|
||||
boardX = edgeX;
|
||||
boardY = edgeY;
|
||||
boardZ = edgeZ;
|
||||
}
|
||||
|
||||
// MovePoint without pathfinding (transport is a moving object)
|
||||
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;
|
||||
}
|
||||
|
||||
mm->MovePoint(0, destX, destY, destZ, FORCED_MOVEMENT_NONE, 0.0f, 0.0f, false, false);
|
||||
EmitDebugMove("Transport:walk", "spline", destX, destY, destZ);
|
||||
// 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;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user