|
|
//========= 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
|