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