Modified source engine (2017) developed by valve and leaked in 2020. Not for commercial purporses
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.
 
 
 
 
 
 

230 lines
6.1 KiB

//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
// Author: Michael S. Booth (mike@turtlerockstudios.com), 2003
#include "cbase.h"
#include "cs_bot.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//--------------------------------------------------------------------------------------------------------------
bool CCSBot::IsNoiseHeard( void ) const
{
if (m_noiseTimestamp <= 0.0f)
return false;
// primitive reaction time simulation - cannot "hear" noise until reaction time has elapsed
if (gpGlobals->curtime - m_noiseTimestamp >= GetProfile()->GetReactionTime())
return true;
return false;
}
//--------------------------------------------------------------------------------------------------------------
/**
* Listen for enemy noises, and determine if we should react to them.
* Returns true if heard a noise and should move to investigate.
*/
bool CCSBot::HeardInterestingNoise( void )
{
if (IsBlind())
return false;
// don't investigate noises during safe time
if (!IsWellPastSafe())
return false;
// if our disposition is not to investigate, dont investigate
if (GetDisposition() != ENGAGE_AND_INVESTIGATE)
return false;
// listen for enemy noises
if (IsNoiseHeard())
{
// if we are hiding, only react to noises very nearby, depending on how aggressive we are
if (IsAtHidingSpot() && GetNoiseRange() > 100.0f + 400.0f * GetProfile()->GetAggression())
return false;
// chance of investigating is inversely proportional to distance
const float maxNoiseDist = 3000.0f;
float chance = 100.0f * (1.0f - (GetNoiseRange()/maxNoiseDist));
// modify chance by number of friends remaining
// if we have lots of friends, presumably one of them is closer and will check it out
if (GetFriendsRemaining() >= 3)
{
float friendFactor = 5.0f * GetFriendsRemaining();
if (friendFactor > 50.0f)
friendFactor = 50.0f;
chance -= friendFactor;
}
if (RandomFloat( 0.0f, 100.0f ) <= chance)
{
return true;
}
}
return false;
}
//--------------------------------------------------------------------------------------------------------------
/**
* Return true if we hear nearby threatening enemy gunfire within given range
* -1 == infinite range
*/
bool CCSBot::CanHearNearbyEnemyGunfire( float range ) const
{
Vector myOrigin = GetCentroid( this );
// only attend to noise if it just happened
if (gpGlobals->curtime - m_noiseTimestamp > 0.5f)
return false;
// gunfire is high priority
if (m_noisePriority < PRIORITY_HIGH)
return false;
// check noise range
if (range > 0.0f && (myOrigin - m_noisePosition).IsLengthGreaterThan( range ))
return false;
// if we dont have line of sight, it's not threatening (cant get shot)
if (!CanSeeNoisePosition())
return false;
if (IsAttacking() && m_enemy != NULL && GetTimeSinceLastSawEnemy() < 1.0f)
{
// gunfire is only threatening if it is closer than our current enemy
float gunfireDistSq = (m_noisePosition - myOrigin).LengthSqr();
float enemyDistSq = (GetCentroid( m_enemy ) - myOrigin).LengthSqr();
const float muchCloserSq = 100.0f * 100.0f;
if (gunfireDistSq > enemyDistSq - muchCloserSq)
return false;
}
return true;
}
//--------------------------------------------------------------------------------------------------------------
/**
* Return true if we directly see where we think the noise came from
* NOTE: Dont check FOV, since this is used to determine if we should turn our head to look at the noise
* NOTE: Dont use IsVisible(), because smoke shouldnt cause us to not look toward noises
*/
bool CCSBot::CanSeeNoisePosition( void ) const
{
trace_t result;
CTraceFilterNoNPCsOrPlayer traceFilter( this, COLLISION_GROUP_NONE );
UTIL_TraceLine( EyePositionConst(), m_noisePosition + Vector( 0, 0, HalfHumanHeight ), MASK_VISIBLE_AND_NPCS, &traceFilter, &result );
if (result.fraction == 1.0f)
{
// we can see the source of the noise
return true;
}
return false;
}
//--------------------------------------------------------------------------------------------------------------
/**
* Return true if we decided to look towards the most recent noise source
* Assumes m_noisePosition is valid.
*/
bool CCSBot::UpdateLookAtNoise( void )
{
// make sure a noise exists
if (!IsNoiseHeard())
{
return false;
}
Vector spot;
// if we have clear line of sight to noise position, look directly at it
if (CanSeeNoisePosition())
{
/// @todo adjust noise Z to keep consistent with current height while fighting
spot = m_noisePosition + Vector( 0, 0, HalfHumanHeight );
// since we can see the noise spot, forget about it
ForgetNoise();
}
else
{
// line of sight is blocked, bend it
// the bending algorithm is very expensive, throttle how often it is done
if (m_noiseBendTimer.IsElapsed())
{
const float noiseBendLOSInterval = RandomFloat( 0.2f, 0.3f );
m_noiseBendTimer.Start( noiseBendLOSInterval );
// line of sight is blocked, bend it
if (BendLineOfSight( EyePosition(), m_noisePosition, &spot ) == false)
{
m_bendNoisePositionValid = false;
return false;
}
m_bentNoisePosition = spot;
m_bendNoisePositionValid = true;
}
else if (m_bendNoisePositionValid)
{
// use result of prior bend computation
spot = m_bentNoisePosition;
}
else
{
// prior bend failed
return false;
}
}
// it's always important to look at enemy noises, because they come from ... enemies!
PriorityType pri = PRIORITY_HIGH;
// look longer if we're hiding
if (IsAtHidingSpot())
{
// if there is only one enemy left, look for a long time
if (GetEnemiesRemaining() == 1)
{
SetLookAt( "Noise", spot, pri, RandomFloat( 5.0f, 15.0f ), true );
}
else
{
SetLookAt( "Noise", spot, pri, RandomFloat( 3.0f, 5.0f ), true );
}
}
else
{
const float closeRange = 500.0f;
if (GetNoiseRange() < closeRange)
{
// look at nearby enemy noises for a longer time
SetLookAt( "Noise", spot, pri, RandomFloat( 3.0f, 5.0f ), true );
}
else
{
SetLookAt( "Noise", spot, pri, RandomFloat( 1.0f, 2.0f ), true );
}
}
return true;
}