Improved commander placement and tactical refresh

This commit is contained in:
RGreenlees 2024-02-12 22:48:03 +00:00 committed by pierow
parent 9e0b42dbf4
commit 261caa1c55
10 changed files with 241 additions and 148 deletions

View file

@ -911,17 +911,19 @@ bool AICOMM_CheckForNextBuildAction(AvHAIPlayer* pBot)
StructureFilter.DeployableTeam = TeamNumber; StructureFilter.DeployableTeam = TeamNumber;
StructureFilter.ReachabilityFlags = AI_REACHABILITY_MARINE; StructureFilter.ReachabilityFlags = AI_REACHABILITY_MARINE;
StructureFilter.ReachabilityTeam = TeamNumber; StructureFilter.ReachabilityTeam = TeamNumber;
StructureFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(10.0f); StructureFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(15.0f);
int NumInfantryPortals = AITAC_GetNumDeployablesNearLocation(CommChair->v.origin, &StructureFilter); int NumInfantryPortals = AITAC_GetNumDeployablesNearLocation(CommChair->v.origin, &StructureFilter);
if (NumInfantryPortals < 2) if (NumInfantryPortals < 2)
{ {
bool bSuccess = AICOMM_BuildInfantryPortal(pBot, CommChair); bool bEnemyInBase = NumInfantryPortals > 1 && AITAC_AnyPlayerOnTeamWithLOS(AIMGR_GetEnemyTeam(TeamNumber), CommChair->v.origin, UTIL_MetresToGoldSrcUnits(10.0f));
bool bSuccess = !bEnemyInBase && AICOMM_BuildInfantryPortal(pBot, CommChair);
return (bSuccess || pBot->Player->GetResources() <= BALANCE_VAR(kInfantryPortalCost) + 5); return (bSuccess || pBot->Player->GetResources() <= BALANCE_VAR(kInfantryPortalCost) + 5);
} }
StructureFilter.DeployableTypes = STRUCTURE_MARINE_ARMOURY | STRUCTURE_MARINE_ADVARMOURY; StructureFilter.DeployableTypes = (STRUCTURE_MARINE_ARMOURY | STRUCTURE_MARINE_ADVARMOURY);
AvHAIBuildableStructure* BaseArmoury = AITAC_FindClosestDeployableToLocation(CommChair->v.origin, &StructureFilter); AvHAIBuildableStructure* BaseArmoury = AITAC_FindClosestDeployableToLocation(CommChair->v.origin, &StructureFilter);
@ -929,7 +931,6 @@ bool AICOMM_CheckForNextBuildAction(AvHAIPlayer* pBot)
{ {
StructureFilter.DeployableTypes = STRUCTURE_MARINE_INFANTRYPORTAL; StructureFilter.DeployableTypes = STRUCTURE_MARINE_INFANTRYPORTAL;
StructureFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(5.0f);
AvHAIBuildableStructure* NearestInfantryPortal = AITAC_FindClosestDeployableToLocation(CommChair->v.origin, &StructureFilter); AvHAIBuildableStructure* NearestInfantryPortal = AITAC_FindClosestDeployableToLocation(CommChair->v.origin, &StructureFilter);
@ -982,7 +983,9 @@ bool AICOMM_CheckForNextBuildAction(AvHAIPlayer* pBot)
if (!vIsZero(BuildLocation)) if (!vIsZero(BuildLocation))
{ {
bool bSuccess = AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_PHASEGATE, BuildLocation); bool bEnemyInBase = AITAC_AnyPlayerOnTeamWithLOS(AIMGR_GetEnemyTeam(TeamNumber), BuildLocation + Vector(0.0f, 0.0f, 32.0f), UTIL_MetresToGoldSrcUnits(10.0f));
bool bSuccess = !bEnemyInBase && AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_PHASEGATE, BuildLocation);
return (bSuccess || pBot->Player->GetResources() <= BALANCE_VAR(kPhaseGateCost) + 5); return (bSuccess || pBot->Player->GetResources() <= BALANCE_VAR(kPhaseGateCost) + 5);
} }
} }
@ -1017,7 +1020,9 @@ bool AICOMM_CheckForNextBuildAction(AvHAIPlayer* pBot)
if (!vIsZero(BuildLocation)) if (!vIsZero(BuildLocation))
{ {
bool bSuccess = AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_ARMSLAB, BuildLocation); bool bEnemyInBase = AITAC_AnyPlayerOnTeamWithLOS(AIMGR_GetEnemyTeam(TeamNumber), BuildLocation + Vector(0.0f, 0.0f, 32.0f), UTIL_MetresToGoldSrcUnits(10.0f));
bool bSuccess = !bEnemyInBase && AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_ARMSLAB, BuildLocation);
return (bSuccess || pBot->Player->GetResources() <= BALANCE_VAR(kArmsLabCost) + 5); return (bSuccess || pBot->Player->GetResources() <= BALANCE_VAR(kArmsLabCost) + 5);
} }
} }
@ -1032,7 +1037,9 @@ bool AICOMM_CheckForNextBuildAction(AvHAIPlayer* pBot)
if (!vIsZero(BuildLocation)) if (!vIsZero(BuildLocation))
{ {
bool bSuccess = AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_OBSERVATORY, BuildLocation); bool bEnemyInBase = AITAC_AnyPlayerOnTeamWithLOS(AIMGR_GetEnemyTeam(TeamNumber), BuildLocation + Vector(0.0f, 0.0f, 32.0f), UTIL_MetresToGoldSrcUnits(10.0f));
bool bSuccess = !bEnemyInBase && AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_OBSERVATORY, BuildLocation);
return (bSuccess || pBot->Player->GetResources() <= BALANCE_VAR(kObservatoryCost) + 5); return (bSuccess || pBot->Player->GetResources() <= BALANCE_VAR(kObservatoryCost) + 5);
} }
} }
@ -1096,10 +1103,10 @@ bool AICOMM_CheckForNextBuildAction(AvHAIPlayer* pBot)
if (!vIsZero(BuildLocation)) if (!vIsZero(BuildLocation))
{ {
if (AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_PROTOTYPELAB, BuildLocation)) bool bEnemyInBase = AITAC_AnyPlayerOnTeamWithLOS(AIMGR_GetEnemyTeam(TeamNumber), BuildLocation + Vector(0.0f, 0.0f, 32.0f), UTIL_MetresToGoldSrcUnits(10.0f));
{
return true; bool bSuccess = !bEnemyInBase && AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_PROTOTYPELAB, BuildLocation);
} return (bSuccess || pBot->Player->GetResources() <= BALANCE_VAR(kPrototypeLabCost) + 5);
} }
} }
@ -1718,6 +1725,8 @@ const AvHAIResourceNode* AICOMM_GetNearestResourceNodeCapOpportunity(const AvHTe
if (!AITAC_AnyPlayerOnTeamWithLOS(Team, (ResNode->Location + Vector(0.0f, 0.0f, 32.0f)), UTIL_MetresToGoldSrcUnits(5.0f))) { continue; } if (!AITAC_AnyPlayerOnTeamWithLOS(Team, (ResNode->Location + Vector(0.0f, 0.0f, 32.0f)), UTIL_MetresToGoldSrcUnits(5.0f))) { continue; }
if (AITAC_AnyPlayerOnTeamWithLOS(AIMGR_GetEnemyTeam(Team), (ResNode->Location + Vector(0.0f, 0.0f, 32.0f)), UTIL_MetresToGoldSrcUnits(10.0f))) { continue; }
float ThisDist = vDist2DSq(ResNode->Location, SearchLocation); float ThisDist = vDist2DSq(ResNode->Location, SearchLocation);
if (!Result || ThisDist < MinDist) if (!Result || ThisDist < MinDist)
@ -1805,12 +1814,16 @@ bool AICOMM_PerformNextSiegeHiveAction(AvHAIPlayer* pBot, const AvHAIHiveDefinit
return AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_PHASEGATE, NextBuildPosition, STRUCTURE_PURPOSE_SIEGE); return AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_PHASEGATE, NextBuildPosition, STRUCTURE_PURPOSE_SIEGE);
} }
if (ExistingPG && !(ExistingPG->StructureStatusFlags & STRUCTURE_STATUS_COMPLETED)) { return false; }
if (!ExistingTF) if (!ExistingTF)
{ {
if (vDist2DSq(NextBuildPosition, HiveToSiege->Location) > sqrf(UTIL_MetresToGoldSrcUnits(20.0f))) { return true; } if (vDist2DSq(NextBuildPosition, HiveToSiege->Location) > sqrf(UTIL_MetresToGoldSrcUnits(20.0f))) { return true; }
return AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_TURRETFACTORY, NextBuildPosition, STRUCTURE_PURPOSE_SIEGE); return AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_TURRETFACTORY, NextBuildPosition, STRUCTURE_PURPOSE_SIEGE);
} }
if (ExistingTF && !(ExistingTF->StructureStatusFlags & STRUCTURE_STATUS_COMPLETED)) { return false; }
StructureFilter.DeployableTypes = STRUCTURE_MARINE_ARMOURY | STRUCTURE_MARINE_ADVARMOURY; StructureFilter.DeployableTypes = STRUCTURE_MARINE_ARMOURY | STRUCTURE_MARINE_ADVARMOURY;
StructureFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(10.0f); StructureFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(10.0f);

View file

@ -483,6 +483,16 @@ typedef struct _BOT_SKILL
} bot_skill; } bot_skill;
typedef struct _AVH_AI_BUILD_ATTEMPT
{
AvHAIDeployableStructureType AttemptedStructureType = STRUCTURE_NONE;
Vector AttemptedLocation = g_vecZero;
int NumAttempts = 0;
BotBuildAttemptStatus BuildStatus = BUILD_ATTEMPT_NONE;
float BuildAttemptTime = 0.0f;
AvHAIBuildableStructure* LinkedStructure = nullptr;
} AvHAIBuildAttempt;
// A bot task is a goal the bot wants to perform, such as attacking a structure, placing a structure etc. NOT USED BY COMMANDER // A bot task is a goal the bot wants to perform, such as attacking a structure, placing a structure etc. NOT USED BY COMMANDER
typedef struct _AVH_AI_PLAYER_TASK typedef struct _AVH_AI_PLAYER_TASK
{ {
@ -500,19 +510,9 @@ typedef struct _AVH_AI_PLAYER_TASK
int BuildAttempts = 0; // How many attempts the Gorge has tried to place it, so it doesn't keep trying forever int BuildAttempts = 0; // How many attempts the Gorge has tried to place it, so it doesn't keep trying forever
AvHMessageID Evolution = MESSAGE_NULL; // Used by TASK_EVOLVE to determine what to evolve into AvHMessageID Evolution = MESSAGE_NULL; // Used by TASK_EVOLVE to determine what to evolve into
float TaskLength = 0.0f; // If a task has gone on longer than this time, it will be considered completed float TaskLength = 0.0f; // If a task has gone on longer than this time, it will be considered completed
AvHAIBuildAttempt ActiveBuildInfo; // If gorge, the current status of any recent attempt to place a structure
} AvHAIPlayerTask; } AvHAIPlayerTask;
typedef struct _AVH_AI_BUILD_ATTEMPT
{
AvHAIDeployableStructureType AttemptedStructureType = STRUCTURE_NONE;
Vector AttemptedLocation = g_vecZero;
int NumAttempts = 0;
BotBuildAttemptStatus BuildStatus = BUILD_ATTEMPT_NONE;
float BuildAttemptTime = 0.0f;
AvHAIBuildableStructure* LinkedStructure = nullptr;
} AvHAIBuildAttempt;
typedef struct _DOOR_TRIGGER typedef struct _DOOR_TRIGGER
{ {
CBaseEntity* Entity = nullptr; CBaseEntity* Entity = nullptr;
@ -727,8 +727,6 @@ typedef struct AVH_AI_PLAYER
nav_status BotNavInfo; // Bot's movement information, their current path, where in the path they are etc. nav_status BotNavInfo; // Bot's movement information, their current path, where in the path they are etc.
AvHAIBuildAttempt ActiveBuildInfo; // If gorge, the current status of any recent attempt to place a structure
vector<ai_commander_request> ActiveRequests; vector<ai_commander_request> ActiveRequests;
vector<ai_commander_order> ActiveOrders; vector<ai_commander_order> ActiveOrders;

View file

@ -1838,7 +1838,8 @@ dtStatus FindPathClosestToPoint(AvHAIPlayer* pBot, const BotMoveStyle MoveStyle,
if (CurrFlags == SAMPLE_POLYFLAGS_WALLCLIMB || CurrFlags == SAMPLE_POLYFLAGS_LADDER) if (CurrFlags == SAMPLE_POLYFLAGS_WALLCLIMB || CurrFlags == SAMPLE_POLYFLAGS_LADDER)
{ {
int HullNum = GetPlayerHullIndex(pBot->Edict, false); int HullNum = GetPlayerHullIndex(pBot->Edict, false);
float NewRequiredZ = UTIL_FindZHeightForWallClimb(path.back().Location, NextPathNode.Location, HullNum); Vector FromLocation = (path.size() > 0) ? path.back().Location : pBot->CurrentFloorPosition;
float NewRequiredZ = UTIL_FindZHeightForWallClimb(FromLocation, NextPathNode.Location, HullNum);
NextPathNode.requiredZ = fmaxf(NewRequiredZ, NextPathNode.Location.z); NextPathNode.requiredZ = fmaxf(NewRequiredZ, NextPathNode.Location.z);
if (CurrFlags == SAMPLE_POLYFLAGS_LADDER) if (CurrFlags == SAMPLE_POLYFLAGS_LADDER)
@ -3054,27 +3055,38 @@ void GroundMove(AvHAIPlayer* pBot, const Vector StartPoint, const Vector EndPoin
void FallMove(AvHAIPlayer* pBot, const Vector StartPoint, const Vector EndPoint) void FallMove(AvHAIPlayer* pBot, const Vector StartPoint, const Vector EndPoint)
{ {
Vector vForward = UTIL_GetVectorNormal2D(EndPoint - pBot->Edict->v.origin); Vector vBotOrientation = UTIL_GetVectorNormal2D(EndPoint - pBot->Edict->v.origin);
Vector vForward = UTIL_GetVectorNormal2D(EndPoint - StartPoint);
if (vIsZero(vForward)) if (pBot->BotNavInfo.IsOnGround)
{ {
vForward = UTIL_GetVectorNormal2D(EndPoint - StartPoint); if (vDist2DSq(pBot->Edict->v.origin, EndPoint) > sqrf(GetPlayerRadius(pBot->Player)))
{
pBot->desiredMovementDir = vBotOrientation;
}
else
{
pBot->desiredMovementDir = vForward;
}
bool bCanDuck = (IsPlayerMarine(pBot->Edict) || IsPlayerFade(pBot->Edict) || IsPlayerOnos(pBot->Edict));
if (!bCanDuck) { return; }
Vector HeadLocation = GetPlayerTopOfCollisionHull(pBot->Edict, false);
if (!UTIL_QuickTrace(pBot->Edict, HeadLocation, (HeadLocation + (pBot->desiredMovementDir * 50.0f))))
{
pBot->Button |= IN_DUCK;
}
}
else
{
pBot->desiredMovementDir = vBotOrientation;
} }
pBot->desiredMovementDir = vForward;
if (UTIL_PointIsDirectlyReachable(pBot, EndPoint)) { return; }
bool bCanDuck = (IsPlayerMarine(pBot->Edict) || IsPlayerFade(pBot->Edict) || IsPlayerOnos(pBot->Edict));
if (!bCanDuck) { return; }
Vector HeadLocation = GetPlayerTopOfCollisionHull(pBot->Edict, false);
if (!UTIL_QuickTrace(pBot->Edict, HeadLocation, (HeadLocation + (pBot->desiredMovementDir * 50.0f))))
{
pBot->Button |= IN_DUCK;
}
} }
void StructureBlockedMove(AvHAIPlayer* pBot, const Vector StartPoint, const Vector EndPoint) void StructureBlockedMove(AvHAIPlayer* pBot, const Vector StartPoint, const Vector EndPoint)
@ -3858,7 +3870,7 @@ bool IsBotOffPath(const AvHAIPlayer* pBot)
Vector vForward = UTIL_GetVectorNormal2D(MoveTo - MoveFrom); Vector vForward = UTIL_GetVectorNormal2D(MoveTo - MoveFrom);
Vector PointOnPath = vClosestPointOnLine2D(MoveFrom, MoveTo, pBot->CurrentFloorPosition); Vector PointOnPath = vClosestPointOnLine2D(MoveFrom, MoveTo, pBot->Edict->v.origin);
if (pBot->BotNavInfo.CurrentPathPoint->flag == SAMPLE_POLYFLAGS_WALLCLIMB) if (pBot->BotNavInfo.CurrentPathPoint->flag == SAMPLE_POLYFLAGS_WALLCLIMB)
{ {
@ -3871,16 +3883,7 @@ bool IsBotOffPath(const AvHAIPlayer* pBot)
if (pBot->BotNavInfo.CurrentPathPoint->flag == SAMPLE_POLYFLAGS_WALK) if (pBot->BotNavInfo.CurrentPathPoint->flag == SAMPLE_POLYFLAGS_WALK)
{ {
if (!UTIL_PointIsDirectlyReachable(pBot->CurrentFloorPosition, MoveTo)) if (vDist2DSq(pBot->Edict->v.origin, PointOnPath) > sqrf(100.0f)) { return true; }
{
Vector TraceEnd = MoveTo;
TraceEnd.z = pBot->Edict->v.origin.z;
if (!UTIL_QuickHullTrace(pBot->Edict, pBot->Edict->v.origin, TraceEnd, GetPlayerHullIndex(pBot->Edict)))
{
return true;
}
}
bool bAtMoveStart = vEquals(PointOnPath, MoveFrom, 2.0f); bool bAtMoveStart = vEquals(PointOnPath, MoveFrom, 2.0f);
@ -4964,7 +4967,7 @@ bool AbortCurrentMove(AvHAIPlayer* pBot, const Vector NewDestination)
if (flag == SAMPLE_POLYFLAGS_LIFT) if (flag == SAMPLE_POLYFLAGS_LIFT)
{ {
if (pBot->BotNavInfo.MovementTask.TaskType != MOVE_TASK_NONE) if (pBot->BotNavInfo.MovementTask.TaskType != MOVE_TASK_NONE && !vEquals(NewDestination, pBot->BotNavInfo.MovementTask.TaskLocation))
{ {
if (NAV_IsMovementTaskStillValid(pBot)) if (NAV_IsMovementTaskStillValid(pBot))
{ {
@ -5132,7 +5135,7 @@ void UpdateBotStuck(AvHAIPlayer* pBot)
if (!vIsZero(pBot->desiredMovementDir)) if (!vIsZero(pBot->desiredMovementDir))
{ {
//BotJump(pBot); BotJump(pBot);
if (!IsPlayerSkulk(pBot->Edict)) if (!IsPlayerSkulk(pBot->Edict))
{ {

View file

@ -1641,27 +1641,49 @@ void StartNewBotFrame(AvHAIPlayer* pBot)
} }
// If we tried placing a building as gorge, and nothing has appeared within the expected time, then mark it as a failed attempt. // If we tried placing a building as gorge, and nothing has appeared within the expected time, then mark it as a failed attempt.
if (pBot->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_PENDING) if (pBot->PrimaryBotTask.ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_PENDING)
{ {
if (pBot->ActiveBuildInfo.AttemptedStructureType == STRUCTURE_ALIEN_HIVE) if (pBot->PrimaryBotTask.ActiveBuildInfo.AttemptedStructureType == STRUCTURE_ALIEN_HIVE)
{ {
// Give a 3-second grace period to check if the hive placement was successful // Give a 3-second grace period to check if the hive placement was successful
if ((gpGlobals->time - pBot->ActiveBuildInfo.BuildAttemptTime) > 3.0f) if ((gpGlobals->time - pBot->PrimaryBotTask.ActiveBuildInfo.BuildAttemptTime) > 3.0f)
{ {
const AvHAIHiveDefinition* NearestHive = AITAC_GetHiveNearestLocation(pBot->ActiveBuildInfo.AttemptedLocation); const AvHAIHiveDefinition* NearestHive = AITAC_GetHiveNearestLocation(pBot->PrimaryBotTask.ActiveBuildInfo.AttemptedLocation);
pBot->ActiveBuildInfo.BuildStatus = (NearestHive->Status != HIVE_STATUS_UNBUILT) ? BUILD_ATTEMPT_SUCCESS : BUILD_ATTEMPT_FAILED; pBot->PrimaryBotTask.ActiveBuildInfo.BuildStatus = (NearestHive->Status != HIVE_STATUS_UNBUILT) ? BUILD_ATTEMPT_SUCCESS : BUILD_ATTEMPT_FAILED;
} }
} }
else else
{ {
// All other structures should appear near-instantly // All other structures should appear near-instantly
if ((gpGlobals->time - pBot->ActiveBuildInfo.BuildAttemptTime) > 0.5f) if ((gpGlobals->time - pBot->PrimaryBotTask.ActiveBuildInfo.BuildAttemptTime) > 0.5f)
{ {
pBot->ActiveBuildInfo.BuildStatus = BUILD_ATTEMPT_FAILED; pBot->PrimaryBotTask.ActiveBuildInfo.BuildStatus = BUILD_ATTEMPT_FAILED;
} }
} }
}
// If we tried placing a building as gorge, and nothing has appeared within the expected time, then mark it as a failed attempt.
if (pBot->SecondaryBotTask.ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_PENDING)
{
if (pBot->SecondaryBotTask.ActiveBuildInfo.AttemptedStructureType == STRUCTURE_ALIEN_HIVE)
{
// Give a 3-second grace period to check if the hive placement was successful
if ((gpGlobals->time - pBot->SecondaryBotTask.ActiveBuildInfo.BuildAttemptTime) > 3.0f)
{
const AvHAIHiveDefinition* NearestHive = AITAC_GetHiveNearestLocation(pBot->SecondaryBotTask.ActiveBuildInfo.AttemptedLocation);
pBot->SecondaryBotTask.ActiveBuildInfo.BuildStatus = (NearestHive->Status != HIVE_STATUS_UNBUILT) ? BUILD_ATTEMPT_SUCCESS : BUILD_ATTEMPT_FAILED;
}
}
else
{
// All other structures should appear near-instantly
if ((gpGlobals->time - pBot->SecondaryBotTask.ActiveBuildInfo.BuildAttemptTime) > 0.5f)
{
pBot->SecondaryBotTask.ActiveBuildInfo.BuildStatus = BUILD_ATTEMPT_FAILED;
}
}
} }
} }
@ -2553,6 +2575,11 @@ void AIPlayerNSMarineThink(AvHAIPlayer* pBot)
return; return;
} }
if (pBot->CurrentEnemy > -1)
{
if (MarineCombatThink(pBot)) { return; }
}
if (!pBot->CurrentTask) { pBot->CurrentTask = &pBot->PrimaryBotTask; } if (!pBot->CurrentTask) { pBot->CurrentTask = &pBot->PrimaryBotTask; }
if (gpGlobals->time >= pBot->BotNextTaskEvaluationTime) if (gpGlobals->time >= pBot->BotNextTaskEvaluationTime)
@ -2568,11 +2595,6 @@ void AIPlayerNSMarineThink(AvHAIPlayer* pBot)
pBot->CurrentTask = AIPlayerGetNextTask(pBot); pBot->CurrentTask = AIPlayerGetNextTask(pBot);
if (pBot->CurrentEnemy > -1)
{
if (MarineCombatThink(pBot)) { return; }
}
if (pBot->CurrentTask && pBot->CurrentTask->TaskType != TASK_NONE) if (pBot->CurrentTask && pBot->CurrentTask->TaskType != TASK_NONE)
{ {
BotProgressTask(pBot, pBot->CurrentTask); BotProgressTask(pBot, pBot->CurrentTask);
@ -2983,6 +3005,8 @@ bool RegularMarineCombatThink(AvHAIPlayer* pBot)
BotShootTarget(pBot, DesiredCombatWeapon, CurrentEnemy); BotShootTarget(pBot, DesiredCombatWeapon, CurrentEnemy);
} }
return true;
} }
return false; return false;
@ -3732,7 +3756,7 @@ bool AIPlayerMustFinishCurrentTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
{ {
AvHTeamNumber BotTeam = pBot->Player->GetTeam(); AvHTeamNumber BotTeam = pBot->Player->GetTeam();
if (pBot->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_PENDING) { return true; } 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 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)
@ -3773,7 +3797,15 @@ void AIPlayerNSAlienThink(AvHAIPlayer* pBot)
if (AITAC_ShouldBotBuildHive(pBot, &HiveToBuild)) if (AITAC_ShouldBotBuildHive(pBot, &HiveToBuild))
{ {
BotAlienBuildHive(pBot, HiveToBuild); if (pBot->PrimaryBotTask.TaskType != TASK_BUILD || pBot->PrimaryBotTask.StructureType != STRUCTURE_ALIEN_HIVE)
{
pBot->PrimaryBotTask.TaskType = TASK_BUILD;
pBot->PrimaryBotTask.StructureType = STRUCTURE_ALIEN_HIVE;
char msg[64];
sprintf(msg, "I'm going to drop the hive at %s", HiveToBuild->HiveName);
BotSay(pBot, true, 1.0f, msg);
}
BotAlienBuildHive(pBot, &pBot->PrimaryBotTask, HiveToBuild);
return; return;
} }
@ -3858,6 +3890,16 @@ void AIPlayerThink(AvHAIPlayer* pBot)
bool bBreak = true; bool bBreak = true;
AIDEBUG_DrawBotPath(pBot); AIDEBUG_DrawBotPath(pBot);
if (pBot->BotNavInfo.CurrentPathPoint != pBot->BotNavInfo.CurrentPath.end())
{
UTIL_DrawLine(INDEXENT(1), pBot->Edict->v.origin, pBot->BotNavInfo.CurrentPathPoint->Location, 0, 255, 255);
}
}
if (pBot->PrimaryBotTask.TaskType == TASK_BUILD)
{
UTIL_DrawLine(INDEXENT(1), pBot->Edict->v.origin, pBot->PrimaryBotTask.TaskLocation, 0, 255, 255);
} }
switch (GetGameRules()->GetMapMode()) switch (GetGameRules()->GetMapMode())
@ -4261,7 +4303,7 @@ void AIPlayerSetAlienBuilderPrimaryTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task
if (!TowerToReinforce || ThisDist < MinDist) if (!TowerToReinforce || ThisDist < MinDist)
{ {
TowerToReinforce = ThisResTower->edict; TowerToReinforce = ThisResTower->edict;
MaxDist = ThisDist; MinDist = ThisDist;
} }
} }
} }

View file

@ -28,6 +28,7 @@ int BotNameIndex = 0;
float AIStartedTime = 0.0f; // Used to give 5-second grace period before adding bots float AIStartedTime = 0.0f; // Used to give 5-second grace period before adding bots
bool bHasRoundStarted = false; bool bHasRoundStarted = false;
bool bMapDataInitialised = false;
extern int m_spriteTexture; extern int m_spriteTexture;
@ -622,7 +623,7 @@ void AIMGR_UpdateAIPlayers()
UpdateBotChat(bot); UpdateBotChat(bot);
DroneThink(bot); AIPlayerThink(bot);
EndBotFrame(bot); EndBotFrame(bot);
@ -837,26 +838,19 @@ void AIMGR_ResetRound()
UTIL_PopulateDoors(); UTIL_PopulateDoors();
UTIL_PopulateWeldableObstacles(); UTIL_PopulateWeldableObstacles();
ALERT(at_console, "AI Manager Reset Round\n");
bHasRoundStarted = false;
}
void AIMGR_RoundStarted()
{
AITAC_PopulateResourceNodes();
AITAC_PopulateHiveData();
AITAC_RefreshResourceNodes();
AITAC_RefreshHiveData();
UTIL_UpdateDoors(true); UTIL_UpdateDoors(true);
UTIL_UpdateTileCache(); UTIL_UpdateTileCache();
ALERT(at_console, "AI Manager Reset Round\n");
bHasRoundStarted = false;
bMapDataInitialised = true;
}
void AIMGR_RoundStarted()
{
bHasRoundStarted = true; bHasRoundStarted = true;
} }
void AIMGR_ClearBotData() void AIMGR_ClearBotData()
@ -891,12 +885,16 @@ void AIMGR_NewMap()
{ {
if (avh_botsenabled.value == 0) { return; } // Do nothing if we're not using bots if (avh_botsenabled.value == 0) { return; } // Do nothing if we're not using bots
bMapDataInitialised = false;
ActiveAIPlayers.clear(); ActiveAIPlayers.clear();
AIStartedTime = gpGlobals->time; AIStartedTime = gpGlobals->time;
LastAIPlayerCountUpdate = 0.0f; LastAIPlayerCountUpdate = 0.0f;
ALERT(at_console, "AI Manager New Map\n"); ALERT(at_console, "AI Manager New Map\n");
AITAC_ClearMapAIData();
if (NavmeshLoaded()) if (NavmeshLoaded())
{ {
UnloadNavigationData(); UnloadNavigationData();
@ -1025,9 +1023,12 @@ vector<AvHPlayer*> AIMGR_GetNonAIPlayersOnTeam(AvHTeamNumber Team)
void AIMGR_UpdateAIMapData() void AIMGR_UpdateAIMapData()
{ {
AITAC_UpdateMapAIData(); if (bMapDataInitialised && gpGlobals->time - AIStartedTime > AI_GRACE_PERIOD)
UTIL_UpdateTileCache(); {
AITAC_CheckNavMeshModified(); AITAC_UpdateMapAIData();
UTIL_UpdateTileCache();
AITAC_CheckNavMeshModified();
}
} }
void AIMGR_BotPrecache() void AIMGR_BotPrecache()

View file

@ -1389,6 +1389,7 @@ AvHAIResourceNode* AITAC_GetRandomResourceNode(AvHTeamNumber SearchingTeam, cons
void AITAC_UpdateMapAIData() void AITAC_UpdateMapAIData()
{ {
AITAC_RefreshHiveData(); AITAC_RefreshHiveData();
UTIL_UpdateDoors(false); UTIL_UpdateDoors(false);
@ -2220,15 +2221,25 @@ void AITAC_LinkStructureToPlayer(AvHAIBuildableStructure* NewStructure)
{ {
AvHAIPlayer* Player = (*it); AvHAIPlayer* Player = (*it);
if (Player->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_PENDING && Player->ActiveBuildInfo.AttemptedStructureType == NewStructure->StructureType) if (Player->PrimaryBotTask.ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_PENDING && Player->PrimaryBotTask.ActiveBuildInfo.AttemptedStructureType == NewStructure->StructureType)
{ {
if (vDist2DSq(NewStructure->Location, Player->ActiveBuildInfo.AttemptedLocation) < sqrf(UTIL_MetresToGoldSrcUnits(2.0f))) if (vDist2DSq(NewStructure->Location, Player->PrimaryBotTask.ActiveBuildInfo.AttemptedLocation) < sqrf(UTIL_MetresToGoldSrcUnits(2.0f)))
{ {
Player->ActiveBuildInfo.BuildStatus = BUILD_ATTEMPT_SUCCESS; Player->PrimaryBotTask.ActiveBuildInfo.BuildStatus = BUILD_ATTEMPT_SUCCESS;
Player->ActiveBuildInfo.LinkedStructure = NewStructure; Player->PrimaryBotTask.ActiveBuildInfo.LinkedStructure = NewStructure;
} }
} }
if (Player->SecondaryBotTask.ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_PENDING && Player->SecondaryBotTask.ActiveBuildInfo.AttemptedStructureType == NewStructure->StructureType)
{
if (vDist2DSq(NewStructure->Location, Player->SecondaryBotTask.ActiveBuildInfo.AttemptedLocation) < sqrf(UTIL_MetresToGoldSrcUnits(2.0f)))
{
Player->SecondaryBotTask.ActiveBuildInfo.BuildStatus = BUILD_ATTEMPT_SUCCESS;
Player->SecondaryBotTask.ActiveBuildInfo.LinkedStructure = NewStructure;
}
}
} }
} }
@ -2996,6 +3007,32 @@ int AITAC_GetNumPlayersOfTeamInArea(const AvHTeamNumber Team, const Vector Searc
} }
bool AITAC_AnyPlayersOfTeamInArea(const AvHTeamNumber Team, const Vector SearchLocation, const float SearchRadius, const bool bConsiderPhaseDist, const edict_t* IgnorePlayer, const AvHUser3 IgnoreClass)
{
float MaxRadiusSq = sqrf(SearchRadius);
for (int i = 1; i <= gpGlobals->maxClients; i++)
{
edict_t* PlayerEdict = INDEXENT(i);
if (FNullEnt(PlayerEdict) || PlayerEdict->free || PlayerEdict == IgnorePlayer) { continue; }
AvHPlayer* PlayerRef = dynamic_cast<AvHPlayer*>(CBaseEntity::Instance(PlayerEdict));
if (PlayerRef != nullptr && GetPlayerActiveClass(PlayerRef) != IgnoreClass && (Team == TEAM_IND || PlayerRef->GetTeam() == Team) && IsPlayerActiveInGame(PlayerEdict))
{
float Dist = (bConsiderPhaseDist) ? sqrf(AITAC_GetPhaseDistanceBetweenPoints(PlayerEdict->v.origin, SearchLocation)) : vDist2DSq(PlayerEdict->v.origin, SearchLocation);
if (Dist <= MaxRadiusSq)
{
return true;
}
}
}
return false;
}
int AITAC_GetNumPlayersOnTeamOfClass(const AvHTeamNumber Team, const AvHUser3 SearchClass, const edict_t* IgnorePlayer) int AITAC_GetNumPlayersOnTeamOfClass(const AvHTeamNumber Team, const AvHUser3 SearchClass, const edict_t* IgnorePlayer)
{ {
int Result = 0; int Result = 0;

View file

@ -122,6 +122,7 @@ AvHAIWeapon UTIL_GetWeaponTypeFromEdict(const edict_t* ItemEdict);
int AITAC_GetNumActivePlayersOnTeam(const AvHTeamNumber Team); int AITAC_GetNumActivePlayersOnTeam(const AvHTeamNumber Team);
int AITAC_GetNumPlayersOfTeamInArea(const AvHTeamNumber Team, const Vector SearchLocation, const float SearchRadius, const bool bConsiderPhaseDist, const edict_t* IgnorePlayer, const AvHUser3 IgnoreClass); int AITAC_GetNumPlayersOfTeamInArea(const AvHTeamNumber Team, const Vector SearchLocation, const float SearchRadius, const bool bConsiderPhaseDist, const edict_t* IgnorePlayer, const AvHUser3 IgnoreClass);
bool AITAC_AnyPlayersOfTeamInArea(const AvHTeamNumber Team, const Vector SearchLocation, const float SearchRadius, const bool bConsiderPhaseDist, const edict_t* IgnorePlayer, const AvHUser3 IgnoreClass);
vector<AvHPlayer*> AITAC_GetAllPlayersOfTeamInArea(const AvHTeamNumber Team, const Vector SearchLocation, const float SearchRadius, const bool bConsiderPhaseDist, const edict_t* IgnorePlayer, const AvHUser3 IgnoreClass); vector<AvHPlayer*> AITAC_GetAllPlayersOfTeamInArea(const AvHTeamNumber Team, const Vector SearchLocation, const float SearchRadius, const bool bConsiderPhaseDist, const edict_t* IgnorePlayer, const AvHUser3 IgnoreClass);
int AITAC_GetNumPlayersOfTeamAndClassInArea(const AvHTeamNumber Team, const Vector SearchLocation, const float SearchRadius, const bool bConsiderPhaseDist, const edict_t* IgnorePlayer, const AvHUser3 SearchClass); int AITAC_GetNumPlayersOfTeamAndClassInArea(const AvHTeamNumber Team, const Vector SearchLocation, const float SearchRadius, const bool bConsiderPhaseDist, const edict_t* IgnorePlayer, const AvHUser3 SearchClass);
int AITAC_GetNumPlayersOnTeamOfClass(const AvHTeamNumber Team, const AvHUser3 SearchClass, const edict_t* IgnorePlayer); int AITAC_GetNumPlayersOnTeamOfClass(const AvHTeamNumber Team, const AvHUser3 SearchClass, const edict_t* IgnorePlayer);

View file

@ -137,7 +137,7 @@ void AITASK_ClearBotTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
Task->BuildAttempts = 0; Task->BuildAttempts = 0;
Task->StructureType = STRUCTURE_NONE; Task->StructureType = STRUCTURE_NONE;
memset(&pBot->ActiveBuildInfo, 0, sizeof(AvHAIBuildAttempt)); memset(&Task->ActiveBuildInfo, 0, sizeof(AvHAIBuildAttempt));
} }
bool AITASK_IsTaskUrgent(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) bool AITASK_IsTaskUrgent(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
@ -585,11 +585,11 @@ bool AITASK_IsAlienBuildTaskStillValid(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
if (Task->StructureType == STRUCTURE_NONE) { return false; } if (Task->StructureType == STRUCTURE_NONE) { return false; }
if (pBot->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_PENDING) { return true; } if (Task->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_PENDING) { return true; }
if (pBot->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_FAILED && pBot->ActiveBuildInfo.NumAttempts >= 3) { return false; } if (Task->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_FAILED && Task->ActiveBuildInfo.NumAttempts >= 3) { return false; }
if (pBot->ActiveBuildInfo.LinkedStructure && (UTIL_StructureIsFullyBuilt(pBot->ActiveBuildInfo.LinkedStructure->edict) || !UTIL_IsBuildableStructureStillReachable(pBot, pBot->ActiveBuildInfo.LinkedStructure->edict))) { 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) if (Task->StructureType == STRUCTURE_ALIEN_HIVE)
{ {
@ -1129,14 +1129,14 @@ void BotProgressPickupTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
void BotProgressMineStructureTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) void BotProgressMineStructureTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
{ {
if (pBot->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_PENDING) if (Task->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_PENDING)
{ {
return; return;
} }
if (pBot->ActiveBuildInfo.BuildStatus != BUILD_ATTEMPT_NONE) if (Task->ActiveBuildInfo.BuildStatus != BUILD_ATTEMPT_NONE)
{ {
if (pBot->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_FAILED) if (Task->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_FAILED)
{ {
float Size = fmaxf(Task->TaskTarget->v.size.x, Task->TaskTarget->v.size.y); float Size = fmaxf(Task->TaskTarget->v.size.x, Task->TaskTarget->v.size.y);
Size += 8.0f; Size += 8.0f;
@ -1147,7 +1147,7 @@ void BotProgressMineStructureTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
Task->TaskLocation = ZERO_VECTOR; Task->TaskLocation = ZERO_VECTOR;
} }
pBot->ActiveBuildInfo.BuildStatus = BUILD_ATTEMPT_NONE; Task->ActiveBuildInfo.BuildStatus = BUILD_ATTEMPT_NONE;
} }
if (vIsZero(Task->TaskLocation)) if (vIsZero(Task->TaskLocation))
@ -1184,11 +1184,11 @@ void BotProgressMineStructureTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
if (LookDot > 0.95f) if (LookDot > 0.95f)
{ {
pBot->Button |= IN_ATTACK; pBot->Button |= IN_ATTACK;
pBot->ActiveBuildInfo.AttemptedLocation = Task->TaskLocation; Task->ActiveBuildInfo.AttemptedLocation = Task->TaskLocation;
pBot->ActiveBuildInfo.BuildStatus = BUILD_ATTEMPT_PENDING; Task->ActiveBuildInfo.BuildStatus = BUILD_ATTEMPT_PENDING;
pBot->ActiveBuildInfo.BuildAttemptTime = gpGlobals->time; Task->ActiveBuildInfo.BuildAttemptTime = gpGlobals->time;
pBot->ActiveBuildInfo.AttemptedStructureType = STRUCTURE_MARINE_DEPLOYEDMINE; Task->ActiveBuildInfo.AttemptedStructureType = STRUCTURE_MARINE_DEPLOYEDMINE;
pBot->ActiveBuildInfo.NumAttempts++; Task->ActiveBuildInfo.NumAttempts++;
} }
} }
} }
@ -1199,13 +1199,13 @@ void BotProgressReinforceStructureTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
{ {
if (FNullEnt(Task->TaskTarget)) { return; } if (FNullEnt(Task->TaskTarget)) { return; }
if (pBot->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_PENDING) { return; } if (Task->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_PENDING) { return; }
// We had a go, whether it succeeded or not we should try a new location // We had a go, whether it succeeded or not we should try a new location
if (pBot->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_FAILED || pBot->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_SUCCESS) if (Task->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_FAILED || Task->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_SUCCESS)
{ {
Task->TaskLocation = ZERO_VECTOR; Task->TaskLocation = ZERO_VECTOR;
pBot->ActiveBuildInfo.BuildStatus = BUILD_ATTEMPT_NONE; Task->ActiveBuildInfo.BuildStatus = BUILD_ATTEMPT_NONE;
} }
AvHTeamNumber BotTeam = pBot->Player->GetTeam(); AvHTeamNumber BotTeam = pBot->Player->GetTeam();
@ -1312,7 +1312,7 @@ void BotProgressReinforceStructureTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
if (pBot->Player->GetResources() >= ResourceCost) if (pBot->Player->GetResources() >= ResourceCost)
{ {
BotAlienPlaceChamber(pBot, Task->TaskLocation, NextStructure); BotAlienPlaceChamber(pBot, Task, NextStructure);
return; return;
} }
} }
@ -1872,7 +1872,7 @@ void AlienProgressHealTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
void AlienProgressBuildHiveTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) void AlienProgressBuildHiveTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
{ {
if (pBot->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_PENDING) if (Task->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_PENDING)
{ {
return; return;
} }
@ -1899,13 +1899,13 @@ void AlienProgressBuildHiveTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
return; return;
} }
BotAlienBuildHive(pBot, Hive); BotAlienBuildHive(pBot, Task, Hive);
} }
void AlienProgressBuildTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) void AlienProgressBuildTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
{ {
// We tried and failed to place the structure // We tried and failed to place the structure
if (pBot->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_PENDING) if (Task->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_PENDING)
{ {
return; return;
} }
@ -1916,9 +1916,9 @@ void AlienProgressBuildTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
return; return;
} }
if (pBot->ActiveBuildInfo.LinkedStructure) if (Task->ActiveBuildInfo.LinkedStructure)
{ {
edict_t* LinkedEdict = pBot->ActiveBuildInfo.LinkedStructure->edict; edict_t* LinkedEdict = Task->ActiveBuildInfo.LinkedStructure->edict;
if (UTIL_StructureIsFullyBuilt(LinkedEdict)) { return; } if (UTIL_StructureIsFullyBuilt(LinkedEdict)) { return; }
@ -1938,10 +1938,10 @@ void AlienProgressBuildTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
} }
// We tried and failed to place the structure // We tried and failed to place the structure
if (pBot->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_FAILED) if (Task->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_FAILED)
{ {
Task->TaskLocation = UTIL_GetRandomPointOnNavmeshInRadius(BaseNavProfiles[GORGE_BASE_NAV_PROFILE], Task->TaskLocation, UTIL_MetresToGoldSrcUnits(2.0f)); Task->TaskLocation = UTIL_GetRandomPointOnNavmeshInRadius(BaseNavProfiles[GORGE_BASE_NAV_PROFILE], Task->TaskLocation, UTIL_MetresToGoldSrcUnits(2.0f));
pBot->ActiveBuildInfo.BuildStatus = BUILD_ATTEMPT_NONE; Task->ActiveBuildInfo.BuildStatus = BUILD_ATTEMPT_NONE;
} }
int ResRequired = UTIL_GetCostOfStructureType(Task->StructureType); int ResRequired = UTIL_GetCostOfStructureType(Task->StructureType);
@ -1980,34 +1980,35 @@ void AlienProgressBuildTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
return; return;
} }
BotAlienPlaceChamber(pBot, Task->TaskLocation, Task->StructureType); BotAlienPlaceChamber(pBot, Task, Task->StructureType);
} }
void BotAlienPlaceChamber(AvHAIPlayer* pBot, Vector Location, AvHAIDeployableStructureType DesiredStructure) void BotAlienPlaceChamber(AvHAIPlayer* pBot, AvHAIPlayerTask* Task, AvHAIDeployableStructureType DesiredStructure)
{ {
if (vIsZero(Location) || DesiredStructure == STRUCTURE_NONE) { return; } if (vIsZero(Task->TaskLocation) || DesiredStructure == STRUCTURE_NONE) { return; }
if (pBot->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_PENDING) { return; }
float DistFromBuildLocation = vDist2DSq(pBot->Edict->v.origin, Location); if (Task->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_PENDING) { return; }
float DistFromBuildLocation = vDist2DSq(pBot->Edict->v.origin, Task->TaskLocation);
if (DistFromBuildLocation > sqrf(UTIL_MetresToGoldSrcUnits(1.0f))) if (DistFromBuildLocation > sqrf(UTIL_MetresToGoldSrcUnits(1.0f)))
{ {
MoveTo(pBot, Location, MOVESTYLE_NORMAL); MoveTo(pBot, Task->TaskLocation, MOVESTYLE_NORMAL);
return; return;
} }
if (DistFromBuildLocation < sqrf(UTIL_MetresToGoldSrcUnits(0.5f))) if (DistFromBuildLocation < sqrf(UTIL_MetresToGoldSrcUnits(0.5f)))
{ {
BotLookAt(pBot, Location); BotLookAt(pBot, Task->TaskLocation);
Vector Orientation = UTIL_GetVectorNormal2D(pBot->Edict->v.origin - Location); Vector Orientation = UTIL_GetVectorNormal2D(pBot->Edict->v.origin - Task->TaskLocation);
Vector NewMoveLoc = Location + (Orientation * UTIL_MetresToGoldSrcUnits(2.0f)); Vector NewMoveLoc = Task->TaskLocation + (Orientation * UTIL_MetresToGoldSrcUnits(2.0f));
MoveToWithoutNav(pBot, NewMoveLoc); MoveToWithoutNav(pBot, NewMoveLoc);
return; return;
} }
Vector LookLocation = Location; Vector LookLocation = Task->TaskLocation;
LookLocation.z += 10.0f; LookLocation.z += 10.0f;
BotLookAt(pBot, LookLocation); BotLookAt(pBot, LookLocation);
@ -2035,15 +2036,15 @@ void BotAlienPlaceChamber(AvHAIPlayer* pBot, Vector Location, AvHAIDeployableStr
if (LookDot > 0.9f) if (LookDot > 0.9f)
{ {
pBot->Impulse = UTIL_StructureTypeToImpulseCommand(DesiredStructure); pBot->Impulse = UTIL_StructureTypeToImpulseCommand(DesiredStructure);
RegisterBotAlienBuildAttempt(pBot, Location, DesiredStructure); RegisterBotAlienBuildAttempt(pBot, Task, Task->TaskLocation, DesiredStructure);
} }
} }
void BotAlienBuildResTower(AvHAIPlayer* pBot, const AvHAIResourceNode* NodeToCap) void BotAlienBuildResTower(AvHAIPlayer* pBot, AvHAIPlayerTask* Task, const AvHAIResourceNode* NodeToCap)
{ {
if (NodeToCap->bIsOccupied) { return; } if (NodeToCap->bIsOccupied) { return; }
if (pBot->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_PENDING) { return; } if (Task->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_PENDING) { return; }
float CurrDist = vDist2DSq(pBot->CurrentFloorPosition, NodeToCap->Location); float CurrDist = vDist2DSq(pBot->CurrentFloorPosition, NodeToCap->Location);
@ -2090,17 +2091,17 @@ void BotAlienBuildResTower(AvHAIPlayer* pBot, const AvHAIResourceNode* NodeToCap
if (LookDot > 0.9f) if (LookDot > 0.9f)
{ {
pBot->Impulse = UTIL_StructureTypeToImpulseCommand(STRUCTURE_ALIEN_RESTOWER); pBot->Impulse = UTIL_StructureTypeToImpulseCommand(STRUCTURE_ALIEN_RESTOWER);
RegisterBotAlienBuildAttempt(pBot, NodeToCap->Location, STRUCTURE_ALIEN_RESTOWER); RegisterBotAlienBuildAttempt(pBot, Task, NodeToCap->Location, STRUCTURE_ALIEN_RESTOWER);
} }
} }
void BotAlienBuildHive(AvHAIPlayer* pBot, const AvHAIHiveDefinition* HiveToBuild) void BotAlienBuildHive(AvHAIPlayer* pBot, AvHAIPlayerTask* Task, const AvHAIHiveDefinition* HiveToBuild)
{ {
// Do nothing if the hive is already built / under construction // Do nothing if the hive is already built / under construction
if (HiveToBuild->Status != HIVE_STATUS_UNBUILT) { return; } if (HiveToBuild->Status != HIVE_STATUS_UNBUILT) { return; }
if (pBot->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_PENDING) { return; } if (Task->ActiveBuildInfo.BuildStatus == BUILD_ATTEMPT_PENDING) { return; }
if (vDist2DSq(pBot->Edict->v.origin, HiveToBuild->Location) > sqrf(UTIL_MetresToGoldSrcUnits(7.5f))) if (vDist2DSq(pBot->Edict->v.origin, HiveToBuild->Location) > sqrf(UTIL_MetresToGoldSrcUnits(7.5f)))
{ {
@ -2139,7 +2140,7 @@ void BotAlienBuildHive(AvHAIPlayer* pBot, const AvHAIHiveDefinition* HiveToBuild
} }
pBot->Impulse = UTIL_StructureTypeToImpulseCommand(STRUCTURE_ALIEN_HIVE); pBot->Impulse = UTIL_StructureTypeToImpulseCommand(STRUCTURE_ALIEN_HIVE);
RegisterBotAlienBuildAttempt(pBot, HiveToBuild->Location, STRUCTURE_ALIEN_HIVE); RegisterBotAlienBuildAttempt(pBot, Task, HiveToBuild->Location, STRUCTURE_ALIEN_HIVE);
} }
} }
@ -2170,14 +2171,14 @@ void BotAlienHealTarget(AvHAIPlayer* pBot, edict_t* HealTarget)
} }
void RegisterBotAlienBuildAttempt(AvHAIPlayer* pBot, Vector PlacementLocation, AvHAIDeployableStructureType DesiredStructure) void RegisterBotAlienBuildAttempt(AvHAIPlayer* pBot, AvHAIPlayerTask* Task, Vector PlacementLocation, AvHAIDeployableStructureType DesiredStructure)
{ {
pBot->ActiveBuildInfo.AttemptedLocation = PlacementLocation; Task->ActiveBuildInfo.AttemptedLocation = PlacementLocation;
pBot->ActiveBuildInfo.BuildAttemptTime = gpGlobals->time; Task->ActiveBuildInfo.BuildAttemptTime = gpGlobals->time;
pBot->ActiveBuildInfo.LinkedStructure = nullptr; Task->ActiveBuildInfo.LinkedStructure = nullptr;
pBot->ActiveBuildInfo.NumAttempts++; Task->ActiveBuildInfo.NumAttempts++;
pBot->ActiveBuildInfo.AttemptedStructureType = DesiredStructure; Task->ActiveBuildInfo.AttemptedStructureType = DesiredStructure;
pBot->ActiveBuildInfo.BuildStatus = BUILD_ATTEMPT_PENDING; Task->ActiveBuildInfo.BuildStatus = BUILD_ATTEMPT_PENDING;
} }
void AlienProgressCapResNodeTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) void AlienProgressCapResNodeTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
@ -2252,7 +2253,7 @@ void AlienProgressCapResNodeTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
// We have enough resources to place the tower (includes cost of evolving to gorge if necessary) // We have enough resources to place the tower (includes cost of evolving to gorge if necessary)
if (pBot->Player->GetResources() >= NumResourcesRequired) if (pBot->Player->GetResources() >= NumResourcesRequired)
{ {
BotAlienBuildResTower(pBot, ResNodeIndex); BotAlienBuildResTower(pBot, Task, ResNodeIndex);
return; return;
} }
} }

View file

@ -109,11 +109,11 @@ AvHAIPlayer* GetFirstBotWithReinforceTask(AvHTeamNumber Team, edict_t* Reinforce
void UTIL_ClearGuardInfo(AvHAIPlayer* pBot); void UTIL_ClearGuardInfo(AvHAIPlayer* pBot);
void BotAlienPlaceChamber(AvHAIPlayer* pBot, Vector Location, AvHAIDeployableStructureType DesiredStructure); void BotAlienPlaceChamber(AvHAIPlayer* pBot, AvHAIPlayerTask* Task, AvHAIDeployableStructureType DesiredStructure);
void BotAlienBuildHive(AvHAIPlayer* pBot, const AvHAIHiveDefinition* HiveToBuild); void BotAlienBuildHive(AvHAIPlayer* pBot, AvHAIPlayerTask* Task, const AvHAIHiveDefinition* HiveToBuild);
void BotAlienBuildResTower(AvHAIPlayer* pBot, const AvHAIResourceNode* NodeToCap); void BotAlienBuildResTower(AvHAIPlayer* pBot, AvHAIPlayerTask* Task, const AvHAIResourceNode* NodeToCap);
void BotAlienHealTarget(AvHAIPlayer* pBot, edict_t* HealTarget); void BotAlienHealTarget(AvHAIPlayer* pBot, edict_t* HealTarget);
void RegisterBotAlienBuildAttempt(AvHAIPlayer* pBot, Vector PlacementLocation, AvHAIDeployableStructureType DesiredStructure); void RegisterBotAlienBuildAttempt(AvHAIPlayer* pBot, AvHAIPlayerTask* Task, Vector PlacementLocation, AvHAIDeployableStructureType DesiredStructure);
#endif #endif

View file

@ -3609,10 +3609,7 @@ void AvHGamerules::Think(void)
if (avh_botsenabled.value > 0) if (avh_botsenabled.value > 0)
{ {
if (this->GetGameStarted()) AIMGR_UpdateAIMapData();
{
AIMGR_UpdateAIMapData();
}
AIMGR_UpdateAIPlayers(); AIMGR_UpdateAIPlayers();
} }