aboutsummaryrefslogtreecommitdiff
path: root/sp/src/game/server/hl2/npc_strider.h
diff options
context:
space:
mode:
authorJoe Ludwig <[email protected]>2013-06-26 15:22:04 -0700
committerJoe Ludwig <[email protected]>2013-06-26 15:22:04 -0700
commit39ed87570bdb2f86969d4be821c94b722dc71179 (patch)
treeabc53757f75f40c80278e87650ea92808274aa59 /sp/src/game/server/hl2/npc_strider.h
downloadsource-sdk-2013-39ed87570bdb2f86969d4be821c94b722dc71179.tar.xz
source-sdk-2013-39ed87570bdb2f86969d4be821c94b722dc71179.zip
First version of the SOurce SDK 2013
Diffstat (limited to 'sp/src/game/server/hl2/npc_strider.h')
-rw-r--r--sp/src/game/server/hl2/npc_strider.h645
1 files changed, 645 insertions, 0 deletions
diff --git a/sp/src/game/server/hl2/npc_strider.h b/sp/src/game/server/hl2/npc_strider.h
new file mode 100644
index 00000000..8673d339
--- /dev/null
+++ b/sp/src/game/server/hl2/npc_strider.h
@@ -0,0 +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
+
+//=============================================================================