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.
426 lines
13 KiB
426 lines
13 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: The downtrodden citizens of City 17. Timid when unarmed, they will |
|
// rise up against their Combine oppressors when given a weapon. |
|
// |
|
//=============================================================================// |
|
|
|
#ifndef NPC_CITIZEN_H |
|
#define NPC_CITIZEN_H |
|
|
|
#include "npc_playercompanion.h" |
|
|
|
#include "ai_behavior_functank.h" |
|
|
|
struct SquadCandidate_t; |
|
|
|
//----------------------------------------------------------------------------- |
|
// |
|
// CLASS: CNPC_Citizen |
|
// |
|
//----------------------------------------------------------------------------- |
|
|
|
//------------------------------------- |
|
// Spawnflags |
|
//------------------------------------- |
|
|
|
#define SF_CITIZEN_FOLLOW ( 1 << 16 ) //65536 follow the player as soon as I spawn. |
|
#define SF_CITIZEN_MEDIC ( 1 << 17 ) //131072 |
|
#define SF_CITIZEN_RANDOM_HEAD ( 1 << 18 ) //262144 |
|
#define SF_CITIZEN_AMMORESUPPLIER ( 1 << 19 ) //524288 |
|
#define SF_CITIZEN_NOT_COMMANDABLE ( 1 << 20 ) //1048576 |
|
#define SF_CITIZEN_IGNORE_SEMAPHORE ( 1 << 21 ) //2097152 Work outside the speech semaphore system |
|
#define SF_CITIZEN_RANDOM_HEAD_MALE ( 1 << 22 ) //4194304 |
|
#define SF_CITIZEN_RANDOM_HEAD_FEMALE ( 1 << 23 )//8388608 |
|
#define SF_CITIZEN_USE_RENDER_BOUNDS ( 1 << 24 )//16777216 |
|
|
|
//------------------------------------- |
|
// Animation events |
|
//------------------------------------- |
|
|
|
enum CitizenType_t |
|
{ |
|
CT_DEFAULT, |
|
CT_DOWNTRODDEN, |
|
CT_REFUGEE, |
|
CT_REBEL, |
|
CT_UNIQUE |
|
}; |
|
|
|
//----------------------------------------------------------------------------- |
|
// Citizen expression types |
|
//----------------------------------------------------------------------------- |
|
enum CitizenExpressionTypes_t |
|
{ |
|
CIT_EXP_UNASSIGNED, // Defaults to this, selects other in spawn. |
|
|
|
CIT_EXP_SCARED, |
|
CIT_EXP_NORMAL, |
|
CIT_EXP_ANGRY, |
|
|
|
CIT_EXP_LAST_TYPE, |
|
}; |
|
|
|
//------------------------------------- |
|
|
|
class CNPC_Citizen : public CNPC_PlayerCompanion |
|
{ |
|
DECLARE_CLASS( CNPC_Citizen, CNPC_PlayerCompanion ); |
|
public: |
|
CNPC_Citizen() |
|
: m_iHead( -1 ) |
|
{ |
|
} |
|
|
|
//--------------------------------- |
|
bool CreateBehaviors(); |
|
void Precache(); |
|
void PrecacheAllOfType( CitizenType_t ); |
|
void Spawn(); |
|
void PostNPCInit(); |
|
virtual void SelectModel(); |
|
void SelectExpressionType(); |
|
void Activate(); |
|
virtual void OnGivenWeapon( CBaseCombatWeapon *pNewWeapon ); |
|
void FixupMattWeapon(); |
|
|
|
#ifdef HL2_EPISODIC |
|
virtual float GetJumpGravity() const { return 1.8f; } |
|
#endif//HL2_EPISODIC |
|
|
|
void OnRestore(); |
|
|
|
//--------------------------------- |
|
string_t GetModelName() const; |
|
|
|
Class_T Classify(); |
|
|
|
bool ShouldAlwaysThink(); |
|
|
|
//--------------------------------- |
|
// Behavior |
|
//--------------------------------- |
|
bool ShouldBehaviorSelectSchedule( CAI_BehaviorBase *pBehavior ); |
|
void GatherConditions(); |
|
void PredictPlayerPush(); |
|
void PrescheduleThink(); |
|
void BuildScheduleTestBits(); |
|
|
|
bool FInViewCone( CBaseEntity *pEntity ); |
|
|
|
int SelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode ); |
|
int SelectSchedule(); |
|
|
|
int SelectSchedulePriorityAction(); |
|
int SelectScheduleHeal(); |
|
int SelectScheduleRetrieveItem(); |
|
int SelectScheduleNonCombat(); |
|
int SelectScheduleManhackCombat(); |
|
int SelectScheduleCombat(); |
|
bool ShouldDeferToFollowBehavior(); |
|
int TranslateSchedule( int scheduleType ); |
|
|
|
bool ShouldAcceptGoal( CAI_BehaviorBase *pBehavior, CAI_GoalEntity *pGoal ); |
|
void OnClearGoal( CAI_BehaviorBase *pBehavior, CAI_GoalEntity *pGoal ); |
|
|
|
void StartTask( const Task_t *pTask ); |
|
void RunTask( const Task_t *pTask ); |
|
|
|
Activity NPC_TranslateActivity( Activity eNewActivity ); |
|
void HandleAnimEvent( animevent_t *pEvent ); |
|
void TaskFail( AI_TaskFailureCode_t code ); |
|
|
|
void PickupItem( CBaseEntity *pItem ); |
|
|
|
void SimpleUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); |
|
|
|
bool IgnorePlayerPushing( void ); |
|
|
|
int DrawDebugTextOverlays( void ); |
|
|
|
virtual const char *SelectRandomExpressionForState( NPC_STATE state ); |
|
|
|
//--------------------------------- |
|
// Combat |
|
//--------------------------------- |
|
bool OnBeginMoveAndShoot(); |
|
void OnEndMoveAndShoot(); |
|
|
|
virtual bool UseAttackSquadSlots() { return false; } |
|
void LocateEnemySound(); |
|
|
|
bool IsManhackMeleeCombatant(); |
|
|
|
Vector GetActualShootPosition( const Vector &shootOrigin ); |
|
void OnChangeActiveWeapon( CBaseCombatWeapon *pOldWeapon, CBaseCombatWeapon *pNewWeapon ); |
|
|
|
bool ShouldLookForBetterWeapon(); |
|
|
|
|
|
//--------------------------------- |
|
// Damage handling |
|
//--------------------------------- |
|
int OnTakeDamage_Alive( const CTakeDamageInfo &info ); |
|
|
|
//--------------------------------- |
|
// Commander mode |
|
//--------------------------------- |
|
bool IsCommandable(); |
|
bool IsPlayerAlly( CBasePlayer *pPlayer = NULL ); |
|
bool CanJoinPlayerSquad(); |
|
bool WasInPlayerSquad(); |
|
bool HaveCommandGoal() const; |
|
bool IsCommandMoving(); |
|
bool ShouldAutoSummon(); |
|
bool IsValidCommandTarget( CBaseEntity *pTarget ); |
|
bool NearCommandGoal(); |
|
bool VeryFarFromCommandGoal(); |
|
bool TargetOrder( CBaseEntity *pTarget, CAI_BaseNPC **Allies, int numAllies ); |
|
void MoveOrder( const Vector &vecDest, CAI_BaseNPC **Allies, int numAllies ); |
|
void OnMoveOrder(); |
|
void CommanderUse( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value ); |
|
bool ShouldSpeakRadio( CBaseEntity *pListener ); |
|
void OnMoveToCommandGoalFailed(); |
|
void AddToPlayerSquad(); |
|
void RemoveFromPlayerSquad(); |
|
void TogglePlayerSquadState(); |
|
void UpdatePlayerSquad(); |
|
static int __cdecl PlayerSquadCandidateSortFunc( const SquadCandidate_t *, const SquadCandidate_t * ); |
|
void FixupPlayerSquad(); |
|
void ClearFollowTarget(); |
|
void UpdateFollowCommandPoint(); |
|
bool IsFollowingCommandPoint(); |
|
CAI_BaseNPC * GetSquadCommandRepresentative(); |
|
void SetSquad( CAI_Squad *pSquad ); |
|
void AddInsignia(); |
|
void RemoveInsignia(); |
|
bool SpeakCommandResponse( AIConcept_t concept, const char *modifiers = NULL ); |
|
|
|
//--------------------------------- |
|
// Scanner interaction |
|
//--------------------------------- |
|
float GetNextScannerInspectTime() { return m_fNextInspectTime; } |
|
void SetNextScannerInspectTime( float flTime ) { m_fNextInspectTime = flTime; } |
|
bool HandleInteraction(int interactionType, void *data, CBaseCombatCharacter* sourceEnt); |
|
|
|
//--------------------------------- |
|
// Hints |
|
//--------------------------------- |
|
bool FValidateHintType ( CAI_Hint *pHint ); |
|
|
|
//--------------------------------- |
|
// Special abilities |
|
//--------------------------------- |
|
bool IsMedic() { return HasSpawnFlags(SF_CITIZEN_MEDIC); } |
|
bool IsAmmoResupplier() { return HasSpawnFlags(SF_CITIZEN_AMMORESUPPLIER); } |
|
|
|
bool CanHeal(); |
|
bool ShouldHealTarget( CBaseEntity *pTarget, bool bActiveUse = false ); |
|
#if HL2_EPISODIC |
|
bool ShouldHealTossTarget( CBaseEntity *pTarget, bool bActiveUse = false ); |
|
#endif |
|
void Heal(); |
|
|
|
bool ShouldLookForHealthItem(); |
|
|
|
#if HL2_EPISODIC |
|
void TossHealthKit( CBaseCombatCharacter *pThrowAt, const Vector &offset ); // create a healthkit and throw it at someone |
|
void InputForceHealthKitToss( inputdata_t &inputdata ); |
|
#endif |
|
|
|
//--------------------------------- |
|
// Inputs |
|
//--------------------------------- |
|
void InputRemoveFromPlayerSquad( inputdata_t &inputdata ) { RemoveFromPlayerSquad(); } |
|
void InputStartPatrolling( inputdata_t &inputdata ); |
|
void InputStopPatrolling( inputdata_t &inputdata ); |
|
void InputSetCommandable( inputdata_t &inputdata ); |
|
void InputSetMedicOn( inputdata_t &inputdata ); |
|
void InputSetMedicOff( inputdata_t &inputdata ); |
|
void InputSetAmmoResupplierOn( inputdata_t &inputdata ); |
|
void InputSetAmmoResupplierOff( inputdata_t &inputdata ); |
|
void InputSpeakIdleResponse( inputdata_t &inputdata ); |
|
|
|
//--------------------------------- |
|
// Sounds & speech |
|
//--------------------------------- |
|
void FearSound( void ); |
|
void DeathSound( const CTakeDamageInfo &info ); |
|
bool UseSemaphore( void ); |
|
|
|
virtual void OnChangeRunningBehavior( CAI_BehaviorBase *pOldBehavior, CAI_BehaviorBase *pNewBehavior ); |
|
|
|
private: |
|
//----------------------------------------------------- |
|
// Conditions, Schedules, Tasks |
|
//----------------------------------------------------- |
|
enum |
|
{ |
|
COND_CIT_PLAYERHEALREQUEST = BaseClass::NEXT_CONDITION, |
|
COND_CIT_COMMANDHEAL, |
|
COND_CIT_HURTBYFIRE, |
|
COND_CIT_START_INSPECTION, |
|
|
|
SCHED_CITIZEN_PLAY_INSPECT_ACTIVITY = BaseClass::NEXT_SCHEDULE, |
|
SCHED_CITIZEN_HEAL, |
|
SCHED_CITIZEN_RANGE_ATTACK1_RPG, |
|
SCHED_CITIZEN_PATROL, |
|
SCHED_CITIZEN_MOURN_PLAYER, |
|
SCHED_CITIZEN_SIT_ON_TRAIN, |
|
SCHED_CITIZEN_STRIDER_RANGE_ATTACK1_RPG, |
|
#ifdef HL2_EPISODIC |
|
SCHED_CITIZEN_HEAL_TOSS, |
|
#endif |
|
|
|
TASK_CIT_HEAL = BaseClass::NEXT_TASK, |
|
TASK_CIT_RPG_AUGER, |
|
TASK_CIT_PLAY_INSPECT_SEQUENCE, |
|
TASK_CIT_SIT_ON_TRAIN, |
|
TASK_CIT_LEAVE_TRAIN, |
|
TASK_CIT_SPEAK_MOURNING, |
|
#ifdef HL2_EPISODIC |
|
TASK_CIT_HEAL_TOSS, |
|
#endif |
|
|
|
}; |
|
|
|
//----------------------------------------------------- |
|
|
|
int m_nInspectActivity; |
|
float m_flNextFearSoundTime; |
|
float m_flStopManhackFlinch; |
|
float m_fNextInspectTime; // Next time I'm allowed to get inspected by a scanner |
|
float m_flPlayerHealTime; |
|
float m_flNextHealthSearchTime; // Next time I'm allowed to look for a healthkit |
|
float m_flAllyHealTime; |
|
float m_flPlayerGiveAmmoTime; |
|
string_t m_iszAmmoSupply; |
|
int m_iAmmoAmount; |
|
bool m_bRPGAvoidPlayer; |
|
bool m_bShouldPatrol; |
|
string_t m_iszOriginalSquad; |
|
float m_flTimeJoinedPlayerSquad; |
|
bool m_bWasInPlayerSquad; |
|
float m_flTimeLastCloseToPlayer; |
|
string_t m_iszDenyCommandConcept; |
|
|
|
CSimpleSimTimer m_AutoSummonTimer; |
|
Vector m_vAutoSummonAnchor; |
|
|
|
CitizenType_t m_Type; |
|
CitizenExpressionTypes_t m_ExpressionType; |
|
|
|
int m_iHead; |
|
|
|
static CSimpleSimTimer gm_PlayerSquadEvaluateTimer; |
|
|
|
float m_flTimePlayerStare; // The game time at which the player started staring at me. |
|
float m_flTimeNextHealStare; // Next time I'm allowed to heal a player who is staring at me. |
|
|
|
//----------------------------------------------------- |
|
// Outputs |
|
//----------------------------------------------------- |
|
COutputEvent m_OnJoinedPlayerSquad; |
|
COutputEvent m_OnLeftPlayerSquad; |
|
COutputEvent m_OnFollowOrder; |
|
COutputEvent m_OnStationOrder; |
|
COutputEvent m_OnPlayerUse; |
|
COutputEvent m_OnNavFailBlocked; |
|
|
|
//----------------------------------------------------- |
|
CAI_FuncTankBehavior m_FuncTankBehavior; |
|
|
|
CHandle<CAI_FollowGoal> m_hSavedFollowGoalEnt; |
|
|
|
bool m_bNotifyNavFailBlocked; |
|
bool m_bNeverLeavePlayerSquad; // Don't leave the player squad unless killed, or removed via Entity I/O. |
|
|
|
//----------------------------------------------------- |
|
|
|
DECLARE_DATADESC(); |
|
#ifdef _XBOX |
|
protected: |
|
#endif |
|
DEFINE_CUSTOM_AI; |
|
}; |
|
|
|
//--------------------------------------------------------- |
|
//--------------------------------------------------------- |
|
inline bool CNPC_Citizen::NearCommandGoal() |
|
{ |
|
const float flDistSqr = COMMAND_GOAL_TOLERANCE * COMMAND_GOAL_TOLERANCE; |
|
return ( ( GetAbsOrigin() - GetCommandGoal() ).LengthSqr() <= flDistSqr ); |
|
} |
|
|
|
//--------------------------------------------------------- |
|
//--------------------------------------------------------- |
|
inline bool CNPC_Citizen::VeryFarFromCommandGoal() |
|
{ |
|
const float flDistSqr = (12*50) * (12*50); |
|
return ( ( GetAbsOrigin() - GetCommandGoal() ).LengthSqr() > flDistSqr ); |
|
} |
|
|
|
|
|
|
|
//============================================================================== |
|
// CITIZEN PLAYER-RESPONSE SYSTEM |
|
// |
|
// NOTE: This system is obsolete, and left here for legacy support. |
|
// It has been superseded by the ai_eventresponse system. |
|
// |
|
//============================================================================== |
|
#define CITIZEN_RESPONSE_DISTANCE 768 // Maximum distance for responding citizens |
|
#define CITIZEN_RESPONSE_REFIRE_TIME 15.0 // Time after giving a response before giving any more |
|
#define CITIZEN_RESPONSE_GIVEUP_TIME 4.0 // Time after a response trigger was fired before discarding it without responding |
|
|
|
enum citizenresponses_t |
|
{ |
|
CR_PLAYER_SHOT_GUNSHIP, // Player has shot the gunship with a bullet weapon |
|
CR_PLAYER_KILLED_GUNSHIP, // Player has destroyed the gunship |
|
CR_VITALNPC_DIED, // Mapmaker specified that an NPC that was vital has died |
|
|
|
// Add new responses here |
|
|
|
MAX_CITIZEN_RESPONSES, |
|
}; |
|
|
|
//------------------------------------- |
|
|
|
class CCitizenResponseSystem : public CBaseEntity |
|
{ |
|
DECLARE_CLASS( CCitizenResponseSystem, CBaseEntity ); |
|
public: |
|
DECLARE_DATADESC(); |
|
|
|
void Spawn(); |
|
void OnRestore(); |
|
|
|
void AddResponseTrigger( citizenresponses_t iTrigger ); |
|
|
|
void ResponseThink(); |
|
|
|
//--------------------------------- |
|
// Inputs |
|
//--------------------------------- |
|
void InputResponseVitalNPC( inputdata_t &inputdata ); |
|
|
|
private: |
|
float m_flResponseAddedTime[ MAX_CITIZEN_RESPONSES ]; // Time at which the response was added. 0 if we have no response. |
|
float m_flNextResponseTime; |
|
}; |
|
|
|
//------------------------------------- |
|
|
|
class CSquadInsignia : public CBaseAnimating |
|
{ |
|
DECLARE_CLASS( CSquadInsignia, CBaseAnimating ); |
|
void Spawn(); |
|
}; |
|
|
|
//------------------------------------- |
|
|
|
CCitizenResponseSystem *GetCitizenResponse(); |
|
|
|
//----------------------------------------------------------------------------- |
|
|
|
#endif //NPC_CITIZEN_H
|
|
|