You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
646 lines
21 KiB
646 lines
21 KiB
![]()
4 years ago
|
//========= 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
|
||
|
|
||
|
//=============================================================================
|