diff --git a/world/client.cpp b/world/client.cpp index 9b04f5cc5..d3b477286 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -92,8 +92,6 @@ 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/client.cpp b/zone/client.cpp index 9fa8fbec7..0f32da9ea 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -156,6 +156,7 @@ 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), diff --git a/zone/client.h b/zone/client.h index f9359aa02..1768c9493 100644 --- a/zone/client.h +++ b/zone/client.h @@ -1514,6 +1514,7 @@ 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 */ diff --git a/zone/client_process.cpp b/zone/client_process.cpp index 12c9a91be..fcfc1df53 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -250,6 +250,28 @@ bool Client::Process() { GetName(), RuleI(Character, InvSnapshotMinRetryM), (RuleI(Character, InvSnapshotMinRetryM) == 1 ? "" : "s")); } } + + /* 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)); + 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)); + } + } + } + } bool may_use_attacks = false; /* diff --git a/zone/mob.cpp b/zone/mob.cpp index 91fb779a6..b2912f46a 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -1658,7 +1658,15 @@ void Mob::ShowBuffList(Client* client) { } void Mob::GMMove(float x, float y, float z, float heading, bool SendUpdate) { - Teleport(glm::vec4(x, y, z, heading)); + if (IsCorpse()) { + m_Position.x = x; + m_Position.y = y; + m_Position.z = z; + mMovementManager->SendCommandToClients(this, 0.0, 0.0, 0.0, 0.0, 0, ClientRangeAny); + } + else { + Teleport(glm::vec4(x, y, z, heading)); + } if (IsNPC()) { CastToNPC()->SaveGuardSpot(glm::vec4(x, y, z, heading)); diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index a0370d1de..3f99d86c7 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -375,11 +375,6 @@ bool NPC::AIDoSpellCast(uint8 i, Mob* tar, int32 mana_cost, uint32* oDontDoAgain #endif casting_spell_AIindex = i; - //stop moving if were casting a spell and were not a bard... - if(!IsBardSong(AIspells[i].spellid)) { - StopNavigation(); - } - return CastSpell(AIspells[i].spellid, tar->GetID(), EQEmu::CastingSlot::Gem2, AIspells[i].manacost == -2 ? 0 : -1, mana_cost, oDontDoAgainBefore, -1, -1, 0, &(AIspells[i].resist_adjust)); } @@ -802,11 +797,11 @@ void Client::AI_Process() if (AI_movement_timer->Check()) { // Check if we have reached the last fear point if(IsPositionEqualWithinCertainZ(glm::vec3(GetX(), GetY(), GetZ()), m_FearWalkTarget, 5.0f)) { - StopNavigation(); CalculateNewFearpoint(); } - - RunTo(m_FearWalkTarget.x, m_FearWalkTarget.y, m_FearWalkTarget.z); + else { + RunTo(m_FearWalkTarget.x, m_FearWalkTarget.y, m_FearWalkTarget.z); + } } return; } @@ -1387,7 +1382,7 @@ void Mob::AI_Process() { // Now pursue // TODO: Check here for another person on hate list with close hate value if (AI_PursueCastCheck()) { - //we did something, so do not process movement. + FaceTarget(); } else if (AI_movement_timer->Check() && target) { if (!IsRooted()) { @@ -1395,7 +1390,7 @@ void Mob::AI_Process() { RunTo(target->GetX(), target->GetY(), target->GetZ()); } - else if (IsMoving()) { + else { FaceTarget(); } } @@ -1433,7 +1428,7 @@ void Mob::AI_Process() { } } if (AI_IdleCastCheck()) { - //we processed a spell action, so do nothing else. + StopNavigation(); } else if (zone->CanDoCombat() && CastToNPC()->WillAggroNPCs() && AI_scan_area_timer->Check()) { @@ -1482,17 +1477,20 @@ void Mob::AI_Process() { * Distance: >= 450 (Snap to owner) */ if (distance_to_owner >= 202500 || z_distance > 100) { - Teleport(pet_owner_position); + if (running) { + RunTo(pet_owner_position.x, pet_owner_position.y, pet_owner_position.z); + } + else { + WalkTo(pet_owner_position.x, pet_owner_position.y, pet_owner_position.z); + } } else { - auto &Goal = owner->GetPosition(); - if (running) { - RunTo(Goal.x, Goal.y, Goal.z); + RunTo(pet_owner_position.x, pet_owner_position.y, pet_owner_position.z); } else { - WalkTo(Goal.x, Goal.y, Goal.z); + WalkTo(pet_owner_position.x, pet_owner_position.y, pet_owner_position.z); } } } @@ -1661,7 +1659,7 @@ void NPC::AI_DoMovement() { destination.x = roambox_destination_x; destination.y = roambox_destination_y; destination.z = m_Position.z; - roambox_destination_z = zone->zonemap->FindClosestZ(destination, nullptr) + this->GetZOffset(); + roambox_destination_z = zone->zonemap ? zone->zonemap->FindClosestZ(destination, nullptr) + this->GetZOffset() : 0; Log(Logs::Detail, Logs::NPCRoamBox, diff --git a/zone/mob_movement_manager.cpp b/zone/mob_movement_manager.cpp index 36f5aae5b..1c1db19fd 100644 --- a/zone/mob_movement_manager.cpp +++ b/zone/mob_movement_manager.cpp @@ -123,7 +123,12 @@ public: int current_speed = 0; if (m_move_to_mode == MovementRunning) { - current_speed = m->GetRunspeed(); + if (m->IsFeared()) { + current_speed = m->GetFearSpeed(); + } + else { + current_speed = m->GetRunspeed(); + } } else { current_speed = m->GetWalkspeed(); @@ -242,7 +247,12 @@ public: int current_speed = 0; if (m_move_to_mode == MovementRunning) { - current_speed = m->GetRunspeed(); + if (m->IsFeared()) { + current_speed = m->GetFearSpeed(); + } + else { + current_speed = m->GetRunspeed(); + } } else { current_speed = m->GetWalkspeed();