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.
580 lines
18 KiB
580 lines
18 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
//=============================================================================// |
|
|
|
#include "cbase.h" |
|
#include "ai_utils.h" |
|
#include "ai_memory.h" |
|
#include "ai_basenpc.h" |
|
#include "ai_senses.h" |
|
#include "ai_moveprobe.h" |
|
#include "vphysics/object_hash.h" |
|
|
|
// memdbgon must be the last include file in a .cpp file!!! |
|
#include "tier0/memdbgon.h" |
|
|
|
//----------------------------------------------------------------------------- |
|
|
|
BEGIN_SIMPLE_DATADESC( CAI_MoveMonitor ) |
|
DEFINE_FIELD( m_vMark, FIELD_POSITION_VECTOR ), |
|
DEFINE_FIELD( m_flMarkTolerance, FIELD_FLOAT ) |
|
END_DATADESC() |
|
|
|
//----------------------------------------------------------------------------- |
|
|
|
BEGIN_SIMPLE_DATADESC( CAI_ShotRegulator ) |
|
DEFINE_FIELD( m_flNextShotTime, FIELD_TIME ), |
|
DEFINE_FIELD( m_bInRestInterval, FIELD_BOOLEAN ), |
|
DEFINE_FIELD( m_nBurstShotsRemaining, FIELD_SHORT ), |
|
DEFINE_FIELD( m_nMinBurstShots, FIELD_SHORT ), |
|
DEFINE_FIELD( m_nMaxBurstShots, FIELD_SHORT ), |
|
DEFINE_FIELD( m_flMinRestInterval, FIELD_FLOAT ), |
|
DEFINE_FIELD( m_flMaxRestInterval, FIELD_FLOAT ), |
|
DEFINE_FIELD( m_flMinBurstInterval, FIELD_FLOAT ), |
|
DEFINE_FIELD( m_flMaxBurstInterval, FIELD_FLOAT ), |
|
DEFINE_FIELD( m_bDisabled, FIELD_BOOLEAN ), |
|
END_DATADESC() |
|
|
|
//----------------------------------------------------------------------------- |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Constructor |
|
//----------------------------------------------------------------------------- |
|
CAI_ShotRegulator::CAI_ShotRegulator() : m_nMinBurstShots(1), m_nMaxBurstShots(1) |
|
{ |
|
m_flMinRestInterval = 0.0f; |
|
m_flMaxRestInterval = 0.0f; |
|
m_flMinBurstInterval = 0.0f; |
|
m_flMaxBurstInterval = 0.0f; |
|
m_flNextShotTime = -1; |
|
m_nBurstShotsRemaining = 1; |
|
m_bInRestInterval = false; |
|
m_bDisabled = false; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// For backward compatibility |
|
//----------------------------------------------------------------------------- |
|
void CAI_ShotRegulator::SetParameters( int minShotsPerBurst, int maxShotsPerBurst, float minRestTime, float maxRestTime ) |
|
{ |
|
SetBurstShotCountRange( minShotsPerBurst, maxShotsPerBurst ); |
|
SetRestInterval( minRestTime, maxRestTime ); |
|
Reset( false ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Sets the number of shots to shoot in a single burst |
|
//----------------------------------------------------------------------------- |
|
void CAI_ShotRegulator::SetBurstShotCountRange( int minShotsPerBurst, int maxShotsPerBurst ) |
|
{ |
|
m_nMinBurstShots = minShotsPerBurst; |
|
m_nMaxBurstShots = maxShotsPerBurst; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// How much time should I rest between bursts? |
|
//----------------------------------------------------------------------------- |
|
void CAI_ShotRegulator::SetRestInterval( float flMinRestInterval, float flMaxRestInterval ) |
|
{ |
|
m_flMinRestInterval = flMinRestInterval; |
|
m_flMaxRestInterval = flMaxRestInterval; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// How much time should I wait in between shots in a single burst? |
|
//----------------------------------------------------------------------------- |
|
void CAI_ShotRegulator::SetBurstInterval( float flMinBurstInterval, float flMaxBurstInterval ) |
|
{ |
|
m_flMinBurstInterval = flMinBurstInterval; |
|
m_flMaxBurstInterval = flMaxBurstInterval; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Poll the current parameters |
|
//----------------------------------------------------------------------------- |
|
void CAI_ShotRegulator::GetBurstShotCountRange( int *pMinShotsPerBurst, int *pMaxShotsPerBurst ) const |
|
{ |
|
*pMinShotsPerBurst = m_nMinBurstShots; |
|
*pMaxShotsPerBurst = m_nMaxBurstShots; |
|
} |
|
|
|
void CAI_ShotRegulator::GetRestInterval( float *pMinRestInterval, float *pMaxRestInterval ) const |
|
{ |
|
*pMinRestInterval = m_flMinRestInterval; |
|
*pMaxRestInterval = m_flMaxRestInterval; |
|
} |
|
|
|
void CAI_ShotRegulator::GetBurstInterval( float *pMinBurstInterval, float *pMaxBurstInterval ) const |
|
{ |
|
*pMinBurstInterval = m_flMinBurstInterval; |
|
*pMaxBurstInterval = m_flMaxBurstInterval; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Resets the shot regulator to start a new burst |
|
//----------------------------------------------------------------------------- |
|
void CAI_ShotRegulator::Reset( bool bStartShooting ) |
|
{ |
|
m_bDisabled = false; |
|
m_nBurstShotsRemaining = random->RandomInt( m_nMinBurstShots, m_nMaxBurstShots ); |
|
if ( bStartShooting ) |
|
{ |
|
m_flNextShotTime = gpGlobals->curtime; |
|
m_bInRestInterval = false; |
|
} |
|
else |
|
{ |
|
m_flNextShotTime = gpGlobals->curtime + random->RandomFloat( m_flMinRestInterval, m_flMaxRestInterval ); |
|
m_bInRestInterval = true; |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Should we shoot? |
|
//----------------------------------------------------------------------------- |
|
bool CAI_ShotRegulator::ShouldShoot() const |
|
{ |
|
return ( !m_bDisabled && (m_flNextShotTime <= gpGlobals->curtime) ); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Am I in the middle of a burst? |
|
//----------------------------------------------------------------------------- |
|
bool CAI_ShotRegulator::IsInRestInterval() const |
|
{ |
|
return (m_bInRestInterval && !ShouldShoot()); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// When will I shoot next? |
|
//----------------------------------------------------------------------------- |
|
float CAI_ShotRegulator::NextShotTime() const |
|
{ |
|
return m_flNextShotTime; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Causes us to potentially delay our shooting time |
|
//----------------------------------------------------------------------------- |
|
void CAI_ShotRegulator::FireNoEarlierThan( float flTime ) |
|
{ |
|
if ( flTime > m_flNextShotTime ) |
|
{ |
|
m_flNextShotTime = flTime; |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Burst shot count accessors |
|
//----------------------------------------------------------------------------- |
|
int CAI_ShotRegulator::GetBurstShotsRemaining() const |
|
{ |
|
return m_nBurstShotsRemaining; |
|
} |
|
|
|
void CAI_ShotRegulator::SetBurstShotsRemaining( int shots ) |
|
{ |
|
m_nBurstShotsRemaining = shots; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// We fired the weapon! Update the next shot time |
|
//----------------------------------------------------------------------------- |
|
void CAI_ShotRegulator::OnFiredWeapon() |
|
{ |
|
--m_nBurstShotsRemaining; |
|
if ( m_nBurstShotsRemaining <= 0 ) |
|
{ |
|
Reset( false ); |
|
} |
|
else |
|
{ |
|
m_bInRestInterval = false; |
|
m_flNextShotTime += random->RandomFloat( m_flMinBurstInterval, m_flMaxBurstInterval ); |
|
if ( m_flNextShotTime < gpGlobals->curtime ) |
|
{ |
|
m_flNextShotTime = gpGlobals->curtime; |
|
} |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CAI_ShotRegulator::EnableShooting( void ) |
|
{ |
|
m_bDisabled = false; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CAI_ShotRegulator::DisableShooting( void ) |
|
{ |
|
m_bDisabled = true; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// |
|
//----------------------------------------------------------------------------- |
|
|
|
BEGIN_SIMPLE_DATADESC( CAI_AccelDecay ) |
|
DEFINE_FIELD( m_velocity, FIELD_FLOAT ), |
|
DEFINE_FIELD( m_maxVelocity, FIELD_FLOAT ), |
|
DEFINE_FIELD( m_minVelocity, FIELD_FLOAT ), |
|
DEFINE_FIELD( m_invDecay, FIELD_FLOAT ), |
|
DEFINE_FIELD( m_decayTime, FIELD_FLOAT ), |
|
DEFINE_FIELD( m_accel, FIELD_FLOAT ), |
|
END_DATADESC() |
|
|
|
|
|
void CAI_AccelDecay::SetParameters( float minVelocity, float maxVelocity, float accelPercentPerTick, float decelPercentPerTick ) |
|
{ |
|
m_minVelocity = minVelocity; |
|
m_maxVelocity = maxVelocity; |
|
|
|
m_accel = accelPercentPerTick; |
|
m_invDecay = 1.0 - decelPercentPerTick; |
|
|
|
m_decayTime = 0.0; |
|
float d = 1.0; |
|
|
|
int i = 0; |
|
while (d * m_maxVelocity > m_minVelocity && i < 10) |
|
{ |
|
d = d * m_invDecay; |
|
m_decayTime = m_decayTime + 0.1 * d; // appox interval call |
|
i++; |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// |
|
//----------------------------------------------------------------------------- |
|
|
|
float CAI_AccelDecay::Update( float flCurrent, float flTarget, float flInterval ) |
|
{ |
|
float delta = flTarget - flCurrent; |
|
float deltaSign = ( delta < 0 ) ? -1 : 1; |
|
delta = fabsf( delta ); |
|
|
|
float curVelocity = m_velocity; |
|
|
|
if ( delta > 0.01 ) |
|
{ |
|
if (fabsf( m_velocity ) < m_minVelocity) |
|
m_velocity = m_minVelocity * deltaSign; |
|
|
|
if (delta < m_velocity * deltaSign * m_decayTime ) |
|
{ |
|
m_velocity = m_velocity * m_invDecay; |
|
|
|
if (delta < m_velocity * deltaSign * flInterval) |
|
{ |
|
m_velocity = delta * deltaSign / flInterval; |
|
} |
|
} |
|
else |
|
{ |
|
m_velocity = m_velocity * (1.0f - m_accel) + m_maxVelocity * m_accel * deltaSign; |
|
if (delta < m_velocity * deltaSign * m_decayTime) |
|
{ |
|
m_velocity = delta * deltaSign / m_decayTime; |
|
} |
|
} |
|
|
|
float newValue = flCurrent + (curVelocity + m_velocity) * 0.5 * flInterval; |
|
return newValue; |
|
} |
|
|
|
return flTarget; |
|
} |
|
|
|
|
|
|
|
void CAI_AccelDecay::ResetVelocity( float flVelocity ) |
|
{ |
|
m_velocity = flVelocity; |
|
} |
|
|
|
|
|
void CAI_AccelDecay::SetMaxVelocity( float maxVelocity ) |
|
{ |
|
if (maxVelocity != m_maxVelocity) |
|
{ |
|
SetParameters( m_minVelocity, maxVelocity, m_accel, 1.0 - m_invDecay ); |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
//----------------------------------------------------------------------------- |
|
|
|
ConVar free_pass_peek_debug( "free_pass_peek_debug", "0" ); |
|
|
|
BEGIN_SIMPLE_DATADESC( AI_FreePassParams_t ) |
|
|
|
DEFINE_KEYFIELD( timeToTrigger, FIELD_FLOAT, "freepass_timetotrigger"), |
|
DEFINE_KEYFIELD( duration, FIELD_FLOAT, "freepass_duration"), |
|
DEFINE_KEYFIELD( moveTolerance, FIELD_FLOAT, "freepass_movetolerance"), |
|
DEFINE_KEYFIELD( refillRate, FIELD_FLOAT, "freepass_refillrate"), |
|
DEFINE_FIELD( coverDist, FIELD_FLOAT), |
|
DEFINE_KEYFIELD( peekTime, FIELD_FLOAT, "freepass_peektime"), |
|
DEFINE_FIELD( peekTimeAfterDamage, FIELD_FLOAT), |
|
DEFINE_FIELD( peekEyeDist, FIELD_FLOAT), |
|
DEFINE_FIELD( peekEyeDistZ, FIELD_FLOAT), |
|
|
|
END_DATADESC() |
|
|
|
BEGIN_SIMPLE_DATADESC( CAI_FreePass ) |
|
|
|
DEFINE_FIELD( m_hTarget, FIELD_EHANDLE ), |
|
DEFINE_FIELD( m_FreePassTimeRemaining, FIELD_FLOAT ), |
|
DEFINE_EMBEDDED( m_FreePassMoveMonitor ), |
|
DEFINE_EMBEDDED( m_Params ), |
|
|
|
END_DATADESC() |
|
|
|
//--------------------------------------------------------- |
|
//--------------------------------------------------------- |
|
|
|
void CAI_FreePass::Reset( float passTime, float moveTolerance ) |
|
{ |
|
CBaseEntity *pTarget = GetPassTarget(); |
|
|
|
if ( !pTarget || m_Params.duration < 0.1 ) |
|
return; |
|
|
|
if ( passTime == -1 ) |
|
{ |
|
m_FreePassTimeRemaining = m_Params.duration; |
|
} |
|
else |
|
{ |
|
m_FreePassTimeRemaining = passTime; |
|
} |
|
|
|
if ( moveTolerance == -1 ) |
|
{ |
|
m_FreePassMoveMonitor.SetMark( pTarget, m_Params.moveTolerance ); |
|
} |
|
else |
|
{ |
|
m_FreePassMoveMonitor.SetMark( pTarget, moveTolerance ); |
|
} |
|
} |
|
|
|
//--------------------------------------------------------- |
|
//--------------------------------------------------------- |
|
|
|
void CAI_FreePass::Update( ) |
|
{ |
|
CBaseEntity *pTarget = GetPassTarget(); |
|
if ( !pTarget || m_Params.duration < 0.1 ) |
|
return; |
|
|
|
//--------------------------------- |
|
// |
|
// Free pass logic |
|
// |
|
AI_EnemyInfo_t *pTargetInfo = GetOuter()->GetEnemies()->Find( pTarget ); |
|
|
|
// This works with old data because need to do before base class so as to not choose as enemy |
|
if ( !HasPass() ) |
|
{ |
|
float timePlayerLastSeen = (pTargetInfo) ? pTargetInfo->timeLastSeen : AI_INVALID_TIME; |
|
float lastTimeDamagedBy = (pTargetInfo) ? pTargetInfo->timeLastReceivedDamageFrom : AI_INVALID_TIME; |
|
|
|
if ( timePlayerLastSeen == AI_INVALID_TIME || gpGlobals->curtime - timePlayerLastSeen > .15 ) // If didn't see the player last think |
|
{ |
|
trace_t tr; |
|
UTIL_TraceLine( pTarget->EyePosition(), GetOuter()->EyePosition(), MASK_BLOCKLOS, GetOuter(), COLLISION_GROUP_NONE, &tr ); |
|
if ( tr.fraction != 1.0 && tr.m_pEnt != pTarget ) |
|
{ |
|
float dist = (tr.endpos - tr.startpos).Length() * tr.fraction; |
|
|
|
if ( dist < m_Params.coverDist ) |
|
{ |
|
if ( ( timePlayerLastSeen == AI_INVALID_TIME || gpGlobals->curtime - timePlayerLastSeen > m_Params.timeToTrigger ) && |
|
( lastTimeDamagedBy == AI_INVALID_TIME || gpGlobals->curtime - lastTimeDamagedBy > m_Params.timeToTrigger ) ) |
|
{ |
|
m_FreePassTimeRemaining = m_Params.duration; |
|
m_FreePassMoveMonitor.SetMark( pTarget, m_Params.moveTolerance ); |
|
} |
|
} |
|
} |
|
} |
|
} |
|
else |
|
{ |
|
float temp = m_FreePassTimeRemaining; |
|
m_FreePassTimeRemaining = 0; |
|
CAI_Senses *pSenses = GetOuter()->GetSenses(); |
|
bool bCanSee = ( pSenses && pSenses->ShouldSeeEntity( pTarget ) && pSenses->CanSeeEntity( pTarget ) ); |
|
m_FreePassTimeRemaining = temp; |
|
|
|
if ( bCanSee ) |
|
{ |
|
if ( !m_FreePassMoveMonitor.TargetMoved( pTarget ) ) |
|
m_FreePassTimeRemaining -= 0.1; |
|
else |
|
Revoke( true ); |
|
} |
|
else |
|
{ |
|
m_FreePassTimeRemaining += 0.1 * m_Params.refillRate; |
|
if ( m_FreePassTimeRemaining > m_Params.duration ) |
|
m_FreePassTimeRemaining = m_Params.duration; |
|
m_FreePassMoveMonitor.SetMark( pTarget, m_Params.moveTolerance ); |
|
} |
|
} |
|
} |
|
|
|
//--------------------------------------------------------- |
|
//--------------------------------------------------------- |
|
bool CAI_FreePass::HasPass() |
|
{ |
|
return ( m_FreePassTimeRemaining > 0 ); |
|
} |
|
|
|
//--------------------------------------------------------- |
|
//--------------------------------------------------------- |
|
void CAI_FreePass::Revoke( bool bUpdateMemory ) |
|
{ |
|
m_FreePassTimeRemaining = 0; |
|
if ( bUpdateMemory && GetPassTarget() ) |
|
{ |
|
GetOuter()->UpdateEnemyMemory( GetPassTarget(), GetPassTarget()->GetAbsOrigin() ); |
|
} |
|
} |
|
|
|
//--------------------------------------------------------- |
|
//--------------------------------------------------------- |
|
bool CAI_FreePass::ShouldAllowFVisible(bool bBaseResult ) |
|
{ |
|
CBaseEntity * pTarget = GetPassTarget(); |
|
AI_EnemyInfo_t *pTargetInfo = GetOuter()->GetEnemies()->Find( pTarget ); |
|
|
|
if ( !bBaseResult || HasPass() ) |
|
return false; |
|
|
|
bool bIsVisible = true; |
|
|
|
// Peek logic |
|
if ( m_Params.peekTime > 0.1 ) |
|
{ |
|
float lastTimeSeen = (pTargetInfo) ? pTargetInfo->timeLastSeen : AI_INVALID_TIME; |
|
float lastTimeDamagedBy = (pTargetInfo) ? pTargetInfo->timeLastReceivedDamageFrom : AI_INVALID_TIME; |
|
|
|
if ( ( lastTimeSeen == AI_INVALID_TIME || gpGlobals->curtime - lastTimeSeen > m_Params.peekTime ) && |
|
( lastTimeDamagedBy == AI_INVALID_TIME || gpGlobals->curtime - lastTimeDamagedBy > m_Params.peekTimeAfterDamage ) ) |
|
{ |
|
Vector vToTarget; |
|
|
|
VectorSubtract( pTarget->EyePosition(), GetOuter()->EyePosition(), vToTarget ); |
|
vToTarget.z = 0.0f; |
|
VectorNormalize( vToTarget ); |
|
|
|
Vector vecRight( -vToTarget.y, vToTarget.x, 0.0f ); |
|
trace_t tr; |
|
|
|
UTIL_TraceLine( GetOuter()->EyePosition(), pTarget->EyePosition() + (vecRight * m_Params.peekEyeDist - Vector( 0, 0, m_Params.peekEyeDistZ )), MASK_BLOCKLOS, GetOuter(), COLLISION_GROUP_NONE, &tr ); |
|
if ( tr.fraction != 1.0 && tr.m_pEnt != pTarget ) |
|
{ |
|
if ( free_pass_peek_debug.GetBool() ) |
|
NDebugOverlay::Line( tr.startpos, tr.endpos - Vector( 0, 0, 2), 0, 255, 0, false, 0.1 ); |
|
bIsVisible = false; |
|
} |
|
|
|
if ( bIsVisible ) |
|
{ |
|
UTIL_TraceLine( GetOuter()->EyePosition(), pTarget->EyePosition() + (-vecRight * m_Params.peekEyeDist - Vector( 0, 0, m_Params.peekEyeDistZ )), MASK_BLOCKLOS, GetOuter(), COLLISION_GROUP_NONE, &tr ); |
|
if ( tr.fraction != 1.0 && tr.m_pEnt != pTarget ) |
|
{ |
|
if ( free_pass_peek_debug.GetBool() ) |
|
NDebugOverlay::Line( tr.startpos, tr.endpos - Vector( 0, 0, 2), 0, 255, 0, false, 0.1 ); |
|
bIsVisible = false; |
|
} |
|
} |
|
} |
|
|
|
if ( bIsVisible && free_pass_peek_debug.GetBool() ) |
|
NDebugOverlay::Line( GetOuter()->EyePosition(), pTarget->EyePosition() - Vector( 0, 0, 2), 255, 0, 0, false, 0.1 ); |
|
} |
|
|
|
return bIsVisible; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
//----------------------------------------------------------------------------- |
|
|
|
string_t g_iszFuncBrushClassname = NULL_STRING; |
|
|
|
//----------------------------------------------------------------------------- |
|
CTraceFilterNav::CTraceFilterNav( CAI_BaseNPC *pProber, bool bIgnoreTransientEntities, const IServerEntity *passedict, int collisionGroup, bool bAllowPlayerAvoid ) : |
|
CTraceFilterSimple( passedict, collisionGroup ), |
|
m_pProber(pProber), |
|
m_bIgnoreTransientEntities(bIgnoreTransientEntities), |
|
m_bAllowPlayerAvoid(bAllowPlayerAvoid) |
|
{ |
|
m_bCheckCollisionTable = g_EntityCollisionHash->IsObjectInHash( pProber ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
bool CTraceFilterNav::ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask ) |
|
{ |
|
IServerEntity *pServerEntity = (IServerEntity*)pHandleEntity; |
|
CBaseEntity *pEntity = (CBaseEntity *)pServerEntity; |
|
|
|
if ( m_pProber == pEntity ) |
|
return false; |
|
|
|
if ( m_pProber->GetMoveProbe()->ShouldBrushBeIgnored( pEntity ) == true ) |
|
return false; |
|
|
|
#ifdef HL1_DLL |
|
if ( ( contentsMask & CONTENTS_MOVEABLE ) == 0 ) |
|
{ |
|
if ( pEntity->ClassMatches( "func_pushable" ) ) |
|
return false; |
|
} |
|
#endif |
|
|
|
if ( m_bIgnoreTransientEntities && (pEntity->IsPlayer() || pEntity->IsNPC() ) ) |
|
return false; |
|
|
|
//Adrian - If I'm flagged as using the new collision method, then ignore the player when trying |
|
//to check if I can get somewhere. |
|
if ( m_bAllowPlayerAvoid && m_pProber->ShouldPlayerAvoid() && pEntity->IsPlayer() ) |
|
return false; |
|
|
|
if ( pEntity->IsNavIgnored() ) |
|
return false; |
|
|
|
if ( m_bCheckCollisionTable ) |
|
{ |
|
if ( g_EntityCollisionHash->IsObjectPairInHash( m_pProber, pEntity ) ) |
|
return false; |
|
} |
|
|
|
if ( m_pProber->ShouldProbeCollideAgainstEntity( pEntity ) == false ) |
|
return false; |
|
|
|
return CTraceFilterSimple::ShouldHitEntity( pHandleEntity, contentsMask ); |
|
}
|
|
|