Code has been reorganized and cleaned up.
Removed HFOV toggle - it's the default way now. Added FOV Range Override for compatibility with FOV-extension mods. Some values should now be grabbed from the game.
This commit is contained in:
parent
eea9786bab
commit
c92693880c
@ -44,10 +44,18 @@
|
||||
<Reference Include="BepInEx">
|
||||
<HintPath>..\..\MyFirstPlugin\MyFirstPlugin\lib\BepInEx.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Comfort, Version=1.0.0.4, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>E:\SPT-AKI\SPT-AKI 3.0.0\EscapeFromTarkov_Data\Managed\Comfort.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\libs\EFT Trainer DLLs\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Sirenix.Serialization, Version=3.0.4.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>E:\SPT-AKI\SPT-AKI 3.0.0\EscapeFromTarkov_Data\Managed\Sirenix.Serialization.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
@ -64,6 +72,8 @@
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="UniformAimUtils.cs" />
|
||||
<Compile Include="UniformAimCore.cs" />
|
||||
<Compile Include="UniformAimPlugin.cs" />
|
||||
<Compile Include="UniformAimPatch.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
|
57
TarkovUniformAim/UniformAimCore.cs
Normal file
57
TarkovUniformAim/UniformAimCore.cs
Normal file
@ -0,0 +1,57 @@
|
||||
using BepInEx;
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace UniformAim
|
||||
{
|
||||
public class Core
|
||||
{
|
||||
//math stuff
|
||||
//Get screen aspect ratio
|
||||
public static float GetAspectRatio()
|
||||
{
|
||||
return Camera.allCameras[0].aspect;
|
||||
}
|
||||
//Calculate horizontal FOV based on vertical FOV and aspect ratio
|
||||
public static float CalculateHFOV(float FOV)
|
||||
{
|
||||
float vFOVRad = FOV / 2 * Mathf.Deg2Rad;
|
||||
float hFOVRad = (float)(2 * Math.Atan(GetAspectRatio() * Math.Tan(vFOVRad)));
|
||||
|
||||
return (float)(hFOVRad * Mathf.Rad2Deg);
|
||||
}
|
||||
|
||||
//calculate sensitivity based on FOV delta and coefficient
|
||||
public static float CalculateSensitivity(float aimedFOV, float hipFOV)
|
||||
{
|
||||
//calculate horizontal FOV values for inputs
|
||||
aimedFOV = CalculateHFOV(aimedFOV) * Mathf.Deg2Rad;
|
||||
hipFOV = CalculateHFOV(hipFOV) * Mathf.Deg2Rad;
|
||||
|
||||
float exponent = (float)(100f / Plugin.configCoeff.Value);
|
||||
|
||||
float tanRatio = (float)(Math.Tan(aimedFOV / 2) / (Math.Tan(hipFOV / 2)));
|
||||
|
||||
float sensitivity = Plugin.configSens.Value / 100f;
|
||||
|
||||
float result = (float)Math.Pow(tanRatio, exponent) * sensitivity;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//check if BaseOpticCamera is present and active
|
||||
public static bool isScopeCameraActive()
|
||||
{
|
||||
if(Camera.allCamerasCount > 1) { return Camera.allCameras[1].GetComponent<Behaviour>().isActiveAndEnabled; }
|
||||
return false;
|
||||
}
|
||||
//figure out current fov based on scope and in-game camera statuses
|
||||
public static float DetermineCurrentFOV()
|
||||
{
|
||||
//dirty fix for the Ultima MP-155 shotgun
|
||||
if (Plugin.currentFPSCameraFOV> 35 && isScopeCameraActive() && Plugin.currentScopeCameraFOV == 15) { return Plugin.currentFPSCameraFOV; }
|
||||
|
||||
if (Plugin.SelectedScope == 0 && isScopeCameraActive()) { return Plugin.currentScopeCameraFOV; } else { return Plugin.currentFPSCameraFOV; }
|
||||
}
|
||||
}
|
||||
}
|
@ -2,6 +2,7 @@
|
||||
using EFT;
|
||||
using System.Reflection;
|
||||
|
||||
|
||||
namespace UniformAim
|
||||
{
|
||||
public class UpdateSensitivityPatch : ModulePatch
|
||||
@ -67,6 +68,4 @@ namespace UniformAim
|
||||
Plugin.isAiming = ____isAiming;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,26 +1,30 @@
|
||||
using BepInEx;
|
||||
using BepInEx.Configuration;
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
|
||||
namespace UniformAim
|
||||
{
|
||||
[BepInPlugin("com.greg.tarkovuniformaim", "Uniform Aim for Tarkov", "1.0.0")]
|
||||
[BepInPlugin("com.greg.tarkovuniformaim", "Uniform Aim for Tarkov", "1.1.0")]
|
||||
[BepInProcess("EscapeFromTarkov.exe")]
|
||||
|
||||
public class Plugin : BaseUnityPlugin
|
||||
{
|
||||
//Bepinex.Configurator fields
|
||||
public static ConfigEntry<int> configFOV;
|
||||
int[] FOVRange = new int[2] { 50, 75 };
|
||||
public static ConfigEntry<bool> configFOVRangeOverride;
|
||||
|
||||
public static ConfigEntry<int> configCoeff;
|
||||
public static ConfigEntry<int> configSens;
|
||||
public static ConfigEntry<bool> configUseHFOV;
|
||||
public static ConfigEntry<bool> configDebug;
|
||||
|
||||
//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
|
||||
//only for persistence
|
||||
public static ConfigEntry<float> inGameSens;
|
||||
|
||||
public static float mySens = 1f;
|
||||
public static float aimingSens;
|
||||
//public static float aimingSens;
|
||||
|
||||
//sight data for hacky workarounds
|
||||
public static int SelectedScope = 0;
|
||||
@ -28,66 +32,18 @@ namespace UniformAim
|
||||
public static bool isAiming = false;
|
||||
|
||||
//human-friendly names for variables used later
|
||||
float FPSCameraFOV;
|
||||
float ScopeFOV;
|
||||
float currentFOV;
|
||||
public static float baseCameraFOV = 75;
|
||||
public static float currentFPSCameraFOV = 75;
|
||||
public static float currentScopeCameraFOV = 75;
|
||||
|
||||
//values to prevent unnecessary repetition
|
||||
float cachedFOV;
|
||||
string cachedDebugInfo;
|
||||
|
||||
//aspect ratio for further calculations
|
||||
float GetAspectRatio()
|
||||
void printDebug()
|
||||
{
|
||||
return Camera.allCameras[0].aspect;
|
||||
}
|
||||
//calculate horizontal FOV based on vertical FOV, currently unused but could be useful in the future
|
||||
float CalculateHFOV(float FOV)
|
||||
{
|
||||
float vFOVRad = FOV / 2 * Mathf.Deg2Rad;
|
||||
float hFOVRad = (float)(2 * Math.Atan(GetAspectRatio() * Math.Tan(vFOVRad)));
|
||||
|
||||
return (float)(hFOVRad * Mathf.Rad2Deg);
|
||||
}
|
||||
//calculate sensitivity based on FOV difference and the coefficient
|
||||
float CalculateSensitivity(float aimedFOV, float hipFOV)
|
||||
{
|
||||
//clamp to avoid invalid values
|
||||
aimedFOV = Mathf.Clamp(aimedFOV, 1f, 75f) * Mathf.Deg2Rad;
|
||||
hipFOV = Mathf.Clamp(hipFOV, 1f, 75f) * Mathf.Deg2Rad;
|
||||
|
||||
//check if configUseHFOV is enabled, convert to horizontal degrees if true
|
||||
if (configUseHFOV.Value)
|
||||
{
|
||||
aimedFOV = CalculateHFOV(aimedFOV);
|
||||
hipFOV = CalculateHFOV(hipFOV);
|
||||
}
|
||||
|
||||
float exponent = (float)(100f / configCoeff.Value);
|
||||
|
||||
float tanRatio = (float)(Math.Tan(aimedFOV / 2) / Math.Tan(hipFOV / 2));
|
||||
|
||||
float sensitivity = configSens.Value / 100f;
|
||||
|
||||
float result = (float)Math.Pow(tanRatio, exponent) * sensitivity;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//determine if the player is looking through the scope
|
||||
bool isScopeCameraActive()
|
||||
{
|
||||
if (Camera.allCamerasCount > 1) { return Camera.allCameras[1].GetComponent<Behaviour>().isActiveAndEnabled; }
|
||||
return false;
|
||||
}
|
||||
|
||||
//determine the correct FOV for calculations
|
||||
void DetermineCurrentFOV()
|
||||
{
|
||||
if (SelectedScope == 0 && isScopeCameraActive()) { currentFOV = ScopeFOV; } else { currentFOV = FPSCameraFOV; }
|
||||
|
||||
//dirty fix for the Ultima MP-155 shotgun
|
||||
if (FPSCameraFOV > 35 && isScopeCameraActive() && ScopeFOV == 15) { currentFOV = FPSCameraFOV; }
|
||||
Logger.LogInfo($"\nIn-Game FOV: {configFOV.Value} In-Game Sens: {inGameSens.Value} FOV Override: {configFOVRangeOverride.Value}" +
|
||||
$"\nFPS Camera FOV: {currentFPSCameraFOV} / {Core.CalculateHFOV(currentFPSCameraFOV)} BaseOpticCamera FOV: {currentScopeCameraFOV} / {Core.CalculateHFOV(currentScopeCameraFOV)} CurrentFOV: {Core.DetermineCurrentFOV()} / {Core.CalculateHFOV(Core.DetermineCurrentFOV())}" +
|
||||
$"\nisAiming? {isAiming} SelectedScope: {SelectedScope} SelectedScopeMode:{SelectedScopeMode}" +
|
||||
$"\nCalculated sensitivity: {Core.CalculateSensitivity(Core.DetermineCurrentFOV(), baseCameraFOV)}" +
|
||||
$"\nAspect Ratio: {Core.GetAspectRatio()}" +
|
||||
$"\nFinal Sensitivity: {mySens * inGameSens.Value}");
|
||||
}
|
||||
|
||||
void Awake()
|
||||
@ -98,38 +54,64 @@ namespace UniformAim
|
||||
new get_SelectedScopeModePatch().Enable();
|
||||
new get_IsAimingPatch().Enable();
|
||||
|
||||
//override FOV range
|
||||
configFOVRangeOverride = Config.Bind("General", "FOV Override", false, new ConfigDescription("Override FOV range for compatibility with other mods. Requires restart."));
|
||||
if (configFOVRangeOverride.Value)
|
||||
{
|
||||
FOVRange[0] = 1; FOVRange[1] = 178;
|
||||
}
|
||||
|
||||
//add configuration slider for field of view
|
||||
configFOV = Config.Bind("General", "FOV", 75, new ConfigDescription("In-game Field of View value", new AcceptableValueRange<int>(51, 75)));
|
||||
configFOV = Config.Bind("General", "FOV", 75, new ConfigDescription("In-game Field of View value", new AcceptableValueRange<int>(FOVRange[0], FOVRange[1])));
|
||||
|
||||
//add coefficient slider
|
||||
configCoeff = Config.Bind("General", "Coefficient", 133, new ConfigDescription("Coefficient - increases sensitivity at higher zoom levels", new AcceptableValueRange<int>(1, 300)));
|
||||
|
||||
//add sensitivity slider
|
||||
configSens = Config.Bind("General", "Sensitivity", 25, new ConfigDescription("Sensitivity while aiming", new AcceptableValueRange<int>(1, 200)));
|
||||
configSens = Config.Bind("General", "Sensitivity", 100, new ConfigDescription("Fine control over sensitivity while aiming", new AcceptableValueRange<int>(1, 200)));
|
||||
|
||||
//enable debug logging
|
||||
configDebug = Config.Bind("Debug", "Enable logging?", false, new ConfigDescription("Enables logging in BepInEx console"));
|
||||
|
||||
//settings for persistence, these values get updated when the in-game menu is opened
|
||||
inGameSens = Config.Bind("¡Do not touch unless necessary!", "In-game Aiming Sensitivity value", 0.5f, new ConfigDescription("Should update on its own - kept for persistence between sessions.", new AcceptableValueRange<float>(0.1f, 5.0f)));
|
||||
|
||||
//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."));
|
||||
}
|
||||
|
||||
void FixedUpdate()
|
||||
{
|
||||
//FixedUpdate() at 50Hz (Unity default) tickrate appears to resolve the issue of this script breaking when AI spawns.
|
||||
//FixedUpdate() at 50Hz (Unity default) tickrate appears to resolve the issue of this script breaking when AI spawns
|
||||
Time.fixedDeltaTime = (1f / 50f);
|
||||
|
||||
if (isAiming)
|
||||
{
|
||||
//Grab FOV values for calculation
|
||||
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
|
||||
//check if the game is running
|
||||
var isRunning = Utils.checkIsReady();
|
||||
if (!isRunning) return;
|
||||
|
||||
//Figure out if the FPSCamera is zoomed in, prevents the script from ticking while the player is healing
|
||||
if (FPSCameraFOV < configFOV.Value)
|
||||
if (isRunning)
|
||||
{
|
||||
if (Utils.SetRootObject() != null) {
|
||||
var rootObject = Utils.SetRootObject();
|
||||
//only update these values if the menu has been opened, otherwise read the config
|
||||
if (rootObject.transform.Find("Game Settings").gameObject.activeInHierarchy)
|
||||
{
|
||||
if (!configFOVRangeOverride.Value) { configFOV.Value = 50 + Utils.GetInGameFOV(rootObject); }
|
||||
inGameSens.Value = Utils.GetInGameSens(rootObject);
|
||||
}
|
||||
}
|
||||
//cgheck if the player is aiming
|
||||
if (isAiming)
|
||||
{
|
||||
DetermineCurrentFOV();
|
||||
//do not update sensitivity if currentFOV hasn't changed
|
||||
if (cachedFOV != currentFOV) { mySens = CalculateSensitivity(currentFOV, configFOV.Value); cachedFOV = currentFOV; }
|
||||
//Grab FOV values for calculation
|
||||
currentFPSCameraFOV = Camera.allCameras[0].fieldOfView; //Camera[0] tends to be FPS Camera
|
||||
if (Camera.allCamerasCount > 1) { currentScopeCameraFOV= Camera.allCameras[1].fieldOfView; } //Camera[1] tends to be BaseOpticCamera
|
||||
|
||||
//Figure out if the FPSCamera is zoomed in, prevents the script from ticking while the player is healing
|
||||
if (currentFPSCameraFOV < configFOV.Value) {
|
||||
mySens = inGameSens.Value * Core.CalculateSensitivity(Core.DetermineCurrentFOV(), configFOV.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
//Print debug info in BepInEx console
|
||||
if (configDebug.Value) printDebug();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
66
TarkovUniformAim/UniformAimUtils.cs
Normal file
66
TarkovUniformAim/UniformAimUtils.cs
Normal file
@ -0,0 +1,66 @@
|
||||
using Comfort.Common;
|
||||
using EFT;
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
|
||||
namespace UniformAim
|
||||
{
|
||||
public class Utils
|
||||
{
|
||||
public static bool isPlaying = false;
|
||||
public static GameObject rootObject = null;
|
||||
|
||||
public static bool checkIsReady()
|
||||
{
|
||||
var gameWorld = Singleton<GameWorld>.Instance;
|
||||
var sessionResultPanel = Singleton<SessionResultPanel>.Instance;
|
||||
|
||||
if (gameWorld == null
|
||||
|| gameWorld.AllPlayers == null
|
||||
|| gameWorld.AllPlayers.Count <= 0
|
||||
|| sessionResultPanel != null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool checkPlayerIsAlive()
|
||||
{
|
||||
var gameWorld = Singleton<GameWorld>.Instance;
|
||||
var currentHealth = gameWorld.AllPlayers[0].HealthController.GetBodyPartHealth(EBodyPart.Common).Current;
|
||||
|
||||
if (currentHealth > 0) { return true; } else { return false; }
|
||||
}
|
||||
|
||||
|
||||
public static GameObject SetRootObject()
|
||||
{
|
||||
string path = "Common UI/Common UI/SettingsScreen";
|
||||
|
||||
if(GameObject.Find(path) != null)
|
||||
{
|
||||
GameObject rootObject = GameObject.Find(path);
|
||||
return rootObject;
|
||||
}
|
||||
else { return null; }
|
||||
}
|
||||
|
||||
public static int GetInGameFOV(GameObject root)
|
||||
{
|
||||
GameObject fovObject = root.transform.Find("Game Settings/Image/Other Settings/FOV/FOV").gameObject;
|
||||
int rootFOV = fovObject.GetComponent<EFT.UI.SelectSlider>().CurrentValue();
|
||||
|
||||
return rootFOV;
|
||||
}
|
||||
|
||||
public static float GetInGameSens(GameObject root)
|
||||
{
|
||||
GameObject sensObject = root.transform.Find("Control Settings/ControlPanel/Mouse Settings/Sensitivity Aiming Panel/Mouse Sensitivity Aiming").gameObject;
|
||||
float rootSens = sensObject.GetComponent<EFT.UI.FloatSlider>().CurrentValue();
|
||||
|
||||
return rootSens;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user