mirror of
https://github.com/Mauler125/r5sdk.git
synced 2025-02-09 19:15:03 +01:00
CAI_NetworkBuilder::SaveNetworkGraph() rewrite
- Use CUtlBuffer instead to construct the data. - Dump traverse ex nodes as well (CAI_TraverseNode).
This commit is contained in:
parent
db6ccff8c2
commit
25e5ea0c83
@ -54,7 +54,7 @@ void* CAI_Network::GetVTable(void) const
|
||||
// Purpose: gets the number of node links
|
||||
// Output : int
|
||||
//-----------------------------------------------------------------------------
|
||||
int CAI_Network::GetNumLinks(void) const
|
||||
int CAI_Network::NumLinks(void) const
|
||||
{
|
||||
return m_iNumLinks;
|
||||
}
|
||||
@ -63,7 +63,7 @@ int CAI_Network::GetNumLinks(void) const
|
||||
// Purpose: gets the number of zones
|
||||
// Output : int
|
||||
//-----------------------------------------------------------------------------
|
||||
int CAI_Network::GetNumZones(void) const
|
||||
int CAI_Network::NumZones(void) const
|
||||
{
|
||||
return m_iNumZones;
|
||||
}
|
||||
@ -72,7 +72,7 @@ int CAI_Network::GetNumZones(void) const
|
||||
// Purpose: gets the number of hints
|
||||
// Output : int
|
||||
//-----------------------------------------------------------------------------
|
||||
int CAI_Network::GetNumHints(void) const
|
||||
int CAI_Network::NumHints(void) const
|
||||
{
|
||||
return m_iNumHints;
|
||||
}
|
||||
@ -81,16 +81,16 @@ int CAI_Network::GetNumHints(void) const
|
||||
// Purpose: gets the number of script nodes
|
||||
// Output : int
|
||||
//-----------------------------------------------------------------------------
|
||||
int CAI_Network::GetNumScriptNodes(void) const
|
||||
int CAI_Network::NumScriptNodes(void) const
|
||||
{
|
||||
return m_iNumScriptNodes;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: gets the path nodes
|
||||
// Output : int64_t
|
||||
// Output : int
|
||||
//-----------------------------------------------------------------------------
|
||||
int64_t CAI_Network::GetNumPathNodes(void) const
|
||||
int CAI_Network::NumPathNodes(void) const
|
||||
{
|
||||
return m_iNumNodes;
|
||||
}
|
||||
@ -115,12 +115,20 @@ CAI_ScriptNode* CAI_Network::GetScriptNodes(void) const
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: gets the pointer to path nodes
|
||||
// Purpose: gets the pointer to path node
|
||||
// Input : id -
|
||||
// Output : CAI_Node**
|
||||
//-----------------------------------------------------------------------------
|
||||
CAI_Node** CAI_Network::GetPathNodes(void) const
|
||||
CAI_Node* CAI_Network::GetPathNode(int id) const
|
||||
{
|
||||
return m_pAInode;
|
||||
if (id >= 0 &&
|
||||
id < m_iNumNodes)
|
||||
{
|
||||
return m_pAInode[id];
|
||||
}
|
||||
|
||||
Assert(0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -11,17 +11,17 @@ class CAI_Network
|
||||
public:
|
||||
static void DebugConnectMsg(int node1, int node2, const char* pszFormat, ...);
|
||||
void* GetVTable(void) const;
|
||||
int GetNumLinks(void) const;
|
||||
int GetNumZones(void) const;
|
||||
int GetNumHints(void) const;
|
||||
int GetNumScriptNodes(void) const;
|
||||
int64_t GetNumPathNodes(void) const;
|
||||
int NumLinks(void) const;
|
||||
int NumZones(void) const;
|
||||
int NumHints(void) const;
|
||||
int NumScriptNodes(void) const;
|
||||
int NumPathNodes(void) const;
|
||||
|
||||
short GetHint(int nIndex) const;
|
||||
CAI_ScriptNode* GetScriptNodes(void) const;
|
||||
|
||||
CAI_Node* AddPathNode(const Vector3D* origin, const float jaw);
|
||||
CAI_Node** GetPathNodes(void) const;
|
||||
CAI_Node* GetPathNode(int id) const;
|
||||
|
||||
CAI_NodeLink* CreateNodeLink(int srcID, int destID);
|
||||
|
||||
|
@ -59,11 +59,6 @@ void CAI_NetworkBuilder::SaveNetworkGraph(CAI_Network* pNetwork)
|
||||
}
|
||||
|
||||
DevMsg(eDLL_T::SERVER, "+- Writing header...\n");
|
||||
DevMsg(eDLL_T::SERVER, " |-- AINet version: '%d'\n", AINET_VERSION_NUMBER);
|
||||
FileSystem()->Write(&AINET_VERSION_NUMBER, sizeof(int), pAIGraph);
|
||||
|
||||
DevMsg(eDLL_T::SERVER, " |-- Map version: '%d'\n", g_ServerGlobalVariables->m_nMapVersion);
|
||||
FileSystem()->Write(&g_ServerGlobalVariables->m_nMapVersion, sizeof(int), pAIGraph);
|
||||
|
||||
FileHandle_t pNavMesh = FileSystem()->Open(szMeshPath, "rb", "GAME");
|
||||
uint32_t nNavMeshCRC = NULL;
|
||||
@ -85,12 +80,18 @@ void CAI_NetworkBuilder::SaveNetworkGraph(CAI_Network* pNetwork)
|
||||
}
|
||||
|
||||
// Large NavMesh CRC.
|
||||
DevMsg(eDLL_T::SERVER, " |-- AINet version: '%d'\n", AINET_VERSION_NUMBER);
|
||||
DevMsg(eDLL_T::SERVER, " |-- Map version: '%d'\n", g_ServerGlobalVariables->m_nMapVersion);
|
||||
DevMsg(eDLL_T::SERVER, " |-- NavMesh CRC: '0x%lX'\n", nNavMeshCRC);
|
||||
FileSystem()->Write(&nNavMeshCRC, sizeof(uint32_t), pAIGraph);
|
||||
|
||||
// Path nodes.
|
||||
DevMsg(eDLL_T::SERVER, " |-- Node count: '%d'\n", pNetwork->m_iNumNodes);
|
||||
FileSystem()->Write(&pNetwork->m_iNumNodes, sizeof(int), pAIGraph);
|
||||
CUtlBuffer buf;
|
||||
|
||||
// ---------------------------
|
||||
// Save the version numbers
|
||||
// ---------------------------
|
||||
buf.PutInt(AINET_VERSION_NUMBER);
|
||||
buf.PutInt(g_ServerGlobalVariables->m_nMapVersion);
|
||||
buf.PutInt(nNavMeshCRC);
|
||||
|
||||
timer.End();
|
||||
Msg(eDLL_T::SERVER, "...done writing header. %lf seconds\n", timer.GetDuration().GetSeconds());
|
||||
@ -98,49 +99,42 @@ void CAI_NetworkBuilder::SaveNetworkGraph(CAI_Network* pNetwork)
|
||||
timer.Start();
|
||||
DevMsg(eDLL_T::SERVER, "+- Writing path nodes...\n");
|
||||
|
||||
if (pNetwork->m_pAInode)
|
||||
// -------------------------------
|
||||
// Dump all the nodes to the file
|
||||
// -------------------------------
|
||||
buf.PutInt(pNetwork->NumPathNodes());
|
||||
int totalNumLinks = 0;
|
||||
|
||||
for (int node = 0; node < pNetwork->NumPathNodes(); node++)
|
||||
{
|
||||
int totalLinkCount = 0;
|
||||
const CAI_Node* aiNode = pNetwork->GetPathNode(node);
|
||||
|
||||
for (int i = 0; i < pNetwork->m_iNumNodes; i++)
|
||||
DevMsg(eDLL_T::SERVER, " |-- Copying node '#%d' from '0x%p' to '0x%zX'\n", aiNode->m_iID, aiNode, buf.TellPut());
|
||||
|
||||
buf.PutFloat(aiNode->GetOrigin().x);
|
||||
buf.PutFloat(aiNode->GetOrigin().y);
|
||||
buf.PutFloat(aiNode->GetOrigin().z);
|
||||
|
||||
buf.PutFloat(aiNode->GetYaw());
|
||||
buf.Put(aiNode->m_flVOffset, sizeof(aiNode->m_flVOffset));
|
||||
buf.PutChar((char)aiNode->GetType());
|
||||
buf.PutInt(aiNode->GetInfo());
|
||||
|
||||
for (int j = 0; j < MAX_HULLS; j++)
|
||||
{
|
||||
const CAI_Node* aiNode = pNetwork->m_pAInode[i];
|
||||
|
||||
DevMsg(eDLL_T::SERVER, " |-- Copying node '#%d' from '0x%p' to '0x%zX'\n", aiNode->m_nIndex, aiNode, FileSystem()->Tell(pAIGraph));
|
||||
|
||||
FileSystem()->Write(&aiNode->m_vOrigin, sizeof(Vector3D), pAIGraph);
|
||||
FileSystem()->Write(&aiNode->m_flYaw, sizeof(float), pAIGraph);
|
||||
FileSystem()->Write(&aiNode->m_fHulls, sizeof(aiNode->m_fHulls), pAIGraph);
|
||||
|
||||
FileSystem()->Write(&aiNode->unk0, sizeof(char), pAIGraph);
|
||||
FileSystem()->Write(&aiNode->unk1, sizeof(int), pAIGraph);
|
||||
|
||||
for (int j = 0; j < MAX_HULLS; j++)
|
||||
{
|
||||
FileSystem()->Write(&aiNode->unk2[j], sizeof(short), pAIGraph);
|
||||
}
|
||||
|
||||
FileSystem()->Write(&aiNode->unk3, sizeof(aiNode->unk3), pAIGraph);
|
||||
FileSystem()->Write(&aiNode->unk6, sizeof(short), pAIGraph);
|
||||
|
||||
// aiNetwork->nodes[i]->unk8; // This field is wrong, however it's always -1 in original navmeshes anyway.
|
||||
short unk8 = -1;
|
||||
|
||||
FileSystem()->Write(&unk8/*aiNode->unk8*/, sizeof(short), pAIGraph);
|
||||
FileSystem()->Write(&aiNode->unk10, sizeof(aiNode->unk10), pAIGraph);
|
||||
|
||||
totalLinkCount += aiNode->m_nNumLinks;
|
||||
buf.PutShort((short)aiNode->unk2[j]);
|
||||
}
|
||||
|
||||
pNetwork->m_iNumLinks = totalLinkCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
// No links, this has to be initialized as the engine doesn't do it
|
||||
// during build.
|
||||
pNetwork->m_iNumLinks = 0;
|
||||
buf.Put(aiNode->unk3, sizeof(aiNode->unk3));
|
||||
buf.PutShort(aiNode->unk6);
|
||||
buf.PutShort(aiNode->unk9); // Always -1;
|
||||
buf.Put(aiNode->unk11, sizeof(aiNode->unk11));
|
||||
|
||||
totalNumLinks += aiNode->NumLinks();
|
||||
}
|
||||
|
||||
pNetwork->m_iNumLinks = totalNumLinks;
|
||||
|
||||
timer.End();
|
||||
Msg(eDLL_T::SERVER, "...done writing path nodes. %lf seconds (%d nodes)\n", timer.GetDuration().GetSeconds(), pNetwork->m_iNumNodes);
|
||||
|
||||
@ -148,31 +142,30 @@ void CAI_NetworkBuilder::SaveNetworkGraph(CAI_Network* pNetwork)
|
||||
DevMsg(eDLL_T::SERVER, "+- Writing node links...\n");
|
||||
DevMsg(eDLL_T::SERVER, " |-- Cached node link count: '%d'\n", pNetwork->m_iNumLinks);
|
||||
|
||||
// -------------------------------
|
||||
// Dump all the links to the file
|
||||
// -------------------------------
|
||||
int packedLinks = pNetwork->m_iNumLinks / 2;
|
||||
FileSystem()->Write(&packedLinks, sizeof(int), pAIGraph);
|
||||
buf.PutInt(packedLinks);
|
||||
|
||||
if (pNetwork->m_pAInode)
|
||||
for (int node = 0; node < pNetwork->NumPathNodes(); node++)
|
||||
{
|
||||
for (int i = 0; i < pNetwork->m_iNumNodes; i++)
|
||||
const CAI_Node* aiNode = pNetwork->GetPathNode(node);
|
||||
|
||||
for (int link = 0; link < aiNode->NumLinks(); link++)
|
||||
{
|
||||
const CAI_Node* aiNode = pNetwork->m_pAInode[i];
|
||||
const CAI_NodeLink* nodeLink = aiNode->GetLinkByIndex(link);
|
||||
|
||||
for (int j = 0; j < aiNode->m_nNumLinks; j++)
|
||||
// Skip links that don't originate from current node.
|
||||
if (nodeLink->m_iSrcID == aiNode->m_iID)
|
||||
{
|
||||
const CAI_NodeLink* nodeLink = aiNode->links[j];
|
||||
DevMsg(eDLL_T::SERVER, " |-- Writing link (%hd <--> %hd) to '0x%zX'\n", nodeLink->m_iSrcID, nodeLink->m_iDestID, buf.TellPut());
|
||||
|
||||
// Skip links that don't originate from current node.
|
||||
if (nodeLink->m_iSrcID != aiNode->m_nIndex)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
buf.PutShort(nodeLink->m_iSrcID);
|
||||
buf.PutShort(nodeLink->m_iDestID);
|
||||
|
||||
DevMsg(eDLL_T::SERVER, " |-- Writing link '%hd' => '%hd' to '0x%zX'\n", nodeLink->m_iSrcID, nodeLink->m_iDestID, FileSystem()->Tell(pAIGraph));
|
||||
|
||||
FileSystem()->Write(&nodeLink->m_iSrcID, sizeof(short), pAIGraph);
|
||||
FileSystem()->Write(&nodeLink->m_iDestID, sizeof(short), pAIGraph);
|
||||
FileSystem()->Write(&nodeLink->unk1, sizeof(char), pAIGraph);
|
||||
FileSystem()->Write(&nodeLink->m_bHulls, sizeof(nodeLink->m_bHulls), pAIGraph);
|
||||
buf.PutChar(nodeLink->unk1);
|
||||
buf.Put(nodeLink->m_iAcceptedMoveTypes, sizeof(nodeLink->m_iAcceptedMoveTypes));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -181,30 +174,68 @@ void CAI_NetworkBuilder::SaveNetworkGraph(CAI_Network* pNetwork)
|
||||
Msg(eDLL_T::SERVER, "...done writing node links. %lf seconds (%d links)\n", timer.GetDuration().GetSeconds(), pNetwork->m_iNumLinks);
|
||||
|
||||
timer.Start();
|
||||
DevMsg(eDLL_T::SERVER, "+- Writing hull data...\n");
|
||||
// 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 '%d' bytes for node block at '0x%zX'\n", pNetwork->m_iNumNodes * sizeof(uint32_t), FileSystem()->Tell(pAIGraph));
|
||||
DevMsg(eDLL_T::SERVER, "+- Writing WC lookup table...\n");
|
||||
|
||||
if (pNetwork->m_iNumNodes > 0)
|
||||
// -------------------------------
|
||||
// Dump WC lookup table
|
||||
// -------------------------------
|
||||
CUtlMap<int, int> wcIDs;
|
||||
SetDefLessFunc(wcIDs);
|
||||
bool bCheckForProblems = false;
|
||||
|
||||
const CAI_NetworkEditTools* const pEditOps = (*g_ppAINetworkManager)->GetEditOps();
|
||||
|
||||
for (int node = 0; node < pNetwork->m_iNumNodes; node++)
|
||||
{
|
||||
std::unique_ptr<uint32[]> unkNodeBlock(new uint32_t[pNetwork->m_iNumNodes * sizeof(uint32_t)]);
|
||||
memset(unkNodeBlock.get(), '\0', pNetwork->m_iNumNodes * sizeof(uint32_t));
|
||||
const int nIndex = pEditOps->m_pNodeIndexTable[node];
|
||||
const int iPreviousNodeBinding = wcIDs.Find(nIndex);
|
||||
|
||||
FileSystem()->Write(unkNodeBlock.get(), pNetwork->m_iNumNodes * sizeof(uint32_t), pAIGraph);
|
||||
if (iPreviousNodeBinding != wcIDs.InvalidIndex())
|
||||
{
|
||||
if (!bCheckForProblems)
|
||||
{
|
||||
DevWarning(eDLL_T::SERVER, "******* MAP CONTAINS DUPLICATE HAMMER NODE IDS! CHECK FOR PROBLEMS IN HAMMER TO CORRECT *******\n");
|
||||
bCheckForProblems = true;
|
||||
}
|
||||
DevWarning(eDLL_T::SERVER, " AI node %d is associated with Hammer node %d, but %d is already bound to node %d\n",
|
||||
node, nIndex, nIndex, wcIDs[(unsigned short)nIndex]);
|
||||
}
|
||||
else
|
||||
{
|
||||
wcIDs.Insert(nIndex, node);
|
||||
}
|
||||
|
||||
DevMsg(eDLL_T::SERVER, " |-- Writing Hammer node (%d <--> %d) at '0x%zX'\n", nIndex, wcIDs.Element((unsigned short)nIndex), buf.TellPut());
|
||||
buf.PutInt(nIndex);
|
||||
}
|
||||
|
||||
// TODO: This is traverse nodes i think? these aren't used in r2 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' traverse ex nodes at '0x%zX'\n", 0, FileSystem()->Tell(pAIGraph));
|
||||
timer.End();
|
||||
Msg(eDLL_T::SERVER, "...done writing hammer nodes. %lf seconds (%d indices)\n", timer.GetDuration().GetSeconds(), wcIDs.Count());
|
||||
|
||||
short traverseExNodeCount = 0; // Only write count since count=0 means we don't have to actually do anything here.
|
||||
FileSystem()->Write(&traverseExNodeCount, sizeof(short), pAIGraph);
|
||||
timer.Start();
|
||||
DevMsg(eDLL_T::SERVER, "+- Writing traverse ex nodes...\n");
|
||||
|
||||
const int traverseExNodeCount = g_pAITraverseNodes->Count();
|
||||
buf.PutShort((short)traverseExNodeCount);
|
||||
|
||||
FOR_EACH_VEC(*g_pAITraverseNodes, i)
|
||||
{
|
||||
DevMsg(eDLL_T::SERVER, " |-- Writing traverse ex node '%d' at '0x%zX'\n", i, buf.TellPut());
|
||||
|
||||
const CAI_TraverseNode& traverseExNode = (*g_pAITraverseNodes)[i];
|
||||
buf.Put(&traverseExNode.m_Quat, sizeof(Quaternion));
|
||||
buf.PutInt(traverseExNode.m_Index_MAYBE);
|
||||
}
|
||||
|
||||
timer.End();
|
||||
Msg(eDLL_T::SERVER, "...done writing traverse ex nodes. %lf seconds (%d nodes)\n", timer.GetDuration().GetSeconds(), traverseExNodeCount);
|
||||
|
||||
// TODO: Ideally these should be actually dumped, but they're always 0 in r2 from what i can tell.
|
||||
DevMsg(eDLL_T::SERVER, " |-- Writing '%d' bytes for hull data block at '0x%zX'\n", (MAX_HULLS * 8), FileSystem()->Tell(pAIGraph));
|
||||
timer.Start();
|
||||
DevMsg(eDLL_T::SERVER, " |-- Writing '%d' bytes for hull data block at '0x%zX'\n", (MAX_HULLS * 8), buf.TellPut());
|
||||
for (int i = 0; i < (MAX_HULLS * 8); i++)
|
||||
{
|
||||
FileSystem()->Write("\0", sizeof(char), pAIGraph);
|
||||
buf.PutChar('\0');
|
||||
}
|
||||
|
||||
timer.End();
|
||||
@ -214,40 +245,40 @@ void CAI_NetworkBuilder::SaveNetworkGraph(CAI_Network* pNetwork)
|
||||
DevMsg(eDLL_T::SERVER, "+- Writing path clusters...\n");
|
||||
|
||||
const int numClusters = g_pAIPathClusters->Count();
|
||||
FileSystem()->Write(&numClusters, sizeof(int), pAIGraph);
|
||||
buf.PutInt(numClusters);
|
||||
|
||||
FOR_EACH_VEC(*g_pAIPathClusters, i)
|
||||
{
|
||||
DevMsg(eDLL_T::SERVER, " |-- Writing cluster '#%d' at '0x%zX'\n", i, FileSystem()->Tell(pAIGraph));
|
||||
DevMsg(eDLL_T::SERVER, " |-- Writing cluster '#%d' at '0x%zX'\n", i, buf.TellPut());
|
||||
|
||||
const CAI_Cluster* pathClusters = (*g_pAIPathClusters)[i];
|
||||
|
||||
FileSystem()->Write(&pathClusters->m_nIndex, sizeof(int), pAIGraph);
|
||||
FileSystem()->Write(&pathClusters->unk1, sizeof(char), pAIGraph);
|
||||
buf.PutInt(pathClusters->m_nIndex);
|
||||
buf.PutChar(pathClusters->unk1);
|
||||
|
||||
FileSystem()->Write(&pathClusters->m_vOrigin.x, sizeof(vec_t), pAIGraph);
|
||||
FileSystem()->Write(&pathClusters->m_vOrigin.y, sizeof(vec_t), pAIGraph);
|
||||
FileSystem()->Write(&pathClusters->m_vOrigin.z, sizeof(vec_t), pAIGraph);
|
||||
buf.PutFloat(pathClusters->GetOrigin().x);
|
||||
buf.PutFloat(pathClusters->GetOrigin().y);
|
||||
buf.PutFloat(pathClusters->GetOrigin().z);
|
||||
|
||||
const int unkVec0Size = pathClusters->unkVec0.Count();
|
||||
FileSystem()->Write(&unkVec0Size, sizeof(int), pAIGraph);
|
||||
buf.PutInt(unkVec0Size);
|
||||
|
||||
FOR_EACH_VEC(pathClusters->unkVec0, j)
|
||||
{
|
||||
short unkShort = static_cast<short>(pathClusters->unkVec0[j]);
|
||||
FileSystem()->Write(&unkShort, sizeof(short), pAIGraph);
|
||||
buf.PutShort(unkShort);
|
||||
}
|
||||
|
||||
const int unkVec1Size = pathClusters->unkVec1.Count();
|
||||
FileSystem()->Write(&unkVec1Size, sizeof(int), pAIGraph);
|
||||
buf.PutInt(unkVec1Size);
|
||||
|
||||
FOR_EACH_VEC(pathClusters->unkVec1, j)
|
||||
{
|
||||
short unkShort = static_cast<short>(pathClusters->unkVec1[j]);
|
||||
FileSystem()->Write(&unkShort, sizeof(short), pAIGraph);
|
||||
buf.PutShort(unkShort);
|
||||
}
|
||||
|
||||
FileSystem()->Write(&pathClusters->unk5, sizeof(char), pAIGraph);
|
||||
buf.PutChar(pathClusters->unk5);
|
||||
}
|
||||
|
||||
timer.End();
|
||||
@ -257,41 +288,41 @@ void CAI_NetworkBuilder::SaveNetworkGraph(CAI_Network* pNetwork)
|
||||
DevMsg(eDLL_T::SERVER, "+- Writing cluster links...\n");
|
||||
|
||||
const int numClusterLinks = g_pAIClusterLinks->Count();
|
||||
FileSystem()->Write(&numClusterLinks, sizeof(int), pAIGraph);
|
||||
buf.PutInt(numClusterLinks);
|
||||
|
||||
FOR_EACH_VEC(*g_pAIClusterLinks, i)
|
||||
{
|
||||
DevMsg(eDLL_T::SERVER, " |-- Writing link '#%d' at '0x%zX'\n", i, FileSystem()->Tell(pAIGraph));
|
||||
|
||||
// Disk and memory structs are literally identical here so just directly write.
|
||||
const CAI_ClusterLink* clusterLink = (*g_pAIClusterLinks)[i];
|
||||
|
||||
FileSystem()->Write(&clusterLink->prevIndex_MAYBE, sizeof(short), pAIGraph);
|
||||
FileSystem()->Write(&clusterLink->nextIndex_MAYBE, sizeof(short), pAIGraph);
|
||||
DevMsg(eDLL_T::SERVER, " |-- Writing link (%hd <--> %hd) to '0x%zX'\n", clusterLink->m_iSrcID, clusterLink->m_iDestID, buf.TellPut());
|
||||
|
||||
FileSystem()->Write(&clusterLink->unk2, sizeof(int), pAIGraph);
|
||||
FileSystem()->Write(&clusterLink->flags, sizeof(char), pAIGraph);
|
||||
buf.PutShort(clusterLink->m_iSrcID);
|
||||
buf.PutShort(clusterLink->m_iDestID);
|
||||
|
||||
FileSystem()->Write(&clusterLink->unk4, sizeof(char), pAIGraph);
|
||||
FileSystem()->Write(&clusterLink->unk5, sizeof(char), pAIGraph);
|
||||
buf.PutInt(clusterLink->unk2);
|
||||
buf.PutChar(clusterLink->flags);
|
||||
|
||||
buf.PutChar(clusterLink->unkFlags4);
|
||||
buf.PutChar(clusterLink->unkFlags5);
|
||||
}
|
||||
|
||||
timer.End();
|
||||
Msg(eDLL_T::SERVER, "...done writing cluster links. %lf seconds (%d links)\n", timer.GetDuration().GetSeconds(), numClusterLinks);
|
||||
|
||||
// This is always set to '-1'. Likely a field for maintaining compatibility.
|
||||
FileSystem()->Write(&pNetwork->unk5, sizeof(pNetwork->unk5), pAIGraph);
|
||||
buf.PutInt(pNetwork->unk5);
|
||||
|
||||
// AIN v57 and above only (not present in r1, static array in r2, pointer to dynamic array in r5).
|
||||
timer.Start();
|
||||
DevMsg(eDLL_T::SERVER, "+- Writing script nodes...\n");
|
||||
|
||||
FileSystem()->Write(&pNetwork->m_iNumScriptNodes, sizeof(pNetwork->m_iNumScriptNodes), pAIGraph);
|
||||
buf.PutInt(pNetwork->m_iNumScriptNodes);
|
||||
for (int i = 0; i < pNetwork->m_iNumScriptNodes; i++)
|
||||
{
|
||||
// Disk and memory structs for script nodes are identical.
|
||||
DevMsg(eDLL_T::SERVER, " |-- Writing script node '#%d' at '0x%zX'\n", i, FileSystem()->Tell(pAIGraph));
|
||||
FileSystem()->Write(&pNetwork->m_ScriptNode[i], sizeof(CAI_ScriptNode), pAIGraph);
|
||||
DevMsg(eDLL_T::SERVER, " |-- Writing script node '#%d' at '0x%zX'\n", i, buf.TellPut());
|
||||
buf.Put(&pNetwork->m_ScriptNode[i], sizeof(CAI_ScriptNode));
|
||||
}
|
||||
|
||||
timer.End();
|
||||
@ -300,16 +331,17 @@ void CAI_NetworkBuilder::SaveNetworkGraph(CAI_Network* pNetwork)
|
||||
timer.Start();
|
||||
DevMsg(eDLL_T::SERVER, "+- Writing hint data...\n");
|
||||
|
||||
FileSystem()->Write(&pNetwork->m_iNumHints, sizeof(pNetwork->m_iNumHints), pAIGraph);
|
||||
buf.PutInt(pNetwork->m_iNumHints);
|
||||
for (int i = 0; i < pNetwork->m_iNumHints; i++)
|
||||
{
|
||||
DevMsg(eDLL_T::SERVER, " |-- Writing hint data '#%d' at '0x%zX'\n", i, FileSystem()->Tell(pAIGraph));
|
||||
FileSystem()->Write(&pNetwork->m_Hints[i], sizeof(pNetwork->m_Hints[i]), pAIGraph);
|
||||
DevMsg(eDLL_T::SERVER, " |-- Writing hint data '#%d' at '0x%zX'\n", i, buf.TellPut());
|
||||
buf.PutShort(pNetwork->m_Hints[i]);
|
||||
}
|
||||
|
||||
timer.End();
|
||||
Msg(eDLL_T::SERVER, "...done writing hint data. %lf seconds (%d hints)\n", timer.GetDuration().GetSeconds(), pNetwork->m_iNumHints);
|
||||
|
||||
FileSystem()->Write(buf.Base(), buf.TellPut(), pAIGraph);
|
||||
FileSystem()->Close(pAIGraph);
|
||||
|
||||
masterTimer.End();
|
||||
@ -326,7 +358,7 @@ CAI_NetworkManager::LoadNetworkGraph
|
||||
and validate status
|
||||
==============================
|
||||
*/
|
||||
void CAI_NetworkManager::LoadNetworkGraph(CAI_NetworkManager* pManager, void* pBuffer, const char* szAIGraphFile)
|
||||
void CAI_NetworkManager::LoadNetworkGraph(CAI_NetworkManager* pManager, CUtlBuffer* pBuffer, const char* szAIGraphFile)
|
||||
{
|
||||
bool bNavMeshAvailable = true;
|
||||
|
||||
@ -407,7 +439,7 @@ CAI_NetworkManager::LoadNetworkGraphEx
|
||||
(internal)
|
||||
==============================
|
||||
*/
|
||||
void CAI_NetworkManager::LoadNetworkGraphEx(CAI_NetworkManager* pManager, void* pBuffer, const char* szAIGraphFile)
|
||||
void CAI_NetworkManager::LoadNetworkGraphEx(CAI_NetworkManager* pManager, CUtlBuffer* pBuffer, const char* szAIGraphFile)
|
||||
{
|
||||
#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1)
|
||||
CAI_NetworkManager__LoadNetworkGraph(pManager, pBuffer, szAIGraphFile);
|
||||
|
@ -15,21 +15,27 @@ class CAI_NetworkBuilder;
|
||||
class CAI_NetworkManager;
|
||||
|
||||
/* ==== CAI_NETWORKMANAGER ============================================================================================================================================== */
|
||||
inline CMemory p_CAI_NetworkManager__InitializeAINetworks = nullptr;
|
||||
inline void (*CAI_NetworkManager__InitializeAINetworks)(void); // Static
|
||||
|
||||
inline CMemory p_CAI_NetworkManager__DelayedInit = nullptr;
|
||||
inline void (*CAI_NetworkManager__DelayedInit)(CAI_NetworkManager* thisptr, CAI_Network* pNetwork);
|
||||
#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1)
|
||||
inline CMemory p_CAI_NetworkManager__LoadNetworkGraph = nullptr;
|
||||
inline void (*CAI_NetworkManager__LoadNetworkGraph)(CAI_NetworkManager* thisptr, void* pBuffer, const char* pszFileName);
|
||||
inline void (*CAI_NetworkManager__LoadNetworkGraph)(CAI_NetworkManager* thisptr, CUtlBuffer* pBuffer, const char* pszFileName);
|
||||
#elif defined (GAMEDLL_S2) || defined (GAMEDLL_S3)
|
||||
inline CMemory p_CAI_NetworkManager__LoadNetworkGraph = nullptr;
|
||||
inline void (*CAI_NetworkManager__LoadNetworkGraph)(CAI_NetworkManager* thisptr, void* pBuffer, const char* pszFileName);
|
||||
inline void (*CAI_NetworkManager__LoadNetworkGraph)(CAI_NetworkManager* thisptr, CUtlBuffer* pBuffer, const char* pszFileName);
|
||||
#endif
|
||||
/* ==== CAI_NETWORKBUILDER ============================================================================================================================================== */
|
||||
inline CMemory p_CAI_NetworkBuilder__Build;
|
||||
inline void (*CAI_NetworkBuilder__Build)(CAI_NetworkBuilder* thisptr, CAI_Network* pNetwork);
|
||||
|
||||
inline CAI_NetworkManager** g_ppAINetworkManager = nullptr;
|
||||
|
||||
inline CUtlVector<CAI_Cluster*>* g_pAIPathClusters = nullptr;
|
||||
inline CUtlVector<CAI_ClusterLink*>* g_pAIClusterLinks = nullptr;
|
||||
inline CUtlVector<CAI_TraverseNode>* g_pAITraverseNodes = nullptr;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// CAI_NetworkEditTools
|
||||
@ -53,7 +59,7 @@ public:
|
||||
// Debugging Tools
|
||||
//-----------------
|
||||
int m_debugNetOverlays;
|
||||
CAI_Node** m_pNodes; // either nodes or node links.
|
||||
int* m_pNodeIndexTable;
|
||||
|
||||
//-----------------
|
||||
// Network pointers
|
||||
@ -92,8 +98,11 @@ public:
|
||||
class CAI_NetworkManager : public CBaseEntity
|
||||
{
|
||||
public:
|
||||
static void LoadNetworkGraph(CAI_NetworkManager* pAINetworkManager, void* pBuffer, const char* szAIGraphFile);
|
||||
static void LoadNetworkGraphEx(CAI_NetworkManager* pAINetworkManager, void* pBuffer, const char* szAIGraphFile);
|
||||
static void LoadNetworkGraph(CAI_NetworkManager* pAINetworkManager, CUtlBuffer* pBuffer, const char* szAIGraphFile);
|
||||
static void LoadNetworkGraphEx(CAI_NetworkManager* pAINetworkManager, CUtlBuffer* pBuffer, const char* szAIGraphFile);
|
||||
|
||||
CAI_NetworkEditTools* GetEditOps() { return m_pEditOps; }
|
||||
CAI_Network* GetNetwork() { /*Assert(!m_ThreadedBuild.pBuildingNetwork);*/ return m_pNetwork; }
|
||||
|
||||
private:
|
||||
// !TODO[ AMOS ]: If found, change to ptr and hook up to engine!
|
||||
@ -118,21 +127,27 @@ class VAI_NetworkManager : public IDetour
|
||||
{
|
||||
virtual void GetAdr(void) const
|
||||
{
|
||||
LogFunAdr("CAI_NetworkManager::InitializeAINetworks", p_CAI_NetworkManager__InitializeAINetworks.GetPtr());
|
||||
LogFunAdr("CAI_NetworkManager::LoadNetworkGraph", p_CAI_NetworkManager__LoadNetworkGraph.GetPtr());
|
||||
LogFunAdr("CAI_NetworkManager::DelayedInit", p_CAI_NetworkManager__DelayedInit.GetPtr());
|
||||
LogFunAdr("CAI_NetworkBuilder::Build", p_CAI_NetworkBuilder__Build.GetPtr());
|
||||
LogVarAdr("g_pAINetworkManager", reinterpret_cast<uintptr_t>(g_ppAINetworkManager));
|
||||
LogVarAdr("g_AIPathClusters< CAI_Cluster* >", reinterpret_cast<uintptr_t>(g_pAIPathClusters));
|
||||
LogVarAdr("g_AIClusterLinks< CAI_ClusterLink* >", reinterpret_cast<uintptr_t>(g_pAIClusterLinks));
|
||||
LogVarAdr("g_AITraverseNodes< CAI_TraverseNode >", reinterpret_cast<uintptr_t>(g_pAITraverseNodes));
|
||||
}
|
||||
virtual void GetFun(void) const
|
||||
{
|
||||
p_CAI_NetworkManager__InitializeAINetworks = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 48 89 74 24 ?? 48 89 7C 24 ?? 4C 89 74 24 ?? 55 48 8D AC 24 ?? ?? ?? ?? 48 81 EC ?? ?? ?? ?? E8 ?? ?? ?? ??");
|
||||
CAI_NetworkManager__InitializeAINetworks = p_CAI_NetworkManager__InitializeAINetworks.RCast<void (*)(void)>();
|
||||
|
||||
p_CAI_NetworkManager__DelayedInit = g_GameDll.FindPatternSIMD("40 53 48 83 EC 20 48 8B D9 48 8B 0D ?? ?? ?? ?? 8B 41 6C");
|
||||
#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1)
|
||||
p_CAI_NetworkManager__LoadNetworkGraph = g_GameDll.FindPatternSIMD("4C 89 44 24 ?? 48 89 4C 24 ?? 55 53 57 41 54 41 55 41 56");
|
||||
CAI_NetworkManager__LoadNetworkGraph = p_CAI_NetworkManager__LoadNetworkGraph.RCast<void (*)(CAI_NetworkManager*, void*, const char*)>();
|
||||
CAI_NetworkManager__LoadNetworkGraph = p_CAI_NetworkManager__LoadNetworkGraph.RCast<void (*)(CAI_NetworkManager*, CUtlBuffer*, const char*)>();
|
||||
#elif defined (GAMEDLL_S2) || defined (GAMEDLL_S3)
|
||||
p_CAI_NetworkManager__LoadNetworkGraph = g_GameDll.FindPatternSIMD("4C 89 44 24 ?? 48 89 4C 24 ?? 55 53 56 57 41 54 41 55 41 56 41 57 48 8D 6C 24 ?? 48 81 EC ?? ?? ?? ?? 48 8B FA");
|
||||
CAI_NetworkManager__LoadNetworkGraph = p_CAI_NetworkManager__LoadNetworkGraph.RCast<void (*)(CAI_NetworkManager*, void*, const char*)>();
|
||||
CAI_NetworkManager__LoadNetworkGraph = p_CAI_NetworkManager__LoadNetworkGraph.RCast<void (*)(CAI_NetworkManager*, CUtlBuffer*, const char*)>();
|
||||
#endif
|
||||
#if defined (GAMEDLL_S0) || defined (GAMEDLL_S1)
|
||||
p_CAI_NetworkBuilder__Build = g_GameDll.FindPatternSIMD("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 ?? ?? ?? ??");
|
||||
@ -144,10 +159,14 @@ class VAI_NetworkManager : public IDetour
|
||||
}
|
||||
virtual void GetVar(void) const
|
||||
{
|
||||
g_ppAINetworkManager = p_CAI_NetworkManager__InitializeAINetworks.FindPattern("48 89 05", CMemory::Direction::DOWN)
|
||||
.ResolveRelativeAddressSelf(0x3, 0x7).RCast<CAI_NetworkManager**>();
|
||||
g_pAIPathClusters = g_GameDll.FindPatternSIMD("F3 0F 10 52 ?? 4C 8B CA")
|
||||
.FindPatternSelf("48 8B 35", CMemory::Direction::DOWN).ResolveRelativeAddressSelf(0x3, 0x7).RCast<CUtlVector<CAI_Cluster*>*>();
|
||||
g_pAIClusterLinks = g_GameDll.FindPatternSIMD("F3 0F 10 52 ?? 4C 8B CA")
|
||||
.FindPatternSelf("4C 8B 1D", CMemory::Direction::DOWN).ResolveRelativeAddressSelf(0x3, 0x7).RCast<CUtlVector<CAI_ClusterLink*>*>();
|
||||
g_pAITraverseNodes = g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 55 56 57 41 54 41 56 48 8B EC 48 81 EC ?? ?? ?? ??").OffsetSelf(0x2EF)
|
||||
.FindPatternSelf("48 8B 05", CMemory::Direction::DOWN).ResolveRelativeAddressSelf(0x3, 0x7).RCast<CUtlVector<CAI_TraverseNode>*>();
|
||||
}
|
||||
virtual void GetCon(void) const { }
|
||||
virtual void Attach(void) const;
|
||||
|
@ -10,6 +10,19 @@ constexpr int MAX_HULLS = 5;
|
||||
constexpr int NOT_CACHED = -2; // Returned if data not in cache
|
||||
constexpr int NO_NODE = -1; // Returned when no node meets the qualification
|
||||
|
||||
//=========================================================
|
||||
// >> The type of node
|
||||
//=========================================================
|
||||
enum NodeType_e // !TODO: unconfirmed for r1/r2/r5.
|
||||
{
|
||||
NODE_ANY, // Used to specify any type of node (for search)
|
||||
NODE_DELETED, // Used in wc_edit mode to remove nodes during runtime
|
||||
NODE_GROUND,
|
||||
NODE_AIR,
|
||||
NODE_CLIMB,
|
||||
NODE_WATER
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
// >> CAI_NodeLink
|
||||
//=============================================================================
|
||||
@ -17,7 +30,7 @@ struct CAI_NodeLink
|
||||
{
|
||||
short m_iSrcID;
|
||||
short m_iDestID;
|
||||
bool m_bHulls[MAX_HULLS];
|
||||
byte m_iAcceptedMoveTypes[MAX_HULLS];
|
||||
byte m_LinkInfo;
|
||||
char unk1; // maps => unk0 on disk
|
||||
char unk2[5];
|
||||
@ -27,15 +40,31 @@ struct CAI_NodeLink
|
||||
//=============================================================================
|
||||
// >> CAI_Node
|
||||
//=============================================================================
|
||||
struct CAI_Node
|
||||
class CAI_Node
|
||||
{
|
||||
int m_nIndex; // Not present on disk
|
||||
Vector3D m_vOrigin;
|
||||
float m_fHulls[MAX_HULLS];
|
||||
float m_flYaw;
|
||||
public:
|
||||
const Vector3D& GetOrigin() const { return m_vOrigin; }
|
||||
Vector3D& AccessOrigin() { return m_vOrigin; }
|
||||
float GetYaw() const { return m_flYaw; }
|
||||
|
||||
int NumLinks() const { return m_Links.Count(); }
|
||||
void ClearLinks() { m_Links.Purge(); }
|
||||
CAI_NodeLink* GetLinkByIndex(int i) const { return m_Links[i]; }
|
||||
|
||||
NodeType_e SetType(NodeType_e type) { return (m_eNodeType = type); }
|
||||
NodeType_e GetType() const { return m_eNodeType; }
|
||||
|
||||
int SetInfo(int info) { return m_eNodeInfo = info; }
|
||||
int GetInfo() const { return m_eNodeInfo; }
|
||||
|
||||
int m_iID; // ID for this node
|
||||
Vector3D m_vOrigin; // location of this node in space
|
||||
float m_flVOffset[MAX_HULLS]; // vertical offset for each hull type, assuming ground node, 0 otherwise
|
||||
float m_flYaw; // NPC on this node should face this yaw to face the hint, or climb a ladder
|
||||
|
||||
NodeType_e m_eNodeType; // The type of node; always 2 in buildainfile.
|
||||
int m_eNodeInfo; // bits that tell us more about this nodes
|
||||
|
||||
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
|
||||
@ -43,36 +72,24 @@ struct CAI_Node
|
||||
char pad[3]; // Aligns next bytes
|
||||
float unk4[MAX_HULLS]; // I have no clue, calculated using some kind float function magic
|
||||
|
||||
CAI_NodeLink** links;
|
||||
void* unkBuf0;
|
||||
void* unkBuf1;
|
||||
int m_nNumLinks;
|
||||
int unk11; // Bad name lmao
|
||||
CUtlVector<CAI_NodeLink*> m_Links;
|
||||
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
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
// >> CAI_ScriptNode
|
||||
//=============================================================================
|
||||
struct CAI_ScriptNode
|
||||
{
|
||||
Vector3D m_vOrigin;
|
||||
|
||||
// Might be wrong; seems to be used for clamping.
|
||||
// See [r5apex_ds + 0xF28A6E]
|
||||
int m_nMin;
|
||||
int m_nMax;
|
||||
short unk8;
|
||||
short unk9; // Should match up to unk5 on disk
|
||||
char unk10[6]; // Padding until next bit
|
||||
char unk11[8]; // Should match up to unk6 on disk
|
||||
};
|
||||
|
||||
//=============================================================================
|
||||
// >> CAI_Cluster
|
||||
//=============================================================================
|
||||
struct CAI_Cluster
|
||||
class CAI_Cluster
|
||||
{
|
||||
public:
|
||||
const Vector3D& GetOrigin() const { return m_vOrigin; }
|
||||
Vector3D& AccessOrigin() { return m_vOrigin; }
|
||||
|
||||
int m_nIndex;
|
||||
char unk0;
|
||||
char unk1; // Maps to unk1 on disk
|
||||
@ -103,11 +120,34 @@ static_assert(sizeof(CAI_Cluster) == 608);
|
||||
//=============================================================================
|
||||
struct CAI_ClusterLink
|
||||
{
|
||||
short prevIndex_MAYBE;
|
||||
short nextIndex_MAYBE;
|
||||
short m_iSrcID;
|
||||
short m_iDestID;
|
||||
int unk2;
|
||||
char flags;
|
||||
char unk4;
|
||||
char unk5;
|
||||
char unkFlags4;
|
||||
char unkFlags5;
|
||||
};
|
||||
static_assert(sizeof(CAI_ClusterLink) == 12);
|
||||
|
||||
//=============================================================================
|
||||
// >> CAI_ScriptNode
|
||||
//=============================================================================
|
||||
struct CAI_TraverseNode
|
||||
{
|
||||
Quaternion m_Quat;
|
||||
int m_Index_MAYBE;
|
||||
};
|
||||
static_assert(sizeof(CAI_TraverseNode) == 20);
|
||||
|
||||
//=============================================================================
|
||||
// >> CAI_ScriptNode
|
||||
//=============================================================================
|
||||
struct CAI_ScriptNode
|
||||
{
|
||||
Vector3D m_vOrigin;
|
||||
|
||||
// Might be wrong; seems to be used for clamping.
|
||||
// See [r5apex_ds + 0xF28A6E]
|
||||
int m_nMin;
|
||||
int m_nMax;
|
||||
};
|
||||
static_assert(sizeof(CAI_ClusterLink) == 12);
|
@ -55,7 +55,7 @@ void CAI_Utility::DrawAIScriptNetwork(const CAI_Network* pNetwork) const
|
||||
OverlayBox_t::Transforms vTransforms;
|
||||
std::unordered_set<int64_t> uLinkSet;
|
||||
|
||||
for (int i = ai_script_nodes_draw->GetInt(), ns = pNetwork->GetNumScriptNodes(); i < ns; i++)
|
||||
for (int i = ai_script_nodes_draw->GetInt(), ns = pNetwork->NumScriptNodes(); i < ns; i++)
|
||||
{
|
||||
if (nNodeRange && i > nNodeRange)
|
||||
break;
|
||||
|
Loading…
x
Reference in New Issue
Block a user