mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-02-19 10:14:35 +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);
|
||||
|
||||
Reference in New Issue
Block a user