More alien role work

This commit is contained in:
RGreenlees 2024-01-17 22:46:11 +00:00 committed by pierow
parent 9e4c531346
commit bb810972c5
7 changed files with 369 additions and 134 deletions

View file

@ -95,6 +95,7 @@ struct dtTileCacheParams
float walkableHeight;
float walkableRadius;
float walkableClimb;
float walkableSlope;
float maxSimplificationError;
int maxTiles;
int maxObstacles;

View file

@ -289,6 +289,8 @@ typedef struct _BOT_GUARD_INFO
Vector GuardLookLocation = g_vecZero; // Which area are we currently watching?
float GuardStartLookTime = 0.0f; // When did we start watching the current area?
float ThisGuardLookTime = 0.0f; // How long should we watch this area for?
float ThisGuardStandTime = 0.0f; // How long should we watch this area for?
float GuardStartStandTime = 0.0f; // How long should we watch this area for?
} AvHAIGuardInfo;

View file

@ -2102,7 +2102,7 @@ void AIPlayerSetMarineAssaultPrimaryTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Tas
if (AITAC_PhaseGatesAvailable(pBot->Player->GetTeam()))
{
const AvHAIHiveDefinition* ActiveHive = AITAC_GetActiveHiveNearestLocation(pBot->Edict->v.origin);
const AvHAIHiveDefinition* ActiveHive = AITAC_GetActiveHiveNearestLocation(AIMGR_GetEnemyTeam(pBot->Player->GetTeam()), pBot->Edict->v.origin);
if (ActiveHive)
{
@ -2471,11 +2471,11 @@ void AIPlayerSetAlienBuilderPrimaryTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task
return;
}
Vector ActualBuildLocation = UTIL_GetRandomPointOnNavmeshInRadiusIgnoreReachability(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), BuildOrigin, UTIL_MetresToGoldSrcUnits(3.0f));
Vector ActualBuildLocation = UTIL_GetRandomPointOnNavmeshInRadius(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), BuildOrigin, UTIL_MetresToGoldSrcUnits(3.0f));
if (vIsZero(ActualBuildLocation))
{
ActualBuildLocation = UTIL_GetRandomPointOnNavmeshInRadius(GetBaseNavProfile(GORGE_BASE_NAV_PROFILE), BuildOrigin, UTIL_MetresToGoldSrcUnits(3.0f));
ActualBuildLocation = UTIL_GetRandomPointOnNavmeshInRadiusIgnoreReachability(GetBaseNavProfile(GORGE_BASE_NAV_PROFILE), BuildOrigin, UTIL_MetresToGoldSrcUnits(3.0f));
}
AITASK_SetBuildTask(pBot, Task, MissingStructure, ActualBuildLocation, false);
@ -2779,6 +2779,131 @@ void AIPlayerSetAlienAssaultPrimaryTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task
void AIPlayerSetAlienHarasserPrimaryTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
{
// If we aren't a lerk, go evolve into one. If we can't, then act like a regular assault alien until we can
if (!IsPlayerLerk(pBot->Edict))
{
if (pBot->Player->GetResources() >= BALANCE_VAR(kLerkCost))
{
if (Task->TaskType == TASK_EVOLVE && Task->Evolution == ALIEN_LIFEFORM_THREE) { return; }
vector<AvHAIHiveDefinition*> AllTeamHives = AITAC_GetAllTeamHives(pBot->Player->GetTeam());
AvHAIHiveDefinition* NearestHive = nullptr;
float MinDist = 0.0f;
for (auto it = AllTeamHives.begin(); it != AllTeamHives.end(); it++)
{
float ThisDist = vDist2DSq(pBot->Edict->v.origin, (*it)->FloorLocation);
if (!NearestHive || ThisDist < MinDist)
{
NearestHive = (*it);
MinDist = ThisDist;
}
}
if (NearestHive)
{
AITASK_SetEvolveTask(pBot, Task, NearestHive->HiveEntity->edict(), ALIEN_LIFEFORM_THREE, true);
return;
}
else
{
AITASK_SetEvolveTask(pBot, Task, pBot->Edict->v.origin, ALIEN_LIFEFORM_THREE, true);
return;
}
}
if (IsPlayerGorge(pBot->Edict))
{
BotEvolveLifeform(pBot, pBot->Edict->v.origin, ALIEN_LIFEFORM_ONE);
return;
}
AIPlayerSetAlienAssaultPrimaryTask(pBot, Task);
return;
}
AvHTeamNumber BotTeam = pBot->Player->GetTeam();
AvHTeamNumber EnemyTeam = AIMGR_GetEnemyTeam(BotTeam);
DeployableSearchFilter EnemyStructureFilter;
EnemyStructureFilter.DeployableTeam = EnemyTeam;
EnemyStructureFilter.ReachabilityTeam = BotTeam;
EnemyStructureFilter.ReachabilityFlags = pBot->BotNavInfo.NavProfile.ReachabilityFlag;
Vector EnemyBaseLocation = AITAC_GetTeamStartingLocation(EnemyTeam);
AvHAIBuildableStructure* EnemyStructureToAttack = nullptr;
bool bEnemyIsMarines = (AIMGR_GetTeamType(EnemyTeam) == AVH_CLASS_TYPE_MARINE);
if (bEnemyIsMarines)
{
EnemyStructureFilter.DeployableTypes = (STRUCTURE_MARINE_ARMSLAB | STRUCTURE_MARINE_OBSERVATORY | STRUCTURE_MARINE_INFANTRYPORTAL);
EnemyStructureToAttack = AITAC_FindFurthestDeployableFromLocation(EnemyBaseLocation, &EnemyStructureFilter);
}
else
{
EnemyStructureFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(20.0f);
EnemyStructureFilter.DeployableTypes = (STRUCTURE_ALIEN_RESTOWER | STRUCTURE_ALIEN_DEFENCECHAMBER | STRUCTURE_ALIEN_MOVEMENTCHAMBER | STRUCTURE_ALIEN_SENSORYCHAMBER);
EnemyStructureToAttack = AITAC_FindClosestDeployableToLocation(EnemyBaseLocation, &EnemyStructureFilter);
}
if (EnemyStructureToAttack)
{
AITASK_SetAttackTask(pBot, Task, EnemyStructureToAttack->edict, false);
return;
}
if (bEnemyIsMarines)
{
edict_t* CommChair = AITAC_GetCommChair(EnemyTeam);
if (!FNullEnt(CommChair))
{
AITASK_SetAttackTask(pBot, Task, CommChair, false);
return;
}
}
else
{
const AvHAIHiveDefinition* EnemyHive = AITAC_GetActiveHiveNearestLocation(EnemyTeam, pBot->Edict->v.origin);
AITASK_SetAttackTask(pBot, Task, EnemyHive->HiveEntity->edict(), false);
return;
}
vector<AvHPlayer*> AllEnemyPlayers = AIMGR_GetAllPlayersOnTeam(EnemyTeam);
edict_t* TargetPlayer = nullptr;
float MinDist = 0.0f;
for (auto it = AllEnemyPlayers.begin(); it != AllEnemyPlayers.end(); it++)
{
AvHPlayer* ThisPlayer = (*it);
if (!ThisPlayer) { continue; }
edict_t* PlayerEdict = ThisPlayer->edict();
if (!IsPlayerActiveInGame(PlayerEdict)) { continue; }
float ThisDist = vDist2DSq(PlayerEdict->v.origin, pBot->Edict->v.origin);
if (FNullEnt(TargetPlayer) || ThisDist < MinDist)
{
TargetPlayer = PlayerEdict;
MinDist = ThisDist;
}
}
if (!FNullEnt(TargetPlayer))
{
MoveTo(pBot, UTIL_GetFloorUnderEntity(TargetPlayer), MOVESTYLE_NORMAL);
}
}

View file

@ -18,6 +18,7 @@
#include "../AvHGamerules.h"
#include "../AvHServerUtil.h"
#include "../AvHMarineEquipment.h"
#include <float.h>
@ -695,8 +696,28 @@ void AITAC_RefreshHiveData()
it->TechStatus = theEntity->GetTechnology();
it->bIsUnderAttack = GetGameRules()->GetIsEntityUnderAttack(theEntity->entindex());
it->OwningTeam = theEntity->GetTeamNumber();
it->Status = (theEntity->GetIsActive() ? HIVE_STATUS_BUILT : (theEntity->GetIsSpawning() ? HIVE_STATUS_BUILDING : HIVE_STATUS_UNBUILT));
AvHTeamNumber CurrentOwningTeam = theEntity->GetTeamNumber();
HiveStatusType CurrentStatus = (theEntity->GetIsActive() ? HIVE_STATUS_BUILT : (theEntity->GetIsSpawning() ? HIVE_STATUS_BUILDING : HIVE_STATUS_UNBUILT));
bool bHiveDestroyed = (CurrentOwningTeam != it->OwningTeam) || (it->Status == HIVE_STATUS_BUILT && CurrentStatus != it->Status);
if (bHiveDestroyed)
{
if (it->OwningTeam == GetGameRules()->GetTeamANumber())
{
TeamAStartingLocation = ZERO_VECTOR;
}
else
{
TeamBStartingLocation = ZERO_VECTOR;
}
AITAC_GetTeamStartingLocation(it->OwningTeam); // Force refresh
}
it->OwningTeam = CurrentOwningTeam;
it->Status = CurrentStatus;
if (it->Status != HIVE_STATUS_UNBUILT && it->ObstacleRefs[REGULAR_NAV_MESH] == 0)
{
@ -718,13 +739,15 @@ void AITAC_RefreshHiveData()
NextRefresh++;
}
}
Vector AITAC_GetTeamStartingLocation(AvHTeamNumber Team)
{
if (vIsZero(TeamAStartingLocation) || vIsZero(TeamBStartingLocation))
{
AvHTeamNumber TeamANum = GetGameRules()->GetTeamANumber();
AvHTeamNumber TeamBNum = GetGameRules()->GetTeamBNumber();
AvHTeam* AvHTeamARef = GetGameRules()->GetTeamA();
AvHTeam* AvHTeamBRef = GetGameRules()->GetTeamB();
@ -734,13 +757,29 @@ Vector AITAC_GetTeamStartingLocation(AvHTeamNumber Team)
if (AvHTeamARef->GetTeamType() == AVH_CLASS_TYPE_MARINE)
{
TeamAStartingLocation = TeamStartLocation;
DeployableSearchFilter IFFilter;
IFFilter.DeployableTeam = TeamANum;
IFFilter.DeployableTypes = STRUCTURE_MARINE_INFANTRYPORTAL;
IFFilter.IncludeStatusFlags = STRUCTURE_STATUS_COMPLETED;
IFFilter.ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING;
AvHAIBuildableStructure* InfantryPortal = AITAC_FindClosestDeployableToLocation(ZERO_VECTOR, &IFFilter);
if (InfantryPortal)
{
TeamAStartingLocation = InfantryPortal->Location;
}
else
{
Vector CommChairLocation = AITAC_GetCommChairLocation(TeamANum);
TeamAStartingLocation = (!vIsZero(CommChairLocation)) ? CommChairLocation : TeamStartLocation;
}
}
else
{
TeamAStartingLocation = TeamStartLocation;
const AvHAIHiveDefinition* Hive = AITAC_GetHiveNearestLocation(TeamStartLocation);
const AvHAIHiveDefinition* Hive = AITAC_GetActiveHiveNearestLocation(TeamANum, TeamStartLocation);
if (Hive)
{
@ -759,13 +798,29 @@ Vector AITAC_GetTeamStartingLocation(AvHTeamNumber Team)
if (AvHTeamBRef->GetTeamType() == AVH_CLASS_TYPE_MARINE)
{
TeamBStartingLocation = TeamStartLocation;
DeployableSearchFilter IFFilter;
IFFilter.DeployableTeam = TeamBNum;
IFFilter.DeployableTypes = STRUCTURE_MARINE_INFANTRYPORTAL;
IFFilter.IncludeStatusFlags = STRUCTURE_STATUS_COMPLETED;
IFFilter.ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING;
AvHAIBuildableStructure* InfantryPortal = AITAC_FindClosestDeployableToLocation(ZERO_VECTOR, &IFFilter);
if (InfantryPortal)
{
TeamAStartingLocation = InfantryPortal->Location;
}
else
{
Vector CommChairLocation = AITAC_GetCommChairLocation(TeamBNum);
TeamAStartingLocation = (!vIsZero(CommChairLocation)) ? CommChairLocation : TeamStartLocation;
}
}
else
{
TeamBStartingLocation = TeamStartLocation;
const AvHAIHiveDefinition* Hive = AITAC_GetActiveHiveNearestLocation(TeamStartLocation);
const AvHAIHiveDefinition* Hive = AITAC_GetActiveHiveNearestLocation(TeamBNum, TeamStartLocation);
if (Hive)
{
@ -777,6 +832,9 @@ Vector AITAC_GetTeamStartingLocation(AvHTeamNumber Team)
}
}
}
// Update reachabilities since team starting points have been modified
bNavMeshModified = true;
}
return (Team == GetGameRules()->GetTeamANumber()) ? TeamAStartingLocation : TeamBStartingLocation;
@ -794,18 +852,11 @@ Vector AITAC_GetCommChairLocation(AvHTeamNumber Team)
}
}
DeployableSearchFilter ChairFilter;
ChairFilter.DeployableTypes = STRUCTURE_MARINE_COMMCHAIR;
ChairFilter.DeployableTeam = Team;
ChairFilter.ReachabilityTeam = TEAM_IND;
ChairFilter.bConsiderPhaseDistance = false;
ChairFilter.IncludeStatusFlags = STRUCTURE_STATUS_COMPLETED;
edict_t* Chair = AITAC_GetCommChair(Team);
AvHAIBuildableStructure* ChairRef = AITAC_FindClosestDeployableToLocation(ZERO_VECTOR, &ChairFilter);
if (ChairRef)
if (!FNullEnt(Chair))
{
return ChairRef->Location;
return Chair->v.origin;
}
return ZERO_VECTOR;
@ -1708,10 +1759,15 @@ AvHAIBuildableStructure* AITAC_UpdateBuildableStructure(CBaseEntity* Structure)
unsigned int NewFlags = STRUCTURE_STATUS_NONE;
bool bJustCompleted = false;
bool bJustRecycled = false;
bool bJustDestroyed = false;
if (BaseBuildable->GetIsBuilt())
{
if (!(BuildingMap[EntIndex].StructureStatusFlags & STRUCTURE_STATUS_COMPLETED)) {
AITAC_OnStructureCompleted(&BuildingMap[EntIndex]);
if (!(BuildingMap[EntIndex].StructureStatusFlags & STRUCTURE_STATUS_COMPLETED))
{
bJustCompleted = true;
}
NewFlags |= STRUCTURE_STATUS_COMPLETED;
}
@ -1730,7 +1786,7 @@ AvHAIBuildableStructure* AITAC_UpdateBuildableStructure(CBaseEntity* Structure)
{
if (!(BuildingMap[EntIndex].StructureStatusFlags & STRUCTURE_STATUS_RECYCLING))
{
AITAC_OnStructureBeginRecycling(&BuildingMap[EntIndex]);
bJustRecycled = true;
}
NewFlags |= STRUCTURE_STATUS_RECYCLING;
}
@ -1757,6 +1813,16 @@ AvHAIBuildableStructure* AITAC_UpdateBuildableStructure(CBaseEntity* Structure)
BuildingMap[EntIndex].StructureStatusFlags = NewFlags;
BuildingMap[EntIndex].LastSeen = StructureRefreshFrame;
if (bJustCompleted)
{
AITAC_OnStructureCompleted(&BuildingMap[EntIndex]);
}
if (bJustRecycled)
{
AITAC_OnStructureBeginRecycling(&BuildingMap[EntIndex]);
}
return &BuildingMap[EntIndex];
}
@ -1819,6 +1885,22 @@ void AITAC_OnStructureCompleted(AvHAIBuildableStructure* NewStructure)
}
}
if (NewStructure->StructureType == STRUCTURE_MARINE_INFANTRYPORTAL)
{
AvHTeamNumber Team = (AvHTeamNumber)NewStructure->edict->v.team;
if (Team == GetGameRules()->GetTeamANumber())
{
TeamAStartingLocation = ZERO_VECTOR;
}
else
{
TeamBStartingLocation = ZERO_VECTOR;
}
AITAC_GetTeamStartingLocation(Team); // Force refresh of reachabilities and team starting locations
}
}
void AITAC_RemovePhaseGateConnections(AvHAIBuildableStructure* SourceGate, AvHAIBuildableStructure* TargetGate)
@ -1881,6 +1963,22 @@ void AITAC_OnStructureDestroyed(AvHAIBuildableStructure* DestroyedStructure)
AITAC_RemovePhaseGateConnections(OtherPhaseGate, DestroyedStructure);
}
}
if (DestroyedStructure->StructureType == STRUCTURE_MARINE_INFANTRYPORTAL)
{
AvHTeamNumber Team = (AvHTeamNumber)DestroyedStructure->edict->v.team;
if (Team == GetGameRules()->GetTeamANumber())
{
TeamAStartingLocation = ZERO_VECTOR;
}
else
{
TeamBStartingLocation = ZERO_VECTOR;
}
AITAC_GetTeamStartingLocation(Team); // Force refresh of reachabilities and team starting locations
}
}
void AITAC_LinkAlienStructureToPlayer(AvHAIBuildableStructure* NewStructure)
@ -2329,14 +2427,14 @@ const AvHAIHiveDefinition* AITAC_GetHiveNearestLocation(const Vector SearchLocat
return Result;
}
const AvHAIHiveDefinition* AITAC_GetActiveHiveNearestLocation(const Vector SearchLocation)
const AvHAIHiveDefinition* AITAC_GetActiveHiveNearestLocation(AvHTeamNumber Team, const Vector SearchLocation)
{
AvHAIHiveDefinition* Result = nullptr;
float MinDist = 0.0f;
for (auto it = Hives.begin(); it != Hives.end(); it++)
{
if (it->Status != HIVE_STATUS_BUILT) { continue; }
if (it->Status != HIVE_STATUS_BUILT || it->OwningTeam != Team) { continue; }
float ThisDist = vDist3DSq(SearchLocation, it->Location);
@ -3133,23 +3231,30 @@ edict_t* AITAC_GetCommChair(AvHTeamNumber Team)
ChairFilter.DeployableTeam = Team;
ChairFilter.ReachabilityTeam = TEAM_IND;
AvHAIBuildableStructure* ChairStructure = AITAC_FindClosestDeployableToLocation(ZERO_VECTOR, &ChairFilter);
vector<AvHAIBuildableStructure*> CommChairs = AITAC_FindAllDeployables(ZERO_VECTOR, &ChairFilter);
if (ChairStructure)
edict_t* MainCommChair = nullptr;
edict_t* BackupChair = nullptr;
// If the team has more than one comm chair, pick the one in use
for (auto it = CommChairs.begin(); it != CommChairs.end(); it++)
{
return ChairStructure->edict;
AvHCommandStation* ChairRef = dynamic_cast<AvHCommandStation*>((*it)->EntityRef);
// Idle animation will be 3 if the chair is in use (closed animation). See AvHCommandStation::GetIdleAnimation
if (ChairRef && ChairRef->GetIdleAnimation() == 3)
{
MainCommChair = ChairRef->edict();
}
else
{
BackupChair = ChairRef->edict();
}
}
ChairFilter.DeployableTeam = TEAM_IND;
if (!FNullEnt(MainCommChair)) { return MainCommChair;}
ChairStructure = AITAC_FindClosestDeployableToLocation(AITAC_GetTeamStartingLocation(Team), &ChairFilter);
if (ChairStructure)
{
return ChairStructure->edict;
}
return nullptr;
return BackupChair;
}
edict_t* AITAC_GetNearestHumanAtLocation(const AvHTeamNumber Team, const Vector Location, const float MaxSearchRadius)
@ -3372,6 +3477,21 @@ const vector<AvHAIHiveDefinition*> AITAC_GetAllHives()
return Results;
}
const vector<AvHAIHiveDefinition*> AITAC_GetAllTeamHives(AvHTeamNumber Team)
{
vector<AvHAIHiveDefinition*> Results;
for (auto it = Hives.begin(); it != Hives.end(); it++)
{
if (it->OwningTeam == Team)
{
Results.push_back(&(*it));
}
}
return Results;
}
bool AITAC_AnyPlayerOnTeamWithLOS(AvHTeamNumber Team, const Vector& Location, float SearchRadius)
{
float distSq = sqrf(SearchRadius);
@ -3521,17 +3641,16 @@ bool AITAC_IsAlienCapperNeeded(AvHAIPlayer* pBot)
AvHTeamNumber BotTeam = pBot->Player->GetTeam();
AvHTeamNumber EnemyTeam = AIMGR_GetEnemyTeam(BotTeam);
float ResNodeOwnership = AITAC_GetTeamResNodeOwnership(BotTeam, false);
float EnemyNodeOwnership = AITAC_GetTeamResNodeOwnership(EnemyTeam, false);
float ResNodeOwnership = AITAC_GetTeamResNodeOwnership(BotTeam, true);
if (ResNodeOwnership > 0.6f) { return false; }
int NumTeamPlayers = AIMGR_GetNumPlayersOnTeam(BotTeam);
int MaxCappers = (int)ceilf((float)NumTeamPlayers * 0.5f);
int MaxCappers = (int)ceilf((float)NumTeamPlayers * 0.4f);
int NumCurrentCappers = AIMGR_GetNumAIPlayersWithRoleOnTeam(BotTeam, BOT_ROLE_FIND_RESOURCES, pBot);
int DesiredCappers = 0;
if (ResNodeOwnership > 0.6f) { return false; }
int DesiredCappers = 0;
if (ResNodeOwnership < 0.25f)
{
@ -3549,7 +3668,7 @@ bool AITAC_IsAlienCapperNeeded(AvHAIPlayer* pBot)
// If we're lerk/fade/onos, only go capper if we have lots of resources and can replace them easily, otherwise we can't afford to waste resources going back to gorge
if (!IsPlayerSkulk(pBot->Edict) && !IsPlayerGorge(pBot->Edict))
{
if (pBot->Player->GetResources() < 75 || ResNodeOwnership < 0.4f) { return false; }
if (pBot->Player->GetResources() < 75 || ResNodeOwnership >= 0.4f) { return false; }
int NumSkulks = AITAC_GetNumPlayersOnTeamOfClass(BotTeam, AVH_USER3_ALIEN_PLAYER1, nullptr);
int NumGorges = AITAC_GetNumPlayersOnTeamOfClass(BotTeam, AVH_USER3_ALIEN_PLAYER2, nullptr);

View file

@ -50,7 +50,7 @@ float AITAC_GetPhaseDistanceBetweenPoints(const Vector StartPoint, const Ve
const AvHAIHiveDefinition* AITAC_GetHiveAtIndex(int Index);
const AvHAIHiveDefinition* AITAC_GetHiveNearestLocation(const Vector SearchLocation);
const AvHAIHiveDefinition* AITAC_GetActiveHiveNearestLocation(const Vector SearchLocation);
const AvHAIHiveDefinition* AITAC_GetActiveHiveNearestLocation(AvHTeamNumber Team, const Vector SearchLocation);
const AvHAIHiveDefinition* AITAC_GetNonEmptyHiveNearestLocation(const Vector SearchLocation);
Vector AITAC_GetCommChairLocation(AvHTeamNumber Team);
@ -157,6 +157,7 @@ edict_t* AITAC_GetNearestHiddenPlayerInLocation(AvHTeamNumber Team, const Vector
const vector<AvHAIResourceNode*> AITAC_GetAllResourceNodes();
const vector<AvHAIHiveDefinition*> AITAC_GetAllHives();
const vector<AvHAIHiveDefinition*> AITAC_GetAllTeamHives(AvHTeamNumber Team);
bool AITAC_AnyPlayerOnTeamWithLOS(AvHTeamNumber Team, const Vector& Location, float SearchRadius);

View file

@ -1893,10 +1893,15 @@ void AlienProgressBuildTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
return;
}
if (!vIsZero(Task->TaskLocation))
{
UTIL_DrawLine(INDEXENT(1), pBot->Edict->v.origin, Task->TaskLocation);
}
// We tried and failed to place the structure
if (pBot->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_FAILED)
{
Task->TaskLocation = UTIL_GetRandomPointOnNavmeshInRadius(BaseNavProfiles[STRUCTURE_BASE_NAV_PROFILE], Task->TaskLocation, UTIL_MetresToGoldSrcUnits(2.0f));
Task->TaskLocation = UTIL_GetRandomPointOnNavmeshInRadius(BaseNavProfiles[GORGE_BASE_NAV_PROFILE], Task->TaskLocation, UTIL_MetresToGoldSrcUnits(2.0f));
pBot->ActiveBuildInfo.BuildStatus = BUILD_ATTEMPT_NONE;
}
@ -1909,6 +1914,29 @@ void AlienProgressBuildTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
if (pBot->Player->GetResources() < ResRequired)
{
if (IsPlayerGorge(pBot->Edict))
{
AvHTeamNumber BotTeam = pBot->Player->GetTeam();
DeployableSearchFilter UnfinishedFilter;
UnfinishedFilter.DeployableTeam = BotTeam;
UnfinishedFilter.DeployableTypes = SEARCH_ALL_STRUCTURES;
UnfinishedFilter.ReachabilityTeam = BotTeam;
UnfinishedFilter.ReachabilityFlags = pBot->BotNavInfo.NavProfile.ReachabilityFlag;
UnfinishedFilter.ExcludeStatusFlags = STRUCTURE_STATUS_COMPLETED;
UnfinishedFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(10.0f);
AvHAIBuildableStructure* UnfinishedStructure = AITAC_FindClosestDeployableToLocation(Task->TaskLocation, &UnfinishedFilter);
if (UnfinishedStructure)
{
AIPlayerBuildStructure(pBot, UnfinishedStructure->edict);
return;
}
}
BotGuardLocation(pBot, Task->TaskLocation);
return;
}
@ -2578,17 +2606,21 @@ void BotGuardLocation(AvHAIPlayer* pBot, const Vector GuardLocation)
if (DistFromGuardLocation > sqrf(UTIL_MetresToGoldSrcUnits(5.0f)))
{
pBot->GuardInfo.GuardLocation = g_vecZero;
pBot->GuardInfo.GuardStartLookTime = 0.0f;
pBot->GuardInfo.ThisGuardLookTime = 0.0f;
pBot->GuardInfo.GuardStartStandTime = 0.0f;
pBot->GuardInfo.ThisGuardStandTime = 0.0f;
MoveTo(pBot, GuardLocation, MOVESTYLE_NORMAL);
return;
}
if (!pBot->GuardInfo.GuardLocation)
if (vIsZero(pBot->GuardInfo.GuardLocation))
{
AITASK_GenerateGuardWatchPoints(pBot, GuardLocation);
pBot->GuardInfo.GuardLocation = GuardLocation;
}
if (gpGlobals->time - pBot->GuardInfo.GuardStartLookTime > pBot->GuardInfo.ThisGuardLookTime)
if (gpGlobals->time > pBot->GuardInfo.ThisGuardLookTime)
{
if (pBot->GuardInfo.NumGuardPoints > 0)
{
@ -2603,36 +2635,28 @@ void BotGuardLocation(AvHAIPlayer* pBot, const Vector GuardLocation)
pBot->GuardInfo.GuardLookLocation.z = pBot->CurrentEyePosition.z;
}
Vector LookDir = UTIL_GetVectorNormal2D(pBot->GuardInfo.GuardLookLocation - GuardLocation);
pBot->GuardInfo.ThisGuardLookTime = gpGlobals->time + frandrange(2.0f, 5.0f);
}
Vector NewMoveCentre = GuardLocation - (LookDir * UTIL_MetresToGoldSrcUnits(2.0f));
if (gpGlobals->time > pBot->GuardInfo.ThisGuardStandTime)
{
pBot->GuardInfo.GuardStandPosition = UTIL_GetRandomPointOnNavmeshInRadius(pBot->BotNavInfo.NavProfile, GuardLocation, UTIL_MetresToGoldSrcUnits(4.0f));
Vector NewMoveLoc = UTIL_GetRandomPointOnNavmeshInRadius(BaseNavProfiles[MARINE_BASE_NAV_PROFILE], NewMoveCentre, UTIL_MetresToGoldSrcUnits(2.0f));
pBot->GuardInfo.ThisGuardStandTime = gpGlobals->time + frandrange(5.0f, 10.0f);
}
if (NewMoveLoc != g_vecZero)
if (vDist2DSq(pBot->Edict->v.origin, pBot->GuardInfo.GuardStandPosition) > sqrf(32.0f))
{
if (IsPlayerLerk(pBot->Edict))
{
pBot->GuardInfo.GuardStandPosition = NewMoveLoc;
MoveTo(pBot, pBot->GuardInfo.GuardStandPosition, MOVESTYLE_HIDE);
}
else
{
pBot->GuardInfo.GuardStandPosition = GuardLocation;
MoveTo(pBot, pBot->GuardInfo.GuardStandPosition, MOVESTYLE_NORMAL);
}
pBot->GuardInfo.ThisGuardLookTime = frandrange(2.0f, 5.0f);
pBot->GuardInfo.GuardStartLookTime = gpGlobals->time;
}
if (IsPlayerLerk(pBot->Edict))
{
MoveTo(pBot, pBot->GuardInfo.GuardStandPosition, MOVESTYLE_HIDE);
}
else
{
MoveTo(pBot, pBot->GuardInfo.GuardStandPosition, MOVESTYLE_NORMAL);
}
BotLookAt(pBot, pBot->GuardInfo.GuardLookLocation);
@ -2659,15 +2683,15 @@ void AITASK_GenerateGuardWatchPoints(AvHAIPlayer* pBot, const Vector& GuardLocat
path.clear();
for (int i = 0; i < AITAC_GetNumHives(); i++)
vector<AvHAIHiveDefinition*> AllHives = AITAC_GetAllHives();
for (auto it = AllHives.begin(); it != AllHives.end(); it++)
{
const AvHAIHiveDefinition* Hive = AITAC_GetHiveAtIndex(i);
const AvHAIHiveDefinition* ThisHive = (*it);
if (!Hive) { continue; }
if (UTIL_QuickTrace(pEdict, GuardLocation + Vector(0.0f, 0.0f, 10.0f), ThisHive->Location) || vDist2DSq(GuardLocation, ThisHive->Location) < sqrf(UTIL_MetresToGoldSrcUnits(10.0f))) { continue; }
if (UTIL_QuickTrace(pEdict, GuardLocation + Vector(0.0f, 0.0f, 10.0f), Hive->Location) || vDist2DSq(GuardLocation, Hive->Location) < sqrf(UTIL_MetresToGoldSrcUnits(10.0f))) { continue; }
dtStatus SearchResult = FindPathClosestToPoint(NavProfile, Hive->FloorLocation, GuardLocation, path, 500.0f);
dtStatus SearchResult = FindPathClosestToPoint(NavProfile, ThisHive->FloorLocation, GuardLocation, path, 500.0f);
if (dtStatusSucceed(SearchResult))
{
@ -2680,21 +2704,10 @@ void AITASK_GenerateGuardWatchPoints(AvHAIPlayer* pBot, const Vector& GuardLocat
}
}
dtStatus SearchResult = FindPathClosestToPoint(NavProfile, AITAC_GetTeamStartingLocation(EnemyTeam), GuardLocation, path, 500.0f);
if (dtStatusSucceed(SearchResult))
if (AIMGR_GetEnemyTeamType(pBot->Player->GetTeam()) == AVH_CLASS_TYPE_MARINE)
{
Vector FinalApproachDir = UTIL_GetVectorNormal2D(path.back().Location - prev(prev(path.end()))->Location);
Vector ProspectiveNewGuardLoc = GuardLocation - (FinalApproachDir * 300.0f);
ProspectiveNewGuardLoc.z = prev(prev(path.end()))->Location.z;
pBot->GuardInfo.GuardPoints[pBot->GuardInfo.NumGuardPoints++] = ProspectiveNewGuardLoc;
}
if (vDist2DSq(GuardLocation, AITAC_GetTeamStartingLocation(pBot->Player->GetTeam())) > sqrf(UTIL_MetresToGoldSrcUnits(15.0f)))
{
dtStatus SearchResult = FindPathClosestToPoint(NavProfile, AITAC_GetTeamStartingLocation(pBot->Player->GetTeam()), GuardLocation, path, 500.0f);
dtStatus SearchResult = FindPathClosestToPoint(NavProfile, AITAC_GetTeamStartingLocation(EnemyTeam), GuardLocation, path, 500.0f);
if (dtStatusSucceed(SearchResult))
{
@ -2707,6 +2720,24 @@ void AITASK_GenerateGuardWatchPoints(AvHAIPlayer* pBot, const Vector& GuardLocat
}
}
if (AIMGR_GetTeamType(pBot->Player->GetTeam()) == AVH_CLASS_TYPE_MARINE)
{
if (vDist2DSq(GuardLocation, AITAC_GetTeamStartingLocation(pBot->Player->GetTeam())) > sqrf(UTIL_MetresToGoldSrcUnits(15.0f)))
{
dtStatus SearchResult = FindPathClosestToPoint(NavProfile, AITAC_GetTeamStartingLocation(pBot->Player->GetTeam()), GuardLocation, path, 500.0f);
if (dtStatusSucceed(SearchResult))
{
Vector FinalApproachDir = UTIL_GetVectorNormal2D(path.back().Location - prev(prev(path.end()))->Location);
Vector ProspectiveNewGuardLoc = GuardLocation - (FinalApproachDir * 300.0f);
ProspectiveNewGuardLoc.z = prev(prev(path.end()))->Location.z;
pBot->GuardInfo.GuardPoints[pBot->GuardInfo.NumGuardPoints++] = ProspectiveNewGuardLoc;
}
}
}
}
bool BotWithBuildTaskExists(AvHTeamNumber Team, AvHAIDeployableStructureType StructureType)

View file

@ -1535,54 +1535,10 @@ BOOL AvHGamerules::ClientCommand( CBasePlayer *pPlayer, const char *pcmd )
theSuccess = true;
}
else if (FStrEq(pcmd, "getaliencomp"))
else if (FStrEq(pcmd, "showteamstarts"))
{
vector<AvHAIPlayer*> AlienPlayers = AIMGR_GetAIPlayersOnTeam(TEAM_TWO);
int NumBuilders = 0;
int NumCappers = 0;
int NumHarassers = 0;
int NumAssault = 0;
for (auto it = AlienPlayers.begin(); it != AlienPlayers.end(); it++)
{
AvHAIPlayer* NewCapper = (*it);
if (NewCapper)
{
switch (NewCapper->BotRole)
{
case BOT_ROLE_BUILDER:
NumBuilders++;
break;
case BOT_ROLE_FIND_RESOURCES:
NumCappers++;
break;
case BOT_ROLE_HARASS:
NumHarassers++;
break;
case BOT_ROLE_ASSAULT:
NumAssault++;
break;
default:
break;
}
}
}
char buf[32];
sprintf(buf, "Builders: %d\n", NumBuilders);
UTIL_SayText(buf, theAvHPlayer);
sprintf(buf, "Cappers: %d\n", NumCappers);
UTIL_SayText(buf, theAvHPlayer);
sprintf(buf, "Harassers: %d\n", NumHarassers);
UTIL_SayText(buf, theAvHPlayer);
sprintf(buf, "Assault: %d\n", NumAssault);
UTIL_SayText(buf, theAvHPlayer);
UTIL_DrawLine(INDEXENT(1), INDEXENT(1)->v.origin, AITAC_GetTeamStartingLocation(TEAM_ONE), 20.0f, 0, 0, 255);
UTIL_DrawLine(INDEXENT(1), INDEXENT(1)->v.origin, AITAC_GetTeamStartingLocation(TEAM_TWO), 20.0f, 255, 255, 0);
theSuccess = true;
}