/*
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see .
*/
#include "MovementPackets.h"
#include "MoveSpline.h"
#include "MoveSplineFlag.h"
#include "MovementTypedefs.h"
#include "PacketOperators.h"
#include "UnitDefines.h"
#include "Util.h"
ByteBuffer& operator<<(ByteBuffer& data, MovementInfo::TransportInfo const& transportInfo)
{
bool hasPrevTime = transportInfo.prevTime != 0;
bool hasVehicleId = transportInfo.vehicleId != 0;
data << transportInfo.guid; // Transport Guid
data << transportInfo.pos.GetPositionX();
data << transportInfo.pos.GetPositionY();
data << transportInfo.pos.GetPositionZ();
data << transportInfo.pos.GetOrientation();
data << transportInfo.seat; // VehicleSeatIndex
data << transportInfo.time; // MoveTime
data.WriteBit(hasPrevTime);
data.WriteBit(hasVehicleId);
data.FlushBits();
if (hasPrevTime)
data << transportInfo.prevTime; // PrevMoveTime
if (hasVehicleId)
data << transportInfo.vehicleId; // VehicleRecID
return data;
}
ByteBuffer& operator>>(ByteBuffer& data, MovementInfo::TransportInfo& transportInfo)
{
data >> transportInfo.guid; // Transport Guid
data >> transportInfo.pos.PositionXYZOStream();
data >> transportInfo.seat; // VehicleSeatIndex
data >> transportInfo.time; // MoveTime
bool hasPrevTime = data.ReadBit();
bool hasVehicleId = data.ReadBit();
if (hasPrevTime)
data >> transportInfo.prevTime; // PrevMoveTime
if (hasVehicleId)
data >> transportInfo.vehicleId; // VehicleRecID
return data;
}
ByteBuffer& operator<<(ByteBuffer& data, MovementInfo const& movementInfo)
{
bool hasTransportData = !movementInfo.transport.guid.IsEmpty();
bool hasFallDirection = movementInfo.HasMovementFlag(MOVEMENTFLAG_FALLING | MOVEMENTFLAG_FALLING_FAR);
bool hasFallData = hasFallDirection || movementInfo.jump.fallTime != 0;
bool hasSpline = false; // todo 6.x send this infos
bool hasInertia = movementInfo.inertia.has_value();
bool hasAdvFlying = movementInfo.advFlying.has_value();
bool hasDriveStatus = movementInfo.driveStatus.has_value();
bool hasStandingOnGameObjectGUID = movementInfo.standingOnGameObjectGUID.has_value();
data << movementInfo.guid;
data << uint32(movementInfo.flags);
data << uint32(movementInfo.flags2);
data << uint32(movementInfo.flags3);
data << uint32(movementInfo.time);
data << movementInfo.pos.PositionXYZOStream();
data << float(movementInfo.pitch);
data << float(movementInfo.stepUpStartElevation);
uint32 removeMovementForcesCount = 0;
data << removeMovementForcesCount;
uint32 moveIndex = 0;
data << moveIndex;
/*for (uint32 i = 0; i < removeMovementForcesCount; ++i)
{
data << ObjectGuid;
}*/
data.WriteBit(hasStandingOnGameObjectGUID);
data.WriteBit(hasTransportData);
data.WriteBit(hasFallData);
data.WriteBit(hasSpline);
data.WriteBit(false); // HeightChangeFailed
data.WriteBit(false); // RemoteTimeValid
data.WriteBit(hasInertia);
data.WriteBit(hasAdvFlying);
data.WriteBit(hasDriveStatus);
data.FlushBits();
if (hasTransportData)
data << movementInfo.transport;
if (hasStandingOnGameObjectGUID)
data << *movementInfo.standingOnGameObjectGUID;
if (hasInertia)
{
data << uint32(movementInfo.inertia->id);
data << movementInfo.inertia->force.PositionXYZStream();
data << uint32(movementInfo.inertia->lifetime);
}
if (hasAdvFlying)
{
data << float(movementInfo.advFlying->forwardVelocity);
data << float(movementInfo.advFlying->upVelocity);
}
if (hasFallData)
{
data << uint32(movementInfo.jump.fallTime);
data << float(movementInfo.jump.zspeed);
data.WriteBit(hasFallDirection);
data.FlushBits();
if (hasFallDirection)
{
data << float(movementInfo.jump.sinAngle);
data << float(movementInfo.jump.cosAngle);
data << float(movementInfo.jump.xyspeed);
}
}
if (hasDriveStatus)
{
data << float(movementInfo.driveStatus->speed);
data << float(movementInfo.driveStatus->movementAngle);
data.WriteBit(movementInfo.driveStatus->accelerating);
data.WriteBit(movementInfo.driveStatus->drifting);
data.FlushBits();
}
return data;
}
ByteBuffer& operator>>(ByteBuffer& data, MovementInfo& movementInfo)
{
//bool hasSpline = false;
data >> movementInfo.guid;
data >> movementInfo.flags;
data >> movementInfo.flags2;
data >> movementInfo.flags3;
data >> movementInfo.time;
data >> movementInfo.pos.PositionXYZOStream();
data >> movementInfo.pitch;
data >> movementInfo.stepUpStartElevation;
uint32 removeMovementForcesCount;
data >> removeMovementForcesCount;
uint32 moveIndex;
data >> moveIndex;
for (uint32 i = 0; i < removeMovementForcesCount; ++i)
{
ObjectGuid guid;
data >> guid;
}
bool hasStandingOnGameObjectGUID = data.ReadBit();
bool hasTransport = data.ReadBit();
bool hasFall = data.ReadBit();
/*hasSpline = */data.ReadBit(); // todo 6.x read this infos
data.ReadBit(); // HeightChangeFailed
data.ReadBit(); // RemoteTimeValid
bool hasInertia = data.ReadBit();
bool hasAdvFlying = data.ReadBit();
bool hasDriveStatus = data.ReadBit();
if (hasTransport)
data >> movementInfo.transport;
if (hasStandingOnGameObjectGUID)
data >> movementInfo.standingOnGameObjectGUID.emplace();
if (hasInertia)
{
movementInfo.inertia.emplace();
data >> movementInfo.inertia->id;
data >> movementInfo.inertia->force.PositionXYZStream();
data >> movementInfo.inertia->lifetime;
}
if (hasAdvFlying)
{
movementInfo.advFlying.emplace();
data >> movementInfo.advFlying->forwardVelocity;
data >> movementInfo.advFlying->upVelocity;
}
if (hasFall)
{
data >> movementInfo.jump.fallTime;
data >> movementInfo.jump.zspeed;
// ResetBitReader
bool hasFallDirection = data.ReadBit();
if (hasFallDirection)
{
data >> movementInfo.jump.sinAngle;
data >> movementInfo.jump.cosAngle;
data >> movementInfo.jump.xyspeed;
}
}
if (hasDriveStatus)
{
data.ResetBitPos();
movementInfo.driveStatus.emplace();
data >> movementInfo.driveStatus->speed;
data >> movementInfo.driveStatus->movementAngle;
movementInfo.driveStatus->accelerating = data.ReadBit();
movementInfo.driveStatus->drifting = data.ReadBit();
}
return data;
}
ByteBuffer& operator<<(ByteBuffer& data, MovementForce const& movementForce)
{
WorldPackets::Movement::CommonMovement::WriteMovementForceWithDirection(movementForce, data);
return data;
}
namespace WorldPackets::Movement
{
void ClientPlayerMovement::Read()
{
_worldPacket >> Status;
}
ByteBuffer& operator<<(ByteBuffer& data, MonsterSplineFilterKey const& monsterSplineFilterKey)
{
data << int16(monsterSplineFilterKey.Idx);
data << uint16(monsterSplineFilterKey.Speed);
return data;
}
ByteBuffer& operator<<(ByteBuffer& data, MonsterSplineFilter const& monsterSplineFilter)
{
data << Size(monsterSplineFilter.FilterKeys);
data << float(monsterSplineFilter.BaseSpeed);
data << int16(monsterSplineFilter.StartOffset);
data << float(monsterSplineFilter.DistToPrevFilterKey);
data << int16(monsterSplineFilter.AddedToStart);
for (MonsterSplineFilterKey const& filterKey : monsterSplineFilter.FilterKeys)
data << filterKey;
data << Bits<2>(monsterSplineFilter.FilterFlags);
data.FlushBits();
return data;
}
ByteBuffer& operator<<(ByteBuffer& data, MonsterSplineSpellEffectExtraData const& spellEffectExtraData)
{
data << spellEffectExtraData.TargetGUID;
data << uint32(spellEffectExtraData.SpellVisualID);
data << uint32(spellEffectExtraData.ProgressCurveID);
data << uint32(spellEffectExtraData.ParabolicCurveID);
data << float(spellEffectExtraData.JumpGravity);
return data;
}
ByteBuffer& operator<<(ByteBuffer& data, MonsterSplineJumpExtraData const& jumpExtraData)
{
data << float(jumpExtraData.JumpGravity);
data << uint32(jumpExtraData.StartTime);
data << uint32(jumpExtraData.Duration);
return data;
}
ByteBuffer& operator<<(ByteBuffer& data, MonsterSplineTurnData const& turnData)
{
data << float(turnData.StartFacing);
data << float(turnData.TotalTurnRads);
data << float(turnData.RadsPerSec);
return data;
}
ByteBuffer& operator<<(ByteBuffer& data, MonsterSplineAnimTierTransition const& animTierTransition)
{
data << int32(animTierTransition.TierTransitionID);
data << uint8(animTierTransition.AnimTier);
data << uint32(animTierTransition.StartTime);
data << uint32(animTierTransition.ExtraDuration);
return data;
}
ByteBuffer& operator<<(ByteBuffer& data, MonsterSplineUnknown901 const& unk)
{
for (MonsterSplineUnknown901::Inner const& unkInner : unk.Data)
{
data << int32(unkInner.Unknown_1);
data << unkInner.Visual;
data << uint32(unkInner.Unknown_4);
}
return data;
}
ByteBuffer& operator<<(ByteBuffer& data, MovementSpline const& movementSpline)
{
data << uint32(movementSpline.Flags);
data << uint8(movementSpline.Face);
data << int32(movementSpline.Elapsed);
data << uint32(movementSpline.MoveTime);
data << uint32(movementSpline.FadeObjectTime);
data << uint8(movementSpline.Mode);
data << movementSpline.TransportGUID;
data << int8(movementSpline.VehicleSeat);
switch (movementSpline.Face)
{
case ::Movement::MONSTER_MOVE_FACING_SPOT:
data << movementSpline.FaceSpot;
break;
case ::Movement::MONSTER_MOVE_FACING_TARGET:
data << float(movementSpline.FaceDirection);
data << movementSpline.FaceGUID;
break;
case ::Movement::MONSTER_MOVE_FACING_ANGLE:
data << float(movementSpline.FaceDirection);
break;
}
data << BitsSize<16>(movementSpline.Points);
data << Bits<1>(movementSpline.VehicleExitVoluntary);
data << Bits<1>(movementSpline.TaxiSmoothing);
data << BitsSize<16>(movementSpline.PackedDeltas);
data << OptionalInit(movementSpline.SplineFilter);
data << OptionalInit(movementSpline.SpellEffectExtraData);
data << OptionalInit(movementSpline.JumpExtraData);
data << OptionalInit(movementSpline.TurnData);
data << OptionalInit(movementSpline.AnimTierTransition);
data << OptionalInit(movementSpline.Unknown901);
data.FlushBits();
if (movementSpline.SplineFilter)
data << *movementSpline.SplineFilter;
for (TaggedPosition const& pos : movementSpline.Points)
data << pos;
for (TaggedPosition const& pos : movementSpline.PackedDeltas)
data << pos;
if (movementSpline.SpellEffectExtraData)
data << *movementSpline.SpellEffectExtraData;
if (movementSpline.JumpExtraData)
data << *movementSpline.JumpExtraData;
if (movementSpline.TurnData)
data << *movementSpline.TurnData;
if (movementSpline.AnimTierTransition)
data << *movementSpline.AnimTierTransition;
if (movementSpline.Unknown901)
data << *movementSpline.Unknown901;
return data;
}
ByteBuffer& operator<<(ByteBuffer& data, MovementMonsterSpline const& movementMonsterSpline)
{
data << movementMonsterSpline.ID;
data << Bits<1>(movementMonsterSpline.CrzTeleport);
data << Bits<1>(movementMonsterSpline.StopUseFaceDirection);
data << Bits<3>(movementMonsterSpline.StopSplineStyle);
data << movementMonsterSpline.Move;
return data;
}
void CommonMovement::WriteCreateObjectSplineDataBlock(::Movement::MoveSpline const& moveSpline, ByteBuffer& data)
{
data << uint32(moveSpline.GetId()); // ID
G3D::Vector3 dest;
if (!moveSpline.isCyclic()) // Destination
dest = moveSpline.FinalDestination();
else
{
::Movement::MoveSpline::MySpline const& spline = moveSpline._Spline();
if (spline.getPointCount() <= 1)
dest = G3D::Vector3::zero();
else
dest = spline.getPoint(spline.last() - 1);
}
data << dest.x << dest.y << dest.z;
bool hasSplineMove = !moveSpline.Finalized() && !moveSpline.splineIsFacingOnly;
data << Bits<1>(hasSplineMove);
data.FlushBits();
if (hasSplineMove) // MovementSplineMove
{
data << uint32(moveSpline.splineflags.Raw.AsUnderlyingType()); // SplineFlags
data << int32(moveSpline.timePassed()); // Elapsed
data << uint32(moveSpline.Duration()); // Duration
data << float(1.0f); // DurationModifier
data << float(1.0f); // NextDurationModifier
data << Bits<2>(moveSpline.facing.type); // Face
bool hasFadeObjectTime = moveSpline.splineflags.FadeObject && moveSpline.effect_start_time < moveSpline.Duration();
data << Bits<1>(hasFadeObjectTime);
data << BitsSize<16>(moveSpline.getPath());
data << Bits<1>(false); // HasSplineFilter
data << OptionalInit(moveSpline.spell_effect_extra); // HasSpellEffectExtraData
bool hasJumpExtraData = moveSpline.splineflags.Parabolic && (!moveSpline.spell_effect_extra || moveSpline.effect_start_time);
data << Bits<1>(hasJumpExtraData);
data << OptionalInit(moveSpline.turn); // HasTurnData
data << OptionalInit(moveSpline.anim_tier); // HasAnimTierTransition
data.WriteBit(false); // HasUnknown901
data.FlushBits();
//if (HasSplineFilterKey)
//{
// data << uint32(FilterKeysCount);
// for (var i = 0; i < FilterKeysCount; ++i)
// {
// data << float(In);
// data << float(Out);
// }
// data.WriteBits(FilterFlags, 2);
// data.FlushBits();
//}
switch (moveSpline.facing.type)
{
case ::Movement::MONSTER_MOVE_FACING_SPOT:
{
// FaceSpot
data << float(moveSpline.facing.f.x);
data << float(moveSpline.facing.f.y);
data << float(moveSpline.facing.f.z);
break;
}
case ::Movement::MONSTER_MOVE_FACING_TARGET:
data << moveSpline.facing.target; // FaceGUID
break;
case ::Movement::MONSTER_MOVE_FACING_ANGLE:
data << moveSpline.facing.angle; // FaceDirection
break;
default:
break;
}
if (hasFadeObjectTime)
data << uint32(moveSpline.effect_start_time); // FadeObjectTime
data.append(reinterpret_cast(moveSpline.getPath().data()), moveSpline.getPath().size() * 3);
if (moveSpline.spell_effect_extra)
{
data << moveSpline.spell_effect_extra->Target;
data << uint32(moveSpline.spell_effect_extra->SpellVisualId);
data << uint32(moveSpline.spell_effect_extra->ProgressCurveId);
data << uint32(moveSpline.spell_effect_extra->ParabolicCurveId);
data << float(moveSpline.vertical_acceleration);
}
if (hasJumpExtraData)
{
data << float(moveSpline.vertical_acceleration);
data << uint32(moveSpline.effect_start_time);
data << uint32(0); // Duration (override)
}
if (moveSpline.turn)
{
data << float(moveSpline.turn->StartFacing);
data << float(moveSpline.turn->TotalTurnRads);
data << float(moveSpline.turn->RadsPerSec);
}
if (moveSpline.anim_tier)
{
data << int32(moveSpline.anim_tier->TierTransitionId);
data << uint8(moveSpline.anim_tier->AnimTier);
data << uint32(moveSpline.effect_start_time);
data << uint32(0);
}
//if (HasUnknown901)
//{
// for (WorldPackets::Movement::MonsterSplineUnknown901::Inner const& unkInner : unk.Data) size = 16
// {
// data << int32(unkInner.Unknown_1);
// data << int32(unkInner.Unknown_2);
// data << int32(unkInner.Unknown_3);
// data << uint32(unkInner.Unknown_4);
// }
//}
}
}
void CommonMovement::WriteMovementForceWithDirection(MovementForce const& movementForce, ByteBuffer& data, Position const* objectPosition /*= nullptr*/)
{
data << movementForce.ID;
data << movementForce.Origin;
if (movementForce.Type == MovementForceType::Gravity && objectPosition)
{
TaggedPosition direction;
if (movementForce.Magnitude != 0.0f)
{
Position tmp(movementForce.Origin.Pos.GetPositionX() - objectPosition->GetPositionX(),
movementForce.Origin.Pos.GetPositionY() - objectPosition->GetPositionY(),
movementForce.Origin.Pos.GetPositionZ() - objectPosition->GetPositionZ());
float lengthSquared = tmp.GetExactDistSq(0.0f, 0.0f, 0.0f);
if (lengthSquared > 0.0f)
{
float mult = 1.0f / std::sqrt(lengthSquared) * movementForce.Magnitude;
tmp.m_positionX *= mult;
tmp.m_positionY *= mult;
tmp.m_positionZ *= mult;
float minLengthSquared = (tmp.GetPositionX() * tmp.GetPositionX() * 0.04f) +
(tmp.GetPositionY() * tmp.GetPositionY() * 0.04f) +
(tmp.GetPositionZ() * tmp.GetPositionZ() * 0.04f);
if (lengthSquared > minLengthSquared)
direction = tmp;
}
}
data << direction;
}
else
data << movementForce.Direction;
data << uint32(movementForce.TransportID);
data << float(movementForce.Magnitude);
data << int32(movementForce.MovementForceID);
data << int32(movementForce.Unknown1110_1);
data << int32(movementForce.Unused1110);
data << uint32(movementForce.Flags);
data << Bits<2>(movementForce.Type);
data.FlushBits();
}
void MonsterMove::InitializeSplineData(::Movement::MoveSpline const& moveSpline)
{
SplineData.ID = moveSpline.m_Id;
MovementSpline& movementSpline = SplineData.Move;
::Movement::MoveSplineFlag splineFlags = moveSpline.splineflags;
movementSpline.Flags = uint32(splineFlags & ~::Movement::MoveSplineFlagEnum::Mask_No_Monster_Move);
movementSpline.Face = moveSpline.facing.type;
movementSpline.FaceDirection = moveSpline.facing.angle;
movementSpline.FaceGUID = moveSpline.facing.target;
movementSpline.FaceSpot = Position(moveSpline.facing.f.x, moveSpline.facing.f.y, moveSpline.facing.f.z);
if (moveSpline.anim_tier)
{
movementSpline.AnimTierTransition.emplace();
movementSpline.AnimTierTransition->TierTransitionID = moveSpline.anim_tier->TierTransitionId;
movementSpline.AnimTierTransition->StartTime = moveSpline.effect_start_time;
movementSpline.AnimTierTransition->AnimTier = AsUnderlyingType(moveSpline.anim_tier->AnimTier);
}
movementSpline.MoveTime = moveSpline.Duration();
if (splineFlags.Parabolic && (!moveSpline.spell_effect_extra || moveSpline.effect_start_time))
{
movementSpline.JumpExtraData.emplace();
movementSpline.JumpExtraData->JumpGravity = moveSpline.vertical_acceleration;
movementSpline.JumpExtraData->StartTime = moveSpline.effect_start_time;
}
if (moveSpline.turn)
{
MonsterSplineTurnData& turn = movementSpline.TurnData.emplace();
turn.StartFacing = moveSpline.turn->StartFacing;
turn.TotalTurnRads = moveSpline.turn->TotalTurnRads;
turn.RadsPerSec = moveSpline.turn->RadsPerSec;
}
if (splineFlags.FadeObject)
movementSpline.FadeObjectTime = moveSpline.effect_start_time;
if (moveSpline.spell_effect_extra)
{
movementSpline.SpellEffectExtraData.emplace();
movementSpline.SpellEffectExtraData->TargetGUID = moveSpline.spell_effect_extra->Target;
movementSpline.SpellEffectExtraData->SpellVisualID = moveSpline.spell_effect_extra->SpellVisualId;
movementSpline.SpellEffectExtraData->ProgressCurveID = moveSpline.spell_effect_extra->ProgressCurveId;
movementSpline.SpellEffectExtraData->ParabolicCurveID = moveSpline.spell_effect_extra->ParabolicCurveId;
movementSpline.SpellEffectExtraData->JumpGravity = moveSpline.vertical_acceleration;
}
::Movement::Spline const& spline = moveSpline.spline;
std::vector const& array = spline.getPoints();
if (splineFlags.UncompressedPath)
{
uint32 count = spline.getPointCount() - (splineFlags.Cyclic ? 4 : 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 lastIdx = spline.getPointCount() - (splineFlags.Cyclic ? 4 : 3);
G3D::Vector3 const* realPath = &array[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* MonsterMove::Write()
{
_worldPacket << MoverGUID;
_worldPacket << Pos;
_worldPacket << SplineData;
return &_worldPacket;
}
WorldPacket const* FlightSplineSync::Write()
{
_worldPacket << Guid;
_worldPacket << float(SplineDist);
return &_worldPacket;
}
WorldPacket const* MoveSplineSetSpeed::Write()
{
_worldPacket << MoverGUID;
_worldPacket << Speed;
return &_worldPacket;
}
WorldPacket const* MoveSetSpeed::Write()
{
_worldPacket << MoverGUID;
_worldPacket << SequenceIndex;
_worldPacket << Speed;
return &_worldPacket;
}
WorldPacket const* MoveUpdateSpeed::Write()
{
_worldPacket << *Status;
_worldPacket << Speed;
return &_worldPacket;
}
WorldPacket const* SetAdvFlyingSpeed::Write()
{
_worldPacket << MoverGUID;
_worldPacket << uint32(SequenceIndex);
_worldPacket << float(Speed);
return &_worldPacket;
}
WorldPacket const* SetAdvFlyingSpeedRange::Write()
{
_worldPacket << MoverGUID;
_worldPacket << uint32(SequenceIndex);
_worldPacket << float(SpeedMin);
_worldPacket << float(SpeedMax);
return &_worldPacket;
}
WorldPacket const* MoveSplineSetFlag::Write()
{
_worldPacket << MoverGUID;
return &_worldPacket;
}
WorldPacket const* MoveSetFlag::Write()
{
_worldPacket << MoverGUID;
_worldPacket << SequenceIndex;
return &_worldPacket;
}
WorldPacket const* MoveUpdate::Write()
{
_worldPacket << *Status;
return &_worldPacket;
}
WorldPacket const* TransferPending::Write()
{
_worldPacket << int32(MapID);
_worldPacket << OldMapPosition;
_worldPacket << OptionalInit(Ship);
_worldPacket << OptionalInit(TransferSpellID);
_worldPacket << OptionalInit(TaxiPathID);
_worldPacket.FlushBits();
if (Ship)
{
_worldPacket << uint32(Ship->ID);
_worldPacket << int32(Ship->OriginMapID);
}
if (TransferSpellID)
_worldPacket << int32(*TransferSpellID);
if (TaxiPathID)
_worldPacket << int32(*TaxiPathID);
return &_worldPacket;
}
WorldPacket const* TransferAborted::Write()
{
_worldPacket << uint32(MapID);
_worldPacket << uint8(Arg);
_worldPacket << int32(MapDifficultyXConditionID);
_worldPacket << Bits<6>(TransfertAbort);
_worldPacket.FlushBits();
return &_worldPacket;
}
ByteBuffer& operator<<(ByteBuffer& data, TeleportLocation const& teleportLocation)
{
data << teleportLocation.Pos;
data << int32(teleportLocation.FloorDifficulty);
data << int32(teleportLocation.FloorIndex);
return data;
}
WorldPacket const* NewWorld::Write()
{
_worldPacket << int32(MapID);
_worldPacket << Loc;
_worldPacket << uint32(Reason);
_worldPacket << MovementOffset;
_worldPacket << int32(Counter);
return &_worldPacket;
}
WorldPacket const* MoveTeleport::Write()
{
_worldPacket << MoverGUID;
_worldPacket << uint32(SequenceIndex);
_worldPacket << Pos;
_worldPacket << float(Facing);
_worldPacket << uint8(PreloadWorld);
_worldPacket << OptionalInit(TransportGUID);
_worldPacket << OptionalInit(Vehicle);
_worldPacket.FlushBits();
if (Vehicle)
{
_worldPacket << uint8(Vehicle->VehicleSeatIndex);
_worldPacket << Bits<1>(Vehicle->VehicleExitVoluntary);
_worldPacket << Bits<1>(Vehicle->VehicleExitTeleport);
_worldPacket.FlushBits();
}
if (TransportGUID)
_worldPacket << *TransportGUID;
return &_worldPacket;
}
ByteBuffer& operator>>(ByteBuffer& data, MovementForce& movementForce)
{
data >> movementForce.ID;
data >> movementForce.Origin;
data >> movementForce.Direction;
data >> movementForce.TransportID;
data >> movementForce.Magnitude;
data >> movementForce.MovementForceID;
data >> movementForce.Unknown1110_1;
data >> movementForce.Unused1110;
data >> movementForce.Flags;
data >> Bits<2>(movementForce.Type);
return data;
}
WorldPacket const* MoveUpdateTeleport::Write()
{
_worldPacket << *Status;
_worldPacket << uint32(MovementForces ? MovementForces->size() : 0);
_worldPacket << OptionalInit(WalkSpeed);
_worldPacket << OptionalInit(RunSpeed);
_worldPacket << OptionalInit(RunBackSpeed);
_worldPacket << OptionalInit(SwimSpeed);
_worldPacket << OptionalInit(SwimBackSpeed);
_worldPacket << OptionalInit(FlightSpeed);
_worldPacket << OptionalInit(FlightBackSpeed);
_worldPacket << OptionalInit(TurnRate);
_worldPacket << OptionalInit(PitchRate);
_worldPacket.FlushBits();
if (MovementForces)
for (MovementForce const& force : *MovementForces)
_worldPacket << force;
if (WalkSpeed)
_worldPacket << *WalkSpeed;
if (RunSpeed)
_worldPacket << *RunSpeed;
if (RunBackSpeed)
_worldPacket << *RunBackSpeed;
if (SwimSpeed)
_worldPacket << *SwimSpeed;
if (SwimBackSpeed)
_worldPacket << *SwimBackSpeed;
if (FlightSpeed)
_worldPacket << *FlightSpeed;
if (FlightBackSpeed)
_worldPacket << *FlightBackSpeed;
if (TurnRate)
_worldPacket << *TurnRate;
if (PitchRate)
_worldPacket << *PitchRate;
return &_worldPacket;
}
void MoveTeleportAck::Read()
{
_worldPacket >> MoverGUID;
_worldPacket >> AckIndex;
_worldPacket >> MoveTime;
}
ByteBuffer& operator>>(ByteBuffer& data, MovementAck& ack)
{
data >> ack.Status;
data >> ack.AckIndex;
return data;
}
void MovementAckMessage::Read()
{
_worldPacket >> Ack;
}
void MovementSpeedAck::Read()
{
_worldPacket >> Ack;
_worldPacket >> Speed;
}
void MovementSpeedRangeAck::Read()
{
_worldPacket >> Ack;
_worldPacket >> SpeedMin;
_worldPacket >> SpeedMax;
}
void SetActiveMover::Read()
{
_worldPacket >> ActiveMover;
}
WorldPacket const* MoveSetActiveMover::Write()
{
_worldPacket << MoverGUID;
return &_worldPacket;
}
ByteBuffer& operator<<(ByteBuffer& data, MoveKnockBackSpeeds const& speeds)
{
data << float(speeds.HorzSpeed);
data << float(speeds.VertSpeed);
return data;
}
ByteBuffer& operator>>(ByteBuffer& data, MoveKnockBackSpeeds& speeds)
{
data >> speeds.HorzSpeed;
data >> speeds.VertSpeed;
return data;
}
WorldPacket const* MoveKnockBack::Write()
{
_worldPacket << MoverGUID;
_worldPacket << uint32(SequenceIndex);
_worldPacket << Direction;
_worldPacket << Speeds;
return &_worldPacket;
}
WorldPacket const* MoveUpdateKnockBack::Write()
{
_worldPacket << *Status;
return &_worldPacket;
}
void MoveKnockBackAck::Read()
{
_worldPacket >> Ack;
_worldPacket >> OptionalInit(Speeds);
if (Speeds)
_worldPacket >> *Speeds;
}
WorldPacket const* MoveSetCollisionHeight::Write()
{
_worldPacket << MoverGUID;
_worldPacket << uint32(SequenceIndex);
_worldPacket << float(Height);
_worldPacket << float(Scale);
_worldPacket << uint8(Reason);
_worldPacket << uint32(MountDisplayID);
_worldPacket << int32(ScaleDuration);
return &_worldPacket;
}
WorldPacket const* MoveUpdateCollisionHeight::Write()
{
_worldPacket << *Status;
_worldPacket << float(Height);
_worldPacket << float(Scale);
return &_worldPacket;
}
WorldPacket const* MoveApplyMovementForce::Write()
{
_worldPacket << MoverGUID;
_worldPacket << SequenceIndex;
_worldPacket << *Force;
return &_worldPacket;
}
void MoveApplyMovementForceAck::Read()
{
_worldPacket >> Ack;
_worldPacket >> Force;
}
WorldPacket const* MoveRemoveMovementForce::Write()
{
_worldPacket << MoverGUID;
_worldPacket << SequenceIndex;
_worldPacket << ID;
return &_worldPacket;
}
void MoveRemoveMovementForceAck::Read()
{
_worldPacket >> Ack;
_worldPacket >> ID;
}
WorldPacket const* MoveUpdateApplyMovementForce::Write()
{
_worldPacket << *Status;
_worldPacket << *Force;
return &_worldPacket;
}
WorldPacket const* MoveUpdateRemoveMovementForce::Write()
{
_worldPacket << *Status;
_worldPacket << TriggerGUID;
return &_worldPacket;
}
void MoveSetCollisionHeightAck::Read()
{
_worldPacket >> Data;
_worldPacket >> Height;
_worldPacket >> MountDisplayID;
_worldPacket >> As(Reason);
}
void MoveTimeSkipped::Read()
{
_worldPacket >> MoverGUID;
_worldPacket >> TimeSkipped;
}
WorldPacket const* MoveSkipTime::Write()
{
_worldPacket << MoverGUID;
_worldPacket << TimeSkipped;
return &_worldPacket;
}
void SummonResponse::Read()
{
_worldPacket >> SummonerGUID;
_worldPacket >> Bits<1>(Accept);
}
WorldPacket const* ControlUpdate::Write()
{
_worldPacket << Guid;
_worldPacket << Bits<1>(On);
_worldPacket.FlushBits();
return &_worldPacket;
}
void MoveSplineDone::Read()
{
_worldPacket >> Status;
_worldPacket >> SplineID;
}
WorldPacket const* SummonRequest::Write()
{
_worldPacket << SummonerGUID;
_worldPacket << uint32(SummonerVirtualRealmAddress);
_worldPacket << int32(AreaID);
_worldPacket << uint8(Reason);
_worldPacket << Bits<1>(SkipStartingArea);
_worldPacket.FlushBits();
return &_worldPacket;
}
WorldPacket const* SuspendToken::Write()
{
_worldPacket << uint32(SequenceIndex);
_worldPacket << Bits<2>(Reason);
_worldPacket.FlushBits();
return &_worldPacket;
}
void SuspendTokenResponse::Read()
{
_worldPacket >> SequenceIndex;
}
WorldPacket const* ResumeToken::Write()
{
_worldPacket << uint32(SequenceIndex);
_worldPacket << Bits<2>(Reason);
_worldPacket.FlushBits();
return &_worldPacket;
}
ByteBuffer& operator<<(ByteBuffer& data, CollisionHeightInfo const& collisionHeightInfo)
{
data << float(collisionHeightInfo.Height);
data << float(collisionHeightInfo.Scale);
data << uint8(collisionHeightInfo.Reason);
return data;
}
ByteBuffer& operator<<(ByteBuffer& data, StateChangeRangeInfo const& stateChangeRangeInfo)
{
data << float(stateChangeRangeInfo.Min);
data << float(stateChangeRangeInfo.Max);
return data;
}
ByteBuffer& operator<<(ByteBuffer& data, KnockBackInfo const& knockBackInfo)
{
data << float(knockBackInfo.HorzSpeed);
data << knockBackInfo.Direction;
data << float(knockBackInfo.InitVertSpeed);
return data;
}
ByteBuffer& operator<<(ByteBuffer& data, MoveStateChange const& stateChange)
{
data << uint32(stateChange.MessageID);
data << uint32(stateChange.SequenceIndex);
data << OptionalInit(stateChange.Speed);
data << OptionalInit(stateChange.Range);
data << OptionalInit(stateChange.KnockBack);
data << OptionalInit(stateChange.VehicleRecID);
data << OptionalInit(stateChange.CollisionHeight);
data << OptionalInit(stateChange.MovementForce_);
data << OptionalInit(stateChange.MovementForceGUID);
data << OptionalInit(stateChange.MovementInertiaID);
data << OptionalInit(stateChange.MovementInertiaLifetimeMs);
data << OptionalInit(stateChange.DriveCapabilityRecID);
data.FlushBits();
if (stateChange.MovementForce_)
data << *stateChange.MovementForce_;
if (stateChange.Speed)
data << float(*stateChange.Speed);
if (stateChange.Range)
data << *stateChange.Range;
if (stateChange.KnockBack)
data << *stateChange.KnockBack;
if (stateChange.VehicleRecID)
data << int32(*stateChange.VehicleRecID);
if (stateChange.CollisionHeight)
data << *stateChange.CollisionHeight;
if (stateChange.MovementForceGUID)
data << *stateChange.MovementForceGUID;
if (stateChange.MovementInertiaID)
data << int32(*stateChange.MovementInertiaID);
if (stateChange.MovementInertiaLifetimeMs)
data << uint32(*stateChange.MovementInertiaLifetimeMs);
if (stateChange.DriveCapabilityRecID)
data << int32(*stateChange.DriveCapabilityRecID);
return data;
}
WorldPacket const* MoveSetCompoundState::Write()
{
_worldPacket << MoverGUID;
_worldPacket << Size(StateChanges);
for (MoveStateChange const& stateChange : StateChanges)
_worldPacket << stateChange;
return &_worldPacket;
}
void MoveInitActiveMoverComplete::Read()
{
_worldPacket >> Ticks;
}
}