mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-26 15:16:24 +00:00
fix(Core/Movement): rework root protocol with ack in mind (#23147)
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1164,8 +1164,11 @@ void WorldSession::HandlePlayerLoginToCharInWorld(Player* pCurrChar)
|
||||
SendPacket(&data);
|
||||
|
||||
// Xinef: fix possible problem with flag UNIT_FLAG_STUNNED added during logout
|
||||
if (!pCurrChar->HasUnitState(UNIT_STATE_STUNNED))
|
||||
if (pCurrChar->HasUnitState(UNIT_STATE_LOGOUT_TIMER))
|
||||
{
|
||||
pCurrChar->SetRooted(false, true, true);
|
||||
pCurrChar->RemoveUnitFlag(UNIT_FLAG_STUNNED);
|
||||
}
|
||||
|
||||
pCurrChar->SendInitialPacketsBeforeAddToMap();
|
||||
|
||||
|
||||
@@ -468,7 +468,7 @@ void WorldSession::HandleLogoutRequestOpcode(WorldPackets::Character::LogoutRequ
|
||||
GetPlayer()->SetStandState(UNIT_STAND_STATE_SIT);
|
||||
}
|
||||
|
||||
GetPlayer()->SetRooted(true);
|
||||
GetPlayer()->SetRooted(true, true, true);
|
||||
GetPlayer()->SetUnitFlag(UNIT_FLAG_STUNNED);
|
||||
}
|
||||
|
||||
@@ -492,7 +492,7 @@ void WorldSession::HandleLogoutCancelOpcode(WorldPackets::Character::LogoutCance
|
||||
// not remove flags if can't free move - its not set in Logout request code.
|
||||
if (GetPlayer()->CanFreeMove())
|
||||
{
|
||||
GetPlayer()->SetRooted(false);
|
||||
GetPlayer()->SetRooted(false, true, true);
|
||||
|
||||
GetPlayer()->SetStandState(UNIT_STAND_STATE_STAND);
|
||||
GetPlayer()->RemoveUnitFlag(UNIT_FLAG_STUNNED);
|
||||
|
||||
@@ -967,79 +967,36 @@ void WorldSession::ComputeNewClockDelta()
|
||||
|
||||
void WorldSession::HandleMoveRootAck(WorldPacket& recvData)
|
||||
{
|
||||
LOG_DEBUG("network", "WORLD: {}", GetOpcodeNameForLogging((Opcodes)recvData.GetOpcode()));
|
||||
|
||||
ObjectGuid guid;
|
||||
recvData >> guid.ReadAsPacked();
|
||||
|
||||
Unit* mover = _player->m_mover;
|
||||
if (!mover || guid != mover->GetGUID())
|
||||
{
|
||||
recvData.rfinish(); // prevent warnings spam
|
||||
return;
|
||||
}
|
||||
|
||||
uint32 movementCounter;
|
||||
recvData >> movementCounter;
|
||||
|
||||
uint32 counter;
|
||||
MovementInfo movementInfo;
|
||||
movementInfo.guid = guid;
|
||||
recvData >> guid.ReadAsPacked();
|
||||
recvData >> counter;
|
||||
ReadMovementInfo(recvData, &movementInfo);
|
||||
|
||||
/* process position-change */
|
||||
int64 movementTime = (int64) movementInfo.time + _timeSyncClockDelta;
|
||||
if (_timeSyncClockDelta == 0 || movementTime < 0 || movementTime > 0xFFFFFFFF)
|
||||
{
|
||||
LOG_INFO("misc", "The computed movement time using clockDelta is erronous. Using fallback instead");
|
||||
movementInfo.time = getMSTime();
|
||||
}
|
||||
else
|
||||
{
|
||||
movementInfo.time = (uint32)movementTime;
|
||||
}
|
||||
|
||||
movementInfo.guid = mover->GetGUID();
|
||||
mover->m_movementInfo = movementInfo;
|
||||
mover->UpdatePosition(movementInfo.pos);
|
||||
|
||||
}
|
||||
|
||||
void WorldSession::HandleMoveUnRootAck(WorldPacket& recvData)
|
||||
{
|
||||
ObjectGuid guid;
|
||||
recvData >> guid.ReadAsPacked();
|
||||
|
||||
Unit* mover = _player->m_mover;
|
||||
if (!mover || guid != mover->GetGUID())
|
||||
{
|
||||
recvData.rfinish(); // prevent warnings spam
|
||||
|
||||
if (mover->GetGUID() != guid)
|
||||
return;
|
||||
}
|
||||
|
||||
uint32 movementCounter;
|
||||
recvData >> movementCounter;
|
||||
|
||||
MovementInfo movementInfo;
|
||||
movementInfo.guid = guid;
|
||||
ReadMovementInfo(recvData, &movementInfo);
|
||||
|
||||
/* process position-change */
|
||||
int64 movementTime = (int64) movementInfo.time + _timeSyncClockDelta;
|
||||
if (_timeSyncClockDelta == 0 || movementTime < 0 || movementTime > 0xFFFFFFFF)
|
||||
if (recvData.GetOpcode() == CMSG_FORCE_MOVE_UNROOT_ACK) // unroot case
|
||||
{
|
||||
LOG_INFO("misc", "The computed movement time using clockDelta is erronous. Using fallback instead");
|
||||
movementInfo.time = getMSTime();
|
||||
if (!mover->m_movementInfo.HasMovementFlag(MOVEMENTFLAG_ROOT))
|
||||
return;
|
||||
}
|
||||
else
|
||||
else // root case
|
||||
{
|
||||
movementInfo.time = (uint32)movementTime;
|
||||
if (mover->m_movementInfo.HasMovementFlag(MOVEMENTFLAG_ROOT))
|
||||
return;
|
||||
}
|
||||
|
||||
if (G3D::fuzzyEq(movementInfo.fallTime, 0.f))
|
||||
{
|
||||
movementInfo.RemoveMovementFlag(MOVEMENTFLAG_FALLING);
|
||||
}
|
||||
|
||||
movementInfo.guid = mover->GetGUID();
|
||||
mover->m_movementInfo = movementInfo;
|
||||
mover->UpdatePosition(movementInfo.pos);
|
||||
if (!ProcessMovementInfo(movementInfo, mover, _player, 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);
|
||||
}
|
||||
|
||||
@@ -363,7 +363,7 @@ void OpcodeTable::Initialize()
|
||||
/*0x0E8*/ DEFINE_SERVER_OPCODE_HANDLER(SMSG_FORCE_MOVE_ROOT, STATUS_NEVER);
|
||||
/*0x0E9*/ DEFINE_HANDLER(CMSG_FORCE_MOVE_ROOT_ACK, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMoveRootAck );
|
||||
/*0x0EA*/ DEFINE_SERVER_OPCODE_HANDLER(SMSG_FORCE_MOVE_UNROOT, STATUS_NEVER);
|
||||
/*0x0EB*/ DEFINE_HANDLER(CMSG_FORCE_MOVE_UNROOT_ACK, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMoveUnRootAck );
|
||||
/*0x0EB*/ DEFINE_HANDLER(CMSG_FORCE_MOVE_UNROOT_ACK, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMoveRootAck );
|
||||
/*0x0EC*/ DEFINE_HANDLER(MSG_MOVE_ROOT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
|
||||
/*0x0ED*/ DEFINE_HANDLER(MSG_MOVE_UNROOT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
|
||||
/*0x0EE*/ DEFINE_HANDLER(MSG_MOVE_HEARTBEAT, STATUS_LOGGEDIN, PROCESS_THREADSAFE, &WorldSession::HandleMovementOpcodes );
|
||||
|
||||
@@ -628,7 +628,6 @@ public: // opcodes handlers
|
||||
void HandlePlayedTime(WorldPackets::Character::PlayedTimeClient& packet);
|
||||
|
||||
// new
|
||||
void HandleMoveUnRootAck(WorldPacket& recvPacket);
|
||||
void HandleMoveRootAck(WorldPacket& recvPacket);
|
||||
|
||||
// new inspect
|
||||
|
||||
Reference in New Issue
Block a user