diff options
Diffstat (limited to 'game/server/hl2/npc_metropolice.h')
| -rw-r--r-- | game/server/hl2/npc_metropolice.h | 470 |
1 files changed, 470 insertions, 0 deletions
diff --git a/game/server/hl2/npc_metropolice.h b/game/server/hl2/npc_metropolice.h new file mode 100644 index 0000000..544fc68 --- /dev/null +++ b/game/server/hl2/npc_metropolice.h @@ -0,0 +1,470 @@ +//========= 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(); + + 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 |