mirror of
https://github.com/ENSL/NS.git
synced 2024-11-10 15:21:54 +00:00
Alien assault AI
This commit is contained in:
parent
ccf180d9a3
commit
f31e2bbf1c
3 changed files with 333 additions and 17 deletions
|
@ -2646,6 +2646,7 @@ void AIPlayerSetAlienBuilderPrimaryTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task
|
|||
void AIPlayerSetAlienCapperPrimaryTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
|
||||
{
|
||||
AvHTeamNumber BotTeam = pBot->Player->GetTeam();
|
||||
AvHTeamNumber EnemyTeam = AIMGR_GetEnemyTeam(BotTeam);
|
||||
|
||||
AvHAIResourceNode* NodeToCap = nullptr;
|
||||
|
||||
|
@ -2675,7 +2676,7 @@ void AIPlayerSetAlienCapperPrimaryTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
|
|||
|
||||
vector<AvHAIResourceNode*> EligibleNodes = AITAC_GetAllMatchingResourceNodes(pBot->Edict->v.origin, &EmptyNodeFilter);
|
||||
|
||||
float MinDist = 0.0f;
|
||||
float MaxDist = 0.0f;
|
||||
|
||||
for (auto it = EligibleNodes.begin(); it != EligibleNodes.end(); it++)
|
||||
{
|
||||
|
@ -2701,12 +2702,12 @@ void AIPlayerSetAlienCapperPrimaryTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
|
|||
|
||||
if (bNodeClaimed) { continue; }
|
||||
|
||||
float ThisDist = vDist2DSq(pBot->Edict->v.origin, ThisNode->Location);
|
||||
float ThisDist = vDist2DSq(AITAC_GetTeamStartingLocation(EnemyTeam), ThisNode->Location);
|
||||
|
||||
if (!NodeToCap || ThisDist < MinDist)
|
||||
if (ThisDist > MaxDist)
|
||||
{
|
||||
NodeToCap = ThisNode;
|
||||
MinDist = ThisDist;
|
||||
MaxDist = ThisDist;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2726,7 +2727,7 @@ void AIPlayerSetAlienCapperPrimaryTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
|
|||
|
||||
vector<AvHAIResourceNode*> EligibleNodes = AITAC_GetAllMatchingResourceNodes(pBot->Edict->v.origin, &EnemyNodeFilter);
|
||||
|
||||
float MinDist = 0.0f;
|
||||
float MaxDist = 0.0f;
|
||||
|
||||
NodeToCap = nullptr;
|
||||
|
||||
|
@ -2752,12 +2753,12 @@ void AIPlayerSetAlienCapperPrimaryTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
|
|||
}
|
||||
}
|
||||
|
||||
float ThisDist = vDist2DSq(ThisNode->Location, AITAC_GetTeamStartingLocation(BotTeam));
|
||||
float ThisDist = vDist2DSq(ThisNode->Location, AITAC_GetTeamStartingLocation(EnemyTeam));
|
||||
|
||||
if (!NodeToCap || ThisDist < MinDist)
|
||||
if (!NodeToCap || ThisDist > MaxDist)
|
||||
{
|
||||
NodeToCap = ThisNode;
|
||||
MinDist = ThisDist;
|
||||
MaxDist = ThisDist;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -2774,6 +2775,238 @@ void AIPlayerSetAlienCapperPrimaryTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
|
|||
|
||||
void AIPlayerSetAlienAssaultPrimaryTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
|
||||
{
|
||||
AvHTeamNumber BotTeam = pBot->Player->GetTeam();
|
||||
AvHTeamNumber EnemyTeam = AIMGR_GetEnemyTeam(BotTeam);
|
||||
|
||||
Vector EnemyBaseLocation = AITAC_GetTeamStartingLocation(EnemyTeam);
|
||||
|
||||
AvHAIHiveDefinition* HiveToGuard = nullptr;
|
||||
AvHAIHiveDefinition* HiveToSecure = nullptr;
|
||||
|
||||
vector<AvHAIHiveDefinition*> AllHives = AITAC_GetAllHives();
|
||||
|
||||
float MaxGuardDist = 0.0f;
|
||||
float MaxSecureDist = 0.0f;
|
||||
|
||||
bool bEnemyIsMarines = (AIMGR_GetTeamType(EnemyTeam) == AVH_CLASS_TYPE_MARINE);
|
||||
|
||||
DeployableSearchFilter EnemyStuffFilter;
|
||||
|
||||
EnemyStuffFilter.DeployableTeam = EnemyTeam;
|
||||
EnemyStuffFilter.ReachabilityTeam = BotTeam;
|
||||
EnemyStuffFilter.ReachabilityFlags = pBot->BotNavInfo.NavProfile.ReachabilityFlag;
|
||||
EnemyStuffFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(15.0f);
|
||||
|
||||
if (bEnemyIsMarines)
|
||||
{
|
||||
EnemyStuffFilter.DeployableTypes = (STRUCTURE_MARINE_PHASEGATE | STRUCTURE_MARINE_TURRETFACTORY | STRUCTURE_MARINE_ADVTURRETFACTORY | STRUCTURE_MARINE_COMMCHAIR);
|
||||
EnemyStuffFilter.ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING;
|
||||
}
|
||||
else
|
||||
{
|
||||
EnemyStuffFilter.DeployableTypes = STRUCTURE_ALIEN_OFFENCECHAMBER;
|
||||
}
|
||||
|
||||
for (auto it = AllHives.begin(); it != AllHives.end(); it++)
|
||||
{
|
||||
AvHAIHiveDefinition* ThisHive = (*it);
|
||||
|
||||
if (ThisHive->OwningTeam != TEAM_IND) { continue; }
|
||||
|
||||
bool bEnemyIsSecuring = AITAC_DeployableExistsAtLocation(ThisHive->FloorLocation, &EnemyStuffFilter);
|
||||
|
||||
if (bEnemyIsSecuring)
|
||||
{
|
||||
float ThisDist = vDist2DSq(ThisHive->FloorLocation, EnemyBaseLocation);
|
||||
|
||||
if (ThisDist > MaxSecureDist)
|
||||
{
|
||||
HiveToSecure = ThisHive;
|
||||
MaxSecureDist = ThisDist;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DeployableSearchFilter FriendlyStuffFilter;
|
||||
|
||||
FriendlyStuffFilter.DeployableTeam = BotTeam;
|
||||
FriendlyStuffFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(15.0f);
|
||||
FriendlyStuffFilter.DeployableTypes = STRUCTURE_ALIEN_OFFENCECHAMBER;
|
||||
|
||||
if (AITAC_DeployableExistsAtLocation(ThisHive->FloorLocation, &FriendlyStuffFilter)) { continue; }
|
||||
|
||||
bool bNeedsExtraGuards = true;
|
||||
int NumGuards = 0;
|
||||
|
||||
vector<AvHPlayer*> HumanPlayers = AIMGR_GetNonAIPlayersOnTeam(BotTeam);
|
||||
vector<AvHAIPlayer*> AITeamPlayers = AIMGR_GetAIPlayersOnTeam(BotTeam);
|
||||
|
||||
for (auto AIIt = AITeamPlayers.begin(); AIIt != AITeamPlayers.end(); AIIt++)
|
||||
{
|
||||
if ((*AIIt) == pBot) { continue; }
|
||||
|
||||
if ((*AIIt)->PrimaryBotTask.TaskType == TASK_GUARD && (*AIIt)->PrimaryBotTask.TaskTarget == ThisHive->HiveEntity->edict())
|
||||
{
|
||||
if ((*AIIt)->Player->GetUser3() >= AVH_USER3_ALIEN_PLAYER3) { bNeedsExtraGuards = false; }
|
||||
NumGuards++;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto GuardIt = HumanPlayers.begin(); GuardIt != HumanPlayers.end(); GuardIt++)
|
||||
{
|
||||
AvHPlayer* ThisGuard = (*GuardIt);
|
||||
|
||||
if (IsPlayerActiveInGame(ThisGuard->edict()) && vDist2DSq(ThisGuard->edict()->v.origin, ThisHive->FloorLocation) < sqrf(UTIL_MetresToGoldSrcUnits(15.0f)))
|
||||
{
|
||||
if (ThisGuard->GetUser3() >= AVH_USER3_ALIEN_PLAYER3) { bNeedsExtraGuards = false; }
|
||||
NumGuards++;
|
||||
}
|
||||
}
|
||||
|
||||
bNeedsExtraGuards = bNeedsExtraGuards && NumGuards < 2;
|
||||
|
||||
if (bNeedsExtraGuards)
|
||||
{
|
||||
float ThisDist = vDist2DSq(ThisHive->FloorLocation, EnemyBaseLocation);
|
||||
|
||||
if (ThisDist > MaxSecureDist)
|
||||
{
|
||||
HiveToGuard = ThisHive;
|
||||
MaxGuardDist = ThisDist;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Favour attacking an enemy outpost over guarding an empty hive if fade or onos
|
||||
if (pBot->Player->GetUser3() > AVH_USER3_ALIEN_PLAYER3)
|
||||
{
|
||||
if (HiveToSecure)
|
||||
{
|
||||
EnemyStuffFilter.DeployableTypes = SEARCH_ALL_STRUCTURES;
|
||||
vector<AvHAIBuildableStructure*> AllEnemyThings = AITAC_FindAllDeployables(HiveToSecure->FloorLocation, &EnemyStuffFilter);
|
||||
|
||||
AvHAIBuildableStructure* StructureToAttack = nullptr;
|
||||
|
||||
for (auto it = AllEnemyThings.begin(); it != AllEnemyThings.end(); it++)
|
||||
{
|
||||
AvHAIBuildableStructure* ThisStructure = (*it);
|
||||
|
||||
// First prioritise phase gates or alien OCs
|
||||
if (ThisStructure->StructureType == STRUCTURE_MARINE_PHASEGATE || ThisStructure->StructureType == STRUCTURE_ALIEN_OFFENCECHAMBER)
|
||||
{
|
||||
if (!StructureToAttack || StructureToAttack->StructureType != ThisStructure->StructureType || vDist2DSq(pBot->Edict->v.origin, ThisStructure->Location) < vDist2DSq(pBot->Edict->v.origin, StructureToAttack->Location))
|
||||
{
|
||||
StructureToAttack = ThisStructure;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (StructureToAttack && (StructureToAttack->StructureType == STRUCTURE_MARINE_PHASEGATE || ThisStructure->StructureType == STRUCTURE_ALIEN_OFFENCECHAMBER)) { continue; }
|
||||
|
||||
// Then prioritise turret factories
|
||||
if (ThisStructure->StructureType == STRUCTURE_MARINE_TURRETFACTORY || ThisStructure->StructureType == STRUCTURE_MARINE_ADVTURRETFACTORY)
|
||||
{
|
||||
if (!StructureToAttack || StructureToAttack->StructureType != ThisStructure->StructureType || vDist2DSq(pBot->Edict->v.origin, ThisStructure->Location) < vDist2DSq(pBot->Edict->v.origin, StructureToAttack->Location))
|
||||
{
|
||||
StructureToAttack = ThisStructure;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (StructureToAttack && (StructureToAttack->StructureType == STRUCTURE_MARINE_TURRETFACTORY || ThisStructure->StructureType == STRUCTURE_MARINE_ADVTURRETFACTORY)) { continue; }
|
||||
|
||||
// Then target any other structures
|
||||
if (!StructureToAttack || vDist2DSq(pBot->Edict->v.origin, ThisStructure->Location) < vDist2DSq(pBot->Edict->v.origin, StructureToAttack->Location))
|
||||
{
|
||||
StructureToAttack = ThisStructure;
|
||||
}
|
||||
}
|
||||
|
||||
if (StructureToAttack)
|
||||
{
|
||||
AITASK_SetAttackTask(pBot, Task, StructureToAttack->edict, false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (HiveToGuard)
|
||||
{
|
||||
Task->TaskType = TASK_GUARD;
|
||||
Task->TaskLocation = HiveToGuard->FloorLocation;
|
||||
Task->TaskTarget = HiveToGuard->HiveEntity->edict();
|
||||
return;
|
||||
}
|
||||
}
|
||||
// We're a skulk
|
||||
else
|
||||
{
|
||||
if (HiveToGuard)
|
||||
{
|
||||
Task->TaskType = TASK_GUARD;
|
||||
Task->TaskLocation = HiveToGuard->FloorLocation;
|
||||
Task->TaskTarget = HiveToGuard->HiveEntity->edict();
|
||||
return;
|
||||
}
|
||||
else if (HiveToSecure)
|
||||
{
|
||||
EnemyStuffFilter.DeployableTypes = SEARCH_ALL_STRUCTURES;
|
||||
EnemyStuffFilter.ExcludeStatusFlags = STRUCTURE_STATUS_ELECTRIFIED;
|
||||
vector<AvHAIBuildableStructure*> AllEnemyThings = AITAC_FindAllDeployables(HiveToSecure->FloorLocation, &EnemyStuffFilter);
|
||||
|
||||
AvHAIBuildableStructure* StructureToAttack = nullptr;
|
||||
|
||||
for (auto it = AllEnemyThings.begin(); it != AllEnemyThings.end(); it++)
|
||||
{
|
||||
AvHAIBuildableStructure* ThisStructure = (*it);
|
||||
|
||||
// First prioritise phase gates or alien OCs
|
||||
if (ThisStructure->StructureType == STRUCTURE_MARINE_PHASEGATE || ThisStructure->StructureType == STRUCTURE_ALIEN_OFFENCECHAMBER)
|
||||
{
|
||||
if (!StructureToAttack || StructureToAttack->StructureType != ThisStructure->StructureType || vDist2DSq(pBot->Edict->v.origin, ThisStructure->Location) < vDist2DSq(pBot->Edict->v.origin, StructureToAttack->Location))
|
||||
{
|
||||
StructureToAttack = ThisStructure;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (StructureToAttack && (StructureToAttack->StructureType == STRUCTURE_MARINE_PHASEGATE || ThisStructure->StructureType == STRUCTURE_ALIEN_OFFENCECHAMBER)) { continue; }
|
||||
|
||||
// Then prioritise turret factories
|
||||
if (ThisStructure->StructureType == STRUCTURE_MARINE_TURRETFACTORY || ThisStructure->StructureType == STRUCTURE_MARINE_ADVTURRETFACTORY)
|
||||
{
|
||||
if (!StructureToAttack || StructureToAttack->StructureType != ThisStructure->StructureType || vDist2DSq(pBot->Edict->v.origin, ThisStructure->Location) < vDist2DSq(pBot->Edict->v.origin, StructureToAttack->Location))
|
||||
{
|
||||
StructureToAttack = ThisStructure;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (StructureToAttack && (StructureToAttack->StructureType == STRUCTURE_MARINE_TURRETFACTORY || ThisStructure->StructureType == STRUCTURE_MARINE_ADVTURRETFACTORY)) { continue; }
|
||||
|
||||
// Then target any other structures
|
||||
if (!StructureToAttack || vDist2DSq(pBot->Edict->v.origin, ThisStructure->Location) < vDist2DSq(pBot->Edict->v.origin, StructureToAttack->Location))
|
||||
{
|
||||
StructureToAttack = ThisStructure;
|
||||
}
|
||||
}
|
||||
|
||||
if (StructureToAttack)
|
||||
{
|
||||
AITASK_SetAttackTask(pBot, Task, StructureToAttack->edict, false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// TODO: Attack enemy hive/base
|
||||
edict_t* EnemyChair = AITAC_GetCommChair(EnemyTeam);
|
||||
|
||||
if (!FNullEnt(EnemyChair))
|
||||
{
|
||||
AITASK_SetAttackTask(pBot, Task, EnemyChair, false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -2748,6 +2748,34 @@ int AITAC_GetNumPlayersOfTeamAndClassInArea(const AvHTeamNumber Team, const Vect
|
|||
return Result;
|
||||
}
|
||||
|
||||
vector<AvHPlayer*> AITAC_GetAllPlayersOfTeamInArea(const AvHTeamNumber Team, const Vector SearchLocation, const float SearchRadius, const bool bConsiderPhaseDist, const edict_t* IgnorePlayer, const AvHUser3 IgnoreClass)
|
||||
{
|
||||
vector<AvHPlayer*> Result;
|
||||
|
||||
float MaxRadiusSq = sqrf(SearchRadius);
|
||||
|
||||
for (int i = 1; i <= gpGlobals->maxClients; i++)
|
||||
{
|
||||
edict_t* PlayerEdict = INDEXENT(i);
|
||||
|
||||
if (FNullEnt(PlayerEdict) || PlayerEdict->free || PlayerEdict == IgnorePlayer) { continue; }
|
||||
|
||||
AvHPlayer* PlayerRef = dynamic_cast<AvHPlayer*>(CBaseEntity::Instance(PlayerEdict));
|
||||
|
||||
if (PlayerRef != nullptr && GetPlayerActiveClass(PlayerRef) != IgnoreClass && (Team == TEAM_IND || PlayerRef->GetTeam() == Team) && IsPlayerActiveInGame(PlayerEdict))
|
||||
{
|
||||
float Dist = (bConsiderPhaseDist) ? sqrf(AITAC_GetPhaseDistanceBetweenPoints(PlayerEdict->v.origin, SearchLocation)) : vDist2DSq(PlayerEdict->v.origin, SearchLocation);
|
||||
|
||||
if (Dist <= MaxRadiusSq)
|
||||
{
|
||||
Result.push_back(PlayerRef);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
int AITAC_GetNumPlayersOfTeamInArea(const AvHTeamNumber Team, const Vector SearchLocation, const float SearchRadius, const bool bConsiderPhaseDist, const edict_t* IgnorePlayer, const AvHUser3 IgnoreClass)
|
||||
{
|
||||
int Result = 0;
|
||||
|
@ -3695,13 +3723,10 @@ bool AITAC_ShouldBotBuildHive(AvHAIPlayer* pBot, AvHAIHiveDefinition** EligibleH
|
|||
bool AITAC_IsAlienCapperNeeded(AvHAIPlayer* pBot)
|
||||
{
|
||||
// Ok so this logic is fairly involved:
|
||||
// A node is eligible if it is reachable, and not in the enemy base (either marine spawn or a live enemy hive)
|
||||
// Of all eligible nodes, if we own 60% or more of them, then we only need one capper, and we will only become a capper if we're skulk/gorge
|
||||
// Otherwise, the number of cappers is on a sliding scale based on map ownership and number of RTs held (max 40% of team capping if things really bad)
|
||||
|
||||
// For an individual alien, they will only go capper if:
|
||||
// They have the resources to cap, or there is an enemy RT they could take out
|
||||
// If they are lerk/fade/onos, then only if there isn't a lower life form (non-builder) to do the job and we are desperate (<35% ownership or less than 3 nodes)
|
||||
// A node is eligible if it is reachable, and not in the enemy base (either marine spawn or a live enemy hive).
|
||||
// We set a max acceptable % of team allowed to be capping nodes at one time (default 50%).
|
||||
// The number of desired cappers is expressed as an inverse function of how many nodes we own, so the more nodes we own = the smaller % of team should be capping
|
||||
// Max desired cappers is also limited by how many available nodes there are so we can't end up with more cappers than available nodes
|
||||
|
||||
AvHTeamNumber BotTeam = pBot->Player->GetTeam();
|
||||
AvHTeamNumber EnemyTeam = AIMGR_GetEnemyTeam(BotTeam);
|
||||
|
@ -3731,6 +3756,7 @@ bool AITAC_IsAlienCapperNeeded(AvHAIPlayer* pBot)
|
|||
if (NumNodesLeft == 0) { return false; }
|
||||
|
||||
float OurNodeOwnership = (float)NumOwnedNodes / (float)NumEligibleNodes;
|
||||
float EnemyNodeOwnership = (float)NumEnemyNodes / (float)NumEligibleNodes;
|
||||
|
||||
int NumTeamPlayers = AIMGR_GetNumPlayersOnTeam(BotTeam);
|
||||
float MaxCapperPercent = 0.5f;
|
||||
|
@ -3743,8 +3769,64 @@ bool AITAC_IsAlienCapperNeeded(AvHAIPlayer* pBot)
|
|||
|
||||
if (NumCurrentCappers >= DesiredCappers) { return false; }
|
||||
|
||||
// TODO: Ok so we need more cappers, but more logic is needed here
|
||||
// to decide if we should go capper or not based on what others are doing
|
||||
int CapperDeficit = DesiredCappers - NumCurrentCappers;
|
||||
|
||||
// Ok, we have established that we need cappers, but let's see if WE should be capping
|
||||
|
||||
float ResourcesNeeded = BALANCE_VAR(kResourceTowerCost);
|
||||
|
||||
if (!IsPlayerGorge(pBot->Edict))
|
||||
{
|
||||
ResourcesNeeded += BALANCE_VAR(kGorgeCost);
|
||||
}
|
||||
|
||||
if (pBot->Player->GetResources() < ResourcesNeeded)
|
||||
{
|
||||
if (EnemyNodeOwnership < 0.35f) { return false; }
|
||||
}
|
||||
|
||||
bool bIsHigherLifeform = (!IsPlayerSkulk(pBot->Edict) && !IsPlayerGorge(pBot->Edict));
|
||||
bool bIsBuilder = (IsPlayerGorge(pBot->Edict) && pBot->BotRole == BOT_ROLE_BUILDER);
|
||||
|
||||
if (bIsHigherLifeform || bIsBuilder)
|
||||
{
|
||||
if (OurNodeOwnership > 0.35f) { return false; }
|
||||
|
||||
int NumAlternativeCandidates = 0;
|
||||
|
||||
vector<AvHPlayer*> CandidateTeamMates = AIMGR_GetNonAIPlayersOnTeam(BotTeam);
|
||||
vector<AvHAIPlayer*> AITeamMates = AIMGR_GetAIPlayersOnTeam(BotTeam);
|
||||
|
||||
for (auto it = AITeamMates.begin(); it != AITeamMates.end(); it++)
|
||||
{
|
||||
AvHAIPlayer* ThisBot = (*it);
|
||||
|
||||
if (ThisBot == pBot) { continue; }
|
||||
|
||||
if (ThisBot->BotRole != BOT_ROLE_FIND_RESOURCES)
|
||||
{
|
||||
CandidateTeamMates.push_back(ThisBot->Player);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto it = CandidateTeamMates.begin(); it != CandidateTeamMates.end(); it++)
|
||||
{
|
||||
AvHPlayer* ThisPlayer = (*it);
|
||||
|
||||
if (ThisPlayer == pBot->Player) { continue; }
|
||||
|
||||
if (ThisPlayer->GetUser3() < pBot->Player->GetUser3() || (ThisPlayer->GetUser3() == pBot->Player->GetUser3() && ThisPlayer->GetResources() > pBot->Player->GetResources()))
|
||||
{
|
||||
NumAlternativeCandidates++;
|
||||
}
|
||||
|
||||
if (NumAlternativeCandidates >= CapperDeficit) { return false; }
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Nobody better to do the job
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AITAC_IsAlienBuilderNeeded(AvHAIPlayer* pBot)
|
||||
|
|
|
@ -119,6 +119,7 @@ AvHAIWeapon UTIL_GetWeaponTypeFromEdict(const edict_t* ItemEdict);
|
|||
|
||||
int AITAC_GetNumActivePlayersOnTeam(const AvHTeamNumber Team);
|
||||
int AITAC_GetNumPlayersOfTeamInArea(const AvHTeamNumber Team, const Vector SearchLocation, const float SearchRadius, const bool bConsiderPhaseDist, const edict_t* IgnorePlayer, const AvHUser3 IgnoreClass);
|
||||
vector<AvHPlayer*> AITAC_GetAllPlayersOfTeamInArea(const AvHTeamNumber Team, const Vector SearchLocation, const float SearchRadius, const bool bConsiderPhaseDist, const edict_t* IgnorePlayer, const AvHUser3 IgnoreClass);
|
||||
int AITAC_GetNumPlayersOfTeamAndClassInArea(const AvHTeamNumber Team, const Vector SearchLocation, const float SearchRadius, const bool bConsiderPhaseDist, const edict_t* IgnorePlayer, const AvHUser3 SearchClass);
|
||||
int AITAC_GetNumPlayersOnTeamOfClass(const AvHTeamNumber Team, const AvHUser3 SearchClass, const edict_t* IgnorePlayer);
|
||||
edict_t* AITAC_GetNearestPlayerOfClassInArea(const AvHTeamNumber Team, const Vector SearchLocation, const float SearchRadius, const bool bConsiderPhaseDist, const edict_t* IgnorePlayer, const AvHUser3 SearchClass);
|
||||
|
|
Loading…
Reference in a new issue