Decompiled source of BetterFlashlight v1.1.0

BetterFlashLight.dll

Decompiled 4 days ago
using System;
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.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp-firstpass")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: IgnoresAccessChecksTo("Autodesk.Fbx")]
[assembly: IgnoresAccessChecksTo("Discord.Sdk")]
[assembly: IgnoresAccessChecksTo("Domain_Reload")]
[assembly: IgnoresAccessChecksTo("Facepunch.Steamworks.Win64")]
[assembly: IgnoresAccessChecksTo("FbxBuildTestAssets")]
[assembly: IgnoresAccessChecksTo("Klattersynth")]
[assembly: IgnoresAccessChecksTo("Photon3Unity3D")]
[assembly: IgnoresAccessChecksTo("PhotonChat")]
[assembly: IgnoresAccessChecksTo("PhotonRealtime")]
[assembly: IgnoresAccessChecksTo("PhotonUnityNetworking")]
[assembly: IgnoresAccessChecksTo("PhotonUnityNetworking.Utilities")]
[assembly: IgnoresAccessChecksTo("PhotonVoice.API")]
[assembly: IgnoresAccessChecksTo("PhotonVoice")]
[assembly: IgnoresAccessChecksTo("PhotonVoice.PUN")]
[assembly: IgnoresAccessChecksTo("SingularityGroup.HotReload.Runtime.Public")]
[assembly: IgnoresAccessChecksTo("Sirenix.OdinInspector.Attributes")]
[assembly: IgnoresAccessChecksTo("Sirenix.OdinInspector.Modules.Unity.Addressables")]
[assembly: IgnoresAccessChecksTo("Sirenix.OdinInspector.Modules.UnityLocalization")]
[assembly: IgnoresAccessChecksTo("Sirenix.Serialization.Config")]
[assembly: IgnoresAccessChecksTo("Sirenix.Serialization")]
[assembly: IgnoresAccessChecksTo("Sirenix.Utilities")]
[assembly: IgnoresAccessChecksTo("Unity.Addressables")]
[assembly: IgnoresAccessChecksTo("Unity.AI.Navigation")]
[assembly: IgnoresAccessChecksTo("Unity.Burst")]
[assembly: IgnoresAccessChecksTo("Unity.Burst.Unsafe")]
[assembly: IgnoresAccessChecksTo("Unity.Collections")]
[assembly: IgnoresAccessChecksTo("Unity.Collections.LowLevel.ILSupport")]
[assembly: IgnoresAccessChecksTo("Unity.Formats.Fbx.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.InputSystem")]
[assembly: IgnoresAccessChecksTo("Unity.InputSystem.ForUI")]
[assembly: IgnoresAccessChecksTo("Unity.InternalAPIEngineBridge.013")]
[assembly: IgnoresAccessChecksTo("Unity.Localization")]
[assembly: IgnoresAccessChecksTo("Unity.Mathematics")]
[assembly: IgnoresAccessChecksTo("Unity.MemoryProfiler")]
[assembly: IgnoresAccessChecksTo("Unity.Postprocessing.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.Profiling.Core")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.ShaderLibrary")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.ShaderGraph.ShaderGraphLibrary")]
[assembly: IgnoresAccessChecksTo("Unity.ResourceManager")]
[assembly: IgnoresAccessChecksTo("Unity.ScriptableBuildPipeline")]
[assembly: IgnoresAccessChecksTo("Unity.Splines")]
[assembly: IgnoresAccessChecksTo("Unity.TextMeshPro")]
[assembly: IgnoresAccessChecksTo("Unity.Timeline")]
[assembly: IgnoresAccessChecksTo("Unity.VisualScripting.Antlr3.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.VisualScripting.Core")]
[assembly: IgnoresAccessChecksTo("Unity.VisualScripting.Flow")]
[assembly: IgnoresAccessChecksTo("Unity.VisualScripting.State")]
[assembly: IgnoresAccessChecksTo("UnityEngine.ARModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.NVIDIAModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.UI")]
[assembly: IgnoresAccessChecksTo("websocket-sharp")]
[assembly: AssemblyCompany("finnick")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.3.0")]
[assembly: AssemblyInformationalVersion("1.0.3")]
[assembly: AssemblyProduct("BetterFlashLight")]
[assembly: AssemblyTitle("BetterFlashLight")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.3.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 BetterFlashlight
{
	[BepInPlugin("finnick.BetterFlashlight", "BetterFlashlight", "1.0.3")]
	public sealed class BetterFlashlight : BaseUnityPlugin
	{
		internal const string PluginGuid = "finnick.BetterFlashlight";

		internal const string PluginName = "BetterFlashlight";

		internal const string PluginVersion = "1.0.3";

		private Harmony? _harmony;

		private Texture2D _pixel = null;

		private float _displayedBattery = 1f;

		private float _displayedAlpha;

		private float _displayedPulse;

		private float _displayedScan;

		internal static BetterFlashlight Instance { get; private set; }

		internal static ManualLogSource Logger => Instance._logger;

		private ManualLogSource _logger => ((BaseUnityPlugin)this).Logger;

		private void Awake()
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Expected O, but got Unknown
			Instance = this;
			((Component)this).transform.SetParent((Transform)null);
			((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
			_pixel = CreatePixelTexture();
			_harmony = new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID);
			_harmony.PatchAll();
			Logger.LogInfo((object)$"{((BaseUnityPlugin)this).Info.Metadata.GUID} v{((BaseUnityPlugin)this).Info.Metadata.Version} has loaded!");
		}

		private void OnDestroy()
		{
			Harmony? harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			if ((Object)(object)_pixel != (Object)null)
			{
				Object.Destroy((Object)(object)_pixel);
			}
		}

		private void Update()
		{
			float unscaledDeltaTime = Time.unscaledDeltaTime;
			if (FlashlightRuntime.TryGetHudState(out var hudState))
			{
				_displayedBattery = Damp(_displayedBattery, hudState.BatteryNormalized, 10f, unscaledDeltaTime);
				_displayedAlpha = Damp(_displayedAlpha, hudState.ShouldDisplay ? 1f : 0f, 8f, unscaledDeltaTime);
				_displayedPulse = Damp(_displayedPulse, hudState.IsOn ? 1f : 0.45f, 7f, unscaledDeltaTime);
				_displayedScan += unscaledDeltaTime * (hudState.IsCharging ? 0.55f : 0.2f);
			}
			else
			{
				_displayedAlpha = Damp(_displayedAlpha, 0f, 8f, unscaledDeltaTime);
				_displayedPulse = Damp(_displayedPulse, 0f, 8f, unscaledDeltaTime);
			}
		}

		private void OnGUI()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Invalid comparison between Unknown and I4
			if (!(_displayedAlpha <= 0.01f) && (int)Event.current.type == 7)
			{
				DrawBatteryHud();
			}
		}

		private void DrawBatteryHud()
		{
			//IL_0068: 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_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: 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_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: 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_0145: 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_016a: 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_018f: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
			FlashlightRuntime.HudState hudStateSnapshot = FlashlightRuntime.GetHudStateSnapshot();
			float num = Mathf.Clamp((float)Screen.height / 1080f, 0.85f, 1.2f);
			float num2 = 260f * num;
			float num3 = 24f * num;
			float num4 = ((float)Screen.width - num2) * 0.5f;
			float num5 = (float)Screen.height - 210f * num;
			float displayedAlpha = _displayedAlpha;
			Rect rect = default(Rect);
			((Rect)(ref rect))..ctor(num4, num5, num2, num3);
			Rect rect2 = ExpandRect(rect, 8f * num, 8f * num);
			Rect val = InsetRect(rect, 4f * num, 4f * num);
			Rect rect3 = default(Rect);
			((Rect)(ref rect3))..ctor(((Rect)(ref val)).x, ((Rect)(ref val)).y, ((Rect)(ref val)).width, ((Rect)(ref val)).height * 0.42f);
			Rect rect4 = default(Rect);
			((Rect)(ref rect4))..ctor(((Rect)(ref rect)).x + 12f * num, ((Rect)(ref rect)).yMax + 3f * num, ((Rect)(ref rect)).width - 24f * num, 2f * num);
			DrawRect(rect2, new Color(0f, 0f, 0f, 0.08f * displayedAlpha));
			DrawRect(rect, new Color(0.035f, 0.05f, 0.06f, 0.34f * displayedAlpha));
			DrawRect(val, new Color(0.08f, 0.11f, 0.13f, 0.44f * displayedAlpha));
			DrawRect(rect3, new Color(0.95f, 0.98f, 1f, 0.045f * displayedAlpha));
			DrawSegments(val, hudStateSnapshot, num, displayedAlpha);
			DrawRect(rect4, new Color(0.8f, 0.9f, 1f, 0.05f * displayedAlpha));
		}

		private void DrawSegments(Rect innerRect, FlashlightRuntime.HudState hudState, float scale, float alpha)
		{
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: 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_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: 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_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: 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_025a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0273: Unknown result type (might be due to invalid IL or missing references)
			float num = 3f * scale;
			float num2 = 6f * scale;
			float num3 = ((Rect)(ref innerRect)).width - num2 * 2f - num * 17f;
			float num4 = num3 / 18f;
			float num5 = ((Rect)(ref innerRect)).height - num2 * 2f;
			int num6 = Mathf.Clamp(Mathf.CeilToInt(_displayedBattery * 18f), 0, 18);
			Color activeColor = GetActiveColor(hudState);
			Color color = default(Color);
			((Color)(ref color))..ctor(0.3f, 0.37f, 0.41f, 0.18f * alpha);
			Color color2 = default(Color);
			((Color)(ref color2))..ctor(1f, 1f, 1f, 0.08f * alpha);
			float num7 = Mathf.Lerp(0.12f, 0.26f, _displayedPulse) * alpha;
			Rect rect = default(Rect);
			for (int i = 0; i < 18; i++)
			{
				float num8 = ((Rect)(ref innerRect)).x + num2 + (float)i * (num4 + num);
				((Rect)(ref rect))..ctor(num8, ((Rect)(ref innerRect)).y + num2, num4, num5);
				DrawRect(rect, color);
				if (i < num6)
				{
					float num9 = (float)i / 17f;
					Color color3 = Color.Lerp(activeColor * 0.82f, activeColor * 1.08f, num9);
					color3.a = activeColor.a;
					DrawRect(rect, color3);
					DrawRect(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, ((Rect)(ref rect)).width, ((Rect)(ref rect)).height * 0.45f), color2);
					if (hudState.IsOn)
					{
						Rect rect2 = ExpandRect(rect, 1f * scale, 1f * scale);
						DrawRect(rect2, new Color(activeColor.r, activeColor.g, activeColor.b, num7 * 0.55f));
					}
				}
			}
			if (hudState.IsCharging && num6 > 0)
			{
				float num10 = Mathf.Max(10f * scale, num4 * 1.35f);
				float num11 = Mathf.Max(0f, num3 - num10);
				float num12 = ((Rect)(ref innerRect)).x + num2 + Mathf.Repeat(_displayedScan * num3, num11 + num);
				Rect rect3 = default(Rect);
				((Rect)(ref rect3))..ctor(num12, ((Rect)(ref innerRect)).y + num2, num10, num5);
				DrawRect(rect3, new Color(0.82f, 0.97f, 0.94f, 0.07f * alpha));
			}
		}

		private static float Damp(float current, float target, float speed, float deltaTime)
		{
			return Mathf.Lerp(current, target, 1f - Mathf.Exp((0f - speed) * deltaTime));
		}

		private Color GetActiveColor(FlashlightRuntime.HudState hudState)
		{
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: 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_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: 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)
			float num = Mathf.Lerp(0.62f, 0.88f, _displayedAlpha);
			if (hudState.IsOn)
			{
				float num2 = 0.5f + 0.5f * Mathf.Sin(Time.unscaledTime * 3.2f);
				Color val = Color.Lerp(new Color(0.87f, 0.55f, 0.22f, num), new Color(0.97f, 0.78f, 0.42f, num), num2 * 0.35f);
				if (_displayedBattery <= 0.25f)
				{
					float num3 = 0.5f + 0.5f * Mathf.Sin(Time.unscaledTime * 5.6f);
					val = Color.Lerp(new Color(0.82f, 0.24f, 0.19f, num), val, num3 * 0.5f);
				}
				return val;
			}
			return new Color(0.42f, 0.8f, 0.75f, num * 0.72f);
		}

		private void DrawRect(Rect rect, Color color)
		{
			//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)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			Color color2 = GUI.color;
			GUI.color = color;
			GUI.DrawTexture(rect, (Texture)(object)_pixel, (ScaleMode)0);
			GUI.color = color2;
		}

		private static Rect InsetRect(Rect rect, float horizontalInset, float verticalInset)
		{
			//IL_0031: 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_0039: Unknown result type (might be due to invalid IL or missing references)
			return new Rect(((Rect)(ref rect)).x + horizontalInset, ((Rect)(ref rect)).y + verticalInset, ((Rect)(ref rect)).width - horizontalInset * 2f, ((Rect)(ref rect)).height - verticalInset * 2f);
		}

		private static Rect ExpandRect(Rect rect, float horizontalExpand, float verticalExpand)
		{
			//IL_0031: 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_0039: Unknown result type (might be due to invalid IL or missing references)
			return new Rect(((Rect)(ref rect)).x - horizontalExpand, ((Rect)(ref rect)).y - verticalExpand, ((Rect)(ref rect)).width + horizontalExpand * 2f, ((Rect)(ref rect)).height + verticalExpand * 2f);
		}

		private static Texture2D CreatePixelTexture()
		{
			//IL_0005: 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_0013: 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)
			//IL_0024: Expected O, but got Unknown
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = new Texture2D(1, 1, (TextureFormat)4, false)
			{
				hideFlags = (HideFlags)61,
				filterMode = (FilterMode)1,
				wrapMode = (TextureWrapMode)1
			};
			val.SetPixel(0, 0, Color.white);
			val.Apply(false, true);
			return val;
		}
	}
	[HarmonyPatch(typeof(FlashlightController), "Update")]
	public static class FlashlightControllerUpdatePatch
	{
		private static bool Prefix(FlashlightController __instance)
		{
			FlashlightRuntime.CleanupDestroyedControllers();
			if (!__instance.PlayerAvatar.isLocal)
			{
				return true;
			}
			FlashlightRuntime.FlashlightState orCreateState = FlashlightRuntime.GetOrCreateState(__instance);
			if (SemiFunc.MenuLevel())
			{
				FlashlightRuntime.ResetForMenu(__instance, orCreateState);
				return false;
			}
			bool isOn = orCreateState.IsOn;
			FlashlightRuntime.HandleManualToggleInput(orCreateState);
			bool requestedState = FlashlightRuntime.CalculateRequestedState(__instance, orCreateState);
			FlashlightRuntime.FlashlightTransition transition = FlashlightRuntime.ApplyBatteryAndState(orCreateState, requestedState);
			FlashlightRuntime.PlayStateChangeAudio(__instance, isOn, transition);
			FlashlightRuntime.ApplyVisualState(__instance, orCreateState.IsOn);
			FlashlightRuntime.UpdateHudState(orCreateState);
			return false;
		}
	}
	internal static class FlashlightRuntime
	{
		internal sealed class FlashlightState
		{
			public bool ManualToggleState { get; set; }

			public bool IsOn { get; set; }

			public float BatteryRemaining { get; set; } = 10f;

		}

		internal readonly struct HudState
		{
			public static HudState Hidden => new HudState(shouldDisplay: false, isOn: false, isCharging: false, 1f, -1f);

			public bool ShouldDisplay { get; }

			public bool IsOn { get; }

			public bool IsCharging { get; }

			public float BatteryNormalized { get; }

			public float LastUpdatedTime { get; }

			public HudState(bool shouldDisplay, bool isOn, bool isCharging, float batteryNormalized, float lastUpdatedTime)
			{
				ShouldDisplay = shouldDisplay;
				IsOn = isOn;
				IsCharging = isCharging;
				BatteryNormalized = batteryNormalized;
				LastUpdatedTime = lastUpdatedTime;
			}
		}

		internal readonly struct FlashlightTransition
		{
			public bool TurnedOn { get; }

			public bool TurnedOffByDepletion { get; }

			public bool FinalState => TurnedOn && !TurnedOffByDepletion;

			public FlashlightTransition(bool turnedOn, bool turnedOffByDepletion)
			{
				TurnedOn = turnedOn;
				TurnedOffByDepletion = turnedOffByDepletion;
			}
		}

		private const float MaxBattery = 10f;

		private const float EnabledLightIntensity = 0.7f;

		private const int CleanupIntervalFrames = 300;

		private const float HudStateTimeout = 0.35f;

		private const int HudSegmentCount = 18;

		private const int MinimumActivationSegments = 3;

		private const float MinimumBatteryToEnable = 1.6666666f;

		private static readonly Dictionary<FlashlightController, FlashlightState> FlashlightStates = new Dictionary<FlashlightController, FlashlightState>();

		private static HudState _hudState = HudState.Hidden;

		internal static void CleanupDestroyedControllers()
		{
			if (Time.frameCount % 300 != 0 || FlashlightStates.Count == 0)
			{
				return;
			}
			List<FlashlightController> list = new List<FlashlightController>();
			foreach (FlashlightController key in FlashlightStates.Keys)
			{
				if ((Object)(object)key == (Object)null)
				{
					list.Add(key);
				}
			}
			foreach (FlashlightController item in list)
			{
				FlashlightStates.Remove(item);
			}
		}

		internal static void UpdateHudState(FlashlightState state)
		{
			float num = Mathf.Clamp01(state.BatteryRemaining / 10f);
			bool shouldDisplay = state.IsOn || num < 0.999f;
			bool isCharging = !state.IsOn && num < 0.999f;
			_hudState = new HudState(shouldDisplay, state.IsOn, isCharging, num, Time.unscaledTime);
		}

		internal static bool TryGetHudState(out HudState hudState)
		{
			if (SemiFunc.MenuLevel() || IsOverlayMenuOpen() || _hudState.LastUpdatedTime < 0f)
			{
				hudState = HudState.Hidden;
				return false;
			}
			if (Time.unscaledTime - _hudState.LastUpdatedTime > 0.35f)
			{
				hudState = HudState.Hidden;
				return false;
			}
			hudState = _hudState;
			return true;
		}

		private static bool IsOverlayMenuOpen()
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Invalid comparison between Unknown and I4
			return Cursor.visible || (int)Cursor.lockState != 1 || Time.timeScale <= 0f;
		}

		internal static HudState GetHudStateSnapshot()
		{
			HudState hudState;
			return TryGetHudState(out hudState) ? hudState : HudState.Hidden;
		}

		internal static FlashlightState GetOrCreateState(FlashlightController controller)
		{
			if (FlashlightStates.TryGetValue(controller, out FlashlightState value))
			{
				return value;
			}
			value = new FlashlightState();
			FlashlightStates[controller] = value;
			return value;
		}

		internal static void ResetForMenu(FlashlightController controller, FlashlightState state)
		{
			state.ManualToggleState = false;
			state.IsOn = false;
			state.BatteryRemaining = 10f;
			_hudState = HudState.Hidden;
			ApplyVisualState(controller, isOn: false);
		}

		internal static void HandleManualToggleInput(FlashlightState state)
		{
			if (Input.GetKeyDown((KeyCode)102))
			{
				state.ManualToggleState = !state.ManualToggleState;
			}
		}

		internal static bool CalculateRequestedState(FlashlightController controller, FlashlightState state)
		{
			if (controller.PlayerAvatar.isCrouching || Input.GetKey((KeyCode)113) || !state.ManualToggleState || state.BatteryRemaining <= 0f)
			{
				return false;
			}
			if (state.IsOn)
			{
				return true;
			}
			return state.BatteryRemaining >= 1.6666666f;
		}

		internal static FlashlightTransition ApplyBatteryAndState(FlashlightState state, bool requestedState)
		{
			state.IsOn = requestedState;
			bool turnedOn = requestedState;
			bool turnedOffByDepletion = false;
			if (requestedState)
			{
				state.BatteryRemaining = Mathf.Max(0f, state.BatteryRemaining - Time.deltaTime);
				if (state.BatteryRemaining <= 0f)
				{
					state.ManualToggleState = false;
					state.IsOn = false;
					turnedOffByDepletion = true;
				}
			}
			else if (state.BatteryRemaining < 10f)
			{
				state.BatteryRemaining = Mathf.Min(10f, state.BatteryRemaining + Time.deltaTime);
			}
			return new FlashlightTransition(turnedOn, turnedOffByDepletion);
		}

		internal static void PlayStateChangeAudio(FlashlightController controller, bool wasOn, FlashlightTransition transition)
		{
			//IL_0025: 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)
			if (!wasOn && transition.TurnedOn)
			{
				Sound lightOnAudio = controller.lightOnAudio;
				if (lightOnAudio != null)
				{
					lightOnAudio.Play(((Component)controller).transform.position, 1f, 1f, 1f, 1f);
				}
			}
			if ((wasOn || transition.TurnedOffByDepletion) && !transition.FinalState)
			{
				Sound lightOffAudio = controller.lightOffAudio;
				if (lightOffAudio != null)
				{
					lightOffAudio.Play(((Component)controller).transform.position, 1f, 1f, 1f, 1f);
				}
			}
		}

		internal static void ApplyVisualState(FlashlightController controller, bool isOn)
		{
			((Renderer)controller.mesh).enabled = true;
			((Behaviour)controller.spotlight).enabled = isOn;
			controller.halo.enabled = isOn;
			controller.LightActive = isOn;
			controller.spotlight.intensity = (isOn ? 0.7f : 0f);
		}
	}
}