Skip to content

Commit 23427ef

Browse files
committed
Lone bots deploy detpack ambush at ghost
1 parent 8c898f0 commit 23427ef

File tree

8 files changed

+488
-72
lines changed

8 files changed

+488
-72
lines changed

src/game/server/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1453,6 +1453,8 @@ target_sources_grouped(
14531453
neo/bot/behavior/neo_bot_ctg_escort.h
14541454
neo/bot/behavior/neo_bot_ctg_lone_wolf.cpp
14551455
neo/bot/behavior/neo_bot_ctg_lone_wolf.h
1456+
neo/bot/behavior/neo_bot_ctg_lone_wolf_ambush.cpp
1457+
neo/bot/behavior/neo_bot_ctg_lone_wolf_ambush.h
14561458
neo/bot/behavior/neo_bot_ctg_seek.cpp
14571459
neo/bot/behavior/neo_bot_ctg_seek.h
14581460
neo/bot/behavior/neo_bot_dead.cpp

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

Lines changed: 84 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@
44
#include "bot/behavior/neo_bot_attack.h"
55
#include "bot/behavior/neo_bot_ctg_capture.h"
66
#include "bot/behavior/neo_bot_ctg_lone_wolf.h"
7+
#include "bot/behavior/neo_bot_ctg_lone_wolf_ambush.h"
78
#include "bot/behavior/neo_bot_seek_weapon.h"
89
#include "bot/behavior/neo_bot_retreat_to_cover.h"
910
#include "bot/neo_bot_path_compute.h"
1011
#include "neo_gamerules.h"
1112
#include "neo_ghost_cap_point.h"
13+
#include "weapon_detpack.h"
1214
#include "weapon_ghost.h"
1315

1416

@@ -17,7 +19,6 @@ CNEOBotCtgLoneWolf::CNEOBotCtgLoneWolf( void )
1719
{
1820
m_hGhost = nullptr;
1921
m_bPursuingDropThreat = false;
20-
m_bHasRetreatedFromGhost = false;
2122
m_vecDropThreatPos = CNEO_Player::VECTOR_INVALID_WAYPOINT;
2223
m_closestCapturePoint = CNEO_Player::VECTOR_INVALID_WAYPOINT;
2324
}
@@ -26,7 +27,7 @@ CNEOBotCtgLoneWolf::CNEOBotCtgLoneWolf( void )
2627
ActionResult< CNEOBot > CNEOBotCtgLoneWolf::OnStart( CNEOBot *me, Action< CNEOBot > *priorAction )
2728
{
2829
m_hGhost = nullptr;
29-
m_bHasRetreatedFromGhost = false;
30+
m_hPursueTarget = nullptr;
3031
m_bPursuingDropThreat = false;
3132
m_useAttemptTimer.Invalidate();
3233
m_lookAroundTimer.Invalidate();
@@ -35,7 +36,6 @@ ActionResult< CNEOBot > CNEOBotCtgLoneWolf::OnStart( CNEOBot *me, Action< CNEOBo
3536
m_capPointUpdateTimer.Invalidate();
3637
m_vecDropThreatPos = CNEO_Player::VECTOR_INVALID_WAYPOINT;
3738
m_closestCapturePoint = CNEO_Player::VECTOR_INVALID_WAYPOINT;
38-
m_hPursueTarget = nullptr;
3939

4040
return Continue();
4141
}
@@ -84,42 +84,15 @@ ActionResult< CNEOBot > CNEOBotCtgLoneWolf::Update( CNEOBot *me, float interval
8484
}
8585

8686
// Always need to find the ghost to act on it
87-
if (!m_hGhost)
88-
{
89-
m_hGhost = dynamic_cast<CWeaponGhost*>( gEntList.FindEntityByClassname(nullptr, "weapon_ghost") );
90-
}
91-
92-
if (!m_hGhost)
87+
if ( !UpdateGhostHandle( me ) )
9388
{
9489
return Done( "Ghost not found" );
9590
}
9691

9792
// Occasionally reconsider which cap zone is our goal
9893
if ( !m_capPointUpdateTimer.HasStarted() || m_capPointUpdateTimer.IsElapsed() )
9994
{
100-
m_closestCapturePoint = CNEO_Player::VECTOR_INVALID_WAYPOINT;
101-
float flNearestCapDistSq = FLT_MAX;
102-
103-
if ( NEORules()->m_pGhostCaps.Count() > 0 )
104-
{
105-
const Vector& vecStart = me->IsCarryingGhost() ? me->GetAbsOrigin() : m_hGhost->GetAbsOrigin();
106-
107-
for( int i=0; i<NEORules()->m_pGhostCaps.Count(); ++i )
108-
{
109-
CNEOGhostCapturePoint *pCapPoint = dynamic_cast<CNEOGhostCapturePoint*>( UTIL_EntityByIndex( NEORules()->m_pGhostCaps[i] ) );
110-
if ( !pCapPoint ) continue;
111-
112-
if ( pCapPoint->owningTeamAlternate() == me->GetTeamNumber() )
113-
{
114-
float distSq = vecStart.DistToSqr( pCapPoint->GetAbsOrigin() );
115-
if ( distSq < flNearestCapDistSq )
116-
{
117-
flNearestCapDistSq = distSq;
118-
m_closestCapturePoint = pCapPoint->GetAbsOrigin();
119-
}
120-
}
121-
}
122-
}
95+
m_closestCapturePoint = GetNearestCapturePoint( me, false );
12396
m_capPointUpdateTimer.Start( RandomFloat( 0.5f, 1.0f ) );
12497
}
12598

@@ -291,11 +264,20 @@ ActionResult< CNEOBot > CNEOBotCtgLoneWolf::Update( CNEOBot *me, float interval
291264
// Ghost is free for taking
292265
if ( bSafeToCap || (bIs1v1 && m_stalemateTimer.HasStarted() && m_stalemateTimer.IsElapsed()) )
293266
{
294-
// Try to cap before enemy can stop us.
295267
float flDistToGhostSq = me->GetAbsOrigin().DistToSqr(m_hGhost->GetAbsOrigin());
296-
if ( flDistToGhostSq < 100.0f * 100.0f )
268+
float flAmbushDistSq = CNEOBotCtgLoneWolf::GetDetpackDeployDistanceSq( me );
269+
270+
if ( flDistToGhostSq < flAmbushDistSq)
297271
{
298-
return SuspendFor(new CNEOBotCtgCapture(m_hGhost.Get()), "Picking up ghost to make a run for it!");
272+
if ( !bSafeToCap && me->Weapon_OwnsThisType("weapon_remotedet") )
273+
{
274+
return ChangeTo(new CNEOBotCtgLoneWolfAmbush(), "Setting up detpack ambush at ghost");
275+
}
276+
else
277+
{
278+
// Try to cap before enemy can stop us.
279+
return SuspendFor(new CNEOBotCtgCapture(m_hGhost.Get()), "Picking up ghost to make a run for it!");
280+
}
299281
}
300282

301283
if ( !m_repathTimer.HasStarted() || m_repathTimer.IsElapsed() )
@@ -320,40 +302,27 @@ ActionResult< CNEOBot > CNEOBotCtgLoneWolf::Update( CNEOBot *me, float interval
320302
m_stalemateTimer.Start( RandomFloat( 10.0f, 20.0f ) );
321303
}
322304

323-
if ( m_bHasRetreatedFromGhost )
305+
// Hide out of sight of ghost to ambush anyone that picks up the ghost
306+
float flDistToGhostSq = me->GetAbsOrigin().DistToSqr(m_hGhost->GetAbsOrigin());
307+
float flAmbushDistSq = CNEOBotCtgLoneWolf::GetDetpackDeployDistanceSq( me );
308+
if (flDistToGhostSq < flAmbushDistSq)
324309
{
325-
// Waiting in ambush/cover
326-
if (threat && me->IsLineOfFireClear( threat->GetEntity()->WorldSpaceCenter(), CNEOBot::LINE_OF_FIRE_FLAGS_DEFAULT ))
327-
{
328-
me->EnableCloak( 3.0f );
329-
return SuspendFor(new CNEOBotAttack, "Ambushing enemy near ghost!");
330-
}
331-
return UpdateLookAround( me, m_hGhost->GetAbsOrigin() );
310+
return ChangeTo(new CNEOBotCtgLoneWolfAmbush(), "Setting up ambush near the ghost");
332311
}
333312
else
334313
{
335-
// Hide out of sight of ghost to ambush anyone that picks up the ghost
336-
float flDistToGhostSq = me->GetAbsOrigin().DistToSqr(m_hGhost->GetAbsOrigin());
337-
if (flDistToGhostSq < 300.0f * 300.0f)
314+
// Get near the ghost first before surveying hiding spots
315+
if ( !m_repathTimer.HasStarted() || m_repathTimer.IsElapsed() )
338316
{
339-
m_bHasRetreatedFromGhost = true;
340-
return SuspendFor(new CNEOBotRetreatToCover(), "Finding a hiding spot near the ghost");
317+
CNEOBotPathCompute(me, m_path, m_hGhost->GetAbsOrigin(), FASTEST_ROUTE);
318+
m_path.Update(me);
319+
m_repathTimer.Start( RandomFloat( 0.5f, 1.0f ) );
341320
}
342321
else
343322
{
344-
// Get near the ghost first before surveying hiding spots
345-
if ( !m_repathTimer.HasStarted() || m_repathTimer.IsElapsed() )
346-
{
347-
CNEOBotPathCompute(me, m_path, m_hGhost->GetAbsOrigin(), FASTEST_ROUTE);
348-
m_path.Update(me);
349-
m_repathTimer.Start( RandomFloat( 0.5f, 1.0f ) );
350-
}
351-
else
352-
{
353-
m_path.Update(me);
354-
}
355-
return Continue();
323+
m_path.Update(me);
356324
}
325+
return Continue();
357326
}
358327
}
359328
}
@@ -414,7 +383,50 @@ EventDesiredResult< CNEOBot > CNEOBotCtgLoneWolf::OnMoveToFailure( CNEOBot *me,
414383
return TryContinue();
415384
}
416385

386+
//---------------------------------------------------------------------------------------------
387+
Vector CNEOBotCtgLoneWolf::GetNearestCapturePoint( CNEOBot *me, bool bEnemyCapPoint )
388+
{
389+
Vector vecBestCapPoint = CNEO_Player::VECTOR_INVALID_WAYPOINT;
390+
float flNearestCapDistSq = FLT_MAX;
391+
392+
if ( NEORules()->m_pGhostCaps.Count() > 0 )
393+
{
394+
const Vector& vecStart = me->IsCarryingGhost() ? me->GetAbsOrigin() : ( m_hGhost.Get() ? m_hGhost->GetAbsOrigin() : me->GetAbsOrigin() );
395+
396+
for( int i=0; i<NEORules()->m_pGhostCaps.Count(); ++i )
397+
{
398+
CNEOGhostCapturePoint *pCapPoint = dynamic_cast<CNEOGhostCapturePoint*>( UTIL_EntityByIndex( NEORules()->m_pGhostCaps[i] ) );
399+
if ( !pCapPoint ) continue;
400+
401+
bool bValidTeam = (pCapPoint->owningTeamAlternate() == me->GetTeamNumber());
402+
if ( bEnemyCapPoint )
403+
{
404+
bValidTeam = (pCapPoint->owningTeamAlternate() != me->GetTeamNumber());
405+
}
417406

407+
if ( bValidTeam )
408+
{
409+
float distSq = vecStart.DistToSqr( pCapPoint->GetAbsOrigin() );
410+
if ( distSq < flNearestCapDistSq )
411+
{
412+
flNearestCapDistSq = distSq;
413+
vecBestCapPoint = pCapPoint->GetAbsOrigin();
414+
}
415+
}
416+
}
417+
}
418+
419+
return vecBestCapPoint;
420+
}
421+
422+
//---------------------------------------------------------------------------------------------
423+
float CNEOBotCtgLoneWolf::GetDetpackDeployDistanceSq( CNEOBot *me )
424+
{
425+
float flArmingTime = CWeaponDetpack::GetArmingTime();
426+
return Square( MAX( 100.0f, flArmingTime * me->GetNormSpeed() ) );
427+
}
428+
429+
//---------------------------------------------------------------------------------------------
418430
// Helper for "UpdateLookAround" - inspired from how CNavArea CollectPotentiallyVisibleAreas works
419431
class CCollectPotentiallyVisibleAreas
420432
{
@@ -434,7 +446,18 @@ class CCollectPotentiallyVisibleAreas
434446
};
435447

436448
//---------------------------------------------------------------------------------------------
437-
ActionResult< CNEOBot > CNEOBotCtgLoneWolf::UpdateLookAround( CNEOBot *me, const Vector &anchorPos )
449+
bool CNEOBotCtgLoneWolf::UpdateGhostHandle( CNEOBot *me )
450+
{
451+
if ( !m_hGhost )
452+
{
453+
m_hGhost = dynamic_cast<CWeaponGhost*>( gEntList.FindEntityByClassname( nullptr, "weapon_ghost" ) );
454+
}
455+
456+
return ( m_hGhost != nullptr );
457+
}
458+
459+
//---------------------------------------------------------------------------------------------
460+
ActionResult< CNEOBot > CNEOBotCtgLoneWolf::UpdateLookAround( CNEOBot *me )
438461
{
439462
if ( !m_lookAroundTimer.HasStarted() || m_lookAroundTimer.IsElapsed() )
440463
{

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

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,23 +19,28 @@ class CNEOBotCtgLoneWolf : public Action< CNEOBot >
1919

2020
virtual const char *GetName( void ) const override { return "ctgLoneWolf"; }
2121

22-
private:
23-
PathFollower m_path;
22+
protected:
23+
static float GetDetpackDeployDistanceSq( CNEOBot *me );
24+
Vector GetNearestCapturePoint( CNEOBot *me, bool bEnemyCapPoint );
25+
bool UpdateGhostHandle( CNEOBot *me );
26+
ActionResult< CNEOBot > UpdateLookAround( CNEOBot *me );
27+
2428
CHandle<CWeaponGhost> m_hGhost;
2529
CountdownTimer m_repathTimer;
26-
CountdownTimer m_useAttemptTimer;
27-
bool m_bHasRetreatedFromGhost;
30+
PathFollower m_path;
2831

29-
Vector m_vecDropThreatPos;
30-
CHandle<CBaseEntity> m_hPursueTarget;
32+
private:
3133
bool m_bPursuingDropThreat;
3234

33-
ActionResult< CNEOBot > UpdateLookAround( CNEOBot *me, const Vector &anchorPos );
34-
CountdownTimer m_lookAroundTimer;
35-
CountdownTimer m_stalemateTimer;
35+
CHandle<CBaseEntity> m_hPursueTarget;
3636

3737
CountdownTimer m_capPointUpdateTimer;
38-
Vector m_closestCapturePoint;
38+
CountdownTimer m_lookAroundTimer;
39+
CountdownTimer m_stalemateTimer;
40+
CountdownTimer m_useAttemptTimer;
3941

4042
CUtlVector< CNavArea * > m_visibleAreas;
43+
44+
Vector m_closestCapturePoint;
45+
Vector m_vecDropThreatPos;
4146
};

0 commit comments

Comments
 (0)