aboutsummaryrefslogtreecommitdiff
path: root/mp/src/game/server/hl2/npc_basescanner.h
blob: ab69c81caeeae2a2c4ea1baccd331f2e825214c9 (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: 
//
//=============================================================================

#ifndef NPC_BASESCANNER_H
#define NPC_BASESCANNER_H
#ifdef _WIN32
#pragma once
#endif

#include "cbase.h"
#include "player_pickup.h"
#include "weapon_physcannon.h"
#include "hl2_player.h"
#include "smoke_trail.h"
#include "ai_basenpc_physicsflyer.h"

//-----------------------------------------------------------------------------
// States for the scanner's sound.
//-----------------------------------------------------------------------------
enum ScannerFlyMode_t
{
	SCANNER_FLY_PHOTO = 0,		// Fly close to photograph entity
	SCANNER_FLY_PATROL,			// Fly slowly around the enviroment
	SCANNER_FLY_FAST,			// Fly quickly around the enviroment
	SCANNER_FLY_CHASE,			// Fly quickly around the enviroment
	SCANNER_FLY_SPOT,			// Fly above enity in spotlight position
	SCANNER_FLY_ATTACK,			// Get in my enemies face for spray or flash
	SCANNER_FLY_DIVE,			// Divebomb - only done when dead
	SCANNER_FLY_FOLLOW,			// Following a target
};

enum ScannerInspectAct_t
{
	SCANNER_INSACT_HANDS_UP,
	SCANNER_INSACT_SHOWARMBAND,
};

// Sentences
#define SCANNER_SENTENCE_ATTENTION	0
#define SCANNER_SENTENCE_HANDSUP	1
#define SCANNER_SENTENCE_PROCEED	2
#define SCANNER_SENTENCE_CURIOUS	3

// Scanner attack distances
#define SCANNER_ATTACK_NEAR_DIST		150		// Fly attack min distance
#define SCANNER_ATTACK_FAR_DIST			300		// Fly attack max distance
#define SCANNER_ATTACK_RANGE			350		// Attack max distance
#define	SCANNER_ATTACK_MIN_DELAY		8		// Min time between attacks
#define	SCANNER_ATTACK_MAX_DELAY		12		// Max time between attacks
#define	SCANNER_EVADE_TIME				1		// How long to evade after take damage

// Scanner movement vars
#define	SCANNER_BANK_RATE				30
#define	SCANNER_MAX_SPEED				250
#define	SCANNER_MAX_DIVE_BOMB_SPEED		2500
#define SCANNER_SQUAD_FLY_DIST			500		// How far to scanners stay apart
#define SCANNER_SQUAD_HELP_DIST			4000	// How far will I fly to help

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
class CNPC_BaseScanner : public CAI_BasePhysicsFlyingBot, public CDefaultPlayerPickupVPhysics
{
	DECLARE_CLASS( CNPC_BaseScanner, CAI_BasePhysicsFlyingBot );

public:
	CNPC_BaseScanner();

	void			Spawn(void);

	virtual void	UpdateEfficiency( bool bInPVS );

	Class_T			Classify( void ) { return(CLASS_SCANNER); }
	virtual float	GetAutoAimRadius();

	void			Event_Killed( const CTakeDamageInfo &info );
	int				OnTakeDamage_Alive( const CTakeDamageInfo &info );
	int				OnTakeDamage_Dying( const CTakeDamageInfo &info );
	void			TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr, CDmgAccumulator *pAccumulator );
	void			Gib(void);

	void			OnStateChange( NPC_STATE eOldState, NPC_STATE eNewState );
	void			ClampMotorForces( Vector &linear, AngularImpulse &angular );

	int				DrawDebugTextOverlays(void);

	virtual float	GetHeadTurnRate( void );

	virtual void	VPhysicsCollision( int index, gamevcollisionevent_t *pEvent );

	// 	CDefaultPlayerPickupVPhysics
	void			OnPhysGunPickup( CBasePlayer *pPhysGunUser, PhysGunPickup_t reason );
	void			OnPhysGunDrop( CBasePlayer *pPhysGunUser, PhysGunDrop_t Reason );

	bool			ShouldPlayIdleSound( void );
	void			IdleSound( void );
	void			DeathSound( const CTakeDamageInfo &info );
	void			AlertSound( void );
	void			PainSound( const CTakeDamageInfo &info );
	virtual char	*GetScannerSoundPrefix( void ) { return ""; }
	void			ScannerEmitSound( const char *pszSoundName );

	int				MeleeAttack1Conditions ( float flDot, float flDist );

	int				SelectSchedule(void);
	void			StartTask( const Task_t *pTask );
	void			OnScheduleChange( void );
	void			UpdateOnRemove( void );
	virtual float	GetMaxSpeed( void );

	void			PostRunStopMoving()	{} // scanner can use "movement" activities but not be moving

	virtual bool	CanBecomeServerRagdoll( void ) { return false;	}

	void			SpeakSentence( int sentenceType );

	bool			IsHeldByPhyscannon( void );

	// Inputs
	void			InputSetFlightSpeed( inputdata_t &inputdata );
	void			InputSetDistanceOverride( inputdata_t &inputdata );

protected:
	virtual char		*GetEngineSound( void ) { return NULL; }
	void				PlayFlySound(void);

	void				SetBanking( float flInterval );
	void				UpdateHead( float flInterval );
	inline CBaseEntity *EntityToWatch( void );

	bool				IsEnemyPlayerInSuit( void );

	// Movement
	virtual bool		OverridePathMove( CBaseEntity *pMoveTarget, float flInterval );
	virtual bool		OverrideMove( float flInterval );
	Vector				IdealGoalForMovement( const Vector &goalPos, const Vector &startPos, float idealRange, float idealHeight );
	virtual void		AdjustScannerVelocity( void ) { return; }
	virtual void		MoveToAttack(float flInterval);
	virtual void		MoveToTarget( float flInterval, const Vector &vecMoveTarget );
	virtual void		MoveExecute_Alive(float flInterval);
	virtual float		MinGroundDist(void) { return 64; }
	Vector				VelocityToEvade(CBaseCombatCharacter *pEnemy);
	virtual float		GetGoalDistance( void );

	// Divebombing
	virtual void		AttackDivebomb( void );
	void				DiveBombSoundThink();
	void				AttackDivebombCollide(float flInterval);
	void				MoveToDivebomb(float flInterval);
	void				BlendPhyscannonLaunchSpeed();

private:
	bool	GetGoalDirection( Vector *vOut );

	void	StartSmokeTrail( void );

	// Take damage from being thrown by a physcannon 
	void TakeDamageFromPhyscannon( CBasePlayer *pPlayer );

	// Take damage from physics impacts
	void TakeDamageFromPhysicsImpact( int index, gamevcollisionevent_t *pEvent );

	// Do we have a physics attacker?
	CBasePlayer *HasPhysicsAttacker( float dt );

	virtual void		StopLoopingSounds(void);

public:
	// ------------------------
	//  Death Cleanup
	// ------------------------
	CTakeDamageInfo		m_KilledInfo;

protected:
	ScannerFlyMode_t	m_nFlyMode;

	// Pose parameters
	int					m_nPoseTail;
	int					m_nPoseDynamo;
	int					m_nPoseFlare;
	int					m_nPoseFaceVert;
	int					m_nPoseFaceHoriz;

	bool				m_bHasSpoken;

	// Movement
	float				m_flFlyNoiseBase;
	float				m_flEngineStallTime;
	float				m_fNextFlySoundTime;
	Vector				m_vecDiveBombDirection;		// The direction we dive bomb. Calculated at the moment of death.
	float				m_flDiveBombRollForce;		// Used for roll while dive bombing.

	float				m_flGoalOverrideDistance;

	// Deriver scanner variables
	float				m_flAttackNearDist;
	float				m_flAttackFarDist;
	float				m_flAttackRange;

private:
	CSoundPatch			*m_pEngineSound;

	// physics influence
	CHandle<CBasePlayer>	m_hPhysicsAttacker;
	float					m_flLastPhysicsInfluenceTime;

	// Attacks
	SmokeTrail			*m_pSmokeTrail;

protected:
	DEFINE_CUSTOM_AI;

	// Custom interrupt conditions
	enum
	{
		COND_SCANNER_FLY_CLEAR = BaseClass::NEXT_CONDITION,
		COND_SCANNER_FLY_BLOCKED,							
		COND_SCANNER_GRABBED_BY_PHYSCANNON,
		COND_SCANNER_RELEASED_FROM_PHYSCANNON,

		NEXT_CONDITION,
	};

	// Custom schedules
	enum
	{
		SCHED_SCANNER_PATROL = BaseClass::NEXT_SCHEDULE,
		SCHED_SCANNER_ATTACK,
		SCHED_SCANNER_ATTACK_HOVER,
		SCHED_SCANNER_ATTACK_DIVEBOMB,
		SCHED_SCANNER_CHASE_ENEMY,
		SCHED_SCANNER_CHASE_TARGET,
		SCHED_SCANNER_FOLLOW_HOVER,
		SCHED_SCANNER_HELD_BY_PHYSCANNON,

		NEXT_SCHEDULE,
	};

	// Custom tasks
	enum
	{
		TASK_SCANNER_SET_FLY_PATROL = BaseClass::NEXT_TASK,
		TASK_SCANNER_SET_FLY_CHASE,
		TASK_SCANNER_SET_FLY_ATTACK,
		TASK_SCANNER_SET_FLY_DIVE,

		NEXT_TASK,
	};

	DECLARE_DATADESC();
};

#endif // NPC_BASESCANNER_H