mirror of
https://github.com/ENSL/NS.git
synced 2024-11-24 21:41:17 +00:00
Fixed base bugs
* Fixed issue where commander would build siege turrets too far from the siege target * Improved commander response to requests for turrets * Nav reachabilities and paths are now regenerated after all nav mesh modifications are updated
This commit is contained in:
parent
2842aba0bb
commit
733ad6eb04
10 changed files with 327 additions and 93 deletions
|
@ -3166,21 +3166,29 @@ bool AICOMM_CheckForNextSupportAction(AvHAIPlayer* pBot)
|
|||
}
|
||||
}
|
||||
|
||||
if (NextRequest->RequestType == BUILD_SIEGE)
|
||||
if (NextRequest->RequestType == BUILD_SIEGE || NextRequest->RequestType == BUILD_TURRET)
|
||||
{
|
||||
DeployableSearchFilter TFFilter;
|
||||
TFFilter.DeployableTeam = CommanderTeam;
|
||||
TFFilter.DeployableTypes = STRUCTURE_MARINE_ADVTURRETFACTORY;
|
||||
TFFilter.DeployableTypes = (NextRequest->RequestType == BUILD_SIEGE) ? STRUCTURE_MARINE_ADVTURRETFACTORY : STRUCTURE_MARINE_TURRETFACTORY;
|
||||
TFFilter.IncludeStatusFlags = STRUCTURE_STATUS_COMPLETED;
|
||||
TFFilter.ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING;
|
||||
TFFilter.MaxSearchRadius = BALANCE_VAR(kTurretFactoryBuildDistance);
|
||||
|
||||
bool bHasChair = AITAC_DeployableExistsAtLocation(ProjectedDeployLocation, &TFFilter);
|
||||
bool bHasTF = AITAC_DeployableExistsAtLocation(ProjectedDeployLocation, &TFFilter);
|
||||
|
||||
if (!bHasChair)
|
||||
if (!bHasTF)
|
||||
{
|
||||
char msg[128];
|
||||
sprintf(msg, "There isn't a an advanced armory there, %s. Ask again next to one", STRING(Requestor->v.netname));
|
||||
|
||||
if (NextRequest->RequestType == BUILD_SIEGE)
|
||||
{
|
||||
sprintf(msg, "There isn't an advanced turret factory in range, %s. Ask again near one", STRING(Requestor->v.netname));
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(msg, "There isn't a completed turret factory in range, %s. Ask again near one", STRING(Requestor->v.netname));
|
||||
}
|
||||
BotSay(pBot, true, 0.5f, msg);
|
||||
NextRequest->bResponded = true;
|
||||
return false;
|
||||
|
@ -3826,16 +3834,42 @@ void AICOMM_UpdateSiegeBaseStatus(AvHAIPlayer* pBot, AvHAIMarineBase* Base)
|
|||
bool bStillStuffToSiege = AITAC_DeployableExistsAtLocation(Base->BaseLocation, &EnemyStuffFilter);
|
||||
|
||||
const AvHAIHiveDefinition* NearestHive = AITAC_GetHiveNearestLocation(Base->BaseLocation);
|
||||
const AvHAIHiveDefinition* SiegeHive = nullptr;
|
||||
|
||||
if (bStillStuffToSiege || (NearestHive && NearestHive->Status != HIVE_STATUS_UNBUILT && vDist2DSq(Base->BaseLocation, NearestHive->Location) < sqrf(BALANCE_VAR(kSiegeTurretRange))))
|
||||
if (vDist2DSq(Base->BaseLocation, NearestHive->Location) < sqrf(BALANCE_VAR(kSiegeTurretRange)))
|
||||
{
|
||||
SiegeHive = NearestHive;
|
||||
}
|
||||
|
||||
if (bStillStuffToSiege || (SiegeHive && SiegeHive->Status != HIVE_STATUS_UNBUILT))
|
||||
{
|
||||
if (SiegeHive && SiegeHive->Status != HIVE_STATUS_UNBUILT)
|
||||
{
|
||||
Base->SiegeTarget = SiegeHive->Location;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Basically, find the centroid (average location) of all siege structures, that will be our target
|
||||
vector<AvHAIBuildableStructure> NearbyEnemyStuff = AITAC_FindAllDeployables(Base->BaseLocation, &EnemyStuffFilter);
|
||||
|
||||
Vector Centroid = ZERO_VECTOR;
|
||||
|
||||
for (auto it = NearbyEnemyStuff.begin(); it != NearbyEnemyStuff.end(); it++)
|
||||
{
|
||||
Centroid = Centroid + it->Location;
|
||||
}
|
||||
|
||||
Centroid = Centroid / NearbyEnemyStuff.size();
|
||||
|
||||
Base->SiegeTarget = Centroid;
|
||||
}
|
||||
Base->bRecycleBase = false;
|
||||
Base->bIsActive = true;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!NearestHive || vDist2DSq(Base->BaseLocation, NearestHive->Location) > sqrf(BALANCE_VAR(kSiegeTurretRange)))
|
||||
if (!SiegeHive)
|
||||
{
|
||||
Base->bRecycleBase = false;
|
||||
Base->bIsActive = false;
|
||||
|
@ -3845,7 +3879,7 @@ void AICOMM_UpdateSiegeBaseStatus(AvHAIPlayer* pBot, AvHAIMarineBase* Base)
|
|||
{
|
||||
for (auto it = pBot->Bases.begin(); it != pBot->Bases.end(); it++)
|
||||
{
|
||||
if (it->BaseType == MARINE_BASE_OUTPOST && vDist2DSq(NearestHive->FloorLocation, it->BaseLocation) < sqrf(UTIL_MetresToGoldSrcUnits(10.0f)))
|
||||
if (it->BaseType == MARINE_BASE_OUTPOST && vDist2DSq(SiegeHive->FloorLocation, it->BaseLocation) < sqrf(UTIL_MetresToGoldSrcUnits(10.0f)))
|
||||
{
|
||||
if (it->bIsBaseEstablished)
|
||||
{
|
||||
|
@ -3862,8 +3896,9 @@ void AICOMM_UpdateSiegeBaseStatus(AvHAIPlayer* pBot, AvHAIMarineBase* Base)
|
|||
}
|
||||
}
|
||||
|
||||
Base->bRecycleBase = false;
|
||||
Base->bIsActive = true;
|
||||
Base->SiegeTarget = ZERO_VECTOR;
|
||||
Base->bRecycleBase = true;
|
||||
Base->bIsActive = false;
|
||||
}
|
||||
|
||||
void AICOMM_DeployBases(AvHAIPlayer* pBot)
|
||||
|
@ -4036,13 +4071,14 @@ void AICOMM_DeployBases(AvHAIPlayer* pBot)
|
|||
|
||||
if (!bHasSiege)
|
||||
{
|
||||
vector<AvHPlayer*> PotentialBuilders = AITAC_GetAllPlayersOfTeamInArea(BotTeam, ThisHive->FloorLocation, BALANCE_VAR(kSiegeTurretRange), false, nullptr, AVH_USER3_COMMANDER_PLAYER);
|
||||
vector<AvHPlayer*> PotentialBuilders = AITAC_GetAllPlayersOfTeamInArea(BotTeam, ThisHive->Location, BALANCE_VAR(kSiegeTurretRange), false, nullptr, AVH_USER3_COMMANDER_PLAYER);
|
||||
|
||||
for (auto playerIt = PotentialBuilders.begin(); playerIt != PotentialBuilders.end(); playerIt++)
|
||||
{
|
||||
AvHPlayer* ThisPlayer = (*playerIt);
|
||||
if (vDist2DSq(ThisPlayer->pev->origin, ThisHive->FloorLocation) > sqrf(UTIL_MetresToGoldSrcUnits(10.0f)))
|
||||
if (vDist2DSq(ThisPlayer->pev->origin, ThisHive->Location) > sqrf(UTIL_MetresToGoldSrcUnits(10.0f)))
|
||||
{
|
||||
// If this player isn't right inside the hive and hasn't been spotted by an enemy, then they're eligible to start building a siege base
|
||||
if (!(ThisPlayer->pev->iuser4 & MASK_VIS_SIGHTED))
|
||||
{
|
||||
DeployableSearchFilter EnemyStuffFilter;
|
||||
|
@ -4052,7 +4088,7 @@ void AICOMM_DeployBases(AvHAIPlayer* pBot)
|
|||
EnemyStuffFilter.DeployableTypes = (STRUCTURE_MARINE_COMMCHAIR | STRUCTURE_MARINE_TURRETFACTORY | STRUCTURE_MARINE_ADVTURRETFACTORY | STRUCTURE_MARINE_PHASEGATE | STRUCTURE_ALIEN_OFFENCECHAMBER);
|
||||
EnemyStuffFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(5.0f);
|
||||
|
||||
if (!AITAC_DeployableExistsAtLocation(ThisHive->FloorLocation, &EnemyStuffFilter))
|
||||
if (!AITAC_DeployableExistsAtLocation(ThisPlayer->pev->origin, &EnemyStuffFilter))
|
||||
{
|
||||
AICOMM_AddNewBase(pBot, ThisPlayer->pev->origin, MARINE_BASE_SIEGE);
|
||||
}
|
||||
|
@ -5078,6 +5114,15 @@ bool AICOMM_BuildOutMainBase(AvHAIPlayer* pBot, AvHAIMarineBase* BaseToBuildOut)
|
|||
{
|
||||
if (pBot->Player->GetResources() < BALANCE_VAR(kSentryCost)) { return true; }
|
||||
|
||||
Vector BuildLocation = AITAC_GetRandomBuildHintInLocation(STRUCTURE_MARINE_TURRET, TurretFactory.Location, BALANCE_VAR(kTurretFactoryBuildDistance));
|
||||
|
||||
if (!vIsZero(BuildLocation))
|
||||
{
|
||||
bool bSuccess = AICOMM_AddStructureToBase(pBot, STRUCTURE_MARINE_TURRET, BuildLocation, BaseToBuildOut);
|
||||
|
||||
if (bSuccess) { return true; }
|
||||
}
|
||||
|
||||
int NumAttempts = 0;
|
||||
|
||||
while (NumAttempts < 5)
|
||||
|
@ -5114,7 +5159,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(15.0f));
|
||||
Vector BuildLocation = AITAC_GetRandomBuildHintInLocation(STRUCTURE_MARINE_ARMSLAB, CommChair.Location, UTIL_MetresToGoldSrcUnits(20.0f));
|
||||
|
||||
if (!vIsZero(BuildLocation))
|
||||
{
|
||||
|
@ -5155,7 +5200,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(15.0f));
|
||||
Vector BuildLocation = AITAC_GetRandomBuildHintInLocation(STRUCTURE_MARINE_OBSERVATORY, CommChair.Location, UTIL_MetresToGoldSrcUnits(20.0f));
|
||||
|
||||
if (!vIsZero(BuildLocation))
|
||||
{
|
||||
|
@ -5198,7 +5243,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(15.0f));
|
||||
Vector BuildLocation = AITAC_GetRandomBuildHintInLocation(STRUCTURE_MARINE_PHASEGATE, CommChair.Location, UTIL_MetresToGoldSrcUnits(20.0f));
|
||||
|
||||
if (!vIsZero(BuildLocation))
|
||||
{
|
||||
|
@ -5250,7 +5295,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(15.0f));
|
||||
Vector BuildLocation = AITAC_GetRandomBuildHintInLocation(STRUCTURE_MARINE_PROTOTYPELAB, CommChair.Location, UTIL_MetresToGoldSrcUnits(20.0f));
|
||||
|
||||
if (!vIsZero(BuildLocation))
|
||||
{
|
||||
|
@ -5481,7 +5526,6 @@ bool AICOMM_BuildOutSiege(AvHAIPlayer* pBot, AvHAIMarineBase* BaseToBuildOut)
|
|||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (NumIncomplete > 0)
|
||||
|
@ -5524,9 +5568,48 @@ bool AICOMM_BuildOutSiege(AvHAIPlayer* pBot, AvHAIMarineBase* BaseToBuildOut)
|
|||
|
||||
if (pBot->Player->GetResources() < ResourcesRequired) { return true; }
|
||||
|
||||
if (StructureToDeploy == STRUCTURE_MARINE_TURRETFACTORY)
|
||||
{
|
||||
Vector BuildLocation = AITAC_GetRandomBuildHintInLocation(StructureToDeploy, BaseToBuildOut->BaseLocation, UTIL_MetresToGoldSrcUnits(5.0f));
|
||||
|
||||
if (!vIsZero(BuildLocation) && (vIsZero(BaseToBuildOut->SiegeTarget) || vDist2DSq(BuildLocation, BaseToBuildOut->SiegeTarget) < sqrf(BALANCE_VAR(kSiegeTurretRange))))
|
||||
{
|
||||
bool bSuccess = AICOMM_AddStructureToBase(pBot, StructureToDeploy, BuildLocation, BaseToBuildOut);
|
||||
|
||||
if (bSuccess) { return true; }
|
||||
}
|
||||
|
||||
int NumAttempts = 0;
|
||||
|
||||
while (NumAttempts < 5)
|
||||
{
|
||||
Vector BuildLocation = UTIL_GetRandomPointOnNavmeshInRadiusIgnoreReachability(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), BaseToBuildOut->BaseLocation, UTIL_MetresToGoldSrcUnits(2.0f + NumAttempts));
|
||||
|
||||
if (!vIsZero(BuildLocation) && (vIsZero(BaseToBuildOut->SiegeTarget) || vDist2DSq(BuildLocation, BaseToBuildOut->SiegeTarget) < sqrf(BALANCE_VAR(kSiegeTurretRange))))
|
||||
{
|
||||
bool bSuccess = AICOMM_AddStructureToBase(pBot, StructureToDeploy, BuildLocation, BaseToBuildOut);
|
||||
|
||||
if (bSuccess) { return true; }
|
||||
}
|
||||
|
||||
BuildLocation = UTIL_GetRandomPointOnNavmeshInRadius(GetBaseNavProfile(MARINE_BASE_NAV_PROFILE), BaseToBuildOut->BaseLocation, UTIL_MetresToGoldSrcUnits(2.0f + NumAttempts));
|
||||
|
||||
if (!vIsZero(BuildLocation) && (vIsZero(BaseToBuildOut->SiegeTarget) || vDist2DSq(BuildLocation, BaseToBuildOut->SiegeTarget) < sqrf(BALANCE_VAR(kSiegeTurretRange))))
|
||||
{
|
||||
bool bSuccess = AICOMM_AddStructureToBase(pBot, StructureToDeploy, BuildLocation, BaseToBuildOut);
|
||||
|
||||
if (bSuccess) { return true; }
|
||||
}
|
||||
|
||||
NumAttempts++;
|
||||
}
|
||||
|
||||
return (pBot->Player->GetResources() <= BALANCE_VAR(kTurretFactoryCost) * 2);
|
||||
}
|
||||
|
||||
if (StructureToDeploy == STRUCTURE_MARINE_SIEGETURRET)
|
||||
{
|
||||
Vector BuildLocation = AITAC_GetRandomBuildHintInLocation(StructureToDeploy, BaseToBuildOut->BaseLocation, UTIL_MetresToGoldSrcUnits(10.0f));
|
||||
Vector BuildLocation = AITAC_GetRandomBuildHintInLocation(StructureToDeploy, TurretFactory.Location, BALANCE_VAR(kTurretFactoryBuildDistance));
|
||||
|
||||
if (!vIsZero(BuildLocation))
|
||||
{
|
||||
|
@ -5541,7 +5624,7 @@ bool AICOMM_BuildOutSiege(AvHAIPlayer* pBot, AvHAIMarineBase* BaseToBuildOut)
|
|||
{
|
||||
Vector BuildLocation = UTIL_GetRandomPointOnNavmeshInRadiusIgnoreReachability(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), TurretFactory.Location, (BALANCE_VAR(kTurretFactoryBuildDistance) * 0.4f));
|
||||
|
||||
if (!vIsZero(BuildLocation))
|
||||
if (!vIsZero(BuildLocation) && (vIsZero(BaseToBuildOut->SiegeTarget) || vDist2DSq(BuildLocation, BaseToBuildOut->SiegeTarget) < sqrf(BALANCE_VAR(kSiegeTurretRange))))
|
||||
{
|
||||
bool bSuccess = AICOMM_AddStructureToBase(pBot, StructureToDeploy, BuildLocation, BaseToBuildOut);
|
||||
|
||||
|
@ -5550,7 +5633,7 @@ bool AICOMM_BuildOutSiege(AvHAIPlayer* pBot, AvHAIMarineBase* BaseToBuildOut)
|
|||
|
||||
BuildLocation = UTIL_GetRandomPointOnNavmeshInRadius(GetBaseNavProfile(MARINE_BASE_NAV_PROFILE), TurretFactory.Location, (BALANCE_VAR(kTurretFactoryBuildDistance) * 0.6f));
|
||||
|
||||
if (!vIsZero(BuildLocation))
|
||||
if (!vIsZero(BuildLocation) && (vIsZero(BaseToBuildOut->SiegeTarget) || vDist2DSq(BuildLocation, BaseToBuildOut->SiegeTarget) < sqrf(BALANCE_VAR(kSiegeTurretRange))))
|
||||
{
|
||||
bool bSuccess = AICOMM_AddStructureToBase(pBot, StructureToDeploy, BuildLocation, BaseToBuildOut);
|
||||
|
||||
|
|
|
@ -488,6 +488,7 @@ typedef struct _AI_MARINE_BASE
|
|||
AvHTeamNumber BaseTeam = TEAM_IND;
|
||||
MarineBaseType BaseType = MARINE_BASE_OUTPOST; // The purpose of the base. Determines what structures the commander will place
|
||||
Vector BaseLocation = ZERO_VECTOR; // Where the base should be located. The base will be grown around this location
|
||||
Vector SiegeTarget = ZERO_VECTOR; // For siege bases, this is where the siege base wants to blast stuff
|
||||
vector<int> PlacedStructures; // Which structures are part of this base.
|
||||
int NumBuilders = 0; // How many potential builders are there, able to construct stuff?
|
||||
int NumEnemies = 0; // How many enemies are in and around the base?
|
||||
|
|
|
@ -350,9 +350,16 @@ void AIDEBUG_DrawPath(edict_t* OutputPlayer, vector<bot_path_node>& path, float
|
|||
|
||||
void UTIL_DrawLine(edict_t* pEntity, Vector start, Vector end)
|
||||
{
|
||||
if (FNullEnt(pEntity) || pEntity->free) { return; }
|
||||
|
||||
if (FNullEnt(pEntity) || pEntity->free)
|
||||
{
|
||||
MESSAGE_BEGIN(MSG_BROADCAST, SVC_TEMPENTITY);
|
||||
}
|
||||
else
|
||||
{
|
||||
MESSAGE_BEGIN(MSG_ONE, SVC_TEMPENTITY, NULL, pEntity);
|
||||
}
|
||||
|
||||
WRITE_BYTE(TE_BEAMPOINTS);
|
||||
WRITE_COORD(start.x);
|
||||
WRITE_COORD(start.y);
|
||||
|
@ -378,12 +385,18 @@ void UTIL_DrawLine(edict_t* pEntity, Vector start, Vector end)
|
|||
|
||||
void UTIL_DrawLine(edict_t* pEntity, Vector start, Vector end, float drawTimeSeconds)
|
||||
{
|
||||
if (FNullEnt(pEntity) || pEntity->free) { return; }
|
||||
|
||||
int timeTenthSeconds = (int)floorf(drawTimeSeconds * 10.0f);
|
||||
timeTenthSeconds = fmaxf(timeTenthSeconds, 1);
|
||||
|
||||
if (FNullEnt(pEntity) || pEntity->free)
|
||||
{
|
||||
MESSAGE_BEGIN(MSG_BROADCAST, SVC_TEMPENTITY);
|
||||
}
|
||||
else
|
||||
{
|
||||
MESSAGE_BEGIN(MSG_ONE, SVC_TEMPENTITY, NULL, pEntity);
|
||||
}
|
||||
|
||||
WRITE_BYTE(TE_BEAMPOINTS);
|
||||
WRITE_COORD(start.x);
|
||||
WRITE_COORD(start.y);
|
||||
|
@ -409,12 +422,18 @@ void UTIL_DrawLine(edict_t* pEntity, Vector start, Vector end, float drawTimeSec
|
|||
|
||||
void UTIL_DrawLine(edict_t* pEntity, Vector start, Vector end, float drawTimeSeconds, int r, int g, int b)
|
||||
{
|
||||
if (FNullEnt(pEntity) || pEntity->free) { return; }
|
||||
|
||||
int timeTenthSeconds = (int)ceilf(drawTimeSeconds * 10.0f);
|
||||
timeTenthSeconds = fmaxf(timeTenthSeconds, 1);
|
||||
|
||||
if (FNullEnt(pEntity) || pEntity->free)
|
||||
{
|
||||
MESSAGE_BEGIN(MSG_BROADCAST, SVC_TEMPENTITY);
|
||||
}
|
||||
else
|
||||
{
|
||||
MESSAGE_BEGIN(MSG_ONE, SVC_TEMPENTITY, NULL, pEntity);
|
||||
}
|
||||
|
||||
WRITE_BYTE(TE_BEAMPOINTS);
|
||||
WRITE_COORD(start.x);
|
||||
WRITE_COORD(start.y);
|
||||
|
@ -440,9 +459,15 @@ void UTIL_DrawLine(edict_t* pEntity, Vector start, Vector end, float drawTimeSec
|
|||
|
||||
void UTIL_DrawLine(edict_t* pEntity, Vector start, Vector end, int r, int g, int b)
|
||||
{
|
||||
if (FNullEnt(pEntity) || pEntity->free) { return; }
|
||||
|
||||
if (FNullEnt(pEntity) || pEntity->free)
|
||||
{
|
||||
MESSAGE_BEGIN(MSG_BROADCAST, SVC_TEMPENTITY);
|
||||
}
|
||||
else
|
||||
{
|
||||
MESSAGE_BEGIN(MSG_ONE, SVC_TEMPENTITY, NULL, pEntity);
|
||||
}
|
||||
|
||||
WRITE_BYTE(TE_BEAMPOINTS);
|
||||
WRITE_COORD(start.x);
|
||||
WRITE_COORD(start.y);
|
||||
|
@ -638,11 +663,64 @@ void UTIL_LocalizeText(const char* InputText, string& OutputText)
|
|||
|
||||
}
|
||||
|
||||
char* UTIL_StructTypeToChar(const AvHAIDeployableStructureType StructureType)
|
||||
{
|
||||
switch (StructureType)
|
||||
{
|
||||
case STRUCTURE_MARINE_RESTOWER:
|
||||
return "RT";
|
||||
case STRUCTURE_MARINE_INFANTRYPORTAL:
|
||||
return "IP";
|
||||
case STRUCTURE_MARINE_TURRETFACTORY:
|
||||
return "TF";
|
||||
case STRUCTURE_MARINE_ADVTURRETFACTORY:
|
||||
return "Adv TF";
|
||||
case STRUCTURE_MARINE_ARMOURY:
|
||||
return "Armoury";
|
||||
case STRUCTURE_MARINE_ADVARMOURY:
|
||||
return "Adv Armoury";
|
||||
case STRUCTURE_MARINE_ARMSLAB:
|
||||
return "Armslab";
|
||||
case STRUCTURE_MARINE_PROTOTYPELAB:
|
||||
return "ProtoLab";
|
||||
case STRUCTURE_MARINE_OBSERVATORY:
|
||||
return "Obs";
|
||||
case STRUCTURE_MARINE_PHASEGATE:
|
||||
return "PG";
|
||||
case STRUCTURE_MARINE_TURRET:
|
||||
return "Sentry";
|
||||
case STRUCTURE_MARINE_SIEGETURRET:
|
||||
return "Siege T";
|
||||
case STRUCTURE_MARINE_COMMCHAIR:
|
||||
return "CC";
|
||||
case STRUCTURE_MARINE_DEPLOYEDMINE:
|
||||
return "Mine";
|
||||
|
||||
case STRUCTURE_ALIEN_HIVE:
|
||||
return "Hive";
|
||||
case STRUCTURE_ALIEN_RESTOWER:
|
||||
return "RT";
|
||||
case STRUCTURE_ALIEN_DEFENCECHAMBER:
|
||||
return "DC";
|
||||
case STRUCTURE_ALIEN_SENSORYCHAMBER:
|
||||
return "SC";
|
||||
case STRUCTURE_ALIEN_MOVEMENTCHAMBER:
|
||||
return "MC";
|
||||
case STRUCTURE_ALIEN_OFFENCECHAMBER:
|
||||
return "OC";
|
||||
default:
|
||||
return "None";
|
||||
}
|
||||
|
||||
return "None";
|
||||
}
|
||||
|
||||
char* UTIL_TaskTypeToChar(const BotTaskType TaskType)
|
||||
{
|
||||
switch (TaskType)
|
||||
{
|
||||
case TASK_ATTACK:
|
||||
|
||||
return "Attack";
|
||||
case TASK_BUILD:
|
||||
return "Build";
|
||||
|
|
|
@ -60,6 +60,7 @@ void UTIL_ClearLocalizations();
|
|||
void UTIL_LocalizeText(const char* InputText, string& OutputText);
|
||||
|
||||
char* UTIL_TaskTypeToChar(const BotTaskType TaskType);
|
||||
char* UTIL_StructTypeToChar(const AvHAIDeployableStructureType StructureType);
|
||||
|
||||
char* UTIL_BotRoleToChar(const AvHAIBotRole Role);
|
||||
|
||||
|
|
|
@ -479,7 +479,7 @@ void AIDEBUG_DrawOffMeshConnections(float DrawTime)
|
|||
|
||||
bool UTIL_UpdateTileCache()
|
||||
{
|
||||
bTileCacheUpToDate = true;
|
||||
bool bNewTileCacheUpToDate = true;
|
||||
|
||||
for (int i = 0; i < MAX_NAV_MESHES; i++)
|
||||
{
|
||||
|
@ -487,10 +487,17 @@ bool UTIL_UpdateTileCache()
|
|||
{
|
||||
bool bUpToDate;
|
||||
NavMeshes[i].tileCache->update(0.0f, NavMeshes[i].navMesh, &bUpToDate);
|
||||
if (!bUpToDate) { bTileCacheUpToDate = false; }
|
||||
if (i != BUILDING_NAV_MESH && !bUpToDate) { bNewTileCacheUpToDate = false; }
|
||||
}
|
||||
}
|
||||
|
||||
if (!bTileCacheUpToDate && bNewTileCacheUpToDate)
|
||||
{
|
||||
bNavMeshModified = true;
|
||||
}
|
||||
|
||||
bTileCacheUpToDate = bNewTileCacheUpToDate;
|
||||
|
||||
return bTileCacheUpToDate;
|
||||
}
|
||||
|
||||
|
@ -604,11 +611,6 @@ unsigned int UTIL_AddTemporaryObstacle(unsigned int NavMeshIndex, const Vector L
|
|||
NavMeshes[NavMeshIndex].tileCache->addObstacle(Pos, Radius, Height, area, &ObsRef);
|
||||
|
||||
ObstacleNum = (unsigned int)ObsRef;
|
||||
|
||||
if (ObstacleNum > 0 && NavMeshIndex != BUILDING_NAV_MESH)
|
||||
{
|
||||
bNavMeshModified = true;
|
||||
}
|
||||
}
|
||||
|
||||
return ObstacleNum;
|
||||
|
@ -670,16 +672,9 @@ void UTIL_RemoveStructureTemporaryObstacles(AvHAIBuildableStructure* Structure)
|
|||
if (ObstacleToRemove)
|
||||
{
|
||||
dtStatus RemovalStatus = NavMeshes[NavMeshIndex].tileCache->removeObstacle((dtObstacleRef)it->ObstacleRef);
|
||||
|
||||
if (dtStatusSucceed(RemovalStatus))
|
||||
{
|
||||
bNavMeshModified = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
it = Structure->Obstacles.erase(it);
|
||||
}
|
||||
|
||||
|
@ -700,11 +695,6 @@ void UTIL_AddTemporaryObstacles(const Vector Location, float Radius, float Heigh
|
|||
NavMeshes[i].tileCache->addObstacle(Pos, Radius, Height, area, &ObsRef);
|
||||
|
||||
ObstacleRefArray[i] = (unsigned int)ObsRef;
|
||||
|
||||
if ((unsigned int)ObsRef > 0)
|
||||
{
|
||||
bNavMeshModified = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -724,12 +714,6 @@ unsigned int UTIL_AddTemporaryBoxObstacle(const Vector bMin, const Vector bMax,
|
|||
NavMeshes[i].tileCache->addBoxObstacle(bMinf, bMaxf, area, &ObsRef);
|
||||
|
||||
ObstacleNum = (unsigned int)ObsRef;
|
||||
|
||||
if (area == DT_TILECACHE_NULL_AREA || area == DT_TILECACHE_WELD_AREA)
|
||||
{
|
||||
bNavMeshModified = true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -746,11 +730,6 @@ void UTIL_RemoveTemporaryObstacle(unsigned int ObstacleRef)
|
|||
{
|
||||
const dtTileCacheObstacle* ObstacleToRemove = NavMeshes[i].tileCache->getObstacleByRef((dtObstacleRef)ObstacleRef);
|
||||
|
||||
if (ObstacleToRemove && (ObstacleToRemove->cylinder.area == DT_TILECACHE_NULL_AREA || ObstacleToRemove->cylinder.area == DT_TILECACHE_WELD_AREA))
|
||||
{
|
||||
bNavMeshModified = true;
|
||||
}
|
||||
|
||||
NavMeshes[i].tileCache->removeObstacle((dtObstacleRef)ObstacleRef);
|
||||
}
|
||||
}
|
||||
|
@ -765,11 +744,6 @@ void UTIL_RemoveTemporaryObstacles(unsigned int* ObstacleRefs)
|
|||
{
|
||||
const dtTileCacheObstacle* ObstacleToRemove = NavMeshes[i].tileCache->getObstacleByRef((dtObstacleRef)ObstacleRefs[i]);
|
||||
|
||||
if (ObstacleToRemove && (ObstacleToRemove->cylinder.area == DT_TILECACHE_NULL_AREA || ObstacleToRemove->cylinder.area == DT_TILECACHE_WELD_AREA))
|
||||
{
|
||||
bNavMeshModified = true;
|
||||
}
|
||||
|
||||
NavMeshes[i].tileCache->removeObstacle((dtObstacleRef)ObstacleRefs[i]);
|
||||
|
||||
}
|
||||
|
@ -6823,6 +6797,7 @@ bool MoveTo(AvHAIPlayer* pBot, const Vector Destination, const BotMoveStyle Move
|
|||
if (!vIsZero(BotNavInfo->LastNavMeshPosition))
|
||||
{
|
||||
MoveDirectlyTo(pBot, BotNavInfo->LastNavMeshPosition);
|
||||
UTIL_DrawLine(nullptr, pBot->Edict->v.origin, BotNavInfo->LastNavMeshPosition, 255, 0, 0);
|
||||
|
||||
if (vDist2DSq(pBot->CurrentFloorPosition, BotNavInfo->LastNavMeshPosition) < sqrf(8.0f))
|
||||
{
|
||||
|
@ -6846,6 +6821,7 @@ bool MoveTo(AvHAIPlayer* pBot, const Vector Destination, const BotMoveStyle Move
|
|||
if (!vIsZero(BotNavInfo->UnstuckMoveLocation))
|
||||
{
|
||||
MoveDirectlyTo(pBot, BotNavInfo->UnstuckMoveLocation);
|
||||
UTIL_DrawLine(nullptr, pBot->Edict->v.origin, BotNavInfo->UnstuckMoveLocation, 255, 255, 0);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -6853,6 +6829,7 @@ bool MoveTo(AvHAIPlayer* pBot, const Vector Destination, const BotMoveStyle Move
|
|||
else
|
||||
{
|
||||
MoveDirectlyTo(pBot, Destination);
|
||||
UTIL_DrawLine(nullptr, pBot->Edict->v.origin, BotNavInfo->UnstuckMoveLocation, 0, 128, 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -8838,8 +8815,6 @@ void UTIL_ModifyOffMeshConnectionFlag(AvHAIOffMeshConnection* Connection, const
|
|||
NavMeshes[i].tileCache->modifyOffMeshConnection(Connection->ConnectionRefs[i], NewFlag);
|
||||
}
|
||||
}
|
||||
|
||||
bNavMeshModified = true;
|
||||
}
|
||||
|
||||
void UTIL_UpdateDoors(bool bInitial)
|
||||
|
@ -9584,8 +9559,6 @@ void UTIL_AddOffMeshConnection(Vector StartLoc, Vector EndLoc, unsigned char are
|
|||
|
||||
RemoveConnectionDef->ConnectionRefs[i] = (unsigned int)ref;
|
||||
}
|
||||
|
||||
bNavMeshModified = true;
|
||||
}
|
||||
|
||||
void UTIL_RemoveOffMeshConnections(AvHAIOffMeshConnection* RemoveConnectionDef)
|
||||
|
@ -9596,8 +9569,6 @@ void UTIL_RemoveOffMeshConnections(AvHAIOffMeshConnection* RemoveConnectionDef)
|
|||
|
||||
RemoveConnectionDef->ConnectionRefs[i] = 0;
|
||||
}
|
||||
|
||||
bNavMeshModified = true;
|
||||
}
|
||||
|
||||
const nav_profile GetBaseNavProfile(const int index)
|
||||
|
|
|
@ -1887,21 +1887,24 @@ void EndBotFrame(AvHAIPlayer* pBot)
|
|||
|
||||
void CustomThink(AvHAIPlayer* pBot)
|
||||
{
|
||||
if (IsPlayerAlien(pBot->Edict)) { return; }
|
||||
if (!IsPlayerAlien(pBot->Edict)) { return; }
|
||||
|
||||
if (!IsPlayerCommander(pBot->Edict))
|
||||
int Enemy = BotGetNextEnemyTarget(pBot);
|
||||
|
||||
if (Enemy > -1)
|
||||
{
|
||||
BotProgressTakeCommandTask(pBot);
|
||||
return;
|
||||
AlienCombatThink(pBot);
|
||||
}
|
||||
else
|
||||
{
|
||||
edict_t* CommChair = AITAC_GetCommChair(AIMGR_GetEnemyTeam(pBot->Player->GetTeam()));
|
||||
|
||||
if (!FNullEnt(CommChair))
|
||||
{
|
||||
MoveTo(pBot, CommChair->v.origin, MOVESTYLE_NORMAL);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto it = pBot->Bases.begin(); it != pBot->Bases.end(); it++)
|
||||
{
|
||||
if (it->bCanBeBuiltOut)
|
||||
{
|
||||
if (AICOMM_BuildOutBase(pBot, &(*it))) { return; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DroneThink(AvHAIPlayer* pBot)
|
||||
|
@ -2059,7 +2062,17 @@ void AIPlayerTakeDamage(AvHAIPlayer* pBot, int damageTaken, edict_t* aggressor)
|
|||
}
|
||||
|
||||
TrackingInfo->AwarenessOfPlayer = 1.0f;
|
||||
|
||||
Vector VisiblePoint = GetVisiblePointOnPlayerFromObserver(pBot->Edict, aggressor);
|
||||
|
||||
if (!vIsZero(VisiblePoint))
|
||||
{
|
||||
TrackingInfo->bHasLOS = true;
|
||||
TrackingInfo->bEnemyHasLOS = true;
|
||||
TrackingInfo->LastVisibleTime = gpGlobals->time;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6348,7 +6361,7 @@ void AIPlayerSetAlienCapperPrimaryTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
|
|||
// If we're already capping a node, are at the node and there is an unfinished tower on there, then finish the job and don't move on yet
|
||||
if (Task->TaskType == TASK_CAP_RESNODE)
|
||||
{
|
||||
const AvHAIResourceNode* ResNodeIndex = AITAC_GetNearestResourceNodeToLocation(Task->TaskLocation);
|
||||
const AvHAIResourceNode* ResNodeIndex = AITAC_GetResourceNodeFromEdict(Task->TaskTarget);
|
||||
|
||||
if (ResNodeIndex && ResNodeIndex->OwningTeam != BotTeam)
|
||||
{
|
||||
|
@ -6358,7 +6371,7 @@ void AIPlayerSetAlienCapperPrimaryTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (!FNullEnt(ResNodeIndex->ActiveTowerEntity) && !UTIL_StructureIsFullyBuilt(ResNodeIndex->ActiveTowerEntity))
|
||||
if (IsPlayerGorge(pBot->Edict) && !FNullEnt(ResNodeIndex->ActiveTowerEntity) && !UTIL_StructureIsFullyBuilt(ResNodeIndex->ActiveTowerEntity))
|
||||
{
|
||||
if (vDist2DSq(pBot->Edict->v.origin, ResNodeIndex->Location) < sqrf(UTIL_MetresToGoldSrcUnits(5.0f)))
|
||||
{
|
||||
|
@ -6380,7 +6393,7 @@ void AIPlayerSetAlienCapperPrimaryTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
|
|||
|
||||
if (IsPlayerLerk(pBot->Edict) || IsPlayerFade(pBot->Edict) || IsPlayerOnos(pBot->Edict))
|
||||
{
|
||||
bCanPlaceTower = pBot->Player->GetResources() >= 75 && AITAC_GetTeamResNodeOwnership(BotTeam, true) >= 0.5f;
|
||||
bCanPlaceTower = pBot->Player->GetResources() >= 75 && AITAC_GetTeamResNodeOwnership(BotTeam, true) < 0.5f;
|
||||
}
|
||||
|
||||
// If we have enough resources to cap a node, then find an empty one we can slap one down in
|
||||
|
|
|
@ -1313,6 +1313,64 @@ void AIMGR_SetDebugAIPlayer(edict_t* SpectatingPlayer, edict_t* AIPlayer)
|
|||
|
||||
DebugBots[PlayerIndex] = nullptr;
|
||||
}
|
||||
|
||||
void AIDEBUG_DisplayTeamGoals()
|
||||
{
|
||||
AvHTeamNumber TeamANumber = AIMGR_GetTeamANumber();
|
||||
AvHTeamNumber TeamBNumber = AIMGR_GetTeamBNumber();
|
||||
|
||||
vector<AvHAIPlayer*> Team1Players = AIMGR_GetAIPlayersOnTeam(TeamANumber);
|
||||
vector<AvHAIPlayer*> Team2Players = AIMGR_GetAIPlayersOnTeam(TeamBNumber);
|
||||
|
||||
char buf[511];
|
||||
char interbuf[164];
|
||||
|
||||
sprintf(buf, "Team A (%s)\n\n", (AIMGR_GetTeamType(TeamANumber) == AVH_CLASS_TYPE_MARINE) ? "Marines" : "Aliens");
|
||||
|
||||
for (auto it = Team1Players.begin(); it != Team1Players.end(); it++)
|
||||
{
|
||||
AvHAIPlayer* ThisPlayer = (*it);
|
||||
|
||||
if (!ThisPlayer->CurrentTask || !IsPlayerActiveInGame(ThisPlayer->Edict)) { continue; }
|
||||
|
||||
if (!FNullEnt(ThisPlayer->CurrentTask->TaskTarget))
|
||||
{
|
||||
sprintf(interbuf, "%s: %s (%s)\n", STRING(ThisPlayer->Player->pev->netname), UTIL_TaskTypeToChar(ThisPlayer->CurrentTask->TaskType), UTIL_StructTypeToChar(UTIL_IUSER3ToStructureType(ThisPlayer->CurrentTask->TaskTarget->v.iuser3)));
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(interbuf, "%s: %s\n", STRING(ThisPlayer->Player->pev->netname), UTIL_TaskTypeToChar(ThisPlayer->CurrentTask->TaskType));
|
||||
}
|
||||
|
||||
|
||||
strcat(buf, interbuf);
|
||||
}
|
||||
|
||||
UTIL_DrawHUDText(INDEXENT(1), 0, 0.1, 0.1f, 255, 255, 255, buf);
|
||||
|
||||
sprintf(buf, "Team B (%s)\n\n", (AIMGR_GetTeamType(TeamBNumber) == AVH_CLASS_TYPE_MARINE) ? "Marines" : "Aliens");
|
||||
|
||||
for (auto it = Team2Players.begin(); it != Team2Players.end(); it++)
|
||||
{
|
||||
AvHAIPlayer* ThisPlayer = (*it);
|
||||
|
||||
if (!ThisPlayer->CurrentTask || !IsPlayerActiveInGame(ThisPlayer->Edict)) { continue; }
|
||||
|
||||
if (!FNullEnt(ThisPlayer->CurrentTask->TaskTarget))
|
||||
{
|
||||
sprintf(interbuf, "%s: %s (%s)\n", STRING(ThisPlayer->Player->pev->netname), UTIL_TaskTypeToChar(ThisPlayer->CurrentTask->TaskType), UTIL_StructTypeToChar(UTIL_IUSER3ToStructureType(ThisPlayer->CurrentTask->TaskTarget->v.iuser3)));
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(interbuf, "%s: %s\n", STRING(ThisPlayer->Player->pev->netname), UTIL_TaskTypeToChar(ThisPlayer->CurrentTask->TaskType));
|
||||
}
|
||||
|
||||
|
||||
strcat(buf, interbuf);
|
||||
}
|
||||
|
||||
UTIL_DrawHUDText(INDEXENT(1), 1, 0.6, 0.1f, 255, 255, 255, buf);
|
||||
}
|
||||
#endif
|
||||
|
||||
void AIMGR_ReceiveCommanderRequest(AvHTeamNumber Team, edict_t* Requestor, const char* Request)
|
||||
|
|
|
@ -137,4 +137,6 @@ void AIMGR_ProcessPendingSounds();
|
|||
void AIMGR_SetFrameDelta(float NewValue);
|
||||
float AIMGR_GetFrameDelta();
|
||||
|
||||
void AIDEBUG_DisplayTeamGoals();
|
||||
|
||||
#endif
|
|
@ -3154,7 +3154,6 @@ bool UTIL_ShouldStructureCollide(AvHAIDeployableStructureType StructureType)
|
|||
{
|
||||
case STRUCTURE_MARINE_INFANTRYPORTAL:
|
||||
case STRUCTURE_MARINE_PHASEGATE:
|
||||
case STRUCTURE_MARINE_TURRET:
|
||||
case STRUCTURE_MARINE_DEPLOYEDMINE:
|
||||
return false;
|
||||
default:
|
||||
|
|
|
@ -875,12 +875,32 @@ bool AITASK_IsReinforceStructureTaskStillValid(AvHAIPlayer* pBot, AvHAIPlayerTas
|
|||
|
||||
if (bActiveHiveWithoutTechExists) { return true; }
|
||||
|
||||
int NumMissing = 0;
|
||||
AvHAIDeployableStructureType MissingStructure = AITAC_GetNextMissingUpgradeChamberForTeam(BotTeam, NumMissing);
|
||||
|
||||
if (MissingStructure != STRUCTURE_NONE) { return true; }
|
||||
|
||||
Vector ReinforceLocation = Task->TaskTarget->v.origin;
|
||||
float SearchRadius = UTIL_MetresToGoldSrcUnits(5.0f);
|
||||
|
||||
if (IsEdictHive(Task->TaskTarget))
|
||||
{
|
||||
AvHAIHiveDefinition* HiveToReinforce = AITAC_GetHiveFromEdict(Task->TaskTarget);
|
||||
|
||||
if (HiveToReinforce)
|
||||
{
|
||||
ReinforceLocation = HiveToReinforce->FloorLocation;
|
||||
}
|
||||
|
||||
SearchRadius = UTIL_MetresToGoldSrcUnits(10.0f);
|
||||
}
|
||||
|
||||
DeployableSearchFilter StructureFilter;
|
||||
StructureFilter.DeployableTypes = SEARCH_ALL_ALIEN_STRUCTURES;
|
||||
StructureFilter.MaxSearchRadius = (IsEdictHive(Task->TaskTarget)) ? UTIL_MetresToGoldSrcUnits(10.0f) : UTIL_MetresToGoldSrcUnits(5.0f);
|
||||
StructureFilter.MaxSearchRadius = SearchRadius * 1.25f;
|
||||
StructureFilter.DeployableTeam = BotTeam;
|
||||
|
||||
vector<AvHAIBuildableStructure> AllNearbyStructures = AITAC_FindAllDeployables(Task->TaskTarget->v.origin, &StructureFilter);
|
||||
vector<AvHAIBuildableStructure> AllNearbyStructures = AITAC_FindAllDeployables(ReinforceLocation, &StructureFilter);
|
||||
|
||||
bool bUnfinishedStructureExists = false;
|
||||
int NumOffenceChambers = 0;
|
||||
|
@ -916,11 +936,11 @@ bool AITASK_IsReinforceStructureTaskStillValid(AvHAIPlayer* pBot, AvHAIPlayerTas
|
|||
|
||||
// Task is still valid if we have any missing structures, or we're a gorge at the target site and there is an incomplete structure that we can finish off
|
||||
|
||||
if (NumOffenceChambers < 2
|
||||
if (NumOffenceChambers < 3
|
||||
|| (AITAC_TeamHiveWithTechExists(BotTeam, ALIEN_BUILD_DEFENSE_CHAMBER) && NumDefenceChambers < 2)
|
||||
|| (AITAC_TeamHiveWithTechExists(BotTeam, ALIEN_BUILD_MOVEMENT_CHAMBER) && NumMovementChambers < 1)
|
||||
|| (AITAC_TeamHiveWithTechExists(BotTeam, ALIEN_BUILD_SENSORY_CHAMBER) && NumSensoryChambers < 1)
|
||||
|| (IsPlayerGorge(pBot->Edict) && bUnfinishedStructureExists && vDist2DSq(pBot->Edict->v.origin, Task->TaskTarget->v.origin) <= sqrf(UTIL_MetresToGoldSrcUnits(10.0f)))
|
||||
|| (IsPlayerGorge(pBot->Edict) && bUnfinishedStructureExists && vDist2DSq(pBot->Edict->v.origin, ReinforceLocation) <= sqrf(UTIL_MetresToGoldSrcUnits(10.0f)))
|
||||
) { return true; }
|
||||
|
||||
// Otherwise, are there any enemy structures lying around we could clear out?
|
||||
|
@ -934,9 +954,9 @@ bool AITASK_IsReinforceStructureTaskStillValid(AvHAIPlayer* pBot, AvHAIPlayerTas
|
|||
EnemyStuff.DeployableTeam = AIMGR_GetEnemyTeam(BotTeam);
|
||||
EnemyStuff.ReachabilityTeam = BotTeam;
|
||||
EnemyStuff.ReachabilityFlags = pBot->BotNavInfo.NavProfile.ReachabilityFlag;
|
||||
EnemyStuff.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(5.0f);
|
||||
EnemyStuff.MaxSearchRadius = SearchRadius;
|
||||
|
||||
return AITAC_DeployableExistsAtLocation(Task->TaskTarget->v.origin, &EnemyStuff);
|
||||
return AITAC_DeployableExistsAtLocation(ReinforceLocation, &EnemyStuff);
|
||||
}
|
||||
|
||||
bool AITASK_IsAlienSecureHiveTaskStillValid(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
|
||||
|
@ -1388,7 +1408,7 @@ void BotProgressReinforceStructureTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
|
|||
|
||||
DeployableSearchFilter StructureFilter;
|
||||
StructureFilter.DeployableTeam = BotTeam;
|
||||
StructureFilter.MaxSearchRadius = SearchRadius;
|
||||
StructureFilter.MaxSearchRadius = SearchRadius * 1.25f;
|
||||
StructureFilter.DeployableTypes = STRUCTURE_ALIEN_OFFENCECHAMBER;
|
||||
|
||||
int NumOCs = AITAC_GetNumDeployablesNearLocation(ReinforceLocation, &StructureFilter);
|
||||
|
@ -1443,6 +1463,14 @@ void BotProgressReinforceStructureTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
|
|||
}
|
||||
}
|
||||
|
||||
if (NextStructure == STRUCTURE_NONE)
|
||||
{
|
||||
int NumMissing = 0;
|
||||
AvHAIDeployableStructureType MissingStructure = AITAC_GetNextMissingUpgradeChamberForTeam(BotTeam, NumMissing);
|
||||
|
||||
NextStructure = MissingStructure;
|
||||
}
|
||||
|
||||
if (NextStructure != STRUCTURE_NONE)
|
||||
{
|
||||
if (vIsZero(Task->TaskLocation))
|
||||
|
|
Loading…
Reference in a new issue