diff --git a/main/source/mod/AIPlayers/AvHAICommander.cpp b/main/source/mod/AIPlayers/AvHAICommander.cpp index 18fe3edc..873e262a 100644 --- a/main/source/mod/AIPlayers/AvHAICommander.cpp +++ b/main/source/mod/AIPlayers/AvHAICommander.cpp @@ -911,17 +911,19 @@ bool AICOMM_CheckForNextBuildAction(AvHAIPlayer* pBot) StructureFilter.DeployableTeam = TeamNumber; StructureFilter.ReachabilityFlags = AI_REACHABILITY_MARINE; StructureFilter.ReachabilityTeam = TeamNumber; - StructureFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(10.0f); + StructureFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(15.0f); int NumInfantryPortals = AITAC_GetNumDeployablesNearLocation(CommChair->v.origin, &StructureFilter); if (NumInfantryPortals < 2) { - bool bSuccess = AICOMM_BuildInfantryPortal(pBot, CommChair); + bool bEnemyInBase = NumInfantryPortals > 1 && AITAC_AnyPlayerOnTeamWithLOS(AIMGR_GetEnemyTeam(TeamNumber), CommChair->v.origin, UTIL_MetresToGoldSrcUnits(10.0f)); + + bool bSuccess = !bEnemyInBase && AICOMM_BuildInfantryPortal(pBot, CommChair); return (bSuccess || pBot->Player->GetResources() <= BALANCE_VAR(kInfantryPortalCost) + 5); } - StructureFilter.DeployableTypes = STRUCTURE_MARINE_ARMOURY | STRUCTURE_MARINE_ADVARMOURY; + StructureFilter.DeployableTypes = (STRUCTURE_MARINE_ARMOURY | STRUCTURE_MARINE_ADVARMOURY); AvHAIBuildableStructure* BaseArmoury = AITAC_FindClosestDeployableToLocation(CommChair->v.origin, &StructureFilter); @@ -929,7 +931,6 @@ bool AICOMM_CheckForNextBuildAction(AvHAIPlayer* pBot) { StructureFilter.DeployableTypes = STRUCTURE_MARINE_INFANTRYPORTAL; - StructureFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(5.0f); AvHAIBuildableStructure* NearestInfantryPortal = AITAC_FindClosestDeployableToLocation(CommChair->v.origin, &StructureFilter); @@ -982,7 +983,9 @@ bool AICOMM_CheckForNextBuildAction(AvHAIPlayer* pBot) if (!vIsZero(BuildLocation)) { - bool bSuccess = AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_PHASEGATE, BuildLocation); + bool bEnemyInBase = AITAC_AnyPlayerOnTeamWithLOS(AIMGR_GetEnemyTeam(TeamNumber), BuildLocation + Vector(0.0f, 0.0f, 32.0f), UTIL_MetresToGoldSrcUnits(10.0f)); + + bool bSuccess = !bEnemyInBase && AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_PHASEGATE, BuildLocation); return (bSuccess || pBot->Player->GetResources() <= BALANCE_VAR(kPhaseGateCost) + 5); } } @@ -1017,7 +1020,9 @@ bool AICOMM_CheckForNextBuildAction(AvHAIPlayer* pBot) if (!vIsZero(BuildLocation)) { - bool bSuccess = AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_ARMSLAB, BuildLocation); + bool bEnemyInBase = AITAC_AnyPlayerOnTeamWithLOS(AIMGR_GetEnemyTeam(TeamNumber), BuildLocation + Vector(0.0f, 0.0f, 32.0f), UTIL_MetresToGoldSrcUnits(10.0f)); + + bool bSuccess = !bEnemyInBase && AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_ARMSLAB, BuildLocation); return (bSuccess || pBot->Player->GetResources() <= BALANCE_VAR(kArmsLabCost) + 5); } } @@ -1032,7 +1037,9 @@ bool AICOMM_CheckForNextBuildAction(AvHAIPlayer* pBot) if (!vIsZero(BuildLocation)) { - bool bSuccess = AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_OBSERVATORY, BuildLocation); + bool bEnemyInBase = AITAC_AnyPlayerOnTeamWithLOS(AIMGR_GetEnemyTeam(TeamNumber), BuildLocation + Vector(0.0f, 0.0f, 32.0f), UTIL_MetresToGoldSrcUnits(10.0f)); + + bool bSuccess = !bEnemyInBase && AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_OBSERVATORY, BuildLocation); return (bSuccess || pBot->Player->GetResources() <= BALANCE_VAR(kObservatoryCost) + 5); } } @@ -1096,10 +1103,10 @@ bool AICOMM_CheckForNextBuildAction(AvHAIPlayer* pBot) if (!vIsZero(BuildLocation)) { - if (AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_PROTOTYPELAB, BuildLocation)) - { - return true; - } + bool bEnemyInBase = AITAC_AnyPlayerOnTeamWithLOS(AIMGR_GetEnemyTeam(TeamNumber), BuildLocation + Vector(0.0f, 0.0f, 32.0f), UTIL_MetresToGoldSrcUnits(10.0f)); + + bool bSuccess = !bEnemyInBase && AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_PROTOTYPELAB, BuildLocation); + return (bSuccess || pBot->Player->GetResources() <= BALANCE_VAR(kPrototypeLabCost) + 5); } } @@ -1718,6 +1725,8 @@ const AvHAIResourceNode* AICOMM_GetNearestResourceNodeCapOpportunity(const AvHTe if (!AITAC_AnyPlayerOnTeamWithLOS(Team, (ResNode->Location + Vector(0.0f, 0.0f, 32.0f)), UTIL_MetresToGoldSrcUnits(5.0f))) { continue; } + if (AITAC_AnyPlayerOnTeamWithLOS(AIMGR_GetEnemyTeam(Team), (ResNode->Location + Vector(0.0f, 0.0f, 32.0f)), UTIL_MetresToGoldSrcUnits(10.0f))) { continue; } + float ThisDist = vDist2DSq(ResNode->Location, SearchLocation); if (!Result || ThisDist < MinDist) @@ -1805,12 +1814,16 @@ bool AICOMM_PerformNextSiegeHiveAction(AvHAIPlayer* pBot, const AvHAIHiveDefinit return AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_PHASEGATE, NextBuildPosition, STRUCTURE_PURPOSE_SIEGE); } + if (ExistingPG && !(ExistingPG->StructureStatusFlags & STRUCTURE_STATUS_COMPLETED)) { return false; } + if (!ExistingTF) { if (vDist2DSq(NextBuildPosition, HiveToSiege->Location) > sqrf(UTIL_MetresToGoldSrcUnits(20.0f))) { return true; } return AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_TURRETFACTORY, NextBuildPosition, STRUCTURE_PURPOSE_SIEGE); } + if (ExistingTF && !(ExistingTF->StructureStatusFlags & STRUCTURE_STATUS_COMPLETED)) { return false; } + StructureFilter.DeployableTypes = STRUCTURE_MARINE_ARMOURY | STRUCTURE_MARINE_ADVARMOURY; StructureFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(10.0f); diff --git a/main/source/mod/AIPlayers/AvHAIConstants.h b/main/source/mod/AIPlayers/AvHAIConstants.h index 878319af..b06105d2 100644 --- a/main/source/mod/AIPlayers/AvHAIConstants.h +++ b/main/source/mod/AIPlayers/AvHAIConstants.h @@ -483,6 +483,16 @@ typedef struct _BOT_SKILL } bot_skill; +typedef struct _AVH_AI_BUILD_ATTEMPT +{ + AvHAIDeployableStructureType AttemptedStructureType = STRUCTURE_NONE; + Vector AttemptedLocation = g_vecZero; + int NumAttempts = 0; + BotBuildAttemptStatus BuildStatus = BUILD_ATTEMPT_NONE; + float BuildAttemptTime = 0.0f; + AvHAIBuildableStructure* LinkedStructure = nullptr; +} AvHAIBuildAttempt; + // A bot task is a goal the bot wants to perform, such as attacking a structure, placing a structure etc. NOT USED BY COMMANDER typedef struct _AVH_AI_PLAYER_TASK { @@ -500,19 +510,9 @@ typedef struct _AVH_AI_PLAYER_TASK int BuildAttempts = 0; // How many attempts the Gorge has tried to place it, so it doesn't keep trying forever AvHMessageID Evolution = MESSAGE_NULL; // Used by TASK_EVOLVE to determine what to evolve into float TaskLength = 0.0f; // If a task has gone on longer than this time, it will be considered completed + AvHAIBuildAttempt ActiveBuildInfo; // If gorge, the current status of any recent attempt to place a structure } AvHAIPlayerTask; - -typedef struct _AVH_AI_BUILD_ATTEMPT -{ - AvHAIDeployableStructureType AttemptedStructureType = STRUCTURE_NONE; - Vector AttemptedLocation = g_vecZero; - int NumAttempts = 0; - BotBuildAttemptStatus BuildStatus = BUILD_ATTEMPT_NONE; - float BuildAttemptTime = 0.0f; - AvHAIBuildableStructure* LinkedStructure = nullptr; -} AvHAIBuildAttempt; - typedef struct _DOOR_TRIGGER { CBaseEntity* Entity = nullptr; @@ -727,8 +727,6 @@ typedef struct AVH_AI_PLAYER nav_status BotNavInfo; // Bot's movement information, their current path, where in the path they are etc. - AvHAIBuildAttempt ActiveBuildInfo; // If gorge, the current status of any recent attempt to place a structure - vector ActiveRequests; vector ActiveOrders; diff --git a/main/source/mod/AIPlayers/AvHAINavigation.cpp b/main/source/mod/AIPlayers/AvHAINavigation.cpp index 760efee2..98132db1 100644 --- a/main/source/mod/AIPlayers/AvHAINavigation.cpp +++ b/main/source/mod/AIPlayers/AvHAINavigation.cpp @@ -1838,7 +1838,8 @@ dtStatus FindPathClosestToPoint(AvHAIPlayer* pBot, const BotMoveStyle MoveStyle, if (CurrFlags == SAMPLE_POLYFLAGS_WALLCLIMB || CurrFlags == SAMPLE_POLYFLAGS_LADDER) { int HullNum = GetPlayerHullIndex(pBot->Edict, false); - float NewRequiredZ = UTIL_FindZHeightForWallClimb(path.back().Location, NextPathNode.Location, HullNum); + Vector FromLocation = (path.size() > 0) ? path.back().Location : pBot->CurrentFloorPosition; + float NewRequiredZ = UTIL_FindZHeightForWallClimb(FromLocation, NextPathNode.Location, HullNum); NextPathNode.requiredZ = fmaxf(NewRequiredZ, NextPathNode.Location.z); if (CurrFlags == SAMPLE_POLYFLAGS_LADDER) @@ -3054,27 +3055,38 @@ void GroundMove(AvHAIPlayer* pBot, const Vector StartPoint, const Vector EndPoin void FallMove(AvHAIPlayer* pBot, const Vector StartPoint, const Vector EndPoint) { - Vector vForward = UTIL_GetVectorNormal2D(EndPoint - pBot->Edict->v.origin); + Vector vBotOrientation = UTIL_GetVectorNormal2D(EndPoint - pBot->Edict->v.origin); + Vector vForward = UTIL_GetVectorNormal2D(EndPoint - StartPoint); - if (vIsZero(vForward)) + if (pBot->BotNavInfo.IsOnGround) { - vForward = UTIL_GetVectorNormal2D(EndPoint - StartPoint); + if (vDist2DSq(pBot->Edict->v.origin, EndPoint) > sqrf(GetPlayerRadius(pBot->Player))) + { + pBot->desiredMovementDir = vBotOrientation; + } + else + { + pBot->desiredMovementDir = vForward; + } + + bool bCanDuck = (IsPlayerMarine(pBot->Edict) || IsPlayerFade(pBot->Edict) || IsPlayerOnos(pBot->Edict)); + + if (!bCanDuck) { return; } + + Vector HeadLocation = GetPlayerTopOfCollisionHull(pBot->Edict, false); + + if (!UTIL_QuickTrace(pBot->Edict, HeadLocation, (HeadLocation + (pBot->desiredMovementDir * 50.0f)))) + { + pBot->Button |= IN_DUCK; + } + } + else + { + pBot->desiredMovementDir = vBotOrientation; } - pBot->desiredMovementDir = vForward; - if (UTIL_PointIsDirectlyReachable(pBot, EndPoint)) { return; } - bool bCanDuck = (IsPlayerMarine(pBot->Edict) || IsPlayerFade(pBot->Edict) || IsPlayerOnos(pBot->Edict)); - - if (!bCanDuck) { return; } - - Vector HeadLocation = GetPlayerTopOfCollisionHull(pBot->Edict, false); - - if (!UTIL_QuickTrace(pBot->Edict, HeadLocation, (HeadLocation + (pBot->desiredMovementDir * 50.0f)))) - { - pBot->Button |= IN_DUCK; - } } void StructureBlockedMove(AvHAIPlayer* pBot, const Vector StartPoint, const Vector EndPoint) @@ -3858,7 +3870,7 @@ bool IsBotOffPath(const AvHAIPlayer* pBot) Vector vForward = UTIL_GetVectorNormal2D(MoveTo - MoveFrom); - Vector PointOnPath = vClosestPointOnLine2D(MoveFrom, MoveTo, pBot->CurrentFloorPosition); + Vector PointOnPath = vClosestPointOnLine2D(MoveFrom, MoveTo, pBot->Edict->v.origin); if (pBot->BotNavInfo.CurrentPathPoint->flag == SAMPLE_POLYFLAGS_WALLCLIMB) { @@ -3871,16 +3883,7 @@ bool IsBotOffPath(const AvHAIPlayer* pBot) if (pBot->BotNavInfo.CurrentPathPoint->flag == SAMPLE_POLYFLAGS_WALK) { - if (!UTIL_PointIsDirectlyReachable(pBot->CurrentFloorPosition, MoveTo)) - { - Vector TraceEnd = MoveTo; - TraceEnd.z = pBot->Edict->v.origin.z; - - if (!UTIL_QuickHullTrace(pBot->Edict, pBot->Edict->v.origin, TraceEnd, GetPlayerHullIndex(pBot->Edict))) - { - return true; - } - } + if (vDist2DSq(pBot->Edict->v.origin, PointOnPath) > sqrf(100.0f)) { return true; } bool bAtMoveStart = vEquals(PointOnPath, MoveFrom, 2.0f); @@ -4964,7 +4967,7 @@ bool AbortCurrentMove(AvHAIPlayer* pBot, const Vector NewDestination) if (flag == SAMPLE_POLYFLAGS_LIFT) { - if (pBot->BotNavInfo.MovementTask.TaskType != MOVE_TASK_NONE) + if (pBot->BotNavInfo.MovementTask.TaskType != MOVE_TASK_NONE && !vEquals(NewDestination, pBot->BotNavInfo.MovementTask.TaskLocation)) { if (NAV_IsMovementTaskStillValid(pBot)) { @@ -5132,7 +5135,7 @@ void UpdateBotStuck(AvHAIPlayer* pBot) if (!vIsZero(pBot->desiredMovementDir)) { - //BotJump(pBot); + BotJump(pBot); if (!IsPlayerSkulk(pBot->Edict)) { diff --git a/main/source/mod/AIPlayers/AvHAIPlayer.cpp b/main/source/mod/AIPlayers/AvHAIPlayer.cpp index d67cd804..5abd041c 100644 --- a/main/source/mod/AIPlayers/AvHAIPlayer.cpp +++ b/main/source/mod/AIPlayers/AvHAIPlayer.cpp @@ -1641,27 +1641,49 @@ void StartNewBotFrame(AvHAIPlayer* pBot) } // If we tried placing a building as gorge, and nothing has appeared within the expected time, then mark it as a failed attempt. - if (pBot->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_PENDING) + if (pBot->PrimaryBotTask.ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_PENDING) { - if (pBot->ActiveBuildInfo.AttemptedStructureType == STRUCTURE_ALIEN_HIVE) + if (pBot->PrimaryBotTask.ActiveBuildInfo.AttemptedStructureType == STRUCTURE_ALIEN_HIVE) { // Give a 3-second grace period to check if the hive placement was successful - if ((gpGlobals->time - pBot->ActiveBuildInfo.BuildAttemptTime) > 3.0f) + if ((gpGlobals->time - pBot->PrimaryBotTask.ActiveBuildInfo.BuildAttemptTime) > 3.0f) { - const AvHAIHiveDefinition* NearestHive = AITAC_GetHiveNearestLocation(pBot->ActiveBuildInfo.AttemptedLocation); + const AvHAIHiveDefinition* NearestHive = AITAC_GetHiveNearestLocation(pBot->PrimaryBotTask.ActiveBuildInfo.AttemptedLocation); - pBot->ActiveBuildInfo.BuildStatus = (NearestHive->Status != HIVE_STATUS_UNBUILT) ? BUILD_ATTEMPT_SUCCESS : BUILD_ATTEMPT_FAILED; + pBot->PrimaryBotTask.ActiveBuildInfo.BuildStatus = (NearestHive->Status != HIVE_STATUS_UNBUILT) ? BUILD_ATTEMPT_SUCCESS : BUILD_ATTEMPT_FAILED; } } else { // All other structures should appear near-instantly - if ((gpGlobals->time - pBot->ActiveBuildInfo.BuildAttemptTime) > 0.5f) + if ((gpGlobals->time - pBot->PrimaryBotTask.ActiveBuildInfo.BuildAttemptTime) > 0.5f) { - pBot->ActiveBuildInfo.BuildStatus = BUILD_ATTEMPT_FAILED; + pBot->PrimaryBotTask.ActiveBuildInfo.BuildStatus = BUILD_ATTEMPT_FAILED; } } + } + // If we tried placing a building as gorge, and nothing has appeared within the expected time, then mark it as a failed attempt. + if (pBot->SecondaryBotTask.ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_PENDING) + { + if (pBot->SecondaryBotTask.ActiveBuildInfo.AttemptedStructureType == STRUCTURE_ALIEN_HIVE) + { + // Give a 3-second grace period to check if the hive placement was successful + if ((gpGlobals->time - pBot->SecondaryBotTask.ActiveBuildInfo.BuildAttemptTime) > 3.0f) + { + const AvHAIHiveDefinition* NearestHive = AITAC_GetHiveNearestLocation(pBot->SecondaryBotTask.ActiveBuildInfo.AttemptedLocation); + + pBot->SecondaryBotTask.ActiveBuildInfo.BuildStatus = (NearestHive->Status != HIVE_STATUS_UNBUILT) ? BUILD_ATTEMPT_SUCCESS : BUILD_ATTEMPT_FAILED; + } + } + else + { + // All other structures should appear near-instantly + if ((gpGlobals->time - pBot->SecondaryBotTask.ActiveBuildInfo.BuildAttemptTime) > 0.5f) + { + pBot->SecondaryBotTask.ActiveBuildInfo.BuildStatus = BUILD_ATTEMPT_FAILED; + } + } } } @@ -2553,6 +2575,11 @@ void AIPlayerNSMarineThink(AvHAIPlayer* pBot) return; } + if (pBot->CurrentEnemy > -1) + { + if (MarineCombatThink(pBot)) { return; } + } + if (!pBot->CurrentTask) { pBot->CurrentTask = &pBot->PrimaryBotTask; } if (gpGlobals->time >= pBot->BotNextTaskEvaluationTime) @@ -2568,11 +2595,6 @@ void AIPlayerNSMarineThink(AvHAIPlayer* pBot) pBot->CurrentTask = AIPlayerGetNextTask(pBot); - if (pBot->CurrentEnemy > -1) - { - if (MarineCombatThink(pBot)) { return; } - } - if (pBot->CurrentTask && pBot->CurrentTask->TaskType != TASK_NONE) { BotProgressTask(pBot, pBot->CurrentTask); @@ -2983,6 +3005,8 @@ bool RegularMarineCombatThink(AvHAIPlayer* pBot) BotShootTarget(pBot, DesiredCombatWeapon, CurrentEnemy); } + + return true; } return false; @@ -3732,7 +3756,7 @@ bool AIPlayerMustFinishCurrentTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) { AvHTeamNumber BotTeam = pBot->Player->GetTeam(); - if (pBot->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_PENDING) { return true; } + if (Task->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_PENDING) { return true; } // If we're already capping a node, are at the node and there is an unfinished tower on there, then finish the job and don't move on yet if (Task->TaskType == TASK_CAP_RESNODE) @@ -3773,7 +3797,15 @@ void AIPlayerNSAlienThink(AvHAIPlayer* pBot) if (AITAC_ShouldBotBuildHive(pBot, &HiveToBuild)) { - BotAlienBuildHive(pBot, HiveToBuild); + if (pBot->PrimaryBotTask.TaskType != TASK_BUILD || pBot->PrimaryBotTask.StructureType != STRUCTURE_ALIEN_HIVE) + { + pBot->PrimaryBotTask.TaskType = TASK_BUILD; + pBot->PrimaryBotTask.StructureType = STRUCTURE_ALIEN_HIVE; + char msg[64]; + sprintf(msg, "I'm going to drop the hive at %s", HiveToBuild->HiveName); + BotSay(pBot, true, 1.0f, msg); + } + BotAlienBuildHive(pBot, &pBot->PrimaryBotTask, HiveToBuild); return; } @@ -3858,6 +3890,16 @@ void AIPlayerThink(AvHAIPlayer* pBot) bool bBreak = true; AIDEBUG_DrawBotPath(pBot); + + if (pBot->BotNavInfo.CurrentPathPoint != pBot->BotNavInfo.CurrentPath.end()) + { + UTIL_DrawLine(INDEXENT(1), pBot->Edict->v.origin, pBot->BotNavInfo.CurrentPathPoint->Location, 0, 255, 255); + } + } + + if (pBot->PrimaryBotTask.TaskType == TASK_BUILD) + { + UTIL_DrawLine(INDEXENT(1), pBot->Edict->v.origin, pBot->PrimaryBotTask.TaskLocation, 0, 255, 255); } switch (GetGameRules()->GetMapMode()) @@ -4261,7 +4303,7 @@ void AIPlayerSetAlienBuilderPrimaryTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task if (!TowerToReinforce || ThisDist < MinDist) { TowerToReinforce = ThisResTower->edict; - MaxDist = ThisDist; + MinDist = ThisDist; } } } diff --git a/main/source/mod/AIPlayers/AvHAIPlayerManager.cpp b/main/source/mod/AIPlayers/AvHAIPlayerManager.cpp index f2b29e81..182f5dd5 100644 --- a/main/source/mod/AIPlayers/AvHAIPlayerManager.cpp +++ b/main/source/mod/AIPlayers/AvHAIPlayerManager.cpp @@ -28,6 +28,7 @@ int BotNameIndex = 0; float AIStartedTime = 0.0f; // Used to give 5-second grace period before adding bots bool bHasRoundStarted = false; +bool bMapDataInitialised = false; extern int m_spriteTexture; @@ -622,7 +623,7 @@ void AIMGR_UpdateAIPlayers() UpdateBotChat(bot); - DroneThink(bot); + AIPlayerThink(bot); EndBotFrame(bot); @@ -837,26 +838,19 @@ void AIMGR_ResetRound() UTIL_PopulateDoors(); UTIL_PopulateWeldableObstacles(); - ALERT(at_console, "AI Manager Reset Round\n"); - - bHasRoundStarted = false; -} - -void AIMGR_RoundStarted() -{ - AITAC_PopulateResourceNodes(); - AITAC_PopulateHiveData(); - - AITAC_RefreshResourceNodes(); - - AITAC_RefreshHiveData(); - UTIL_UpdateDoors(true); UTIL_UpdateTileCache(); + ALERT(at_console, "AI Manager Reset Round\n"); + + bHasRoundStarted = false; + bMapDataInitialised = true; +} + +void AIMGR_RoundStarted() +{ bHasRoundStarted = true; - } void AIMGR_ClearBotData() @@ -891,12 +885,16 @@ void AIMGR_NewMap() { if (avh_botsenabled.value == 0) { return; } // Do nothing if we're not using bots + bMapDataInitialised = false; + ActiveAIPlayers.clear(); AIStartedTime = gpGlobals->time; LastAIPlayerCountUpdate = 0.0f; ALERT(at_console, "AI Manager New Map\n"); + AITAC_ClearMapAIData(); + if (NavmeshLoaded()) { UnloadNavigationData(); @@ -1025,9 +1023,12 @@ vector AIMGR_GetNonAIPlayersOnTeam(AvHTeamNumber Team) void AIMGR_UpdateAIMapData() { - AITAC_UpdateMapAIData(); - UTIL_UpdateTileCache(); - AITAC_CheckNavMeshModified(); + if (bMapDataInitialised && gpGlobals->time - AIStartedTime > AI_GRACE_PERIOD) + { + AITAC_UpdateMapAIData(); + UTIL_UpdateTileCache(); + AITAC_CheckNavMeshModified(); + } } void AIMGR_BotPrecache() diff --git a/main/source/mod/AIPlayers/AvHAITactical.cpp b/main/source/mod/AIPlayers/AvHAITactical.cpp index 0fc3f296..288b5ef9 100644 --- a/main/source/mod/AIPlayers/AvHAITactical.cpp +++ b/main/source/mod/AIPlayers/AvHAITactical.cpp @@ -1389,6 +1389,7 @@ AvHAIResourceNode* AITAC_GetRandomResourceNode(AvHTeamNumber SearchingTeam, cons void AITAC_UpdateMapAIData() { + AITAC_RefreshHiveData(); UTIL_UpdateDoors(false); @@ -2220,15 +2221,25 @@ void AITAC_LinkStructureToPlayer(AvHAIBuildableStructure* NewStructure) { AvHAIPlayer* Player = (*it); - if (Player->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_PENDING && Player->ActiveBuildInfo.AttemptedStructureType == NewStructure->StructureType) + if (Player->PrimaryBotTask.ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_PENDING && Player->PrimaryBotTask.ActiveBuildInfo.AttemptedStructureType == NewStructure->StructureType) { - if (vDist2DSq(NewStructure->Location, Player->ActiveBuildInfo.AttemptedLocation) < sqrf(UTIL_MetresToGoldSrcUnits(2.0f))) + if (vDist2DSq(NewStructure->Location, Player->PrimaryBotTask.ActiveBuildInfo.AttemptedLocation) < sqrf(UTIL_MetresToGoldSrcUnits(2.0f))) { - Player->ActiveBuildInfo.BuildStatus = BUILD_ATTEMPT_SUCCESS; - Player->ActiveBuildInfo.LinkedStructure = NewStructure; + Player->PrimaryBotTask.ActiveBuildInfo.BuildStatus = BUILD_ATTEMPT_SUCCESS; + Player->PrimaryBotTask.ActiveBuildInfo.LinkedStructure = NewStructure; } } + + if (Player->SecondaryBotTask.ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_PENDING && Player->SecondaryBotTask.ActiveBuildInfo.AttemptedStructureType == NewStructure->StructureType) + { + if (vDist2DSq(NewStructure->Location, Player->SecondaryBotTask.ActiveBuildInfo.AttemptedLocation) < sqrf(UTIL_MetresToGoldSrcUnits(2.0f))) + { + Player->SecondaryBotTask.ActiveBuildInfo.BuildStatus = BUILD_ATTEMPT_SUCCESS; + Player->SecondaryBotTask.ActiveBuildInfo.LinkedStructure = NewStructure; + } + + } } } @@ -2996,6 +3007,32 @@ int AITAC_GetNumPlayersOfTeamInArea(const AvHTeamNumber Team, const Vector Searc } +bool AITAC_AnyPlayersOfTeamInArea(const AvHTeamNumber Team, const Vector SearchLocation, const float SearchRadius, const bool bConsiderPhaseDist, const edict_t* IgnorePlayer, const AvHUser3 IgnoreClass) +{ + float MaxRadiusSq = sqrf(SearchRadius); + + for (int i = 1; i <= gpGlobals->maxClients; i++) + { + edict_t* PlayerEdict = INDEXENT(i); + + if (FNullEnt(PlayerEdict) || PlayerEdict->free || PlayerEdict == IgnorePlayer) { continue; } + + AvHPlayer* PlayerRef = dynamic_cast(CBaseEntity::Instance(PlayerEdict)); + + if (PlayerRef != nullptr && GetPlayerActiveClass(PlayerRef) != IgnoreClass && (Team == TEAM_IND || PlayerRef->GetTeam() == Team) && IsPlayerActiveInGame(PlayerEdict)) + { + float Dist = (bConsiderPhaseDist) ? sqrf(AITAC_GetPhaseDistanceBetweenPoints(PlayerEdict->v.origin, SearchLocation)) : vDist2DSq(PlayerEdict->v.origin, SearchLocation); + + if (Dist <= MaxRadiusSq) + { + return true; + } + } + } + + return false; +} + int AITAC_GetNumPlayersOnTeamOfClass(const AvHTeamNumber Team, const AvHUser3 SearchClass, const edict_t* IgnorePlayer) { int Result = 0; diff --git a/main/source/mod/AIPlayers/AvHAITactical.h b/main/source/mod/AIPlayers/AvHAITactical.h index 51b60fbe..dde57dca 100644 --- a/main/source/mod/AIPlayers/AvHAITactical.h +++ b/main/source/mod/AIPlayers/AvHAITactical.h @@ -122,6 +122,7 @@ AvHAIWeapon UTIL_GetWeaponTypeFromEdict(const edict_t* ItemEdict); int AITAC_GetNumActivePlayersOnTeam(const AvHTeamNumber Team); int AITAC_GetNumPlayersOfTeamInArea(const AvHTeamNumber Team, const Vector SearchLocation, const float SearchRadius, const bool bConsiderPhaseDist, const edict_t* IgnorePlayer, const AvHUser3 IgnoreClass); +bool AITAC_AnyPlayersOfTeamInArea(const AvHTeamNumber Team, const Vector SearchLocation, const float SearchRadius, const bool bConsiderPhaseDist, const edict_t* IgnorePlayer, const AvHUser3 IgnoreClass); vector AITAC_GetAllPlayersOfTeamInArea(const AvHTeamNumber Team, const Vector SearchLocation, const float SearchRadius, const bool bConsiderPhaseDist, const edict_t* IgnorePlayer, const AvHUser3 IgnoreClass); int AITAC_GetNumPlayersOfTeamAndClassInArea(const AvHTeamNumber Team, const Vector SearchLocation, const float SearchRadius, const bool bConsiderPhaseDist, const edict_t* IgnorePlayer, const AvHUser3 SearchClass); int AITAC_GetNumPlayersOnTeamOfClass(const AvHTeamNumber Team, const AvHUser3 SearchClass, const edict_t* IgnorePlayer); diff --git a/main/source/mod/AIPlayers/AvHAITask.cpp b/main/source/mod/AIPlayers/AvHAITask.cpp index 4fbead69..d40657f0 100644 --- a/main/source/mod/AIPlayers/AvHAITask.cpp +++ b/main/source/mod/AIPlayers/AvHAITask.cpp @@ -137,7 +137,7 @@ void AITASK_ClearBotTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) Task->BuildAttempts = 0; Task->StructureType = STRUCTURE_NONE; - memset(&pBot->ActiveBuildInfo, 0, sizeof(AvHAIBuildAttempt)); + memset(&Task->ActiveBuildInfo, 0, sizeof(AvHAIBuildAttempt)); } bool AITASK_IsTaskUrgent(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) @@ -585,11 +585,11 @@ bool AITASK_IsAlienBuildTaskStillValid(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) if (Task->StructureType == STRUCTURE_NONE) { return false; } - if (pBot->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_PENDING) { return true; } + if (Task->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_PENDING) { return true; } - if (pBot->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_FAILED && pBot->ActiveBuildInfo.NumAttempts >= 3) { return false; } + if (Task->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_FAILED && Task->ActiveBuildInfo.NumAttempts >= 3) { return false; } - if (pBot->ActiveBuildInfo.LinkedStructure && (UTIL_StructureIsFullyBuilt(pBot->ActiveBuildInfo.LinkedStructure->edict) || !UTIL_IsBuildableStructureStillReachable(pBot, pBot->ActiveBuildInfo.LinkedStructure->edict))) { return false; } + if (Task->ActiveBuildInfo.LinkedStructure && (UTIL_StructureIsFullyBuilt(Task->ActiveBuildInfo.LinkedStructure->edict) || !UTIL_IsBuildableStructureStillReachable(pBot, Task->ActiveBuildInfo.LinkedStructure->edict))) { return false; } if (Task->StructureType == STRUCTURE_ALIEN_HIVE) { @@ -1129,14 +1129,14 @@ void BotProgressPickupTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) void BotProgressMineStructureTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) { - if (pBot->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_PENDING) + if (Task->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_PENDING) { return; } - if (pBot->ActiveBuildInfo.BuildStatus != BUILD_ATTEMPT_NONE) + if (Task->ActiveBuildInfo.BuildStatus != BUILD_ATTEMPT_NONE) { - if (pBot->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_FAILED) + if (Task->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_FAILED) { float Size = fmaxf(Task->TaskTarget->v.size.x, Task->TaskTarget->v.size.y); Size += 8.0f; @@ -1147,7 +1147,7 @@ void BotProgressMineStructureTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) Task->TaskLocation = ZERO_VECTOR; } - pBot->ActiveBuildInfo.BuildStatus = BUILD_ATTEMPT_NONE; + Task->ActiveBuildInfo.BuildStatus = BUILD_ATTEMPT_NONE; } if (vIsZero(Task->TaskLocation)) @@ -1184,11 +1184,11 @@ void BotProgressMineStructureTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) if (LookDot > 0.95f) { pBot->Button |= IN_ATTACK; - pBot->ActiveBuildInfo.AttemptedLocation = Task->TaskLocation; - pBot->ActiveBuildInfo.BuildStatus = BUILD_ATTEMPT_PENDING; - pBot->ActiveBuildInfo.BuildAttemptTime = gpGlobals->time; - pBot->ActiveBuildInfo.AttemptedStructureType = STRUCTURE_MARINE_DEPLOYEDMINE; - pBot->ActiveBuildInfo.NumAttempts++; + Task->ActiveBuildInfo.AttemptedLocation = Task->TaskLocation; + Task->ActiveBuildInfo.BuildStatus = BUILD_ATTEMPT_PENDING; + Task->ActiveBuildInfo.BuildAttemptTime = gpGlobals->time; + Task->ActiveBuildInfo.AttemptedStructureType = STRUCTURE_MARINE_DEPLOYEDMINE; + Task->ActiveBuildInfo.NumAttempts++; } } } @@ -1199,13 +1199,13 @@ void BotProgressReinforceStructureTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) { if (FNullEnt(Task->TaskTarget)) { return; } - if (pBot->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_PENDING) { return; } + if (Task->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_PENDING) { return; } // We had a go, whether it succeeded or not we should try a new location - if (pBot->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_FAILED || pBot->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_SUCCESS) + if (Task->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_FAILED || Task->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_SUCCESS) { Task->TaskLocation = ZERO_VECTOR; - pBot->ActiveBuildInfo.BuildStatus = BUILD_ATTEMPT_NONE; + Task->ActiveBuildInfo.BuildStatus = BUILD_ATTEMPT_NONE; } AvHTeamNumber BotTeam = pBot->Player->GetTeam(); @@ -1312,7 +1312,7 @@ void BotProgressReinforceStructureTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) if (pBot->Player->GetResources() >= ResourceCost) { - BotAlienPlaceChamber(pBot, Task->TaskLocation, NextStructure); + BotAlienPlaceChamber(pBot, Task, NextStructure); return; } } @@ -1872,7 +1872,7 @@ void AlienProgressHealTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) void AlienProgressBuildHiveTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) { - if (pBot->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_PENDING) + if (Task->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_PENDING) { return; } @@ -1899,13 +1899,13 @@ void AlienProgressBuildHiveTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) return; } - BotAlienBuildHive(pBot, Hive); + BotAlienBuildHive(pBot, Task, Hive); } void AlienProgressBuildTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) { // We tried and failed to place the structure - if (pBot->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_PENDING) + if (Task->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_PENDING) { return; } @@ -1916,9 +1916,9 @@ void AlienProgressBuildTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) return; } - if (pBot->ActiveBuildInfo.LinkedStructure) + if (Task->ActiveBuildInfo.LinkedStructure) { - edict_t* LinkedEdict = pBot->ActiveBuildInfo.LinkedStructure->edict; + edict_t* LinkedEdict = Task->ActiveBuildInfo.LinkedStructure->edict; if (UTIL_StructureIsFullyBuilt(LinkedEdict)) { return; } @@ -1938,10 +1938,10 @@ void AlienProgressBuildTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) } // We tried and failed to place the structure - if (pBot->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_FAILED) + if (Task->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_FAILED) { Task->TaskLocation = UTIL_GetRandomPointOnNavmeshInRadius(BaseNavProfiles[GORGE_BASE_NAV_PROFILE], Task->TaskLocation, UTIL_MetresToGoldSrcUnits(2.0f)); - pBot->ActiveBuildInfo.BuildStatus = BUILD_ATTEMPT_NONE; + Task->ActiveBuildInfo.BuildStatus = BUILD_ATTEMPT_NONE; } int ResRequired = UTIL_GetCostOfStructureType(Task->StructureType); @@ -1980,34 +1980,35 @@ void AlienProgressBuildTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) return; } - BotAlienPlaceChamber(pBot, Task->TaskLocation, Task->StructureType); + BotAlienPlaceChamber(pBot, Task, Task->StructureType); } -void BotAlienPlaceChamber(AvHAIPlayer* pBot, Vector Location, AvHAIDeployableStructureType DesiredStructure) +void BotAlienPlaceChamber(AvHAIPlayer* pBot, AvHAIPlayerTask* Task, AvHAIDeployableStructureType DesiredStructure) { - if (vIsZero(Location) || DesiredStructure == STRUCTURE_NONE) { return; } + if (vIsZero(Task->TaskLocation) || DesiredStructure == STRUCTURE_NONE) { return; } - if (pBot->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_PENDING) { return; } - float DistFromBuildLocation = vDist2DSq(pBot->Edict->v.origin, Location); + if (Task->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_PENDING) { return; } + + float DistFromBuildLocation = vDist2DSq(pBot->Edict->v.origin, Task->TaskLocation); if (DistFromBuildLocation > sqrf(UTIL_MetresToGoldSrcUnits(1.0f))) { - MoveTo(pBot, Location, MOVESTYLE_NORMAL); + MoveTo(pBot, Task->TaskLocation, MOVESTYLE_NORMAL); return; } if (DistFromBuildLocation < sqrf(UTIL_MetresToGoldSrcUnits(0.5f))) { - BotLookAt(pBot, Location); - Vector Orientation = UTIL_GetVectorNormal2D(pBot->Edict->v.origin - Location); - Vector NewMoveLoc = Location + (Orientation * UTIL_MetresToGoldSrcUnits(2.0f)); + BotLookAt(pBot, Task->TaskLocation); + Vector Orientation = UTIL_GetVectorNormal2D(pBot->Edict->v.origin - Task->TaskLocation); + Vector NewMoveLoc = Task->TaskLocation + (Orientation * UTIL_MetresToGoldSrcUnits(2.0f)); MoveToWithoutNav(pBot, NewMoveLoc); return; } - Vector LookLocation = Location; + Vector LookLocation = Task->TaskLocation; LookLocation.z += 10.0f; BotLookAt(pBot, LookLocation); @@ -2035,15 +2036,15 @@ void BotAlienPlaceChamber(AvHAIPlayer* pBot, Vector Location, AvHAIDeployableStr if (LookDot > 0.9f) { pBot->Impulse = UTIL_StructureTypeToImpulseCommand(DesiredStructure); - RegisterBotAlienBuildAttempt(pBot, Location, DesiredStructure); + RegisterBotAlienBuildAttempt(pBot, Task, Task->TaskLocation, DesiredStructure); } } -void BotAlienBuildResTower(AvHAIPlayer* pBot, const AvHAIResourceNode* NodeToCap) +void BotAlienBuildResTower(AvHAIPlayer* pBot, AvHAIPlayerTask* Task, const AvHAIResourceNode* NodeToCap) { if (NodeToCap->bIsOccupied) { return; } - if (pBot->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_PENDING) { return; } + if (Task->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_PENDING) { return; } float CurrDist = vDist2DSq(pBot->CurrentFloorPosition, NodeToCap->Location); @@ -2090,17 +2091,17 @@ void BotAlienBuildResTower(AvHAIPlayer* pBot, const AvHAIResourceNode* NodeToCap if (LookDot > 0.9f) { pBot->Impulse = UTIL_StructureTypeToImpulseCommand(STRUCTURE_ALIEN_RESTOWER); - RegisterBotAlienBuildAttempt(pBot, NodeToCap->Location, STRUCTURE_ALIEN_RESTOWER); + RegisterBotAlienBuildAttempt(pBot, Task, NodeToCap->Location, STRUCTURE_ALIEN_RESTOWER); } } -void BotAlienBuildHive(AvHAIPlayer* pBot, const AvHAIHiveDefinition* HiveToBuild) +void BotAlienBuildHive(AvHAIPlayer* pBot, AvHAIPlayerTask* Task, const AvHAIHiveDefinition* HiveToBuild) { // Do nothing if the hive is already built / under construction if (HiveToBuild->Status != HIVE_STATUS_UNBUILT) { return; } - if (pBot->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_PENDING) { return; } + if (Task->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_PENDING) { return; } if (vDist2DSq(pBot->Edict->v.origin, HiveToBuild->Location) > sqrf(UTIL_MetresToGoldSrcUnits(7.5f))) { @@ -2139,7 +2140,7 @@ void BotAlienBuildHive(AvHAIPlayer* pBot, const AvHAIHiveDefinition* HiveToBuild } pBot->Impulse = UTIL_StructureTypeToImpulseCommand(STRUCTURE_ALIEN_HIVE); - RegisterBotAlienBuildAttempt(pBot, HiveToBuild->Location, STRUCTURE_ALIEN_HIVE); + RegisterBotAlienBuildAttempt(pBot, Task, HiveToBuild->Location, STRUCTURE_ALIEN_HIVE); } } @@ -2170,14 +2171,14 @@ void BotAlienHealTarget(AvHAIPlayer* pBot, edict_t* HealTarget) } -void RegisterBotAlienBuildAttempt(AvHAIPlayer* pBot, Vector PlacementLocation, AvHAIDeployableStructureType DesiredStructure) +void RegisterBotAlienBuildAttempt(AvHAIPlayer* pBot, AvHAIPlayerTask* Task, Vector PlacementLocation, AvHAIDeployableStructureType DesiredStructure) { - pBot->ActiveBuildInfo.AttemptedLocation = PlacementLocation; - pBot->ActiveBuildInfo.BuildAttemptTime = gpGlobals->time; - pBot->ActiveBuildInfo.LinkedStructure = nullptr; - pBot->ActiveBuildInfo.NumAttempts++; - pBot->ActiveBuildInfo.AttemptedStructureType = DesiredStructure; - pBot->ActiveBuildInfo.BuildStatus = BUILD_ATTEMPT_PENDING; + Task->ActiveBuildInfo.AttemptedLocation = PlacementLocation; + Task->ActiveBuildInfo.BuildAttemptTime = gpGlobals->time; + Task->ActiveBuildInfo.LinkedStructure = nullptr; + Task->ActiveBuildInfo.NumAttempts++; + Task->ActiveBuildInfo.AttemptedStructureType = DesiredStructure; + Task->ActiveBuildInfo.BuildStatus = BUILD_ATTEMPT_PENDING; } void AlienProgressCapResNodeTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) @@ -2252,7 +2253,7 @@ void AlienProgressCapResNodeTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) // We have enough resources to place the tower (includes cost of evolving to gorge if necessary) if (pBot->Player->GetResources() >= NumResourcesRequired) { - BotAlienBuildResTower(pBot, ResNodeIndex); + BotAlienBuildResTower(pBot, Task, ResNodeIndex); return; } } diff --git a/main/source/mod/AIPlayers/AvHAITask.h b/main/source/mod/AIPlayers/AvHAITask.h index c49f5027..04d52d19 100644 --- a/main/source/mod/AIPlayers/AvHAITask.h +++ b/main/source/mod/AIPlayers/AvHAITask.h @@ -109,11 +109,11 @@ AvHAIPlayer* GetFirstBotWithReinforceTask(AvHTeamNumber Team, edict_t* Reinforce void UTIL_ClearGuardInfo(AvHAIPlayer* pBot); -void BotAlienPlaceChamber(AvHAIPlayer* pBot, Vector Location, AvHAIDeployableStructureType DesiredStructure); -void BotAlienBuildHive(AvHAIPlayer* pBot, const AvHAIHiveDefinition* HiveToBuild); -void BotAlienBuildResTower(AvHAIPlayer* pBot, const AvHAIResourceNode* NodeToCap); +void BotAlienPlaceChamber(AvHAIPlayer* pBot, AvHAIPlayerTask* Task, AvHAIDeployableStructureType DesiredStructure); +void BotAlienBuildHive(AvHAIPlayer* pBot, AvHAIPlayerTask* Task, const AvHAIHiveDefinition* HiveToBuild); +void BotAlienBuildResTower(AvHAIPlayer* pBot, AvHAIPlayerTask* Task, const AvHAIResourceNode* NodeToCap); void BotAlienHealTarget(AvHAIPlayer* pBot, edict_t* HealTarget); -void RegisterBotAlienBuildAttempt(AvHAIPlayer* pBot, Vector PlacementLocation, AvHAIDeployableStructureType DesiredStructure); +void RegisterBotAlienBuildAttempt(AvHAIPlayer* pBot, AvHAIPlayerTask* Task, Vector PlacementLocation, AvHAIDeployableStructureType DesiredStructure); #endif \ No newline at end of file diff --git a/main/source/mod/AvHGamerules.cpp b/main/source/mod/AvHGamerules.cpp index b2223586..8fd83a70 100644 --- a/main/source/mod/AvHGamerules.cpp +++ b/main/source/mod/AvHGamerules.cpp @@ -3609,10 +3609,7 @@ void AvHGamerules::Think(void) if (avh_botsenabled.value > 0) { - if (this->GetGameStarted()) - { - AIMGR_UpdateAIMapData(); - } + AIMGR_UpdateAIMapData(); AIMGR_UpdateAIPlayers(); }