diff options
Diffstat (limited to 'game/server/hl2/npc_alyx_episodic.h')
| -rw-r--r-- | game/server/hl2/npc_alyx_episodic.h | 289 |
1 files changed, 289 insertions, 0 deletions
diff --git a/game/server/hl2/npc_alyx_episodic.h b/game/server/hl2/npc_alyx_episodic.h new file mode 100644 index 0000000..5657dae --- /dev/null +++ b/game/server/hl2/npc_alyx_episodic.h @@ -0,0 +1,289 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Base combat character with no AI +// +//=====================================================================================// + +#include "ai_baseactor.h" +#include "npc_playercompanion.h" +#include "ai_behavior_holster.h" +#include "ai_behavior_functank.h" +#include "soundenvelope.h" + +extern ConVar npc_alyx_readiness; + +class CNPC_Alyx : public CNPC_PlayerCompanion +{ +public: + DECLARE_CLASS( CNPC_Alyx, CNPC_PlayerCompanion ); + + // fast class list + CNPC_Alyx *m_pNext; + + virtual void ModifyOrAppendCriteria( AI_CriteriaSet &set ); + + bool ForceVehicleInteraction( const char *lpszInteractionName, CBaseCombatCharacter *pOther ); + + CNPC_Alyx( ); + ~CNPC_Alyx( ); + + static CNPC_Alyx *GetAlyx( void ); + + bool CreateBehaviors(); + void Spawn( void ); + void Activate( void ); + void StopLoopingSounds( void ); + void SelectModel(); + void Precache( void ); + void SetupAlyxWithoutParent( void ); + void CreateEmpTool( void ); + void PrescheduleThink( void ); + void GatherConditions(); + bool ShouldPlayerAvoid( void ); + void AnalyzeGunfireSound( CSound *pSound ); + bool IsValidEnemy( CBaseEntity *pEnemy ); + void Event_KilledOther( CBaseEntity *pVictim, const CTakeDamageInfo &info ); + void Event_Killed( const CTakeDamageInfo &info ); + void EnemyIgnited( CAI_BaseNPC *pVictim ); + void CombineBallSocketed( int iNumBounces ); + void AimGun( void ); + Vector GetActualShootPosition( const Vector &shootOrigin ); + float MaxYawSpeed( void ); + void OnUpdateShotRegulator(); + bool IsCrouchedActivity( Activity activity ); + bool OnBeginMoveAndShoot(); + void SpeakAttacking( void ); + + virtual float GetJumpGravity() const { return 1.8f; } + + // Crouching + Vector GetCrouchEyeOffset( void ) { return Vector(0,0,50); } + Vector GetCrouchGunOffset( void ) { return Vector(0,0,40); } + bool EnemyIsValidCrouchTarget( CBaseEntity *pEnemy ); + bool Stand( void ); + bool Crouch( void ); + void DesireCrouch( void ); + + // Custom AI + void DoCustomCombatAI( void ); + void DoMobbedCombatAI( void ); + void DoCustomSpeechAI( void ); + + Disposition_t IRelationType( CBaseEntity *pTarget ); + int IRelationPriority( CBaseEntity *pTarget ); + + CAI_FollowBehavior &GetFollowBehavior( void ); + + Class_T Classify ( void ); + bool FValidateHintType( CAI_Hint *pHint ); + int ObjectCaps(); + void HandleAnimEvent( animevent_t *pEvent ); + bool FInViewCone( CBaseEntity *pEntity ); + bool QuerySeeEntity( CBaseEntity *pEntity, bool bOnlyHateOrFearIfNPC = false ); + bool CanSeeEntityInDarkness( CBaseEntity *pEntity ); + bool IsCoverPosition( const Vector &vecThreat, const Vector &vecPosition ); + Activity NPC_TranslateActivity ( Activity activity ); + bool ShouldDeferToFollowBehavior(); + void BuildScheduleTestBits(); + bool ShouldBehaviorSelectSchedule( CAI_BehaviorBase *pBehavior ); + int SelectSchedule( void ); + int SelectScheduleDanger( void ); + int TranslateSchedule( int scheduleType ); + void StartTask( const Task_t *pTask ); + void RunTask( const Task_t *pTask ); + void OnStateChange( NPC_STATE OldState, NPC_STATE NewState ); + float LengthOfLastCombat( void ) const; + // bool IsNavigationUrgent(); + + void TraceAttack( const CTakeDamageInfo &info, const Vector &vecDir, trace_t *ptr, CDmgAccumulator *pAccumulator ); + bool CanBeHitByMeleeAttack( CBaseEntity *pAttacker ); + int OnTakeDamage_Alive( const CTakeDamageInfo &info ); + bool FCanCheckAttacks(); + float GetAttackDamageScale( CBaseEntity *pVictim ); + + + bool HandleInteraction(int interactionType, void *data, CBaseCombatCharacter* sourceEnt); + virtual bool SpeakIfAllowed( AIConcept_t concept, const char *modifiers = NULL, bool bRespondingToPlayer = false, char *pszOutResponseChosen = NULL, size_t bufsize = 0 ); + + void HolsterPistol(); + void DrawPistol(); + void Weapon_Drop( CBaseCombatWeapon *pWeapon, const Vector *pvecTarget = NULL, const Vector *pVelocity = NULL ); + + void SetEMPHolstered( bool bHolstered ) { m_bIsEMPHolstered = bHolstered; } + bool IsEMPHolstered() { return (!m_hEmpTool || m_hEmpTool->GetParent() != this || m_bIsEMPHolstered); } + + float GetReadinessDecay() { return 60.0f; } + virtual bool IsAllowedToAim(); + + virtual void PainSound( const CTakeDamageInfo &info ); + virtual void DeathSound( const CTakeDamageInfo &info ); + + // Hacking and object interaction + void SearchForInteractTargets(); + bool IsValidInteractTarget( CBaseEntity *pTarget ); + bool CanInteractWithTarget( CBaseEntity *pTarget ); + void SetInteractTarget( CBaseEntity *pTarget ); + bool HasInteractTarget() { return m_hHackTarget != NULL; } + CBaseEntity *GetInteractTarget() { return m_hHackTarget; } + void EmpZapTarget( CBaseEntity *pTarget ); + + virtual void OnSeeEntity( CBaseEntity *pEntity ); + + void InputAllowInteraction( inputdata_t &inputdata ) + { + m_bInteractionAllowed = true; + } + void InputDisallowInteraction( inputdata_t &inputdata ) + { + m_bInteractionAllowed = false; + } + void InputAllowDarknessSpeech( inputdata_t &inputdata ) + { + m_bDarknessSpeechAllowed = inputdata.value.Bool(); + } + void InputGiveEMP( inputdata_t &inputdata ); + void InputVehiclePunted( inputdata_t &inputdata ); + void InputOutsideTransition( inputdata_t &inputdata ); + + virtual void OnGivenWeapon( CBaseCombatWeapon *pNewWeapon ); + virtual void OnChangeActiveWeapon( CBaseCombatWeapon *pOldWeapon, CBaseCombatWeapon *pNewWeapon ); + virtual void Weapon_Equip( CBaseCombatWeapon *pWeapon ); + virtual bool Weapon_CanUse( CBaseCombatWeapon *pWeapon ); + + // Blinding + virtual void PlayerHasIlluminatedNPC( CBasePlayer *pPlayer, float flDot ); + void CheckBlindedByFlare( void ); + bool CanBeBlindedByFlashlight( bool bCheckLightSources ); + bool PlayerFlashlightOnMyEyes( CBasePlayer *pPlayer ); + bool BlindedByFlare( void ); + bool CanReload( void ); + + virtual bool PickTacticalLookTarget( AILookTargetArgs_t *pArgs ); + virtual void OnSelectedLookTarget( AILookTargetArgs_t *pArgs ); + virtual bool IsReadinessCapable( void ); + + virtual void ReadinessLevelChanged( int iPriorLevel ); + + bool IsAllowedToInteract(); + virtual void BarnacleDeathSound( void ); + + virtual const char *GetDeathMessageText( void ) { return "GAMEOVER_ALYXDEAD"; } + + PassengerState_e GetPassengerState( void ); + + void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); + bool PlayerInSpread( const Vector &sourcePos, const Vector &targetPos, float flSpread, float maxDistOffCenter, bool ignoreHatedPlayers ); + +private: + EHANDLE m_hEmpTool; + EHANDLE m_hHackTarget; + CHandle<CAI_Hint> m_hStealthLookTarget; + bool m_bInteractionAllowed; + float m_fTimeNextSearchForInteractTargets; + bool m_bDarknessSpeechAllowed; + bool m_bIsEMPHolstered; + bool m_bIsFlashlightBlind; + float m_fStayBlindUntil; + float m_flDontBlindUntil; + bool m_bSpokeLostPlayerInDarkness; + bool m_bPlayerFlashlightState; + bool m_bHadCondSeeEnemy; + string_t m_iszCurrentBlindScene; + float m_fTimeUntilNextDarknessFoundPlayer; + float m_fCombatStartTime; + float m_fCombatEndTime; + float m_flNextCrouchTime; + + CSoundPatch *m_sndDarknessBreathing; + + // Speech timers + // Theoretically, these shouldn't be needed. Instead, each response + // should prevent the concept being spoken for the desired time. But + // until the responses exists, Alyx will spam the response rules forever, + // so these timers stop that. + CRandStopwatch m_SpeechWatch_LostPlayer; + CSimpleSimTimer m_SpeechTimer_HeardSound; + CRandStopwatch m_SpeechWatch_SoundDelay; + CRandStopwatch m_SpeechWatch_BreathingRamp; + CRandStopwatch m_SpeechWatch_FoundPlayer; + + CAI_MoveMonitor m_MoveMonitor; + + enum WeaponType_t + { + WT_NONE, + WT_ALYXGUN, + WT_SMG1, + WT_SHOTGUN, + WT_AR2, + WT_OTHER, + }; + + int m_WeaponType; + + bool m_bShouldHaveEMP; + + CAI_FuncTankBehavior m_FuncTankBehavior; + + COutputEvent m_OnFinishInteractWithObject; + COutputEvent m_OnPlayerUse; + + bool RunningPassengerBehavior( void ); + + WeaponType_t ComputeWeaponType( CBaseEntity *pWeapon = NULL ); + WeaponType_t GetWeaponType() { return (WeaponType_t)m_WeaponType; } + bool HasShotgun() { Assert( m_WeaponType == ComputeWeaponType() ); return ( m_WeaponType == WT_SHOTGUN ); } + bool HasAlyxgun() { Assert( m_WeaponType == ComputeWeaponType() ); return ( m_WeaponType == WT_ALYXGUN ); } + bool HasAR2() { Assert( m_WeaponType == ComputeWeaponType() ); return ( m_WeaponType == WT_AR2 ); } + +private: + enum + { + COND_ALYX_HAS_INTERACT_TARGET = BaseClass::NEXT_CONDITION, + COND_ALYX_NO_INTERACT_TARGET, + COND_ALYX_CAN_INTERACT_WITH_TARGET, // Hack target is in a suitable state and location to hack + COND_ALYX_CAN_NOT_INTERACT_WITH_TARGET, + COND_ALYX_PLAYER_TURNED_ON_FLASHLIGHT, + COND_ALYX_PLAYER_TURNED_OFF_FLASHLIGHT, + COND_ALYX_PLAYER_FLASHLIGHT_EXPIRED, + COND_ALYX_IN_DARK, // lights are out and she can't see + }; + + enum + { + SCHED_ALYX_PREPARE_TO_INTERACT_WITH_TARGET = BaseClass::NEXT_SCHEDULE, + SCHED_ALYX_WAIT_TO_INTERACT_WITH_TARGET, + SCHED_ALYX_INTERACT_WITH_TARGET, + SCHED_ALYX_INTERACTION_INTERRUPTED, + SCHED_ALYX_FINISH_INTERACTING_WITH_TARGET, + SCHED_ALYX_HOLSTER_EMP, + SCHED_ALYX_ALERT_FACE_AWAYFROM_BESTSOUND, + SCHED_ALYX_RANGE_ATTACK1, + SCHED_ALYX_ALERT_REACT_TO_COMBAT_SOUND, + SCHED_ALYX_COMBAT_FACE, + SCHED_ALYX_WAKE_ANGRY, + SCHED_ALYX_NEW_WEAPON, + SCHED_ALYX_IDLE_STAND, + SCHED_ALYX_ALERT_FACE_BESTSOUND, + SCHED_ALYX_FALL_TO_GROUND, + }; + + enum + { + + TASK_ALYX_BEGIN_INTERACTION = BaseClass::NEXT_TASK, + TASK_ALYX_COMPLETE_INTERACTION, + TASK_ALYX_ANNOUNCE_HACK, + TASK_ALYX_GET_PATH_TO_INTERACT_TARGET, + TASK_ALYX_WAIT_HACKING, + TASK_ALYX_HOLSTER_PISTOL, + TASK_ALYX_DRAW_PISTOL, + TASK_ALYX_HOLSTER_AND_DESTROY_PISTOL, + TASK_ALYX_BUILD_COMBAT_FACE_PATH, + TASK_ALYX_SET_IDLE_ACTIVITY, + TASK_ALYX_FALL_TO_GROUND, + }; + + DECLARE_DATADESC(); + DEFINE_CUSTOM_AI; +}; |