diff --git a/main/navmeshes/ns_lost.nav b/main/navmeshes/ns_lost.nav index caebb49a..4a235744 100644 Binary files a/main/navmeshes/ns_lost.nav and b/main/navmeshes/ns_lost.nav differ diff --git a/main/navmeshes/ns_machina.nav b/main/navmeshes/ns_machina.nav index 65f6d0f4..a20c668b 100644 Binary files a/main/navmeshes/ns_machina.nav and b/main/navmeshes/ns_machina.nav differ diff --git a/main/navmeshes/ns_tanith.nav b/main/navmeshes/ns_tanith.nav index 7dfba37b..4b3b4d19 100644 Binary files a/main/navmeshes/ns_tanith.nav and b/main/navmeshes/ns_tanith.nav differ diff --git a/main/source/mod/AvHAICommander.cpp b/main/source/mod/AvHAICommander.cpp index 9005f266..ca0b2bf3 100644 --- a/main/source/mod/AvHAICommander.cpp +++ b/main/source/mod/AvHAICommander.cpp @@ -1501,7 +1501,7 @@ bool AICOMM_CheckForNextSupplyAction(AvHAIPlayer* pBot) if (!bShouldPrioritiseNodes && pBot->Player->GetResources() >= 20) { - NumDesiredWelders = (int)ceilf((float)AIMGR_GetNumPlayersOnTeam(CommanderTeam) * 0.3f); + NumDesiredWelders = (int)ceilf((float)(AIMGR_GetNumPlayersOnTeam(CommanderTeam) - 1) * 0.3f); } int NumTeamWelders = AITAC_GetNumWeaponsInPlay(CommanderTeam, WEAPON_MARINE_WELDER); @@ -1539,7 +1539,7 @@ bool AICOMM_CheckForNextSupplyAction(AvHAIPlayer* pBot) } } - NumDesiredWelders = imini(NumDesiredWelders, (int)(ceilf((float)AIMGR_GetNumPlayersOnTeam(CommanderTeam) * 0.5f))); + NumDesiredWelders = imini(NumDesiredWelders, (int)(ceilf((float)(AIMGR_GetNumPlayersOnTeam(CommanderTeam) - 1) * 0.5f))); if (NumTeamWelders < NumDesiredWelders) { @@ -1561,9 +1561,15 @@ bool AICOMM_CheckForNextSupplyAction(AvHAIPlayer* pBot) } // Don't drop stuff if we badly need resource nodes - if (AICOMM_ShouldCommanderPrioritiseNodes(pBot) && pBot->Player->GetResources() < 20) { return false; } + if (AICOMM_ShouldCommanderPrioritiseNodes(pBot) && pBot->Player->GetResources() < 30) { return false; } - int NumDesiredShotguns = (int)ceilf(AIMGR_GetNumPlayersOnTeam(CommanderTeam) * 0.33f); + // Get basic research first + if (!AITAC_ResearchIsComplete(CommanderTeam, TECH_RESEARCH_ARMOR_ONE) || !AITAC_ResearchIsComplete(CommanderTeam, TECH_RESEARCH_WEAPONS_ONE)) { return false; } + + // Likewise, don't spend res if we can get phase tech going! + if (!AITAC_ResearchIsComplete(CommanderTeam, TECH_RESEARCH_PHASETECH) && AITAC_MarineResearchIsAvailable(CommanderTeam, RESEARCH_PHASETECH)) { return false; } + + int NumDesiredShotguns = (int)ceilf((AIMGR_GetNumPlayersOnTeam(CommanderTeam) - 1) * 0.33f); int NumShottysInPlay = AITAC_GetNumWeaponsInPlay(CommanderTeam, WEAPON_MARINE_SHOTGUN); if (NumShottysInPlay < NumDesiredShotguns) @@ -4746,6 +4752,7 @@ bool AICOMM_ShouldCommanderRelocate(AvHAIPlayer* pBot) if (!CurrentMainBase->bIsActive || CurrentMainBase->bRecycleBase) { return true; } + // If our main base is within 10m of the chair we're sitting in, then we clearly haven't relocated yet bool bMainBaseIsAtChair = vDist2DSq(CurrentCommChair->v.origin, CurrentMainBase->BaseLocation) < sqrf(UTIL_MetresToGoldSrcUnits(10.0f)); // We're not able to relocate after 90 seconds, best find somewhere else or we're in trouble @@ -5077,7 +5084,7 @@ bool AICOMM_BuildOutMainBase(AvHAIPlayer* pBot, AvHAIMarineBase* BaseToBuildOut) { if (pBot->Player->GetResources() < BALANCE_VAR(kCommandStationCost)) { return true; } - Vector BuildLocation = AITAC_GetRandomBuildHintInLocation(STRUCTURE_MARINE_COMMCHAIR, BaseToBuildOut->BaseLocation, UTIL_MetresToGoldSrcUnits(10.0f)); + Vector BuildLocation = AITAC_GetRandomBuildHintInLocation(STRUCTURE_MARINE_COMMCHAIR, BaseToBuildOut->BaseLocation, UTIL_MetresToGoldSrcUnits(20.0f)); if (!vIsZero(BuildLocation)) { @@ -5162,7 +5169,7 @@ bool AICOMM_BuildOutMainBase(AvHAIPlayer* pBot, AvHAIMarineBase* BaseToBuildOut) { if (pBot->Player->GetResources() < BALANCE_VAR(kArmoryCost)) { return true; } - Vector BuildLocation = AITAC_GetRandomBuildHintInLocation(STRUCTURE_MARINE_ARMOURY, CommChair.Location, UTIL_MetresToGoldSrcUnits(15.0f)); + Vector BuildLocation = AITAC_GetRandomBuildHintInLocation(STRUCTURE_MARINE_ARMOURY, BaseToBuildOut->BaseLocation, UTIL_MetresToGoldSrcUnits(20.0f)); if (!vIsZero(BuildLocation)) { @@ -5203,7 +5210,7 @@ bool AICOMM_BuildOutMainBase(AvHAIPlayer* pBot, AvHAIMarineBase* BaseToBuildOut) { if (pBot->Player->GetResources() < BALANCE_VAR(kTurretFactoryCost)) { return true; } - Vector BuildLocation = AITAC_GetRandomBuildHintInLocation(STRUCTURE_MARINE_TURRETFACTORY, CommChair.Location, UTIL_MetresToGoldSrcUnits(15.0f)); + Vector BuildLocation = AITAC_GetRandomBuildHintInLocation(STRUCTURE_MARINE_TURRETFACTORY, BaseToBuildOut->BaseLocation, UTIL_MetresToGoldSrcUnits(20.0f)); if (!vIsZero(BuildLocation)) { @@ -5315,7 +5322,7 @@ bool AICOMM_BuildOutMainBase(AvHAIPlayer* pBot, AvHAIMarineBase* BaseToBuildOut) { if (pBot->Player->GetResources() < BALANCE_VAR(kArmsLabCost)) { return true; } - Vector BuildLocation = AITAC_GetRandomBuildHintInLocation(STRUCTURE_MARINE_ARMSLAB, CommChair.Location, UTIL_MetresToGoldSrcUnits(20.0f)); + Vector BuildLocation = AITAC_GetRandomBuildHintInLocation(STRUCTURE_MARINE_ARMSLAB, BaseToBuildOut->BaseLocation, UTIL_MetresToGoldSrcUnits(20.0f)); if (!vIsZero(BuildLocation)) { @@ -5356,7 +5363,7 @@ bool AICOMM_BuildOutMainBase(AvHAIPlayer* pBot, AvHAIMarineBase* BaseToBuildOut) { if (pBot->Player->GetResources() < BALANCE_VAR(kObservatoryCost)) { return true; } - Vector BuildLocation = AITAC_GetRandomBuildHintInLocation(STRUCTURE_MARINE_OBSERVATORY, CommChair.Location, UTIL_MetresToGoldSrcUnits(20.0f)); + Vector BuildLocation = AITAC_GetRandomBuildHintInLocation(STRUCTURE_MARINE_OBSERVATORY, BaseToBuildOut->BaseLocation, UTIL_MetresToGoldSrcUnits(20.0f)); if (!vIsZero(BuildLocation)) { @@ -5399,7 +5406,7 @@ bool AICOMM_BuildOutMainBase(AvHAIPlayer* pBot, AvHAIMarineBase* BaseToBuildOut) { if (pBot->Player->GetResources() < BALANCE_VAR(kPhaseGateCost)) { return true; } - Vector BuildLocation = AITAC_GetRandomBuildHintInLocation(STRUCTURE_MARINE_PHASEGATE, CommChair.Location, UTIL_MetresToGoldSrcUnits(20.0f)); + Vector BuildLocation = AITAC_GetRandomBuildHintInLocation(STRUCTURE_MARINE_PHASEGATE, BaseToBuildOut->BaseLocation, UTIL_MetresToGoldSrcUnits(20.0f)); if (!vIsZero(BuildLocation)) { @@ -5451,7 +5458,7 @@ bool AICOMM_BuildOutMainBase(AvHAIPlayer* pBot, AvHAIMarineBase* BaseToBuildOut) { if (pBot->Player->GetResources() < BALANCE_VAR(kPrototypeLabCost)) { return true; } - Vector BuildLocation = AITAC_GetRandomBuildHintInLocation(STRUCTURE_MARINE_PROTOTYPELAB, CommChair.Location, UTIL_MetresToGoldSrcUnits(20.0f)); + Vector BuildLocation = AITAC_GetRandomBuildHintInLocation(STRUCTURE_MARINE_PROTOTYPELAB, BaseToBuildOut->BaseLocation, UTIL_MetresToGoldSrcUnits(20.0f)); if (!vIsZero(BuildLocation)) { diff --git a/main/source/mod/AvHAINavigation.cpp b/main/source/mod/AvHAINavigation.cpp index c1c18a71..8ddff7cb 100644 --- a/main/source/mod/AvHAINavigation.cpp +++ b/main/source/mod/AvHAINavigation.cpp @@ -433,6 +433,8 @@ void AIDEBUG_DrawOffMeshConnections(float DrawTime) { if (NavMeshes[REGULAR_NAV_MESH].tileCache) { + int NumDrawn = 0; + for (int i = 0; i < NavMeshes[REGULAR_NAV_MESH].tileCache->getOffMeshCount(); i++) { const dtOffMeshConnection* con = NavMeshes[REGULAR_NAV_MESH].tileCache->getOffMeshConnection(i); @@ -472,6 +474,13 @@ void AIDEBUG_DrawOffMeshConnections(float DrawTime) UTIL_DrawLine(INDEXENT(1), StartLine, EndLine, DrawTime, 0, 255, 255); break; } + + NumDrawn++; + + if (NumDrawn > 30) + { + break; + } } } @@ -783,9 +792,12 @@ void ReloadNavMeshes() bool bTileCacheFullyUpdated = UTIL_UpdateTileCache(); - while (!bTileCacheFullyUpdated) + int NumAttempts = 0; + + while (!bTileCacheFullyUpdated && NumAttempts < 30) { bTileCacheFullyUpdated = UTIL_UpdateTileCache(); + NumAttempts++; } } } @@ -3994,14 +4006,16 @@ void SkulkLadderMove(AvHAIPlayer* pBot, const Vector StartPoint, const Vector En if (IsPlayerClimbingWall(pBot->Edict)) { - Vector StartLeftTrace = pBot->CollisionHullTopLocation - (ClimbRightNormal * GetPlayerRadius(pBot->Player)); - Vector StartRightTrace = pBot->CollisionHullTopLocation + (ClimbRightNormal * GetPlayerRadius(pBot->Player)); + Vector TraceBeginLocation = (bIsGoingUpLadder) ? pBot->CollisionHullTopLocation : pBot->CollisionHullBottomLocation; + Vector StartLeftTrace = TraceBeginLocation - (ClimbRightNormal * (GetPlayerRadius(pBot->Player) - 1.0f)); + + Vector StartRightTrace = TraceBeginLocation + (ClimbRightNormal * (GetPlayerRadius(pBot->Player) - 1.0f)); - Vector EndLeftTrace = (bIsGoingUpLadder) ? StartLeftTrace + Vector(0.0f, 0.0f, 32.0f) : StartLeftTrace - Vector(0.0f, 0.0f, 32.0f); - Vector EndRightTrace = (bIsGoingUpLadder) ? StartRightTrace + Vector(0.0f, 0.0f, 32.0f) : StartRightTrace - Vector(0.0f, 0.0f, 32.0f); + Vector EndLeftTrace = (bIsGoingUpLadder) ? StartLeftTrace + Vector(0.0f, 0.0f, 4.0f) : StartLeftTrace - Vector(0.0f, 0.0f, 4.0f); + Vector EndRightTrace = (bIsGoingUpLadder) ? StartRightTrace + Vector(0.0f, 0.0f, 4.0f) : StartRightTrace - Vector(0.0f, 0.0f, 4.0f); - bool bBlockedLeft = !UTIL_QuickHullTrace(pEdict, StartLeftTrace, EndLeftTrace, head_hull); - bool bBlockedRight = !UTIL_QuickHullTrace(pEdict, StartRightTrace, EndRightTrace, head_hull); + bool bBlockedLeft = !UTIL_QuickCollisionTrace(StartLeftTrace, EndLeftTrace); + bool bBlockedRight = !UTIL_QuickCollisionTrace(StartRightTrace, EndRightTrace); if (bBlockedLeft && bBlockedRight) { @@ -4010,11 +4024,11 @@ void SkulkLadderMove(AvHAIPlayer* pBot, const Vector StartPoint, const Vector En if (Side > 0) { - pBot->desiredMovementDir = -LadderRightNormal; + pBot->desiredMovementDir = UTIL_GetVectorNormal2D(-CurrentLadderNormal - LadderRightNormal); } else { - pBot->desiredMovementDir = LadderRightNormal; + pBot->desiredMovementDir = UTIL_GetVectorNormal2D(-CurrentLadderNormal + LadderRightNormal); } Vector LookLocation = pBot->Edict->v.origin - (CurrentLadderNormal * 50.0f); @@ -4075,7 +4089,7 @@ void LadderMove(AvHAIPlayer* pBot, const Vector StartPoint, const Vector EndPoin return; } - edict_t* Ladder = UTIL_GetNearestLadderAtPoint(pBot->Edict->v.origin); + edict_t* Ladder = UTIL_GetNearestLadderAtPoint(StartPoint); if (FNullEnt(Ladder)) { return; } @@ -4135,10 +4149,6 @@ void LadderMove(AvHAIPlayer* pBot, const Vector StartPoint, const Vector EndPoin if (bIsGoingUpLadder) { - Vector HullTraceTo = EndPoint; - HullTraceTo.z = pBot->CollisionHullBottomLocation.z; - - // We have reached our desired climb height and want to get off the ladder if ((pBot->Edict->v.origin.z >= RequiredClimbHeight) && UTIL_QuickHullTrace(pEdict, pEdict->v.origin, Vector(EndPoint.x, EndPoint.y, pEdict->v.origin.z), head_hull)) { @@ -4168,27 +4178,41 @@ void LadderMove(AvHAIPlayer* pBot, const Vector StartPoint, const Vector EndPoin return; } - else + + if (CanPlayerCrouch(pBot->Edict) && pBot->BotNavInfo.CurrentPathPoint < pBot->BotNavInfo.CurrentPath.size() - 1) { - // This is for cases where the ladder physically doesn't reach the desired get-off point and the bot kind of has to "jump" up off the ladder. - if (pBot->CollisionHullTopLocation.z >= UTIL_GetNearestLadderTopPoint(pEdict).z) + bot_path_node NextPathPoint = pBot->BotNavInfo.CurrentPath[pBot->BotNavInfo.CurrentPathPoint + 1]; + + if (NextPathPoint.area == SAMPLE_POLYAREA_CROUCH && fabsf(RequiredClimbHeight - pBot->Edict->v.origin.z) < GetPlayerHeight(pBot->Edict, false)) { - pBot->desiredMovementDir = vForward; - // We look up really far to get maximum launch - BotMoveLookAt(pBot, EndPoint + Vector(0.0f, 0.0f, 100.0f), true); - return; + pBot->Button |= IN_DUCK; } + } - // Still climbing the ladder. Look up, and move left/right on the ladder to avoid any blockages + // This is for cases where the ladder physically doesn't reach the desired get-off point and the bot kind of has to "jump" up off the ladder. + if (pBot->CollisionHullTopLocation.z >= UTIL_GetNearestLadderTopPoint(pEdict).z) + { + pBot->desiredMovementDir = vForward; + // We look up really far to get maximum launch + BotMoveLookAt(pBot, EndPoint + Vector(0.0f, 0.0f, 100.0f), true); + return; + } - Vector StartLeftTrace = pBot->CollisionHullTopLocation - (ClimbRightNormal * GetPlayerRadius(pBot->Player)); - Vector StartRightTrace = pBot->CollisionHullTopLocation + (ClimbRightNormal * GetPlayerRadius(pBot->Player)); + // Still climbing the ladder. Look up, and move left/right on the ladder to avoid any blockages - Vector EndLeftTrace = (bIsGoingUpLadder) ? StartLeftTrace + Vector(0.0f, 0.0f, 32.0f) : StartLeftTrace - Vector(0.0f, 0.0f, 32.0f); - Vector EndRightTrace = (bIsGoingUpLadder) ? StartRightTrace + Vector(0.0f, 0.0f, 32.0f) : StartRightTrace - Vector(0.0f, 0.0f, 32.0f); + if (fabsf(RequiredClimbHeight - pBot->Edict->v.origin.z) > GetPlayerHeight(pBot->Edict, false)) + { - bool bBlockedLeft = !UTIL_QuickTrace(pEdict, StartLeftTrace, EndLeftTrace); - bool bBlockedRight = !UTIL_QuickTrace(pEdict, StartRightTrace, EndRightTrace); + Vector TraceBeginLocation = (bIsGoingUpLadder) ? pBot->CollisionHullTopLocation : pBot->CollisionHullBottomLocation; + Vector StartLeftTrace = TraceBeginLocation - (ClimbRightNormal * (GetPlayerRadius(pBot->Player) - 1.0f)); + + Vector StartRightTrace = TraceBeginLocation + (ClimbRightNormal * (GetPlayerRadius(pBot->Player) - 1.0f)); + + Vector EndLeftTrace = (bIsGoingUpLadder) ? StartLeftTrace + Vector(0.0f, 0.0f, 4.0f) : StartLeftTrace - Vector(0.0f, 0.0f, 4.0f); + Vector EndRightTrace = (bIsGoingUpLadder) ? StartRightTrace + Vector(0.0f, 0.0f, 4.0f) : StartRightTrace - Vector(0.0f, 0.0f, 4.0f); + + bool bBlockedLeft = !UTIL_QuickCollisionTrace(StartLeftTrace, EndLeftTrace); + bool bBlockedRight = !UTIL_QuickCollisionTrace(StartRightTrace, EndRightTrace); if (bBlockedLeft && bBlockedRight) { @@ -4232,18 +4256,18 @@ void LadderMove(AvHAIPlayer* pBot, const Vector StartPoint, const Vector EndPoin return; } - if (!UTIL_QuickHullTrace(pBot->Edict, pBot->CurrentEyePosition, pBot->CurrentEyePosition + Vector(0.0f, 0.0f, 32.0f))) + if (!UTIL_QuickCollisionTrace(pBot->CollisionHullTopLocation, pBot->CollisionHullTopLocation + Vector(0.0f, 0.0f, 4.0f))) { Vector LadderCentre = UTIL_GetCentreOfEntity(Ladder); int Side = vPointOnLine(LadderCentre, LadderCentre + CurrentLadderNormal, pBot->Edict->v.origin); if (Side > 0) { - pBot->desiredMovementDir = -LadderRightNormal; + pBot->desiredMovementDir = LadderRightNormal; } else { - pBot->desiredMovementDir = LadderRightNormal; + pBot->desiredMovementDir = -LadderRightNormal; } Vector LookLocation = pBot->Edict->v.origin - (CurrentLadderNormal * 50.0f); @@ -4252,63 +4276,62 @@ void LadderMove(AvHAIPlayer* pBot, const Vector StartPoint, const Vector EndPoin return; } + } - // Crouch if we're hitting our head on a ceiling + // Crouch if we're hitting our head on a ceiling - if (!IsPlayerGorge(pEdict) && !IsPlayerLerk(pEdict)) + if (!IsPlayerGorge(pEdict) && !IsPlayerLerk(pEdict)) + { + Vector HeadTraceLocation = GetPlayerTopOfCollisionHull(pEdict, false); + + bool bHittingHead = !UTIL_QuickTrace(pBot->Edict, HeadTraceLocation, HeadTraceLocation + Vector(0.0f, 0.0f, 10.0f)); + + if (bHittingHead) { - Vector HeadTraceLocation = GetPlayerTopOfCollisionHull(pEdict, false); - - bool bHittingHead = !UTIL_QuickTrace(pBot->Edict, HeadTraceLocation, HeadTraceLocation + Vector(0.0f, 0.0f, 10.0f)); - - if (bHittingHead) - { - pBot->Button |= IN_DUCK; - } - } - - // We're not blocked by anything - - // If the get-off point is to the side, look to the side and climb. Otherwise, face the ladder - - Vector LookLocation = EndPoint; - - float dot = UTIL_GetDotProduct2D(vForward, LadderRightNormal); - - // Get-off point is to the side of the ladder rather than right at the top - if (fabsf(dot) > 0.5f) - { - if (dot > 0.0f) - { - LookLocation = pBot->Edict->v.origin + (LadderRightNormal * 50.0f); - } - else - { - LookLocation = pBot->Edict->v.origin - (LadderRightNormal * 50.0f); - } - - } - else - { - // Get-off point is at the top of the ladder, so face the ladder - LookLocation = EndPoint - (CurrentLadderNormal * 50.0f); - } - - LookLocation.z += 100.0f; - - BotMoveLookAt(pBot, LookLocation, true); - - if (RequiredClimbHeight > pBot->Edict->v.origin.z || IsPlayerSkulk(pBot->Edict)) - { - pBot->desiredMovementDir = -CurrentLadderNormal; - } - else - { - pBot->desiredMovementDir = CurrentLadderNormal; + pBot->Button |= IN_DUCK; } } + // We're not blocked by anything + + // If the get-off point is to the side, look to the side and climb. Otherwise, face the ladder + + Vector LookLocation = EndPoint; + + float dot = UTIL_GetDotProduct2D(vForward, LadderRightNormal); + + // Get-off point is to the side of the ladder rather than right at the top + if (fabsf(dot) > 0.5f) + { + if (dot > 0.0f) + { + LookLocation = pBot->Edict->v.origin + (LadderRightNormal * 50.0f); + } + else + { + LookLocation = pBot->Edict->v.origin - (LadderRightNormal * 50.0f); + } + + } + else + { + // Get-off point is at the top of the ladder, so face the ladder + LookLocation = EndPoint - (CurrentLadderNormal * 50.0f); + } + + LookLocation.z += 100.0f; + + BotMoveLookAt(pBot, LookLocation, true); + + if (RequiredClimbHeight > pBot->Edict->v.origin.z || IsPlayerSkulk(pBot->Edict)) + { + pBot->desiredMovementDir = -CurrentLadderNormal; + } + else + { + pBot->desiredMovementDir = CurrentLadderNormal; + } } else @@ -4316,11 +4339,16 @@ void LadderMove(AvHAIPlayer* pBot, const Vector StartPoint, const Vector EndPoin // We're going down the ladder - Vector StartLeftTrace = pBot->CollisionHullBottomLocation - (LadderRightNormal * (GetPlayerRadius(pBot->Player) + 2.0f)); - Vector StartRightTrace = pBot->CollisionHullBottomLocation + (LadderRightNormal * (GetPlayerRadius(pBot->Player) + 2.0f)); + Vector TraceBeginLocation = (bIsGoingUpLadder) ? pBot->CollisionHullTopLocation : pBot->CollisionHullBottomLocation; + Vector StartLeftTrace = TraceBeginLocation - (ClimbRightNormal * (GetPlayerRadius(pBot->Player) - 1.0f)); - bool bBlockedLeft = !UTIL_QuickTrace(pEdict, StartLeftTrace, StartLeftTrace - Vector(0.0f, 0.0f, 32.0f)); - bool bBlockedRight = !UTIL_QuickTrace(pEdict, StartRightTrace, StartRightTrace - Vector(0.0f, 0.0f, 32.0f)); + Vector StartRightTrace = TraceBeginLocation + (ClimbRightNormal * (GetPlayerRadius(pBot->Player) - 1.0f)); + + Vector EndLeftTrace = (bIsGoingUpLadder) ? StartLeftTrace + Vector(0.0f, 0.0f, 4.0f) : StartLeftTrace - Vector(0.0f, 0.0f, 4.0f); + Vector EndRightTrace = (bIsGoingUpLadder) ? StartRightTrace + Vector(0.0f, 0.0f, 4.0f) : StartRightTrace - Vector(0.0f, 0.0f, 4.0f); + + bool bBlockedLeft = !UTIL_QuickCollisionTrace(StartLeftTrace, EndLeftTrace); + bool bBlockedRight = !UTIL_QuickCollisionTrace(StartRightTrace, EndRightTrace); if (bBlockedLeft && !bBlockedRight) { diff --git a/main/source/mod/AvHAIPlayer.cpp b/main/source/mod/AvHAIPlayer.cpp index 2c62af42..0a1e8755 100644 --- a/main/source/mod/AvHAIPlayer.cpp +++ b/main/source/mod/AvHAIPlayer.cpp @@ -6138,17 +6138,23 @@ void AIPlayerSetAlienBuilderPrimaryTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task { if (Task->TaskType == TASK_BUILD && Task->StructureType == MissingStructure) { return; } + int MaxChambersInOnePlace = (MissingStructure == STRUCTURE_ALIEN_DEFENCECHAMBER) ? 3 : 1; + vector AllHives = AITAC_GetAllHives(); + vector AllNodes = AITAC_GetAllResourceNodes(); DeployableSearchFilter ResNodeFilter; ResNodeFilter.DeployableTeam = BotTeam; ResNodeFilter.ReachabilityTeam = BotTeam; ResNodeFilter.ReachabilityFlags = pBot->BotNavInfo.NavProfile.ReachabilityFlag; - AvHAIResourceNode* NearestNode = AITAC_FindNearestResourceNodeToLocation(pBot->Edict->v.origin, &ResNodeFilter); - Vector BuildOrigin = ZERO_VECTOR; + DeployableSearchFilter ExistingChamberFilter; + ExistingChamberFilter.DeployableTeam = BotTeam; + ExistingChamberFilter.DeployableTypes = MissingStructure; + ExistingChamberFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(10.0f); + float MinDist = 0.0f; for (auto it = AllHives.begin(); it != AllHives.end(); it++) @@ -6157,6 +6163,14 @@ void AIPlayerSetAlienBuilderPrimaryTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task if (ThisHive->OwningTeam != BotTeam) { continue; } + if (AITAC_GetNumDeployablesNearLocation(ThisHive->FloorLocation, &ExistingChamberFilter) >= MaxChambersInOnePlace) { continue; } + + if (MaxChambersInOnePlace == 1) + { + AvHAIPlayer* ExistingBuilder = GetFirstBotWithBuildTask(BotTeam, MissingStructure, pBot->Edict); + if (ExistingBuilder && vDist2DSq(ExistingBuilder->PrimaryBotTask.TaskLocation, ThisHive->FloorLocation) < sqrf(UTIL_MetresToGoldSrcUnits(10.0f))) { continue; } + } + float ThisDist = vDist2DSq(pBot->Edict->v.origin, ThisHive->FloorLocation); if (vIsZero(BuildOrigin) || ThisDist < MinDist) @@ -6166,13 +6180,26 @@ void AIPlayerSetAlienBuilderPrimaryTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task } } - if (NearestNode) + for (auto it = AllNodes.begin(); it != AllNodes.end(); it++) { - float ThisDist = vDist2DSq(pBot->Edict->v.origin, NearestNode->Location); + AvHAIResourceNode* ThisNode = (*it); + + if (ThisNode->OwningTeam == EnemyTeam) { continue; } + + if (AITAC_GetNumDeployablesNearLocation(ThisNode->Location, &ExistingChamberFilter) >= MaxChambersInOnePlace) { continue; } + + if (MaxChambersInOnePlace == 1) + { + AvHAIPlayer* ExistingBuilder = GetFirstBotWithBuildTask(BotTeam, MissingStructure, pBot->Edict); + if (ExistingBuilder && vDist2DSq(ExistingBuilder->PrimaryBotTask.TaskLocation, ThisNode->Location) < sqrf(UTIL_MetresToGoldSrcUnits(10.0f))) { continue; } + } + + float ThisDist = vDist2DSq(pBot->Edict->v.origin, ThisNode->Location); if (vIsZero(BuildOrigin) || ThisDist < MinDist) { - BuildOrigin = NearestNode->Location; + BuildOrigin = ThisNode->Location; + MinDist = ThisDist; } } diff --git a/main/source/mod/AvHAIPlayerManager.cpp b/main/source/mod/AvHAIPlayerManager.cpp index cf9b33d8..055199df 100644 --- a/main/source/mod/AvHAIPlayerManager.cpp +++ b/main/source/mod/AvHAIPlayerManager.cpp @@ -929,9 +929,12 @@ void AIMGR_ResetRound() bool bTileCacheFullyUpdated = UTIL_UpdateTileCache(); - while (!bTileCacheFullyUpdated) + int NumAttempts = 0; + + while (!bTileCacheFullyUpdated && NumAttempts < 30) { bTileCacheFullyUpdated = UTIL_UpdateTileCache(); + NumAttempts++; } bHasRoundStarted = false; @@ -1437,9 +1440,12 @@ void AIMGR_OnBotEnabled() bool bTileCacheFullyUpdated = UTIL_UpdateTileCache(); - while (!bTileCacheFullyUpdated) + int NumAttempts = 0; + + while (!bTileCacheFullyUpdated && NumAttempts < 30) { bTileCacheFullyUpdated = UTIL_UpdateTileCache(); + NumAttempts++; } } // Figure out the current game status diff --git a/main/source/mod/AvHAIPlayerUtil.cpp b/main/source/mod/AvHAIPlayerUtil.cpp index 550e78aa..6da57123 100644 --- a/main/source/mod/AvHAIPlayerUtil.cpp +++ b/main/source/mod/AvHAIPlayerUtil.cpp @@ -996,6 +996,13 @@ Vector UTIL_GetNearestSurfaceNormal(Vector SearchLocation) return ClosestNormal; } +bool UTIL_QuickCollisionTrace(Vector StartTrace, Vector EndTrace) +{ + trace_t TraceResult; + NS_TraceLine(StartTrace, EndTrace, 0, PM_WORLD_ONLY, -1, true, TraceResult); + return TraceResult.fraction >= 1.0f; +} + Vector UTIL_GetLadderNormal(Vector SearchLocation, edict_t* Ladder) { if (FNullEnt(Ladder)) { return ZERO_VECTOR; } diff --git a/main/source/mod/AvHAIPlayerUtil.h b/main/source/mod/AvHAIPlayerUtil.h index ce30893a..41b0c781 100644 --- a/main/source/mod/AvHAIPlayerUtil.h +++ b/main/source/mod/AvHAIPlayerUtil.h @@ -174,6 +174,8 @@ Vector UTIL_GetNearestLadderBottomPoint(edict_t* pEdict); Vector UTIL_GetLadderNormal(Vector SearchLocation, edict_t* Ladder); +bool UTIL_QuickCollisionTrace(Vector StartTrace, Vector EndTrace); + Vector UTIL_GetNearestSurfaceNormal(Vector SearchLocation); #endif \ No newline at end of file diff --git a/main/source/mod/AvHAITactical.cpp b/main/source/mod/AvHAITactical.cpp index 2b521a0c..087d2e14 100644 --- a/main/source/mod/AvHAITactical.cpp +++ b/main/source/mod/AvHAITactical.cpp @@ -2938,9 +2938,12 @@ void AITAC_ClearMapAIData(bool bInitialMapLoad) AITAC_ClearStructureNavData(); - while (!bTileCacheUpToDate) + int NumAttempts = 0; + + while (!bTileCacheUpToDate && NumAttempts < 30) { UTIL_UpdateTileCache(); + NumAttempts++; } } else