aboutsummaryrefslogtreecommitdiff
path: root/mp/src/game/server/ai_utils.cpp
diff options
context:
space:
mode:
authorJørgen P. Tjernø <[email protected]>2013-12-02 19:31:46 -0800
committerJørgen P. Tjernø <[email protected]>2013-12-02 19:46:31 -0800
commitf56bb35301836e56582a575a75864392a0177875 (patch)
treede61ddd39de3e7df52759711950b4c288592f0dc /mp/src/game/server/ai_utils.cpp
parentMark some more files as text. (diff)
downloadsource-sdk-2013-f56bb35301836e56582a575a75864392a0177875.tar.xz
source-sdk-2013-f56bb35301836e56582a575a75864392a0177875.zip
Fix line endings. WHAMMY.
Diffstat (limited to 'mp/src/game/server/ai_utils.cpp')
-rw-r--r--mp/src/game/server/ai_utils.cpp1160
1 files changed, 580 insertions, 580 deletions
diff --git a/mp/src/game/server/ai_utils.cpp b/mp/src/game/server/ai_utils.cpp
index 3119d2f8..802a1c10 100644
--- a/mp/src/game/server/ai_utils.cpp
+++ b/mp/src/game/server/ai_utils.cpp
@@ -1,580 +1,580 @@
-//========= 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_flMinRestInterval = 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 );
-}
+//========= 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_flMinRestInterval = 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 );
+}