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
|