mirror of
https://github.com/ENSL/NS.git
synced 2024-11-10 07:11:38 +00:00
Wave attacking implementation
This commit is contained in:
parent
8835eb0a60
commit
6021daabab
13 changed files with 695 additions and 198 deletions
|
@ -323,7 +323,7 @@ typedef struct _BOT_MSG
|
|||
bool bIsTeamSay = false; // Is this a team-only message?
|
||||
} bot_msg;
|
||||
|
||||
typedef struct _BOT_GUARD_INFO
|
||||
typedef struct _AVH_AI_GUARD_INFO
|
||||
{
|
||||
Vector GuardLocation = g_vecZero; // What position are we guarding?
|
||||
Vector GuardStandPosition = g_vecZero; // Where the bot should stand to guard position (moves around a bit)
|
||||
|
@ -414,7 +414,8 @@ typedef enum
|
|||
TASK_TOUCH,
|
||||
TASK_REINFORCE_STRUCTURE,
|
||||
TASK_SECURE_HIVE,
|
||||
TASK_PLACE_MINE
|
||||
TASK_PLACE_MINE,
|
||||
TASK_ATTACK_BASE
|
||||
}
|
||||
BotTaskType;
|
||||
|
||||
|
@ -809,7 +810,24 @@ typedef struct AVH_AI_PLAYER
|
|||
|
||||
float HearingThreshold = 0.0f; // How loud does a sound need to be before the bot detects it? This is set when hearing a sound so that louder sounds drown out quieter ones, and decrements quickly
|
||||
|
||||
int DebugValue = 0; // Used for debugging the bot
|
||||
|
||||
} AvHAIPlayer;
|
||||
|
||||
typedef struct _AVH_AI_SQUAD
|
||||
{
|
||||
AvHTeamNumber SquadTeam = TEAM_IND; // Which team this squad is for
|
||||
vector<AvHAIPlayer*> SquadMembers; // Which bots are assigned to this
|
||||
Vector SquadGatherLocation = g_vecZero; // Where should the squad gather before attempting the objective?
|
||||
edict_t* SquadTarget = nullptr; // The target of the objective
|
||||
BotTaskType SquadObjective = TASK_NONE; // What to do with the objective
|
||||
bool bExecuteObjective = false; // Are we at the gather or execute phase?
|
||||
|
||||
bool IsValid()
|
||||
{
|
||||
return (SquadMembers.size() > 0 && !FNullEnt(SquadTarget));
|
||||
}
|
||||
} AvHAISquad;
|
||||
|
||||
|
||||
#endif
|
|
@ -302,12 +302,12 @@ bool GetNearestMapLocationAtPoint(vec3_t SearchLocation, string& outLocation)
|
|||
return theSuccess;
|
||||
}
|
||||
|
||||
void AIDEBUG_DrawBotPath(AvHAIPlayer* pBot, float DrawTime)
|
||||
void AIDEBUG_DrawBotPath(edict_t* OutputPlayer, AvHAIPlayer* pBot, float DrawTime)
|
||||
{
|
||||
AIDEBUG_DrawPath(pBot->BotNavInfo.CurrentPath, DrawTime);
|
||||
AIDEBUG_DrawPath(OutputPlayer, pBot->BotNavInfo.CurrentPath, DrawTime);
|
||||
}
|
||||
|
||||
void AIDEBUG_DrawPath(vector<bot_path_node>& path, float DrawTime)
|
||||
void AIDEBUG_DrawPath(edict_t* OutputPlayer, vector<bot_path_node>& path, float DrawTime)
|
||||
{
|
||||
if (path.size() == 0) { return; }
|
||||
|
||||
|
@ -320,28 +320,28 @@ void AIDEBUG_DrawPath(vector<bot_path_node>& path, float DrawTime)
|
|||
{
|
||||
case SAMPLE_POLYFLAGS_WELD:
|
||||
case SAMPLE_POLYFLAGS_DOOR:
|
||||
UTIL_DrawLine(INDEXENT(1), FromLoc, ToLoc, DrawTime, 255, 0, 0);
|
||||
UTIL_DrawLine(OutputPlayer, FromLoc, ToLoc, DrawTime, 255, 0, 0);
|
||||
break;
|
||||
case SAMPLE_POLYFLAGS_JUMP:
|
||||
case SAMPLE_POLYFLAGS_DUCKJUMP:
|
||||
UTIL_DrawLine(INDEXENT(1), FromLoc, ToLoc, DrawTime, 255, 255, 0);
|
||||
UTIL_DrawLine(OutputPlayer, FromLoc, ToLoc, DrawTime, 255, 255, 0);
|
||||
break;
|
||||
case SAMPLE_POLYFLAGS_LADDER:
|
||||
case SAMPLE_POLYFLAGS_LIFT:
|
||||
UTIL_DrawLine(INDEXENT(1), FromLoc, ToLoc, DrawTime, 0, 0, 255);
|
||||
UTIL_DrawLine(OutputPlayer, FromLoc, ToLoc, DrawTime, 0, 0, 255);
|
||||
break;
|
||||
case SAMPLE_POLYFLAGS_WALLCLIMB:
|
||||
UTIL_DrawLine(INDEXENT(1), FromLoc, ToLoc, DrawTime, 0, 128, 0);
|
||||
UTIL_DrawLine(OutputPlayer, FromLoc, ToLoc, DrawTime, 0, 128, 0);
|
||||
break;
|
||||
case SAMPLE_POLYFLAGS_BLOCKED:
|
||||
UTIL_DrawLine(INDEXENT(1), FromLoc, ToLoc, DrawTime, 128, 128, 128);
|
||||
UTIL_DrawLine(OutputPlayer, FromLoc, ToLoc, DrawTime, 128, 128, 128);
|
||||
break;
|
||||
case SAMPLE_POLYFLAGS_TEAM1PHASEGATE:
|
||||
case SAMPLE_POLYFLAGS_TEAM2PHASEGATE:
|
||||
UTIL_DrawLine(INDEXENT(1), FromLoc, ToLoc, DrawTime, 255, 128, 128);
|
||||
UTIL_DrawLine(OutputPlayer, FromLoc, ToLoc, DrawTime, 255, 128, 128);
|
||||
break;
|
||||
default:
|
||||
UTIL_DrawLine(INDEXENT(1), FromLoc, ToLoc, DrawTime);
|
||||
UTIL_DrawLine(OutputPlayer, FromLoc, ToLoc, DrawTime);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -525,32 +525,29 @@ void UTIL_DrawHUDText(edict_t* pEntity, char channel, float x, float y, unsigned
|
|||
{
|
||||
if (FNullEnt(pEntity)) { return; }
|
||||
|
||||
float FrameDelta = AIMGR_GetFrameDelta();
|
||||
FrameDelta *= 256.0f;
|
||||
float delta = AIMGR_GetFrameDelta();
|
||||
|
||||
short Duration = (short)roundf(FrameDelta);
|
||||
// TODO: Be able to turn these off as a preference
|
||||
hudtextparms_t theTextParms;
|
||||
|
||||
MESSAGE_BEGIN(MSG_ONE_UNRELIABLE, SVC_TEMPENTITY, NULL, pEntity);
|
||||
WRITE_BYTE(TE_TEXTMESSAGE);
|
||||
WRITE_BYTE(channel); // channel
|
||||
WRITE_SHORT((int)(x * 8192.0f)); // x coordinates * 8192
|
||||
WRITE_SHORT((int)(y * 8192.0f)); // y coordinates * 8192
|
||||
WRITE_BYTE(0); // effect (fade in/out)
|
||||
WRITE_BYTE(r); // initial RED
|
||||
WRITE_BYTE(g); // initial GREEN
|
||||
WRITE_BYTE(b); // initial BLUE
|
||||
WRITE_BYTE(1); // initial ALPHA
|
||||
WRITE_BYTE(r); // effect RED
|
||||
WRITE_BYTE(g); // effect GREEN
|
||||
WRITE_BYTE(b); // effect BLUE
|
||||
WRITE_BYTE(1); // effect ALPHA
|
||||
WRITE_SHORT(1); // fade-in time in seconds * 256
|
||||
WRITE_SHORT(Duration); // fade-out time in seconds * 256
|
||||
WRITE_SHORT(Duration); // hold time in seconds * 256
|
||||
WRITE_STRING(string);//string); // send the string
|
||||
MESSAGE_END(); // end
|
||||
// Init text parms
|
||||
theTextParms.x = x;
|
||||
theTextParms.y = y;
|
||||
theTextParms.effect = 0;
|
||||
theTextParms.r1 = 240;
|
||||
theTextParms.g1 = 240;
|
||||
theTextParms.b1 = 240;
|
||||
theTextParms.a1 = 128;
|
||||
theTextParms.r2 = 240;
|
||||
theTextParms.g2 = 240;
|
||||
theTextParms.b2 = 240;
|
||||
theTextParms.a2 = 128;
|
||||
theTextParms.fadeinTime = .0f;
|
||||
theTextParms.fadeoutTime = .0f;
|
||||
theTextParms.holdTime = 0.2f;
|
||||
theTextParms.channel = channel;
|
||||
|
||||
return;
|
||||
UTIL_HudMessage(CBaseEntity::Instance(pEntity), theTextParms, string);
|
||||
}
|
||||
|
||||
void UTIL_ClearLocalizations()
|
||||
|
@ -682,6 +679,8 @@ char* UTIL_TaskTypeToChar(const BotTaskType TaskType)
|
|||
return "Touch Trigger";
|
||||
case TASK_WELD:
|
||||
return "Weld Target";
|
||||
case TASK_ATTACK_BASE:
|
||||
return "Attack Enemy Base";
|
||||
default:
|
||||
return "None";
|
||||
}
|
||||
|
|
|
@ -39,8 +39,8 @@ bool GetNearestMapLocationAtPoint(vec3_t SearchLocation, string& outLocation);
|
|||
|
||||
AvHAIDeployableStructureType GetDeployableObjectTypeFromEdict(const edict_t* StructureEdict);
|
||||
|
||||
void AIDEBUG_DrawBotPath(AvHAIPlayer* pBot, float DrawTime = 0.0f);
|
||||
void AIDEBUG_DrawPath(vector<bot_path_node>& path, float DrawTime = 0.0f);
|
||||
void AIDEBUG_DrawBotPath(edict_t* OutputPlayer, AvHAIPlayer* pBot, float DrawTime = 0.0f);
|
||||
void AIDEBUG_DrawPath(edict_t* OutputPlayer, vector<bot_path_node>& path, float DrawTime = 0.0f);
|
||||
|
||||
// Draws a white line between start and end for the given player (pEntity) for 0.1s
|
||||
void UTIL_DrawLine(edict_t* pEntity, Vector start, Vector end);
|
||||
|
|
|
@ -21,6 +21,10 @@ extern nav_profile BaseNavProfiles[MAX_NAV_PROFILES]; // Array of nav profiles
|
|||
|
||||
extern cvar_t avh_botdebugmode;
|
||||
|
||||
#ifdef BOTDEBUG
|
||||
extern edict_t* DebugBots[MAX_PLAYERS];
|
||||
#endif
|
||||
|
||||
void BotJump(AvHAIPlayer* pBot)
|
||||
{
|
||||
if (pBot->BotNavInfo.IsOnGround)
|
||||
|
@ -1861,7 +1865,8 @@ void EndBotFrame(AvHAIPlayer* pBot)
|
|||
|
||||
void CustomThink(AvHAIPlayer* pBot)
|
||||
{
|
||||
DEBUG_PrintCombatInfo(pBot);
|
||||
// Test Combat Stuff
|
||||
//DEBUG_PrintCombatInfo(INDEXENT(1), pBot);
|
||||
|
||||
pBot->CurrentEnemy = BotGetNextEnemyTarget(pBot);
|
||||
|
||||
|
@ -1876,6 +1881,66 @@ void CustomThink(AvHAIPlayer* pBot)
|
|||
AlienCombatThink(pBot);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (AITAC_ShouldBotBeCautious(pBot))
|
||||
{
|
||||
MoveTo(pBot, AITAC_GetTeamStartingLocation(AIMGR_GetEnemyTeam(pBot->Player->GetTeam())), MOVESTYLE_AMBUSH);
|
||||
}
|
||||
else
|
||||
{
|
||||
MoveTo(pBot, AITAC_GetTeamStartingLocation(AIMGR_GetEnemyTeam(pBot->Player->GetTeam())), MOVESTYLE_NORMAL);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*AITASK_BotUpdateAndClearTasks(pBot);
|
||||
|
||||
if (pBot->PrimaryBotTask.TaskType != TASK_SECURE_HIVE)
|
||||
{
|
||||
AvHTeamNumber BotTeam = pBot->Player->GetTeam();
|
||||
AvHTeamNumber EnemyTeam = AIMGR_GetEnemyTeam(BotTeam);
|
||||
|
||||
AvHAIHiveDefinition* HiveToClear = nullptr;
|
||||
float MinDist = 0.0f;
|
||||
|
||||
vector<AvHAIHiveDefinition*> Hives = AITAC_GetAllHives();
|
||||
|
||||
for (auto it = Hives.begin(); it != Hives.end(); it++)
|
||||
{
|
||||
AvHAIHiveDefinition* ThisHive = (*it);
|
||||
|
||||
if (ThisHive->Status == HIVE_STATUS_UNBUILT)
|
||||
{
|
||||
DeployableSearchFilter EnemyStuffFilter;
|
||||
EnemyStuffFilter.DeployableTeam = EnemyTeam;
|
||||
EnemyStuffFilter.DeployableTypes = SEARCH_ALL_STRUCTURES;
|
||||
EnemyStuffFilter.ReachabilityTeam = BotTeam;
|
||||
EnemyStuffFilter.ReachabilityFlags = pBot->BotNavInfo.NavProfile.ReachabilityFlag;
|
||||
EnemyStuffFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(15.0f);
|
||||
|
||||
if (AITAC_DeployableExistsAtLocation(ThisHive->FloorLocation, &EnemyStuffFilter))
|
||||
{
|
||||
float ThisDist = vDist2DSq(pBot->Edict->v.origin, ThisHive->FloorLocation);
|
||||
|
||||
if (!HiveToClear || ThisDist < MinDist)
|
||||
{
|
||||
HiveToClear = ThisHive;
|
||||
MinDist = ThisDist;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (HiveToClear)
|
||||
{
|
||||
AITASK_SetSecureHiveTask(pBot, &pBot->PrimaryBotTask, HiveToClear->HiveEdict, HiveToClear->FloorLocation, true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BotProgressTask(pBot, &pBot->PrimaryBotTask);
|
||||
}*/
|
||||
}
|
||||
|
||||
void DroneThink(AvHAIPlayer* pBot)
|
||||
|
@ -2482,6 +2547,23 @@ AvHAICombatStrategy GetLerkCombatStrategyForTarget(AvHAIPlayer* pBot, enemy_stat
|
|||
float EnemyHealthPercent = GetPlayerOverallHealthPercent(EnemyEdict);
|
||||
int NumAllies = AITAC_GetNumPlayersOnTeamWithLOS(EnemyTeam, EnemyEdict->v.origin, UTIL_MetresToGoldSrcUnits(20.0f), EnemyEdict);
|
||||
|
||||
DeployableSearchFilter TurretFilter;
|
||||
TurretFilter.DeployableTeam = EnemyTeam;
|
||||
TurretFilter.DeployableTypes = (STRUCTURE_MARINE_TURRET | STRUCTURE_ALIEN_OFFENCECHAMBER);
|
||||
TurretFilter.IncludeStatusFlags = STRUCTURE_STATUS_COMPLETED;
|
||||
TurretFilter.ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING;
|
||||
TurretFilter.MaxSearchRadius = BALANCE_VAR(kTurretRange);
|
||||
|
||||
vector<AvHAIBuildableStructure> Turrets = AITAC_FindAllDeployables(EnemyEdict->v.origin, &TurretFilter);
|
||||
|
||||
for (auto it = Turrets.begin(); it != Turrets.end(); it++)
|
||||
{
|
||||
if (UTIL_QuickTrace(pBot->Edict, GetPlayerTopOfCollisionHull(it->edict), EnemyEdict->v.origin))
|
||||
{
|
||||
NumAllies++;
|
||||
}
|
||||
}
|
||||
|
||||
float DistToEnemy = vDist2DSq(pBot->Edict->v.origin, EnemyEdict->v.origin);
|
||||
|
||||
float RetreatHealthPercent = (NumAllies > 1) ? 0.5f : 0.35f;
|
||||
|
@ -2775,7 +2857,7 @@ AvHAICombatStrategy GetMarineCombatStrategyForTarget(AvHAIPlayer* pBot, enemy_st
|
|||
case TASK_CAP_RESNODE:
|
||||
case TASK_GUARD:
|
||||
case TASK_SECURE_HIVE:
|
||||
ThreatThreshold = 1.0f;
|
||||
ThreatThreshold = (IsPlayerMarine(pBot->Edict)) ? 1.0f : 2.0f;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -4370,17 +4452,9 @@ bool AIPlayerMustFinishCurrentTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
|
|||
if (Task->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_PENDING) { return true; }
|
||||
|
||||
// If we're already capping a node, are at the node and there is an unfinished tower on there, then finish the job and don't move on yet
|
||||
if (Task->TaskType == TASK_CAP_RESNODE)
|
||||
if (Task->TaskType == TASK_CAP_RESNODE && vDist2DSq(pBot->Edict->v.origin, Task->TaskLocation) < sqrf(UTIL_MetresToGoldSrcUnits(10.0f)))
|
||||
{
|
||||
const AvHAIResourceNode* ResNodeIndex = AITAC_GetNearestResourceNodeToLocation(Task->TaskLocation);
|
||||
|
||||
if (ResNodeIndex && ResNodeIndex->OwningTeam == BotTeam)
|
||||
{
|
||||
if (!FNullEnt(ResNodeIndex->ActiveTowerEntity) && !UTIL_StructureIsFullyBuilt(ResNodeIndex->ActiveTowerEntity))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5524,17 +5598,22 @@ void AIPlayerDMThink(AvHAIPlayer* pBot)
|
|||
void AIPlayerThink(AvHAIPlayer* pBot)
|
||||
{
|
||||
|
||||
//#ifdef DEBUG
|
||||
if (pBot == AIMGR_GetDebugAIPlayer())
|
||||
#ifdef BOTDEBUG
|
||||
for (int i = 0; i < gpGlobals->maxClients; i++)
|
||||
{
|
||||
bool bBreak = true; // Add a break point here if you want to debug a specific bot
|
||||
edict_t* PlayerEdict = INDEXENT(i + 1);
|
||||
|
||||
AIDEBUG_DrawBotPath(pBot);
|
||||
if (DebugBots[i] == pBot->Edict && !FNullEnt(PlayerEdict) && IsEdictPlayer(PlayerEdict) && IsPlayerHuman(PlayerEdict))
|
||||
{
|
||||
AvHAIPlayer* BotRef = AIMGR_GetBotRefFromEdict(DebugBots[i]);
|
||||
|
||||
DEBUG_PrintTaskInfo(pBot);
|
||||
DEBUG_PrintCombatInfo(pBot);
|
||||
if (BotRef)
|
||||
{
|
||||
DEBUG_PrintBotDebugInfo(PlayerEdict, BotRef);
|
||||
}
|
||||
}
|
||||
}
|
||||
//#endif
|
||||
#endif
|
||||
|
||||
pBot->ThinkDelta = fminf(gpGlobals->time - pBot->LastThinkTime, 0.1f);
|
||||
pBot->LastThinkTime = gpGlobals->time;
|
||||
|
@ -6327,6 +6406,8 @@ void AIPlayerSetAlienAssaultPrimaryTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task
|
|||
|
||||
if (Task->TaskType == TASK_EVOLVE) { return; }
|
||||
|
||||
// CHECK TO SEE IF WE NEED TO EVOLVE INTO FADE/ONOS
|
||||
|
||||
if (!IsPlayerFade(pBot->Edict) && !IsPlayerOnos(pBot->Edict))
|
||||
{
|
||||
|
||||
|
@ -6366,6 +6447,8 @@ void AIPlayerSetAlienAssaultPrimaryTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task
|
|||
|
||||
}
|
||||
|
||||
// CHECK TO SEE IF WE NEED TO HELP BREAK A SIEGE THAT IS ACTIVE (I.E. HAS SIEGE TURRETS)
|
||||
|
||||
const AvHAIHiveDefinition* NearestSiegedHive = AITAC_GetNearestHiveUnderActiveSiege(EnemyTeam, pBot->Edict->v.origin);
|
||||
|
||||
if (NearestSiegedHive)
|
||||
|
@ -6434,7 +6517,8 @@ void AIPlayerSetAlienAssaultPrimaryTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task
|
|||
}
|
||||
}
|
||||
|
||||
// If we're up against marines, look out for any siege stuff
|
||||
// CHECK IF MARINES ARE TRYING TO BUILD A SIEGE BASE
|
||||
|
||||
if (AIMGR_GetTeamType(EnemyTeam) == AVH_CLASS_TYPE_MARINE)
|
||||
{
|
||||
// Check if we're already trying to break a siege attempt, so we don't get torn between multiple potentials
|
||||
|
@ -6513,11 +6597,11 @@ void AIPlayerSetAlienAssaultPrimaryTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task
|
|||
|
||||
}
|
||||
|
||||
// CHECK IF WE NEED TO HOLD AN EMPTY HIVE FOR US TO BUILD IN
|
||||
|
||||
Vector EnemyBaseLocation = AITAC_GetTeamStartingLocation(EnemyTeam);
|
||||
|
||||
AvHAIHiveDefinition* HiveToGuard = nullptr;
|
||||
AvHAIHiveDefinition* HiveToSecure = nullptr;
|
||||
|
||||
vector<AvHAIHiveDefinition*> AllHives = AITAC_GetAllHives();
|
||||
|
||||
|
@ -6551,84 +6635,72 @@ void AIPlayerSetAlienAssaultPrimaryTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task
|
|||
|
||||
for (auto it = AllHives.begin(); it != AllHives.end(); it++)
|
||||
{
|
||||
if (!bShouldGuardEmptyHive) { continue; }
|
||||
|
||||
AvHAIHiveDefinition* ThisHive = (*it);
|
||||
|
||||
if (ThisHive->OwningTeam != TEAM_IND) { continue; }
|
||||
if (ThisHive->Status != HIVE_STATUS_UNBUILT) { continue; }
|
||||
|
||||
bool bEnemyIsSecuring = AITAC_DeployableExistsAtLocation(ThisHive->FloorLocation, &EnemyStuffFilter);
|
||||
|
||||
if (bEnemyIsSecuring)
|
||||
if (bEnemyIsSecuring) { continue; }
|
||||
|
||||
DeployableSearchFilter FriendlyStuffFilter;
|
||||
FriendlyStuffFilter.DeployableTeam = BotTeam;
|
||||
FriendlyStuffFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(15.0f);
|
||||
FriendlyStuffFilter.DeployableTypes = STRUCTURE_ALIEN_OFFENCECHAMBER;
|
||||
|
||||
// Don't guard a hive if some defences are already present
|
||||
if (AITAC_GetNumDeployablesNearLocation(ThisHive->FloorLocation, &FriendlyStuffFilter) >= 2) { continue; }
|
||||
|
||||
// Only guard empty hives if a gorge is in there
|
||||
if (AITAC_GetNumPlayersOfTeamAndClassInArea(BotTeam, ThisHive->FloorLocation, UTIL_MetresToGoldSrcUnits(20.0f), false, pBot->Edict, AVH_USER3_ALIEN_PLAYER2) == 0) { continue; }
|
||||
|
||||
bool bNeedsExtraGuards = true;
|
||||
int NumGuards = 0;
|
||||
|
||||
vector<AvHPlayer*> HumanPlayers = AIMGR_GetNonAIPlayersOnTeam(BotTeam);
|
||||
vector<AvHAIPlayer*> AITeamPlayers = AIMGR_GetAIPlayersOnTeam(BotTeam);
|
||||
|
||||
for (auto AIIt = AITeamPlayers.begin(); AIIt != AITeamPlayers.end(); AIIt++)
|
||||
{
|
||||
if ((*AIIt) == pBot) { continue; }
|
||||
|
||||
if ((*AIIt)->PrimaryBotTask.TaskType == TASK_GUARD && (*AIIt)->PrimaryBotTask.TaskTarget == ThisHive->HiveEdict)
|
||||
{
|
||||
if ((*AIIt)->Player->GetUser3() >= AVH_USER3_ALIEN_PLAYER3) { bNeedsExtraGuards = false; }
|
||||
NumGuards++;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto GuardIt = HumanPlayers.begin(); GuardIt != HumanPlayers.end(); GuardIt++)
|
||||
{
|
||||
AvHPlayer* ThisGuard = (*GuardIt);
|
||||
|
||||
if (IsPlayerActiveInGame(ThisGuard->edict()) && vDist2DSq(ThisGuard->edict()->v.origin, ThisHive->FloorLocation) < sqrf(UTIL_MetresToGoldSrcUnits(15.0f)))
|
||||
{
|
||||
if (ThisGuard->GetUser3() >= AVH_USER3_ALIEN_PLAYER3) { bNeedsExtraGuards = false; }
|
||||
NumGuards++;
|
||||
}
|
||||
}
|
||||
|
||||
bNeedsExtraGuards = bNeedsExtraGuards && NumGuards < 2;
|
||||
|
||||
if (bNeedsExtraGuards)
|
||||
{
|
||||
float ThisDist = vDist2DSq(ThisHive->FloorLocation, EnemyBaseLocation);
|
||||
|
||||
if (ThisDist > MaxSecureDist)
|
||||
{
|
||||
HiveToSecure = ThisHive;
|
||||
MaxSecureDist = ThisDist;
|
||||
HiveToGuard = ThisHive;
|
||||
MaxGuardDist = ThisDist;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!bShouldGuardEmptyHive) { continue; }
|
||||
|
||||
DeployableSearchFilter FriendlyStuffFilter;
|
||||
|
||||
FriendlyStuffFilter.DeployableTeam = BotTeam;
|
||||
FriendlyStuffFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(15.0f);
|
||||
FriendlyStuffFilter.DeployableTypes = STRUCTURE_ALIEN_OFFENCECHAMBER;
|
||||
|
||||
// Don't guard a hive if some defences are already present
|
||||
if (AITAC_GetNumDeployablesNearLocation(ThisHive->FloorLocation, &FriendlyStuffFilter) >= 2) { continue; }
|
||||
|
||||
// Only guard empty hives if a gorge is in there
|
||||
if (AITAC_GetNumPlayersOfTeamAndClassInArea(BotTeam, ThisHive->FloorLocation, UTIL_MetresToGoldSrcUnits(20.0f), false, pBot->Edict, AVH_USER3_ALIEN_PLAYER2) == 0) { continue; }
|
||||
|
||||
bool bNeedsExtraGuards = true;
|
||||
int NumGuards = 0;
|
||||
|
||||
vector<AvHPlayer*> HumanPlayers = AIMGR_GetNonAIPlayersOnTeam(BotTeam);
|
||||
vector<AvHAIPlayer*> AITeamPlayers = AIMGR_GetAIPlayersOnTeam(BotTeam);
|
||||
|
||||
for (auto AIIt = AITeamPlayers.begin(); AIIt != AITeamPlayers.end(); AIIt++)
|
||||
{
|
||||
if ((*AIIt) == pBot) { continue; }
|
||||
|
||||
if ((*AIIt)->PrimaryBotTask.TaskType == TASK_GUARD && (*AIIt)->PrimaryBotTask.TaskTarget == ThisHive->HiveEdict)
|
||||
{
|
||||
if ((*AIIt)->Player->GetUser3() >= AVH_USER3_ALIEN_PLAYER3) { bNeedsExtraGuards = false; }
|
||||
NumGuards++;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto GuardIt = HumanPlayers.begin(); GuardIt != HumanPlayers.end(); GuardIt++)
|
||||
{
|
||||
AvHPlayer* ThisGuard = (*GuardIt);
|
||||
|
||||
if (IsPlayerActiveInGame(ThisGuard->edict()) && vDist2DSq(ThisGuard->edict()->v.origin, ThisHive->FloorLocation) < sqrf(UTIL_MetresToGoldSrcUnits(15.0f)))
|
||||
{
|
||||
if (ThisGuard->GetUser3() >= AVH_USER3_ALIEN_PLAYER3) { bNeedsExtraGuards = false; }
|
||||
NumGuards++;
|
||||
}
|
||||
}
|
||||
|
||||
bNeedsExtraGuards = bNeedsExtraGuards && NumGuards < 2;
|
||||
|
||||
if (bNeedsExtraGuards)
|
||||
{
|
||||
float ThisDist = vDist2DSq(ThisHive->FloorLocation, EnemyBaseLocation);
|
||||
|
||||
if (ThisDist > MaxSecureDist)
|
||||
{
|
||||
HiveToGuard = ThisHive;
|
||||
MaxGuardDist = ThisDist;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// The purpose of this is to ensure we only guard one empty hive at a time, otherwise all the assault bots will be sitting around in empty hives and not pressuring marines
|
||||
// If we have an empty hive already being guarded, then this bool will ensure the bot doesn't go guard an empty hive even if there are 2
|
||||
bShouldGuardEmptyHive = false;
|
||||
}
|
||||
// The purpose of this is to ensure we only guard one empty hive at a time, otherwise all the assault bots will be sitting around in empty hives and not pressuring marines
|
||||
// If we have an empty hive already being guarded, then this bool will ensure the bot doesn't go guard an empty hive even if there are 2
|
||||
bShouldGuardEmptyHive = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6641,70 +6713,61 @@ void AIPlayerSetAlienAssaultPrimaryTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task
|
|||
Task->TaskLength = 60.0f;
|
||||
return;
|
||||
}
|
||||
else if (HiveToSecure)
|
||||
|
||||
// FIND A HIVE TO RETAKE. PICK THE WEAKEST ONE
|
||||
|
||||
int MaxHiveStrength = 0;
|
||||
AvHAIHiveDefinition* HiveToSecure = nullptr;
|
||||
|
||||
for (auto it = AllHives.begin(); it != AllHives.end(); it++)
|
||||
{
|
||||
// Check if we're already trying to clear out a hive
|
||||
if (Task->TaskType == TASK_ATTACK)
|
||||
AvHAIHiveDefinition* ThisHive = (*it);
|
||||
|
||||
if (ThisHive->OwningTeam == BotTeam) { continue; }
|
||||
|
||||
vector<AvHAIBuildableStructure> EnemyStructures = AITAC_FindAllDeployables(ThisHive->FloorLocation, &EnemyStuffFilter);
|
||||
|
||||
// Enemy hasn't built anything here, so doesn't need clearing
|
||||
if (ThisHive->OwningTeam != EnemyTeam && EnemyStructures.size() == 0) { continue; }
|
||||
|
||||
int ThisStrength = 0;
|
||||
|
||||
for (auto StructureIt = EnemyStructures.begin(); StructureIt != EnemyStructures.end(); StructureIt++)
|
||||
{
|
||||
const AvHAIHiveDefinition* HiveNearestAttackTarget = AITAC_GetNearestTeamHive(BotTeam, Task->TaskTarget->v.origin, false);
|
||||
|
||||
if (HiveNearestAttackTarget && vDist2DSq(HiveNearestAttackTarget->Location, Task->TaskTarget->v.origin) <= sqrf(UTIL_MetresToGoldSrcUnits(15.0f))) { return; }
|
||||
}
|
||||
|
||||
EnemyStuffFilter.DeployableTypes = SEARCH_ALL_STRUCTURES;
|
||||
|
||||
// Don't attack electrified structures as skulk
|
||||
if (pBot->Player->GetUser3() < AVH_USER3_ALIEN_PLAYER4)
|
||||
{
|
||||
EnemyStuffFilter.ExcludeStatusFlags = STRUCTURE_STATUS_ELECTRIFIED;
|
||||
}
|
||||
|
||||
vector<AvHAIBuildableStructure> AllEnemyThings = AITAC_FindAllDeployables(HiveToSecure->FloorLocation, &EnemyStuffFilter);
|
||||
|
||||
AvHAIBuildableStructure StructureToAttack;
|
||||
|
||||
for (auto it = AllEnemyThings.begin(); it != AllEnemyThings.end(); it++)
|
||||
{
|
||||
AvHAIBuildableStructure ThisStructure = (*it);
|
||||
|
||||
// First prioritise phase gates or alien OCs
|
||||
if (ThisStructure.StructureType == STRUCTURE_MARINE_PHASEGATE || ThisStructure.StructureType == STRUCTURE_ALIEN_OFFENCECHAMBER)
|
||||
switch (StructureIt->StructureType)
|
||||
{
|
||||
if (FNullEnt(StructureToAttack.edict) || StructureToAttack.StructureType != ThisStructure.StructureType || vDist2DSq(pBot->Edict->v.origin, ThisStructure.Location) < vDist2DSq(pBot->Edict->v.origin, StructureToAttack.Location))
|
||||
{
|
||||
StructureToAttack = ThisStructure;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!FNullEnt(StructureToAttack.edict) && (StructureToAttack.StructureType == STRUCTURE_MARINE_PHASEGATE || ThisStructure.StructureType == STRUCTURE_ALIEN_OFFENCECHAMBER)) { continue; }
|
||||
|
||||
// Then prioritise turret factories
|
||||
if (ThisStructure.StructureType == STRUCTURE_MARINE_TURRETFACTORY || ThisStructure.StructureType == STRUCTURE_MARINE_ADVTURRETFACTORY)
|
||||
{
|
||||
if (FNullEnt(StructureToAttack.edict) || StructureToAttack.StructureType != ThisStructure.StructureType || vDist2DSq(pBot->Edict->v.origin, ThisStructure.Location) < vDist2DSq(pBot->Edict->v.origin, StructureToAttack.Location))
|
||||
{
|
||||
StructureToAttack = ThisStructure;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!FNullEnt(StructureToAttack.edict) && (StructureToAttack.StructureType == STRUCTURE_MARINE_TURRETFACTORY || ThisStructure.StructureType == STRUCTURE_MARINE_ADVTURRETFACTORY)) { continue; }
|
||||
|
||||
// Then target any other structures
|
||||
if (FNullEnt(StructureToAttack.edict) || vDist2DSq(pBot->Edict->v.origin, ThisStructure.Location) < vDist2DSq(pBot->Edict->v.origin, StructureToAttack.Location))
|
||||
{
|
||||
StructureToAttack = ThisStructure;
|
||||
case STRUCTURE_MARINE_PHASEGATE:
|
||||
ThisStrength += 2;
|
||||
break;
|
||||
case STRUCTURE_MARINE_TURRETFACTORY:
|
||||
ThisStrength += (UTIL_IsStructureElectrified(StructureIt->edict)) ? 2 : 1;
|
||||
break;
|
||||
case STRUCTURE_MARINE_TURRET:
|
||||
ThisStrength += 1;
|
||||
break;
|
||||
case STRUCTURE_ALIEN_OFFENCECHAMBER:
|
||||
ThisStrength += 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (StructureToAttack.IsValid())
|
||||
if (!HiveToSecure || ThisStrength < MaxHiveStrength)
|
||||
{
|
||||
AITASK_SetAttackTask(pBot, Task, StructureToAttack.edict, false);
|
||||
return;
|
||||
HiveToSecure = ThisHive;
|
||||
MaxHiveStrength = ThisStrength;
|
||||
}
|
||||
}
|
||||
|
||||
if (HiveToSecure)
|
||||
{
|
||||
AITASK_SetSecureHiveTask(pBot, Task, HiveToSecure->HiveEdict, HiveToSecure->FloorLocation, false);
|
||||
return;
|
||||
}
|
||||
|
||||
// ATTACK THE ENEMY BASE
|
||||
|
||||
DeployableSearchFilter EnemyInfPortalFilter;
|
||||
EnemyInfPortalFilter.DeployableTypes = STRUCTURE_MARINE_INFANTRYPORTAL;
|
||||
EnemyInfPortalFilter.DeployableTeam = EnemyTeam;
|
||||
|
@ -6730,6 +6793,8 @@ void AIPlayerSetAlienAssaultPrimaryTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task
|
|||
return;
|
||||
}
|
||||
|
||||
// FIND ANY LAST ENEMIES TO KILL AND END GAME
|
||||
|
||||
vector<AvHPlayer*> AllEnemyPlayers = AIMGR_GetAllPlayersOnTeam(EnemyTeam);
|
||||
edict_t* TargetPlayer = nullptr;
|
||||
|
||||
|
@ -8468,7 +8533,7 @@ bool OnosCombatThink(AvHAIPlayer* pBot)
|
|||
return true;
|
||||
}
|
||||
|
||||
void DEBUG_PrintTaskInfo(AvHAIPlayer* pBot)
|
||||
void DEBUG_PrintTaskInfo(edict_t* OutputPlayer, AvHAIPlayer* pBot)
|
||||
{
|
||||
char buf[511];
|
||||
char interbuf[164];
|
||||
|
@ -8516,19 +8581,19 @@ void DEBUG_PrintTaskInfo(AvHAIPlayer* pBot)
|
|||
|
||||
if (!FNullEnt(pBot->CurrentTask->TaskTarget))
|
||||
{
|
||||
UTIL_DrawLine(INDEXENT(1), pBot->Edict->v.origin, pBot->CurrentTask->TaskTarget->v.origin, 255, 0, 0);
|
||||
UTIL_DrawLine(OutputPlayer, pBot->Edict->v.origin, pBot->CurrentTask->TaskTarget->v.origin, 255, 0, 0);
|
||||
}
|
||||
|
||||
if (!vIsZero(pBot->CurrentTask->TaskLocation))
|
||||
{
|
||||
UTIL_DrawLine(INDEXENT(1), pBot->Edict->v.origin, pBot->CurrentTask->TaskLocation, 255, 255, 0);
|
||||
UTIL_DrawLine(OutputPlayer, pBot->Edict->v.origin, pBot->CurrentTask->TaskLocation, 255, 255, 0);
|
||||
}
|
||||
}
|
||||
|
||||
UTIL_DrawHUDText(INDEXENT(1), 0, 0.1f, 0.1f, 255, 255, 255, buf);
|
||||
UTIL_DrawHUDText(OutputPlayer, 0, 0.1, 0.1f, 255, 255, 255, buf);
|
||||
}
|
||||
|
||||
void DEBUG_PrintCombatInfo(AvHAIPlayer* pBot)
|
||||
void DEBUG_PrintCombatInfo(edict_t* OutputPlayer, AvHAIPlayer* pBot)
|
||||
{
|
||||
char buf[511];
|
||||
char interbuf[164];
|
||||
|
@ -8550,7 +8615,7 @@ void DEBUG_PrintCombatInfo(AvHAIPlayer* pBot)
|
|||
|
||||
if (TrackedEnemy < 0)
|
||||
{
|
||||
UTIL_DrawHUDText(INDEXENT(1), 1, 0.6f, 0.1f, 255, 255, 255, buf);
|
||||
UTIL_DrawHUDText(OutputPlayer, 1, 0.6f, 0.1f, 255, 255, 255, buf);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -8606,11 +8671,23 @@ void DEBUG_PrintCombatInfo(AvHAIPlayer* pBot)
|
|||
|
||||
strcat(buf, interbuf);
|
||||
|
||||
UTIL_DrawHUDText(INDEXENT(1), 1, 0.6f, 0.1f, 255, 255, 255, buf);
|
||||
UTIL_DrawHUDText(OutputPlayer, 1, 0.6f, 0.1f, 255, 255, 255, buf);
|
||||
|
||||
if (!vIsZero(TrackedInfo->LastDetectedLocation))
|
||||
{
|
||||
UTIL_DrawLine(INDEXENT(1), pBot->Edict->v.origin, TrackedInfo->LastDetectedLocation, 255, 0, 0);
|
||||
UTIL_DrawLine(OutputPlayer, pBot->Edict->v.origin, TrackedInfo->LastDetectedLocation, 255, 0, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void DEBUG_PrintBotDebugInfo(edict_t* OutputPlayer, AvHAIPlayer* pBot)
|
||||
{
|
||||
if (FNullEnt(OutputPlayer) || OutputPlayer->free) { return; }
|
||||
|
||||
bool bBreak = true; // Add a break point here if you want to debug a specific bot
|
||||
|
||||
AIDEBUG_DrawBotPath(OutputPlayer, pBot);
|
||||
|
||||
DEBUG_PrintTaskInfo(OutputPlayer, pBot);
|
||||
DEBUG_PrintCombatInfo(OutputPlayer, pBot);
|
||||
}
|
|
@ -184,7 +184,8 @@ bool OnosCombatThink(AvHAIPlayer* pBot);
|
|||
bool BombardierCombatThink(AvHAIPlayer* pBot);
|
||||
bool RegularMarineCombatThink(AvHAIPlayer* pBot);
|
||||
|
||||
void DEBUG_PrintTaskInfo(AvHAIPlayer* pBot);
|
||||
void DEBUG_PrintCombatInfo(AvHAIPlayer* pBot);
|
||||
void DEBUG_PrintBotDebugInfo(edict_t* OutputPlayer, AvHAIPlayer* pBot);
|
||||
void DEBUG_PrintTaskInfo(edict_t* OutputPlayer, AvHAIPlayer* pBot);
|
||||
void DEBUG_PrintCombatInfo(edict_t* OutputPlayer, AvHAIPlayer* pBot);
|
||||
|
||||
#endif
|
|
@ -54,6 +54,10 @@ bool bBotsEnabled = false;
|
|||
|
||||
float CurrentFrameDelta = 0.01f;
|
||||
|
||||
#ifdef BOTDEBUG
|
||||
edict_t* DebugBots[MAX_PLAYERS];
|
||||
#endif
|
||||
|
||||
AvHAICommanderMode AIMGR_GetCommanderMode()
|
||||
{
|
||||
if (avh_botcommandermode.value == 1)
|
||||
|
@ -599,6 +603,7 @@ void AIMGR_UpdateAIPlayers()
|
|||
}
|
||||
|
||||
AIMGR_ProcessPendingSounds();
|
||||
AITAC_UpdateSquads();
|
||||
}
|
||||
|
||||
int NumCommanders = AIMGR_GetNumAICommanders();
|
||||
|
@ -889,7 +894,11 @@ void AIMGR_ResetRound()
|
|||
{
|
||||
if (!AIMGR_IsBotEnabled()) { return; } // Do nothing if we're not using bots, as the data will be cleared out via AIMGR_OnBotDisabled()
|
||||
|
||||
AITAC_ClearMapAIData(false);
|
||||
AITAC_ClearMapAIData(false);
|
||||
|
||||
#ifdef BOTDEBUG
|
||||
memset(DebugBots, 0, sizeof(DebugBots));
|
||||
#endif
|
||||
|
||||
// AI Players would be 0 if the round is being reset because a new game is starting. If the round is reset
|
||||
// from a console command, or tournament mode readying up etc, then bot logic is unaffected
|
||||
|
@ -1084,6 +1093,16 @@ AvHAIPlayer* AIMGR_GetBotRefFromPlayer(AvHPlayer* PlayerRef)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
AvHAIPlayer* AIMGR_GetBotRefFromEdict(edict_t* PlayerEdict)
|
||||
{
|
||||
for (auto BotIt = ActiveAIPlayers.begin(); BotIt != ActiveAIPlayers.end(); BotIt++)
|
||||
{
|
||||
if (BotIt->Edict == PlayerEdict) { return &(*BotIt); }
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AvHTeamNumber AIMGR_GetEnemyTeam(const AvHTeamNumber FriendlyTeam)
|
||||
{
|
||||
AvHTeamNumber TeamANumber = GetGameRules()->GetTeamANumber();
|
||||
|
@ -1259,11 +1278,14 @@ AvHAIPlayer* AIMGR_GetDebugAIPlayer()
|
|||
return DebugAIPlayer;
|
||||
}
|
||||
|
||||
void AIMGR_SetDebugAIPlayer(edict_t* AIPlayer)
|
||||
void AIMGR_SetDebugAIPlayer(edict_t* SpectatingPlayer, edict_t* AIPlayer)
|
||||
{
|
||||
#ifdef BOTDEBUG
|
||||
int PlayerIndex = ENTINDEX(SpectatingPlayer) - 1;
|
||||
|
||||
if (FNullEnt(AIPlayer))
|
||||
{
|
||||
DebugAIPlayer = nullptr;
|
||||
DebugBots[PlayerIndex] = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1271,12 +1293,13 @@ void AIMGR_SetDebugAIPlayer(edict_t* AIPlayer)
|
|||
{
|
||||
if (it->Edict == AIPlayer)
|
||||
{
|
||||
DebugAIPlayer = &(*it);
|
||||
DebugBots[PlayerIndex] = it->Edict;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
DebugAIPlayer = nullptr;
|
||||
DebugBots[PlayerIndex] = nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
void AIMGR_ReceiveCommanderRequest(AvHTeamNumber Team, edict_t* Requestor, const char* Request)
|
||||
|
|
|
@ -86,6 +86,7 @@ void AIMGR_ReloadNavigationData();
|
|||
AvHAIPlayer* AIMGR_GetAICommander(AvHTeamNumber Team);
|
||||
|
||||
AvHAIPlayer* AIMGR_GetBotRefFromPlayer(AvHPlayer* PlayerRef);
|
||||
AvHAIPlayer* AIMGR_GetBotRefFromEdict(edict_t* PlayerEdict);
|
||||
|
||||
AvHTeamNumber AIMGR_GetEnemyTeam(const AvHTeamNumber FriendlyTeam);
|
||||
AvHClassType AIMGR_GetEnemyTeamType(const AvHTeamNumber FriendlyTeam);
|
||||
|
@ -108,7 +109,7 @@ vector<AvHPlayer*> AIMGR_GetNonAIPlayersOnTeam(AvHTeamNumber Team);
|
|||
void AIMGR_ClearBotData();
|
||||
|
||||
AvHAIPlayer* AIMGR_GetDebugAIPlayer();
|
||||
void AIMGR_SetDebugAIPlayer(edict_t* AIPlayer);
|
||||
void AIMGR_SetDebugAIPlayer(edict_t* SpectatingPlayer, edict_t* AIPlayer);
|
||||
|
||||
void AIMGR_ReceiveCommanderRequest(AvHTeamNumber Team, edict_t* Requestor, const char* Request);
|
||||
|
||||
|
|
|
@ -78,6 +78,8 @@ bool IsPlayerInReadyRoom(const edict_t* Player)
|
|||
|
||||
bool IsPlayerActiveInGame(const edict_t* Player)
|
||||
{
|
||||
if (FNullEnt(Player)) { return false; }
|
||||
|
||||
return !IsPlayerInReadyRoom(Player) && Player->v.team != 0 && !IsPlayerSpectator(Player) && !IsPlayerDead(Player) && !IsPlayerBeingDigested(Player) && !IsPlayerCommander(Player);
|
||||
}
|
||||
|
||||
|
|
|
@ -66,6 +66,8 @@ edict_t* LastSeenLerkTeamB = nullptr; // Track who went lerk on team B last time
|
|||
float LastSeenLerkTeamATime = 0.0f;
|
||||
float LastSeenLerkTeamBTime = 0.0f;
|
||||
|
||||
vector<AvHAISquad> ActiveSquads;
|
||||
|
||||
std::vector<AvHAIBuildableStructure> AITAC_FindAllDeployables(const Vector& Location, const DeployableSearchFilter* Filter)
|
||||
{
|
||||
std::vector<AvHAIBuildableStructure> Result;
|
||||
|
@ -2562,7 +2564,7 @@ void AITAC_OnStructureCreated(AvHAIBuildableStructure* NewStructure)
|
|||
{
|
||||
NavHint* ThisHint = (*it);
|
||||
|
||||
if (vDist2DSq(NewStructure->edict->v.origin, ThisHint->Position) < sqrf(32.0f) && fabsf(NewStructure->Location.z - ThisHint->Position.z) < 50.0f)
|
||||
if (vDist2DSq(NewStructure->edict->v.origin, ThisHint->Position) < sqrf(64.0f) && fabsf(NewStructure->Location.z - ThisHint->Position.z) < 50.0f)
|
||||
{
|
||||
ThisHint->OccupyingBuilding = NewStructure->edict;
|
||||
}
|
||||
|
@ -2802,6 +2804,8 @@ void AITAC_ClearMapAIData(bool bInitialMapLoad)
|
|||
Hives.clear();
|
||||
}
|
||||
|
||||
AITAC_ClearSquads();
|
||||
|
||||
MarineDroppedItemMap.clear();
|
||||
TeamAStructureMap.clear();
|
||||
TeamBStructureMap.clear();
|
||||
|
@ -4266,6 +4270,27 @@ bool AITAC_ShouldBotBeCautious(AvHAIPlayer* pBot)
|
|||
|
||||
int NumEnemiesAtDestination = AITAC_GetNumPlayersOnTeamWithLOS(EnemyTeam, CurrentPathNode.Location, UTIL_MetresToGoldSrcUnits(50.0f), pBot->Edict);
|
||||
|
||||
if (NumEnemiesAtDestination <= 1)
|
||||
{
|
||||
DeployableSearchFilter TurretFilter;
|
||||
TurretFilter.DeployableTeam = EnemyTeam;
|
||||
TurretFilter.DeployableTypes = (STRUCTURE_MARINE_TURRET | STRUCTURE_ALIEN_OFFENCECHAMBER);
|
||||
TurretFilter.IncludeStatusFlags = STRUCTURE_STATUS_COMPLETED;
|
||||
TurretFilter.ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING;
|
||||
TurretFilter.MaxSearchRadius = BALANCE_VAR(kTurretRange);
|
||||
|
||||
vector<AvHAIBuildableStructure> Turrets = AITAC_FindAllDeployables(CurrentPathNode.Location, &TurretFilter);
|
||||
|
||||
for (auto it = Turrets.begin(); it != Turrets.end(); it++)
|
||||
{
|
||||
if (UTIL_QuickTrace(pBot->Edict, GetPlayerTopOfCollisionHull(it->edict), CurrentPathNode.Location))
|
||||
{
|
||||
NumEnemiesAtDestination++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (NumEnemiesAtDestination > 1)
|
||||
{
|
||||
return (vDist2DSq(pBot->Edict->v.origin, CurrentPathNode.Location) < sqrf(UTIL_MetresToGoldSrcUnits(5.0f)));
|
||||
|
@ -5403,4 +5428,200 @@ Vector AITAC_GetRandomBuildHintInLocation(const unsigned int StructureType, cons
|
|||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
bool AITAC_IsBotPursuingSquadObjective(AvHAIPlayer* pBot, AvHAISquad* Squad)
|
||||
{
|
||||
// Bot is dead, no longer playing, or otherwise incapacitated
|
||||
if (!IsPlayerActiveInGame(pBot->Edict) || pBot->Player->GetTeam() != Squad->SquadTeam) { return false; }
|
||||
|
||||
// Bot no longer has this squad's objective as its primary task
|
||||
if (pBot->PrimaryBotTask.TaskType != Squad->SquadObjective || pBot->PrimaryBotTask.TaskTarget != Squad->SquadTarget) { return false; }
|
||||
|
||||
// Bot is focused on the job at hand
|
||||
if (!pBot->CurrentTask || pBot->CurrentTask == &pBot->PrimaryBotTask) { return true; }
|
||||
|
||||
// Bot isn't currently pursuing squad objective, so check if it's doing something in the vicinity
|
||||
Vector TaskLocation = (!FNullEnt(pBot->CurrentTask->TaskTarget)) ? pBot->CurrentTask->TaskTarget->v.origin : pBot->CurrentTask->TaskLocation;
|
||||
|
||||
return vDist2DSq(TaskLocation, Squad->SquadTarget->v.origin) < sqrf(UTIL_MetresToGoldSrcUnits(10.0f));
|
||||
}
|
||||
|
||||
void AITAC_ManageSquads()
|
||||
{
|
||||
for (auto it = ActiveSquads.begin(); it != ActiveSquads.end();)
|
||||
{
|
||||
for (auto pIt = it->SquadMembers.begin(); pIt != it->SquadMembers.end();)
|
||||
{
|
||||
AvHAIPlayer* ThisPlayer = (*pIt);
|
||||
if (!AITAC_IsBotPursuingSquadObjective(ThisPlayer, &(*it)))
|
||||
{
|
||||
pIt = it->SquadMembers.erase(pIt);
|
||||
}
|
||||
else
|
||||
{
|
||||
pIt++;
|
||||
}
|
||||
}
|
||||
|
||||
if (it->SquadMembers.size() == 0)
|
||||
{
|
||||
it = ActiveSquads.erase(it);
|
||||
}
|
||||
else
|
||||
{
|
||||
it++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AITAC_UpdateSquads()
|
||||
{
|
||||
AITAC_ManageSquads();
|
||||
|
||||
for (auto it = ActiveSquads.begin(); it != ActiveSquads.end(); it++)
|
||||
{
|
||||
if (it->SquadMembers.size() > 1)
|
||||
{
|
||||
if (vIsZero(it->SquadGatherLocation))
|
||||
{
|
||||
vector<bot_path_node> TravelPath;
|
||||
|
||||
dtStatus PathFindResult = FindPathClosestToPoint(GetBaseNavProfile(ONOS_BASE_NAV_PROFILE), AITAC_GetTeamStartingLocation(it->SquadTeam), UTIL_GetEntityGroundLocation(it->SquadTarget), TravelPath, UTIL_MetresToGoldSrcUnits(20.0f));
|
||||
|
||||
if (dtStatusSucceed(PathFindResult))
|
||||
{
|
||||
for (auto pIt = TravelPath.rbegin(); pIt != TravelPath.rend(); pIt++)
|
||||
{
|
||||
if (pIt->area != SAMPLE_POLYAREA_GROUND || pIt->flag != SAMPLE_POLYFLAGS_WALK) { continue; }
|
||||
|
||||
if (UTIL_QuickTrace(nullptr, pIt->Location, it->SquadTarget->v.origin)) { continue; }
|
||||
|
||||
if (vDist2DSq(pIt->Location, it->SquadTarget->v.origin) > sqrf(UTIL_MetresToGoldSrcUnits(20.0f)))
|
||||
{
|
||||
DeployableSearchFilter EnemyStuff;
|
||||
EnemyStuff.DeployableTeam = AIMGR_GetEnemyTeam(it->SquadTeam);
|
||||
EnemyStuff.ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING;
|
||||
EnemyStuff.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(5.0f);
|
||||
|
||||
if (AITAC_DeployableExistsAtLocation(pIt->Location, &EnemyStuff))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
it->SquadGatherLocation = pIt->Location;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
it->SquadGatherLocation = ZERO_VECTOR;
|
||||
}
|
||||
|
||||
if (!it->bExecuteObjective && !vIsZero(it->SquadGatherLocation))
|
||||
{
|
||||
bool bAllHaveGathered = true;
|
||||
|
||||
for (auto playerIt = it->SquadMembers.begin(); playerIt != it->SquadMembers.end(); playerIt++)
|
||||
{
|
||||
AvHAIPlayer* ThisBot = (*playerIt);
|
||||
|
||||
if (vDist2DSq(ThisBot->Edict->v.origin, it->SquadGatherLocation) > sqrf(UTIL_MetresToGoldSrcUnits(5.0f)))
|
||||
{
|
||||
bAllHaveGathered = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (bAllHaveGathered)
|
||||
{
|
||||
it->bExecuteObjective = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AvHAISquad* AITAC_GetSquadForObjective(AvHAIPlayer* pBot, edict_t* TaskTarget, BotTaskType ObjectiveType)
|
||||
{
|
||||
AvHAISquad* JoinSquad = nullptr;
|
||||
|
||||
for (auto it = ActiveSquads.begin(); it != ActiveSquads.end(); it++)
|
||||
{
|
||||
if (it->SquadTeam == pBot->Player->GetTeam() && it->SquadTarget == TaskTarget && it->SquadObjective == ObjectiveType)
|
||||
{
|
||||
auto element = std::find(it->SquadMembers.begin(), it->SquadMembers.end(), pBot);
|
||||
|
||||
if (element != it->SquadMembers.end())
|
||||
{
|
||||
return &(*it);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!JoinSquad && !it->bExecuteObjective)
|
||||
{
|
||||
JoinSquad = &(*it);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (JoinSquad)
|
||||
{
|
||||
JoinSquad->SquadMembers.push_back(pBot);
|
||||
return JoinSquad;
|
||||
}
|
||||
|
||||
AvHAISquad NewSquad;
|
||||
NewSquad.SquadTeam = pBot->Player->GetTeam();
|
||||
NewSquad.SquadTarget = TaskTarget;
|
||||
NewSquad.SquadObjective = ObjectiveType;
|
||||
NewSquad.bExecuteObjective = false;
|
||||
NewSquad.SquadGatherLocation = ZERO_VECTOR;
|
||||
|
||||
ActiveSquads.push_back(NewSquad);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void AITAC_ClearSquads()
|
||||
{
|
||||
ActiveSquads.clear();
|
||||
}
|
||||
|
||||
Vector AITAC_GetGatherLocationForSquad(AvHAISquad* Squad)
|
||||
{
|
||||
if (!Squad || FNullEnt(Squad->SquadTarget)) { return ZERO_VECTOR; }
|
||||
|
||||
vector<bot_path_node> TravelPath;
|
||||
|
||||
dtStatus PathFindResult = FindPathClosestToPoint(GetBaseNavProfile(ONOS_BASE_NAV_PROFILE), AITAC_GetTeamStartingLocation(Squad->SquadTeam), UTIL_GetEntityGroundLocation(Squad->SquadTarget), TravelPath, UTIL_MetresToGoldSrcUnits(20.0f));
|
||||
|
||||
if (dtStatusSucceed(PathFindResult))
|
||||
{
|
||||
for (auto pIt = TravelPath.rend(); pIt != TravelPath.rbegin(); pIt++)
|
||||
{
|
||||
if (pIt->area != SAMPLE_POLYAREA_GROUND || pIt->flag != SAMPLE_POLYFLAGS_WALK) { continue; }
|
||||
|
||||
if (UTIL_QuickTrace(nullptr, pIt->Location, Squad->SquadTarget->v.origin)) { continue; }
|
||||
|
||||
if (vDist2DSq(pIt->Location, Squad->SquadTarget->v.origin) > sqrf(UTIL_MetresToGoldSrcUnits(20.0f)))
|
||||
{
|
||||
DeployableSearchFilter EnemyStuff;
|
||||
EnemyStuff.DeployableTeam = AIMGR_GetEnemyTeam(Squad->SquadTeam);
|
||||
EnemyStuff.ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING;
|
||||
EnemyStuff.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(5.0f);
|
||||
|
||||
if (AITAC_DeployableExistsAtLocation(pIt->Location, &EnemyStuff))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
return pIt->Location;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ZERO_VECTOR;
|
||||
}
|
|
@ -204,4 +204,10 @@ edict_t* AITAC_GetLastSeenLerkForTeam(AvHTeamNumber Team, float& LastSeenTime);
|
|||
bool AITAC_IsCompletedStructureOfTypeNearLocation(AvHTeamNumber Team, unsigned int StructureType, Vector SearchLocation, float SearchRadius);
|
||||
bool AITAC_IsStructureOfTypeNearLocation(AvHTeamNumber Team, unsigned int StructureType, Vector SearchLocation, float SearchRadius);
|
||||
|
||||
void AITAC_UpdateSquads();
|
||||
void AITAC_ManageSquads();
|
||||
void AITAC_ClearSquads();
|
||||
AvHAISquad* AITAC_GetSquadForObjective(AvHAIPlayer* pBot, edict_t* TaskTarget, BotTaskType ObjectiveType);
|
||||
Vector AITAC_GetGatherLocationForSquad(AvHAISquad* Squad);
|
||||
|
||||
#endif
|
|
@ -392,9 +392,11 @@ bool AITASK_IsTaskStillValid(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
|
|||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
return AITASK_IsAlienSecureHiveTaskStillValid(pBot, Task);
|
||||
}
|
||||
}
|
||||
case TASK_ATTACK_BASE:
|
||||
return true;
|
||||
case TASK_DEFEND:
|
||||
return AITASK_IsDefendTaskStillValid(pBot, Task);
|
||||
case TASK_WELD:
|
||||
|
@ -937,6 +939,28 @@ bool AITASK_IsReinforceStructureTaskStillValid(AvHAIPlayer* pBot, AvHAIPlayerTas
|
|||
return AITAC_DeployableExistsAtLocation(Task->TaskTarget->v.origin, &EnemyStuff);
|
||||
}
|
||||
|
||||
bool AITASK_IsAlienSecureHiveTaskStillValid(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
|
||||
{
|
||||
if (!Task || FNullEnt(Task->TaskTarget) || !IsPlayerAlien(pBot->Edict)) { return false; }
|
||||
|
||||
AvHAIHiveDefinition* HiveToSecure = AITAC_GetHiveFromEdict(Task->TaskTarget);
|
||||
|
||||
if (!HiveToSecure) { return false; }
|
||||
|
||||
if (HiveToSecure->Status != HIVE_STATUS_UNBUILT && HiveToSecure->OwningTeam != pBot->Player->GetTeam()) { return true; }
|
||||
|
||||
AvHTeamNumber BotTeam = pBot->Player->GetTeam();
|
||||
|
||||
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(15.0f);
|
||||
|
||||
return AITAC_DeployableExistsAtLocation(HiveToSecure->FloorLocation, &EnemyStuff);
|
||||
}
|
||||
|
||||
bool AITASK_IsMarineSecureHiveTaskStillValid(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
|
||||
{
|
||||
if (!Task || FNullEnt(Task->TaskTarget) || IsPlayerAlien(pBot->Edict)) { return false; }
|
||||
|
@ -2530,6 +2554,10 @@ void BotProgressTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
|
|||
{
|
||||
MarineProgressSecureHiveTask(pBot, Task);
|
||||
}
|
||||
else
|
||||
{
|
||||
AlienProgressSecureHiveTask(pBot, Task);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -2617,6 +2645,121 @@ void BotProgressWeldTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
|
|||
return;
|
||||
}
|
||||
|
||||
void AlienProgressSecureHiveTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
|
||||
{
|
||||
const AvHAIHiveDefinition* Hive = AITAC_GetHiveFromEdict(Task->TaskTarget);
|
||||
|
||||
if (!Hive) { return; }
|
||||
|
||||
AvHAISquad* ActiveSquad = AITAC_GetSquadForObjective(pBot, Task->TaskTarget, Task->TaskType);
|
||||
|
||||
if (ActiveSquad && !ActiveSquad->bExecuteObjective && !vIsZero(ActiveSquad->SquadGatherLocation))
|
||||
{
|
||||
BotGuardLocation(pBot, ActiveSquad->SquadGatherLocation);
|
||||
return;
|
||||
}
|
||||
|
||||
AvHTeamNumber BotTeam = pBot->Player->GetTeam();
|
||||
AvHTeamNumber EnemyTeam = AIMGR_GetEnemyTeam(BotTeam);
|
||||
|
||||
bool bEnemyIsMarines = AIMGR_GetTeamType(EnemyTeam) == AVH_CLASS_TYPE_MARINE;
|
||||
// Don't prioritise electrified structures if we're skulk or lerk
|
||||
bool bAvoidElectrified = (pBot->Player->GetUser3() == AVH_USER3_ALIEN_PLAYER1 || pBot->Player->GetUser3() == AVH_USER3_ALIEN_PLAYER3);
|
||||
|
||||
DeployableSearchFilter EnemyStuffFilter;
|
||||
EnemyStuffFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(15.0f);
|
||||
EnemyStuffFilter.DeployableTeam = EnemyTeam;
|
||||
EnemyStuffFilter.ReachabilityTeam = BotTeam;
|
||||
EnemyStuffFilter.ReachabilityFlags = pBot->BotNavInfo.NavProfile.ReachabilityFlag;
|
||||
EnemyStuffFilter.ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING;
|
||||
|
||||
if (bEnemyIsMarines)
|
||||
{
|
||||
EnemyStuffFilter.DeployableTypes = STRUCTURE_MARINE_PHASEGATE;
|
||||
|
||||
AvHAIBuildableStructure PhaseGate = AITAC_FindClosestDeployableToLocation(Hive->FloorLocation, &EnemyStuffFilter);
|
||||
|
||||
if (PhaseGate.IsValid())
|
||||
{
|
||||
if (bAvoidElectrified)
|
||||
{
|
||||
EnemyStuffFilter.DeployableTypes = SEARCH_ALL_STRUCTURES;
|
||||
EnemyStuffFilter.IncludeStatusFlags = STRUCTURE_STATUS_ELECTRIFIED;
|
||||
EnemyStuffFilter.MaxSearchRadius = BALANCE_VAR(kElectricalRange);
|
||||
|
||||
AvHAIBuildableStructure ElectrifiedStructure = AITAC_FindClosestDeployableToLocation(PhaseGate.Location, &EnemyStuffFilter);
|
||||
|
||||
if (ElectrifiedStructure.IsValid())
|
||||
{
|
||||
BotAlienAttackNonPlayerTarget(pBot, ElectrifiedStructure.edict);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
BotAlienAttackNonPlayerTarget(pBot, PhaseGate.edict);
|
||||
return;
|
||||
}
|
||||
|
||||
EnemyStuffFilter.DeployableTypes = (STRUCTURE_MARINE_TURRETFACTORY | STRUCTURE_MARINE_ADVTURRETFACTORY);
|
||||
EnemyStuffFilter.IncludeStatusFlags = STRUCTURE_STATUS_NONE;
|
||||
EnemyStuffFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(15.0f);
|
||||
|
||||
AvHAIBuildableStructure TF = AITAC_FindClosestDeployableToLocation(Hive->FloorLocation, &EnemyStuffFilter);
|
||||
|
||||
if (TF.IsValid())
|
||||
{
|
||||
BotAlienAttackNonPlayerTarget(pBot, TF.edict);
|
||||
return;
|
||||
}
|
||||
|
||||
EnemyStuffFilter.DeployableTypes = SEARCH_ALL_STRUCTURES;
|
||||
|
||||
AvHAIBuildableStructure EnemyStructure = AITAC_FindClosestDeployableToLocation(Hive->FloorLocation, &EnemyStuffFilter);
|
||||
|
||||
if (EnemyStructure.IsValid())
|
||||
{
|
||||
BotAlienAttackNonPlayerTarget(pBot, EnemyStructure.edict);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
EnemyStuffFilter.DeployableTypes = STRUCTURE_ALIEN_OFFENCECHAMBER;
|
||||
|
||||
AvHAIBuildableStructure EnemyOC = AITAC_FindClosestDeployableToLocation(Hive->FloorLocation, &EnemyStuffFilter);
|
||||
|
||||
if (EnemyOC.IsValid())
|
||||
{
|
||||
BotAlienAttackNonPlayerTarget(pBot, EnemyOC.edict);
|
||||
return;
|
||||
}
|
||||
|
||||
if (Hive->Status == HIVE_STATUS_BUILT && Hive->OwningTeam != BotTeam)
|
||||
{
|
||||
BotAlienAttackNonPlayerTarget(pBot, Hive->HiveEdict);
|
||||
return;
|
||||
}
|
||||
|
||||
EnemyStuffFilter.DeployableTypes = SEARCH_ALL_STRUCTURES;
|
||||
|
||||
AvHAIBuildableStructure AnyEnemyStructure = AITAC_FindClosestDeployableToLocation(Hive->FloorLocation, &EnemyStuffFilter);
|
||||
|
||||
if (AnyEnemyStructure.IsValid())
|
||||
{
|
||||
BotAlienAttackNonPlayerTarget(pBot, AnyEnemyStructure.edict);
|
||||
return;
|
||||
}
|
||||
|
||||
if (Hive->Status != HIVE_STATUS_UNBUILT && Hive->OwningTeam != BotTeam)
|
||||
{
|
||||
BotAlienAttackNonPlayerTarget(pBot, Hive->HiveEdict);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
BotGuardLocation(pBot, Hive->FloorLocation);
|
||||
}
|
||||
|
||||
void MarineProgressSecureHiveTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
|
||||
{
|
||||
const AvHAIHiveDefinition* Hive = AITAC_GetHiveFromEdict(Task->TaskTarget);
|
||||
|
@ -2624,6 +2767,7 @@ void MarineProgressSecureHiveTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
|
|||
if (!Hive) { return; }
|
||||
|
||||
AvHTeamNumber BotTeam = pBot->Player->GetTeam();
|
||||
AvHTeamNumber EnemyTeam = AIMGR_GetEnemyTeam(BotTeam);
|
||||
|
||||
DeployableSearchFilter StructureFilter;
|
||||
StructureFilter.DeployableTypes = SEARCH_ALL_MARINE_STRUCTURES;
|
||||
|
@ -2703,7 +2847,7 @@ void MarineProgressSecureHiveTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
|
|||
DeployableSearchFilter EnemyStructures;
|
||||
EnemyStructures.DeployableTypes = SEARCH_ALL_STRUCTURES;
|
||||
EnemyStructures.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(15.0f);
|
||||
EnemyStructures.DeployableTeam = AIMGR_GetEnemyTeam(BotTeam);
|
||||
EnemyStructures.DeployableTeam = EnemyTeam;
|
||||
EnemyStructures.ReachabilityTeam = BotTeam;
|
||||
EnemyStructures.ReachabilityFlags = pBot->BotNavInfo.NavProfile.ReachabilityFlag;
|
||||
|
||||
|
@ -2927,7 +3071,6 @@ void AITASK_GenerateGuardWatchPoints(AvHAIPlayer* pBot, const Vector& GuardLocat
|
|||
|
||||
vector<bot_path_node> path;
|
||||
path.clear();
|
||||
|
||||
|
||||
vector<AvHAIHiveDefinition*> AllHives = AITAC_GetAllHives();
|
||||
|
||||
|
|
|
@ -45,6 +45,7 @@ bool AITASK_IsEvolveTaskStillValid(AvHAIPlayer* pBot, AvHAIPlayerTask* Task);
|
|||
|
||||
bool AITASK_IsReinforceStructureTaskStillValid(AvHAIPlayer* pBot, AvHAIPlayerTask* Task);
|
||||
bool AITASK_IsMarineSecureHiveTaskStillValid(AvHAIPlayer* pBot, AvHAIPlayerTask* Task);
|
||||
bool AITASK_IsAlienSecureHiveTaskStillValid(AvHAIPlayer* pBot, AvHAIPlayerTask* Task);
|
||||
|
||||
bool AITASK_IsAlienGetHealthTaskStillValid(AvHAIPlayer* pBot, AvHAIPlayerTask* Task);
|
||||
bool AITASK_IsAlienHealTaskStillValid(AvHAIPlayer* pBot, AvHAIPlayerTask* Task);
|
||||
|
@ -93,6 +94,9 @@ void AIPlayerBuildStructure(AvHAIPlayer* pBot, edict_t* BuildTarget);
|
|||
|
||||
void MarineProgressSecureHiveTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task);
|
||||
|
||||
// Clear all enemy structures
|
||||
void AlienProgressSecureHiveTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task);
|
||||
|
||||
void AlienProgressGetHealthTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task);
|
||||
void AlienProgressHealTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task);
|
||||
void AlienProgressBuildTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task);
|
||||
|
|
|
@ -1416,21 +1416,23 @@ BOOL AvHGamerules::ClientCommand( CBasePlayer *pPlayer, const char *pcmd )
|
|||
theSuccess = true;
|
||||
}
|
||||
}
|
||||
#ifdef BOTDEBUG
|
||||
else if (FStrEq(pcmd, "bot_setdebugaiplayer"))
|
||||
{
|
||||
CBaseEntity* SpectatedPlayer = theAvHPlayer->GetSpectatingEntity();
|
||||
|
||||
if (SpectatedPlayer)
|
||||
{
|
||||
AIMGR_SetDebugAIPlayer(SpectatedPlayer->edict());
|
||||
AIMGR_SetDebugAIPlayer(theAvHPlayer->edict(), SpectatedPlayer->edict());
|
||||
}
|
||||
else
|
||||
{
|
||||
AIMGR_SetDebugAIPlayer(nullptr);
|
||||
AIMGR_SetDebugAIPlayer(theAvHPlayer->edict(), nullptr);
|
||||
}
|
||||
|
||||
theSuccess = true;
|
||||
}
|
||||
#endif
|
||||
else if (FStrEq(pcmd, "bot_cometome"))
|
||||
{
|
||||
vector<AvHAIPlayer*> AIPlayers = AIMGR_GetAllAIPlayers();
|
||||
|
|
Loading…
Reference in a new issue