mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-03-22 23:30:14 +00:00
fix: handle transport data in other player movement packets
Other players on transports (boats, zeppelins, trams) were not properly tracked because handleOtherPlayerMovement() did not read transport data from MSG_MOVE_* packets. This caused entities to slide off transports between movement updates since no transport attachment was established. Now reads the transport GUID and local offset from the packet using expansion-aware wire flags (0x200 for WotLK/TBC, 0x02000000 for Classic/Turtle), registers a transport attachment so the entity follows the transport smoothly via updateAttachedTransportChildren(), and clears the attachment when the player disembarks.
This commit is contained in:
parent
f5297f9945
commit
1152a70201
2 changed files with 45 additions and 0 deletions
|
|
@ -26,6 +26,10 @@ public:
|
|||
// Classic: none, TBC: u8, WotLK: u16.
|
||||
virtual uint8_t movementFlags2Size() const { return 2; }
|
||||
|
||||
// Wire-format movement flag that gates transport data in MSG_MOVE_* payloads.
|
||||
// WotLK/TBC: 0x200, Classic/Turtle: 0x02000000.
|
||||
virtual uint32_t wireOnTransportFlag() const { return 0x00000200; }
|
||||
|
||||
// --- Movement ---
|
||||
|
||||
/** Parse movement block from SMSG_UPDATE_OBJECT */
|
||||
|
|
@ -380,6 +384,7 @@ public:
|
|||
class ClassicPacketParsers : public TbcPacketParsers {
|
||||
public:
|
||||
uint8_t movementFlags2Size() const override { return 0; }
|
||||
uint32_t wireOnTransportFlag() const override { return 0x02000000; }
|
||||
bool parseCharEnum(network::Packet& packet, CharEnumResponse& response) override;
|
||||
bool parseMovementBlock(network::Packet& packet, UpdateBlock& block) override;
|
||||
void writeMovementPayload(network::Packet& packet, const MovementInfo& info) override;
|
||||
|
|
|
|||
|
|
@ -16855,6 +16855,32 @@ void GameHandler::handleOtherPlayerMovement(network::Packet& packet) {
|
|||
info.z = packet.readFloat();
|
||||
info.orientation = packet.readFloat();
|
||||
|
||||
// Read transport data if the on-transport flag is set in wire-format move flags.
|
||||
// The flag bit position differs between expansions (0x200 for WotLK/TBC, 0x02000000 for Classic/Turtle).
|
||||
const uint32_t wireTransportFlag = packetParsers_ ? packetParsers_->wireOnTransportFlag() : 0x00000200;
|
||||
const bool onTransport = (info.flags & wireTransportFlag) != 0;
|
||||
uint64_t transportGuid = 0;
|
||||
float tLocalX = 0, tLocalY = 0, tLocalZ = 0, tLocalO = 0;
|
||||
if (onTransport) {
|
||||
transportGuid = UpdateObjectParser::readPackedGuid(packet);
|
||||
tLocalX = packet.readFloat();
|
||||
tLocalY = packet.readFloat();
|
||||
tLocalZ = packet.readFloat();
|
||||
tLocalO = packet.readFloat();
|
||||
// TBC and WotLK include a transport timestamp; Classic does not.
|
||||
if (flags2Size >= 1) {
|
||||
/*uint32_t transportTime =*/ packet.readUInt32();
|
||||
}
|
||||
// WotLK adds a transport seat byte.
|
||||
if (flags2Size >= 2) {
|
||||
/*int8_t transportSeat =*/ packet.readUInt8();
|
||||
// Optional second transport time for interpolated movement.
|
||||
if (info.flags2 & 0x0200) {
|
||||
/*uint32_t transportTime2 =*/ packet.readUInt32();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update entity position in entity manager
|
||||
auto entity = entityManager.getEntity(moverGuid);
|
||||
if (!entity) {
|
||||
|
|
@ -16864,6 +16890,20 @@ void GameHandler::handleOtherPlayerMovement(network::Packet& packet) {
|
|||
// Convert server coords to canonical
|
||||
glm::vec3 canonical = core::coords::serverToCanonical(glm::vec3(info.x, info.y, info.z));
|
||||
float canYaw = core::coords::serverToCanonicalYaw(info.orientation);
|
||||
|
||||
// Handle transport attachment: attach/detach the entity so it follows the transport
|
||||
// smoothly between movement updates via updateAttachedTransportChildren().
|
||||
if (onTransport && transportGuid != 0 && transportManager_) {
|
||||
glm::vec3 localCanonical = core::coords::serverToCanonical(glm::vec3(tLocalX, tLocalY, tLocalZ));
|
||||
setTransportAttachment(moverGuid, entity->getType(), transportGuid, localCanonical, true,
|
||||
core::coords::serverToCanonicalYaw(tLocalO));
|
||||
// Derive world position from transport system for best accuracy.
|
||||
glm::vec3 worldPos = transportManager_->getPlayerWorldPosition(transportGuid, localCanonical);
|
||||
canonical = worldPos;
|
||||
} else if (!onTransport) {
|
||||
// Player left transport — clear any stale attachment.
|
||||
clearTransportAttachment(moverGuid);
|
||||
}
|
||||
// Compute a smoothed interpolation window for this player.
|
||||
// Using a raw packet delta causes jitter when timing spikes (e.g. 50ms then 300ms).
|
||||
// An exponential moving average of intervals gives a stable playback speed that
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue