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
|
//========= Copyright Valve Corporation, All rights reserved. ============//
#ifndef NPC_TURRET_FLOOR_H
#define NPC_TURRET_FLOOR_H
#ifdef _WIN32
#pragma once
#endif
#include "ai_basenpc.h"
#include "player_pickup.h"
#include "particle_system.h"
//Turret states
enum turretState_e
{
TURRET_SEARCHING,
TURRET_AUTO_SEARCHING,
TURRET_ACTIVE,
TURRET_SUPPRESSING,
TURRET_DEPLOYING,
TURRET_RETIRING,
TURRET_TIPPED,
TURRET_SELF_DESTRUCTING,
TURRET_STATE_TOTAL
};
//Eye states
enum eyeState_t
{
TURRET_EYE_SEE_TARGET, //Sees the target, bright and big
TURRET_EYE_SEEKING_TARGET, //Looking for a target, blinking (bright)
TURRET_EYE_DORMANT, //Not active
TURRET_EYE_DEAD, //Completely invisible
TURRET_EYE_DISABLED, //Turned off, must be reactivated before it'll deploy again (completely invisible)
TURRET_EYE_ALARM, // On side, but warning player to pick it back up
};
//Spawnflags
// BUG: These all stomp Base NPC spawnflags. Any Base NPC code called by this
// this class may have undesired side effects due to these being set.
#define SF_FLOOR_TURRET_AUTOACTIVATE 0x00000020
#define SF_FLOOR_TURRET_STARTINACTIVE 0x00000040
#define SF_FLOOR_TURRET_FASTRETIRE 0x00000080
#define SF_FLOOR_TURRET_OUT_OF_AMMO 0x00000100
#define SF_FLOOR_TURRET_CITIZEN 0x00000200 // Citizen modified turret
class CTurretTipController;
class CBeam;
class CSprite;
//-----------------------------------------------------------------------------
// Purpose: Floor turret
//-----------------------------------------------------------------------------
class CNPC_FloorTurret : public CNPCBaseInteractive<CAI_BaseNPC>, public CDefaultPlayerPickupVPhysics
{
DECLARE_CLASS( CNPC_FloorTurret, CNPCBaseInteractive<CAI_BaseNPC> );
public:
CNPC_FloorTurret( void );
virtual void Precache( void );
virtual void Spawn( void );
virtual void Activate( void );
virtual bool CreateVPhysics( void );
virtual void UpdateOnRemove( void );
virtual int OnTakeDamage( const CTakeDamageInfo &info );
virtual void PlayerPenetratingVPhysics( void );
virtual int VPhysicsTakeDamage( const CTakeDamageInfo &info );
virtual bool CanBecomeServerRagdoll( void ) { return false; }
#ifdef HL2_EPISODIC
// We don't want to be NPCSOLID because we'll collide with NPC clips
virtual unsigned int PhysicsSolidMaskForEntity( void ) const { return MASK_SOLID; }
#endif // HL2_EPISODIC
// Player pickup
virtual void OnPhysGunPickup( CBasePlayer *pPhysGunUser, PhysGunPickup_t reason );
virtual void OnPhysGunDrop( CBasePlayer *pPhysGunUser, PhysGunDrop_t Reason );
virtual bool HasPreferredCarryAnglesForPlayer( CBasePlayer *pPlayer );
virtual QAngle PreferredCarryAngles( void );
virtual bool OnAttemptPhysGunPickup( CBasePlayer *pPhysGunUser, PhysGunPickup_t reason );
const char *GetTracerType( void ) { return "AR2Tracer"; }
bool ShouldSavePhysics() { return true; }
bool HandleInteraction( int interactionType, void *data, CBaseCombatCharacter *sourceEnt );
// Think functions
virtual void Retire( void );
virtual void Deploy( void );
virtual void ActiveThink( void );
virtual void SearchThink( void );
virtual void AutoSearchThink( void );
virtual void TippedThink( void );
virtual void InactiveThink( void );
virtual void SuppressThink( void );
virtual void DisabledThink( void );
virtual void SelfDestructThink( void );
virtual void BreakThink( void );
virtual void HackFindEnemy( void );
virtual float GetAttackDamageScale( CBaseEntity *pVictim );
virtual Vector GetAttackSpread( CBaseCombatWeapon *pWeapon, CBaseEntity *pTarget );
// Do we have a physics attacker?
CBasePlayer *HasPhysicsAttacker( float dt );
bool IsHeldByPhyscannon( ) { return VPhysicsGetObject() && (VPhysicsGetObject()->GetGameFlags() & FVPHYSICS_PLAYER_HELD); }
// Use functions
void ToggleUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value );
int ObjectCaps()
{
return BaseClass::ObjectCaps() | FCAP_IMPULSE_USE;
}
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
CBasePlayer *pPlayer = ToBasePlayer( pActivator );
if ( pPlayer )
{
pPlayer->PickupObject( this, false );
}
}
// Inputs
void InputToggle( inputdata_t &inputdata );
void InputEnable( inputdata_t &inputdata );
void InputDisable( inputdata_t &inputdata );
void InputDepleteAmmo( inputdata_t &inputdata );
void InputRestoreAmmo( inputdata_t &inputdata );
void InputSelfDestruct( inputdata_t &inputdata );
virtual bool IsValidEnemy( CBaseEntity *pEnemy );
bool CanBeAnEnemyOf( CBaseEntity *pEnemy );
bool IsBeingCarriedByPlayer( void ) { return m_bCarriedByPlayer; }
bool WasJustDroppedByPlayer( void );
int BloodColor( void ) { return DONT_BLEED; }
float MaxYawSpeed( void );
virtual Class_T Classify( void );
Vector EyePosition( void )
{
UpdateMuzzleMatrix();
Vector vecOrigin;
MatrixGetColumn( m_muzzleToWorld, 3, vecOrigin );
Vector vecForward;
MatrixGetColumn( m_muzzleToWorld, 0, vecForward );
// Note: We back up into the model to avoid an edge case where the eyes clip out of the world and
// cause problems with the PVS calculations -- jdw
vecOrigin -= vecForward * 8.0f;
return vecOrigin;
}
Vector EyeOffset( Activity nActivity ) { return Vector( 0, 0, 58 ); }
// Restore the turret to working operation after falling over
void ReturnToLife( void );
int DrawDebugTextOverlays( void );
// 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 )
{
// For now, turn green so we can tell who is hacked.
SetRenderColor( 0, 255, 0 );
m_bHackedByAlyx = true;
}
static float fMaxTipControllerVelocity;
static float fMaxTipControllerAngularVelocity;
protected:
virtual bool PreThink( turretState_e state );
virtual void Shoot( const Vector &vecSrc, const Vector &vecDirToEnemy, bool bStrict = false );
virtual void SetEyeState( eyeState_t state );
void Ping( void );
void Toggle( void );
void Enable( void );
void Disable( void );
void SpinUp( void );
void SpinDown( void );
virtual bool OnSide( void );
bool IsCitizenTurret( void ) { return HasSpawnFlags( SF_FLOOR_TURRET_CITIZEN ); }
bool UpdateFacing( void );
void DryFire( void );
void UpdateMuzzleMatrix();
protected:
matrix3x4_t m_muzzleToWorld;
int m_muzzleToWorldTick;
int m_iAmmoType;
bool m_bAutoStart;
bool m_bActive; //Denotes the turret is deployed and looking for targets
bool m_bBlinkState;
bool m_bEnabled; //Denotes whether the turret is able to deploy or not
bool m_bNoAlarmSounds;
bool m_bSelfDestructing; // Going to blow up
float m_flDestructStartTime;
float m_flShotTime;
float m_flLastSight;
float m_flThrashTime;
float m_flPingTime;
float m_flNextActivateSoundTime;
bool m_bCarriedByPlayer;
bool m_bUseCarryAngles;
float m_flPlayerDropTime;
int m_iKeySkin;
CHandle<CBaseCombatCharacter> m_hLastNPCToKickMe; // Stores the last NPC who tried to knock me over
float m_flKnockOverFailedTime; // Time at which we should tell the NPC that he failed to knock me over
QAngle m_vecGoalAngles;
int m_iEyeAttachment;
int m_iMuzzleAttachment;
eyeState_t m_iEyeState;
CHandle<CSprite> m_hEyeGlow;
CHandle<CBeam> m_hLaser;
CHandle<CTurretTipController> m_pMotionController;
CHandle<CParticleSystem> m_hFizzleEffect;
Vector m_vecEnemyLKP;
// physics influence
CHandle<CBasePlayer> m_hPhysicsAttacker;
float m_flLastPhysicsInfluenceTime;
static const char *m_pShotSounds[];
COutputEvent m_OnDeploy;
COutputEvent m_OnRetire;
COutputEvent m_OnTipped;
COutputEvent m_OnPhysGunPickup;
COutputEvent m_OnPhysGunDrop;
bool m_bHackedByAlyx;
HSOUNDSCRIPTHANDLE m_ShotSounds;
DECLARE_DATADESC();
DEFINE_CUSTOM_AI;
};
//
// Tip controller
//
class CTurretTipController : public CPointEntity, public IMotionEvent
{
DECLARE_CLASS( CTurretTipController, CPointEntity );
DECLARE_DATADESC();
public:
~CTurretTipController( void );
void Spawn( void );
void Activate( void );
void Enable( bool state = true );
void Suspend( float time );
float SuspendedTill( void );
bool Enabled( void );
static CTurretTipController *CreateTipController( CNPC_FloorTurret *pOwner )
{
if ( pOwner == NULL )
return NULL;
CTurretTipController *pController = (CTurretTipController *) Create( "floorturret_tipcontroller", pOwner->GetAbsOrigin(), pOwner->GetAbsAngles() );
if ( pController != NULL )
{
pController->m_pParentTurret = pOwner;
}
return pController;
}
// IMotionEvent
virtual simresult_e Simulate( IPhysicsMotionController *pController, IPhysicsObject *pObject, float deltaTime, Vector &linear, AngularImpulse &angular );
private:
bool m_bEnabled;
float m_flSuspendTime;
Vector m_worldGoalAxis;
Vector m_localTestAxis;
IPhysicsMotionController *m_pController;
float m_angularLimit;
CNPC_FloorTurret *m_pParentTurret;
};
#endif //#ifndef NPC_TURRET_FLOOR_H
|