Decompiled source of FlashlightFocus v1.0.0

plugins/FlashlightFocus.dll

Decompiled 3 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("FlashlightFocus")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Client-side adjustable flashlight focus and manual flashlight toggle. Keeps the vanilla flashlight model.")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("FlashlightFocus")]
[assembly: AssemblyTitle("FlashlightFocus")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.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 FlashlightFocus
{
	internal static class Focus
	{
		private static FlashlightController _fc;

		private static float _originalAngle = 60f;

		private static bool _captured;

		internal static bool ManualOff;

		internal static float HudUntil = -99f;

		internal static bool HudVisible => Time.unscaledTime <= HudUntil;

		internal static FlashlightController Local()
		{
			FlashlightController instance = FlashlightController.Instance;
			if ((Object)(object)instance == (Object)null || (Object)(object)instance.PlayerAvatar == (Object)null || !instance.PlayerAvatar.isLocal)
			{
				return null;
			}
			return instance;
		}

		internal static void Bind(FlashlightController fc)
		{
			if (!((Object)(object)fc == (Object)null) && (!((Object)(object)_fc == (Object)(object)fc) || !_captured))
			{
				_fc = fc;
				ManualOff = false;
				if ((Object)(object)fc.spotlight != (Object)null)
				{
					_originalAngle = fc.spotlight.spotAngle;
					_captured = true;
					Plugin.Log.LogInfo((object)("Vanilla flashlight beam width: " + _originalAngle.ToString("0.#") + " degrees"));
				}
			}
		}

		internal static float EffectiveAngle()
		{
			float num = ((Plugin.FocusAngle != null) ? Plugin.FocusAngle.Value : 0f);
			if (num <= 0.01f || !_captured)
			{
				return _originalAngle;
			}
			return Mathf.Clamp(num, Min(), Max());
		}

		private static float Min()
		{
			return Mathf.Clamp(Mathf.Min(Plugin.MinAngle.Value, Plugin.MaxAngle.Value), 1f, 179f);
		}

		private static float Max()
		{
			return Mathf.Clamp(Mathf.Max(Plugin.MinAngle.Value, Plugin.MaxAngle.Value), 1f, 179f);
		}

		internal static void Tick(FlashlightController fc)
		{
			if ((Object)(object)fc == (Object)null || (Object)(object)fc != (Object)(object)Local())
			{
				return;
			}
			Bind(fc);
			if (!Plugin.Enabled.Value)
			{
				Restore();
			}
			else if (!((Object)(object)fc.spotlight == (Object)null))
			{
				float num = EffectiveAngle();
				if (Mathf.Abs(fc.spotlight.spotAngle - num) > 0.001f)
				{
					fc.spotlight.spotAngle = num;
				}
				if (ManualOff)
				{
					ForceOff(fc);
				}
				else
				{
					ForceOnIfLit(fc);
				}
			}
		}

		internal static bool Adjust(float scroll)
		{
			if ((Object)(object)_fc == (Object)null || (Object)(object)_fc.spotlight == (Object)null)
			{
				return false;
			}
			float num = EffectiveAngle();
			float num2 = ((scroll > 0f) ? (-1f) : 1f);
			if (Plugin.InvertScroll.Value)
			{
				num2 = 0f - num2;
			}
			float num3 = Mathf.Clamp(Plugin.Step.Value, 0.1f, 45f);
			float num4 = Mathf.Clamp(num + num2 * num3, Min(), Max());
			num4 = Mathf.Round(num4 * 10f) / 10f;
			if (Mathf.Abs(num4 - num) > 0.001f)
			{
				Plugin.FocusAngle.Value = num4;
			}
			HudUntil = Time.unscaledTime + 1.6f;
			return true;
		}

		internal static bool CanToggle(FlashlightController fc)
		{
			if ((Object)(object)fc != (Object)null && (Object)(object)fc.PlayerAvatar != (Object)null && fc.active)
			{
				return !fc.PlayerAvatar.isDisabled;
			}
			return false;
		}

		internal static void Toggle(FlashlightController fc)
		{
			if (!((Object)(object)fc == (Object)null))
			{
				Bind(fc);
				ManualOff = !ManualOff;
				if (!ManualOff)
				{
					ForceOnIfLit(fc);
				}
			}
		}

		internal static void Restore()
		{
			bool manualOff = ManualOff;
			ManualOff = false;
			if (!((Object)(object)_fc == (Object)null))
			{
				if ((Object)(object)_fc.spotlight != (Object)null && _captured)
				{
					_fc.spotlight.spotAngle = _originalAngle;
				}
				if (manualOff)
				{
					ForceOnIfLit(_fc);
				}
			}
		}

		private static void ForceOff(FlashlightController fc)
		{
			if ((Object)(object)fc.spotlight != (Object)null && ((Behaviour)fc.spotlight).enabled)
			{
				((Behaviour)fc.spotlight).enabled = false;
			}
			if ((Object)(object)fc.halo != (Object)null && fc.halo.enabled)
			{
				fc.halo.enabled = false;
			}
			fc.LightActive = false;
		}

		private static void ForceOnIfLit(FlashlightController fc)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			if (fc.active && IsLitState(fc.currentState))
			{
				if ((Object)(object)fc.spotlight != (Object)null && !((Behaviour)fc.spotlight).enabled)
				{
					((Behaviour)fc.spotlight).enabled = true;
				}
				if ((Object)(object)fc.halo != (Object)null && !fc.halo.enabled)
				{
					fc.halo.enabled = true;
				}
				fc.LightActive = true;
			}
		}

		private static bool IsLitState(State state)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Invalid comparison between Unknown and I4
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Invalid comparison between Unknown and I4
			if ((int)state != 2)
			{
				return (int)state == 3;
			}
			return true;
		}
	}
	internal static class Lang
	{
		internal class Row
		{
			public string Id;

			public string[] Sec;

			public string[] Name;

			public string[] Desc;
		}

		public const int En = 0;

		public const int Zh = 1;

		public static readonly string[] Options = new string[3] { "Auto", "English", "中文" };

		internal static ConfigEntry<string> Cur;

		private static string _gameCode;

		private static float _gameAt = -99f;

		private static readonly string[] SecGeneral = new string[2] { "1.General", "1.常规" };

		private static readonly string[] SecFocus = new string[2] { "2.Focus", "2.聚焦" };

		internal static readonly Row[] Rows = new Row[10]
		{
			new Row
			{
				Id = "enabled",
				Sec = SecGeneral,
				Name = new string[2] { "Enable mod", "启用模组" },
				Desc = new string[2] { "Master switch. When off, the flashlight focus and its manual on/off state are restored to vanilla.", "总开关。关闭后,手电筒聚焦和手动开关状态都会恢复为原版。" }
			},
			new Row
			{
				Id = "focuskey",
				Sec = SecGeneral,
				Name = new string[2] { "Focus key (hold)", "聚焦按键(按住)" },
				Desc = new string[2] { "Hold this key and scroll the mouse wheel to adjust the flashlight beam width. Default: E.", "按住此键并滚动鼠标滚轮即可调节手电筒光束宽度。默认:E。" }
			},
			new Row
			{
				Id = "togglekey",
				Sec = SecGeneral,
				Name = new string[2] { "Flashlight toggle key", "手电筒开关按键" },
				Desc = new string[2] { "Press in game to switch the flashlight beam on or off. The vanilla flashlight model stays in the hand. Default: X.", "游戏内按下可打开或关闭手电筒光束。原版手电筒模型仍会拿在手上。默认:X。" }
			},
			new Row
			{
				Id = "showtoast",
				Sec = SecGeneral,
				Name = new string[2] { "Show on-screen messages", "显示屏幕提示" },
				Desc = new string[2] { "Show a short message when the flashlight is switched on or off.", "手电筒打开或关闭时在屏幕上显示简短提示。" }
			},
			new Row
			{
				Id = "showhud",
				Sec = SecGeneral,
				Name = new string[2] { "Show focus indicator", "显示聚焦指示" },
				Desc = new string[2] { "Show the beam width indicator while you adjust the focus with the mouse wheel.", "用鼠标滚轮调节聚焦时,显示光束宽度指示条。" }
			},
			new Row
			{
				Id = "focusangle",
				Sec = SecFocus,
				Name = new string[2] { "Focus width", "聚焦角度" },
				Desc = new string[2] { "Current beam width in degrees. 0 = use the vanilla flashlight width. Hold the focus key and scroll in game to change it.", "当前光束角度(度)。0 = 使用原版手电筒宽度。游戏内按住聚焦按键滚动滚轮即可改变。" }
			},
			new Row
			{
				Id = "step",
				Sec = SecFocus,
				Name = new string[2] { "Wheel step (degrees)", "滚轮步进(度)" },
				Desc = new string[2] { "How many degrees one mouse wheel notch changes the beam width.", "鼠标滚轮每滚动一格改变多少度光束宽度。" }
			},
			new Row
			{
				Id = "min",
				Sec = SecFocus,
				Name = new string[2] { "Narrowest angle", "最窄角度" },
				Desc = new string[2] { "Lower limit of the beam width in degrees. Smaller = a tighter, more focused beam.", "光束宽度的下限(度)。数值越小,光束越集中。" }
			},
			new Row
			{
				Id = "max",
				Sec = SecFocus,
				Name = new string[2] { "Widest angle", "最宽角度" },
				Desc = new string[2] { "Upper limit of the beam width in degrees. Larger = a wider beam.", "光束宽度的上限(度)。数值越大,光束越宽。" }
			},
			new Row
			{
				Id = "invert",
				Sec = SecFocus,
				Name = new string[2] { "Invert scroll direction", "反转滚轮方向" },
				Desc = new string[2] { "Off: scroll up narrows the beam. On: scroll up widens it.", "关闭:向上滚动收窄光束。开启:向上滚动放宽光束。" }
			}
		};

		public static int Idx
		{
			get
			{
				string text = ((Cur != null) ? Cur.Value : "Auto");
				for (int i = 1; i < Options.Length; i++)
				{
					if (text == Options[i])
					{
						return i - 1;
					}
				}
				return FromGame();
			}
		}

		public static string HudTitle => Pick("FLASHLIGHT FOCUS", "手电筒聚焦");

		public static string Narrowest => Pick("Narrowest beam", "最窄光束");

		public static string Widest => Pick("Widest beam", "最宽光束");

		public static string ToastOn => Pick("Flashlight ON", "手电筒已打开");

		public static string ToastOff => Pick("Flashlight OFF", "手电筒已关闭");

		public static string ToastUnavailable => Pick("Flashlight is not available right now", "当前无法使用手电筒");

		private static int FromGame()
		{
			if (_gameCode == null || Time.unscaledTime - _gameAt > 1f)
			{
				_gameAt = Time.unscaledTime;
				try
				{
					_gameCode = (SemiFunc.LocaleGetCode() ?? "en").ToLowerInvariant();
				}
				catch
				{
					_gameCode = "en";
				}
			}
			return _gameCode.StartsWith("zh") ? 1 : 0;
		}

		public static string Pick(string en, string zh)
		{
			if (Idx != 1)
			{
				return en;
			}
			return zh;
		}

		public static string HudHint(string key)
		{
			return Pick("Scroll to adjust  ·  release " + key + " to finish", "滚轮调节  ·  松开 " + key + " 完成");
		}

		internal static Row Find(string id)
		{
			Row[] rows = Rows;
			foreach (Row row in rows)
			{
				if (row.Id == id)
				{
					return row;
				}
			}
			return null;
		}
	}
	internal static class LangHost
	{
		private static ConfigFile _c;

		private static readonly Dictionary<string, ConfigEntryBase> Map = new Dictionary<string, ConfigEntryBase>();

		private static readonly Dictionary<string, string> Legacy = new Dictionary<string, string>
		{
			{ "enabled", "Enabled" },
			{ "focuskey", "FocusKey" },
			{ "togglekey", "ToggleKey" },
			{ "showtoast", "ShowToast" },
			{ "showhud", "ShowHud" },
			{ "focusangle", "FocusAngle" },
			{ "step", "ScrollStep" },
			{ "min", "MinAngle" },
			{ "max", "MaxAngle" },
			{ "invert", "InvertScroll" }
		};

		private static int _applied = -1;

		private static float _refreshAt = -1f;

		public static void Init(ConfigFile c)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Expected O, but got Unknown
			_c = c;
			Lang.Cur = c.Bind<string>("0.Language", "Language", "Auto", new ConfigDescription("Auto = follow the game language (English if unsupported) / 自动 = 跟随游戏语言(不支持则用英文)", (AcceptableValueBase)(object)new AcceptableValueList<string>(Lang.Options), Array.Empty<object>()));
			Lang.Cur.SettingChanged += delegate
			{
				Apply();
			};
			_applied = Lang.Idx;
		}

		public static ConfigEntry<T> B<T>(string id, T def, AcceptableValueBase range = null)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Expected O, but got Unknown
			Lang.Row row = Lang.Find(id);
			int idx = Lang.Idx;
			string saved = FindSaved(row);
			ConfigEntry<T> val = _c.Bind<T>(row.Sec[idx], row.Name[idx], def, new ConfigDescription(row.Desc[idx], range, Array.Empty<object>()));
			Map[id] = (ConfigEntryBase)(object)val;
			RestoreSaved((ConfigEntryBase)(object)val, saved);
			return val;
		}

		private static string FindSaved(Lang.Row r)
		{
			try
			{
				if (!(GetMember(_c, "OrphanedEntries") is IDictionary dictionary))
				{
					return null;
				}
				string result = null;
				foreach (DictionaryEntry item in dictionary)
				{
					object key = item.Key;
					ConfigDefinition val = (ConfigDefinition)((key is ConfigDefinition) ? key : null);
					if (val == (ConfigDefinition)null)
					{
						continue;
					}
					string value;
					bool flag = Legacy.TryGetValue(r.Id, out value) && val.Key == value;
					int num = 0;
					while (!flag && num < r.Name.Length)
					{
						flag = val.Key == r.Name[num];
						num++;
					}
					if (flag)
					{
						result = item.Value as string;
						if (val.Section == r.Sec[Lang.Idx] && val.Key == r.Name[Lang.Idx])
						{
							break;
						}
					}
				}
				return result;
			}
			catch
			{
				return null;
			}
		}

		private static void RestoreSaved(ConfigEntryBase e, string saved)
		{
			if (saved == null)
			{
				return;
			}
			try
			{
				e.SetSerializedValue(saved);
			}
			catch
			{
			}
		}

		public static void Finish()
		{
			try
			{
				if (GetMember(_c, "OrphanedEntries") is IDictionary dictionary)
				{
					dictionary.Clear();
				}
				_c.Save();
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Config cleanup: " + ex.Message));
			}
		}

		public static void Tick()
		{
			if (_applied >= 0 && Lang.Idx != _applied)
			{
				Apply();
			}
			if (_refreshAt >= 0f && Time.unscaledTime >= _refreshAt)
			{
				_refreshAt = -1f;
				RefreshMenu();
			}
		}

		private static void Apply()
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Expected O, but got Unknown
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Expected O, but got Unknown
			if (_c == null)
			{
				return;
			}
			try
			{
				int num = (_applied = Lang.Idx);
				foreach (KeyValuePair<string, ConfigEntryBase> item in Map)
				{
					Lang.Row row = Lang.Find(item.Key);
					ConfigEntryBase value = item.Value;
					SetBacking(value, "Definition", (object)new ConfigDefinition(row.Sec[num], row.Name[num]));
					string obj = row.Desc[num];
					ConfigDescription description = value.Description;
					AcceptableValueBase obj2 = ((description != null) ? description.AcceptableValues : null);
					ConfigDescription description2 = value.Description;
					SetBacking(value, "Description", (object)new ConfigDescription(obj, obj2, ((description2 != null) ? description2.Tags : null) ?? new object[0]));
				}
				if (GetMember(_c, "Entries") is IDictionary dictionary)
				{
					dictionary.Clear();
					foreach (ConfigEntryBase value2 in Map.Values)
					{
						dictionary[value2.Definition] = value2;
					}
					dictionary[((ConfigEntryBase)Lang.Cur).Definition] = Lang.Cur;
				}
				else
				{
					Plugin.Log.LogWarning((object)"ConfigFile.Entries not found, config menu texts may not switch");
				}
				if (GetMember(_c, "OrphanedEntries") is IDictionary dictionary2)
				{
					dictionary2.Clear();
				}
				_c.Save();
				_refreshAt = Time.unscaledTime + 0.15f;
				Plugin.Log.LogInfo((object)("Language -> " + Lang.Options[num + 1]));
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Language switch failed: " + ex.Message));
			}
		}

		private static object GetMember(object obj, string name)
		{
			Type type = obj.GetType();
			while (type != null)
			{
				FieldInfo fieldInfo = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? type.GetField("<" + name + ">k__BackingField", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (fieldInfo != null)
				{
					return fieldInfo.GetValue(obj);
				}
				PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (property != null && property.GetIndexParameters().Length == 0)
				{
					return property.GetValue(obj);
				}
				type = type.BaseType;
			}
			return null;
		}

		private static void SetBacking(object obj, string member, object val)
		{
			Type type = obj.GetType();
			while (type != null)
			{
				FieldInfo field = type.GetField("<" + member + ">k__BackingField", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (field != null)
				{
					field.SetValue(obj, val);
					return;
				}
				type = type.BaseType;
			}
			throw new MissingFieldException(obj.GetType().Name, member);
		}

		private static void RefreshMenu()
		{
			try
			{
				Type type = FindType("MenuLib.MenuAPI");
				Type type2 = FindType("REPOConfig.ConfigMenu");
				if (type == null || type2 == null)
				{
					return;
				}
				FieldInfo field = type2.GetField("hasPopupMenuOpened", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				if (field != null)
				{
					object value = field.GetValue(null);
					if (value is bool && !(bool)value)
					{
						return;
					}
				}
				type.GetMethod("CloseAllPagesAddedOnTop", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null)?.Invoke(null, null);
				type2.GetMethod("CreateModMenu", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null)?.Invoke(null, null);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Menu refresh: " + ex.Message));
			}
		}

		private static Type FindType(string name)
		{
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			for (int i = 0; i < assemblies.Length; i++)
			{
				Type type = assemblies[i].GetType(name, throwOnError: false);
				if (type != null)
				{
					return type;
				}
			}
			return null;
		}
	}
	internal static class Patches
	{
		[HarmonyPatch(typeof(FlashlightController), "Update")]
		[HarmonyPostfix]
		private static void UpdatePostfix(FlashlightController __instance)
		{
			try
			{
				Focus.Tick(__instance);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)ex.ToString());
			}
		}
	}
	[BepInPlugin("com.yanyan.repo.flashlightfocus", "Flashlight Focus 手电筒聚焦", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		public const string Guid = "com.yanyan.repo.flashlightfocus";

		public const string Version = "1.0.0";

		internal static ManualLogSource Log;

		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<KeyCode> FocusKey;

		internal static ConfigEntry<KeyCode> ToggleKey;

		internal static ConfigEntry<bool> ShowToast;

		internal static ConfigEntry<bool> ShowHud;

		internal static ConfigEntry<float> FocusAngle;

		internal static ConfigEntry<float> Step;

		internal static ConfigEntry<float> MinAngle;

		internal static ConfigEntry<float> MaxAngle;

		internal static ConfigEntry<bool> InvertScroll;

		private Harmony _harmony;

		private string _toast;

		private float _toastT = -99f;

		private void Awake()
		{
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			LangHost.Init(((BaseUnityPlugin)this).Config);
			Enabled = LangHost.B("enabled", def: true);
			FocusKey = LangHost.B<KeyCode>("focuskey", (KeyCode)101);
			ToggleKey = LangHost.B<KeyCode>("togglekey", (KeyCode)120);
			ShowToast = LangHost.B("showtoast", def: true);
			ShowHud = LangHost.B("showhud", def: true);
			FocusAngle = LangHost.B("focusangle", 0f, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 179f));
			Step = LangHost.B("step", 2.5f, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 20f));
			MinAngle = LangHost.B("min", 8f, (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 179f));
			MaxAngle = LangHost.B("max", 120f, (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 179f));
			InvertScroll = LangHost.B("invert", def: false);
			LangHost.Finish();
			Enabled.SettingChanged += OnEnabledChanged;
			_harmony = new Harmony("com.yanyan.repo.flashlightfocus");
			_harmony.PatchAll(typeof(Patches));
			Log.LogInfo((object)"Flashlight Focus 1.0.0 loaded");
		}

		private static void OnEnabledChanged(object sender, EventArgs e)
		{
			if (!Enabled.Value)
			{
				Focus.Restore();
			}
		}

		private void Update()
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: 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_008e: 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)
			try
			{
				LangHost.Tick();
				if (!Enabled.Value)
				{
					Focus.Restore();
					return;
				}
				FlashlightController val = Focus.Local();
				if ((Object)(object)val == (Object)null)
				{
					return;
				}
				Focus.Bind(val);
				if (!InputAllowed())
				{
					return;
				}
				if ((int)FocusKey.Value != 0 && Input.GetKey(FocusKey.Value))
				{
					float y = Input.mouseScrollDelta.y;
					if (Mathf.Abs(y) > 0.01f)
					{
						Focus.Adjust(y);
					}
				}
				if ((int)ToggleKey.Value != 0 && Input.GetKeyDown(ToggleKey.Value))
				{
					if (Focus.CanToggle(val))
					{
						Focus.Toggle(val);
						Toast(Focus.ManualOff ? Lang.ToastOff : Lang.ToastOn);
					}
					else
					{
						Toast(Lang.ToastUnavailable);
					}
				}
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)ex.ToString());
			}
		}

		private static bool InputAllowed()
		{
			if (SemiFunc.MenuLevel() || !SemiFunc.NoTextInputsActive())
			{
				return false;
			}
			if ((Object)(object)MenuManager.instance != (Object)null && (Object)(object)MenuManager.instance.currentMenuPage != (Object)null)
			{
				return false;
			}
			if ((Object)(object)GameDirector.instance != (Object)null && GameDirector.instance.DisableInput)
			{
				return false;
			}
			return true;
		}

		private void Toast(string s)
		{
			if (ShowToast.Value)
			{
				_toast = s;
				_toastT = Time.unscaledTime;
			}
		}

		private void OnGUI()
		{
			if (Enabled.Value)
			{
				if (ShowToast.Value && _toast != null && Time.unscaledTime - _toastT <= 2.2f)
				{
					DrawToast(_toast);
				}
				if (ShowHud.Value && Focus.HudVisible)
				{
					DrawFocusHud();
				}
			}
		}

		private static void DrawToast(string text)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: 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_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			//IL_0042: 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)
			GUIStyle style = new GUIStyle(GUI.skin.label)
			{
				fontSize = 22,
				alignment = (TextAnchor)4,
				fontStyle = (FontStyle)1
			};
			DrawLabel(new Rect(0f, (float)Screen.height * 0.2f, (float)Screen.width, 40f), text, style, Color.white);
		}

		private static void DrawFocusHud()
		{
			//IL_003f: 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)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: 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_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Expected O, but got Unknown
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Expected O, but got Unknown
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Expected O, but got Unknown
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//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_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_021e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0223: Unknown result type (might be due to invalid IL or missing references)
			//IL_0228: Unknown result type (might be due to invalid IL or missing references)
			//IL_023e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0252: Unknown result type (might be due to invalid IL or missing references)
			//IL_025e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0263: Unknown result type (might be due to invalid IL or missing references)
			//IL_02dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f5: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.Min(460f, (float)Screen.width - 40f);
			float num2 = 100f;
			float num3 = ((float)Screen.width - num) * 0.5f;
			float num4 = (float)Screen.height - num2 - 120f;
			Rect val = new Rect(num3, num4, num, num2);
			Color color = GUI.color;
			GUI.color = new Color(0f, 0f, 0f, 0.58f);
			GUI.DrawTexture(val, (Texture)(object)Texture2D.whiteTexture);
			GUI.color = color;
			float num5 = Focus.EffectiveAngle();
			float num6 = Mathf.Min(MinAngle.Value, MaxAngle.Value);
			float num7 = Mathf.Max(MinAngle.Value, MaxAngle.Value);
			float num8 = ((num7 > num6) ? Mathf.InverseLerp(num6, num7, num5) : 0.5f);
			GUIStyle style = new GUIStyle(GUI.skin.label)
			{
				fontSize = 15,
				fontStyle = (FontStyle)1,
				alignment = (TextAnchor)3
			};
			GUIStyle style2 = new GUIStyle(GUI.skin.label)
			{
				fontSize = 26,
				fontStyle = (FontStyle)1,
				alignment = (TextAnchor)5
			};
			GUIStyle style3 = new GUIStyle(GUI.skin.label)
			{
				fontSize = 13,
				alignment = (TextAnchor)4
			};
			Rect r = new Rect(num3 + 18f, num4 + 8f, num - 36f, 24f);
			DrawLabel(r, Lang.HudTitle, style, new Color(1f, 0.92f, 0.66f));
			DrawLabel(r, num5.ToString("0.#") + "°", style2, Color.white);
			Rect val2 = default(Rect);
			((Rect)(ref val2))..ctor(num3 + 18f, num4 + 44f, num - 36f, 8f);
			Color color2 = GUI.color;
			GUI.color = new Color(1f, 1f, 1f, 0.18f);
			GUI.DrawTexture(val2, (Texture)(object)Texture2D.whiteTexture);
			GUI.color = color2;
			Rect val3 = new Rect(((Rect)(ref val2)).x, ((Rect)(ref val2)).y, ((Rect)(ref val2)).width * Mathf.Clamp01(num8), ((Rect)(ref val2)).height);
			color2 = GUI.color;
			GUI.color = new Color(1f, 0.84f, 0.32f, 1f);
			GUI.DrawTexture(val3, (Texture)(object)Texture2D.whiteTexture);
			GUI.color = color2;
			string text = Lang.HudHint(((object)FocusKey.Value/*cast due to .constrained prefix*/).ToString());
			if (Mathf.Abs(num5 - num6) < 0.05f)
			{
				text = Lang.Narrowest + "  ·  " + text;
			}
			else if (Mathf.Abs(num5 - num7) < 0.05f)
			{
				text = Lang.Widest + "  ·  " + text;
			}
			DrawLabel(new Rect(num3 + 18f, num4 + 60f, num - 36f, 24f), text, style3, new Color(0.88f, 0.88f, 0.88f));
		}

		private static void DrawLabel(Rect r, string text, GUIStyle style, Color color)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			GUIStyle val = new GUIStyle(style);
			val.normal.textColor = new Color(0f, 0f, 0f, 0.85f);
			GUI.Label(new Rect(((Rect)(ref r)).x + 2f, ((Rect)(ref r)).y + 2f, ((Rect)(ref r)).width, ((Rect)(ref r)).height), text, val);
			style.normal.textColor = color;
			GUI.Label(r, text, style);
		}

		private void OnDestroy()
		{
			try
			{
				Focus.Restore();
			}
			catch
			{
			}
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}