using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using Comfort.Common; using EFT; using EFT.Settings.Graphics; //using System.Collections; //using System.Reflection; using System.Threading.Tasks; 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.7")] [BepInDependency("FOVFix", BepInDependency.DependencyFlags.SoftDependency)] public class Plugin : BaseUnityPlugin { //ConfigEntry scopeCameraResolutionScale; ConfigEntry enableDebug; void Awake() { if (Chainloader.PluginInfos.ContainsKey("FOVFix")) { Logger.LogWarning("Fontaine's FOV Fix detected! FOV Fix will NOT be available."); } else { new CalculateScaleValueByFovPatch().Enable(); } //scopeCameraResolutionScale = Config.Bind( // "General", // "Scope camera scale %", // 80, // new ConfigDescription("Additional override applied on top of currently enabled resolution scaling method.", new AcceptableValueRange(10, 100))); 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.Instance == null) return; GameStatus currentGameState = Singleton.Instance.Status; if (mainPlayer != null) { int inGameFov = Singleton.Instance.Game.Settings.FieldOfView; float fov_clamped = Mathf.Clamp(inGameFov, 50, 75); target_scale = Mathf.Lerp(1.0f, 0.65f, (fov_clamped - 50) / 25); if (mainPlayer.ProceduralWeaponAnimation.IsAiming) { mainPlayer.RibcageScaleCurrent = 1.0f; mainPlayer.RibcageScaleCurrentTarget = 1.0f; } else { mainPlayer.RibcageScaleCurrentTarget = target_scale; mainPlayer.RibcageScaleCurrent = target_scale; } } //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(); break; } case GameStatus.SoftStopping: case GameStatus.Stopping: case GameStatus.Stopped: { if (enableDebug.Value) Logger.LogInfo("Resetting..."); scopeCamera = null; mainPlayer = null; break; } default: break; } } /// /// GAME STATUS /// 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 = null; //find and return the player character in the session Player getLocalPlayer() { if (enableDebug.Value) Logger.LogInfo("Looking for local player..."); Player localPlayer = Singleton.Instance.RegisteredPlayers.Find(p => p.IsYourPlayer); if (enableDebug.Value && localPlayer != null) Logger.LogInfo($"Found local player: {localPlayer.GetType()}"); return localPlayer; } /// /// CAMERA SETUP /// Camera scopeCamera = null; async void tryGetScopeCamera() { string cameraName = "BaseOpticCamera(Clone)"; if (await Task.Run(() => GameObject.Find(cameraName) != null)) { scopeCamera = await Task.Run(() => GameObject.Find(cameraName).GetComponent()); } } //SSAAOptic ssaaOpticInstance = null; //Component has been nuked by BSG, thanks Nikita :) //TODO: Find a workaround to achieve the same result (scale scope resolution while ADS) //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}%"); // if (ssaaOpticInstance == null) // { // ssaaOpticInstance = scopeCamera.GetComponent(); // } // ssaaOpticInstance.OpticCameraToMainCameraResolutionRatio = (float)(currentResoScalingFactor * (value / 100.0f)); //} /// /// PLAYER WEAPON EVENTS /// void subscribeHandsChangedEvent() { if (enableDebug.Value) Logger.LogInfo("Subscribing to HandsChanged Event"); mainPlayer.HandsChangedEvent += (handsArgs) => { subscribeOnAimingChangedEvent(); }; } internal static float target_scale = 1.0f; void subscribeOnAimingChangedEvent() { if (enableDebug.Value) Logger.LogInfo("Subscribing to OnAimingChanged Event"); mainPlayer.HandsController.OnAimingChanged += (aimingArgs) => { currentResoScalingFactor = getcurrentResoScalingFactor(); tryGetScopeCamera(); if (mainPlayer.ProceduralWeaponAnimation.IsAiming) { target_scale = 1.0f; //setScopeCameraResolutionScale(scopeCameraResolutionScale.Value); } }; } float currentResoScalingFactor = 1.0f; float getcurrentResoScalingFactor() { if (enableDebug.Value) Logger.LogInfo("Getting current scaling factor:"); var graphics = Singleton.Instance.Graphics.Settings; 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($"Supersampling factor: {graphics.SuperSamplingFactor}"); return graphics.SuperSamplingFactor; } } }