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
object.cpp
oriented_bounding_box.cpp
pathfinder_interface.cpp
pathfinder_nav_mesh.cpp
pathfinder_null.cpp
pathfinder_waypoint.cpp
pathing.cpp
perl_client.cpp
@ -201,6 +203,7 @@ SET(zone_headers
oriented_bounding_box.h
pathfinder_interface.h
pathfinder_nav_mesh.h
pathfinder_null.h
pathfinder_waypoint.h
pathing.h
perlpacket.h

View File

@ -2165,7 +2165,7 @@ void Bot::AI_Process() {
} else if(!IsRooted()) {
if(GetTarget() && GetTarget()->GetHateTop() && GetTarget()->GetHateTop() != this) {
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));
return;
}
@ -2256,12 +2256,12 @@ void Bot::AI_Process() {
if (WaypointChanged)
tar_ndx = 20;
CalculateNewPosition2(Goal.x, Goal.y, Goal.z, GetBotRunspeed());
CalculateNewPosition(Goal.x, Goal.y, Goal.z, GetBotRunspeed());
}
else {
Mob* follow = entity_list.GetMob(GetFollowID());
if (follow)
CalculateNewPosition2(follow->GetX(), follow->GetY(), follow->GetZ(), GetBotRunspeed());
CalculateNewPosition(follow->GetX(), follow->GetY(), follow->GetZ(), GetBotRunspeed());
}
return;
@ -2352,7 +2352,7 @@ void Bot::AI_Process() {
float newZ = 0;
FaceTarget(GetTarget());
if (PlotPositionAroundTarget(this, newX, newY, newZ)) {
CalculateNewPosition2(newX, newY, newZ, GetBotRunspeed());
CalculateNewPosition(newX, newY, newZ, GetBotRunspeed());
return;
}
}
@ -2364,7 +2364,7 @@ void Bot::AI_Process() {
float newY = 0;
float newZ = 0;
if (PlotPositionAroundTarget(GetTarget(), newX, newY, newZ)) {
CalculateNewPosition2(newX, newY, newZ, GetBotRunspeed());
CalculateNewPosition(newX, newY, newZ, GetBotRunspeed());
return;
}
}
@ -2375,7 +2375,7 @@ void Bot::AI_Process() {
float newY = 0;
float newZ = 0;
if (PlotPositionAroundTarget(GetTarget(), newX, newY, newZ, false) && GetArchetype() != ARCHETYPE_CASTER) {
CalculateNewPosition2(newX, newY, newZ, GetBotRunspeed());
CalculateNewPosition(newX, newY, newZ, GetBotRunspeed());
return;
}
}
@ -2500,7 +2500,7 @@ void Bot::AI_Process() {
if (AI_movement_timer->Check()) {
if(!IsRooted()) {
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;
}
@ -2560,10 +2560,10 @@ void Bot::AI_Process() {
if (WaypointChanged)
tar_ndx = 20;
CalculateNewPosition2(Goal.x, Goal.y, Goal.z, speed);
CalculateNewPosition(Goal.x, Goal.y, Goal.z, speed);
}
else {
CalculateNewPosition2(follow->GetX(), follow->GetY(), follow->GetZ(), speed);
CalculateNewPosition(follow->GetX(), follow->GetY(), follow->GetZ(), speed);
}
if (rest_timer.Enabled())
@ -2643,14 +2643,14 @@ void Bot::PetAIProcess() {
if(botPet->GetClass() == ROGUE && !petHasAggro && !botPet->BehindMob(botPet->GetTarget(), botPet->GetX(), botPet->GetY())) {
// Move the rogue to behind the mob
if(botPet->PlotPositionAroundTarget(botPet->GetTarget(), newX, newY, newZ)) {
botPet->CalculateNewPosition2(newX, newY, newZ, botPet->GetRunspeed());
botPet->CalculateNewPosition(newX, newY, newZ, botPet->GetRunspeed());
return;
}
}
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(botPet->PlotPositionAroundTarget(botPet->GetTarget(), newX, newY, newZ)) {
botPet->CalculateNewPosition2(newX, newY, newZ, botPet->GetRunspeed());
botPet->CalculateNewPosition(newX, newY, newZ, botPet->GetRunspeed());
return;
}
}
@ -2665,7 +2665,7 @@ void Bot::PetAIProcess() {
moveBehindMob = true;
if(botPet->PlotPositionAroundTarget(botPet->GetTarget(), newX, newY, newZ, moveBehindMob)) {
botPet->CalculateNewPosition2(newX, newY, newZ, botPet->GetRunspeed());
botPet->CalculateNewPosition(newX, newY, newZ, botPet->GetRunspeed());
return;
}
}
@ -2748,7 +2748,7 @@ void Bot::PetAIProcess() {
botPet->SetRunAnimSpeed(0);
if(!botPet->IsRooted()) {
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;
} else {
botPet->SetHeading(botPet->GetTarget()->GetHeading());
@ -2776,7 +2776,7 @@ void Bot::PetAIProcess() {
float dist = DistanceSquared(botPet->GetPosition(), botPet->GetTarget()->GetPosition());
botPet->SetRunAnimSpeed(0);
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;
} else {
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)
{
if (app->size != sizeof(FindPersonRequest_Struct))
printf("Error in FindPersonRequest_Struct. Expected size of: %zu, but got: %i\n", sizeof(FindPersonRequest_Struct), app->size);
else {
FindPersonRequest_Struct* t = (FindPersonRequest_Struct*)app->pBuffer;
std::vector<FindPerson_Point> points;
Mob* target = entity_list.GetMob(t->npc_id);
if (target == nullptr) {
//empty length packet == not found.
EQApplicationPacket outapp(OP_FindPersonReply, 0);
QueuePacket(&outapp);
return;
}
if (!RuleB(Pathing, Find) && RuleB(Bazaar, EnableWarpToTrader) && target->IsClient() && (target->CastToClient()->Trader ||
target->CastToClient()->Buyer)) {
Message(15, "Moving you to Trader %s", target->GetName());
MovePC(zone->GetZoneID(), zone->GetInstanceID(), target->GetX(), target->GetY(), target->GetZ(), 0.0f);
}
if (!RuleB(Pathing, Find) || !zone->pathing)
{
//fill in the path array...
//
points.resize(2);
points[0].x = GetX();
points[0].y = GetY();
points[0].z = GetZ();
points[1].x = target->GetX();
points[1].y = target->GetY();
points[1].z = target->GetZ();
}
else
{
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);
if (!zone->zonemap->LineIntersectsZone(Start, End, 1.0f, nullptr) && zone->pathing->NoHazards(Start, End))
{
points.resize(2);
points[0].x = Start.x;
points[0].y = Start.y;
points[0].z = Start.z;
points[1].x = End.x;
points[1].y = End.y;
points[1].z = End.z;
}
else
{
std::deque<int> pathlist = zone->pathing->FindRoute(Start, End);
if (pathlist.empty())
{
EQApplicationPacket outapp(OP_FindPersonReply, 0);
QueuePacket(&outapp);
return;
}
//the client seems to have issues with packets larger than this
if (pathlist.size() > 36)
{
EQApplicationPacket outapp(OP_FindPersonReply, 0);
QueuePacket(&outapp);
return;
}
// Live appears to send the points in this order:
// Final destination.
// Current Position.
// rest of the points.
FindPerson_Point p;
int PointNumber = 0;
bool LeadsToTeleporter = false;
glm::vec3 v = zone->pathing->GetPathNodeCoordinates(pathlist.back());
p.x = v.x;
p.y = v.y;
p.z = v.z;
points.push_back(p);
p.x = GetX();
p.y = GetY();
p.z = GetZ();
points.push_back(p);
for (auto Iterator = pathlist.begin(); Iterator != pathlist.end(); ++Iterator)
{
if ((*Iterator) == -1) // Teleporter
{
LeadsToTeleporter = true;
break;
}
glm::vec3 v = zone->pathing->GetPathNodeCoordinates((*Iterator), false);
p.x = v.x;
p.y = v.y;
p.z = v.z;
points.push_back(p);
++PointNumber;
}
if (!LeadsToTeleporter)
{
p.x = target->GetX();
p.y = target->GetY();
p.z = target->GetZ();
points.push_back(p);
}
}
}
SendPathPacket(points);
}
return;
//if (app->size != sizeof(FindPersonRequest_Struct))
// printf("Error in FindPersonRequest_Struct. Expected size of: %zu, but got: %i\n", sizeof(FindPersonRequest_Struct), app->size);
//else {
// FindPersonRequest_Struct* t = (FindPersonRequest_Struct*)app->pBuffer;
//
// std::vector<FindPerson_Point> points;
// Mob* target = entity_list.GetMob(t->npc_id);
//
// if (target == nullptr) {
// //empty length packet == not found.
// EQApplicationPacket outapp(OP_FindPersonReply, 0);
// QueuePacket(&outapp);
// return;
// }
//
// if (!RuleB(Pathing, Find) && RuleB(Bazaar, EnableWarpToTrader) && target->IsClient() && (target->CastToClient()->Trader ||
// target->CastToClient()->Buyer)) {
// Message(15, "Moving you to Trader %s", target->GetName());
// MovePC(zone->GetZoneID(), zone->GetInstanceID(), target->GetX(), target->GetY(), target->GetZ(), 0.0f);
// }
//
// if (!RuleB(Pathing, Find) || !zone->pathing)
// {
// //fill in the path array...
// //
// points.resize(2);
// points[0].x = GetX();
// points[0].y = GetY();
// points[0].z = GetZ();
// points[1].x = target->GetX();
// points[1].y = target->GetY();
// points[1].z = target->GetZ();
// }
// else
// {
// 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);
//
// if (!zone->zonemap->LineIntersectsZone(Start, End, 1.0f, nullptr) && zone->pathing->NoHazards(Start, End))
// {
// points.resize(2);
// points[0].x = Start.x;
// points[0].y = Start.y;
// points[0].z = Start.z;
//
// points[1].x = End.x;
// points[1].y = End.y;
// points[1].z = End.z;
//
// }
// else
// {
// std::deque<int> pathlist = zone->pathing->FindRoute(Start, End);
//
// if (pathlist.empty())
// {
// EQApplicationPacket outapp(OP_FindPersonReply, 0);
// QueuePacket(&outapp);
// return;
// }
//
// //the client seems to have issues with packets larger than this
// if (pathlist.size() > 36)
// {
// EQApplicationPacket outapp(OP_FindPersonReply, 0);
// QueuePacket(&outapp);
// return;
// }
//
// // Live appears to send the points in this order:
// // Final destination.
// // Current Position.
// // rest of the points.
// FindPerson_Point p;
//
// int PointNumber = 0;
//
// bool LeadsToTeleporter = false;
//
// glm::vec3 v = zone->pathing->GetPathNodeCoordinates(pathlist.back());
//
// p.x = v.x;
// p.y = v.y;
// p.z = v.z;
// points.push_back(p);
//
// p.x = GetX();
// p.y = GetY();
// p.z = GetZ();
// points.push_back(p);
//
// for (auto Iterator = pathlist.begin(); Iterator != pathlist.end(); ++Iterator)
// {
// if ((*Iterator) == -1) // Teleporter
// {
// LeadsToTeleporter = true;
// break;
// }
//
// glm::vec3 v = zone->pathing->GetPathNodeCoordinates((*Iterator), false);
// p.x = v.x;
// p.y = v.y;
// p.z = v.z;
// points.push_back(p);
// ++PointNumber;
// }
//
// if (!LeadsToTeleporter)
// {
// p.x = target->GetX();
// p.y = target->GetY();
// p.z = target->GetZ();
//
// points.push_back(p);
// }
//
// }
// }
//
// SendPathPacket(points);
//}
//return;
}
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)
{
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, "#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 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 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 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 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.");
return;
}
if(!strcasecmp(sep->arg[1], "shownodes"))
{
if(zone->pathing)
zone->pathing->SpawnPathNodes();
return;
}
if(!strcasecmp(sep->arg[1], "info"))
{
if(zone->pathing)
{
zone->pathing->NodeInfo(c);
}
return;
}
if(!strcasecmp(sep->arg[1], "dump"))
{
if(zone->pathing)
{
if(sep->arg[2][0] == '\0')
return;
zone->pathing->DumpPath(sep->arg[2]);
}
return;
}
if(!strcasecmp(sep->arg[1], "add"))
{
if(zone->pathing)
{
float px = c->GetX();
float py = c->GetY();
float pz = c->GetZ();
float best_z;
if(zone->zonemap)
{
glm::vec3 loc(px, py, pz);
best_z = zone->zonemap->FindBestZ(loc, nullptr);
}
else
{
best_z = pz;
}
int32 res = zone->pathing->AddNode(px, py, pz, best_z, atoi(sep->arg[2]));
if(res >= 0)
{
c->Message(0, "Added Path Node: %i", res);
}
else
{
c->Message(0, "Failed to add Path Node");
}
}
else
{
zone->pathing = new PathManager();
float px = c->GetX();
float py = c->GetY();
float pz = c->GetZ();
float best_z;
if(zone->zonemap)
{
glm::vec3 loc(px, py, pz);
best_z = zone->zonemap->FindBestZ(loc, nullptr);
}
else
{
best_z = pz;
}
int32 res = zone->pathing->AddNode(px, py, pz, best_z, atoi(sep->arg[2]));
if(res >= 0)
{
c->Message(0, "Added Path Node: %i", res);
}
else
{
c->Message(0, "Failed to add Path Node");
}
}
return;
}
if(!strcasecmp(sep->arg[1], "remove"))
{
if(zone->pathing)
{
if(zone->pathing->DeleteNode(c))
{
c->Message(0, "Removed Node.");
}
else
{
c->Message(0, "Unable to Remove Node.");
}
}
return;
}
if(!strcasecmp(sep->arg[1], "connect"))
{
if(zone->pathing)
{
zone->pathing->ConnectNodeToNode(c, atoi(sep->arg[2]), atoi(sep->arg[3]), atoi(sep->arg[4]));
}
return;
}
if(!strcasecmp(sep->arg[1], "sconnect"))
{
if(zone->pathing)
{
zone->pathing->ConnectNode(c, atoi(sep->arg[2]), atoi(sep->arg[3]), atoi(sep->arg[4]));
}
return;
}
if(!strcasecmp(sep->arg[1], "qconnect"))
{
if(zone->pathing)
{
if(!strcasecmp(sep->arg[2], "set"))
{
zone->pathing->QuickConnect(c, true);
}
else
{
zone->pathing->QuickConnect(c, false);
}
}
return;
}
if(!strcasecmp(sep->arg[1], "disconnect"))
{
if(zone->pathing)
{
if(!strcasecmp(sep->arg[2], "all"))
{
zone->pathing->DisconnectAll(c);
}
else
{
zone->pathing->DisconnectNodeToNode(c, atoi(sep->arg[2]));
}
}
return;
}
if(!strcasecmp(sep->arg[1], "move"))
{
if(zone->pathing)
{
zone->pathing->MoveNode(c);
}
return;
}
if(!strcasecmp(sep->arg[1], "process"))
{
if(zone->pathing)
{
if(sep->arg[2][0] == '\0')
return;
zone->pathing->ProcessNodesAndSave(sep->arg[2]);
c->Message(0, "Path processed...");
}
return;
}
if(!strcasecmp(sep->arg[1], "resort"))
{
if(zone->pathing)
{
if(!strcasecmp(sep->arg[2], "nodes"))
{
zone->pathing->SortNodes();
c->Message(0, "Nodes resorted...");
}
else
{
zone->pathing->ResortConnections();
c->Message(0, "Connections resorted...");
}
}
return;
}
if(!strcasecmp(sep->arg[1], "hazard"))
{
if(zone->pathing)
{
if(c && c->GetTarget())
{
if (zone->pathing->NoHazardsAccurate(glm::vec3(c->GetX(), c->GetY(), c->GetZ()),
glm::vec3(c->GetTarget()->GetX(), c->GetTarget()->GetY(), c->GetTarget()->GetZ())))
{
c->Message(0, "No hazards.");
}
else
{
c->Message(0, "Hazard Detected...");
}
}
}
return;
}
if(!strcasecmp(sep->arg[1], "print"))
{
if(zone->pathing)
{
zone->pathing->PrintPathing();
}
return;
}
if(!strcasecmp(sep->arg[1], "showneighbours") || !strcasecmp(sep->arg[1], "showneighbors"))
{
if(!c->GetTarget())
{
c->Message(0, "First #path shownodes to spawn the pathnodes, and then target one of them.");
return;
}
if(zone->pathing)
{
zone->pathing->ShowPathNodeNeighbours(c);
return;
}
}
if(!strcasecmp(sep->arg[1], "meshtest"))
{
if(zone->pathing)
{
if(!strcasecmp(sep->arg[2], "simple"))
{
c->Message(0, "You may go linkdead. Results will be in the log file.");
zone->pathing->SimpleMeshTest();
return;
}
else
{
c->Message(0, "You may go linkdead. Results will be in the log file.");
zone->pathing->MeshTest();
return;
}
}
}
if(!strcasecmp(sep->arg[1], "allspawns"))
{
if(zone->pathing)
{
c->Message(0, "You may go linkdead. Results will be in the log file.");
entity_list.FindPathsToAllNPCs();
return;
}
}
if(!strcasecmp(sep->arg[1], "nearest"))
{
if(!c->GetTarget() || !c->GetTarget()->IsMob())
{
c->Message(0, "You must target something.");
return;
}
if(zone->pathing)
{
Mob *m = c->GetTarget();
glm::vec3 Position(m->GetX(), m->GetY(), m->GetZ());
int Node = zone->pathing->FindNearestPathNode(Position);
if(Node == -1)
c->Message(0, "Unable to locate a path node within range.");
else
c->Message(0, "Nearest path node is %i", Node);
return;
}
}
c->Message(0, "Unknown path command.");
//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, "#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 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 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 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 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.");
// return;
//}
//if(!strcasecmp(sep->arg[1], "shownodes"))
//{
// if(zone->pathing)
// zone->pathing->SpawnPathNodes();
//
// return;
//}
//
//if(!strcasecmp(sep->arg[1], "info"))
//{
// if(zone->pathing)
// {
// zone->pathing->NodeInfo(c);
// }
// return;
//}
//
//if(!strcasecmp(sep->arg[1], "dump"))
//{
// if(zone->pathing)
// {
// if(sep->arg[2][0] == '\0')
// return;
//
// zone->pathing->DumpPath(sep->arg[2]);
// }
// return;
//}
//
//if(!strcasecmp(sep->arg[1], "add"))
//{
// if(zone->pathing)
// {
// float px = c->GetX();
// float py = c->GetY();
// float pz = c->GetZ();
// float best_z;
//
// if(zone->zonemap)
// {
// glm::vec3 loc(px, py, pz);
// best_z = zone->zonemap->FindBestZ(loc, nullptr);
// }
// else
// {
// best_z = pz;
// }
// int32 res = zone->pathing->AddNode(px, py, pz, best_z, atoi(sep->arg[2]));
// if(res >= 0)
// {
// c->Message(0, "Added Path Node: %i", res);
// }
// else
// {
// c->Message(0, "Failed to add Path Node");
// }
// }
// else
// {
// zone->pathing = new PathManager();
// float px = c->GetX();
// float py = c->GetY();
// float pz = c->GetZ();
// float best_z;
//
// if(zone->zonemap)
// {
// glm::vec3 loc(px, py, pz);
// best_z = zone->zonemap->FindBestZ(loc, nullptr);
// }
// else
// {
// best_z = pz;
// }
// int32 res = zone->pathing->AddNode(px, py, pz, best_z, atoi(sep->arg[2]));
// if(res >= 0)
// {
// c->Message(0, "Added Path Node: %i", res);
// }
// else
// {
// c->Message(0, "Failed to add Path Node");
// }
// }
// return;
//}
//
//if(!strcasecmp(sep->arg[1], "remove"))
//{
// if(zone->pathing)
// {
// if(zone->pathing->DeleteNode(c))
// {
// c->Message(0, "Removed Node.");
// }
// else
// {
// c->Message(0, "Unable to Remove Node.");
// }
// }
// return;
//}
//
//if(!strcasecmp(sep->arg[1], "connect"))
//{
// if(zone->pathing)
// {
// zone->pathing->ConnectNodeToNode(c, atoi(sep->arg[2]), atoi(sep->arg[3]), atoi(sep->arg[4]));
// }
// return;
//}
//
//if(!strcasecmp(sep->arg[1], "sconnect"))
//{
// if(zone->pathing)
// {
// zone->pathing->ConnectNode(c, atoi(sep->arg[2]), atoi(sep->arg[3]), atoi(sep->arg[4]));
// }
// return;
//}
//
//if(!strcasecmp(sep->arg[1], "qconnect"))
//{
// if(zone->pathing)
// {
// if(!strcasecmp(sep->arg[2], "set"))
// {
// zone->pathing->QuickConnect(c, true);
// }
// else
// {
// zone->pathing->QuickConnect(c, false);
// }
// }
// return;
//}
//
//if(!strcasecmp(sep->arg[1], "disconnect"))
//{
// if(zone->pathing)
// {
// if(!strcasecmp(sep->arg[2], "all"))
// {
// zone->pathing->DisconnectAll(c);
// }
// else
// {
// zone->pathing->DisconnectNodeToNode(c, atoi(sep->arg[2]));
// }
// }
// return;
//}
//
//
//if(!strcasecmp(sep->arg[1], "move"))
//{
// if(zone->pathing)
// {
// zone->pathing->MoveNode(c);
// }
// return;
//}
//
//if(!strcasecmp(sep->arg[1], "process"))
//{
// if(zone->pathing)
// {
// if(sep->arg[2][0] == '\0')
// return;
//
// zone->pathing->ProcessNodesAndSave(sep->arg[2]);
// c->Message(0, "Path processed...");
// }
// return;
//}
//
//if(!strcasecmp(sep->arg[1], "resort"))
//{
// if(zone->pathing)
// {
// if(!strcasecmp(sep->arg[2], "nodes"))
// {
// zone->pathing->SortNodes();
// c->Message(0, "Nodes resorted...");
// }
// else
// {
// zone->pathing->ResortConnections();
// c->Message(0, "Connections resorted...");
// }
// }
// return;
//}
//
//if(!strcasecmp(sep->arg[1], "hazard"))
//{
// if(zone->pathing)
// {
// if(c && c->GetTarget())
// {
// if (zone->pathing->NoHazardsAccurate(glm::vec3(c->GetX(), c->GetY(), c->GetZ()),
// glm::vec3(c->GetTarget()->GetX(), c->GetTarget()->GetY(), c->GetTarget()->GetZ())))
// {
// c->Message(0, "No hazards.");
// }
// else
// {
// c->Message(0, "Hazard Detected...");
// }
// }
// }
// return;
//}
//
//if(!strcasecmp(sep->arg[1], "print"))
//{
// if(zone->pathing)
// {
// zone->pathing->PrintPathing();
// }
// return;
//}
//
//if(!strcasecmp(sep->arg[1], "showneighbours") || !strcasecmp(sep->arg[1], "showneighbors"))
//{
// if(!c->GetTarget())
// {
// c->Message(0, "First #path shownodes to spawn the pathnodes, and then target one of them.");
// return;
// }
// if(zone->pathing)
// {
// zone->pathing->ShowPathNodeNeighbours(c);
// return;
// }
//}
//if(!strcasecmp(sep->arg[1], "meshtest"))
//{
// if(zone->pathing)
// {
// if(!strcasecmp(sep->arg[2], "simple"))
// {
// c->Message(0, "You may go linkdead. Results will be in the log file.");
// zone->pathing->SimpleMeshTest();
// return;
// }
// else
// {
// c->Message(0, "You may go linkdead. Results will be in the log file.");
// zone->pathing->MeshTest();
// return;
// }
// }
//}
//
//if(!strcasecmp(sep->arg[1], "allspawns"))
//{
// if(zone->pathing)
// {
// c->Message(0, "You may go linkdead. Results will be in the log file.");
// entity_list.FindPathsToAllNPCs();
// return;
// }
//}
//
//if(!strcasecmp(sep->arg[1], "nearest"))
//{
// if(!c->GetTarget() || !c->GetTarget()->IsMob())
// {
// c->Message(0, "You must target something.");
// return;
// }
//
// if(zone->pathing)
// {
// Mob *m = c->GetTarget();
//
// glm::vec3 Position(m->GetX(), m->GetY(), m->GetZ());
//
// int Node = zone->pathing->FindNearestPathNode(Position);
//
// if(Node == -1)
// c->Message(0, "Unable to locate a path node within range.");
// else
// c->Message(0, "Nearest path node is %i", Node);
//
// return;
// }
//}
//
//c->Message(0, "Unknown path command.");
}
void Client::Undye() {

View File

@ -2822,26 +2822,6 @@ void EntityList::ListPlayerCorpses(Client *client)
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.
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 ListNPCCorpses(Client* client);
void ListPlayerCorpses(Client* client);
void FindPathsToAllNPCs();
int32 DeleteNPCCorpses();
int32 DeletePlayerCorpses();
void CorpseFix(Client* c);

View File

@ -130,23 +130,25 @@ void Mob::CalculateNewFearpoint()
{
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())
{
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, first.x, first.y, first.z);
return;
}
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.");
@ -171,6 +173,7 @@ void Mob::CalculateNewFearpoint()
break;
}
}
if (currently_fleeing)
m_FearWalkTarget = glm::vec3(ranx, rany, ranz);
else //Break fear

View File

@ -1125,17 +1125,6 @@ bool Lua_Mob::CalculateNewPosition(double x, double y, double z, double speed, b
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) {
Lua_Safe_Call_Real();
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("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("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("SendTo", (void(Lua_Mob::*)(double,double,double))&Lua_Mob::SendTo)
.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);
bool CalculateNewPosition(double x, double y, double z, double speed);
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);
void SendTo(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)
tar_ndx = 20;
CalculateNewPosition2(Goal.x, Goal.y, Goal.z, GetRunspeed());
CalculateNewPosition(Goal.x, Goal.y, Goal.z, GetRunspeed());
}
else {
Mob* follow = entity_list.GetMob(GetFollowID());
if (follow)
CalculateNewPosition2(follow->GetX(), follow->GetY(), follow->GetZ(), GetRunspeed());
CalculateNewPosition(follow->GetX(), follow->GetY(), follow->GetZ(), GetRunspeed());
}
return;
@ -1559,7 +1559,7 @@ void Merc::AI_Process() {
float newZ = 0;
FaceTarget(GetTarget());
if (PlotPositionAroundTarget(this, newX, newY, newZ)) {
CalculateNewPosition2(newX, newY, newZ, GetRunspeed());
CalculateNewPosition(newX, newY, newZ, GetRunspeed());
return;
}
}
@ -1571,7 +1571,7 @@ void Merc::AI_Process() {
float newY = 0;
float newZ = 0;
if (PlotPositionAroundTarget(GetTarget(), newX, newY, newZ)) {
CalculateNewPosition2(newX, newY, newZ, GetRunspeed());
CalculateNewPosition(newX, newY, newZ, GetRunspeed());
return;
}
}
@ -1582,7 +1582,7 @@ void Merc::AI_Process() {
float newY = 0;
float newZ = 0;
if (PlotPositionAroundTarget(GetTarget(), newX, newY, newZ, false) && GetArchetype() != ARCHETYPE_CASTER) {
CalculateNewPosition2(newX, newY, newZ, GetRunspeed());
CalculateNewPosition(newX, newY, newZ, GetRunspeed());
return;
}
}
@ -1709,7 +1709,7 @@ void Merc::AI_Process() {
{
if(!IsRooted()) {
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;
}
@ -1781,10 +1781,10 @@ void Merc::AI_Process() {
if (WaypointChanged)
tar_ndx = 20;
CalculateNewPosition2(Goal.x, Goal.y, Goal.z, speed);
CalculateNewPosition(Goal.x, Goal.y, Goal.z, speed);
}
else {
CalculateNewPosition2(follow->GetX(), follow->GetY(), follow->GetZ(), speed);
CalculateNewPosition(follow->GetX(), follow->GetY(), follow->GetZ(), speed);
}
if (rest_timer.Enabled())

View File

@ -430,15 +430,7 @@ Mob::Mob(const char* in_name,
m_TargetRing = glm::vec3();
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;
PathingTraversedNodes = 0;
hate_list.SetHateOwner(this);
m_AllowBeneficial = false;
@ -485,9 +477,6 @@ Mob::~Mob()
entity_list.DestroyTempPets(this);
}
entity_list.UnMarkNPC(GetID());
safe_delete(PathingLOSCheckTimer);
safe_delete(PathingRouteUpdateTimerShort);
safe_delete(PathingRouteUpdateTimerLong);
UninitializeBuffSlots();
#ifdef BOTS
@ -1642,7 +1631,6 @@ void Mob::ShowBuffList(Client* client) {
}
void Mob::GMMove(float x, float y, float z, float heading, bool SendUpdate) {
Route.clear();
if(IsNPC()) {

View File

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

View File

@ -563,10 +563,6 @@ void Client::AI_Stop() {
// only call this on a zone shutdown event
void Mob::AI_ShutDown() {
safe_delete(PathingLOSCheckTimer);
safe_delete(PathingRouteUpdateTimerShort);
safe_delete(PathingRouteUpdateTimerLong);
attack_timer.Disable();
attack_dw_timer.Disable();
ranged_timer.Disable();
@ -770,7 +766,7 @@ void Client::AI_Process()
CalculateNewFearpoint();
}
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
{
bool WaypointChanged, NodeReached;
@ -781,7 +777,7 @@ void Client::AI_Process()
if(WaypointChanged)
tar_ndx = 20;
CalculateNewPosition2(Goal.x, Goal.y, Goal.z, speed);
CalculateNewPosition(Goal.x, Goal.y, Goal.z, speed);
}
}
return;
@ -853,7 +849,7 @@ void Client::AI_Process()
newspeed *= 2;
SetCurrentSpeed(newspeed);
if(!RuleB(Pathing, Aggro) || !zone->pathing)
CalculateNewPosition2(GetTarget()->GetX(), GetTarget()->GetY(), GetTarget()->GetZ(), newspeed);
CalculateNewPosition(GetTarget()->GetX(), GetTarget()->GetY(), GetTarget()->GetZ(), newspeed);
else
{
bool WaypointChanged, NodeReached;
@ -863,7 +859,7 @@ void Client::AI_Process()
if(WaypointChanged)
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;
SetCurrentSpeed(nspeed);
CalculateNewPosition2(owner->GetX(), owner->GetY(), owner->GetZ(), nspeed);
CalculateNewPosition(owner->GetX(), owner->GetY(), owner->GetZ(), nspeed);
}
}
else
@ -969,7 +965,7 @@ void Mob::AI_Process() {
}
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
{
@ -981,7 +977,7 @@ void Mob::AI_Process() {
if(WaypointChanged)
tar_ndx = 20;
CalculateNewPosition2(Goal.x, Goal.y, Goal.z, GetFearSpeed());
CalculateNewPosition(Goal.x, Goal.y, Goal.z, GetFearSpeed());
}
}
return;
@ -1300,7 +1296,7 @@ void Mob::AI_Process() {
if (!IsRooted()) {
Log(Logs::Detail, Logs::AI, "Pursuing %s while engaged.", target->GetName());
if (!RuleB(Pathing, Aggro) || !zone->pathing)
CalculateNewPosition2(target->GetX(), target->GetY(), target->GetZ(), GetRunspeed());
CalculateNewPosition(target->GetX(), target->GetY(), target->GetZ(), GetRunspeed());
else
{
bool WaypointChanged, NodeReached;
@ -1311,7 +1307,7 @@ void Mob::AI_Process() {
if (WaypointChanged)
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)
speed = GetRunspeed();
CalculateNewPosition2(owner->GetX(), owner->GetY(), owner->GetZ(), speed);
CalculateNewPosition(owner->GetX(), owner->GetY(), owner->GetZ(), speed);
}
else
{
@ -1454,7 +1450,7 @@ void Mob::AI_Process() {
int speed = GetWalkspeed();
if (dist2 >= followdist + 150)
speed = GetRunspeed();
CalculateNewPosition2(follow->GetX(), follow->GetY(), follow->GetZ(), speed);
CalculateNewPosition(follow->GetX(), follow->GetY(), follow->GetZ(), speed);
}
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)",
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
pLastFightingDelayMoving = Timer::GetCurrentTime() + RandomTimer(roambox_min_delay, roambox_delay);
@ -1593,7 +1589,7 @@ void NPC::AI_DoMovement() {
if (doMove)
{ // not at waypoint yet or at 0 pause WP, so keep moving
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
{
bool WaypointChanged;
@ -1605,13 +1601,13 @@ void NPC::AI_DoMovement() {
if(NodeReached)
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)
// handle new quest grid command processing
// handle new quest grid command processing
else if (gridno < 0)
{ // this mob is under quest control
if (movetimercompleted==true)
@ -1630,7 +1626,7 @@ void NPC::AI_DoMovement() {
{
bool CP2Moved;
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
{
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)
entity_list.OpenDoorsNear(CastToNPC());
CP2Moved = CalculateNewPosition2(Goal.x, Goal.y, Goal.z, walksp);
CP2Moved = CalculateNewPosition(Goal.x, Goal.y, Goal.z, walksp);
}
else
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;
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);
@ -500,7 +500,7 @@ std::deque<int> PathManager::FindRoute(glm::vec3 Start, glm::vec3 End)
break;
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);
@ -644,439 +644,62 @@ void PathManager::SimpleMeshTest()
glm::vec3 Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &WaypointChanged, bool &NodeReached)
{
WaypointChanged = false;
NodeReached = false;
glm::vec3 NodeLoc;
glm::vec3 To(ToX, ToY, ToZ);
if (Speed <= 0) {
return To;
}
glm::vec3 From(GetX(), GetY(), GetZ());
glm::vec3 HeadPosition(From.x, From.y, From.z + (GetSize() < 6.0 ? 6 : GetSize()) * HEAD_POSITION);
glm::vec3 To(ToX, ToY, ToZ);
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)
if (DistanceSquared(To, From) < 1.0f) {
WaypointChanged = false;
NodeReached = true;
Route.clear();
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(From == PathingLastPosition)
{
++PathingLoopCount;
if((PathingLoopCount > 5) && !IsRooted())
{
Log(Logs::Detail, Logs::None, "appears to be stuck. Teleporting them to next position.", GetName());
if(Route.empty())
{
Teleport(To);
WaypointChanged = true;
PathingLoopCount = 0;
return To;
}
NodeLoc = zone->pathing->GetPathNodeCoordinates(Route.front());
Route.pop_front();
++PathingTraversedNodes;
Teleport(NodeLoc);
if (Route.empty()) {
Route = zone->pathing->FindRoute(From, To);
PathingDestination = To;
WaypointChanged = true;
NodeReached = false;
return *Route.begin();
}
else {
bool SameDestination = DistanceSquared(To, PathingDestination) < 1.0f;
if (!SameDestination) {
//We had a route but our target position moved too much
Route = zone->pathing->FindRoute(From, To);
PathingDestination = To;
WaypointChanged = true;
PathingLoopCount = 0;
return NodeLoc;
NodeReached = false;
return *Route.begin();
}
}
else
{
PathingLoopCount = 0;
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);
else {
bool AtNextNode = DistanceSquared(From, *Route.begin()) < 1.0f;
if (AtNextNode) {
WaypointChanged = false;
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();
++PathingTraversedNodes;
WaypointChanged = true;
// 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;
if (Route.empty()) {
Route = zone->pathing->FindRoute(From, To);
PathingDestination = To;
WaypointChanged = true;
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();
}
// 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 *Route.begin();
}
else {
return *Route.begin();
}
return NodeLoc;
}
else
{
Log(Logs::Detail, Logs::None, " Target moved. End node is different. Clearing route.");
Route.clear();
// We will now fall through to get a new route.
else {
WaypointChanged = false;
NodeReached = false;
return *Route.begin();
}
}
}
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)
@ -1254,14 +877,14 @@ bool PathManager::NoHazardsAccurate(glm::vec3 From, glm::vec3 To)
void Mob::PrintRoute()
{
printf("Route is : ");
for(auto Iterator = Route.begin(); Iterator !=Route.end(); ++Iterator)
{
printf("%i, ", (*Iterator));
}
printf("\n");
//printf("Route is : ");
//
//for(auto Iterator = Route.begin(); Iterator !=Route.end(); ++Iterator)
//{
// printf("%i, ", (*Iterator));
//}
//
//printf("\n");
}
@ -1346,7 +969,7 @@ void PathManager::ShowPathNodeNeighbours(Client *c)
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)
{
@ -1412,7 +1035,7 @@ void PathManager::NodeInfo(Client *c)
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)
{
return;
@ -1661,7 +1284,7 @@ bool PathManager::DeleteNode(Client *c)
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)
{
return false;
@ -1742,7 +1365,7 @@ void PathManager::ConnectNodeToNode(Client *c, int32 Node2, int32 teleport, int3
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)
{
return;
@ -1832,7 +1455,7 @@ void PathManager::ConnectNode(Client *c, int32 Node2, int32 teleport, int32 door
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)
{
return;
@ -1902,7 +1525,7 @@ void PathManager::DisconnectNodeToNode(Client *c, int32 Node2)
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)
{
return;
@ -1986,7 +1609,7 @@ void PathManager::MoveNode(Client *c)
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)
{
return;
@ -2020,7 +1643,7 @@ void PathManager::DisconnectAll(Client *c)
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)
{
return;
@ -2193,7 +1816,7 @@ void PathManager::QuickConnect(Client *c, bool set)
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)
{
return;

View File

@ -59,26 +59,18 @@ public:
~PathManager();
static PathManager *LoadPathFile(const char *ZoneName);
bool loadPaths(FILE *fp);
void PrintPathing();
static PathManager *LoadPathFile(const char *ZoneName);
std::deque<int> FindRoute(glm::vec3 Start, glm::vec3 End);
private:
bool loadPaths(FILE *fp);
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);
void SpawnPathNodes();
void MeshTest();
void SimpleMeshTest();
int FindNearestPathNode(glm::vec3 Position);
bool NoHazards(glm::vec3 From, glm::vec3 To);
bool NoHazardsAccurate(glm::vec3 From, glm::vec3 To);
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);
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);
@ -98,7 +90,16 @@ public:
void QuickConnect(Client *c, bool set = false);
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;
PathNode *PathNodes;
int QuickConnectTarget;

View File

@ -5886,43 +5886,6 @@ XS(XS_Mob_CalculateNewPosition)
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)
{
@ -9262,7 +9225,6 @@ XS(boot_Mob)
newXSproto(strcpy(buf, "CheckAggro"), XS_Mob_CheckAggro, file, "$$");
newXSproto(strcpy(buf, "CalculateHeadingToTarget"), XS_Mob_CalculateHeadingToTarget, 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, "SendTo"), XS_Mob_SendTo, 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) {
if (!node1 || !node2)
{
Log(Logs::General, Logs::Quests, "QuestManager::ConnectNodeToNode called without node1 or node2. Probably syntax error in quest file.");
}
else
{
if (!teleport)
{
teleport = 0;
}
else if (teleport == 1 || teleport == -1)
{
teleport = -1;
}
if (!doorid)
{
doorid = 0;
}
if (!zone->pathing)
{
// if no pathing bits available, make them available.
zone->pathing = new PathManager();
}
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);
}
}
//PATHING TODO
//if (!node1 || !node2)
//{
// Log(Logs::General, Logs::Quests, "QuestManager::ConnectNodeToNode called without node1 or node2. Probably syntax error in quest file.");
//}
//else
//{
// if (!teleport)
// {
// teleport = 0;
// }
// else if (teleport == 1 || teleport == -1)
// {
// teleport = -1;
// }
//
// if (!doorid)
// {
// doorid = 0;
// }
//
// if (!zone->pathing)
// {
// // if no pathing bits available, make them available.
// zone->pathing = new PathManager();
// }
//
// 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);
// }
//}
}
void QuestManager::AddNode(float x, float y, float z, float best_z, int32 requested_id)
{
if (!x || !y || !z)
{
Log(Logs::General, Logs::Quests, "QuestManager::AddNode called without x, y, z. Probably syntax error in quest file.");
}
//PATHING TODO
if (!best_z || best_z == 0)
{
if (zone->zonemap)
{
glm::vec3 loc(x, y, z);
best_z = zone->zonemap->FindBestZ(loc, nullptr);
}
else
{
best_z = z;
}
}
if (!requested_id)
{
requested_id = 0;
}
if (!zone->pathing)
{
// if no pathing bits available, make them available.
zone->pathing = new PathManager();
}
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);
}
//if (!x || !y || !z)
//{
// 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 (zone->zonemap)
// {
// glm::vec3 loc(x, y, z);
// best_z = zone->zonemap->FindBestZ(loc, nullptr);
// }
// else
// {
// best_z = z;
// }
//}
//
//if (!requested_id)
//{
// requested_id = 0;
//}
//
//if (!zone->pathing)
//{
// // if no pathing bits available, make them available.
// zone->pathing = new PathManager();
//}
//
//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) {

View File

@ -412,7 +412,7 @@ void NPC::SaveGuardSpot(bool iClearGuardSpot) {
}
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);
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;
}
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) {
if (GetID() == 0)
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;
return MakeNewPositionAndSendUpdate(x, y, z, speed, checkZ);
}
void NPC::AssignWaypoints(int32 grid)

View File

@ -42,7 +42,9 @@
#include "net.h"
#include "npc.h"
#include "object.h"
#include "pathing.h"
#include "pathfinder_null.h"
#include "pathfinder_nav_mesh.h"
#include "pathfinder_waypoint.h"
#include "petitions.h"
#include "quest_parser_collection.h"
#include "spawn2.h"
@ -893,7 +895,7 @@ bool Zone::Init(bool iStaticZone) {
zone->zonemap = Map::LoadMapFile(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...");
if(!spawn_conditions.LoadSpawnConditions(short_name, instanceid)) {

View File

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