mirror of
https://github.com/ENSL/NS.git
synced 2025-03-04 08:20:54 +00:00
Final fixes for next release
* Fixed some nav meshes so Onos can navigate better, and avoid bad structure placement * Improved bot movement when not using the nav mesh (i.e. direct movement) * Fixed player-built structures being duplicated if a commander takes over (i.e. AI commander ignoring player-placed structures and acting like they don't exist) * Fixed marines just loitering in enemy hives doing nothing * Fixed gorges sometimes not fully building structures and just leaving them to slowly grow
This commit is contained in:
parent
802174ddcd
commit
1363f48d96
12 changed files with 338 additions and 173 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1065,7 +1065,7 @@ bool AICOMM_CheckForNextBuildAction(AvHAIPlayer* pBot)
|
|||
|
||||
if (HiveUnderSiege)
|
||||
{
|
||||
bool bAlreadyScanning = AITAC_ItemExistsInLocation(HiveUnderSiege->Location, DEPLOYABLE_ITEM_SCAN, pBot->Player->GetTeam(), AI_REACHABILITY_NONE, 0.0f, UTIL_MetresToGoldSrcUnits(5.0f), false);
|
||||
bool bAlreadyScanning = AITAC_ItemExistsInLocation(HiveUnderSiege->Location, DEPLOYABLE_ITEM_SCAN, TEAM_IND, AI_REACHABILITY_NONE, 0.0f, UTIL_MetresToGoldSrcUnits(10.0f), false);
|
||||
|
||||
if (!bAlreadyScanning)
|
||||
{
|
||||
|
|
|
@ -354,7 +354,7 @@ typedef struct _AVH_AI_BUILDABLE_STRUCTURE
|
|||
vector<AvHAIOffMeshConnection> OffMeshConnections; // References to any off-mesh connections this structure is associated with
|
||||
Vector LastSuccessfulCommanderLocation = g_vecZero; // Tracks the last commander view location where it successfully placed or selected the building
|
||||
Vector LastSuccessfulCommanderAngle = g_vecZero; // Tracks the last commander input angle ("click" location) used to successfully place or select building
|
||||
StructurePurpose Purpose = STRUCTURE_PURPOSE_GENERAL;
|
||||
StructurePurpose Purpose = STRUCTURE_PURPOSE_NONE;
|
||||
bool bReachabilityMarkedDirty = false; // If true, reachability flags will be recalculated for this structure
|
||||
|
||||
bool IsValid() { return !FNullEnt(edict) && !edict->free && !(edict->v.flags & EF_NODRAW) && edict->v.deadflag == DEAD_NO; }
|
||||
|
|
|
@ -2429,7 +2429,7 @@ bool HasBotCompletedWalkMove(const AvHAIPlayer* pBot, Vector MoveStart, Vector M
|
|||
|
||||
if (NextMoveFlag != SAMPLE_POLYFLAGS_DISABLED)
|
||||
{
|
||||
bNextPointReachable = UTIL_PointIsDirectlyReachable(pBot->CurrentFloorPosition, NextMoveDestination);
|
||||
bNextPointReachable = UTIL_PointIsDirectlyReachable(pBot->CurrentFloorPosition, NextMoveDestination, GetPlayerRadius(pBot->Edict));
|
||||
}
|
||||
|
||||
return vPointOverlaps3D(MoveEnd, pBot->Edict->v.absmin, pBot->Edict->v.absmax) || (bNextPointReachable && vDist2DSq(pBot->Edict->v.origin, MoveEnd) < sqrf(GetPlayerRadius(pBot->Edict) * 2.0f));
|
||||
|
@ -2448,11 +2448,11 @@ bool HasBotCompletedLadderMove(const AvHAIPlayer* pBot, Vector MoveStart, Vector
|
|||
{
|
||||
if (pBot->BotNavInfo.IsOnGround)
|
||||
{
|
||||
if (UTIL_PointIsDirectlyReachable(pBot->CollisionHullBottomLocation, NextMoveDestination)) { return true; }
|
||||
if (UTIL_PointIsDirectlyReachable(pBot->CollisionHullBottomLocation, NextMoveDestination, GetPlayerRadius(pBot->Edict))) { return true; }
|
||||
}
|
||||
else
|
||||
{
|
||||
if (vDist2DSq(pBot->Edict->v.origin, MoveEnd) < sqrf(GetPlayerRadius(pBot->Edict)) && UTIL_PointIsDirectlyReachable(pBot->CurrentFloorPosition, NextMoveDestination)) { return true; }
|
||||
if (vDist2DSq(pBot->Edict->v.origin, MoveEnd) < sqrf(GetPlayerRadius(pBot->Edict)) && UTIL_PointIsDirectlyReachable(pBot->CurrentFloorPosition, NextMoveDestination, GetPlayerRadius(pBot->Edict))) { return true; }
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -2628,7 +2628,7 @@ void CheckAndHandleDoorObstruction(AvHAIPlayer* pBot)
|
|||
}
|
||||
|
||||
// If we're blocked by a door that's open, and its wait time isn't infinite (i.e. it will close shortly) then just wait it out
|
||||
if (BlockingDoor->m_toggle_state == TS_AT_TOP && BlockingDoor->m_flWait >= 0.0f)
|
||||
if (BlockingDoor->m_toggle_state == TS_AT_TOP && BlockingDoor->m_flWait > 0.0f)
|
||||
{
|
||||
// Wait for the door to start closing
|
||||
if (vDist2DSq(pBot->Edict->v.origin, NearestPoint) < sqrf(UTIL_MetresToGoldSrcUnits(1.5f)))
|
||||
|
@ -5049,7 +5049,8 @@ void MoveDirectlyTo(AvHAIPlayer* pBot, const Vector Destination)
|
|||
|
||||
if (vIsZero(Destination)) { return; }
|
||||
|
||||
Vector CurrentPos = (pBot->BotNavInfo.IsOnGround) ? pBot->Edict->v.origin : pBot->CurrentFloorPosition;
|
||||
Vector CurrentPos = (pBot->BotNavInfo.IsOnGround) ? pBot->Edict->v.origin : pBot->CurrentFloorPosition + GetPlayerOriginOffsetFromFloor(pBot->Edict, false);
|
||||
CurrentPos.z += 18.0f;
|
||||
|
||||
const Vector vForward = UTIL_GetVectorNormal2D(Destination - CurrentPos);
|
||||
// Same goes for the right vector, might not be the same as the bot's right
|
||||
|
@ -5059,11 +5060,18 @@ void MoveDirectlyTo(AvHAIPlayer* pBot, const Vector Destination)
|
|||
|
||||
Vector stTrcLft = CurrentPos - (vRight * PlayerRadius);
|
||||
Vector stTrcRt = CurrentPos + (vRight * PlayerRadius);
|
||||
Vector endTrcLft = stTrcLft + (vForward * 24.0f);
|
||||
Vector endTrcRt = stTrcRt + (vForward * 24.0f);
|
||||
Vector endTrcLft = stTrcLft + (vForward * (PlayerRadius * 1.5f));
|
||||
Vector endTrcRt = stTrcRt + (vForward * (PlayerRadius * 1.5f));
|
||||
|
||||
const bool bumpLeft = !UTIL_PointIsDirectlyReachable(pBot->BotNavInfo.NavProfile, stTrcLft, endTrcLft);
|
||||
const bool bumpRight = !UTIL_PointIsDirectlyReachable(pBot->BotNavInfo.NavProfile, stTrcRt, endTrcRt);
|
||||
TraceResult hit;
|
||||
|
||||
UTIL_TraceHull(stTrcLft, endTrcLft, ignore_monsters, head_hull, pBot->Edict->v.pContainingEntity, &hit);
|
||||
|
||||
const bool bumpLeft = (hit.flFraction < 1.0f || hit.fAllSolid > 0 || hit.fStartSolid > 0);
|
||||
|
||||
UTIL_TraceHull(stTrcRt, endTrcRt, ignore_monsters, head_hull, pBot->Edict->v.pContainingEntity, &hit);
|
||||
|
||||
const bool bumpRight = (hit.flFraction < 1.0f || hit.fAllSolid > 0 || hit.fStartSolid > 0);
|
||||
|
||||
pBot->desiredMovementDir = vForward;
|
||||
|
||||
|
@ -5077,19 +5085,89 @@ void MoveDirectlyTo(AvHAIPlayer* pBot, const Vector Destination)
|
|||
}
|
||||
else if (bumpLeft && bumpRight)
|
||||
{
|
||||
stTrcLft.z = pBot->Edict->v.origin.z;
|
||||
stTrcRt.z = pBot->Edict->v.origin.z;
|
||||
endTrcLft.z = pBot->Edict->v.origin.z;
|
||||
endTrcRt.z = pBot->Edict->v.origin.z;
|
||||
float MaxScaleHeight = CanPlayerClimb(pBot->Edict) ? 200.0f : GetPlayerMaxJumpHeight(pBot->Edict);
|
||||
if (pBot->Edict->v.iuser3 == AVH_USER3_ALIEN_PLAYER2) { MaxScaleHeight = 44.0f; }
|
||||
|
||||
if (!UTIL_QuickTrace(pBot->Edict, stTrcLft, endTrcLft))
|
||||
float JumpHeight = 0.0f;
|
||||
|
||||
bool bFoundJumpHeight = false;
|
||||
|
||||
Vector StartTrace = pBot->CurrentFloorPosition;
|
||||
Vector EndTrace = StartTrace + (vForward * 50.0f);
|
||||
EndTrace.z = StartTrace.z;
|
||||
|
||||
TraceResult JumpTestHit;
|
||||
|
||||
while (JumpHeight < MaxScaleHeight && !bFoundJumpHeight)
|
||||
{
|
||||
pBot->desiredMovementDir = pBot->desiredMovementDir + vRight;
|
||||
UTIL_TraceHull(StartTrace, EndTrace, ignore_monsters, head_hull, pBot->Edict->v.pContainingEntity, &JumpTestHit);
|
||||
|
||||
if (JumpTestHit.flFraction >= 1.0f && !JumpTestHit.fAllSolid)
|
||||
{
|
||||
bFoundJumpHeight = true;
|
||||
break;
|
||||
}
|
||||
|
||||
JumpHeight += 5.0f;
|
||||
|
||||
StartTrace.z += 5.0f;
|
||||
EndTrace.z += 5.0f;
|
||||
}
|
||||
|
||||
if (JumpHeight <= MaxScaleHeight)
|
||||
{
|
||||
if (JumpHeight <= GetPlayerMaxJumpHeight(pBot->Edict))
|
||||
{
|
||||
BotJump(pBot);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (pBot->Edict->v.iuser3)
|
||||
{
|
||||
case AVH_USER3_ALIEN_PLAYER3:
|
||||
{
|
||||
LerkFlightBehaviour FlightBehaviour = BotFlightClimbMove(pBot, pBot->CurrentFloorPosition, EndTrace, pBot->Edict->v.origin.z + JumpHeight);
|
||||
|
||||
if (FlightBehaviour == FLIGHT_GLIDE)
|
||||
{
|
||||
pBot->Button |= IN_JUMP;
|
||||
}
|
||||
else if (FlightBehaviour == FLIGHT_FLAP)
|
||||
{
|
||||
if (gpGlobals->time - pBot->BotNavInfo.LastFlapTime > 0.2f)
|
||||
{
|
||||
pBot->Button |= IN_JUMP;
|
||||
pBot->BotNavInfo.LastFlapTime = gpGlobals->time;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case AVH_USER3_ALIEN_PLAYER4:
|
||||
BlinkClimbMove(pBot, pBot->CurrentFloorPosition, EndTrace, pBot->Edict->v.origin.z + JumpHeight);
|
||||
break;
|
||||
default:
|
||||
WallClimbMove(pBot, pBot->CurrentFloorPosition, EndTrace, pBot->Edict->v.origin.z + JumpHeight);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pBot->desiredMovementDir = pBot->desiredMovementDir - vRight;
|
||||
stTrcLft.z = pBot->Edict->v.origin.z;
|
||||
stTrcRt.z = pBot->Edict->v.origin.z;
|
||||
endTrcLft.z = pBot->Edict->v.origin.z;
|
||||
endTrcRt.z = pBot->Edict->v.origin.z;
|
||||
|
||||
if (!UTIL_QuickTrace(pBot->Edict, stTrcLft, endTrcLft))
|
||||
{
|
||||
pBot->desiredMovementDir = pBot->desiredMovementDir + vRight;
|
||||
}
|
||||
else
|
||||
{
|
||||
pBot->desiredMovementDir = pBot->desiredMovementDir - vRight;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
float DistFromDestination = vDist2DSq(pBot->Edict->v.origin, Destination);
|
||||
|
@ -5114,7 +5192,7 @@ void MoveDirectlyTo(AvHAIPlayer* pBot, const Vector Destination)
|
|||
}
|
||||
|
||||
|
||||
bool UTIL_PointIsDirectlyReachable(const AvHAIPlayer* pBot, const Vector targetPoint)
|
||||
bool UTIL_PointIsDirectlyReachable(const AvHAIPlayer* pBot, const Vector targetPoint, const float MaxDist)
|
||||
{
|
||||
const dtNavMeshQuery* m_navQuery = UTIL_GetNavMeshQueryForProfile(pBot->BotNavInfo.NavProfile);
|
||||
const dtNavMesh* m_navMesh = UTIL_GetNavMeshForProfile(pBot->BotNavInfo.NavProfile);
|
||||
|
@ -5160,7 +5238,24 @@ bool UTIL_PointIsDirectlyReachable(const AvHAIPlayer* pBot, const Vector targetP
|
|||
|
||||
m_navQuery->raycast(StartPoly, StartNearest, EndNearest, m_navFilter, &hitDist, HitNormal, PolyPath, &pathCount, MAX_AI_PATH_SIZE);
|
||||
|
||||
if (hitDist < 1.0f) { return false; }
|
||||
if (hitDist < 1.0f)
|
||||
{
|
||||
if (pathCount == 0) { return false; }
|
||||
|
||||
float epos[3];
|
||||
dtVcopy(epos, EndNearest);
|
||||
|
||||
m_navQuery->closestPointOnPoly(PolyPath[pathCount - 1], EndNearest, epos, 0);
|
||||
|
||||
if (dtVdistSqr(EndNearest, epos) > sqrf(MaxDist))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (EndPoly == PolyPath[pathCount - 1]) { return true; }
|
||||
|
||||
|
@ -5174,7 +5269,7 @@ bool UTIL_PointIsDirectlyReachable(const AvHAIPlayer* pBot, const Vector targetP
|
|||
|
||||
}
|
||||
|
||||
bool UTIL_PointIsDirectlyReachable(const AvHAIPlayer* pBot, const Vector start, const Vector target)
|
||||
bool UTIL_PointIsDirectlyReachable(const AvHAIPlayer* pBot, const Vector start, const Vector target, const float MaxDist)
|
||||
{
|
||||
const dtNavMeshQuery* m_navQuery = UTIL_GetNavMeshQueryForProfile(pBot->BotNavInfo.NavProfile);
|
||||
const dtNavMesh* m_navMesh = UTIL_GetNavMeshForProfile(pBot->BotNavInfo.NavProfile);
|
||||
|
@ -5217,7 +5312,24 @@ bool UTIL_PointIsDirectlyReachable(const AvHAIPlayer* pBot, const Vector start,
|
|||
|
||||
m_navQuery->raycast(StartPoly, StartNearest, EndNearest, m_navFilter, &hitDist, HitNormal, PolyPath, &pathCount, MAX_AI_PATH_SIZE);
|
||||
|
||||
if (hitDist < 1.0f) { return false; }
|
||||
if (hitDist < 1.0f)
|
||||
{
|
||||
if (pathCount == 0) { return false; }
|
||||
|
||||
float epos[3];
|
||||
dtVcopy(epos, EndNearest);
|
||||
|
||||
m_navQuery->closestPointOnPoly(PolyPath[pathCount - 1], EndNearest, epos, 0);
|
||||
|
||||
if (dtVdistSqr(EndNearest, epos) > sqrf(MaxDist))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (EndPoly == PolyPath[pathCount - 1]) { return true; }
|
||||
|
||||
|
@ -5252,7 +5364,7 @@ const dtTileCache* UTIL_GetTileCacheForProfile(const nav_profile& NavProfile)
|
|||
return NavMeshes[NavProfile.NavMeshIndex].tileCache;
|
||||
}
|
||||
|
||||
bool UTIL_PointIsDirectlyReachable(const nav_profile &NavProfile, const Vector start, const Vector target)
|
||||
bool UTIL_PointIsDirectlyReachable(const nav_profile &NavProfile, const Vector start, const Vector target, const float MaxDist)
|
||||
{
|
||||
const dtNavMesh* m_navMesh = UTIL_GetNavMeshForProfile(NavProfile);
|
||||
const dtNavMeshQuery* m_navQuery = UTIL_GetNavMeshQueryForProfile(NavProfile);
|
||||
|
@ -5274,7 +5386,6 @@ bool UTIL_PointIsDirectlyReachable(const nav_profile &NavProfile, const Vector s
|
|||
dtPolyRef PolyPath[MAX_PATH_POLY];
|
||||
int pathCount = 0;
|
||||
|
||||
|
||||
dtStatus FoundStartPoly = m_navQuery->findNearestPoly(pStartPos, pReachableExtents, m_navFilter, &StartPoly, StartNearest);
|
||||
|
||||
if (!dtStatusSucceed(FoundStartPoly))
|
||||
|
@ -5303,7 +5414,7 @@ bool UTIL_PointIsDirectlyReachable(const nav_profile &NavProfile, const Vector s
|
|||
|
||||
m_navQuery->closestPointOnPoly(PolyPath[pathCount - 1], EndNearest, epos, 0);
|
||||
|
||||
if (dtVdistSqr(EndNearest, epos) > sqrf(max_ai_use_reach))
|
||||
if (dtVdistSqr(EndNearest, epos) > sqrf(MaxDist))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -5481,7 +5592,7 @@ void UTIL_TraceNavLine(const nav_profile &NavProfile, const Vector Start, const
|
|||
HitResult->TraceEndPoint = HitLocation;
|
||||
}
|
||||
|
||||
bool UTIL_PointIsDirectlyReachable(const Vector start, const Vector target)
|
||||
bool UTIL_PointIsDirectlyReachable(const Vector start, const Vector target, const float MaxDist)
|
||||
{
|
||||
const dtNavMeshQuery* m_navQuery = UTIL_GetNavMeshQueryForProfile(BaseNavProfiles[ALL_NAV_PROFILE]);
|
||||
const dtNavMesh* m_navMesh = UTIL_GetNavMeshForProfile(BaseNavProfiles[ALL_NAV_PROFILE]);
|
||||
|
@ -5532,7 +5643,7 @@ bool UTIL_PointIsDirectlyReachable(const Vector start, const Vector target)
|
|||
|
||||
m_navQuery->closestPointOnPoly(PolyPath[pathCount - 1], EndNearest, epos, 0);
|
||||
|
||||
if (dtVdistSqr(EndNearest, epos) > sqrf(max_ai_use_reach))
|
||||
if (dtVdistSqr(EndNearest, epos) > sqrf(MaxDist))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -7778,7 +7889,7 @@ float UTIL_FindZHeightForWallClimb(const Vector ClimbStart, const Vector ClimbEn
|
|||
testCount++;
|
||||
}
|
||||
|
||||
if (hit.flFraction >= 1.0f && !hit.fStartSolid)
|
||||
if (hit.flFraction >= 1.0f && !hit.fStartSolid && !hit.fAllSolid)
|
||||
{
|
||||
if (UTIL_QuickHullTrace(nullptr, EndTrace, EndTrace + Vector(0.0f, 0.0f, 8.0f), false))
|
||||
{
|
||||
|
@ -8216,7 +8327,10 @@ bool UTIL_IsTriggerLinkedToDoor(CBaseEntity* TriggerEntity, vector<CBaseEntity*>
|
|||
|
||||
if (ToggleRef && ToggleRef->pev->target)
|
||||
{
|
||||
CBaseEntity* TargetEntity = UTIL_FindEntityByTargetname(NULL, STRING(ToggleRef->pev->target));
|
||||
const char* TargetEntityName = STRING(ToggleRef->pev->target);
|
||||
CBaseEntity* TargetEntity = UTIL_FindEntityByTargetname(NULL, TargetEntityName);
|
||||
|
||||
if (!TargetEntity) { return false; }
|
||||
|
||||
const char* TestTriggerTargetname = STRING(TriggerEntity->pev->targetname);
|
||||
const char* ThisTriggerTarget = STRING(TargetEntity->pev->target);
|
||||
|
|
|
@ -253,6 +253,7 @@ void FallMove(AvHAIPlayer* pBot, const Vector StartPoint, const Vector EndPoint)
|
|||
void LadderMove(AvHAIPlayer* pBot, const Vector StartPoint, const Vector EndPoint, float RequiredClimbHeight, unsigned char NextArea);
|
||||
|
||||
// Called by NewMove, determines the movement direction and inputs required to climb a wall to reach endpoint
|
||||
LerkFlightBehaviour BotFlightClimbMove(AvHAIPlayer* pBot, Vector FromLocation, Vector ToLocation, float RequiredZ);
|
||||
void WallClimbMove(AvHAIPlayer* pBot, const Vector StartPoint, const Vector EndPoint, float RequiredClimbHeight);
|
||||
void BlinkClimbMove(AvHAIPlayer* pBot, const Vector StartPoint, const Vector EndPoint, float RequiredClimbHeight);
|
||||
// Called by NewMove, determines the movement direction and inputs required to use a phase gate to reach end point
|
||||
|
@ -395,10 +396,10 @@ float UTIL_PointIsDirectlyReachable_DEBUG(const Vector start, const Vector targe
|
|||
Determines if the bot can walk directly between the two points.
|
||||
Ignores map geometry, so will return true even if stairs are in the way, provided the bot can walk up/down them unobstructed
|
||||
*/
|
||||
bool UTIL_PointIsDirectlyReachable(const AvHAIPlayer* pBot, const Vector targetPoint);
|
||||
bool UTIL_PointIsDirectlyReachable(const AvHAIPlayer* pBot, const Vector start, const Vector target);
|
||||
bool UTIL_PointIsDirectlyReachable(const Vector start, const Vector target);
|
||||
bool UTIL_PointIsDirectlyReachable(const nav_profile& NavProfile, const Vector start, const Vector target);
|
||||
bool UTIL_PointIsDirectlyReachable(const AvHAIPlayer* pBot, const Vector targetPoint, const float MaxDist = max_ai_use_reach);
|
||||
bool UTIL_PointIsDirectlyReachable(const AvHAIPlayer* pBot, const Vector start, const Vector target, const float MaxDist = max_ai_use_reach);
|
||||
bool UTIL_PointIsDirectlyReachable(const Vector start, const Vector target, const float MaxDist = max_ai_use_reach);
|
||||
bool UTIL_PointIsDirectlyReachable(const nav_profile& NavProfile, const Vector start, const Vector target, const float MaxDist = max_ai_use_reach);
|
||||
|
||||
// Will trace along the nav mesh from start to target and return true if the trace reaches within MaxAcceptableDistance
|
||||
bool UTIL_TraceNav(const nav_profile& NavProfile, const Vector start, const Vector target, const float MaxAcceptableDistance);
|
||||
|
|
|
@ -1865,82 +1865,12 @@ void EndBotFrame(AvHAIPlayer* pBot)
|
|||
|
||||
void CustomThink(AvHAIPlayer* pBot)
|
||||
{
|
||||
// Test Combat Stuff
|
||||
//DEBUG_PrintCombatInfo(INDEXENT(1), pBot);
|
||||
AITASK_BotUpdateAndClearTasks(pBot);
|
||||
|
||||
pBot->CurrentEnemy = BotGetNextEnemyTarget(pBot);
|
||||
|
||||
if (pBot->CurrentEnemy > -1)
|
||||
if (pBot->PrimaryBotTask.TaskType != TASK_NONE && !vIsZero(pBot->PrimaryBotTask.TaskLocation))
|
||||
{
|
||||
if (IsPlayerMarine(pBot->Edict))
|
||||
{
|
||||
MarineCombatThink(pBot);
|
||||
}
|
||||
else
|
||||
{
|
||||
AlienCombatThink(pBot);
|
||||
}
|
||||
MoveDirectlyTo(pBot, pBot->PrimaryBotTask.TaskLocation);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (AITAC_ShouldBotBeCautious(pBot))
|
||||
{
|
||||
MoveTo(pBot, AITAC_GetTeamStartingLocation(AIMGR_GetEnemyTeam(pBot->Player->GetTeam())), MOVESTYLE_AMBUSH);
|
||||
}
|
||||
else
|
||||
{
|
||||
MoveTo(pBot, AITAC_GetTeamStartingLocation(AIMGR_GetEnemyTeam(pBot->Player->GetTeam())), MOVESTYLE_NORMAL);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*AITASK_BotUpdateAndClearTasks(pBot);
|
||||
|
||||
if (pBot->PrimaryBotTask.TaskType != TASK_SECURE_HIVE)
|
||||
{
|
||||
AvHTeamNumber BotTeam = pBot->Player->GetTeam();
|
||||
AvHTeamNumber EnemyTeam = AIMGR_GetEnemyTeam(BotTeam);
|
||||
|
||||
AvHAIHiveDefinition* HiveToClear = nullptr;
|
||||
float MinDist = 0.0f;
|
||||
|
||||
vector<AvHAIHiveDefinition*> Hives = AITAC_GetAllHives();
|
||||
|
||||
for (auto it = Hives.begin(); it != Hives.end(); it++)
|
||||
{
|
||||
AvHAIHiveDefinition* ThisHive = (*it);
|
||||
|
||||
if (ThisHive->Status == HIVE_STATUS_UNBUILT)
|
||||
{
|
||||
DeployableSearchFilter EnemyStuffFilter;
|
||||
EnemyStuffFilter.DeployableTeam = EnemyTeam;
|
||||
EnemyStuffFilter.DeployableTypes = SEARCH_ALL_STRUCTURES;
|
||||
EnemyStuffFilter.ReachabilityTeam = BotTeam;
|
||||
EnemyStuffFilter.ReachabilityFlags = pBot->BotNavInfo.NavProfile.ReachabilityFlag;
|
||||
EnemyStuffFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(15.0f);
|
||||
|
||||
if (AITAC_DeployableExistsAtLocation(ThisHive->FloorLocation, &EnemyStuffFilter))
|
||||
{
|
||||
float ThisDist = vDist2DSq(pBot->Edict->v.origin, ThisHive->FloorLocation);
|
||||
|
||||
if (!HiveToClear || ThisDist < MinDist)
|
||||
{
|
||||
HiveToClear = ThisHive;
|
||||
MinDist = ThisDist;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (HiveToClear)
|
||||
{
|
||||
AITASK_SetSecureHiveTask(pBot, &pBot->PrimaryBotTask, HiveToClear->HiveEdict, HiveToClear->FloorLocation, true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BotProgressTask(pBot, &pBot->PrimaryBotTask);
|
||||
}*/
|
||||
}
|
||||
|
||||
void DroneThink(AvHAIPlayer* pBot)
|
||||
|
@ -4463,6 +4393,21 @@ bool AIPlayerMustFinishCurrentTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
|
|||
|
||||
return (pBot->Player->GetResources() >= (BALANCE_VAR(kResourceTowerCost) * 0.65f));
|
||||
}
|
||||
|
||||
if (Task->TaskType == TASK_REINFORCE_STRUCTURE && vDist2DSq(pBot->Edict->v.origin, Task->TaskTarget->v.origin) < sqrf(UTIL_MetresToGoldSrcUnits(10.0f)))
|
||||
{
|
||||
float SearchRadius = (IsEdictHive(Task->TaskTarget)) ? UTIL_MetresToGoldSrcUnits(10.0f) : UTIL_MetresToGoldSrcUnits(5.0f);
|
||||
|
||||
DeployableSearchFilter UnfinishedStructures;
|
||||
UnfinishedStructures.DeployableTeam = BotTeam;
|
||||
UnfinishedStructures.DeployableTypes = SEARCH_ALL_STRUCTURES;
|
||||
UnfinishedStructures.ReachabilityTeam = BotTeam;
|
||||
UnfinishedStructures.ReachabilityFlags = pBot->BotNavInfo.NavProfile.ReachabilityFlag;
|
||||
UnfinishedStructures.MaxSearchRadius = SearchRadius;
|
||||
UnfinishedStructures.ExcludeStatusFlags = STRUCTURE_STATUS_COMPLETED;
|
||||
|
||||
return (AITAC_DeployableExistsAtLocation(Task->TaskTarget->v.origin, &UnfinishedStructures));
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -7639,7 +7584,7 @@ bool SkulkCombatThink(AvHAIPlayer* pBot)
|
|||
bot_path_node CurrentPathNode = pBot->BotNavInfo.CurrentPath[pBot->BotNavInfo.CurrentPathPoint];
|
||||
|
||||
// EVASIVE MANOEUVRES! Only do this if we're running along the floor and aren't approaching a path point (so we don't stray off the path)
|
||||
if (CurrentPathNode.flag == SAMPLE_POLYFLAGS_WALK && vDist2DSq(pBot->Edict->v.origin, CurrentPathNode.Location) > sqrf(50.0f))
|
||||
if (TrackedEnemyRef->bHasLOS && CurrentPathNode.flag == SAMPLE_POLYFLAGS_WALK && vDist2DSq(pBot->Edict->v.origin, CurrentPathNode.Location) > sqrf(50.0f))
|
||||
{
|
||||
Vector RightDir = UTIL_GetCrossProduct(pBot->desiredMovementDir, UP_VECTOR);
|
||||
|
||||
|
@ -7790,16 +7735,20 @@ bool GorgeCombatThink(AvHAIPlayer* pBot)
|
|||
Vector EnemyOrientation = UTIL_GetVectorNormal2D(pBot->desiredMovementDir);
|
||||
Vector RightDir = UTIL_GetCrossProduct(EnemyOrientation, UP_VECTOR);
|
||||
|
||||
pBot->desiredMovementDir = (pBot->BotNavInfo.bZig) ? UTIL_GetVectorNormal2D(pBot->desiredMovementDir + RightDir) : UTIL_GetVectorNormal2D(pBot->desiredMovementDir - RightDir);
|
||||
|
||||
// Let's get ziggy with it
|
||||
if (gpGlobals->time > pBot->BotNavInfo.NextZigTime)
|
||||
if (TrackedEnemyRef->bHasLOS)
|
||||
{
|
||||
pBot->BotNavInfo.bZig = !pBot->BotNavInfo.bZig;
|
||||
pBot->BotNavInfo.NextZigTime = gpGlobals->time + frandrange(0.5f, 1.0f);
|
||||
}
|
||||
|
||||
BotMovementInputs(pBot);
|
||||
pBot->desiredMovementDir = (pBot->BotNavInfo.bZig) ? UTIL_GetVectorNormal2D(pBot->desiredMovementDir + RightDir) : UTIL_GetVectorNormal2D(pBot->desiredMovementDir - RightDir);
|
||||
|
||||
// Let's get ziggy with it
|
||||
if (gpGlobals->time > pBot->BotNavInfo.NextZigTime)
|
||||
{
|
||||
pBot->BotNavInfo.bZig = !pBot->BotNavInfo.bZig;
|
||||
pBot->BotNavInfo.NextZigTime = gpGlobals->time + frandrange(0.5f, 1.0f);
|
||||
}
|
||||
|
||||
BotMovementInputs(pBot);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -7859,19 +7808,22 @@ bool GorgeCombatThink(AvHAIPlayer* pBot)
|
|||
|
||||
}
|
||||
|
||||
Vector EnemyOrientation = UTIL_GetVectorNormal2D(pBot->desiredMovementDir);
|
||||
Vector RightDir = UTIL_GetCrossProduct(EnemyOrientation, UP_VECTOR);
|
||||
|
||||
pBot->desiredMovementDir = (pBot->BotNavInfo.bZig) ? UTIL_GetVectorNormal2D(pBot->desiredMovementDir + RightDir) : UTIL_GetVectorNormal2D(pBot->desiredMovementDir - RightDir);
|
||||
|
||||
// Let's get ziggy with it
|
||||
if (gpGlobals->time > pBot->BotNavInfo.NextZigTime)
|
||||
if (TrackedEnemyRef->bHasLOS)
|
||||
{
|
||||
pBot->BotNavInfo.bZig = !pBot->BotNavInfo.bZig;
|
||||
pBot->BotNavInfo.NextZigTime = gpGlobals->time + frandrange(0.5f, 1.0f);
|
||||
}
|
||||
Vector EnemyOrientation = UTIL_GetVectorNormal2D(pBot->desiredMovementDir);
|
||||
Vector RightDir = UTIL_GetCrossProduct(EnemyOrientation, UP_VECTOR);
|
||||
|
||||
BotMovementInputs(pBot);
|
||||
pBot->desiredMovementDir = (pBot->BotNavInfo.bZig) ? UTIL_GetVectorNormal2D(pBot->desiredMovementDir + RightDir) : UTIL_GetVectorNormal2D(pBot->desiredMovementDir - RightDir);
|
||||
|
||||
// Let's get ziggy with it
|
||||
if (gpGlobals->time > pBot->BotNavInfo.NextZigTime)
|
||||
{
|
||||
pBot->BotNavInfo.bZig = !pBot->BotNavInfo.bZig;
|
||||
pBot->BotNavInfo.NextZigTime = gpGlobals->time + frandrange(0.5f, 1.0f);
|
||||
}
|
||||
|
||||
BotMovementInputs(pBot);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -7882,19 +7834,23 @@ bool GorgeCombatThink(AvHAIPlayer* pBot)
|
|||
BotShootTarget(pBot, WEAPON_GORGE_SPIT, CurrentEnemy);
|
||||
}
|
||||
|
||||
Vector EnemyOrientation = UTIL_GetVectorNormal2D(pBot->desiredMovementDir);
|
||||
Vector RightDir = UTIL_GetCrossProduct(EnemyOrientation, UP_VECTOR);
|
||||
|
||||
pBot->desiredMovementDir = (pBot->BotNavInfo.bZig) ? UTIL_GetVectorNormal2D(pBot->desiredMovementDir + RightDir) : UTIL_GetVectorNormal2D(pBot->desiredMovementDir - RightDir);
|
||||
|
||||
// Let's get ziggy with it
|
||||
if (gpGlobals->time > pBot->BotNavInfo.NextZigTime)
|
||||
if (TrackedEnemyRef->bHasLOS)
|
||||
{
|
||||
pBot->BotNavInfo.bZig = !pBot->BotNavInfo.bZig;
|
||||
pBot->BotNavInfo.NextZigTime = gpGlobals->time + frandrange(0.5f, 1.0f);
|
||||
}
|
||||
|
||||
BotMovementInputs(pBot);
|
||||
Vector EnemyOrientation = UTIL_GetVectorNormal2D(pBot->desiredMovementDir);
|
||||
Vector RightDir = UTIL_GetCrossProduct(EnemyOrientation, UP_VECTOR);
|
||||
|
||||
pBot->desiredMovementDir = (pBot->BotNavInfo.bZig) ? UTIL_GetVectorNormal2D(pBot->desiredMovementDir + RightDir) : UTIL_GetVectorNormal2D(pBot->desiredMovementDir - RightDir);
|
||||
|
||||
// Let's get ziggy with it
|
||||
if (gpGlobals->time > pBot->BotNavInfo.NextZigTime)
|
||||
{
|
||||
pBot->BotNavInfo.bZig = !pBot->BotNavInfo.bZig;
|
||||
pBot->BotNavInfo.NextZigTime = gpGlobals->time + frandrange(0.5f, 1.0f);
|
||||
}
|
||||
|
||||
BotMovementInputs(pBot);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -246,6 +246,16 @@ float GetPlayerRadius(const edict_t* Player)
|
|||
}
|
||||
}
|
||||
|
||||
bool CanPlayerClimb(const edict_t* Player)
|
||||
{
|
||||
return IsPlayerSkulk(Player) || IsPlayerFade(Player) || IsPlayerLerk(Player) || PlayerHasJetpack(Player);
|
||||
}
|
||||
|
||||
float GetPlayerMaxJumpHeight(const edict_t* Player)
|
||||
{
|
||||
return (CanPlayerCrouch(Player) ? max_player_crouchjump_height : max_player_normaljump_height);
|
||||
}
|
||||
|
||||
bool CanPlayerCrouch(const edict_t* Player)
|
||||
{
|
||||
if (FNullEnt(Player) || Player->free || !IsEdictPlayer(Player)) { return false; }
|
||||
|
@ -610,7 +620,7 @@ bool PlayerHasHeavyArmour(const edict_t* Player)
|
|||
return (Player->v.iuser4 & MASK_UPGRADE_13);
|
||||
}
|
||||
|
||||
bool PlayerHasJetpack(edict_t* Player)
|
||||
bool PlayerHasJetpack(const edict_t* Player)
|
||||
{
|
||||
if (!IsPlayerMarine(Player)) { return false; }
|
||||
return (Player->v.iuser4 & MASK_UPGRADE_7);
|
||||
|
|
|
@ -12,8 +12,11 @@ static const float max_player_use_reach = 55.0f;
|
|||
// Minimum time a bot can wait between attempts to use something in seconds (when not holding the use key down)
|
||||
static const float min_player_use_interval = 0.5f;
|
||||
|
||||
// Minimum time a bot can wait between attempts to use something in seconds (when not holding the use key down)
|
||||
static const float max_player_jump_height = 62.0f;
|
||||
// Max height reachable by crouch-jumping
|
||||
static const float max_player_normaljump_height = 44.0f;
|
||||
|
||||
// Max height reachable by crouch-jumping
|
||||
static const float max_player_crouchjump_height = 62.0f;
|
||||
|
||||
/****************
|
||||
|
||||
|
@ -95,6 +98,9 @@ int GetPlayerCombatLevel(const AvHPlayer* Player);
|
|||
float GetPlayerRadius(const AvHPlayer* Player);
|
||||
float GetPlayerRadius(const edict_t* Player);
|
||||
|
||||
bool CanPlayerClimb(const edict_t* Player);
|
||||
float GetPlayerMaxJumpHeight(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);
|
||||
|
||||
|
@ -137,7 +143,7 @@ bool IsPlayerInUseRange(const edict_t* Player, const edict_t* Target);
|
|||
|
||||
bool PlayerHasHeavyArmour(const edict_t* Player);
|
||||
|
||||
bool PlayerHasJetpack(edict_t* Player);
|
||||
bool PlayerHasJetpack(const edict_t* Player);
|
||||
|
||||
bool PlayerHasWeapon(const AvHPlayer* Player, const AvHAIWeapon DesiredCombatWeapon);
|
||||
bool PlayerHasEquipment(edict_t* Player);
|
||||
|
|
|
@ -2413,24 +2413,26 @@ AvHAIBuildableStructure* AITAC_UpdateBuildableStructure(CBaseEntity* Structure)
|
|||
|
||||
std::unordered_map<int, AvHAIBuildableStructure>& BuildingMap = ((AvHTeamNumber)BuildingEdict->v.team == TeamANumber) ? TeamAStructureMap : TeamBStructureMap;
|
||||
|
||||
AvHAIBuildableStructure* StructureRef = &BuildingMap[EntIndex];
|
||||
|
||||
if (StructureType == STRUCTURE_MARINE_DEPLOYEDMINE)
|
||||
{
|
||||
BuildingMap[EntIndex].StructureType = StructureType;
|
||||
if (BuildingMap[EntIndex].LastSeen == 0)
|
||||
StructureRef->StructureType = StructureType;
|
||||
if (StructureRef->LastSeen == 0)
|
||||
{
|
||||
BuildingMap[EntIndex].Location = BuildingEdict->v.origin;
|
||||
BuildingMap[EntIndex].edict = BuildingEdict;
|
||||
BuildingMap[EntIndex].healthPercent = 1.0f;
|
||||
BuildingMap[EntIndex].EntityRef = nullptr;
|
||||
BuildingMap[EntIndex].StructureStatusFlags = STRUCTURE_STATUS_COMPLETED;
|
||||
BuildingMap[EntIndex].TeamAReachabilityFlags = (AI_REACHABILITY_ALL & ~(AI_REACHABILITY_UNREACHABLE));
|
||||
BuildingMap[EntIndex].TeamBReachabilityFlags = (AI_REACHABILITY_ALL & ~(AI_REACHABILITY_UNREACHABLE));
|
||||
StructureRef->Location = BuildingEdict->v.origin;
|
||||
StructureRef->edict = BuildingEdict;
|
||||
StructureRef->healthPercent = 1.0f;
|
||||
StructureRef->EntityRef = nullptr;
|
||||
StructureRef->StructureStatusFlags = STRUCTURE_STATUS_COMPLETED;
|
||||
StructureRef->TeamAReachabilityFlags = (AI_REACHABILITY_ALL & ~(AI_REACHABILITY_UNREACHABLE));
|
||||
StructureRef->TeamBReachabilityFlags = (AI_REACHABILITY_ALL & ~(AI_REACHABILITY_UNREACHABLE));
|
||||
AITAC_OnStructureCreated(&BuildingMap[EntIndex]);
|
||||
}
|
||||
|
||||
BuildingMap[EntIndex].LastSeen = StructureRefreshFrame;
|
||||
StructureRef->LastSeen = StructureRefreshFrame;
|
||||
|
||||
return &BuildingMap[EntIndex];
|
||||
return StructureRef;
|
||||
}
|
||||
|
||||
AvHBaseBuildable* BaseBuildable = dynamic_cast<AvHBaseBuildable*>(Structure);
|
||||
|
@ -2440,27 +2442,27 @@ AvHAIBuildableStructure* AITAC_UpdateBuildableStructure(CBaseEntity* Structure)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
BuildingMap[EntIndex].StructureType = StructureType;
|
||||
StructureRef->StructureType = StructureType;
|
||||
|
||||
// This is the first time we've seen this structure, so it must be new
|
||||
if (BuildingMap[EntIndex].LastSeen == 0)
|
||||
if (StructureRef->LastSeen == 0)
|
||||
{
|
||||
BuildingMap[EntIndex].EntityRef = BaseBuildable;
|
||||
BuildingMap[EntIndex].edict = BuildingEdict;
|
||||
StructureRef->EntityRef = BaseBuildable;
|
||||
StructureRef->edict = BuildingEdict;
|
||||
|
||||
BuildingMap[EntIndex].OffMeshConnections.clear();
|
||||
BuildingMap[EntIndex].Obstacles.clear();
|
||||
StructureRef->OffMeshConnections.clear();
|
||||
StructureRef->Obstacles.clear();
|
||||
|
||||
BuildingMap[EntIndex].Location = g_vecZero; // We set this just below after calculating reachability
|
||||
StructureRef->Location = g_vecZero; // We set this just below after calculating reachability
|
||||
|
||||
AITAC_OnStructureCreated(&BuildingMap[EntIndex]);
|
||||
}
|
||||
|
||||
if (vIsZero(BuildingMap[EntIndex].Location) || !vEquals(BaseBuildable->pev->origin, BuildingMap[EntIndex].Location, 5.0f))
|
||||
if (vIsZero(StructureRef->Location) || !vEquals(BaseBuildable->pev->origin, StructureRef->Location, 5.0f))
|
||||
{
|
||||
AITAC_RefreshReachabilityForStructure(&BuildingMap[EntIndex]);
|
||||
|
||||
BuildingMap[EntIndex].Location = BaseBuildable->pev->origin;
|
||||
StructureRef->Location = BaseBuildable->pev->origin;
|
||||
}
|
||||
|
||||
unsigned int NewFlags = STRUCTURE_STATUS_NONE;
|
||||
|
@ -2471,7 +2473,7 @@ AvHAIBuildableStructure* AITAC_UpdateBuildableStructure(CBaseEntity* Structure)
|
|||
|
||||
if (BaseBuildable->GetIsBuilt())
|
||||
{
|
||||
if (!(BuildingMap[EntIndex].StructureStatusFlags & STRUCTURE_STATUS_COMPLETED))
|
||||
if (!(StructureRef->StructureStatusFlags & STRUCTURE_STATUS_COMPLETED))
|
||||
{
|
||||
bJustCompleted = true;
|
||||
}
|
||||
|
@ -2490,7 +2492,7 @@ AvHAIBuildableStructure* AITAC_UpdateBuildableStructure(CBaseEntity* Structure)
|
|||
|
||||
if (BaseBuildable->GetIsRecycling())
|
||||
{
|
||||
if (!(BuildingMap[EntIndex].StructureStatusFlags & STRUCTURE_STATUS_RECYCLING))
|
||||
if (!(StructureRef->StructureStatusFlags & STRUCTURE_STATUS_RECYCLING))
|
||||
{
|
||||
bJustRecycled = true;
|
||||
}
|
||||
|
@ -2514,25 +2516,25 @@ AvHAIBuildableStructure* AITAC_UpdateBuildableStructure(CBaseEntity* Structure)
|
|||
|
||||
float NewHealthPercent = (BuildingEdict->v.health / BuildingEdict->v.max_health);
|
||||
|
||||
if (NewHealthPercent < BuildingMap[EntIndex].healthPercent)
|
||||
if (NewHealthPercent < StructureRef->healthPercent)
|
||||
{
|
||||
BuildingMap[EntIndex].lastDamagedTime = gpGlobals->time;
|
||||
StructureRef->lastDamagedTime = gpGlobals->time;
|
||||
}
|
||||
|
||||
BuildingMap[EntIndex].healthPercent = NewHealthPercent;
|
||||
StructureRef->healthPercent = NewHealthPercent;
|
||||
|
||||
if (BuildingMap[EntIndex].healthPercent < 0.99f && BaseBuildable->GetIsBuilt())
|
||||
if (StructureRef->healthPercent < 0.99f && BaseBuildable->GetIsBuilt())
|
||||
{
|
||||
NewFlags |= STRUCTURE_STATUS_DAMAGED;
|
||||
}
|
||||
|
||||
if (gpGlobals->time - BuildingMap[EntIndex].lastDamagedTime < 10.0f)
|
||||
if (gpGlobals->time - StructureRef->lastDamagedTime < 10.0f)
|
||||
{
|
||||
NewFlags |= STRUCTURE_STATUS_UNDERATTACK;
|
||||
}
|
||||
|
||||
BuildingMap[EntIndex].StructureStatusFlags = NewFlags;
|
||||
BuildingMap[EntIndex].LastSeen = StructureRefreshFrame;
|
||||
StructureRef->StructureStatusFlags = NewFlags;
|
||||
StructureRef->LastSeen = StructureRefreshFrame;
|
||||
|
||||
if (bJustCompleted)
|
||||
{
|
||||
|
@ -2544,7 +2546,76 @@ AvHAIBuildableStructure* AITAC_UpdateBuildableStructure(CBaseEntity* Structure)
|
|||
AITAC_OnStructureBeginRecycling(&BuildingMap[EntIndex]);
|
||||
}
|
||||
|
||||
return &BuildingMap[EntIndex];
|
||||
if (StructureRef->Purpose == STRUCTURE_PURPOSE_NONE)
|
||||
{
|
||||
AvHTeamNumber StructureTeam = (AvHTeamNumber)StructureRef->edict->v.team;
|
||||
|
||||
if (AIMGR_GetTeamType(StructureTeam) == AVH_CLASS_TYPE_MARINE)
|
||||
{
|
||||
switch (StructureRef->StructureType)
|
||||
{
|
||||
case STRUCTURE_MARINE_COMMCHAIR:
|
||||
case STRUCTURE_MARINE_INFANTRYPORTAL:
|
||||
case STRUCTURE_MARINE_ARMSLAB:
|
||||
case STRUCTURE_MARINE_PROTOTYPELAB:
|
||||
StructureRef->Purpose = STRUCTURE_PURPOSE_BASE;
|
||||
break;
|
||||
case STRUCTURE_MARINE_RESTOWER:
|
||||
StructureRef->Purpose = STRUCTURE_PURPOSE_GENERAL;
|
||||
break;
|
||||
case STRUCTURE_MARINE_TURRET:
|
||||
StructureRef->Purpose = STRUCTURE_PURPOSE_FORTIFY;
|
||||
break;
|
||||
case STRUCTURE_MARINE_SIEGETURRET:
|
||||
StructureRef->Purpose = STRUCTURE_PURPOSE_SIEGE;
|
||||
break;
|
||||
default:
|
||||
{
|
||||
Vector TeamStart = AITAC_GetTeamStartingLocation(StructureTeam);
|
||||
|
||||
if (vDist2DSq(StructureRef->Location, TeamStart) < sqrf(UTIL_MetresToGoldSrcUnits(15.0f)))
|
||||
{
|
||||
StructureRef->Purpose = STRUCTURE_PURPOSE_BASE;
|
||||
}
|
||||
else
|
||||
{
|
||||
AvHTeamNumber EnemyTeam = AIMGR_GetEnemyTeam(StructureTeam);
|
||||
|
||||
const AvHAIHiveDefinition* NearestHive = AITAC_GetHiveNearestLocation(StructureRef->Location);
|
||||
|
||||
if (NearestHive)
|
||||
{
|
||||
if (NearestHive->Status == HIVE_STATUS_UNBUILT && vDist2DSq(NearestHive->FloorLocation, StructureRef->Location) < sqrf(UTIL_MetresToGoldSrcUnits(10.0f)))
|
||||
{
|
||||
StructureRef->Purpose = STRUCTURE_PURPOSE_FORTIFY;
|
||||
}
|
||||
else if (NearestHive->Status != HIVE_STATUS_UNBUILT && vDist2DSq(NearestHive->FloorLocation, StructureRef->Location) < sqrf(UTIL_MetresToGoldSrcUnits(25.0f)))
|
||||
{
|
||||
StructureRef->Purpose = STRUCTURE_PURPOSE_SIEGE;
|
||||
}
|
||||
else
|
||||
{
|
||||
StructureRef->Purpose = STRUCTURE_PURPOSE_GENERAL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
StructureRef->Purpose = STRUCTURE_PURPOSE_GENERAL;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
StructureRef->Purpose = STRUCTURE_PURPOSE_GENERAL;
|
||||
}
|
||||
}
|
||||
|
||||
return StructureRef;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -877,7 +877,7 @@ bool AITASK_IsReinforceStructureTaskStillValid(AvHAIPlayer* pBot, AvHAIPlayerTas
|
|||
|
||||
DeployableSearchFilter StructureFilter;
|
||||
StructureFilter.DeployableTypes = STRUCTURE_ALIEN_OFFENCECHAMBER | ALIEN_BUILD_DEFENSE_CHAMBER | ALIEN_BUILD_MOVEMENT_CHAMBER | ALIEN_BUILD_SENSORY_CHAMBER;
|
||||
StructureFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(5.0f);
|
||||
StructureFilter.MaxSearchRadius = (IsEdictHive(Task->TaskTarget)) ? UTIL_MetresToGoldSrcUnits(10.0f) : UTIL_MetresToGoldSrcUnits(5.0f);
|
||||
StructureFilter.DeployableTeam = pBot->Player->GetTeam();
|
||||
|
||||
vector<AvHAIBuildableStructure> AllNearbyStructures = AITAC_FindAllDeployables(Task->TaskTarget->v.origin, &StructureFilter);
|
||||
|
@ -1339,7 +1339,7 @@ void BotProgressReinforceStructureTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
|
|||
Vector ReinforceLocation = UTIL_ProjectPointToNavmesh(UTIL_GetEntityGroundLocation(Task->TaskTarget), pBot->BotNavInfo.NavProfile);
|
||||
float SearchRadius = UTIL_MetresToGoldSrcUnits(5.0f);
|
||||
|
||||
if (Task->StructureType == STRUCTURE_ALIEN_HIVE)
|
||||
if (IsEdictHive(Task->TaskTarget))
|
||||
{
|
||||
AvHAIHiveDefinition* HiveToReinforce = AITAC_GetHiveFromEdict(Task->TaskTarget);
|
||||
|
||||
|
@ -2834,6 +2834,12 @@ void MarineProgressSecureHiveTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
|
|||
return;
|
||||
}
|
||||
|
||||
if (Hive->Status != HIVE_STATUS_UNBUILT && Hive->OwningTeam != BotTeam)
|
||||
{
|
||||
BotAttackNonPlayerTarget(pBot, Hive->HiveEdict);
|
||||
return;
|
||||
}
|
||||
|
||||
const AvHAIResourceNode* ResNode = Hive->HiveResNodeRef;
|
||||
|
||||
if (ResNode && ResNode->bIsOccupied)
|
||||
|
@ -2877,6 +2883,7 @@ void MarineProgressSecureHiveTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
BotGuardLocation(pBot, Task->TaskLocation);
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue