diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/server/game/Entities/Object/MovementInfo.h | 57 | ||||
-rw-r--r-- | src/server/game/Entities/Object/Object.cpp | 26 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 12 | ||||
-rw-r--r-- | src/server/game/Entities/Player/Player.h | 1 | ||||
-rw-r--r-- | src/server/game/Entities/Unit/Unit.cpp | 128 | ||||
-rw-r--r-- | src/server/game/Entities/Unit/Unit.h | 8 | ||||
-rw-r--r-- | src/server/game/Handlers/MovementHandler.cpp | 86 | ||||
-rw-r--r-- | src/server/game/Server/Packets/MovementPackets.cpp | 59 | ||||
-rw-r--r-- | src/server/game/Server/Packets/MovementPackets.h | 77 | ||||
-rw-r--r-- | src/server/game/Server/Protocol/Opcodes.cpp | 16 | ||||
-rw-r--r-- | src/server/game/Server/WorldSession.h | 7 | ||||
-rw-r--r-- | src/server/game/Spells/Auras/SpellAuraDefines.h | 2 | ||||
-rw-r--r-- | src/server/game/Spells/Auras/SpellAuraEffects.cpp | 27 | ||||
-rw-r--r-- | src/server/game/Spells/Auras/SpellAuraEffects.h | 2 |
14 files changed, 452 insertions, 56 deletions
diff --git a/src/server/game/Entities/Object/MovementInfo.h b/src/server/game/Entities/Object/MovementInfo.h index 869429851bd..52941d290ec 100644 --- a/src/server/game/Entities/Object/MovementInfo.h +++ b/src/server/game/Entities/Object/MovementInfo.h @@ -20,6 +20,8 @@ #include "ObjectGuid.h" #include "Position.h" +#include <algorithm> +#include <vector> struct MovementInfo { @@ -108,4 +110,59 @@ struct MovementInfo void OutDebug(); }; +struct MovementForce +{ + ObjectGuid ID; + TaggedPosition<Position::XYZ> Origin; + TaggedPosition<Position::XYZ> Direction; + uint32 TransportID = 0; + float Magnitude = 0.0f; + uint8 Type = 0; +}; + +class MovementForces +{ +public: + using Container = std::vector<MovementForce>; + + Container const* GetForces() const { return &_forces; } + bool Add(MovementForce const& newForce) + { + auto itr = FindMovementForce(newForce.ID); + if (itr == _forces.end()) + { + _forces.push_back(newForce); + return true; + } + + return false; + } + + bool Remove(ObjectGuid id) + { + auto itr = FindMovementForce(id); + if (itr != _forces.end()) + { + _forces.erase(itr); + return true; + } + + return false; + } + + float GetModMagnitude() const { return _modMagnitude; } + void SetModMagnitude(float modMagnitude) { _modMagnitude = modMagnitude; } + + bool IsEmpty() const { return _forces.empty() && _modMagnitude == 1.0f; } + +private: + Container::iterator FindMovementForce(ObjectGuid id) + { + return std::find_if(_forces.begin(), _forces.end(), [id](MovementForce const& force) { return force.ID == id; }); + } + + Container _forces; + float _modMagnitude = 1.0f; +}; + #endif // MovementInfo_h__ diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index 41e5e62f395..a2b5da60d1c 100644 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -367,23 +367,23 @@ void Object::BuildMovementUpdate(ByteBuffer* data, CreateObjectBits flags) const *data << float(unit->GetSpeed(MOVE_TURN_RATE)); *data << float(unit->GetSpeed(MOVE_PITCH_RATE)); - *data << uint32(0); // unit->m_movementInfo.forces.size() - - *data << float(1.0f); // MovementForcesModMagnitude + if (MovementForces const* movementForces = unit->GetMovementForces()) + { + *data << uint32(movementForces->GetForces()->size()); + *data << float(movementForces->GetModMagnitude()); // MovementForcesModMagnitude + } + else + { + *data << uint32(0); + *data << float(1.0f); // MovementForcesModMagnitude + } data->WriteBit(HasSpline); data->FlushBits(); - //for (std::size_t i = 0; i < unit->m_movementInfo.forces.size(); ++i) - //{ - // *data << ObjectGuid(ID); - // *data << Vector3(Origin); - // *data << Vector3(Direction); - // *data << uint32(TransportID); - // *data << float(Magnitude); - // data->WriteBits(Type, 2); - // data->FlushBits(); - //} + if (MovementForces const* movementForces = unit->GetMovementForces()) + for (MovementForce const& force : *movementForces->GetForces()) + *data << force; if (HasSpline) WorldPackets::Movement::CommonMovement::WriteCreateObjectSplineDataBlock(*unit->movespline, *data); diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 2d61bd36c50..3d2acb15a7c 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -251,6 +251,8 @@ Player::Player(WorldSession* session) : Unit(true), m_sceneMgr(this) for (uint8 i = 0; i < MAX_MOVE_TYPE; ++i) m_forced_speed_changes[i] = 0; + m_movementForceModMagnitudeChanges = 0; + m_stableSlots = 0; /////////////////// Instance System ///////////////////// @@ -27836,7 +27838,7 @@ void Player::ValidateMovementInfo(MovementInfo* mi) mi->RemoveMovementFlag((maskToRemove)); #endif - if (!GetVehicleBase() || !(GetVehicle()->GetVehicleInfo()->Flags & VEHICLE_FLAG_FIXED_POSITION)) + if (!m_unitMovedByMe->GetVehicleBase() || !(m_unitMovedByMe->GetVehicle()->GetVehicleInfo()->Flags & VEHICLE_FLAG_FIXED_POSITION)) REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_ROOT), MOVEMENTFLAG_ROOT); /*! This must be a packet spoofing attempt. MOVEMENTFLAG_ROOT sent from the client is not valid @@ -27847,7 +27849,7 @@ void Player::ValidateMovementInfo(MovementInfo* mi) MOVEMENTFLAG_MASK_MOVING); //! Cannot hover without SPELL_AURA_HOVER - REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_HOVER) && !HasAuraType(SPELL_AURA_HOVER), + REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_HOVER) && !m_unitMovedByMe->HasAuraType(SPELL_AURA_HOVER), MOVEMENTFLAG_HOVER); //! Cannot ascend and descend at the same time @@ -27872,12 +27874,12 @@ void Player::ValidateMovementInfo(MovementInfo* mi) //! Cannot walk on water without SPELL_AURA_WATER_WALK except for ghosts REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_WATERWALKING) && - !HasAuraType(SPELL_AURA_WATER_WALK) && - !HasAuraType(SPELL_AURA_GHOST), + !m_unitMovedByMe->HasAuraType(SPELL_AURA_WATER_WALK) && + !m_unitMovedByMe->HasAuraType(SPELL_AURA_GHOST), MOVEMENTFLAG_WATERWALKING); //! Cannot feather fall without SPELL_AURA_FEATHER_FALL - REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_FALLING_SLOW) && !HasAuraType(SPELL_AURA_FEATHER_FALL), + REMOVE_VIOLATING_FLAGS(mi->HasMovementFlag(MOVEMENTFLAG_FALLING_SLOW) && !m_unitMovedByMe->HasAuraType(SPELL_AURA_FEATHER_FALL), MOVEMENTFLAG_FALLING_SLOW); /*! Cannot fly if no fly auras present. Exception is being a GM. diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 879b7499e10..83a0e5fb60c 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -2162,6 +2162,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player> void UpdateVisibilityOf(T* target, UpdateData& data, std::set<Unit*>& visibleNow); uint8 m_forced_speed_changes[MAX_MOVE_TYPE]; + uint8 m_movementForceModMagnitudeChanges; bool HasAtLoginFlag(AtLoginFlags f) const { return (m_atLoginFlags & f) != 0; } void SetAtLoginFlag(AtLoginFlags f) { m_atLoginFlags |= f; } diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 89d545458ca..54d583f0437 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -13110,6 +13110,8 @@ void Unit::SendTeleportPacket(Position const& pos) WorldPackets::Movement::MoveUpdateTeleport moveUpdateTeleport; moveUpdateTeleport.Status = &m_movementInfo; + if (_movementForces) + moveUpdateTeleport.MovementForces = _movementForces->GetForces(); Unit* broadcastSource = this; if (Player* playerMover = GetPlayerBeingMoved()) @@ -13898,6 +13900,132 @@ void Unit::SendSetVehicleRecId(uint32 vehicleId) SendMessageToSet(setVehicleRec.Write(), true); } +void Unit::ApplyMovementForce(ObjectGuid id, Position origin, float magnitude, uint8 type, Position direction /*= {}*/, ObjectGuid transportGuid /*= ObjectGuid::Empty*/) +{ + if (!_movementForces) + _movementForces = Trinity::make_unique<MovementForces>(); + + MovementForce force; + force.ID = id; + force.Origin = origin; + force.Direction = direction; + if (transportGuid.IsMOTransport()) + force.TransportID = transportGuid.GetCounter(); + + force.Magnitude = magnitude; + force.Type = type; + + if (_movementForces->Add(force)) + { + if (Player const* movingPlayer = GetPlayerMovingMe()) + { + WorldPackets::Movement::MoveApplyMovementForce applyMovementForce; + applyMovementForce.MoverGUID = GetGUID(); + applyMovementForce.SequenceIndex = m_movementCounter++; + applyMovementForce.Force = &force; + movingPlayer->SendDirectMessage(applyMovementForce.Write()); + } + else + { + WorldPackets::Movement::MoveUpdateApplyMovementForce updateApplyMovementForce; + updateApplyMovementForce.Status = &m_movementInfo; + updateApplyMovementForce.Force = &force; + SendMessageToSet(updateApplyMovementForce.Write(), true); + } + } +} + +void Unit::RemoveMovementForce(ObjectGuid id) +{ + if (!_movementForces) + return; + + if (_movementForces->Remove(id)) + { + if (Player const* movingPlayer = GetPlayerMovingMe()) + { + WorldPackets::Movement::MoveRemoveMovementForce moveRemoveMovementForce; + moveRemoveMovementForce.MoverGUID = GetGUID(); + moveRemoveMovementForce.SequenceIndex = m_movementCounter++; + moveRemoveMovementForce.ID = id; + movingPlayer->SendDirectMessage(moveRemoveMovementForce.Write()); + } + else + { + WorldPackets::Movement::MoveUpdateRemoveMovementForce updateRemoveMovementForce; + updateRemoveMovementForce.Status = &m_movementInfo; + updateRemoveMovementForce.TriggerGUID = id; + SendMessageToSet(updateRemoveMovementForce.Write(), true); + } + } + + if (_movementForces->IsEmpty()) + _movementForces.reset(); +} + +bool Unit::SetIgnoreMovementForces(bool ignore) +{ + if (ignore == HasExtraUnitMovementFlag(MOVEMENTFLAG2_IGNORE_MOVEMENT_FORCES)) + return false; + + if (ignore) + AddExtraUnitMovementFlag(MOVEMENTFLAG2_IGNORE_MOVEMENT_FORCES); + else + RemoveExtraUnitMovementFlag(MOVEMENTFLAG2_IGNORE_MOVEMENT_FORCES); + + static OpcodeServer const ignoreMovementForcesOpcodeTable[2] = + { + SMSG_MOVE_UNSET_IGNORE_MOVEMENT_FORCES, + SMSG_MOVE_SET_IGNORE_MOVEMENT_FORCES + }; + + if (Player const* movingPlayer = GetPlayerMovingMe()) + { + WorldPackets::Movement::MoveSetFlag packet(ignoreMovementForcesOpcodeTable[ignore]); + packet.MoverGUID = GetGUID(); + packet.SequenceIndex = m_movementCounter++; + movingPlayer->SendDirectMessage(packet.Write()); + + WorldPackets::Movement::MoveUpdate moveUpdate; + moveUpdate.Status = &m_movementInfo; + SendMessageToSet(moveUpdate.Write(), movingPlayer); + } + + return true; +} + +void Unit::UpdateMovementForcesModMagnitude() +{ + float modMagnitude = GetTotalAuraMultiplier(SPELL_AURA_MOD_MOVEMENT_FORCE_MAGNITUDE); + + if (Player* movingPlayer = GetPlayerMovingMe()) + { + WorldPackets::Movement::MoveSetSpeed setModMovementForceMagnitude(SMSG_MOVE_SET_MOD_MOVEMENT_FORCE_MAGNITUDE); + setModMovementForceMagnitude.MoverGUID = GetGUID(); + setModMovementForceMagnitude.SequenceIndex = m_movementCounter++; + setModMovementForceMagnitude.Speed = modMagnitude; + movingPlayer->SendDirectMessage(setModMovementForceMagnitude.Write()); + ++movingPlayer->m_movementForceModMagnitudeChanges; + } + else + { + WorldPackets::Movement::MoveUpdateSpeed updateModMovementForceMagnitude(SMSG_MOVE_UPDATE_MOD_MOVEMENT_FORCE_MAGNITUDE); + updateModMovementForceMagnitude.Status = &m_movementInfo; + updateModMovementForceMagnitude.Speed = modMagnitude; + SendMessageToSet(updateModMovementForceMagnitude.Write(), true); + } + + if (modMagnitude != 1.0f && !_movementForces) + _movementForces = Trinity::make_unique<MovementForces>(); + + if (_movementForces) + { + _movementForces->SetModMagnitude(modMagnitude); + if (_movementForces->IsEmpty()) + _movementForces.reset(); + } +} + void Unit::SendSetPlayHoverAnim(bool enable) { WorldPackets::Misc::SetPlayHoverAnim data; diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 14a66db986d..e4b5a803163 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1378,6 +1378,12 @@ class TC_GAME_API Unit : public WorldObject bool SetCanDoubleJump(bool enable); void SendSetVehicleRecId(uint32 vehicleId); + MovementForces const* GetMovementForces() const { return _movementForces.get(); } + void ApplyMovementForce(ObjectGuid id, Position origin, float magnitude, uint8 type, Position direction = {}, ObjectGuid transportGuid = ObjectGuid::Empty); + void RemoveMovementForce(ObjectGuid id); + bool SetIgnoreMovementForces(bool ignore); + void UpdateMovementForcesModMagnitude(); + void SetInFront(WorldObject const* target); void SetFacingTo(float ori, bool force = false); void SetFacingToObject(WorldObject const* object, bool force = false); @@ -2131,6 +2137,8 @@ class TC_GAME_API Unit : public WorldObject uint16 _meleeAnimKitId; SpellHistory* _spellHistory; + + std::unique_ptr<MovementForces> _movementForces; }; namespace Trinity diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp index 9ff173b8add..465a1e49239 100644 --- a/src/server/game/Handlers/MovementHandler.cpp +++ b/src/server/game/Handlers/MovementHandler.cpp @@ -572,6 +572,92 @@ void WorldSession::HandleSetCollisionHeightAck(WorldPackets::Movement::MoveSetCo GetPlayer()->ValidateMovementInfo(&setCollisionHeightAck.Data.Status); } +void WorldSession::HandleMoveApplyMovementForceAck(WorldPackets::Movement::MoveApplyMovementForceAck& moveApplyMovementForceAck) +{ + Unit* mover = _player->m_unitMovedByMe; + ASSERT(mover != nullptr); + _player->ValidateMovementInfo(&moveApplyMovementForceAck.Ack.Status); + + // prevent tampered movement data + if (moveApplyMovementForceAck.Ack.Status.guid != mover->GetGUID()) + { + TC_LOG_ERROR("network", "HandleMoveApplyMovementForceAck: guid error, expected %s, got %s", + mover->GetGUID().ToString().c_str(), moveApplyMovementForceAck.Ack.Status.guid.ToString().c_str()); + return; + } + + moveApplyMovementForceAck.Ack.Status.time += m_clientTimeDelay + MOVEMENT_PACKET_TIME_DELAY; + + WorldPackets::Movement::MoveUpdateApplyMovementForce updateApplyMovementForce; + updateApplyMovementForce.Status = &moveApplyMovementForceAck.Ack.Status; + updateApplyMovementForce.Force = &moveApplyMovementForceAck.Force; + mover->SendMessageToSet(updateApplyMovementForce.Write(), false); +} + +void WorldSession::HandleMoveRemoveMovementForceAck(WorldPackets::Movement::MoveRemoveMovementForceAck& moveRemoveMovementForceAck) +{ + Unit* mover = _player->m_unitMovedByMe; + ASSERT(mover != nullptr); + _player->ValidateMovementInfo(&moveRemoveMovementForceAck.Ack.Status); + + // prevent tampered movement data + if (moveRemoveMovementForceAck.Ack.Status.guid != mover->GetGUID()) + { + TC_LOG_ERROR("network", "HandleMoveRemoveMovementForceAck: guid error, expected %s, got %s", + mover->GetGUID().ToString().c_str(), moveRemoveMovementForceAck.Ack.Status.guid.ToString().c_str()); + return; + } + + moveRemoveMovementForceAck.Ack.Status.time += m_clientTimeDelay + MOVEMENT_PACKET_TIME_DELAY; + + WorldPackets::Movement::MoveUpdateRemoveMovementForce updateRemoveMovementForce; + updateRemoveMovementForce.Status = &moveRemoveMovementForceAck.Ack.Status; + updateRemoveMovementForce.TriggerGUID = moveRemoveMovementForceAck.ID; + mover->SendMessageToSet(updateRemoveMovementForce.Write(), false); +} + +void WorldSession::HandleMoveSetModMovementForceMagnitudeAck(WorldPackets::Movement::MovementSpeedAck& setModMovementForceMagnitudeAck) +{ + Unit* mover = _player->m_unitMovedByMe; + ASSERT(mover != nullptr); // there must always be a mover + _player->ValidateMovementInfo(&setModMovementForceMagnitudeAck.Ack.Status); + + // prevent tampered movement data + if (setModMovementForceMagnitudeAck.Ack.Status.guid != mover->GetGUID()) + { + TC_LOG_ERROR("network", "HandleSetModMovementForceMagnitudeAck: guid error, expected %s, got %s", + mover->GetGUID().ToString().c_str(), setModMovementForceMagnitudeAck.Ack.Status.guid.ToString().c_str()); + return; + } + + // skip all except last + if (_player->m_movementForceModMagnitudeChanges > 0) + { + --_player->m_movementForceModMagnitudeChanges; + if (!_player->m_movementForceModMagnitudeChanges) + { + float expectedModMagnitude = 1.0f; + if (MovementForces const* movementForces = mover->GetMovementForces()) + expectedModMagnitude = movementForces->GetModMagnitude(); + + if (std::fabs(expectedModMagnitude - setModMovementForceMagnitudeAck.Speed) > 0.01f) + { + TC_LOG_DEBUG("misc", "Player %s from account id %u kicked for incorrect movement force magnitude (must be %f instead %f)", + _player->GetName().c_str(), _player->GetSession()->GetAccountId(), expectedModMagnitude, setModMovementForceMagnitudeAck.Speed); + _player->GetSession()->KickPlayer(); + return; + } + } + } + + setModMovementForceMagnitudeAck.Ack.Status.time += m_clientTimeDelay + MOVEMENT_PACKET_TIME_DELAY; + + WorldPackets::Movement::MoveUpdateSpeed updateModMovementForceMagnitude(SMSG_MOVE_UPDATE_MOD_MOVEMENT_FORCE_MAGNITUDE); + updateModMovementForceMagnitude.Status = &setModMovementForceMagnitudeAck.Ack.Status; + updateModMovementForceMagnitude.Speed = setModMovementForceMagnitudeAck.Speed; + mover->SendMessageToSet(updateModMovementForceMagnitude.Write(), false); +} + void WorldSession::HandleMoveTimeSkippedOpcode(WorldPackets::Movement::MoveTimeSkipped& /*moveTimeSkipped*/) { } diff --git a/src/server/game/Server/Packets/MovementPackets.cpp b/src/server/game/Server/Packets/MovementPackets.cpp index c14d96e0964..943d312dffb 100644 --- a/src/server/game/Server/Packets/MovementPackets.cpp +++ b/src/server/game/Server/Packets/MovementPackets.cpp @@ -579,7 +579,7 @@ WorldPacket const* WorldPackets::Movement::MoveTeleport::Write() return &_worldPacket; } -ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Movement::MovementForce const& movementForce) +ByteBuffer& operator<<(ByteBuffer& data, MovementForce const& movementForce) { data << movementForce.ID; data << movementForce.Origin; @@ -592,11 +592,23 @@ ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Movement::MovementForce c return data; } +ByteBuffer& operator>>(ByteBuffer& data, MovementForce& movementForce) +{ + data >> movementForce.ID; + data >> movementForce.Origin; + data >> movementForce.Direction; + data >> movementForce.TransportID; + data >> movementForce.Magnitude; + movementForce.Type = data.ReadBits(2); + + return data; +} + WorldPacket const* WorldPackets::Movement::MoveUpdateTeleport::Write() { _worldPacket << *Status; - _worldPacket << uint32(MovementForces.size()); + _worldPacket << uint32(MovementForces ? MovementForces->size() : 0); _worldPacket.WriteBit(WalkSpeed.is_initialized()); _worldPacket.WriteBit(RunSpeed.is_initialized()); _worldPacket.WriteBit(RunBackSpeed.is_initialized()); @@ -608,8 +620,9 @@ WorldPacket const* WorldPackets::Movement::MoveUpdateTeleport::Write() _worldPacket.WriteBit(PitchRate.is_initialized()); _worldPacket.FlushBits(); - for (WorldPackets::Movement::MovementForce const& force : MovementForces) - _worldPacket << force; + if (MovementForces) + for (MovementForce const& force : *MovementForces) + _worldPacket << force; if (WalkSpeed) _worldPacket << *WalkSpeed; @@ -745,18 +758,48 @@ WorldPacket const* WorldPackets::Movement::MoveUpdateCollisionHeight::Write() return &_worldPacket; } -WorldPacket const* WorldPackets::Movement::MoveUpdateRemoveMovementForce::Write() +WorldPacket const* WorldPackets::Movement::MoveApplyMovementForce::Write() { - _worldPacket << *Status; - _worldPacket << TriggerGUID; + _worldPacket << MoverGUID; + _worldPacket << SequenceIndex; + _worldPacket << *Force; return &_worldPacket; } +void WorldPackets::Movement::MoveApplyMovementForceAck::Read() +{ + _worldPacket >> Ack; + _worldPacket >> Force; +} + +WorldPacket const* WorldPackets::Movement::MoveRemoveMovementForce::Write() +{ + _worldPacket << MoverGUID; + _worldPacket << SequenceIndex; + _worldPacket << ID; + + return &_worldPacket; +} + +void WorldPackets::Movement::MoveRemoveMovementForceAck::Read() +{ + _worldPacket >> Ack; + _worldPacket >> ID; +} + WorldPacket const* WorldPackets::Movement::MoveUpdateApplyMovementForce::Write() { _worldPacket << *Status; - _worldPacket << Force; + _worldPacket << *Force; + + return &_worldPacket; +} + +WorldPacket const* WorldPackets::Movement::MoveUpdateRemoveMovementForce::Write() +{ + _worldPacket << *Status; + _worldPacket << TriggerGUID; return &_worldPacket; } diff --git a/src/server/game/Server/Packets/MovementPackets.h b/src/server/game/Server/Packets/MovementPackets.h index f806551c24c..47197949c55 100644 --- a/src/server/game/Server/Packets/MovementPackets.h +++ b/src/server/game/Server/Packets/MovementPackets.h @@ -33,6 +33,12 @@ namespace WorldPackets { namespace Movement { + struct MovementAck + { + MovementInfo Status; + int32 AckIndex = 0; + }; + class ClientPlayerMovement final : public ClientPacket { public: @@ -269,16 +275,6 @@ namespace WorldPackets uint8 PreloadWorld = 0; }; - struct MovementForce - { - ObjectGuid ID; - TaggedPosition<Position::XYZ> Origin; - TaggedPosition<Position::XYZ> Direction; - uint32 TransportID = 0; - float Magnitude = 0; - uint8 Type = 0; - }; - class MoveUpdateTeleport final : public ServerPacket { public: @@ -287,7 +283,7 @@ namespace WorldPackets WorldPacket const* Write() override; MovementInfo* Status = nullptr; - std::vector<MovementForce> MovementForces; + ::MovementForces::Container const* MovementForces = nullptr; Optional<float> SwimBackSpeed; Optional<float> FlightSpeed; Optional<float> SwimSpeed; @@ -299,21 +295,67 @@ namespace WorldPackets Optional<float> PitchRate; }; + class MoveApplyMovementForce final : public ServerPacket + { + public: + MoveApplyMovementForce() : ServerPacket(SMSG_MOVE_APPLY_MOVEMENT_FORCE, 16 + 4 + 16 + 12 + 12 + 4 + 4 + 1) { } + + WorldPacket const* Write() override; + + ObjectGuid MoverGUID; + int32 SequenceIndex = 0; + MovementForce const* Force = nullptr; + }; + + class MoveApplyMovementForceAck final : public ClientPacket + { + public: + MoveApplyMovementForceAck(WorldPacket&& packet) : ClientPacket(CMSG_MOVE_APPLY_MOVEMENT_FORCE_ACK, std::move(packet)) { } + + void Read() override; + + MovementAck Ack; + MovementForce Force; + }; + + class MoveRemoveMovementForce final : public ServerPacket + { + public: + MoveRemoveMovementForce() : ServerPacket(SMSG_MOVE_REMOVE_MOVEMENT_FORCE, 16 + 4 + 16) { } + + WorldPacket const* Write() override; + + ObjectGuid MoverGUID; + int32 SequenceIndex = 0; + ObjectGuid ID; + }; + + class MoveRemoveMovementForceAck final : public ClientPacket + { + public: + MoveRemoveMovementForceAck(WorldPacket&& packet) : ClientPacket(CMSG_MOVE_REMOVE_MOVEMENT_FORCE_ACK, std::move(packet)) { } + + void Read() override; + + MovementAck Ack; + ObjectGuid ID; + }; + class MoveUpdateApplyMovementForce final : public ServerPacket { public: - MoveUpdateApplyMovementForce() : ServerPacket(SMSG_MOVE_UPDATE_APPLY_MOVEMENT_FORCE) { } + MoveUpdateApplyMovementForce() : ServerPacket(SMSG_MOVE_UPDATE_APPLY_MOVEMENT_FORCE, sizeof(MovementInfo) + 16 + 12 + 12 + 4 + 4 + 1) { } WorldPacket const* Write() override; MovementInfo* Status = nullptr; - MovementForce Force; + MovementForce const* Force = nullptr; }; class MoveUpdateRemoveMovementForce final : public ServerPacket { public: - MoveUpdateRemoveMovementForce() : ServerPacket(SMSG_MOVE_UPDATE_REMOVE_MOVEMENT_FORCE) { } + MoveUpdateRemoveMovementForce() : ServerPacket(SMSG_MOVE_UPDATE_REMOVE_MOVEMENT_FORCE, sizeof(MovementInfo) + 16) { } WorldPacket const* Write() override; @@ -333,12 +375,6 @@ namespace WorldPackets int32 MoveTime = 0; }; - struct MovementAck - { - MovementInfo Status; - int32 AckIndex = 0; - }; - class MovementAckMessage final : public ClientPacket { public: @@ -616,5 +652,6 @@ ByteBuffer& operator<<(ByteBuffer& data, MovementInfo const& movementInfo); ByteBuffer& operator>>(ByteBuffer& data, MovementInfo::TransportInfo& transportInfo); ByteBuffer& operator<<(ByteBuffer& data, MovementInfo::TransportInfo const& transportInfo); ByteBuffer& operator>>(ByteBuffer& data, WorldPackets::Movement::MovementAck& movementAck); +ByteBuffer& operator<<(ByteBuffer& data, MovementForce const& movementForce); #endif // MovementPackets_h__ diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp index 13306152bcd..0cf5e036ac4 100644 --- a/src/server/game/Server/Protocol/Opcodes.cpp +++ b/src/server/game/Server/Protocol/Opcodes.cpp @@ -542,7 +542,7 @@ void OpcodeTable::Initialize() DEFINE_HANDLER(CMSG_MOUNT_CLEAR_FANFARE, STATUS_UNHANDLED, PROCESS_THREADUNSAFE, &WorldSession::Handle_NULL); DEFINE_HANDLER(CMSG_MOUNT_SET_FAVORITE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMountSetFavorite); DEFINE_HANDLER(CMSG_MOUNT_SPECIAL_ANIM, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMountSpecialAnimOpcode); - DEFINE_HANDLER(CMSG_MOVE_APPLY_MOVEMENT_FORCE_ACK, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL); + DEFINE_HANDLER(CMSG_MOVE_APPLY_MOVEMENT_FORCE_ACK, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMoveApplyMovementForceAck); DEFINE_HANDLER(CMSG_MOVE_CHANGE_TRANSPORT, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes); DEFINE_HANDLER(CMSG_MOVE_CHANGE_VEHICLE_SEATS, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMoveChangeVehicleSeats); DEFINE_HANDLER(CMSG_MOVE_DISMISS_VEHICLE, STATUS_LOGGEDIN, PROCESS_THREADUNSAFE, &WorldSession::HandleMoveDismissVehicle); @@ -570,7 +570,7 @@ void OpcodeTable::Initialize() DEFINE_HANDLER(CMSG_MOVE_JUMP, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes); DEFINE_HANDLER(CMSG_MOVE_KNOCK_BACK_ACK, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMoveKnockBackAck); DEFINE_HANDLER(CMSG_MOVE_REMOVE_MOVEMENT_FORCES, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::Handle_NULL); - DEFINE_HANDLER(CMSG_MOVE_REMOVE_MOVEMENT_FORCE_ACK, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::Handle_NULL); + DEFINE_HANDLER(CMSG_MOVE_REMOVE_MOVEMENT_FORCE_ACK, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMoveRemoveMovementForceAck); DEFINE_HANDLER(CMSG_MOVE_SEAMLESS_TRANSFER_COMPLETE, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::Handle_NULL); DEFINE_HANDLER(CMSG_MOVE_SET_CAN_FLY_ACK, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementAckMessage); DEFINE_HANDLER(CMSG_MOVE_SET_CAN_TURN_WHILE_FALLING_ACK, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementAckMessage); @@ -578,7 +578,7 @@ void OpcodeTable::Initialize() DEFINE_HANDLER(CMSG_MOVE_SET_FACING, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes); DEFINE_HANDLER(CMSG_MOVE_SET_FLY, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes); DEFINE_HANDLER(CMSG_MOVE_SET_IGNORE_MOVEMENT_FORCES_ACK, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementAckMessage); - DEFINE_HANDLER(CMSG_MOVE_SET_MOD_MOVEMENT_FORCE_MAGNITUDE_ACK, STATUS_UNHANDLED, PROCESS_THREADSAFE, &WorldSession::Handle_NULL); + DEFINE_HANDLER(CMSG_MOVE_SET_MOD_MOVEMENT_FORCE_MAGNITUDE_ACK, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMoveSetModMovementForceMagnitudeAck); DEFINE_HANDLER(CMSG_MOVE_SET_PITCH, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes); DEFINE_HANDLER(CMSG_MOVE_SET_RUN_MODE, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes); DEFINE_HANDLER(CMSG_MOVE_SET_VEHICLE_REC_ID_ACK, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMoveSetVehicleRecAck); @@ -1444,7 +1444,7 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_MOTD, STATUS_NEVER, CONNECTION_TYPE_REALM); DEFINE_SERVER_OPCODE_HANDLER(SMSG_MOUNT_EQUIPMENT_APPLY_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_MOUNT_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_MOVE_APPLY_MOVEMENT_FORCE, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_MOVE_APPLY_MOVEMENT_FORCE, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_MOVE_DISABLE_COLLISION, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_MOVE_DISABLE_DOUBLE_JUMP, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_MOVE_DISABLE_GRAVITY, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); @@ -1454,7 +1454,7 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_MOVE_ENABLE_GRAVITY, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_MOVE_ENABLE_TRANSITION_BETWEEN_SWIM_AND_FLY, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_MOVE_KNOCK_BACK, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_MOVE_REMOVE_MOVEMENT_FORCE, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_MOVE_REMOVE_MOVEMENT_FORCE, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_MOVE_ROOT, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_MOVE_SET_ACTIVE_MOVER, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_MOVE_SET_CAN_FLY, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); @@ -1465,9 +1465,9 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_MOVE_SET_FLIGHT_BACK_SPEED, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_MOVE_SET_FLIGHT_SPEED, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_MOVE_SET_HOVERING, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_MOVE_SET_IGNORE_MOVEMENT_FORCES, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_MOVE_SET_IGNORE_MOVEMENT_FORCES, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_MOVE_SET_LAND_WALK, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_MOVE_SET_MOD_MOVEMENT_FORCE_MAGNITUDE, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_MOVE_SET_MOD_MOVEMENT_FORCE_MAGNITUDE, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_MOVE_SET_NORMAL_FALL, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_MOVE_SET_PITCH_RATE, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_MOVE_SET_RUN_BACK_SPEED, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); @@ -1518,7 +1518,7 @@ void OpcodeTable::Initialize() DEFINE_SERVER_OPCODE_HANDLER(SMSG_MOVE_UPDATE_FLIGHT_BACK_SPEED, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_MOVE_UPDATE_FLIGHT_SPEED, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_MOVE_UPDATE_KNOCK_BACK, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); - DEFINE_SERVER_OPCODE_HANDLER(SMSG_MOVE_UPDATE_MOD_MOVEMENT_FORCE_MAGNITUDE,STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE); + DEFINE_SERVER_OPCODE_HANDLER(SMSG_MOVE_UPDATE_MOD_MOVEMENT_FORCE_MAGNITUDE,STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_MOVE_UPDATE_PITCH_RATE, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_MOVE_UPDATE_REMOVE_MOVEMENT_FORCE, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); DEFINE_SERVER_OPCODE_HANDLER(SMSG_MOVE_UPDATE_RUN_BACK_SPEED, STATUS_NEVER, CONNECTION_TYPE_INSTANCE); diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index 5607e6c375b..52f6766d7ff 100644 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -479,6 +479,8 @@ namespace WorldPackets class SummonResponse; class MoveSplineDone; class SuspendTokenResponse; + class MoveApplyMovementForceAck; + class MoveRemoveMovementForceAck; } namespace NPC @@ -1163,6 +1165,11 @@ class TC_GAME_API WorldSession void HandleForceSpeedChangeAck(WorldPackets::Movement::MovementSpeedAck& packet); void HandleSetCollisionHeightAck(WorldPackets::Movement::MoveSetCollisionHeightAck& setCollisionHeightAck); + // Movement forces + void HandleMoveApplyMovementForceAck(WorldPackets::Movement::MoveApplyMovementForceAck& moveApplyMovementForceAck); + void HandleMoveRemoveMovementForceAck(WorldPackets::Movement::MoveRemoveMovementForceAck& moveRemoveMovementForceAck); + void HandleMoveSetModMovementForceMagnitudeAck(WorldPackets::Movement::MovementSpeedAck& setModMovementForceMagnitudeAck); + void HandleRepopRequest(WorldPackets::Misc::RepopRequest& packet); void HandleAutostoreLootItemOpcode(WorldPackets::Loot::LootItem& packet); void HandleLootMoneyOpcode(WorldPackets::Loot::LootMoney& packet); diff --git a/src/server/game/Spells/Auras/SpellAuraDefines.h b/src/server/game/Spells/Auras/SpellAuraDefines.h index 8d83c108304..5590a396a5f 100644 --- a/src/server/game/Spells/Auras/SpellAuraDefines.h +++ b/src/server/game/Spells/Auras/SpellAuraDefines.h @@ -555,7 +555,7 @@ enum AuraType : uint32 SPELL_AURA_482 = 482, SPELL_AURA_SUPPRESS_TRANSFORMS = 483, // NYI SPELL_AURA_484 = 484, - SPELL_AURA_485 = 485, + SPELL_AURA_MOD_MOVEMENT_FORCE_MAGNITUDE = 485, SPELL_AURA_486 = 486, SPELL_AURA_487 = 487, SPELL_AURA_488 = 488, diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 77cc228683b..dd155e91952 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -551,7 +551,7 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]= &AuraEffect::HandleNULL, //482 &AuraEffect::HandleNULL, //483 SPELL_AURA_SUPPRESS_TRANSFORMS &AuraEffect::HandleNULL, //484 - &AuraEffect::HandleNULL, //485 + &AuraEffect::HandleModMovementForceMagnitude, //485 SPELL_AURA_MOD_MOVEMENT_FORCE_MAGNITUDE &AuraEffect::HandleNULL, //486 &AuraEffect::HandleNULL, //487 &AuraEffect::HandleNULL, //488 @@ -2693,6 +2693,23 @@ void AuraEffect::HandleAuraCanTurnWhileFalling(AuraApplication const* aurApp, ui target->SetCanTurnWhileFalling(apply); } +void AuraEffect::HandleIgnoreMovementForces(AuraApplication const* aurApp, uint8 mode, bool apply) const +{ + if (!(mode & AURA_EFFECT_HANDLE_SEND_FOR_CLIENT_MASK)) + 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 ***/ /****************************/ @@ -3061,6 +3078,14 @@ void AuraEffect::HandleAuraModMinimumSpeedRate(AuraApplication const* aurApp, ui target->UpdateSpeed(MOVE_RUN); } +void AuraEffect::HandleModMovementForceMagnitude(AuraApplication const* aurApp, uint8 mode, bool /*apply*/) const +{ + if (!(mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK)) + return; + + aurApp->GetTarget()->UpdateMovementForcesModMagnitude(); +} + /*********************************************************/ /*** IMMUNITY ***/ /*********************************************************/ diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.h b/src/server/game/Spells/Auras/SpellAuraEffects.h index a9d8ea4a52c..829cfa4cd26 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.h +++ b/src/server/game/Spells/Auras/SpellAuraEffects.h @@ -187,6 +187,7 @@ class TC_GAME_API AuraEffect void HandleWaterBreathing(AuraApplication const* aurApp, uint8 mode, bool apply) const; void HandleForceMoveForward(AuraApplication const* aurApp, uint8 mode, bool apply) const; void HandleAuraCanTurnWhileFalling(AuraApplication const* aurApp, uint8 mode, bool apply) const; + void HandleIgnoreMovementForces(AuraApplication const* aurApp, uint8 mode, bool apply) const; // threat void HandleModThreat(AuraApplication const* aurApp, uint8 mode, bool apply) const; void HandleAuraModTotalThreat(AuraApplication const* aurApp, uint8 mode, bool apply) const; @@ -211,6 +212,7 @@ class TC_GAME_API AuraEffect void HandleAuraModDecreaseSpeed(AuraApplication const* aurApp, uint8 mode, bool apply) const; void HandleAuraModUseNormalSpeed(AuraApplication const* aurApp, uint8 mode, bool apply) const; void HandleAuraModMinimumSpeedRate(AuraApplication const* aurApp, uint8 mode, bool apply) const; + void HandleModMovementForceMagnitude(AuraApplication const* aurApp, uint8 mode, bool apply) const; // immunity void HandleModMechanicImmunityMask(AuraApplication const* aurApp, uint8 mode, bool apply) const; void HandleModMechanicImmunity(AuraApplication const* aurApp, uint8 mode, bool apply) const; |