From 09a8827693876e88280dde6d8169be90089bcdf2 Mon Sep 17 00:00:00 2001 From: RGreenlees Date: Sun, 18 Feb 2024 20:52:22 +0000 Subject: [PATCH] Add commander beacon back in --- main/source/mod/AIPlayers/AvHAICommander.cpp | 105 ++++++++++++++---- main/source/mod/AIPlayers/AvHAICommander.h | 2 +- main/source/mod/AIPlayers/AvHAIPlayer.cpp | 24 +++- .../mod/AIPlayers/AvHAIPlayerManager.cpp | 2 +- 4 files changed, 107 insertions(+), 26 deletions(-) diff --git a/main/source/mod/AIPlayers/AvHAICommander.cpp b/main/source/mod/AIPlayers/AvHAICommander.cpp index cc1b289e..ed750468 100644 --- a/main/source/mod/AIPlayers/AvHAICommander.cpp +++ b/main/source/mod/AIPlayers/AvHAICommander.cpp @@ -588,29 +588,6 @@ void AICOMM_UpdatePlayerOrders(AvHAIPlayer* pBot) } } - DeployableSearchFilter ResNodeFilter; - ResNodeFilter.DeployableTeam = TEAM_IND; - ResNodeFilter.ReachabilityTeam = pBot->Player->GetTeam(); - ResNodeFilter.ReachabilityFlags = AI_REACHABILITY_MARINE; - - const AvHAIResourceNode* ResNode = AITAC_FindNearestResourceNodeToLocation(AITAC_GetCommChairLocation(pBot->Player->GetTeam()), &ResNodeFilter); - - if (ResNode) - { - int NumAssignedPlayers = AICOMM_GetNumPlayersAssignedToOrder(pBot, ResNode->ResourceEntity->edict(), ORDERPURPOSE_SECURE_RESNODE); - - if (NumAssignedPlayers < 1) - { - edict_t* NewAssignee = AICOMM_GetPlayerWithNoOrderNearestLocation(pBot, ResNode->Location); - - if (!FNullEnt(NewAssignee)) - { - AICOMM_AssignNewPlayerOrder(pBot, NewAssignee, ResNode->ResourceEntity->edict(), ORDERPURPOSE_SECURE_RESNODE); - } - } - } - - } edict_t* AICOMM_GetPlayerWithNoOrderNearestLocation(AvHAIPlayer* pBot, Vector SearchLocation) @@ -2344,6 +2321,14 @@ void AICOMM_ClearAction(commander_action* Action) void AICOMM_CommanderThink(AvHAIPlayer* pBot) { + if (IsPlayerCommander(pBot->Edict)) + { + if (AICOMM_ShouldBeacon(pBot)) + { + return; + } + } + // Thanks to EterniumDev (Alien) for the suggestion to have the commander jump out and build if nobody is around to help if (AICOMM_ShouldCommanderLeaveChair(pBot)) { @@ -2586,4 +2571,78 @@ bool AICOMM_IsHiveFullySecured(AvHAIPlayer* CommanderBot, const AvHAIHiveDefinit bool bSecuredResNode = (!ResNode || (ResNode->bIsOccupied && ResNode->OwningTeam == CommanderTeam && UTIL_StructureIsFullyBuilt(ResNode->ActiveTowerEntity))); return ((!bPhaseGatesAvailable || bHasPhaseGate) && bHasTurretFactory && (!bIncludeElectrical || bTurretFactoryElectrified) && NumTurrets >= 5 && bSecuredResNode); +} + +bool AICOMM_ShouldBeacon(AvHAIPlayer* pBot) +{ + if (pBot->Player->GetResources() < BALANCE_VAR(kDistressBeaconCost)) { return false; } + + AvHTeamNumber BotTeam = pBot->Player->GetTeam(); + + DeployableSearchFilter ObservatoryFilter; + ObservatoryFilter.DeployableTypes = STRUCTURE_MARINE_OBSERVATORY; + ObservatoryFilter.DeployableTeam = BotTeam; + ObservatoryFilter.IncludeStatusFlags = STRUCTURE_STATUS_COMPLETED; + ObservatoryFilter.ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING; + + AvHAIBuildableStructure* Observatory = AITAC_FindClosestDeployableToLocation(ZERO_VECTOR, &ObservatoryFilter); + + if (!Observatory || Observatory->StructureStatusFlags == STRUCTURE_STATUS_RESEARCHING) { return false; } + + AvHTeamNumber EnemyTeam = AIMGR_GetEnemyTeam(BotTeam); + + Vector BaseLocation = AITAC_GetTeamStartingLocation(BotTeam); + + DeployableSearchFilter BaseStructureFilter; + BaseStructureFilter.DeployableTypes = (STRUCTURE_MARINE_INFANTRYPORTAL | STRUCTURE_MARINE_COMMCHAIR); + BaseStructureFilter.DeployableTeam = BotTeam; + BaseStructureFilter.IncludeStatusFlags = STRUCTURE_STATUS_COMPLETED; + BaseStructureFilter.ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING; + + vector BaseStructures = AITAC_FindAllDeployables(BaseLocation, &BaseStructureFilter); + + bool bHasInfantryPortals = false; + bool bBaseUnderAttack = false; + + for (auto it = BaseStructures.begin(); it != BaseStructures.end(); it++) + { + AvHAIBuildableStructure* ThisStructure = (*it); + + if (ThisStructure->StructureStatusFlags & STRUCTURE_STATUS_UNDERATTACK) + { + bBaseUnderAttack = true; + } + + if (ThisStructure->StructureType == STRUCTURE_MARINE_INFANTRYPORTAL) + { + bHasInfantryPortals = true; + } + } + + if (!bBaseUnderAttack && bHasInfantryPortals) { return false; } + + int EnemyStrength = 0; + int DefenderStrength = AITAC_GetNumPlayersOfTeamInArea(BotTeam, BaseLocation, UTIL_MetresToGoldSrcUnits(10.0f), false, nullptr, AVH_USER3_COMMANDER_PLAYER); + + if (AIMGR_GetTeamType(EnemyTeam) == AVH_CLASS_TYPE_MARINE) + { + EnemyStrength = AITAC_GetNumPlayersOfTeamInArea(EnemyTeam, BaseLocation, UTIL_MetresToGoldSrcUnits(10.0f), false, nullptr, AVH_USER3_COMMANDER_PLAYER); + } + else + { + int NumSkulks = AITAC_GetNumPlayersOfTeamAndClassInArea(EnemyTeam, BaseLocation, UTIL_MetresToGoldSrcUnits(10.0f), false, nullptr, AVH_USER3_ALIEN_PLAYER1); + int NumFades = AITAC_GetNumPlayersOfTeamAndClassInArea(EnemyTeam, BaseLocation, UTIL_MetresToGoldSrcUnits(10.0f), false, nullptr, AVH_USER3_ALIEN_PLAYER4); + int NumOnos = AITAC_GetNumPlayersOfTeamAndClassInArea(EnemyTeam, BaseLocation, UTIL_MetresToGoldSrcUnits(10.0f), false, nullptr, AVH_USER3_ALIEN_PLAYER5); + + EnemyStrength = NumSkulks + (NumFades * 2) + (NumOnos * 2); + } + + if (EnemyStrength >= 3 && EnemyStrength >= DefenderStrength * 3) + { + return AICOMM_ResearchTech(pBot, Observatory, RESEARCH_DISTRESSBEACON); + } + + return false; + + } \ No newline at end of file diff --git a/main/source/mod/AIPlayers/AvHAICommander.h b/main/source/mod/AIPlayers/AvHAICommander.h index b263a58c..914fc155 100644 --- a/main/source/mod/AIPlayers/AvHAICommander.h +++ b/main/source/mod/AIPlayers/AvHAICommander.h @@ -67,6 +67,6 @@ const AvHAIResourceNode* AICOMM_GetNearestResourceNodeCapOpportunity(const AvHTe const AvHAIHiveDefinition* AICOMM_GetHiveSiegeOpportunityNearestLocation(AvHAIPlayer* CommanderBot, const Vector SearchLocation); bool AICOMM_ShouldCommanderPrioritiseNodes(AvHAIPlayer* pBot); - +bool AICOMM_ShouldBeacon(AvHAIPlayer* pBot); #endif // AVH_AI_COMMANDER_H \ No newline at end of file diff --git a/main/source/mod/AIPlayers/AvHAIPlayer.cpp b/main/source/mod/AIPlayers/AvHAIPlayer.cpp index 7c9c4dea..b9090db8 100644 --- a/main/source/mod/AIPlayers/AvHAIPlayer.cpp +++ b/main/source/mod/AIPlayers/AvHAIPlayer.cpp @@ -3391,6 +3391,7 @@ void AIPlayerSetWantsAndNeedsMarineTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task { vector NearbyPlayers = AITAC_GetAllPlayersOfTeamInArea(BotTeam, NearbyHA->Location, UTIL_MetresToGoldSrcUnits(5.0f), false, pBot->Edict, AVH_USER3_COMMANDER_PLAYER); bool bHumanNearby = false; + bool bHumanWaitingRespawn = false; for (auto it = NearbyPlayers.begin(); it != NearbyPlayers.end(); it++) { @@ -5435,7 +5436,28 @@ void AIPlayerSetWantsAndNeedsAlienTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) GetHealthThreshold = 0.4f; } } - + + // If we're a skulk and we're attacking something, don't bother going to get health. DEATH OR GLORY. + if (IsPlayerSkulk(pBot->Edict)) + { + if (pBot->PrimaryBotTask.TaskType == TASK_ATTACK) + { + if (pBot->PrimaryBotTask.bTaskIsUrgent || vDist2DSq(pBot->Edict->v.origin, pBot->PrimaryBotTask.TaskTarget->v.origin) <= sqrf(UTIL_MetresToGoldSrcUnits(5.0f))) + { + AITASK_ClearBotTask(pBot, Task); + return; + } + } + + if (pBot->SecondaryBotTask.TaskType == TASK_ATTACK) + { + if (pBot->SecondaryBotTask.bTaskIsUrgent || vDist2DSq(pBot->Edict->v.origin, pBot->SecondaryBotTask.TaskTarget->v.origin) <= sqrf(UTIL_MetresToGoldSrcUnits(5.0f))) + { + AITASK_ClearBotTask(pBot, Task); + return; + } + } + } if (CurrentHealth < GetHealthThreshold) { diff --git a/main/source/mod/AIPlayers/AvHAIPlayerManager.cpp b/main/source/mod/AIPlayers/AvHAIPlayerManager.cpp index 4efd4e9f..17aaa3f2 100644 --- a/main/source/mod/AIPlayers/AvHAIPlayerManager.cpp +++ b/main/source/mod/AIPlayers/AvHAIPlayerManager.cpp @@ -631,7 +631,7 @@ void AIMGR_UpdateAIPlayers() } else { - DroneThink(bot); + AIPlayerThink(bot); }