Skip to content

Commit f6b8450

Browse files
committed
Penalize bot nav penalties based on weapon limits
- Bots with shotguns shy away from NavAreas that have many visibility connections - Bots with pistol caliber weapons slightly avoid areas but to a lesser degree - Bots with scoped/semi-auto weapons favor exposed NavAreas with long sightlines - Generally, a minor penalty is applied for NavArea exposure for bots to avoid wide open exposed NavAreas
1 parent 36087ff commit f6b8450

6 files changed

Lines changed: 116 additions & 2 deletions

File tree

src/game/server/nav_area.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,8 +258,37 @@ CNavArea::CNavArea( void )
258258
m_funcNavCostVector.RemoveAll();
259259

260260
m_nVisTestCounter = (uint32)-1;
261+
262+
#ifdef NEO
263+
m_visibleAreaCount = 0;
264+
#endif
261265
}
262266

267+
268+
#ifdef NEO
269+
//--------------------------------------------------------------------------------------------------------------
270+
struct CountPotentiallyVisibleAreas
271+
{
272+
int count;
273+
CountPotentiallyVisibleAreas() : count(0) {}
274+
bool operator()( CNavArea* area )
275+
{
276+
count++;
277+
return true;
278+
}
279+
};
280+
281+
282+
//--------------------------------------------------------------------------------------------------------------
283+
void CNavArea::ComputePotentiallyVisibleAreaCount()
284+
{
285+
CountPotentiallyVisibleAreas counter;
286+
const_cast<CNavArea*>(this)->ForAllPotentiallyVisibleAreas( counter );
287+
m_visibleAreaCount = counter.count;
288+
}
289+
#endif
290+
291+
263292
//--------------------------------------------------------------------------------------------------------------
264293
/**
265294
* Assumes Z is flat

src/game/server/nav_area.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -520,6 +520,10 @@ class CNavArea : protected CNavAreaCriticalData
520520
virtual bool IsPartiallyVisible( const Vector &eye, const CBaseEntity *ignore = NULL ) const; // return true if any portion of the area is visible from given eyepoint (CPU intensive)
521521

522522
virtual bool IsPotentiallyVisible( const CNavArea *area ) const; // return true if given area is potentially visible from somewhere in this area (very fast)
523+
#ifdef NEO
524+
int GetPotentiallyVisibleAreaCount() const { return m_visibleAreaCount; }
525+
void ComputePotentiallyVisibleAreaCount();
526+
#endif
523527
virtual bool IsPotentiallyVisibleToTeam( int team ) const; // return true if any portion of this area is visible to anyone on the given team (very fast)
524528

525529
virtual bool IsCompletelyVisible( const CNavArea *area ) const; // return true if given area is completely visible from somewhere in this area (very fast)
@@ -662,6 +666,9 @@ class CNavArea : protected CNavAreaCriticalData
662666
*/
663667

664668
static unsigned int m_nextID; // used to allocate unique IDs
669+
#ifdef NEO
670+
int m_visibleAreaCount;
671+
#endif
665672
unsigned int m_id; // unique area ID
666673
unsigned int m_debugid;
667674

src/game/server/nav_file.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1647,6 +1647,14 @@ NavErrorType CNavMesh::PostLoad( unsigned int version )
16471647
area->PostLoad();
16481648
}
16491649

1650+
#ifdef NEO
1651+
FOR_EACH_VEC( TheNavAreas, vit )
1652+
{
1653+
CNavArea *area = TheNavAreas[ vit ];
1654+
area->ComputePotentiallyVisibleAreaCount();
1655+
}
1656+
#endif
1657+
16501658
// allow hiding spots to compute information
16511659
FOR_EACH_VEC( TheHidingSpots, hit )
16521660
{

src/game/server/neo/bot/neo_bot_path_cost.cpp

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,34 @@
55
#include "neo_bot_locomotion.h"
66
#include "nav_mesh.h"
77
#include "neo_bot_path_reservation.h"
8+
#include "weapon_neobasecombatweapon.h"
89

910
extern ConVar neo_bot_path_reservation_enable;
1011

1112
ConVar neo_bot_path_around_friendly_cooldown("neo_bot_path_around_friendly_cooldown", "2.0", FCVAR_CHEAT,
1213
"How often to check for friendly path dispersion", false, 0, false, 60);
1314

14-
ConVar neo_bot_path_penalty_jump_multiplier("neo_bot_path_penalty_jump_multiplier", "100.0", FCVAR_CHEAT,
15+
ConVar neo_bot_path_penalty_jump_multiplier("neo_bot_path_penalty_jump_multiplier", "1000.0", FCVAR_CHEAT,
1516
"Maximum penalty multiplier for jump height changes in pathfinding", false, 0.01f, false, 1000.0f);
1617

1718
ConVar neo_bot_path_penalty_ladder_multiplier("neo_bot_path_penalty_ladder_multiplier", "3.0", FCVAR_CHEAT,
1819
"Penalty multiplier for ladder traversal in pathfinding", true, 0.1f, true, 100.0f);
1920

21+
ConVar neo_bot_path_penalty_exposure_base("neo_bot_path_penalty_exposure_base", "5.0", FCVAR_CHEAT,
22+
"General additional penalty per visible area for bots to avoid exposed areas", true, 0.0f, false, 0.0f);
23+
24+
ConVar neo_bot_path_penalty_exposure_pistol("neo_bot_path_penalty_exposure_pistol", "10.0", FCVAR_CHEAT,
25+
"Additional penalty per visible area for bots wielding pistol caliber weapons", true, 0.0f, false, 0.0f);
26+
27+
ConVar neo_bot_path_penalty_exposure_shotgun("neo_bot_path_penalty_exposure_shotgun", "20.0", FCVAR_CHEAT,
28+
"Additional penalty per visible area for shotgun-wielding bots", true, 0.0f, false, 0.0f);
29+
30+
ConVar neo_bot_path_penalty_exposure_inverse_base_battle_rifle("neo_bot_path_penalty_exposure_inverse_base_battle_rifle", "500.0", FCVAR_CHEAT,
31+
"Base penalty for calculating inverse traversal penalty for semi-auto battle rifles", true, 1.0f, false, 0.0f);
32+
33+
ConVar neo_bot_path_penalty_exposure_inverse_base_scoped("neo_bot_path_penalty_exposure_inverse_base_scoped", "1000.0", FCVAR_CHEAT,
34+
"Base penalty for calculating inverse traversal penalty for scoped weapons", true, 1.0f, false, 0.0f);
35+
2036
//-------------------------------------------------------------------------------------------------
2137
CNEOBotPathCost::CNEOBotPathCost(CNEOBot* me, RouteType routeType)
2238
{
@@ -126,6 +142,50 @@ float CNEOBotPathCost::operator()(CNavArea* baseArea, CNavArea* fromArea, const
126142
cost += CNEOBotPathReservations()->GetPredictedFriendlyPathCount(area->GetID(), m_me->GetTeamNumber()) * neo_bot_path_reservation_penalty.GetFloat();
127143
cost += CNEOBotPathReservations()->GetAreaAvoidPenalty(area->GetID());
128144

145+
// Weapon range penalties
146+
CNEOBaseCombatWeapon* myWeapon = ToNEOWeapon(m_me->GetActiveWeapon());
147+
const int nWeaponBits = myWeapon->GetNeoWepBits();
148+
if (myWeapon && (nWeaponBits & NEO_WEP_FIREARM))
149+
{
150+
constexpr int nShotgunBits = NEO_WEP_AA13 | NEO_WEP_SUPA7;
151+
constexpr int nBattleRifleBits = NEO_WEP_M41 | NEO_WEP_M41_S;
152+
constexpr int nPistolCaliberBits = NEO_WEP_MILSO | NEO_WEP_TACHI | NEO_WEP_KYLA
153+
| NEO_WEP_MPN | NEO_WEP_MPN_S | NEO_WEP_JITTE | NEO_WEP_JITTE_S | NEO_WEP_SRM | NEO_WEP_SRM_S;
154+
155+
const int visibleAreaCount = area->GetPotentiallyVisibleAreaCount();
156+
157+
if (nWeaponBits & nPistolCaliberBits)
158+
{
159+
// Weapons that don't have max first shot accuracy
160+
const float exposurePenalty = neo_bot_path_penalty_exposure_pistol.GetFloat();
161+
dist += visibleAreaCount * exposurePenalty;
162+
}
163+
else if (nWeaponBits & nShotgunBits)
164+
{
165+
// Weapons that have spread that can't hit long range targets
166+
const float exposurePenalty = neo_bot_path_penalty_exposure_shotgun.GetFloat();
167+
dist += visibleAreaCount * exposurePenalty;
168+
}
169+
else if (nWeaponBits & nBattleRifleBits)
170+
{
171+
// Weapons that benefit from medium sightlines that can see many NavAreas
172+
const float baseline_penalty = neo_bot_path_penalty_exposure_inverse_base_battle_rifle.GetFloat();
173+
dist += baseline_penalty / visibleAreaCount;
174+
}
175+
else if (nWeaponBits & NEO_WEP_SCOPEDWEAPON)
176+
{
177+
// Weapons that benefit from long sightlines that can see many NavAreas
178+
const float baseline_penalty = neo_bot_path_penalty_exposure_inverse_base_scoped.GetFloat();
179+
dist += baseline_penalty / visibleAreaCount;
180+
}
181+
else
182+
{
183+
// Generally avoiding exposed areas when traversing a wide open area
184+
const float exposurePenalty = neo_bot_path_penalty_exposure_base.GetFloat();
185+
dist += visibleAreaCount * exposurePenalty;
186+
}
187+
}
188+
129189
if (m_routeType == SAFEST_ROUTE)
130190
{
131191
// NEO Jank Cheat: Incorporate enemy bot paths so that we don't run directly into their line of fire

src/game/server/neo/bot/neo_bot_path_reservation.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ ConVar neo_bot_path_reservation_avoid_penalty_enable("neo_bot_path_reservation_a
2929
ConVar neo_bot_path_reservation_killed_penalty("neo_bot_path_reservation_killed_penalty", "10", FCVAR_NONE,
3030
"Path selection penalty added to a nav area each time a bot dies moving through that area.", true, 0, false, 0);
3131

32-
ConVar neo_bot_path_reservation_onstuck_penalty("neo_bot_path_reservation_onstuck_penalty", "10000", FCVAR_NONE,
32+
ConVar neo_bot_path_reservation_onstuck_penalty("neo_bot_path_reservation_onstuck_penalty", "1000", FCVAR_NONE,
3333
"Path selection penalty added to a nav area each time a bot gets stuck moving through that area.", true, 0, false, 0);
3434

3535

src/game/shared/neo/weapons/weapon_neobasecombatweapon.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,4 +254,14 @@ class CNEOBaseCombatWeapon : public CBaseHL2MPCombatWeapon
254254

255255
};
256256

257+
258+
inline CNEOBaseCombatWeapon *ToNEOWeapon(CBaseCombatWeapon *pWeapon)
259+
{
260+
if (!pWeapon)
261+
{
262+
return nullptr;
263+
}
264+
return dynamic_cast<CNEOBaseCombatWeapon*>(pWeapon);
265+
}
266+
257267
#endif // WEAPON_NEO_BASECOMBATWEAPON_SHARED_H

0 commit comments

Comments
 (0)