mirror of
https://github.com/ENSL/NS.git
synced 2024-11-24 21:41:17 +00:00
Potential crash fix
* Hopefully fixed rare crash in the Detour library * Improved bot retreat thought process * Fixed potential bot stuck when trying to evolve * Aliens will now also see and track enemies marked by OC / scent of fear * Updated some nav meshes
This commit is contained in:
parent
cea65c1fdc
commit
be1aead879
12 changed files with 45 additions and 542 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -2025,410 +2025,6 @@ const AvHAIResourceNode* AICOMM_GetNearestResourceNodeCapOpportunity(const AvHTe
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AICOMM_PerformNextSiegeHiveAction(AvHAIPlayer* pBot, const AvHAIHiveDefinition* HiveToSiege)
|
|
||||||
{
|
|
||||||
AvHTeamNumber CommanderTeam = pBot->Player->GetTeam();
|
|
||||||
|
|
||||||
DeployableSearchFilter StructureFilter;
|
|
||||||
StructureFilter.DeployableTeam = CommanderTeam;
|
|
||||||
StructureFilter.ReachabilityFlags = AI_REACHABILITY_MARINE;
|
|
||||||
StructureFilter.ReachabilityTeam = CommanderTeam;
|
|
||||||
StructureFilter.ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING;
|
|
||||||
|
|
||||||
StructureFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(25.0f);
|
|
||||||
|
|
||||||
Vector SiegeLocation = ZERO_VECTOR;
|
|
||||||
|
|
||||||
StructureFilter.DeployableTypes = STRUCTURE_MARINE_PHASEGATE;
|
|
||||||
AvHAIBuildableStructure ExistingPG = AITAC_FindClosestDeployableToLocation(HiveToSiege->Location, &StructureFilter);
|
|
||||||
|
|
||||||
StructureFilter.DeployableTypes = (STRUCTURE_MARINE_TURRETFACTORY | STRUCTURE_MARINE_ADVTURRETFACTORY);
|
|
||||||
AvHAIBuildableStructure ExistingTF = AITAC_FindClosestDeployableToLocation(HiveToSiege->Location, &StructureFilter);
|
|
||||||
|
|
||||||
StructureFilter.DeployableTypes = (STRUCTURE_MARINE_ARMOURY | STRUCTURE_MARINE_ADVARMOURY);
|
|
||||||
AvHAIBuildableStructure ExistingArmoury = AITAC_FindClosestDeployableToLocation(HiveToSiege->Location, &StructureFilter);
|
|
||||||
|
|
||||||
edict_t* NearestBuilder = nullptr;
|
|
||||||
|
|
||||||
// We only build one of these at a time, so we don't drop a bunch of structures and then our intrepid sieger gets killed and the aliens nom them all
|
|
||||||
if (ExistingPG.IsValid())
|
|
||||||
{
|
|
||||||
if (ExistingPG.IsCompleted())
|
|
||||||
{
|
|
||||||
SiegeLocation = ExistingPG.Location;
|
|
||||||
NearestBuilder = AITAC_GetClosestPlayerOnTeamWithLOS(CommanderTeam, ExistingPG.Location, UTIL_MetresToGoldSrcUnits(5.0f), pBot->Edict);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Don't do anything else until we've finished building the phase gate
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ExistingTF.IsValid())
|
|
||||||
{
|
|
||||||
if (ExistingTF.IsCompleted())
|
|
||||||
{
|
|
||||||
if (vIsZero(SiegeLocation))
|
|
||||||
{
|
|
||||||
SiegeLocation = ExistingTF.Location;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FNullEnt(NearestBuilder))
|
|
||||||
{
|
|
||||||
NearestBuilder = AITAC_GetClosestPlayerOnTeamWithLOS(CommanderTeam, ExistingTF.Location, UTIL_MetresToGoldSrcUnits(5.0f), pBot->Edict);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Don't do anything else until we've finished building the turret factory
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (FNullEnt(NearestBuilder))
|
|
||||||
{
|
|
||||||
NearestBuilder = AITAC_GetNearestHiddenPlayerInLocation(CommanderTeam, HiveToSiege->Location, UTIL_MetresToGoldSrcUnits(20.0f));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FNullEnt(NearestBuilder)) { return false; }
|
|
||||||
|
|
||||||
bool bPhaseGatesAvailable = AITAC_PhaseGatesAvailable(CommanderTeam);
|
|
||||||
|
|
||||||
if (vIsZero(SiegeLocation))
|
|
||||||
{
|
|
||||||
SiegeLocation = NearestBuilder->v.origin;
|
|
||||||
}
|
|
||||||
|
|
||||||
AvHAIDeployableStructureType NextStructure = STRUCTURE_NONE;
|
|
||||||
|
|
||||||
if (!ExistingPG.IsValid() && bPhaseGatesAvailable)
|
|
||||||
{
|
|
||||||
NextStructure = STRUCTURE_MARINE_PHASEGATE;
|
|
||||||
}
|
|
||||||
else if (!ExistingTF.IsValid())
|
|
||||||
{
|
|
||||||
NextStructure = STRUCTURE_MARINE_TURRETFACTORY;
|
|
||||||
}
|
|
||||||
else if (!ExistingArmoury.IsValid())
|
|
||||||
{
|
|
||||||
NextStructure = STRUCTURE_MARINE_ARMOURY;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NextStructure != STRUCTURE_NONE)
|
|
||||||
{
|
|
||||||
Vector NextBuildPosition = UTIL_GetRandomPointOnNavmeshInRadius(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), SiegeLocation, UTIL_MetresToGoldSrcUnits(3.0f));
|
|
||||||
|
|
||||||
if (!vIsZero(NextBuildPosition) && vDist2DSq(NextBuildPosition, HiveToSiege->Location) < sqrf(UTIL_MetresToGoldSrcUnits(22.0f)))
|
|
||||||
{
|
|
||||||
AvHAIBuildableStructure* DeployedStructure = AICOMM_DeployStructure(pBot, NextStructure, NextBuildPosition, STRUCTURE_PURPOSE_SIEGE);
|
|
||||||
|
|
||||||
if (DeployedStructure) { return true; }
|
|
||||||
}
|
|
||||||
|
|
||||||
NextBuildPosition = UTIL_GetRandomPointOnNavmeshInRadiusIgnoreReachability(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), SiegeLocation, UTIL_MetresToGoldSrcUnits(5.0f));
|
|
||||||
|
|
||||||
if (!vIsZero(NextBuildPosition) && vDist2DSq(NextBuildPosition, HiveToSiege->Location) < sqrf(UTIL_MetresToGoldSrcUnits(22.0f)))
|
|
||||||
{
|
|
||||||
AvHAIBuildableStructure* DeployedStructure = AICOMM_DeployStructure(pBot, NextStructure, NextBuildPosition, STRUCTURE_PURPOSE_SIEGE);
|
|
||||||
|
|
||||||
if (DeployedStructure) { return true; }
|
|
||||||
}
|
|
||||||
|
|
||||||
NextBuildPosition = UTIL_GetRandomPointOnNavmeshInRadius(GetBaseNavProfile(MARINE_BASE_NAV_PROFILE), SiegeLocation, UTIL_MetresToGoldSrcUnits(5.0f));
|
|
||||||
|
|
||||||
if (!vIsZero(NextBuildPosition) && vDist2DSq(NextBuildPosition, HiveToSiege->Location) < sqrf(UTIL_MetresToGoldSrcUnits(22.0f)))
|
|
||||||
{
|
|
||||||
AvHAIBuildableStructure* DeployedStructure = AICOMM_DeployStructure(pBot, NextStructure, NextBuildPosition, STRUCTURE_PURPOSE_SIEGE);
|
|
||||||
|
|
||||||
if (DeployedStructure) { return true; }
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ExistingTF.IsValid()) { return false; }
|
|
||||||
|
|
||||||
if ((ExistingTF.StructureStatusFlags & STRUCTURE_STATUS_RESEARCHING)) { return false; }
|
|
||||||
|
|
||||||
if (ExistingTF.StructureType != STRUCTURE_MARINE_ADVTURRETFACTORY)
|
|
||||||
{
|
|
||||||
return AICOMM_UpgradeStructure(pBot, &ExistingTF);
|
|
||||||
}
|
|
||||||
|
|
||||||
StructureFilter.DeployableTypes = STRUCTURE_MARINE_SIEGETURRET;
|
|
||||||
StructureFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(5.0f);
|
|
||||||
|
|
||||||
int NumSiegeTurrets = AITAC_GetNumDeployablesNearLocation(ExistingTF.Location, &StructureFilter);
|
|
||||||
|
|
||||||
if (NumSiegeTurrets == 0 || (NumSiegeTurrets < 3 && UTIL_IsStructureElectrified(ExistingTF.edict)))
|
|
||||||
{
|
|
||||||
Vector NextBuildPosition = UTIL_GetRandomPointOnNavmeshInRadius(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), ExistingTF.Location, UTIL_MetresToGoldSrcUnits(5.0f));
|
|
||||||
|
|
||||||
if (!vIsZero(NextBuildPosition) && vDist2DSq(NextBuildPosition, HiveToSiege->Location) <= sqrf(BALANCE_VAR(kSiegeTurretRange)))
|
|
||||||
{
|
|
||||||
AvHAIBuildableStructure* DeployedStructure = AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_SIEGETURRET, NextBuildPosition, STRUCTURE_PURPOSE_SIEGE);
|
|
||||||
|
|
||||||
if (DeployedStructure) { return true; }
|
|
||||||
}
|
|
||||||
|
|
||||||
NextBuildPosition = UTIL_GetRandomPointOnNavmeshInRadiusIgnoreReachability(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), ExistingTF.Location, UTIL_MetresToGoldSrcUnits(5.0f));
|
|
||||||
|
|
||||||
if (!vIsZero(NextBuildPosition) && vDist2DSq(NextBuildPosition, HiveToSiege->Location) <= sqrf(BALANCE_VAR(kSiegeTurretRange)))
|
|
||||||
{
|
|
||||||
AvHAIBuildableStructure* DeployedStructure = AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_SIEGETURRET, NextBuildPosition, STRUCTURE_PURPOSE_SIEGE);
|
|
||||||
|
|
||||||
if (DeployedStructure) { return true; }
|
|
||||||
}
|
|
||||||
|
|
||||||
NextBuildPosition = UTIL_GetRandomPointOnNavmeshInRadius(GetBaseNavProfile(MARINE_BASE_NAV_PROFILE), ExistingTF.Location, UTIL_MetresToGoldSrcUnits(5.0f));
|
|
||||||
|
|
||||||
if (!vIsZero(NextBuildPosition) && vDist2DSq(NextBuildPosition, HiveToSiege->Location) <= sqrf(BALANCE_VAR(kSiegeTurretRange)))
|
|
||||||
{
|
|
||||||
AvHAIBuildableStructure* DeployedStructure = AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_SIEGETURRET, NextBuildPosition, STRUCTURE_PURPOSE_SIEGE);
|
|
||||||
|
|
||||||
if (DeployedStructure) { return true; }
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!UTIL_IsStructureElectrified(ExistingTF.edict))
|
|
||||||
{
|
|
||||||
return AICOMM_ResearchTech(pBot, &ExistingTF, RESEARCH_ELECTRICAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AICOMM_PerformNextSecureHiveAction(AvHAIPlayer* pBot, const AvHAIHiveDefinition* HiveToSecure)
|
|
||||||
{
|
|
||||||
DeployableSearchFilter StructureFilter;
|
|
||||||
StructureFilter.DeployableTypes = STRUCTURE_MARINE_TURRETFACTORY | STRUCTURE_MARINE_ADVTURRETFACTORY | STRUCTURE_MARINE_PHASEGATE;
|
|
||||||
StructureFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(15.0f);
|
|
||||||
StructureFilter.DeployableTeam = pBot->Player->GetTeam();
|
|
||||||
StructureFilter.ReachabilityFlags = AI_REACHABILITY_MARINE;
|
|
||||||
StructureFilter.ReachabilityTeam = pBot->Player->GetTeam();
|
|
||||||
StructureFilter.ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING;
|
|
||||||
|
|
||||||
AvHAIBuildableStructure ExistingStructure = AITAC_FindClosestDeployableToLocation(HiveToSecure->FloorLocation, &StructureFilter);
|
|
||||||
AvHAIBuildableStructure ExistingPG;
|
|
||||||
AvHAIBuildableStructure ExistingTF;
|
|
||||||
|
|
||||||
Vector OutpostLocation = (ExistingStructure.IsValid() && (ExistingStructure.Purpose == STRUCTURE_PURPOSE_FORTIFY || ExistingStructure.Purpose == STRUCTURE_PURPOSE_BASE)) ? ExistingStructure.Location : HiveToSecure->FloorLocation;
|
|
||||||
|
|
||||||
if (HiveToSecure->HiveResNodeRef && HiveToSecure->HiveResNodeRef->OwningTeam == TEAM_IND)
|
|
||||||
{
|
|
||||||
AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_RESTOWER, HiveToSecure->HiveResNodeRef->Location);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ExistingStructure.IsValid())
|
|
||||||
{
|
|
||||||
if (ExistingStructure.StructureType == STRUCTURE_MARINE_PHASEGATE)
|
|
||||||
{
|
|
||||||
ExistingPG = ExistingStructure;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ExistingTF = ExistingStructure;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (AITAC_PhaseGatesAvailable(pBot->Player->GetTeam()))
|
|
||||||
{
|
|
||||||
if (!ExistingPG.IsValid())
|
|
||||||
{
|
|
||||||
StructureFilter.DeployableTypes = STRUCTURE_MARINE_PHASEGATE;
|
|
||||||
|
|
||||||
ExistingPG = AITAC_FindClosestDeployableToLocation(OutpostLocation, &StructureFilter);
|
|
||||||
|
|
||||||
if (!ExistingPG.IsValid())
|
|
||||||
{
|
|
||||||
Vector BuildLocation = UTIL_GetRandomPointOnNavmeshInRadius(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), OutpostLocation, UTIL_MetresToGoldSrcUnits(5.0f));
|
|
||||||
|
|
||||||
if (!vIsZero(BuildLocation))
|
|
||||||
{
|
|
||||||
AvHAIBuildableStructure* DeployedStructure = AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_PHASEGATE, BuildLocation, STRUCTURE_PURPOSE_FORTIFY);
|
|
||||||
|
|
||||||
if (DeployedStructure) { return true; }
|
|
||||||
}
|
|
||||||
|
|
||||||
BuildLocation = UTIL_GetRandomPointOnNavmeshInRadiusIgnoreReachability(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), OutpostLocation, UTIL_MetresToGoldSrcUnits(5.0f));
|
|
||||||
|
|
||||||
if (!vIsZero(BuildLocation))
|
|
||||||
{
|
|
||||||
AvHAIBuildableStructure* DeployedStructure = AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_PHASEGATE, BuildLocation, STRUCTURE_PURPOSE_FORTIFY);
|
|
||||||
|
|
||||||
if (DeployedStructure) { return true; }
|
|
||||||
}
|
|
||||||
|
|
||||||
BuildLocation = UTIL_GetRandomPointOnNavmeshInRadiusIgnoreReachability(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), HiveToSecure->FloorLocation, UTIL_MetresToGoldSrcUnits(5.0f));
|
|
||||||
|
|
||||||
if (!vIsZero(BuildLocation))
|
|
||||||
{
|
|
||||||
AvHAIBuildableStructure* DeployedStructure = AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_PHASEGATE, BuildLocation, STRUCTURE_PURPOSE_FORTIFY);
|
|
||||||
|
|
||||||
if (DeployedStructure) { return true; }
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ExistingTF.IsValid())
|
|
||||||
{
|
|
||||||
StructureFilter.DeployableTypes = STRUCTURE_MARINE_TURRETFACTORY;
|
|
||||||
|
|
||||||
ExistingTF = AITAC_FindClosestDeployableToLocation(OutpostLocation, &StructureFilter);
|
|
||||||
|
|
||||||
if (!ExistingTF.IsValid())
|
|
||||||
{
|
|
||||||
// First, try and put the TF near any existing phasegate (if it exists)
|
|
||||||
Vector BuildLocation = UTIL_GetRandomPointOnNavmeshInRadius(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), OutpostLocation, UTIL_MetresToGoldSrcUnits(3.0f));
|
|
||||||
|
|
||||||
if (!vIsZero(BuildLocation))
|
|
||||||
{
|
|
||||||
AvHAIBuildableStructure* DeployedStructure = AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_TURRETFACTORY, BuildLocation, STRUCTURE_PURPOSE_FORTIFY);
|
|
||||||
|
|
||||||
if (DeployedStructure) { return true; }
|
|
||||||
}
|
|
||||||
|
|
||||||
// That failed, now try expanding the radius a bit and ignoring reachability
|
|
||||||
BuildLocation = UTIL_GetRandomPointOnNavmeshInRadiusIgnoreReachability(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), OutpostLocation, UTIL_MetresToGoldSrcUnits(5.0f));
|
|
||||||
|
|
||||||
if (!vIsZero(BuildLocation))
|
|
||||||
{
|
|
||||||
AvHAIBuildableStructure* DeployedStructure = AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_TURRETFACTORY, BuildLocation, STRUCTURE_PURPOSE_FORTIFY);
|
|
||||||
|
|
||||||
if (DeployedStructure) { return true; }
|
|
||||||
}
|
|
||||||
|
|
||||||
// That failed too, try putting it anywhere near the hive location
|
|
||||||
BuildLocation = UTIL_GetRandomPointOnNavmeshInRadiusIgnoreReachability(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), HiveToSecure->FloorLocation, UTIL_MetresToGoldSrcUnits(5.0f));
|
|
||||||
|
|
||||||
if (!vIsZero(BuildLocation))
|
|
||||||
{
|
|
||||||
AvHAIBuildableStructure* DeployedStructure = AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_TURRETFACTORY, BuildLocation, STRUCTURE_PURPOSE_FORTIFY);
|
|
||||||
|
|
||||||
if (DeployedStructure) { return true; }
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
StructureFilter.DeployableTypes = STRUCTURE_MARINE_TURRET;
|
|
||||||
StructureFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(10.0f);
|
|
||||||
|
|
||||||
int NumTurrets = AITAC_GetNumDeployablesNearLocation(ExistingTF.Location, &StructureFilter);
|
|
||||||
|
|
||||||
if (NumTurrets < 5)
|
|
||||||
{
|
|
||||||
Vector BuildLocation = UTIL_GetRandomPointOnNavmeshInRadiusIgnoreReachability(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), ExistingTF.Location, (BALANCE_VAR(kCommandStationBuildDistance) * 0.8f));
|
|
||||||
|
|
||||||
if (!vIsZero(BuildLocation))
|
|
||||||
{
|
|
||||||
AvHAIBuildableStructure* DeployedStructure = AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_TURRET, BuildLocation, STRUCTURE_PURPOSE_FORTIFY);
|
|
||||||
|
|
||||||
if (DeployedStructure) { return true; }
|
|
||||||
}
|
|
||||||
|
|
||||||
BuildLocation = UTIL_GetRandomPointOnNavmeshInRadius(GetBaseNavProfile(MARINE_BASE_NAV_PROFILE), ExistingTF.Location, (BALANCE_VAR(kCommandStationBuildDistance) * 0.8f));
|
|
||||||
|
|
||||||
if (!vIsZero(BuildLocation))
|
|
||||||
{
|
|
||||||
AvHAIBuildableStructure* DeployedStructure = AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_TURRET, BuildLocation, STRUCTURE_PURPOSE_FORTIFY);
|
|
||||||
|
|
||||||
if (DeployedStructure) { return true; }
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AICOMM_BuildInfantryPortal(AvHAIPlayer* pBot, edict_t* CommChair)
|
|
||||||
{
|
|
||||||
if (FNullEnt(CommChair) || !UTIL_StructureIsFullyBuilt(CommChair)) { return false; }
|
|
||||||
|
|
||||||
Vector BuildLocation = AITAC_GetRandomBuildHintInLocation(STRUCTURE_MARINE_INFANTRYPORTAL, CommChair->v.origin, BALANCE_VAR(kCommandStationBuildDistance));
|
|
||||||
|
|
||||||
if (!vIsZero(BuildLocation))
|
|
||||||
{
|
|
||||||
AvHAIBuildableStructure* DeployedStructure = AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_INFANTRYPORTAL, BuildLocation, STRUCTURE_PURPOSE_BASE);
|
|
||||||
|
|
||||||
if (DeployedStructure) { return true; }
|
|
||||||
}
|
|
||||||
|
|
||||||
DeployableSearchFilter ExistingPortalFilter;
|
|
||||||
ExistingPortalFilter.DeployableTypes = STRUCTURE_MARINE_INFANTRYPORTAL;
|
|
||||||
ExistingPortalFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(10.0f);
|
|
||||||
ExistingPortalFilter.DeployableTeam = pBot->Player->GetTeam();
|
|
||||||
ExistingPortalFilter.ReachabilityFlags = AI_REACHABILITY_MARINE;
|
|
||||||
ExistingPortalFilter.ReachabilityTeam = pBot->Player->GetTeam();
|
|
||||||
|
|
||||||
AvHAIBuildableStructure ExistingInfantryPortal = AITAC_FindClosestDeployableToLocation(CommChair->v.origin, &ExistingPortalFilter);
|
|
||||||
|
|
||||||
// First see if we can place the next infantry portal next to the first one
|
|
||||||
if (ExistingInfantryPortal.IsValid())
|
|
||||||
{
|
|
||||||
BuildLocation = UTIL_GetRandomPointOnNavmeshInDonutIgnoreReachability(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), ExistingInfantryPortal.edict->v.origin, UTIL_MetresToGoldSrcUnits(2.0f), UTIL_MetresToGoldSrcUnits(3.0f));
|
|
||||||
|
|
||||||
if (!vIsZero(BuildLocation))
|
|
||||||
{
|
|
||||||
AvHAIBuildableStructure* DeployedStructure = AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_INFANTRYPORTAL, BuildLocation, STRUCTURE_PURPOSE_BASE);
|
|
||||||
|
|
||||||
if (DeployedStructure) { return true; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector SearchPoint = ZERO_VECTOR;
|
|
||||||
|
|
||||||
DeployableSearchFilter ResNodeFilter;
|
|
||||||
ResNodeFilter.ReachabilityFlags = AI_REACHABILITY_MARINE;
|
|
||||||
ResNodeFilter.ReachabilityTeam = pBot->Player->GetTeam();
|
|
||||||
|
|
||||||
const AvHAIResourceNode* ResNode = AITAC_FindNearestResourceNodeToLocation(CommChair->v.origin, &ResNodeFilter);
|
|
||||||
|
|
||||||
if (ResNode)
|
|
||||||
{
|
|
||||||
SearchPoint = ResNode->Location;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector NearestPointToChair = FindClosestNavigablePointToDestination(GetBaseNavProfile(MARINE_BASE_NAV_PROFILE), SearchPoint, CommChair->v.origin, BALANCE_VAR(kCommandStationBuildDistance));
|
|
||||||
|
|
||||||
if (!vIsZero(NearestPointToChair))
|
|
||||||
{
|
|
||||||
float Distance = vDist2D(NearestPointToChair, CommChair->v.origin);
|
|
||||||
float RandomDist = UTIL_MetresToGoldSrcUnits(5.0f) - Distance;
|
|
||||||
|
|
||||||
BuildLocation = UTIL_GetRandomPointOnNavmeshInRadiusIgnoreReachability(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), NearestPointToChair, RandomDist);
|
|
||||||
|
|
||||||
if (!vIsZero(BuildLocation))
|
|
||||||
{
|
|
||||||
AvHAIBuildableStructure* DeployedStructure = AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_INFANTRYPORTAL, BuildLocation, STRUCTURE_PURPOSE_BASE);
|
|
||||||
|
|
||||||
if (DeployedStructure) { return true; }
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
BuildLocation = UTIL_GetRandomPointOnNavmeshInRadiusIgnoreReachability(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), CommChair->v.origin, BALANCE_VAR(kCommandStationBuildDistance));
|
|
||||||
|
|
||||||
if (vIsZero(BuildLocation)) { return false; }
|
|
||||||
|
|
||||||
return AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_INFANTRYPORTAL, BuildLocation, STRUCTURE_PURPOSE_BASE) != nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AICOMM_CheckForNextRecycleAction(AvHAIPlayer* pBot)
|
bool AICOMM_CheckForNextRecycleAction(AvHAIPlayer* pBot)
|
||||||
{
|
{
|
||||||
for (auto it = pBot->Bases.begin(); it != pBot->Bases.end(); it++)
|
for (auto it = pBot->Bases.begin(); it != pBot->Bases.end(); it++)
|
||||||
|
@ -4188,7 +3784,7 @@ void AICOMM_DeployBases(AvHAIPlayer* pBot)
|
||||||
{
|
{
|
||||||
AvHAIMarineBase* ThisBase = &(*baseIt);
|
AvHAIMarineBase* ThisBase = &(*baseIt);
|
||||||
|
|
||||||
if (ThisBase->BaseType == MARINE_BASE_SIEGE && !ThisBase->bRecycleBase)
|
if (ThisBase->BaseType == MARINE_BASE_SIEGE)
|
||||||
{
|
{
|
||||||
if (vDist2DSq(ThisHive->Location, ThisBase->BaseLocation) < sqrf(BALANCE_VAR(kSiegeTurretRange)))
|
if (vDist2DSq(ThisHive->Location, ThisBase->BaseLocation) < sqrf(BALANCE_VAR(kSiegeTurretRange)))
|
||||||
{
|
{
|
||||||
|
@ -4838,119 +4434,6 @@ bool AICOMM_ShouldCommanderRelocate(AvHAIPlayer* pBot)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AICOMM_CheckForNextRelocationAction(AvHAIPlayer* pBot)
|
|
||||||
{
|
|
||||||
AvHTeamNumber BotTeam = pBot->Player->GetTeam();
|
|
||||||
AvHTeamNumber EnemyTeam = AIMGR_GetEnemyTeam(BotTeam);
|
|
||||||
|
|
||||||
Vector RelocationPoint = pBot->RelocationSpot;
|
|
||||||
|
|
||||||
if (vIsZero(RelocationPoint)) { return false; }
|
|
||||||
|
|
||||||
edict_t* CurrentCommChair = AITAC_GetCommChair(BotTeam);
|
|
||||||
|
|
||||||
if (FNullEnt(CurrentCommChair)) { return false; }
|
|
||||||
|
|
||||||
DeployableSearchFilter OrigInfPortalFilter;
|
|
||||||
OrigInfPortalFilter.DeployableTeam = BotTeam;
|
|
||||||
OrigInfPortalFilter.DeployableTypes = STRUCTURE_MARINE_INFANTRYPORTAL;
|
|
||||||
OrigInfPortalFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(5.0f);
|
|
||||||
|
|
||||||
// First ensure we have one infantry portal in our starting location, in case it goes horribly wrong
|
|
||||||
if (!AITAC_DeployableExistsAtLocation(CurrentCommChair->v.origin, &OrigInfPortalFilter))
|
|
||||||
{
|
|
||||||
return AICOMM_BuildInfantryPortal(pBot, CurrentCommChair);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't do anything more if we don't have anyone at the relocation point yet, but we can drop RTs if needed
|
|
||||||
if (AITAC_GetNumPlayersOfTeamInArea(BotTeam, RelocationPoint, UTIL_MetresToGoldSrcUnits(10.0f), false, nullptr, AVH_USER3_COMMANDER_PLAYER) == 0)
|
|
||||||
{
|
|
||||||
const AvHAIResourceNode* CappableNode = AICOMM_GetNearestResourceNodeCapOpportunity(BotTeam, CurrentCommChair->v.origin);
|
|
||||||
|
|
||||||
if (CappableNode)
|
|
||||||
{
|
|
||||||
AvHAIBuildableStructure* DeployedStructure = AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_RESTOWER, CappableNode->Location);
|
|
||||||
|
|
||||||
if (DeployedStructure || pBot->Player->GetResources() <= BALANCE_VAR(kResourceTowerCost) + 10) { return true; }
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
DeployableSearchFilter NewBaseFilter;
|
|
||||||
NewBaseFilter.DeployableTeam = BotTeam;
|
|
||||||
NewBaseFilter.DeployableTypes = STRUCTURE_MARINE_COMMCHAIR;
|
|
||||||
NewBaseFilter.ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING;
|
|
||||||
NewBaseFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(10.0f);
|
|
||||||
|
|
||||||
AvHAIBuildableStructure RelocationCommChair = AITAC_FindClosestDeployableToLocation(RelocationPoint, &NewBaseFilter);
|
|
||||||
|
|
||||||
if (!RelocationCommChair.IsValid())
|
|
||||||
{
|
|
||||||
Vector BuildPoint = AITAC_GetRandomBuildHintInLocation(STRUCTURE_MARINE_COMMCHAIR, pBot->RelocationSpot, UTIL_MetresToGoldSrcUnits(10.0f));
|
|
||||||
|
|
||||||
if (!vIsZero(BuildPoint))
|
|
||||||
{
|
|
||||||
AvHAIBuildableStructure* DeployedStructure = AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_COMMCHAIR, BuildPoint, STRUCTURE_PURPOSE_BASE);
|
|
||||||
|
|
||||||
if (DeployedStructure) { return true; }
|
|
||||||
}
|
|
||||||
|
|
||||||
BuildPoint = UTIL_GetRandomPointOnNavmeshInRadius(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), pBot->RelocationSpot, UTIL_MetresToGoldSrcUnits(2.0f));
|
|
||||||
|
|
||||||
if (!vIsZero(BuildPoint))
|
|
||||||
{
|
|
||||||
AvHAIBuildableStructure* DeployedStructure = AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_COMMCHAIR, BuildPoint, STRUCTURE_PURPOSE_BASE);
|
|
||||||
|
|
||||||
if (DeployedStructure) { return true; }
|
|
||||||
}
|
|
||||||
|
|
||||||
BuildPoint = UTIL_GetRandomPointOnNavmeshInRadius(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), pBot->RelocationSpot, UTIL_MetresToGoldSrcUnits(10.0f));
|
|
||||||
|
|
||||||
if (!vIsZero(BuildPoint))
|
|
||||||
{
|
|
||||||
AvHAIBuildableStructure* DeployedStructure = AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_COMMCHAIR, BuildPoint, STRUCTURE_PURPOSE_BASE);
|
|
||||||
|
|
||||||
if (DeployedStructure) { return true; }
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(RelocationCommChair.StructureStatusFlags & STRUCTURE_STATUS_COMPLETED)) { return false; }
|
|
||||||
|
|
||||||
NewBaseFilter.DeployableTypes = STRUCTURE_MARINE_INFANTRYPORTAL;
|
|
||||||
NewBaseFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(8.0f);
|
|
||||||
NewBaseFilter.IncludeStatusFlags = STRUCTURE_STATUS_NONE;
|
|
||||||
|
|
||||||
int NumInfPortals = AITAC_GetNumDeployablesNearLocation(RelocationCommChair.Location, &NewBaseFilter);
|
|
||||||
|
|
||||||
if (NumInfPortals < 2)
|
|
||||||
{
|
|
||||||
return AICOMM_BuildInfantryPortal(pBot, RelocationCommChair.edict);
|
|
||||||
}
|
|
||||||
|
|
||||||
DeployableSearchFilter OldStuffFilter;
|
|
||||||
OldStuffFilter.DeployableTeam = BotTeam;
|
|
||||||
OldStuffFilter.ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING;
|
|
||||||
OldStuffFilter.DeployableTypes = SEARCH_ALL_STRUCTURES;
|
|
||||||
OldStuffFilter.MinSearchRadius = UTIL_MetresToGoldSrcUnits(20.0f);
|
|
||||||
OldStuffFilter.PurposeFlags = STRUCTURE_PURPOSE_BASE;
|
|
||||||
|
|
||||||
vector<AvHAIBuildableStructure> OldBaseStructures = AITAC_FindAllDeployables(pBot->RelocationSpot, &OldStuffFilter);
|
|
||||||
|
|
||||||
for (auto it = OldBaseStructures.begin(); it != OldBaseStructures.end(); it++)
|
|
||||||
{
|
|
||||||
if (it->edict != CurrentCommChair)
|
|
||||||
{
|
|
||||||
return AICOMM_RecycleStructure(pBot, &(*it));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AICOMM_BuildOutBase(AvHAIPlayer* pBot, AvHAIMarineBase* BaseToBuildOut)
|
bool AICOMM_BuildOutBase(AvHAIPlayer* pBot, AvHAIMarineBase* BaseToBuildOut)
|
||||||
{
|
{
|
||||||
if (!pBot || !BaseToBuildOut) { return false; }
|
if (!pBot || !BaseToBuildOut) { return false; }
|
||||||
|
|
|
@ -43,7 +43,6 @@ bool AICOMM_CheckForNextSupportAction(AvHAIPlayer* pBot);
|
||||||
bool AICOMM_CheckForNextRecycleAction(AvHAIPlayer* pBot);
|
bool AICOMM_CheckForNextRecycleAction(AvHAIPlayer* pBot);
|
||||||
bool AICOMM_CheckForNextResearchAction(AvHAIPlayer* pBot);
|
bool AICOMM_CheckForNextResearchAction(AvHAIPlayer* pBot);
|
||||||
bool AICOMM_CheckForNextSupplyAction(AvHAIPlayer* pBot);
|
bool AICOMM_CheckForNextSupplyAction(AvHAIPlayer* pBot);
|
||||||
bool AICOMM_CheckForNextRelocationAction(AvHAIPlayer* pBot);
|
|
||||||
|
|
||||||
Vector AICOMM_GetNextScanLocation(AvHAIPlayer* pBot);
|
Vector AICOMM_GetNextScanLocation(AvHAIPlayer* pBot);
|
||||||
|
|
||||||
|
@ -51,10 +50,6 @@ void AICOMM_CommanderThink(AvHAIPlayer* pBot);
|
||||||
|
|
||||||
const AvHAIHiveDefinition* AICOMM_GetEmptyHiveOpportunityNearestLocation(AvHAIPlayer* CommanderBot, const Vector SearchLocation);
|
const AvHAIHiveDefinition* AICOMM_GetEmptyHiveOpportunityNearestLocation(AvHAIPlayer* CommanderBot, const Vector SearchLocation);
|
||||||
|
|
||||||
bool AICOMM_BuildInfantryPortal(AvHAIPlayer* pBot, edict_t* CommChair);
|
|
||||||
bool AICOMM_PerformNextSiegeHiveAction(AvHAIPlayer* pBot, const AvHAIHiveDefinition* HiveToSiege);
|
|
||||||
bool AICOMM_PerformNextSecureHiveAction(AvHAIPlayer* pBot, const AvHAIHiveDefinition* HiveToSecure);
|
|
||||||
|
|
||||||
ai_commander_request* AICOMM_GetExistingRequestForPlayer(AvHAIPlayer* pBot, edict_t* Requestor);
|
ai_commander_request* AICOMM_GetExistingRequestForPlayer(AvHAIPlayer* pBot, edict_t* Requestor);
|
||||||
void AICOMM_CheckNewRequests(AvHAIPlayer* pBot);
|
void AICOMM_CheckNewRequests(AvHAIPlayer* pBot);
|
||||||
bool AICOMM_IsRequestValid(ai_commander_request* Request);
|
bool AICOMM_IsRequestValid(ai_commander_request* Request);
|
||||||
|
|
|
@ -510,6 +510,11 @@ bool UTIL_UpdateTileCache()
|
||||||
return bTileCacheUpToDate;
|
return bTileCacheUpToDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool UTIL_IsTileCacheUpToDate()
|
||||||
|
{
|
||||||
|
return bTileCacheUpToDate;
|
||||||
|
}
|
||||||
|
|
||||||
Vector UTIL_AdjustPointAwayFromNavWall(const Vector Location, const float MaxDistanceFromWall)
|
Vector UTIL_AdjustPointAwayFromNavWall(const Vector Location, const float MaxDistanceFromWall)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -6865,6 +6870,8 @@ bool MoveTo(AvHAIPlayer* pBot, const Vector Destination, const BotMoveStyle Move
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!UTIL_IsTileCacheUpToDate()) { return true; }
|
||||||
|
|
||||||
nav_status* BotNavInfo = &pBot->BotNavInfo;
|
nav_status* BotNavInfo = &pBot->BotNavInfo;
|
||||||
|
|
||||||
pBot->BotNavInfo.MoveStyle = MoveStyle;
|
pBot->BotNavInfo.MoveStyle = MoveStyle;
|
||||||
|
@ -7060,10 +7067,8 @@ bool MoveTo(AvHAIPlayer* pBot, const Vector Destination, const BotMoveStyle Move
|
||||||
|
|
||||||
Vector FindClosestPointBackOnPath(AvHAIPlayer* pBot, Vector Destination)
|
Vector FindClosestPointBackOnPath(AvHAIPlayer* pBot, Vector Destination)
|
||||||
{
|
{
|
||||||
Vector GeneralMoveDir = UTIL_GetVectorNormal2D(Destination - pBot->Edict->v.origin);
|
|
||||||
Vector CheckDir = pBot->Edict->v.origin + (GeneralMoveDir * 16.0f);
|
|
||||||
|
|
||||||
Vector ValidNavmeshPoint = AdjustPointForPathfinding(CheckDir);
|
Vector ValidNavmeshPoint = AdjustPointForPathfinding(pBot->CollisionHullBottomLocation, pBot->BotNavInfo.NavProfile);
|
||||||
|
|
||||||
if (vIsZero(ValidNavmeshPoint))
|
if (vIsZero(ValidNavmeshPoint))
|
||||||
{
|
{
|
||||||
|
|
|
@ -495,6 +495,8 @@ nav_door* UTIL_GetNavDoorByEdict(const edict_t* DoorEdict);
|
||||||
nav_door* UTIL_GetClosestLiftToPoints(const Vector StartPoint, const Vector EndPoint);
|
nav_door* UTIL_GetClosestLiftToPoints(const Vector StartPoint, const Vector EndPoint);
|
||||||
AvHAIOffMeshConnection* UTIL_GetOffMeshConnectionForLift(nav_door* LiftRef);
|
AvHAIOffMeshConnection* UTIL_GetOffMeshConnectionForLift(nav_door* LiftRef);
|
||||||
|
|
||||||
|
bool UTIL_IsTileCacheUpToDate();
|
||||||
|
|
||||||
Vector UTIL_AdjustPointAwayFromNavWall(const Vector Location, const float MaxDistanceFromWall);
|
Vector UTIL_AdjustPointAwayFromNavWall(const Vector Location, const float MaxDistanceFromWall);
|
||||||
|
|
||||||
void UTIL_PopulateBaseNavProfiles();
|
void UTIL_PopulateBaseNavProfiles();
|
||||||
|
|
|
@ -1460,7 +1460,7 @@ void BotUpdateView(AvHAIPlayer* pBot)
|
||||||
bool bHasLOS = !vIsZero(VisiblePoint);
|
bool bHasLOS = !vIsZero(VisiblePoint);
|
||||||
bool bIsPlayerInvisible = UTIL_IsCloakedPlayerInvisible(pBot->Edict, PlayerRef);
|
bool bIsPlayerInvisible = UTIL_IsCloakedPlayerInvisible(pBot->Edict, PlayerRef);
|
||||||
|
|
||||||
bool bIsTracked = PlayerRef->GetOpacity() > 0.1f && (!bHasLOS && (IsPlayerParasited(PlayerEdict) || (GetHasUpgrade(pBot->Edict->v.iuser4, MASK_UPGRADE_8) && IsPlayerMotionTracked(PlayerEdict))));
|
bool bIsTracked = PlayerRef->GetOpacity() > 0.1f && (!bHasLOS && (IsPlayerParasited(PlayerEdict) || IsPlayerSOF(PlayerEdict) || (GetHasUpgrade(pBot->Edict->v.iuser4, MASK_UPGRADE_8) && IsPlayerMotionTracked(PlayerEdict))));
|
||||||
|
|
||||||
TrackingInfo->bHasLOS = bHasLOS;
|
TrackingInfo->bHasLOS = bHasLOS;
|
||||||
TrackingInfo->bEnemyHasLOS = bEnemyCanSee;
|
TrackingInfo->bEnemyHasLOS = bEnemyCanSee;
|
||||||
|
@ -1739,7 +1739,7 @@ void StartNewBotFrame(AvHAIPlayer* pBot)
|
||||||
|
|
||||||
Vector ProjectPoint = (IsPlayerLerk(pBot->Edict)) ? pBot->CurrentFloorPosition : pBot->CollisionHullBottomLocation;
|
Vector ProjectPoint = (IsPlayerLerk(pBot->Edict)) ? pBot->CurrentFloorPosition : pBot->CollisionHullBottomLocation;
|
||||||
|
|
||||||
if (vDist3DSq(pBot->BotNavInfo.LastNavMeshCheckPosition, ProjectPoint) > sqrf(16.0f))
|
if (UTIL_IsTileCacheUpToDate() && vDist3DSq(pBot->BotNavInfo.LastNavMeshCheckPosition, ProjectPoint) > sqrf(16.0f))
|
||||||
{
|
{
|
||||||
if (UTIL_PointIsReachable(pBot->BotNavInfo.NavProfile, AITAC_GetTeamStartingLocation(pBot->Player->GetTeam()), ProjectPoint, 16.0f))
|
if (UTIL_PointIsReachable(pBot->BotNavInfo.NavProfile, AITAC_GetTeamStartingLocation(pBot->Player->GetTeam()), ProjectPoint, 16.0f))
|
||||||
{
|
{
|
||||||
|
@ -1748,7 +1748,6 @@ void StartNewBotFrame(AvHAIPlayer* pBot)
|
||||||
|
|
||||||
pBot->BotNavInfo.LastNavMeshPosition = NavPoint;
|
pBot->BotNavInfo.LastNavMeshPosition = NavPoint;
|
||||||
|
|
||||||
|
|
||||||
if (pBot->BotNavInfo.IsOnGround || IsPlayerLerk(pBot->Edict))
|
if (pBot->BotNavInfo.IsOnGround || IsPlayerLerk(pBot->Edict))
|
||||||
{
|
{
|
||||||
Vector ForwardVector = UTIL_GetForwardVector2D(pBot->Edict->v.angles);
|
Vector ForwardVector = UTIL_GetForwardVector2D(pBot->Edict->v.angles);
|
||||||
|
@ -3027,7 +3026,7 @@ void AIPlayerNSMarineThink(AvHAIPlayer* pBot)
|
||||||
if (MarineCombatThink(pBot)) { return; }
|
if (MarineCombatThink(pBot)) { return; }
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gpGlobals->time >= pBot->BotNextTaskEvaluationTime)
|
if (UTIL_IsTileCacheUpToDate() && gpGlobals->time >= pBot->BotNextTaskEvaluationTime)
|
||||||
{
|
{
|
||||||
pBot->BotNextTaskEvaluationTime = gpGlobals->time + frandrange(0.2f, 0.5f);
|
pBot->BotNextTaskEvaluationTime = gpGlobals->time + frandrange(0.2f, 0.5f);
|
||||||
|
|
||||||
|
@ -7734,6 +7733,8 @@ bool SkulkCombatThink(AvHAIPlayer* pBot)
|
||||||
|
|
||||||
float DistToEnemy = vDist2DSq(pBot->Edict->v.origin, TrackedEnemyRef->LastDetectedLocation);
|
float DistToEnemy = vDist2DSq(pBot->Edict->v.origin, TrackedEnemyRef->LastDetectedLocation);
|
||||||
|
|
||||||
|
bool bShouldBreakRetreat = false;
|
||||||
|
|
||||||
if (pBot->CurrentCombatStrategy == COMBAT_STRATEGY_RETREAT)
|
if (pBot->CurrentCombatStrategy == COMBAT_STRATEGY_RETREAT)
|
||||||
{
|
{
|
||||||
edict_t* NearestHealingSource = AITAC_AlienFindNearestHealingSource(pBot->Player->GetTeam(), pBot->Edict->v.origin, pBot->Edict, true);
|
edict_t* NearestHealingSource = AITAC_AlienFindNearestHealingSource(pBot->Player->GetTeam(), pBot->Edict->v.origin, pBot->Edict, true);
|
||||||
|
@ -7777,7 +7778,7 @@ bool SkulkCombatThink(AvHAIPlayer* pBot)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
bShouldBreakRetreat = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool bShouldBreakAmbush = false;
|
bool bShouldBreakAmbush = false;
|
||||||
|
@ -7787,7 +7788,7 @@ bool SkulkCombatThink(AvHAIPlayer* pBot)
|
||||||
bShouldBreakAmbush = DistToEnemy < ((TrackedEnemyRef->bHasLOS) ? sqrf(UTIL_MetresToGoldSrcUnits(5.0f)) : sqrf(UTIL_MetresToGoldSrcUnits(3.0f)));
|
bShouldBreakAmbush = DistToEnemy < ((TrackedEnemyRef->bHasLOS) ? sqrf(UTIL_MetresToGoldSrcUnits(5.0f)) : sqrf(UTIL_MetresToGoldSrcUnits(3.0f)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pBot->CurrentCombatStrategy == COMBAT_STRATEGY_ATTACK || (pBot->CurrentCombatStrategy == COMBAT_STRATEGY_AMBUSH && bShouldBreakAmbush))
|
if (pBot->CurrentCombatStrategy == COMBAT_STRATEGY_ATTACK || bShouldBreakRetreat || (pBot->CurrentCombatStrategy == COMBAT_STRATEGY_AMBUSH && bShouldBreakAmbush))
|
||||||
{
|
{
|
||||||
|
|
||||||
bool bIsCloaked = (UTIL_IsCloakedPlayerInvisible(CurrentEnemy, pBot->Player) || pBot->Player->GetOpacity() < 0.5f);
|
bool bIsCloaked = (UTIL_IsCloakedPlayerInvisible(CurrentEnemy, pBot->Player) || pBot->Player->GetOpacity() < 0.5f);
|
||||||
|
@ -8551,10 +8552,9 @@ bool FadeCombatThink(AvHAIPlayer* pBot)
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the enemy can see the healing source, then we must go on the attack as we're cornered
|
|
||||||
bShouldBreakRetreat = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bShouldBreakRetreat = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool bShouldBreakAmbush = false;
|
bool bShouldBreakAmbush = false;
|
||||||
|
@ -8769,11 +8769,11 @@ bool OnosCombatThink(AvHAIPlayer* pBot)
|
||||||
MoveTo(pBot, UTIL_GetEntityGroundLocation(NearestHealingSource), MOVESTYLE_NORMAL, DesiredDistFromHealingSource);
|
MoveTo(pBot, UTIL_GetEntityGroundLocation(NearestHealingSource), MOVESTYLE_NORMAL, DesiredDistFromHealingSource);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If the enemy can see the healing source, then we must go on the attack
|
// If the enemy can see the healing source, then we must go on the attack
|
||||||
bShouldBreakRetreat = true;
|
bShouldBreakRetreat = true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (pBot->CurrentCombatStrategy == COMBAT_STRATEGY_ATTACK || bShouldBreakRetreat)
|
if (pBot->CurrentCombatStrategy == COMBAT_STRATEGY_ATTACK || bShouldBreakRetreat)
|
||||||
{
|
{
|
||||||
|
|
|
@ -170,6 +170,11 @@ bool IsPlayerMotionTracked(const edict_t* Player)
|
||||||
return (Player->v.iuser4 & MASK_VIS_DETECTED);
|
return (Player->v.iuser4 & MASK_VIS_DETECTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsPlayerSOF(const edict_t* Player)
|
||||||
|
{
|
||||||
|
return (Player->v.iuser4 & MASK_SENSORY_NEARBY);
|
||||||
|
}
|
||||||
|
|
||||||
float GetPlayerEnergy(const edict_t* Player)
|
float GetPlayerEnergy(const edict_t* Player)
|
||||||
{
|
{
|
||||||
return (Player->v.fuser3 * 0.001f);
|
return (Player->v.fuser3 * 0.001f);
|
||||||
|
|
|
@ -67,6 +67,8 @@ bool IsPlayerGestating(const edict_t* Player);
|
||||||
bool IsPlayerParasited(const edict_t* Player);
|
bool IsPlayerParasited(const edict_t* Player);
|
||||||
// Is the player being marked through walls to enemies through being sighted by an ally or affected by motion tracking?
|
// Is the player being marked through walls to enemies through being sighted by an ally or affected by motion tracking?
|
||||||
bool IsPlayerMotionTracked(const edict_t* Player);
|
bool IsPlayerMotionTracked(const edict_t* Player);
|
||||||
|
// Is the player being marked through walls by a nearby sensory chamber or scent of fear?
|
||||||
|
bool IsPlayerSOF(const edict_t* Player);
|
||||||
// Is the player currently on a ladder? Always false for Skulks and Lerks as they can't climb ladders
|
// Is the player currently on a ladder? Always false for Skulks and Lerks as they can't climb ladders
|
||||||
bool IsPlayerOnLadder(const edict_t* Player);
|
bool IsPlayerOnLadder(const edict_t* Player);
|
||||||
// Is the player an onos under the effect of charge?
|
// Is the player an onos under the effect of charge?
|
||||||
|
|
|
@ -5396,6 +5396,8 @@ edict_t* AITAC_AlienFindNearestHealingSource(AvHTeamNumber Team, Vector SearchLo
|
||||||
edict_t* Result = nullptr;
|
edict_t* Result = nullptr;
|
||||||
float MinDist = 0.0f;
|
float MinDist = 0.0f;
|
||||||
|
|
||||||
|
AvHTeamNumber EnemyTeam = AIMGR_GetEnemyTeam(Team);
|
||||||
|
|
||||||
vector<AvHAIHiveDefinition*> AllTeamHives = AITAC_GetAllTeamHives(Team, true);
|
vector<AvHAIHiveDefinition*> AllTeamHives = AITAC_GetAllTeamHives(Team, true);
|
||||||
|
|
||||||
for (auto it = AllTeamHives.begin(); it != AllTeamHives.end(); it++)
|
for (auto it = AllTeamHives.begin(); it != AllTeamHives.end(); it++)
|
||||||
|
@ -5404,6 +5406,8 @@ edict_t* AITAC_AlienFindNearestHealingSource(AvHTeamNumber Team, Vector SearchLo
|
||||||
// Factor healing radius into the distance checks, we don't have to be right at the hive to heal
|
// Factor healing radius into the distance checks, we don't have to be right at the hive to heal
|
||||||
ThisDist -= BALANCE_VAR(kHiveHealRadius) * 0.75f;
|
ThisDist -= BALANCE_VAR(kHiveHealRadius) * 0.75f;
|
||||||
|
|
||||||
|
if (AITAC_AnyPlayerOnTeamHasLOSToLocation(EnemyTeam, (*it)->Location, UTIL_MetresToGoldSrcUnits(30.0f), nullptr)) { continue; }
|
||||||
|
|
||||||
// We're already in healing distance of a hive, that's our healing source
|
// We're already in healing distance of a hive, that's our healing source
|
||||||
if (ThisDist <= 0.0f) { return (*it)->HiveEdict; }
|
if (ThisDist <= 0.0f) { return (*it)->HiveEdict; }
|
||||||
|
|
||||||
|
@ -5429,6 +5433,8 @@ edict_t* AITAC_AlienFindNearestHealingSource(AvHTeamNumber Team, Vector SearchLo
|
||||||
// Factor healing radius into the distance checks, we don't have to be sat on top of the DC to heal
|
// Factor healing radius into the distance checks, we don't have to be sat on top of the DC to heal
|
||||||
ThisDist -= BALANCE_VAR(kHiveHealRadius) * 0.75f;
|
ThisDist -= BALANCE_VAR(kHiveHealRadius) * 0.75f;
|
||||||
|
|
||||||
|
if (AITAC_AnyPlayerOnTeamHasLOSToLocation(EnemyTeam, ThisDC.Location, UTIL_MetresToGoldSrcUnits(30.0f), nullptr)) { continue; }
|
||||||
|
|
||||||
// We're already in healing distance of a DC, that's our healing source
|
// We're already in healing distance of a DC, that's our healing source
|
||||||
if (ThisDist <= 0.0f) { return ThisDC.edict; }
|
if (ThisDist <= 0.0f) { return ThisDC.edict; }
|
||||||
|
|
||||||
|
@ -5445,6 +5451,11 @@ edict_t* AITAC_AlienFindNearestHealingSource(AvHTeamNumber Team, Vector SearchLo
|
||||||
{
|
{
|
||||||
float PlayerSearchDist = (!FNullEnt(Result)) ? MinDist : 0.0f; // As before, we only want players closer than our current "winner"
|
float PlayerSearchDist = (!FNullEnt(Result)) ? MinDist : 0.0f; // As before, we only want players closer than our current "winner"
|
||||||
FriendlyGorge = AITAC_GetNearestPlayerOfClassInArea(Team, SearchLocation, PlayerSearchDist, false, SearchingPlayer, AVH_USER3_ALIEN_PLAYER2);
|
FriendlyGorge = AITAC_GetNearestPlayerOfClassInArea(Team, SearchLocation, PlayerSearchDist, false, SearchingPlayer, AVH_USER3_ALIEN_PLAYER2);
|
||||||
|
|
||||||
|
if (!FNullEnt(FriendlyGorge))
|
||||||
|
{
|
||||||
|
if (AITAC_AnyPlayerOnTeamHasLOSToLocation(EnemyTeam, FriendlyGorge->v.origin, UTIL_MetresToGoldSrcUnits(30.0f), nullptr)) { FriendlyGorge = nullptr; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (!FNullEnt(FriendlyGorge) ? FriendlyGorge : Result);
|
return (!FNullEnt(FriendlyGorge) ? FriendlyGorge : Result);
|
||||||
|
|
|
@ -2108,7 +2108,7 @@ void BotProgressEvolveTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
|
||||||
{
|
{
|
||||||
if (FNullEnt(Task->TaskTarget))
|
if (FNullEnt(Task->TaskTarget))
|
||||||
{
|
{
|
||||||
Task->TaskLocation = FindClosestNavigablePointToDestination(BaseNavProfiles[ONOS_BASE_NAV_PROFILE], AITAC_GetTeamStartingLocation(pBot->Player->GetTeam()), UTIL_GetEntityGroundLocation(Task->TaskTarget), UTIL_MetresToGoldSrcUnits(10.0f));
|
Task->TaskLocation = FindClosestNavigablePointToDestination(BaseNavProfiles[ONOS_BASE_NAV_PROFILE], AITAC_GetTeamStartingLocation(pBot->Player->GetTeam()), pBot->CurrentFloorPosition, UTIL_MetresToGoldSrcUnits(10.0f));
|
||||||
|
|
||||||
if (vIsZero(Task->TaskLocation))
|
if (vIsZero(Task->TaskLocation))
|
||||||
{
|
{
|
||||||
|
@ -2126,11 +2126,11 @@ void BotProgressEvolveTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Task->TaskLocation = FindClosestNavigablePointToDestination(BaseNavProfiles[ONOS_BASE_NAV_PROFILE], pBot->CurrentFloorPosition, UTIL_GetEntityGroundLocation(Task->TaskTarget), UTIL_MetresToGoldSrcUnits(10.0f));
|
Task->TaskLocation = FindClosestNavigablePointToDestination(BaseNavProfiles[ONOS_BASE_NAV_PROFILE], AITAC_GetTeamStartingLocation(pBot->Player->GetTeam()), UTIL_GetEntityGroundLocation(Task->TaskTarget), UTIL_MetresToGoldSrcUnits(10.0f));
|
||||||
|
|
||||||
if (vIsZero(Task->TaskLocation))
|
if (vIsZero(Task->TaskLocation))
|
||||||
{
|
{
|
||||||
Task->TaskLocation = UTIL_GetRandomPointOnNavmeshInRadius(BaseNavProfiles[STRUCTURE_BASE_NAV_PROFILE], Task->TaskLocation, UTIL_MetresToGoldSrcUnits(5.0f));
|
Task->TaskLocation = UTIL_GetRandomPointOnNavmeshInRadius(BaseNavProfiles[STRUCTURE_BASE_NAV_PROFILE], UTIL_GetEntityGroundLocation(Task->TaskTarget), UTIL_MetresToGoldSrcUnits(10.0f));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue