Decompiled source of RemainingValueTracker v0.2.0

RemainingValueTracker.dll

Decompiled 15 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 BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("RemainingValueTracker")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.2.0.0")]
[assembly: AssemblyInformationalVersion("0.2.0+2c925949335c2da79fef1c985c0dd08932b688d0")]
[assembly: AssemblyProduct("RemainingValueTracker")]
[assembly: AssemblyTitle("RemainingValueTracker")]
[assembly: AssemblyVersion("0.2.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 RemainingValueTracker
{
	[BepInPlugin("DarkSpider90.RemainingValueTracker", "Remaining Value Tracker", "0.2.0")]
	public sealed class Plugin : BaseUnityPlugin
	{
		private sealed class ParsedShortcut
		{
			internal string Source;

			internal bool Disabled;

			internal KeyCode MainKey;

			internal KeyCode[] Modifiers;
		}

		private enum TrackingMode
		{
			Value,
			Count
		}

		private readonly struct TrackerProgress
		{
			internal static readonly TrackerProgress Empty = new TrackerProgress(0f, 0f);

			internal float Discovered { get; }

			internal float Total { get; }

			internal float Percent
			{
				get
				{
					if (!(Total <= 0f))
					{
						return Discovered / Total * 100f;
					}
					return 0f;
				}
			}

			internal bool HasData => Total > 0f;

			internal TrackerProgress(float discovered, float total)
			{
				Discovered = discovered;
				Total = total;
			}
		}

		internal const string PluginGuid = "DarkSpider90.RemainingValueTracker";

		internal const string PluginName = "Remaining Value Tracker";

		internal const string PluginVersion = "0.2.0";

		private const float DefaultScanInterval = 0.5f;

		private static readonly Color MessageColor = new Color(0.8f, 1f, 0.35f);

		private static readonly Color MessageFlashColor = new Color(1f, 1f, 0.2f);

		private static readonly Color MessageShadowColor = new Color(0f, 0f, 0f, 0.75f);

		private static readonly FieldRef<ValuableObject, bool> DiscoveredRef = AccessTools.FieldRefAccess<ValuableObject, bool>("discovered");

		private static readonly FieldRef<ValuableObject, bool> DollarValueSetRef = AccessTools.FieldRefAccess<ValuableObject, bool>("dollarValueSet");

		private static readonly FieldRef<ValuableObject, float> DollarValueOriginalRef = AccessTools.FieldRefAccess<ValuableObject, float>("dollarValueOriginal");

		private static readonly FieldRef<ValuableDiscoverCustom, bool> CustomDiscoveredRef = AccessTools.FieldRefAccess<ValuableDiscoverCustom, bool>("discovered");

		private ConfigEntry<bool> _enableMod;

		private ConfigEntry<TrackingMode> _trackingMode;

		private ConfigEntry<float> _triggerPercent;

		private ConfigEntry<float> _scanInterval;

		private ConfigEntry<string> _revealHotkey;

		private ConfigEntry<bool> _revealCosmeticBoxesWithValuables;

		private ConfigEntry<string> _revealCosmeticBoxesHotkey;

		private ConfigEntry<bool> _showMessage;

		private ConfigEntry<float> _messageDuration;

		private ConfigEntry<string> _messageText;

		private ConfigEntry<string> _cosmeticBoxesMessageText;

		private ConfigEntry<bool> _debugLogs;

		private readonly List<ValuableObject> _roundValuables = new List<ValuableObject>();

		private readonly Dictionary<int, float> _initialValues = new Dictionary<int, float>();

		private readonly HashSet<string> _invalidHotkeyWarnings = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

		private int _levelInstanceId;

		private bool _snapshotReady;

		private bool _revealed;

		private bool _cosmeticBoxesRevealed;

		private float _nextScanTime;

		private Coroutine _messageCoroutine;

		private GameObject _messageOverlay;

		private CanvasGroup _messageCanvasGroup;

		private TextMeshProUGUI _messageLabel;

		private TextMeshProUGUI _messageShadow;

		private bool _isQuitting;

		private static readonly KeyCode[] EmptyModifiers = (KeyCode[])(object)new KeyCode[0];

		private readonly Dictionary<ConfigEntry<string>, ParsedShortcut> _shortcutCache = new Dictionary<ConfigEntry<string>, ParsedShortcut>();

		internal static ManualLogSource Log { get; private set; }

		private void Awake()
		{
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Expected O, but got Unknown
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Expected O, but got Unknown
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			_enableMod = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enable Mod", true, "Master switch for Remaining Value Tracker.");
			_trackingMode = ((BaseUnityPlugin)this).Config.Bind<TrackingMode>("General", "Tracking Mode", TrackingMode.Value, "Value reveals remaining valuables after the configured percent of total value is discovered. Count uses item count instead.");
			_triggerPercent = ((BaseUnityPlugin)this).Config.Bind<float>("General", "Trigger Percent", 85f, new ConfigDescription("Percent of the round's valuables that must be discovered before all remaining valuables are revealed.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 100f), Array.Empty<object>()));
			_scanInterval = ((BaseUnityPlugin)this).Config.Bind<float>("General", "Scan Interval", 0.5f, new ConfigDescription("Seconds between tracker checks.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 5f), Array.Empty<object>()));
			_revealHotkey = ((BaseUnityPlugin)this).Config.Bind<string>("Controls", "Reveal Hotkey", "F10", "Key used to reveal all remaining valuables immediately. Use Unity KeyCode names, for example F10, F8, Mouse3, or LeftControl+F10. Set to None to disable.");
			_revealCosmeticBoxesHotkey = ((BaseUnityPlugin)this).Config.Bind<string>("Controls", "Reveal Cosmetic Boxes Hotkey", "F9", "Key used to reveal all cosmetic boxes immediately. Use Unity KeyCode names, for example F9, F7, Mouse4, or LeftControl+F9. Set to None to disable.");
			_revealCosmeticBoxesWithValuables = ((BaseUnityPlugin)this).Config.Bind<bool>("Cosmetic Boxes", "Reveal With Valuables", true, "Reveal all cosmetic boxes automatically when remaining valuables are revealed.");
			_showMessage = ((BaseUnityPlugin)this).Config.Bind<bool>("UI", "Show Message", true, "Show a top-center message when remaining valuables are revealed.");
			_messageDuration = ((BaseUnityPlugin)this).Config.Bind<float>("UI", "Message Duration", 4f, new ConfigDescription("Seconds to keep the reveal message visible.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 15f), Array.Empty<object>()));
			_messageText = ((BaseUnityPlugin)this).Config.Bind<string>("UI", "Message Text", "All remaining valuables discovered", "Message shown when the tracker reveals the remaining valuables.");
			_cosmeticBoxesMessageText = ((BaseUnityPlugin)this).Config.Bind<string>("UI", "Cosmetic Boxes Message Text", "All cosmetic boxes discovered", "Message shown when cosmetic boxes are revealed with the cosmetic boxes hotkey.");
			_debugLogs = ((BaseUnityPlugin)this).Config.Bind<bool>("Diagnostics", "Debug Logs", false, "Print tracker snapshot and reveal details to the BepInEx log.");
			((BaseUnityPlugin)this).Config.Save();
			Log.LogInfo((object)"Remaining Value Tracker v0.2.0 loaded for R.E.P.O. v0.4.0.");
		}

		private void OnApplicationQuit()
		{
			_isQuitting = true;
			CleanupMessageOverlay();
		}

		private void OnDestroy()
		{
			_isQuitting = true;
			CleanupMessageOverlay();
		}

		private void Update()
		{
			if (_isQuitting || !_enableMod.Value)
			{
				return;
			}
			if (!LevelIsReady())
			{
				ResetRound();
				return;
			}
			int instanceID = ((Object)LevelGenerator.Instance).GetInstanceID();
			if (_levelInstanceId != instanceID)
			{
				ResetRound(instanceID);
			}
			if (TryRevealByHotkey() || TryRevealCosmeticBoxesByHotkey() || _revealed || Time.time < _nextScanTime)
			{
				return;
			}
			_nextScanTime = Time.time + Mathf.Max(0.1f, _scanInterval.Value);
			if (!_snapshotReady && !TryBuildSnapshot())
			{
				return;
			}
			TrackerProgress trackerProgress = CalculateProgress();
			if (trackerProgress.HasData)
			{
				if (_debugLogs.Value)
				{
					Log.LogInfo((object)$"Progress: {trackerProgress.Percent:0.##}% by {_trackingMode.Value} ({trackerProgress.Discovered:0.##}/{trackerProgress.Total:0.##}).");
				}
				float num = Mathf.Clamp(_triggerPercent.Value, 1f, 100f);
				if (trackerProgress.Percent >= num)
				{
					Log.LogInfo((object)$"Reveal threshold reached: {trackerProgress.Percent:0.##}% >= {num:0.##}%.");
					RevealRemaining();
				}
			}
		}

		private bool TryRevealByHotkey()
		{
			if (_revealed || !IsConfiguredShortcutDown(_revealHotkey, (KeyCode)291, "Reveal Hotkey"))
			{
				return false;
			}
			if (!_snapshotReady && !TryBuildSnapshot())
			{
				Log.LogWarning((object)"Reveal hotkey was pressed, but valuables are not ready to scan yet.");
				return false;
			}
			Log.LogInfo((object)"Reveal hotkey pressed.");
			RevealRemaining();
			return true;
		}

		private static bool LevelIsReady()
		{
			try
			{
				return (Object)(object)RunManager.instance != (Object)null && (Object)(object)LevelGenerator.Instance != (Object)null && LevelGenerator.Instance.Generated && (Object)(object)ValuableDirector.instance != (Object)null && (Object)(object)RoundDirector.instance != (Object)null && (Object)(object)Map.Instance != (Object)null && SemiFunc.RunIsLevel();
			}
			catch (Exception)
			{
				return false;
			}
		}

		private bool TryBuildSnapshot()
		{
			ValuableObject[] array = Object.FindObjectsByType<ValuableObject>((FindObjectsSortMode)0);
			if (array == null || array.Length == 0)
			{
				return false;
			}
			List<ValuableObject> list = array.Where((ValuableObject valuable) => (Object)(object)valuable != (Object)null && ((Behaviour)valuable).isActiveAndEnabled).Distinct().ToList();
			if (list.Count == 0 || list.Any((ValuableObject valuable) => !DollarValueSetRef.Invoke(valuable)))
			{
				return false;
			}
			_roundValuables.Clear();
			_roundValuables.AddRange(list);
			_initialValues.Clear();
			foreach (ValuableObject roundValuable in _roundValuables)
			{
				_initialValues[((Object)roundValuable).GetInstanceID()] = Mathf.Max(0f, DollarValueOriginalRef.Invoke(roundValuable));
			}
			_snapshotReady = true;
			if (_debugLogs.Value)
			{
				float num = _initialValues.Values.Sum();
				Log.LogInfo((object)$"Snapshot ready: {_roundValuables.Count} valuables, total value {num:0}.");
			}
			return true;
		}

		private TrackerProgress CalculateProgress()
		{
			if (_roundValuables.Count == 0)
			{
				return TrackerProgress.Empty;
			}
			float num = 0f;
			float num2 = 0f;
			foreach (ValuableObject roundValuable in _roundValuables)
			{
				if ((Object)(object)roundValuable == (Object)null)
				{
					continue;
				}
				float value;
				if (_trackingMode.Value == TrackingMode.Count)
				{
					num2 += 1f;
					if (DiscoveredRef.Invoke(roundValuable))
					{
						num += 1f;
					}
				}
				else if (_initialValues.TryGetValue(((Object)roundValuable).GetInstanceID(), out value))
				{
					num2 += value;
					if (DiscoveredRef.Invoke(roundValuable))
					{
						num += value;
					}
				}
			}
			if (num2 <= 0f)
			{
				return TrackerProgress.Empty;
			}
			return new TrackerProgress(num, num2);
		}

		private void RevealRemaining()
		{
			_revealed = true;
			int num = 0;
			foreach (ValuableObject roundValuable in _roundValuables)
			{
				if (!((Object)(object)roundValuable == (Object)null) && !DiscoveredRef.Invoke(roundValuable))
				{
					try
					{
						roundValuable.Discover((State)0);
						num++;
					}
					catch (Exception ex)
					{
						Log.LogWarning((object)("Could not reveal " + ((Object)roundValuable).name + ": " + ex.Message));
					}
				}
			}
			int num2 = 0;
			if (_revealCosmeticBoxesWithValuables.Value)
			{
				num2 = RevealCosmeticBoxes(showMessage: false);
			}
			if (_showMessage.Value)
			{
				ShowRevealMessage(_messageText.Value);
			}
			Log.LogInfo((object)$"Revealed {num} remaining valuables.");
			if (_revealCosmeticBoxesWithValuables.Value)
			{
				Log.LogInfo((object)$"Revealed {num2} cosmetic boxes with valuables.");
			}
		}

		private bool TryRevealCosmeticBoxesByHotkey()
		{
			if (_cosmeticBoxesRevealed || !IsConfiguredShortcutDown(_revealCosmeticBoxesHotkey, (KeyCode)290, "Reveal Cosmetic Boxes Hotkey"))
			{
				return false;
			}
			Log.LogInfo((object)"Cosmetic boxes reveal hotkey pressed.");
			RevealCosmeticBoxes(showMessage: true);
			return true;
		}

		private int RevealCosmeticBoxes(bool showMessage)
		{
			List<CosmeticWorldObject> list = FindActiveCosmeticBoxes();
			if (list.Count == 0)
			{
				Log.LogInfo((object)"No active cosmetic boxes found to reveal.");
				return 0;
			}
			_cosmeticBoxesRevealed = true;
			int num = 0;
			foreach (CosmeticWorldObject item in list)
			{
				ValuableDiscoverCustom val = (((Object)(object)item != (Object)null) ? ((Component)item).GetComponent<ValuableDiscoverCustom>() : null);
				if ((Object)(object)val == (Object)null || CustomDiscoveredRef.Invoke(val))
				{
					continue;
				}
				try
				{
					if (val.Discover())
					{
						num++;
					}
				}
				catch (Exception ex)
				{
					Log.LogWarning((object)("Could not reveal cosmetic box " + ((Object)item).name + ": " + ex.Message));
				}
			}
			if (showMessage && _showMessage.Value)
			{
				ShowRevealMessage(_cosmeticBoxesMessageText.Value);
			}
			Log.LogInfo((object)$"Revealed {num} cosmetic boxes.");
			return num;
		}

		private bool IsConfiguredShortcutDown(ConfigEntry<string> entry, KeyCode fallbackKey, string settingName)
		{
			//IL_0002: 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)
			ParsedShortcut parsedShortcut = ResolveShortcut(entry, fallbackKey, settingName);
			if (parsedShortcut.Disabled || !Input.GetKeyDown(parsedShortcut.MainKey))
			{
				return false;
			}
			KeyCode[] modifiers = parsedShortcut.Modifiers;
			for (int i = 0; i < modifiers.Length; i++)
			{
				if (!Input.GetKey(modifiers[i]))
				{
					return false;
				}
			}
			return true;
		}

		private unsafe ParsedShortcut ResolveShortcut(ConfigEntry<string> entry, KeyCode fallbackKey, string settingName)
		{
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: 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_008b: Unknown result type (might be due to invalid IL or missing references)
			string value = entry.Value;
			if (_shortcutCache.TryGetValue(entry, out var value2) && string.Equals(value2.Source, value, StringComparison.Ordinal))
			{
				return value2;
			}
			ParsedShortcut parsedShortcut = new ParsedShortcut
			{
				Source = value,
				Modifiers = EmptyModifiers
			};
			string value3 = value?.Trim();
			if (string.IsNullOrWhiteSpace(value3))
			{
				value3 = ((object)(*(KeyCode*)(&fallbackKey))/*cast due to .constrained prefix*/).ToString();
			}
			if (IsDisabledShortcut(value3))
			{
				parsedShortcut.Disabled = true;
			}
			else
			{
				if (!TryParseShortcut(value3, fallbackKey, out var mainKey, out var modifiers))
				{
					WarnInvalidHotkey(settingName, value3, fallbackKey);
					mainKey = fallbackKey;
					modifiers.Clear();
				}
				parsedShortcut.MainKey = mainKey;
				parsedShortcut.Modifiers = ((modifiers.Count == 0) ? EmptyModifiers : modifiers.ToArray());
			}
			_shortcutCache[entry] = parsedShortcut;
			return parsedShortcut;
		}

		private static bool TryParseShortcut(string value, KeyCode fallbackKey, out KeyCode mainKey, out List<KeyCode> modifiers)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Expected I4, but got Unknown
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Expected I4, but got Unknown
			mainKey = (KeyCode)(int)fallbackKey;
			modifiers = new List<KeyCode>();
			string[] array = (from part in value.Split(new char[1] { '+' }, StringSplitOptions.RemoveEmptyEntries)
				select part.Trim() into part
				where !string.IsNullOrWhiteSpace(part)
				select part).ToArray();
			if (array.Length == 0)
			{
				return false;
			}
			for (int num = 0; num < array.Length; num++)
			{
				if (!TryParseKeyCode(array[num], out var key))
				{
					return false;
				}
				if (num == array.Length - 1)
				{
					mainKey = (KeyCode)(int)key;
				}
				else
				{
					modifiers.Add(key);
				}
			}
			return true;
		}

		private static bool TryParseKeyCode(string value, out KeyCode key)
		{
			string text = value.Replace(" ", string.Empty).Replace("-", string.Empty).Replace("_", string.Empty);
			switch (text.ToLowerInvariant())
			{
			case "control":
			case "leftctrl":
			case "ctrl":
			case "leftcontrol":
				key = (KeyCode)306;
				return true;
			case "rightctrl":
			case "rightcontrol":
				key = (KeyCode)305;
				return true;
			case "leftshift":
			case "shift":
				key = (KeyCode)304;
				return true;
			case "rightshift":
				key = (KeyCode)303;
				return true;
			case "leftalt":
			case "alt":
				key = (KeyCode)308;
				return true;
			case "rightalt":
				key = (KeyCode)307;
				return true;
			default:
				if (!Enum.TryParse<KeyCode>(value, ignoreCase: true, out key))
				{
					return Enum.TryParse<KeyCode>(text, ignoreCase: true, out key);
				}
				return true;
			}
		}

		private static bool IsDisabledShortcut(string value)
		{
			if (!value.Equals("None", StringComparison.OrdinalIgnoreCase) && !value.Equals("Off", StringComparison.OrdinalIgnoreCase))
			{
				return value.Equals("Disabled", StringComparison.OrdinalIgnoreCase);
			}
			return true;
		}

		private void WarnInvalidHotkey(string settingName, string value, KeyCode fallbackKey)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			string item = settingName + ":" + value;
			if (_invalidHotkeyWarnings.Add(item))
			{
				Log.LogWarning((object)$"Invalid {settingName} value '{value}'. Falling back to {fallbackKey}.");
			}
		}

		private static List<CosmeticWorldObject> FindActiveCosmeticBoxes()
		{
			IEnumerable<CosmeticWorldObject> enumerable = RoundDirector.instance?.cosmeticWorldObjects;
			if (enumerable == null || !enumerable.Any())
			{
				enumerable = Object.FindObjectsByType<CosmeticWorldObject>((FindObjectsSortMode)0) ?? Array.Empty<CosmeticWorldObject>();
			}
			return enumerable.Where((CosmeticWorldObject box) => (Object)(object)box != (Object)null && ((Behaviour)box).isActiveAndEnabled && ((Component)box).gameObject.activeInHierarchy).Distinct().ToList();
		}

		private void ShowRevealMessage(string message)
		{
			if (!_isQuitting)
			{
				if (_messageCoroutine != null)
				{
					((MonoBehaviour)this).StopCoroutine(_messageCoroutine);
				}
				_messageCoroutine = ((MonoBehaviour)this).StartCoroutine(ShowRevealMessageRoutine(message));
			}
		}

		private IEnumerator ShowRevealMessageRoutine(string message)
		{
			EnsureMessageOverlay();
			float duration = Mathf.Clamp(_messageDuration.Value, 0.5f, 15f);
			float endTime = Time.time + duration;
			float fadeIn = Mathf.Min(0.2f, duration * 0.25f);
			float fadeOut = Mathf.Min(0.35f, duration * 0.3f);
			SetOverlayText(message);
			_messageOverlay.SetActive(true);
			Log.LogInfo((object)$"Showing reveal message for {duration:0.##}s.");
			while (Time.time < endTime)
			{
				float num = duration - (endTime - Time.time);
				float num2 = endTime - Time.time;
				float alpha = 1f;
				if (fadeIn > 0f && num < fadeIn)
				{
					alpha = Mathf.Clamp01(num / fadeIn);
				}
				else if (fadeOut > 0f && num2 < fadeOut)
				{
					alpha = Mathf.Clamp01(num2 / fadeOut);
				}
				_messageCanvasGroup.alpha = alpha;
				yield return null;
			}
			_messageCanvasGroup.alpha = 0f;
			_messageOverlay.SetActive(false);
			_messageCoroutine = null;
		}

		private void EnsureMessageOverlay()
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_messageOverlay != (Object)null))
			{
				_messageOverlay = new GameObject("RemainingValueTracker Message Overlay");
				Object.DontDestroyOnLoad((Object)(object)_messageOverlay);
				Canvas obj = _messageOverlay.AddComponent<Canvas>();
				obj.renderMode = (RenderMode)0;
				obj.sortingOrder = 32760;
				CanvasScaler obj2 = _messageOverlay.AddComponent<CanvasScaler>();
				obj2.uiScaleMode = (ScaleMode)1;
				obj2.referenceResolution = new Vector2(1920f, 1080f);
				obj2.matchWidthOrHeight = 0.5f;
				_messageCanvasGroup = _messageOverlay.AddComponent<CanvasGroup>();
				_messageCanvasGroup.blocksRaycasts = false;
				_messageCanvasGroup.interactable = false;
				_messageShadow = CreateOverlayText("Message Shadow", MessageShadowColor, new Vector2(2f, -2f));
				_messageLabel = CreateOverlayText("Message", MessageColor, Vector2.zero);
				_messageOverlay.SetActive(false);
			}
		}

		private TextMeshProUGUI CreateOverlayText(string name, Color color, Vector2 offset)
		{
			//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_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: 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_00e0: 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)
			GameObject val = new GameObject(name);
			val.transform.SetParent(_messageOverlay.transform, false);
			TextMeshProUGUI val2 = val.AddComponent<TextMeshProUGUI>();
			((Graphic)val2).raycastTarget = false;
			((TMP_Text)val2).alignment = (TextAlignmentOptions)514;
			((TMP_Text)val2).fontStyle = (FontStyles)1;
			((Graphic)val2).color = color;
			((TMP_Text)val2).fontSize = 36f;
			((TMP_Text)val2).enableAutoSizing = true;
			((TMP_Text)val2).fontSizeMin = 18f;
			((TMP_Text)val2).fontSizeMax = 38f;
			((TMP_Text)val2).textWrappingMode = (TextWrappingModes)1;
			TMP_FontAsset val3 = FindExistingFont();
			if ((Object)(object)val3 != (Object)null)
			{
				((TMP_Text)val2).font = val3;
			}
			RectTransform rectTransform = ((TMP_Text)val2).rectTransform;
			rectTransform.anchorMin = new Vector2(0.5f, 1f);
			rectTransform.anchorMax = new Vector2(0.5f, 1f);
			rectTransform.pivot = new Vector2(0.5f, 1f);
			rectTransform.anchoredPosition = new Vector2(offset.x, -95f + offset.y);
			rectTransform.sizeDelta = new Vector2(1200f, 96f);
			return val2;
		}

		private static TMP_FontAsset FindExistingFont()
		{
			TextMeshProUGUI val = Object.FindAnyObjectByType<TextMeshProUGUI>();
			if (!((Object)(object)val != (Object)null))
			{
				return null;
			}
			return ((TMP_Text)val).font;
		}

		private void SetOverlayText(string message)
		{
			((TMP_Text)_messageLabel).text = message;
			((TMP_Text)_messageShadow).text = message;
		}

		private void ResetRound(int levelInstanceId = 0)
		{
			StopMessageCoroutine();
			_levelInstanceId = levelInstanceId;
			_snapshotReady = false;
			_revealed = false;
			_cosmeticBoxesRevealed = false;
			_nextScanTime = 0f;
			_roundValuables.Clear();
			_initialValues.Clear();
		}

		private void StopMessageCoroutine()
		{
			if (_messageCoroutine != null)
			{
				((MonoBehaviour)this).StopCoroutine(_messageCoroutine);
				_messageCoroutine = null;
			}
		}

		private void CleanupMessageOverlay()
		{
			StopMessageCoroutine();
			if (!((Object)(object)_messageOverlay == (Object)null))
			{
				Object.Destroy((Object)(object)_messageOverlay);
				_messageOverlay = null;
				_messageCanvasGroup = null;
				_messageLabel = null;
				_messageShadow = null;
			}
		}
	}
}