summaryrefslogtreecommitdiff
path: root/game/server/cstrike/cs_bot_temp.cpp
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /game/server/cstrike/cs_bot_temp.cpp
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'game/server/cstrike/cs_bot_temp.cpp')
-rw-r--r--game/server/cstrike/cs_bot_temp.cpp554
1 files changed, 554 insertions, 0 deletions
diff --git a/game/server/cstrike/cs_bot_temp.cpp b/game/server/cstrike/cs_bot_temp.cpp
new file mode 100644
index 0000000..b154911
--- /dev/null
+++ b/game/server/cstrike/cs_bot_temp.cpp
@@ -0,0 +1,554 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Basic BOT handling.
+//
+// $Workfile: $
+// $Date: $
+//
+//-----------------------------------------------------------------------------
+// $Log: $
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#include "cbase.h"
+#include "cs_player.h"
+#include "in_buttons.h"
+#include "movehelper_server.h"
+#include "team.h"
+#include "cs_gamerules.h"
+#include "client.h"
+
+
+void Bot_Think( CCSPlayer *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_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." );
+
+static int BotNumber = 1;
+static int g_iNextBotTeam = -1;
+
+
+typedef struct
+{
+ bool backwards;
+
+ float nextturntime;
+ bool lastturntoright;
+
+ float nextstrafetime;
+ float sidemove;
+
+ QAngle forwardAngle;
+ QAngle lastAngles;
+
+ int m_WantedTeam;
+ float m_flJoinTeamTime;
+
+ bool m_bTempBot; // Is this slot a dump temp bot or a real bot?
+} botdata_t;
+
+static botdata_t g_BotData[ MAX_PLAYERS ];
+
+//-----------------------------------------------------------------------------
+// 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, int iTeam )
+{
+ g_iNextBotTeam = iTeam;
+
+ char botname[ 64 ];
+ Q_snprintf( botname, sizeof( botname ), "Bot%02i", BotNumber );
+
+ edict_t *pEdict = engine->CreateFakeClient( botname );
+
+ if (!pEdict)
+ {
+ Msg( "Failed to create Bot.\n");
+ return NULL;
+ }
+
+ // Allocate a CBasePlayer for the bot, and call spawn
+ //ClientPutInServer( pEdict, botname );
+ //ClientActive( pEdict, false );
+
+ CCSPlayer *pPlayer = ((CCSPlayer *)CBaseEntity::Instance( pEdict ));
+ pPlayer->ClearFlags();
+ pPlayer->AddFlag( FL_CLIENT | FL_FAKECLIENT );
+
+ if ( bFrozen )
+ pPlayer->AddEFlags( EFL_BOT_FROZEN );
+
+ if ( iTeam == -1 )
+ iTeam = ( pPlayer->entindex() & 1 ) ? TEAM_TERRORIST : TEAM_CT;
+
+ botdata_t *pData = &g_BotData[pPlayer->entindex()-1];
+ pData->m_WantedTeam = iTeam;
+ pData->m_flJoinTeamTime = gpGlobals->curtime + 0.3;
+ pData->m_bTempBot = true;
+
+ BotNumber++;
+ return pPlayer;
+}
+
+bool IsTempBot( CBaseEntity *pEnt )
+{
+ if ( !pEnt )
+ return false;
+
+ if ( !(pEnt->GetFlags() & FL_FAKECLIENT) )
+ return false;
+
+ int i = pEnt->entindex();
+ if ( i >= 1 && i < MAX_PLAYERS )
+ return g_BotData[i-1].m_bTempBot;
+ else
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+// 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++ )
+ {
+ CCSPlayer *pPlayer = ToCSPlayer( UTIL_PlayerByIndex( i ) );
+
+ if ( IsTempBot( pPlayer ) )
+ {
+ Bot_Think( pPlayer );
+ }
+ }
+}
+
+bool 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();
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Simulates a single frame of movement for a player
+// Input : *fakeclient -
+// *viewangles -
+// forwardmove -
+// sidemove -
+// upmove -
+// buttons -
+// impulse -
+// msec -
+// Output : virtual void
+//-----------------------------------------------------------------------------
+static void RunPlayerMove( CCSPlayer *fakeclient, const QAngle& viewangles, float forwardmove, float sidemove, float upmove, unsigned short buttons, byte impulse, float frametime )
+{
+ if ( !fakeclient )
+ return;
+
+ CUserCmd cmd;
+
+ // Store off the globals.. they're gonna get whacked
+ float flOldFrametime = gpGlobals->frametime;
+ float flOldCurtime = gpGlobals->curtime;
+
+ float flTimeBase = gpGlobals->curtime;
+ fakeclient->SetTimeBase( flTimeBase );
+
+ Q_memset( &cmd, 0, sizeof( cmd ) );
+
+ if ( !RunMimicCommand( cmd ) )
+ {
+ VectorCopy( viewangles, cmd.viewangles );
+ cmd.forwardmove = forwardmove;
+ cmd.sidemove = sidemove;
+ cmd.upmove = upmove;
+ cmd.buttons = buttons;
+ cmd.impulse = impulse;
+ cmd.random_seed = random->RandomInt( 0, 0x7fffffff );
+ }
+
+ 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;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Run this Bot's AI for one frame.
+//-----------------------------------------------------------------------------
+void Bot_Think( CCSPlayer *pBot )
+{
+ // Make sure we stay being a bot
+ pBot->AddFlag( FL_FAKECLIENT );
+
+ botdata_t *botdata = &g_BotData[ pBot->entindex() - 1 ];
+
+ float forwardmove = 0.0;
+ float sidemove = botdata->sidemove;
+ float upmove = 0.0;
+ unsigned short buttons = 0;
+ byte impulse = 0;
+ float frametime = gpGlobals->frametime;
+
+ if ( pBot->GetTeamNumber() == TEAM_UNASSIGNED && gpGlobals->curtime > botdata->m_flJoinTeamTime )
+ {
+ pBot->HandleCommand_JoinTeam( botdata->m_WantedTeam );
+ }
+ else if ( pBot->GetTeamNumber() != TEAM_UNASSIGNED && pBot->PlayerClass() == CS_CLASS_NONE )
+ {
+ // If they're on a team but haven't picked a class, choose a random class..
+ pBot->HandleCommand_JoinClass( 0 );
+ }
+ else
+ {
+ QAngle vecViewAngles;
+ vecViewAngles = pBot->GetLocalAngles();
+
+ // Create some random values
+ if ( pBot->IsAlive() && (pBot->GetSolid() == SOLID_BBOX) )
+ {
+ trace_t trace;
+
+ // Stop when shot
+ if ( !pBot->IsEFlagSet(EFL_BOT_FROZEN) )
+ {
+ if ( pBot->m_iHealth == 100 )
+ {
+ forwardmove = 600 * ( botdata->backwards ? -1 : 1 );
+ if ( botdata->sidemove != 0.0f )
+ {
+ forwardmove *= random->RandomFloat( 0.1, 1.0f );
+ }
+ }
+ else
+ {
+ forwardmove = 0;
+ }
+ }
+
+ // Only turn if I haven't been hurt
+ if ( !pBot->IsEFlagSet(EFL_BOT_FROZEN) && pBot->m_iHealth == 100 )
+ {
+ Vector vecEnd;
+ Vector forward;
+
+ QAngle angle;
+ float angledelta = 15.0;
+
+ int maxtries = (int)360.0/angledelta;
+
+ if ( botdata->lastturntoright )
+ {
+ angledelta = -angledelta;
+ }
+
+ angle = pBot->GetLocalAngles();
+
+ Vector vecSrc;
+ while ( --maxtries >= 0 )
+ {
+ AngleVectors( angle, &forward, NULL, NULL );
+
+ 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 < botdata->nextturntime )
+ //{
+ break;
+ //}
+ }
+
+ angle.y += angledelta;
+
+ if ( angle.y > 180 )
+ angle.y -= 360;
+ else if ( angle.y < -180 )
+ angle.y += 360;
+
+ botdata->nextturntime = gpGlobals->curtime + 2.0;
+ botdata->lastturntoright = random->RandomInt( 0, 1 ) == 0 ? true : false;
+
+ botdata->forwardAngle = angle;
+ botdata->lastAngles = angle;
+
+ }
+
+
+ /*
+ if ( gpGlobals->curtime >= botdata->nextstrafetime )
+ {
+ botdata->nextstrafetime = gpGlobals->curtime + 1.0f;
+
+ if ( random->RandomInt( 0, 5 ) == 0 )
+ {
+ botdata->sidemove = -600.0f + 1200.0f * random->RandomFloat( 0, 2 );
+ }
+ else
+ {
+ botdata->sidemove = 0;
+ }
+ sidemove = botdata->sidemove;
+
+ if ( random->RandomInt( 0, 20 ) == 0 )
+ {
+ botdata->backwards = true;
+ }
+ else
+ {
+ botdata->backwards = false;
+ }
+ }
+ */
+
+ pBot->SetLocalAngles( angle );
+ vecViewAngles = angle;
+ }
+
+ // If bots are being forced to fire a weapon, see if I have it
+ else 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) )
+ {
+ buttons |= bot_forceattack2.GetBool() ? IN_ATTACK2 : IN_ATTACK;
+ }
+ }
+ }
+ }
+
+ if ( bot_flipout.GetInt() )
+ {
+ if ( bot_forceattackon.GetBool() || (RandomFloat(0.0,1.0) > 0.5) )
+ {
+ buttons |= bot_forceattack2.GetBool() ? IN_ATTACK2 : IN_ATTACK;
+ }
+ }
+ }
+ else
+ {
+ // 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 )
+ {
+ buttons |= IN_JUMP;
+ }
+ else
+ {
+ buttons = 0;
+ }
+ }
+ }
+ }
+
+ if ( bot_flipout.GetInt() >= 2 )
+ {
+
+ QAngle angOffset = RandomAngle( -1, 1 );
+
+ botdata->lastAngles += angOffset;
+
+ for ( int i = 0 ; i < 2; i++ )
+ {
+ if ( fabs( botdata->lastAngles[ i ] - botdata->forwardAngle[ i ] ) > 15.0f )
+ {
+ if ( botdata->lastAngles[ i ] > botdata->forwardAngle[ i ] )
+ {
+ botdata->lastAngles[ i ] = botdata->forwardAngle[ i ] + 15;
+ }
+ else
+ {
+ botdata->lastAngles[ i ] = botdata->forwardAngle[ i ] - 15;
+ }
+ }
+ }
+
+ botdata->lastAngles[ 2 ] = 0;
+
+ pBot->SetLocalAngles( botdata->lastAngles );
+ }
+ }
+
+ pBot->SetPunchAngle( QAngle( 0, 0, 0 ) );
+ RunPlayerMove( pBot, pBot->GetLocalAngles(), forwardmove, sidemove, upmove, buttons, impulse, frametime );
+}
+
+
+
+// Handler for the "bot" command.
+CON_COMMAND_F( "bot_old", "Add a bot.", FCVAR_CHEAT )
+{
+ // Disable the CS bots, otherwise they'll interfere with the bot code here.
+ //extern bool g_bEnableCSBots;
+ //g_bEnableCSBots = false;
+
+ CCSPlayer *pPlayer = CCSPlayer::Instance( UTIL_GetCommandClientIndex() );
+
+ // The bot command uses switches like command-line switches.
+ // -count <count> tells how many bots to spawn.
+ // -team <index> selects the bot's team. Default is -1 which chooses randomly.
+ // Note: if you do -team !, then it
+ // -class <index> selects the bot's class. Default is -1 which chooses randomly.
+ // -frozen prevents the bots from running around when they spawn in.
+
+ int count = args.FindArgInt( "-count", 1 );
+ count = clamp( count, 1, 16 );
+
+ int iTeam = -1;
+ const char *pVal = args.FindArg( "-team" );
+ if ( pVal )
+ {
+ if ( pVal[0] == '!' )
+ {
+ if ( pPlayer->GetTeamNumber() == TEAM_TERRORIST )
+ iTeam = TEAM_CT;
+ else
+ iTeam = TEAM_TERRORIST;
+ }
+ else if ( pVal[0] == 't' || pVal[0] == 'T' )
+ {
+ iTeam = TEAM_TERRORIST;
+ }
+ else if ( pVal[0] == 'c' || pVal[0] == 'C' )
+ {
+ iTeam = TEAM_CT;
+ }
+ else
+ {
+ iTeam = atoi( pVal );
+ if ( iTeam == 1 )
+ iTeam = TEAM_TERRORIST;
+ else
+ iTeam = TEAM_CT;
+ }
+ }
+
+ // Look at -frozen.
+ bool bFrozen = !!args.FindArg( "-frozen" );
+
+ // Ok, spawn all the bots.
+ while ( --count >= 0 )
+ {
+ extern CBasePlayer *BotPutInServer( bool bFrozen, int iTeam );
+ BotPutInServer( bFrozen, iTeam );
+ }
+}
+
+
+// Handle the "PossessBot" command.
+void PossessBot_f( const CCommand &args )
+{
+ CCSPlayer *pPlayer = CCSPlayer::Instance( UTIL_GetCommandClientIndex() );
+ if ( !pPlayer )
+ return;
+
+ // Put the local player in control of this bot.
+ if ( args.ArgC() != 2 )
+ {
+ Warning( "PossessBot <client index>\n" );
+ return;
+ }
+
+ int iBotClient = atoi( args[1] );
+ int iBotEnt = iBotClient + 1;
+
+ if ( iBotClient < 0 ||
+ iBotClient >= gpGlobals->maxClients ||
+ pPlayer->entindex() == iBotEnt )
+ {
+ Warning( "PossessBot <client index>\n" );
+ }
+ else
+ {
+ edict_t *pPlayerData = pPlayer->edict();
+ edict_t *pBotData = engine->PEntityOfEntIndex( iBotEnt );
+ if ( pBotData && pBotData )
+ {
+ // SWAP EDICTS
+
+ // Backup things we don't want to swap.
+ edict_t oldPlayerData = *pPlayerData;
+ edict_t oldBotData = *pBotData;
+
+ // Swap edicts.
+ edict_t tmp = *pPlayerData;
+ *pPlayerData = *pBotData;
+ *pBotData = tmp;
+
+ // Restore things we didn't want to swap.
+ //pPlayerData->m_EntitiesTouched = oldPlayerData.m_EntitiesTouched;
+ //pBotData->m_EntitiesTouched = oldBotData.m_EntitiesTouched;
+
+ CBaseEntity *pPlayerBaseEnt = CBaseEntity::Instance( pPlayerData );
+ CBaseEntity *pBotBaseEnt = CBaseEntity::Instance( pBotData );
+
+ // Make the other a bot and make the player not a bot.
+ pPlayerBaseEnt->RemoveFlag( FL_FAKECLIENT );
+ pBotBaseEnt->AddFlag( FL_FAKECLIENT );
+
+
+ // Point the CBaseEntities at the right players.
+ pPlayerBaseEnt->NetworkProp()->SetEdict( pPlayerData );
+ pBotBaseEnt->NetworkProp()->SetEdict( pBotData );
+
+ // Freeze the bot.
+ pBotBaseEnt->AddEFlags( EFL_BOT_FROZEN );
+ }
+ }
+}
+
+
+ConCommand cc_PossessBot( "PossessBot", PossessBot_f, "Toggle. Possess a bot.\n\tArguments: <bot client number>", FCVAR_CHEAT );
+