diff --git a/zone/client.cpp b/zone/client.cpp index ac696247a..3f0e33d2f 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -9116,3 +9116,16 @@ bool Client::GotoPlayer(std::string player_name) return false; } + +glm::vec4 &Client::GetLastPositionBeforeBulkUpdate() +{ + return last_position_before_bulk_update; +} + +/** + * @param in_last_position_before_bulk_update + */ +void Client::SetLastPositionBeforeBulkUpdate(glm::vec4 in_last_position_before_bulk_update) +{ + Client::last_position_before_bulk_update = in_last_position_before_bulk_update; +} \ No newline at end of file diff --git a/zone/client.h b/zone/client.h index 7b37c2b47..2ea27b108 100644 --- a/zone/client.h +++ b/zone/client.h @@ -1309,6 +1309,9 @@ public: uint32 trapid; //ID of trap player has triggered. This is cleared when the player leaves the trap's radius, or it despawns. + void SetLastPositionBeforeBulkUpdate(glm::vec4 in_last_position_before_bulk_update); + glm::vec4 &GetLastPositionBeforeBulkUpdate(); + protected: friend class Mob; void CalcItemBonuses(StatBonuses* newbon); @@ -1540,6 +1543,7 @@ private: Timer position_update_timer; /* Timer used when client hasn't updated within a 10 second window */ glm::vec3 m_Proximity; + glm::vec4 last_position_before_bulk_update; void BulkSendInventoryItems(); diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 2dc5cdbf9..688a448eb 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -806,6 +806,8 @@ void Client::CompleteConnect() parse->EventPlayer(EVENT_ENTER_ZONE, this, "", 0); + SetLastPositionBeforeBulkUpdate(GetPosition()); + /* This sub event is for if a player logs in for the first time since entering world. */ if (firstlogon == 1) { parse->EventPlayer(EVENT_CONNECT, this, "", 0); @@ -4487,10 +4489,21 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) { /** * On a normal basis we limit mob movement updates based on distance - * This ensures we send a periodic full zone update to a client that has started - * moving after 5 or so minutes + * This ensures we send a periodic full zone update to a client that has started moving after 5 or so minutes + * + * For very large zones we will also force a full update based on distance + * + * We ignore a small distance around us so that we don't interrupt already pathing deltas as those npcs will appear + * to full stop when they are actually still pathing */ - if (is_client_moving && client_zone_wide_full_position_update_timer.Check()) { + + float distance_moved = DistanceNoZ(GetLastPositionBeforeBulkUpdate(), GetPosition()); + bool moved_far_enough_before_bulk_update = distance_moved >= 1200; + bool is_ready_to_update = ( + client_zone_wide_full_position_update_timer.Check() || moved_far_enough_before_bulk_update + ); + + if (is_client_moving && is_ready_to_update) { Log(Logs::Detail, Logs::Normal, "[%s] Client Zone Wide Position Update NPCs", GetCleanName()); auto &mob_movement_manager = MobMovementManager::Get(); @@ -4509,6 +4522,8 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) { mob_movement_manager.SendCommandToClients(entity, 0.0, 0.0, 0.0, 0.0, 0, ClientRangeAny, this); } + + SetLastPositionBeforeBulkUpdate(GetPosition()); } float new_heading = EQ12toFloat(ppu->heading);