|
|
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Hint node utilities and functions.
//
// $NoKeywords: $
//=============================================================================//
#ifndef AI_HINT_H
#define AI_HINT_H
#pragma once
#include "ai_initutils.h"
#include "tier1/utlmap.h"
//Flags for FindHintNode
#define bits_HINT_NODE_NONE 0x00000000
#define bits_HINT_NODE_VISIBLE 0x00000001
#define bits_HINT_NODE_NEAREST 0x00000002 // Choose the node nearest me
#define bits_HINT_NODE_RANDOM 0x00000004 // Find a random hintnode meeting other criteria
#define bits_HINT_NODE_CLEAR 0x00000008 // Only choose nodes that have clear room for my bounding box (requires NPC)
#define bits_HINT_NODE_USE_GROUP 0x00000010 // Use the NPC's hintgroup when searching for a node (requires NPC)
#define bits_HINT_NODE_VISIBLE_TO_PLAYER 0x00000020
#define bits_HINT_NODE_NOT_VISIBLE_TO_PLAYER 0x00000040
#define bits_HINT_NODE_REPORT_FAILURES 0x00000080
#define bits_HINT_NODE_IN_VIEWCONE 0x00000100
#define bits_HINT_NODE_IN_AIMCONE 0x00000200
#define bits_HINT_NPC_IN_NODE_FOV 0x00000400 // Is the searcher inside the hint node's FOV?
#define bits_HINT_NOT_CLOSE_TO_ENEMY 0x00000800 // Hint must not be within 30 feet of my enemy
#define bits_HINT_HAS_LOS_TO_PLAYER 0x00001000 // Like VISIBLE_TO_PLAYER but doesn't care about player's facing
#define bits_HAS_EYEPOSITION_LOS_TO_PLAYER 0x00002000 // Like HAS LOS TO PLAYER, but checks NPC's eye position at the node, not node origin.
//-----------------------------------------------------------------------------
//
// hints - these MUST coincide with the HINTS listed under
// info_node in the FGD file!
//
// For debugging, they must also coincide with g_pszHintDescriptions.
//
//-----------------------------------------------------------------------------
enum Hint_e { HINT_ANY = -1, HINT_NONE = 0, HINT_NOT_USED_WORLD_DOOR, HINT_WORLD_WINDOW, HINT_NOT_USED_WORLD_BUTTON, HINT_NOT_USED_WORLD_MACHINERY, HINT_NOT_USED_WORLD_LEDGE, HINT_NOT_USED_WORLD_LIGHT_SOURCE, HINT_NOT_USED_WORLD_HEAT_SOURCE, HINT_NOT_USED_WORLD_BLINKING_LIGHT, HINT_NOT_USED_WORLD_BRIGHT_COLORS, HINT_NOT_USED_WORLD_HUMAN_BLOOD, HINT_NOT_USED_WORLD_ALIEN_BLOOD,
HINT_WORLD_WORK_POSITION, HINT_WORLD_VISUALLY_INTERESTING, HINT_WORLD_VISUALLY_INTERESTING_DONT_AIM, HINT_WORLD_INHIBIT_COMBINE_MINES, HINT_WORLD_VISUALLY_INTERESTING_STEALTH,
HINT_TACTICAL_COVER_MED = 100, HINT_TACTICAL_COVER_LOW, HINT_TACTICAL_SPAWN, HINT_TACTICAL_PINCH, // Exit / entrance to an arena
HINT_NOT_USED_TACTICAL_GUARD, HINT_TACTICAL_ENEMY_DISADVANTAGED, //Disadvantageous position for the enemy
HINT_NOT_USED_HEALTH_KIT,
HINT_NOT_USED_URBAN_STREETCORNER = 200, HINT_NOT_USED_URBAN_STREETLAMP, HINT_NOT_USED_URBAN_DARK_SPOT, HINT_NOT_USED_URBAN_POSTER, HINT_NOT_USED_URBAN_SHELTER,
HINT_NOT_USED_ASSASSIN_SECLUDED = 300, HINT_NOT_USED_ASSASSIN_RAFTERS, HINT_NOT_USED_ASSASSIN_GROUND, HINT_NOT_USED_ASSASSIN_MONKEYBARS,
HINT_ANTLION_BURROW_POINT = 400, HINT_ANTLION_THUMPER_FLEE_POINT,
HINT_HEADCRAB_BURROW_POINT = 450, HINT_HEADCRAB_EXIT_POD_POINT,
HINT_NOT_USED_ROLLER_PATROL_POINT = 500, HINT_NOT_USED_ROLLER_CLEANUP_POINT,
HINT_NOT_USED_PSTORM_ROCK_SPAWN = 600,
HINT_CROW_FLYTO_POINT = 700,
// TF2 Hints
HINT_BUG_PATROL_POINT = 800,
// HL2 Hints
HINT_FOLLOW_WAIT_POINT = 900, HINT_JUMP_OVERRIDE = 901, HINT_PLAYER_SQUAD_TRANSITON_POINT = 902, HINT_NPC_EXIT_POINT = 903, HINT_STRIDER_NODE = 904,
HINT_PLAYER_ALLY_MOVE_AWAY_DEST = 950, HINT_PLAYER_ALLY_FEAR_DEST,
// HL1 port hints
HINT_HL1_WORLD_MACHINERY = 1000, HINT_HL1_WORLD_BLINKING_LIGHT, HINT_HL1_WORLD_HUMAN_BLOOD, HINT_HL1_WORLD_ALIEN_BLOOD,
// CS port hints
HINT_CSTRIKE_HOSTAGE_ESCAPE = 1100, }; const char *GetHintTypeDescription( Hint_e iHintType ); const char *GetHintTypeDescription( CAI_Hint *pHint );
//-----------------------------------------------------------------------------
// CHintCriteria
//-----------------------------------------------------------------------------
class CHintCriteria { public:
CHintCriteria(); ~CHintCriteria();
bool HasFlag( int bitmask ) const { return ( m_iFlags & bitmask ) != 0; } void SetFlag( int bitmask ); void ClearFlag( int bitmask );
void SetGroup( string_t group ); string_t GetGroup( void ) const { return m_strGroup; }
int GetFirstHintType( void ) const { return m_iFirstHintType; } int GetLastHintType( void ) const { return m_iLastHintType; } bool MatchesHintType( int hintType ) const; bool MatchesSingleHintType() const;
bool HasIncludeZones( void ) const { return ( m_zoneInclude.Count() != 0 ); } bool HasExcludeZones( void ) const { return ( m_zoneExclude.Count() != 0 ); } void AddIncludePosition( const Vector &position, float radius ); void AddExcludePosition( const Vector &position, float radius ); void SetHintType( int hintType ); void SetHintTypeRange( int firstType, int lastType ); void AddHintType( int hintType );
bool InIncludedZone( const Vector &testPosition ) const; bool InExcludedZone( const Vector &testPosition ) const;
int NumHintTypes() const; int GetHintType( int idx ) const;
private:
struct hintZone_t { Vector position; float radiussqr; };
typedef CUtlVector < hintZone_t > zoneList_t;
void AddZone( zoneList_t &list, const Vector &position, float radius ); bool InZone( const zoneList_t &zone, const Vector &testPosition ) const;
CUtlVector<int> m_HintTypes;
int m_iFlags; int m_iFirstHintType; int m_iLastHintType; string_t m_strGroup; zoneList_t m_zoneInclude; zoneList_t m_zoneExclude; };
class CAI_Node;
//-----------------------------------------------------------------------------
// CAI_HintManager
//-----------------------------------------------------------------------------
DECLARE_POINTER_HANDLE(AIHintIter_t);
class CAIHintVector : public CUtlVector< CAI_Hint * > { public: CAIHintVector() : CUtlVector< CAI_Hint * >( 1, 0 ) { }
CAIHintVector( const CAIHintVector& src ) { CopyArray( src.Base(), src.Count() ); }
CAIHintVector &operator=( const CAIHintVector &src ) { CopyArray( src.Base(), src.Count() ); return *this; } };
class CAI_HintManager { friend class CAI_Hint; public: // Hint node creation
static CAI_Hint *CreateHint( HintNodeData *pNodeData, const char *pMapData = NULL ); static void DrawHintOverlays(float flDrawDuration);
static void AddHint( CAI_Hint *pTestHint ); static void RemoveHint( CAI_Hint *pTestHint ); static void AddHintByType( CAI_Hint *pHint ); static void RemoveHintByType( CAI_Hint *pHintToRemove );
// Interface for searching the hint node list
static CAI_Hint *FindHint( CAI_BaseNPC *pNPC, const Vector &position, const CHintCriteria &hintCriteria ); static CAI_Hint *FindHint( CAI_BaseNPC *pNPC, const CHintCriteria &hintCriteria ); static CAI_Hint *FindHint( const Vector &position, const CHintCriteria &hintCriteria ); static CAI_Hint *FindHint( CAI_BaseNPC *pNPC, Hint_e nHintType, int nFlags, float flMaxDist, const Vector *pMaxDistFrom = NULL );
// Purpose: Finds a random suitable hint within the requested radious of the npc
static CAI_Hint *FindHintRandom( CAI_BaseNPC *pNPC, const Vector &position, const CHintCriteria &hintCriteria ); static int FindAllHints( CAI_BaseNPC *pNPC, const Vector &position, const CHintCriteria &hintCriteria, CUtlVector<CAI_Hint *> *pResult ); static int FindAllHints( const Vector &position, const CHintCriteria &hintCriteria, CUtlVector<CAI_Hint *> *pResult ) { return FindAllHints( NULL, position, hintCriteria, pResult ); } static int FindAllHints( CAI_BaseNPC *pNPC, const CHintCriteria &hintCriteria, CUtlVector<CAI_Hint *> *pResult ) { return FindAllHints( pNPC, pNPC->GetAbsOrigin(), hintCriteria, pResult ); } static int GetFlags( const char *token );
static CAI_Hint *GetFirstHint( AIHintIter_t *pIter ); static CAI_Hint *GetNextHint( AIHintIter_t *pIter );
static void DumpHints();
static void ValidateHints();
private: enum { // MUST BE POWER OF 2
HINT_HISTORY = (1<<3), HINT_HISTORY_MASK = (HINT_HISTORY-1) };
static CAI_Hint *AddFoundHint( CAI_Hint *hint ); static int GetFoundHintCount(); static CAI_Hint *GetFoundHint( int index ); static CAI_Hint *GetLastFoundHint(); static void ResetFoundHints(); static bool IsInFoundHintList( CAI_Hint *hint );
static int gm_nFoundHintIndex; static CAI_Hint *gm_pLastFoundHints[ HINT_HISTORY ]; // Last used hint
static CAIHintVector gm_AllHints; // A linked list of all hints
static CUtlMap< int, CAIHintVector > gm_TypedHints; };
//-----------------------------------------------------------------------------
// CAI_Hint
//-----------------------------------------------------------------------------
class CAI_Hint : public CServerOnlyEntity { DECLARE_CLASS( CAI_Hint, CServerOnlyEntity ); public: CAI_Hint( void ); ~CAI_Hint( void );
// Interface for specific nodes
bool Lock( CBaseEntity *pNPC ); // Makes unavailable for hints
void Unlock( float delay = 0.0 ); // Makes available for hints after delay
bool IsLocked(void); // Whether this node is available for use.
bool IsLockedBy( CBaseEntity *pNPC ); // Whether this node is available for use.
void GetPosition(CBaseCombatCharacter *pBCC, Vector *vPosition); void GetPosition( Hull_t hull, Vector *vPosition ); Vector GetDirection( void ); float Yaw( void ); CAI_Node *GetNode( void ); string_t GetGroup( void ) const { return m_NodeData.strGroup; } CBaseEntity *User( void ) const { return m_hHintOwner; }; Hint_e HintType( void ) const { return (Hint_e)m_NodeData.nHintType; }; void SetHintType( int hintType, bool force = false ); string_t HintActivityName( void ) const { return m_NodeData.iszActivityName; } int GetTargetNode( void ) const { return m_nTargetNodeID; } bool IsDisabled( void ) const { return (m_NodeData.iDisabled != 0); } void SetDisabled( bool bDisabled ) { m_NodeData.iDisabled = bDisabled; } void DisableForSeconds( float flSeconds ); void EnableThink(); void FixupTargetNode(); void NPCStartedUsing( CAI_BaseNPC *pNPC ); void NPCStoppedUsing( CAI_BaseNPC *pNPC );
HintIgnoreFacing_t GetIgnoreFacing() const { return m_NodeData.fIgnoreFacing; }
NPC_STATE GetMinState() const { return m_NodeData.minState; } NPC_STATE GetMaxState() const { return m_NodeData.maxState; }
int GetNodeId() { return m_NodeData.nNodeID; } int GetWCId() { return m_NodeData.nWCNodeID; }
bool HintMatchesCriteria( CAI_BaseNPC *pNPC, const CHintCriteria &hintCriteria, const Vector &position, float *flNearestDistance, bool bIgnoreLock = false, bool bIgnoreHintType = false ); bool IsInNodeFOV( CBaseEntity *pOther );
private: void Spawn( void ); virtual void Activate(); virtual void UpdateOnRemove( void ); int DrawDebugTextOverlays(void); virtual int ObjectCaps( void ) { return (BaseClass::ObjectCaps() & ~FCAP_ACROSS_TRANSITION); } virtual void OnRestore(); bool IsViewable( void );
// Input handlers
void InputEnableHint( inputdata_t &inputdata ); void InputDisableHint( inputdata_t &inputdata );
private:
HintNodeData m_NodeData; int m_nTargetNodeID; EHANDLE m_hHintOwner; // Is hint locked (being used by NPC / NPC en-route to use it)
float m_flNextUseTime; // When can I be used again?
COutputEHANDLE m_OnNPCStartedUsing; // Triggered when an NPC has actively begun to use the node.
COutputEHANDLE m_OnNPCStoppedUsing; // Triggered when an NPC has finished using this node.
float m_nodeFOV; Vector m_vecForward;
// The next hint in list of all hints
friend class CAI_HintManager;
DECLARE_DATADESC(); };
#define SF_ALLOW_JUMP_UP 65536
#endif //AI_HINT_H
|