mirror of
https://github.com/ENSL/NS.git
synced 2025-04-20 16:30:56 +00:00
Replaced fixed arrays with vectors
* Resource node and hive lists are now vectors. * Further improved bot weld behaviour
This commit is contained in:
parent
d15e7bfdad
commit
410351149e
10 changed files with 214 additions and 173 deletions
|
@ -80,22 +80,6 @@ typedef enum
|
|||
HIVE_TECH_MOVEMENT = 3
|
||||
} HiveTechStatus;
|
||||
|
||||
// Data structure to hold information about each hive in the map
|
||||
typedef struct _HIVE_DEFINITION_T
|
||||
{
|
||||
AvHHive* HiveEntity = nullptr;
|
||||
Vector Location = g_vecZero; // Origin of the hive
|
||||
Vector FloorLocation = g_vecZero; // Some hives are suspended in the air, this is the floor location directly beneath it
|
||||
HiveStatusType Status = HIVE_STATUS_UNBUILT; // Can be unbuilt, in progress, or fully built
|
||||
AvHMessageID TechStatus = MESSAGE_NULL; // What tech (if any) is assigned to this hive right now
|
||||
bool bIsUnderAttack = false; // Is the hive currently under attack? Becomes false if not taken damage for more than 10 seconds
|
||||
int HiveResNodeIndex = -1; // Which resource node (indexes into ResourceNodes array) belongs to this hive?
|
||||
unsigned int ObstacleRefs[8]; // When in progress or built, will place an obstacle so bots don't try to walk through it
|
||||
float NextFloorLocationCheck = 0.0f; // When should the closest navigable point to the hive be calculated? Used to delay the check after a hive is built
|
||||
AvHTeamNumber OwningTeam = TEAM_IND;
|
||||
|
||||
} AvHAIHiveDefinition;
|
||||
|
||||
typedef enum _AI_REACHABILITY_STATUS
|
||||
{
|
||||
AI_REACHABILITY_NONE = 0,
|
||||
|
@ -105,18 +89,6 @@ typedef enum _AI_REACHABILITY_STATUS
|
|||
AI_REACHABILITY_WELDER = 1u << 3,
|
||||
} AvHAIReachabilityStatus;
|
||||
|
||||
// Data structure used to track resource nodes in the map
|
||||
typedef struct _RESOURCE_NODE
|
||||
{
|
||||
AvHFuncResource* ResourceEntity = nullptr; // The func_resource edict reference
|
||||
Vector Location = g_vecZero; // origin of the func_resource edict (not the tower itself)
|
||||
bool bIsOccupied = false; // True if there is any resource tower on it
|
||||
AvHTeamNumber OwningTeam = TEAM_IND; // The team that has currently capped this node (TEAM_IND if none)
|
||||
edict_t* ActiveTowerEntity = nullptr; // Reference to the resource tower edict (if capped)
|
||||
bool bIsBaseNode = false; // Is this a node in the marine base or active alien hive?
|
||||
unsigned int ReachabilityFlags = AI_REACHABILITY_NONE; // Is this reachable by the bots? Checks for marine reachability only
|
||||
} AvHAIResourceNode;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
STRUCTURE_STATUS_NONE = 0, // No filters, all buildings will be returned
|
||||
|
@ -193,6 +165,34 @@ typedef enum _STRUCTUREPURPOSE
|
|||
|
||||
} StructurePurpose;
|
||||
|
||||
// Data structure used to track resource nodes in the map
|
||||
typedef struct _RESOURCE_NODE
|
||||
{
|
||||
AvHFuncResource* ResourceEntity = nullptr; // The func_resource edict reference
|
||||
Vector Location = g_vecZero; // origin of the func_resource edict (not the tower itself)
|
||||
bool bIsOccupied = false; // True if there is any resource tower on it
|
||||
AvHTeamNumber OwningTeam = TEAM_IND; // The team that has currently capped this node (TEAM_IND if none)
|
||||
edict_t* ActiveTowerEntity = nullptr; // Reference to the resource tower edict (if capped)
|
||||
bool bIsBaseNode = false; // Is this a node in the marine base or active alien hive?
|
||||
unsigned int ReachabilityFlags = AI_REACHABILITY_NONE; // Is this reachable by the bots? Checks for marine reachability only
|
||||
} AvHAIResourceNode;
|
||||
|
||||
// Data structure to hold information about each hive in the map
|
||||
typedef struct _HIVE_DEFINITION_T
|
||||
{
|
||||
AvHHive* HiveEntity = nullptr; // Hive entity reference
|
||||
Vector Location = g_vecZero; // Origin of the hive
|
||||
Vector FloorLocation = g_vecZero; // Some hives are suspended in the air, this is the floor location directly beneath it
|
||||
HiveStatusType Status = HIVE_STATUS_UNBUILT; // Can be unbuilt, in progress, or fully built
|
||||
AvHMessageID TechStatus = MESSAGE_NULL; // What tech (if any) is assigned to this hive right now
|
||||
bool bIsUnderAttack = false; // Is the hive currently under attack? Becomes false if not taken damage for more than 10 seconds
|
||||
AvHAIResourceNode* HiveResNodeRef = nullptr; // Which resource node (indexes into ResourceNodes array) belongs to this hive?
|
||||
unsigned int ObstacleRefs[8]; // When in progress or built, will place an obstacle so bots don't try to walk through it
|
||||
float NextFloorLocationCheck = 0.0f; // When should the closest navigable point to the hive be calculated? Used to delay the check after a hive is built
|
||||
AvHTeamNumber OwningTeam = TEAM_IND; // Which team owns this hive currently (TEAM_IND if empty)
|
||||
|
||||
} AvHAIHiveDefinition;
|
||||
|
||||
// A nav profile combines a nav mesh reference (indexed into NavMeshes) and filters to determine how a bot should find paths
|
||||
typedef struct _NAV_PROFILE
|
||||
{
|
||||
|
@ -446,6 +446,7 @@ typedef struct _NAV_STATUS
|
|||
|
||||
bool bShouldWalk = false; // Should the bot walk at this point?
|
||||
|
||||
BotMoveStyle PreviousMoveStyle = MOVESTYLE_NORMAL; // Previous desired move style (e.g. normal, ambush, hide). Will trigger new path calculations if this changes
|
||||
BotMoveStyle MoveStyle = MOVESTYLE_NORMAL; // Current desired move style (e.g. normal, ambush, hide). Will trigger new path calculations if this changes
|
||||
float LastPathCalcTime = 0.0f; // When the bot last calculated a path, to limit how frequently it can recalculate
|
||||
|
||||
|
|
|
@ -4596,8 +4596,9 @@ void MarineUpdateBotMoveProfile(AvHAIPlayer* pBot, BotMoveStyle MoveStyle)
|
|||
}
|
||||
}
|
||||
|
||||
if (MoveStyle == pBot->BotNavInfo.MoveStyle) { return; }
|
||||
if (MoveStyle == pBot->BotNavInfo.PreviousMoveStyle) { return; }
|
||||
|
||||
pBot->BotNavInfo.PreviousMoveStyle = MoveStyle;
|
||||
pBot->BotNavInfo.bNavProfileChanged = true;
|
||||
pBot->BotNavInfo.MoveStyle = MoveStyle;
|
||||
|
||||
|
@ -4618,7 +4619,9 @@ void MarineUpdateBotMoveProfile(AvHAIPlayer* pBot, BotMoveStyle MoveStyle)
|
|||
|
||||
void SkulkUpdateBotMoveProfile(AvHAIPlayer* pBot, BotMoveStyle MoveStyle)
|
||||
{
|
||||
if (MoveStyle == pBot->BotNavInfo.MoveStyle) { return; }
|
||||
if (MoveStyle == pBot->BotNavInfo.PreviousMoveStyle) { return; }
|
||||
|
||||
pBot->BotNavInfo.PreviousMoveStyle = MoveStyle;
|
||||
|
||||
pBot->BotNavInfo.bNavProfileChanged = true;
|
||||
pBot->BotNavInfo.MoveStyle = MoveStyle;
|
||||
|
@ -4643,7 +4646,9 @@ void SkulkUpdateBotMoveProfile(AvHAIPlayer* pBot, BotMoveStyle MoveStyle)
|
|||
|
||||
void GorgeUpdateBotMoveProfile(AvHAIPlayer* pBot, BotMoveStyle MoveStyle)
|
||||
{
|
||||
if (MoveStyle == pBot->BotNavInfo.MoveStyle) { return; }
|
||||
if (MoveStyle == pBot->BotNavInfo.PreviousMoveStyle) { return; }
|
||||
|
||||
pBot->BotNavInfo.PreviousMoveStyle = MoveStyle;
|
||||
|
||||
pBot->BotNavInfo.bNavProfileChanged = true;
|
||||
pBot->BotNavInfo.MoveStyle = MoveStyle;
|
||||
|
@ -4667,7 +4672,9 @@ void GorgeUpdateBotMoveProfile(AvHAIPlayer* pBot, BotMoveStyle MoveStyle)
|
|||
|
||||
void LerkUpdateBotMoveProfile(AvHAIPlayer* pBot, BotMoveStyle MoveStyle)
|
||||
{
|
||||
if (MoveStyle == pBot->BotNavInfo.MoveStyle) { return; }
|
||||
if (MoveStyle == pBot->BotNavInfo.PreviousMoveStyle) { return; }
|
||||
|
||||
pBot->BotNavInfo.PreviousMoveStyle = MoveStyle;
|
||||
|
||||
pBot->BotNavInfo.bNavProfileChanged = true;
|
||||
pBot->BotNavInfo.MoveStyle = MoveStyle;
|
||||
|
@ -4693,7 +4700,9 @@ void LerkUpdateBotMoveProfile(AvHAIPlayer* pBot, BotMoveStyle MoveStyle)
|
|||
|
||||
void FadeUpdateBotMoveProfile(AvHAIPlayer* pBot, BotMoveStyle MoveStyle)
|
||||
{
|
||||
if (MoveStyle == pBot->BotNavInfo.MoveStyle) { return; }
|
||||
if (MoveStyle == pBot->BotNavInfo.PreviousMoveStyle) { return; }
|
||||
|
||||
pBot->BotNavInfo.PreviousMoveStyle = MoveStyle;
|
||||
|
||||
pBot->BotNavInfo.bNavProfileChanged = true;
|
||||
pBot->BotNavInfo.MoveStyle = MoveStyle;
|
||||
|
@ -4773,7 +4782,7 @@ bool MoveTo(AvHAIPlayer* pBot, const Vector Destination, const BotMoveStyle Move
|
|||
}
|
||||
}
|
||||
|
||||
UpdateBotMoveProfile(pBot, MoveStyle);
|
||||
pBot->BotNavInfo.MoveStyle = MoveStyle;
|
||||
UTIL_UpdateBotMovementStatus(pBot);
|
||||
|
||||
bool bIsFlyingProfile = pBot->BotNavInfo.NavProfile.bFlyingProfile;
|
||||
|
@ -4786,14 +4795,16 @@ bool MoveTo(AvHAIPlayer* pBot, const Vector Destination, const BotMoveStyle Move
|
|||
|
||||
Vector MoveTaskDestination = g_vecZero;
|
||||
Vector MoveTaskOrigin = g_vecZero;
|
||||
Vector MoveSecondaryOrigin = g_vecZero;
|
||||
|
||||
if (bHasMovementTask)
|
||||
{
|
||||
MoveTaskDestination = BotNavInfo->MovementTask.TaskLocation;
|
||||
MoveTaskOrigin = (!FNullEnt(BotNavInfo->MovementTask.TaskTarget)) ? BotNavInfo->MovementTask.TaskTarget->v.origin : g_vecZero;
|
||||
MoveSecondaryOrigin = (!FNullEnt(BotNavInfo->MovementTask.TaskSecondaryTarget)) ? BotNavInfo->MovementTask.TaskSecondaryTarget->v.origin : g_vecZero;
|
||||
}
|
||||
|
||||
bool bUltimateDestinationChanged = !vEquals(Destination, BotNavInfo->TargetDestination, GetPlayerRadius(pBot->Player)) && !vEquals(Destination, MoveTaskDestination) && !vEquals(Destination, MoveTaskOrigin);
|
||||
bool bUltimateDestinationChanged = !vEquals(Destination, BotNavInfo->TargetDestination, GetPlayerRadius(pBot->Player)) && !vEquals(Destination, MoveTaskDestination) && !vEquals(Destination, MoveTaskOrigin) && !vEquals(Destination, MoveSecondaryOrigin);
|
||||
|
||||
bool bHasReachedDestination = BotIsAtLocation(pBot, BotNavInfo->TargetDestination);
|
||||
|
||||
|
@ -4803,7 +4814,7 @@ bool MoveTo(AvHAIPlayer* pBot, const Vector Destination, const BotMoveStyle Move
|
|||
if (bIsFlyingProfile || AbortCurrentMove(pBot, Destination))
|
||||
{
|
||||
// Don't clear the path if we're in the middle of a movement task
|
||||
if (!vEquals(Destination, MoveTaskDestination) && !vEquals(Destination, MoveTaskOrigin))
|
||||
if (!vEquals(Destination, MoveTaskDestination) && !vEquals(Destination, MoveTaskOrigin) && !vEquals(Destination, MoveSecondaryOrigin))
|
||||
{
|
||||
ClearBotPath(pBot);
|
||||
}
|
||||
|
@ -4812,7 +4823,7 @@ bool MoveTo(AvHAIPlayer* pBot, const Vector Destination, const BotMoveStyle Move
|
|||
}
|
||||
else
|
||||
{
|
||||
if (bHasMovementTask && !vEquals(Destination, MoveTaskDestination) && !vEquals(Destination, MoveTaskOrigin))
|
||||
if (bHasMovementTask && !vEquals(Destination, MoveTaskDestination) && !vEquals(Destination, MoveTaskOrigin) && !vEquals(Destination, MoveSecondaryOrigin))
|
||||
{
|
||||
if (AITASK_IsTaskStillValid(pBot, &BotNavInfo->MovementTask))
|
||||
{
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
#include "DetourStatus.h"
|
||||
#include "DetourNavMeshQuery.h"
|
||||
#include "DetourTileCache.h"
|
||||
#include "AvHAIPlayer.h"
|
||||
|
||||
/* Navigation profiles determine which nav mesh (regular, onos, building) is used for queries, and what
|
||||
|
@ -31,7 +32,7 @@ constexpr auto ONOS_BASE_NAV_PROFILE = 5;
|
|||
constexpr auto STRUCTURE_BASE_NAV_PROFILE = 6;
|
||||
constexpr auto ALL_NAV_PROFILE = 7;
|
||||
|
||||
#define MAX_PATH_POLY 512 // Max nav mesh polys that can be traversed in a path. This should be sufficient for any sized map.
|
||||
constexpr auto MAX_PATH_POLY = 512; // Max nav mesh polys that can be traversed in a path. This should be sufficient for any sized map.
|
||||
|
||||
// Possible area types. Water, Road, Door and Grass are not used (left-over from Detour library)
|
||||
enum SamplePolyAreas
|
||||
|
|
|
@ -1458,6 +1458,13 @@ void StartNewBotFrame(AvHAIPlayer* pBot)
|
|||
SetBaseNavProfile(pBot);
|
||||
}
|
||||
|
||||
UpdateBotMoveProfile(pBot, pBot->BotNavInfo.MoveStyle);
|
||||
|
||||
if (IsPlayerMarine(pBot->Edict))
|
||||
{
|
||||
UpdateCommanderOrders(pBot);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void DroneThink(AvHAIPlayer* pBot)
|
||||
|
@ -1466,7 +1473,12 @@ void DroneThink(AvHAIPlayer* pBot)
|
|||
|
||||
pBot->CurrentTask = &pBot->PrimaryBotTask;
|
||||
|
||||
if (pBot->PrimaryBotTask.TaskType != TASK_NONE)
|
||||
if (pBot->CommanderTask.TaskType != TASK_NONE)
|
||||
{
|
||||
BotProgressTask(pBot, &pBot->CommanderTask);
|
||||
AITASK_ClearBotTask(pBot, &pBot->PrimaryBotTask);
|
||||
}
|
||||
else if (pBot->PrimaryBotTask.TaskType != TASK_NONE)
|
||||
{
|
||||
BotProgressTask(pBot, &pBot->PrimaryBotTask);
|
||||
}
|
||||
|
@ -1489,11 +1501,10 @@ void TestNavThink(AvHAIPlayer* pBot)
|
|||
}
|
||||
|
||||
BotProgressTask(pBot, &pBot->PrimaryBotTask);
|
||||
//BotDrawPath(pBot, 0.0f, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
AvHAIResourceNode* RandomNode = AITAC_GetRandomResourceNode();
|
||||
AvHAIResourceNode* RandomNode = AITAC_GetRandomResourceNode(pBot->BotNavInfo.NavProfile.ReachabilityFlag);
|
||||
|
||||
if (!RandomNode) { return; }
|
||||
|
||||
|
@ -1527,4 +1538,30 @@ void BotResumePlay(AvHAIPlayer* pBot)
|
|||
SetBaseNavProfile(pBot);
|
||||
|
||||
pBot->bIsInactive = false;
|
||||
}
|
||||
|
||||
void UpdateCommanderOrders(AvHAIPlayer* pBot)
|
||||
{
|
||||
OrderListType ActiveOrders = pBot->Player->GetActiveOrders();
|
||||
|
||||
for (auto it = ActiveOrders.begin(); it != ActiveOrders.end(); it++)
|
||||
{
|
||||
if (it->GetOrderActive() && it->GetReceiver() && ENTINDEX(pBot->Edict) == it->GetReceiver())
|
||||
{
|
||||
Vector OrderLocation = g_vecZero;
|
||||
it->GetLocation(OrderLocation);
|
||||
|
||||
switch (it->GetOrderType())
|
||||
{
|
||||
case ORDERTYPEL_MOVE:
|
||||
AITASK_SetMoveTask(pBot, &pBot->CommanderTask, OrderLocation, true);
|
||||
break;
|
||||
case ORDERTYPET_BUILD:
|
||||
AITASK_SetBuildTask(pBot, &pBot->CommanderTask, INDEXENT(it->GetTargetIndex()), true);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -62,4 +62,6 @@ bool ShouldBotThink(AvHAIPlayer* pBot);
|
|||
|
||||
void BotResumePlay(AvHAIPlayer* pBot);
|
||||
|
||||
void UpdateCommanderOrders(AvHAIPlayer* pBot);
|
||||
|
||||
#endif
|
|
@ -25,11 +25,8 @@
|
|||
#include <unordered_map>
|
||||
|
||||
|
||||
AvHAIResourceNode ResourceNodes[64];
|
||||
int NumTotalResNodes;
|
||||
|
||||
AvHAIHiveDefinition Hives[3];
|
||||
int NumTotalHives;
|
||||
vector<AvHAIResourceNode> ResourceNodes;
|
||||
vector<AvHAIHiveDefinition> Hives;
|
||||
|
||||
float CommanderViewZHeight;
|
||||
|
||||
|
@ -368,47 +365,52 @@ Vector AITAC_GetFloorLocationForHive(const AvHAIHiveDefinition* Hive)
|
|||
|
||||
void AITAC_RefreshHiveData()
|
||||
{
|
||||
if (NumTotalHives == 0)
|
||||
if (Hives.size() == 0)
|
||||
{
|
||||
FOR_ALL_ENTITIES(kesTeamHive, AvHHive*)
|
||||
|
||||
Hives[NumTotalHives].HiveEntity = theEntity;
|
||||
Hives[NumTotalHives].Location = theEntity->pev->origin;
|
||||
Hives[NumTotalHives].HiveResNodeIndex = AITAC_FindNearestResNodeIndexToLocation(theEntity->pev->origin);
|
||||
Hives[NumTotalHives].FloorLocation = UTIL_GetFloorUnderEntity(theEntity->edict()); // Some hives are suspended in the air, this is the floor location directly beneath it
|
||||
AvHAIHiveDefinition NewHive;
|
||||
NewHive.HiveEntity = theEntity;
|
||||
NewHive.Location = theEntity->pev->origin;
|
||||
NewHive.HiveResNodeRef = AITAC_GetNearestResourceNodeToLocation(theEntity->pev->origin);
|
||||
NewHive.FloorLocation = UTIL_GetFloorUnderEntity(theEntity->edict()); // Some hives are suspended in the air, this is the floor location directly beneath it
|
||||
|
||||
NumTotalHives++;
|
||||
Hives.push_back(NewHive);
|
||||
|
||||
END_FOR_ALL_ENTITIES(kesTeamHive)
|
||||
|
||||
}
|
||||
|
||||
for (int i = 0; i < NumTotalHives; i++)
|
||||
int NextRefresh = 0;
|
||||
|
||||
for (auto it = Hives.begin(); it != Hives.end(); it++)
|
||||
{
|
||||
AvHHive* theEntity = Hives[i].HiveEntity;
|
||||
AvHHive* theEntity = it->HiveEntity;
|
||||
|
||||
Hives[i].TechStatus = theEntity->GetTechnology();
|
||||
Hives[i].bIsUnderAttack = GetGameRules()->GetIsEntityUnderAttack(theEntity->entindex());
|
||||
Hives[i].OwningTeam = theEntity->GetTeamNumber();
|
||||
Hives[i].Status = (theEntity->GetIsActive() ? HIVE_STATUS_BUILT : (theEntity->GetIsSpawning() ? HIVE_STATUS_BUILDING : HIVE_STATUS_UNBUILT));
|
||||
it->TechStatus = theEntity->GetTechnology();
|
||||
it->bIsUnderAttack = GetGameRules()->GetIsEntityUnderAttack(theEntity->entindex());
|
||||
it->OwningTeam = theEntity->GetTeamNumber();
|
||||
it->Status = (theEntity->GetIsActive() ? HIVE_STATUS_BUILT : (theEntity->GetIsSpawning() ? HIVE_STATUS_BUILDING : HIVE_STATUS_UNBUILT));
|
||||
|
||||
if (Hives[i].Status != HIVE_STATUS_UNBUILT && Hives[i].ObstacleRefs[REGULAR_NAV_MESH] == 0)
|
||||
if (it->Status != HIVE_STATUS_UNBUILT && it->ObstacleRefs[REGULAR_NAV_MESH] == 0)
|
||||
{
|
||||
UTIL_AddTemporaryObstacles(UTIL_GetCentreOfEntity(Hives[i].HiveEntity->edict()) - Vector(0.0f, 0.0f, 25.0f), 125.0f, 300.0f, DT_AREA_NULL, Hives[i].ObstacleRefs);
|
||||
Hives[i].NextFloorLocationCheck = gpGlobals->time + 1.0f;
|
||||
UTIL_AddTemporaryObstacles(UTIL_GetCentreOfEntity(it->HiveEntity->edict()) - Vector(0.0f, 0.0f, 25.0f), 125.0f, 300.0f, DT_AREA_NULL, it->ObstacleRefs);
|
||||
it->NextFloorLocationCheck = gpGlobals->time + 1.0f;
|
||||
}
|
||||
else if (Hives[i].Status == HIVE_STATUS_UNBUILT && Hives[i].ObstacleRefs[REGULAR_NAV_MESH] != 0)
|
||||
else if (it->Status == HIVE_STATUS_UNBUILT && it->ObstacleRefs[REGULAR_NAV_MESH] != 0)
|
||||
{
|
||||
UTIL_RemoveTemporaryObstacles(Hives[i].ObstacleRefs);
|
||||
Hives[i].NextFloorLocationCheck = gpGlobals->time + 1.0f;
|
||||
UTIL_RemoveTemporaryObstacles(it->ObstacleRefs);
|
||||
it->NextFloorLocationCheck = gpGlobals->time + 1.0f;
|
||||
}
|
||||
|
||||
if (Hives[i].NextFloorLocationCheck > 0.0f && gpGlobals->time >= Hives[i].NextFloorLocationCheck)
|
||||
if (it->NextFloorLocationCheck > 0.0f && gpGlobals->time >= it->NextFloorLocationCheck)
|
||||
{
|
||||
Hives[i].FloorLocation = AITAC_GetFloorLocationForHive(&Hives[i]);
|
||||
it->FloorLocation = AITAC_GetFloorLocationForHive(&(*it));
|
||||
|
||||
Hives[i].NextFloorLocationCheck = gpGlobals->time + (5.0f + (0.1f * i));
|
||||
it->NextFloorLocationCheck = gpGlobals->time + (5.0f + (0.1f * NextRefresh));
|
||||
}
|
||||
|
||||
NextRefresh++;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -499,79 +501,95 @@ Vector AITAC_GetCommChairLocation(AvHTeamNumber Team)
|
|||
|
||||
void AITAC_RefreshResourceNodes()
|
||||
{
|
||||
if (NumTotalResNodes == 0)
|
||||
if (ResourceNodes.size() == 0)
|
||||
{
|
||||
FOR_ALL_ENTITIES(kesFuncResource, AvHFuncResource*)
|
||||
|
||||
ResourceNodes[NumTotalResNodes].ResourceEntity = theEntity;
|
||||
ResourceNodes[NumTotalResNodes].Location = theEntity->pev->origin;
|
||||
ResourceNodes[NumTotalResNodes].ReachabilityFlags = AI_REACHABILITY_NONE;
|
||||
AvHAIResourceNode NewResNode;
|
||||
NewResNode.ResourceEntity = theEntity;
|
||||
NewResNode.Location = theEntity->pev->origin;
|
||||
NewResNode.ReachabilityFlags = AI_REACHABILITY_NONE;
|
||||
|
||||
bool bIsReachableMarine = UTIL_PointIsReachable(BaseNavProfiles[MARINE_BASE_NAV_PROFILE], AITAC_GetTeamStartingLocation(GetGameRules()->GetTeamANumber()), ResourceNodes[NumTotalResNodes].Location, max_player_use_reach);
|
||||
bool bIsReachableSkulk = UTIL_PointIsReachable(BaseNavProfiles[SKULK_BASE_NAV_PROFILE], AITAC_GetTeamStartingLocation(GetGameRules()->GetTeamANumber()), ResourceNodes[NumTotalResNodes].Location, max_player_use_reach);
|
||||
bool bIsReachableOnos = UTIL_PointIsReachable(BaseNavProfiles[ONOS_BASE_NAV_PROFILE], AITAC_GetTeamStartingLocation(GetGameRules()->GetTeamANumber()), ResourceNodes[NumTotalResNodes].Location, max_player_use_reach);
|
||||
bool bIsReachableMarine = UTIL_PointIsReachable(BaseNavProfiles[MARINE_BASE_NAV_PROFILE], AITAC_GetTeamStartingLocation(GetGameRules()->GetTeamANumber()), NewResNode.Location, max_player_use_reach);
|
||||
bool bIsReachableSkulk = UTIL_PointIsReachable(BaseNavProfiles[SKULK_BASE_NAV_PROFILE], AITAC_GetTeamStartingLocation(GetGameRules()->GetTeamANumber()), NewResNode.Location, max_player_use_reach);
|
||||
bool bIsReachableOnos = UTIL_PointIsReachable(BaseNavProfiles[ONOS_BASE_NAV_PROFILE], AITAC_GetTeamStartingLocation(GetGameRules()->GetTeamANumber()), NewResNode.Location, max_player_use_reach);
|
||||
|
||||
if (bIsReachableMarine)
|
||||
{
|
||||
ResourceNodes[NumTotalResNodes].ReachabilityFlags |= AI_REACHABILITY_MARINE;
|
||||
NewResNode.ReachabilityFlags |= AI_REACHABILITY_MARINE;
|
||||
NewResNode.ReachabilityFlags |= AI_REACHABILITY_WELDER;
|
||||
}
|
||||
else
|
||||
{
|
||||
nav_profile WelderProfile;
|
||||
memcpy(&WelderProfile, &BaseNavProfiles[MARINE_BASE_NAV_PROFILE], sizeof(nav_profile));
|
||||
|
||||
WelderProfile.Filters.removeExcludeFlags(SAMPLE_POLYFLAGS_WELD);
|
||||
|
||||
bool bIsReachableWelder = UTIL_PointIsReachable(WelderProfile, AITAC_GetTeamStartingLocation(GetGameRules()->GetTeamANumber()), NewResNode.Location, max_player_use_reach);
|
||||
|
||||
if (bIsReachableWelder)
|
||||
{
|
||||
NewResNode.ReachabilityFlags |= AI_REACHABILITY_WELDER;
|
||||
}
|
||||
}
|
||||
|
||||
if (bIsReachableSkulk)
|
||||
{
|
||||
ResourceNodes[NumTotalResNodes].ReachabilityFlags |= AI_REACHABILITY_SKULK;
|
||||
NewResNode.ReachabilityFlags |= AI_REACHABILITY_SKULK;
|
||||
}
|
||||
|
||||
if (bIsReachableOnos)
|
||||
{
|
||||
ResourceNodes[NumTotalResNodes].ReachabilityFlags |= AI_REACHABILITY_ONOS;
|
||||
NewResNode.ReachabilityFlags |= AI_REACHABILITY_ONOS;
|
||||
}
|
||||
|
||||
NumTotalResNodes++;
|
||||
ResourceNodes.push_back(NewResNode);
|
||||
|
||||
END_FOR_ALL_ENTITIES(kesFuncResource)
|
||||
}
|
||||
|
||||
for (int i = 0; i < NumTotalResNodes; i++)
|
||||
for (auto it = ResourceNodes.begin(); it != ResourceNodes.end(); it++)
|
||||
{
|
||||
AvHFuncResource* ResourceEntity = ResourceNodes[i].ResourceEntity;
|
||||
AvHFuncResource* ResourceEntity = it->ResourceEntity;
|
||||
|
||||
ResourceNodes[i].bIsOccupied = ResourceEntity->GetIsOccupied();
|
||||
it->bIsOccupied = ResourceEntity->GetIsOccupied();
|
||||
|
||||
if (ResourceNodes[i].bIsOccupied)
|
||||
if (it->bIsOccupied)
|
||||
{
|
||||
DeployableSearchFilter TowerFilter;
|
||||
TowerFilter.DeployableTypes = (STRUCTURE_MARINE_RESTOWER | STRUCTURE_ALIEN_RESTOWER);
|
||||
|
||||
AvHAIBuildableStructure* OccupyingTower = AITAC_FindClosestDeployableToLocation(ResourceNodes[i].Location, &TowerFilter);
|
||||
AvHAIBuildableStructure* OccupyingTower = AITAC_FindClosestDeployableToLocation(it->Location, &TowerFilter);
|
||||
|
||||
if (OccupyingTower)
|
||||
{
|
||||
ResourceNodes[i].ActiveTowerEntity = OccupyingTower->edict;
|
||||
ResourceNodes[i].OwningTeam = OccupyingTower->EntityRef->GetTeamNumber();
|
||||
it->ActiveTowerEntity = OccupyingTower->edict;
|
||||
it->OwningTeam = OccupyingTower->EntityRef->GetTeamNumber();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ResourceNodes[i].ActiveTowerEntity = nullptr;
|
||||
ResourceNodes[i].OwningTeam = TEAM_IND;
|
||||
it->ActiveTowerEntity = nullptr;
|
||||
it->OwningTeam = TEAM_IND;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AvHAIResourceNode* AITAC_GetRandomResourceNode()
|
||||
AvHAIResourceNode* AITAC_GetRandomResourceNode(const unsigned int ReachabilityFlags)
|
||||
{
|
||||
AvHAIResourceNode* Result = nullptr;
|
||||
float MaxScore = 0.0f;
|
||||
|
||||
for (int i = 0; i < NumTotalResNodes; i++)
|
||||
for (auto it = ResourceNodes.begin(); it != ResourceNodes.end(); it++)
|
||||
{
|
||||
if (!(ResourceNodes[i].ReachabilityFlags & AI_REACHABILITY_MARINE)) { continue; }
|
||||
if (ReachabilityFlags != AI_REACHABILITY_NONE && !(it->ReachabilityFlags & ReachabilityFlags)) { continue; }
|
||||
|
||||
float ThisScore = frandrange(0.0f, 1.0f);
|
||||
|
||||
if (!Result || ThisScore > MaxScore)
|
||||
{
|
||||
Result = &ResourceNodes[i];
|
||||
Result = &(*it);
|
||||
MaxScore = ThisScore;
|
||||
}
|
||||
}
|
||||
|
@ -1054,6 +1072,8 @@ void AITAC_UpdateBuildableStructure(CBaseEntity* Structure)
|
|||
BuildingMap[EntIndex].StructureStatusFlags |= STRUCTURE_STATUS_UNDERATTACK;
|
||||
}
|
||||
|
||||
BuildingMap[EntIndex].LastSeen = StructureRefreshFrame;
|
||||
|
||||
}
|
||||
|
||||
void AITAC_OnStructureCreated(AvHAIBuildableStructure* NewStructure)
|
||||
|
@ -1102,8 +1122,7 @@ void AITAC_LinkDeployedItemToAction(AvHAIPlayer* CommanderBot, const AvHAIDroppe
|
|||
|
||||
void AITAC_ClearMapAIData()
|
||||
{
|
||||
memset(ResourceNodes, 0, sizeof(ResourceNodes));
|
||||
NumTotalResNodes = 0;
|
||||
ResourceNodes.clear();
|
||||
|
||||
AITAC_ClearHiveInfo();
|
||||
|
||||
|
@ -1123,38 +1142,19 @@ void AITAC_ClearMapAIData()
|
|||
|
||||
void AITAC_ClearHiveInfo()
|
||||
{
|
||||
memset(Hives, 0, sizeof(Hives));
|
||||
NumTotalHives = 0;
|
||||
}
|
||||
|
||||
int AITAC_FindNearestResNodeIndexToLocation(const Vector& Location)
|
||||
{
|
||||
int Result = -1;
|
||||
float MinDist = 0.0f;
|
||||
|
||||
for (int i = 0; i < NumTotalResNodes; i++)
|
||||
for (auto it = Hives.begin(); it != Hives.end(); it++)
|
||||
{
|
||||
if (ResourceNodes[i].ResourceEntity)
|
||||
if (it->ObstacleRefs[REGULAR_NAV_MESH] != 0)
|
||||
{
|
||||
float ThisDist = vDist3DSq(Location, ResourceNodes[i].ResourceEntity->pev->origin);
|
||||
|
||||
if (Result < 0 || ThisDist < MinDist)
|
||||
{
|
||||
Result = i;
|
||||
MinDist = ThisDist;
|
||||
}
|
||||
UTIL_RemoveTemporaryObstacles(it->ObstacleRefs);
|
||||
}
|
||||
}
|
||||
|
||||
return Result;
|
||||
|
||||
Hives.clear();
|
||||
}
|
||||
|
||||
bool AITAC_AlienHiveNeedsReinforcing(int HiveIndex)
|
||||
bool AITAC_AlienHiveNeedsReinforcing(const AvHAIHiveDefinition* Hive)
|
||||
{
|
||||
if (HiveIndex < 0 || HiveIndex >= NumTotalHives) { return false; }
|
||||
|
||||
const AvHAIHiveDefinition* Hive = AITAC_GetHiveAtIndex(HiveIndex);
|
||||
|
||||
if (!Hive) { return false; }
|
||||
|
||||
DeployableSearchFilter SearchFilter;
|
||||
|
@ -1196,7 +1196,7 @@ bool AITAC_AlienHiveNeedsReinforcing(int HiveIndex)
|
|||
|
||||
const AvHAIHiveDefinition* AITAC_GetHiveAtIndex(int Index)
|
||||
{
|
||||
if (Index > -1 && Index < NumTotalHives)
|
||||
if (Index > -1 && Index < Hives.size())
|
||||
{
|
||||
return &Hives[Index];
|
||||
}
|
||||
|
@ -1457,11 +1457,11 @@ bool UTIL_StructureIsResearching(edict_t* Structure, const AvHMessageID Research
|
|||
|
||||
AvHAIHiveDefinition* AITAC_GetHiveFromEdict(const edict_t* Edict)
|
||||
{
|
||||
for (int i = 0; i < NumTotalHives; i++)
|
||||
for (auto it = Hives.begin(); it != Hives.end(); it++)
|
||||
{
|
||||
if (Hives[i].HiveEntity->edict() == Edict)
|
||||
if (it->HiveEntity->edict() == Edict)
|
||||
{
|
||||
return &Hives[i];
|
||||
return &(*it);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1473,13 +1473,13 @@ const AvHAIHiveDefinition* AITAC_GetHiveNearestLocation(const Vector SearchLocat
|
|||
AvHAIHiveDefinition* Result = nullptr;
|
||||
float MinDist = 0.0f;
|
||||
|
||||
for (int i = 0; i < NumTotalHives; i++)
|
||||
for (auto it = Hives.begin(); it != Hives.end(); it++)
|
||||
{
|
||||
float ThisDist = vDist3DSq(SearchLocation, Hives[i].Location);
|
||||
float ThisDist = vDist3DSq(SearchLocation, it->Location);
|
||||
|
||||
if (!Result || ThisDist < MinDist)
|
||||
{
|
||||
Result = &Hives[i];
|
||||
Result = &(*it);
|
||||
MinDist = ThisDist;
|
||||
}
|
||||
}
|
||||
|
@ -1489,31 +1489,26 @@ const AvHAIHiveDefinition* AITAC_GetHiveNearestLocation(const Vector SearchLocat
|
|||
|
||||
AvHAIResourceNode* AITAC_GetNearestResourceNodeToLocation(const Vector Location)
|
||||
{
|
||||
int ResultIndex = -1;
|
||||
AvHAIResourceNode* Result = nullptr;
|
||||
float CurrMinDist = 0;
|
||||
|
||||
for (int i = 0; i < NumTotalResNodes; i++)
|
||||
for (auto it = ResourceNodes.begin(); it != ResourceNodes.end(); it++)
|
||||
{
|
||||
float DistSq = vDist2DSq(ResourceNodes[i].Location, Location);
|
||||
float DistSq = vDist2DSq(it->Location, Location);
|
||||
|
||||
if (ResultIndex < 0 || DistSq < CurrMinDist)
|
||||
if (!Result || DistSq < CurrMinDist)
|
||||
{
|
||||
ResultIndex = i;
|
||||
Result = &(*it);
|
||||
CurrMinDist = DistSq;
|
||||
}
|
||||
}
|
||||
|
||||
if (ResultIndex > -1)
|
||||
{
|
||||
return &ResourceNodes[ResultIndex];
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
return Result;
|
||||
}
|
||||
|
||||
AvHAIResourceNode* AITAC_FindNearestResourceNodeToLocation(const Vector Location, const DeployableSearchFilter* Filter)
|
||||
{
|
||||
int ResultIndex = -1;
|
||||
AvHAIResourceNode* Result = nullptr;
|
||||
|
||||
float MinDistSq = sqrf(Filter->MinSearchRadius);
|
||||
float MaxDistSq = sqrf(Filter->MaxSearchRadius);
|
||||
|
@ -1523,25 +1518,20 @@ AvHAIResourceNode* AITAC_FindNearestResourceNodeToLocation(const Vector Location
|
|||
|
||||
float CurrMinDist = 0;
|
||||
|
||||
for (int i = 0; i < NumTotalResNodes; i++)
|
||||
for (auto it = ResourceNodes.begin(); it != ResourceNodes.end(); it++)
|
||||
{
|
||||
if (Filter->ReachabilityFlags != AI_REACHABILITY_NONE && !(ResourceNodes[i].ReachabilityFlags & Filter->ReachabilityFlags)) { continue; }
|
||||
if (ResourceNodes[i].OwningTeam != Filter->Team) { continue; }
|
||||
if (Filter->ReachabilityFlags != AI_REACHABILITY_NONE && !(it->ReachabilityFlags & Filter->ReachabilityFlags)) { continue; }
|
||||
if (it->OwningTeam != Filter->Team) { continue; }
|
||||
|
||||
float DistSq = (Filter->bConsiderPhaseDistance) ? sqrf(AITAC_GetPhaseDistanceBetweenPoints(ResourceNodes[i].Location, Location)) : vDist2DSq(ResourceNodes[i].Location, Location);
|
||||
float DistSq = (Filter->bConsiderPhaseDistance) ? sqrf(AITAC_GetPhaseDistanceBetweenPoints(it->Location, Location)) : vDist2DSq(it->Location, Location);
|
||||
|
||||
if ((!bUseMinDist || DistSq >= MinDistSq) && (!bUseMaxDist || DistSq <= MaxDistSq) && (ResultIndex < 0 || DistSq < CurrMinDist))
|
||||
if ((!bUseMinDist || DistSq >= MinDistSq) && (!bUseMaxDist || DistSq <= MaxDistSq) && (!Result || DistSq < CurrMinDist))
|
||||
{
|
||||
ResultIndex = i;
|
||||
Result = &(*it);
|
||||
}
|
||||
}
|
||||
|
||||
if (ResultIndex > -1)
|
||||
{
|
||||
return &ResourceNodes[ResultIndex];
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
return Result;
|
||||
|
||||
}
|
||||
|
||||
|
@ -1633,12 +1623,12 @@ AvHAIHiveDefinition* AITAC_GetTeamHiveWithTech(const AvHTeamNumber Team, const A
|
|||
if (!TeamRef || TeamRef->GetTeamType() != AVH_CLASS_TYPE_ALIEN) { return nullptr; }
|
||||
|
||||
|
||||
for (int i = 0; i < NumTotalHives; i++)
|
||||
for (auto it = Hives.begin(); it != Hives.end(); it++)
|
||||
{
|
||||
// Only return active hives with the tech
|
||||
if (Hives[i].OwningTeam == Team && Hives[i].Status == HIVE_STATUS_BUILT && Hives[i].TechStatus == Tech)
|
||||
if (it->OwningTeam == Team && it->Status == HIVE_STATUS_BUILT && it->TechStatus == Tech)
|
||||
{
|
||||
return &Hives[i];
|
||||
return &(*it);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1653,10 +1643,10 @@ bool AITAC_TeamHiveWithTechExists(const AvHTeamNumber Team, const AvHMessageID T
|
|||
if (!TeamRef || TeamRef->GetTeamType() != AVH_CLASS_TYPE_ALIEN) { return false; }
|
||||
|
||||
|
||||
for (int i = 0; i < NumTotalHives; i++)
|
||||
for (auto it = Hives.begin(); it != Hives.end(); it++)
|
||||
{
|
||||
// Only return active hives with the tech
|
||||
if (Hives[i].OwningTeam == Team && Hives[i].Status == HIVE_STATUS_BUILT && Hives[i].TechStatus == Tech)
|
||||
if (it->OwningTeam == Team && it->Status == HIVE_STATUS_BUILT && it->TechStatus == Tech)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@ -1845,16 +1835,9 @@ int UTIL_GetCostOfStructureType(AvHAIDeployableStructureType StructureType)
|
|||
return 0;
|
||||
}
|
||||
|
||||
AvHAIResourceNode* AITAC_GetResourceNodeAtIndex(const int Index)
|
||||
{
|
||||
if (Index < 0 || Index >= NumTotalResNodes) { return nullptr; }
|
||||
|
||||
return &ResourceNodes[Index];
|
||||
}
|
||||
|
||||
int AITAC_GetNumHives()
|
||||
{
|
||||
return NumTotalHives;
|
||||
return Hives.size();
|
||||
}
|
||||
|
||||
AvHMessageID UTIL_StructureTypeToImpulseCommand(const AvHAIDeployableStructureType StructureType)
|
||||
|
|
|
@ -36,19 +36,15 @@ void AITAC_LinkAlienStructureToTask(AvHAIPlayer* pBot, AvHAIBuildableStruct
|
|||
|
||||
float AITAC_GetPhaseDistanceBetweenPoints(const Vector StartPoint, const Vector EndPoint);
|
||||
|
||||
int AITAC_FindNearestResNodeIndexToLocation(const Vector& Location);
|
||||
|
||||
const AvHAIHiveDefinition* AITAC_GetHiveAtIndex(int Index);
|
||||
const AvHAIHiveDefinition* AITAC_GetHiveNearestLocation(const Vector SearchLocation);
|
||||
|
||||
Vector AITAC_GetCommChairLocation(AvHTeamNumber Team);
|
||||
edict_t* AITAC_GetCommChair(AvHTeamNumber Team);
|
||||
|
||||
AvHAIResourceNode* AITAC_GetResourceNodeAtIndex(const int Index);
|
||||
|
||||
Vector AITAC_GetTeamStartingLocation(AvHTeamNumber Team);
|
||||
|
||||
AvHAIResourceNode* AITAC_GetRandomResourceNode();
|
||||
AvHAIResourceNode* AITAC_GetRandomResourceNode(const unsigned int ReachabilityFlags);
|
||||
|
||||
AvHAIDroppedItem* AITAC_FindClosestItemToLocation(const Vector& Location, const AvHAIDeployableItemType ItemType, float MinRadius, float MaxRadius, bool bConsiderPhaseDistance);
|
||||
|
||||
|
@ -70,7 +66,7 @@ void AITAC_ClearMapAIData();
|
|||
// Clear out all the hive information
|
||||
void AITAC_ClearHiveInfo();
|
||||
|
||||
bool AITAC_AlienHiveNeedsReinforcing(int HiveIndex);
|
||||
bool AITAC_AlienHiveNeedsReinforcing(const AvHAIHiveDefinition* Hive);
|
||||
|
||||
void AITAC_RefreshMarineItems();
|
||||
void AITAC_UpdateMarineItem(CBaseEntity* Item, AvHAIDeployableItemType ItemType);
|
||||
|
|
|
@ -90,7 +90,7 @@ void AITASK_OnCompleteCommanderTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
|
|||
|
||||
AvHAIBuildableStructure* NearbyAlienTower = AITAC_FindClosestDeployableToLocation(pBot->Edict->v.origin, &EnemyResTowerFilter);
|
||||
|
||||
if (!NearbyAlienTower)
|
||||
if (NearbyAlienTower)
|
||||
{
|
||||
const AvHAIResourceNode* NodeRef = AITAC_GetNearestResourceNodeToLocation(NearbyAlienTower->Location);
|
||||
if (NodeRef)
|
||||
|
@ -2196,13 +2196,22 @@ void BotProgressWeldTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
|
|||
{
|
||||
MoveTo(pBot, Task->TaskSecondaryTarget->v.origin, MOVESTYLE_NORMAL);
|
||||
}
|
||||
else
|
||||
{
|
||||
AvHAIDroppedItem* Welder = AITAC_FindClosestItemToLocation(pBot->Edict->v.origin, DEPLOYABLE_ITEM_WELDER, 0.0f, 0.0f, true);
|
||||
|
||||
if (Welder)
|
||||
{
|
||||
Task->TaskSecondaryTarget = Welder->edict;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsPlayerInUseRange(pBot->Edict, Task->TaskTarget))
|
||||
{
|
||||
BotLookAt(pBot, UTIL_GetClosestPointOnEntityToLocation(pBot->CurrentEyePosition, Task->TaskTarget));
|
||||
BotLookAt(pBot, UTIL_GetClosestPointOnEntityToLocation(pBot->Edict->v.origin, Task->TaskTarget));
|
||||
pBot->DesiredCombatWeapon = WEAPON_MARINE_WELDER;
|
||||
|
||||
if (GetBotCurrentWeapon(pBot) != WEAPON_MARINE_WELDER)
|
||||
|
@ -2280,7 +2289,7 @@ void MarineProgressSecureHiveTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
|
|||
return;
|
||||
}
|
||||
|
||||
const AvHAIResourceNode* ResNode = AITAC_GetResourceNodeAtIndex(Hive->HiveResNodeIndex);
|
||||
const AvHAIResourceNode* ResNode = Hive->HiveResNodeRef;
|
||||
|
||||
if (ResNode && ResNode->OwningTeam != pBot->Player->GetTeam())
|
||||
{
|
||||
|
@ -2780,7 +2789,7 @@ void AITASK_SetAttackTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task, edict_t* Tar
|
|||
|
||||
void AITASK_SetMoveTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task, const Vector Location, bool bIsUrgent)
|
||||
{
|
||||
if (Task->TaskType == TASK_MOVE && vDist2DSq(Task->TaskLocation, Location) < sqrf(100.0f))
|
||||
if (Task->TaskType == TASK_MOVE && vDist2DSq(Task->TaskLocation, Location) < sqrf(16.0f))
|
||||
{
|
||||
Task->bTaskIsUrgent = bIsUrgent;
|
||||
return;
|
||||
|
|
|
@ -295,6 +295,7 @@ public:
|
|||
int GetExperienceLevel() const;
|
||||
|
||||
AvHServerPlayerData* GetServerPlayerData();
|
||||
const OrderListType& GetActiveOrders() { return mClientOrders; }
|
||||
|
||||
virtual bool GetHasItem(const char *szName);
|
||||
virtual void GiveNamedItem(const char *szName, bool inSendMessage = false);
|
||||
|
|
|
@ -2331,7 +2331,7 @@ void AvHTeam::UpdateOrders()
|
|||
const float kExpireTime = 1.0f;
|
||||
if(!theOrderIter->GetOrderActive() && (theOrderIter->GetTimeOrderCompleted() != -1) && (gpGlobals->time > (theOrderIter->GetTimeOrderCompleted() + kExpireTime)))
|
||||
{
|
||||
this->mOrderList.erase(theOrderIter);
|
||||
theOrderIter = this->mOrderList.erase(theOrderIter);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue