Counter Strike : Global Offensive Source Code
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
|
|
// simple_bot.cpp
// A simple bot
// Michael Booth, February 2009
#include "cbase.h"
#include "simple_bot.h"
#include "nav_mesh.h"
//-----------------------------------------------------------------------------------------------------
// Command to add a Simple Bot where your crosshairs are aiming
//-----------------------------------------------------------------------------------------------------
CON_COMMAND_F( simple_bot_add, "Add a simple bot.", FCVAR_CHEAT ) { CBasePlayer *player = UTIL_GetCommandClient(); if ( !player ) { return; }
Vector forward; player->EyeVectors( &forward );
trace_t result; UTIL_TraceLine( player->EyePosition(), player->EyePosition() + 999999.9f * forward, MASK_BLOCKLOS_AND_NPCS|CONTENTS_IGNORE_NODRAW_OPAQUE, player, COLLISION_GROUP_NONE, &result ); if ( !result.DidHit() ) { return; }
CSimpleBot *bot = static_cast< CSimpleBot * >( CreateEntityByName( "simple_bot" ) ); if ( bot ) { Vector forward = player->GetAbsOrigin() - result.endpos; forward.z = 0.0f; forward.NormalizeInPlace();
QAngle angles; VectorAngles( forward, angles );
bot->SetAbsAngles( angles ); bot->SetAbsOrigin( result.endpos + Vector( 0, 0, 10.0f ) );
DispatchSpawn( bot ); } }
//-----------------------------------------------------------------------------------------------------
// The Simple Bot
//-----------------------------------------------------------------------------------------------------
LINK_ENTITY_TO_CLASS( simple_bot, CSimpleBot ); PRECACHE_REGISTER( simple_bot );
//-----------------------------------------------------------------------------------------------------
CSimpleBot::CSimpleBot() { ALLOCATE_INTENTION_INTERFACE( CSimpleBot );
m_locomotor = new NextBotGroundLocomotion( this ); }
//-----------------------------------------------------------------------------------------------------
CSimpleBot::~CSimpleBot() { DEALLOCATE_INTENTION_INTERFACE;
if ( m_locomotor ) delete m_locomotor; }
//-----------------------------------------------------------------------------------------------------
void CSimpleBot::Precache() { BaseClass::Precache();
#ifndef DOTA_DLL
PrecacheModel( "models/humans/group01/female_01.mdl" ); #endif
}
//-----------------------------------------------------------------------------------------------------
void CSimpleBot::Spawn( void ) { BaseClass::Spawn();
#ifndef DOTA_DLL
SetModel( "models/humans/group01/female_01.mdl" ); #endif
}
//---------------------------------------------------------------------------------------------
// The Simple Bot behaviors
//---------------------------------------------------------------------------------------------
/**
* For use with TheNavMesh->ForAllAreas() * Find the Nth area in the sequence */ class SelectNthAreaFunctor { public: SelectNthAreaFunctor( int count ) { m_count = count; m_area = NULL; }
bool operator() ( CNavArea *area ) { m_area = area; return ( m_count-- > 0 ); }
int m_count; CNavArea *m_area; };
//---------------------------------------------------------------------------------------------
/**
* This action causes the bot to pick a random nav area in the mesh and move to it, then * pick another, etc. * Actions usually each have their own .cpp/.h file and are organized into folders since there * are often many of them. For this example, we're keeping everything to a single .cpp/.h file. */ class CSimpleBotRoam : public Action< CSimpleBot > { public: //----------------------------------------------------------------------------------
// OnStart is called once when the Action first becomes active
virtual ActionResult< CSimpleBot > OnStart( CSimpleBot *me, Action< CSimpleBot > *priorAction ) { // smooth out the bot's path following by moving toward a point farther down the path
m_path.SetMinLookAheadDistance( 300.0f );
return Continue(); }
//----------------------------------------------------------------------------------
// Update is called repeatedly (usually once per server frame) while the Action is active
virtual ActionResult< CSimpleBot > Update( CSimpleBot *me, float interval ) { if ( m_path.IsValid() && !m_timer.IsElapsed() ) { // PathFollower::Update() moves the bot along the path using the bot's ILocomotion and IBody interfaces
m_path.Update( me ); } else { SelectNthAreaFunctor pick( RandomInt( 0, TheNavMesh->GetNavAreaCount() - 1 ) ); TheNavMesh->ForAllAreas( pick );
if ( pick.m_area ) { CSimpleBotPathCost cost( me ); m_path.Compute( me, pick.m_area->GetCenter(), cost ); }
// follow this path for a random duration (or until we reach the end)
m_timer.Start( RandomFloat( 5.0f, 10.0f ) ); }
return Continue(); }
//----------------------------------------------------------------------------------
// this is an event handler - many more are available (see declaration of Action< Actor > in NextBotBehavior.h)
virtual EventDesiredResult< CSimpleBot > OnStuck( CSimpleBot *me ) { // we are stuck trying to follow the current path - invalidate it so a new one is chosen
m_path.Invalidate();
return TryContinue(); }
virtual const char *GetName( void ) const { return "Roam"; } // return name of this action
private: PathFollower m_path; CountdownTimer m_timer; };
//---------------------------------------------------------------------------------------------
/**
* Instantiate the bot's Intention interface and start the initial Action (CSimpleBotRoam in this case) */ IMPLEMENT_INTENTION_INTERFACE( CSimpleBot, CSimpleBotRoam )
|