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-22 18:35:54 +02:00
public static ConfigEntry < bool > configEnableLogging ;
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-06-26 18:16:31 +02:00
//so we don't keep repeating ourselves
float cachedFOV ;
string cachedDebugInfo ;
2022-06-20 15:43:15 +02:00
2022-06-22 14:56:37 +02:00
//Return aspect ratio based on game window resolution, currently unused but could be useful in the future
2022-06-20 15:43:15 +02:00
float GetAspectRatio ( )
{
2022-07-03 09:23:48 +02:00
float resX = Convert . ToUInt16 ( Screen . width . ToString ( ) ) ;
float resY = Convert . ToUInt16 ( Screen . height . ToString ( ) ) ;
//string screenWidth = Screen.width.ToString();
//string screenHeight = Screen.height.ToString();
//float resX = Convert.ToUInt16(screenWidth);
//float resY = Convert.ToUInt16(screenHeight);
2022-06-20 15:43:15 +02:00
//Logger.LogInfo("GetAspectRatio(): resX: " + resX + " resY: " + resY);
return ( resX / resY ) ;
}
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 ) ) ) ;
if ( configEnableLogging . Value ) { Logger . LogInfo ( "Calculate HFOV: " + FOV + " Result: " + hFOVRad * Mathf . Rad2Deg ) ; }
2022-06-20 15:43:15 +02:00
2022-07-03 09:23:48 +02:00
return ( float ) ( hFOVRad * Mathf . Rad2Deg ) ;
2022-06-20 15:43:15 +02:00
}
//calculate sensitivity based on FOV difference and coefficient
2022-06-26 18:16:31 +02:00
float CalculateSensitivity ( float aimedFOV , float hipFOV )
2022-07-03 09:23:48 +02:00
{
//clamp to avoid invalid values
aimedFOV = Mathf . Clamp ( aimedFOV , 1f , 75f ) ;
2022-06-26 18:16:31 +02:00
hipFOV = Mathf . Clamp ( hipFOV , 1f , 75f ) ;
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
if ( configUseHFOV . Value )
{
Logger . LogInfo ( "HFOV Hip: " + CalculateHFOV ( hipFOV ) + " HFOV Aim: " + CalculateHFOV ( aimedFOV ) ) ;
aimedFOV = CalculateHFOV ( aimedFOV ) / 2 * Mathf . Deg2Rad ;
hipFOV = CalculateHFOV ( hipFOV ) / 2 * Mathf . Deg2Rad ;
}
else
{
aimedFOV = aimedFOV / 2 * Mathf . Deg2Rad ;
hipFOV = hipFOV / 2 * Mathf . Deg2Rad ;
}
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-06-26 18:16:31 +02:00
float tanRatio = ( float ) ( Math . Tan ( aimedFOV ) / Math . Tan ( hipFOV ) ) ;
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-06-26 18:16:31 +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
if ( FPSCameraFOV > 35 & & isScopeCameraActive ( ) & & ScopeFOV = = 15 ) { currentFOV = FPSCameraFOV ; }
2022-06-22 14:56:37 +02:00
}
2022-06-22 18:35:54 +02:00
void LogDebugInfo ( )
{
2022-06-26 18:16:31 +02:00
//preformatted debug info string
string currentDebugInfo = $"Current FOV: {currentFOV} FPS Camera FOV: {FPSCameraFOV} Scope FOV: {ScopeFOV} Cached FOV: {cachedFOV} Sens: {mySens} SelectedScope: {SelectedScope}" ;
//only output currentDebugInfo if there were any changes
if ( currentDebugInfo ! = cachedDebugInfo )
{
Logger . LogInfo ( currentDebugInfo ) ; cachedDebugInfo = currentDebugInfo ;
}
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-22 18:35:54 +02:00
//enable logging
configEnableLogging = Config . Bind ( "Debug" , "Enable logging" , false , new ConfigDescription ( "Enables logging in BepInEx console, extremely spammy!" ) ) ;
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-06-22 22:19:14 +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-06-20 15:43:15 +02:00
FPSCameraFOV = Camera . allCameras [ 0 ] . fieldOfView ;
2022-06-22 14:56:37 +02:00
if ( Camera . allCamerasCount > 1 ) { ScopeFOV = Camera . allCameras [ 1 ] . fieldOfView ; }
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
//if(FPSCameraFOV < configFOV.Value)
if ( FPSCameraFOV < 75 )
{
DetermineCurrentFOV ( ) ;
//do not update sensitivity if currentFOV hasn't changed
if ( cachedFOV ! = currentFOV ) { mySens = CalculateSensitivity ( currentFOV , configFOV . Value ) ; cachedFOV = currentFOV ; }
}
2022-06-20 15:43:15 +02:00
}
2022-06-22 14:56:37 +02:00
2022-06-26 18:16:31 +02:00
//draw debug info
2022-07-03 09:23:48 +02:00
if ( configEnableLogging . Value ) { LogDebugInfo ( ) ; }
2022-06-20 15:43:15 +02:00
}
2022-06-20 14:08:15 +02:00
}
}
2022-06-22 14:56:37 +02:00