2024-03-21 18:17:18 +00:00
# include "AvHAITask.h"
# include "AvHAINavigation.h"
# include "AvHAITactical.h"
# include "AvHAIMath.h"
# include "AvHAIPlayerUtil.h"
# include "AvHAIWeaponHelper.h"
# include "AvHAIHelper.h"
# include "AvHAIPlayerManager.h"
# include "AvHAIConfig.h"
# include "AvHSharedUtil.h"
# include "AvHAlienWeaponConstants.h"
# include "AvHMarineEquipmentConstants.h"
# include "AvHGamerules.h"
# include "AvHWeldable.h"
# include "AvHTurret.h"
extern nav_mesh NavMeshes [ MAX_NAV_MESHES ] ; // Array of nav meshes. Currently only 3 are used (building, onos, and regular)
extern nav_profile BaseNavProfiles [ MAX_NAV_PROFILES ] ; // Array of nav profiles
void AITASK_ClearAllBotTasks ( AvHAIPlayer * pBot )
{
AITASK_ClearBotTask ( pBot , & pBot - > PrimaryBotTask ) ;
AITASK_ClearBotTask ( pBot , & pBot - > SecondaryBotTask ) ;
AITASK_ClearBotTask ( pBot , & pBot - > WantsAndNeedsTask ) ;
AITASK_ClearBotTask ( pBot , & pBot - > CommanderTask ) ;
}
void AITASK_BotUpdateAndClearTasks ( AvHAIPlayer * pBot )
{
if ( pBot - > CommanderTask . TaskType ! = TASK_NONE )
{
if ( ! AITASK_IsTaskStillValid ( pBot , & pBot - > CommanderTask ) )
{
if ( AITASK_IsTaskCompleted ( pBot , & pBot - > CommanderTask ) )
{
AITASK_OnCompleteCommanderTask ( pBot , & pBot - > CommanderTask ) ;
}
else
{
AITASK_ClearBotTask ( pBot , & pBot - > CommanderTask ) ;
}
}
}
if ( pBot - > PrimaryBotTask . TaskType ! = TASK_NONE )
{
if ( ! AITASK_IsTaskStillValid ( pBot , & pBot - > PrimaryBotTask ) )
{
AITASK_ClearBotTask ( pBot , & pBot - > PrimaryBotTask ) ;
}
}
if ( pBot - > SecondaryBotTask . TaskType ! = TASK_NONE )
{
if ( ! AITASK_IsTaskStillValid ( pBot , & pBot - > SecondaryBotTask ) )
{
AITASK_ClearBotTask ( pBot , & pBot - > SecondaryBotTask ) ;
}
}
if ( pBot - > WantsAndNeedsTask . TaskType ! = TASK_NONE )
{
if ( ! AITASK_IsTaskStillValid ( pBot , & pBot - > WantsAndNeedsTask ) )
{
AITASK_ClearBotTask ( pBot , & pBot - > WantsAndNeedsTask ) ;
}
}
}
void AITASK_OnCompleteCommanderTask ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task )
{
if ( ! Task | | ! IsPlayerMarine ( pBot - > Edict ) ) { return ; }
BotTaskType OldTaskType = Task - > TaskType ;
AITASK_ClearBotTask ( pBot , Task ) ;
if ( OldTaskType = = TASK_GUARD )
{
UTIL_ClearGuardInfo ( pBot ) ;
}
if ( OldTaskType = = TASK_MOVE )
{
2024-04-05 14:53:19 +00:00
AvHTeamNumber BotTeam = pBot - > Player - > GetTeam ( ) ;
AvHTeamNumber EnemyTeam = AIMGR_GetEnemyTeam ( BotTeam ) ;
if ( AIMGR_GetTeamType ( EnemyTeam ) = = AVH_CLASS_TYPE_ALIEN )
{
const AvHAIHiveDefinition * NearestHive = AITAC_GetHiveNearestLocation ( pBot - > Edict - > v . origin ) ;
if ( NearestHive & & vDist2DSq ( NearestHive - > FloorLocation , pBot - > Edict - > v . origin ) < sqrf ( UTIL_MetresToGoldSrcUnits ( 15.0f ) ) )
{
if ( NearestHive - > Status = = HIVE_STATUS_UNBUILT )
{
AITASK_SetSecureHiveTask ( pBot , Task , NearestHive - > HiveEdict , NearestHive - > FloorLocation , false ) ;
Task - > bIssuedByCommander = true ;
return ;
}
else
{
if ( UTIL_PlayerHasLOSToEntity ( pBot - > Edict , NearestHive - > HiveEdict , UTIL_MetresToGoldSrcUnits ( 15.0f ) , false ) )
{
AITASK_SetAttackTask ( pBot , Task , NearestHive - > HiveEdict , false ) ;
Task - > bIssuedByCommander = true ;
return ;
}
}
}
}
else
{
if ( vDist2DSq ( pBot - > Edict - > v . origin , AITAC_GetTeamStartingLocation ( EnemyTeam ) ) < sqrf ( UTIL_MetresToGoldSrcUnits ( 10.0f ) ) )
{
DeployableSearchFilter EnemyStuffFilter ;
EnemyStuffFilter . DeployableTypes = SEARCH_ALL_STRUCTURES ;
EnemyStuffFilter . DeployableTeam = EnemyTeam ;
EnemyStuffFilter . ReachabilityFlags = pBot - > BotNavInfo . NavProfile . ReachabilityFlag ;
EnemyStuffFilter . ReachabilityTeam = ( AvHTeamNumber ) pBot - > Edict - > v . team ;
EnemyStuffFilter . MaxSearchRadius = UTIL_MetresToGoldSrcUnits ( 10.0f ) ;
AvHAIBuildableStructure NearbyEnemyStructure = AITAC_FindClosestDeployableToLocation ( AITAC_GetTeamStartingLocation ( EnemyTeam ) , & EnemyStuffFilter ) ;
if ( NearbyEnemyStructure . IsValid ( ) )
{
AITASK_SetAttackTask ( pBot , Task , NearbyEnemyStructure . edict , false ) ;
Task - > bIssuedByCommander = true ;
return ;
}
}
}
2024-03-21 18:17:18 +00:00
DeployableSearchFilter EnemyResTowerFilter ;
EnemyResTowerFilter . DeployableTypes = SEARCH_ANY_RES_TOWER ;
EnemyResTowerFilter . DeployableTeam = ( AIMGR_GetEnemyTeam ( pBot - > Player - > GetTeam ( ) ) ) ;
EnemyResTowerFilter . ReachabilityFlags = pBot - > BotNavInfo . NavProfile . ReachabilityFlag ;
EnemyResTowerFilter . ReachabilityTeam = ( AvHTeamNumber ) pBot - > Edict - > v . team ;
EnemyResTowerFilter . MaxSearchRadius = UTIL_MetresToGoldSrcUnits ( 5.0f ) ;
AvHAIBuildableStructure NearbyAlienTower = AITAC_FindClosestDeployableToLocation ( pBot - > Edict - > v . origin , & EnemyResTowerFilter ) ;
if ( NearbyAlienTower . IsValid ( ) )
{
const AvHAIResourceNode * NodeRef = AITAC_GetNearestResourceNodeToLocation ( NearbyAlienTower . Location ) ;
if ( NodeRef )
{
AITASK_SetCapResNodeTask ( pBot , Task , NodeRef , false ) ;
Task - > bIssuedByCommander = true ;
return ;
}
}
}
// After completing a move or build task, wait a bit in case the commander wants to do something else
if ( OldTaskType = = TASK_MOVE | | OldTaskType = = TASK_BUILD )
{
Task - > TaskType = TASK_GUARD ;
Task - > TaskLocation = pBot - > Edict - > v . origin ;
Task - > TaskLength = ( OldTaskType = = TASK_MOVE ) ? 30.0f : 20.0f ;
Task - > TaskStartedTime = gpGlobals - > time ;
Task - > bIssuedByCommander = true ;
}
}
void AITASK_ClearBotTask ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task )
{
if ( ! Task ) { return ; }
if ( Task - > TaskType = = TASK_GUARD )
{
UTIL_ClearGuardInfo ( pBot ) ;
}
Task - > TaskType = TASK_NONE ;
Task - > TaskLocation = g_vecZero ;
Task - > TaskTarget = nullptr ;
Task - > TaskSecondaryTarget = nullptr ;
Task - > TaskStartedTime = 0.0f ;
Task - > TaskLength = 0.0f ;
Task - > bIssuedByCommander = false ;
Task - > bTargetIsPlayer = false ;
Task - > bTaskIsUrgent = false ;
Task - > LastBuildAttemptTime = 0.0f ;
Task - > BuildAttempts = 0 ;
Task - > StructureType = STRUCTURE_NONE ;
memset ( & Task - > ActiveBuildInfo , 0 , sizeof ( AvHAIBuildAttempt ) ) ;
}
bool AITASK_IsTaskUrgent ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task )
{
if ( Task - > TaskType = = TASK_NONE ) { return false ; }
if ( Task - > bTaskIsUrgent ) { return true ; }
switch ( Task - > TaskType )
{
case TASK_GET_AMMO :
return ( UTIL_GetPlayerPrimaryAmmoReserve ( pBot - > Player ) = = 0 ) ;
case TASK_GET_HEALTH :
return Task - > bTaskIsUrgent | | ( ( IsPlayerMarine ( pBot - > Edict ) ) ? ( pBot - > Edict - > v . health < 50.0f ) : ( GetPlayerOverallHealthPercent ( pBot - > Edict ) < 0.5f ) ) ;
case TASK_ATTACK :
case TASK_GET_WEAPON :
case TASK_GET_EQUIPMENT :
case TASK_WELD :
return false ;
case TASK_RESUPPLY :
return ( pBot - > Edict - > v . health < 50.0f ) | | ( UTIL_GetPlayerPrimaryAmmoReserve ( pBot - > Player ) = = 0 ) ;
case TASK_MOVE :
return AITASK_IsMoveTaskUrgent ( pBot , Task ) ;
case TASK_BUILD :
return AITASK_IsBuildTaskUrgent ( pBot , Task ) ;
case TASK_GUARD :
return AITASK_IsGuardTaskUrgent ( pBot , Task ) ;
default :
return false ;
}
return false ;
}
bool AITASK_IsGuardTaskUrgent ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task )
{
if ( Task - > TaskTarget )
{
AvHAIDeployableStructureType StructType = GetStructureTypeFromEdict ( Task - > TaskTarget ) ;
if ( StructType = = STRUCTURE_MARINE_PHASEGATE | | StructType = = STRUCTURE_MARINE_TURRETFACTORY )
{
return true ;
}
}
return false ;
}
bool AITASK_IsBuildTaskUrgent ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task )
{
if ( ! Task - > TaskTarget ) { return false ; }
AvHAIDeployableStructureType StructType = GetStructureTypeFromEdict ( Task - > TaskTarget ) ;
if ( StructType = = STRUCTURE_MARINE_PHASEGATE | | StructType = = STRUCTURE_MARINE_TURRETFACTORY ) { return true ; }
return false ;
}
bool AITASK_IsMoveTaskUrgent ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task )
{
return false ; //UTIL_IsNearActiveHive(Task->TaskLocation, UTIL_MetresToGoldSrcUnits(30.0f)) || UTIL_IsAlienPlayerInArea(Task->TaskLocation, UTIL_MetresToGoldSrcUnits(20.0f));
}
AvHAIPlayerTask * BotGetNextTask ( AvHAIPlayer * pBot )
{
// Any orders issued by the commander take priority over everything else
if ( pBot - > CommanderTask . TaskType ! = TASK_NONE )
{
if ( pBot - > SecondaryBotTask . bTaskIsUrgent )
{
return & pBot - > SecondaryBotTask ;
}
else
{
return & pBot - > CommanderTask ;
}
}
// Prioritise healing our friends (heal tasks are only valid if the target is close by anyway)
if ( pBot - > SecondaryBotTask . TaskType = = TASK_HEAL )
{
return & pBot - > SecondaryBotTask ;
}
if ( AITASK_IsTaskUrgent ( pBot , & pBot - > WantsAndNeedsTask ) )
{
return & pBot - > WantsAndNeedsTask ;
}
if ( AITASK_IsTaskUrgent ( pBot , & pBot - > PrimaryBotTask ) )
{
return & pBot - > PrimaryBotTask ;
}
if ( AITASK_IsTaskUrgent ( pBot , & pBot - > SecondaryBotTask ) )
{
return & pBot - > SecondaryBotTask ;
}
if ( pBot - > WantsAndNeedsTask . TaskType ! = TASK_NONE )
{
return & pBot - > WantsAndNeedsTask ;
}
if ( pBot - > SecondaryBotTask . TaskType ! = TASK_NONE )
{
return & pBot - > SecondaryBotTask ;
}
return & pBot - > PrimaryBotTask ;
}
bool AITASK_IsTaskCompleted ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task )
{
if ( ! Task ) { return false ; }
switch ( Task - > TaskType )
{
case TASK_MOVE :
return vDist2DSq ( pBot - > Edict - > v . origin , Task - > TaskLocation ) < = sqrf ( max_player_use_reach ) ;
case TASK_BUILD :
return ! FNullEnt ( Task - > TaskTarget ) & & UTIL_StructureIsFullyBuilt ( Task - > TaskTarget ) ;
case TASK_ATTACK :
return FNullEnt ( Task - > TaskTarget ) | | ( Task - > TaskTarget - > v . effects & EF_NODRAW ) | | ( Task - > TaskTarget - > v . deadflag ! = DEAD_NO ) ;
case TASK_GUARD :
return ( gpGlobals - > time - Task - > TaskStartedTime ) > Task - > TaskLength ;
default :
return ! AITASK_IsTaskStillValid ( pBot , Task ) ;
}
return false ;
}
bool AITASK_IsTaskStillValid ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task )
{
if ( ! Task | | FNullEnt ( pBot - > Edict ) ) { return false ; }
if ( ( Task - > TaskStartedTime > 0.0f & & Task - > TaskLength > 0.0f ) & & ( gpGlobals - > time - Task - > TaskStartedTime > = Task - > TaskLength ) ) { return false ; }
switch ( Task - > TaskType )
{
case TASK_NONE :
return false ;
case TASK_MOVE :
return AITASK_IsMoveTaskStillValid ( pBot , Task ) ;
case TASK_GET_AMMO :
return AITASK_IsAmmoPickupTaskStillValid ( pBot , Task ) ;
case TASK_GET_HEALTH :
{
if ( IsPlayerMarine ( pBot - > Edict ) )
{
return AITASK_IsHealthPickupTaskStillValid ( pBot , Task ) ;
}
else
{
return AITASK_IsAlienGetHealthTaskStillValid ( pBot , Task ) ;
}
}
case TASK_GET_EQUIPMENT :
return AITASK_IsEquipmentPickupTaskStillValid ( pBot , Task ) ;
case TASK_GET_WEAPON :
return AITASK_IsWeaponPickupTaskStillValid ( pBot , Task ) ;
case TASK_RESUPPLY :
return AITASK_IsResupplyTaskStillValid ( pBot , Task ) ;
case TASK_ATTACK :
return AITASK_IsAttackTaskStillValid ( pBot , Task ) ;
case TASK_GUARD :
return AITASK_IsGuardTaskStillValid ( pBot , Task ) ;
case TASK_BUILD :
{
if ( IsPlayerMarine ( pBot - > Edict ) )
{
return AITASK_IsMarineBuildTaskStillValid ( pBot , Task ) ;
}
else
{
return AITASK_IsAlienBuildTaskStillValid ( pBot , Task ) ;
}
}
case TASK_CAP_RESNODE :
{
if ( IsPlayerMarine ( pBot - > Edict ) )
{
return AITASK_IsMarineCapResNodeTaskStillValid ( pBot , Task ) ;
}
else
{
return AITASK_IsAlienCapResNodeTaskStillValid ( pBot , Task ) ;
}
}
case TASK_REINFORCE_STRUCTURE :
return AITASK_IsReinforceStructureTaskStillValid ( pBot , Task ) ;
case TASK_SECURE_HIVE :
{
if ( IsPlayerMarine ( pBot - > Edict ) )
{
return AITASK_IsMarineSecureHiveTaskStillValid ( pBot , Task ) ;
}
else
{
return false ;
}
}
case TASK_DEFEND :
return AITASK_IsDefendTaskStillValid ( pBot , Task ) ;
case TASK_WELD :
return AITASK_IsWeldTaskStillValid ( pBot , Task ) ;
case TASK_EVOLVE :
return AITASK_IsEvolveTaskStillValid ( pBot , Task ) ;
case TASK_HEAL :
return AITASK_IsAlienHealTaskStillValid ( pBot , Task ) ;
case TASK_USE :
return AITASK_IsUseTaskStillValid ( pBot , Task ) ;
case TASK_PLACE_MINE :
return AITASK_IsMineStructureTaskStillValid ( pBot , Task ) ;
case TASK_TOUCH :
return AITASK_IsTouchTaskStillValid ( pBot , Task ) ;
default :
return false ;
}
return false ;
}
bool AITASK_IsTouchTaskStillValid ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task )
{
return ( ! FNullEnt ( Task - > TaskTarget ) & & ! IsPlayerTouchingEntity ( pBot - > Edict , Task - > TaskTarget ) ) ;
}
bool AITASK_IsMoveTaskStillValid ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task )
{
if ( vIsZero ( Task - > TaskLocation ) ) { return false ; }
if ( pBot - > BotNavInfo . NavProfile . bFlyingProfile & & vEquals ( pBot - > Edict - > v . origin , Task - > TaskLocation , 50.0f ) ) { return false ; }
return ( vDist2DSq ( pBot - > Edict - > v . origin , Task - > TaskLocation ) > sqrf ( GetPlayerRadius ( pBot - > Player ) ) | | fabsf ( pBot - > Edict - > v . origin . z - Task - > TaskLocation . z ) > 50.0f ) ;
}
bool AITASK_IsWeldTaskStillValid ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task )
{
if ( ! Task ) { return false ; }
if ( ! Task - > TaskTarget | | FNullEnt ( Task - > TaskTarget ) | | ( Task - > TaskTarget - > v . effects & EF_NODRAW ) | | Task - > TaskTarget - > v . deadflag ! = DEAD_NO ) { return false ; }
if ( Task - > TaskTarget = = pBot - > Edict ) { return false ; }
if ( ! PlayerHasWeapon ( pBot - > Player , WEAPON_MARINE_WELDER ) )
{
if ( FNullEnt ( Task - > TaskSecondaryTarget ) )
{
AvHAIDroppedItem * NearestWelder = AITAC_FindClosestItemToLocation ( pBot - > Edict - > v . origin , DEPLOYABLE_ITEM_WELDER , pBot - > Player - > GetTeam ( ) , pBot - > BotNavInfo . NavProfile . ReachabilityFlag , 0.0f , 0.0f , true ) ;
if ( NearestWelder )
{
Task - > TaskSecondaryTarget = NearestWelder - > edict ;
}
else
{
return false ;
}
}
}
if ( IsEdictPlayer ( Task - > TaskTarget ) )
{
if ( Task - > TaskTarget - > v . team ! = pBot - > Edict - > v . team | | ! IsPlayerMarine ( Task - > TaskTarget ) | | ! IsPlayerActiveInGame ( Task - > TaskTarget ) ) { return false ; }
return ( Task - > TaskTarget - > v . armorvalue < GetPlayerMaxArmour ( Task - > TaskTarget ) ) ;
}
else
{
if ( IsEdictStructure ( Task - > TaskTarget ) )
{
if ( Task - > TaskTarget - > v . team ! = pBot - > Edict - > v . team | | ! UTIL_IsBuildableStructureStillReachable ( pBot , Task - > TaskTarget ) ) { return false ; }
return ( Task - > TaskTarget - > v . health < Task - > TaskTarget - > v . max_health ) ;
}
AvHWeldable * WeldableRef = dynamic_cast < AvHWeldable * > ( CBaseEntity : : Instance ( Task - > TaskTarget ) ) ;
if ( WeldableRef )
{
return ! WeldableRef - > GetIsWelded ( ) ;
}
}
return false ;
}
bool AITASK_IsAmmoPickupTaskStillValid ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task )
{
if ( FNullEnt ( Task - > TaskTarget ) | | ! IsPlayerMarine ( pBot - > Edict ) | | ! IsPlayerActiveInGame ( pBot - > Edict ) | | ( Task - > TaskTarget - > v . effects & EF_NODRAW ) ) { return false ; }
if ( ! UTIL_IsDroppedItemStillReachable ( pBot , Task - > TaskTarget ) ) { return false ; }
return ( vDist2DSq ( pBot - > Edict - > v . origin , Task - > TaskTarget - > v . origin ) < sqrf ( UTIL_MetresToGoldSrcUnits ( 20.0f ) ) ) & & ( UTIL_GetPlayerPrimaryAmmoReserve ( pBot - > Player ) < UTIL_GetPlayerPrimaryMaxAmmoReserve ( pBot - > Player ) ) ;
}
bool AITASK_IsHealthPickupTaskStillValid ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task )
{
if ( FNullEnt ( Task - > TaskTarget ) | | ! IsPlayerMarine ( pBot - > Edict ) | | ! IsPlayerActiveInGame ( pBot - > Edict ) | | ( Task - > TaskTarget - > v . effects & EF_NODRAW ) ) { return false ; }
if ( ! UTIL_IsDroppedItemStillReachable ( pBot , Task - > TaskTarget ) ) { return false ; }
return ( ( vDist2DSq ( pBot - > Edict - > v . origin , Task - > TaskTarget - > v . origin ) < sqrf ( UTIL_MetresToGoldSrcUnits ( 20.0f ) ) ) & & ( pBot - > Edict - > v . health < pBot - > Edict - > v . max_health ) ) ;
}
bool AITASK_IsEquipmentPickupTaskStillValid ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task )
{
if ( FNullEnt ( Task - > TaskTarget ) | | ! IsPlayerMarine ( pBot - > Edict ) | | ! IsPlayerActiveInGame ( pBot - > Edict ) | | ( Task - > TaskTarget - > v . effects & EF_NODRAW ) ) { return false ; }
if ( ! UTIL_IsDroppedItemStillReachable ( pBot , Task - > TaskTarget ) ) { return false ; }
return ! PlayerHasEquipment ( pBot - > Edict ) ;
}
bool AITASK_IsWeaponPickupTaskStillValid ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task )
{
if ( FNullEnt ( Task - > TaskTarget ) | | ! IsPlayerMarine ( pBot - > Edict ) | | ! IsPlayerActiveInGame ( pBot - > Edict ) | | ( Task - > TaskTarget - > v . effects & EF_NODRAW ) ) { return false ; }
if ( ! UTIL_IsDroppedItemStillReachable ( pBot , Task - > TaskTarget ) ) { return false ; }
AvHAIWeapon WeaponType = UTIL_GetWeaponTypeFromEdict ( Task - > TaskTarget ) ;
if ( WeaponType = = WEAPON_INVALID ) { return false ; }
return ! PlayerHasWeapon ( pBot - > Player , WeaponType ) ;
}
bool AITASK_IsAttackTaskStillValid ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task )
{
if ( ! Task - > TaskTarget | | FNullEnt ( Task - > TaskTarget ) | | ( Task - > TaskTarget - > v . effects & EF_NODRAW ) | | Task - > TaskTarget - > v . deadflag ! = DEAD_NO ) { return false ; }
if ( ( vIsZero ( Task - > TaskTarget - > v . origin ) & & vIsZero ( Task - > TaskLocation ) ) ) { return false ; }
if ( ( Task - > TaskTarget - > v . effects & EF_NODRAW ) | | ( Task - > TaskTarget - > v . deadflag ! = DEAD_NO ) ) { return false ; }
if ( IsEdictStructure ( Task - > TaskTarget ) & & ! UTIL_IsBuildableStructureStillReachable ( pBot , Task - > TaskTarget ) ) { return false ; }
if ( IsPlayerSkulk ( pBot - > Edict ) )
{
if ( UTIL_IsStructureElectrified ( Task - > TaskTarget ) ) { return false ; }
}
if ( IsPlayerGorge ( pBot - > Edict ) & & ( Task - > TaskTarget - > v . health > 100 & & ! PlayerHasWeapon ( pBot - > Player , WEAPON_GORGE_BILEBOMB ) ) ) { return false ; }
AvHAIDeployableStructureType StructureType = GetStructureTypeFromEdict ( Task - > TaskTarget ) ;
if ( IsPlayerMarine ( pBot - > Edict ) )
{
if ( StructureType = = STRUCTURE_ALIEN_HIVE | | StructureType = = STRUCTURE_ALIEN_OFFENCECHAMBER )
{
if ( UTIL_GetPlayerPrimaryWeaponClipAmmo ( pBot - > Player ) < = 0 & & UTIL_GetPlayerPrimaryAmmoReserve ( pBot - > Player ) < = 0 )
{
return false ;
}
}
}
return Task - > TaskTarget - > v . team ! = pBot - > Edict - > v . team ;
}
bool AITASK_IsResupplyTaskStillValid ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task )
{
if ( FNullEnt ( Task - > TaskTarget ) | | ! IsPlayerMarine ( pBot - > Edict ) | | ! IsPlayerActiveInGame ( pBot - > Edict ) | | ( Task - > TaskTarget - > v . deadflag ! = DEAD_NO ) ) { return false ; }
if ( ! UTIL_IsBuildableStructureStillReachable ( pBot , Task - > TaskTarget ) ) { return false ; }
AvHAIDeployableStructureType StructureType = GetStructureTypeFromEdict ( Task - > TaskTarget ) ;
if ( StructureType ! = STRUCTURE_MARINE_ARMOURY & & StructureType ! = STRUCTURE_MARINE_ADVARMOURY ) { return false ; }
if ( ! UTIL_StructureIsFullyBuilt ( Task - > TaskTarget ) | | UTIL_StructureIsRecycling ( Task - > TaskTarget ) ) { return false ; }
2024-04-12 15:40:50 +00:00
if ( IsAreaAffectedBySpores ( Task - > TaskTarget - > v . origin ) & & ! PlayerHasHeavyArmour ( pBot - > Edict ) ) { return false ; }
2024-04-05 20:34:50 +00:00
return (
( pBot - > Edict - > v . health < pBot - > Edict - > v . max_health )
| | ( UTIL_GetPlayerPrimaryAmmoReserve ( pBot - > Player ) < UTIL_GetPlayerPrimaryMaxAmmoReserve ( pBot - > Player ) )
| | ( UTIL_GetPlayerSecondaryAmmoReserve ( pBot - > Player ) < UTIL_GetPlayerSecondaryMaxAmmoReserve ( pBot - > Player ) )
2024-03-21 18:17:18 +00:00
) ;
}
bool AITASK_IsGuardTaskStillValid ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task )
{
if ( ! Task ) { return false ; }
if ( vIsZero ( Task - > TaskLocation ) )
{
return false ;
}
2024-03-25 20:46:54 +00:00
if ( Task - > TaskLength > 0.0f & & Task - > TaskStartedTime > 0.0f )
{
return ( gpGlobals - > time - Task - > TaskStartedTime < Task - > TaskLength ) ;
}
2024-03-21 18:17:18 +00:00
return true ;
}
bool AITASK_IsMineStructureTaskStillValid ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task )
{
if ( ! Task - > TaskTarget | | FNullEnt ( Task - > TaskTarget ) | | ( Task - > TaskTarget - > v . effects & EF_NODRAW ) | | Task - > TaskTarget - > v . deadflag ! = DEAD_NO ) { return false ; }
if ( UTIL_StructureIsRecycling ( Task - > TaskTarget ) ) { return false ; }
if ( ! PlayerHasWeapon ( pBot - > Player , WEAPON_MARINE_MINES ) ) { return false ; }
DeployableSearchFilter MineFilter ;
MineFilter . DeployableTypes = STRUCTURE_MARINE_DEPLOYEDMINE ;
MineFilter . MaxSearchRadius = UTIL_MetresToGoldSrcUnits ( 2.0f ) ;
MineFilter . bConsiderPhaseDistance = false ;
MineFilter . DeployableTeam = pBot - > Player - > GetTeam ( ) ;
if ( AITAC_GetNumDeployablesNearLocation ( Task - > TaskTarget - > v . origin , & MineFilter ) > = 4 ) { return false ; }
return true ;
}
bool AITASK_IsMarineBuildTaskStillValid ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task )
{
if ( FNullEnt ( Task - > TaskTarget ) | | ( Task - > TaskTarget - > v . effects & EF_NODRAW ) | | ( Task - > TaskTarget - > v . deadflag ! = DEAD_NO ) ) { return false ; }
AvHAIDeployableStructureType StructureType = GetStructureTypeFromEdict ( Task - > TaskTarget ) ;
if ( StructureType = = STRUCTURE_NONE ) { return false ; }
if ( ! UTIL_IsBuildableStructureStillReachable ( pBot , Task - > TaskTarget ) ) { return false ; }
if ( UTIL_StructureIsRecycling ( Task - > TaskTarget ) )
{
return false ;
}
// Always go build if commanded to, regardless of how many are already working on it
if ( ! Task - > bIssuedByCommander )
{
int NumBuilders = AITAC_GetNumPlayersOfTeamInArea ( ( AvHTeamNumber ) pBot - > Edict - > v . team , Task - > TaskTarget - > v . origin , UTIL_MetresToGoldSrcUnits ( 2.0f ) , false , pBot - > Edict , AVH_USER3_NONE ) ;
// Only one marine should build stuff if it's near the marine base. If not, then two for safety
int NumDesiredBuilders = ( vDist2DSq ( Task - > TaskTarget - > v . origin , AITAC_GetCommChairLocation ( pBot - > Player - > GetTeam ( ) ) ) < sqrf ( UTIL_MetresToGoldSrcUnits ( 15.0f ) ) ) ? 1 : 2 ;
if ( NumBuilders > = NumDesiredBuilders )
{
return false ;
}
}
return ! UTIL_StructureIsFullyBuilt ( Task - > TaskTarget ) ;
}
bool AITASK_IsAlienBuildTaskStillValid ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task )
{
if ( ! Task ) { return false ; }
if ( vIsZero ( Task - > TaskLocation ) ) { return false ; }
if ( Task - > StructureType = = STRUCTURE_NONE ) { return false ; }
if ( Task - > ActiveBuildInfo . BuildStatus = = BUILD_ATTEMPT_PENDING ) { return true ; }
if ( Task - > ActiveBuildInfo . BuildStatus = = BUILD_ATTEMPT_FAILED & & Task - > ActiveBuildInfo . NumAttempts > = 3 ) { return false ; }
if ( Task - > ActiveBuildInfo . LinkedStructure & & ( UTIL_StructureIsFullyBuilt ( Task - > ActiveBuildInfo . LinkedStructure - > edict ) | | ! UTIL_IsBuildableStructureStillReachable ( pBot , Task - > ActiveBuildInfo . LinkedStructure - > edict ) ) ) { return false ; }
if ( Task - > StructureType = = STRUCTURE_ALIEN_HIVE )
{
const AvHAIHiveDefinition * HiveIndex = AITAC_GetHiveNearestLocation ( Task - > TaskLocation ) ;
if ( ! HiveIndex ) { return false ; }
if ( HiveIndex - > Status ! = HIVE_STATUS_UNBUILT ) { return false ; }
}
if ( Task - > StructureType = = STRUCTURE_ALIEN_RESTOWER )
{
const AvHAIResourceNode * ResNodeIndex = AITAC_GetNearestResourceNodeToLocation ( Task - > TaskLocation ) ;
if ( ! ResNodeIndex ) { return false ; }
if ( ResNodeIndex - > bIsOccupied )
{
if ( ResNodeIndex - > OwningTeam ! = pBot - > Player - > GetTeam ( ) ) { return false ; } // Node has been capped by the enemy, no longer relevant
if ( UTIL_StructureIsFullyBuilt ( ResNodeIndex - > ActiveTowerEntity ) ) { return false ; } // Don't bother if it's already completed
}
return true ;
}
return UTIL_GetNavAreaAtLocation ( Task - > TaskLocation ) = = SAMPLE_POLYAREA_GROUND ;
}
bool AITASK_IsAlienCapResNodeTaskStillValid ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task )
{
if ( vIsZero ( Task - > TaskLocation ) )
{
return false ;
}
const AvHAIResourceNode * ResNodeIndex = AITAC_GetNearestResourceNodeToLocation ( Task - > TaskLocation ) ;
if ( ! ResNodeIndex )
{
return false ;
}
AvHTeamNumber BotTeam = pBot - > Player - > GetTeam ( ) ;
AvHTeamNumber EnemyTeam = AIMGR_GetEnemyTeam ( BotTeam ) ;
if ( ResNodeIndex - > bIsBaseNode )
{
if ( FNullEnt ( ResNodeIndex - > ParentHive ) ) { return false ; } // This is the marine base res node, leave it alone
AvHAIHiveDefinition * ParentHive = AITAC_GetHiveFromEdict ( ResNodeIndex - > ParentHive ) ;
// An enemy is now building the hive that this res node belongs to, abort
if ( ParentHive & & ParentHive - > OwningTeam = = EnemyTeam ) { return false ; }
}
// Don't waste resources switching down to gorge if we're a lerk, fade or onos
// but we can still clear the area of enemy structures
if ( ! IsPlayerSkulk ( pBot - > Edict ) & & ! IsPlayerGorge ( pBot - > Edict ) )
{
DeployableSearchFilter EnemyStructuresFilter ;
EnemyStructuresFilter . DeployableTeam = EnemyTeam ;
EnemyStructuresFilter . ReachabilityTeam = BotTeam ;
EnemyStructuresFilter . ReachabilityFlags = pBot - > BotNavInfo . NavProfile . ReachabilityFlag ;
EnemyStructuresFilter . MaxSearchRadius = UTIL_MetresToGoldSrcUnits ( 5.0f ) ;
return AITAC_DeployableExistsAtLocation ( ResNodeIndex - > Location , & EnemyStructuresFilter ) ;
}
if ( ! FNullEnt ( ResNodeIndex - > ParentHive ) )
{
DeployableSearchFilter EnemyStructuresFilter ;
EnemyStructuresFilter . DeployableTeam = EnemyTeam ;
EnemyStructuresFilter . IncludeStatusFlags = STRUCTURE_STATUS_COMPLETED ;
EnemyStructuresFilter . ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING ;
EnemyStructuresFilter . MaxSearchRadius = UTIL_MetresToGoldSrcUnits ( 15.0f ) ;
if ( AIMGR_GetTeamType ( EnemyTeam ) = = AVH_CLASS_TYPE_MARINE )
{
EnemyStructuresFilter . DeployableTypes = ( STRUCTURE_MARINE_PHASEGATE | STRUCTURE_MARINE_TURRETFACTORY | STRUCTURE_MARINE_ADVTURRETFACTORY ) ;
}
else
{
EnemyStructuresFilter . DeployableTypes = ( STRUCTURE_ALIEN_OFFENCECHAMBER ) ;
}
// Enemy has started fortifying the hive we want to build a RT in, abort
if ( AITAC_DeployableExistsAtLocation ( ResNodeIndex - > Location , & EnemyStructuresFilter ) ) { return false ; }
}
// We can attack structures basically if we aren't stuck with Gorge's spit attack
bool bCanAttackStructures = ( ! IsPlayerGorge ( pBot - > Edict ) | | PlayerHasWeapon ( pBot - > Player , WEAPON_GORGE_BILEBOMB ) ) ;
if ( ResNodeIndex - > bIsOccupied )
{
// If we have a tower on the node, we can still help build it if it's not finished yet,
// or we can clear the area if we're able to
if ( ResNodeIndex - > OwningTeam = = BotTeam )
{
if ( IsPlayerGorge ( pBot - > Edict ) & & ! UTIL_StructureIsFullyBuilt ( ResNodeIndex - > ActiveTowerEntity ) ) { return true ; }
// If the tower is fully built and we don't have bile bomb then our work here is done
if ( ! bCanAttackStructures ) { return false ; }
// If we can clear the area of enemy junk then do so, otherwise we're finished
DeployableSearchFilter EnemyStructuresFilter ;
EnemyStructuresFilter . DeployableTeam = AIMGR_GetEnemyTeam ( BotTeam ) ;
EnemyStructuresFilter . ReachabilityTeam = BotTeam ;
EnemyStructuresFilter . ReachabilityFlags = pBot - > BotNavInfo . NavProfile . ReachabilityFlag ;
EnemyStructuresFilter . MaxSearchRadius = UTIL_MetresToGoldSrcUnits ( 5.0f ) ;
return AITAC_DeployableExistsAtLocation ( ResNodeIndex - > Location , & EnemyStructuresFilter ) ;
}
else
{
// Enemy owns the res node, but we can cap it if we're able to attack structures, or there's a friend in the area who can.
return ( bCanAttackStructures | | AITAC_GetNumPlayersOfTeamInArea ( BotTeam , ResNodeIndex - > Location , UTIL_MetresToGoldSrcUnits ( 5.0f ) , false , pBot - > Edict , AVH_USER3_ALIEN_PLAYER2 ) > 0 ) ;
}
}
// If another gorge is claiming this spot, then move on
if ( ! IsPlayerGorge ( pBot - > Edict ) )
{
edict_t * OtherBuilder = AITAC_GetNearestPlayerOfClassInArea ( pBot - > Player - > GetTeam ( ) , ResNodeIndex - > Location , UTIL_MetresToGoldSrcUnits ( 5.0f ) , false , pBot - > Edict , AVH_USER3_ALIEN_PLAYER2 ) ;
if ( ! FNullEnt ( OtherBuilder ) )
{
if ( GetPlayerResources ( OtherBuilder ) > = ( int ) ( kResourceTowerCost * 0.7f ) )
{
// If we can clear the area of enemy junk then do so, otherwise we will let the other guy place the tower
DeployableSearchFilter EnemyStructuresFilter ;
EnemyStructuresFilter . DeployableTeam = AIMGR_GetEnemyTeam ( BotTeam ) ;
EnemyStructuresFilter . ReachabilityTeam = BotTeam ;
EnemyStructuresFilter . ReachabilityFlags = pBot - > BotNavInfo . NavProfile . ReachabilityFlag ;
EnemyStructuresFilter . MaxSearchRadius = UTIL_MetresToGoldSrcUnits ( 5.0f ) ;
return AITAC_DeployableExistsAtLocation ( ResNodeIndex - > Location , & EnemyStructuresFilter ) ;
}
}
}
return true ;
}
bool AITASK_IsMarineCapResNodeTaskStillValid ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task )
{
if ( ! Task | | vIsZero ( Task - > TaskLocation ) ) { return false ; }
const AvHAIResourceNode * ResNodeIndex = AITAC_GetNearestResourceNodeToLocation ( Task - > TaskLocation ) ;
if ( ! ResNodeIndex ) { return false ; }
AvHTeamNumber BotTeam = pBot - > Player - > GetTeam ( ) ;
// Always obey commander orders even if there's a bunch of other marines already there, otherwise don't bother if someone else is securing it
if ( ! Task - > bIssuedByCommander )
{
int DesiredNumCappers = ( ResNodeIndex - > OwningTeam = = AIMGR_GetEnemyTeam ( pBot - > Player - > GetTeam ( ) ) ) ? 2 : 1 ;
int NumMarinesNearby = AITAC_GetNumPlayersOfTeamInArea ( pBot - > Player - > GetTeam ( ) , Task - > TaskLocation , UTIL_MetresToGoldSrcUnits ( 4.0f ) , false , pBot - > Edict , AVH_USER3_COMMANDER_PLAYER ) ;
if ( NumMarinesNearby > = DesiredNumCappers & & vDist2DSq ( pBot - > Edict - > v . origin , Task - > TaskLocation ) > sqrf ( UTIL_MetresToGoldSrcUnits ( 4.0f ) ) ) { return false ; }
}
// Obviously still valid task if the node is empty
if ( ! ResNodeIndex - > bIsOccupied ) { return true ; }
// Also obviously still valid if it's owned by the enemy
if ( ResNodeIndex - > OwningTeam ! = BotTeam ) { return true ; }
// Likewise, still valid if there isn't a tower or it's not fully built
if ( FNullEnt ( ResNodeIndex - > ActiveTowerEntity ) | | ! UTIL_StructureIsFullyBuilt ( ResNodeIndex - > ActiveTowerEntity ) ) { return true ; }
// At this point, the node is capped fully. However, don't consider a res node secured if the enemy still has their junk lying around. Clear it all out.
DeployableSearchFilter EnemyStructures ;
EnemyStructures . DeployableTypes = SEARCH_ALL_STRUCTURES ;
EnemyStructures . DeployableTeam = AIMGR_GetEnemyTeam ( BotTeam ) ;
EnemyStructures . ReachabilityTeam = BotTeam ;
EnemyStructures . ReachabilityFlags = pBot - > BotNavInfo . NavProfile . ReachabilityFlag ;
EnemyStructures . MaxSearchRadius = UTIL_MetresToGoldSrcUnits ( 5.0f ) ;
return AITAC_DeployableExistsAtLocation ( ResNodeIndex - > Location , & EnemyStructures ) ;
}
bool AITASK_IsDefendTaskStillValid ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task )
{
if ( ! Task - > TaskTarget | | FNullEnt ( Task - > TaskTarget ) | | ( Task - > TaskTarget - > v . effects & EF_NODRAW ) | | Task - > TaskTarget - > v . deadflag ! = DEAD_NO ) { return false ; }
if ( GetStructureTypeFromEdict ( Task - > TaskTarget ) = = STRUCTURE_NONE ) { return false ; }
if ( ! UTIL_IsBuildableStructureStillReachable ( pBot , Task - > TaskTarget ) ) { return false ; }
if ( Task - > TaskTarget - > v . team ! = pBot - > Edict - > v . team ) { return false ; }
int NumExistingDefenders = AITAC_GetNumPlayersOfTeamInArea ( pBot - > Player - > GetTeam ( ) , Task - > TaskTarget - > v . origin , UTIL_MetresToGoldSrcUnits ( 10.0f ) , false , pBot - > Edict , AVH_USER3_ALIEN_PLAYER2 ) ;
if ( NumExistingDefenders > = 2 ) { return false ; }
if ( gpGlobals - > time - pBot - > LastCombatTime < 5.0f ) { return true ; }
if ( vDist2DSq ( pBot - > Edict - > v . origin , Task - > TaskTarget - > v . origin ) < = sqrf ( UTIL_MetresToGoldSrcUnits ( 5.0f ) ) & & gpGlobals - > time - pBot - > LastCombatTime > 10.0f ) { return false ; }
return true ;
}
bool AITASK_IsReinforceStructureTaskStillValid ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task )
{
if ( ! Task - > TaskTarget | | FNullEnt ( Task - > TaskTarget ) | | ( Task - > TaskTarget - > v . effects & EF_NODRAW ) | | Task - > TaskTarget - > v . deadflag ! = DEAD_NO ) { return false ; }
if ( ! FNullEnt ( Task - > TaskSecondaryTarget ) & & ! UTIL_StructureIsFullyBuilt ( Task - > TaskSecondaryTarget ) ) { return true ; }
AvHTeamNumber BotTeam = pBot - > Player - > GetTeam ( ) ;
2024-04-25 18:28:50 +00:00
AvHTeamNumber EnemyTeam = AIMGR_GetEnemyTeam ( BotTeam ) ;
2024-03-21 18:17:18 +00:00
2024-04-25 18:28:50 +00:00
if ( Task - > TaskTarget - > v . team = = EnemyTeam ) { return false ; }
2024-03-21 18:17:18 +00:00
// The reinforce structure task is true if we have an undecided hive available that we could build a new chamber with
bool bActiveHiveWithoutTechExists = AITAC_TeamHiveWithTechExists ( pBot - > Player - > GetTeam ( ) , MESSAGE_NULL ) ;
if ( bActiveHiveWithoutTechExists ) { return true ; }
DeployableSearchFilter StructureFilter ;
StructureFilter . DeployableTypes = STRUCTURE_ALIEN_OFFENCECHAMBER | ALIEN_BUILD_DEFENSE_CHAMBER | ALIEN_BUILD_MOVEMENT_CHAMBER | ALIEN_BUILD_SENSORY_CHAMBER ;
StructureFilter . MaxSearchRadius = UTIL_MetresToGoldSrcUnits ( 5.0f ) ;
StructureFilter . DeployableTeam = pBot - > Player - > GetTeam ( ) ;
vector < AvHAIBuildableStructure > AllNearbyStructures = AITAC_FindAllDeployables ( Task - > TaskTarget - > v . origin , & StructureFilter ) ;
bool bUnfinishedStructureExists = false ;
int NumOffenceChambers = 0 ;
int NumDefenceChambers = 0 ;
int NumMovementChambers = 0 ;
int NumSensoryChambers = 0 ;
for ( auto it = AllNearbyStructures . begin ( ) ; it ! = AllNearbyStructures . end ( ) ; it + + )
{
AvHAIBuildableStructure ThisStructure = ( * it ) ;
if ( ! ( ThisStructure . StructureStatusFlags & STRUCTURE_STATUS_COMPLETED ) ) { bUnfinishedStructureExists = true ; }
switch ( ThisStructure . StructureType )
{
case STRUCTURE_ALIEN_OFFENCECHAMBER :
NumOffenceChambers + + ;
break ;
case STRUCTURE_ALIEN_DEFENCECHAMBER :
NumDefenceChambers + + ;
break ;
case STRUCTURE_ALIEN_MOVEMENTCHAMBER :
NumMovementChambers + + ;
break ;
case STRUCTURE_ALIEN_SENSORYCHAMBER :
NumSensoryChambers + + ;
break ;
default :
break ;
}
}
// 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
| | ( 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 ) ) )
) { return true ; }
// Otherwise, are there any enemy structures lying around we could clear out?
bool bCanAttackStructures = ( ! IsPlayerGorge ( pBot - > Edict ) | | PlayerHasWeapon ( pBot - > Player , WEAPON_GORGE_BILEBOMB ) ) ;
if ( ! bCanAttackStructures ) { return false ; }
DeployableSearchFilter EnemyStuff ;
EnemyStuff . DeployableTypes = SEARCH_ALL_STRUCTURES ;
EnemyStuff . DeployableTeam = AIMGR_GetEnemyTeam ( BotTeam ) ;
EnemyStuff . ReachabilityTeam = BotTeam ;
EnemyStuff . ReachabilityFlags = pBot - > BotNavInfo . NavProfile . ReachabilityFlag ;
EnemyStuff . MaxSearchRadius = UTIL_MetresToGoldSrcUnits ( 5.0f ) ;
return AITAC_DeployableExistsAtLocation ( Task - > TaskTarget - > v . origin , & EnemyStuff ) ;
}
bool AITASK_IsMarineSecureHiveTaskStillValid ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task )
{
if ( ! Task | | FNullEnt ( Task - > TaskTarget ) | | IsPlayerAlien ( pBot - > Edict ) ) { return false ; }
AvHAIHiveDefinition * HiveToSecure = AITAC_GetHiveFromEdict ( Task - > TaskTarget ) ;
if ( ! HiveToSecure | | HiveToSecure - > Status ! = HIVE_STATUS_UNBUILT ) { return false ; }
// A marine bot will consider their "secure hive" task completed if the following structures have been fully built:
// Phase gate (only if tech available)
// Turret factory (regular or advanced)
// 5 turrets
// Resource node has been capped by the bot's team
AvHTeamNumber BotTeam = pBot - > Player - > GetTeam ( ) ;
bool bPhaseGatesAvailable = AITAC_PhaseGatesAvailable ( BotTeam ) ;
bool bHasPhaseGate = false ;
bool bHasTurretFactory = false ;
bool bTurretFactoryElectrified = false ;
int NumTurrets = 0 ;
DeployableSearchFilter SearchFilter ;
SearchFilter . DeployableTypes = ( STRUCTURE_MARINE_PHASEGATE | STRUCTURE_MARINE_TURRETFACTORY | STRUCTURE_MARINE_ADVTURRETFACTORY ) ;
SearchFilter . DeployableTeam = BotTeam ;
SearchFilter . IncludeStatusFlags = STRUCTURE_STATUS_COMPLETED ;
SearchFilter . ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING ;
SearchFilter . MaxSearchRadius = UTIL_MetresToGoldSrcUnits ( 15.0f ) ;
vector < AvHAIBuildableStructure > HiveStructures = AITAC_FindAllDeployables ( HiveToSecure - > FloorLocation , & SearchFilter ) ;
for ( auto it = HiveStructures . begin ( ) ; it ! = HiveStructures . end ( ) ; it + + )
{
AvHAIBuildableStructure Structure = ( * it ) ;
if ( Structure . StructureType = = STRUCTURE_MARINE_PHASEGATE )
{
bHasPhaseGate = true ;
}
if ( Structure . StructureType = = STRUCTURE_MARINE_TURRETFACTORY | | Structure . StructureType = = STRUCTURE_MARINE_ADVTURRETFACTORY )
{
bHasTurretFactory = true ;
SearchFilter . DeployableTypes = STRUCTURE_MARINE_TURRET ;
SearchFilter . MaxSearchRadius = UTIL_MetresToGoldSrcUnits ( 8.0f ) ;
NumTurrets = AITAC_GetNumDeployablesNearLocation ( Structure . Location , & SearchFilter ) ;
}
}
const AvHAIResourceNode * ResNode = HiveToSecure - > HiveResNodeRef ;
bool bSecuredResNode = ( ! ResNode | | ( ResNode - > OwningTeam = = BotTeam & & ! FNullEnt ( ResNode - > ActiveTowerEntity ) & & UTIL_StructureIsFullyBuilt ( ResNode - > ActiveTowerEntity ) ) ) ;
if ( ( bPhaseGatesAvailable & & ! bHasPhaseGate ) | | ! bHasTurretFactory | | NumTurrets < 5 ) { return true ; }
// Don't consider a hive secured if the enemy still has their junk in there. Clear it all out.
DeployableSearchFilter EnemyStructures ;
EnemyStructures . DeployableTypes = SEARCH_ALL_STRUCTURES ;
EnemyStructures . DeployableTeam = AIMGR_GetEnemyTeam ( BotTeam ) ;
EnemyStructures . ReachabilityTeam = BotTeam ;
EnemyStructures . ReachabilityFlags = pBot - > BotNavInfo . NavProfile . ReachabilityFlag ;
EnemyStructures . MaxSearchRadius = UTIL_MetresToGoldSrcUnits ( 15.0f ) ;
return AITAC_DeployableExistsAtLocation ( HiveToSecure - > FloorLocation , & EnemyStructures ) ;
}
bool AITASK_IsEvolveTaskStillValid ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task )
{
if ( ! Task | | Task - > Evolution = = MESSAGE_NULL | | ! IsPlayerAlien ( pBot - > Edict ) ) { return false ; }
switch ( Task - > Evolution )
{
case ALIEN_LIFEFORM_ONE :
return ! IsPlayerSkulk ( pBot - > Edict ) ;
case ALIEN_LIFEFORM_TWO :
return ! IsPlayerGorge ( pBot - > Edict ) & & pBot - > Player - > GetResources ( ) > = BALANCE_VAR ( kGorgeCost ) ;
case ALIEN_LIFEFORM_THREE :
return ! IsPlayerLerk ( pBot - > Edict ) & & pBot - > Player - > GetResources ( ) > = BALANCE_VAR ( kLerkCost ) ;
case ALIEN_LIFEFORM_FOUR :
return ! IsPlayerFade ( pBot - > Edict ) & & pBot - > Player - > GetResources ( ) > = BALANCE_VAR ( kFadeCost ) ;
case ALIEN_LIFEFORM_FIVE :
return ! IsPlayerOnos ( pBot - > Edict ) & & pBot - > Player - > GetResources ( ) > = BALANCE_VAR ( kOnosCost ) & & ( AITAC_GetNumPlayersOnTeamOfClass ( pBot - > Player - > GetTeam ( ) , AVH_USER3_ALIEN_PLAYER5 , nullptr ) < 2 ) ;
2024-04-05 14:53:19 +00:00
case ALIEN_EVOLUTION_ONE :
case ALIEN_EVOLUTION_TWO :
case ALIEN_EVOLUTION_THREE :
return ( ! PlayerHasAlienUpgradeOfType ( pBot - > Edict , HIVE_TECH_DEFENCE ) & & AITAC_IsAlienUpgradeAvailableForTeam ( pBot - > Player - > GetTeam ( ) , HIVE_TECH_DEFENCE ) ) ;
case ALIEN_EVOLUTION_SEVEN :
case ALIEN_EVOLUTION_EIGHT :
case ALIEN_EVOLUTION_NINE :
return ( ! PlayerHasAlienUpgradeOfType ( pBot - > Edict , HIVE_TECH_MOVEMENT ) & & AITAC_IsAlienUpgradeAvailableForTeam ( pBot - > Player - > GetTeam ( ) , HIVE_TECH_MOVEMENT ) ) ;
case ALIEN_EVOLUTION_TEN :
case ALIEN_EVOLUTION_ELEVEN :
case ALIEN_EVOLUTION_TWELVE :
return ( ! PlayerHasAlienUpgradeOfType ( pBot - > Edict , HIVE_TECH_SENSORY ) & & AITAC_IsAlienUpgradeAvailableForTeam ( pBot - > Player - > GetTeam ( ) , HIVE_TECH_SENSORY ) ) ;
2024-03-21 18:17:18 +00:00
default :
return false ;
}
return false ;
}
bool AITASK_IsAlienGetHealthTaskStillValid ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task )
{
if ( FNullEnt ( Task - > TaskTarget ) | | ( Task - > TaskTarget - > v . deadflag ! = DEAD_NO ) ) { return false ; }
if ( IsEdictHive ( Task - > TaskTarget ) )
{
AvHAIHiveDefinition * HiveRef = AITAC_GetHiveFromEdict ( Task - > TaskTarget ) ;
if ( ! HiveRef | | HiveRef - > Status ! = HIVE_STATUS_BUILT ) { return false ; }
}
if ( IsEdictStructure ( Task - > TaskTarget ) & & ! UTIL_IsBuildableStructureStillReachable ( pBot , Task - > TaskTarget ) ) { return false ; }
if ( IsEdictPlayer ( Task - > TaskTarget ) )
{
if ( ! IsPlayerGorge ( Task - > TaskTarget ) ) { return false ; }
}
return ( pBot - > Edict - > v . health < pBot - > Edict - > v . max_health ) | | ( ! IsPlayerSkulk ( pBot - > Edict ) & & pBot - > Edict - > v . armorvalue < ( GetPlayerMaxArmour ( pBot - > Edict ) * 0.8f ) ) ;
}
bool AITASK_IsAlienHealTaskStillValid ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task )
{
if ( ! Task - > TaskTarget | | FNullEnt ( Task - > TaskTarget ) | | ( Task - > TaskTarget - > v . effects & EF_NODRAW ) | | Task - > TaskTarget - > v . deadflag ! = DEAD_NO ) { return false ; }
2024-04-05 14:53:19 +00:00
if ( GetPlayerActiveClass ( pBot - > Player ) ! = AVH_USER3_ALIEN_PLAYER2 ) { return false ; }
2024-03-21 18:17:18 +00:00
if ( GetPlayerOverallHealthPercent ( Task - > TaskTarget ) > = 0.99f ) { return false ; }
if ( IsEdictStructure ( Task - > TaskTarget ) ) { return true ; }
// If our target is a player, give up if they are too far away. I'm not going to waste time chasing you around the map!
float MaxHealRelevant = sqrf ( UTIL_MetresToGoldSrcUnits ( 5.0f ) ) ;
return ( IsPlayerActiveInGame ( Task - > TaskTarget ) & & vDist2DSq ( pBot - > CurrentFloorPosition , Task - > TaskTarget - > v . origin ) < = MaxHealRelevant ) ;
}
bool AITASK_IsUseTaskStillValid ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task )
{
CBaseToggle * ToggleRef = dynamic_cast < CBaseToggle * > ( CBaseEntity : : Instance ( Task - > TaskTarget ) ) ;
if ( ! ToggleRef ) { return false ; }
DoorTrigger * TriggerRef = UTIL_GetDoorTriggerByEntity ( Task - > TaskTarget ) ;
if ( TriggerRef & & gpGlobals - > time < TriggerRef - > NextActivationTime ) { return false ; }
return ToggleRef - > GetToggleState ( ) = = TS_AT_BOTTOM | | ( ToggleRef - > GetToggleState ( ) = = TS_AT_TOP & & ( ToggleRef - > pev - > spawnflags & 32 ) ) ;
}
void BotProgressMoveTask ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task )
{
Task - > TaskStartedTime = gpGlobals - > time ;
2024-04-12 15:40:50 +00:00
bool bPlayerCloaked = pBot - > Player - > GetOpacity ( ) < 0.5f & & ! GetHasUpgrade ( pBot - > Edict - > v . iuser4 , MASK_SENSORY_NEARBY ) ;
if ( IsPlayerLerk ( pBot - > Edict ) | | bPlayerCloaked )
2024-03-21 18:17:18 +00:00
{
if ( AITAC_ShouldBotBeCautious ( pBot ) )
{
2024-04-12 15:40:50 +00:00
if ( bPlayerCloaked )
{
pBot - > BotNavInfo . bShouldWalk = true ;
}
MoveTo ( pBot , Task - > TaskLocation , MOVESTYLE_AMBUSH , 100.0f ) ;
2024-03-21 18:17:18 +00:00
}
else
{
MoveTo ( pBot , Task - > TaskLocation , MOVESTYLE_NORMAL , 100.0f ) ;
}
return ;
}
bool bMoveSuccess = MoveTo ( pBot , Task - > TaskLocation , MOVESTYLE_NORMAL ) ;
if ( ! bMoveSuccess )
{
MoveDirectlyTo ( pBot , Task - > TaskLocation ) ;
}
}
void BotProgressTouchTask ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task )
{
MoveTo ( pBot , Task - > TaskLocation , MOVESTYLE_NORMAL ) ;
}
void BotProgressUseTask ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task )
{
if ( IsPlayerInUseRange ( pBot - > Edict , Task - > TaskTarget ) )
{
if ( pBot - > Edict - > v . oldbuttons & IN_DUCK )
{
pBot - > Button | = IN_DUCK ;
}
BotUseObject ( pBot , Task - > TaskTarget , false ) ;
return ;
}
else
{
if ( vDist2DSq ( pBot - > Edict - > v . origin , Task - > TaskLocation ) < sqrf ( 18.0f ) )
{
if ( pBot - > Edict - > v . origin . z < UTIL_GetClosestPointOnEntityToLocation ( pBot - > Edict - > v . origin , Task - > TaskTarget ) . z )
{
BotJump ( pBot ) ;
}
else
{
pBot - > Button | = IN_DUCK ;
}
}
bool bMoveSuccess = MoveTo ( pBot , Task - > TaskLocation , MOVESTYLE_NORMAL ) ;
if ( ! bMoveSuccess )
{
MoveDirectlyTo ( pBot , Task - > TaskLocation ) ;
}
}
}
void BotProgressPickupTask ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task )
{
if ( Task - > TaskType = = TASK_GET_AMMO )
{
pBot - > DesiredCombatWeapon = UTIL_GetPlayerPrimaryWeapon ( pBot - > Player ) ;
}
MoveTo ( pBot , Task - > TaskTarget - > v . origin , MOVESTYLE_NORMAL ) ;
Task - > TaskStartedTime = gpGlobals - > time ;
float DistFromItem = vDist2DSq ( pBot - > Edict - > v . origin , Task - > TaskTarget - > v . origin ) ;
if ( DistFromItem < sqrf ( UTIL_MetresToGoldSrcUnits ( 1.0f ) ) )
{
BotLookAt ( pBot , Task - > TaskTarget ) ;
if ( Task - > TaskType = = TASK_GET_WEAPON )
{
AvHAIDeployableItemType ItemType = UTIL_GetItemTypeFromEdict ( Task - > TaskTarget ) ;
// Allows bots to drop their current primary weapon to pick up a new weapon
if ( UTIL_DroppedItemIsPrimaryWeapon ( ItemType ) )
{
AvHAIWeapon CurrentPrimaryWeapon = UTIL_GetPlayerPrimaryWeapon ( pBot - > Player ) ;
2024-04-14 19:50:26 +00:00
if ( CurrentPrimaryWeapon ! = WEAPON_INVALID & & CurrentPrimaryWeapon ! = UTIL_GetWeaponTypeFromEdict ( Task - > TaskTarget ) )
2024-03-21 18:17:18 +00:00
{
if ( GetPlayerCurrentWeapon ( pBot - > Player ) ! = CurrentPrimaryWeapon )
{
pBot - > DesiredCombatWeapon = CurrentPrimaryWeapon ;
}
else
{
BotDropWeapon ( pBot ) ;
}
}
}
}
}
}
void BotProgressMineStructureTask ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task )
{
if ( vIsZero ( Task - > TaskLocation ) )
{
Task - > TaskLocation = UTIL_GetNextMinePosition2 ( Task - > TaskTarget ) ;
if ( vIsZero ( Task - > TaskLocation ) )
{
AITASK_ClearBotTask ( pBot , Task ) ;
return ;
}
}
float DistToPlaceLocation = vDist2DSq ( pBot - > Edict - > v . origin , Task - > TaskLocation ) ;
if ( DistToPlaceLocation < sqrf ( UTIL_MetresToGoldSrcUnits ( 5.0f ) ) )
{
pBot - > DesiredCombatWeapon = WEAPON_MARINE_MINES ;
}
else
{
MoveTo ( pBot , Task - > TaskLocation , MOVESTYLE_NORMAL ) ;
return ;
}
if ( Task - > ActiveBuildInfo . BuildStatus = = BUILD_ATTEMPT_PENDING )
{
return ;
}
if ( Task - > ActiveBuildInfo . BuildStatus ! = BUILD_ATTEMPT_NONE )
{
if ( Task - > ActiveBuildInfo . BuildStatus = = BUILD_ATTEMPT_FAILED )
{
float Size = fmaxf ( Task - > TaskTarget - > v . size . x , Task - > TaskTarget - > v . size . y ) ;
Size + = 8.0f ;
Task - > TaskLocation = UTIL_GetRandomPointOnNavmeshInDonut ( GetBaseNavProfile ( MARINE_BASE_NAV_PROFILE ) , Task - > TaskTarget - > v . origin , Size , Size + 8.0f ) ;
}
else
{
Task - > TaskLocation = ZERO_VECTOR ;
}
Task - > ActiveBuildInfo . BuildStatus = BUILD_ATTEMPT_NONE ;
}
BotLookAt ( pBot , Task - > TaskLocation ) ;
if ( GetPlayerCurrentWeapon ( pBot - > Player ) = = WEAPON_MARINE_MINES )
{
Vector TraceStart = pBot - > Player - > GetGunPosition ( ) ;
Vector TraceDir = UTIL_GetForwardVector ( pBot - > Edict - > v . v_angle ) ;
TraceResult tr ;
UTIL_TraceLine ( TraceStart , TraceStart + ( TraceDir * kMineRange ) , dont_ignore_monsters , pBot - > Edict - > v . pContainingEntity , & tr ) ;
bool bTraceSuccessful = false ;
if ( tr . flFraction < 1.0f )
{
if ( tr . pHit ! = Task - > TaskTarget )
{
if ( vDist2DSq ( tr . vecEndPos , Task - > TaskLocation ) < sqrf ( 8.0f ) )
{
bTraceSuccessful = true ;
}
}
}
if ( bTraceSuccessful )
{
pBot - > Button | = IN_ATTACK ;
Task - > ActiveBuildInfo . AttemptedLocation = Task - > TaskLocation ;
Task - > ActiveBuildInfo . BuildStatus = BUILD_ATTEMPT_PENDING ;
Task - > ActiveBuildInfo . BuildAttemptTime = gpGlobals - > time ;
Task - > ActiveBuildInfo . AttemptedStructureType = STRUCTURE_MARINE_DEPLOYEDMINE ;
Task - > ActiveBuildInfo . NumAttempts + + ;
}
else
{
MoveTo ( pBot , Task - > TaskLocation , MOVESTYLE_NORMAL ) ;
return ;
}
}
}
void BotProgressReinforceStructureTask ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task )
{
if ( FNullEnt ( Task - > TaskTarget ) ) { return ; }
if ( Task - > ActiveBuildInfo . BuildStatus = = BUILD_ATTEMPT_PENDING ) { return ; }
// We had a go, whether it succeeded or not we should try a new location
if ( Task - > ActiveBuildInfo . BuildStatus = = BUILD_ATTEMPT_FAILED | | Task - > ActiveBuildInfo . BuildStatus = = BUILD_ATTEMPT_SUCCESS )
{
Task - > TaskLocation = ZERO_VECTOR ;
Task - > ActiveBuildInfo . BuildStatus = BUILD_ATTEMPT_NONE ;
}
AvHTeamNumber BotTeam = pBot - > Player - > GetTeam ( ) ;
Vector ReinforceLocation = UTIL_ProjectPointToNavmesh ( UTIL_GetEntityGroundLocation ( Task - > TaskTarget ) , pBot - > BotNavInfo . NavProfile ) ;
float SearchRadius = UTIL_MetresToGoldSrcUnits ( 5.0f ) ;
if ( Task - > StructureType = = STRUCTURE_ALIEN_HIVE )
{
AvHAIHiveDefinition * HiveToReinforce = AITAC_GetHiveFromEdict ( Task - > TaskTarget ) ;
if ( HiveToReinforce )
{
ReinforceLocation = HiveToReinforce - > FloorLocation ;
}
SearchRadius = UTIL_MetresToGoldSrcUnits ( 10.0f ) ;
}
AvHAIDeployableStructureType NextStructure = STRUCTURE_NONE ;
DeployableSearchFilter StructureFilter ;
StructureFilter . DeployableTeam = BotTeam ;
StructureFilter . MaxSearchRadius = SearchRadius ;
StructureFilter . DeployableTypes = STRUCTURE_ALIEN_OFFENCECHAMBER ;
int NumOCs = AITAC_GetNumDeployablesNearLocation ( ReinforceLocation , & StructureFilter ) ;
if ( NumOCs < 3 )
{
NextStructure = STRUCTURE_ALIEN_OFFENCECHAMBER ;
}
if ( NextStructure = = STRUCTURE_NONE )
{
if ( AITAC_TeamHiveWithTechExists ( BotTeam , ALIEN_BUILD_DEFENSE_CHAMBER ) )
{
StructureFilter . DeployableTypes = STRUCTURE_ALIEN_DEFENCECHAMBER ;
int NumDCs = AITAC_GetNumDeployablesNearLocation ( ReinforceLocation , & StructureFilter ) ;
if ( NumDCs < 2 )
{
NextStructure = STRUCTURE_ALIEN_DEFENCECHAMBER ;
}
}
}
if ( NextStructure = = STRUCTURE_NONE )
{
if ( AITAC_TeamHiveWithTechExists ( BotTeam , ALIEN_BUILD_MOVEMENT_CHAMBER ) )
{
StructureFilter . DeployableTypes = STRUCTURE_ALIEN_MOVEMENTCHAMBER ;
int NumMCs = AITAC_GetNumDeployablesNearLocation ( ReinforceLocation , & StructureFilter ) ;
if ( NumMCs < 1 )
{
NextStructure = STRUCTURE_ALIEN_MOVEMENTCHAMBER ;
}
}
}
if ( NextStructure = = STRUCTURE_NONE )
{
if ( AITAC_TeamHiveWithTechExists ( BotTeam , ALIEN_BUILD_SENSORY_CHAMBER ) )
{
StructureFilter . DeployableTypes = STRUCTURE_ALIEN_SENSORYCHAMBER ;
int NumSCs = AITAC_GetNumDeployablesNearLocation ( ReinforceLocation , & StructureFilter ) ;
if ( NumSCs < 1 )
{
NextStructure = STRUCTURE_ALIEN_SENSORYCHAMBER ;
}
}
}
if ( NextStructure ! = STRUCTURE_NONE )
{
if ( vIsZero ( Task - > TaskLocation ) )
{
Vector NewLoc = UTIL_GetRandomPointOnNavmeshInRadiusIgnoreReachability ( GetBaseNavProfile ( STRUCTURE_BASE_NAV_PROFILE ) , ReinforceLocation , SearchRadius ) ;
if ( vIsZero ( NewLoc ) )
{
NewLoc = UTIL_GetRandomPointOnNavmeshInRadius ( GetBaseNavProfile ( GORGE_BASE_NAV_PROFILE ) , ReinforceLocation , SearchRadius ) ;
}
Task - > TaskLocation = NewLoc ;
}
if ( ! vIsZero ( Task - > TaskLocation ) )
{
float ResourceCost = UTIL_GetCostOfStructureType ( NextStructure ) ;
2024-04-05 14:53:19 +00:00
if ( GetPlayerActiveClass ( pBot - > Player ) ! = AVH_USER3_ALIEN_PLAYER2 )
2024-03-21 18:17:18 +00:00
{
ResourceCost + = BALANCE_VAR ( kGorgeCost ) ;
}
if ( pBot - > Player - > GetResources ( ) > = ResourceCost )
{
BotAlienPlaceChamber ( pBot , Task , NextStructure ) ;
return ;
}
}
}
// We have nothing to build, or we don't have enough resources yet, see if there's any unfinished structures we can finish off
2024-04-05 14:53:19 +00:00
if ( GetPlayerActiveClass ( pBot - > Player ) = = AVH_USER3_ALIEN_PLAYER2 )
2024-03-21 18:17:18 +00:00
{
DeployableSearchFilter UnfinishedFilter ;
UnfinishedFilter . DeployableTeam = BotTeam ;
UnfinishedFilter . ExcludeStatusFlags = STRUCTURE_STATUS_COMPLETED ;
UnfinishedFilter . ReachabilityTeam = BotTeam ;
UnfinishedFilter . ReachabilityFlags = pBot - > BotNavInfo . NavProfile . ReachabilityFlag ;
UnfinishedFilter . DeployableTypes = SEARCH_ALL_ALIEN_STRUCTURES ;
UnfinishedFilter . MaxSearchRadius = UTIL_MetresToGoldSrcUnits ( 10.0f ) ;
AvHAIBuildableStructure UnfinishedStructure = AITAC_FindClosestDeployableToLocation ( ReinforceLocation , & UnfinishedFilter ) ;
if ( UnfinishedStructure . IsValid ( ) )
{
AIPlayerBuildStructure ( pBot , UnfinishedStructure . edict ) ;
return ;
}
}
// We can't build anything, see if there's anything to attack nearby
if ( ! IsPlayerGorge ( pBot - > Edict ) | | PlayerHasWeapon ( pBot - > Player , WEAPON_GORGE_BILEBOMB ) )
{
DeployableSearchFilter EnemyStructureFilter ;
EnemyStructureFilter . DeployableTeam = AIMGR_GetEnemyTeam ( BotTeam ) ;
EnemyStructureFilter . DeployableTypes = SEARCH_ALL_STRUCTURES ;
EnemyStructureFilter . ReachabilityTeam = BotTeam ;
EnemyStructureFilter . ReachabilityFlags = pBot - > BotNavInfo . NavProfile . ReachabilityFlag ;
EnemyStructureFilter . MaxSearchRadius = UTIL_MetresToGoldSrcUnits ( 10.0f ) ;
AvHAIBuildableStructure EnemyStructure = AITAC_FindClosestDeployableToLocation ( ReinforceLocation , & EnemyStructureFilter ) ;
if ( EnemyStructure . IsValid ( ) )
{
BotAttackNonPlayerTarget ( pBot , EnemyStructure . edict ) ;
return ;
}
}
BotGuardLocation ( pBot , ( ! vIsZero ( Task - > TaskLocation ) ) ? Task - > TaskLocation : ReinforceLocation ) ;
}
void BotProgressResupplyTask ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task )
{
if ( UTIL_GetPlayerPrimaryAmmoReserve ( pBot - > Player ) < UTIL_GetPlayerPrimaryMaxAmmoReserve ( pBot - > Player ) )
{
pBot - > DesiredCombatWeapon = UTIL_GetPlayerPrimaryWeapon ( pBot - > Player ) ;
}
else
{
pBot - > DesiredCombatWeapon = GetBotMarineSecondaryWeapon ( pBot ) ;
}
2024-04-24 13:20:12 +00:00
bool bHasLOS = UTIL_PlayerHasLOSToEntity ( pBot - > Edict , Task - > TaskTarget , UTIL_MetresToGoldSrcUnits ( 5.0f ) , false ) ;
float DistToArmoury = vDist2DSq ( pBot - > Edict - > v . origin , Task - > TaskTarget - > v . origin ) ;
if ( bHasLOS & & DistToArmoury < = sqrf ( max_player_use_reach ) )
2024-03-21 18:17:18 +00:00
{
BotUseObject ( pBot , Task - > TaskTarget , true ) ;
2024-04-24 13:20:12 +00:00
if ( DistToArmoury > sqrf ( 50.0f ) )
2024-03-21 18:17:18 +00:00
{
MoveDirectlyTo ( pBot , Task - > TaskTarget - > v . origin ) ;
}
return ;
}
MoveTo ( pBot , Task - > TaskTarget - > v . origin , MOVESTYLE_NORMAL ) ;
2024-04-24 13:20:12 +00:00
if ( bHasLOS )
2024-03-21 18:17:18 +00:00
{
BotLookAt ( pBot , UTIL_GetCentreOfEntity ( Task - > TaskTarget ) ) ;
}
}
void AIPlayerBuildStructure ( AvHAIPlayer * pBot , edict_t * BuildTarget )
{
if ( ! pBot | | ! IsPlayerActiveInGame ( pBot - > Edict ) | | FNullEnt ( BuildTarget ) | | UTIL_StructureIsFullyBuilt ( BuildTarget ) ) { return ; }
if ( IsPlayerAlien ( pBot - > Edict ) & & ! IsPlayerGorge ( pBot - > Edict ) ) { return ; }
if ( IsPlayerMarine ( pBot - > Edict ) )
{
// If we're not already building
if ( pBot - > Edict - > v . viewmodel ! = 0 )
{
// If someone else is building, then we will guard
edict_t * OtherBuilder = AITAC_GetClosestPlayerOnTeamWithLOS ( pBot - > Player - > GetTeam ( ) , BuildTarget - > v . origin , UTIL_MetresToGoldSrcUnits ( 2.0f ) , pBot - > Edict ) ;
if ( ! FNullEnt ( OtherBuilder ) & & OtherBuilder - > v . weaponmodel = = 0 )
{
BotGuardLocation ( pBot , BuildTarget - > v . origin ) ;
return ;
}
}
}
if ( IsPlayerInUseRange ( pBot - > Edict , BuildTarget ) )
{
BotUseObject ( pBot , BuildTarget , true ) ;
// Haven't started building, maybe not quite looking at the right angle
if ( IsPlayerMarine ( pBot - > Edict ) )
{
// If we were ducking before then keep ducking
if ( pBot - > Edict - > v . oldbuttons & IN_DUCK )
{
pBot - > Button | = IN_DUCK ;
}
if ( pBot - > Edict - > v . weaponmodel ! = 0 )
{
if ( vDist2DSq ( pBot - > Edict - > v . origin , BuildTarget - > v . origin ) > sqrf ( 60.0f ) )
{
MoveDirectlyTo ( pBot , BuildTarget - > v . origin ) ;
}
else
{
Vector NewViewPoint = UTIL_GetRandomPointInBoundingBox ( BuildTarget - > v . absmin , BuildTarget - > v . absmax ) ;
BotLookAt ( pBot , NewViewPoint ) ;
}
}
}
return ;
}
// Might need to duck if it's an infantry portal
if ( vDist2DSq ( pBot - > Edict - > v . origin , BuildTarget - > v . origin ) < sqrf ( max_player_use_reach ) )
{
if ( BuildTarget - > v . origin > pBot - > Edict - > v . origin )
{
BotJump ( pBot ) ;
}
else
{
pBot - > Button | = IN_DUCK ;
}
}
MoveTo ( pBot , BuildTarget - > v . origin , MOVESTYLE_NORMAL ) ;
if ( vDist2DSq ( pBot - > Edict - > v . origin , BuildTarget - > v . origin ) < sqrf ( UTIL_MetresToGoldSrcUnits ( 5.0f ) ) )
{
BotLookAt ( pBot , UTIL_GetCentreOfEntity ( BuildTarget ) ) ;
}
}
void MarineProgressBuildTask ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task )
{
edict_t * pEdict = pBot - > Edict ;
if ( UTIL_GetPlayerPrimaryWeaponClipAmmo ( pBot - > Player ) > 0 | | UTIL_GetPlayerPrimaryAmmoReserve ( pBot - > Player ) > 0 )
{
pBot - > DesiredCombatWeapon = UTIL_GetPlayerPrimaryWeapon ( pBot - > Player ) ;
}
else
{
if ( BotGetSecondaryWeaponClipAmmo ( pBot ) > 0 | | BotGetSecondaryWeaponAmmoReserve ( pBot ) > 0 )
{
pBot - > DesiredCombatWeapon = GetBotMarineSecondaryWeapon ( pBot ) ;
}
else
{
pBot - > DesiredCombatWeapon = UTIL_GetPlayerPrimaryWeapon ( pBot - > Player ) ;
}
}
// If we're not already building
if ( pBot - > Edict - > v . viewmodel ! = 0 )
{
// If someone else is building, then we will guard
edict_t * OtherBuilder = AITAC_GetClosestPlayerOnTeamWithLOS ( pBot - > Player - > GetTeam ( ) , Task - > TaskLocation , UTIL_MetresToGoldSrcUnits ( 2.0f ) , pBot - > Edict ) ;
if ( ! FNullEnt ( OtherBuilder ) & & OtherBuilder - > v . weaponmodel = = 0 )
{
BotGuardLocation ( pBot , Task - > TaskLocation ) ;
return ;
}
}
if ( IsPlayerInUseRange ( pBot - > Edict , Task - > TaskTarget ) )
{
// If we were ducking before then keep ducking
if ( pBot - > Edict - > v . oldbuttons & IN_DUCK )
{
pBot - > Button | = IN_DUCK ;
}
BotUseObject ( pBot , Task - > TaskTarget , true ) ;
// Haven't started building, maybe not quite looking at the right angle
if ( pBot - > Edict - > v . weaponmodel ! = 0 )
{
if ( vDist2DSq ( pBot - > Edict - > v . origin , Task - > TaskTarget - > v . origin ) > sqrf ( 60.0f ) )
{
MoveDirectlyTo ( pBot , Task - > TaskTarget - > v . origin ) ;
}
else
{
Vector NewViewPoint = UTIL_GetRandomPointInBoundingBox ( Task - > TaskTarget - > v . absmin , Task - > TaskTarget - > v . absmax ) ;
BotLookAt ( pBot , NewViewPoint ) ;
}
}
return ;
}
else
{
// Might need to duck if it's an infantry portal
if ( vDist2DSq ( pBot - > Edict - > v . origin , Task - > TaskTarget - > v . origin ) < sqrf ( max_player_use_reach ) )
{
if ( Task - > TaskTarget - > v . origin > pEdict - > v . origin )
{
BotJump ( pBot ) ;
}
else
{
pBot - > Button | = IN_DUCK ;
}
}
}
MoveTo ( pBot , Task - > TaskTarget - > v . origin , MOVESTYLE_NORMAL ) ;
if ( vDist2DSq ( pBot - > Edict - > v . origin , Task - > TaskTarget - > v . origin ) < sqrf ( UTIL_MetresToGoldSrcUnits ( 5.0f ) ) )
{
BotLookAt ( pBot , UTIL_GetCentreOfEntity ( Task - > TaskTarget ) ) ;
}
}
void BotProgressGuardTask ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task )
{
2024-03-25 20:46:54 +00:00
if ( vDist2DSq ( pBot - > Edict - > v . origin , Task - > TaskLocation ) > sqrf ( UTIL_MetresToGoldSrcUnits ( 10.0f ) ) )
2024-03-21 18:17:18 +00:00
{
2024-03-25 20:46:54 +00:00
Task - > TaskStartedTime = 0.0f ;
2024-04-12 15:40:50 +00:00
bool bPlayerCloaked = pBot - > Player - > GetOpacity ( ) < 0.5f & & ! GetHasUpgrade ( pBot - > Edict - > v . iuser4 , MASK_SENSORY_NEARBY ) ;
if ( IsPlayerLerk ( pBot - > Edict ) | | bPlayerCloaked )
2024-03-21 18:17:18 +00:00
{
if ( AITAC_ShouldBotBeCautious ( pBot ) )
{
2024-04-12 15:40:50 +00:00
if ( bPlayerCloaked )
{
pBot - > BotNavInfo . bShouldWalk = true ;
}
MoveTo ( pBot , Task - > TaskLocation , MOVESTYLE_AMBUSH , 100.0f ) ;
2024-03-21 18:17:18 +00:00
}
else
{
MoveTo ( pBot , Task - > TaskLocation , MOVESTYLE_NORMAL , 100.0f ) ;
}
return ;
}
MoveTo ( pBot , Task - > TaskLocation , MOVESTYLE_NORMAL ) ;
return ;
}
else
{
if ( Task - > TaskStartedTime = = 0.0f )
{
Task - > TaskStartedTime = gpGlobals - > time ;
}
BotGuardLocation ( pBot , Task - > TaskLocation ) ;
}
}
void BotProgressAttackTask ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task )
{
if ( ! Task | | FNullEnt ( Task - > TaskTarget ) ) { return ; }
if ( Task - > bTargetIsPlayer )
{
// For now just move to the target, the combat code will take over once the enemy is sighted
MoveTo ( pBot , UTIL_GetEntityGroundLocation ( Task - > TaskTarget ) , MOVESTYLE_AMBUSH ) ;
return ;
}
if ( IsPlayerGorge ( pBot - > Edict ) & & ! PlayerHasWeapon ( pBot - > Player , WEAPON_GORGE_BILEBOMB ) )
{
BotEvolveLifeform ( pBot , pBot - > CurrentFloorPosition , ALIEN_LIFEFORM_ONE ) ;
return ;
}
AvHAIWeapon Weapon = WEAPON_INVALID ;
if ( IsPlayerMarine ( pBot - > Edict ) )
{
Weapon = BotMarineChooseBestWeaponForStructure ( pBot , Task - > TaskTarget ) ;
}
else
{
Weapon = BotAlienChooseBestWeaponForStructure ( pBot , Task - > TaskTarget ) ;
}
if ( IsPlayerMarine ( pBot - > Player ) & & IsDamagingStructure ( Task - > TaskTarget ) & & ! IsMeleeWeapon ( Weapon ) )
{
if ( GetPlayerCurrentWeaponClipAmmo ( pBot - > Player ) = = 0 | | IsPlayerReloading ( pBot - > Player ) )
{
BotReloadWeapons ( pBot ) ;
AvHTurret * TurretRef = dynamic_cast < AvHTurret * > ( CBaseEntity : : Instance ( Task - > TaskTarget ) ) ;
if ( TurretRef & & TurretRef - > GetIsValidTarget ( pBot - > Player ) )
{
if ( vIsZero ( pBot - > LastSafeLocation ) )
{
pBot - > LastSafeLocation = AITAC_GetTeamStartingLocation ( pBot - > Player - > GetTeam ( ) ) ;
}
MoveTo ( pBot , pBot - > LastSafeLocation , MOVESTYLE_NORMAL ) ;
return ;
}
}
}
BotAttackResult AttackResult = PerformAttackLOSCheck ( pBot , Weapon , Task - > TaskTarget ) ;
if ( AttackResult = = ATTACK_SUCCESS )
{
// If we were ducking before then keep ducking
if ( pBot - > Edict - > v . oldbuttons & IN_DUCK )
{
pBot - > Button | = IN_DUCK ;
}
if ( PlayerHasWeapon ( pBot - > Player , WEAPON_LERK_PRIMALSCREAM ) & & ! pBot - > Player - > GetIsScreaming ( ) )
{
int NumBuffTargets = AITAC_GetNumPlayersOfTeamInArea ( pBot - > Player - > GetTeam ( ) , pBot - > Edict - > v . origin , BALANCE_VAR ( kPrimalScreamRange ) , false , pBot - > Edict , AVH_USER3_ALIEN_PLAYER2 ) ;
if ( NumBuffTargets > 0 )
{
pBot - > DesiredCombatWeapon = WEAPON_LERK_PRIMALSCREAM ;
if ( GetPlayerCurrentWeapon ( pBot - > Player ) = = WEAPON_LERK_PRIMALSCREAM )
{
pBot - > Button | = IN_ATTACK ;
}
return ;
}
}
BotShootTarget ( pBot , Weapon , Task - > TaskTarget ) ;
if ( IsDamagingStructure ( Task - > TaskTarget ) & & ! IsMeleeWeapon ( Weapon ) )
{
Vector EnemyOrientation = UTIL_GetVectorNormal2D ( Task - > TaskTarget - > v . origin - pBot - > Edict - > v . origin ) ;
Vector RightDir = UTIL_GetCrossProduct ( EnemyOrientation , UP_VECTOR ) ;
pBot - > desiredMovementDir = ( pBot - > BotNavInfo . bZig ) ? UTIL_GetVectorNormal2D ( RightDir ) : UTIL_GetVectorNormal2D ( - RightDir ) ;
// Let's get ziggy with it
if ( gpGlobals - > time > pBot - > BotNavInfo . NextZigTime )
{
pBot - > BotNavInfo . bZig = ! pBot - > BotNavInfo . bZig ;
pBot - > BotNavInfo . NextZigTime = gpGlobals - > time + frandrange ( 0.5f , 1.0f ) ;
}
BotMovementInputs ( pBot ) ;
}
return ;
}
if ( ! vIsZero ( Task - > TaskLocation ) )
{
MoveTo ( pBot , Task - > TaskLocation , MOVESTYLE_NORMAL , max_player_use_reach ) ;
return ;
}
Vector AttackLocation = ( IsEdictPlayer ( Task - > TaskTarget ) | | IsEdictStructure ( Task - > TaskTarget ) ) ? Task - > TaskTarget - > v . origin : UTIL_GetButtonFloorLocation ( pBot - > Edict - > v . origin , Task - > TaskTarget ) ;
if ( vIsZero ( AttackLocation ) )
{
AttackLocation = Task - > TaskTarget - > v . origin ;
}
float WeaponRange = GetMaxIdealWeaponRange ( Weapon ) ;
Vector NewTaskLocation = FindClosestNavigablePointToDestination ( pBot - > BotNavInfo . NavProfile , pBot - > CurrentFloorPosition , AttackLocation , WeaponRange ) ;
Task - > TaskLocation = ( ! vIsZero ( NewTaskLocation ) ) ? NewTaskLocation : AttackLocation ;
MoveTo ( pBot , Task - > TaskLocation , MOVESTYLE_NORMAL , max_player_use_reach ) ;
return ;
}
void BotProgressDefendTask ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task )
{
if ( ! FNullEnt ( Task - > TaskTarget ) )
{
vector < AvHPlayer * > Attackers = AITAC_GetAllPlayersOnTeamWithLOS ( AIMGR_GetEnemyTeam ( pBot - > Player - > GetTeam ( ) ) , Task - > TaskTarget - > v . origin , UTIL_MetresToGoldSrcUnits ( 15.0f ) , nullptr ) ;
edict_t * NearestAttacker = nullptr ;
float MinDist = 0.0f ;
for ( auto it = Attackers . begin ( ) ; it ! = Attackers . end ( ) ; it + + )
{
AvHPlayer * ThisPlayer = ( * it ) ;
edict_t * PlayerEdict = ThisPlayer - > edict ( ) ;
if ( FNullEnt ( PlayerEdict ) ) { continue ; }
float ThisDist = vDist2DSq ( pBot - > Edict - > v . origin , PlayerEdict - > v . origin ) ;
if ( FNullEnt ( NearestAttacker ) | | ThisDist < MinDist )
{
NearestAttacker = PlayerEdict ;
MinDist = ThisDist ;
}
}
if ( ! FNullEnt ( NearestAttacker ) )
{
MoveTo ( pBot , UTIL_GetEntityGroundLocation ( NearestAttacker ) , MOVESTYLE_NORMAL ) ;
return ;
}
AvHAIBuildableStructure StructureRef = AITAC_GetDeployableFromEdict ( Task - > TaskTarget ) ;
2024-04-02 11:14:10 +00:00
if ( StructureRef . IsValid ( ) )
2024-03-21 18:17:18 +00:00
{
2024-04-02 11:14:10 +00:00
// If the structure we're defending was damaged just now, look at it so we can see who is attacking
if ( gpGlobals - > time - StructureRef . lastDamagedTime < 5.0f )
2024-03-21 18:17:18 +00:00
{
2024-04-02 11:14:10 +00:00
if ( UTIL_QuickTrace ( pBot - > Edict , pBot - > CurrentEyePosition , UTIL_GetCentreOfEntity ( Task - > TaskTarget ) ) )
{
BotLookAt ( pBot , Task - > TaskTarget ) ;
}
2024-03-21 18:17:18 +00:00
}
}
2024-04-02 11:14:10 +00:00
else
{
AvHAIHiveDefinition * Hive = AITAC_GetHiveFromEdict ( Task - > TaskTarget ) ;
if ( Hive & & Hive - > bIsUnderAttack )
{
if ( UTIL_QuickTrace ( pBot - > Edict , pBot - > CurrentEyePosition , Hive - > Location ) )
{
BotLookAt ( pBot , Task - > TaskTarget ) ;
}
}
}
2024-03-21 18:17:18 +00:00
}
BotProgressGuardTask ( pBot , Task ) ;
}
void BotProgressTakeCommandTask ( AvHAIPlayer * pBot )
{
// Don't take command if we already have a commander
if ( pBot - > Player - > GetCommander ( ) ) { return ; }
edict_t * CommChair = AITAC_GetCommChair ( pBot - > Player - > GetTeam ( ) ) ;
if ( ! CommChair ) { return ; }
float DistFromChair = vDist2DSq ( pBot - > Edict - > v . origin , CommChair - > v . origin ) ;
if ( ! IsPlayerInUseRange ( pBot - > Edict , CommChair ) )
{
MoveTo ( pBot , CommChair - > v . origin , MOVESTYLE_NORMAL ) ;
if ( DistFromChair < sqrf ( UTIL_MetresToGoldSrcUnits ( 5.0f ) ) )
{
BotLookAt ( pBot , CommChair ) ;
}
}
else
{
if ( gpGlobals - > time > AIMGR_GetCommanderAllowedTime ( pBot - > Player - > GetTeam ( ) ) )
{
BotUseObject ( pBot , CommChair , false ) ;
}
else
{
edict_t * NearestHuman = AITAC_GetNearestHumanAtLocation ( pBot - > Player - > GetTeam ( ) , CommChair - > v . origin , UTIL_MetresToGoldSrcUnits ( 15.0f ) ) ;
if ( FNullEnt ( NearestHuman ) )
{
BotLookAt ( pBot , CommChair ) ;
}
else
{
BotLookAt ( pBot , NearestHuman ) ;
}
}
}
}
void BotProgressEvolveTask ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task )
{
if ( ! Task | | ! Task - > Evolution ) { return ; }
// We tried evolving a second ago and nothing happened. Must be in a bad spot
if ( Task - > TaskStartedTime > 0.0f )
{
if ( ( gpGlobals - > time - Task - > TaskStartedTime ) > 1.0f )
{
2024-04-19 14:25:24 +00:00
Task - > TaskLocation = UTIL_GetRandomPointOnNavmeshInRadius ( GetBaseNavProfile ( STRUCTURE_BASE_NAV_PROFILE ) , pBot - > Edict - > v . origin , UTIL_MetresToGoldSrcUnits ( 5.0f ) ) ;
2024-03-21 18:17:18 +00:00
if ( vIsZero ( Task - > TaskLocation ) )
{
Task - > TaskLocation = UTIL_GetRandomPointOnNavmeshInRadius ( BaseNavProfiles [ ONOS_BASE_NAV_PROFILE ] , pBot - > Edict - > v . origin , UTIL_MetresToGoldSrcUnits ( 5.0f ) ) ;
}
Task - > TaskStartedTime = 0.0f ;
}
return ;
}
if ( ! vIsZero ( Task - > TaskLocation ) )
{
if ( vDist2DSq ( pBot - > Edict - > v . origin , Task - > TaskLocation ) > sqrf ( 32.0f ) )
{
MoveTo ( pBot , Task - > TaskLocation , MOVESTYLE_NORMAL ) ;
return ;
}
else
{
pBot - > Impulse = Task - > Evolution ;
Task - > TaskStartedTime = gpGlobals - > time ;
}
}
else
{
if ( FNullEnt ( Task - > TaskTarget ) )
{
Task - > TaskLocation = pBot - > Edict - > v . origin ;
return ;
}
else
{
2024-04-04 14:54:57 +00:00
if ( vDist2DSq ( pBot - > Edict - > v . origin , UTIL_GetEntityGroundLocation ( Task - > TaskTarget ) ) > sqrf ( UTIL_MetresToGoldSrcUnits ( 10.0f ) ) | | UTIL_GetNavAreaAtLocation ( BaseNavProfiles [ STRUCTURE_BASE_NAV_PROFILE ] , pBot - > Edict - > v . origin ) ! = SAMPLE_POLYAREA_GROUND )
2024-03-21 18:17:18 +00:00
{
2024-04-04 14:54:57 +00:00
MoveTo ( pBot , UTIL_GetEntityGroundLocation ( Task - > TaskTarget ) , MOVESTYLE_NORMAL , UTIL_MetresToGoldSrcUnits ( 10.0f ) ) ;
2024-03-21 18:17:18 +00:00
return ;
}
else
{
2024-04-04 14:54:57 +00:00
Task - > TaskLocation = FindClosestNavigablePointToDestination ( BaseNavProfiles [ STRUCTURE_BASE_NAV_PROFILE ] , pBot - > Edict - > v . origin , UTIL_GetEntityGroundLocation ( Task - > TaskTarget ) , UTIL_MetresToGoldSrcUnits ( 10.0f ) ) ;
2024-03-21 18:17:18 +00:00
if ( vIsZero ( Task - > TaskLocation ) )
{
Task - > TaskLocation = pBot - > Edict - > v . origin ;
}
2024-04-04 14:54:57 +00:00
Vector FinalEvolveLoc = UTIL_GetRandomPointOnNavmeshInRadius ( BaseNavProfiles [ STRUCTURE_BASE_NAV_PROFILE ] , Task - > TaskLocation , UTIL_MetresToGoldSrcUnits ( 5.0f ) ) ;
2024-03-21 18:17:18 +00:00
2024-04-04 14:54:57 +00:00
if ( ! vIsZero ( FinalEvolveLoc ) )
{
Task - > TaskLocation = FinalEvolveLoc ;
return ;
2024-03-21 18:17:18 +00:00
}
}
}
}
}
void AlienProgressGetHealthTask ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task )
{
if ( PlayerHasWeapon ( pBot - > Player , WEAPON_FADE_METABOLIZE ) )
{
pBot - > DesiredCombatWeapon = WEAPON_FADE_METABOLIZE ;
if ( GetPlayerCurrentWeapon ( pBot - > Player ) = = WEAPON_FADE_METABOLIZE )
{
pBot - > Button | = IN_ATTACK ;
}
}
if ( ! FNullEnt ( Task - > TaskTarget ) )
{
Vector MoveLocation = ( IsPlayerGorge ( Task - > TaskTarget ) ) ? Task - > TaskTarget - > v . origin : Task - > TaskLocation ;
BotGuardLocation ( pBot , MoveLocation ) ;
if ( IsPlayerGorge ( Task - > TaskTarget ) & & vDist2DSq ( pBot - > Edict - > v . origin , Task - > TaskTarget - > v . origin ) < sqrf ( UTIL_MetresToGoldSrcUnits ( 2.0f ) ) )
{
BotLookAt ( pBot , Task - > TaskTarget ) ;
AIPlayerRequestHealth ( pBot ) ;
}
}
}
void AlienProgressHealTask ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task )
{
if ( FNullEnt ( Task - > TaskTarget ) | | IsPlayerDead ( Task - > TaskTarget ) ) { return ; }
BotAlienHealTarget ( pBot , Task - > TaskTarget ) ;
}
void AlienProgressBuildHiveTask ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task )
{
if ( Task - > ActiveBuildInfo . BuildStatus = = BUILD_ATTEMPT_PENDING )
{
return ;
}
const AvHAIHiveDefinition * Hive = AITAC_GetHiveNearestLocation ( Task - > TaskLocation ) ;
if ( ! Hive )
{
AITASK_ClearBotTask ( pBot , Task ) ;
return ;
}
int ResRequired = UTIL_GetCostOfStructureType ( Task - > StructureType ) ;
2024-04-05 14:53:19 +00:00
if ( GetPlayerActiveClass ( pBot - > Player ) ! = AVH_USER3_ALIEN_PLAYER2 )
2024-03-21 18:17:18 +00:00
{
ResRequired + = BALANCE_VAR ( kGorgeCost ) ;
}
if ( pBot - > Player - > GetResources ( ) < ResRequired )
{
BotGuardLocation ( pBot , Task - > TaskLocation ) ;
return ;
}
BotAlienBuildHive ( pBot , Task , Hive ) ;
}
void AlienProgressBuildTask ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task )
{
// We tried and failed to place the structure
if ( Task - > ActiveBuildInfo . BuildStatus = = BUILD_ATTEMPT_PENDING )
{
return ;
}
if ( Task - > StructureType = = STRUCTURE_ALIEN_HIVE )
{
AlienProgressBuildHiveTask ( pBot , Task ) ;
return ;
}
if ( Task - > ActiveBuildInfo . LinkedStructure )
{
edict_t * LinkedEdict = Task - > ActiveBuildInfo . LinkedStructure - > edict ;
if ( UTIL_StructureIsFullyBuilt ( LinkedEdict ) ) { return ; }
if ( IsPlayerInUseRange ( pBot - > Edict , LinkedEdict ) )
{
BotUseObject ( pBot , LinkedEdict , true ) ;
if ( vDist2DSq ( pBot - > Edict - > v . origin , LinkedEdict - > v . origin ) > sqrf ( 60.0f ) )
{
MoveDirectlyTo ( pBot , LinkedEdict - > v . origin ) ;
}
return ;
}
MoveTo ( pBot , LinkedEdict - > v . origin , MOVESTYLE_NORMAL ) ;
return ;
}
// We tried and failed to place the structure
if ( Task - > ActiveBuildInfo . BuildStatus = = BUILD_ATTEMPT_FAILED )
{
Task - > TaskLocation = UTIL_GetRandomPointOnNavmeshInRadius ( BaseNavProfiles [ GORGE_BASE_NAV_PROFILE ] , Task - > TaskLocation , UTIL_MetresToGoldSrcUnits ( 2.0f ) ) ;
Task - > ActiveBuildInfo . BuildStatus = BUILD_ATTEMPT_NONE ;
}
int ResRequired = UTIL_GetCostOfStructureType ( Task - > StructureType ) ;
2024-04-05 14:53:19 +00:00
if ( GetPlayerActiveClass ( pBot - > Player ) ! = AVH_USER3_ALIEN_PLAYER2 )
2024-03-21 18:17:18 +00:00
{
ResRequired + = BALANCE_VAR ( kGorgeCost ) ;
}
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 . IsValid ( ) )
{
AIPlayerBuildStructure ( pBot , UnfinishedStructure . edict ) ;
return ;
}
}
BotGuardLocation ( pBot , Task - > TaskLocation ) ;
return ;
}
BotAlienPlaceChamber ( pBot , Task , Task - > StructureType ) ;
}
void BotAlienPlaceChamber ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task , AvHAIDeployableStructureType DesiredStructure )
{
if ( vIsZero ( Task - > TaskLocation ) | | DesiredStructure = = STRUCTURE_NONE ) { return ; }
if ( Task - > ActiveBuildInfo . BuildStatus = = BUILD_ATTEMPT_PENDING ) { return ; }
float DistFromBuildLocation = vDist2DSq ( pBot - > Edict - > v . origin , Task - > TaskLocation ) ;
if ( DistFromBuildLocation > sqrf ( UTIL_MetresToGoldSrcUnits ( 1.0f ) ) )
{
MoveTo ( pBot , Task - > TaskLocation , MOVESTYLE_NORMAL ) ;
return ;
}
if ( DistFromBuildLocation < sqrf ( UTIL_MetresToGoldSrcUnits ( 0.5f ) ) )
{
BotLookAt ( pBot , Task - > TaskLocation ) ;
Vector Orientation = UTIL_GetVectorNormal2D ( pBot - > Edict - > v . origin - Task - > TaskLocation ) ;
Vector NewMoveLoc = Task - > TaskLocation + ( Orientation * UTIL_MetresToGoldSrcUnits ( 2.0f ) ) ;
MoveToWithoutNav ( pBot , NewMoveLoc ) ;
return ;
}
Vector LookLocation = Task - > TaskLocation ;
LookLocation . z + = 10.0f ;
BotLookAt ( pBot , LookLocation ) ;
int ResRequired = UTIL_GetCostOfStructureType ( DesiredStructure ) ;
2024-04-05 14:53:19 +00:00
if ( GetPlayerActiveClass ( pBot - > Player ) ! = AVH_USER3_ALIEN_PLAYER2 )
2024-03-21 18:17:18 +00:00
{
ResRequired + = BALANCE_VAR ( kGorgeCost ) ;
}
if ( pBot - > Player - > GetResources ( ) < ResRequired )
{
return ;
}
2024-04-05 14:53:19 +00:00
if ( GetPlayerActiveClass ( pBot - > Player ) ! = AVH_USER3_ALIEN_PLAYER2 )
2024-03-21 18:17:18 +00:00
{
BotEvolveLifeform ( pBot , pBot - > CurrentFloorPosition , ALIEN_LIFEFORM_TWO ) ;
return ;
}
float LookDot = UTIL_GetDotProduct2D ( UTIL_GetForwardVector2D ( pBot - > Edict - > v . v_angle ) , UTIL_GetVectorNormal2D ( LookLocation - pBot - > Edict - > v . origin ) ) ;
if ( LookDot > 0.9f )
{
pBot - > Impulse = UTIL_StructureTypeToImpulseCommand ( DesiredStructure ) ;
RegisterBotAlienBuildAttempt ( pBot , Task , Task - > TaskLocation , DesiredStructure ) ;
}
}
void BotAlienBuildResTower ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task , const AvHAIResourceNode * NodeToCap )
{
if ( NodeToCap - > bIsOccupied ) { return ; }
if ( Task - > ActiveBuildInfo . BuildStatus = = BUILD_ATTEMPT_PENDING ) { return ; }
float CurrDist = vDist2DSq ( pBot - > CurrentFloorPosition , NodeToCap - > Location ) ;
// Get close enough to place the tower if we aren't
if ( CurrDist > sqrf ( UTIL_MetresToGoldSrcUnits ( 3.0f ) ) )
{
MoveTo ( pBot , NodeToCap - > Location , MOVESTYLE_NORMAL ) ;
return ;
}
// Back up a bit if we're too close
if ( CurrDist < sqrf ( UTIL_MetresToGoldSrcUnits ( 1.0f ) ) )
{
BotLookAt ( pBot , NodeToCap - > Location ) ;
Vector Orientation = UTIL_GetVectorNormal2D ( pBot - > Edict - > v . origin - NodeToCap - > Location ) ;
Vector NewMoveLoc = NodeToCap - > Location + ( Orientation * UTIL_MetresToGoldSrcUnits ( 2.0f ) ) ;
MoveToWithoutNav ( pBot , NewMoveLoc ) ;
return ;
}
int ResRequired = UTIL_GetCostOfStructureType ( STRUCTURE_ALIEN_RESTOWER ) ;
2024-04-05 14:53:19 +00:00
if ( GetPlayerActiveClass ( pBot - > Player ) ! = AVH_USER3_ALIEN_PLAYER2 )
2024-03-21 18:17:18 +00:00
{
ResRequired + = BALANCE_VAR ( kGorgeCost ) ;
}
BotLookAt ( pBot , NodeToCap - > Location ) ;
if ( pBot - > Player - > GetResources ( ) < ResRequired )
{
return ;
}
2024-04-05 14:53:19 +00:00
if ( GetPlayerActiveClass ( pBot - > Player ) ! = AVH_USER3_ALIEN_PLAYER2 )
2024-03-21 18:17:18 +00:00
{
BotEvolveLifeform ( pBot , pBot - > CurrentFloorPosition , ALIEN_LIFEFORM_TWO ) ;
return ;
}
float LookDot = UTIL_GetDotProduct2D ( UTIL_GetForwardVector2D ( pBot - > Edict - > v . v_angle ) , UTIL_GetVectorNormal2D ( NodeToCap - > Location - pBot - > Edict - > v . origin ) ) ;
if ( LookDot > 0.9f )
{
pBot - > Impulse = UTIL_StructureTypeToImpulseCommand ( STRUCTURE_ALIEN_RESTOWER ) ;
RegisterBotAlienBuildAttempt ( pBot , Task , NodeToCap - > Location , STRUCTURE_ALIEN_RESTOWER ) ;
}
}
void BotAlienBuildHive ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task , const AvHAIHiveDefinition * HiveToBuild )
{
// Do nothing if the hive is already built / under construction
if ( HiveToBuild - > Status ! = HIVE_STATUS_UNBUILT ) { return ; }
if ( Task - > ActiveBuildInfo . BuildStatus = = BUILD_ATTEMPT_PENDING ) { return ; }
if ( vDist2DSq ( pBot - > Edict - > v . origin , HiveToBuild - > Location ) > sqrf ( UTIL_MetresToGoldSrcUnits ( 7.5f ) ) )
{
MoveTo ( pBot , HiveToBuild - > FloorLocation , MOVESTYLE_NORMAL ) ;
return ;
}
BotLookAt ( pBot , HiveToBuild - > Location ) ;
Vector TraceStart = GetPlayerEyePosition ( pBot - > Edict ) ;
Vector TraceEnd = TraceStart + ( UTIL_GetForwardVector ( pBot - > Edict - > v . v_angle ) * 60.0f ) ;
if ( ! UTIL_QuickTrace ( pBot - > Edict , TraceStart , TraceEnd ) )
{
MoveTo ( pBot , HiveToBuild - > FloorLocation , MOVESTYLE_NORMAL ) ;
return ;
}
else
{
int ResRequired = UTIL_GetCostOfStructureType ( STRUCTURE_ALIEN_HIVE ) ;
2024-04-05 14:53:19 +00:00
if ( GetPlayerActiveClass ( pBot - > Player ) ! = AVH_USER3_ALIEN_PLAYER2 )
2024-03-21 18:17:18 +00:00
{
ResRequired + = BALANCE_VAR ( kGorgeCost ) ;
}
if ( pBot - > Player - > GetResources ( ) < ResRequired )
{
return ;
}
2024-04-05 14:53:19 +00:00
if ( GetPlayerActiveClass ( pBot - > Player ) ! = AVH_USER3_ALIEN_PLAYER2 )
2024-03-21 18:17:18 +00:00
{
BotEvolveLifeform ( pBot , pBot - > CurrentFloorPosition , ALIEN_LIFEFORM_TWO ) ;
return ;
}
pBot - > Impulse = UTIL_StructureTypeToImpulseCommand ( STRUCTURE_ALIEN_HIVE ) ;
RegisterBotAlienBuildAttempt ( pBot , Task , HiveToBuild - > Location , STRUCTURE_ALIEN_HIVE ) ;
}
}
void BotAlienHealTarget ( AvHAIPlayer * pBot , edict_t * HealTarget )
{
float MaxHealRange = GetMaxIdealWeaponRange ( WEAPON_GORGE_HEALINGSPRAY ) ;
float TargetHealRange = MaxHealRange * 0.5f ;
BotAttackResult HitCheck = PerformAttackLOSCheck ( pBot , WEAPON_GORGE_HEALINGSPRAY , HealTarget ) ;
if ( HitCheck = = ATTACK_SUCCESS )
{
if ( IsPlayerGorge ( pBot - > Edict ) )
{
BotShootTarget ( pBot , WEAPON_GORGE_HEALINGSPRAY , HealTarget ) ;
return ;
}
else
{
BotEvolveLifeform ( pBot , pBot - > CurrentFloorPosition , ALIEN_LIFEFORM_TWO ) ;
return ;
}
}
else
{
MoveTo ( pBot , UTIL_GetEntityGroundLocation ( HealTarget ) , MOVESTYLE_NORMAL , MaxHealRange ) ;
}
}
void RegisterBotAlienBuildAttempt ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task , Vector PlacementLocation , AvHAIDeployableStructureType DesiredStructure )
{
Task - > ActiveBuildInfo . AttemptedLocation = PlacementLocation ;
Task - > ActiveBuildInfo . BuildAttemptTime = gpGlobals - > time ;
Task - > ActiveBuildInfo . LinkedStructure = nullptr ;
Task - > ActiveBuildInfo . NumAttempts + + ;
Task - > ActiveBuildInfo . AttemptedStructureType = DesiredStructure ;
Task - > ActiveBuildInfo . BuildStatus = BUILD_ATTEMPT_PENDING ;
}
void AlienProgressCapResNodeTask ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task )
{
const AvHAIResourceNode * ResNodeIndex = AITAC_GetNearestResourceNodeToLocation ( Task - > TaskLocation ) ;
if ( ! ResNodeIndex ) { return ; }
AvHTeamNumber BotTeam = pBot - > Player - > GetTeam ( ) ;
// We can attack structures if we're not a gorge stuck with spit as our only offensive weapon
bool bBotCanAttackStructures = ! IsPlayerGorge ( pBot - > Edict ) | | PlayerHasWeapon ( pBot - > Player , WEAPON_GORGE_BILEBOMB ) ;
// First, clear out any marine phase gates nearby so they can't send backup, if we can actually do meaningful damage to them
if ( bBotCanAttackStructures )
{
AvHClassType EnemyClassType = AIMGR_GetEnemyTeamType ( BotTeam ) ;
if ( EnemyClassType = = AVH_CLASS_TYPE_MARINE )
{
DeployableSearchFilter PGFilter ;
PGFilter . DeployableTeam = AIMGR_GetEnemyTeam ( BotTeam ) ;
PGFilter . DeployableTypes = STRUCTURE_MARINE_PHASEGATE ;
PGFilter . MaxSearchRadius = UTIL_MetresToGoldSrcUnits ( 5.0f ) ;
PGFilter . ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING ;
AvHAIBuildableStructure PG = AITAC_FindClosestDeployableToLocation ( ResNodeIndex - > Location , & PGFilter ) ;
if ( PG . IsValid ( ) )
{
BotAttackNonPlayerTarget ( pBot , PG . edict ) ;
return ;
}
}
}
if ( ResNodeIndex - > bIsOccupied )
{
// If we have a tower on there already then help build it if we're gorge
if ( ResNodeIndex - > OwningTeam = = BotTeam )
{
if ( ! UTIL_StructureIsFullyBuilt ( ResNodeIndex - > ActiveTowerEntity ) )
{
if ( IsPlayerGorge ( pBot - > Edict ) )
{
AIPlayerBuildStructure ( pBot , ResNodeIndex - > ActiveTowerEntity ) ;
return ;
}
}
}
else
{
// If the enemy owns it then destroy it if we can, or go Skulk to do so.
if ( bBotCanAttackStructures )
{
BotAttackNonPlayerTarget ( pBot , ResNodeIndex - > ActiveTowerEntity ) ;
return ;
}
else
{
BotEvolveLifeform ( pBot , pBot - > CurrentFloorPosition , ALIEN_LIFEFORM_ONE ) ;
return ;
}
}
}
else
{
// Node is empty and not capped by either side
2024-04-05 14:53:19 +00:00
int NumResourcesRequired = ( GetPlayerActiveClass ( pBot - > Player ) = = AVH_USER3_ALIEN_PLAYER2 ) ? BALANCE_VAR ( kResourceTowerCost ) : ( BALANCE_VAR ( kResourceTowerCost ) + BALANCE_VAR ( kGorgeCost ) ) ;
2024-03-21 18:17:18 +00:00
// We have enough resources to place the tower (includes cost of evolving to gorge if necessary)
if ( pBot - > Player - > GetResources ( ) > = NumResourcesRequired )
{
BotAlienBuildResTower ( pBot , Task , ResNodeIndex ) ;
return ;
}
}
// We don't have enough resources to cap the node yet, so take out any enemy structures in the area while we wait if we can
if ( bBotCanAttackStructures )
{
DeployableSearchFilter EnemyStructureFilter ;
EnemyStructureFilter . DeployableTeam = AIMGR_GetEnemyTeam ( BotTeam ) ;
EnemyStructureFilter . DeployableTypes = SEARCH_ALL_STRUCTURES ;
EnemyStructureFilter . MaxSearchRadius = UTIL_MetresToGoldSrcUnits ( 5.0f ) ;
AvHAIBuildableStructure AttackTarget = AITAC_FindClosestDeployableToLocation ( ResNodeIndex - > Location , & EnemyStructureFilter ) ;
if ( AttackTarget . IsValid ( ) )
{
BotAttackNonPlayerTarget ( pBot , AttackTarget . edict ) ;
return ;
}
}
// No structures to take out, just wait for resources
BotGuardLocation ( pBot , ResNodeIndex - > Location ) ;
}
void BotProgressTask ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task )
{
if ( ! Task | | Task - > TaskType = = TASK_NONE ) { return ; }
switch ( Task - > TaskType )
{
case TASK_MOVE :
BotProgressMoveTask ( pBot , Task ) ;
break ;
case TASK_USE :
BotProgressUseTask ( pBot , Task ) ;
break ;
case TASK_TOUCH :
BotProgressTouchTask ( pBot , Task ) ;
break ;
case TASK_GET_AMMO :
case TASK_GET_EQUIPMENT :
case TASK_GET_WEAPON :
BotProgressPickupTask ( pBot , Task ) ;
break ;
case TASK_GET_HEALTH :
{
if ( IsPlayerMarine ( pBot - > Edict ) )
{
BotProgressPickupTask ( pBot , Task ) ;
}
else
{
AlienProgressGetHealthTask ( pBot , Task ) ;
}
}
break ;
case TASK_RESUPPLY :
BotProgressResupplyTask ( pBot , Task ) ;
break ;
case TASK_BUILD :
{
if ( IsPlayerMarine ( pBot - > Edict ) )
{
MarineProgressBuildTask ( pBot , Task ) ;
}
else
{
AlienProgressBuildTask ( pBot , Task ) ;
}
}
break ;
case TASK_REINFORCE_STRUCTURE :
BotProgressReinforceStructureTask ( pBot , Task ) ;
break ;
case TASK_GUARD :
BotProgressGuardTask ( pBot , Task ) ;
break ;
case TASK_ATTACK :
BotProgressAttackTask ( pBot , Task ) ;
break ;
case TASK_CAP_RESNODE :
{
if ( IsPlayerMarine ( pBot - > Edict ) )
{
MarineProgressCapResNodeTask ( pBot , Task ) ;
}
else
{
AlienProgressCapResNodeTask ( pBot , Task ) ;
}
}
break ;
case TASK_WELD :
BotProgressWeldTask ( pBot , Task ) ;
break ;
case TASK_DEFEND :
BotProgressDefendTask ( pBot , Task ) ;
break ;
case TASK_COMMAND :
BotProgressTakeCommandTask ( pBot ) ;
break ;
case TASK_EVOLVE :
BotProgressEvolveTask ( pBot , Task ) ;
break ;
case TASK_PLACE_MINE :
BotProgressMineStructureTask ( pBot , Task ) ;
break ;
case TASK_HEAL :
AlienProgressHealTask ( pBot , Task ) ;
break ;
case TASK_SECURE_HIVE :
{
if ( IsPlayerMarine ( pBot - > Edict ) )
{
MarineProgressSecureHiveTask ( pBot , Task ) ;
}
}
break ;
default :
break ;
}
}
void BotProgressWeldTask ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task )
{
if ( ! PlayerHasWeapon ( pBot - > Player , WEAPON_MARINE_WELDER ) )
{
if ( ! FNullEnt ( Task - > TaskSecondaryTarget ) )
{
MoveTo ( pBot , Task - > TaskSecondaryTarget - > v . origin , MOVESTYLE_NORMAL ) ;
}
else
{
AvHAIDroppedItem * Welder = AITAC_FindClosestItemToLocation ( pBot - > Edict - > v . origin , DEPLOYABLE_ITEM_WELDER , pBot - > Player - > GetTeam ( ) , pBot - > BotNavInfo . NavProfile . ReachabilityFlag , 0.0f , 0.0f , true ) ;
if ( Welder )
{
Task - > TaskSecondaryTarget = Welder - > edict ;
}
}
return ;
}
if ( IsPlayerInUseRange ( pBot - > Edict , Task - > TaskTarget ) )
{
2024-03-25 23:37:14 +00:00
Vector EntityCentre = UTIL_GetCentreOfEntity ( Task - > TaskTarget ) ;
Vector AimLocation = EntityCentre ;
2024-03-21 18:17:18 +00:00
// If we're targeting a func_weldable, then the centre of the entity might be in a wall or out of reach
// so instead aim at the closest point on the func_weldable to us.
if ( ! IsEdictPlayer ( Task - > TaskTarget ) & & ! IsEdictStructure ( Task - > TaskTarget ) )
{
if ( Task - > TaskTarget - > v . size . Length2D ( ) < 100.0f )
{
AimLocation = UTIL_GetCentreOfEntity ( Task - > TaskTarget ) ;
}
else
{
Vector BBMin = Task - > TaskTarget - > v . absmin + Vector ( 5.0f , 5.0f , 5.0f ) ;
Vector BBMax = Task - > TaskTarget - > v . absmax - Vector ( 5.0f , 5.0f , 5.0f ) ;
vScaleBB ( BBMin , BBMax , 0.75f ) ;
2024-03-25 20:46:54 +00:00
AimLocation = vClosestPointOnBB ( pBot - > CurrentEyePosition , BBMin , BBMax ) ;
2024-03-25 23:37:14 +00:00
if ( Task - > TaskTarget - > v . absmax . z - Task - > TaskTarget - > v . absmin . z < 100.0f )
{
AimLocation . z = EntityCentre . z ;
}
2024-03-21 18:17:18 +00:00
}
}
BotLookAt ( pBot , AimLocation ) ;
pBot - > DesiredCombatWeapon = WEAPON_MARINE_WELDER ;
if ( GetPlayerCurrentWeapon ( pBot - > Player ) ! = WEAPON_MARINE_WELDER )
{
return ;
}
pBot - > Button | = IN_ATTACK ;
return ;
}
else
{
if ( IsEdictPlayer ( Task - > TaskTarget ) | | IsEdictStructure ( Task - > TaskTarget ) )
{
MoveTo ( pBot , Task - > TaskTarget - > v . origin , MOVESTYLE_NORMAL ) ;
}
else
{
MoveTo ( pBot , Task - > TaskLocation , MOVESTYLE_NORMAL ) ;
}
}
return ;
}
void MarineProgressSecureHiveTask ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task )
{
const AvHAIHiveDefinition * Hive = AITAC_GetHiveFromEdict ( Task - > TaskTarget ) ;
if ( ! Hive ) { return ; }
AvHTeamNumber BotTeam = pBot - > Player - > GetTeam ( ) ;
DeployableSearchFilter StructureFilter ;
StructureFilter . DeployableTypes = SEARCH_ALL_MARINE_STRUCTURES ;
StructureFilter . MaxSearchRadius = UTIL_MetresToGoldSrcUnits ( 15.0f ) ;
StructureFilter . DeployableTeam = BotTeam ;
StructureFilter . ReachabilityTeam = BotTeam ;
StructureFilter . ReachabilityFlags = pBot - > BotNavInfo . NavProfile . ReachabilityFlag ;
StructureFilter . ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING ;
vector < AvHAIBuildableStructure > BuildableStructures = AITAC_FindAllDeployables ( Hive - > FloorLocation , & StructureFilter ) ;
bool bKeyStructureBuilt = false ;
AvHAIBuildableStructure StructureToBuild ;
float MinDist = 0.0f ;
for ( auto it = BuildableStructures . begin ( ) ; it ! = BuildableStructures . end ( ) ; it + + )
{
AvHAIBuildableStructure ThisStructure = ( * it ) ;
if ( ( ThisStructure . StructureStatusFlags & STRUCTURE_STATUS_COMPLETED ) & & ( ThisStructure . StructureType & ( STRUCTURE_MARINE_TURRETFACTORY | STRUCTURE_MARINE_ADVTURRETFACTORY | STRUCTURE_MARINE_PHASEGATE ) ) )
{
bKeyStructureBuilt = true ;
}
if ( ThisStructure . StructureStatusFlags & STRUCTURE_STATUS_COMPLETED ) { continue ; }
// Phase gates always take priority, so just go and build it if there is one
if ( ThisStructure . StructureType = = STRUCTURE_MARINE_PHASEGATE )
{
AIPlayerBuildStructure ( pBot , ThisStructure . edict ) ;
return ;
}
float ThisDist = vDist2DSq ( pBot - > Edict - > v . origin , ThisStructure . Location ) ;
if ( FNullEnt ( StructureToBuild . edict ) | | ThisDist < MinDist )
{
StructureToBuild = ThisStructure ;
MinDist = ThisDist ;
}
}
if ( StructureToBuild . IsValid ( ) )
{
AIPlayerBuildStructure ( pBot , StructureToBuild . edict ) ;
return ;
}
const AvHAIResourceNode * ResNode = Hive - > HiveResNodeRef ;
if ( ResNode & & ResNode - > bIsOccupied )
{
if ( ResNode - > OwningTeam ! = BotTeam )
{
// Don't attack the RT until we have build a TF or PG. Avoids giving the game away too quickly
if ( bKeyStructureBuilt )
{
BotAttackNonPlayerTarget ( pBot , ResNode - > ActiveTowerEntity ) ;
return ;
}
}
else
{
if ( ! UTIL_StructureIsFullyBuilt ( ResNode - > ActiveTowerEntity ) )
{
AIPlayerBuildStructure ( pBot , ResNode - > ActiveTowerEntity ) ;
return ;
}
}
}
// We won't start attacking enemy structures until we have built a turret factory or phase gate so we don't reveal our evil plans until we're ready
if ( bKeyStructureBuilt )
{
DeployableSearchFilter EnemyStructures ;
EnemyStructures . DeployableTypes = SEARCH_ALL_STRUCTURES ;
EnemyStructures . MaxSearchRadius = UTIL_MetresToGoldSrcUnits ( 15.0f ) ;
EnemyStructures . DeployableTeam = AIMGR_GetEnemyTeam ( BotTeam ) ;
EnemyStructures . ReachabilityTeam = BotTeam ;
EnemyStructures . ReachabilityFlags = pBot - > BotNavInfo . NavProfile . ReachabilityFlag ;
AvHAIBuildableStructure EnemyStructure = AITAC_FindClosestDeployableToLocation ( Hive - > FloorLocation , & EnemyStructures ) ;
if ( EnemyStructure . IsValid ( ) )
{
BotAttackNonPlayerTarget ( pBot , EnemyStructure . edict ) ;
return ;
}
}
BotGuardLocation ( pBot , Task - > TaskLocation ) ;
}
void MarineProgressCapResNodeTask ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task )
{
if ( ! Task ) { return ; }
const AvHAIResourceNode * ResNodeIndex = AITAC_GetNearestResourceNodeToLocation ( Task - > TaskLocation ) ;
// This shouldn't happen, but if somehow it does then at least do SOMETHING
if ( ! ResNodeIndex )
{
MoveTo ( pBot , Task - > TaskLocation , MOVESTYLE_NORMAL ) ;
return ;
}
// There is a res tower, ours or the enemies
if ( ResNodeIndex - > bIsOccupied )
{
Task - > TaskTarget = ResNodeIndex - > ActiveTowerEntity ;
if ( ResNodeIndex - > OwningTeam = = pBot - > Player - > GetTeam ( ) )
{
if ( ! UTIL_StructureIsFullyBuilt ( ResNodeIndex - > ActiveTowerEntity ) )
{
// Cancel the waiting timeout since there is something for us to do
Task - > TaskLength = 0.0f ;
AIPlayerBuildStructure ( pBot , ResNodeIndex - > ActiveTowerEntity ) ;
return ;
}
}
else
{
// Cancel the waiting timeout since there is something for us to do
Task - > TaskLength = 0.0f ;
// If we're playing MvM, then check the enemy hasn't got a phase gate nearby which could bring in defenders. If so, take that out first.
AvHClassType EnemyType = AIMGR_GetEnemyTeamType ( pBot - > Player - > GetTeam ( ) ) ;
if ( EnemyType = = AVH_CLASS_TYPE_MARINE )
{
DeployableSearchFilter EnemyStructureFilter ;
EnemyStructureFilter . DeployableTeam = AIMGR_GetEnemyTeam ( pBot - > Player - > GetTeam ( ) ) ;
EnemyStructureFilter . DeployableTypes = STRUCTURE_MARINE_PHASEGATE ;
EnemyStructureFilter . ReachabilityTeam = pBot - > Player - > GetTeam ( ) ;
EnemyStructureFilter . ReachabilityFlags = pBot - > BotNavInfo . NavProfile . ReachabilityFlag ;
EnemyStructureFilter . MaxSearchRadius = UTIL_MetresToGoldSrcUnits ( 5.0f ) ;
AvHAIBuildableStructure EnemyStructure = AITAC_FindClosestDeployableToLocation ( Task - > TaskLocation , & EnemyStructureFilter ) ;
if ( EnemyStructure . IsValid ( ) )
{
BotAttackNonPlayerTarget ( pBot , EnemyStructure . edict ) ;
return ;
}
}
BotAttackNonPlayerTarget ( pBot , ResNodeIndex - > ActiveTowerEntity ) ;
return ;
}
}
// Clear out any enemy structures around the node
DeployableSearchFilter EnemyStructureFilter ;
EnemyStructureFilter . DeployableTeam = AIMGR_GetEnemyTeam ( pBot - > Player - > GetTeam ( ) ) ;
EnemyStructureFilter . DeployableTypes = SEARCH_ALL_STRUCTURES ;
EnemyStructureFilter . ReachabilityTeam = pBot - > Player - > GetTeam ( ) ;
EnemyStructureFilter . ReachabilityFlags = pBot - > BotNavInfo . NavProfile . ReachabilityFlag ;
EnemyStructureFilter . MaxSearchRadius = UTIL_MetresToGoldSrcUnits ( 5.0f ) ;
AvHAIBuildableStructure EnemyStructure = AITAC_FindClosestDeployableToLocation ( Task - > TaskLocation , & EnemyStructureFilter ) ;
if ( EnemyStructure . IsValid ( ) )
{
// Cancel the waiting timeout since we have something useful to do
Task - > TaskLength = 0.0f ;
BotAttackNonPlayerTarget ( pBot , EnemyStructure . edict ) ;
return ;
}
else
{
// If we're not at our destination yet, go there
if ( vDist2DSq ( pBot - > Edict - > v . origin , Task - > TaskLocation ) > sqrf ( UTIL_MetresToGoldSrcUnits ( 5.0f ) ) )
{
MoveTo ( pBot , Task - > TaskLocation , MOVESTYLE_NORMAL ) ;
return ;
}
// Empty res node with nothing to do but wait, stick around for 30 seconds and then move on if the commander doesn't drop an RT to build
if ( Task - > TaskLength = = 0.0f )
{
Task - > TaskStartedTime = gpGlobals - > time ;
Task - > TaskLength = 30.0f ;
}
BotGuardLocation ( pBot , Task - > TaskLocation ) ;
}
}
void BotGuardLocation ( AvHAIPlayer * pBot , const Vector GuardLocation )
{
float DistFromGuardLocation = vDist2DSq ( pBot - > Edict - > v . origin , GuardLocation ) ;
2024-04-14 19:50:26 +00:00
if ( DistFromGuardLocation > sqrf ( UTIL_MetresToGoldSrcUnits ( 5.0f ) ) )
2024-03-21 18:17:18 +00:00
{
2024-04-14 19:50:26 +00:00
UTIL_ClearGuardInfo ( pBot ) ;
2024-03-21 18:17:18 +00:00
MoveTo ( pBot , GuardLocation , MOVESTYLE_NORMAL , UTIL_MetresToGoldSrcUnits ( 10.0f ) ) ;
return ;
}
if ( vIsZero ( pBot - > GuardInfo . GuardLocation ) )
{
AITASK_GenerateGuardWatchPoints ( pBot , GuardLocation ) ;
pBot - > GuardInfo . GuardLocation = GuardLocation ;
}
if ( gpGlobals - > time > pBot - > GuardInfo . ThisGuardLookTime )
{
2024-04-14 19:50:26 +00:00
if ( pBot - > GuardInfo . GuardPoints . size ( ) > 0 )
2024-03-21 18:17:18 +00:00
{
2024-04-14 19:50:26 +00:00
if ( pBot - > GuardInfo . GuardPoints . size ( ) = = 1 )
{
pBot - > GuardInfo . GuardLookLocation = ( * pBot - > GuardInfo . GuardPoints . begin ( ) ) ;
}
else
{
Vector NewLookPoint = pBot - > GuardInfo . GuardLookLocation ;
int HighestScore = 0.0f ;
for ( auto it = pBot - > GuardInfo . GuardPoints . begin ( ) ; it ! = pBot - > GuardInfo . GuardPoints . end ( ) ; it + + )
{
if ( vEquals ( ( * it ) , pBot - > GuardInfo . GuardLookLocation ) ) { continue ; }
float thisScore = frandrange ( 0.01f , 1.0f ) ;
if ( thisScore > HighestScore )
{
NewLookPoint = ( * it ) ;
HighestScore = thisScore ;
}
}
pBot - > GuardInfo . GuardLookLocation = NewLookPoint ;
}
2024-03-21 18:17:18 +00:00
}
else
{
2024-04-14 19:50:26 +00:00
pBot - > GuardInfo . GuardLookLocation = UTIL_GetRandomPointOnNavmeshInRadius ( BaseNavProfiles [ SKULK_BASE_NAV_PROFILE ] , pBot - > Edict - > v . origin , UTIL_MetresToGoldSrcUnits ( 3.0f ) ) ;
2024-03-21 18:17:18 +00:00
pBot - > GuardInfo . GuardLookLocation . z = pBot - > CurrentEyePosition . z ;
}
pBot - > GuardInfo . ThisGuardLookTime = gpGlobals - > time + frandrange ( 2.0f , 5.0f ) ;
}
if ( gpGlobals - > time > pBot - > GuardInfo . ThisGuardStandTime )
{
2024-04-14 19:50:26 +00:00
pBot - > GuardInfo . GuardStandPosition = UTIL_GetRandomPointOnNavmeshInRadius ( pBot - > BotNavInfo . NavProfile , GuardLocation , UTIL_MetresToGoldSrcUnits ( 3.0f ) ) ;
2024-03-21 18:17:18 +00:00
pBot - > GuardInfo . ThisGuardStandTime = gpGlobals - > time + frandrange ( 5.0f , 10.0f ) ;
}
if ( vDist2DSq ( pBot - > Edict - > v . origin , pBot - > GuardInfo . GuardStandPosition ) > sqrf ( 32.0f ) )
{
if ( IsPlayerLerk ( pBot - > Edict ) )
{
MoveTo ( pBot , pBot - > GuardInfo . GuardStandPosition , MOVESTYLE_AMBUSH ) ;
}
else
{
MoveTo ( pBot , pBot - > GuardInfo . GuardStandPosition , MOVESTYLE_NORMAL ) ;
}
}
BotLookAt ( pBot , pBot - > GuardInfo . GuardLookLocation ) ;
}
void UTIL_ClearGuardInfo ( AvHAIPlayer * pBot )
{
2024-04-14 19:50:26 +00:00
pBot - > GuardInfo . GuardLocation = ZERO_VECTOR ;
pBot - > GuardInfo . GuardLookLocation = ZERO_VECTOR ;
pBot - > GuardInfo . GuardPoints . clear ( ) ;
pBot - > GuardInfo . GuardStandPosition = ZERO_VECTOR ;
pBot - > GuardInfo . GuardStartLookTime = 0.0f ;
pBot - > GuardInfo . GuardStartStandTime = 0.0f ;
pBot - > GuardInfo . ThisGuardLookTime = 0.0f ;
pBot - > GuardInfo . ThisGuardStandTime = 0.0f ;
2024-03-21 18:17:18 +00:00
}
void AITASK_GenerateGuardWatchPoints ( AvHAIPlayer * pBot , const Vector & GuardLocation )
{
const edict_t * pEdict = pBot - > Edict ;
UTIL_ClearGuardInfo ( pBot ) ;
AvHTeamNumber EnemyTeam = AIMGR_GetEnemyTeam ( pBot - > Player - > GetTeam ( ) ) ;
bool bEnemyIsAlien = GetGameRules ( ) - > GetTeam ( EnemyTeam ) - > GetTeamType ( ) = = AVH_CLASS_TYPE_ALIEN ;
const nav_profile NavProfile = ( bEnemyIsAlien ) ? BaseNavProfiles [ SKULK_BASE_NAV_PROFILE ] : BaseNavProfiles [ MARINE_BASE_NAV_PROFILE ] ;
vector < bot_path_node > path ;
path . clear ( ) ;
vector < AvHAIHiveDefinition * > AllHives = AITAC_GetAllHives ( ) ;
for ( auto it = AllHives . begin ( ) ; it ! = AllHives . end ( ) ; it + + )
{
const AvHAIHiveDefinition * ThisHive = ( * it ) ;
2024-04-14 19:50:26 +00:00
if ( UTIL_QuickTrace ( pEdict , GuardLocation , ThisHive - > Location ) ) { continue ; }
2024-03-21 18:17:18 +00:00
if ( UTIL_QuickTrace ( pEdict , GuardLocation + Vector ( 0.0f , 0.0f , 10.0f ) , ThisHive - > Location ) | | vDist2DSq ( GuardLocation , ThisHive - > Location ) < sqrf ( UTIL_MetresToGoldSrcUnits ( 10.0f ) ) ) { continue ; }
2024-04-14 19:50:26 +00:00
dtStatus SearchResult = FindPathClosestToPoint ( NavProfile , GuardLocation , ThisHive - > FloorLocation , path , 500.0f ) ;
2024-03-21 18:17:18 +00:00
if ( dtStatusSucceed ( SearchResult ) & & path . size ( ) > 0 )
{
2024-04-14 19:50:26 +00:00
Vector FurthestPoint = UTIL_GetFurthestVisiblePointOnPath ( GuardLocation + Vector ( 0.0f , 0.0f , 64.0f ) , path , true ) ;
FurthestPoint . z + = 64.0f ;
Vector LookDir = UTIL_GetVectorNormal ( FurthestPoint - GuardLocation ) ;
bool bShouldAdd = true ;
for ( auto it = pBot - > GuardInfo . GuardPoints . begin ( ) ; it ! = pBot - > GuardInfo . GuardPoints . end ( ) ; it + + )
{
Vector ThisLookDir = UTIL_GetVectorNormal ( ( * it ) - GuardLocation ) ;
2024-03-21 18:17:18 +00:00
2024-04-14 19:50:26 +00:00
if ( UTIL_GetDotProduct ( ThisLookDir , LookDir ) > 0.8f )
{
bShouldAdd = false ;
break ;
}
}
2024-03-21 18:17:18 +00:00
2024-04-14 19:50:26 +00:00
if ( bShouldAdd )
{
pBot - > GuardInfo . GuardPoints . push_back ( FurthestPoint ) ;
}
2024-03-21 18:17:18 +00:00
}
}
if ( AIMGR_GetEnemyTeamType ( pBot - > Player - > GetTeam ( ) ) = = AVH_CLASS_TYPE_MARINE )
{
2024-04-14 19:50:26 +00:00
if ( ! UTIL_QuickTrace ( nullptr , GuardLocation , AITAC_GetTeamStartingLocation ( EnemyTeam ) ) )
{
dtStatus SearchResult = FindPathClosestToPoint ( NavProfile , GuardLocation , AITAC_GetTeamStartingLocation ( EnemyTeam ) , path , 500.0f ) ;
2024-03-21 18:17:18 +00:00
2024-04-14 19:50:26 +00:00
if ( dtStatusSucceed ( SearchResult ) & & path . size ( ) > 0 )
{
Vector FurthestPoint = UTIL_GetFurthestVisiblePointOnPath ( GuardLocation + Vector ( 0.0f , 0.0f , 64.0f ) , path , true ) ;
FurthestPoint . z + = 64.0f ;
2024-03-21 18:17:18 +00:00
2024-04-14 19:50:26 +00:00
Vector LookDir = UTIL_GetVectorNormal ( FurthestPoint - GuardLocation ) ;
bool bShouldAdd = true ;
2024-03-21 18:17:18 +00:00
2024-04-14 19:50:26 +00:00
for ( auto it = pBot - > GuardInfo . GuardPoints . begin ( ) ; it ! = pBot - > GuardInfo . GuardPoints . end ( ) ; it + + )
{
Vector ThisLookDir = UTIL_GetVectorNormal ( ( * it ) - GuardLocation ) ;
2024-03-21 18:17:18 +00:00
2024-04-14 19:50:26 +00:00
if ( UTIL_GetDotProduct ( ThisLookDir , LookDir ) > 0.8f )
{
bShouldAdd = false ;
break ;
}
}
if ( bShouldAdd )
{
pBot - > GuardInfo . GuardPoints . push_back ( FurthestPoint ) ;
}
}
2024-03-21 18:17:18 +00:00
}
}
if ( AIMGR_GetTeamType ( pBot - > Player - > GetTeam ( ) ) = = AVH_CLASS_TYPE_MARINE )
{
2024-04-14 19:50:26 +00:00
if ( ! UTIL_QuickTrace ( pEdict , GuardLocation , AITAC_GetTeamStartingLocation ( pBot - > Player - > GetTeam ( ) ) ) )
2024-03-21 18:17:18 +00:00
{
2024-04-14 19:50:26 +00:00
if ( vDist2DSq ( GuardLocation , AITAC_GetTeamStartingLocation ( pBot - > Player - > GetTeam ( ) ) ) > sqrf ( UTIL_MetresToGoldSrcUnits ( 15.0f ) ) )
2024-03-21 18:17:18 +00:00
{
2024-04-14 19:50:26 +00:00
dtStatus SearchResult = FindPathClosestToPoint ( NavProfile , GuardLocation , AITAC_GetTeamStartingLocation ( pBot - > Player - > GetTeam ( ) ) , path , 500.0f ) ;
if ( dtStatusSucceed ( SearchResult ) & & path . size ( ) > 0 )
{
Vector FurthestPoint = UTIL_GetFurthestVisiblePointOnPath ( GuardLocation + Vector ( 0.0f , 0.0f , 64.0f ) , path , true ) ;
FurthestPoint . z + = 64.0f ;
Vector LookDir = UTIL_GetVectorNormal ( FurthestPoint - GuardLocation ) ;
bool bShouldAdd = true ;
2024-03-21 18:17:18 +00:00
2024-04-14 19:50:26 +00:00
for ( auto it = pBot - > GuardInfo . GuardPoints . begin ( ) ; it ! = pBot - > GuardInfo . GuardPoints . end ( ) ; it + + )
{
Vector ThisLookDir = UTIL_GetVectorNormal ( ( * it ) - GuardLocation ) ;
if ( UTIL_GetDotProduct ( ThisLookDir , LookDir ) > 0.8f )
{
bShouldAdd = false ;
break ;
}
}
2024-03-21 18:17:18 +00:00
2024-04-14 19:50:26 +00:00
if ( bShouldAdd )
{
pBot - > GuardInfo . GuardPoints . push_back ( FurthestPoint ) ;
}
}
2024-03-21 18:17:18 +00:00
}
}
}
}
bool BotWithBuildTaskExists ( AvHTeamNumber Team , AvHAIDeployableStructureType StructureType )
{
vector < AvHAIPlayer * > AIPlayers = AIMGR_GetAIPlayersOnTeam ( Team ) ;
for ( auto it = AIPlayers . begin ( ) ; it ! = AIPlayers . end ( ) ; it + + )
{
AvHAIPlayer * Bot = ( * it ) ;
if ( ! IsPlayerActiveInGame ( Bot - > Edict ) ) { continue ; }
if ( ( Bot - > PrimaryBotTask . TaskType = = TASK_BUILD & & Bot - > PrimaryBotTask . StructureType = = StructureType ) | | ( Bot - > SecondaryBotTask . TaskType = = TASK_BUILD & & Bot - > SecondaryBotTask . StructureType = = StructureType ) )
{
return true ;
}
}
return false ;
}
AvHAIPlayer * GetFirstBotWithBuildTask ( AvHTeamNumber Team , AvHAIDeployableStructureType StructureType , edict_t * IgnorePlayer )
{
vector < AvHAIPlayer * > AIPlayers = AIMGR_GetAIPlayersOnTeam ( Team ) ;
for ( auto it = AIPlayers . begin ( ) ; it ! = AIPlayers . end ( ) ; it + + )
{
AvHAIPlayer * Bot = ( * it ) ;
if ( ! IsPlayerActiveInGame ( Bot - > Edict ) | | Bot - > Edict = = IgnorePlayer ) { continue ; }
bool bPrimaryIsBuildTask = ( Bot - > PrimaryBotTask . TaskType = = TASK_BUILD | | Bot - > PrimaryBotTask . TaskType = = TASK_REINFORCE_STRUCTURE ) ;
bool bSecondaryIsBuildTask = ( Bot - > SecondaryBotTask . TaskType = = TASK_BUILD | | Bot - > SecondaryBotTask . TaskType = = TASK_REINFORCE_STRUCTURE ) ;
if ( ( bPrimaryIsBuildTask & & Bot - > PrimaryBotTask . StructureType = = StructureType ) | | ( bSecondaryIsBuildTask & & Bot - > SecondaryBotTask . StructureType = = StructureType ) )
{
return Bot ;
}
}
return nullptr ;
}
int AITASK_GetNumBotsWithBuildTask ( AvHTeamNumber Team , AvHAIDeployableStructureType StructureType , edict_t * IgnorePlayer )
{
vector < AvHAIPlayer * > AIPlayers = AIMGR_GetAIPlayersOnTeam ( Team ) ;
int Result = 0 ;
for ( auto it = AIPlayers . begin ( ) ; it ! = AIPlayers . end ( ) ; it + + )
{
AvHAIPlayer * Bot = ( * it ) ;
if ( ! IsPlayerActiveInGame ( Bot - > Edict ) | | Bot - > Edict = = IgnorePlayer ) { continue ; }
bool bPrimaryIsBuildTask = ( Bot - > PrimaryBotTask . TaskType = = TASK_BUILD | | Bot - > PrimaryBotTask . TaskType = = TASK_REINFORCE_STRUCTURE ) ;
bool bSecondaryIsBuildTask = ( Bot - > SecondaryBotTask . TaskType = = TASK_BUILD | | Bot - > SecondaryBotTask . TaskType = = TASK_REINFORCE_STRUCTURE ) ;
if ( ( bPrimaryIsBuildTask & & Bot - > PrimaryBotTask . StructureType = = StructureType ) | | ( bSecondaryIsBuildTask & & Bot - > SecondaryBotTask . StructureType = = StructureType ) )
{
Result + + ;
}
}
return Result ;
}
AvHAIPlayer * GetFirstBotWithReinforceTask ( AvHTeamNumber Team , edict_t * ReinforceStructure , edict_t * IgnorePlayer )
{
vector < AvHAIPlayer * > AIPlayers = AIMGR_GetAIPlayersOnTeam ( Team ) ;
for ( auto it = AIPlayers . begin ( ) ; it ! = AIPlayers . end ( ) ; it + + )
{
AvHAIPlayer * Bot = ( * it ) ;
if ( ! IsPlayerActiveInGame ( Bot - > Edict ) | | Bot - > Edict = = IgnorePlayer ) { continue ; }
if ( ( Bot - > PrimaryBotTask . TaskType = = TASK_REINFORCE_STRUCTURE & & Bot - > PrimaryBotTask . TaskTarget = = ReinforceStructure ) | | ( Bot - > SecondaryBotTask . TaskType = = TASK_REINFORCE_STRUCTURE & & Bot - > SecondaryBotTask . TaskTarget = = ReinforceStructure ) )
{
return Bot ;
}
}
return nullptr ;
}
char * AITASK_TaskTypeToChar ( const BotTaskType TaskType )
{
switch ( TaskType )
{
case TASK_NONE :
return " None " ;
case TASK_BUILD :
return " Build " ;
case TASK_GET_AMMO :
return " Get Ammo " ;
case TASK_ATTACK :
return " Attack " ;
case TASK_GET_EQUIPMENT :
return " Get Equipment " ;
case TASK_GET_HEALTH :
return " Get Health " ;
case TASK_GET_WEAPON :
return " Get Weapon " ;
case TASK_GUARD :
return " Guard " ;
case TASK_HEAL :
return " Heal " ;
case TASK_MOVE :
return " Move " ;
case TASK_RESUPPLY :
return " Resupply " ;
case TASK_CAP_RESNODE :
return " Cap Resource Node " ;
case TASK_WELD :
return " Weld " ;
case TASK_DEFEND :
return " Defend " ;
case TASK_EVOLVE :
return " Evolve " ;
case TASK_REINFORCE_STRUCTURE :
return " Reinforce Structure " ;
case TASK_SECURE_HIVE :
return " Secure Hive " ;
case TASK_PLACE_MINE :
return " Place Mine " ;
default :
return " INVALID " ;
}
}
void AITASK_SetPickupTask ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task , edict_t * Target , const bool bIsUrgent )
{
if ( FNullEnt ( Target ) | | ( Target - > v . effects & EF_NODRAW ) | | ! UTIL_IsDroppedItemStillReachable ( pBot , Target ) )
{
AITASK_ClearBotTask ( pBot , Task ) ;
return ;
}
if ( Task - > TaskTarget = = Target )
{
Task - > bTaskIsUrgent = bIsUrgent ;
return ;
}
AvHAIDroppedItem * ItemToPickup = AITAC_GetDroppedItemRefFromEdict ( Target ) ;
if ( ! ItemToPickup )
{
AITASK_ClearBotTask ( pBot , Task ) ;
return ;
}
Vector PickupLocation = FindClosestNavigablePointToDestination ( pBot - > BotNavInfo . NavProfile , pBot - > CurrentFloorPosition , Target - > v . origin , max_player_use_reach ) ;
if ( vIsZero ( PickupLocation ) )
{
AITASK_ClearBotTask ( pBot , Task ) ;
return ;
}
switch ( ItemToPickup - > ItemType )
{
case DEPLOYABLE_ITEM_AMMO :
Task - > TaskType = TASK_GET_AMMO ;
break ;
case DEPLOYABLE_ITEM_HEALTHPACK :
Task - > TaskType = TASK_GET_HEALTH ;
break ;
case DEPLOYABLE_ITEM_JETPACK :
case DEPLOYABLE_ITEM_HEAVYARMOUR :
Task - > TaskType = TASK_GET_EQUIPMENT ;
break ;
default :
Task - > TaskType = TASK_GET_WEAPON ;
break ;
}
Task - > TaskTarget = Target ;
Task - > TaskLocation = PickupLocation ;
Task - > bTaskIsUrgent = bIsUrgent ;
}
void AITASK_SetGetHealthTask ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task , edict_t * HealingSource , const bool bIsUrgent )
{
if ( Task - > TaskType = = TASK_GET_HEALTH & & Task - > TaskTarget = = HealingSource )
{
Task - > bTaskIsUrgent = bIsUrgent ;
return ;
}
AITASK_ClearBotTask ( pBot , Task ) ;
if ( FNullEnt ( HealingSource ) ) { return ; }
Vector HealLocation = ZERO_VECTOR ;
AvHAIHiveDefinition * HiveRef = AITAC_GetHiveFromEdict ( HealingSource ) ;
if ( HiveRef )
{
HealLocation = HiveRef - > FloorLocation ;
}
else
{
if ( IsEdictPlayer ( HealingSource ) )
{
HealLocation = HealingSource - > v . origin ;
}
else
{
HealLocation = FindClosestNavigablePointToDestination ( pBot - > BotNavInfo . NavProfile , pBot - > Edict - > v . origin , HealingSource - > v . origin , UTIL_MetresToGoldSrcUnits ( 5.0f ) ) ;
}
}
if ( ! vIsZero ( HealLocation ) )
{
Task - > TaskType = TASK_GET_HEALTH ;
Task - > TaskTarget = HealingSource ;
Task - > TaskLocation = HealLocation ;
Task - > bTaskIsUrgent = bIsUrgent ;
}
}
void AITASK_SetWeldTask ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task , edict_t * Target , const bool bIsUrgent )
{
if ( FNullEnt ( Target ) | | ( Target - > v . deadflag ! = DEAD_NO ) )
{
AITASK_ClearBotTask ( pBot , Task ) ;
return ;
}
if ( Task - > TaskType = = TASK_WELD & & Task - > TaskTarget = = Target )
{
Task - > bTaskIsUrgent = bIsUrgent ;
return ;
}
if ( ! PlayerHasWeapon ( pBot - > Player , WEAPON_MARINE_WELDER ) )
{
AvHAIDroppedItem * NearestWelder = AITAC_FindClosestItemToLocation ( pBot - > Edict - > v . origin , DEPLOYABLE_ITEM_WELDER , pBot - > Player - > GetTeam ( ) , pBot - > BotNavInfo . NavProfile . ReachabilityFlag , 0.0f , 0.0f , true ) ;
if ( ! NearestWelder )
{
AITASK_ClearBotTask ( pBot , Task ) ;
return ;
}
else
{
Task - > TaskSecondaryTarget = NearestWelder - > edict ;
}
}
Task - > TaskTarget = Target ;
Task - > TaskType = TASK_WELD ;
Task - > bTaskIsUrgent = bIsUrgent ;
Task - > TaskLocation = ZERO_VECTOR ;
Task - > TaskLength = 0.0f ;
if ( IsEdictPlayer ( Target ) | | IsEdictStructure ( Target ) ) { return ; }
Vector TargetLocation = UTIL_GetButtonFloorLocation ( pBot - > Edict - > v . origin , Task - > TaskTarget ) ;
if ( vIsZero ( TargetLocation ) )
{
TargetLocation = Task - > TaskTarget - > v . origin ;
}
Vector TaskLocation = FindClosestNavigablePointToDestination ( pBot - > BotNavInfo . NavProfile , pBot - > Edict - > v . origin , TargetLocation , UTIL_MetresToGoldSrcUnits ( 5.0f ) ) ;
if ( vIsZero ( TaskLocation ) )
{
AITASK_ClearBotTask ( pBot , Task ) ;
return ;
}
Task - > TaskLocation = TaskLocation ;
}
void AITASK_SetAttackTask ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task , edict_t * Target , const bool bIsUrgent )
{
// Don't set the task if the target is invalid, dead or on the same team as the bot (can't picture a situation where you want them to teamkill...)
if ( ! Target | | FNullEnt ( Target ) | | ( Target - > v . deadflag ! = DEAD_NO ) | | Target - > v . team = = pBot - > Edict - > v . team )
{
AITASK_ClearBotTask ( pBot , Task ) ;
return ;
}
if ( Task - > TaskType = = TASK_ATTACK & & Task - > TaskTarget = = Target )
{
Task - > bTaskIsUrgent = bIsUrgent ;
return ;
}
AITASK_ClearBotTask ( pBot , Task ) ;
Task - > TaskType = TASK_ATTACK ;
Task - > TaskTarget = Target ;
Task - > bTaskIsUrgent = bIsUrgent ;
// We don't need an attack location for players since this will be moving around anyway
if ( IsEdictPlayer ( Target ) )
{
Task - > bTargetIsPlayer = true ;
return ;
}
// Get as close as possible to the target
Vector AttackLocation = FindClosestNavigablePointToDestination ( pBot - > BotNavInfo . NavProfile , pBot - > CurrentFloorPosition , UTIL_GetEntityGroundLocation ( Target ) , UTIL_MetresToGoldSrcUnits ( 20.0f ) ) ;
if ( AttackLocation ! = g_vecZero )
{
Task - > TaskLocation = AttackLocation ;
}
else
{
AttackLocation = Target - > v . origin ;
}
}
void AITASK_SetMoveTask ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task , const Vector Location , bool bIsUrgent )
{
if ( Task - > TaskType = = TASK_MOVE & & vDist2DSq ( Task - > TaskLocation , Location ) < sqrf ( 16.0f ) )
{
Task - > bTaskIsUrgent = bIsUrgent ;
return ;
}
AITASK_ClearBotTask ( pBot , Task ) ;
if ( vIsZero ( Location ) ) { return ; }
UpdateBotMoveProfile ( pBot , MOVESTYLE_NORMAL ) ;
Vector MoveStart = AdjustPointForPathfinding ( pBot - > CurrentFloorPosition ) ;
Vector MoveEnd = AdjustPointForPathfinding ( Location ) ;
// Get as close as possible to desired location
Vector MoveLocation = FindClosestNavigablePointToDestination ( pBot - > BotNavInfo . NavProfile , MoveStart , MoveEnd , UTIL_MetresToGoldSrcUnits ( 1.0f ) ) ;
if ( vIsZero ( MoveLocation ) )
{
Vector ReverseMove = FindClosestNavigablePointToDestination ( pBot - > BotNavInfo . NavProfile , MoveEnd , MoveStart , UTIL_MetresToGoldSrcUnits ( 5.0f ) ) ;
if ( ! vIsZero ( ReverseMove ) )
{
MoveLocation = MoveEnd ;
}
}
if ( ! vIsZero ( MoveLocation ) )
{
Task - > TaskType = TASK_MOVE ;
Task - > TaskLocation = MoveLocation ;
Task - > bTaskIsUrgent = bIsUrgent ;
Task - > TaskLength = 120.0f ; // Set a maximum time to reach destination. Helps avoid bots getting permanently stuck
}
}
void AITASK_SetBuildTask ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task , const AvHAIDeployableStructureType StructureType , const Vector Location , const bool bIsUrgent )
{
if ( Task - > TaskType = = TASK_BUILD & & Task - > StructureType = = StructureType & & vDist2DSq ( Task - > TaskLocation , Location ) < sqrf ( UTIL_MetresToGoldSrcUnits ( 5.0f ) ) ) { return ; }
AITASK_ClearBotTask ( pBot , Task ) ;
if ( vIsZero ( Location ) ) { return ; }
// Get as close as possible to desired location
Vector BuildLocation = FindClosestNavigablePointToDestination ( BaseNavProfiles [ GORGE_BASE_NAV_PROFILE ] , AITAC_GetTeamStartingLocation ( pBot - > Player - > GetTeam ( ) ) , Location , UTIL_MetresToGoldSrcUnits ( 10.0f ) ) ;
BuildLocation = UTIL_ProjectPointToNavmesh ( BuildLocation , BaseNavProfiles [ STRUCTURE_BASE_NAV_PROFILE ] ) ;
if ( vIsZero ( BuildLocation ) )
{
BuildLocation = FindClosestNavigablePointToDestination ( pBot - > BotNavInfo . NavProfile , pBot - > CurrentFloorPosition , Location , UTIL_MetresToGoldSrcUnits ( 10.0f ) ) ;
}
if ( BuildLocation ! = g_vecZero )
{
Task - > TaskType = TASK_BUILD ;
Task - > TaskLocation = BuildLocation ;
Task - > StructureType = StructureType ;
Task - > bTaskIsUrgent = bIsUrgent ;
if ( StructureType = = STRUCTURE_ALIEN_HIVE )
{
char buf [ 512 ] ;
string MapLocationName ;
if ( GetNearestMapLocationAtPoint ( Task - > TaskLocation , MapLocationName ) )
{
sprintf ( buf , " I'll drop hive at %s " , MapLocationName . c_str ( ) ) ;
}
else
{
sprintf ( buf , " I'll drop the hive " ) ;
}
BotSay ( pBot , true , 1.0f , buf ) ;
}
}
}
void AITASK_SetBuildTask ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task , edict_t * StructureToBuild , const bool bIsUrgent )
{
AITASK_ClearBotTask ( pBot , Task ) ;
if ( FNullEnt ( StructureToBuild ) | | UTIL_StructureIsFullyBuilt ( StructureToBuild ) ) { return ; }
if ( Task - > TaskType = = TASK_BUILD & & Task - > TaskTarget = = StructureToBuild )
{
Task - > bTaskIsUrgent = bIsUrgent ;
return ;
}
// Get as close as possible to desired location
Vector BuildLocation = UTIL_ProjectPointToNavmesh ( StructureToBuild - > v . origin ) ;
Task - > TaskType = TASK_BUILD ;
Task - > TaskTarget = StructureToBuild ;
Task - > TaskLocation = ( ! vIsZero ( BuildLocation ) ) ? BuildLocation : UTIL_GetFloorUnderEntity ( StructureToBuild ) ;
Task - > bTaskIsUrgent = bIsUrgent ;
Task - > StructureType = GetStructureTypeFromEdict ( StructureToBuild ) ;
}
void AITASK_SetCapResNodeTask ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task , const AvHAIResourceNode * NodeRef , const bool bIsUrgent )
{
if ( ! NodeRef ) { return ; }
AvHAIDeployableStructureType NodeStructureType = ( IsPlayerMarine ( pBot - > Edict ) ) ? STRUCTURE_MARINE_RESTOWER : STRUCTURE_ALIEN_RESTOWER ;
if ( Task - > TaskType = = TASK_CAP_RESNODE & & Task - > TaskTarget = = NodeRef - > ResourceEdict )
{
Task - > bTaskIsUrgent = bIsUrgent ;
return ;
}
AITASK_ClearBotTask ( pBot , Task ) ;
Vector WaitLocation = UTIL_GetRandomPointOnNavmeshInRadius ( pBot - > BotNavInfo . NavProfile , NodeRef - > Location , UTIL_MetresToGoldSrcUnits ( 1.0f ) ) ;
Task - > TaskType = TASK_CAP_RESNODE ;
Task - > StructureType = NodeStructureType ;
Task - > TaskLocation = ( ! vIsZero ( WaitLocation ) ) ? WaitLocation : NodeRef - > Location ;
Task - > TaskTarget = NodeRef - > ResourceEdict ;
Task - > bTaskIsUrgent = bIsUrgent ;
}
void AITASK_SetDefendTask ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task , edict_t * Target , const bool bIsUrgent )
{
if ( Task - > TaskType = = TASK_DEFEND & & Task - > TaskTarget = = Target )
{
Task - > bTaskIsUrgent = bIsUrgent ;
return ;
}
AITASK_ClearBotTask ( pBot , Task ) ;
// Can't defend an invalid or dead target
if ( FNullEnt ( Target ) | | Target - > v . deadflag ! = DEAD_NO ) { return ; }
Task - > TaskType = TASK_DEFEND ;
Task - > TaskTarget = Target ;
Task - > bTaskIsUrgent = bIsUrgent ;
Vector DefendPoint = FindClosestNavigablePointToDestination ( pBot - > BotNavInfo . NavProfile , pBot - > CurrentFloorPosition , UTIL_GetEntityGroundLocation ( Target ) , UTIL_MetresToGoldSrcUnits ( 10.0f ) ) ;
if ( DefendPoint ! = g_vecZero )
{
Task - > TaskLocation = DefendPoint ;
}
else
{
Task - > TaskLocation = UTIL_GetEntityGroundLocation ( Target ) ;
}
}
void AITASK_SetEvolveTask ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task , edict_t * EvolveHive , const AvHMessageID EvolveImpulse , const bool bIsUrgent )
{
if ( EvolveImpulse < = 0 )
{
AITASK_ClearBotTask ( pBot , Task ) ;
return ;
}
if ( Task - > TaskType = = TASK_EVOLVE & & Task - > TaskTarget = = EvolveHive )
{
Task - > Evolution = EvolveImpulse ;
Task - > bTaskIsUrgent = bIsUrgent ;
return ;
}
AITASK_ClearBotTask ( pBot , Task ) ;
Task - > TaskType = TASK_EVOLVE ;
Task - > TaskTarget = EvolveHive ;
Task - > TaskLocation = g_vecZero ;
Task - > Evolution = EvolveImpulse ;
Task - > bTaskIsUrgent = bIsUrgent ;
}
void AITASK_SetEvolveTask ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task , const Vector EvolveLocation , const AvHMessageID EvolveImpulse , const bool bIsUrgent )
{
if ( Task - > TaskType = = TASK_EVOLVE & & Task - > Evolution = = EvolveImpulse )
{
Task - > TaskLocation = EvolveLocation ;
Task - > bTaskIsUrgent = bIsUrgent ;
return ;
}
AITASK_ClearBotTask ( pBot , Task ) ;
if ( EvolveImpulse < = 0 ) { return ; }
Task - > TaskType = TASK_EVOLVE ;
Task - > TaskLocation = EvolveLocation ;
Task - > Evolution = EvolveImpulse ;
Task - > bTaskIsUrgent = bIsUrgent ;
}
void AITASK_SetUseTask ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task , edict_t * Target , const bool bIsUrgent )
{
if ( Task - > TaskType = = TASK_USE & & Task - > TaskTarget = = Target )
{
Task - > bTaskIsUrgent = bIsUrgent ;
return ;
}
Task - > TaskType = TASK_USE ;
Task - > TaskTarget = Target ;
Task - > TaskLocation = FindClosestNavigablePointToDestination ( pBot - > BotNavInfo . NavProfile , pBot - > CurrentFloorPosition , UTIL_ProjectPointToNavmesh ( UTIL_GetCentreOfEntity ( Target ) ) , UTIL_MetresToGoldSrcUnits ( 10.0f ) ) ;
Task - > bTaskIsUrgent = bIsUrgent ;
Task - > TaskLength = 10.0f ;
Task - > TaskStartedTime = gpGlobals - > time ;
}
void AITASK_SetUseTask ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task , edict_t * Target , const Vector UseLocation , const bool bIsUrgent )
{
if ( Task - > TaskType = = TASK_USE & & Task - > TaskTarget = = Target )
{
Task - > bTaskIsUrgent = bIsUrgent ;
return ;
}
Task - > TaskType = TASK_USE ;
Task - > TaskTarget = Target ;
Task - > TaskLocation = UseLocation ;
Task - > bTaskIsUrgent = bIsUrgent ;
Task - > TaskLength = 10.0f ;
Task - > TaskStartedTime = gpGlobals - > time ;
}
void AITASK_SetTouchTask ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task , edict_t * Target , bool bIsUrgent )
{
if ( Task - > TaskType = = TASK_TOUCH & & Task - > TaskTarget = = Target )
{
Task - > bTaskIsUrgent = bIsUrgent ;
return ;
}
Task - > TaskType = TASK_TOUCH ;
Task - > TaskTarget = Target ;
Task - > TaskLocation = FindClosestNavigablePointToDestination ( pBot - > BotNavInfo . NavProfile , pBot - > CurrentFloorPosition , UTIL_ProjectPointToNavmesh ( UTIL_GetCentreOfEntity ( Target ) ) , UTIL_MetresToGoldSrcUnits ( 10.0f ) ) ;
Task - > bTaskIsUrgent = bIsUrgent ;
}
void AITASK_SetReinforceStructureTask ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task , edict_t * Target , bool bIsUrgent )
{
if ( Task - > TaskType = = TASK_REINFORCE_STRUCTURE & & Target = = Task - > TaskTarget )
{
Task - > bTaskIsUrgent = bIsUrgent ;
return ;
}
AITASK_ClearBotTask ( pBot , Task ) ;
if ( FNullEnt ( Target ) | | Target - > v . deadflag ! = DEAD_NO ) { return ; }
Task - > TaskType = TASK_REINFORCE_STRUCTURE ;
Task - > TaskTarget = Target ;
Task - > StructureType = GetStructureTypeFromEdict ( Target ) ;
Task - > bTaskIsUrgent = bIsUrgent ;
}
void AITASK_SetReinforceStructureTask ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task , edict_t * Target , const AvHAIDeployableStructureType FirstStructureType , bool bIsUrgent )
{
if ( Task - > TaskType = = TASK_REINFORCE_STRUCTURE & & Target = = Task - > TaskTarget )
{
Task - > bTaskIsUrgent = bIsUrgent ;
Task - > StructureType = FirstStructureType ;
return ;
}
AITASK_ClearBotTask ( pBot , Task ) ;
Task - > TaskType = TASK_REINFORCE_STRUCTURE ;
Task - > TaskTarget = Target ;
Task - > bTaskIsUrgent = bIsUrgent ;
Task - > StructureType = FirstStructureType ;
}
void AITASK_SetSecureHiveTask ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task , edict_t * Target , const Vector WaitLocation , bool bIsUrgent )
{
if ( Task - > TaskType = = TASK_SECURE_HIVE & & Target = = Task - > TaskTarget )
{
Task - > bTaskIsUrgent = bIsUrgent ;
Task - > TaskLocation = WaitLocation ;
return ;
}
AITASK_ClearBotTask ( pBot , Task ) ;
Task - > TaskType = TASK_SECURE_HIVE ;
Task - > TaskTarget = Target ;
Task - > bTaskIsUrgent = bIsUrgent ;
Task - > TaskLocation = WaitLocation ;
}
void AITASK_SetMineStructureTask ( AvHAIPlayer * pBot , AvHAIPlayerTask * Task , edict_t * Target , bool bIsUrgent )
{
if ( Task - > TaskType = = TASK_PLACE_MINE & & Target = = Task - > TaskTarget )
{
Task - > bTaskIsUrgent = bIsUrgent ;
return ;
}
AITASK_ClearBotTask ( pBot , Task ) ;
Task - > TaskType = TASK_PLACE_MINE ;
Task - > TaskTarget = Target ;
Task - > bTaskIsUrgent = bIsUrgent ;
Task - > TaskLocation = UTIL_GetNextMinePosition2 ( Target ) ;
Task - > StructureType = STRUCTURE_MARINE_DEPLOYEDMINE ;
}