2022-06-20 14:08:15 +02:00
using BepInEx ;
using BepInEx.Configuration ;
2022-06-20 15:43:15 +02:00
using System ;
using UnityEngine ;
2022-06-20 14:08:15 +02:00
2022-06-20 15:43:15 +02:00
namespace UniformAim
2022-06-20 14:08:15 +02:00
{
2022-06-20 20:15:14 +02:00
[BepInPlugin("com.greg.tarkovuniformaim", "Uniform Aim for Tarkov", "1.0.0")]
2022-06-20 14:08:15 +02:00
[BepInProcess("EscapeFromTarkov.exe")]
2022-06-20 15:43:15 +02:00
public class Plugin : BaseUnityPlugin
2022-06-20 14:08:15 +02:00
{
//Bepinex.Configurator fields
public static ConfigEntry < int > configFOV ;
2022-06-20 20:06:49 +02:00
public static ConfigEntry < int > configCoeff ;
2022-06-20 14:08:15 +02:00
public static ConfigEntry < int > configSens ;
2022-07-03 09:23:48 +02:00
public static ConfigEntry < bool > configUseHFOV ;
2022-06-20 14:08:15 +02:00
2022-06-22 14:56:37 +02:00
//TODO: figure out a way to read game settings to default the configFOV.Value to whatever the player has already set
//TODO: figure out a way to read game settings to apply configSens.Value as a multiplier on top of Tarkov's stock sensitivity setting
2022-06-20 15:43:15 +02:00
2022-06-22 14:56:37 +02:00
public static float mySens = 1f ;
2022-06-26 18:16:31 +02:00
public static float aimingSens ;
2022-06-22 14:56:37 +02:00
//sight data for hacky workarounds
public static int SelectedScope = 0 ;
public static int SelectedScopeMode = 0 ;
public static bool isAiming = false ;
2022-06-20 15:43:15 +02:00
2022-06-20 20:06:49 +02:00
//human-friendly names for variables used later
2022-06-26 18:16:31 +02:00
float FPSCameraFOV ;
float ScopeFOV ;
float currentFOV ;
2022-07-03 09:23:48 +02:00
2022-08-02 11:12:35 +02:00
//values to prevent unnecessary repetition
2022-06-26 18:16:31 +02:00
float cachedFOV ;
string cachedDebugInfo ;
2022-06-20 15:43:15 +02:00
2022-08-02 11:12:35 +02:00
//aspect ratio for further calculations
2022-06-20 15:43:15 +02:00
float GetAspectRatio ( )
{
2022-08-02 11:12:35 +02:00
return Camera . allCameras [ 0 ] . aspect ;
2022-06-20 15:43:15 +02:00
}
2022-06-22 14:56:37 +02:00
//calculate horizontal FOV based on vertical FOV, currently unused but could be useful in the future
2022-06-20 15:43:15 +02:00
float CalculateHFOV ( float FOV )
{
2022-07-03 09:23:48 +02:00
float vFOVRad = FOV / 2 * Mathf . Deg2Rad ;
float hFOVRad = ( float ) ( 2 * Math . Atan ( GetAspectRatio ( ) * Math . Tan ( vFOVRad ) ) ) ;
return ( float ) ( hFOVRad * Mathf . Rad2Deg ) ;
2022-06-20 15:43:15 +02:00
}
2022-08-02 11:12:35 +02:00
//calculate sensitivity based on FOV difference and the coefficient
2022-06-26 18:16:31 +02:00
float CalculateSensitivity ( float aimedFOV , float hipFOV )
2022-08-02 11:12:35 +02:00
{
2022-07-03 09:23:48 +02:00
//clamp to avoid invalid values
2022-08-02 11:12:35 +02:00
aimedFOV = Mathf . Clamp ( aimedFOV , 1f , 75f ) * Mathf . Deg2Rad ;
hipFOV = Mathf . Clamp ( hipFOV , 1f , 75f ) * Mathf . Deg2Rad ;
2022-06-20 15:43:15 +02:00
2022-07-03 09:23:48 +02:00
//check if configUseHFOV is enabled, convert to horizontal degrees if true
2022-08-02 11:12:35 +02:00
if ( configUseHFOV . Value )
2022-07-03 09:23:48 +02:00
{
2022-08-02 11:12:35 +02:00
aimedFOV = CalculateHFOV ( aimedFOV ) ;
hipFOV = CalculateHFOV ( hipFOV ) ;
2022-07-03 09:23:48 +02:00
}
2022-06-20 15:43:15 +02:00
2022-06-20 20:06:49 +02:00
float exponent = ( float ) ( 100f / configCoeff . Value ) ;
2022-06-20 15:43:15 +02:00
2022-08-02 11:12:35 +02:00
float tanRatio = ( float ) ( Math . Tan ( aimedFOV / 2 ) / Math . Tan ( hipFOV / 2 ) ) ;
2022-06-26 18:16:31 +02:00
float sensitivity = configSens . Value / 100f ;
2022-06-20 20:06:49 +02:00
float result = ( float ) Math . Pow ( tanRatio , exponent ) * sensitivity ;
return result ;
2022-06-20 15:43:15 +02:00
}
2022-06-26 18:16:31 +02:00
//determine if the player is looking through the scope
2022-06-22 14:56:37 +02:00
bool isScopeCameraActive ( )
{
if ( Camera . allCamerasCount > 1 ) { return Camera . allCameras [ 1 ] . GetComponent < Behaviour > ( ) . isActiveAndEnabled ; }
return false ;
}
2022-06-26 18:16:31 +02:00
//determine the correct FOV for calculations
2022-06-22 14:56:37 +02:00
void DetermineCurrentFOV ( )
{
2022-08-02 11:12:35 +02:00
if ( SelectedScope = = 0 & & isScopeCameraActive ( ) ) { currentFOV = ScopeFOV ; } else { currentFOV = FPSCameraFOV ; }
2022-07-03 09:23:48 +02:00
//dirty fix for the Ultima MP-155 shotgun
2022-08-02 11:12:35 +02:00
if ( FPSCameraFOV > 35 & & isScopeCameraActive ( ) & & ScopeFOV = = 15 ) { currentFOV = FPSCameraFOV ; }
2022-06-22 18:35:54 +02:00
}
2022-06-26 18:16:31 +02:00
2022-06-20 14:08:15 +02:00
void Awake ( )
{
new UpdateSensitivityPatch ( ) . Enable ( ) ;
2022-06-20 20:06:49 +02:00
new get_AimingSensitivityPatch ( ) . Enable ( ) ;
2022-06-22 14:56:37 +02:00
new get_SelectedScopeIndexPatch ( ) . Enable ( ) ;
new get_SelectedScopeModePatch ( ) . Enable ( ) ;
new get_IsAimingPatch ( ) . Enable ( ) ;
2022-06-26 18:16:31 +02:00
2022-06-20 14:08:15 +02:00
//add configuration slider for field of view
2022-06-22 14:56:37 +02:00
configFOV = Config . Bind ( "General" , "FOV" , 75 , new ConfigDescription ( "In-game Field of View value" , new AcceptableValueRange < int > ( 51 , 75 ) ) ) ;
2022-06-20 14:08:15 +02:00
//add coefficient slider
2022-06-20 20:06:49 +02:00
configCoeff = Config . Bind ( "General" , "Coefficient" , 133 , new ConfigDescription ( "Coefficient - increases sensitivity at higher zoom levels" , new AcceptableValueRange < int > ( 1 , 300 ) ) ) ;
2022-06-20 14:08:15 +02:00
2022-06-22 14:56:37 +02:00
//add sensitivity slider
2022-06-20 20:06:49 +02:00
configSens = Config . Bind ( "General" , "Sensitivity" , 25 , new ConfigDescription ( "Sensitivity while aiming" , new AcceptableValueRange < int > ( 1 , 200 ) ) ) ;
2022-06-20 14:08:15 +02:00
2022-07-03 09:23:48 +02:00
//use HFOV instead of VFOV for sensitivity calculations
configUseHFOV = Config . Bind ( "General" , "Use Horizontal FOV?" , true , new ConfigDescription ( "Toggles between using Horizontal FOV and Vertical FOV for sensitivity calculations." ) ) ;
2022-06-20 14:08:15 +02:00
}
2022-06-20 15:43:15 +02:00
2022-06-22 22:19:14 +02:00
void FixedUpdate ( )
2022-06-20 15:43:15 +02:00
{
2022-06-26 18:16:31 +02:00
//FixedUpdate() at 50Hz (Unity default) tickrate appears to resolve the issue of this script breaking when AI spawns.
2022-08-02 11:12:35 +02:00
Time . fixedDeltaTime = ( 1f / 50f ) ;
2022-06-26 18:16:31 +02:00
2022-06-22 14:56:37 +02:00
if ( isAiming )
2022-06-20 15:43:15 +02:00
{
2022-06-22 14:56:37 +02:00
//Grab FOV values for calculation
2022-08-02 11:12:35 +02:00
FPSCameraFOV = Camera . allCameras [ 0 ] . fieldOfView ; //Camera[0] tends to be FPS Camera
if ( Camera . allCamerasCount > 1 ) { ScopeFOV = Camera . allCameras [ 1 ] . fieldOfView ; } //Camera[1] tends to be BaseOpticCamera
2022-06-22 18:35:54 +02:00
2022-06-26 18:16:31 +02:00
//Figure out if the FPSCamera is zoomed in, prevents the script from ticking while the player is healing
2022-08-02 11:12:35 +02:00
if ( FPSCameraFOV < configFOV . Value )
{
2022-06-26 18:16:31 +02:00
DetermineCurrentFOV ( ) ;
//do not update sensitivity if currentFOV hasn't changed
if ( cachedFOV ! = currentFOV ) { mySens = CalculateSensitivity ( currentFOV , configFOV . Value ) ; cachedFOV = currentFOV ; }
2022-08-02 11:12:35 +02:00
}
2022-06-20 15:43:15 +02:00
}
}
2022-06-20 14:08:15 +02:00
}
}
2022-06-22 14:56:37 +02:00