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
342
343
344
|
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: This is the base version of the vortigaunt
//
//=============================================================================//
#ifndef NPC_VORTIGAUNT_H
#define NPC_VORTIGAUNT_H
#ifdef _WIN32
#pragma once
#endif
#include "ai_basenpc.h"
#include "ai_behavior.h"
#include "ai_behavior_lead.h"
#include "ai_behavior_standoff.h"
#include "ai_behavior_assault.h"
#include "npc_playercompanion.h"
#define VORTIGAUNT_MAX_BEAMS 8
#define VORTIGAUNT_BEAM_ALL -1
#define VORTIGAUNT_BEAM_ZAP 0
#define VORTIGAUNT_BEAM_HEAL 1
#define VORTIGAUNT_BEAM_DISPEL 2
class CBeam;
class CSprite;
class CVortigauntChargeToken;
class CVortigauntEffectDispel;
extern ConVar sk_vortigaunt_zap_range;
enum VortigauntHealState_t
{
HEAL_STATE_NONE, // Not trying to heal
HEAL_STATE_WARMUP, // In the "warm-up" phase of healing
HEAL_STATE_HEALING, // In the process of healing
HEAL_STATE_COOLDOWN, // in the "cooldown" phase of healing
};
//=========================================================
// >> CNPC_Vortigaunt
//=========================================================
class CNPC_Vortigaunt : public CNPC_PlayerCompanion
{
DECLARE_CLASS( CNPC_Vortigaunt, CNPC_PlayerCompanion );
public:
CNPC_Vortigaunt( void );
virtual void Spawn( void );
virtual void Precache( void );
virtual float MaxYawSpeed( void );
virtual Vector FacingPosition( void );
virtual Vector BodyTarget( const Vector &posSrc, bool bNoisy = true );
virtual void PrescheduleThink( void );
virtual void BuildScheduleTestBits( void );
virtual void OnScheduleChange( void );
virtual int RangeAttack1Conditions( float flDot, float flDist ); // Primary zap
virtual int RangeAttack2Conditions( float flDot, float flDist ); // Concussive zap (larger)
virtual bool InnateWeaponLOSCondition( const Vector &ownerPos, const Vector &targetPos, bool bSetConditions );
virtual int MeleeAttack1Conditions( float flDot, float flDist ); // Dispel
virtual float InnateRange1MinRange( void ) { return 0.0f; }
virtual float InnateRange1MaxRange( void ) { return sk_vortigaunt_zap_range.GetFloat()*12; }
virtual int OnTakeDamage_Alive( const CTakeDamageInfo &info );
virtual bool FInViewCone( CBaseEntity *pEntity );
virtual bool ShouldMoveAndShoot( void );
// vorts have a very long head/neck swing, so debounce heavily
virtual float GetHeadDebounce( void ) { return 0.7; } // how much of previous head turn to use
virtual void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
virtual void AlertSound( void );
virtual Class_T Classify ( void ) { return IsGameEndAlly() ? CLASS_PLAYER_ALLY_VITAL : CLASS_VORTIGAUNT; }
virtual void HandleAnimEvent( animevent_t *pEvent );
virtual Activity NPC_TranslateActivity( Activity eNewActivity );
virtual void UpdateOnRemove( void );
virtual void Event_Killed( const CTakeDamageInfo &info );
virtual void GatherConditions( void );
virtual void RunTask( const Task_t *pTask );
virtual void StartTask( const Task_t *pTask );
virtual void ClearSchedule( const char *szReason );
virtual void DeclineFollowing( void );
virtual bool CanBeUsedAsAFriend( void );
virtual bool IsPlayerAlly( void ) { return true; }
// Override these to set behavior
virtual int TranslateSchedule( int scheduleType );
virtual int SelectSchedule( void );
virtual int SelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode );
virtual bool IsValidEnemy( CBaseEntity *pEnemy );
bool IsLeading( void ) { return ( GetRunningBehavior() == &m_LeadBehavior && m_LeadBehavior.HasGoal() ); }
void DeathSound( const CTakeDamageInfo &info );
void PainSound( const CTakeDamageInfo &info );
virtual void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr, CDmgAccumulator *pAccumulator );
virtual void SpeakSentence( int sentType );
virtual int IRelationPriority( CBaseEntity *pTarget );
virtual Disposition_t IRelationType( CBaseEntity *pTarget );
virtual bool IsReadinessCapable( void ) { return true; }
virtual float GetReadinessDecay() { return 30.0f; }
virtual bool ShouldRegenerateHealth( void ) { return m_bRegenerateHealth; }
virtual bool CanRunAScriptedNPCInteraction( bool bForced = false );
virtual void AimGun( void );
virtual void OnUpdateShotRegulator( void );
void InputEnableArmorRecharge( inputdata_t &data );
void InputDisableArmorRecharge( inputdata_t &data );
void InputExtractBugbait( inputdata_t &data );
void InputChargeTarget( inputdata_t &data );
void InputDispel( inputdata_t &data );
void InputBeginCarryNPC( inputdata_t &indputdata );
void InputEndCarryNPC( inputdata_t &indputdata );
// Health regeneration
void InputEnableHealthRegeneration( inputdata_t &data );
void InputDisableHealthRegeneration( inputdata_t &data );
// color
void InputTurnBlue( inputdata_t &data );
void InputTurnBlack( inputdata_t &data );
virtual void SetScriptedScheduleIgnoreConditions( Interruptability_t interrupt );
virtual void OnRestore( void );
virtual bool OverrideMoveFacing( const AILocalMoveGoal_t &move, float flInterval );
virtual void OnStartScene( void );
virtual bool IsInterruptable( void );
virtual bool CanFlinch( void );
// used so a grub can notify me that I stepped on it. Says a line.
void OnSquishedGrub( const CBaseEntity *pGrub );
private:
int NumAntlionsInRadius( float flRadius );
void DispelAntlions( const Vector &vecOrigin, float flRadius, bool bDispel = true );
bool HealGestureHasLOS( void );
bool PlayerBelowHealthPercentage( CBasePlayer *pPlayer, float flPerc );
void StartHealing( void );
void StopHealing( bool bInterrupt = false );
void MaintainHealSchedule( void );
bool ShouldHealTarget( CBaseEntity *pTarget );
int SelectHealSchedule( void );
void CreateBeamBlast( const Vector &vecOrigin );
private:
//=========================================================
// Vortigaunt schedules
//=========================================================
enum
{
SCHED_VORTIGAUNT_STAND = BaseClass::NEXT_SCHEDULE,
SCHED_VORTIGAUNT_RANGE_ATTACK,
SCHED_VORTIGAUNT_HEAL,
SCHED_VORTIGAUNT_EXTRACT_BUGBAIT,
SCHED_VORTIGAUNT_FACE_PLAYER,
SCHED_VORTIGAUNT_RUN_TO_PLAYER,
SCHED_VORTIGAUNT_DISPEL_ANTLIONS,
SCHED_VORT_FLEE_FROM_BEST_SOUND,
SCHED_VORT_ALERT_FACE_BESTSOUND,
};
//=========================================================
// Vortigaunt Tasks
//=========================================================
enum
{
TASK_VORTIGAUNT_HEAL_WARMUP = BaseClass::NEXT_TASK,
TASK_VORTIGAUNT_HEAL,
TASK_VORTIGAUNT_EXTRACT_WARMUP,
TASK_VORTIGAUNT_EXTRACT,
TASK_VORTIGAUNT_EXTRACT_COOLDOWN,
TASK_VORTIGAUNT_FIRE_EXTRACT_OUTPUT,
TASK_VORTIGAUNT_WAIT_FOR_PLAYER,
TASK_VORTIGAUNT_GET_HEAL_TARGET,
TASK_VORTIGAUNT_DISPEL_ANTLIONS
};
//=========================================================
// Vortigaunt Conditions
//=========================================================
enum
{
COND_VORTIGAUNT_CAN_HEAL = BaseClass::NEXT_CONDITION,
COND_VORTIGAUNT_HEAL_TARGET_TOO_FAR, // Outside or heal range
COND_VORTIGAUNT_HEAL_TARGET_BLOCKED, // Blocked by an obstruction
COND_VORTIGAUNT_HEAL_TARGET_BEHIND_US, // Not within our "forward" range
COND_VORTIGAUNT_HEAL_VALID, // All conditions satisfied
COND_VORTIGAUNT_DISPEL_ANTLIONS, // Repulse all antlions around us
};
// ------------
// Beams
// ------------
inline bool InAttackSequence( void );
void ClearBeams( void );
void ArmBeam( int beamType, int nHand );
void ZapBeam( int nHand );
int m_nLightningSprite;
// ---------------
// Glow
// ----------------
void ClearHandGlow( void );
float m_fGlowAge;
float m_fGlowChangeTime;
bool m_bGlowTurningOn;
int m_nCurGlowIndex;
CHandle<CVortigauntEffectDispel> m_hHandEffect[2];
void StartHandGlow( int beamType, int nHand );
void EndHandGlow( int beamType = VORTIGAUNT_BEAM_ALL );
void MaintainGlows( void );
// ----------------
// Healing
// ----------------
bool m_bRegenerateHealth;
float m_flNextHealTime; // Next time allowed to heal player
EHANDLE m_hHealTarget; // The person that I'm going to heal.
bool m_bPlayerRequestedHeal; // This adds some priority to our heal (allows it to happen in combat, etc)
float m_flNextHealTokenTime;
VortigauntHealState_t m_eHealState;
CBaseEntity *FindHealTarget( void );
bool HealBehaviorAvailable( void );
void SetHealTarget( CBaseEntity *pTarget, bool bPlayerRequested );
void GatherHealConditions( void );
int m_nNumTokensToSpawn;
float m_flHealHinderedTime;
float m_flPainTime;
float m_nextLineFireTime;
bool m_bArmorRechargeEnabled;
bool m_bForceArmorRecharge;
float m_flDispelTestTime;
bool m_bExtractingBugbait;
bool IsCarryingNPC( void ) const { return m_bCarryingNPC; }
bool m_bCarryingNPC;
COutputEvent m_OnFinishedExtractingBugbait;
COutputEvent m_OnFinishedChargingTarget;
COutputEvent m_OnPlayerUse;
//Adrian: Let's do it the right way!
int m_iLeftHandAttachment;
int m_iRightHandAttachment;
bool m_bStopLoopingSounds;
float m_flAimDelay; // Amount of time to suppress aiming
// used for fading from green vort to blue vort
CNetworkVar( bool, m_bIsBlue );
CNetworkVar( float, m_flBlueEndFadeTime );
// used for fading to black
CNetworkVar( bool, m_bIsBlack );
public:
DECLARE_SERVERCLASS();
DECLARE_DATADESC();
DEFINE_CUSTOM_AI;
};
//=============================================================================
//
// Charge Token
//
//=============================================================================
class CVortigauntChargeToken : public CBaseEntity
{
DECLARE_CLASS( CVortigauntChargeToken, CBaseEntity );
public:
static CVortigauntChargeToken *CreateChargeToken( const Vector &vecOrigin, CBaseEntity *pOwner, CBaseEntity *pTarget );
CVortigauntChargeToken( void );
virtual void Spawn( void );
virtual void Precache( void );
virtual unsigned int PhysicsSolidMaskForEntity( void ) const;
void FadeAndDie( void );
void SeekThink( void );
void SeekTouch( CBaseEntity *pOther );
void SetTargetEntity( CBaseEntity *pTarget ) { m_hTarget = pTarget; }
private:
Vector GetSteerVector( const Vector &vecForward );
float m_flLifetime;
EHANDLE m_hTarget;
CNetworkVar( bool, m_bFadeOut );
DECLARE_SERVERCLASS();
DECLARE_DATADESC();
};
//=============================================================================
//
// Dispel Effect
//
//=============================================================================
class CVortigauntEffectDispel : public CBaseEntity
{
DECLARE_CLASS( CVortigauntEffectDispel, CBaseEntity );
public:
static CVortigauntEffectDispel *CreateEffectDispel( const Vector &vecOrigin, CBaseEntity *pOwner, CBaseEntity *pTarget );
CVortigauntEffectDispel( void );
virtual void Spawn( void );
void FadeAndDie( void );
private:
CNetworkVar( bool, m_bFadeOut );
DECLARE_SERVERCLASS();
DECLARE_DATADESC();
};
#endif // NPC_VORTIGAUNT_H
|