diff --git a/common/pathfind.cpp b/common/pathfind.cpp index 2ce88935d..f886577e9 100644 --- a/common/pathfind.cpp +++ b/common/pathfind.cpp @@ -309,6 +309,10 @@ PathfindingRoute::~PathfindingRoute() bool PathfindingRoute::DestinationValid(const glm::vec3 &dest) { + if (m_current_node >= 255) { + return false; + } + auto dist = vec_dist(dest, m_dest); if (dist <= max_dest_drift) { return true; diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 224232758..12ac8eac8 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -5626,7 +5626,18 @@ void Client::Handle_OP_FindPersonRequest(const EQApplicationPacket *app) } glm::vec3 dest(target->GetX(), target->GetY(), target->GetZ()); - auto route = zone->pathing.FindRoute(glm::vec3(GetX(), GetY(), GetZ()), dest); + glm::vec3 src(GetX(), GetY(), GetZ()); + if (zone->HasMap()) { + auto best_z_src = zone->zonemap->FindBestZ(src, nullptr); + if (best_z_src != BEST_Z_INVALID) { + src.z = best_z_src; + } + auto best_z_dest = zone->zonemap->FindBestZ(dest, nullptr); + if (best_z_dest != BEST_Z_INVALID) { + dest.z = best_z_dest; + } + } + auto route = zone->pathing.FindRoute(src, dest); CreatePathFromRoute(dest, route); } } diff --git a/zone/command.cpp b/zone/command.cpp index 53b5a2929..28815475e 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -4062,6 +4062,17 @@ void command_path(Client *c, const Seperator *sep) dest.x = target->GetX(); dest.y = target->GetY(); dest.z = target->GetZ(); + + if (zone->HasMap()) { + auto best_z_src = zone->zonemap->FindBestZ(src, nullptr); + if (best_z_src != BEST_Z_INVALID) { + src.z = best_z_src; + } + auto best_z_dest = zone->zonemap->FindBestZ(dest, nullptr); + if (best_z_dest != BEST_Z_INVALID) { + dest.z = best_z_dest; + } + } } else if (strcasecmp(sep->arg[1], "from") == 0) { src.x = target->GetX(); @@ -4070,6 +4081,17 @@ void command_path(Client *c, const Seperator *sep) dest.x = c->GetX(); dest.y = c->GetY(); dest.z = c->GetZ(); + + if (zone->HasMap()) { + auto best_z_src = zone->zonemap->FindBestZ(src, nullptr); + if (best_z_src != BEST_Z_INVALID) { + src.z = best_z_src; + } + auto best_z_dest = zone->zonemap->FindBestZ(dest, nullptr); + if (best_z_dest != BEST_Z_INVALID) { + dest.z = best_z_dest; + } + } } else { c->Message(0, "Unknown path argument: '%s'.", sep->arg[1]); @@ -4112,8 +4134,6 @@ void command_path(Client *c, const Seperator *sep) dest.y, dest.z, (int)nodes.size()); - - return; } void command_pvp(Client *c, const Seperator *sep) diff --git a/zone/mob.cpp b/zone/mob.cpp index 5812a0685..d345085cb 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -1398,7 +1398,13 @@ void Mob::SendPosUpdate(uint8 iSendToSelf) { { m_pos_update_speed = pRunAnimSpeed; m_pos_update_heading = GetHeading(); - entity_list.QueueCloseClients(this, &app, (iSendToSelf == 0), 1000, nullptr, false); + + if (IsBoat()) { + entity_list.QueueClients(this, &app, (iSendToSelf == 0), false); + } + else { + entity_list.QueueCloseClients(this, &app, (iSendToSelf == 0), 1000, nullptr, false); + } m_pos_update_timer.Start(); } } diff --git a/zone/pathing.cpp b/zone/pathing.cpp index d04bb21aa..c46ece58a 100644 --- a/zone/pathing.cpp +++ b/zone/pathing.cpp @@ -19,30 +19,51 @@ glm::vec3 Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &Wa if (to == from) return to; + //if from is swimming and has los to target then just swim toward them don't bother with pathing. + if (zone->HasMap() && zone->HasWaterMap() && zone->watermap->InLiquid(from) && zone->zonemap->CheckLoS(from, to) ) { + return to; + } + if (!m_pathing_route.Active() || !m_pathing_route.DestinationValid(to)) { + if (zone->HasMap()) { + auto best_z_src = zone->zonemap->FindBestZ(from, nullptr); + if (best_z_src != BEST_Z_INVALID) { + from.z = best_z_src; + } + auto best_z_dest = zone->zonemap->FindBestZ(to, nullptr); + if (best_z_dest != BEST_Z_INVALID) { + to.z = best_z_dest; + } + } + m_pathing_route = zone->pathing.FindRoute(from, to); auto &nodes = m_pathing_route.GetNodesEdit(); - auto &last_node = nodes[nodes.size() - 1]; - auto dist = DistanceSquared(glm::vec4(last_node.position, 1.0f), glm::vec4(ToX, ToY, ToZ, 0.0f)); - if (dist > 10000.0f) { - auto flag_temp = last_node.flag; - last_node.flag = NavigationPolyFlagPortal; + //Code to complete partial paths. + //256 is the max number of nodes, if we get that back then we likely got a partial path that + //*may* have more after so instead let it run the path till it gets there and then DestinationValid will return false again + if (nodes.size() < 256) { + auto &last_node = nodes[nodes.size() - 1]; + auto dist = DistanceSquared(glm::vec4(last_node.position, 1.0f), glm::vec4(ToX, ToY, ToZ, 0.0f)); + if (dist > 10000.0f) { + auto flag_temp = last_node.flag; + last_node.flag = NavigationPolyFlagPortal; - PathfindingNode end; - end.position.x = ToX; - end.position.y = ToY; - end.position.z = ToZ; - end.flag = flag_temp; - nodes.push_back(end); - } - else if (dist > 100.0f) { - PathfindingNode end; - end.position.x = ToX; - end.position.y = ToY; - end.position.z = ToZ; - end.flag = NavigationPolyFlagNormal; - nodes.push_back(end); + PathfindingNode end; + end.position.x = ToX; + end.position.y = ToY; + end.position.z = ToZ; + end.flag = flag_temp; + nodes.push_back(end); + } + else if (dist > 100.0f) { + PathfindingNode end; + end.position.x = ToX; + end.position.y = ToY; + end.position.z = ToZ; + end.flag = NavigationPolyFlagNormal; + nodes.push_back(end); + } } } @@ -55,7 +76,7 @@ glm::vec3 Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &Wa Teleport(current.position); } - //TrySnapToMap(); + TrySnapToMap(); } return current.position;