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.
195 lines
6.2 KiB
195 lines
6.2 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
// $NoKeywords: $ |
|
//=============================================================================// |
|
|
|
// Author: Michael S. Booth (mike@turtlerockstudios.com), 2003 |
|
|
|
#ifndef BASE_CONTROL_H |
|
#define BASE_CONTROL_H |
|
|
|
#pragma warning( disable : 4530 ) // STL uses exceptions, but we are not compiling with them - ignore warning |
|
|
|
extern float g_BotUpkeepInterval; ///< duration between bot upkeeps |
|
extern float g_BotUpdateInterval; ///< duration between bot updates |
|
const int g_BotUpdateSkipCount = 2; ///< number of upkeep periods to skip update |
|
|
|
class CNavArea; |
|
|
|
/// TODO: move CS-specific defines into CSBot files |
|
enum |
|
{ |
|
SmokeGrenadeRadius = 155, |
|
FlashbangGrenadeRadius = 115, |
|
HEGrenadeRadius = 115, |
|
}; |
|
|
|
//-------------------------------------------------------------------------------------------------------------- |
|
class CBaseGrenade; |
|
|
|
/** |
|
* An ActiveGrenade is a representation of a grenade in the world |
|
* NOTE: Currently only used for smoke grenade line-of-sight testing |
|
* @todo Use system allow bots to avoid HE and Flashbangs |
|
*/ |
|
class ActiveGrenade |
|
{ |
|
public: |
|
ActiveGrenade( CBaseGrenade *grenadeEntity ); |
|
|
|
void OnEntityGone( void ); ///< called when the grenade in the world goes away |
|
void Update( void ); ///< called every frame |
|
bool IsValid( void ) const ; ///< return true if this grenade is valid |
|
|
|
bool IsEntity( CBaseGrenade *grenade ) const { return (grenade == m_entity) ? true : false; } |
|
CBaseGrenade *GetEntity( void ) const { return m_entity; } |
|
|
|
const Vector &GetDetonationPosition( void ) const { return m_detonationPosition; } |
|
const Vector &GetPosition( void ) const; |
|
bool IsSmoke( void ) const { return m_isSmoke; } |
|
bool IsFlashbang( void ) const { return m_isFlashbang; } |
|
CBaseGrenade *GetGrenade( void ) { return m_entity; } |
|
float GetRadius( void ) const { return m_radius; } |
|
void SetRadius( float radius ) { m_radius = radius; } |
|
|
|
private: |
|
CBaseGrenade *m_entity; ///< the entity |
|
Vector m_detonationPosition; ///< the location where the grenade detonated (smoke) |
|
float m_dieTimestamp; ///< time this should go away after m_entity is NULL |
|
bool m_isSmoke; ///< true if this is a smoke grenade |
|
bool m_isFlashbang; ///< true if this is a flashbang grenade |
|
float m_radius; |
|
}; |
|
|
|
typedef CUtlLinkedList<ActiveGrenade *> ActiveGrenadeList; |
|
|
|
|
|
//-------------------------------------------------------------------------------------------------------------- |
|
/** |
|
* This class manages all active bots, propagating events to them and updating them. |
|
*/ |
|
class CBotManager |
|
{ |
|
public: |
|
CBotManager(); |
|
virtual ~CBotManager(); |
|
|
|
CBasePlayer *AllocateAndBindBotEntity( edict_t *ed ); ///< allocate the appropriate entity for the bot and bind it to the given edict |
|
virtual CBasePlayer *AllocateBotEntity( void ) = 0; ///< factory method to allocate the appropriate entity for the bot |
|
|
|
virtual void ClientDisconnect( CBaseEntity *entity ) = 0; |
|
virtual bool ClientCommand( CBasePlayer *player, const CCommand &args ) = 0; |
|
|
|
virtual void ServerActivate( void ) = 0; |
|
virtual void ServerDeactivate( void ) = 0; |
|
virtual bool ServerCommand( const char * pcmd ) = 0; |
|
|
|
virtual void RestartRound( void ); ///< (EXTEND) invoked when a new round begins |
|
virtual void StartFrame( void ); ///< (EXTEND) called each frame |
|
|
|
virtual unsigned int GetPlayerPriority( CBasePlayer *player ) const = 0; ///< return priority of player (0 = max pri) |
|
|
|
|
|
void AddGrenade( CBaseGrenade *grenade ); ///< add an active grenade to the bot's awareness |
|
void RemoveGrenade( CBaseGrenade *grenade ); ///< the grenade entity in the world is going away |
|
void SetGrenadeRadius( CBaseGrenade *grenade, float radius ); ///< the radius of the grenade entity (or associated smoke cloud) |
|
void ValidateActiveGrenades( void ); ///< destroy any invalid active grenades |
|
void DestroyAllGrenades( void ); |
|
bool IsLineBlockedBySmoke( const Vector &from, const Vector &to, float grenadeBloat = 1.0f ); ///< return true if line intersects smoke volume, with grenade radius increased by the grenadeBloat factor |
|
bool IsInsideSmokeCloud( const Vector *pos ); ///< return true if position is inside a smoke cloud |
|
|
|
// |
|
// Invoke functor on all active grenades. |
|
// If any functor call return false, return false. Otherwise, return true. |
|
// |
|
template < typename T > |
|
bool ForEachGrenade( T &func ) |
|
{ |
|
int it = m_activeGrenadeList.Head(); |
|
|
|
while( it != m_activeGrenadeList.InvalidIndex() ) |
|
{ |
|
ActiveGrenade *ag = m_activeGrenadeList[ it ]; |
|
|
|
int current = it; |
|
it = m_activeGrenadeList.Next( it ); |
|
|
|
// lazy validation |
|
if (!ag->IsValid()) |
|
{ |
|
m_activeGrenadeList.Remove( current ); |
|
delete ag; |
|
continue; |
|
} |
|
else |
|
{ |
|
if (func( ag ) == false) |
|
{ |
|
return false; |
|
} |
|
} |
|
} |
|
|
|
return true; |
|
} |
|
|
|
enum { MAX_DBG_MSG_SIZE = 1024 }; |
|
struct DebugMessage |
|
{ |
|
char m_string[ MAX_DBG_MSG_SIZE ]; |
|
IntervalTimer m_age; |
|
}; |
|
|
|
// debug message history ------------------------------------------------------------------------------- |
|
int GetDebugMessageCount( void ) const; ///< get number of debug messages in history |
|
const DebugMessage *GetDebugMessage( int which = 0 ) const; ///< return the debug message emitted by the bot (0 = most recent) |
|
void ClearDebugMessages( void ); |
|
void AddDebugMessage( const char *msg ); |
|
|
|
|
|
private: |
|
ActiveGrenadeList m_activeGrenadeList;///< the list of active grenades the bots are aware of |
|
|
|
enum { MAX_DBG_MSGS = 6 }; |
|
DebugMessage m_debugMessage[ MAX_DBG_MSGS ]; ///< debug message history |
|
int m_debugMessageCount; |
|
int m_currentDebugMessage; |
|
|
|
IntervalTimer m_frameTimer; ///< for measuring each frame's duration |
|
}; |
|
|
|
|
|
inline CBasePlayer *CBotManager::AllocateAndBindBotEntity( edict_t *ed ) |
|
{ |
|
CBasePlayer::s_PlayerEdict = ed; |
|
return AllocateBotEntity(); |
|
} |
|
|
|
inline int CBotManager::GetDebugMessageCount( void ) const |
|
{ |
|
return m_debugMessageCount; |
|
} |
|
|
|
inline const CBotManager::DebugMessage *CBotManager::GetDebugMessage( int which ) const |
|
{ |
|
if (which >= m_debugMessageCount) |
|
return NULL; |
|
|
|
int i = m_currentDebugMessage - which; |
|
if (i < 0) |
|
i += MAX_DBG_MSGS; |
|
|
|
return &m_debugMessage[ i ]; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
// global singleton to create and control bots |
|
extern CBotManager *TheBots; |
|
|
|
|
|
#endif
|
|
|