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.
169 lines
5.6 KiB
169 lines
5.6 KiB
5 years ago
|
//========= 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;
|
||
|
}
|