diff --git a/dlls/nodes.cpp b/dlls/nodes.cpp index 04705638..5e5b6acf 100644 --- a/dlls/nodes.cpp +++ b/dlls/nodes.cpp @@ -21,6 +21,7 @@ #include "cbase.h" #include "monsters.h" #include "nodes.h" +#include "nodes_compat.h" #include "animation.h" #include "doors.h" @@ -2386,42 +2387,47 @@ int CGraph::FLoadGraph( const char *szMapName ) pMemFile = aMemFile = LOAD_FILE_FOR_ME( szFilename, &length ); if( !aMemFile ) - { return FALSE; - } - else - { - // Read the graph version number - // - length -= sizeof(int); - if( length < 0 ) - goto ShortFile; - memcpy( &iVersion, pMemFile, sizeof(int) ); - pMemFile += sizeof(int); - if( iVersion != GRAPH_VERSION ) - { - // This file was written by a different build of the dll! - // - ALERT( at_aiconsole, "**ERROR** Graph version is %d, expected %d\n", iVersion, GRAPH_VERSION ); - goto ShortFile; - } + // Read the graph version number + // + length -= sizeof(int); + if( length < 0 ) + goto ShortFile; + iVersion = *(int *) pMemFile; + pMemFile += sizeof(int); + if( iVersion == GRAPH_VERSION || iVersion == 16 ) + { // Read the graph class // - length -= sizeof(CGraph); - if( length < 0 ) - goto ShortFile; - memcpy( this, pMemFile, sizeof(CGraph) ); - pMemFile += sizeof(CGraph); + if ( iVersion == GRAPH_VERSION ) + { + length -= sizeof(CGraph); + if( length < 0 ) + goto ShortFile; + memcpy( this, pMemFile, sizeof(CGraph) ); + pMemFile += sizeof(CGraph); - // Set the pointers to zero, just in case we run out of memory. - // - m_pNodes = NULL; - m_pLinkPool = NULL; - m_di = NULL; - m_pRouteInfo = NULL; - m_pHashLinks = NULL; + // Set the pointers to zero, just in case we run out of memory. + // + m_pNodes = NULL; + m_pLinkPool = NULL; + m_di = NULL; + m_pRouteInfo = NULL; + m_pHashLinks = NULL; + } +#if _GRAPH_VERSION != 16 + else + { + ALERT( at_aiconsole, "Loading CGraph in GRAPH_VERSION 16 compatibility mode\n" ); + length -= sizeof(CGraph_32); + if( length < 0 ) + goto ShortFile; + reinterpret_cast(pMemFile) -> copyOverTo(this); + pMemFile += sizeof(CGraph_32); + } +#endif // Malloc for the nodes // @@ -2453,11 +2459,25 @@ int CGraph::FLoadGraph( const char *szMapName ) // Read in all the links // - length -= sizeof(CLink) * m_cLinks; - if( length < 0 ) - goto ShortFile; - memcpy( m_pLinkPool, pMemFile, sizeof(CLink) * m_cLinks ); - pMemFile += sizeof(CLink) * m_cLinks; + if( iVersion == GRAPH_VERSION ) + { + length -= sizeof(CLink) * m_cLinks; + if( length < 0 ) + goto ShortFile; + memcpy( m_pLinkPool, pMemFile, sizeof(CLink) * m_cLinks ); + pMemFile += sizeof(CLink) * m_cLinks; + } +#if _GRAPH_VERSION != 16 + else + { + ALERT( at_aiconsole, "Loading CLink array in GRAPH_VERSION 16 compatibility mode\n" ); + length -= sizeof(CLink_32) * m_cLinks; + if( length < 0 ) + goto ShortFile; + reinterpret_cast(pMemFile) -> copyOverTo(m_pLinkPool); + pMemFile += sizeof(CLink_32) * m_cLinks; + } +#endif // Malloc for the sorting info. // @@ -2482,7 +2502,7 @@ int CGraph::FLoadGraph( const char *szMapName ) m_pRouteInfo = (signed char *)calloc( sizeof(signed char), m_nRouteInfo ); if( !m_pRouteInfo ) { - ALERT( at_aiconsole, "***ERROR**\nCounldn't malloc %d route bytes!\n", m_nRouteInfo ); + ALERT( at_aiconsole, "***ERROR**\nCouldn't malloc %d route bytes!\n", m_nRouteInfo ); goto NoMemory; } m_CheckedCounter = 0; @@ -2505,7 +2525,7 @@ int CGraph::FLoadGraph( const char *szMapName ) m_pHashLinks = (short *)calloc( sizeof(short), m_nHashLinks ); if( !m_pHashLinks ) { - ALERT( at_aiconsole, "***ERROR**\nCounldn't malloc %d hash link bytes!\n", m_nHashLinks ); + ALERT( at_aiconsole, "***ERROR**\nCouldn't malloc %d hash link bytes!\n", m_nHashLinks ); goto NoMemory; } @@ -2531,6 +2551,13 @@ int CGraph::FLoadGraph( const char *szMapName ) return TRUE; } + else + { + // This file was written by a different build of the dll! + // + ALERT( at_aiconsole, "**ERROR** Graph version is %d, expected %d\n", iVersion, GRAPH_VERSION ); + goto ShortFile; + } ShortFile: NoMemory: diff --git a/dlls/nodes.h b/dlls/nodes.h index 52b715e5..f43684c8 100644 --- a/dlls/nodes.h +++ b/dlls/nodes.h @@ -106,10 +106,11 @@ typedef struct // CGraph //========================================================= #ifdef XASH_64BIT -#define GRAPH_VERSION (int)16 * 10 +#define _GRAPH_VERSION (16 * 10) #else -#define GRAPH_VERSION (int)16// !!!increment this whever graph/node/link classes change, to obsolesce older disk files. +#define _GRAPH_VERSION (16)// !!!increment this whever graph/node/link classes change, to obsolesce older disk files. #endif +#define GRAPH_VERSION (int)_GRAPH_VERSION class CGraph { diff --git a/dlls/nodes_compat.h b/dlls/nodes_compat.h new file mode 100644 index 00000000..da91a5b8 --- /dev/null +++ b/dlls/nodes_compat.h @@ -0,0 +1,141 @@ + +#pragma once +#ifndef NODES_32BIT_COMPAT +#define NODES_32BIT_COMPAT + +//#include "nodes.h" + +#if _GRAPH_VERSION != 16 + +#include "stdint.h" + +typedef int32_t PTR32; + +class CGraph_32 +{ +public: + + BOOL m_fGraphPresent; + BOOL m_fGraphPointersSet; + BOOL m_fRoutingComplete; + + PTR32 m_pNodes; // CNode* + PTR32 m_pLinkPool; // CLink* + PTR32 m_pRouteInfo; // signed char* + + int m_cNodes; + int m_cLinks; + int m_nRouteInfo; + + PTR32 m_di; // DIST_INFO* + int m_RangeStart[3][NUM_RANGES]; + int m_RangeEnd[3][NUM_RANGES]; + float m_flShortest; + int m_iNearest; + int m_minX, m_minY, m_minZ, m_maxX, m_maxY, m_maxZ; + int m_minBoxX, m_minBoxY, m_minBoxZ, m_maxBoxX, m_maxBoxY, m_maxBoxZ; + int m_CheckedCounter; + float m_RegionMin[3], m_RegionMax[3]; + CACHE_ENTRY m_Cache[CACHE_SIZE]; + + + int m_HashPrimes[16]; + PTR32 m_pHashLinks; // short* + int m_nHashLinks; + + int m_iLastActiveIdleSearch; + + int m_iLastCoverSearch; + + + void copyOverTo(CGraph *other) { + other->m_fGraphPresent = m_fGraphPresent; + other->m_fGraphPointersSet = m_fGraphPointersSet; + other->m_fRoutingComplete = m_fRoutingComplete; + + other->m_pNodes = NULL; + other->m_pLinkPool = NULL; + other->m_pRouteInfo = NULL; + + other->m_cNodes = m_cNodes; + other->m_cLinks = m_cLinks; + other->m_nRouteInfo = m_nRouteInfo; + + other->m_di = NULL; +#if _GRAPH_VERSION == 160 + memcpy( (void *) &other->m_RangeStart, (void *) m_RangeStart, + offsetof(class CGraph, m_pHashLinks) - offsetof(class CGraph, m_RangeStart) ); +#else // fallback routine if the graph version changes + for (int i = 0; i < 3; ++i) + for (int j = 0; j < NUM_RANGES; ++j) + other->m_RangeStart[i][j] = m_RangeStart[i][j]; +// m_RangeStart[3][NUM_RANGES] + for (int i = 0; i < 3; ++i) + for (int j = 0; j < NUM_RANGES; ++j) + other->m_RangeEnd[i][j] = m_RangeEnd[i][j]; +// m_RangeEnd[3][NUM_RANGES] + other->m_flShortest = m_flShortest; + other->m_iNearest = m_iNearest; + other->m_minX = m_minX; + other->m_minY = m_minY; + other->m_minZ = m_minZ; + other->m_maxX = m_maxX; + other->m_maxY = m_maxY; + other->m_maxZ = m_maxZ; + other->m_minBoxX = m_minBoxX; + other->m_minBoxY = m_minBoxY; + other->m_minBoxZ = m_minBoxZ; + other->m_maxBoxX = m_maxBoxX; + other->m_maxBoxY = m_maxBoxY; + other->m_maxBoxZ = m_maxBoxZ; + other->m_CheckedCounter = m_CheckedCounter; + for (int i = 0; i < 3; ++i) + other->m_RegionMin[i] = m_RegionMin[i]; +// m_RegionMin[3] + for (int i = 0; i < 3; ++i) + other->m_RegionMax[i] = m_RegionMax[i]; +// m_RegionMax[3] + for (int i = 0; i < CACHE_SIZE; ++i) + other->m_Cache[i] = m_Cache[i]; +// m_Cache[CACHE_SIZE] + for (int i = 0; i < 16; ++i) + other->m_HashPrimes[i] = m_HashPrimes[i]; +// m_HashPrimes[16] +#endif + other->m_pHashLinks = NULL; + other->m_nHashLinks = m_nHashLinks; + + other->m_iLastActiveIdleSearch = m_iLastActiveIdleSearch; + + other->m_iLastCoverSearch = m_iLastCoverSearch; + + } + +}; + + +class CLink_32 +{ + +public: + int m_iSrcNode; + int m_iDestNode; + PTR32 m_pLinkEnt; // entvars_t* + char m_szLinkEntModelname[ 4 ]; + int m_afLinkInfo; + float m_flWeight; + + void copyOverTo(CLink* other) { + other->m_iSrcNode = m_iSrcNode; + other->m_iDestNode = m_iDestNode ; + other->m_pLinkEnt = NULL; + for (int i = 0; i < 4; ++i) + other->m_szLinkEntModelname[i] = m_szLinkEntModelname[i]; +// m_szLinkEntModelname[ 4 ] + other->m_afLinkInfo = m_afLinkInfo; + other->m_flWeight = m_flWeight; + } +}; + +#endif +#endif