2023-02-19 11:58:12 +01:00

408 lines
16 KiB
C#

using BepInEx;
using BepInEx.Configuration;
using Comfort.Common;
using EFT;
using EFT.Settings.Graphics;
using System.Collections;
using System.ComponentModel;
using System.Reflection;
using UnityEngine;
/* Dependencies:
* ../BepInEx/core/
* BepInEx.dll
* ../EscapeFromTarkov_Data/Managed/
* Aki.Reflection.dll
* Assembly-CSharp.dll
* Comfort.dll
* ItemComponent.Types.dll
* System.dll
* Unity.Postprocessing.Runtime.dll
* UnityEngine.dll
* UnityEngine.CoreModule.dll
*/
namespace ScopeTweaks
{
[BepInPlugin("com.notGreg.scopeTweaks", "notGreg's Scope Tweaks", "3.5.0")]
public class Plugin : BaseUnityPlugin
{
ConfigEntry<int> cameraResolutionScale;
ConfigEntry<int> scopeCameraResolutionScale;
ConfigEntry<EFOVScalingMode> scopeFixType;
ConfigEntry<bool> enableDebug;
enum EFOVScalingMode
{
Disabled,
[Description("Magnified optics")]
ScopesOnly,
[Description("All sights")]
All,
}
//The following assignments should allow for faster patching in the future.
//The correct GClass can be found by searching for "ClearSettings" in Assembly-CSharp.dll via dnSpy, netFiddle, ilSpy, etc.
//GClass1642 settingsLibrary = Singleton<GClass1642>.Instance; //used by SPT-AKI 3.2.3
//GClass1653 settingsLibrary = Singleton<GClass1653>.Instance; //used by SPT-AKI 3.3.0
//GClass1659 settingsLibrary = Singleton<GClass1659>.Instance; //used by SPT-AKI 3.4.1
//The correct GClass can be found by searching for "SetFov" in Assembly-CSharp.dll via dnSpy, netFiddle, ilSpy, etc.
//GClass1774 setFovLibrary = Singleton<GClass1774>.Instance; //used by SPT-AKI 3.2.3
//GClass1785 setFovLibrary = Singleton<GClass1785>.Instance; //used by SPT-AKI 3.3.0
CameraClass setFovLibrary = CameraClass.Instance; //used by SPT-AKI 3.4.1 and 3.5.0
void Awake()
{
cameraResolutionScale = Config.Bind(
"General",
"Main camera scale %",
80,
new ConfigDescription("Additional override applied on top of currently enabled resolution scaling method.", new AcceptableValueRange<int>(25, 100)));
scopeCameraResolutionScale = Config.Bind(
"General",
"Scope camera scale %",
80,
new ConfigDescription("Additional override applied on top of currently enabled resolution scaling method.", new AcceptableValueRange<int>(25, 100)));
scopeFixType = Config.Bind(
"General",
"High FOV sight tweak",
EFOVScalingMode.ScopesOnly,
new ConfigDescription(""));
enableDebug = Config.Bind("Debug", "Enable debug logging", false);
}
void Update()
{
//Check if the game is in a valid state and execute logic depening on the status of the game
if (Singleton<AbstractGame>.Instance == null) return;
GameStatus currentGameState = Singleton<AbstractGame>.Instance.Status;
//logic should only execute once per game instead of every frame
if (!gameStateChanged(currentGameState)) return;
switch (currentGameState)
{
case GameStatus.Started:
{
if (enableDebug.Value) Logger.LogInfo("Getting local player");
mainPlayer = getLocalPlayer();
subscribeHandsChangedEvent();
if (enableDebug.Value) Logger.LogInfo("Assigning cameras...");
StartCoroutine(tryGetMainCamera());
StartCoroutine(tryGetScopeCamera());
defaultInGameFOV = inGameFOV;
break;
}
case GameStatus.SoftStopping:
case GameStatus.Stopping:
case GameStatus.Stopped:
{
if (enableDebug.Value) Logger.LogInfo("Resetting...");
FPSCamera = null;
scopeCamera = null;
mainPlayer = null;
if (enableDebug.Value) Logger.LogInfo($"Restoring FOV in settings: {defaultInGameFOV}");
inGameFOV = defaultInGameFOV;
break;
}
default: break;
}
}
/// <summary>
/// GAME STATUS
/// </summary>
GameStatus lastGameState;
//compare current game status to the last saved game status, return true if game status has changed
bool gameStateChanged(GameStatus currentState)
{
if (currentState == lastGameState) return false;
lastGameState = currentState;
return true;
}
Player mainPlayer;
//find and return the player character in the session
Player getLocalPlayer()
{
return Singleton<GameWorld>.Instance.RegisteredPlayers.Find(p => p.IsYourPlayer);
}
/// <summary>
/// FIELD OF VIEW
/// </summary>
///
private int defaultInGameFOV;
private int inGameFOV
{
get
{
//int fov = settingsLibrary.Game.Settings.FieldOfView.Value;
//int fov = Singleton<GClass1659>.Instance.Game.Settings.FieldOfView.Value; //SPT-AKI 3.4.1
int fov = Singleton<GClass1776>.Instance.Game.Settings.FieldOfView.Value; // SPT-AKI 3.5.0
if (enableDebug.Value) Logger.LogInfo($"get_defaultInGameFOV: Reading from settings: {fov}");
return fov;
}
set
{
if (enableDebug.Value) Logger.LogInfo($"set_defaultInGameFOV: Writing to settings: {value}");
//settingsLibrary.Game.Settings.FieldOfView.Value = value;
//int fov = Singleton<GClass1659>.Instance.Game.Settings.FieldOfView.Value;
int fov = Singleton<GClass1776>.Instance.Game.Settings.FieldOfView.Value; // SPT-AKI 3.5.0
}
}
/// <summary>
/// CAMERA SETUP
/// </summary>
Camera FPSCamera = null;
Camera scopeCamera = null;
SSAA ssaaInstance = null;
FieldInfo _nextSSRation = null;
WaitForSeconds myDelaySec = new WaitForSeconds(1);
IEnumerator tryGetMainCamera()
{
string cameraName = "FPS Camera";
if (GameObject.Find(cameraName) != null)
{
FPSCamera = GameObject.Find(cameraName).GetComponent<Camera>();
if (enableDebug.Value) Logger.LogInfo($"{FPSCamera.name} found!");
}
else
{
if (enableDebug.Value) Logger.LogMessage($"Camera \"{cameraName}\" not found.");
yield return myDelaySec;
StartCoroutine(tryGetMainCamera());
yield break;
}
yield return null;
}
FieldInfo getFieldInfo(string fieldName)
{
return typeof(SSAA).GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance);
}
IEnumerator tryGetScopeCamera()
{
string cameraName = "BaseOpticCamera(Clone)";
if (GameObject.Find(cameraName) != null)
{
scopeCamera = GameObject.Find(cameraName).GetComponent<Camera>();
if (enableDebug.Value) Logger.LogInfo($"Camera \"{scopeCamera.name}\" found!");
}
yield break;
}
void setMainCameraResolutionScale(int value = 100)
{
//if (settingsLibrary.Graphics.Settings.DLSSEnabled)
//if (Singleton<GClass1659>.Instance.Graphics.Settings.DLSSEnabled)
if (Singleton<GClass1776>.Instance.Graphics.Settings.DLSSEnabled)
{
if (enableDebug.Value) Logger.LogInfo("DLSS enabled - skipping MainCamera resolution change");
return;
}
if (enableDebug.Value) Logger.LogInfo($"Setting MainCam res scale to {value}%");
ssaaInstance = FPSCamera.GetComponent<SSAA>();
_nextSSRation = getFieldInfo("_nextSSRation");
_nextSSRation.SetValue(ssaaInstance, (float)(currentScalingFactor * value / 100f));
}
void setScopeCameraResolutionScale(int value)
{
if (scopeCamera == null || !scopeCamera.isActiveAndEnabled)
{
if (enableDebug.Value) Logger.LogInfo("ScopeCam inactive or absent!");
return;
}
if (enableDebug.Value) Logger.LogInfo($"Setting Scope res scale to {value}%");
scopeCamera.GetComponent<SSAAOptic>().OpticCameraToMainCameraResolutionRatio = (float)(currentScalingFactor * (value / 100f));
}
/// <summary>
/// PLAYER WEAPON EVENTS
/// </summary>
void subscribeHandsChangedEvent()
{
if (enableDebug.Value) Logger.LogInfo("Subscribing to HandsChanged Event");
mainPlayer.HandsChangedEvent += (handsArgs) =>
{
subscribeOnAimingChangedEvent();
};
}
void subscribeOnAimingChangedEvent()
{
if (enableDebug.Value) Logger.LogInfo("Subscribing to OnAimingChanged Event");
mainPlayer.HandsController.OnAimingChanged += (aimingArgs) =>
{
currentScalingFactor = getCurrentScalingFactor();
StartCoroutine(tryGetScopeCamera());
if (!mainPlayer.ProceduralWeaponAnimation.IsAiming)
{
switch (scopeFixType.Value)
{
case EFOVScalingMode.Disabled:
{
if (enableDebug.Value) Logger.LogInfo($"Switch: Not Aiming: ScalingMode: {scopeFixType.Value}");
break;
}
case EFOVScalingMode.ScopesOnly:
{
if (enableDebug.Value) Logger.LogInfo($"Switch: Not Aiming: ScalingMode: {scopeFixType.Value}");
setMainCameraResolutionScale();
setFovLibrary.SetFov(defaultInGameFOV, 0.33f, false);
inGameFOV = defaultInGameFOV;
break;
}
case EFOVScalingMode.All:
{
if (enableDebug.Value) Logger.LogInfo($"Switch: Not Aiming: ScalingMode: {scopeFixType.Value}");
setMainCameraResolutionScale();
setFovLibrary.SetFov(defaultInGameFOV, 0.33f, false);
inGameFOV = defaultInGameFOV;
break;
}
}
return;
}
if (mainPlayer.ProceduralWeaponAnimation.IsAiming)
{
defaultInGameFOV = inGameFOV;
switch (scopeFixType.Value)
{
case EFOVScalingMode.Disabled:
{
if (enableDebug.Value) Logger.LogInfo($"Switch: Aiming: ScalingMode: {scopeFixType.Value}");
break;
}
case EFOVScalingMode.ScopesOnly:
{
if (enableDebug.Value) Logger.LogInfo($"Switch: Aiming: ScalingMode: {scopeFixType.Value}");
if (scopeCamera.isActiveAndEnabled)
{
if (enableDebug.Value) Logger.LogInfo("ScopeCamera not found or disabled!");
applyFixesWhileAiming();
}
break;
}
case EFOVScalingMode.All:
{
if (enableDebug.Value) Logger.LogInfo($"Switch: Aiming: ScalingMode: {scopeFixType.Value}");
applyFixesWhileAiming();
break;
}
}
}
};
}
void applyFixesWhileAiming()
{
if (enableDebug.Value) Logger.LogInfo($"AimingSpeed: {mainPlayer.ProceduralWeaponAnimation.AimingSpeed}");
if (enableDebug.Value) Logger.LogInfo("Changing FOV while aiming");
setFovLibrary.SetFov(35, 0.25f, false); //SPT-AKI 3.3.0
inGameFOV = 50;
if (enableDebug.Value) Logger.LogInfo("Updating scope resolution");
setMainCameraResolutionScale(cameraResolutionScale.Value);
setScopeCameraResolutionScale(scopeCameraResolutionScale.Value);
}
/// <summary>
/// IN-GAME SETTINGS
/// </summary>
float currentScalingFactor = 1.0f;
float getCurrentScalingFactor()
{
if (enableDebug.Value) Logger.LogInfo("Getting current scaling factor:");
//var graphics = settingsLibrary.Graphics.Settings; //SPT-AKI 3.3.0
//var graphics = Singleton<GClass1659>.Instance.Graphics.Settings; // SPT-AKI 3.4.1
var graphics = Singleton<GClass1776>.Instance.Graphics.Settings; // SPT-AKI 3.5.0
if (!graphics.DLSSEnabled && !graphics.FSREnabled)
{
if (enableDebug.Value) Logger.LogInfo($"Supersampling factor: {graphics.SuperSamplingFactor}");
return graphics.SuperSamplingFactor;
}
if (graphics.DLSSEnabled)
{
float DLSSFactor = 1.0f;
switch (graphics.DLSSMode.Value)
{
case EDLSSMode.Off: { DLSSFactor = 1.0f; break; }
case EDLSSMode.Quality: { DLSSFactor = 0.67f; break; }
case EDLSSMode.Balanced: { DLSSFactor = 0.58f; break; }
case EDLSSMode.Performance: { DLSSFactor = 0.5f; break; }
case EDLSSMode.UltraPerformance: { DLSSFactor = 0.33f; break; }
}
if (enableDebug.Value) Logger.LogInfo($"DLSS factor: {DLSSFactor}");
return DLSSFactor;
}
if (graphics.FSREnabled)
{
float FSRFactor = 1.0f;
switch (graphics.FSRMode.Value)
{
case EFSRMode.Off: { FSRFactor = 1.0f; break; }
case EFSRMode.UltraQuality: { FSRFactor = 0.77f; break; }
case EFSRMode.Quality: { FSRFactor = 0.66f; break; }
case EFSRMode.Balanced: { FSRFactor = 0.59f; break; }
case EFSRMode.Performance: { FSRFactor = 0.5f; break; }
}
if (enableDebug.Value) Logger.LogInfo($"FSR factor: {FSRFactor}");
return FSRFactor;
}
if (graphics.FSR2Enabled)
{
float FSR2Factor = 1.0f;
switch (graphics.FSR2Mode.Value)
{
case EFSR2Mode.Off: { FSR2Factor = 1.0f; break; }
case EFSR2Mode.Quality: { FSR2Factor = 0.67f; break; }
case EFSR2Mode.Balanced: { FSR2Factor = 0.59f; break; }
case EFSR2Mode.Performance: { FSR2Factor = 0.5f; break; }
case EFSR2Mode.UltraPerformance: { FSR2Factor = 0.33f; break; }
}
if (enableDebug.Value) Logger.LogInfo($"FSR factor: {FSR2Factor}");
return FSR2Factor;
}
if (enableDebug.Value) Logger.LogInfo($"GetCurrentScalingFactor(): Something went wrong. Returning 1.0f");
return 1.0f;
}
}
}