Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/game/server/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1589,6 +1589,11 @@ target_sources_grouped(
neo/bot/behavior/neo_bot_ctg_seek.cpp
neo/bot/behavior/neo_bot_ctg_seek.h
neo/bot/behavior/neo_bot_dead.h
neo/bot/behavior/neo_bot_detpack_deploy.cpp
neo/bot/behavior/neo_bot_detpack_deploy.h
neo/bot/behavior/neo_bot_detpack_trigger.cpp
neo/bot/behavior/neo_bot_detpack_trigger.h
neo/bot/behavior/neo_bot_grenade_dispatch.cpp
neo/bot/behavior/neo_bot_grenade_dispatch.h
neo/bot/behavior/neo_bot_grenade_throw.h
neo/bot/behavior/neo_bot_grenade_throw_frag.h
Expand Down
5 changes: 5 additions & 0 deletions src/game/server/neo/bot/behavior/neo_bot_ctg_lone_wolf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "bot/behavior/neo_bot_ctg_lone_wolf.h"
#include "bot/behavior/neo_bot_ctg_lone_wolf_ambush.h"
#include "bot/behavior/neo_bot_ctg_lone_wolf_seek.h"
#include "bot/behavior/neo_bot_detpack_deploy.h"
#include "bot/neo_bot_path_compute.h"
#include "neo_gamerules.h"
#include "neo_ghost_cap_point.h"
Expand Down Expand Up @@ -57,6 +58,10 @@ ActionResult< CNEOBot > CNEOBotCtgLoneWolf::Update( CNEOBot *me, float interval
const CNavArea *myArea = me->GetLastKnownArea();
if ( ghostArea && myArea && ghostArea->IsPotentiallyVisible( myArea ) )
{
if ( pDetpackWeapon && !pDetpackWeapon->m_bThisDetpackHasBeenThrown && NEORules()->m_pGhost )
{
return ChangeTo( new CNEOBotDetpackDeploy( NEORules()->GetGhostPos(), new CNEOBotCtgLoneWolfAmbush() ), "Moving to plant detpack" );
}
return ChangeTo( new CNEOBotCtgLoneWolfAmbush(), "Waiting in ambush near ghost" );
}

Expand Down
218 changes: 218 additions & 0 deletions src/game/server/neo/bot/behavior/neo_bot_detpack_deploy.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
#include "cbase.h"
#include "bot/neo_bot.h"
#include "bot/neo_bot_path_compute.h"
#include "bot/behavior/neo_bot_attack.h"
#include "bot/behavior/neo_bot_ctg_lone_wolf_seek.h"
#include "bot/behavior/neo_bot_detpack_deploy.h"
#include "neo_detpack.h"
#include "weapon_detpack.h"

//---------------------------------------------------------------------------------------------
CNEOBotDetpackDeploy::CNEOBotDetpackDeploy( const Vector &targetPos, Action< CNEOBot > *nextAction )
: m_targetPos( targetPos ), m_nextAction( nextAction ), m_flDeployDistSq( 0.0f )
{
m_bPushedWeapon = false;
m_losTimer.Invalidate();
}


//---------------------------------------------------------------------------------------------
ActionResult< CNEOBot > CNEOBotDetpackDeploy::OnStart( CNEOBot *me, Action< CNEOBot > *priorAction )
{
m_hDetpackWeapon = assert_cast< CWeaponDetpack* >( me->Weapon_OwnsThisType( "weapon_remotedet" ) );
if ( !m_hDetpackWeapon )
{
if (m_nextAction != nullptr)
{
return ChangeTo( m_nextAction, "No detpack weapon, transitioning to next action" );
}
return Done( "No detpack weapon found" );
}

me->PushRequiredWeapon( m_hDetpackWeapon );
m_bPushedWeapon = true;

// Ignore enemy to prevent weapon handling interference with detpack deployment
me->StopLookingAroundForEnemies();
me->SetAttribute( CNEOBot::IGNORE_ENEMIES );

m_expiryTimer.Start( 10.0f );
m_repathTimer.Invalidate();

m_flDeployDistSq = Square( MAX( 100.0f, CWeaponDetpack::GetArmingTime() * me->GetNormSpeed() ) );

return Continue();
}

//---------------------------------------------------------------------------------------------
ActionResult< CNEOBot > CNEOBotDetpackDeploy::Update( CNEOBot *me, float interval )
{
if ( !m_hDetpackWeapon )
{
if ( m_nextAction )
{
return ChangeTo( m_nextAction, "No detpack weapon, transitioning to next action" );
}
return Done( "No detpack weapon" );
}

if ( m_expiryTimer.IsElapsed() )
{
if ( m_nextAction )
{
return ChangeTo( m_nextAction, "Detpack deploy timer expired, transitioning to next action" );
}
return Done( "Detpack deploy timer expired" );
}

if ( m_hDetpackWeapon->m_bThisDetpackHasBeenThrown )
{
if ( m_nextAction )
{
return ChangeTo( m_nextAction, "Detpack deployed, transitioning to next action" );
}
return Done( "Detpack deployed" );
}

const CKnownEntity* threat = me->GetVisionInterface()->GetPrimaryKnownThreat( true );
if ( threat && threat->GetEntity() )
{
if (m_nextAction != nullptr)
{
return ChangeTo( m_nextAction, "Interrupting detpack deploy to let next action handle enemy" );
}
return ChangeTo( new CNEOBotAttack(), "Engaging enemy encountered while deploying detpack" );
}

float flDistToTargetSq = me->GetAbsOrigin().DistToSqr( m_targetPos );
if ( flDistToTargetSq < m_flDeployDistSq )
{
if ( me->GetActiveWeapon() == m_hDetpackWeapon )
{
if ( !m_losTimer.HasStarted() || m_losTimer.IsElapsed() )
{
if ( me->GetVisionInterface()->IsLineOfSightClear( m_targetPos ) )
{
CBaseEntity *pEnts[256];
int numEnts = UTIL_EntitiesInSphere( pEnts, 256, me->GetAbsOrigin(), NEO_DETPACK_DAMAGE_RADIUS, 0 );
bool bDetpackNear = false;
for ( int i = 0; i < numEnts; ++i )
{
if ( pEnts[i] && FClassnameIs( pEnts[i], "neo_deployed_detpack" ) )
{
bDetpackNear = true;
break;
}
}

if ( bDetpackNear )
{
if ( m_nextAction )
{
return ChangeTo( m_nextAction, "Skipping detpack deploy: in blast radius of another detpack" );
}
return Done( "Aborting detpack deploy: in blast radius of another detpack" );
}

me->PressFireButton();

if ( flDistToTargetSq < Square( 64.0f ) )
{
m_path.Invalidate();
m_repathTimer.Start( 10.0f );
}
}

m_losTimer.Start( RandomFloat( 0.2f, 0.4f ) );
}
}
}

if ( !m_path.IsValid() )
{
if ( !m_repathTimer.HasStarted() || m_repathTimer.IsElapsed() )
{
CNEOBotPathCompute( me, m_path, m_targetPos, FASTEST_ROUTE );
m_repathTimer.Start( RandomFloat( 1.0f, 2.0f ) );
}
}
else
{
m_path.Update( me );
}

return Continue();
}


//---------------------------------------------------------------------------------------------
void CNEOBotDetpackDeploy::OnEnd( CNEOBot *me, Action< CNEOBot > *nextAction )
{
if ( m_bPushedWeapon )
{
me->PopRequiredWeapon();
m_bPushedWeapon = false;
}
me->StartLookingAroundForEnemies();
me->ClearAttribute( CNEOBot::IGNORE_ENEMIES );

if ( m_hDetpackWeapon && m_hDetpackWeapon->m_bThisDetpackHasBeenThrown )
{
me->EquipBestWeaponForThreat( me->GetVisionInterface()->GetPrimaryKnownThreat( true ) );
}
}


//---------------------------------------------------------------------------------------------
ActionResult<CNEOBot> CNEOBotDetpackDeploy::OnSuspend( CNEOBot *me, Action<CNEOBot> *interruptingAction )
{
if (m_nextAction != nullptr)
{
return ChangeTo( m_nextAction, "Detpack deploy suspend cancelled, transitioning to next action" );
}

return Done( "Detpack deploy suspended, situation will likely become stale." );
// OnEnd will get called after Done
}

//---------------------------------------------------------------------------------------------
ActionResult<CNEOBot> CNEOBotDetpackDeploy::OnResume( CNEOBot *me, Action<CNEOBot> *interruptingAction )
{
if (m_nextAction != nullptr)
{
return ChangeTo( m_nextAction, "Detpack deploy resume cancelled, transitioning to next action" );
}

return Done( "Detpack deploy resumed, situation is likely stale." );
// OnEnd will get called after Done
}

//---------------------------------------------------------------------------------------------
EventDesiredResult< CNEOBot > CNEOBotDetpackDeploy::OnStuck( CNEOBot *me )
{
if (m_nextAction != nullptr)
{
return TryChangeTo( m_nextAction, RESULT_CRITICAL, "Detpack deploy stuck, transitioning to next action" );
}

return TryDone( RESULT_CRITICAL, "Detpack deploy stuck, situation will likely become stale." );
// OnEnd will get called after Done
}

//---------------------------------------------------------------------------------------------
EventDesiredResult< CNEOBot > CNEOBotDetpackDeploy::OnMoveToSuccess( CNEOBot *me, const Path *path )
{
return TryContinue();
}

//---------------------------------------------------------------------------------------------
EventDesiredResult< CNEOBot > CNEOBotDetpackDeploy::OnMoveToFailure( CNEOBot *me, const Path *path, MoveToFailureType reason )
{
if (m_nextAction != nullptr)
{
return TryChangeTo( m_nextAction, RESULT_CRITICAL, "Detpack deploy move to failure, transitioning to next action" );
}

return TryDone( RESULT_CRITICAL, "Detpack deploy move to failure, situation will likely become stale." );
// OnEnd will get called after Done
}
35 changes: 35 additions & 0 deletions src/game/server/neo/bot/behavior/neo_bot_detpack_deploy.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#pragma once

#include "bot/neo_bot.h"

class CWeaponDetpack;

//--------------------------------------------------------------------------------------------------------
class CNEOBotDetpackDeploy : public Action< CNEOBot >
{
public:
CNEOBotDetpackDeploy( const Vector &targetPos, Action< CNEOBot > *nextAction = nullptr );

virtual ActionResult< CNEOBot > OnStart( CNEOBot *me, Action< CNEOBot > *priorAction ) override;
virtual ActionResult< CNEOBot > Update( CNEOBot *me, float interval ) override;
virtual ActionResult< CNEOBot > OnSuspend( CNEOBot *me, Action< CNEOBot > *interruptingAction ) override;
virtual ActionResult< CNEOBot > OnResume( CNEOBot *me, Action< CNEOBot > *interruptingAction ) override;
virtual void OnEnd( CNEOBot *me, Action< CNEOBot > *nextAction ) override;

virtual EventDesiredResult< CNEOBot > OnStuck( CNEOBot *me ) override;
virtual EventDesiredResult< CNEOBot > OnMoveToSuccess( CNEOBot *me, const Path *path ) override;
virtual EventDesiredResult< CNEOBot > OnMoveToFailure( CNEOBot *me, const Path *path, MoveToFailureType reason ) override;

virtual const char *GetName( void ) const override { return "DetpackDeploy"; }

private:
bool m_bPushedWeapon;
float m_flDeployDistSq;
Action< CNEOBot > *m_nextAction;
CHandle< CWeaponDetpack > m_hDetpackWeapon;
CountdownTimer m_expiryTimer;
CountdownTimer m_losTimer;
CountdownTimer m_repathTimer;
PathFollower m_path;
Vector m_targetPos;
};
82 changes: 82 additions & 0 deletions src/game/server/neo/bot/behavior/neo_bot_detpack_trigger.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#include "cbase.h"
#include "bot/neo_bot.h"
#include "bot/behavior/neo_bot_detpack_trigger.h"
#include "weapon_detpack.h"

//---------------------------------------------------------------------------------------------
CNEOBotDetpackTrigger::CNEOBotDetpackTrigger( void )
{
m_hDetpackWeapon = nullptr;
m_bPushedWeapon = false;
}

//---------------------------------------------------------------------------------------------
ActionResult< CNEOBot > CNEOBotDetpackTrigger::OnStart( CNEOBot *me, Action< CNEOBot > *priorAction )
{
m_hDetpackWeapon = assert_cast<CWeaponDetpack*>( me->Weapon_OwnsThisType( "weapon_remotedet" ) );
if ( m_hDetpackWeapon )
{
me->PushRequiredWeapon( m_hDetpackWeapon );
m_bPushedWeapon = true;
}
else
{
return Done( "No detpack weapon found" );
}

// Ignore enemy to prevent weapon handling interference with detpack trigger
me->StopLookingAroundForEnemies();
me->SetAttribute( CNEOBot::IGNORE_ENEMIES );

m_expiryTimer.Start( 5.0f );

return Continue();
}

//---------------------------------------------------------------------------------------------
ActionResult< CNEOBot > CNEOBotDetpackTrigger::Update( CNEOBot *me, float interval )
{
if ( m_expiryTimer.IsElapsed() )
{
return Done( "Detpack trigger timer expired" );
}

if ( !m_hDetpackWeapon || !m_hDetpackWeapon->m_bThisDetpackHasBeenThrown || m_hDetpackWeapon->m_bRemoteHasBeenTriggered )
{
return Done( "Detpack triggered or invalid" );
}

if ( me->GetActiveWeapon() == m_hDetpackWeapon && gpGlobals->curtime >= m_hDetpackWeapon->m_flNextPrimaryAttack )
{
me->PressFireButton();
}

return Continue();
}

//---------------------------------------------------------------------------------------------
void CNEOBotDetpackTrigger::OnEnd( CNEOBot *me, Action< CNEOBot > *nextAction )
{
// Restore looking and weapon handling behaviors
if ( m_bPushedWeapon )
{
me->PopRequiredWeapon();
m_bPushedWeapon = false;
}
me->StartLookingAroundForEnemies();
me->ClearAttribute( CNEOBot::IGNORE_ENEMIES );
}

//---------------------------------------------------------------------------------------------
ActionResult<CNEOBot> CNEOBotDetpackTrigger::OnSuspend( CNEOBot *me, Action<CNEOBot> *interruptingAction )
{
return Done( "OnSuspend: Cancel out of detpack trigger behavior, situation will likely become stale." );
// OnEnd will get called after Done
}

//---------------------------------------------------------------------------------------------
ActionResult<CNEOBot> CNEOBotDetpackTrigger::OnResume( CNEOBot *me, Action<CNEOBot> *interruptingAction )
{
return Done( "OnResume: Cancel out of detpack trigger behavior, situation is likely stale." );
// OnEnd will get called after Done
}
26 changes: 26 additions & 0 deletions src/game/server/neo/bot/behavior/neo_bot_detpack_trigger.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#pragma once

#include "bot/neo_bot.h"

class CWeaponDetpack;

//-----------------------------------------------------------------------------
class CNEOBotDetpackTrigger : public Action< CNEOBot >
{
public:
CNEOBotDetpackTrigger( void );

virtual ActionResult< CNEOBot > OnStart( CNEOBot *me, Action< CNEOBot > *priorAction ) override;
virtual ActionResult< CNEOBot > Update( CNEOBot *me, float interval ) override;
virtual void OnEnd( CNEOBot *me, Action< CNEOBot > *nextAction ) override;

virtual ActionResult<CNEOBot> OnSuspend( CNEOBot *me, Action<CNEOBot> *interruptingAction ) override;
virtual ActionResult<CNEOBot> OnResume( CNEOBot *me, Action<CNEOBot> *interruptingAction ) override;

virtual const char *GetName( void ) const override { return "DetpackTrigger"; }

private:
bool m_bPushedWeapon;
CHandle< CWeaponDetpack > m_hDetpackWeapon;
CountdownTimer m_expiryTimer;
};
Loading