-
Notifications
You must be signed in to change notification settings - Fork 17
/
Copy pathNextBotInterface.h
302 lines (241 loc) · 9.57 KB
/
NextBotInterface.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
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_