using BepInEx; using BepInEx.Configuration; using EFT; using UnityEngine; using Comfort.Common; using System.Reflection; using System.Collections; using EFT.UI; using EFT.Animations; using System.ComponentModel; namespace ScopeTweaks { [BepInPlugin("com.notGreg.scopeTweaks", "notGreg's Scope Tweaks", "1.0.0")] public class Plugin : BaseUnityPlugin { Utils utils = new Utils(); CameraUtils scopeRes = new CameraUtils(); ConfigEntry cameraResolutionScale; ConfigEntry scopeCameraResolutionScale; ConfigEntry scopeFixType; enum EFOVScalingMode { Disabled, [Description("Only affect scopes")] ScopesOnly, [Description("Affect all sights")] All } 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", "Disable ADS FOV scaling", EFOVScalingMode.ScopesOnly, new ConfigDescription("")); } float defaultSSRatio = 1.0f; Camera FPSCamera = null; Camera scopeCamera = null; SSAA ssaaInstance = null; FieldInfo _currentSSRatio = null; FieldInfo _nextSSRation = null; int defaultFOVValue = 50; 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"); _currentSSRatio = scopeRes.getFieldInfo("_currentSSRatio"); //Logger.LogInfo($"Updating defaultSSRatio to {_nextSSRation.GetValue(ssaaInstance)}"); defaultSSRatio = (float)_nextSSRation.GetValue(ssaaInstance); } 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)(defaultSSRatio * 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 subscribeToOnAimingChanged() { mainPlayer.HandsController.OnAimingChanged += (args) => { switch (scopeFixType.Value) { case EFOVScalingMode.Disabled: { break; } case EFOVScalingMode.ScopesOnly: { if (scopeCamera == null || !scopeCamera.isActiveAndEnabled) break; updateScopeCameraResolution(scopeCameraResolutionScale.Value); updateInGameFOVValue(50); break; } case EFOVScalingMode.All: { updateScopeCameraResolution(scopeCameraResolutionScale.Value); updateInGameFOVValue(50); break; } } if (mainPlayer.HandsController.IsAiming) { updateMainCameraResolution(cameraResolutionScale.Value); if (scopeCamera != null && scopeCamera.isActiveAndEnabled) { updateScopeCameraResolution(scopeCameraResolutionScale.Value); updateInGameFOVValue(50); } return; } if (!mainPlayer.HandsController.IsAiming) { updateMainCameraResolution(defaultSSRatio); updateInGameFOVValue(defaultFOVValue); GClass1762.Instance.SetFov(defaultFOVValue, 1f, true); return; } }; } 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; } Player mainPlayer = null; void hideoutWorkaround() { if (mainPlayer.HandsController.IsAiming) { if (mainPlayer.HandsController.IsAiming) { updateMainCameraResolution(cameraResolutionScale.Value); if (scopeCamera != null && scopeCamera.isActiveAndEnabled) { updateScopeCameraResolution(scopeCameraResolutionScale.Value); updateInGameFOVValue(50); } return; } if (!mainPlayer.HandsController.IsAiming) { updateMainCameraResolution(defaultSSRatio); updateInGameFOVValue(defaultFOVValue); GClass1762.Instance.SetFov(defaultFOVValue, 1f, true); return; } } } void Update() { if (Singleton.Instance == null) return; GameStatus currentGameState = Singleton.Instance.Status; if (currentGameState == GameStatus.Started && mainPlayer != null && mainPlayer.GetType() == typeof(HideoutPlayer)) { switch(scopeFixType.Value) { case EFOVScalingMode.Disabled: { break; } default: { hideoutWorkaround(); break; } } } 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($"Returned: {mainPlayer.GetType()}"); //Logger.LogInfo("Updating default FOV value"); if (defaultFOVValue != Camera.main.fieldOfView) { defaultFOVValue = (int)Camera.main.fieldOfView; } //Logger.LogInfo("setUpCameras()"); setUpCameras(); //Logger.LogInfo("UpdateSSRatio()"); defaultSSRatio = (float)_nextSSRation.GetValue(ssaaInstance); //Logger.LogInfo($"Updating defaultSSRatio to {defaultSSRatio}"); //updateSSRatio(); //Logger.LogInfo("subscibeToOnAimingChanged()"); subscribeToOnAimingChanged(); defaultFOVValue = Singleton.Instance.Game.Settings.FieldOfView; return; } } } }