aboutsummaryrefslogtreecommitdiff
path: root/mp/src/game/server/sdk/sdk_bot_temp.cpp
diff options
context:
space:
mode:
authorJørgen P. Tjernø <[email protected]>2013-12-02 19:31:46 -0800
committerJørgen P. Tjernø <[email protected]>2013-12-02 19:46:31 -0800
commitf56bb35301836e56582a575a75864392a0177875 (patch)
treede61ddd39de3e7df52759711950b4c288592f0dc /mp/src/game/server/sdk/sdk_bot_temp.cpp
parentMark some more files as text. (diff)
downloadsource-sdk-2013-f56bb35301836e56582a575a75864392a0177875.tar.xz
source-sdk-2013-f56bb35301836e56582a575a75864392a0177875.zip
Fix line endings. WHAMMY.
Diffstat (limited to 'mp/src/game/server/sdk/sdk_bot_temp.cpp')
-rw-r--r--mp/src/game/server/sdk/sdk_bot_temp.cpp944
1 files changed, 472 insertions, 472 deletions
diff --git a/mp/src/game/server/sdk/sdk_bot_temp.cpp b/mp/src/game/server/sdk/sdk_bot_temp.cpp
index e8990919..cfc57644 100644
--- a/mp/src/game/server/sdk/sdk_bot_temp.cpp
+++ b/mp/src/game/server/sdk/sdk_bot_temp.cpp
@@ -1,472 +1,472 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose: Basic BOT handling.
-//
-// $Workfile: $
-// $Date: $
-//
-//-----------------------------------------------------------------------------
-// $Log: $
-//
-// $NoKeywords: $
-//=============================================================================//
-
-#include "cbase.h"
-#include "player.h"
-#include "sdk_player.h"
-#include "in_buttons.h"
-#include "movehelper_server.h"
-#include "gameinterface.h"
-
-
-class CSDKBot;
-void Bot_Think( CSDKBot *pBot );
-
-
-ConVar bot_forcefireweapon( "bot_forcefireweapon", "", 0, "Force bots with the specified weapon to fire." );
-ConVar bot_forceattack2( "bot_forceattack2", "0", 0, "When firing, use attack2." );
-ConVar bot_forceattackon( "bot_forceattackon", "0", 0, "When firing, don't tap fire, hold it down." );
-ConVar bot_flipout( "bot_flipout", "0", 0, "When on, all bots fire their guns." );
-ConVar bot_changeclass( "bot_changeclass", "0", 0, "Force all bots to change to the specified class." );
-static ConVar bot_mimic( "bot_mimic", "0", 0, "Bot uses usercmd of player by index." );
-static ConVar bot_mimic_yaw_offset( "bot_mimic_yaw_offset", "0", 0, "Offsets the bot yaw." );
-
-ConVar bot_sendcmd( "bot_sendcmd", "", 0, "Forces bots to send the specified command." );
-
-ConVar bot_crouch( "bot_crouch", "0", 0, "Bot crouches" );
-
-static int g_CurBotNumber = 1;
-
-
-// This is our bot class.
-class CSDKBot : public CSDKPlayer
-{
-public:
- bool m_bBackwards;
-
- float m_flNextTurnTime;
- bool m_bLastTurnToRight;
-
- float m_flNextStrafeTime;
- float m_flSideMove;
-
- QAngle m_ForwardAngle;
- QAngle m_LastAngles;
-};
-
-LINK_ENTITY_TO_CLASS( sdk_bot, CSDKBot );
-
-class CBotManager
-{
-public:
- static CBasePlayer* ClientPutInServerOverride_Bot( edict_t *pEdict, const char *playername )
- {
- // This tells it which edict to use rather than creating a new one.
- CBasePlayer::s_PlayerEdict = pEdict;
-
- CSDKBot *pPlayer = static_cast<CSDKBot *>( CreateEntityByName( "sdk_bot" ) );
- if ( pPlayer )
- {
- pPlayer->SetPlayerName( playername );
- }
-
- return pPlayer;
- }
-};
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Create a new Bot and put it in the game.
-// Output : Pointer to the new Bot, or NULL if there's no free clients.
-//-----------------------------------------------------------------------------
-CBasePlayer *BotPutInServer( bool bFrozen )
-{
- char botname[ 64 ];
- Q_snprintf( botname, sizeof( botname ), "Bot%02i", g_CurBotNumber );
-
-
- // This trick lets us create a CSDKBot for this client instead of the CSDKPlayer
- // that we would normally get when ClientPutInServer is called.
- ClientPutInServerOverride( &CBotManager::ClientPutInServerOverride_Bot );
- edict_t *pEdict = engine->CreateFakeClient( botname );
- ClientPutInServerOverride( NULL );
-
- if (!pEdict)
- {
- Msg( "Failed to create Bot.\n");
- return NULL;
- }
-
- // Allocate a player entity for the bot, and call spawn
- CSDKBot *pPlayer = ((CSDKBot*)CBaseEntity::Instance( pEdict ));
-
- pPlayer->ClearFlags();
- pPlayer->AddFlag( FL_CLIENT | FL_FAKECLIENT );
-
- if ( bFrozen )
- pPlayer->AddEFlags( EFL_BOT_FROZEN );
-
- pPlayer->ChangeTeam( TEAM_UNASSIGNED );
- pPlayer->RemoveAllItems( true );
- pPlayer->Spawn();
-
- g_CurBotNumber++;
-
- return pPlayer;
-}
-
-// Handler for the "bot" command.
-CON_COMMAND_F( "bot_add", "Add a bot.", FCVAR_CHEAT )
-{
- // Look at -count.
- int count = args.FindArgInt( "-count", 1 );
- count = clamp( count, 1, 16 );
-
- // Look at -frozen.
- bool bFrozen = !!args.FindArg( "-frozen" );
-
- // Ok, spawn all the bots.
- while ( --count >= 0 )
- {
- BotPutInServer( bFrozen );
- }
-}
-
-
-//-----------------------------------------------------------------------------
-// Purpose: Run through all the Bots in the game and let them think.
-//-----------------------------------------------------------------------------
-void Bot_RunAll( void )
-{
- for ( int i = 1; i <= gpGlobals->maxClients; i++ )
- {
- CSDKPlayer *pPlayer = ToSDKPlayer( UTIL_PlayerByIndex( i ) );
-
- if ( pPlayer && (pPlayer->GetFlags() & FL_FAKECLIENT) )
- {
- CSDKBot *pBot = dynamic_cast< CSDKBot* >( pPlayer );
- if ( pBot )
- Bot_Think( pBot );
- }
- }
-}
-
-bool Bot_RunMimicCommand( CUserCmd& cmd )
-{
- if ( bot_mimic.GetInt() <= 0 )
- return false;
-
- if ( bot_mimic.GetInt() > gpGlobals->maxClients )
- return false;
-
-
- CBasePlayer *pPlayer = UTIL_PlayerByIndex( bot_mimic.GetInt() );
- if ( !pPlayer )
- return false;
-
- if ( !pPlayer->GetLastUserCommand() )
- return false;
-
- cmd = *pPlayer->GetLastUserCommand();
- cmd.viewangles[YAW] += bot_mimic_yaw_offset.GetFloat();
-
- if( bot_crouch.GetInt() )
- cmd.buttons |= IN_DUCK;
-
- return true;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Simulates a single frame of movement for a player
-// Input : *fakeclient -
-// *viewangles -
-// forwardmove -
-// m_flSideMove -
-// upmove -
-// buttons -
-// impulse -
-// msec -
-// Output : virtual void
-//-----------------------------------------------------------------------------
-static void RunPlayerMove( CSDKPlayer *fakeclient, CUserCmd &cmd, float frametime )
-{
- if ( !fakeclient )
- return;
-
- // Store off the globals.. they're gonna get whacked
- float flOldFrametime = gpGlobals->frametime;
- float flOldCurtime = gpGlobals->curtime;
-
- float flTimeBase = gpGlobals->curtime + gpGlobals->frametime - frametime;
- fakeclient->SetTimeBase( flTimeBase );
-
- MoveHelperServer()->SetHost( fakeclient );
- fakeclient->PlayerRunCommand( &cmd, MoveHelperServer() );
-
- // save off the last good usercmd
- fakeclient->SetLastUserCommand( cmd );
-
- // Clear out any fixangle that has been set
- fakeclient->pl.fixangle = FIXANGLE_NONE;
-
- // Restore the globals..
- gpGlobals->frametime = flOldFrametime;
- gpGlobals->curtime = flOldCurtime;
-}
-
-
-
-void Bot_UpdateStrafing( CSDKBot *pBot, CUserCmd &cmd )
-{
- if ( gpGlobals->curtime >= pBot->m_flNextStrafeTime )
- {
- pBot->m_flNextStrafeTime = gpGlobals->curtime + 1.0f;
-
- if ( random->RandomInt( 0, 5 ) == 0 )
- {
- pBot->m_flSideMove = -600.0f + 1200.0f * random->RandomFloat( 0, 2 );
- }
- else
- {
- pBot->m_flSideMove = 0;
- }
- cmd.sidemove = pBot->m_flSideMove;
-
- if ( random->RandomInt( 0, 20 ) == 0 )
- {
- pBot->m_bBackwards = true;
- }
- else
- {
- pBot->m_bBackwards = false;
- }
- }
-}
-
-
-void Bot_UpdateDirection( CSDKBot *pBot )
-{
- float angledelta = 15.0;
- QAngle angle;
-
- int maxtries = (int)360.0/angledelta;
-
- if ( pBot->m_bLastTurnToRight )
- {
- angledelta = -angledelta;
- }
-
- angle = pBot->GetLocalAngles();
-
- trace_t trace;
- Vector vecSrc, vecEnd, forward;
- while ( --maxtries >= 0 )
- {
- AngleVectors( angle, &forward );
-
- vecSrc = pBot->GetLocalOrigin() + Vector( 0, 0, 36 );
-
- vecEnd = vecSrc + forward * 10;
-
- UTIL_TraceHull( vecSrc, vecEnd, VEC_HULL_MIN_SCALED( pBot ), VEC_HULL_MAX_SCALED( pBot ),
- MASK_PLAYERSOLID, pBot, COLLISION_GROUP_NONE, &trace );
-
- if ( trace.fraction == 1.0 )
- {
- if ( gpGlobals->curtime < pBot->m_flNextTurnTime )
- {
- break;
- }
- }
-
- angle.y += angledelta;
-
- if ( angle.y > 180 )
- angle.y -= 360;
- else if ( angle.y < -180 )
- angle.y += 360;
-
- pBot->m_flNextTurnTime = gpGlobals->curtime + 2.0;
- pBot->m_bLastTurnToRight = random->RandomInt( 0, 1 ) == 0 ? true : false;
-
- pBot->m_ForwardAngle = angle;
- pBot->m_LastAngles = angle;
- }
-
- pBot->SetLocalAngles( angle );
-}
-
-
-void Bot_FlipOut( CSDKBot *pBot, CUserCmd &cmd )
-{
- if ( bot_flipout.GetInt() > 0 && pBot->IsAlive() )
- {
- if ( bot_forceattackon.GetBool() || (RandomFloat(0.0,1.0) > 0.5) )
- {
- cmd.buttons |= bot_forceattack2.GetBool() ? IN_ATTACK2 : IN_ATTACK;
- }
-
- if ( bot_flipout.GetInt() >= 2 )
- {
- QAngle angOffset = RandomAngle( -1, 1 );
-
- pBot->m_LastAngles += angOffset;
-
- for ( int i = 0 ; i < 2; i++ )
- {
- if ( fabs( pBot->m_LastAngles[ i ] - pBot->m_ForwardAngle[ i ] ) > 15.0f )
- {
- if ( pBot->m_LastAngles[ i ] > pBot->m_ForwardAngle[ i ] )
- {
- pBot->m_LastAngles[ i ] = pBot->m_ForwardAngle[ i ] + 15;
- }
- else
- {
- pBot->m_LastAngles[ i ] = pBot->m_ForwardAngle[ i ] - 15;
- }
- }
- }
-
- pBot->m_LastAngles[ 2 ] = 0;
-
- pBot->SetLocalAngles( pBot->m_LastAngles );
- }
- }
-}
-
-
-void Bot_HandleSendCmd( CSDKBot *pBot )
-{
- if ( strlen( bot_sendcmd.GetString() ) > 0 )
- {
- //send the cmd from this bot
- pBot->ClientCommand( bot_sendcmd.GetString() );
-
- bot_sendcmd.SetValue("");
- }
-}
-
-
-// If bots are being forced to fire a weapon, see if I have it
-void Bot_ForceFireWeapon( CSDKBot *pBot, CUserCmd &cmd )
-{
- if ( bot_forcefireweapon.GetString() )
- {
- CBaseCombatWeapon *pWeapon = pBot->Weapon_OwnsThisType( bot_forcefireweapon.GetString() );
- if ( pWeapon )
- {
- // Switch to it if we don't have it out
- CBaseCombatWeapon *pActiveWeapon = pBot->GetActiveWeapon();
-
- // Switch?
- if ( pActiveWeapon != pWeapon )
- {
- pBot->Weapon_Switch( pWeapon );
- }
- else
- {
- // Start firing
- // Some weapons require releases, so randomise firing
- if ( bot_forceattackon.GetBool() || (RandomFloat(0.0,1.0) > 0.5) )
- {
- cmd.buttons |= bot_forceattack2.GetBool() ? IN_ATTACK2 : IN_ATTACK;
- }
- }
- }
- }
-}
-
-
-void Bot_SetForwardMovement( CSDKBot *pBot, CUserCmd &cmd )
-{
- if ( !pBot->IsEFlagSet(EFL_BOT_FROZEN) )
- {
- if ( pBot->m_iHealth == 100 )
- {
- cmd.forwardmove = 600 * ( pBot->m_bBackwards ? -1 : 1 );
- if ( pBot->m_flSideMove != 0.0f )
- {
- cmd.forwardmove *= random->RandomFloat( 0.1, 1.0f );
- }
- }
- else
- {
- // Stop when shot
- cmd.forwardmove = 0;
- }
- }
-}
-
-
-void Bot_HandleRespawn( CSDKBot *pBot, CUserCmd &cmd )
-{
- // Wait for Reinforcement wave
- if ( !pBot->IsAlive() )
- {
- // Try hitting my buttons occasionally
- if ( random->RandomInt( 0, 100 ) > 80 )
- {
- // Respawn the bot
- if ( random->RandomInt( 0, 1 ) == 0 )
- {
- cmd.buttons |= IN_JUMP;
- }
- else
- {
- cmd.buttons = 0;
- }
- }
- }
-}
-
-
-//-----------------------------------------------------------------------------
-// Run this Bot's AI for one frame.
-//-----------------------------------------------------------------------------
-void Bot_Think( CSDKBot *pBot )
-{
- // Make sure we stay being a bot
- pBot->AddFlag( FL_FAKECLIENT );
-
-
- CUserCmd cmd;
- Q_memset( &cmd, 0, sizeof( cmd ) );
-
-
- // Finally, override all this stuff if the bot is being forced to mimic a player.
- if ( !Bot_RunMimicCommand( cmd ) )
- {
- cmd.sidemove = pBot->m_flSideMove;
-
- if ( pBot->IsAlive() && (pBot->GetSolid() == SOLID_BBOX) )
- {
- Bot_SetForwardMovement( pBot, cmd );
-
- // Only turn if I haven't been hurt
- if ( !pBot->IsEFlagSet(EFL_BOT_FROZEN) && pBot->m_iHealth == 100 )
- {
- Bot_UpdateDirection( pBot );
- Bot_UpdateStrafing( pBot, cmd );
- }
-
- // Handle console settings.
- Bot_ForceFireWeapon( pBot, cmd );
- Bot_HandleSendCmd( pBot );
- }
- else
- {
- Bot_HandleRespawn( pBot, cmd );
- }
-
- Bot_FlipOut( pBot, cmd );
-
- cmd.viewangles = pBot->GetLocalAngles();
- cmd.upmove = 0;
- cmd.impulse = 0;
- }
-
- float frametime = gpGlobals->frametime;
- RunPlayerMove( pBot, cmd, frametime );
-}
-
-
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Basic BOT handling.
+//
+// $Workfile: $
+// $Date: $
+//
+//-----------------------------------------------------------------------------
+// $Log: $
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#include "cbase.h"
+#include "player.h"
+#include "sdk_player.h"
+#include "in_buttons.h"
+#include "movehelper_server.h"
+#include "gameinterface.h"
+
+
+class CSDKBot;
+void Bot_Think( CSDKBot *pBot );
+
+
+ConVar bot_forcefireweapon( "bot_forcefireweapon", "", 0, "Force bots with the specified weapon to fire." );
+ConVar bot_forceattack2( "bot_forceattack2", "0", 0, "When firing, use attack2." );
+ConVar bot_forceattackon( "bot_forceattackon", "0", 0, "When firing, don't tap fire, hold it down." );
+ConVar bot_flipout( "bot_flipout", "0", 0, "When on, all bots fire their guns." );
+ConVar bot_changeclass( "bot_changeclass", "0", 0, "Force all bots to change to the specified class." );
+static ConVar bot_mimic( "bot_mimic", "0", 0, "Bot uses usercmd of player by index." );
+static ConVar bot_mimic_yaw_offset( "bot_mimic_yaw_offset", "0", 0, "Offsets the bot yaw." );
+
+ConVar bot_sendcmd( "bot_sendcmd", "", 0, "Forces bots to send the specified command." );
+
+ConVar bot_crouch( "bot_crouch", "0", 0, "Bot crouches" );
+
+static int g_CurBotNumber = 1;
+
+
+// This is our bot class.
+class CSDKBot : public CSDKPlayer
+{
+public:
+ bool m_bBackwards;
+
+ float m_flNextTurnTime;
+ bool m_bLastTurnToRight;
+
+ float m_flNextStrafeTime;
+ float m_flSideMove;
+
+ QAngle m_ForwardAngle;
+ QAngle m_LastAngles;
+};
+
+LINK_ENTITY_TO_CLASS( sdk_bot, CSDKBot );
+
+class CBotManager
+{
+public:
+ static CBasePlayer* ClientPutInServerOverride_Bot( edict_t *pEdict, const char *playername )
+ {
+ // This tells it which edict to use rather than creating a new one.
+ CBasePlayer::s_PlayerEdict = pEdict;
+
+ CSDKBot *pPlayer = static_cast<CSDKBot *>( CreateEntityByName( "sdk_bot" ) );
+ if ( pPlayer )
+ {
+ pPlayer->SetPlayerName( playername );
+ }
+
+ return pPlayer;
+ }
+};
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Create a new Bot and put it in the game.
+// Output : Pointer to the new Bot, or NULL if there's no free clients.
+//-----------------------------------------------------------------------------
+CBasePlayer *BotPutInServer( bool bFrozen )
+{
+ char botname[ 64 ];
+ Q_snprintf( botname, sizeof( botname ), "Bot%02i", g_CurBotNumber );
+
+
+ // This trick lets us create a CSDKBot for this client instead of the CSDKPlayer
+ // that we would normally get when ClientPutInServer is called.
+ ClientPutInServerOverride( &CBotManager::ClientPutInServerOverride_Bot );
+ edict_t *pEdict = engine->CreateFakeClient( botname );
+ ClientPutInServerOverride( NULL );
+
+ if (!pEdict)
+ {
+ Msg( "Failed to create Bot.\n");
+ return NULL;
+ }
+
+ // Allocate a player entity for the bot, and call spawn
+ CSDKBot *pPlayer = ((CSDKBot*)CBaseEntity::Instance( pEdict ));
+
+ pPlayer->ClearFlags();
+ pPlayer->AddFlag( FL_CLIENT | FL_FAKECLIENT );
+
+ if ( bFrozen )
+ pPlayer->AddEFlags( EFL_BOT_FROZEN );
+
+ pPlayer->ChangeTeam( TEAM_UNASSIGNED );
+ pPlayer->RemoveAllItems( true );
+ pPlayer->Spawn();
+
+ g_CurBotNumber++;
+
+ return pPlayer;
+}
+
+// Handler for the "bot" command.
+CON_COMMAND_F( "bot_add", "Add a bot.", FCVAR_CHEAT )
+{
+ // Look at -count.
+ int count = args.FindArgInt( "-count", 1 );
+ count = clamp( count, 1, 16 );
+
+ // Look at -frozen.
+ bool bFrozen = !!args.FindArg( "-frozen" );
+
+ // Ok, spawn all the bots.
+ while ( --count >= 0 )
+ {
+ BotPutInServer( bFrozen );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Run through all the Bots in the game and let them think.
+//-----------------------------------------------------------------------------
+void Bot_RunAll( void )
+{
+ for ( int i = 1; i <= gpGlobals->maxClients; i++ )
+ {
+ CSDKPlayer *pPlayer = ToSDKPlayer( UTIL_PlayerByIndex( i ) );
+
+ if ( pPlayer && (pPlayer->GetFlags() & FL_FAKECLIENT) )
+ {
+ CSDKBot *pBot = dynamic_cast< CSDKBot* >( pPlayer );
+ if ( pBot )
+ Bot_Think( pBot );
+ }
+ }
+}
+
+bool Bot_RunMimicCommand( CUserCmd& cmd )
+{
+ if ( bot_mimic.GetInt() <= 0 )
+ return false;
+
+ if ( bot_mimic.GetInt() > gpGlobals->maxClients )
+ return false;
+
+
+ CBasePlayer *pPlayer = UTIL_PlayerByIndex( bot_mimic.GetInt() );
+ if ( !pPlayer )
+ return false;
+
+ if ( !pPlayer->GetLastUserCommand() )
+ return false;
+
+ cmd = *pPlayer->GetLastUserCommand();
+ cmd.viewangles[YAW] += bot_mimic_yaw_offset.GetFloat();
+
+ if( bot_crouch.GetInt() )
+ cmd.buttons |= IN_DUCK;
+
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Simulates a single frame of movement for a player
+// Input : *fakeclient -
+// *viewangles -
+// forwardmove -
+// m_flSideMove -
+// upmove -
+// buttons -
+// impulse -
+// msec -
+// Output : virtual void
+//-----------------------------------------------------------------------------
+static void RunPlayerMove( CSDKPlayer *fakeclient, CUserCmd &cmd, float frametime )
+{
+ if ( !fakeclient )
+ return;
+
+ // Store off the globals.. they're gonna get whacked
+ float flOldFrametime = gpGlobals->frametime;
+ float flOldCurtime = gpGlobals->curtime;
+
+ float flTimeBase = gpGlobals->curtime + gpGlobals->frametime - frametime;
+ fakeclient->SetTimeBase( flTimeBase );
+
+ MoveHelperServer()->SetHost( fakeclient );
+ fakeclient->PlayerRunCommand( &cmd, MoveHelperServer() );
+
+ // save off the last good usercmd
+ fakeclient->SetLastUserCommand( cmd );
+
+ // Clear out any fixangle that has been set
+ fakeclient->pl.fixangle = FIXANGLE_NONE;
+
+ // Restore the globals..
+ gpGlobals->frametime = flOldFrametime;
+ gpGlobals->curtime = flOldCurtime;
+}
+
+
+
+void Bot_UpdateStrafing( CSDKBot *pBot, CUserCmd &cmd )
+{
+ if ( gpGlobals->curtime >= pBot->m_flNextStrafeTime )
+ {
+ pBot->m_flNextStrafeTime = gpGlobals->curtime + 1.0f;
+
+ if ( random->RandomInt( 0, 5 ) == 0 )
+ {
+ pBot->m_flSideMove = -600.0f + 1200.0f * random->RandomFloat( 0, 2 );
+ }
+ else
+ {
+ pBot->m_flSideMove = 0;
+ }
+ cmd.sidemove = pBot->m_flSideMove;
+
+ if ( random->RandomInt( 0, 20 ) == 0 )
+ {
+ pBot->m_bBackwards = true;
+ }
+ else
+ {
+ pBot->m_bBackwards = false;
+ }
+ }
+}
+
+
+void Bot_UpdateDirection( CSDKBot *pBot )
+{
+ float angledelta = 15.0;
+ QAngle angle;
+
+ int maxtries = (int)360.0/angledelta;
+
+ if ( pBot->m_bLastTurnToRight )
+ {
+ angledelta = -angledelta;
+ }
+
+ angle = pBot->GetLocalAngles();
+
+ trace_t trace;
+ Vector vecSrc, vecEnd, forward;
+ while ( --maxtries >= 0 )
+ {
+ AngleVectors( angle, &forward );
+
+ vecSrc = pBot->GetLocalOrigin() + Vector( 0, 0, 36 );
+
+ vecEnd = vecSrc + forward * 10;
+
+ UTIL_TraceHull( vecSrc, vecEnd, VEC_HULL_MIN_SCALED( pBot ), VEC_HULL_MAX_SCALED( pBot ),
+ MASK_PLAYERSOLID, pBot, COLLISION_GROUP_NONE, &trace );
+
+ if ( trace.fraction == 1.0 )
+ {
+ if ( gpGlobals->curtime < pBot->m_flNextTurnTime )
+ {
+ break;
+ }
+ }
+
+ angle.y += angledelta;
+
+ if ( angle.y > 180 )
+ angle.y -= 360;
+ else if ( angle.y < -180 )
+ angle.y += 360;
+
+ pBot->m_flNextTurnTime = gpGlobals->curtime + 2.0;
+ pBot->m_bLastTurnToRight = random->RandomInt( 0, 1 ) == 0 ? true : false;
+
+ pBot->m_ForwardAngle = angle;
+ pBot->m_LastAngles = angle;
+ }
+
+ pBot->SetLocalAngles( angle );
+}
+
+
+void Bot_FlipOut( CSDKBot *pBot, CUserCmd &cmd )
+{
+ if ( bot_flipout.GetInt() > 0 && pBot->IsAlive() )
+ {
+ if ( bot_forceattackon.GetBool() || (RandomFloat(0.0,1.0) > 0.5) )
+ {
+ cmd.buttons |= bot_forceattack2.GetBool() ? IN_ATTACK2 : IN_ATTACK;
+ }
+
+ if ( bot_flipout.GetInt() >= 2 )
+ {
+ QAngle angOffset = RandomAngle( -1, 1 );
+
+ pBot->m_LastAngles += angOffset;
+
+ for ( int i = 0 ; i < 2; i++ )
+ {
+ if ( fabs( pBot->m_LastAngles[ i ] - pBot->m_ForwardAngle[ i ] ) > 15.0f )
+ {
+ if ( pBot->m_LastAngles[ i ] > pBot->m_ForwardAngle[ i ] )
+ {
+ pBot->m_LastAngles[ i ] = pBot->m_ForwardAngle[ i ] + 15;
+ }
+ else
+ {
+ pBot->m_LastAngles[ i ] = pBot->m_ForwardAngle[ i ] - 15;
+ }
+ }
+ }
+
+ pBot->m_LastAngles[ 2 ] = 0;
+
+ pBot->SetLocalAngles( pBot->m_LastAngles );
+ }
+ }
+}
+
+
+void Bot_HandleSendCmd( CSDKBot *pBot )
+{
+ if ( strlen( bot_sendcmd.GetString() ) > 0 )
+ {
+ //send the cmd from this bot
+ pBot->ClientCommand( bot_sendcmd.GetString() );
+
+ bot_sendcmd.SetValue("");
+ }
+}
+
+
+// If bots are being forced to fire a weapon, see if I have it
+void Bot_ForceFireWeapon( CSDKBot *pBot, CUserCmd &cmd )
+{
+ if ( bot_forcefireweapon.GetString() )
+ {
+ CBaseCombatWeapon *pWeapon = pBot->Weapon_OwnsThisType( bot_forcefireweapon.GetString() );
+ if ( pWeapon )
+ {
+ // Switch to it if we don't have it out
+ CBaseCombatWeapon *pActiveWeapon = pBot->GetActiveWeapon();
+
+ // Switch?
+ if ( pActiveWeapon != pWeapon )
+ {
+ pBot->Weapon_Switch( pWeapon );
+ }
+ else
+ {
+ // Start firing
+ // Some weapons require releases, so randomise firing
+ if ( bot_forceattackon.GetBool() || (RandomFloat(0.0,1.0) > 0.5) )
+ {
+ cmd.buttons |= bot_forceattack2.GetBool() ? IN_ATTACK2 : IN_ATTACK;
+ }
+ }
+ }
+ }
+}
+
+
+void Bot_SetForwardMovement( CSDKBot *pBot, CUserCmd &cmd )
+{
+ if ( !pBot->IsEFlagSet(EFL_BOT_FROZEN) )
+ {
+ if ( pBot->m_iHealth == 100 )
+ {
+ cmd.forwardmove = 600 * ( pBot->m_bBackwards ? -1 : 1 );
+ if ( pBot->m_flSideMove != 0.0f )
+ {
+ cmd.forwardmove *= random->RandomFloat( 0.1, 1.0f );
+ }
+ }
+ else
+ {
+ // Stop when shot
+ cmd.forwardmove = 0;
+ }
+ }
+}
+
+
+void Bot_HandleRespawn( CSDKBot *pBot, CUserCmd &cmd )
+{
+ // Wait for Reinforcement wave
+ if ( !pBot->IsAlive() )
+ {
+ // Try hitting my buttons occasionally
+ if ( random->RandomInt( 0, 100 ) > 80 )
+ {
+ // Respawn the bot
+ if ( random->RandomInt( 0, 1 ) == 0 )
+ {
+ cmd.buttons |= IN_JUMP;
+ }
+ else
+ {
+ cmd.buttons = 0;
+ }
+ }
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Run this Bot's AI for one frame.
+//-----------------------------------------------------------------------------
+void Bot_Think( CSDKBot *pBot )
+{
+ // Make sure we stay being a bot
+ pBot->AddFlag( FL_FAKECLIENT );
+
+
+ CUserCmd cmd;
+ Q_memset( &cmd, 0, sizeof( cmd ) );
+
+
+ // Finally, override all this stuff if the bot is being forced to mimic a player.
+ if ( !Bot_RunMimicCommand( cmd ) )
+ {
+ cmd.sidemove = pBot->m_flSideMove;
+
+ if ( pBot->IsAlive() && (pBot->GetSolid() == SOLID_BBOX) )
+ {
+ Bot_SetForwardMovement( pBot, cmd );
+
+ // Only turn if I haven't been hurt
+ if ( !pBot->IsEFlagSet(EFL_BOT_FROZEN) && pBot->m_iHealth == 100 )
+ {
+ Bot_UpdateDirection( pBot );
+ Bot_UpdateStrafing( pBot, cmd );
+ }
+
+ // Handle console settings.
+ Bot_ForceFireWeapon( pBot, cmd );
+ Bot_HandleSendCmd( pBot );
+ }
+ else
+ {
+ Bot_HandleRespawn( pBot, cmd );
+ }
+
+ Bot_FlipOut( pBot, cmd );
+
+ cmd.viewangles = pBot->GetLocalAngles();
+ cmd.upmove = 0;
+ cmd.impulse = 0;
+ }
+
+ float frametime = gpGlobals->frametime;
+ RunPlayerMove( pBot, cmd, frametime );
+}
+
+