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.
199 lines
5.6 KiB
199 lines
5.6 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// 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 ); |
|
|
|
#ifndef TF_DLL |
|
PRECACHE_REGISTER( simple_bot ); |
|
#endif |
|
|
|
|
|
//----------------------------------------------------------------------------------------------------- |
|
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 )
|
|
|