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.
200 lines
5.6 KiB
200 lines
5.6 KiB
5 years ago
|
//========= 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 )
|