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
|