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.
299 lines
10 KiB
299 lines
10 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// tf_nav_area.h |
|
// TF specific nav area |
|
// Michael Booth, February 2009 |
|
|
|
#ifndef TF_NAV_AREA_H |
|
#define TF_NAV_AREA_H |
|
|
|
#include "nav_area.h" |
|
#include "tf_shareddefs.h" |
|
|
|
enum TFNavAttributeType |
|
{ |
|
TF_NAV_INVALID = 0x00000000, |
|
|
|
// Also look for NAV_MESH_NAV_BLOCKER (w/ nav_debug_blocked ConVar). |
|
TF_NAV_BLOCKED = 0x00000001, // blocked for some TF-specific reason |
|
TF_NAV_SPAWN_ROOM_RED = 0x00000002, |
|
TF_NAV_SPAWN_ROOM_BLUE = 0x00000004, |
|
TF_NAV_SPAWN_ROOM_EXIT = 0x00000008, |
|
TF_NAV_HAS_AMMO = 0x00000010, |
|
TF_NAV_HAS_HEALTH = 0x00000020, |
|
TF_NAV_CONTROL_POINT = 0x00000040, |
|
|
|
TF_NAV_BLUE_SENTRY_DANGER = 0x00000080, // sentry can potentially fire upon enemies in this area |
|
TF_NAV_RED_SENTRY_DANGER = 0x00000100, |
|
|
|
TF_NAV_BLUE_SETUP_GATE = 0x00000800, // this area is blocked until the setup period is over |
|
TF_NAV_RED_SETUP_GATE = 0x00001000, // this area is blocked until the setup period is over |
|
TF_NAV_BLOCKED_AFTER_POINT_CAPTURE = 0x00002000, // this area becomes blocked after the first point is capped |
|
TF_NAV_BLOCKED_UNTIL_POINT_CAPTURE = 0x00004000, // this area is blocked until the first point is capped, then is unblocked |
|
TF_NAV_BLUE_ONE_WAY_DOOR = 0x00008000, |
|
TF_NAV_RED_ONE_WAY_DOOR = 0x00010000, |
|
|
|
TF_NAV_WITH_SECOND_POINT = 0x00020000, // modifier for BLOCKED_*_POINT_CAPTURE |
|
TF_NAV_WITH_THIRD_POINT = 0x00040000, // modifier for BLOCKED_*_POINT_CAPTURE |
|
TF_NAV_WITH_FOURTH_POINT = 0x00080000, // modifier for BLOCKED_*_POINT_CAPTURE |
|
TF_NAV_WITH_FIFTH_POINT = 0x00100000, // modifier for BLOCKED_*_POINT_CAPTURE |
|
|
|
TF_NAV_SNIPER_SPOT = 0x00200000, // this is a good place for a sniper to lurk |
|
TF_NAV_SENTRY_SPOT = 0x00400000, // this is a good place to build a sentry |
|
|
|
TF_NAV_ESCAPE_ROUTE = 0x00800000, // for Raid mode |
|
TF_NAV_ESCAPE_ROUTE_VISIBLE = 0x01000000, // all areas that have visibility to the escape route |
|
|
|
TF_NAV_NO_SPAWNING = 0x02000000, // don't spawn bots in this area |
|
|
|
TF_NAV_RESCUE_CLOSET = 0x04000000, // for respawning friends in Raid mode |
|
|
|
TF_NAV_BOMB_CAN_DROP_HERE = 0x08000000, // the bomb can be dropped here and reached by the invaders in MvM |
|
|
|
TF_NAV_DOOR_NEVER_BLOCKS = 0x10000000, |
|
TF_NAV_DOOR_ALWAYS_BLOCKS = 0x20000000, |
|
|
|
TF_NAV_UNBLOCKABLE = 0x40000000, // this area cannot be blocked |
|
|
|
// save/load these manually set flags, and don't clear them between rounds |
|
TF_NAV_PERSISTENT_ATTRIBUTES = TF_NAV_SNIPER_SPOT | TF_NAV_SENTRY_SPOT | TF_NAV_NO_SPAWNING | TF_NAV_BLUE_SETUP_GATE | TF_NAV_RED_SETUP_GATE | TF_NAV_BLOCKED_AFTER_POINT_CAPTURE | TF_NAV_BLOCKED_UNTIL_POINT_CAPTURE | TF_NAV_BLUE_ONE_WAY_DOOR | TF_NAV_RED_ONE_WAY_DOOR | TF_NAV_DOOR_NEVER_BLOCKS | TF_NAV_DOOR_ALWAYS_BLOCKS | TF_NAV_UNBLOCKABLE | TF_NAV_WITH_SECOND_POINT | TF_NAV_WITH_THIRD_POINT | TF_NAV_WITH_FOURTH_POINT | TF_NAV_WITH_FIFTH_POINT | TF_NAV_RESCUE_CLOSET |
|
}; |
|
|
|
|
|
|
|
class CTFNavArea : public CNavArea |
|
{ |
|
public: |
|
DECLARE_CLASS( CTFNavArea, CNavArea ); |
|
|
|
CTFNavArea( void ); |
|
|
|
virtual void OnServerActivate( void ); // (EXTEND) invoked when map is initially loaded |
|
virtual void OnRoundRestart( void ); // (EXTEND) invoked for each area when the round restarts |
|
|
|
virtual void CustomAnalysis( bool isIncremental = false ); // for game-specific analysis |
|
virtual void Draw( void ) const; // draw area for debugging & editing |
|
|
|
virtual void UpdateBlocked( bool force = false, int teamID = TEAM_ANY ) { } // we'll handle managing blocked status directly |
|
virtual bool IsBlocked( int teamID, bool ignoreNavBlockers = false ) const; |
|
|
|
virtual void Save( CUtlBuffer &fileBuffer, unsigned int version ) const; // (EXTEND) |
|
virtual NavErrorType Load( CUtlBuffer &fileBuffer, unsigned int version, unsigned int subVersion ); // (EXTEND) |
|
|
|
float GetIncursionDistance( int team ) const; // return travel distance from the team's active spawn room to this area, -1 for invalid |
|
CTFNavArea *GetNextIncursionArea( int team ) const; // return adjacent area with largest increase in incursion distance |
|
bool IsReachableByTeam( int team ) const; // return true if the given team can reach this area |
|
void CollectPriorIncursionAreas( int team, CUtlVector< CTFNavArea * > *priorVector ); // populate 'priorVector' with a collection of adjacent areas that have a lower incursion distance that this area |
|
void CollectNextIncursionAreas( int team, CUtlVector< CTFNavArea * > *priorVector ); // populate 'priorVector' with a collection of adjacent areas that have a higher incursion distance that this area |
|
|
|
const CUtlVector< CTFNavArea * > &GetEnemyInvasionAreaVector( int myTeam ) const; // given OUR team index, return list of areas the enemy is invading from |
|
bool IsAwayFromInvasionAreas( int myTeam, float safetyRange = 1000.0f ) const; // return true if this area is at least safetyRange units away from all invasion areas |
|
|
|
void ComputeInvasionAreaVectors( void ); |
|
void SetInvasionSearchMarker( unsigned int marker ); |
|
bool IsInvasionSearchMarked( unsigned int marker ) const; |
|
|
|
void SetAttributeTF( int flags ); |
|
void ClearAttributeTF( int flags ); |
|
bool HasAttributeTF( int flags ) const; |
|
|
|
void AddPotentiallyVisibleActor( CBaseCombatCharacter *who ); |
|
void RemovePotentiallyVisibleActor( CBaseCombatCharacter *who ); |
|
void ClearAllPotentiallyVisibleActors( void ); |
|
bool IsPotentiallyVisibleToActor( CBaseCombatCharacter *who ) const; // return true if the given actor has potential visibility to this area |
|
|
|
virtual bool IsPotentiallyVisibleToTeam( int team ) const; // return true if any portion of this area is visible to anyone on the given team (very fast) |
|
|
|
class IForEachPotentiallyVisibleActor |
|
{ |
|
public: |
|
virtual bool Inspect( CBaseCombatCharacter *who ) = 0; |
|
}; |
|
bool ForEachPotentiallyVisibleActor( IForEachPotentiallyVisibleActor &func, int team = TEAM_ANY ); |
|
|
|
void OnCombat( void ); // invoked when combat happens in/near this area |
|
bool IsInCombat( void ) const; // return true if this area has seen combat recently |
|
float GetCombatIntensity( void ) const; // 1 = in active combat, 0 = quiet |
|
|
|
static void MakeNewTFMarker( void ); |
|
static void ResetTFMarker( void ); |
|
bool IsTFMarked( void ) const; |
|
void TFMark( void ); |
|
|
|
// Raid mode ------------------------------------------------- |
|
void AddToWanderCount( int count ); |
|
void SetWanderCount( int count ); |
|
int GetWanderCount( void ) const; |
|
|
|
bool IsValidForWanderingPopulation( void ) const; |
|
// Raid mode ------------------------------------------------- |
|
|
|
// Distance for MvM bomb delivery |
|
float GetTravelDistanceToBombTarget( void ) const; |
|
|
|
private: |
|
friend class CTFNavMesh; |
|
|
|
float m_distanceFromSpawnRoom[ TF_TEAM_COUNT ]; |
|
CUtlVector< CTFNavArea * > m_invasionAreaVector[ TF_TEAM_COUNT ]; // use our team as index to get list of areas the enemy is invading from |
|
unsigned int m_invasionSearchMarker; |
|
|
|
unsigned int m_attributeFlags; |
|
|
|
CUtlVector< CHandle< CBaseCombatCharacter > > m_potentiallyVisibleActor[ TF_TEAM_COUNT ]; |
|
|
|
float m_combatIntensity; |
|
IntervalTimer m_combatTimer; |
|
|
|
static unsigned int m_masterTFMark; |
|
unsigned int m_TFMark; // this area's mark |
|
|
|
// Raid mode ------------------------------------------------- |
|
int m_wanderCount; // how many wandering defenders to populate here |
|
// Raid mode ------------------------------------------------- |
|
|
|
float m_distanceToBombTarget; |
|
}; |
|
|
|
|
|
inline float CTFNavArea::GetTravelDistanceToBombTarget( void ) const |
|
{ |
|
return m_distanceToBombTarget; |
|
} |
|
|
|
inline void CTFNavArea::AddToWanderCount( int count ) |
|
{ |
|
m_wanderCount += count; |
|
} |
|
|
|
inline void CTFNavArea::SetWanderCount( int count ) |
|
{ |
|
m_wanderCount = count; |
|
} |
|
|
|
inline int CTFNavArea::GetWanderCount( void ) const |
|
{ |
|
return m_wanderCount; |
|
} |
|
|
|
|
|
|
|
inline bool CTFNavArea::IsPotentiallyVisibleToActor( CBaseCombatCharacter *who ) const |
|
{ |
|
if ( who == NULL ) |
|
return false; |
|
|
|
int team = who->GetTeamNumber(); |
|
if ( team < 0 || team >= TF_TEAM_COUNT ) |
|
return false; |
|
|
|
return m_potentiallyVisibleActor[ team ].Find( who ) != m_potentiallyVisibleActor[ team ].InvalidIndex(); |
|
} |
|
|
|
|
|
inline bool CTFNavArea::IsPotentiallyVisibleToTeam( int team ) const |
|
{ |
|
return team >= 0 && team < TF_TEAM_COUNT && m_potentiallyVisibleActor[ team ].Count() > 0; |
|
} |
|
|
|
|
|
inline bool CTFNavArea::ForEachPotentiallyVisibleActor( CTFNavArea::IForEachPotentiallyVisibleActor &func, int team ) |
|
{ |
|
if ( team == TEAM_ANY ) |
|
{ |
|
for( int t=0; t<TF_TEAM_COUNT; ++t ) |
|
{ |
|
for( int i=0; i<m_potentiallyVisibleActor[ t ].Count(); ++i ) |
|
{ |
|
CBaseCombatCharacter *who = m_potentiallyVisibleActor[ t ][ i ]; |
|
|
|
if ( who && func.Inspect( who ) == false ) |
|
{ |
|
return false; |
|
} |
|
} |
|
} |
|
} |
|
else if ( team >= 0 && team < TF_TEAM_COUNT ) |
|
{ |
|
for( int i=0; i<m_potentiallyVisibleActor[ team ].Count(); ++i ) |
|
{ |
|
CBaseCombatCharacter *who = m_potentiallyVisibleActor[ team ][ i ]; |
|
|
|
if ( who && func.Inspect( who ) == false ) |
|
{ |
|
return false; |
|
} |
|
} |
|
} |
|
|
|
return true; |
|
} |
|
|
|
inline void CTFNavArea::RemovePotentiallyVisibleActor( CBaseCombatCharacter *who ) |
|
{ |
|
for( int i=0; i<TF_TEAM_COUNT; ++i ) |
|
m_potentiallyVisibleActor[i].FindAndFastRemove( who ); |
|
} |
|
|
|
inline void CTFNavArea::ClearAllPotentiallyVisibleActors( void ) |
|
{ |
|
for( int i=0; i<TF_TEAM_COUNT; ++i ) |
|
m_potentiallyVisibleActor[i].RemoveAll(); |
|
} |
|
|
|
inline float CTFNavArea::GetIncursionDistance( int team ) const |
|
{ |
|
if ( team < 0 || team >= TF_TEAM_COUNT ) |
|
{ |
|
return -1.0f; |
|
} |
|
|
|
return m_distanceFromSpawnRoom[ team ]; |
|
} |
|
|
|
inline bool CTFNavArea::IsReachableByTeam( int team ) const |
|
{ |
|
if ( team < 0 || team >= TF_TEAM_COUNT ) |
|
{ |
|
return false; |
|
} |
|
|
|
return m_distanceFromSpawnRoom[ team ] >= 0.0f; |
|
} |
|
|
|
inline const CUtlVector< CTFNavArea * > &CTFNavArea::GetEnemyInvasionAreaVector( int myTeam ) const |
|
{ |
|
if ( myTeam < 0 || myTeam >= TF_TEAM_COUNT ) |
|
{ |
|
myTeam = 0.0f; |
|
} |
|
|
|
return m_invasionAreaVector[ myTeam ]; |
|
} |
|
|
|
inline void CTFNavArea::SetInvasionSearchMarker( unsigned int marker ) |
|
{ |
|
m_invasionSearchMarker = marker; |
|
} |
|
|
|
inline bool CTFNavArea::IsInvasionSearchMarked( unsigned int marker ) const |
|
{ |
|
return marker == m_invasionSearchMarker; |
|
} |
|
|
|
inline void CTFNavArea::SetAttributeTF( int flags ) |
|
{ |
|
m_attributeFlags |= flags; |
|
} |
|
|
|
inline void CTFNavArea::ClearAttributeTF( int flags ) |
|
{ |
|
m_attributeFlags &= ~flags; |
|
} |
|
|
|
inline bool CTFNavArea::HasAttributeTF( int flags ) const |
|
{ |
|
return ( m_attributeFlags & flags ) ? true : false; |
|
} |
|
|
|
#endif // TF_NAV_AREA_H
|