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-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;
|
|
|
|
|
//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()
|
|
|
|
|
{
|
|
|
|
|
string screenWidth = Screen.width.ToString();
|
|
|
|
|
string screenHeight = Screen.height.ToString();
|
|
|
|
|
float resX = Convert.ToUInt16(screenWidth);
|
|
|
|
|
float resY = Convert.ToUInt16(screenHeight);
|
|
|
|
|
|
|
|
|
|
//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)
|
|
|
|
|
{
|
|
|
|
|
float vFOVRad = FOV * Mathf.Deg2Rad;
|
|
|
|
|
float hFOVRad = (float)(2 * Math.Atan(Math.Tan(FOV / 2) * Mathf.Deg2Rad) * GetAspectRatio());
|
|
|
|
|
|
|
|
|
|
return (float)(Math.Round(hFOVRad * Mathf.Rad2Deg));
|
|
|
|
|
}
|
|
|
|
|
//calculate sensitivity based on FOV difference and coefficient
|
2022-06-26 18:16:31 +02:00
|
|
|
|
float CalculateSensitivity(float aimedFOV, float hipFOV)
|
2022-06-20 15:43:15 +02:00
|
|
|
|
{ //clamp to avoid invalid values
|
2022-06-26 18:16:31 +02:00
|
|
|
|
aimedFOV = Mathf.Clamp(aimedFOV, 1f, 76f);
|
|
|
|
|
hipFOV = Mathf.Clamp(hipFOV, 1f, 75f);
|
2022-06-20 15:43:15 +02:00
|
|
|
|
|
2022-06-26 18:16:31 +02:00
|
|
|
|
//halve the angle and convert to radians
|
|
|
|
|
aimedFOV = (aimedFOV / 2f) * Mathf.Deg2Rad;
|
|
|
|
|
hipFOV = (hipFOV / 2f) * 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; }
|
|
|
|
|
|
|
|
|
|
//if (isScopeCameraActive())
|
|
|
|
|
//{
|
|
|
|
|
// if (SelectedScope == 0)
|
|
|
|
|
// {
|
|
|
|
|
// currentFOV = ScopeFOV; //Logger.LogInfo("Updating currentFOV to ScopeFOV");
|
|
|
|
|
// }
|
|
|
|
|
// if (SelectedScope != 0)
|
|
|
|
|
// {
|
|
|
|
|
// currentFOV = FPSCameraFOV; //Logger.LogInfo("Updating currentFOV to FPSCameraFOV");
|
|
|
|
|
// }
|
|
|
|
|
//}
|
|
|
|
|
//else
|
|
|
|
|
//{
|
|
|
|
|
// //Logger.LogInfo("Updating currentFOV to FPSCameraFOV");
|
|
|
|
|
// 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-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-26 18:16:31 +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-06-22 18:35:54 +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
|
|
|
|
|