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.
318 lines
10 KiB
318 lines
10 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
//=============================================================================// |
|
|
|
#ifndef AI_BEHAVIOR_ACTBUSY_H |
|
#define AI_BEHAVIOR_ACTBUSY_H |
|
#ifdef _WIN32 |
|
#pragma once |
|
#endif |
|
|
|
#include "ai_behavior.h" |
|
#include "ai_goalentity.h" |
|
|
|
//----------------------------------------------------------------------------- |
|
enum |
|
{ |
|
ACTBUSY_TYPE_DEFAULT = 0, |
|
ACTBUSY_TYPE_COMBAT, |
|
}; |
|
|
|
enum busyinterrupt_t |
|
{ |
|
BA_INT_NONE, // Nothing breaks us out of this |
|
BA_INT_DANGER, // Only danger signals interrupts this busy anim. The player will be ignored. |
|
BA_INT_PLAYER, // The Player's presence interrupts this busy anim |
|
BA_INT_AMBUSH, // We're waiting to ambush enemies. Don't break on danger sounds in front of us. |
|
BA_INT_COMBAT, // Only break out if we're shot at. |
|
BA_INT_ZOMBIESLUMP, // Zombies who are slumped on the ground. |
|
BA_INT_SIEGE_DEFENSE, |
|
}; |
|
|
|
enum busyanimparts_t |
|
{ |
|
BA_BUSY, |
|
BA_ENTRY, |
|
BA_EXIT, |
|
|
|
BA_MAX_ANIMS, |
|
}; |
|
|
|
struct busyanim_t |
|
{ |
|
string_t iszName; |
|
Activity iActivities[BA_MAX_ANIMS]; |
|
string_t iszSequences[BA_MAX_ANIMS]; |
|
string_t iszSounds[BA_MAX_ANIMS]; |
|
float flMinTime; // Min time spent in this busy animation |
|
float flMaxTime; // Max time spent in this busy animation. 0 means continue until interrupted. |
|
busyinterrupt_t iBusyInterruptType; |
|
bool bUseAutomovement; |
|
}; |
|
|
|
struct busysafezone_t |
|
{ |
|
Vector vecMins; |
|
Vector vecMaxs; |
|
}; |
|
|
|
#define NO_MAX_TIME -1 |
|
|
|
class CAI_ActBusyGoal; |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
class CAI_ActBusyBehavior : public CAI_SimpleBehavior |
|
{ |
|
DECLARE_CLASS( CAI_ActBusyBehavior, CAI_SimpleBehavior ); |
|
public: |
|
DECLARE_DATADESC(); |
|
CAI_ActBusyBehavior(); |
|
|
|
enum |
|
{ |
|
// Schedules |
|
SCHED_ACTBUSY_START_BUSYING = BaseClass::NEXT_SCHEDULE, |
|
SCHED_ACTBUSY_BUSY, |
|
SCHED_ACTBUSY_STOP_BUSYING, |
|
SCHED_ACTBUSY_LEAVE, |
|
SCHED_ACTBUSY_TELEPORT_TO_BUSY, |
|
NEXT_SCHEDULE, |
|
|
|
// Tasks |
|
TASK_ACTBUSY_PLAY_BUSY_ANIM = BaseClass::NEXT_TASK, |
|
TASK_ACTBUSY_PLAY_ENTRY, |
|
TASK_ACTBUSY_PLAY_EXIT, |
|
TASK_ACTBUSY_TELEPORT_TO_BUSY, |
|
TASK_ACTBUSY_WALK_PATH_TO_BUSY, |
|
TASK_ACTBUSY_GET_PATH_TO_ACTBUSY, |
|
TASK_ACTBUSY_VERIFY_EXIT, |
|
NEXT_TASK, |
|
|
|
// Conditions |
|
COND_ACTBUSY_LOST_SEE_ENTITY = BaseClass::NEXT_CONDITION, |
|
COND_ACTBUSY_AWARE_OF_ENEMY_IN_SAFE_ZONE, |
|
COND_ACTBUSY_ENEMY_TOO_CLOSE, |
|
NEXT_CONDITION, |
|
}; |
|
|
|
virtual const char *GetName() { return "ActBusy"; } |
|
|
|
void Enable( CAI_ActBusyGoal *pGoal, float flRange, bool bVisibleOnly ); |
|
void OnRestore(); |
|
void SetBusySearchRange( float flRange ); |
|
void Disable( void ); |
|
void ForceActBusy( CAI_ActBusyGoal *pGoal, CAI_Hint *pHintNode = NULL, float flMaxTime = NO_MAX_TIME, bool bVisibleOnly = false, bool bTeleportToBusy = false, bool bUseNearestBusy = false, CBaseEntity *pSeeEntity = NULL, Activity activity = ACT_INVALID ); |
|
void ForceActBusyLeave( bool bVisibleOnly = false ); |
|
void StopBusying( void ); |
|
bool IsStopBusying(); |
|
CAI_Hint *FindActBusyHintNode( void ); |
|
CAI_Hint *FindCombatActBusyHintNode( void ); |
|
CAI_Hint *FindCombatActBusyTeleportHintNode( void ); |
|
bool CanSelectSchedule( void ); |
|
bool IsCurScheduleOverridable( void ); |
|
bool ShouldIgnoreSound( CSound *pSound ); |
|
void OnFriendDamaged( CBaseCombatCharacter *pSquadmate, CBaseEntity *pAttacker ); |
|
int OnTakeDamage_Alive( const CTakeDamageInfo &info ); |
|
void GatherConditions( void ); |
|
void BuildScheduleTestBits( void ); |
|
void EndScheduleSelection( void ); |
|
Activity NPC_TranslateActivity( Activity nActivity ); |
|
void HandleAnimEvent( animevent_t *pEvent ); |
|
void CheckAndCleanupOnExit( void ); |
|
bool FValidateHintType( CAI_Hint *pHint ); |
|
bool ActBusyNodeStillActive( void ); |
|
bool IsMovingToBusy( void ) { return m_bMovingToBusy; } |
|
bool IsEnabled( void ) { return m_bEnabled; } |
|
float GetReasonableFacingDist( void ) { return 0; } // Actbusy ignores reasonable facing |
|
bool IsInterruptable( void ); |
|
bool ShouldPlayerAvoid( void ); |
|
void SetUseRenderBounds( bool bUseBounds ) { m_bUseRenderBoundsForCollision = bUseBounds; } |
|
void ComputeAndSetRenderBounds(); |
|
bool CanFlinch( void ); |
|
bool CanRunAScriptedNPCInteraction( bool bForced ); |
|
void OnScheduleChange(); |
|
bool QueryHearSound( CSound *pSound ); |
|
void OnSeeEntity( CBaseEntity *pEntity ); |
|
bool NeedsToPlayExitAnim() { return m_bNeedsToPlayExitAnim; } |
|
|
|
// Returns true if the current NPC is acting busy, or moving to an actbusy |
|
bool IsActive( void ); |
|
// Returns true if the current NPC is actually acting busy (i.e. inside an act busy anim) |
|
bool IsInsideActBusy( void ) { return m_bBusy; } |
|
|
|
// Combat act busy stuff |
|
bool IsCombatActBusy(); |
|
void CollectSafeZoneVolumes( CAI_ActBusyGoal *pActBusyGoal ); |
|
bool IsInSafeZone( CBaseEntity *pEntity ); |
|
int CountEnemiesInSafeZone(); |
|
|
|
private: |
|
virtual int SelectSchedule( void ); |
|
int SelectScheduleForLeaving( void ); |
|
int SelectScheduleWhileNotBusy( int iBase ); |
|
int SelectScheduleWhileBusy( void ); |
|
virtual void StartTask( const Task_t *pTask ); |
|
virtual void RunTask( const Task_t *pTask ); |
|
void NotifyBusyEnding( void ); |
|
bool HasAnimForActBusy( int iActBusy, busyanimparts_t AnimPart ); |
|
bool PlayAnimForActBusy( busyanimparts_t AnimPart ); |
|
void PlaySoundForActBusy( busyanimparts_t AnimPart ); |
|
|
|
private: |
|
bool m_bEnabled; |
|
bool m_bForceActBusy; |
|
Activity m_ForcedActivity; |
|
bool m_bTeleportToBusy; |
|
bool m_bUseNearestBusy; |
|
bool m_bLeaving; |
|
bool m_bVisibleOnly; |
|
bool m_bUseRenderBoundsForCollision; |
|
float m_flForcedMaxTime; |
|
bool m_bBusy; |
|
bool m_bMovingToBusy; |
|
bool m_bNeedsToPlayExitAnim; |
|
float m_flNextBusySearchTime; |
|
float m_flEndBusyAt; |
|
float m_flBusySearchRange; |
|
bool m_bInQueue; |
|
int m_iCurrentBusyAnim; |
|
CHandle<CAI_ActBusyGoal> m_hActBusyGoal; |
|
bool m_bNeedToSetBounds; |
|
EHANDLE m_hSeeEntity; |
|
float m_fTimeLastSawSeeEntity; |
|
bool m_bExitedBusyToDueLostSeeEntity; |
|
bool m_bExitedBusyToDueSeeEnemy; |
|
|
|
int m_iNumConsecutivePathFailures; // Count how many times we failed to find a path to a node, so we can consider teleporting. |
|
bool m_bAutoFireWeapon; |
|
float m_flDeferUntil; |
|
int m_iNumEnemiesInSafeZone; |
|
|
|
CUtlVector<busysafezone_t>m_SafeZones; |
|
|
|
DEFINE_CUSTOM_SCHEDULE_PROVIDER; |
|
}; |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: A level tool to control the actbusy behavior. |
|
//----------------------------------------------------------------------------- |
|
class CAI_ActBusyGoal : public CAI_GoalEntity |
|
{ |
|
DECLARE_CLASS( CAI_ActBusyGoal, CAI_GoalEntity ); |
|
public: |
|
CAI_ActBusyGoal() |
|
{ |
|
// Support legacy maps, where this value used to be set from a constant (with a value of 1). |
|
// Now designers can specify whatever they want in Hammer. Take care of old maps by setting |
|
// this in the constructor. (sjb) |
|
m_flSeeEntityTimeout = 1; |
|
} |
|
|
|
virtual void NPCMovingToBusy( CAI_BaseNPC *pNPC ); |
|
virtual void NPCAbortedMoveTo( CAI_BaseNPC *pNPC ); |
|
virtual void NPCStartedBusy( CAI_BaseNPC *pNPC ); |
|
virtual void NPCStartedLeavingBusy( CAI_BaseNPC *pNPC ); |
|
virtual void NPCFinishedBusy( CAI_BaseNPC *pNPC ); |
|
virtual void NPCLeft( CAI_BaseNPC *pNPC ); |
|
virtual void NPCLostSeeEntity( CAI_BaseNPC *pNPC ); |
|
virtual void NPCSeeEnemy( CAI_BaseNPC *pNPC ); |
|
|
|
int GetType() { return m_iType; } |
|
bool IsCombatActBusyTeleportAllowed() { return m_bAllowCombatActBusyTeleport; } |
|
|
|
protected: |
|
CAI_ActBusyBehavior *GetBusyBehaviorForNPC( const char *pszActorName, CBaseEntity *pActivator, CBaseEntity *pCaller, const char *sInputName ); |
|
CAI_ActBusyBehavior *GetBusyBehaviorForNPC( CBaseEntity *pEntity, const char *sInputName ); |
|
|
|
void EnableGoal( CAI_BaseNPC *pAI ); |
|
|
|
// Inputs |
|
virtual void InputActivate( inputdata_t &inputdata ); |
|
virtual void InputDeactivate( inputdata_t &inputdata ); |
|
void InputSetBusySearchRange( inputdata_t &inputdata ); |
|
void InputForceNPCToActBusy( inputdata_t &inputdata ); |
|
void InputForceThisNPCToActBusy( inputdata_t &inputdata ); |
|
void InputForceThisNPCToLeave( inputdata_t &inputdata ); |
|
|
|
DECLARE_DATADESC(); |
|
|
|
protected: |
|
float m_flBusySearchRange; |
|
bool m_bVisibleOnly; |
|
int m_iType; |
|
bool m_bAllowCombatActBusyTeleport; |
|
|
|
public: |
|
// Let the actbusy behavior query these so we don't have to duplicate the data. |
|
string_t m_iszSeeEntityName; |
|
float m_flSeeEntityTimeout; |
|
string_t m_iszSafeZoneVolume; |
|
int m_iSightMethod; |
|
|
|
protected: |
|
COutputEHANDLE m_OnNPCStartedBusy; |
|
COutputEHANDLE m_OnNPCFinishedBusy; |
|
COutputEHANDLE m_OnNPCLeft; |
|
COutputEHANDLE m_OnNPCLostSeeEntity; |
|
COutputEHANDLE m_OnNPCSeeEnemy; |
|
}; |
|
|
|
// Maximum number of nodes allowed in an actbusy queue |
|
#define MAX_QUEUE_NODES 20 |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: A level tool to control the actbusy behavior to create NPC queues |
|
//----------------------------------------------------------------------------- |
|
class CAI_ActBusyQueueGoal : public CAI_ActBusyGoal |
|
{ |
|
DECLARE_CLASS( CAI_ActBusyQueueGoal, CAI_ActBusyGoal ); |
|
public: |
|
virtual void Spawn( void ); |
|
virtual void DrawDebugGeometryOverlays( void ); |
|
virtual void NPCMovingToBusy( CAI_BaseNPC *pNPC ); |
|
virtual void NPCStartedBusy( CAI_BaseNPC *pNPC ); |
|
virtual void NPCAbortedMoveTo( CAI_BaseNPC *pNPC ); |
|
virtual void NPCFinishedBusy( CAI_BaseNPC *pNPC ); |
|
virtual void NPCStartedLeavingBusy( CAI_BaseNPC *pNPC ); |
|
|
|
virtual void InputActivate( inputdata_t &inputdata ); |
|
void InputPlayerStartedBlocking( inputdata_t &inputdata ); |
|
void InputPlayerStoppedBlocking( inputdata_t &inputdata ); |
|
void InputMoveQueueUp( inputdata_t &inputdata ); |
|
|
|
void PushNPCBackInQueue( CAI_BaseNPC *pNPC, int iStartingNode ); |
|
void RemoveNPCFromQueue( CAI_BaseNPC *pNPC ); |
|
void RecalculateQueueCount( void ); |
|
void QueueThink( void ); |
|
void MoveQueueUp( void ); |
|
void MoveQueueUpThink( void ); |
|
bool NodeIsOccupied( int i ); |
|
CAI_BaseNPC *GetNPCOnNode( int iNode ); |
|
CAI_ActBusyBehavior *GetQueueBehaviorForNPC( CAI_BaseNPC *pNPC ); |
|
|
|
DECLARE_DATADESC(); |
|
|
|
private: |
|
int m_iCurrentQueueCount; |
|
CHandle<CAI_Hint> m_hNodes[ MAX_QUEUE_NODES ]; |
|
bool m_bPlayerBlockedNodes[ MAX_QUEUE_NODES ]; |
|
EHANDLE m_hExitNode; |
|
EHANDLE m_hExitingNPC; |
|
bool m_bForceReachFront; |
|
|
|
// Read from mapdata |
|
string_t m_iszNodes[ MAX_QUEUE_NODES ]; |
|
string_t m_iszExitNode; |
|
|
|
// Outputs |
|
COutputInt m_OnQueueMoved; |
|
COutputEHANDLE m_OnNPCLeftQueue; |
|
COutputEHANDLE m_OnNPCStartedLeavingQueue; |
|
}; |
|
|
|
#endif // AI_BEHAVIOR_ACTBUSY_H
|
|
|