Skip to content
Merged
8 changes: 8 additions & 0 deletions src/game/server/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1455,6 +1455,14 @@ target_sources_grouped(
neo/bot/behavior/neo_bot_ctg_seek.h
neo/bot/behavior/neo_bot_dead.cpp
neo/bot/behavior/neo_bot_dead.h
neo/bot/behavior/neo_bot_grenade_dispatch.cpp
neo/bot/behavior/neo_bot_grenade_dispatch.h
neo/bot/behavior/neo_bot_grenade_throw.cpp
neo/bot/behavior/neo_bot_grenade_throw.h
neo/bot/behavior/neo_bot_grenade_throw_frag.cpp
neo/bot/behavior/neo_bot_grenade_throw_frag.h
neo/bot/behavior/neo_bot_grenade_throw_smoke.cpp
neo/bot/behavior/neo_bot_grenade_throw_smoke.h
neo/bot/behavior/neo_bot_jgr_capture.cpp
neo/bot/behavior/neo_bot_jgr_capture.h
neo/bot/behavior/neo_bot_jgr_enemy.cpp
Expand Down
12 changes: 12 additions & 0 deletions src/game/server/neo/bot/behavior/neo_bot_attack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "team_control_point_master.h"
#include "bot/neo_bot.h"
#include "bot/behavior/neo_bot_attack.h"
#include "bot/behavior/neo_bot_grenade_dispatch.h"
#include "bot/neo_bot_path_compute.h"

#include "nav_mesh.h"
Expand Down Expand Up @@ -79,6 +80,17 @@ ActionResult< CNEOBot > CNEOBotAttack::Update( CNEOBot *me, float interval )
// pre-cloak needs more thermoptic budget when chasing threats
me->EnableCloak(6.0f);

// Consider throwing a grenade
if ( !m_grenadeThrowCooldownTimer.HasStarted() || m_grenadeThrowCooldownTimer.IsElapsed() )
{
Action<CNEOBot> *pGrenadeBehavior = CNEOBotGrenadeDispatch::ChooseGrenadeThrowBehavior( me, threat );
if ( pGrenadeBehavior )
{
m_grenadeThrowCooldownTimer.Start( sv_neo_bot_grenade_throw_cooldown.GetFloat() );
return SuspendFor( pGrenadeBehavior, "Throwing grenade before chasing threat!" );
}
}

if ( isUsingCloseRangeWeapon )
{
CNEOBotPathUpdateChase( me, m_chasePath, threat->GetEntity(), FASTEST_ROUTE );
Expand Down
1 change: 1 addition & 0 deletions src/game/server/neo/bot/behavior/neo_bot_attack.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,6 @@ class CNEOBotAttack : public Action< CNEOBot >
private:
PathFollower m_path;
ChasePath m_chasePath;
CountdownTimer m_grenadeThrowCooldownTimer;
CountdownTimer m_repathTimer;
};
123 changes: 123 additions & 0 deletions src/game/server/neo/bot/behavior/neo_bot_grenade_dispatch.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
#include "cbase.h"
#include "neo_gamerules.h"
#include "neo_player.h"
#include "bot/neo_bot.h"
#include "bot/behavior/neo_bot_grenade_dispatch.h"
#include "bot/behavior/neo_bot_grenade_throw_frag.h"
#include "bot/behavior/neo_bot_grenade_throw_smoke.h"
#include "weapon_neobasecombatweapon.h"
#include "weapon_grenade.h"
#include "weapon_smokegrenade.h"

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");

//---------------------------------------------------------------------------------------------
Action< CNEOBot > *CNEOBotGrenadeDispatch::ChooseGrenadeThrowBehavior( const CNEOBot *me, const CKnownEntity *threat )
{
if (!sv_neo_bot_grenade_use_frag.GetBool() && !sv_neo_bot_grenade_use_smoke.GetBool())
{
return nullptr;
}

if ( !threat || !threat->GetEntity() || !threat->GetEntity()->IsPlayer() || !threat->GetEntity()->IsAlive() )
{
return nullptr;
}

// Prefer shooting if we have a clear line of fire
if ( me->IsLineOfFireClear( threat->GetEntity(), CNEOBot::LINE_OF_FIRE_FLAGS_DEFAULT ) )
{
return nullptr;
}

CWeaponGrenade *pFragGrenade = nullptr;
CWeaponSmokeGrenade *pSmokeGrenade = nullptr;

int iWeaponCount = me->WeaponCount();
for ( int i=0; i<iWeaponCount; ++i )
{
CBaseCombatWeapon *pWep = me->GetWeapon( i );
if ( !pWep )
{
continue;
}

CNEOBaseCombatWeapon *pNeoWep = static_cast< CNEOBaseCombatWeapon * >( pWep );

if ( !pNeoWep->HasPrimaryAmmo() )
{
continue;
}

auto bits = pNeoWep->GetNeoWepBits();
if ( sv_neo_bot_grenade_use_frag.GetBool() && (bits & NEO_WEP_FRAG_GRENADE) )
{
pFragGrenade = static_cast< CWeaponGrenade * >( pNeoWep );
if ( pSmokeGrenade )
{
break; // found both
}
}
else if ( sv_neo_bot_grenade_use_smoke.GetBool() && (bits & NEO_WEP_SMOKE_GRENADE) )
{
pSmokeGrenade = static_cast< CWeaponSmokeGrenade * >( pNeoWep );
if ( pFragGrenade )
{
break; // found both
}
}
}

if ( !pFragGrenade && !pSmokeGrenade )
{
return nullptr;
}

// Should I toss a smoke grenade?
if ( pSmokeGrenade )
{
for ( int i = 1; i <= gpGlobals->maxClients; i++ )
{
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 )
{
// Avoid blocking the vision of a friendly human
// (Bots benefit from concealment without the disorientation)
return nullptr;
}
}
else
{
if ( pPlayer->GetClass() == NEO_CLASS_SUPPORT )
{
// Avoid giving an enemy with thermal vision a free smoke screen
return nullptr;
}
}
}

return new CNEOBotGrenadeThrowSmoke( pSmokeGrenade, threat );
}

// Should I toss a frag grenade?
if ( pFragGrenade )
{
if ( !CNEOBotGrenadeThrowFrag::IsFragSafe( me, threat->GetLastKnownPosition() ) )
{
return nullptr;
}

return new CNEOBotGrenadeThrowFrag( pFragGrenade, threat );
}

return nullptr;
}
20 changes: 20 additions & 0 deletions src/game/server/neo/bot/behavior/neo_bot_grenade_dispatch.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#ifndef NEO_BOT_GRENADE_DISPATCH_H
#define NEO_BOT_GRENADE_DISPATCH_H
#ifdef _WIN32
#pragma once
#endif

#include "neo_bot_behavior.h"

class CNEOBot;
class CKnownEntity;

extern ConVar sv_neo_bot_grenade_throw_cooldown;

class CNEOBotGrenadeDispatch
{
public:
static Action< CNEOBot > *ChooseGrenadeThrowBehavior( const CNEOBot *me, const CKnownEntity *threat );
};

#endif // NEO_BOT_GRENADE_DISPATCH_H
Loading