mirror of
https://github.com/ENSL/NS.git
synced 2024-11-10 07:11:38 +00:00
Crash fixes
This commit is contained in:
parent
d1d1e1f746
commit
0df89d9abe
7 changed files with 133 additions and 26 deletions
|
@ -936,9 +936,11 @@ bool AICOMM_CheckForNextBuildAction(AvHAIPlayer* pBot)
|
|||
StructureFilter.ReachabilityTeam = TeamNumber;
|
||||
StructureFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(15.0f);
|
||||
|
||||
edict_t* BaseBuilder = AITAC_GetNearestHiddenPlayerInLocation(TeamNumber, CommChair->v.origin, UTIL_MetresToGoldSrcUnits(10.0f));
|
||||
|
||||
int NumInfantryPortals = AITAC_GetNumDeployablesNearLocation(CommChair->v.origin, &StructureFilter);
|
||||
|
||||
if (NumInfantryPortals < 2)
|
||||
if (NumInfantryPortals < 2 && !FNullEnt(BaseBuilder))
|
||||
{
|
||||
bool bEnemyInBase = NumInfantryPortals > 1 && AITAC_AnyPlayerOnTeamWithLOS(AIMGR_GetEnemyTeam(TeamNumber), CommChair->v.origin, UTIL_MetresToGoldSrcUnits(10.0f));
|
||||
|
||||
|
@ -950,9 +952,11 @@ bool AICOMM_CheckForNextBuildAction(AvHAIPlayer* pBot)
|
|||
|
||||
AvHAIBuildableStructure* BaseArmoury = AITAC_FindClosestDeployableToLocation(CommChair->v.origin, &StructureFilter);
|
||||
|
||||
if (!BaseArmoury)
|
||||
{
|
||||
|
||||
|
||||
if (!BaseArmoury && !FNullEnt(BaseBuilder))
|
||||
{
|
||||
|
||||
StructureFilter.DeployableTypes = STRUCTURE_MARINE_INFANTRYPORTAL;
|
||||
|
||||
AvHAIBuildableStructure* NearestInfantryPortal = AITAC_FindClosestDeployableToLocation(CommChair->v.origin, &StructureFilter);
|
||||
|
@ -1014,7 +1018,7 @@ bool AICOMM_CheckForNextBuildAction(AvHAIPlayer* pBot)
|
|||
|
||||
bool bPhaseNearBase = AITAC_DeployableExistsAtLocation(CommChair->v.origin, &StructureFilter);
|
||||
|
||||
if (!bPhaseNearBase)
|
||||
if (!bPhaseNearBase && !FNullEnt(BaseBuilder))
|
||||
{
|
||||
Vector BuildLocation = UTIL_GetRandomPointOnNavmeshInRadiusIgnoreReachability(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), CommChair->v.origin, UTIL_MetresToGoldSrcUnits(10.0f));
|
||||
|
||||
|
@ -1051,7 +1055,7 @@ bool AICOMM_CheckForNextBuildAction(AvHAIPlayer* pBot)
|
|||
|
||||
bool bHasArmsLab = AITAC_DeployableExistsAtLocation(CommChair->v.origin, &StructureFilter);
|
||||
|
||||
if (!bHasArmsLab)
|
||||
if (!bHasArmsLab && !FNullEnt(BaseBuilder))
|
||||
{
|
||||
Vector BuildLocation = UTIL_GetRandomPointOnNavmeshInRadiusIgnoreReachability(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), CommChair->v.origin, UTIL_MetresToGoldSrcUnits(10.0f));
|
||||
|
||||
|
@ -1068,7 +1072,7 @@ bool AICOMM_CheckForNextBuildAction(AvHAIPlayer* pBot)
|
|||
|
||||
bool bHasObservatory = AITAC_DeployableExistsAtLocation(CommChair->v.origin, &StructureFilter);
|
||||
|
||||
if (!bHasObservatory)
|
||||
if (!bHasObservatory && !FNullEnt(BaseBuilder))
|
||||
{
|
||||
Vector BuildLocation = UTIL_GetRandomPointOnNavmeshInRadiusIgnoreReachability(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), CommChair->v.origin, UTIL_MetresToGoldSrcUnits(10.0f));
|
||||
|
||||
|
@ -1129,7 +1133,7 @@ bool AICOMM_CheckForNextBuildAction(AvHAIPlayer* pBot)
|
|||
|
||||
bool bHasPrototypeLab = AITAC_DeployableExistsAtLocation(CommChair->v.origin, &StructureFilter);
|
||||
|
||||
if (!bHasPrototypeLab && bHasAdvArmoury)
|
||||
if (!bHasPrototypeLab && bHasAdvArmoury && !FNullEnt(BaseBuilder))
|
||||
{
|
||||
Vector BuildLocation = UTIL_GetRandomPointOnNavmeshInDonutIgnoreReachability(GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE), BaseArmoury->Location, UTIL_MetresToGoldSrcUnits(3.0f), UTIL_MetresToGoldSrcUnits(5.0f));
|
||||
|
||||
|
@ -1325,7 +1329,12 @@ bool AICOMM_CheckForNextSupplyAction(AvHAIPlayer* pBot)
|
|||
bool bNeedsMines = false;
|
||||
int DesiredMines = 0;
|
||||
|
||||
if (NumMinesInPlay < 2)
|
||||
DeployableSearchFilter MineFilter;
|
||||
MineFilter.DeployableTypes = STRUCTURE_MARINE_DEPLOYEDMINE;
|
||||
|
||||
int NumDeployedMines = AITAC_GetNumDeployablesNearLocation(ZERO_VECTOR, &MineFilter);
|
||||
|
||||
if (NumMinesInPlay < 2 && NumDeployedMines < 32)
|
||||
{
|
||||
int UnminedStructures = 0;
|
||||
|
||||
|
|
|
@ -2138,6 +2138,13 @@ bool HasBotReachedPathPoint(const AvHAIPlayer* pBot)
|
|||
return false;
|
||||
}
|
||||
|
||||
bool HasBotCompletedLadderMove(AvHAIPlayer* pBot, Vector MoveStart, Vector MoveEnd)
|
||||
{
|
||||
if (IsPlayerOnLadder(pBot->Edict)) { return false; }
|
||||
|
||||
return UTIL_PointIsDirectlyReachable(pBot->CollisionHullBottomLocation, MoveEnd);
|
||||
}
|
||||
|
||||
void CheckAndHandleDoorObstruction(AvHAIPlayer* pBot)
|
||||
{
|
||||
edict_t* BlockingDoorEdict = UTIL_GetDoorBlockingPathPoint(pBot->Edict->v.origin, pBot->BotNavInfo.CurrentPathPoint->Location, pBot->BotNavInfo.CurrentPathPoint->flag, nullptr);
|
||||
|
@ -3258,7 +3265,7 @@ void LadderMove(AvHAIPlayer* pBot, const Vector StartPoint, const Vector EndPoin
|
|||
CurrentLadderNormal = UTIL_GetNearestLadderNormal(pBot->CollisionHullBottomLocation + Vector(0.0f, 0.0f, 5.0f));
|
||||
}
|
||||
|
||||
//CurrentLadderNormal = UTIL_GetVectorNormal2D(CurrentLadderNormal);
|
||||
CurrentLadderNormal = UTIL_GetVectorNormal2D(CurrentLadderNormal);
|
||||
|
||||
if (vIsZero(CurrentLadderNormal))
|
||||
{
|
||||
|
@ -5541,6 +5548,8 @@ bool MoveTo(AvHAIPlayer* pBot, const Vector Destination, const BotMoveStyle Move
|
|||
}
|
||||
else
|
||||
{
|
||||
BotNavInfo->CurrentPathPoint = BotNavInfo->CurrentPath.end();
|
||||
|
||||
pBot->BotNavInfo.StuckInfo.bPathFollowFailed = true;
|
||||
|
||||
if (!UTIL_PointIsOnNavmesh(pBot->CollisionHullBottomLocation, pBot->BotNavInfo.NavProfile) && !vIsZero(BotNavInfo->LastNavMeshPosition))
|
||||
|
@ -6385,7 +6394,8 @@ void HandlePlayerAvoidance(AvHAIPlayer* pBot, const Vector MoveDestination)
|
|||
// Don't handle player avoidance if climbing a wall, ladder or in the air, as it will mess up the move and cause them to get stuck most likely
|
||||
if (pBot->Player->IsOnLadder() || IsPlayerClimbingWall(pBot->Edict) || !pBot->BotNavInfo.IsOnGround) { return; }
|
||||
|
||||
float avoidDistSq = sqrf(50.0f);
|
||||
float MyRadius = GetPlayerRadius(pBot->Edict);
|
||||
|
||||
const Vector BotLocation = pBot->Edict->v.origin;
|
||||
const Vector MoveDir = UTIL_GetVectorNormal2D((MoveDestination - pBot->Edict->v.origin));
|
||||
|
||||
|
@ -6395,6 +6405,10 @@ void HandlePlayerAvoidance(AvHAIPlayer* pBot, const Vector MoveDestination)
|
|||
|
||||
if (!FNullEnt(OtherPlayer) && OtherPlayer != pBot->Edict && IsPlayerActiveInGame(OtherPlayer))
|
||||
{
|
||||
float OtherPlayerRadius = GetPlayerRadius(OtherPlayer);
|
||||
|
||||
float avoidDistSq = sqrf(MyRadius + OtherPlayerRadius + 16.0f);
|
||||
|
||||
// Don't do avoidance for a player if they're moving in broadly the same direction as us
|
||||
Vector OtherMoveDir = GetPlayerAttemptedMoveDirection(OtherPlayer);
|
||||
|
||||
|
@ -6418,26 +6432,41 @@ void HandlePlayerAvoidance(AvHAIPlayer* pBot, const Vector MoveDestination)
|
|||
|
||||
int modifier = vPointOnLine(pBot->Edict->v.origin, MoveDestination, OtherPlayer->v.origin);
|
||||
|
||||
float OtherPersonDistFromLine = vDistanceFromLine2D(pBot->Edict->v.origin, MoveDestination, OtherPlayer->v.origin);
|
||||
|
||||
if (modifier == 0) { modifier = 1; }
|
||||
|
||||
Vector PreferredMoveDir = (MoveRightVector * modifier);
|
||||
|
||||
float TraceLength = OtherPersonDistFromLine + (fmaxf(MyRadius, OtherPlayerRadius) * 2.0f);
|
||||
|
||||
UTIL_DrawLine(INDEXENT(1), pBot->Edict->v.origin, pBot->Edict->v.origin + (PreferredMoveDir * TraceLength), 0, 128, 0);
|
||||
UTIL_DrawLine(INDEXENT(1), pBot->Edict->v.origin, pBot->Edict->v.origin - (PreferredMoveDir * TraceLength), 255, 0, 0);
|
||||
|
||||
|
||||
// First see if we have enough room to move in our preferred avoidance direction
|
||||
if (UTIL_TraceNav(pBot->BotNavInfo.NavProfile, BotLocation, BotLocation + (PreferredMoveDir * 32.0f), 2.0f))
|
||||
if (UTIL_TraceNav(pBot->BotNavInfo.NavProfile, BotLocation, BotLocation + (PreferredMoveDir * TraceLength), 0.0f))
|
||||
{
|
||||
pBot->desiredMovementDir = PreferredMoveDir;
|
||||
return;
|
||||
}
|
||||
|
||||
// Then try the opposite direction
|
||||
if (UTIL_TraceNav(pBot->BotNavInfo.NavProfile, BotLocation, BotLocation - (PreferredMoveDir * 32.0f), 2.0f))
|
||||
if (UTIL_TraceNav(pBot->BotNavInfo.NavProfile, BotLocation, BotLocation - (PreferredMoveDir * TraceLength), 0.0f))
|
||||
{
|
||||
pBot->desiredMovementDir = -PreferredMoveDir;
|
||||
return;
|
||||
}
|
||||
|
||||
// Back up since we can't go either side
|
||||
if (UTIL_GetDotProduct2D(MoveDir, OtherMoveDir) < 0.0f)
|
||||
bool bCanBackUp = UTIL_TraceNav(pBot->BotNavInfo.NavProfile, BotLocation, BotLocation - (MoveDir * (MyRadius * 2.0f)), 0.0f);
|
||||
|
||||
if (!bCanBackUp)
|
||||
{
|
||||
bCanBackUp = UTIL_QuickHullTrace(pBot->Edict, pBot->Edict->v.origin, pBot->Edict->v.origin - (MoveDir * (MyRadius * 2.0f)), head_hull);
|
||||
}
|
||||
|
||||
// Back up since we can't go either side, but only if we can back up. Otherwise, we push forward and demand the OTHER guy back up
|
||||
if (UTIL_GetDotProduct2D(MoveDir, OtherMoveDir) < 0.0f && bCanBackUp)
|
||||
{
|
||||
pBot->desiredMovementDir = MoveDir * -1.0f;
|
||||
}
|
||||
|
|
|
@ -227,6 +227,28 @@ float GetPlayerRadius(const AvHPlayer* Player)
|
|||
}
|
||||
}
|
||||
|
||||
float GetPlayerRadius(const edict_t* Player)
|
||||
{
|
||||
if (!Player) { return 0.0f; }
|
||||
|
||||
int hullnum = GetPlayerHullIndex(Player);
|
||||
|
||||
switch (hullnum)
|
||||
{
|
||||
case human_hull:
|
||||
case head_hull:
|
||||
return 16.0f;
|
||||
break;
|
||||
case large_hull:
|
||||
return 32.0f;
|
||||
break;
|
||||
default:
|
||||
return 16.0f;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
bool CanPlayerCrouch(const edict_t* Player)
|
||||
{
|
||||
if (FNullEnt(Player) || Player->free || !IsEdictPlayer(Player)) { return false; }
|
||||
|
|
|
@ -91,6 +91,7 @@ int GetPlayerCombatLevel(const AvHPlayer* Player);
|
|||
|
||||
// Returns the player radius based on their current state
|
||||
float GetPlayerRadius(const AvHPlayer* Player);
|
||||
float GetPlayerRadius(const edict_t* Player);
|
||||
|
||||
// Returns the hull index that should be used for this player when performing hull traces. Depends on if player is crouching right now or not
|
||||
int GetPlayerHullIndex(const edict_t* Player);
|
||||
|
|
|
@ -85,6 +85,8 @@ std::vector<AvHAIBuildableStructure*> AITAC_FindAllDeployables(const Vector& Loc
|
|||
{
|
||||
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; }
|
||||
|
||||
|
@ -116,6 +118,8 @@ std::vector<AvHAIBuildableStructure*> AITAC_FindAllDeployables(const Vector& Loc
|
|||
{
|
||||
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; }
|
||||
|
||||
|
@ -161,6 +165,8 @@ bool AITAC_DeployableExistsAtLocation(const Vector& Location, const DeployableSe
|
|||
{
|
||||
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; }
|
||||
|
||||
|
@ -189,6 +195,8 @@ bool AITAC_DeployableExistsAtLocation(const Vector& Location, const DeployableSe
|
|||
{
|
||||
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; }
|
||||
|
||||
|
@ -234,6 +242,8 @@ AvHAIBuildableStructure* AITAC_FindClosestDeployableToLocation(const Vector& Loc
|
|||
{
|
||||
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; }
|
||||
|
@ -261,6 +271,8 @@ AvHAIBuildableStructure* AITAC_FindClosestDeployableToLocation(const Vector& Loc
|
|||
{
|
||||
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; }
|
||||
|
@ -305,6 +317,8 @@ AvHAIBuildableStructure* AITAC_FindFurthestDeployableFromLocation(const Vector&
|
|||
{
|
||||
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; }
|
||||
|
@ -332,6 +346,8 @@ AvHAIBuildableStructure* AITAC_FindFurthestDeployableFromLocation(const Vector&
|
|||
{
|
||||
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; }
|
||||
|
@ -382,6 +398,8 @@ AvHAIDroppedItem* AITAC_FindClosestItemToLocation(const Vector& Location, const
|
|||
|
||||
for (auto& it : MarineDroppedItemMap)
|
||||
{
|
||||
if (FNullEnt(it.second.edict) || it.second.edict->v.deadflag != DEAD_NO || (it.second.edict->v.effects & EF_NODRAW)) { continue; }
|
||||
|
||||
unsigned int StructureReachabilityFlags = (it.second.TeamAReachabilityFlags | it.second.TeamBReachabilityFlags);
|
||||
|
||||
if (SearchingTeam != TEAM_IND)
|
||||
|
@ -418,6 +436,8 @@ int AITAC_GetNumItemsInLocation(const Vector& Location, const AvHAIDeployableIte
|
|||
|
||||
for (auto& it : MarineDroppedItemMap)
|
||||
{
|
||||
if (FNullEnt(it.second.edict) || it.second.edict->v.deadflag != DEAD_NO || (it.second.edict->v.effects & EF_NODRAW)) { continue; }
|
||||
|
||||
if (it.second.ItemType != ItemType) { continue; }
|
||||
|
||||
unsigned int StructureReachabilityFlags = (it.second.TeamAReachabilityFlags | it.second.TeamBReachabilityFlags);
|
||||
|
@ -452,6 +472,8 @@ bool AITAC_ItemExistsInLocation(const Vector& Location, const AvHAIDeployableIte
|
|||
|
||||
for (auto& it : MarineDroppedItemMap)
|
||||
{
|
||||
if (FNullEnt(it.second.edict) || it.second.edict->v.deadflag != DEAD_NO || (it.second.edict->v.effects & EF_NODRAW)) { continue; }
|
||||
|
||||
unsigned int StructureReachabilityFlags = (it.second.TeamAReachabilityFlags | it.second.TeamBReachabilityFlags);
|
||||
|
||||
if (SearchingTeam != TEAM_IND)
|
||||
|
@ -508,6 +530,8 @@ AvHAIBuildableStructure* AITAC_GetNearestDeployableDirectlyReachable(AvHAIPlayer
|
|||
{
|
||||
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; }
|
||||
|
||||
|
@ -539,6 +563,8 @@ AvHAIBuildableStructure* AITAC_GetNearestDeployableDirectlyReachable(AvHAIPlayer
|
|||
{
|
||||
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; }
|
||||
|
||||
|
@ -586,6 +612,8 @@ int AITAC_GetNumDeployablesNearLocation(const Vector& Location, const Deployable
|
|||
{
|
||||
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; }
|
||||
|
||||
|
@ -614,6 +642,8 @@ int AITAC_GetNumDeployablesNearLocation(const Vector& Location, const Deployable
|
|||
{
|
||||
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; }
|
||||
|
||||
|
@ -948,6 +978,8 @@ Vector AITAC_GetCommChairLocation(AvHTeamNumber Team)
|
|||
|
||||
void AITAC_RefreshReachabilityForItem(AvHAIDroppedItem* Item)
|
||||
{
|
||||
if (FNullEnt(Item->edict) || Item->edict->v.deadflag != DEAD_NO || (Item->edict->v.effects & EF_NODRAW)) { return; }
|
||||
|
||||
if (Item->ItemType == DEPLOYABLE_ITEM_SCAN)
|
||||
{
|
||||
Item->TeamAReachabilityFlags = AI_REACHABILITY_ALL;
|
||||
|
@ -1634,7 +1666,7 @@ void AITAC_RefreshBuildableStructures()
|
|||
|
||||
for (auto it = TeamAStructureMap.begin(); it != TeamAStructureMap.end();)
|
||||
{
|
||||
if (it->second.LastSeen < StructureRefreshFrame)
|
||||
if (it->second.LastSeen < StructureRefreshFrame || FNullEnt(it->second.edict) || it->second.edict->v.deadflag != DEAD_NO || (it->second.edict->v.effects & EF_NODRAW))
|
||||
{
|
||||
AITAC_OnStructureDestroyed(&it->second);
|
||||
it = TeamAStructureMap.erase(it);
|
||||
|
@ -1652,7 +1684,7 @@ void AITAC_RefreshBuildableStructures()
|
|||
|
||||
for (auto it = TeamBStructureMap.begin(); it != TeamBStructureMap.end();)
|
||||
{
|
||||
if (it->second.LastSeen < StructureRefreshFrame)
|
||||
if (it->second.LastSeen < StructureRefreshFrame || FNullEnt(it->second.edict) || it->second.edict->v.deadflag != DEAD_NO || (it->second.edict->v.effects & EF_NODRAW))
|
||||
{
|
||||
AITAC_OnStructureDestroyed(&it->second);
|
||||
it = TeamBStructureMap.erase(it);
|
||||
|
@ -1777,7 +1809,7 @@ void AITAC_UpdateMarineItem(CBaseEntity* Item, AvHAIDeployableItemType ItemType)
|
|||
|
||||
edict_t* ItemEdict = Item->edict();
|
||||
|
||||
if (FNullEnt(ItemEdict)) { return; }
|
||||
if (FNullEnt(ItemEdict) || ItemEdict->v.deadflag != DEAD_NO || (ItemEdict->v.effects & EF_NODRAW)) { return; }
|
||||
|
||||
// All items except scans are of interest only if they're collectable. Without this check, marines will attempt to grab weapons from other players.
|
||||
if (ItemType != DEPLOYABLE_ITEM_SCAN)
|
||||
|
@ -1835,6 +1867,8 @@ void AITAC_RefreshReachabilityForStructure(AvHAIBuildableStructure* Structure)
|
|||
AITAC_RefreshHiveData();
|
||||
}
|
||||
|
||||
if (!Structure || FNullEnt(Structure->edict) || Structure->edict->v.deadflag != DEAD_NO || (Structure->edict->v.effects & EF_NODRAW)) { return; }
|
||||
|
||||
if (Structure->StructureType == STRUCTURE_MARINE_DEPLOYEDMINE)
|
||||
{
|
||||
Structure->TeamAReachabilityFlags = AI_REACHABILITY_ALL;
|
||||
|
@ -2125,6 +2159,8 @@ AvHAIBuildableStructure* AITAC_UpdateBuildableStructure(CBaseEntity* Structure)
|
|||
|
||||
void AITAC_OnStructureCreated(AvHAIBuildableStructure* NewStructure)
|
||||
{
|
||||
if (!NewStructure || FNullEnt(NewStructure->edict) || NewStructure->edict->v.deadflag != DEAD_NO || (NewStructure->edict->v.effects & EF_NODRAW)) { return; }
|
||||
|
||||
UTIL_AddStructureTemporaryObstacles(NewStructure);
|
||||
|
||||
AvHTeamNumber StructureTeam = (AvHTeamNumber)NewStructure->edict->v.team;
|
||||
|
@ -2146,6 +2182,8 @@ void AITAC_OnStructureCreated(AvHAIBuildableStructure* NewStructure)
|
|||
|
||||
void AITAC_OnStructureCompleted(AvHAIBuildableStructure* NewStructure)
|
||||
{
|
||||
if (!NewStructure || FNullEnt(NewStructure->edict) || NewStructure->edict->v.deadflag != DEAD_NO || (NewStructure->edict->v.effects & EF_NODRAW)) { return; }
|
||||
|
||||
if (NewStructure->StructureType == STRUCTURE_MARINE_PHASEGATE)
|
||||
{
|
||||
DeployableSearchFilter Filter;
|
||||
|
@ -2217,6 +2255,8 @@ void AITAC_RemovePhaseGateConnections(AvHAIBuildableStructure* SourceGate, AvHAI
|
|||
|
||||
void AITAC_OnStructureBeginRecycling(AvHAIBuildableStructure* RecyclingStructure)
|
||||
{
|
||||
if (!RecyclingStructure || FNullEnt(RecyclingStructure->edict) || RecyclingStructure->edict->v.deadflag != DEAD_NO || (RecyclingStructure->edict->v.effects & EF_NODRAW)) { return; }
|
||||
|
||||
// For phase gates, treat them like they've been destroyed
|
||||
if (RecyclingStructure->StructureType == STRUCTURE_MARINE_PHASEGATE)
|
||||
{
|
||||
|
@ -2226,6 +2266,8 @@ void AITAC_OnStructureBeginRecycling(AvHAIBuildableStructure* RecyclingStructure
|
|||
|
||||
void AITAC_OnStructureDestroyed(AvHAIBuildableStructure* DestroyedStructure)
|
||||
{
|
||||
if (!DestroyedStructure || FNullEnt(DestroyedStructure->edict)) { return; }
|
||||
|
||||
UTIL_RemoveStructureTemporaryObstacles(DestroyedStructure);
|
||||
|
||||
if (DestroyedStructure->StructureType == STRUCTURE_MARINE_PHASEGATE)
|
||||
|
|
|
@ -15,10 +15,10 @@
|
|||
#include "AvHAIConstants.h"
|
||||
|
||||
// How frequently to update the global list of built structures (in seconds). 0 = every frame
|
||||
static const float structure_inventory_refresh_rate = 0.2f;
|
||||
static const float structure_inventory_refresh_rate = 0.0f;
|
||||
|
||||
// How frequently to update the global list of dropped marine items (in seconds). 0 = every frame
|
||||
static const float item_inventory_refresh_rate = 0.1f;
|
||||
static const float item_inventory_refresh_rate = 0.0f;
|
||||
|
||||
bool AITAC_DeployableExistsAtLocation(const Vector& Location, const DeployableSearchFilter* Filter);
|
||||
std::vector<AvHAIBuildableStructure*> AITAC_FindAllDeployables(const Vector& Location, const DeployableSearchFilter* Filter);
|
||||
|
|
|
@ -383,7 +383,7 @@ bool AITASK_IsMoveTaskStillValid(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
|
|||
bool AITASK_IsWeldTaskStillValid(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
|
||||
{
|
||||
if (!Task) { return false; }
|
||||
if (FNullEnt(Task->TaskTarget)) { return false; }
|
||||
if (!Task->TaskTarget || FNullEnt(Task->TaskTarget) || (Task->TaskTarget->v.effects & EF_NODRAW) || Task->TaskTarget->v.deadflag != DEAD_NO) { return false; }
|
||||
if (Task->TaskTarget == pBot->Edict) { return false; }
|
||||
if (!PlayerHasWeapon(pBot->Player, WEAPON_MARINE_WELDER))
|
||||
{
|
||||
|
@ -469,7 +469,9 @@ bool AITASK_IsWeaponPickupTaskStillValid(AvHAIPlayer* pBot, AvHAIPlayerTask* Tas
|
|||
|
||||
bool AITASK_IsAttackTaskStillValid(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
|
||||
{
|
||||
if (FNullEnt(Task->TaskTarget) || (vIsZero(Task->TaskTarget->v.origin) && vIsZero(Task->TaskLocation))) { return false; }
|
||||
if (!Task->TaskTarget || FNullEnt(Task->TaskTarget) || (Task->TaskTarget->v.effects & EF_NODRAW) || Task->TaskTarget->v.deadflag != DEAD_NO) { return false; }
|
||||
|
||||
if ((vIsZero(Task->TaskTarget->v.origin) && vIsZero(Task->TaskLocation))) { return false; }
|
||||
|
||||
if ((Task->TaskTarget->v.effects & EF_NODRAW) || (Task->TaskTarget->v.deadflag != DEAD_NO)) { return false; }
|
||||
|
||||
|
@ -531,7 +533,9 @@ bool AITASK_IsGuardTaskStillValid(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
|
|||
|
||||
bool AITASK_IsMineStructureTaskStillValid(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
|
||||
{
|
||||
if (FNullEnt(Task->TaskTarget) || UTIL_StructureIsRecycling(Task->TaskTarget)) { return false; }
|
||||
if (!Task->TaskTarget || FNullEnt(Task->TaskTarget) || (Task->TaskTarget->v.effects & EF_NODRAW) || Task->TaskTarget->v.deadflag != DEAD_NO) { return false; }
|
||||
|
||||
if (UTIL_StructureIsRecycling(Task->TaskTarget)) { return false; }
|
||||
|
||||
if (!PlayerHasWeapon(pBot->Player, WEAPON_MARINE_MINES)) { return false; }
|
||||
|
||||
|
@ -776,7 +780,7 @@ bool AITASK_IsMarineCapResNodeTaskStillValid(AvHAIPlayer* pBot, AvHAIPlayerTask*
|
|||
|
||||
bool AITASK_IsDefendTaskStillValid(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
|
||||
{
|
||||
if (FNullEnt(Task->TaskTarget) || Task->TaskTarget->v.deadflag != DEAD_NO) { return false; }
|
||||
if (!Task->TaskTarget || FNullEnt(Task->TaskTarget) || (Task->TaskTarget->v.effects & EF_NODRAW) || Task->TaskTarget->v.deadflag != DEAD_NO) { return false; }
|
||||
|
||||
if (GetStructureTypeFromEdict(Task->TaskTarget) == STRUCTURE_NONE) { return false; }
|
||||
|
||||
|
@ -797,7 +801,7 @@ bool AITASK_IsDefendTaskStillValid(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
|
|||
|
||||
bool AITASK_IsReinforceStructureTaskStillValid(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
|
||||
{
|
||||
if (FNullEnt(Task->TaskTarget) || Task->TaskTarget->v.deadflag != DEAD_NO) { return false; }
|
||||
if (!Task->TaskTarget || FNullEnt(Task->TaskTarget) || (Task->TaskTarget->v.effects & EF_NODRAW) || Task->TaskTarget->v.deadflag != DEAD_NO) { return false; }
|
||||
|
||||
if (!FNullEnt(Task->TaskSecondaryTarget) && !UTIL_StructureIsFullyBuilt(Task->TaskSecondaryTarget)) { return true; }
|
||||
|
||||
|
@ -984,7 +988,7 @@ bool AITASK_IsAlienGetHealthTaskStillValid(AvHAIPlayer* pBot, AvHAIPlayerTask* T
|
|||
|
||||
bool AITASK_IsAlienHealTaskStillValid(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
|
||||
{
|
||||
if (FNullEnt(Task->TaskTarget) || Task->TaskTarget->v.deadflag != DEAD_NO) { return false; }
|
||||
if (!Task->TaskTarget || FNullEnt(Task->TaskTarget) || (Task->TaskTarget->v.effects & EF_NODRAW) || Task->TaskTarget->v.deadflag != DEAD_NO) { return false; }
|
||||
|
||||
if (!IsPlayerGorge(pBot->Edict)) { return false; }
|
||||
|
||||
|
@ -3082,7 +3086,7 @@ void AITASK_SetWeldTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task, edict_t* Targe
|
|||
void AITASK_SetAttackTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task, edict_t* Target, const bool bIsUrgent)
|
||||
{
|
||||
// Don't set the task if the target is invalid, dead or on the same team as the bot (can't picture a situation where you want them to teamkill...)
|
||||
if (FNullEnt(Target) || (Target->v.deadflag != DEAD_NO) || Target->v.team == pBot->Edict->v.team)
|
||||
if (!Target || FNullEnt(Target) || (Target->v.deadflag != DEAD_NO) || Target->v.team == pBot->Edict->v.team)
|
||||
{
|
||||
AITASK_ClearBotTask(pBot, Task);
|
||||
return;
|
||||
|
|
Loading…
Reference in a new issue