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
|
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Hooks and classes for the support of humanoid NPCs with
// groovy facial animation capabilities, aka, "Actors"
//
//=============================================================================//
#ifndef AI_BASEACTOR_H
#define AI_BASEACTOR_H
#include "ai_basehumanoid.h"
#include "ai_speech.h"
#include "AI_Interest_Target.h"
#include <limits.h>
#if defined( _WIN32 )
#pragma once
#endif
//-----------------------------------------------------------------------------
// CAI_BaseActor
//
// Purpose: The base class for all head/body/eye expressive NPCS.
//
//-----------------------------------------------------------------------------
enum PoseParameter_t { POSE_END=INT_MAX };
enum FlexWeight_t { FLEX_END=INT_MAX };
struct AILookTargetArgs_t
{
EHANDLE hTarget;
Vector vTarget;
float flDuration;
float flInfluence;
float flRamp;
bool bExcludePlayers;
CAI_InterestTarget *pQueue;
};
class CAI_BaseActor : public CAI_ExpresserHost<CAI_BaseHumanoid>
{
DECLARE_CLASS( CAI_BaseActor, CAI_ExpresserHost<CAI_BaseHumanoid> );
//friend CPoseParameter;
//friend CFlexWeight;
public:
// FIXME: this method is lame, isn't there some sort of template thing that would get rid of the Outer pointer?
void Init( PoseParameter_t &index, const char *szName ) { index = (PoseParameter_t)LookupPoseParameter( szName ); };
void Set( PoseParameter_t index, float flValue ) { SetPoseParameter( (int)index, flValue ); }
float Get( PoseParameter_t index ) { return GetPoseParameter( (int)index ); }
float ClampWithBias( PoseParameter_t index, float value, float base );
// Note, you must add all names to this static function in order for Init to work
static bool IsServerSideFlexController( char const *szName );
void Init( FlexWeight_t &index, const char *szName )
{
// Make this fatal!!!
if ( !IsServerSideFlexController( szName ) )
{
Error( "You forgot to add flex controller %s to list in CAI_BaseActor::IsServerSideFlexController().", szName );
}
index = (FlexWeight_t)FindFlexController( szName );
}
void Set( FlexWeight_t index, float flValue ) { SetFlexWeight( (LocalFlexController_t)index, flValue ); }
float Get( FlexWeight_t index ) { return GetFlexWeight( (LocalFlexController_t)index ); }
public:
CAI_BaseActor()
: m_fLatchedPositions( 0 ),
m_latchedEyeOrigin( vec3_origin ),
m_latchedEyeDirection( vec3_origin ),
m_latchedHeadDirection( vec3_origin ),
m_flBlinktime( 0 ),
m_hLookTarget( NULL ),
m_iszExpressionScene( NULL_STRING ),
m_iszIdleExpression( NULL_STRING ),
m_iszAlertExpression( NULL_STRING ),
m_iszCombatExpression( NULL_STRING ),
m_iszDeathExpression( NULL_STRING ),
m_iszExpressionOverride( NULL_STRING )
{
memset( m_flextarget, 0, 64 * sizeof( m_flextarget[0] ) );
}
~CAI_BaseActor()
{
delete m_pExpresser;
}
virtual void StudioFrameAdvance();
virtual void Precache();
virtual void SetModel( const char *szModelName );
virtual bool StartSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event, CChoreoActor *actor, CBaseEntity *pTarget );
virtual bool ProcessSceneEvent( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event );
virtual bool ClearSceneEvent( CSceneEventInfo *info, bool fastKill, bool canceled );
virtual bool CheckSceneEventCompletion( CSceneEventInfo *info, float currenttime, CChoreoScene *scene, CChoreoEvent *event );
Vector EyePosition( );
virtual Vector HeadDirection2D( void );
virtual Vector HeadDirection3D( void );
virtual Vector EyeDirection2D( void );
virtual Vector EyeDirection3D( void );
CBaseEntity *GetLooktarget() { return m_hLookTarget.Get(); }
virtual void OnNewLookTarget() {};
// CBaseFlex
virtual void SetViewtarget( const Vector &viewtarget );
// CAI_BaseNPC
virtual float PickLookTarget( bool bExcludePlayers = false, float minTime = 1.5, float maxTime = 2.5 );
virtual float PickLookTarget( CAI_InterestTarget &queue, bool bExcludePlayers = false, float minTime = 1.5, float maxTime = 2.5 );
virtual bool PickTacticalLookTarget( AILookTargetArgs_t *pArgs );
virtual bool PickRandomLookTarget( AILookTargetArgs_t *pArgs );
virtual void MakeRandomLookTarget( AILookTargetArgs_t *pArgs, float minTime, float maxTime );
virtual bool HasActiveLookTargets( void );
virtual void OnSelectedLookTarget( AILookTargetArgs_t *pArgs ) { return; }
virtual void ClearLookTarget( CBaseEntity *pTarget );
virtual void ExpireCurrentRandomLookTarget() { m_flNextRandomLookTime = gpGlobals->curtime - 0.1f; }
virtual void StartTaskRangeAttack1( const Task_t *pTask );
virtual void AddLookTarget( CBaseEntity *pTarget, float flImportance, float flDuration, float flRamp = 0.0 );
virtual void AddLookTarget( const Vector &vecPosition, float flImportance, float flDuration, float flRamp = 0.0 );
virtual void SetHeadDirection( const Vector &vTargetPos, float flInterval );
void UpdateBodyControl( void );
void UpdateHeadControl( const Vector &vHeadTarget, float flHeadInfluence );
virtual float GetHeadDebounce( void ) { return 0.3; } // how much of previous head turn to use
virtual void MaintainLookTargets( float flInterval );
virtual bool ValidEyeTarget(const Vector &lookTargetPos);
virtual bool ValidHeadTarget(const Vector &lookTargetPos);
virtual float HeadTargetValidity(const Vector &lookTargetPos);
virtual bool ShouldBruteForceFailedNav() { return true; }
void AccumulateIdealYaw( float flYaw, float flIntensity );
bool SetAccumulatedYawAndUpdate( void );
float m_flAccumYawDelta;
float m_flAccumYawScale;
//---------------------------------
virtual void OnStateChange( NPC_STATE OldState, NPC_STATE NewState );
//---------------------------------
virtual void PlayExpressionForState( NPC_STATE state );
virtual const char *SelectRandomExpressionForState( NPC_STATE state );
float SetExpression( const char * );
void ClearExpression();
const char * GetExpression();
enum
{
SCENE_AI_BLINK = 1,
SCENE_AI_HOLSTER,
SCENE_AI_UNHOLSTER,
SCENE_AI_AIM,
SCENE_AI_RANDOMLOOK,
SCENE_AI_RANDOMFACEFLEX,
SCENE_AI_RANDOMHEADFLEX,
SCENE_AI_IGNORECOLLISION,
SCENE_AI_DISABLEAI
};
DECLARE_DATADESC();
private:
enum
{
HUMANOID_LATCHED_EYE = 0x0001,
HUMANOID_LATCHED_HEAD = 0x0002,
HUMANOID_LATCHED_ALL = 0x0003,
};
//---------------------------------
void UpdateLatchedValues( void );
// Input handlers.
void InputSetExpressionOverride( inputdata_t &inputdata );
//---------------------------------
int m_fLatchedPositions;
Vector m_latchedEyeOrigin;
Vector m_latchedEyeDirection; // direction eyes are looking
Vector m_latchedHeadDirection; // direction head is aiming
void ClearHeadAdjustment( void );
Vector m_goalHeadDirection;
float m_goalHeadInfluence;
//---------------------------------
float m_goalSpineYaw;
float m_goalBodyYaw;
Vector m_goalHeadCorrection;
//---------------------------------
float m_flBlinktime;
EHANDLE m_hLookTarget;
CAI_InterestTarget m_lookQueue;
CAI_InterestTarget m_syntheticLookQueue;
CAI_InterestTarget m_randomLookQueue;
float m_flNextRandomLookTime; // FIXME: move to scene
//---------------------------------
string_t m_iszExpressionScene;
EHANDLE m_hExpressionSceneEnt;
float m_flNextRandomExpressionTime;
string_t m_iszExpressionOverride;
protected:
string_t m_iszIdleExpression;
string_t m_iszAlertExpression;
string_t m_iszCombatExpression;
string_t m_iszDeathExpression;
private:
//---------------------------------
//PoseParameter_t m_ParameterBodyTransY; // "body_trans_Y"
//PoseParameter_t m_ParameterBodyTransX; // "body_trans_X"
//PoseParameter_t m_ParameterBodyLift; // "body_lift"
PoseParameter_t m_ParameterBodyYaw; // "body_yaw"
//PoseParameter_t m_ParameterBodyPitch; // "body_pitch"
//PoseParameter_t m_ParameterBodyRoll; // "body_roll"
PoseParameter_t m_ParameterSpineYaw; // "spine_yaw"
//PoseParameter_t m_ParameterSpinePitch; // "spine_pitch"
//PoseParameter_t m_ParameterSpineRoll; // "spine_roll"
PoseParameter_t m_ParameterNeckTrans; // "neck_trans"
PoseParameter_t m_ParameterHeadYaw; // "head_yaw"
PoseParameter_t m_ParameterHeadPitch; // "head_pitch"
PoseParameter_t m_ParameterHeadRoll; // "head_roll"
//FlexWeight_t m_FlexweightMoveRightLeft; // "move_rightleft"
//FlexWeight_t m_FlexweightMoveForwardBack;// "move_forwardback"
//FlexWeight_t m_FlexweightMoveUpDown; // "move_updown"
FlexWeight_t m_FlexweightBodyRightLeft; // "body_rightleft"
//FlexWeight_t m_FlexweightBodyUpDown; // "body_updown"
//FlexWeight_t m_FlexweightBodyTilt; // "body_tilt"
FlexWeight_t m_FlexweightChestRightLeft; // "chest_rightleft"
//FlexWeight_t m_FlexweightChestUpDown; // "chest_updown"
//FlexWeight_t m_FlexweightChestTilt; // "chest_tilt"
FlexWeight_t m_FlexweightHeadForwardBack;// "head_forwardback"
FlexWeight_t m_FlexweightHeadRightLeft; // "head_rightleft"
FlexWeight_t m_FlexweightHeadUpDown; // "head_updown"
FlexWeight_t m_FlexweightHeadTilt; // "head_tilt"
PoseParameter_t m_ParameterGestureHeight; // "gesture_height"
PoseParameter_t m_ParameterGestureWidth; // "gesture_width"
FlexWeight_t m_FlexweightGestureUpDown; // "gesture_updown"
FlexWeight_t m_FlexweightGestureRightLeft; // "gesture_rightleft"
private:
//---------------------------------
bool RandomFaceFlex( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event );
bool RandomHeadFlex( CSceneEventInfo *info, CChoreoScene *scene, CChoreoEvent *event );
float m_flextarget[64];
public:
virtual bool UseSemaphore( void );
protected:
bool m_bDontUseSemaphore;
public:
//---------------------------------
//
// Speech support
//
virtual CAI_Expresser *GetExpresser();
protected:
bool CreateComponents();
virtual CAI_Expresser *CreateExpresser();
private:
//---------------------------------
CAI_Expresser *m_pExpresser;
};
//-----------------------------------------------------------------------------
#endif // AI_BASEACTOR_H
|