diff --git a/main/source/detour/DetourNavMeshQuery.cpp b/main/source/detour/DetourNavMeshQuery.cpp index f3ec71ce..666981df 100644 --- a/main/source/detour/DetourNavMeshQuery.cpp +++ b/main/source/detour/DetourNavMeshQuery.cpp @@ -61,7 +61,7 @@ /// @see dtNavMeshQuery dtQueryFilter::dtQueryFilter() : - m_includeFlags(0xffffffff), + m_includeFlags(-1), m_excludeFlags(0) { for (int i = 0; i < DT_MAX_AREAS; ++i) diff --git a/main/source/detour/DetourTileCache.cpp b/main/source/detour/DetourTileCache.cpp index 233bb53c..63a8b91b 100644 --- a/main/source/detour/DetourTileCache.cpp +++ b/main/source/detour/DetourTileCache.cpp @@ -94,16 +94,12 @@ dtTileCache::~dtTileCache() } dtFree(m_obstacles); m_obstacles = 0; - dtFree(m_offMeshConnections); m_offMeshConnections = 0; - dtFree(m_posLookup); m_posLookup = 0; - dtFree(m_tiles); m_tiles = 0; - m_nreqs = 0; m_nOffMeshReqs = 0; m_nupdate = 0; @@ -423,6 +419,8 @@ dtStatus dtTileCache::addOffMeshConnection(const float* spos, const float* epos, memset(req, 0, sizeof(OffMeshRequest)); req->action = REQUEST_OFFMESH_ADD; req->ref = getOffMeshRef(con); + + con->userId = req->ref; if (result) *result = req->ref; diff --git a/main/source/mod/AIPlayers/AvHAINavigation.cpp b/main/source/mod/AIPlayers/AvHAINavigation.cpp index 73ce0350..f516b0cd 100644 --- a/main/source/mod/AIPlayers/AvHAINavigation.cpp +++ b/main/source/mod/AIPlayers/AvHAINavigation.cpp @@ -77,6 +77,33 @@ struct TileCacheSetExportHeader int OffMeshConsOffset; }; +struct TileCacheBuildHeader +{ + int magic; + int version; + int numRegularTiles; + int numOnosTiles; + int numBuildingTiles; + + dtNavMeshParams regularMeshParams; + dtTileCacheParams regularCacheParams; + + dtNavMeshParams onosMeshParams; + dtTileCacheParams onosCacheParams; + + dtNavMeshParams buildingMeshParams; + dtTileCacheParams buildingCacheParams; + + int NumSurfTypes; + int SurfTypesOffset; + + int NumOffMeshCons; + int OffMeshConsOffset; + + int NumConvexVols; + int ConvexVolOffset; +}; + struct TileCacheTileHeader { dtCompressedTileRef tileRef; @@ -571,17 +598,15 @@ bool LoadNavMesh(const char* mapname) FILE* savedFile = fopen(filename, "rb"); - if (!savedFile) - { - char buf[64]; - sprintf(buf, "Nav file for map %s not found.\n", mapname); - ALERT(at_console, buf); - return false; - } + if (!savedFile) { return false; } + + LinearAllocator* m_talloc = new LinearAllocator(32000); + FastLZCompressor* m_tcomp = new FastLZCompressor; + MeshProcess* m_tmproc = new MeshProcess; // Read header. - TileCacheSetExportHeader header; - size_t headerReadReturnCode = fread(&header, sizeof(TileCacheSetExportHeader), 1, savedFile); + TileCacheBuildHeader header; + size_t headerReadReturnCode = fread(&header, sizeof(TileCacheBuildHeader), 1, savedFile); if (headerReadReturnCode != 1) { // Error or early EOF @@ -589,139 +614,53 @@ bool LoadNavMesh(const char* mapname) UnloadNavigationData(); return false; } - if (header.magic != TILECACHESET_MAGIC) + + if (header.magic != TILECACHESET_MAGIC || header.version != TILECACHESET_VERSION) { - char buf[64]; - sprintf(buf, "Header Magic does not match! %d\n", header.magic); - ALERT(at_console, buf); - fclose(savedFile); - UnloadNavigationData(); - return false; - } - if (header.version != TILECACHESET_VERSION) - { - ALERT(at_console, "Header version does not match!\n"); fclose(savedFile); UnloadNavigationData(); return false; } - NavMeshes[REGULAR_NAV_MESH].navMesh = dtAllocNavMesh(); - if (!NavMeshes[REGULAR_NAV_MESH].navMesh) + dtNavMeshParams* NavMeshParams[3] = { &header.regularMeshParams, &header.onosMeshParams, &header.buildingMeshParams }; + dtTileCacheParams* TileCacheParams[3] = { &header.regularCacheParams, &header.onosCacheParams, &header.buildingCacheParams }; + + for (int i = 0; i <= BUILDING_NAV_MESH; i++) { - ALERT(at_console, "Could not allocate navmesh\n"); - fclose(savedFile); - UnloadNavigationData(); - return false; + NavMeshes[i].navMesh = dtAllocNavMesh(); + + if (!NavMeshes[i].navMesh) + { + fclose(savedFile); + UnloadNavigationData(); + return false; + } + + dtStatus status = NavMeshes[i].navMesh->init(NavMeshParams[i]); + if (dtStatusFailed(status)) + { + fclose(savedFile); + UnloadNavigationData(); + return false; + } + + NavMeshes[i].tileCache = dtAllocTileCache(); + if (!NavMeshes[i].tileCache) + { + fclose(savedFile); + UnloadNavigationData(); + return false; + } + + status = NavMeshes[i].tileCache->init(TileCacheParams[i], m_talloc, m_tcomp, m_tmproc); + if (dtStatusFailed(status)) + { + ALERT(at_console, "Could not initialise tile cache\n"); + fclose(savedFile); + UnloadNavigationData(); + return false; + } } - dtStatus status = NavMeshes[REGULAR_NAV_MESH].navMesh->init(&header.regularMeshParams); - if (dtStatusFailed(status)) - { - ALERT(at_console, "Could not initialise nav mesh\n"); - fclose(savedFile); - UnloadNavigationData(); - return false; - } - - NavMeshes[REGULAR_NAV_MESH].tileCache = dtAllocTileCache(); - if (!NavMeshes[REGULAR_NAV_MESH].tileCache) - { - ALERT(at_console, "Could not allocate tile cache\n"); - fclose(savedFile); - UnloadNavigationData(); - return false; - } - - - NavMeshes[ONOS_NAV_MESH].navMesh = dtAllocNavMesh(); - if (!NavMeshes[ONOS_NAV_MESH].navMesh) - { - ALERT(at_console, "Could not allocate onos navmesh\n"); - fclose(savedFile); - UnloadNavigationData(); - return false; - } - status = NavMeshes[ONOS_NAV_MESH].navMesh->init(&header.onosMeshParams); - if (dtStatusFailed(status)) - { - ALERT(at_console, "Could not initialise onos nav mesh\n"); - fclose(savedFile); - UnloadNavigationData(); - return false; - } - - NavMeshes[ONOS_NAV_MESH].tileCache = dtAllocTileCache(); - if (!NavMeshes[ONOS_NAV_MESH].tileCache) - { - ALERT(at_console, "Could not allocate onos tile cache\n"); - fclose(savedFile); - UnloadNavigationData(); - return false; - } - - - NavMeshes[BUILDING_NAV_MESH].navMesh = dtAllocNavMesh(); - if (!NavMeshes[BUILDING_NAV_MESH].navMesh) - { - ALERT(at_console, "Could not allocate building navmesh\n"); - fclose(savedFile); - UnloadNavigationData(); - return false; - } - status = NavMeshes[BUILDING_NAV_MESH].navMesh->init(&header.buildingMeshParams); - if (dtStatusFailed(status)) - { - ALERT(at_console, "Could not initialise building nav mesh\n"); - fclose(savedFile); - UnloadNavigationData(); - return false; - } - - NavMeshes[BUILDING_NAV_MESH].tileCache = dtAllocTileCache(); - if (!NavMeshes[BUILDING_NAV_MESH].tileCache) - { - ALERT(at_console, "Could not allocate building tile cache\n"); - fclose(savedFile); - UnloadNavigationData(); - return false; - } - - int CurrFilePos = ftell(savedFile); - - LinearAllocator* m_talloc = new LinearAllocator(32000); - FastLZCompressor* m_tcomp = new FastLZCompressor; - MeshProcess* m_tmproc = new MeshProcess; - - // TODO: Need to pass all off mesh connection verts, areas, flags etc as arrays to m_tmproc. Needs to be exported from recast as such - - status = NavMeshes[REGULAR_NAV_MESH].tileCache->init(&header.regularCacheParams, m_talloc, m_tcomp, m_tmproc); - if (dtStatusFailed(status)) - { - ALERT(at_console, "Could not initialise tile cache\n"); - fclose(savedFile); - UnloadNavigationData(); - return false; - } - - status = NavMeshes[ONOS_NAV_MESH].tileCache->init(&header.onosCacheParams, m_talloc, m_tcomp, m_tmproc); - if (dtStatusFailed(status)) - { - ALERT(at_console, "Could not initialise tile cache\n"); - fclose(savedFile); - UnloadNavigationData(); - return false; - } - - status = NavMeshes[BUILDING_NAV_MESH].tileCache->init(&header.buildingCacheParams, m_talloc, m_tcomp, m_tmproc); - if (dtStatusFailed(status)) - { - ALERT(at_console, "Could not initialise tile cache\n"); - fclose(savedFile); - UnloadNavigationData(); - return false; - } - - fseek(savedFile, CurrFilePos, SEEK_SET); // Read tiles. for (int i = 0; i < header.numRegularTiles; ++i) @@ -851,43 +790,24 @@ bool LoadNavMesh(const char* mapname) for (int ii = 0; ii < BUILDING_NAV_MESH; ii++) { - NavMeshes[ii].tileCache->addOffMeshConnection(&def.pos[0], &def.pos[3], def.rad, def.area, def.flags, def.bBiDir, 0); + NavMeshes[ii].tileCache->addOffMeshConnection(&def.pos[0], &def.pos[3], 10.0f, def.area, def.flags, def.bBiDir, 0); } } fclose(savedFile); - NavMeshes[REGULAR_NAV_MESH].navQuery = dtAllocNavMeshQuery(); - - dtStatus initStatus = NavMeshes[REGULAR_NAV_MESH].navQuery->init(NavMeshes[REGULAR_NAV_MESH].navMesh, 65535); - - if (dtStatusFailed(initStatus)) + for (int i = 0; i <= BUILDING_NAV_MESH; i++) { - ALERT(at_console, "Could not initialise nav query\n"); - UnloadNavigationData(); - return false; - } + NavMeshes[i].navQuery = dtAllocNavMeshQuery(); - NavMeshes[ONOS_NAV_MESH].navQuery = dtAllocNavMeshQuery(); + dtStatus initStatus = NavMeshes[i].navQuery->init(NavMeshes[i].navMesh, 65535); - initStatus = NavMeshes[ONOS_NAV_MESH].navQuery->init(NavMeshes[ONOS_NAV_MESH].navMesh, 65535); - - if (dtStatusFailed(initStatus)) - { - ALERT(at_console, "Could not initialise onos nav query\n"); - UnloadNavigationData(); - return false; - } - - NavMeshes[BUILDING_NAV_MESH].navQuery = dtAllocNavMeshQuery(); - - initStatus = NavMeshes[BUILDING_NAV_MESH].navQuery->init(NavMeshes[BUILDING_NAV_MESH].navMesh, 65535); - - if (dtStatusFailed(initStatus)) - { - ALERT(at_console, "Could not initialise building nav query\n"); - UnloadNavigationData(); - return false; + if (dtStatusFailed(initStatus)) + { + ALERT(at_console, "Could not initialise nav query\n"); + UnloadNavigationData(); + return false; + } } return true; @@ -914,120 +834,85 @@ void UTIL_PopulateBaseNavProfiles() BaseNavProfiles[MARINE_BASE_NAV_PROFILE].NavMeshIndex = REGULAR_NAV_MESH; BaseNavProfiles[MARINE_BASE_NAV_PROFILE].bFlyingProfile = false; BaseNavProfiles[MARINE_BASE_NAV_PROFILE].ReachabilityFlag = AI_REACHABILITY_MARINE; - BaseNavProfiles[MARINE_BASE_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_GROUND, 1.0f); BaseNavProfiles[MARINE_BASE_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_OBSTRUCTION, 2.0f); BaseNavProfiles[MARINE_BASE_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_CROUCH, 2.0f); BaseNavProfiles[MARINE_BASE_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_BLOCKED, 2.0f); BaseNavProfiles[MARINE_BASE_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_FALLDAMAGE, 10.0f); - BaseNavProfiles[MARINE_BASE_NAV_PROFILE].Filters.setIncludeFlags(0xFFFF); + BaseNavProfiles[MARINE_BASE_NAV_PROFILE].Filters.setIncludeFlags(SAMPLE_POLYFLAGS_ALL); + BaseNavProfiles[MARINE_BASE_NAV_PROFILE].Filters.removeIncludeFlags(SAMPLE_POLYFLAGS_FLY | SAMPLE_POLYFLAGS_WALLCLIMB | SAMPLE_POLYFLAGS_WELD); BaseNavProfiles[MARINE_BASE_NAV_PROFILE].Filters.setExcludeFlags(0); - BaseNavProfiles[MARINE_BASE_NAV_PROFILE].Filters.addExcludeFlags(SAMPLE_POLYFLAGS_WALLCLIMB); - BaseNavProfiles[MARINE_BASE_NAV_PROFILE].Filters.addExcludeFlags(SAMPLE_POLYFLAGS_WELD); - BaseNavProfiles[MARINE_BASE_NAV_PROFILE].Filters.addExcludeFlags(SAMPLE_POLYFLAGS_FLY); + BaseNavProfiles[SKULK_BASE_NAV_PROFILE].NavMeshIndex = REGULAR_NAV_MESH; BaseNavProfiles[SKULK_BASE_NAV_PROFILE].bFlyingProfile = false; BaseNavProfiles[SKULK_BASE_NAV_PROFILE].ReachabilityFlag = AI_REACHABILITY_SKULK; - BaseNavProfiles[SKULK_BASE_NAV_PROFILE].Filters.setIncludeFlags(0xFFFF); - BaseNavProfiles[SKULK_BASE_NAV_PROFILE].Filters.setExcludeFlags(0); - BaseNavProfiles[SKULK_BASE_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_GROUND, 1.0f); BaseNavProfiles[SKULK_BASE_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_OBSTRUCTION, 2.0f); - BaseNavProfiles[SKULK_BASE_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_CROUCH, 1.0f); - BaseNavProfiles[SKULK_BASE_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_BLOCKED, 1.0f); - BaseNavProfiles[SKULK_BASE_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_FALLDAMAGE, 1.0f); - BaseNavProfiles[SKULK_BASE_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_WALLCLIMB, 1.0f); - BaseNavProfiles[SKULK_BASE_NAV_PROFILE].Filters.addExcludeFlags(SAMPLE_POLYFLAGS_TEAM1PHASEGATE); - BaseNavProfiles[SKULK_BASE_NAV_PROFILE].Filters.addExcludeFlags(SAMPLE_POLYFLAGS_TEAM2PHASEGATE); - BaseNavProfiles[SKULK_BASE_NAV_PROFILE].Filters.addExcludeFlags(SAMPLE_POLYFLAGS_DUCKJUMP); - BaseNavProfiles[SKULK_BASE_NAV_PROFILE].Filters.addExcludeFlags(SAMPLE_POLYFLAGS_WELD); - BaseNavProfiles[SKULK_BASE_NAV_PROFILE].Filters.addExcludeFlags(SAMPLE_POLYFLAGS_FLY); + BaseNavProfiles[SKULK_BASE_NAV_PROFILE].Filters.setIncludeFlags(SAMPLE_POLYFLAGS_ALL); + BaseNavProfiles[SKULK_BASE_NAV_PROFILE].Filters.removeIncludeFlags(SAMPLE_POLYFLAGS_TEAM1PHASEGATE | SAMPLE_POLYFLAGS_TEAM2PHASEGATE | SAMPLE_POLYFLAGS_DUCKJUMP | SAMPLE_POLYFLAGS_WELD | SAMPLE_POLYFLAGS_FLY); + BaseNavProfiles[SKULK_BASE_NAV_PROFILE].Filters.setExcludeFlags(0); + BaseNavProfiles[GORGE_BASE_NAV_PROFILE].NavMeshIndex = REGULAR_NAV_MESH; BaseNavProfiles[GORGE_BASE_NAV_PROFILE].bFlyingProfile = false; BaseNavProfiles[GORGE_BASE_NAV_PROFILE].ReachabilityFlag = AI_REACHABILITY_GORGE; - BaseNavProfiles[GORGE_BASE_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_GROUND, 1.0f); BaseNavProfiles[GORGE_BASE_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_OBSTRUCTION, 2.0f); - BaseNavProfiles[GORGE_BASE_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_CROUCH, 1.0f); BaseNavProfiles[GORGE_BASE_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_BLOCKED, 2.0f); BaseNavProfiles[GORGE_BASE_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_FALLDAMAGE, 10.0f); - BaseNavProfiles[GORGE_BASE_NAV_PROFILE].Filters.setIncludeFlags(0xFFFF); + BaseNavProfiles[GORGE_BASE_NAV_PROFILE].Filters.setIncludeFlags(SAMPLE_POLYFLAGS_ALL); BaseNavProfiles[GORGE_BASE_NAV_PROFILE].Filters.setExcludeFlags(0); - BaseNavProfiles[GORGE_BASE_NAV_PROFILE].Filters.addExcludeFlags(SAMPLE_POLYFLAGS_WALLCLIMB); - BaseNavProfiles[GORGE_BASE_NAV_PROFILE].Filters.addExcludeFlags(SAMPLE_POLYFLAGS_TEAM1PHASEGATE); - BaseNavProfiles[GORGE_BASE_NAV_PROFILE].Filters.addExcludeFlags(SAMPLE_POLYFLAGS_TEAM2PHASEGATE); - BaseNavProfiles[GORGE_BASE_NAV_PROFILE].Filters.addExcludeFlags(SAMPLE_POLYFLAGS_DUCKJUMP); - BaseNavProfiles[GORGE_BASE_NAV_PROFILE].Filters.addExcludeFlags(SAMPLE_POLYFLAGS_WELD); - BaseNavProfiles[GORGE_BASE_NAV_PROFILE].Filters.addExcludeFlags(SAMPLE_POLYFLAGS_FLY); + BaseNavProfiles[GORGE_BASE_NAV_PROFILE].Filters.removeIncludeFlags(SAMPLE_POLYFLAGS_WALLCLIMB); + BaseNavProfiles[GORGE_BASE_NAV_PROFILE].Filters.removeIncludeFlags(SAMPLE_POLYFLAGS_TEAM1PHASEGATE); + BaseNavProfiles[GORGE_BASE_NAV_PROFILE].Filters.removeIncludeFlags(SAMPLE_POLYFLAGS_TEAM2PHASEGATE); + BaseNavProfiles[GORGE_BASE_NAV_PROFILE].Filters.removeIncludeFlags(SAMPLE_POLYFLAGS_DUCKJUMP); + BaseNavProfiles[GORGE_BASE_NAV_PROFILE].Filters.removeIncludeFlags(SAMPLE_POLYFLAGS_WELD); + BaseNavProfiles[GORGE_BASE_NAV_PROFILE].Filters.removeIncludeFlags(SAMPLE_POLYFLAGS_FLY); BaseNavProfiles[LERK_BASE_NAV_PROFILE].NavMeshIndex = REGULAR_NAV_MESH; BaseNavProfiles[LERK_BASE_NAV_PROFILE].bFlyingProfile = true; BaseNavProfiles[LERK_BASE_NAV_PROFILE].ReachabilityFlag = AI_REACHABILITY_SKULK; - BaseNavProfiles[LERK_BASE_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_GROUND, 1.0f); BaseNavProfiles[LERK_BASE_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_OBSTRUCTION, 2.0f); - BaseNavProfiles[LERK_BASE_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_CROUCH, 1.0f); - BaseNavProfiles[LERK_BASE_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_BLOCKED, 1.0f); - BaseNavProfiles[LERK_BASE_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_FALLDAMAGE, 1.0f); - BaseNavProfiles[LERK_BASE_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_WALLCLIMB, 1.0f); - BaseNavProfiles[LERK_BASE_NAV_PROFILE].Filters.setIncludeFlags(0xFFFF); + BaseNavProfiles[LERK_BASE_NAV_PROFILE].Filters.setIncludeFlags(SAMPLE_POLYFLAGS_ALL); BaseNavProfiles[LERK_BASE_NAV_PROFILE].Filters.setExcludeFlags(0); - BaseNavProfiles[LERK_BASE_NAV_PROFILE].Filters.addExcludeFlags(SAMPLE_POLYFLAGS_TEAM1PHASEGATE); - BaseNavProfiles[LERK_BASE_NAV_PROFILE].Filters.addExcludeFlags(SAMPLE_POLYFLAGS_TEAM2PHASEGATE); - BaseNavProfiles[LERK_BASE_NAV_PROFILE].Filters.addExcludeFlags(SAMPLE_POLYFLAGS_WELD); + BaseNavProfiles[LERK_BASE_NAV_PROFILE].Filters.removeIncludeFlags(SAMPLE_POLYFLAGS_TEAM1PHASEGATE); + BaseNavProfiles[LERK_BASE_NAV_PROFILE].Filters.removeIncludeFlags(SAMPLE_POLYFLAGS_TEAM2PHASEGATE); + BaseNavProfiles[LERK_BASE_NAV_PROFILE].Filters.removeIncludeFlags(SAMPLE_POLYFLAGS_WELD); BaseNavProfiles[FADE_BASE_NAV_PROFILE].NavMeshIndex = REGULAR_NAV_MESH; BaseNavProfiles[FADE_BASE_NAV_PROFILE].bFlyingProfile = false; BaseNavProfiles[FADE_BASE_NAV_PROFILE].ReachabilityFlag = AI_REACHABILITY_SKULK; - BaseNavProfiles[FADE_BASE_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_GROUND, 1.0f); BaseNavProfiles[FADE_BASE_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_OBSTRUCTION, 2.0f); BaseNavProfiles[FADE_BASE_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_CROUCH, 1.5f); - BaseNavProfiles[FADE_BASE_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_BLOCKED, 1.0f); - BaseNavProfiles[FADE_BASE_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_FALLDAMAGE, 1.0f); - BaseNavProfiles[FADE_BASE_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_WALLCLIMB, 1.0f); - BaseNavProfiles[FADE_BASE_NAV_PROFILE].Filters.setIncludeFlags(0xFFFF); + BaseNavProfiles[FADE_BASE_NAV_PROFILE].Filters.setIncludeFlags(SAMPLE_POLYFLAGS_ALL); BaseNavProfiles[FADE_BASE_NAV_PROFILE].Filters.setExcludeFlags(0); - BaseNavProfiles[FADE_BASE_NAV_PROFILE].Filters.addExcludeFlags(SAMPLE_POLYFLAGS_TEAM1PHASEGATE); - BaseNavProfiles[FADE_BASE_NAV_PROFILE].Filters.addExcludeFlags(SAMPLE_POLYFLAGS_TEAM2PHASEGATE); - BaseNavProfiles[FADE_BASE_NAV_PROFILE].Filters.addExcludeFlags(SAMPLE_POLYFLAGS_WELD); - BaseNavProfiles[FADE_BASE_NAV_PROFILE].Filters.addExcludeFlags(SAMPLE_POLYFLAGS_FLY); + BaseNavProfiles[FADE_BASE_NAV_PROFILE].Filters.removeIncludeFlags(SAMPLE_POLYFLAGS_TEAM1PHASEGATE); + BaseNavProfiles[FADE_BASE_NAV_PROFILE].Filters.removeIncludeFlags(SAMPLE_POLYFLAGS_TEAM2PHASEGATE); + BaseNavProfiles[FADE_BASE_NAV_PROFILE].Filters.removeIncludeFlags(SAMPLE_POLYFLAGS_WELD); + BaseNavProfiles[FADE_BASE_NAV_PROFILE].Filters.removeIncludeFlags(SAMPLE_POLYFLAGS_FLY); BaseNavProfiles[ONOS_BASE_NAV_PROFILE].NavMeshIndex = ONOS_NAV_MESH; BaseNavProfiles[ONOS_BASE_NAV_PROFILE].bFlyingProfile = false; BaseNavProfiles[ONOS_BASE_NAV_PROFILE].ReachabilityFlag = AI_REACHABILITY_ONOS; - BaseNavProfiles[ONOS_BASE_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_GROUND, 1.0f); BaseNavProfiles[ONOS_BASE_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_OBSTRUCTION, 2.0f); BaseNavProfiles[ONOS_BASE_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_CROUCH, 2.0f); - BaseNavProfiles[ONOS_BASE_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_BLOCKED, 1.0f); BaseNavProfiles[ONOS_BASE_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_FALLDAMAGE, 10.0f); - BaseNavProfiles[ONOS_BASE_NAV_PROFILE].Filters.setIncludeFlags(0xFFFF); + BaseNavProfiles[ONOS_BASE_NAV_PROFILE].Filters.setIncludeFlags(SAMPLE_POLYFLAGS_ALL); BaseNavProfiles[ONOS_BASE_NAV_PROFILE].Filters.setExcludeFlags(0); - BaseNavProfiles[ONOS_BASE_NAV_PROFILE].Filters.addExcludeFlags(SAMPLE_POLYFLAGS_WALLCLIMB); - BaseNavProfiles[ONOS_BASE_NAV_PROFILE].Filters.addExcludeFlags(SAMPLE_POLYFLAGS_TEAM1PHASEGATE); - BaseNavProfiles[ONOS_BASE_NAV_PROFILE].Filters.addExcludeFlags(SAMPLE_POLYFLAGS_TEAM2PHASEGATE); - BaseNavProfiles[ONOS_BASE_NAV_PROFILE].Filters.addExcludeFlags(SAMPLE_POLYFLAGS_WELD); - BaseNavProfiles[ONOS_BASE_NAV_PROFILE].Filters.addExcludeFlags(SAMPLE_POLYFLAGS_NOONOS); - BaseNavProfiles[ONOS_BASE_NAV_PROFILE].Filters.addExcludeFlags(SAMPLE_POLYFLAGS_FLY); + BaseNavProfiles[ONOS_BASE_NAV_PROFILE].Filters.removeIncludeFlags(SAMPLE_POLYFLAGS_WALLCLIMB); + BaseNavProfiles[ONOS_BASE_NAV_PROFILE].Filters.removeIncludeFlags(SAMPLE_POLYFLAGS_TEAM1PHASEGATE); + BaseNavProfiles[ONOS_BASE_NAV_PROFILE].Filters.removeIncludeFlags(SAMPLE_POLYFLAGS_TEAM2PHASEGATE); + BaseNavProfiles[ONOS_BASE_NAV_PROFILE].Filters.removeIncludeFlags(SAMPLE_POLYFLAGS_WELD); + BaseNavProfiles[ONOS_BASE_NAV_PROFILE].Filters.removeIncludeFlags(SAMPLE_POLYFLAGS_NOONOS); + BaseNavProfiles[ONOS_BASE_NAV_PROFILE].Filters.removeIncludeFlags(SAMPLE_POLYFLAGS_FLY); BaseNavProfiles[STRUCTURE_BASE_NAV_PROFILE].NavMeshIndex = BUILDING_NAV_MESH; - BaseNavProfiles[STRUCTURE_BASE_NAV_PROFILE].Filters.setIncludeFlags(0xFFFF); + BaseNavProfiles[STRUCTURE_BASE_NAV_PROFILE].Filters.setIncludeFlags(SAMPLE_POLYFLAGS_ALL); BaseNavProfiles[STRUCTURE_BASE_NAV_PROFILE].Filters.setExcludeFlags(0); - BaseNavProfiles[STRUCTURE_BASE_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_GROUND, 1.0f); - BaseNavProfiles[STRUCTURE_BASE_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_OBSTRUCTION, 1.0f); - BaseNavProfiles[STRUCTURE_BASE_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_CROUCH, 1.0f); - BaseNavProfiles[STRUCTURE_BASE_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_BLOCKED, 1.0f); - BaseNavProfiles[STRUCTURE_BASE_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_FALLDAMAGE, 1.0f); - BaseNavProfiles[STRUCTURE_BASE_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_WALLCLIMB, 1.0f); BaseNavProfiles[STRUCTURE_BASE_NAV_PROFILE].bFlyingProfile = false; BaseNavProfiles[STRUCTURE_BASE_NAV_PROFILE].ReachabilityFlag = AI_REACHABILITY_MARINE; BaseNavProfiles[ALL_NAV_PROFILE].NavMeshIndex = REGULAR_NAV_MESH; - BaseNavProfiles[ALL_NAV_PROFILE].Filters.setIncludeFlags(0xFFFF); + BaseNavProfiles[ALL_NAV_PROFILE].Filters.setIncludeFlags(SAMPLE_POLYFLAGS_ALL); BaseNavProfiles[ALL_NAV_PROFILE].Filters.setExcludeFlags(0); - BaseNavProfiles[ALL_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_GROUND, 1.0f); - BaseNavProfiles[ALL_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_OBSTRUCTION, 1.0f); - BaseNavProfiles[ALL_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_CROUCH, 1.0f); - BaseNavProfiles[ALL_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_BLOCKED, 1.0f); - BaseNavProfiles[ALL_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_FALLDAMAGE, 1.0f); - BaseNavProfiles[ALL_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_WALLCLIMB, 1.0f); BaseNavProfiles[ALL_NAV_PROFILE].bFlyingProfile = false; BaseNavProfiles[ALL_NAV_PROFILE].ReachabilityFlag = AI_REACHABILITY_SKULK; } diff --git a/main/source/mod/AIPlayers/AvHAINavigation.h b/main/source/mod/AIPlayers/AvHAINavigation.h index 63946cb9..a948e9ad 100644 --- a/main/source/mod/AIPlayers/AvHAINavigation.h +++ b/main/source/mod/AIPlayers/AvHAINavigation.h @@ -63,7 +63,7 @@ enum SamplePolyFlags SAMPLE_POLYFLAGS_TEAM2STRUCTURE = 1 << 12, // A team 2 structure is in the way that cannot be jumped over. Impassable to team 2 players (assume cannot teamkill own structures) SAMPLE_POLYFLAGS_WELD = 1 << 13, // Requires a welder to get through here SAMPLE_POLYFLAGS_DOOR = 1 << 14, // Requires a welder to get through here - SAMPLE_POLYFLAGS_LIFT = 1 << 15, // Disabled, not usable by anyone + SAMPLE_POLYFLAGS_LIFT = 1 << 15, // Requires using a lift or moving platform SAMPLE_POLYFLAGS_DISABLED = 1 << 16, // Disabled, not usable by anyone SAMPLE_POLYFLAGS_ALL = -1 // All abilities. diff --git a/main/source/mod/AIPlayers/AvHAIPlayerManager.cpp b/main/source/mod/AIPlayers/AvHAIPlayerManager.cpp index 3f797347..0f34565e 100644 --- a/main/source/mod/AIPlayers/AvHAIPlayerManager.cpp +++ b/main/source/mod/AIPlayers/AvHAIPlayerManager.cpp @@ -631,14 +631,23 @@ void AIMGR_ResetRound() AIStartedTime = gpGlobals->time; } + AITAC_ClearMapAIData(); + UTIL_PopulateDoors(); UTIL_PopulateWeldableObstacles(); - AITAC_ClearMapAIData(); - ALERT(at_console, "AI Manager Reset Round\n"); } +void AIMGR_RoundStarted() +{ + AITAC_RefreshHiveData(); + + UTIL_UpdateTileCache(); + + AITAC_RefreshResourceNodes(); +} + void AIMGR_ClearBotData() { // We have to be careful here, depending on how the nav data is being unloaded, there could be stale references in the ActiveAIPlayers list. diff --git a/main/source/mod/AIPlayers/AvHAIPlayerManager.h b/main/source/mod/AIPlayers/AvHAIPlayerManager.h index bbf622bc..5afd4733 100644 --- a/main/source/mod/AIPlayers/AvHAIPlayerManager.h +++ b/main/source/mod/AIPlayers/AvHAIPlayerManager.h @@ -15,6 +15,8 @@ void AIMGR_BotPrecache(); void AIMGR_ResetRound(); // Called when a new map is loaded. Clears all tactical information AND loads new navmesh. void AIMGR_NewMap(); +// Called when the match begins (countdown finished). Populates initial tactical information. +void AIMGR_RoundStarted(); // Adds a new AI player to a team (0 = Auto-assign, 1 = Team A, 2 = Team B) void AIMGR_AddAIPlayerToTeam(int Team); diff --git a/main/source/mod/AIPlayers/AvHAITactical.cpp b/main/source/mod/AIPlayers/AvHAITactical.cpp index 93809a21..04e74586 100644 --- a/main/source/mod/AIPlayers/AvHAITactical.cpp +++ b/main/source/mod/AIPlayers/AvHAITactical.cpp @@ -570,7 +570,7 @@ void AITAC_RefreshHiveData() Vector AITAC_GetTeamStartingLocation(AvHTeamNumber Team) { - if (TeamAStartingLocation == ZERO_VECTOR || TeamBStartingLocation == ZERO_VECTOR) + if (vIsZero(TeamAStartingLocation) || vIsZero(TeamBStartingLocation)) { AvHTeam* AvHTeamARef = GetGameRules()->GetTeamA(); AvHTeam* AvHTeamBRef = GetGameRules()->GetTeamB(); @@ -606,13 +606,13 @@ Vector AITAC_GetTeamStartingLocation(AvHTeamNumber Team) if (AvHTeamBRef->GetTeamType() == AVH_CLASS_TYPE_MARINE) { - TeamBStartingLocation = AvHTeamBRef->GetStartingLocation(); + TeamBStartingLocation = TeamStartLocation; } else { TeamBStartingLocation = TeamStartLocation; - const AvHAIHiveDefinition* Hive = AITAC_GetHiveNearestLocation(TeamStartLocation); + const AvHAIHiveDefinition* Hive = AITAC_GetActiveHiveNearestLocation(TeamStartLocation); if (Hive) { @@ -730,14 +730,29 @@ void AITAC_RefreshReachabilityForItem(AvHAIDroppedItem* Item) } } +void AITAC_RefreshAllResNodeReachability() +{ + for (auto it = ResourceNodes.begin(); it != ResourceNodes.end(); it++) + { + AITAC_RefreshReachabilityForResNode(&(*it)); + } +} + void AITAC_RefreshReachabilityForResNode(AvHAIResourceNode* ResNode) { + if (Hives.size() == 0) + { + AITAC_RefreshHiveData(); + } + ResNode->bReachabilityMarkedDirty = false; ResNode->TeamAReachabilityFlags = AI_REACHABILITY_NONE; ResNode->TeamBReachabilityFlags = AI_REACHABILITY_NONE; - bool bOnNavMesh = UTIL_PointIsOnNavmesh(BaseNavProfiles[MARINE_BASE_NAV_PROFILE], ResNode->Location, Vector(max_player_use_reach, max_player_use_reach, max_player_use_reach)); + Vector ResNodeLocation = AdjustPointForPathfinding(ResNode->Location); + + bool bOnNavMesh = UTIL_PointIsOnNavmesh(BaseNavProfiles[MARINE_BASE_NAV_PROFILE], ResNodeLocation, Vector(max_player_use_reach, max_player_use_reach, max_player_use_reach)); if (!bOnNavMesh) { @@ -748,7 +763,7 @@ void AITAC_RefreshReachabilityForResNode(AvHAIResourceNode* ResNode) if (GetGameRules()->GetTeamA()->GetTeamType() == AVH_CLASS_TYPE_MARINE) { - bool bIsReachableMarine = UTIL_PointIsReachable(BaseNavProfiles[MARINE_BASE_NAV_PROFILE], AITAC_GetTeamStartingLocation(GetGameRules()->GetTeamANumber()), ResNode->Location, max_player_use_reach); + bool bIsReachableMarine = UTIL_PointIsReachable(BaseNavProfiles[MARINE_BASE_NAV_PROFILE], AITAC_GetTeamStartingLocation(GetGameRules()->GetTeamANumber()), ResNodeLocation, max_player_use_reach); if (bIsReachableMarine) { @@ -762,7 +777,7 @@ void AITAC_RefreshReachabilityForResNode(AvHAIResourceNode* ResNode) WelderProfile.Filters.removeExcludeFlags(SAMPLE_POLYFLAGS_WELD); - bool bIsReachableWelder = UTIL_PointIsReachable(WelderProfile, AITAC_GetTeamStartingLocation(GetGameRules()->GetTeamANumber()), ResNode->Location, max_player_use_reach); + bool bIsReachableWelder = UTIL_PointIsReachable(WelderProfile, AITAC_GetTeamStartingLocation(GetGameRules()->GetTeamANumber()), ResNodeLocation, max_player_use_reach); if (bIsReachableWelder) { @@ -772,9 +787,9 @@ void AITAC_RefreshReachabilityForResNode(AvHAIResourceNode* ResNode) } else { - bool bIsReachableSkulk = UTIL_PointIsReachable(BaseNavProfiles[SKULK_BASE_NAV_PROFILE], AITAC_GetTeamStartingLocation(GetGameRules()->GetTeamANumber()), ResNode->Location, max_player_use_reach); - bool bIsReachableGorge = UTIL_PointIsReachable(BaseNavProfiles[GORGE_BASE_NAV_PROFILE], AITAC_GetTeamStartingLocation(GetGameRules()->GetTeamANumber()), ResNode->Location, max_player_use_reach); - bool bIsReachableOnos = UTIL_PointIsReachable(BaseNavProfiles[ONOS_BASE_NAV_PROFILE], AITAC_GetTeamStartingLocation(GetGameRules()->GetTeamANumber()), ResNode->Location, max_player_use_reach); + bool bIsReachableSkulk = UTIL_PointIsReachable(BaseNavProfiles[SKULK_BASE_NAV_PROFILE], AITAC_GetTeamStartingLocation(GetGameRules()->GetTeamANumber()), ResNodeLocation, max_player_use_reach); + bool bIsReachableGorge = UTIL_PointIsReachable(BaseNavProfiles[GORGE_BASE_NAV_PROFILE], AITAC_GetTeamStartingLocation(GetGameRules()->GetTeamANumber()), ResNodeLocation, max_player_use_reach); + bool bIsReachableOnos = UTIL_PointIsReachable(BaseNavProfiles[ONOS_BASE_NAV_PROFILE], AITAC_GetTeamStartingLocation(GetGameRules()->GetTeamANumber()), ResNodeLocation, max_player_use_reach); if (bIsReachableSkulk) { @@ -794,7 +809,7 @@ void AITAC_RefreshReachabilityForResNode(AvHAIResourceNode* ResNode) if (GetGameRules()->GetTeamB()->GetTeamType() == AVH_CLASS_TYPE_MARINE) { - bool bIsReachableMarine = UTIL_PointIsReachable(BaseNavProfiles[MARINE_BASE_NAV_PROFILE], AITAC_GetTeamStartingLocation(GetGameRules()->GetTeamBNumber()), ResNode->Location, max_player_use_reach); + bool bIsReachableMarine = UTIL_PointIsReachable(BaseNavProfiles[MARINE_BASE_NAV_PROFILE], AITAC_GetTeamStartingLocation(GetGameRules()->GetTeamBNumber()), ResNodeLocation, max_player_use_reach); if (bIsReachableMarine) { @@ -808,7 +823,7 @@ void AITAC_RefreshReachabilityForResNode(AvHAIResourceNode* ResNode) WelderProfile.Filters.removeExcludeFlags(SAMPLE_POLYFLAGS_WELD); - bool bIsReachableWelder = UTIL_PointIsReachable(WelderProfile, AITAC_GetTeamStartingLocation(GetGameRules()->GetTeamANumber()), ResNode->Location, max_player_use_reach); + bool bIsReachableWelder = UTIL_PointIsReachable(WelderProfile, AITAC_GetTeamStartingLocation(GetGameRules()->GetTeamBNumber()), ResNodeLocation, max_player_use_reach); if (bIsReachableWelder) { @@ -818,9 +833,16 @@ void AITAC_RefreshReachabilityForResNode(AvHAIResourceNode* ResNode) } else { - bool bIsReachableSkulk = UTIL_PointIsReachable(BaseNavProfiles[SKULK_BASE_NAV_PROFILE], AITAC_GetTeamStartingLocation(GetGameRules()->GetTeamBNumber()), ResNode->Location, max_player_use_reach); - bool bIsReachableGorge = UTIL_PointIsReachable(BaseNavProfiles[GORGE_BASE_NAV_PROFILE], AITAC_GetTeamStartingLocation(GetGameRules()->GetTeamBNumber()), ResNode->Location, max_player_use_reach); - bool bIsReachableOnos = UTIL_PointIsReachable(BaseNavProfiles[ONOS_BASE_NAV_PROFILE], AITAC_GetTeamStartingLocation(GetGameRules()->GetTeamBNumber()), ResNode->Location, max_player_use_reach); + bool bIsReachableSkulk = UTIL_PointIsReachable(BaseNavProfiles[SKULK_BASE_NAV_PROFILE], AITAC_GetTeamStartingLocation(GetGameRules()->GetTeamBNumber()), ResNodeLocation, max_player_use_reach); + + if (!bIsReachableSkulk) + { + UTIL_DrawLine(INDEXENT(1), INDEXENT(1)->v.origin, ResNodeLocation, 20.0f); + UTIL_DrawLine(INDEXENT(1), INDEXENT(1)->v.origin, AITAC_GetTeamStartingLocation(GetGameRules()->GetTeamBNumber()), 20.0f, 255, 255, 0); + } + + bool bIsReachableGorge = UTIL_PointIsReachable(BaseNavProfiles[GORGE_BASE_NAV_PROFILE], AITAC_GetTeamStartingLocation(GetGameRules()->GetTeamBNumber()), ResNodeLocation, max_player_use_reach); + bool bIsReachableOnos = UTIL_PointIsReachable(BaseNavProfiles[ONOS_BASE_NAV_PROFILE], AITAC_GetTeamStartingLocation(GetGameRules()->GetTeamBNumber()), ResNodeLocation, max_player_use_reach); if (bIsReachableSkulk) { @@ -923,6 +945,12 @@ AvHAIResourceNode* AITAC_GetRandomResourceNode(AvHTeamNumber SearchingTeam, cons void AITAC_UpdateMapAIData() { + AITAC_RefreshHiveData(); + + UTIL_UpdateDoors(false); + UTIL_UpdateWeldableObstacles(); + + if (gpGlobals->time - last_structure_refresh_time >= structure_inventory_refresh_rate) { AITAC_RefreshBuildableStructures(); @@ -935,11 +963,6 @@ void AITAC_UpdateMapAIData() AITAC_RefreshMarineItems(); last_item_refresh_time = gpGlobals->time; } - - UTIL_UpdateDoors(false); - UTIL_UpdateWeldableObstacles(); - - AITAC_RefreshHiveData(); } void AITAC_CheckNavMeshModified() @@ -1298,6 +1321,11 @@ void AITAC_OnItemDropped(const AvHAIDroppedItem* NewItem) void AITAC_RefreshReachabilityForStructure(AvHAIBuildableStructure* Structure) { + if (Hives.size() == 0) + { + AITAC_RefreshHiveData(); + } + Structure->bReachabilityMarkedDirty = false; bool bIsOnNavMesh = UTIL_PointIsOnNavmesh(BaseNavProfiles[MARINE_BASE_NAV_PROFILE], UTIL_GetEntityGroundLocation(Structure->edict), Vector(max_player_use_reach, max_player_use_reach, max_player_use_reach)); @@ -1612,11 +1640,9 @@ void AITAC_OnStructureDestroyed(AvHAIBuildableStructure* DestroyedStructure) if (DestroyedStructure->StructureType == STRUCTURE_MARINE_PHASEGATE) { // Eliminate all connections from this phase gate - for (auto it = DestroyedStructure->OffMeshConnections.begin(); it != DestroyedStructure->OffMeshConnections.begin();) + for (auto it = DestroyedStructure->OffMeshConnections.begin(); it != DestroyedStructure->OffMeshConnections.end(); it++) { UTIL_RemoveOffMeshConnections(&(*it)); - - it = DestroyedStructure->OffMeshConnections.erase(it); } DestroyedStructure->OffMeshConnections.clear(); @@ -2024,6 +2050,27 @@ const AvHAIHiveDefinition* AITAC_GetHiveNearestLocation(const Vector SearchLocat return Result; } +const AvHAIHiveDefinition* AITAC_GetActiveHiveNearestLocation(const Vector SearchLocation) +{ + AvHAIHiveDefinition* Result = nullptr; + float MinDist = 0.0f; + + for (auto it = Hives.begin(); it != Hives.end(); it++) + { + if (it->Status != HIVE_STATUS_BUILT) { continue; } + + float ThisDist = vDist3DSq(SearchLocation, it->Location); + + if (!Result || ThisDist < MinDist) + { + Result = &(*it); + MinDist = ThisDist; + } + } + + return Result; +} + AvHAIResourceNode* AITAC_GetNearestResourceNodeToLocation(const Vector Location) { AvHAIResourceNode* Result = nullptr; diff --git a/main/source/mod/AIPlayers/AvHAITactical.h b/main/source/mod/AIPlayers/AvHAITactical.h index 8a462438..bc86782d 100644 --- a/main/source/mod/AIPlayers/AvHAITactical.h +++ b/main/source/mod/AIPlayers/AvHAITactical.h @@ -34,6 +34,7 @@ void AITAC_RefreshBuildableStructures(); void AITAC_UpdateBuildableStructure(CBaseEntity* Structure); void AITAC_RefreshReachabilityForStructure(AvHAIBuildableStructure* Structure); void AITAC_RefreshReachabilityForResNode(AvHAIResourceNode* ResNode); +void AITAC_RefreshAllResNodeReachability(); void AITAC_RefreshReachabilityForItem(AvHAIDroppedItem* Item); void AITAC_OnStructureCreated(AvHAIBuildableStructure* NewStructure); void AITAC_OnStructureCompleted(AvHAIBuildableStructure* NewStructure); @@ -46,6 +47,7 @@ float AITAC_GetPhaseDistanceBetweenPoints(const Vector StartPoint, const Ve const AvHAIHiveDefinition* AITAC_GetHiveAtIndex(int Index); const AvHAIHiveDefinition* AITAC_GetHiveNearestLocation(const Vector SearchLocation); +const AvHAIHiveDefinition* AITAC_GetActiveHiveNearestLocation(const Vector SearchLocation); Vector AITAC_GetCommChairLocation(AvHTeamNumber Team); edict_t* AITAC_GetCommChair(AvHTeamNumber Team); diff --git a/main/source/mod/AvHConsoleCommands.cpp b/main/source/mod/AvHConsoleCommands.cpp index 6d400c22..90f686ad 100644 --- a/main/source/mod/AvHConsoleCommands.cpp +++ b/main/source/mod/AvHConsoleCommands.cpp @@ -1485,6 +1485,29 @@ BOOL AvHGamerules::ClientCommand( CBasePlayer *pPlayer, const char *pcmd ) theSuccess = true; } + else if (FStrEq(pcmd, "testreachable")) + { + Vector TeamAStart = AITAC_GetTeamStartingLocation(TEAM_ONE); + Vector TeamBStart = AITAC_GetTeamStartingLocation(TEAM_TWO); + + Vector CheckLoc = UTIL_GetFloorUnderEntity(theAvHPlayer->edict()); + + UTIL_DrawLine(INDEXENT(1), TeamAStart, CheckLoc, 10.0f, 0, 0, 255); + UTIL_DrawLine(INDEXENT(1), TeamBStart, CheckLoc, 10.0f, 255, 255, 0); + + bool bTeamARechable = UTIL_PointIsReachable(GetBaseNavProfile(MARINE_BASE_NAV_PROFILE), TeamAStart, CheckLoc, max_player_use_reach); + bool bTeamBRechable = UTIL_PointIsReachable(GetBaseNavProfile(SKULK_BASE_NAV_PROFILE), TeamBStart, CheckLoc, max_player_use_reach); + + char buf[64]; + + sprintf(buf, "Team A: %s\n", (bTeamARechable) ? "True" : "False"); + UTIL_SayText(buf, theAvHPlayer); + + sprintf(buf, "Team B: %s\n", (bTeamBRechable) ? "True" : "False"); + UTIL_SayText(buf, theAvHPlayer); + + theSuccess = true; + } else if (FStrEq(pcmd, "tracelift")) { Vector TraceStart = GetPlayerEyePosition(theAvHPlayer->edict()); // origin + pev->view_ofs diff --git a/main/source/mod/AvHGamerules.cpp b/main/source/mod/AvHGamerules.cpp index d0d2b9a4..b2223586 100644 --- a/main/source/mod/AvHGamerules.cpp +++ b/main/source/mod/AvHGamerules.cpp @@ -3417,6 +3417,7 @@ void AvHGamerules::SetGameStarted(bool inGameStarted) if(!this->mGameStarted && inGameStarted) { FireTargets(ktGameStartedStatus, NULL, NULL, USE_TOGGLE, 0.0f); + AIMGR_RoundStarted(); //AvHNexus::startGame(); } this->mGameStarted = inGameStarted;