aboutsummaryrefslogtreecommitdiff
path: root/sp/src/game/server/ai_hint.h
blob: 89daef3d58d510d0dec14be3c1082edb11aeea4d (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
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Hint node utilities and functions.
//
// $NoKeywords: $
//=============================================================================//

#ifndef	AI_HINT_H
#define	AI_HINT_H
#pragma once

#include "ai_initutils.h"
#include "tier1/utlmap.h"

//Flags for FindHintNode
#define bits_HINT_NODE_NONE						0x00000000
#define bits_HINT_NODE_VISIBLE					0x00000001
#define	bits_HINT_NODE_NEAREST					0x00000002		// Choose the node nearest me
#define bits_HINT_NODE_RANDOM					0x00000004		// Find a random hintnode meeting other criteria
#define bits_HINT_NODE_CLEAR					0x00000008		// Only choose nodes that have clear room for my bounding box (requires NPC)
#define bits_HINT_NODE_USE_GROUP				0x00000010		// Use the NPC's hintgroup when searching for a node (requires NPC)
#define	bits_HINT_NODE_VISIBLE_TO_PLAYER		0x00000020
#define	bits_HINT_NODE_NOT_VISIBLE_TO_PLAYER	0x00000040
#define bits_HINT_NODE_REPORT_FAILURES			0x00000080
#define bits_HINT_NODE_IN_VIEWCONE				0x00000100
#define bits_HINT_NODE_IN_AIMCONE				0x00000200
#define bits_HINT_NPC_IN_NODE_FOV				0x00000400		// Is the searcher inside the hint node's FOV?
#define bits_HINT_NOT_CLOSE_TO_ENEMY			0x00000800		// Hint must not be within 30 feet of my enemy
#define bits_HINT_HAS_LOS_TO_PLAYER				0x00001000		// Like VISIBLE_TO_PLAYER but doesn't care about player's facing
#define bits_HAS_EYEPOSITION_LOS_TO_PLAYER		0x00002000		// Like HAS LOS TO PLAYER, but checks NPC's eye position at the node, not node origin.

//-----------------------------------------------------------------------------
//
// hints - these MUST coincide with the HINTS listed under
// info_node in the FGD file!
//
// For debugging, they must also coincide with g_pszHintDescriptions.
//
//-----------------------------------------------------------------------------
enum Hint_e
{
	HINT_ANY = -1,
	HINT_NONE = 0,
	HINT_NOT_USED_WORLD_DOOR,
	HINT_WORLD_WINDOW,
	HINT_NOT_USED_WORLD_BUTTON,
	HINT_NOT_USED_WORLD_MACHINERY,
	HINT_NOT_USED_WORLD_LEDGE,
	HINT_NOT_USED_WORLD_LIGHT_SOURCE,
	HINT_NOT_USED_WORLD_HEAT_SOURCE,
	HINT_NOT_USED_WORLD_BLINKING_LIGHT,
	HINT_NOT_USED_WORLD_BRIGHT_COLORS,
	HINT_NOT_USED_WORLD_HUMAN_BLOOD,
	HINT_NOT_USED_WORLD_ALIEN_BLOOD,

	HINT_WORLD_WORK_POSITION,
	HINT_WORLD_VISUALLY_INTERESTING,
	HINT_WORLD_VISUALLY_INTERESTING_DONT_AIM,
	HINT_WORLD_INHIBIT_COMBINE_MINES,
	HINT_WORLD_VISUALLY_INTERESTING_STEALTH,

	HINT_TACTICAL_COVER_MED	= 100,
	HINT_TACTICAL_COVER_LOW,
	HINT_TACTICAL_SPAWN,
	HINT_TACTICAL_PINCH,				// Exit / entrance to an arena
	HINT_NOT_USED_TACTICAL_GUARD,
	HINT_TACTICAL_ENEMY_DISADVANTAGED,	//Disadvantageous position for the enemy
	HINT_NOT_USED_HEALTH_KIT,

	HINT_NOT_USED_URBAN_STREETCORNER = 200,
	HINT_NOT_USED_URBAN_STREETLAMP,
	HINT_NOT_USED_URBAN_DARK_SPOT,
	HINT_NOT_USED_URBAN_POSTER,
	HINT_NOT_USED_URBAN_SHELTER,

	HINT_NOT_USED_ASSASSIN_SECLUDED = 300,
	HINT_NOT_USED_ASSASSIN_RAFTERS,
	HINT_NOT_USED_ASSASSIN_GROUND,
	HINT_NOT_USED_ASSASSIN_MONKEYBARS,

	HINT_ANTLION_BURROW_POINT = 400,
	HINT_ANTLION_THUMPER_FLEE_POINT,

	HINT_HEADCRAB_BURROW_POINT = 450,
	HINT_HEADCRAB_EXIT_POD_POINT,

	HINT_NOT_USED_ROLLER_PATROL_POINT = 500,
	HINT_NOT_USED_ROLLER_CLEANUP_POINT,

	HINT_NOT_USED_PSTORM_ROCK_SPAWN = 600,

	HINT_CROW_FLYTO_POINT = 700,

	 // TF2 Hints
	HINT_BUG_PATROL_POINT = 800,

	// HL2 Hints
	HINT_FOLLOW_WAIT_POINT	= 900,
	HINT_JUMP_OVERRIDE		= 901,
	HINT_PLAYER_SQUAD_TRANSITON_POINT = 902,
	HINT_NPC_EXIT_POINT = 903,
	HINT_STRIDER_NODE = 904,

	HINT_PLAYER_ALLY_MOVE_AWAY_DEST = 950,
	HINT_PLAYER_ALLY_FEAR_DEST,

	// HL1 port hints
	HINT_HL1_WORLD_MACHINERY = 1000,
	HINT_HL1_WORLD_BLINKING_LIGHT,
	HINT_HL1_WORLD_HUMAN_BLOOD,
	HINT_HL1_WORLD_ALIEN_BLOOD,

	// CS port hints
	HINT_CSTRIKE_HOSTAGE_ESCAPE = 1100,
};
const char *GetHintTypeDescription( Hint_e iHintType );
const char *GetHintTypeDescription( CAI_Hint *pHint );

//-----------------------------------------------------------------------------
// CHintCriteria
//-----------------------------------------------------------------------------

class CHintCriteria
{
public:

	CHintCriteria();
	~CHintCriteria();

	bool		HasFlag( int bitmask )	const	{ return ( m_iFlags & bitmask ) != 0;	}
	void		SetFlag( int bitmask );
	void		ClearFlag( int bitmask );

	void		SetGroup( string_t group );
	string_t	GetGroup( void )	const	{ return m_strGroup;	}

	int			GetFirstHintType( void ) const	{ return m_iFirstHintType; }
	int			GetLastHintType( void ) const	{ return m_iLastHintType; }
	bool		MatchesHintType( int hintType ) const;
	bool		MatchesSingleHintType() const;

	bool		HasIncludeZones( void )	const	{ return ( m_zoneInclude.Count() != 0 ); }
	bool		HasExcludeZones( void )	const	{ return ( m_zoneExclude.Count() != 0 ); }
	
	void		AddIncludePosition( const Vector &position, float radius );
	void		AddExcludePosition( const Vector &position, float radius );
	void		SetHintType( int hintType );
	void		SetHintTypeRange( int firstType, int lastType );
	void		AddHintType( int hintType );

	bool		InIncludedZone( const Vector &testPosition ) const;
	bool		InExcludedZone( const Vector &testPosition ) const;

	int			NumHintTypes() const;
	int			GetHintType( int idx ) const;

private:

	struct	hintZone_t
	{
		Vector		position;
		float		radiussqr;
	};

	typedef CUtlVector < hintZone_t >	zoneList_t;

	void		AddZone( zoneList_t &list, const Vector &position, float radius );
	bool		InZone( const zoneList_t &zone, const Vector &testPosition ) const;

	CUtlVector<int> m_HintTypes;

	int			m_iFlags;
	int			m_iFirstHintType;
	int			m_iLastHintType;
	string_t	m_strGroup;
	
	zoneList_t	m_zoneInclude;
	zoneList_t	m_zoneExclude;
};

class CAI_Node;

//-----------------------------------------------------------------------------
// CAI_HintManager
//-----------------------------------------------------------------------------

DECLARE_POINTER_HANDLE(AIHintIter_t);

class CAIHintVector : public CUtlVector< CAI_Hint * >
{
public:
	CAIHintVector() : CUtlVector< CAI_Hint * >( 1, 0 )
	{
	}

	CAIHintVector( const CAIHintVector& src )
	{
		CopyArray( src.Base(), src.Count() );
	}

	CAIHintVector &operator=( const CAIHintVector &src )
	{
		CopyArray( src.Base(), src.Count() );
		return *this;
	}
};

class CAI_HintManager
{
	friend class CAI_Hint;
public:
	// Hint node creation
	static CAI_Hint		*CreateHint( HintNodeData *pNodeData, const char *pMapData = NULL );
	static void			DrawHintOverlays(float flDrawDuration);

	static void			AddHint( CAI_Hint *pTestHint );
	static void			RemoveHint( CAI_Hint *pTestHint );
	static void			AddHintByType( CAI_Hint *pHint );
	static void			RemoveHintByType( CAI_Hint *pHintToRemove );

	// Interface for searching the hint node list
	static CAI_Hint		*FindHint( CAI_BaseNPC *pNPC, const Vector &position, const CHintCriteria &hintCriteria );
	static CAI_Hint		*FindHint( CAI_BaseNPC *pNPC, const CHintCriteria &hintCriteria );
	static CAI_Hint		*FindHint( const Vector &position, const CHintCriteria &hintCriteria );
	static CAI_Hint		*FindHint( CAI_BaseNPC *pNPC, Hint_e nHintType, int nFlags, float flMaxDist, const Vector *pMaxDistFrom = NULL );

	// Purpose: Finds a random suitable hint within the requested radious of the npc
	static CAI_Hint		*FindHintRandom( CAI_BaseNPC *pNPC, const Vector &position, const CHintCriteria &hintCriteria );
	static int			FindAllHints( CAI_BaseNPC *pNPC, const Vector &position, const CHintCriteria &hintCriteria, CUtlVector<CAI_Hint *> *pResult );
	static int			FindAllHints( const Vector &position, const CHintCriteria &hintCriteria, CUtlVector<CAI_Hint *> *pResult )	{ return FindAllHints( NULL, position, hintCriteria, pResult ); }
	static int			FindAllHints( CAI_BaseNPC *pNPC, const CHintCriteria &hintCriteria, CUtlVector<CAI_Hint *> *pResult )		{ return FindAllHints( pNPC, pNPC->GetAbsOrigin(), hintCriteria, pResult ); }
	static int			GetFlags( const char *token );

	static CAI_Hint		*GetFirstHint( AIHintIter_t *pIter );					
	static CAI_Hint		*GetNextHint( AIHintIter_t *pIter );

	static void DumpHints();

	static void ValidateHints();

private:
	enum
	{
		// MUST BE POWER OF 2
		HINT_HISTORY = (1<<3),
		HINT_HISTORY_MASK = (HINT_HISTORY-1)
	};

	static CAI_Hint		*AddFoundHint( CAI_Hint *hint );
	static int			GetFoundHintCount();
	static CAI_Hint		*GetFoundHint( int index );
	static CAI_Hint		*GetLastFoundHint();
	static void			ResetFoundHints();
	static bool			IsInFoundHintList( CAI_Hint *hint );

	static int			gm_nFoundHintIndex;
	static CAI_Hint		*gm_pLastFoundHints[ HINT_HISTORY ];			// Last used hint 
	static CAIHintVector gm_AllHints;				// A linked list of all hints
	static CUtlMap< int,  CAIHintVector >	gm_TypedHints;
};

//-----------------------------------------------------------------------------
// CAI_Hint
//-----------------------------------------------------------------------------

class CAI_Hint : public CServerOnlyEntity
{
	DECLARE_CLASS( CAI_Hint, CServerOnlyEntity );
public:
	CAI_Hint( void );
	~CAI_Hint( void );

	// Interface for specific nodes
	bool				Lock( CBaseEntity *pNPC );			// Makes unavailable for hints
	void				Unlock( float delay = 0.0 );		// Makes available for hints after delay
	bool				IsLocked(void);						// Whether this node is available for use.
	bool				IsLockedBy( CBaseEntity *pNPC );	// Whether this node is available for use.
	void				GetPosition(CBaseCombatCharacter *pBCC, Vector *vPosition);
	void				GetPosition( Hull_t hull, Vector *vPosition );
	Vector				GetDirection( void );
	float				Yaw( void );
	CAI_Node			*GetNode( void );
	string_t			GetGroup( void ) const			{ return m_NodeData.strGroup;	}
	CBaseEntity			*User( void ) const				{ return m_hHintOwner; };
	Hint_e				HintType( void ) const			{ return (Hint_e)m_NodeData.nHintType;  };
	void				SetHintType( int hintType, bool force = false );
	string_t			HintActivityName( void ) const	{ return m_NodeData.iszActivityName; }
	int					GetTargetNode( void ) const		{ return m_nTargetNodeID; }
	bool				IsDisabled( void ) const		{ return (m_NodeData.iDisabled != 0); }
	void				SetDisabled( bool bDisabled	)	{ m_NodeData.iDisabled = bDisabled; }
	void				DisableForSeconds( float flSeconds );
	void				EnableThink();
	void				FixupTargetNode();
	void				NPCStartedUsing( CAI_BaseNPC *pNPC );
	void				NPCStoppedUsing( CAI_BaseNPC *pNPC );

	HintIgnoreFacing_t	GetIgnoreFacing() const			{ return m_NodeData.fIgnoreFacing; }

	NPC_STATE			GetMinState() const				{ return m_NodeData.minState; }
	NPC_STATE			GetMaxState() const				{ return m_NodeData.maxState; }

	int					GetNodeId()	{ return m_NodeData.nNodeID; }
	int					GetWCId()	{ return m_NodeData.nWCNodeID; }

	bool				HintMatchesCriteria( CAI_BaseNPC *pNPC, const CHintCriteria &hintCriteria, const Vector &position, float *flNearestDistance, bool bIgnoreLock = false, bool bIgnoreHintType = false );
	bool				IsInNodeFOV( CBaseEntity *pOther );

private:
	void				Spawn( void );
	virtual void		Activate();
	virtual void		UpdateOnRemove( void );
	int					DrawDebugTextOverlays(void);
	virtual int			ObjectCaps( void ) { return (BaseClass::ObjectCaps() & ~FCAP_ACROSS_TRANSITION); }
	virtual void		OnRestore();
	bool				IsViewable( void );

	// Input handlers
	void				InputEnableHint( inputdata_t &inputdata );
	void				InputDisableHint( inputdata_t &inputdata );

private:

	HintNodeData		m_NodeData;
	int					m_nTargetNodeID;
	EHANDLE				m_hHintOwner;			// Is hint locked (being used by NPC / NPC en-route to use it)
	float				m_flNextUseTime;		// When can I be used again?
	COutputEHANDLE		m_OnNPCStartedUsing;	// Triggered when an NPC has actively begun to use the node.
	COutputEHANDLE		m_OnNPCStoppedUsing;	// Triggered when an NPC has finished using this node.
	float				m_nodeFOV;
	Vector				m_vecForward;

	// The next hint in list of all hints
	friend class CAI_HintManager;

	DECLARE_DATADESC();
};

#define SF_ALLOW_JUMP_UP 65536


#endif	//AI_HINT_H