using BepInEx; using BepInEx.Configuration; using EFT; using UnityEngine; using Comfort.Common; using System.Reflection; using System.Collections; using EFT.Settings.Graphics; namespace ScopeTweaks { [BepInPlugin("com.notGreg.scopeTweaks", "notGreg's Scope Tweaks", "1.1.0")] public class Plugin : BaseUnityPlugin { Utils utils = new Utils(); CameraUtils scopeRes = new CameraUtils(); ConfigEntry cameraResolutionScale; ConfigEntry scopeCameraResolutionScale; ConfigEntry scopeFixType; enum EFOVScalingMode { Disabled, Enabled, } void Awake() { cameraResolutionScale = Config.Bind( "General", "Main camera scale %", 80, new ConfigDescription("Main camera resolution scale", new AcceptableValueRange(50, 100))); scopeCameraResolutionScale = Config.Bind( "General", "Scope camera scale %", 40, new ConfigDescription("Scope camera resolution scale", new AcceptableValueRange(25, 100))); scopeFixType = Config.Bind("General", "High FOV scope tweak", EFOVScalingMode.Enabled, new ConfigDescription("")); } Camera FPSCamera = null; Camera scopeCamera = null; SSAA ssaaInstance = null; FieldInfo _nextSSRation = null; int defaultFOVValue; void setUpCameras() { //Logger.LogInfo("Game started!"); //Logger.LogInfo("Get FPS Camera"); StartCoroutine(tryGetMainCamera()); //Logger.LogInfo("Get Scope Camera"); StartCoroutine(tryGetScopeCamera()); } WaitForSeconds myDelaySec = new WaitForSeconds(1); IEnumerator tryGetMainCamera() { if (scopeRes.getMainCamera() == null) { yield return myDelaySec; StartCoroutine(tryGetMainCamera()); yield break; } FPSCamera = scopeRes.getMainCamera(); defaultFOVValue = (int)FPSCamera.fieldOfView; //Logger.LogInfo("Get SSAAInstance (Camera)"); ssaaInstance = scopeRes.getSSAAInstance(FPSCamera); //Logger.LogInfo("Set SSRatios"); _nextSSRation = scopeRes.getFieldInfo("_nextSSRation"); } IEnumerator tryGetScopeCamera() { if (scopeRes.getScopeCamera() == null) { //Logger.LogInfo("ScopeCamera not found! Restarting..."); yield return myDelaySec; StartCoroutine(tryGetScopeCamera()); yield break; } //Logger.LogInfo("Assigning scopeCamera"); scopeCamera = scopeRes.getScopeCamera(); } void updateMainCameraResolution(float value) { //Logger.LogInfo($"Updating {Camera.main.name} SSRatio to {value / 100f}"); _nextSSRation.SetValue(ssaaInstance, (float)(getCurrentScalingFactor() * value / 100f)); } void updateScopeCameraResolution(float value) { //Logger.LogInfo($"Updating {scopeCamera.name} to {value / 100f}"); scopeCamera.GetComponent().OpticCameraToMainCameraResolutionRatio = (float)(value / 100f); } void updateInGameFOVValue(int value) { //Logger.LogInfo($"Updating in-game FOV value to: {value}"); Singleton.Instance.Game.Settings.FieldOfView.Value = value; } void onAimingChanged() { //Logger.LogInfo($"isAiming: {mainPlayer.HandsController.IsAiming}"); if (mainPlayer.HandsController.IsAiming) { //Logger.LogInfo($"Updating MainCamRes to {cameraResolutionScale.Value}"); updateMainCameraResolution(cameraResolutionScale.Value); switch (scopeFixType.Value) { case EFOVScalingMode.Disabled: { break; } case EFOVScalingMode.Enabled: { //Logger.LogInfo($"Scopes only! ScopeCamRes: {scopeCameraResolutionScale.Value}"); if (scopeCamera == null || !scopeCamera.isActiveAndEnabled) break; updateScopeCameraResolution(scopeCameraResolutionScale.Value); updateInGameFOVValue(50); break; } } return; } if (!mainPlayer.HandsController.IsAiming) { //Logger.LogWarning($"Restoring default MainCamRes {defaultSSRatio * 100f}"); updateMainCameraResolution(getCurrentScalingFactor() * 100f); switch (scopeFixType.Value) { case EFOVScalingMode.Disabled: { break; } case EFOVScalingMode.Enabled: { //Logger.LogInfo($"Restoring FOV to {defaultFOVValue}"); updateInGameFOVValue(defaultFOVValue); GClass1762.Instance.SetFov(defaultFOVValue, 1f, true); break; } } return; } } void subscribeToOnAimingChanged() { mainPlayer.HandsController.OnAimingChanged += (args) => { onAimingChanged(); }; } GameStatus lastGameState = GameStatus.Stopped; bool gameStateChanged(GameStatus currentState) { if (lastGameState != currentState) { lastGameState = currentState; //Logger.LogInfo($"GameState changed! {currentState}"); return true; } //Logger.LogInfo("GameState unchanged."); return false; } IEnumerator tryApplyHideoutWorkaround() { if (Singleton.Instance != null) { Singleton.Instance.HandsChangedEvent += (argsHand) => { Singleton.Instance.HandsController.OnAimingChanged += (argsAim) => { onAimingChanged(); }; }; } else { yield return myDelaySec; StartCoroutine(tryApplyHideoutWorkaround()); } } Player mainPlayer = null; bool doneOnce = false; void Update() { if (Singleton.Instance == null) { doneOnce = false; return; } GameStatus currentGameState = Singleton.Instance.Status; if (currentGameState == GameStatus.Started && mainPlayer != null && mainPlayer.GetType() == typeof(HideoutPlayer) && !doneOnce) { //Logger.LogInfo("Hideout workaround"); doneOnce = true; StartCoroutine(tryApplyHideoutWorkaround()); } if (!gameStateChanged(currentGameState)) return; if ((currentGameState == GameStatus.SoftStopping || currentGameState == GameStatus.Stopped)) { //Logger.LogInfo("Game is stopping, resetting stuffs for the next raid"); mainPlayer = null; return; } if (currentGameState == GameStatus.Started) { //Logger.LogInfo("Getting local player"); mainPlayer = utils.getLocalPlayer(); //Logger.LogInfo("setUpCameras()"); setUpCameras(); //Logger.LogInfo("Grab default FOV from settings singleton"); defaultFOVValue = Singleton.Instance.Game.Settings.FieldOfView; mainPlayer.HandsChangedEvent += (args) => { //Logger.LogInfo($"Hands changed! {args.Item.Name} Subscribing again..."); subscribeToOnAimingChanged(); }; } } float getCurrentScalingFactor() { var graphics = Singleton.Instance.Graphics.Settings; if (!graphics.DLSSEnabled && !graphics.FSREnabled) { //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; } } //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; } } //Logger.LogInfo($"FSR factor: {FSRFactor}"); return FSRFactor; } Logger.LogInfo($"GetCurrentScalingFactor(): Something went wrong. Returning 1.0f"); return 1.0f; } } }