From c86ad4ebf41e8aecdecb8e2a387f1564630ab39d Mon Sep 17 00:00:00 2001 From: RGreenlees Date: Mon, 1 Jul 2024 15:45:38 +0100 Subject: [PATCH] Further bot improvements * Fixed nav meshes for lost and machina which could get bots stuck * Improved ladder usage, fixed edge cases where bots could get stuck * At match start, aliens will attempt to spread chambers out if the first chamber is MC or SC, rather than clustering them all at the starting hive * Eliminated potential freeze issues with nav mesh refreshes --- main/navmeshes/ns_lost.nav | Bin 1380657 -> 1380489 bytes main/navmeshes/ns_machina.nav | Bin 2409663 -> 2409249 bytes main/navmeshes/ns_tanith.nav | Bin 1613137 -> 1613137 bytes main/source/mod/AvHAICommander.cpp | 29 ++-- main/source/mod/AvHAINavigation.cpp | 198 ++++++++++++++----------- main/source/mod/AvHAIPlayer.cpp | 37 ++++- main/source/mod/AvHAIPlayerManager.cpp | 10 +- main/source/mod/AvHAIPlayerUtil.cpp | 7 + main/source/mod/AvHAIPlayerUtil.h | 2 + main/source/mod/AvHAITactical.cpp | 5 +- 10 files changed, 184 insertions(+), 104 deletions(-) diff --git a/main/navmeshes/ns_lost.nav b/main/navmeshes/ns_lost.nav index caebb49a43de10bd5d34446fe252d43f65770f24..4a23574479117a3f6e55654eaa7a090c88d4ac87 100644 GIT binary patch delta 294 zcmdnED5P^?$OaWgv84fz8LJZ>#P&)c9Z!TEX_a};AgIR&{3P8-jz{tQk-R`o8xF92x f3!*^UnYM4bD)QTk+wmL7fX547ry?7&w5mC8sEZ8i?j=wqk6zVgz9(AZ7+)79eH?Vm2UV z2VxE&<^*CcAm#>Q9w6ogVm=_|2Vwyr76f7;AQs+k#VB(9l4khCnx+6%7qrzOU@rk?TkMgcv9Vc`q6H)m)4~p9OMtWj zF$hQkG23*zw<6-=5{`>q{B$Z^0`DjsHI-NeHtyI=h3Pd{L=>lcUJ;Q1yKVXHMJ^VS zl`c-~ibrn>LM#=qhgbwMlnG=i5O7ZK1G6I_{6({Y2KKo;`6Dx3KtQw- E06Ys|+5i9m diff --git a/main/navmeshes/ns_machina.nav b/main/navmeshes/ns_machina.nav index 65f6d0f4613d747f157e6b9c8ab2ed5e9a333c17..a20c668b6fe9e3bd3cad5b2f60d8fcf64cccbacf 100644 GIT binary patch delta 6878 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 D!*>^Q diff --git a/main/navmeshes/ns_tanith.nav b/main/navmeshes/ns_tanith.nav index 7dfba37b6b76f4c48633d6f99979682d2ffa6812..4b3b4d19999f1f9135772431c1075ae930a53f06 100644 GIT binary patch delta 109 zcmcb(E9v5{q=pv87N!>F7M2#)7Pc1l7LFFq7OocV7M>Q~7QPn#7J(MQ7NHj57LgXw z7O@ubEfRu>jEvKT5+#Be8Mmh;O58UR|L45Lg@NJ3;nMbFF82SIg4u^Ej!%!7B4NqM Lw0+tXiQOCk2Y@Ej delta 109 zcmcb(E9v5{q=pv87N!>F7M2#)7Pc1l7LFFq7OocV7M>Q~7QPn#7J(MQ7NHj57LgXw z7O@ubEfRu>j7-yo5+#BenYO1TO58URf7`mug@NJ3;h!u=U0N?}2D5)%IWj$Fii9O2 MPlayer->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