mirror of
https://github.com/ENSL/NS.git
synced 2024-11-21 20:21:14 +00:00
Further bot improvements
* Player-requested structures are properly integrated into the base system to prevent duplicates and better anticipate player desires * Improved bot path finding for moving targets, hopefully they get caught less often on railings and stuff when pursuing a moving target * When bots teleport (e.g. phase gate, but any kind of teleport), they clear their stored unstuck locations so they don't try and backtrack when attempting to get unstuck
This commit is contained in:
parent
11512d9d28
commit
4102dabe05
4 changed files with 205 additions and 36 deletions
|
@ -3143,6 +3143,88 @@ bool AICOMM_CheckForNextSupportAction(AvHAIPlayer* pBot)
|
||||||
Vector IdealDeployLocation = Requestor->v.origin + (UTIL_GetForwardVector2D(Requestor->v.angles) * ProjectDistance);
|
Vector IdealDeployLocation = Requestor->v.origin + (UTIL_GetForwardVector2D(Requestor->v.angles) * ProjectDistance);
|
||||||
Vector ProjectedDeployLocation = AdjustPointForPathfinding(IdealDeployLocation, GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE));
|
Vector ProjectedDeployLocation = AdjustPointForPathfinding(IdealDeployLocation, GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE));
|
||||||
|
|
||||||
|
AvHAIMarineBase* BaseToDeployIn = nullptr;
|
||||||
|
float MinDist = 0.0f;
|
||||||
|
|
||||||
|
for (auto it = pBot->Bases.begin(); it != pBot->Bases.end(); it++)
|
||||||
|
{
|
||||||
|
float DistFromBase = vDist2DSq(Requestor->v.origin, it->BaseLocation);
|
||||||
|
|
||||||
|
if (it->BaseType == MARINE_BASE_MAINBASE && DistFromBase < sqrf(UTIL_MetresToGoldSrcUnits(20.0f)))
|
||||||
|
{
|
||||||
|
BaseToDeployIn = &(*it);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
float DesiredDist = (it->BaseType == MARINE_BASE_GUARDPOST) ? BALANCE_VAR(kTurretFactoryBuildDistance) : UTIL_MetresToGoldSrcUnits(15.0f);
|
||||||
|
|
||||||
|
if (DistFromBase < sqrf(DesiredDist))
|
||||||
|
{
|
||||||
|
if (!BaseToDeployIn || DistFromBase < MinDist)
|
||||||
|
{
|
||||||
|
BaseToDeployIn = &(*it);
|
||||||
|
MinDist = DistFromBase;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We've requested a building away from any existing bases the commander is building
|
||||||
|
if (!BaseToDeployIn && (NextRequest->RequestType == BUILD_PHASEGATE || NextRequest->RequestType == BUILD_TURRET_FACTORY))
|
||||||
|
{
|
||||||
|
|
||||||
|
const AvHAIHiveDefinition* NearestHive = AITAC_GetHiveNearestLocation(Requestor->v.origin);
|
||||||
|
float DesiredDistance = (NearestHive->Status != HIVE_STATUS_UNBUILT) ? sqrf(BALANCE_VAR(kSiegeTurretRange)) : sqrf(UTIL_MetresToGoldSrcUnits(10.0f));
|
||||||
|
float DistFromHive = vDist2DSq(NearestHive->Location, Requestor->v.origin);
|
||||||
|
|
||||||
|
if (NearestHive && DistFromHive < DesiredDistance)
|
||||||
|
{
|
||||||
|
AvHAIMarineBase* ExistingBase = nullptr;
|
||||||
|
|
||||||
|
for (auto it = pBot->Bases.begin(); it != pBot->Bases.end(); it++)
|
||||||
|
{
|
||||||
|
if (!it->bIsActive || !it->bRecycleBase) { continue; }
|
||||||
|
|
||||||
|
if (NearestHive->Status != HIVE_STATUS_UNBUILT)
|
||||||
|
{
|
||||||
|
if (it->BaseType == MARINE_BASE_SIEGE && vEquals2D(it->SiegeTarget, NearestHive->Location))
|
||||||
|
{
|
||||||
|
if (!it->bBaseInitialised)
|
||||||
|
{
|
||||||
|
BaseToDeployIn = &(*it);
|
||||||
|
BaseToDeployIn->BaseLocation = Requestor->v.origin;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (it->BaseType == MARINE_BASE_OUTPOST && vDist2DSq(it->BaseLocation, NearestHive->FloorLocation) < UTIL_MetresToGoldSrcUnits(15.0f))
|
||||||
|
{
|
||||||
|
if (!it->bBaseInitialised)
|
||||||
|
{
|
||||||
|
BaseToDeployIn = &(*it);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!BaseToDeployIn && NearestHive)
|
||||||
|
{
|
||||||
|
MarineBaseType NewBaseType = (NearestHive->Status != HIVE_STATUS_UNBUILT) ? MARINE_BASE_SIEGE : MARINE_BASE_OUTPOST;
|
||||||
|
|
||||||
|
BaseToDeployIn = AICOMM_AddNewBase(pBot, Requestor->v.origin, NewBaseType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BaseToDeployIn = AICOMM_AddNewBase(pBot, Requestor->v.origin, MARINE_BASE_GUARDPOST);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if (!vIsZero(ProjectedDeployLocation))
|
if (!vIsZero(ProjectedDeployLocation))
|
||||||
{
|
{
|
||||||
if (NextRequest->RequestType == BUILD_INFANTRYPORTAL)
|
if (NextRequest->RequestType == BUILD_INFANTRYPORTAL)
|
||||||
|
@ -3195,9 +3277,20 @@ bool AICOMM_CheckForNextSupportAction(AvHAIPlayer* pBot)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AvHAIBuildableStructure* DeployedStructure = AICOMM_DeployStructure(pBot, StructureToDeploy, ProjectedDeployLocation, STRUCTURE_PURPOSE_GENERAL, true);
|
bool bSuccess = false;
|
||||||
|
|
||||||
if (DeployedStructure)
|
if (BaseToDeployIn)
|
||||||
|
{
|
||||||
|
bSuccess = AICOMM_AddStructureToBase(pBot, StructureToDeploy, ProjectedDeployLocation, BaseToDeployIn);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AvHAIBuildableStructure* DeployedStructure = AICOMM_DeployStructure(pBot, StructureToDeploy, ProjectedDeployLocation, STRUCTURE_PURPOSE_GENERAL, true);
|
||||||
|
|
||||||
|
bSuccess = DeployedStructure != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bSuccess)
|
||||||
{
|
{
|
||||||
NextRequest->bResponded = true;
|
NextRequest->bResponded = true;
|
||||||
return true;
|
return true;
|
||||||
|
@ -3208,9 +3301,21 @@ bool AICOMM_CheckForNextSupportAction(AvHAIPlayer* pBot)
|
||||||
|
|
||||||
if (!vIsZero(DeployLocation))
|
if (!vIsZero(DeployLocation))
|
||||||
{
|
{
|
||||||
AvHAIBuildableStructure* DeployedStructure = AICOMM_DeployStructure(pBot, StructureToDeploy, DeployLocation, STRUCTURE_PURPOSE_GENERAL);
|
bool bSuccess = false;
|
||||||
|
|
||||||
if (DeployedStructure)
|
if (BaseToDeployIn)
|
||||||
|
{
|
||||||
|
bSuccess = AICOMM_AddStructureToBase(pBot, StructureToDeploy, DeployLocation, BaseToDeployIn);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AvHAIBuildableStructure* DeployedStructure = AICOMM_DeployStructure(pBot, StructureToDeploy, DeployLocation, STRUCTURE_PURPOSE_GENERAL, true);
|
||||||
|
|
||||||
|
bSuccess = DeployedStructure != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (bSuccess)
|
||||||
{
|
{
|
||||||
NextRequest->bResponded = true;
|
NextRequest->bResponded = true;
|
||||||
return true;
|
return true;
|
||||||
|
@ -3221,9 +3326,21 @@ bool AICOMM_CheckForNextSupportAction(AvHAIPlayer* pBot)
|
||||||
|
|
||||||
if (!vIsZero(DeployLocation))
|
if (!vIsZero(DeployLocation))
|
||||||
{
|
{
|
||||||
AvHAIBuildableStructure* DeployedStructure = AICOMM_DeployStructure(pBot, StructureToDeploy, DeployLocation, STRUCTURE_PURPOSE_GENERAL);
|
bool bSuccess = false;
|
||||||
|
|
||||||
if (DeployedStructure)
|
if (BaseToDeployIn)
|
||||||
|
{
|
||||||
|
bSuccess = AICOMM_AddStructureToBase(pBot, StructureToDeploy, DeployLocation, BaseToDeployIn);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AvHAIBuildableStructure* DeployedStructure = AICOMM_DeployStructure(pBot, StructureToDeploy, DeployLocation, STRUCTURE_PURPOSE_GENERAL, true);
|
||||||
|
|
||||||
|
bSuccess = DeployedStructure != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (bSuccess)
|
||||||
{
|
{
|
||||||
NextRequest->bResponded = true;
|
NextRequest->bResponded = true;
|
||||||
return true;
|
return true;
|
||||||
|
@ -3744,6 +3861,8 @@ void AICOMM_UpdateGuardpostStatus(AvHAIPlayer* pBot, AvHAIMarineBase* Base)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Base->bRecycleBase = false;
|
||||||
|
Base->bIsActive = true;
|
||||||
|
|
||||||
// Check how far we are into building this outpost. If we have a TF and at least 3 sentries then we can consider it "established"
|
// Check how far we are into building this outpost. If we have a TF and at least 3 sentries then we can consider it "established"
|
||||||
// even if it isn't finished yet
|
// even if it isn't finished yet
|
||||||
|
@ -4040,7 +4159,11 @@ void AICOMM_DeployBases(AvHAIPlayer* pBot)
|
||||||
|
|
||||||
if (!AITAC_DeployableExistsAtLocation(ThisHive->FloorLocation, &EnemyStuffFilter))
|
if (!AITAC_DeployableExistsAtLocation(ThisHive->FloorLocation, &EnemyStuffFilter))
|
||||||
{
|
{
|
||||||
AICOMM_AddNewBase(pBot, ThisHive->FloorLocation, MARINE_BASE_OUTPOST);
|
Vector ProjectedPoint = UTIL_ProjectPointToNavmesh(ThisHive->FloorLocation, Vector(500.0f, 500.0f, 500.0f), GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE));
|
||||||
|
if (!vIsZero(ProjectedPoint))
|
||||||
|
{
|
||||||
|
AICOMM_AddNewBase(pBot, ProjectedPoint, MARINE_BASE_OUTPOST);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4090,7 +4213,12 @@ void AICOMM_DeployBases(AvHAIPlayer* pBot)
|
||||||
|
|
||||||
if (!AITAC_DeployableExistsAtLocation(ThisPlayer->pev->origin, &EnemyStuffFilter))
|
if (!AITAC_DeployableExistsAtLocation(ThisPlayer->pev->origin, &EnemyStuffFilter))
|
||||||
{
|
{
|
||||||
AICOMM_AddNewBase(pBot, ThisPlayer->pev->origin, MARINE_BASE_SIEGE);
|
// Make sure that our siege guy is somewhere we can build
|
||||||
|
Vector ProjectedPoint = UTIL_ProjectPointToNavmesh(ThisPlayer->pev->origin, Vector(100.0f, 100.0f, 100.0f), GetBaseNavProfile(STRUCTURE_BASE_NAV_PROFILE));
|
||||||
|
if (!vIsZero(ProjectedPoint))
|
||||||
|
{
|
||||||
|
AICOMM_AddNewBase(pBot, ProjectedPoint, MARINE_BASE_SIEGE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4162,7 +4290,6 @@ bool AICOMM_GetRelocationMessage(Vector RelocationPoint, char* MessageBuffer)
|
||||||
sprintf(MessageBuffer, "Get ready to relocate");
|
sprintf(MessageBuffer, "Get ready to relocate");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int MsgIndex = irandrange(0, 2);
|
int MsgIndex = irandrange(0, 2);
|
||||||
|
|
||||||
|
@ -4829,6 +4956,8 @@ bool AICOMM_BuildOutBase(AvHAIPlayer* pBot, AvHAIMarineBase* BaseToBuildOut)
|
||||||
return AICOMM_BuildOutOutpost(pBot, BaseToBuildOut);
|
return AICOMM_BuildOutOutpost(pBot, BaseToBuildOut);
|
||||||
case MARINE_BASE_MAINBASE:
|
case MARINE_BASE_MAINBASE:
|
||||||
return AICOMM_BuildOutMainBase(pBot, BaseToBuildOut);
|
return AICOMM_BuildOutMainBase(pBot, BaseToBuildOut);
|
||||||
|
case MARINE_BASE_GUARDPOST:
|
||||||
|
return AICOMM_BuildOutGuardPost(pBot, BaseToBuildOut);
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1166,6 +1166,7 @@ void UTIL_PopulateBaseNavProfiles()
|
||||||
BaseNavProfiles[SKULK_BASE_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_STRUCTUREBLOCK, 20.0f);
|
BaseNavProfiles[SKULK_BASE_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_STRUCTUREBLOCK, 20.0f);
|
||||||
BaseNavProfiles[SKULK_BASE_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_LADDER, 1.5f);
|
BaseNavProfiles[SKULK_BASE_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_LADDER, 1.5f);
|
||||||
BaseNavProfiles[SKULK_BASE_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_WALLCLIMB, 1.0f);
|
BaseNavProfiles[SKULK_BASE_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_WALLCLIMB, 1.0f);
|
||||||
|
BaseNavProfiles[SKULK_BASE_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_FALLDAMAGE, 1.0f);
|
||||||
BaseNavProfiles[SKULK_BASE_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_LIFT, 3.0f);
|
BaseNavProfiles[SKULK_BASE_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_LIFT, 3.0f);
|
||||||
BaseNavProfiles[SKULK_BASE_NAV_PROFILE].Filters.setIncludeFlags(SAMPLE_POLYFLAGS_ALL);
|
BaseNavProfiles[SKULK_BASE_NAV_PROFILE].Filters.setIncludeFlags(SAMPLE_POLYFLAGS_ALL);
|
||||||
BaseNavProfiles[SKULK_BASE_NAV_PROFILE].Filters.setExcludeFlags(SAMPLE_POLYFLAGS_DISABLED);
|
BaseNavProfiles[SKULK_BASE_NAV_PROFILE].Filters.setExcludeFlags(SAMPLE_POLYFLAGS_DISABLED);
|
||||||
|
@ -1199,6 +1200,7 @@ void UTIL_PopulateBaseNavProfiles()
|
||||||
BaseNavProfiles[LERK_BASE_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_BLOCKED, 2.0f);
|
BaseNavProfiles[LERK_BASE_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_BLOCKED, 2.0f);
|
||||||
BaseNavProfiles[LERK_BASE_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_STRUCTUREBLOCK, 20.0f);
|
BaseNavProfiles[LERK_BASE_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_STRUCTUREBLOCK, 20.0f);
|
||||||
BaseNavProfiles[LERK_BASE_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_LADDER, 1.0f);
|
BaseNavProfiles[LERK_BASE_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_LADDER, 1.0f);
|
||||||
|
BaseNavProfiles[LERK_BASE_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_FALLDAMAGE, 1.0f);
|
||||||
BaseNavProfiles[LERK_BASE_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_LIFT, 3.0f);
|
BaseNavProfiles[LERK_BASE_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_LIFT, 3.0f);
|
||||||
BaseNavProfiles[LERK_BASE_NAV_PROFILE].Filters.setIncludeFlags(SAMPLE_POLYFLAGS_ALL);
|
BaseNavProfiles[LERK_BASE_NAV_PROFILE].Filters.setIncludeFlags(SAMPLE_POLYFLAGS_ALL);
|
||||||
BaseNavProfiles[LERK_BASE_NAV_PROFILE].Filters.setExcludeFlags(SAMPLE_POLYFLAGS_DISABLED);
|
BaseNavProfiles[LERK_BASE_NAV_PROFILE].Filters.setExcludeFlags(SAMPLE_POLYFLAGS_DISABLED);
|
||||||
|
@ -1215,6 +1217,7 @@ void UTIL_PopulateBaseNavProfiles()
|
||||||
BaseNavProfiles[FADE_BASE_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_BLOCKED, 2.0f);
|
BaseNavProfiles[FADE_BASE_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_BLOCKED, 2.0f);
|
||||||
BaseNavProfiles[FADE_BASE_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_STRUCTUREBLOCK, 20.0f);
|
BaseNavProfiles[FADE_BASE_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_STRUCTUREBLOCK, 20.0f);
|
||||||
BaseNavProfiles[FADE_BASE_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_LADDER, 1.5f);
|
BaseNavProfiles[FADE_BASE_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_LADDER, 1.5f);
|
||||||
|
BaseNavProfiles[FADE_BASE_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_FALLDAMAGE, 1.0f);
|
||||||
BaseNavProfiles[FADE_BASE_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_LIFT, 3.0f);
|
BaseNavProfiles[FADE_BASE_NAV_PROFILE].Filters.setAreaCost(SAMPLE_POLYAREA_LIFT, 3.0f);
|
||||||
BaseNavProfiles[FADE_BASE_NAV_PROFILE].Filters.setIncludeFlags(SAMPLE_POLYFLAGS_ALL);
|
BaseNavProfiles[FADE_BASE_NAV_PROFILE].Filters.setIncludeFlags(SAMPLE_POLYFLAGS_ALL);
|
||||||
BaseNavProfiles[FADE_BASE_NAV_PROFILE].Filters.setExcludeFlags(SAMPLE_POLYFLAGS_DISABLED);
|
BaseNavProfiles[FADE_BASE_NAV_PROFILE].Filters.setExcludeFlags(SAMPLE_POLYFLAGS_DISABLED);
|
||||||
|
@ -2085,17 +2088,48 @@ dtStatus FindPathClosestToPoint(AvHAIPlayer* pBot, const BotMoveStyle MoveStyle,
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector FromLocation = pBot->CurrentFloorPosition;
|
Vector FromLocation = pBot->CurrentFloorPosition;
|
||||||
|
Vector FromFloorLocation = FromLocation;
|
||||||
|
|
||||||
// Add a slight bias towards trying to move forward if on a railing or other narrow bit of navigable terrain
|
// If the bot currently has a path, then let's calculate the navigation from the "from" point rather than our exact position right now
|
||||||
// rather than potentially dropping back off it the wrong way
|
if (pBot->BotNavInfo.CurrentPathPoint < pBot->BotNavInfo.CurrentPath.size())
|
||||||
Vector GeneralDir = UTIL_GetVectorNormal2D(ToLocation - pBot->CurrentFloorPosition);
|
|
||||||
Vector CheckLocation = FromLocation + (GeneralDir * 16.0f);
|
|
||||||
|
|
||||||
Vector FromFloorLocation = AdjustPointForPathfinding(CheckLocation);
|
|
||||||
|
|
||||||
if (vIsZero(FromFloorLocation))
|
|
||||||
{
|
{
|
||||||
FromFloorLocation = AdjustPointForPathfinding(FromLocation);
|
bot_path_node CurrentPathNode = pBot->BotNavInfo.CurrentPath[pBot->BotNavInfo.CurrentPathPoint];
|
||||||
|
|
||||||
|
if (CurrentPathNode.flag == SAMPLE_POLYFLAGS_WALK)
|
||||||
|
{
|
||||||
|
bool bFromReachable = UTIL_PointIsDirectlyReachable(pBot->CurrentFloorPosition, CurrentPathNode.Location);
|
||||||
|
bool bToReachable = UTIL_PointIsDirectlyReachable(pBot->CurrentFloorPosition, CurrentPathNode.FromLocation);
|
||||||
|
if (bFromReachable && bToReachable)
|
||||||
|
{
|
||||||
|
FromFloorLocation = pBot->CurrentFloorPosition;
|
||||||
|
}
|
||||||
|
else if (bFromReachable)
|
||||||
|
{
|
||||||
|
FromFloorLocation = CurrentPathNode.FromLocation;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FromFloorLocation = CurrentPathNode.Location;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FromFloorLocation = CurrentPathNode.FromLocation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Add a slight bias towards trying to move forward if on a railing or other narrow bit of navigable terrain
|
||||||
|
// rather than potentially dropping back off it the wrong way
|
||||||
|
Vector GeneralDir = UTIL_GetVectorNormal2D(ToLocation - pBot->CurrentFloorPosition);
|
||||||
|
Vector CheckLocation = FromLocation + (GeneralDir * 16.0f);
|
||||||
|
|
||||||
|
Vector FromFloorLocation = AdjustPointForPathfinding(CheckLocation);
|
||||||
|
|
||||||
|
if (vIsZero(FromFloorLocation))
|
||||||
|
{
|
||||||
|
FromFloorLocation = AdjustPointForPathfinding(FromLocation);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nav_door* LiftReference = UTIL_GetLiftReferenceByEdict(pBot->Edict->v.groundentity);
|
nav_door* LiftReference = UTIL_GetLiftReferenceByEdict(pBot->Edict->v.groundentity);
|
||||||
|
@ -6602,10 +6636,12 @@ bool NAV_MergeAndUpdatePath(AvHAIPlayer* pBot, std::vector<bot_path_node>& NewPa
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Start with the bot's current path point
|
||||||
std::vector<bot_path_node>::iterator OldPathStart = (pBot->BotNavInfo.CurrentPath.begin() + pBot->BotNavInfo.CurrentPathPoint);
|
std::vector<bot_path_node>::iterator OldPathStart = (pBot->BotNavInfo.CurrentPath.begin() + pBot->BotNavInfo.CurrentPathPoint);
|
||||||
std::vector<bot_path_node>::iterator OldPathEnd;
|
std::vector<bot_path_node>::iterator OldPathEnd;
|
||||||
std::vector<bot_path_node>::iterator NewPathStart;
|
std::vector<bot_path_node>::iterator NewPathStart;
|
||||||
|
|
||||||
|
// We skip ahead in the path until we reach the first non-walk node in our CURRENT path
|
||||||
for (OldPathEnd = OldPathStart; OldPathEnd != pBot->BotNavInfo.CurrentPath.end(); OldPathEnd++)
|
for (OldPathEnd = OldPathStart; OldPathEnd != pBot->BotNavInfo.CurrentPath.end(); OldPathEnd++)
|
||||||
{
|
{
|
||||||
if (OldPathEnd->flag != SAMPLE_POLYFLAGS_WALK)
|
if (OldPathEnd->flag != SAMPLE_POLYFLAGS_WALK)
|
||||||
|
@ -6614,11 +6650,13 @@ bool NAV_MergeAndUpdatePath(AvHAIPlayer* pBot, std::vector<bot_path_node>& NewPa
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Our path is all walk, so we will return false which will basically cause us to cancel this path completely and adopt a new one
|
||||||
if (OldPathEnd == pBot->BotNavInfo.CurrentPath.end())
|
if (OldPathEnd == pBot->BotNavInfo.CurrentPath.end())
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We have reached the next non-walk node in our CURRENT path, now we find the next non-walk path in a prospective NEW path
|
||||||
for (NewPathStart = NewPath.begin(); NewPathStart != NewPath.end(); NewPathStart++)
|
for (NewPathStart = NewPath.begin(); NewPathStart != NewPath.end(); NewPathStart++)
|
||||||
{
|
{
|
||||||
if (NewPathStart->flag != SAMPLE_POLYFLAGS_WALK)
|
if (NewPathStart->flag != SAMPLE_POLYFLAGS_WALK)
|
||||||
|
@ -6627,16 +6665,19 @@ bool NAV_MergeAndUpdatePath(AvHAIPlayer* pBot, std::vector<bot_path_node>& NewPa
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// New path is all walk, just embrace it and forget the old path
|
||||||
if (NewPathStart == NewPath.end())
|
if (NewPathStart == NewPath.end())
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The upcoming non-walk node in our current path and the upcoming non-walk node in our new path are different: we have a different path entirely so just get the new path instead
|
||||||
if (OldPathEnd->flag != NewPathStart->flag || !vEquals(OldPathEnd->FromLocation, NewPathStart->FromLocation, 16.0f) || !vEquals(OldPathEnd->Location, NewPathStart->Location, 16.0f))
|
if (OldPathEnd->flag != NewPathStart->flag || !vEquals(OldPathEnd->FromLocation, NewPathStart->FromLocation, 16.0f) || !vEquals(OldPathEnd->Location, NewPathStart->Location, 16.0f))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Now we truncate the current path at the non-walk node, and append the new path from that point
|
||||||
OldPathEnd = next(OldPathEnd);
|
OldPathEnd = next(OldPathEnd);
|
||||||
NewPathStart = next(NewPathStart);
|
NewPathStart = next(NewPathStart);
|
||||||
|
|
||||||
|
|
|
@ -1714,7 +1714,14 @@ void StartNewBotFrame(AvHAIPlayer* pBot)
|
||||||
ClearBotInputs(pBot);
|
ClearBotInputs(pBot);
|
||||||
pBot->CurrentEyePosition = GetPlayerEyePosition(pEdict);
|
pBot->CurrentEyePosition = GetPlayerEyePosition(pEdict);
|
||||||
|
|
||||||
pBot->CurrentFloorPosition = UTIL_GetEntityGroundLocation(pEdict);
|
Vector NewFloorPosition = UTIL_GetEntityGroundLocation(pEdict);
|
||||||
|
|
||||||
|
if (vDist2DSq(NewFloorPosition, pBot->CurrentFloorPosition) > sqrf(UTIL_MetresToGoldSrcUnits(3.0f)))
|
||||||
|
{
|
||||||
|
OnBotTeleport(pBot);
|
||||||
|
}
|
||||||
|
|
||||||
|
pBot->CurrentFloorPosition = NewFloorPosition;
|
||||||
|
|
||||||
if (vDist3DSq(pBot->BotNavInfo.LastNavMeshCheckPosition, pBot->CurrentFloorPosition) > sqrf(16.0f))
|
if (vDist3DSq(pBot->BotNavInfo.LastNavMeshCheckPosition, pBot->CurrentFloorPosition) > sqrf(16.0f))
|
||||||
{
|
{
|
||||||
|
@ -1887,23 +1894,7 @@ void EndBotFrame(AvHAIPlayer* pBot)
|
||||||
|
|
||||||
void CustomThink(AvHAIPlayer* pBot)
|
void CustomThink(AvHAIPlayer* pBot)
|
||||||
{
|
{
|
||||||
if (!IsPlayerAlien(pBot->Edict)) { return; }
|
MoveTo(pBot, UTIL_GetFloorUnderEntity(INDEXENT(1)), MOVESTYLE_NORMAL);
|
||||||
|
|
||||||
int Enemy = BotGetNextEnemyTarget(pBot);
|
|
||||||
|
|
||||||
if (Enemy > -1)
|
|
||||||
{
|
|
||||||
AlienCombatThink(pBot);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
edict_t* CommChair = AITAC_GetCommChair(AIMGR_GetEnemyTeam(pBot->Player->GetTeam()));
|
|
||||||
|
|
||||||
if (!FNullEnt(CommChair))
|
|
||||||
{
|
|
||||||
MoveTo(pBot, CommChair->v.origin, MOVESTYLE_NORMAL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8896,4 +8887,10 @@ void DEBUG_PrintBotDebugInfo(edict_t* OutputPlayer, AvHAIPlayer* pBot)
|
||||||
|
|
||||||
DEBUG_PrintTaskInfo(OutputPlayer, pBot);
|
DEBUG_PrintTaskInfo(OutputPlayer, pBot);
|
||||||
DEBUG_PrintCombatInfo(OutputPlayer, pBot);
|
DEBUG_PrintCombatInfo(OutputPlayer, pBot);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnBotTeleport(AvHAIPlayer* pBot)
|
||||||
|
{
|
||||||
|
ClearBotStuck(pBot);
|
||||||
|
ClearBotStuckMovement(pBot);
|
||||||
}
|
}
|
|
@ -159,6 +159,8 @@ void AIPlayerHearEnemy(AvHAIPlayer* pBot, edict_t* HeardEnemy, float SoundVolume
|
||||||
|
|
||||||
int BotGetNextEnemyTarget(AvHAIPlayer* pBot);
|
int BotGetNextEnemyTarget(AvHAIPlayer* pBot);
|
||||||
|
|
||||||
|
void OnBotTeleport(AvHAIPlayer* pBot);
|
||||||
|
|
||||||
AvHMessageID AlienGetDesiredUpgrade(AvHAIPlayer* pBot, HiveTechStatus DesiredTech);
|
AvHMessageID AlienGetDesiredUpgrade(AvHAIPlayer* pBot, HiveTechStatus DesiredTech);
|
||||||
|
|
||||||
AvHAICombatStrategy GetBotCombatStrategyForTarget(AvHAIPlayer* pBot, enemy_status* CurrentEnemy);
|
AvHAICombatStrategy GetBotCombatStrategyForTarget(AvHAIPlayer* pBot, enemy_status* CurrentEnemy);
|
||||||
|
|
Loading…
Reference in a new issue