void CSDKBot::Think() { bool didThink = false; if (gpGlobals->curtime > m_flNextThink) { didThink = true; ThinkMsg(m_pPlayer->GetPlayerName()); //ThinkMsg(" Updating Players..."); m_PlayerSearchInfo.UpdateOwnerLocation(); m_PlayerSearchInfo.UpdatePlayers(); if (m_bLastThinkWasStateChange) { m_bLastThinkWasStateChange = false; PostStateChangeThink(); } //ThinkMsg("Flags..."); if (m_bUpdateFlags) m_PlayerSearchInfo.UpdateFlags(); ThinkMsgF("%s ", m_pCurThinker->m_ppszThinkerName); ThinkMsg("Check...\n"); if ((this->*(m_pCurThinker->m_pThinkCheck))()) { ThinkMsgF("Think...", m_pCurThinker->m_ppszThinkerName); //wonderful syntax here right? (this->*(m_pCurThinker->m_pThink))(); m_flNextThink = gpGlobals->curtime + m_pCurThinker->m_flThinkDelay; } else { m_bLastThinkWasStateChange = true; ThinkMsg("Change..."); } m_LastCmd = m_curCmd; //ThinkMsg("Buttons..."); ButtonThink(); } if (didThink) { //ThinkMsg("Move..."); } RunPlayerMove(m_pPlayer, m_curCmd, gpGlobals->frametime); if (didThink) { ThinkMsg("Finished!\n"); } }
//----------------------------------------------------------------------------- // Purpose: Run this Bot's AI for one frame. //----------------------------------------------------------------------------- void Bot_Think( CBaseTFPlayer *pBot ) { // Hack to make Bots use Menus if ( pBot->m_pCurrentMenu == gMenus[MENU_CLASS] ) { int iClass = g_iNextBotClass; if ( iClass == -1 ) iClass = random->RandomInt( 1, TFCLASS_CLASS_COUNT ); pBot->m_pCurrentMenu->Input( pBot, iClass ); } else if ( bot_changeclass.GetInt() && bot_changeclass.GetInt() != pBot->PlayerClass() ) { pBot->m_pCurrentMenu = gMenus[MENU_CLASS]; pBot->m_pCurrentMenu->Input( pBot, bot_changeclass.GetInt() ); } // Make sure we stay being a bot pBot->AddFlag( FL_FAKECLIENT ); botdata_t *botdata = &g_BotData[ ENTINDEX( pBot->pev ) - 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->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(); // Is it a twohandedweapon? If so, get the left weapon CWeaponTwoHandedContainer *pContainer = dynamic_cast< CWeaponTwoHandedContainer * >( pActiveWeapon ); if ( pContainer ) { pActiveWeapon = pContainer->GetLeftWeapon(); } // 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 ); } // Fix up the m_fEffects flags pBot->PostClientMessagesSent(); RunPlayerMove( pBot, pBot->GetLocalAngles(), forwardmove, sidemove, upmove, buttons, impulse, frametime ); }
//----------------------------------------------------------------------------- // 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 ); }
//----------------------------------------------------------------------------- // Run this Bot's AI for one tick. //----------------------------------------------------------------------------- void CSDKBot::BotThink() { // Make sure we stay being a bot AddFlag( FL_FAKECLIENT ); if ( IsEFlagSet(EFL_BOT_FROZEN) ) return; CUserCmd cmd; Q_memset( &cmd, 0, sizeof( cmd ) ); ConVarRef bot_freeze("bot_freeze"); if ( !IsAlive() ) { HandleRespawn(cmd); } else if (bot_mimic.GetBool()) { CBasePlayer *pPlayer = UTIL_PlayerByIndex( bot_mimic.GetInt() ); if ( pPlayer && pPlayer->GetLastUserCommand() ) { cmd = *pPlayer->GetLastUserCommand(); ConVarRef bot_mimic_yaw_offset("bot_mimic_yaw_offset"); cmd.viewangles[YAW] += bot_mimic_yaw_offset.GetFloat(); ConVarRef bot_crouch("bot_crouch"); if( bot_crouch.GetInt() ) cmd.buttons |= IN_DUCK; } } else if (!bot_freeze.GetBool()) { trace_t tr_front; Vector Forward; AngleVectors(GetLocalAngles(), &Forward); UTIL_TraceHull( GetLocalOrigin()+Vector(0,0,5), GetLocalOrigin() + Vector(0,0,5) + (Forward * 50), GetPlayerMins(), GetPlayerMaxs(), MASK_PLAYERSOLID, this, COLLISION_GROUP_NONE, &tr_front ); // enemy acquisition if( !GetEnemy() || RecheckEnemy() || !GetEnemy()->IsAlive() ) { if( GetEnemy() && !GetEnemy()->IsAlive() ) ResetNavigationParams(); AcquireEnemy(); m_flTimeToRecheckEnemy = gpGlobals->curtime + 1.0f; } // assume we have an enemy from now on InfoGathering(); Attack(cmd); if( m_flTimeToRecheckStuck < gpGlobals->curtime ) CheckStuck(cmd); if( m_flNextDealObstacles < gpGlobals->curtime ) DealWithObstacles(tr_front.m_pEnt, cmd); Navigation(cmd); CheckNavMeshAttrib(&tr_front, cmd); } // debug waypoint related position /*for( int i=0; i<m_Waypoints.Count(); i++ ) { NDebugOverlay::Cross3DOriented( m_Waypoints[i].Center, QAngle(0,0,0), 5*i+1, 200, 0, 0, false, -1 ); }*/ RunPlayerMove( cmd, gpGlobals->frametime ); }