277 lines
7.6 KiB
C
277 lines
7.6 KiB
C
|
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||
|
//
|
||
|
// Purpose: Squad classes
|
||
|
//
|
||
|
//=============================================================================//
|
||
|
|
||
|
#ifndef AI_SQUAD_H
|
||
|
#define AI_SQUAD_H
|
||
|
|
||
|
#include "ai_memory.h"
|
||
|
#include "ai_squadslot.h"
|
||
|
#include "bitstring.h"
|
||
|
|
||
|
class CAI_Squad;
|
||
|
typedef CHandle<CAI_BaseNPC> AIHANDLE;
|
||
|
|
||
|
#define PER_ENEMY_SQUADSLOTS 1
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
DECLARE_POINTER_HANDLE(AISquadsIter_t);
|
||
|
DECLARE_POINTER_HANDLE(AISquadIter_t);
|
||
|
|
||
|
#define MAX_SQUAD_MEMBERS 16
|
||
|
#define MAX_SQUAD_DATA_SLOTS 4
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// CAI_SquadManager
|
||
|
//
|
||
|
// Purpose: Manages all the squads in the system
|
||
|
//
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
class CAI_SquadManager
|
||
|
{
|
||
|
public:
|
||
|
CAI_SquadManager()
|
||
|
{
|
||
|
m_pSquads = NULL;
|
||
|
}
|
||
|
|
||
|
CAI_Squad * GetFirstSquad( AISquadsIter_t *pIter );
|
||
|
CAI_Squad * GetNextSquad( AISquadsIter_t *pIter );
|
||
|
int NumSquads();
|
||
|
|
||
|
CAI_Squad * FindSquad( string_t squadName ); // Returns squad of the given name
|
||
|
CAI_Squad * CreateSquad( string_t squadName ); // Returns squad of the given name
|
||
|
CAI_Squad * FindCreateSquad( string_t squadName ); // Returns squad of the given name
|
||
|
CAI_Squad * FindCreateSquad( CAI_BaseNPC *pNPC, string_t squadName ); // Returns squad of the given name
|
||
|
|
||
|
void DeleteSquad( CAI_Squad *pSquad );
|
||
|
void DeleteAllSquads(void);
|
||
|
|
||
|
private:
|
||
|
|
||
|
CAI_Squad * m_pSquads; // A linked list of all squads
|
||
|
|
||
|
};
|
||
|
|
||
|
//-------------------------------------
|
||
|
|
||
|
extern CAI_SquadManager g_AI_SquadManager;
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
#ifdef PER_ENEMY_SQUADSLOTS
|
||
|
|
||
|
struct AISquadEnemyInfo_t
|
||
|
{
|
||
|
EHANDLE hEnemy;
|
||
|
CBitVec<MAX_SQUADSLOTS> slots; // What squad slots are filled?
|
||
|
|
||
|
DECLARE_SIMPLE_DATADESC();
|
||
|
};
|
||
|
|
||
|
#endif
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// CAI_Squad
|
||
|
//
|
||
|
// Purpose: Tracks enemies, squad slots, squad members
|
||
|
//
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
class CAI_Squad
|
||
|
{
|
||
|
public:
|
||
|
|
||
|
const char * GetName() const { return STRING(m_Name); }
|
||
|
|
||
|
void RemoveFromSquad( CAI_BaseNPC *pNPC, bool bDeath = false );
|
||
|
|
||
|
CAI_BaseNPC * GetFirstMember( AISquadIter_t *pIter = NULL, bool bIgnoreSilentMembers = true );
|
||
|
CAI_BaseNPC * GetNextMember( AISquadIter_t *pIter, bool bIgnoreSilentMembers = true );
|
||
|
CAI_BaseNPC * GetAnyMember();
|
||
|
int NumMembers( bool bIgnoreSilentMembers = true );
|
||
|
int GetSquadIndex( CAI_BaseNPC * );
|
||
|
|
||
|
void SquadNewEnemy ( CBaseEntity *pEnemy );
|
||
|
void UpdateEnemyMemory( CAI_BaseNPC *pUpdater, CBaseEntity *pEnemy, const Vector &position );
|
||
|
|
||
|
bool OccupyStrategySlotRange( CBaseEntity *pEnemy, int slotIDStart, int slotIDEnd, int *pSlot );
|
||
|
void VacateStrategySlot( CBaseEntity *pEnemy, int slot);
|
||
|
bool IsStrategySlotRangeOccupied( CBaseEntity *pEnemy, int slotIDStart, int slotIDEnd );
|
||
|
|
||
|
CAI_BaseNPC * SquadMemberInRange( const Vector &vecLocation, float flDist );
|
||
|
CAI_BaseNPC * NearestSquadMember( CAI_BaseNPC *pMember );
|
||
|
int GetVisibleSquadMembers( CAI_BaseNPC *pMember );
|
||
|
CAI_BaseNPC * GetSquadMemberNearestTo( const Vector &vecLocation );
|
||
|
bool SquadIsMember( CBaseEntity *pMember );
|
||
|
bool IsLeader( CAI_BaseNPC *pLeader );
|
||
|
CAI_BaseNPC *GetLeader( void );
|
||
|
|
||
|
int BroadcastInteraction( int interactionType, void *data, CBaseCombatCharacter *sender = NULL );
|
||
|
|
||
|
void AddToSquad(CAI_BaseNPC *pNPC);
|
||
|
bool FOkToMakeSound( int soundPriority );
|
||
|
void JustMadeSound( int soundPriority, float time );
|
||
|
float GetSquadSoundWaitTime() const { return m_flSquadSoundWaitTime; }
|
||
|
void SetSquadSoundWaitTime( float time ) { m_flSquadSoundWaitTime = time; }
|
||
|
void SquadRemember( int iMemory );
|
||
|
|
||
|
void SetSquadInflictor( CBaseEntity *pInflictor );
|
||
|
bool IsSquadInflictor( CBaseEntity *pInflictor );
|
||
|
|
||
|
static bool IsSilentMember( const CAI_BaseNPC *pNPC );
|
||
|
|
||
|
template <typename T>
|
||
|
void SetSquadData( unsigned slot, const T &data )
|
||
|
{
|
||
|
Assert( slot < MAX_SQUAD_DATA_SLOTS );
|
||
|
if ( slot < MAX_SQUAD_DATA_SLOTS )
|
||
|
{
|
||
|
m_SquadData[slot] = *((int *)&data);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
template <typename T>
|
||
|
void GetSquadData( unsigned slot, T *pData )
|
||
|
{
|
||
|
Assert( slot < MAX_SQUAD_DATA_SLOTS );
|
||
|
if ( slot < MAX_SQUAD_DATA_SLOTS )
|
||
|
{
|
||
|
*pData = *((T *)&m_SquadData[slot]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
private:
|
||
|
void OccupySlot( CBaseEntity *pEnemy, int i );
|
||
|
void VacateSlot( CBaseEntity *pEnemy, int i );
|
||
|
bool IsSlotOccupied( CBaseEntity *pEnemy, int i ) const;
|
||
|
|
||
|
private:
|
||
|
friend class CAI_SaveRestoreBlockHandler;
|
||
|
friend class CAI_SquadManager;
|
||
|
|
||
|
CAI_Squad();
|
||
|
CAI_Squad(string_t squadName);
|
||
|
~CAI_Squad(void);
|
||
|
|
||
|
CAI_Squad* GetNext() { return m_pNextSquad; }
|
||
|
|
||
|
void Init( string_t squadName );
|
||
|
|
||
|
CAI_Squad * m_pNextSquad; // The next squad is list of all squads
|
||
|
|
||
|
string_t m_Name;
|
||
|
CUtlVectorFixed<AIHANDLE, MAX_SQUAD_MEMBERS> m_SquadMembers;
|
||
|
|
||
|
float m_flSquadSoundWaitTime; // Time when I'm allowed to make another sound
|
||
|
int m_nSquadSoundPriority; // if we're still waiting, this is the priority of the current sound
|
||
|
|
||
|
EHANDLE m_hSquadInflictor;
|
||
|
|
||
|
int m_SquadData[MAX_SQUAD_DATA_SLOTS];
|
||
|
|
||
|
#ifdef PER_ENEMY_SQUADSLOTS
|
||
|
|
||
|
AISquadEnemyInfo_t *FindEnemyInfo( CBaseEntity *pEnemy );
|
||
|
const AISquadEnemyInfo_t *FindEnemyInfo( CBaseEntity *pEnemy ) const { return const_cast<CAI_Squad *>(this)->FindEnemyInfo( pEnemy ); }
|
||
|
|
||
|
AISquadEnemyInfo_t * m_pLastFoundEnemyInfo; // Occupy/Vacate need to be reworked to not want this
|
||
|
|
||
|
CUtlVector<AISquadEnemyInfo_t> m_EnemyInfos;
|
||
|
float m_flEnemyInfoCleanupTime;
|
||
|
|
||
|
#else
|
||
|
|
||
|
CVarBitVec m_squadSlotsUsed; // What squad slots are filled?
|
||
|
|
||
|
#endif
|
||
|
|
||
|
//---------------------------------
|
||
|
public:
|
||
|
DECLARE_SIMPLE_DATADESC();
|
||
|
};
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
//
|
||
|
// Purpose: CAI_SquadManager inline functions
|
||
|
//
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
inline CAI_Squad *CAI_SquadManager::GetFirstSquad( AISquadsIter_t *pIter )
|
||
|
{
|
||
|
*pIter = (AISquadsIter_t)m_pSquads;
|
||
|
return m_pSquads;
|
||
|
}
|
||
|
|
||
|
//-------------------------------------
|
||
|
|
||
|
inline CAI_Squad *CAI_SquadManager::GetNextSquad( AISquadsIter_t *pIter )
|
||
|
{
|
||
|
CAI_Squad *pSquad = (CAI_Squad *)*pIter;
|
||
|
if ( pSquad )
|
||
|
pSquad = pSquad->m_pNextSquad;
|
||
|
*pIter = (AISquadsIter_t)pSquad;
|
||
|
return pSquad;
|
||
|
}
|
||
|
|
||
|
//-------------------------------------
|
||
|
// Purpose: Returns squad of the given name or creates a new squad with the
|
||
|
// given name if none exists and add pNPC to the list of members
|
||
|
//-------------------------------------
|
||
|
|
||
|
inline CAI_Squad *CAI_SquadManager::FindCreateSquad(CAI_BaseNPC *pNPC, string_t squadName)
|
||
|
{
|
||
|
CAI_Squad* pSquad = FindSquad( squadName );
|
||
|
|
||
|
if ( !pSquad )
|
||
|
pSquad = CreateSquad( squadName );
|
||
|
|
||
|
pSquad->AddToSquad( pNPC );
|
||
|
|
||
|
return pSquad;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
inline CAI_Squad *CAI_SquadManager::FindCreateSquad(string_t squadName)
|
||
|
{
|
||
|
CAI_Squad* pSquad = FindSquad( squadName );
|
||
|
|
||
|
if ( !pSquad )
|
||
|
pSquad = CreateSquad( squadName );
|
||
|
|
||
|
return pSquad;
|
||
|
}
|
||
|
|
||
|
//-------------------------------------
|
||
|
|
||
|
inline CAI_BaseNPC *CAI_Squad::GetAnyMember()
|
||
|
{
|
||
|
if ( m_SquadMembers.Count() )
|
||
|
return m_SquadMembers[random->RandomInt( 0, m_SquadMembers.Count()-1 )];
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
//-------------------------------------
|
||
|
|
||
|
inline int CAI_Squad::GetSquadIndex( CAI_BaseNPC *pAI )
|
||
|
{
|
||
|
for ( int i = 0; i < m_SquadMembers.Count(); i++ )
|
||
|
{
|
||
|
if ( m_SquadMembers[i] == pAI )
|
||
|
return i;
|
||
|
}
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
|
||
|
#endif // AI_SQUAD_H
|