Decompiled source of InternalResolutionDownscaling v1.1.0

BepInEx/plugins/InternalResolutionDownscaling/InternalResolutionDownscaling.dll

Decompiled 4 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using RiskOfOptions;
using RiskOfOptions.OptionConfigs;
using RiskOfOptions.Options;
using RoR2;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace InternalResolutionDownscaling
{
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("qlutz.InternalResolutionDownscaling", "InternalResolutionDownscaling", "1.0.1")]
	public class InternalResolutionDownscalingPlugin : BaseUnityPlugin
	{
		private class RigState
		{
			public Camera sceneCam;

			public Camera uiCam;

			public float originalSceneDepth;

			public CameraClearFlags originalUiClear;

			public bool uiClearChanged;
		}

		private class HoloState
		{
			public Component comp;

			public readonly Dictionary<Transform, int> orig = new Dictionary<Transform, int>();

			public Renderer[] renderers;

			public bool onOverlay;

			public int clearFrames;
		}

		public const string PluginGuid = "qlutz.InternalResolutionDownscaling";

		public const string PluginName = "InternalResolutionDownscaling";

		public const string PluginVersion = "1.0.1";

		public const string RiskOfOptionsGuid = "com.rune580.riskofoptions";

		private const float SceneCamDepth = -100f;

		private const float UpscalerDepth = -99f;

		private ConfigEntry<bool> enabledCfg;

		private ConfigEntry<float> scaleCfg;

		private ConfigEntry<FilterMode> filterCfg;

		private ConfigEntry<bool> exclusiveFullscreenCfg;

		private ConfigEntry<bool> clearBackbufferCfg;

		private ConfigEntry<bool> opaqueMatCfg;

		private ConfigEntry<bool> noAlphaCfg;

		private ConfigEntry<int> pausedFpsCfg;

		private bool fpsLimited;

		private float pausedSince = -1f;

		private bool fpsUserOverride;

		private int savedTargetFps = -1;

		private int lastAppliedFps = -2;

		private bool exiting;

		private RenderTextureFormat rtFormat;

		private float nextShaderRetry;

		private Material opaqueMat;

		private Func<bool> pauseGetter;

		private Func<object> runGetter;

		private bool runResolved;

		private bool pauseResolved;

		private ConfigEntry<bool> drawTextureCfg;

		private ConfigEntry<bool> testPatternCfg;

		private ConfigEntry<KeyboardShortcut> increaseKeyCfg;

		private ConfigEntry<KeyboardShortcut> decreaseKeyCfg;

		private ConfigEntry<float> stepCfg;

		private ConfigEntry<bool> customResCfg;

		private ConfigEntry<int> customWidthCfg;

		private ConfigEntry<int> customHeightCfg;

		private ConfigEntry<bool> flipCfg;

		private ConfigEntry<bool> releaseCfg;

		private ConfigEntry<bool> damageNumbersCfg;

		private ConfigEntry<bool> pricesCfg;

		private ConfigEntry<bool> overlayCamCfg;

		private ConfigEntry<bool> overlayForwardCfg;

		private ConfigEntry<bool> occlusionCfg;

		private ConfigEntry<float> priceBrightnessCfg;

		private float appliedPriceBrightness = -1f;

		private readonly Dictionary<Component, HoloState> holos = new Dictionary<Component, HoloState>();

		private readonly List<Component> holoDead = new List<Component>();

		private int overlayHolos;

		private int occlusionMask = -2;

		private Type costHoloType;

		private bool costHoloTypeResolved;

		private float nextHoloScan;

		private readonly List<Component> holoNew = new List<Component>();

		private readonly HashSet<Component> holoKnown = new HashSet<Component>();

		private readonly List<Transform> tmpTransforms = new List<Transform>();

		private bool holoHooked;

		private bool holoNeedsScan = true;

		private Camera overlayCam;

		private GameObject dmgGo;

		private ParticleSystem dmgPs;

		private float dmgLastActive = -999f;

		private int dmgOrigLayer;

		private int dmgLayer = -1;

		private float nextDmgSearch;

		private float nextFullscreenCheck;

		private Texture2D testTex;

		private readonly Dictionary<CameraRigController, RigState> states = new Dictionary<CameraRigController, RigState>();

		private readonly List<CameraRigController> deadRigs = new List<CameraRigController>();

		private RenderTexture rt;

		private bool rtHdr;

		private Upscaler upscaler;

		private bool isActive;

		internal static InternalResolutionDownscalingPlugin Instance;

		private Harmony harmony;

		private static readonly MaterialPropertyBlock flatFaceBlock = new MaterialPropertyBlock();

		private static readonly int FaceTexId = Shader.PropertyToID("_FaceTex");

		private static readonly int FaceColorId = Shader.PropertyToID("_FaceColor");

		private readonly RaycastHit[] rayHits = (RaycastHit[])(object)new RaycastHit[16];

		private void Awake()
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Expected O, but got Unknown
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Expected O, but got Unknown
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Expected O, but got Unknown
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Expected O, but got Unknown
			//IL_02a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b0: Expected O, but got Unknown
			//IL_0367: Unknown result type (might be due to invalid IL or missing references)
			//IL_0392: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03df: Expected O, but got Unknown
			//IL_048c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0492: Expected O, but got Unknown
			//IL_04ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_0546: Unknown result type (might be due to invalid IL or missing references)
			//IL_054c: Expected O, but got Unknown
			//IL_0614: Unknown result type (might be due to invalid IL or missing references)
			//IL_061e: Expected O, but got Unknown
			//IL_061e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0628: Expected O, but got Unknown
			//IL_0667: Unknown result type (might be due to invalid IL or missing references)
			//IL_0671: Expected O, but got Unknown
			//IL_0671: Unknown result type (might be due to invalid IL or missing references)
			//IL_067b: Expected O, but got Unknown
			//IL_0687: Unknown result type (might be due to invalid IL or missing references)
			//IL_0691: Expected O, but got Unknown
			//IL_052a: Unknown result type (might be due to invalid IL or missing references)
			//IL_052f: Unknown result type (might be due to invalid IL or missing references)
			//IL_053c: Expected O, but got Unknown
			//IL_06f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0708: Unknown result type (might be due to invalid IL or missing references)
			//IL_0715: Expected O, but got Unknown
			//IL_0715: Expected O, but got Unknown
			enabledCfg = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Turn this off (or set render scale to exactly 1.0) to render the game normally.");
			scaleCfg = ((BaseUnityPlugin)this).Config.Bind<float>("General", "RenderScale", 1f, new ConfigDescription("Internal 3D resolution multiplier. 0.5 = half resolution, 1.0 = native, 2.0 = supersampled. The UI is never scaled.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 2f), Array.Empty<object>()));
			customResCfg = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "UseCustomResolution", false, "Ignore RenderScale and render the 3D scene at exactly CustomWidth x CustomHeight pixels. Keep the same aspect ratio as your screen or the image will be stretched and the field of view will change.");
			customWidthCfg = ((BaseUnityPlugin)this).Config.Bind<int>("General", "CustomWidth", 1920, new ConfigDescription("Internal render width in pixels (used when UseCustomResolution is on).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(16, 8192), Array.Empty<object>()));
			customHeightCfg = ((BaseUnityPlugin)this).Config.Bind<int>("General", "CustomHeight", 1080, new ConfigDescription("Internal render height in pixels (used when UseCustomResolution is on).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(16, 8192), Array.Empty<object>()));
			pausedFpsCfg = ((BaseUnityPlugin)this).Config.Bind<int>("General", "PausedFpsLimit", 60, new ConfigDescription("Cap the frame rate while the game is paused (0 = no cap). Has no effect if VSync is on (VSync already sets the frame rate).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 500), Array.Empty<object>()));
			clearBackbufferCfg = ((BaseUnityPlugin)this).Config.Bind<bool>("Troubleshooting", "ClearBackbuffer", false, "Clear the screen to black before drawing the upscaled image. Prevents after-images from semi-transparent pixels. Turn on if you see after-images; leave off if the screen goes black or flickers.");
			opaqueMatCfg = ((BaseUnityPlugin)this).Config.Bind<bool>("Troubleshooting", "OpaqueUpscaleMaterial", true, "Draw the upscaled image with a blend-off copy shader (Hidden/BlitCopy) instead of Unity's default alpha-blended one, so the scene's alpha channel is ignored. This is the proper fix for both after-images and dark outlines. Only used with UseDrawTexture. Check the log for 'Opaque copy material created'.");
			noAlphaCfg = ((BaseUnityPlugin)this).Config.Bind<bool>("Troubleshooting", "NoAlphaSceneTexture", false, "Fallback if OpaqueUpscaleMaterial can't find its shader: render the scene into a texture with no alpha channel (R11G11B10) so alpha is always 1. May affect effects that rely on scene alpha.");
			damageNumbersCfg = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "UnscaledDamageNumbers", true, "Draw damage numbers at native resolution (like the UI) instead of through the scaled 3D image.");
			pricesCfg = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "UnscaledInteractablePrices", false, "Draw the price shown near chests, shrines and other interactables at native resolution instead of through the scaled 3D image.");
			flipCfg = ((BaseUnityPlugin)this).Config.Bind<bool>("Troubleshooting", "FlipVertical", true, "Flip the upscaled image vertically. Leave on unless the image appears upside down.");
			releaseCfg = ((BaseUnityPlugin)this).Config.Bind<bool>("Troubleshooting", "ReleaseTargetDuringUpdate", true, "Detach the scene camera from the render texture while the game's Update/LateUpdate scripts run, so things positioned with sceneCam.WorldToScreenPoint (enemy health bars) use screen coordinates. Turn off if the image looks wrong; health bars will then disappear again.");
			overlayCamCfg = ((BaseUnityPlugin)this).Config.Bind<bool>("Troubleshooting", "OverlayCameraRender", true, "Diagnostic: when off, the camera that draws the unscaled damage numbers and prices is never enabled (they will simply not be drawn).");
			overlayForwardCfg = ((BaseUnityPlugin)this).Config.Bind<bool>("Troubleshooting", "OverlayForwardRendering", true, "Diagnostic: the overlay camera uses forward rendering (cheap). Turn off to make it use the game's own rendering path (deferred, slower).");
			occlusionCfg = ((BaseUnityPlugin)this).Config.Bind<bool>("Troubleshooting", "PriceOcclusionCheck", true, "Switches out native resolution prices for downscaled when obscured by geometry. Turning this off will result in native resolution prices being visible through geometry.");
			priceBrightnessCfg = ((BaseUnityPlugin)this).Config.Bind<float>("General", "UnscaledPriceBrightness", 1.3f, new ConfigDescription("Brightness multiplier for the price text rendered at native resolution.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 3f), Array.Empty<object>()));
			filterCfg = ((BaseUnityPlugin)this).Config.Bind<FilterMode>("General", "UpscaleFilter", (FilterMode)0, "How the scaled image is stretched to the screen. Point = crisp pixels, Bilinear = smooth.");
			exclusiveFullscreenCfg = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ExclusiveFullscreen", false, "Force exclusive fullscreen instead of the game's default borderless window.");
			exclusiveFullscreenCfg.SettingChanged += delegate
			{
				ApplyFullscreenMode(force: true);
			};
			drawTextureCfg = ((BaseUnityPlugin)this).Config.Bind<bool>("Troubleshooting", "UseDrawTexture", true, "Upscale with Graphics.DrawTexture instead of Graphics.Blit. On some setups Graphics.Blit to the backbuffer never shows up or stays smooth even with UpscaleFilter = Point, while DrawTexture gives crisp pixels. Turn off to fall back to Blit.");
			testPatternCfg = ((BaseUnityPlugin)this).Config.Bind<bool>("Troubleshooting", "TestPattern", false, "Diagnostic: draw a coarse checkerboard through the upscaler instead of the game image.");
			increaseKeyCfg = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Hotkeys", "IncreaseScale", new KeyboardShortcut((KeyCode)0, Array.Empty<KeyCode>()), "Raise the render scale by one step.");
			decreaseKeyCfg = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Hotkeys", "DecreaseScale", new KeyboardShortcut((KeyCode)0, Array.Empty<KeyCode>()), "Lower the render scale by one step.");
			stepCfg = ((BaseUnityPlugin)this).Config.Bind<float>("Hotkeys", "Step", 0.05f, new ConfigDescription("How much each hotkey press changes the scale.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.01f, 0.5f), Array.Empty<object>()));
			if (Chainloader.PluginInfos.ContainsKey("com.rune580.riskofoptions"))
			{
				RiskOfOptionsCompat.Register(enabledCfg, scaleCfg, customResCfg, customWidthCfg, customHeightCfg, pausedFpsCfg, clearBackbufferCfg, opaqueMatCfg, noAlphaCfg, filterCfg, exclusiveFullscreenCfg, damageNumbersCfg, pricesCfg, drawTextureCfg, testPatternCfg, flipCfg, releaseCfg, overlayCamCfg, overlayForwardCfg, occlusionCfg, priceBrightnessCfg, increaseKeyCfg, decreaseKeyCfg);
			}
			GameObject val = new GameObject("InternalResolutionDownscaling_Upscaler");
			val.transform.SetParent(((Component)this).transform, false);
			Camera val2 = val.AddComponent<Camera>();
			val2.cullingMask = 0;
			val2.clearFlags = (CameraClearFlags)4;
			val2.backgroundColor = Color.black;
			val2.depth = -99f;
			val2.allowHDR = false;
			val2.allowMSAA = false;
			val2.useOcclusionCulling = false;
			val2.renderingPath = (RenderingPath)1;
			val2.depthTextureMode = (DepthTextureMode)0;
			val2.allowDynamicResolution = false;
			((Behaviour)val2).enabled = false;
			upscaler = val.AddComponent<Upscaler>();
			upscaler.cam = val2;
			try
			{
				Shader val3 = FindOpaqueCopyShader();
				if ((Object)(object)val3 != (Object)null)
				{
					opaqueMat = new Material(val3)
					{
						hideFlags = (HideFlags)61
					};
				}
			}
			catch (Exception)
			{
			}
			GameObject val4 = new GameObject("InternalResolutionDownscaling_DamageNumbers");
			val4.transform.SetParent(((Component)this).transform, false);
			overlayCam = val4.AddComponent<Camera>();
			overlayCam.cullingMask = 0;
			overlayCam.clearFlags = (CameraClearFlags)3;
			overlayCam.depth = -98f;
			overlayCam.allowHDR = false;
			overlayCam.allowMSAA = false;
			overlayCam.useOcclusionCulling = false;
			overlayCam.renderingPath = (RenderingPath)1;
			overlayCam.depthTextureMode = (DepthTextureMode)0;
			overlayCam.allowDynamicResolution = false;
			((Behaviour)overlayCam).enabled = false;
			((Component)this).gameObject.AddComponent<TargetGateEarly>().plugin = this;
			((Component)this).gameObject.AddComponent<TargetGateLate>().plugin = this;
			Camera.onPreCull = (CameraCallback)Delegate.Combine((Delegate?)(object)Camera.onPreCull, (Delegate?)new CameraCallback(OnAnyCamPreCull));
			Application.wantsToQuit += OnWantsToQuit;
			Application.quitting += OnQuitting;
			SceneManager.activeSceneChanged += OnActiveSceneChanged;
			Camera.onPreRender = (CameraCallback)Delegate.Combine((Delegate?)(object)Camera.onPreRender, (Delegate?)new CameraCallback(OnAnyCamPreRender));
			Instance = this;
			try
			{
				harmony = new Harmony("qlutz.InternalResolutionDownscaling");
				MethodInfo[] methods = typeof(Camera).GetMethods(BindingFlags.Instance | BindingFlags.Public);
				foreach (MethodInfo methodInfo in methods)
				{
					if (!(methodInfo.Name != "WorldToScreenPoint") && !(methodInfo.ReturnType != typeof(Vector3)))
					{
						harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(WorldToScreenFix), "Prefix", (Type[])null), new HarmonyMethod(typeof(WorldToScreenFix), "Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					}
				}
			}
			catch (Exception)
			{
			}
		}

		private Shader FindOpaqueCopyShader()
		{
			try
			{
				Shader val = Shader.Find("Hidden/BlitCopy");
				if ((Object)(object)val != (Object)null && val.isSupported)
				{
					return val;
				}
			}
			catch (Exception)
			{
			}
			Shader[] array = Resources.FindObjectsOfTypeAll<Shader>();
			foreach (Shader val2 in array)
			{
				if (Object.op_Implicit((Object)(object)val2) && ((Object)val2).name == "Hidden/BlitCopy" && val2.isSupported)
				{
					return val2;
				}
			}
			return null;
		}

		internal bool TryGetProjectionFactor(Camera c, out float fx, out float fy)
		{
			fx = (fy = 1f);
			if (!isActive || (Object)(object)rt == (Object)null || !Object.op_Implicit((Object)(object)c) || (Object)(object)c.targetTexture != (Object)(object)rt)
			{
				return false;
			}
			fx = (float)Screen.width / (float)((Texture)rt).width;
			fy = (float)Screen.height / (float)((Texture)rt).height;
			return true;
		}

		private void OnDestroy()
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Expected O, but got Unknown
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Expected O, but got Unknown
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Expected O, but got Unknown
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Expected O, but got Unknown
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			if ((Object)(object)Instance == (Object)(object)this)
			{
				Instance = null;
			}
			Camera.onPreCull = (CameraCallback)Delegate.Remove((Delegate?)(object)Camera.onPreCull, (Delegate?)new CameraCallback(OnAnyCamPreCull));
			Camera.onPreRender = (CameraCallback)Delegate.Remove((Delegate?)(object)Camera.onPreRender, (Delegate?)new CameraCallback(OnAnyCamPreRender));
			Application.wantsToQuit -= OnWantsToQuit;
			Application.quitting -= OnQuitting;
			SceneManager.activeSceneChanged -= OnActiveSceneChanged;
			RestoreFpsLimit();
			Deactivate();
		}

		private bool OnWantsToQuit()
		{
			exiting = true;
			RestoreFpsLimit();
			return true;
		}

		private void OnQuitting()
		{
			exiting = true;
			RestoreFpsLimit();
		}

		private void OnApplicationQuit()
		{
			exiting = true;
			RestoreFpsLimit();
		}

		private void OnActiveSceneChanged(Scene from, Scene to)
		{
			if (fpsLimited)
			{
				fpsUserOverride = true;
			}
			RestoreFpsLimit();
		}

		private void RestoreFpsLimit()
		{
			if (fpsLimited)
			{
				fpsLimited = false;
				Application.targetFrameRate = savedTargetFps;
			}
		}

		private void OnAnyCamPreCull(Camera c)
		{
			EnforceTarget(c, "Camera.onPreCull");
		}

		private void OnAnyCamPreRender(Camera c)
		{
			EnforceTarget(c, "Camera.onPreRender");
		}

		private void SyncOverlay()
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			foreach (KeyValuePair<CameraRigController, RigState> state in states)
			{
				Camera sceneCam = state.Value.sceneCam;
				if (Object.op_Implicit((Object)(object)sceneCam))
				{
					((Component)overlayCam).transform.SetPositionAndRotation(((Component)sceneCam).transform.position, ((Component)sceneCam).transform.rotation);
					overlayCam.fieldOfView = sceneCam.fieldOfView;
					overlayCam.nearClipPlane = sceneCam.nearClipPlane;
					overlayCam.farClipPlane = sceneCam.farClipPlane;
					overlayCam.rect = sceneCam.rect;
					break;
				}
			}
		}

		private void SyncOverlayObjects()
		{
			//IL_02d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02de: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e7: Unknown result type (might be due to invalid IL or missing references)
			bool value = damageNumbersCfg.Value;
			bool value2 = pricesCfg.Value;
			if (!value)
			{
				RestoreDamageNumbers();
			}
			if (!value2)
			{
				RestorePrices();
			}
			if (!value && !value2)
			{
				((Behaviour)overlayCam).enabled = false;
				return;
			}
			if (dmgLayer < 0)
			{
				for (int num = 31; num >= 8; num--)
				{
					if (string.IsNullOrEmpty(LayerMask.LayerToName(num)))
					{
						dmgLayer = num;
						break;
					}
				}
				if (dmgLayer < 0)
				{
					int[] array = new int[32];
					GameObject[] array2 = Object.FindObjectsOfType<GameObject>();
					foreach (GameObject val in array2)
					{
						array[val.layer]++;
					}
					int num2 = -1;
					for (int num3 = 31; num3 >= 8; num3--)
					{
						if (num2 < 0 || array[num3] < array[num2])
						{
							num2 = num3;
						}
					}
					dmgLayer = num2;
				}
				overlayCam.cullingMask = 1 << dmgLayer;
			}
			if (value && !Object.op_Implicit((Object)(object)dmgGo) && Time.unscaledTime >= nextDmgSearch)
			{
				nextDmgSearch = Time.unscaledTime + 0.5f;
				DamageNumberManager val2 = Object.FindObjectOfType<DamageNumberManager>();
				if (Object.op_Implicit((Object)(object)val2))
				{
					ParticleSystem val3 = null;
					FieldInfo field = typeof(DamageNumberManager).GetField("ps", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (field != null && typeof(ParticleSystem).IsAssignableFrom(field.FieldType))
					{
						object? value3 = field.GetValue(val2);
						val3 = (ParticleSystem)((value3 is ParticleSystem) ? value3 : null);
					}
					if (!Object.op_Implicit((Object)(object)val3))
					{
						val3 = ((Component)val2).GetComponent<ParticleSystem>();
					}
					if (!Object.op_Implicit((Object)(object)val3))
					{
						val3 = ((Component)val2).GetComponentInChildren<ParticleSystem>(true);
					}
					if (Object.op_Implicit((Object)(object)val3))
					{
						dmgGo = ((Component)val3).gameObject;
						dmgPs = val3;
						dmgOrigLayer = dmgGo.layer;
						Transform[] componentsInChildren = dmgGo.GetComponentsInChildren<Transform>(true);
						for (int i = 0; i < componentsInChildren.Length; i++)
						{
							((Component)componentsInChildren[i]).gameObject.layer = dmgLayer;
						}
					}
				}
			}
			if (value2)
			{
				SyncPrices();
			}
			if (value2 && !Mathf.Approximately(appliedPriceBrightness, priceBrightnessCfg.Value))
			{
				appliedPriceBrightness = priceBrightnessCfg.Value;
				foreach (KeyValuePair<Component, HoloState> holo in holos)
				{
					if (holo.Value.onOverlay)
					{
						ApplyHoloLook(holo.Value);
					}
				}
			}
			if (Object.op_Implicit((Object)(object)dmgPs) && dmgPs.particleCount > 0)
			{
				dmgLastActive = Time.unscaledTime;
			}
			RenderingPath val4 = (RenderingPath)(overlayForwardCfg.Value ? 1 : (-1));
			if (overlayCam.renderingPath != val4)
			{
				overlayCam.renderingPath = val4;
			}
			((Behaviour)overlayCam).enabled = overlayCamCfg.Value && (Time.unscaledTime - dmgLastActive < 0.25f || HoloWantsCamera());
		}

		private void SyncPrices()
		{
			if (!costHoloTypeResolved)
			{
				costHoloTypeResolved = true;
				costHoloType = typeof(DamageNumberManager).Assembly.GetType("RoR2.CostHologramContent");
				if (costHoloType != null)
				{
					holoHooked = HookHologram(costHoloType);
				}
			}
			if (costHoloType == null)
			{
				return;
			}
			float unscaledTime = Time.unscaledTime;
			bool flag = unscaledTime >= nextHoloScan;
			if (flag)
			{
				nextHoloScan = unscaledTime + 0.5f;
			}
			if (holoNeedsScan || (!holoHooked && flag))
			{
				holoNeedsScan = false;
				Object[] array = Object.FindObjectsOfType(costHoloType);
				foreach (Object o in array)
				{
					OnHologramSeen(o);
				}
			}
			for (int j = 0; j < holoNew.Count; j++)
			{
				if (Object.op_Implicit((Object)(object)holoNew[j]) && !holos.ContainsKey(holoNew[j]))
				{
					AddHolo(holoNew[j]);
				}
			}
			holoNew.Clear();
			if (!flag)
			{
				return;
			}
			holoDead.Clear();
			foreach (KeyValuePair<Component, HoloState> holo in holos)
			{
				if (!Object.op_Implicit((Object)(object)holo.Key))
				{
					holoDead.Add(holo.Key);
				}
				else
				{
					RefreshHolo(holo.Value);
				}
			}
			foreach (Component item in holoDead)
			{
				ForgetHolo(item);
			}
		}

		internal void OnHologramSeen(object o)
		{
			if (isActive && !(costHoloType == null) && pricesCfg.Value)
			{
				Component val = (Component)((o is Component) ? o : null);
				if (Object.op_Implicit((Object)(object)val) && holoKnown.Add(val))
				{
					holoNew.Add(val);
				}
			}
		}

		private void AddHolo(Component comp)
		{
			HoloState holoState = new HoloState
			{
				comp = comp
			};
			holos[comp] = holoState;
			RefreshHolo(holoState);
		}

		private void ForgetHolo(Component comp)
		{
			if (holos.TryGetValue(comp, out var value))
			{
				if (value.onOverlay)
				{
					overlayHolos--;
				}
				holos.Remove(comp);
			}
			holoKnown.Remove(comp);
		}

		private void RefreshHolo(HoloState h)
		{
			if (!Object.op_Implicit((Object)(object)h.comp))
			{
				return;
			}
			h.comp.GetComponentsInChildren<Transform>(true, tmpTransforms);
			for (int i = 0; i < tmpTransforms.Count; i++)
			{
				Transform val = tmpTransforms[i];
				if (!h.orig.ContainsKey(val))
				{
					h.orig[val] = ((Component)val).gameObject.layer;
					if (h.onOverlay && dmgLayer >= 0)
					{
						((Component)val).gameObject.layer = dmgLayer;
					}
				}
				else if (h.onOverlay && dmgLayer >= 0 && ((Component)val).gameObject.layer != dmgLayer)
				{
					((Component)val).gameObject.layer = dmgLayer;
				}
			}
			tmpTransforms.Clear();
			h.renderers = h.comp.GetComponentsInChildren<Renderer>(true);
			if (h.onOverlay)
			{
				ApplyHoloLook(h);
			}
		}

		private void SetHoloLayer(HoloState h, bool overlay)
		{
			if (h.onOverlay == overlay || dmgLayer < 0)
			{
				return;
			}
			h.onOverlay = overlay;
			overlayHolos += (overlay ? 1 : (-1));
			foreach (KeyValuePair<Transform, int> item in h.orig)
			{
				if (Object.op_Implicit((Object)(object)item.Key))
				{
					((Component)item.Key).gameObject.layer = (overlay ? dmgLayer : item.Value);
				}
			}
			ApplyHoloLook(h);
		}

		private void ApplyHoloLook(HoloState h)
		{
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			if (h.renderers == null)
			{
				return;
			}
			Renderer[] renderers = h.renderers;
			foreach (Renderer val in renderers)
			{
				if (!Object.op_Implicit((Object)(object)val))
				{
					continue;
				}
				Material sharedMaterial = val.sharedMaterial;
				if (Object.op_Implicit((Object)(object)sharedMaterial) && Object.op_Implicit((Object)(object)sharedMaterial.shader) && ((Object)sharedMaterial.shader).name.IndexOf("TextMeshPro", StringComparison.Ordinal) >= 0)
				{
					if (h.onOverlay)
					{
						val.GetPropertyBlock(flatFaceBlock);
						flatFaceBlock.SetTexture(FaceTexId, (Texture)(object)Texture2D.whiteTexture);
						float value = priceBrightnessCfg.Value;
						flatFaceBlock.SetColor(FaceColorId, new Color(value, value, value, 1f));
						val.SetPropertyBlock(flatFaceBlock);
					}
					else
					{
						val.SetPropertyBlock((MaterialPropertyBlock)null);
					}
				}
			}
		}

		private bool HoloWantsCamera()
		{
			if (overlayHolos > 0)
			{
				return true;
			}
			foreach (KeyValuePair<Component, HoloState> holo in holos)
			{
				if (holo.Value.clearFrames > 0)
				{
					return true;
				}
			}
			return false;
		}

		private void UpdateHoloOcclusion(Camera cam)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			if (dmgLayer < 0)
			{
				return;
			}
			Transform transform = ((Component)cam).transform;
			Vector3 position = transform.position;
			bool value = occlusionCfg.Value;
			foreach (KeyValuePair<Component, HoloState> holo in holos)
			{
				HoloState value2 = holo.Value;
				if (Object.op_Implicit((Object)(object)value2.comp))
				{
					if (!value)
					{
						value2.clearFrames = 3;
						SetHoloLayer(value2, overlay: true);
					}
					else if ((Object)(object)FindOccluder(position, transform, value2) != (Object)null)
					{
						value2.clearFrames = 0;
						SetHoloLayer(value2, overlay: false);
					}
					else if (++value2.clearFrames >= 3)
					{
						SetHoloLayer(value2, overlay: true);
					}
				}
			}
		}

		private Collider RayBlocker(Vector3 eye, Vector3 p, Transform ownRoot)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			Vector3 val = p - eye;
			float magnitude = ((Vector3)(ref val)).magnitude;
			float num = magnitude - 0.25f;
			if (num < 0.25f)
			{
				return null;
			}
			int num2 = Physics.RaycastNonAlloc(eye, val / magnitude, rayHits, num, GetOcclusionMask(), (QueryTriggerInteraction)1);
			for (int i = 0; i < num2; i++)
			{
				Collider collider = ((RaycastHit)(ref rayHits[i])).collider;
				if (Object.op_Implicit((Object)(object)collider) && (!Object.op_Implicit((Object)(object)ownRoot) || !((Object)(object)((Component)collider).transform.root == (Object)(object)ownRoot)))
				{
					return collider;
				}
			}
			return null;
		}

		private Collider FindOccluder(Vector3 eye, Transform camT, HoloState h)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			if (h.renderers == null)
			{
				return null;
			}
			bool flag = false;
			Bounds val = default(Bounds);
			for (int i = 0; i < h.renderers.Length; i++)
			{
				Renderer val2 = h.renderers[i];
				if (Object.op_Implicit((Object)(object)val2) && val2.enabled && ((Component)val2).gameObject.activeInHierarchy)
				{
					if (!flag)
					{
						val = val2.bounds;
						flag = true;
					}
					else
					{
						((Bounds)(ref val)).Encapsulate(val2.bounds);
					}
				}
			}
			if (!flag)
			{
				return null;
			}
			Vector3 right = camT.right;
			Vector3 up = camT.up;
			Vector3 extents = ((Bounds)(ref val)).extents;
			float num = (Mathf.Abs(right.x) * extents.x + Mathf.Abs(right.y) * extents.y + Mathf.Abs(right.z) * extents.z) * 0.8f;
			float num2 = (Mathf.Abs(up.x) * extents.x + Mathf.Abs(up.y) * extents.y + Mathf.Abs(up.z) * extents.z) * 0.8f;
			Vector3 center = ((Bounds)(ref val)).center;
			Transform root = h.comp.transform.root;
			Collider val3 = null;
			int num3 = 0;
			for (int j = 0; j < 5; j++)
			{
				Vector3 val4 = center;
				switch (j)
				{
				case 1:
					val4 += right * num;
					break;
				case 2:
					val4 -= right * num;
					break;
				case 3:
					val4 += up * num2;
					break;
				case 4:
					val4 -= up * num2;
					break;
				}
				Collider val5 = RayBlocker(eye, val4, root);
				if (!((Object)(object)val5 == (Object)null))
				{
					if (j == 0)
					{
						return val5;
					}
					if ((Object)(object)val3 == (Object)null)
					{
						val3 = val5;
					}
					num3++;
				}
			}
			if (num3 < 2)
			{
				return null;
			}
			return val3;
		}

		private int GetOcclusionMask()
		{
			if (occlusionMask != -2)
			{
				return occlusionMask;
			}
			int num = LayerMask.GetMask(new string[10] { "Debris", "Projectile", "Pickup", "Ragdoll", "Bullet", "Fluid", "NoCollision", "UI", "TransparentFX", "Water" });
			if (dmgLayer >= 0)
			{
				num |= 1 << dmgLayer;
			}
			occlusionMask = -5 & ~num;
			return occlusionMask;
		}

		private bool HookHologram(Type t)
		{
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Expected O, but got Unknown
			if (harmony == null)
			{
				return false;
			}
			int num = 0;
			BindingFlags bindingAttr = BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
			string[] array = new string[5] { "Awake", "OnEnable", "Start", "FixedUpdate", "Update" };
			foreach (string name in array)
			{
				MethodInfo method = t.GetMethod(name, bindingAttr, null, Type.EmptyTypes, null);
				if (!(method == null))
				{
					try
					{
						harmony.Patch((MethodBase)method, (HarmonyMethod)null, new HarmonyMethod(typeof(HologramHook), "Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
						num++;
					}
					catch (Exception)
					{
					}
				}
			}
			return num > 0;
		}

		private void RestorePrices()
		{
			foreach (KeyValuePair<Component, HoloState> holo in holos)
			{
				foreach (KeyValuePair<Transform, int> item in holo.Value.orig)
				{
					if (Object.op_Implicit((Object)(object)item.Key))
					{
						((Component)item.Key).gameObject.layer = item.Value;
					}
				}
				holo.Value.onOverlay = false;
				ApplyHoloLook(holo.Value);
			}
			holos.Clear();
			holoNew.Clear();
			holoKnown.Clear();
			overlayHolos = 0;
			holoNeedsScan = true;
		}

		private void RestoreDamageNumbers()
		{
			if (Object.op_Implicit((Object)(object)overlayCam))
			{
				((Behaviour)overlayCam).enabled = false;
			}
			if (Object.op_Implicit((Object)(object)dmgGo))
			{
				Transform[] componentsInChildren = dmgGo.GetComponentsInChildren<Transform>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					((Component)componentsInChildren[i]).gameObject.layer = dmgOrigLayer;
				}
			}
			dmgGo = null;
			dmgPs = null;
		}

		private void EnforceTarget(Camera c, string stage)
		{
			if (!isActive || (Object)(object)rt == (Object)null || !rt.IsCreated())
			{
				return;
			}
			if ((Object)(object)c == (Object)(object)overlayCam)
			{
				SyncOverlay();
				return;
			}
			bool flag = true;
			foreach (KeyValuePair<CameraRigController, RigState> state in states)
			{
				bool flag2 = flag;
				flag = false;
				if (!((Object)(object)state.Value.sceneCam != (Object)(object)c))
				{
					if (flag2 && holos.Count > 0 && stage == "Camera.onPreCull")
					{
						UpdateHoloOcclusion(c);
					}
					if ((Object.op_Implicit((Object)(object)dmgGo) || overlayHolos > 0) && dmgLayer >= 0)
					{
						c.cullingMask &= ~(1 << dmgLayer);
					}
					if ((Object)(object)c.targetTexture != (Object)(object)rt)
					{
						c.targetTexture = rt;
					}
				}
			}
		}

		private void LateUpdate()
		{
			if (Time.unscaledTime >= nextFullscreenCheck)
			{
				nextFullscreenCheck = Time.unscaledTime + 1f;
				ApplyFullscreenMode(force: false);
			}
			HandleHotkeys();
			ApplyPausedFpsLimit(IsPaused());
			if (!enabledCfg.Value || (!customResCfg.Value && Mathf.Approximately(scaleCfg.Value, 1f)))
			{
				if (isActive)
				{
					Deactivate();
				}
			}
			else
			{
				isActive = true;
				EnsureTexture();
				SyncRigs();
				SyncOverlayObjects();
			}
		}

		private void ApplyFullscreenMode(bool force)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			FullScreenMode val = (FullScreenMode)(!exclusiveFullscreenCfg.Value);
			if ((force || (exclusiveFullscreenCfg.Value && Application.isFocused)) && Screen.fullScreenMode != val)
			{
				Resolution currentResolution = Screen.currentResolution;
				Screen.SetResolution(((Resolution)(ref currentResolution)).width, ((Resolution)(ref currentResolution)).height, val, ((Resolution)(ref currentResolution)).refreshRate);
			}
		}

		private bool IsPaused()
		{
			if (!pauseResolved)
			{
				pauseResolved = true;
				try
				{
					Type type = typeof(DamageNumberManager).Assembly.GetType("RoR2.PauseManager");
					if (type != null)
					{
						BindingFlags bindingAttr = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
						PropertyInfo p = type.GetProperty("isPaused", bindingAttr);
						FieldInfo f = type.GetField("isPaused", bindingAttr);
						if (p != null && p.PropertyType == typeof(bool) && p.GetGetMethod(nonPublic: true) != null)
						{
							pauseGetter = () => (bool)p.GetValue(null, null);
						}
						else if (f != null && f.FieldType == typeof(bool))
						{
							pauseGetter = () => (bool)f.GetValue(null);
						}
					}
				}
				catch (Exception)
				{
					pauseGetter = null;
				}
			}
			if (pauseGetter != null)
			{
				try
				{
					return pauseGetter();
				}
				catch (Exception)
				{
					pauseGetter = null;
				}
			}
			return Time.timeScale <= 0f;
		}

		private bool InRun()
		{
			if (!runResolved)
			{
				runResolved = true;
				try
				{
					Type type = typeof(DamageNumberManager).Assembly.GetType("RoR2.Run");
					if (type != null)
					{
						BindingFlags bindingAttr = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
						PropertyInfo p = type.GetProperty("instance", bindingAttr);
						FieldInfo f = type.GetField("instance", bindingAttr);
						if (p != null && p.GetGetMethod(nonPublic: true) != null)
						{
							runGetter = () => p.GetValue(null, null);
						}
						else if (f != null)
						{
							runGetter = () => f.GetValue(null);
						}
					}
				}
				catch (Exception)
				{
					runGetter = null;
				}
			}
			if (runGetter == null)
			{
				return true;
			}
			try
			{
				object obj = runGetter();
				return Object.op_Implicit((Object)((obj is Object) ? obj : null));
			}
			catch (Exception)
			{
				runGetter = null;
				return true;
			}
		}

		private void ApplyPausedFpsLimit(bool paused)
		{
			if (!InRun() || exiting)
			{
				paused = false;
			}
			float unscaledTime = Time.unscaledTime;
			if (paused)
			{
				if (pausedSince < 0f)
				{
					pausedSince = unscaledTime;
				}
			}
			else
			{
				pausedSince = -1f;
			}
			bool flag = paused && unscaledTime - pausedSince >= 0.3f;
			if (!paused)
			{
				fpsUserOverride = false;
			}
			if (fpsLimited && Application.targetFrameRate != lastAppliedFps)
			{
				savedTargetFps = Application.targetFrameRate;
				fpsLimited = false;
				fpsUserOverride = true;
				return;
			}
			int value = pausedFpsCfg.Value;
			if (flag && value > 0 && !fpsUserOverride)
			{
				if (!fpsLimited)
				{
					int targetFrameRate = Application.targetFrameRate;
					if (targetFrameRate == value)
					{
						return;
					}
					fpsLimited = true;
					savedTargetFps = targetFrameRate;
				}
				if (Application.targetFrameRate != value)
				{
					Application.targetFrameRate = value;
				}
				lastAppliedFps = value;
			}
			else if (fpsLimited)
			{
				fpsLimited = false;
				Application.targetFrameRate = savedTargetFps;
			}
		}

		private void HandleHotkeys()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			KeyboardShortcut value = increaseKeyCfg.Value;
			if (((KeyboardShortcut)(ref value)).IsDown())
			{
				scaleCfg.Value = Mathf.Clamp(Mathf.Round((scaleCfg.Value + stepCfg.Value) * 100f) / 100f, 0.01f, 2f);
				return;
			}
			value = decreaseKeyCfg.Value;
			if (((KeyboardShortcut)(ref value)).IsDown())
			{
				scaleCfg.Value = Mathf.Clamp(Mathf.Round((scaleCfg.Value - stepCfg.Value) * 100f) / 100f, 0.01f, 2f);
			}
		}

		private static bool AnySceneCamHdr()
		{
			foreach (CameraRigController readOnlyInstances in CameraRigController.readOnlyInstancesList)
			{
				if (Object.op_Implicit((Object)(object)readOnlyInstances) && Object.op_Implicit((Object)(object)readOnlyInstances.sceneCam))
				{
					return readOnlyInstances.sceneCam.allowHDR;
				}
			}
			return false;
		}

		private void EnsureTexture()
		{
			//IL_0204: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ec: Expected O, but got Unknown
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Expected O, but got Unknown
			float value = scaleCfg.Value;
			int num;
			int num2;
			if (customResCfg.Value)
			{
				num = Mathf.Clamp(customWidthCfg.Value, 16, 8192);
				num2 = Mathf.Clamp(customHeightCfg.Value, 16, 8192);
			}
			else
			{
				num = Mathf.Clamp(Mathf.RoundToInt((float)Screen.width * value), 16, 8192);
				num2 = Mathf.Clamp(Mathf.RoundToInt((float)Screen.height * value), 16, 8192);
			}
			bool flag = AnySceneCamHdr();
			RenderTextureFormat val = (RenderTextureFormat)(flag ? 9 : 7);
			if (noAlphaCfg.Value && SystemInfo.SupportsRenderTextureFormat((RenderTextureFormat)22))
			{
				val = (RenderTextureFormat)22;
			}
			if ((Object)(object)rt != (Object)null && (rtHdr != flag || rtFormat != val))
			{
				ReleaseTexture();
			}
			else if ((Object)(object)rt != (Object)null && (((Texture)rt).width != num || ((Texture)rt).height != num2))
			{
				rt.Release();
				((Texture)rt).width = num;
				((Texture)rt).height = num2;
				rt.Create();
			}
			if (opaqueMatCfg.Value && (Object)(object)opaqueMat == (Object)null && Time.unscaledTime >= nextShaderRetry)
			{
				nextShaderRetry = Time.unscaledTime + 1f;
				try
				{
					Shader val2 = FindOpaqueCopyShader();
					if ((Object)(object)val2 != (Object)null)
					{
						opaqueMat = new Material(val2)
						{
							hideFlags = (HideFlags)61
						};
					}
				}
				catch (Exception)
				{
				}
			}
			if ((Object)(object)rt == (Object)null)
			{
				rtHdr = flag;
				rtFormat = val;
				rt = new RenderTexture(num, num2, 24, val)
				{
					name = "InternalResolutionDownscaling_SceneRT",
					antiAliasing = 1,
					wrapMode = (TextureWrapMode)1,
					useMipMap = false,
					autoGenerateMips = false,
					anisoLevel = 0
				};
				rt.Create();
			}
			((Texture)rt).filterMode = filterCfg.Value;
			((Texture)rt).anisoLevel = 0;
			upscaler.source = (Texture)(testPatternCfg.Value ? ((object)GetTestTexture()) : ((object)rt));
			upscaler.useDrawTexture = drawTextureCfg.Value;
			upscaler.flipVertical = flipCfg.Value;
			upscaler.opaqueMat = (opaqueMatCfg.Value ? opaqueMat : null);
			upscaler.cam.clearFlags = (CameraClearFlags)(clearBackbufferCfg.Value ? 2 : 4);
			((Behaviour)upscaler.cam).enabled = true;
		}

		private Texture2D GetTestTexture()
		{
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)testTex == (Object)null)
			{
				testTex = new Texture2D(64, 36, (TextureFormat)4, false)
				{
					name = "InternalResolutionDownscaling_TestPattern",
					wrapMode = (TextureWrapMode)1
				};
				Color32[] array = (Color32[])(object)new Color32[2304];
				for (int i = 0; i < 36; i++)
				{
					for (int j = 0; j < 64; j++)
					{
						array[i * 64 + j] = ((((j + i) & 1) == 0) ? new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, byte.MaxValue) : new Color32(byte.MaxValue, (byte)0, (byte)0, byte.MaxValue));
					}
				}
				testTex.SetPixels32(array);
				testTex.Apply(false);
			}
			((Texture)testTex).filterMode = filterCfg.Value;
			return testTex;
		}

		private void ReleaseTexture()
		{
			foreach (KeyValuePair<CameraRigController, RigState> state in states)
			{
				Camera sceneCam = state.Value.sceneCam;
				if (Object.op_Implicit((Object)(object)sceneCam) && (Object)(object)sceneCam.targetTexture == (Object)(object)rt)
				{
					sceneCam.targetTexture = null;
				}
			}
			if (Object.op_Implicit((Object)(object)upscaler))
			{
				upscaler.source = null;
			}
			if ((Object)(object)rt != (Object)null)
			{
				rt.Release();
				Object.Destroy((Object)(object)rt);
				rt = null;
			}
		}

		private void SyncRigs()
		{
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Invalid comparison between Unknown and I4
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Invalid comparison between Unknown and I4
			deadRigs.Clear();
			foreach (KeyValuePair<CameraRigController, RigState> state in states)
			{
				if (!Object.op_Implicit((Object)(object)state.Key) || !Object.op_Implicit((Object)(object)state.Value.sceneCam))
				{
					deadRigs.Add(state.Key);
				}
			}
			foreach (CameraRigController deadRig in deadRigs)
			{
				states.Remove(deadRig);
			}
			foreach (CameraRigController readOnlyInstances in CameraRigController.readOnlyInstancesList)
			{
				if (Object.op_Implicit((Object)(object)readOnlyInstances) && Object.op_Implicit((Object)(object)readOnlyInstances.sceneCam) && !states.ContainsKey(readOnlyInstances) && !((Object)(object)readOnlyInstances.sceneCam.targetTexture != (Object)null))
				{
					RigState rigState = new RigState
					{
						sceneCam = readOnlyInstances.sceneCam,
						uiCam = readOnlyInstances.uiCam,
						originalSceneDepth = readOnlyInstances.sceneCam.depth
					};
					readOnlyInstances.sceneCam.depth = -100f;
					if (Object.op_Implicit((Object)(object)rigState.uiCam) && ((int)rigState.uiCam.clearFlags == 1 || (int)rigState.uiCam.clearFlags == 2))
					{
						rigState.originalUiClear = rigState.uiCam.clearFlags;
						rigState.uiCam.clearFlags = (CameraClearFlags)3;
						rigState.uiClearChanged = true;
					}
					states[readOnlyInstances] = rigState;
				}
			}
		}

		internal void ReleaseTargets()
		{
			if (!isActive || !releaseCfg.Value)
			{
				return;
			}
			foreach (KeyValuePair<CameraRigController, RigState> state in states)
			{
				Camera sceneCam = state.Value.sceneCam;
				if (Object.op_Implicit((Object)(object)sceneCam) && (Object)(object)sceneCam.targetTexture == (Object)(object)rt)
				{
					sceneCam.targetTexture = null;
				}
			}
		}

		internal void AssignTargets()
		{
			if (!isActive || (Object)(object)rt == (Object)null)
			{
				return;
			}
			foreach (KeyValuePair<CameraRigController, RigState> state in states)
			{
				Camera sceneCam = state.Value.sceneCam;
				if (Object.op_Implicit((Object)(object)sceneCam) && (Object)(object)sceneCam.targetTexture != (Object)(object)rt)
				{
					sceneCam.targetTexture = rt;
				}
			}
		}

		private void Deactivate()
		{
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			isActive = false;
			RestoreDamageNumbers();
			RestorePrices();
			foreach (KeyValuePair<CameraRigController, RigState> state in states)
			{
				RigState value = state.Value;
				if (Object.op_Implicit((Object)(object)value.sceneCam))
				{
					value.sceneCam.targetTexture = null;
					value.sceneCam.depth = value.originalSceneDepth;
				}
				if (Object.op_Implicit((Object)(object)value.uiCam) && value.uiClearChanged)
				{
					value.uiCam.clearFlags = value.originalUiClear;
				}
			}
			states.Clear();
			ReleaseTexture();
			if (Object.op_Implicit((Object)(object)upscaler) && Object.op_Implicit((Object)(object)upscaler.cam))
			{
				((Behaviour)upscaler.cam).enabled = false;
			}
		}
	}
	internal static class WorldToScreenFix
	{
		[ThreadStatic]
		private static int depth;

		public static void Prefix()
		{
			depth++;
		}

		public static void Postfix(Camera __instance, ref Vector3 __result)
		{
			if (--depth <= 0)
			{
				if (depth < 0)
				{
					depth = 0;
				}
				InternalResolutionDownscalingPlugin instance = InternalResolutionDownscalingPlugin.Instance;
				if ((Object)(object)instance != (Object)null && instance.TryGetProjectionFactor(__instance, out var fx, out var fy))
				{
					__result.x *= fx;
					__result.y *= fy;
				}
			}
		}
	}
	internal static class HologramHook
	{
		public static void Postfix(object __instance)
		{
			InternalResolutionDownscalingPlugin instance = InternalResolutionDownscalingPlugin.Instance;
			if ((Object)(object)instance != (Object)null)
			{
				instance.OnHologramSeen(__instance);
			}
		}
	}
	[DefaultExecutionOrder(-32000)]
	public class TargetGateEarly : MonoBehaviour
	{
		internal InternalResolutionDownscalingPlugin plugin;

		private void Update()
		{
			Run();
		}

		private void LateUpdate()
		{
			Run();
		}

		private void Run()
		{
			if (Object.op_Implicit((Object)(object)plugin))
			{
				plugin.ReleaseTargets();
			}
		}
	}
	[DefaultExecutionOrder(32000)]
	public class TargetGateLate : MonoBehaviour
	{
		internal InternalResolutionDownscalingPlugin plugin;

		private void LateUpdate()
		{
			if (Object.op_Implicit((Object)(object)plugin))
			{
				plugin.AssignTargets();
			}
		}
	}
	public class Upscaler : MonoBehaviour
	{
		public Camera cam;

		public Texture source;

		public bool useDrawTexture;

		public bool flipVertical = true;

		public Material opaqueMat;

		private void OnPostRender()
		{
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)source == (Object)null)
			{
				return;
			}
			Texture obj = source;
			RenderTexture val = (RenderTexture)(object)((obj is RenderTexture) ? obj : null);
			if ((Object)(object)val != (Object)null && !val.IsCreated())
			{
				return;
			}
			if (!useDrawTexture)
			{
				Graphics.Blit(source, (RenderTexture)null);
				return;
			}
			GL.PushMatrix();
			if (flipVertical)
			{
				GL.LoadPixelMatrix(0f, (float)Screen.width, (float)Screen.height, 0f);
			}
			else
			{
				GL.LoadPixelMatrix(0f, (float)Screen.width, 0f, (float)Screen.height);
			}
			Graphics.DrawTexture(new Rect(0f, 0f, (float)Screen.width, (float)Screen.height), source, opaqueMat);
			GL.PopMatrix();
		}
	}
	internal static class RiskOfOptionsCompat
	{
		[MethodImpl(MethodImplOptions.NoInlining)]
		public static void Register(ConfigEntry<bool> enabled, ConfigEntry<float> scale, ConfigEntry<bool> customRes, ConfigEntry<int> customWidth, ConfigEntry<int> customHeight, ConfigEntry<int> pausedFps, ConfigEntry<bool> clearBackbuffer, ConfigEntry<bool> opaqueMat, ConfigEntry<bool> noAlpha, ConfigEntry<FilterMode> filter, ConfigEntry<bool> exclusiveFullscreen, ConfigEntry<bool> damageNumbers, ConfigEntry<bool> prices, ConfigEntry<bool> drawTexture, ConfigEntry<bool> testPattern, ConfigEntry<bool> flip, ConfigEntry<bool> releaseTarget, ConfigEntry<bool> overlayCamera, ConfigEntry<bool> overlayForward, ConfigEntry<bool> priceOcclusion, ConfigEntry<float> priceBrightness, ConfigEntry<KeyboardShortcut> increaseKey, ConfigEntry<KeyboardShortcut> decreaseKey)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Expected O, but got Unknown
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Expected O, but got Unknown
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Expected O, but got Unknown
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Expected O, but got Unknown
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Expected O, but got Unknown
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Expected O, but got Unknown
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Expected O, but got Unknown
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Expected O, but got Unknown
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Expected O, but got Unknown
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Expected O, but got Unknown
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Expected O, but got Unknown
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Expected O, but got Unknown
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Expected O, but got Unknown
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Expected O, but got Unknown
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Expected O, but got Unknown
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Expected O, but got Unknown
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Expected O, but got Unknown
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Expected O, but got Unknown
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Expected O, but got Unknown
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Expected O, but got Unknown
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Expected O, but got Unknown
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_0180: Expected O, but got Unknown
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Expected O, but got Unknown
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Expected O, but got Unknown
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Expected O, but got Unknown
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Expected O, but got Unknown
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bc: Expected O, but got Unknown
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Expected O, but got Unknown
			ModSettingsManager.SetModDescription("Change the internal 3D render resolution without affecting the UI.");
			TrySetIcon();
			ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(enabled));
			ModSettingsManager.AddOption((BaseOption)new StepSliderOption(scale, new StepSliderConfig
			{
				min = 0.01f,
				max = 2f,
				increment = 0.01f,
				FormatString = "{0:0.00}x"
			}));
			ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(customRes));
			ModSettingsManager.AddOption((BaseOption)new IntSliderOption(customWidth, new IntSliderConfig
			{
				min = 16,
				max = 3840
			}));
			ModSettingsManager.AddOption((BaseOption)new IntSliderOption(customHeight, new IntSliderConfig
			{
				min = 16,
				max = 2160
			}));
			ModSettingsManager.AddOption((BaseOption)new IntSliderOption(pausedFps, new IntSliderConfig
			{
				min = 0,
				max = 500
			}));
			ModSettingsManager.AddOption((BaseOption)new ChoiceOption((ConfigEntryBase)(object)filter));
			ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(exclusiveFullscreen));
			ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(damageNumbers));
			ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(prices));
			ModSettingsManager.AddOption((BaseOption)new StepSliderOption(priceBrightness, new StepSliderConfig
			{
				min = 0.5f,
				max = 3f,
				increment = 0.05f,
				FormatString = "{0:0.00}x"
			}));
			ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(drawTexture));
			ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(testPattern));
			ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(flip));
			ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(clearBackbuffer));
			ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(opaqueMat));
			ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(noAlpha));
			ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(releaseTarget));
			ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(overlayCamera));
			ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(overlayForward));
			ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(priceOcclusion));
			ModSettingsManager.AddOption((BaseOption)new KeyBindOption(increaseKey));
			ModSettingsManager.AddOption((BaseOption)new KeyBindOption(decreaseKey));
		}

		private static void TrySetIcon()
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("InternalResolutionDownscaling.icon.png");
				if (stream != null)
				{
					byte[] array;
					using (MemoryStream memoryStream = new MemoryStream())
					{
						stream.CopyTo(memoryStream);
						array = memoryStream.ToArray();
					}
					Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
					if (ImageConversion.LoadImage(val, array))
					{
						ModSettingsManager.SetModIcon(Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f)));
					}
				}
			}
			catch
			{
			}
		}
	}
}