Decompiled source of MarsarahTweaks v1.5.0

MarsarahTweaks.dll

Decompiled 4 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using HarmonyLib;
using JetBrains.Annotations;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using MarsarahTweaks.Managers;
using MarsarahTweaks.Patches.Balance;
using MarsarahTweaks.Patches.BuildPieces;
using MarsarahTweaks.Patches.Features;
using MarsarahTweaks.Patches.Grind;
using MarsarahTweaks.Patches.QOL;
using MarsarahTweaks.Patches.UI;
using Microsoft.CodeAnalysis;
using ServerSync;
using Splatform;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("MarsarahTweaks")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("MarsarahTweaks")]
[assembly: AssemblyCopyright("Copyright ©  2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("831fc141-e3fa-4e67-9d2f-5e56cf6f3935")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace MarsarahTweaks
{
	[BepInPlugin("Marsarah.MarsarahTweaks", "MarsarahTweaks", "1.5.0")]
	public class MarsarahTweaks : BaseUnityPlugin
	{
		internal const string ModName = "MarsarahTweaks";

		internal const string ModVersion = "1.5.0";

		internal const string Author = "Marsarah";

		public const string ModGUID = "Marsarah.MarsarahTweaks";

		private readonly Harmony harmony = new Harmony("Marsarah.MarsarahTweaks");

		private void Awake()
		{
			LogManager.SetGlobalLogLevel(LogManager.LogLevel.Info);
			ConfigManager.Init(((BaseUnityPlugin)this).Config);
			UISmartBiome.UpdateBiomeWeights();
			harmony.PatchAll();
		}

		private void Start()
		{
			CompatibilityManager.Initialize();
			CompatibilityManager.UpdateIncompatibilities();
			CompatibilityManager.DumpAllLoadedMods();
		}

		private void Update()
		{
			UIController.UpdateUIDisplay();
		}

		private void OnDestroy()
		{
			((BaseUnityPlugin)this).Config.Save();
		}
	}
}
namespace MarsarahTweaks.Features.UI
{
	internal class UIEnemyNameplates : UIController
	{
		private class HpTexts
		{
			public TextMeshProUGUI HP;

			public TextMeshProUGUI HpPercent;
		}

		[HarmonyPatch(typeof(EnemyHud), "Awake")]
		public static class EmenyHud_Awake_Patch
		{
			private static void Postfix(ref EnemyHud __instance)
			{
				if (!((Object)(object)__instance == (Object)null) && !CompatibilityManager.BetterUI.Loaded)
				{
					if (ConfigManager.EnemyNameplateChoice.Value != ConfigManager.EnemyNameplateMode.Off)
					{
						float num = 2f;
						DefaultDistance = __instance.m_maxShowDistance;
						EnemyHud obj = __instance;
						obj.m_maxShowDistance *= num;
					}
					else if (DefaultDistance != -1f)
					{
						__instance.m_maxShowDistance = DefaultDistance;
					}
				}
			}
		}

		[HarmonyPatch(typeof(EnemyHud), "ShowHud")]
		public static class EnemyHud_ShowHud_CustomBar_Patch
		{
			private static void Postfix(EnemyHud __instance, Character c)
			{
				if ((Object)(object)c == (Object)null || m_hudsField == null || CompatibilityManager.BetterUI.Loaded || !(m_hudsField.GetValue(__instance) is IDictionary dictionary) || !dictionary.Contains(c))
				{
					return;
				}
				object obj = dictionary[c];
				if (obj == null)
				{
					return;
				}
				object? obj2 = hud_m_gui_Field?.GetValue(obj);
				GameObject val = (GameObject)((obj2 is GameObject) ? obj2 : null);
				if (!((Object)(object)val == (Object)null))
				{
					Transform obj3 = val.transform.Find("Health");
					RectTransform val2 = (RectTransform)(object)((obj3 is RectTransform) ? obj3 : null);
					if (!((Object)(object)val2 == (Object)null))
					{
						object? obj4 = hud_m_healthFast_Field?.GetValue(obj);
						GuiBar fastBar = (GuiBar)((obj4 is GuiBar) ? obj4 : null);
						object? obj5 = hud_m_healthSlow_Field?.GetValue(obj);
						GuiBar slowBar = (GuiBar)((obj5 is GuiBar) ? obj5 : null);
						object? obj6 = hud_m_healthFastFriendly_Field?.GetValue(obj);
						GuiBar fastFriendlyBar = (GuiBar)((obj6 is GuiBar) ? obj6 : null);
						bool flag = ConfigManager.EnemyNameplateChoice.Value != ConfigManager.EnemyNameplateMode.Off;
						ApplyBarSettings(c, val2, fastBar, slowBar, fastFriendlyBar, flag);
						AddHpText(c, obj, val2, flag);
					}
				}
			}
		}

		[HarmonyPatch(typeof(EnemyHud), "UpdateHuds")]
		public static class EnemyHud_UpdateHuds_CustomBar_Patch
		{
			private static void Postfix(EnemyHud __instance)
			{
				if (m_hudsField == null || !(m_hudsField.GetValue(__instance) is IDictionary dictionary))
				{
					return;
				}
				bool flag = ConfigManager.EnemyNameplateChoice.Value != ConfigManager.EnemyNameplateMode.Off;
				foreach (DictionaryEntry item in dictionary)
				{
					object value = item.Value;
					if (value != null)
					{
						object? obj = hud_m_character_Field?.GetValue(value);
						Character val = (Character)((obj is Character) ? obj : null);
						if (!((Object)(object)val == (Object)null) && !val.IsDead())
						{
							UpdateHpText(val, value, flag);
							UpdateAlertAndName(val, value, flag);
							UpdateBarColor(val, value);
						}
					}
				}
			}
		}

		private static readonly LogManager log;

		private const float BarHeight = 14f;

		private const float BarHeightBoss = 18f;

		private static float DefaultDistance;

		private static float DefaultBarHeight;

		private static float DefaultBarHeightBoss;

		private static readonly Dictionary<object, float> _lastBarHeight;

		private static readonly FieldInfo m_hudsField;

		private static readonly Type hudDataType;

		private static readonly FieldInfo hud_m_gui_Field;

		private static readonly FieldInfo hud_m_character_Field;

		private static readonly FieldInfo hud_m_healthFast_Field;

		private static readonly FieldInfo hud_m_healthSlow_Field;

		private static readonly FieldInfo hud_m_healthFastFriendly_Field;

		private static readonly FieldInfo hud_m_name_Field;

		private static readonly FieldInfo hud_m_alerted_Field;

		private static readonly FieldInfo hud_m_aware_Field;

		private static readonly FieldInfo guiBar_m_width_Field;

		private static readonly ConditionalWeakTable<object, HpTexts> _hpTextCache;

		static UIEnemyNameplates()
		{
			log = new LogManager("UI Enemy Nameplates", LogManager.LogLevel.Warning);
			DefaultDistance = -1f;
			DefaultBarHeight = -1f;
			DefaultBarHeightBoss = -1f;
			_lastBarHeight = new Dictionary<object, float>();
			_hpTextCache = new ConditionalWeakTable<object, HpTexts>();
			m_hudsField = typeof(EnemyHud).GetField("m_huds", BindingFlags.Instance | BindingFlags.NonPublic);
			hudDataType = typeof(EnemyHud).GetNestedType("HudData", BindingFlags.Instance | BindingFlags.NonPublic);
			if (m_hudsField == null || hudDataType == null)
			{
				log.Error("Failed to locate EnemyHud.m_huds or nested type HudData via reflection.");
				return;
			}
			hud_m_gui_Field = hudDataType.GetField("m_gui", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			hud_m_character_Field = hudDataType.GetField("m_character", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			hud_m_healthFast_Field = hudDataType.GetField("m_healthFast", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			hud_m_healthSlow_Field = hudDataType.GetField("m_healthSlow", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			hud_m_healthFastFriendly_Field = hudDataType.GetField("m_healthFastFriendly", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			hud_m_name_Field = hudDataType.GetField("m_name", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			hud_m_alerted_Field = hudDataType.GetField("m_alerted", BindingFlags.Instance | BindingFlags.Public);
			hud_m_aware_Field = hudDataType.GetField("m_aware", BindingFlags.Instance | BindingFlags.Public);
			guiBar_m_width_Field = typeof(GuiBar).GetField("m_width", BindingFlags.Instance | BindingFlags.NonPublic);
			if (guiBar_m_width_Field == null)
			{
				log.Warn("Could not resolve GuiBar.m_width via reflection. Resizing may fallback to default width.");
			}
		}

		private static void ApplyBarSettings(Character character, RectTransform health, GuiBar fastBar, GuiBar slowBar, GuiBar fastFriendlyBar, bool enable)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: 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_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_0284: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0294: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0262: Unknown result type (might be due to invalid IL or missing references)
			//IL_023f: Unknown result type (might be due to invalid IL or missing references)
			//IL_021f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0272: Unknown result type (might be due to invalid IL or missing references)
			//IL_024f: Unknown result type (might be due to invalid IL or missing references)
			//IL_022e: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)character == (Object)null || (Object)(object)health == (Object)null)
			{
				return;
			}
			if (!character.IsBoss() && DefaultBarHeight == -1f)
			{
				DefaultBarHeight = health.sizeDelta.y;
			}
			if (character.IsBoss() && DefaultBarHeightBoss == -1f)
			{
				DefaultBarHeightBoss = health.sizeDelta.y;
			}
			float num = ((!enable) ? (character.IsBoss() ? DefaultBarHeightBoss : DefaultBarHeight) : (character.IsBoss() ? 18f : 14f));
			if (_lastBarHeight.TryGetValue(health, out var value) && value == num)
			{
				return;
			}
			health.sizeDelta = new Vector2(health.sizeDelta.x, num);
			if ((Object)(object)fastBar != (Object)null)
			{
				fastBar.m_bar.sizeDelta = new Vector2(fastBar.m_bar.sizeDelta.x, num);
			}
			if ((Object)(object)slowBar != (Object)null)
			{
				slowBar.m_bar.sizeDelta = new Vector2(slowBar.m_bar.sizeDelta.x, num);
			}
			if ((Object)(object)fastFriendlyBar != (Object)null)
			{
				fastFriendlyBar.m_bar.sizeDelta = new Vector2(fastFriendlyBar.m_bar.sizeDelta.x, num);
			}
			_lastBarHeight[health] = num;
			Color magenta = Color.magenta;
			Color yellow = Color.yellow;
			Color green = Color.green;
			Color red = Color.red;
			if (enable)
			{
				if (character.IsBoss())
				{
					if (fastBar != null)
					{
						fastBar.SetColor(magenta);
					}
				}
				else if (character.IsTamed())
				{
					if (fastBar != null)
					{
						fastBar.SetColor(yellow);
					}
					if (fastFriendlyBar != null)
					{
						fastFriendlyBar.SetColor(yellow);
					}
				}
				else if (character.IsPlayer())
				{
					if (character.IsPVPEnabled())
					{
						if (fastBar != null)
						{
							fastBar.SetColor(magenta);
						}
						if (fastFriendlyBar != null)
						{
							fastFriendlyBar.SetColor(magenta);
						}
					}
					else
					{
						if (fastBar != null)
						{
							fastBar.SetColor(green);
						}
						if (fastFriendlyBar != null)
						{
							fastFriendlyBar.SetColor(green);
						}
					}
				}
				else
				{
					if (fastBar != null)
					{
						fastBar.SetColor(red);
					}
					if (fastFriendlyBar != null)
					{
						fastFriendlyBar.SetColor(yellow);
					}
				}
			}
			else
			{
				if (fastBar != null)
				{
					fastBar.SetColor(red);
				}
				if (fastFriendlyBar != null)
				{
					fastFriendlyBar.SetColor(green);
				}
			}
		}

		private static void AddHpText(Character character, object hudData, RectTransform healthTransform, bool enableMainBars)
		{
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: 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_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_023b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0252: Unknown result type (might be due to invalid IL or missing references)
			//IL_0269: Unknown result type (might be due to invalid IL or missing references)
			//IL_0280: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0209: Unknown result type (might be due to invalid IL or missing references)
			//IL_0220: Unknown result type (might be due to invalid IL or missing references)
			if (!_hpTextCache.TryGetValue(hudData, out var _))
			{
				ConfigManager.EnemyNameplateMode value2 = ConfigManager.EnemyNameplateChoice.Value;
				bool active = (value2 == ConfigManager.EnemyNameplateMode.BarsWithHealth || value2 == ConfigManager.EnemyNameplateMode.BarsWithBoth) && enableMainBars;
				bool active2 = (value2 == ConfigManager.EnemyNameplateMode.BarsWithPercent || value2 == ConfigManager.EnemyNameplateMode.BarsWithBoth) && enableMainBars;
				bool flag = value2 == ConfigManager.EnemyNameplateMode.BarsWithBoth && enableMainBars;
				string fontName = "Valheim-AveriaSansLibre";
				Vector2 sizeDelta = default(Vector2);
				((Vector2)(ref sizeDelta))..ctor(100f, 14f);
				int fontSize = 11;
				TextMeshProUGUI val = UIController.CreateTMPTextObject("HpText", ((Component)healthTransform).gameObject, Color.white, fontName, fontSize, (TextAlignmentOptions)(flag ? 513 : 514), Vector2.zero, sizeDelta, log);
				((Component)val).gameObject.SetActive(active);
				RectTransform component = ((Component)val).GetComponent<RectTransform>();
				if (flag)
				{
					component.anchorMin = new Vector2(0f, 0.5f);
					component.anchorMax = new Vector2(0f, 0.5f);
					component.pivot = new Vector2(0f, 0.5f);
					component.anchoredPosition = new Vector2(3f, 1f);
				}
				else
				{
					component.anchorMin = new Vector2(0.5f, 0.5f);
					component.anchorMax = new Vector2(0.5f, 0.5f);
					component.pivot = new Vector2(0.5f, 0.5f);
					component.anchoredPosition = new Vector2(0f, 1f);
				}
				TextMeshProUGUI val2 = UIController.CreateTMPTextObject("HpPercentText", ((Component)healthTransform).gameObject, Color.white, fontName, fontSize, (TextAlignmentOptions)(flag ? 516 : 514), Vector2.zero, sizeDelta, log);
				((Component)val2).gameObject.SetActive(active2);
				RectTransform component2 = ((Component)val2).GetComponent<RectTransform>();
				if (flag)
				{
					component2.anchorMin = new Vector2(1f, 0.5f);
					component2.anchorMax = new Vector2(1f, 0.5f);
					component2.pivot = new Vector2(1f, 0.5f);
					component2.anchoredPosition = new Vector2(-3f, 1f);
				}
				else
				{
					component2.anchorMin = new Vector2(0.5f, 0.5f);
					component2.anchorMax = new Vector2(0.5f, 0.5f);
					component2.pivot = new Vector2(0.5f, 0.5f);
					component2.anchoredPosition = new Vector2(0f, 1f);
				}
				_hpTextCache.Add(hudData, new HpTexts
				{
					HP = val,
					HpPercent = val2
				});
			}
		}

		private static void UpdateHpText(Character character, object hudData, bool enableMainBars)
		{
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			if (!_hpTextCache.TryGetValue(hudData, out var value))
			{
				return;
			}
			ConfigManager.EnemyNameplateMode value2 = ConfigManager.EnemyNameplateChoice.Value;
			bool active = (value2 == ConfigManager.EnemyNameplateMode.BarsWithHealth || value2 == ConfigManager.EnemyNameplateMode.BarsWithBoth) && enableMainBars;
			bool active2 = (value2 == ConfigManager.EnemyNameplateMode.BarsWithPercent || value2 == ConfigManager.EnemyNameplateMode.BarsWithBoth) && enableMainBars;
			bool enableBoth = value2 == ConfigManager.EnemyNameplateMode.BarsWithBoth && enableMainBars;
			((Component)value.HP).gameObject.SetActive(active);
			((Component)value.HpPercent).gameObject.SetActive(active2);
			if (!enableMainBars)
			{
				return;
			}
			UpdateHpTextLayout(value, enableBoth);
			float health = character.GetHealth();
			float maxHealth = character.GetMaxHealth();
			float num = Mathf.Clamp01(health / Math.Max(1f, maxHealth));
			((TMP_Text)value.HP).text = $"{Mathf.CeilToInt(health)} / {Mathf.CeilToInt(maxHealth)}";
			((TMP_Text)value.HpPercent).text = $"{Mathf.RoundToInt(num * 100f)}%";
			Color black = Color.black;
			Color white = Color.white;
			if (character.IsTamed() || character.IsPlayer())
			{
				((Graphic)value.HP).color = black;
				((Graphic)value.HpPercent).color = black;
				return;
			}
			BaseAI baseAI = character.GetBaseAI();
			if (!((Object)(object)baseAI != (Object)null) || !baseAI.IsEnemy((Character)(object)Player.m_localPlayer))
			{
				((Graphic)value.HP).color = black;
				((Graphic)value.HpPercent).color = black;
			}
			else
			{
				((Graphic)value.HP).color = white;
				((Graphic)value.HpPercent).color = white;
			}
		}

		private static void UpdateHpTextLayout(HpTexts hpTexts, bool enableBoth)
		{
			//IL_0088: 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_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: 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_0102: 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_012a: Unknown result type (might be due to invalid IL or missing references)
			RectTransform rectTransform = ((TMP_Text)hpTexts.HP).rectTransform;
			Vector2 val = default(Vector2);
			if (enableBoth)
			{
				((Vector2)(ref val))..ctor(0f, 0.5f);
				rectTransform.anchorMax = val;
				rectTransform.anchorMin = val;
				rectTransform.pivot = new Vector2(0f, 0.5f);
				rectTransform.anchoredPosition = new Vector2(3f, 1f);
				((TMP_Text)hpTexts.HP).alignment = (TextAlignmentOptions)513;
			}
			else
			{
				((Vector2)(ref val))..ctor(0.5f, 0.5f);
				rectTransform.anchorMax = val;
				rectTransform.anchorMin = val;
				rectTransform.pivot = new Vector2(0.5f, 0.5f);
				rectTransform.anchoredPosition = new Vector2(0f, 1f);
				((TMP_Text)hpTexts.HP).alignment = (TextAlignmentOptions)514;
			}
			RectTransform rectTransform2 = ((TMP_Text)hpTexts.HpPercent).rectTransform;
			if (enableBoth)
			{
				((Vector2)(ref val))..ctor(1f, 0.5f);
				rectTransform2.anchorMax = val;
				rectTransform2.anchorMin = val;
				rectTransform2.pivot = new Vector2(1f, 0.5f);
				rectTransform2.anchoredPosition = new Vector2(-3f, 1f);
				((TMP_Text)hpTexts.HpPercent).alignment = (TextAlignmentOptions)516;
			}
			else
			{
				((Vector2)(ref val))..ctor(0.5f, 0.5f);
				rectTransform2.anchorMax = val;
				rectTransform2.anchorMin = val;
				rectTransform2.pivot = new Vector2(0.5f, 0.5f);
				rectTransform2.anchoredPosition = new Vector2(0f, 1f);
				((TMP_Text)hpTexts.HpPercent).alignment = (TextAlignmentOptions)514;
			}
		}

		private static void UpdateAlertAndName(Character character, object hudData, bool enable)
		{
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			object? obj = hud_m_alerted_Field?.GetValue(hudData);
			RectTransform val = (RectTransform)((obj is RectTransform) ? obj : null);
			object? obj2 = hud_m_aware_Field?.GetValue(hudData);
			RectTransform val2 = (RectTransform)((obj2 is RectTransform) ? obj2 : null);
			if (enable)
			{
				if (val != null)
				{
					((Component)val).gameObject.SetActive(false);
				}
				if (val2 != null)
				{
					((Component)val2).gameObject.SetActive(false);
				}
			}
			BaseAI baseAI = character.GetBaseAI();
			bool flag = baseAI != null && baseAI.IsAlerted();
			bool flag2 = baseAI != null && baseAI.HaveTarget();
			object? obj3 = hud_m_name_Field?.GetValue(hudData);
			TextMeshProUGUI val3 = (TextMeshProUGUI)((obj3 is TextMeshProUGUI) ? obj3 : null);
			if (!((Object)(object)val3 != (Object)null))
			{
				return;
			}
			if (enable)
			{
				if (flag)
				{
					((Graphic)val3).color = Color.red;
				}
				else if (flag2)
				{
					((Graphic)val3).color = Color.yellow;
				}
				else
				{
					((Graphic)val3).color = Color.white;
				}
			}
			else
			{
				((Graphic)val3).color = Color.white;
			}
		}

		private static void UpdateBarColor(Character character, object hudData)
		{
			//IL_0073: 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_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: 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_00ad: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)character == (Object)null || hudData == null)
			{
				return;
			}
			object? obj = hud_m_healthFast_Field?.GetValue(hudData);
			GuiBar val = (GuiBar)((obj is GuiBar) ? obj : null);
			object? obj2 = hud_m_healthSlow_Field?.GetValue(hudData);
			GuiBar val2 = (GuiBar)((obj2 is GuiBar) ? obj2 : null);
			object? obj3 = hud_m_healthFastFriendly_Field?.GetValue(hudData);
			GuiBar val3 = (GuiBar)((obj3 is GuiBar) ? obj3 : null);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			Color magenta = Color.magenta;
			Color green = Color.green;
			if (!character.IsPlayer())
			{
				return;
			}
			if (character.IsPVPEnabled())
			{
				if (val != null)
				{
					val.SetColor(magenta);
				}
				if (val3 != null)
				{
					val3.SetColor(magenta);
				}
			}
			else
			{
				if (val != null)
				{
					val.SetColor(green);
				}
				if (val3 != null)
				{
					val3.SetColor(green);
				}
			}
		}

		private static void SetBackgroundColor(GuiBar bar, Color color)
		{
			//IL_00c6: 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)
			if ((Object)(object)bar == (Object)null || (Object)(object)bar.m_bar == (Object)null)
			{
				log.Warn("[BackgroundChange] Bar or bar.m_bar is null");
				return;
			}
			Transform parent = ((Transform)bar.m_bar).parent;
			Transform obj = ((parent != null) ? parent.parent : null);
			RectTransform val = (RectTransform)(object)((obj is RectTransform) ? obj : null);
			if ((Object)(object)val == (Object)null)
			{
				log.Warn("[BackgroundChange] Could not find health container");
				return;
			}
			Image[] componentsInChildren = ((Component)val).GetComponentsInChildren<Image>(true);
			Image[] array = componentsInChildren;
			foreach (Image val2 in array)
			{
				log.Info("Image name: " + ((Object)val2).name);
				if (((Object)val2).name == "bkg")
				{
					((Graphic)val2).color = color;
					log.Info($"[BackgroundChange] Changed {((Object)val2).name} to {((Graphic)val2).color}");
					break;
				}
			}
		}

		private static Color GetBackgroundColor(RectTransform health)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: 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)
			if ((Object)(object)health == (Object)null)
			{
				log.Warn("[GetBackgroundColor] health is null");
				return Color.clear;
			}
			Image[] componentsInChildren = ((Component)health).GetComponentsInChildren<Image>(true);
			Image[] array = componentsInChildren;
			foreach (Image val in array)
			{
				if (((Object)val).name == "bkg")
				{
					log.Info($"[GetBackgroundColor] Found {((Object)val).name} with color {((Graphic)val).color}");
					return ((Graphic)val).color;
				}
			}
			log.Warn("[GetBackgroundColor] No 'bkg' image found under health");
			return Color.clear;
		}
	}
}
namespace MarsarahTweaks.Patches
{
	public static class GlobalKeyChecker
	{
		[HarmonyPatch(typeof(ZoneSystem), "Update")]
		private class BossStatusUpdate_Patch
		{
			private static void Postfix(ZoneSystem __instance)
			{
				UpdateDefeatedStates(__instance);
				EikthyrDefeated = CheckGlobalKey("defeated_eikthyr");
				ElderDefeated = CheckGlobalKey("defeated_gdking");
				BonemassDefeated = CheckGlobalKey("defeated_bonemass");
				ModerDefeated = CheckGlobalKey("defeated_dragon");
				YagluthDefeated = CheckGlobalKey("defeated_goblinking");
				QueenDefeated = CheckGlobalKey("defeated_queen");
				FaderDefeated = CheckGlobalKey("defeated_fader");
				BrennaDefeated = CheckGlobalKey("hildir1");
				GeirrhafaDefeated = CheckGlobalKey("hildir2");
				ThungrNZilDefeated = CheckGlobalKey("hildir3");
			}
		}

		private static readonly LogManager log = new LogManager("Global Key Checker", LogManager.LogLevel.Warning);

		public static bool EikthyrDefeated = false;

		public static bool ElderDefeated = false;

		public static bool BonemassDefeated = false;

		public static bool ModerDefeated = false;

		public static bool YagluthDefeated = false;

		public static bool QueenDefeated = false;

		public static bool FaderDefeated = false;

		public static bool BrennaDefeated = false;

		public static bool GeirrhafaDefeated = false;

		public static bool ThungrNZilDefeated = false;

		private static readonly Dictionary<string, bool> globalKeyStates = new Dictionary<string, bool>
		{
			{ "defeated_eikthyr", false },
			{ "defeated_gdking", false },
			{ "defeated_bonemass", false },
			{ "defeated_dragon", false },
			{ "defeated_goblinking", false },
			{ "defeated_queen", false },
			{ "defeated_fader", false },
			{ "hildir1", false },
			{ "hildir2", false },
			{ "hildir3", false }
		};

		private static readonly Dictionary<string, string> bossToGlobalKey = new Dictionary<string, string>
		{
			{ "Eikthyr", "defeated_eikthyr" },
			{ "The Elder", "defeated_gdking" },
			{ "Bonemass", "defeated_bonemass" },
			{ "Moder", "defeated_dragon" },
			{ "Yagluth", "defeated_goblinking" },
			{ "The Queen", "defeated_queen" },
			{ "Fader", "defeated_fader" },
			{ "Brenna", "hildir1" },
			{ "Geirrhafa", "hildir2" },
			{ "ThungrNZil", "hildir3" }
		};

		private static void UpdateDefeatedStates(ZoneSystem zoneSystem)
		{
			List<string> globalKeys = zoneSystem.GetGlobalKeys();
			foreach (string item in globalKeyStates.Keys.ToList())
			{
				bool flag = globalKeys.Contains(item);
				if (globalKeyStates[item] != flag)
				{
					globalKeyStates[item] = flag;
				}
			}
		}

		private static bool CheckGlobalKey(string globalKey)
		{
			return globalKeyStates.ContainsKey(globalKey) && globalKeyStates[globalKey];
		}

		public static bool IsBossDefeated(string boss)
		{
			if (bossToGlobalKey.TryGetValue(boss, out var value))
			{
				return CheckGlobalKey(value);
			}
			log.Warn("IsBossDefeated called with unknown boss: " + boss);
			return false;
		}
	}
}
namespace MarsarahTweaks.Patches.UI
{
	internal class UIAshlandsHeatLevel : UIController
	{
		[HarmonyPatch(typeof(Character), "UpdateLava")]
		public class GetHeatLevel_Patch
		{
			private static void Postfix(Character __instance, ref float ___m_lavaHeatLevel)
			{
				if ((!((Object)(object)ZNet.instance != (Object)null) || !ZNet.instance.IsDedicated()) && ConfigManager.ShowHeatLevelInAshlands.Value && UIController.ShowUI && __instance is Player)
				{
					heatThreshold = __instance.m_heatLevelFirstDamageThreshold;
					currentHeat = ___m_lavaHeatLevel;
				}
			}
		}

		[HarmonyPatch(typeof(Hud), "Awake")]
		private class InventoryWeightAndSlots_HUDAwakePatch
		{
			private static void Postfix(Hud __instance)
			{
				if ((!((Object)(object)ZNet.instance != (Object)null) || !ZNet.instance.IsDedicated()) && !((Object)(object)__instance == (Object)null) && ConfigManager.ShowInventoryWeightAndSlots.Value)
				{
					CreateUI(__instance);
				}
			}
		}

		[HarmonyPatch(typeof(Hud), "Update")]
		private static class HeatLevelHUDUpdate_Patch
		{
			private static void Postfix(Hud __instance)
			{
				//IL_0082: Unknown result type (might be due to invalid IL or missing references)
				//IL_0089: Invalid comparison between Unknown and I4
				//IL_016f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0174: Unknown result type (might be due to invalid IL or missing references)
				//IL_018c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0191: 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)
				//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
				//IL_01c1: 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_019e: Unknown result type (might be due to invalid IL or missing references)
				//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
				//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
				//IL_0215: Unknown result type (might be due to invalid IL or missing references)
				if (((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsDedicated()) || (Object)(object)__instance == (Object)null)
				{
					return;
				}
				if (ConfigManager.ShowHeatLevelInAshlands.Value)
				{
					CreateUI(__instance);
					if (!Object.op_Implicit((Object)(object)Player.m_localPlayer) || !((Object)(object)heatBarFill != (Object)null) || !(heatThreshold > 0f))
					{
						return;
					}
					if ((int)Player.m_localPlayer.GetCurrentBiome() != 32)
					{
						if ((Object)(object)UIHeatBarArea != (Object)null && UIHeatBarArea.activeSelf)
						{
							UIHeatBarArea.SetActive(false);
						}
						return;
					}
					bool flag = !IsUIHidden() && !IsLoadScreenActive(__instance);
					if (UIHeatBarArea.activeSelf != flag)
					{
						UIHeatBarArea.SetActive(flag);
					}
					heatBarFill.fillAmount = Mathf.Clamp01(currentHeat / heatThreshold);
					if ((Object)(object)heatBarText != (Object)null)
					{
						float num = Mathf.Clamp01(currentHeat / heatThreshold) * 100f;
						heatBarText.text = $"{num:0}%";
					}
					float fillAmount = heatBarFill.fillAmount;
					Color yellow = Color.yellow;
					Color val = default(Color);
					((Color)(ref val))..ctor(1f, 0.549019f, 0f);
					Color red = Color.red;
					Color color = ((fillAmount < 0.5f) ? Color.Lerp(yellow, val, fillAmount * 2f) : Color.Lerp(val, red, (fillAmount - 0.5f) * 2f));
					if (fillAmount > 0.8f)
					{
						float a = 0.6f + 0.4f * Mathf.Sin(Time.time * 4f);
						color.a = a;
					}
					else
					{
						color.a = 0.8f;
					}
					((Graphic)heatBarFill).color = color;
					if (heatBarFill.fillAmount == 0f)
					{
						if ((Object)(object)heatBarFill != (Object)null)
						{
							((Behaviour)heatBarFill).enabled = false;
						}
						if ((Object)(object)heatBarBGImage != (Object)null)
						{
							((Behaviour)heatBarBGImage).enabled = false;
						}
						if ((Object)(object)heatBarText != (Object)null)
						{
							((Behaviour)heatBarText).enabled = false;
						}
						if ((Object)(object)heatBarEmojiTMP != (Object)null)
						{
							((Behaviour)heatBarEmojiTMP).enabled = false;
							((TMP_Text)heatBarEmojiTMP).text = "";
						}
					}
					else
					{
						if ((Object)(object)heatBarFill != (Object)null)
						{
							((Behaviour)heatBarFill).enabled = UIController.ShowUI;
						}
						if ((Object)(object)heatBarBGImage != (Object)null)
						{
							((Behaviour)heatBarBGImage).enabled = UIController.ShowUI;
						}
						if ((Object)(object)heatBarText != (Object)null)
						{
							((Behaviour)heatBarText).enabled = UIController.ShowUI;
						}
						if ((Object)(object)heatBarEmojiTMP != (Object)null)
						{
							((Behaviour)heatBarEmojiTMP).enabled = UIController.ShowUI;
							((TMP_Text)heatBarEmojiTMP).text = "\ud83d\udd25";
						}
					}
				}
				else
				{
					if ((Object)(object)heatBarFill != (Object)null)
					{
						((Behaviour)heatBarFill).enabled = false;
					}
					if ((Object)(object)heatBarBGImage != (Object)null)
					{
						((Behaviour)heatBarBGImage).enabled = false;
					}
					if ((Object)(object)heatBarText != (Object)null)
					{
						((Behaviour)heatBarText).enabled = false;
					}
					if ((Object)(object)heatBarEmojiTMP != (Object)null)
					{
						((Behaviour)heatBarEmojiTMP).enabled = false;
					}
				}
			}

			private static Sprite GenerateWhiteSprite()
			{
				//IL_0003: Unknown result type (might be due to invalid IL or missing references)
				//IL_0009: Expected O, but got Unknown
				//IL_000c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0033: Unknown result type (might be due to invalid IL or missing references)
				//IL_0042: Unknown result type (might be due to invalid IL or missing references)
				Texture2D val = new Texture2D(1, 1);
				val.SetPixel(0, 0, Color.white);
				val.Apply();
				return Sprite.Create(val, new Rect(0f, 0f, 1f, 1f), new Vector2(0.5f, 0.5f));
			}

			private static bool IsLoadScreenActive(Hud hud)
			{
				return Object.op_Implicit((Object)(object)Hud.instance) && Object.op_Implicit((Object)(object)hud.m_loadingScreen) && ((Component)hud.m_loadingScreen).gameObject.activeSelf;
			}

			private static bool IsUIHidden()
			{
				return Hud.IsUserHidden();
			}
		}

		private static readonly LogManager log = new LogManager("UI Ashlands Heat", LogManager.LogLevel.Warning);

		private static Image heatBarFill = null;

		private static Image heatBarBGImage = null;

		private static GameObject UIHeatBarArea = null;

		private static Text heatBarText = null;

		private static TextMeshProUGUI heatBarEmojiTMP = null;

		private static float heatThreshold;

		private static float currentHeat;

		private static void CreateUI(Hud hud)
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Expected O, but got Unknown
			//IL_008f: 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)
			//IL_00bd: 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_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Expected O, but got Unknown
			//IL_0138: 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_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: 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_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: Expected O, but got Unknown
			//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0210: Unknown result type (might be due to invalid IL or missing references)
			//IL_029d: Unknown result type (might be due to invalid IL or missing references)
			//IL_02af: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e5: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)UIHeatBarArea != (Object)null))
			{
				Vector2 sizeDelta = default(Vector2);
				((Vector2)(ref sizeDelta))..ctor(200f, 25f);
				int fontSize = 13;
				int fontSize2 = 10;
				string fontName = "AveriaSansLibre-Bold";
				string fontName2 = "NotoEmoji-Regular SDF";
				UIHeatBarArea = new GameObject("HeatBar");
				UIHeatBarArea.layer = 5;
				UIHeatBarArea.transform.SetParent(hud.m_rootObject.transform.parent, false);
				RectTransform val = UIHeatBarArea.AddComponent<RectTransform>();
				val.anchorMin = new Vector2(0.5f, 0.5f);
				val.anchorMax = new Vector2(0.5f, 0.5f);
				val.pivot = new Vector2(0.5f, 0.5f);
				val.anchoredPosition = new Vector2(0f, 350f);
				val.sizeDelta = sizeDelta;
				UIHeatBarArea.transform.localScale = Vector3.one;
				GameObject val2 = new GameObject("HeatBarBackground");
				val2.transform.SetParent(UIHeatBarArea.transform, false);
				heatBarBGImage = val2.AddComponent<Image>();
				RectTransform component = val2.GetComponent<RectTransform>();
				component.anchorMin = Vector2.zero;
				component.anchorMax = Vector2.one;
				component.offsetMin = Vector2.zero;
				component.offsetMax = Vector2.zero;
				((Graphic)heatBarBGImage).color = new Color(0f, 0f, 0f, 0.4f);
				((Behaviour)heatBarBGImage).enabled = false;
				GameObject val3 = new GameObject("HeatBarFill");
				val3.transform.SetParent(UIHeatBarArea.transform, false);
				heatBarFill = val3.AddComponent<Image>();
				RectTransform component2 = val3.GetComponent<RectTransform>();
				component2.anchorMin = Vector2.zero;
				component2.anchorMax = Vector2.one;
				component2.offsetMin = new Vector2(3f, 3f);
				component2.offsetMax = new Vector2(-3f, -3f);
				Sprite sprite = ((IEnumerable<Sprite>)Resources.FindObjectsOfTypeAll<Sprite>()).FirstOrDefault((Func<Sprite, bool>)((Sprite s) => ((Object)s).name == "bar_monster_hp_5"));
				heatBarFill.sprite = sprite;
				heatBarFill.type = (Type)3;
				heatBarFill.fillMethod = (FillMethod)0;
				heatBarFill.fillOrigin = 0;
				heatBarFill.fillAmount = 0f;
				((Behaviour)heatBarFill).enabled = false;
				heatBarText = UIController.CreateTextObject("HeatText", UIHeatBarArea, Color.white, fontName, fontSize, (TextAnchor)4, new Vector2(0f, 0f), sizeDelta);
				heatBarEmojiTMP = UIController.CreateTMPTextObject("HeatEmojiTMP", UIHeatBarArea, Color.red, fontName2, fontSize2, (TextAlignmentOptions)4100, new Vector2(-2f, 0f), sizeDelta, log);
			}
		}
	}
	internal class UIBoatSpeed : UIController
	{
		[HarmonyPatch(typeof(Ship), "GetSpeed")]
		private class ShowBoatSpeed_Patch
		{
			private static void Prefix(Ship __instance, ref Rigidbody ___m_body)
			{
				//IL_0048: 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)
				if ((!((Object)(object)ZNet.instance != (Object)null) || !ZNet.instance.IsDedicated()) && ConfigManager.ShowBoatSpeed.Value)
				{
					if (Object.op_Implicit((Object)(object)__instance) && __instance.HasPlayerOnboard())
					{
						boatSpeed = Vector3.Dot(___m_body.linearVelocity, ((Component)__instance).transform.forward);
					}
					if (Traverse.Create((object)__instance).Method("HaveControllingPlayer", Array.Empty<object>()).GetValue<bool>())
					{
						showBoatSpeedUI = true;
					}
					else
					{
						showBoatSpeedUI = false;
					}
				}
			}
		}

		[HarmonyPatch(typeof(Hud), "Awake")]
		private class InventoryWeightAndSlots_HUDAwakePatch
		{
			private static void Postfix(Hud __instance)
			{
				if ((!((Object)(object)ZNet.instance != (Object)null) || !ZNet.instance.IsDedicated()) && !((Object)(object)__instance == (Object)null) && ConfigManager.ShowInventoryWeightAndSlots.Value)
				{
					CreateTextBasedUI(__instance);
					CreateSymbolBasedUI(__instance);
				}
			}
		}

		[HarmonyPatch(typeof(Hud), "Update")]
		private static class BoatSpeedHUDUpdate_Patch
		{
			private static void Postfix(Hud __instance)
			{
				//IL_0181: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
				if (((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsDedicated()) || (Object)(object)__instance == (Object)null)
				{
					return;
				}
				if (ConfigManager.ShowBoatSpeed.Value)
				{
					bool flag = ConfigManager.UILayoutChoice.Value == ConfigManager.UIMode.New;
					CreateTextBasedUI(__instance);
					CreateSymbolBasedUI(__instance);
					if (!flag)
					{
						GameObject uIBoatArea = UIBoatArea;
						if (uIBoatArea != null)
						{
							uIBoatArea.SetActive(showBoatSpeedUI && UIController.ShowUI);
						}
						GameObject uIBoatArea2 = UIBoatArea2;
						if (uIBoatArea2 != null)
						{
							uIBoatArea2.SetActive(false);
						}
						if (showBoatSpeedUI && UIController.ShowUI)
						{
							((Graphic)UIBoatText).color = GetColorFromSpeed(boatSpeed);
							UIBoatText.text = ((boatSpeed > 0f) ? boatSpeed.ToString("0.00") : ("R " + Math.Abs(boatSpeed).ToString("0.00")));
							UIBoatTextTitle.text = "Boat speed";
						}
					}
					else
					{
						GameObject uIBoatArea3 = UIBoatArea;
						if (uIBoatArea3 != null)
						{
							uIBoatArea3.SetActive(false);
						}
						GameObject uIBoatArea4 = UIBoatArea2;
						if (uIBoatArea4 != null)
						{
							uIBoatArea4.SetActive(showBoatSpeedUI && UIController.ShowUI);
						}
						if (showBoatSpeedUI && UIController.ShowUI)
						{
							((Graphic)UIBoatText2).color = GetColorFromSpeed(boatSpeed);
							UIBoatText2.text = ((boatSpeed > 0f) ? boatSpeed.ToString("0.00") : ("R " + Math.Abs(boatSpeed).ToString("0.00")));
							((TMP_Text)UIBoatEmojiTMP).text = "⛵";
						}
					}
				}
				else
				{
					CreateTextBasedUI(__instance);
					CreateSymbolBasedUI(__instance);
					GameObject uIBoatArea5 = UIBoatArea;
					if (uIBoatArea5 != null)
					{
						uIBoatArea5.SetActive(false);
					}
					GameObject uIBoatArea6 = UIBoatArea2;
					if (uIBoatArea6 != null)
					{
						uIBoatArea6.SetActive(false);
					}
				}
			}

			private static Color GetColorFromSpeed(float speed)
			{
				//IL_000d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0012: Unknown result type (might be due to invalid IL or missing references)
				//IL_0030: 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_0054: Unknown result type (might be due to invalid IL or missing references)
				//IL_004c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0051: Unknown result type (might be due to invalid IL or missing references)
				//IL_0044: Unknown result type (might be due to invalid IL or missing references)
				//IL_0049: Unknown result type (might be due to invalid IL or missing references)
				if (speed < 2.5f)
				{
					return Color.red;
				}
				if (speed < 5f)
				{
					return new Color(1f, 0.549019f, 0f);
				}
				if (speed < 7.5f)
				{
					return Color.yellow;
				}
				return Color.green;
			}
		}

		private static readonly LogManager log = new LogManager("UI Boat Speed", LogManager.LogLevel.Warning);

		private static float boatSpeed;

		private static bool showBoatSpeedUI;

		internal static GameObject UIBoatArea = null;

		private static Text UIBoatText = null;

		private static Text UIBoatTextTitle = null;

		internal static GameObject UIBoatArea2 = null;

		private static Text UIBoatText2 = null;

		private static TextMeshProUGUI UIBoatEmojiTMP = null;

		private static void CreateTextBasedUI(Hud hud)
		{
			//IL_0066: 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_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Expected O, but got Unknown
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: 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_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_0213: Unknown result type (might be due to invalid IL or missing references)
			//IL_0218: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)UIBoatArea != (Object)null) || !((Object)(object)UIBoatText != (Object)null) || !((Object)(object)UIBoatTextTitle != (Object)null))
			{
				bool flag = ConfigManager.UILayoutChoice.Value == ConfigManager.UIMode.New;
				int fontSize = 16;
				string fontName = "AveriaSansLibre-Bold";
				Vector2 val = default(Vector2);
				((Vector2)(ref val))..ctor(155f, 30f);
				Vector2 sizeDelta = default(Vector2);
				if (!flag)
				{
					sizeDelta = val;
				}
				else
				{
					((Vector2)(ref sizeDelta))..ctor(155f, 30f);
				}
				UIBoatArea = new GameObject("BoatArea");
				UIBoatArea.layer = 5;
				UIBoatArea.transform.SetParent(((Component)hud.m_healthPanel).transform);
				RectTransform val2 = UIBoatArea.AddComponent<RectTransform>();
				val2.anchorMin = new Vector2(1f, 1f);
				val2.anchorMax = new Vector2(1f, 1f);
				val2.anchoredPosition = new Vector2((ConfigManager.ShowInventoryWeightAndSlots.Value && ConfigManager.ShowEnemyDetector.Value) ? 203f : ((ConfigManager.ShowInventoryWeightAndSlots.Value || ConfigManager.ShowEnemyDetector.Value) ? 100f : (-40f)), -230f);
				val2.sizeDelta = sizeDelta;
				UIBoatArea.transform.localScale = Vector3.one;
				Sprite sprite = ((IEnumerable<Sprite>)Resources.FindObjectsOfTypeAll<Sprite>()).FirstOrDefault((Func<Sprite, bool>)((Sprite tempSprite) => ((Object)tempSprite).name == "InputFieldBackground"));
				Image val3 = UIBoatArea.AddComponent<Image>();
				((Graphic)val3).color = new Color(0f, 0f, 0f, 0.4f);
				val3.sprite = sprite;
				val3.type = (Type)1;
				UIBoatTextTitle = UIController.CreateTextObject("BoatTextTitle", UIBoatArea, Color.white, fontName, fontSize, (TextAnchor)4, new Vector2(-25f, 0f), val);
				UIBoatText = UIController.CreateTextObject("BoatText", UIBoatArea, Color.white, fontName, fontSize, (TextAnchor)4, new Vector2(45f, 0f), sizeDelta);
			}
		}

		private static void CreateSymbolBasedUI(Hud hud)
		{
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Expected O, but got Unknown
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_018d: 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_01aa: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)UIBoatArea2 != (Object)null) || !((Object)(object)UIBoatText2 != (Object)null) || !((Object)(object)UIBoatEmojiTMP != (Object)null))
			{
				int num = 16;
				string fontName = "AveriaSansLibre-Bold";
				string fontName2 = "NotoEmoji-Regular SDF";
				Vector2 sizeDelta = default(Vector2);
				((Vector2)(ref sizeDelta))..ctor(80f, 30f);
				float num2 = (Game.m_noMap ? (-145f) : (-283f));
				float num3 = -225f;
				if (AppDomain.CurrentDomain.GetAssemblies().Any((Assembly a) => a.GetName().Name == "MinimalStatusEffects"))
				{
					num2 = -360f;
					num3 = -25f;
				}
				UIBoatArea2 = new GameObject("BoatArea2");
				UIBoatArea2.layer = 5;
				UIBoatArea2.transform.SetParent(hud.m_rootObject.transform);
				RectTransform val = UIBoatArea2.AddComponent<RectTransform>();
				val.anchorMin = new Vector2(1f, 1f);
				val.anchorMax = new Vector2(1f, 1f);
				val.anchoredPosition = new Vector2(num2, num3);
				val.sizeDelta = sizeDelta;
				UIBoatArea2.transform.localScale = Vector3.one;
				UIBoatText2 = UIController.CreateTextObject("BoatText2", UIBoatArea2, Color.white, fontName, num, (TextAnchor)5, new Vector2(-4f, 0f), sizeDelta);
				UIBoatEmojiTMP = UIController.CreateTMPTextObject("BoatEmojiTMP", UIBoatArea2, Color.white, fontName2, num + 4, (TextAlignmentOptions)4097, new Vector2(4f, 0f), sizeDelta, log);
			}
		}
	}
	internal class UIBossPowerExpiration
	{
		[HarmonyPatch(typeof(StatusEffect), "Stop")]
		public class StatusEffectStopPatch
		{
			public static void Postfix(StatusEffect __instance)
			{
				if (!ConfigManager.ShowBossExpirationMessage.Value)
				{
					return;
				}
				Character character = __instance.m_character;
				if (!((Object)(object)character == (Object)null) && character.IsPlayer() && character.IsOwner())
				{
					string name = ((Object)__instance).name;
					log.Info("SE Name: " + name);
					if (name.Contains("GP_"))
					{
						string text = Localization.instance.Localize(__instance.m_name);
						character.Message((MessageType)2, text + " Power Expired", 0, (Sprite)null);
					}
				}
			}
		}

		private static readonly LogManager log = new LogManager("UI Boss Power Expire", LogManager.LogLevel.Warning);
	}
	internal class UIController
	{
		[HarmonyPatch(typeof(Hud), "Awake")]
		private static class HudAwakePatch
		{
			private static void Prefix()
			{
				TMP_FontAsset val = ((IEnumerable<TMP_FontAsset>)Resources.FindObjectsOfTypeAll<TMP_FontAsset>()).FirstOrDefault((Func<TMP_FontAsset, bool>)((TMP_FontAsset f) => ((Object)f).name == "NotoEmoji-Regular SDF"));
				if ((Object)(object)val != (Object)null)
				{
					TMP_Settings.defaultFontAsset = val;
					log.Info("Set default TMP font asset to NotoEmoji-Regular SDF");
				}
				else
				{
					log.Warn("NotoEmoji font not found.");
				}
			}
		}

		private static readonly LogManager log = new LogManager("UI Controller", LogManager.LogLevel.Warning);

		internal static bool ShowUI = true;

		internal static bool ShowPlayerList = true;

		private static ConfigManager.UIMode LastLayout = ConfigManager.UIMode.New;

		public static void LogAllTMPFonts()
		{
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			TMP_FontAsset[] array = Resources.FindObjectsOfTypeAll<TMP_FontAsset>();
			if (array.Length == 0)
			{
				Debug.LogWarning((object)"[TMPDebug] No TMP_FontAssets found in memory!");
				return;
			}
			Debug.Log((object)$"[TMPDebug] {array.Length} TMP_FontAssets found in memory:");
			foreach (TMP_FontAsset item in array.OrderBy((TMP_FontAsset f) => ((Object)f).name))
			{
				string text = (((Object)(object)item != (Object)null) ? $"name: '{((Object)item).name}', hideFlags: {((Object)item).hideFlags}" : "null font");
				Debug.Log((object)("[TMPDebug] " + text));
			}
		}

		public static void UpdateUIDisplay()
		{
			ConfigManager.UIMode value = ConfigManager.UILayoutChoice.Value;
			if (LastLayout != value)
			{
				ShowUI = true;
				ShowPlayerList = true;
			}
			if (Input.GetKeyDown((KeyCode)277))
			{
				ShowUI = !ShowUI;
			}
			if (Input.GetKeyDown((KeyCode)278))
			{
				ShowPlayerList = !ShowPlayerList;
			}
			LastLayout = value;
		}

		public static Text CreateTextObject(string name, GameObject parent, Color textColor, string fontName, int fontSize, TextAnchor alignment, Vector2 position, Vector2 sizeDelta)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Expected O, but got Unknown
			//IL_0037: 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)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name);
			val.layer = 5;
			val.transform.SetParent(parent.transform);
			RectTransform val2 = val.AddComponent<RectTransform>();
			val2.anchoredPosition = position;
			val2.sizeDelta = sizeDelta;
			((Transform)val2).localScale = Vector3.one;
			Text val3 = val.AddComponent<Text>();
			((Graphic)val3).color = textColor;
			val3.font = ((IEnumerable<Font>)Resources.FindObjectsOfTypeAll<Font>()).FirstOrDefault((Func<Font, bool>)((Font f) => ((Object)f).name == fontName));
			val3.fontSize = fontSize;
			val3.alignment = alignment;
			Outline val4 = val.AddComponent<Outline>();
			((Shadow)val4).effectColor = Color.black;
			((Shadow)val4).effectDistance = new Vector2(1f, -1f);
			((Shadow)val4).useGraphicAlpha = true;
			((MonoBehaviour)val4).useGUILayout = true;
			return val3;
		}

		public static TextMeshProUGUI CreateTMPTextObject(string name, GameObject parent, Color textColor, string fontName, int fontSize, TextAlignmentOptions alignment, Vector2 position, Vector2 sizeDelta, LogManager specificLog)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Expected O, but got Unknown
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name);
			val.layer = 5;
			val.transform.SetParent(parent.transform, false);
			RectTransform val2 = val.AddComponent<RectTransform>();
			val2.anchoredPosition = position;
			val2.sizeDelta = sizeDelta;
			((Transform)val2).localScale = Vector3.one;
			TextMeshProUGUI val3 = val.AddComponent<TextMeshProUGUI>();
			((Graphic)val3).color = textColor;
			((TMP_Text)val3).font = ((IEnumerable<TMP_FontAsset>)Resources.FindObjectsOfTypeAll<TMP_FontAsset>()).FirstOrDefault((Func<TMP_FontAsset, bool>)((TMP_FontAsset f) => ((Object)f).name == fontName));
			((TMP_Text)val3).fontSize = fontSize;
			((TMP_Text)val3).alignment = alignment;
			((TMP_Text)val3).text = "";
			if ((Object)(object)((TMP_Text)val3).font != (Object)null)
			{
				object obj = val3;
				obj = ((!((Object)(object)((TMP_Text)val3).fontMaterial != (Object)null)) ? ((object)((TMP_Asset)((TMP_Text)val3).font).material) : ((object)new Material(((TMP_Text)val3).fontMaterial)));
				((TMP_Text)obj).fontMaterial = (Material)obj;
				if (((TMP_Text)val3).fontMaterial.HasProperty(ShaderUtilities.ID_OutlineWidth) && ((TMP_Text)val3).fontMaterial.HasProperty(ShaderUtilities.ID_OutlineColor))
				{
					((TMP_Text)val3).fontMaterial.SetFloat(ShaderUtilities.ID_OutlineWidth, 0.125f);
					((TMP_Text)val3).fontMaterial.SetColor(ShaderUtilities.ID_OutlineColor, Color.black);
				}
				((TMP_Text)val3).havePropertiesChanged = true;
				((Graphic)val3).SetAllDirty();
				((TMP_Text)val3).ForceMeshUpdate(false, false);
			}
			else
			{
				specificLog.Warn("Font material for '" + fontName + "' is null or font is missing. Skipping outline setup.");
			}
			return val3;
		}

		public static Image CreateUIImageObject(string name, GameObject parent, Vector2 position, Vector2 sizeDelta)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Expected O, but got Unknown
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name);
			val.layer = 5;
			val.transform.SetParent(parent.transform, false);
			RectTransform val2 = val.AddComponent<RectTransform>();
			val2.anchoredPosition = position;
			val2.sizeDelta = sizeDelta;
			((Transform)val2).localScale = Vector3.one;
			Image val3 = val.AddComponent<Image>();
			((Graphic)val3).color = Color.white;
			return val3;
		}

		public static void UpdateUIPositions()
		{
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			if (ConfigManager.UILayoutChoice.Value != 0)
			{
				float num = -45f;
				float num2 = -230f;
				bool flag = (Object)(object)UIInventoryWeightAndSlots.UIInventoryArea != (Object)null && ConfigManager.ShowInventoryWeightAndSlots.Value;
				bool flag2 = (Object)(object)UIEnemyDetector.UIEnemyArea != (Object)null && ConfigManager.ShowEnemyDetector.Value;
				bool flag3 = (Object)(object)UIBoatSpeed.UIBoatArea != (Object)null && ConfigManager.ShowBoatSpeed.Value;
				if (flag)
				{
					num += 115f;
					if (!flag2 && flag3)
					{
						num += 30f;
					}
				}
				if (flag2)
				{
					UIEnemyDetector.UIEnemyArea.GetComponent<RectTransform>().anchoredPosition = new Vector2(num, num2);
					num += 133f;
				}
				if (flag3)
				{
					UIBoatSpeed.UIBoatArea.GetComponent<RectTransform>().anchoredPosition = new Vector2(num, num2);
				}
			}
			else
			{
				float num3 = -10f;
				float num4 = -230f;
				bool flag4 = (Object)(object)UIInventoryWeightAndSlots.UIWeightBarArea != (Object)null && (Object)(object)UIInventoryWeightAndSlots.UISlotsArea != (Object)null && ConfigManager.ShowInventoryWeightAndSlots.Value;
				bool flag5 = (Object)(object)UIEnemyDetector.UIEnemyArea2 != (Object)null && (Object)(object)UIEnemyDetector.UIFriendlyArea != (Object)null && ConfigManager.ShowEnemyDetector.Value;
				if (flag4)
				{
					num3 += 132f;
				}
				else if (flag5)
				{
					num3 -= 55f;
				}
				if (flag5)
				{
					UIEnemyDetector.UIEnemyArea2.GetComponent<RectTransform>().anchoredPosition = new Vector2(num3, num4);
					UIEnemyDetector.UIFriendlyArea.GetComponent<RectTransform>().anchoredPosition = new Vector2(num3 + 54f, num4);
				}
			}
		}
	}
	internal class UIDetailedHovers
	{
		[HarmonyPatch(typeof(Container), "GetHoverText")]
		internal static class DetailedHoverContainer_Patch
		{
			private static void Postfix(Container __instance, Inventory ___m_inventory, ref string __result)
			{
				if (ConfigManager.DetailedHoverInfoChoice.Value != ConfigManager.HoverInfoMode.Off && ___m_inventory.NrOfItems() != 0)
				{
					__result = GetContainerHover(__instance, ___m_inventory);
				}
			}

			public static string GetContainerHover(Container container, Inventory inventory)
			{
				//IL_0065: Unknown result type (might be due to invalid IL or missing references)
				//IL_0098: 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_0129: Unknown result type (might be due to invalid IL or missing references)
				ConfigManager.ContainerHoverMode value = ConfigManager.ContainerHoverModeChoice.Value;
				int num = inventory.GetWidth() * inventory.GetHeight();
				string text = "";
				switch (value)
				{
				case ConfigManager.ContainerHoverMode.CurrentPerMax:
				{
					int num3 = inventory.NrOfItems();
					string text4 = $"{num3}/{num}";
					text = PaintTextIfEnabled(text4, GetInventoryRatioColor(num3, num));
					break;
				}
				case ConfigManager.ContainerHoverMode.AmountOfFreeSlots:
				{
					int emptySlots = inventory.GetEmptySlots();
					string text3 = $"{emptySlots}";
					text = "Free Slots: " + PaintTextIfEnabled(text3, GetInventoryEmptySlotsColor(emptySlots, num));
					break;
				}
				case ConfigManager.ContainerHoverMode.Percent:
				{
					float num2 = inventory.SlotsUsedPercentage();
					float percent = num2 / 100f;
					string text2 = $"{num2}%";
					text = PaintTextIfEnabled(text2, GetPercentColorInverted(percent));
					break;
				}
				}
				string text5 = Localization.instance.Localize(container.m_name);
				string text6 = Localization.instance.Localize("$piece_container_open");
				string text7 = Localization.instance.Localize("$msg_stackall_hover");
				string text8 = "[" + PaintText(Localization.instance.Localize("$KEY_Use"), Color.yellow) + "]";
				string containerInventoryList = GetContainerInventoryList(inventory);
				string text9 = ((containerInventoryList != "") ? (text5 + " (" + text + ")\n" + text8 + " " + text6 + " " + text7 + "\n\n" + containerInventoryList) : (text5 + " (" + text + ")\n" + text8 + " " + text6 + " " + text7));
				LogHoverText(text9);
				return text9;
			}

			private static string GetContainerInventoryList(Inventory inventory)
			{
				//IL_012b: Unknown result type (might be due to invalid IL or missing references)
				//IL_013f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0191: Unknown result type (might be due to invalid IL or missing references)
				//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
				//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
				if (!ConfigManager.ShowContainerContents.Value)
				{
					return "";
				}
				Dictionary<string, int> dictionary = new Dictionary<string, int>();
				foreach (ItemData allItem in inventory.GetAllItems())
				{
					if (allItem?.m_shared != null)
					{
						string key = Localization.instance.Localize(allItem.m_shared.m_name);
						if (!dictionary.ContainsKey(key))
						{
							dictionary[key] = 0;
						}
						dictionary[key] += allItem.m_stack;
					}
				}
				if (dictionary.Count == 0)
				{
					return "";
				}
				StringBuilder stringBuilder = new StringBuilder();
				int num = 0;
				int count = dictionary.Count;
				foreach (KeyValuePair<string, int> item in dictionary)
				{
					if (num >= 10)
					{
						break;
					}
					string text = PaintTextIfEnabled(item.Value.ToString(), Color.yellow);
					string text2 = PaintTextIfEnabled(item.Key, Color.gray);
					stringBuilder.AppendLine(text + " " + text2);
					num++;
				}
				if (count > 10)
				{
					string text3 = PaintTextIfEnabled("+", Color.yellow);
					string text4 = PaintTextIfEnabled((count - 10).ToString(), Color.yellow);
					string text5 = PaintTextIfEnabled(" Others", Color.gray);
					stringBuilder.AppendLine(text3 + text4 + text5);
				}
				return stringBuilder.ToString().TrimEnd(Array.Empty<char>());
			}

			private static Color GetInventoryRatioColor(int used, int max)
			{
				//IL_0038: 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_0049: Unknown result type (might be due to invalid IL or missing references)
				//IL_001a: Unknown result type (might be due to invalid IL or missing references)
				//IL_001f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0031: Unknown result type (might be due to invalid IL or missing references)
				//IL_004e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0051: Unknown result type (might be due to invalid IL or missing references)
				float num = ((max > 0) ? ((float)used / (float)max) : 0f);
				return (num < 0.5f) ? Color.Lerp(Color.green, Color.yellow, num / 0.5f) : Color.Lerp(Color.yellow, Color.red, (num - 0.5f) / 0.5f);
			}

			private static Color GetInventoryEmptySlotsColor(int empty, int max)
			{
				//IL_0038: 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_0049: Unknown result type (might be due to invalid IL or missing references)
				//IL_001a: Unknown result type (might be due to invalid IL or missing references)
				//IL_001f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0031: Unknown result type (might be due to invalid IL or missing references)
				//IL_004e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0051: Unknown result type (might be due to invalid IL or missing references)
				float num = ((max > 0) ? ((float)empty / (float)max) : 0f);
				return (num < 0.5f) ? Color.Lerp(Color.red, Color.yellow, num / 0.5f) : Color.Lerp(Color.yellow, Color.green, (num - 0.5f) / 0.5f);
			}
		}

		[HarmonyPatch(typeof(Beehive), "GetHoverText")]
		internal static class DetailedHoverBeehive_Patch
		{
			private static bool Prefix(Beehive __instance, ZNetView ___m_nview, ref string __result)
			{
				//IL_001c: Unknown result type (might be due to invalid IL or missing references)
				if (ConfigManager.DetailedHoverInfoChoice.Value == ConfigManager.HoverInfoMode.Off)
				{
					return true;
				}
				if (!PrivateArea.CheckAccess(((Component)__instance).transform.position, 0f, false, false))
				{
					__result = Localization.instance.Localize(__instance.m_name + "\n$piece_noaccess");
					return false;
				}
				__result = GetBeehiveHover(__instance, ___m_nview);
				return false;
			}

			private static string GetBeehiveHover(Beehive beehive, ZNetView m_nview)
			{
				//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
				//IL_0116: Unknown result type (might be due to invalid IL or missing references)
				//IL_012d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0176: Unknown result type (might be due to invalid IL or missing references)
				//IL_019b: Unknown result type (might be due to invalid IL or missing references)
				//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
				//IL_02bb: Unknown result type (might be due to invalid IL or missing references)
				string text = Localization.instance.Localize(beehive.m_name);
				if (GetHoneyLevelMethod == null)
				{
					log.Warn("Beehive reflection fields not found.");
					return text;
				}
				int num = (int)GetHoneyLevelMethod.Invoke(beehive, null);
				float @float = m_nview.GetZDO().GetFloat("product", 0f);
				float seconds = beehive.m_secPerUnit - @float;
				ConfigManager.BeeHoverMode value = ConfigManager.BeehiveHoverModeChoice.Value;
				string text2 = "";
				switch (value)
				{
				case ConfigManager.BeeHoverMode.Percent:
				{
					float num2 = Mathf.Clamp01(@float / beehive.m_secPerUnit);
					string text3 = $"{num2:0%}";
					text2 = PaintTextIfEnabled(text3, GetPercentColor(num2));
					break;
				}
				case ConfigManager.BeeHoverMode.RemainingTime:
				{
					string text5 = FormatTime(seconds);
					text2 = PaintTextIfEnabled(text5, Color.cyan);
					break;
				}
				case ConfigManager.BeeHoverMode.PercentAndTime:
				{
					float num2 = Mathf.Clamp01(@float / beehive.m_secPerUnit);
					string text3 = $"{num2:0%}";
					string text4 = PaintTextIfEnabled(text3, GetPercentColor(num2));
					string text5 = FormatTime(seconds);
					string text6 = PaintTextIfEnabled(text5, Color.cyan);
					text2 = text4 + " - " + text6;
					break;
				}
				}
				string text7 = Localization.instance.Localize(beehive.m_honeyItem.m_itemData.m_shared.m_name);
				string text8 = PaintTextIfEnabled(text7, GetHoneyColor(num, beehive.m_maxHoney));
				string text9 = PaintTextIfEnabled("x" + num, GetHoneyColor(num, beehive.m_maxHoney));
				string text10 = "[" + PaintText(Localization.instance.Localize("$KEY_Use"), Color.yellow) + "]";
				string result;
				if (num == beehive.m_maxHoney)
				{
					result = text + " ( " + text8 + " " + text9 + " )\n" + text10 + " " + Localization.instance.Localize("$piece_beehive_extract");
				}
				else if (num > 0)
				{
					result = text + " ( " + text2 + ", " + text8 + " " + text9 + " )\n" + text10 + " " + Localization.instance.Localize("$piece_beehive_extract");
				}
				else
				{
					string text11 = PaintTextIfEnabled(Localization.instance.Localize("$piece_container_empty"), GetEmptyColor());
					result = text + " ( " + text2 + ", " + text11 + " )\n" + text10 + " " + Localization.instance.Localize("$piece_beehive_check");
				}
				return result;
			}

			private static Color GetHoneyColor(int honeyLevel, int maxHoney)
			{
				//IL_0038: 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_0049: Unknown result type (might be due to invalid IL or missing references)
				//IL_001a: Unknown result type (might be due to invalid IL or missing references)
				//IL_001f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0031: Unknown result type (might be due to invalid IL or missing references)
				//IL_004e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0051: Unknown result type (might be due to invalid IL or missing references)
				float num = ((maxHoney > 0) ? ((float)honeyLevel / (float)maxHoney) : 0f);
				return (num < 0.5f) ? Color.Lerp(Color.red, Color.yellow, num / 0.5f) : Color.Lerp(Color.yellow, Color.green, (num - 0.5f) / 0.5f);
			}

			private static Color GetEmptyColor()
			{
				//IL_000f: Unknown result type (might be due to invalid IL or missing references)
				return new Color(1f, 0.4f, 0f);
			}
		}

		[HarmonyPatch(typeof(Plant), "GetHoverText")]
		internal static class DetailedHoverPlant_Patch
		{
			private static bool Prefix(Plant __instance, ref string __result)
			{
				//IL_001c: Unknown result type (might be due to invalid IL or missing references)
				if (ConfigManager.DetailedHoverInfoChoice.Value == ConfigManager.HoverInfoMode.Off)
				{
					return true;
				}
				if (!PrivateArea.CheckAccess(((Component)__instance).transform.position, 0f, false, false))
				{
					__result = Localization.instance.Localize(__instance.m_name + "\n$piece_noaccess");
					return false;
				}
				__result = GetPlantHover(__instance);
				return false;
			}

			private static string GetPlantHover(Plant plant)
			{
				//IL_00e3: 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_0115: Unknown result type (might be due to invalid IL or missing references)
				//IL_013d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0170: Unknown result type (might be due to invalid IL or missing references)
				string text = Localization.instance.Localize(plant.m_name);
				if (GetTimeSincePlantedMethod == null)
				{
					log.Warn("Plant reflection fields not found.");
					return text;
				}
				ConfigManager.PlantHoverMode value = ConfigManager.PlantHoverModeChoice.Value;
				double num = (double)GetTimeSincePlantedMethod.Invoke(plant, null);
				float num2 = (float)GetGrowTimeMethod.Invoke(plant, null);
				string text2 = "";
				switch (value)
				{
				case ConfigManager.PlantHoverMode.Percent:
				{
					float num3 = Mathf.Clamp01((float)(num / (double)num2));
					string text3 = $"{num3:0%}";
					text2 = PaintTextIfEnabled(text3, GetPercentColor(num3));
					break;
				}
				case ConfigManager.PlantHoverMode.RemainingTime:
				{
					float seconds = Mathf.Max(0f, num2 - (float)num);
					string text5 = FormatTime(seconds);
					text2 = PaintTextIfEnabled(text5, Color.cyan);
					break;
				}
				case ConfigManager.PlantHoverMode.PercentAndTime:
				{
					float num3 = Mathf.Clamp01((float)(num / (double)num2));
					string text3 = $"{num3:0%}";
					string text4 = PaintTextIfEnabled(text3, GetPercentColor(num3));
					float seconds = Mathf.Max(0f, num2 - (float)num);
					string text5 = FormatTime(seconds);
					string text6 = PaintTextIfEnabled(text5, Color.cyan);
					text2 = text4 + " - " + text6;
					break;
				}
				}
				string text7 = "[" + PaintText(Localization.instance.Localize("$KEY_Use"), Color.yellow) + "]";
				return (!(num >= (double)num2)) ? (text + " ( " + text2 + " )") : (text + " ( " + Localization.instance.Localize("$hud_ready") + " )\n" + text7 + " " + Localization.instance.Localize("$inventory_pickup"));
			}
		}

		[HarmonyPatch(typeof(Fermenter), "GetHoverText")]
		internal static class DetailedHoverFermenter_Patch
		{
			private static bool Prefix(Fermenter __instance, bool ___m_exposed, ref string __result)
			{
				//IL_001c: Unknown result type (might be due to invalid IL or missing references)
				if (ConfigManager.DetailedHoverInfoChoice.Value == ConfigManager.HoverInfoMode.Off)
				{
					return true;
				}
				if (!PrivateArea.CheckAccess(((Component)__instance).transform.position, 0f, false, false))
				{
					__result = Localization.instance.Localize(__instance.m_name + "\n$piece_noaccess");
					return false;
				}
				string fermenterHover = GetFermenterHover(__instance, ___m_exposed);
				if (fermenterHover == null)
				{
					return true;
				}
				__result = fermenterHover;
				return false;
			}

			private static string GetFermenterHover(Fermenter fermenter, bool exposed)
			{
				//IL_035a: Unknown result type (might be due to invalid IL or missing references)
				//IL_037f: Unknown result type (might be due to invalid IL or missing references)
				//IL_022a: Unknown result type (might be due to invalid IL or missing references)
				//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
				//IL_0299: Unknown result type (might be due to invalid IL or missing references)
				//IL_02c3: Unknown result type (might be due to invalid IL or missing references)
				string text = Localization.instance.Localize(fermenter.m_name);
				if (GetFermenterStatusMethod == null || GetFermenterContentNameMethod == null || GetFermentationTimeMethod == null)
				{
					log.Warn("Fermenter reflection fields not found.");
					return null;
				}
				object obj = GetFermenterStatusMethod.Invoke(fermenter, null);
				if (obj == null)
				{
					log.Warn("Fermenter.GetStatus returned null.");
					return null;
				}
				Type returnType = GetFermenterStatusMethod.ReturnType;
				string name = Enum.GetName(returnType, obj);
				string text2 = name;
				string text3 = text2;
				if (!(text3 == "Fermenting"))
				{
					if (text3 == "Ready")
					{
						LogHoverText("Switch case - " + name);
						string text4 = (string)GetFermenterContentNameMethod.Invoke(fermenter, null);
						string text5 = "[" + PaintText(Localization.instance.Localize("$KEY_Use"), Color.yellow) + "]";
						string text6 = PaintTextIfEnabled(Localization.instance.Localize("$piece_fermenter_ready"), Color.green);
						string text7 = Localization.instance.Localize("$piece_fermenter_tap");
						return Localization.instance.Localize(text + " ( " + text6 + " )\n" + text4 + "\n" + text5 + " " + text7);
					}
					LogHoverText("Switch case - " + name);
					return null;
				}
				LogHoverText("Switch case - " + name);
				ConfigManager.FermenterHoverMode value = ConfigManager.FermenterHoverModeChoice.Value;
				string text8 = Localization.instance.Localize((string)GetFermenterContentNameMethod.Invoke(fermenter, null));
				string text9 = Localization.instance.Localize("$piece_fermenter_exposed");
				string text10 = Localization.instance.Localize("$piece_fermenter_fermenting");
				string result = null;
				double num = (double)GetFermentationTimeMethod.Invoke(fermenter, null);
				float fermentationDuration = fermenter.m_fermentationDuration;
				if (exposed)
				{
					return text + " ( " + text8 + " )\n" + text9;
				}
				switch (value)
				{
				case ConfigManager.FermenterHoverMode.Percent:
				{
					float num2 = Mathf.Clamp01((float)(num / (double)fermentationDuration));
					string text11 = $"{num2:0%}";
					string text12 = PaintTextIfEnabled(text11, GetPercentColor(num2));
					result = text + " ( " + text8 + " )\n" + text10 + ": " + text12;
					break;
				}
				case ConfigManager.FermenterHoverMode.RemainingTime:
				{
					float seconds = Mathf.Max(0f, fermentationDuration - (float)num);
					string text13 = FormatTime(seconds);
					string text14 = PaintTextIfEnabled(text13, Color.cyan);
					result = text + " ( " + text8 + " )\n" + text10 + ": " + text14;
					break;
				}
				case ConfigManager.FermenterHoverMode.PercentAndTime:
				{
					float num2 = Mathf.Clamp01((float)(num / (double)fermentationDuration));
					string text11 = $"{num2:0%}";
					string text12 = PaintTextIfEnabled(text11, GetPercentColor(num2));
					float seconds = Mathf.Max(0f, fermentationDuration - (float)num);
					string text13 = FormatTime(seconds);
					string text14 = PaintTextIfEnabled(text13, Color.cyan);
					result = text + " ( " + text8 + " )\n" + text10 + ": " + text12 + " - " + text14;
					break;
				}
				}
				return result;
			}
		}

		[HarmonyPatch(typeof(CookingStation), "Awake")]
		internal static class CookingStation_AddFoodSwitchHoverPatch
		{
			private static void Postfix(CookingStation __instance, ZNetView ___m_nview)
			{
				//IL_005f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0069: Expected O, but got Unknown
				//IL_007b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0085: Expected O, but got Unknown
				if ((Object)(object)__instance.m_addFoodSwitch == (Object)null || __instance.m_addFoodSwitch.m_onHover != null || !___m_nview.IsOwner())
				{
					return;
				}
				__instance.m_addFoodSwitch.m_onHover = (TooltipCallback)delegate
				{
					string text3 = Localization.instance.Localize(GetHoverTextMethod.Invoke(__instance, null) as string);
					if (ConfigManager.DetailedHoverInfoChoice.Value == ConfigManager.HoverInfoMode.Off)
					{
						return text3;
					}
					string cookingStationHover = GetCookingStationHover(__instance);
					return (!string.IsNullOrEmpty(cookingStationHover)) ? cookingStationHover : text3;
				};
				__instance.m_addFuelSwitch.m_onHover = (TooltipCallback)delegate
				{
					//IL_0087: Unknown result type (might be due to invalid IL or missing references)
					string text = Localization.instance.Localize(OnHoverFuelSwitchMethod.Invoke(__instance, null) as string);
					if (ConfigManager.DetailedHoverInfoChoice.Value == ConfigManager.HoverInfoMode.Off)
					{
						return text;
					}
					float num = (float)GetCSFuelMethod.Invoke(__instance, null);
					float num2 = num * (float)__instance.m_secPerFuel;
					string text2 = "";
					return (!(num2 <= 0f)) ? (text + "\nTime Left: " + PaintTextIfEnabled(FormatTime(num2), Color.cyan)) : text;
				};
			}
		}

		[HarmonyPatch(typeof(CookingStation), "GetHoverText")]
		internal static class CookingStationHoverPatch
		{
			private static bool Prefix(CookingStation __instance, ZNetView ___m_nview, ref string __result)
			{
				if (ConfigManager.DetailedHoverInfoChoice.Value == ConfigManager.HoverInfoMode.Off)
				{
					return true;
				}
				if (!___m_nview.IsOwner())
				{
					return true;
				}
				if (__instance.m_useFuel && !__instance.m_requireFire)
				{
					return true;
				}
				string cookingStationHover = GetCookingStationHover(__instance);
				if (cookingStationHover != null)
				{
					__result = cookingStationHover;
					return false;
				}
				return true;
			}
		}

		[HarmonyPatch(typeof(Smelter), "OnHoverAddOre")]
		internal static class SmelterHoverAddPatch
		{
			private static void Postfix(Smelter __instance, ref string __result)
			{
				if (ConfigManager.DetailedHoverInfoChoice.Value != ConfigManager.HoverInfoMode.Off)
				{
					__result = GetSmelterHover(__instance, __result);
				}
			}
		}

		[HarmonyPatch(typeof(Smelter), "OnHoverAddFuel")]
		internal static class SmelterHoverFuelPatch
		{
			private static void Postfix(Smelter __instance, ref string __result)
			{
				if (ConfigManager.DetailedHoverInfoChoice.Value != ConfigManager.HoverInfoMode.Off)
				{
					__result = GetSmelterHover(__instance, __result);
				}
			}
		}

		[HarmonyPatch(typeof(Smelter), "OnHoverEmptyOre")]
		internal static class SmelterHoverEmptyPatch
		{
			private static void Postfix(Smelter __instance, ref string __result)
			{
				if (ConfigManager.DetailedHoverInfoChoice.Value != ConfigManager.HoverInfoMode.Off)
				{
					__result = GetSmelterHover(__instance, __result);
				}
			}
		}

		[HarmonyPatch(typeof(EggGrow), "GetHoverText")]
		internal static class EggGrowHoverPatch
		{
			private static void Postfix(EggGrow __instance, ZNetView ___m_nview, ref string __result)
			{
				if (ConfigManager.DetailedHoverInfoChoice.Value != ConfigManager.HoverInfoMode.Off)
				{
					__result = GetEggHover(__instance, ___m_nview, __result);
				}
			}

			private static string GetEggHover(EggGrow egg, ZNetView m_nview, string originalHover)
			{
				//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
				//IL_016e: Unknown result type (might be due to invalid IL or missing references)
				//IL_019f: Unknown result type (might be due to invalid IL or missing references)
				//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
				//IL_01da: Unknown result type (might be due to invalid IL or missing references)
				if ((Object)(object)m_nview == (Object)null || !m_nview.IsValid())
				{
					return originalHover;
				}
				ZDO zDO = m_nview.GetZDO();
				if (zDO == null)
				{
					return originalHover;
				}
				float @float = zDO.GetFloat(ZDOVars.s_growStart, 0f);
				if (@float <= 0f)
				{
					return originalHover;
				}
				double num = ZNet.instance.GetTimeSeconds() - (double)@float;
				float growTime = egg.m_growTime;
				GameObject grownPrefab = egg.m_grownPrefab;
				object obj = ((grownPrefab == null) ? null : grownPrefab.GetComponent<Character>()?.m_name);
				if (obj == null)
				{
					GameObject grownPrefab2 = egg.m_grownPrefab;
					obj = ((grownPrefab2 != null) ? ((Object)grownPrefab2).name : null) ?? "Unknown";
				}
				string text = (string)obj;
				text = Localization.instance.Localize(text);
				if (num >= (double)growTime)
				{
					return originalHover + "\n" + text + ": " + PaintTextIfEnabled("Hatching soon", Color.green);
				}
				float num2 = Mathf.Clamp01((float)(num / (double)growTime));
				float seconds = Mathf.Max(0f, growTime - (float)num);
				string text2 = "";
				switch (ConfigManager.EggHoverModeChoice.Value)
				{
				case ConfigManager.EggHoverMode.RemainingTime:
					text2 = text + ": " + PaintTextIfEnabled(FormatTime(seconds), Color.cyan);
					break;
				case ConfigManager.EggHoverMode.Percent:
					text2 = text + ": " + PaintTextIfEnabled($"{num2:0%}", GetPercentColor(num2));
					break;
				case ConfigManager.EggHoverMode.PercentAndTime:
				{
					string text3 = PaintTextIfEnabled($"{num2:0%}", GetPercentColor(num2));
					string text4 = PaintTextIfEnabled(FormatTime(seconds), Color.cyan);
					text2 = text + ": " + text3 + " - " + text4;
					break;
				}
				}
				return originalHover + "\n" + text2;
			}
		}

		private static readonly LogManager log = new LogManager("UI Detailed Hover Info", LogManager.LogLevel.Warning);

		private static readonly MethodInfo GetHoneyLevelMethod = typeof(Beehive).GetMethod("GetHoneyLevel", BindingFlags.Instance | BindingFlags.NonPublic);

		private static readonly MethodInfo GetTimeSincePlantedMethod = typeof(Plant).GetMethod("TimeSincePlanted", BindingFlags.Instance | BindingFlags.NonPublic);

		private static readonly MethodInfo GetGrowTimeMethod = typeof(Plant).GetMethod("GetGrowTime", BindingFlags.Instance | BindingFlags.NonPublic);

		private static readonly MethodInfo GetFermenterStatusMethod = typeof(Fermenter).GetMethod("GetStatus", BindingFlags.Instance | BindingFlags.NonPublic);

		private static readonly MethodInfo GetFermenterContentNameMethod = typeof(Fermenter).GetMethod("GetContentName", BindingFlags.Instance | BindingFlags.NonPublic);

		private static readonly MethodInfo GetFermentationTimeMethod = typeof(Fermenter).GetMethod("GetFermentationTime", BindingFlags.Instance | BindingFlags.NonPublic);

		private static readonly MethodInfo GetSlotMethod = typeof(CookingStation).GetMethod("GetSlot", BindingFlags.Instance | BindingFlags.NonPublic);

		private static readonly MethodInfo GetItemConversionMethod = typeof(CookingStation).GetMethod("GetItemConversion", BindingFlags.Instance | BindingFlags.NonPublic);

		private static readonly MethodInfo GetHoverTextMethod = typeof(CookingStation).GetMethod("HoverText", BindingFlags.Instance | BindingFlags.NonPublic);

		private static readonly MethodInfo GetCSFuelMethod = typeof(CookingStation).GetMethod("GetFuel", BindingFlags.Instance | BindingFlags.NonPublic);

		private static readonly MethodInfo OnHoverFuelSwitchMethod = typeof(CookingStation).GetMethod("OnHoverFuelSwitch", BindingFlags.Instance | BindingFlags.NonPublic);

		private static readonly MethodInfo GetQueueSizeMethod = typeof(Smelter).GetMethod("GetQueueSize", BindingFlags.Instance | BindingFlags.NonPublic);

		private static readonly MethodInfo GetFuelMethod = typeof(Smelter).GetMethod("GetFuel", BindingFlags.Instance | BindingFlags.NonPublic);

		private static readonly MethodInfo GetBakeTimerMethod = typeof(Smelter).GetMethod("GetBakeTimer", BindingFlags.Instance | BindingFlags.NonPublic);

		private static string _lastHoverText = "";

		private static string GetCookingStationHover(CookingStation station)
		{
			//IL_0198: 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_00fb: Expected O, but got Unknown
			if (GetSlotMethod == null || GetItemConversionMethod == null)
			{
				log.Warn("CookingStation reflection not found.");
				return null;
			}
			string text = Localization.instance.Localize(station.m_name);
			string text2 = "";
			int num = 0;
			bool flag = false;
			bool flag2 = false;
			for (int i = 0; i < station.m_slots.Length; i++)
			{
				object[] array = new object[4] { i, null, 0f, null };
				GetSlotMethod.Invoke(station, array);
				string text3 = array[1] as string;
				float num2 = (float)array[2];
				if (string.IsNullOrEmpty(text3))
				{
					continue;
				}
				ItemDrop overCookedItem = station.m_overCookedItem;
				if (text3 == ((overCookedItem != null) ? ((Object)overCookedItem).name : null))
				{
					flag2 = true;
					continue;
				}
				ItemConversion val = (ItemConversion)GetItemConversionMethod.Invoke(station, new object[1] { text3 });
				if (val != null)
				{
					num++;
					if (num2 >= val.m_cookTime && num2 < val.m_cookTime * 2f)
					{
						flag = true;
					}
					string text4 = BuildCookingSlotText(val, num2, station, text3);
					text2 = text2 + "\n" + text4;
				}
			}
			if (num == 0 && !flag2)
			{
				return null;
			}
			string text5 = "[" + PaintText(Localization.instance.Localize("$KEY_Use"), Color.yellow) + "]";
			string text6 = Localization.instance.Localize("$piece_cstand_cook");
			string text7 = Localization.instance.Localize("$piece_itemstand_take");
			if (flag || flag2)
			{
				return text + "\n" + text5 + " " + text7 + text2;
			}
			return (num >= station.m_slots.Length) ? (text + text2) : (text + "\n" + text5 + " " + text6 + " " + text2);
		}

		private static string BuildCookingSlotText(ItemConversion conv, float cookedTime, CookingStation station, string currentItemName)
		{
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			//IL_024a: 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_01c8: Unknown result type (might be due to invalid IL or missing references)
			float cookTime = conv.m_cookTime;
			float num = cookTime * 2f;
			GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(currentItemName);
			string text = (((Object)(object)itemPrefab != (Object)null) ? Localization.instance.Localize(itemPrefab.GetComponent<ItemDrop>().m_itemData.m_shared.m_name) : currentItemName);
			switch (ConfigManager.CookingStationHoverModeChoice.Value)
			{
			case ConfigManager.CookingStationHoverMode.Percent:
			{
				if (cookedTime > cookTime)
				{
					float num4 = Mathf.Clamp01((cookedTime - cookTime) / cookTime);
					string text10 = $"{num4:0%}";
					return text + ": " + PaintTextIfEnabled(text10, GetPercentColorInverted(num4));
				}
				float num5 = Mathf.Clamp01(cookedTime / cookTime);
				string text11 = $"{num5:0%}";
				return text + ": " + PaintTextIfEnabled(text11, GetPercentColor(num5));
			}
			case ConfigManager.CookingStationHoverMode.RemainingTime:
			{
				if (cookedTime > cookTime)
				{
					float seconds3 = Mathf.Max(0f, num - cookedTime);
					string text8 = FormatTime(seconds3);
					return text + ": " + PaintTextIfEnabled(text8, Color.red);
				}
				float seconds4 = Mathf.Max(0f, cookTime - cookedTime);
				string text9 = FormatTime(seconds4);
				return text + ": " + PaintTextIfEnabled(text9, Color.cyan);
			}
			case ConfigManager.CookingStationHoverMode.PercentAndTime:
			{
				if (cookedTime > cookTime)
				{
					float num2 = Mathf.Clamp01((cookedTime - cookTime) / cookTime);
					string text2 = $"{num2:0%}";
					string text3 = PaintTextIfEnabled(text2, GetPercentColorInverted(num2));
					float seconds = Mathf.Max(0f, num - cookedTime);
					string text4 = PaintTextIfEnabled(FormatTime(seconds), Color.red);
					return text + ": " + text3 + " - " + text4;
				}
				float num3 = Mathf.Clamp01(cookedTime / cookTime);
				string text5 = $"{num3:0%}";
				string text6 = PaintTextIfEnabled(text5, GetPercentColor(num3));
				float seconds2 = Mathf.Max(0f, cookTime - cookedTime);
				string text7 = PaintTextIfEnabled(FormatTime(seconds2), Color.cyan);
				return text + ": " + text6 + " - " + text7;
			}
			default:
				return null;
			}
		}

		private static string GetSmelterHover(Smelter smelter, string result)
		{
			//IL_017c: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			if (!smelter.IsActive())
			{
				return result;
			}
			float num = (float)GetFuelMethod.Invoke(smelter, null);
			int num2 = (int)GetQueueSizeMethod.Invoke(smelter, null);
			float num3 = (float)GetBakeTimerMethod.Invoke(smelter, null);
			if (num2 <= 0)
			{
				return result;
			}
			float secPerProduct = smelter.m_secPerProduct;
			int fuelPerProduct = smelter.m_fuelPerProduct;
			int num6;
			if (fuelPerProduct > 0)
			{
				int num4 = Mathf.FloorToInt(num / (float)fuelPerProduct);
				int num5 = Mathf.Max(0, num2 - 1);
				num6 = Mathf.Clamp(num4, 0, num5);
			}
			else
			{
				num6 = Mathf.Max(0, num2 - 1);
			}
			float num7 = Mathf.Clamp(secPerProduct - num3, 0f, secPerProduct);
			float num8 = num7 + (float)num6 * secPerProduct;
			float num9 = 1f;
			if ((Object)(object)smelter.m_windmill != (Object)null)
			{
				num9 = Mathf.Max(smelter.m_windmill.GetPowerOutput(), 0.0001f);
				num8 /= num9;
			}
			string text = "";
			if (ConfigManager.SmelterHoverModeChoice.Value == ConfigManager.SmelterHoverMode.RemainingTime)
			{
				if ((Object)(object)smelter.m_windmill != (Object)null)
				{
					int num10 = Mathf.RoundToInt(num9 * 100f);
					text = text + "\nWind: " + PaintTextIfEnabled($"{num10}%", GetPercentColor(num9));
				}
				text = text + "\n" + PaintTextIfEnabled(FormatTime(num8), Color.cyan);
			}
			return Localization.instance.Localize(result + " " + text);
		}

		private static string FormatTime(float seconds)
		{
			int num = Mathf.FloorToInt(seconds);
			int num2 = num / 3600;
			int num3 = num % 3600 / 60;
			int num4 = num % 60;
			if (num2 > 0)
			{
				return $"{num2}h {num3}m {num4}s";
			}
			if (num3 > 0)
			{
				return $"{num3}m {num4}s";
			}
			return $"{num4}s";
		}

		private static Color GetPercentColor(float percent)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: 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_0020: 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_0040: Unknown result type (might be due to invalid IL or missing references)
			return (percent < 0.5f) ? Color.Lerp(Color.red, Color.yellow, percent / 0.5f) : Color.Lerp(Color.yellow, Color.green, (percent - 0.5f) / 0.5f);
		}

		private static Color GetPercentColorInverted(float percent)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: 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_0020: 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_0040: Unknown result type (might be due to invalid IL or missing references)
			return (percent < 0.5f) ? Color.Lerp(Color.green, Color.yellow, percent / 0.5f) : Color.Lerp(Color.yellow, Color.red, (percent - 0.5f) / 0.5f);
		}

		private static string PaintText(string text, Color col)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			string text2 = ColorUtility.ToHtmlStringRGBA(col);
			return "<color=#" + text2 + ">" + text + "</color>";
		}

		private static string PaintTextIfEnabled(string text, Color col, bool bold = false)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			if (ConfigManager.DetailedHoverInfoChoice.Value != 0)
			{
				return bold ? ("<b>" + text + "</b>") : text;
			}
			string text2 = PaintText(text, col);
			return bold ? ("<b>" + text2 + "</b>") : text2;
		}

		private static void LogHoverText(string composed)
		{
			if (_lastHoverText != composed)
			{
				_lastHoverText = composed;
				log.Info("UIDetailedHovers hover updated: " + composed, header: true);
			}
		}
	}
	internal class UIEnemyDetector : UIController
	{
		[HarmonyPatch(typeof(Player), "Update")]
		private class EnemyDetector_PlayerPatch
		{
			private static void Prefix(ref Player ___m_localPlayer)
			{
				//IL_005a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0087: Unknown result type (might be due