mirror of
https://github.com/ENSL/NS.git
synced 2024-11-21 12:11:04 +00:00
Bot movement improvements
* Commander no longer sends reminders once an order is issued * Fixed an issue where marines would loiter and refuse to move on once securing a hive * Improved wall climbing: bots handle varied wall angles better
This commit is contained in:
parent
5beb313546
commit
c2e41c2011
7 changed files with 98 additions and 33 deletions
|
@ -380,7 +380,7 @@ bool AICOMM_IsOrderStillValid(AvHAIPlayer* pBot, ai_commander_order* Order)
|
|||
bool AICOMM_DoesPlayerOrderNeedReminder(AvHAIPlayer* pBot, ai_commander_order* Order)
|
||||
{
|
||||
// For now, disable reminders as it is annoying for humans and pointless for bots who should obey it always anyway
|
||||
return false;
|
||||
return (Order->LastReminderTime < 0.1f);
|
||||
|
||||
float NewDist = vDist2DSq(Order->Assignee->v.origin, Order->OrderLocation);
|
||||
float OldDist = Order->LastPlayerDistance;
|
||||
|
@ -2154,7 +2154,7 @@ bool AICOMM_PerformNextSecureHiveAction(AvHAIPlayer* pBot, const AvHAIHiveDefini
|
|||
{
|
||||
DeployableSearchFilter StructureFilter;
|
||||
StructureFilter.DeployableTypes = STRUCTURE_MARINE_TURRETFACTORY | STRUCTURE_MARINE_ADVTURRETFACTORY | STRUCTURE_MARINE_PHASEGATE;
|
||||
StructureFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(10.0f);
|
||||
StructureFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(15.0f);
|
||||
StructureFilter.DeployableTeam = pBot->Player->GetTeam();
|
||||
StructureFilter.ReachabilityFlags = AI_REACHABILITY_MARINE;
|
||||
StructureFilter.ReachabilityTeam = pBot->Player->GetTeam();
|
||||
|
@ -2164,7 +2164,7 @@ bool AICOMM_PerformNextSecureHiveAction(AvHAIPlayer* pBot, const AvHAIHiveDefini
|
|||
AvHAIBuildableStructure ExistingPG;
|
||||
AvHAIBuildableStructure ExistingTF;
|
||||
|
||||
Vector OutpostLocation = (ExistingStructure.IsValid()) ? ExistingStructure.Location : HiveToSecure->FloorLocation;
|
||||
Vector OutpostLocation = (ExistingStructure.IsValid() && ExistingStructure.Purpose == STRUCTURE_PURPOSE_FORTIFY) ? ExistingStructure.Location : HiveToSecure->FloorLocation;
|
||||
|
||||
if (HiveToSecure->HiveResNodeRef && HiveToSecure->HiveResNodeRef->OwningTeam == TEAM_IND)
|
||||
{
|
||||
|
@ -3360,11 +3360,11 @@ const AvHAIHiveDefinition* AICOMM_GetEmptyHiveOpportunityNearestLocation(AvHAIPl
|
|||
StructureFilter.ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING;
|
||||
|
||||
StructureFilter.DeployableTypes = STRUCTURE_MARINE_PHASEGATE | STRUCTURE_MARINE_TURRETFACTORY | STRUCTURE_MARINE_ADVTURRETFACTORY;
|
||||
StructureFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(10.0f);
|
||||
StructureFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(15.0f);
|
||||
|
||||
AvHAIBuildableStructure ExistingStructure = AITAC_FindClosestDeployableToLocation(Hive->FloorLocation, &StructureFilter);
|
||||
|
||||
if (ExistingStructure.IsValid() && UTIL_QuickTrace(nullptr, UTIL_GetCentreOfEntity(ExistingStructure.edict), Hive->Location))
|
||||
if (ExistingStructure.IsValid() && ExistingStructure.Purpose == STRUCTURE_PURPOSE_FORTIFY)
|
||||
{
|
||||
SecureLocation = ExistingStructure.Location;
|
||||
}
|
||||
|
@ -3444,7 +3444,7 @@ bool AICOMM_IsHiveFullySecured(AvHAIPlayer* CommanderBot, const AvHAIHiveDefinit
|
|||
bTurretFactoryElectrified = (Structure.StructureStatusFlags & STRUCTURE_STATUS_ELECTRIFIED);
|
||||
|
||||
SearchFilter.DeployableTypes = STRUCTURE_MARINE_TURRET;
|
||||
SearchFilter.MaxSearchRadius = UTIL_MetresToGoldSrcUnits(8.0f);
|
||||
SearchFilter.MaxSearchRadius = BALANCE_VAR(kTurretFactoryBuildDistance);
|
||||
|
||||
NumTurrets = AITAC_GetNumDeployablesNearLocation(Structure.Location, &SearchFilter);
|
||||
|
||||
|
|
|
@ -788,6 +788,7 @@ typedef struct AVH_AI_PLAYER
|
|||
edict_t* LookTarget = nullptr; // Used to work out what view angle is needed to look at the desired entity
|
||||
Vector LookTargetLocation = g_vecZero; // This is the bot's current desired look target. Could be an enemy (see LookTarget), or point of interest
|
||||
Vector MoveLookLocation = g_vecZero; // If the bot has to look somewhere specific for movement (e.g. up for a ladder or wall-climb), this will override LookTargetLocation so the bot doesn't get distracted and mess the move up
|
||||
bool bSnapView = false; // Use for rapid, precise snapping of the bot's view to the target. Useful if the bot requires more precise view angles for movement or other reasons
|
||||
float LastTargetTrackUpdate = 0.0f; // Add a delay to how frequently a bot can track a target's movements
|
||||
float ViewInterpolationSpeed = 0.0f; // How fast should the bot turn its view? Depends on distance to turn
|
||||
float ViewInterpStartedTime = 0.0f; // Used for interpolation
|
||||
|
|
|
@ -3702,7 +3702,10 @@ void FallMove(AvHAIPlayer* pBot, const Vector StartPoint, const Vector EndPoint)
|
|||
pBot->desiredMovementDir = vBotOrientation;
|
||||
}
|
||||
|
||||
|
||||
if (vIsZero(pBot->LookTargetLocation))
|
||||
{
|
||||
BotLookAt(pBot, EndPoint + (vBotOrientation * 100.0f));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -4890,6 +4893,30 @@ void WallClimbMove(AvHAIPlayer* pBot, const Vector StartPoint, const Vector EndP
|
|||
}
|
||||
|
||||
Vector vForward = UTIL_GetVectorNormal2D(EndPoint - StartPoint);
|
||||
Vector ClimbAngle = UTIL_GetVectorNormal(Vector(EndPoint.x, EndPoint.y, RequiredClimbHeight) - pBot->Edict->v.origin);
|
||||
|
||||
TraceResult SurfaceCheck;
|
||||
|
||||
UTIL_TraceHull(pBot->Edict->v.origin - Vector(0.0f, 0.0f, 1.0f), pBot->Edict->v.origin + Vector(0.0f, 0.0f, 5.0f), ignore_monsters, head_hull, pBot->Edict->v.pContainingEntity, &SurfaceCheck);
|
||||
|
||||
Vector CeilNormal = SurfaceCheck.vecPlaneNormal;
|
||||
|
||||
bool bIsUnderClimbing = false;
|
||||
|
||||
bool bClimbingUnderway = ((pBot->CollisionHullBottomLocation.z - StartPoint.z) >= 32.0f) && IsPlayerClimbingWall(pBot->Edict);
|
||||
|
||||
if (pEdict->v.origin.z < (RequiredClimbHeight - 10.0f) && !(pEdict->v.flags & FL_ONGROUND) && bClimbingUnderway)
|
||||
{
|
||||
bIsUnderClimbing = (SurfaceCheck.flFraction < 1.0f && UTIL_GetDotProduct(ClimbAngle, CeilNormal) < 0.0f);
|
||||
}
|
||||
|
||||
if (bIsUnderClimbing)
|
||||
{
|
||||
pBot->Button |= IN_WALK;
|
||||
vForward = (UTIL_GetDotProduct2D(vForward, CeilNormal) > 0.0f) ? vForward : -vForward;
|
||||
|
||||
}
|
||||
|
||||
Vector vRight = UTIL_GetVectorNormal(UTIL_GetCrossProduct(vForward, UP_VECTOR));
|
||||
|
||||
pBot->desiredMovementDir = vForward;
|
||||
|
@ -4912,14 +4939,10 @@ void WallClimbMove(AvHAIPlayer* pBot, const Vector StartPoint, const Vector EndP
|
|||
pBot->Button &= ~IN_DUCK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
float ZDiff = fabs(pEdict->v.origin.z - RequiredClimbHeight);
|
||||
Vector AdjustedTargetLocation = EndPoint + (UTIL_GetVectorNormal2D(EndPoint - StartPoint) * 1000.0f);
|
||||
Vector DirectAheadView = pBot->CurrentEyePosition + (UTIL_GetVectorNormal2D(AdjustedTargetLocation - pBot->CurrentEyePosition) * 100.0f);
|
||||
|
||||
Vector ClimbSurfaceNormal = UTIL_GetVectorNormal(EndPoint - StartPoint);
|
||||
|
||||
|
||||
Vector LookLocation = g_vecZero;
|
||||
|
||||
if (ZDiff < 1.0f)
|
||||
|
@ -4931,10 +4954,10 @@ void WallClimbMove(AvHAIPlayer* pBot, const Vector StartPoint, const Vector EndP
|
|||
// Don't look up/down quite so much as we reach the desired height so we slow down a bit, reduces the chance of over-shooting and climbing right over a vent
|
||||
if (pEdict->v.origin.z > RequiredClimbHeight)
|
||||
{
|
||||
if (ZDiff > 32.0f)
|
||||
if (ZDiff > 16.0f)
|
||||
{
|
||||
ClimbSurfaceNormal = ClimbSurfaceNormal - (2.0f * (UTIL_GetDotProduct(ClimbSurfaceNormal, UP_VECTOR) * ClimbSurfaceNormal));
|
||||
LookLocation = pBot->CurrentEyePosition + (ClimbSurfaceNormal * 100.0f);
|
||||
ClimbAngle = ClimbAngle - (2.0f * (UTIL_GetDotProduct(ClimbAngle, UP_VECTOR) * ClimbAngle));
|
||||
LookLocation = pBot->CurrentEyePosition + (ClimbAngle * 100.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -4943,12 +4966,27 @@ void WallClimbMove(AvHAIPlayer* pBot, const Vector StartPoint, const Vector EndP
|
|||
}
|
||||
else
|
||||
{
|
||||
ClimbSurfaceNormal = ClimbSurfaceNormal;
|
||||
LookLocation = pBot->CurrentEyePosition + (ClimbSurfaceNormal * 100.0f);
|
||||
if (bIsUnderClimbing)
|
||||
{
|
||||
LookLocation = pBot->CurrentEyePosition + vForward;
|
||||
LookLocation.z = EndPoint.z + 100.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bClimbingUnderway)
|
||||
{
|
||||
LookLocation = pBot->CurrentEyePosition + (ClimbAngle * 100.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
LookLocation = pBot->CurrentEyePosition + vForward;
|
||||
LookLocation.z = RequiredClimbHeight;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (IsPlayerClimbingWall(pBot->Edict))
|
||||
if (IsPlayerClimbingWall(pBot->Edict) && !bIsUnderClimbing)
|
||||
{
|
||||
Vector RightDir = UTIL_GetCrossProduct(vForward, UP_VECTOR);
|
||||
|
||||
|
@ -4971,7 +5009,8 @@ void WallClimbMove(AvHAIPlayer* pBot, const Vector StartPoint, const Vector EndP
|
|||
}
|
||||
}
|
||||
|
||||
BotMoveLookAt(pBot, LookLocation);
|
||||
BotMoveLookAt(pBot, LookLocation, true);
|
||||
//BotDirectLookAt(pBot, LookLocation);
|
||||
|
||||
}
|
||||
|
||||
|
@ -7937,6 +7976,11 @@ void BotMovementInputs(AvHAIPlayer* pBot)
|
|||
|
||||
float botSpeed = (pBot->BotNavInfo.bShouldWalk) ? (pBot->Edict->v.maxspeed * 0.4f) : pBot->Edict->v.maxspeed;
|
||||
|
||||
if (pBot->BotNavInfo.bShouldWalk)
|
||||
{
|
||||
pBot->Button |= IN_WALK;
|
||||
}
|
||||
|
||||
if (angleDelta < -180.0f)
|
||||
{
|
||||
angleDelta += 360.0f;
|
||||
|
@ -9690,6 +9734,11 @@ bool NAV_IsMovementTaskStillValid(AvHAIPlayer* pBot)
|
|||
|
||||
if (MoveTask->TaskType == MOVE_TASK_TOUCH)
|
||||
{
|
||||
if (pBot->BotNavInfo.IsOnGround)
|
||||
{
|
||||
if (vDist2DSq(pBot->Edict->v.origin, MoveTask->TaskLocation) < sqrf(8.0f) && fabs(pBot->Edict->v.origin.z - MoveTask->TaskLocation.z) < 32.0f) { return false; }
|
||||
}
|
||||
|
||||
return (!FNullEnt(MoveTask->TaskTarget) && !IsPlayerTouchingEntity(pBot->Edict, MoveTask->TaskTarget));
|
||||
}
|
||||
|
||||
|
|
|
@ -59,17 +59,18 @@ void BotSuicide(AvHAIPlayer* pBot)
|
|||
}
|
||||
|
||||
/* Makes the bot look at the specified position */
|
||||
void BotLookAt(AvHAIPlayer* pBot, const Vector target)
|
||||
void BotLookAt(AvHAIPlayer* pBot, const Vector target, bool bSnap)
|
||||
{
|
||||
|
||||
pBot->bSnapView = bSnap;
|
||||
pBot->LookTargetLocation.x = target.x;
|
||||
pBot->LookTargetLocation.y = target.y;
|
||||
pBot->LookTargetLocation.z = target.z;
|
||||
|
||||
}
|
||||
|
||||
void BotMoveLookAt(AvHAIPlayer* pBot, const Vector target)
|
||||
void BotMoveLookAt(AvHAIPlayer* pBot, const Vector target, bool bSnap)
|
||||
{
|
||||
pBot->bSnapView = bSnap;
|
||||
pBot->MoveLookLocation.x = target.x;
|
||||
pBot->MoveLookLocation.y = target.y;
|
||||
pBot->MoveLookLocation.z = target.z;
|
||||
|
@ -126,10 +127,12 @@ enemy_status* GetTrackedEnemyRefForTarget(AvHAIPlayer* pBot, edict_t* Target)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
void BotLookAt(AvHAIPlayer* pBot, edict_t* target)
|
||||
void BotLookAt(AvHAIPlayer* pBot, edict_t* target, bool bSnap)
|
||||
{
|
||||
if (FNullEnt(target)) { return; }
|
||||
|
||||
pBot->bSnapView = bSnap;
|
||||
|
||||
pBot->LookTarget = target;
|
||||
|
||||
// For team mates we don't track enemy refs, so just look at the friendly player
|
||||
|
@ -1152,6 +1155,14 @@ void BotUpdateDesiredViewRotation(AvHAIPlayer* pBot)
|
|||
if (pBot->DesiredLookDirection.x > 180)
|
||||
pBot->DesiredLookDirection.x -= 360;
|
||||
|
||||
if (pBot->bSnapView)
|
||||
{
|
||||
pBot->ViewInterpolationSpeed = 1000.0f;
|
||||
pBot->ViewInterpStartedTime = gpGlobals->time;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Now figure out how far we have to turn to reach our desired target
|
||||
float yDelta = pBot->DesiredLookDirection.y - pBot->InterpolatedLookDirection.y;
|
||||
float xDelta = pBot->DesiredLookDirection.x - pBot->InterpolatedLookDirection.x;
|
||||
|
@ -1194,8 +1205,6 @@ void BotUpdateDesiredViewRotation(AvHAIPlayer* pBot)
|
|||
yOffset *= -1.0f;
|
||||
}
|
||||
|
||||
|
||||
|
||||
pBot->DesiredLookDirection.x += xOffset;
|
||||
pBot->DesiredLookDirection.y += yOffset;
|
||||
}
|
||||
|
@ -5741,7 +5750,7 @@ void TestNavThink(AvHAIPlayer* pBot)
|
|||
|
||||
pBot->CurrentTask = &pBot->PrimaryBotTask;
|
||||
|
||||
if (IsPlayerAlien(pBot->Edict) && IsPlayerSkulk(pBot->Edict))
|
||||
if (IsPlayerAlien(pBot->Edict) && IsPlayerSkulk(pBot->Edict) && AITAC_GetNumPlayersOnTeamOfClass(pBot->Player->GetTeam(), AVH_USER3_ALIEN_PLAYER1, pBot->Edict) > 0)
|
||||
{
|
||||
if (AITAC_GetNumPlayersOnTeamOfClass(pBot->Player->GetTeam(), AVH_USER3_ALIEN_PLAYER2, pBot->Edict) == 0)
|
||||
{
|
||||
|
|
|
@ -26,9 +26,9 @@ static const float f_ffwidth = f_ffheight * BOT_ASPECT_RATIO;
|
|||
|
||||
void BotJump(AvHAIPlayer* pBot);
|
||||
void BotSuicide(AvHAIPlayer* pBot);
|
||||
void BotLookAt(AvHAIPlayer* pBot, Vector NewLocation);
|
||||
void BotLookAt(AvHAIPlayer* pBot, edict_t* target);
|
||||
void BotMoveLookAt(AvHAIPlayer* pBot, const Vector target);
|
||||
void BotLookAt(AvHAIPlayer* pBot, Vector NewLocation, bool bSnap = false);
|
||||
void BotLookAt(AvHAIPlayer* pBot, edict_t* target, bool bSnap = false);
|
||||
void BotMoveLookAt(AvHAIPlayer* pBot, const Vector target, bool bSnap = false);
|
||||
void BotDirectLookAt(AvHAIPlayer* pBot, Vector target);
|
||||
|
||||
bool BotUseObject(AvHAIPlayer* pBot, edict_t* Target, bool bContinuous);
|
||||
|
|
|
@ -2585,7 +2585,7 @@ AvHAIBuildableStructure* AITAC_UpdateBuildableStructure(CBaseEntity* Structure)
|
|||
|
||||
if (NearestHive)
|
||||
{
|
||||
if (NearestHive->Status == HIVE_STATUS_UNBUILT && vDist2DSq(NearestHive->FloorLocation, StructureRef->Location) < sqrf(UTIL_MetresToGoldSrcUnits(10.0f)))
|
||||
if (NearestHive->Status == HIVE_STATUS_UNBUILT && vDist2DSq(NearestHive->FloorLocation, StructureRef->Location) < sqrf(UTIL_MetresToGoldSrcUnits(15.0f)))
|
||||
{
|
||||
StructureRef->Purpose = STRUCTURE_PURPOSE_FORTIFY;
|
||||
}
|
||||
|
@ -5520,9 +5520,10 @@ bool AITAC_IsBotPursuingSquadObjective(AvHAIPlayer* pBot, AvHAISquad* Squad)
|
|||
if (!pBot->CurrentTask || pBot->CurrentTask == &pBot->PrimaryBotTask) { return true; }
|
||||
|
||||
// Bot isn't currently pursuing squad objective, so check if it's doing something in the vicinity
|
||||
Vector TaskLocation = (!FNullEnt(pBot->CurrentTask->TaskTarget)) ? pBot->CurrentTask->TaskTarget->v.origin : pBot->CurrentTask->TaskLocation;
|
||||
Vector BotTaskLocation = (!FNullEnt(pBot->CurrentTask->TaskTarget)) ? pBot->CurrentTask->TaskTarget->v.origin : pBot->CurrentTask->TaskLocation;
|
||||
Vector SquadTaskLocation = (!FNullEnt(Squad->SquadTarget)) ? Squad->SquadTarget->v.origin : Squad->ObjectiveLocation;
|
||||
|
||||
return vDist2DSq(TaskLocation, Squad->SquadTarget->v.origin) < sqrf(UTIL_MetresToGoldSrcUnits(10.0f));
|
||||
return vDist2DSq(BotTaskLocation, SquadTaskLocation) < sqrf(UTIL_MetresToGoldSrcUnits(10.0f));
|
||||
}
|
||||
|
||||
void AITAC_ManageSquads()
|
||||
|
|
|
@ -2814,11 +2814,14 @@ void MarineProgressSecureHiveTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
|
|||
StructureFilter.ReachabilityTeam = BotTeam;
|
||||
StructureFilter.ReachabilityFlags = pBot->BotNavInfo.NavProfile.ReachabilityFlag;
|
||||
StructureFilter.ExcludeStatusFlags = STRUCTURE_STATUS_RECYCLING;
|
||||
StructureFilter.PurposeFlags = STRUCTURE_PURPOSE_FORTIFY;
|
||||
|
||||
vector<AvHAIBuildableStructure> BuildableStructures = AITAC_FindAllDeployables(Hive->FloorLocation, &StructureFilter);
|
||||
|
||||
bool bKeyStructureBuilt = false;
|
||||
|
||||
AvHAIBuildableStructure KeyOutpostStructure;
|
||||
|
||||
AvHAIBuildableStructure StructureToBuild;
|
||||
float MinDist = 0.0f;
|
||||
|
||||
|
@ -2828,6 +2831,7 @@ void MarineProgressSecureHiveTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
|
|||
|
||||
if ((ThisStructure.StructureStatusFlags & STRUCTURE_STATUS_COMPLETED) && (ThisStructure.StructureType & (STRUCTURE_MARINE_TURRETFACTORY | STRUCTURE_MARINE_ADVTURRETFACTORY | STRUCTURE_MARINE_PHASEGATE)))
|
||||
{
|
||||
KeyOutpostStructure = ThisStructure;
|
||||
bKeyStructureBuilt = true;
|
||||
}
|
||||
|
||||
|
@ -2904,8 +2908,9 @@ void MarineProgressSecureHiveTask(AvHAIPlayer* pBot, AvHAIPlayerTask* Task)
|
|||
}
|
||||
}
|
||||
|
||||
Vector OutpostLocation = (KeyOutpostStructure.IsValid()) ? KeyOutpostStructure.Location : Task->TaskLocation;
|
||||
|
||||
BotGuardLocation(pBot, Task->TaskLocation);
|
||||
BotGuardLocation(pBot, OutpostLocation);
|
||||
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue