private static MovementInfo ReadMovementUpdateBlock(Packet packet, CreateObject createObject, WowGuid guid, WoWObject obj, object index) { var moveInfo = new MovementInfo(); packet.ResetBitReader(); packet.ReadBit("NoBirthAnim", index); packet.ReadBit("EnablePortals", index); packet.ReadBit("PlayHoverAnim", index); var hasMovementUpdate = packet.ReadBit("HasMovementUpdate", index); var hasMovementTransport = packet.ReadBit("HasMovementTransport", index); var hasStationaryPosition = packet.ReadBit("Stationary", index); var hasCombatVictim = packet.ReadBit("HasCombatVictim", index); var hasServerTime = packet.ReadBit("HasServerTime", index); var hasVehicleCreate = packet.ReadBit("HasVehicleCreate", index); var hasAnimKitCreate = packet.ReadBit("HasAnimKitCreate", index); var hasRotation = packet.ReadBit("HasRotation", index); var hasAreaTrigger = packet.ReadBit("HasAreaTrigger", index); var hasGameObject = packet.ReadBit("HasGameObject", index); var hasSmoothPhasing = packet.ReadBit("HasSmoothPhasing", index); packet.ReadBit("ThisIsYou", index); var sceneObjCreate = packet.ReadBit("SceneObjCreate", index); var playerCreateData = packet.ReadBit("HasPlayerCreateData", index); var hasConversation = packet.ReadBit("HasConversation", index); if (hasMovementUpdate) { var movementUpdate = createObject.Movement = new(); packet.ResetBitReader(); movementUpdate.Mover = packet.ReadPackedGuid128("MoverGUID", index); movementUpdate.MoveTime = packet.ReadUInt32("MoveTime", index); movementUpdate.Position = moveInfo.Position = packet.ReadVector3("Position", index); movementUpdate.Orientation = moveInfo.Orientation = packet.ReadSingle("Orientation", index); movementUpdate.Pitch = packet.ReadSingle("Pitch", index); movementUpdate.StepUpStartElevation = packet.ReadSingle("StepUpStartElevation", index); var removeForcesIDsCount = packet.ReadInt32(); movementUpdate.MoveIndex = packet.ReadInt32("MoveIndex", index); for (var i = 0; i < removeForcesIDsCount; i++) { packet.ReadPackedGuid128("RemoveForcesIDs", index, i); } moveInfo.Flags = (MovementFlag)packet.ReadBitsE <V6_0_2_19033.Enums.MovementFlag>("Movement Flags", 30, index); moveInfo.FlagsExtra = (MovementFlagExtra)packet.ReadBitsE <Enums.MovementFlags2>("Extra Movement Flags", 18, index); var hasTransport = packet.ReadBit("Has Transport Data", index); var hasFall = packet.ReadBit("Has Fall Data", index); packet.ReadBit("HasSpline", index); packet.ReadBit("HeightChangeFailed", index); packet.ReadBit("RemoteTimeValid", index); if (hasTransport) { movementUpdate.Transport = ReadTransportData(moveInfo, guid, packet, index); } if (hasFall) { packet.ResetBitReader(); movementUpdate.FallTime = packet.ReadUInt32("Fall Time", index); movementUpdate.JumpVelocity = packet.ReadSingle("JumpVelocity", index); var hasFallDirection = packet.ReadBit("Has Fall Direction", index); if (hasFallDirection) { packet.ReadVector2("Fall", index); packet.ReadSingle("Horizontal Speed", index); } } movementUpdate.WalkSpeed = moveInfo.WalkSpeed = packet.ReadSingle("WalkSpeed", index) / 2.5f; movementUpdate.RunSpeed = moveInfo.RunSpeed = packet.ReadSingle("RunSpeed", index) / 7.0f; packet.ReadSingle("RunBackSpeed", index); packet.ReadSingle("SwimSpeed", index); packet.ReadSingle("SwimBackSpeed", index); packet.ReadSingle("FlightSpeed", index); packet.ReadSingle("FlightBackSpeed", index); packet.ReadSingle("TurnRate", index); packet.ReadSingle("PitchRate", index); var movementForceCount = packet.ReadUInt32("MovementForceCount", index); if (ClientVersion.AddedInVersion(ClientVersionBuild.V8_1_0_28724)) { packet.ReadSingle("MovementForcesModMagnitude", index); } packet.ResetBitReader(); moveInfo.HasSplineData = packet.ReadBit("HasMovementSpline", index); for (var i = 0; i < movementForceCount; ++i) { packet.ResetBitReader(); packet.ReadPackedGuid128("Id", index); packet.ReadVector3("Origin", index); packet.ReadVector3("Direction", index); packet.ReadUInt32("TransportID", index); packet.ReadSingle("Magnitude", index); packet.ReadBits("Type", 2, index); if (ClientVersion.AddedInVersion(ClientVersionBuild.V9_1_0_39185)) { var unused910 = packet.ReadBit(); if (unused910) { packet.ReadInt32("Unused910", index); } } } if (moveInfo.HasSplineData) { var splineData = movementUpdate.SplineData = new(); packet.ResetBitReader(); splineData.Id = packet.ReadInt32("ID", index); splineData.Destination = packet.ReadVector3("Destination", index); var hasMovementSplineMove = packet.ReadBit("MovementSplineMove", index); if (hasMovementSplineMove) { var moveData = splineData.MoveData = new(); packet.ResetBitReader(); moveData.Flags = packet.ReadUInt32E <SplineFlag>("SplineFlags", index).ToUniversal(); moveData.Elapsed = packet.ReadInt32("Elapsed", index); moveData.Duration = packet.ReadUInt32("Duration", index); moveData.DurationModifier = packet.ReadSingle("DurationModifier", index); moveData.NextDurationModifier = packet.ReadSingle("NextDurationModifier", index); var face = packet.ReadBits("Face", 2, index); var hasSpecialTime = packet.ReadBit("HasSpecialTime", index); var pointsCount = packet.ReadBits("PointsCount", 16, index); if (ClientVersion.RemovedInVersion(ClientType.Shadowlands)) { packet.ReadBitsE <SplineMode>("Mode", 2, index); } var hasSplineFilterKey = packet.ReadBit("HasSplineFilterKey", index); var hasSpellEffectExtraData = packet.ReadBit("HasSpellEffectExtraData", index); var hasJumpExtraData = packet.ReadBit("HasJumpExtraData", index); var hasAnimationTierTransition = false; var hasUnknown901 = false; if (ClientVersion.AddedInVersion(ClientType.Shadowlands)) { hasAnimationTierTransition = packet.ReadBit("HasAnimationTierTransition", index); hasUnknown901 = packet.ReadBit("Unknown901", index); } if (hasSplineFilterKey) { packet.ResetBitReader(); var filterKeysCount = packet.ReadUInt32("FilterKeysCount", index); for (var i = 0; i < filterKeysCount; ++i) { packet.ReadSingle("In", index, i); packet.ReadSingle("Out", index, i); } packet.ReadBits("FilterFlags", 2, index); } switch (face) { case 1: moveData.LookPosition = packet.ReadVector3("FaceSpot", index); break; case 2: moveData.LookTarget = new() { Target = packet.ReadPackedGuid128("FaceGUID", index) }; break; case 3: moveData.LookOrientation = packet.ReadSingle("FaceDirection", index); break; default: break; } if (hasSpecialTime) { packet.ReadUInt32("SpecialTime", index); } for (var i = 0; i < pointsCount; ++i) { moveData.Points.Add(packet.ReadVector3("Points", index, i)); } if (hasSpellEffectExtraData) { MovementHandler.ReadMonsterSplineSpellEffectExtraData(packet, index); } if (hasJumpExtraData) { moveData.Jump = MovementHandler.ReadMonsterSplineJumpExtraData(packet, index); } if (hasAnimationTierTransition) { packet.ReadInt32("TierTransitionID", index); packet.ReadInt32("StartTime", index); packet.ReadInt32("EndTime", index); packet.ReadByte("AnimTier", index); } if (hasUnknown901) { for (var i = 0; i < 16; ++i) { packet.ReadInt32("Unknown1", index, "Unknown901", i); packet.ReadInt32("Unknown2", index, "Unknown901", i); packet.ReadInt32("Unknown3", index, "Unknown901", i); packet.ReadInt32("Unknown4", index, "Unknown901", i); } } } } } var pauseTimesCount = packet.ReadUInt32("PauseTimesCount", index); if (hasStationaryPosition) { moveInfo.Position = packet.ReadVector3(); moveInfo.Orientation = packet.ReadSingle(); packet.AddValue("Stationary Position", moveInfo.Position, index); packet.AddValue("Stationary Orientation", moveInfo.Orientation, index); createObject.Stationary = new() { Position = moveInfo.Position, Orientation = moveInfo.Orientation }; } if (hasCombatVictim) { packet.ReadPackedGuid128("CombatVictim Guid", index); } if (hasServerTime) { packet.ReadUInt32("ServerTime", index); } if (hasVehicleCreate) { var vehicle = createObject.Vehicle = new(); moveInfo.VehicleId = (uint)packet.ReadInt32("RecID", index); vehicle.VehicleId = (int)moveInfo.VehicleId; vehicle.InitialRawFacing = packet.ReadSingle("InitialRawFacing", index); } if (hasAnimKitCreate) { var aiId = packet.ReadUInt16("AiID", index); var movementId = packet.ReadUInt16("MovementID", index); var meleeId = packet.ReadUInt16("MeleeID", index); if (obj is Unit unit) { unit.AIAnimKit = aiId; unit.MovementAnimKit = movementId; unit.MeleeAnimKit = meleeId; } else if (obj is GameObject gob) { gob.AIAnimKitID = aiId; } } if (hasRotation) { createObject.Rotation = moveInfo.Rotation = packet.ReadPackedQuaternion("GameObject Rotation", index); } for (var i = 0; i < pauseTimesCount; ++i) { packet.ReadUInt32("PauseTimes", index, i); } if (hasMovementTransport) { createObject.Transport = ReadTransportData(moveInfo, guid, packet, index); } if (hasAreaTrigger && obj is AreaTriggerCreateProperties) { AreaTriggerTemplate areaTriggerTemplate = new AreaTriggerTemplate { Id = guid.GetEntry() }; AreaTriggerCreateProperties spellAreaTrigger = (AreaTriggerCreateProperties)obj; spellAreaTrigger.AreaTriggerId = guid.GetEntry(); packet.ResetBitReader(); // CliAreaTrigger packet.ReadUInt32("ElapsedMs", index); packet.ReadVector3("RollPitchYaw1", index); areaTriggerTemplate.Flags = 0; if (packet.ReadBit("HasAbsoluteOrientation", index)) { areaTriggerTemplate.Flags |= (uint)AreaTriggerFlags.HasAbsoluteOrientation; } if (packet.ReadBit("HasDynamicShape", index)) { areaTriggerTemplate.Flags |= (uint)AreaTriggerFlags.HasDynamicShape; } if (packet.ReadBit("HasAttached", index)) { areaTriggerTemplate.Flags |= (uint)AreaTriggerFlags.HasAttached; } if (packet.ReadBit("HasFaceMovementDir", index)) { areaTriggerTemplate.Flags |= (uint)AreaTriggerFlags.FaceMovementDirection; } if (packet.ReadBit("HasFollowsTerrain", index)) { areaTriggerTemplate.Flags |= (uint)AreaTriggerFlags.FollowsTerrain; } if (packet.ReadBit("Unk bit WoD62x", index)) { areaTriggerTemplate.Flags |= (uint)AreaTriggerFlags.Unk1; } if (packet.ReadBit("HasTargetRollPitchYaw", index)) { areaTriggerTemplate.Flags |= (uint)AreaTriggerFlags.HasTargetRollPitchYaw; } bool hasScaleCurveID = packet.ReadBit("HasScaleCurveID", index); bool hasMorphCurveID = packet.ReadBit("HasMorphCurveID", index); bool hasFacingCurveID = packet.ReadBit("HasFacingCurveID", index); bool hasMoveCurveID = packet.ReadBit("HasMoveCurveID", index); bool hasAnimProgress = false; if (ClientVersion.RemovedInVersion(ClientVersionBuild.V9_1_5_40772)) { if (packet.ReadBit("HasAnimID", index)) { areaTriggerTemplate.Flags |= (uint)AreaTriggerFlags.HasAnimId; } if (packet.ReadBit("HasAnimKitID", index)) { areaTriggerTemplate.Flags |= (uint)AreaTriggerFlags.HasAnimKitId; } if (packet.ReadBit("unkbit50", index)) { areaTriggerTemplate.Flags |= (uint)AreaTriggerFlags.Unk3; } hasAnimProgress = packet.ReadBit("HasAnimProgress", index); } if (packet.ReadBit("HasAreaTriggerSphere", index)) { areaTriggerTemplate.Type = (byte)AreaTriggerType.Sphere; } if (packet.ReadBit("HasAreaTriggerBox", index)) { areaTriggerTemplate.Type = (byte)AreaTriggerType.Box; } if (packet.ReadBit("HasAreaTriggerPolygon", index)) { areaTriggerTemplate.Type = (byte)AreaTriggerType.Polygon; } if (packet.ReadBit("HasAreaTriggerCylinder", index)) { areaTriggerTemplate.Type = (byte)AreaTriggerType.Cylinder; } bool hasAreaTriggerSpline = packet.ReadBit("HasAreaTriggerSpline", index); if (packet.ReadBit("HasAreaTriggerOrbit", index)) { areaTriggerTemplate.Flags |= (uint)AreaTriggerFlags.HasOrbit; } if (ClientVersion.AddedInVersion(ClientType.Shadowlands)) { if (packet.ReadBit("HasAreaTriggerMovementScript", index)) // seen with spellid 343597 { areaTriggerTemplate.Flags |= (uint)AreaTriggerFlags.HasMovementScript; } } if ((areaTriggerTemplate.Flags & (uint)AreaTriggerFlags.Unk3) != 0) { packet.ReadBit(); } if (hasAreaTriggerSpline) { foreach (var splinePoint in AreaTriggerHandler.ReadAreaTriggerSpline(spellAreaTrigger, packet, index, "AreaTriggerSpline")) { Storage.AreaTriggerCreatePropertiesSplinePoints.Add(splinePoint); } } if ((areaTriggerTemplate.Flags & (uint)AreaTriggerFlags.HasTargetRollPitchYaw) != 0) { packet.ReadVector3("TargetRollPitchYaw", index); } if (hasScaleCurveID) { spellAreaTrigger.ScaleCurveId = (int)packet.ReadUInt32("ScaleCurveID", index); } if (hasMorphCurveID) { spellAreaTrigger.MorphCurveId = (int)packet.ReadUInt32("MorphCurveID", index); } if (hasFacingCurveID) { spellAreaTrigger.FacingCurveId = (int)packet.ReadUInt32("FacingCurveID", index); } if (hasMoveCurveID) { spellAreaTrigger.MoveCurveId = (int)packet.ReadUInt32("MoveCurveID", index); } if ((areaTriggerTemplate.Flags & (int)AreaTriggerFlags.HasAnimId) != 0) { spellAreaTrigger.AnimId = packet.ReadInt32("AnimId", index); } if ((areaTriggerTemplate.Flags & (int)AreaTriggerFlags.HasAnimKitId) != 0) { spellAreaTrigger.AnimKitId = packet.ReadInt32("AnimKitId", index); } if (hasAnimProgress) { packet.ReadUInt32("AnimProgress", index); } if (areaTriggerTemplate.Type == (byte)AreaTriggerType.Sphere) { areaTriggerTemplate.Data[0] = packet.ReadSingle("Radius", index); areaTriggerTemplate.Data[1] = packet.ReadSingle("RadiusTarget", index); } if (areaTriggerTemplate.Type == (byte)AreaTriggerType.Box) { Vector3 Extents = packet.ReadVector3("Extents", index); Vector3 ExtentsTarget = packet.ReadVector3("ExtentsTarget", index); areaTriggerTemplate.Data[0] = Extents.X; areaTriggerTemplate.Data[1] = Extents.Y; areaTriggerTemplate.Data[2] = Extents.Z; areaTriggerTemplate.Data[3] = ExtentsTarget.X; areaTriggerTemplate.Data[4] = ExtentsTarget.Y; areaTriggerTemplate.Data[5] = ExtentsTarget.Z; } if (areaTriggerTemplate.Type == (byte)AreaTriggerType.Polygon) { var verticesCount = packet.ReadUInt32("VerticesCount", index); var verticesTargetCount = packet.ReadUInt32("VerticesTargetCount", index); List <AreaTriggerCreatePropertiesPolygonVertex> verticesList = new List <AreaTriggerCreatePropertiesPolygonVertex>(); areaTriggerTemplate.Data[0] = packet.ReadSingle("Height", index); areaTriggerTemplate.Data[1] = packet.ReadSingle("HeightTarget", index); for (uint i = 0; i < verticesCount; ++i) { AreaTriggerCreatePropertiesPolygonVertex spellAreatriggerVertices = new AreaTriggerCreatePropertiesPolygonVertex { areatriggerGuid = guid, Idx = i }; Vector2 vertices = packet.ReadVector2("Vertices", index, i); spellAreatriggerVertices.VerticeX = vertices.X; spellAreatriggerVertices.VerticeY = vertices.Y; verticesList.Add(spellAreatriggerVertices); } for (var i = 0; i < verticesTargetCount; ++i) { Vector2 verticesTarget = packet.ReadVector2("VerticesTarget", index, i); verticesList[i].VerticeTargetX = verticesTarget.X; verticesList[i].VerticeTargetY = verticesTarget.Y; } foreach (AreaTriggerCreatePropertiesPolygonVertex vertice in verticesList) { Storage.AreaTriggerCreatePropertiesPolygonVertices.Add(vertice); } } if (areaTriggerTemplate.Type == (byte)AreaTriggerType.Cylinder) { areaTriggerTemplate.Data[0] = packet.ReadSingle("Radius", index); areaTriggerTemplate.Data[1] = packet.ReadSingle("RadiusTarget", index); areaTriggerTemplate.Data[2] = packet.ReadSingle("Height", index); areaTriggerTemplate.Data[3] = packet.ReadSingle("HeightTarget", index); areaTriggerTemplate.Data[4] = packet.ReadSingle("LocationZOffset", index); areaTriggerTemplate.Data[5] = packet.ReadSingle("LocationZOffsetTarget", index); } if ((areaTriggerTemplate.Flags & (uint)AreaTriggerFlags.HasMovementScript) != 0) { packet.ReadInt32("SpellScriptID"); packet.ReadVector3("Center"); } if ((areaTriggerTemplate.Flags & (uint)AreaTriggerFlags.HasOrbit) != 0) { Storage.AreaTriggerCreatePropertiesOrbits.Add(AreaTriggerHandler.ReadAreaTriggerOrbit(guid, packet, index, "AreaTriggerOrbit")); } spellAreaTrigger.Shape = areaTriggerTemplate.Type; Array.Copy(areaTriggerTemplate.Data, spellAreaTrigger.ShapeData, Math.Min(areaTriggerTemplate.Data.Length, spellAreaTrigger.ShapeData.Length)); Storage.AreaTriggerTemplates.Add(areaTriggerTemplate); } if (hasGameObject) { packet.ResetBitReader(); var worldEffectId = packet.ReadUInt32("WorldEffectID", index); if (worldEffectId != 0 && obj is GameObject gob) { gob.WorldEffectID = worldEffectId; } var bit8 = packet.ReadBit("bit8", index); if (bit8) { packet.ReadUInt32("Int1", index); } } if (hasSmoothPhasing) { packet.ResetBitReader(); packet.ReadBit("ReplaceActive", index); if (ClientVersion.AddedInVersion(ClientType.Shadowlands)) { packet.ReadBit("StopAnimKits", index); } var replaceObject = packet.ReadBit(); if (replaceObject) { packet.ReadPackedGuid128("ReplaceObject", index); } } if (sceneObjCreate) { packet.ResetBitReader(); var hasSceneLocalScriptData = packet.ReadBit("HasSceneLocalScriptData", index); var petBattleFullUpdate = packet.ReadBit("HasPetBattleFullUpdate", index); if (hasSceneLocalScriptData) { packet.ResetBitReader(); var dataLength = packet.ReadBits(7); packet.ReadWoWString("Data", dataLength, index); } if (petBattleFullUpdate) { V6_0_2_19033.Parsers.BattlePetHandler.ReadPetBattleFullUpdate(packet, index); } } if (playerCreateData) { packet.ResetBitReader(); var hasSceneInstanceIDs = packet.ReadBit("ScenePendingInstances", index); var hasRuneState = packet.ReadBit("Runes", index); if (hasSceneInstanceIDs) { var sceneInstanceIDs = packet.ReadUInt32("SceneInstanceIDsCount"); for (var i = 0; i < sceneInstanceIDs; ++i) { packet.ReadInt32("SceneInstanceIDs", index, i); } } if (hasRuneState) { packet.ReadByte("RechargingRuneMask", index); packet.ReadByte("UsableRuneMask", index); var runeCount = packet.ReadUInt32(); for (var i = 0; i < runeCount; ++i) { packet.ReadByte("RuneCooldown", index, i); } } } if (hasConversation) { packet.ResetBitReader(); if (packet.ReadBit("HasTextureKitID", index)) { (obj as ConversationTemplate).TextureKitId = packet.ReadUInt32("TextureKitID", index); } } return(moveInfo); } }