//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CChangeClassZone::Touch( CBaseEntity *pOther ) { if ( !IsDisabled() ) { CTFPlayer *pPlayer = ToTFPlayer( pOther ); if ( pPlayer ) { if ( pPlayer->GetNextChangeClassTime() > gpGlobals->curtime ) return; int iTeam = GetTeamNumber(); if ( iTeam && ( pPlayer->GetTeamNumber() != iTeam ) ) return; // bring up the player's changeclass menu CCommand args; args.Tokenize( "changeclass" ); pPlayer->ClientCommand( args ); pPlayer->SetNextChangeClassTime( gpGlobals->curtime + TF_CHANGECLASS_NEXT_USE_TIME ); CPASAttenuationFilter filter( pOther, TF_CHANGECLASS_SOUND ); EmitSound( filter, pOther->entindex(), TF_CHANGECLASS_SOUND ); } } }
bool CForwardManager::OnSpectatorExecuteStringCommand(const char *s) { if (!hltvserver) RETURN_META_VALUE(MRES_IGNORED, true); IClient *client = META_IFACEPTR(IClient); if (!s || !s[0]) RETURN_META_VALUE(MRES_IGNORED, true); CCommand args; if (!args.Tokenize(s)) RETURN_META_VALUE(MRES_IGNORED, true); // See if the client wants to chat. if (!Q_stricmp(args[0], "say") && args.ArgC() > 1) { // TODO find correct hltvserver this client is connected to! // Save the client index and message. hltvserver->SetLastChatClient(client); hltvserver->SetLastChatMessage(args[1]); } RETURN_META_VALUE(MRES_IGNORED, true); }
void CSDKPlayer::State_Enter_WELCOME() { // Important to set MOVETYPE_NONE or our physics object will fall while we're sitting at one of the intro cameras. SetMoveType( MOVETYPE_NONE ); AddSolidFlags( FSOLID_NOT_SOLID ); PhysObjectSleep(); // Show info panel if ( IsBot() ) { // If they want to auto join a team for debugging, pretend they clicked the button. CCommand args; args.Tokenize( "joingame" ); ClientCommand( args ); } else { const ConVar *hostname = cvar->FindVar( "hostname" ); const char *title = (hostname) ? hostname->GetString() : "MESSAGE OF THE DAY"; // open info panel on client showing MOTD: KeyValues *data = new KeyValues("data"); data->SetString( "title", title ); // info panel title data->SetString( "type", "1" ); // show userdata from stringtable entry data->SetString( "msg", "motd" ); // use this stringtable entry data->SetString( "cmd", "joingame" );// exec this command if panel closed ShowViewPortPanel( PANEL_INFO, true, data ); data->deleteThis(); } }
void CBotComManager::DispatchVCommToBot() { //I think the compiler is optimizing the necessary null checks, so I'll do this volatile CHL2MP_Player* pContextPlayer = m_pContextPlayer; if (m_pContextPlayer) { if (m_eForcedContext) { m_eContext = m_eForcedContext; m_eForcedContext = CONTEXT_NONE; if (m_bRedirectForcedContextToTeammate) { pContextPlayer = m_pContextPlayer = ToHL2MPPlayer(CPlayerSearch::FriendlyBotNearestTo(m_pContextPlayer)); m_bRedirectForcedContextToTeammate = false; } } //nearest bot might be null so check it again if (pContextPlayer && m_pContextPlayer && m_pContextPlayer->IsFakeClient()) { //build a vcomm static char vcommTemplate[64]; Q_snprintf(vcommTemplate, sizeof vcommTemplate, "voicecomm %i\n", ParseContext(m_eContext)); static CCommand vcommCmd; vcommCmd.Tokenize(vcommTemplate); m_pContextPlayer->ClientCommand(vcommCmd); } } }
//----------------------------------------------------------------------------- // 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(); CCommand args; args.Tokenize( "jointeam 0" ); pPlayer->ClientCommand( args ); args.Tokenize( "joinclass -2" ); pPlayer->ClientCommand( args ); g_CurBotNumber++; return pPlayer; }
object execute_server_command(tuple args, dict kwargs) { std::string szCommand; ConCommand* pCommand; prepare_command(args, kwargs, &pCommand, &szCommand); CCommand c; if (!c.Tokenize(szCommand.c_str())) BOOST_RAISE_EXCEPTION(PyExc_ValueError, "Failed to tokenize '%s'.", szCommand.c_str()) pCommand->Dispatch(c); return object(); }
bool CGameClient::ExecuteStringCommand( const char *pCommandString ) { // first let the baseclass handle it if ( CBaseClient::ExecuteStringCommand( pCommandString ) ) return true; // Determine whether the command is appropriate CCommand args; if ( !args.Tokenize( pCommandString ) ) return false; if ( args.ArgC() == 0 ) return false; if ( IsEngineClientCommand( args ) ) { Cmd_ExecuteCommand( args, src_client, m_nClientSlot ); return true; } const ConCommandBase *pCommand = g_pCVar->FindCommandBase( args[ 0 ] ); if ( pCommand && pCommand->IsCommand() && pCommand->IsFlagSet( FCVAR_GAMEDLL ) ) { // Allow cheat commands in singleplayer, debug, or multiplayer with sv_cheats on // NOTE: Don't bother with rpt stuff; commands that matter there shouldn't have FCVAR_GAMEDLL set if ( pCommand->IsFlagSet( FCVAR_CHEAT ) ) { if ( sv.IsMultiplayer() && !CanCheat() ) return false; } if ( pCommand->IsFlagSet( FCVAR_SPONLY ) ) { if ( sv.IsMultiplayer() ) { return false; } } g_pServerPluginHandler->SetCommandClient( m_nClientSlot ); Cmd_Dispatch( pCommand, args ); } else { g_pServerPluginHandler->ClientCommand( edict, args ); // TODO pass client id and string } return true; }
//----------------------------------------------------------------------------- // 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 ); SDKWeaponID eWeapon = SDK_WEAPON_NONE; while (eWeapon == SDK_WEAPON_NONE || eWeapon == SDK_WEAPON_BRAWL) eWeapon = (SDKWeaponID)RandomInt(1, WEAPON_MAX-1); pPlayer->AddToLoadout(eWeapon); pPlayer->State_Transition( STATE_ACTIVE ); CCommand args; args.Tokenize( "menuclosed" ); pPlayer->ClientCommand( args ); g_CurBotNumber++; return pPlayer; }
//-------------------------------------------------------------------------------------------------------------- void BuyState::OnUpdate( CCSBot *me ) { char cmdBuffer[256]; // wait for a Navigation Mesh if (!TheNavMesh->IsLoaded()) return; // apparently we cant buy things in the first few seconds, so wait a bit if (m_isInitialDelay) { const float waitToBuyTime = 0.25f; if (gpGlobals->curtime - me->GetStateTimestamp() < waitToBuyTime) return; m_isInitialDelay = false; } // if we're done buying and still in the freeze period, wait if (m_doneBuying) { if (CSGameRules()->IsMultiplayer() && CSGameRules()->IsFreezePeriod()) { // make sure we're locked and loaded me->EquipBestWeapon( MUST_EQUIP ); me->Reload(); me->ResetStuckMonitor(); return; } me->Idle(); return; } // If we're supposed to buy a specific weapon for debugging, do so and then bail const char *cheatWeaponString = bot_loadout.GetString(); if ( cheatWeaponString && *cheatWeaponString ) { CUtlVector<char*, CUtlMemory<char*> > loadout; Q_SplitString( cheatWeaponString, " ", loadout ); for ( int i=0; i<loadout.Count(); ++i ) { const char *item = loadout[i]; if ( FStrEq( item, "vest" ) ) { me->GiveNamedItem( "item_kevlar" ); } else if ( FStrEq( item, "vesthelm" ) ) { me->GiveNamedItem( "item_assaultsuit" ); } else if ( FStrEq( item, "defuser" ) ) { if ( me->GetTeamNumber() == TEAM_CT ) { me->GiveDefuser(); } } else if ( FStrEq( item, "nvgs" ) ) { me->m_bHasNightVision = true; } else if ( FStrEq( item, "primammo" ) ) { me->AttemptToBuyAmmo( 0 ); } else if ( FStrEq( item, "secammo" ) ) { me->AttemptToBuyAmmo( 1 ); } else { me->GiveWeapon( item ); } } m_doneBuying = true; return; } if (!me->IsInBuyZone()) { m_doneBuying = true; CONSOLE_ECHO( "%s bot spawned outside of a buy zone (%d, %d, %d)\n", (me->GetTeamNumber() == TEAM_CT) ? "CT" : "Terrorist", (int)me->GetAbsOrigin().x, (int)me->GetAbsOrigin().y, (int)me->GetAbsOrigin().z ); return; } // try to buy some weapons const float buyInterval = 0.02f; if (gpGlobals->curtime - me->GetStateTimestamp() > buyInterval) { me->m_stateTimestamp = gpGlobals->curtime; bool isPreferredAllDisallowed = true; // try to buy our preferred weapons first if (m_prefIndex < me->GetProfile()->GetWeaponPreferenceCount() && bot_randombuy.GetBool() == false ) { // need to retry because sometimes first buy fails?? const int maxPrefRetries = 2; if (m_prefRetries >= maxPrefRetries) { // try to buy next preferred weapon ++m_prefIndex; m_prefRetries = 0; return; } int weaponPreference = me->GetProfile()->GetWeaponPreference( m_prefIndex ); // don't buy it again if we still have one from last round char weaponPreferenceName[32]; Q_snprintf( weaponPreferenceName, sizeof(weaponPreferenceName), "weapon_%s", me->GetProfile()->GetWeaponPreferenceAsString( m_prefIndex ) ); if( me->Weapon_OwnsThisType(weaponPreferenceName) )//Prefs and buyalias use the short version, this uses the long { // done with buying preferred weapon m_prefIndex = 9999; return; } if (me->HasShield() && weaponPreference == WEAPON_SHIELDGUN) { // done with buying preferred weapon m_prefIndex = 9999; return; } const char *buyAlias = NULL; if (weaponPreference == WEAPON_SHIELDGUN) { if (TheCSBots()->AllowTacticalShield()) buyAlias = "shield"; } else { buyAlias = WeaponIDToAlias( weaponPreference ); WeaponType type = GetWeaponType( buyAlias ); switch( type ) { case PISTOL: if (!TheCSBots()->AllowPistols()) buyAlias = NULL; break; case SHOTGUN: if (!TheCSBots()->AllowShotguns()) buyAlias = NULL; break; case SUB_MACHINE_GUN: if (!TheCSBots()->AllowSubMachineGuns()) buyAlias = NULL; break; case RIFLE: if (!TheCSBots()->AllowRifles()) buyAlias = NULL; break; case MACHINE_GUN: if (!TheCSBots()->AllowMachineGuns()) buyAlias = NULL; break; case SNIPER_RIFLE: if (!TheCSBots()->AllowSnipers()) buyAlias = NULL; break; } } if (buyAlias) { Q_snprintf( cmdBuffer, 256, "buy %s\n", buyAlias ); CCommand args; args.Tokenize( cmdBuffer ); me->ClientCommand( args ); me->PrintIfWatched( "Tried to buy preferred weapon %s.\n", buyAlias ); isPreferredAllDisallowed = false; } ++m_prefRetries; // bail out so we dont waste money on other equipment // unless everything we prefer has been disallowed, then buy at random if (isPreferredAllDisallowed == false) return; } // if we have no preferred primary weapon (or everything we want is disallowed), buy at random if (!me->HasPrimaryWeapon() && (isPreferredAllDisallowed || !me->GetProfile()->HasPrimaryPreference())) { if (m_buyShield) { // buy a shield CCommand args; args.Tokenize( "buy shield" ); me->ClientCommand( args ); me->PrintIfWatched( "Tried to buy a shield.\n" ); } else { // build list of allowable weapons to buy BuyInfo *masterPrimary = (me->GetTeamNumber() == TEAM_TERRORIST) ? primaryWeaponBuyInfoT : primaryWeaponBuyInfoCT; BuyInfo *stockPrimary[ PRIMARY_WEAPON_BUY_COUNT ]; int stockPrimaryCount = 0; // dont choose sniper rifles as often const float sniperRifleChance = 50.0f; bool wantSniper = (RandomFloat( 0, 100 ) < sniperRifleChance) ? true : false; if ( bot_randombuy.GetBool() ) { wantSniper = true; } for( int i=0; i<PRIMARY_WEAPON_BUY_COUNT; ++i ) { if ((masterPrimary[i].type == SHOTGUN && TheCSBots()->AllowShotguns()) || (masterPrimary[i].type == SUB_MACHINE_GUN && TheCSBots()->AllowSubMachineGuns()) || (masterPrimary[i].type == RIFLE && TheCSBots()->AllowRifles()) || (masterPrimary[i].type == SNIPER_RIFLE && TheCSBots()->AllowSnipers() && wantSniper) || (masterPrimary[i].type == MACHINE_GUN && TheCSBots()->AllowMachineGuns())) { stockPrimary[ stockPrimaryCount++ ] = &masterPrimary[i]; } } if (stockPrimaryCount) { // buy primary weapon if we don't have one int which; // on hard difficulty levels, bots try to buy preferred weapons on the first pass if (m_retries == 0 && TheCSBots()->GetDifficultyLevel() >= BOT_HARD && bot_randombuy.GetBool() == false ) { // count up available preferred weapons int prefCount = 0; for( which=0; which<stockPrimaryCount; ++which ) if (stockPrimary[which]->preferred) ++prefCount; if (prefCount) { int whichPref = RandomInt( 0, prefCount-1 ); for( which=0; which<stockPrimaryCount; ++which ) if (stockPrimary[which]->preferred && whichPref-- == 0) break; } else { // no preferred weapons available, just pick randomly which = RandomInt( 0, stockPrimaryCount-1 ); } } else { which = RandomInt( 0, stockPrimaryCount-1 ); } Q_snprintf( cmdBuffer, 256, "buy %s\n", stockPrimary[ which ]->buyAlias ); CCommand args; args.Tokenize( cmdBuffer ); me->ClientCommand( args ); me->PrintIfWatched( "Tried to buy %s.\n", stockPrimary[ which ]->buyAlias ); } } } // // If we now have a weapon, or have tried for too long, we're done // if (me->HasPrimaryWeapon() || m_retries++ > 5) { // primary ammo CCommand args; if (me->HasPrimaryWeapon()) { args.Tokenize( "buy primammo" ); me->ClientCommand( args ); } // buy armor last, to make sure we bought a weapon first args.Tokenize( "buy vesthelm" ); me->ClientCommand( args ); args.Tokenize( "buy vest" ); me->ClientCommand( args ); // pistols - if we have no preferred pistol, buy at random if (TheCSBots()->AllowPistols() && !me->GetProfile()->HasPistolPreference()) { if (m_buyPistol) { int which = RandomInt( 0, SECONDARY_WEAPON_BUY_COUNT-1 ); const char *what = NULL; if (me->GetTeamNumber() == TEAM_TERRORIST) what = secondaryWeaponBuyInfoT[ which ].buyAlias; else what = secondaryWeaponBuyInfoCT[ which ].buyAlias; Q_snprintf( cmdBuffer, 256, "buy %s\n", what ); args.Tokenize( cmdBuffer ); me->ClientCommand( args ); // only buy one pistol m_buyPistol = false; } // make sure we have enough pistol ammo args.Tokenize( "buy secammo" ); me->ClientCommand( args ); } // buy a grenade if we wish, and we don't already have one if (m_buyGrenade && !me->HasGrenade()) { if (UTIL_IsTeamAllBots( me->GetTeamNumber() )) { // only allow Flashbangs if everyone on the team is a bot (dont want to blind our friendly humans) float rnd = RandomFloat( 0, 100 ); if (rnd < 10) { args.Tokenize( "buy smokegrenade" ); me->ClientCommand( args ); // smoke grenade } else if (rnd < 35) { args.Tokenize( "buy flashbang" ); me->ClientCommand( args ); // flashbang } else { args.Tokenize( "buy hegrenade" ); me->ClientCommand( args ); // he grenade } } else { if (RandomFloat( 0, 100 ) < 10) { args.Tokenize( "buy smokegrenade" ); // smoke grenade me->ClientCommand( args ); } else { args.Tokenize( "buy hegrenade" ); // he grenade me->ClientCommand( args ); } } } if (m_buyDefuseKit) { args.Tokenize( "buy defuser" ); me->ClientCommand( args ); } m_doneBuying = true; } } }
//----------------------------------------------------------------------------- // Purpose: Run this Bot's AI for one frame. //----------------------------------------------------------------------------- void Bot_Think( CDODPlayer *pBot ) { // Make sure we stay being a bot pBot->AddFlag( FL_FAKECLIENT ); botdata_t *botdata = &g_BotData[ ENTINDEX( pBot->edict() ) - 1 ]; QAngle vecViewAngles; float forwardmove = 0.0; float sidemove = botdata->sidemove; float upmove = 0.0; unsigned short buttons = 0; byte impulse = 0; float frametime = gpGlobals->frametime; vecViewAngles = pBot->GetLocalAngles(); // Create some random values if ( pBot->GetTeamNumber() == TEAM_UNASSIGNED && gpGlobals->curtime > botdata->m_flJoinTeamTime ) { pBot->HandleCommand_JoinTeam( botdata->m_WantedTeam ); } else if ( pBot->GetTeamNumber() != TEAM_UNASSIGNED && pBot->m_Shared.PlayerClass() == PLAYERCLASS_UNDEFINED ) { // If they're on a team but haven't picked a class, choose a random class.. pBot->HandleCommand_JoinClass( botdata->m_WantedClass ); pBot->DODRespawn(); } else 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 ); vecSrc = pBot->GetLocalOrigin() + Vector( 0, 0, 36 ); vecEnd = vecSrc + forward * 10; UTIL_TraceHull( vecSrc, vecEnd, VEC_HULL_MIN, VEC_HULL_MAX, 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; } // Is my team being forced to defend? if ( bot_defend.GetInt() == pBot->GetTeamNumber() ) { buttons |= IN_ATTACK2; } // 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; } if ( RandomFloat(0.0,1.0) > 0.9 ) buttons |= IN_RELOAD; } if ( Q_strlen( bot_sendcmd.GetString() ) > 0 ) { //send the cmd from this bot CCommand args; args.Tokenize( bot_sendcmd.GetString() ); pBot->ClientCommand( args ); bot_sendcmd.SetValue(""); } } 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 ) { botdata->lastAngles.x = sin( gpGlobals->curtime + pBot->entindex() ) * 90; botdata->lastAngles.y = AngleNormalize( ( gpGlobals->curtime * 1.7 + pBot->entindex() ) * 45 ); botdata->lastAngles.z = 0.0; // botdata->lastAngles = QAngle( 0, 0, 0 ); /* QAngle angOffset = RandomAngle( -1, 1 ); 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; */ float speed = 300; // sin( gpGlobals->curtime / 1.7 + pBot->entindex() ) * 600; forwardmove = sin( gpGlobals->curtime + pBot->entindex() ) * speed; sidemove = cos( gpGlobals->curtime * 2.3 + pBot->entindex() ) * speed; if (sin(gpGlobals->curtime ) < -0.5) { buttons |= IN_DUCK; } else if (sin(gpGlobals->curtime ) < 0.5) { buttons |= IN_WALK; } pBot->SetLocalAngles( botdata->lastAngles ); } // Fix up the m_fEffects flags pBot->PostClientMessagesSent(); RunPlayerMove( pBot, pBot->GetLocalAngles(), forwardmove, sidemove, upmove, buttons, impulse, frametime ); }