fix(Core/Unit): Re-sync movement speed to target's client after possess/charm ends (#26304)
This commit is contained in:
@@ -11329,22 +11329,7 @@ void Unit::SetSpeed(UnitMoveType mtype, float rate, bool forced)
|
|||||||
|
|
||||||
if (forced && IsClientControlled())
|
if (forced && IsClientControlled())
|
||||||
{
|
{
|
||||||
Player* player = const_cast<Player*>(GetClientControlling());
|
SendSpeedToController(mtype, 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)
|
else if (forced)
|
||||||
{
|
{
|
||||||
@@ -11377,6 +11362,24 @@ void Unit::SetSpeed(UnitMoveType mtype, float rate, bool forced)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Unit::SendSpeedToController(UnitMoveType mtype, Player* target) const
|
||||||
|
{
|
||||||
|
SpeedOpcodePair const& speedOpcodes = SetSpeed2Opc_table[mtype];
|
||||||
|
uint32 const counter = target->GetSession()->GetOrderCounter();
|
||||||
|
|
||||||
|
++target->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);
|
||||||
|
|
||||||
|
data << GetSpeed(mtype);
|
||||||
|
target->GetSession()->SendPacket(&data);
|
||||||
|
target->GetSession()->IncrementOrderCounter();
|
||||||
|
}
|
||||||
|
|
||||||
void Unit::setDeathState(DeathState s, bool despawn)
|
void Unit::setDeathState(DeathState s, bool despawn)
|
||||||
{
|
{
|
||||||
// death state needs to be updated before RemoveAllAurasOnDeath() calls HandleChannelDeathItem(..) so that
|
// death state needs to be updated before RemoveAllAurasOnDeath() calls HandleChannelDeathItem(..) so that
|
||||||
@@ -14698,6 +14701,10 @@ bool Unit::SetCharmedBy(Unit* charmer, CharmType type, AuraApplication const* au
|
|||||||
_oldFactionId = GetFaction();
|
_oldFactionId = GetFaction();
|
||||||
SetFaction(charmer->GetFaction());
|
SetFaction(charmer->GetFaction());
|
||||||
|
|
||||||
|
// snapshot current speed rates so we can detect speed changes
|
||||||
|
for (uint8 i = MOVE_WALK; i < MAX_MOVE_TYPE; ++i)
|
||||||
|
_charmStartSpeedRate[i] = m_speed_rate[i];
|
||||||
|
|
||||||
// Set charmed
|
// Set charmed
|
||||||
charmer->SetCharm(this, true);
|
charmer->SetCharm(this, true);
|
||||||
|
|
||||||
@@ -14849,9 +14856,6 @@ void Unit::RemoveCharmedBy(Unit* charmer)
|
|||||||
CastStop();
|
CastStop();
|
||||||
AttackStop();
|
AttackStop();
|
||||||
|
|
||||||
// xinef: update speed after charming
|
|
||||||
UpdateSpeed(MOVE_RUN, false);
|
|
||||||
|
|
||||||
// xinef: do not break any controlled motion slot
|
// xinef: do not break any controlled motion slot
|
||||||
if (GetMotionMaster()->GetMotionSlotType(MOTION_SLOT_CONTROLLED) == NULL_MOTION_TYPE)
|
if (GetMotionMaster()->GetMotionSlotType(MOTION_SLOT_CONTROLLED) == NULL_MOTION_TYPE)
|
||||||
{
|
{
|
||||||
@@ -14954,7 +14958,15 @@ void Unit::RemoveCharmedBy(Unit* charmer)
|
|||||||
RemoveUnitMovementFlag(MOVEMENTFLAG_FLYING);
|
RemoveUnitMovementFlag(MOVEMENTFLAG_FLYING);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
ToPlayer()->SetClientControl(this, true); // verified
|
{
|
||||||
|
Player* targetPlayer = ToPlayer();
|
||||||
|
targetPlayer->SetClientControl(this, true); // verified
|
||||||
|
|
||||||
|
// Re-sync only the speed types that changed during the charm.
|
||||||
|
for (uint8 i = MOVE_WALK; i < MAX_MOVE_TYPE; ++i)
|
||||||
|
if (m_speed_rate[i] != _charmStartSpeedRate[i])
|
||||||
|
SendSpeedToController(UnitMoveType(i), targetPlayer);
|
||||||
|
}
|
||||||
|
|
||||||
// a guardian should always have charminfo
|
// a guardian should always have charminfo
|
||||||
if (playerCharmer && this != charmer->GetFirstControlled())
|
if (playerCharmer && this != charmer->GetFirstControlled())
|
||||||
|
|||||||
@@ -1744,6 +1744,7 @@ public:
|
|||||||
[[nodiscard]] float GetSpeedRate(UnitMoveType mtype) const { return m_speed_rate[mtype]; }
|
[[nodiscard]] float GetSpeedRate(UnitMoveType mtype) const { return m_speed_rate[mtype]; }
|
||||||
void SetSpeed(UnitMoveType mtype, float rate, bool forced = false);
|
void SetSpeed(UnitMoveType mtype, float rate, bool forced = false);
|
||||||
void SetSpeedRate(UnitMoveType mtype, float rate) { m_speed_rate[mtype] = rate; }
|
void SetSpeedRate(UnitMoveType mtype, float rate) { m_speed_rate[mtype] = rate; }
|
||||||
|
void SendSpeedToController(UnitMoveType mtype, Player* target) const;
|
||||||
|
|
||||||
void propagateSpeedChange() { GetMotionMaster()->propagateSpeedChange(); }
|
void propagateSpeedChange() { GetMotionMaster()->propagateSpeedChange(); }
|
||||||
|
|
||||||
@@ -2186,6 +2187,9 @@ protected:
|
|||||||
|
|
||||||
float m_speed_rate[MAX_MOVE_TYPE];
|
float m_speed_rate[MAX_MOVE_TYPE];
|
||||||
|
|
||||||
|
// snapshot of speed rates taken when SetCharmedBy() is called
|
||||||
|
float _charmStartSpeedRate[MAX_MOVE_TYPE]{};
|
||||||
|
|
||||||
CharmInfo* m_charmInfo;
|
CharmInfo* m_charmInfo;
|
||||||
SharedVisionList m_sharedVision;
|
SharedVisionList m_sharedVision;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user