Decompiled source of LethalKuchClient v2.5.0

LethalKuchClient.dll

Decompiled 5 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using LethalKuchQOL.Features;
using LethalKuchQOL.Lobby;
using LethalKuchQOL.UI;
using Microsoft.CodeAnalysis;
using TMPro;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.InputSystem.Utilities;
using UnityEngine.Rendering;
using UnityEngine.Rendering.HighDefinition;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyVersion("0.0.0.0")]
[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 LethalKuchQOL
{
	public static class Cfg
	{
		public static ConfigEntry<bool> SlotHotkeys;

		public static ConfigEntry<bool> FlashlightToggle;

		public static ConfigEntry<string> KeySlot1;

		public static ConfigEntry<string> KeySlot2;

		public static ConfigEntry<string> KeySlot3;

		public static ConfigEntry<string> KeySlot4;

		public static ConfigEntry<string> KeyFlashlight;

		public static ConfigEntry<string> KeyMenu;

		public static ConfigEntry<bool> ControlTips;

		public static ConfigEntry<bool> HoverTips;

		public static ConfigEntry<bool> VotingTips;

		public static ConfigEntry<bool> BuildModeTips;

		public static ConfigEntry<bool> DisableOutline;

		public static ConfigEntry<bool> DisableFog;

		public static ConfigEntry<bool> DisableHelmet;

		public static ConfigEntry<bool> DisableHud;

		public static ConfigEntry<bool> GraphicsEnabled;

		public static ConfigEntry<float> ResolutionScale;

		public static ConfigEntry<float> LodBias;

		public static ConfigEntry<int> AntiAliasing;

		public static ConfigEntry<int> TextureQuality;

		public static ConfigEntry<int> Anisotropic;

		public static ConfigEntry<int> FovOffset;

		public static ConfigEntry<bool> SellCommands;

		public static ConfigEntry<bool> SellShowItems;

		public static ConfigEntry<string> DontSellList;

		public static ConfigEntry<int> AmbientFogMode;

		public static ConfigEntry<int> InteriorFogMode;

		public static ConfigEntry<int> WeatherFogMode;

		public static ConfigEntry<float> AmbientFogDistance;

		public static ConfigEntry<float> InteriorFogThinness;

		public static ConfigEntry<float> WeatherFogThinness;

		public static ConfigEntry<float> InteriorFogAlpha;

		public static ConfigEntry<bool> InteriorFogCustomDensity;

		public static ConfigEntry<bool> InteriorFogCustomColor;

		public static ConfigEntry<bool> WeatherFogCustomDensity;

		public static ConfigEntry<string> InteriorFogColor;

		public static ConfigEntry<bool> NightVision;

		public static ConfigEntry<bool> ClearView;

		public static ConfigEntry<float> NightVisionStrength;

		public static void Bind(ConfigFile c)
		{
			//IL_020c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0216: Expected O, but got Unknown
			//IL_0238: Unknown result type (might be due to invalid IL or missing references)
			//IL_0242: Expected O, but got Unknown
			//IL_0264: Unknown result type (might be due to invalid IL or missing references)
			//IL_026e: Expected O, but got Unknown
			//IL_029c: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a6: Expected O, but got Unknown
			//IL_02c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d2: Expected O, but got Unknown
			//IL_02f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0300: Expected O, but got Unknown
			//IL_0377: Unknown result type (might be due to invalid IL or missing references)
			//IL_0381: Expected O, but got Unknown
			//IL_03af: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b9: Expected O, but got Unknown
			//IL_03db: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e5: Expected O, but got Unknown
			//IL_042e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0438: Expected O, but got Unknown
			//IL_04a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_04aa: Expected O, but got Unknown
			//IL_04cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d6: Expected O, but got Unknown
			//IL_051f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0529: Expected O, but got Unknown
			//IL_0572: Unknown result type (might be due to invalid IL or missing references)
			//IL_057c: Expected O, but got Unknown
			SlotHotkeys = c.Bind<bool>("Controls", "SlotHotkeys", true, "Number keys jump straight to item slots.");
			FlashlightToggle = c.Bind<bool>("Controls", "FlashlightToggle", true, "Toggle a pocketed flashlight with a key.");
			KeySlot1 = c.Bind<string>("Keys", "Slot1", "Digit1", "Unity InputSystem Key name. Rebind in the F12 menu.");
			KeySlot2 = c.Bind<string>("Keys", "Slot2", "Digit2", "");
			KeySlot3 = c.Bind<string>("Keys", "Slot3", "Digit3", "");
			KeySlot4 = c.Bind<string>("Keys", "Slot4", "Digit4", "");
			KeyFlashlight = c.Bind<string>("Keys", "Flashlight", "F", "");
			KeyMenu = c.Bind<string>("Keys", "Menu", "F12", "Opens the LethalKuchClient menu.");
			ControlTips = c.Bind<bool>("ControlTips", "ControlTipLines", true, "Bottom-left control tips show your real binds.");
			HoverTips = c.Bind<bool>("ControlTips", "HoverPrompts", true, "Crosshair prompts (Grab : [E]) show your real binds.");
			VotingTips = c.Bind<bool>("ControlTips", "VotingTips", true, "Leave-early / spectator vote prompts show your real binds.");
			BuildModeTips = c.Bind<bool>("ControlTips", "BuildModeTip", true, "Ship build-mode prompt shows your real binds.");
			DisableOutline = c.Bind<bool>("Visuals", "DisableOutline", false, "Remove the item/player outline custom pass.");
			DisableFog = c.Bind<bool>("Visuals", "DisableFog", false, "Disable the main post-processing volume (fog, grain, etc.).");
			DisableHelmet = c.Bind<bool>("Visuals", "DisableHelmet", false, "Hide the helmet visor model.");
			DisableHud = c.Bind<bool>("Visuals", "DisableHud", false, "Hide inventory, sprint meter, battery, weight and quota HUD.");
			GraphicsEnabled = c.Bind<bool>("Graphics", "Enabled", true, "Apply the graphics settings below.");
			ResolutionScale = c.Bind<float>("Graphics", "ResolutionScale", 1f, new ConfigDescription("Internal render resolution multiplier. Vanilla is 1 (860x520).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 4f), Array.Empty<object>()));
			AntiAliasing = c.Bind<int>("Graphics", "AntiAliasing", 0, new ConfigDescription("0 None, 1 FXAA, 2 TAA, 3 SMAA.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 3), Array.Empty<object>()));
			TextureQuality = c.Bind<int>("Graphics", "TextureQuality", 0, new ConfigDescription("Mipmap limit. 0 full res, 3 lowest.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 3), Array.Empty<object>()));
			LodBias = c.Bind<float>("Graphics", "LodBias", 1f, new ConfigDescription("Level-of-detail bias. Higher keeps detail further away.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 4f), Array.Empty<object>()));
			Anisotropic = c.Bind<int>("Graphics", "Anisotropic", 0, new ConfigDescription("0 game default, 1 disable, 2 force on.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 2), Array.Empty<object>()));
			FovOffset = c.Bind<int>("Graphics", "FovOffset", 0, new ConfigDescription("Added to the camera field of view.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(-10, 30), Array.Empty<object>()));
			SellCommands = c.Bind<bool>("Selling", "Enabled", true, "Terminal commands: sell <amount>, sell quota, sell all.");
			SellShowItems = c.Bind<bool>("Selling", "ShowFoundItems", true, "List the items that will be sold before confirming.");
			DontSellList = c.Bind<string>("Selling", "DontSell", "", "Comma-separated item names never to auto-sell.");
			AmbientFogMode = c.Bind<int>("Fog", "AmbientMode", 0, new ConfigDescription("Moon-wide sky/atmosphere fog on global volumes. 0 vanilla, 1 off, 2 custom distance.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 2), Array.Empty<object>()));
			AmbientFogDistance = c.Bind<float>("Fog", "AmbientDistance", 2f, new ConfigDescription("Custom mode: multiplier on fog view distance.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.25f, 10f), Array.Empty<object>()));
			InteriorFogMode = c.Bind<int>("Fog", "InteriorMode", 0, new ConfigDescription("Facility fog. 0 vanilla (random chance), 1 off, 2 always on.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 2), Array.Empty<object>()));
			InteriorFogCustomDensity = c.Bind<bool>("Fog", "InteriorCustomDensity", false, "Override interior fog thinness.");
			InteriorFogThinness = c.Bind<float>("Fog", "InteriorThinness", 5f, new ConfigDescription("Interior fog mean free path. Higher = thinner. Vanilla ~5.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 40f), Array.Empty<object>()));
			InteriorFogCustomColor = c.Bind<bool>("Fog", "InteriorCustomColor", false, "Override interior fog colour.");
			InteriorFogColor = c.Bind<string>("Fog", "InteriorColor", "#261710", "Interior fog colour (hex).");
			InteriorFogAlpha = c.Bind<float>("Fog", "InteriorAlpha", 1f, new ConfigDescription("Interior fog opacity.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			WeatherFogMode = c.Bind<int>("Fog", "WeatherMode", 0, new ConfigDescription("Foggy-weather fog. 0 vanilla, 1 off.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 1), Array.Empty<object>()));
			WeatherFogCustomDensity = c.Bind<bool>("Fog", "WeatherCustomDensity", false, "Override foggy-weather thinness.");
			WeatherFogThinness = c.Bind<float>("Fog", "WeatherThinness", 10f, new ConfigDescription("Foggy weather mean free path. Higher = thinner.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 60f), Array.Empty<object>()));
			NightVision = c.Bind<bool>("Visuals", "NightVision", false, "See in the dark: adds a shadowless light that follows your view. Only you see it.");
			NightVisionStrength = c.Bind<float>("Visuals", "NightVisionLux", 5f, new ConfigDescription("Night vision brightness in lux.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 50f), Array.Empty<object>()));
			ClearView = c.Bind<bool>("Fog", "ClearView", false, "One switch: removes all fog (sky, interior, weather) and hides rain/storm/dust weather visuals. Overrides the fog modes.");
		}
	}
	[BepInPlugin("ishred.LethalKuchClient", "LethalKuchClient", "2.5.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public const string GUID = "ishred.LethalKuchClient";

		public const string NAME = "LethalKuchClient";

		public const string VERSION = "2.5.0";

		internal static ManualLogSource Log;

		internal static Plugin Instance;

		public static void Instance_SaveConfig()
		{
			Plugin instance = Instance;
			if (instance != null)
			{
				((BaseUnityPlugin)instance).Config.Save();
			}
		}

		private void Awake()
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: 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_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: 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_0095: Expected O, but got Unknown
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			Cfg.Bind(((BaseUnityPlugin)this).Config);
			Harmony val = new Harmony("ishred.LethalKuchClient");
			val.PatchAll(typeof(FlashlightToggle));
			val.PatchAll(typeof(ControlTips));
			val.PatchAll(typeof(GraphicsTweaks));
			val.PatchAll(typeof(SellCommands));
			val.PatchAll(typeof(FogControl.Patches));
			val.PatchAll(typeof(NightVision));
			GameObject val2 = new GameObject("LethalKuchClient");
			Object.DontDestroyOnLoad((Object)val2);
			((Object)val2).hideFlags = (HideFlags)61;
			val2.AddComponent<SlotHotkeys>();
			val2.AddComponent<Visuals>();
			val2.AddComponent<FogControl>();
			val2.AddComponent<NightVision>();
			val2.AddComponent<SettingsPanel>();
			Log.LogInfo((object)string.Format("{0} {1} loaded. Press {2} for the menu. Server mod installed: {3}", "LethalKuchClient", "2.5.0", KeyInput.Pretty(Cfg.KeyMenu.Value), LobbyBridge.Installed));
		}
	}
}
namespace LethalKuchQOL.UI
{
	public class SettingsPanel : MonoBehaviour
	{
		private static SettingsPanel inst;

		private int tab;

		private static readonly string[] Tabs = new string[6] { "Controls", "Visuals", "Fog", "Graphics", "Selling", "About" };

		private GUIStyle panel;

		private GUIStyle title;

		private GUIStyle tabOn;

		private GUIStyle tabOff;

		private GUIStyle label;

		private GUIStyle hint;

		private GUIStyle toggleOn;

		private GUIStyle toggleOff;

		private GUIStyle section;

		private GUIStyle keyOn;

		private GUIStyle keyOff;

		private Vector2 scroll;

		private Texture2D texPanel;

		private Texture2D texCard;

		private Texture2D texAccent;

		private Texture2D texDim;

		private Texture2D texTabOn;

		private Texture2D texTabOff;

		private bool styled;

		private CursorLockMode prevLock;

		private bool prevLookDisabled;

		private ConfigEntry<string> capturing;

		public static bool Open { get; private set; }

		public static void Toggle()
		{
			if ((Object)(object)inst != (Object)null)
			{
				inst.SetOpen(!Open);
			}
		}

		private void Awake()
		{
			inst = this;
		}

		private unsafe void Update()
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Invalid comparison between Unknown and I4
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Invalid comparison between Unknown and I4
			if (capturing != null)
			{
				Key val = KeyInput.AnyPressed();
				if ((int)val != 0)
				{
					if ((int)val != 60)
					{
						capturing.Value = (((int)val == 65) ? "None" : ((object)(*(Key*)(&val))/*cast due to .constrained prefix*/).ToString());
					}
					capturing = null;
				}
			}
			else if (KeyInput.Pressed(Cfg.KeyMenu))
			{
				Toggle();
			}
		}

		private void SetOpen(bool open)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: 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)
			if (open == Open)
			{
				return;
			}
			Open = open;
			PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController;
			if (open)
			{
				prevLock = Cursor.lockState;
				Cursor.lockState = (CursorLockMode)0;
				Cursor.visible = true;
				if ((Object)(object)val != (Object)null)
				{
					prevLookDisabled = val.disableLookInput;
					val.disableLookInput = true;
				}
				return;
			}
			if ((Object)(object)val != (Object)null)
			{
				val.disableLookInput = prevLookDisabled;
			}
			if ((Object)(object)val != (Object)null && !val.quickMenuManager.isMenuOpen && !val.inTerminalMenu)
			{
				Cursor.lockState = (CursorLockMode)1;
				Cursor.visible = false;
			}
			else
			{
				Cursor.lockState = prevLock;
			}
			Plugin.Instance_SaveConfig();
		}

		private static Texture2D Solid(Color c)
		{
			//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_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			Texture2D val = new Texture2D(1, 1);
			val.SetPixel(0, 0, c);
			val.Apply();
			return val;
		}

		private void Style()
		{
			//IL_0025: 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_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Expected O, but got Unknown
			//IL_0121: Expected O, but got Unknown
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: 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_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Expected O, but got Unknown
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: 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_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: 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_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Expected O, but got Unknown
			//IL_01b7: Expected O, but got Unknown
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fa: Expected O, but got Unknown
			//IL_0205: Unknown result type (might be due to invalid IL or missing references)
			//IL_020a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0212: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			//IL_0231: Unknown result type (might be due to invalid IL or missing references)
			//IL_023d: Expected O, but got Unknown
			//IL_0248: Unknown result type (might be due to invalid IL or missing references)
			//IL_024d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0255: Unknown result type (might be due to invalid IL or missing references)
			//IL_025c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0267: Unknown result type (might be due to invalid IL or missing references)
			//IL_0278: Unknown result type (might be due to invalid IL or missing references)
			//IL_028d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0297: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02dd: Expected O, but got Unknown
			//IL_02e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0301: Unknown result type (might be due to invalid IL or missing references)
			//IL_0316: Unknown result type (might be due to invalid IL or missing references)
			//IL_0320: Unknown result type (might be due to invalid IL or missing references)
			//IL_0331: Unknown result type (might be due to invalid IL or missing references)
			//IL_0337: Unknown result type (might be due to invalid IL or missing references)
			//IL_0346: Expected O, but got Unknown
			//IL_0351: Unknown result type (might be due to invalid IL or missing references)
			//IL_0356: Unknown result type (might be due to invalid IL or missing references)
			//IL_0361: Unknown result type (might be due to invalid IL or missing references)
			//IL_036c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0374: Unknown result type (might be due to invalid IL or missing references)
			//IL_037b: Unknown result type (might be due to invalid IL or missing references)
			//IL_038c: 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_039c: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d3: Expected O, but got Unknown
			//IL_03da: Unknown result type (might be due to invalid IL or missing references)
			//IL_03df: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0405: Unknown result type (might be due to invalid IL or missing references)
			//IL_040f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0420: Unknown result type (might be due to invalid IL or missing references)
			//IL_0426: Unknown result type (might be due to invalid IL or missing references)
			//IL_0430: Unknown result type (might be due to invalid IL or missing references)
			//IL_0446: Expected O, but got Unknown
			//IL_044d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0452: Unknown result type (might be due to invalid IL or missing references)
			//IL_045d: Unknown result type (might be due to invalid IL or missing references)
			//IL_046a: Expected O, but got Unknown
			//IL_0471: Unknown result type (might be due to invalid IL or missing references)
			//IL_0476: Unknown result type (might be due to invalid IL or missing references)
			//IL_0481: Unknown result type (might be due to invalid IL or missing references)
			//IL_048e: Expected O, but got Unknown
			if (!styled)
			{
				styled = true;
				texPanel = Solid(new Color(0.07f, 0.08f, 0.1f, 0.96f));
				texCard = Solid(new Color(0.12f, 0.13f, 0.16f, 1f));
				texAccent = Solid(new Color(1f, 0.47f, 0.16f, 1f));
				texDim = Solid(new Color(0.22f, 0.23f, 0.27f, 1f));
				texTabOn = Solid(new Color(0.18f, 0.19f, 0.23f, 1f));
				texTabOff = Solid(new Color(0.1f, 0.11f, 0.13f, 1f));
				GUIStyle val = new GUIStyle(GUI.skin.box);
				val.normal.background = texPanel;
				val.padding = new RectOffset(18, 18, 14, 14);
				panel = val;
				GUIStyle val2 = new GUIStyle(GUI.skin.label)
				{
					fontSize = 22,
					fontStyle = (FontStyle)1
				};
				val2.normal.textColor = new Color(1f, 0.55f, 0.25f);
				title = val2;
				GUIStyle val3 = new GUIStyle(GUI.skin.label)
				{
					fontSize = 13,
					fontStyle = (FontStyle)1
				};
				val3.normal.textColor = new Color(0.6f, 0.65f, 0.75f);
				val3.margin = new RectOffset(0, 0, 10, 2);
				section = val3;
				GUIStyle val4 = new GUIStyle(GUI.skin.label)
				{
					fontSize = 14
				};
				val4.normal.textColor = new Color(0.92f, 0.93f, 0.95f);
				val4.alignment = (TextAnchor)3;
				label = val4;
				GUIStyle val5 = new GUIStyle(GUI.skin.label)
				{
					fontSize = 11
				};
				val5.normal.textColor = new Color(0.55f, 0.58f, 0.65f);
				val5.wordWrap = true;
				hint = val5;
				GUIStyle val6 = new GUIStyle(GUI.skin.button)
				{
					fontSize = 14,
					fontStyle = (FontStyle)1,
					fixedHeight = 32f
				};
				val6.normal.background = texTabOn;
				val6.normal.textColor = new Color(1f, 0.6f, 0.3f);
				val6.hover.background = texTabOn;
				val6.hover.textColor = new Color(1f, 0.6f, 0.3f);
				val6.active.background = texTabOn;
				tabOn = val6;
				GUIStyle val7 = new GUIStyle(tabOn)
				{
					fontStyle = (FontStyle)0
				};
				val7.normal.background = texTabOff;
				val7.normal.textColor = new Color(0.7f, 0.72f, 0.78f);
				val7.hover.background = texTabOn;
				val7.hover.textColor = Color.white;
				tabOff = val7;
				GUIStyle val8 = new GUIStyle(GUI.skin.button)
				{
					fixedWidth = 54f,
					fixedHeight = 24f,
					fontSize = 11,
					fontStyle = (FontStyle)1
				};
				val8.normal.background = texAccent;
				val8.normal.textColor = Color.black;
				val8.hover.background = texAccent;
				val8.hover.textColor = Color.black;
				val8.active.background = texAccent;
				toggleOn = val8;
				GUIStyle val9 = new GUIStyle(toggleOn);
				val9.normal.background = texDim;
				val9.normal.textColor = new Color(0.8f, 0.8f, 0.85f);
				val9.hover.background = texDim;
				val9.hover.textColor = Color.white;
				val9.active.background = texDim;
				toggleOff = val9;
				keyOn = new GUIStyle(toggleOn)
				{
					fixedWidth = 130f,
					fontSize = 12
				};
				keyOff = new GUIStyle(toggleOff)
				{
					fixedWidth = 130f,
					fontSize = 12
				};
			}
		}

		private void OnGUI()
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			if (!Open)
			{
				return;
			}
			Style();
			float num = 600f;
			float num2 = 620f;
			Rect val = default(Rect);
			((Rect)(ref val))..ctor(((float)Screen.width - num) / 2f, ((float)Screen.height - num2) / 2f, num, num2);
			GUI.Box(val, GUIContent.none, panel);
			GUILayout.BeginArea(new Rect(((Rect)(ref val)).x + 18f, ((Rect)(ref val)).y + 14f, num - 36f, num2 - 28f));
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label("LethalKuchClient", title, Array.Empty<GUILayoutOption>());
			GUILayout.FlexibleSpace();
			GUILayout.Label("v2.5.0   " + KeyInput.Pretty(Cfg.KeyMenu.Value) + " to close", hint, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(140f) });
			GUILayout.EndHorizontal();
			GUILayout.Space(6f);
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			for (int i = 0; i < Tabs.Length; i++)
			{
				if (GUILayout.Button(Tabs[i], (i == tab) ? tabOn : tabOff, Array.Empty<GUILayoutOption>()))
				{
					if (tab != i)
					{
						scroll = Vector2.zero;
					}
					tab = i;
				}
			}
			GUILayout.EndHorizontal();
			GUILayout.Space(10f);
			scroll = GUILayout.BeginScrollView(scroll, false, false, Array.Empty<GUILayoutOption>());
			switch (tab)
			{
			case 0:
				Controls();
				break;
			case 1:
				VisualsTab();
				break;
			case 2:
				FogTab();
				break;
			case 3:
				GraphicsTab();
				break;
			case 4:
				Selling();
				break;
			default:
				About();
				break;
			}
			GUILayout.EndScrollView();
			GUILayout.EndArea();
		}

		private void Controls()
		{
			GUILayout.Label("HOTKEYS", section, Array.Empty<GUILayoutOption>());
			Toggle(Cfg.SlotHotkeys, "Item slot hotkeys", "Jump straight to a slot.");
			Toggle(Cfg.FlashlightToggle, "Flashlight toggle key", "Toggle a pocketed flashlight.");
			GUILayout.Label("KEYBINDS  (click, then press a key. Esc cancels, Backspace unbinds)", section, Array.Empty<GUILayoutOption>());
			KeyRow(Cfg.KeySlot1, "Item slot 1");
			KeyRow(Cfg.KeySlot2, "Item slot 2");
			KeyRow(Cfg.KeySlot3, "Item slot 3");
			KeyRow(Cfg.KeySlot4, "Item slot 4");
			KeyRow(Cfg.KeyFlashlight, "Flashlight");
			KeyRow(Cfg.KeyMenu, "This menu");
			GUILayout.Label("CONTROL TIPS", section, Array.Empty<GUILayoutOption>());
			Toggle(Cfg.ControlTips, "Control tip lines", "Bottom-left tips show your real binds.");
			Toggle(Cfg.HoverTips, "Hover prompts", "Crosshair prompts like Grab : [E].");
			Toggle(Cfg.VotingTips, "Vote prompts", "Leave-early and spectator vote prompts.");
			Toggle(Cfg.BuildModeTips, "Build mode prompt", "Confirm / Store keys in ship build mode.");
		}

		private void VisualsTab()
		{
			GUILayout.Label("POST-PROCESSING", section, Array.Empty<GUILayoutOption>());
			Toggle(Cfg.DisableOutline, "Disable outline pass", "Removes the item and player outline effect.");
			Toggle(Cfg.DisableFog, "Disable main post-processing volume", "Kills all VolumeMain effects at once. For fog alone, use the Fog tab.");
			GUILayout.Label("HUD", section, Array.Empty<GUILayoutOption>());
			Toggle(Cfg.DisableHelmet, "Hide helmet visor", "Removes the helmet model overlay.");
			Toggle(Cfg.DisableHud, "Hide HUD", "Inventory, sprint, battery, weight and quota.");
			GUILayout.Label("SEE IN THE DARK", section, Array.Empty<GUILayoutOption>());
			Toggle(Cfg.NightVision, "Night vision", "Lights up everything you look at, inside and outside. Only you see it.");
			if (Cfg.NightVision.Value)
			{
				SliderF(Cfg.NightVisionStrength, "Brightness", 0.5f, 50f, 0.5f, (float v) => $"{v:0.0} lux");
			}
		}

		private void FogTab()
		{
			Toggle(Cfg.ClearView, "CLEAR VIEW", "Removes all fog and weather visuals in one go. Overrides everything below.");
			if (Cfg.ClearView.Value)
			{
				return;
			}
			GUILayout.Label("AMBIENT / SKY FOG", section, Array.Empty<GUILayoutOption>());
			SliderI(Cfg.AmbientFogMode, "Mode", 0, 2, (int v) => (new string[3] { "Vanilla", "Off", "Custom" })[v]);
			if (Cfg.AmbientFogMode.Value == 2)
			{
				SliderF(Cfg.AmbientFogDistance, "View distance", 0.25f, 10f, 0.25f, (float v) => $"{v:0.00}x");
			}
			GUILayout.Label("INTERIOR FOG", section, Array.Empty<GUILayoutOption>());
			SliderI(Cfg.InteriorFogMode, "Mode", 0, 2, (int v) => (new string[3] { "Vanilla", "Off", "Always" })[v]);
			if (Cfg.InteriorFogMode.Value != 1)
			{
				Toggle(Cfg.InteriorFogCustomDensity, "Custom thinness", "Override how thick the facility fog is.");
				if (Cfg.InteriorFogCustomDensity.Value)
				{
					SliderF(Cfg.InteriorFogThinness, "Thinness", 1f, 40f, 1f, (float v) => $"{v:0}  (vanilla 5)");
				}
				Toggle(Cfg.InteriorFogCustomColor, "Custom colour", "Hex colour and opacity for the fog.");
				if (Cfg.InteriorFogCustomColor.Value)
				{
					GUILayout.BeginHorizontal(GUI.skin.box, Array.Empty<GUILayoutOption>());
					GUILayout.Label("Colour", label, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(170f) });
					string text = GUILayout.TextField(Cfg.InteriorFogColor.Value, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(100f) });
					if (text != Cfg.InteriorFogColor.Value)
					{
						Cfg.InteriorFogColor.Value = text;
					}
					GUILayout.EndHorizontal();
					SliderF(Cfg.InteriorFogAlpha, "Opacity", 0f, 1f, 0.05f, (float v) => $"{v:0.00}");
				}
			}
			GUILayout.Label("FOGGY WEATHER", section, Array.Empty<GUILayoutOption>());
			SliderI(Cfg.WeatherFogMode, "Mode", 0, 1, (int v) => (new string[2] { "Vanilla", "Off" })[v]);
			if (Cfg.WeatherFogMode.Value == 0)
			{
				Toggle(Cfg.WeatherFogCustomDensity, "Custom thinness", "Override the rolled fog density on foggy days.");
				if (Cfg.WeatherFogCustomDensity.Value)
				{
					SliderF(Cfg.WeatherFogThinness, "Thinness", 1f, 60f, 1f, (float v) => $"{v:0}");
				}
			}
			GUILayout.Space(4f);
			GUILayout.Label("Changes apply within a second. Ambient 'Off' skips status-effect volumes (poison, drunk, underwater) so those still work.", hint, Array.Empty<GUILayoutOption>());
		}

		private void GraphicsTab()
		{
			Toggle(Cfg.GraphicsEnabled, "Apply graphics tweaks", "Master switch for this tab.");
			GUILayout.Label("RENDERING", section, Array.Empty<GUILayoutOption>());
			int num = (int)(0u | (SliderF(Cfg.ResolutionScale, "Resolution scale", 0.5f, 4f, 0.25f, (float v) => $"{v:0.00}x  ({Mathf.RoundToInt(860f * v)}x{Mathf.RoundToInt(520f * v)})") ? 1u : 0u)) | (SliderI(Cfg.AntiAliasing, "Anti-aliasing", 0, 3, (int v) => (new string[4] { "None", "FXAA", "TAA", "SMAA" })[v]) ? 1 : 0);
			GUILayout.Label("QUALITY", section, Array.Empty<GUILayoutOption>());
			int num2 = (int)((uint)num | (SliderI(Cfg.TextureQuality, "Texture quality", 0, 3, (int v) => (new string[4] { "Full", "Half", "Quarter", "Eighth" })[v]) ? 1u : 0u) | (SliderF(Cfg.LodBias, "LOD bias", 0.5f, 4f, 0.25f, (float v) => $"{v:0.00}") ? 1u : 0u)) | (SliderI(Cfg.Anisotropic, "Anisotropic filtering", 0, 2, (int v) => (new string[3] { "Default", "Off", "Force on" })[v]) ? 1 : 0);
			GUILayout.Label("CAMERA", section, Array.Empty<GUILayoutOption>());
			if (((uint)num2 | (SliderI(Cfg.FovOffset, "FOV offset", -10, 30, (int v) => ((v >= 0) ? "+" : "") + v) ? 1u : 0u)) != 0)
			{
				GraphicsTweaks.MarkDirty();
			}
			GUILayout.Space(6f);
			GUILayout.Label("Resolution scale above 1 sharpens the image at a GPU cost. TAA smooths edges but can blur; SMAA is a good middle ground.", hint, Array.Empty<GUILayoutOption>());
		}

		private void Selling()
		{
			Toggle(Cfg.SellCommands, "Terminal sell commands", "sell <amount>, sell quota, sell all, sell list. Host only.");
			Toggle(Cfg.SellShowItems, "Show items before confirming", "Lists what will be sold.");
			GUILayout.Label("NEVER SELL (comma-separated item names)", section, Array.Empty<GUILayoutOption>());
			string text = GUILayout.TextField(Cfg.DontSellList.Value, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(26f) });
			if (text != Cfg.DontSellList.Value)
			{
				Cfg.DontSellList.Value = text;
			}
			GUILayout.Space(8f);
			GUILayout.Label("Type SELL in the ship terminal at The Company for a command list. Only the host can execute sells; anyone can use SELL LIST.", hint, Array.Empty<GUILayoutOption>());
		}

		private void About()
		{
			GUILayout.Label("LethalKuchClient combines item slot hotkeys, flashlight toggle, real-key control tips, post-processing and HUD toggles, graphics quality settings, and terminal sell commands into one client-side mod.", hint, Array.Empty<GUILayoutOption>());
			GUILayout.Space(8f);
			GUILayout.Label("Keybinds are set on the Controls tab. All options save to BepInEx/config/ishred.LethalKuchClient.cfg when this menu closes.", hint, Array.Empty<GUILayoutOption>());
		}

		private void Toggle(ConfigEntry<bool> e, string name, string desc)
		{
			GUILayout.BeginHorizontal(GUI.skin.box, Array.Empty<GUILayoutOption>());
			GUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
			GUILayout.Label(name, label, Array.Empty<GUILayoutOption>());
			GUILayout.Label(desc, hint, Array.Empty<GUILayoutOption>());
			GUILayout.EndVertical();
			GUILayout.FlexibleSpace();
			GUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
			GUILayout.Space(8f);
			if (GUILayout.Button(e.Value ? "ON" : "OFF", e.Value ? toggleOn : toggleOff, Array.Empty<GUILayoutOption>()))
			{
				e.Value = !e.Value;
			}
			GUILayout.EndVertical();
			GUILayout.EndHorizontal();
		}

		private void KeyRow(ConfigEntry<string> e, string name)
		{
			GUILayout.BeginHorizontal(GUI.skin.box, Array.Empty<GUILayoutOption>());
			GUILayout.Label(name, label, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(170f) });
			GUILayout.FlexibleSpace();
			bool flag = capturing == e;
			if (GUILayout.Button(flag ? "press a key..." : KeyInput.Pretty(e.Value), flag ? keyOn : keyOff, Array.Empty<GUILayoutOption>()))
			{
				capturing = (flag ? null : e);
			}
			GUILayout.EndHorizontal();
		}

		private bool SliderF(ConfigEntry<float> e, string name, float min, float max, float step, Func<float, string> fmt)
		{
			GUILayout.BeginHorizontal(GUI.skin.box, Array.Empty<GUILayoutOption>());
			GUILayout.Label(name, label, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(170f) });
			float num = GUILayout.HorizontalSlider(e.Value, min, max, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(200f) });
			num = Mathf.Round(num / step) * step;
			GUILayout.Label(fmt(num), label, Array.Empty<GUILayoutOption>());
			GUILayout.EndHorizontal();
			if (!Mathf.Approximately(num, e.Value))
			{
				e.Value = num;
				return true;
			}
			return false;
		}

		private bool SliderI(ConfigEntry<int> e, string name, int min, int max, Func<int, string> fmt)
		{
			GUILayout.BeginHorizontal(GUI.skin.box, Array.Empty<GUILayoutOption>());
			GUILayout.Label(name, label, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(170f) });
			int num = Mathf.RoundToInt(GUILayout.HorizontalSlider((float)e.Value, (float)min, (float)max, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(200f) }));
			GUILayout.Label(fmt(num), label, Array.Empty<GUILayoutOption>());
			GUILayout.EndHorizontal();
			if (num != e.Value)
			{
				e.Value = num;
				return true;
			}
			return false;
		}
	}
}
namespace LethalKuchQOL.Features
{
	[HarmonyPatch]
	public static class ControlTips
	{
		private enum Ctx
		{
			Line,
			Hover,
			Vote
		}

		private class Rule
		{
			public string Action;

			public string Kbm;

			public string Pad;

			public Rule(string a, string k, string p)
			{
				Action = a;
				Kbm = k;
				Pad = p;
			}
		}

		private static readonly Regex Token = new Regex("\\[\\s*([A-Za-z][A-Za-z0-9-]*)\\s*\\]", RegexOptions.Compiled);

		private static readonly Regex CtrlPath = new Regex("^<([A-Za-z0-9]+)>/([A-Za-z0-9/]+)$", RegexOptions.Compiled);

		private static readonly Regex BuildConfirm = new Regex("Confirm: \\[\\s*\\w+\\s*\\]", RegexOptions.Compiled);

		private static readonly Regex BuildStore = new Regex("Store: \\[\\s*\\w+\\s*\\]", RegexOptions.Compiled);

		private static readonly Rule ConfirmRule = new Rule("ConfirmBuildMode", "<Keyboard>/v", null);

		private static readonly Rule StoreRule = new Rule("Delete", "<Keyboard>/x", null);

		private static readonly Dictionary<string, Rule> LineRules = new Dictionary<string, Rule>
		{
			["G"] = new Rule("Discard", "<Keyboard>/g", "<Gamepad>/buttonEast"),
			["E"] = new Rule("QEItemInteract", "<Keyboard>/e", "<Gamepad>/dpad/up"),
			["Q"] = new Rule("QEItemInteract", "<Keyboard>/q", "<Gamepad>/dpad/down"),
			["LMB"] = new Rule("Use", "<Mouse>/leftButton", "<Gamepad>/rightTrigger"),
			["RMB"] = new Rule("ActivateItem", "<Mouse>/leftButton", "<Gamepad>/rightTrigger"),
			["TAB"] = new Rule("UseUtilitySlot", "<Keyboard>/tab", "<Gamepad>/leftShoulder"),
			["START"] = new Rule("OpenMenu", "<Keyboard>/escape", "<Gamepad>/start"),
			["R-TRIGGER"] = new Rule("PingScan", "<Mouse>/rightButton", "<Gamepad>/rightShoulder")
		};

		private static readonly Dictionary<string, Rule> HoverRules = new Dictionary<string, Rule>
		{
			["G"] = new Rule("Discard", "<Keyboard>/g", "<Gamepad>/buttonEast"),
			["E"] = new Rule("Interact", "<Keyboard>/e", "<Gamepad>/buttonWest"),
			["LMB"] = new Rule("Interact", "<Keyboard>/e", "<Gamepad>/buttonWest"),
			["RMB"] = new Rule("PingScan", "<Mouse>/rightButton", "<Gamepad>/rightShoulder"),
			["Q"] = new Rule("QEItemInteract", "<Keyboard>/q", "<Gamepad>/dpad/down"),
			["TAB"] = new Rule("UseUtilitySlot", "<Keyboard>/tab", "<Gamepad>/leftShoulder"),
			["START"] = new Rule("OpenMenu", "<Keyboard>/escape", "<Gamepad>/start"),
			["R-TRIGGER"] = new Rule("PingScan", "<Mouse>/rightButton", "<Gamepad>/rightShoulder")
		};

		private static readonly Dictionary<string, Rule> VoteRules = new Dictionary<string, Rule>
		{
			["RMB"] = new Rule("PingScan", "<Mouse>/rightButton", "<Gamepad>/rightShoulder"),
			["R-TRIGGER"] = new Rule("PingScan", "<Mouse>/rightButton", "<Gamepad>/rightShoulder")
		};

		private static readonly Dictionary<string, string> MouseNames = new Dictionary<string, string>
		{
			["leftButton"] = "LMB",
			["rightButton"] = "RMB",
			["middleButton"] = "MMB",
			["forwardButton"] = "Mouse4",
			["backButton"] = "Mouse5",
			["scroll/up"] = "Scroll Up",
			["scroll/down"] = "Scroll Down",
			["scroll/y"] = "Scroll"
		};

		private static readonly Dictionary<string, string> KeyNames = new Dictionary<string, string>
		{
			["tab"] = "TAB",
			["space"] = "SPACE",
			["escape"] = "ESC",
			["enter"] = "ENTER",
			["leftShift"] = "LSHIFT",
			["rightShift"] = "RSHIFT",
			["leftCtrl"] = "LCTRL",
			["rightCtrl"] = "RCTRL",
			["leftAlt"] = "LALT",
			["rightAlt"] = "RALT",
			["upArrow"] = "UP",
			["downArrow"] = "DOWN",
			["leftArrow"] = "LEFT",
			["rightArrow"] = "RIGHT",
			["slash"] = "/",
			["comma"] = ",",
			["period"] = ".",
			["semicolon"] = ";",
			["quote"] = "'",
			["backquote"] = "`",
			["minus"] = "-",
			["equals"] = "=",
			["leftBracket"] = "[",
			["rightBracket"] = "]",
			["backslash"] = "\\",
			["backspace"] = "BACKSPACE",
			["capsLock"] = "CAPS",
			["delete"] = "DEL",
			["home"] = "HOME",
			["end"] = "END",
			["pageUp"] = "PGUP",
			["pageDown"] = "PGDN",
			["insert"] = "INS"
		};

		private static readonly Dictionary<string, string> PadNames = new Dictionary<string, string>
		{
			["buttonSouth"] = "A",
			["buttonEast"] = "B",
			["buttonWest"] = "X",
			["buttonNorth"] = "Y",
			["dpad/up"] = "D-pad up",
			["dpad/down"] = "D-pad down",
			["dpad/left"] = "D-pad left",
			["dpad/right"] = "D-pad right",
			["rightTrigger"] = "R-Trigger",
			["leftTrigger"] = "L-Trigger",
			["rightShoulder"] = "R-shoulder",
			["leftShoulder"] = "L-shoulder",
			["start"] = "Start",
			["select"] = "Select",
			["leftStickPress"] = "L-stick",
			["rightStickPress"] = "R-stick"
		};

		private static bool Pad
		{
			get
			{
				if ((Object)(object)StartOfRound.Instance != (Object)null)
				{
					return StartOfRound.Instance.localPlayerUsingController;
				}
				return false;
			}
		}

		private static string Replace(string text, Ctx ctx)
		{
			if (string.IsNullOrEmpty(text) || text.IndexOf('[') < 0)
			{
				return text;
			}
			Dictionary<string, Rule> rules = ctx switch
			{
				Ctx.Vote => VoteRules, 
				Ctx.Hover => HoverRules, 
				_ => LineRules, 
			};
			bool pad = Pad;
			return Token.Replace(text, delegate(Match m)
			{
				if (!rules.TryGetValue(m.Groups[1].Value.ToUpperInvariant(), out var value))
				{
					return m.Value;
				}
				string text2 = Display(value, pad);
				return (text2 != null) ? ("[" + text2 + "]") : m.Value;
			});
		}

		private static string Display(Rule rule, bool pad)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: 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_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				InputActionAsset actions = InputSystem.actions;
				InputAction val = ((actions != null) ? actions.FindAction(rule.Action, false) : null);
				if (val == null)
				{
					return null;
				}
				string text = (pad ? rule.Pad : rule.Kbm);
				InputBinding? val2 = null;
				Enumerator<InputBinding> enumerator = val.bindings.GetEnumerator();
				try
				{
					while (enumerator.MoveNext())
					{
						InputBinding current = enumerator.Current;
						if (((InputBinding)(ref current)).isComposite)
						{
							continue;
						}
						string effectivePath = ((InputBinding)(ref current)).effectivePath;
						if (!string.IsNullOrEmpty(effectivePath) && !(effectivePath == "[Disabled]") && effectivePath.StartsWith("<Gamepad>", StringComparison.OrdinalIgnoreCase) == pad)
						{
							if (text != null && string.Equals(((InputBinding)(ref current)).path, text, StringComparison.OrdinalIgnoreCase))
							{
								val2 = current;
								break;
							}
							if (!val2.HasValue)
							{
								val2 = current;
							}
						}
					}
				}
				finally
				{
					((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose();
				}
				object result;
				if (!val2.HasValue)
				{
					result = null;
				}
				else
				{
					InputBinding value = val2.Value;
					result = Normalize(((InputBinding)(ref value)).effectivePath);
				}
				return (string)result;
			}
			catch
			{
				return null;
			}
		}

		private static string Normalize(string path)
		{
			if (string.IsNullOrEmpty(path))
			{
				return null;
			}
			Match match = CtrlPath.Match(path);
			if (match.Success)
			{
				string value = match.Groups[1].Value;
				string value2 = match.Groups[2].Value;
				switch (value)
				{
				case "Mouse":
				{
					if (!MouseNames.TryGetValue(value2, out var value5))
					{
						return null;
					}
					return value5;
				}
				case "Keyboard":
				{
					if (!KeyNames.TryGetValue(value2, out var value4))
					{
						if (value2.Length != 1)
						{
							return null;
						}
						return value2.ToUpperInvariant();
					}
					return value4;
				}
				case "Gamepad":
				{
					if (!PadNames.TryGetValue(value2, out var value3))
					{
						return null;
					}
					return value3;
				}
				}
			}
			string text = InputControlPath.ToHumanReadableString(path, (HumanReadableStringOptions)2, (InputControl)null);
			if (!string.IsNullOrWhiteSpace(text))
			{
				return text.Trim();
			}
			return null;
		}

		[HarmonyPatch(typeof(HUDManager), "ChangeControlTipMultiple")]
		[HarmonyPrefix]
		private static void TipMulti(ref string[] allLines)
		{
			if (Cfg.ControlTips.Value && allLines != null)
			{
				string[] array = (string[])allLines.Clone();
				for (int i = 0; i < array.Length; i++)
				{
					array[i] = Replace(array[i], Ctx.Line);
				}
				allLines = array;
			}
		}

		[HarmonyPatch(typeof(HUDManager), "ChangeControlTipMultiple")]
		[HarmonyPostfix]
		private static void TipMultiPost(bool holdingItem)
		{
			if (Cfg.ControlTips.Value && holdingItem)
			{
				TextMeshProUGUI[] array = HUDManager.Instance?.controlTipLines;
				if (array != null && array.Length != 0 && (Object)(object)array[0] != (Object)null)
				{
					((TMP_Text)array[0]).text = Replace(((TMP_Text)array[0]).text, Ctx.Line);
				}
			}
		}

		[HarmonyPatch(typeof(HUDManager), "ChangeControlTip")]
		[HarmonyPrefix]
		private static void Tip(ref string changeTo)
		{
			if (Cfg.ControlTips.Value && changeTo != null)
			{
				changeTo = Replace(changeTo, Ctx.Line);
			}
		}

		[HarmonyPatch(typeof(PlayerControllerB), "SetHoverTipAndCurrentInteractTrigger")]
		[HarmonyPostfix]
		private static void Hover(PlayerControllerB __instance)
		{
			if (Cfg.HoverTips.Value)
			{
				TextMeshProUGUI cursorTip = __instance.cursorTip;
				if ((Object)(object)cursorTip != (Object)null && !string.IsNullOrEmpty(((TMP_Text)cursorTip).text) && ((TMP_Text)cursorTip).text.IndexOf('[') >= 0)
				{
					((TMP_Text)cursorTip).text = Replace(((TMP_Text)cursorTip).text, Ctx.Hover);
				}
			}
		}

		[HarmonyPatch(typeof(HUDManager), "Update")]
		[HarmonyPostfix]
		private static void HudUpdate(HUDManager __instance)
		{
			if (Cfg.VotingTips.Value)
			{
				Fix(__instance.holdButtonToEndGameEarlyText, Ctx.Vote);
			}
		}

		[HarmonyPatch(typeof(HUDManager), "DisplaySpectatorVoteTip")]
		[HarmonyPostfix]
		private static void SpectatorTip(HUDManager __instance)
		{
			if (Cfg.VotingTips.Value)
			{
				Fix(__instance.spectatorTipText, Ctx.Vote);
			}
		}

		private static void Fix(TextMeshProUGUI t, Ctx c)
		{
			if (!((Object)(object)t == (Object)null) && !string.IsNullOrEmpty(((TMP_Text)t).text) && ((TMP_Text)t).text.IndexOf('[') >= 0)
			{
				string text = Replace(((TMP_Text)t).text, c);
				if (text != ((TMP_Text)t).text)
				{
					((TMP_Text)t).text = text;
				}
			}
		}

		[HarmonyPatch(typeof(ShipBuildModeManager), "CreateGhostObjectAndHighlight")]
		[HarmonyPostfix]
		private static void BuildTip()
		{
			if (!Cfg.BuildModeTips.Value || Pad)
			{
				return;
			}
			TextMeshProUGUI val = HUDManager.Instance?.buildModeControlTip;
			if (!((Object)(object)val == (Object)null) && !string.IsNullOrEmpty(((TMP_Text)val).text))
			{
				string text = ((TMP_Text)val).text;
				string text2 = Display(ConfirmRule, pad: false);
				if (text2 != null)
				{
					text = BuildConfirm.Replace(text, "Confirm: [" + text2 + "]");
				}
				string text3 = Display(StoreRule, pad: false);
				if (text3 != null)
				{
					text = BuildStore.Replace(text, "Store: [" + text3 + "]");
				}
				if (text != ((TMP_Text)val).text)
				{
					((TMP_Text)val).text = text;
				}
			}
		}

		[HarmonyPatch(typeof(IngamePlayerSettings), "UpdateGameToMatchSettings")]
		[HarmonyPostfix]
		private static void RefreshAfterRebind()
		{
			PlayerControllerB val = StartOfRound.Instance?.localPlayerController;
			if ((Object)(object)val != (Object)null && (Object)(object)val.currentlyHeldObjectServer != (Object)null)
			{
				val.currentlyHeldObjectServer.SetControlTipsForItem();
			}
		}
	}
	[HarmonyPatch]
	public static class FlashlightToggle
	{
		[HarmonyPatch(typeof(PlayerControllerB), "KillPlayer")]
		[HarmonyPostfix]
		private static void Clear(PlayerControllerB __instance)
		{
			__instance.pocketedFlashlight = null;
		}

		[HarmonyPatch(typeof(PlayerControllerB), "Update")]
		[HarmonyPostfix]
		private static void ReadInput(PlayerControllerB __instance)
		{
			if (!Cfg.FlashlightToggle.Value || ((!((NetworkBehaviour)__instance).IsOwner || !__instance.isPlayerControlled || (((NetworkBehaviour)__instance).IsServer && !__instance.isHostPlayerObject)) && !__instance.isTestingPlayer) || __instance.inTerminalMenu || __instance.isTypingChat || !Application.isFocused)
			{
				return;
			}
			if (__instance.currentlyHeldObjectServer is FlashlightItem && (Object)(object)__instance.currentlyHeldObjectServer != (Object)(object)__instance.pocketedFlashlight)
			{
				__instance.pocketedFlashlight = __instance.currentlyHeldObjectServer;
			}
			if (SettingsPanel.Open)
			{
				return;
			}
			GrabbableObject pocketedFlashlight = __instance.pocketedFlashlight;
			FlashlightItem val = (FlashlightItem)(object)((pocketedFlashlight is FlashlightItem) ? pocketedFlashlight : null);
			if (val == null || !((GrabbableObject)val).isHeld || !KeyInput.Pressed(Cfg.KeyFlashlight))
			{
				return;
			}
			try
			{
				((GrabbableObject)val).UseItemOnClient(true);
				if (!(__instance.currentlyHeldObjectServer is FlashlightItem))
				{
					((Behaviour)val.flashlightBulbGlow).enabled = false;
					((Behaviour)val.flashlightBulb).enabled = false;
					bool isBeingUsed = ((GrabbableObject)val).isBeingUsed;
					((Behaviour)__instance.helmetLight).enabled = isBeingUsed;
					val.usingPlayerHelmetLight = isBeingUsed;
					val.PocketFlashlightServerRpc(isBeingUsed);
				}
			}
			catch
			{
			}
		}
	}
	public class FogControl : MonoBehaviour
	{
		private class FogOrig
		{
			public bool active;

			public bool enabled;

			public bool overrideState;

			public float meanFreePath;
		}

		[HarmonyPatch]
		public static class Patches
		{
			[HarmonyPatch(typeof(TimeOfDay), "SetWeatherBasedOnVariables")]
			[HarmonyPostfix]
			private static void AfterWeather(TimeOfDay __instance)
			{
				//IL_0021: Unknown result type (might be due to invalid IL or missing references)
				//IL_0026: Unknown result type (might be due to invalid IL or missing references)
				//IL_003e: Unknown result type (might be due to invalid IL or missing references)
				//IL_003f: Unknown result type (might be due to invalid IL or missing references)
				if (!((Object)(object)__instance.foggyWeather == (Object)null) && Cfg.WeatherFogCustomDensity.Value)
				{
					LocalVolumetricFogArtistParameters parameters = __instance.foggyWeather.parameters;
					parameters.meanFreePath = Cfg.WeatherFogThinness.Value;
					__instance.foggyWeather.parameters = parameters;
				}
			}

			[HarmonyPatch(typeof(RoundManager), "RefreshEnemiesList")]
			[HarmonyPostfix]
			private static void AfterLevelLoad(RoundManager __instance)
			{
				if (!((Object)(object)__instance.indoorFog == (Object)null))
				{
					if (Cfg.ClearView.Value || Cfg.InteriorFogMode.Value == 1)
					{
						((Component)__instance.indoorFog).gameObject.SetActive(false);
					}
					else if (Cfg.InteriorFogMode.Value == 2)
					{
						((Component)__instance.indoorFog).gameObject.SetActive(true);
					}
				}
			}
		}

		private static readonly string[] StatusProfiles = new string[7] { "PoisonFilter", "DrunkFilter", "UnderwaterFilter", "FlashbangedFilter", "InsideFactorySkyVolume", "SeeingRedFilter", "InsanityVolume" };

		private readonly Dictionary<Fog, FogOrig> ambientOrig = new Dictionary<Fog, FogOrig>();

		private float indoorOrigPath = -1f;

		private float weatherOrigPath = -1f;

		private Color indoorOrigAlbedo;

		private Color weatherOrigAlbedo;

		private LocalVolumetricFog indoorRef;

		private LocalVolumetricFog weatherRef;

		private float t;

		private readonly List<Behaviour> hiddenFog = new List<Behaviour>();

		private readonly List<Renderer> hiddenParticles = new List<Renderer>();

		private void Update()
		{
			t += Time.unscaledDeltaTime;
			if (t < 1f)
			{
				return;
			}
			t = 0f;
			try
			{
				Ambient();
				Interior();
				Weather();
				WeatherVisuals();
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Fog apply: " + ex.Message));
			}
		}

		private void WeatherVisuals()
		{
			TimeOfDay instance = TimeOfDay.Instance;
			if (!Cfg.ClearView.Value || (Object)(object)instance == (Object)null || instance.effects == null)
			{
				foreach (Behaviour item in hiddenFog)
				{
					if ((Object)(object)item != (Object)null)
					{
						item.enabled = true;
					}
				}
				foreach (Renderer hiddenParticle in hiddenParticles)
				{
					if ((Object)(object)hiddenParticle != (Object)null)
					{
						hiddenParticle.enabled = true;
					}
				}
				hiddenFog.Clear();
				hiddenParticles.Clear();
				return;
			}
			WeatherEffect[] effects = instance.effects;
			foreach (WeatherEffect val in effects)
			{
				if ((Object)(object)val?.effectObject == (Object)null)
				{
					continue;
				}
				ParticleSystemRenderer[] componentsInChildren = val.effectObject.GetComponentsInChildren<ParticleSystemRenderer>(true);
				foreach (ParticleSystemRenderer val2 in componentsInChildren)
				{
					if (((Renderer)val2).enabled)
					{
						((Renderer)val2).enabled = false;
						hiddenParticles.Add((Renderer)(object)val2);
					}
				}
				LocalVolumetricFog[] componentsInChildren2 = val.effectObject.GetComponentsInChildren<LocalVolumetricFog>(true);
				foreach (LocalVolumetricFog val3 in componentsInChildren2)
				{
					if (((Behaviour)val3).enabled)
					{
						((Behaviour)val3).enabled = false;
						hiddenFog.Add((Behaviour)(object)val3);
					}
				}
			}
		}

		private void Ambient()
		{
			int num = (Cfg.ClearView.Value ? 1 : Cfg.AmbientFogMode.Value);
			Volume[] array = Object.FindObjectsOfType<Volume>();
			Fog val2 = default(Fog);
			foreach (Volume val in array)
			{
				if (!val.isGlobal || (Object)(object)val.sharedProfile == (Object)null)
				{
					continue;
				}
				string text = ((Object)val.sharedProfile).name ?? "";
				bool flag = false;
				string[] statusProfiles = StatusProfiles;
				foreach (string value in statusProfiles)
				{
					if (text.IndexOf(value, StringComparison.OrdinalIgnoreCase) >= 0)
					{
						flag = true;
						break;
					}
				}
				if (!flag && val.sharedProfile.TryGet<Fog>(ref val2))
				{
					if (!ambientOrig.TryGetValue(val2, out var value2))
					{
						Dictionary<Fog, FogOrig> dictionary = ambientOrig;
						Fog key = val2;
						FogOrig obj = new FogOrig
						{
							active = ((VolumeComponent)val2).active,
							enabled = ((VolumeParameter<bool>)(object)val2.enabled).value,
							overrideState = ((VolumeParameter)val2.enabled).overrideState,
							meanFreePath = ((VolumeParameter<float>)(object)val2.meanFreePath).value
						};
						value2 = obj;
						dictionary[key] = obj;
					}
					if (num == 1)
					{
						((VolumeComponent)val2).active = false;
						((VolumeParameter<bool>)(object)val2.enabled).value = false;
						((VolumeParameter)val2.enabled).overrideState = false;
					}
					else
					{
						((VolumeComponent)val2).active = value2.active;
						((VolumeParameter<bool>)(object)val2.enabled).value = value2.enabled;
						((VolumeParameter)val2.enabled).overrideState = value2.overrideState;
						((VolumeParameter<float>)(object)val2.meanFreePath).value = ((num == 2) ? (value2.meanFreePath * Cfg.AmbientFogDistance.Value) : value2.meanFreePath);
					}
				}
			}
		}

		private void Interior()
		{
			//IL_0052: 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_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: 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)
			RoundManager instance = RoundManager.Instance;
			if ((Object)(object)instance == (Object)null || (Object)(object)instance.indoorFog == (Object)null)
			{
				return;
			}
			LocalVolumetricFog indoorFog = instance.indoorFog;
			if ((Object)(object)indoorRef != (Object)(object)indoorFog)
			{
				indoorRef = indoorFog;
				indoorOrigPath = indoorFog.parameters.meanFreePath;
				indoorOrigAlbedo = indoorFog.parameters.albedo;
			}
			int num = (Cfg.ClearView.Value ? 1 : Cfg.InteriorFogMode.Value);
			switch (num)
			{
			case 1:
				if (((Component)indoorFog).gameObject.activeSelf)
				{
					((Component)indoorFog).gameObject.SetActive(false);
				}
				break;
			case 2:
				if (!((Component)indoorFog).gameObject.activeSelf)
				{
					((Component)indoorFog).gameObject.SetActive(true);
				}
				break;
			}
			if (num != 1)
			{
				LocalVolumetricFogArtistParameters parameters = indoorFog.parameters;
				parameters.meanFreePath = (Cfg.InteriorFogCustomDensity.Value ? Cfg.InteriorFogThinness.Value : indoorOrigPath);
				Color albedo = default(Color);
				if (Cfg.InteriorFogCustomColor.Value && ColorUtility.TryParseHtmlString(Cfg.InteriorFogColor.Value, ref albedo))
				{
					albedo.a = Cfg.InteriorFogAlpha.Value;
					parameters.albedo = albedo;
				}
				else
				{
					parameters.albedo = indoorOrigAlbedo;
				}
				indoorFog.parameters = parameters;
			}
		}

		private void Weather()
		{
			//IL_0026: 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_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: 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_0073: 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_00d3: Unknown result type (might be due to invalid IL or missing references)
			TimeOfDay instance = TimeOfDay.Instance;
			if ((Object)(object)instance == (Object)null || (Object)(object)instance.foggyWeather == (Object)null)
			{
				return;
			}
			LocalVolumetricFog foggyWeather = instance.foggyWeather;
			LocalVolumetricFogArtistParameters parameters = foggyWeather.parameters;
			if ((Object)(object)weatherRef != (Object)(object)foggyWeather || weatherOrigPath < 0f)
			{
				weatherRef = foggyWeather;
				weatherOrigPath = parameters.meanFreePath;
				weatherOrigAlbedo = parameters.albedo;
			}
			if (!Cfg.WeatherFogCustomDensity.Value)
			{
				weatherOrigPath = parameters.meanFreePath;
			}
			if ((Cfg.ClearView.Value ? 1 : Cfg.WeatherFogMode.Value) == 1)
			{
				if (((Component)foggyWeather).gameObject.activeSelf)
				{
					((Component)foggyWeather).gameObject.SetActive(false);
				}
				return;
			}
			if (Cfg.WeatherFogCustomDensity.Value)
			{
				parameters.meanFreePath = Cfg.WeatherFogThinness.Value;
			}
			foggyWeather.parameters = parameters;
		}
	}
	[HarmonyPatch]
	public static class GraphicsTweaks
	{
		private static RenderTexture original;

		private static RenderTexture scaled;

		private static bool dirty = true;

		private static readonly List<Camera> cameras = new List<Camera>();

		public static void MarkDirty()
		{
			dirty = true;
		}

		[HarmonyPatch(typeof(HUDManager), "Start")]
		[HarmonyPostfix]
		private static void OnHudStart()
		{
			dirty = true;
		}

		[HarmonyPatch(typeof(PlayerControllerB), "LateUpdate")]
		[HarmonyPostfix]
		private static void LateUpdate(PlayerControllerB __instance)
		{
			if (!Cfg.GraphicsEnabled.Value)
			{
				return;
			}
			PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController;
			if (!((Object)(object)val == (Object)null) && !((Object)(object)__instance != (Object)(object)val))
			{
				if (Cfg.FovOffset.Value != 0 && !val.inTerminalMenu && (Object)(object)val.gameplayCamera != (Object)null)
				{
					val.gameplayCamera.fieldOfView = Mathf.Lerp(val.gameplayCamera.fieldOfView, val.targetFOV + (float)Cfg.FovOffset.Value, 6f * Time.deltaTime);
				}
				if (dirty)
				{
					ApplyNow(val);
				}
			}
		}

		private static void ApplyNow(PlayerControllerB local)
		{
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Expected O, but got Unknown
			//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
			dirty = false;
			try
			{
				HUDManager instance = HUDManager.Instance;
				if ((Object)(object)instance == (Object)null || (Object)(object)instance.playerScreenTexture == (Object)null || (Object)(object)local.gameplayCamera == (Object)null)
				{
					return;
				}
				if ((Object)(object)original == (Object)null)
				{
					original = local.gameplayCamera.targetTexture;
				}
				if ((Object)(object)original == (Object)null)
				{
					return;
				}
				float value = Cfg.ResolutionScale.Value;
				RenderTexture val;
				if (Mathf.Approximately(value, 1f))
				{
					val = original;
				}
				else
				{
					if ((Object)(object)scaled != (Object)null)
					{
						scaled.Release();
						Object.Destroy((Object)(object)scaled);
					}
					RenderTextureDescriptor descriptor = original.descriptor;
					((RenderTextureDescriptor)(ref descriptor)).width = Mathf.RoundToInt((float)((Texture)original).width * value);
					((RenderTextureDescriptor)(ref descriptor)).height = Mathf.RoundToInt((float)((Texture)original).height * value);
					scaled = new RenderTexture(descriptor)
					{
						name = "KuchQOL_Screen",
						filterMode = (FilterMode)1
					};
					scaled.Create();
					val = scaled;
				}
				cameras.Clear();
				Camera[] array = Object.FindObjectsOfType<Camera>(true);
				foreach (Camera val2 in array)
				{
					if ((Object)(object)val2.targetTexture == (Object)(object)original || ((Object)(object)scaled != (Object)null && (Object)(object)val2.targetTexture == (Object)(object)scaled))
					{
						cameras.Add(val2);
					}
				}
				foreach (Camera camera in cameras)
				{
					camera.targetTexture = val;
					HDAdditionalCameraData component = ((Component)camera).GetComponent<HDAdditionalCameraData>();
					if ((Object)(object)component != (Object)null)
					{
						component.antialiasing = (AntialiasingMode)Cfg.AntiAliasing.Value;
					}
				}
				instance.playerScreenTexture.texture = (Texture)(object)val;
				QualitySettings.globalTextureMipmapLimit = Cfg.TextureQuality.Value;
				QualitySettings.lodBias = Cfg.LodBias.Value;
				if (Cfg.Anisotropic.Value == 1)
				{
					QualitySettings.anisotropicFiltering = (AnisotropicFiltering)0;
				}
				else if (Cfg.Anisotropic.Value == 2)
				{
					QualitySettings.anisotropicFiltering = (AnisotropicFiltering)2;
				}
				Plugin.Log.LogInfo((object)$"Graphics applied: {((Texture)val).width}x{((Texture)val).height}, AA {Cfg.AntiAliasing.Value}, tex {Cfg.TextureQuality.Value}, lod {Cfg.LodBias.Value}");
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Graphics apply failed: " + ex));
			}
		}
	}
	public static class KeyInput
	{
		private static readonly Dictionary<string, Key> cache = new Dictionary<string, Key>();

		public static Key Resolve(string name)
		{
			//IL_0026: 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_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			if (string.IsNullOrEmpty(name) || name == "None")
			{
				return (Key)0;
			}
			if (cache.TryGetValue(name, out var value))
			{
				return value;
			}
			value = (Key)(Enum.TryParse<Key>(name, ignoreCase: true, out Key result) ? ((int)result) : 0);
			cache[name] = value;
			return value;
		}

		public static bool Pressed(ConfigEntry<string> bind)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: 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_001b: Unknown result type (might be due to invalid IL or missing references)
			Keyboard current = Keyboard.current;
			if (current == null)
			{
				return false;
			}
			Key val = Resolve(bind.Value);
			if ((int)val != 0)
			{
				return ((ButtonControl)current[val]).wasPressedThisFrame;
			}
			return false;
		}

		public static Key AnyPressed()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: 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)
			Keyboard current = Keyboard.current;
			if (current != null && ((ButtonControl)current.anyKey).wasPressedThisFrame)
			{
				Enumerator<KeyControl> enumerator = current.allKeys.GetEnumerator();
				try
				{
					while (enumerator.MoveNext())
					{
						KeyControl current2 = enumerator.Current;
						if (((ButtonControl)current2).wasPressedThisFrame)
						{
							return current2.keyCode;
						}
					}
				}
				finally
				{
					((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose();
				}
				return (Key)0;
			}
			return (Key)0;
		}

		public unsafe static string Pretty(string name)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: 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)
			Key val = Resolve(name);
			if ((int)val == 0)
			{
				return "unbound";
			}
			string text = ((object)(*(Key*)(&val))/*cast due to .constrained prefix*/).ToString();
			if (text.StartsWith("Digit"))
			{
				return text.Substring(5);
			}
			if (text.StartsWith("Numpad"))
			{
				return "Num " + text.Substring(6);
			}
			return text;
		}
	}
	public static class LobbyBridge
	{
		public const string LobbyGuid = "ishred.LethalKuchServer";

		public static bool Installed => Chainloader.PluginInfos.ContainsKey("ishred.LethalKuchServer");

		public static bool Ready
		{
			get
			{
				if (Installed)
				{
					return ReadyImpl();
				}
				return false;
			}
		}

		public static bool ClientSellAllowed
		{
			get
			{
				if (Ready)
				{
					return ClientSellAllowedImpl();
				}
				return true;
			}
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static bool ReadyImpl()
		{
			return (Object)(object)KuchNet.Instance != (Object)null;
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		private static bool ClientSellAllowedImpl()
		{
			return KuchNet.Instance.AllowClientSell.Value;
		}

		[MethodImpl(MethodImplOptions.NoInlining)]
		public static void RequestSell(List<GrabbableObject> items)
		{
			KuchNet.Instance.RequestSell(items);
		}
	}
	public class NightVision : MonoBehaviour
	{
		private Light light;

		private HDAdditionalLightData hd;

		private void LateUpdate()
		{
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			int num;
			object obj;
			if (Cfg.NightVision.Value && (Object)(object)StartOfRound.Instance != (Object)null)
			{
				num = (((Object)(object)GameNetworkManager.Instance?.localPlayerController != (Object)null) ? 1 : 0);
				if (num != 0)
				{
					obj = StartOfRound.Instance.activeCamera;
					goto IL_0043;
				}
			}
			else
			{
				num = 0;
			}
			obj = null;
			goto IL_0043;
			IL_0043:
			Camera val = (Camera)obj;
			if (num == 0 || (Object)(object)val == (Object)null)
			{
				if ((Object)(object)light != (Object)null && ((Behaviour)light).enabled)
				{
					((Behaviour)light).enabled = false;
				}
				return;
			}
			if ((Object)(object)light == (Object)null)
			{
				Create();
			}
			((Component)light).transform.rotation = ((Component)val).transform.rotation;
			float value = Cfg.NightVisionStrength.Value;
			if (!Mathf.Approximately(hd.intensity, value))
			{
				hd.SetIntensity(value, (LightUnit)2);
			}
			if (!((Behaviour)light).enabled)
			{
				((Behaviour)light).enabled = true;
			}
		}

		private void Create()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Expected O, but got Unknown
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("KuchNightVision");
			Object.DontDestroyOnLoad((Object)(object)val);
			((Object)val).hideFlags = (HideFlags)61;
			light = val.AddComponent<Light>();
			light.type = (LightType)1;
			light.shadows = (LightShadows)0;
			light.color = new Color(0.92f, 0.97f, 0.92f);
			hd = val.GetComponent<HDAdditionalLightData>() ?? val.AddComponent<HDAdditionalLightData>();
			hd.affectsVolumetric = false;
			hd.EnableShadows(false);
			hd.SetIntensity(Cfg.NightVisionStrength.Value, (LightUnit)2);
			Plugin.Log.LogInfo((object)"Night vision light created.");
		}

		[HarmonyPatch(typeof(PlayerControllerB), "SetNightVisionEnabled")]
		[HarmonyPostfix]
		private static void After(PlayerControllerB __instance, bool isNotLocalClient)
		{
			if (Cfg.NightVision.Value && !((Object)(object)__instance.nightVision == (Object)null))
			{
				PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController;
				if ((Object)(object)val != (Object)null && (isNotLocalClient ? ((Object)(object)val.spectatedPlayerScript == (Object)(object)__instance) : ((Object)(object)__instance == (Object)(object)val)))
				{
					((Behaviour)__instance.nightVision).enabled = true;
				}
			}
		}
	}
	[HarmonyPatch]
	public static class SellCommands
	{
		private static List<GrabbableObject> pending;

		private static float Rate => StartOfRound.Instance.companyBuyingRate;

		private static string[] DontSell => (from s in Cfg.DontSellList.Value.Split(',')
			select s.Trim() into s
			where s.Length > 0
			select s).ToArray();

		private static TerminalNode Node(string msg)
		{
			TerminalNode obj = ScriptableObject.CreateInstance<TerminalNode>();
			obj.displayText = msg;
			obj.clearPreviousText = true;
			obj.maxCharactersToType = 50;
			return obj;
		}

		private static int Real(int v)
		{
			return (int)((float)v * Rate);
		}

		[HarmonyPatch(typeof(Terminal), "QuitTerminal")]
		[HarmonyPostfix]
		private static void OnQuit()
		{
			pending = null;
		}

		[HarmonyPatch(typeof(Terminal), "ParsePlayerSentence")]
		[HarmonyPrefix]
		[HarmonyPriority(800)]
		private static bool Parse(Terminal __instance, ref TerminalNode __result)
		{
			if (!Cfg.SellCommands.Value)
			{
				return true;
			}
			string text = __instance.screenText.text;
			string[] array = text.Substring(Mathf.Max(0, text.Length - __instance.textAdded)).Trim().Split(' ', StringSplitOptions.RemoveEmptyEntries);
			if (array.Length == 0)
			{
				return true;
			}
			if (pending != null)
			{
				string value = array[0].ToLowerInvariant();
				if ("confirm".StartsWith(value))
				{
					__result = Confirm();
					return false;
				}
				if ("deny".StartsWith(value))
				{
					pending = null;
					__result = Node("Sell request cancelled.\n\n");
					return false;
				}
				pending = null;
				return true;
			}
			if (!array[0].Equals("sell", StringComparison.OrdinalIgnoreCase))
			{
				return true;
			}
			try
			{
				__result = Run(array.Skip(1).ToArray());
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)ex);
				__result = Node("Sell command failed: " + ex.Message + "\n\n");
			}
			return false;
		}

		private static TerminalNode Run(string[] a)
		{
			if (a.Length == 0 || a[0].Equals("help", StringComparison.OrdinalIgnoreCase))
			{
				return Node("LethalKuchClient selling\n\n>SELL <amount>\nSell scrap worth at least <amount>.\n\n>SELL QUOTA\nSell just enough to meet the quota.\n\n>SELL ALL\nSell every scrap item on the ship.\n\n>SELL LIST\nShow sellable scrap on the ship.\n\n");
			}
			StartOfRound instance = StartOfRound.Instance;
			if ((Object)(object)instance == (Object)null || instance.inShipPhase)
			{
				return Node("You must be landed at The Company to sell.\n\n");
			}
			if ((Object)(object)Object.FindObjectOfType<DepositItemsDesk>() == (Object)null)
			{
				return Node("You cannot sell on this moon.\n\n");
			}
			List<GrabbableObject> list = ShipScrap();
			if (a[0].Equals("list", StringComparison.OrdinalIgnoreCase))
			{
				return Node($"Sellable scrap on ship: {list.Count} items, ${Real(list.Sum((GrabbableObject g) => g.scrapValue))} at {(int)(Rate * 100f)}%\n\n{ItemList(list)}\n\n");
			}
			if (!NetworkManager.Singleton.IsHost && !LobbyBridge.Ready)
			{
				return Node(LobbyBridge.Installed ? "Lobby sync is not active (the host needs LethalKuchServer too). Only the host can sell right now.\n\n" : "Only the host can sell. For everyone to sell, host and clients install LethalKuchServer.\n\n");
			}
			if (!NetworkManager.Singleton.IsHost && !LobbyBridge.ClientSellAllowed)
			{
				return Node("The host has disabled client selling (Lobby panel, F9).\n\n");
			}
			if (list.Count == 0)
			{
				return Node("No sellable scrap found on the ship.\n\n");
			}
			int result;
			if (a[0].Equals("all", StringComparison.OrdinalIgnoreCase))
			{
				result = int.MaxValue;
			}
			else if (a[0].Equals("quota", StringComparison.OrdinalIgnoreCase))
			{
				result = TimeOfDay.Instance.profitQuota - TimeOfDay.Instance.quotaFulfilled;
				if (result <= 0)
				{
					return Node("Quota already fulfilled.\n\n");
				}
			}
			else if (!int.TryParse(a[0], out result) || result <= 0)
			{
				return Node("Usage: sell <amount> | sell quota | sell all | sell list\n\n");
			}
			List<GrabbableObject> list2 = ((result == int.MaxValue) ? list : Pick(list, result));
			int num = Real(list2.Sum((GrabbableObject g) => g.scrapValue));
			pending = list2;
			StringBuilder stringBuilder = new StringBuilder();
			string arg = ((result == int.MaxValue || num >= result) ? "green" : "red");
			stringBuilder.AppendLine($"Found {list2.Count} items worth <color={arg}>${num}</color>");
			if (result != int.MaxValue)
			{
				stringBuilder.AppendLine($"Requested: ${result}");
			}
			stringBuilder.AppendLine($"The Company is buying at {(int)(Rate * 100f)}%\n");
			if (Cfg.SellShowItems.Value)
			{
				stringBuilder.AppendLine(ItemList(list2) + "\n");
			}
			stringBuilder.AppendLine("Please CONFIRM or DENY.\n\n");
			return Node(stringBuilder.ToString());
		}

		private static TerminalNode Confirm()
		{
			List<GrabbableObject> list = pending;
			pending = null;
			DepositItemsDesk val = Object.FindObjectOfType<DepositItemsDesk>();
			if ((Object)(object)val == (Object)null || list == null)
			{
				return Node("Nothing to sell.\n\n");
			}
			list = list.Where((GrabbableObject g) => (Object)(object)g != (Object)null && !g.isHeld).ToList();
			if (list.Count == 0)
			{
				return Node("Items are gone.\n\n");
			}
			if (LobbyBridge.Ready)
			{
				LobbyBridge.RequestSell(list);
			}
			else
			{
				if (!NetworkManager.Singleton.IsHost)
				{
					return Node("Only the host can sell without LethalKuchServer.\n\n");
				}
				((MonoBehaviour)StartOfRound.Instance).StartCoroutine(SellRoutine(val, list));
			}
			return Node($"Selling {list.Count} items for ${Real(list.Sum((GrabbableObject g) => g.scrapValue))}...\n\n");
		}

		private static IEnumerator SellRoutine(DepositItemsDesk desk, List<GrabbableObject> items)
		{
			foreach (GrabbableObject item in items)
			{
				NetworkObject component = ((Component)item).GetComponent<NetworkObject>();
				if (!((Object)(object)component == (Object)null))
				{
					item.EnablePhysics(false);
					item.EnableItemMeshes(false);
					((Component)item).transform.SetParent(((Component)desk.deskObjectsContainer).transform);
					((Component)item).transform.localPosition = Vector3.zero;
					desk.AddObjectToDeskServerRpc(NetworkObjectReference.op_Implicit(component));
				}
			}
			yield return (object)new WaitForSeconds(0.5f);
			desk.SellItemsOnServer();
		}

		private static List<GrabbableObject> ShipScrap()
		{
			List<GrabbableObject> list = new List<GrabbableObject>(((Component)StartOfRound.Instance.elevatorTransform).GetComponentsInChildren<GrabbableObject>());
			AutoParentToShip[] array = Object.FindObjectsByType<AutoParentToShip>((FindObjectsSortMode)0);
			foreach (AutoParentToShip val in array)
			{
				if ((Object)(object)((Component)val).transform.parent == (Object)null)
				{
					list.AddRange(((Component)val).GetComponentsInChildren<GrabbableObject>());
				}
			}
			string[] ban = DontSell;
			return (from g in list.Distinct()
				where (Object)(object)g != (Object)null && (Object)(object)g.itemProperties != (Object)null && g.itemProperties.isScrap && !g.isHeld && g.grabbable && g.scrapValue > 0 && !ban.Any((string b) => b.Equals(g.itemProperties.itemName, StringComparison.OrdinalIgnoreCase))
				select g).ToList();
		}

		private static List<GrabbableObject> Pick(List<GrabbableObject> scrap, int target)
		{
			int num = scrap.Sum((GrabbableObject g) => g.scrapValue);
			if (Real(num) < target)
			{
				return scrap;
			}
			int[] array = new int[num + 1];
			array[0] = -1;
			for (int num2 = 0; num2 < scrap.Count; num2++)
			{
				int scrapValue = scrap[num2].scrapValue;
				for (int num3 = num; num3 >= scrapValue; num3--)
				{
					if (array[num3] == 0 && array[num3 - scrapValue] != 0)
					{
						array[num3] = num2 + 1;
					}
				}
			}
			int num4 = num;
			for (int num5 = 0; num5 <= num; num5++)
			{
				if (array[num5] != 0 && Real(num5) >= target)
				{
					num4 = num5;
					break;
				}
			}
			List<GrabbableObject> list = new List<GrabbableObject>();
			int num6 = num4;
			while (num6 > 0)
			{
				int index = array[num6] - 1;
				list.Add(scrap[index]);
				num6 -= scrap[index].scrapValue;
			}
			return list;
		}

		private static string ItemList(List<GrabbableObject> items)
		{
			return string.Join("\n", from g in items
				group g by g.itemProperties.itemName into gr
				orderby gr.Sum((GrabbableObject x) => x.scrapValue) descending
				select string.Format("{0}{1}: ${2}", gr.Key, (gr.Count() > 1) ? $" x{gr.Count()}" : "", Real(gr.Sum((GrabbableObject x) => x.scrapValue))));
		}
	}
	public class SlotHotkeys : MonoBehaviour
	{
		private static readonly MethodInfo SwitchToItemSlot = AccessTools.Method(typeof(PlayerControllerB), "SwitchToItemSlot", (Type[])null, (Type[])null);

		private static readonly MethodInfo SwitchItemSlotsServerRpc = AccessTools.Method(typeof(PlayerControllerB), "SwitchItemSlotsServerRpc", (Type[])null, (Type[])null);

		private static readonly FieldInfo TimeSinceSwitchingSlots = AccessTools.Field(typeof(PlayerControllerB), "timeSinceSwitchingSlots");

		private static readonly FieldInfo ThrowingObject = AccessTools.Field(typeof(PlayerControllerB), "throwingObject");

		private void Update()
		{
			if (Cfg.SlotHotkeys.Value && !SettingsPanel.Open && Application.isFocused)
			{
				if (KeyInput.Pressed(Cfg.KeySlot1))
				{
					Select(0);
				}
				else if (KeyInput.Pressed(Cfg.KeySlot2))
				{
					Select(1);
				}
				else if (KeyInput.Pressed(Cfg.KeySlot3))
				{
					Select(2);
				}
				else if (KeyInput.Pressed(Cfg.KeySlot4))
				{
					Select(3);
				}
			}
		}

		private static void Select(int target)
		{
			PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController;
			if ((Object)(object)val == (Object)null || target < 0 || target >= val.ItemSlots.Length || ((!((NetworkBehaviour)val).IsOwner || !val.isPlayerControlled || (((NetworkBehaviour)val).IsServer && !val.isHostPlayerObject)) && !val.isTestingPlayer) || (float)TimeSinceSwitchingSlots.GetValue(val) < 0.3f || val.isGrabbingObjectAnimation || val.quickMenuManager.isMenuOpen || val.inSpecialInteractAnimation || (bool)ThrowingObject.GetValue(val) || val.isTypingChat || val.twoHanded || val.activatingItem || val.inTerminalMenu || ((val.jetpackControls || val.disablingJetpackControls) && (Object)(object)val.currentlyHeldObjectServer != (Object)null && val.currentlyHeldObjectServer.itemProperties.itemId == 13))
			{
				return;
			}
			int currentItemSlot = val.currentItemSlot;
			int num = val.ItemSlots.Length;
			if (currentItemSlot != target)
			{
				int num2 = ((target - currentItemSlot) % num + num) % num;
				int num3 = num - num2;
				bool flag = num2 <= num3;
				int num4 = (flag ? num2 : num3);
				ShipBuildModeManager.Instance.CancelBuildMode(true);
				val.playerBodyAnimator.SetBool("GrabValidated", false);
				SwitchToItemSlot.Invoke(val, new object[2] { target, null });
				for (int i = 0; i < num4; i++)
				{
					SwitchItemSlotsServerRpc.Invoke(val, new object[1] { flag });
				}
				if ((Object)(object)val.currentlyHeldObjectServer != (Object)null)
				{
					((Component)val.currentlyHeldObjectServer).gameObject.GetComponent<AudioSource>().PlayOneShot(val.currentlyHeldObjectServer.itemProperties.grabSFX, 0.6f);
				}
				TimeSinceSwitchingSlots.SetValue(val, 0f);
			}
		}
	}
	public class Visuals : MonoBehaviour
	{
		private float t;

		private void Update()
		{
			t += Time.unscaledDeltaTime;
			if (t < 0.5f)
			{
				return;
			}
			t = 0f;
			GameObject val = GameObject.Find("Systems");
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			Transform root = val.transform.Find("Rendering");
			Set(root, "CustomPass", !Cfg.DisableOutline.Value);
			Set(root, "VolumeMain", !Cfg.DisableFog.Value);
			Set(root, "PlayerHUDHelmetModel", !Cfg.DisableHelmet.Value);
			Transform val2 = val.transform.Find("UI/Canvas/IngamePlayerHUD");
			if (!((Object)(object)val2 == (Object)null))
			{
				bool active = !Cfg.DisableHud.Value;
				string[] array = new string[7] { "Inventory", "TopLeftCorner/SprintMeter", "TopLeftCorner/Batteries", "TopLeftCorner/WeightUI", "TopLeftCorner/Self", "TopLeftCorner/SelfRed", "BottomLeftCorner" };
				foreach (string path in array)
				{
					Set(val2, path, active);
				}
			}
		}

		private static void Set(Transform root, string path, bool active)
		{
			Transform val = ((root != null) ? root.Find(path) : null);
			if ((Object)(object)val != (Object)null && ((Component)val).gameObject.activeSelf != active)
			{
				((Component)val).gameObject.SetActive(active);
			}
		}
	}
}