Skip to content

Commit 38271f2

Browse files
committed
Bots investigate gunfire sounds while searching
1 parent db47650 commit 38271f2

5 files changed

Lines changed: 142 additions & 67 deletions

File tree

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

Lines changed: 9 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -5,44 +5,6 @@
55
#include "bot/neo_bot_path_compute.h"
66
#include "bot/behavior/neo_bot_jgr_juggernaut.h"
77

8-
//---------------------------------------------------------------------------------------------
9-
static CSound* SearchGunfireSounds(CNEOBot* me)
10-
{
11-
CSound* pClosestSound = NULL;
12-
float flClosestDistSqr = FLT_MAX;
13-
const Vector& vecMyOrigin = me->GetAbsOrigin();
14-
15-
int iSound = CSoundEnt::ActiveList();
16-
while (iSound != SOUNDLIST_EMPTY)
17-
{
18-
CSound* pSound = CSoundEnt::SoundPointerForIndex(iSound);
19-
if (!pSound)
20-
break;
21-
22-
if ((pSound->SoundType() & (SOUND_COMBAT | SOUND_BULLET_IMPACT)) && pSound->ValidateOwner())
23-
{
24-
// Don't listen to sounds I was responsible for
25-
if (pSound->m_hOwner.Get() == me->GetEntity())
26-
{
27-
iSound = pSound->NextSound();
28-
continue;
29-
}
30-
31-
// Search for the closest gunfire sounds
32-
float distSqr = (pSound->GetSoundOrigin() - vecMyOrigin).LengthSqr();
33-
if (distSqr < flClosestDistSqr)
34-
{
35-
flClosestDistSqr = distSqr;
36-
pClosestSound = pSound;
37-
}
38-
}
39-
40-
iSound = pSound->NextSound();
41-
}
42-
43-
return pClosestSound;
44-
}
45-
468
//---------------------------------------------------------------------------------------------
479
ActionResult< CNEOBot > CNEOBotJgrJuggernaut::OnStart( CNEOBot *me, Action< CNEOBot > *priorAction )
4810
{
@@ -67,30 +29,6 @@ ActionResult< CNEOBot > CNEOBotJgrJuggernaut::Update( CNEOBot *me, float interva
6729
if ( result.IsRequestingChange() || result.IsDone() )
6830
return result;
6931

70-
// Listen for gunfire
71-
if ( !m_soundSearchTimer.HasStarted() || m_soundSearchTimer.IsElapsed() )
72-
{
73-
m_soundSearchTimer.Start( 0.25f );
74-
75-
CSound* pBestSound = SearchGunfireSounds(me);
76-
if (pBestSound)
77-
{
78-
// Only change goal if recent gunfire is radically different than where I was going
79-
constexpr float flThresholdSqr = 200.0f * 200.0f;
80-
if (m_vGoalPos.DistToSqr(pBestSound->GetSoundOrigin()) > flThresholdSqr)
81-
{
82-
m_vGoalPos = pBestSound->GetSoundOrigin();
83-
// gunfire is not an entity target
84-
m_bGoingToTargetEntity = false;
85-
86-
if (CNEOBotPathCompute(me, m_path, m_vGoalPos, FASTEST_ROUTE))
87-
{
88-
return Continue();
89-
}
90-
}
91-
}
92-
}
93-
9432
return Continue();
9533
}
9634

@@ -102,16 +40,21 @@ void CNEOBotJgrJuggernaut::RecomputeSeekPath( CNEOBot *me )
10240
m_vGoalPos = vec3_origin;
10341

10442
// Listen for gunfights
105-
CSound* pBestSound = SearchGunfireSounds(me);
106-
if (pBestSound)
43+
const Vector& vGunfireLocation = SearchGunfireLocation(me);
44+
if (vGunfireLocation != vec3_invalid)
10745
{
108-
m_vGoalPos = pBestSound->GetSoundOrigin();
46+
m_vGoalPos = vGunfireLocation;
10947
m_bGoingToTargetEntity = false;
11048

111-
if (CNEOBotPathCompute(me, m_path, m_vGoalPos, FASTEST_ROUTE) && m_path.IsValid() && m_path.GetResult() == Path::COMPLETE_PATH)
49+
if (CNEOBotPathCompute(me, m_path, m_vGoalPos, DEFAULT_ROUTE) && m_path.IsValid() && m_path.GetResult() == Path::COMPLETE_PATH)
11250
{
11351
return;
11452
}
53+
else
54+
{
55+
// NEO Jank: Sound is unreachable so wait for it clear from the sound list
56+
m_soundSearchTimer.Start( 3.0f );
57+
}
11558
}
11659

11760
// If unaware of gunfights, patrol spawn points

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,5 @@ class CNEOBotJgrJuggernaut : public CNEOBotSeekAndDestroy
2323

2424
private:
2525
CUtlVector<CHandle<CBaseEntity>> m_jgrSpawns;
26-
CountdownTimer m_soundSearchTimer;
2726
};
2827
#endif // NEO_BOT_JGR_JUGGERNAUT_H

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
//---------------------------------------------------------------------------------------------
1515
ActionResult< CNEOBot > CNEOBotJgrSeek::Update( CNEOBot *me, float interval )
1616
{
17+
m_bInvestigateGunfire = false; // Focus on capturing JGR
18+
1719
if (NEORules()->GetGameType() != NEO_GAME_TYPE_JGR)
1820
{
1921
return Done( "Game mode is no longer JGR" );

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

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "bot/behavior/neo_bot_jgr_seek.h"
1010
#include "bot/neo_bot_path_compute.h"
1111
#include "nav_mesh.h"
12+
#include "soundent.h"
1213

1314
extern ConVar neo_bot_path_lookahead_range;
1415
extern ConVar neo_bot_offense_must_push_time;
@@ -18,6 +19,87 @@ ConVar neo_bot_debug_seek_and_destroy( "neo_bot_debug_seek_and_destroy", "0", FC
1819
ConVar neo_bot_disable_seek_and_destroy( "neo_bot_disable_seek_and_destroy", "0", FCVAR_CHEAT );
1920

2021

22+
//---------------------------------------------------------------------------------------------
23+
CSound* CNEOBotSeekAndDestroy::SearchGunfireSounds(CNEOBot* me, const Vector* currentGoalPos)
24+
{
25+
CSound* pClosestSound = nullptr;
26+
float flClosestDistSqr = FLT_MAX;
27+
const Vector& vecMyOrigin = me->GetAbsOrigin();
28+
29+
float flGoalDistSqr = FLT_MAX;
30+
if (currentGoalPos && *currentGoalPos != vec3_invalid)
31+
{
32+
flGoalDistSqr = vecMyOrigin.DistToSqr(*currentGoalPos);
33+
}
34+
35+
CSound* pSound = nullptr;
36+
for (int iSound = CSoundEnt::ActiveList(); iSound != SOUNDLIST_EMPTY; iSound = pSound->NextSound())
37+
{
38+
pSound = CSoundEnt::SoundPointerForIndex(iSound);
39+
if (!pSound)
40+
{
41+
break;
42+
}
43+
44+
if (!(pSound->SoundType() & SOUND_COMBAT))
45+
{
46+
continue;
47+
}
48+
49+
CBaseEntity *pOwner = pSound->m_hOwner.Get();
50+
51+
// Ignore non-player sounds and sounds we were responsible for
52+
if (!pOwner || !pOwner->IsPlayer() || pOwner == me)
53+
{
54+
continue;
55+
}
56+
57+
// NEO Jank: prevent bots from crowding teammates in teamplay
58+
if (NEORules()->IsTeamplay() && me->InSameTeam(pOwner))
59+
{
60+
continue;
61+
}
62+
63+
// Search for the closest gunfire sounds
64+
float distSqr = vecMyOrigin.DistToSqr(pSound->GetSoundOrigin());
65+
66+
// Only consider sounds that are closer than the current goal
67+
if (distSqr >= flGoalDistSqr)
68+
{
69+
continue;
70+
}
71+
72+
if (distSqr < flClosestDistSqr)
73+
{
74+
flClosestDistSqr = distSqr;
75+
pClosestSound = pSound;
76+
}
77+
}
78+
79+
return pClosestSound;
80+
}
81+
82+
//---------------------------------------------------------------------------------------------
83+
const Vector& CNEOBotSeekAndDestroy::SearchGunfireLocation(CNEOBot* me, const Vector* currentGoalPos)
84+
{
85+
CSound* pBestSound = SearchGunfireSounds(me, currentGoalPos);
86+
if (pBestSound)
87+
{
88+
if (currentGoalPos && *currentGoalPos != vec3_invalid)
89+
{
90+
// Only change goal if recent gunfire is radically different than where I was going
91+
constexpr float flThresholdSqr = 200.0f * 200.0f;
92+
if (currentGoalPos->DistToSqr(pBestSound->GetSoundOrigin()) <= flThresholdSqr)
93+
{
94+
return vec3_invalid;
95+
}
96+
}
97+
return pBestSound->GetSoundOrigin();
98+
}
99+
100+
return vec3_invalid;
101+
}
102+
21103
//---------------------------------------------------------------------------------------------
22104
CNEOBotSeekAndDestroy::CNEOBotSeekAndDestroy( float duration )
23105
{
@@ -161,6 +243,27 @@ ActionResult< CNEOBot > CNEOBotSeekAndDestroy::UpdateCommon( CNEOBot *me, float
161243

162244
RecomputeSeekPath( me );
163245
}
246+
else if ( m_bInvestigateGunfire && (!m_soundSearchTimer.HasStarted() || m_soundSearchTimer.IsElapsed()) )
247+
{
248+
m_soundSearchTimer.Start( 0.25f );
249+
250+
const Vector& vGunfireLocation = SearchGunfireLocation(me, &m_vGoalPos);
251+
if (vGunfireLocation != vec3_invalid)
252+
{
253+
m_vGoalPos = vGunfireLocation;
254+
m_bGoingToTargetEntity = false;
255+
256+
if (CNEOBotPathCompute(me, m_path, m_vGoalPos, DEFAULT_ROUTE))
257+
{
258+
m_repathTimer.Start( 45.0f );
259+
}
260+
else
261+
{
262+
// NEO Jank: Sound is unreachable so wait for it clear from the sound list
263+
m_soundSearchTimer.Start( 3.0f );
264+
}
265+
}
266+
}
164267

165268
return Continue();
166269
}
@@ -363,6 +466,28 @@ void CNEOBotSeekAndDestroy::RecomputeSeekPath( CNEOBot *me )
363466
}
364467
}
365468
#endif
469+
470+
// Listen for gunfights
471+
if (m_bInvestigateGunfire)
472+
{
473+
const Vector& vGunfireLocation = SearchGunfireLocation(me);
474+
if (vGunfireLocation != vec3_invalid)
475+
{
476+
m_vGoalPos = vGunfireLocation;
477+
m_bGoingToTargetEntity = false;
478+
479+
if (CNEOBotPathCompute(me, m_path, m_vGoalPos, DEFAULT_ROUTE) && m_path.IsValid() && m_path.GetResult() == Path::COMPLETE_PATH)
480+
{
481+
return;
482+
}
483+
else
484+
{
485+
// NEO Jank: Sound is unreachable so wait for it clear from the sound list
486+
m_soundSearchTimer.Start( 3.0f );
487+
}
488+
}
489+
}
490+
366491
// Fallback and roam random spawn points if we have all weapons.
367492
{
368493
CNextSpawnFilter spawnFilter( me, 128.0f );

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include "Path/NextBotChasePath.h"
44

5+
class CSound;
56

67
//
78
// Roam around the map attacking enemies
@@ -36,11 +37,16 @@ class CNEOBotSeekAndDestroy : public Action< CNEOBot >
3637

3738
virtual void RecomputeSeekPath( CNEOBot *me );
3839

40+
static CSound* SearchGunfireSounds(CNEOBot* me, const Vector* currentGoalPos = nullptr);
41+
static const Vector& SearchGunfireLocation(CNEOBot* me, const Vector* currentGoalPos = nullptr);
42+
3943
PathFollower m_path;
4044
CountdownTimer m_repathTimer;
45+
CountdownTimer m_soundSearchTimer;
4146
CountdownTimer m_itemStolenTimer;
4247
EHANDLE m_hTargetEntity;
4348
bool m_bGoingToTargetEntity = false;
49+
bool m_bInvestigateGunfire = true;
4450
Vector m_vGoalPos = vec3_origin;
4551
bool m_bTimerElapsed = false;
4652
bool m_bOverrideApproach = false;

0 commit comments

Comments
 (0)