From 5b67e2f539c3d849353ac801b8564f9f46941bc4 Mon Sep 17 00:00:00 2001 From: hondacrx Date: Sun, 8 Sep 2019 12:48:10 -0400 Subject: [PATCH] Core/Movement: Implemented movement forces Port From (https://github.com/TrinityCore/TrinityCore/commit/8e98ceb2936842ea0032cbfdc04a510d6b1e5de0) --- .../Constants/Spells/SpellAuraConst.cs | 2 +- Source/Game/Entities/Object/WorldObject.cs | 93 ++++++++-- Source/Game/Entities/Player/Player.Fields.cs | 1 + Source/Game/Entities/Player/Player.cs | 11 +- Source/Game/Entities/Unit/Unit.Fields.cs | 1 + Source/Game/Entities/Unit/Unit.Movement.cs | 134 ++++++++++++++ Source/Game/Handlers/MovementHandler.cs | 86 +++++++++ .../Game/Network/Packets/MovementPackets.cs | 164 +++++++++++++----- Source/Game/Spells/Auras/AuraEffect.cs | 28 ++- 9 files changed, 458 insertions(+), 62 deletions(-) diff --git a/Source/Framework/Constants/Spells/SpellAuraConst.cs b/Source/Framework/Constants/Spells/SpellAuraConst.cs index 837051af3..c6b4e4b2b 100644 --- a/Source/Framework/Constants/Spells/SpellAuraConst.cs +++ b/Source/Framework/Constants/Spells/SpellAuraConst.cs @@ -506,7 +506,7 @@ namespace Framework.Constants Unk482 = 482, SuppressTransforms = 483, // NYI Unk484 = 484, - Unk485 = 485, + ModMovementForceMagnitude = 485, Unk486 = 486, Unk487 = 487, Unk488 = 488, diff --git a/Source/Game/Entities/Object/WorldObject.cs b/Source/Game/Entities/Object/WorldObject.cs index 65a6a6920..c5b90b542 100644 --- a/Source/Game/Entities/Object/WorldObject.cs +++ b/Source/Game/Entities/Object/WorldObject.cs @@ -336,21 +336,24 @@ namespace Game.Entities data.WriteFloat(unit.GetSpeed(UnitMoveType.TurnRate)); data.WriteFloat(unit.GetSpeed(UnitMoveType.PitchRate)); - data.WriteUInt32(0); // unit.m_movementInfo.forces.size() - data.WriteFloat(1.0f); // MovementForcesModMagnitude + MovementForces movementForces = unit.GetMovementForces(); + if (movementForces != null) + { + data.WriteInt32(movementForces.GetForces().Count); + data.WriteFloat(movementForces.GetModMagnitude()); // MovementForcesModMagnitude + } + else + { + data.WriteUInt32(0); + data.WriteFloat(1.0f); // MovementForcesModMagnitude + } data.WriteBit(HasSpline); data.FlushBits(); - //for (public uint i = 0; i < unit.m_movementInfo.forces.Count; ++i) - //{ - // *data << ObjectGuid(ID); - // *data << Vector3(Origin); - // *data << Vector3(Direction); - // *data << uint32(TransportID); - // *data.WriteFloat(Magnitude); - // *data.WriteBits(Type, 2); - //} + if (movementForces != null) + foreach (MovementForce force in movementForces.GetForces()) + MovementExtensions.WriteMovementForceWithDirection(force, data, unit); // HasMovementSpline - marks that spline data is present in packet if (HasSpline) @@ -2460,6 +2463,74 @@ namespace Game.Entities } } + public class MovementForce + { + public ObjectGuid ID; + public Vector3 Origin; + public Vector3 Direction; + public uint TransportID; + public float Magnitude; + public byte Type; + + public void Read(WorldPacket data) + { + ID = data.ReadPackedGuid(); + Origin = data.ReadVector3(); + Direction = data.ReadVector3(); + TransportID = data.ReadUInt32(); + Magnitude = data.ReadFloat(); + Type = data.ReadBits(2); + + } + + public void Write(WorldPacket data) + { + MovementExtensions.WriteMovementForceWithDirection(this, data); + } + } + + public class MovementForces + { + List _forces = new List(); + float _modMagnitude = 1.0f; + + public List GetForces() { return _forces; } + + public bool Add(MovementForce newForce) + { + var movementForce = FindMovementForce(newForce.ID); + if (movementForce == null) + { + _forces.Add(newForce); + return true; + } + + return false; + } + + public bool Remove(ObjectGuid id) + { + var movementForce = FindMovementForce(id); + if (movementForce != null) + { + _forces.Remove(movementForce); + return true; + } + + return false; + } + + public float GetModMagnitude() { return _modMagnitude; } + public void SetModMagnitude(float modMagnitude) { _modMagnitude = modMagnitude; } + + public bool IsEmpty() { return _forces.Empty() && _modMagnitude == 1.0f; } + + MovementForce FindMovementForce(ObjectGuid id) + { + return _forces.Find(force => force.ID == id); + } + } + public struct CreateObjectBits { public bool NoBirthAnim; diff --git a/Source/Game/Entities/Player/Player.Fields.cs b/Source/Game/Entities/Player/Player.Fields.cs index 8c2df6cd4..abb42cd80 100644 --- a/Source/Game/Entities/Player/Player.Fields.cs +++ b/Source/Game/Entities/Player/Player.Fields.cs @@ -89,6 +89,7 @@ namespace Game.Entities //Movement public PlayerTaxi m_taxi = new PlayerTaxi(); public byte[] m_forced_speed_changes = new byte[(int)UnitMoveType.Max]; + public byte m_movementForceModMagnitudeChanges; uint m_lastFallTime; float m_lastFallZ; WorldLocation teleportDest; diff --git a/Source/Game/Entities/Player/Player.cs b/Source/Game/Entities/Player/Player.cs index e468d4258..ceebbd4fe 100644 --- a/Source/Game/Entities/Player/Player.cs +++ b/Source/Game/Entities/Player/Player.cs @@ -1972,7 +1972,7 @@ namespace Game.Entities } }); - if (!GetVehicleBase() || !GetVehicle().GetVehicleInfo().Flags.HasAnyFlag(VehicleFlags.FixedPosition)) + if (!m_unitMovedByMe.GetVehicleBase() || !m_unitMovedByMe.GetVehicle().GetVehicleInfo().Flags.HasAnyFlag(VehicleFlags.FixedPosition)) RemoveViolatingFlags(mi.HasMovementFlag(MovementFlag.Root), MovementFlag.Root); /*! This must be a packet spoofing attempt. MOVEMENTFLAG_ROOT sent from the client is not valid @@ -1982,7 +1982,7 @@ namespace Game.Entities RemoveViolatingFlags(mi.HasMovementFlag(MovementFlag.Root) && mi.HasMovementFlag(MovementFlag.MaskMoving), MovementFlag.MaskMoving); //! Cannot hover without SPELL_AURA_HOVER - RemoveViolatingFlags(mi.HasMovementFlag(MovementFlag.Hover) && !HasAuraType(AuraType.Hover), + RemoveViolatingFlags(mi.HasMovementFlag(MovementFlag.Hover) && !m_unitMovedByMe.HasAuraType(AuraType.Hover), MovementFlag.Hover); //! Cannot ascend and descend at the same time @@ -2007,10 +2007,10 @@ namespace Game.Entities //! Cannot walk on water without SPELL_AURA_WATER_WALK except for ghosts RemoveViolatingFlags(mi.HasMovementFlag(MovementFlag.WaterWalk) && - !HasAuraType(AuraType.WaterWalk) && !HasAuraType(AuraType.Ghost), MovementFlag.WaterWalk); + !m_unitMovedByMe.HasAuraType(AuraType.WaterWalk) && !m_unitMovedByMe.HasAuraType(AuraType.Ghost), MovementFlag.WaterWalk); //! Cannot feather fall without SPELL_AURA_FEATHER_FALL - RemoveViolatingFlags(mi.HasMovementFlag(MovementFlag.FallingSlow) && !HasAuraType(AuraType.FeatherFall), + RemoveViolatingFlags(mi.HasMovementFlag(MovementFlag.FallingSlow) && !m_unitMovedByMe.HasAuraType(AuraType.FeatherFall), MovementFlag.FallingSlow); /*! Cannot fly if no fly auras present. Exception is being a GM. @@ -7443,7 +7443,6 @@ namespace Game.Entities public void AddAuraVision(PlayerFieldByte2Flags flags) { SetUpdateFieldFlagValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.AuraVision), (byte)flags); } public void RemoveAuraVision(PlayerFieldByte2Flags flags) { RemoveUpdateFieldFlagValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.AuraVision), (byte)flags); } - public bool CanTameExoticPets() { return IsGameMaster() || HasAuraType(AuraType.AllowTamePetType); } void SendAttackSwingDeadTarget() { SendPacket(new AttackSwingError(AttackSwingErr.DeadTarget)); } @@ -7528,7 +7527,7 @@ namespace Game.Entities UpdateFieldFlag flags = GetUpdateFieldFlagsFor(target); WorldPacket buffer = new WorldPacket(); - buffer.WriteUInt32((uint)(m_values.GetChangedObjectTypeMask() & ~((target != this) ? 1 : 0 << (int)TypeId.ActivePlayer))); + buffer.WriteUInt32((uint)(m_values.GetChangedObjectTypeMask() & ~((target != this ? 1 : 0) << (int)TypeId.ActivePlayer))); if (m_values.HasChanged(TypeId.Object)) m_objectData.WriteUpdate(buffer, flags, this, target); diff --git a/Source/Game/Entities/Unit/Unit.Fields.cs b/Source/Game/Entities/Unit/Unit.Fields.cs index 999eef410..fbef402f2 100644 --- a/Source/Game/Entities/Unit/Unit.Fields.cs +++ b/Source/Game/Entities/Unit/Unit.Fields.cs @@ -46,6 +46,7 @@ namespace Game.Entities public uint m_movementCounter; //< Incrementing counter used in movement packets TimeTrackerSmall movesplineTimer; public Player m_playerMovingMe; + MovementForces _movementForces; //Combat protected List attackerList = new List(); diff --git a/Source/Game/Entities/Unit/Unit.Movement.cs b/Source/Game/Entities/Unit/Unit.Movement.cs index 825db7869..d071d00cc 100644 --- a/Source/Game/Entities/Unit/Unit.Movement.cs +++ b/Source/Game/Entities/Unit/Unit.Movement.cs @@ -1415,6 +1415,138 @@ namespace Game.Entities SendMessageToSet(setVehicleRec, true); } + public MovementForces GetMovementForces() { return _movementForces; } + + void ApplyMovementForce(ObjectGuid id, Vector3 origin, float magnitude, byte type, Vector3 direction, ObjectGuid transportGuid = default) + { + if (_movementForces == null) + _movementForces = new MovementForces(); + + MovementForce force = new MovementForce(); + force.ID = id; + force.Origin = origin; + force.Direction = direction; + if (transportGuid.IsMOTransport()) + force.TransportID = (uint)transportGuid.GetCounter(); + + force.Magnitude = magnitude; + force.Type = type; + + if (_movementForces.Add(force)) + { + Player movingPlayer = GetPlayerMovingMe(); + if (movingPlayer != null) + { + MoveApplyMovementForce applyMovementForce = new MoveApplyMovementForce(); + applyMovementForce.MoverGUID = GetGUID(); + applyMovementForce.SequenceIndex = (int)m_movementCounter++; + applyMovementForce.Force = force; + movingPlayer.SendPacket(applyMovementForce); + } + else + { + MoveUpdateApplyMovementForce updateApplyMovementForce = new MoveUpdateApplyMovementForce(); + updateApplyMovementForce.Status = m_movementInfo; + updateApplyMovementForce.Force = force; + SendMessageToSet(updateApplyMovementForce, true); + } + } + } + + void RemoveMovementForce(ObjectGuid id) + { + if (_movementForces == null) + return; + + if (_movementForces.Remove(id)) + { + Player movingPlayer = GetPlayerMovingMe(); + if (movingPlayer != null) + { + MoveRemoveMovementForce moveRemoveMovementForce = new MoveRemoveMovementForce(); + moveRemoveMovementForce.MoverGUID = GetGUID(); + moveRemoveMovementForce.SequenceIndex = (int)m_movementCounter++; + moveRemoveMovementForce.ID = id; + movingPlayer.SendPacket(moveRemoveMovementForce); + } + else + { + MoveUpdateRemoveMovementForce updateRemoveMovementForce = new MoveUpdateRemoveMovementForce(); + updateRemoveMovementForce.Status = m_movementInfo; + updateRemoveMovementForce.TriggerGUID = id; + SendMessageToSet(updateRemoveMovementForce, true); + } + } + + if (_movementForces.IsEmpty()) + _movementForces = new MovementForces(); + } + + public bool SetIgnoreMovementForces(bool ignore) + { + if (ignore == HasUnitMovementFlag2(MovementFlag2.IgnoreMovementForces)) + return false; + + if (ignore) + AddUnitMovementFlag2(MovementFlag2.IgnoreMovementForces); + else + RemoveUnitMovementFlag2(MovementFlag2.IgnoreMovementForces); + + ServerOpcodes[] ignoreMovementForcesOpcodeTable = + { + ServerOpcodes.MoveUnsetIgnoreMovementForces, + ServerOpcodes.MoveSetIgnoreMovementForces + }; + + Player movingPlayer = GetPlayerMovingMe(); + if (movingPlayer != null) + { + MoveSetFlag packet = new MoveSetFlag(ignoreMovementForcesOpcodeTable[ignore ? 1 : 0]); + packet.MoverGUID = GetGUID(); + packet.SequenceIndex = m_movementCounter++; + movingPlayer.SendPacket(packet); + + MoveUpdate moveUpdate = new MoveUpdate(); + moveUpdate.Status = m_movementInfo; + SendMessageToSet(moveUpdate, movingPlayer); + } + + return true; + } + + public void UpdateMovementForcesModMagnitude() + { + float modMagnitude = GetTotalAuraMultiplier(AuraType.ModMovementForceMagnitude); + + Player movingPlayer = GetPlayerMovingMe(); + if (movingPlayer != null) + { + MoveSetSpeed setModMovementForceMagnitude = new MoveSetSpeed(ServerOpcodes.MoveSetModMovementForceMagnitude); + setModMovementForceMagnitude.MoverGUID = GetGUID(); + setModMovementForceMagnitude.SequenceIndex = m_movementCounter++; + setModMovementForceMagnitude.Speed = modMagnitude; + movingPlayer.SendPacket(setModMovementForceMagnitude); + ++movingPlayer.m_movementForceModMagnitudeChanges; + } + else + { + MoveUpdateSpeed updateModMovementForceMagnitude = new MoveUpdateSpeed(ServerOpcodes.MoveUpdateModMovementForceMagnitude); + updateModMovementForceMagnitude.Status = m_movementInfo; + updateModMovementForceMagnitude.Speed = modMagnitude; + SendMessageToSet(updateModMovementForceMagnitude, true); + } + + if (modMagnitude != 1.0f && _movementForces == null) + _movementForces = new MovementForces(); + + if (_movementForces != null) + { + _movementForces.SetModMagnitude(modMagnitude); + if (_movementForces.IsEmpty()) + _movementForces = new MovementForces(); + } + } + void SendSetPlayHoverAnim(bool enable) { SetPlayHoverAnim data = new SetPlayHoverAnim(); @@ -1562,6 +1694,8 @@ namespace Game.Entities MoveUpdateTeleport moveUpdateTeleport = new MoveUpdateTeleport(); moveUpdateTeleport.Status = m_movementInfo; + if (_movementForces != null) + moveUpdateTeleport.MovementForces = _movementForces.GetForces(); Unit broadcastSource = this; Player playerMover = GetPlayerBeingMoved(); diff --git a/Source/Game/Handlers/MovementHandler.cs b/Source/Game/Handlers/MovementHandler.cs index fa8d83721..0c518d48c 100644 --- a/Source/Game/Handlers/MovementHandler.cs +++ b/Source/Game/Handlers/MovementHandler.cs @@ -620,6 +620,92 @@ namespace Game GetPlayer().ValidateMovementInfo(packet.Data.Status); } + [WorldPacketHandler(ClientOpcodes.MoveApplyMovementForceAck, Processing = PacketProcessing.ThreadSafe)] + void HandleMoveApplyMovementForceAck(MoveApplyMovementForceAck moveApplyMovementForceAck) + { + Unit mover = _player.m_unitMovedByMe; + Cypher.Assert(mover != null); + _player.ValidateMovementInfo(moveApplyMovementForceAck.Ack.Status); + + // prevent tampered movement data + if (moveApplyMovementForceAck.Ack.Status.Guid != mover.GetGUID()) + { + Log.outError(LogFilter.Network, $"HandleMoveApplyMovementForceAck: guid error, expected {mover.GetGUID().ToString()}, got {moveApplyMovementForceAck.Ack.Status.Guid.ToString()}"); + return; + } + + moveApplyMovementForceAck.Ack.Status.Time += m_clientTimeDelay; + + MoveUpdateApplyMovementForce updateApplyMovementForce = new MoveUpdateApplyMovementForce(); + updateApplyMovementForce.Status = moveApplyMovementForceAck.Ack.Status; + updateApplyMovementForce.Force = moveApplyMovementForceAck.Force; + mover.SendMessageToSet(updateApplyMovementForce, false); + } + + [WorldPacketHandler(ClientOpcodes.MoveRemoveMovementForceAck, Processing = PacketProcessing.ThreadSafe)] + void HandleMoveRemoveMovementForceAck(MoveRemoveMovementForceAck moveRemoveMovementForceAck) + { + Unit mover = _player.m_unitMovedByMe; + Cypher.Assert(mover != null); + _player.ValidateMovementInfo(moveRemoveMovementForceAck.Ack.Status); + + // prevent tampered movement data + if (moveRemoveMovementForceAck.Ack.Status.Guid != mover.GetGUID()) + { + Log.outError(LogFilter.Network, $"HandleMoveRemoveMovementForceAck: guid error, expected {mover.GetGUID().ToString()}, got {moveRemoveMovementForceAck.Ack.Status.Guid.ToString()}"); + return; + } + + moveRemoveMovementForceAck.Ack.Status.Time += m_clientTimeDelay; + + MoveUpdateRemoveMovementForce updateRemoveMovementForce = new MoveUpdateRemoveMovementForce(); + updateRemoveMovementForce.Status = moveRemoveMovementForceAck.Ack.Status; + updateRemoveMovementForce.TriggerGUID = moveRemoveMovementForceAck.ID; + mover.SendMessageToSet(updateRemoveMovementForce, false); + } + + [WorldPacketHandler(ClientOpcodes.MoveSetModMovementForceMagnitudeAck, Processing = PacketProcessing.ThreadSafe)] + void HandleMoveSetModMovementForceMagnitudeAck(MovementSpeedAck setModMovementForceMagnitudeAck) + { + Unit mover = _player.m_unitMovedByMe; + Cypher.Assert(mover != null); // there must always be a mover + _player.ValidateMovementInfo(setModMovementForceMagnitudeAck.Ack.Status); + + // prevent tampered movement data + if (setModMovementForceMagnitudeAck.Ack.Status.Guid != mover.GetGUID()) + { + Log.outError(LogFilter.Network, "HandleSetModMovementForceMagnitudeAck: guid error, expected {mover.GetGUID().ToString()}, got {setModMovementForceMagnitudeAck.Ack.Status.guid.ToString()}"); + return; + } + + // skip all except last + if (_player.m_movementForceModMagnitudeChanges > 0) + { + --_player.m_movementForceModMagnitudeChanges; + if (_player.m_movementForceModMagnitudeChanges == 0) + { + float expectedModMagnitude = 1.0f; + MovementForces movementForces = mover.GetMovementForces(); + if (movementForces != null) + expectedModMagnitude = movementForces.GetModMagnitude(); + + if (Math.Abs(expectedModMagnitude - setModMovementForceMagnitudeAck.Speed) > 0.01f) + { + Log.outDebug(LogFilter.Misc, $"Player {_player.GetName()} from account id {_player.GetSession().GetAccountId()} kicked for incorrect movement force magnitude (must be {expectedModMagnitude} instead {setModMovementForceMagnitudeAck.Speed})"); + _player.GetSession().KickPlayer(); + return; + } + } + } + + setModMovementForceMagnitudeAck.Ack.Status.Time += m_clientTimeDelay; + + MoveUpdateSpeed updateModMovementForceMagnitude = new MoveUpdateSpeed(ServerOpcodes.MoveUpdateModMovementForceMagnitude); + updateModMovementForceMagnitude.Status = setModMovementForceMagnitudeAck.Ack.Status; + updateModMovementForceMagnitude.Speed = setModMovementForceMagnitudeAck.Speed; + mover.SendMessageToSet(updateModMovementForceMagnitude, false); + } + [WorldPacketHandler(ClientOpcodes.MoveTimeSkipped, Processing = PacketProcessing.Inplace)] void HandleMoveTimeSkipped(MoveTimeSkipped moveTimeSkipped) { diff --git a/Source/Game/Network/Packets/MovementPackets.cs b/Source/Game/Network/Packets/MovementPackets.cs index 18d36eb6b..09e85e41c 100644 --- a/Source/Game/Network/Packets/MovementPackets.cs +++ b/Source/Game/Network/Packets/MovementPackets.cs @@ -268,6 +268,44 @@ namespace Game.Network.Packets foreach (var point in spline.getPoints()) data.WriteVector3(point); } + + public static void WriteMovementForceWithDirection(MovementForce movementForce, WorldPacket data, Position objectPosition = null) + { + data.WritePackedGuid(movementForce.ID); + data.WriteVector3(movementForce.Origin); + if (movementForce.Type == 1 && objectPosition != null) // gravity + { + Vector3 direction = Vector3.Zero; + if (movementForce.Magnitude != 0.0f) + { + Position tmp = new Position(movementForce.Origin.X - objectPosition.GetPositionX(), + movementForce.Origin.Y - objectPosition.GetPositionY(), + movementForce.Origin.Z - objectPosition.GetPositionZ()); + float lengthSquared = tmp.GetExactDistSq(0.0f, 0.0f, 0.0f); + if (lengthSquared > 0.0f) + { + float mult = 1.0f / (float)Math.Sqrt(lengthSquared) * movementForce.Magnitude; + tmp.posX *= mult; + tmp.posY *= mult; + tmp.posZ *= 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 = new Vector3(tmp.posX, tmp.posY, tmp.posZ); + } + } + + data.WriteVector3(direction); + } + else + data.WriteVector3(movementForce.Direction); + + data.WriteUInt32(movementForce.TransportID); + data.WriteFloat(movementForce.Magnitude); + data.WriteBits(movementForce.Type, 2); + data.FlushBits(); + } } public class ClientPlayerMovement : ClientPacket @@ -588,7 +626,7 @@ namespace Game.Network.Packets { MovementExtensions.WriteMovementInfo(_worldPacket, Status); - _worldPacket.WriteInt32(MovementForces.Count); + _worldPacket.WriteInt32(MovementForces != null ? MovementForces.Count : 0); _worldPacket.WriteBit(WalkSpeed.HasValue); _worldPacket.WriteBit(RunSpeed.HasValue); _worldPacket.WriteBit(RunBackSpeed.HasValue); @@ -600,8 +638,9 @@ namespace Game.Network.Packets _worldPacket.WriteBit(PitchRate.HasValue); _worldPacket.FlushBits(); - foreach (MovementForce force in MovementForces) - force.Write(_worldPacket); + if (MovementForces != null) + foreach (MovementForce force in MovementForces) + force.Write(_worldPacket); if (WalkSpeed.HasValue) _worldPacket.WriteFloat(WalkSpeed.Value); @@ -632,7 +671,7 @@ namespace Game.Network.Packets } public MovementInfo Status; - public List MovementForces = new List(); + public List MovementForces; public Optional SwimBackSpeed; public Optional FlightSpeed; public Optional SwimSpeed; @@ -644,18 +683,78 @@ namespace Game.Network.Packets public Optional PitchRate; } + class MoveApplyMovementForce : ServerPacket + { + public MoveApplyMovementForce() : base(ServerOpcodes.MoveApplyMovementForce, ConnectionType.Instance) { } + + public override void Write() + { + _worldPacket.WritePackedGuid(MoverGUID); + _worldPacket.WriteInt32(SequenceIndex); + Force.Write(_worldPacket); + } + + public ObjectGuid MoverGUID; + public int SequenceIndex; + public MovementForce Force; + } + + class MoveApplyMovementForceAck : ClientPacket + { + public MoveApplyMovementForceAck(WorldPacket packet) : base(packet) { } + + public override void Read() + { + Ack.Read(_worldPacket); + Force.Read(_worldPacket); + } + + public MovementAck Ack = new MovementAck(); + public MovementForce Force = new MovementForce(); + } + + class MoveRemoveMovementForce : ServerPacket + { + public MoveRemoveMovementForce() : base(ServerOpcodes.MoveRemoveMovementForce, ConnectionType.Instance) { } + + public override void Write() + { + _worldPacket.WritePackedGuid(MoverGUID); + _worldPacket.WriteInt32(SequenceIndex); + _worldPacket.WritePackedGuid(ID); + } + + public ObjectGuid MoverGUID; + public int SequenceIndex; + public ObjectGuid ID; + } + + class MoveRemoveMovementForceAck : ClientPacket + { + public MoveRemoveMovementForceAck(WorldPacket packet) : base(packet) { } + + public override void Read() + { + Ack.Read(_worldPacket); + ID = _worldPacket.ReadPackedGuid(); + } + + public MovementAck Ack = new MovementAck(); + public ObjectGuid ID; + } + class MoveUpdateApplyMovementForce : ServerPacket { public MoveUpdateApplyMovementForce() : base(ServerOpcodes.MoveUpdateApplyMovementForce) { } public override void Write() { - MovementExtensions.WriteMovementInfo(_worldPacket, movementInfo); + MovementExtensions.WriteMovementInfo(_worldPacket, Status); Force.Write(_worldPacket); } - MovementInfo movementInfo = new MovementInfo(); - MovementForce Force = new MovementForce(); + public MovementInfo Status = new MovementInfo(); + public MovementForce Force = new MovementForce(); } class MoveUpdateRemoveMovementForce : ServerPacket @@ -664,12 +763,12 @@ namespace Game.Network.Packets public override void Write() { - MovementExtensions.WriteMovementInfo(_worldPacket, movementInfo); + MovementExtensions.WriteMovementInfo(_worldPacket, Status); _worldPacket.WritePackedGuid(TriggerGUID); } - MovementInfo movementInfo = new MovementInfo(); - ObjectGuid TriggerGUID; + public MovementInfo Status = new MovementInfo(); + public ObjectGuid TriggerGUID; } class MoveTeleportAck : ClientPacket @@ -1060,6 +1159,18 @@ namespace Game.Network.Packets } //Structs + public struct MovementAck + { + public void Read(WorldPacket data) + { + Status = MovementExtensions.ReadMovementInfo(data); + AckIndex = data.ReadInt32(); + } + + public MovementInfo Status; + public int AckIndex; + } + public struct MonsterSplineFilterKey { public void Write(WorldPacket data) @@ -1232,39 +1343,6 @@ namespace Game.Network.Packets public bool VehicleExitTeleport; } - public struct MovementForce - { - public void Write(WorldPacket data) - { - data.WritePackedGuid(ID); - data.WriteVector3(Origin); - data.WriteVector3(Direction); - data.WriteUInt32(TransportID); - data.WriteFloat(Magnitude); - data.WriteBits(Type, 2); - data.FlushBits(); - } - - public ObjectGuid ID; - public Vector3 Origin; - public Vector3 Direction; - public uint TransportID; - public float Magnitude; - public byte Type; - } - - public struct MovementAck - { - public void Read(WorldPacket data) - { - Status = MovementExtensions.ReadMovementInfo(data); - AckIndex = data.ReadInt32(); - } - - public MovementInfo Status; - public int AckIndex; - } - public struct MoveKnockBackSpeeds { public void Write(WorldPacket data) diff --git a/Source/Game/Spells/Auras/AuraEffect.cs b/Source/Game/Spells/Auras/AuraEffect.cs index f4ab27e56..c03cc2778 100644 --- a/Source/Game/Spells/Auras/AuraEffect.cs +++ b/Source/Game/Spells/Auras/AuraEffect.cs @@ -2330,6 +2330,23 @@ namespace Game.Spells target.SetCanTurnWhileFalling(apply); } + [AuraEffectHandler(AuraType.IgnoreMovementForces)] + void HandleIgnoreMovementForces(AuraApplication aurApp, AuraEffectHandleModes mode, bool apply) + { + if (!mode.HasAnyFlag(AuraEffectHandleModes.SendForClientMask)) + return; + + Unit target = aurApp.GetTarget(); + if (!apply) + { + // do not remove unit flag if there are more than this auraEffect of that kind on unit on unit + if (target.HasAuraType(GetAuraType())) + return; + } + + target.SetIgnoreMovementForces(apply); + } + /****************************/ /*** THREAT ***/ /****************************/ @@ -2722,6 +2739,15 @@ namespace Game.Spells target.UpdateSpeed(UnitMoveType.Run); } + [AuraEffectHandler(AuraType.ModMovementForceMagnitude)] + void HandleModMovementForceMagnitude(AuraApplication aurApp, AuraEffectHandleModes mode, bool apply) + { + if (!mode.HasAnyFlag(AuraEffectHandleModes.ChangeAmountMask)) + return; + + aurApp.GetTarget().UpdateMovementForcesModMagnitude(); + } + /*********************************************************/ /*** IMMUNITY ***/ /*********************************************************/ @@ -6027,7 +6053,7 @@ namespace Game.Spells uint summonEntry = (uint)spellEffect.MiscValue; if (summonEntry != 0) summonedEntries.Add(summonEntry); - + } }