Compare commits

...

No commits in common. "master" and "update_341" have entirely different histories.

7 changed files with 315 additions and 257 deletions

View File

@ -1,15 +0,0 @@
# Uniform Aim for Tarkov
Many thanks to the helpful community of SPT-AKI server, especially kiobu-kouhai, Kobrakon, and SamSWAT
---
This plugin aims to address the issue of wonky and inconsistent sensitivity multipliers of all sights in Escape from Tarkov.
Sensitivity is now derived from player's hipfire Field of View and weapon's Field of View when aiming to produce consistent experience regardless of weapon and sight used. It also addresses some edge cases like NcSTAR ADO P4 back-up sight being way slower than it should be.
Examples in other games:
[Battlefield: Important Guide to Uniform Soldier Aiming on web.archive](https://web.archive.org/web/20160716041925/http://battlelog.battlefield.com/bf4/forum/threadview/2979150494051524581/)
[Rainbow Six Siege: Guide to ADS Sensitivity in Y5S3](https://www.ubisoft.com/en-gb/game/rainbow-six/siege/news-updates/3IMlDGlaRFgdvQNq3BOSFv/guide-to-ads-sensitivity-in-y5s3)

View File

@ -1,221 +0,0 @@
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());
};
};
}
}
}

View File

@ -1,9 +1,9 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.2.32602.215
VisualStudioVersion = 17.3.32825.248
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "notGreg.UniformAim", "TarkovUniformAim\notGreg.UniformAim.csproj", "{B2F4587D-CFE6-42A6-8462-A884EB6E15CD}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "notGreg.UniformAim", "notGregs.UniformAim\notGreg.UniformAim.csproj", "{26A09451-8D42-403F-8528-F479FEF0E74D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -11,15 +11,15 @@ Global
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{B2F4587D-CFE6-42A6-8462-A884EB6E15CD}.Debug|Any CPU.ActiveCfg = Release|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.Build.0 = Release|Any CPU
{26A09451-8D42-403F-8528-F479FEF0E74D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{26A09451-8D42-403F-8528-F479FEF0E74D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{26A09451-8D42-403F-8528-F479FEF0E74D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{26A09451-8D42-403F-8528-F479FEF0E74D}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {49C52BAD-50C6-43D2-AF11-112E812415E4}
SolutionGuid = {5C5634EB-9884-4C66-B34A-E1B9BB82AD69}
EndGlobalSection
EndGlobal

View File

@ -15,7 +15,7 @@ namespace notGreg.UniformAim
protected override MethodBase GetTargetMethod()
{
return typeof(Player.FirearmController).GetMethod("get_AimingSensitivity");
return typeof(Player.FirearmController).GetMethod("get_AimingSensitivity");
}
[PatchPostfix]
public static void PatchPostfix(ref float ____aimingSens)

View File

@ -0,0 +1,295 @@
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using Comfort.Common;
using EFT;
using EFT.UI.Settings;
using System;
using System.Collections;
using UnityEngine;
//Assembly-CSharp.dll
//Aki.Reflection.dll
//BepInEx.dll
//Comfort.dll
//UnityEngine.dll
//UnityEngine.CoreModule.dll
namespace notGreg.UniformAim
{
[BepInPlugin("com.notGreg.UniformAim", "notGreg's Uniform Aim for Tarkov", "3.5.0")]
[BepInDependency("RealismMod", BepInDependency.DependencyFlags.SoftDependency)]
public class Plugin : BaseUnityPlugin
{
ConfigEntry<int> configExponent;
ConfigEntry<float> configSens;
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)));
if (!isRealismModPresent)
{
new get_AimingSensitivityPatch().Enable();
}
else
{
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
//Logger.LogInfo("Checking world instance");
if (Singleton<AbstractGame>.Instance == null)
{
return;
}
//grab the game status of the existing instance
//Logger.LogInfo("Checking game status");
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)
//Logger.LogInfo("Checking GameStatus and isAiming");
//Logger.LogInfo($"GameStatus: {currentGameStatus}");
if (currentGameStatus == GameStatus.Started && mainPlayer != null)
{
//Logger.LogInfo($"isAiming? {mainPlayer.HandsController.IsAiming}");
if (mainPlayer.HandsController.IsAiming)
{
aimingSens = calculateSensitivity();
}
return;
}
//Logger.LogInfo("Switch on GameStatus");
switch (currentGameStatus)
{
case GameStatus.Started:
{
mainPlayer = getLocalPlayer();
//Logger.LogInfo($"Subscribing to onAimingChanged event");
subscribeOnAimingChanged();
//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.
//SharedGameSettingsClass settingsLibrary = SharedGameSettingsClass.Instance; // Futureproofing for 3.5.1 and onwards
int getInGameFOV()
{
//int fov = Singleton<GClass1642>.Instance.Game.Settings.FieldOfView; //SPT-AKI 3.2.3
//int fov = Singleton<GClass1653>.Instance.Game.Settings.FieldOfView; //SPT-AKI 3.3.0
//int fov = Singleton<GClass1659>.Instance.Game.Settings.FieldOfView; //SPT-AKI 3.4.1
int fov = Singleton<GClass1776>.Instance.Game.Settings.FieldOfView; //SPT-AKI 3.5.0
//int fov = settingsLibrary.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<GClass1642>.Instance.Control.Settings.MouseAimingSensitivity; //SPT-AKI 3.2.*
//float sens = Singleton<GClass1653>.Instance.Control.Settings.MouseAimingSensitivity; //SPT-AKI 3.3.0
//float sens = Singleton<GClass1659>.Instance.Control.Settings.MouseAimingSensitivity; //SPT-AKI 3.4.1
float sens = Singleton<GClass1776>.Instance.Control.Settings.MouseAimingSensitivity; //SPT-AKI 3.5.0
//float sens = settingsLibrary.Control.Settings.MouseAimingSensitivity;
//Logger.LogInfo($"In-game AimSens: {sens}");
return sens;
}
Player getLocalPlayer()
{
//Logger.LogInfo("Setting local player...");
return Singleton<GameWorld>.Instance.RegisteredPlayers.Find(p => p.IsYourPlayer);
}
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>();
//Logger.LogInfo($"{mainCamera.name} found!");
}
else
{
//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. The state of this camera is used to determine whether the player is using a magnified optic or not.
IEnumerator tryGetScopeCamera()
{
string cameraName = "BaseOpticCamera(Clone)";
if (GameObject.Find(cameraName) != null)
{
scopeCamera = GameObject.Find(cameraName).GetComponent<Camera>();
//Logger.LogInfo($"{scopeCamera.name} found!");
}
yield break;
}
//figure out whether the player is using a magnified optic or not. Return the FOV of the sight.
Camera determineCurrentAimedFOV()
{
//Logger.LogInfo("Get current aiming mod");
//Logger.LogInfo($"MainPlayer {mainPlayer.name}");
//Logger.LogInfo($"ProcWeapAnim {mainPlayer.ProceduralWeaponAnimation}");
//Logger.LogInfo($"CurrAimMod {mainPlayer.ProceduralWeaponAnimation.CurrentAimingMod}");
if (mainPlayer.ProceduralWeaponAnimation.CurrentAimingMod == null)
{
return mainCamera;
}
var currentAimingMod = mainPlayer.ProceduralWeaponAnimation.CurrentAimingMod;
//get the name of the currently active scope
//string scopeName = currentAimingMod.Item.Template.Name;
string scopeName = currentAimingMod.Item.Name;
//Logger.LogInfo($"Scope name: {scopeName}");
//scopeMode determines the scope being used (e.g. main magnified optic at index 0, backup RDS at index 1)
//scopeIndex determines the mode of the scope being used (e.g. x1 magnification at index 0, x4 magnification at index 1)
//there are exceptions to this rule thanks to BSG's inconsistency, some of them are patched below
var scopeIndex = currentAimingMod.SelectedScopeIndex;
var scopeMode = currentAimingMod.SelectedScopeMode;
//Logger.LogInfo("Index: " + scopeIndex + "\nMode: " + scopeMode);
//patches for specific scopes, matches item name
switch (scopeName)
{
case "tactical_mp155_kalashnikov_ultima_camera":
{
//Logger.LogInfo("MP-155 Thermal");
return mainCamera;
}
//SAM-SWAT's Leupold D-Evo optic patch. The modes on this scope are reversed. Causes detection based on baseOpticCamera to fail as the magnified optic camera is always active
case "scope_leupold_d_evo":
{
if (scopeMode == 0)
{
//Logger.LogInfo($"Leupold D-EVO BUIS FOV: {mainCamera.fieldOfView}");
return mainCamera;
}
else
{
//Logger.LogInfo($"Leupold D-EVO Scope FOV: {scopeCamera.fieldOfView}");
return scopeCamera;
}
}
case "scope_base_trijicon_acog_ta11_3,5x35":
{
if (scopeIndex == 1)
{
//Logger.LogInfo($"G36 Rail sight");
return mainCamera;
}
else
{
return scopeCamera;
}
}
default:
{
if (scopeCamera == null || scopeCamera.isActiveAndEnabled == false)
{
//Logger.LogInfo($"Non-magnified: {scopeName} FOV: {mainCamera.fieldOfView}");
return mainCamera;
}
else
{
//Logger.LogInfo($"Magnified: {scopeName} FOV: {scopeCamera.fieldOfView}");
return scopeCamera;
}
}
}
}
float calculateSensitivity()
{
//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().fieldOfView, 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;
//Logger.LogInfo($"Sensitivity: {sensitivity}");
return sensitivity * configSens.Value;
}
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) =>
{
inGameFOV = getInGameFOV();
inGameAimedSens = getInGameAimSens();
StartCoroutine(tryGetScopeCamera());
};
};
}
}
}

View File

@ -1,15 +1,14 @@
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: AssemblyTitle("notGregs.UniformAim")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("TarkovUniformAim")]
[assembly: AssemblyProduct("notGregs.UniformAim")]
[assembly: AssemblyCopyright("Copyright © 2022")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
@ -20,7 +19,7 @@ using System.Runtime.InteropServices;
[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")]
[assembly: Guid("26a09451-8d42-403f-8528-f479fef0e74d")]
// Version information for an assembly consists of the following four values:
//

View File

@ -4,10 +4,10 @@
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{B2F4587D-CFE6-42A6-8462-A884EB6E15CD}</ProjectGuid>
<ProjectGuid>{26A09451-8D42-403F-8528-F479FEF0E74D}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>UniformAim</RootNamespace>
<RootNamespace>notGreg.UniformAim</RootNamespace>
<AssemblyName>notGreg.UniformAim</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
@ -38,27 +38,27 @@
<ItemGroup>
<Reference Include="Aki.Reflection, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>G:\SPT\SPT-AKI 3.8.0\EscapeFromTarkov_Data\Managed\Aki.Reflection.dll</HintPath>
<HintPath>E:\SPT-AKI\SPT-AKI 3.5.0\EscapeFromTarkov_Data\Managed\Aki.Reflection.dll</HintPath>
</Reference>
<Reference Include="Assembly-CSharp, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>G:\SPT\SPT-AKI 3.8.0\EscapeFromTarkov_Data\Managed\Assembly-CSharp.dll</HintPath>
<HintPath>E:\SPT-AKI\SPT-AKI 3.5.0\EscapeFromTarkov_Data\Managed\Assembly-CSharp.dll</HintPath>
</Reference>
<Reference Include="BepInEx, Version=5.4.22.0, Culture=neutral, processorArchitecture=MSIL">
<Reference Include="BepInEx, Version=5.4.21.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>G:\SPT\SPT-AKI 3.8.0\BepInEx\core\BepInEx.dll</HintPath>
<HintPath>E:\SPT-AKI\SPT-AKI 3.5.0\BepInEx\core\BepInEx.dll</HintPath>
</Reference>
<Reference Include="Comfort, Version=1.0.0.4, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>G:\SPT\SPT-AKI 3.8.0\EscapeFromTarkov_Data\Managed\Comfort.dll</HintPath>
<HintPath>E:\SPT-AKI\SPT-AKI 3.5.0\EscapeFromTarkov_Data\Managed\Comfort.dll</HintPath>
</Reference>
<Reference Include="UnityEngine, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>G:\SPT\SPT-AKI 3.8.0\EscapeFromTarkov_Data\Managed\UnityEngine.dll</HintPath>
<HintPath>E:\SPT-AKI\SPT-AKI 3.5.0\EscapeFromTarkov_Data\Managed\UnityEngine.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>G:\SPT\SPT-AKI 3.8.0\EscapeFromTarkov_Data\Managed\UnityEngine.CoreModule.dll</HintPath>
<HintPath>E:\SPT-AKI\SPT-AKI 3.5.0\EscapeFromTarkov_Data\Managed\UnityEngine.CoreModule.dll</HintPath>
</Reference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />