eqemu-server/zone/pathing.cpp

90 lines
2.3 KiB
C++

#include "../common/global_define.h"
#include "client.h"
#include "doors.h"
#include "water_map.h"
#include "zone.h"
#include <math.h>
glm::vec3 Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &WaypointChanged)
{
WaypointChanged = false;
glm::vec3 from(GetX(), GetY(), GetZ());
glm::vec3 to(ToX, ToY, ToZ);
if (Speed <= 0)
return to;
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);
if (m_pathing_route.GetStatus() == PathBroken) {
auto &nodes = m_pathing_route.GetNodesEdit();
auto &last_node = nodes[nodes.size() - 1];
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);
}
}
m_pathing_route.CalcCurrentNode(from, WaypointChanged);
auto &current = m_pathing_route.GetCurrentNode();
//We reached a wp and rolled over to a new wp dest and it was a portal wp so we portal to the next spot
if (WaypointChanged) {
if (m_pathing_route.GetPreviousNodeFlag() & NavigationPolyFlagPortal) {
Teleport(current.position);
}
TrySnapToMap();
}
return current.position;
}
void Mob::TrySnapToMap() {
bool snap = true;
if (IsNPC()) {
auto npc = CastToNPC();
if (npc->GetFlyMode() == 1 || npc->GetFlyMode() == 2) {
snap = false;
}
}
if (snap && zone->HasMap()) {
if (!RuleB(Watermap, CheckForWaterWhenMoving) ||
!zone->HasWaterMap() ||
(zone->HasWaterMap() && !zone->watermap->InLiquid(glm::vec3(m_Position)))) {
glm::vec3 dest(m_Position);
float newz = zone->zonemap->FindBestZ(dest, nullptr) + 3.5f;
m_Position.z = newz;
}
}
}