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.
300 lines
7.2 KiB
300 lines
7.2 KiB
5 years ago
|
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||
|
//
|
||
|
// Purpose:
|
||
|
//
|
||
|
//=============================================================================//
|
||
|
|
||
|
#ifndef AI_BEHAVIOR_ASSAULT_H
|
||
|
#define AI_BEHAVIOR_ASSAULT_H
|
||
|
#ifdef _WIN32
|
||
|
#pragma once
|
||
|
#endif
|
||
|
|
||
|
#include "simtimer.h"
|
||
|
#include "ai_behavior.h"
|
||
|
#include "ai_goalentity.h"
|
||
|
#include "ai_moveshoot.h"
|
||
|
#include "ai_utils.h"
|
||
|
|
||
|
#define CUE_POINT_TOLERANCE (3.0*12.0)
|
||
|
|
||
|
enum RallySelectMethod_t
|
||
|
{
|
||
|
RALLY_POINT_SELECT_DEFAULT = 0,
|
||
|
RALLY_POINT_SELECT_RANDOM,
|
||
|
};
|
||
|
|
||
|
enum AssaultCue_t
|
||
|
{
|
||
|
CUE_NO_ASSAULT = 0, // used to indicate that no assault is being conducted presently
|
||
|
|
||
|
CUE_ENTITY_INPUT = 1,
|
||
|
CUE_PLAYER_GUNFIRE,
|
||
|
CUE_DONT_WAIT,
|
||
|
CUE_COMMANDER,
|
||
|
CUE_NONE,
|
||
|
};
|
||
|
|
||
|
enum
|
||
|
{
|
||
|
ASSAULT_SENTENCE_HIT_RALLY_POINT = SENTENCE_BASE_BEHAVIOR_INDEX,
|
||
|
ASSAULT_SENTENCE_HIT_ASSAULT_POINT,
|
||
|
ASSAULT_SENTENCE_SQUAD_ADVANCE_TO_RALLY,
|
||
|
ASSAULT_SENTENCE_SQUAD_ADVANCE_TO_ASSAULT,
|
||
|
ASSAULT_SENTENCE_COVER_NO_AMMO,
|
||
|
ASSAULT_SENTENCE_UNDER_ATTACK,
|
||
|
};
|
||
|
|
||
|
// Allow diversion from the assault up to this amount of time after last having an enemy
|
||
|
#define ASSAULT_DIVERSION_TIME 4
|
||
|
|
||
|
#define SF_ASSAULTPOINT_CLEARONARRIVAL 0x00000001
|
||
|
|
||
|
//=============================================================================
|
||
|
//=============================================================================
|
||
|
class CRallyPoint : public CPointEntity
|
||
|
{
|
||
|
DECLARE_CLASS( CRallyPoint, CPointEntity );
|
||
|
|
||
|
public:
|
||
|
CRallyPoint()
|
||
|
{
|
||
|
m_hLockedBy.Set(NULL);
|
||
|
m_sExclusivity = RALLY_EXCLUSIVE_NOT_EVALUATED;
|
||
|
}
|
||
|
|
||
|
bool Lock( CBaseEntity *pLocker )
|
||
|
{
|
||
|
if( IsLocked() )
|
||
|
{
|
||
|
// Already locked.
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
m_hLockedBy.Set( pLocker );
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool Unlock( CBaseEntity *pUnlocker )
|
||
|
{
|
||
|
if( IsLocked() )
|
||
|
{
|
||
|
if( m_hLockedBy.Get() != pUnlocker )
|
||
|
{
|
||
|
// Refuse! Only the locker may unlock.
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
m_hLockedBy.Set( NULL );
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool IsLocked( void ) { return (m_hLockedBy.Get() != NULL); }
|
||
|
|
||
|
int DrawDebugTextOverlays();
|
||
|
bool IsExclusive();
|
||
|
|
||
|
enum
|
||
|
{
|
||
|
RALLY_EXCLUSIVE_NOT_EVALUATED = -1,
|
||
|
RALLY_EXCLUSIVE_NO,
|
||
|
RALLY_EXCLUSIVE_YES,
|
||
|
};
|
||
|
|
||
|
string_t m_AssaultPointName;
|
||
|
string_t m_RallySequenceName;
|
||
|
float m_flAssaultDelay;
|
||
|
int m_iPriority;
|
||
|
int m_iStrictness;
|
||
|
bool m_bForceCrouch;
|
||
|
bool m_bIsUrgent;
|
||
|
short m_sExclusivity;
|
||
|
|
||
|
COutputEvent m_OnArrival;
|
||
|
|
||
|
DECLARE_DATADESC();
|
||
|
|
||
|
private:
|
||
|
EHANDLE m_hLockedBy;
|
||
|
};
|
||
|
|
||
|
//=============================================================================
|
||
|
//=============================================================================
|
||
|
class CAssaultPoint : public CPointEntity
|
||
|
{
|
||
|
DECLARE_CLASS( CAssaultPoint, CPointEntity );
|
||
|
|
||
|
public:
|
||
|
CAssaultPoint()
|
||
|
{
|
||
|
// This used to be a constant in code. Now it's a keyfield in hammer.
|
||
|
// So in the constructor, we set this value to the former constant
|
||
|
// default value, for legacy maps. (sjb)
|
||
|
m_flAssaultPointTolerance = CUE_POINT_TOLERANCE;
|
||
|
}
|
||
|
|
||
|
void InputSetClearOnContact( inputdata_t &inputdata )
|
||
|
{
|
||
|
m_bClearOnContact = inputdata.value.Bool();
|
||
|
}
|
||
|
|
||
|
void InputSetAllowDiversion( inputdata_t &inputdata )
|
||
|
{
|
||
|
m_bAllowDiversion = inputdata.value.Bool();
|
||
|
}
|
||
|
|
||
|
void InputSetForceClear( inputdata_t &inputdata )
|
||
|
{
|
||
|
m_bInputForcedClear = inputdata.value.Bool();
|
||
|
}
|
||
|
|
||
|
public:
|
||
|
string_t m_AssaultHintGroup;
|
||
|
string_t m_NextAssaultPointName;
|
||
|
COutputEvent m_OnAssaultClear;
|
||
|
float m_flAssaultTimeout;
|
||
|
bool m_bClearOnContact;
|
||
|
bool m_bAllowDiversion;
|
||
|
float m_flAllowDiversionRadius;
|
||
|
bool m_bNeverTimeout;
|
||
|
int m_iStrictness;
|
||
|
bool m_bForceCrouch;
|
||
|
bool m_bIsUrgent;
|
||
|
bool m_bInputForcedClear;
|
||
|
float m_flAssaultPointTolerance;
|
||
|
float m_flTimeLastUsed;
|
||
|
|
||
|
COutputEvent m_OnArrival;
|
||
|
|
||
|
DECLARE_DATADESC();
|
||
|
};
|
||
|
|
||
|
//=============================================================================
|
||
|
//=============================================================================
|
||
|
class CAI_AssaultBehavior : public CAI_SimpleBehavior
|
||
|
{
|
||
|
DECLARE_CLASS( CAI_AssaultBehavior, CAI_SimpleBehavior );
|
||
|
|
||
|
public:
|
||
|
CAI_AssaultBehavior();
|
||
|
|
||
|
virtual const char *GetName() { return "Assault"; }
|
||
|
virtual int DrawDebugTextOverlays( int text_offset );
|
||
|
|
||
|
virtual void OnRestore();
|
||
|
|
||
|
bool CanRunAScriptedNPCInteraction( bool bForced );
|
||
|
|
||
|
virtual bool CanSelectSchedule();
|
||
|
virtual void BeginScheduleSelection();
|
||
|
virtual void EndScheduleSelection();
|
||
|
|
||
|
bool HasHitRallyPoint() { return m_bHitRallyPoint; }
|
||
|
bool HasHitAssaultPoint() { return m_bHitAssaultPoint; }
|
||
|
|
||
|
void ClearAssaultPoint( void );
|
||
|
void OnHitAssaultPoint( void );
|
||
|
bool PollAssaultCue( void );
|
||
|
void ReceiveAssaultCue( AssaultCue_t cue );
|
||
|
bool HasAssaultCue( void ) { return m_AssaultCue != CUE_NO_ASSAULT; }
|
||
|
bool AssaultHasBegun();
|
||
|
|
||
|
CAssaultPoint *FindAssaultPoint( string_t iszAssaultPointName );
|
||
|
void SetAssaultPoint( CAssaultPoint *pAssaultPoint );
|
||
|
|
||
|
void GatherConditions( void );
|
||
|
void StartTask( const Task_t *pTask );
|
||
|
void RunTask( const Task_t *pTask );
|
||
|
void BuildScheduleTestBits();
|
||
|
int TranslateSchedule( int scheduleType );
|
||
|
void OnStartSchedule( int scheduleType );
|
||
|
void ClearSchedule( const char *szReason );
|
||
|
|
||
|
void InitializeBehavior();
|
||
|
void SetParameters( string_t rallypointname, AssaultCue_t assaultcue, int rallySelectMethod );
|
||
|
void SetParameters( CBaseEntity *pRallyEnt, AssaultCue_t assaultcue );
|
||
|
|
||
|
bool IsAllowedToDivert( void );
|
||
|
bool IsValidShootPosition( const Vector &vLocation, CAI_Node *pNode, CAI_Hint const *pHint );
|
||
|
float GetMaxTacticalLateralMovement( void );
|
||
|
|
||
|
void UpdateOnRemove();
|
||
|
|
||
|
bool OnStrictAssault( void );
|
||
|
bool UpdateForceCrouch( void );
|
||
|
bool IsForcingCrouch( void );
|
||
|
bool IsUrgent( void );
|
||
|
|
||
|
CRallyPoint *FindBestRallyPointInRadius( const Vector &vecCenter, float flRadius );;
|
||
|
|
||
|
void Disable( void ) { m_AssaultCue = CUE_NO_ASSAULT; m_bHitRallyPoint = false; m_bHitAssaultPoint = false; }
|
||
|
|
||
|
enum
|
||
|
{
|
||
|
SCHED_MOVE_TO_RALLY_POINT = BaseClass::NEXT_SCHEDULE, // Try to get out of the player's way
|
||
|
SCHED_ASSAULT_FAILED_TO_MOVE,
|
||
|
SCHED_FAIL_MOVE_TO_RALLY_POINT,
|
||
|
SCHED_MOVE_TO_ASSAULT_POINT,
|
||
|
SCHED_AT_ASSAULT_POINT,
|
||
|
SCHED_HOLD_RALLY_POINT,
|
||
|
SCHED_HOLD_ASSAULT_POINT,
|
||
|
SCHED_WAIT_AND_CLEAR,
|
||
|
SCHED_ASSAULT_MOVE_AWAY,
|
||
|
SCHED_CLEAR_ASSAULT_POINT,
|
||
|
NEXT_SCHEDULE,
|
||
|
|
||
|
TASK_GET_PATH_TO_RALLY_POINT = BaseClass::NEXT_TASK,
|
||
|
TASK_FACE_RALLY_POINT,
|
||
|
TASK_GET_PATH_TO_ASSAULT_POINT,
|
||
|
TASK_FACE_ASSAULT_POINT,
|
||
|
TASK_HIT_ASSAULT_POINT,
|
||
|
TASK_HIT_RALLY_POINT,
|
||
|
TASK_AWAIT_CUE,
|
||
|
TASK_AWAIT_ASSAULT_TIMEOUT,
|
||
|
TASK_ANNOUNCE_CLEAR,
|
||
|
TASK_WAIT_ASSAULT_DELAY,
|
||
|
TASK_ASSAULT_MOVE_AWAY_PATH,
|
||
|
TASK_ASSAULT_DEFER_SCHEDULE_SELECTION,
|
||
|
NEXT_TASK,
|
||
|
|
||
|
/*
|
||
|
COND_PUT_CONDITIONS_HERE = BaseClass::NEXT_CONDITION,
|
||
|
NEXT_CONDITION,
|
||
|
*/
|
||
|
};
|
||
|
|
||
|
DEFINE_CUSTOM_SCHEDULE_PROVIDER;
|
||
|
|
||
|
public:
|
||
|
CHandle<CAssaultPoint> m_hAssaultPoint;
|
||
|
CHandle<CRallyPoint> m_hRallyPoint;
|
||
|
|
||
|
public:
|
||
|
void UnlockRallyPoint( void );
|
||
|
|
||
|
private:
|
||
|
void OnScheduleChange();
|
||
|
virtual int SelectSchedule();
|
||
|
|
||
|
AssaultCue_t m_AssaultCue; // the cue we're waiting for to begin the assault
|
||
|
AssaultCue_t m_ReceivedAssaultCue; // the last assault cue we received from someone/thing external.
|
||
|
|
||
|
bool m_bHitRallyPoint;
|
||
|
bool m_bHitAssaultPoint;
|
||
|
|
||
|
// Diversion
|
||
|
bool m_bDiverting;
|
||
|
float m_flLastSawAnEnemyAt;
|
||
|
|
||
|
float m_flTimeDeferScheduleSelection;
|
||
|
|
||
|
string_t m_AssaultPointName;
|
||
|
|
||
|
//---------------------------------
|
||
|
|
||
|
DECLARE_DATADESC();
|
||
|
};
|
||
|
|
||
|
#endif // AI_BEHAVIOR_ASSAULT_H
|