Stability and randomness improvements

* Fixed potential crashing when obtaining references to dropped items
* Fixed issues with random number generation
This commit is contained in:
RGreenlees 2024-05-30 13:44:46 +01:00 committed by pierow
parent ef7e7a9178
commit f427a9c052
9 changed files with 107 additions and 171 deletions

View file

@ -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<AvHPlayer*> 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<edict_t*> 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);
}

View file

@ -20,6 +20,8 @@ bot_skill BotSkillLevels[4];
std::vector<AvHMessageID> 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";

View file

@ -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

View file

@ -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);

View file

@ -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;
}
}

View file

@ -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<AvHAIHiveDefinition*> 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<AvHAIBuildableStructure> 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<AvHPlayer*> NearbyPlayers = AITAC_GetAllPlayersOfTeamInArea(BotTeam, NearbyHA->Location, UTIL_MetresToGoldSrcUnits(5.0f), false, pBot->Edict, AVH_USER3_COMMANDER_PLAYER);
vector<AvHPlayer*> 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<AvHPlayer*> NearbyPlayers = AITAC_GetAllPlayersOfTeamInArea(BotTeam, NearbyWeapon->Location, UTIL_MetresToGoldSrcUnits(5.0f), false, pBot->Edict, AVH_USER3_COMMANDER_PLAYER);
vector<AvHPlayer*> 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<AvHPlayer*> NearbyPlayers = AITAC_GetAllPlayersOfTeamInArea(BotTeam, NearbyWeapon->Location, UTIL_MetresToGoldSrcUnits(5.0f), false, pBot->Edict, AVH_USER3_COMMANDER_PLAYER);
vector<AvHPlayer*> 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<AvHPlayer*> NearbyPlayers = AITAC_GetAllPlayersOfTeamInArea(BotTeam, NearbyWeapon->Location, UTIL_MetresToGoldSrcUnits(5.0f), false, pBot->Edict, AVH_USER3_COMMANDER_PLAYER);
vector<AvHPlayer*> 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<AvHPlayer*> NearbyPlayers = AITAC_GetAllPlayersOfTeamInArea(BotTeam, NearbyWeapon->Location, UTIL_MetresToGoldSrcUnits(5.0f), false, pBot->Edict, AVH_USER3_COMMANDER_PLAYER);
vector<AvHPlayer*> 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;
}
}

View file

@ -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;
}

View file

@ -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);

View file

@ -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;
}
}