From 2224b83ae08d31bdb2be3aea083c05b4362d81ca Mon Sep 17 00:00:00 2001 From: KimLS Date: Mon, 17 Sep 2018 14:32:36 -0700 Subject: [PATCH] Movement manager add --- world/client.cpp | 2 + zone/CMakeLists.txt | 2 + zone/client.cpp | 7 +- zone/client.h | 2 - zone/client_packet.cpp | 8 -- zone/client_process.cpp | 43 +----- zone/mob.cpp | 71 ++-------- zone/mob.h | 11 +- zone/mob_movement_manager.cpp | 259 ++++++++++++++++++++++++++++++++++ zone/mob_movement_manager.h | 38 +++++ zone/perl_mob.cpp | 2 +- zone/spell_effects.cpp | 2 +- zone/waypoints.cpp | 14 +- zone/zone.cpp | 5 + zone/zone.h | 3 + 15 files changed, 342 insertions(+), 127 deletions(-) create mode 100644 zone/mob_movement_manager.cpp create mode 100644 zone/mob_movement_manager.h diff --git a/world/client.cpp b/world/client.cpp index f8b4fe3f4..0b04373a1 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -92,6 +92,8 @@ Client::Client(EQStreamInterface* ieqs) connect(1000), eqs(ieqs) { + //mMovementManager->AddClient(this); + // Live does not send datarate as of 3/11/2005 //eqs->SetDataRate(7); ip = eqs->GetRemoteIP(); diff --git a/zone/CMakeLists.txt b/zone/CMakeLists.txt index 0414a8d2b..616f76c5f 100644 --- a/zone/CMakeLists.txt +++ b/zone/CMakeLists.txt @@ -82,6 +82,7 @@ SET(zone_sources merc.cpp mob.cpp mob_ai.cpp + mob_movement_manager.cpp mod_functions.cpp net.cpp npc.cpp @@ -204,6 +205,7 @@ SET(zone_headers message.h merc.h mob.h + mob_movement_manager.h net.h npc.h npc_ai.h diff --git a/zone/client.cpp b/zone/client.cpp index 129293970..8477c6fc6 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -53,6 +53,7 @@ extern volatile bool RunLoops; #include "guild_mgr.h" #include "quest_parser_collection.h" #include "queryserv.h" +#include "mob_movement_manager.h" extern QueryServ* QServ; extern EntityList entity_list; @@ -156,7 +157,6 @@ Client::Client(EQStreamInterface* ieqs) m_AutoAttackTargetLocation(0.0f, 0.0f, 0.0f), last_region_type(RegionTypeUnsupported), m_dirtyautohaters(false), - npc_close_scan_timer(6000), hp_self_update_throttle_timer(300), hp_other_update_throttle_timer(500), position_update_timer(10000), @@ -166,6 +166,7 @@ Client::Client(EQStreamInterface* ieqs) for (int client_filter = 0; client_filter < _FilterCount; client_filter++) ClientFilters[client_filter] = FilterShow; + mMovementManager->AddClient(this); character_id = 0; conn_state = NoPacketsReceived; client_data_loaded = false; @@ -339,6 +340,8 @@ Client::Client(EQStreamInterface* ieqs) } Client::~Client() { + mMovementManager->RemoveClient(this); + #ifdef BOTS Bot::ProcessBotOwnerRefDelete(this); #endif @@ -6464,7 +6467,7 @@ void Client::LocateCorpse() SetHeading(CalculateHeadingToTarget(ClosestCorpse->GetX(), ClosestCorpse->GetY())); SetTarget(ClosestCorpse); SendTargetCommand(ClosestCorpse->GetID()); - SendPositionUpdate(2); + SendPositionUpdate(true); } else if(!GetTarget()) Message_StringID(clientMessageError, SENSE_CORPSE_NONE); diff --git a/zone/client.h b/zone/client.h index 393ede129..b0c65e6e2 100644 --- a/zone/client.h +++ b/zone/client.h @@ -1534,13 +1534,11 @@ private: Timer afk_toggle_timer; Timer helm_toggle_timer; Timer aggro_meter_timer; - Timer npc_close_scan_timer; Timer hp_self_update_throttle_timer; /* This is to prevent excessive packet sending under trains/fast combat */ Timer hp_other_update_throttle_timer; /* This is to keep clients from DOSing the server with macros that change client targets constantly */ Timer position_update_timer; /* Timer used when client hasn't updated within a 10 second window */ glm::vec3 m_Proximity; - glm::vec4 last_major_update_position; void BulkSendInventoryItems(); diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 8fee2460a..3b954419a 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -4622,10 +4622,6 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) { Log(Logs::Detail, Logs::Normal, "ClientUpdate: Client is moving - scan timer is: %u", client_scan_npc_aggro_timer.GetDuration()); if (client_scan_npc_aggro_timer.GetDuration() > 1000) { - - npc_close_scan_timer.Disable(); - npc_close_scan_timer.Start(500); - client_scan_npc_aggro_timer.Disable(); client_scan_npc_aggro_timer.Start(500); @@ -4634,10 +4630,6 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) { Log(Logs::Detail, Logs::Normal, "ClientUpdate: Client is NOT moving - scan timer is: %u", client_scan_npc_aggro_timer.GetDuration()); if (client_scan_npc_aggro_timer.GetDuration() < 1000) { - - npc_close_scan_timer.Disable(); - npc_close_scan_timer.Start(6000); - client_scan_npc_aggro_timer.Disable(); client_scan_npc_aggro_timer.Start(3000); } diff --git a/zone/client_process.cpp b/zone/client_process.cpp index 3894826d6..988b558ec 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -242,47 +242,6 @@ bool Client::Process() { } } - ///* Build a close range list of NPC's */ - //if (npc_close_scan_timer.Check()) { - // close_mobs.clear(); - // - // /* Force spawn updates when traveled far */ - // bool force_spawn_updates = false; - // float client_update_range = (RuleI(Range, ClientForceSpawnUpdateRange) * RuleI(Range, ClientForceSpawnUpdateRange)); - // if (DistanceSquared(last_major_update_position, m_Position) >= client_update_range) { - // last_major_update_position = m_Position; - // force_spawn_updates = true; - // } - // - // float scan_range = (RuleI(Range, ClientNPCScan) * RuleI(Range, ClientNPCScan)); - // auto &mob_list = entity_list.GetMobList(); - // for (auto itr = mob_list.begin(); itr != mob_list.end(); ++itr) { - // Mob* mob = itr->second; - // - // float distance = DistanceSquared(m_Position, mob->GetPosition()); - // if (mob->IsNPC()) { - // if (distance <= scan_range) { - // close_mobs.insert(std::pair(mob, distance)); - // } - // else if ((mob->GetAggroRange() * mob->GetAggroRange()) > scan_range) { - // close_mobs.insert(std::pair(mob, distance)); - // } - // } - // - // if (force_spawn_updates && mob != this) { - // - // if (mob->is_distance_roamer) { - // mob->SendPositionUpdateToClient(this); - // continue; - // } - // - // if (distance <= client_update_range) - // mob->SendPositionUpdateToClient(this); - // } - // - // } - //} - bool may_use_attacks = false; /* Things which prevent us from attacking: @@ -460,7 +419,7 @@ bool Client::Process() { { animation = 0; m_Delta = glm::vec4(0.0f, 0.0f, 0.0f, m_Delta.w); - SendPositionUpdate(2); + SendPositionUpdate(true); } } diff --git a/zone/mob.cpp b/zone/mob.cpp index a4e7dbff8..63a1c47ca 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -23,6 +23,7 @@ #include "quest_parser_collection.h" #include "string_ids.h" #include "worldserver.h" +#include "mob_movement_manager.h" #include #include @@ -116,12 +117,12 @@ Mob::Mob(const char* in_name, position_update_melee_push_timer(500), hate_list_cleanup_timer(6000) { + mMovementManager = &MobMovementManager::Get(); + mMovementManager->AddMob(this); + targeted = 0; currently_fleeing = false; - last_major_update_position = m_Position; - is_distance_roamer = false; - AI_Init(); SetMoving(false); moved = false; @@ -448,6 +449,8 @@ Mob::Mob(const char* in_name, Mob::~Mob() { + mMovementManager->RemoveMob(this); + AI_Stop(); if (GetPet()) { if (GetPet()->Charmed()) @@ -1450,59 +1453,12 @@ void Mob::StopMoving(float new_heading) { /* Used for mobs standing still - this does not send a delta */ void Mob::SendPosition() { - //auto app = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct)); - //PlayerPositionUpdateServer_Struct* spu = (PlayerPositionUpdateServer_Struct*)app->pBuffer; - //MakeSpawnUpdateNoDelta(spu); - // - //entity_list.QueueCloseClients(this, app, true, 200.0f, nullptr, false); - // - ///* When an NPC has made a large distance change - we should update all clients to prevent "ghosts" */ - //if (DistanceSquared(last_major_update_position, m_Position) >= (100 * 100)) { - // entity_list.QueueClients(this, app, true, true); - // last_major_update_position = m_Position; - // is_distance_roamer = true; - //} - //else { - // entity_list.QueueCloseClients(this, app, true, RuleI(Range, MobPositionUpdates), nullptr, false); - //} - // - //safe_delete(app); -} - -void Mob::SendPositionUpdateToClient(Client *client) { - //auto app = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct)); - //PlayerPositionUpdateServer_Struct* spawn_update = (PlayerPositionUpdateServer_Struct*)app->pBuffer; - // - //if(this->IsMoving()) - // MakeSpawnUpdate(spawn_update); - //else - // MakeSpawnUpdateNoDelta(spawn_update); - // - //client->QueuePacket(app, false); - // - //safe_delete(app); + mMovementManager->SendPosition(this); } /* Position updates for mobs on the move */ -void Mob::SendPositionUpdate(uint8 iSendToSelf) { - //auto app = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct)); - //PlayerPositionUpdateServer_Struct* spu = (PlayerPositionUpdateServer_Struct*)app->pBuffer; - //MakeSpawnUpdate(spu); - // - //if (iSendToSelf == 2) { - // if (IsClient()) { - // CastToClient()->FastQueuePacket(&app, false); - // } - //} - //else if (DistanceSquared(last_major_update_position, m_Position) >= (100 * 100)) { - // entity_list.QueueClients(this, app, true, true); - // last_major_update_position = m_Position; - // is_distance_roamer = true; - //} - //else { - // entity_list.QueueCloseClients(this, app, (iSendToSelf == 0), RuleI(Range, MobPositionUpdates), nullptr, false); - //} - //safe_delete(app); +void Mob::SendPositionUpdate(bool iSendToSelf) { + mMovementManager->SendPositionUpdate(this, iSendToSelf); } // this is for SendPosition() @@ -1518,11 +1474,6 @@ void Mob::MakeSpawnUpdateNoDelta(PlayerPositionUpdateServer_Struct *spu) { spu->heading = FloatToEQ12(m_Position.w); spu->animation = 0; spu->delta_heading = FloatToEQ10(0); - spu->padding0002 = 0; - spu->padding0006 = 7; - spu->padding0014 = 0x7f; - spu->padding0018 = 0x5df27; - } // this is for SendPosUpdate() @@ -1535,10 +1486,6 @@ void Mob::MakeSpawnUpdate(PlayerPositionUpdateServer_Struct* spu) { spu->delta_y = FloatToEQ13(m_Delta.y); spu->delta_z = FloatToEQ13(m_Delta.z); spu->heading = FloatToEQ12(m_Position.w); - spu->padding0002 = 0; - spu->padding0006 = 7; - spu->padding0014 = 0x7f; - spu->padding0018 = 0x5df27; #ifdef BOTS if (this->IsClient() || this->IsBot()) #else diff --git a/zone/mob.h b/zone/mob.h index e01c5c66f..52d404049 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -49,6 +49,7 @@ class Aura; struct AuraRecord; struct NewSpawn_Struct; struct PlayerPositionUpdateServer_Struct; +class MobMovementManager; const int COLLISION_BOX_SIZE = 8; @@ -164,8 +165,6 @@ public: inline virtual bool IsMob() const { return true; } inline virtual bool InZone() const { return true; } - bool is_distance_roamer; - //Somewhat sorted: needs documenting! //Attack @@ -559,8 +558,7 @@ public: void SetRunning(bool val) { m_is_running = val; } virtual void GMMove(float x, float y, float z, float heading = 0.01, bool SendUpdate = true); void SetDelta(const glm::vec4& delta); - void SendPositionUpdateToClient(Client *client); - void SendPositionUpdate(uint8 iSendToSelf = 0); + void SendPositionUpdate(bool iSendToSelf = false); void MakeSpawnUpdateNoDelta(PlayerPositionUpdateServer_Struct* spu); void MakeSpawnUpdate(PlayerPositionUpdateServer_Struct* spu); void SendPosition(); @@ -802,6 +800,7 @@ public: void SendAppearancePacket(uint32 type, uint32 value, bool WholeZone = true, bool iIgnoreSelf = false, Client *specific_target=nullptr); void SetAppearance(EmuAppearance app, bool iIgnoreSelf = true); inline EmuAppearance GetAppearance() const { return _appearance; } + inline const int GetAnimation() const { return animation; } inline const uint8 GetRunAnimSpeed() const { return pRunAnimSpeed; } inline void SetRunAnimSpeed(int8 in) { if (pRunAnimSpeed != in) { pRunAnimSpeed = in; } } bool IsDestructibleObject() { return destructibleobject; } @@ -1247,8 +1246,6 @@ protected: uint8 orig_level; uint32 npctype_id; glm::vec4 m_Position; - /* Used to determine when an NPC has traversed so many units - to send a zone wide pos update */ - glm::vec4 last_major_update_position; int animation; // this is really what MQ2 calls SpeedRun just packed like (int)(SpeedRun * 40.0f) float base_size; @@ -1530,6 +1527,8 @@ protected: AuraMgr aura_mgr; AuraMgr trap_mgr; + MobMovementManager *mMovementManager; + private: void _StopSong(); //this is not what you think it is Mob* target; diff --git a/zone/mob_movement_manager.cpp b/zone/mob_movement_manager.cpp new file mode 100644 index 000000000..138a85255 --- /dev/null +++ b/zone/mob_movement_manager.cpp @@ -0,0 +1,259 @@ +#include "mob_movement_manager.h" +#include "client.h" +#include "mob.h" +#include "../common/timer.h" + +#include +#include + +struct MobMovementEntry +{ + Mob *m; + int animation; + float heading; + bool dirty; + double last_sent_time; + double last_sent_time_long_distance; + + MobMovementEntry(Mob *m) { + this->m = m; + animation = 0; + heading = m->GetHeading(); + dirty = false; + last_sent_time = 0.0; + last_sent_time_long_distance = 0.0; + } +}; + +struct MobMovementManager::Implementation +{ + std::vector Entries; + std::vector Clients; +}; + +MobMovementManager::MobMovementManager() +{ + _impl.reset(new Implementation()); +} + +MobMovementManager::~MobMovementManager() +{ +} + +void MobMovementManager::Process() +{ + double current_time = static_cast(Timer::GetCurrentTime()) / 1000.0; + + for (auto &ent : _impl->Entries) { + if (ent.dirty) { + SendUpdate(ent.m, ent.animation, ent.heading); + + ent.dirty = false; + ent.last_sent_time = current_time; + ent.last_sent_time_long_distance = current_time; + } else if (ent.animation != 0) { + double diff_short_range = current_time - ent.last_sent_time; + double diff_long_range = current_time - ent.last_sent_time_long_distance; + + if (diff_short_range >= 2.0) { + SendUpdateShortDistance(ent.m, ent.animation, ent.heading); + ent.last_sent_time = current_time; + } + + if (diff_long_range >= 6.0) { + SendUpdateLongDistance(ent.m, ent.animation, ent.heading); + ent.last_sent_time_long_distance = current_time; + } + } + } +} + +void MobMovementManager::AddMob(Mob *m) +{ + _impl->Entries.push_back(MobMovementEntry(m)); +} + +void MobMovementManager::RemoveMob(Mob *m) +{ + auto iter = _impl->Entries.begin(); + while (iter != _impl->Entries.end()) { + auto &ent = *iter; + if (ent.m == m) { + _impl->Entries.erase(iter); + return; + } + ++iter; + } +} + +void MobMovementManager::AddClient(Client *c) +{ + _impl->Clients.push_back(c); +} + +void MobMovementManager::RemoveClient(Client *c) +{ + auto iter = _impl->Clients.begin(); + while (iter != _impl->Clients.end()) { + if (c == *iter) { + _impl->Clients.erase(iter); + return; + } + + ++iter; + } + +} + +void MobMovementManager::SendPosition(Mob *who) +{ + auto iter = _impl->Entries.begin(); + while (iter != _impl->Entries.end()) { + auto &ent = *iter; + + if (ent.m == who) { + auto anim = 0; + auto heading = who->GetHeading(); + + if (ent.animation != anim || !HeadingEqual(ent.heading, heading)) { + ent.animation = anim; + ent.heading = heading; + ent.dirty = true; + } + + return; + } + + ++iter; + } +} + +void MobMovementManager::SendPositionUpdate(Mob *who, bool send_to_self) +{ + auto iter = _impl->Entries.begin(); + while (iter != _impl->Entries.end()) { + auto &ent = *iter; + + if (ent.m == who) { + auto anim = 0; + auto heading = who->GetHeading(); + if (who->IsMoving()) { + if (who->IsClient()) { + anim = who->GetAnimation(); + } + else { + anim = who->GetRunAnimSpeed(); + } + } + + if (send_to_self && who->IsClient()) { + SendUpdateTo(who, who->CastToClient(), anim, heading); + } + + if (ent.animation != anim || !HeadingEqual(ent.heading, heading)) { + ent.animation = anim; + ent.heading = heading; + ent.dirty = true; + } + + return; + } + + ++iter; + } +} + +bool MobMovementManager::HeadingEqual(float a, float b) +{ + const float eps = 0.001f; + return abs(a - b) < eps; +} + +void MobMovementManager::SendUpdateTo(Mob *who, Client *c, int anim, float heading) +{ + EQApplicationPacket outapp(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct)); + PlayerPositionUpdateServer_Struct* spu = (PlayerPositionUpdateServer_Struct*)outapp.pBuffer; + if (anim == 0) { + who->MakeSpawnUpdateNoDelta(spu); + } + else { + who->MakeSpawnUpdate(spu); + } + + c->QueuePacket(&outapp); +} + +void MobMovementManager::SendUpdate(Mob *who, int anim, float heading) +{ + EQApplicationPacket outapp(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct)); + PlayerPositionUpdateServer_Struct* spu = (PlayerPositionUpdateServer_Struct*)outapp.pBuffer; + if (anim == 0) { + who->MakeSpawnUpdateNoDelta(spu); + } + else { + who->MakeSpawnUpdate(spu); + } + + for (auto &c : _impl->Clients) { + if (c != who) { + c->QueuePacket(&outapp); + } + else if (c->IsAIControlled()) { + c->QueuePacket(&outapp); + } + } +} + +void MobMovementManager::SendUpdateShortDistance(Mob *who, int anim, float heading) +{ + EQApplicationPacket outapp(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct)); + PlayerPositionUpdateServer_Struct* spu = (PlayerPositionUpdateServer_Struct*)outapp.pBuffer; + if (anim == 0) { + who->MakeSpawnUpdateNoDelta(spu); + } + else { + who->MakeSpawnUpdate(spu); + } + + for (auto &c : _impl->Clients) { + if (c != who) { + auto dist = who->CalculateDistance(c->GetX(), c->GetY(), c->GetZ()); + if (dist <= 1000.0f) { + c->QueuePacket(&outapp); + } + } + else if (c->IsAIControlled()) { + auto dist = who->CalculateDistance(c->GetX(), c->GetY(), c->GetZ()); + if (dist <= 1000.0f) { + c->QueuePacket(&outapp); + } + } + } +} + +void MobMovementManager::SendUpdateLongDistance(Mob *who, int anim, float heading) +{ + EQApplicationPacket outapp(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct)); + PlayerPositionUpdateServer_Struct* spu = (PlayerPositionUpdateServer_Struct*)outapp.pBuffer; + if (anim == 0) { + who->MakeSpawnUpdateNoDelta(spu); + } + else { + who->MakeSpawnUpdate(spu); + } + + for (auto &c : _impl->Clients) { + if (c != who) { + auto dist = who->CalculateDistance(c->GetX(), c->GetY(), c->GetZ()); + if (dist > 1000.0f) { + c->QueuePacket(&outapp); + } + } + else if (c->IsAIControlled()) { + auto dist = who->CalculateDistance(c->GetX(), c->GetY(), c->GetZ()); + if (dist > 1000.0f) { + c->QueuePacket(&outapp); + } + } + } +} diff --git a/zone/mob_movement_manager.h b/zone/mob_movement_manager.h new file mode 100644 index 000000000..69ea2ee80 --- /dev/null +++ b/zone/mob_movement_manager.h @@ -0,0 +1,38 @@ +#pragma once +#include + +class Mob; +class Client; + +class MobMovementManager +{ +public: + ~MobMovementManager(); + void Process(); + void AddMob(Mob *m); + void RemoveMob(Mob *m); + void AddClient(Client *c); + void RemoveClient(Client *c); + + void SendPosition(Mob *who); + void SendPositionUpdate(Mob *who, bool send_to_self); + + static MobMovementManager &Get() { + static MobMovementManager inst; + return inst; + } + +private: + MobMovementManager(); + MobMovementManager(const MobMovementManager&); + MobMovementManager& operator=(const MobMovementManager&); + + bool HeadingEqual(float a, float b); + void SendUpdateTo(Mob *who, Client *c, int anim, float heading); + void SendUpdate(Mob *who, int anim, float heading); + void SendUpdateShortDistance(Mob *who, int anim, float heading); + void SendUpdateLongDistance(Mob *who, int anim, float heading); + + struct Implementation; + std::unique_ptr _impl; +}; diff --git a/zone/perl_mob.cpp b/zone/perl_mob.cpp index ea3ba40b4..e61f6ec81 100644 --- a/zone/perl_mob.cpp +++ b/zone/perl_mob.cpp @@ -1189,7 +1189,7 @@ XS(XS_Mob_SendPosUpdate) { iSendToSelf = (uint8) SvUV(ST(1)); } - THIS->SendPositionUpdate(iSendToSelf); + THIS->SendPositionUpdate(iSendToSelf != 0 ? true : false); } XSRETURN_EMPTY; } diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 7e8db6930..da345fcdd 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -853,7 +853,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove SetHeading(CalculateHeadingToTarget(ClosestMob->GetX(), ClosestMob->GetY())); SetTarget(ClosestMob); CastToClient()->SendTargetCommand(ClosestMob->GetID()); - SendPositionUpdate(2); + SendPositionUpdate(true); } else Message_StringID(clientMessageError, SENSE_NOTHING); diff --git a/zone/waypoints.cpp b/zone/waypoints.cpp index 0c1e4d11d..f285b8887 100644 --- a/zone/waypoints.cpp +++ b/zone/waypoints.cpp @@ -463,7 +463,7 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, float speed, b if (IsClient()) #endif { - animation = speed / 2; + animation = speed * 0.55f; } //Setup Vectors @@ -481,7 +481,7 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, float speed, b } double time_since_last = static_cast(frame_time) / 1000.0; - double distance_moved = time_since_last * (speed + 100.0f); + double distance_moved = time_since_last * speed * 2.275f; if (distance_moved > len) { m_Position.x = x; @@ -492,6 +492,10 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, float speed, b entity_list.ProcessMove(CastToNPC(), x, y, z); } + if (check_z && fix_z_timer.Check() && (!IsEngaged() || flee_mode || currently_fleeing)) { + FixZ(); + } + return true; } else { @@ -505,11 +509,15 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, float speed, b } } + if (check_z && fix_z_timer.Check() && !IsEngaged()) { + FixZ(); + } + SetMoving(true); m_Delta = glm::vec4(m_Position.x - pos.x, m_Position.y - pos.y, m_Position.z - pos.z, 0.0f); if (IsClient()) { - SendPositionUpdate(1); + SendPositionUpdate(); CastToClient()->ResetPositionTimer(); } else { diff --git a/zone/zone.cpp b/zone/zone.cpp index 3b9e5e513..2acb0fa6b 100644 --- a/zone/zone.cpp +++ b/zone/zone.cpp @@ -53,6 +53,7 @@ #include "worldserver.h" #include "zone.h" #include "zone_config.h" +#include "mob_movement_manager.h" #include #include @@ -861,6 +862,8 @@ Zone::Zone(uint32 in_zoneid, uint32 in_instanceid, const char* in_short_name) m_ucss_available = false; m_last_ucss_update = 0; + + mMovementManager = &MobMovementManager::Get(); } Zone::~Zone() { @@ -1303,6 +1306,8 @@ bool Zone::Process() { if(hotzone_timer.Check()) { UpdateHotzone(); } + mMovementManager->Process(); + return true; } diff --git a/zone/zone.h b/zone/zone.h index 5f8651d8b..1e3d345fb 100644 --- a/zone/zone.h +++ b/zone/zone.h @@ -79,6 +79,7 @@ class WaterMap; extern EntityList entity_list; struct NPCType; struct ServerZoneIncomingClient_Struct; +class MobMovementManager; class Zone { @@ -362,6 +363,8 @@ private: bool m_ucss_available; uint32 m_last_ucss_update; + + MobMovementManager *mMovementManager; }; #endif