-
Notifications
You must be signed in to change notification settings - Fork 24
Bots avoid grenade related hazard areas #2020
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -62,6 +62,7 @@ class CSearchForAttackCover : public ISearchSurroundingAreasFunctor | |
| m_threatArea = threat->GetLastKnownArea(); | ||
| m_goalArea = goalArea ? goalArea : m_threatArea; // prioritize movement towards input goal area or threat | ||
| m_myDistToGoalSq = m_goalArea ? ( m_goalArea->GetCenter() - m_me->GetAbsOrigin() ).LengthSqr() : 0; | ||
| m_onStuckPenalty = neo_bot_path_reservation_onstuck_penalty.GetFloat(); | ||
| } | ||
|
|
||
| virtual bool operator() ( CNavArea *baseArea, CNavArea *priorArea, float travelDistanceSoFar ) | ||
|
|
@@ -79,10 +80,18 @@ class CSearchForAttackCover : public ISearchSurroundingAreasFunctor | |
| return true; // skip our starting area | ||
| } | ||
|
|
||
| if ( neo_bot_path_reservation_enable.GetBool() && | ||
| ( CNEOBotPathReservations()->GetAreaAvoidPenalty(area->GetID()) > 0 ) ) | ||
| // Skip areas that are hazardous or where bots get stuck | ||
| if ( neo_bot_path_reservation_enable.GetBool() ) | ||
| { | ||
| return true; // skip areas that have had navigation hiccups | ||
| int navAreaId = area->GetID(); | ||
| if (CNEOBotPathReservations()->IsAreaHazardous(navAreaId, m_me)) | ||
| { | ||
| return true; | ||
| } | ||
| if (CNEOBotPathReservations()->GetAreaAvoidPenalty(navAreaId) >= m_onStuckPenalty) | ||
| { | ||
| return true; | ||
| } | ||
| } | ||
|
|
||
| if ( m_attackCoverArea ) | ||
|
|
@@ -199,6 +208,7 @@ class CSearchForAttackCover : public ISearchSurroundingAreasFunctor | |
| const CNavArea *m_myArea; // reference point of myself | ||
| const CNavArea *m_threatArea; // reference point of the threat | ||
| float m_myDistToGoalSq; // the bot's current distance to the threat | ||
| float m_onStuckPenalty; // cache onstuck penalty | ||
| }; | ||
|
|
||
|
|
||
|
|
@@ -452,11 +462,6 @@ QueryResultType CNEOBotAttack::ShouldRetreat( const INextBot *me ) const | |
| return ANSWER_UNDEFINED; | ||
| } | ||
|
|
||
| if ( m_goalArea && m_attackCoverArea ) | ||
| { | ||
| return ANSWER_NO; | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. While preventing the bots from retreating when they are rushing for a cover area was okay for proving out #2000, it made the bots a bit suicidal when their chosen advancing cover was too exposed, so I think it's better to retreat when there's any incoming fire. This also encourages more grenade throw attempts which is helpful for viewing the smoke and grenade avoidance behavior. |
||
| } | ||
|
|
||
| return ANSWER_UNDEFINED; | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -196,7 +196,7 @@ ActionResult< CNEOBot > CNEOBotCtgEscort::Update( CNEOBot *me, float interval ) | |
| m_chasePath.Invalidate(); | ||
|
|
||
| CNEOBotPathCompute( me, m_path, vecMoveTarget, SAFEST_ROUTE ); | ||
| m_repathTimer.Start( RandomFloat( 1.0f, 2.0f ) ); | ||
| m_repathTimer.Start( RandomFloat( 5.0f, 10.0f ) ); | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Excessively short repath timers can cause bots to indecisively fail to move towards a position, so I increased these timers to allow some movement towards a goal. |
||
| } | ||
| m_path.Update( me ); | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,6 +9,8 @@ | |
| #include "weapon_grenade.h" | ||
| #include "weapon_smokegrenade.h" | ||
|
|
||
| ConVar sv_neo_bot_grenade_polite_frag("sv_neo_bot_grenade_polite_frag", "1", FCVAR_NONE, "Force bots to consider teammates when throwing frag grenades.", true, 0, true, 1); | ||
| ConVar sv_neo_bot_grenade_polite_smoke("sv_neo_bot_grenade_polite_smoke", "1", FCVAR_NONE, "Force bots to consider teammates when throwing smoke grenades.", true, 0, true, 1); | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It can be rare to see a smoke deployment with the default bot deployment decisions, so I added a ConVar to induce bots to throw grenades more readily. This helps observe the hazard avoidance behavior more frequently.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The existing logic below should be mostly the same despite the indentation changes that caused many diff line changes. |
||
| ConVar sv_neo_bot_grenade_use_frag("sv_neo_bot_grenade_use_frag", "1", FCVAR_NONE, "Allow bots to use frag grenades", true, 0, true, 1); | ||
| ConVar sv_neo_bot_grenade_use_smoke("sv_neo_bot_grenade_use_smoke", "1", FCVAR_NONE, "Allow bots to use smoke grenades", true, 0, true, 1); | ||
| ConVar sv_neo_bot_grenade_throw_cooldown("sv_neo_bot_grenade_throw_cooldown", "10", FCVAR_NONE, "Cooldown in seconds between grenade throws for bots"); | ||
|
|
@@ -78,29 +80,32 @@ Action< CNEOBot > *CNEOBotGrenadeDispatch::ChooseGrenadeThrowBehavior( const CNE | |
| // Should I toss a smoke grenade? | ||
| if ( pSmokeGrenade && (me->GetClass() == NEO_CLASS_SUPPORT) ) | ||
| { | ||
| for ( int i = 1; i <= gpGlobals->maxClients; i++ ) | ||
| if ( sv_neo_bot_grenade_polite_smoke.GetBool() ) | ||
| { | ||
| CNEO_Player *pPlayer = ToNEOPlayer( UTIL_PlayerByIndex( i ) ); | ||
| if ( !pPlayer || !pPlayer->IsAlive() || pPlayer == me ) | ||
| for ( int i = 1; i <= gpGlobals->maxClients; i++ ) | ||
| { | ||
| continue; | ||
| } | ||
| CNEO_Player *pPlayer = ToNEOPlayer( UTIL_PlayerByIndex( i ) ); | ||
| if ( !pPlayer || !pPlayer->IsAlive() || pPlayer == me ) | ||
| { | ||
| continue; | ||
| } | ||
|
|
||
| if ( pPlayer->InSameTeam( me ) ) | ||
| { | ||
| if ( !pPlayer->IsBot() && pPlayer->GetClass() != NEO_CLASS_SUPPORT ) | ||
| if ( pPlayer->InSameTeam( me ) ) | ||
| { | ||
| // Avoid blocking the vision of a friendly human | ||
| // (Bots benefit from concealment without the disorientation) | ||
| return nullptr; | ||
| if ( !pPlayer->IsBot() && pPlayer->GetClass() != NEO_CLASS_SUPPORT ) | ||
| { | ||
| // Avoid blocking the vision of a friendly human | ||
| // (Bots benefit from concealment without the disorientation) | ||
| return nullptr; | ||
| } | ||
| } | ||
| } | ||
| else | ||
| { | ||
| if ( pPlayer->GetClass() == NEO_CLASS_SUPPORT ) | ||
| else | ||
| { | ||
| // Avoid giving an enemy with thermal vision a free smoke screen | ||
| return nullptr; | ||
| if ( pPlayer->GetClass() == NEO_CLASS_SUPPORT ) | ||
| { | ||
| // Avoid giving an enemy with thermal vision a free smoke screen | ||
| return nullptr; | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
@@ -111,9 +116,12 @@ Action< CNEOBot > *CNEOBotGrenadeDispatch::ChooseGrenadeThrowBehavior( const CNE | |
| // Should I toss a frag grenade? | ||
| if ( pFragGrenade ) | ||
| { | ||
| if ( !CNEOBotGrenadeThrowFrag::IsFragSafe( me, threat->GetLastKnownPosition() ) ) | ||
| if ( sv_neo_bot_grenade_polite_frag.GetBool() ) | ||
| { | ||
| return nullptr; | ||
| if ( !CNEOBotGrenadeThrowFrag::IsFragSafe( me, threat->GetLastKnownPosition() ) ) | ||
| { | ||
| return nullptr; | ||
| } | ||
| } | ||
|
|
||
| return new CNEOBotGrenadeThrowFrag( pFragGrenade, threat ); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,11 +1,13 @@ | ||
| #include "cbase.h" | ||
| #include "bot/neo_bot.h" | ||
| #include "bot/neo_bot_path_compute.h" | ||
| #include "bot/neo_bot_path_reservation.h" | ||
| #include "bot/behavior/neo_bot_grenade_throw_frag.h" | ||
| #include "neo_gamerules.h" | ||
| #include "neo_player.h" | ||
| #include "weapon_neobasecombatweapon.h" | ||
|
|
||
| #include "nav_mesh.h" | ||
| #include "nav_pathfind.h" | ||
|
|
||
| extern ConVar sv_neo_grenade_blast_radius; | ||
|
|
@@ -106,6 +108,15 @@ CNEOBotGrenadeThrow::ThrowTargetResult CNEOBotGrenadeThrowFrag::UpdateGrenadeTar | |
| return THROW_TARGET_CANCEL; // risk of friendly fire | ||
| } | ||
|
|
||
| // Register explosive hazard at the target position | ||
| // so the throwing bot's team can avoid the trajectory and landing areas | ||
| CNavArea *area = TheNavMesh->GetNearestNavArea(m_vecTarget); | ||
| if (area) | ||
| { | ||
| int team = me->GetTeamNumber(); | ||
| CNEOBotPathReservations()->AddFragHazard(area->GetID(), gpGlobals->curtime + sv_neo_grenade_fuse_timer.GetFloat(), team); | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Expanding the hazard area around grenades by adjacent Potentially Visible Set is intended as a shorthand for avoid the area along the line through the target, as well as avoid the radiating circle around the idea detonation zone, with some leeway for the trajectory to be off as it usually is. |
||
| } | ||
|
|
||
| return THROW_TARGET_READY; | ||
| } | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I forgot I added avoidance penalties for areas where a bot died, so I made the threshold under which a bot got stuck in a location, allowing to minor penalty for death areas to be used as candidates if under the OnStuck threshold.