From d58046032bfca733873421f8addca75edf2ffd47 Mon Sep 17 00:00:00 2001 From: killerwife Date: Fri, 24 Oct 2025 23:48:58 +0200 Subject: [PATCH] fix(Core/Movement): Add force speed ack to async movement and resolve stutter (#23371) --- .../game/Entities/Creature/Creature.cpp | 59 ++---- src/server/game/Entities/Creature/Creature.h | 3 +- src/server/game/Entities/Player/Player.cpp | 26 +-- src/server/game/Entities/Player/Player.h | 2 - src/server/game/Entities/Unit/Unit.cpp | 186 +++++++----------- src/server/game/Entities/Unit/Unit.h | 24 ++- src/server/game/Handlers/MiscHandler.cpp | 20 +- src/server/game/Handlers/MovementHandler.cpp | 85 ++++---- src/server/game/Server/Protocol/Opcodes.cpp | 8 +- src/server/scripts/Commands/cs_modify.cpp | 8 +- .../IcecrownCitadel/boss_the_lich_king.cpp | 4 +- .../Nexus/EyeOfEternity/boss_malygos.cpp | 9 +- .../Outland/TempestKeep/Eye/boss_kaelthas.cpp | 2 +- 13 files changed, 173 insertions(+), 263 deletions(-) diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 4b18aa2e9..19db15590 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -1999,7 +1999,7 @@ void Creature::setDeathState(DeathState state, bool despawn) bool needsFalling = !despawn && (IsFlying() || IsHovering()) && !IsUnderWater(); SetHover(false); - SetDisableGravity(false, false, false); + SetDisableGravity(false); if (needsFalling) GetMotionMaster()->MoveFall(0, true); @@ -3230,47 +3230,6 @@ bool Creature::SetWalk(bool enable) return true; } -/** - * @brief Enable or disable the creature's fly mode by adding or removing: MOVEMENTFLAG_FLYING. Infom also the client - */ -bool Creature::SetDisableGravity(bool disable, bool packetOnly /*= false*/, bool updateAnimationTier /*= true*/) -{ - //! It's possible only a packet is sent but moveflags are not updated - //! Need more research on this - if (!packetOnly && !Unit::SetDisableGravity(disable)) - return false; - - if (m_movedByPlayer) - { - WorldPacket data(disable ? SMSG_MOVE_GRAVITY_DISABLE : SMSG_MOVE_GRAVITY_ENABLE, 12); - data << GetPackGUID(); - data << m_movedByPlayer->ToPlayer()->GetSession()->GetOrderCounter(); // movement counter - m_movedByPlayer->ToPlayer()->SendDirectMessage(&data); - m_movedByPlayer->ToPlayer()->GetSession()->IncrementOrderCounter(); - - data.Initialize(MSG_MOVE_GRAVITY_CHNG, 64); - data << GetPackGUID(); - BuildMovementPacket(&data); - m_movedByPlayer->ToPlayer()->SendMessageToSet(&data, false); - return true; - } - - if (updateAnimationTier && IsAlive() && !HasUnitState(UNIT_STATE_ROOT) && !IsRooted()) - { - if (IsLevitating()) - SetByteValue(UNIT_FIELD_BYTES_1, UNIT_BYTES_1_OFFSET_ANIM_TIER, UNIT_BYTE1_FLAG_FLY); - else if (IsHovering()) - SetByteValue(UNIT_FIELD_BYTES_1, UNIT_BYTES_1_OFFSET_ANIM_TIER, UNIT_BYTE1_FLAG_HOVER); - else - SetByteValue(UNIT_FIELD_BYTES_1, UNIT_BYTES_1_OFFSET_ANIM_TIER, UNIT_BYTE1_FLAG_GROUND); - } - - WorldPacket data(disable ? SMSG_SPLINE_MOVE_GRAVITY_DISABLE : SMSG_SPLINE_MOVE_GRAVITY_ENABLE, 9); - data << GetPackGUID(); - SendMessageToSet(&data, false); - return true; -} - bool Creature::SetSwim(bool enable) { if (!Unit::SetSwim(enable)) @@ -3385,19 +3344,23 @@ void Creature::UpdateMovementFlags() if (GetMovementTemplate().IsFlightAllowed() && isInAir && !IsFalling()) { - if (GetMovementTemplate().Flight == CreatureFlightMovementType::CanFly) + if (GetMovementTemplate().Flight == CreatureFlightMovementType::CanFly && !m_movementInfo.HasMovementFlag(MOVEMENTFLAG_CAN_FLY)) SetCanFly(true); - else + else if (!IsLevitating()) SetDisableGravity(true); - if (!HasHoverAura()) + if (!HasHoverAura() && IsHovering()) SetHover(false); } else { - SetCanFly(false); - SetDisableGravity(false); - if (IsAlive() && (CanHover() || HasHoverAura())) + if (m_movementInfo.HasMovementFlag(MOVEMENTFLAG_CAN_FLY)) + SetCanFly(false); + + if (IsLevitating()) + SetDisableGravity(false); + + if (IsAlive() && (GetMovementTemplate().Ground == CreatureGroundMovementType::Hover || HasHoverAura()) && !IsHovering()) SetHover(true); } diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index 1ea560045..b5d93cd3b 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -83,7 +83,7 @@ public: [[nodiscard]] bool CanWalk() const { return GetMovementTemplate().IsGroundAllowed(); } [[nodiscard]] bool CanSwim() const override; [[nodiscard]] bool CanEnterWater() const override; - [[nodiscard]] bool CanFly() const override { return GetMovementTemplate().IsFlightAllowed() || IsFlying(); } + [[nodiscard]] bool CanFly() const override { return GetMovementTemplate().IsFlightAllowed() || IsFlying(); } [[nodiscard]] bool CanHover() const { return GetMovementTemplate().Ground == CreatureGroundMovementType::Hover || IsHovering(); } [[nodiscard]] bool IsRooted() const { return GetMovementTemplate().IsRooted(); } @@ -145,7 +145,6 @@ public: [[nodiscard]] CreatureAI* AI() const { return (CreatureAI*)i_AI; } bool SetWalk(bool enable) override; - bool SetDisableGravity(bool disable, bool packetOnly = false, bool updateAnimationTier = true) override; bool SetSwim(bool enable) override; bool HasSpellFocus(Spell const* focusSpell = nullptr) const; diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 7bca647f7..e4e703492 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -11704,7 +11704,7 @@ void Player::SendInitialPacketsAfterAddToMap() // manual send package (have code in HandleEffect(this, AURA_EFFECT_HANDLE_SEND_FOR_CLIENT, true); that must not be re-applied. if (IsImmobilizedState()) { - auto const counter = GetSession()->GetOrderCounter(); + uint32 const counter = GetSession()->GetOrderCounter(); setCompoundState << uint8(2 + GetPackGUID().size() + 4); setCompoundState << uint16(SMSG_FORCE_MOVE_ROOT); setCompoundState << GetPackGUID(); @@ -11714,7 +11714,7 @@ void Player::SendInitialPacketsAfterAddToMap() if (HasAuraType(SPELL_AURA_FEATHER_FALL)) { - auto const counter = GetSession()->GetOrderCounter(); + uint32 const counter = GetSession()->GetOrderCounter(); setCompoundState << uint8(2 + GetPackGUID().size() + 4); setCompoundState << uint16(SMSG_MOVE_FEATHER_FALL); setCompoundState << GetPackGUID(); @@ -11724,7 +11724,7 @@ void Player::SendInitialPacketsAfterAddToMap() if (HasAuraType(SPELL_AURA_WATER_WALK)) { - auto const counter = GetSession()->GetOrderCounter(); + uint32 const counter = GetSession()->GetOrderCounter(); setCompoundState << uint8(2 + GetPackGUID().size() + 4); setCompoundState << uint16(SMSG_MOVE_WATER_WALK); setCompoundState << GetPackGUID(); @@ -11734,7 +11734,7 @@ void Player::SendInitialPacketsAfterAddToMap() if (HasAuraType(SPELL_AURA_HOVER)) { - auto const counter = GetSession()->GetOrderCounter(); + uint32 const counter = GetSession()->GetOrderCounter(); setCompoundState << uint8(2 + GetPackGUID().size() + 4); setCompoundState << uint16(SMSG_MOVE_SET_HOVER); setCompoundState << GetPackGUID(); @@ -16034,24 +16034,6 @@ bool Player::IsInWhisperWhiteList(ObjectGuid guid) return false; } -bool Player::SetDisableGravity(bool disable, bool packetOnly /*= false*/, bool /*updateAnimationTier = true*/) -{ - if (!packetOnly && !Unit::SetDisableGravity(disable)) - return false; - - WorldPacket data(disable ? SMSG_MOVE_GRAVITY_DISABLE : SMSG_MOVE_GRAVITY_ENABLE, 12); - data << GetPackGUID(); - data << GetSession()->GetOrderCounter(); // movement counter - SendDirectMessage(&data); - GetSession()->IncrementOrderCounter(); - - data.Initialize(MSG_MOVE_GRAVITY_CHNG, 64); - data << GetPackGUID(); - BuildMovementPacket(&data); - SendMessageToSet(&data, false); - return true; -} - Guild* Player::GetGuild() const { uint32 guildId = GetGuildId(); diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 7154eaa33..11bb75df4 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -2566,8 +2566,6 @@ public: bool IsInWhisperWhiteList(ObjectGuid guid); void RemoveFromWhisperWhiteList(ObjectGuid guid) { WhisperList.remove(guid); } - bool SetDisableGravity(bool disable, bool packetOnly = false, bool updateAnimationTier = true) override; - [[nodiscard]] bool CanFly() const override { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_CAN_FLY); } [[nodiscard]] bool CanEnterWater() const override { return true; } bool IsFreeFlying() const { return HasAuraType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED) || HasAuraType(SPELL_AURA_FLY); } diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 4ec9c9567..4c9d6b60c 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -14523,116 +14523,55 @@ void Unit::SetSpeed(UnitMoveType mtype, float rate, bool forced) propagateSpeedChange(); - WorldPacket data; - if (!forced) - { - switch (mtype) - { - case MOVE_WALK: - data.Initialize(MSG_MOVE_SET_WALK_SPEED, 8 + 4 + 2 + 4 + 4 + 4 + 4 + 4 + 4 + 4); - break; - case MOVE_RUN: - data.Initialize(MSG_MOVE_SET_RUN_SPEED, 8 + 4 + 2 + 4 + 4 + 4 + 4 + 4 + 4 + 4); - break; - case MOVE_RUN_BACK: - data.Initialize(MSG_MOVE_SET_RUN_BACK_SPEED, 8 + 4 + 2 + 4 + 4 + 4 + 4 + 4 + 4 + 4); - break; - case MOVE_SWIM: - data.Initialize(MSG_MOVE_SET_SWIM_SPEED, 8 + 4 + 2 + 4 + 4 + 4 + 4 + 4 + 4 + 4); - break; - case MOVE_SWIM_BACK: - data.Initialize(MSG_MOVE_SET_SWIM_BACK_SPEED, 8 + 4 + 2 + 4 + 4 + 4 + 4 + 4 + 4 + 4); - break; - case MOVE_TURN_RATE: - data.Initialize(MSG_MOVE_SET_TURN_RATE, 8 + 4 + 2 + 4 + 4 + 4 + 4 + 4 + 4 + 4); - break; - case MOVE_FLIGHT: - data.Initialize(MSG_MOVE_SET_FLIGHT_SPEED, 8 + 4 + 2 + 4 + 4 + 4 + 4 + 4 + 4 + 4); - break; - case MOVE_FLIGHT_BACK: - data.Initialize(MSG_MOVE_SET_FLIGHT_BACK_SPEED, 8 + 4 + 2 + 4 + 4 + 4 + 4 + 4 + 4 + 4); - break; - case MOVE_PITCH_RATE: - data.Initialize(MSG_MOVE_SET_PITCH_RATE, 8 + 4 + 2 + 4 + 4 + 4 + 4 + 4 + 4 + 4); - break; - default: - LOG_ERROR("entities.unit", "Unit::SetSpeed: Unsupported move type ({}), data not sent to client.", mtype); - return; - } + SpeedOpcodePair const& speedOpcodes = SetSpeed2Opc_table[mtype]; + if (forced && IsClientControlled()) + { + Player* player = const_cast(GetClientControlling()); + uint32 const counter = player->GetSession()->GetOrderCounter(); + + // register forced speed changes for WorldSession::HandleForceSpeedChangeAck + // and do it only for real sent packets and use run for run/mounted as client expected + ++player->m_forced_speed_changes[mtype]; + + WorldPacket data(speedOpcodes[static_cast(SpeedOpcodeIndex::PC)], 18); + data << GetPackGUID(); + data << counter; + if (mtype == MOVE_RUN) + data << uint8(0); // new 2.1.0 + + data << GetSpeed(mtype); + player->GetSession()->SendPacket(&data); + player->GetSession()->IncrementOrderCounter(); + } + else if (forced) + { + WorldPacket data(speedOpcodes[static_cast(SpeedOpcodeIndex::NPC)], 12); data << GetPackGUID(); - BuildMovementPacket(&data); data << float(GetSpeed(mtype)); SendMessageToSet(&data, true); } - else + + if (IsPlayer()) { - if (IsPlayer()) + // Xinef: update speed of pet also + if (!IsInCombat()) { - // register forced speed changes for WorldSession::HandleForceSpeedChangeAck - // and do it only for real sent packets and use run for run/mounted as client expected - ++ToPlayer()->m_forced_speed_changes[mtype]; + Unit* pet = ToPlayer()->GetPet(); + if (!pet) + pet = GetCharm(); - // Xinef: update speed of pet also - if (!IsInCombat()) - { - Unit* pet = ToPlayer()->GetPet(); - if (!pet) - pet = GetCharm(); + // xinef: do not affect vehicles and possesed pets + if (pet && (pet->HasUnitFlag(UNIT_FLAG_POSSESSED) || pet->IsVehicle())) + pet = nullptr; - // xinef: do not affect vehicles and possesed pets - if (pet && (pet->HasUnitFlag(UNIT_FLAG_POSSESSED) || pet->IsVehicle())) - pet = nullptr; + if (pet && pet->IsCreature() && !pet->IsInCombat() && pet->GetMotionMaster()->GetCurrentMovementGeneratorType() == FOLLOW_MOTION_TYPE) + pet->UpdateSpeed(mtype, forced); - if (pet && pet->IsCreature() && !pet->IsInCombat() && pet->GetMotionMaster()->GetCurrentMovementGeneratorType() == FOLLOW_MOTION_TYPE) - pet->UpdateSpeed(mtype, forced); - if (Unit* critter = ObjectAccessor::GetUnit(*this, GetCritterGUID())) - critter->UpdateSpeed(mtype, forced); - } - ToPlayer()->SetCanTeleport(true); + if (Unit* critter = ObjectAccessor::GetUnit(*this, GetCritterGUID())) + critter->UpdateSpeed(mtype, forced); } - - switch (mtype) - { - case MOVE_WALK: - data.Initialize(SMSG_FORCE_WALK_SPEED_CHANGE, 16); - break; - case MOVE_RUN: - data.Initialize(SMSG_FORCE_RUN_SPEED_CHANGE, 17); - break; - case MOVE_RUN_BACK: - data.Initialize(SMSG_FORCE_RUN_BACK_SPEED_CHANGE, 16); - break; - case MOVE_SWIM: - data.Initialize(SMSG_FORCE_SWIM_SPEED_CHANGE, 16); - break; - case MOVE_SWIM_BACK: - data.Initialize(SMSG_FORCE_SWIM_BACK_SPEED_CHANGE, 16); - break; - case MOVE_TURN_RATE: - data.Initialize(SMSG_FORCE_TURN_RATE_CHANGE, 16); - break; - case MOVE_FLIGHT: - data.Initialize(SMSG_FORCE_FLIGHT_SPEED_CHANGE, 16); - break; - case MOVE_FLIGHT_BACK: - data.Initialize(SMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE, 16); - break; - case MOVE_PITCH_RATE: - data.Initialize(SMSG_FORCE_PITCH_RATE_CHANGE, 16); - break; - default: - LOG_ERROR("entities.unit", "Unit::SetSpeed: Unsupported move type ({}), data not sent to client.", mtype); - return; - } - data << GetPackGUID(); - data << (IsPlayer() ? ToPlayer()->GetSession()->GetOrderCounter() : uint32(0)); // movement counter - if (mtype == MOVE_RUN) - data << uint8(0); // new 2.1.0 - data << float(GetSpeed(mtype)); - SendMessageToSet(&data, true); - if (IsPlayer()) // TODO: Resolve this mess - ToPlayer()->GetSession()->IncrementOrderCounter(); + ToPlayer()->SetCanTeleport(true); } } @@ -18343,7 +18282,7 @@ void Unit::SendMoveRoot(bool apply) // Wrath+ force root: when unit is controlled by a player else { - auto const counter = client->GetSession()->GetOrderCounter(); + uint32 const counter = client->GetSession()->GetOrderCounter(); WorldPacket data(apply ? SMSG_FORCE_MOVE_ROOT : SMSG_FORCE_MOVE_UNROOT, guid.size() + 4); data << guid; @@ -20381,22 +20320,39 @@ bool Unit::SetWalk(bool enable) return true; } -bool Unit::SetDisableGravity(bool disable, bool /*packetOnly = false*/, bool /*updateAnimationTier = true*/) +void Unit::SetDisableGravity(bool enable) { - if (disable == IsLevitating()) - return false; + bool isClientControlled = IsClientControlled(); - if (disable) + if (!isClientControlled) { - AddUnitMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY); - RemoveUnitMovementFlag(MOVEMENTFLAG_FALLING); - } - else - { - RemoveUnitMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY); + if (enable) + m_movementInfo.AddMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY); + else + m_movementInfo.RemoveMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY); } - return true; + if (!IsInWorld()) // is sent on add to map + return; + + if (isClientControlled) + { + if (Player const* player = GetClientControlling()) + { + uint32 const counter = player->GetSession()->GetOrderCounter(); + + WorldPacket data(enable ? SMSG_MOVE_GRAVITY_DISABLE : SMSG_MOVE_GRAVITY_ENABLE, GetPackGUID().size() + 4); + data << GetPackGUID(); + data << counter; + player->GetSession()->SendPacket(&data); + player->GetSession()->IncrementOrderCounter(); + return; + } + } + + WorldPacket data(enable ? SMSG_SPLINE_MOVE_GRAVITY_DISABLE : SMSG_SPLINE_MOVE_GRAVITY_ENABLE, 9); + data << GetPackGUID(); + SendMessageToSet(&data, true); } bool Unit::SetSwim(bool enable) @@ -20443,7 +20399,7 @@ void Unit::SetCanFly(bool enable) { if (Player const* player = GetClientControlling()) { - auto const counter = player->GetSession()->GetOrderCounter(); + uint32 const counter = player->GetSession()->GetOrderCounter(); WorldPacket data(enable ? SMSG_MOVE_SET_CAN_FLY : SMSG_MOVE_UNSET_CAN_FLY, GetPackGUID().size() + 4); data << GetPackGUID(); @@ -20478,7 +20434,7 @@ void Unit::SetFeatherFall(bool enable) { if (Player const* player = GetClientControlling()) { - auto const counter = player->GetSession()->GetOrderCounter(); + uint32 const counter = player->GetSession()->GetOrderCounter(); WorldPacket data(enable ? SMSG_MOVE_FEATHER_FALL : SMSG_MOVE_NORMAL_FALL, GetPackGUID().size() + 4); @@ -20538,7 +20494,7 @@ void Unit::SetHover(bool enable) { WorldPacket data(enable ? SMSG_MOVE_SET_HOVER : SMSG_MOVE_UNSET_HOVER, GetPackGUID().size() + 4); - auto const counter = player->GetSession()->GetOrderCounter(); + uint32 const counter = player->GetSession()->GetOrderCounter(); data << GetPackGUID(); data << counter; @@ -20572,7 +20528,7 @@ void Unit::SetWaterWalking(bool enable) { if (Player const* player = GetClientControlling()) { - auto const counter = player->GetSession()->GetOrderCounter(); + uint32 const counter = player->GetSession()->GetOrderCounter(); WorldPacket data(enable ? SMSG_MOVE_WATER_WALK : SMSG_MOVE_LAND_WALK, GetPackGUID().size() + 4); data << GetPackGUID(); diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 7b98132fe..a1d3f2e74 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -624,6 +624,28 @@ typedef std::unordered_map PacketCooldowns; struct SpellProcEventEntry; // used only privately +enum class SpeedOpcodeIndex : uint32 +{ + PC, + NPC, + ACK_RESPONSE, + MAX +}; + +typedef const Opcodes SpeedOpcodePair[static_cast(SpeedOpcodeIndex::MAX)]; +SpeedOpcodePair SetSpeed2Opc_table[MAX_MOVE_TYPE] = +{ + {SMSG_FORCE_WALK_SPEED_CHANGE, SMSG_SPLINE_SET_WALK_SPEED, MSG_MOVE_SET_WALK_SPEED}, + {SMSG_FORCE_RUN_SPEED_CHANGE, SMSG_SPLINE_SET_RUN_SPEED, MSG_MOVE_SET_RUN_SPEED}, + {SMSG_FORCE_RUN_BACK_SPEED_CHANGE, SMSG_SPLINE_SET_RUN_BACK_SPEED, MSG_MOVE_SET_RUN_BACK_SPEED}, + {SMSG_FORCE_SWIM_SPEED_CHANGE, SMSG_SPLINE_SET_SWIM_SPEED, MSG_MOVE_SET_SWIM_SPEED}, + {SMSG_FORCE_SWIM_BACK_SPEED_CHANGE, SMSG_SPLINE_SET_SWIM_BACK_SPEED, MSG_MOVE_SET_SWIM_BACK_SPEED}, + {SMSG_FORCE_TURN_RATE_CHANGE, SMSG_SPLINE_SET_TURN_RATE, MSG_MOVE_SET_TURN_RATE}, + {SMSG_FORCE_FLIGHT_SPEED_CHANGE, SMSG_SPLINE_SET_FLIGHT_SPEED, MSG_MOVE_SET_FLIGHT_SPEED}, + {SMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE, SMSG_SPLINE_SET_FLIGHT_BACK_SPEED, MSG_MOVE_SET_FLIGHT_BACK_SPEED}, + {SMSG_FORCE_PITCH_RATE_CHANGE, SMSG_SPLINE_SET_PITCH_RATE, MSG_MOVE_SET_PITCH_RATE}, +}; + class Unit : public WorldObject { public: @@ -1681,7 +1703,7 @@ public: void MonsterMoveWithSpeed(float x, float y, float z, float speed); // Not to be used outside of cinematics virtual bool SetWalk(bool enable); - virtual bool SetDisableGravity(bool disable, bool packetOnly = false, bool updateAnimationTier = true); + void SetDisableGravity(bool disable); virtual bool SetSwim(bool enable); void SetCanFly(bool enable); void SetWaterWalking(bool enable); diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp index 03c91c298..13ef9ec66 100644 --- a/src/server/game/Handlers/MiscHandler.cpp +++ b/src/server/game/Handlers/MiscHandler.cpp @@ -1490,6 +1490,8 @@ void WorldSession::HandleMoveFlagChangeOpcode(WorldPacket& recv_data) { LOG_DEBUG("network", "WORLD: {}", GetOpcodeNameForLogging((Opcodes)recv_data.GetOpcode())); + Opcodes opcode = (Opcodes)recv_data.GetOpcode(); + ObjectGuid guid; uint32 counter; uint32 isApplied; @@ -1507,7 +1509,8 @@ void WorldSession::HandleMoveFlagChangeOpcode(WorldPacket& recv_data) movementInfo.guid = guid; ReadMovementInfo(recv_data, &movementInfo); - recv_data >> isApplied; + if (opcode != CMSG_MOVE_GRAVITY_DISABLE_ACK && opcode != CMSG_MOVE_GRAVITY_ENABLE_ACK) + recv_data >> isApplied; sScriptMgr->AnticheatSetCanFlybyServer(_player, movementInfo.HasMovementFlag(MOVEMENTFLAG_CAN_FLY)); @@ -1516,6 +1519,12 @@ void WorldSession::HandleMoveFlagChangeOpcode(WorldPacket& recv_data) mover->m_movementInfo.flags = movementInfo.GetMovementFlags(); + if (!ProcessMovementInfo(movementInfo, mover, plrMover, recv_data)) + { + recv_data.rfinish(); // prevent warnings spam + return; + } + Opcodes response; switch (recv_data.GetOpcode()) @@ -1524,17 +1533,12 @@ void WorldSession::HandleMoveFlagChangeOpcode(WorldPacket& recv_data) case CMSG_MOVE_FEATHER_FALL_ACK: response = MSG_MOVE_FEATHER_FALL; break; case CMSG_MOVE_WATER_WALK_ACK: response = MSG_MOVE_WATER_WALK; break; case CMSG_MOVE_SET_CAN_FLY_ACK: response = MSG_MOVE_UPDATE_CAN_FLY; break; + case CMSG_MOVE_GRAVITY_DISABLE_ACK: response = MSG_MOVE_GRAVITY_CHNG; break; + case CMSG_MOVE_GRAVITY_ENABLE_ACK: response = MSG_MOVE_GRAVITY_CHNG; break; default: return; } - if (!ProcessMovementInfo(movementInfo, mover, plrMover, recv_data)) - { - recv_data.rfinish(); // prevent warnings spam - return; - } - WorldPacket data(response, 8); - data << guid.WriteAsPacked(); WriteMovementInfo(&data, &movementInfo); _player->m_mover->SendMessageToSet(&data, _player); } diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp index 6bf1b899b..537756706 100644 --- a/src/server/game/Handlers/MovementHandler.cpp +++ b/src/server/game/Handlers/MovementHandler.cpp @@ -378,7 +378,6 @@ void WorldSession::HandleMovementOpcodes(WorldPacket& recvData) /* process position-change */ WorldPacket data(opcode, recvData.size()); - movementInfo.guid = mover->GetGUID(); WriteMovementInfo(&data, &movementInfo); mover->SendMessageToSet(&data, _player); } @@ -655,26 +654,39 @@ void WorldSession::HandleForceSpeedChangeAck(WorldPacket& recvData) /* extract packet */ ObjectGuid guid; - uint32 unk1; + uint32 counter; + MovementInfo movementInfo; float newspeed; recvData >> guid.ReadAsPacked(); + recvData >> counter; // counter or moveEvent + movementInfo.guid = guid; + ReadMovementInfo(recvData, &movementInfo); + recvData >> newspeed; + + Unit* mover = _player->m_mover; // pussywizard: special check, only player mover allowed here - if (guid != _player->m_mover->GetGUID() || guid != _player->GetGUID()) + if (guid != mover->GetGUID() || guid != _player->GetGUID()) { recvData.rfinish(); // prevent warnings spam return; } - // continue parse packet - recvData >> unk1; // counter or moveEvent + if (!ProcessMovementInfo(movementInfo, mover, _player, recvData)) + { + recvData.rfinish(); // prevent warnings spam + return; + } - MovementInfo movementInfo; - movementInfo.guid = guid; - ReadMovementInfo(recvData, &movementInfo); - - recvData >> newspeed; + if (opcode == CMSG_MOVE_SET_COLLISION_HGT_ACK) + { + WorldPacket data(MSG_MOVE_SET_COLLISION_HGT, 18); + WriteMovementInfo(&data, &movementInfo); + data << newspeed; // new collision height + mover->SendMessageToSet(&data, _player); + return; + } // client ACK send one packet for mounted/run case and need skip all except last from its // in other cases anti-cheat check can be fail in false case @@ -685,42 +697,15 @@ void WorldSession::HandleForceSpeedChangeAck(WorldPacket& recvData) switch (opcode) { - case CMSG_FORCE_WALK_SPEED_CHANGE_ACK: - move_type = MOVE_WALK; - force_move_type = MOVE_WALK; - break; - case CMSG_FORCE_RUN_SPEED_CHANGE_ACK: - move_type = MOVE_RUN; - force_move_type = MOVE_RUN; - break; - case CMSG_FORCE_RUN_BACK_SPEED_CHANGE_ACK: - move_type = MOVE_RUN_BACK; - force_move_type = MOVE_RUN_BACK; - break; - case CMSG_FORCE_SWIM_SPEED_CHANGE_ACK: - move_type = MOVE_SWIM; - force_move_type = MOVE_SWIM; - break; - case CMSG_FORCE_SWIM_BACK_SPEED_CHANGE_ACK: - move_type = MOVE_SWIM_BACK; - force_move_type = MOVE_SWIM_BACK; - break; - case CMSG_FORCE_TURN_RATE_CHANGE_ACK: - move_type = MOVE_TURN_RATE; - force_move_type = MOVE_TURN_RATE; - break; - case CMSG_FORCE_FLIGHT_SPEED_CHANGE_ACK: - move_type = MOVE_FLIGHT; - force_move_type = MOVE_FLIGHT; - break; - case CMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE_ACK: - move_type = MOVE_FLIGHT_BACK; - force_move_type = MOVE_FLIGHT_BACK; - break; - case CMSG_FORCE_PITCH_RATE_CHANGE_ACK: - move_type = MOVE_PITCH_RATE; - force_move_type = MOVE_PITCH_RATE; - break; + case CMSG_FORCE_WALK_SPEED_CHANGE_ACK: move_type = MOVE_WALK; force_move_type = MOVE_WALK; break; + case CMSG_FORCE_RUN_SPEED_CHANGE_ACK: move_type = MOVE_RUN; force_move_type = MOVE_RUN; break; + case CMSG_FORCE_RUN_BACK_SPEED_CHANGE_ACK: move_type = MOVE_RUN_BACK; force_move_type = MOVE_RUN_BACK; break; + case CMSG_FORCE_SWIM_SPEED_CHANGE_ACK: move_type = MOVE_SWIM; force_move_type = MOVE_SWIM; break; + case CMSG_FORCE_SWIM_BACK_SPEED_CHANGE_ACK: move_type = MOVE_SWIM_BACK; force_move_type = MOVE_SWIM_BACK; break; + case CMSG_FORCE_TURN_RATE_CHANGE_ACK: move_type = MOVE_TURN_RATE; force_move_type = MOVE_TURN_RATE; break; + case CMSG_FORCE_FLIGHT_SPEED_CHANGE_ACK: move_type = MOVE_FLIGHT; force_move_type = MOVE_FLIGHT; break; + case CMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE_ACK: move_type = MOVE_FLIGHT_BACK; force_move_type = MOVE_FLIGHT_BACK; break; + case CMSG_FORCE_PITCH_RATE_CHANGE_ACK: move_type = MOVE_PITCH_RATE; force_move_type = MOVE_PITCH_RATE; break; default: LOG_ERROR("network.opcode", "WorldSession::HandleForceSpeedChangeAck: Unknown move type opcode: {}", opcode); return; @@ -728,6 +713,12 @@ void WorldSession::HandleForceSpeedChangeAck(WorldPacket& recvData) sScriptMgr->AnticheatSetUnderACKmount(_player); + SpeedOpcodePair const& speedOpcodes = SetSpeed2Opc_table[move_type]; + WorldPacket data(speedOpcodes[static_cast(SpeedOpcodeIndex::ACK_RESPONSE)], 18); + WriteMovementInfo(&data, &movementInfo); + data << newspeed; + mover->SendMessageToSet(&data, _player); + // skip all forced speed changes except last and unexpected // in run/mounted case used one ACK and it must be skipped.m_forced_speed_changes[MOVE_RUN} store both. if (_player->m_forced_speed_changes[force_move_type] > 0) @@ -974,6 +965,7 @@ void WorldSession::HandleMoveRootAck(WorldPacket& recvData) MovementInfo movementInfo; recvData >> guid.ReadAsPacked(); recvData >> counter; + movementInfo.guid = guid; ReadMovementInfo(recvData, &movementInfo); Unit* mover = _player->m_mover; @@ -996,7 +988,6 @@ void WorldSession::HandleMoveRootAck(WorldPacket& recvData) return; WorldPacket data(recvData.GetOpcode() == CMSG_FORCE_MOVE_UNROOT_ACK ? MSG_MOVE_UNROOT : MSG_MOVE_ROOT); - data << guid.WriteAsPacked(); WriteMovementInfo(&data, &movementInfo); mover->SendMessageToSet(&data, _player); } diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp index cbb576580..d14eee29c 100644 --- a/src/server/game/Server/Protocol/Opcodes.cpp +++ b/src/server/game/Server/Protocol/Opcodes.cpp @@ -1245,7 +1245,7 @@ void OpcodeTable::Initialize() /*0x45A*/ DEFINE_HANDLER(MSG_MOVE_SET_PITCH_RATE_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); /*0x45B*/ DEFINE_HANDLER(MSG_MOVE_SET_PITCH_RATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); /*0x45C*/ DEFINE_SERVER_OPCODE_HANDLER(SMSG_FORCE_PITCH_RATE_CHANGE, STATUS_NEVER); - /*0x45D*/ DEFINE_HANDLER(CMSG_FORCE_PITCH_RATE_CHANGE_ACK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + /*0x45D*/ DEFINE_HANDLER(CMSG_FORCE_PITCH_RATE_CHANGE_ACK, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleForceSpeedChangeAck ); /*0x45E*/ DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPLINE_SET_PITCH_RATE, STATUS_NEVER); /*0x45F*/ DEFINE_HANDLER(CMSG_CALENDAR_EVENT_INVITE_NOTES, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); /*0x460*/ DEFINE_SERVER_OPCODE_HANDLER(SMSG_CALENDAR_EVENT_INVITE_NOTES, STATUS_NEVER); @@ -1359,9 +1359,9 @@ void OpcodeTable::Initialize() /*0x4CC*/ DEFINE_HANDLER(CMSG_END_BATTLEFIELD_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); /*0x4CD*/ DEFINE_SERVER_OPCODE_HANDLER(SMSG_MULTIPLE_PACKETS, STATUS_NEVER); /*0x4CE*/ DEFINE_SERVER_OPCODE_HANDLER(SMSG_MOVE_GRAVITY_DISABLE, STATUS_NEVER); - /*0x4CF*/ DEFINE_HANDLER(CMSG_MOVE_GRAVITY_DISABLE_ACK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + /*0x4CF*/ DEFINE_HANDLER(CMSG_MOVE_GRAVITY_DISABLE_ACK, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleMoveFlagChangeOpcode ); /*0x4D0*/ DEFINE_SERVER_OPCODE_HANDLER(SMSG_MOVE_GRAVITY_ENABLE, STATUS_NEVER); - /*0x4D1*/ DEFINE_HANDLER(CMSG_MOVE_GRAVITY_ENABLE_ACK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + /*0x4D1*/ DEFINE_HANDLER(CMSG_MOVE_GRAVITY_ENABLE_ACK, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleMoveFlagChangeOpcode ); /*0x4D2*/ DEFINE_SERVER_OPCODE_HANDLER(MSG_MOVE_GRAVITY_CHNG, STATUS_NEVER); /*0x4D3*/ DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPLINE_MOVE_GRAVITY_DISABLE, STATUS_NEVER); /*0x4D4*/ DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPLINE_MOVE_GRAVITY_ENABLE, STATUS_NEVER); @@ -1431,7 +1431,7 @@ void OpcodeTable::Initialize() /*0x514*/ DEFINE_SERVER_OPCODE_HANDLER(SMSG_SEND_ALL_COMBAT_LOG, STATUS_NEVER); /*0x515*/ DEFINE_SERVER_OPCODE_HANDLER(SMSG_OPEN_LFG_DUNGEON_FINDER, STATUS_NEVER); /*0x516*/ DEFINE_SERVER_OPCODE_HANDLER(SMSG_MOVE_SET_COLLISION_HGT, STATUS_NEVER); - /*0x517*/ DEFINE_HANDLER(CMSG_MOVE_SET_COLLISION_HGT_ACK, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL ); + /*0x517*/ DEFINE_HANDLER(CMSG_MOVE_SET_COLLISION_HGT_ACK, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleForceSpeedChangeAck ); /*0x518*/ DEFINE_HANDLER(MSG_MOVE_SET_COLLISION_HGT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); /*0x519*/ DEFINE_HANDLER(CMSG_CLEAR_RANDOM_BG_WIN_TIME, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); /*0x51A*/ DEFINE_HANDLER(CMSG_CLEAR_HOLIDAY_BG_WIN_TIME, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL ); diff --git a/src/server/scripts/Commands/cs_modify.cpp b/src/server/scripts/Commands/cs_modify.cpp index 733f88a7a..12dd15f11 100644 --- a/src/server/scripts/Commands/cs_modify.cpp +++ b/src/server/scripts/Commands/cs_modify.cpp @@ -417,10 +417,10 @@ public: if (CheckModifySpeed(handler, target, allSpeed, 0.1f, 50.0f)) { NotifyModification(handler, target, LANG_YOU_CHANGE_ASPEED, LANG_YOURS_ASPEED_CHANGED, allSpeed); - target->SetSpeed(MOVE_WALK, allSpeed); - target->SetSpeed(MOVE_RUN, allSpeed); - target->SetSpeed(MOVE_SWIM, allSpeed); - target->SetSpeed(MOVE_FLIGHT, allSpeed); + target->SetSpeed(MOVE_WALK, allSpeed, true); + target->SetSpeed(MOVE_RUN, allSpeed, true); + target->SetSpeed(MOVE_SWIM, allSpeed, true); + target->SetSpeed(MOVE_FLIGHT, allSpeed, true); return true; } diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp index 3aef1085b..a1f9d3e6d 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp @@ -2566,7 +2566,7 @@ public: me->SetCanFly(false); me->SetDisableGravity(false); me->GetMotionMaster()->MovePoint(POINT_DROP_PLAYER, _destPoint, FORCED_MOVEMENT_NONE, 0.f, false); - me->SetDisableGravity(true, true); + me->SetDisableGravity(true); me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE); break; case EVENT_MOVE_TO_SIPHON_POS: @@ -2732,7 +2732,7 @@ class spell_the_lich_king_valkyr_target_search : public SpellScript if (Unit* target = GetHitUnit()) { GetCaster()->GetMotionMaster()->MoveCharge(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ() + 4.0f, 42.0f, EVENT_CHARGE); - GetCaster()->SetDisableGravity(true, true); + GetCaster()->SetDisableGravity(true); } } diff --git a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp index 6ca80d64f..8b6c5f25d 100644 --- a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp +++ b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp @@ -528,9 +528,7 @@ public: init.Launch(); pPlayer->SetUnitMovementFlags(MOVEMENTFLAG_NONE); - pPlayer->SetDisableGravity(true, true); - - sScriptMgr->AnticheatSetCanFlybyServer(pPlayer, true); + pPlayer->SetDisableGravity(true); WorldPacket data(SMSG_SPLINE_MOVE_UNROOT, 8); data << pPlayer->GetPackGUID(); @@ -941,10 +939,7 @@ public: if (!bUpdatedFlying && timer) { bUpdatedFlying = true; - plr->SetDisableGravity(true, true); - - sScriptMgr->AnticheatSetCanFlybyServer(plr, true); - sScriptMgr->AnticheatSetUnderACKmount(plr); + plr->SetDisableGravity(true); } plr->SendMonsterMove(me->GetPositionX() + dist * cos(arcangle), me->GetPositionY() + dist * std::sin(arcangle), me->GetPositionZ(), VORTEX_DEFAULT_DIFF * 2, SPLINEFLAG_FLYING); diff --git a/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp b/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp index 871d014d9..028025023 100644 --- a/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp +++ b/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp @@ -347,7 +347,7 @@ struct boss_kaelthas : public BossAI } else if (point == POINT_AIR) { - me->SetDisableGravity(true, false, false); // updating AnimationTier will break drowning animation later + me->SetDisableGravity(true); // updating AnimationTier will break drowning animation later } else if (point == POINT_START_LAST_PHASE) {