diff options
Diffstat (limited to 'game/server/tf2/tf_accuracy.cpp')
| -rw-r--r-- | game/server/tf2/tf_accuracy.cpp | 168 |
1 files changed, 168 insertions, 0 deletions
diff --git a/game/server/tf2/tf_accuracy.cpp b/game/server/tf2/tf_accuracy.cpp new file mode 100644 index 0000000..db2b342 --- /dev/null +++ b/game/server/tf2/tf_accuracy.cpp @@ -0,0 +1,168 @@ +//========= 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; +} |