diff --git a/main/source/mod/AvHAICommander.cpp b/main/source/mod/AvHAICommander.cpp index 7c6cd053..db1e96f7 100644 --- a/main/source/mod/AvHAICommander.cpp +++ b/main/source/mod/AvHAICommander.cpp @@ -4215,7 +4215,7 @@ void AICOMM_DeployBases(AvHAIPlayer* pBot) { // Make sure that our siege guy is somewhere we can build Vector ProjectedPoint = UTIL_ProjectPointToNavmesh(ThisPlayer->pev->origin, Vector(100.0f, 100.0f, 100.0f), GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE)); - if (!vIsZero(ProjectedPoint)) + if (!vIsZero(ProjectedPoint) && vDist2DSq(ProjectedPoint, ThisHive->Location) < sqrf(BALANCE_VAR(kSiegeTurretRange))) { AICOMM_AddNewBase(pBot, ProjectedPoint, MARINE_BASE_SIEGE); } @@ -4982,6 +4982,8 @@ bool AICOMM_BuildOutMainBase(AvHAIPlayer* pBot, AvHAIMarineBase* BaseToBuildOut) int NumTurrets = 0; int NumIncomplete = 0; + vector TurretLocations; + int DesiredInfPortals = (int)ceilf((float)AIMGR_GetNumPlayersOnTeam(BotTeam) / 4.0f); for (auto it = BaseToBuildOut->PlacedStructures.begin(); it != BaseToBuildOut->PlacedStructures.end(); it++) @@ -5056,6 +5058,7 @@ bool AICOMM_BuildOutMainBase(AvHAIPlayer* pBot, AvHAIMarineBase* BaseToBuildOut) break; case STRUCTURE_MARINE_TURRET: NumTurrets++; + TurretLocations.push_back(StructureRef.Location); break; default: break; @@ -5209,6 +5212,30 @@ bool AICOMM_BuildOutMainBase(AvHAIPlayer* pBot, AvHAIMarineBase* BaseToBuildOut) if (bSuccess) { return true; } } + if (NumTurrets > 0) + { + Vector Centroid = ZERO_VECTOR; + + for (auto tLocs = TurretLocations.begin(); tLocs != TurretLocations.end(); tLocs++) + { + Centroid = Centroid + *tLocs; + } + + Centroid = Centroid / TurretLocations.size(); + + if (!vIsZero(Centroid)) + { + Vector CentroidBuildLocation = UTIL_ProjectPointToNavmesh(Centroid, GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE)); + + if (!vIsZero(CentroidBuildLocation)) + { + bool bSuccess = AICOMM_AddStructureToBase(pBot, STRUCTURE_MARINE_TURRETFACTORY, CentroidBuildLocation, BaseToBuildOut); + + if (bSuccess) { return true; } + } + } + } + int NumAttempts = 0; while (NumAttempts < 5) @@ -5475,6 +5502,8 @@ bool AICOMM_BuildOutOutpost(AvHAIPlayer* pBot, AvHAIMarineBase* BaseToBuildOut) int NumTurrets = 0; int NumIncomplete = 0; + vector TurretLocations; + for (auto it = BaseToBuildOut->PlacedStructures.begin(); it != BaseToBuildOut->PlacedStructures.end(); it++) { AvHAIBuildableStructure StructureRef = AITAC_GetDeployableStructureByEntIndex(BaseToBuildOut->BaseTeam, *it); @@ -5499,6 +5528,7 @@ bool AICOMM_BuildOutOutpost(AvHAIPlayer* pBot, AvHAIMarineBase* BaseToBuildOut) break; case STRUCTURE_MARINE_TURRET: NumTurrets++; + TurretLocations.push_back(StructureRef.Location); break; default: break; @@ -5584,6 +5614,33 @@ bool AICOMM_BuildOutOutpost(AvHAIPlayer* pBot, AvHAIMarineBase* BaseToBuildOut) if (bSuccess) { return true; } } + if (StructureToDeploy == STRUCTURE_MARINE_TURRETFACTORY) + { + if (NumTurrets > 0) + { + Vector Centroid = ZERO_VECTOR; + + for (auto tLocs = TurretLocations.begin(); tLocs != TurretLocations.end(); tLocs++) + { + Centroid = Centroid + *tLocs; + } + + Centroid = Centroid / TurretLocations.size(); + + if (!vIsZero(Centroid)) + { + Vector CentroidBuildLocation = UTIL_ProjectPointToNavmesh(Centroid, GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE)); + + if (!vIsZero(CentroidBuildLocation)) + { + bool bSuccess = AICOMM_AddStructureToBase(pBot, StructureToDeploy, CentroidBuildLocation, BaseToBuildOut); + + if (bSuccess) { return true; } + } + } + } + } + int NumAttempts = 0; while (NumAttempts < 5) @@ -5624,6 +5681,8 @@ bool AICOMM_BuildOutSiege(AvHAIPlayer* pBot, AvHAIMarineBase* BaseToBuildOut) int NumTurrets = 0; int NumIncomplete = 0; + vector TurretLocations; + for (auto it = BaseToBuildOut->PlacedStructures.begin(); it != BaseToBuildOut->PlacedStructures.end(); it++) { AvHAIBuildableStructure StructureRef = AITAC_GetDeployableStructureByEntIndex(BaseToBuildOut->BaseTeam, *it); @@ -5651,6 +5710,7 @@ bool AICOMM_BuildOutSiege(AvHAIPlayer* pBot, AvHAIMarineBase* BaseToBuildOut) break; case STRUCTURE_MARINE_SIEGETURRET: NumTurrets++; + TurretLocations.push_back(StructureRef.Location); break; default: break; @@ -5710,6 +5770,30 @@ bool AICOMM_BuildOutSiege(AvHAIPlayer* pBot, AvHAIMarineBase* BaseToBuildOut) int NumAttempts = 0; + if (NumTurrets > 0) + { + Vector Centroid = ZERO_VECTOR; + + for (auto tLocs = TurretLocations.begin(); tLocs != TurretLocations.end(); tLocs++) + { + Centroid = Centroid + *tLocs; + } + + Centroid = Centroid / TurretLocations.size(); + + if (!vIsZero(Centroid)) + { + Vector BuildLocation = UTIL_ProjectPointToNavmesh(Centroid, GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE)); + + if (!vIsZero(BuildLocation)) + { + bool bSuccess = AICOMM_AddStructureToBase(pBot, StructureToDeploy, BuildLocation, BaseToBuildOut); + + if (bSuccess) { return true; } + } + } + } + while (NumAttempts < 5) { Vector BuildLocation = UTIL_GetRandomPointOnNavmeshInRadiusIgnoreReachability(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), BaseToBuildOut->BaseLocation, UTIL_MetresToGoldSrcUnits(2.0f + NumAttempts)); @@ -5820,6 +5904,8 @@ bool AICOMM_BuildOutGuardPost(AvHAIPlayer* pBot, AvHAIMarineBase* BaseToBuildOut int NumTurrets = 0; int NumIncomplete = 0; + vector TurretLocations; + for (auto it = BaseToBuildOut->PlacedStructures.begin(); it != BaseToBuildOut->PlacedStructures.end(); it++) { AvHAIBuildableStructure StructureRef = AITAC_GetDeployableStructureByEntIndex(BaseToBuildOut->BaseTeam, *it); @@ -5839,6 +5925,7 @@ bool AICOMM_BuildOutGuardPost(AvHAIPlayer* pBot, AvHAIMarineBase* BaseToBuildOut else if (StructureRef.StructureType == STRUCTURE_MARINE_TURRET) { NumTurrets++; + TurretLocations.push_back(StructureRef.Location); } else if (StructureRef.StructureType == STRUCTURE_MARINE_OBSERVATORY) { @@ -5919,6 +6006,33 @@ bool AICOMM_BuildOutGuardPost(AvHAIPlayer* pBot, AvHAIMarineBase* BaseToBuildOut if (bSuccess) { return true; } } + if (StructureToDeploy == STRUCTURE_MARINE_TURRETFACTORY) + { + if (NumTurrets > 0) + { + Vector Centroid = ZERO_VECTOR; + + for (auto tLocs = TurretLocations.begin(); tLocs != TurretLocations.end(); tLocs++) + { + Centroid = Centroid + *tLocs; + } + + Centroid = Centroid / TurretLocations.size(); + + if (!vIsZero(Centroid)) + { + Vector CentroidBuildLocation = UTIL_ProjectPointToNavmesh(Centroid, GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE)); + + if (!vIsZero(CentroidBuildLocation)) + { + bool bSuccess = AICOMM_AddStructureToBase(pBot, StructureToDeploy, CentroidBuildLocation, BaseToBuildOut); + + if (bSuccess) { return true; } + } + } + } + } + int NumAttempts = 0; while (NumAttempts < 5) @@ -5953,7 +6067,7 @@ AvHAIMarineBase* AICOMM_AddNewBase(AvHAIPlayer* pBot, Vector NewBaseLocation, Ma bool AICOMM_AddStructureToBase(AvHAIPlayer* pBot, AvHAIDeployableStructureType StructureToDeploy, Vector BuildLocation, AvHAIMarineBase* BaseToAdd) { - if (vIsZero(BuildLocation)) { return false; } + if (!BaseToAdd || vIsZero(BuildLocation)) { return false; } AvHAIBuildableStructure* DeployedStructure = AICOMM_DeployStructure(pBot, StructureToDeploy, BuildLocation); @@ -5961,6 +6075,18 @@ bool AICOMM_AddStructureToBase(AvHAIPlayer* pBot, AvHAIDeployableStructureType S { BaseToAdd->PlacedStructures.push_back(DeployedStructure->EntIndex); BaseToAdd->bBaseInitialised = true; + if (BaseToAdd->BaseType == MARINE_BASE_MAINBASE) + { + DeployedStructure->Purpose = STRUCTURE_PURPOSE_BASE; + } + else if (BaseToAdd->BaseType == MARINE_BASE_SIEGE) + { + DeployedStructure->Purpose = STRUCTURE_PURPOSE_SIEGE; + } + else + { + DeployedStructure->Purpose = STRUCTURE_PURPOSE_FORTIFY; + } return true; } diff --git a/main/source/mod/AvHAIConstants.h b/main/source/mod/AvHAIConstants.h index c88fc7bd..7446312e 100644 --- a/main/source/mod/AvHAIConstants.h +++ b/main/source/mod/AvHAIConstants.h @@ -768,6 +768,8 @@ typedef struct AVH_AI_PLAYER float LastRequestTime = 0.0f; // When bot last used a voice line to request something. Prevents spam + float LastTeleportTime = 0.0f; // Last time the bot teleported somewhere + Vector DesiredLookDirection = g_vecZero; // What view angle is the bot currently turning towards Vector InterpolatedLookDirection = g_vecZero; // Used to smoothly interpolate the bot's view rather than snap instantly like an aimbot edict_t* LookTarget = nullptr; // Used to work out what view angle is needed to look at the desired entity diff --git a/main/source/mod/AvHAINavigation.cpp b/main/source/mod/AvHAINavigation.cpp index 356d8629..b06a24d1 100644 --- a/main/source/mod/AvHAINavigation.cpp +++ b/main/source/mod/AvHAINavigation.cpp @@ -3772,7 +3772,16 @@ void BlockedMove(AvHAIPlayer* pBot, const Vector StartPoint, const Vector EndPoi if (vIsZero(vForward)) { - vForward = UTIL_GetForwardVector2D(pBot->Edict->v.angles); + if (pBot->BotNavInfo.CurrentPathPoint < pBot->BotNavInfo.CurrentPath.size() - 1) + { + bot_path_node NextPathNode = pBot->BotNavInfo.CurrentPath[pBot->BotNavInfo.CurrentPathPoint + 1]; + + vForward = UTIL_GetVectorNormal2D(NextPathNode.Location - pBot->Edict->v.origin); + } + else + { + vForward = UTIL_GetForwardVector2D(pBot->Edict->v.angles); + } } } @@ -6830,7 +6839,8 @@ bool MoveTo(AvHAIPlayer* pBot, const Vector Destination, const BotMoveStyle Move bool bSucceeded = NAV_GenerateNewBasePath(pBot, Destination, MoveStyle, MaxAcceptableDist); if (!bSucceeded) - { + { + const char* botName = STRING(pBot->Edict->v.netname); pBot->BotNavInfo.StuckInfo.bPathFollowFailed = true; if (!UTIL_PointIsOnNavmesh(pBot->CollisionHullBottomLocation, pBot->BotNavInfo.NavProfile)) @@ -6839,7 +6849,7 @@ bool MoveTo(AvHAIPlayer* pBot, const Vector Destination, const BotMoveStyle Move { MoveDirectlyTo(pBot, BotNavInfo->LastNavMeshPosition); - if (vDist2DSq(pBot->CurrentFloorPosition, BotNavInfo->LastNavMeshPosition) < sqrf(8.0f)) + if (vDist2DSq(pBot->CurrentFloorPosition, BotNavInfo->LastNavMeshPosition) < 1.0f) { BotNavInfo->LastNavMeshPosition = g_vecZero; } @@ -6848,7 +6858,7 @@ bool MoveTo(AvHAIPlayer* pBot, const Vector Destination, const BotMoveStyle Move } else { - if (!vIsZero(BotNavInfo->UnstuckMoveLocation) && vDist2DSq(pBot->CurrentFloorPosition, BotNavInfo->UnstuckMoveLocation) < sqrf(8.0f)) + if (!vIsZero(BotNavInfo->UnstuckMoveLocation) && vDist2DSq(pBot->CurrentFloorPosition, BotNavInfo->UnstuckMoveLocation) < 1.0f) { BotNavInfo->UnstuckMoveLocation = ZERO_VECTOR; } @@ -6867,7 +6877,27 @@ bool MoveTo(AvHAIPlayer* pBot, const Vector Destination, const BotMoveStyle Move } else { - MoveDirectlyTo(pBot, Destination); + if (!vIsZero(BotNavInfo->UnstuckMoveLocation) && vDist2DSq(pBot->CurrentFloorPosition, BotNavInfo->UnstuckMoveLocation) < 1.0f) + { + BotNavInfo->UnstuckMoveLocation = ZERO_VECTOR; + } + + if (vIsZero(BotNavInfo->UnstuckMoveLocation)) + { + BotNavInfo->UnstuckMoveLocation = FindClosestPointBackOnPath(pBot, Destination); + } + + if (!vIsZero(BotNavInfo->UnstuckMoveLocation)) + { + MoveDirectlyTo(pBot, BotNavInfo->UnstuckMoveLocation); + return false; + } + else + { + MoveDirectlyTo(pBot, Destination); + } + + return false; } diff --git a/main/source/mod/AvHAIPlayer.cpp b/main/source/mod/AvHAIPlayer.cpp index 06a84b28..2c62af42 100644 --- a/main/source/mod/AvHAIPlayer.cpp +++ b/main/source/mod/AvHAIPlayer.cpp @@ -1433,6 +1433,20 @@ void BotUpdateView(AvHAIPlayer* pBot) } } + // Detect if a player has teleported away. Basically, if the player has moved significantly far away from where they were last detected in a very short space of time + // then they've teleported and we should clear their tracking info. This should work for phase gates, but also any trigger_teleport in the map (e.g. co_daimos phase gates) + if (!vIsZero(TrackingInfo->LastDetectedLocation) && gpGlobals->time - TrackingInfo->LastDetectedTime < 1.0f) + { + if (vDist2DSq(PlayerEdict->v.origin, TrackingInfo->LastDetectedLocation) > sqrf(UTIL_MetresToGoldSrcUnits(5.0f))) + { + if (!UTIL_PlayerHasLOSToEntity(pBot->Edict, PlayerEdict, UTIL_MetresToGoldSrcUnits(20.0f), false)) + { + BotClearEnemyTrackingInfo(TrackingInfo); + continue; + } + } + } + Vector VisiblePoint = GetVisiblePointOnPlayerFromObserver(pBot->Edict, PlayerEdict); TrackingInfo->VisiblePointOnPlayer = VisiblePoint; @@ -1518,7 +1532,7 @@ void BotUpdateView(AvHAIPlayer* pBot) AvHAIBuildableStructure ThisTurret = (*it); AvHTurret* TurretRef = dynamic_cast(ThisTurret.EntityRef); - if (TurretRef && TurretRef->GetIsValidTarget(pBot->Player)) + if (TurretRef && TurretRef->GetIsValidTarget(pBot->Player) && !vIsZero(GetVisiblePointOnPlayerFromObserver(ThisTurret.edict, pBot->Edict))) { bIsInRangeOfEnemyTurret = true; pBot->DangerTurrets.push_back(ThisTurret); @@ -1723,11 +1737,17 @@ void StartNewBotFrame(AvHAIPlayer* pBot) pBot->CurrentFloorPosition = NewFloorPosition; - if (vDist3DSq(pBot->BotNavInfo.LastNavMeshCheckPosition, pBot->CurrentFloorPosition) > sqrf(16.0f)) + Vector ProjectPoint = (IsPlayerLerk(pBot->Edict)) ? pBot->CurrentFloorPosition : pBot->CollisionHullBottomLocation; + + if (vDist3DSq(pBot->BotNavInfo.LastNavMeshCheckPosition, ProjectPoint) > sqrf(16.0f)) { - if (UTIL_PointIsReachable(pBot->BotNavInfo.NavProfile, AITAC_GetTeamStartingLocation(pBot->Player->GetTeam()), pBot->CurrentFloorPosition, 16.0f)) - { - pBot->BotNavInfo.LastNavMeshPosition = pBot->CurrentFloorPosition; + if (UTIL_PointIsReachable(pBot->BotNavInfo.NavProfile, AITAC_GetTeamStartingLocation(pBot->Player->GetTeam()), ProjectPoint, 16.0f)) + { + Vector NavPoint = UTIL_ProjectPointToNavmesh(ProjectPoint); + UTIL_AdjustPointAwayFromNavWall(NavPoint, 8.0f); + + pBot->BotNavInfo.LastNavMeshPosition = NavPoint; + if (pBot->BotNavInfo.IsOnGround || IsPlayerLerk(pBot->Edict)) { @@ -1894,7 +1914,24 @@ void EndBotFrame(AvHAIPlayer* pBot) void CustomThink(AvHAIPlayer* pBot) { - MoveTo(pBot, UTIL_GetFloorUnderEntity(INDEXENT(1)), MOVESTYLE_NORMAL); + pBot->CurrentTask = &pBot->PrimaryBotTask; + + AITASK_BotUpdateAndClearTasks(pBot); + + if (pBot->CurrentTask->TaskType != TASK_ATTACK) + { + DeployableSearchFilter EnemyOCFilter; + EnemyOCFilter.DeployableTypes = STRUCTURE_ALIEN_OFFENCECHAMBER; + + AvHAIBuildableStructure NearestOC = AITAC_FindClosestDeployableToLocation(pBot->Edict->v.origin, &EnemyOCFilter); + + if (NearestOC.IsValid()) + { + AITASK_SetAttackTask(pBot, pBot->CurrentTask, NearestOC.edict, false); + } + } + + BotProgressTask(pBot, pBot->CurrentTask); } @@ -4305,6 +4342,7 @@ void AIPlayerSetSecondaryMarineTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) if (FNullEnt(NearestDangerTurret.edict) || ThisDist < MinDist) { NearestDangerTurret = (*it); + MinDist = ThisDist; } } @@ -4615,6 +4653,9 @@ void AIPlayerNSAlienThink(AvHAIPlayer* pBot) if (AlienCombatThink(pBot)) { return; } } + // We've JUST tried placing a structure. Wait until we get confirmation of the structure being placed before doing anything else + if (pBot->CurrentTask && pBot->CurrentTask->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_PENDING) { return; } + bool bPlayerMustFinishPrimaryTask = AIPlayerMustFinishCurrentTask(pBot, &pBot->PrimaryBotTask); if (!bPlayerMustFinishPrimaryTask) @@ -7124,6 +7165,7 @@ void AIPlayerSetSecondaryAlienTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) if (FNullEnt(NearestDangerTurret.edict) || ThisDist < MinDist) { NearestDangerTurret = (*it); + MinDist = ThisDist; } } @@ -7521,7 +7563,10 @@ void AIPlayerSetWantsAndNeedsAlienTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) bInMiddleOfMove = CurrentMove.flag != SAMPLE_POLYFLAGS_WALK; } - if (!bInMiddleOfMove) + // Don't get upgrades if we're not in our regular desired life form, e.g. we've temporarily gone gorge to drop a res tower + bool bTempEvolved = (pBot->BotRole == BOT_ROLE_BUILDER && !IsPlayerGorge(pBot->Edict)) || (pBot->BotRole != BOT_ROLE_BUILDER && IsPlayerGorge(pBot->Edict)); + + if (!bInMiddleOfMove && !bTempEvolved) { if (!PlayerHasAlienUpgradeOfType(pBot->Edict, HIVE_TECH_DEFENCE) && AITAC_IsAlienUpgradeAvailableForTeam(pBot->Player->GetTeam(), HIVE_TECH_DEFENCE)) { @@ -8894,4 +8939,5 @@ void OnBotTeleport(AvHAIPlayer* pBot) ClearBotStuck(pBot); ClearBotStuckMovement(pBot); pBot->BotNavInfo.LastOpenLocation = ZERO_VECTOR; + pBot->LastTeleportTime = gpGlobals->time; } \ No newline at end of file diff --git a/main/source/mod/AvHAIPlayerManager.cpp b/main/source/mod/AvHAIPlayerManager.cpp index 3557f919..cf9b33d8 100644 --- a/main/source/mod/AvHAIPlayerManager.cpp +++ b/main/source/mod/AvHAIPlayerManager.cpp @@ -644,6 +644,10 @@ void AIMGR_UpdateAIPlayers() BotUpdateViewRotation(bot, FrameDelta); + // Need to reset this since impulses generally should only be called once at a time, so this + // prevents it from being called on consecutive frames if this bot isn't running its think routine every frame + bot->Impulse = 0; + if (bHasRoundStarted) { if (IsPlayerCommander(bot->Edict)) diff --git a/main/source/mod/AvHAITactical.cpp b/main/source/mod/AvHAITactical.cpp index 5290d11b..2b521a0c 100644 --- a/main/source/mod/AvHAITactical.cpp +++ b/main/source/mod/AvHAITactical.cpp @@ -1146,6 +1146,11 @@ void AITAC_PopulateHiveData() void AITAC_RefreshHiveData() { + if (ResourceNodes.size() == 0) + { + AITAC_PopulateResourceNodes(); + } + if (Hives.size() == 0) { AITAC_PopulateHiveData(); @@ -4827,7 +4832,7 @@ bool AITAC_ShouldBotBuildHive(AvHAIPlayer* pBot, AvHAIHiveDefinition** EligibleH HiveCost += BALANCE_VAR(kGorgeCost); } - if (pBot->Player->GetResources() < HiveCost) { return false; } + if (pBot->Player->GetResources() < HiveCost - 10) { return false; } AvHTeamNumber BotTeam = pBot->Player->GetTeam(); AvHTeamNumber EnemyTeam = AIMGR_GetEnemyTeam(BotTeam); diff --git a/main/source/mod/AvHAITask.cpp b/main/source/mod/AvHAITask.cpp index dac31355..f8cf85f1 100644 --- a/main/source/mod/AvHAITask.cpp +++ b/main/source/mod/AvHAITask.cpp @@ -1006,9 +1006,7 @@ bool AITASK_IsMarineSecureHiveTaskStillValid(AvHAIPlayer* pBot, AvHAIPlayerTask* AvHAIHiveDefinition* HiveToSecure = AITAC_GetHiveFromEdict(Task->TaskTarget); if (!HiveToSecure || HiveToSecure->Status != HIVE_STATUS_UNBUILT) { return false; } - - // A marine bot will consider their "secure hive" task completed if the following structures have been fully built: // Phase gate (only if tech available) // Turret factory (regular or advanced) @@ -1380,6 +1378,7 @@ void BotProgressReinforceStructureTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) // We had a go, whether it succeeded or not we should try a new location if (Task->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_FAILED || Task->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_SUCCESS) { + pBot->Impulse = 0; Task->TaskStartedTime = gpGlobals->time; Task->TaskLocation = ZERO_VECTOR; Task->ActiveBuildInfo.BuildStatus = BUILD_ATTEMPT_NONE; @@ -1817,7 +1816,7 @@ void BotProgressAttackTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) AvHTurret* TurretRef = dynamic_cast(CBaseEntity::Instance(Task->TaskTarget)); - if (TurretRef && TurretRef->GetIsValidTarget(pBot->Player)) + if (TurretRef && TurretRef->GetIsValidTarget(pBot->Player) && !vIsZero(GetVisiblePointOnPlayerFromObserver(Task->TaskTarget, pBot->Edict))) { if (vIsZero(pBot->LastSafeLocation)) { @@ -1825,6 +1824,7 @@ void BotProgressAttackTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) } MoveTo(pBot, pBot->LastSafeLocation, MOVESTYLE_NORMAL); + BotLookAt(pBot, Task->TaskTarget); } return; @@ -2908,7 +2908,6 @@ void MarineProgressSecureHiveTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) StructureFilter.ReachabilityTeam = BotTeam; StructureFilter.ReachabilityFlags = pBot->BotNavInfo.NavProfile.ReachabilityFlag; StructureFilter.ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING; - StructureFilter.PurposeFlags = STRUCTURE_PURPOSE_FORTIFY; vector BuildableStructures = AITAC_FindAllDeployables(Hive->FloorLocation, &StructureFilter); @@ -2988,10 +2987,10 @@ void MarineProgressSecureHiveTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) { DeployableSearchFilter EnemyStructures; EnemyStructures.DeployableTypes = SEARCH_ALL_STRUCTURES; - EnemyStructures.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(15.0f); EnemyStructures.DeployableTeam = EnemyTeam; EnemyStructures.ReachabilityTeam = BotTeam; EnemyStructures.ReachabilityFlags = pBot->BotNavInfo.NavProfile.ReachabilityFlag; + EnemyStructures.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(15.0f); AvHAIBuildableStructure EnemyStructure = AITAC_FindClosestDeployableToLocation(Hive->FloorLocation, &EnemyStructures); @@ -3113,8 +3112,6 @@ void MarineProgressCapResNodeTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) BotGuardLocation(pBot, Task->TaskLocation); } - - } void BotProgressAssaultMarineBaseTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) @@ -3809,7 +3806,13 @@ void AITASK_SetMoveTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task, const Vector L void AITASK_SetBuildTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task, const AvHAIDeployableStructureType StructureType, const Vector Location, const bool bIsUrgent) { - if (Task->TaskType == TASK_BUILD && Task->StructureType == StructureType && vDist2DSq(Task->TaskLocation, Location) < sqrf(UTIL_MetresToGoldSrcUnits(5.0f))) { return; } + if (Task->TaskType == TASK_BUILD && Task->StructureType == StructureType && vDist2DSq(Task->TaskLocation, Location) < sqrf(UTIL_MetresToGoldSrcUnits(1.0f))) + { + Task->bTaskIsUrgent = bIsUrgent; + return; + } + + if (Task->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_PENDING) { return; } AITASK_ClearBotTask(pBot, Task); @@ -4028,6 +4031,8 @@ void AITASK_SetReinforceStructureTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task, return; } + if (Task->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_PENDING) { return; } + AITASK_ClearBotTask(pBot, Task); if (FNullEnt(Target) || Target->v.deadflag != DEAD_NO) { return; }