Performance improvements

This commit is contained in:
RGreenlees 2024-03-18 16:48:50 +00:00 committed by pierow
parent 6883eb33b3
commit ad1c5da03a
9 changed files with 174 additions and 52 deletions

View file

@ -129,7 +129,7 @@ cvar_t avh_botsenabled = { kvBotsEnabled,"0", FCVAR_SERVER }; // Bots can b
cvar_t avh_botautomode = { kvBotAutoMode,"0", FCVAR_SERVER }; // Defines automated behaviour for adding/removing bots. 0 = manual (must add via console), 1 = automatic (auto-fills teams), 2 = balance only (only keeps teams even)
cvar_t avh_botminplayers = { kvBotMinPlayers,"0", FCVAR_SERVER }; // If bots are enabled and auto mode == 1 then it will maintain this player count by adding/removing as needed
cvar_t avh_botskill = { kvBotSkill,"1", FCVAR_SERVER }; // Sets the skill for the bots (0 = easiest, 3 = hardest)
cvar_t avh_botusemapdefaults = { kvBotUseMapDefaults,"0", FCVAR_SERVER }; // If bot auto mode == 1 then the min players will be taken from the config
cvar_t avh_botusemapdefaults = { kvBotUseMapDefaults,"1", FCVAR_SERVER }; // If bot auto mode == 1 then the min players will be taken from the config
cvar_t avh_botcommandermode = { kvBotCommanderMode,"0", FCVAR_SERVER }; // 0 = Bots never command, 1 = If nobody takes charge, 2 = Only if no humans on team
cvar_t avh_botdebugmode = { kvBotDebugMode,"0", FCVAR_SERVER }; // 0 = Regular play, 1 = Drone mode, 2 = Test Navigation mode
cvar_t avh_botallowlerk = { kvBotAllowLerk,"1", FCVAR_SERVER }; // 0 = Bot will never evolve lerk, 1 = Bot will go lerk when appropriate

View file

@ -212,6 +212,13 @@ typedef enum _AVHAICOMBATSTRATEGY
COMBAT_STRATEGY_ATTACK // Attack the enemy
} AvHAICombatStrategy;
typedef enum _AVHAINAVMESHSTATUS
{
NAVMESH_STATUS_PENDING = 0, // Waiting to try loading the navmesh
NAVMESH_STATUS_FAILED, // Failed to load the navmesh
NAVMESH_STATUS_SUCCESS // Successfully loaded the navmesh
} AvHAINavMeshStatus;
typedef struct _OFF_MESH_CONN
{
unsigned int ConnectionRefs[2];

View file

@ -230,7 +230,8 @@ bool IsEdictStructure(const edict_t* edict)
bool IsEdictHive(const edict_t* edict)
{
return (GetDeployableObjectTypeFromEdict(edict) != STRUCTURE_ALIEN_HIVE);
if (FNullEnt(edict)) { return false; }
return (edict->v.iuser3 == AVH_USER3_HIVE);
}
bool IsDamagingStructure(const edict_t* StructureEdict)

View file

@ -42,6 +42,8 @@ vector<AvHAIOffMeshConnection> BaseMapConnections;
nav_mesh NavMeshes[MAX_NAV_MESHES] = { }; // Array of nav meshes. Currently only 3 are used (building, onos, and regular)
nav_profile BaseNavProfiles[MAX_NAV_PROFILES] = { }; // Array of nav profiles
AvHAINavMeshStatus NavmeshStatus = NAVMESH_STATUS_PENDING;
vector<NavHint> MapNavHints;
extern bool bNavMeshModified;
@ -833,6 +835,8 @@ void UnloadNavMeshes()
BaseMapConnections.clear();
MapNavHints.clear();
NavmeshStatus = NAVMESH_STATUS_PENDING;
}
void UnloadNavigationData()
@ -860,7 +864,11 @@ bool LoadNavMesh(const char* mapname)
FILE* savedFile = fopen(filename, "rb");
if (!savedFile) { return false; }
if (!savedFile)
{
ALERT(at_console, "No nav file found for %s in the navmeshes folder.", mapname);
return false;
}
LinearAllocator* m_talloc = new LinearAllocator(32000);
FastLZCompressor* m_tcomp = new FastLZCompressor;
@ -874,6 +882,7 @@ bool LoadNavMesh(const char* mapname)
// Error or early EOF
fclose(savedFile);
UnloadNavigationData();
ALERT(at_console, "The nav file found for %s is a different version to the current bot version. Please regenerate it.", mapname);
return false;
}
@ -881,6 +890,7 @@ bool LoadNavMesh(const char* mapname)
{
fclose(savedFile);
UnloadNavigationData();
ALERT(at_console, "The nav file found for %s is a different version to the current bot version. Please regenerate it.", mapname);
return false;
}
@ -895,6 +905,7 @@ bool LoadNavMesh(const char* mapname)
{
fclose(savedFile);
UnloadNavigationData();
ALERT(at_console, "Unable to allocate memory for the nav mesh.", mapname);
return false;
}
@ -903,6 +914,7 @@ bool LoadNavMesh(const char* mapname)
{
fclose(savedFile);
UnloadNavigationData();
ALERT(at_console, "Could not initialise nav mesh, please try regenerating the nav file.\n");
return false;
}
@ -917,7 +929,7 @@ bool LoadNavMesh(const char* mapname)
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");
ALERT(at_console, "Could not initialise tile cache, please try regenerating the nav file.\n");
fclose(savedFile);
UnloadNavigationData();
return false;
@ -933,6 +945,7 @@ bool LoadNavMesh(const char* mapname)
{
fclose(savedFile);
UnloadNavigationData();
ALERT(at_console, "The nav file has been corrupted or is out of date. Please try regenerating it.\n");
return false;
}
if (!tileHeader.tileRef || !tileHeader.dataSize)
@ -947,6 +960,7 @@ bool LoadNavMesh(const char* mapname)
dtFree(data);
fclose(savedFile);
UnloadNavigationData();
ALERT(at_console, "The nav file has been corrupted or is out of date. Please try regenerating it.\n");
return false;
}
@ -969,6 +983,7 @@ bool LoadNavMesh(const char* mapname)
{
fclose(savedFile);
UnloadNavigationData();
ALERT(at_console, "The nav file has been corrupted or is out of date. Please try regenerating it.\n");
return false;
}
if (!tileHeader.tileRef || !tileHeader.dataSize)
@ -983,6 +998,7 @@ bool LoadNavMesh(const char* mapname)
dtFree(data);
fclose(savedFile);
UnloadNavigationData();
ALERT(at_console, "The nav file has been corrupted or is out of date. Please try regenerating it.\n");
return false;
}
@ -1005,6 +1021,7 @@ bool LoadNavMesh(const char* mapname)
{
fclose(savedFile);
UnloadNavigationData();
ALERT(at_console, "The nav file has been corrupted or is out of date. Please try regenerating it.\n");
return false;
}
if (!tileHeader.tileRef || !tileHeader.dataSize)
@ -1019,6 +1036,7 @@ bool LoadNavMesh(const char* mapname)
dtFree(data);
fclose(savedFile);
UnloadNavigationData();
ALERT(at_console, "The nav file has been corrupted or is out of date. Please try regenerating it.\n");
return false;
}
@ -1103,6 +1121,7 @@ bool LoadNavMesh(const char* mapname)
if (dtStatusFailed(initStatus))
{
UnloadNavigationData();
ALERT(at_console, "The nav file has been corrupted or is out of date. Please try regenerating it.\n");
return false;
}
}
@ -1254,8 +1273,11 @@ bool loadNavigationData(const char* mapname)
if (!LoadNavMesh(mapname))
{
NavmeshStatus = NAVMESH_STATUS_FAILED;
return false;
}
NavmeshStatus = NAVMESH_STATUS_SUCCESS;
UTIL_PopulateBaseNavProfiles();
@ -1267,6 +1289,11 @@ bool NavmeshLoaded()
return NavMeshes[0].navMesh != nullptr;
}
AvHAINavMeshStatus NAV_GetNavMeshStatus()
{
return NavmeshStatus;
}
Vector UTIL_GetRandomPointOnNavmesh(const AvHAIPlayer* pBot)
{
const dtNavMeshQuery* m_navQuery = UTIL_GetNavMeshQueryForProfile(pBot->BotNavInfo.NavProfile);
@ -3081,11 +3108,36 @@ DoorTrigger* UTIL_GetNearestDoorTrigger(const Vector Location, nav_door* Door, C
void CheckAndHandleBreakableObstruction(AvHAIPlayer* pBot, const Vector MoveFrom, const Vector MoveTo)
{
if (pBot->BotNavInfo.CurrentPathPoint > pBot->BotNavInfo.CurrentPath.size()) { return; }
if (pBot->BotNavInfo.CurrentPathPoint >= pBot->BotNavInfo.CurrentPath.size()) { return; }
Vector MoveDir = UTIL_GetVectorNormal2D(MoveTo - pBot->Edict->v.origin);
if (vIsZero(MoveDir))
{
MoveDir = UTIL_GetForwardVector2D(pBot->Edict->v.angles);
}
TraceResult breakableHit;
edict_t* BlockingBreakableEdict = nullptr;
UTIL_TraceLine(pBot->Edict->v.origin, pBot->Edict->v.origin + (MoveDir * 100.0f), dont_ignore_monsters, dont_ignore_glass, pBot->Edict->v.pContainingEntity, &breakableHit);
if (!FNullEnt(breakableHit.pHit))
{
if (strcmp(STRING(breakableHit.pHit->v.classname), "func_breakable") == 0)
{
BlockingBreakableEdict = breakableHit.pHit;
}
}
bot_path_node CurrentPathNode = pBot->BotNavInfo.CurrentPath[pBot->BotNavInfo.CurrentPathPoint];
edict_t* BlockingBreakableEdict = UTIL_GetBreakableBlockingPathPoint(pBot, pBot->Edict->v.origin, CurrentPathNode.Location, SAMPLE_POLYAREA_GROUND, nullptr);
if (FNullEnt(BlockingBreakableEdict))
{
BlockingBreakableEdict = UTIL_GetBreakableBlockingPathPoint(pBot, pBot->Edict->v.origin, CurrentPathNode.Location, SAMPLE_POLYAREA_GROUND, nullptr);
}
if (FNullEnt(BlockingBreakableEdict))
{
@ -5912,13 +5964,18 @@ bool MoveTo(AvHAIPlayer* pBot, const Vector Destination, const BotMoveStyle Move
}
else
{
if (!vIsZero(BotNavInfo->UnstuckMoveLocation) && vDist2DSq(pBot->CurrentFloorPosition, BotNavInfo->UnstuckMoveLocation) < sqrf(8.0f))
{
BotNavInfo->UnstuckMoveLocation = ZERO_VECTOR;
}
if (vIsZero(BotNavInfo->UnstuckMoveLocation))
{
BotNavInfo->UnstuckMoveLocation = FindClosestPointBackOnPath(pBot);
}
if (!vIsZero(BotNavInfo->UnstuckMoveLocation))
{
{
MoveDirectlyTo(pBot, BotNavInfo->UnstuckMoveLocation);
return true;
}
@ -6020,17 +6077,17 @@ Vector FindClosestPointBackOnPath(AvHAIPlayer* pBot)
// Now we find a path backwards from the valid nav mesh point to our location, trying to get as close as we can to it
dtStatus BackwardFindingStatus = FindPathClosestToPoint(pBot->BotNavInfo.NavProfile, ValidNavmeshPoint, pBot->CurrentFloorPosition, BackwardsPath, 500.0f);
dtStatus BackwardFindingStatus = FindPathClosestToPoint(pBot->BotNavInfo.NavProfile, ValidNavmeshPoint, pBot->CurrentFloorPosition, BackwardsPath, UTIL_MetresToGoldSrcUnits(50.0f));
if (dtStatusSucceed(BackwardFindingStatus))
{
Vector NewMoveLocation = ZERO_VECTOR;
Vector NewMoveFromLocation = ZERO_VECTOR;
Vector NewMoveLocation = prev(BackwardsPath.end())->Location;
Vector NewMoveFromLocation = prev(BackwardsPath.end())->FromLocation;
for (auto it = BackwardsPath.rbegin(); it != BackwardsPath.rend(); it++)
{
if (UTIL_QuickTrace(pBot->Edict, pBot->Edict->v.origin, it->Location))
if (vDist2DSq(pBot->Edict->v.origin, it->Location) > sqrf(GetPlayerRadius(pBot->Edict)) && UTIL_QuickTrace(pBot->Edict, pBot->Edict->v.origin, it->Location))
{
NewMoveLocation = it->Location;
NewMoveFromLocation = it->FromLocation;

View file

@ -152,6 +152,8 @@ bool LoadNavMesh(const char* mapname);
// Unloads the nav meshes (UnloadNavMeshes()) and then reloads them (LoadNavMesh). Map data such as doors, hives, locations are not touched.
void ReloadNavMeshes();
AvHAINavMeshStatus NAV_GetNavMeshStatus();
void SetBaseNavProfile(AvHAIPlayer* pBot);
void UpdateBotMoveProfile(AvHAIPlayer* pBot, BotMoveStyle MoveStyle);
void MarineUpdateBotMoveProfile(AvHAIPlayer* pBot, BotMoveStyle MoveStyle);

View file

@ -107,7 +107,6 @@ float AIMGR_GetCommanderAllowedTime(AvHTeamNumber Team)
void AIMGR_UpdateAIPlayerCounts()
{
if (!NavmeshLoaded()) { return; }
for (auto BotIt = ActiveAIPlayers.begin(); BotIt != ActiveAIPlayers.end();)
{
@ -137,7 +136,7 @@ void AIMGR_UpdateAIPlayerCounts()
LastAIPlayerCountUpdate = gpGlobals->time;
// If bots are disabled, ensure we've removed all bots from the game
if (avh_botsenabled.value == 0)
if (!AIMGR_IsBotEnabled())
{
if (AIMGR_GetNumAIPlayers() > 0)
{
@ -591,7 +590,7 @@ void AIDEBUG_TestPathFind()
void AIMGR_UpdateAIPlayers()
{
// If bots are not enabled then do nothing
if (avh_botsenabled.value == 0) { return; }
if (!AIMGR_IsBotEnabled()) { return; }
static float PrevTime = 0.0f;
static float CurrTime = 0.0f;
@ -600,6 +599,8 @@ void AIMGR_UpdateAIPlayers()
static int CurrentBotSkill = 1;
static bool bUpdateEven = false;
CurrTime = gpGlobals->time;
if (CurrTime < PrevTime)
@ -642,12 +643,15 @@ void AIMGR_UpdateAIPlayers()
memcpy(&bot->BotSkillSettings, &NewSkillSettings, sizeof(bot_skill));
}
int BotIndex = distance(ActiveAIPlayers.begin(), BotIt);
BotUpdateViewRotation(bot, FrameDelta);
if (IS_DEDICATED_SERVER() || ThinkDelta >= BOT_MIN_FRAME_TIME)
{
BotDeltaTime = ThinkDelta;
#ifdef DEBUG
if (bot == AIMGR_GetDebugAIPlayer())
{
bool bBreak = true; // Add a break point here if you want to debug a specific bot
@ -674,6 +678,7 @@ void AIMGR_UpdateAIPlayers()
}
}
}
#endif
if (bHasRoundStarted)
{
@ -707,25 +712,30 @@ void AIMGR_UpdateAIPlayers()
BotResumePlay(bot);
}
StartNewBotFrame(bot);
bool bIsEvenBot = !(BotIndex % 2);
UpdateBotChat(bot);
if (avh_botdebugmode.value == 1)
if (bIsEvenBot == bUpdateEven)
{
DroneThink(bot);
StartNewBotFrame(bot);
UpdateBotChat(bot);
if (avh_botdebugmode.value == 1)
{
DroneThink(bot);
}
else if (avh_botdebugmode.value == 2)
{
TestNavThink(bot);
}
else
{
AIPlayerThink(bot);
}
EndBotFrame(bot);
}
else if (avh_botdebugmode.value == 2)
{
TestNavThink(bot);
}
else
{
AIPlayerThink(bot);
}
EndBotFrame(bot);
BotUpdateDesiredViewRotation(bot);
}
else
@ -763,7 +773,7 @@ void AIMGR_UpdateAIPlayers()
}
PrevTime = CurrTime;
bUpdateEven = !bUpdateEven;
}
float AIMGR_GetBotDeltaTime()
@ -920,7 +930,7 @@ void AIMGR_RemoveBotsInReadyRoom()
void AIMGR_ResetRound()
{
if (avh_botsenabled.value == 0 || !NavmeshLoaded()) { return; } // Do nothing if we're not using bots
if (!AIMGR_IsBotEnabled()) { return; } // Do nothing if we're not using bots
// AI Players would be 0 if the round is being reset because a new game is starting. If the round is reset
// from a console command, or tournament mode readying up etc, then bot logic is unaffected
@ -964,7 +974,7 @@ void AIMGR_ReloadNavigationData()
void AIMGR_RoundStarted()
{
if (avh_botsenabled.value == 0 || !NavmeshLoaded()) { return; } // Do nothing if we're not using bots
if (!AIMGR_IsBotEnabled()) { return; } // Do nothing if we're not using bots
bHasRoundStarted = true;
@ -1038,7 +1048,12 @@ void AIMGR_ClearBotData()
void AIMGR_NewMap()
{
if (avh_botsenabled.value == 0) { return; } // Do nothing if we're not using bots
if (NavmeshLoaded())
{
UnloadNavigationData();
}
if (!AIMGR_IsBotEnabled()) { return; } // Do nothing if we're not using bots
bMapDataInitialised = false;
@ -1049,11 +1064,6 @@ void AIMGR_NewMap()
AITAC_ClearMapAIData(true);
if (NavmeshLoaded())
{
UnloadNavigationData();
}
CONFIG_ParseConfigFile();
AIMGR_BotPrecache();
@ -1063,6 +1073,21 @@ void AIMGR_NewMap()
bPlayerSpawned = false;
}
bool AIMGR_IsNavmeshLoaded()
{
return NavmeshLoaded();
}
bool AIMGR_IsBotEnabled()
{
return avh_botsenabled.value > 0 && NAV_GetNavMeshStatus() != NAVMESH_STATUS_FAILED;
}
AvHAINavMeshStatus AIMGR_GetNavMeshStatus()
{
return NAV_GetNavMeshStatus();
}
void AIMGR_LoadNavigationData()
{
// Don't reload the nav mesh if it's already loaded
@ -1072,7 +1097,7 @@ void AIMGR_LoadNavigationData()
if (!loadNavigationData(theCStrLevelName))
{
ALERT(at_console, "Failed to load navigation data for %s\n");
ALERT(at_console, "Failed to load navigation data for %s\n", theCStrLevelName);
}
}

View file

@ -68,6 +68,11 @@ int AIMGR_GetNumAIPlayersWithRoleOnTeam(AvHTeamNumber Team, AvHAIBotRole Role, A
int AIMGR_GetNumHumansOfClassOnTeam(AvHTeamNumber Team, AvHUser3 PlayerType);
bool AIMGR_IsNavmeshLoaded();
AvHAINavMeshStatus AIMGR_GetNavMeshStatus();
bool AIMGR_IsBotEnabled();
void AIMGR_LoadNavigationData();
void AIMGR_ReloadNavigationData();

View file

@ -153,7 +153,7 @@ bool AITASK_IsTaskUrgent(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
case TASK_GET_AMMO:
return (UTIL_GetPlayerPrimaryAmmoReserve(pBot->Player) == 0);
case TASK_GET_HEALTH:
return (IsPlayerMarine(pBot->Edict)) ? (pBot->Edict->v.health < 50.0f) : (GetPlayerOverallHealthPercent(pBot->Edict) < 50.0f);
return (IsPlayerMarine(pBot->Edict)) ? (pBot->Edict->v.health < 50.0f) : (GetPlayerOverallHealthPercent(pBot->Edict) < 0.5f);
case TASK_ATTACK:
case TASK_GET_WEAPON:
case TASK_GET_EQUIPMENT:
@ -978,13 +978,20 @@ bool AITASK_IsAlienGetHealthTaskStillValid(AvHAIPlayer* pBot, AvHAIPlayerTask* T
{
if (FNullEnt(Task->TaskTarget) || (Task->TaskTarget->v.deadflag != DEAD_NO)) { return false; }
if (IsEdictHive(Task->TaskTarget))
{
AvHAIHiveDefinition* HiveRef = AITAC_GetHiveFromEdict(Task->TaskTarget);
if (!HiveRef || HiveRef->Status != HIVE_STATUS_BUILT) { return false; }
}
if (IsEdictStructure(Task->TaskTarget) && !UTIL_IsBuildableStructureStillReachable(pBot, Task->TaskTarget)) { return false; }
if (IsEdictPlayer(Task->TaskTarget))
{
if (!IsPlayerGorge(Task->TaskTarget)) { return false; }
}
return (pBot->Edict->v.health < pBot->Edict->v.max_health) || (!IsPlayerSkulk(pBot->Edict) && pBot->Edict->v.armorvalue < (GetPlayerMaxArmour(pBot->Edict) * 0.7f));
return (pBot->Edict->v.health < pBot->Edict->v.max_health) || (!IsPlayerSkulk(pBot->Edict) && pBot->Edict->v.armorvalue < (GetPlayerMaxArmour(pBot->Edict) * 0.8f));
}
bool AITASK_IsAlienHealTaskStillValid(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)

View file

@ -236,6 +236,8 @@ extern cvar_t avh_botsenabled;
extern cvar_t avh_botautomode;
extern cvar_t avh_botminplayers;
extern cvar_t avh_botskill;
extern cvar_t avh_botcommandermode;
extern cvar_t avh_botdebugmode;
BOOL IsSpawnPointValid( CBaseEntity *pPlayer, CBaseEntity *pSpot );
inline int FNullEnt( CBaseEntity *ent ) { return (ent == NULL) || FNullEnt( ent->edict() ); }
@ -348,15 +350,19 @@ AvHGamerules::AvHGamerules() : mTeamA(TEAM_ONE), mTeamB(TEAM_TWO)
RegisterServerVariable(&avh_fastjp);
RegisterServerVariable(&avh_randomrfk);
RegisterServerVariable(&avh_parasiteonmap);
// AI Player cvars
RegisterServerVariable(&avh_botsenabled);
RegisterServerVariable(&avh_botautomode);
RegisterServerVariable(&avh_botminplayers);
RegisterServerVariable(&avh_botskill);
RegisterServerVariable(&avh_botdebugmode);
RegisterServerVariable(&avh_botcommandermode);
REGISTER_SERVER_FUNCTION("sv_addaiplayer", []()
{
if (avh_botsenabled.value == 0)
if (!AIMGR_IsBotEnabled())
{
ALERT(at_console, "Bots are disabled, or the navmesh could not be loaded.");
return;
}
@ -377,6 +383,12 @@ AvHGamerules::AvHGamerules() : mTeamA(TEAM_ONE), mTeamB(TEAM_TWO)
REGISTER_SERVER_FUNCTION("sv_removeaiplayer", []()
{
if (!AIMGR_IsBotEnabled())
{
ALERT(at_console, "Bots are disabled, or the navmesh could not be loaded.");
return;
}
int DesiredTeam = 0;
if (CMD_ARGC() >= 2)
@ -394,7 +406,14 @@ AvHGamerules::AvHGamerules() : mTeamA(TEAM_ONE), mTeamB(TEAM_TWO)
REGISTER_SERVER_FUNCTION("sv_reloadnavmesh", []()
{
AIMGR_ReloadNavigationData();
if (avh_botsenabled.value > 0)
{
AIMGR_ReloadNavigationData();
}
else
{
ALERT(at_console, "Bots are disabled, enable first before loading the navmesh.");
}
});
g_VoiceGameMgr.Init(&gVoiceHelper, gpGlobals->maxClients);
@ -2323,11 +2342,6 @@ void AvHGamerules::PostWorldPrecacheReset(bool inNewMap)
// Must happen after processing spawn entities
this->RecalculateMapMode();
if (avh_botsenabled.value > 0)
{
AIMGR_LoadNavigationData();
}
// Loop through all players that are playing and respawn them
bool theJustResetGameAtCountdownStart = false;
@ -3615,12 +3629,16 @@ void AvHGamerules::Think(void)
this->UpdateGameTime();
if(GET_RUN_CODE(4))
{
{
AIMGR_UpdateAIPlayerCounts();
if (avh_botsenabled.value > 0)
if (AIMGR_IsBotEnabled())
{
if (AIMGR_GetNavMeshStatus() == NAVMESH_STATUS_PENDING)
{
AIMGR_LoadNavigationData();
}
AIMGR_UpdateAIMapData();
AIMGR_UpdateAIPlayers();