mirror of
https://github.com/liyunfan1223/azerothcore-wotlk.git
synced 2026-08-04 22:07:52 +00:00
fix(Core/Entities): Knock back players if they are not under client control. (#26540)
Co-authored-by: Claude <claude@users.noreply.github.com> Co-authored-by: sogladev <sogladev@gmail.com>
This commit is contained in:
@@ -15417,10 +15417,12 @@ void Unit::KnockbackFrom(float x, float y, float speedXY, float speedZ)
|
||||
}
|
||||
}
|
||||
|
||||
if (!player)
|
||||
{
|
||||
// While feared/confused the client has no control over the unit,
|
||||
// so a SMSG_MOVE_KNOCK_BACK would be ignored or immediately overridden by the server
|
||||
// side fleeing/confused splines. Perform the knockback server side instead; the
|
||||
// fleeing/confused movement generator resumes once this spline is finalized
|
||||
if (!player || !IsClientControlled())
|
||||
GetMotionMaster()->MoveKnockbackFrom(x, y, speedXY, speedZ);
|
||||
}
|
||||
else
|
||||
{
|
||||
float vcos, vsin;
|
||||
|
||||
@@ -840,14 +840,20 @@ void WorldSession::HandleMoveKnockBackAck(WorldPacket& recvData)
|
||||
movementInfo.guid = guid;
|
||||
ReadMovementInfo(recvData, &movementInfo);
|
||||
|
||||
mover->m_movementInfo = movementInfo;
|
||||
// Relocate the mover to the acknowledged position. Otherwise the server (and the
|
||||
// MSG_MOVE_KNOCK_BACK broadcast below) keeps using the pre-knockback position until
|
||||
// the next regular movement packet arrives, desyncing the unit for nearby clients
|
||||
if (!ProcessMovementInfo(movementInfo, mover, mover->ToPlayer(), recvData))
|
||||
{
|
||||
recvData.rfinish(); // prevent warnings spam
|
||||
return;
|
||||
}
|
||||
|
||||
if (mover->IsPlayer() && static_cast<Player*>(mover)->IsFreeFlying())
|
||||
mover->SetCanFly(true);
|
||||
|
||||
WorldPacket data(MSG_MOVE_KNOCK_BACK, 66);
|
||||
data << guid.WriteAsPacked();
|
||||
_player->m_mover->BuildMovementPacket(&data);
|
||||
WriteMovementInfo(&data, &movementInfo);
|
||||
_player->SetCanTeleport(true);
|
||||
// knockback specific info
|
||||
data << movementInfo.jump.sinAngle;
|
||||
|
||||
@@ -620,7 +620,7 @@ void MotionMaster::MoveTakeoff(uint32 id, float x, float y, float z, float speed
|
||||
void MotionMaster::MoveKnockbackFrom(float srcX, float srcY, float speedXY, float speedZ)
|
||||
{
|
||||
//this function may make players fall below map
|
||||
if (_owner->IsPlayer())
|
||||
if (_owner->IsPlayer() && _owner->IsClientControlled())
|
||||
return;
|
||||
|
||||
if (speedXY <= 0.1f)
|
||||
@@ -640,6 +640,15 @@ void MotionMaster::MoveKnockbackFrom(float srcX, float srcY, float speedXY, floa
|
||||
init.SetOrientationFixed(true);
|
||||
init.SetVelocity(speedXY);
|
||||
|
||||
// Do not mutate an active fleeing/confused movement generator,
|
||||
// doing so breaks the movement upon landing from the knockback
|
||||
MovementGeneratorType slotType = GetMotionSlotType(MOTION_SLOT_CONTROLLED);
|
||||
if (slotType == FLEEING_MOTION_TYPE || slotType == CONFUSED_MOTION_TYPE)
|
||||
{
|
||||
init.Launch();
|
||||
return;
|
||||
}
|
||||
|
||||
Mutate(new EffectMovementGenerator(init, 0), MOTION_SLOT_CONTROLLED);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user