aboutsummaryrefslogtreecommitdiff
path: root/sp/src/game/server/ai_navigator.h
blob: a2100943c62da129d21c95a519ed2c4b4b406772 (plain) (blame)
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
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//

#ifndef AI_NAVIGATOR_H
#define AI_NAVIGATOR_H

#ifdef _WIN32
#pragma once
#endif

#include "simtimer.h"
#include "ai_component.h"
#include "ai_navgoaltype.h"
#include "ai_navtype.h"
#include "ai_motor.h"

class CAI_BaseNPC;
class CAI_Motor;
class CAI_Route;
class CAI_Path;
class CAI_Pathfinder;
class CAI_LocalNavigator;
struct AI_Waypoint_t;
class CAI_WaypointList;
class CAI_Network;
struct AIMoveTrace_t;
struct AILocalMoveGoal_t;
typedef int AI_TaskFailureCode_t;

//-----------------------------------------------------------------------------
// Debugging tools
//-----------------------------------------------------------------------------

#define DEBUG_AI_NAVIGATION 1
#ifdef DEBUG_AI_NAVIGATION
extern ConVar ai_debug_nav;
#define DbgNav() ai_debug_nav.GetBool()
#define DbgNavMsg( pAI, pszMsg ) \
	do \
	{ \
		if (DbgNav()) \
			DevMsg( pAI, CFmtStr( "[Nav] %s", static_cast<const char *>(pszMsg) ) ); \
	} while (0)
#define DbgNavMsg1( pAI, pszMsg, a ) DbgNavMsg( pAI, CFmtStr(static_cast<const char *>(pszMsg), (a) ) )
#define DbgNavMsg2( pAI, pszMsg, a, b ) DbgNavMsg( pAI, CFmtStr(static_cast<const char *>(pszMsg), (a), (b) ) )
#else
#define DbgNav() false
#define DbgNavMsg( pAI, pszMsg ) ((void)0)
#define DbgNavMsg1( pAI, pszMsg, a ) ((void)0)
#define DbgNavMsg2( pAI, pszMsg, a, b ) ((void)0)
#endif


//-----------------------------------------------------------------------------
// STRUCTURES & ENUMERATIONS
//-----------------------------------------------------------------------------

DECLARE_POINTER_HANDLE( AI_PathNode_t );

//-------------------------------------
// Purpose: Constants used to specify the properties of a requested navigation
//			goal.
//-------------------------------------

// Navigator should use the default or previously set tolerance
const float AIN_DEF_TOLERANCE  = -1.0;

// Navigator should use the hull size as the tolerance
const float AIN_HULL_TOLERANCE = -2.0;

// Goal does not specify a new activity
const Activity AIN_DEF_ACTIVITY = ACT_INVALID;

// Goal has no target
CBaseEntity * const AIN_NO_TARGET  = NULL;

// Goal does not specify a new target, use the existing one, if any
CBaseEntity * const AIN_DEF_TARGET = (AIN_NO_TARGET + 1);

// Goal does not specify a vector location
extern const Vector AIN_NO_DEST;

// Goal does not specify a node location
#define AIN_NO_NODE ((AI_PathNode_t)-1)


//-------------------------------------

enum AI_NavGoalFlags_t
{
	// While navigating, try to face the destination point
	AIN_YAW_TO_DEST			= 0x01,
	
	// If I'm a goal of type GOALTYPE_TARGETENT, update my goal position every time I think
	AIN_UPDATE_TARGET_POS	= 0x02,

	// If navigating on a designer placed path, don't use pathfinder between waypoints, just do it
	AIN_NO_PATHCORNER_PATHFINDING = 0x04,

	AIN_DEF_FLAGS			= 0,
};

//-------------------------------------

enum AI_NavSetGoalFlags_t
{
	// Reset the navigator's navigation to the default state
	AIN_CLEAR_PREVIOUS_STATE 	= 0x01,
	
	// Clear out the target entity, while retaining other settings
	AIN_CLEAR_TARGET			= 0x02,
	
	// If the navigate fails, return navigation to the default state
	AIN_DISCARD_IF_FAIL			= 0x04,

	// Don't signal TaskFail() if the pathfind fails, just return the result
	AIN_NO_PATH_TASK_FAIL		= 0x08,
};

//-------------------------------------

enum AI_NpcBlockHandling_t
{
	AISF_BLOCK,
	AISF_AVOID,
	AISF_IGNORE,
};

//-------------------------------------

enum AI_NavPathProgress_t
{
	AINPP_NO_CHANGE,
	AINPP_ADVANCED,
	AINPP_COMPLETE,
	AINPP_BLOCKED,
};

//-------------------------------------
// Purpose: Describes a navigation request. The various constructors simply
//			allow ease of use in the common cases.
//-------------------------------------

struct AI_NavGoal_t
{
	// Goal is unspecifed, or not a specific location
	AI_NavGoal_t( GoalType_t    type	  = GOALTYPE_INVALID,
				  Activity		activity  = AIN_DEF_ACTIVITY, 
				  float			tolerance = AIN_DEF_TOLERANCE,
				  unsigned 		flags     = AIN_DEF_FLAGS,
				  CBaseEntity * pTarget   = AIN_DEF_TARGET);
	
	// Goal is a specific location, and GOALTYPE_LOCATION
	AI_NavGoal_t( const Vector &dest,
				  Activity		activity  = AIN_DEF_ACTIVITY, 
				  float			tolerance = AIN_DEF_TOLERANCE,
				  unsigned 		flags     = AIN_DEF_FLAGS,
				  CBaseEntity * pTarget   = AIN_DEF_TARGET);

	// Goal is a specific location and goal type
	AI_NavGoal_t( GoalType_t 	type,
				  const Vector &dest,
				  Activity		activity  = AIN_DEF_ACTIVITY, 
				  float			tolerance = AIN_DEF_TOLERANCE,
				  unsigned 		flags     = AIN_DEF_FLAGS,
				  CBaseEntity * pTarget   = AIN_DEF_TARGET);

	// Goal is a specific node, and GOALTYPE_LOCATION
	AI_NavGoal_t( AI_PathNode_t	destNode,
				  Activity		activity  = AIN_DEF_ACTIVITY, 
				  float			tolerance = AIN_DEF_TOLERANCE,
				  unsigned 		flags     = AIN_DEF_FLAGS,
				  CBaseEntity *	pTarget   = AIN_DEF_TARGET);
				  
	// Goal is a specific location and goal type
	AI_NavGoal_t( GoalType_t	type,
				  AI_PathNode_t	destNode,
				  Activity		activity  = AIN_DEF_ACTIVITY, 
				  float			tolerance = AIN_DEF_TOLERANCE,
				  unsigned 		flags     = AIN_DEF_FLAGS,
				  CBaseEntity *	pTarget   = AIN_DEF_TARGET);
				  
	//----------------------------------
	
	// What type of goal is this
	GoalType_t 		type;

	// The destination, either as a vector, or as a path node
	Vector 			dest;
	AI_PathNode_t	destNode;

	// The activity to use, or none if a previosly set activity should be used
	Activity		activity;
	
	// The predicted activity used after arrival
	Activity		arrivalActivity;
	int				arrivalSequence;

	// The tolerance of success, or none if a previosly set tolerance should be used
	float			tolerance;

	// How far to permit an initial simplification of path
	// (will use default if this value is less than the default)
	float			maxInitialSimplificationDist;

	// Optional flags specifying
	unsigned		flags;

	// The target of the navigation, primarily used to ignore the entity in hull and line traces
	CBaseEntity *	pTarget;
};

//-------------------------------------
// Purpose: Used to describe rules for advance on a (fly) path. There's nothing
// 			specifically "flying" about it, other than it came from an attempte
//			to consolodate duplicated code in the various fliers. It may serve
//			a more general purpose in the future. The constructor takes those
//			arguments that can usually be specified just once (as in a 
//			local static constructor)
//-------------------------------------

struct AI_ProgressFlyPathParams_t
{
	AI_ProgressFlyPathParams_t( unsigned _collisionMask, 
							   	float _strictPointTolerance = 32.0, float _blockTolerance = 0.0,
							   	float _waypointTolerance = 100, float _goalTolerance = 12,
							   	AI_NpcBlockHandling_t _blockHandling = AISF_BLOCK )
	 :	collisionMask( _collisionMask ),
		strictPointTolerance( _strictPointTolerance ),
		blockTolerance( _blockTolerance ),
		waypointTolerance( _waypointTolerance ),
		goalTolerance( _goalTolerance ),
		blockHandling( _blockHandling ),
		pTarget( NULL ),
		bTrySimplify( true )
	{
	}

	void SetCurrent( const CBaseEntity *pNewTarget, bool bNewTrySimplify = true )
	{
		pTarget 	 = pNewTarget;
		bTrySimplify = bNewTrySimplify;
	}

	//----------------------------------
	
	// Fields that tend to stay constant
	unsigned 				collisionMask;
	float 					strictPointTolerance;
	float 					blockTolerance; 		// @TODO (toml 07-03-02): rename "blockTolerance". This is specifically the "simplify" block tolerance. See SimplifyFlyPath()
	float 					waypointTolerance;
	float 					goalTolerance;			// @TODO (toml 07-03-02): goalTolerance appears to have come into existence because
													// noone had set a good tolerance in the path itself. It is therefore redundant,
													// and more than likely should be excised
	AI_NpcBlockHandling_t 	blockHandling;			// @TODO (toml 07-03-02): rename "blockHandling". This is specifically the "simplify" block handling. See SimplifyFlyPath()

	// Fields that tend to change
	const CBaseEntity *		pTarget;
	bool 					bTrySimplify;
};

//-----------------------------------------------------------------------------
// CAI_Navigator
//
// Purpose: Implements pathing and path navigaton logic
//-----------------------------------------------------------------------------

class CAI_Navigator : public CAI_Component,
					  public CAI_DefMovementSink
{
	typedef CAI_Component BaseClass;
public:
	// --------------------------------
	
	CAI_Navigator(CAI_BaseNPC *pOuter);
	virtual ~CAI_Navigator();

	virtual void Init( CAI_Network *pNetwork );
	
	// --------------------------------

	void SetPathcornerPathfinding( bool fNewVal)					{ m_bNoPathcornerPathfinds = !fNewVal; }
	void SetRememberStaleNodes( bool fNewVal)						{ m_fRememberStaleNodes = fNewVal; }
	void SetValidateActivitySpeed( bool bValidateActivitySpeed )	{ m_bValidateActivitySpeed = bValidateActivitySpeed; }
	void SetLocalSucceedOnWithinTolerance( bool fNewVal )			{ m_bLocalSucceedOnWithinTolerance = fNewVal; }

	// --------------------------------

	void Save( ISave &save );
	void Restore( IRestore &restore );
	
	// --------------------------------
	// Methods to issue movement directives
	// --------------------------------

	// Simple pathfind
	virtual bool 		SetGoal( const AI_NavGoal_t &goal, unsigned flags = 0 );
	
	// Change the target of the path
	virtual bool		SetGoalTarget( CBaseEntity *pEntity, const Vector &offset );
	
	// Fancy pathing
	bool				SetRadialGoal( const Vector &destination, const Vector &center, float radius, float arc, float stepDist, bool bClockwise, bool bAirRoute = false );
	bool 				SetRandomGoal( float minPathLength, const Vector &dir = vec3_origin );
	bool 				SetRandomGoal( const Vector &from, float minPathLength, const Vector &dir = vec3_origin );
	bool				SetDirectGoal( const Vector &goalPos, Navigation_t navType = NAV_GROUND );
	
	bool				SetWanderGoal( float minRadius, float maxRadius );
	bool				SetVectorGoal( const Vector &dir, float targetDist, float minDist = 0, bool fShouldDeflect = false );
	bool				SetVectorGoalFromTarget( const Vector &goalPos, float minDist = 0, bool fShouldDeflect = false );

	bool				FindVectorGoal( Vector *pResult, const Vector &dir, float targetDist, float minDist = 0, bool fShouldDeflect = false );
	
	// Path manipulation
	bool 				PrependLocalAvoidance( float distObstacle, const AIMoveTrace_t &directTrace );
	void 				PrependWaypoint( const Vector &newPoint, Navigation_t navType, unsigned waypointFlags = 0 );
	
	// Query or change the movement activity
	Activity 			GetMovementActivity() const;
	Activity 			SetMovementActivity(Activity activity);
	int		 			GetMovementSequence();
	void				SetMovementSequence( int sequence );

	// Query or change the Arrival activity
	Activity 			GetArrivalActivity() const;
	void				SetArrivalActivity( Activity activity );
	int					GetArrivalSequence( int curSequence );
	void				SetArrivalSequence( int sequence );

	// Set the facing direction at arrival
	void				SetArrivalDirection( const Vector &goalDirection );
	void				SetArrivalDirection( const QAngle &goalAngle );
	void				SetArrivalDirection( CBaseEntity *pTarget );
	Vector				GetArrivalDirection( );

	// Set the speed to reach at arrival (
	void				SetArrivalSpeed( float flSpeed );
	float				GetArrivalSpeed();

	// Set the estimated distance to stop before the actual goal
	void				SetArrivalDistance( float flDistance );
	float				GetArrivalDistance( ) const;

	// Query or change the goal tolerance
	float				GetGoalTolerance() const;
	void				SetGoalTolerance(float tolerance);

	GoalType_t			GetGoalType() const;
	const Vector &		GetGoalPos() const;
	CBaseEntity *		GetGoalTarget();
	int					GetGoalFlags() const;
	
	const Vector &		GetCurWaypointPos() const;
	int 				GetCurWaypointFlags() const;

	bool				CurWaypointIsGoal() const;

	bool				GetPointAlongPath( Vector *pResult, float distance, bool fReducibleOnly = false );

	float				GetPathDistanceToGoal();
	float				GetPathTimeToGoal();

	// Query if there is a current goal
	bool				IsGoalSet() const;

	// Query if the current goal is active, meaning the navigator has a path in can progress on
	bool				IsGoalActive() const;

	// Update the goal position to reflect current conditions
	bool 				RefindPathToGoal( bool fSignalTaskStatus = true, bool bDontIgnoreBadLinks = false );
	bool 				UpdateGoalPos( const Vector & );
	
	// Wrap up current locomotion
	void				StopMoving( bool bImmediate = true );

	// Discard the current goal, use StopMoving() if just executing a normal stop
	bool 				ClearGoal();

	// --------------------------------

	void				SetAllowBigStep( CBaseEntity *pEntToStepOff )	{ if ( !pEntToStepOff || !pEntToStepOff->IsWorld() ) m_hBigStepGroundEnt = pEntToStepOff; }

	// --------------------------------
	bool				SetGoalFromStoppingPath();
	void				IgnoreStoppingPath();
	
	// --------------------------------
	// Navigation mode
	// --------------------------------
	Navigation_t		GetNavType() const					{ return m_navType; }
	void				SetNavType( Navigation_t navType );

	bool 				IsInterruptable() const				{ return ( m_navType != NAV_CLIMB && m_navType != NAV_JUMP ); }
	
	// --------------------------------
	// Pathing
	// --------------------------------
	
	AI_NavPathProgress_t ProgressFlyPath( const AI_ProgressFlyPathParams_t &params); // note: will not return "blocked"

	AI_PathNode_t		GetNearestNode();
	Vector				GetNodePos( AI_PathNode_t );

	CAI_Network *		GetNetwork()						{ return m_pAINetwork; }
	const CAI_Network *	GetNetwork() const					{ return m_pAINetwork; }
	void 				SetNetwork( CAI_Network *pNetwork ) { m_pAINetwork = pNetwork; }
	
	CAI_Path *			GetPath()							{ return m_pPath; }
	const CAI_Path *	GetPath() const						{ return m_pPath; }

	void				AdvancePath();

	virtual bool		SimplifyPath( bool bFirstForPath = false, float maxDist = -1 );
	void				SimplifyFlyPath( unsigned collisionMask, const CBaseEntity *pTarget, 
										 float strictPointTolerance = 32.0, float blockTolerance = 0.0,
										 AI_NpcBlockHandling_t blockHandling = AISF_BLOCK);
	bool				SimplifyFlyPath(  const AI_ProgressFlyPathParams_t &params );
	
	bool				CanFitAtNode(int nodeNum, unsigned int collisionMask = MASK_NPCSOLID_BRUSHONLY); 
	float				MovementCost( int moveType, Vector &vecStart, Vector &vecEnd );

	bool				CanFitAtPosition( const Vector &vStartPos, unsigned int collisionMask, bool bIgnoreTransients = false, bool bAllowPlayerAvoid = true );
	bool				IsOnNetwork() const			{ return !m_bNotOnNetwork; }

	void				SetMaxRouteRebuildTime(float time) { m_timePathRebuildMax = time;			}

	// --------------------------------
	void				DrawDebugRouteOverlay( void );

	// --------------------------------
	// Miscellany
	// --------------------------------

	float				CalcYawSpeed();
	float				GetStepDownMultiplier();
	CBaseEntity *		GetNextPathcorner( CBaseEntity *pPathCorner );
	virtual void		OnScheduleChange();
	
	// --------------------------------
	
	// See comments at CAI_BaseNPC::Move()
	virtual bool		Move( float flInterval = 0.1 );

	// --------------------------------

	CBaseEntity *		GetBlockingEntity()	{ return m_hLastBlockingEnt; }
	
protected:
	// --------------------------------
	//
	// Common services provided by CAI_BaseNPC
	//
	CBaseEntity *		GetNavTargetEntity();
	void				TaskMovementComplete();
	float				MaxYawSpeed();
	void				SetSpeed( float );

	// --------------------------------

	CAI_Motor *			GetMotor()			{ return m_pMotor; }
	const CAI_Motor *	GetMotor() const	{ return m_pMotor; }

	CAI_MoveProbe *		GetMoveProbe()		{ return m_pMoveProbe; }
	const CAI_MoveProbe *GetMoveProbe() const { return m_pMoveProbe; }

	CAI_LocalNavigator *GetLocalNavigator()				{ return m_pLocalNavigator; }
	const CAI_LocalNavigator *GetLocalNavigator() const { return m_pLocalNavigator; }

	CAI_Pathfinder *	GetPathfinder();
	const CAI_Pathfinder *GetPathfinder() const;

	virtual void		OnClearPath(void);

	// --------------------------------
	
	virtual void OnNewGoal();
	virtual void OnNavComplete();
			void OnNavFailed( bool bMovement = false );
			void OnNavFailed( AI_TaskFailureCode_t code, bool bMovement = false );
			void OnNavFailed( const char *pszGeneralFailText, bool bMovement = false );
	
	// --------------------------------
	
 	virtual AIMoveResult_t MoveNormal();

	// Navigation execution
	virtual AIMoveResult_t MoveClimb();
	virtual AIMoveResult_t MoveJump();

	// --------------------------------
	
	virtual AIMoveResult_t MoveEnact( const AILocalMoveGoal_t &baseMove );
		
protected:
	// made this virtual so strider can implement hover behavior with a navigator
	virtual void 		MoveCalcBaseGoal(  AILocalMoveGoal_t *pMoveGoal);
	
private:
	virtual bool		OnCalcBaseMove( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult );
	virtual bool		OnObstructionPreSteer( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult );
	virtual bool		OnFailedSteer( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult );
	virtual bool 		OnFailedLocalNavigation( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult );
	virtual bool		OnInsufficientStopDist( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult );
	virtual bool		OnMoveStalled( const AILocalMoveGoal_t &move );
	virtual bool		OnMoveExecuteFailed( const AILocalMoveGoal_t &move, const AIMoveTrace_t &trace, AIMotorMoveResult_t fMotorResult, AIMoveResult_t *pResult );
	virtual bool		OnMoveBlocked( AIMoveResult_t *pResult );
	
	void ResetCalculations();
	
	// Methods shared between ground and fly movement
	bool 				PreMove();
	virtual bool 		MoveUpdateWaypoint( AIMoveResult_t *pResult );
	bool 				IsMovingOutOfWay( const AILocalMoveGoal_t &moveGoal, float distClear );
	bool 				DelayNavigationFailure( const AIMoveTrace_t &trace );

	static void			CalculateDeflection( const Vector &start, const Vector &dir, const Vector &normal, Vector *pResult );

	// --------------------------------
	// Pathfinding
	// --------------------------------

public:
	float				GetPathDistToCurWaypoint() const;
	float				GetPathDistToGoal() const;
	float				BuildAndGetPathDistToGoal();

	// --------------------------------

	int					GetNavFailCounter() const;
	void 				ClearNavFailCounter();
	float				GetLastNavFailTime() const;
	bool				TeleportAlongPath();

private:
	bool				DoFindPath( void );							// Find a route
	bool				DoFindPathToPathcorner( CBaseEntity *pPathCorner );

protected:
	virtual bool		DoFindPathToPos(void);
	virtual	bool		ShouldOptimizeInitialPathSegment( AI_Waypoint_t * ) { return true; }

private:
	void				ClearPath(void);
	void				SaveStoppingPath( void );

protected:
	virtual bool 		GetStoppingPath( CAI_WaypointList *pClippedWaypoints );

private:
	bool				FindPath( const AI_NavGoal_t &goal, unsigned flags );
	bool				FindPath( bool fSignalTaskStatus = true, bool bDontIgnoreBadLinks = false );
	bool				MarkCurWaypointFailedLink( void );			// Call when route fails

	struct SimplifyForwardScanParams
	{
		float scanDist;
		float radius;
		float increment;
		int maxSamples;
	};

	bool 				ShouldAttemptSimplifyTo( const Vector &pos );
	bool 				ShouldSimplifyTo( bool passedDetour, const Vector &pos );
	bool 				SimplifyPathForwardScan( const CAI_Navigator::SimplifyForwardScanParams &params );
	bool				SimplifyPathForwardScan( const SimplifyForwardScanParams &params, AI_Waypoint_t *pCurWaypoint, const Vector &curPoint, float distRemaining, bool skip, bool passedDetour, int *pTestCount );
	bool 				SimplifyPathForward( float maxDist = -1 );
	bool 				SimplifyPathBacktrack();
	bool 				SimplifyPathQuick();
	void				SimplifyPathInsertSimplification( AI_Waypoint_t *pSegmentStart, const Vector &point );

    // ---------------------------------

	static bool			ActivityIsLocomotive( Activity );
    
    // ---------------------------------

	Navigation_t		m_navType;									// My current navigation type (walk,fly)
	bool				m_fNavComplete;
	bool				m_bLastNavFailed;

	// Cached pointers to other components, for efficiency
	CAI_Motor *			m_pMotor;
	CAI_MoveProbe *		m_pMoveProbe;
	CAI_LocalNavigator *m_pLocalNavigator;

    // ---------------------------------

	CAI_Network*		m_pAINetwork;			 					// My current AINetwork
	CAI_Path*			m_pPath;									// My current route

	CAI_WaypointList *	m_pClippedWaypoints;
	float				m_flTimeClipped;
	Activity			m_PreviousMoveActivity;
	Activity			m_PreviousArrivalActivity;

	bool				m_bValidateActivitySpeed;
	bool				m_bCalledStartMove;
	
	bool				m_bNotOnNetwork;							// This NPC has no reachable nodes!

	float				m_flNextSimplifyTime;						// next time we should try to simplify our route
	bool				m_bForcedSimplify;
	float				m_flLastSuccessfulSimplifyTime;

	float				m_flTimeLastAvoidanceTriangulate;

	// --------------

	float				m_timePathRebuildMax;						// How long to try rebuilding path before failing task
	float				m_timePathRebuildDelay;						// How long to wait before trying to rebuild again

	float				m_timePathRebuildFail;						// Current global time when should fail building path
	float				m_timePathRebuildNext;						// Global time to try rebuilding again

	// --------------
	
	bool				m_fRememberStaleNodes;
	bool				m_bNoPathcornerPathfinds;
	bool				m_bLocalSucceedOnWithinTolerance;

	// --------------
	
	bool				m_fPeerMoveWait;
	EHANDLE				m_hPeerWaitingOn;
	CSimTimer 			m_PeerWaitMoveTimer;
	CSimTimer			m_PeerWaitClearTimer;

	CSimTimer			m_NextSidestepTimer;

	// --------------

	EHANDLE				m_hBigStepGroundEnt;
	EHANDLE				m_hLastBlockingEnt;

	// --------------

	Vector				m_vPosBeginFailedSteer;
	float				m_timeBeginFailedSteer;

	// --------------

	int					m_nNavFailCounter;
	float				m_flLastNavFailTime;
public:
	DECLARE_SIMPLE_DATADESC();
};


//-----------------------------------------------------------------------------
// AI_NavGoal_t inline methods
//-----------------------------------------------------------------------------

inline AI_NavGoal_t::AI_NavGoal_t( GoalType_t   type,
								   Activity		activity, 
								   float		tolerance,
								   unsigned 	flags,
								   CBaseEntity *pTarget)
 :	type(type),
	dest(AIN_NO_DEST),
	destNode(AIN_NO_NODE),
	activity(activity),
	tolerance(tolerance),
	maxInitialSimplificationDist(-1),
	flags(flags),
	pTarget(pTarget),
	arrivalActivity( AIN_DEF_ACTIVITY ),
	arrivalSequence( ACT_INVALID )
{
}

inline AI_NavGoal_t::AI_NavGoal_t( const Vector &dest,
								   Activity		activity, 
								   float		tolerance,
								   unsigned 	flags,
								   CBaseEntity *pTarget)
 :	type(GOALTYPE_LOCATION),
	dest(dest),
	destNode(AIN_NO_NODE),
	activity(activity),
	tolerance(tolerance),
	maxInitialSimplificationDist(-1),
	flags(flags),
	pTarget(pTarget),
	arrivalActivity( AIN_DEF_ACTIVITY ),
	arrivalSequence( ACT_INVALID )
{
}

inline AI_NavGoal_t::AI_NavGoal_t( GoalType_t 	type,
								   const Vector &dest,
								   Activity		activity, 
								   float		tolerance,
								   unsigned 	flags,
								   CBaseEntity *pTarget)
 :	type(type),
	dest(dest),
	destNode(AIN_NO_NODE),
	activity(activity),
	tolerance(tolerance),
	maxInitialSimplificationDist(-1),
	flags(flags),
	pTarget(pTarget),
	arrivalActivity( AIN_DEF_ACTIVITY ),
	arrivalSequence( ACT_INVALID )
{
}

inline AI_NavGoal_t::AI_NavGoal_t( AI_PathNode_t destNode,
								   Activity		 activity, 
								   float		 tolerance,
								   unsigned 	 flags,
								   CBaseEntity * pTarget)
 :	type(GOALTYPE_LOCATION),
	dest(AIN_NO_DEST),
	destNode(destNode),
	activity(activity),
	tolerance(tolerance),
	maxInitialSimplificationDist(-1),
	flags(flags),
	pTarget(pTarget),
	arrivalActivity( AIN_DEF_ACTIVITY ),
	arrivalSequence( ACT_INVALID )
{
}

inline AI_NavGoal_t::AI_NavGoal_t( GoalType_t	 type,
								   AI_PathNode_t destNode,
								   Activity		 activity, 
								   float		 tolerance,
								   unsigned 	 flags,
								   CBaseEntity * pTarget)
 :	type(type),
	dest(AIN_NO_DEST),
	destNode(destNode),
	activity(activity),
	tolerance(tolerance),
	maxInitialSimplificationDist(-1),
	flags(flags),
	pTarget(pTarget),
	arrivalActivity( AIN_DEF_ACTIVITY ),
	arrivalSequence( ACT_INVALID )
{
}

//-----------------------------------------------------------------------------

#endif // AI_NAVIGATOR_H