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
This commit is contained in:
RGreenlees 2024-07-01 15:45:38 +01:00 committed by pierow
parent b1bcdd2f70
commit cea65c1fdc
10 changed files with 184 additions and 104 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -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))
{

View file

@ -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)
{

View file

@ -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<AvHAIHiveDefinition*> AllHives = AITAC_GetAllHives();
vector<AvHAIResourceNode*> 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;
}
}

View file

@ -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

View file

@ -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; }

View file

@ -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

View file

@ -2938,9 +2938,12 @@ void AITAC_ClearMapAIData(bool bInitialMapLoad)
AITAC_ClearStructureNavData();
while (!bTileCacheUpToDate)
int NumAttempts = 0;
while (!bTileCacheUpToDate && NumAttempts < 30)
{
UTIL_UpdateTileCache();
NumAttempts++;
}
}
else