diff options
Diffstat (limited to 'game/server/NextBot/NextBotInterface.h')
| -rw-r--r-- | game/server/NextBot/NextBotInterface.h | 302 |
1 files changed, 302 insertions, 0 deletions
diff --git a/game/server/NextBot/NextBotInterface.h b/game/server/NextBot/NextBotInterface.h new file mode 100644 index 0000000..a2fd67e --- /dev/null +++ b/game/server/NextBot/NextBotInterface.h @@ -0,0 +1,302 @@ +// NextBotInterface.h +// Interface for NextBot +// Author: Michael Booth, May 2006 +//========= Copyright Valve Corporation, All rights reserved. ============// + +#ifndef _NEXT_BOT_INTERFACE_H_ +#define _NEXT_BOT_INTERFACE_H_ + +#include "NextBot/NextBotKnownEntity.h" +#include "NextBotComponentInterface.h" +#include "NextBotLocomotionInterface.h" +#include "NextBotBodyInterface.h" +#include "NextBotIntentionInterface.h" +#include "NextBotVisionInterface.h" +#include "NextBotDebug.h" + +class CBaseCombatCharacter; +class PathFollower; + +//---------------------------------------------------------------------------------------------------------------- +/** + * A general purpose filter interface for various bot systems + */ +class INextBotFilter +{ +public: + virtual bool IsSelected( const CBaseEntity *candidate ) const = 0; // return true if this entity passes the filter +}; + + +//---------------------------------------------------------------------------------------------------------------- +class INextBot : public INextBotEventResponder +{ +public: + INextBot( void ); + virtual ~INextBot(); + + int GetBotId() const; + + bool BeginUpdate(); + void EndUpdate(); + + virtual void Reset( void ); // (EXTEND) reset to initial state + virtual void Update( void ); // (EXTEND) update internal state + virtual void Upkeep( void ); // (EXTEND) lightweight update guaranteed to occur every server tick + + void FlagForUpdate( bool b = true ); + bool IsFlaggedForUpdate(); + int GetTickLastUpdate() const; + void SetTickLastUpdate( int ); + + virtual bool IsRemovedOnReset( void ) const { return true; } // remove this bot when the NextBot manager calls Reset + + virtual CBaseCombatCharacter *GetEntity( void ) const = 0; + virtual class NextBotCombatCharacter *GetNextBotCombatCharacter( void ) const { return NULL; } + +#ifdef TERROR + virtual class SurvivorBot *MySurvivorBotPointer() const { return NULL; } +#endif + + // interfaces are never NULL - return base no-op interfaces at a minimum + virtual ILocomotion * GetLocomotionInterface( void ) const; + virtual IBody * GetBodyInterface( void ) const; + virtual IIntention * GetIntentionInterface( void ) const; + virtual IVision * GetVisionInterface( void ) const; + + /** + * Attempt to change the bot's position. Return true if successful. + */ + virtual bool SetPosition( const Vector &pos ); + virtual const Vector &GetPosition( void ) const; // get the global position of the bot + + /** + * Friend/enemy/neutral queries + */ + virtual bool IsEnemy( const CBaseEntity *them ) const; // return true if given entity is our enemy + virtual bool IsFriend( const CBaseEntity *them ) const; // return true if given entity is our friend + virtual bool IsSelf( const CBaseEntity *them ) const; // return true if 'them' is actually me + + /** + * Can we climb onto this entity? + */ + virtual bool IsAbleToClimbOnto( const CBaseEntity *object ) const; + + /** + * Can we break this entity? + */ + virtual bool IsAbleToBreak( const CBaseEntity *object ) const; + + /** + * Sometimes we want to pass through other NextBots. OnContact() will always + * be invoked, but collision resolution can be skipped if this + * method returns false. + */ + virtual bool IsAbleToBlockMovementOf( const INextBot *botInMotion ) const { return true; } + + /** + * Should we ever care about noticing physical contact with this entity? + */ + virtual bool ShouldTouch( const CBaseEntity *object ) const { return true; } + + /** + * This immobile system is used to track the global state of "am I actually moving or not". + * The OnStuck() event is only emitted when following a path, and paths can be recomputed, etc. + */ + virtual bool IsImmobile( void ) const; // return true if we haven't moved in awhile + virtual float GetImmobileDuration( void ) const; // how long have we been immobile + virtual void ClearImmobileStatus( void ); + virtual float GetImmobileSpeedThreshold( void ) const; // return units/second below which this actor is considered "immobile" + + /** + * Get the last PathFollower we followed. This method gives other interfaces a + * single accessor to the most recent Path being followed by the myriad of + * different PathFollowers used in the various behaviors the bot may be doing. + */ + virtual const PathFollower *GetCurrentPath( void ) const; + virtual void SetCurrentPath( const PathFollower *path ); + virtual void NotifyPathDestruction( const PathFollower *path ); // this PathFollower is going away, which may or may not be ours + + // between distance utility methods + virtual bool IsRangeLessThan( CBaseEntity *subject, float range ) const; + virtual bool IsRangeLessThan( const Vector &pos, float range ) const; + virtual bool IsRangeGreaterThan( CBaseEntity *subject, float range ) const; + virtual bool IsRangeGreaterThan( const Vector &pos, float range ) const; + virtual float GetRangeTo( CBaseEntity *subject ) const; + virtual float GetRangeTo( const Vector &pos ) const; + virtual float GetRangeSquaredTo( CBaseEntity *subject ) const; + virtual float GetRangeSquaredTo( const Vector &pos ) const; + + // event propagation + virtual INextBotEventResponder *FirstContainedResponder( void ) const; + virtual INextBotEventResponder *NextContainedResponder( INextBotEventResponder *current ) const; + + virtual bool IsDebugging( unsigned int type ) const; // return true if this bot is debugging any of the given types + virtual const char *GetDebugIdentifier( void ) const; // return the name of this bot for debugging purposes + virtual bool IsDebugFilterMatch( const char *name ) const; // return true if we match the given debug symbol + virtual void DisplayDebugText( const char *text ) const; // show a line of text on the bot in the world + void DebugConColorMsg( NextBotDebugType debugType, const Color &color, PRINTF_FORMAT_STRING const char *fmt, ... ); + + enum { + MAX_NEXTBOT_DEBUG_HISTORY = 100, + MAX_NEXTBOT_DEBUG_LINE_LENGTH = 256, + }; + struct NextBotDebugLineType + { + NextBotDebugType debugType; + char data[ MAX_NEXTBOT_DEBUG_LINE_LENGTH ]; + }; + void GetDebugHistory( unsigned int type, CUtlVector< const NextBotDebugLineType * > *lines ) const; // build a vector of debug history of the given types + //------------------------------------------------------------------------------ + + +private: + friend class INextBotComponent; + void RegisterComponent( INextBotComponent *comp ); // components call this to register themselves with the bot that contains them + INextBotComponent *m_componentList; // the first component + + const PathFollower *m_currentPath; // the path we most recently followed + + int m_id; + bool m_bFlaggedForUpdate; + int m_tickLastUpdate; + + unsigned int m_debugType; + mutable int m_debugDisplayLine; + + Vector m_immobileAnchor; + CountdownTimer m_immobileCheckTimer; + IntervalTimer m_immobileTimer; + void UpdateImmobileStatus( void ); + + mutable ILocomotion *m_baseLocomotion; + mutable IBody *m_baseBody; + mutable IIntention *m_baseIntention; + mutable IVision *m_baseVision; + //mutable IAttention *m_baseAttention; + + // Debugging info + void ResetDebugHistory( void ); + CUtlVector< NextBotDebugLineType * > m_debugHistory; +}; + + +inline const PathFollower *INextBot::GetCurrentPath( void ) const +{ + return m_currentPath; +} + +inline void INextBot::SetCurrentPath( const PathFollower *path ) +{ + m_currentPath = path; +} + +inline void INextBot::NotifyPathDestruction( const PathFollower *path ) +{ + if ( m_currentPath == path ) + m_currentPath = NULL; +} + + +inline ILocomotion *INextBot::GetLocomotionInterface( void ) const +{ + // these base interfaces are lazy-allocated (instead of being fully instanced classes) for two reasons: + // 1) so the memory is only used if needed + // 2) so the component is registered properly + if ( m_baseLocomotion == NULL ) + { + m_baseLocomotion = new ILocomotion( const_cast< INextBot * >( this ) ); + } + + return m_baseLocomotion; +} + +inline IBody *INextBot::GetBodyInterface( void ) const +{ + if ( m_baseBody == NULL ) + { + m_baseBody = new IBody( const_cast< INextBot * >( this ) ); + } + + return m_baseBody; +} + +inline IIntention *INextBot::GetIntentionInterface( void ) const +{ + if ( m_baseIntention == NULL ) + { + m_baseIntention = new IIntention( const_cast< INextBot * >( this ) ); + } + + return m_baseIntention; +} + +inline IVision *INextBot::GetVisionInterface( void ) const +{ + if ( m_baseVision == NULL ) + { + m_baseVision = new IVision( const_cast< INextBot * >( this ) ); + } + + return m_baseVision; +} + +inline int INextBot::GetBotId() const +{ + return m_id; +} + +inline void INextBot::FlagForUpdate( bool b ) +{ + m_bFlaggedForUpdate = b; +} + +inline bool INextBot::IsFlaggedForUpdate() +{ + return m_bFlaggedForUpdate; +} + +inline int INextBot::GetTickLastUpdate() const +{ + return m_tickLastUpdate; +} + +inline void INextBot::SetTickLastUpdate( int tick ) +{ + m_tickLastUpdate = tick; +} + +inline bool INextBot::IsImmobile( void ) const +{ + return m_immobileTimer.HasStarted(); +} + +inline float INextBot::GetImmobileDuration( void ) const +{ + return m_immobileTimer.GetElapsedTime(); +} + +inline void INextBot::ClearImmobileStatus( void ) +{ + m_immobileTimer.Invalidate(); + m_immobileAnchor = GetEntity()->GetAbsOrigin(); +} + +inline float INextBot::GetImmobileSpeedThreshold( void ) const +{ + return 30.0f; +} + +inline INextBotEventResponder *INextBot::FirstContainedResponder( void ) const +{ + return m_componentList; +} + + +inline INextBotEventResponder *INextBot::NextContainedResponder( INextBotEventResponder *current ) const +{ + return static_cast< INextBotComponent * >( current )->m_nextComponent; +} + + +#endif // _NEXT_BOT_INTERFACE_H_ |