Skip to content
Open
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
2 changes: 2 additions & 0 deletions src/game/server/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1468,6 +1468,8 @@ target_sources_grouped(
neo/bot/behavior/neo_bot_seek_weapon.h
neo/bot/behavior/neo_bot_tactical_monitor.cpp
neo/bot/behavior/neo_bot_tactical_monitor.h
neo/bot/behavior/neo_bot_throw_weapon_at_player.cpp
neo/bot/behavior/neo_bot_throw_weapon_at_player.h
neo/bot/behavior/nav_entities/neo_bot_nav_ent_destroy_entity.cpp
neo/bot/behavior/nav_entities/neo_bot_nav_ent_destroy_entity.h
neo/bot/behavior/nav_entities/neo_bot_nav_ent_move_to.cpp
Expand Down
25 changes: 25 additions & 0 deletions src/game/server/NextBot/Player/NextBotPlayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,9 @@ class INextBotPlayerInput
virtual void ReleaseJumpButton( void ) = 0;

#ifdef NEO
virtual void PressDropButton( float duration = -1.0f ) = 0;
virtual void ReleaseDropButton( void ) = 0;

virtual void PressThermopticButton( float duration = -1.0f ) = 0;
virtual void ReleaseThermopticButton( void ) = 0;
#endif // NEO
Expand Down Expand Up @@ -202,6 +205,9 @@ class NextBotPlayer : public PlayerType, public INextBot, public INextBotPlayerI
virtual void ReleaseSpecialFireButton( void );

#ifdef NEO
virtual void PressDropButton( float duration = -1.0f );
virtual void ReleaseDropButton( void );

virtual void PressThermopticButton( float duration = -1.0f );
virtual void ReleaseThermopticButton( void );
#endif
Expand Down Expand Up @@ -286,6 +292,7 @@ class NextBotPlayer : public PlayerType, public INextBot, public INextBotPlayerI
CountdownTimer m_walkButtonTimer;
CountdownTimer m_buttonScaleTimer;
#ifdef NEO
CountdownTimer m_dropButtonTimer;
CountdownTimer m_thermopticButtonTimer;
CountdownTimer m_leanLeftButtonTimer;
CountdownTimer m_leanRightButtonTimer;
Expand Down Expand Up @@ -450,6 +457,20 @@ inline void NextBotPlayer< PlayerType >::ReleaseJumpButton( void )
}

#ifdef NEO
template < typename PlayerType >
inline void NextBotPlayer< PlayerType >::PressDropButton( float duration )
{
m_inputButtons |= IN_DROP;
m_dropButtonTimer.Start( duration );
}

template < typename PlayerType >
inline void NextBotPlayer< PlayerType >::ReleaseDropButton( void )
{
m_inputButtons &= ~IN_DROP;
m_dropButtonTimer.Invalidate();
}

template < typename PlayerType >
inline void NextBotPlayer< PlayerType >::PressThermopticButton( float duration )
{
Expand Down Expand Up @@ -642,6 +663,7 @@ inline void NextBotPlayer< PlayerType >::Spawn( void )
m_forwardScale = m_rightScale = 0.04;
m_burningTimer.Invalidate();
#ifdef NEO
m_dropButtonTimer.Invalidate();
m_thermopticButtonTimer.Invalidate();
m_leanLeftButtonTimer.Invalidate();
m_leanRightButtonTimer.Invalidate();
Expand Down Expand Up @@ -780,6 +802,9 @@ inline void NextBotPlayer< PlayerType >::PhysicsSimulate( void )
m_inputButtons |= IN_SPEED;

#ifdef NEO
if ( !m_dropButtonTimer.IsElapsed() )
m_inputButtons |= IN_DROP;

if ( !m_leanLeftButtonTimer.IsElapsed() )
m_inputButtons |= IN_LEAN_LEFT;

Expand Down
78 changes: 78 additions & 0 deletions src/game/server/neo/bot/behavior/neo_bot_command_follow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "neo_player.h"
#include "bot/neo_bot.h"
#include "bot/behavior/neo_bot_command_follow.h"
#include "bot/behavior/neo_bot_throw_weapon_at_player.h"
#include "nav_mesh.h"

// memdbgon must be the last include file in a .cpp file!!!
Expand Down Expand Up @@ -36,6 +37,8 @@ CNEOBotCommandFollow::CNEOBotCommandFollow() : m_vGoalPos( CNEO_Player::VECTOR_I
ActionResult< CNEOBot > CNEOBotCommandFollow::OnStart(CNEOBot *me, Action< CNEOBot > *priorAction)
{
m_path.SetMinLookAheadDistance(me->GetDesiredPathLookAheadRange());
m_commanderLookingAtMeTimer.Invalidate();
m_bWasCommanderLookingAtMe = false;

if (!FollowCommandChain(me))
{
Expand All @@ -53,6 +56,81 @@ ActionResult< CNEOBot > CNEOBotCommandFollow::Update(CNEOBot *me, float interval
return Done("Lost commander or released");
}

ActionResult<CNEOBot> weaponRequestResult = CheckCommanderWeaponRequest(me);
if (weaponRequestResult.IsRequestingChange())
{
return weaponRequestResult;
}

return Continue();
}


//---------------------------------------------------------------------------------------------
ActionResult< CNEOBot > CNEOBotCommandFollow::CheckCommanderWeaponRequest(CNEOBot *me)
{
CNEO_Player* pCommander = me->m_hCommandingPlayer.Get();
if (pCommander && pCommander->IsAlive())
{
// Check if commander has dropped primary
if (!pCommander->Weapon_GetSlot(0))
{
// Check if looking at me
Vector vecToBot = me->EyePosition() - pCommander->EyePosition();
vecToBot.NormalizeInPlace();
Vector vecCmdrFacing;
pCommander->EyeVectors(&vecCmdrFacing);

if (vecCmdrFacing.Dot(vecToBot) > 0.99f)
{
if (!m_bWasCommanderLookingAtMe)
{
// Wait to see if it wasn't just a momentary glance
m_commanderLookingAtMeTimer.Start();
m_bWasCommanderLookingAtMe = true;
}

if (m_commanderLookingAtMeTimer.GetElapsedTime() > 0.2f)
{
// Look at commander after 0.5s
me->GetBodyInterface()->AimHeadTowards(pCommander->EyePosition(), IBody::CRITICAL, 0.2f, NULL, "Commander looking at me without a primary");
}

if (m_commanderLookingAtMeTimer.GetElapsedTime() > 1.0f)
{
// Sanity check that commander is really looking at me with more expensive traceline
// e.g. for edge case where I am behind the player the commander is looking at
trace_t tr;
const float estimatedReasonableThrowDistance = 300.0f;
Vector traceEnd = pCommander->EyePosition() + vecCmdrFacing * estimatedReasonableThrowDistance;
UTIL_TraceLine(pCommander->EyePosition(), traceEnd, MASK_SHOT_HULL, pCommander, COLLISION_GROUP_NONE, &tr);

if (tr.DidHit() && tr.m_pEnt == me)
{
m_bWasCommanderLookingAtMe = false; // Reset state
return SuspendFor(new CNEOBotThrowWeaponAtPlayer(pCommander), "Donating weapon to commander");
}
else
{
// Line of sight blocked
m_commanderLookingAtMeTimer.Invalidate();
m_bWasCommanderLookingAtMe = false;
}
}
}
else
{
m_commanderLookingAtMeTimer.Invalidate();
m_bWasCommanderLookingAtMe = false;
}
}
else
{
m_commanderLookingAtMeTimer.Invalidate();
m_bWasCommanderLookingAtMe = false;
}
}

m_path.Update(me);

return Continue();
Expand Down
4 changes: 4 additions & 0 deletions src/game/server/neo/bot/behavior/neo_bot_command_follow.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,14 @@ class CNEOBotCommandFollow : public Action< CNEOBot >
private:
bool FollowCommandChain( CNEOBot *me );
bool FanOutAndCover( CNEOBot *me, Vector &movementTarget, bool bMoveToSeparate = true, float flArrivalZoneSizeSq = -1.0f );
ActionResult< CNEOBot > CheckCommanderWeaponRequest( CNEOBot *me );

PathFollower m_path;
CountdownTimer m_repathTimer;

IntervalTimer m_commanderLookingAtMeTimer;
bool m_bWasCommanderLookingAtMe = false;

EHANDLE m_hTargetEntity;
bool m_bGoingToTargetEntity = false;
Vector m_vGoalPos;
Expand Down
18 changes: 18 additions & 0 deletions src/game/server/neo/bot/behavior/neo_bot_scenario_monitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
#include "bot/behavior/neo_bot_retreat_to_cover.h"
#include "bot/behavior/neo_bot_get_health.h"
#include "bot/behavior/neo_bot_get_ammo.h"
#include "bot/behavior/neo_bot_command_follow.h"
#include "bot/behavior/neo_bot_pause.h"

#include "bot/behavior/neo_bot_attack.h"
#include "bot/behavior/neo_bot_seek_and_destroy.h"
Expand Down Expand Up @@ -64,10 +66,26 @@ ActionResult< CNEOBot > CNEOBotScenarioMonitor::OnStart( CNEOBot *me, Action< CN
ConVar neo_bot_fetch_lost_flag_time( "neo_bot_fetch_lost_flag_time", "10", FCVAR_CHEAT, "How long busy NEOBots will ignore the dropped flag before they give up what they are doing and go after it" );
ConVar neo_bot_flag_kill_on_touch( "neo_bot_flag_kill_on_touch", "0", FCVAR_CHEAT, "If nonzero, any bot that picks up the flag dies. For testing." );

extern ConVar sv_neo_bot_cmdr_enable;
extern ConVar sv_neo_bot_cmdr_debug_pause_uncommanded;


//-----------------------------------------------------------------------------------------
ActionResult< CNEOBot > CNEOBotScenarioMonitor::Update( CNEOBot *me, float interval )
{
if (sv_neo_bot_cmdr_enable.GetBool())
{
if (me->m_hLeadingPlayer.Get() || me->m_hCommandingPlayer.Get())
{
return SuspendFor(new CNEOBotCommandFollow, "Following commander");
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved from neo_bot_tactical_monitor, to unblock other tactical monitor behaviors.

}

if (sv_neo_bot_cmdr_debug_pause_uncommanded.GetBool())
{
return SuspendFor(new CNEOBotPause, "Paused by debug convar sv_neo_bot_cmdr_debug_pause_uncommanded");
}
}

return Continue();
}

18 changes: 1 addition & 17 deletions src/game/server/neo/bot/behavior/neo_bot_tactical_monitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
#include "bot/behavior/neo_bot_tactical_monitor.h"
#include "bot/behavior/neo_bot_scenario_monitor.h"

#include "bot/behavior/neo_bot_command_follow.h"
#include "bot/behavior/neo_bot_seek_and_destroy.h"
#include "bot/behavior/neo_bot_seek_weapon.h"
#include "bot/behavior/neo_bot_retreat_to_cover.h"
Expand All @@ -26,8 +25,6 @@

ConVar neo_bot_force_jump( "neo_bot_force_jump", "0", FCVAR_CHEAT, "Force bots to continuously jump" );
ConVar neo_bot_grenade_check_radius( "neo_bot_grenade_check_radius", "500", FCVAR_CHEAT );
extern ConVar sv_neo_bot_cmdr_enable;
extern ConVar sv_neo_bot_cmdr_debug_pause_uncommanded;

////////////////////////////////////////////////////////////////////////////////////////////////////

Expand Down Expand Up @@ -279,19 +276,6 @@ ActionResult< CNEOBot > CNEOBotTacticalMonitor::Update( CNEOBot *me, float inter
return result;
}

if (sv_neo_bot_cmdr_enable.GetBool())
{
if (me->m_hLeadingPlayer.Get() || me->m_hCommandingPlayer.Get())
{
return SuspendFor(new CNEOBotCommandFollow, "Following commander");
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It turns out that launching into the bot commander following behavior was blocking other tactical monitor behaviors, so I moved this behavior launch point into neo_bot_scenario_monitor.

}

if (sv_neo_bot_cmdr_debug_pause_uncommanded.GetBool())
{
return SuspendFor( new CNEOBotPause, "Paused by debug convar sv_neo_bot_cmdr_debug_pause_uncommanded" );
}
}

const CKnownEntity *threat = me->GetVisionInterface()->GetPrimaryKnownThreat();

// check if we need to get to cover
Expand Down Expand Up @@ -370,7 +354,7 @@ ActionResult< CNEOBot > CNEOBotTacticalMonitor::ScavengeForPrimaryWeapon( CNEOBo
{
return Continue();
}
m_maintainTimer.Start( RandomFloat( 1.0f, 3.0f ) );
m_maintainTimer.Start( 1.0f );

// Look for any one valid primary weapon, then dispatch into behavior for more optimal search
// true parameter: short-circuit the search if any valid primary weapon is found
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#include "cbase.h"
#include "bot/neo_bot.h"
#include "neo_player.h"
#include "bot/behavior/neo_bot_throw_weapon_at_player.h"

// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"

//---------------------------------------------------------------------------------------------
CNEOBotThrowWeaponAtPlayer::CNEOBotThrowWeaponAtPlayer( CNEO_Player *pTargetPlayer )
{
m_hTargetPlayer = pTargetPlayer;
}

//---------------------------------------------------------------------------------------------
ActionResult< CNEOBot > CNEOBotThrowWeaponAtPlayer::OnStart( CNEOBot *me, Action< CNEOBot > *priorAction )
{
if ( !m_hTargetPlayer )
{
return Done( "No target player to throw weapon at" );
}

return Continue();
}

//---------------------------------------------------------------------------------------------
ActionResult< CNEOBot > CNEOBotThrowWeaponAtPlayer::Update( CNEOBot *me, float interval )
{
CNEO_Player *pTarget = m_hTargetPlayer.Get();
if ( !pTarget || !pTarget->IsAlive() )
{
return Done( "Target player lost or died" );
}

me->GetBodyInterface()->AimHeadTowards( pTarget->EyePosition(), IBody::CRITICAL, 0.2f, NULL, "Aiming at player to throw weapon" );

CBaseCombatWeapon *pPrimary = me->Weapon_GetSlot( 0 );
if ( pPrimary )
{
if ( me->GetActiveWeapon() != pPrimary )
{
me->Weapon_Switch( pPrimary );
return Continue(); // Wait for switch
}
}
else
{
return Done( "No primary weapon to throw" );
}

if ( me->GetBodyInterface()->IsHeadAimingOnTarget() )
{
me->PressDropButton();
return Done("Weapon dropped");
}

return Continue();
}

//---------------------------------------------------------------------------------------------
void CNEOBotThrowWeaponAtPlayer::OnEnd( CNEOBot *me, Action< CNEOBot > *nextAction )
{
}
26 changes: 26 additions & 0 deletions src/game/server/neo/bot/behavior/neo_bot_throw_weapon_at_player.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#ifndef NEO_BOT_THROW_WEAPON_AT_PLAYER_H
#define NEO_BOT_THROW_WEAPON_AT_PLAYER_H
#ifdef _WIN32
#pragma once
#endif

#include "NextBotBehavior.h"

class CNEO_Player;

class CNEOBotThrowWeaponAtPlayer : public Action< CNEOBot >
{
public:
CNEOBotThrowWeaponAtPlayer( CNEO_Player *pTargetPlayer );

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 const char *GetName( void ) const override { return "ThrowWeaponAtPlayer"; };

private:
CHandle<CNEO_Player> m_hTargetPlayer;
};

#endif // NEO_BOT_THROW_WEAPON_AT_PLAYER_H