Decompiled source of UsefullInfoUI v1.2.0

UsefullInfoUI.dll

Decompiled 2 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using Assets.Scripts.Actors.Player;
using Assets.Scripts.Inventory__Items__Pickups.Chests;
using Assets.Scripts.Inventory__Items__Pickups.Stats;
using Assets.Scripts.Menu.Shop;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using HarmonyLib;
using Il2CppInterop.Runtime.Injection;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("UsefullInfoUI")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("UsefullInfoUI")]
[assembly: AssemblyCopyright("Copyright ©  2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("18eb221b-ea9f-4bc0-add2-adbebf2000b0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.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.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace MegabonkRunInfo
{
	internal enum RunInfoKey
	{
		Shrines,
		Chests,
		Vendors,
		Microwaves,
		MoaiOnly,
		MoaiAndGreed,
		Challenge,
		Magnet,
		Cursed
	}
	internal static class UIConfig
	{
		private static ConfigFile _cfg;

		private static ConfigEntry<string> _readme;

		private static ConfigEntry<string> _defaultStatsCsv;

		private static ConfigEntry<string> _detailedStatsCsv;

		private static ConfigEntry<string> _defaultRunCsv;

		private static ConfigEntry<string> _detailedRunCsv;

		private static ConfigEntry<float> _runInfoScale;

		private static ConfigEntry<float> _playerStatsScale;

		private static readonly StatsKey[] FALLBACK_STATS_DEFAULT = new StatsKey[5]
		{
			StatsKey.Damage,
			StatsKey.AttackSpeed,
			StatsKey.Luck,
			StatsKey.Difficulty,
			StatsKey.XpGain
		};

		private static readonly StatsKey[] FALLBACK_STATS_DETAILED = new StatsKey[12]
		{
			StatsKey.Damage,
			StatsKey.CritChance,
			StatsKey.CritDamage,
			StatsKey.AttackSpeed,
			StatsKey.Lifesteal,
			StatsKey.Projectiles,
			StatsKey.ExtraJumps,
			StatsKey.Luck,
			StatsKey.Difficulty,
			StatsKey.MoveSpeed,
			StatsKey.XpGain,
			StatsKey.GoldGain
		};

		private static readonly RunInfoKey[] FALLBACK_RUN_DEFAULT = new RunInfoKey[4]
		{
			RunInfoKey.Shrines,
			RunInfoKey.Chests,
			RunInfoKey.Vendors,
			RunInfoKey.MoaiOnly
		};

		private static readonly RunInfoKey[] FALLBACK_RUN_DETAILED = new RunInfoKey[8]
		{
			RunInfoKey.Shrines,
			RunInfoKey.Chests,
			RunInfoKey.Vendors,
			RunInfoKey.Microwaves,
			RunInfoKey.MoaiAndGreed,
			RunInfoKey.Challenge,
			RunInfoKey.Magnet,
			RunInfoKey.Cursed
		};

		public static void Init()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Expected O, but got Unknown
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Expected O, but got Unknown
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Expected O, but got Unknown
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Expected O, but got Unknown
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Expected O, but got Unknown
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Expected O, but got Unknown
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Expected O, but got Unknown
			_cfg = new ConfigFile(Path.Combine(PathsBridge.UserDataDir, "UsefulInfoUI.cfg"), true);
			ConfigDescription val = new ConfigDescription("One config controls everything (F1 cycles Default → Detailed → Hidden). Press Ctrl+R to hot-reload the config.", (AcceptableValueBase)null, Array.Empty<object>());
			_readme = _cfg.Bind<string>("UsefulInfoUI", "Readme", "See description above", val);
			ConfigDescription val2 = new ConfigDescription("Useful Info UI shows a compact overlay with Run Info on the left (Shrines, Chests, Vendors, etc.) and Player Stats on the right (Damage, Crit, Attack Speed, Luck, XP/Gold gain).\n\nShortcuts:\n  • F1 – Toggle overlay state (Default → Detailed → Hidden)\n  • Ctrl+R – Hot reload the config from disk\n  • Ctrl+Up – Increase both Run Info and Player Stats scale\n  • Ctrl+Down – Decrease both Run Info and Player Stats scale\n\nRun Info variables (case-insensitive):\n  • Shrines – Charge shrines (common + legendary)\n  • Chests – Normal + free chests\n  • Vendors – Shady Guy counts by rarity (common/rare/epic/legendary)\n  • Microwaves – Microwave counts by rarity (common/rare/epic/legendary)\n  • MoaiOnly – Only Moai shrine count\n  • MoaiAndGreed – Moai and Greed counts together\n  • Challenge – Challenge shrine count\n  • Magnet – Magnet shrine count\n  • Cursed – Cursed shrine count", (AcceptableValueBase)null, Array.Empty<object>());
			_defaultRunCsv = _cfg.Bind<string>("UsefulInfoUI", "DefaultRunInfoOrder", "Shrines,Chests,Vendors,MoaiOnly", val2);
			_detailedRunCsv = _cfg.Bind<string>("UsefulInfoUI", "DetailedRunInfoOrder", "Shrines,Chests,Vendors,Microwaves,MoaiAndGreed,Challenge,Magnet,Cursed", new ConfigDescription("DETAILED state - Run Info rows", (AcceptableValueBase)null, Array.Empty<object>()));
			_runInfoScale = _cfg.Bind<float>("UsefulInfoUI", "RunInfoScale", 1f, new ConfigDescription("Run Info scale (Ctrl+Up/Down)", (AcceptableValueBase)null, Array.Empty<object>()));
			ConfigDescription val3 = new ConfigDescription("Player Stats variables (case-insensitive):\n  • Preset-colored: Damage, CritChance, CritDamage, AttackSpeed, Lifesteal, Projectiles, ExtraJumps, Luck, Difficulty, MoveSpeed, XpGain, GoldGain\n  • Full list:\n    MaxHealth, HealthRegen, Shield, Thorns, Armor, Evasion, Lifesteal, CritChance, CritDamage,\n    DamageReductionMultiplier, DamageCooldownMultiplier, SizeMultiplier, DurationMultiplier, DamageMultiplier,\n    EffectDurationMultiplier, AttackSpeed, Projectiles, ProjectileSpeedMultiplier, EliteDamageMultiplier,\n    KnockbackMultiplier, MoveSpeedMultiplier, JumpHeight, PickupRange, Luck, GoldIncreaseMultiplier,\n    XpIncreaseMultiplier, Difficulty, EliteSpawnIncrease, BurnChance, FreezeChance, PowerupBoostMultiplier,\n    PowerupChance, WeaponBurstCooldown, ProjectileBounces, ExtraJumps, Overheal, HealingMultiplier, SilverIncreaseMultiplier", (AcceptableValueBase)null, Array.Empty<object>());
			_defaultStatsCsv = _cfg.Bind<string>("UsefulInfoUI", "DefaultStatsOrder", "Damage,AttackSpeed,Luck,Difficulty,XpGain", val3);
			_detailedStatsCsv = _cfg.Bind<string>("UsefulInfoUI", "DetailedStatsOrder", "Damage,CritChance,CritDamage,AttackSpeed,Lifesteal,Projectiles,ExtraJumps,Luck,Difficulty,MoveSpeed,XpGain,GoldGain", new ConfigDescription("DETAILED state - Player Stats order", (AcceptableValueBase)null, Array.Empty<object>()));
			_playerStatsScale = _cfg.Bind<float>("UsefulInfoUI", "PlayerStatsScale", 1f, new ConfigDescription("Player Stats scale (Ctrl+Up/Down)", (AcceptableValueBase)null, Array.Empty<object>()));
		}

		public static void ReloadFromDisk()
		{
			try
			{
				ConfigFile cfg = _cfg;
				if (cfg != null)
				{
					cfg.Reload();
				}
				LoggerBridge.Info("[UsefulInfoUI] Config reloaded from disk.");
			}
			catch (Exception ex)
			{
				LoggerBridge.Warn("[UsefulInfoUI] Failed to reload config: " + ex.Message);
			}
		}

		public static StatsKey[] GetPlayerStatsOrder(int state)
		{
			StatsKey[] array = ParseStats(((state == 2) ? Get(_detailedStatsCsv) : Get(_defaultStatsCsv)) ?? string.Empty);
			if (array.Length != 0)
			{
				return array;
			}
			if (state != 2)
			{
				return FALLBACK_STATS_DEFAULT;
			}
			return FALLBACK_STATS_DETAILED;
		}

		public static RunInfoKey[] GetRunInfoOrder(int state)
		{
			RunInfoKey[] array = ParseRun(((state == 2) ? Get(_detailedRunCsv) : Get(_defaultRunCsv)) ?? string.Empty);
			if (array.Length != 0)
			{
				return array;
			}
			if (state != 2)
			{
				return FALLBACK_RUN_DEFAULT;
			}
			return FALLBACK_RUN_DETAILED;
		}

		private static string Get(object entry)
		{
			return (entry as ConfigEntry<string>)?.Value;
		}

		private static StatsKey[] ParseStats(string csv)
		{
			if (string.IsNullOrWhiteSpace(csv))
			{
				return Array.Empty<StatsKey>();
			}
			List<StatsKey> list = new List<StatsKey>();
			foreach (string item in from s in csv.Split(new char[3] { ',', ';', '|' }, StringSplitOptions.RemoveEmptyEntries)
				select s.Trim())
			{
				if (StatsCatalog.TryResolveKey(item, out var key))
				{
					if (!list.Contains(key))
					{
						list.Add(key);
					}
				}
				else
				{
					LoggerBridge.Warn("[UsefulInfoUI] Unknown Player Stat key: '" + item + "'. Ignored.");
				}
			}
			return list.ToArray();
		}

		private static RunInfoKey[] ParseRun(string csv)
		{
			if (string.IsNullOrWhiteSpace(csv))
			{
				return Array.Empty<RunInfoKey>();
			}
			List<RunInfoKey> list = new List<RunInfoKey>();
			foreach (string item in from s in csv.Split(new char[3] { ',', ';', '|' }, StringSplitOptions.RemoveEmptyEntries)
				select s.Trim())
			{
				if (Enum.TryParse<RunInfoKey>(item, ignoreCase: true, out var result))
				{
					if (!list.Contains(result))
					{
						list.Add(result);
					}
				}
				else
				{
					LoggerBridge.Warn("[UsefulInfoUI] Unknown Run Info key: '" + item + "'. Ignored.");
				}
			}
			return list.ToArray();
		}

		public static float GetRunInfoScale()
		{
			return _runInfoScale?.Value ?? 1f;
		}

		public static float GetPlayerStatsScale()
		{
			return _playerStatsScale?.Value ?? 1f;
		}

		public static void SetRunInfoScale(float v, bool save)
		{
			if (_runInfoScale != null)
			{
				_runInfoScale.Value = v;
			}
			if (save)
			{
				ConfigFile cfg = _cfg;
				if (cfg != null)
				{
					cfg.Save();
				}
			}
		}

		public static void SetPlayerStatsScale(float v, bool save)
		{
			if (_playerStatsScale != null)
			{
				_playerStatsScale.Value = v;
			}
			if (save)
			{
				ConfigFile cfg = _cfg;
				if (cfg != null)
				{
					cfg.Save();
				}
			}
		}
	}
	public sealed class UsefulInfoUICore
	{
		private TextMeshProUGUI _overlayText;

		private Text _overlayFallback;

		private GameObject _overlayObj;

		private TextMeshProUGUI _playerStatsText;

		private GameObject _playerStatsObj;

		private GameObject _hud;

		private int _toggleState = 1;

		private int _commonShrineCount;

		private int _legendaryShrineCount;

		private int _normalChestCount;

		private int _freeChestCount;

		private int _moaiShrineCount;

		private int _commonVendorCount;

		private int _rareVendorCount;

		private int _epicVendorCount;

		private int _legendaryVendorCount;

		private int _commonMicrowaveCount;

		private int _rareMicrowaveCount;

		private int _epicMicrowaveCount;

		private int _legendaryMicrowaveCount;

		private int _magnetShrineCount;

		private int _cursedShrineCount;

		private int _challengeShrineCount;

		private int _greedShrineCount;

		private const float WORLD_POLL_INTERVAL = 0.5f;

		private const float STATS_POLL_INTERVAL = 0.25f;

		private float _nextWorldPoll;

		private float _nextStatsPoll;

		private bool _countsDirty;

		private bool _toggleDirty;

		private bool _overlayBuiltOnce;

		private Harmony _harmony;

		private float _runInfoScale = 1f;

		private float _playerStatsScale = 1f;

		private const float SCALE_STEP = 0.05f;

		private const float SCALE_MIN = 0.1f;

		private const float SCALE_MAX = 5f;

		public static UsefulInfoUICore Instance { get; private set; }

		public event Action OnRunInfoChanged;

		public void Init()
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Expected O, but got Unknown
			Instance = this;
			UIConfig.Init();
			OnRunInfoChanged += UpdateRunInfo;
			try
			{
				_harmony = new Harmony("Maskoliver.UsefulInfoUI");
				_harmony.PatchAll();
				LoggerBridge.Info("Harmony patches applied.");
			}
			catch (Exception ex)
			{
				LoggerBridge.Warn("Harmony patching failed: " + ex.Message);
			}
			_runInfoScale = Mathf.Clamp(UIConfig.GetRunInfoScale(), 0.1f, 5f);
			_playerStatsScale = Mathf.Clamp(UIConfig.GetPlayerStatsScale(), 0.1f, 5f);
			LoggerBridge.Info("Useful Info UI initialized!");
		}

		public void OnSceneLoaded(int buildIndex, string sceneName)
		{
			_overlayText = null;
			_overlayFallback = null;
			_overlayObj = null;
			_playerStatsText = null;
			_playerStatsObj = null;
			_hud = null;
			_toggleState = 1;
			_commonShrineCount = (_legendaryShrineCount = (_normalChestCount = (_freeChestCount = (_moaiShrineCount = 0))));
			_commonVendorCount = (_rareVendorCount = (_epicVendorCount = (_legendaryVendorCount = 0)));
			_commonMicrowaveCount = (_rareMicrowaveCount = (_epicMicrowaveCount = (_legendaryMicrowaveCount = 0)));
			_magnetShrineCount = (_cursedShrineCount = (_challengeShrineCount = (_greedShrineCount = 0)));
			_countsDirty = true;
			_toggleDirty = true;
			_overlayBuiltOnce = false;
			_nextWorldPoll = 0f;
			_nextStatsPoll = 0f;
		}

		public void UpdateLoop()
		{
			HandleToggleKey();
			HandleScaleKeys();
			HandleHotReloadKey();
			if ((Object)(object)_overlayObj == (Object)null && (Object)(object)GetHud() != (Object)null)
			{
				CreateOverlayUI();
			}
			if ((Object)(object)_playerStatsObj == (Object)null && (Object)(object)GetHud() != (Object)null)
			{
				CreatePlayerStatsUI();
			}
			InvokeRunInfoChanged();
		}

		public void InvokeRunInfoChanged()
		{
			this.OnRunInfoChanged?.Invoke();
		}

		private static string Z(int v)
		{
			if (v != 0)
			{
				return v.ToString();
			}
			return "-";
		}

		private void UpdateRunInfo()
		{
			float unscaledTime = Time.unscaledTime;
			bool flag = _countsDirty || _toggleDirty || !_overlayBuiltOnce || unscaledTime >= _nextWorldPoll;
			bool flag2 = _toggleDirty || !_overlayBuiltOnce || unscaledTime >= _nextStatsPoll;
			if (flag || flag2)
			{
				UpdateRunInfo(flag, flag2);
				if (flag)
				{
					_countsDirty = false;
					_nextWorldPoll = unscaledTime + 0.5f;
					_overlayBuiltOnce = true;
				}
				if (flag2)
				{
					_nextStatsPoll = unscaledTime + 0.25f;
				}
				_toggleDirty = false;
			}
		}

		private void UpdateRunInfo(bool recountWorld, bool updateStats)
		{
			//IL_0570: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_overlayText == (Object)null && (Object)(object)_overlayFallback == (Object)null && (Object)(object)_playerStatsText == (Object)null)
			{
				return;
			}
			bool flag = false;
			if (recountWorld)
			{
				Il2CppArrayBase<ChargeShrine> source = Object.FindObjectsByType<ChargeShrine>((FindObjectsSortMode)0);
				Il2CppArrayBase<InteractableChest> source2 = Object.FindObjectsByType<InteractableChest>((FindObjectsSortMode)0);
				Il2CppArrayBase<InteractableShrineMoai> source3 = Object.FindObjectsByType<InteractableShrineMoai>((FindObjectsSortMode)0);
				Il2CppArrayBase<InteractableShadyGuy> source4 = Object.FindObjectsByType<InteractableShadyGuy>((FindObjectsSortMode)0);
				Il2CppArrayBase<InteractableShrineMagnet> source5 = Object.FindObjectsByType<InteractableShrineMagnet>((FindObjectsSortMode)0);
				Il2CppArrayBase<InteractableShrineCursed> source6 = Object.FindObjectsByType<InteractableShrineCursed>((FindObjectsSortMode)0);
				Il2CppArrayBase<InteractableShrineChallenge> source7 = Object.FindObjectsByType<InteractableShrineChallenge>((FindObjectsSortMode)0);
				Il2CppArrayBase<InteractableShrineGreed> source8 = Object.FindObjectsByType<InteractableShrineGreed>((FindObjectsSortMode)0);
				Il2CppArrayBase<InteractableMicrowave> source9 = Object.FindObjectsByType<InteractableMicrowave>((FindObjectsSortMode)0);
				int value = ((IEnumerable<ChargeShrine>)source).Count((ChargeShrine x) => !x.completed && !x.isGolden);
				int value2 = ((IEnumerable<ChargeShrine>)source).Count((ChargeShrine x) => !x.completed && x.isGolden);
				int value3 = ((IEnumerable<InteractableChest>)source2).Count((InteractableChest x) => !((Il2CppObjectBase)x).WasCollected && (int)x.chestType == 0);
				int value4 = ((IEnumerable<InteractableChest>)source2).Count((InteractableChest x) => !((Il2CppObjectBase)x).WasCollected && (int)x.chestType == 2);
				int value5 = ((IEnumerable<InteractableShrineMoai>)source3).Count((InteractableShrineMoai x) => !x.done);
				int value6 = ((IEnumerable<InteractableShadyGuy>)source4).Count((InteractableShadyGuy x) => !x.done && (int)x.rarity == 0);
				int value7 = ((IEnumerable<InteractableShadyGuy>)source4).Count((InteractableShadyGuy x) => !x.done && (int)x.rarity == 1);
				int value8 = ((IEnumerable<InteractableShadyGuy>)source4).Count((InteractableShadyGuy x) => !x.done && (int)x.rarity == 2);
				int value9 = ((IEnumerable<InteractableShadyGuy>)source4).Count((InteractableShadyGuy x) => !x.done && (int)x.rarity == 3);
				int value10 = ((IEnumerable<InteractableMicrowave>)source9).Count((InteractableMicrowave x) => x.usesLeft > 0 && (int)x.rarity == 0);
				int value11 = ((IEnumerable<InteractableMicrowave>)source9).Count((InteractableMicrowave x) => x.usesLeft > 0 && (int)x.rarity == 1);
				int value12 = ((IEnumerable<InteractableMicrowave>)source9).Count((InteractableMicrowave x) => x.usesLeft > 0 && (int)x.rarity == 2);
				int value13 = ((IEnumerable<InteractableMicrowave>)source9).Count((InteractableMicrowave x) => x.usesLeft > 0 && (int)x.rarity == 3);
				int value14 = ((IEnumerable<InteractableShrineMagnet>)source5).Count((InteractableShrineMagnet x) => !x.done);
				int value15 = ((IEnumerable<InteractableShrineCursed>)source6).Count((InteractableShrineCursed x) => !x.done);
				int value16 = ((IEnumerable<InteractableShrineChallenge>)source7).Count((InteractableShrineChallenge x) => !x.done);
				int value17 = ((IEnumerable<InteractableShrineGreed>)source8).Count((InteractableShrineGreed x) => !x.done);
				flag |= UpdateIfChanged(ref _commonShrineCount, value);
				flag |= UpdateIfChanged(ref _legendaryShrineCount, value2);
				flag |= UpdateIfChanged(ref _normalChestCount, value3);
				flag |= UpdateIfChanged(ref _freeChestCount, value4);
				flag |= UpdateIfChanged(ref _moaiShrineCount, value5);
				flag |= UpdateIfChanged(ref _commonVendorCount, value6);
				flag |= UpdateIfChanged(ref _rareVendorCount, value7);
				flag |= UpdateIfChanged(ref _epicVendorCount, value8);
				flag |= UpdateIfChanged(ref _legendaryVendorCount, value9);
				flag |= UpdateIfChanged(ref _commonMicrowaveCount, value10);
				flag |= UpdateIfChanged(ref _rareMicrowaveCount, value11);
				flag |= UpdateIfChanged(ref _epicMicrowaveCount, value12);
				flag |= UpdateIfChanged(ref _legendaryMicrowaveCount, value13);
				flag |= UpdateIfChanged(ref _magnetShrineCount, value14);
				flag |= UpdateIfChanged(ref _cursedShrineCount, value15);
				flag |= UpdateIfChanged(ref _challengeShrineCount, value16);
				flag |= UpdateIfChanged(ref _greedShrineCount, value17);
			}
			if (_toggleState == 0)
			{
				SetOverlayText("");
				SyncStatsVisibility();
				return;
			}
			if (((Object)(object)_overlayText != (Object)null || (Object)(object)_overlayFallback != (Object)null) && (flag || _toggleDirty || !_overlayBuiltOnce))
			{
				RunInfoKey[] runInfoOrder = UIConfig.GetRunInfoOrder(_toggleState);
				List<string> list = new List<string>(runInfoOrder.Length);
				RunInfoKey[] array = runInfoOrder;
				foreach (RunInfoKey key in array)
				{
					string text = BuildRunInfoRow(key);
					if (!string.IsNullOrEmpty(text))
					{
						list.Add(text);
					}
				}
				SetOverlayText(string.Join("\n", list));
			}
			if (updateStats && (Object)(object)_playerStatsText != (Object)null)
			{
				MyPlayer instance = MyPlayer.Instance;
				object obj;
				if (instance == null)
				{
					obj = null;
				}
				else
				{
					PlayerInventory inventory = instance.inventory;
					obj = ((inventory != null) ? inventory.playerStats : null);
				}
				PlayerStatsNew val = (PlayerStatsNew)obj;
				List<string> list2 = new List<string>();
				if (val != null)
				{
					StatsKey[] playerStatsOrder = UIConfig.GetPlayerStatsOrder(_toggleState);
					Dictionary<StatsKey, string> dictionary = StatPalette.ForOrder(playerStatsOrder.Where(StatsCatalog.NeedsDynamicColor).ToList());
					StatsKey[] array2 = playerStatsOrder;
					foreach (StatsKey key2 in array2)
					{
						if (StatsCatalog.All.TryGetValue(key2, out var value18))
						{
							float stat = val.GetStat(value18.Stat);
							string value19 = StatsCatalog.FormatValue(value18, stat);
							string value20;
							string value21 = ((!StatsCatalog.NeedsDynamicColor(key2)) ? value18.ColorHex : (dictionary.TryGetValue(key2, out value20) ? value20 : "#FFFFFF"));
							list2.Add($"<color={"#FFFFFF"}>{value18.Label}:</color> <color={value21}>{value19}</color>");
						}
					}
				}
				((TMP_Text)_playerStatsText).text = string.Join("\n", list2);
			}
			SyncStatsVisibility();
		}

		private string BuildRunInfoRow(RunInfoKey key)
		{
			return key switch
			{
				RunInfoKey.Shrines => $"<color=white>Shrine :</color><pos=60%> <font-weight=\"200\"><color=#C0C0C0>{Z(_commonShrineCount)}</color></font-weight> <font-weight=\"700\"><color=#FFA500>{Z(_legendaryShrineCount)}</color></font-weight>", 
				RunInfoKey.Chests => $"<color=white>Chest :</color><pos=60%> <font-weight=\"200\"><color=#C0C0C0>{Z(_normalChestCount)}</color></font-weight> <font-weight=\"700\"><color=#FFA500>{Z(_freeChestCount)}</color></font-weight>", 
				RunInfoKey.Vendors => $"<color=white>Vendor :</color><pos=60%> <font-weight=\"200\"><color=#C0C0C0>{Z(_commonVendorCount)}</color></font-weight> <color=blue>{Z(_rareVendorCount)}</color> <color=#FF00FF>{Z(_epicVendorCount)}</color> <font-weight=\"700\"><color=#FFA500>{Z(_legendaryVendorCount)}</color></font-weight>", 
				RunInfoKey.Microwaves => $"<color=white>Microwave :</color><pos=60%> <font-weight=\"200\"><color=#C0C0C0>{Z(_commonMicrowaveCount)}</color></font-weight> <color=blue>{Z(_rareMicrowaveCount)}</color> <color=#FF00FF>{Z(_epicMicrowaveCount)}</color> <font-weight=\"700\"><color=#FFA500>{Z(_legendaryMicrowaveCount)}</color></font-weight>", 
				RunInfoKey.MoaiOnly => "<color=white>Moai :</color><pos=60%> <color=white>" + Z(_moaiShrineCount) + "</color>", 
				RunInfoKey.MoaiAndGreed => $"<color=white>Moai&Greed :</color><pos=60%> <color=white>{Z(_moaiShrineCount)} </color> <color=#C0C0C0>{Z(_greedShrineCount)}</color>", 
				RunInfoKey.Challenge => "<color=white>Challange</color><pos=60%> <color=white>" + Z(_challengeShrineCount) + "</color>", 
				RunInfoKey.Magnet => "<color=white>Magnet :</color><pos=60%> <color=white>" + Z(_magnetShrineCount) + "</color>", 
				RunInfoKey.Cursed => "<color=white>Cursed :</color><pos=60%> <color=white>" + Z(_cursedShrineCount) + "</color>", 
				_ => string.Empty, 
			};
		}

		private void CreateOverlayUI()
		{
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: 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_0021: Expected O, but got Unknown
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			GameObject hud = GetHud();
			if (!((Object)(object)hud == (Object)null))
			{
				_overlayObj = new GameObject("RunInfo");
				_overlayObj.transform.SetParent(hud.transform, false);
				try
				{
					_overlayText = _overlayObj.AddComponent<TextMeshProUGUI>();
					((TMP_Text)_overlayText).fontSize = 20f;
					((Graphic)_overlayText).color = Color.white;
					((TMP_Text)_overlayText).alignment = (TextAlignmentOptions)257;
					((TMP_Text)_overlayText).textWrappingMode = (TextWrappingModes)0;
					((Graphic)_overlayText).raycastTarget = false;
					ConfigureAnchors(((TMP_Text)_overlayText).rectTransform, new Vector2(30f, 0f));
					LoggerBridge.Info("RunInfo UI created (TMPro)");
				}
				catch (Exception ex)
				{
					LoggerBridge.Warn("TMPro failed: " + ex.Message + " - Using UI.Text fallback");
					_overlayFallback = _overlayObj.AddComponent<Text>();
					_overlayFallback.font = Resources.GetBuiltinResource<Font>("Arial.ttf");
					_overlayFallback.fontSize = 20;
					((Graphic)_overlayFallback).color = Color.white;
					_overlayFallback.alignment = (TextAnchor)0;
					((Graphic)_overlayFallback).raycastTarget = false;
					ConfigureAnchors(((Graphic)_overlayFallback).rectTransform, new Vector2(30f, 0f));
				}
				_overlayObj.SetActive(_toggleState != 0);
				ApplyRunInfoScale();
				UpdateRunInfo();
			}
		}

		private void CreatePlayerStatsUI()
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			GameObject hud = GetHud();
			if (!((Object)(object)hud == (Object)null))
			{
				_playerStatsObj = new GameObject("PlayerStatsInfo");
				_playerStatsObj.transform.SetParent(hud.transform, false);
				try
				{
					_playerStatsText = _playerStatsObj.AddComponent<TextMeshProUGUI>();
					((TMP_Text)_playerStatsText).fontSize = 20f;
					((Graphic)_playerStatsText).color = Color.white;
					((TMP_Text)_playerStatsText).alignment = (TextAlignmentOptions)260;
					((TMP_Text)_playerStatsText).textWrappingMode = (TextWrappingModes)0;
					((Graphic)_playerStatsText).raycastTarget = false;
					ConfigureAnchorsRight(((TMP_Text)_playerStatsText).rectTransform, new Vector2(-30f, 0f));
					LoggerBridge.Info("Player Stats UI created (TMPro)");
				}
				catch (Exception ex)
				{
					LoggerBridge.Warn("Player TMPro failed: " + ex.Message);
					_playerStatsText = null;
				}
				if ((Object)(object)_playerStatsObj != (Object)null)
				{
					_playerStatsObj.SetActive(_toggleState != 0);
				}
				ApplyPlayerStatsScale();
				UpdateRunInfo();
			}
		}

		private void HandleToggleKey()
		{
			if (!Input.GetKeyDown((KeyCode)282))
			{
				return;
			}
			switch (_toggleState)
			{
			case 1:
				_toggleState = 2;
				break;
			case 2:
				_toggleState = 0;
				break;
			default:
				_toggleState = 1;
				break;
			}
			if ((Object)(object)_overlayObj != (Object)null)
			{
				_overlayObj.SetActive(_toggleState != 0);
				if (_toggleState != 0)
				{
					UpdateRunInfo();
				}
				else
				{
					SetOverlayText("");
				}
			}
			if ((Object)(object)_playerStatsObj != (Object)null)
			{
				_playerStatsObj.SetActive(_toggleState != 0);
			}
			string text = ((_toggleState == 0) ? "hidden" : ((_toggleState == 1) ? "default" : "detailed"));
			LoggerBridge.Info("Overlay toggled to " + text + " (F1)");
			_toggleDirty = true;
		}

		private void HandleHotReloadKey()
		{
			if ((Input.GetKey((KeyCode)306) || Input.GetKey((KeyCode)305)) && Input.GetKeyDown((KeyCode)114))
			{
				try
				{
					UIConfig.ReloadFromDisk();
					_toggleDirty = true;
					_nextStatsPoll = 0f;
					_overlayBuiltOnce = false;
					UpdateRunInfo();
					_runInfoScale = Mathf.Clamp(UIConfig.GetRunInfoScale(), 0.1f, 5f);
					_playerStatsScale = Mathf.Clamp(UIConfig.GetPlayerStatsScale(), 0.1f, 5f);
					ApplyRunInfoScale();
					ApplyPlayerStatsScale();
					LoggerBridge.Info("[UsefulInfoUI] Hot reload applied (Ctrl+R).");
				}
				catch (Exception ex)
				{
					LoggerBridge.Warn("[UsefulInfoUI] Hot reload failed: " + ex.Message);
				}
			}
		}

		private GameObject GetHud()
		{
			if ((Object)(object)_hud == (Object)null)
			{
				_hud = GameObject.Find("HUD");
			}
			return _hud;
		}

		private static void ConfigureAnchors(RectTransform rt, Vector2 anchored)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			rt.anchorMax = new Vector2(0f, 0.5f);
			rt.anchorMin = new Vector2(0f, 0.5f);
			rt.pivot = new Vector2(0f, 0.5f);
			rt.anchoredPosition = anchored;
		}

		private static void ConfigureAnchorsRight(RectTransform rt, Vector2 anchored)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			rt.anchorMax = new Vector2(1f, 0.5f);
			rt.anchorMin = new Vector2(1f, 0.5f);
			rt.pivot = new Vector2(1f, 0.5f);
			rt.anchoredPosition = anchored;
		}

		private void SetOverlayText(string value)
		{
			if ((Object)(object)_overlayText != (Object)null)
			{
				((TMP_Text)_overlayText).text = value;
			}
			else if ((Object)(object)_overlayFallback != (Object)null)
			{
				_overlayFallback.text = value;
			}
		}

		private void SyncStatsVisibility()
		{
			if ((Object)(object)_playerStatsObj != (Object)null)
			{
				_playerStatsObj.SetActive(_toggleState != 0);
			}
		}

		private static bool UpdateIfChanged(ref int cache, int value)
		{
			if (cache != value)
			{
				cache = value;
				return true;
			}
			return false;
		}

		internal void _MarkCountsDirty()
		{
			_countsDirty = true;
			_nextWorldPoll = 0f;
		}

		private static bool IsCtrl()
		{
			if (!Input.GetKey((KeyCode)306))
			{
				return Input.GetKey((KeyCode)305);
			}
			return true;
		}

		private void HandleScaleKeys()
		{
			if (IsCtrl())
			{
				if (Input.GetKeyDown((KeyCode)273))
				{
					_runInfoScale = Mathf.Clamp(_runInfoScale + 0.05f, 0.1f, 5f);
					_playerStatsScale = Mathf.Clamp(_playerStatsScale + 0.05f, 0.1f, 5f);
					LoggerBridge.Info($"[UsefulInfoUI] Scales -> RunInfo={_runInfoScale:0.00}, PlayerStats={_playerStatsScale:0.00}");
					ApplyRunInfoScale();
					ApplyPlayerStatsScale();
					UIConfig.SetRunInfoScale(_runInfoScale, save: true);
					UIConfig.SetPlayerStatsScale(_playerStatsScale, save: true);
				}
				if (Input.GetKeyDown((KeyCode)274))
				{
					_runInfoScale = Mathf.Clamp(_runInfoScale - 0.05f, 0.1f, 5f);
					_playerStatsScale = Mathf.Clamp(_playerStatsScale - 0.05f, 0.1f, 5f);
					LoggerBridge.Info($"[UsefulInfoUI] Scales -> RunInfo={_runInfoScale:0.00}, PlayerStats={_playerStatsScale:0.00}");
					ApplyRunInfoScale();
					ApplyPlayerStatsScale();
					UIConfig.SetRunInfoScale(_runInfoScale, save: true);
					UIConfig.SetPlayerStatsScale(_playerStatsScale, save: true);
				}
			}
		}

		private void ApplyRunInfoScale()
		{
			//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_0049: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_overlayObj != (Object)null)
			{
				Vector3 val = default(Vector3);
				((Vector3)(ref val))..ctor(_runInfoScale, _runInfoScale, 1f);
				if (_overlayObj.transform.localScale != val)
				{
					_overlayObj.transform.localScale = val;
				}
			}
		}

		private void ApplyPlayerStatsScale()
		{
			//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_0049: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_playerStatsObj != (Object)null)
			{
				Vector3 val = default(Vector3);
				((Vector3)(ref val))..ctor(_playerStatsScale, _playerStatsScale, 1f);
				if (_playerStatsObj.transform.localScale != val)
				{
					_playerStatsObj.transform.localScale = val;
				}
			}
		}
	}
	[HarmonyPatch]
	internal static class InteractableDirtyPatches
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(BaseInteractable), "Start")]
		private static void BI_Start_Postfix()
		{
			UsefulInfoUICore.Instance?._MarkCountsDirty();
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(BaseInteractable), "OnDestroy")]
		private static void BI_OnDestroy_Postfix()
		{
			UsefulInfoUICore.Instance?._MarkCountsDirty();
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(BaseInteractable), "RefreshInteractable")]
		private static void BI_Refresh_Postfix()
		{
			UsefulInfoUICore.Instance?._MarkCountsDirty();
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(BaseInteractable), "Interact")]
		private static void BI_Interact_Postfix()
		{
			UsefulInfoUICore.Instance?._MarkCountsDirty();
		}
	}
	internal static class Hex
	{
		public const string Label = "#FFFFFF";

		public const string Damage = "#FFB200";

		public const string CritChance = "#FF2E63";

		public const string CritDamage = "#FF006E";

		public const string AttackSpeed = "#00B8D9";

		public const string Lifesteal = "#2ECC71";

		public const string Projectiles = "#9B5DE5";

		public const string ExtraJumps = "#F15BB5";

		public const string Luck = "#34D399";

		public const string Difficulty = "#FF8C00";

		public const string MoveSpeed = "#E9C46A";

		public const string Xp = "#06D6A0";

		public const string Gold = "#FFD700";
	}
	internal enum StatsKey
	{
		Damage,
		AttackSpeed,
		Luck,
		Difficulty,
		MoveSpeed,
		XpGain,
		GoldGain,
		CritChance,
		CritDamage,
		Lifesteal,
		Projectiles,
		ExtraJumps,
		MaxHealth,
		HealthRegen,
		Shield,
		Thorns,
		Armor,
		Evasion,
		DamageReductionMultiplier,
		DamageCooldownMultiplier,
		SizeMultiplier,
		DurationMultiplier,
		DamageMultiplier,
		EffectDurationMultiplier,
		ProjectileSpeedMultiplier,
		EliteDamageMultiplier,
		KnockbackMultiplier,
		MoveSpeedMultiplier,
		JumpHeight,
		PickupRange,
		GoldIncreaseMultiplier,
		XpIncreaseMultiplier,
		EliteSpawnIncrease,
		BurnChance,
		FreezeChance,
		PowerupBoostMultiplier,
		PowerupChance,
		WeaponBurstCooldown,
		ProjectileBounces,
		Overheal,
		HealingMultiplier,
		SilverIncreaseMultiplier
	}
	internal enum StatFormat
	{
		MultiplierX,
		Percent01,
		Percent01_F1,
		Integer,
		Float1,
		Float2
	}
	internal sealed class StatDef
	{
		public readonly StatsKey Key;

		public readonly string Label;

		public readonly EStat Stat;

		public readonly StatFormat Format;

		public readonly string ColorHex;

		public StatDef(StatsKey key, string label, EStat stat, StatFormat fmt, string colorHex)
		{
			//IL_0015: 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)
			Key = key;
			Label = label;
			Stat = stat;
			Format = fmt;
			ColorHex = colorHex;
		}
	}
	internal static class StatPalette
	{
		private const double GR = 0.6180339887498949;

		private const float SAT = 0.78f;

		private const float VAL = 0.95f;

		private static readonly Dictionary<string, Dictionary<StatsKey, string>> _cache = new Dictionary<string, Dictionary<StatsKey, string>>(StringComparer.Ordinal);

		public static Dictionary<StatsKey, string> ForOrder(IReadOnlyList<StatsKey> order)
		{
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			if (order == null || order.Count == 0)
			{
				return new Dictionary<StatsKey, string>();
			}
			string text = string.Join(",", order.Select((StatsKey k) => k.ToString()));
			if (_cache.TryGetValue(text, out var value))
			{
				return value;
			}
			double num = Hash01(text);
			Dictionary<StatsKey, string> dictionary = new Dictionary<StatsKey, string>(order.Count);
			for (int i = 0; i < order.Count; i++)
			{
				num = (num + 0.6180339887498949) % 1.0;
				string value2 = ToHtmlRGB(HSV((float)num, 0.78f, 0.95f));
				dictionary[order[i]] = value2;
			}
			_cache[text] = dictionary;
			return dictionary;
		}

		private static Color HSV(float h, float s, float v)
		{
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			h = Mathf.Repeat(h, 1f);
			s = Mathf.Clamp01(s);
			v = Mathf.Clamp01(v);
			float num = v * s;
			float num2 = num * (1f - Mathf.Abs(h * 6f % 2f - 1f));
			float num3 = v - num;
			float num4 = 0f;
			float num5 = 0f;
			float num6 = 0f;
			float num7 = h * 6f;
			if (num7 < 1f)
			{
				num4 = num;
				num5 = num2;
			}
			else if (num7 < 2f)
			{
				num4 = num2;
				num5 = num;
			}
			else if (num7 < 3f)
			{
				num5 = num;
				num6 = num2;
			}
			else if (num7 < 4f)
			{
				num5 = num2;
				num6 = num;
			}
			else if (num7 < 5f)
			{
				num4 = num2;
				num6 = num;
			}
			else
			{
				num4 = num;
				num6 = num2;
			}
			return new Color(num4 + num3, num5 + num3, num6 + num3, 1f);
		}

		private static string ToHtmlRGB(Color c)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			int value = Mathf.Clamp(Mathf.RoundToInt(c.r * 255f), 0, 255);
			int value2 = Mathf.Clamp(Mathf.RoundToInt(c.g * 255f), 0, 255);
			int value3 = Mathf.Clamp(Mathf.RoundToInt(c.b * 255f), 0, 255);
			return $"#{value:X2}{value2:X2}{value3:X2}";
		}

		private static double Hash01(string s)
		{
			uint num = 2166136261u;
			foreach (char c in s)
			{
				num ^= c;
				num *= 16777619;
			}
			return (double)(num % 100000) / 100000.0;
		}
	}
	internal static class StatsCatalog
	{
		private static readonly Dictionary<string, StatsKey> _aliasToKey = new Dictionary<string, StatsKey>(StringComparer.OrdinalIgnoreCase)
		{
			["Damage"] = StatsKey.Damage,
			["AttackSpeed"] = StatsKey.AttackSpeed,
			["Luck"] = StatsKey.Luck,
			["Difficulty"] = StatsKey.Difficulty,
			["MoveSpeed"] = StatsKey.MoveSpeed,
			["XpGain"] = StatsKey.XpGain,
			["GoldGain"] = StatsKey.GoldGain,
			["CritChance"] = StatsKey.CritChance,
			["CritDamage"] = StatsKey.CritDamage,
			["Lifesteal"] = StatsKey.Lifesteal,
			["Projectiles"] = StatsKey.Projectiles,
			["ExtraJumps"] = StatsKey.ExtraJumps,
			["MaxHealth"] = StatsKey.MaxHealth,
			["HealthRegen"] = StatsKey.HealthRegen,
			["Shield"] = StatsKey.Shield,
			["Thorns"] = StatsKey.Thorns,
			["Armor"] = StatsKey.Armor,
			["Evasion"] = StatsKey.Evasion,
			["DamageReductionMultiplier"] = StatsKey.DamageReductionMultiplier,
			["DamageCooldownMultiplier"] = StatsKey.DamageCooldownMultiplier,
			["SizeMultiplier"] = StatsKey.SizeMultiplier,
			["DurationMultiplier"] = StatsKey.DurationMultiplier,
			["DamageMultiplier"] = StatsKey.DamageMultiplier,
			["EffectDurationMultiplier"] = StatsKey.EffectDurationMultiplier,
			["ProjectileSpeedMultiplier"] = StatsKey.ProjectileSpeedMultiplier,
			["EliteDamageMultiplier"] = StatsKey.EliteDamageMultiplier,
			["KnockbackMultiplier"] = StatsKey.KnockbackMultiplier,
			["MoveSpeedMultiplier"] = StatsKey.MoveSpeedMultiplier,
			["JumpHeight"] = StatsKey.JumpHeight,
			["PickupRange"] = StatsKey.PickupRange,
			["GoldIncreaseMultiplier"] = StatsKey.GoldIncreaseMultiplier,
			["XpIncreaseMultiplier"] = StatsKey.XpIncreaseMultiplier,
			["EliteSpawnIncrease"] = StatsKey.EliteSpawnIncrease,
			["BurnChance"] = StatsKey.BurnChance,
			["FreezeChance"] = StatsKey.FreezeChance,
			["PowerupBoostMultiplier"] = StatsKey.PowerupBoostMultiplier,
			["PowerupChance"] = StatsKey.PowerupChance,
			["WeaponBurstCooldown"] = StatsKey.WeaponBurstCooldown,
			["ProjectileBounces"] = StatsKey.ProjectileBounces,
			["Overheal"] = StatsKey.Overheal,
			["HealingMultiplier"] = StatsKey.HealingMultiplier,
			["SilverIncreaseMultiplier"] = StatsKey.SilverIncreaseMultiplier
		};

		public static readonly IReadOnlyDictionary<StatsKey, StatDef> All = BuildDefs();

		private static Dictionary<StatsKey, StatDef> BuildDefs()
		{
			string colorHex = "#FFFFFF";
			string colorHex2 = "#FFB200";
			string colorHex3 = "#FF2E63";
			string colorHex4 = "#FF006E";
			string colorHex5 = "#00B8D9";
			string colorHex6 = "#2ECC71";
			string colorHex7 = "#9B5DE5";
			string colorHex8 = "#F15BB5";
			string colorHex9 = "#34D399";
			string colorHex10 = "#FF8C00";
			string colorHex11 = "#E9C46A";
			string colorHex12 = "#06D6A0";
			string colorHex13 = "#FFD700";
			return new Dictionary<StatsKey, StatDef>
			{
				[StatsKey.Damage] = new StatDef(StatsKey.Damage, "Damage", (EStat)12, StatFormat.MultiplierX, colorHex2),
				[StatsKey.AttackSpeed] = new StatDef(StatsKey.AttackSpeed, "Attack Speed", (EStat)15, StatFormat.Percent01, colorHex5),
				[StatsKey.Luck] = new StatDef(StatsKey.Luck, "Luck", (EStat)30, StatFormat.Percent01, colorHex9),
				[StatsKey.Difficulty] = new StatDef(StatsKey.Difficulty, "Difficulty", (EStat)38, StatFormat.Percent01, colorHex10),
				[StatsKey.MoveSpeed] = new StatDef(StatsKey.MoveSpeed, "Move Speed", (EStat)25, StatFormat.MultiplierX, colorHex11),
				[StatsKey.XpGain] = new StatDef(StatsKey.XpGain, "XP Gain", (EStat)32, StatFormat.MultiplierX, colorHex12),
				[StatsKey.GoldGain] = new StatDef(StatsKey.GoldGain, "Gold Gain", (EStat)31, StatFormat.MultiplierX, colorHex13),
				[StatsKey.CritChance] = new StatDef(StatsKey.CritChance, "Crit Chance", (EStat)18, StatFormat.Percent01, colorHex3),
				[StatsKey.CritDamage] = new StatDef(StatsKey.CritDamage, "Crit Damage", (EStat)19, StatFormat.MultiplierX, colorHex4),
				[StatsKey.Lifesteal] = new StatDef(StatsKey.Lifesteal, "Lifesteal", (EStat)17, StatFormat.Percent01, colorHex6),
				[StatsKey.Projectiles] = new StatDef(StatsKey.Projectiles, "Projectiles", (EStat)16, StatFormat.Float1, colorHex7),
				[StatsKey.ExtraJumps] = new StatDef(StatsKey.ExtraJumps, "Extra Jumps", (EStat)46, StatFormat.Float1, colorHex8),
				[StatsKey.MaxHealth] = new StatDef(StatsKey.MaxHealth, "Max Health", (EStat)0, StatFormat.Integer, colorHex),
				[StatsKey.HealthRegen] = new StatDef(StatsKey.HealthRegen, "Health Regen", (EStat)1, StatFormat.Integer, colorHex),
				[StatsKey.Shield] = new StatDef(StatsKey.Shield, "Shield", (EStat)2, StatFormat.Integer, colorHex),
				[StatsKey.Thorns] = new StatDef(StatsKey.Thorns, "Thorns", (EStat)3, StatFormat.Integer, colorHex),
				[StatsKey.Armor] = new StatDef(StatsKey.Armor, "Armor", (EStat)4, StatFormat.Percent01, colorHex),
				[StatsKey.Evasion] = new StatDef(StatsKey.Evasion, "Evasion", (EStat)5, StatFormat.Percent01, colorHex),
				[StatsKey.DamageReductionMultiplier] = new StatDef(StatsKey.DamageReductionMultiplier, "Damage Reduction", (EStat)7, StatFormat.Percent01, colorHex),
				[StatsKey.DamageCooldownMultiplier] = new StatDef(StatsKey.DamageCooldownMultiplier, "Damage Cooldown", (EStat)8, StatFormat.MultiplierX, colorHex),
				[StatsKey.SizeMultiplier] = new StatDef(StatsKey.SizeMultiplier, "Size", (EStat)9, StatFormat.MultiplierX, colorHex),
				[StatsKey.DurationMultiplier] = new StatDef(StatsKey.DurationMultiplier, "Duration", (EStat)10, StatFormat.MultiplierX, colorHex),
				[StatsKey.DamageMultiplier] = new StatDef(StatsKey.DamageMultiplier, "Damage", (EStat)12, StatFormat.MultiplierX, colorHex2),
				[StatsKey.EffectDurationMultiplier] = new StatDef(StatsKey.EffectDurationMultiplier, "Effect Duration", (EStat)14, StatFormat.MultiplierX, colorHex),
				[StatsKey.ProjectileSpeedMultiplier] = new StatDef(StatsKey.ProjectileSpeedMultiplier, "Projectile Speed", (EStat)11, StatFormat.MultiplierX, colorHex),
				[StatsKey.EliteDamageMultiplier] = new StatDef(StatsKey.EliteDamageMultiplier, "Elite Damage", (EStat)23, StatFormat.MultiplierX, colorHex),
				[StatsKey.KnockbackMultiplier] = new StatDef(StatsKey.KnockbackMultiplier, "Knockback", (EStat)24, StatFormat.MultiplierX, colorHex),
				[StatsKey.MoveSpeedMultiplier] = new StatDef(StatsKey.MoveSpeedMultiplier, "Move Speed", (EStat)25, StatFormat.MultiplierX, colorHex11),
				[StatsKey.JumpHeight] = new StatDef(StatsKey.JumpHeight, "Jump Height", (EStat)26, StatFormat.Integer, colorHex),
				[StatsKey.PickupRange] = new StatDef(StatsKey.PickupRange, "Pickup Range", (EStat)29, StatFormat.Integer, colorHex),
				[StatsKey.GoldIncreaseMultiplier] = new StatDef(StatsKey.GoldIncreaseMultiplier, "Gold Gain", (EStat)31, StatFormat.MultiplierX, colorHex13),
				[StatsKey.XpIncreaseMultiplier] = new StatDef(StatsKey.XpIncreaseMultiplier, "XP Gain", (EStat)32, StatFormat.MultiplierX, colorHex12),
				[StatsKey.EliteSpawnIncrease] = new StatDef(StatsKey.EliteSpawnIncrease, "Elite Spawn", (EStat)39, StatFormat.Percent01, colorHex),
				[StatsKey.BurnChance] = new StatDef(StatsKey.BurnChance, "Burn Chance", (EStat)42, StatFormat.Percent01, colorHex),
				[StatsKey.FreezeChance] = new StatDef(StatsKey.FreezeChance, "Freeze Chance", (EStat)43, StatFormat.Percent01, colorHex),
				[StatsKey.PowerupBoostMultiplier] = new StatDef(StatsKey.PowerupBoostMultiplier, "Powerup Boost", (EStat)40, StatFormat.MultiplierX, colorHex),
				[StatsKey.PowerupChance] = new StatDef(StatsKey.PowerupChance, "Powerup Chance", (EStat)41, StatFormat.Percent01, colorHex),
				[StatsKey.WeaponBurstCooldown] = new StatDef(StatsKey.WeaponBurstCooldown, "Burst Cooldown", (EStat)44, StatFormat.Float2, colorHex),
				[StatsKey.ProjectileBounces] = new StatDef(StatsKey.ProjectileBounces, "Proj. Bounces", (EStat)45, StatFormat.Integer, colorHex),
				[StatsKey.Overheal] = new StatDef(StatsKey.Overheal, "Overheal", (EStat)47, StatFormat.Integer, colorHex),
				[StatsKey.HealingMultiplier] = new StatDef(StatsKey.HealingMultiplier, "Healing", (EStat)48, StatFormat.MultiplierX, colorHex),
				[StatsKey.SilverIncreaseMultiplier] = new StatDef(StatsKey.SilverIncreaseMultiplier, "Silver Gain", (EStat)49, StatFormat.MultiplierX, colorHex)
			};
		}

		public static bool TryResolveKey(string s, out StatsKey key)
		{
			return _aliasToKey.TryGetValue(s, out key);
		}

		public static string FormatValue(StatDef def, float raw)
		{
			return def.Format switch
			{
				StatFormat.MultiplierX => $"{raw:F2}x", 
				StatFormat.Percent01 => $"{raw * 100f:0}%", 
				StatFormat.Percent01_F1 => $"{raw * 100f:0.0}%", 
				StatFormat.Integer => Mathf.RoundToInt(raw).ToString(), 
				StatFormat.Float1 => raw.ToString("0.0"), 
				StatFormat.Float2 => raw.ToString("0.00"), 
				_ => raw.ToString(), 
			};
		}

		public static bool NeedsDynamicColor(StatsKey key)
		{
			if ((uint)key <= 11u)
			{
				return false;
			}
			return true;
		}
	}
	[BepInPlugin("com.maskoliver.usefulinfoui", "Useful Info UI", "1.1.5")]
	public sealed class BepInEntry : BasePlugin
	{
		private sealed class UpdateDriver : MonoBehaviour
		{
			private int _lastSceneBuildIndex = -1;

			public UpdateDriver(IntPtr ptr)
				: base(ptr)
			{
			}

			private void Start()
			{
				//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)
				try
				{
					_core.Init();
					Scene activeScene = SceneManager.GetActiveScene();
					_lastSceneBuildIndex = ((Scene)(ref activeScene)).buildIndex;
					_core.OnSceneLoaded(((Scene)(ref activeScene)).buildIndex, ((Scene)(ref activeScene)).name);
				}
				catch (Exception ex)
				{
					ManualLogSource sLog = SLog;
					if (sLog != null)
					{
						sLog.LogError((object)ex);
					}
				}
			}

			private void Update()
			{
				//IL_0010: Unknown result type (might be due to invalid IL or missing references)
				//IL_0015: Unknown result type (might be due to invalid IL or missing references)
				_core?.UpdateLoop();
				Scene activeScene = SceneManager.GetActiveScene();
				if (((Scene)(ref activeScene)).buildIndex == _lastSceneBuildIndex)
				{
					return;
				}
				try
				{
					_core?.OnSceneLoaded(((Scene)(ref activeScene)).buildIndex, ((Scene)(ref activeScene)).name);
					_lastSceneBuildIndex = ((Scene)(ref activeScene)).buildIndex;
				}
				catch (Exception ex)
				{
					ManualLogSource sLog = SLog;
					if (sLog != null)
					{
						sLog.LogError((object)ex);
					}
				}
			}

			private void OnDestroy()
			{
				ManualLogSource sLog = SLog;
				if (sLog != null)
				{
					sLog.LogInfo((object)"UsefulInfoUI_UpdateHost destroyed");
				}
			}
		}

		private Harmony _harmony;

		internal static ManualLogSource SLog;

		private static GameObject _host;

		private static UsefulInfoUICore _core;

		public override void Load()
		{
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Expected O, but got Unknown
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Expected O, but got Unknown
			SLog = Logger.CreateLogSource("UsefulInfoUI");
			LoggerBridge.Info = delegate(string s)
			{
				SLog.LogInfo((object)s);
			};
			LoggerBridge.Warn = delegate(string s)
			{
				SLog.LogWarning((object)s);
			};
			LoggerBridge.Error = delegate(string s)
			{
				SLog.LogError((object)s);
			};
			ClassInjector.RegisterTypeInIl2Cpp<UpdateDriver>();
			_core = new UsefulInfoUICore();
			_host = new GameObject("UsefulInfoUI_UpdateHost");
			Object.DontDestroyOnLoad((Object)(object)_host);
			((Object)_host).hideFlags = (HideFlags)61;
			_host.AddComponent<UpdateDriver>();
			_harmony = new Harmony("Maskoliver.UsefulInfoUI");
			_harmony.PatchAll();
			SLog.LogInfo((object)"Useful Info UI (BepInEx) loaded.");
		}
	}
	internal static class LoggerBridge
	{
		public static Action<string> Info = delegate
		{
		};

		public static Action<string> Warn = delegate
		{
		};

		public static Action<string> Error = delegate
		{
		};
	}
	internal static class PathsBridge
	{
		public static string UserDataDir => Paths.ConfigPath;
	}
	[HarmonyPatch(typeof(ChargeShrine), "Complete")]
	public static class ChargeShrinePatch
	{
		[HarmonyPostfix]
		public static void Postfix()
		{
			UsefulInfoUICore.Instance?.InvokeRunInfoChanged();
		}
	}
	[HarmonyPatch(typeof(InteractableShrineMoai), "Interact")]
	public static class MoaiPatch
	{
		[HarmonyPostfix]
		public static void Postfix()
		{
			UsefulInfoUICore.Instance?.InvokeRunInfoChanged();
		}
	}
	[HarmonyPatch(typeof(InteractableShadyGuy), "OnDestroy")]
	public static class ShadyGuyPatch
	{
		[HarmonyPostfix]
		public static void Postfix()
		{
			UsefulInfoUICore.Instance?.InvokeRunInfoChanged();
		}
	}
	public static class ToggleImage
	{
		public static TextMeshProUGUI text;

		public static bool isOn;

		public static void Toggle()
		{
			isOn = !isOn;
			if (isOn && (Object)(object)text != (Object)null)
			{
				((TMP_Text)text).text = "Press key";
			}
		}
	}
}