mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-22 13:16:23 +00:00
fix(Core/Movement): Add force speed ack to async movement and resolve stutter (#23371)
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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); }
|
||||
|
||||
@@ -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<Player*>(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<size_t>(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<size_t>(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();
|
||||
|
||||
@@ -624,6 +624,28 @@ typedef std::unordered_map<uint32, uint32> PacketCooldowns;
|
||||
|
||||
struct SpellProcEventEntry; // used only privately
|
||||
|
||||
enum class SpeedOpcodeIndex : uint32
|
||||
{
|
||||
PC,
|
||||
NPC,
|
||||
ACK_RESPONSE,
|
||||
MAX
|
||||
};
|
||||
|
||||
typedef const Opcodes SpeedOpcodePair[static_cast<size_t>(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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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<size_t>(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);
|
||||
}
|
||||
|
||||
@@ -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 );
|
||||
|
||||
Reference in New Issue
Block a user