mirror of
https://github.com/EQEmu/Server.git
synced 2026-01-04 15:43:52 +00:00
Add pathfinding interfaces, still heavily wip
This commit is contained in:
parent
596e3b28b5
commit
5f1063acb9
@ -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
|
||||
|
||||
28
zone/bot.cpp
28
zone/bot.cpp
@ -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());
|
||||
|
||||
@ -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)
|
||||
|
||||
612
zone/command.cpp
612
zone/command.cpp
@ -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() {
|
||||
|
||||
@ -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()
|
||||
{
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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())
|
||||
|
||||
12
zone/mob.cpp
12
zone/mob.cpp
@ -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()) {
|
||||
|
||||
15
zone/mob.h
15
zone/mob.h
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
7
zone/pathfinder_interface.cpp
Normal file
7
zone/pathfinder_interface.cpp
Normal 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();
|
||||
}
|
||||
@ -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);
|
||||
};
|
||||
@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
#include "pathfinder_interface.h"
|
||||
15
zone/pathfinder_null.cpp
Normal file
15
zone/pathfinder_null.cpp
Normal 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
13
zone/pathfinder_null.h
Normal 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();
|
||||
};
|
||||
@ -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();
|
||||
};
|
||||
495
zone/pathing.cpp
495
zone/pathing.cpp
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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, "$$$$");
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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)) {
|
||||
|
||||
@ -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;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user