find command uses new pathing system now which loads .nav files saved by map_edit, still in initial stages of testing. Fixed a bug where find might cause a desync in some cases as well.

This commit is contained in:
KimLS
2016-01-12 18:33:00 -08:00
parent c6e9fbc878
commit e61e2e7f02
57 changed files with 25463 additions and 653 deletions
+1 -3
View File
@@ -33,7 +33,6 @@ SET(zone_sources
horse.cpp
inventory.cpp
loottables.cpp
lua_behavior_interface.cpp
lua_bit.cpp
lua_corpse.cpp
lua_client.cpp
@@ -151,7 +150,6 @@ SET(zone_headers
guild_mgr.h
hate_list.h
horse.h
lua_behavior_interface.h
lua_bit.h
lua_client.h
lua_corpse.h
@@ -227,7 +225,7 @@ INSTALL(TARGETS zone RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX})
ADD_DEFINITIONS(-DZONE)
TARGET_LINK_LIBRARIES(zone common debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE} ${ZLIB_LIBRARY})
TARGET_LINK_LIBRARIES(zone common debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE} ${ZLIB_LIBRARY} recast_navigation)
IF(EQEMU_BUILD_PERL)
TARGET_LINK_LIBRARIES(zone ${PERL_LIBRARY})
+28
View File
@@ -8728,3 +8728,31 @@ uint32 Client::GetMoney(uint8 type, uint8 subtype) {
int Client::GetAccountAge() {
return (time(nullptr) - GetAccountCreation());
}
void Client::CreatePathFromRoute(const glm::vec3 &dest, const PathfindingRoute &route)
{
auto nodes = route.GetNodes();
if (nodes.size() < 2) {
EQApplicationPacket outapp(OP_FindPersonReply, 0);
QueuePacket(&outapp);
return;
}
EQApplicationPacket outapp(OP_FindPersonReply, (nodes.size() + 1) * 12);
int i = 0;
FindPerson_Point *point_buffer = (FindPerson_Point*)outapp.pBuffer;
point_buffer[i].x = dest.x;
point_buffer[i].y = dest.y;
point_buffer[i].z = dest.z;
i++;
for (auto &node : nodes) {
point_buffer[i].x = node.position.x;
point_buffer[i].y = node.position.y;
point_buffer[i].z = node.position.z;
i++;
}
QueuePacket(&outapp);
}
+1 -1
View File
@@ -759,7 +759,7 @@ public:
void ChangeTributeSettings(TributeInfo_Struct *t);
void SendTributeTimer();
void ToggleTribute(bool enabled);
void SendPathPacket(std::vector<FindPerson_Point> &path);
void CreatePathFromRoute(const glm::vec3 &dest, const PathfindingRoute &route);
inline PTimerList &GetPTimers() { return(p_timers); }
+3 -100
View File
@@ -5629,107 +5629,10 @@ void Client::Handle_OP_FindPersonRequest(const EQApplicationPacket *app)
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.size() == 0)
{
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);
glm::vec3 dest(target->GetX(), target->GetY(), target->GetZ());
auto route = zone->pathing_new.FindRoute(glm::vec3(GetX(), GetY(), GetZ()), dest);
CreatePathFromRoute(dest, route);
}
return;
}
void Client::Handle_OP_Fishing(const EQApplicationPacket *app)
-311
View File
@@ -290,7 +290,6 @@ int command_init(void)
command_add("packetprofile", "- Dump packet profile for target or self.", 250, command_packetprofile) ||
#endif
command_add("path", "- view and edit pathing", 200, command_path) ||
command_add("peekinv", "[worn/inv/cursor/trib/bank/trade/world/all] - Print out contents of your player target's inventory", 100, command_peekinv) ||
command_add("peqzone", "[zonename] - Go to specified zone, if you have > 75% health", 0, command_peqzone) ||
command_add("permaclass", "[classnum] - Change your or your player target's class (target is disconnected)", 80, command_permaclass) ||
@@ -6777,316 +6776,6 @@ void command_qglobal(Client *c, const Seperator *sep) {
c->Message(15, "Invalid action specified.");
}
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.");
}
void Client::Undye() {
for (int cur_slot = EmuConstants::MATERIAL_BEGIN; cur_slot <= EmuConstants::MATERIAL_END; cur_slot++ ) {
uint8 slot2=SlotConvert(cur_slot);
-1
View File
@@ -196,7 +196,6 @@ void command_optest(Client *c, const Seperator *sep);
void command_packetprofile(Client *c, const Seperator *sep);
#endif
void command_path(Client *c, const Seperator *sep);
void command_peekinv(Client *c, const Seperator *sep);
void command_peqzone(Client *c, const Seperator *sep);
void command_permaclass(Client *c, const Seperator *sep);
-166
View File
@@ -1,166 +0,0 @@
#ifdef LUA_EQEMU
#include "lua_behavior_interface.h"
#include <lua.hpp>
#include <luabind/luabind.hpp>
#include <luabind/object.hpp>
#include "masterentity.h"
#include "../common/spdat.h"
#include "lua_bit.h"
#include "lua_entity.h"
#include "lua_item.h"
#include "lua_iteminst.h"
#include "lua_mob.h"
#include "lua_hate_list.h"
#include "lua_client.h"
#include "lua_inventory.h"
#include "lua_npc.h"
#include "lua_spell.h"
#include "lua_entity_list.h"
#include "lua_group.h"
#include "lua_raid.h"
#include "lua_corpse.h"
#include "lua_object.h"
#include "lua_door.h"
#include "lua_spawn.h"
#include "lua_packet.h"
#include "lua_general.h"
LuaBehaviorInterface::LuaBehaviorInterface()
{
L = nullptr;
}
LuaBehaviorInterface::~LuaBehaviorInterface()
{
if (L) {
lua_close(L);
}
}
bool LuaBehaviorInterface::Init()
{
if (L) {
return false;
}
L = luaL_newstate();
luaL_openlibs(L);
if (luaopen_bit(L) != 1) {
return false;
}
if (luaL_dostring(L, "math.randomseed(os.time())")) {
return false;
}
#ifdef SANITIZE_LUA_LIBS
lua_pushnil(L);
lua_setglobal(L, "io");
lua_getglobal(L, "os");
lua_pushnil(L);
lua_setfield(L, -2, "exit");
lua_pushnil(L);
lua_setfield(L, -2, "execute");
lua_pushnil(L);
lua_setfield(L, -2, "getenv");
lua_pushnil(L);
lua_setfield(L, -2, "remove");
lua_pushnil(L);
lua_setfield(L, -2, "rename");
lua_pushnil(L);
lua_setfield(L, -2, "setlocale");
lua_pushnil(L);
lua_setfield(L, -2, "tmpname");
lua_pop(L, 1);
lua_pushnil(L);
lua_setglobal(L, "collectgarbage");
lua_pushnil(L);
lua_setglobal(L, "loadfile");
#endif
lua_getglobal(L, "package");
lua_getfield(L, -1, "path");
std::string module_path = lua_tostring(L, -1);
module_path += ";./lua_modules/?.lua";
lua_pop(L, 1);
lua_pushstring(L, module_path.c_str());
lua_setfield(L, -2, "path");
lua_pop(L, 1);
if (!MapFunctions()) {
return false;
}
std::string path = "ai/script_init.lua";
FILE *f = fopen(path.c_str(), "r");
if (f) {
fclose(f);
if (luaL_dofile(L, path.c_str())) {
return false;
}
}
return true;
}
bool LuaBehaviorInterface::MapFunctions()
{
try {
luabind::open(L);
luabind::module(L)
[
lua_register_general(),
lua_register_events(),
lua_register_faction(),
lua_register_slot(),
lua_register_material(),
lua_register_client_version(),
lua_register_appearance(),
lua_register_entity(),
lua_register_mob(),
lua_register_special_abilities(),
lua_register_npc(),
lua_register_client(),
lua_register_inventory(),
lua_register_inventory_where(),
lua_register_iteminst(),
lua_register_item(),
lua_register_spell(),
lua_register_spawn(),
lua_register_hate_entry(),
lua_register_hate_list(),
lua_register_entity_list(),
lua_register_mob_list(),
lua_register_client_list(),
lua_register_npc_list(),
lua_register_corpse_list(),
lua_register_object_list(),
lua_register_door_list(),
lua_register_spawn_list(),
lua_register_group(),
lua_register_raid(),
lua_register_corpse(),
lua_register_door(),
lua_register_object(),
lua_register_packet(),
lua_register_packet_opcodes()
];
}
catch (std::exception &ex) {
return false;
}
return true;
}
#endif
-25
View File
@@ -1,25 +0,0 @@
#ifndef EQEMU_LUA_BEHAVIOR_INTERFACE_H
#define EQEMU_LUA_BEHAVIOR_INTERFACE_H
#ifdef LUA_EQEMU
namespace luabind {
namespace adl {
class object;
}
}
struct lua_State;
class LuaBehaviorInterface
{
public:
LuaBehaviorInterface();
~LuaBehaviorInterface();
bool Init();
private:
bool MapFunctions();
lua_State *L;
};
#endif
#endif
-32
View File
@@ -1300,38 +1300,6 @@ void PathManager::OpenDoors(int Node1, int Node2, Mob *ForWho)
}
}
//this assumes that the first point in the list is the player's
//current position, I dont know how well it works if its not.
void Client::SendPathPacket(std::vector<FindPerson_Point> &points) {
if(points.size() < 2) {
//empty length packet == not found.
EQApplicationPacket outapp(OP_FindPersonReply, 0);
QueuePacket(&outapp);
return;
}
int len = sizeof(FindPersonResult_Struct) + (points.size()+1) * sizeof(FindPerson_Point);
EQApplicationPacket *outapp = new EQApplicationPacket(OP_FindPersonReply, len);
FindPersonResult_Struct* fpr=(FindPersonResult_Struct*)outapp->pBuffer;
std::vector<FindPerson_Point>::iterator cur, end;
cur = points.begin();
end = points.end();
unsigned int r;
for(r = 0; cur != end; ++cur, r++) {
fpr->path[r] = *cur;
}
//put the last element into the destination field
--cur;
fpr->path[r] = *cur;
fpr->dest = *cur;
FastQueuePacket(&outapp);
}
PathNode* PathManager::FindPathNodeByCoordinates(float x, float y, float z)
{
for(uint32 i = 0; i < Head.PathNodeCount; ++i)
+19 -14
View File
@@ -1708,14 +1708,6 @@ void QuestManager::showgrid(int grid) {
if(initiator == nullptr)
return;
FindPerson_Point pt;
std::vector<FindPerson_Point> pts;
pt.x = initiator->GetX();
pt.y = initiator->GetY();
pt.z = initiator->GetZ();
pts.push_back(pt);
// Retrieve all waypoints for this grid
std::string query = StringFormat("SELECT `x`,`y`,`z` FROM grid_entries "
"WHERE `gridid` = %i AND `zoneid` = %i "
@@ -1726,16 +1718,29 @@ void QuestManager::showgrid(int grid) {
return;
}
for(auto row = results.begin(); row != results.end(); ++row) {
pt.x = atof(row[0]);
pt.y = atof(row[1]);
pt.z = atof(row[2]);
PathfindingRoute route;
auto& nodes = route.GetNodesEdit();
PathfindingNode node;
node.position.x = initiator->GetX();
node.position.y = initiator->GetY();
node.position.z = initiator->GetZ();
nodes.push_back(node);
pts.push_back(pt);
for(auto row = results.begin(); row != results.end(); ++row) {
node.position.x = atof(row[0]);
node.position.y = atof(row[1]);
node.position.z = atof(row[2]);
nodes.push_back(node);
}
initiator->SendPathPacket(pts);
auto sz = nodes.size();
if (sz < 2) {
return;
}
glm::vec3 dest = nodes[sz].position;
initiator->CreatePathFromRoute(dest, route);
}
//change the value of a spawn condition
+1
View File
@@ -103,6 +103,7 @@ bool Zone::Bootup(uint32 iZoneID, uint32 iInstanceID, 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_new.Load(zone->map_name);
char tmp[10];
if (database.GetVariable("loglevel",tmp, 9)) {
+2
View File
@@ -24,6 +24,7 @@
#include "../common/types.h"
#include "../common/random.h"
#include "../common/string_util.h"
#include "../common/pathfind.h"
#include "qglobals.h"
#include "spawn2.h"
#include "spawngroup.h"
@@ -212,6 +213,7 @@ public:
Map* zonemap;
WaterMap* watermap;
PathManager *pathing;
PathfindingManager pathing_new;
NewZone_Struct newzone_data;
SpawnConditionManager spawn_conditions;