mirror of
https://github.com/ENSL/NS.git
synced 2025-04-21 00:41:10 +00:00
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:
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.
|
@ -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))
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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
|
|
@ -2938,9 +2938,12 @@ void AITAC_ClearMapAIData(bool bInitialMapLoad)
|
|||
|
||||
AITAC_ClearStructureNavData();
|
||||
|
||||
while (!bTileCacheUpToDate)
|
||||
int NumAttempts = 0;
|
||||
|
||||
while (!bTileCacheUpToDate && NumAttempts < 30)
|
||||
{
|
||||
UTIL_UpdateTileCache();
|
||||
NumAttempts++;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
Loading…
Reference in a new issue