diff --git a/TarkovUniformAim.sln b/TarkovUniformAim.sln
new file mode 100644
index 0000000..910d6a5
--- /dev/null
+++ b/TarkovUniformAim.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.2.32602.215
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TarkovUniformAim", "TarkovUniformAim\TarkovUniformAim.csproj", "{B2F4587D-CFE6-42A6-8462-A884EB6E15CD}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {B2F4587D-CFE6-42A6-8462-A884EB6E15CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B2F4587D-CFE6-42A6-8462-A884EB6E15CD}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B2F4587D-CFE6-42A6-8462-A884EB6E15CD}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B2F4587D-CFE6-42A6-8462-A884EB6E15CD}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {49C52BAD-50C6-43D2-AF11-112E812415E4}
+ EndGlobalSection
+EndGlobal
diff --git a/TarkovUniformAim/Properties/AssemblyInfo.cs b/TarkovUniformAim/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..50f6d6c
--- /dev/null
+++ b/TarkovUniformAim/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("TarkovUniformAim")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("TarkovUniformAim")]
+[assembly: AssemblyCopyright("Copyright © 2022")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("b2f4587d-cfe6-42a6-8462-a884eb6e15cd")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/TarkovUniformAim/TarkovUniformAim.csproj b/TarkovUniformAim/TarkovUniformAim.csproj
new file mode 100644
index 0000000..0bf7c0a
--- /dev/null
+++ b/TarkovUniformAim/TarkovUniformAim.csproj
@@ -0,0 +1,64 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {B2F4587D-CFE6-42A6-8462-A884EB6E15CD}
+ Library
+ Properties
+ TarkovUniformAim
+ TarkovUniformAim
+ v4.8
+ 512
+ true
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ E:\SPT-AKI\SPT-AKI 2.3.1 UniformAimTest\EscapeFromTarkov_Data\Managed\Aki.Reflection.dll
+
+
+ ..\..\libs\EFT Trainer DLLs\Assembly-CSharp.dll
+
+
+ ..\..\MyFirstPlugin\MyFirstPlugin\lib\BepInEx.dll
+
+
+
+
+
+
+
+
+
+
+ ..\..\MyFirstPlugin\MyFirstPlugin\lib\UnityEngine.dll
+
+
+ ..\..\MyFirstPlugin\MyFirstPlugin\lib\UnityEngine.CoreModule.dll
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/TarkovUniformAim/UniformAimPatch.cs b/TarkovUniformAim/UniformAimPatch.cs
new file mode 100644
index 0000000..01dfb82
--- /dev/null
+++ b/TarkovUniformAim/UniformAimPatch.cs
@@ -0,0 +1,21 @@
+using System.Reflection;
+using Aki.Reflection.Patching;
+using EFT;
+using UniformAim;
+
+namespace TarkovUniformAim
+{
+ public class UpdateSensitivityPatch : ModulePatch
+ {
+ protected override MethodBase GetTargetMethod()
+ {
+ return typeof(Player.FirearmController).GetMethod("UpdateSensitivity");
+ }
+
+ [PatchPostfix]
+ public static void PatchPostfix(ref float ____aimingSens)
+ {
+ ____aimingSens = UniformAimUtils.adjustedSensitivity;
+ }
+ }
+}
diff --git a/TarkovUniformAim/UniformAimUtils.cs b/TarkovUniformAim/UniformAimUtils.cs
new file mode 100644
index 0000000..b5d5dc3
--- /dev/null
+++ b/TarkovUniformAim/UniformAimUtils.cs
@@ -0,0 +1,129 @@
+using BepInEx;
+using BepInEx.Configuration;
+using System;
+using UnityEngine;
+using TarkovUniformAim;
+
+namespace UniformAim
+{
+
+ [BepInPlugin("com.greg.tarkovuniformaim", "Uniform Aim for Tarkov", "0.1.1")]
+ [BepInProcess("EscapeFromTarkov.exe")]
+
+ public class UniformAimConfig : BaseUnityPlugin
+ {
+ //Bepinex.Configurator fields
+ public static ConfigEntry configFOV;
+ public static ConfigEntry configCoeff;
+ public static ConfigEntry configSens;
+
+ void Awake()
+ {
+
+ //Enable uniform aim patch
+ new UpdateSensitivityPatch().Enable();
+
+ //add configuration slider for field of view
+ configFOV = Config.Bind("General", "FOV", 75, new ConfigDescription("In-game Field of View value", new AcceptableValueRange(50, 75)));
+
+ //add coefficient slider
+ configCoeff = Config.Bind("General", "Coefficient", 1.33f, new ConfigDescription("Coefficient - increases sensitivity at higher zoom levels, default 4/3", new AcceptableValueRange(0.001f, 5.0f)));
+
+ //add secondary sensitivity slider for greater control
+ configSens = Config.Bind("General", "Sensitivity", 25, new ConfigDescription("Secondary sensitivity multiplier in case Tarkov's default isn't enough", new AcceptableValueRange(1, 200)));
+
+ }
+ }
+
+ public class UniformAimUtils : MonoBehaviour
+ {
+ //Return aspect ratio based on game window resolution
+ 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);
+ }
+ //convert degrees to radians
+ float Deg2Rad(float angle)
+ {
+ return (float)(angle * Math.PI / 180);
+ }
+ //convert radians to degrees
+ float Rad2Deg(float radian)
+ {
+ return (float)(radian * 180 / Math.PI);
+ }
+ //calculate horizontal FOV based on vertical FOV
+ float CalculateHFOV(float FOV)
+ {
+ float vFOVRad = Deg2Rad(FOV);
+ float hFOVRad = (float)(2 * Math.Atan(Math.Tan(Deg2Rad(FOV) / 2) * GetAspectRatio()));
+
+ return (float)(Math.Round(Rad2Deg(hFOVRad)));
+ }
+ //calculate sensitivity based on FOV difference and coefficient
+ float CalculateSensitivity(float aimedFOV, float hipFOV)
+ { //clamp to avoid invalid values
+ aimedFOV = Mathf.Clamp(aimedFOV, 0.001f, 90f);
+ hipFOV = Mathf.Clamp(hipFOV, 0.001f, 90f);
+
+ //halve and convert to radians
+ aimedFOV = Deg2Rad(aimedFOV / 2);
+ hipFOV = Deg2Rad(hipFOV / 2);
+
+ //ratio of tangents as sensitivity
+ float sensitivity = (float)(Math.Tan(aimedFOV) / Math.Tan(hipFOV));
+
+ return sensitivity;
+
+
+ }
+
+ public static float adjustedSensitivity = -1f;
+
+ float lastFOV = -1f;
+ float lastFOV2 = -1f;
+
+ float FPSCameraFOV = -1f;
+ float ScopeFOV = -1f;
+ float currentFOV = -1f;
+
+ void Update()
+ {
+ if (Camera.allCamerasCount >= 1)
+ {
+ FPSCameraFOV = Camera.allCameras[0].fieldOfView;
+ }
+ if (Camera.allCamerasCount >= 2)
+ {
+ ScopeFOV = Camera.allCameras[1].fieldOfView;
+ }
+ if (Camera.allCamerasCount >= 1 && FPSCameraFOV != lastFOV)
+ {
+ //Logger.LogInfo("[0] FOV: " + FPSCameraFOV);
+ lastFOV = FPSCameraFOV;
+ }
+ if (Camera.allCamerasCount >= 2 && ScopeFOV != lastFOV2)
+ {
+ //Logger.LogInfo("[1] FOV: " + ScopeFOV);
+ lastFOV2 = ScopeFOV;
+ }
+
+ //nasty workaround for sensitivity while using PIP scopes, WILL break when FOV is set to 50
+ if (35 < FPSCameraFOV && FPSCameraFOV < UniformAimConfig.configFOV.Value) { currentFOV = FPSCameraFOV; }
+ if (Camera.allCamerasCount >= 2)
+ {
+ if (FPSCameraFOV == 35) { currentFOV = ScopeFOV; }
+ if (FPSCameraFOV == UniformAimConfig.configFOV.Value - 15) { currentFOV = FPSCameraFOV; }
+ }
+
+ adjustedSensitivity = CalculateSensitivity(currentFOV, UniformAimConfig.configFOV.Value) * 0.25f; //(float)(UniformAimConfig.configSens.Value/100)
+
+ }
+ }
+}