The beginning of SaveAINFile

This commit is contained in:
Kawe Mazidjatari 2022-03-20 17:03:46 +01:00
parent 9b33e1b94e
commit 92edf22b07
5 changed files with 178 additions and 156 deletions

View File

@ -151,6 +151,7 @@ void Systems_Init()
//DebugOverlays_Attach();
#endif // !DEDICATED
CAI_Utility_Attach();
CAI_NetworkManager_Attach();
// Patch instructions
RuntimePtc_Init();
@ -242,6 +243,7 @@ void Systems_Shutdown()
//DebugOverlays_Detach();
#endif // !DEDICATED
CAI_Utility_Detach();
CAI_NetworkManager_Detach();
// Commit the transaction
DetourTransactionCommit();

View File

@ -9,7 +9,7 @@
class CAI_Network
{
public:
char unk0[8]; // +0
void* m_pVTable;
// this is uninitialised and never set on ain build, fun!
int linkcount; // +8
@ -25,9 +25,11 @@ public:
// these probably aren't actually hints, but there's 1 of them per hint so idk
short hints[2000]; // +168
int scriptnodecount; // +4168
char pad[28]; // unk
int64_t nodecount; // +4200
CAI_Node** nodes; // +4208
CAI_ScriptNode scriptnodes[4000]; // +4172
int nodecount; // +84172
CAI_Node** nodes; // +84176
public:
static void BuildAINFile(CAI_Network* aiNetwork);

View File

@ -30,184 +30,187 @@ CAI_NetworkBuilder::BuildFile
*/
void CAI_NetworkBuilder::BuildFile(CAI_Network* pNetwork)
{
//std::filesystem::path fsWritePath("platform/maps/graphs");
//fsWritePath /= g_pHostState->m_levelName;
//fsWritePath += ".ain";
std::filesystem::path fsWritePath("platform\\maps\\graphs\\");
fsWritePath /= g_pHostState->m_levelName;
fsWritePath += ".ain";
//// Dump from memory.
//DevMsg(eDLL_T::SERVER, "++++--------------------------------------------------------------------------------------------------------------------------++++\n");
//DevMsg(eDLL_T::SERVER, ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> AI NODE GRAPH FILE CONSTRUCTION STARTED <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
//DevMsg(eDLL_T::SERVER, "++++--------------------------------------------------------------------------------------------------------------------------++++\n");
//DevMsg(eDLL_T::SERVER, "Output file: '%s'\n", fsWritePath.string());
// Dump from memory.
DevMsg(eDLL_T::SERVER, "++++--------------------------------------------------------------------------------------------------------------------------++++\n");
DevMsg(eDLL_T::SERVER, ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> AI NETWORK GRAPH FILE CONSTRUCTION STARTED <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
DevMsg(eDLL_T::SERVER, "++++--------------------------------------------------------------------------------------------------------------------------++++\n");
DevMsg(eDLL_T::SERVER, "Output file: '%s'\n", fsWritePath.string().c_str());
//std::ofstream writeStream(fsWritePath, std::ofstream::binary);
//DevMsg(eDLL_T::SERVER, "Writing AINet version: %d\n", AINET_VERSION_NUMBER);
//writeStream.write((char*)&AINET_VERSION_NUMBER, sizeof(int));
std::ofstream writeStream(fsWritePath, std::ofstream::binary);
DevMsg(eDLL_T::SERVER, "Writing AINet version: '%d'\n", AINET_VERSION_NUMBER);
writeStream.write((char*)&AINET_VERSION_NUMBER, sizeof(int));
//// Could probably be cleaner but whatever
////int nMapVersion = *(int*)(*pUnkServerMapversionGlobal + 104); // TODO: Find in apex
////DevMsg(eDLL_T::SERVER, "Writing map version: %d\n", nMapVersion); // temp
////writeStream.write((char*)&nMapVersion, sizeof(int));
int nMapVersion = g_ServerGlobalVariables->m_nMapVersion;
DevMsg(eDLL_T::SERVER, "Writing map version: '%d'\n", nMapVersion);
writeStream.write((char*)&nMapVersion, sizeof(int));
//DevMsg(eDLL_T::SERVER, "Writing placeholder crc: %d\n", PLACEHOLDER_CRC);
//writeStream.write((char*)&PLACEHOLDER_CRC, sizeof(int));
DevMsg(eDLL_T::SERVER, "Writing placeholder CRC: '%d'\n", PLACEHOLDER_CRC);
writeStream.write((char*)&PLACEHOLDER_CRC, sizeof(int));
//int nCalculatedLinkcount = 0;
int nCalculatedLinkcount = 0;
//// Path nodes
//DevMsg(eDLL_T::SERVER, "Writing nodecount: %d\n", pNetwork->nodecount);
//writeStream.write((char*)&pNetwork->nodecount, sizeof(int));
// Path nodes
DevMsg(eDLL_T::SERVER, "Writing nodecount: '%d'\n", pNetwork->nodecount);
writeStream.write((char*)&pNetwork->nodecount, sizeof(int));
//for (int i = 0; i < pNetwork->nodecount; i++)
//{
// // construct on-disk node struct
// CAI_NodeDisk diskNode{};
// diskNode.x = pNetwork->nodes[i]->x;
// diskNode.y = pNetwork->nodes[i]->y;
// diskNode.z = pNetwork->nodes[i]->z;
// diskNode.yaw = pNetwork->nodes[i]->yaw;
// memcpy(diskNode.hulls, pNetwork->nodes[i]->hulls, sizeof(diskNode.hulls));
// diskNode.unk0 = (char)pNetwork->nodes[i]->unk0;
// diskNode.unk1 = pNetwork->nodes[i]->unk1;
for (int i = 0; i < pNetwork->nodecount; i++)
{
sizeof(CAI_Network);
// for (int j = 0; j < MAX_HULLS; j++)
// {
// diskNode.unk2[j] = (short)pNetwork->nodes[i]->unk2[j];
// spdlog::info((short)pNetwork->nodes[i]->unk2[j]);
// }
// Construct on-disk node struct.
CAI_NodeDisk diskNode{};
diskNode.x = pNetwork->nodes[i]->x;
diskNode.y = pNetwork->nodes[i]->y;
diskNode.z = pNetwork->nodes[i]->z;
diskNode.yaw = pNetwork->nodes[i]->yaw;
memcpy(diskNode.hulls, pNetwork->nodes[i]->hulls, sizeof(diskNode.hulls));
diskNode.unk0 = (char)pNetwork->nodes[i]->unk0;
diskNode.unk1 = pNetwork->nodes[i]->unk1;
// memcpy(diskNode.unk3, pNetwork->nodes[i]->unk3, sizeof(diskNode.unk3));
// diskNode.unk4 = pNetwork->nodes[i]->unk6;
// diskNode.unk5 =
// -1; // aiNetwork->nodes[i]->unk8; // This field is wrong, however it's always -1 in original navmeshes anyway.
// memcpy(diskNode.unk6, pNetwork->nodes[i]->unk10, sizeof(diskNode.unk6));
for (int j = 0; j < MAX_HULLS; j++)
{
diskNode.unk2[j] = (short)pNetwork->nodes[i]->unk2[j];
spdlog::info((short)pNetwork->nodes[i]->unk2[j]);
}
// DevMsg(eDLL_T::SERVER, "Writing node %d from %d to %x\n", pNetwork->nodes[i]->index, (void*)pNetwork->nodes[i], writeStream.tellp());
// writeStream.write((char*)&diskNode, sizeof(CAI_NodeDisk));
memcpy(diskNode.unk3, pNetwork->nodes[i]->unk3, sizeof(diskNode.unk3));
diskNode.unk4 = pNetwork->nodes[i]->unk6;
diskNode.unk5 = -1; // aiNetwork->nodes[i]->unk8; // This field is wrong, however it's always -1 in original navmeshes anyway.
memcpy(diskNode.unk6, pNetwork->nodes[i]->unk10, sizeof(diskNode.unk6));
// nCalculatedLinkcount += pNetwork->nodes[i]->linkcount;
//}
DevMsg(eDLL_T::SERVER, "Writing node '%d' from '%d' to '%x'\n", pNetwork->nodes[i]->index, (void*)pNetwork->nodes[i], writeStream.tellp());
writeStream.write((char*)&diskNode, sizeof(CAI_NodeDisk));
//// links
//DevMsg(eDLL_T::SERVER, "Linkcount: %d\n", pNetwork->linkcount);
//DevMsg(eDLL_T::SERVER, "Calculated total linkcount: %d\n", nCalculatedLinkcount);
nCalculatedLinkcount += pNetwork->nodes[i]->linkcount;
}
//nCalculatedLinkcount /= 2;
//if (ai_dumpAINfileFromLoad->GetBool())
//{
// if (pNetwork->linkcount == nCalculatedLinkcount)
// DevMsg(eDLL_T::SERVER, "Caculated linkcount is normal!");
// else
// DevMsg(eDLL_T::SERVER, "Calculated linkcount has weird value! this is expected on build!");
//}
// links
DevMsg(eDLL_T::SERVER, "Linkcount: '%d'\n", pNetwork->linkcount);
DevMsg(eDLL_T::SERVER, "Calculated total linkcount: '%d'\n", nCalculatedLinkcount);
//spdlog::info("Writing linkcount: %d\n", nCalculatedLinkcount);
//writeStream.write((char*)&nCalculatedLinkcount, sizeof(int));
nCalculatedLinkcount /= 2;
if (ai_dumpAINfileFromLoad->GetBool())
{
if (pNetwork->linkcount == nCalculatedLinkcount)
{
DevMsg(eDLL_T::SERVER, "Caculated linkcount is normal!");
}
else
{
DevMsg(eDLL_T::SERVER, "Calculated linkcount has unexpected value. This is expected on build!");
}
}
//for (int i = 0; i < pNetwork->nodecount; i++)
//{
// for (int j = 0; j < pNetwork->nodes[i]->linkcount; j++)
// {
// // skip links that don't originate from current node
// if (pNetwork->nodes[i]->links[j]->srcId != pNetwork->nodes[i]->index)
// continue;
DevMsg(eDLL_T::SERVER, "Writing linkcount: '%d'\n", nCalculatedLinkcount);
writeStream.write((char*)&nCalculatedLinkcount, sizeof(int));
// CAI_NodeLinkDisk diskLink{};
// diskLink.srcId = pNetwork->nodes[i]->links[j]->srcId;
// diskLink.destId = pNetwork->nodes[i]->links[j]->destId;
// diskLink.unk0 = pNetwork->nodes[i]->links[j]->unk1;
// memcpy(diskLink.hulls, pNetwork->nodes[i]->links[j]->hulls, sizeof(diskLink.hulls));
for (int i = 0; i < pNetwork->nodecount; i++)
{
for (int j = 0; j < pNetwork->nodes[i]->linkcount; j++)
{
// skip links that don't originate from current node
if (pNetwork->nodes[i]->links[j]->srcId != pNetwork->nodes[i]->index)
continue;
// DevMsg(eDLL_T::SERVER, "Writing link %d => %d to %x\n", diskLink.srcId, diskLink.destId, writeStream.tellp());
// writeStream.write((char*)&diskLink, sizeof(CAI_NodeLinkDisk));
// }
//}
CAI_NodeLinkDisk diskLink{};
diskLink.srcId = pNetwork->nodes[i]->links[j]->srcId;
diskLink.destId = pNetwork->nodes[i]->links[j]->destId;
diskLink.unk0 = pNetwork->nodes[i]->links[j]->unk1;
memcpy(diskLink.hulls, pNetwork->nodes[i]->links[j]->hulls, sizeof(diskLink.hulls));
//// Don't know what this is, it's likely a block from tf1 that got deprecated? should just be 1 int per node
//DevMsg(eDLL_T::SERVER, "Writing %x bytes for unknown block at %x\n", pNetwork->nodecount * sizeof(uint32_t), writeStream.tellp());
//uint32_t* unkNodeBlock = new uint32_t[pNetwork->nodecount];
//memset(unkNodeBlock, 0, pNetwork->nodecount * sizeof(uint32_t));
//writeStream.write((char*)unkNodeBlock, pNetwork->nodecount * sizeof(uint32_t));
//delete[] unkNodeBlock;
DevMsg(eDLL_T::SERVER, "Writing link '%d' => '%d' to '%x'\n", diskLink.srcId, diskLink.destId, writeStream.tellp());
writeStream.write((char*)&diskLink, sizeof(CAI_NodeLinkDisk));
}
}
//// TODO: this is traverse nodes i think? these aren't used in tf2 ains so we can get away with just writing count=0 and skipping
//// but ideally should actually dump these
//DevMsg(eDLL_T::SERVER, "Writing %d traversal nodes at %x\n", 0, writeStream.tellp());
//short traverseNodeCount = 0;
//writeStream.write((char*)&traverseNodeCount, sizeof(short));
//// Only write count since count=0 means we don't have to actually do anything here
// Don't know what this is, it's likely a block from tf1 that got deprecated? should just be 1 int per node
DevMsg(eDLL_T::SERVER, "Writing '%x' bytes for unknown block at '%x'\n", pNetwork->nodecount * sizeof(uint32_t), writeStream.tellp());
uint32_t* unkNodeBlock = new uint32_t[pNetwork->nodecount];
memset(unkNodeBlock, 0, pNetwork->nodecount * sizeof(uint32_t));
writeStream.write((char*)unkNodeBlock, pNetwork->nodecount * sizeof(uint32_t));
delete[] unkNodeBlock;
//// TODO: ideally these should be actually dumped, but they're always 0 in tf2 from what i can tell
//DevMsg(eDLL_T::SERVER, "Writing %d bytes for unknown hull block at %x\n", MAX_HULLS * 8, writeStream.tellp());
//char* unkHullBlock = new char[MAX_HULLS * 8];
//memset(unkHullBlock, 0, MAX_HULLS * 8);
//writeStream.write(unkHullBlock, MAX_HULLS * 8);
//delete[] unkHullBlock;
// TODO: this is traverse nodes i think? these aren't used in tf2 ains so we can get away with just writing count=0 and skipping
// but ideally should actually dump these
DevMsg(eDLL_T::SERVER, "Writing '%d' traversal nodes at '%x'\n", 0, writeStream.tellp());
short traverseNodeCount = 0;
writeStream.write((char*)&traverseNodeCount, sizeof(short));
// Only write count since count=0 means we don't have to actually do anything here
//// Snknown struct that's seemingly node-related
//DevMsg(eDLL_T::SERVER, "Writing %d unknown node structs at %x\n", *pUnkStruct0Count, writeStream.tellp());
//writeStream.write((char*)pUnkStruct0Count, sizeof(*pUnkStruct0Count));
//for (int i = 0; i < *pUnkStruct0Count; i++)
//{
// DevMsg(eDLL_T::SERVER, "Writing unknown node struct %d at %x\n", i, writeStream.tellp());
// UnkNodeStruct0* nodeStruct = (*pppUnkNodeStruct0s)[i];
// TODO: ideally these should be actually dumped, but they're always 0 in tf2 from what i can tell
DevMsg(eDLL_T::SERVER, "Writing '%d' bytes for unknown hull block at '%x'\n", MAX_HULLS * 8, writeStream.tellp());
char* unkHullBlock = new char[MAX_HULLS * 8];
memset(unkHullBlock, 0, MAX_HULLS * 8);
writeStream.write(unkHullBlock, MAX_HULLS * 8);
delete[] unkHullBlock;
// writeStream.write((char*)&nodeStruct->index, sizeof(nodeStruct->index));
// writeStream.write((char*)&nodeStruct->unk1, sizeof(nodeStruct->unk1));
DevMsg(eDLL_T::SERVER, "Writing '%d' node clusters at '%x'\n", *g_nAiNodeClusters, writeStream.tellp());
writeStream.write((char*)g_nAiNodeClusters, sizeof(*g_nAiNodeClusters));
for (int i = 0; i < *g_nAiNodeClusters; i++)
{
DevMsg(eDLL_T::SERVER, "Writing unknown node struct '%d' at '%x'\n", i, writeStream.tellp());
AINodeClusters* nodeClusters = (*g_pppAiNodeClusters)[i];
// writeStream.write((char*)&nodeStruct->x, sizeof(nodeStruct->x));
// writeStream.write((char*)&nodeStruct->y, sizeof(nodeStruct->y));
// writeStream.write((char*)&nodeStruct->z, sizeof(nodeStruct->z));
writeStream.write((char*)&nodeClusters->index, sizeof(nodeClusters->index));
writeStream.write((char*)&nodeClusters->unk1, sizeof(nodeClusters->unk1));
// writeStream.write((char*)&nodeStruct->unkcount0, sizeof(nodeStruct->unkcount0));
// for (int j = 0; j < nodeStruct->unkcount0; j++)
// {
// short unk2Short = (short)nodeStruct->unk2[j];
// writeStream.write((char*)&unk2Short, sizeof(unk2Short));
// }
writeStream.write((char*)&nodeClusters->x, sizeof(nodeClusters->x));
writeStream.write((char*)&nodeClusters->y, sizeof(nodeClusters->y));
writeStream.write((char*)&nodeClusters->z, sizeof(nodeClusters->z));
// writeStream.write((char*)&nodeStruct->unkcount1, sizeof(nodeStruct->unkcount1));
// for (int j = 0; j < nodeStruct->unkcount1; j++)
// {
// short unk3Short = (short)nodeStruct->unk3[j];
// writeStream.write((char*)&unk3Short, sizeof(unk3Short));
// }
writeStream.write((char*)&nodeClusters->unkcount0, sizeof(nodeClusters->unkcount0));
for (int j = 0; j < nodeClusters->unkcount0; j++)
{
short unk2Short = (short)nodeClusters->unk2[j];
writeStream.write((char*)&unk2Short, sizeof(unk2Short));
}
// writeStream.write((char*)&nodeStruct->unk5, sizeof(nodeStruct->unk5));
//}
writeStream.write((char*)&nodeClusters->unkcount1, sizeof(nodeClusters->unkcount1));
for (int j = 0; j < nodeClusters->unkcount1; j++)
{
short unk3Short = (short)nodeClusters->unk3[j];
writeStream.write((char*)&unk3Short, sizeof(unk3Short));
}
//// Unknown struct that's seemingly link-related
//DevMsg(eDLL_T::SERVER, "Writing %d unknown link structs at %x\n", *pUnkLinkStruct1Count, writeStream.tellp());
//writeStream.write((char*)pUnkLinkStruct1Count, sizeof(*pUnkLinkStruct1Count));
//for (int i = 0; i < *pUnkLinkStruct1Count; i++)
//{
// // disk and memory structs are literally identical here so just directly write
// DevMsg(eDLL_T::SERVER, "Writing unknown link struct %d at %x\n", i, writeStream.tellp());
// writeStream.write((char*)(*pppUnkStruct1s)[i], sizeof(*(*pppUnkStruct1s)[i]));
//}
writeStream.write((char*)&nodeClusters->unk5, sizeof(nodeClusters->unk5));
}
//// Some weird int idk what this is used for
//writeStream.write((char*)&pNetwork->unk5, sizeof(pNetwork->unk5));
// Unknown struct that's seemingly link-related
DevMsg(eDLL_T::SERVER, "Writing '%d' unknown link structs at '%x'\n", *g_nAiNodeClusterLinks, writeStream.tellp());
writeStream.write((char*)g_nAiNodeClusterLinks, sizeof(*g_nAiNodeClusterLinks));
for (int i = 0; i < *g_nAiNodeClusterLinks; i++)
{
// Disk and memory structs are literally identical here so just directly write.
DevMsg(eDLL_T::SERVER, "Writing unknown link struct '%d' at '%x'\n", i, writeStream.tellp());
writeStream.write((char*)(*g_pppAiNodeClusterLinks)[i], sizeof(*(*g_pppAiNodeClusterLinks)[i]));
}
//// Tf2-exclusive stuff past this point, i.e. ain v57 only
//DevMsg(eDLL_T::SERVER, "Writing %d script nodes at %x\n", pNetwork->scriptnodecount, writeStream.tellp());
//writeStream.write((char*)&pNetwork->scriptnodecount, sizeof(pNetwork->scriptnodecount));
//for (int i = 0; i < pNetwork->scriptnodecount; i++)
//{
// // disk and memory structs are literally identical here so just directly write
// DevMsg(eDLL_T::SERVER, "Writing script node %d at %x\n", i, writeStream.tellp());
// writeStream.write((char*)&pNetwork->scriptnodes[i], sizeof(pNetwork->scriptnodes[i]));
//}
// Some weird int idk what this is used for.
writeStream.write((char*)&pNetwork->unk5, sizeof(pNetwork->unk5));
//DevMsg(eDLL_T::SERVER, "Writing %d hints at %x\n", pNetwork->hintcount, writeStream.tellp());
//writeStream.write((char*)&pNetwork->hintcount, sizeof(pNetwork->hintcount));
//for (int i = 0; i < pNetwork->hintcount; i++)
//{
// DevMsg(eDLL_T::SERVER, "Writing hint data %d at %x\n", i, writeStream.tellp());
// writeStream.write((char*)&pNetwork->hints[i], sizeof(pNetwork->hints[i]));
//}
// Tf2-exclusive stuff past this point, i.e. ain v57 only.
DevMsg(eDLL_T::SERVER, "Writing '%d' script nodes at '%x'\n", pNetwork->scriptnodecount, writeStream.tellp());
writeStream.write((char*)&pNetwork->scriptnodecount, sizeof(pNetwork->scriptnodecount));
for (int i = 0; i < pNetwork->scriptnodecount; i++)
{
// disk and memory structs are literally identical here so just directly write
//DevMsg(eDLL_T::SERVER, "Writing script node %d at %x\n", i, writeStream.tellp());
//writeStream.write((char*)&pNetwork->scriptnodes[i], sizeof(pNetwork->scriptnodes[i]));
}
//writeStream.close();
DevMsg(eDLL_T::SERVER, "Writing '%d' hints at '%x'\n", pNetwork->hintcount, writeStream.tellp());
writeStream.write((char*)&pNetwork->hintcount, sizeof(pNetwork->hintcount));
for (int i = 0; i < pNetwork->hintcount; i++)
{
DevMsg(eDLL_T::SERVER, "Writing hint data '%d' at '%x'\n", i, writeStream.tellp());
writeStream.write((char*)&pNetwork->hints[i], sizeof(pNetwork->hints[i]));
}
writeStream.close();
}
void HCAI_NetworkManager__LoadNetworkGraph(void* aimanager, void* buf, const char* filename)
@ -220,15 +223,14 @@ void HCAI_NetworkManager__LoadNetworkGraph(void* aimanager, void* buf, const cha
if (ai_dumpAINfileFromLoad->GetBool())
{
DevMsg(eDLL_T::SERVER, "Running BuildAINFile for loaded file %s\n", filename);
CAI_NetworkBuilder::BuildFile(*(CAI_Network**)((char*)aimanager + 2536)); // TODO: Verify in r5apex.exe.
DevMsg(eDLL_T::SERVER, "Running BuildAINFile for loaded file '%s'\n", filename);
CAI_NetworkBuilder::BuildFile(*(CAI_Network**)((char*)aimanager + 2840));
}
}
void HCAI_NetworkBuilder__Build(void* builder, CAI_Network* aiNetwork, void* a3, int a4)
{
CAI_NetworkBuilder__Build(builder, aiNetwork, a3, a4);
CAI_NetworkBuilder::BuildFile(aiNetwork);
}

View File

@ -23,11 +23,27 @@ namespace
ADDRESS p_CAI_NetworkBuilder__Build = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x48\x89\x5C\x24\x00\x48\x89\x6C\x24\x00\x48\x89\x74\x24\x00\x48\x89\x4C\x24\x00\x57\x41\x54\x41\x55\x41\x56\x41\x57\x48\x83\xEC\x30\x48\x63\xBA\x00\x00\x00\x00", "xxxx?xxxx?xxxx?xxxx?xxxxxxxxxxxxxxxx????");
void* (*CAI_NetworkBuilder__Build)(void* thisptr, CAI_Network* pNetWork, void* a3, int a4) = (void* (*)(void*, CAI_Network*, void*, int))p_CAI_NetworkBuilder__Build.GetPtr(); /*48 89 5C 24 ? 48 89 6C 24 ? 48 89 74 24 ? 48 89 4C 24 ? 57 41 54 41 55 41 56 41 57 48 83 EC 30 48 63 BA ? ? ? ?*/
#elif defined (GAMEDLL_S2) || defined (GAMEDLL_S3)
ADDRESS p_CAI_NetworkBuilder__Build = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x40\x53\x48\x83\xEC\x20\x48\x8B\xD9\x48\x8B\x0D\x00\x00\x00\x00\x8B\x41\x6C", "xxxxxxxxxxxx????xxx");
ADDRESS p_CAI_NetworkBuilder__Build = g_mGameDll.FindPatternSIMD((std::uint8_t*)"\x48\x89\x54\x24\x00\x48\x89\x4C\x24\x00\x53\x55\x56\x57\x41\x54\x41\x55\x41\x56\x41\x57\x48\x83\xEC\x38\x8B\xB2\x00\x00\x00\x00", "xxxx?xxxx?xxxxxxxxxxxxxxxxxx????");
void* (*CAI_NetworkBuilder__Build)(void* thisptr, CAI_Network* pNetWork, void* a3, int a4) = (void* (*)(void*, CAI_Network*, void*, int))p_CAI_NetworkBuilder__Build.GetPtr(); /*48 89 54 24 ? 48 89 4C 24 ? 53 55 56 57 41 54 41 55 41 56 41 57 48 83 EC 38 8B B2 ? ? ? ?*/
#endif
}
void CAI_NetworkManager_Attach();
void CAI_NetworkManager_Detach();
// dword_165DAD808 = g_nAiNodeClusters
// qword_165DAD7F0 = pppUnkNodeStruct0s
// dword_165DB18E8 = g_nAiNodeClusterLinks
// qword_165DB18D0 = pppUnkStruct1s
namespace // !TODO: [AMOS] don't hardocde.
{
int* g_nAiNodeClusters = ADDRESS(0x165DAD808).RCast<int*>();
AINodeClusters*** g_pppAiNodeClusters = ADDRESS(0x165DB18E8).RCast<AINodeClusters***>();
int* g_nAiNodeClusterLinks = ADDRESS(0x165DB18E8).RCast<int*>();
AINodeClusterLinks*** g_pppAiNodeClusterLinks = ADDRESS(0x165DB18E8).RCast<AINodeClusterLinks***>();
}
//-----------------------------------------------------------------------------
// CAI_NetworkBuilder
//

View File

@ -98,7 +98,7 @@ struct CAI_ScriptNode
uint64_t scriptdata;
};
struct UnkNodeStruct0
struct AINodeClusters
{
int index;
char unk0;
@ -126,7 +126,7 @@ struct UnkNodeStruct0
//int* pUnkStruct0Count;
//UnkNodeStruct0*** pppUnkNodeStruct0s;
struct UnkLinkStruct1
struct AINodeClusterLinks
{
short unk0;
short unk1;