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.
470 lines
15 KiB
470 lines
15 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
//=============================================================================// |
|
|
|
#ifndef NPC_METROPOLICE_H |
|
#define NPC_METROPOLICE_H |
|
#ifdef _WIN32 |
|
#pragma once |
|
#endif |
|
|
|
#include "rope.h" |
|
#include "rope_shared.h" |
|
#include "ai_baseactor.h" |
|
#include "ai_basenpc.h" |
|
#include "ai_goal_police.h" |
|
#include "ai_behavior.h" |
|
#include "ai_behavior_standoff.h" |
|
#include "ai_behavior_assault.h" |
|
#include "ai_behavior_functank.h" |
|
#include "ai_behavior_actbusy.h" |
|
#include "ai_behavior_rappel.h" |
|
#include "ai_behavior_police.h" |
|
#include "ai_behavior_follow.h" |
|
#include "ai_sentence.h" |
|
#include "props.h" |
|
|
|
class CNPC_MetroPolice; |
|
|
|
class CNPC_MetroPolice : public CAI_BaseActor |
|
{ |
|
DECLARE_CLASS( CNPC_MetroPolice, CAI_BaseActor ); |
|
DECLARE_DATADESC(); |
|
|
|
public: |
|
CNPC_MetroPolice() = default; |
|
|
|
virtual bool CreateComponents(); |
|
bool CreateBehaviors(); |
|
void Spawn( void ); |
|
void Precache( void ); |
|
|
|
Class_T Classify( void ); |
|
Disposition_t IRelationType(CBaseEntity *pTarget); |
|
float MaxYawSpeed( void ); |
|
void HandleAnimEvent( animevent_t *pEvent ); |
|
Activity NPC_TranslateActivity( Activity newActivity ); |
|
|
|
Vector EyeDirection3D( void ) { return CAI_BaseHumanoid::EyeDirection3D(); } // cops don't have eyes |
|
|
|
virtual void Event_Killed( const CTakeDamageInfo &info ); |
|
|
|
virtual void OnScheduleChange(); |
|
|
|
float GetIdealAccel( void ) const; |
|
int ObjectCaps( void ) { return UsableNPCObjectCaps(BaseClass::ObjectCaps()); } |
|
void PrecriminalUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); |
|
|
|
// These are overridden so that the cop can shove and move a non-criminal player safely |
|
CBaseEntity *CheckTraceHullAttack( float flDist, const Vector &mins, const Vector &maxs, int iDamage, int iDmgType, float forceScale, bool bDamageAnyNPC ); |
|
CBaseEntity *CheckTraceHullAttack( const Vector &vStart, const Vector &vEnd, const Vector &mins, const Vector &maxs, int iDamage, int iDmgType, float flForceScale, bool bDamageAnyNPC ); |
|
|
|
virtual int SelectSchedule( void ); |
|
virtual int SelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode ); |
|
virtual int TranslateSchedule( int scheduleType ); |
|
void StartTask( const Task_t *pTask ); |
|
void RunTask( const Task_t *pTask ); |
|
virtual Vector GetActualShootTrajectory( const Vector &shootOrigin ); |
|
virtual void FireBullets( const FireBulletsInfo_t &info ); |
|
virtual bool HandleInteraction(int interactionType, void *data, CBaseCombatCharacter* sourceEnt); |
|
virtual void Weapon_Equip( CBaseCombatWeapon *pWeapon ); |
|
|
|
//virtual bool OverrideMoveFacing( const AILocalMoveGoal_t &move, float flInterval ); |
|
bool OnObstructionPreSteer( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult ); |
|
bool ShouldBruteForceFailedNav() { return false; } |
|
|
|
virtual void GatherConditions( void ); |
|
|
|
virtual bool OverrideMoveFacing( const AILocalMoveGoal_t &move, float flInterval ); |
|
|
|
// Can't move and shoot when the enemy is an airboat |
|
virtual bool ShouldMoveAndShoot(); |
|
|
|
// TraceAttack |
|
virtual void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr, CDmgAccumulator *pAccumulator ); |
|
|
|
// Speaking |
|
virtual void SpeakSentence( int nSentenceType ); |
|
|
|
// Set up the shot regulator based on the equipped weapon |
|
virtual void OnUpdateShotRegulator( ); |
|
|
|
bool ShouldKnockOutTarget( CBaseEntity *pTarget ); |
|
void KnockOutTarget( CBaseEntity *pTarget ); |
|
void StunnedTarget( CBaseEntity *pTarget ); |
|
void AdministerJustice( void ); |
|
|
|
bool QueryHearSound( CSound *pSound ); |
|
|
|
void SetBatonState( bool state ); |
|
bool BatonActive( void ); |
|
|
|
CAI_Sentence< CNPC_MetroPolice > *GetSentences() { return &m_Sentences; } |
|
|
|
virtual bool AllowedToIgnite( void ) { return true; } |
|
|
|
void PlayFlinchGesture( void ); |
|
|
|
protected: |
|
// Determines the best type of flinch anim to play. |
|
virtual Activity GetFlinchActivity( bool bHeavyDamage, bool bGesture ); |
|
|
|
// Only move and shoot when attacking |
|
virtual bool OnBeginMoveAndShoot(); |
|
virtual void OnEndMoveAndShoot(); |
|
|
|
private: |
|
bool PlayerIsCriminal( void ); |
|
void ReleaseManhack( void ); |
|
|
|
// Speech-related methods |
|
void AnnounceTakeCoverFromDanger( CSound *pSound ); |
|
void AnnounceEnemyType( CBaseEntity *pEnemy ); |
|
void AnnounceEnemyKill( CBaseEntity *pEnemy ); |
|
void AnnounceHarrassment( ); |
|
void AnnounceOutOfAmmo( ); |
|
|
|
// Behavior-related sentences |
|
void SpeakFuncTankSentence( int nSentenceType ); |
|
void SpeakAssaultSentence( int nSentenceType ); |
|
void SpeakStandoffSentence( int nSentenceType ); |
|
|
|
virtual void LostEnemySound( void ); |
|
virtual void FoundEnemySound( void ); |
|
virtual void AlertSound( void ); |
|
virtual void PainSound( const CTakeDamageInfo &info ); |
|
virtual void DeathSound( const CTakeDamageInfo &info ); |
|
virtual void IdleSound( void ); |
|
virtual bool ShouldPlayIdleSound( void ); |
|
|
|
// Burst mode! |
|
void SetBurstMode( bool bEnable ); |
|
|
|
int OnTakeDamage_Alive( const CTakeDamageInfo &info ); |
|
|
|
int GetSoundInterests( void ); |
|
|
|
void BuildScheduleTestBits( void ); |
|
|
|
bool CanDeployManhack( void ); |
|
|
|
bool ShouldHitPlayer( const Vector &targetDir, float targetDist ); |
|
|
|
void PrescheduleThink( void ); |
|
|
|
void SetPlayerCriminalDuration( float time ); |
|
|
|
void IncrementPlayerCriminalStatus( void ); |
|
|
|
virtual bool UseAttackSquadSlots() { return true; } |
|
|
|
WeaponProficiency_t CalcWeaponProficiency( CBaseCombatWeapon *pWeapon ); |
|
|
|
// Inputs |
|
void InputEnableManhackToss( inputdata_t &inputdata ); |
|
void InputSetPoliceGoal( inputdata_t &inputdata ); |
|
void InputActivateBaton( inputdata_t &inputdata ); |
|
|
|
void NotifyDeadFriend ( CBaseEntity* pFriend ); |
|
|
|
// Stitch aiming! |
|
void AimBurstRandomly( int nMinCount, int nMaxCount, float flMinDelay, float flMaxDelay ); |
|
void AimBurstAtEnemy( float flReactionTime ); |
|
void AimBurstInFrontOfEnemy( float flReactionTime ); |
|
void AimBurstAlongSideOfEnemy( float flFollowTime ); |
|
void AimBurstBehindEnemy( float flFollowTime ); |
|
void AimBurstTightGrouping( float flShotTime ); |
|
|
|
// Anim event handlers |
|
void OnAnimEventDeployManhack( animevent_t *pEvent ); |
|
void OnAnimEventShove( void ); |
|
void OnAnimEventBatonOn( void ); |
|
void OnAnimEventBatonOff( void ); |
|
void OnAnimEventStartDeployManhack( void ); |
|
void OnAnimEventPreDeployManhack( void ); |
|
|
|
bool HasBaton( void ); |
|
|
|
// Normal schedule selection |
|
int SelectCombatSchedule(); |
|
int SelectScheduleNewEnemy(); |
|
int SelectScheduleArrestEnemy(); |
|
int SelectRangeAttackSchedule(); |
|
int SelectScheduleNoDirectEnemy(); |
|
int SelectScheduleInvestigateSound(); |
|
int SelectShoveSchedule( void ); |
|
|
|
bool TryToEnterPistolSlot( int nSquadSlot ); |
|
|
|
// Airboat schedule selection |
|
int SelectAirboatCombatSchedule(); |
|
int SelectAirboatRangeAttackSchedule(); |
|
|
|
// Handle flinching |
|
bool IsHeavyDamage( const CTakeDamageInfo &info ); |
|
|
|
// Is my enemy currently in an airboat? |
|
bool IsEnemyInAnAirboat() const; |
|
|
|
// Returns the airboat |
|
CBaseEntity *GetEnemyAirboat() const; |
|
|
|
// Compute a predicted enemy position n seconds into the future |
|
void PredictShootTargetPosition( float flDeltaTime, float flMinLeadDist, float flAddVelocity, Vector *pVecTarget, Vector *pVecTargetVel ); |
|
|
|
// Compute a predicted velocity n seconds into the future (given a known acceleration rate) |
|
void PredictShootTargetVelocity( float flDeltaTime, Vector *pVecTargetVel ); |
|
|
|
// How many shots will I fire in a particular amount of time? |
|
int CountShotsInTime( float flDeltaTime ) const; |
|
float GetTimeForShots( int nShotCount ) const; |
|
|
|
// Visualize stitch |
|
void VisualizeStitch( const Vector &vecStart, const Vector &vecEnd ); |
|
|
|
// Visualize line of death |
|
void VisualizeLineOfDeath( ); |
|
|
|
// Modify the stitch length |
|
float ComputeDistanceStitchModifier( float flDistanceToTarget ) const; |
|
|
|
// Adjusts the burst toward the target as it's being fired. |
|
void SteerBurstTowardTarget( ); |
|
|
|
// Methods to compute shot trajectory based on burst mode |
|
Vector ComputeBurstLockOnTrajectory( const Vector &shootOrigin ); |
|
Vector ComputeBurstDeliberatelyMissTrajectory( const Vector &shootOrigin ); |
|
Vector ComputeBurstTrajectory( const Vector &shootOrigin ); |
|
Vector ComputeTightBurstTrajectory( const Vector &shootOrigin ); |
|
|
|
// Are we currently firing a burst? |
|
bool IsCurrentlyFiringBurst() const; |
|
|
|
// Which entity are we actually trying to shoot at? |
|
CBaseEntity *GetShootTarget(); |
|
|
|
// Different burst steering modes |
|
void SteerBurstTowardTargetUseSpeedOnly( const Vector &vecShootAt, const Vector &vecShootAtVelocity, float flPredictTime, int nShotsTillPredict ); |
|
void SteerBurstTowardTargetUseVelocity( const Vector &vecShootAt, const Vector &vecShootAtVelocity, int nShotsTillPredict ); |
|
void SteerBurstTowardTargetUsePosition( const Vector &vecShootAt, const Vector &vecShootAtVelocity, int nShotsTillPredict ); |
|
void SteerBurstTowardPredictedPoint( const Vector &vecShootAt, const Vector &vecShootAtVelocity, int nShotsTillPredict ); |
|
void SteerBurstWithinLineOfDeath( ); |
|
|
|
// Set up the shot regulator |
|
int SetupBurstShotRegulator( float flReactionTime ); |
|
|
|
// Choose a random vector somewhere between the two specified vectors |
|
void RandomDirectionBetweenVectors( const Vector &vecStart, const Vector &vecEnd, Vector *pResult ); |
|
|
|
// Stitch selector |
|
float StitchAtWeight( float flDist, float flSpeed, float flDot, float flReactionTime, const Vector &vecTargetToGun ); |
|
float StitchAcrossWeight( float flDist, float flSpeed, float flDot, float flReactionTime ); |
|
float StitchAlongSideWeight( float flDist, float flSpeed, float flDot ); |
|
float StitchBehindWeight( float flDist, float flSpeed, float flDot ); |
|
float StitchTightWeight( float flDist, float flSpeed, const Vector &vecTargetToGun, const Vector &vecVelocity ); |
|
int SelectStitchSchedule(); |
|
|
|
// Can me enemy see me? |
|
bool CanEnemySeeMe( ); |
|
|
|
// Combat schedule selection |
|
int SelectMoveToLedgeSchedule(); |
|
|
|
// position to shoot at |
|
Vector StitchAimTarget( const Vector &posSrc, bool bNoisy ); |
|
|
|
// Should we attempt to stitch? |
|
bool ShouldAttemptToStitch(); |
|
|
|
// Deliberately aims as close as possible w/o hitting |
|
Vector AimCloseToTargetButMiss( CBaseEntity *pTarget, const Vector &shootOrigin ); |
|
|
|
// Compute the actual reaction time based on distance + speed modifiers |
|
float AimBurstAtReactionTime( float flReactonTime, float flDistToTargetSqr, float flCurrentSpeed ); |
|
int AimBurstAtSetupHitCount( float flDistToTargetSqr, float flCurrentSpeed ); |
|
|
|
// How many squad members are trying to arrest the player? |
|
int SquadArrestCount(); |
|
|
|
// He's resisting arrest! |
|
void EnemyResistingArrest(); |
|
void VPhysicsCollision( int index, gamevcollisionevent_t *pEvent ); |
|
|
|
// Rappel |
|
virtual bool IsWaitingToRappel( void ) { return m_RappelBehavior.IsWaitingToRappel(); } |
|
void BeginRappel() { m_RappelBehavior.BeginRappel(); } |
|
|
|
private: |
|
enum |
|
{ |
|
BURST_NOT_ACTIVE = 0, |
|
BURST_ACTIVE, |
|
BURST_LOCK_ON_AFTER_HIT, |
|
BURST_LOCKED_ON, |
|
BURST_DELIBERATELY_MISS, |
|
BURST_TIGHT_GROUPING, |
|
}; |
|
|
|
enum |
|
{ |
|
BURST_STEER_NONE = 0, |
|
BURST_STEER_TOWARD_PREDICTED_POINT, |
|
BURST_STEER_WITHIN_LINE_OF_DEATH, |
|
BURST_STEER_ADJUST_FOR_SPEED_CHANGES, |
|
BURST_STEER_EXACTLY_TOWARD_TARGET, |
|
}; |
|
|
|
enum |
|
{ |
|
COND_METROPOLICE_ON_FIRE = BaseClass::NEXT_CONDITION, |
|
COND_METROPOLICE_ENEMY_RESISTING_ARREST, |
|
COND_METROPOLICE_PLAYER_TOO_CLOSE, |
|
COND_METROPOLICE_CHANGE_BATON_STATE, |
|
COND_METROPOLICE_PHYSOBJECT_ASSAULT, |
|
|
|
}; |
|
|
|
enum |
|
{ |
|
SCHED_METROPOLICE_WALK = BaseClass::NEXT_SCHEDULE, |
|
SCHED_METROPOLICE_WAKE_ANGRY, |
|
SCHED_METROPOLICE_HARASS, |
|
SCHED_METROPOLICE_CHASE_ENEMY, |
|
SCHED_METROPOLICE_ESTABLISH_LINE_OF_FIRE, |
|
SCHED_METROPOLICE_DRAW_PISTOL, |
|
SCHED_METROPOLICE_DEPLOY_MANHACK, |
|
SCHED_METROPOLICE_ADVANCE, |
|
SCHED_METROPOLICE_CHARGE, |
|
SCHED_METROPOLICE_BURNING_RUN, |
|
SCHED_METROPOLICE_BURNING_STAND, |
|
SCHED_METROPOLICE_SMG_NORMAL_ATTACK, |
|
SCHED_METROPOLICE_SMG_BURST_ATTACK, |
|
SCHED_METROPOLICE_AIM_STITCH_AT_AIRBOAT, |
|
SCHED_METROPOLICE_AIM_STITCH_IN_FRONT_OF_AIRBOAT, |
|
SCHED_METROPOLICE_AIM_STITCH_TIGHTLY, |
|
SCHED_METROPOLICE_AIM_STITCH_ALONG_SIDE_OF_AIRBOAT, |
|
SCHED_METROPOLICE_AIM_STITCH_BEHIND_AIRBOAT, |
|
SCHED_METROPOLICE_ESTABLISH_STITCH_LINE_OF_FIRE, |
|
SCHED_METROPOLICE_INVESTIGATE_SOUND, |
|
SCHED_METROPOLICE_WARN_AND_ARREST_ENEMY, |
|
SCHED_METROPOLICE_ARREST_ENEMY, |
|
SCHED_METROPOLICE_ENEMY_RESISTING_ARREST, |
|
SCHED_METROPOLICE_WARN_TARGET, |
|
SCHED_METROPOLICE_HARASS_TARGET, |
|
SCHED_METROPOLICE_SUPPRESS_TARGET, |
|
SCHED_METROPOLICE_RETURN_FROM_HARASS, |
|
SCHED_METROPOLICE_SHOVE, |
|
SCHED_METROPOLICE_ACTIVATE_BATON, |
|
SCHED_METROPOLICE_DEACTIVATE_BATON, |
|
SCHED_METROPOLICE_ALERT_FACE_BESTSOUND, |
|
SCHED_METROPOLICE_RETURN_TO_PRECHASE, |
|
SCHED_METROPOLICE_SMASH_PROP, |
|
}; |
|
|
|
enum |
|
{ |
|
TASK_METROPOLICE_HARASS = BaseClass::NEXT_TASK, |
|
TASK_METROPOLICE_DIE_INSTANTLY, |
|
TASK_METROPOLICE_BURST_ATTACK, |
|
TASK_METROPOLICE_STOP_FIRE_BURST, |
|
TASK_METROPOLICE_AIM_STITCH_AT_PLAYER, |
|
TASK_METROPOLICE_AIM_STITCH_AT_AIRBOAT, |
|
TASK_METROPOLICE_AIM_STITCH_TIGHTLY, |
|
TASK_METROPOLICE_AIM_STITCH_IN_FRONT_OF_AIRBOAT, |
|
TASK_METROPOLICE_AIM_STITCH_ALONG_SIDE_OF_AIRBOAT, |
|
TASK_METROPOLICE_AIM_STITCH_BEHIND_AIRBOAT, |
|
TASK_METROPOLICE_RELOAD_FOR_BURST, |
|
TASK_METROPOLICE_GET_PATH_TO_STITCH, |
|
TASK_METROPOLICE_RESET_LEDGE_CHECK_TIME, |
|
TASK_METROPOLICE_GET_PATH_TO_BESTSOUND_LOS, |
|
TASK_METROPOLICE_AIM_WEAPON_AT_ENEMY, |
|
TASK_METROPOLICE_ARREST_ENEMY, |
|
TASK_METROPOLICE_LEAD_ARREST_ENEMY, |
|
TASK_METROPOLICE_SIGNAL_FIRING_TIME, |
|
TASK_METROPOLICE_ACTIVATE_BATON, |
|
TASK_METROPOLICE_WAIT_FOR_SENTENCE, |
|
TASK_METROPOLICE_GET_PATH_TO_PRECHASE, |
|
TASK_METROPOLICE_CLEAR_PRECHASE, |
|
}; |
|
|
|
private: |
|
|
|
int m_iPistolClips; // How many clips the cop has in reserve |
|
int m_iManhacks; // How many manhacks the cop has |
|
bool m_fWeaponDrawn; // Is my weapon drawn? (ready to use) |
|
bool m_bSimpleCops; // The easy version of the cops |
|
int m_LastShootSlot; |
|
CRandSimTimer m_TimeYieldShootSlot; |
|
CSimpleSimTimer m_BatonSwingTimer; |
|
CSimpleSimTimer m_NextChargeTimer; |
|
|
|
// All related to burst firing |
|
Vector m_vecBurstTargetPos; |
|
Vector m_vecBurstDelta; |
|
int m_nBurstHits; |
|
int m_nMaxBurstHits; |
|
int m_nBurstReloadCount; |
|
Vector m_vecBurstLineOfDeathDelta; |
|
Vector m_vecBurstLineOfDeathOrigin; |
|
int m_nBurstMode; |
|
int m_nBurstSteerMode; |
|
float m_flBurstSteerDistance; |
|
float m_flBurstPredictTime; |
|
Vector m_vecBurstPredictedVelocityDir; |
|
float m_vecBurstPredictedSpeed; |
|
float m_flValidStitchTime; |
|
float m_flNextLedgeCheckTime; |
|
float m_flTaskCompletionTime; |
|
|
|
bool m_bShouldActivateBaton; |
|
float m_flBatonDebounceTime; // Minimum amount of time before turning the baton off |
|
float m_flLastPhysicsFlinchTime; |
|
float m_flLastDamageFlinchTime; |
|
|
|
// Sentences |
|
float m_flNextPainSoundTime; |
|
float m_flNextLostSoundTime; |
|
int m_nIdleChatterType; |
|
bool m_bPlayerIsNear; |
|
|
|
// Policing state |
|
bool m_bPlayerTooClose; |
|
bool m_bKeepFacingPlayer; |
|
float m_flChasePlayerTime; |
|
Vector m_vecPreChaseOrigin; |
|
float m_flPreChaseYaw; |
|
int m_nNumWarnings; |
|
int m_iNumPlayerHits; |
|
|
|
// Outputs |
|
COutputEvent m_OnStunnedPlayer; |
|
COutputEvent m_OnCupCopped; |
|
|
|
AIHANDLE m_hManhack; |
|
CHandle<CPhysicsProp> m_hBlockingProp; |
|
|
|
CAI_ActBusyBehavior m_ActBusyBehavior; |
|
CAI_StandoffBehavior m_StandoffBehavior; |
|
CAI_AssaultBehavior m_AssaultBehavior; |
|
CAI_FuncTankBehavior m_FuncTankBehavior; |
|
CAI_RappelBehavior m_RappelBehavior; |
|
CAI_PolicingBehavior m_PolicingBehavior; |
|
CAI_FollowBehavior m_FollowBehavior; |
|
|
|
CAI_Sentence< CNPC_MetroPolice > m_Sentences; |
|
|
|
int m_nRecentDamage; |
|
float m_flRecentDamageTime; |
|
|
|
// The last hit direction, measured as a yaw relative to our orientation |
|
float m_flLastHitYaw; |
|
|
|
static float gm_flTimeLastSpokePeek; |
|
|
|
public: |
|
DEFINE_CUSTOM_AI; |
|
}; |
|
|
|
#endif // NPC_METROPOLICE_H
|
|
|