aboutsummaryrefslogtreecommitdiff
path: root/mp/src/game/server/ai_utils.h
blob: 8cdde7bae1eb2a55d25fa39d9c11ebf8b1bb00d8 (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
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Simple, small, free-standing tools for building AIs
//
//=============================================================================//

#ifndef AI_UTILS_H
#define AI_UTILS_H

#include "simtimer.h"
#include "ai_component.h"

#if defined( _WIN32 )
#pragma once
#endif

//-----------------------------------------------------------------------------
//
// Function to get the local player. AI does not want asserts or warnings,
// just NULL result
//
//-----------------------------------------------------------------------------

inline CBasePlayer *AI_GetSinglePlayer()
{
	if ( gpGlobals->maxClients > 1 )
	{
		return NULL;
	}
	
	return UTIL_GetLocalPlayer();
}

inline bool AI_IsSinglePlayer()
{
	return ( gpGlobals->maxClients == 1 );
}


//-----------------------------------------------------------------------------
//
// CAI_MoveMonitor
//
// Purpose: Watch an entity, trigger if moved more than a tolerance
//
//-----------------------------------------------------------------------------

class CAI_MoveMonitor
{
public:
	CAI_MoveMonitor()
	 : m_vMark( 0, 0, 0 ),
	   m_flMarkTolerance( NO_MARK )
	{
	}
	
	void SetMark( CBaseEntity *pEntity, float tolerance )
	{
		if ( pEntity )
		{
			m_vMark = pEntity->GetAbsOrigin();
			m_flMarkTolerance = tolerance;
		}
	}
	
	void ClearMark()
	{
	   m_flMarkTolerance = NO_MARK;
	}

	bool IsMarkSet()
	{
		return ( m_flMarkTolerance != NO_MARK );
	}

	bool TargetMoved( CBaseEntity *pEntity )
	{
		if ( IsMarkSet() && pEntity != NULL )
		{
			float distance = ( m_vMark - pEntity->GetAbsOrigin() ).Length();
			if ( distance > m_flMarkTolerance )
				return true;
		}
		return false;
	}

	bool TargetMoved2D( CBaseEntity *pEntity )
	{
		if ( IsMarkSet() && pEntity != NULL )
		{
			float distance = ( m_vMark.AsVector2D() - pEntity->GetAbsOrigin().AsVector2D() ).Length();
			if ( distance > m_flMarkTolerance )
				return true;
		}
		return false;
	}

	Vector GetMarkPos() { return m_vMark; }
	
private:
	enum
	{
		NO_MARK = -1
	};
	
	Vector			   m_vMark;
	float			   m_flMarkTolerance;

	DECLARE_SIMPLE_DATADESC();
};


//-----------------------------------------------------------------------------
//
// CAI_ShotRegulator
//
// Purpose: Assists in creating non-constant bursty shooting style
//
//-----------------------------------------------------------------------------
class CAI_ShotRegulator
{
public:
	CAI_ShotRegulator();

	// Sets the various parameters for burst (this one's for backwards compatibility)
	// NOTE: This will modify the next shot time
	void SetParameters( int minShotsPerBurst, int maxShotsPerBurst, float minRestTime, float maxRestTime = 0.0 );

	// NOTE: The next 3 methods will *not* modify the next shot time
	// Sets the number of shots to shoot in a single burst
	void SetBurstShotCountRange( int minShotsPerBurst, int maxShotsPerBurst );

	// How much time should I rest between bursts?
	void SetRestInterval( float flMinRestInterval, float flMaxRestInterval );

	// How much time should I wait in between shots in a single burst?
	void SetBurstInterval( float flMinBurstInterval, float flMaxBurstInterval );
	
	// Poll the current parameters
	void GetBurstShotCountRange( int *pMinShotsPerBurst, int *pMaxShotsPerBurst ) const;
	void GetRestInterval( float *pMinRestInterval, float *pMaxRestInterval ) const;
	void GetBurstInterval( float *pMinBurstInterval, float *pMaxBurstInterval ) const;

	// Reset the state. If true, the next burst time is set to now,
	// otherwise it'll wait one rest interval before shooting 
	void Reset( bool bStartShooting = true );

	// Should we shoot?
	bool ShouldShoot() const;

	// When will I shoot next?
	float NextShotTime() const;

	// Am I in the middle of a rest period?
	bool IsInRestInterval() const;

	// NOTE: These will not modify the next shot time
	int GetBurstShotsRemaining() const;
	void SetBurstShotsRemaining( int shots );

	// Call this when the NPC fired the weapon;
	void OnFiredWeapon();

	// Causes us to potentially delay our shooting time
	void FireNoEarlierThan( float flTime );

	// Prevent/Allow shooting
	void EnableShooting( void );
	void DisableShooting( void );
	
private:
	float	m_flNextShotTime;
	bool	m_bInRestInterval;
	unsigned short	m_nBurstShotsRemaining;
	unsigned short	m_nMinBurstShots, m_nMaxBurstShots;
	float	m_flMinRestInterval, m_flMaxRestInterval;
	float	m_flMinBurstInterval, m_flMaxBurstInterval;
	bool	m_bDisabled;

	DECLARE_SIMPLE_DATADESC();
};


//-----------------------------------------------------------------------------
//
// CAI_AccelDecay
//
// Purpose: Maintain a smooth acceleration, deceleration curve
//
//-----------------------------------------------------------------------------

class CAI_AccelDecay
{
public:
	CAI_AccelDecay();

	void	SetParameters( float minVelocity, float maxVelocity, float accelPercent, float decelPercent );
	float	Update( float flCurrent, float flTarget, float flInterval );
	void	ResetVelocity( float flVelocity = 0.0f );
	void	SetMaxVelocity( float maxVelocity );

private:
	float	m_velocity;

	float	m_maxVelocity; // = 300;
	float	m_minVelocity; // = 10;

	float	m_invDecay; //	0.8	// maintain X percent of velocity when slowing down
	float	m_decayTime;//	0.4161	// Sum( 1..cycle, HEIGHTINVDECAY^cycle ) 
	float	m_accel;	//	0.5		// accel toward maxVelocity by X percent each cycle

	DECLARE_SIMPLE_DATADESC();
};



//-----------------------------------------------------------------------------
//
// Purpose: Utility to allow place grace in cover
//
//-----------------------------------------------------------------------------

struct AI_FreePassParams_t
{
	float timeToTrigger;		// How long after not detected to issue pass
	float duration;				// How long in the open pass before revoked
	float moveTolerance;		// How far in open needed to move to revoke pass
	float refillRate;			// After hiding again during pass, how quickly to reinstitute pass(seconds per second)
	float coverDist;			// When hiding, how far from an obstructing object needed to be considered in cover
	
	float peekTime;				// How long allowed to peek
	float peekTimeAfterDamage;	// How long allowed to peek after damaged by
	float peekEyeDist;			// how far spaced out the eyes are
	float peekEyeDistZ;			// how far below eye position to test eyes (handles peek up)

	DECLARE_SIMPLE_DATADESC();
};

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

class CAI_FreePass : public CAI_Component
{
public:
	CAI_FreePass()
	 : m_FreePassTimeRemaining(0)
	{
	}

	void			Reset( float passTime = -1, float moveTolerance = -1 );

	void			SetPassTarget( CBaseEntity *pTarget )		{ m_hTarget = pTarget; m_FreePassTimeRemaining = 0; }
	CBaseEntity *	GetPassTarget()								{ return m_hTarget; }
	
	void			SetParams( const AI_FreePassParams_t &params )	{ m_Params = params; }
	const AI_FreePassParams_t &GetParams() const					{ return m_Params; }
	
	//---------------------------------
	//	Free pass
	//---------------------------------
	void			Update();
	
	bool			HasPass();
	void 			Revoke( bool bUpdateMemory = false );
	
	float			GetTimeRemaining()					{ return m_FreePassTimeRemaining; }
	void			SetTimeRemaining( float passTime )	{ m_FreePassTimeRemaining = passTime; }

	bool			ShouldAllowFVisible( bool bBaseResult );

private:
	EHANDLE			m_hTarget;

	float			m_FreePassTimeRemaining;
	CAI_MoveMonitor m_FreePassMoveMonitor;
	
	AI_FreePassParams_t m_Params;

	DECLARE_SIMPLE_DATADESC();
};

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

class CTraceFilterNav : public CTraceFilterSimple
{
public:
	CTraceFilterNav( CAI_BaseNPC *pProber, bool bIgnoreTransientEntities, const IServerEntity *passedict, int collisionGroup, bool m_bAllowPlayerAvoid = true );
	bool ShouldHitEntity( IHandleEntity *pServerEntity, int contentsMask );

private:
	CAI_BaseNPC *m_pProber;
	bool m_bIgnoreTransientEntities;
	bool m_bCheckCollisionTable;
	bool m_bAllowPlayerAvoid;
};

extern string_t g_iszFuncBrushClassname;

#endif // AI_UTILS_H