diff options
author | BobTheBob9 <for.oliver.kirkham@gmail.com> | 2022-07-07 21:31:41 +0100 |
---|---|---|
committer | BobTheBob9 <for.oliver.kirkham@gmail.com> | 2022-07-07 21:31:41 +0100 |
commit | 2ae34b67e36b8ba05132d481876eb4ed7a826283 (patch) | |
tree | 63f44c8e2dcdc959d7a5317a3a7b36efedbd7d38 /NorthstarDLL/buildainfile.cpp | |
parent | 3406de7aaaf52cbef20b1549f2d7da0255d30f51 (diff) | |
download | NorthstarLauncher-2ae34b67e36b8ba05132d481876eb4ed7a826283.tar.gz NorthstarLauncher-2ae34b67e36b8ba05132d481876eb4ed7a826283.zip |
almost fully replaced hooking lib
Diffstat (limited to 'NorthstarDLL/buildainfile.cpp')
-rw-r--r-- | NorthstarDLL/buildainfile.cpp | 767 |
1 files changed, 384 insertions, 383 deletions
diff --git a/NorthstarDLL/buildainfile.cpp b/NorthstarDLL/buildainfile.cpp index a80185e5..c0e97fd8 100644 --- a/NorthstarDLL/buildainfile.cpp +++ b/NorthstarDLL/buildainfile.cpp @@ -1,384 +1,385 @@ -#include "pch.h" -#include "convar.h" -#include "hoststate.h" -#include "NSMem.h" - -#include <fstream> -#include <filesystem> - -AUTOHOOK_INIT() - -namespace fs = std::filesystem; - -const int AINET_VERSION_NUMBER = 57; -const int AINET_SCRIPT_VERSION_NUMBER = 21; -const int PLACEHOLDER_CRC = 0; -const int MAX_HULLS = 5; - -struct CAI_NodeLink -{ - short srcId; - short destId; - bool hulls[MAX_HULLS]; - char unk0; - char unk1; // maps => unk0 on disk - char unk2[5]; - int64_t flags; -}; - -#pragma pack(push, 1) -struct CAI_NodeLinkDisk -{ - short srcId; - short destId; - char unk0; - bool hulls[MAX_HULLS]; -}; - -struct CAI_Node -{ - int index; // not present on disk - float x; - float y; - float z; - float hulls[MAX_HULLS]; - float yaw; - - int unk0; // always 2 in buildainfile, maps directly to unk0 in disk struct - int unk1; // maps directly to unk1 in disk struct - int unk2[MAX_HULLS]; // maps directly to unk2 in disk struct, despite being ints rather than shorts - - // view server.dll+393672 for context and death wish - char unk3[MAX_HULLS]; // hell on earth, should map to unk3 on disk - char pad[3]; // aligns next bytes - float unk4[MAX_HULLS]; // i have no fucking clue, calculated using some kind of demon hell function float magic - - CAI_NodeLink** links; - char unk5[16]; - int linkcount; - int unk11; // bad name lmao - short unk6; // should match up to unk4 on disk - char unk7[16]; // padding until next bit - short unk8; // should match up to unk5 on disk - char unk9[8]; // padding until next bit - char unk10[8]; // should match up to unk6 on disk -}; - -// the way CAI_Nodes are represented in on-disk ain files -#pragma pack(push, 1) -struct CAI_NodeDisk -{ - float x; - float y; - float z; - float yaw; - float hulls[MAX_HULLS]; - - char unk0; - int unk1; - short unk2[MAX_HULLS]; - char unk3[MAX_HULLS]; - short unk4; - short unk5; - char unk6[8]; -}; // total size of 68 bytes - -struct UnkNodeStruct0 -{ - int index; - char unk0; - char unk1; // maps to unk1 on disk - char pad0[2]; // padding to +8 - - float x; - float y; - float z; - - char pad5[4]; - int* unk2; // maps to unk5 on disk; - char pad1[16]; // pad to +48 - int unkcount0; // maps to unkcount0 on disk - - char pad2[4]; // pad to +56 - int* unk3; - char pad3[16]; // pad to +80 - int unkcount1; - - char pad4[132]; - char unk5; -}; - -int* pUnkStruct0Count; -UnkNodeStruct0*** pppUnkNodeStruct0s; - -struct UnkLinkStruct1 -{ - short unk0; - short unk1; - int unk2; - char unk3; - char unk4; - char unk5; -}; - -int* pUnkLinkStruct1Count; -UnkLinkStruct1*** pppUnkStruct1s; - -struct CAI_ScriptNode -{ - float x; - float y; - float z; - uint64_t scriptdata; -}; - -struct CAI_Network -{ - // +0 - char unk0[8]; - // +8 - int linkcount; // this is uninitialised and never set on ain build, fun! - // +12 - char unk1[124]; - // +136 - int zonecount; - // +140 - char unk2[16]; - // +156 - int unk5; // unk8 on disk - // +160 - char unk6[4]; - // +164 - int hintcount; - // +168 - short hints[2000]; // these probably aren't actually hints, but there's 1 of them per hint so idk - // +4168 - int scriptnodecount; - // +4172 - CAI_ScriptNode scriptnodes[4000]; - // +84172 - int nodecount; - // +84176 - CAI_Node** nodes; -}; - -char** pUnkServerMapversionGlobal; - -ConVar* Cvar_ns_ai_dumpAINfileFromLoad; - -void DumpAINInfo(CAI_Network* aiNetwork) -{ - fs::path writePath("r2/maps/graphs"); - writePath /= R2::g_pHostState->m_levelName; - writePath += ".ain"; - - // dump from memory - spdlog::info("writing ain file {}", writePath.string()); - spdlog::info(""); - spdlog::info(""); - spdlog::info(""); - spdlog::info(""); - spdlog::info(""); - - std::ofstream writeStream(writePath, std::ofstream::binary); - spdlog::info("writing ainet version: {}", AINET_VERSION_NUMBER); - writeStream.write((char*)&AINET_VERSION_NUMBER, sizeof(int)); - - // could probably be cleaner but whatever - int mapVersion = *(int*)(*pUnkServerMapversionGlobal + 104); - spdlog::info("writing map version: {}", mapVersion); // temp - writeStream.write((char*)&mapVersion, sizeof(int)); - spdlog::info("writing placeholder crc: {}", PLACEHOLDER_CRC); - writeStream.write((char*)&PLACEHOLDER_CRC, sizeof(int)); - - int calculatedLinkcount = 0; - - // path nodes - spdlog::info("writing nodecount: {}", aiNetwork->nodecount); - writeStream.write((char*)&aiNetwork->nodecount, sizeof(int)); - - for (int i = 0; i < aiNetwork->nodecount; i++) - { - // construct on-disk node struct - CAI_NodeDisk diskNode; - diskNode.x = aiNetwork->nodes[i]->x; - diskNode.y = aiNetwork->nodes[i]->y; - diskNode.z = aiNetwork->nodes[i]->z; - diskNode.yaw = aiNetwork->nodes[i]->yaw; - memcpy(diskNode.hulls, aiNetwork->nodes[i]->hulls, sizeof(diskNode.hulls)); - diskNode.unk0 = (char)aiNetwork->nodes[i]->unk0; - diskNode.unk1 = aiNetwork->nodes[i]->unk1; - - for (int j = 0; j < MAX_HULLS; j++) - { - diskNode.unk2[j] = (short)aiNetwork->nodes[i]->unk2[j]; - spdlog::info((short)aiNetwork->nodes[i]->unk2[j]); - } - - memcpy(diskNode.unk3, aiNetwork->nodes[i]->unk3, sizeof(diskNode.unk3)); - diskNode.unk4 = aiNetwork->nodes[i]->unk6; - diskNode.unk5 = - -1; // aiNetwork->nodes[i]->unk8; // this field is wrong, however, it's always -1 in vanilla navmeshes anyway, so no biggie - memcpy(diskNode.unk6, aiNetwork->nodes[i]->unk10, sizeof(diskNode.unk6)); - - spdlog::info("writing node {} from {} to {:x}", aiNetwork->nodes[i]->index, (void*)aiNetwork->nodes[i], writeStream.tellp()); - writeStream.write((char*)&diskNode, sizeof(CAI_NodeDisk)); - - calculatedLinkcount += aiNetwork->nodes[i]->linkcount; - } - - // links - spdlog::info("linkcount: {}", aiNetwork->linkcount); - spdlog::info("calculated total linkcount: {}", calculatedLinkcount); - - calculatedLinkcount /= 2; - if (Cvar_ns_ai_dumpAINfileFromLoad->GetBool()) - { - if (aiNetwork->linkcount == calculatedLinkcount) - spdlog::info("caculated linkcount is normal!"); - else - spdlog::warn("calculated linkcount has weird value! this is expected on build!"); - } - - spdlog::info("writing linkcount: {}", calculatedLinkcount); - writeStream.write((char*)&calculatedLinkcount, sizeof(int)); - - for (int i = 0; i < aiNetwork->nodecount; i++) - { - for (int j = 0; j < aiNetwork->nodes[i]->linkcount; j++) - { - // skip links that don't originate from current node - if (aiNetwork->nodes[i]->links[j]->srcId != aiNetwork->nodes[i]->index) - continue; - - CAI_NodeLinkDisk diskLink; - diskLink.srcId = aiNetwork->nodes[i]->links[j]->srcId; - diskLink.destId = aiNetwork->nodes[i]->links[j]->destId; - diskLink.unk0 = aiNetwork->nodes[i]->links[j]->unk1; - memcpy(diskLink.hulls, aiNetwork->nodes[i]->links[j]->hulls, sizeof(diskLink.hulls)); - - spdlog::info("writing link {} => {} to {:x}", diskLink.srcId, diskLink.destId, writeStream.tellp()); - writeStream.write((char*)&diskLink, sizeof(CAI_NodeLinkDisk)); - } - } - - // don't know what this is, it's likely a block from tf1 that got deprecated? should just be 1 int per node - spdlog::info("writing {:x} bytes for unknown block at {:x}", aiNetwork->nodecount * sizeof(uint32_t), writeStream.tellp()); - uint32_t* unkNodeBlock = new uint32_t[aiNetwork->nodecount]; - memset(unkNodeBlock, 0, aiNetwork->nodecount * sizeof(uint32_t)); - writeStream.write((char*)unkNodeBlock, aiNetwork->nodecount * sizeof(uint32_t)); - delete[] unkNodeBlock; - - // 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 - spdlog::info("writing {} traversal nodes at {:x}...", 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 - - // TODO: ideally these should be actually dumped, but they're always 0 in tf2 from what i can tell - spdlog::info("writing {} bytes for unknown hull block at {:x}", 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; - - // unknown struct that's seemingly node-related - spdlog::info("writing {} unknown node structs at {:x}", *pUnkStruct0Count, writeStream.tellp()); - writeStream.write((char*)pUnkStruct0Count, sizeof(*pUnkStruct0Count)); - for (int i = 0; i < *pUnkStruct0Count; i++) - { - spdlog::info("writing unknown node struct {} at {:x}", i, writeStream.tellp()); - UnkNodeStruct0* nodeStruct = (*pppUnkNodeStruct0s)[i]; - - writeStream.write((char*)&nodeStruct->index, sizeof(nodeStruct->index)); - writeStream.write((char*)&nodeStruct->unk1, sizeof(nodeStruct->unk1)); - - 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*)&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*)&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*)&nodeStruct->unk5, sizeof(nodeStruct->unk5)); - } - - // unknown struct that's seemingly link-related - spdlog::info("writing {} unknown link structs at {:x}", *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 - spdlog::info("writing unknown link struct {} at {:x}", i, writeStream.tellp()); - writeStream.write((char*)(*pppUnkStruct1s)[i], sizeof(*(*pppUnkStruct1s)[i])); - } - - // some weird int idk what this is used for - writeStream.write((char*)&aiNetwork->unk5, sizeof(aiNetwork->unk5)); - - // tf2-exclusive stuff past this point, i.e. ain v57 only - spdlog::info("writing {} script nodes at {:x}", aiNetwork->scriptnodecount, writeStream.tellp()); - writeStream.write((char*)&aiNetwork->scriptnodecount, sizeof(aiNetwork->scriptnodecount)); - for (int i = 0; i < aiNetwork->scriptnodecount; i++) - { - // disk and memory structs are literally identical here so just directly write - spdlog::info("writing script node {} at {:x}", i, writeStream.tellp()); - writeStream.write((char*)&aiNetwork->scriptnodes[i], sizeof(aiNetwork->scriptnodes[i])); - } - - spdlog::info("writing {} hints at {:x}", aiNetwork->hintcount, writeStream.tellp()); - writeStream.write((char*)&aiNetwork->hintcount, sizeof(aiNetwork->hintcount)); - for (int i = 0; i < aiNetwork->hintcount; i++) - { - spdlog::info("writing hint data {} at {:x}", i, writeStream.tellp()); - writeStream.write((char*)&aiNetwork->hints[i], sizeof(aiNetwork->hints[i])); - } - - writeStream.close(); -} - -AUTOHOOK(CAI_NetworkBuilder__Build, server.dll + 0x385E20, -void,, (void* builder, CAI_Network* aiNetwork, void* unknown), -{ - CAI_NetworkBuilder__Build(builder, aiNetwork, unknown); - - DumpAINInfo(aiNetwork); -}) - -AUTOHOOK(LoadAINFile, server.dll + 0x3933A0, -void,, (void* aimanager, void* buf, const char* filename), -{ - LoadAINFile(aimanager, buf, filename); - - if (Cvar_ns_ai_dumpAINfileFromLoad->GetBool()) - { - spdlog::info("running DumpAINInfo for loaded file {}", filename); - DumpAINInfo(*(CAI_Network**)((char*)aimanager + 2536)); - } -}) - -ON_DLL_LOAD("server.dll", BuildAINFile, [](HMODULE baseAddress) -{ - AUTOHOOK_DISPATCH() - - Cvar_ns_ai_dumpAINfileFromLoad = new ConVar( - "ns_ai_dumpAINfileFromLoad", "0", FCVAR_NONE, "For debugging: whether we should dump ain data for ains loaded from disk"); - - pUnkStruct0Count = (int*)((char*)baseAddress + 0x1063BF8); - pppUnkNodeStruct0s = (UnkNodeStruct0***)((char*)baseAddress + 0x1063BE0); - pUnkLinkStruct1Count = (int*)((char*)baseAddress + 0x1063AA8); - pppUnkStruct1s = (UnkLinkStruct1***)((char*)baseAddress + 0x1063A90); - pUnkServerMapversionGlobal = (char**)((char*)baseAddress + 0xBFBE08); +#include "pch.h"
+#include "convar.h"
+#include "hoststate.h"
+#include "r2engine.h"
+#include "NSMem.h"
+
+#include <fstream>
+#include <filesystem>
+
+AUTOHOOK_INIT()
+
+namespace fs = std::filesystem;
+
+const int AINET_VERSION_NUMBER = 57;
+const int AINET_SCRIPT_VERSION_NUMBER = 21;
+const int PLACEHOLDER_CRC = 0;
+const int MAX_HULLS = 5;
+
+struct CAI_NodeLink
+{
+ short srcId;
+ short destId;
+ bool hulls[MAX_HULLS];
+ char unk0;
+ char unk1; // maps => unk0 on disk
+ char unk2[5];
+ int64_t flags;
+};
+
+#pragma pack(push, 1)
+struct CAI_NodeLinkDisk
+{
+ short srcId;
+ short destId;
+ char unk0;
+ bool hulls[MAX_HULLS];
+};
+
+struct CAI_Node
+{
+ int index; // not present on disk
+ float x;
+ float y;
+ float z;
+ float hulls[MAX_HULLS];
+ float yaw;
+
+ int unk0; // always 2 in buildainfile, maps directly to unk0 in disk struct
+ int unk1; // maps directly to unk1 in disk struct
+ int unk2[MAX_HULLS]; // maps directly to unk2 in disk struct, despite being ints rather than shorts
+
+ // view server.dll+393672 for context and death wish
+ char unk3[MAX_HULLS]; // hell on earth, should map to unk3 on disk
+ char pad[3]; // aligns next bytes
+ float unk4[MAX_HULLS]; // i have no fucking clue, calculated using some kind of demon hell function float magic
+
+ CAI_NodeLink** links;
+ char unk5[16];
+ int linkcount;
+ int unk11; // bad name lmao
+ short unk6; // should match up to unk4 on disk
+ char unk7[16]; // padding until next bit
+ short unk8; // should match up to unk5 on disk
+ char unk9[8]; // padding until next bit
+ char unk10[8]; // should match up to unk6 on disk
+};
+
+// the way CAI_Nodes are represented in on-disk ain files
+#pragma pack(push, 1)
+struct CAI_NodeDisk
+{
+ float x;
+ float y;
+ float z;
+ float yaw;
+ float hulls[MAX_HULLS];
+
+ char unk0;
+ int unk1;
+ short unk2[MAX_HULLS];
+ char unk3[MAX_HULLS];
+ short unk4;
+ short unk5;
+ char unk6[8];
+}; // total size of 68 bytes
+
+struct UnkNodeStruct0
+{
+ int index;
+ char unk0;
+ char unk1; // maps to unk1 on disk
+ char pad0[2]; // padding to +8
+
+ float x;
+ float y;
+ float z;
+
+ char pad5[4];
+ int* unk2; // maps to unk5 on disk;
+ char pad1[16]; // pad to +48
+ int unkcount0; // maps to unkcount0 on disk
+
+ char pad2[4]; // pad to +56
+ int* unk3;
+ char pad3[16]; // pad to +80
+ int unkcount1;
+
+ char pad4[132];
+ char unk5;
+};
+
+int* pUnkStruct0Count;
+UnkNodeStruct0*** pppUnkNodeStruct0s;
+
+struct UnkLinkStruct1
+{
+ short unk0;
+ short unk1;
+ int unk2;
+ char unk3;
+ char unk4;
+ char unk5;
+};
+
+int* pUnkLinkStruct1Count;
+UnkLinkStruct1*** pppUnkStruct1s;
+
+struct CAI_ScriptNode
+{
+ float x;
+ float y;
+ float z;
+ uint64_t scriptdata;
+};
+
+struct CAI_Network
+{
+ // +0
+ char unk0[8];
+ // +8
+ int linkcount; // this is uninitialised and never set on ain build, fun!
+ // +12
+ char unk1[124];
+ // +136
+ int zonecount;
+ // +140
+ char unk2[16];
+ // +156
+ int unk5; // unk8 on disk
+ // +160
+ char unk6[4];
+ // +164
+ int hintcount;
+ // +168
+ short hints[2000]; // these probably aren't actually hints, but there's 1 of them per hint so idk
+ // +4168
+ int scriptnodecount;
+ // +4172
+ CAI_ScriptNode scriptnodes[4000];
+ // +84172
+ int nodecount;
+ // +84176
+ CAI_Node** nodes;
+};
+
+char** pUnkServerMapversionGlobal;
+
+ConVar* Cvar_ns_ai_dumpAINfileFromLoad;
+
+void DumpAINInfo(CAI_Network* aiNetwork)
+{
+ fs::path writePath(fmt::format("{}/maps/graphs", "r2"));
+ writePath /= R2::g_pHostState->m_levelName;
+ writePath += ".ain";
+
+ // dump from memory
+ spdlog::info("writing ain file {}", writePath.string());
+ spdlog::info("");
+ spdlog::info("");
+ spdlog::info("");
+ spdlog::info("");
+ spdlog::info("");
+
+ std::ofstream writeStream(writePath, std::ofstream::binary);
+ spdlog::info("writing ainet version: {}", AINET_VERSION_NUMBER);
+ writeStream.write((char*)&AINET_VERSION_NUMBER, sizeof(int));
+
+ // could probably be cleaner but whatever
+ int mapVersion = *(int*)(*pUnkServerMapversionGlobal + 104);
+ spdlog::info("writing map version: {}", mapVersion); // temp
+ writeStream.write((char*)&mapVersion, sizeof(int));
+ spdlog::info("writing placeholder crc: {}", PLACEHOLDER_CRC);
+ writeStream.write((char*)&PLACEHOLDER_CRC, sizeof(int));
+
+ int calculatedLinkcount = 0;
+
+ // path nodes
+ spdlog::info("writing nodecount: {}", aiNetwork->nodecount);
+ writeStream.write((char*)&aiNetwork->nodecount, sizeof(int));
+
+ for (int i = 0; i < aiNetwork->nodecount; i++)
+ {
+ // construct on-disk node struct
+ CAI_NodeDisk diskNode;
+ diskNode.x = aiNetwork->nodes[i]->x;
+ diskNode.y = aiNetwork->nodes[i]->y;
+ diskNode.z = aiNetwork->nodes[i]->z;
+ diskNode.yaw = aiNetwork->nodes[i]->yaw;
+ memcpy(diskNode.hulls, aiNetwork->nodes[i]->hulls, sizeof(diskNode.hulls));
+ diskNode.unk0 = (char)aiNetwork->nodes[i]->unk0;
+ diskNode.unk1 = aiNetwork->nodes[i]->unk1;
+
+ for (int j = 0; j < MAX_HULLS; j++)
+ {
+ diskNode.unk2[j] = (short)aiNetwork->nodes[i]->unk2[j];
+ spdlog::info((short)aiNetwork->nodes[i]->unk2[j]);
+ }
+
+ memcpy(diskNode.unk3, aiNetwork->nodes[i]->unk3, sizeof(diskNode.unk3));
+ diskNode.unk4 = aiNetwork->nodes[i]->unk6;
+ diskNode.unk5 =
+ -1; // aiNetwork->nodes[i]->unk8; // this field is wrong, however, it's always -1 in vanilla navmeshes anyway, so no biggie
+ memcpy(diskNode.unk6, aiNetwork->nodes[i]->unk10, sizeof(diskNode.unk6));
+
+ spdlog::info("writing node {} from {} to {:x}", aiNetwork->nodes[i]->index, (void*)aiNetwork->nodes[i], writeStream.tellp());
+ writeStream.write((char*)&diskNode, sizeof(CAI_NodeDisk));
+
+ calculatedLinkcount += aiNetwork->nodes[i]->linkcount;
+ }
+
+ // links
+ spdlog::info("linkcount: {}", aiNetwork->linkcount);
+ spdlog::info("calculated total linkcount: {}", calculatedLinkcount);
+
+ calculatedLinkcount /= 2;
+ if (Cvar_ns_ai_dumpAINfileFromLoad->GetBool())
+ {
+ if (aiNetwork->linkcount == calculatedLinkcount)
+ spdlog::info("caculated linkcount is normal!");
+ else
+ spdlog::warn("calculated linkcount has weird value! this is expected on build!");
+ }
+
+ spdlog::info("writing linkcount: {}", calculatedLinkcount);
+ writeStream.write((char*)&calculatedLinkcount, sizeof(int));
+
+ for (int i = 0; i < aiNetwork->nodecount; i++)
+ {
+ for (int j = 0; j < aiNetwork->nodes[i]->linkcount; j++)
+ {
+ // skip links that don't originate from current node
+ if (aiNetwork->nodes[i]->links[j]->srcId != aiNetwork->nodes[i]->index)
+ continue;
+
+ CAI_NodeLinkDisk diskLink;
+ diskLink.srcId = aiNetwork->nodes[i]->links[j]->srcId;
+ diskLink.destId = aiNetwork->nodes[i]->links[j]->destId;
+ diskLink.unk0 = aiNetwork->nodes[i]->links[j]->unk1;
+ memcpy(diskLink.hulls, aiNetwork->nodes[i]->links[j]->hulls, sizeof(diskLink.hulls));
+
+ spdlog::info("writing link {} => {} to {:x}", diskLink.srcId, diskLink.destId, writeStream.tellp());
+ writeStream.write((char*)&diskLink, sizeof(CAI_NodeLinkDisk));
+ }
+ }
+
+ // don't know what this is, it's likely a block from tf1 that got deprecated? should just be 1 int per node
+ spdlog::info("writing {:x} bytes for unknown block at {:x}", aiNetwork->nodecount * sizeof(uint32_t), writeStream.tellp());
+ uint32_t* unkNodeBlock = new uint32_t[aiNetwork->nodecount];
+ memset(unkNodeBlock, 0, aiNetwork->nodecount * sizeof(uint32_t));
+ writeStream.write((char*)unkNodeBlock, aiNetwork->nodecount * sizeof(uint32_t));
+ delete[] unkNodeBlock;
+
+ // 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
+ spdlog::info("writing {} traversal nodes at {:x}...", 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
+
+ // TODO: ideally these should be actually dumped, but they're always 0 in tf2 from what i can tell
+ spdlog::info("writing {} bytes for unknown hull block at {:x}", 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;
+
+ // unknown struct that's seemingly node-related
+ spdlog::info("writing {} unknown node structs at {:x}", *pUnkStruct0Count, writeStream.tellp());
+ writeStream.write((char*)pUnkStruct0Count, sizeof(*pUnkStruct0Count));
+ for (int i = 0; i < *pUnkStruct0Count; i++)
+ {
+ spdlog::info("writing unknown node struct {} at {:x}", i, writeStream.tellp());
+ UnkNodeStruct0* nodeStruct = (*pppUnkNodeStruct0s)[i];
+
+ writeStream.write((char*)&nodeStruct->index, sizeof(nodeStruct->index));
+ writeStream.write((char*)&nodeStruct->unk1, sizeof(nodeStruct->unk1));
+
+ 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*)&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*)&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*)&nodeStruct->unk5, sizeof(nodeStruct->unk5));
+ }
+
+ // unknown struct that's seemingly link-related
+ spdlog::info("writing {} unknown link structs at {:x}", *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
+ spdlog::info("writing unknown link struct {} at {:x}", i, writeStream.tellp());
+ writeStream.write((char*)(*pppUnkStruct1s)[i], sizeof(*(*pppUnkStruct1s)[i]));
+ }
+
+ // some weird int idk what this is used for
+ writeStream.write((char*)&aiNetwork->unk5, sizeof(aiNetwork->unk5));
+
+ // tf2-exclusive stuff past this point, i.e. ain v57 only
+ spdlog::info("writing {} script nodes at {:x}", aiNetwork->scriptnodecount, writeStream.tellp());
+ writeStream.write((char*)&aiNetwork->scriptnodecount, sizeof(aiNetwork->scriptnodecount));
+ for (int i = 0; i < aiNetwork->scriptnodecount; i++)
+ {
+ // disk and memory structs are literally identical here so just directly write
+ spdlog::info("writing script node {} at {:x}", i, writeStream.tellp());
+ writeStream.write((char*)&aiNetwork->scriptnodes[i], sizeof(aiNetwork->scriptnodes[i]));
+ }
+
+ spdlog::info("writing {} hints at {:x}", aiNetwork->hintcount, writeStream.tellp());
+ writeStream.write((char*)&aiNetwork->hintcount, sizeof(aiNetwork->hintcount));
+ for (int i = 0; i < aiNetwork->hintcount; i++)
+ {
+ spdlog::info("writing hint data {} at {:x}", i, writeStream.tellp());
+ writeStream.write((char*)&aiNetwork->hints[i], sizeof(aiNetwork->hints[i]));
+ }
+
+ writeStream.close();
+}
+
+AUTOHOOK(CAI_NetworkBuilder__Build, server.dll + 0x385E20,
+void,, (void* builder, CAI_Network* aiNetwork, void* unknown))
+{
+ CAI_NetworkBuilder__Build(builder, aiNetwork, unknown);
+
+ DumpAINInfo(aiNetwork);
+}
+
+AUTOHOOK(LoadAINFile, server.dll + 0x3933A0,
+void,, (void* aimanager, void* buf, const char* filename))
+{
+ LoadAINFile(aimanager, buf, filename);
+
+ if (Cvar_ns_ai_dumpAINfileFromLoad->GetBool())
+ {
+ spdlog::info("running DumpAINInfo for loaded file {}", filename);
+ DumpAINInfo(*(CAI_Network**)((char*)aimanager + 2536));
+ }
+}
+
+ON_DLL_LOAD("server.dll", BuildAINFile, [](HMODULE baseAddress)
+{
+ AUTOHOOK_DISPATCH()
+
+ Cvar_ns_ai_dumpAINfileFromLoad = new ConVar(
+ "ns_ai_dumpAINfileFromLoad", "0", FCVAR_NONE, "For debugging: whether we should dump ain data for ains loaded from disk");
+
+ pUnkStruct0Count = (int*)((char*)baseAddress + 0x1063BF8);
+ pppUnkNodeStruct0s = (UnkNodeStruct0***)((char*)baseAddress + 0x1063BE0);
+ pUnkLinkStruct1Count = (int*)((char*)baseAddress + 0x1063AA8);
+ pppUnkStruct1s = (UnkLinkStruct1***)((char*)baseAddress + 0x1063A90);
+ pUnkServerMapversionGlobal = (char**)((char*)baseAddress + 0xBFBE08);
});
\ No newline at end of file |