aboutsummaryrefslogtreecommitdiff
path: root/mp/src/game/server/hl2/npc_strider.h
diff options
context:
space:
mode:
Diffstat (limited to 'mp/src/game/server/hl2/npc_strider.h')
-rw-r--r--mp/src/game/server/hl2/npc_strider.h1290
1 files changed, 645 insertions, 645 deletions
diff --git a/mp/src/game/server/hl2/npc_strider.h b/mp/src/game/server/hl2/npc_strider.h
index 8673d339..dd645781 100644
--- a/mp/src/game/server/hl2/npc_strider.h
+++ b/mp/src/game/server/hl2/npc_strider.h
@@ -1,645 +1,645 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose:
-//
-//=============================================================================//
-
-#ifndef NPC_STRIDER_H
-#define NPC_STRIDER_H
-
-#include "ai_blended_movement.h"
-#include "ai_pathfinder.h"
-#include "ai_navigator.h"
-#include "ai_utils.h"
-#include "smoke_trail.h"
-#include "physics_bone_follower.h"
-#include "physics_prop_ragdoll.h"
-
-#if defined( _WIN32 )
-#pragma once
-#endif
-
-#include "tier0/memdbgon.h"
-
-class CNPC_Strider;
-class CNPC_Bullseye;
-class CStriderMinigun;
-
-//-----------------------------------------------------------------------------
-//
-// Support for moving Strider air nodes to the correct Z for the Strider
-// regardless of Hammer placement
-//
-//-----------------------------------------------------------------------------
-
-class CAI_Network;
-class CAI_Node;
-struct StriderMinigunViewcone_t;
-struct AI_EnemyInfo_t;
-
-void AdjustStriderNodePosition( CAI_Network *pNetwork, CAI_Node *pNode );
-
-//-----------------------------------------------------------------------------
-//
-// Strider Minigun
-//
-//-----------------------------------------------------------------------------
-
-abstract_class IMinigunHost
-{
-public:
- virtual void ShootMinigun( const Vector *pTarget, float aimError, const Vector &vecSpread = vec3_origin ) = 0;
- virtual void UpdateMinigunControls( float &yaw, float &pitch ) = 0;
- virtual void GetViewCone( StriderMinigunViewcone_t &cone ) = 0;
- virtual void NewTarget() = 0;
- virtual void OnMinigunStartShooting( CBaseEntity *pTarget ) = 0;
- virtual void OnMinigunStopShooting( CBaseEntity *pTarget ) = 0;
- virtual CAI_BaseNPC *GetEntity() = 0;
-};
-
-abstract_class IStriderMinigunHost : public IMinigunHost
-{
-public:
- virtual float GetMinigunRateOfFire() = 0;
- virtual float GetMinigunOnTargetTime() = 0;
- virtual float GetMinigunShootDuration() = 0;
- virtual float GetMinigunShootDowntime() = 0;
- virtual float GetMinigunShootVariation() = 0;
-};
-
-//-----------------------------------------------------------------------------
-//
-// npc_strider
-//
-//-----------------------------------------------------------------------------
-
-const int NUM_STRIDER_IK_TARGETS = 6;
-
-//---------------------------------------------------------
-
-class CNPC_Strider : public CAI_BlendingHost<CAI_BaseNPC>,
- public IStriderMinigunHost
-{
- DECLARE_CLASS( CNPC_Strider, CAI_BaseNPC );
- DECLARE_SERVERCLASS();
-
-public:
- CNPC_Strider();
- ~CNPC_Strider();
-
- //---------------------------------
-
- void Precache();
- void Spawn();
- bool CreateVPhysics();
- void InitBoneFollowers( void );
- void PostNPCInit();
- void Activate();
- void UpdateOnRemove();
- void InitBoneControllers();
- void OnRestore();
-
- Class_T Classify();
- bool ShouldAttractAutoAim( CBaseEntity *pAimingEnt );
-
- virtual float GetAutoAimRadius() { return 80.0f; }
-
- int DrawDebugTextOverlays();
-
- void UpdateEfficiency( bool bInPVS ) { SetEfficiency( ( GetSleepState() != AISS_AWAKE ) ? AIE_DORMANT : AIE_NORMAL ); SetMoveEfficiency( AIME_NORMAL ); }
- virtual bool ShouldProbeCollideAgainstEntity( CBaseEntity *pEntity );
-
- //---------------------------------
-
- virtual Vector GetNodeViewOffset() { return BaseClass::GetDefaultEyeOffset(); }
-
- Vector EyePosition();
- const Vector & GetViewOffset();
- Vector EyePositionCrouched() { return GetAbsOrigin() - Vector( 0, 0, 330 ); }
-
- //---------------------------------
- // CBaseAnimating
- void CalculateIKLocks( float currentTime );
- float GetIdealAccel() const { return GetIdealSpeed(); }
-
- //---------------------------------
- // Behavior
- //---------------------------------
- void NPCThink();
- void PrescheduleThink();
- void GatherConditions();
- void CheckFlinches() {} // Strider handles on own
- void GatherHeightConditions( const Vector &vTestPos, CBaseEntity *pEntity );
- void OnStateChange( NPC_STATE oldState, NPC_STATE newState );
- void BuildScheduleTestBits();
- int SelectSchedule();
- int TranslateSchedule( int scheduleType );
- void StartTask( const Task_t *pTask );
- void RunTask( const Task_t *pTask );
- bool HandleInteraction( int interactionType, void *data, CBaseCombatCharacter* sourceEnt );
- void HandleAnimEvent( animevent_t *pEvent );
-
- Disposition_t IRelationType( CBaseEntity *pTarget );
- void AddEntityRelationship( CBaseEntity *pEntity, Disposition_t nDisposition, int nPriority );
-
- bool ScheduledMoveToGoalEntity( int scheduleType, CBaseEntity *pGoalEntity, Activity movementActivity );
- bool ScheduledFollowPath( int scheduleType, CBaseEntity *pPathStart, Activity movementActivity );
-
- //---------------------------------
- // Inputs
- //---------------------------------
- void InputSetMinigunTime( inputdata_t &inputdata );
- void InputSetMinigunTarget( inputdata_t &inputdata );
- void InputDisableMinigun( inputdata_t &inputdata );
- void InputEnableMinigun( inputdata_t &inputdata );
- void InputSetCannonTarget( inputdata_t &inputdata );
- void InputFlickRagdoll( inputdata_t &inputdata );
- void InputDisableCollisionWith( inputdata_t &inputdata );
- void InputEnableCollisionWith( inputdata_t &inputdata );
- void InputCrouch( inputdata_t &inputdata );
- void InputCrouchInstantly( inputdata_t &inputdata );
- void InputStand( inputdata_t &inputdata );
- void InputSetHeight( inputdata_t &inputdata );
- void InputSetTargetPath( inputdata_t &inputdata );
- void InputClearTargetPath( inputdata_t &inputdata );
- void InputDisableCrouchWalk( inputdata_t &inputdata );
- void InputEnableCrouchWalk( inputdata_t &inputdata );
- void InputEnableAggressiveBehavior( inputdata_t &inputdata );
- void InputDisableAggressiveBehavior( inputdata_t &inputdata );
- void InputStopShootingMinigunForSeconds( inputdata_t &inputdata );
- void InputDisableCrouch( inputdata_t &inputdata );
- void InputDisableMoveToLOS( inputdata_t &inputdata );
- void InputExplode( inputdata_t &inputdata );
- void InputScaleGroundSpeed( inputdata_t &inputdata );
-
- //---------------------------------
- // Combat
- //---------------------------------
- bool HasPass() { return m_PlayerFreePass.HasPass(); }
-
- bool FVisible( CBaseEntity *pEntity, int traceMask = MASK_BLOCKLOS, CBaseEntity **ppBlocker = NULL );
- Vector BodyTarget( const Vector &posSrc, bool bNoisy );
-
- bool IsValidEnemy( CBaseEntity *pTarget );
- bool UpdateEnemyMemory( CBaseEntity *pEnemy, const Vector &position, CBaseEntity *pInformer = NULL );
- float StriderEnemyDistance( CBaseEntity *pEnemy );
-
- bool FCanCheckAttacks();
- int RangeAttack2Conditions( float flDot, float flDist );
- int MeleeAttack1Conditions( float flDot, float flDist );
- int MeleeAttack2Conditions( float flDot, float flDist );
- bool WeaponLOSCondition(const Vector &ownerPos, const Vector &targetPos, bool bSetConditions);
- bool CurrentWeaponLOSCondition(const Vector &targetPos, bool bSetConditions);
- bool IsValidShootPosition ( const Vector &vecCoverLocation, CAI_Node *pNode, CAI_Hint const *pHint );
- bool TestShootPosition(const Vector &vecShootPos, const Vector &targetPos );
-
- Vector Weapon_ShootPosition();
-
- void MakeTracer( const Vector &vecTracerSrc, const trace_t &tr, int iTracerType );
- void DoImpactEffect( trace_t &tr, int nDamageType );
- void DoMuzzleFlash( void );
-
- bool CanShootThrough( const trace_t &tr, const Vector &vecTarget );
-
- void CreateFocus();
- CNPC_Bullseye * GetFocus();
-
- bool GetWeaponLosZ( const Vector &vOrigin, float minZ, float maxZ, float increment, CBaseEntity *pTarget, float *pResult );
-
- //---------------------------------
- // Sounds & speech
- //---------------------------------
- void AlertSound();
- void PainSound( const CTakeDamageInfo &info );
- void DeathSound( const CTakeDamageInfo &info );
- void HuntSound();
-
- //---------------------------------
- // Damage handling
- //---------------------------------
- void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr, CDmgAccumulator *pAccumulator );
- int OnTakeDamage_Alive( const CTakeDamageInfo &info );
- int TakeDamageFromCombineBall( const CTakeDamageInfo &info );
- void Event_Killed( const CTakeDamageInfo &info );
- void RagdollDeathEffect( CRagdollProp *pRagdoll, float flDuration );
- bool BecomeRagdoll( const CTakeDamageInfo &info, const Vector &forceVector );
- void StartSmoking();
- void StopSmoking( float flDelay = 0.1 );
- bool IsSmoking() { return m_hSmoke != NULL; }
- void Explode();
-
- //---------------------------------
- // Posture
- //---------------------------------
- float GetMaxHeightModel() const { return 500.0; }
- float GetMaxHeight() const { return 490.0; }
- float GetMinHeight() const { return 200.0; }
- float GetHeightRange() const { return GetMaxHeight() - GetMinHeight(); }
- void SetHeight( float h );
- float GetHeight() { return GetPoseParameter( gm_BodyHeightPoseParam ); }
- void SetIdealHeight( float h );
- void SetAbsIdealHeight( float z );
- float GetIdealHeight() { return m_idealHeight; }
- Vector GetAdjustedOrigin() { Vector result = GetAbsOrigin(); result.z -= GetMaxHeightModel() - GetHeight(); return result; }
-
- bool IsInCrouchedPosture() { return GetIdealHeight() < GetMaxHeight() * .5; }
- bool IsInStandingPosture() { return !IsInCrouchedPosture(); }
- bool IsStriderCrouching();
- bool IsStriderStanding();
- void SetupGlobalModelData();
-
- virtual bool CanBecomeServerRagdoll( void ) { return false; }
-
- //---------------------------------
- // Navigation & Movement
- //---------------------------------
- class CNavigator : public CAI_ComponentWithOuter<CNPC_Strider, CAI_Navigator>
- {
- typedef CAI_ComponentWithOuter<CNPC_Strider, CAI_Navigator> BaseClass;
- public:
- CNavigator( CNPC_Strider *pOuter )
- : BaseClass( pOuter )
- {
- }
-
- void MoveCalcBaseGoal( AILocalMoveGoal_t *pMoveGoal );
- bool MoveUpdateWaypoint( AIMoveResult_t *pResult );
- bool DoFindPathToPos();
- bool ShouldOptimizeInitialPathSegment( AI_Waypoint_t *pFirstWaypoint );
- bool GetStoppingPath( CAI_WaypointList *pClippedWaypoints );
- };
-
- class CPathfinder : public CAI_Pathfinder
- {
- typedef CAI_Pathfinder BaseClass;
- public:
- CPathfinder( CNPC_Strider *pOuter ) : BaseClass( pOuter ) {}
- virtual bool CanUseLocalNavigation() { return false; }
- };
-
- friend class CNavigator;
- friend void AdjustStriderNodePosition( CAI_Network *pNetwork, CAI_Node *pNode );
-
- bool OverrideMove( float flInterval );
- void MaintainTurnActivity( void );
- bool IsUnusableNode(int iNodeID, CAI_Hint *pHint); // Override for special NPC behavior
- void TranslateNavGoal( CBaseEntity *pEnemy, Vector &chasePosition );
- bool HasPendingTargetPath();
- void SetTargetPath();
- float GetDefaultNavGoalTolerance();
- void OnMovementComplete();
- float GetSequenceGroundSpeed( CStudioHdr *pStudioHdr, int iSequence );
-
- float MaxYawSpeed();
-
- CAI_Navigator * CreateNavigator() { return new CNavigator( this ); }
- CAI_Pathfinder *CreatePathfinder() { return new CPathfinder( this ); }
-
- //---------------------------------
- // Minigun
- //---------------------------------
- void ShootMinigun( const Vector *pTarget, float aimError, const Vector &vecSpread = vec3_origin );
- void UpdateMinigunControls( float &yaw, float &pitch );
- void GetViewCone( StriderMinigunViewcone_t &cone );
- void NewTarget() { m_flTargetAcquiredTime = gpGlobals->curtime; }
- void OnMinigunStartShooting( CBaseEntity *pTarget ) {};
- void OnMinigunStopShooting( CBaseEntity *pTarget );
- float GetMinigunRateOfFire();
- float GetMinigunOnTargetTime();
- float GetMinigunShootDuration();
- float GetMinigunShootDowntime();
- float GetMinigunShootVariation();
-
- CAI_BaseNPC * GetEntity() { return this; }
-
- bool IsUsingAggressiveBehavior() { return m_bUseAggressiveBehavior; }
-
- //---------------------------------
- // Cannon
- //---------------------------------
- Vector CannonPosition();
- CBaseEntity * GetCannonTarget();
- bool HasCannonTarget() const;
- bool IsCannonTarget( CBaseEntity *pTarget ) const;
- bool AimCannonAt( CBaseEntity *pEntity, float flInterval );
- void FireCannon();
- void CannonHitThink();
-
- //---------------------------------
- // Collision handling
- //---------------------------------
-
- void VPhysicsShadowCollision( int index, gamevcollisionevent_t *pEvent );
- bool TestCollision( const Ray_t &ray, unsigned int mask, trace_t& trace );
-
- // Conservative collision volumes
- static float gm_strideLength;
-
-#ifdef HL2_EPISODIC
- void StriderBusterAttached( CBaseEntity *pAttached );
- void StriderBusterDetached( CBaseEntity *pAttached );
-#endif // HL2_EPISODIC
-
-public:
-
- //---------------------------------
- // Misc
- //---------------------------------
- bool CarriedByDropship();
- void CarriedThink();
-
- //---------------------------------
- // Foot handling
- //---------------------------------
- Vector LeftFootHit( float eventtime );
- Vector RightFootHit( float eventtime );
- Vector BackFootHit( float eventtime );
- void StompHit( int followerBoneIndex );
-
- void FootFX( const Vector &origin );
- Vector CalculateStompHitPosition( CBaseEntity *pEnemy );
- bool IsLegBoneFollower( CBoneFollower *pFollower );
- CBoneFollower *GetBoneFollowerByIndex( int nIndex );
- int GetBoneFollowerIndex( CBoneFollower *pFollower );
-
-protected:
- // Because the strider is a leaf class, we can use
- // static variables to store this information, and save some memory.
- // Should the strider end up having inheritors, their activate may
- // stomp these numbers, in which case you should make these ordinary members
- // again.
- //
- // The strider also caches some pose parameters in SetupGlobalModelData().
- static int m_poseMiniGunYaw, m_poseMiniGunPitch;
- static bool m_sbStaticPoseParamsLoaded;
- virtual void PopulatePoseParameters( void );
-
-private:
-
- bool ShouldExplodeFromDamage( const CTakeDamageInfo &info );
- bool m_bExploding;
-
- //-----------------------------------------------------
- // Conditions, Schedules, Tasks
- //-----------------------------------------------------
- enum
- {
- SCHED_STRIDER_RANGE_ATTACK1 = BaseClass::NEXT_SCHEDULE,
- SCHED_STRIDER_RANGE_ATTACK2, // Immolator
- SCHED_STRIDER_CROUCH,
- SCHED_STRIDER_STAND,
- SCHED_STRIDER_DODGE,
- SCHED_STRIDER_STOMPL,
- SCHED_STRIDER_STOMPR,
- SCHED_STRIDER_FLICKL,
- SCHED_STRIDER_FLICKR,
- SCHED_STRIDER_HUNT,
- SCHED_STRIDER_DIE,
- SCHED_STRIDER_ATTACK_CANNON_TARGET,
- SCHED_STRIDER_CHASE_ENEMY,
- SCHED_STRIDER_COMBAT_FACE,
- SCHED_STRIDER_AGGRESSIVE_COMBAT_STAND,
- SCHED_STRIDER_ESTABLISH_LINE_OF_FIRE_CANNON,
- SCHED_STRIDER_FALL_TO_GROUND,
-
- TASK_STRIDER_AIM = BaseClass::NEXT_TASK,
- TASK_STRIDER_DODGE,
- TASK_STRIDER_STOMP,
- TASK_STRIDER_BREAKDOWN,
- TASK_STRIDER_START_MOVING,
- TASK_STRIDER_REFRESH_HUNT_PATH,
- TASK_STRIDER_GET_PATH_TO_CANNON_TARGET,
- TASK_STRIDER_FACE_CANNON_TARGET,
- TASK_STRIDER_SET_HEIGHT,
- TASK_STRIDER_GET_PATH_TO_CANNON_LOS,
- TASK_STRIDER_SET_CANNON_HEIGHT,
- TASK_STRIDER_FIRE_CANNON,
- TASK_STRIDER_FALL_TO_GROUND,
-
- COND_STRIDER_DO_FLICK = BaseClass::NEXT_CONDITION,
- COND_TRACK_PATH_GO,
- COND_STRIDER_SHOULD_CROUCH,
- COND_STRIDER_SHOULD_STAND,
- COND_STRIDER_MINIGUN_SHOOTING,
- COND_STRIDER_MINIGUN_NOT_SHOOTING,
- COND_STRIDER_HAS_CANNON_TARGET,
- COND_STRIDER_ENEMY_UPDATED,
- COND_STRIDER_HAS_LOS_Z,
- };
-
- string_t m_iszStriderBusterName;
- string_t m_iszMagnadeClassname;
- string_t m_iszHunterClassname;
-
- CStriderMinigun *m_pMinigun;
- int m_miniGunAmmo;
- int m_miniGunDirectAmmo;
- float m_nextShootTime;
- float m_nextStompTime;
- float m_ragdollTime;
- float m_miniGunShootDuration;
- float m_aimYaw;
- float m_aimPitch;
- Vector m_blastHit;
- Vector m_blastNormal;
- CNetworkVector( m_vecHitPos );
- CNetworkArray( Vector, m_vecIKTarget, NUM_STRIDER_IK_TARGETS );
-
- CRandSimTimer m_PostureAnimationTimer;
-
- EHANDLE m_hRagdoll;
-
- EHANDLE m_hCannonTarget;
- CSimpleSimTimer m_AttemptCannonLOSTimer;
-
- float m_flSpeedScale;
- float m_flTargetSpeedScale;
-
- CSimpleSimTimer m_LowZCorrectionTimer;
-
- // Contained Bone Follower manager
- CBoneFollowerManager m_BoneFollowerManager;
-
- int m_BodyTargetBone;
-
- bool m_bDisableBoneFollowers;
-
- int m_iVisibleEnemies;
- float m_flTargetAcquiredTime;
- bool m_bCrouchLocked; // Designer made the strider crouch. Don't let the AI stand him up.
- bool m_bNoCrouchWalk;
- bool m_bDontCrouch;
- bool m_bNoMoveToLOS;
- bool m_bFastCrouch;
- bool m_bMinigunEnabled; // If false, minigun disabled by level designer until further notice.
-
- float m_idealHeight;
- float m_HeightVelocity;
-
- // FIXME: move to a base class to handle turning for blended movement derived characters
- float m_prevYaw;
- float m_doTurn;
- float m_doLeft;
- float m_doRight;
- float m_flNextTurnAct;
-
- string_t m_strTrackName;
-
- EHANDLE m_hFocus;
-
- float m_flTimeLastAlertSound;
- float m_flTimeNextHuntSound;
- bool m_bUseAggressiveBehavior;
- float m_flTimePlayerMissileDetected;
- EHANDLE m_hPlayersMissile;
- bool m_bMinigunUseDirectFire;
-
- CHandle<SmokeTrail> m_hSmoke;
-
- CSimpleSimTimer m_EnemyUpdatedTimer;
-
- CAI_FreePass m_PlayerFreePass;
-
-#ifdef HL2_EPISODIC
- CUtlVector< EHANDLE > m_hAttachedBusters; // List of busters attached to us
-#endif // HL2_EPISODIC
-
- static float gm_zCannonDist;
- static float gm_zMinigunDist;
- static Vector gm_vLocalRelativePositionCannon;
- static Vector gm_vLocalRelativePositionMinigun;
-
- static int gm_YawControl;
- static int gm_PitchControl;
- static int gm_CannonAttachment;
- static int gm_BodyHeightPoseParam;
-
- DEFINE_CUSTOM_AI;
-
- DECLARE_DATADESC();
-};
-
-//-----------------------------------------------------------------------------
-//---------------------------------------------------------
-
-enum StriderMinigunPeg_t
-{
- MINIGUN_PEGGED_DONT_CARE = 0,
- MINIGUN_PEGGED_UP,
- MINIGUN_PEGGED_DOWN,
- MINIGUN_PEGGED_LEFT,
- MINIGUN_PEGGED_RIGHT,
-};
-
-//---------------------------------------------------------
-
-struct StriderMinigunViewcone_t
-{
- Vector origin;
- Vector axis;
- float cosAngle;
- float length;
-};
-
-//---------------------------------------------------------
-
-struct StriderMinigunAnimController_t
-{
- float current;
- float target;
- float rate;
-
- void Update( float dt, bool approach = true )
- {
- if( approach )
- {
- current = Approach( target, current, rate * dt );
- }
- else
- {
- current = target;
- }
- }
-
- void Random( float minTarget, float maxTarget, float minRate, float maxRate )
- {
- target = random->RandomFloat( minTarget, maxTarget );
- rate = random->RandomFloat( minRate, maxRate );
- }
-};
-
-//---------------------------------------------------------
-
-class CStriderMinigun
-{
-public:
- DECLARE_DATADESC();
-
- void Init();
- void SetTarget( IStriderMinigunHost *pHost, CBaseEntity *pTarget, bool bOverrideEnemy = false );
- CBaseEntity *GetTarget() { return m_hTarget.Get(); }
- void Think( IStriderMinigunHost *pHost, float dt );
- void SetState( int newState );
- bool ShouldFindTarget( IMinigunHost *pHost );
- void AimAtPoint( IStriderMinigunHost *pHost, const Vector &vecPoint, bool bSnap = false );
- void AimAtTarget( IStriderMinigunHost *pHost, CBaseEntity *pTarget, bool bSnap = false );
- void ShootAtTarget( IStriderMinigunHost *pHost, CBaseEntity *pTarget, float shootTime );
- void StartShooting( IStriderMinigunHost *pHost, CBaseEntity *pTarget, float duration );
- void ExtendShooting( float timeExtend );
- void SetShootDuration( float duration );
- void StopShootingForSeconds( IStriderMinigunHost *pHost, CBaseEntity *pTarget, float duration );
- bool IsPegged( int dir = MINIGUN_PEGGED_DONT_CARE );
- bool CanStartShooting( IStriderMinigunHost *pHost, CBaseEntity *pTargetEnt );
- float GetBurstTimeRemaining() { return m_burstTime - gpGlobals->curtime; }
-
- void RecordShotOnTarget() { m_iOnTargetShots++; }
- void ClearOnTarget() { m_iOnTargetShots = 0; }
- bool IsOnTarget( int numShots = 0 ) { return ( numShots == 0 ) ? (m_iOnTargetShots > 0) : (m_iOnTargetShots >= numShots); }
-
- void Enable( IMinigunHost *pHost, bool enable );
- float GetAimError();
-
- enum minigunstates_t
- {
- MINIGUN_OFF = 0,
- MINIGUN_SHOOTING = 1,
- };
-
- int GetState() { return m_minigunState; }
- bool IsShooting() { return GetState() == MINIGUN_SHOOTING; }
-
-private:
- bool m_enable;
- int m_minigunState;
- float m_nextBulletTime; // Minigun is shooting, when can I fire my next bullet?
- float m_burstTime; // If firing, how long till done? If not, how long till I can?
- float m_nextTwitchTime;
- int m_randomState;
- EHANDLE m_hTarget;
- StriderMinigunAnimController_t m_yaw;
- StriderMinigunAnimController_t m_pitch;
- bool m_bWarnedAI;
- float m_shootDuration;
- Vector m_vecAnchor; // A burst starts here and goes to the target's orgin.
- bool m_bOverrideEnemy; // The minigun wants something other than the Strider's enemy as a target right now.
- Vector m_vecLastTargetPos; // Last place minigun saw the target.
- int m_iOnTargetShots;
-};
-
-
-class CSparkTrail : public CPointEntity
-{
- DECLARE_CLASS( CSparkTrail, CPointEntity );
- void Spawn( void );
- void SparkThink( void );
-
- virtual void Precache();
-
- DECLARE_DATADESC();
-};
-
-#include "tier0/memdbgoff.h"
-
-#endif // NPC_STRIDER_H
-
-//=============================================================================
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================//
+
+#ifndef NPC_STRIDER_H
+#define NPC_STRIDER_H
+
+#include "ai_blended_movement.h"
+#include "ai_pathfinder.h"
+#include "ai_navigator.h"
+#include "ai_utils.h"
+#include "smoke_trail.h"
+#include "physics_bone_follower.h"
+#include "physics_prop_ragdoll.h"
+
+#if defined( _WIN32 )
+#pragma once
+#endif
+
+#include "tier0/memdbgon.h"
+
+class CNPC_Strider;
+class CNPC_Bullseye;
+class CStriderMinigun;
+
+//-----------------------------------------------------------------------------
+//
+// Support for moving Strider air nodes to the correct Z for the Strider
+// regardless of Hammer placement
+//
+//-----------------------------------------------------------------------------
+
+class CAI_Network;
+class CAI_Node;
+struct StriderMinigunViewcone_t;
+struct AI_EnemyInfo_t;
+
+void AdjustStriderNodePosition( CAI_Network *pNetwork, CAI_Node *pNode );
+
+//-----------------------------------------------------------------------------
+//
+// Strider Minigun
+//
+//-----------------------------------------------------------------------------
+
+abstract_class IMinigunHost
+{
+public:
+ virtual void ShootMinigun( const Vector *pTarget, float aimError, const Vector &vecSpread = vec3_origin ) = 0;
+ virtual void UpdateMinigunControls( float &yaw, float &pitch ) = 0;
+ virtual void GetViewCone( StriderMinigunViewcone_t &cone ) = 0;
+ virtual void NewTarget() = 0;
+ virtual void OnMinigunStartShooting( CBaseEntity *pTarget ) = 0;
+ virtual void OnMinigunStopShooting( CBaseEntity *pTarget ) = 0;
+ virtual CAI_BaseNPC *GetEntity() = 0;
+};
+
+abstract_class IStriderMinigunHost : public IMinigunHost
+{
+public:
+ virtual float GetMinigunRateOfFire() = 0;
+ virtual float GetMinigunOnTargetTime() = 0;
+ virtual float GetMinigunShootDuration() = 0;
+ virtual float GetMinigunShootDowntime() = 0;
+ virtual float GetMinigunShootVariation() = 0;
+};
+
+//-----------------------------------------------------------------------------
+//
+// npc_strider
+//
+//-----------------------------------------------------------------------------
+
+const int NUM_STRIDER_IK_TARGETS = 6;
+
+//---------------------------------------------------------
+
+class CNPC_Strider : public CAI_BlendingHost<CAI_BaseNPC>,
+ public IStriderMinigunHost
+{
+ DECLARE_CLASS( CNPC_Strider, CAI_BaseNPC );
+ DECLARE_SERVERCLASS();
+
+public:
+ CNPC_Strider();
+ ~CNPC_Strider();
+
+ //---------------------------------
+
+ void Precache();
+ void Spawn();
+ bool CreateVPhysics();
+ void InitBoneFollowers( void );
+ void PostNPCInit();
+ void Activate();
+ void UpdateOnRemove();
+ void InitBoneControllers();
+ void OnRestore();
+
+ Class_T Classify();
+ bool ShouldAttractAutoAim( CBaseEntity *pAimingEnt );
+
+ virtual float GetAutoAimRadius() { return 80.0f; }
+
+ int DrawDebugTextOverlays();
+
+ void UpdateEfficiency( bool bInPVS ) { SetEfficiency( ( GetSleepState() != AISS_AWAKE ) ? AIE_DORMANT : AIE_NORMAL ); SetMoveEfficiency( AIME_NORMAL ); }
+ virtual bool ShouldProbeCollideAgainstEntity( CBaseEntity *pEntity );
+
+ //---------------------------------
+
+ virtual Vector GetNodeViewOffset() { return BaseClass::GetDefaultEyeOffset(); }
+
+ Vector EyePosition();
+ const Vector & GetViewOffset();
+ Vector EyePositionCrouched() { return GetAbsOrigin() - Vector( 0, 0, 330 ); }
+
+ //---------------------------------
+ // CBaseAnimating
+ void CalculateIKLocks( float currentTime );
+ float GetIdealAccel() const { return GetIdealSpeed(); }
+
+ //---------------------------------
+ // Behavior
+ //---------------------------------
+ void NPCThink();
+ void PrescheduleThink();
+ void GatherConditions();
+ void CheckFlinches() {} // Strider handles on own
+ void GatherHeightConditions( const Vector &vTestPos, CBaseEntity *pEntity );
+ void OnStateChange( NPC_STATE oldState, NPC_STATE newState );
+ void BuildScheduleTestBits();
+ int SelectSchedule();
+ int TranslateSchedule( int scheduleType );
+ void StartTask( const Task_t *pTask );
+ void RunTask( const Task_t *pTask );
+ bool HandleInteraction( int interactionType, void *data, CBaseCombatCharacter* sourceEnt );
+ void HandleAnimEvent( animevent_t *pEvent );
+
+ Disposition_t IRelationType( CBaseEntity *pTarget );
+ void AddEntityRelationship( CBaseEntity *pEntity, Disposition_t nDisposition, int nPriority );
+
+ bool ScheduledMoveToGoalEntity( int scheduleType, CBaseEntity *pGoalEntity, Activity movementActivity );
+ bool ScheduledFollowPath( int scheduleType, CBaseEntity *pPathStart, Activity movementActivity );
+
+ //---------------------------------
+ // Inputs
+ //---------------------------------
+ void InputSetMinigunTime( inputdata_t &inputdata );
+ void InputSetMinigunTarget( inputdata_t &inputdata );
+ void InputDisableMinigun( inputdata_t &inputdata );
+ void InputEnableMinigun( inputdata_t &inputdata );
+ void InputSetCannonTarget( inputdata_t &inputdata );
+ void InputFlickRagdoll( inputdata_t &inputdata );
+ void InputDisableCollisionWith( inputdata_t &inputdata );
+ void InputEnableCollisionWith( inputdata_t &inputdata );
+ void InputCrouch( inputdata_t &inputdata );
+ void InputCrouchInstantly( inputdata_t &inputdata );
+ void InputStand( inputdata_t &inputdata );
+ void InputSetHeight( inputdata_t &inputdata );
+ void InputSetTargetPath( inputdata_t &inputdata );
+ void InputClearTargetPath( inputdata_t &inputdata );
+ void InputDisableCrouchWalk( inputdata_t &inputdata );
+ void InputEnableCrouchWalk( inputdata_t &inputdata );
+ void InputEnableAggressiveBehavior( inputdata_t &inputdata );
+ void InputDisableAggressiveBehavior( inputdata_t &inputdata );
+ void InputStopShootingMinigunForSeconds( inputdata_t &inputdata );
+ void InputDisableCrouch( inputdata_t &inputdata );
+ void InputDisableMoveToLOS( inputdata_t &inputdata );
+ void InputExplode( inputdata_t &inputdata );
+ void InputScaleGroundSpeed( inputdata_t &inputdata );
+
+ //---------------------------------
+ // Combat
+ //---------------------------------
+ bool HasPass() { return m_PlayerFreePass.HasPass(); }
+
+ bool FVisible( CBaseEntity *pEntity, int traceMask = MASK_BLOCKLOS, CBaseEntity **ppBlocker = NULL );
+ Vector BodyTarget( const Vector &posSrc, bool bNoisy );
+
+ bool IsValidEnemy( CBaseEntity *pTarget );
+ bool UpdateEnemyMemory( CBaseEntity *pEnemy, const Vector &position, CBaseEntity *pInformer = NULL );
+ float StriderEnemyDistance( CBaseEntity *pEnemy );
+
+ bool FCanCheckAttacks();
+ int RangeAttack2Conditions( float flDot, float flDist );
+ int MeleeAttack1Conditions( float flDot, float flDist );
+ int MeleeAttack2Conditions( float flDot, float flDist );
+ bool WeaponLOSCondition(const Vector &ownerPos, const Vector &targetPos, bool bSetConditions);
+ bool CurrentWeaponLOSCondition(const Vector &targetPos, bool bSetConditions);
+ bool IsValidShootPosition ( const Vector &vecCoverLocation, CAI_Node *pNode, CAI_Hint const *pHint );
+ bool TestShootPosition(const Vector &vecShootPos, const Vector &targetPos );
+
+ Vector Weapon_ShootPosition();
+
+ void MakeTracer( const Vector &vecTracerSrc, const trace_t &tr, int iTracerType );
+ void DoImpactEffect( trace_t &tr, int nDamageType );
+ void DoMuzzleFlash( void );
+
+ bool CanShootThrough( const trace_t &tr, const Vector &vecTarget );
+
+ void CreateFocus();
+ CNPC_Bullseye * GetFocus();
+
+ bool GetWeaponLosZ( const Vector &vOrigin, float minZ, float maxZ, float increment, CBaseEntity *pTarget, float *pResult );
+
+ //---------------------------------
+ // Sounds & speech
+ //---------------------------------
+ void AlertSound();
+ void PainSound( const CTakeDamageInfo &info );
+ void DeathSound( const CTakeDamageInfo &info );
+ void HuntSound();
+
+ //---------------------------------
+ // Damage handling
+ //---------------------------------
+ void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr, CDmgAccumulator *pAccumulator );
+ int OnTakeDamage_Alive( const CTakeDamageInfo &info );
+ int TakeDamageFromCombineBall( const CTakeDamageInfo &info );
+ void Event_Killed( const CTakeDamageInfo &info );
+ void RagdollDeathEffect( CRagdollProp *pRagdoll, float flDuration );
+ bool BecomeRagdoll( const CTakeDamageInfo &info, const Vector &forceVector );
+ void StartSmoking();
+ void StopSmoking( float flDelay = 0.1 );
+ bool IsSmoking() { return m_hSmoke != NULL; }
+ void Explode();
+
+ //---------------------------------
+ // Posture
+ //---------------------------------
+ float GetMaxHeightModel() const { return 500.0; }
+ float GetMaxHeight() const { return 490.0; }
+ float GetMinHeight() const { return 200.0; }
+ float GetHeightRange() const { return GetMaxHeight() - GetMinHeight(); }
+ void SetHeight( float h );
+ float GetHeight() { return GetPoseParameter( gm_BodyHeightPoseParam ); }
+ void SetIdealHeight( float h );
+ void SetAbsIdealHeight( float z );
+ float GetIdealHeight() { return m_idealHeight; }
+ Vector GetAdjustedOrigin() { Vector result = GetAbsOrigin(); result.z -= GetMaxHeightModel() - GetHeight(); return result; }
+
+ bool IsInCrouchedPosture() { return GetIdealHeight() < GetMaxHeight() * .5; }
+ bool IsInStandingPosture() { return !IsInCrouchedPosture(); }
+ bool IsStriderCrouching();
+ bool IsStriderStanding();
+ void SetupGlobalModelData();
+
+ virtual bool CanBecomeServerRagdoll( void ) { return false; }
+
+ //---------------------------------
+ // Navigation & Movement
+ //---------------------------------
+ class CNavigator : public CAI_ComponentWithOuter<CNPC_Strider, CAI_Navigator>
+ {
+ typedef CAI_ComponentWithOuter<CNPC_Strider, CAI_Navigator> BaseClass;
+ public:
+ CNavigator( CNPC_Strider *pOuter )
+ : BaseClass( pOuter )
+ {
+ }
+
+ void MoveCalcBaseGoal( AILocalMoveGoal_t *pMoveGoal );
+ bool MoveUpdateWaypoint( AIMoveResult_t *pResult );
+ bool DoFindPathToPos();
+ bool ShouldOptimizeInitialPathSegment( AI_Waypoint_t *pFirstWaypoint );
+ bool GetStoppingPath( CAI_WaypointList *pClippedWaypoints );
+ };
+
+ class CPathfinder : public CAI_Pathfinder
+ {
+ typedef CAI_Pathfinder BaseClass;
+ public:
+ CPathfinder( CNPC_Strider *pOuter ) : BaseClass( pOuter ) {}
+ virtual bool CanUseLocalNavigation() { return false; }
+ };
+
+ friend class CNavigator;
+ friend void AdjustStriderNodePosition( CAI_Network *pNetwork, CAI_Node *pNode );
+
+ bool OverrideMove( float flInterval );
+ void MaintainTurnActivity( void );
+ bool IsUnusableNode(int iNodeID, CAI_Hint *pHint); // Override for special NPC behavior
+ void TranslateNavGoal( CBaseEntity *pEnemy, Vector &chasePosition );
+ bool HasPendingTargetPath();
+ void SetTargetPath();
+ float GetDefaultNavGoalTolerance();
+ void OnMovementComplete();
+ float GetSequenceGroundSpeed( CStudioHdr *pStudioHdr, int iSequence );
+
+ float MaxYawSpeed();
+
+ CAI_Navigator * CreateNavigator() { return new CNavigator( this ); }
+ CAI_Pathfinder *CreatePathfinder() { return new CPathfinder( this ); }
+
+ //---------------------------------
+ // Minigun
+ //---------------------------------
+ void ShootMinigun( const Vector *pTarget, float aimError, const Vector &vecSpread = vec3_origin );
+ void UpdateMinigunControls( float &yaw, float &pitch );
+ void GetViewCone( StriderMinigunViewcone_t &cone );
+ void NewTarget() { m_flTargetAcquiredTime = gpGlobals->curtime; }
+ void OnMinigunStartShooting( CBaseEntity *pTarget ) {};
+ void OnMinigunStopShooting( CBaseEntity *pTarget );
+ float GetMinigunRateOfFire();
+ float GetMinigunOnTargetTime();
+ float GetMinigunShootDuration();
+ float GetMinigunShootDowntime();
+ float GetMinigunShootVariation();
+
+ CAI_BaseNPC * GetEntity() { return this; }
+
+ bool IsUsingAggressiveBehavior() { return m_bUseAggressiveBehavior; }
+
+ //---------------------------------
+ // Cannon
+ //---------------------------------
+ Vector CannonPosition();
+ CBaseEntity * GetCannonTarget();
+ bool HasCannonTarget() const;
+ bool IsCannonTarget( CBaseEntity *pTarget ) const;
+ bool AimCannonAt( CBaseEntity *pEntity, float flInterval );
+ void FireCannon();
+ void CannonHitThink();
+
+ //---------------------------------
+ // Collision handling
+ //---------------------------------
+
+ void VPhysicsShadowCollision( int index, gamevcollisionevent_t *pEvent );
+ bool TestCollision( const Ray_t &ray, unsigned int mask, trace_t& trace );
+
+ // Conservative collision volumes
+ static float gm_strideLength;
+
+#ifdef HL2_EPISODIC
+ void StriderBusterAttached( CBaseEntity *pAttached );
+ void StriderBusterDetached( CBaseEntity *pAttached );
+#endif // HL2_EPISODIC
+
+public:
+
+ //---------------------------------
+ // Misc
+ //---------------------------------
+ bool CarriedByDropship();
+ void CarriedThink();
+
+ //---------------------------------
+ // Foot handling
+ //---------------------------------
+ Vector LeftFootHit( float eventtime );
+ Vector RightFootHit( float eventtime );
+ Vector BackFootHit( float eventtime );
+ void StompHit( int followerBoneIndex );
+
+ void FootFX( const Vector &origin );
+ Vector CalculateStompHitPosition( CBaseEntity *pEnemy );
+ bool IsLegBoneFollower( CBoneFollower *pFollower );
+ CBoneFollower *GetBoneFollowerByIndex( int nIndex );
+ int GetBoneFollowerIndex( CBoneFollower *pFollower );
+
+protected:
+ // Because the strider is a leaf class, we can use
+ // static variables to store this information, and save some memory.
+ // Should the strider end up having inheritors, their activate may
+ // stomp these numbers, in which case you should make these ordinary members
+ // again.
+ //
+ // The strider also caches some pose parameters in SetupGlobalModelData().
+ static int m_poseMiniGunYaw, m_poseMiniGunPitch;
+ static bool m_sbStaticPoseParamsLoaded;
+ virtual void PopulatePoseParameters( void );
+
+private:
+
+ bool ShouldExplodeFromDamage( const CTakeDamageInfo &info );
+ bool m_bExploding;
+
+ //-----------------------------------------------------
+ // Conditions, Schedules, Tasks
+ //-----------------------------------------------------
+ enum
+ {
+ SCHED_STRIDER_RANGE_ATTACK1 = BaseClass::NEXT_SCHEDULE,
+ SCHED_STRIDER_RANGE_ATTACK2, // Immolator
+ SCHED_STRIDER_CROUCH,
+ SCHED_STRIDER_STAND,
+ SCHED_STRIDER_DODGE,
+ SCHED_STRIDER_STOMPL,
+ SCHED_STRIDER_STOMPR,
+ SCHED_STRIDER_FLICKL,
+ SCHED_STRIDER_FLICKR,
+ SCHED_STRIDER_HUNT,
+ SCHED_STRIDER_DIE,
+ SCHED_STRIDER_ATTACK_CANNON_TARGET,
+ SCHED_STRIDER_CHASE_ENEMY,
+ SCHED_STRIDER_COMBAT_FACE,
+ SCHED_STRIDER_AGGRESSIVE_COMBAT_STAND,
+ SCHED_STRIDER_ESTABLISH_LINE_OF_FIRE_CANNON,
+ SCHED_STRIDER_FALL_TO_GROUND,
+
+ TASK_STRIDER_AIM = BaseClass::NEXT_TASK,
+ TASK_STRIDER_DODGE,
+ TASK_STRIDER_STOMP,
+ TASK_STRIDER_BREAKDOWN,
+ TASK_STRIDER_START_MOVING,
+ TASK_STRIDER_REFRESH_HUNT_PATH,
+ TASK_STRIDER_GET_PATH_TO_CANNON_TARGET,
+ TASK_STRIDER_FACE_CANNON_TARGET,
+ TASK_STRIDER_SET_HEIGHT,
+ TASK_STRIDER_GET_PATH_TO_CANNON_LOS,
+ TASK_STRIDER_SET_CANNON_HEIGHT,
+ TASK_STRIDER_FIRE_CANNON,
+ TASK_STRIDER_FALL_TO_GROUND,
+
+ COND_STRIDER_DO_FLICK = BaseClass::NEXT_CONDITION,
+ COND_TRACK_PATH_GO,
+ COND_STRIDER_SHOULD_CROUCH,
+ COND_STRIDER_SHOULD_STAND,
+ COND_STRIDER_MINIGUN_SHOOTING,
+ COND_STRIDER_MINIGUN_NOT_SHOOTING,
+ COND_STRIDER_HAS_CANNON_TARGET,
+ COND_STRIDER_ENEMY_UPDATED,
+ COND_STRIDER_HAS_LOS_Z,
+ };
+
+ string_t m_iszStriderBusterName;
+ string_t m_iszMagnadeClassname;
+ string_t m_iszHunterClassname;
+
+ CStriderMinigun *m_pMinigun;
+ int m_miniGunAmmo;
+ int m_miniGunDirectAmmo;
+ float m_nextShootTime;
+ float m_nextStompTime;
+ float m_ragdollTime;
+ float m_miniGunShootDuration;
+ float m_aimYaw;
+ float m_aimPitch;
+ Vector m_blastHit;
+ Vector m_blastNormal;
+ CNetworkVector( m_vecHitPos );
+ CNetworkArray( Vector, m_vecIKTarget, NUM_STRIDER_IK_TARGETS );
+
+ CRandSimTimer m_PostureAnimationTimer;
+
+ EHANDLE m_hRagdoll;
+
+ EHANDLE m_hCannonTarget;
+ CSimpleSimTimer m_AttemptCannonLOSTimer;
+
+ float m_flSpeedScale;
+ float m_flTargetSpeedScale;
+
+ CSimpleSimTimer m_LowZCorrectionTimer;
+
+ // Contained Bone Follower manager
+ CBoneFollowerManager m_BoneFollowerManager;
+
+ int m_BodyTargetBone;
+
+ bool m_bDisableBoneFollowers;
+
+ int m_iVisibleEnemies;
+ float m_flTargetAcquiredTime;
+ bool m_bCrouchLocked; // Designer made the strider crouch. Don't let the AI stand him up.
+ bool m_bNoCrouchWalk;
+ bool m_bDontCrouch;
+ bool m_bNoMoveToLOS;
+ bool m_bFastCrouch;
+ bool m_bMinigunEnabled; // If false, minigun disabled by level designer until further notice.
+
+ float m_idealHeight;
+ float m_HeightVelocity;
+
+ // FIXME: move to a base class to handle turning for blended movement derived characters
+ float m_prevYaw;
+ float m_doTurn;
+ float m_doLeft;
+ float m_doRight;
+ float m_flNextTurnAct;
+
+ string_t m_strTrackName;
+
+ EHANDLE m_hFocus;
+
+ float m_flTimeLastAlertSound;
+ float m_flTimeNextHuntSound;
+ bool m_bUseAggressiveBehavior;
+ float m_flTimePlayerMissileDetected;
+ EHANDLE m_hPlayersMissile;
+ bool m_bMinigunUseDirectFire;
+
+ CHandle<SmokeTrail> m_hSmoke;
+
+ CSimpleSimTimer m_EnemyUpdatedTimer;
+
+ CAI_FreePass m_PlayerFreePass;
+
+#ifdef HL2_EPISODIC
+ CUtlVector< EHANDLE > m_hAttachedBusters; // List of busters attached to us
+#endif // HL2_EPISODIC
+
+ static float gm_zCannonDist;
+ static float gm_zMinigunDist;
+ static Vector gm_vLocalRelativePositionCannon;
+ static Vector gm_vLocalRelativePositionMinigun;
+
+ static int gm_YawControl;
+ static int gm_PitchControl;
+ static int gm_CannonAttachment;
+ static int gm_BodyHeightPoseParam;
+
+ DEFINE_CUSTOM_AI;
+
+ DECLARE_DATADESC();
+};
+
+//-----------------------------------------------------------------------------
+//---------------------------------------------------------
+
+enum StriderMinigunPeg_t
+{
+ MINIGUN_PEGGED_DONT_CARE = 0,
+ MINIGUN_PEGGED_UP,
+ MINIGUN_PEGGED_DOWN,
+ MINIGUN_PEGGED_LEFT,
+ MINIGUN_PEGGED_RIGHT,
+};
+
+//---------------------------------------------------------
+
+struct StriderMinigunViewcone_t
+{
+ Vector origin;
+ Vector axis;
+ float cosAngle;
+ float length;
+};
+
+//---------------------------------------------------------
+
+struct StriderMinigunAnimController_t
+{
+ float current;
+ float target;
+ float rate;
+
+ void Update( float dt, bool approach = true )
+ {
+ if( approach )
+ {
+ current = Approach( target, current, rate * dt );
+ }
+ else
+ {
+ current = target;
+ }
+ }
+
+ void Random( float minTarget, float maxTarget, float minRate, float maxRate )
+ {
+ target = random->RandomFloat( minTarget, maxTarget );
+ rate = random->RandomFloat( minRate, maxRate );
+ }
+};
+
+//---------------------------------------------------------
+
+class CStriderMinigun
+{
+public:
+ DECLARE_DATADESC();
+
+ void Init();
+ void SetTarget( IStriderMinigunHost *pHost, CBaseEntity *pTarget, bool bOverrideEnemy = false );
+ CBaseEntity *GetTarget() { return m_hTarget.Get(); }
+ void Think( IStriderMinigunHost *pHost, float dt );
+ void SetState( int newState );
+ bool ShouldFindTarget( IMinigunHost *pHost );
+ void AimAtPoint( IStriderMinigunHost *pHost, const Vector &vecPoint, bool bSnap = false );
+ void AimAtTarget( IStriderMinigunHost *pHost, CBaseEntity *pTarget, bool bSnap = false );
+ void ShootAtTarget( IStriderMinigunHost *pHost, CBaseEntity *pTarget, float shootTime );
+ void StartShooting( IStriderMinigunHost *pHost, CBaseEntity *pTarget, float duration );
+ void ExtendShooting( float timeExtend );
+ void SetShootDuration( float duration );
+ void StopShootingForSeconds( IStriderMinigunHost *pHost, CBaseEntity *pTarget, float duration );
+ bool IsPegged( int dir = MINIGUN_PEGGED_DONT_CARE );
+ bool CanStartShooting( IStriderMinigunHost *pHost, CBaseEntity *pTargetEnt );
+ float GetBurstTimeRemaining() { return m_burstTime - gpGlobals->curtime; }
+
+ void RecordShotOnTarget() { m_iOnTargetShots++; }
+ void ClearOnTarget() { m_iOnTargetShots = 0; }
+ bool IsOnTarget( int numShots = 0 ) { return ( numShots == 0 ) ? (m_iOnTargetShots > 0) : (m_iOnTargetShots >= numShots); }
+
+ void Enable( IMinigunHost *pHost, bool enable );
+ float GetAimError();
+
+ enum minigunstates_t
+ {
+ MINIGUN_OFF = 0,
+ MINIGUN_SHOOTING = 1,
+ };
+
+ int GetState() { return m_minigunState; }
+ bool IsShooting() { return GetState() == MINIGUN_SHOOTING; }
+
+private:
+ bool m_enable;
+ int m_minigunState;
+ float m_nextBulletTime; // Minigun is shooting, when can I fire my next bullet?
+ float m_burstTime; // If firing, how long till done? If not, how long till I can?
+ float m_nextTwitchTime;
+ int m_randomState;
+ EHANDLE m_hTarget;
+ StriderMinigunAnimController_t m_yaw;
+ StriderMinigunAnimController_t m_pitch;
+ bool m_bWarnedAI;
+ float m_shootDuration;
+ Vector m_vecAnchor; // A burst starts here and goes to the target's orgin.
+ bool m_bOverrideEnemy; // The minigun wants something other than the Strider's enemy as a target right now.
+ Vector m_vecLastTargetPos; // Last place minigun saw the target.
+ int m_iOnTargetShots;
+};
+
+
+class CSparkTrail : public CPointEntity
+{
+ DECLARE_CLASS( CSparkTrail, CPointEntity );
+ void Spawn( void );
+ void SparkThink( void );
+
+ virtual void Precache();
+
+ DECLARE_DATADESC();
+};
+
+#include "tier0/memdbgoff.h"
+
+#endif // NPC_STRIDER_H
+
+//=============================================================================