Start alien tactical decisioning

This commit is contained in:
RichardGreenlees 2024-01-12 16:31:30 +00:00 committed by pierow
parent 07f488af9a
commit d3e1d18e11
7 changed files with 150 additions and 36 deletions

View file

@ -1001,7 +1001,31 @@ void BotEvolveLifeform(AvHAIPlayer* pBot, Vector DesiredEvolveLocation, AvHMessa
return; return;
} }
float EvolveCost = 0.0f;
switch (TargetLifeform)
{
case ALIEN_LIFEFORM_TWO:
EvolveCost = BALANCE_VAR(kGorgeCost);
break;
case ALIEN_LIFEFORM_THREE:
EvolveCost = BALANCE_VAR(kLerkCost);
break;
case ALIEN_LIFEFORM_FOUR:
EvolveCost = BALANCE_VAR(kFadeCost);
break;
case ALIEN_LIFEFORM_FIVE:
EvolveCost = BALANCE_VAR(kOnosCost);
break;
default:
EvolveCost = 0.0f;
break;
}
if (pBot->Player->GetResources() >= EvolveCost)
{
pBot->Impulse = TargetLifeform; pBot->Impulse = TargetLifeform;
}
} }
void BotUpdateDesiredViewRotation(AvHAIPlayer* pBot) void BotUpdateDesiredViewRotation(AvHAIPlayer* pBot)
@ -1646,11 +1670,6 @@ void UpdateAIPlayerDMRole(AvHAIPlayer* pBot)
} }
void UpdateAIAlienPlayerNSRole(AvHAIPlayer* pBot)
{
}
bool ShouldAIPlayerTakeCommand(AvHAIPlayer* pBot) bool ShouldAIPlayerTakeCommand(AvHAIPlayer* pBot)
{ {
AvHAICommanderMode CurrentCommanderMode = AIMGR_GetCommanderMode(); AvHAICommanderMode CurrentCommanderMode = AIMGR_GetCommanderMode();
@ -1700,6 +1719,34 @@ bool ShouldAIPlayerTakeCommand(AvHAIPlayer* pBot)
return true; return true;
} }
void UpdateAIAlienPlayerNSRole(AvHAIPlayer* pBot)
{
AvHTeamNumber BotTeamNumber = pBot->Player->GetTeam();
if (BotTeamNumber == TEAM_IND)
{
SetNewAIPlayerRole(pBot, BOT_ROLE_NONE);
return;
}
// Don't switch roles if already fade/onos or those resources are potentially wasted
if (IsPlayerFade(pBot->Edict) || IsPlayerOnos(pBot->Edict))
{
SetNewAIPlayerRole(pBot, BOT_ROLE_ASSAULT);
return;
}
// Likewise for lerks
if (IsPlayerLerk(pBot->Edict))
{
SetNewAIPlayerRole(pBot, BOT_ROLE_HARASS);
return;
}
}
void UpdateAIMarinePlayerNSRole(AvHAIPlayer* pBot) void UpdateAIMarinePlayerNSRole(AvHAIPlayer* pBot)
{ {
AvHTeamNumber BotTeamNumber = pBot->Player->GetTeam(); AvHTeamNumber BotTeamNumber = pBot->Player->GetTeam();
@ -1857,11 +1904,6 @@ void AIPlayerNSMarineThink(AvHAIPlayer* pBot)
{ {
pBot->DesiredCombatWeapon = BotMarineChooseBestWeapon(pBot, nullptr); pBot->DesiredCombatWeapon = BotMarineChooseBestWeapon(pBot, nullptr);
} }
if (pBot->CommanderTask.TaskType != TASK_NONE)
{
UTIL_DrawLine(INDEXENT(1), pBot->Edict->v.origin, pBot->CommanderTask.TaskLocation);
}
} }
void AIPlayerSetPrimaryMarineTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) void AIPlayerSetPrimaryMarineTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)

View file

@ -142,6 +142,16 @@ void AIMGR_UpdateAIPlayerCounts()
return; return;
} }
int AIMGR_GetNumPlayersOnTeam(AvHTeamNumber Team)
{
AvHTeamNumber teamA = GetGameRules()->GetTeamANumber();
AvHTeamNumber teamB = GetGameRules()->GetTeamBNumber();
if (Team != teamA && Team != teamB) { return 0; }
return (Team == teamA) ? GetGameRules()->GetTeamAPlayerCount() : GetGameRules()->GetTeamBPlayerCount();
}
void AIMGR_UpdateTeamBalance() void AIMGR_UpdateTeamBalance()
{ {
AvHTeamNumber teamA = GetGameRules()->GetTeamANumber(); AvHTeamNumber teamA = GetGameRules()->GetTeamANumber();

View file

@ -38,7 +38,9 @@ void AIMGR_UpdateFillTeams();
vector<AvHPlayer*> AIMGR_GetAllPlayersOnTeam(AvHTeamNumber Team); vector<AvHPlayer*> AIMGR_GetAllPlayersOnTeam(AvHTeamNumber Team);
// How many AI players are in the game (does not include third-party bots like RCBot/Whichbot) // Convenient helper function to get total number of players (human and AI) on a team
int AIMGR_GetNumPlayersOnTeam(AvHTeamNumber Team);
// How many AI players are in the game (does NOT include third-party bots like RCBot/Whichbot)
int AIMGR_GetNumAIPlayers(); int AIMGR_GetNumAIPlayers();
// Returns true if an AI player is on the requested team (does NOT include third-party bots like RCBot/Whichbot) // Returns true if an AI player is on the requested team (does NOT include third-party bots like RCBot/Whichbot)
int AIMGR_AIPlayerExistsOnTeam(AvHTeamNumber Team); int AIMGR_AIPlayerExistsOnTeam(AvHTeamNumber Team);

View file

@ -14,6 +14,7 @@
#include "AvHAIHelper.h" #include "AvHAIHelper.h"
#include "AvHAIConstants.h" #include "AvHAIConstants.h"
#include "AvHAIPlayerManager.h" #include "AvHAIPlayerManager.h"
#include "AvHAIConfig.h"
#include "../AvHGamerules.h" #include "../AvHGamerules.h"
#include "../AvHServerUtil.h" #include "../AvHServerUtil.h"
@ -3300,3 +3301,55 @@ bool AITAC_AnyPlayerOnTeamWithLOS(AvHTeamNumber Team, const Vector& Location, fl
return false; return false;
} }
bool AITAC_IsAlienBuilderNeeded(AvHAIPlayer* pBot)
{
AvHTeamNumber BotTeam = pBot->Player->GetTeam();
AvHMessageID HiveTechOne = CONFIG_GetHiveTechAtIndex(0);
AvHMessageID HiveTechTwo = CONFIG_GetHiveTechAtIndex(1);
AvHMessageID HiveTechThree = CONFIG_GetHiveTechAtIndex(2);
AvHAIDeployableStructureType ChamberTypeOne = UTIL_GetChamberTypeForHiveTech(HiveTechOne);
AvHAIDeployableStructureType ChamberTypeTwo = UTIL_GetChamberTypeForHiveTech(HiveTechTwo);
AvHAIDeployableStructureType ChamberTypeThree = UTIL_GetChamberTypeForHiveTech(HiveTechThree);
DeployableSearchFilter StructureFilter;
StructureFilter.DeployableTeam = BotTeam;
int NumTeamPlayers = AIMGR_GetNumPlayersOnTeam(BotTeam);
int MaxBuilders = imini(2, (int)floorf((float)NumTeamPlayers * 0.5f));
int NumCurrentBuilders = AIMGR_GetNumAIPlayersWithRoleOnTeam(BotTeam, BOT_ROLE_BUILDER, pBot);
if (MaxBuilders == 0) { return false; }
// We have a hive without any associated chambers yet
if (AITAC_TeamHiveWithTechExists(BotTeam, MESSAGE_NULL))
{
return NumCurrentBuilders < MaxBuilders;
}
StructureFilter.DeployableTypes = ChamberTypeOne;
if (AITAC_TeamHiveWithTechExists(BotTeam, HiveTechOne) && AITAC_GetNumDeployablesNearLocation(pBot->Edict->v.origin, &StructureFilter) < 3) { return NumBuilders < 1; }
StructureFilter.DeployableTypes = ChamberTypeTwo;
if (AITAC_TeamHiveWithTechExists(BotTeam, HiveTechTwo) && AITAC_GetNumDeployablesNearLocation(pBot->Edict->v.origin, &StructureFilter) < 3) { return NumBuilders < 1; }
StructureFilter.DeployableTypes = ChamberTypeThree;
if (AITAC_TeamHiveWithTechExists(BotTeam, HiveTechThree) && AITAC_GetNumDeployablesNearLocation(pBot->Edict->v.origin, &StructureFilter) < 3) { return NumBuilders < 1; }
DeployableSearchFilter ResNodeFilter;
ResNodeFilter.DeployableTeam = BotTeam;
ResNodeFilter.ReachabilityTeam = BotTeam;
ResNodeFilter.ReachabilityFlags = pBot->BotNavInfo.NavProfile.ReachabilityFlag;
vector <AvHAIResourceNode*> OwnedNodes = AITAC_GetAllMatchingResourceNodes(pBot->Edict->v.origin, &ResNodeFilter);
for (auto it = OwnedNodes.begin(); it != OwnedNodes.end(); it++)
{
AvHAIResourceNode* ThisNode = (*it);
}
}

View file

@ -1999,27 +1999,9 @@ void AlienProgressGetHealthTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
void AlienProgressHealTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) void AlienProgressHealTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
{ {
if (!IsPlayerGorge(pBot->Edict) || FNullEnt(Task->TaskTarget) || IsPlayerDead(Task->TaskTarget)) { return; } if (FNullEnt(Task->TaskTarget) || IsPlayerDead(Task->TaskTarget)) { return; }
float DesiredDist = (IsEdictStructure(Task->TaskTarget)) ? kHealingSprayRange : (kHealingSprayRange * 0.5f); BotAlienHealTarget(pBot, Task->TaskTarget);
BotAttackResult LOSCheck = PerformAttackLOSCheck(pBot, WEAPON_GORGE_HEALINGSPRAY, Task->TaskTarget);
if (LOSCheck == ATTACK_SUCCESS)
{
pBot->DesiredCombatWeapon = WEAPON_GORGE_HEALINGSPRAY;
BotLookAt(pBot, UTIL_GetCentreOfEntity(Task->TaskTarget));
if (GetPlayerCurrentWeapon(pBot->Player) == WEAPON_GORGE_HEALINGSPRAY)
{
pBot->Button |= IN_ATTACK;
}
return;
}
else
{
MoveTo(pBot, UTIL_GetEntityGroundLocation(Task->TaskTarget), MOVESTYLE_NORMAL, kHealingSprayRange);
}
} }
void AlienProgressBuildHiveTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) void AlienProgressBuildHiveTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
@ -2214,9 +2196,6 @@ void BotAlienBuildResTower(AvHAIPlayer* pBot, const AvHAIResourceNode* NodeToCap
RegisterBotAlienBuildAttempt(pBot, NodeToCap->Location, STRUCTURE_ALIEN_RESTOWER); RegisterBotAlienBuildAttempt(pBot, NodeToCap->Location, STRUCTURE_ALIEN_RESTOWER);
} }
} }
void BotAlienBuildHive(AvHAIPlayer* pBot, const AvHAIHiveDefinition* HiveToBuild) void BotAlienBuildHive(AvHAIPlayer* pBot, const AvHAIHiveDefinition* HiveToBuild)
@ -2267,6 +2246,33 @@ void BotAlienBuildHive(AvHAIPlayer* pBot, const AvHAIHiveDefinition* HiveToBuild
} }
} }
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->Edict->v.origin, ALIEN_LIFEFORM_TWO);
return;
}
}
else
{
MoveTo(pBot, UTIL_GetEntityGroundLocation(HealTarget), MOVESTYLE_NORMAL, MaxHealRange);
}
}
void RegisterBotAlienBuildAttempt(AvHAIPlayer* pBot, Vector PlacementLocation, AvHAIDeployableStructureType DesiredStructure) void RegisterBotAlienBuildAttempt(AvHAIPlayer* pBot, Vector PlacementLocation, AvHAIDeployableStructureType DesiredStructure)
{ {
pBot->ActiveBuildInfo.AttemptedLocation = PlacementLocation; pBot->ActiveBuildInfo.AttemptedLocation = PlacementLocation;

View file

@ -112,6 +112,7 @@ void UTIL_ClearGuardInfo(AvHAIPlayer* pBot);
void BotAlienPlaceChamber(AvHAIPlayer* pBot, Vector Location, AvHAIDeployableStructureType DesiredStructure); void BotAlienPlaceChamber(AvHAIPlayer* pBot, Vector Location, AvHAIDeployableStructureType DesiredStructure);
void BotAlienBuildHive(AvHAIPlayer* pBot, const AvHAIHiveDefinition* HiveToBuild); void BotAlienBuildHive(AvHAIPlayer* pBot, const AvHAIHiveDefinition* HiveToBuild);
void BotAlienBuildResTower(AvHAIPlayer* pBot, const AvHAIResourceNode* NodeToCap); void BotAlienBuildResTower(AvHAIPlayer* pBot, const AvHAIResourceNode* NodeToCap);
void BotAlienHealTarget(AvHAIPlayer* pBot, edict_t* HealTarget);
void RegisterBotAlienBuildAttempt(AvHAIPlayer* pBot, Vector PlacementLocation, AvHAIDeployableStructureType DesiredStructure); void RegisterBotAlienBuildAttempt(AvHAIPlayer* pBot, Vector PlacementLocation, AvHAIDeployableStructureType DesiredStructure);

View file

@ -399,7 +399,7 @@ float GetMaxIdealWeaponRange(const AvHAIWeapon Weapon)
case WEAPON_LERK_BITE: case WEAPON_LERK_BITE:
return BALANCE_VAR(kBite2Range); return BALANCE_VAR(kBite2Range);
case WEAPON_GORGE_HEALINGSPRAY: case WEAPON_GORGE_HEALINGSPRAY:
return BALANCE_VAR(kHealingSprayRange); return BALANCE_VAR(kHealingSprayRange) * 0.5f;
case WEAPON_MARINE_WELDER: case WEAPON_MARINE_WELDER:
return BALANCE_VAR(kWelderRange); return BALANCE_VAR(kWelderRange);
default: default: