Skip to content

Commit 729fb9f

Browse files
committed
Bots move to vantage point to throw grenade
1 parent 8cfdc9f commit 729fb9f

File tree

3 files changed

+156
-1
lines changed

3 files changed

+156
-1
lines changed

src/game/server/neo/bot/behavior/neo_bot_grenade_throw.cpp

Lines changed: 153 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,24 @@
1010
#include "nav_pathfind.h"
1111
#include "bot/neo_bot_path_compute.h"
1212

13+
extern ConVar sv_neo_bot_grenade_frag_safety_range_multiplier;
14+
extern ConVar sv_neo_grenade_blast_radius;
15+
1316
ConVar sv_neo_bot_grenade_debug_behavior("sv_neo_bot_grenade_debug_behavior", "0", FCVAR_CHEAT,
1417
"Draw debug overlays for bot grenade behavior", true, 0, true, 1);
1518

1619
ConVar sv_neo_bot_grenade_give_up_time("sv_neo_bot_grenade_give_up_time", "5.0", FCVAR_NONE,
1720
"Time in seconds before bot gives up on grenade throw", true, 1, false, 0);
1821

22+
ConVar sv_neo_bot_grenade_search_range("sv_neo_bot_grenade_search_range", "1000", FCVAR_CHEAT,
23+
"Travel distance range for bot to search for a grenade throw vantage point", true, 0, false, 0);
24+
1925
//---------------------------------------------------------------------------------------------
2026
CNEOBotGrenadeThrow::CNEOBotGrenadeThrow( CNEOBaseCombatWeapon *pWeapon, const CKnownEntity *threat )
2127
{
2228
m_hGrenadeWeapon = pWeapon;
29+
m_bVantagePointBlocked = false;
30+
m_vantageArea = nullptr;
2331
m_vecTarget = vec3_invalid;
2432

2533
if ( threat )
@@ -95,6 +103,100 @@ const Vector& CNEOBotGrenadeThrow::FindEmergencePointAlongPath( const CNEOBot *m
95103
return vec3_invalid;
96104
}
97105

106+
107+
//---------------------------------------------------------------------------------------------
108+
class CFindVantagePointTargetPos : public ISearchSurroundingAreasFunctor
109+
{
110+
public:
111+
CFindVantagePointTargetPos( CNEOBot *me, const Vector &targetPos, CBaseEntity *pThreat )
112+
{
113+
m_me = me;
114+
m_targetPos = targetPos;
115+
m_vantageArea = nullptr;
116+
m_threatArea = nullptr;
117+
m_targetArea = TheNavMesh->GetNavArea( m_targetPos );
118+
119+
if ( pThreat )
120+
{
121+
m_threatArea = TheNavMesh->GetNavArea( pThreat->GetAbsOrigin() );
122+
}
123+
124+
if ( !m_threatArea )
125+
{
126+
const CKnownEntity *primaryThreat = me->GetVisionInterface()->GetPrimaryKnownThreat();
127+
if ( primaryThreat )
128+
{
129+
m_threatArea = primaryThreat->GetLastKnownArea();
130+
}
131+
}
132+
133+
float flRadius = sv_neo_grenade_blast_radius.GetFloat() * sv_neo_bot_grenade_frag_safety_range_multiplier.GetFloat();
134+
m_flSafetyRadiusSq = flRadius * flRadius;
135+
}
136+
137+
virtual bool operator() ( CNavArea* baseArea, CNavArea* priorArea, float travelDistanceSoFar )
138+
{
139+
CNavArea* area = (CNavArea*)baseArea;
140+
141+
if (!m_targetArea)
142+
{
143+
return false; // can't search
144+
}
145+
146+
if ( area->IsPotentiallyVisible( m_targetArea ) )
147+
{
148+
// nearby area from which we can see the last known position
149+
m_vantageArea = area;
150+
return false; // stop searching
151+
}
152+
153+
return true; // continue searching
154+
}
155+
156+
// return true if 'adjArea' should be included in the ongoing search
157+
virtual bool ShouldSearch( CNavArea *adjArea, CNavArea *currentArea, float travelDistanceSoFar )
158+
{
159+
if ( travelDistanceSoFar > sv_neo_bot_grenade_search_range.GetFloat() )
160+
{
161+
return false;
162+
}
163+
164+
// For considering areas off to the side of current area
165+
constexpr float distanceThresholdRatio = 0.8f;
166+
167+
if ( m_threatArea )
168+
{
169+
// The adjacent area to search should not be farther from the threat
170+
float adjThreatDistance = ( m_threatArea->GetCenter() - adjArea->GetCenter() ).LengthSqr();
171+
float curThreatDistance = ( m_threatArea->GetCenter() - currentArea->GetCenter() ).LengthSqr();
172+
if ( adjThreatDistance * distanceThresholdRatio > curThreatDistance )
173+
{
174+
return false; // Candidate adjacent area veers farther from threat
175+
}
176+
177+
// The adjacent area to search should not be closer than the safety range
178+
if ( adjThreatDistance < m_flSafetyRadiusSq )
179+
{
180+
// NEO JANK: While this range is based on frag grenades,
181+
// it's still likely a bad idea to throw smoke grenades this close to the threat
182+
// Though logic at time of comment just throws smoke safely from behind cover
183+
return false; // Candidate adjacent area is too close to threat
184+
}
185+
}
186+
187+
// allow falling off ledges, but don't jump up - too slow
188+
return ( currentArea->ComputeAdjacentConnectionHeightChange( adjArea ) < m_me->GetLocomotionInterface()->GetStepHeight() );
189+
}
190+
191+
CNEOBot *m_me;
192+
Vector m_targetPos;
193+
CNavArea *m_targetArea;
194+
CNavArea *m_vantageArea;
195+
const CNavArea *m_threatArea;
196+
float m_flSafetyRadiusSq;
197+
};
198+
199+
98200
//---------------------------------------------------------------------------------------------
99201
ActionResult< CNEOBot > CNEOBotGrenadeThrow::OnStart( CNEOBot *me, Action< CNEOBot > *priorAction )
100202
{
@@ -135,6 +237,7 @@ ActionResult< CNEOBot > CNEOBotGrenadeThrow::OnStart( CNEOBot *me, Action< CNEOB
135237
return Continue();
136238
}
137239

240+
138241
//---------------------------------------------------------------------------------------------
139242
ActionResult< CNEOBot > CNEOBotGrenadeThrow::Update( CNEOBot *me, float interval )
140243
{
@@ -292,10 +395,53 @@ ActionResult< CNEOBot > CNEOBotGrenadeThrow::Update( CNEOBot *me, float interval
292395
{
293396
m_PathFollower.Update( me );
294397

398+
// Watch for threats emerging from known position
399+
if ( m_vecThreatLastKnownPos != vec3_invalid )
400+
{
401+
me->GetBodyInterface()->AimHeadTowards(
402+
m_vecThreatLastKnownPos, IBody::IMPORTANT, 0.1f, nullptr,
403+
"Looking towards last known threat position while moving to vantage point");
404+
}
405+
406+
if ( m_vantageArea && me->GetLastKnownArea() == m_vantageArea )
407+
{
408+
// Arrived at vantage point but still blocked - fallback to chase
409+
m_bVantagePointBlocked = true;
410+
m_vantageArea = nullptr;
411+
}
412+
295413
if ( m_repathTimer.IsElapsed() )
296414
{
297415
m_repathTimer.Start( RandomFloat( 0.3f, 0.5f ) );
298-
CNEOBotPathCompute( me, m_PathFollower, m_vecTarget != vec3_invalid ? m_vecTarget : m_vecThreatLastKnownPos, FASTEST_ROUTE );
416+
417+
if ( !m_vantageArea && !m_bVantagePointBlocked )
418+
{
419+
CFindVantagePointTargetPos find( me, m_vecThreatLastKnownPos, m_hThreatGrenadeTarget.Get() );
420+
SearchSurroundingAreas( me->GetLastKnownArea(), find, sv_neo_bot_grenade_search_range.GetFloat() );
421+
m_vantageArea = find.m_vantageArea;
422+
423+
if ( !m_vantageArea )
424+
{
425+
return Done( "Failed to find a vantage area to throw grenade from" );
426+
}
427+
}
428+
429+
bool bGoingToVantagePoint = false;
430+
if ( m_vantageArea )
431+
{
432+
bGoingToVantagePoint = CNEOBotPathCompute( me, m_PathFollower, m_vantageArea->GetCenter(), FASTEST_ROUTE );
433+
}
434+
435+
if ( !bGoingToVantagePoint )
436+
{
437+
// Fallback to direct chase behavior if vantage point is blocked
438+
if ( m_vantageArea )
439+
{
440+
m_vantageArea = nullptr;
441+
m_bVantagePointBlocked = true;
442+
}
443+
CNEOBotPathCompute( me, m_PathFollower, m_vecTarget != vec3_invalid ? m_vecTarget : m_vecThreatLastKnownPos, FASTEST_ROUTE );
444+
}
299445
}
300446
}
301447

@@ -309,6 +455,12 @@ ActionResult< CNEOBot > CNEOBotGrenadeThrow::Update( CNEOBot *me, float interval
309455
NDebugOverlay::HorzArrow( vecStart, m_vecTarget, 2.0f, 255, 128, 0, 255, true, 2.0f );
310456
NDebugOverlay::Box( m_vecTarget, Vector(-16,-16,-16), Vector(16,16,16), 255, 128, 0, 30, 2.0f );
311457
}
458+
459+
if ( m_vantageArea )
460+
{
461+
NDebugOverlay::Box( m_vantageArea->GetCenter(), Vector(-16,-16,0), Vector(16,16,16), 0, 255, 0, 30, 0.1f );
462+
NDebugOverlay::Line( me->EyePosition(), m_vantageArea->GetCenter(), 0, 255, 0, true, 0.1f );
463+
}
312464
}
313465

314466
// NEO JANK: Force the throwing phase if aimed.

src/game/server/neo/bot/behavior/neo_bot_grenade_throw.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ class CNEOBotGrenadeThrow : public Action< CNEOBot >
2424
virtual QueryResultType ShouldRetreat( const INextBot *me ) const override;
2525

2626
protected:
27+
CNavArea *m_vantageArea;
2728
Vector m_vecTarget; // caches target to aim at during throw action in implementation classes
2829
Vector m_vecThreatLastKnownPos;
2930
CHandle< CNEOBaseCombatWeapon > m_hGrenadeWeapon;
@@ -34,6 +35,7 @@ class CNEOBotGrenadeThrow : public Action< CNEOBot >
3435
PathFollower m_PathFollower;
3536

3637
bool m_bPinPulled;
38+
bool m_bVantagePointBlocked;
3739

3840
enum ThrowTargetResult
3941
{

src/game/server/neo/bot/behavior/neo_bot_grenade_throw_frag.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ CNEOBotGrenadeThrow::ThrowTargetResult CNEOBotGrenadeThrowFrag::UpdateGrenadeTar
5757
{
5858
// Update target to immediate threat
5959
m_hThreatGrenadeTarget = pPrimaryThreat->GetEntity();
60+
m_vantageArea = nullptr; // reconsider vantage point
6061
m_vecTarget = pPrimaryThreat->GetLastKnownPosition();
6162
m_vecThreatLastKnownPos = m_vecTarget;
6263
m_scanTimer.Start( 0.2f );

0 commit comments

Comments
 (0)