Compare commits
10 Commits
update-3.3
...
master
Author | SHA1 | Date | |
---|---|---|---|
e12a9a69ed | |||
![]() |
090125b836 | ||
4a8da5a6ac | |||
eca93b02cd | |||
60e25fa04a | |||
17341ad1f9 | |||
945bd0fd67 | |||
08f0319d29 | |||
4e5d8d28a5 | |||
abf160f4e7 |
@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00
|
|||||||
# Visual Studio Version 17
|
# Visual Studio Version 17
|
||||||
VisualStudioVersion = 17.2.32602.215
|
VisualStudioVersion = 17.2.32602.215
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TarkovUniformAim", "TarkovUniformAim\TarkovUniformAim.csproj", "{B2F4587D-CFE6-42A6-8462-A884EB6E15CD}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "notGreg.UniformAim", "TarkovUniformAim\notGreg.UniformAim.csproj", "{B2F4587D-CFE6-42A6-8462-A884EB6E15CD}"
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
@ -11,8 +11,8 @@ Global
|
|||||||
Release|Any CPU = Release|Any CPU
|
Release|Any CPU = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
{B2F4587D-CFE6-42A6-8462-A884EB6E15CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{B2F4587D-CFE6-42A6-8462-A884EB6E15CD}.Debug|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{B2F4587D-CFE6-42A6-8462-A884EB6E15CD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{B2F4587D-CFE6-42A6-8462-A884EB6E15CD}.Debug|Any CPU.Build.0 = Release|Any CPU
|
||||||
{B2F4587D-CFE6-42A6-8462-A884EB6E15CD}.Release|Any CPU.ActiveCfg = Release|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
|
{B2F4587D-CFE6-42A6-8462-A884EB6E15CD}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
|
26
TarkovUniformAim/Patch.cs
Normal file
26
TarkovUniformAim/Patch.cs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
using Aki.Reflection.Patching;
|
||||||
|
using EFT;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
namespace notGreg.UniformAim
|
||||||
|
{
|
||||||
|
internal class get_AimingSensitivityPatch : ModulePatch
|
||||||
|
{
|
||||||
|
private float myAimingSens;
|
||||||
|
public float MyAimingSens
|
||||||
|
{
|
||||||
|
get { return myAimingSens; }
|
||||||
|
set { myAimingSens = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override MethodBase GetTargetMethod()
|
||||||
|
{
|
||||||
|
return typeof(Player.FirearmController).GetMethod("get_AimingSensitivity");
|
||||||
|
}
|
||||||
|
[PatchPostfix]
|
||||||
|
public static void PatchPostfix(ref float ____aimingSens)
|
||||||
|
{
|
||||||
|
____aimingSens = Plugin.aimingSens;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
221
TarkovUniformAim/Plugin.cs
Normal file
221
TarkovUniformAim/Plugin.cs
Normal file
@ -0,0 +1,221 @@
|
|||||||
|
using BepInEx;
|
||||||
|
using BepInEx.Bootstrap;
|
||||||
|
using BepInEx.Configuration;
|
||||||
|
using Comfort.Common;
|
||||||
|
using EFT;
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
|
||||||
|
// DLL dependencies needed to update the Uniform Aim Mod for newer versions of the game
|
||||||
|
//%tarkovdir%\BepInEx\core\BepInEx.dll
|
||||||
|
//%tarkovdir%\EscapeFromTarkov_Data\Managed\Assembly-CSharp.dll
|
||||||
|
//%tarkovdir%\EscapeFromTarkov_Data\Managed\Aki.Reflection.dll
|
||||||
|
//%tarkovdir%\EscapeFromTarkov_Data\Managed\Comfort.dll
|
||||||
|
//%tarkovdir%\EscapeFromTarkov_Data\Managed\UnityEngine.dll
|
||||||
|
//%tarkovdir%\EscapeFromTarkov_Data\Managed\UnityEngine.CoreModule.dll
|
||||||
|
|
||||||
|
|
||||||
|
namespace notGreg.UniformAim
|
||||||
|
{
|
||||||
|
[BepInPlugin("com.notGreg.UniformAim", "notGreg's Uniform Aim for Tarkov", "3.8.0")]
|
||||||
|
[BepInDependency("RealismMod", BepInDependency.DependencyFlags.SoftDependency)]
|
||||||
|
public class Plugin : BaseUnityPlugin
|
||||||
|
{
|
||||||
|
ConfigEntry<int> configExponent;
|
||||||
|
ConfigEntry<int> configSens;
|
||||||
|
ConfigEntry<bool> enableDebug;
|
||||||
|
|
||||||
|
public static bool isRealismModPresent = Chainloader.PluginInfos.ContainsKey("RealismMod");
|
||||||
|
|
||||||
|
void Awake()
|
||||||
|
{
|
||||||
|
configExponent = Config.Bind("General", "Coefficient", 133, new ConfigDescription("", new AcceptableValueRange<int>(10, 500)));
|
||||||
|
//configSens = Config.Bind("General", "Sensitivity", 1.0f, new ConfigDescription("", new AcceptableValueRange<float>(0.01f, 2.0f))); // an old float-based sensitivity for future reference
|
||||||
|
configSens = Config.Bind("General", "Sensitivity", 100, new ConfigDescription("", new AcceptableValueRange<int>(10, 200)));
|
||||||
|
|
||||||
|
enableDebug = Config.Bind("Debug", "Enable debug logging", false);
|
||||||
|
|
||||||
|
|
||||||
|
if (!isRealismModPresent)
|
||||||
|
{
|
||||||
|
new get_AimingSensitivityPatch().Enable();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(enableDebug.Value) Logger.LogInfo("RealismMod detected! Abandoning aimingSens patch...\nMake sure to use the compatibility plugin!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Player mainPlayer;
|
||||||
|
int inGameFOV;
|
||||||
|
float inGameAimedSens;
|
||||||
|
public static float aimingSens = 1.0f;
|
||||||
|
|
||||||
|
//this function can be replaced by FixedUpdate() at 50Hz (adjustable via Time.fixedDeltaTime)
|
||||||
|
//FixedUpdate() proved to be slightly more reliable in the past, however it had other unintended effects on the game.
|
||||||
|
void FixedUpdate()
|
||||||
|
{
|
||||||
|
//check if the world instance exists
|
||||||
|
if (Singleton<AbstractGame>.Instance == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//grab the game status of the existing instance
|
||||||
|
GameStatus currentGameStatus = Singleton<AbstractGame>.Instance.Status;
|
||||||
|
|
||||||
|
//check if the game has started and if the player exists. If the player is aiming, update the scoped sensitivity (executed every frame while aiming)
|
||||||
|
if (currentGameStatus == GameStatus.Started && mainPlayer != null)
|
||||||
|
{
|
||||||
|
if (mainPlayer.HandsController.IsAiming)
|
||||||
|
{
|
||||||
|
aimingSens = calculateSensitivity();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(enableDebug.Value) Logger.LogInfo("Switch on GameStatus");
|
||||||
|
switch (currentGameStatus)
|
||||||
|
{
|
||||||
|
case GameStatus.Started:
|
||||||
|
{
|
||||||
|
mainPlayer = getLocalPlayer();
|
||||||
|
if(enableDebug.Value) Logger.LogInfo($"Subscribing to onAimingChanged event");
|
||||||
|
subscribeOnAimingChanged();
|
||||||
|
|
||||||
|
if(enableDebug.Value) Logger.LogInfo("TryGetCameras coroutines");
|
||||||
|
StartCoroutine(tryGetMainCamera());
|
||||||
|
StartCoroutine(tryGetScopeCamera());
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GameStatus.SoftStopping:
|
||||||
|
case GameStatus.Stopped:
|
||||||
|
{
|
||||||
|
mainPlayer = null;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//this function grabs the Field of View from the settings. This is the function that most often needs patching after update.
|
||||||
|
//Appropriate class can usually be found by searching for the "ClearSettings" function.
|
||||||
|
int getInGameFOV()
|
||||||
|
{
|
||||||
|
int fov = Singleton<SharedGameSettingsClass>.Instance.Game.Settings.FieldOfView;
|
||||||
|
return fov;
|
||||||
|
}
|
||||||
|
|
||||||
|
//this function grabs the Aiming Sensitivity from the settings. This is the function that most often needs patching after update.
|
||||||
|
//Appropriate class can usually be found by searching for the "ClearSettings" function.
|
||||||
|
float getInGameAimSens()
|
||||||
|
{
|
||||||
|
float sens = Singleton<SharedGameSettingsClass>.Instance.Control.Settings.MouseAimingSensitivity;
|
||||||
|
if(enableDebug.Value) Logger.LogInfo($"In-game AimSens: {sens}");
|
||||||
|
return sens;
|
||||||
|
}
|
||||||
|
|
||||||
|
Player getLocalPlayer()
|
||||||
|
{
|
||||||
|
if(enableDebug.Value) Logger.LogInfo("Setting local player...");
|
||||||
|
return Singleton<GameWorld>.Instance.RegisteredPlayers.Find(p => p.IsYourPlayer) as Player;
|
||||||
|
}
|
||||||
|
|
||||||
|
WaitForSecondsRealtime myDelay = new WaitForSecondsRealtime(1f);
|
||||||
|
Camera mainCamera;
|
||||||
|
Camera scopeCamera;
|
||||||
|
|
||||||
|
//this coroutine attempts to find the FPS Camera in the scene.
|
||||||
|
IEnumerator tryGetMainCamera()
|
||||||
|
{
|
||||||
|
string cameraName = "FPS Camera";
|
||||||
|
if (GameObject.Find(cameraName) != null)
|
||||||
|
{
|
||||||
|
mainCamera = GameObject.Find(cameraName).GetComponent<Camera>();
|
||||||
|
if (enableDebug.Value) Logger.LogInfo($"{mainCamera.name} found!");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (enableDebug.Value) Logger.LogMessage($"Camera \"{cameraName}\" not found, rescheduling...");
|
||||||
|
yield return myDelay;
|
||||||
|
StartCoroutine(tryGetMainCamera());
|
||||||
|
yield break;
|
||||||
|
}
|
||||||
|
yield return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
//this coroutine attempts to find existing baseOpticCamera in the scene.
|
||||||
|
IEnumerator tryGetScopeCamera()
|
||||||
|
{
|
||||||
|
string cameraName = "BaseOpticCamera(Clone)";
|
||||||
|
if (GameObject.Find(cameraName) != null)
|
||||||
|
{
|
||||||
|
scopeCamera = GameObject.Find(cameraName).GetComponent<Camera>();
|
||||||
|
if(enableDebug.Value) Logger.LogInfo($"{scopeCamera.name} found!");
|
||||||
|
}
|
||||||
|
yield break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//figure out whether the player is using a magnified optic or not. Return the camera of the sight.
|
||||||
|
float determineCurrentAimedFOV()
|
||||||
|
{
|
||||||
|
if(enableDebug.Value)
|
||||||
|
{
|
||||||
|
Logger.LogInfo($"Current scope: {mainPlayer.ProceduralWeaponAnimation.CurrentAimingMod.Item.LocalizedName()} isOptic? {mainPlayer.ProceduralWeaponAnimation.CurrentScope.IsOptic}");
|
||||||
|
}
|
||||||
|
if (mainPlayer.ProceduralWeaponAnimation.CurrentScope.IsOptic)
|
||||||
|
{
|
||||||
|
return scopeCamera.fieldOfView;
|
||||||
|
}
|
||||||
|
return mainCamera.fieldOfView;
|
||||||
|
}
|
||||||
|
|
||||||
|
float calculateSensitivity()
|
||||||
|
{
|
||||||
|
if(enableDebug.Value) Logger.LogInfo("calculateSensitivity()");
|
||||||
|
//grab vertical hipfire field of view (FOV set by the user in the setting), then convert it to horizontal FOV
|
||||||
|
//convert degrees to radians
|
||||||
|
float hipFOV = Mathf.Deg2Rad * Camera.VerticalToHorizontalFieldOfView(inGameFOV, mainCamera.aspect);
|
||||||
|
|
||||||
|
//grab current field of view while aiming, then convert it to horizontal FOV
|
||||||
|
//convert degrees to radians
|
||||||
|
float aimedFOV = Mathf.Deg2Rad * Camera.VerticalToHorizontalFieldOfView(determineCurrentAimedFOV(), mainCamera.aspect);
|
||||||
|
|
||||||
|
//exponent applied to the ratio of aimedFOV to hipFOV, causes sights to become relatively faster or slower as zoom increases
|
||||||
|
float exponent = 100f / configExponent.Value;
|
||||||
|
|
||||||
|
float tanRatio = (float)(Mathf.Tan(aimedFOV / 2) / Mathf.Tan(hipFOV / 2));
|
||||||
|
|
||||||
|
float sensitivity = (float)Math.Pow(tanRatio, exponent) * inGameAimedSens;
|
||||||
|
|
||||||
|
if(enableDebug.Value) Logger.LogInfo($"Sensitivity: {sensitivity}");
|
||||||
|
return sensitivity * (configSens.Value / 100.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void subscribeOnAimingChanged()
|
||||||
|
{
|
||||||
|
//HandsChangedEvent triggers whenever player changes weapons
|
||||||
|
//without it the patch would cease to work as expected when weapons were changed
|
||||||
|
mainPlayer.HandsChangedEvent += (handsArgs) =>
|
||||||
|
{
|
||||||
|
//onAimingChanged triggers whenever the player starts or stops aiming.
|
||||||
|
mainPlayer.HandsController.OnAimingChanged += (aimArgs) =>
|
||||||
|
{
|
||||||
|
if (enableDebug.Value) Logger.LogInfo($"Scope: {mainPlayer.ProceduralWeaponAnimation.CurrentAimingMod.Item.LocalizedName()} isOptic? {mainPlayer.ProceduralWeaponAnimation.CurrentScope.IsOptic}");
|
||||||
|
inGameFOV = getInGameFOV();
|
||||||
|
inGameAimedSens = getInGameAimSens();
|
||||||
|
StartCoroutine(tryGetScopeCamera());
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,41 +0,0 @@
|
|||||||
using UnityEngine;
|
|
||||||
using System.Collections;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace UniformAim
|
|
||||||
{
|
|
||||||
internal class SightPatches : MonoBehaviour
|
|
||||||
{
|
|
||||||
internal IEnumerator delayedLoad()
|
|
||||||
{
|
|
||||||
yield return new WaitForSeconds(5);
|
|
||||||
findOptics();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
internal static System.Collections.Generic.Dictionary<string, GameObject> customOpticPatches = new System.Collections.Generic.Dictionary<string, GameObject>() { {"scope_leupold_d_evo(Clone)", null},
|
|
||||||
{"tactical_mp155_kalashnikov_ultima_camera(Clone)", null } };
|
|
||||||
|
|
||||||
|
|
||||||
internal async void findOptics()
|
|
||||||
{
|
|
||||||
Utils utils = new Utils();
|
|
||||||
|
|
||||||
SightModVisualControllers[] sightControllers = FindObjectsOfType<SightModVisualControllers>();
|
|
||||||
if (sightControllers.Length == 0)
|
|
||||||
{
|
|
||||||
StartCoroutine(delayedLoad());
|
|
||||||
}
|
|
||||||
foreach (SightModVisualControllers sightController in sightControllers)
|
|
||||||
{
|
|
||||||
if (customOpticPatches.ContainsKey(sightController.name))
|
|
||||||
{
|
|
||||||
|
|
||||||
customOpticPatches[sightController.name] = sightController.gameObject;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
await Task.Yield();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,69 +0,0 @@
|
|||||||
using BepInEx;
|
|
||||||
using BepInEx.Configuration;
|
|
||||||
using System;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace UniformAim
|
|
||||||
{
|
|
||||||
internal class Core
|
|
||||||
{
|
|
||||||
//math stuff
|
|
||||||
internal float CalculateHFOV(float FOV)
|
|
||||||
{
|
|
||||||
//RETURNS RADIANS
|
|
||||||
return Camera.VerticalToHorizontalFieldOfView(FOV, Camera.main.aspect);
|
|
||||||
}
|
|
||||||
|
|
||||||
//calculate sensitivity based on FOV delta and coefficient
|
|
||||||
internal 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
|
|
||||||
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
|
|
||||||
internal float DetermineCurrentFOV(float FPSCameraFOV = 60f, float ScopeCameraFOV = 28f, int SelectedScope = 0, int SelectedScopeMode = 0)
|
|
||||||
{
|
|
||||||
var leupold = SightPatches.customOpticPatches["scope_leupold_d_evo(Clone)"];
|
|
||||||
var ultima = SightPatches.customOpticPatches["tactical_mp155_kalashnikov_ultima_camera(Clone)"];
|
|
||||||
|
|
||||||
if (leupold != null && leupold.activeInHierarchy)
|
|
||||||
{
|
|
||||||
switch (Plugin.SelectedScope)
|
|
||||||
{
|
|
||||||
case 0: return Plugin.currentFPSCameraFOV;
|
|
||||||
case 1: return Plugin.currentScopeCameraFOV;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ultima != null && ultima.activeInHierarchy && isScopeCameraActive() && Plugin.currentScopeCameraFOV == 15)
|
|
||||||
{
|
|
||||||
return Plugin.currentFPSCameraFOV;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Plugin.SelectedScope == 0 && isScopeCameraActive())
|
|
||||||
{
|
|
||||||
return Plugin.currentScopeCameraFOV;
|
|
||||||
}
|
|
||||||
return Plugin.currentFPSCameraFOV;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,71 +0,0 @@
|
|||||||
using Aki.Reflection.Patching;
|
|
||||||
using EFT;
|
|
||||||
using System.Reflection;
|
|
||||||
|
|
||||||
|
|
||||||
namespace UniformAim
|
|
||||||
{
|
|
||||||
public class UpdateSensitivityPatch : ModulePatch
|
|
||||||
{
|
|
||||||
|
|
||||||
protected override MethodBase GetTargetMethod()
|
|
||||||
{
|
|
||||||
return typeof(Player.FirearmController).GetMethod("UpdateSensitivity");
|
|
||||||
}
|
|
||||||
|
|
||||||
[PatchPostfix]
|
|
||||||
public static void PatchPostfix(ref float ____aimingSens)
|
|
||||||
{
|
|
||||||
____aimingSens = Plugin.mySens;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public class get_AimingSensitivityPatch : ModulePatch
|
|
||||||
{
|
|
||||||
protected override MethodBase GetTargetMethod()
|
|
||||||
{
|
|
||||||
return typeof(Player.FirearmController).GetMethod("get_AimingSensitivity");
|
|
||||||
}
|
|
||||||
[PatchPostfix]
|
|
||||||
public static void PatchPostfix(ref float ____aimingSens)
|
|
||||||
{
|
|
||||||
____aimingSens = Plugin.mySens;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public class get_SelectedScopeIndexPatch : ModulePatch
|
|
||||||
{
|
|
||||||
protected override MethodBase GetTargetMethod()
|
|
||||||
{
|
|
||||||
return typeof(EFT.InventoryLogic.SightComponent).GetMethod("get_SelectedScopeIndex");
|
|
||||||
}
|
|
||||||
[PatchPostfix]
|
|
||||||
public static void PatchPostfix(ref int ___SelectedScope)
|
|
||||||
{
|
|
||||||
Plugin.SelectedScope = ___SelectedScope;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public class get_SelectedScopeModePatch : ModulePatch
|
|
||||||
{
|
|
||||||
protected override MethodBase GetTargetMethod()
|
|
||||||
{
|
|
||||||
return typeof(EFT.InventoryLogic.SightComponent).GetMethod("get_SelectedScopeMode");
|
|
||||||
}
|
|
||||||
[PatchPostfix]
|
|
||||||
public static void PatchPostfix(ref int[] ___ScopesSelectedModes)
|
|
||||||
{
|
|
||||||
Plugin.SelectedScopeMode = ___ScopesSelectedModes[Plugin.SelectedScope];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public class get_IsAimingPatch : ModulePatch
|
|
||||||
{
|
|
||||||
protected override MethodBase GetTargetMethod()
|
|
||||||
{
|
|
||||||
return typeof(Player.FirearmController).GetMethod("get_IsAiming");
|
|
||||||
}
|
|
||||||
[PatchPostfix]
|
|
||||||
public static void PatchPostfix(ref bool ____isAiming)
|
|
||||||
{
|
|
||||||
Plugin.isAiming = ____isAiming;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,154 +0,0 @@
|
|||||||
using BepInEx;
|
|
||||||
using BepInEx.Configuration;
|
|
||||||
using Comfort.Common;
|
|
||||||
using UnityEngine;
|
|
||||||
using System;
|
|
||||||
using System.Collections;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
|
|
||||||
namespace UniformAim
|
|
||||||
{
|
|
||||||
[BepInPlugin("com.greg.tarkovuniformaim", "notGreg's Uniform Aim for Tarkov", "1.1.4")]
|
|
||||||
[BepInProcess("EscapeFromTarkov.exe")]
|
|
||||||
|
|
||||||
public class Plugin : BaseUnityPlugin
|
|
||||||
{
|
|
||||||
//Bepinex.Configurator fields
|
|
||||||
public static ConfigEntry<int> configFOV;
|
|
||||||
int[] FOVRange = new int[2] { 50, 75 };
|
|
||||||
ConfigEntry<bool> configFOVRangeOverride;
|
|
||||||
|
|
||||||
public static ConfigEntry<int> configCoeff;
|
|
||||||
public static ConfigEntry<int> configSens;
|
|
||||||
ConfigEntry<bool> configDebug;
|
|
||||||
|
|
||||||
//only for persistence
|
|
||||||
ConfigEntry<float> inGameSens;
|
|
||||||
|
|
||||||
public static float mySens = 1f;
|
|
||||||
//public static float aimingSens;
|
|
||||||
|
|
||||||
//sight data for hacky workarounds
|
|
||||||
public static int SelectedScope = 0;
|
|
||||||
public static int SelectedScopeMode = 0;
|
|
||||||
public static bool isAiming = false;
|
|
||||||
|
|
||||||
//human-friendly names for variables used later
|
|
||||||
float baseCameraFOV = 75;
|
|
||||||
public static float currentFPSCameraFOV = 75;
|
|
||||||
public static float currentScopeCameraFOV = 75;
|
|
||||||
|
|
||||||
Core core = new Core();
|
|
||||||
Utils utils = new Utils();
|
|
||||||
|
|
||||||
Vector2 FOVInfo = new Vector2(75, 35);
|
|
||||||
Vector2 ScopeInfo = new Vector2(0, 0);
|
|
||||||
|
|
||||||
bool delayed = false;
|
|
||||||
|
|
||||||
|
|
||||||
void Awake()
|
|
||||||
{
|
|
||||||
//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>(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", 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)));
|
|
||||||
|
|
||||||
enablePatches();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool doOnce = false;
|
|
||||||
void FixedUpdate()
|
|
||||||
{
|
|
||||||
//FixedUpdate() at 50Hz (Unity default) tickrate appears to resolve the issue of this script breaking when AI spawns
|
|
||||||
Time.fixedDeltaTime = (1f / 50f);
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//check if the player is in the Hideout or in a Raid
|
|
||||||
var isRunning = utils.checkIsReady();
|
|
||||||
if (!isRunning) {
|
|
||||||
doOnce = false;
|
|
||||||
return; }
|
|
||||||
//if (Camera.main == null) return;
|
|
||||||
|
|
||||||
if (isRunning)
|
|
||||||
{
|
|
||||||
if(!doOnce)
|
|
||||||
{
|
|
||||||
SightPatches sightPatches = new SightPatches();
|
|
||||||
|
|
||||||
StartCoroutine(sightPatches.delayedLoad());
|
|
||||||
doOnce = true;
|
|
||||||
}
|
|
||||||
//check if the player is aiming
|
|
||||||
if (isAiming)
|
|
||||||
{
|
|
||||||
//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) {
|
|
||||||
FOVInfo = new Vector2(currentFPSCameraFOV, currentScopeCameraFOV);
|
|
||||||
ScopeInfo = new Vector2(SelectedScope, SelectedScopeMode);
|
|
||||||
mySens = inGameSens.Value * core.CalculateSensitivity(core.DetermineCurrentFOV(FOVInfo.x, FOVInfo.y, (int)ScopeInfo.x, (int)ScopeInfo.y), configFOV.Value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Print debug info in BepInEx console
|
|
||||||
if (configDebug.Value && delayed) printDebug();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
string lastDebugLog;
|
|
||||||
void printDebug()
|
|
||||||
{
|
|
||||||
string debugLog = $"\nIn-Game FOV: {configFOV.Value} | In-Game Sens: {inGameSens.Value} | FOV Override: {configFOVRangeOverride.Value}" +
|
|
||||||
$"\nFPS Camera FOV: {currentFPSCameraFOV}V / {core.CalculateHFOV(currentFPSCameraFOV)}H | BaseOpticCamera FOV: {currentScopeCameraFOV}V / {core.CalculateHFOV(currentScopeCameraFOV)}H | CurrentFOV: {core.DetermineCurrentFOV(FOVInfo.x, FOVInfo.y, (int)ScopeInfo.x, (int)ScopeInfo.y)}V / {core.CalculateHFOV(core.DetermineCurrentFOV(FOVInfo.x, FOVInfo.y, (int)ScopeInfo.x, (int)ScopeInfo.y))}H" +
|
|
||||||
$"\nisAiming? {isAiming} | SelectedScope: {SelectedScope} | SelectedScopeMode:{SelectedScopeMode}" +
|
|
||||||
$"\nCalculated sensitivity: {core.CalculateSensitivity(core.DetermineCurrentFOV(FOVInfo.x, FOVInfo.y, (int)ScopeInfo.x, (int)ScopeInfo.y), baseCameraFOV)}" +
|
|
||||||
$"\nAspect Ratio: {Camera.main.aspect}" +
|
|
||||||
$"\nFinal Sensitivity: {mySens}";
|
|
||||||
if (lastDebugLog != debugLog) { Logger.LogInfo(debugLog); lastDebugLog = debugLog; }
|
|
||||||
}
|
|
||||||
void enablePatches()
|
|
||||||
{
|
|
||||||
Logger.LogInfo("Enabling patches!");
|
|
||||||
new UpdateSensitivityPatch().Enable();
|
|
||||||
new get_AimingSensitivityPatch().Enable();
|
|
||||||
new get_SelectedScopeIndexPatch().Enable();
|
|
||||||
new get_SelectedScopeModePatch().Enable();
|
|
||||||
new get_IsAimingPatch().Enable();
|
|
||||||
delayed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,67 +0,0 @@
|
|||||||
using Comfort.Common;
|
|
||||||
using EFT;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
namespace UniformAim
|
|
||||||
{
|
|
||||||
public class Utils
|
|
||||||
{
|
|
||||||
//bool isPlaying = false;
|
|
||||||
//GameObject rootObject = null;
|
|
||||||
|
|
||||||
public bool checkIsReady()
|
|
||||||
{
|
|
||||||
var gameWorld = Singleton<GameWorld>.Instance;
|
|
||||||
var sessionResultPanel = Singleton<SessionResultPanel>.Instance;
|
|
||||||
|
|
||||||
if (gameWorld == null
|
|
||||||
|| gameWorld.AllPlayers == null
|
|
||||||
|| gameWorld.AllPlayers.Count <= 0
|
|
||||||
|| sessionResultPanel != null
|
|
||||||
|| Camera.main == null)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
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 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 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 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -7,8 +7,8 @@
|
|||||||
<ProjectGuid>{B2F4587D-CFE6-42A6-8462-A884EB6E15CD}</ProjectGuid>
|
<ProjectGuid>{B2F4587D-CFE6-42A6-8462-A884EB6E15CD}</ProjectGuid>
|
||||||
<OutputType>Library</OutputType>
|
<OutputType>Library</OutputType>
|
||||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||||
<RootNamespace>TarkovUniformAim</RootNamespace>
|
<RootNamespace>UniformAim</RootNamespace>
|
||||||
<AssemblyName>TarkovUniformAim</AssemblyName>
|
<AssemblyName>notGreg.UniformAim</AssemblyName>
|
||||||
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
|
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
|
||||||
<FileAlignment>512</FileAlignment>
|
<FileAlignment>512</FileAlignment>
|
||||||
<Deterministic>true</Deterministic>
|
<Deterministic>true</Deterministic>
|
||||||
@ -31,54 +31,35 @@
|
|||||||
<WarningLevel>4</WarningLevel>
|
<WarningLevel>4</WarningLevel>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="0Harmony, Version=2.9.0.0, Culture=neutral, processorArchitecture=MSIL">
|
<Compile Include="Patch.cs" />
|
||||||
<SpecificVersion>False</SpecificVersion>
|
<Compile Include="Plugin.cs" />
|
||||||
<HintPath>..\..\MyFirstPlugin\MyFirstPlugin\lib\0Harmony.dll</HintPath>
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
</Reference>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
<Reference Include="Aki.Reflection, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="Aki.Reflection, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<SpecificVersion>False</SpecificVersion>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
<HintPath>E:\SPT-AKI\SPT-AKI 3.1.1\EscapeFromTarkov_Data\Managed\Aki.Reflection.dll</HintPath>
|
<HintPath>G:\SPT\SPT-AKI 3.8.0\EscapeFromTarkov_Data\Managed\Aki.Reflection.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Assembly-CSharp">
|
<Reference Include="Assembly-CSharp, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<HintPath>..\..\libs\EFT Trainer DLLs\Assembly-CSharp.dll</HintPath>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
|
<HintPath>G:\SPT\SPT-AKI 3.8.0\EscapeFromTarkov_Data\Managed\Assembly-CSharp.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="BepInEx">
|
<Reference Include="BepInEx, Version=5.4.22.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<HintPath>..\..\MyFirstPlugin\MyFirstPlugin\lib\BepInEx.dll</HintPath>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
|
<HintPath>G:\SPT\SPT-AKI 3.8.0\BepInEx\core\BepInEx.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Comfort, Version=1.0.0.4, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="Comfort, Version=1.0.0.4, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<SpecificVersion>False</SpecificVersion>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
<HintPath>E:\SPT-AKI\SPT-AKI 3.0.0\EscapeFromTarkov_Data\Managed\Comfort.dll</HintPath>
|
<HintPath>G:\SPT\SPT-AKI 3.8.0\EscapeFromTarkov_Data\Managed\Comfort.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
<Reference Include="UnityEngine, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<SpecificVersion>False</SpecificVersion>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
<HintPath>..\..\libs\EFT Trainer DLLs\Newtonsoft.Json.dll</HintPath>
|
<HintPath>G:\SPT\SPT-AKI 3.8.0\EscapeFromTarkov_Data\Managed\UnityEngine.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Sirenix.Serialization, Version=3.0.4.0, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<SpecificVersion>False</SpecificVersion>
|
<SpecificVersion>False</SpecificVersion>
|
||||||
<HintPath>E:\SPT-AKI\SPT-AKI 3.0.0\EscapeFromTarkov_Data\Managed\Sirenix.Serialization.dll</HintPath>
|
<HintPath>G:\SPT\SPT-AKI 3.8.0\EscapeFromTarkov_Data\Managed\UnityEngine.CoreModule.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System" />
|
|
||||||
<Reference Include="System.Core" />
|
|
||||||
<Reference Include="System.Xml.Linq" />
|
|
||||||
<Reference Include="System.Data.DataSetExtensions" />
|
|
||||||
<Reference Include="Microsoft.CSharp" />
|
|
||||||
<Reference Include="System.Data" />
|
|
||||||
<Reference Include="System.Net.Http" />
|
|
||||||
<Reference Include="System.Xml" />
|
|
||||||
<Reference Include="UnityEngine">
|
|
||||||
<HintPath>..\..\MyFirstPlugin\MyFirstPlugin\lib\UnityEngine.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="UnityEngine.CoreModule">
|
|
||||||
<HintPath>..\..\MyFirstPlugin\MyFirstPlugin\lib\UnityEngine.CoreModule.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Compile Include="SightPatches.cs" />
|
|
||||||
<Compile Include="UniformAimUtils.cs" />
|
|
||||||
<Compile Include="UniformAimCore.cs" />
|
|
||||||
<Compile Include="UniformAimPlugin.cs" />
|
|
||||||
<Compile Include="UniformAimPatch.cs" />
|
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
</Project>
|
</Project>
|
Loading…
x
Reference in New Issue
Block a user