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.
 
 
 
 
 
 

168 lines
5.6 KiB

//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: TF2 Accuracy system
//
// $Workfile: $
// $Date: $
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "player.h"
#include "tf_player.h"
#include "basecombatweapon.h"
#include "vstdlib/random.h"
// THIS ISN'T USED ANYMORE. NO REASON TO MAKE OUR HITSCAN WPNS THIS COMPLEX
// Accuracy is measured as the weapons spread in inches at 1024 units (~85 feet)
// Accuracy is sent to the client, where it's used to generate the size of the accuracy representation.
// Accuracy is a "floating" value, in that it's always moving towards a target accuracy, and takes some time to change
// Accuracy Multipliers
// < 1 increases accuracy, > 1 decreases
#define ACCMULT_DUCKING 0.75 // Player is ducking
#define ACCMULT_RUNNING 1.25 // Player is moving >50% of his max speed
// Ricochet Multiplier
// This works differently to other acc multipliers.
#define ACCMULT_RICOCHET 1.0 // Player is being suppressed by bullet fire
#define ACC_RICOCHET_TIME 1.0 // Amount of time accuracy is affected by a ricochet near the player
#define ACC_RICOCHET_MULTIPLE 0.25 // The effect of ricochets on accuracy is multiplied by this by the number of ricochets nearby
#define ACC_RICOCHET_CAP 10 // Maximum number of bullets to register for suppression fire
#define ACCURACY_CHANGE_SPEED 5
//-----------------------------------------------------------------------------
// Purpose: Calculates the players "accuracy" level
//-----------------------------------------------------------------------------
void CBaseTFPlayer::CalculateAccuracy( void )
{
static flLastTime = 0;
// Get the time since the last calculation
float flTimeSlice = (gpGlobals->curtime - flLastTime);
m_flTargetAccuracy = 0;
if ( !GetPlayerClass() )
return;
// Get the base accuracy from the current weapon
if ( m_hActiveWeapon )
{
m_flTargetAccuracy = m_hActiveWeapon->GetAccuracy();
// Accuracy is increased if the player's crouching
if ( GetFlags() & FL_DUCKING )
m_flTargetAccuracy *= m_hActiveWeapon->GetDuckingMultiplier();
// Accuracy is decreased if the player's moving
if ( m_vecVelocity.Length2D() > ( GetPlayerClass()->GetMaxSpeed() * 0.5 ) )
m_flTargetAccuracy *= m_hActiveWeapon->GetRunningMultiplier();
}
// Accuracy is decreased if the player's arms are injured
// Accuracy is increased if there's an Officer nearby
// Accuracy is decreased if this player's being supressed (bullets/explosions impacting nearby)
float flFarTime = (m_flLastRicochetNearby + ACC_RICOCHET_TIME);
if ( gpGlobals->curtime <= flFarTime )
m_flTargetAccuracy *= 1 + (m_flNumberOfRicochets * ACC_RICOCHET_MULTIPLE) * (ACCMULT_RICOCHET * ((flFarTime - gpGlobals->curtime) / ACC_RICOCHET_TIME));
// Accuracy is decreased if the player's just been hit by a bullet/explosion
// Now float towards the target accuracy
if ( m_bSnapAccuracy )
{
m_bSnapAccuracy = false;
m_flAccuracy = m_flTargetAccuracy;
}
else
{
if ( m_flAccuracy < m_flTargetAccuracy )
{
m_flAccuracy += (flTimeSlice * ACCURACY_CHANGE_SPEED);
if ( m_flAccuracy > m_flTargetAccuracy )
m_flAccuracy = m_flTargetAccuracy ;
}
else if ( m_flAccuracy > m_flTargetAccuracy )
{
m_flAccuracy -= (flTimeSlice * ACCURACY_CHANGE_SPEED);
if ( m_flAccuracy < m_flTargetAccuracy )
m_flAccuracy = m_flTargetAccuracy ;
}
}
// Clip to prevent silly accuracies
if ( m_flAccuracy > 1024 )
m_flAccuracy = 1024;
flLastTime = gpGlobals->curtime;
}
//-----------------------------------------------------------------------------
// Purpose: Snap the players accuracy immediately
//-----------------------------------------------------------------------------
void CBaseTFPlayer::SnapAccuracy( void )
{
m_bSnapAccuracy = true;
}
//-----------------------------------------------------------------------------
// Purpose: Return the player's current accuracy
//-----------------------------------------------------------------------------
float CBaseTFPlayer::GetAccuracy( void )
{
return m_flAccuracy;
}
//-----------------------------------------------------------------------------
// Purpose: Bullets / Explosions are hitting near the player. Reduce his/her accuracy.
//-----------------------------------------------------------------------------
void CBaseTFPlayer::Supress( void )
{
if ( gpGlobals->curtime <= (m_flLastRicochetNearby + ACC_RICOCHET_TIME) )
{
m_flNumberOfRicochets = MIN( ACC_RICOCHET_CAP, m_flNumberOfRicochets + 1 );
}
else
{
m_flNumberOfRicochets = 1;
}
m_flLastRicochetNearby = gpGlobals->curtime;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
Vector CBaseTFPlayer::GenerateFireVector( Vector *viewVector )
{
// Calculate the weapon spread from the player's accuracy
float flAcc = (GetAccuracy() * 0.5) / ACCURACY_DISTANCE;
float flAccuracyAngle = RAD2DEG( atan( flAcc ) );
// If the user passed in a viewVector, use it, otherwise use player's v_angle
Vector angShootAngles = viewVector ? *viewVector : pl->v_angle;
if ( flAccuracyAngle )
{
float x, y, z;
do {
x = random->RandomFloat(-0.5,0.5) + random->RandomFloat(-0.5,0.5);
y = random->RandomFloat(-0.5,0.5) + random->RandomFloat(-0.5,0.5);
z = x*x+y*y;
} while (z > 1);
angShootAngles.x = UTIL_AngleMod( angShootAngles.x + (x * flAccuracyAngle) );
angShootAngles.y = UTIL_AngleMod( angShootAngles.y + (y * flAccuracyAngle) );
}
Vector forward;
AngleVectors( angShootAngles, &forward );
return forward;
}