diff options
Diffstat (limited to 'game/server/hl2/npc_playercompanion.h')
| -rw-r--r-- | game/server/hl2/npc_playercompanion.h | 439 |
1 files changed, 439 insertions, 0 deletions
diff --git a/game/server/hl2/npc_playercompanion.h b/game/server/hl2/npc_playercompanion.h new file mode 100644 index 0000000..f1c3b1f --- /dev/null +++ b/game/server/hl2/npc_playercompanion.h @@ -0,0 +1,439 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Base class for humanoid NPCs intended to fight along side player in close +// environments +// +//=============================================================================// + +#ifndef NPC_PLAYERCOMPANION_H +#define NPC_PLAYERCOMPANION_H + +#include "ai_playerally.h" + +#include "ai_behavior_follow.h" +#include "ai_behavior_standoff.h" +#include "ai_behavior_assault.h" +#include "ai_behavior_lead.h" +#include "ai_behavior_actbusy.h" +#include "ai_behavior_fear.h" + +#ifdef HL2_EPISODIC +#include "ai_behavior_operator.h" +#include "ai_behavior_passenger_companion.h" +#endif + +#if defined( _WIN32 ) +#pragma once +#endif + +enum AIReadiness_t +{ + AIRL_PANIC = -2, + AIRL_STEALTH = -1, + AIRL_RELAXED = 0, + AIRL_STIMULATED, + AIRL_AGITATED, +}; + +enum AIReadinessUse_t +{ + AIRU_NEVER, + AIRU_ALWAYS, + AIRU_ONLY_PLAYER_SQUADMATES, +}; + + +class CCompanionActivityRemap : public CActivityRemap +{ +public: + CCompanionActivityRemap( void ) : + m_fUsageBits( 0 ), + m_readiness( AIRL_RELAXED ), + m_bAiming( false ), + m_bWeaponRequired( false ), + m_bInVehicle( false ) {} + + // This bitfield maps which bits of data are being utilized by this data structure, since not all criteria + // in the parsed file are essential. You must add corresponding bits to the definitions below and maintain + // their state in the parsing of the file, as well as check the bitfield before accessing the data. This + // could be encapsulated into this class, but we'll probably move away from this model and closer to something + // more akin to the response rules -- jdw + + int m_fUsageBits; + + AIReadiness_t m_readiness; + bool m_bAiming; + bool m_bWeaponRequired; + bool m_bInVehicle; // For future expansion, this needs to speak more to the exact seat, role, and vehicle +}; + +// Usage bits for remap "extra" parsing - if these bits are set, the associated data has changed +#define bits_REMAP_READINESS (1<<0) +#define bits_REMAP_AIMING (1<<1) +#define bits_REMAP_WEAPON_REQUIRED (1<<2) +#define bits_REMAP_IN_VEHICLE (1<<3) + +// Readiness modes that only change due to mapmaker scripts +#define READINESS_MIN_VALUE -2 +#define READINESS_MODE_PANIC -2 +#define READINESS_MODE_STEALTH -1 + +// Readiness modes that change normally +#define READINESS_VALUE_RELAXED 0.1f +#define READINESS_VALUE_STIMULATED 0.95f +#define READINESS_VALUE_AGITATED 1.0f + +class CPhysicsProp; + +//----------------------------------------------------------------------------- +// +// CLASS: CNPC_PlayerCompanion +// +//----------------------------------------------------------------------------- + +class CNPC_PlayerCompanion : public CAI_PlayerAlly +{ + DECLARE_CLASS( CNPC_PlayerCompanion, CAI_PlayerAlly ); + +public: + //--------------------------------- + bool CreateBehaviors(); + void Precache(); + void Spawn(); + virtual void SelectModel() {}; + + virtual int Restore( IRestore &restore ); + virtual void DoCustomSpeechAI( void ); + + //--------------------------------- + int ObjectCaps(); + bool ShouldAlwaysThink(); + + Disposition_t IRelationType( CBaseEntity *pTarget ); + + bool IsSilentSquadMember() const; + + //--------------------------------- + // Behavior + //--------------------------------- + void GatherConditions(); + virtual void PredictPlayerPush(); + void BuildScheduleTestBits(); + + CSound *GetBestSound( int validTypes = ALL_SOUNDS ); + bool QueryHearSound( CSound *pSound ); + bool QuerySeeEntity( CBaseEntity *pEntity, bool bOnlyHateOrFearIfNPC = false ); + bool ShouldIgnoreSound( CSound * ); + + int SelectSchedule(); + + virtual int SelectScheduleDanger(); + virtual int SelectSchedulePriorityAction(); + virtual int SelectScheduleNonCombat() { return SCHED_NONE; } + virtual int SelectScheduleCombat(); + int SelectSchedulePlayerPush(); + + virtual bool CanReload( void ); + + virtual bool ShouldDeferToFollowBehavior(); + bool ShouldDeferToPassengerBehavior( void ); + + bool IsValidReasonableFacing( const Vector &vecSightDir, float sightDist ); + + int TranslateSchedule( int scheduleType ); + + void StartTask( const Task_t *pTask ); + void RunTask( const Task_t *pTask ); + + Activity TranslateActivityReadiness( Activity activity ); + Activity NPC_TranslateActivity( Activity eNewActivity ); + void HandleAnimEvent( animevent_t *pEvent ); + bool HandleInteraction(int interactionType, void *data, CBaseCombatCharacter* sourceEnt); + + int GetSoundInterests(); + + void Touch( CBaseEntity *pOther ); + + virtual bool IgnorePlayerPushing( void ); + + void ModifyOrAppendCriteria( AI_CriteriaSet& set ); + void Activate( void ); + + void PrepareReadinessRemap( void ); + + virtual bool IsNavigationUrgent( void ); + + //--------------------------------- + // Readiness + //--------------------------------- + +protected: + virtual bool IsReadinessCapable(); + bool IsReadinessLocked() { return gpGlobals->curtime < m_flReadinessLockedUntil; } + void AddReadiness( float flAdd, bool bOverrideLock = false ); + void SubtractReadiness( float flAdd, bool bOverrideLock = false ); + void SetReadinessValue( float flSet ); + void SetReadinessSensitivity( float flSensitivity ) { m_flReadinessSensitivity = flSensitivity; } + virtual void UpdateReadiness(); + virtual float GetReadinessDecay(); + bool IsInScriptedReadinessState( void ) { return (m_flReadiness < 0 ); } + + CUtlVector< CCompanionActivityRemap > m_activityMappings; + +public: + float GetReadinessValue() { return m_flReadiness; } + int GetReadinessLevel(); + void SetReadinessLevel( int iLevel, bool bOverrideLock, bool bSlam ); + void LockReadiness( float duration = -1.0f ); // Defaults to indefinitely locked + void UnlockReadiness( void ); + + virtual void ReadinessLevelChanged( int iPriorLevel ) { } + + void InputGiveWeapon( inputdata_t &inputdata ); + +#ifdef HL2_EPISODIC + //--------------------------------- + // Vehicle passenger + //--------------------------------- + void InputEnterVehicle( inputdata_t &inputdata ); + void InputEnterVehicleImmediately( inputdata_t &inputdata ); + void InputCancelEnterVehicle( inputdata_t &inputdata ); + void InputExitVehicle( inputdata_t &inputdata ); + bool CanEnterVehicle( void ); + bool CanExitVehicle( void ); + void EnterVehicle( CBaseEntity *pEntityVehicle, bool bImmediately ); + virtual bool ExitVehicle( void ); + + virtual void UpdateEfficiency( bool bInPVS ); + virtual bool IsInAVehicle( void ) const; + virtual IServerVehicle *GetVehicle( void ); + virtual CBaseEntity *GetVehicleEntity( void ); + + virtual bool CanRunAScriptedNPCInteraction( bool bForced = false ); + virtual bool IsAllowedToDodge( void ); + +#endif // HL2_EPISODIC + +public: + + virtual void OnPlayerKilledOther( CBaseEntity *pVictim, const CTakeDamageInfo &info ); + + //--------------------------------- + //--------------------------------- + bool PickTacticalLookTarget( AILookTargetArgs_t *pArgs ); + + //--------------------------------- + // Aiming + //--------------------------------- + CBaseEntity *GetAimTarget() { return m_hAimTarget; } + void SetAimTarget( CBaseEntity *pTarget ); + void StopAiming( char *pszReason = NULL ); + bool FindNewAimTarget(); + void OnNewLookTarget(); + bool ShouldBeAiming(); + virtual bool IsAllowedToAim(); + bool HasAimLOS( CBaseEntity *pAimTarget ); + void AimGun(); + CBaseEntity *GetAlternateMoveShootTarget(); + + //--------------------------------- + // Combat + //--------------------------------- + virtual void LocateEnemySound() {}; + + bool IsValidEnemy( CBaseEntity *pEnemy ); + + bool IsSafeFromFloorTurret( const Vector &vecLocation, CBaseEntity *pTurret ); + + bool ShouldMoveAndShoot( void ); + void OnUpdateShotRegulator(); + + void DecalTrace( trace_t *pTrace, char const *decalName ); + bool FCanCheckAttacks(); + Vector GetActualShootPosition( const Vector &shootOrigin ); + WeaponProficiency_t CalcWeaponProficiency( CBaseCombatWeapon *pWeapon ); + bool ShouldLookForBetterWeapon(); + bool Weapon_CanUse( CBaseCombatWeapon *pWeapon ); + void Weapon_Equip( CBaseCombatWeapon *pWeapon ); + void PickupWeapon( CBaseCombatWeapon *pWeapon ); + + bool FindCoverPos( CBaseEntity *pEntity, Vector *pResult); + bool FindCoverPosInRadius( CBaseEntity *pEntity, const Vector &goalPos, float coverRadius, Vector *pResult ); + bool FindCoverPos( CSound *pSound, Vector *pResult ); + bool FindMortarCoverPos( CSound *pSound, Vector *pResult ); + bool IsCoverPosition( const Vector &vecThreat, const Vector &vecPosition ); + + bool IsEnemyTurret() { return ( GetEnemy() && IsTurret(GetEnemy()) ); } + + static bool IsMortar( CBaseEntity *pEntity ); + static bool IsSniper( CBaseEntity *pEntity ); + static bool IsTurret( CBaseEntity *pEntity ); + static bool IsGunship( CBaseEntity *pEntity ); + + //--------------------------------- + // Damage handling + //--------------------------------- + int OnTakeDamage_Alive( const CTakeDamageInfo &info ); + void OnFriendDamaged( CBaseCombatCharacter *pSquadmate, CBaseEntity *pAttacker ); + + //--------------------------------- + // Hints + //--------------------------------- + bool FValidateHintType ( CAI_Hint *pHint ); + + //--------------------------------- + // Navigation + //--------------------------------- + bool IsValidMoveAwayDest( const Vector &vecDest ); + bool ValidateNavGoal(); + bool OverrideMove( float flInterval ); // Override to take total control of movement (return true if done so) + bool MovementCost( int moveType, const Vector &vecStart, const Vector &vecEnd, float *pCost ); + float GetIdealSpeed() const; + float GetIdealAccel() const; + bool OnObstructionPreSteer( AILocalMoveGoal_t *pMoveGoal, float distClear, AIMoveResult_t *pResult ); + + //--------------------------------- + // Inputs + //--------------------------------- + void InputOutsideTransition( inputdata_t &inputdata ); + void InputSetReadinessPanic( inputdata_t &inputdata ); + void InputSetReadinessStealth( inputdata_t &inputdata ); + void InputSetReadinessLow( inputdata_t &inputdata ); + void InputSetReadinessMedium( inputdata_t &inputdata ); + void InputSetReadinessHigh( inputdata_t &inputdata ); + void InputLockReadiness( inputdata_t &inputdata ); +#if HL2_EPISODIC + void InputClearAllOuputs( inputdata_t &inputdata ); ///< annihilate every output on this npc +#endif + + bool AllowReadinessValueChange( void ); + +protected: + //----------------------------------------------------- + // Conditions, Schedules, Tasks + //----------------------------------------------------- + enum + { + COND_PC_HURTBYFIRE = BaseClass::NEXT_CONDITION, + COND_PC_SAFE_FROM_MORTAR, + COND_PC_BECOMING_PASSENGER, + NEXT_CONDITION, + + SCHED_PC_COWER = BaseClass::NEXT_SCHEDULE, + SCHED_PC_MOVE_TOWARDS_COVER_FROM_BEST_SOUND, + SCHED_PC_TAKE_COVER_FROM_BEST_SOUND, + SCHED_PC_FLEE_FROM_BEST_SOUND, + SCHED_PC_FAIL_TAKE_COVER_TURRET, + SCHED_PC_FAKEOUT_MORTAR, + SCHED_PC_GET_OFF_COMPANION, + NEXT_SCHEDULE, + + TASK_PC_WAITOUT_MORTAR = BaseClass::NEXT_TASK, + TASK_PC_GET_PATH_OFF_COMPANION, + NEXT_TASK, + }; + +private: + void SetupCoverSearch( CBaseEntity *pEntity ); + void CleanupCoverSearch(); + + //----------------------------------------------------- + + bool m_bMovingAwayFromPlayer; + bool m_bWeightPathsInCover; + + enum eCoverType + { + CT_NORMAL, + CT_TURRET, + CT_MORTAR + }; + + static eCoverType gm_fCoverSearchType; + static bool gm_bFindingCoverFromAllEnemies; + + CSimpleSimTimer m_FakeOutMortarTimer; + + // Derived classes should not use the expresser directly + virtual CAI_Expresser *GetExpresser() { return BaseClass::GetExpresser(); } + +protected: + //----------------------------------------------------- + + virtual CAI_FollowBehavior &GetFollowBehavior( void ) { return m_FollowBehavior; } + + CAI_AssaultBehavior m_AssaultBehavior; + CAI_FollowBehavior m_FollowBehavior; + CAI_StandoffBehavior m_StandoffBehavior; + CAI_LeadBehavior m_LeadBehavior; + CAI_ActBusyBehavior m_ActBusyBehavior; +#ifdef HL2_EPISODIC + CAI_OperatorBehavior m_OperatorBehavior; + CAI_PassengerBehaviorCompanion m_PassengerBehavior; + CAI_FearBehavior m_FearBehavior; +#endif + //----------------------------------------------------- + + bool ShouldAlwaysTransition( void ); + + // Readiness is a value that's fed by various events in the NPC's AI. It is used + // to make decisions about what type of posture the NPC should be in (relaxed, agitated). + // It is not used to make decisions about what to do in the AI. + float m_flReadiness; + float m_flReadinessSensitivity; + bool m_bReadinessCapable; + float m_flReadinessLockedUntil; + float m_fLastBarrelExploded; + float m_fLastPlayerKill; + int m_iNumConsecutiveBarrelsExploded; // Companions keep track of the # of consecutive barrels exploded by the player and speaks a response as it increases + int m_iNumConsecutivePlayerKills; // Alyx keeps track of the # of consecutive kills by the player and speaks a response as it increases + + //----------------------------------------------------- + + float m_flBoostSpeed; + + //----------------------------------------------------- + + CSimpleSimTimer m_AnnounceAttackTimer; + + //----------------------------------------------------- + + EHANDLE m_hAimTarget; + +#ifdef HL2_EPISODIC + CHandle<CPhysicsProp> m_hFlare; +#endif // HL2_EPISODIC + + //----------------------------------------------------- + + static string_t gm_iszMortarClassname; + static string_t gm_iszFloorTurretClassname; + static string_t gm_iszGroundTurretClassname; + static string_t gm_iszShotgunClassname; + static string_t gm_iszRollerMineClassname; + + //----------------------------------------------------- + + void InputEnableAlwaysTransition( inputdata_t &inputdata ); + void InputDisableAlwaysTransition( inputdata_t &inputdata ); + bool m_bAlwaysTransition; + bool m_bDontPickupWeapons; + + void InputEnableWeaponPickup( inputdata_t &inputdata ); + void InputDisableWeaponPickup( inputdata_t &inputdata ); + + COutputEvent m_OnWeaponPickup; + + CStopwatch m_SpeechWatch_PlayerLooking; + + DECLARE_DATADESC(); + DEFINE_CUSTOM_AI; +}; + +// Used for quick override move searches against certain types of entities +void OverrideMoveCache_ForceRepopulateList( void ); +CBaseEntity *OverrideMoveCache_FindTargetsInRadius( CBaseEntity *pFirstEntity, const Vector &vecOrigin, float flRadius ); +void OverrideMoveCache_LevelInitPreEntity( void ); +void OverrideMoveCache_LevelShutdownPostEntity( void ); + +#endif // NPC_PLAYERCOMPANION_H |