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.
538 lines
16 KiB
538 lines
16 KiB
5 years ago
|
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||
|
// tf_nav_area.h
|
||
|
// TF specific nav area
|
||
|
// Michael Booth, February 2009
|
||
|
|
||
|
#include "cbase.h"
|
||
|
#include "tf_nav_mesh.h"
|
||
|
#include "tf_nav_area.h"
|
||
|
#include "tf_gamerules.h"
|
||
|
#include "bot/tf_bot.h"
|
||
|
#include "nav_pathfind.h"
|
||
|
|
||
|
ConVar tf_nav_show_incursion_distance( "tf_nav_show_incursion_distance", "0", FCVAR_CHEAT, "Display travel distances from current spawn room (1=red, 2=blue)" );
|
||
|
ConVar tf_nav_show_bomb_target_distance( "tf_nav_show_bomb_target_distance", "0", FCVAR_CHEAT, "Display travel distances to bomb target (MvM mode)" );
|
||
|
ConVar tf_nav_show_turf_ownership( "tf_nav_show_turf_ownership", "0", FCVAR_CHEAT, "Color nav area by smallest incursion distance" );
|
||
|
|
||
|
ConVar tf_nav_in_combat_duration( "tf_nav_in_combat_duration", "30", FCVAR_CHEAT, "How long after gunfire occurs is this area still considered to be 'in combat'" );
|
||
|
|
||
|
ConVar tf_nav_combat_build_rate( "tf_nav_combat_build_rate", "0.05", FCVAR_CHEAT, "Gunfire/second increase (combat caps at 1.0)" );
|
||
|
ConVar tf_nav_combat_decay_rate( "tf_nav_combat_decay_rate", "0.022", FCVAR_CHEAT, "Decay/second toward zero" );
|
||
|
|
||
|
ConVar tf_show_sniper_areas( "tf_show_sniper_areas", "0", FCVAR_CHEAT );
|
||
|
ConVar tf_show_sniper_areas_safety_range( "tf_show_sniper_areas_safety_range", "1000", FCVAR_CHEAT );
|
||
|
|
||
|
ConVar tf_show_incursion_range( "tf_show_incursion_range", "0", FCVAR_CHEAT, "1 = red, 2 = blue" );
|
||
|
ConVar tf_show_incursion_range_min( "tf_show_incursion_range_min", "0", FCVAR_CHEAT, "Highlight areas with incursion distances between min and max cvar values" );
|
||
|
ConVar tf_show_incursion_range_max( "tf_show_incursion_range_max", "0", FCVAR_CHEAT, "Highlight areas with incursion distances between min and max cvar values" );
|
||
|
|
||
|
|
||
|
//------------------------------------------------------------------------------------------------
|
||
|
CTFNavArea::CTFNavArea( void )
|
||
|
{
|
||
|
m_attributeFlags = 0;
|
||
|
m_wanderCount = 0;
|
||
|
m_combatIntensity = 0.0f;
|
||
|
m_distanceToBombTarget = 0.0f;
|
||
|
m_TFMark = 0;
|
||
|
m_invasionSearchMarker = (unsigned int)-1;
|
||
|
}
|
||
|
|
||
|
|
||
|
//------------------------------------------------------------------------------------------------
|
||
|
/**
|
||
|
* (EXTEND) invoked when map is initially loaded
|
||
|
*/
|
||
|
void CTFNavArea::OnServerActivate( void )
|
||
|
{
|
||
|
BaseClass::OnServerActivate();
|
||
|
|
||
|
ClearAllPotentiallyVisibleActors();
|
||
|
}
|
||
|
|
||
|
//------------------------------------------------------------------------------------------------
|
||
|
/**
|
||
|
* (EXTEND) invoked for each area when the round restarts
|
||
|
*/
|
||
|
void CTFNavArea::OnRoundRestart( void )
|
||
|
{
|
||
|
BaseClass::OnRoundRestart();
|
||
|
|
||
|
ClearAllPotentiallyVisibleActors();
|
||
|
|
||
|
m_combatIntensity = 0.0f;
|
||
|
}
|
||
|
|
||
|
//------------------------------------------------------------------------------------------------
|
||
|
/**
|
||
|
* For game-specific analysis
|
||
|
*/
|
||
|
void CTFNavArea::CustomAnalysis( bool isIncremental )
|
||
|
{
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
//------------------------------------------------------------------------------------------------
|
||
|
/**
|
||
|
* Draw area for debugging & editing
|
||
|
*/
|
||
|
void CTFNavArea::Draw( void ) const
|
||
|
{
|
||
|
CNavArea::Draw();
|
||
|
|
||
|
#ifdef TF_RAID_MODE
|
||
|
if ( TFGameRules()->IsRaidMode() && m_wanderCount > 0 )
|
||
|
{
|
||
|
NDebugOverlay::Text( GetCenter(), UTIL_VarArgs( "%d", m_wanderCount ), false, NDEBUG_PERSIST_TILL_NEXT_SERVER );
|
||
|
}
|
||
|
#endif // TF_RAID_MODE
|
||
|
|
||
|
if ( tf_nav_show_incursion_distance.GetBool() )
|
||
|
{
|
||
|
NDebugOverlay::Text( GetCenter(), UTIL_VarArgs( "R:%3.1f B:%3.1f", GetIncursionDistance( TF_TEAM_RED ), GetIncursionDistance( TF_TEAM_BLUE ) ), false, NDEBUG_PERSIST_TILL_NEXT_SERVER );
|
||
|
}
|
||
|
|
||
|
if ( tf_nav_show_bomb_target_distance.GetBool() )
|
||
|
{
|
||
|
NDebugOverlay::Text( GetCenter(), UTIL_VarArgs( "%3.1f", GetTravelDistanceToBombTarget() ), false, NDEBUG_PERSIST_TILL_NEXT_SERVER );
|
||
|
}
|
||
|
|
||
|
if ( tf_show_sniper_areas.GetBool() )
|
||
|
{
|
||
|
bool redSniper = IsAwayFromInvasionAreas( TF_TEAM_RED, tf_show_sniper_areas_safety_range.GetFloat() );
|
||
|
bool blueSniper = IsAwayFromInvasionAreas( TF_TEAM_BLUE, tf_show_sniper_areas_safety_range.GetFloat() );
|
||
|
|
||
|
if ( blueSniper )
|
||
|
{
|
||
|
if ( redSniper )
|
||
|
{
|
||
|
// both teams like this spot?
|
||
|
DrawFilled( 255, 0, 255, 255, NDEBUG_PERSIST_TILL_NEXT_SERVER );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// blue sniper area
|
||
|
DrawFilled( 0, 0, 255, 255, NDEBUG_PERSIST_TILL_NEXT_SERVER );
|
||
|
}
|
||
|
}
|
||
|
else if ( redSniper )
|
||
|
{
|
||
|
// red sniper area
|
||
|
DrawFilled( 255, 0, 0, 255, NDEBUG_PERSIST_TILL_NEXT_SERVER );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int rangeTeam = tf_show_incursion_range.GetInt();
|
||
|
if ( rangeTeam > 0 )
|
||
|
{
|
||
|
rangeTeam += ( TF_TEAM_RED - 1);
|
||
|
|
||
|
float range = GetIncursionDistance( rangeTeam );
|
||
|
if ( range >= tf_show_incursion_range_min.GetFloat() && range <= tf_show_incursion_range_max.GetFloat() )
|
||
|
{
|
||
|
DrawFilled( 0, 255, 0, 255, NDEBUG_PERSIST_TILL_NEXT_SERVER );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//------------------------------------------------------------------------------------------------
|
||
|
/**
|
||
|
* Return adjacent area with largest increase in incursion distance
|
||
|
*/
|
||
|
CTFNavArea *CTFNavArea::GetNextIncursionArea( int team ) const
|
||
|
{
|
||
|
CTFNavArea *nextIncursionArea = NULL;
|
||
|
float nextIncursionDistance = GetIncursionDistance( team );
|
||
|
|
||
|
for( int dir=0; dir<NUM_DIRECTIONS; ++dir )
|
||
|
{
|
||
|
const NavConnectVector *adjVector = GetAdjacentAreas( (NavDirType)dir );
|
||
|
FOR_EACH_VEC( (*adjVector), bit )
|
||
|
{
|
||
|
CTFNavArea *adjArea = static_cast< CTFNavArea * >( (*adjVector)[ bit ].area );
|
||
|
|
||
|
if ( adjArea->GetIncursionDistance( team ) > nextIncursionDistance )
|
||
|
{
|
||
|
nextIncursionArea = adjArea;
|
||
|
nextIncursionDistance = adjArea->GetIncursionDistance( team );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return nextIncursionArea;
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Populate 'priorVector' with a collection of adjacent areas that have a lower incursion distance that this area
|
||
|
void CTFNavArea::CollectPriorIncursionAreas( int team, CUtlVector< CTFNavArea * > *priorVector )
|
||
|
{
|
||
|
float myIncursionDistance = GetIncursionDistance( team );
|
||
|
|
||
|
priorVector->RemoveAll();
|
||
|
|
||
|
for( int dir=0; dir<NUM_DIRECTIONS; ++dir )
|
||
|
{
|
||
|
const NavConnectVector *adjVector = GetAdjacentAreas( (NavDirType)dir );
|
||
|
FOR_EACH_VEC( (*adjVector), bit )
|
||
|
{
|
||
|
CTFNavArea *adjArea = static_cast< CTFNavArea * >( (*adjVector)[ bit ].area );
|
||
|
|
||
|
if ( adjArea->GetIncursionDistance( team ) < myIncursionDistance )
|
||
|
{
|
||
|
priorVector->AddToTail( adjArea );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Populate 'priorVector' with a collection of adjacent areas that have a higher incursion distance that this area
|
||
|
void CTFNavArea::CollectNextIncursionAreas( int team, CUtlVector< CTFNavArea * > *priorVector )
|
||
|
{
|
||
|
float myIncursionDistance = GetIncursionDistance( team );
|
||
|
|
||
|
priorVector->RemoveAll();
|
||
|
|
||
|
for( int dir=0; dir<NUM_DIRECTIONS; ++dir )
|
||
|
{
|
||
|
const NavConnectVector *adjVector = GetAdjacentAreas( (NavDirType)dir );
|
||
|
FOR_EACH_VEC( (*adjVector), bit )
|
||
|
{
|
||
|
CTFNavArea *adjArea = static_cast< CTFNavArea * >( (*adjVector)[ bit ].area );
|
||
|
|
||
|
if ( adjArea->GetIncursionDistance( team ) > myIncursionDistance )
|
||
|
{
|
||
|
priorVector->AddToTail( adjArea );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
/**
|
||
|
* Return true if this area is at least safetyRange units away from all invasion areas
|
||
|
*/
|
||
|
bool CTFNavArea::IsAwayFromInvasionAreas( int myTeam, float safetyRange ) const
|
||
|
{
|
||
|
const CUtlVector< CTFNavArea * > &invasionVector = GetEnemyInvasionAreaVector( myTeam );
|
||
|
FOR_EACH_VEC( invasionVector, vit )
|
||
|
{
|
||
|
CTFNavArea *invasionArea = invasionVector[ vit ];
|
||
|
|
||
|
if ( ( invasionArea->GetCenter() - GetCenter() ).IsLengthLessThan( safetyRange ) )
|
||
|
{
|
||
|
// too close to incoming enemy route to snipe
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
class MarkVisibleSet
|
||
|
{
|
||
|
public:
|
||
|
MarkVisibleSet( unsigned int marker )
|
||
|
{
|
||
|
m_marker = marker;
|
||
|
}
|
||
|
|
||
|
bool operator() ( CNavArea *baseArea )
|
||
|
{
|
||
|
CTFNavArea *area = static_cast< CTFNavArea * >( baseArea );
|
||
|
area->SetInvasionSearchMarker( m_marker );
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
unsigned int m_marker;
|
||
|
};
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
class CollectInvasionAreas
|
||
|
{
|
||
|
public:
|
||
|
CollectInvasionAreas( unsigned int marker, CTFNavArea *homeArea, CUtlVector< CTFNavArea * > *redInvasionAreaVector, CUtlVector< CTFNavArea * > *blueInvasionAreaVector )
|
||
|
{
|
||
|
m_homeArea = homeArea;
|
||
|
m_visibleMarker = marker;
|
||
|
m_redInvasionAreaVector = redInvasionAreaVector;
|
||
|
m_blueInvasionAreaVector = blueInvasionAreaVector;
|
||
|
}
|
||
|
|
||
|
void FilterArea( CTFNavArea *area, CTFNavArea *adjArea )
|
||
|
{
|
||
|
if ( adjArea->IsInvasionSearchMarked( m_visibleMarker ) )
|
||
|
{
|
||
|
// also in PVS - can't be invasion area
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
const float behindTolerance = 100.0;
|
||
|
|
||
|
// adjacent area is not in PVS, test if adjacent area not penetrated as far, if so it is an invasion area
|
||
|
if ( area->GetIncursionDistance( TF_TEAM_BLUE ) > adjArea->GetIncursionDistance( TF_TEAM_BLUE ) )
|
||
|
{
|
||
|
if ( area->GetIncursionDistance( TF_TEAM_BLUE ) > m_homeArea->GetIncursionDistance( TF_TEAM_BLUE ) + behindTolerance )
|
||
|
{
|
||
|
// this area is farther "in" than we are - don't search further
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
m_redInvasionAreaVector->AddToTail( adjArea );
|
||
|
}
|
||
|
|
||
|
if ( area->GetIncursionDistance( TF_TEAM_RED ) > adjArea->GetIncursionDistance( TF_TEAM_RED ) )
|
||
|
{
|
||
|
if ( area->GetIncursionDistance( TF_TEAM_RED ) > m_homeArea->GetIncursionDistance( TF_TEAM_RED ) + behindTolerance )
|
||
|
{
|
||
|
// this area is farther "in" than we are - don't search further
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
m_blueInvasionAreaVector->AddToTail( adjArea );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool operator() ( CNavArea *baseArea )
|
||
|
{
|
||
|
CTFNavArea *area = static_cast< CTFNavArea * >( baseArea );
|
||
|
|
||
|
// explore adjacent floor areas
|
||
|
int dir;
|
||
|
for( dir=0; dir<NUM_DIRECTIONS; ++dir )
|
||
|
{
|
||
|
int count = area->GetAdjacentCount( (NavDirType)dir );
|
||
|
for( int i=0; i<count; ++i )
|
||
|
{
|
||
|
CTFNavArea *adjArea = static_cast< CTFNavArea * >( area->GetAdjacentArea( (NavDirType)dir, i ) );
|
||
|
|
||
|
FilterArea( area, adjArea );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// include areas that connect TO this area via a one-way link, since the enemy is coming TO us
|
||
|
for( dir=0; dir<NUM_DIRECTIONS; ++dir )
|
||
|
{
|
||
|
const NavConnectVector *list = area->GetIncomingConnections( (NavDirType)dir );
|
||
|
|
||
|
FOR_EACH_VEC( (*list), it )
|
||
|
{
|
||
|
NavConnect connect = (*list)[ it ];
|
||
|
|
||
|
FilterArea( area, static_cast< CTFNavArea * >( connect.area ) );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
CTFNavArea *m_homeArea;
|
||
|
CUtlVector< CTFNavArea * > *m_redInvasionAreaVector;
|
||
|
CUtlVector< CTFNavArea * > *m_blueInvasionAreaVector;
|
||
|
unsigned int m_visibleMarker;
|
||
|
};
|
||
|
|
||
|
|
||
|
//------------------------------------------------------------------------------------------------
|
||
|
/**
|
||
|
* Find invasion areas where enemies enter from
|
||
|
*/
|
||
|
void CTFNavArea::ComputeInvasionAreaVectors( void )
|
||
|
{
|
||
|
static unsigned int searchMarker = RandomInt( 0, 1024*1024 );
|
||
|
|
||
|
for( int i=0; i<TF_TEAM_COUNT; ++i )
|
||
|
{
|
||
|
m_invasionAreaVector[ i ].RemoveAll();
|
||
|
}
|
||
|
|
||
|
++searchMarker;
|
||
|
|
||
|
// mark all potentially visible areas for quick testing during the search
|
||
|
MarkVisibleSet marker( searchMarker );
|
||
|
ForAllCompletelyVisibleAreas( marker );
|
||
|
|
||
|
// search boundary of potentially visible area set for area pairs where
|
||
|
// the area in the PVS has a higher incursion distance than an adjacent
|
||
|
// area outside of the PVS - an invasion area
|
||
|
|
||
|
CollectInvasionAreas collector( searchMarker, this, &m_invasionAreaVector[ TF_TEAM_RED ], &m_invasionAreaVector[ TF_TEAM_BLUE ] );
|
||
|
ForAllCompletelyVisibleAreas( collector );
|
||
|
}
|
||
|
|
||
|
|
||
|
//------------------------------------------------------------------------------------------------
|
||
|
bool CTFNavArea::IsBlocked( int teamID, bool ignoreNavBlockers ) const
|
||
|
{
|
||
|
if ( HasAttributeTF( TF_NAV_UNBLOCKABLE ) )
|
||
|
return false;
|
||
|
|
||
|
if ( HasAttributeTF( TF_NAV_BLOCKED ) )
|
||
|
return true;
|
||
|
|
||
|
// temporary fix:
|
||
|
if ( teamID == TF_TEAM_RED && HasAttributeTF( TF_NAV_BLUE_ONE_WAY_DOOR ) )
|
||
|
return true;
|
||
|
|
||
|
if ( teamID == TF_TEAM_BLUE && HasAttributeTF( TF_NAV_RED_ONE_WAY_DOOR ) )
|
||
|
return true;
|
||
|
|
||
|
return CNavArea::IsBlocked( teamID, ignoreNavBlockers );
|
||
|
}
|
||
|
|
||
|
|
||
|
//------------------------------------------------------------------------------------------------
|
||
|
void CTFNavArea::Save( CUtlBuffer &fileBuffer, unsigned int version ) const
|
||
|
{
|
||
|
CNavArea::Save( fileBuffer, version );
|
||
|
|
||
|
// save attribute flags
|
||
|
unsigned int attributes = m_attributeFlags & TF_NAV_PERSISTENT_ATTRIBUTES;
|
||
|
fileBuffer.PutUnsignedInt( attributes );
|
||
|
}
|
||
|
|
||
|
|
||
|
//------------------------------------------------------------------------------------------------
|
||
|
NavErrorType CTFNavArea::Load( CUtlBuffer &fileBuffer, unsigned int version, unsigned int subVersion )
|
||
|
{
|
||
|
// load base class data
|
||
|
CNavArea::Load( fileBuffer, version, subVersion );
|
||
|
|
||
|
if ( subVersion > TheNavMesh->GetSubVersionNumber() )
|
||
|
{
|
||
|
Warning( "Unknown NavArea sub-version number\n" );
|
||
|
return NAV_INVALID_FILE;
|
||
|
}
|
||
|
else if ( subVersion <= 1 )
|
||
|
{
|
||
|
// no data
|
||
|
m_attributeFlags = 0;
|
||
|
return NAV_OK;
|
||
|
}
|
||
|
|
||
|
m_attributeFlags = fileBuffer.GetUnsignedInt();
|
||
|
if ( !fileBuffer.IsValid() )
|
||
|
{
|
||
|
Warning( "Can't read TF-specific attributes\n" );
|
||
|
return NAV_INVALID_FILE;
|
||
|
}
|
||
|
|
||
|
return NAV_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
//--------------------------------------------------------------------------------------------------------
|
||
|
unsigned int CTFNavArea::m_masterTFMark = 1;
|
||
|
|
||
|
|
||
|
//--------------------------------------------------------------------------------------------------------
|
||
|
void CTFNavArea::MakeNewTFMarker( void )
|
||
|
{
|
||
|
++m_masterTFMark;
|
||
|
}
|
||
|
|
||
|
|
||
|
//--------------------------------------------------------------------------------------------------------
|
||
|
void CTFNavArea::ResetTFMarker( void )
|
||
|
{
|
||
|
m_masterTFMark = 1;
|
||
|
}
|
||
|
|
||
|
|
||
|
//--------------------------------------------------------------------------------------------------------
|
||
|
bool CTFNavArea::IsTFMarked( void ) const
|
||
|
{
|
||
|
return ( m_TFMark == m_masterTFMark );
|
||
|
}
|
||
|
|
||
|
|
||
|
//--------------------------------------------------------------------------------------------------------
|
||
|
void CTFNavArea::TFMark( void )
|
||
|
{
|
||
|
m_TFMark = m_masterTFMark;
|
||
|
}
|
||
|
|
||
|
|
||
|
//--------------------------------------------------------------------------------------------------------
|
||
|
bool CTFNavArea::IsValidForWanderingPopulation( void ) const
|
||
|
{
|
||
|
if ( HasAttributeTF( TF_NAV_BLOCKED | TF_NAV_SPAWN_ROOM_RED | TF_NAV_SPAWN_ROOM_BLUE | TF_NAV_NO_SPAWNING | TF_NAV_RESCUE_CLOSET ) )
|
||
|
return false;
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
//--------------------------------------------------------------------------------------------------------
|
||
|
void CTFNavArea::AddPotentiallyVisibleActor( CBaseCombatCharacter *who )
|
||
|
{
|
||
|
if ( who == NULL )
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
int team = who->GetTeamNumber();
|
||
|
if ( team < 0 || team >= TF_TEAM_COUNT )
|
||
|
return;
|
||
|
|
||
|
CTFBot *bot = ToTFBot( who );
|
||
|
if ( bot && bot->HasAttribute( CTFBot::IS_NPC ) )
|
||
|
return;
|
||
|
|
||
|
if ( m_potentiallyVisibleActor[ team ].Find( who ) == m_potentiallyVisibleActor[ team ].InvalidIndex() )
|
||
|
{
|
||
|
m_potentiallyVisibleActor[ team ].AddToTail( who );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//--------------------------------------------------------------------------------------------------------
|
||
|
float CTFNavArea::GetCombatIntensity( void ) const
|
||
|
{
|
||
|
if ( !m_combatTimer.HasStarted() )
|
||
|
{
|
||
|
return 0.0f;
|
||
|
}
|
||
|
|
||
|
float actualIntensity = m_combatIntensity - m_combatTimer.GetElapsedTime() * tf_nav_combat_decay_rate.GetFloat();
|
||
|
|
||
|
if ( actualIntensity < 0.0f )
|
||
|
{
|
||
|
actualIntensity = 0.0f;
|
||
|
}
|
||
|
|
||
|
return actualIntensity;
|
||
|
}
|
||
|
|
||
|
|
||
|
//--------------------------------------------------------------------------------------------------------
|
||
|
// Invoked when combat happens in/near this area
|
||
|
void CTFNavArea::OnCombat( void )
|
||
|
{
|
||
|
m_combatIntensity += tf_nav_combat_build_rate.GetFloat();
|
||
|
if ( m_combatIntensity > 1.0f )
|
||
|
{
|
||
|
m_combatIntensity = 1.0f;
|
||
|
}
|
||
|
|
||
|
m_combatTimer.Start();
|
||
|
}
|
||
|
|
||
|
|
||
|
//--------------------------------------------------------------------------------------------------------
|
||
|
bool CTFNavArea::IsInCombat( void ) const
|
||
|
{
|
||
|
return GetCombatIntensity() > 0.01f;
|
||
|
}
|
||
|
|
||
|
|