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.
383 lines
9.9 KiB
383 lines
9.9 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
//=============================================================================// |
|
|
|
#ifndef AI_BEHAVIOR_FOLLOW_H |
|
#define AI_BEHAVIOR_FOLLOW_H |
|
|
|
#include "simtimer.h" |
|
#include "ai_behavior.h" |
|
#include "ai_goalentity.h" |
|
#include "ai_utils.h" |
|
#include "ai_moveshoot.h" |
|
|
|
#ifdef HL2_EPISODIC |
|
#include "hl2_gamerules.h" |
|
#endif |
|
|
|
#if defined( _WIN32 ) |
|
#pragma once |
|
#endif |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// NOTE: these must correspond with the AI_FollowFormation_t array in AI_Behavior_Follow.cpp!! |
|
//----------------------------------------------------------------------------- |
|
enum AI_Formations_t |
|
{ |
|
AIF_SIMPLE, |
|
AIF_WIDE, |
|
AIF_ANTLION, |
|
AIF_COMMANDER, |
|
AIF_TIGHT, |
|
AIF_MEDIUM, |
|
AIF_SIDEKICK, |
|
AIF_HUNTER, |
|
AIF_VORTIGAUNT, |
|
}; |
|
|
|
enum AI_FollowFormationFlags_t |
|
{ |
|
AIFF_DEFAULT = 0, |
|
AIFF_USE_FOLLOW_POINTS = 0x01, |
|
AIFF_REQUIRE_LOS_OUTSIDE_COMBAT = 0x02, |
|
}; |
|
|
|
//----------------------------------------------------------------------------- |
|
// |
|
// CAI_FollowGoal |
|
// |
|
// Purpose: A level tool to control the follow behavior. Use is not required |
|
// in order to use behavior. |
|
// |
|
//----------------------------------------------------------------------------- |
|
|
|
class CAI_FollowGoal : public CAI_GoalEntity |
|
{ |
|
DECLARE_CLASS( CAI_FollowGoal, CAI_GoalEntity ); |
|
|
|
public: |
|
|
|
virtual void EnableGoal( CAI_BaseNPC *pAI ); |
|
virtual void DisableGoal( CAI_BaseNPC *pAI ); |
|
#ifdef HL2_EPISODIC |
|
virtual void InputOutsideTransition( inputdata_t &inputdata ); |
|
#endif |
|
|
|
int m_iFormation; |
|
|
|
DECLARE_DATADESC(); |
|
}; |
|
|
|
//----------------------------------------------------------------------------- |
|
|
|
int AIGetNumFollowers( CBaseEntity *pEntity, string_t iszClassname = NULL_STRING ); |
|
|
|
//----------------------------------------------------------------------------- |
|
|
|
struct AI_FollowNavInfo_t |
|
{ |
|
int flags; |
|
Vector position; |
|
float range; |
|
float Zrange; |
|
float tolerance; |
|
float followPointTolerance; |
|
float targetMoveTolerance; |
|
float repathOnRouteTolerance; |
|
float walkTolerance; |
|
float coverTolerance; |
|
float enemyLOSTolerance; |
|
float chaseEnemyTolerance; |
|
|
|
DECLARE_SIMPLE_DATADESC(); |
|
}; |
|
|
|
struct AI_FollowGroup_t; |
|
|
|
struct AI_FollowManagerInfoHandle_t |
|
{ |
|
AI_FollowGroup_t *m_pGroup; |
|
intp m_hFollower; |
|
}; |
|
|
|
//------------------------------------- |
|
|
|
struct AI_FollowParams_t |
|
{ |
|
AI_FollowParams_t( AI_Formations_t formation = AIF_SIMPLE, bool bNormalMemoryDiscard = false ) |
|
: formation(formation), |
|
bNormalMemoryDiscard( bNormalMemoryDiscard ) |
|
{ |
|
} |
|
|
|
AI_Formations_t formation; |
|
bool bNormalMemoryDiscard; |
|
|
|
DECLARE_SIMPLE_DATADESC(); |
|
}; |
|
|
|
//------------------------------------- |
|
|
|
class CAI_FollowBehavior : public CAI_SimpleBehavior |
|
{ |
|
DECLARE_CLASS( CAI_FollowBehavior, CAI_SimpleBehavior ); |
|
public: |
|
CAI_FollowBehavior( const AI_FollowParams_t ¶ms = AIF_SIMPLE ); |
|
~CAI_FollowBehavior(); |
|
|
|
virtual int DrawDebugTextOverlays( int text_offset ); |
|
virtual void DrawDebugGeometryOverlays(); |
|
|
|
// Returns true if the NPC is actively following a target. |
|
bool IsActive( void ); |
|
|
|
void SetParameters( const AI_FollowParams_t ¶ms ); |
|
|
|
virtual const char *GetName() { return "Follow"; } |
|
AI_Formations_t GetFormation() const { return m_params.formation; } |
|
|
|
virtual bool CanSelectSchedule(); |
|
|
|
const AI_FollowNavInfo_t &GetFollowGoalInfo(); |
|
CBaseEntity * GetFollowTarget(); |
|
void SetFollowTarget( CBaseEntity *pLeader, bool fFinishCurSchedule = false ); |
|
|
|
CAI_FollowGoal *GetFollowGoal() { return m_hFollowGoalEnt; } // if any |
|
bool SetFollowGoal( CAI_FollowGoal *pGoal, bool fFinishCurSchedule = false ); |
|
void ClearFollowGoal( CAI_FollowGoal *pGoal ); |
|
void SetFollowGoalDirect( CAI_FollowGoal *pGoal ); |
|
|
|
virtual bool FarFromFollowTarget() { return ( m_hFollowTarget && (GetAbsOrigin() - m_hFollowTarget->GetAbsOrigin()).LengthSqr() > (75*12)*(75*12) ); } |
|
|
|
virtual bool TargetIsUnreachable() { return m_bTargetUnreachable; } |
|
|
|
int GetNumFailedFollowAttempts() { return m_nFailedFollowAttempts; } |
|
float GetTimeFailFollowStarted() { return m_flTimeFailFollowStarted; } |
|
bool FollowTargetVisible() { return HasCondition( COND_FOLLOW_TARGET_VISIBLE ); }; |
|
|
|
bool IsMovingToFollowTarget(); |
|
|
|
float GetGoalRange(); |
|
float GetGoalZRange(); |
|
|
|
virtual Activity NPC_TranslateActivity( Activity activity ); |
|
virtual int TranslateSchedule( int scheduleType ); |
|
virtual void StartTask( const Task_t *pTask ); |
|
virtual int SelectFailSchedule( int failedSchedule, int failedTask, AI_TaskFailureCode_t taskFailCode ); |
|
virtual void TaskComplete( bool fIgnoreSetFailedCondition = false ); |
|
virtual void GatherConditions(); |
|
|
|
protected: |
|
|
|
const Vector &GetGoalPosition(); |
|
|
|
virtual bool ShouldFollow(); |
|
|
|
friend class CAI_FollowManager; |
|
|
|
virtual void BeginScheduleSelection(); |
|
virtual void EndScheduleSelection(); |
|
|
|
virtual void CleanupOnDeath( CBaseEntity *pCulprit, bool bFireDeathOutput ); |
|
|
|
virtual void Precache(); |
|
virtual int SelectSchedule(); |
|
virtual int FollowCallBaseSelectSchedule() { return BaseClass::SelectSchedule(); } |
|
virtual void OnStartSchedule( int scheduleType ); |
|
virtual void RunTask( const Task_t *pTask ); |
|
void BuildScheduleTestBits(); |
|
|
|
bool IsCurScheduleFollowSchedule(); |
|
|
|
virtual bool IsCurTaskContinuousMove(); |
|
virtual void OnMovementFailed(); |
|
virtual void OnMovementComplete(); |
|
virtual bool FValidateHintType( CAI_Hint *pHint ); |
|
|
|
bool IsValidCover( const Vector &vLocation, CAI_Hint const *pHint ); |
|
bool IsValidShootPosition( const Vector &vLocation, CAI_Node *pNode, CAI_Hint const *pHint ); |
|
bool FindCoverFromEnemyAtFollowTarget( float coverRadius, Vector *pResult ); |
|
|
|
bool ShouldAlwaysThink(); |
|
|
|
bool ShouldMoveToFollowTarget(); |
|
|
|
int SelectScheduleManagePosition(); |
|
int SelectScheduleFollowPoints(); |
|
int SelectScheduleMoveToFormation(); |
|
|
|
void GetFollowTargetViewLoc( Vector *pResult); |
|
bool ValidateFaceTarget( Vector *pFaceTarget ); |
|
|
|
//---------------------------- |
|
|
|
bool ShouldUseFollowPoints(); |
|
bool HasFollowPoint(); |
|
void SetFollowPoint( CAI_Hint *pHintNode ); |
|
void ClearFollowPoint(); |
|
const Vector & GetFollowPoint(); |
|
CAI_Hint * FindFollowPoint(); |
|
bool IsFollowPointInRange(); |
|
bool ShouldIgnoreFollowPointFacing(); |
|
|
|
//---------------------------- |
|
|
|
bool UpdateFollowPosition(); |
|
const int GetGoalFlags(); |
|
float GetGoalTolerance(); |
|
bool PlayerIsPushing(); |
|
|
|
bool IsFollowTargetInRange( float rangeMultiplier = 1.0 ); |
|
|
|
bool IsFollowGoalInRange( float tolerance, float zTolerance, int flags ); |
|
virtual bool IsChaseGoalInRange(); |
|
|
|
void NoteFailedFollow(); |
|
void NoteSuccessfulFollow(); |
|
|
|
//---------------------------- |
|
|
|
protected: |
|
|
|
enum |
|
{ |
|
SCHED_FOLLOWER_MOVE_AWAY_FAIL = BaseClass::NEXT_SCHEDULE, // Turn back toward player |
|
SCHED_FOLLOWER_MOVE_AWAY_END, |
|
SCHED_FOLLOW, |
|
SCHED_FOLLOWER_IDLE_STAND, |
|
SCHED_MOVE_TO_FACE_FOLLOW_TARGET, |
|
SCHED_FACE_FOLLOW_TARGET, |
|
SCHED_FOLLOWER_GO_TO_WAIT_POINT, |
|
SCHED_FOLLOWER_GO_TO_WAIT_POINT_FAIL, |
|
SCHED_FOLLOWER_STAND_AT_WAIT_POINT, |
|
SCHED_FOLLOWER_COMBAT_FACE, |
|
NEXT_SCHEDULE, |
|
|
|
TASK_CANT_FOLLOW = BaseClass::NEXT_TASK, |
|
TASK_FACE_FOLLOW_TARGET, |
|
TASK_MOVE_TO_FOLLOW_POSITION, |
|
TASK_GET_PATH_TO_FOLLOW_POSITION, |
|
TASK_SET_FOLLOW_TARGET_MARK, |
|
TASK_FOLLOWER_FACE_TACTICAL, |
|
TASK_SET_FOLLOW_DELAY, |
|
TASK_GET_PATH_TO_FOLLOW_POINT, |
|
TASK_ARRIVE_AT_FOLLOW_POINT, |
|
TASK_SET_FOLLOW_POINT_STAND_SCHEDULE, |
|
TASK_BEGIN_STAND_AT_WAIT_POINT, |
|
NEXT_TASK, |
|
|
|
COND_TARGET_MOVED_FROM_MARK = BaseClass::NEXT_CONDITION, |
|
COND_FOUND_WAIT_POINT, |
|
COND_FOLLOW_DELAY_EXPIRED, |
|
COND_FOLLOW_TARGET_VISIBLE, |
|
COND_FOLLOW_TARGET_NOT_VISIBLE, |
|
COND_FOLLOW_WAIT_POINT_INVALID, |
|
COND_FOLLOW_PLAYER_IS_LIT, |
|
COND_FOLLOW_PLAYER_IS_NOT_LIT, |
|
NEXT_CONDITION, |
|
}; |
|
|
|
DEFINE_CUSTOM_SCHEDULE_PROVIDER; |
|
|
|
protected: |
|
|
|
//---------------------------- |
|
|
|
EHANDLE m_hFollowTarget; |
|
AI_FollowNavInfo_t m_FollowNavGoal; |
|
float m_flTimeUpdatedFollowPosition; |
|
bool m_bFirstFacing; |
|
float m_flTimeFollowTargetVisible; |
|
|
|
CAI_MoveMonitor m_TargetMonitor; |
|
bool m_bTargetUnreachable; |
|
bool m_bFollowNavFailed; // Set when pathfinding fails to limit impact of m_FollowDelay on ShouldFollow |
|
|
|
int m_nFailedFollowAttempts; |
|
float m_flTimeFailFollowStarted; |
|
Vector m_vFollowMoveAnchor; |
|
|
|
bool m_bMovingToCover; |
|
float m_flOriginalEnemyDiscardTime; |
|
float m_SavedDistTooFar; |
|
|
|
CRandStopwatch m_FollowDelay; |
|
CSimpleSimTimer m_RepathOnFollowTimer; |
|
|
|
//--------------------------------- |
|
|
|
Activity m_CurrentFollowActivity; |
|
|
|
//--------------------------------- |
|
|
|
CRandSimTimer m_TimeBlockUseWaitPoint; |
|
CSimTimer m_TimeCheckForWaitPoint; |
|
CAI_Hint * m_pInterruptWaitPoint; |
|
|
|
//--------------------------------- |
|
|
|
CRandSimTimer m_TimeBeforeSpreadFacing; |
|
CRandSimTimer m_TimeNextSpreadFacing; |
|
|
|
//--------------------------------- |
|
|
|
AI_FollowManagerInfoHandle_t m_hFollowManagerInfo; |
|
AI_FollowParams_t m_params; |
|
|
|
//--------------------------------- |
|
|
|
CHandle<CAI_FollowGoal> m_hFollowGoalEnt; |
|
|
|
//--------------------------------- |
|
|
|
DECLARE_DATADESC(); |
|
}; |
|
|
|
//------------------------------------- |
|
|
|
inline const AI_FollowNavInfo_t &CAI_FollowBehavior::GetFollowGoalInfo() |
|
{ |
|
return m_FollowNavGoal; |
|
} |
|
|
|
//------------------------------------- |
|
|
|
inline const int CAI_FollowBehavior::GetGoalFlags() |
|
{ |
|
return m_FollowNavGoal.flags; |
|
} |
|
|
|
//------------------------------------- |
|
|
|
inline const Vector &CAI_FollowBehavior::GetGoalPosition() |
|
{ |
|
return m_FollowNavGoal.position; |
|
} |
|
|
|
//------------------------------------- |
|
|
|
inline float CAI_FollowBehavior::GetGoalTolerance() |
|
{ |
|
return m_FollowNavGoal.tolerance; |
|
} |
|
|
|
//------------------------------------- |
|
|
|
inline float CAI_FollowBehavior::GetGoalRange() |
|
{ |
|
return m_FollowNavGoal.range; |
|
} |
|
|
|
//------------------------------------- |
|
|
|
inline float CAI_FollowBehavior::GetGoalZRange() |
|
{ |
|
return m_FollowNavGoal.Zrange; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
|
|
#endif // AI_BEHAVIOR_FOLLOW_H
|
|
|