fix(Core/Movement): rework root protocol with ack in mind (#23147)

This commit is contained in:
killerwife
2025-10-11 18:49:43 +02:00
committed by GitHub
parent bc89aa561c
commit 31b11d0d11
10 changed files with 86 additions and 143 deletions

View File

@@ -4431,12 +4431,6 @@ void Player::SetMovement(PlayerMovementType pType)
const PackedGuid& guid = GetPackGUID();
switch (pType)
{
case MOVE_ROOT:
data.Initialize(SMSG_FORCE_MOVE_ROOT, guid.size() + 4);
break;
case MOVE_UNROOT:
data.Initialize(SMSG_FORCE_MOVE_UNROOT, guid.size() + 4);
break;
case MOVE_WATER_WALK:
data.Initialize(SMSG_MOVE_WATER_WALK, guid.size() + 4);
break;
@@ -4490,10 +4484,10 @@ void Player::BuildPlayerRepop()
SetHealth(1); // convert player body to ghost
SetMovement(MOVE_WATER_WALK);
SetWaterWalking(true);
if (!GetSession()->isLogingOut())
{
SetMovement(MOVE_UNROOT);
}
if (!IsImmobilizedState())
SendMoveRoot(false);
RemoveUnitFlag(UNIT_FLAG_SKINNABLE); // BG - remove insignia related
int32 corpseReclaimDelay = CalculateCorpseReclaimDelay();
if (corpseReclaimDelay >= 0)
@@ -4530,7 +4524,7 @@ void Player::ResurrectPlayer(float restore_percent, bool applySickness)
setDeathState(DeathState::Alive);
SetMovement(MOVE_LAND_WALK);
SetMovement(MOVE_UNROOT);
SendMoveRoot(false);
SetWaterWalking(false);
m_deathTimer = 0;
@@ -4594,7 +4588,7 @@ void Player::KillPlayer()
if (IsFlying() && !GetTransport())
GetMotionMaster()->MoveFall();
SetMovement(MOVE_ROOT);
SendMoveRoot(true);
StopMirrorTimers(); //disable timers(bars)
@@ -11703,9 +11697,6 @@ void Player::SendInitialPacketsAfterAddToMap()
GetZoneAndAreaId(newzone, newarea);
UpdateZone(newzone, newarea); // also call SendInitWorldStates();
if (HasStunAura())
SetMovement(MOVE_ROOT);
WorldPacket setCompoundState(SMSG_MULTIPLE_MOVES, 100);
setCompoundState << uint32(0); // size placeholder

View File

@@ -448,8 +448,6 @@ typedef std::list<Item*> ItemDurationList;
enum PlayerMovementType
{
MOVE_ROOT = 1,
MOVE_UNROOT = 2,
MOVE_WATER_WALK = 3,
MOVE_LAND_WALK = 4
};

View File

@@ -18293,73 +18293,65 @@ void Unit::SetStunned(bool apply)
}
}
void Unit::SetRooted(bool apply, bool isStun)
void Unit::SetRooted(bool apply, bool stun, bool logout)
{
const uint32 state = (stun ? (logout ? UNIT_STATE_LOGOUT_TIMER : UNIT_STATE_STUNNED) : UNIT_STATE_ROOT);
if (apply)
{
// MOVEMENTFLAG_ROOT cannot be used in conjunction with MOVEMENTFLAG_MASK_MOVING (tested 3.3.5a)
// this will freeze clients. That's why we remove MOVEMENTFLAG_MASK_MOVING before
// setting MOVEMENTFLAG_ROOT
RemoveUnitMovementFlag(MOVEMENTFLAG_MASK_MOVING);
AddUnitState(state);
if (IsFalling())
{
AddUnitMovementFlag(MOVEMENTFLAG_PENDING_ROOT);
}
else
{
AddUnitMovementFlag(MOVEMENTFLAG_ROOT);
}
// Creature specific
if (!IsPlayer())
{
if (isStun && movespline->Finalized())
{
StopMovingOnCurrentPos();
}
else
{
StopMoving();
}
}
if (m_movedByPlayer)
{
WorldPacket data(SMSG_FORCE_MOVE_ROOT, GetPackGUID().size() + 4);
data << GetPackGUID();
data << m_movedByPlayer->ToPlayer()->GetSession()->GetOrderCounter(); // movement counter
m_movedByPlayer->ToPlayer()->SendDirectMessage(&data);
m_movedByPlayer->ToPlayer()->GetSession()->IncrementOrderCounter();
}
else
{
WorldPacket data(SMSG_SPLINE_MOVE_ROOT, GetPackGUID().size());
data << GetPackGUID();
SendMessageToSet(&data, true);
}
SendMoveRoot(true);
}
else
{
RemoveUnitMovementFlag(MOVEMENTFLAG_ROOT | MOVEMENTFLAG_PENDING_ROOT);
ClearUnitState(state);
if (!HasUnitState(UNIT_STATE_STUNNED)) // prevent moving if it also has stun effect
// Prevent giving ability to move if more immobilizers are active
if (!IsImmobilizedState())
SendMoveRoot(false);
}
}
void Unit::SendMoveRoot(bool apply)
{
const Player* client = GetClientControlling();
// Apply flags in-place when unit currently is not controlled by a player
if (!client)
{
if (apply)
{
if (m_movedByPlayer)
{
WorldPacket data(SMSG_FORCE_MOVE_UNROOT, GetPackGUID().size() + 4);
data << GetPackGUID();
data << m_movedByPlayer->ToPlayer()->GetSession()->GetOrderCounter(); // movement counter
m_movedByPlayer->ToPlayer()->SendDirectMessage(&data);
m_movedByPlayer->ToPlayer()->GetSession()->IncrementOrderCounter();
}
else
{
WorldPacket data(SMSG_SPLINE_MOVE_UNROOT, GetPackGUID().size());
data << GetPackGUID();
SendMessageToSet(&data, true);
}
m_movementInfo.RemoveMovementFlag(MOVEMENTFLAG_MASK_MOVING_FLY);
m_movementInfo.AddMovementFlag(MOVEMENTFLAG_ROOT);
if (!client)
StopMoving();
}
else
m_movementInfo.RemoveMovementFlag(MOVEMENTFLAG_ROOT);
}
if (!IsInWorld())
return;
const PackedGuid& guid = GetPackGUID();
// Wrath+ spline root: when unit is currently not controlled by a player
if (!client)
{
WorldPacket data(apply ? SMSG_SPLINE_MOVE_ROOT : SMSG_SPLINE_MOVE_UNROOT, guid.size());
data << guid;
SendMessageToSet(&data, true);
}
// Wrath+ force root: when unit is controlled by a player
else
{
auto const counter = client->GetSession()->GetOrderCounter();
WorldPacket data(apply ? SMSG_FORCE_MOVE_ROOT : SMSG_FORCE_MOVE_UNROOT, guid.size() + 4);
data << guid;
data << counter;
client->GetSession()->SendPacket(&data);
client->GetSession()->IncrementOrderCounter();
}
}

View File

@@ -2066,7 +2066,8 @@ protected:
void SetFeared(bool apply, Unit* fearedBy = nullptr, bool isFear = false);
void SetConfused(bool apply);
void SetStunned(bool apply);
void SetRooted(bool apply, bool isStun = false);
void SetRooted(bool apply, bool stun = false, bool logout = false);
void SendMoveRoot(bool state);
//----------- Protected variables ----------//
UnitAI* i_AI;

View File

@@ -197,7 +197,9 @@ enum UnitState
UNIT_STATE_IGNORE_PATHFINDING = 0x10000000, // do not use pathfinding in any MovementGenerator
UNIT_STATE_NO_ENVIRONMENT_UPD = 0x20000000,
UNIT_STATE_NO_COMBAT_MOVEMENT = 0x40000000, // serverside only - should not be changed outside the core and should be placed at the end
// serverside region
UNIT_STATE_NO_COMBAT_MOVEMENT = 0x40000000, // should not be changed outside the core and should be placed at the end
UNIT_STATE_LOGOUT_TIMER = 0x80000000, // Unit is logging out
UNIT_STATE_ALL_STATE_SUPPORTED = UNIT_STATE_DIED | UNIT_STATE_MELEE_ATTACKING | UNIT_STATE_STUNNED | UNIT_STATE_ROAMING | UNIT_STATE_CHASE
| UNIT_STATE_FLEEING | UNIT_STATE_IN_FLIGHT | UNIT_STATE_FOLLOW | UNIT_STATE_ROOT | UNIT_STATE_CONFUSED