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
f6c41f57e4
commit
fff692e3f3
@ -3145,28 +3145,49 @@ bool MovementAction::WaitForTransport()
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Disembark: head is the transport node where we should get off,
|
// Disembark: head is the transport node where we should get off,
|
||||||
// next is the world-position dock to land at. Reference uses
|
// next is the world-position dock to land at. Reference UseTransport
|
||||||
// UseTransport(ai, dock.entry, dock.point, tele.point, type>0)
|
// with doTeleport=(transportTeleportType > 0) routes to either
|
||||||
// — we don't have UseTransport, so inline the equivalent.
|
// MoveOffTransport-teleport (mode 1+) or MoveOffTransport-walk (mode 0).
|
||||||
PathNodePoint const& dock = path[0];
|
PathNodePoint const& dock = path[0];
|
||||||
if (path.size() < 2)
|
if (path.size() < 2)
|
||||||
return true; // no telePoint to land at; keep waiting
|
return true; // no telePoint to land at; keep waiting
|
||||||
PathNodePoint const& tele = path[1];
|
PathNodePoint const& tele = path[1];
|
||||||
|
(void)dock; // kept for reference parity (UseTransport signature)
|
||||||
|
|
||||||
transport->RemovePassenger(bot);
|
transport->RemovePassenger(bot);
|
||||||
bot->StopMovingOnCurrentPos();
|
|
||||||
bool const teleported = bot->TeleportTo(tele.point.GetMapId(),
|
if (sPlayerbotAIConfig.transportTeleportType > 0)
|
||||||
tele.point.GetPositionX(),
|
{
|
||||||
tele.point.GetPositionY(),
|
// Mode 1+: teleport directly to exit.
|
||||||
tele.point.GetPositionZ(),
|
bot->StopMovingOnCurrentPos();
|
||||||
bot->GetOrientation());
|
bool const teleported = bot->TeleportTo(tele.point.GetMapId(),
|
||||||
if (!teleported)
|
tele.point.GetPositionX(),
|
||||||
return true; // try again next tick
|
tele.point.GetPositionY(),
|
||||||
|
tele.point.GetPositionZ(),
|
||||||
|
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;
|
lastMove.lastTransportEntry = 0;
|
||||||
// Suppress unused-variable on `dock` — kept for parity with reference's
|
|
||||||
// UseTransport(entry, dockPoint, telePoint, ...) signature shape.
|
|
||||||
(void)dock;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3253,9 +3274,10 @@ bool MovementAction::HandleSpecialMovement(TravelPath& path)
|
|||||||
case PathNodeType::NODE_TRANSPORT:
|
case PathNodeType::NODE_TRANSPORT:
|
||||||
{
|
{
|
||||||
// Disembark: head is a transport node and bot is on one.
|
// Disembark: head is a transport node and bot is on one.
|
||||||
// Remove passenger + teleport to the next-step world position
|
// Reference dispatch: MoveOffTransport(exit, doTeleport) where
|
||||||
// (cmangos uses UseTransport with current→next teleport here;
|
// doTeleport = (transportTeleportType > 0). Mode 1+ teleports
|
||||||
// our equivalent is RemovePassenger + TeleportTo).
|
// straight to exit; mode 0 NearTeleports off transport plane
|
||||||
|
// then walks to exit.
|
||||||
if (!hasNext)
|
if (!hasNext)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -3265,14 +3287,35 @@ bool MovementAction::HandleSpecialMovement(TravelPath& path)
|
|||||||
|
|
||||||
PathNodePoint const& dst = path[1];
|
PathNodePoint const& dst = path[1];
|
||||||
transport->RemovePassenger(bot);
|
transport->RemovePassenger(bot);
|
||||||
bot->StopMovingOnCurrentPos();
|
|
||||||
bool const teleported = bot->TeleportTo(dst.point.GetMapId(),
|
if (sPlayerbotAIConfig.transportTeleportType > 0)
|
||||||
dst.point.GetPositionX(),
|
{
|
||||||
dst.point.GetPositionY(),
|
bot->StopMovingOnCurrentPos();
|
||||||
dst.point.GetPositionZ(),
|
bool const teleported = bot->TeleportTo(dst.point.GetMapId(),
|
||||||
bot->GetOrientation());
|
dst.point.GetPositionX(),
|
||||||
|
dst.point.GetPositionY(),
|
||||||
|
dst.point.GetPositionZ(),
|
||||||
|
bot->GetOrientation());
|
||||||
|
AI_VALUE(LastMovement&, "last movement").lastTransportEntry = 0;
|
||||||
|
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;
|
AI_VALUE(LastMovement&, "last movement").lastTransportEntry = 0;
|
||||||
return teleported;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -3479,15 +3522,14 @@ bool MovementAction::BoardTransport(Transport* transport)
|
|||||||
{
|
{
|
||||||
transport->AddPassenger(bot, true);
|
transport->AddPassenger(bot, true);
|
||||||
bot->StopMovingOnCurrentPos();
|
bot->StopMovingOnCurrentPos();
|
||||||
EmitDebugMove("Transport:board", "teleport", transport->GetPositionX(),
|
EmitDebugMove("Transport:board", "on-surface", transport->GetPositionX(),
|
||||||
transport->GetPositionY(), transport->GetPositionZ());
|
transport->GetPositionY(), transport->GetPositionZ());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Teleport-onto mode (transportTeleportType >= 1): skip the walk-toward
|
// Teleport-onto mode (transportTeleportType >= 1): skip the walk-toward
|
||||||
// phase and jump directly to a boarding edge. Matches reference's
|
// phase and jump directly to a boarding edge. Matches reference's
|
||||||
// `UseTransport(...telep=true)` shortcut for invisible / random bots
|
// MoveOnTransport(doTeleport=true) — PlayerRelocation + AddPassenger.
|
||||||
// and any caller that doesn't want the visible boarding sequence.
|
|
||||||
if (sPlayerbotAIConfig.transportTeleportType >= 1)
|
if (sPlayerbotAIConfig.transportTeleportType >= 1)
|
||||||
{
|
{
|
||||||
float edgeX, edgeY, edgeZ;
|
float edgeX, edgeY, edgeZ;
|
||||||
@ -3506,33 +3548,65 @@ bool MovementAction::BoardTransport(Transport* transport)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Fall through to walk-toward if no boarding point or teleport
|
// Fall through to mode-0 if no boarding point — better than refusing.
|
||||||
// failed — better than refusing the board outright.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Walk-toward mode (transportTeleportType == 0, or mode>=1 fallback).
|
// Mode 0: reference MoveOnTransport(doTeleport=false) — AddPassenger
|
||||||
float destX = transport->GetPositionX();
|
// FIRST (snaps bot onto transport plane), then walk a path on deck.
|
||||||
float destY = transport->GetPositionY();
|
// We don't have RandomPointOnTrans / transport-surface mmap, so when
|
||||||
float destZ = transport->GetPositionZ();
|
// 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;
|
float edgeX, edgeY, edgeZ;
|
||||||
if (FindBoardingPointOnTransport(map, transport, transport, transport->GetPositionX(), transport->GetPositionY(),
|
bool haveEdge = FindBoardingPointOnTransport(map, transport, transport,
|
||||||
transport->GetPositionZ(), bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ(), edgeX, edgeY, edgeZ))
|
transport->GetPositionX(), transport->GetPositionY(),
|
||||||
|
transport->GetPositionZ(), bot->GetPositionX(), bot->GetPositionY(),
|
||||||
|
bot->GetPositionZ(), edgeX, edgeY, edgeZ);
|
||||||
|
if (haveEdge)
|
||||||
{
|
{
|
||||||
destX = edgeX;
|
boardX = edgeX;
|
||||||
destY = edgeY;
|
boardY = edgeY;
|
||||||
destZ = edgeZ;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Too far to snap — walk toward boarding edge.
|
||||||
if (MotionMaster* mm = bot->GetMotionMaster())
|
if (MotionMaster* mm = bot->GetMotionMaster())
|
||||||
{
|
{
|
||||||
if (!bot->IsStandState())
|
if (!bot->IsStandState())
|
||||||
bot->SetStandState(UNIT_STAND_STATE_STAND);
|
bot->SetStandState(UNIT_STAND_STATE_STAND);
|
||||||
|
mm->MovePoint(0, boardX, boardY, boardZ,
|
||||||
mm->MovePoint(0, destX, destY, destZ, FORCED_MOVEMENT_NONE, 0.0f, 0.0f, false, false);
|
FORCED_MOVEMENT_NONE, 0.0f, 0.0f, false, false);
|
||||||
EmitDebugMove("Transport:walk", "spline", destX, destY, destZ);
|
EmitDebugMove("Transport:walk", "approach-boarding", boardX, boardY, boardZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user