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
|
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#ifndef NPC_MANHACK_H
#define NPC_MANHACK_H
#ifdef _WIN32
#pragma once
#endif
#include "ai_basenpc_physicsflyer.h"
#include "Sprite.h"
#include "SpriteTrail.h"
#include "player_pickup.h"
// Start with the engine off and folded up.
#define SF_MANHACK_PACKED_UP (1 << 16)
#define SF_MANHACK_NO_DAMAGE_EFFECTS (1 << 17)
#define SF_MANHACK_USE_AIR_NODES (1 << 18)
#define SF_MANHACK_CARRIED (1 << 19) // Being carried by a metrocop
#define SF_MANHACK_NO_DANGER_SOUNDS (1 << 20)
enum
{
MANHACK_EYE_STATE_IDLE,
MANHACK_EYE_STATE_CHASE,
MANHACK_EYE_STATE_CHARGE,
MANHACK_EYE_STATE_STUNNED,
};
//-----------------------------------------------------------------------------
// Attachment points.
//-----------------------------------------------------------------------------
#define MANHACK_GIB_HEALTH 30
#define MANHACK_INACTIVE_HEALTH 25
#define MANHACK_MAX_SPEED 500
#define MANHACK_BURST_SPEED 650
#define MANHACK_NPC_BURST_SPEED 800
//-----------------------------------------------------------------------------
// Movement parameters.
//-----------------------------------------------------------------------------
#define MANHACK_WAYPOINT_DISTANCE 25 // Distance from waypoint that counts as arrival.
class CSprite;
class SmokeTrail;
class CSoundPatch;
//-----------------------------------------------------------------------------
// Manhack
//-----------------------------------------------------------------------------
class CNPC_Manhack : public CNPCBaseInteractive<CAI_BasePhysicsFlyingBot>, public CDefaultPlayerPickupVPhysics
{
DECLARE_CLASS( CNPC_Manhack, CNPCBaseInteractive<CAI_BasePhysicsFlyingBot> );
DECLARE_SERVERCLASS();
public:
CNPC_Manhack();
~CNPC_Manhack();
Class_T Classify(void);
bool CorpseGib( const CTakeDamageInfo &info );
void Event_Dying(void);
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 TranslateNavGoal( CBaseEntity *pEnemy, Vector &chasePosition );
float GetDefaultNavGoalTolerance();
void UpdateOnRemove( void );
void KillSprites( float flDelay );
void OnStateChange( NPC_STATE OldState, NPC_STATE NewState );
virtual bool CreateVPhysics( void );
virtual void DeathSound( const CTakeDamageInfo &info );
virtual bool ShouldGib( const CTakeDamageInfo &info );
Activity NPC_TranslateActivity( Activity baseAct );
virtual int TranslateSchedule( int scheduleType );
int MeleeAttack1Conditions ( float flDot, float flDist );
void HandleAnimEvent( animevent_t *pEvent );
bool OverrideMove(float flInterval);
void MoveToTarget(float flInterval, const Vector &MoveTarget);
void MoveExecute_Alive(float flInterval);
void MoveExecute_Dead(float flInterval);
int MoveCollisionMask(void);
void TurnHeadRandomly( float flInterval );
void CrashTouch( CBaseEntity *pOther );
void StartEngine( bool fStartSound );
virtual Vector BodyTarget( const Vector &posSrc, bool bNoisy = true ) { return WorldSpaceCenter(); }
virtual float GetHeadTurnRate( void ) { return 45.0f; } // Degrees per second
void CheckCollisions(float flInterval);
virtual void GatherEnemyConditions( CBaseEntity *pEnemy );
void PlayFlySound(void);
virtual void StopLoopingSounds(void);
void Precache(void);
void RunTask( const Task_t *pTask );
void Spawn(void);
void Activate();
void StartTask( const Task_t *pTask );
void BladesInit();
void SoundInit( void );
void StartEye( void );
bool HandleInteraction(int interactionType, void* data, CBaseCombatCharacter* sourceEnt);
void PostNPCInit( void );
void GatherConditions();
void PrescheduleThink( void );
void SpinBlades(float flInterval);
void Slice( CBaseEntity *pHitEntity, float flInterval, trace_t &tr );
void Bump( CBaseEntity *pHitEntity, float flInterval, trace_t &tr );
void Splash( const Vector &vecSplashPos );
float ManhackMaxSpeed( void );
virtual void VPhysicsShadowCollision( int index, gamevcollisionevent_t *pEvent );
void VPhysicsCollision( int index, gamevcollisionevent_t *pEvent );
void HitPhysicsObject( CBaseEntity *pOther );
virtual void ClampMotorForces( Vector &linear, AngularImpulse &angular );
unsigned int PhysicsSolidMaskForEntity( void ) const;
// Create smoke trail!
void CreateSmokeTrail();
void DestroySmokeTrail();
void Ignite( float flFlameLifetime, bool bNPCOnly, float flSize, bool bCalledByLevelDesigner ) { return; }
void InputDisableSwarm( inputdata_t &inputdata );
void InputUnpack( inputdata_t &inputdata );
// CDefaultPlayerPickupVPhysics
virtual void OnPhysGunPickup( CBasePlayer *pPhysGunUser, PhysGunPickup_t reason );
virtual void OnPhysGunDrop( CBasePlayer *pPhysGunUser, PhysGunDrop_t Reason );
CBasePlayer *HasPhysicsAttacker( float dt );
float GetMaxEnginePower();
// INPCInteractive Functions
virtual bool CanInteractWith( CAI_BaseNPC *pUser ) { return false; } // Disabled for now (sjb)
virtual bool HasBeenInteractedWith() { return m_bHackedByAlyx; }
virtual void NotifyInteraction( CAI_BaseNPC *pUser )
{
// Turn the sprites off and on again so their colors will change.
KillSprites(0.0f);
m_bHackedByAlyx = true;
StartEye();
}
virtual void InputPowerdown( inputdata_t &inputdata )
{
m_iHealth = 0;
}
DEFINE_CUSTOM_AI;
DECLARE_DATADESC();
private:
bool IsInEffectiveTargetZone( CBaseEntity *pTarget );
void MaintainGroundHeight( void );
void StartBurst( const Vector &vecDirection );
void StopBurst( bool bInterruptSchedule = false );
void UpdatePanels( void );
void SetEyeState( int state );
void ShowHostile( bool hostile = true );
bool IsFlyingActivity( Activity baseAct );
// Computes the slice bounce velocity
void ComputeSliceBounceVelocity( CBaseEntity *pHitEntity, trace_t &tr );
// Take damage from being thrown by a physcannon
void TakeDamageFromPhyscannon( CBasePlayer *pPlayer );
// Take damage from a vehicle:
void TakeDamageFromVehicle( int index, gamevcollisionevent_t *pEvent );
// Take damage from physics impacts
void TakeDamageFromPhysicsImpact( int index, gamevcollisionevent_t *pEvent );
// Are we being held by the physcannon?
bool IsHeldByPhyscannon( );
void StartLoitering( const Vector &vecLoiterPosition );
void StopLoitering() { m_vecLoiterPosition = vec3_invalid; m_fTimeNextLoiterPulse = gpGlobals->curtime; }
bool IsLoitering() { return m_vecLoiterPosition != vec3_invalid; }
void Loiter();
//
// Movement variables.
//
Vector m_vForceVelocity; // Someone forced me to move
Vector m_vTargetBanking;
Vector m_vForceMoveTarget; // Will fly here
float m_fForceMoveTime; // If time is less than this
Vector m_vSwarmMoveTarget; // Will fly here
float m_fSwarmMoveTime; // If time is less than this
float m_fEnginePowerScale; // scale all thrust by this amount (usually 1.0!)
float m_flNextEngineSoundTime;
float m_flEngineStallTime;
float m_flNextBurstTime;
float m_flBurstDuration;
Vector m_vecBurstDirection;
float m_flWaterSuspendTime;
int m_nLastSpinSound;
// physics influence
CHandle<CBasePlayer> m_hPhysicsAttacker;
float m_flLastPhysicsInfluenceTime;
// Death
float m_fSparkTime;
float m_fSmokeTime;
bool m_bDirtyPitch; // indicates whether we want the sound pitch updated.(sjb)
bool m_bShowingHostile;
bool m_bBladesActive;
bool m_bIgnoreClipbrushes;
float m_flBladeSpeed;
CSprite *m_pEyeGlow;
CSprite *m_pLightGlow;
CHandle<SmokeTrail> m_hSmokeTrail;
int m_iPanel1;
int m_iPanel2;
int m_iPanel3;
int m_iPanel4;
int m_nLastWaterLevel;
bool m_bDoSwarmBehavior;
bool m_bGib;
bool m_bHeld;
bool m_bHackedByAlyx;
Vector m_vecLoiterPosition;
float m_fTimeNextLoiterPulse;
float m_flBumpSuppressTime;
CNetworkVar( int, m_nEnginePitch1 );
CNetworkVar( int, m_nEnginePitch2 );
CNetworkVar( float, m_flEnginePitch1Time );
CNetworkVar( float, m_flEnginePitch2Time );
};
#endif //NPC_MANHACK_H
|