From 6883eb33b31aa7e9dd70889390ba26e8002e291f Mon Sep 17 00:00:00 2001 From: RGreenlees Date: Sat, 16 Mar 2024 17:34:52 +0000 Subject: [PATCH] Tweaked level load sequence --- main/source/mod/AIPlayers/AvHAICommander.cpp | 711 ++++++++++-------- main/source/mod/AIPlayers/AvHAIConstants.h | 4 +- main/source/mod/AIPlayers/AvHAINavigation.cpp | 34 +- main/source/mod/AIPlayers/AvHAIPlayer.cpp | 344 ++++----- .../mod/AIPlayers/AvHAIPlayerManager.cpp | 23 +- .../source/mod/AIPlayers/AvHAIPlayerManager.h | 1 + main/source/mod/AIPlayers/AvHAIPlayerUtil.cpp | 1 - main/source/mod/AIPlayers/AvHAITactical.cpp | 442 +++++++++-- main/source/mod/AIPlayers/AvHAITactical.h | 13 +- main/source/mod/AIPlayers/AvHAITask.cpp | 100 +-- main/source/mod/AvHConsoleCommands.cpp | 15 + main/source/mod/AvHGamerules.cpp | 5 + 12 files changed, 1090 insertions(+), 603 deletions(-) diff --git a/main/source/mod/AIPlayers/AvHAICommander.cpp b/main/source/mod/AIPlayers/AvHAICommander.cpp index 68818c1d..f248ef9f 100644 --- a/main/source/mod/AIPlayers/AvHAICommander.cpp +++ b/main/source/mod/AIPlayers/AvHAICommander.cpp @@ -251,21 +251,21 @@ void AICOMM_IssueOrderForAssignedJob(AvHAIPlayer* pBot, ai_commander_order* Orde StructureFilter.ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING; StructureFilter.MaxSearchRadius = (bIsSiegeHiveOrder) ? UTIL_MetresToGoldSrcUnits(25.0f) : UTIL_MetresToGoldSrcUnits(10.0f); - AvHAIBuildableStructure* NearestToHive = AITAC_FindClosestDeployableToLocation(Hive->Location, &StructureFilter); + AvHAIBuildableStructure NearestToHive = AITAC_FindClosestDeployableToLocation(Hive->Location, &StructureFilter); - if (NearestToHive) + if (NearestToHive.IsValid()) { - if (!(NearestToHive->StructureStatusFlags & STRUCTURE_STATUS_COMPLETED)) + if (!(NearestToHive.StructureStatusFlags & STRUCTURE_STATUS_COMPLETED)) { - AICOMM_IssueBuildOrder(pBot, Order->Assignee, NearestToHive->edict); + AICOMM_IssueBuildOrder(pBot, Order->Assignee, NearestToHive.edict); Order->LastReminderTime = gpGlobals->time; - Order->LastPlayerDistance = vDist2DSq(Order->Assignee->v.origin, NearestToHive->Location); - Order->OrderLocation = NearestToHive->Location; + Order->LastPlayerDistance = vDist2DSq(Order->Assignee->v.origin, NearestToHive.Location); + Order->OrderLocation = NearestToHive.Location; return; } else { - Vector MoveLoc = UTIL_GetRandomPointOnNavmeshInRadius(GetBaseNavProfile(MARINE_BASE_NAV_PROFILE), NearestToHive->Location, UTIL_MetresToGoldSrcUnits(3.0f)); + Vector MoveLoc = UTIL_GetRandomPointOnNavmeshInRadius(GetBaseNavProfile(MARINE_BASE_NAV_PROFILE), NearestToHive.Location, UTIL_MetresToGoldSrcUnits(3.0f)); AICOMM_IssueMovementOrder(pBot, Order->Assignee, MoveLoc); Order->LastReminderTime = gpGlobals->time; @@ -692,9 +692,9 @@ bool AICOMM_IssueSecureHiveOrder(AvHAIPlayer* pBot, edict_t* Recipient, const Av TFFilter.ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING; TFFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(15.0f); - AvHAIBuildableStructure* TF = AITAC_FindClosestDeployableToLocation(HiveToSecure->FloorLocation, &TFFilter); + AvHAIBuildableStructure TF = AITAC_FindClosestDeployableToLocation(HiveToSecure->FloorLocation, &TFFilter); - if (!TF) + if (!TF.IsValid()) { Vector OrderLocation = UTIL_GetRandomPointOnNavmeshInRadius(GetBaseNavProfile(MARINE_BASE_NAV_PROFILE), HiveToSecure->FloorLocation, UTIL_MetresToGoldSrcUnits(5.0f)); @@ -708,7 +708,7 @@ bool AICOMM_IssueSecureHiveOrder(AvHAIPlayer* pBot, edict_t* Recipient, const Av TurretFilter.ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING; TurretFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(5.0f); - int NumTurrets = AITAC_GetNumDeployablesNearLocation(TF->Location, &TurretFilter); + int NumTurrets = AITAC_GetNumDeployablesNearLocation(TF.Location, &TurretFilter); if (NumTurrets < 5) { @@ -887,29 +887,22 @@ bool AICOMM_IsRequestValid(ai_commander_request* Request) return Requestor->v.health < Requestor->v.max_health; case BUILD_SHOTGUN: return !PlayerHasWeapon(PlayerRef, WEAPON_MARINE_SHOTGUN) - && !AITAC_ItemExistsInLocation(Requestor->v.origin, DEPLOYABLE_ITEM_SHOTGUN, RequestorTeam, AI_REACHABILITY_MARINE, 0.0f, UTIL_MetresToGoldSrcUnits(5.0f), false) - && AITAC_IsCompletedStructureOfTypeNearLocation(RequestorTeam, (STRUCTURE_MARINE_ARMOURY | STRUCTURE_MARINE_ADVARMOURY), Requestor->v.origin, UTIL_MetresToGoldSrcUnits(5.0f)) ; + && !AITAC_ItemExistsInLocation(Requestor->v.origin, DEPLOYABLE_ITEM_SHOTGUN, RequestorTeam, AI_REACHABILITY_MARINE, 0.0f, UTIL_MetresToGoldSrcUnits(5.0f), false) ; case BUILD_WELDER: return !PlayerHasWeapon(PlayerRef, WEAPON_MARINE_WELDER) - && !AITAC_ItemExistsInLocation(Requestor->v.origin, DEPLOYABLE_ITEM_WELDER, RequestorTeam, AI_REACHABILITY_MARINE, 0.0f, UTIL_MetresToGoldSrcUnits(5.0f), false) - && AITAC_IsCompletedStructureOfTypeNearLocation(RequestorTeam, (STRUCTURE_MARINE_ARMOURY | STRUCTURE_MARINE_ADVARMOURY), Requestor->v.origin, UTIL_MetresToGoldSrcUnits(5.0f)); + && !AITAC_ItemExistsInLocation(Requestor->v.origin, DEPLOYABLE_ITEM_WELDER, RequestorTeam, AI_REACHABILITY_MARINE, 0.0f, UTIL_MetresToGoldSrcUnits(5.0f), false); case BUILD_HMG: return !PlayerHasWeapon(PlayerRef, WEAPON_MARINE_HMG) - && !AITAC_ItemExistsInLocation(Requestor->v.origin, DEPLOYABLE_ITEM_HMG, RequestorTeam, AI_REACHABILITY_MARINE, 0.0f, UTIL_MetresToGoldSrcUnits(5.0f), false) - && AITAC_IsCompletedStructureOfTypeNearLocation(RequestorTeam, STRUCTURE_MARINE_ADVARMOURY, Requestor->v.origin, UTIL_MetresToGoldSrcUnits(5.0f)); + && !AITAC_ItemExistsInLocation(Requestor->v.origin, DEPLOYABLE_ITEM_HMG, RequestorTeam, AI_REACHABILITY_MARINE, 0.0f, UTIL_MetresToGoldSrcUnits(5.0f), false); case BUILD_GRENADE_GUN: return !PlayerHasWeapon(PlayerRef, WEAPON_MARINE_GL) - && !AITAC_ItemExistsInLocation(Requestor->v.origin, DEPLOYABLE_ITEM_GRENADELAUNCHER, RequestorTeam, AI_REACHABILITY_MARINE, 0.0f, UTIL_MetresToGoldSrcUnits(5.0f), false) - && AITAC_IsCompletedStructureOfTypeNearLocation(RequestorTeam, STRUCTURE_MARINE_ADVARMOURY, Requestor->v.origin, UTIL_MetresToGoldSrcUnits(5.0f)); + && !AITAC_ItemExistsInLocation(Requestor->v.origin, DEPLOYABLE_ITEM_GRENADELAUNCHER, RequestorTeam, AI_REACHABILITY_MARINE, 0.0f, UTIL_MetresToGoldSrcUnits(5.0f), false); case BUILD_MINES: return !PlayerHasWeapon(PlayerRef, WEAPON_MARINE_MINES) - && !AITAC_ItemExistsInLocation(Requestor->v.origin, DEPLOYABLE_ITEM_MINES, RequestorTeam, AI_REACHABILITY_MARINE, 0.0f, UTIL_MetresToGoldSrcUnits(5.0f), false) - && AITAC_IsCompletedStructureOfTypeNearLocation(RequestorTeam, (STRUCTURE_MARINE_ARMOURY | STRUCTURE_MARINE_ADVARMOURY), Requestor->v.origin, UTIL_MetresToGoldSrcUnits(5.0f)); + && !AITAC_ItemExistsInLocation(Requestor->v.origin, DEPLOYABLE_ITEM_MINES, RequestorTeam, AI_REACHABILITY_MARINE, 0.0f, UTIL_MetresToGoldSrcUnits(5.0f), false); case BUILD_CAT: return !IsPlayerBuffed(Requestor) - && !AITAC_ItemExistsInLocation(Requestor->v.origin, DEPLOYABLE_ITEM_CATALYSTS, RequestorTeam, AI_REACHABILITY_MARINE, 0.0f, UTIL_MetresToGoldSrcUnits(5.0f), false) - && AITAC_IsCompletedStructureOfTypeNearLocation(RequestorTeam, (STRUCTURE_MARINE_ARMOURY | STRUCTURE_MARINE_ADVARMOURY), Requestor->v.origin, 0.0f) - && AITAC_ResearchIsComplete(RequestorTeam, TECH_RESEARCH_CATALYSTS); + && !AITAC_ItemExistsInLocation(Requestor->v.origin, DEPLOYABLE_ITEM_CATALYSTS, RequestorTeam, AI_REACHABILITY_MARINE, 0.0f, UTIL_MetresToGoldSrcUnits(5.0f), false); case BUILD_PHASEGATE: return !AITAC_IsStructureOfTypeNearLocation(RequestorTeam, STRUCTURE_MARINE_PHASEGATE, Requestor->v.origin, UTIL_MetresToGoldSrcUnits(5.0f)); case BUILD_TURRET_FACTORY: @@ -954,9 +947,9 @@ bool AICOMM_CheckForNextBuildAction(AvHAIPlayer* pBot) StructureFilter.DeployableTypes = (STRUCTURE_MARINE_ARMOURY | STRUCTURE_MARINE_ADVARMOURY); - AvHAIBuildableStructure* BaseArmoury = AITAC_FindClosestDeployableToLocation(CommChair->v.origin, &StructureFilter); + AvHAIBuildableStructure BaseArmoury = AITAC_FindClosestDeployableToLocation(CommChair->v.origin, &StructureFilter); - if (!BaseArmoury && !FNullEnt(BaseBuilder)) + if (!BaseArmoury.IsValid() && !FNullEnt(BaseBuilder)) { Vector BuildLocation = AITAC_GetRandomBuildHintInLocation(STRUCTURE_MARINE_ARMOURY, CommChair->v.origin, UTIL_MetresToGoldSrcUnits(10.0f)); @@ -974,11 +967,11 @@ bool AICOMM_CheckForNextBuildAction(AvHAIPlayer* pBot) StructureFilter.DeployableTypes = STRUCTURE_MARINE_INFANTRYPORTAL; - AvHAIBuildableStructure* NearestInfantryPortal = AITAC_FindClosestDeployableToLocation(CommChair->v.origin, &StructureFilter); + AvHAIBuildableStructure NearestInfantryPortal = AITAC_FindClosestDeployableToLocation(CommChair->v.origin, &StructureFilter); - if (NearestInfantryPortal) + if (NearestInfantryPortal.IsValid()) { - BuildLocation = UTIL_GetRandomPointOnNavmeshInRadiusIgnoreReachability(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), NearestInfantryPortal->Location, UTIL_MetresToGoldSrcUnits(5.0f)); + BuildLocation = UTIL_GetRandomPointOnNavmeshInRadiusIgnoreReachability(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), NearestInfantryPortal.Location, UTIL_MetresToGoldSrcUnits(5.0f)); if (!vIsZero(BuildLocation)) { @@ -1177,15 +1170,15 @@ bool AICOMM_CheckForNextBuildAction(AvHAIPlayer* pBot) StructureFilter.IncludeStatusFlags = STRUCTURE_STATUS_COMPLETED; StructureFilter.ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING | STRUCTURE_STATUS_RESEARCHING; - AvHAIBuildableStructure* NearestArmoury = AITAC_FindClosestDeployableToLocation(CommChair->v.origin, &StructureFilter); + AvHAIBuildableStructure NearestArmoury = AITAC_FindClosestDeployableToLocation(CommChair->v.origin, &StructureFilter); - if (NearestArmoury) + if (NearestArmoury.IsValid()) { - bIsResearchingArmoury = UTIL_StructureIsUpgrading(NearestArmoury->edict); + bIsResearchingArmoury = UTIL_StructureIsUpgrading(NearestArmoury.edict); if (!bIsResearchingArmoury) { - if (AICOMM_UpgradeStructure(pBot, NearestArmoury)) + if (AICOMM_UpgradeStructure(pBot, &NearestArmoury)) { return true; } @@ -1254,11 +1247,11 @@ bool AICOMM_CheckForNextBuildAction(AvHAIPlayer* pBot) StructureFilter.ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING | STRUCTURE_STATUS_ELECTRIFIED; StructureFilter.MaxSearchRadius = 0.0f; - AvHAIBuildableStructure* ResTower = AITAC_FindFurthestDeployableFromLocation(CommChair->v.origin, &StructureFilter); + AvHAIBuildableStructure ResTower = AITAC_FindFurthestDeployableFromLocation(CommChair->v.origin, &StructureFilter); - if (ResTower && AITAC_ElectricalResearchIsAvailable(ResTower->edict)) + if (ResTower.IsValid() && AITAC_ElectricalResearchIsAvailable(ResTower.edict)) { - if (AICOMM_ResearchTech(pBot, ResTower, RESEARCH_ELECTRICAL)) + if (AICOMM_ResearchTech(pBot, &ResTower, RESEARCH_ELECTRICAL)) { return true; } @@ -1315,11 +1308,11 @@ bool AICOMM_CheckForNextSupplyAction(AvHAIPlayer* pBot) ArmouryFilter.IncludeStatusFlags = STRUCTURE_STATUS_COMPLETED; ArmouryFilter.ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING; - AvHAIBuildableStructure* NearestArmoury = AITAC_FindClosestDeployableToLocation(AITAC_GetTeamStartingLocation(CommanderTeam), &ArmouryFilter); + AvHAIBuildableStructure NearestArmoury = AITAC_FindClosestDeployableToLocation(AITAC_GetTeamStartingLocation(CommanderTeam), &ArmouryFilter); - if (NearestArmoury) + if (NearestArmoury.IsValid()) { - Vector DeployLocation = UTIL_GetRandomPointOnNavmeshInRadius(GetBaseNavProfile(MARINE_BASE_NAV_PROFILE), NearestArmoury->Location, UTIL_MetresToGoldSrcUnits(3.0f)); + Vector DeployLocation = UTIL_GetRandomPointOnNavmeshInRadius(GetBaseNavProfile(MARINE_BASE_NAV_PROFILE), NearestArmoury.Location, UTIL_MetresToGoldSrcUnits(3.0f)); bool bSuccess = AICOMM_DeployItem(pBot, DEPLOYABLE_ITEM_WELDER, DeployLocation); return bSuccess; @@ -1382,11 +1375,11 @@ bool AICOMM_CheckForNextSupplyAction(AvHAIPlayer* pBot) ArmouryFilter.IncludeStatusFlags = STRUCTURE_STATUS_COMPLETED; ArmouryFilter.ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING; - AvHAIBuildableStructure* NearestArmoury = AITAC_FindClosestDeployableToLocation(AITAC_GetTeamStartingLocation(CommanderTeam), &ArmouryFilter); + AvHAIBuildableStructure NearestArmoury = AITAC_FindClosestDeployableToLocation(AITAC_GetTeamStartingLocation(CommanderTeam), &ArmouryFilter); - if (NearestArmoury) + if (NearestArmoury.IsValid()) { - Vector DeployLocation = UTIL_GetRandomPointOnNavmeshInRadius(GetBaseNavProfile(MARINE_BASE_NAV_PROFILE), NearestArmoury->Location, UTIL_MetresToGoldSrcUnits(3.0f)); + Vector DeployLocation = UTIL_GetRandomPointOnNavmeshInRadius(GetBaseNavProfile(MARINE_BASE_NAV_PROFILE), NearestArmoury.Location, UTIL_MetresToGoldSrcUnits(3.0f)); bool bSuccess = AICOMM_DeployItem(pBot, DEPLOYABLE_ITEM_WELDER, DeployLocation); return bSuccess; @@ -1408,11 +1401,11 @@ bool AICOMM_CheckForNextSupplyAction(AvHAIPlayer* pBot) ArmouryFilter.IncludeStatusFlags = STRUCTURE_STATUS_COMPLETED; ArmouryFilter.ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING; - AvHAIBuildableStructure* NearestArmoury = AITAC_FindClosestDeployableToLocation(AITAC_GetTeamStartingLocation(CommanderTeam), &ArmouryFilter); + AvHAIBuildableStructure NearestArmoury = AITAC_FindClosestDeployableToLocation(AITAC_GetTeamStartingLocation(CommanderTeam), &ArmouryFilter); - if (NearestArmoury) + if (NearestArmoury.IsValid()) { - Vector DeployLocation = UTIL_GetRandomPointOnNavmeshInRadius(GetBaseNavProfile(MARINE_BASE_NAV_PROFILE), NearestArmoury->Location, UTIL_MetresToGoldSrcUnits(3.0f)); + Vector DeployLocation = UTIL_GetRandomPointOnNavmeshInRadius(GetBaseNavProfile(MARINE_BASE_NAV_PROFILE), NearestArmoury.Location, UTIL_MetresToGoldSrcUnits(3.0f)); bool bSuccess = AICOMM_DeployItem(pBot, DEPLOYABLE_ITEM_SHOTGUN, DeployLocation); return bSuccess; @@ -1440,16 +1433,16 @@ bool AICOMM_CheckForNextSupplyAction(AvHAIPlayer* pBot) MineStructures.ReachabilityTeam = CommanderTeam; MineStructures.ReachabilityFlags = AI_REACHABILITY_MARINE; - vector MineableStructures = AITAC_FindAllDeployables(ZERO_VECTOR, &MineStructures); + vector MineableStructures = AITAC_FindAllDeployables(ZERO_VECTOR, &MineStructures); MineStructures.DeployableTypes = STRUCTURE_MARINE_DEPLOYEDMINE; MineStructures.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(3.0f); for (auto it = MineableStructures.begin(); it != MineableStructures.end(); it++) { - AvHAIBuildableStructure* ThisStructure = (*it); + AvHAIBuildableStructure ThisStructure = (*it); - int NumMines = AITAC_GetNumDeployablesNearLocation(ThisStructure->Location, &MineStructures); + int NumMines = AITAC_GetNumDeployablesNearLocation(ThisStructure.Location, &MineStructures); if (NumMines < 2) { @@ -1469,11 +1462,11 @@ bool AICOMM_CheckForNextSupplyAction(AvHAIPlayer* pBot) ArmouryFilter.IncludeStatusFlags = STRUCTURE_STATUS_COMPLETED; ArmouryFilter.ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING; - AvHAIBuildableStructure* NearestArmoury = AITAC_FindClosestDeployableToLocation(AITAC_GetTeamStartingLocation(CommanderTeam), &ArmouryFilter); + AvHAIBuildableStructure NearestArmoury = AITAC_FindClosestDeployableToLocation(AITAC_GetTeamStartingLocation(CommanderTeam), &ArmouryFilter); - if (NearestArmoury) + if (NearestArmoury.IsValid()) { - Vector DeployLocation = UTIL_GetRandomPointOnNavmeshInRadius(GetBaseNavProfile(MARINE_BASE_NAV_PROFILE), NearestArmoury->Location, UTIL_MetresToGoldSrcUnits(3.0f)); + Vector DeployLocation = UTIL_GetRandomPointOnNavmeshInRadius(GetBaseNavProfile(MARINE_BASE_NAV_PROFILE), NearestArmoury.Location, UTIL_MetresToGoldSrcUnits(3.0f)); bool bSuccess = AICOMM_DeployItem(pBot, DEPLOYABLE_ITEM_MINES, DeployLocation); return bSuccess; @@ -1488,20 +1481,20 @@ bool AICOMM_CheckForNextSupplyAction(AvHAIPlayer* pBot) StructureFilter.IncludeStatusFlags = STRUCTURE_STATUS_COMPLETED; StructureFilter.ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING; - AvHAIBuildableStructure* NearestAdvArmoury = AITAC_FindClosestDeployableToLocation(AITAC_GetTeamStartingLocation(CommanderTeam), &StructureFilter); + AvHAIBuildableStructure NearestAdvArmoury = AITAC_FindClosestDeployableToLocation(AITAC_GetTeamStartingLocation(CommanderTeam), &StructureFilter); StructureFilter.DeployableTypes = STRUCTURE_MARINE_PROTOTYPELAB; - AvHAIBuildableStructure* NearestPrototypeLab = AITAC_FindClosestDeployableToLocation(AITAC_GetTeamStartingLocation(CommanderTeam), &StructureFilter); + AvHAIBuildableStructure NearestPrototypeLab = AITAC_FindClosestDeployableToLocation(AITAC_GetTeamStartingLocation(CommanderTeam), &StructureFilter); - if (!NearestAdvArmoury || !NearestPrototypeLab) { return false; } + if (!NearestAdvArmoury.IsValid() || !NearestPrototypeLab.IsValid()) { return false; } - AvHAIDroppedItem* ExistingHA = AITAC_FindClosestItemToLocation(NearestPrototypeLab->Location, DEPLOYABLE_ITEM_HEAVYARMOUR, CommanderTeam, AI_REACHABILITY_MARINE, 0.0f, UTIL_MetresToGoldSrcUnits(5.0f), false); - AvHAIDroppedItem* ExistingHMG = AITAC_FindClosestItemToLocation(NearestAdvArmoury->Location, DEPLOYABLE_ITEM_HMG, CommanderTeam, AI_REACHABILITY_MARINE, 0.0f, UTIL_MetresToGoldSrcUnits(5.0f), false); - AvHAIDroppedItem* ExistingWelder = AITAC_FindClosestItemToLocation(NearestAdvArmoury->Location, DEPLOYABLE_ITEM_WELDER, CommanderTeam, AI_REACHABILITY_MARINE, 0.0f, UTIL_MetresToGoldSrcUnits(5.0f), false); + AvHAIDroppedItem* ExistingHA = AITAC_FindClosestItemToLocation(NearestPrototypeLab.Location, DEPLOYABLE_ITEM_HEAVYARMOUR, CommanderTeam, AI_REACHABILITY_MARINE, 0.0f, UTIL_MetresToGoldSrcUnits(5.0f), false); + AvHAIDroppedItem* ExistingHMG = AITAC_FindClosestItemToLocation(NearestAdvArmoury.Location, DEPLOYABLE_ITEM_HMG, CommanderTeam, AI_REACHABILITY_MARINE, 0.0f, UTIL_MetresToGoldSrcUnits(5.0f), false); + AvHAIDroppedItem* ExistingWelder = AITAC_FindClosestItemToLocation(NearestAdvArmoury.Location, DEPLOYABLE_ITEM_WELDER, CommanderTeam, AI_REACHABILITY_MARINE, 0.0f, UTIL_MetresToGoldSrcUnits(5.0f), false); if (ExistingHA && ExistingHMG && ExistingWelder) { return false; } - vector NearbyPlayers = AITAC_GetAllPlayersOfClassInArea(CommanderTeam, NearestAdvArmoury->Location, UTIL_MetresToGoldSrcUnits(10.0f), false, pBot->Edict, AVH_USER3_MARINE_PLAYER); + vector NearbyPlayers = AITAC_GetAllPlayersOfClassInArea(CommanderTeam, NearestAdvArmoury.Location, UTIL_MetresToGoldSrcUnits(10.0f), false, pBot->Edict, AVH_USER3_MARINE_PLAYER); bool bDropWeapon = false; bool bDropWelder = false; @@ -1530,11 +1523,11 @@ bool AICOMM_CheckForNextSupplyAction(AvHAIPlayer* pBot) if (!ExistingHA && !bDropWelder && !bDropWeapon) { - Vector DeployLocation = UTIL_GetRandomPointOnNavmeshInRadiusIgnoreReachability(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), NearestPrototypeLab->Location, UTIL_MetresToGoldSrcUnits(3.0f)); + Vector DeployLocation = UTIL_GetRandomPointOnNavmeshInRadiusIgnoreReachability(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), NearestPrototypeLab.Location, UTIL_MetresToGoldSrcUnits(3.0f)); if (vIsZero(DeployLocation)) { - DeployLocation = UTIL_GetRandomPointOnNavmeshInRadius(GetBaseNavProfile(MARINE_BASE_NAV_PROFILE), NearestPrototypeLab->Location, UTIL_MetresToGoldSrcUnits(3.0f)); + DeployLocation = UTIL_GetRandomPointOnNavmeshInRadius(GetBaseNavProfile(MARINE_BASE_NAV_PROFILE), NearestPrototypeLab.Location, UTIL_MetresToGoldSrcUnits(3.0f)); } bool bSuccess = AICOMM_DeployItem(pBot, DEPLOYABLE_ITEM_HEAVYARMOUR, DeployLocation); @@ -1544,11 +1537,11 @@ bool AICOMM_CheckForNextSupplyAction(AvHAIPlayer* pBot) if (bDropWeapon && !ExistingHMG) { - Vector DeployLocation = UTIL_GetRandomPointOnNavmeshInRadiusIgnoreReachability(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), NearestAdvArmoury->Location, UTIL_MetresToGoldSrcUnits(3.0f)); + Vector DeployLocation = UTIL_GetRandomPointOnNavmeshInRadiusIgnoreReachability(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), NearestAdvArmoury.Location, UTIL_MetresToGoldSrcUnits(3.0f)); if (vIsZero(DeployLocation)) { - DeployLocation = UTIL_GetRandomPointOnNavmeshInRadius(GetBaseNavProfile(MARINE_BASE_NAV_PROFILE), NearestAdvArmoury->Location, UTIL_MetresToGoldSrcUnits(3.0f)); + DeployLocation = UTIL_GetRandomPointOnNavmeshInRadius(GetBaseNavProfile(MARINE_BASE_NAV_PROFILE), NearestAdvArmoury.Location, UTIL_MetresToGoldSrcUnits(3.0f)); } bool bSuccess = AICOMM_DeployItem(pBot, DEPLOYABLE_ITEM_HMG, DeployLocation); @@ -1558,11 +1551,11 @@ bool AICOMM_CheckForNextSupplyAction(AvHAIPlayer* pBot) if (bDropWelder && !ExistingWelder) { - Vector DeployLocation = UTIL_GetRandomPointOnNavmeshInRadiusIgnoreReachability(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), NearestAdvArmoury->Location, UTIL_MetresToGoldSrcUnits(3.0f)); + Vector DeployLocation = UTIL_GetRandomPointOnNavmeshInRadiusIgnoreReachability(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), NearestAdvArmoury.Location, UTIL_MetresToGoldSrcUnits(3.0f)); if (vIsZero(DeployLocation)) { - DeployLocation = UTIL_GetRandomPointOnNavmeshInRadius(GetBaseNavProfile(MARINE_BASE_NAV_PROFILE), NearestAdvArmoury->Location, UTIL_MetresToGoldSrcUnits(3.0f)); + DeployLocation = UTIL_GetRandomPointOnNavmeshInRadius(GetBaseNavProfile(MARINE_BASE_NAV_PROFILE), NearestAdvArmoury.Location, UTIL_MetresToGoldSrcUnits(3.0f)); } bool bSuccess = AICOMM_DeployItem(pBot, DEPLOYABLE_ITEM_WELDER, DeployLocation); @@ -1592,18 +1585,18 @@ bool AICOMM_CheckForNextResearchAction(AvHAIPlayer* pBot) TFFilter.ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING | STRUCTURE_STATUS_ELECTRIFIED; TFFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(15.0f); - AvHAIBuildableStructure* NearestTF = AITAC_FindClosestDeployableToLocation(Hive->FloorLocation, &TFFilter); + AvHAIBuildableStructure NearestTF = AITAC_FindClosestDeployableToLocation(Hive->FloorLocation, &TFFilter); - if (NearestTF) + if (NearestTF.IsValid()) { TFFilter.DeployableTypes = STRUCTURE_MARINE_TURRET; TFFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(5.0f); - int NumTurrets = AITAC_GetNumDeployablesNearLocation(NearestTF->Location, &TFFilter); + int NumTurrets = AITAC_GetNumDeployablesNearLocation(NearestTF.Location, &TFFilter); if (NumTurrets > 0) { - if (AICOMM_ResearchTech(pBot, NearestTF, RESEARCH_ELECTRICAL)) + if (AICOMM_ResearchTech(pBot, &NearestTF, RESEARCH_ELECTRICAL)) { return true; } @@ -1617,9 +1610,9 @@ bool AICOMM_CheckForNextResearchAction(AvHAIPlayer* pBot) edict_t* Tower = Hive->HiveResNodeRef->ActiveTowerEntity; if (!FNullEnt(Tower) && UTIL_StructureIsFullyBuilt(Tower) && !UTIL_IsStructureElectrified(Tower)) { - AvHAIBuildableStructure* ResTower = AITAC_GetDeployableRefFromEdict(Tower); + AvHAIBuildableStructure ResTower = AITAC_GetDeployableFromEdict(Tower); - if (ResTower && AICOMM_ResearchTech(pBot, ResTower, RESEARCH_ELECTRICAL)) + if (ResTower.IsValid() && AICOMM_ResearchTech(pBot, &ResTower, RESEARCH_ELECTRICAL)) { return true; } @@ -1641,156 +1634,114 @@ bool AICOMM_CheckForNextResearchAction(AvHAIPlayer* pBot) StructureFilter.DeployableTypes = STRUCTURE_MARINE_ARMOURY | STRUCTURE_MARINE_ADVARMOURY; StructureFilter.ExcludeStatusFlags |= STRUCTURE_STATUS_RESEARCHING; - AvHAIBuildableStructure* Armoury = AITAC_FindClosestDeployableToLocation(AITAC_GetTeamStartingLocation(CommanderTeam), &StructureFilter); + AvHAIBuildableStructure Armoury = AITAC_FindClosestDeployableToLocation(AITAC_GetTeamStartingLocation(CommanderTeam), &StructureFilter); - if (Armoury) + if (Armoury.IsValid()) { - return AICOMM_ResearchTech(pBot, Armoury, RESEARCH_GRENADES); + return AICOMM_ResearchTech(pBot, &Armoury, RESEARCH_GRENADES); } } + StructureFilter.DeployableTypes = STRUCTURE_MARINE_ARMSLAB; + StructureFilter.ExcludeStatusFlags |= STRUCTURE_STATUS_RESEARCHING; + + AvHAIBuildableStructure ArmsLab = AITAC_FindClosestDeployableToLocation(AITAC_GetTeamStartingLocation(CommanderTeam), &StructureFilter); + if (AITAC_MarineResearchIsAvailable(CommanderTeam, RESEARCH_ARMOR_ONE)) { - StructureFilter.DeployableTypes = STRUCTURE_MARINE_ARMSLAB; - StructureFilter.ExcludeStatusFlags |= STRUCTURE_STATUS_RESEARCHING; - - AvHAIBuildableStructure* ArmsLab = AITAC_FindClosestDeployableToLocation(AITAC_GetTeamStartingLocation(CommanderTeam), &StructureFilter); - - if (ArmsLab) + if (ArmsLab.IsValid()) { - return AICOMM_ResearchTech(pBot, ArmsLab, RESEARCH_ARMOR_ONE); + return AICOMM_ResearchTech(pBot, &ArmsLab, RESEARCH_ARMOR_ONE); } } if (AITAC_MarineResearchIsAvailable(CommanderTeam, RESEARCH_WEAPONS_ONE)) { - StructureFilter.DeployableTypes = STRUCTURE_MARINE_ARMSLAB; - StructureFilter.ExcludeStatusFlags |= STRUCTURE_STATUS_RESEARCHING; - - AvHAIBuildableStructure* ArmsLab = AITAC_FindClosestDeployableToLocation(AITAC_GetTeamStartingLocation(CommanderTeam), &StructureFilter); - - if (ArmsLab) + if (ArmsLab.IsValid()) { - return AICOMM_ResearchTech(pBot, ArmsLab, RESEARCH_WEAPONS_ONE); + return AICOMM_ResearchTech(pBot, &ArmsLab, RESEARCH_WEAPONS_ONE); } } + StructureFilter.DeployableTypes = STRUCTURE_MARINE_OBSERVATORY; + StructureFilter.ExcludeStatusFlags |= STRUCTURE_STATUS_RESEARCHING; + + AvHAIBuildableStructure Observatory = AITAC_FindClosestDeployableToLocation(AITAC_GetTeamStartingLocation(CommanderTeam), &StructureFilter); + if (AITAC_MarineResearchIsAvailable(CommanderTeam, RESEARCH_PHASETECH)) { - StructureFilter.DeployableTypes = STRUCTURE_MARINE_OBSERVATORY; - StructureFilter.ExcludeStatusFlags |= STRUCTURE_STATUS_RESEARCHING; - - AvHAIBuildableStructure* Observatory = AITAC_FindClosestDeployableToLocation(AITAC_GetTeamStartingLocation(CommanderTeam), &StructureFilter); - - if (Observatory) + if (Observatory.IsValid()) { - return AICOMM_ResearchTech(pBot, Observatory, RESEARCH_PHASETECH); + return AICOMM_ResearchTech(pBot, &Observatory, RESEARCH_PHASETECH); } } if (AITAC_MarineResearchIsAvailable(CommanderTeam, RESEARCH_MOTIONTRACK)) { - StructureFilter.DeployableTypes = STRUCTURE_MARINE_OBSERVATORY; - StructureFilter.ExcludeStatusFlags |= STRUCTURE_STATUS_RESEARCHING; - - AvHAIBuildableStructure* Observatory = AITAC_FindClosestDeployableToLocation(AITAC_GetTeamStartingLocation(CommanderTeam), &StructureFilter); - - if (Observatory) + if (Observatory.IsValid()) { - return AICOMM_ResearchTech(pBot, Observatory, RESEARCH_MOTIONTRACK); + return AICOMM_ResearchTech(pBot, &Observatory, RESEARCH_MOTIONTRACK); } } if (AITAC_MarineResearchIsAvailable(CommanderTeam, RESEARCH_ARMOR_TWO)) { - StructureFilter.DeployableTypes = STRUCTURE_MARINE_ARMSLAB; - StructureFilter.ExcludeStatusFlags |= STRUCTURE_STATUS_RESEARCHING; - - AvHAIBuildableStructure* ArmsLab = AITAC_FindClosestDeployableToLocation(AITAC_GetTeamStartingLocation(CommanderTeam), &StructureFilter); - - if (ArmsLab) + if (ArmsLab.IsValid()) { - return AICOMM_ResearchTech(pBot, ArmsLab, RESEARCH_ARMOR_TWO); + return AICOMM_ResearchTech(pBot, &ArmsLab, RESEARCH_ARMOR_TWO); } } if (AITAC_MarineResearchIsAvailable(CommanderTeam, RESEARCH_WEAPONS_TWO)) { - - StructureFilter.DeployableTypes = STRUCTURE_MARINE_ARMSLAB; - StructureFilter.ExcludeStatusFlags |= STRUCTURE_STATUS_RESEARCHING; - - AvHAIBuildableStructure* ArmsLab = AITAC_FindClosestDeployableToLocation(AITAC_GetTeamStartingLocation(CommanderTeam), &StructureFilter); - - if (ArmsLab) + if (ArmsLab.IsValid()) { - return AICOMM_ResearchTech(pBot, ArmsLab, RESEARCH_WEAPONS_TWO); + return AICOMM_ResearchTech(pBot, &ArmsLab, RESEARCH_WEAPONS_TWO); } } if (AITAC_MarineResearchIsAvailable(CommanderTeam, RESEARCH_CATALYSTS)) { - StructureFilter.DeployableTypes = STRUCTURE_MARINE_ARMSLAB; - StructureFilter.ExcludeStatusFlags |= STRUCTURE_STATUS_RESEARCHING; - - AvHAIBuildableStructure* ArmsLab = AITAC_FindClosestDeployableToLocation(AITAC_GetTeamStartingLocation(CommanderTeam), &StructureFilter); - - if (ArmsLab) + if (ArmsLab.IsValid()) { - return AICOMM_ResearchTech(pBot, ArmsLab, RESEARCH_CATALYSTS); + return AICOMM_ResearchTech(pBot, &ArmsLab, RESEARCH_CATALYSTS); } } + StructureFilter.DeployableTypes = STRUCTURE_MARINE_PROTOTYPELAB; + StructureFilter.ExcludeStatusFlags |= STRUCTURE_STATUS_RESEARCHING; + + AvHAIBuildableStructure ProtoLab = AITAC_FindClosestDeployableToLocation(AITAC_GetTeamStartingLocation(CommanderTeam), &StructureFilter); + if (AITAC_MarineResearchIsAvailable(CommanderTeam, RESEARCH_HEAVYARMOR)) { - StructureFilter.DeployableTypes = STRUCTURE_MARINE_PROTOTYPELAB; - StructureFilter.ExcludeStatusFlags |= STRUCTURE_STATUS_RESEARCHING; - - AvHAIBuildableStructure* ProtoLab = AITAC_FindClosestDeployableToLocation(AITAC_GetTeamStartingLocation(CommanderTeam), &StructureFilter); - - if (ProtoLab) + if (ProtoLab.IsValid()) { - return AICOMM_ResearchTech(pBot, ProtoLab, RESEARCH_HEAVYARMOR); + return AICOMM_ResearchTech(pBot, &ProtoLab, RESEARCH_HEAVYARMOR); } } if (AITAC_MarineResearchIsAvailable(CommanderTeam, RESEARCH_JETPACKS)) { - StructureFilter.DeployableTypes = STRUCTURE_MARINE_PROTOTYPELAB; - StructureFilter.ExcludeStatusFlags |= STRUCTURE_STATUS_RESEARCHING; - - AvHAIBuildableStructure* ProtoLab = AITAC_FindClosestDeployableToLocation(AITAC_GetTeamStartingLocation(CommanderTeam), &StructureFilter); - - if (ProtoLab) + if (ProtoLab.IsValid()) { - return AICOMM_ResearchTech(pBot, ProtoLab, RESEARCH_JETPACKS); + return AICOMM_ResearchTech(pBot, &ProtoLab, RESEARCH_JETPACKS); } } if (AITAC_MarineResearchIsAvailable(CommanderTeam, RESEARCH_ARMOR_THREE)) { - - StructureFilter.DeployableTypes = STRUCTURE_MARINE_ARMSLAB; - StructureFilter.ExcludeStatusFlags |= STRUCTURE_STATUS_RESEARCHING; - - AvHAIBuildableStructure* ArmsLab = AITAC_FindClosestDeployableToLocation(AITAC_GetTeamStartingLocation(CommanderTeam), &StructureFilter); - - if (ArmsLab) + if (ArmsLab.IsValid()) { - return AICOMM_ResearchTech(pBot, ArmsLab, RESEARCH_ARMOR_THREE); + return AICOMM_ResearchTech(pBot, &ArmsLab, RESEARCH_ARMOR_THREE); } } if (AITAC_MarineResearchIsAvailable(CommanderTeam, RESEARCH_WEAPONS_THREE)) { - StructureFilter.DeployableTypes = STRUCTURE_MARINE_ARMSLAB; - StructureFilter.ExcludeStatusFlags |= STRUCTURE_STATUS_RESEARCHING; - - AvHAIBuildableStructure* ArmsLab = AITAC_FindClosestDeployableToLocation(AITAC_GetTeamStartingLocation(CommanderTeam), &StructureFilter); - - if (ArmsLab) + if (ArmsLab.IsValid()) { - return AICOMM_ResearchTech(pBot, ArmsLab, RESEARCH_WEAPONS_THREE); + return AICOMM_ResearchTech(pBot, &ArmsLab, RESEARCH_WEAPONS_THREE); } } @@ -1823,12 +1774,12 @@ const AvHAIHiveDefinition* AICOMM_GetHiveSiegeOpportunityNearestLocation(AvHAIPl StructureFilter.IncludeStatusFlags = STRUCTURE_STATUS_COMPLETED; StructureFilter.ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING; - AvHAIBuildableStructure* BuiltPhaseGate = AITAC_FindClosestDeployableToLocation(Hive->Location, &StructureFilter); + AvHAIBuildableStructure BuiltPhaseGate = AITAC_FindClosestDeployableToLocation(Hive->Location, &StructureFilter); // If we have a phase gate already in place, then keep building as long as someone is there. If we don't have a phase gate, only build if there is a marine who isn't sighted by the enemy (to allow element of surprise) - if (BuiltPhaseGate) + if (BuiltPhaseGate.IsValid()) { - int NumBuilders = AITAC_GetNumPlayersOfTeamInArea(CommanderTeam, BuiltPhaseGate->Location, UTIL_MetresToGoldSrcUnits(5.0f), false, CommanderBot->Edict, AVH_USER3_COMMANDER_PLAYER); + int NumBuilders = AITAC_GetNumPlayersOfTeamInArea(CommanderTeam, BuiltPhaseGate.Location, UTIL_MetresToGoldSrcUnits(5.0f), false, CommanderBot->Edict, AVH_USER3_COMMANDER_PLAYER); if (NumBuilders == 0) { continue; } } @@ -1892,7 +1843,7 @@ bool AICOMM_PerformNextSiegeHiveAction(AvHAIPlayer* pBot, const AvHAIHiveDefinit StructureFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(25.0f); Vector SiegeLocation = ZERO_VECTOR; - AvHAIBuildableStructure* ExistingPG = nullptr; + AvHAIBuildableStructure ExistingPG; edict_t* NearestBuilder = nullptr; @@ -1902,22 +1853,22 @@ bool AICOMM_PerformNextSiegeHiveAction(AvHAIPlayer* pBot, const AvHAIHiveDefinit ExistingPG = AITAC_FindClosestDeployableToLocation(HiveToSiege->Location, &StructureFilter); - if (ExistingPG) + if (ExistingPG.IsValid()) { - SiegeLocation = ExistingPG->Location; + SiegeLocation = ExistingPG.Location; } } StructureFilter.DeployableTypes = STRUCTURE_MARINE_TURRETFACTORY | STRUCTURE_MARINE_ADVTURRETFACTORY; - AvHAIBuildableStructure* ExistingTF = AITAC_FindClosestDeployableToLocation(HiveToSiege->Location, &StructureFilter); + AvHAIBuildableStructure ExistingTF = AITAC_FindClosestDeployableToLocation(HiveToSiege->Location, &StructureFilter); if (vIsZero(SiegeLocation)) { - if (ExistingTF) + if (ExistingTF.IsValid()) { - SiegeLocation = ExistingTF->Location; + SiegeLocation = ExistingTF.Location; } else { @@ -1949,56 +1900,56 @@ bool AICOMM_PerformNextSiegeHiveAction(AvHAIPlayer* pBot, const AvHAIHiveDefinit } } - if (!ExistingPG) + if (!ExistingPG.IsValid()) { return AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_PHASEGATE, NextBuildPosition, STRUCTURE_PURPOSE_SIEGE); } - if (ExistingPG && !(ExistingPG->StructureStatusFlags & STRUCTURE_STATUS_COMPLETED)) { return false; } + if (ExistingPG.IsValid() && !(ExistingPG.StructureStatusFlags & STRUCTURE_STATUS_COMPLETED)) { return false; } - if (!ExistingTF) + if (!ExistingTF.IsValid()) { if (vDist2DSq(NextBuildPosition, HiveToSiege->Location) > sqrf(UTIL_MetresToGoldSrcUnits(20.0f))) { return true; } return AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_TURRETFACTORY, NextBuildPosition, STRUCTURE_PURPOSE_SIEGE); } - if (ExistingTF && !(ExistingTF->StructureStatusFlags & STRUCTURE_STATUS_COMPLETED)) { return false; } + if (ExistingTF.IsValid() && !(ExistingTF.StructureStatusFlags & STRUCTURE_STATUS_COMPLETED)) { return false; } StructureFilter.DeployableTypes = STRUCTURE_MARINE_ARMOURY | STRUCTURE_MARINE_ADVARMOURY; StructureFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(10.0f); - AvHAIBuildableStructure* ExistingArmoury = AITAC_FindClosestDeployableToLocation(SiegeLocation, &StructureFilter); + AvHAIBuildableStructure ExistingArmoury = AITAC_FindClosestDeployableToLocation(SiegeLocation, &StructureFilter); - if (!ExistingArmoury) + if (!ExistingArmoury.IsValid()) { return AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_ARMOURY, NextBuildPosition, STRUCTURE_PURPOSE_SIEGE); } - if (ExistingTF->StructureType != STRUCTURE_MARINE_ADVTURRETFACTORY) + if (ExistingTF.StructureType != STRUCTURE_MARINE_ADVTURRETFACTORY) { - return AICOMM_UpgradeStructure(pBot, ExistingTF); + return AICOMM_UpgradeStructure(pBot, &ExistingTF); } StructureFilter.DeployableTypes = STRUCTURE_MARINE_SIEGETURRET; StructureFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(5.0f); - int NumSiegeTurrets = AITAC_GetNumDeployablesNearLocation(ExistingTF->Location, &StructureFilter); + int NumSiegeTurrets = AITAC_GetNumDeployablesNearLocation(ExistingTF.Location, &StructureFilter); - if (NumSiegeTurrets == 0 || (NumSiegeTurrets < 5 && UTIL_IsStructureElectrified(ExistingTF->edict))) + if (NumSiegeTurrets == 0 || (NumSiegeTurrets < 5 && UTIL_IsStructureElectrified(ExistingTF.edict))) { - SiegeLocation = ExistingTF->Location; + SiegeLocation = ExistingTF.Location; - NextBuildPosition = UTIL_GetRandomPointOnNavmeshInRadius(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), ExistingTF->Location, UTIL_MetresToGoldSrcUnits(5.0f)); + NextBuildPosition = UTIL_GetRandomPointOnNavmeshInRadius(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), ExistingTF.Location, UTIL_MetresToGoldSrcUnits(5.0f)); if (vIsZero(NextBuildPosition)) { // Reduce radius to avoid putting it on the other side of a wall or something - NextBuildPosition = UTIL_GetRandomPointOnNavmeshInRadiusIgnoreReachability(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), ExistingTF->Location, UTIL_MetresToGoldSrcUnits(3.0f)); + NextBuildPosition = UTIL_GetRandomPointOnNavmeshInRadiusIgnoreReachability(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), ExistingTF.Location, UTIL_MetresToGoldSrcUnits(3.0f)); if (vIsZero(NextBuildPosition)) { // Fall-back, this could end up putting the structure in dodgy spots but better than not placing it at all - NextBuildPosition = UTIL_GetRandomPointOnNavmeshInRadius(GetBaseNavProfile(MARINE_BASE_NAV_PROFILE), ExistingTF->Location, UTIL_MetresToGoldSrcUnits(5.0f)); + NextBuildPosition = UTIL_GetRandomPointOnNavmeshInRadius(GetBaseNavProfile(MARINE_BASE_NAV_PROFILE), ExistingTF.Location, UTIL_MetresToGoldSrcUnits(5.0f)); } } @@ -2007,9 +1958,9 @@ bool AICOMM_PerformNextSiegeHiveAction(AvHAIPlayer* pBot, const AvHAIHiveDefinit return AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_SIEGETURRET, NextBuildPosition, STRUCTURE_PURPOSE_SIEGE); } - if (!UTIL_IsStructureElectrified(ExistingTF->edict)) + if (!UTIL_IsStructureElectrified(ExistingTF.edict)) { - return AICOMM_ResearchTech(pBot, ExistingTF, RESEARCH_ELECTRICAL); + return AICOMM_ResearchTech(pBot, &ExistingTF, RESEARCH_ELECTRICAL); } return false; @@ -2026,11 +1977,11 @@ bool AICOMM_PerformNextSecureHiveAction(AvHAIPlayer* pBot, const AvHAIHiveDefini StructureFilter.ReachabilityTeam = pBot->Player->GetTeam(); StructureFilter.ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING; - AvHAIBuildableStructure* ExistingStructure = AITAC_FindClosestDeployableToLocation(HiveToSecure->FloorLocation, &StructureFilter); - AvHAIBuildableStructure* ExistingPG = nullptr; - AvHAIBuildableStructure* ExistingTF = nullptr; + AvHAIBuildableStructure ExistingStructure = AITAC_FindClosestDeployableToLocation(HiveToSecure->FloorLocation, &StructureFilter); + AvHAIBuildableStructure ExistingPG; + AvHAIBuildableStructure ExistingTF; - Vector OutpostLocation = (ExistingStructure) ? ExistingStructure->Location : HiveToSecure->FloorLocation; + Vector OutpostLocation = (ExistingStructure.IsValid()) ? ExistingStructure.Location : HiveToSecure->FloorLocation; if (HiveToSecure->HiveResNodeRef && HiveToSecure->HiveResNodeRef->OwningTeam == TEAM_IND) { @@ -2038,9 +1989,9 @@ bool AICOMM_PerformNextSecureHiveAction(AvHAIPlayer* pBot, const AvHAIHiveDefini return true; } - if (ExistingStructure) + if (ExistingStructure.IsValid()) { - if (ExistingStructure->StructureType == STRUCTURE_MARINE_PHASEGATE) + if (ExistingStructure.StructureType == STRUCTURE_MARINE_PHASEGATE) { ExistingPG = ExistingStructure; } @@ -2052,13 +2003,13 @@ bool AICOMM_PerformNextSecureHiveAction(AvHAIPlayer* pBot, const AvHAIHiveDefini if (AITAC_PhaseGatesAvailable(pBot->Player->GetTeam())) { - if (!ExistingPG) + if (!ExistingPG.IsValid()) { StructureFilter.DeployableTypes = STRUCTURE_MARINE_PHASEGATE; ExistingPG = AITAC_FindClosestDeployableToLocation(OutpostLocation, &StructureFilter); - if (!ExistingPG) + if (!ExistingPG.IsValid()) { Vector BuildLocation = UTIL_GetRandomPointOnNavmeshInRadius(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), OutpostLocation, UTIL_MetresToGoldSrcUnits(5.0f)); @@ -2077,13 +2028,13 @@ bool AICOMM_PerformNextSecureHiveAction(AvHAIPlayer* pBot, const AvHAIHiveDefini } } - if (!ExistingTF) + if (!ExistingTF.IsValid()) { StructureFilter.DeployableTypes = STRUCTURE_MARINE_TURRETFACTORY; ExistingTF = AITAC_FindClosestDeployableToLocation(OutpostLocation, &StructureFilter); - if (!ExistingTF) + if (!ExistingTF.IsValid()) { Vector BuildLocation = UTIL_GetRandomPointOnNavmeshInRadius(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), OutpostLocation, UTIL_MetresToGoldSrcUnits(3.0f)); @@ -2104,11 +2055,11 @@ bool AICOMM_PerformNextSecureHiveAction(AvHAIPlayer* pBot, const AvHAIHiveDefini StructureFilter.DeployableTypes = STRUCTURE_MARINE_TURRET; StructureFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(10.0f); - int NumTurrets = AITAC_GetNumDeployablesNearLocation(ExistingTF->Location, &StructureFilter); + int NumTurrets = AITAC_GetNumDeployablesNearLocation(ExistingTF.Location, &StructureFilter); if (NumTurrets < 5) { - Vector BuildLocation = UTIL_GetRandomPointOnNavmeshInRadiusIgnoreReachability(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), ExistingTF->Location, UTIL_MetresToGoldSrcUnits(3.0f)); + Vector BuildLocation = UTIL_GetRandomPointOnNavmeshInRadiusIgnoreReachability(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), ExistingTF.Location, UTIL_MetresToGoldSrcUnits(3.0f)); if (!vIsZero(BuildLocation)) { @@ -2137,12 +2088,12 @@ bool AICOMM_BuildInfantryPortal(AvHAIPlayer* pBot, edict_t* CommChair) ExistingPortalFilter.ReachabilityFlags = AI_REACHABILITY_MARINE; ExistingPortalFilter.ReachabilityTeam = pBot->Player->GetTeam(); - AvHAIBuildableStructure* ExistingInfantryPortal = AITAC_FindClosestDeployableToLocation(CommChair->v.origin, &ExistingPortalFilter); + AvHAIBuildableStructure ExistingInfantryPortal = AITAC_FindClosestDeployableToLocation(CommChair->v.origin, &ExistingPortalFilter); // First see if we can place the next infantry portal next to the first one - if (ExistingInfantryPortal) + if (ExistingInfantryPortal.IsValid()) { - BuildLocation = UTIL_GetRandomPointOnNavmeshInDonutIgnoreReachability(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), ExistingInfantryPortal->edict->v.origin, UTIL_MetresToGoldSrcUnits(2.0f), UTIL_MetresToGoldSrcUnits(3.0f)); + BuildLocation = UTIL_GetRandomPointOnNavmeshInDonutIgnoreReachability(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), ExistingInfantryPortal.edict->v.origin, UTIL_MetresToGoldSrcUnits(2.0f), UTIL_MetresToGoldSrcUnits(3.0f)); if (!vIsZero(BuildLocation)) { @@ -2204,12 +2155,12 @@ bool AICOMM_CheckForNextRecycleAction(AvHAIPlayer* pBot) UnreachableFilter.ReachabilityFlags = AI_REACHABILITY_UNREACHABLE; UnreachableFilter.ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING | STRUCTURE_STATUS_RESEARCHING; - AvHAIBuildableStructure* UnreachableStructure = AITAC_FindClosestDeployableToLocation(AITAC_GetCommChairLocation(pBot->Player->GetTeam()), &UnreachableFilter); + AvHAIBuildableStructure UnreachableStructure = AITAC_FindClosestDeployableToLocation(AITAC_GetCommChairLocation(pBot->Player->GetTeam()), &UnreachableFilter); // Recycle any structures which are unreachable (e.g. sunk below the map) - if (UnreachableStructure) + if (UnreachableStructure.IsValid()) { - return AICOMM_RecycleStructure(pBot, UnreachableStructure); + return AICOMM_RecycleStructure(pBot, &UnreachableStructure); } vector Hives = AITAC_GetAllHives(); @@ -2229,7 +2180,7 @@ bool AICOMM_CheckForNextRecycleAction(AvHAIPlayer* pBot) SecuringStructuresFilter.ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING; SecuringStructuresFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(15.0f); - vector NearbySecuringStructures = AITAC_FindAllDeployables(Hive->Location, &SecuringStructuresFilter); + vector NearbySecuringStructures = AITAC_FindAllDeployables(Hive->Location, &SecuringStructuresFilter); bool bHiveHasPG = false; bool bHiveHasTF = false; @@ -2237,21 +2188,21 @@ bool AICOMM_CheckForNextRecycleAction(AvHAIPlayer* pBot) for (auto SecureIt = NearbySecuringStructures.begin(); SecureIt != NearbySecuringStructures.end(); SecureIt++) { - AvHAIBuildableStructure* Structure = (*SecureIt); + AvHAIBuildableStructure Structure = (*SecureIt); - if (Structure->Purpose == STRUCTURE_PURPOSE_FORTIFY) + if (Structure.Purpose == STRUCTURE_PURPOSE_FORTIFY) { - if (Structure->StructureType == STRUCTURE_MARINE_PHASEGATE) + if (Structure.StructureType == STRUCTURE_MARINE_PHASEGATE) { bHiveHasPG = true; } - if (Structure->StructureType == STRUCTURE_MARINE_TURRETFACTORY || Structure->StructureType == STRUCTURE_MARINE_ADVTURRETFACTORY) + if (Structure.StructureType == STRUCTURE_MARINE_TURRETFACTORY || Structure.StructureType == STRUCTURE_MARINE_ADVTURRETFACTORY) { bHiveHasTF = true; } - if (Structure->StructureType == STRUCTURE_MARINE_TURRET) + if (Structure.StructureType == STRUCTURE_MARINE_TURRET) { bHiveHasTurret = true; } @@ -2269,20 +2220,20 @@ bool AICOMM_CheckForNextRecycleAction(AvHAIPlayer* pBot) RedundantFilter.ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING; RedundantFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(30.0f); - vector NearbyStructures = AITAC_FindAllDeployables(Hive->Location, &RedundantFilter); + vector NearbyStructures = AITAC_FindAllDeployables(Hive->Location, &RedundantFilter); for (auto StructIt = NearbyStructures.begin(); StructIt != NearbyStructures.end(); StructIt++) { - AvHAIBuildableStructure* Structure = (*StructIt); + AvHAIBuildableStructure Structure = (*StructIt); - if (Structure->Purpose == STRUCTURE_PURPOSE_SIEGE) + if (Structure.Purpose == STRUCTURE_PURPOSE_SIEGE) { // Check for the potential situation where we can siege more than one hive at a time - const AvHAIHiveDefinition* NearestHive = AITAC_GetNonEmptyHiveNearestLocation(Structure->Location); + const AvHAIHiveDefinition* NearestHive = AITAC_GetNonEmptyHiveNearestLocation(Structure.Location); - if (!NearestHive || vDist2DSq(NearestHive->Location, Structure->Location) > sqrf(UTIL_MetresToGoldSrcUnits(25.0f))) + if (!NearestHive || vDist2DSq(NearestHive->Location, Structure.Location) > sqrf(UTIL_MetresToGoldSrcUnits(25.0f))) { - return AICOMM_RecycleStructure(pBot, Structure); + return AICOMM_RecycleStructure(pBot, &Structure); } } } @@ -2455,8 +2406,27 @@ bool AICOMM_CheckForNextSupportAction(AvHAIPlayer* pBot) if (NextRequest->RequestType == BUILD_CAT) { + if (!AITAC_ResearchIsComplete(CommanderTeam, TECH_RESEARCH_CATALYSTS)) + { + char msg[128]; + sprintf(msg, "We haven't researched catalysts yet, %s. Ask again later.", STRING(Requestor->v.netname)); + BotSay(pBot, true, 0.5f, msg); + NextRequest->bResponded = true; + return false; + } + + if (!AITAC_IsCompletedStructureOfTypeNearLocation(CommanderTeam, (STRUCTURE_MARINE_ARMOURY | STRUCTURE_MARINE_ADVARMOURY), ZERO_VECTOR, 0.0f)) + { + char msg[128]; + sprintf(msg, "Don't have an armory anymore, %s. We need to build one.", STRING(Requestor->v.netname)); + BotSay(pBot, true, 0.5f, msg); + NextRequest->bResponded = true; + return false; + } + + Vector DeployLocation = UTIL_GetRandomPointOnNavmeshInRadius(GetBaseNavProfile(MARINE_BASE_NAV_PROFILE), Requestor->v.origin, UTIL_MetresToGoldSrcUnits(2.0f)); - bool bSuccess = AICOMM_DeployItem(pBot, DEPLOYABLE_ITEM_AMMO, DeployLocation); + bool bSuccess = AICOMM_DeployItem(pBot, DEPLOYABLE_ITEM_CATALYSTS, DeployLocation); if (bSuccess) { @@ -2502,9 +2472,9 @@ bool AICOMM_CheckForNextSupportAction(AvHAIPlayer* pBot) ArmouryFilter.ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING; ArmouryFilter.MaxSearchRadius = BALANCE_VAR(kArmoryBuildDistance); - AvHAIBuildableStructure* NearestArmoury = AITAC_FindClosestDeployableToLocation(Requestor->v.origin, &ArmouryFilter); + AvHAIBuildableStructure NearestArmoury = AITAC_FindClosestDeployableToLocation(Requestor->v.origin, &ArmouryFilter); - if (!NearestArmoury) + if (!NearestArmoury.IsValid()) { if (!NextRequest->bAcknowledged) { @@ -2532,7 +2502,7 @@ bool AICOMM_CheckForNextSupportAction(AvHAIPlayer* pBot) Vector IdealDeployLocation = Requestor->v.origin + (UTIL_GetForwardVector2D(Requestor->v.angles) * 75.0f); Vector ProjectedDeployLocation = AdjustPointForPathfinding(IdealDeployLocation); - if (vDist2DSq(ProjectedDeployLocation, NearestArmoury->Location) < BALANCE_VAR(kArmoryBuildDistance)) + if (vDist2DSq(ProjectedDeployLocation, NearestArmoury.Location) < BALANCE_VAR(kArmoryBuildDistance)) { bool bSuccess = AICOMM_DeployItem(pBot, ItemToDrop, ProjectedDeployLocation); @@ -2543,11 +2513,11 @@ bool AICOMM_CheckForNextSupportAction(AvHAIPlayer* pBot) } } - Vector DeployLocation = UTIL_GetRandomPointOnNavmeshInRadius(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), NearestArmoury->Location, UTIL_MetresToGoldSrcUnits(4.0f)); + Vector DeployLocation = UTIL_GetRandomPointOnNavmeshInRadius(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), NearestArmoury.Location, UTIL_MetresToGoldSrcUnits(4.0f)); if (vIsZero(DeployLocation)) { - DeployLocation = UTIL_GetRandomPointOnNavmeshInRadius(GetBaseNavProfile(MARINE_BASE_NAV_PROFILE), NearestArmoury->Location, UTIL_MetresToGoldSrcUnits(4.0f)); + DeployLocation = UTIL_GetRandomPointOnNavmeshInRadius(GetBaseNavProfile(MARINE_BASE_NAV_PROFILE), NearestArmoury.Location, UTIL_MetresToGoldSrcUnits(4.0f)); } if (vIsZero(DeployLocation)) @@ -2578,20 +2548,28 @@ bool AICOMM_CheckForNextSupportAction(AvHAIPlayer* pBot) ArmouryFilter.DeployableTypes = STRUCTURE_MARINE_ADVARMOURY; ArmouryFilter.IncludeStatusFlags = STRUCTURE_STATUS_COMPLETED; ArmouryFilter.ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING; - ArmouryFilter.MaxSearchRadius = BALANCE_VAR(kArmoryBuildDistance); - AvHAIBuildableStructure* NearestArmoury = AITAC_FindClosestDeployableToLocation(Requestor->v.origin, &ArmouryFilter); + AvHAIBuildableStructure NearestArmoury = AITAC_FindClosestDeployableToLocation(Requestor->v.origin, &ArmouryFilter); - if (!NearestArmoury) + if (!NearestArmoury.IsValid()) + { + char msg[128]; + sprintf(msg, "We don't have an adv armory yet %s, ask again later.", STRING(Requestor->v.netname)); + BotSay(pBot, true, 0.5f, msg); + NextRequest->bResponded = true; + + return false; + } + + if (vDist2DSq(Requestor->v.origin, NearestArmoury.Location) > sqrf(BALANCE_VAR(kArmoryBuildDistance))) { if (!NextRequest->bAcknowledged) { char msg[128]; - sprintf(msg, "Get to an advanced armory %s, and I'll drop it for you.", STRING(Requestor->v.netname)); + sprintf(msg, "Get near the adv armory %s, and I will drop it for you.", STRING(Requestor->v.netname)); BotSay(pBot, true, 0.5f, msg); NextRequest->bAcknowledged = true; } - return false; } @@ -2610,7 +2588,7 @@ bool AICOMM_CheckForNextSupportAction(AvHAIPlayer* pBot) Vector IdealDeployLocation = Requestor->v.origin + (UTIL_GetForwardVector2D(Requestor->v.angles) * 75.0f); Vector ProjectedDeployLocation = AdjustPointForPathfinding(IdealDeployLocation); - if (vDist2DSq(ProjectedDeployLocation, NearestArmoury->Location) < BALANCE_VAR(kArmoryBuildDistance)) + if (vDist2DSq(ProjectedDeployLocation, NearestArmoury.Location) < BALANCE_VAR(kArmoryBuildDistance)) { bool bSuccess = AICOMM_DeployItem(pBot, ItemToDrop, ProjectedDeployLocation); @@ -2621,11 +2599,11 @@ bool AICOMM_CheckForNextSupportAction(AvHAIPlayer* pBot) } } - Vector DeployLocation = UTIL_GetRandomPointOnNavmeshInRadius(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), NearestArmoury->Location, UTIL_MetresToGoldSrcUnits(4.0f)); + Vector DeployLocation = UTIL_GetRandomPointOnNavmeshInRadius(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), NearestArmoury.Location, UTIL_MetresToGoldSrcUnits(4.0f)); if (vIsZero(DeployLocation)) { - DeployLocation = UTIL_GetRandomPointOnNavmeshInRadius(GetBaseNavProfile(MARINE_BASE_NAV_PROFILE), NearestArmoury->Location, UTIL_MetresToGoldSrcUnits(4.0f)); + DeployLocation = UTIL_GetRandomPointOnNavmeshInRadius(GetBaseNavProfile(MARINE_BASE_NAV_PROFILE), NearestArmoury.Location, UTIL_MetresToGoldSrcUnits(4.0f)); } if (vIsZero(DeployLocation)) @@ -2647,94 +2625,235 @@ bool AICOMM_CheckForNextSupportAction(AvHAIPlayer* pBot) if (NextRequest->RequestType == BUILD_PHASEGATE) { - if (pBot->Player->GetResources() < BALANCE_VAR(kPhaseGateCost)) { return false; } - - Vector DeployLocation = UTIL_GetRandomPointOnNavmeshInRadius(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), Requestor->v.origin, UTIL_MetresToGoldSrcUnits(5.0f)); - - if (vIsZero(DeployLocation)) - { - DeployLocation = UTIL_GetRandomPointOnNavmeshInRadiusIgnoreReachability(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), Requestor->v.origin, UTIL_MetresToGoldSrcUnits(5.0f)); - } - - if (vIsZero(DeployLocation)) + if (!AITAC_ResearchIsComplete(CommanderTeam, TECH_RESEARCH_PHASETECH)) { + char msg[128]; + sprintf(msg, "We haven't got phase tech yet, %s. Ask again later.", STRING(Requestor->v.netname)); + BotSay(pBot, true, 0.5f, msg); NextRequest->bResponded = true; return false; } - bool bSuccess = AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_PHASEGATE, DeployLocation); + if (pBot->Player->GetResources() < BALANCE_VAR(kPhaseGateCost)) + { + if (!NextRequest->bAcknowledged) + { + char msg[128]; + sprintf(msg, "Just waiting on resources, %s. Will drop asap.", STRING(Requestor->v.netname)); + BotSay(pBot, true, 0.5f, msg); + NextRequest->bAcknowledged = true; + return false; + } + return false; + } - NextRequest->ResponseAttempts++; + Vector IdealDeployLocation = Requestor->v.origin + (UTIL_GetForwardVector2D(Requestor->v.angles) * 75.0f); + Vector ProjectedDeployLocation = AdjustPointForPathfinding(IdealDeployLocation, GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE)); - NextRequest->bResponded = bSuccess; - return true; + if (!vIsZero(ProjectedDeployLocation)) + { + bool bSuccess = AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_PHASEGATE, ProjectedDeployLocation, STRUCTURE_PURPOSE_NONE); + + if (bSuccess) + { + NextRequest->bResponded = true; + return true; + } + } + + Vector DeployLocation = UTIL_GetRandomPointOnNavmeshInRadius(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), Requestor->v.origin, UTIL_MetresToGoldSrcUnits(5.0f)); + + if (!vIsZero(DeployLocation)) + { + bool bSuccess = AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_PHASEGATE, DeployLocation, STRUCTURE_PURPOSE_NONE); + + if (bSuccess) + { + NextRequest->bResponded = true; + return true; + } + } + + DeployLocation = UTIL_GetRandomPointOnNavmeshInRadiusIgnoreReachability(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), Requestor->v.origin, UTIL_MetresToGoldSrcUnits(5.0f)); + + if (!vIsZero(DeployLocation)) + { + bool bSuccess = AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_PHASEGATE, DeployLocation, STRUCTURE_PURPOSE_NONE); + + if (bSuccess) + { + NextRequest->bResponded = true; + return true; + } + else + { + char msg[128]; + sprintf(msg, "I can't find a good deploy spot, %s. Try again elsewhere.", STRING(Requestor->v.netname)); + BotSay(pBot, true, 0.5f, msg); + NextRequest->bResponded = true; + return false; + } + } + else + { + char msg[128]; + sprintf(msg, "I can't find a good deploy spot, %s. Try again elsewhere.", STRING(Requestor->v.netname)); + BotSay(pBot, true, 0.5f, msg); + NextRequest->bResponded = true; + return false; + } + + return false; } if (NextRequest->RequestType == BUILD_TURRET_FACTORY) { - if (pBot->Player->GetResources() < BALANCE_VAR(kTurretFactoryCost)) { return false; } + if (pBot->Player->GetResources() < BALANCE_VAR(kTurretFactoryCost)) + { + if (!NextRequest->bAcknowledged) + { + char msg[128]; + sprintf(msg, "Just waiting on resources, %s. Will drop asap.", STRING(Requestor->v.netname)); + BotSay(pBot, true, 0.5f, msg); + NextRequest->bAcknowledged = true; + return false; + } + return false; + } + + Vector IdealDeployLocation = Requestor->v.origin + (UTIL_GetForwardVector2D(Requestor->v.angles) * 75.0f); + Vector ProjectedDeployLocation = AdjustPointForPathfinding(IdealDeployLocation, GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE)); + + if (!vIsZero(ProjectedDeployLocation)) + { + bool bSuccess = AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_TURRETFACTORY, ProjectedDeployLocation, STRUCTURE_PURPOSE_NONE); + + if (bSuccess) + { + NextRequest->bResponded = true; + return true; + } + } Vector DeployLocation = UTIL_GetRandomPointOnNavmeshInRadius(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), Requestor->v.origin, UTIL_MetresToGoldSrcUnits(5.0f)); - if (vIsZero(DeployLocation)) + if (!vIsZero(DeployLocation)) { - DeployLocation = UTIL_GetRandomPointOnNavmeshInRadiusIgnoreReachability(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), Requestor->v.origin, UTIL_MetresToGoldSrcUnits(5.0f)); + bool bSuccess = AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_TURRETFACTORY, DeployLocation, STRUCTURE_PURPOSE_NONE); + + if (bSuccess) + { + NextRequest->bResponded = true; + return true; + } } - if (vIsZero(DeployLocation)) + DeployLocation = UTIL_GetRandomPointOnNavmeshInRadiusIgnoreReachability(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), Requestor->v.origin, UTIL_MetresToGoldSrcUnits(5.0f)); + + if (!vIsZero(DeployLocation)) { + bool bSuccess = AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_TURRETFACTORY, DeployLocation, STRUCTURE_PURPOSE_NONE); + + if (bSuccess) + { + NextRequest->bResponded = true; + return true; + } + else + { + char msg[128]; + sprintf(msg, "I can't find a good deploy spot, %s. Try again elsewhere.", STRING(Requestor->v.netname)); + BotSay(pBot, true, 0.5f, msg); + NextRequest->bResponded = true; + return false; + } + } + else + { + char msg[128]; + sprintf(msg, "I can't find a good deploy spot, %s. Try again elsewhere.", STRING(Requestor->v.netname)); + BotSay(pBot, true, 0.5f, msg); NextRequest->bResponded = true; return false; } - bool bSuccess = AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_TURRETFACTORY, DeployLocation); - - NextRequest->ResponseAttempts++; - - NextRequest->bResponded = bSuccess; - return true; + return false; } if (NextRequest->RequestType == BUILD_TURRET) { - if (pBot->Player->GetResources() < BALANCE_VAR(kSentryCost)) { return false; } - - DeployableSearchFilter TFFilter; - TFFilter.DeployableTeam = CommanderTeam; - TFFilter.DeployableTypes = (STRUCTURE_MARINE_TURRETFACTORY | STRUCTURE_MARINE_ADVTURRETFACTORY); - TFFilter.IncludeStatusFlags = STRUCTURE_STATUS_COMPLETED; - TFFilter.ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING; - TFFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(10.0f); - - AvHAIBuildableStructure* NearestTF = AITAC_FindClosestDeployableToLocation(Requestor->v.origin, &TFFilter); - - if (!NearestTF) + if (pBot->Player->GetResources() < BALANCE_VAR(kSentryCost)) { + if (!NextRequest->bAcknowledged) + { + char msg[128]; + sprintf(msg, "Just waiting on resources, %s. Will drop asap.", STRING(Requestor->v.netname)); + BotSay(pBot, true, 0.5f, msg); + NextRequest->bAcknowledged = true; + return false; + } + return false; + } + + Vector IdealDeployLocation = Requestor->v.origin + (UTIL_GetForwardVector2D(Requestor->v.angles) * 75.0f); + Vector ProjectedDeployLocation = AdjustPointForPathfinding(IdealDeployLocation, GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE)); + + if (!vIsZero(ProjectedDeployLocation)) + { + bool bSuccess = AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_TURRET, ProjectedDeployLocation, STRUCTURE_PURPOSE_NONE); + + if (bSuccess) + { + NextRequest->bResponded = true; + return true; + } + } + + Vector DeployLocation = UTIL_GetRandomPointOnNavmeshInRadius(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), Requestor->v.origin, UTIL_MetresToGoldSrcUnits(5.0f)); + + if (!vIsZero(DeployLocation)) + { + bool bSuccess = AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_TURRET, DeployLocation, STRUCTURE_PURPOSE_NONE); + + if (bSuccess) + { + NextRequest->bResponded = true; + return true; + } + } + + DeployLocation = UTIL_GetRandomPointOnNavmeshInRadiusIgnoreReachability(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), Requestor->v.origin, UTIL_MetresToGoldSrcUnits(5.0f)); + + if (!vIsZero(DeployLocation)) + { + bool bSuccess = AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_TURRET, DeployLocation, STRUCTURE_PURPOSE_NONE); + + if (bSuccess) + { + NextRequest->bResponded = true; + return true; + } + else + { + char msg[128]; + sprintf(msg, "I can't find a good deploy spot, %s. Try again elsewhere.", STRING(Requestor->v.netname)); + BotSay(pBot, true, 0.5f, msg); + NextRequest->bResponded = true; + return false; + } + } + else + { + char msg[128]; + sprintf(msg, "I can't find a good deploy spot, %s. Try again elsewhere.", STRING(Requestor->v.netname)); + BotSay(pBot, true, 0.5f, msg); NextRequest->bResponded = true; return false; } - Vector DeployLocation = UTIL_GetRandomPointOnNavmeshInRadius(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), NearestTF->Location, UTIL_MetresToGoldSrcUnits(5.0f)); - - if (vIsZero(DeployLocation)) - { - DeployLocation = UTIL_GetRandomPointOnNavmeshInRadiusIgnoreReachability(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), NearestTF->Location, UTIL_MetresToGoldSrcUnits(5.0f)); - } - - if (vIsZero(DeployLocation)) - { - NextRequest->bResponded = true; - return false; - } - - bool bSuccess = AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_TURRET, DeployLocation); - - NextRequest->ResponseAttempts++; - - NextRequest->bResponded = bSuccess; - return true; + return false; } @@ -2815,11 +2934,11 @@ void AICOMM_CommanderThink(AvHAIPlayer* pBot) StructureFilter.ReachabilityTeam = pBot->Player->GetTeam(); StructureFilter.ExcludeStatusFlags = STRUCTURE_STATUS_COMPLETED | STRUCTURE_STATUS_RECYCLING; - AvHAIBuildableStructure* NearestUnbuiltStructure = AITAC_FindClosestDeployableToLocation(AITAC_GetCommChairLocation(pBot->Player->GetTeam()), &StructureFilter); + AvHAIBuildableStructure NearestUnbuiltStructure = AITAC_FindClosestDeployableToLocation(AITAC_GetCommChairLocation(pBot->Player->GetTeam()), &StructureFilter); - if (NearestUnbuiltStructure) + if (NearestUnbuiltStructure.IsValid()) { - AITASK_SetBuildTask(pBot, &pBot->PrimaryBotTask, NearestUnbuiltStructure->edict, false); + AITASK_SetBuildTask(pBot, &pBot->PrimaryBotTask, NearestUnbuiltStructure.edict, false); } BotProgressTask(pBot, &pBot->PrimaryBotTask); @@ -2947,14 +3066,14 @@ const AvHAIHiveDefinition* AICOMM_GetEmptyHiveOpportunityNearestLocation(AvHAIPl StructureFilter.DeployableTypes = STRUCTURE_MARINE_PHASEGATE | STRUCTURE_MARINE_TURRETFACTORY | STRUCTURE_MARINE_ADVTURRETFACTORY; StructureFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(10.0f); - AvHAIBuildableStructure* ExistingStructure = AITAC_FindClosestDeployableToLocation(Hive->FloorLocation, &StructureFilter); + AvHAIBuildableStructure ExistingStructure = AITAC_FindClosestDeployableToLocation(Hive->FloorLocation, &StructureFilter); - if (ExistingStructure && UTIL_QuickTrace(nullptr, UTIL_GetCentreOfEntity(ExistingStructure->edict), Hive->Location)) + if (ExistingStructure.IsValid() && UTIL_QuickTrace(nullptr, UTIL_GetCentreOfEntity(ExistingStructure.edict), Hive->Location)) { - SecureLocation = ExistingStructure->Location; + SecureLocation = ExistingStructure.Location; } - float MarineDist = (ExistingStructure) ? UTIL_MetresToGoldSrcUnits(5.0f) : UTIL_MetresToGoldSrcUnits(10.0f); + float MarineDist = (ExistingStructure.IsValid()) ? UTIL_MetresToGoldSrcUnits(5.0f) : UTIL_MetresToGoldSrcUnits(10.0f); if (AITAC_GetNearestHiddenPlayerInLocation(CommanderTeam, SecureLocation, MarineDist) == nullptr) { continue; } @@ -3012,26 +3131,26 @@ bool AICOMM_IsHiveFullySecured(AvHAIPlayer* CommanderBot, const AvHAIHiveDefinit SearchFilter.ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING; SearchFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(15.0f); - vector HiveStructures = AITAC_FindAllDeployables(Hive->FloorLocation, &SearchFilter); + vector HiveStructures = AITAC_FindAllDeployables(Hive->FloorLocation, &SearchFilter); for (auto it = HiveStructures.begin(); it != HiveStructures.end(); it++) { - AvHAIBuildableStructure* Structure = (*it); + AvHAIBuildableStructure Structure = (*it); - if (Structure->StructureType == STRUCTURE_MARINE_PHASEGATE) + if (Structure.StructureType == STRUCTURE_MARINE_PHASEGATE) { bHasPhaseGate = true; } - if (Structure->StructureType == STRUCTURE_MARINE_TURRETFACTORY || Structure->StructureType == STRUCTURE_MARINE_ADVTURRETFACTORY) + if (Structure.StructureType == STRUCTURE_MARINE_TURRETFACTORY || Structure.StructureType == STRUCTURE_MARINE_ADVTURRETFACTORY) { bHasTurretFactory = true; - bTurretFactoryElectrified = (Structure->StructureStatusFlags & STRUCTURE_STATUS_ELECTRIFIED); + bTurretFactoryElectrified = (Structure.StructureStatusFlags & STRUCTURE_STATUS_ELECTRIFIED); SearchFilter.DeployableTypes = STRUCTURE_MARINE_TURRET; SearchFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(8.0f); - NumTurrets = AITAC_GetNumDeployablesNearLocation(Structure->Location, &SearchFilter); + NumTurrets = AITAC_GetNumDeployablesNearLocation(Structure.Location, &SearchFilter); } @@ -3054,11 +3173,11 @@ bool AICOMM_ShouldBeacon(AvHAIPlayer* pBot) ObservatoryFilter.DeployableTypes = STRUCTURE_MARINE_OBSERVATORY; ObservatoryFilter.DeployableTeam = BotTeam; ObservatoryFilter.IncludeStatusFlags = STRUCTURE_STATUS_COMPLETED; - ObservatoryFilter.ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING; + ObservatoryFilter.ExcludeStatusFlags = (STRUCTURE_STATUS_RECYCLING | STRUCTURE_STATUS_RESEARCHING); - AvHAIBuildableStructure* Observatory = AITAC_FindClosestDeployableToLocation(ZERO_VECTOR, &ObservatoryFilter); + AvHAIBuildableStructure Observatory = AITAC_FindClosestDeployableToLocation(ZERO_VECTOR, &ObservatoryFilter); - if (!Observatory || Observatory->StructureStatusFlags == STRUCTURE_STATUS_RESEARCHING) { return false; } + if (!Observatory.IsValid()) { return false; } AvHTeamNumber EnemyTeam = AIMGR_GetEnemyTeam(BotTeam); @@ -3070,21 +3189,21 @@ bool AICOMM_ShouldBeacon(AvHAIPlayer* pBot) BaseStructureFilter.IncludeStatusFlags = STRUCTURE_STATUS_COMPLETED; BaseStructureFilter.ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING; - vector BaseStructures = AITAC_FindAllDeployables(BaseLocation, &BaseStructureFilter); + vector BaseStructures = AITAC_FindAllDeployables(BaseLocation, &BaseStructureFilter); bool bHasInfantryPortals = false; bool bBaseUnderAttack = false; for (auto it = BaseStructures.begin(); it != BaseStructures.end(); it++) { - AvHAIBuildableStructure* ThisStructure = (*it); + AvHAIBuildableStructure ThisStructure = (*it); - if (ThisStructure->StructureStatusFlags & STRUCTURE_STATUS_UNDERATTACK) + if (ThisStructure.StructureStatusFlags & STRUCTURE_STATUS_UNDERATTACK) { bBaseUnderAttack = true; } - if (ThisStructure->StructureType == STRUCTURE_MARINE_INFANTRYPORTAL) + if (ThisStructure.StructureType == STRUCTURE_MARINE_INFANTRYPORTAL) { bHasInfantryPortals = true; } @@ -3110,7 +3229,7 @@ bool AICOMM_ShouldBeacon(AvHAIPlayer* pBot) if (EnemyStrength >= 3 && EnemyStrength >= DefenderStrength * 3) { - return AICOMM_ResearchTech(pBot, Observatory, RESEARCH_DISTRESSBEACON); + return AICOMM_ResearchTech(pBot, &Observatory, RESEARCH_DISTRESSBEACON); } return false; diff --git a/main/source/mod/AIPlayers/AvHAIConstants.h b/main/source/mod/AIPlayers/AvHAIConstants.h index 3373a43c..025dd7c4 100644 --- a/main/source/mod/AIPlayers/AvHAIConstants.h +++ b/main/source/mod/AIPlayers/AvHAIConstants.h @@ -344,6 +344,8 @@ typedef struct _AVH_AI_BUILDABLE_STRUCTURE StructurePurpose Purpose = STRUCTURE_PURPOSE_NONE; bool bReachabilityMarkedDirty = false; // If true, reachability flags will be recalculated for this structure + bool IsValid() { return !FNullEnt(edict) && !edict->free && !(edict->v.flags & EF_NODRAW) && edict->v.deadflag == DEAD_NO; } + } AvHAIBuildableStructure; // Any kind of pickup that has been dropped either by the commander or by a player @@ -735,7 +737,7 @@ typedef struct AVH_AI_PLAYER AvHAICombatStrategy CurrentCombatStrategy = COMBAT_STRATEGY_ATTACK; edict_t* CurrentEnemyRef = nullptr; - vector DangerTurrets; + vector DangerTurrets; AvHAIPlayerTask* CurrentTask = nullptr; // Bot's current task they're performing AvHAIPlayerTask PrimaryBotTask; diff --git a/main/source/mod/AIPlayers/AvHAINavigation.cpp b/main/source/mod/AIPlayers/AvHAINavigation.cpp index 7c90e8df..c2631957 100644 --- a/main/source/mod/AIPlayers/AvHAINavigation.cpp +++ b/main/source/mod/AIPlayers/AvHAINavigation.cpp @@ -3405,28 +3405,28 @@ void StructureBlockedMove(AvHAIPlayer* pBot, const Vector StartPoint, const Vect BlockingFilter.DeployableTeam = AIMGR_GetEnemyTeam(pBot->Player->GetTeam()); BlockingFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(3.0f); - vector BlockingStructures = AITAC_FindAllDeployables(pBot->Edict->v.origin, &BlockingFilter); + vector BlockingStructures = AITAC_FindAllDeployables(pBot->Edict->v.origin, &BlockingFilter); - AvHAIBuildableStructure* CulpritStructure = nullptr; + AvHAIBuildableStructure CulpritStructure; float MinDist = 0.0f; for (auto it = BlockingStructures.begin(); it != BlockingStructures.end(); it++) { - AvHAIBuildableStructure* ThisStructure = (*it); + AvHAIBuildableStructure ThisStructure = (*it); - float ThisDist = vDistanceFromLine2DSq(StartPoint, EndPoint, ThisStructure->Location); + float ThisDist = vDistanceFromLine2DSq(StartPoint, EndPoint, ThisStructure.Location); - if (!CulpritStructure || ThisDist < MinDist) + if (FNullEnt(CulpritStructure.edict) || ThisDist < MinDist) { CulpritStructure = ThisStructure; } } - if (CulpritStructure) + if (CulpritStructure.IsValid()) { - BotMoveLookAt(pBot, CulpritStructure->Location); + BotMoveLookAt(pBot, CulpritStructure.Location); - AvHAIWeapon AttackWeapon = (IsPlayerAlien(pBot->Edict)) ? BotAlienChooseBestWeaponForStructure(pBot, CulpritStructure->edict) : BotMarineChooseBestWeaponForStructure(pBot, CulpritStructure->edict); + AvHAIWeapon AttackWeapon = (IsPlayerAlien(pBot->Edict)) ? BotAlienChooseBestWeaponForStructure(pBot, CulpritStructure.edict) : BotMarineChooseBestWeaponForStructure(pBot, CulpritStructure.edict); if (GetPlayerCurrentWeapon(pBot->Player) != AttackWeapon) { @@ -3434,7 +3434,7 @@ void StructureBlockedMove(AvHAIPlayer* pBot, const Vector StartPoint, const Vect } else { - BotShootTarget(pBot, AttackWeapon, CulpritStructure->edict); + BotShootTarget(pBot, AttackWeapon, CulpritStructure.edict); } } } @@ -4161,26 +4161,26 @@ void PhaseGateMove(AvHAIPlayer* pBot, const Vector StartPoint, const Vector EndP PGFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(2.0f); PGFilter.IncludeStatusFlags = STRUCTURE_STATUS_COMPLETED; - AvHAIBuildableStructure* NearestPhaseGate = AITAC_FindClosestDeployableToLocation(pBot->Edict->v.origin, &PGFilter); + AvHAIBuildableStructure NearestPhaseGate = AITAC_FindClosestDeployableToLocation(pBot->Edict->v.origin, &PGFilter); - if (!NearestPhaseGate) { return; } + if (!NearestPhaseGate.IsValid()) { return; } - if (IsPlayerInUseRange(pBot->Edict, NearestPhaseGate->edict)) + if (IsPlayerInUseRange(pBot->Edict, NearestPhaseGate.edict)) { - BotMoveLookAt(pBot, NearestPhaseGate->edict->v.origin); + BotMoveLookAt(pBot, NearestPhaseGate.edict->v.origin); pBot->desiredMovementDir = g_vecZero; - BotUseObject(pBot, NearestPhaseGate->edict, false); + BotUseObject(pBot, NearestPhaseGate.edict, false); - if (vDist2DSq(pBot->Edict->v.origin, NearestPhaseGate->edict->v.origin) < sqrf(16.0f)) + if (vDist2DSq(pBot->Edict->v.origin, NearestPhaseGate.edict->v.origin) < sqrf(16.0f)) { - pBot->desiredMovementDir = UTIL_GetForwardVector2D(NearestPhaseGate->edict->v.angles); + pBot->desiredMovementDir = UTIL_GetForwardVector2D(NearestPhaseGate.edict->v.angles); } return; } else { - pBot->desiredMovementDir = UTIL_GetVectorNormal2D(NearestPhaseGate->edict->v.origin - pBot->Edict->v.origin); + pBot->desiredMovementDir = UTIL_GetVectorNormal2D(NearestPhaseGate.edict->v.origin - pBot->Edict->v.origin); } } diff --git a/main/source/mod/AIPlayers/AvHAIPlayer.cpp b/main/source/mod/AIPlayers/AvHAIPlayer.cpp index bd57da9c..3b58c3c9 100644 --- a/main/source/mod/AIPlayers/AvHAIPlayer.cpp +++ b/main/source/mod/AIPlayers/AvHAIPlayer.cpp @@ -1501,12 +1501,12 @@ void BotUpdateView(AvHAIPlayer* pBot) EnemyTurretFilter.MaxSearchRadius = BALANCE_VAR(kTurretRange); } - vector EligibleTurrets = AITAC_FindAllDeployables(pBot->Edict->v.origin, &EnemyTurretFilter); + vector EligibleTurrets = AITAC_FindAllDeployables(pBot->Edict->v.origin, &EnemyTurretFilter); for (auto it = EligibleTurrets.begin(); it != EligibleTurrets.end(); it++) { - AvHAIBuildableStructure* ThisTurret = (*it); - AvHTurret* TurretRef = dynamic_cast(ThisTurret->EntityRef); + AvHAIBuildableStructure ThisTurret = (*it); + AvHTurret* TurretRef = dynamic_cast(ThisTurret.EntityRef); if (TurretRef && TurretRef->GetIsValidTarget(pBot->Player)) { @@ -1807,11 +1807,11 @@ void CustomThink(AvHAIPlayer* pBot) MineStructureFilter.ReachabilityTeam = pBot->Player->GetTeam(); MineStructureFilter.ReachabilityFlags = AI_REACHABILITY_MARINE; - AvHAIBuildableStructure* NearestIP = AITAC_FindClosestDeployableToLocation(pBot->Edict->v.origin, &MineStructureFilter); + AvHAIBuildableStructure NearestIP = AITAC_FindClosestDeployableToLocation(pBot->Edict->v.origin, &MineStructureFilter); - if (NearestIP) + if (NearestIP.IsValid()) { - AITASK_SetMineStructureTask(pBot, &pBot->PrimaryBotTask, NearestIP->edict, true); + AITASK_SetMineStructureTask(pBot, &pBot->PrimaryBotTask, NearestIP.edict, true); } } @@ -2855,20 +2855,20 @@ bool RegularMarineCombatThink(AvHAIPlayer* pBot) NearestArmoury.IncludeStatusFlags = STRUCTURE_STATUS_COMPLETED; NearestArmoury.ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING; - AvHAIBuildableStructure* NearestArmouryRef = AITAC_FindClosestDeployableToLocation(pBot->Edict->v.origin, &NearestArmoury); + AvHAIBuildableStructure NearestArmouryRef = AITAC_FindClosestDeployableToLocation(pBot->Edict->v.origin, &NearestArmoury); - if (NearestArmouryRef && !IsAreaAffectedBySpores(NearestArmouryRef->Location)) + if (NearestArmouryRef.IsValid() && !IsAreaAffectedBySpores(NearestArmouryRef.Location)) { - if (!TrackedEnemyRef->bHasLOS || (IsPlayerAlien(pBot->Edict) && vDist2DSq(NearestArmouryRef->Location, CurrentEnemy->v.origin) > sqrf(UTIL_MetresToGoldSrcUnits(10.0f)))) + if (!TrackedEnemyRef->bHasLOS || (IsPlayerAlien(pBot->Edict) && vDist2DSq(NearestArmouryRef.Location, CurrentEnemy->v.origin) > sqrf(UTIL_MetresToGoldSrcUnits(10.0f)))) { - if (IsPlayerInUseRange(pBot->Edict, NearestArmouryRef->edict)) + if (IsPlayerInUseRange(pBot->Edict, NearestArmouryRef.edict)) { - BotUseObject(pBot, NearestArmouryRef->edict, true); + BotUseObject(pBot, NearestArmouryRef.edict, true); return true; } } - MoveTo(pBot, NearestArmouryRef->Location, MOVESTYLE_NORMAL); + MoveTo(pBot, NearestArmouryRef.Location, MOVESTYLE_NORMAL); } else @@ -3198,22 +3198,22 @@ void AIPlayerSetMarineSweeperPrimaryTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Tas StructureFilter.ReachabilityFlags = pBot->BotNavInfo.NavProfile.ReachabilityFlag; StructureFilter.ExcludeStatusFlags = (STRUCTURE_STATUS_RECYCLING | STRUCTURE_STATUS_COMPLETED); - AvHAIBuildableStructure* UnbuiltIP = AITAC_FindClosestDeployableToLocation(CommChairLocation, &StructureFilter); + AvHAIBuildableStructure UnbuiltIP = AITAC_FindClosestDeployableToLocation(CommChairLocation, &StructureFilter); - if (UnbuiltIP) + if (UnbuiltIP.IsValid()) { - AITASK_SetBuildTask(pBot, Task, UnbuiltIP->edict, true); + AITASK_SetBuildTask(pBot, Task, UnbuiltIP.edict, true); return; } StructureFilter.DeployableTypes = SEARCH_ALL_STRUCTURES; StructureFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(15.0f); - AvHAIBuildableStructure* UnbuiltStructure = AITAC_FindClosestDeployableToLocation(CommChairLocation, &StructureFilter); + AvHAIBuildableStructure UnbuiltStructure = AITAC_FindClosestDeployableToLocation(CommChairLocation, &StructureFilter); - if (UnbuiltStructure) + if (UnbuiltStructure.IsValid()) { - AITASK_SetBuildTask(pBot, Task, UnbuiltStructure->edict, true); + AITASK_SetBuildTask(pBot, Task, UnbuiltStructure.edict, true); return; } @@ -3227,11 +3227,11 @@ void AIPlayerSetMarineSweeperPrimaryTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Tas AttackedStructureFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(20.0f); AttackedStructureFilter.bConsiderPhaseDistance = true; - AvHAIBuildableStructure* AttackedStructure = AITAC_FindClosestDeployableToLocation(CommChairLocation, &AttackedStructureFilter); + AvHAIBuildableStructure AttackedStructure = AITAC_FindClosestDeployableToLocation(CommChairLocation, &AttackedStructureFilter); - if (AttackedStructure) + if (AttackedStructure.IsValid()) { - AITASK_SetDefendTask(pBot, Task, AttackedStructure->edict, true); + AITASK_SetDefendTask(pBot, Task, AttackedStructure.edict, true); return; } @@ -3239,11 +3239,11 @@ void AIPlayerSetMarineSweeperPrimaryTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Tas { AttackedStructureFilter.IncludeStatusFlags = STRUCTURE_STATUS_DAMAGED; - AvHAIBuildableStructure* AttackedStructure = AITAC_FindClosestDeployableToLocation(CommChairLocation, &AttackedStructureFilter); + AvHAIBuildableStructure AttackedStructure = AITAC_FindClosestDeployableToLocation(CommChairLocation, &AttackedStructureFilter); - if (AttackedStructure) + if (AttackedStructure.IsValid()) { - AITASK_SetWeldTask(pBot, Task, AttackedStructure->edict, true); + AITASK_SetWeldTask(pBot, Task, AttackedStructure.edict, true); return; } } @@ -3265,34 +3265,34 @@ void AIPlayerSetMarineSweeperPrimaryTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Tas return; } - AvHAIBuildableStructure* NearestPG = AITAC_FindClosestDeployableToLocation(pBot->Edict->v.origin, &StructureFilter); + AvHAIBuildableStructure NearestPG = AITAC_FindClosestDeployableToLocation(pBot->Edict->v.origin, &StructureFilter); - vector AllPG = AITAC_FindAllDeployables(pBot->Edict->v.origin, &StructureFilter); + vector AllPG = AITAC_FindAllDeployables(pBot->Edict->v.origin, &StructureFilter); - AvHAIBuildableStructure* RandomPG = nullptr; + AvHAIBuildableStructure RandomPG; int HighestRand = 0; for (auto it = AllPG.begin(); it != AllPG.end(); it++) { - AvHAIBuildableStructure* ThisStruct = (*it); + AvHAIBuildableStructure ThisStruct = (*it); - if (ThisStruct == NearestPG) { continue; } + if (ThisStruct.edict == NearestPG.edict) { continue; } int ThisRand = irandrange(0, 100); - if (!RandomPG || ThisRand > HighestRand) + if (FNullEnt(RandomPG.edict) || ThisRand > HighestRand) { RandomPG = ThisStruct; HighestRand = ThisRand; } } - if (RandomPG) + if (RandomPG.IsValid()) { if (Task->TaskType != TASK_GUARD) { Task->TaskType = TASK_GUARD; - Task->TaskLocation = UTIL_GetRandomPointOnNavmeshInRadius(pBot->BotNavInfo.NavProfile, RandomPG->Location, UTIL_MetresToGoldSrcUnits(5.0f)); + Task->TaskLocation = UTIL_GetRandomPointOnNavmeshInRadius(pBot->BotNavInfo.NavProfile, RandomPG.Location, UTIL_MetresToGoldSrcUnits(5.0f)); Task->bTaskIsUrgent = false; Task->TaskLength = frandrange(20.0f, 30.0f); } @@ -3481,15 +3481,15 @@ void AIPlayerSetWantsAndNeedsCOMarineTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Ta NearestArmouryFilter.ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING; NearestArmouryFilter.MaxSearchRadius = SearchRadius; - AvHAIBuildableStructure* NearestArmoury = AITAC_FindClosestDeployableToLocation(pBot->Edict->v.origin, &NearestArmouryFilter); + AvHAIBuildableStructure NearestArmoury = AITAC_FindClosestDeployableToLocation(pBot->Edict->v.origin, &NearestArmouryFilter); // We really need some health or ammo, hit the armoury - if (NearestArmoury) + if (NearestArmoury.IsValid()) { Task->TaskType = TASK_RESUPPLY; Task->bTaskIsUrgent = true; - Task->TaskLocation = NearestArmoury->Location; - Task->TaskTarget = NearestArmoury->edict; + Task->TaskLocation = NearestArmoury.Location; + Task->TaskTarget = NearestArmoury.edict; return; } } @@ -3540,15 +3540,15 @@ void AIPlayerSetWantsAndNeedsMarineTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task NearestArmouryFilter.ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING; NearestArmouryFilter.MaxSearchRadius = (bTaskIsUrgent) ? UTIL_MetresToGoldSrcUnits(20.0f) : UTIL_MetresToGoldSrcUnits(5.0f); - AvHAIBuildableStructure* NearestArmoury = AITAC_FindClosestDeployableToLocation(pBot->Edict->v.origin, &NearestArmouryFilter); + AvHAIBuildableStructure NearestArmoury = AITAC_FindClosestDeployableToLocation(pBot->Edict->v.origin, &NearestArmouryFilter); // We really need some health or ammo, either hit the armoury, or ask for a resupply - if (NearestArmoury) + if (NearestArmoury.IsValid()) { Task->TaskType = TASK_RESUPPLY; Task->bTaskIsUrgent = true; - Task->TaskLocation = NearestArmoury->Location; - Task->TaskTarget = NearestArmoury->edict; + Task->TaskLocation = NearestArmoury.Location; + Task->TaskTarget = NearestArmoury.edict; return; } else @@ -3758,24 +3758,24 @@ void AIPlayerSetSecondaryMarineTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) if (pBot->DangerTurrets.size() > 0) { - AvHAIBuildableStructure* NearestDangerTurret = nullptr; + AvHAIBuildableStructure NearestDangerTurret; float MinDist = 0.0f; for (auto it = pBot->DangerTurrets.begin(); it != pBot->DangerTurrets.end(); it++) { - float ThisDist = vDist2DSq(pBot->Edict->v.origin, (*it)->Location); + float ThisDist = vDist2DSq(pBot->Edict->v.origin, (*it).Location); - if (!NearestDangerTurret || ThisDist < MinDist) + if (FNullEnt(NearestDangerTurret.edict) || ThisDist < MinDist) { NearestDangerTurret = (*it); } } - if (NearestDangerTurret) + if (NearestDangerTurret.IsValid()) { if (AIMGR_GetTeamType(EnemyTeam) == AVH_CLASS_TYPE_ALIEN) { - AITASK_SetAttackTask(pBot, Task, NearestDangerTurret->edict, true); + AITASK_SetAttackTask(pBot, Task, NearestDangerTurret.edict, true); return; } else @@ -3789,16 +3789,16 @@ void AIPlayerSetSecondaryMarineTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) EnemyTFFilter.ReachabilityFlags = pBot->BotNavInfo.NavProfile.ReachabilityFlag; EnemyTFFilter.ReachabilityTeam = BotTeam; - AvHAIBuildableStructure* EnemyTF = AITAC_FindClosestDeployableToLocation(NearestDangerTurret->Location, &EnemyTFFilter); + AvHAIBuildableStructure EnemyTF = AITAC_FindClosestDeployableToLocation(NearestDangerTurret.Location, &EnemyTFFilter); - if (EnemyTF) + if (EnemyTF.IsValid()) { - AITASK_SetAttackTask(pBot, Task, EnemyTF->edict, true); + AITASK_SetAttackTask(pBot, Task, EnemyTF.edict, true); return; } else { - AITASK_SetAttackTask(pBot, Task, NearestDangerTurret->edict, true); + AITASK_SetAttackTask(pBot, Task, NearestDangerTurret.edict, true); return; } } @@ -3814,39 +3814,39 @@ void AIPlayerSetSecondaryMarineTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) UnbuiltFilter.ExcludeStatusFlags = (STRUCTURE_STATUS_RECYCLING | STRUCTURE_STATUS_COMPLETED); UnbuiltFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(20.0f); - AvHAIBuildableStructure* UnbuiltIP = AITAC_FindClosestDeployableToLocation(pBot->Edict->v.origin, &UnbuiltFilter); + AvHAIBuildableStructure UnbuiltIP = AITAC_FindClosestDeployableToLocation(pBot->Edict->v.origin, &UnbuiltFilter); - if (UnbuiltIP) + if (UnbuiltIP.IsValid()) { - float ThisDist = vDist2D(UnbuiltIP->Location, pBot->Edict->v.origin); - int NumBuilders = AITAC_GetNumPlayersOfTeamInArea(BotTeam, UnbuiltIP->Location, ThisDist - 5.0f, false, pBot->Edict, AVH_USER3_COMMANDER_PLAYER); + float ThisDist = vDist2D(UnbuiltIP.Location, pBot->Edict->v.origin); + int NumBuilders = AITAC_GetNumPlayersOfTeamInArea(BotTeam, UnbuiltIP.Location, ThisDist - 5.0f, false, pBot->Edict, AVH_USER3_COMMANDER_PLAYER); if (NumBuilders < 1) { - AITASK_SetBuildTask(pBot, Task, UnbuiltIP->edict, true); + AITASK_SetBuildTask(pBot, Task, UnbuiltIP.edict, true); return; } } UnbuiltFilter.DeployableTypes = SEARCH_ALL_STRUCTURES; - vector BuildableStructures = AITAC_FindAllDeployables(pBot->Edict->v.origin, &UnbuiltFilter); + vector BuildableStructures = AITAC_FindAllDeployables(pBot->Edict->v.origin, &UnbuiltFilter); - AvHAIBuildableStructure* NearestStructure = nullptr; + AvHAIBuildableStructure NearestStructure; float MinDist = 0.0f; for (auto it = BuildableStructures.begin(); it != BuildableStructures.end(); it++) { - float ThisDist = vDist2D((*it)->Location, pBot->Edict->v.origin); + float ThisDist = vDist2D((*it).Location, pBot->Edict->v.origin); - int NumBuilders = AITAC_GetNumPlayersOfTeamInArea(BotTeam, (*it)->Location, ThisDist - 5.0f, false, pBot->Edict, AVH_USER3_COMMANDER_PLAYER); + int NumBuilders = AITAC_GetNumPlayersOfTeamInArea(BotTeam, (*it).Location, ThisDist - 5.0f, false, pBot->Edict, AVH_USER3_COMMANDER_PLAYER); // Two builders if we're not in the marine base, one to guard and keep lookout while the other builds - int NumDesiredBuilders = (vDist2DSq((*it)->Location, AITAC_GetCommChairLocation(BotTeam)) < sqrf(UTIL_MetresToGoldSrcUnits(15.0f))) ? 1 : 2; + int NumDesiredBuilders = (vDist2DSq((*it).Location, AITAC_GetCommChairLocation(BotTeam)) < sqrf(UTIL_MetresToGoldSrcUnits(15.0f))) ? 1 : 2; if (NumBuilders < NumDesiredBuilders) { - if (!NearestStructure || ThisDist < MinDist) + if (FNullEnt(NearestStructure.edict) || ThisDist < MinDist) { NearestStructure = (*it); MinDist = ThisDist; @@ -3854,9 +3854,9 @@ void AIPlayerSetSecondaryMarineTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) } } - if (NearestStructure) + if (NearestStructure.IsValid()) { - AITASK_SetBuildTask(pBot, Task, NearestStructure->edict, true); + AITASK_SetBuildTask(pBot, Task, NearestStructure.edict, true); return; } @@ -3920,13 +3920,13 @@ void AIPlayerSetSecondaryMarineTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) WeldableStructures.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(20.0f); WeldableStructures.bConsiderPhaseDistance = true; - AvHAIBuildableStructure* NearestDamagedStructure = AITAC_FindClosestDeployableToLocation(pBot->Edict->v.origin, &WeldableStructures); + AvHAIBuildableStructure NearestDamagedStructure = AITAC_FindClosestDeployableToLocation(pBot->Edict->v.origin, &WeldableStructures); - if (NearestDamagedStructure) + if (NearestDamagedStructure.IsValid()) { - bool bIsUrgent = (NearestDamagedStructure->healthPercent < 0.5f); + bool bIsUrgent = (NearestDamagedStructure.healthPercent < 0.5f); - AITASK_SetWeldTask(pBot, Task, NearestDamagedStructure->edict, bIsUrgent); + AITASK_SetWeldTask(pBot, Task, NearestDamagedStructure.edict, bIsUrgent); return; } @@ -3952,8 +3952,8 @@ void AIPlayerSetSecondaryMarineTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) MineableStructures.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(20.0f); MineableStructures.bConsiderPhaseDistance = true; - vector AllMineableStructures = AITAC_FindAllDeployables(AITAC_GetTeamStartingLocation(BotTeam), &MineableStructures); - AvHAIBuildableStructure* StructureToMine = nullptr; + vector AllMineableStructures = AITAC_FindAllDeployables(AITAC_GetTeamStartingLocation(BotTeam), &MineableStructures); + AvHAIBuildableStructure StructureToMine; DeployableSearchFilter MineFilter; MineFilter.DeployableTypes = STRUCTURE_MARINE_DEPLOYEDMINE; @@ -3964,15 +3964,15 @@ void AIPlayerSetSecondaryMarineTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) for (auto it = AllMineableStructures.begin(); it != AllMineableStructures.end(); it++) { - AvHAIBuildableStructure* ThisStructure = (*it); + AvHAIBuildableStructure ThisStructure = (*it); - int NumMines = AITAC_GetNumDeployablesNearLocation(ThisStructure->Location, &MineFilter); + int NumMines = AITAC_GetNumDeployablesNearLocation(ThisStructure.Location, &MineFilter); if (NumMines < 4) { - float ThisDist = AITAC_GetPhaseDistanceBetweenPoints(ThisStructure->Location, AITAC_GetTeamStartingLocation(BotTeam)); + float ThisDist = AITAC_GetPhaseDistanceBetweenPoints(ThisStructure.Location, AITAC_GetTeamStartingLocation(BotTeam)); - if (!StructureToMine || ThisDist > FarDist) + if (FNullEnt(StructureToMine.edict) || ThisDist > FarDist) { StructureToMine = ThisStructure; FarDist = ThisDist; @@ -3980,9 +3980,9 @@ void AIPlayerSetSecondaryMarineTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) } } - if (StructureToMine) + if (StructureToMine.IsValid()) { - AITASK_SetMineStructureTask(pBot, Task, StructureToMine->edict, true); + AITASK_SetMineStructureTask(pBot, Task, StructureToMine.edict, true); } } @@ -4509,11 +4509,11 @@ void AIPlayerSetPrimaryCOMarineTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) EnemyStuffFilter.ReachabilityTeam = BotTeam; EnemyStuffFilter.ReachabilityFlags = pBot->BotNavInfo.NavProfile.ReachabilityFlag; - AvHAIBuildableStructure* EnemyStructure = AITAC_FindClosestDeployableToLocation(pBot->Edict->v.origin, &EnemyStuffFilter); + AvHAIBuildableStructure EnemyStructure = AITAC_FindClosestDeployableToLocation(pBot->Edict->v.origin, &EnemyStuffFilter); - if (EnemyStructure) + if (EnemyStructure.IsValid()) { - AITASK_SetAttackTask(pBot, Task, EnemyStructure->edict, false); + AITASK_SetAttackTask(pBot, Task, EnemyStructure.edict, false); return; } else @@ -4575,26 +4575,26 @@ void AIPlayerSetSecondaryCOMarineTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) AttackedStructuresFilter.IncludeStatusFlags = STRUCTURE_STATUS_UNDERATTACK; AttackedStructuresFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(30.0f); - vector AllAttackedStructures = AITAC_FindAllDeployables(pBot->Edict->v.origin, &AttackedStructuresFilter); + vector AllAttackedStructures = AITAC_FindAllDeployables(pBot->Edict->v.origin, &AttackedStructuresFilter); - AvHAIBuildableStructure* StructureToDefend = nullptr; + AvHAIBuildableStructure StructureToDefend; float MinDist = 0.0f; for (auto it = AllAttackedStructures.begin(); it != AllAttackedStructures.end(); it++) { - AvHAIBuildableStructure* ThisStructure = (*it); + AvHAIBuildableStructure ThisStructure = (*it); - float ThisDist = vDist2D(pBot->Edict->v.origin, ThisStructure->edict->v.origin); + float ThisDist = vDist2D(pBot->Edict->v.origin, ThisStructure.edict->v.origin); - int NumAttackers = AITAC_GetNumPlayersOnTeamWithLOS(EnemyTeam, ThisStructure->Location, UTIL_MetresToGoldSrcUnits(15.0f), nullptr); + int NumAttackers = AITAC_GetNumPlayersOnTeamWithLOS(EnemyTeam, ThisStructure.Location, UTIL_MetresToGoldSrcUnits(15.0f), nullptr); if (NumAttackers == 0) { continue; } - int NumExistingDefenders = AITAC_GetNumPlayersOfTeamInArea(BotTeam, ThisStructure->Location, ThisDist - 10.0f, false, pBot->Edict, AVH_USER3_COMMANDER_PLAYER); + int NumExistingDefenders = AITAC_GetNumPlayersOfTeamInArea(BotTeam, ThisStructure.Location, ThisDist - 10.0f, false, pBot->Edict, AVH_USER3_COMMANDER_PLAYER); if (NumExistingDefenders < 2) { - if (!StructureToDefend || ThisDist < MinDist) + if (FNullEnt(StructureToDefend.edict) || ThisDist < MinDist) { StructureToDefend = ThisStructure; MinDist = ThisDist; @@ -4602,9 +4602,9 @@ void AIPlayerSetSecondaryCOMarineTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) } } - if (StructureToDefend) + if (StructureToDefend.IsValid()) { - AITASK_SetDefendTask(pBot, Task, StructureToDefend->edict, true); + AITASK_SetDefendTask(pBot, Task, StructureToDefend.edict, true); return; } @@ -4618,33 +4618,33 @@ void AIPlayerSetSecondaryCOMarineTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) DamagedStructuresFilter.IncludeStatusFlags = STRUCTURE_STATUS_DAMAGED; DamagedStructuresFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(20.0f); - AvHAIBuildableStructure* StructureToRepair = nullptr; - vector AllDamagedStructures = AITAC_FindAllDeployables(pBot->Edict->v.origin, &DamagedStructuresFilter); + AvHAIBuildableStructure StructureToRepair; + vector AllDamagedStructures = AITAC_FindAllDeployables(pBot->Edict->v.origin, &DamagedStructuresFilter); MinDist = 0.0f; for (auto it = AllDamagedStructures.begin(); it != AllDamagedStructures.end(); it++) { - AvHAIBuildableStructure* ThisStructure = (*it); + AvHAIBuildableStructure ThisStructure = (*it); - if (ThisStructure->StructureType == STRUCTURE_MARINE_COMMCHAIR && ThisStructure->healthPercent < 0.7f) + if (ThisStructure.StructureType == STRUCTURE_MARINE_COMMCHAIR && ThisStructure.healthPercent < 0.7f) { StructureToRepair = ThisStructure; break; } - float ThisDist = vDist2DSq(ThisStructure->Location, pBot->Edict->v.origin); + float ThisDist = vDist2DSq(ThisStructure.Location, pBot->Edict->v.origin); - if (!StructureToRepair || ThisDist < MinDist) + if (FNullEnt(StructureToRepair.edict) || ThisDist < MinDist) { StructureToRepair = ThisStructure; MinDist = ThisDist; } } - if (StructureToRepair) + if (StructureToRepair.IsValid()) { - AITASK_SetWeldTask(pBot, Task, StructureToRepair->edict, true); + AITASK_SetWeldTask(pBot, Task, StructureToRepair.edict, true); return; } @@ -4654,17 +4654,17 @@ void AIPlayerSetSecondaryCOMarineTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) NearbyArmouryFilter.ReachabilityTeam = BotTeam; NearbyArmouryFilter.ReachabilityFlags = AI_REACHABILITY_MARINE; - AvHAIBuildableStructure* NearestEasyAccessArmoury = AITAC_FindClosestDeployableToLocation(ZERO_VECTOR, &NearbyArmouryFilter); + AvHAIBuildableStructure NearestEasyAccessArmoury = AITAC_FindClosestDeployableToLocation(ZERO_VECTOR, &NearbyArmouryFilter); - if (!NearestEasyAccessArmoury) + if (!NearestEasyAccessArmoury.IsValid()) { NearbyArmouryFilter.ReachabilityFlags = AI_REACHABILITY_WELDER; - AvHAIBuildableStructure* NearestWeldableAccessArmoury = AITAC_FindClosestDeployableToLocation(ZERO_VECTOR, &NearbyArmouryFilter); + AvHAIBuildableStructure NearestWeldableAccessArmoury = AITAC_FindClosestDeployableToLocation(ZERO_VECTOR, &NearbyArmouryFilter); - if (NearestWeldableAccessArmoury) + if (NearestWeldableAccessArmoury.IsValid()) { - AITASK_SetMoveTask(pBot, Task, NearestWeldableAccessArmoury->Location, true); + AITASK_SetMoveTask(pBot, Task, NearestWeldableAccessArmoury.Location, true); return; } } @@ -4769,11 +4769,11 @@ void AIPlayerSetPrimaryCOAlienTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) EnemyStuffFilter.ReachabilityTeam = BotTeam; EnemyStuffFilter.ReachabilityFlags = pBot->BotNavInfo.NavProfile.ReachabilityFlag; - AvHAIBuildableStructure* EnemyStructure = AITAC_FindClosestDeployableToLocation(pBot->Edict->v.origin, &EnemyStuffFilter); + AvHAIBuildableStructure EnemyStructure = AITAC_FindClosestDeployableToLocation(pBot->Edict->v.origin, &EnemyStuffFilter); - if (EnemyStructure) + if (EnemyStructure.IsValid()) { - AITASK_SetAttackTask(pBot, Task, EnemyStructure->edict, false); + AITASK_SetAttackTask(pBot, Task, EnemyStructure.edict, false); return; } @@ -5296,7 +5296,7 @@ void AIPlayerSetAlienBuilderPrimaryTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task ExistingReinforcementFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(10.0f); ExistingReinforcementFilter.DeployableTypes = SEARCH_ALL_STRUCTURES; - vector AllReinforcingStructures = AITAC_FindAllDeployables(ThisHive->FloorLocation, &ExistingReinforcementFilter); + vector AllReinforcingStructures = AITAC_FindAllDeployables(ThisHive->FloorLocation, &ExistingReinforcementFilter); int NumOCs = 0; int NumDCs = 0; @@ -5305,7 +5305,7 @@ void AIPlayerSetAlienBuilderPrimaryTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task for (auto it = AllReinforcingStructures.begin(); it != AllReinforcingStructures.end(); it++) { - switch ((*it)->StructureType) + switch ((*it).StructureType) { case STRUCTURE_ALIEN_OFFENCECHAMBER: NumOCs++; @@ -5353,21 +5353,21 @@ void AIPlayerSetAlienBuilderPrimaryTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task ResNodeFilter.ReachabilityTeam = BotTeam; ResNodeFilter.ReachabilityFlags = pBot->BotNavInfo.NavProfile.ReachabilityFlag; - vector AllMatchingTowers = AITAC_FindAllDeployables(pBot->Edict->v.origin, &ResNodeFilter); + vector AllMatchingTowers = AITAC_FindAllDeployables(pBot->Edict->v.origin, &ResNodeFilter); edict_t* TowerToReinforce = nullptr; MinDist = 0.0f; for (auto it = AllMatchingTowers.begin(); it != AllMatchingTowers.end(); it++) { - AvHAIBuildableStructure* ThisResTower = (*it); + AvHAIBuildableStructure ThisResTower = (*it); DeployableSearchFilter ExistingReinforcementFilter; ExistingReinforcementFilter.DeployableTeam = BotTeam; ExistingReinforcementFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(5.0f); ExistingReinforcementFilter.DeployableTypes = SEARCH_ALL_STRUCTURES; - vector AllReinforcingStructures = AITAC_FindAllDeployables(ThisResTower->Location, &ExistingReinforcementFilter); + vector AllReinforcingStructures = AITAC_FindAllDeployables(ThisResTower.Location, &ExistingReinforcementFilter); int NumOCs = 0; int NumDCs = 0; @@ -5376,7 +5376,7 @@ void AIPlayerSetAlienBuilderPrimaryTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task for (auto it = AllReinforcingStructures.begin(); it != AllReinforcingStructures.end(); it++) { - switch ((*it)->StructureType) + switch ((*it).StructureType) { case STRUCTURE_ALIEN_OFFENCECHAMBER: NumOCs++; @@ -5400,11 +5400,11 @@ void AIPlayerSetAlienBuilderPrimaryTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task || (AITAC_TeamHiveWithTechExists(BotTeam, ALIEN_BUILD_MOVEMENT_CHAMBER) && NumMCs < 1) || (AITAC_TeamHiveWithTechExists(BotTeam, ALIEN_BUILD_SENSORY_CHAMBER) && NumSCs < 1)) { - float ThisDist = vDist2DSq(AITAC_GetTeamStartingLocation(EnemyTeam), ThisResTower->Location); + float ThisDist = vDist2DSq(AITAC_GetTeamStartingLocation(EnemyTeam), ThisResTower.Location); if (!TowerToReinforce || ThisDist < MinDist) { - TowerToReinforce = ThisResTower->edict; + TowerToReinforce = ThisResTower.edict; MinDist = ThisDist; } } @@ -5679,49 +5679,49 @@ void AIPlayerSetAlienAssaultPrimaryTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task EnemyStuffFilter.ReachabilityFlags = pBot->BotNavInfo.NavProfile.ReachabilityFlag; EnemyStuffFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(25.0f); - vector AllSiegingStructures = AITAC_FindAllDeployables(NearestSiegedHive->Location, &EnemyStuffFilter); + vector AllSiegingStructures = AITAC_FindAllDeployables(NearestSiegedHive->Location, &EnemyStuffFilter); - AvHAIBuildableStructure* StructureToTarget = nullptr; + AvHAIBuildableStructure StructureToTarget; float MinDist = 0.0f; for (auto it = AllSiegingStructures.begin(); it != AllSiegingStructures.end(); it++) { - AvHAIBuildableStructure* ThisStructure = (*it); + AvHAIBuildableStructure ThisStructure = (*it); // Always go for the phase gate first to prevent reinforcements - if (ThisStructure->StructureType == STRUCTURE_MARINE_PHASEGATE) + if (ThisStructure.StructureType == STRUCTURE_MARINE_PHASEGATE) { StructureToTarget = ThisStructure; continue; } // Then go for any turret factories, especially advanced ones to cut off siege turrets - if (ThisStructure->StructureType == STRUCTURE_MARINE_ADVTURRETFACTORY) + if (ThisStructure.StructureType == STRUCTURE_MARINE_ADVTURRETFACTORY) { StructureToTarget = ThisStructure; continue; } - if (ThisStructure->StructureType == STRUCTURE_MARINE_TURRETFACTORY) + if (ThisStructure.StructureType == STRUCTURE_MARINE_TURRETFACTORY) { StructureToTarget = ThisStructure; continue; } // Pick up anything else - float ThisDist = vDist2DSq(ThisStructure->Location, pBot->Edict->v.origin); + float ThisDist = vDist2DSq(ThisStructure.Location, pBot->Edict->v.origin); - if (!StructureToTarget || ThisDist < MinDist) + if (FNullEnt(StructureToTarget.edict) || ThisDist < MinDist) { StructureToTarget = ThisStructure; MinDist = ThisDist; } } - if (StructureToTarget) + if (StructureToTarget.IsValid()) { - AITASK_SetAttackTask(pBot, Task, StructureToTarget->edict, true); + AITASK_SetAttackTask(pBot, Task, StructureToTarget.edict, true); return; } } @@ -5751,53 +5751,53 @@ void AIPlayerSetAlienAssaultPrimaryTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task EnemyStuffFilter.ReachabilityFlags = pBot->BotNavInfo.NavProfile.ReachabilityFlag; EnemyStuffFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(25.0f); - vector AllSiegingStructures = AITAC_FindAllDeployables(ThisHive->Location, &EnemyStuffFilter); + vector AllSiegingStructures = AITAC_FindAllDeployables(ThisHive->Location, &EnemyStuffFilter); - AvHAIBuildableStructure* StructureToTarget = nullptr; + AvHAIBuildableStructure StructureToTarget; float MinDist = 0.0f; for (auto it = AllSiegingStructures.begin(); it != AllSiegingStructures.end(); it++) { - AvHAIBuildableStructure* ThisStructure = (*it); + AvHAIBuildableStructure ThisStructure = (*it); // Always go for the phase gate first to prevent reinforcements - if (ThisStructure->StructureType == STRUCTURE_MARINE_PHASEGATE) + if (ThisStructure.StructureType == STRUCTURE_MARINE_PHASEGATE) { StructureToTarget = ThisStructure; continue; } // Then go for any turret factories, especially advanced ones to cut off siege turrets - if (ThisStructure->StructureType == STRUCTURE_MARINE_ADVTURRETFACTORY) + if (ThisStructure.StructureType == STRUCTURE_MARINE_ADVTURRETFACTORY) { StructureToTarget = ThisStructure; continue; } - if (ThisStructure->StructureType == STRUCTURE_MARINE_TURRETFACTORY) + if (ThisStructure.StructureType == STRUCTURE_MARINE_TURRETFACTORY) { StructureToTarget = ThisStructure; continue; } // Pick up anything else - float ThisDist = vDist2DSq(ThisStructure->Location, pBot->Edict->v.origin); + float ThisDist = vDist2DSq(ThisStructure.Location, pBot->Edict->v.origin); - if (!StructureToTarget || ThisDist < MinDist) + if (FNullEnt(StructureToTarget.edict) || ThisDist < MinDist) { StructureToTarget = ThisStructure; MinDist = ThisDist; } } - if (StructureToTarget) + if (StructureToTarget.IsValid()) { - int NumAttackers = AITAC_GetNumPlayersOfTeamInArea(BotTeam, StructureToTarget->Location, UTIL_MetresToGoldSrcUnits(10.0f), false, pBot->Edict, AVH_USER3_ALIEN_PLAYER2); + int NumAttackers = AITAC_GetNumPlayersOfTeamInArea(BotTeam, StructureToTarget.Location, UTIL_MetresToGoldSrcUnits(10.0f), false, pBot->Edict, AVH_USER3_ALIEN_PLAYER2); if (NumAttackers < 2) { - AITASK_SetAttackTask(pBot, Task, StructureToTarget->edict, true); + AITASK_SetAttackTask(pBot, Task, StructureToTarget.edict, true); return; } } @@ -5949,48 +5949,48 @@ void AIPlayerSetAlienAssaultPrimaryTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task EnemyStuffFilter.ExcludeStatusFlags = STRUCTURE_STATUS_ELECTRIFIED; } - vector AllEnemyThings = AITAC_FindAllDeployables(HiveToSecure->FloorLocation, &EnemyStuffFilter); + vector AllEnemyThings = AITAC_FindAllDeployables(HiveToSecure->FloorLocation, &EnemyStuffFilter); - AvHAIBuildableStructure* StructureToAttack = nullptr; + AvHAIBuildableStructure StructureToAttack; for (auto it = AllEnemyThings.begin(); it != AllEnemyThings.end(); it++) { - AvHAIBuildableStructure* ThisStructure = (*it); + AvHAIBuildableStructure ThisStructure = (*it); // First prioritise phase gates or alien OCs - if (ThisStructure->StructureType == STRUCTURE_MARINE_PHASEGATE || ThisStructure->StructureType == STRUCTURE_ALIEN_OFFENCECHAMBER) + if (ThisStructure.StructureType == STRUCTURE_MARINE_PHASEGATE || ThisStructure.StructureType == STRUCTURE_ALIEN_OFFENCECHAMBER) { - if (!StructureToAttack || StructureToAttack->StructureType != ThisStructure->StructureType || vDist2DSq(pBot->Edict->v.origin, ThisStructure->Location) < vDist2DSq(pBot->Edict->v.origin, StructureToAttack->Location)) + 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 (StructureToAttack && (StructureToAttack->StructureType == STRUCTURE_MARINE_PHASEGATE || ThisStructure->StructureType == STRUCTURE_ALIEN_OFFENCECHAMBER)) { 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 (ThisStructure.StructureType == STRUCTURE_MARINE_TURRETFACTORY || ThisStructure.StructureType == STRUCTURE_MARINE_ADVTURRETFACTORY) { - if (!StructureToAttack || StructureToAttack->StructureType != ThisStructure->StructureType || vDist2DSq(pBot->Edict->v.origin, ThisStructure->Location) < vDist2DSq(pBot->Edict->v.origin, StructureToAttack->Location)) + 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 (StructureToAttack && (StructureToAttack->StructureType == STRUCTURE_MARINE_TURRETFACTORY || ThisStructure->StructureType == STRUCTURE_MARINE_ADVTURRETFACTORY)) { continue; } + if (!FNullEnt(StructureToAttack.edict) && (StructureToAttack.StructureType == STRUCTURE_MARINE_TURRETFACTORY || ThisStructure.StructureType == STRUCTURE_MARINE_ADVTURRETFACTORY)) { continue; } // Then target any other structures - if (!StructureToAttack || vDist2DSq(pBot->Edict->v.origin, ThisStructure->Location) < vDist2DSq(pBot->Edict->v.origin, StructureToAttack->Location)) + if (FNullEnt(StructureToAttack.edict) || vDist2DSq(pBot->Edict->v.origin, ThisStructure.Location) < vDist2DSq(pBot->Edict->v.origin, StructureToAttack.Location)) { StructureToAttack = ThisStructure; } } - if (StructureToAttack) + if (StructureToAttack.IsValid()) { - AITASK_SetAttackTask(pBot, Task, StructureToAttack->edict, false); + AITASK_SetAttackTask(pBot, Task, StructureToAttack.edict, false); return; } } @@ -6003,11 +6003,11 @@ void AIPlayerSetAlienAssaultPrimaryTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task EnemyInfPortalFilter.IncludeStatusFlags = STRUCTURE_STATUS_COMPLETED; EnemyInfPortalFilter.ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING; - AvHAIBuildableStructure* EnemyInfPortal = AITAC_FindClosestDeployableToLocation(pBot->Edict->v.origin, &EnemyInfPortalFilter); + AvHAIBuildableStructure EnemyInfPortal = AITAC_FindClosestDeployableToLocation(pBot->Edict->v.origin, &EnemyInfPortalFilter); - if (EnemyInfPortal) + if (EnemyInfPortal.IsValid()) { - AITASK_SetAttackTask(pBot, Task, EnemyInfPortal->edict, false); + AITASK_SetAttackTask(pBot, Task, EnemyInfPortal.edict, false); return; } @@ -6109,7 +6109,7 @@ void AIPlayerSetAlienHarasserPrimaryTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Tas Vector EnemyBaseLocation = AITAC_GetTeamStartingLocation(EnemyTeam); - AvHAIBuildableStructure* EnemyStructureToAttack = nullptr; + AvHAIBuildableStructure EnemyStructureToAttack; bool bEnemyIsMarines = (AIMGR_GetTeamType(EnemyTeam) == AVH_CLASS_TYPE_MARINE); @@ -6125,9 +6125,9 @@ void AIPlayerSetAlienHarasserPrimaryTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Tas EnemyStructureToAttack = AITAC_FindClosestDeployableToLocation(EnemyBaseLocation, &EnemyStructureFilter); } - if (EnemyStructureToAttack) + if (EnemyStructureToAttack.IsValid()) { - AITASK_SetAttackTask(pBot, Task, EnemyStructureToAttack->edict, false); + AITASK_SetAttackTask(pBot, Task, EnemyStructureToAttack.edict, false); return; } @@ -6188,24 +6188,24 @@ void AIPlayerSetSecondaryAlienTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) if (pBot->DangerTurrets.size() > 0) { - AvHAIBuildableStructure* NearestDangerTurret = nullptr; + AvHAIBuildableStructure NearestDangerTurret; float MinDist = 0.0f; for (auto it = pBot->DangerTurrets.begin(); it != pBot->DangerTurrets.end(); it++) { - float ThisDist = vDist2DSq(pBot->Edict->v.origin, (*it)->Location); + float ThisDist = vDist2DSq(pBot->Edict->v.origin, (*it).Location); - if (!NearestDangerTurret || ThisDist < MinDist) + if (FNullEnt(NearestDangerTurret.edict) || ThisDist < MinDist) { NearestDangerTurret = (*it); } } - if (NearestDangerTurret) + if (NearestDangerTurret.IsValid()) { if (AIMGR_GetTeamType(EnemyTeam) == AVH_CLASS_TYPE_ALIEN) { - AITASK_SetAttackTask(pBot, Task, NearestDangerTurret->edict, true); + AITASK_SetAttackTask(pBot, Task, NearestDangerTurret.edict, true); return; } else @@ -6224,16 +6224,16 @@ void AIPlayerSetSecondaryAlienTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) EnemyTFFilter.ReachabilityFlags = pBot->BotNavInfo.NavProfile.ReachabilityFlag; EnemyTFFilter.ReachabilityTeam = BotTeam; - AvHAIBuildableStructure* EnemyTF = AITAC_FindClosestDeployableToLocation(NearestDangerTurret->Location, &EnemyTFFilter); + AvHAIBuildableStructure EnemyTF = AITAC_FindClosestDeployableToLocation(NearestDangerTurret.Location, &EnemyTFFilter); - if (EnemyTF) + if (EnemyTF.IsValid()) { - AITASK_SetAttackTask(pBot, Task, EnemyTF->edict, true); + AITASK_SetAttackTask(pBot, Task, EnemyTF.edict, true); return; } else { - AITASK_SetAttackTask(pBot, Task, NearestDangerTurret->edict, true); + AITASK_SetAttackTask(pBot, Task, NearestDangerTurret.edict, true); return; } } @@ -6278,7 +6278,7 @@ void AIPlayerSetSecondaryAlienTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) DamagedStructuresFilter.IncludeStatusFlags = STRUCTURE_STATUS_COMPLETED; DamagedStructuresFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(5.0f); - vector AllNearbyStructures = AITAC_FindAllDeployables(pBot->Edict->v.origin, &DamagedStructuresFilter); + vector AllNearbyStructures = AITAC_FindAllDeployables(pBot->Edict->v.origin, &DamagedStructuresFilter); edict_t* StructureToHeal = nullptr; @@ -6286,14 +6286,14 @@ void AIPlayerSetSecondaryAlienTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) for (auto it = AllNearbyStructures.begin(); it != AllNearbyStructures.end(); it++) { - AvHAIBuildableStructure* ThisStructure = (*it); + AvHAIBuildableStructure ThisStructure = (*it); - if (ThisStructure && ThisStructure->healthPercent < 0.99f) + if (!FNullEnt(ThisStructure.edict) && ThisStructure.healthPercent < 0.99f) { - float ThisDist = vDist2DSq(pBot->Edict->v.origin, ThisStructure->Location); + float ThisDist = vDist2DSq(pBot->Edict->v.origin, ThisStructure.Location); if (FNullEnt(StructureToHeal) || ThisDist < MinDist) { - StructureToHeal = ThisStructure->edict; + StructureToHeal = ThisStructure.edict; MinDist = ThisDist; } } @@ -6429,26 +6429,26 @@ void AIPlayerSetSecondaryAlienTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) AttackedStructuresFilter.IncludeStatusFlags = STRUCTURE_STATUS_UNDERATTACK; AttackedStructuresFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(30.0f); - vector AllAttackedStructures = AITAC_FindAllDeployables(pBot->Edict->v.origin, &AttackedStructuresFilter); + vector AllAttackedStructures = AITAC_FindAllDeployables(pBot->Edict->v.origin, &AttackedStructuresFilter); - AvHAIBuildableStructure* StructureToDefend = nullptr; + AvHAIBuildableStructure StructureToDefend; MinDist = 0.0f; for (auto it = AllAttackedStructures.begin(); it != AllAttackedStructures.end(); it++) { - AvHAIBuildableStructure* ThisStructure = (*it); + AvHAIBuildableStructure ThisStructure = (*it); - float ThisDist = vDist2D(pBot->Edict->v.origin, ThisStructure->edict->v.origin); + float ThisDist = vDist2D(pBot->Edict->v.origin, ThisStructure.edict->v.origin); - int NumAttackers = AITAC_GetNumPlayersOnTeamWithLOS(EnemyTeam, ThisStructure->Location, UTIL_MetresToGoldSrcUnits(15.0f), nullptr); + int NumAttackers = AITAC_GetNumPlayersOnTeamWithLOS(EnemyTeam, ThisStructure.Location, UTIL_MetresToGoldSrcUnits(15.0f), nullptr); if (NumAttackers == 0) { continue; } - int NumExistingDefenders = AITAC_GetNumPlayersOfTeamInArea(BotTeam, ThisStructure->Location, ThisDist - 10.0f, false, pBot->Edict, AVH_USER3_ALIEN_PLAYER2); + int NumExistingDefenders = AITAC_GetNumPlayersOfTeamInArea(BotTeam, ThisStructure.Location, ThisDist - 10.0f, false, pBot->Edict, AVH_USER3_ALIEN_PLAYER2); if (NumExistingDefenders < 2) { - if (!StructureToDefend || ThisDist < MinDist) + if (FNullEnt(StructureToDefend.edict) || ThisDist < MinDist) { StructureToDefend = ThisStructure; MinDist = ThisDist; @@ -6456,9 +6456,9 @@ void AIPlayerSetSecondaryAlienTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) } } - if (StructureToDefend) + if (StructureToDefend.IsValid()) { - AITASK_SetDefendTask(pBot, Task, StructureToDefend->edict, true); + AITASK_SetDefendTask(pBot, Task, StructureToDefend.edict, true); return; } diff --git a/main/source/mod/AIPlayers/AvHAIPlayerManager.cpp b/main/source/mod/AIPlayers/AvHAIPlayerManager.cpp index eb239e2d..510bebcc 100644 --- a/main/source/mod/AIPlayers/AvHAIPlayerManager.cpp +++ b/main/source/mod/AIPlayers/AvHAIPlayerManager.cpp @@ -1046,8 +1046,7 @@ void AIMGR_NewMap() AIStartedTime = gpGlobals->time; LastAIPlayerCountUpdate = 0.0f; - ALERT(at_console, "AI Manager New Map\n"); - + AITAC_ClearMapAIData(true); if (NavmeshLoaded()) @@ -1057,13 +1056,6 @@ void AIMGR_NewMap() CONFIG_ParseConfigFile(); - const char* theCStrLevelName = STRING(gpGlobals->mapname); - - if (!loadNavigationData(theCStrLevelName)) - { - return; - } - AIMGR_BotPrecache(); bHasRoundStarted = false; @@ -1071,6 +1063,19 @@ void AIMGR_NewMap() bPlayerSpawned = false; } +void AIMGR_LoadNavigationData() +{ + // Don't reload the nav mesh if it's already loaded + if (NavmeshLoaded()) { return; } + + const char* theCStrLevelName = STRING(gpGlobals->mapname); + + if (!loadNavigationData(theCStrLevelName)) + { + ALERT(at_console, "Failed to load navigation data for %s\n"); + } +} + AvHAIPlayer* AIMGR_GetAICommander(AvHTeamNumber Team) { AvHPlayer* ActiveCommander = GetGameRules()->GetTeam(Team)->GetCommanderPlayer(); diff --git a/main/source/mod/AIPlayers/AvHAIPlayerManager.h b/main/source/mod/AIPlayers/AvHAIPlayerManager.h index f1d65177..0b2e4422 100644 --- a/main/source/mod/AIPlayers/AvHAIPlayerManager.h +++ b/main/source/mod/AIPlayers/AvHAIPlayerManager.h @@ -68,6 +68,7 @@ int AIMGR_GetNumAIPlayersWithRoleOnTeam(AvHTeamNumber Team, AvHAIBotRole Role, A int AIMGR_GetNumHumansOfClassOnTeam(AvHTeamNumber Team, AvHUser3 PlayerType); +void AIMGR_LoadNavigationData(); void AIMGR_ReloadNavigationData(); AvHAIPlayer* AIMGR_GetAICommander(AvHTeamNumber Team); diff --git a/main/source/mod/AIPlayers/AvHAIPlayerUtil.cpp b/main/source/mod/AIPlayers/AvHAIPlayerUtil.cpp index a5c12692..25c7325d 100644 --- a/main/source/mod/AIPlayers/AvHAIPlayerUtil.cpp +++ b/main/source/mod/AIPlayers/AvHAIPlayerUtil.cpp @@ -1153,7 +1153,6 @@ void AIPlayer_Say(edict_t* pEntity, int teamonly, const char* Msg) int j; char* p; char text[256]; - char szTemp[256]; bool theTalkerInReadyRoom = theTalkingPlayer->GetInReadyRoom(); // We can get a raw string now, without the "say " prepended diff --git a/main/source/mod/AIPlayers/AvHAITactical.cpp b/main/source/mod/AIPlayers/AvHAITactical.cpp index 58999598..5000aa69 100644 --- a/main/source/mod/AIPlayers/AvHAITactical.cpp +++ b/main/source/mod/AIPlayers/AvHAITactical.cpp @@ -66,13 +66,97 @@ edict_t* LastSeenLerkTeamB = nullptr; // Track who went lerk on team B last time float LastSeenLerkTeamATime = 0.0f; float LastSeenLerkTeamBTime = 0.0f; -std::vector AITAC_FindAllDeployables(const Vector& Location, const DeployableSearchFilter* Filter) +std::vector AITAC_FindAllDeployables(const Vector& Location, const DeployableSearchFilter* Filter) +{ + std::vector Result; + + AvHTeamNumber TeamA = GetGameRules()->GetTeamANumber(); + AvHTeamNumber TeamB = GetGameRules()->GetTeamBNumber(); + + float CurrMinDist = 0.0f; + + float MinDistSq = sqrf(Filter->MinSearchRadius); + float MaxDistSq = sqrf(Filter->MaxSearchRadius); + + bool bUseMinDist = MinDistSq > 0.1f; + bool bUseMaxDist = MaxDistSq > 0.1f; + + if (Filter->DeployableTeam == TeamA || Filter->DeployableTeam == TEAM_IND) + { + for (auto& it : TeamAStructureMap) + { + if (FNullEnt(it.second.edict) || it.second.edict->v.deadflag != DEAD_NO || (it.second.edict->v.effects & EF_NODRAW)) { continue; } + + if (it.second.StructureStatusFlags & Filter->ExcludeStatusFlags) { continue; } + if ((it.second.StructureStatusFlags & Filter->IncludeStatusFlags) != Filter->IncludeStatusFlags) { continue; } + + if (Filter->ReachabilityFlags != AI_REACHABILITY_NONE) + { + unsigned int StructureReachabilityFlags = (it.second.TeamAReachabilityFlags | it.second.TeamBReachabilityFlags); + + if (Filter->ReachabilityTeam != TEAM_IND) + { + StructureReachabilityFlags = (Filter->ReachabilityTeam == TeamA) ? it.second.TeamAReachabilityFlags : it.second.TeamBReachabilityFlags; + } + + if (!(StructureReachabilityFlags & Filter->ReachabilityFlags)) { continue; } + } + + if (it.second.StructureType & Filter->DeployableTypes) + { + float DistSq = (Filter->bConsiderPhaseDistance) ? sqrf(AITAC_GetPhaseDistanceBetweenPoints(it.second.Location, Location)) : vDist2DSq(it.second.Location, Location); + + if ((!bUseMinDist || DistSq >= MinDistSq) && (!bUseMaxDist || DistSq <= MaxDistSq)) + { + Result.push_back(it.second); + } + } + } + } + + if (Filter->DeployableTeam == TeamB || Filter->DeployableTeam == TEAM_IND) + { + for (auto& it : TeamBStructureMap) + { + if (FNullEnt(it.second.edict) || it.second.edict->v.deadflag != DEAD_NO || (it.second.edict->v.effects & EF_NODRAW)) { continue; } + + if (it.second.StructureStatusFlags & Filter->ExcludeStatusFlags) { continue; } + if ((it.second.StructureStatusFlags & Filter->IncludeStatusFlags) != Filter->IncludeStatusFlags) { continue; } + + if (Filter->ReachabilityFlags != AI_REACHABILITY_NONE) + { + unsigned int StructureReachabilityFlags = (it.second.TeamAReachabilityFlags | it.second.TeamBReachabilityFlags); + + if (Filter->ReachabilityTeam != TEAM_IND) + { + StructureReachabilityFlags = (Filter->ReachabilityTeam == TeamA) ? it.second.TeamAReachabilityFlags : it.second.TeamBReachabilityFlags; + } + + if (!(StructureReachabilityFlags & Filter->ReachabilityFlags)) { continue; } + } + + if (it.second.StructureType & Filter->DeployableTypes) + { + float DistSq = (Filter->bConsiderPhaseDistance) ? sqrf(AITAC_GetPhaseDistanceBetweenPoints(it.second.Location, Location)) : vDist2DSq(it.second.Location, Location); + + if ((!bUseMinDist || DistSq >= MinDistSq) && (!bUseMaxDist || DistSq <= MaxDistSq)) + { + Result.push_back(it.second); + } + } + } + } + + return Result; +} + +std::vector AITAC_FindAllDeployablesByRef(const Vector& Location, const DeployableSearchFilter* Filter) { std::vector Result; AvHTeamNumber TeamA = GetGameRules()->GetTeamANumber(); AvHTeamNumber TeamB = GetGameRules()->GetTeamBNumber(); - + float CurrMinDist = 0.0f; float MinDistSq = sqrf(Filter->MinSearchRadius); @@ -224,7 +308,82 @@ bool AITAC_DeployableExistsAtLocation(const Vector& Location, const DeployableSe return false; } -AvHAIBuildableStructure* AITAC_FindClosestDeployableToLocation(const Vector& Location, const DeployableSearchFilter* Filter) +AvHAIBuildableStructure AITAC_FindClosestDeployableToLocation(const Vector& Location, const DeployableSearchFilter* Filter) +{ + AvHTeamNumber TeamA = GetGameRules()->GetTeamANumber(); + AvHTeamNumber TeamB = GetGameRules()->GetTeamBNumber(); + + AvHAIBuildableStructure Result; + float CurrMinDist = 0.0f; + + float MinDistSq = sqrf(Filter->MinSearchRadius); + float MaxDistSq = sqrf(Filter->MaxSearchRadius); + + bool bUseMinDist = MinDistSq > 0.1f; + bool bUseMaxDist = MaxDistSq > 0.1f; + + if (Filter->DeployableTeam == TeamA || Filter->DeployableTeam == TEAM_IND) + { + for (auto& it : TeamAStructureMap) + { + if (FNullEnt(it.second.edict) || it.second.edict->v.deadflag != DEAD_NO || (it.second.edict->v.effects & EF_NODRAW)) { continue; } + + if (!(it.second.StructureType & Filter->DeployableTypes)) { continue; } + if (it.second.StructureStatusFlags & Filter->ExcludeStatusFlags) { continue; } + if ((it.second.StructureStatusFlags & Filter->IncludeStatusFlags) != Filter->IncludeStatusFlags) { continue; } + + unsigned int StructureReachabilityFlags = (it.second.TeamAReachabilityFlags | it.second.TeamBReachabilityFlags); + + if (Filter->ReachabilityTeam != TEAM_IND) + { + StructureReachabilityFlags = (Filter->ReachabilityTeam == TeamA) ? it.second.TeamAReachabilityFlags : it.second.TeamBReachabilityFlags; + } + + if (Filter->ReachabilityFlags != AI_REACHABILITY_NONE && !(StructureReachabilityFlags & Filter->ReachabilityFlags)) { continue; } + + float DistSq = (Filter->bConsiderPhaseDistance) ? sqrf(AITAC_GetPhaseDistanceBetweenPoints(it.second.Location, Location)) : vDist2DSq(it.second.Location, Location); + + if ((!bUseMinDist || DistSq >= MinDistSq) && (!bUseMaxDist || DistSq <= MaxDistSq) && (FNullEnt(Result.edict) || DistSq < CurrMinDist)) + { + Result = it.second; + CurrMinDist = DistSq; + } + } + } + + if (Filter->DeployableTeam == TeamB || Filter->DeployableTeam == TEAM_IND) + { + for (auto& it : TeamBStructureMap) + { + if (FNullEnt(it.second.edict) || it.second.edict->v.deadflag != DEAD_NO || (it.second.edict->v.effects & EF_NODRAW)) { continue; } + + if (!(it.second.StructureType & Filter->DeployableTypes)) { continue; } + if (it.second.StructureStatusFlags & Filter->ExcludeStatusFlags) { continue; } + if ((it.second.StructureStatusFlags & Filter->IncludeStatusFlags) != Filter->IncludeStatusFlags) { continue; } + + unsigned int StructureReachabilityFlags = (it.second.TeamAReachabilityFlags | it.second.TeamBReachabilityFlags); + + if (Filter->ReachabilityTeam != TEAM_IND) + { + StructureReachabilityFlags = (Filter->ReachabilityTeam == TeamA) ? it.second.TeamAReachabilityFlags : it.second.TeamBReachabilityFlags; + } + + if (Filter->ReachabilityFlags != AI_REACHABILITY_NONE && !(StructureReachabilityFlags & Filter->ReachabilityFlags)) { continue; } + + float DistSq = (Filter->bConsiderPhaseDistance) ? sqrf(AITAC_GetPhaseDistanceBetweenPoints(it.second.Location, Location)) : vDist2DSq(it.second.Location, Location); + + if ((!bUseMinDist || DistSq >= MinDistSq) && (!bUseMaxDist || DistSq <= MaxDistSq) && (FNullEnt(Result.edict) || DistSq < CurrMinDist)) + { + Result = it.second; + CurrMinDist = DistSq; + } + } + } + + return Result; +} + +AvHAIBuildableStructure* AITAC_FindClosestDeployableToLocationByRef(const Vector& Location, const DeployableSearchFilter* Filter) { AvHTeamNumber TeamA = GetGameRules()->GetTeamANumber(); AvHTeamNumber TeamB = GetGameRules()->GetTeamBNumber(); @@ -299,12 +458,87 @@ AvHAIBuildableStructure* AITAC_FindClosestDeployableToLocation(const Vector& Loc return Result; } -AvHAIBuildableStructure* AITAC_FindFurthestDeployableFromLocation(const Vector& Location, const DeployableSearchFilter* Filter) +AvHAIBuildableStructure AITAC_FindFurthestDeployableFromLocation(const Vector& Location, const DeployableSearchFilter* Filter) { AvHTeamNumber TeamA = GetGameRules()->GetTeamANumber(); AvHTeamNumber TeamB = GetGameRules()->GetTeamBNumber(); - AvHAIBuildableStructure* Result = NULL; + AvHAIBuildableStructure Result; + float CurrMinDist = 0.0f; + + float MinDistSq = sqrf(Filter->MinSearchRadius); + float MaxDistSq = sqrf(Filter->MaxSearchRadius); + + bool bUseMinDist = MinDistSq > 0.1f; + bool bUseMaxDist = MaxDistSq > 0.1f; + + if (Filter->DeployableTeam == TeamA || Filter->DeployableTeam == TEAM_IND) + { + for (auto& it : TeamAStructureMap) + { + if (FNullEnt(it.second.edict) || it.second.edict->v.deadflag != DEAD_NO || (it.second.edict->v.effects & EF_NODRAW)) { continue; } + + if (it.second.StructureStatusFlags & Filter->ExcludeStatusFlags) { continue; } + if ((it.second.StructureStatusFlags & Filter->IncludeStatusFlags) != Filter->IncludeStatusFlags) { continue; } + if (!(it.second.StructureType & Filter->DeployableTypes)) { continue; } + + unsigned int StructureReachabilityFlags = (it.second.TeamAReachabilityFlags | it.second.TeamBReachabilityFlags); + + if (Filter->ReachabilityTeam != TEAM_IND) + { + StructureReachabilityFlags = (Filter->ReachabilityTeam == TeamA) ? it.second.TeamAReachabilityFlags : it.second.TeamBReachabilityFlags; + } + + if (Filter->ReachabilityFlags != AI_REACHABILITY_NONE && !(StructureReachabilityFlags & Filter->ReachabilityFlags)) { continue; } + + float DistSq = (Filter->bConsiderPhaseDistance) ? sqrf(AITAC_GetPhaseDistanceBetweenPoints(it.second.Location, Location)) : vDist2DSq(it.second.Location, Location); + + if ((!bUseMinDist || DistSq >= MinDistSq) && (!bUseMaxDist || DistSq <= MaxDistSq) && DistSq > CurrMinDist) + { + Result = it.second; + CurrMinDist = DistSq; + } + } + } + + if (Filter->DeployableTeam == TeamB || Filter->DeployableTeam == TEAM_IND) + { + for (auto& it : TeamBStructureMap) + { + if (FNullEnt(it.second.edict) || it.second.edict->v.deadflag != DEAD_NO || (it.second.edict->v.effects & EF_NODRAW)) { continue; } + + if (it.second.StructureStatusFlags & Filter->ExcludeStatusFlags) { continue; } + if ((it.second.StructureStatusFlags & Filter->IncludeStatusFlags) != Filter->IncludeStatusFlags) { continue; } + if (!(it.second.StructureType & Filter->DeployableTypes)) { continue; } + + unsigned int StructureReachabilityFlags = (it.second.TeamAReachabilityFlags | it.second.TeamBReachabilityFlags); + + if (Filter->ReachabilityTeam != TEAM_IND) + { + StructureReachabilityFlags = (Filter->ReachabilityTeam == TeamA) ? it.second.TeamAReachabilityFlags : it.second.TeamBReachabilityFlags; + } + + if (Filter->ReachabilityFlags != AI_REACHABILITY_NONE && !(StructureReachabilityFlags & Filter->ReachabilityFlags)) { continue; } + + float DistSq = (Filter->bConsiderPhaseDistance) ? sqrf(AITAC_GetPhaseDistanceBetweenPoints(it.second.Location, Location)) : vDist2DSq(it.second.Location, Location); + + if ((!bUseMinDist || DistSq >= MinDistSq) && (!bUseMaxDist || DistSq <= MaxDistSq) && DistSq > CurrMinDist) + { + Result = it.second; + CurrMinDist = DistSq; + } + } + } + + return Result; +} + +AvHAIBuildableStructure* AITAC_FindFurthestDeployableFromLocationByRef(const Vector& Location, const DeployableSearchFilter* Filter) +{ + AvHTeamNumber TeamA = GetGameRules()->GetTeamANumber(); + AvHTeamNumber TeamB = GetGameRules()->GetTeamBNumber(); + + AvHAIBuildableStructure* Result = nullptr; float CurrMinDist = 0.0f; float MinDistSq = sqrf(Filter->MinSearchRadius); @@ -497,6 +731,25 @@ bool AITAC_ItemExistsInLocation(const Vector& Location, const AvHAIDeployableIte return false; } +AvHAIBuildableStructure AITAC_GetDeployableFromEdict(const edict_t* Structure) +{ + AvHAIBuildableStructure Result; + + if (FNullEnt(Structure)) { return Result; } + + int EntIndex = ENTINDEX(Structure); + + if (EntIndex < 0) { return Result; } + + AvHTeamNumber TeamA = GetGameRules()->GetTeamANumber(); + AvHTeamNumber TeamB = GetGameRules()->GetTeamBNumber(); + + Result = (Structure->v.team == TeamA) ? TeamAStructureMap[EntIndex] : TeamBStructureMap[EntIndex]; + + return Result; + +} + AvHAIBuildableStructure* AITAC_GetDeployableRefFromEdict(const edict_t* Structure) { if (FNullEnt(Structure)) { return nullptr; } @@ -512,12 +765,95 @@ AvHAIBuildableStructure* AITAC_GetDeployableRefFromEdict(const edict_t* Structur } -AvHAIBuildableStructure* AITAC_GetNearestDeployableDirectlyReachable(AvHAIPlayer* pBot, const Vector Location, const DeployableSearchFilter* Filter) +AvHAIBuildableStructure AITAC_GetNearestDeployableDirectlyReachable(AvHAIPlayer* pBot, const Vector Location, const DeployableSearchFilter* Filter) { AvHTeamNumber TeamA = GetGameRules()->GetTeamANumber(); AvHTeamNumber TeamB = GetGameRules()->GetTeamBNumber(); - AvHAIBuildableStructure* Result = NULL; + AvHAIBuildableStructure Result; + float CurrMinDist = 0.0f; + + float MinDistSq = sqrf(Filter->MinSearchRadius); + float MaxDistSq = sqrf(Filter->MaxSearchRadius); + + bool bUseMinDist = MinDistSq > 0.1f; + bool bUseMaxDist = MaxDistSq > 0.1f; + + if (Filter->DeployableTeam == TeamA || Filter->DeployableTeam == TEAM_IND) + { + for (auto& it : TeamAStructureMap) + { + if (FNullEnt(it.second.edict) || it.second.edict->v.deadflag != DEAD_NO || (it.second.edict->v.effects & EF_NODRAW)) { continue; } + + if (it.second.StructureStatusFlags & Filter->ExcludeStatusFlags) { continue; } + if ((it.second.StructureStatusFlags & Filter->IncludeStatusFlags) != Filter->IncludeStatusFlags) { continue; } + + unsigned int StructureReachabilityFlags = (it.second.TeamAReachabilityFlags | it.second.TeamBReachabilityFlags); + + if (Filter->ReachabilityTeam != TEAM_IND) + { + StructureReachabilityFlags = (Filter->ReachabilityTeam == TeamA) ? it.second.TeamAReachabilityFlags : it.second.TeamBReachabilityFlags; + } + + if (Filter->ReachabilityFlags != AI_REACHABILITY_NONE && !(StructureReachabilityFlags & Filter->ReachabilityFlags)) { continue; } + + if (it.second.StructureType & Filter->DeployableTypes) + { + if (!UTIL_PointIsDirectlyReachable(pBot->BotNavInfo.NavProfile, pBot->Edict->v.origin, it.second.Location)) { continue; } + + float DistSq = (Filter->bConsiderPhaseDistance) ? sqrf(AITAC_GetPhaseDistanceBetweenPoints(it.second.Location, Location)) : vDist2DSq(it.second.Location, Location); + + if ((!bUseMinDist || DistSq >= MinDistSq) && (!bUseMaxDist || DistSq <= MaxDistSq) && (!Result.IsValid() || DistSq < CurrMinDist)) + { + Result = it.second; + CurrMinDist = DistSq; + } + } + } + } + + if (Filter->DeployableTeam == TeamB || Filter->DeployableTeam == TEAM_IND) + { + for (auto& it : TeamBStructureMap) + { + if (FNullEnt(it.second.edict) || it.second.edict->v.deadflag != DEAD_NO || (it.second.edict->v.effects & EF_NODRAW)) { continue; } + + if (it.second.StructureStatusFlags & Filter->ExcludeStatusFlags) { continue; } + if ((it.second.StructureStatusFlags & Filter->IncludeStatusFlags) != Filter->IncludeStatusFlags) { continue; } + + unsigned int StructureReachabilityFlags = (it.second.TeamAReachabilityFlags | it.second.TeamBReachabilityFlags); + + if (Filter->ReachabilityTeam != TEAM_IND) + { + StructureReachabilityFlags = (Filter->ReachabilityTeam == TeamA) ? it.second.TeamAReachabilityFlags : it.second.TeamBReachabilityFlags; + } + + if (Filter->ReachabilityFlags != AI_REACHABILITY_NONE && !(StructureReachabilityFlags & Filter->ReachabilityFlags)) { continue; } + + if (it.second.StructureType & Filter->DeployableTypes) + { + if (!UTIL_PointIsDirectlyReachable(pBot->BotNavInfo.NavProfile, pBot->Edict->v.origin, it.second.Location)) { continue; } + + float DistSq = (Filter->bConsiderPhaseDistance) ? sqrf(AITAC_GetPhaseDistanceBetweenPoints(it.second.Location, Location)) : vDist2DSq(it.second.Location, Location); + + if ((!bUseMinDist || DistSq >= MinDistSq) && (!bUseMaxDist || DistSq <= MaxDistSq) && (!Result.IsValid() || DistSq < CurrMinDist)) + { + Result = it.second; + CurrMinDist = DistSq; + } + } + } + } + + return Result; +} + +AvHAIBuildableStructure* AITAC_GetNearestDeployableDirectlyReachableByRef(AvHAIPlayer* pBot, const Vector Location, const DeployableSearchFilter* Filter) +{ + AvHTeamNumber TeamA = GetGameRules()->GetTeamANumber(); + AvHTeamNumber TeamB = GetGameRules()->GetTeamBNumber(); + + AvHAIBuildableStructure* Result = nullptr; float CurrMinDist = 0.0f; float MinDistSq = sqrf(Filter->MinSearchRadius); @@ -848,11 +1184,11 @@ Vector AITAC_GetTeamStartingLocation(AvHTeamNumber Team) IFFilter.IncludeStatusFlags = STRUCTURE_STATUS_COMPLETED; IFFilter.ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING; - AvHAIBuildableStructure* InfantryPortal = AITAC_FindClosestDeployableToLocation(ZERO_VECTOR, &IFFilter); + AvHAIBuildableStructure InfantryPortal = AITAC_FindClosestDeployableToLocation(ZERO_VECTOR, &IFFilter); - if (InfantryPortal) + if (InfantryPortal.IsValid()) { - TeamAStartingLocation = InfantryPortal->Location; + TeamAStartingLocation = InfantryPortal.Location; } else { @@ -890,11 +1226,11 @@ Vector AITAC_GetTeamStartingLocation(AvHTeamNumber Team) IFFilter.IncludeStatusFlags = STRUCTURE_STATUS_COMPLETED; IFFilter.ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING; - AvHAIBuildableStructure* InfantryPortal = AITAC_FindClosestDeployableToLocation(ZERO_VECTOR, &IFFilter); + AvHAIBuildableStructure InfantryPortal = AITAC_FindClosestDeployableToLocation(ZERO_VECTOR, &IFFilter); - if (InfantryPortal) + if (InfantryPortal.IsValid()) { - TeamBStartingLocation = InfantryPortal->Location; + TeamBStartingLocation = InfantryPortal.Location; } else { @@ -1387,12 +1723,12 @@ void AITAC_RefreshResourceNodes() DeployableSearchFilter TowerFilter; TowerFilter.DeployableTypes = (STRUCTURE_MARINE_RESTOWER | STRUCTURE_ALIEN_RESTOWER); - AvHAIBuildableStructure* OccupyingTower = AITAC_FindClosestDeployableToLocation(it->Location, &TowerFilter); + AvHAIBuildableStructure OccupyingTower = AITAC_FindClosestDeployableToLocation(it->Location, &TowerFilter); - if (OccupyingTower) + if (OccupyingTower.IsValid()) { - it->ActiveTowerEntity = OccupyingTower->edict; - it->OwningTeam = OccupyingTower->EntityRef->GetTeamNumber(); + it->ActiveTowerEntity = OccupyingTower.edict; + it->OwningTeam = OccupyingTower.EntityRef->GetTeamNumber(); } } else @@ -2218,25 +2554,25 @@ void AITAC_OnStructureCompleted(AvHAIBuildableStructure* NewStructure) Filter.IncludeStatusFlags = STRUCTURE_STATUS_COMPLETED; // Get all other completed phase gates for this team and add bidirectional connections to them - std::vector OtherPhaseGates = AITAC_FindAllDeployables(NewStructure->Location, &Filter); + std::vector OtherPhaseGates = AITAC_FindAllDeployables(NewStructure->Location, &Filter); SamplePolyFlags NewFlag = ((AvHTeamNumber)NewStructure->edict->v.team == GetGameRules()->GetTeamANumber()) ? SAMPLE_POLYFLAGS_TEAM1PHASEGATE : SAMPLE_POLYFLAGS_TEAM2PHASEGATE; for (auto pg = OtherPhaseGates.begin(); pg != OtherPhaseGates.end(); pg++) { // Don't add off-mesh connections to ourselves! - if ((*pg) == NewStructure) { continue; } + if (pg->edict == NewStructure->edict) { continue; } - AvHAIBuildableStructure* OtherPhaseGate = (*pg); + AvHAIBuildableStructure OtherPhaseGate = (*pg); AvHAIOffMeshConnection NewConnection; NewConnection.FromLocation = NewStructure->Location; - NewConnection.ToLocation = OtherPhaseGate->Location; + NewConnection.ToLocation = OtherPhaseGate.Location; NewConnection.ConnectionFlags = NewFlag; - NewConnection.TargetObject = OtherPhaseGate->edict; + NewConnection.TargetObject = OtherPhaseGate.edict; memset(&NewConnection.ConnectionRefs[0], 0, sizeof(NewConnection.ConnectionRefs)); - UTIL_AddOffMeshConnection(NewStructure->Location, OtherPhaseGate->Location, SAMPLE_POLYAREA_PHASEGATE, NewFlag, true, &NewConnection); + UTIL_AddOffMeshConnection(NewStructure->Location, OtherPhaseGate.Location, SAMPLE_POLYAREA_PHASEGATE, NewFlag, true, &NewConnection); NewStructure->OffMeshConnections.push_back(NewConnection); @@ -2312,12 +2648,12 @@ void AITAC_OnStructureDestroyed(AvHAIBuildableStructure* DestroyedStructure) Filter.IncludeStatusFlags = STRUCTURE_STATUS_COMPLETED; // Get all other completed phase gates for this team and remove any connections going to this structure - std::vector OtherPhaseGates = AITAC_FindAllDeployables(DestroyedStructure->Location, &Filter); + std::vector OtherPhaseGates = AITAC_FindAllDeployablesByRef(DestroyedStructure->Location, &Filter); for (auto it = OtherPhaseGates.begin(); it != OtherPhaseGates.end(); it++) { // Don't check for off-mesh connections from ourselves! - if ((*it) == DestroyedStructure) { continue; } + if ((*it)->edict == DestroyedStructure->edict) { continue; } AvHAIBuildableStructure* OtherPhaseGate = (*it); @@ -2531,21 +2867,21 @@ float AITAC_GetPhaseDistanceBetweenPoints(const Vector StartPoint, const Vector PGFilter.MaxSearchRadius = DirectDist; - AvHAIBuildableStructure* StartPhase = AITAC_FindClosestDeployableToLocation(StartPoint, &PGFilter); + AvHAIBuildableStructure StartPhase = AITAC_FindClosestDeployableToLocation(StartPoint, &PGFilter); - if (!StartPhase) + if (!StartPhase.IsValid()) { return DirectDist; } - AvHAIBuildableStructure* EndPhase = AITAC_FindClosestDeployableToLocation(EndPoint, &PGFilter); + AvHAIBuildableStructure EndPhase = AITAC_FindClosestDeployableToLocation(EndPoint, &PGFilter); - if (!EndPhase || EndPhase == StartPhase) + if (FNullEnt(EndPhase.edict) || EndPhase.edict == StartPhase.edict) { return DirectDist; } - float PhaseDist = vDist2DSq(StartPoint, StartPhase->edict->v.origin) + vDist2DSq(EndPoint, EndPhase->edict->v.origin); + float PhaseDist = vDist2DSq(StartPoint, StartPhase.edict->v.origin) + vDist2DSq(EndPoint, EndPhase.edict->v.origin); PhaseDist = sqrtf(PhaseDist); @@ -2689,11 +3025,11 @@ bool UTIL_IsBuildableStructureStillReachable(AvHAIPlayer* pBot, const edict_t* S AvHAIDeployableStructureType StructureType = GetStructureTypeFromEdict(Structure); if (StructureType == STRUCTURE_ALIEN_HIVE || StructureType == STRUCTURE_NONE) { return true; } - AvHAIBuildableStructure* StructureRef = AITAC_GetDeployableRefFromEdict(Structure); + AvHAIBuildableStructure StructureRef = AITAC_GetDeployableFromEdict(Structure); - if (!StructureRef) { return false; } + if (!StructureRef.IsValid()) { return false; } - unsigned int TeamReachability = (pBot->Edict->v.team == GetGameRules()->GetTeamANumber()) ? StructureRef->TeamAReachabilityFlags : StructureRef->TeamBReachabilityFlags; + unsigned int TeamReachability = (pBot->Edict->v.team == GetGameRules()->GetTeamANumber()) ? StructureRef.TeamAReachabilityFlags : StructureRef.TeamBReachabilityFlags; return (TeamReachability & pBot->BotNavInfo.NavProfile.ReachabilityFlag); } @@ -3436,13 +3772,13 @@ Vector UTIL_GetNextMinePosition2(edict_t* StructureToMine) MineFilter.DeployableTypes = STRUCTURE_MARINE_DEPLOYEDMINE; MineFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(3.0f); - vector SurroundingMines = AITAC_FindAllDeployables(StructureToMine->v.origin, &MineFilter); + vector SurroundingMines = AITAC_FindAllDeployables(StructureToMine->v.origin, &MineFilter); for (auto it = SurroundingMines.begin(); it != SurroundingMines.end(); it++) { - AvHAIBuildableStructure* ThisMine = (*it); + AvHAIBuildableStructure ThisMine = (*it); - Vector Dir = UTIL_GetVectorNormal2D(ThisMine->Location - StructureToMine->v.origin); + Vector Dir = UTIL_GetVectorNormal2D(ThisMine.Location - StructureToMine->v.origin); if (UTIL_GetDotProduct2D(FwdVector, Dir) > 0.7f) { @@ -3540,13 +3876,13 @@ Vector UTIL_GetNextMinePosition(edict_t* StructureToMine) MineFilter.DeployableTypes = STRUCTURE_MARINE_DEPLOYEDMINE; MineFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(3.0f); - vector SurroundingMines = AITAC_FindAllDeployables(StructureToMine->v.origin, &MineFilter); + vector SurroundingMines = AITAC_FindAllDeployables(StructureToMine->v.origin, &MineFilter); for (auto it = SurroundingMines.begin(); it != SurroundingMines.end(); it++) { - AvHAIBuildableStructure* ThisMine = (*it); + AvHAIBuildableStructure ThisMine = (*it); - Vector Dir = UTIL_GetVectorNormal2D(ThisMine->Location - StructureToMine->v.origin); + Vector Dir = UTIL_GetVectorNormal2D(ThisMine.Location - StructureToMine->v.origin); if (UTIL_GetDotProduct2D(FwdVector, Dir) > 0.7f) { @@ -3909,7 +4245,7 @@ edict_t* AITAC_GetCommChair(AvHTeamNumber Team) ChairFilter.DeployableTeam = Team; ChairFilter.ReachabilityTeam = TEAM_IND; - vector CommChairs = AITAC_FindAllDeployables(ZERO_VECTOR, &ChairFilter); + vector CommChairs = AITAC_FindAllDeployables(ZERO_VECTOR, &ChairFilter); edict_t* MainCommChair = nullptr; edict_t* BackupChair = nullptr; @@ -3917,7 +4253,7 @@ edict_t* AITAC_GetCommChair(AvHTeamNumber Team) // If the team has more than one comm chair, pick the one in use for (auto it = CommChairs.begin(); it != CommChairs.end(); it++) { - AvHCommandStation* ChairRef = dynamic_cast((*it)->EntityRef); + AvHCommandStation* ChairRef = dynamic_cast((*it).EntityRef); // Idle animation will be 3 if the chair is in use (closed animation). See AvHCommandStation::GetIdleAnimation if (ChairRef && ChairRef->GetIdleAnimation() == 3) @@ -4044,14 +4380,14 @@ const AvHAIHiveDefinition* AITAC_GetNearestHiveUnderActiveSiege(AvHTeamNumber Si SiegeFilter.IncludeStatusFlags = STRUCTURE_STATUS_COMPLETED; SiegeFilter.ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING; - AvHAIBuildableStructure* AdvTF = AITAC_FindClosestDeployableToLocation(it->Location, &SiegeFilter); + AvHAIBuildableStructure AdvTF = AITAC_FindClosestDeployableToLocation(it->Location, &SiegeFilter); - if (!AdvTF) { continue; } + if (!AdvTF.IsValid()) { continue; } SiegeFilter.DeployableTypes = STRUCTURE_MARINE_SIEGETURRET; SiegeFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(5.0f); - bool bSTExists = AITAC_DeployableExistsAtLocation(AdvTF->Location, &SiegeFilter); + bool bSTExists = AITAC_DeployableExistsAtLocation(AdvTF.Location, &SiegeFilter); if (bSTExists) { @@ -4642,7 +4978,7 @@ bool AITAC_IsAlienBuilderNeeded(AvHAIPlayer* pBot) ExistingReinforcementFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(10.0f); ExistingReinforcementFilter.DeployableTypes = SEARCH_ALL_ALIEN_STRUCTURES; - vector AllReinforcingStructures = AITAC_FindAllDeployables(ThisHive->FloorLocation, &ExistingReinforcementFilter); + vector AllReinforcingStructures = AITAC_FindAllDeployables(ThisHive->FloorLocation, &ExistingReinforcementFilter); int NumOCs = 0; int NumDCs = 0; @@ -4651,7 +4987,7 @@ bool AITAC_IsAlienBuilderNeeded(AvHAIPlayer* pBot) for (auto it = AllReinforcingStructures.begin(); it != AllReinforcingStructures.end(); it++) { - switch ((*it)->StructureType) + switch ((*it).StructureType) { case STRUCTURE_ALIEN_OFFENCECHAMBER: NumOCs++; @@ -4716,7 +5052,7 @@ bool AITAC_IsAlienBuilderNeeded(AvHAIPlayer* pBot) ExistingReinforcementFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(5.0f); ExistingReinforcementFilter.DeployableTypes = SEARCH_ALL_ALIEN_STRUCTURES; - vector AllReinforcingStructures = AITAC_FindAllDeployables(ThisNode->Location, &ExistingReinforcementFilter); + vector AllReinforcingStructures = AITAC_FindAllDeployables(ThisNode->Location, &ExistingReinforcementFilter); int NumOCs = 0; int NumDCs = 0; @@ -4725,7 +5061,7 @@ bool AITAC_IsAlienBuilderNeeded(AvHAIPlayer* pBot) for (auto it = AllReinforcingStructures.begin(); it != AllReinforcingStructures.end(); it++) { - switch ((*it)->StructureType) + switch ((*it).StructureType) { case STRUCTURE_ALIEN_OFFENCECHAMBER: NumOCs++; @@ -4852,22 +5188,22 @@ edict_t* AITAC_AlienFindNearestHealingSource(AvHTeamNumber Team, Vector SearchLo DCFilter.DeployableTypes = STRUCTURE_ALIEN_DEFENCECHAMBER; DCFilter.MaxSearchRadius = (!FNullEnt(Result)) ? MinDist : 0.0f; // We should always have a result, unless we have no hives left. That's our benchmark: only look for DCs closer than the hive - vector AllDCs = AITAC_FindAllDeployables(SearchLocation, &DCFilter); + vector AllDCs = AITAC_FindAllDeployables(SearchLocation, &DCFilter); for (auto it = AllDCs.begin(); it != AllDCs.end(); it++) { - AvHAIBuildableStructure* ThisDC = (*it); + AvHAIBuildableStructure ThisDC = (*it); - float ThisDist = vDist2DSq(ThisDC->Location, SearchLocation); + float ThisDist = vDist2DSq(ThisDC.Location, SearchLocation); // Factor healing radius into the distance checks, we don't have to be sat on top of the DC to heal ThisDist -= BALANCE_VAR(kHiveHealRadius) * 0.75f; // We're already in healing distance of a DC, that's our healing source - if (ThisDist <= 0.0f) { return ThisDC->edict; } + if (ThisDist <= 0.0f) { return ThisDC.edict; } if (FNullEnt(Result) || ThisDist < MinDist) { - Result = ThisDC->edict; + Result = ThisDC.edict; MinDist = ThisDist; } } diff --git a/main/source/mod/AIPlayers/AvHAITactical.h b/main/source/mod/AIPlayers/AvHAITactical.h index 17bb2b09..673a42ec 100644 --- a/main/source/mod/AIPlayers/AvHAITactical.h +++ b/main/source/mod/AIPlayers/AvHAITactical.h @@ -21,11 +21,16 @@ static const float structure_inventory_refresh_rate = 0.2f; static const float item_inventory_refresh_rate = 0.2f; bool AITAC_DeployableExistsAtLocation(const Vector& Location, const DeployableSearchFilter* Filter); -std::vector AITAC_FindAllDeployables(const Vector& Location, const DeployableSearchFilter* Filter); -AvHAIBuildableStructure* AITAC_FindClosestDeployableToLocation(const Vector& Location, const DeployableSearchFilter* Filter); -AvHAIBuildableStructure* AITAC_FindFurthestDeployableFromLocation(const Vector& Location, const DeployableSearchFilter* Filter); +std::vector AITAC_FindAllDeployables(const Vector& Location, const DeployableSearchFilter* Filter); +std::vector AITAC_FindAllDeployablesByRef(const Vector& Location, const DeployableSearchFilter* Filter); +AvHAIBuildableStructure AITAC_FindClosestDeployableToLocation(const Vector& Location, const DeployableSearchFilter* Filter); +AvHAIBuildableStructure* AITAC_FindClosestDeployableToLocationByRef(const Vector& Location, const DeployableSearchFilter* Filter); +AvHAIBuildableStructure AITAC_FindFurthestDeployableFromLocation(const Vector& Location, const DeployableSearchFilter* Filter); +AvHAIBuildableStructure* AITAC_FindFurthestDeployableFromLocationByRef(const Vector& Location, const DeployableSearchFilter* Filter); +AvHAIBuildableStructure AITAC_GetDeployableFromEdict(const edict_t* Structure); AvHAIBuildableStructure* AITAC_GetDeployableRefFromEdict(const edict_t* Structure); -AvHAIBuildableStructure* AITAC_GetNearestDeployableDirectlyReachable(AvHAIPlayer* pBot, const Vector Location, const DeployableSearchFilter* Filter); +AvHAIBuildableStructure AITAC_GetNearestDeployableDirectlyReachable(AvHAIPlayer* pBot, const Vector Location, const DeployableSearchFilter* Filter); +AvHAIBuildableStructure* AITAC_GetNearestDeployableDirectlyReachableByRef(AvHAIPlayer* pBot, const Vector Location, const DeployableSearchFilter* Filter); int AITAC_GetNumDeployablesNearLocation(const Vector& Location, const DeployableSearchFilter* Filter); void AITAC_PopulateHiveData(); void AITAC_RefreshHiveData(); diff --git a/main/source/mod/AIPlayers/AvHAITask.cpp b/main/source/mod/AIPlayers/AvHAITask.cpp index 0cb2223f..a3eb6d60 100644 --- a/main/source/mod/AIPlayers/AvHAITask.cpp +++ b/main/source/mod/AIPlayers/AvHAITask.cpp @@ -91,11 +91,11 @@ void AITASK_OnCompleteCommanderTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) EnemyResTowerFilter.ReachabilityTeam = (AvHTeamNumber)pBot->Edict->v.team; EnemyResTowerFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(5.0f); - AvHAIBuildableStructure* NearbyAlienTower = AITAC_FindClosestDeployableToLocation(pBot->Edict->v.origin, &EnemyResTowerFilter); + AvHAIBuildableStructure NearbyAlienTower = AITAC_FindClosestDeployableToLocation(pBot->Edict->v.origin, &EnemyResTowerFilter); - if (NearbyAlienTower) + if (NearbyAlienTower.IsValid()) { - const AvHAIResourceNode* NodeRef = AITAC_GetNearestResourceNodeToLocation(NearbyAlienTower->Location); + const AvHAIResourceNode* NodeRef = AITAC_GetNearestResourceNodeToLocation(NearbyAlienTower.Location); if (NodeRef) { AITASK_SetCapResNodeTask(pBot, Task, NodeRef, false); @@ -820,7 +820,7 @@ bool AITASK_IsReinforceStructureTaskStillValid(AvHAIPlayer* pBot, AvHAIPlayerTas StructureFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(5.0f); StructureFilter.DeployableTeam = pBot->Player->GetTeam(); - vector AllNearbyStructures = AITAC_FindAllDeployables(Task->TaskTarget->v.origin, &StructureFilter); + vector AllNearbyStructures = AITAC_FindAllDeployables(Task->TaskTarget->v.origin, &StructureFilter); bool bUnfinishedStructureExists = false; int NumOffenceChambers = 0; @@ -830,11 +830,11 @@ bool AITASK_IsReinforceStructureTaskStillValid(AvHAIPlayer* pBot, AvHAIPlayerTas for (auto it = AllNearbyStructures.begin(); it != AllNearbyStructures.end(); it++) { - AvHAIBuildableStructure* ThisStructure = (*it); + AvHAIBuildableStructure ThisStructure = (*it); - if (!(ThisStructure->StructureStatusFlags & STRUCTURE_STATUS_COMPLETED)) { bUnfinishedStructureExists = true; } + if (!(ThisStructure.StructureStatusFlags & STRUCTURE_STATUS_COMPLETED)) { bUnfinishedStructureExists = true; } - switch (ThisStructure->StructureType) + switch (ThisStructure.StructureType) { case STRUCTURE_ALIEN_OFFENCECHAMBER: NumOffenceChambers++; @@ -909,25 +909,25 @@ bool AITASK_IsMarineSecureHiveTaskStillValid(AvHAIPlayer* pBot, AvHAIPlayerTask* SearchFilter.ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING; SearchFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(15.0f); - vector HiveStructures = AITAC_FindAllDeployables(HiveToSecure->FloorLocation, &SearchFilter); + vector HiveStructures = AITAC_FindAllDeployables(HiveToSecure->FloorLocation, &SearchFilter); for (auto it = HiveStructures.begin(); it != HiveStructures.end(); it++) { - AvHAIBuildableStructure* Structure = (*it); + AvHAIBuildableStructure Structure = (*it); - if (Structure->StructureType == STRUCTURE_MARINE_TURRETFACTORY) + if (Structure.StructureType == STRUCTURE_MARINE_TURRETFACTORY) { bHasPhaseGate = true; } - if (Structure->StructureType == STRUCTURE_MARINE_TURRETFACTORY || Structure->StructureType == STRUCTURE_MARINE_ADVTURRETFACTORY) + if (Structure.StructureType == STRUCTURE_MARINE_TURRETFACTORY || Structure.StructureType == STRUCTURE_MARINE_ADVTURRETFACTORY) { bHasTurretFactory = true; SearchFilter.DeployableTypes = STRUCTURE_MARINE_TURRET; SearchFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(8.0f); - NumTurrets = AITAC_GetNumDeployablesNearLocation(Structure->Location, &SearchFilter); + NumTurrets = AITAC_GetNumDeployablesNearLocation(Structure.Location, &SearchFilter); } @@ -1343,11 +1343,11 @@ void BotProgressReinforceStructureTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) UnfinishedFilter.DeployableTypes = SEARCH_ALL_ALIEN_STRUCTURES; UnfinishedFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(10.0f); - AvHAIBuildableStructure* UnfinishedStructure = AITAC_FindClosestDeployableToLocation(ReinforceLocation, &UnfinishedFilter); + AvHAIBuildableStructure UnfinishedStructure = AITAC_FindClosestDeployableToLocation(ReinforceLocation, &UnfinishedFilter); - if (UnfinishedStructure) + if (UnfinishedStructure.IsValid()) { - AIPlayerBuildStructure(pBot, UnfinishedStructure->edict); + AIPlayerBuildStructure(pBot, UnfinishedStructure.edict); return; } } @@ -1362,11 +1362,11 @@ void BotProgressReinforceStructureTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) EnemyStructureFilter.ReachabilityFlags = pBot->BotNavInfo.NavProfile.ReachabilityFlag; EnemyStructureFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(10.0f); - AvHAIBuildableStructure* EnemyStructure = AITAC_FindClosestDeployableToLocation(ReinforceLocation, &EnemyStructureFilter); + AvHAIBuildableStructure EnemyStructure = AITAC_FindClosestDeployableToLocation(ReinforceLocation, &EnemyStructureFilter); - if (EnemyStructure) + if (EnemyStructure.IsValid()) { - BotAttackNonPlayerTarget(pBot, EnemyStructure->edict); + BotAttackNonPlayerTarget(pBot, EnemyStructure.edict); return; } @@ -1738,12 +1738,12 @@ void BotProgressDefendTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) return; } - AvHAIBuildableStructure* StructureRef = AITAC_GetDeployableRefFromEdict(Task->TaskTarget); + AvHAIBuildableStructure StructureRef = AITAC_GetDeployableFromEdict(Task->TaskTarget); - if (!StructureRef) { return; } + if (!StructureRef.IsValid()) { return; } // If the structure we're defending was damaged just now, look at it so we can see who is attacking - if (gpGlobals->time - StructureRef->lastDamagedTime < 5.0f) + if (gpGlobals->time - StructureRef.lastDamagedTime < 5.0f) { if (UTIL_QuickTrace(pBot->Edict, pBot->CurrentEyePosition, UTIL_GetCentreOfEntity(Task->TaskTarget))) { @@ -2001,11 +2001,11 @@ void AlienProgressBuildTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) UnfinishedFilter.ExcludeStatusFlags = STRUCTURE_STATUS_COMPLETED; UnfinishedFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(10.0f); - AvHAIBuildableStructure* UnfinishedStructure = AITAC_FindClosestDeployableToLocation(Task->TaskLocation, &UnfinishedFilter); + AvHAIBuildableStructure UnfinishedStructure = AITAC_FindClosestDeployableToLocation(Task->TaskLocation, &UnfinishedFilter); - if (UnfinishedStructure) + if (UnfinishedStructure.IsValid()) { - AIPlayerBuildStructure(pBot, UnfinishedStructure->edict); + AIPlayerBuildStructure(pBot, UnfinishedStructure.edict); return; } } @@ -2240,11 +2240,11 @@ void AlienProgressCapResNodeTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) PGFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(5.0f); PGFilter.ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING; - AvHAIBuildableStructure* PG = AITAC_FindClosestDeployableToLocation(ResNodeIndex->Location, &PGFilter); + AvHAIBuildableStructure PG = AITAC_FindClosestDeployableToLocation(ResNodeIndex->Location, &PGFilter); - if (PG) + if (PG.IsValid()) { - BotAttackNonPlayerTarget(pBot, PG->edict); + BotAttackNonPlayerTarget(pBot, PG.edict); return; } } @@ -2301,11 +2301,11 @@ void AlienProgressCapResNodeTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) EnemyStructureFilter.DeployableTypes = SEARCH_ALL_STRUCTURES; EnemyStructureFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(5.0f); - AvHAIBuildableStructure* AttackTarget = AITAC_FindClosestDeployableToLocation(ResNodeIndex->Location, &EnemyStructureFilter); + AvHAIBuildableStructure AttackTarget = AITAC_FindClosestDeployableToLocation(ResNodeIndex->Location, &EnemyStructureFilter); - if (AttackTarget) + if (AttackTarget.IsValid()) { - BotAttackNonPlayerTarget(pBot, AttackTarget->edict); + BotAttackNonPlayerTarget(pBot, AttackTarget.edict); return; } } @@ -2505,43 +2505,43 @@ void MarineProgressSecureHiveTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) StructureFilter.ReachabilityFlags = pBot->BotNavInfo.NavProfile.ReachabilityFlag; StructureFilter.ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING; - vector BuildableStructures = AITAC_FindAllDeployables(Hive->FloorLocation, &StructureFilter); + vector BuildableStructures = AITAC_FindAllDeployables(Hive->FloorLocation, &StructureFilter); bool bKeyStructureBuilt = false; - AvHAIBuildableStructure* StructureToBuild = nullptr; + AvHAIBuildableStructure StructureToBuild; float MinDist = 0.0f; for (auto it = BuildableStructures.begin(); it != BuildableStructures.end(); it++) { - AvHAIBuildableStructure* ThisStructure = (*it); + AvHAIBuildableStructure ThisStructure = (*it); - if ((ThisStructure->StructureStatusFlags & STRUCTURE_STATUS_COMPLETED) && (ThisStructure->StructureType & (STRUCTURE_MARINE_TURRETFACTORY | STRUCTURE_MARINE_ADVTURRETFACTORY | STRUCTURE_MARINE_PHASEGATE))) + if ((ThisStructure.StructureStatusFlags & STRUCTURE_STATUS_COMPLETED) && (ThisStructure.StructureType & (STRUCTURE_MARINE_TURRETFACTORY | STRUCTURE_MARINE_ADVTURRETFACTORY | STRUCTURE_MARINE_PHASEGATE))) { bKeyStructureBuilt = true; } - if (ThisStructure->StructureStatusFlags & STRUCTURE_STATUS_COMPLETED) { continue; } + if (ThisStructure.StructureStatusFlags & STRUCTURE_STATUS_COMPLETED) { continue; } // Phase gates always take priority, so just go and build it if there is one - if (ThisStructure->StructureType == STRUCTURE_MARINE_PHASEGATE) + if (ThisStructure.StructureType == STRUCTURE_MARINE_PHASEGATE) { - AIPlayerBuildStructure(pBot, ThisStructure->edict); + AIPlayerBuildStructure(pBot, ThisStructure.edict); return; } - float ThisDist = vDist2DSq(pBot->Edict->v.origin, ThisStructure->Location); + float ThisDist = vDist2DSq(pBot->Edict->v.origin, ThisStructure.Location); - if (!StructureToBuild || ThisDist < MinDist) + if (FNullEnt(StructureToBuild.edict) || ThisDist < MinDist) { StructureToBuild = ThisStructure; MinDist = ThisDist; } } - if (StructureToBuild) + if (StructureToBuild.IsValid()) { - AIPlayerBuildStructure(pBot, StructureToBuild->edict); + AIPlayerBuildStructure(pBot, StructureToBuild.edict); return; } @@ -2579,11 +2579,11 @@ void MarineProgressSecureHiveTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) EnemyStructures.ReachabilityTeam = BotTeam; EnemyStructures.ReachabilityFlags = pBot->BotNavInfo.NavProfile.ReachabilityFlag; - AvHAIBuildableStructure* EnemyStructure = AITAC_FindClosestDeployableToLocation(Hive->FloorLocation, &EnemyStructures); + AvHAIBuildableStructure EnemyStructure = AITAC_FindClosestDeployableToLocation(Hive->FloorLocation, &EnemyStructures); - if (EnemyStructure) + if (EnemyStructure.IsValid()) { - BotAttackNonPlayerTarget(pBot, EnemyStructure->edict); + BotAttackNonPlayerTarget(pBot, EnemyStructure.edict); return; } } @@ -2638,11 +2638,11 @@ void MarineProgressCapResNodeTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) EnemyStructureFilter.ReachabilityFlags = pBot->BotNavInfo.NavProfile.ReachabilityFlag; EnemyStructureFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(5.0f); - AvHAIBuildableStructure* EnemyStructure = AITAC_FindClosestDeployableToLocation(Task->TaskLocation, &EnemyStructureFilter); + AvHAIBuildableStructure EnemyStructure = AITAC_FindClosestDeployableToLocation(Task->TaskLocation, &EnemyStructureFilter); - if (EnemyStructure) + if (EnemyStructure.IsValid()) { - BotAttackNonPlayerTarget(pBot, EnemyStructure->edict); + BotAttackNonPlayerTarget(pBot, EnemyStructure.edict); return; } } @@ -2661,13 +2661,13 @@ void MarineProgressCapResNodeTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) EnemyStructureFilter.ReachabilityFlags = pBot->BotNavInfo.NavProfile.ReachabilityFlag; EnemyStructureFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(5.0f); - AvHAIBuildableStructure* EnemyStructure = AITAC_FindClosestDeployableToLocation(Task->TaskLocation, &EnemyStructureFilter); + AvHAIBuildableStructure EnemyStructure = AITAC_FindClosestDeployableToLocation(Task->TaskLocation, &EnemyStructureFilter); - if (EnemyStructure) + if (EnemyStructure.IsValid()) { // Cancel the waiting timeout since we have something useful to do Task->TaskLength = 0.0f; - BotAttackNonPlayerTarget(pBot, EnemyStructure->edict); + BotAttackNonPlayerTarget(pBot, EnemyStructure.edict); return; } else diff --git a/main/source/mod/AvHConsoleCommands.cpp b/main/source/mod/AvHConsoleCommands.cpp index f78e529f..e7d984fa 100644 --- a/main/source/mod/AvHConsoleCommands.cpp +++ b/main/source/mod/AvHConsoleCommands.cpp @@ -1454,6 +1454,21 @@ BOOL AvHGamerules::ClientCommand( CBasePlayer *pPlayer, const char *pcmd ) { AIDEBUG_DrawOffMeshConnections(10.0f); + theSuccess = true; + } + else if (FStrEq(pcmd, "ai_saysomething")) + { + vector AIPlayers = AIMGR_GetAllAIPlayers(); + + for (auto it = AIPlayers.begin(); it != AIPlayers.end(); it++) + { + AvHAIPlayer* thisBot = (*it); + { + BotSay(thisBot, false, 1.0f, "Regular Chat"); + BotSay(thisBot, true, 2.0f, "Team Chat"); + } + } + theSuccess = true; } else if( FStrEq( pcmd, kcRemoveUpgrade) ) diff --git a/main/source/mod/AvHGamerules.cpp b/main/source/mod/AvHGamerules.cpp index f67b9883..1a95c9fa 100644 --- a/main/source/mod/AvHGamerules.cpp +++ b/main/source/mod/AvHGamerules.cpp @@ -2323,6 +2323,11 @@ void AvHGamerules::PostWorldPrecacheReset(bool inNewMap) // Must happen after processing spawn entities this->RecalculateMapMode(); + if (avh_botsenabled.value > 0) + { + AIMGR_LoadNavigationData(); + } + // Loop through all players that are playing and respawn them bool theJustResetGameAtCountdownStart = false;