Command changes and code cleanup

This commit is contained in:
KimLS 2017-07-21 20:22:33 -07:00
parent ab33148f81
commit bdc90ac3a7
12 changed files with 253 additions and 2482 deletions

View File

@ -205,7 +205,6 @@ SET(zone_headers
pathfinder_nav_mesh.h
pathfinder_null.h
pathfinder_waypoint.h
pathing.h
perlpacket.h
petitions.h
pets.h

View File

@ -63,7 +63,6 @@
#include "guild_mgr.h"
#include "map.h"
#include "doors.h"
#include "pathing.h"
#include "qglobals.h"
#include "queryserv.h"
#include "quest_parser_collection.h"

View File

@ -300,8 +300,8 @@ public:
void FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho);
virtual bool Process();
void ProcessPackets();
void LogMerchant(Client* player, Mob* merchant, uint32 quantity, uint32 price, const EQEmu::ItemData* item, bool buying);
void SendPacketQueue(bool Block = true);
void QueuePacket(const EQApplicationPacket* app, bool ack_req = true, CLIENT_CONN_STATUS = CLIENT_CONNECTINGALL, eqFilterType filter=FilterNone);
void FastQueuePacket(EQApplicationPacket** app, bool ack_req = true, CLIENT_CONN_STATUS = CLIENT_CONNECTINGALL);
void ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_skill, const char* orig_message, const char* targetname=nullptr);

View File

@ -4366,7 +4366,6 @@ void Client::Handle_OP_ClientTimeStamp(const EQApplicationPacket *app)
void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app)
{
Log(Logs::General, Logs::Status, "Incoming client position packet");
if (IsAIControlled())
return;
@ -4380,8 +4379,12 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app)
Log(Logs::General, Logs::Error, "OP size error: OP_ClientUpdate expected:%i got:%i", sizeof(PlayerPositionUpdateClient_Struct), app->size);
return;
}
PlayerPositionUpdateClient_Struct* ppu = (PlayerPositionUpdateClient_Struct*)app->pBuffer;
Message(0, "Client Update Position (%.2f, %.2f, %.2f, %u) (%u)", ppu->x_pos, ppu->y_pos, ppu->z_pos, ppu->heading, ppu->animation);
Message(0, "Client Update Deltas (%.2f, %.2f, %.2f, %u)", ppu->delta_x, ppu->delta_y, ppu->delta_z, ppu->delta_heading);
/* Boat handling */
if (ppu->spawn_id != GetID()) {
/* If player is controlling boat */
@ -4607,7 +4610,6 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app)
m_Position.x = ppu->x_pos;
m_Position.y = ppu->y_pos;
m_Position.z = ppu->z_pos;
Log(Logs::General, Logs::Status, "Client position updated");
/* Visual Debugging */
if (RuleB(Character, OPClientUpdateVisualDebug)) {
@ -5690,128 +5692,111 @@ 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);
auto 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;
auto v = pathlist.back();
p.x = v.pos.x;
p.y = v.pos.y;
p.z = v.pos.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).teleport) // Teleporter
{
LeadsToTeleporter = true;
break;
}
glm::vec3 v = (*Iterator).pos;
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);
}
}
void Client::Handle_OP_Fishing(const EQApplicationPacket *app)

View File

@ -600,9 +600,8 @@ bool Client::Process() {
EQApplicationPacket *app = nullptr;
if (!eqs->CheckState(CLOSING))
{
while (ret && (app = (EQApplicationPacket *)eqs->PopPacket())) {
if (app)
ret = HandlePacket(app);
while (app = eqs->PopPacket()) {
HandlePacket(app);
safe_delete(app);
}
}

View File

@ -59,7 +59,6 @@
#include "command.h"
#include "guild_mgr.h"
#include "map.h"
#include "pathing.h"
#include "qglobals.h"
#include "queryserv.h"
#include "quest_parser_collection.h"
@ -6816,313 +6815,6 @@ void command_path(Client *c, const Seperator *sep)
if (zone->pathing) {
zone->pathing->DebugCommand(c, 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.");
}
void Client::Undye() {

View File

@ -19,7 +19,6 @@
#include "../common/rulesys.h"
#include "map.h"
#include "pathing.h"
#include "zone.h"
#ifdef _WINDOWS
@ -142,10 +141,10 @@ void Mob::CalculateNewFearpoint()
if (!Route.empty())
{
auto first = (*Route.begin());
m_FearWalkTarget = glm::vec3(first.x, first.y, first.z);
m_FearWalkTarget = glm::vec3(first.pos.x, first.pos.y, first.pos.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);
Log(Logs::Detail, Logs::None, "Feared to node %i (%8.3f, %8.3f, %8.3f)", Node, first.pos.x, first.pos.y, first.pos.z);
return;
}

View File

@ -9,7 +9,22 @@ class Seperator;
class IPathfinder
{
public:
typedef std::list<glm::vec3> IPath;
struct IPathNode
{
IPathNode(const glm::vec3 &p) {
pos = p;
teleport = false;
}
IPathNode(bool tp) {
teleport = tp;
}
glm::vec3 pos;
bool teleport;
};
typedef std::list<IPathNode> IPath;
IPathfinder() { }
virtual ~IPathfinder() { }

View File

@ -3,14 +3,15 @@
#include <boost/geometry/index/rtree.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/astar_search.hpp>
#include <string>
#include <memory>
#include <stdio.h>
#include "pathfinder_waypoint.h"
#include "zone.h"
#include "client.h"
#include "../common/eqemu_logsys.h"
#include "../common/rulesys.h"
#include <string>
#include <stdio.h>
extern Zone *zone;
@ -115,6 +116,7 @@ PathfinderWaypoint::PathfinderWaypoint(const std::string &path)
if (strncmp(Magic, "EQEMUPATH", 9))
{
Log(Logs::General, Logs::Error, "Bad Magic String in .path file.");
fclose(f);
return;
}
@ -123,62 +125,20 @@ PathfinderWaypoint::PathfinderWaypoint(const std::string &path)
Log(Logs::General, Logs::Status, "Path File Header: Version %ld, PathNodes %ld",
(long)Head.version, (long)Head.PathNodeCount);
if (Head.version != 2)
if (Head.version == 2)
{
Log(Logs::General, Logs::Error, "Unsupported path file version.");
LoadV2(f, Head);
return;
}
std::unique_ptr<PathNode[]> PathNodes(new PathNode[Head.PathNodeCount]);
fread(PathNodes.get(), sizeof(PathNode), Head.PathNodeCount, f);
int MaxNodeID = Head.PathNodeCount - 1;
m_impl->PathFileValid = true;
m_impl->Nodes.reserve(Head.PathNodeCount);
for (uint32 i = 0; i < Head.PathNodeCount; ++i)
{
auto &n = PathNodes[i];
Point p = Point(n.v.x, n.v.y, n.v.z);
m_impl->Tree.insert(std::make_pair(p, i));
boost::add_vertex(m_impl->Graph);
Node node;
node.v = n.v;
node.bestz = n.bestz;
m_impl->Nodes.push_back(node);
else if (Head.version == 3) {
LoadV3(f, Head);
return;
}
auto weightmap = boost::get(boost::edge_weight, m_impl->Graph);
for (uint32 i = 0; i < Head.PathNodeCount; ++i) {
for (uint32 j = 0; j < 50; ++j)
{
if (PathNodes[i].Neighbours[j].id > MaxNodeID)
{
Log(Logs::General, Logs::Error, "Path Node %i, Neighbour %i (%i) out of range.", i, j, PathNodes[i].Neighbours[j].id);
m_impl->PathFileValid = false;
}
if (PathNodes[i].Neighbours[j].id > 0) {
GraphType::edge_descriptor e;
bool inserted;
boost::tie(e, inserted) = boost::add_edge(PathNodes[i].id, PathNodes[i].Neighbours[j].id, m_impl->Graph);
weightmap[e] = PathNodes[i].Neighbours[j].distance;
Edge edge;
edge.distance = PathNodes[i].Neighbours[j].distance;
edge.door_id = PathNodes[i].Neighbours[j].DoorID;
edge.teleport = PathNodes[i].Neighbours[j].Teleport;
m_impl->Edges[std::make_pair(PathNodes[i].id, PathNodes[i].Neighbours[j].id)] = edge;
}
}
else {
Log(Logs::General, Logs::Error, "Unsupported path file version.");
fclose(f);
return;
}
fclose(f);
}
}
@ -239,8 +199,7 @@ IPathfinder::IPath PathfinderWaypoint::FindRoute(const glm::vec3 &start, const g
auto &edge = iter->second;
if (edge.teleport) {
Route.push_front(m_impl->Nodes[v].v);
glm::vec3 teleport(100000000.0f, 100000000.0f, 100000000.0f);
Route.push_front(teleport);
Route.push_front(true);
}
else {
Route.push_front(m_impl->Nodes[v].v);
@ -295,16 +254,75 @@ void PathfinderWaypoint::DebugCommand(Client *c, const Seperator *sep)
{
if (c->GetTarget() != nullptr) {
auto target = c->GetTarget();
glm::vec3 start(target->GetX(), target->GetY(), target->GetZ());
glm::vec3 end(c->GetX(), c->GetY(), c->GetZ());
glm::vec3 end(target->GetX(), target->GetY(), target->GetZ());
glm::vec3 start(c->GetX(), c->GetY(), c->GetZ());
ShowPath(start, end);
ShowPath(c, start, end);
}
return;
}
}
void PathfinderWaypoint::LoadV2(FILE *f, const PathFileHeader &header)
{
std::unique_ptr<PathNode[]> PathNodes(new PathNode[header.PathNodeCount]);
fread(PathNodes.get(), sizeof(PathNode), header.PathNodeCount, f);
int MaxNodeID = header.PathNodeCount - 1;
m_impl->PathFileValid = true;
m_impl->Nodes.reserve(header.PathNodeCount);
for (uint32 i = 0; i < header.PathNodeCount; ++i)
{
auto &n = PathNodes[i];
Point p = Point(n.v.x, n.v.y, n.v.z);
m_impl->Tree.insert(std::make_pair(p, i));
boost::add_vertex(m_impl->Graph);
Node node;
node.v = n.v;
node.bestz = n.bestz;
m_impl->Nodes.push_back(node);
}
auto weightmap = boost::get(boost::edge_weight, m_impl->Graph);
for (uint32 i = 0; i < header.PathNodeCount; ++i) {
for (uint32 j = 0; j < 50; ++j)
{
if (PathNodes[i].Neighbours[j].id > MaxNodeID)
{
Log(Logs::General, Logs::Error, "Path Node %i, Neighbour %i (%i) out of range.", i, j, PathNodes[i].Neighbours[j].id);
m_impl->PathFileValid = false;
}
if (PathNodes[i].Neighbours[j].id > 0) {
GraphType::edge_descriptor e;
bool inserted;
boost::tie(e, inserted) = boost::add_edge(PathNodes[i].id, PathNodes[i].Neighbours[j].id, m_impl->Graph);
weightmap[e] = PathNodes[i].Neighbours[j].distance;
Edge edge;
edge.distance = PathNodes[i].Neighbours[j].distance;
edge.door_id = PathNodes[i].Neighbours[j].DoorID;
edge.teleport = PathNodes[i].Neighbours[j].Teleport;
m_impl->Edges[std::make_pair(PathNodes[i].id, PathNodes[i].Neighbours[j].id)] = edge;
}
}
}
fclose(f);
}
void PathfinderWaypoint::LoadV3(FILE *f, const PathFileHeader &header)
{
fclose(f);
}
void PathfinderWaypoint::ShowNodes()
{
for (size_t i = 0; i < m_impl->Nodes.size(); ++i)
@ -348,46 +366,22 @@ void PathfinderWaypoint::ShowNodes()
}
}
void PathfinderWaypoint::ShowPath(const glm::vec3 &start, const glm::vec3 &end)
void PathfinderWaypoint::ShowPath(Client *c, const glm::vec3 &start, const glm::vec3 &end)
{
auto path = FindRoute(start, end);
std::vector<FindPerson_Point> points;
FindPerson_Point p;
for (auto &node : path)
{
auto npc_type = new NPCType;
memset(npc_type, 0, sizeof(NPCType));
sprintf(npc_type->name, "Path");
npc_type->cur_hp = 4000000;
npc_type->max_hp = 4000000;
npc_type->race = 2254;
npc_type->gender = 2;
npc_type->class_ = 9;
npc_type->deity = 1;
npc_type->level = 75;
npc_type->npc_id = 0;
npc_type->loottable_id = 0;
npc_type->texture = 1;
npc_type->light = 0;
npc_type->runspeed = 0;
npc_type->d_melee_texture1 = 1;
npc_type->d_melee_texture2 = 1;
npc_type->merchanttype = 1;
npc_type->bodytype = 1;
npc_type->STR = 150;
npc_type->STA = 150;
npc_type->DEX = 150;
npc_type->AGI = 150;
npc_type->INT = 150;
npc_type->WIS = 150;
npc_type->CHA = 150;
npc_type->findable = 1;
auto position = glm::vec4(node.x, node.y, node.z, 0.0f);
auto npc = new NPC(npc_type, nullptr, position, FlyMode1);
npc->GiveNPCTypeData(npc_type);
entity_list.AddNPC(npc, true, true);
if (!node.teleport) {
p.x = node.pos.x;
p.y = node.pos.y;
p.z = node.pos.z;
points.push_back(p);
}
}
c->SendPathPacket(points);
}

View File

@ -1,7 +1,8 @@
#pragma once
#include "pathfinder_interface.h"
#include <memory>
struct PathFileHeader;
class PathfinderWaypoint : public IPathfinder
{
@ -14,8 +15,10 @@ public:
virtual void DebugCommand(Client *c, const Seperator *sep);
private:
void LoadV2(FILE *f, const PathFileHeader &header);
void LoadV3(FILE *f, const PathFileHeader &header);
void ShowNodes();
void ShowPath(const glm::vec3 &start, const glm::vec3 &end);
void ShowPath(Client *c, const glm::vec3 &start, const glm::vec3 &end);
struct Implementation;
std::unique_ptr<Implementation> m_impl;

File diff suppressed because it is too large Load Diff

View File

@ -1,112 +0,0 @@
#ifndef PATHING_H
#define PATHING_H
#include "map.h"
#include "zone_config.h"
#include <deque>
extern const ZoneConfig *Config;
class Client;
class Mob;
#define PATHNODENEIGHBOURS 50
#pragma pack(1)
struct AStarNode
{
int PathNodeID;
int Parent;
float HCost;
float GCost;
bool Teleport;
};
struct NeighbourNode {
int16 id;
float distance;
uint8 Teleport;
int16 DoorID;
};
struct PathNode {
uint16 id;
glm::vec3 v;
float bestz;
NeighbourNode Neighbours[PATHNODENEIGHBOURS];
};
struct PathFileHeader {
uint32 version;
uint32 PathNodeCount;
};
#pragma pack()
struct PathNodeSortStruct
{
int id;
float Distance;
};
enum LOSType{ UnknownLOS, HaveLOS, NoLOS };
class PathManager {
public:
PathManager();
~PathManager();
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);
void PrintPathing();
bool CheckLosFN(glm::vec3 a, glm::vec3 b);
bool NoHazards(glm::vec3 From, glm::vec3 To);
bool NoHazardsAccurate(glm::vec3 From, glm::vec3 To);
void OpenDoors(int Node1, int Node2, Mob* ForWho);
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);
bool DeleteNode(int32 id); //returns true on success, false on failure, tries to delete a node from this map
void ConnectNodeToNode(Client *c, int32 Node2, int32 teleport = 0, int32 doorid = -1); //connects a node both ways
void ConnectNodeToNode(int32 Node1, int32 Node2, int32 teleport = 0, int32 doorid = -1);
void ConnectNode(Client *c, int32 Node2, int32 teleport = 0, int32 doorid = -1); //connects a node one way
void ConnectNode(int32 Node1, int32 Node2, int32 teleport = 0, int32 doorid = -1);
void DisconnectNodeToNode(Client *c, int32 Node2);
void DisconnectNodeToNode(int32 Node1, int32 Node2);
void MoveNode(Client *c);
void DisconnectAll(Client *c);
bool NodesConnected(PathNode *a, PathNode *b);
void DumpPath(std::string filename);
void ProcessNodesAndSave(std::string filename);
void ResortConnections();
void QuickConnect(Client *c, bool set = false);
void SortNodes();
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;
int *ClosedListFlag;
};
#endif