aboutsummaryrefslogtreecommitdiff
path: root/sp/src/game/server/ai_scriptconditions.h
blob: 8162c1001c4888e38d38eee3ee70c9aad90117f2 (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
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//

#ifndef AI_SCRIPTCONDITIONS_H
#define AI_SCRIPTCONDITIONS_H

#include "baseentity.h"
#include "entityoutput.h"
#include "simtimer.h"
#include "ai_npcstate.h"

#if defined( _WIN32 )
#pragma once
#endif

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

class CAI_ProxTester
{
public:
	CAI_ProxTester()
		: m_distSq( 0 ),
		m_fInside( false )
	{
	}

	void Init( float dist )
	{
		m_fInside = ( dist > 0 );
		m_distSq = dist * dist;
	}

	bool Check( CBaseEntity *pEntity1, CBaseEntity *pEntity2 )
	{
		if ( m_distSq != 0 )
		{
			float distSq = ( pEntity1->GetAbsOrigin() - pEntity2->GetAbsOrigin() ).LengthSqr();
			bool fInside = ( distSq < m_distSq );

			return ( m_fInside == fInside );
		}
		return true;
	}

	DECLARE_SIMPLE_DATADESC();

private:

	float m_distSq;
	bool  m_fInside;
};

//-----------------------------------------------------------------------------
class CAI_ScriptConditionsElement
{
public:

	DECLARE_SIMPLE_DATADESC();

	void			SetActor( CBaseEntity *pEntity ) { m_hActor = pEntity; }
	CBaseEntity		*GetActor( void ){ return m_hActor.Get(); }

	void			SetTimer( CSimTimer timer ) { m_Timer = timer;	}
	CSimTimer		*GetTimer( void ) { return &m_Timer;	}
	
	void			SetTimeOut( CSimTimer timeout) { m_Timeout = timeout;	}
	CSimTimer		*GetTimeOut( void ) { return &m_Timeout;	}

private:
	EHANDLE			m_hActor;
	CSimTimer		m_Timer;
	CSimTimer		m_Timeout;
};

//-----------------------------------------------------------------------------
// class CAI_ScriptConditions
//
// Purpose: Watches a set of conditions relative to a given NPC, and when they
//			are all satisfied, fires the relevant output
//-----------------------------------------------------------------------------

class CAI_ScriptConditions : public CBaseEntity, public IEntityListener
{
	DECLARE_CLASS( CAI_ScriptConditions, CBaseEntity );

public:
	CAI_ScriptConditions()
		:	m_fDisabled( true ),
		m_flRequiredTime( 0 ),
		m_fMinState( NPC_STATE_IDLE ),
		m_fMaxState( NPC_STATE_IDLE ),
		m_fScriptStatus( TRS_NONE ),
		m_fActorSeePlayer( TRS_NONE ),
		m_flPlayerActorProximity( 0 ),
		m_flPlayerActorFOV( -1 ),
		m_fPlayerActorLOS( TRS_NONE ),
		m_fActorSeeTarget( TRS_NONE ),
		m_flActorTargetProximity( 0 ),
		m_flPlayerTargetProximity( 0 ),
		m_flPlayerTargetFOV( 0 ),
		m_fPlayerTargetLOS( TRS_NONE ),
		m_fPlayerBlockingActor( TRS_NONE ),
		m_flMinTimeout( 0 ),
		m_flMaxTimeout( 0 ),
		m_fActorInPVS( TRS_NONE ),
		m_fActorInVehicle( TRS_NONE ),
		m_fPlayerInVehicle( TRS_NONE )
	{
#ifndef HL2_EPISODIC
		m_hActor = NULL;
#endif
	}

private:
	void Spawn();
	void Activate();

	void EvaluationThink();

	void Enable();
	void Disable();

	void SetThinkTime()			{ SetNextThink( gpGlobals->curtime + 0.250 ); }

	// Evaluators
	struct EvalArgs_t
	{
		CBaseEntity *pActor; 
		CBasePlayer *pPlayer; 
		CBaseEntity *pTarget;
	};

	bool EvalState( const EvalArgs_t &args );
	bool EvalActorSeePlayer( const EvalArgs_t &args );
	bool EvalPlayerActorLook( const EvalArgs_t &args );
	bool EvalPlayerTargetLook( const EvalArgs_t &args );
	bool EvalPlayerActorProximity( const EvalArgs_t &args );
	bool EvalPlayerTargetProximity( const EvalArgs_t &args );
	bool EvalActorTargetProximity( const EvalArgs_t &args );
	bool EvalActorSeeTarget( const EvalArgs_t &args );
	bool EvalPlayerActorLOS( const EvalArgs_t &args );
	bool EvalPlayerTargetLOS( const EvalArgs_t &args );
	bool EvalPlayerBlockingActor( const EvalArgs_t &args );
	bool EvalActorInPVS( const EvalArgs_t &args );
	bool EvalPlayerInVehicle( const EvalArgs_t &args );
	bool EvalActorInVehicle( const EvalArgs_t &args );

	void OnEntitySpawned( CBaseEntity *pEntity );

	int AddNewElement( CBaseEntity *pActor );

	bool ActorInList( CBaseEntity *pActor );
	void UpdateOnRemove( void );

	// Input handlers
	void InputEnable( inputdata_t &inputdata );
	void InputDisable( inputdata_t &inputdata );

	// Output handlers
	COutputEvent	m_OnConditionsSatisfied;
	COutputEvent	m_OnConditionsTimeout;
	COutputEvent	m_NoValidActors;

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

#ifndef HL2_EPISODIC
	CBaseEntity *GetActor()		{ return m_hActor.Get();			}
#endif
	CBasePlayer *GetPlayer()	{ return UTIL_GetLocalPlayer();	}

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

	// @Note (toml 07-17-02): At some point, it may be desireable to switch to using function objects instead of functions. Probably
	// if support for NPCs addiing custom conditions becomes necessary
	typedef bool (CAI_ScriptConditions::*EvaluationFunc_t)( const EvalArgs_t &args );

	struct EvaluatorInfo_t
	{
		EvaluationFunc_t	pfnEvaluator;
		const char			*pszName;
	};

	static EvaluatorInfo_t gm_Evaluators[];

	//---------------------------------
	// Evaluation helpers

	static bool IsInFOV( CBaseEntity *pViewer, CBaseEntity *pViewed, float fov, bool bTrueCone );
	static bool PlayerHasLineOfSight( CBaseEntity *pViewer, CBaseEntity *pViewed, bool fNot );
	static bool ActorInPlayersPVS( CBaseEntity *pActor, bool bNot );

	virtual void OnRestore( void );

	//---------------------------------
	// General conditions info

	bool			m_fDisabled;
	bool			m_bLeaveAsleep;
	EHANDLE			m_hTarget;

	float			m_flRequiredTime;	// How long should the conditions me true

#ifndef HL2_EPISODIC
	EHANDLE 		m_hActor;
	CSimTimer		m_Timer; 			// @TODO (toml 07-16-02): save/load of timer once Jay has save/load of contained objects
	CSimTimer		m_Timeout;
#endif

	//---------------------------------
	// Specific conditions data
	NPC_STATE		m_fMinState;
	NPC_STATE		m_fMaxState;
	ThreeState_t 	m_fScriptStatus;
	ThreeState_t 	m_fActorSeePlayer;
	string_t		m_Actor;

	float 			m_flPlayerActorProximity;
	CAI_ProxTester	m_PlayerActorProxTester;

	float			m_flPlayerActorFOV;
	bool			m_bPlayerActorFOVTrueCone;
	ThreeState_t	m_fPlayerActorLOS;
	ThreeState_t 	m_fActorSeeTarget;

	float 			m_flActorTargetProximity;
	CAI_ProxTester	m_ActorTargetProxTester;

	float 			m_flPlayerTargetProximity;
	CAI_ProxTester	m_PlayerTargetProxTester;

	float 			m_flPlayerTargetFOV;
	bool			m_bPlayerTargetFOVTrueCone;
	ThreeState_t	m_fPlayerTargetLOS;
	ThreeState_t	m_fPlayerBlockingActor;
	ThreeState_t	m_fActorInPVS;

	float			m_flMinTimeout;
	float			m_flMaxTimeout;

	ThreeState_t	m_fActorInVehicle;
	ThreeState_t	m_fPlayerInVehicle;

	CUtlVector< CAI_ScriptConditionsElement > m_ElementList;

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

	DECLARE_DATADESC();
};

//=============================================================================

#endif // AI_SCRIPTCONDITIONS_H