Add pathfinding interfaces, still heavily wip

This commit is contained in:
KimLS 2017-07-18 00:01:59 -07:00
parent 596e3b28b5
commit 5f1063acb9
26 changed files with 705 additions and 1181 deletions

View File

@ -84,7 +84,9 @@ SET(zone_sources
npc_ai.cpp npc_ai.cpp
object.cpp object.cpp
oriented_bounding_box.cpp oriented_bounding_box.cpp
pathfinder_interface.cpp
pathfinder_nav_mesh.cpp pathfinder_nav_mesh.cpp
pathfinder_null.cpp
pathfinder_waypoint.cpp pathfinder_waypoint.cpp
pathing.cpp pathing.cpp
perl_client.cpp perl_client.cpp
@ -201,6 +203,7 @@ SET(zone_headers
oriented_bounding_box.h oriented_bounding_box.h
pathfinder_interface.h pathfinder_interface.h
pathfinder_nav_mesh.h pathfinder_nav_mesh.h
pathfinder_null.h
pathfinder_waypoint.h pathfinder_waypoint.h
pathing.h pathing.h
perlpacket.h perlpacket.h

View File

@ -2165,7 +2165,7 @@ void Bot::AI_Process() {
} else if(!IsRooted()) { } else if(!IsRooted()) {
if(GetTarget() && GetTarget()->GetHateTop() && GetTarget()->GetHateTop() != this) { if(GetTarget() && GetTarget()->GetHateTop() && GetTarget()->GetHateTop() != this) {
Log(Logs::Detail, Logs::AI, "Returning to location prior to being summoned."); Log(Logs::Detail, Logs::AI, "Returning to location prior to being summoned.");
CalculateNewPosition2(m_PreSummonLocation.x, m_PreSummonLocation.y, m_PreSummonLocation.z, GetBotRunspeed()); CalculateNewPosition(m_PreSummonLocation.x, m_PreSummonLocation.y, m_PreSummonLocation.z, GetBotRunspeed());
SetHeading(CalculateHeadingToTarget(m_PreSummonLocation.x, m_PreSummonLocation.y)); SetHeading(CalculateHeadingToTarget(m_PreSummonLocation.x, m_PreSummonLocation.y));
return; return;
} }
@ -2256,12 +2256,12 @@ void Bot::AI_Process() {
if (WaypointChanged) if (WaypointChanged)
tar_ndx = 20; tar_ndx = 20;
CalculateNewPosition2(Goal.x, Goal.y, Goal.z, GetBotRunspeed()); CalculateNewPosition(Goal.x, Goal.y, Goal.z, GetBotRunspeed());
} }
else { else {
Mob* follow = entity_list.GetMob(GetFollowID()); Mob* follow = entity_list.GetMob(GetFollowID());
if (follow) if (follow)
CalculateNewPosition2(follow->GetX(), follow->GetY(), follow->GetZ(), GetBotRunspeed()); CalculateNewPosition(follow->GetX(), follow->GetY(), follow->GetZ(), GetBotRunspeed());
} }
return; return;
@ -2352,7 +2352,7 @@ void Bot::AI_Process() {
float newZ = 0; float newZ = 0;
FaceTarget(GetTarget()); FaceTarget(GetTarget());
if (PlotPositionAroundTarget(this, newX, newY, newZ)) { if (PlotPositionAroundTarget(this, newX, newY, newZ)) {
CalculateNewPosition2(newX, newY, newZ, GetBotRunspeed()); CalculateNewPosition(newX, newY, newZ, GetBotRunspeed());
return; return;
} }
} }
@ -2364,7 +2364,7 @@ void Bot::AI_Process() {
float newY = 0; float newY = 0;
float newZ = 0; float newZ = 0;
if (PlotPositionAroundTarget(GetTarget(), newX, newY, newZ)) { if (PlotPositionAroundTarget(GetTarget(), newX, newY, newZ)) {
CalculateNewPosition2(newX, newY, newZ, GetBotRunspeed()); CalculateNewPosition(newX, newY, newZ, GetBotRunspeed());
return; return;
} }
} }
@ -2375,7 +2375,7 @@ void Bot::AI_Process() {
float newY = 0; float newY = 0;
float newZ = 0; float newZ = 0;
if (PlotPositionAroundTarget(GetTarget(), newX, newY, newZ, false) && GetArchetype() != ARCHETYPE_CASTER) { if (PlotPositionAroundTarget(GetTarget(), newX, newY, newZ, false) && GetArchetype() != ARCHETYPE_CASTER) {
CalculateNewPosition2(newX, newY, newZ, GetBotRunspeed()); CalculateNewPosition(newX, newY, newZ, GetBotRunspeed());
return; return;
} }
} }
@ -2500,7 +2500,7 @@ void Bot::AI_Process() {
if (AI_movement_timer->Check()) { if (AI_movement_timer->Check()) {
if(!IsRooted()) { if(!IsRooted()) {
Log(Logs::Detail, Logs::AI, "Pursuing %s while engaged.", GetTarget()->GetCleanName()); Log(Logs::Detail, Logs::AI, "Pursuing %s while engaged.", GetTarget()->GetCleanName());
CalculateNewPosition2(GetTarget()->GetX(), GetTarget()->GetY(), GetTarget()->GetZ(), GetBotRunspeed()); CalculateNewPosition(GetTarget()->GetX(), GetTarget()->GetY(), GetTarget()->GetZ(), GetBotRunspeed());
return; return;
} }
@ -2560,10 +2560,10 @@ void Bot::AI_Process() {
if (WaypointChanged) if (WaypointChanged)
tar_ndx = 20; tar_ndx = 20;
CalculateNewPosition2(Goal.x, Goal.y, Goal.z, speed); CalculateNewPosition(Goal.x, Goal.y, Goal.z, speed);
} }
else { else {
CalculateNewPosition2(follow->GetX(), follow->GetY(), follow->GetZ(), speed); CalculateNewPosition(follow->GetX(), follow->GetY(), follow->GetZ(), speed);
} }
if (rest_timer.Enabled()) if (rest_timer.Enabled())
@ -2643,14 +2643,14 @@ void Bot::PetAIProcess() {
if(botPet->GetClass() == ROGUE && !petHasAggro && !botPet->BehindMob(botPet->GetTarget(), botPet->GetX(), botPet->GetY())) { if(botPet->GetClass() == ROGUE && !petHasAggro && !botPet->BehindMob(botPet->GetTarget(), botPet->GetX(), botPet->GetY())) {
// Move the rogue to behind the mob // Move the rogue to behind the mob
if(botPet->PlotPositionAroundTarget(botPet->GetTarget(), newX, newY, newZ)) { if(botPet->PlotPositionAroundTarget(botPet->GetTarget(), newX, newY, newZ)) {
botPet->CalculateNewPosition2(newX, newY, newZ, botPet->GetRunspeed()); botPet->CalculateNewPosition(newX, newY, newZ, botPet->GetRunspeed());
return; return;
} }
} }
else if(GetTarget() == botPet->GetTarget() && !petHasAggro && !botPet->BehindMob(botPet->GetTarget(), botPet->GetX(), botPet->GetY())) { else if(GetTarget() == botPet->GetTarget() && !petHasAggro && !botPet->BehindMob(botPet->GetTarget(), botPet->GetX(), botPet->GetY())) {
// If the bot owner and the bot are fighting the same mob, then move the pet to the rear arc of the mob // If the bot owner and the bot are fighting the same mob, then move the pet to the rear arc of the mob
if(botPet->PlotPositionAroundTarget(botPet->GetTarget(), newX, newY, newZ)) { if(botPet->PlotPositionAroundTarget(botPet->GetTarget(), newX, newY, newZ)) {
botPet->CalculateNewPosition2(newX, newY, newZ, botPet->GetRunspeed()); botPet->CalculateNewPosition(newX, newY, newZ, botPet->GetRunspeed());
return; return;
} }
} }
@ -2665,7 +2665,7 @@ void Bot::PetAIProcess() {
moveBehindMob = true; moveBehindMob = true;
if(botPet->PlotPositionAroundTarget(botPet->GetTarget(), newX, newY, newZ, moveBehindMob)) { if(botPet->PlotPositionAroundTarget(botPet->GetTarget(), newX, newY, newZ, moveBehindMob)) {
botPet->CalculateNewPosition2(newX, newY, newZ, botPet->GetRunspeed()); botPet->CalculateNewPosition(newX, newY, newZ, botPet->GetRunspeed());
return; return;
} }
} }
@ -2748,7 +2748,7 @@ void Bot::PetAIProcess() {
botPet->SetRunAnimSpeed(0); botPet->SetRunAnimSpeed(0);
if(!botPet->IsRooted()) { if(!botPet->IsRooted()) {
Log(Logs::Detail, Logs::AI, "Pursuing %s while engaged.", botPet->GetTarget()->GetCleanName()); Log(Logs::Detail, Logs::AI, "Pursuing %s while engaged.", botPet->GetTarget()->GetCleanName());
botPet->CalculateNewPosition2(botPet->GetTarget()->GetX(), botPet->GetTarget()->GetY(), botPet->GetTarget()->GetZ(), botPet->GetOwner()->GetRunspeed()); botPet->CalculateNewPosition(botPet->GetTarget()->GetX(), botPet->GetTarget()->GetY(), botPet->GetTarget()->GetZ(), botPet->GetOwner()->GetRunspeed());
return; return;
} else { } else {
botPet->SetHeading(botPet->GetTarget()->GetHeading()); botPet->SetHeading(botPet->GetTarget()->GetHeading());
@ -2776,7 +2776,7 @@ void Bot::PetAIProcess() {
float dist = DistanceSquared(botPet->GetPosition(), botPet->GetTarget()->GetPosition()); float dist = DistanceSquared(botPet->GetPosition(), botPet->GetTarget()->GetPosition());
botPet->SetRunAnimSpeed(0); botPet->SetRunAnimSpeed(0);
if(dist > 184) { if(dist > 184) {
botPet->CalculateNewPosition2(botPet->GetTarget()->GetX(), botPet->GetTarget()->GetY(), botPet->GetTarget()->GetZ(), botPet->GetTarget()->GetRunspeed()); botPet->CalculateNewPosition(botPet->GetTarget()->GetX(), botPet->GetTarget()->GetY(), botPet->GetTarget()->GetZ(), botPet->GetTarget()->GetRunspeed());
return; return;
} else { } else {
botPet->SetHeading(botPet->GetTarget()->GetHeading()); botPet->SetHeading(botPet->GetTarget()->GetHeading());

View File

@ -5688,128 +5688,128 @@ void Client::Handle_OP_FeignDeath(const EQApplicationPacket *app)
void Client::Handle_OP_FindPersonRequest(const EQApplicationPacket *app) void Client::Handle_OP_FindPersonRequest(const EQApplicationPacket *app)
{ {
if (app->size != sizeof(FindPersonRequest_Struct)) //if (app->size != sizeof(FindPersonRequest_Struct))
printf("Error in FindPersonRequest_Struct. Expected size of: %zu, but got: %i\n", sizeof(FindPersonRequest_Struct), app->size); // printf("Error in FindPersonRequest_Struct. Expected size of: %zu, but got: %i\n", sizeof(FindPersonRequest_Struct), app->size);
else { //else {
FindPersonRequest_Struct* t = (FindPersonRequest_Struct*)app->pBuffer; // FindPersonRequest_Struct* t = (FindPersonRequest_Struct*)app->pBuffer;
//
std::vector<FindPerson_Point> points; // std::vector<FindPerson_Point> points;
Mob* target = entity_list.GetMob(t->npc_id); // Mob* target = entity_list.GetMob(t->npc_id);
//
if (target == nullptr) { // if (target == nullptr) {
//empty length packet == not found. // //empty length packet == not found.
EQApplicationPacket outapp(OP_FindPersonReply, 0); // EQApplicationPacket outapp(OP_FindPersonReply, 0);
QueuePacket(&outapp); // QueuePacket(&outapp);
return; // return;
} // }
//
if (!RuleB(Pathing, Find) && RuleB(Bazaar, EnableWarpToTrader) && target->IsClient() && (target->CastToClient()->Trader || // if (!RuleB(Pathing, Find) && RuleB(Bazaar, EnableWarpToTrader) && target->IsClient() && (target->CastToClient()->Trader ||
target->CastToClient()->Buyer)) { // target->CastToClient()->Buyer)) {
Message(15, "Moving you to Trader %s", target->GetName()); // Message(15, "Moving you to Trader %s", target->GetName());
MovePC(zone->GetZoneID(), zone->GetInstanceID(), target->GetX(), target->GetY(), target->GetZ(), 0.0f); // MovePC(zone->GetZoneID(), zone->GetInstanceID(), target->GetX(), target->GetY(), target->GetZ(), 0.0f);
} // }
//
if (!RuleB(Pathing, Find) || !zone->pathing) // if (!RuleB(Pathing, Find) || !zone->pathing)
{ // {
//fill in the path array... // //fill in the path array...
// // //
points.resize(2); // points.resize(2);
points[0].x = GetX(); // points[0].x = GetX();
points[0].y = GetY(); // points[0].y = GetY();
points[0].z = GetZ(); // points[0].z = GetZ();
points[1].x = target->GetX(); // points[1].x = target->GetX();
points[1].y = target->GetY(); // points[1].y = target->GetY();
points[1].z = target->GetZ(); // points[1].z = target->GetZ();
} // }
else // else
{ // {
glm::vec3 Start(GetX(), GetY(), GetZ() + (GetSize() < 6.0 ? 6 : GetSize()) * HEAD_POSITION); // glm::vec3 Start(GetX(), GetY(), GetZ() + (GetSize() < 6.0 ? 6 : GetSize()) * HEAD_POSITION);
glm::vec3 End(target->GetX(), target->GetY(), target->GetZ() + (target->GetSize() < 6.0 ? 6 : target->GetSize()) * HEAD_POSITION); // glm::vec3 End(target->GetX(), target->GetY(), target->GetZ() + (target->GetSize() < 6.0 ? 6 : target->GetSize()) * HEAD_POSITION);
//
if (!zone->zonemap->LineIntersectsZone(Start, End, 1.0f, nullptr) && zone->pathing->NoHazards(Start, End)) // if (!zone->zonemap->LineIntersectsZone(Start, End, 1.0f, nullptr) && zone->pathing->NoHazards(Start, End))
{ // {
points.resize(2); // points.resize(2);
points[0].x = Start.x; // points[0].x = Start.x;
points[0].y = Start.y; // points[0].y = Start.y;
points[0].z = Start.z; // points[0].z = Start.z;
//
points[1].x = End.x; // points[1].x = End.x;
points[1].y = End.y; // points[1].y = End.y;
points[1].z = End.z; // points[1].z = End.z;
//
} // }
else // else
{ // {
std::deque<int> pathlist = zone->pathing->FindRoute(Start, End); // std::deque<int> pathlist = zone->pathing->FindRoute(Start, End);
//
if (pathlist.empty()) // if (pathlist.empty())
{ // {
EQApplicationPacket outapp(OP_FindPersonReply, 0); // EQApplicationPacket outapp(OP_FindPersonReply, 0);
QueuePacket(&outapp); // QueuePacket(&outapp);
return; // return;
} // }
//
//the client seems to have issues with packets larger than this // //the client seems to have issues with packets larger than this
if (pathlist.size() > 36) // if (pathlist.size() > 36)
{ // {
EQApplicationPacket outapp(OP_FindPersonReply, 0); // EQApplicationPacket outapp(OP_FindPersonReply, 0);
QueuePacket(&outapp); // QueuePacket(&outapp);
return; // return;
} // }
//
// Live appears to send the points in this order: // // Live appears to send the points in this order:
// Final destination. // // Final destination.
// Current Position. // // Current Position.
// rest of the points. // // rest of the points.
FindPerson_Point p; // FindPerson_Point p;
//
int PointNumber = 0; // int PointNumber = 0;
//
bool LeadsToTeleporter = false; // bool LeadsToTeleporter = false;
//
glm::vec3 v = zone->pathing->GetPathNodeCoordinates(pathlist.back()); // glm::vec3 v = zone->pathing->GetPathNodeCoordinates(pathlist.back());
//
p.x = v.x; // p.x = v.x;
p.y = v.y; // p.y = v.y;
p.z = v.z; // p.z = v.z;
points.push_back(p); // points.push_back(p);
//
p.x = GetX(); // p.x = GetX();
p.y = GetY(); // p.y = GetY();
p.z = GetZ(); // p.z = GetZ();
points.push_back(p); // points.push_back(p);
//
for (auto Iterator = pathlist.begin(); Iterator != pathlist.end(); ++Iterator) // for (auto Iterator = pathlist.begin(); Iterator != pathlist.end(); ++Iterator)
{ // {
if ((*Iterator) == -1) // Teleporter // if ((*Iterator) == -1) // Teleporter
{ // {
LeadsToTeleporter = true; // LeadsToTeleporter = true;
break; // break;
} // }
//
glm::vec3 v = zone->pathing->GetPathNodeCoordinates((*Iterator), false); // glm::vec3 v = zone->pathing->GetPathNodeCoordinates((*Iterator), false);
p.x = v.x; // p.x = v.x;
p.y = v.y; // p.y = v.y;
p.z = v.z; // p.z = v.z;
points.push_back(p); // points.push_back(p);
++PointNumber; // ++PointNumber;
} // }
//
if (!LeadsToTeleporter) // if (!LeadsToTeleporter)
{ // {
p.x = target->GetX(); // p.x = target->GetX();
p.y = target->GetY(); // p.y = target->GetY();
p.z = target->GetZ(); // p.z = target->GetZ();
//
points.push_back(p); // points.push_back(p);
} // }
//
} // }
} // }
//
SendPathPacket(points); // SendPathPacket(points);
} //}
return; //return;
} }
void Client::Handle_OP_Fishing(const EQApplicationPacket *app) void Client::Handle_OP_Fishing(const EQApplicationPacket *app)

View File

@ -6813,312 +6813,312 @@ void command_qglobal(Client *c, const Seperator *sep) {
void command_path(Client *c, const Seperator *sep) void command_path(Client *c, const Seperator *sep)
{ {
if(sep->arg[1][0] == '\0' || !strcasecmp(sep->arg[1], "help")) //if(sep->arg[1][0] == '\0' || !strcasecmp(sep->arg[1], "help"))
{ //{
c->Message(0, "Syntax: #path shownodes: Spawns a npc to represent every npc node."); // c->Message(0, "Syntax: #path shownodes: Spawns a npc to represent every npc node.");
c->Message(0, "#path info node_id: Gives information about node info (requires shownode target)."); // c->Message(0, "#path info node_id: Gives information about node info (requires shownode target).");
c->Message(0, "#path dump file_name: Dumps the current zone->pathing to a file of your naming."); // c->Message(0, "#path dump file_name: Dumps the current zone->pathing to a file of your naming.");
c->Message(0, "#path add [requested_id]: Adds a node at your current location will try to take the requested id if possible."); // c->Message(0, "#path add [requested_id]: Adds a node at your current location will try to take the requested id if possible.");
c->Message(0, "#path connect connect_to_id [is_teleport] [door_id]: Connects the currently targeted node to connect_to_id's node and connects that node back (requires shownode target)."); // c->Message(0, "#path connect connect_to_id [is_teleport] [door_id]: Connects the currently targeted node to connect_to_id's node and connects that node back (requires shownode target).");
c->Message(0, "#path sconnect connect_to_id [is_teleport] [door_id]: Connects the currently targeted node to connect_to_id's node (requires shownode target)."); // c->Message(0, "#path sconnect connect_to_id [is_teleport] [door_id]: Connects the currently targeted node to connect_to_id's node (requires shownode target).");
c->Message(0, "#path qconnect [set]: short cut connect, connects the targeted node to the node you set with #path qconnect set (requires shownode target)."); // c->Message(0, "#path qconnect [set]: short cut connect, connects the targeted node to the node you set with #path qconnect set (requires shownode target).");
c->Message(0, "#path disconnect [all]/disconnect_from_id: Disconnects the currently targeted node to disconnect from disconnect from id's node (requires shownode target), if passed all as the second argument it will disconnect this node from every other node."); // c->Message(0, "#path disconnect [all]/disconnect_from_id: Disconnects the currently targeted node to disconnect from disconnect from id's node (requires shownode target), if passed all as the second argument it will disconnect this node from every other node.");
c->Message(0, "#path move: Moves your targeted node to your current position"); // c->Message(0, "#path move: Moves your targeted node to your current position");
c->Message(0, "#path process file_name: processes the map file and tries to automatically generate a rudimentary path setup and then dumps the current zone->pathing to a file of your naming."); // c->Message(0, "#path process file_name: processes the map file and tries to automatically generate a rudimentary path setup and then dumps the current zone->pathing to a file of your naming.");
c->Message(0, "#path resort [nodes]: resorts the connections/nodes after you've manually altered them so they'll work."); // c->Message(0, "#path resort [nodes]: resorts the connections/nodes after you've manually altered them so they'll work.");
return; // return;
} //}
if(!strcasecmp(sep->arg[1], "shownodes")) //if(!strcasecmp(sep->arg[1], "shownodes"))
{ //{
if(zone->pathing) // if(zone->pathing)
zone->pathing->SpawnPathNodes(); // zone->pathing->SpawnPathNodes();
//
return; // return;
} //}
//
if(!strcasecmp(sep->arg[1], "info")) //if(!strcasecmp(sep->arg[1], "info"))
{ //{
if(zone->pathing) // if(zone->pathing)
{ // {
zone->pathing->NodeInfo(c); // zone->pathing->NodeInfo(c);
} // }
return; // return;
} //}
//
if(!strcasecmp(sep->arg[1], "dump")) //if(!strcasecmp(sep->arg[1], "dump"))
{ //{
if(zone->pathing) // if(zone->pathing)
{ // {
if(sep->arg[2][0] == '\0') // if(sep->arg[2][0] == '\0')
return; // return;
//
zone->pathing->DumpPath(sep->arg[2]); // zone->pathing->DumpPath(sep->arg[2]);
} // }
return; // return;
} //}
//
if(!strcasecmp(sep->arg[1], "add")) //if(!strcasecmp(sep->arg[1], "add"))
{ //{
if(zone->pathing) // if(zone->pathing)
{ // {
float px = c->GetX(); // float px = c->GetX();
float py = c->GetY(); // float py = c->GetY();
float pz = c->GetZ(); // float pz = c->GetZ();
float best_z; // float best_z;
//
if(zone->zonemap) // if(zone->zonemap)
{ // {
glm::vec3 loc(px, py, pz); // glm::vec3 loc(px, py, pz);
best_z = zone->zonemap->FindBestZ(loc, nullptr); // best_z = zone->zonemap->FindBestZ(loc, nullptr);
} // }
else // else
{ // {
best_z = pz; // best_z = pz;
} // }
int32 res = zone->pathing->AddNode(px, py, pz, best_z, atoi(sep->arg[2])); // int32 res = zone->pathing->AddNode(px, py, pz, best_z, atoi(sep->arg[2]));
if(res >= 0) // if(res >= 0)
{ // {
c->Message(0, "Added Path Node: %i", res); // c->Message(0, "Added Path Node: %i", res);
} // }
else // else
{ // {
c->Message(0, "Failed to add Path Node"); // c->Message(0, "Failed to add Path Node");
} // }
} // }
else // else
{ // {
zone->pathing = new PathManager(); // zone->pathing = new PathManager();
float px = c->GetX(); // float px = c->GetX();
float py = c->GetY(); // float py = c->GetY();
float pz = c->GetZ(); // float pz = c->GetZ();
float best_z; // float best_z;
//
if(zone->zonemap) // if(zone->zonemap)
{ // {
glm::vec3 loc(px, py, pz); // glm::vec3 loc(px, py, pz);
best_z = zone->zonemap->FindBestZ(loc, nullptr); // best_z = zone->zonemap->FindBestZ(loc, nullptr);
} // }
else // else
{ // {
best_z = pz; // best_z = pz;
} // }
int32 res = zone->pathing->AddNode(px, py, pz, best_z, atoi(sep->arg[2])); // int32 res = zone->pathing->AddNode(px, py, pz, best_z, atoi(sep->arg[2]));
if(res >= 0) // if(res >= 0)
{ // {
c->Message(0, "Added Path Node: %i", res); // c->Message(0, "Added Path Node: %i", res);
} // }
else // else
{ // {
c->Message(0, "Failed to add Path Node"); // c->Message(0, "Failed to add Path Node");
} // }
} // }
return; // return;
} //}
//
if(!strcasecmp(sep->arg[1], "remove")) //if(!strcasecmp(sep->arg[1], "remove"))
{ //{
if(zone->pathing) // if(zone->pathing)
{ // {
if(zone->pathing->DeleteNode(c)) // if(zone->pathing->DeleteNode(c))
{ // {
c->Message(0, "Removed Node."); // c->Message(0, "Removed Node.");
} // }
else // else
{ // {
c->Message(0, "Unable to Remove Node."); // c->Message(0, "Unable to Remove Node.");
} // }
} // }
return; // return;
} //}
//
if(!strcasecmp(sep->arg[1], "connect")) //if(!strcasecmp(sep->arg[1], "connect"))
{ //{
if(zone->pathing) // if(zone->pathing)
{ // {
zone->pathing->ConnectNodeToNode(c, atoi(sep->arg[2]), atoi(sep->arg[3]), atoi(sep->arg[4])); // zone->pathing->ConnectNodeToNode(c, atoi(sep->arg[2]), atoi(sep->arg[3]), atoi(sep->arg[4]));
} // }
return; // return;
} //}
//
if(!strcasecmp(sep->arg[1], "sconnect")) //if(!strcasecmp(sep->arg[1], "sconnect"))
{ //{
if(zone->pathing) // if(zone->pathing)
{ // {
zone->pathing->ConnectNode(c, atoi(sep->arg[2]), atoi(sep->arg[3]), atoi(sep->arg[4])); // zone->pathing->ConnectNode(c, atoi(sep->arg[2]), atoi(sep->arg[3]), atoi(sep->arg[4]));
} // }
return; // return;
} //}
//
if(!strcasecmp(sep->arg[1], "qconnect")) //if(!strcasecmp(sep->arg[1], "qconnect"))
{ //{
if(zone->pathing) // if(zone->pathing)
{ // {
if(!strcasecmp(sep->arg[2], "set")) // if(!strcasecmp(sep->arg[2], "set"))
{ // {
zone->pathing->QuickConnect(c, true); // zone->pathing->QuickConnect(c, true);
} // }
else // else
{ // {
zone->pathing->QuickConnect(c, false); // zone->pathing->QuickConnect(c, false);
} // }
} // }
return; // return;
} //}
//
if(!strcasecmp(sep->arg[1], "disconnect")) //if(!strcasecmp(sep->arg[1], "disconnect"))
{ //{
if(zone->pathing) // if(zone->pathing)
{ // {
if(!strcasecmp(sep->arg[2], "all")) // if(!strcasecmp(sep->arg[2], "all"))
{ // {
zone->pathing->DisconnectAll(c); // zone->pathing->DisconnectAll(c);
} // }
else // else
{ // {
zone->pathing->DisconnectNodeToNode(c, atoi(sep->arg[2])); // zone->pathing->DisconnectNodeToNode(c, atoi(sep->arg[2]));
} // }
} // }
return; // return;
} //}
//
//
if(!strcasecmp(sep->arg[1], "move")) //if(!strcasecmp(sep->arg[1], "move"))
{ //{
if(zone->pathing) // if(zone->pathing)
{ // {
zone->pathing->MoveNode(c); // zone->pathing->MoveNode(c);
} // }
return; // return;
} //}
//
if(!strcasecmp(sep->arg[1], "process")) //if(!strcasecmp(sep->arg[1], "process"))
{ //{
if(zone->pathing) // if(zone->pathing)
{ // {
if(sep->arg[2][0] == '\0') // if(sep->arg[2][0] == '\0')
return; // return;
//
zone->pathing->ProcessNodesAndSave(sep->arg[2]); // zone->pathing->ProcessNodesAndSave(sep->arg[2]);
c->Message(0, "Path processed..."); // c->Message(0, "Path processed...");
} // }
return; // return;
} //}
//
if(!strcasecmp(sep->arg[1], "resort")) //if(!strcasecmp(sep->arg[1], "resort"))
{ //{
if(zone->pathing) // if(zone->pathing)
{ // {
if(!strcasecmp(sep->arg[2], "nodes")) // if(!strcasecmp(sep->arg[2], "nodes"))
{ // {
zone->pathing->SortNodes(); // zone->pathing->SortNodes();
c->Message(0, "Nodes resorted..."); // c->Message(0, "Nodes resorted...");
} // }
else // else
{ // {
zone->pathing->ResortConnections(); // zone->pathing->ResortConnections();
c->Message(0, "Connections resorted..."); // c->Message(0, "Connections resorted...");
} // }
} // }
return; // return;
} //}
//
if(!strcasecmp(sep->arg[1], "hazard")) //if(!strcasecmp(sep->arg[1], "hazard"))
{ //{
if(zone->pathing) // if(zone->pathing)
{ // {
if(c && c->GetTarget()) // if(c && c->GetTarget())
{ // {
if (zone->pathing->NoHazardsAccurate(glm::vec3(c->GetX(), c->GetY(), c->GetZ()), // if (zone->pathing->NoHazardsAccurate(glm::vec3(c->GetX(), c->GetY(), c->GetZ()),
glm::vec3(c->GetTarget()->GetX(), c->GetTarget()->GetY(), c->GetTarget()->GetZ()))) // glm::vec3(c->GetTarget()->GetX(), c->GetTarget()->GetY(), c->GetTarget()->GetZ())))
{ // {
c->Message(0, "No hazards."); // c->Message(0, "No hazards.");
} // }
else // else
{ // {
c->Message(0, "Hazard Detected..."); // c->Message(0, "Hazard Detected...");
} // }
} // }
} // }
return; // return;
} //}
//
if(!strcasecmp(sep->arg[1], "print")) //if(!strcasecmp(sep->arg[1], "print"))
{ //{
if(zone->pathing) // if(zone->pathing)
{ // {
zone->pathing->PrintPathing(); // zone->pathing->PrintPathing();
} // }
return; // return;
} //}
//
if(!strcasecmp(sep->arg[1], "showneighbours") || !strcasecmp(sep->arg[1], "showneighbors")) //if(!strcasecmp(sep->arg[1], "showneighbours") || !strcasecmp(sep->arg[1], "showneighbors"))
{ //{
if(!c->GetTarget()) // if(!c->GetTarget())
{ // {
c->Message(0, "First #path shownodes to spawn the pathnodes, and then target one of them."); // c->Message(0, "First #path shownodes to spawn the pathnodes, and then target one of them.");
return; // return;
} // }
if(zone->pathing) // if(zone->pathing)
{ // {
zone->pathing->ShowPathNodeNeighbours(c); // zone->pathing->ShowPathNodeNeighbours(c);
return; // return;
} // }
} //}
if(!strcasecmp(sep->arg[1], "meshtest")) //if(!strcasecmp(sep->arg[1], "meshtest"))
{ //{
if(zone->pathing) // if(zone->pathing)
{ // {
if(!strcasecmp(sep->arg[2], "simple")) // if(!strcasecmp(sep->arg[2], "simple"))
{ // {
c->Message(0, "You may go linkdead. Results will be in the log file."); // c->Message(0, "You may go linkdead. Results will be in the log file.");
zone->pathing->SimpleMeshTest(); // zone->pathing->SimpleMeshTest();
return; // return;
} // }
else // else
{ // {
c->Message(0, "You may go linkdead. Results will be in the log file."); // c->Message(0, "You may go linkdead. Results will be in the log file.");
zone->pathing->MeshTest(); // zone->pathing->MeshTest();
return; // return;
} // }
} // }
} //}
//
if(!strcasecmp(sep->arg[1], "allspawns")) //if(!strcasecmp(sep->arg[1], "allspawns"))
{ //{
if(zone->pathing) // if(zone->pathing)
{ // {
c->Message(0, "You may go linkdead. Results will be in the log file."); // c->Message(0, "You may go linkdead. Results will be in the log file.");
entity_list.FindPathsToAllNPCs(); // entity_list.FindPathsToAllNPCs();
return; // return;
} // }
} //}
//
if(!strcasecmp(sep->arg[1], "nearest")) //if(!strcasecmp(sep->arg[1], "nearest"))
{ //{
if(!c->GetTarget() || !c->GetTarget()->IsMob()) // if(!c->GetTarget() || !c->GetTarget()->IsMob())
{ // {
c->Message(0, "You must target something."); // c->Message(0, "You must target something.");
return; // return;
} // }
//
if(zone->pathing) // if(zone->pathing)
{ // {
Mob *m = c->GetTarget(); // Mob *m = c->GetTarget();
//
glm::vec3 Position(m->GetX(), m->GetY(), m->GetZ()); // glm::vec3 Position(m->GetX(), m->GetY(), m->GetZ());
//
int Node = zone->pathing->FindNearestPathNode(Position); // int Node = zone->pathing->FindNearestPathNode(Position);
//
if(Node == -1) // if(Node == -1)
c->Message(0, "Unable to locate a path node within range."); // c->Message(0, "Unable to locate a path node within range.");
else // else
c->Message(0, "Nearest path node is %i", Node); // c->Message(0, "Nearest path node is %i", Node);
//
return; // return;
} // }
} //}
//
c->Message(0, "Unknown path command."); //c->Message(0, "Unknown path command.");
} }
void Client::Undye() { void Client::Undye() {

View File

@ -2822,26 +2822,6 @@ void EntityList::ListPlayerCorpses(Client *client)
client->Message(0, "%d player corpses listed.", x); client->Message(0, "%d player corpses listed.", x);
} }
void EntityList::FindPathsToAllNPCs()
{
if (!zone->pathing)
return;
auto it = npc_list.begin();
while (it != npc_list.end()) {
glm::vec3 Node0 = zone->pathing->GetPathNodeCoordinates(0, false);
glm::vec3 Dest(it->second->GetX(), it->second->GetY(), it->second->GetZ());
std::deque<int> Route = zone->pathing->FindRoute(Node0, Dest);
if (Route.empty())
printf("Unable to find a route to %s\n", it->second->GetName());
else
printf("Found a route to %s\n", it->second->GetName());
++it;
}
fflush(stdout);
}
// returns the number of corpses deleted. A negative number indicates an error code. // returns the number of corpses deleted. A negative number indicates an error code.
int32 EntityList::DeleteNPCCorpses() int32 EntityList::DeleteNPCCorpses()
{ {

View File

@ -383,7 +383,6 @@ public:
void ListNPCs(Client* client, const char* arg1 = 0, const char* arg2 = 0, uint8 searchtype = 0); void ListNPCs(Client* client, const char* arg1 = 0, const char* arg2 = 0, uint8 searchtype = 0);
void ListNPCCorpses(Client* client); void ListNPCCorpses(Client* client);
void ListPlayerCorpses(Client* client); void ListPlayerCorpses(Client* client);
void FindPathsToAllNPCs();
int32 DeleteNPCCorpses(); int32 DeleteNPCCorpses();
int32 DeletePlayerCorpses(); int32 DeletePlayerCorpses();
void CorpseFix(Client* c); void CorpseFix(Client* c);

View File

@ -130,23 +130,25 @@ void Mob::CalculateNewFearpoint()
{ {
if(RuleB(Pathing, Fear) && zone->pathing) if(RuleB(Pathing, Fear) && zone->pathing)
{ {
int Node = zone->pathing->GetRandomPathNode(); auto Node = zone->pathing->GetRandomLocation();
if (Node.x != 0.0f || Node.y != 0.0f || Node.z != 0.0f) {
glm::vec3 Loc = zone->pathing->GetPathNodeCoordinates(Node); ++Node.z;
++Loc.z; glm::vec3 CurrentPosition(GetX(), GetY(), GetZ());
glm::vec3 CurrentPosition(GetX(), GetY(), GetZ()); auto Route = zone->pathing->FindRoute(CurrentPosition, Node);
std::deque<int> Route = zone->pathing->FindRoute(CurrentPosition, Loc); if (!Route.empty())
{
auto first = (*Route.begin());
m_FearWalkTarget = glm::vec3(first.x, first.y, first.z);
currently_fleeing = true;
if(!Route.empty()) Log(Logs::Detail, Logs::None, "Feared to node %i (%8.3f, %8.3f, %8.3f)", Node, first.x, first.y, first.z);
{ return;
m_FearWalkTarget = glm::vec3(Loc.x, Loc.y, Loc.z); }
currently_fleeing = true;
Log(Logs::Detail, Logs::None, "Feared to node %i (%8.3f, %8.3f, %8.3f)", Node, Loc.x, Loc.y, Loc.z);
return;
} }
Log(Logs::Detail, Logs::None, "No path found to selected node. Falling through to old fear point selection."); Log(Logs::Detail, Logs::None, "No path found to selected node. Falling through to old fear point selection.");
@ -171,6 +173,7 @@ void Mob::CalculateNewFearpoint()
break; break;
} }
} }
if (currently_fleeing) if (currently_fleeing)
m_FearWalkTarget = glm::vec3(ranx, rany, ranz); m_FearWalkTarget = glm::vec3(ranx, rany, ranz);
else //Break fear else //Break fear

View File

@ -1125,17 +1125,6 @@ bool Lua_Mob::CalculateNewPosition(double x, double y, double z, double speed, b
check_z); check_z);
} }
bool Lua_Mob::CalculateNewPosition2(double x, double y, double z, double speed) {
Lua_Safe_Call_Bool();
return self->CalculateNewPosition2(static_cast<float>(x), static_cast<float>(y), static_cast<float>(z), static_cast<float>(speed));
}
bool Lua_Mob::CalculateNewPosition2(double x, double y, double z, double speed, bool check_z) {
Lua_Safe_Call_Bool();
return self->CalculateNewPosition2(static_cast<float>(x), static_cast<float>(y), static_cast<float>(z), static_cast<float>(speed),
check_z);
}
float Lua_Mob::CalculateDistance(double x, double y, double z) { float Lua_Mob::CalculateDistance(double x, double y, double z) {
Lua_Safe_Call_Real(); Lua_Safe_Call_Real();
return self->CalculateDistance(static_cast<float>(x), static_cast<float>(y), static_cast<float>(z)); return self->CalculateDistance(static_cast<float>(x), static_cast<float>(y), static_cast<float>(z));
@ -2287,8 +2276,6 @@ luabind::scope lua_register_mob() {
.def("CalculateHeadingToTarget", (double(Lua_Mob::*)(double,double))&Lua_Mob::CalculateHeadingToTarget) .def("CalculateHeadingToTarget", (double(Lua_Mob::*)(double,double))&Lua_Mob::CalculateHeadingToTarget)
.def("CalculateNewPosition", (bool(Lua_Mob::*)(double,double,double,double))&Lua_Mob::CalculateNewPosition) .def("CalculateNewPosition", (bool(Lua_Mob::*)(double,double,double,double))&Lua_Mob::CalculateNewPosition)
.def("CalculateNewPosition", (bool(Lua_Mob::*)(double,double,double,double,bool))&Lua_Mob::CalculateNewPosition) .def("CalculateNewPosition", (bool(Lua_Mob::*)(double,double,double,double,bool))&Lua_Mob::CalculateNewPosition)
.def("CalculateNewPosition2", (bool(Lua_Mob::*)(double,double,double,double))&Lua_Mob::CalculateNewPosition2)
.def("CalculateNewPosition2", (bool(Lua_Mob::*)(double,double,double,double,bool))&Lua_Mob::CalculateNewPosition2)
.def("CalculateDistance", (float(Lua_Mob::*)(double,double,double))&Lua_Mob::CalculateDistance) .def("CalculateDistance", (float(Lua_Mob::*)(double,double,double))&Lua_Mob::CalculateDistance)
.def("SendTo", (void(Lua_Mob::*)(double,double,double))&Lua_Mob::SendTo) .def("SendTo", (void(Lua_Mob::*)(double,double,double))&Lua_Mob::SendTo)
.def("SendToFixZ", (void(Lua_Mob::*)(double,double,double))&Lua_Mob::SendToFixZ) .def("SendToFixZ", (void(Lua_Mob::*)(double,double,double))&Lua_Mob::SendToFixZ)

View File

@ -240,8 +240,6 @@ public:
double CalculateHeadingToTarget(double in_x, double in_y); double CalculateHeadingToTarget(double in_x, double in_y);
bool CalculateNewPosition(double x, double y, double z, double speed); bool CalculateNewPosition(double x, double y, double z, double speed);
bool CalculateNewPosition(double x, double y, double z, double speed, bool check_z); bool CalculateNewPosition(double x, double y, double z, double speed, bool check_z);
bool CalculateNewPosition2(double x, double y, double z, double speed);
bool CalculateNewPosition2(double x, double y, double z, double speed, bool check_z);
float CalculateDistance(double x, double y, double z); float CalculateDistance(double x, double y, double z);
void SendTo(double x, double y, double z); void SendTo(double x, double y, double z);
void SendToFixZ(double x, double y, double z); void SendToFixZ(double x, double y, double z);

View File

@ -1487,12 +1487,12 @@ void Merc::AI_Process() {
if (WaypointChanged) if (WaypointChanged)
tar_ndx = 20; tar_ndx = 20;
CalculateNewPosition2(Goal.x, Goal.y, Goal.z, GetRunspeed()); CalculateNewPosition(Goal.x, Goal.y, Goal.z, GetRunspeed());
} }
else { else {
Mob* follow = entity_list.GetMob(GetFollowID()); Mob* follow = entity_list.GetMob(GetFollowID());
if (follow) if (follow)
CalculateNewPosition2(follow->GetX(), follow->GetY(), follow->GetZ(), GetRunspeed()); CalculateNewPosition(follow->GetX(), follow->GetY(), follow->GetZ(), GetRunspeed());
} }
return; return;
@ -1559,7 +1559,7 @@ void Merc::AI_Process() {
float newZ = 0; float newZ = 0;
FaceTarget(GetTarget()); FaceTarget(GetTarget());
if (PlotPositionAroundTarget(this, newX, newY, newZ)) { if (PlotPositionAroundTarget(this, newX, newY, newZ)) {
CalculateNewPosition2(newX, newY, newZ, GetRunspeed()); CalculateNewPosition(newX, newY, newZ, GetRunspeed());
return; return;
} }
} }
@ -1571,7 +1571,7 @@ void Merc::AI_Process() {
float newY = 0; float newY = 0;
float newZ = 0; float newZ = 0;
if (PlotPositionAroundTarget(GetTarget(), newX, newY, newZ)) { if (PlotPositionAroundTarget(GetTarget(), newX, newY, newZ)) {
CalculateNewPosition2(newX, newY, newZ, GetRunspeed()); CalculateNewPosition(newX, newY, newZ, GetRunspeed());
return; return;
} }
} }
@ -1582,7 +1582,7 @@ void Merc::AI_Process() {
float newY = 0; float newY = 0;
float newZ = 0; float newZ = 0;
if (PlotPositionAroundTarget(GetTarget(), newX, newY, newZ, false) && GetArchetype() != ARCHETYPE_CASTER) { if (PlotPositionAroundTarget(GetTarget(), newX, newY, newZ, false) && GetArchetype() != ARCHETYPE_CASTER) {
CalculateNewPosition2(newX, newY, newZ, GetRunspeed()); CalculateNewPosition(newX, newY, newZ, GetRunspeed());
return; return;
} }
} }
@ -1709,7 +1709,7 @@ void Merc::AI_Process() {
{ {
if(!IsRooted()) { if(!IsRooted()) {
Log(Logs::Detail, Logs::AI, "Pursuing %s while engaged.", GetTarget()->GetCleanName()); Log(Logs::Detail, Logs::AI, "Pursuing %s while engaged.", GetTarget()->GetCleanName());
CalculateNewPosition2(GetTarget()->GetX(), GetTarget()->GetY(), GetTarget()->GetZ(), GetRunspeed()); CalculateNewPosition(GetTarget()->GetX(), GetTarget()->GetY(), GetTarget()->GetZ(), GetRunspeed());
return; return;
} }
@ -1781,10 +1781,10 @@ void Merc::AI_Process() {
if (WaypointChanged) if (WaypointChanged)
tar_ndx = 20; tar_ndx = 20;
CalculateNewPosition2(Goal.x, Goal.y, Goal.z, speed); CalculateNewPosition(Goal.x, Goal.y, Goal.z, speed);
} }
else { else {
CalculateNewPosition2(follow->GetX(), follow->GetY(), follow->GetZ(), speed); CalculateNewPosition(follow->GetX(), follow->GetY(), follow->GetZ(), speed);
} }
if (rest_timer.Enabled()) if (rest_timer.Enabled())

View File

@ -430,15 +430,7 @@ Mob::Mob(const char* in_name,
m_TargetRing = glm::vec3(); m_TargetRing = glm::vec3();
flymode = FlyMode3; flymode = FlyMode3;
// Pathing
PathingLOSState = UnknownLOS;
PathingLoopCount = 0;
PathingLastNodeVisited = -1;
PathingLOSCheckTimer = new Timer(RuleI(Pathing, LOSCheckFrequency));
PathingRouteUpdateTimerShort = new Timer(RuleI(Pathing, RouteUpdateFrequencyShort));
PathingRouteUpdateTimerLong = new Timer(RuleI(Pathing, RouteUpdateFrequencyLong));
DistractedFromGrid = false; DistractedFromGrid = false;
PathingTraversedNodes = 0;
hate_list.SetHateOwner(this); hate_list.SetHateOwner(this);
m_AllowBeneficial = false; m_AllowBeneficial = false;
@ -485,9 +477,6 @@ Mob::~Mob()
entity_list.DestroyTempPets(this); entity_list.DestroyTempPets(this);
} }
entity_list.UnMarkNPC(GetID()); entity_list.UnMarkNPC(GetID());
safe_delete(PathingLOSCheckTimer);
safe_delete(PathingRouteUpdateTimerShort);
safe_delete(PathingRouteUpdateTimerLong);
UninitializeBuffSlots(); UninitializeBuffSlots();
#ifdef BOTS #ifdef BOTS
@ -1642,7 +1631,6 @@ void Mob::ShowBuffList(Client* client) {
} }
void Mob::GMMove(float x, float y, float z, float heading, bool SendUpdate) { void Mob::GMMove(float x, float y, float z, float heading, bool SendUpdate) {
Route.clear(); Route.clear();
if(IsNPC()) { if(IsNPC()) {

View File

@ -21,7 +21,7 @@
#include "common.h" #include "common.h"
#include "entity.h" #include "entity.h"
#include "hate_list.h" #include "hate_list.h"
#include "pathing.h" #include "pathfinder_interface.h"
#include "position.h" #include "position.h"
#include "aa_ability.h" #include "aa_ability.h"
#include "aa.h" #include "aa.h"
@ -908,8 +908,7 @@ public:
inline bool CheckAggro(Mob* other) {return hate_list.IsEntOnHateList(other);} inline bool CheckAggro(Mob* other) {return hate_list.IsEntOnHateList(other);}
float CalculateHeadingToTarget(float in_x, float in_y); float CalculateHeadingToTarget(float in_x, float in_y);
bool CalculateNewPosition(float x, float y, float z, int speed, bool checkZ = false, bool calcheading = true); virtual bool CalculateNewPosition(float x, float y, float z, int speed, bool checkZ = true, bool calcheading = true);
virtual bool CalculateNewPosition2(float x, float y, float z, int speed, bool checkZ = true, bool calcheading = true);
float CalculateDistance(float x, float y, float z); float CalculateDistance(float x, float y, float z);
float GetGroundZ(float new_x, float new_y, float z_offset=0.0); float GetGroundZ(float new_x, float new_y, float z_offset=0.0);
void SendTo(float new_x, float new_y, float new_z); void SendTo(float new_x, float new_y, float new_z);
@ -1410,16 +1409,8 @@ protected:
// Pathing // Pathing
// //
glm::vec3 PathingDestination; glm::vec3 PathingDestination;
glm::vec3 PathingLastPosition; IPathfinder::IPath Route;
int PathingLoopCount;
int PathingLastNodeVisited;
std::deque<int> Route;
LOSType PathingLOSState;
Timer *PathingLOSCheckTimer;
Timer *PathingRouteUpdateTimerShort;
Timer *PathingRouteUpdateTimerLong;
bool DistractedFromGrid; bool DistractedFromGrid;
int PathingTraversedNodes;
uint32 pDontHealMeBefore; uint32 pDontHealMeBefore;
uint32 pDontBuffMeBefore; uint32 pDontBuffMeBefore;

View File

@ -563,10 +563,6 @@ void Client::AI_Stop() {
// only call this on a zone shutdown event // only call this on a zone shutdown event
void Mob::AI_ShutDown() { void Mob::AI_ShutDown() {
safe_delete(PathingLOSCheckTimer);
safe_delete(PathingRouteUpdateTimerShort);
safe_delete(PathingRouteUpdateTimerLong);
attack_timer.Disable(); attack_timer.Disable();
attack_dw_timer.Disable(); attack_dw_timer.Disable();
ranged_timer.Disable(); ranged_timer.Disable();
@ -770,7 +766,7 @@ void Client::AI_Process()
CalculateNewFearpoint(); CalculateNewFearpoint();
} }
if(!RuleB(Pathing, Fear) || !zone->pathing) if(!RuleB(Pathing, Fear) || !zone->pathing)
CalculateNewPosition2(m_FearWalkTarget.x, m_FearWalkTarget.y, m_FearWalkTarget.z, speed, true); CalculateNewPosition(m_FearWalkTarget.x, m_FearWalkTarget.y, m_FearWalkTarget.z, speed, true);
else else
{ {
bool WaypointChanged, NodeReached; bool WaypointChanged, NodeReached;
@ -781,7 +777,7 @@ void Client::AI_Process()
if(WaypointChanged) if(WaypointChanged)
tar_ndx = 20; tar_ndx = 20;
CalculateNewPosition2(Goal.x, Goal.y, Goal.z, speed); CalculateNewPosition(Goal.x, Goal.y, Goal.z, speed);
} }
} }
return; return;
@ -853,7 +849,7 @@ void Client::AI_Process()
newspeed *= 2; newspeed *= 2;
SetCurrentSpeed(newspeed); SetCurrentSpeed(newspeed);
if(!RuleB(Pathing, Aggro) || !zone->pathing) if(!RuleB(Pathing, Aggro) || !zone->pathing)
CalculateNewPosition2(GetTarget()->GetX(), GetTarget()->GetY(), GetTarget()->GetZ(), newspeed); CalculateNewPosition(GetTarget()->GetX(), GetTarget()->GetY(), GetTarget()->GetZ(), newspeed);
else else
{ {
bool WaypointChanged, NodeReached; bool WaypointChanged, NodeReached;
@ -863,7 +859,7 @@ void Client::AI_Process()
if(WaypointChanged) if(WaypointChanged)
tar_ndx = 20; tar_ndx = 20;
CalculateNewPosition2(Goal.x, Goal.y, Goal.z, newspeed); CalculateNewPosition(Goal.x, Goal.y, Goal.z, newspeed);
} }
} }
} }
@ -912,7 +908,7 @@ void Client::AI_Process()
nspeed *= 2; nspeed *= 2;
SetCurrentSpeed(nspeed); SetCurrentSpeed(nspeed);
CalculateNewPosition2(owner->GetX(), owner->GetY(), owner->GetZ(), nspeed); CalculateNewPosition(owner->GetX(), owner->GetY(), owner->GetZ(), nspeed);
} }
} }
else else
@ -969,7 +965,7 @@ void Mob::AI_Process() {
} }
if(!RuleB(Pathing, Fear) || !zone->pathing) if(!RuleB(Pathing, Fear) || !zone->pathing)
{ {
CalculateNewPosition2(m_FearWalkTarget.x, m_FearWalkTarget.y, m_FearWalkTarget.z, GetFearSpeed(), true); CalculateNewPosition(m_FearWalkTarget.x, m_FearWalkTarget.y, m_FearWalkTarget.z, GetFearSpeed(), true);
} }
else else
{ {
@ -981,7 +977,7 @@ void Mob::AI_Process() {
if(WaypointChanged) if(WaypointChanged)
tar_ndx = 20; tar_ndx = 20;
CalculateNewPosition2(Goal.x, Goal.y, Goal.z, GetFearSpeed()); CalculateNewPosition(Goal.x, Goal.y, Goal.z, GetFearSpeed());
} }
} }
return; return;
@ -1300,7 +1296,7 @@ void Mob::AI_Process() {
if (!IsRooted()) { if (!IsRooted()) {
Log(Logs::Detail, Logs::AI, "Pursuing %s while engaged.", target->GetName()); Log(Logs::Detail, Logs::AI, "Pursuing %s while engaged.", target->GetName());
if (!RuleB(Pathing, Aggro) || !zone->pathing) if (!RuleB(Pathing, Aggro) || !zone->pathing)
CalculateNewPosition2(target->GetX(), target->GetY(), target->GetZ(), GetRunspeed()); CalculateNewPosition(target->GetX(), target->GetY(), target->GetZ(), GetRunspeed());
else else
{ {
bool WaypointChanged, NodeReached; bool WaypointChanged, NodeReached;
@ -1311,7 +1307,7 @@ void Mob::AI_Process() {
if (WaypointChanged) if (WaypointChanged)
tar_ndx = 20; tar_ndx = 20;
CalculateNewPosition2(Goal.x, Goal.y, Goal.z, GetRunspeed()); CalculateNewPosition(Goal.x, Goal.y, Goal.z, GetRunspeed());
} }
} }
@ -1395,7 +1391,7 @@ void Mob::AI_Process() {
if (dist >= 5625) if (dist >= 5625)
speed = GetRunspeed(); speed = GetRunspeed();
CalculateNewPosition2(owner->GetX(), owner->GetY(), owner->GetZ(), speed); CalculateNewPosition(owner->GetX(), owner->GetY(), owner->GetZ(), speed);
} }
else else
{ {
@ -1454,7 +1450,7 @@ void Mob::AI_Process() {
int speed = GetWalkspeed(); int speed = GetWalkspeed();
if (dist2 >= followdist + 150) if (dist2 >= followdist + 150)
speed = GetRunspeed(); speed = GetRunspeed();
CalculateNewPosition2(follow->GetX(), follow->GetY(), follow->GetZ(), speed); CalculateNewPosition(follow->GetX(), follow->GetY(), follow->GetZ(), speed);
} }
else else
{ {
@ -1536,7 +1532,7 @@ void NPC::AI_DoMovement() {
Log(Logs::Detail, Logs::AI, "Roam Box: d=%.3f (%.3f->%.3f,%.3f->%.3f): Go To (%.3f,%.3f)", Log(Logs::Detail, Logs::AI, "Roam Box: d=%.3f (%.3f->%.3f,%.3f->%.3f): Go To (%.3f,%.3f)",
roambox_distance, roambox_min_x, roambox_max_x, roambox_min_y, roambox_max_y, roambox_movingto_x, roambox_movingto_y); roambox_distance, roambox_min_x, roambox_max_x, roambox_min_y, roambox_max_y, roambox_movingto_x, roambox_movingto_y);
if (!CalculateNewPosition2(roambox_movingto_x, roambox_movingto_y, GetZ(), walksp, true)) if (!CalculateNewPosition(roambox_movingto_x, roambox_movingto_y, GetZ(), walksp, true))
{ {
roambox_movingto_x = roambox_max_x + 1; // force update roambox_movingto_x = roambox_max_x + 1; // force update
pLastFightingDelayMoving = Timer::GetCurrentTime() + RandomTimer(roambox_min_delay, roambox_delay); pLastFightingDelayMoving = Timer::GetCurrentTime() + RandomTimer(roambox_min_delay, roambox_delay);
@ -1593,7 +1589,7 @@ void NPC::AI_DoMovement() {
if (doMove) if (doMove)
{ // not at waypoint yet or at 0 pause WP, so keep moving { // not at waypoint yet or at 0 pause WP, so keep moving
if(!RuleB(Pathing, AggroReturnToGrid) || !zone->pathing || (DistractedFromGrid == 0)) if(!RuleB(Pathing, AggroReturnToGrid) || !zone->pathing || (DistractedFromGrid == 0))
CalculateNewPosition2(m_CurrentWayPoint.x, m_CurrentWayPoint.y, m_CurrentWayPoint.z, walksp, true); CalculateNewPosition(m_CurrentWayPoint.x, m_CurrentWayPoint.y, m_CurrentWayPoint.z, walksp, true);
else else
{ {
bool WaypointChanged; bool WaypointChanged;
@ -1605,13 +1601,13 @@ void NPC::AI_DoMovement() {
if(NodeReached) if(NodeReached)
entity_list.OpenDoorsNear(CastToNPC()); entity_list.OpenDoorsNear(CastToNPC());
CalculateNewPosition2(Goal.x, Goal.y, Goal.z, walksp, true); CalculateNewPosition(Goal.x, Goal.y, Goal.z, walksp, true);
} }
} }
} }
} // endif (gridno > 0) } // endif (gridno > 0)
// handle new quest grid command processing // handle new quest grid command processing
else if (gridno < 0) else if (gridno < 0)
{ // this mob is under quest control { // this mob is under quest control
if (movetimercompleted==true) if (movetimercompleted==true)
@ -1630,7 +1626,7 @@ void NPC::AI_DoMovement() {
{ {
bool CP2Moved; bool CP2Moved;
if(!RuleB(Pathing, Guard) || !zone->pathing) if(!RuleB(Pathing, Guard) || !zone->pathing)
CP2Moved = CalculateNewPosition2(m_GuardPoint.x, m_GuardPoint.y, m_GuardPoint.z, walksp); CP2Moved = CalculateNewPosition(m_GuardPoint.x, m_GuardPoint.y, m_GuardPoint.z, walksp);
else else
{ {
if(!((m_Position.x == m_GuardPoint.x) && (m_Position.y == m_GuardPoint.y) && (m_Position.z == m_GuardPoint.z))) if(!((m_Position.x == m_GuardPoint.x) && (m_Position.y == m_GuardPoint.y) && (m_Position.z == m_GuardPoint.z)))
@ -1643,7 +1639,7 @@ void NPC::AI_DoMovement() {
if(NodeReached) if(NodeReached)
entity_list.OpenDoorsNear(CastToNPC()); entity_list.OpenDoorsNear(CastToNPC());
CP2Moved = CalculateNewPosition2(Goal.x, Goal.y, Goal.z, walksp); CP2Moved = CalculateNewPosition(Goal.x, Goal.y, Goal.z, walksp);
} }
else else
CP2Moved = false; CP2Moved = false;

View File

@ -0,0 +1,7 @@
#include "pathfinder_null.h"
#include "pathfinder_nav_mesh.h"
#include "pathfinder_waypoint.h"
IPathfinder *IPathfinder::Load(const std::string &zone) {
return new PathfinderNull();
}

View File

@ -0,0 +1,18 @@
#pragma once
#include "map.h"
#include <list>
class IPathfinder
{
public:
typedef std::list<glm::vec3> IPath;
IPathfinder() { }
virtual ~IPathfinder() { }
virtual IPath FindRoute(const glm::vec3 &start, const glm::vec3 &end) = 0;
virtual glm::vec3 GetRandomLocation() = 0;
static IPathfinder *Load(const std::string &zone);
};

View File

@ -0,0 +1,3 @@
#pragma once
#include "pathfinder_interface.h"

15
zone/pathfinder_null.cpp Normal file
View File

@ -0,0 +1,15 @@
#include "pathfinder_null.h"
#pragma once
IPathfinder::IPath PathfinderNull::FindRoute(const glm::vec3 &start, const glm::vec3 &end)
{
IPath ret;
ret.push_back(start);
ret.push_back(end);
return ret;
}
glm::vec3 PathfinderNull::GetRandomLocation()
{
return glm::vec3();
}

13
zone/pathfinder_null.h Normal file
View File

@ -0,0 +1,13 @@
#pragma once
#include "pathfinder_interface.h"
class PathfinderNull : public IPathfinder
{
public:
PathfinderNull() { }
virtual ~PathfinderNull() { }
virtual IPath FindRoute(const glm::vec3 &start, const glm::vec3 &end);
virtual glm::vec3 GetRandomLocation();
};

View File

@ -0,0 +1,13 @@
#pragma once
#include "pathfinder_interface.h"
class PathfinderWaypoint : public IPathfinder
{
public:
PathfinderWaypoint() { }
virtual ~PathfinderWaypoint() { }
virtual IPath FindRoute(const glm::vec3 &start, const glm::vec3 &end);
virtual glm::vec3 GetRandomLocation();
};

View File

@ -467,7 +467,7 @@ std::deque<int> PathManager::FindRoute(glm::vec3 Start, glm::vec3 End)
break; break;
if(!zone->zonemap->LineIntersectsZone(Start, PathNodes[(*Second)].v, 1.0f, nullptr) if(!zone->zonemap->LineIntersectsZone(Start, PathNodes[(*Second)].v, 1.0f, nullptr)
&& zone->pathing->NoHazards(Start, PathNodes[(*Second)].v)) && NoHazards(Start, PathNodes[(*Second)].v))
{ {
noderoute.erase(First); noderoute.erase(First);
@ -500,7 +500,7 @@ std::deque<int> PathManager::FindRoute(glm::vec3 Start, glm::vec3 End)
break; break;
if(!zone->zonemap->LineIntersectsZone(End, PathNodes[(*Second)].v, 1.0f, nullptr) if(!zone->zonemap->LineIntersectsZone(End, PathNodes[(*Second)].v, 1.0f, nullptr)
&& zone->pathing->NoHazards(End, PathNodes[(*Second)].v)) && NoHazards(End, PathNodes[(*Second)].v))
{ {
noderoute.erase(First); noderoute.erase(First);
@ -644,439 +644,62 @@ void PathManager::SimpleMeshTest()
glm::vec3 Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &WaypointChanged, bool &NodeReached) glm::vec3 Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &WaypointChanged, bool &NodeReached)
{ {
WaypointChanged = false; glm::vec3 To(ToX, ToY, ToZ);
if (Speed <= 0) {
NodeReached = false; return To;
}
glm::vec3 NodeLoc;
glm::vec3 From(GetX(), GetY(), GetZ()); glm::vec3 From(GetX(), GetY(), GetZ());
glm::vec3 HeadPosition(From.x, From.y, From.z + (GetSize() < 6.0 ? 6 : GetSize()) * HEAD_POSITION); if (DistanceSquared(To, From) < 1.0f) {
WaypointChanged = false;
glm::vec3 To(ToX, ToY, ToZ); NodeReached = true;
Route.clear();
bool SameDestination = (To == PathingDestination);
if (Speed <= 0) // our speed is 0, we cant move so lets return the dest
return To; // this will also avoid the teleports cleanly
int NextNode;
if(To == From)
return To; return To;
}
Log(Logs::Detail, Logs::None, "UpdatePath. From(%8.3f, %8.3f, %8.3f) To(%8.3f, %8.3f, %8.3f)", From.x, From.y, From.z, To.x, To.y, To.z); if (Route.empty()) {
Route = zone->pathing->FindRoute(From, To);
if(From == PathingLastPosition) PathingDestination = To;
{ WaypointChanged = true;
++PathingLoopCount; NodeReached = false;
return *Route.begin();
if((PathingLoopCount > 5) && !IsRooted()) }
{ else {
Log(Logs::Detail, Logs::None, "appears to be stuck. Teleporting them to next position.", GetName()); bool SameDestination = DistanceSquared(To, PathingDestination) < 1.0f;
if (!SameDestination) {
if(Route.empty()) //We had a route but our target position moved too much
{ Route = zone->pathing->FindRoute(From, To);
Teleport(To); PathingDestination = To;
WaypointChanged = true;
PathingLoopCount = 0;
return To;
}
NodeLoc = zone->pathing->GetPathNodeCoordinates(Route.front());
Route.pop_front();
++PathingTraversedNodes;
Teleport(NodeLoc);
WaypointChanged = true; WaypointChanged = true;
NodeReached = false;
PathingLoopCount = 0; return *Route.begin();
return NodeLoc;
} }
} else {
else bool AtNextNode = DistanceSquared(From, *Route.begin()) < 1.0f;
{ if (AtNextNode) {
PathingLoopCount = 0; WaypointChanged = false;
PathingLastPosition = From;
}
if(!Route.empty())
{
// If we are already pathing, and the destination is the same as before ...
if(SameDestination)
{
Log(Logs::Detail, Logs::None, " Still pathing to the same destination.");
// Get the coordinates of the first path node we are going to.
NextNode = Route.front();
NodeLoc = zone->pathing->GetPathNodeCoordinates(NextNode);
// May need to refine this as rounding errors may mean we never have equality
// We have reached the path node.
if(NodeLoc == From)
{
Log(Logs::Detail, Logs::None, " Arrived at node %i", NextNode);
NodeReached = true; NodeReached = true;
PathingLastNodeVisited = Route.front();
// We only check for LOS again after traversing more than 1 node, otherwise we can get into
// a loop where we have a hazard and so run to a path node far enough away from the hazard, and
// then run right back towards the same hazard again.
//
// An exception is when we are about to head for the last node. We always check LOS then. This
// is because we are seeking a path to the node nearest to our target. This node may be behind the
// target, and we may run past the target if we don't check LOS at this point.
int RouteSize = Route.size();
Log(Logs::Detail, Logs::None, "Route size is %i", RouteSize);
if((RouteSize == 2)
|| ((PathingTraversedNodes >= RuleI(Pathing, MinNodesTraversedForLOSCheck))
&& (RouteSize <= RuleI(Pathing, MinNodesLeftForLOSCheck))
&& PathingLOSCheckTimer->Check()))
{
Log(Logs::Detail, Logs::None, " Checking distance to target.");
float Distance = VectorDistanceNoRoot(From, To);
Log(Logs::Detail, Logs::None, " Distance between From and To (NoRoot) is %8.3f", Distance);
if ((Distance <= RuleR(Pathing, MinDistanceForLOSCheckShort)) &&
(std::abs(From.z - To.z) <= RuleR(Pathing, ZDiffThresholdNew))) {
if(!zone->zonemap->LineIntersectsZone(HeadPosition, To, 1.0f, nullptr))
PathingLOSState = HaveLOS;
else
PathingLOSState = NoLOS;
Log(Logs::Detail, Logs::None, "NoLOS");
if((PathingLOSState == HaveLOS) && zone->pathing->NoHazards(From, To))
{
Log(Logs::Detail, Logs::None, " No hazards. Running directly to target.");
Route.clear();
return To;
}
else
{
Log(Logs::Detail, Logs::None, " Continuing on node path.");
}
}
else
PathingLOSState = UnknownLOS;
}
// We are on the same route, no LOS (or not checking this time, so pop off the node we just reached
//
Route.pop_front(); Route.pop_front();
++PathingTraversedNodes; if (Route.empty()) {
Route = zone->pathing->FindRoute(From, To);
WaypointChanged = true; PathingDestination = To;
// If there are more nodes on the route, return the coords of the next node
if(!Route.empty())
{
NextNode = Route.front();
if(NextNode == -1)
{
// -1 indicates a teleport to the next node
Route.pop_front();
if(Route.empty())
{
Log(Logs::Detail, Logs::None, "Missing node after teleport.");
return To;
}
NextNode = Route.front();
NodeLoc = zone->pathing->GetPathNodeCoordinates(NextNode);
Teleport(NodeLoc);
Log(Logs::Detail, Logs::None, " TELEPORTED to %8.3f, %8.3f, %8.3f\n", NodeLoc.x, NodeLoc.y, NodeLoc.z);
Route.pop_front();
if(Route.empty())
return To;
NextNode = Route.front();
}
zone->pathing->OpenDoors(PathingLastNodeVisited, NextNode, this);
Log(Logs::Detail, Logs::None, " Now moving to node %i", NextNode);
return zone->pathing->GetPathNodeCoordinates(NextNode);
}
else
{
// we have run all the nodes, all that is left is the direct path from the last node
// to the destination
Log(Logs::Detail, Logs::None, " Reached end of node path, running direct to target.");
return To;
}
}
// At this point, we are still on the previous path, but not reached a node yet.
// The route shouldn't be empty, but check anyway.
//
int RouteSize = Route.size();
if((PathingTraversedNodes >= RuleI(Pathing, MinNodesTraversedForLOSCheck))
&& (RouteSize <= RuleI(Pathing, MinNodesLeftForLOSCheck))
&& PathingLOSCheckTimer->Check())
{
Log(Logs::Detail, Logs::None, " Checking distance to target.");
float Distance = VectorDistanceNoRoot(From, To);
Log(Logs::Detail, Logs::None, " Distance between From and To (NoRoot) is %8.3f", Distance);
if ((Distance <= RuleR(Pathing, MinDistanceForLOSCheckShort)) &&
(std::abs(From.z - To.z) <= RuleR(Pathing, ZDiffThresholdNew))) {
if(!zone->zonemap->LineIntersectsZone(HeadPosition, To, 1.0f, nullptr))
PathingLOSState = HaveLOS;
else
PathingLOSState = NoLOS;
Log(Logs::Detail, Logs::None, "NoLOS");
if((PathingLOSState == HaveLOS) && zone->pathing->NoHazards(From, To))
{
Log(Logs::Detail, Logs::None, " No hazards. Running directly to target.");
Route.clear();
return To;
}
else
{
Log(Logs::Detail, Logs::None, " Continuing on node path.");
}
}
else
PathingLOSState = UnknownLOS;
}
return NodeLoc;
}
else
{
// We get here if we were already pathing, but our destination has now changed.
//
Log(Logs::Detail, Logs::None, " Target has changed position.");
// Update our record of where we are going to.
PathingDestination = To;
// Check if we now have LOS etc to the new destination.
if(PathingLOSCheckTimer->Check())
{
float Distance = VectorDistanceNoRoot(From, To);
if ((Distance <= RuleR(Pathing, MinDistanceForLOSCheckShort)) &&
(std::abs(From.z - To.z) <= RuleR(Pathing, ZDiffThresholdNew))) {
Log(Logs::Detail, Logs::None, " Checking for short LOS at distance %8.3f.", Distance);
if(!zone->zonemap->LineIntersectsZone(HeadPosition, To, 1.0f, nullptr))
PathingLOSState = HaveLOS;
else
PathingLOSState = NoLOS;
Log(Logs::Detail, Logs::None, "NoLOS");
if((PathingLOSState == HaveLOS) && zone->pathing->NoHazards(From, To))
{
Log(Logs::Detail, Logs::None, " No hazards. Running directly to target.");
Route.clear();
return To;
}
else
{
Log(Logs::Detail, Logs::None, " Continuing on node path.");
}
}
}
// If the player is moving, we don't want to recalculate our route too frequently.
//
if(static_cast<int>(Route.size()) <= RuleI(Pathing, RouteUpdateFrequencyNodeCount))
{
if(!PathingRouteUpdateTimerShort->Check())
{
Log(Logs::Detail, Logs::None, "Short route update timer not yet expired.");
return zone->pathing->GetPathNodeCoordinates(Route.front());
}
Log(Logs::Detail, Logs::None, "Short route update timer expired.");
}
else
{
if(!PathingRouteUpdateTimerLong->Check())
{
Log(Logs::Detail, Logs::None, "Long route update timer not yet expired.");
return zone->pathing->GetPathNodeCoordinates(Route.front());
}
Log(Logs::Detail, Logs::None, "Long route update timer expired.");
}
// We are already pathing, destination changed, no LOS. Find the nearest node to our destination.
int DestinationPathNode= zone->pathing->FindNearestPathNode(To);
// Destination unreachable via pathing, return direct route.
if(DestinationPathNode == -1)
{
Log(Logs::Detail, Logs::None, " Unable to find path node for new destination. Running straight to target.");
Route.clear();
return To;
}
// If the nearest path node to our new destination is the same as for the previous
// one, we will carry on on our path.
if(DestinationPathNode == Route.back())
{
Log(Logs::Detail, Logs::None, " Same destination Node (%i). Continue with current path.", DestinationPathNode);
NodeLoc = zone->pathing->GetPathNodeCoordinates(Route.front());
// May need to refine this as rounding errors may mean we never have equality
// Check if we have reached a path node.
if(NodeLoc == From)
{
Log(Logs::Detail, Logs::None, " Arrived at node %i, moving to next one.\n", Route.front());
NodeReached = true;
PathingLastNodeVisited = Route.front();
Route.pop_front();
++PathingTraversedNodes;
WaypointChanged = true; WaypointChanged = true;
return *Route.begin();
if(!Route.empty()) }
{ else {
NextNode = Route.front(); return *Route.begin();
if(NextNode == -1)
{
// -1 indicates a teleport to the next node
Route.pop_front();
if(Route.empty())
{
Log(Logs::Detail, Logs::None, "Missing node after teleport.");
return To;
}
NextNode = Route.front();
NodeLoc = zone->pathing->GetPathNodeCoordinates(NextNode);
Teleport(NodeLoc);
Log(Logs::Detail, Logs::None, " TELEPORTED to %8.3f, %8.3f, %8.3f\n", NodeLoc.x, NodeLoc.y, NodeLoc.z);
Route.pop_front();
if(Route.empty())
return To;
NextNode = Route.front();
}
// Return the coords of our next path node on the route.
Log(Logs::Detail, Logs::None, " Now moving to node %i", NextNode);
zone->pathing->OpenDoors(PathingLastNodeVisited, NextNode, this);
return zone->pathing->GetPathNodeCoordinates(NextNode);
}
else
{
Log(Logs::Detail, Logs::None, " Reached end of path grid. Running direct to target.");
return To;
}
} }
return NodeLoc;
} }
else else {
{ WaypointChanged = false;
Log(Logs::Detail, Logs::None, " Target moved. End node is different. Clearing route."); NodeReached = false;
return *Route.begin();
Route.clear();
// We will now fall through to get a new route.
} }
}
}
Log(Logs::Detail, Logs::None, " Our route list is empty.");
if((SameDestination) && !PathingLOSCheckTimer->Check())
{
Log(Logs::Detail, Logs::None, " Destination same as before, LOS check timer not reached. Returning To.");
return To;
}
PathingLOSState = UnknownLOS;
PathingDestination = To;
WaypointChanged = true;
float Distance = VectorDistanceNoRoot(From, To);
if ((Distance <= RuleR(Pathing, MinDistanceForLOSCheckLong)) &&
(std::abs(From.z - To.z) <= RuleR(Pathing, ZDiffThresholdNew))) {
Log(Logs::Detail, Logs::None, " Checking for long LOS at distance %8.3f.", Distance);
if(!zone->zonemap->LineIntersectsZone(HeadPosition, To, 1.0f, nullptr))
PathingLOSState = HaveLOS;
else
PathingLOSState = NoLOS;
Log(Logs::Detail, Logs::None, "NoLOS");
if((PathingLOSState == HaveLOS) && zone->pathing->NoHazards(From, To))
{
Log(Logs::Detail, Logs::None, "Target is reachable. Running directly there.");
return To;
} }
} }
Log(Logs::Detail, Logs::None, " Calculating new route to target.");
Route = zone->pathing->FindRoute(From, To);
PathingTraversedNodes = 0;
if(Route.empty())
{
Log(Logs::Detail, Logs::None, " No route available, running direct.");
return To;
}
if(SameDestination && (Route.front() == PathingLastNodeVisited))
{
Log(Logs::Detail, Logs::None, " Probable loop detected. Same destination and Route.front() == PathingLastNodeVisited.");
Route.clear();
return To;
}
NodeLoc = zone->pathing->GetPathNodeCoordinates(Route.front());
Log(Logs::Detail, Logs::None, " New route determined, heading for node %i", Route.front());
PathingLoopCount = 0;
return NodeLoc;
} }
int PathManager::FindNearestPathNode(glm::vec3 Position) int PathManager::FindNearestPathNode(glm::vec3 Position)
@ -1254,14 +877,14 @@ bool PathManager::NoHazardsAccurate(glm::vec3 From, glm::vec3 To)
void Mob::PrintRoute() void Mob::PrintRoute()
{ {
printf("Route is : "); //printf("Route is : ");
//
for(auto Iterator = Route.begin(); Iterator !=Route.end(); ++Iterator) //for(auto Iterator = Route.begin(); Iterator !=Route.end(); ++Iterator)
{ //{
printf("%i, ", (*Iterator)); // printf("%i, ", (*Iterator));
} //}
//
printf("\n"); //printf("\n");
} }
@ -1346,7 +969,7 @@ void PathManager::ShowPathNodeNeighbours(Client *c)
return; return;
PathNode *Node = zone->pathing->FindPathNodeByCoordinates(c->GetTarget()->GetX(), c->GetTarget()->GetY(), c->GetTarget()->GetZ()); PathNode *Node = FindPathNodeByCoordinates(c->GetTarget()->GetX(), c->GetTarget()->GetY(), c->GetTarget()->GetZ());
if(!Node) if(!Node)
{ {
@ -1412,7 +1035,7 @@ void PathManager::NodeInfo(Client *c)
return; return;
} }
PathNode *Node = zone->pathing->FindPathNodeByCoordinates(c->GetTarget()->GetX(), c->GetTarget()->GetY(), c->GetTarget()->GetZ()); PathNode *Node = FindPathNodeByCoordinates(c->GetTarget()->GetX(), c->GetTarget()->GetY(), c->GetTarget()->GetZ());
if(!Node) if(!Node)
{ {
return; return;
@ -1661,7 +1284,7 @@ bool PathManager::DeleteNode(Client *c)
return false; return false;
} }
PathNode *Node = zone->pathing->FindPathNodeByCoordinates(c->GetTarget()->GetX(), c->GetTarget()->GetY(), c->GetTarget()->GetZ()); PathNode *Node = FindPathNodeByCoordinates(c->GetTarget()->GetX(), c->GetTarget()->GetY(), c->GetTarget()->GetZ());
if(!Node) if(!Node)
{ {
return false; return false;
@ -1742,7 +1365,7 @@ void PathManager::ConnectNodeToNode(Client *c, int32 Node2, int32 teleport, int3
return; return;
} }
PathNode *Node = zone->pathing->FindPathNodeByCoordinates(c->GetTarget()->GetX(), c->GetTarget()->GetY(), c->GetTarget()->GetZ()); PathNode *Node = FindPathNodeByCoordinates(c->GetTarget()->GetX(), c->GetTarget()->GetY(), c->GetTarget()->GetZ());
if(!Node) if(!Node)
{ {
return; return;
@ -1832,7 +1455,7 @@ void PathManager::ConnectNode(Client *c, int32 Node2, int32 teleport, int32 door
return; return;
} }
PathNode *Node = zone->pathing->FindPathNodeByCoordinates(c->GetTarget()->GetX(), c->GetTarget()->GetY(), c->GetTarget()->GetZ()); PathNode *Node = FindPathNodeByCoordinates(c->GetTarget()->GetX(), c->GetTarget()->GetY(), c->GetTarget()->GetZ());
if(!Node) if(!Node)
{ {
return; return;
@ -1902,7 +1525,7 @@ void PathManager::DisconnectNodeToNode(Client *c, int32 Node2)
return; return;
} }
PathNode *Node = zone->pathing->FindPathNodeByCoordinates(c->GetTarget()->GetX(), c->GetTarget()->GetY(), c->GetTarget()->GetZ()); PathNode *Node = FindPathNodeByCoordinates(c->GetTarget()->GetX(), c->GetTarget()->GetY(), c->GetTarget()->GetZ());
if(!Node) if(!Node)
{ {
return; return;
@ -1986,7 +1609,7 @@ void PathManager::MoveNode(Client *c)
return; return;
} }
PathNode *Node = zone->pathing->FindPathNodeByCoordinates(c->GetTarget()->GetX(), c->GetTarget()->GetY(), c->GetTarget()->GetZ()); PathNode *Node = FindPathNodeByCoordinates(c->GetTarget()->GetX(), c->GetTarget()->GetY(), c->GetTarget()->GetZ());
if(!Node) if(!Node)
{ {
return; return;
@ -2020,7 +1643,7 @@ void PathManager::DisconnectAll(Client *c)
return; return;
} }
PathNode *Node = zone->pathing->FindPathNodeByCoordinates(c->GetTarget()->GetX(), c->GetTarget()->GetY(), c->GetTarget()->GetZ()); PathNode *Node = FindPathNodeByCoordinates(c->GetTarget()->GetX(), c->GetTarget()->GetY(), c->GetTarget()->GetZ());
if(!Node) if(!Node)
{ {
return; return;
@ -2193,7 +1816,7 @@ void PathManager::QuickConnect(Client *c, bool set)
return; return;
} }
PathNode *Node = zone->pathing->FindPathNodeByCoordinates(c->GetTarget()->GetX(), c->GetTarget()->GetY(), c->GetTarget()->GetZ()); PathNode *Node = FindPathNodeByCoordinates(c->GetTarget()->GetX(), c->GetTarget()->GetY(), c->GetTarget()->GetZ());
if(!Node) if(!Node)
{ {
return; return;

View File

@ -59,26 +59,18 @@ public:
~PathManager(); ~PathManager();
static PathManager *LoadPathFile(const char *ZoneName); static PathManager *LoadPathFile(const char *ZoneName);
bool loadPaths(FILE *fp);
void PrintPathing();
std::deque<int> FindRoute(glm::vec3 Start, glm::vec3 End); std::deque<int> FindRoute(glm::vec3 Start, glm::vec3 End);
private:
bool loadPaths(FILE *fp);
std::deque<int> FindRoute(int startID, int endID); std::deque<int> FindRoute(int startID, int endID);
glm::vec3 GetPathNodeCoordinates(int NodeNumber, bool BestZ = true); void PrintPathing();
bool CheckLosFN(glm::vec3 a, glm::vec3 b); bool CheckLosFN(glm::vec3 a, glm::vec3 b);
void SpawnPathNodes();
void MeshTest();
void SimpleMeshTest();
int FindNearestPathNode(glm::vec3 Position);
bool NoHazards(glm::vec3 From, glm::vec3 To); bool NoHazards(glm::vec3 From, glm::vec3 To);
bool NoHazardsAccurate(glm::vec3 From, glm::vec3 To); bool NoHazardsAccurate(glm::vec3 From, glm::vec3 To);
void OpenDoors(int Node1, int Node2, Mob* ForWho); void OpenDoors(int Node1, int Node2, Mob* ForWho);
PathNode* FindPathNodeByCoordinates(float x, float y, float z);
void ShowPathNodeNeighbours(Client *c);
int GetRandomPathNode();
void NodeInfo(Client *c); void NodeInfo(Client *c);
int32 AddNode(float x, float y, float z, float best_z, int32 requested_id = 0); //return -1 on failure, else returns the id of this node int32 AddNode(float x, float y, float z, float best_z, int32 requested_id = 0); //return -1 on failure, else returns the id of this node
bool DeleteNode(Client *c); bool DeleteNode(Client *c);
@ -98,7 +90,16 @@ public:
void QuickConnect(Client *c, bool set = false); void QuickConnect(Client *c, bool set = false);
void SortNodes(); void SortNodes();
private: glm::vec3 GetPathNodeCoordinates(int NodeNumber, bool BestZ = true);
void SpawnPathNodes();
void MeshTest();
void SimpleMeshTest();
int FindNearestPathNode(glm::vec3 Position);
PathNode* FindPathNodeByCoordinates(float x, float y, float z);
void ShowPathNodeNeighbours(Client *c);
int GetRandomPathNode();
PathFileHeader Head; PathFileHeader Head;
PathNode *PathNodes; PathNode *PathNodes;
int QuickConnectTarget; int QuickConnectTarget;

View File

@ -5886,43 +5886,6 @@ XS(XS_Mob_CalculateNewPosition)
XSRETURN(1); XSRETURN(1);
} }
XS(XS_Mob_CalculateNewPosition2); /* prototype to pass -Wmissing-prototypes */
XS(XS_Mob_CalculateNewPosition2)
{
dXSARGS;
if (items < 5 || items > 6)
Perl_croak(aTHX_ "Usage: Mob::CalculateNewPosition2(THIS, x, y, z, speed, checkZ= false)");
{
Mob * THIS;
bool RETVAL;
float x = (float)SvNV(ST(1));
float y = (float)SvNV(ST(2));
float z = (float)SvNV(ST(3));
float speed = (float)SvNV(ST(4));
bool checkZ;
if (sv_derived_from(ST(0), "Mob")) {
IV tmp = SvIV((SV*)SvRV(ST(0)));
THIS = INT2PTR(Mob *,tmp);
}
else
Perl_croak(aTHX_ "THIS is not of type Mob");
if(THIS == nullptr)
Perl_croak(aTHX_ "THIS is nullptr, avoiding crash.");
if (items < 6)
checkZ = false;
else {
checkZ = (bool)SvTRUE(ST(5));
}
RETVAL = THIS->CalculateNewPosition2(x, y, z, speed, checkZ);
ST(0) = boolSV(RETVAL);
sv_2mortal(ST(0));
}
XSRETURN(1);
}
XS(XS_Mob_CalculateDistance); /* prototype to pass -Wmissing-prototypes */ XS(XS_Mob_CalculateDistance); /* prototype to pass -Wmissing-prototypes */
XS(XS_Mob_CalculateDistance) XS(XS_Mob_CalculateDistance)
{ {
@ -9262,7 +9225,6 @@ XS(boot_Mob)
newXSproto(strcpy(buf, "CheckAggro"), XS_Mob_CheckAggro, file, "$$"); newXSproto(strcpy(buf, "CheckAggro"), XS_Mob_CheckAggro, file, "$$");
newXSproto(strcpy(buf, "CalculateHeadingToTarget"), XS_Mob_CalculateHeadingToTarget, file, "$$$"); newXSproto(strcpy(buf, "CalculateHeadingToTarget"), XS_Mob_CalculateHeadingToTarget, file, "$$$");
newXSproto(strcpy(buf, "CalculateNewPosition"), XS_Mob_CalculateNewPosition, file, "$$$$$;$"); newXSproto(strcpy(buf, "CalculateNewPosition"), XS_Mob_CalculateNewPosition, file, "$$$$$;$");
newXSproto(strcpy(buf, "CalculateNewPosition2"), XS_Mob_CalculateNewPosition2, file, "$$$$$;$");
newXSproto(strcpy(buf, "CalculateDistance"), XS_Mob_CalculateDistance, file, "$$$$"); newXSproto(strcpy(buf, "CalculateDistance"), XS_Mob_CalculateDistance, file, "$$$$");
newXSproto(strcpy(buf, "SendTo"), XS_Mob_SendTo, file, "$$$$"); newXSproto(strcpy(buf, "SendTo"), XS_Mob_SendTo, file, "$$$$");
newXSproto(strcpy(buf, "SendToFixZ"), XS_Mob_SendToFixZ, file, "$$$$"); newXSproto(strcpy(buf, "SendToFixZ"), XS_Mob_SendToFixZ, file, "$$$$");

View File

@ -673,76 +673,79 @@ void QuestManager::repopzone() {
} }
void QuestManager::ConnectNodeToNode(int node1, int node2, int teleport, int doorid) { void QuestManager::ConnectNodeToNode(int node1, int node2, int teleport, int doorid) {
if (!node1 || !node2) //PATHING TODO
{ //if (!node1 || !node2)
Log(Logs::General, Logs::Quests, "QuestManager::ConnectNodeToNode called without node1 or node2. Probably syntax error in quest file."); //{
} // Log(Logs::General, Logs::Quests, "QuestManager::ConnectNodeToNode called without node1 or node2. Probably syntax error in quest file.");
else //}
{ //else
if (!teleport) //{
{ // if (!teleport)
teleport = 0; // {
} // teleport = 0;
else if (teleport == 1 || teleport == -1) // }
{ // else if (teleport == 1 || teleport == -1)
teleport = -1; // {
} // teleport = -1;
// }
if (!doorid) //
{ // if (!doorid)
doorid = 0; // {
} // doorid = 0;
// }
if (!zone->pathing) //
{ // if (!zone->pathing)
// if no pathing bits available, make them available. // {
zone->pathing = new PathManager(); // // if no pathing bits available, make them available.
} // zone->pathing = new PathManager();
// }
if (zone->pathing) //
{ // if (zone->pathing)
zone->pathing->ConnectNodeToNode(node1, node2, teleport, doorid); // {
Log(Logs::Moderate, Logs::Quests, "QuestManager::ConnectNodeToNode connecting node %i to node %i.", node1, node2); // zone->pathing->ConnectNodeToNode(node1, node2, teleport, doorid);
} // Log(Logs::Moderate, Logs::Quests, "QuestManager::ConnectNodeToNode connecting node %i to node %i.", node1, node2);
} // }
//}
} }
void QuestManager::AddNode(float x, float y, float z, float best_z, int32 requested_id) void QuestManager::AddNode(float x, float y, float z, float best_z, int32 requested_id)
{ {
if (!x || !y || !z) //PATHING TODO
{
Log(Logs::General, Logs::Quests, "QuestManager::AddNode called without x, y, z. Probably syntax error in quest file.");
}
if (!best_z || best_z == 0) //if (!x || !y || !z)
{ //{
if (zone->zonemap) // Log(Logs::General, Logs::Quests, "QuestManager::AddNode called without x, y, z. Probably syntax error in quest file.");
{ //}
glm::vec3 loc(x, y, z); //
best_z = zone->zonemap->FindBestZ(loc, nullptr); //if (!best_z || best_z == 0)
} //{
else // if (zone->zonemap)
{ // {
best_z = z; // glm::vec3 loc(x, y, z);
} // best_z = zone->zonemap->FindBestZ(loc, nullptr);
} // }
// else
if (!requested_id) // {
{ // best_z = z;
requested_id = 0; // }
} //}
//
if (!zone->pathing) //if (!requested_id)
{ //{
// if no pathing bits available, make them available. // requested_id = 0;
zone->pathing = new PathManager(); //}
} //
//if (!zone->pathing)
if (zone->pathing) //{
{ // // if no pathing bits available, make them available.
zone->pathing->AddNode(x, y, z, best_z, requested_id); // zone->pathing = new PathManager();
Log(Logs::Moderate, Logs::Quests, "QuestManager::AddNode adding node at (%i, %i, %i).", x, y, z); //}
} //
//if (zone->pathing)
//{
// zone->pathing->AddNode(x, y, z, best_z, requested_id);
// Log(Logs::Moderate, Logs::Quests, "QuestManager::AddNode adding node at (%i, %i, %i).", x, y, z);
//}
} }
void QuestManager::settarget(const char *type, int target_id) { void QuestManager::settarget(const char *type, int target_id) {

View File

@ -412,7 +412,7 @@ void NPC::SaveGuardSpot(bool iClearGuardSpot) {
} }
void NPC::NextGuardPosition() { void NPC::NextGuardPosition() {
if (!CalculateNewPosition2(m_GuardPoint.x, m_GuardPoint.y, m_GuardPoint.z, GetMovespeed())) { if (!CalculateNewPosition(m_GuardPoint.x, m_GuardPoint.y, m_GuardPoint.z, GetMovespeed())) {
SetHeading(m_GuardPoint.w); SetHeading(m_GuardPoint.w);
Log(Logs::Detail, Logs::AI, "Unable to move to next guard position. Probably rooted."); Log(Logs::Detail, Logs::AI, "Unable to move to next guard position. Probably rooted.");
} }
@ -625,89 +625,8 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, int speed, boo
return true; return true;
} }
bool Mob::CalculateNewPosition2(float x, float y, float z, int speed, bool checkZ, bool calcHeading) {
return MakeNewPositionAndSendUpdate(x, y, z, speed, checkZ);
}
bool Mob::CalculateNewPosition(float x, float y, float z, int speed, bool checkZ, bool calcHeading) { bool Mob::CalculateNewPosition(float x, float y, float z, int speed, bool checkZ, bool calcHeading) {
if (GetID() == 0) return MakeNewPositionAndSendUpdate(x, y, z, speed, checkZ);
return true;
float nx = m_Position.x;
float ny = m_Position.y;
float nz = m_Position.z;
// if NPC is rooted
if (speed == 0) {
SetHeading(CalculateHeadingToTarget(x, y));
if (moved) {
SetCurrentSpeed(0);
moved = false;
}
Log(Logs::Detail, Logs::AI, "Rooted while calculating new position to (%.3f, %.3f, %.3f)", x, y, z);
return true;
}
float old_test_vector = test_vector;
m_TargetV.x = x - nx;
m_TargetV.y = y - ny;
m_TargetV.z = z - nz;
if (m_TargetV.x == 0 && m_TargetV.y == 0)
return false;
SetCurrentSpeed((int8)(speed)); //*NPC_RUNANIM_RATIO);
//speed *= NPC_SPEED_MULTIPLIER;
Log(Logs::Detail, Logs::AI, "Calculating new position to (%.3f, %.3f, %.3f) vector (%.3f, %.3f, %.3f) rate %.3f RAS %d", x, y, z, m_TargetV.x, m_TargetV.y, m_TargetV.z, speed, pRunAnimSpeed);
// --------------------------------------------------------------------------
// 2: get unit vector
// --------------------------------------------------------------------------
test_vector = sqrtf(x*x + y*y + z*z);
tar_vector = speed / sqrtf(m_TargetV.x*m_TargetV.x + m_TargetV.y*m_TargetV.y + m_TargetV.z*m_TargetV.z);
m_Position.w = CalculateHeadingToTarget(x, y);
if (tar_vector >= 1.0) {
if (IsNPC()) {
entity_list.ProcessMove(CastToNPC(), x, y, z);
}
m_Position.x = x;
m_Position.y = y;
m_Position.z = z;
Log(Logs::Detail, Logs::AI, "Close enough, jumping to waypoint");
}
else {
float new_x = m_Position.x + m_TargetV.x*tar_vector;
float new_y = m_Position.y + m_TargetV.y*tar_vector;
float new_z = m_Position.z + m_TargetV.z*tar_vector;
if (IsNPC()) {
entity_list.ProcessMove(CastToNPC(), new_x, new_y, new_z);
}
m_Position.x = new_x;
m_Position.y = new_y;
m_Position.z = new_z;
Log(Logs::Detail, Logs::AI, "Next position (%.3f, %.3f, %.3f)", m_Position.x, m_Position.y, m_Position.z);
}
if (fix_z_timer.Check())
this->FixZ();
//OP_MobUpdate
if ((old_test_vector != test_vector) || tar_ndx>20) { //send update
tar_ndx = 0;
this->SetMoving(true);
moved = true;
m_Delta = glm::vec4(m_Position.x - nx, m_Position.y - ny, m_Position.z - nz, 0.0f);
SendPositionUpdate();
}
tar_ndx++;
// now get new heading
SetAppearance(eaStanding, false); // make sure they're standing
pLastChange = Timer::GetCurrentTime();
return true;
} }
void NPC::AssignWaypoints(int32 grid) void NPC::AssignWaypoints(int32 grid)

View File

@ -42,7 +42,9 @@
#include "net.h" #include "net.h"
#include "npc.h" #include "npc.h"
#include "object.h" #include "object.h"
#include "pathing.h" #include "pathfinder_null.h"
#include "pathfinder_nav_mesh.h"
#include "pathfinder_waypoint.h"
#include "petitions.h" #include "petitions.h"
#include "quest_parser_collection.h" #include "quest_parser_collection.h"
#include "spawn2.h" #include "spawn2.h"
@ -893,7 +895,7 @@ bool Zone::Init(bool iStaticZone) {
zone->zonemap = Map::LoadMapFile(zone->map_name); zone->zonemap = Map::LoadMapFile(zone->map_name);
zone->watermap = WaterMap::LoadWaterMapfile(zone->map_name); zone->watermap = WaterMap::LoadWaterMapfile(zone->map_name);
zone->pathing = PathManager::LoadPathFile(zone->map_name); zone->pathing = IPathfinder::Load(zone->map_name);
Log(Logs::General, Logs::Status, "Loading spawn conditions..."); Log(Logs::General, Logs::Status, "Loading spawn conditions...");
if(!spawn_conditions.LoadSpawnConditions(short_name, instanceid)) { if(!spawn_conditions.LoadSpawnConditions(short_name, instanceid)) {

View File

@ -28,6 +28,7 @@
#include "spawn2.h" #include "spawn2.h"
#include "spawngroup.h" #include "spawngroup.h"
#include "aa_ability.h" #include "aa_ability.h"
#include "pathfinder_interface.h"
struct ZonePoint struct ZonePoint
{ {
@ -73,7 +74,6 @@ struct item_tick_struct {
class Client; class Client;
class Map; class Map;
class Mob; class Mob;
class PathManager;
class WaterMap; class WaterMap;
extern EntityList entity_list; extern EntityList entity_list;
struct NPCType; struct NPCType;
@ -211,7 +211,7 @@ public:
Map* zonemap; Map* zonemap;
WaterMap* watermap; WaterMap* watermap;
PathManager *pathing; IPathfinder *pathing;
NewZone_Struct newzone_data; NewZone_Struct newzone_data;
SpawnConditionManager spawn_conditions; SpawnConditionManager spawn_conditions;