aboutsummaryrefslogtreecommitdiff
path: root/mp/src/game/server/ai_trackpather.h
blob: a2ce734515d6fd6a6a79677f0a3974fb15b0031c (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
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//

#ifndef AI_TRACKPATHER_H
#define AI_TRACKPATHER_H

#if defined( _WIN32 )
#pragma once
#endif


#include "ai_basenpc.h"


class CPathTrack;

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

class CAI_TrackPather : public CAI_BaseNPC
{
	DECLARE_CLASS( CAI_TrackPather, CAI_BaseNPC );
	DECLARE_DATADESC();
public:

	bool			IsOnPathTrack()							{ return (m_pCurrentPathTarget != NULL); }

protected:	
	void			InitPathingData( float flTrackArrivalTolerance, float flTargetDistance, float flAvoidDistance );
	virtual bool	GetTrackPatherTarget( Vector *pPos ) { return false; }
	virtual CBaseEntity *GetTrackPatherTargetEnt()	{ return NULL; }

	const Vector &	GetDesiredPosition() const				{ return m_vecDesiredPosition; 	}
	void 			SetDesiredPosition( const Vector &v )	{ m_vecDesiredPosition = v; 	}
	const Vector &	GetGoalOrientation() const				{ return m_vecGoalOrientation; 	}
	void 			SetGoalOrientation( const Vector &v )	{ m_vecGoalOrientation = v; 	}

	bool			CurPathTargetIsDest()					{ return ( m_pDestPathTarget == m_pCurrentPathTarget ); }

	virtual bool	HasReachedTarget( void ) 				{ return (WorldSpaceCenter() - m_vecDesiredPosition).Length() < 128; }

	CPathTrack *	GetDestPathTarget()						{ return m_pDestPathTarget;		}

	bool			IsInForcedMove() const					{ return m_bForcedMove;			}
	void			ClearForcedMove()						{ m_bForcedMove = false;		}

	float			GetPathMaxSpeed() const					{ return m_flPathMaxSpeed;		}

	void			OnSave( IEntitySaveUtils *pUtils );
	void			OnRestore( void );

protected:
	enum PauseState_t
	{
		PAUSE_NO_PAUSE = 0,
		PAUSED_AT_POSITION,
		PAUSE_AT_NEXT_LOS_POSITION,

		PAUSE_FORCE_DWORD = 0xFFFFFFFF,
	};

	// Sets a track
	void SetTrack( string_t strTrackName );
	void SetTrack( CBaseEntity *pGoalEnt );

	// Fly to a particular track point via the path
	virtual void InputFlyToPathTrack( inputdata_t &inputdata );

	// Updates the nav target if we've reached it
	void UpdateTrackNavigation( void );

	// Computes distance + nearest point from the current path..
	float ClosestPointToCurrentPath( Vector *pVecPoint ) const;

	// Computes a "path" velocity at a particular point along the current path
	void ComputePathTangent( float t, Vector *pVecTangent ) const;

	// Computes the *normalized* velocity at which the helicopter should approach the final point
	void ComputeNormalizedDestVelocity( Vector *pVecVelocity ) const;

	// Sets the farthest path distance
	void SetFarthestPathDist( float flMaxPathDist );

	// Returns the next/previous path along our current path
	CPathTrack *NextAlongCurrentPath( CPathTrack *pPath ) const;
	CPathTrack *PreviousAlongCurrentPath( CPathTrack *pPath ) const;

	// Adjusts a "next"most node based on the current movement direction
	CPathTrack *AdjustForMovementDirection( CPathTrack *pPath ) const;

	// Enemy visibility check
	virtual CBaseEntity *FindTrackBlocker( const Vector &vecViewPoint, const Vector &vecTargetPos );

	// Compute a point n units along a path
	void ComputePointAlongPath( const Vector &vecStartPoint, float flDistance, Vector *pTarget );

	// Are we leading?
	bool IsLeading() const { return m_bLeading && !m_bForcedMove; }

	// Leading + leading distance
	void EnableLeading( bool bEnable );
	void SetLeadingDistance( float flLeadDistance );
	float GetLeadingDistance( ) const;

	// Compute a point n units along the current path from our current position
	// (but don't pass the desired target point)
	void ComputePointAlongCurrentPath( float flDistance, float flPerpDist, Vector *pTarget );

	// Returns the perpendicular distance of the target from the nearest path point
	float TargetDistanceToPath() const { return m_flTargetDistFromPath; }

	// Returns the speed of the target relative to the path
	float TargetSpeedAlongPath() const;

	// Returns the speed of the target *across* the path
	float TargetSpeedAcrossPath() const;

	// Compute a path direction
	void ComputePathDirection( CPathTrack *pPath, Vector *pVecPathDir );

	// What's the current path direction?
	void CurrentPathDirection( Vector *pVecPathDir );

	// Returns the max distance we can be from the path
	float MaxDistanceFromCurrentPath() const;

	// true to use farthest, false for nearest
	void UseFarthestPathPoint( bool useFarthest );

	// Moves to an explicit track point
	void MoveToTrackPoint( CPathTrack *pTrack );

	// Sets up a new current path target
	void SetupNewCurrentTarget( CPathTrack *pTrack );

	// Compute the distance to the leading position
	float ComputeDistanceToLeadingPosition();

	// Compute the distance to the target position
	float ComputeDistanceToTargetPosition();

	// Set the pause state.
	void SetPauseState( PauseState_t pauseState ) { m_nPauseState = pauseState; }

	// Does this path track have LOS to the target?
	bool HasLOSToTarget( CPathTrack *pTrack );

	// FIXME: Work this back into the base class
	virtual bool ShouldUseFixedPatrolLogic() { return false; }

	// Deal with teleportation
	void Teleported();

private:

	CPathTrack		*BestPointOnPath( CPathTrack *pPath, const Vector &targetPos, float avoidRadius, bool visible, bool bFarthestPointOnPath );

	// Input methods
	void InputSetTrack( inputdata_t &inputdata );
	void InputChooseFarthestPathPoint( inputdata_t &inputdata );
	void InputChooseNearestPathPoint( inputdata_t &inputdata );
	void InputStartBreakableMovement( inputdata_t &inputdata );
	void InputStopBreakableMovement( inputdata_t &inputdata );
	void InputStartPatrol( inputdata_t &inputdata );
	void InputStopPatrol( inputdata_t &inputdata );
	void InputStartLeading( inputdata_t &inputdata );
	void InputStopLeading( inputdata_t &inputdata );

	// Obsolete, for backward compatibility
	void InputStartPatrolBreakable( inputdata_t &inputdata );

	// Flies to a point on a track
	void FlyToPathTrack( string_t strTrackName );

	// Selects a new destination target
	void SelectNewDestTarget();

	// Makes sure we've picked the right position along the path if we're chasing an enemy
	void UpdateTargetPosition( );

	// Moves to the track
	void UpdateCurrentTarget();
	void UpdateCurrentTargetLeading();

	// Track debugging info
	void VisualizeDebugInfo( const Vector &vecNearestPoint, const Vector &vecTarget );

	// Moves to the closest track point
	void MoveToClosestTrackPoint( CPathTrack *pTrack );

	// Are the two path tracks connected?
	bool IsOnSameTrack( CPathTrack *pPath1, CPathTrack *pPath2 ) const;

	// Is pPathTest in "front" of pPath on the same path? (Namely, does GetNext() get us there?)
	bool IsForwardAlongPath( CPathTrack *pPath, CPathTrack *pPathTest ) const;

	// Purpose: 
	void UpdateTargetPositionLeading( void );

	// Compute a point n units along a path
	CPathTrack *ComputeLeadingPointAlongPath( const Vector &vecStartPoint, CPathTrack *pFirstTrack, float flDistance, Vector *pTarget );

	// Finds the closest point on the path, returns a signed perpendicular distance
	CPathTrack *FindClosestPointOnPath( CPathTrack *pPath, const Vector &targetPos, Vector *pVecClosestPoint, Vector *pVecPathDir, float *pDistanceFromPath );

	// Methods to find a signed perp distance from the track
	// and to compute a point off the path based on the signed perp distance
	float ComputePerpDistanceFromPath( const Vector &vecPointOnPath, const Vector &vecPathDir, const Vector &vecPointOffPath );
	void ComputePointFromPerpDistance( const Vector &vecPointOnPath, const Vector &vecPathDir, float flPerpDist, Vector *pResult );

	// Returns the direction of the path at the closest point to the target
	const Vector &TargetPathDirection() const;
	const Vector &TargetPathAcrossDirection() const;

	// Returns distance along path to target, returns -1 if there's no path
	float ComputePathDistance( CPathTrack *pStart, CPathTrack *pDest, bool bForward ) const;

	// Compute the distance to a particular point on the path
	float ComputeDistanceAlongPathToPoint( CPathTrack *pStartTrack, CPathTrack *pDestTrack, const Vector &vecDestPosition, bool bMovingForward );

private:
	//---------------------------------
	Vector			m_vecDesiredPosition;
	Vector			m_vecGoalOrientation; // orientation of the goal entity.

	// NOTE: CurrentPathTarget changes meaning based on movement direction
	// For this *after* means the "next" (m_pnext) side of the line segment
	// and "before" means the "prev" (m_pprevious) side of the line segment
	// CurrentPathTarget is *after* the desired point when moving forward, 
	// and *before* the desired point when moving backward.
	// DestPathTarget + TargetNearestPath always represent points
	// *after* the desired point.
	CHandle<CPathTrack> m_pCurrentPathTarget;
	CHandle<CPathTrack> m_pDestPathTarget;
	CHandle<CPathTrack> m_pLastPathTarget;
	CHandle<CPathTrack> m_pTargetNearestPath;	// Used only by leading, it specifies the path point *after* where the target is

	string_t		m_strCurrentPathName;
	string_t		m_strDestPathName;
	string_t		m_strLastPathName;
	string_t		m_strTargetNearestPathName;

	Vector			m_vecLastGoalCheckPosition;	// Last position checked for moving towards
	float			m_flEnemyPathUpdateTime;	// Next time to update our enemies position
	bool			m_bForcedMove;				// Means the destination point must be reached regardless of enemy position
	bool			m_bPatrolling;				// If set, move back and forth along the current track until we see an enemy
	bool			m_bPatrolBreakable;			// If set, I'll stop patrolling if I see an enemy
	bool			m_bLeading;					// If set, we can lead our enemies

	// Derived class pathing data
	float			m_flTargetDistanceThreshold;// Distance threshold used to determine when a target has moved enough to update our navigation to it
	float			m_flAvoidDistance;			//
	
	float			m_flTargetTolerance;		// How far from a path track do we need to be before we 'reached' it?
	Vector			m_vecSegmentStartPoint;		// Starting point for the current segment
	Vector			m_vecSegmentStartSplinePoint;	// Used to define a spline which is used to compute path velocity
	bool			m_bMovingForward;
	bool			m_bChooseFarthestPoint;
	float			m_flFarthestPathDist;		// How far from a path track do we need to be before we 'reached' it?

	float			m_flPathMaxSpeed;
	float			m_flTargetDistFromPath;		// How far is the target from the closest point on the path?
	float			m_flLeadDistance;
	Vector			m_vecTargetPathDir;
	Vector			m_vecTargetPathPoint;		// What point on the path is closest to the target?

	PauseState_t	m_nPauseState;
};

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

#endif // AI_TRACKPATHER_H