diff --git a/src/server/game/Entities/Unit/UnitDefines.h b/src/server/game/Entities/Unit/UnitDefines.h index 11139a02d47..4b68fc3b1d2 100644 --- a/src/server/game/Entities/Unit/UnitDefines.h +++ b/src/server/game/Entities/Unit/UnitDefines.h @@ -278,23 +278,23 @@ enum MovementFlags : uint32 enum MovementFlags2 : uint32 { - MOVEMENTFLAG2_NONE = 0x00000000, - MOVEMENTFLAG2_NO_STRAFE = 0x00000001, - MOVEMENTFLAG2_NO_JUMPING = 0x00000002, - MOVEMENTFLAG2_FULL_SPEED_TURNING = 0x00000004, - MOVEMENTFLAG2_FULL_SPEED_PITCHING = 0x00000008, - MOVEMENTFLAG2_ALWAYS_ALLOW_PITCHING = 0x00000010, - MOVEMENTFLAG2_UNK5 = 0x00000020, - MOVEMENTFLAG2_UNK6 = 0x00000040, - MOVEMENTFLAG2_UNK7 = 0x00000080, - MOVEMENTFLAG2_UNK8 = 0x00000100, - MOVEMENTFLAG2_UNK9 = 0x00000200, - MOVEMENTFLAG2_CAN_SWIM_TO_FLY_TRANS = 0x00000400, - MOVEMENTFLAG2_UNK11 = 0x00000800, - MOVEMENTFLAG2_AWAITING_LOAD = 0x00001000, - MOVEMENTFLAG2_INTERPOLATED_MOVEMENT = 0x00002000, - MOVEMENTFLAG2_INTERPOLATED_TURNING = 0x00004000, - MOVEMENTFLAG2_INTERPOLATED_PITCHING = 0x00008000 + MOVEMENTFLAG2_NONE = 0x00000000, + MOVEMENTFLAG2_NO_STRAFE = 0x00000001, + MOVEMENTFLAG2_NO_JUMPING = 0x00000002, + MOVEMENTFLAG2_FULL_SPEED_TURNING = 0x00000004, + MOVEMENTFLAG2_FULL_SPEED_PITCHING = 0x00000008, + MOVEMENTFLAG2_ALWAYS_ALLOW_PITCHING = 0x00000010, + MOVEMENTFLAG2_IS_VEHICLE_EXIT_VOLUNTARY = 0x00000020, + MOVEMENTFLAG2_UNK6 = 0x00000040, + MOVEMENTFLAG2_UNK7 = 0x00000080, + MOVEMENTFLAG2_UNK8 = 0x00000100, + MOVEMENTFLAG2_UNK9 = 0x00000200, + MOVEMENTFLAG2_CAN_SWIM_TO_FLY_TRANS = 0x00000400, + MOVEMENTFLAG2_UNK11 = 0x00000800, + MOVEMENTFLAG2_AWAITING_LOAD = 0x00001000, + MOVEMENTFLAG2_INTERPOLATED_MOVEMENT = 0x00002000, + MOVEMENTFLAG2_INTERPOLATED_TURNING = 0x00004000, + MOVEMENTFLAG2_INTERPOLATED_PITCHING = 0x00008000 }; enum HitInfo diff --git a/src/server/game/Movement/Spline/MoveSpline.h b/src/server/game/Movement/Spline/MoveSpline.h index 9f0d684b548..406e44e77a7 100644 --- a/src/server/game/Movement/Spline/MoveSpline.h +++ b/src/server/game/Movement/Spline/MoveSpline.h @@ -22,6 +22,15 @@ #include "MoveSplineInitArgs.h" #include +namespace WorldPackets +{ + namespace Movement + { + class CommonMovement; + class MonsterMove; + } +} + enum class AnimationTier : uint8; namespace Movement @@ -41,6 +50,8 @@ namespace Movement // point can have vertical acceleration motion componemt(used in fall, parabolic movement) class TC_GAME_API MoveSpline { + friend class WorldPackets::Movement::MonsterMove; + public: typedef Spline MySpline; enum UpdateResult diff --git a/src/server/game/Movement/Spline/MoveSplineInit.cpp b/src/server/game/Movement/Spline/MoveSplineInit.cpp index 62a42ff0b60..c0c275b03c7 100644 --- a/src/server/game/Movement/Spline/MoveSplineInit.cpp +++ b/src/server/game/Movement/Spline/MoveSplineInit.cpp @@ -16,6 +16,7 @@ */ #include "MoveSplineInit.h" +#include "MovementPackets.h" #include "MoveSpline.h" #include "MovementPacketBuilder.h" #include "Creature.h" @@ -119,17 +120,20 @@ namespace Movement unit->m_movementInfo.SetMovementFlags(moveFlags); move_spline.Initialize(args); - WorldPacket data(SMSG_MONSTER_MOVE, 64); - data << unit->GetPackGUID(); - if (unit->GetTransGUID()) + WorldPackets::Movement::MonsterMove packet(transport); + packet.MoverGUID = unit->GetGUID(); + packet.Pos = Position(real_position.x, real_position.y, real_position.z, real_position.orientation); + packet.InitializeSplineData(move_spline); + if (unit->m_movementInfo.HasExtraMovementFlag(MOVEMENTFLAG2_IS_VEHICLE_EXIT_VOLUNTARY)) + packet.SplineData.Move.VehicleExitVoluntary = true; + + if (transport) { - data.SetOpcode(SMSG_MONSTER_MOVE_TRANSPORT); - data << unit->GetTransGUID().WriteAsPacked(); - data << int8(unit->GetTransSeat()); + packet.SplineData.Move.TransportGUID = unit->GetTransGUID(); + packet.SplineData.Move.VehicleSeat = unit->GetTransSeat(); } - PacketBuilder::WriteMonsterMove(move_spline, data); - unit->SendMessageToSet(&data, true); + unit->SendMessageToSet(packet.Write(), true); return move_spline.Duration(); } @@ -165,17 +169,18 @@ namespace Movement move_spline.onTransport = transport; move_spline.Initialize(args); - WorldPacket data(SMSG_MONSTER_MOVE, 64); - data << unit->GetPackGUID(); + WorldPackets::Movement::MonsterMove packet(transport); + packet.MoverGUID = unit->GetGUID(); + packet.Pos = Position(loc.x, loc.y, loc.z, loc.orientation); + packet.SplineData.ID = move_spline.GetId(); + packet.SplineData.Move.Face = MONSTER_MOVE_STOP; + if (transport) { - data.SetOpcode(SMSG_MONSTER_MOVE_TRANSPORT); - data << unit->GetTransGUID().WriteAsPacked(); - data << int8(unit->GetTransSeat()); + packet.SplineData.Move.TransportGUID = unit->GetTransGUID(); + packet.SplineData.Move.VehicleSeat = unit->GetTransSeat(); } - - PacketBuilder::WriteStopMovement(loc, args.splineId, data); - unit->SendMessageToSet(&data, true); + unit->SendMessageToSet(packet.Write(), true); } MoveSplineInit::MoveSplineInit(Unit* m) : unit(m) diff --git a/src/server/game/Movement/Spline/MovementPacketBuilder.cpp b/src/server/game/Movement/Spline/MovementPacketBuilder.cpp index 6001cda01f4..1f8364a5725 100644 --- a/src/server/game/Movement/Spline/MovementPacketBuilder.cpp +++ b/src/server/game/Movement/Spline/MovementPacketBuilder.cpp @@ -33,118 +33,6 @@ namespace Movement b >> v.x >> v.y >> v.z; } - enum MonsterMoveType - { - MonsterMoveNormal = 0, - MonsterMoveStop = 1, - MonsterMoveFacingSpot = 2, - MonsterMoveFacingTarget = 3, - MonsterMoveFacingAngle = 4 - }; - - void PacketBuilder::WriteCommonMonsterMovePart(const MoveSpline& move_spline, WorldPacket& data) - { - MoveSplineFlag splineflags = move_spline.splineflags; - - data << uint8(0); // sets/unsets MOVEMENTFLAG2_UNK7 (0x40) - data << move_spline.spline.getPoint(move_spline.spline.first()); - data << move_spline.GetId(); - - switch (splineflags & MoveSplineFlag::Mask_Final_Facing) - { - case MoveSplineFlag::Final_Target: - data << uint8(MonsterMoveFacingTarget); - data << move_spline.facing.target; - break; - case MoveSplineFlag::Final_Angle: - data << uint8(MonsterMoveFacingAngle); - data << move_spline.facing.angle; - break; - case MoveSplineFlag::Final_Point: - data << uint8(MonsterMoveFacingSpot); - data << move_spline.facing.f.x << move_spline.facing.f.y << move_spline.facing.f.z; - break; - default: - data << uint8(MonsterMoveNormal); - break; - } - - data << uint32(splineflags & uint32(~MoveSplineFlag::Mask_No_Monster_Move)); - - if (splineflags.animation) - { - data << splineflags.getAnimationId(); - data << move_spline.effect_start_time; - } - - data << move_spline.Duration(); - - if (splineflags.parabolic) - { - data << move_spline.vertical_acceleration; - data << move_spline.effect_start_time; - } - } - - void PacketBuilder::WriteStopMovement(Vector3 const& pos, uint32 splineId, ByteBuffer& data) - { - data << uint8(0); // sets/unsets MOVEMENTFLAG2_UNK7 (0x40) - data << pos; - data << splineId; - data << uint8(MonsterMoveStop); - } - - void WriteLinearPath(Spline const& spline, ByteBuffer& data) - { - uint32 last_idx = spline.getPointCount() - 3; - Vector3 const* real_path = &spline.getPoint(1); - - data << last_idx; - data << real_path[last_idx]; // destination - if (last_idx > 1) - { - Vector3 middle = (real_path[0] + real_path[last_idx]) / 2.f; - Vector3 offset; - // first and last points already appended - for (uint32 i = 1; i < last_idx; ++i) - { - offset = middle - real_path[i]; - data.appendPackXYZ(offset.x, offset.y, offset.z); - } - } - } - - void WriteUncompressedPath(Spline const& spline, ByteBuffer& data) - { - uint32 count = spline.getPointCount() - 3; - data << count; - data.append(&spline.getPoint(2), count); - } - - void WriteUncompressedCyclicPath(Spline const& spline, ByteBuffer& data) - { - uint32 count = spline.getPointCount() - 4; - data << count; - data.append(&spline.getPoint(2), count); - } - - void PacketBuilder::WriteMonsterMove(const MoveSpline& move_spline, WorldPacket& data) - { - WriteCommonMonsterMovePart(move_spline, data); - - Spline const& spline = move_spline.spline; - MoveSplineFlag splineflags = move_spline.splineflags; - if (splineflags & MoveSplineFlag::UncompressedPath) - { - if (!splineflags.cyclic) - WriteUncompressedPath(spline, data); - else - WriteUncompressedCyclicPath(spline, data); - } - else - WriteLinearPath(spline, data); - } - void PacketBuilder::WriteCreateBits(MoveSpline const& moveSpline, ByteBuffer& data) { if (!data.WriteBit(!moveSpline.Finalized())) diff --git a/src/server/game/Movement/Spline/MovementPacketBuilder.h b/src/server/game/Movement/Spline/MovementPacketBuilder.h index 97874226301..37086c963de 100644 --- a/src/server/game/Movement/Spline/MovementPacketBuilder.h +++ b/src/server/game/Movement/Spline/MovementPacketBuilder.h @@ -31,11 +31,7 @@ namespace Movement class MoveSpline; class PacketBuilder { - static void WriteCommonMonsterMovePart(const MoveSpline& mov, WorldPacket& data); public: - - static void WriteMonsterMove(const MoveSpline& mov, WorldPacket& data); - static void WriteStopMovement(Vector3 const& loc, uint32 splineId, ByteBuffer& data); static void WriteCreateBits(MoveSpline const& moveSpline, ByteBuffer& data); static void WriteCreateData(MoveSpline const& moveSpline, ByteBuffer& data); static void WriteSplineSync(MoveSpline const& moveSpline, ByteBuffer& data); diff --git a/src/server/game/Movement/Spline/MovementTypedefs.h b/src/server/game/Movement/Spline/MovementTypedefs.h index 593a91c1a30..513eef1dac7 100644 --- a/src/server/game/Movement/Spline/MovementTypedefs.h +++ b/src/server/game/Movement/Spline/MovementTypedefs.h @@ -19,7 +19,6 @@ #define TRINITYSERVER_TYPEDEFS_H #include "Common.h" - namespace G3D { class Vector3; @@ -31,6 +30,15 @@ namespace Movement using G3D::Vector3; using G3D::Vector4; + enum MonsterMoveType + { + MONSTER_MOVE_NORMAL = 0, + MONSTER_MOVE_STOP = 1, + MONSTER_MOVE_FACING_SPOT = 2, + MONSTER_MOVE_FACING_TARGET = 3, + MONSTER_MOVE_FACING_ANGLE = 4 + }; + inline uint32 SecToMS(float sec) { return static_cast(sec * 1000.f); diff --git a/src/server/game/Server/Packets/MovementPackets.cpp b/src/server/game/Server/Packets/MovementPackets.cpp index 0d80ba8d0ed..ed9c318d048 100644 --- a/src/server/game/Server/Packets/MovementPackets.cpp +++ b/src/server/game/Server/Packets/MovementPackets.cpp @@ -368,3 +368,167 @@ WorldPacket const* WorldPackets::Movement::MoveUpdateTeleport::Write() return &_worldPacket; } + +void WorldPackets::Movement::MonsterMove::InitializeSplineData(::Movement::MoveSpline const& moveSpline) +{ + SplineData.ID = moveSpline.m_Id; + WorldPackets::Movement::MovementSpline& movementSpline = SplineData.Move; + + ::Movement::MoveSplineFlag splineFlags = moveSpline.splineflags; + splineFlags.enter_cycle = moveSpline.isCyclic(); + movementSpline.Flags = uint32(splineFlags & uint32(~::Movement::MoveSplineFlag::Mask_No_Monster_Move)); + + switch (moveSpline.splineflags & ::Movement::MoveSplineFlag::Mask_Final_Facing) + { + case ::Movement::MoveSplineFlag::Final_Point: + movementSpline.Face = ::Movement::MONSTER_MOVE_FACING_SPOT; + movementSpline.FaceSpot = Position(moveSpline.facing.f.x, moveSpline.facing.f.y, moveSpline.facing.f.z); + break; + case ::Movement::MoveSplineFlag::Final_Target: + movementSpline.Face = ::Movement::MONSTER_MOVE_FACING_TARGET; + movementSpline.FaceGUID = moveSpline.facing.target; + break; + case ::Movement::MoveSplineFlag::Final_Angle: + movementSpline.Face = ::Movement::MONSTER_MOVE_FACING_ANGLE; + movementSpline.FaceDirection = moveSpline.facing.angle; + break; + default: + movementSpline.Face = ::Movement::MONSTER_MOVE_NORMAL; + break; + } + + if (splineFlags.animation) + { + movementSpline.Animation = boost::in_place(); + movementSpline.Animation->AnimTier = splineFlags.getAnimationId(); + movementSpline.Animation->TierTransStartTime = moveSpline.effect_start_time; + } + + movementSpline.MoveTime = moveSpline.Duration(); + + if (splineFlags.parabolic) + { + movementSpline.JumpExtraData = boost::in_place(); + movementSpline.JumpExtraData->JumpGravity = moveSpline.vertical_acceleration; + movementSpline.JumpExtraData->StartTime = moveSpline.effect_start_time; + } + + ::Movement::Spline const& spline = moveSpline.spline; + std::vector const& array = spline.getPoints(); + + if (splineFlags & ::Movement::MoveSplineFlag::UncompressedPath) + { + if (!splineFlags.cyclic) + { + uint32 count = spline.getPointCount() - 3; + for (uint32 i = 0; i < count; ++i) + movementSpline.Points.emplace_back(array[i + 2].x, array[i + 2].y, array[i + 2].z); + } + else + { + uint32 count = spline.getPointCount() - 3; + movementSpline.Points.emplace_back(array[1].x, array[1].y, array[1].z); + for (uint32 i = 0; i < count; ++i) + movementSpline.Points.emplace_back(array[i + 1].x, array[i + 1].y, array[i + 1].z); + } + } + else + { + uint32 lastIdx = spline.getPointCount() - 3; + G3D::Vector3 const* realPath = &spline.getPoint(1); + + movementSpline.Points.emplace_back(realPath[lastIdx].x, realPath[lastIdx].y, realPath[lastIdx].z); + + if (lastIdx > 1) + { + G3D::Vector3 middle = (realPath[0] + realPath[lastIdx]) / 2.f; + + // first and last points already appended + for (uint32 i = 1; i < lastIdx; ++i) + { + G3D::Vector3 delta = middle - realPath[i]; + movementSpline.PackedDeltas.emplace_back(delta.x, delta.y, delta.z); + } + } + } +} + +WorldPacket const* WorldPackets::Movement::MonsterMove::Write() +{ + _worldPacket << MoverGUID.WriteAsPacked(); + + if (_worldPacket.GetOpcode() == SMSG_ON_MONSTER_MOVE_TRANSPORT) + { + _worldPacket << SplineData.Move.TransportGUID.WriteAsPacked(); + _worldPacket << int8(SplineData.Move.VehicleSeat); + } + + _worldPacket << int8(SplineData.Move.VehicleExitVoluntary); + _worldPacket << Pos; + _worldPacket << SplineData; + return &_worldPacket; +} + +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Movement::MonsterSplineJumpExtraData const& jumpExtraData) +{ + data << float(jumpExtraData.JumpGravity); + data << int32(jumpExtraData.StartTime); + + return data; +} + +ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Movement::MonsterSplineAnimationExtraData const& animationExtraData) +{ + data << int8(animationExtraData.AnimTier); + data << int32(animationExtraData.TierTransStartTime); + + return data; +} + +ByteBuffer& WorldPackets::operator<<(ByteBuffer& data, Movement::MovementSpline const& movementSpline) +{ + data << int8(movementSpline.Face); + + switch (movementSpline.Face) + { + case ::Movement::MONSTER_MOVE_NORMAL: + break; + case ::Movement::MONSTER_MOVE_FACING_SPOT: + data << movementSpline.FaceSpot; + break; + case ::Movement::MONSTER_MOVE_FACING_TARGET: + data << movementSpline.FaceGUID; + break; + case ::Movement::MONSTER_MOVE_FACING_ANGLE: + data << float(movementSpline.FaceDirection); + break; + default: + return data; + } + + data << int32(movementSpline.Flags); + + if (movementSpline.Animation) + data << *movementSpline.Animation; + + data << int32(movementSpline.MoveTime); + + if (movementSpline.JumpExtraData) + data << *movementSpline.JumpExtraData; + + data << int32(movementSpline.Points.size() + movementSpline.PackedDeltas.size()); + for (TaggedPosition const& pos : movementSpline.Points) + data << pos; + for (TaggedPosition const& pos : movementSpline.PackedDeltas) + data << pos; + + return data; +} + +ByteBuffer& WorldPackets::operator<<(ByteBuffer& data, Movement::MovementMonsterSpline const& movementMonsterSpline) +{ + data << int32(movementMonsterSpline.ID); + data << movementMonsterSpline.Move; + + return data; +} diff --git a/src/server/game/Server/Packets/MovementPackets.h b/src/server/game/Server/Packets/MovementPackets.h index 2a1258553be..af60a05c446 100644 --- a/src/server/game/Server/Packets/MovementPackets.h +++ b/src/server/game/Server/Packets/MovementPackets.h @@ -22,6 +22,13 @@ #include "Object.h" #include "Optional.h" +namespace Movement +{ + template + class Spline; + class MoveSpline; +} + namespace WorldPackets { namespace Movement @@ -167,7 +174,61 @@ namespace WorldPackets MovementInfo* Status = nullptr; }; + + struct MonsterSplineJumpExtraData + { + float JumpGravity = 0.0f; + uint32 StartTime = 0; + }; + + struct MonsterSplineAnimationExtraData + { + uint8 AnimTier = 0; + uint32 TierTransStartTime = 0; + }; + + struct MovementSpline + { + uint32 Flags = 0; // Spline flags + uint8 Face = 0; // Movement direction (see MonsterMoveType enum) + uint32 MoveTime = 0; + std::vector> Points; // Spline path + int8 VehicleExitVoluntary = 0; + ObjectGuid TransportGUID; + int8 VehicleSeat = -1; + std::vector> PackedDeltas; + Optional JumpExtraData; + Optional Animation; + float FaceDirection = 0.0f; + ObjectGuid FaceGUID; + TaggedPosition FaceSpot; + }; + + struct MovementMonsterSpline + { + uint32 ID = 0; + TaggedPosition Destination; + bool CrzTeleport = false; + MovementSpline Move; + }; + + class MonsterMove final : public ServerPacket + { + public: + MonsterMove(bool onTransport) : ServerPacket(onTransport ? SMSG_ON_MONSTER_MOVE_TRANSPORT : SMSG_ON_MONSTER_MOVE) { } + + void InitializeSplineData(::Movement::MoveSpline const& moveSpline); + + WorldPacket const* Write() override; + + MovementMonsterSpline SplineData; + ObjectGuid MoverGUID; + TaggedPosition Pos; + }; } + + ByteBuffer& operator<<(ByteBuffer& data, Movement::MovementSpline const& movementSpline); + ByteBuffer& operator<<(ByteBuffer& data, Movement::MovementMonsterSpline const& movementMonsterSpline); } #endif // MovementPackets_h__ diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp index 5cd3dceeffc..2077ef0a8cb 100644 --- a/src/server/game/Server/Protocol/Opcodes.cpp +++ b/src/server/game/Server/Protocol/Opcodes.cpp @@ -1021,8 +1021,8 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_MISSILE_CANCEL, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_MODIFY_COOLDOWN, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_MONEY_NOTIFY, STATUS_UNHANDLED, CONNECTION_TYPE_REALM); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_MONSTER_MOVE, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_MONSTER_MOVE_TRANSPORT, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_ON_MONSTER_MOVE, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_ON_MONSTER_MOVE_TRANSPORT, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_MOTD, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_MOUNT_RESULT, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_MOUNTSPECIAL_ANIM, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); diff --git a/src/server/game/Server/Protocol/Opcodes.h b/src/server/game/Server/Protocol/Opcodes.h index 7d0510a6331..d6aefd4cd92 100644 --- a/src/server/game/Server/Protocol/Opcodes.h +++ b/src/server/game/Server/Protocol/Opcodes.h @@ -972,8 +972,8 @@ enum OpcodeServer SMSG_MISSILE_CANCEL = 0x3DB4, SMSG_MODIFY_COOLDOWN = 0x6016, SMSG_MONEY_NOTIFY = 0x55B6, - SMSG_MONSTER_MOVE = 0x6E17, - SMSG_MONSTER_MOVE_TRANSPORT = 0x2004, + SMSG_ON_MONSTER_MOVE = 0x6E17, + SMSG_ON_MONSTER_MOVE_TRANSPORT = 0x2004, SMSG_MOTD = 0x0A35, SMSG_MOUNT_RESULT = 0x2225, SMSG_MOUNTSPECIAL_ANIM = 0x0217,