From f427a9c052846d345b3c6f199ebaee0a266b5ddb Mon Sep 17 00:00:00 2001 From: RGreenlees Date: Thu, 30 May 2024 13:44:46 +0100 Subject: [PATCH] Stability and randomness improvements * Fixed potential crashing when obtaining references to dropped items * Fixed issues with random number generation --- main/source/mod/AvHAICommander.cpp | 22 ++-- main/source/mod/AvHAIConfig.cpp | 14 ++- main/source/mod/AvHAIConstants.h | 2 + main/source/mod/AvHAIMath.cpp | 7 -- main/source/mod/AvHAINavigation.cpp | 10 +- main/source/mod/AvHAIPlayer.cpp | 175 +++++++++------------------- main/source/mod/AvHAITactical.cpp | 20 ++-- main/source/mod/AvHAITactical.h | 4 +- main/source/mod/AvHAITask.cpp | 24 ++-- 9 files changed, 107 insertions(+), 171 deletions(-) diff --git a/main/source/mod/AvHAICommander.cpp b/main/source/mod/AvHAICommander.cpp index a3032de2..6cfa65f3 100644 --- a/main/source/mod/AvHAICommander.cpp +++ b/main/source/mod/AvHAICommander.cpp @@ -1453,10 +1453,10 @@ bool AICOMM_CheckForNextSupplyAction(AvHAIPlayer* pBot) if (bBaseIsDamaged) { - AvHAIDroppedItem* NearestWelder = AITAC_FindClosestItemToLocation(AITAC_GetCommChairLocation(CommanderTeam), DEPLOYABLE_ITEM_WELDER, CommanderTeam, AI_REACHABILITY_MARINE, 0.0f, UTIL_MetresToGoldSrcUnits(15.0f), false); + AvHAIDroppedItem NearestWelder = AITAC_FindClosestItemToLocation(AITAC_GetCommChairLocation(CommanderTeam), DEPLOYABLE_ITEM_WELDER, CommanderTeam, AI_REACHABILITY_MARINE, 0.0f, UTIL_MetresToGoldSrcUnits(15.0f), false); bool bPlayerHasWelder = false; - if (!NearestWelder) + if (!NearestWelder.IsValid()) { vector PlayersAtBase = AITAC_GetAllPlayersOfTeamInArea(CommanderTeam, AITAC_GetCommChairLocation(CommanderTeam), UTIL_MetresToGoldSrcUnits(15.0f), false, pBot->Edict, AVH_USER3_COMMANDER_PLAYER); @@ -1471,7 +1471,7 @@ bool AICOMM_CheckForNextSupplyAction(AvHAIPlayer* pBot) } } - if (!NearestWelder && !bPlayerHasWelder) + if (!NearestWelder.IsValid() && !bPlayerHasWelder) { DeployableSearchFilter ArmouryFilter; ArmouryFilter.DeployableTypes = (STRUCTURE_MARINE_ARMOURY | STRUCTURE_MARINE_ADVARMOURY); @@ -1659,11 +1659,11 @@ bool AICOMM_CheckForNextSupplyAction(AvHAIPlayer* pBot) 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; } + if (ExistingHA.IsValid() && ExistingHMG.IsValid() && ExistingWelder.IsValid()) { return false; } vector NearbyPlayers = AITAC_GetAllPlayersOfClassInArea(CommanderTeam, NearestAdvArmoury.Location, UTIL_MetresToGoldSrcUnits(10.0f), false, pBot->Edict, AVH_USER3_MARINE_PLAYER); @@ -1692,7 +1692,7 @@ bool AICOMM_CheckForNextSupplyAction(AvHAIPlayer* pBot) } } - if (!ExistingHA && !bDropWelder && !bDropWeapon) + if (!ExistingHA.IsValid() && !bDropWelder && !bDropWeapon) { Vector DeployLocation = UTIL_GetRandomPointOnNavmeshInRadiusIgnoreReachability(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), NearestPrototypeLab.Location, UTIL_MetresToGoldSrcUnits(3.0f)); @@ -1706,7 +1706,7 @@ bool AICOMM_CheckForNextSupplyAction(AvHAIPlayer* pBot) return bSuccess; } - if (bDropWeapon && !ExistingHMG) + if (bDropWeapon && !ExistingHMG.IsValid()) { Vector DeployLocation = UTIL_GetRandomPointOnNavmeshInRadiusIgnoreReachability(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), NearestAdvArmoury.Location, UTIL_MetresToGoldSrcUnits(3.0f)); @@ -1720,7 +1720,7 @@ bool AICOMM_CheckForNextSupplyAction(AvHAIPlayer* pBot) return bSuccess; } - if (bDropWelder && !ExistingWelder) + if (bDropWelder && !ExistingWelder.IsValid()) { Vector DeployLocation = UTIL_GetRandomPointOnNavmeshInRadiusIgnoreReachability(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), NearestAdvArmoury.Location, UTIL_MetresToGoldSrcUnits(3.0f)); @@ -2402,6 +2402,8 @@ bool AICOMM_BuildInfantryPortal(AvHAIPlayer* pBot, edict_t* CommChair) if (vIsZero(BuildLocation)) { return false; } + UTIL_DrawLine(INDEXENT(1), BuildLocation, BuildLocation + Vector(0.0f, 0.0f, 100.0f), 2.0f); + return AICOMM_DeployStructure(pBot, STRUCTURE_MARINE_INFANTRYPORTAL, BuildLocation, STRUCTURE_PURPOSE_BASE); } diff --git a/main/source/mod/AvHAIConfig.cpp b/main/source/mod/AvHAIConfig.cpp index 61d37055..5f5f4f9f 100644 --- a/main/source/mod/AvHAIConfig.cpp +++ b/main/source/mod/AvHAIConfig.cpp @@ -20,6 +20,8 @@ bot_skill BotSkillLevels[4]; std::vector ChamberSequence; +bool bRNGSeeded = false; + string DefaultBotNames[MAX_PLAYERS] = { "MrRobot", "Wall-E", "BeepBoop", @@ -185,7 +187,6 @@ void CONFIG_PopulateBotNames() if (BotNames.size() > 2) { auto rng = std::default_random_engine{}; - rng.seed(time(0)); std::shuffle(begin(BotNames), end(BotNames), rng); } @@ -200,7 +201,6 @@ void CONFIG_PopulateBotNames() if (DefaultNames.size() > 2) { auto rng = std::default_random_engine{}; - rng.seed(time(0)); std::shuffle(begin(DefaultNames), end(DefaultNames), rng); } @@ -274,9 +274,15 @@ void CONFIG_ParseConfigFile() ChamberSequence.push_back(ALIEN_BUILD_MOVEMENT_CHAMBER); ChamberSequence.push_back(ALIEN_BUILD_SENSORY_CHAMBER); - std::srand(time(0)); auto rng = std::default_random_engine{}; - rng.seed(time(0)); + + if (!bRNGSeeded) + { + srand(time(NULL)); + rng.seed(time(NULL)); + bRNGSeeded = true; + } + std::shuffle(std::begin(ChamberSequence), std::end(ChamberSequence), rng); string BotConfigFile = string(getModDirectory()) + "/nsbots.ini"; diff --git a/main/source/mod/AvHAIConstants.h b/main/source/mod/AvHAIConstants.h index c89b17c4..f8becb46 100644 --- a/main/source/mod/AvHAIConstants.h +++ b/main/source/mod/AvHAIConstants.h @@ -372,6 +372,8 @@ typedef struct _DROPPED_MARINE_ITEM unsigned int TeamBReachabilityFlags = AI_REACHABILITY_NONE; bool bReachabilityMarkedDirty = false; // Reachability needs to be recalculated int LastSeen = 0; // Which refresh cycle was this last seen on? Used to determine if the item has been removed from play + + bool IsValid() { return !FNullEnt(edict) && !edict->free && !(edict->v.flags & EF_NODRAW) && edict->v.deadflag == DEAD_NO; } } AvHAIDroppedItem; // How far a bot can be from a useable object when trying to interact with it. Used also for melee attacks. We make it slightly less than actual to avoid edge cases diff --git a/main/source/mod/AvHAIMath.cpp b/main/source/mod/AvHAIMath.cpp index a146179a..ed9a58f7 100644 --- a/main/source/mod/AvHAIMath.cpp +++ b/main/source/mod/AvHAIMath.cpp @@ -403,7 +403,6 @@ Vector UTIL_RandomPointOnCircle(const Vector origin, const float radius) { Vector result; - srand(time(NULL)); float random = ((float)rand()) / (float)RAND_MAX; float a = random * (MATH_PI * 2); @@ -643,7 +642,6 @@ float fInterpConstantTo(float start, float end, float DeltaTime, float InterpSpe float frandrange(float MinValue, float MaxValue) { - srand(time(NULL)); return ((float(rand()) / float(RAND_MAX)) * (MaxValue - MinValue)) + MinValue; } @@ -651,14 +649,11 @@ int irandrange(int MinValue, int MaxValue) { if (MinValue == MaxValue) { return MinValue; } - srand(time(NULL)); - return MinValue + rand() / (RAND_MAX / (MaxValue - MinValue + 1) + 1); } bool randbool() { - srand(time(NULL)); return (rand() & 1); } @@ -666,8 +661,6 @@ Vector random_unit_vector_within_cone(const Vector Direction, double cone_half_a { Vector Result = ZERO_VECTOR; - srand(time(NULL)); - double u = ((double)rand() / RAND_MAX) * 2 - 1; // random number in [-1, 1] double phi = ((double)rand() / RAND_MAX) * 2 * M_PI; // random number in [0, 2*pi] double r = sqrt(1 - u * u); diff --git a/main/source/mod/AvHAINavigation.cpp b/main/source/mod/AvHAINavigation.cpp index dc860cbf..ba37bf56 100644 --- a/main/source/mod/AvHAINavigation.cpp +++ b/main/source/mod/AvHAINavigation.cpp @@ -6448,9 +6448,9 @@ void MarineUpdateBotMoveProfile(AvHAIPlayer* pBot, BotMoveStyle MoveStyle) if (!bHasWelder) { - AvHAIDroppedItem* NearbyWelder = AITAC_FindClosestItemToLocation(pBot->Edict->v.origin, DEPLOYABLE_ITEM_WELDER, pBot->Player->GetTeam(), pBot->BotNavInfo.NavProfile.ReachabilityFlag, 0.0f, UTIL_MetresToGoldSrcUnits(10.0f), true); + AvHAIDroppedItem NearbyWelder = AITAC_FindClosestItemToLocation(pBot->Edict->v.origin, DEPLOYABLE_ITEM_WELDER, pBot->Player->GetTeam(), pBot->BotNavInfo.NavProfile.ReachabilityFlag, 0.0f, UTIL_MetresToGoldSrcUnits(10.0f), true); - bHasWelder = (NearbyWelder != nullptr); + bHasWelder = (NearbyWelder.IsValid()); } // Did our nav profile previously indicate we could go through weldable doors? @@ -6914,11 +6914,11 @@ bool MoveTo(AvHAIPlayer* pBot, const Vector Destination, const BotMoveStyle Move { nav_profile BaseProfile = GetBaseNavProfile(MARINE_BASE_NAV_PROFILE); - AvHAIDroppedItem* NearestWelder = AITAC_FindClosestItemToLocation(pBot->Edict->v.origin, DEPLOYABLE_ITEM_WELDER, pBot->Player->GetTeam(), BaseProfile.ReachabilityFlag, 0.0f, 0.0f, true); + AvHAIDroppedItem NearestWelder = AITAC_FindClosestItemToLocation(pBot->Edict->v.origin, DEPLOYABLE_ITEM_WELDER, pBot->Player->GetTeam(), BaseProfile.ReachabilityFlag, 0.0f, 0.0f, true); - if (NearestWelder) + if (NearestWelder.IsValid()) { - NAV_SetPickupMovementTask(pBot, NearestWelder->edict, nullptr); + NAV_SetPickupMovementTask(pBot, NearestWelder.edict, nullptr); return true; } } diff --git a/main/source/mod/AvHAIPlayer.cpp b/main/source/mod/AvHAIPlayer.cpp index 93ae9d72..6ebca69d 100644 --- a/main/source/mod/AvHAIPlayer.cpp +++ b/main/source/mod/AvHAIPlayer.cpp @@ -1896,107 +1896,36 @@ void CustomThink(AvHAIPlayer* pBot) AITASK_BotUpdateAndClearTasks(pBot); - if (pBot->CurrentTask->TaskType == TASK_REINFORCE_STRUCTURE) + if (!PlayerHasWeapon(pBot->Player, WEAPON_MARINE_MINES)) { - BotProgressTask(pBot, pBot->CurrentTask); - return; - } - - // No missing upgrade chambers to drop, let's look for empty hives we can start staking a claim to, to deny to the enemy - vector AllHives = AITAC_GetAllHives(); - - AvHAIHiveDefinition* HiveToSecure = nullptr; - - AvHTeamNumber BotTeam = pBot->Player->GetTeam(); - AvHTeamNumber EnemyTeam = AIMGR_GetEnemyTeam(BotTeam); - - float MinDist = 0.0f; - - for (auto it = AllHives.begin(); it != AllHives.end(); it++) - { - AvHAIHiveDefinition* ThisHive = (*it); - - if (ThisHive->Status == HIVE_STATUS_UNBUILT) + if (pBot->CurrentTask->TaskType != TASK_GET_WEAPON) { - unsigned int StructureTypes = (STRUCTURE_MARINE_PHASEGATE | STRUCTURE_MARINE_TURRETFACTORY | STRUCTURE_MARINE_ADVTURRETFACTORY); + AvHAIDroppedItem Mines = AITAC_FindClosestItemToLocation(pBot->Edict->v.origin, DEPLOYABLE_ITEM_MINES, pBot->Player->GetTeam(), pBot->BotNavInfo.NavProfile.ReachabilityFlag, 0.0f, 0.0f, false); - if (AIMGR_GetTeamType(EnemyTeam) == AVH_CLASS_TYPE_ALIEN) + if (Mines.IsValid()) { - StructureTypes = STRUCTURE_ALIEN_OFFENCECHAMBER; + AITASK_SetPickupTask(pBot, pBot->CurrentTask, Mines.edict, true); } + } + } + else + { + if (pBot->CurrentTask->TaskType != TASK_PLACE_MINE) + { - DeployableSearchFilter EnemyStructureFilter; - EnemyStructureFilter.DeployableTeam = EnemyTeam; - EnemyStructureFilter.IncludeStatusFlags = STRUCTURE_STATUS_COMPLETED; - EnemyStructureFilter.ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING; - EnemyStructureFilter.DeployableTypes = StructureTypes; - EnemyStructureFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(10.0f); + DeployableSearchFilter TFFilter; + TFFilter.DeployableTypes = STRUCTURE_MARINE_TURRETFACTORY; - bool bEnemyHaveFoothold = AITAC_DeployableExistsAtLocation(ThisHive->FloorLocation, &EnemyStructureFilter); + AvHAIBuildableStructure NearestTF = AITAC_FindClosestDeployableToLocation(pBot->Edict->v.origin, &TFFilter); - if (bEnemyHaveFoothold) { continue; } - - if (AITAC_GetNumPlayersOfTeamInArea(EnemyTeam, ThisHive->FloorLocation, UTIL_MetresToGoldSrcUnits(10.0f), false, nullptr, AVH_USER3_COMMANDER_PLAYER) > 1) { continue; } - - int OtherBuilders = AITAC_GetNumPlayersOfTeamAndClassInArea(EnemyTeam, ThisHive->FloorLocation, UTIL_MetresToGoldSrcUnits(10.0f), false, nullptr, AVH_USER3_ALIEN_PLAYER2); - - if (OtherBuilders >= 2) { continue; } - - DeployableSearchFilter ExistingReinforcementFilter; - ExistingReinforcementFilter.DeployableTeam = BotTeam; - ExistingReinforcementFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(10.0f); - ExistingReinforcementFilter.DeployableTypes = SEARCH_ALL_STRUCTURES; - - vector AllReinforcingStructures = AITAC_FindAllDeployables(ThisHive->FloorLocation, &ExistingReinforcementFilter); - - int NumOCs = 0; - int NumDCs = 0; - int NumMCs = 0; - int NumSCs = 0; - - for (auto it = AllReinforcingStructures.begin(); it != AllReinforcingStructures.end(); it++) + if (NearestTF.IsValid()) { - switch ((*it).StructureType) - { - case STRUCTURE_ALIEN_OFFENCECHAMBER: - NumOCs++; - break; - case STRUCTURE_ALIEN_DEFENCECHAMBER: - NumDCs++; - break; - case STRUCTURE_ALIEN_MOVEMENTCHAMBER: - NumMCs++; - break; - case STRUCTURE_ALIEN_SENSORYCHAMBER: - NumSCs++; - break; - default: - break; - } + AITASK_SetMineStructureTask(pBot, pBot->CurrentTask, NearestTF.edict, true); } - - if (NumOCs < 3 - || (AITAC_TeamHiveWithTechExists(BotTeam, ALIEN_BUILD_DEFENSE_CHAMBER) && NumDCs < 2) - || (AITAC_TeamHiveWithTechExists(BotTeam, ALIEN_BUILD_MOVEMENT_CHAMBER) && NumMCs < 1) - || (AITAC_TeamHiveWithTechExists(BotTeam, ALIEN_BUILD_SENSORY_CHAMBER) && NumSCs < 1)) - { - float ThisDist = vDist2DSq(pBot->Edict->v.origin, ThisHive->FloorLocation); - - if (!HiveToSecure || ThisDist < MinDist) - { - HiveToSecure = ThisHive; - MinDist = ThisDist; - } - } - } } - if (HiveToSecure) - { - AITASK_SetReinforceStructureTask(pBot, &pBot->PrimaryBotTask, HiveToSecure->HiveEdict, false); - return; - } + BotProgressTask(pBot, pBot->CurrentTask); } void DroneThink(AvHAIPlayer* pBot) @@ -3273,8 +3202,8 @@ bool RegularMarineCombatThink(AvHAIPlayer* pBot) edict_t* CurrentEnemy = pBot->TrackedEnemies[pBot->CurrentEnemy].PlayerEdict; enemy_status* TrackedEnemyRef = &pBot->TrackedEnemies[pBot->CurrentEnemy]; - AvHAIDroppedItem* NearestHealthPack = AITAC_FindClosestItemToLocation(pBot->Edict->v.origin, DEPLOYABLE_ITEM_HEALTHPACK, BotTeam, pBot->BotNavInfo.NavProfile.ReachabilityFlag, 0.0f, UTIL_MetresToGoldSrcUnits(10.0f), true); - AvHAIDroppedItem* NearestAmmoPack = AITAC_FindClosestItemToLocation(pBot->Edict->v.origin, DEPLOYABLE_ITEM_AMMO, BotTeam, pBot->BotNavInfo.NavProfile.ReachabilityFlag, 0.0f, UTIL_MetresToGoldSrcUnits(10.0f), true); + AvHAIDroppedItem NearestHealthPack = AITAC_FindClosestItemToLocation(pBot->Edict->v.origin, DEPLOYABLE_ITEM_HEALTHPACK, BotTeam, pBot->BotNavInfo.NavProfile.ReachabilityFlag, 0.0f, UTIL_MetresToGoldSrcUnits(10.0f), true); + AvHAIDroppedItem NearestAmmoPack = AITAC_FindClosestItemToLocation(pBot->Edict->v.origin, DEPLOYABLE_ITEM_AMMO, BotTeam, pBot->BotNavInfo.NavProfile.ReachabilityFlag, 0.0f, UTIL_MetresToGoldSrcUnits(10.0f), true); AvHAIWeapon DesiredCombatWeapon = BotMarineChooseBestWeapon(pBot, CurrentEnemy); @@ -3294,17 +3223,17 @@ bool RegularMarineCombatThink(AvHAIPlayer* pBot) { pBot->DesiredCombatWeapon = DesiredCombatWeapon; - if (NearestHealthPack && (pBot->Edict->v.health < pBot->Edict->v.max_health * 0.7f)) + if (NearestHealthPack.IsValid() && (pBot->Edict->v.health < pBot->Edict->v.max_health * 0.7f)) { - MoveTo(pBot, NearestHealthPack->Location, MOVESTYLE_NORMAL); + MoveTo(pBot, NearestHealthPack.Location, MOVESTYLE_NORMAL); } - else if (NearestAmmoPack && UTIL_GetPlayerPrimaryAmmoReserve(pBot->Player) < UTIL_GetPlayerPrimaryMaxAmmoReserve(pBot->Player)) + else if (NearestAmmoPack.IsValid() && UTIL_GetPlayerPrimaryAmmoReserve(pBot->Player) < UTIL_GetPlayerPrimaryMaxAmmoReserve(pBot->Player)) { - if (vDist2DSq(pBot->Edict->v.origin, NearestAmmoPack->Location) < sqrf(150.0f)) + if (vDist2DSq(pBot->Edict->v.origin, NearestAmmoPack.Location) < sqrf(150.0f)) { pBot->DesiredCombatWeapon = UTIL_GetPlayerPrimaryWeapon(pBot->Player); } - MoveTo(pBot, NearestAmmoPack->Location, MOVESTYLE_NORMAL); + MoveTo(pBot, NearestAmmoPack.Location, MOVESTYLE_NORMAL); } else { @@ -4119,18 +4048,18 @@ void AIPlayerSetWantsAndNeedsMarineTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task float SearchRadius = (bTaskIsUrgent) ? UTIL_MetresToGoldSrcUnits(5.0f) : UTIL_MetresToGoldSrcUnits(10.0f); - AvHAIDroppedItem* NearestHealthPack = AITAC_FindClosestItemToLocation(pBot->Edict->v.origin, DEPLOYABLE_ITEM_HEALTHPACK, BotTeam, pBot->BotNavInfo.NavProfile.ReachabilityFlag, 0.0f, SearchRadius, false); - AvHAIDroppedItem* NearestAmmoPack = AITAC_FindClosestItemToLocation(pBot->Edict->v.origin, DEPLOYABLE_ITEM_AMMO, BotTeam, pBot->BotNavInfo.NavProfile.ReachabilityFlag, 0.0f, SearchRadius, false); + AvHAIDroppedItem NearestHealthPack = AITAC_FindClosestItemToLocation(pBot->Edict->v.origin, DEPLOYABLE_ITEM_HEALTHPACK, BotTeam, pBot->BotNavInfo.NavProfile.ReachabilityFlag, 0.0f, SearchRadius, false); + AvHAIDroppedItem NearestAmmoPack = AITAC_FindClosestItemToLocation(pBot->Edict->v.origin, DEPLOYABLE_ITEM_AMMO, BotTeam, pBot->BotNavInfo.NavProfile.ReachabilityFlag, 0.0f, SearchRadius, false); - if (bNeedsHealth && NearestHealthPack) + if (bNeedsHealth && NearestHealthPack.IsValid()) { - AITASK_SetPickupTask(pBot, Task, NearestHealthPack->edict, bTaskIsUrgent); + AITASK_SetPickupTask(pBot, Task, NearestHealthPack.edict, bTaskIsUrgent); return; } - if (bNeedsAmmo && NearestAmmoPack) + if (bNeedsAmmo && NearestAmmoPack.IsValid()) { - AITASK_SetPickupTask(pBot, Task, NearestAmmoPack->edict, bTaskIsUrgent); + AITASK_SetPickupTask(pBot, Task, NearestAmmoPack.edict, bTaskIsUrgent); return; } @@ -4176,11 +4105,11 @@ void AIPlayerSetWantsAndNeedsMarineTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task if (!PlayerHasEquipment(pBot->Edict)) { - AvHAIDroppedItem* NearbyHA = AITAC_FindClosestItemToLocation(pBot->Edict->v.origin, DEPLOYABLE_ITEM_HEAVYARMOUR, BotTeam, pBot->BotNavInfo.NavProfile.ReachabilityFlag, 0.0f, UTIL_MetresToGoldSrcUnits(10.0f), true); + AvHAIDroppedItem NearbyHA = AITAC_FindClosestItemToLocation(pBot->Edict->v.origin, DEPLOYABLE_ITEM_HEAVYARMOUR, BotTeam, pBot->BotNavInfo.NavProfile.ReachabilityFlag, 0.0f, UTIL_MetresToGoldSrcUnits(10.0f), true); - if (NearbyHA) + if (NearbyHA.IsValid()) { - vector NearbyPlayers = AITAC_GetAllPlayersOfTeamInArea(BotTeam, NearbyHA->Location, UTIL_MetresToGoldSrcUnits(5.0f), false, pBot->Edict, AVH_USER3_COMMANDER_PLAYER); + vector NearbyPlayers = AITAC_GetAllPlayersOfTeamInArea(BotTeam, NearbyHA.Location, UTIL_MetresToGoldSrcUnits(5.0f), false, pBot->Edict, AVH_USER3_COMMANDER_PLAYER); bool bHumanNearby = false; bool bHumanWaitingRespawn = false; @@ -4198,7 +4127,7 @@ void AIPlayerSetWantsAndNeedsMarineTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task if (!bHumanNearby) { - AITASK_SetPickupTask(pBot, Task, NearbyHA->edict, vDist2DSq(pBot->Edict->v.origin, NearbyHA->Location) < sqrf(UTIL_MetresToGoldSrcUnits(5.0f))); + AITASK_SetPickupTask(pBot, Task, NearbyHA.edict, vDist2DSq(pBot->Edict->v.origin, NearbyHA.Location) < sqrf(UTIL_MetresToGoldSrcUnits(5.0f))); return; } } @@ -4208,14 +4137,14 @@ void AIPlayerSetWantsAndNeedsMarineTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task { if (!PlayerHasSpecialWeapon(pBot->Player)) { - AvHAIDroppedItem* NearbyHMG = AITAC_FindClosestItemToLocation(pBot->Edict->v.origin, DEPLOYABLE_ITEM_HMG, BotTeam, pBot->BotNavInfo.NavProfile.ReachabilityFlag, 0.0f, UTIL_MetresToGoldSrcUnits(10.0f), true); - AvHAIDroppedItem* NearbyGL = AITAC_FindClosestItemToLocation(pBot->Edict->v.origin, DEPLOYABLE_ITEM_GRENADELAUNCHER, BotTeam, pBot->BotNavInfo.NavProfile.ReachabilityFlag, 0.0f, UTIL_MetresToGoldSrcUnits(10.0f), true); + AvHAIDroppedItem NearbyHMG = AITAC_FindClosestItemToLocation(pBot->Edict->v.origin, DEPLOYABLE_ITEM_HMG, BotTeam, pBot->BotNavInfo.NavProfile.ReachabilityFlag, 0.0f, UTIL_MetresToGoldSrcUnits(10.0f), true); + AvHAIDroppedItem NearbyGL = AITAC_FindClosestItemToLocation(pBot->Edict->v.origin, DEPLOYABLE_ITEM_GRENADELAUNCHER, BotTeam, pBot->BotNavInfo.NavProfile.ReachabilityFlag, 0.0f, UTIL_MetresToGoldSrcUnits(10.0f), true); - AvHAIDroppedItem* NearbyWeapon = (NearbyHMG != nullptr) ? NearbyHMG : NearbyGL; + AvHAIDroppedItem NearbyWeapon = (NearbyHMG.IsValid()) ? NearbyHMG : NearbyGL; - if (NearbyWeapon) + if (NearbyWeapon.IsValid()) { - vector NearbyPlayers = AITAC_GetAllPlayersOfTeamInArea(BotTeam, NearbyWeapon->Location, UTIL_MetresToGoldSrcUnits(5.0f), false, pBot->Edict, AVH_USER3_COMMANDER_PLAYER); + vector NearbyPlayers = AITAC_GetAllPlayersOfTeamInArea(BotTeam, NearbyWeapon.Location, UTIL_MetresToGoldSrcUnits(5.0f), false, pBot->Edict, AVH_USER3_COMMANDER_PLAYER); bool bHumanNearby = false; for (auto it = NearbyPlayers.begin(); it != NearbyPlayers.end(); it++) @@ -4232,7 +4161,7 @@ void AIPlayerSetWantsAndNeedsMarineTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task if (!bHumanNearby) { - AITASK_SetPickupTask(pBot, Task, NearbyWeapon->edict, vDist2DSq(pBot->Edict->v.origin, NearbyWeapon->Location) < sqrf(UTIL_MetresToGoldSrcUnits(5.0f))); + AITASK_SetPickupTask(pBot, Task, NearbyWeapon.edict, vDist2DSq(pBot->Edict->v.origin, NearbyWeapon.Location) < sqrf(UTIL_MetresToGoldSrcUnits(5.0f))); return; } } @@ -4241,11 +4170,11 @@ void AIPlayerSetWantsAndNeedsMarineTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task if (!PlayerHasWeapon(pBot->Player, WEAPON_MARINE_WELDER)) { - AvHAIDroppedItem* NearbyWeapon = AITAC_FindClosestItemToLocation(pBot->Edict->v.origin, DEPLOYABLE_ITEM_WELDER, BotTeam, pBot->BotNavInfo.NavProfile.ReachabilityFlag, 0.0f, UTIL_MetresToGoldSrcUnits(10.0f), true); + AvHAIDroppedItem NearbyWeapon = AITAC_FindClosestItemToLocation(pBot->Edict->v.origin, DEPLOYABLE_ITEM_WELDER, BotTeam, pBot->BotNavInfo.NavProfile.ReachabilityFlag, 0.0f, UTIL_MetresToGoldSrcUnits(10.0f), true); - if (NearbyWeapon) + if (NearbyWeapon.IsValid()) { - vector NearbyPlayers = AITAC_GetAllPlayersOfTeamInArea(BotTeam, NearbyWeapon->Location, UTIL_MetresToGoldSrcUnits(5.0f), false, pBot->Edict, AVH_USER3_COMMANDER_PLAYER); + vector NearbyPlayers = AITAC_GetAllPlayersOfTeamInArea(BotTeam, NearbyWeapon.Location, UTIL_MetresToGoldSrcUnits(5.0f), false, pBot->Edict, AVH_USER3_COMMANDER_PLAYER); bool bHumanNearby = false; for (auto it = NearbyPlayers.begin(); it != NearbyPlayers.end(); it++) @@ -4262,7 +4191,7 @@ void AIPlayerSetWantsAndNeedsMarineTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task if (!bHumanNearby) { - AITASK_SetPickupTask(pBot, Task, NearbyWeapon->edict, vDist2DSq(pBot->Edict->v.origin, NearbyWeapon->Location) < sqrf(UTIL_MetresToGoldSrcUnits(5.0f))); + AITASK_SetPickupTask(pBot, Task, NearbyWeapon.edict, vDist2DSq(pBot->Edict->v.origin, NearbyWeapon.Location) < sqrf(UTIL_MetresToGoldSrcUnits(5.0f))); return; } } @@ -4270,11 +4199,11 @@ void AIPlayerSetWantsAndNeedsMarineTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task if (!PlayerHasSpecialWeapon(pBot->Player)) { - AvHAIDroppedItem* NearbyWeapon = AITAC_FindClosestItemToLocation(pBot->Edict->v.origin, DEPLOYABLE_ITEM_SHOTGUN, BotTeam, pBot->BotNavInfo.NavProfile.ReachabilityFlag, 0.0f, UTIL_MetresToGoldSrcUnits(10.0f), true); + AvHAIDroppedItem NearbyWeapon = AITAC_FindClosestItemToLocation(pBot->Edict->v.origin, DEPLOYABLE_ITEM_SHOTGUN, BotTeam, pBot->BotNavInfo.NavProfile.ReachabilityFlag, 0.0f, UTIL_MetresToGoldSrcUnits(10.0f), true); - if (NearbyWeapon) + if (NearbyWeapon.IsValid()) { - vector NearbyPlayers = AITAC_GetAllPlayersOfTeamInArea(BotTeam, NearbyWeapon->Location, UTIL_MetresToGoldSrcUnits(5.0f), false, pBot->Edict, AVH_USER3_COMMANDER_PLAYER); + vector NearbyPlayers = AITAC_GetAllPlayersOfTeamInArea(BotTeam, NearbyWeapon.Location, UTIL_MetresToGoldSrcUnits(5.0f), false, pBot->Edict, AVH_USER3_COMMANDER_PLAYER); bool bHumanNearby = false; for (auto it = NearbyPlayers.begin(); it != NearbyPlayers.end(); it++) @@ -4291,7 +4220,7 @@ void AIPlayerSetWantsAndNeedsMarineTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task if (!bHumanNearby) { - AITASK_SetPickupTask(pBot, Task, NearbyWeapon->edict, vDist2DSq(pBot->Edict->v.origin, NearbyWeapon->Location) < sqrf(UTIL_MetresToGoldSrcUnits(5.0f))); + AITASK_SetPickupTask(pBot, Task, NearbyWeapon.edict, vDist2DSq(pBot->Edict->v.origin, NearbyWeapon.Location) < sqrf(UTIL_MetresToGoldSrcUnits(5.0f))); return; } } @@ -4299,11 +4228,11 @@ void AIPlayerSetWantsAndNeedsMarineTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task if (!PlayerHasWeapon(pBot->Player, WEAPON_MARINE_MINES)) { - AvHAIDroppedItem* NearbyWeapon = AITAC_FindClosestItemToLocation(pBot->Edict->v.origin, DEPLOYABLE_ITEM_MINES, BotTeam, pBot->BotNavInfo.NavProfile.ReachabilityFlag, 0.0f, UTIL_MetresToGoldSrcUnits(10.0f), true); + AvHAIDroppedItem NearbyWeapon = AITAC_FindClosestItemToLocation(pBot->Edict->v.origin, DEPLOYABLE_ITEM_MINES, BotTeam, pBot->BotNavInfo.NavProfile.ReachabilityFlag, 0.0f, UTIL_MetresToGoldSrcUnits(10.0f), true); - if (NearbyWeapon) + if (NearbyWeapon.IsValid()) { - vector NearbyPlayers = AITAC_GetAllPlayersOfTeamInArea(BotTeam, NearbyWeapon->Location, UTIL_MetresToGoldSrcUnits(5.0f), false, pBot->Edict, AVH_USER3_COMMANDER_PLAYER); + vector NearbyPlayers = AITAC_GetAllPlayersOfTeamInArea(BotTeam, NearbyWeapon.Location, UTIL_MetresToGoldSrcUnits(5.0f), false, pBot->Edict, AVH_USER3_COMMANDER_PLAYER); bool bHumanNearby = false; for (auto it = NearbyPlayers.begin(); it != NearbyPlayers.end(); it++) @@ -4320,7 +4249,7 @@ void AIPlayerSetWantsAndNeedsMarineTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task if (!bHumanNearby) { - AITASK_SetPickupTask(pBot, Task, NearbyWeapon->edict, vDist2DSq(pBot->Edict->v.origin, NearbyWeapon->Location) < sqrf(UTIL_MetresToGoldSrcUnits(5.0f))); + AITASK_SetPickupTask(pBot, Task, NearbyWeapon.edict, vDist2DSq(pBot->Edict->v.origin, NearbyWeapon.Location) < sqrf(UTIL_MetresToGoldSrcUnits(5.0f))); return; } } diff --git a/main/source/mod/AvHAITactical.cpp b/main/source/mod/AvHAITactical.cpp index a79e4bf9..dca20b32 100644 --- a/main/source/mod/AvHAITactical.cpp +++ b/main/source/mod/AvHAITactical.cpp @@ -630,20 +630,24 @@ AvHAIBuildableStructure* AITAC_FindFurthestDeployableFromLocationByRef(const Vec return Result; } -AvHAIDroppedItem* AITAC_GetDroppedItemRefFromEdict(edict_t* ItemEdict) +AvHAIDroppedItem AITAC_GetDroppedItemRefFromEdict(edict_t* ItemEdict) { - if (FNullEnt(ItemEdict)) { return nullptr; } + AvHAIDroppedItem Result; + + if (FNullEnt(ItemEdict)) { return Result; } int EntIndex = ENTINDEX(ItemEdict); - if (EntIndex < 0) { return nullptr; } + if (EntIndex < 0) { return Result; } - return &MarineDroppedItemMap[EntIndex]; + Result = MarineDroppedItemMap[EntIndex]; + + return Result; } -AvHAIDroppedItem* AITAC_FindClosestItemToLocation(const Vector& Location, const AvHAIDeployableItemType ItemType, AvHTeamNumber SearchingTeam, const unsigned int ReachabilityFlags, float MinRadius, float MaxRadius, bool bConsiderPhaseDistance) +AvHAIDroppedItem AITAC_FindClosestItemToLocation(const Vector& Location, const AvHAIDeployableItemType ItemType, AvHTeamNumber SearchingTeam, const unsigned int ReachabilityFlags, float MinRadius, float MaxRadius, bool bConsiderPhaseDistance) { - AvHAIDroppedItem* Result = NULL; + AvHAIDroppedItem Result; float CurrMinDist = 0.0f; float MinDistSq = sqrf(MinRadius); @@ -669,9 +673,9 @@ AvHAIDroppedItem* AITAC_FindClosestItemToLocation(const Vector& Location, const float DistSq = (bConsiderPhaseDistance) ? sqrf(AITAC_GetPhaseDistanceBetweenPoints(it.second.Location, Location)) : vDist2DSq(it.second.Location, Location); - if ((!bUseMinDist || DistSq >= MinDistSq) && (!bUseMaxDist || DistSq <= MaxDistSq) && (!Result || DistSq < CurrMinDist)) + if ((!bUseMinDist || DistSq >= MinDistSq) && (!bUseMaxDist || DistSq <= MaxDistSq) && (!Result.IsValid() || DistSq < CurrMinDist)) { - Result = &it.second; + Result = it.second; CurrMinDist = DistSq; } diff --git a/main/source/mod/AvHAITactical.h b/main/source/mod/AvHAITactical.h index d6b25ca6..6667b568 100644 --- a/main/source/mod/AvHAITactical.h +++ b/main/source/mod/AvHAITactical.h @@ -67,11 +67,11 @@ Vector AITAC_GetTeamRelocationPoint(AvHTeamNumber Team); AvHAIResourceNode* AITAC_GetRandomResourceNode(AvHTeamNumber SearchingTeam, const unsigned int ReachabilityFlags); -AvHAIDroppedItem* AITAC_FindClosestItemToLocation(const Vector& Location, const AvHAIDeployableItemType ItemType, AvHTeamNumber SearchingTeam, const unsigned int ReachabilityFlags, float MinRadius, float MaxRadius, bool bConsiderPhaseDistance); +AvHAIDroppedItem AITAC_FindClosestItemToLocation(const Vector& Location, const AvHAIDeployableItemType ItemType, AvHTeamNumber SearchingTeam, const unsigned int ReachabilityFlags, float MinRadius, float MaxRadius, bool bConsiderPhaseDistance); bool AITAC_ItemExistsInLocation(const Vector& Location, const AvHAIDeployableItemType ItemType, AvHTeamNumber SearchingTeam, const unsigned int ReachabilityFlags, float MinRadius, float MaxRadius, bool bConsiderPhaseDistance); int AITAC_GetNumItemsInLocation(const Vector& Location, const AvHAIDeployableItemType ItemType, AvHTeamNumber SearchingTeam, const unsigned int ReachabilityFlags, float MinRadius, float MaxRadius, bool bConsiderPhaseDistance); -AvHAIDroppedItem* AITAC_GetDroppedItemRefFromEdict(edict_t* ItemEdict); +AvHAIDroppedItem AITAC_GetDroppedItemRefFromEdict(edict_t* ItemEdict); Vector AITAC_GetRandomBuildHintInLocation(const unsigned int StructureType, const Vector SearchLocation, const float SearchRadius); diff --git a/main/source/mod/AvHAITask.cpp b/main/source/mod/AvHAITask.cpp index e5167fbd..15666396 100644 --- a/main/source/mod/AvHAITask.cpp +++ b/main/source/mod/AvHAITask.cpp @@ -441,11 +441,11 @@ bool AITASK_IsWeldTaskStillValid(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) { if (FNullEnt(Task->TaskSecondaryTarget)) { - AvHAIDroppedItem* NearestWelder = AITAC_FindClosestItemToLocation(pBot->Edict->v.origin, DEPLOYABLE_ITEM_WELDER, pBot->Player->GetTeam(), pBot->BotNavInfo.NavProfile.ReachabilityFlag, 0.0f, 0.0f, true); + AvHAIDroppedItem NearestWelder = AITAC_FindClosestItemToLocation(pBot->Edict->v.origin, DEPLOYABLE_ITEM_WELDER, pBot->Player->GetTeam(), pBot->BotNavInfo.NavProfile.ReachabilityFlag, 0.0f, 0.0f, true); - if (NearestWelder) + if (NearestWelder.IsValid()) { - Task->TaskSecondaryTarget = NearestWelder->edict; + Task->TaskSecondaryTarget = NearestWelder.edict; } else { @@ -2651,11 +2651,11 @@ void BotProgressWeldTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task) } else { - AvHAIDroppedItem* Welder = AITAC_FindClosestItemToLocation(pBot->Edict->v.origin, DEPLOYABLE_ITEM_WELDER, pBot->Player->GetTeam(), pBot->BotNavInfo.NavProfile.ReachabilityFlag, 0.0f, 0.0f, true); + AvHAIDroppedItem Welder = AITAC_FindClosestItemToLocation(pBot->Edict->v.origin, DEPLOYABLE_ITEM_WELDER, pBot->Player->GetTeam(), pBot->BotNavInfo.NavProfile.ReachabilityFlag, 0.0f, 0.0f, true); - if (Welder) + if (Welder.IsValid()) { - Task->TaskSecondaryTarget = Welder->edict; + Task->TaskSecondaryTarget = Welder.edict; } } @@ -3537,9 +3537,9 @@ void AITASK_SetPickupTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task, edict_t* Tar return; } - AvHAIDroppedItem* ItemToPickup = AITAC_GetDroppedItemRefFromEdict(Target); + AvHAIDroppedItem ItemToPickup = AITAC_GetDroppedItemRefFromEdict(Target); - if (!ItemToPickup) + if (!ItemToPickup.IsValid()) { AITASK_ClearBotTask(pBot, Task); return; @@ -3553,7 +3553,7 @@ void AITASK_SetPickupTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task, edict_t* Tar return; } - switch (ItemToPickup->ItemType) + switch (ItemToPickup.ItemType) { case DEPLOYABLE_ITEM_AMMO: Task->TaskType = TASK_GET_AMMO; @@ -3633,16 +3633,16 @@ void AITASK_SetWeldTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task, edict_t* Targe if (!PlayerHasWeapon(pBot->Player, WEAPON_MARINE_WELDER)) { - AvHAIDroppedItem* NearestWelder = AITAC_FindClosestItemToLocation(pBot->Edict->v.origin, DEPLOYABLE_ITEM_WELDER, pBot->Player->GetTeam(), pBot->BotNavInfo.NavProfile.ReachabilityFlag, 0.0f, 0.0f, true); + AvHAIDroppedItem NearestWelder = AITAC_FindClosestItemToLocation(pBot->Edict->v.origin, DEPLOYABLE_ITEM_WELDER, pBot->Player->GetTeam(), pBot->BotNavInfo.NavProfile.ReachabilityFlag, 0.0f, 0.0f, true); - if (!NearestWelder) + if (!NearestWelder.IsValid()) { AITASK_ClearBotTask(pBot, Task); return; } else { - Task->TaskSecondaryTarget = NearestWelder->edict; + Task->TaskSecondaryTarget = NearestWelder.edict; } }