diff --git a/samp-npcs.sln b/samp-npcs.sln new file mode 100644 index 0000000..273f64b --- /dev/null +++ b/samp-npcs.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.30804.86 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "samp-npcs", "samp-npcs\samp-npcs.vcxproj", "{C22E627F-89B3-420A-AA08-903CB9BE7382}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C22E627F-89B3-420A-AA08-903CB9BE7382}.Debug|x64.ActiveCfg = Debug|x64 + {C22E627F-89B3-420A-AA08-903CB9BE7382}.Debug|x64.Build.0 = Debug|x64 + {C22E627F-89B3-420A-AA08-903CB9BE7382}.Debug|x86.ActiveCfg = Debug|Win32 + {C22E627F-89B3-420A-AA08-903CB9BE7382}.Debug|x86.Build.0 = Debug|Win32 + {C22E627F-89B3-420A-AA08-903CB9BE7382}.Release|x64.ActiveCfg = Release|x64 + {C22E627F-89B3-420A-AA08-903CB9BE7382}.Release|x64.Build.0 = Release|x64 + {C22E627F-89B3-420A-AA08-903CB9BE7382}.Release|x86.ActiveCfg = Release|Win32 + {C22E627F-89B3-420A-AA08-903CB9BE7382}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {1A897BC0-C32B-4A52-908C-81A4A030DAB1} + EndGlobalSection +EndGlobal diff --git a/samp-npcs/DEFINE.def b/samp-npcs/DEFINE.def new file mode 100644 index 0000000..020fda5 --- /dev/null +++ b/samp-npcs/DEFINE.def @@ -0,0 +1,5 @@ +EXPORTS + Supports + Load + Unload + ProcessTick \ No newline at end of file diff --git a/samp-npcs/main.cpp b/samp-npcs/main.cpp new file mode 100644 index 0000000..68ef1b6 --- /dev/null +++ b/samp-npcs/main.cpp @@ -0,0 +1,30 @@ +#include "paths.h" + +#define SAMP_PLUGIN_VERSION 0x0200 + +enum SUPPORTS_FLAGS +{ + SUPPORTS_VERSION = SAMP_PLUGIN_VERSION, + SUPPORTS_VERSION_MASK = 0xffff, + SUPPORTS_AMX_NATIVES = 0x10000, + SUPPORTS_PROCESS_TICK = 0x20000 +}; + +unsigned int __stdcall Supports() +{ + return SUPPORTS_VERSION | SUPPORTS_PROCESS_TICK; +} + +int __stdcall Load(void** ppData) +{ + loadPaths(); + return 1; +} + +void __stdcall Unload() +{ +} + +void __stdcall ProcessTick() +{ +} \ No newline at end of file diff --git a/samp-npcs/paths.cpp b/samp-npcs/paths.cpp new file mode 100644 index 0000000..c8e064f --- /dev/null +++ b/samp-npcs/paths.cpp @@ -0,0 +1,129 @@ +#include "paths.h" +#include +#include + +PathsData pathsData; + +void loadPaths() { + std::vector files; + + for (const auto& entry : std::filesystem::directory_iterator(PATH)) { + const auto path = entry.path().string(); + + if (!std::regex_match(path, std::regex(".*NODES\\d{1,2}\\.DAT", std::regex_constants::icase))) + continue; + + files.push_back(fopen(path.c_str(), "rb")); + } + + for (FILE* file : files) { + SerializedHeader header = parseHeader(file); + pathsData.num_nodes += header.num_nodes; + pathsData.num_vehicle_nodes += header.num_vehicle_nodes; + pathsData.num_ped_nodes += header.num_ped_nodes; + pathsData.num_nav_nodes += header.num_nav_nodes; + pathsData.num_links += header.num_links; + fseek(file, 0, SEEK_SET); + } + + pathsData.pathNodes = (PathNode*)malloc(pathsData.num_nodes * sizeof(PathNode)); + pathsData.navNodes = (NavNode*)malloc(pathsData.num_nav_nodes * sizeof(NavNode)); + pathsData.links = (Link*)malloc(pathsData.num_links * sizeof(Link)); + pathsData.navLinks = (NavLink*)malloc(pathsData.num_links * sizeof(NavLink)); + pathsData.linkLengths = (LinkLength*)malloc(pathsData.num_links * sizeof(LinkLength)); + pathsData.intersectionFlags = (IntersectionFlags*)malloc(pathsData.num_links * sizeof(IntersectionFlags)); + + PathsData pathsDataPointers = pathsData; + for (FILE* file : files) { + parsePathsFile(file, &pathsDataPointers); + } + + for (FILE* file : files) { + fclose(file); + } +} + +void parsePathsFile(FILE* file, PathsData* pathsData) { + SerializedHeader header = parseHeader(file); + + for (unsigned int i = 0; i < header.num_nodes; i++) { + parseNode(file, pathsData->pathNodes); + pathsData->pathNodes++; + } + + for (unsigned int i = 0; i < header.num_nav_nodes; i++) { + parseNav(file, pathsData->navNodes); + pathsData->navNodes++; + } + + for (unsigned int i = 0; i < header.num_links; i++) { + parseLink(file, pathsData->links); + pathsData->links++; + } + + fseek(file, 768, SEEK_CUR); // Filler? + + for (unsigned int i = 0; i < header.num_links; i++) { + parseNavLink(file, pathsData->navLinks); + pathsData->navLinks++; + } + + for (unsigned int i = 0; i < header.num_links; i++) { + parseLinkLengths(file, pathsData->linkLengths); + pathsData->linkLengths++; + } + + for (unsigned int i = 0; i < header.num_links; i++) { + parseIntersectionFlags(file, pathsData->intersectionFlags); + pathsData->intersectionFlags++; + } +} + +SerializedHeader parseHeader(FILE* file) { + SerializedHeader header; + fread(&header, sizeof(header), 1, file); + return header; +} + +void parseNode(FILE* file, PathNode* node) { + SerializedPathNode serializedNode; + fread(&serializedNode, sizeof(serializedNode), 1, file); + node->position_x = serializedNode.position_x / 8.f; + node->position_y = serializedNode.position_y / 8.f; + node->position_z = serializedNode.position_z / 8.f; + node->cost = serializedNode.cost; + node->link = serializedNode.link; + node->area = serializedNode.area; + node->node = serializedNode.node; + node->width = serializedNode.width; + node->flood_fill = serializedNode.flood_fill; + node->flags = serializedNode.flags; +} + +void parseNav(FILE* file, NavNode* node) { + SerializedNavNode serializedNode; + fread(&serializedNode, sizeof(serializedNode), 1, file); + node->position_x = serializedNode.position_x / 8.f; + node->position_y = serializedNode.position_y / 8.f; + node->area = serializedNode.area; + node->node = serializedNode.node; + node->direction_x = serializedNode.direction_x / 100.f; + node->direction_y = serializedNode.direction_y / 100.f; + node->flags = serializedNode.flags; +} + +void parseLink(FILE* file, Link* link) { + fread(link, sizeof(Link), 1, file); +} + +void parseNavLink(FILE* file, NavLink* link) { + fread(link, sizeof(NavLink), 1, file); +} + +void parseLinkLengths(FILE* file, LinkLength* length) { + fread(length, sizeof(LinkLength), 1, file); +} + +void parseIntersectionFlags(FILE* file, IntersectionFlags* flags) { + fread(flags, sizeof(IntersectionFlags), 1, file); +} diff --git a/samp-npcs/paths.h b/samp-npcs/paths.h new file mode 100644 index 0000000..7cb7704 --- /dev/null +++ b/samp-npcs/paths.h @@ -0,0 +1,94 @@ +#pragma once +#define _CRT_SECURE_NO_WARNINGS + +#include +#include + +#define PATH "plugins/samp-npcs/Paths/" + +#pragma pack(push, 1) +struct SerializedHeader { + unsigned int num_nodes; + unsigned int num_vehicle_nodes; + unsigned int num_ped_nodes; + unsigned int num_nav_nodes; + unsigned int num_links; +}; + +struct SerializedPathNode { + unsigned int _mem_addr, _nulls; + short position_x, position_y, position_z; + short cost; + unsigned short link, area, node; + unsigned char width; + unsigned char flood_fill; + unsigned int flags; +}; + +struct SerializedNavNode { + short position_x, position_y; + unsigned short area, node; + char direction_x, direction_y; + unsigned int flags; +}; + +struct SerializedLink { + unsigned short area, node; +}; + +struct SerializedNavLink { + unsigned short nav_node : 10; + unsigned short area : 6; +}; + +struct SerializedLinkLength { + unsigned char length; +}; + +struct SerializedIntersectionFlags { + bool road_cross : 1; + bool ped_traffic_light : 1; +}; +#pragma pack(pop) + +struct PathNode { + float position_x, position_y, position_z; + short cost; + unsigned short link, area, node; + unsigned char width; + unsigned char flood_fill; + unsigned int flags; +}; + +struct NavNode { + float position_x, position_y; + unsigned short area, node; + float direction_x, direction_y; + unsigned int flags; +}; + +struct Link : SerializedLink {}; +struct NavLink : SerializedNavLink {}; +struct LinkLength : SerializedLinkLength {}; +struct IntersectionFlags : SerializedIntersectionFlags {}; + +struct PathsData : SerializedHeader { + PathNode* pathNodes; + NavNode* navNodes; + Link* links; + NavLink* navLinks; + LinkLength* linkLengths; + IntersectionFlags* intersectionFlags; +}; + +extern PathsData pathsData; + +void loadPaths(); +void parsePathsFile(FILE* file, PathsData* pathsData); +SerializedHeader parseHeader(FILE* file); +void parseNode(FILE* file, PathNode* node); +void parseNav(FILE* file, NavNode* node); +void parseLink(FILE* file, Link* link); +void parseNavLink(FILE* file, NavLink* link); +void parseLinkLengths(FILE* file, LinkLength* length); +void parseIntersectionFlags(FILE* file, IntersectionFlags* flags); diff --git a/samp-npcs/samp-npcs.vcxproj b/samp-npcs/samp-npcs.vcxproj new file mode 100644 index 0000000..5ba71e1 --- /dev/null +++ b/samp-npcs/samp-npcs.vcxproj @@ -0,0 +1,172 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + + + + + + + + + + + 16.0 + Win32Proj + {c22e627f-89b3-420a-aa08-903cb9be7382} + sampnpcs + 10.0 + + + + DynamicLibrary + true + v142 + Unicode + + + DynamicLibrary + false + v142 + true + Unicode + + + DynamicLibrary + true + v142 + Unicode + + + DynamicLibrary + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + ..\..\..\..\..\..\Users\Emily\Documents\servers\samp\plugins + + + false + + + true + + + false + + + + Level3 + true + WIN32;_DEBUG;SAMPNPCS_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + NotUsing + pch.h + stdcpp17 + + + Windows + true + false + DEFINE.def + + + + + Level3 + true + true + true + WIN32;NDEBUG;SAMPNPCS_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + Use + pch.h + + + Windows + true + true + true + false + DEFINE.def + + + + + Level3 + true + _DEBUG;SAMPNPCS_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + Use + pch.h + + + Windows + true + false + DEFINE.def + + + + + Level3 + true + true + true + NDEBUG;SAMPNPCS_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + Use + pch.h + + + Windows + true + true + true + false + DEFINE.def + + + + + + \ No newline at end of file diff --git a/samp-npcs/samp-npcs.vcxproj.filters b/samp-npcs/samp-npcs.vcxproj.filters new file mode 100644 index 0000000..050abeb --- /dev/null +++ b/samp-npcs/samp-npcs.vcxproj.filters @@ -0,0 +1,35 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + Source Files + + + + + Source Files + + + + + Header Files + + + \ No newline at end of file