Decompiled source of TalentTreeTweaks v1.1.1

plugins/TalentTreeTweaks.dll

Decompiled 2 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using SeneaL.API;
using TMPro;
using TalentTreeTweaks.Features;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("0.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace TalentTreeTweaks
{
	[BepInPlugin("DarthVladi.TalentTreeTweaks", "TalentTree Tweaks", "1.1.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInProcess("valheim.exe")]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "DarthVladi.TalentTreeTweaks";

		public const string PluginName = "TalentTree Tweaks";

		public const string PluginVersion = "1.1.1";

		internal static ManualLogSource Log;

		private void Awake()
		{
			Log = ((BaseUnityPlugin)this).Logger;
			try
			{
				QolConfig.Init(((BaseUnityPlugin)this).Config);
				TalentTreeHotkey.Init();
				TalentTreeSelectButton.Init();
				TalentTreeReleaseNode.Init();
				TalentTreeTooltipStyle.Init();
				TalentTreeRoundNodes.Init();
				TalentTreeSelectionStyle.Init();
				TalentTreeIcons.Init();
				TalentTreePaths.Init();
				TalentTreeNodeHints.Init();
				TalentTreeSearchHighlight.Init();
				TalentTreeTab.Init();
				Log.LogInfo((object)"TalentTree Tweaks 1.1.1 loaded.");
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Startup failed, features may be unavailable: " + ex.Message));
			}
		}

		private void Start()
		{
			try
			{
				TalentTreeHotkey.Resolve();
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("TalentTree hotkey could not be set up: " + ex.Message));
			}
			try
			{
				TalentTreeSelectButton.Resolve();
			}
			catch (Exception ex2)
			{
				Log.LogWarning((object)("TalentTree tooltip tweak could not be set up: " + ex2.Message));
			}
			try
			{
				TalentTreeReleaseNode.Resolve();
			}
			catch (Exception ex3)
			{
				Log.LogWarning((object)("TalentTree node release could not be set up: " + ex3.Message));
			}
			try
			{
				TalentTreeTooltipStyle.Resolve();
			}
			catch (Exception ex4)
			{
				Log.LogWarning((object)("TalentTree tooltip style could not be set up: " + ex4.Message));
			}
			try
			{
				TalentTreeRoundNodes.Resolve();
			}
			catch (Exception ex5)
			{
				Log.LogWarning((object)("TalentTree round nodes could not be set up: " + ex5.Message));
			}
			try
			{
				TalentTreeNodeHints.Resolve();
			}
			catch (Exception ex6)
			{
				Log.LogWarning((object)("TalentTree node hints could not be set up: " + ex6.Message));
			}
			try
			{
				TalentTreePaths.Resolve();
			}
			catch (Exception ex7)
			{
				Log.LogWarning((object)("TalentTree paths could not be set up: " + ex7.Message));
			}
			try
			{
				TalentTreeIcons.Resolve();
			}
			catch (Exception ex8)
			{
				Log.LogWarning((object)("TalentTree icons could not be set up: " + ex8.Message));
			}
			try
			{
				TalentTreeSelectionStyle.Resolve();
			}
			catch (Exception ex9)
			{
				Log.LogWarning((object)("TalentTree selection style could not be set up: " + ex9.Message));
			}
			try
			{
				TalentTreeSearchHighlight.Resolve();
			}
			catch (Exception ex10)
			{
				Log.LogWarning((object)("TalentTree search highlight could not be set up: " + ex10.Message));
			}
			try
			{
				TalentTreeTab.Resolve();
			}
			catch (Exception ex11)
			{
				Log.LogWarning((object)("TalentTree tab could not be set up: " + ex11.Message));
			}
		}

		private void Update()
		{
			TalentTreeHotkey.Tick();
			TalentTreeSearchHighlight.Tick();
		}

		private void OnDestroy()
		{
			try
			{
				TalentTreeHotkey.Shutdown();
			}
			catch
			{
			}
			try
			{
				TalentTreeSelectButton.Shutdown();
			}
			catch
			{
			}
			try
			{
				TalentTreeReleaseNode.Shutdown();
			}
			catch
			{
			}
			try
			{
				TalentTreeTooltipStyle.Shutdown();
			}
			catch
			{
			}
			try
			{
				TalentTreeRoundNodes.Shutdown();
			}
			catch
			{
			}
			try
			{
				TalentTreeNodeHints.Shutdown();
			}
			catch
			{
			}
			try
			{
				TalentTreePaths.Shutdown();
			}
			catch
			{
			}
			try
			{
				TalentTreeIcons.Shutdown();
			}
			catch
			{
			}
			try
			{
				TalentTreeSelectionStyle.Shutdown();
			}
			catch
			{
			}
			try
			{
				TalentTreeSearchHighlight.Shutdown();
			}
			catch
			{
			}
			try
			{
				TalentTreeTab.Shutdown();
			}
			catch
			{
			}
		}
	}
	internal static class QolConfig
	{
		private const string TalentTreeHotkeySection = "TalentTree Hotkey";

		private const string TalentTreeTooltipSection = "TalentTree Tooltip";

		private const string TalentTreeTabSection = "TalentTree Tab";

		private const string TalentTreeSearchSection = "TalentTree Search";

		private const string TalentTreeNodesSection = "TalentTree Nodes";

		private const string TalentTreeIconsSection = "TalentTree Icons";

		internal static ConfigEntry<bool> TalentTreeHotkeyEnabled;

		internal static ConfigEntry<KeyboardShortcut> TalentTreeHotkey;

		internal static ConfigEntry<bool> RoundMinorNodes;

		internal static ConfigEntry<bool> ReplaceTalentIcons;

		internal static ConfigEntry<string> TalentIconsFolder;

		internal static ConfigEntry<bool> SoftSelection;

		internal static ConfigEntry<float> SelectionLighten;

		internal static ConfigEntry<bool> SearchHighlightEnabled;

		internal static ConfigEntry<float> SearchDimAlpha;

		internal static ConfigEntry<bool> SearchHideDropdown;

		internal static ConfigEntry<bool> SearchGlow;

		internal static ConfigEntry<Color> SearchHighlightColor;

		internal static ConfigEntry<bool> TalentTreeTabEnabled;

		internal static ConfigEntry<string> TalentTreeTabIcon;

		internal static ConfigEntry<bool> HideSelectButtonEnabled;

		internal static ConfigEntry<bool> HideSelectButtonWhenUnavailable;

		internal static ConfigEntry<bool> ReleaseNodeAfterSelect;

		internal static ConfigEntry<bool> QuietPathHints;

		internal static ConfigEntry<bool> QuietAvailableNodes;

		internal static ConfigEntry<bool> TitleColorByBranch;

		internal static ConfigEntry<bool> SubtitleColorByBranch;

		internal static ConfigEntry<bool> CostTokenColorByBranch;

		internal static ConfigEntry<float> CostTokenOutline;

		internal static ConfigEntry<string> TooltipFont;

		internal static ConfigEntry<float> CostTokenSize;

		internal static ConfigEntry<int> CostTokenFontSize;

		internal static void Init(ConfigFile config)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Expected O, but got Unknown
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Expected O, but got Unknown
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_02aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b4: Expected O, but got Unknown
			//IL_02d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e2: Expected O, but got Unknown
			//IL_0310: Unknown result type (might be due to invalid IL or missing references)
			//IL_031a: Expected O, but got Unknown
			TalentTreeHotkeyEnabled = config.Bind<bool>("TalentTree Hotkey", "Enabled", true, "Open and close the TalentTree window with a hotkey. Useful when your inventory UI hides the Talents button. Does nothing if TalentTree is not installed.");
			TalentTreeHotkey = config.Bind<KeyboardShortcut>("TalentTree Hotkey", "Hotkey", new KeyboardShortcut((KeyCode)112, Array.Empty<KeyCode>()), "Key that toggles the TalentTree window. Ignored while typing in chat, with the console open, or while any text field is active.");
			RoundMinorNodes = config.Bind<bool>("TalentTree Nodes", "RoundMinorNodes", true, "Draws the small nodes of the TalentTree window (Health, Stamina, Armor...) as circles, like the big ones, instead of octagons. Does nothing if TalentTree is not installed. Needs a game restart.");
			ReplaceTalentIcons = config.Bind<bool>("TalentTree Icons", "Enabled", true, "Replaces TalentTree's talent icons with the PNG files of the talent icons folder. The same icon is used in the tree, in the buff icons of the talents' effects and in the debuff icons TalentTree shows on enemies. A talent without a file keeps TalentTree's icon. Does nothing if TalentTree is not installed. Needs a game restart.");
			TalentIconsFolder = config.Bind<string>("TalentTree Icons", "Folder", "talent-icons", "Folder with the icon files, next to TalentTreeTweaks.dll. Each file is named like TalentTree's icon id, for example warrior.focus.png or mid.warrior.png (the six mid.* ones are the sector hubs). Square PNGs, 128x128 or larger. Needs a game restart.");
			SoftSelection = config.Bind<bool>("TalentTree Nodes", "SoftSelection", true, "The ring around the node you hover or select takes the node's own colour (its branch colour, or grey while it is locked), lightened, instead of Valheim yellow. Does nothing if TalentTree is not installed. Needs a game restart.");
			SelectionLighten = config.Bind<float>("TalentTree Nodes", "SelectionLighten", 0.6f, new ConfigDescription("How far that ring is lightened toward white: 0 = the node's own colour, 1 = white. Takes effect at once.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			SearchHighlightEnabled = config.Bind<bool>("TalentTree Search", "Enabled", true, "The search box of the TalentTree window also looks at what a node gives (its description and stat rows, like \"health\" or \"stamina\"), keeps the nodes that match at full brightness and dims all the others. Clearing the box brings everything back. Does nothing if TalentTree is not installed. Needs a game restart.");
			SearchDimAlpha = config.Bind<float>("TalentTree Search", "DimAlpha", 0.12f, new ConfigDescription("How visible the nodes that don't match are while you search: 0 hides them, 1 leaves them as they are.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			SearchGlow = config.Bind<bool>("TalentTree Search", "Glow", true, "Puts a softly pulsing ring of light around the nodes that match the search, so they stand out from the dimmed ones.");
			SearchHighlightColor = config.Bind<Color>("TalentTree Search", "GlowColor", new Color(1f, 0.84f, 0.28f, 1f), "Colour of that ring, as RRGGBBAA hex. FFD647FF is gold (the default), FFFFFFFF is white.");
			SearchHideDropdown = config.Bind<bool>("TalentTree Search", "HideDropdown", true, "Hides the list of suggestions under the search box (it only lists node names). Without it you can't jump to a node by name; the matches are highlighted instead.");
			TalentTreeTabEnabled = config.Bind<bool>("TalentTree Tab", "Enabled", true, "Adds a Talents tab to the character screen when SeneaL UI (through SeneaL API) draws its row of tabs. Clicking it opens and closes the TalentTree window. Does nothing without SeneaL API or TalentTree. Needs a game restart.");
			TalentTreeTabIcon = config.Bind<string>("TalentTree Tab", "Icon", "tree-structure", "Icon of the tab: the name of any Phosphor icon (phosphoricons.com), for example tree-structure, star, sparkle, graph. Needs a game restart.");
			HideSelectButtonEnabled = config.Bind<bool>("TalentTree Tooltip", "HideSelectButtonWhenMaxed", true, "Hides the Select button in TalentTree's node tooltip once the node has no rank left to take, and trims the tooltip to fit. A node you can't take only for lack of points or an unmet requirement keeps its button. Does nothing if TalentTree is not installed.");
			HideSelectButtonWhenUnavailable = config.Bind<bool>("TalentTree Tooltip", "HideSelectButtonWhenUnavailable", true, "Hides the Select button on every node you can't take right now (no points left, a requirement not met, or no rank left), so only nodes you can level up show it. With this off, HideSelectButtonWhenMaxed decides. Does nothing if TalentTree is not installed.");
			ReleaseNodeAfterSelect = config.Bind<bool>("TalentTree Tooltip", "ReleaseNodeAfterSelect", true, "A click on a node pins its tooltip, and while it is pinned the other nodes show nothing when you hover them until you click an empty spot. With this on, pressing Select (or Select all) in the tooltip takes the point and lets go of the node at once, so hovering other nodes works again. Before you take the point nothing changes. Does nothing if TalentTree is not installed. Applies at once.");
			QuietPathHints = config.Bind<bool>("TalentTree Nodes", "QuietPathHints", true, "TalentTree paints in bright white the path from a node you have to a node you could take next, which makes the tree noisy. With this on they look like any other path that is not lit. Paths between nodes you have keep their orange. Does nothing if TalentTree is not installed. Needs a game restart.");
			QuietAvailableNodes = config.Bind<bool>("TalentTree Nodes", "QuietAvailableNodes", true, "TalentTree paints in bright white the small nodes you could take next. With this on they look like any other small node you can't take yet. Nodes you have keep their look. Does nothing if TalentTree is not installed. Needs a game restart.");
			TitleColorByBranch = config.Bind<bool>("TalentTree Tooltip", "TitleColorByBranch", true, "The node's name in TalentTree's tooltip takes the colour of its branch (the same colour as the node's ring) instead of orange. Does nothing if TalentTree is not installed.");
			CostTokenSize = config.Bind<float>("TalentTree Tooltip", "CostTokenSize", 24f, new ConfigDescription("Diameter of the round token with the point cost in TalentTree's tooltip. TalentTree's own value is 18. Needs a game restart.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 60f), Array.Empty<object>()));
			CostTokenFontSize = config.Bind<int>("TalentTree Tooltip", "CostTokenFontSize", 15, new ConfigDescription("Size of the number inside that token. TalentTree's own value is 11. Keep it below about 60 % of CostTokenSize so the number fits. Needs a game restart.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(6, 40), Array.Empty<object>()));
			CostTokenOutline = config.Bind<float>("TalentTree Tooltip", "CostTokenOutline", 2f, new ConfigDescription("Thickness of the black outline around the number in the point-cost token, in pixels. TalentTree's own is about 1. 0 leaves TalentTree's outline as it is.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 6f), Array.Empty<object>()));
			SubtitleColorByBranch = config.Bind<bool>("TalentTree Tooltip", "SubtitleColorByBranch", true, "The sub-titles of the stat rows in TalentTree's tooltip (like \"Bonus Health Points\") take the colour of the node's branch instead of orange. Does nothing if TalentTree is not installed.");
			CostTokenColorByBranch = config.Bind<bool>("TalentTree Tooltip", "CostTokenColorByBranch", true, "The round point-cost token takes the colour of the node's branch instead of orange. Does nothing if TalentTree is not installed.");
			TooltipFont = config.Bind<string>("TalentTree Tooltip", "Font", "RussoOne-Regular.ttf", "Font file for the text of TalentTree's tooltip: a .ttf or .otf next to TalentTreeTweaks.dll or in its \"fonts\" folder. Empty keeps TalentTree's own font. Needs a game restart.");
		}
	}
}
namespace TalentTreeTweaks.Features
{
	internal static class TalentTreeHotkey
	{
		internal const string TalentTreeGuid = "M2Valheim.TalentTree";

		private const string WindowTypeName = "UI.TalentWindow";

		private static Action _toggle;

		private static Func<bool> _isOpen;

		private static bool _configEnabled;

		private static KeyboardShortcut _shortcut;

		private static bool _active;

		private static bool _toggleFailureLogged;

		internal static bool IsWindowOpen
		{
			get
			{
				try
				{
					return _isOpen != null && _isOpen();
				}
				catch
				{
					return false;
				}
			}
		}

		internal static bool Available => _toggle != null;

		internal static string HotkeyText
		{
			get
			{
				if (!_configEnabled)
				{
					return "";
				}
				return ((object)Unsafe.As<KeyboardShortcut, KeyboardShortcut>(ref _shortcut)/*cast due to .constrained prefix*/).ToString();
			}
		}

		internal static void Init()
		{
			QolConfig.TalentTreeHotkeyEnabled.SettingChanged += OnConfigChanged;
			QolConfig.TalentTreeHotkey.SettingChanged += OnConfigChanged;
			RefreshConfig();
		}

		internal static void Shutdown()
		{
			if (QolConfig.TalentTreeHotkeyEnabled != null)
			{
				QolConfig.TalentTreeHotkeyEnabled.SettingChanged -= OnConfigChanged;
			}
			if (QolConfig.TalentTreeHotkey != null)
			{
				QolConfig.TalentTreeHotkey.SettingChanged -= OnConfigChanged;
			}
		}

		internal static void Resolve()
		{
			_toggle = null;
			_isOpen = null;
			if (!Chainloader.PluginInfos.TryGetValue("M2Valheim.TalentTree", out var value) || value == null || (Object)(object)value.Instance == (Object)null)
			{
				Plugin.Log.LogInfo((object)"TalentTree is not installed; the TalentTree hotkey stays inactive.");
				RefreshActive();
				return;
			}
			try
			{
				Type type = ((object)value.Instance).GetType().Assembly.GetType("UI.TalentWindow", throwOnError: false);
				if (type == null)
				{
					Plugin.Log.LogWarning((object)"TalentTree found, but UI.TalentWindow does not exist (different TalentTree version?). Hotkey disabled.");
					RefreshActive();
					return;
				}
				MethodInfo method = type.GetMethod("Toggle", BindingFlags.Static | BindingFlags.Public, null, Type.EmptyTypes, null);
				MethodInfo methodInfo = type.GetProperty("IsOpen", BindingFlags.Static | BindingFlags.Public)?.GetGetMethod();
				if (method == null || methodInfo == null || methodInfo.ReturnType != typeof(bool))
				{
					Plugin.Log.LogWarning((object)"TalentTree found, but UI.TalentWindow.Toggle/IsOpen have an unexpected shape (different TalentTree version?). Hotkey disabled.");
					RefreshActive();
					return;
				}
				_toggle = (Action)Delegate.CreateDelegate(typeof(Action), method);
				_isOpen = (Func<bool>)Delegate.CreateDelegate(typeof(Func<bool>), methodInfo);
				Plugin.Log.LogInfo((object)"TalentTree found; the TalentTree hotkey is ready.");
			}
			catch (Exception ex)
			{
				_toggle = null;
				_isOpen = null;
				Plugin.Log.LogWarning((object)("Could not hook TalentTree, hotkey disabled: " + ex.Message));
			}
			RefreshActive();
		}

		internal static bool TryToggle()
		{
			if (_toggle == null)
			{
				return false;
			}
			try
			{
				_toggle();
				return true;
			}
			catch (Exception ex)
			{
				if (!_toggleFailureLogged)
				{
					_toggleFailureLogged = true;
					Plugin.Log.LogWarning((object)("TalentTree Toggle failed: " + ex.Message));
				}
				return false;
			}
		}

		internal static void Tick()
		{
			if (!_active || !((KeyboardShortcut)(ref _shortcut)).IsDown() || !CanTrigger())
			{
				return;
			}
			try
			{
				_toggle();
			}
			catch (Exception ex)
			{
				if (!_toggleFailureLogged)
				{
					_toggleFailureLogged = true;
					Plugin.Log.LogWarning((object)("TalentTree Toggle failed: " + ex.Message));
				}
			}
		}

		private static bool CanTrigger()
		{
			if ((Object)(object)Player.m_localPlayer == (Object)null)
			{
				return false;
			}
			if ((Object)(object)Chat.instance != (Object)null && Chat.instance.HasFocus())
			{
				return false;
			}
			if (Console.IsVisible())
			{
				return false;
			}
			if (TextInput.IsVisible())
			{
				return false;
			}
			return !IsTypingInInputField();
		}

		private static bool IsTypingInInputField()
		{
			EventSystem current = EventSystem.current;
			GameObject val = (((Object)(object)current != (Object)null) ? current.currentSelectedGameObject : null);
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			TMP_InputField component = val.GetComponent<TMP_InputField>();
			if ((Object)(object)component != (Object)null && component.isFocused)
			{
				return true;
			}
			InputField component2 = val.GetComponent<InputField>();
			if ((Object)(object)component2 != (Object)null)
			{
				return component2.isFocused;
			}
			return false;
		}

		private static void OnConfigChanged(object sender, EventArgs e)
		{
			RefreshConfig();
		}

		private static void RefreshConfig()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			_configEnabled = QolConfig.TalentTreeHotkeyEnabled.Value;
			_shortcut = QolConfig.TalentTreeHotkey.Value;
			RefreshActive();
		}

		private static void RefreshActive()
		{
			_active = _configEnabled && _toggle != null;
		}
	}
	internal static class TalentTreeIcons
	{
		private const string RegistryTypeName = "Integration.IconRegistry";

		private static Harmony _harmony;

		private static Dictionary<string, Sprite> _sprites;

		private static bool _failureLogged;

		private static readonly MethodInfo LoadImageMethod = typeof(ImageConversion).GetMethod("LoadImage", BindingFlags.Static | BindingFlags.Public, null, new Type[3]
		{
			typeof(Texture2D),
			typeof(byte[]),
			typeof(bool)
		}, null);

		private const string LethalPatienceId = "valkyrie.lethal_patience";

		private const string VanillaSneakId = "vanilla:skill_sneak";

		private static MethodInfo _registryGet;

		internal static void Init()
		{
		}

		internal static void Shutdown()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			_harmony = null;
		}

		internal static void Resolve()
		{
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Expected O, but got Unknown
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Expected O, but got Unknown
			if (!QolConfig.ReplaceTalentIcons.Value)
			{
				return;
			}
			if (!Chainloader.PluginInfos.TryGetValue("M2Valheim.TalentTree", out var value) || value == null || (Object)(object)value.Instance == (Object)null)
			{
				Plugin.Log.LogInfo((object)"TalentTree is not installed; its talent icons are left alone.");
				return;
			}
			try
			{
				Type type = ((object)value.Instance).GetType().Assembly.GetType("Integration.IconRegistry", throwOnError: false);
				if (type == null)
				{
					Unexpected("Integration.IconRegistry does not exist");
					return;
				}
				MethodInfo methodInfo = AccessTools.Method(type, "Get", (Type[])null, (Type[])null);
				if (methodInfo == null || !methodInfo.IsStatic || methodInfo.ReturnType != typeof(Sprite) || methodInfo.GetParameters().Length != 1 || methodInfo.GetParameters()[0].ParameterType != typeof(string))
				{
					Unexpected("IconRegistry.Get is not as expected");
					return;
				}
				if (LoadImageMethod == null)
				{
					Unexpected("this game's Unity can't load PNG files");
					return;
				}
				_harmony = new Harmony("DarthVladi.TalentTreeTweaks.TalentIcons");
				_harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(TalentTreeIcons), "GetPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				FixLethalPatience(((object)value.Instance).GetType().Assembly, methodInfo);
			}
			catch (Exception ex)
			{
				Harmony harmony = _harmony;
				if (harmony != null)
				{
					harmony.UnpatchSelf();
				}
				_harmony = null;
				Unexpected(ex.Message);
			}
		}

		private static void FixLethalPatience(Assembly talentTree, MethodInfo registryGet)
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Expected O, but got Unknown
			_registryGet = registryGet;
			try
			{
				Type type = talentTree.GetType("Talents.Valkyrie.SE_ValkyrieLethalPatience", throwOnError: false);
				MethodInfo methodInfo = ((type == null) ? null : AccessTools.Method(type, "Setup", (Type[])null, (Type[])null));
				if (methodInfo != null)
				{
					_harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(TalentTreeIcons), "LethalPatienceSetupPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				Type type2 = talentTree.GetType("Integration.HealthBarStatusEffects", throwOnError: false);
				PropertyInfo propertyInfo = ((type2 == null) ? null : AccessTools.Property(type2, "Entries"));
				IList list = ((propertyInfo == null) ? null : (propertyInfo.GetValue(null, null) as IList));
				if (list == null || (Object)(object)GetLethalPatienceIcon() == (Object)null)
				{
					return;
				}
				for (int i = 0; i < list.Count; i++)
				{
					object obj = list[i];
					FieldInfo fieldInfo = obj?.GetType().GetField("IconId");
					if (!(fieldInfo == null) && !(fieldInfo.FieldType != typeof(string)) && !((string)fieldInfo.GetValue(obj) != "vanilla:skill_sneak"))
					{
						fieldInfo.SetValue(obj, "valkyrie.lethal_patience");
						list[i] = obj;
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogInfo((object)("Lethal Patience's icon is left as it is (" + ex.Message + ")."));
			}
		}

		private static Sprite GetLethalPatienceIcon()
		{
			if (!(_registryGet == null))
			{
				object? obj = _registryGet.Invoke(null, new object[1] { "valkyrie.lethal_patience" });
				return (Sprite)((obj is Sprite) ? obj : null);
			}
			return null;
		}

		private static void LethalPatienceSetupPostfix(StatusEffect __instance)
		{
			try
			{
				Sprite lethalPatienceIcon = GetLethalPatienceIcon();
				if ((Object)(object)lethalPatienceIcon != (Object)null && (Object)(object)__instance != (Object)null)
				{
					__instance.m_icon = lethalPatienceIcon;
				}
			}
			catch (Exception)
			{
			}
		}

		private static bool GetPrefix(object[] __args, ref Sprite __result)
		{
			try
			{
				if (_sprites == null)
				{
					Load();
				}
				if (_sprites.Count == 0 || __args == null || __args.Length < 1)
				{
					return true;
				}
				string text = __args[0] as string;
				if (string.IsNullOrEmpty(text))
				{
					return true;
				}
				if (!_sprites.TryGetValue(text, out var value))
				{
					int num = text.IndexOf('.');
					int num2 = ((num < 0) ? (-1) : text.IndexOf('.', num + 1));
					if (num2 < 0 || !_sprites.TryGetValue(text.Substring(0, num2), out value))
					{
						return true;
					}
				}
				if ((Object)(object)value == (Object)null)
				{
					return true;
				}
				__result = value;
				return false;
			}
			catch (Exception ex)
			{
				if (_sprites == null)
				{
					_sprites = new Dictionary<string, Sprite>();
				}
				Unexpected("an icon could not be replaced: " + ex.Message);
				return true;
			}
		}

		private static void Load()
		{
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Expected O, but got Unknown
			//IL_0183: 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)
			_sprites = new Dictionary<string, Sprite>(StringComparer.OrdinalIgnoreCase);
			string text = Path.GetDirectoryName(typeof(Plugin).Assembly.Location) ?? "";
			string text2 = Path.Combine(text, QolConfig.TalentIconsFolder.Value.Trim());
			if (!Directory.Exists(text2))
			{
				if (!Directory.Exists(text) || Directory.GetFiles(text, "*.*.png").Length == 0)
				{
					Plugin.Log.LogInfo((object)("Talent icon folder \"" + text2 + "\" not found; TalentTree's icons are kept."));
					return;
				}
				Plugin.Log.LogInfo((object)("Talent icon folder \"" + text2 + "\" not found; using the icons next to TalentTreeTweaks.dll."));
				text2 = text;
			}
			string[] files = Directory.GetFiles(text2, "*.png");
			foreach (string path in files)
			{
				string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(path);
				if (text2 == text && fileNameWithoutExtension.IndexOf('.') < 0)
				{
					continue;
				}
				try
				{
					Texture2D val = new Texture2D(2, 2, (TextureFormat)4, true);
					if (!(bool)LoadImageMethod.Invoke(null, new object[3]
					{
						val,
						File.ReadAllBytes(path),
						true
					}))
					{
						Object.Destroy((Object)(object)val);
						Plugin.Log.LogWarning((object)("Talent icon \"" + fileNameWithoutExtension + ".png\" could not be read; TalentTree's icon is kept."));
						continue;
					}
					((Object)val).name = "TalentTreeTweaks " + fileNameWithoutExtension;
					((Texture)val).filterMode = (FilterMode)2;
					((Texture)val).wrapMode = (TextureWrapMode)1;
					((Object)val).hideFlags = (HideFlags)32;
					Sprite val2 = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f, 0u, (SpriteMeshType)0);
					((Object)val2).name = ((Object)val).name;
					((Object)val2).hideFlags = (HideFlags)32;
					_sprites[fileNameWithoutExtension] = val2;
				}
				catch (Exception ex)
				{
					Plugin.Log.LogWarning((object)("Talent icon \"" + fileNameWithoutExtension + ".png\" could not be loaded (" + ex.Message + "); TalentTree's icon is kept."));
				}
			}
			Plugin.Log.LogInfo((object)$"{_sprites.Count} talent icons loaded from \"{text2}\".");
		}

		private static void Unexpected(string why)
		{
			if (!_failureLogged)
			{
				_failureLogged = true;
				Plugin.Log.LogWarning((object)("TalentTree's talent icons are left as they are (" + why + "); a different TalentTree version may have changed it."));
			}
		}
	}
	internal static class TalentTreeNodeHints
	{
		private static Harmony _harmony;

		private static FieldInfo _nodes;

		private static FieldInfo _isMinor;

		private static FieldInfo _background;

		private static FieldInfo _available;

		private static FieldInfo _locked;

		private static PropertyInfo _themeDefault;

		private static bool _failureLogged;

		private static bool _failed;

		internal static void Init()
		{
		}

		internal static void Shutdown()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			_harmony = null;
		}

		internal static void Resolve()
		{
			//IL_021f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0229: Expected O, but got Unknown
			//IL_0240: Unknown result type (might be due to invalid IL or missing references)
			//IL_024d: Expected O, but got Unknown
			if (!QolConfig.QuietAvailableNodes.Value)
			{
				return;
			}
			if (!Chainloader.PluginInfos.TryGetValue("M2Valheim.TalentTree", out var value) || value == null || (Object)(object)value.Instance == (Object)null)
			{
				Plugin.Log.LogInfo((object)"TalentTree is not installed; the small nodes of its tree are left alone.");
				return;
			}
			try
			{
				Assembly assembly = ((object)value.Instance).GetType().Assembly;
				Type type = assembly.GetType("UI.TalentTreeView", throwOnError: false);
				Type type2 = assembly.GetType("UI.TalentUiTheme", throwOnError: false);
				if (type == null || type2 == null)
				{
					Unexpected("UI.TalentTreeView / UI.TalentUiTheme do not exist");
					return;
				}
				MethodInfo methodInfo = AccessTools.Method(type, "UpdateVisuals", (Type[])null, (Type[])null);
				_nodes = AccessTools.Field(type, "_nodes");
				_themeDefault = AccessTools.Property(type2, "Default");
				_available = AccessTools.Field(type2, "MinorAvailableBackground");
				_locked = AccessTools.Field(type2, "MinorLockedBackground");
				if (methodInfo == null || _nodes == null || !typeof(IDictionary).IsAssignableFrom(_nodes.FieldType) || !_nodes.FieldType.IsGenericType || _themeDefault == null || _available == null || _available.FieldType != typeof(Color) || _locked == null || _locked.FieldType != typeof(Color))
				{
					Unexpected("the tree view or the theme are not as expected");
					return;
				}
				Type obj = _nodes.FieldType.GetGenericArguments()[1];
				_isMinor = AccessTools.Field(obj, "IsMinor");
				_background = AccessTools.Field(obj, "Background");
				if (_isMinor == null || _isMinor.FieldType != typeof(bool) || _background == null || !typeof(Graphic).IsAssignableFrom(_background.FieldType))
				{
					Unexpected("a node is not as expected");
					return;
				}
				_harmony = new Harmony("DarthVladi.TalentTreeTweaks.NodeHints");
				_harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(TalentTreeNodeHints), "UpdatePostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				Plugin.Log.LogInfo((object)"The small nodes you could take next will be drawn like the other locked ones.");
			}
			catch (Exception ex)
			{
				Harmony harmony = _harmony;
				if (harmony != null)
				{
					harmony.UnpatchSelf();
				}
				_harmony = null;
				Unexpected(ex.Message);
			}
		}

		private static void UpdatePostfix(object __instance)
		{
			//IL_002c: 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_003d: 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)
			//IL_0043: 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_00b8: 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_00c7: Unknown result type (might be due to invalid IL or missing references)
			if (_failed || __instance == null)
			{
				return;
			}
			try
			{
				object value = _themeDefault.GetValue(null, null);
				if (value == null)
				{
					return;
				}
				Color val = (Color)_available.GetValue(value);
				Color val2 = (Color)_locked.GetValue(value);
				if (val == val2 || !(_nodes.GetValue(__instance) is IDictionary dictionary))
				{
					return;
				}
				foreach (object value3 in dictionary.Values)
				{
					if (value3 != null && (bool)_isMinor.GetValue(value3))
					{
						object? value2 = _background.GetValue(value3);
						Graphic val3 = (Graphic)((value2 is Graphic) ? value2 : null);
						if ((Object)(object)val3 != (Object)null && val3.color == val)
						{
							val3.color = val2;
						}
					}
				}
			}
			catch (Exception ex)
			{
				_failed = true;
				Unexpected("a node could not be changed: " + ex.Message);
			}
		}

		private static void Unexpected(string why)
		{
			if (!_failureLogged)
			{
				_failureLogged = true;
				Plugin.Log.LogWarning((object)("The small nodes of TalentTree's tree stay as TalentTree draws them (" + why + "); a different TalentTree version may have changed it."));
			}
		}
	}
	internal static class TalentTreePaths
	{
		private const string PathViewTypeName = "UI.TalentTreePathView";

		private const string ThemeTypeName = "UI.TalentUiTheme";

		private static Harmony _harmony;

		private static FieldInfo _paths;

		private static FieldInfo _curve;

		private static FieldInfo _inner;

		private static FieldInfo _hint;

		private static FieldInfo _locked;

		private static PropertyInfo _themeDefault;

		private static MethodInfo _refresh;

		private static bool _failureLogged;

		private static bool _failed;

		internal static void Init()
		{
		}

		internal static void Shutdown()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			_harmony = null;
		}

		internal static void Resolve()
		{
			//IL_0248: Unknown result type (might be due to invalid IL or missing references)
			//IL_0252: Expected O, but got Unknown
			//IL_0269: Unknown result type (might be due to invalid IL or missing references)
			//IL_0276: Expected O, but got Unknown
			if (!QolConfig.QuietPathHints.Value)
			{
				return;
			}
			if (!Chainloader.PluginInfos.TryGetValue("M2Valheim.TalentTree", out var value) || value == null || (Object)(object)value.Instance == (Object)null)
			{
				Plugin.Log.LogInfo((object)"TalentTree is not installed; the paths of its tree are left alone.");
				return;
			}
			try
			{
				Assembly assembly = ((object)value.Instance).GetType().Assembly;
				Type type = assembly.GetType("UI.TalentTreePathView", throwOnError: false);
				Type type2 = assembly.GetType("UI.TalentUiTheme", throwOnError: false);
				if (type == null || type2 == null)
				{
					Unexpected("UI.TalentTreePathView / UI.TalentUiTheme do not exist");
					return;
				}
				MethodInfo methodInfo = AccessTools.Method(type, "UpdateVisuals", (Type[])null, (Type[])null);
				_paths = AccessTools.Field(type, "_paths");
				_themeDefault = AccessTools.Property(type2, "Default");
				_hint = AccessTools.Field(type2, "PathInnerHint");
				_locked = AccessTools.Field(type2, "PathInnerLocked");
				if (methodInfo == null || _paths == null || !typeof(IEnumerable).IsAssignableFrom(_paths.FieldType) || !_paths.FieldType.IsGenericType || _themeDefault == null || _hint == null || _hint.FieldType != typeof(Color) || _locked == null || _locked.FieldType != typeof(Color))
				{
					Unexpected("the path view or the theme are not as expected");
					return;
				}
				_curve = AccessTools.Field(_paths.FieldType.GetGenericArguments()[0], "Curve");
				if (_curve == null)
				{
					Unexpected("a path has no Curve");
					return;
				}
				_inner = AccessTools.Field(_curve.FieldType, "InnerColor");
				_refresh = AccessTools.Method(_curve.FieldType, "Refresh", Type.EmptyTypes, (Type[])null);
				if (_inner == null || _inner.FieldType != typeof(Color) || _refresh == null)
				{
					Unexpected("a path's curve is not as expected");
					return;
				}
				_harmony = new Harmony("DarthVladi.TalentTreeTweaks.Paths");
				_harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(TalentTreePaths), "UpdatePostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				Plugin.Log.LogInfo((object)"The white hint paths of TalentTree's tree will be drawn like the other locked paths.");
			}
			catch (Exception ex)
			{
				Harmony harmony = _harmony;
				if (harmony != null)
				{
					harmony.UnpatchSelf();
				}
				_harmony = null;
				Unexpected(ex.Message);
			}
		}

		private static void UpdatePostfix(object __instance)
		{
			//IL_002c: 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_003d: 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)
			//IL_0043: 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_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			if (_failed || __instance == null)
			{
				return;
			}
			try
			{
				object value = _themeDefault.GetValue(null, null);
				if (value == null)
				{
					return;
				}
				Color val = (Color)_hint.GetValue(value);
				Color val2 = (Color)_locked.GetValue(value);
				if (val == val2 || !(_paths.GetValue(__instance) is IEnumerable enumerable))
				{
					return;
				}
				foreach (object item in enumerable)
				{
					object obj = ((item != null) ? _curve.GetValue(item) : null);
					if (obj != null && !((Color)_inner.GetValue(obj) != val))
					{
						_inner.SetValue(obj, val2);
						_refresh.Invoke(obj, null);
					}
				}
			}
			catch (Exception ex)
			{
				_failed = true;
				Unexpected("a path could not be changed: " + ex.Message);
			}
		}

		private static void Unexpected(string why)
		{
			if (!_failureLogged)
			{
				_failureLogged = true;
				Plugin.Log.LogWarning((object)("The paths of TalentTree's tree stay as TalentTree draws them (" + why + "); a different TalentTree version may have changed it."));
			}
		}
	}
	internal static class TalentTreeReleaseNode
	{
		private const string ControllerTypeName = "UI.TalentWindowSelectionController";

		private static Harmony _harmony;

		private static PropertyInfo _pinned;

		private static MethodInfo _closeAndUnpin;

		private static bool _failureLogged;

		internal static void Init()
		{
		}

		internal static void Shutdown()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			_harmony = null;
		}

		internal static void Resolve()
		{
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Expected O, but got Unknown
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Expected O, but got Unknown
			if (!Chainloader.PluginInfos.TryGetValue("M2Valheim.TalentTree", out var value) || value == null || (Object)(object)value.Instance == (Object)null)
			{
				Plugin.Log.LogInfo((object)"TalentTree is not installed; its node selection is left alone.");
				return;
			}
			try
			{
				Type type = ((object)value.Instance).GetType().Assembly.GetType("UI.TalentWindowSelectionController", throwOnError: false);
				if (type == null)
				{
					Unexpected("UI.TalentWindowSelectionController does not exist");
					return;
				}
				MethodInfo methodInfo = AccessTools.Method(type, "StageById", new Type[1] { typeof(string) }, (Type[])null);
				MethodInfo methodInfo2 = AccessTools.Method(type, "StageAllById", new Type[1] { typeof(string) }, (Type[])null);
				_closeAndUnpin = AccessTools.Method(type, "CloseAndUnpin", Type.EmptyTypes, (Type[])null);
				_pinned = AccessTools.Property(type, "Pinned");
				if (methodInfo == null || methodInfo2 == null || _closeAndUnpin == null || _pinned == null || _pinned.PropertyType != typeof(bool))
				{
					Unexpected("the selection controller is not as expected");
					return;
				}
				_harmony = new Harmony("DarthVladi.TalentTreeTweaks.ReleaseNode");
				HarmonyMethod val = new HarmonyMethod(typeof(TalentTreeReleaseNode), "AfterStage", (Type[])null);
				_harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				_harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				Plugin.Log.LogInfo((object)"TalentTree found; a node is released as soon as you select it.");
			}
			catch (Exception ex)
			{
				Harmony harmony = _harmony;
				if (harmony != null)
				{
					harmony.UnpatchSelf();
				}
				_harmony = null;
				Unexpected(ex.Message);
			}
		}

		private static void AfterStage(object __instance)
		{
			try
			{
				if (QolConfig.ReleaseNodeAfterSelect.Value && __instance != null && (bool)_pinned.GetValue(__instance, null))
				{
					_closeAndUnpin.Invoke(__instance, null);
				}
			}
			catch (Exception ex)
			{
				Unexpected("a node could not be released: " + ex.Message);
			}
		}

		private static void Unexpected(string why)
		{
			if (!_failureLogged)
			{
				_failureLogged = true;
				Plugin.Log.LogWarning((object)("TalentTree's node selection is left as it is (" + why + "); a different TalentTree version may have changed it."));
			}
		}
	}
	internal static class TalentTreeRoundNodes
	{
		private const string ViewTypeName = "UI.TalentTreeView";

		private const string FactoryTypeName = "UI.UiFactory";

		private static Harmony _harmony;

		private static Func<Sprite> _circleMask;

		private static Func<Sprite> _circle;

		private static FieldInfo _fill;

		private static FieldInfo _inner;

		private static bool _failureLogged;

		private static bool _failed;

		internal static void Init()
		{
		}

		internal static void Shutdown()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			_harmony = null;
		}

		internal static void Resolve()
		{
			//IL_0208: Unknown result type (might be due to invalid IL or missing references)
			//IL_0212: Expected O, but got Unknown
			//IL_0229: Unknown result type (might be due to invalid IL or missing references)
			//IL_0236: Expected O, but got Unknown
			if (!QolConfig.RoundMinorNodes.Value)
			{
				return;
			}
			if (!Chainloader.PluginInfos.TryGetValue("M2Valheim.TalentTree", out var value) || value == null || (Object)(object)value.Instance == (Object)null)
			{
				Plugin.Log.LogInfo((object)"TalentTree is not installed; its small nodes are left alone.");
				return;
			}
			try
			{
				Assembly assembly = ((object)value.Instance).GetType().Assembly;
				Type type = assembly.GetType("UI.TalentTreeView", throwOnError: false);
				Type type2 = assembly.GetType("UI.UiFactory", throwOnError: false);
				if (type == null || type2 == null)
				{
					Unexpected("UI.TalentTreeView / UI.UiFactory do not exist");
					return;
				}
				MethodInfo methodInfo = AccessTools.Method(type, "BuildMinorVisuals", (Type[])null, (Type[])null);
				MethodInfo methodInfo2 = AccessTools.Method(type2, "GetCircleMaskSprite", (Type[])null, (Type[])null);
				MethodInfo methodInfo3 = AccessTools.Method(type2, "GetCircleSprite", (Type[])null, (Type[])null);
				if (methodInfo == null || methodInfo2 == null || methodInfo3 == null)
				{
					Unexpected("BuildMinorVisuals / the circle sprites were not found");
					return;
				}
				if (methodInfo2.ReturnType != typeof(Sprite) || methodInfo3.ReturnType != typeof(Sprite) || methodInfo2.GetParameters().Length != 0 || methodInfo3.GetParameters().Length != 0 || !methodInfo2.IsStatic || !methodInfo3.IsStatic)
				{
					Unexpected("the circle sprites are not as expected");
					return;
				}
				Type returnType = methodInfo.ReturnType;
				_fill = AccessTools.Field(returnType, "Border");
				_inner = AccessTools.Field(returnType, "Background");
				if (_fill == null || !typeof(Image).IsAssignableFrom(_fill.FieldType) || _inner == null || !typeof(Image).IsAssignableFrom(_inner.FieldType))
				{
					Unexpected("the node's fields are not as expected");
					return;
				}
				_circleMask = (Func<Sprite>)Delegate.CreateDelegate(typeof(Func<Sprite>), methodInfo2);
				_circle = (Func<Sprite>)Delegate.CreateDelegate(typeof(Func<Sprite>), methodInfo3);
				_harmony = new Harmony("DarthVladi.TalentTreeTweaks.RoundNodes");
				_harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(TalentTreeRoundNodes), "BuildPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				Plugin.Log.LogInfo((object)"TalentTree's small nodes will be drawn round.");
			}
			catch (Exception ex)
			{
				Harmony harmony = _harmony;
				if (harmony != null)
				{
					harmony.UnpatchSelf();
				}
				_harmony = null;
				Unexpected(ex.Message);
			}
		}

		private static void BuildPostfix(object __result)
		{
			if (_failed || __result == null)
			{
				return;
			}
			try
			{
				object? value = _fill.GetValue(__result);
				Image val = (Image)((value is Image) ? value : null);
				object? value2 = _inner.GetValue(__result);
				Image val2 = (Image)((value2 is Image) ? value2 : null);
				Transform val3 = (((Object)(object)val != (Object)null) ? ((Component)val).transform.parent : null);
				Image val4 = (((Object)(object)val3 != (Object)null) ? ((Component)val3).GetComponent<Image>() : null);
				if (!((Object)(object)val4 == (Object)null) && !((Object)(object)val2 == (Object)null))
				{
					Sprite val5 = _circleMask();
					Sprite val6 = _circle();
					if (!((Object)(object)val5 == (Object)null) && !((Object)(object)val6 == (Object)null))
					{
						val4.sprite = val5;
						val2.sprite = val6;
					}
				}
			}
			catch (Exception ex)
			{
				_failed = true;
				Unexpected("a node could not be changed: " + ex.Message);
			}
		}

		private static void Unexpected(string why)
		{
			if (!_failureLogged)
			{
				_failureLogged = true;
				Plugin.Log.LogWarning((object)("TalentTree's small nodes keep their octagon shape (" + why + "); a different TalentTree version may have changed it."));
			}
		}
	}
	internal static class TalentTreeSearchHighlight
	{
		private struct Entry
		{
			public string Id;

			public string Text;
		}

		private const string ControllerTypeName = "UI.TalentSearchController";

		private const string WindowTypeName = "UI.TalentWindow";

		private const string ViewTypeName = "UI.TalentTreeView";

		private const string RegistryTypeName = "Core.TalentRegistry";

		private const string DefinitionTypeName = "Core.TalentDefinition";

		private const string RowTypeName = "Core.StatProgressionRow";

		private const string LocalizationTypeName = "Integration.JotunnLocalization";

		private static Harmony _harmony;

		private static FieldInfo _treeField;

		private static MethodInfo _getNodeRects;

		private static MethodInfo _hideDropdown;

		private static PropertyInfo _all;

		private static PropertyInfo _id;

		private static PropertyInfo _nameKey;

		private static PropertyInfo _descKey;

		private static MethodInfo _statRows;

		private static FieldInfo _label;

		private static MethodInfo _translate;

		private static FieldInfo _pathsField;

		private static FieldInfo _pathsRoot;

		private const string GlowName = "TTT_SearchGlow";

		private const float GlowScale = 2.3f;

		private static readonly List<Image> _glows = new List<Image>();

		private static Sprite _glowSprite;

		private static List<Entry> _index;

		private static bool _failureLogged;

		private static bool _loggedFirstSearch;

		internal static void Init()
		{
		}

		internal static void Shutdown()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			_harmony = null;
			_index = null;
		}

		internal static void Resolve()
		{
			//IL_03d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e3: Expected O, but got Unknown
			//IL_03fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0408: Expected O, but got Unknown
			//IL_0421: Unknown result type (might be due to invalid IL or missing references)
			//IL_042e: Expected O, but got Unknown
			if (!QolConfig.SearchHighlightEnabled.Value || !Chainloader.PluginInfos.TryGetValue("M2Valheim.TalentTree", out var value) || value == null || (Object)(object)value.Instance == (Object)null)
			{
				return;
			}
			try
			{
				Assembly assembly = ((object)value.Instance).GetType().Assembly;
				Type type = assembly.GetType("UI.TalentSearchController", throwOnError: false);
				Type type2 = assembly.GetType("UI.TalentWindow", throwOnError: false);
				Type type3 = assembly.GetType("UI.TalentTreeView", throwOnError: false);
				Type type4 = assembly.GetType("Core.TalentRegistry", throwOnError: false);
				Type type5 = assembly.GetType("Core.TalentDefinition", throwOnError: false);
				Type type6 = assembly.GetType("Core.StatProgressionRow", throwOnError: false);
				Type type7 = assembly.GetType("Integration.JotunnLocalization", throwOnError: false);
				if (type == null || type2 == null || type3 == null || type4 == null || type5 == null || type6 == null || type7 == null)
				{
					Unexpected("a type was not found");
					return;
				}
				MethodInfo methodInfo = AccessTools.Method(type, "OnSearchChanged", new Type[1] { typeof(string) }, (Type[])null);
				MethodInfo methodInfo2 = AccessTools.Method(type, "Clear", Type.EmptyTypes, (Type[])null);
				_hideDropdown = AccessTools.Method(type, "HideDropdown", Type.EmptyTypes, (Type[])null);
				_treeField = AccessTools.Field(type2, "_tree");
				_getNodeRects = type3.GetMethod("GetNodeRects", BindingFlags.Instance | BindingFlags.Public, null, Type.EmptyTypes, null);
				_all = type4.GetProperty("All", BindingFlags.Static | BindingFlags.Public);
				_id = StringProperty(type5, "Id");
				_nameKey = StringProperty(type5, "NameKey");
				_descKey = StringProperty(type5, "DescKey");
				_statRows = type5.GetMethod("GetStatProgressionRows", BindingFlags.Instance | BindingFlags.Public, null, Type.EmptyTypes, null);
				_label = type6.GetField("Label", BindingFlags.Instance | BindingFlags.Public);
				_translate = FindTranslate(type7);
				Type type8 = assembly.GetType("UI.TalentTreePathView", throwOnError: false);
				_pathsField = AccessTools.Field(type2, "_paths");
				_pathsRoot = ((type8 != null) ? AccessTools.Field(type8, "_rootRect") : null);
				if (_pathsField == null || !_pathsField.IsStatic || _pathsField.FieldType != type8 || _pathsRoot == null || _pathsRoot.FieldType != typeof(RectTransform))
				{
					_pathsField = null;
					_pathsRoot = null;
				}
				if (methodInfo == null || methodInfo2 == null || _hideDropdown == null || _treeField == null || !_treeField.IsStatic || _treeField.FieldType != type3 || _getNodeRects == null || !typeof(IDictionary).IsAssignableFrom(_getNodeRects.ReturnType) || _all == null || !typeof(IEnumerable).IsAssignableFrom(_all.PropertyType) || _id == null || _nameKey == null || _descKey == null || _statRows == null || !typeof(IEnumerable).IsAssignableFrom(_statRows.ReturnType) || _label == null || _label.FieldType != typeof(string) || _translate == null)
				{
					Unexpected("the search or the node view are not where expected");
					return;
				}
				_harmony = new Harmony("DarthVladi.TalentTreeTweaks.SearchHighlight");
				_harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(TalentTreeSearchHighlight), "SearchChangedPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				_harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(typeof(TalentTreeSearchHighlight), "ClearPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				Plugin.Log.LogInfo((object)"TalentTree found; its search box can highlight the nodes that match a name, description or stat.");
			}
			catch (Exception ex)
			{
				Harmony harmony = _harmony;
				if (harmony != null)
				{
					harmony.UnpatchSelf();
				}
				_harmony = null;
				Plugin.Log.LogWarning((object)("Could not hook TalentTree's search, it keeps working as it is: " + ex.Message));
			}
		}

		private static PropertyInfo StringProperty(Type type, string name)
		{
			PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public);
			if (!(property != null) || !(property.PropertyType == typeof(string)) || !(property.GetGetMethod() != null))
			{
				return null;
			}
			return property;
		}

		private static MethodInfo FindTranslate(Type loc)
		{
			MethodInfo[] methods = loc.GetMethods(BindingFlags.Static | BindingFlags.Public);
			foreach (MethodInfo methodInfo in methods)
			{
				if (methodInfo.Name != "TranslateSmart" || methodInfo.ReturnType != typeof(string))
				{
					continue;
				}
				ParameterInfo[] parameters = methodInfo.GetParameters();
				if (parameters.Length == 0 || parameters[0].ParameterType != typeof(string))
				{
					continue;
				}
				bool flag = true;
				for (int j = 1; j < parameters.Length; j++)
				{
					if (!parameters[j].IsOptional)
					{
						flag = false;
					}
				}
				if (flag)
				{
					return methodInfo;
				}
			}
			return null;
		}

		private static void Unexpected(string what)
		{
			Plugin.Log.LogWarning((object)("TalentTree found, but its search is not as expected (" + what + "; different TalentTree version?). It keeps working as it is."));
		}

		internal static void SearchChangedPostfix(object __instance, string raw)
		{
			try
			{
				Apply(raw);
				if (QolConfig.SearchHideDropdown.Value)
				{
					_hideDropdown.Invoke(__instance, null);
				}
			}
			catch (Exception e)
			{
				LogOnce("highlighting the search result", e);
			}
		}

		internal static void ClearPostfix()
		{
			try
			{
				Apply("");
			}
			catch (Exception e)
			{
				LogOnce("clearing the search highlight", e);
			}
		}

		private static void Apply(string raw)
		{
			object value = _treeField.GetValue(null);
			if (value == null || !(_getNodeRects.Invoke(value, null) is IDictionary rects))
			{
				return;
			}
			string text = (raw ?? "").Trim().ToLowerInvariant();
			if (text.Length == 0)
			{
				SetAll(rects, null, 1f);
				SetPaths(1f);
				return;
			}
			string[] array = text.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
			if (_index == null)
			{
				_index = BuildIndex();
			}
			HashSet<string> hashSet = new HashSet<string>();
			for (int i = 0; i < _index.Count; i++)
			{
				string text2 = _index[i].Text;
				bool flag = true;
				for (int j = 0; j < array.Length && flag; j++)
				{
					flag = text2.IndexOf(array[j], StringComparison.Ordinal) >= 0;
				}
				if (flag)
				{
					hashSet.Add(_index[i].Id);
				}
			}
			float value2 = QolConfig.SearchDimAlpha.Value;
			SetAll(rects, hashSet, value2);
			SetPaths(Mathf.Clamp01(value2 + 0.2f));
			if (!_loggedFirstSearch)
			{
				_loggedFirstSearch = true;
				Plugin.Log.LogInfo((object)$"TalentTree search: \"{text}\" matches {hashSet.Count} of {_index.Count} nodes.");
			}
		}

		private static void SetAll(IDictionary rects, HashSet<string> hits, float dimAlpha)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			_glows.Clear();
			bool flag = hits != null && QolConfig.SearchGlow.Value;
			Color value = QolConfig.SearchHighlightColor.Value;
			foreach (DictionaryEntry rect in rects)
			{
				object? value2 = rect.Value;
				RectTransform val = (RectTransform)((value2 is RectTransform) ? value2 : null);
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				bool flag2 = hits?.Contains(rect.Key as string) ?? true;
				CanvasGroup val2 = ((Component)val).GetComponent<CanvasGroup>();
				if ((Object)(object)val2 == (Object)null && !flag2)
				{
					val2 = ((Component)val).gameObject.AddComponent<CanvasGroup>();
				}
				if ((Object)(object)val2 != (Object)null)
				{
					val2.alpha = (flag2 ? 1f : dimAlpha);
				}
				Image val3 = GlowOf(val, flag && flag2);
				if (!((Object)(object)val3 == (Object)null))
				{
					bool flag3 = flag && flag2;
					if (((Component)val3).gameObject.activeSelf != flag3)
					{
						((Component)val3).gameObject.SetActive(flag3);
					}
					if (flag3)
					{
						((Graphic)val3).color = value;
						_glows.Add(val3);
					}
				}
			}
		}

		private static void SetPaths(float alpha)
		{
			if (_pathsField == null)
			{
				return;
			}
			object value = _pathsField.GetValue(null);
			RectTransform val = (RectTransform)((value != null) ? /*isinst with value type is only supported in some contexts*/: null);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			CanvasGroup val2 = ((Component)val).GetComponent<CanvasGroup>();
			if ((Object)(object)val2 == (Object)null)
			{
				if (alpha >= 1f)
				{
					return;
				}
				val2 = ((Component)val).gameObject.AddComponent<CanvasGroup>();
			}
			val2.alpha = alpha;
			val2.blocksRaycasts = true;
		}

		private static Image GlowOf(RectTransform node, bool create)
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: 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_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: 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_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: 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_00a9: 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)
			Transform val = ((Transform)node).Find("TTT_SearchGlow");
			if ((Object)(object)val != (Object)null)
			{
				return ((Component)val).GetComponent<Image>();
			}
			if (!create)
			{
				return null;
			}
			GameObject val2 = new GameObject("TTT_SearchGlow", new Type[1] { typeof(RectTransform) });
			val2.transform.SetParent((Transform)(object)node, false);
			val2.transform.SetAsFirstSibling();
			RectTransform val3 = (RectTransform)val2.transform;
			Vector2 val4 = default(Vector2);
			((Vector2)(ref val4))..ctor(0.5f, 0.5f);
			val3.pivot = val4;
			Vector2 anchorMin = (val3.anchorMax = val4);
			val3.anchorMin = anchorMin;
			val3.anchoredPosition = Vector2.zero;
			Rect rect = node.rect;
			float width = ((Rect)(ref rect)).width;
			rect = node.rect;
			float num = Mathf.Max(width, ((Rect)(ref rect)).height);
			if (num < 1f)
			{
				num = 40f;
			}
			val3.sizeDelta = new Vector2(num * 2.3f, num * 2.3f);
			Image obj = val2.AddComponent<Image>();
			obj.sprite = GlowSprite();
			((Graphic)obj).raycastTarget = false;
			return obj;
		}

		private static Sprite GlowSprite()
		{
			//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_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Expected O, but got Unknown
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_glowSprite != (Object)null)
			{
				return _glowSprite;
			}
			Texture2D val = new Texture2D(128, 128, (TextureFormat)4, false)
			{
				wrapMode = (TextureWrapMode)1,
				filterMode = (FilterMode)1
			};
			Color32[] array = (Color32[])(object)new Color32[16384];
			float num = 0.43478262f;
			float num2 = 64f;
			for (int i = 0; i < 128; i++)
			{
				for (int j = 0; j < 128; j++)
				{
					float num3 = Mathf.Sqrt(((float)j + 0.5f - num2) * ((float)j + 0.5f - num2) + ((float)i + 0.5f - num2) * ((float)i + 0.5f - num2)) / num2;
					float num4 = (num3 - num) / 0.16f;
					float num5 = Mathf.Exp((0f - num4) * num4);
					num5 *= Mathf.Clamp01((1f - num3) / 0.12f);
					array[i * 128 + j] = new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, (byte)Mathf.Clamp(Mathf.RoundToInt(num5 * 255f), 0, 255));
				}
			}
			val.SetPixels32(array);
			val.Apply(false, true);
			((Object)val).hideFlags = (HideFlags)32;
			_glowSprite = Sprite.Create(val, new Rect(0f, 0f, 128f, 128f), new Vector2(0.5f, 0.5f), 100f);
			((Object)_glowSprite).hideFlags = (HideFlags)32;
			return _glowSprite;
		}

		internal static void Tick()
		{
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			if (_glows.Count == 0)
			{
				return;
			}
			float a = 0.65f + 0.35f * Mathf.Sin(Time.unscaledTime * 3.2f);
			for (int num = _glows.Count - 1; num >= 0; num--)
			{
				Image val = _glows[num];
				if ((Object)(object)val == (Object)null)
				{
					_glows.RemoveAt(num);
				}
				else
				{
					Color color = ((Graphic)val).color;
					color.a = a;
					((Graphic)val).color = color;
				}
			}
		}

		private static List<Entry> BuildIndex()
		{
			List<Entry> list = new List<Entry>();
			StringBuilder stringBuilder = new StringBuilder();
			foreach (object item in (IEnumerable)_all.GetValue(null, null))
			{
				if (item == null)
				{
					continue;
				}
				string text = _id.GetValue(item, null) as string;
				if (string.IsNullOrEmpty(text))
				{
					continue;
				}
				stringBuilder.Length = 0;
				Append(stringBuilder, Translate(_nameKey.GetValue(item, null) as string));
				Append(stringBuilder, text);
				Append(stringBuilder, Translate(_descKey.GetValue(item, null) as string));
				try
				{
					if (_statRows.Invoke(item, null) is IEnumerable enumerable)
					{
						foreach (object item2 in enumerable)
						{
							if (item2 != null)
							{
								Append(stringBuilder, _label.GetValue(item2) as string);
							}
						}
					}
				}
				catch
				{
				}
				list.Add(new Entry
				{
					Id = text,
					Text = stringBuilder.ToString().ToLowerInvariant()
				});
			}
			return list;
		}

		private static void Append(StringBuilder sb, string s)
		{
			if (!string.IsNullOrEmpty(s))
			{
				if (sb.Length > 0)
				{
					sb.Append(' ');
				}
				sb.Append(s);
			}
		}

		private static string Translate(string key)
		{
			if (string.IsNullOrEmpty(key))
			{
				return null;
			}
			ParameterInfo[] parameters = _translate.GetParameters();
			object[] array = new object[parameters.Length];
			array[0] = key;
			for (int i = 1; i < parameters.Length; i++)
			{
				array[i] = parameters[i].DefaultValue;
			}
			return _translate.Invoke(null, array) as string;
		}

		private static void LogOnce(string doing, Exception e)
		{
			if (!_failureLogged)
			{
				_failureLogged = true;
				Plugin.Log.LogWarning((object)("Problem while " + doing + "; the search is left as it is: " + e.Message));
			}
		}
	}
	internal static class TalentTreeSelectButton
	{
		private const string TooltipTypeName = "UI.TalentHoverTooltip";

		private static Harmony _harmony;

		private static bool _enabled;

		private static bool _hideNow;

		private static int _iDef;

		private static int _iRank;

		private static int _iStaged;

		private static int _iCanUnlock;

		private static FieldInfo _rootRt;

		private static FieldInfo _unlockButtonRt;

		private static FieldInfo _separatorRts;

		private static Type _defType;

		private static PropertyInfo _maxRank;

		private static bool _failureLogged;

		internal static void Init()
		{
			QolConfig.HideSelectButtonEnabled.SettingChanged += OnConfigChanged;
			QolConfig.HideSelectButtonWhenUnavailable.SettingChanged += OnConfigChanged;
			RefreshConfig();
		}

		internal static void Shutdown()
		{
			if (QolConfig.HideSelectButtonEnabled != null)
			{
				QolConfig.HideSelectButtonEnabled.SettingChanged -= OnConfigChanged;
			}
			if (QolConfig.HideSelectButtonWhenUnavailable != null)
			{
				QolConfig.HideSelectButtonWhenUnavailable.SettingChanged -= OnConfigChanged;
			}
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			_harmony = null;
		}

		internal static void Resolve()
		{
			//IL_027b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0285: Expected O, but got Unknown
			//IL_029b: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a9: Expected O, but got Unknown
			//IL_02c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ce: Expected O, but got Unknown
			if (!Chainloader.PluginInfos.TryGetValue("M2Valheim.TalentTree", out var value) || value == null || (Object)(object)value.Instance == (Object)null)
			{
				Plugin.Log.LogInfo((object)"TalentTree is not installed; the Select button of its tooltip is left alone.");
				return;
			}
			try
			{
				Type type = ((object)value.Instance).GetType().Assembly.GetType("UI.TalentHoverTooltip", throwOnError: false);
				if (type == null)
				{
					Unexpected("UI.TalentHoverTooltip does not exist");
					return;
				}
				MethodInfo methodInfo = AccessTools.Method(type, "ShowFor", (Type[])null, (Type[])null);
				MethodInfo methodInfo2 = AccessTools.Method(type, "LayoutUnlockBlock", (Type[])null, (Type[])null);
				if (methodInfo == null || methodInfo2 == null)
				{
					Unexpected("ShowFor / LayoutUnlockBlock not found");
					return;
				}
				ParameterInfo[] parameters = methodInfo.GetParameters();
				_iDef = IndexOf(parameters, "def", null);
				_iRank = IndexOf(parameters, "currentRank", typeof(int));
				_iStaged = IndexOf(parameters, "stagedDelta", typeof(int));
				_iCanUnlock = IndexOf(parameters, "canUnlock", typeof(bool));
				if (_iDef < 0 || _iRank < 0 || _iStaged < 0 || _iCanUnlock < 0)
				{
					Unexpected("ShowFor has other parameters");
					return;
				}
				ParameterInfo[] parameters2 = methodInfo2.GetParameters();
				if (parameters2.Length != 4 || parameters2[0].ParameterType != typeof(float) || parameters2[1].ParameterType != typeof(float) || parameters2[2].ParameterType != typeof(float) || parameters2[3].ParameterType != typeof(float))
				{
					Unexpected("LayoutUnlockBlock has other parameters");
					return;
				}
				_rootRt = AccessTools.Field(type, "_rootRt");
				_unlockButtonRt = AccessTools.Field(type, "_unlockButtonRt");
				_separatorRts = AccessTools.Field(type, "_separatorRts");
				if (_rootRt == null || _rootRt.FieldType != typeof(RectTransform) || _unlockButtonRt == null || _unlockButtonRt.FieldType != typeof(RectTransform) || _separatorRts == null || _separatorRts.FieldType != typeof(RectTransform[]))
				{
					Unexpected("the tooltip's fields are not as expected");
					return;
				}
				_harmony = new Harmony("DarthVladi.TalentTreeTweaks.SelectButton");
				_harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(TalentTreeSelectButton), "ShowForPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				_harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(typeof(TalentTreeSelectButton), "LayoutPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				Plugin.Log.LogInfo((object)"TalentTree found; its Select button will be hidden on nodes that can't be taken.");
			}
			catch (Exception ex)
			{
				Harmony harmony = _harmony;
				if (harmony != null)
				{
					harmony.UnpatchSelf();
				}
				_harmony = null;
				Plugin.Log.LogWarning((object)("Could not hook TalentTree's tooltip, the Select button stays as it is: " + ex.Message));
			}
		}

		private static int IndexOf(ParameterInfo[] ps, string name, Type type)
		{
			for (int i = 0; i < ps.Length; i++)
			{
				if (ps[i].Name == name && (type == null || ps[i].ParameterType == type))
				{
					return i;
				}
			}
			return -1;
		}

		private static void Unexpected(string what)
		{
			Plugin.Log.LogWarning((object)("TalentTree found, but its tooltip is not as expected (" + what + "; different TalentTree version?). The Select button stays as it is."));
		}

		internal static void ShowForPrefix(object[] __args)
		{
			_hideNow = false;
			if (!_enabled)
			{
				return;
			}
			try
			{
				if ((bool)__args[_iCanUnlock])
				{
					return;
				}
				if (QolConfig.HideSelectButtonWhenUnavailable.Value)
				{
					_hideNow = true;
					return;
				}
				object obj = __args[_iDef];
				if (obj != null)
				{
					int num = MaxRankOf(obj);
					_hideNow = num > 0 && (int)__args[_iRank] + (int)__args[_iStaged] >= num;
				}
			}
			catch (Exception e)
			{
				LogOnce("deciding about the Select button", e);
			}
		}

		internal static void LayoutPostfix(object __instance, object[] __args)
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			if (!_hideNow)
			{
				return;
			}
			try
			{
				object? value = _unlockButtonRt.GetValue(__instance);
				RectTransform val = (RectTransform)((value is RectTransform) ? value : null);
				RectTransform[] array = _separatorRts.GetValue(__instance) as RectTransform[];
				object? value2 = _rootRt.GetValue(__instance);
				RectTransform val2 = (RectTransform)((value2 is RectTransform) ? value2 : null);
				float num = (((Object)(object)val != (Object)null) ? val.sizeDelta.y : 0f);
				if ((Object)(object)val != (Object)null)
				{
					((Component)val).gameObject.SetActive(false);
				}
				if (array != null && array.Length > 2 && (Object)(object)array[2] != (Object)null)
				{
					((Component)array[2]).gameObject.SetActive(false);
				}
				float num2 = (float)__args[1];
				float num3 = (float)__args[2];
				float num4 = 2f * num3 + num2 + num;
				if ((Object)(object)val2 != (Object)null && num > 0f && num < 400f)
				{
					Vector2 sizeDelta = val2.sizeDelta;
					val2.sizeDelta = new Vector2(sizeDelta.x, Mathf.Max(1f, sizeDelta.y - num4));
				}
			}
			catch (Exception e)
			{
				LogOnce("hiding the Select button", e);
			}
		}

		private static int MaxRankOf(object def)
		{
			Type type = def.GetType();
			if (type != _defType)
			{
				_defType = type;
				PropertyInfo property = type.GetProperty("MaxRank", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				_maxRank = ((property != null && property.PropertyType == typeof(int)) ? property : null);
				if (_maxRank == null)
				{
					Unexpected("a node has no MaxRank");
				}
			}
			if (!(_maxRank != null))
			{
				return 0;
			}
			return (int)_maxRank.GetValue(def, null);
		}

		private static void LogOnce(string doing, Exception e)
		{
			if (!_failureLogged)
			{
				_failureLogged = true;
				Plugin.Log.LogWarning((object)("Problem while " + doing + "; the Select button is left as it is: " + e.Message));
			}
		}

		private static void OnConfigChanged(object sender, EventArgs e)
		{
			RefreshConfig();
		}

		private static void RefreshConfig()
		{
			_enabled = QolConfig.HideSelectButtonEnabled.Value || QolConfig.HideSelectButtonWhenUnavailable.Value;
		}
	}
	internal static class TalentTreeSelectionStyle
	{
		private const string ViewTypeName = "UI.TalentTreeView";

		private static Harmony _harmony;

		private static FieldInfo _nodes;

		private static FieldInfo _border;

		private static FieldInfo _state;

		private static bool _failureLogged;

		private static bool _failed;

		private static float _lighten;

		internal static void Init()
		{
			QolConfig.SelectionLighten.SettingChanged += OnConfigChanged;
			_lighten = Mathf.Clamp01(QolConfig.SelectionLighten.Value);
		}

		internal static void Shutdown()
		{
			if (QolConfig.SelectionLighten != null)
			{
				QolConfig.SelectionLighten.SettingChanged -= OnConfigChanged;
			}
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			_harmony = null;
		}

		private static void OnConfigChanged(object sender, EventArgs e)
		{
			_lighten = Mathf.Clamp01(QolConfig.SelectionLighten.Value);
		}

		internal static void Resolve()
		{
			//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f6: Expected O, but got Unknown
			//IL_020d: Unknown result type (might be due to invalid IL or missing references)
			//IL_021a: Expected O, but got Unknown
			if (!QolConfig.SoftSelection.Value)
			{
				return;
			}
			if (!Chainloader.PluginInfos.TryGetValue("M2Valheim.TalentTree", out var value) || value == null || (Object)(object)value.Instance == (Object)null)
			{
				Plugin.Log.LogInfo((object)"TalentTree is not installed; the selection ring of its nodes is left alone.");
				return;
			}
			try
			{
				Type type = ((object)value.Instance).GetType().Assembly.GetType("UI.TalentTreeView", throwOnError: false);
				if (type == null)
				{
					Unexpected("UI.TalentTreeView does not exist");
					return;
				}
				MethodInfo methodInfo = AccessTools.Method(type, "SetHighlighted", (Type[])null, (Type[])null);
				if (methodInfo == null)
				{
					Unexpected("SetHighlighted was not found");
					return;
				}
				ParameterInfo[] parameters = methodInfo.GetParameters();
				if (parameters.Length != 3 || parameters[0].ParameterType != typeof(string) || parameters[1].ParameterType != typeof(bool) || parameters[2].ParameterType != typeof(float))
				{
					Unexpected("SetHighlighted has other parameters");
					return;
				}
				_nodes = AccessTools.Field(type, "_nodes");
				if (_nodes == null || !typeof(IDictionary).IsAssignableFrom(_nodes.FieldType) || !_nodes.FieldType.IsGenericType)
				{
					Unexpected("_nodes is not as expected");
					return;
				}
				Type obj = _nodes.FieldType.GetGenericArguments()[1];
				_border = AccessTools.Field(obj, "Border");
				_state = AccessTools.Field(obj, "StateColor");
				if (_border == null || !typeof(Image).IsAssignableFrom(_border.FieldType) || _state == null || _state.FieldType != typeof(Color))
				{
					Unexpected("the node's fields are not as expected");
					return;
				}
				_harmony = new Harmony("DarthVladi.TalentTreeTweaks.SelectionStyle");
				_harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(TalentTreeSelectionStyle), "HighlightPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				Plugin.Log.LogInfo((object)"The selection ring of TalentTree's nodes will use the node's own colour, lightened.");
			}
			catch (Exception ex)
			{
				Harmony harmony = _harmony;
				if (harmony != null)
				{
					harmony.UnpatchSelf();
				}
				_harmony = null;
				Unexpected(ex.Message);
			}
		}

		private static void HighlightPostfix(object __instance, object[] __args)
		{
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			if (_failed || __instance == null || __args == null || __args.Length < 2)
			{
				return;
			}
			try
			{
				if (!(bool)__args[1])
				{
					return;
				}
				object obj = ((_nodes.GetValue(__instance) is IDictionary dictionary && __args[0] is string key) ? dictionary[key] : null);
				if (obj != null)
				{
					object? value = _border.GetValue(obj);
					Image val = (Image)((value is Image) ? value : null);
					if (!((Object)(object)val == (Object)null))
					{
						Color val2 = (Color)_state.GetValue(obj);
						Color color = Color.Lerp(val2, Color.white, _lighten);
						color.a = val2.a;
						((Graphic)val).color = color;
					}
				}
			}
			catch (Exception ex)
			{
				_failed = true;
				Unexpected("a node could not be changed: " + ex.Message);
			}
		}

		private static void Unexpected(string why)
		{
			if (!_failureLogged)
			{
				_failureLogged = true;
				Plugin.Log.LogWarning((object)("The selection ring of TalentTree's nodes stays as TalentTree draws it (" + why + "); a different TalentTree version may have changed it."));
			}
		}
	}
	internal static class TalentTreeTab
	{
		internal const string SenealApiGuid = "seneaL.valheim.api";

		private static bool _registered;

		internal static void Init()
		{
		}

		internal static void Resolve()
		{
			if (!QolConfig.TalentTreeTabEnabled.Value)
			{
				return;
			}
			if (!Chainloader.PluginInfos.ContainsKey("seneaL.valheim.api"))
			{
				Plugin.Log.LogInfo((object)"SeneaL API is not installed; the TalentTree tab is not added.");
				return;
			}
			if (!TalentTreeHotkey.Available)
			{
				Plugin.Log.LogInfo((object)"TalentTree is not available; the TalentTree tab is not added.");
				return;
			}
			try
			{
				string value = QolConfig.TalentTreeTabIcon.Value;
				_registered = SenealTabApi.Register("DarthVladi.TalentTreeTweaks", value);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Could not add the TalentTree tab to SeneaL (" + ex.GetType().Name + ": " + ex.Message + ")."));
			}
		}

		internal static void Shutdown()
		{
			if (!_registered)
			{
				return;
			}
			_registered = false;
			try
			{
				SenealTabApi.Remove("DarthVladi.TalentTreeTweaks");
			}
			catch
			{
			}
		}
	}
	internal static class SenealTabApi
	{
		private const string TabId = "talents";

		internal static bool Register(string owner, string iconName)
		{
			if (!Api.Has("tabs"))
			{
				Plugin.Log.LogInfo((object)"The installed SeneaL API has no character tabs (needs 1.1.0 or newer); the TalentTree tab is not added.");
				return false;
			}
			CharacterTab val = CharacterTabs.Add(owner, "talents", (Func<string>)(() => "Talents"), (Action)OnOpen);
			if (val == null)
			{
				return false;
			}
			if (!string.IsNullOrWhiteSpace(iconName))
			{
				val.IconName = iconName.Trim();
			}
			val.Order = 50;
			val.Active = () => TalentTreeHotkey.IsWindowOpen;
			val.Tip = Tip;
			Plugin.Log.LogInfo((object)"TalentTree tab added to SeneaL's character screen.");
			return true;
		}

		internal static void Remove(string owner)
		{
			CharacterTabs.Remove(owner, "talents");
		}

		private static void OnOpen()
		{
			TalentTreeHotkey.TryToggle();
		}

		private static string Tip()
		{
			string hotkeyText = TalentTreeHotkey.HotkeyText;
			if (hotkeyText.Length != 0)
			{
				return "Talent tree (" + hotkeyText + ")";
			}
			return "Talent tree";
		}
	}
	internal static class TalentTreeTooltipStyle
	{
		private const string TooltipTypeName = "UI.TalentHoverTooltip";

		private const string LayoutTypeName = "UI.TalentUiLayout";

		private const string RegistryTypeName = "Core.SectorRegistry";

		private const string DefinitionTypeName = "Core.TalentDefinition";

		private static Harmony _harmony;

		private static bool _titleByBranch;

		private static bool _subtitlesByBranch;

		private static bool _tokenByBranch;

		private static float _tokenOutline;

		private static int _iShowForDef;

		private static int _iRowsDef;

		private static FieldInfo _title;

		private static FieldInfo _desc;

		private static FieldInfo _rankRows;

		private static FieldInfo _keyGlyphRow;

		private static FieldInfo _costTokenRt;

		private static FieldInfo _costTokenText;

		private static FieldInfo _unlockButtonText;

		private static PropertyInfo _sectorId;

		private static Func<string, Color> _getAccent;

		private static Font _font;

		private static bool _fontTried;

		private const string StatsPanelTypeName = "UI.StatsPanelView";

		private static FieldInfo _statsRoot;

		private static object _styledInstance;

		private static Color _originalTitle;

		private static Color _originalToken;

		private static bool _originalKnown;

		private static bool _failureLogged;

		internal static void Init()
		{
			QolConfig.TitleColorByBranch.SettingChanged += OnConfigChanged;
			QolConfig.SubtitleColorByBranch.SettingChanged += OnConfigChanged;
			QolConfig.CostTokenColorByBranch.SettingChanged += OnConfigChanged;
			QolConfig.CostTokenOutline.SettingChanged += OnConfigChanged;
			RefreshConfig();
		}

		internal static void Shutdown()
		{
			if (QolConfig.TitleColorByBranch != null)
			{
				QolConfig.TitleColorByBranch.SettingChanged -= OnConfigChanged;
			}
			if (QolConfig.SubtitleColorByBranch != null)
			{
				QolConfig.SubtitleColorByBranch.SettingChanged -= OnConfigChanged;
			}
			if (QolConfig.CostTokenColorByBranch != null)
			{
				QolConfig.CostTokenColorByBranch.SettingChanged -= OnConfigChanged;
			}
			if (QolConfig.CostTokenOutline != null)
			{
				QolConfig.CostTokenOutline.SettingChanged -= OnConfigChanged;
			}
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			_harmony = null;
		}

		internal static void Resolve()
		{
			if (Chainloader.PluginInfos.TryGetValue("M2Valheim.TalentTree", out var value) && value != null && !((Object)(object)value.Instance == (Object)null))
			{
				Assembly assembly = ((object)value.Instance).GetType().Assembly;
				ApplyTokenSize(assembly);
				PatchTooltip(assembly);
			}
		}

		private static void ApplyTokenSize(Assembly asm)
		{
			try
			{
				Type? type = asm.GetType("UI.TalentUiLayout", throwOnError: false);
				PropertyInfo propertyInfo = type?.GetProperty("Default", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				FieldInfo fieldInfo = type?.GetField("CostTokenSize", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				FieldInfo fieldInfo2 = type?.GetField("CostTokenFontSize", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				object obj = propertyInfo?.GetValue(null, null);
				if (obj == null || fieldInfo == null || fieldInfo.FieldType != typeof(float) || fieldInfo2 == null || fieldInfo2.FieldType != typeof(int))
				{
					Plugin.Log.LogWarning((object)"TalentTree found, but its layout is not as expected (CostTokenSize / CostTokenFontSize; different TalentTree version?). The cost token keeps its size.");
					return;
				}
				fieldInfo.SetValue(obj, QolConfig.CostTokenSize.Value);
				fieldInfo2.SetValue(obj, QolConfig.CostTokenFontSize.Value);
				Plugin.Log.LogInfo((object)$"TalentTree cost token set to size {QolConfig.CostTokenSize.Value:0.#}, font {QolConfig.CostTokenFontSize.Value}.");
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Could not change TalentTree's cost token size, it keeps its size: " + ex.Message));
			}
		}

		private static void LoadFont()
		{
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Expected O, but got Unknown
			_fontTried = true;
			string value = QolConfig.TooltipFont.Value;
			if (string.IsNullOrWhiteSpace(value))
			{
				return;
			}
			try
			{
				string path = Path.GetDirectoryName(typeof(Plugin).Assembly.Location) ?? "";
				string text = Path.Combine(path, value);
				if (!File.Exists(text))
				{
					text = Path.Combine(Path.Combine(path, "fonts"), value);
				}
				if (!File.Exists(text))
				{
					Plugin.Log.LogWarning((object)("Font \"" + value + "\" not found next to TalentTreeTweaks.dll or in its \"fonts\" folder; TalentTree's tooltip keeps its font."));
					return;
				}
				Font val = new Font(text);
				if ((Object)(object)val == (Object)null)
				{
					Plugin.Log.LogWarning((object)("Font \"" + value + "\" could not be read (Unity rejected " + text + "); TalentTree's tooltip keeps its font."));
					return;
				}
				if (!val.dynamic)
				{
					Font val2 = LoadAsOsFont(text);
					if (!((Object)(object)val2 != (Object)null))
					{
						Plugin.Log.LogWarning((object)("Font \"" + value + "\" could not be used (not a dynamic font, no OS fallback); TalentTree's tooltip keeps its font."));
						Object.Destroy((Object)(object)val);
						return;
					}
					Object.Destroy((Object)(object)val);
					val = val2;
				}
				((Object)val).name = "TalentTreeTweaks " + Path.GetFileNameWithoutExtension(value);
				((Object)val).hideFlags = (HideFlags)32;
				_font = val;
				Plugin.Log.LogInfo((object)$"Font \"{value}\" created from {text} (dynamic: {val.dynamic}); it is used on TalentTree's tooltip once it is shown.");
			}
			catch (Exception ex)
			{
				_font = null;
				Plugin.Log.LogWarning((object)("Could not load font \"" + value + "\" (" + ex.Message + "); TalentTree's tooltip keeps its font."));
			}
		}

		[DllImport("gdi32.dll", CharSet = CharSet.Unicode, EntryPoint = "AddFontResourceExW")]
		private static extern int AddFontResourceEx(string file, uint flags, IntPtr reserved);

		private static Font LoadAsOsFont(string path)
		{
			try
			{
				string text = ReadFamilyName(path);
				if (text == null)
				{
					return null;
				}
				if (AddFontResourceEx(path, 16u, IntPtr.Zero) <= 0)
				{
					return null;
				}
				Font val = Font.CreateDynamicFontFromOSFont(text, 16);
				Plugin.Log.LogInfo((object)$"Font family \"{text}\" registered for this game session (dynamic: {(Object)(object)val != (Object)null && val.dynamic}).");
				return ((Object)(object)val != (Object)null && val.dynamic) ? val : null;
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("OS font fallback failed (" + ex.GetType().Name + ": " + ex.Message + ")."));
				return null;
			}
		}

		private static string ReadFamilyName(string path)
		{
			byte[] d = File.ReadAllBytes(path);
			Func<int, int> func = (int o) => (d[o] << 8) | d[o + 1];
			Func<int, long> func2 = (int o) => (long)(((ulong)d[o] << 24) | ((ulong)d[o + 1] << 16) | ((ulong)d[o + 2] << 8) | d[o + 3]);
			int num = func(4);
			for (int num2 = 0; num2 < num; num2++)
			{
				int num3 = 12 + num2 * 16;
				if (d[num3] != 110 || d[num3 + 1] != 97 || d[num3 + 2] != 109 || d[num3 + 3] != 101)
				{
					continue;
				}
				int num4 = (int)func2(num3 + 8);
				int num5 = func(num4 + 2);
				int num6 = num4 + func(num4 + 4);
				string text = null;
				for (int num7 = 0; num7 < num5; num7++)
				{
					int num8 = num4 + 6 + num7 * 12;
					if (func(num8 + 6) == 1)
					{
						int num9 = func(num8);
						int count = func(num8 + 8);
						int index = num6 + func(num8 + 10);
						string text2 = ((num9 == 3 || num9 == 0) ? Encoding.BigEndianUnicode.GetString(d, index, count) : Encoding.ASCII.GetString(d, index, count));
						if (num9 == 3)
						{
							return text2;
						}
						text = text ?? text2;
					}
				}
				return text;
			}
			return null;
		}

		private static void PatchTooltip(Assembly asm)
		{
			//IL_02ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b8: Expected O, but got Unknown
			//IL_02ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f0: Expected O, but got Unknown
			//IL_02f0: Expected O, but got Unknown
			//IL_0309: Unknown result type (might be due to invalid IL or missing references)
			//IL_0316: Expected O, but got Unknown
			try
			{
				Type type = asm.GetType("UI.TalentHoverTooltip", throwOnError: false);
				Type type2 = asm.GetType("Core.SectorRegistry", throwOnError: false);
				Type type3 = asm.GetType("Core.TalentDefinition", throwOnError: false);
				if (type == null || type2 == null || type3 == null)
				{
					Unexpected("a type was not found");
					return;
				}
				MethodInfo methodInfo = AccessTools.Method(type, "ShowFor", (Type[])null, (Type[])null);
				MethodInfo methodInfo2 = AccessTools.Method(type, "UpdateRankRows", (Type[])null, (Type[])null);
				MethodInfo method = type2.GetMethod("GetAccent", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(string) }, null);
				_sectorId = type3.GetProperty("SectorId", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (methodInfo == null || methodInfo2 == null || method == null || method.ReturnType != typeof(Color) || _sectorId == null || _sectorId.PropertyType != typeof(string))
				{
					Unexpected("the branch colour or the tooltip methods are not where expected");
					return;
				}
				_iShowForDef = IndexOf(methodInfo.GetParameters(), "def");
				_iRowsDef = IndexOf(methodInfo2.GetParameters(), "def");
				if (_iShowForDef < 0 || _iRowsDef < 0)
				{
					Unexpected("ShowFor / UpdateRankRows have other parameters");
					return;
				}
				_title = TextField(type, "_title");
				_desc = TextField(type, "_desc");
				_costTokenText = TextField(type, "_costTokenText");
				_unlockButtonText = TextField(type, "_unlockButtonText");
				_rankRows = AccessTools.Field(type, "_rankRows");
				_keyGlyphRow = AccessTools.Field(type, "_keyGlyphRow");
				_costTokenRt = AccessTools.Field(type, "_costTokenRt");
				if (_title == null || _desc == null || _costTokenText == null || _unlockButtonText == null || _rankRows == null || _rankRows.FieldType != typeof(Text[]) || _keyGlyphRow == null || _keyGlyphRow.FieldType != typeof(int) || _costTokenRt == null || _costTokenRt.FieldType != typeof(RectTransform))
				{
					Unexpected("the tooltip's fields are not as expected");
					return;
				}
				_getAccent = (Func<string, Color>)Delegate.CreateDelegate(typeof(Func<string, Color>), method);
				_harmony = new Harmony("DarthVladi.TalentTreeTweaks.TooltipStyle");
				_harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(TalentTreeTooltipStyle), "ShowForPrefix", (Type[])null), new HarmonyMethod(typeof(TalentTreeTooltipStyle), "ShowForPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				_harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(typeof(TalentTreeTooltipStyle), "UpdateRankRowsPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				Plugin.Log.LogInfo((object)"TalentTree found; its tooltip can take branch colours, a thicker token outline and your font.");
				PatchStatsPanel(asm);
			}
			catch (Exception ex)
			{
				Harmony harmony = _harmony;
				if (harmony != null)
				{
					harmony.UnpatchSelf();
				}
				_harmony = null;
				Plugin.Log.LogWarning((object)("Could not hook TalentTree's tooltip, it keeps its look: " + ex.Message));
			}
		}

		private static void PatchStatsPanel(Assembly asm)
		{
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Expected O, but got Unknown
			try
			{
				Type type = asm.GetType("UI.StatsPanelView", throwOnError: false);
				MethodInfo methodInfo = ((type != null) ? AccessTools.Method(type, "Build", (Type[])null, (Type[])null) : null);
				_statsRoot = ((type != null) ? AccessTools.Field(type, "_root") : null);
				if (methodInfo == null || _statsRoot == null || _statsRoot.FieldType != typeof(GameObject))
				{
					Plugin.Log.LogWarning((object)"TalentTree found, but its Stats panel is not as expected (different TalentTree version?). It keeps its font.");
				}
				else
				{
					_harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(TalentTreeTooltipStyle), "StatsBuildPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Could not hook TalentTree's Stats panel, it keeps its font: " + ex.Message));
			}
		}

		internal static void StatsBuildPostfix(object __instance)
		{
			try
			{
				if (!_fontTried)
				{
					LoadFont();
				}
				if ((Object)(object)_font == (Object)null)
				{
					return;
				}
				object? value = _statsRoot.GetValue(__instance);
				GameObject val = (GameObject)((value is GameObject) ? value : null);
				if ((Object)(object)val == (Object)null)
				{
					return;
				}
				Text[] componentsInChildren = val.GetComponentsInChildren<Text>(true);
				if (componentsInChildren.Length != 0)
				{
					EnsureMaterial(componentsInChildren[0]);
					for (int i = 0; i < componentsInChildren.Length; i++)
					{
						SetFont(componentsInChildren[i]);
					}
				}
			}
			catch (Exception e)
			{
				LogOnce("setting the font of the Stats panel", e);
			}
		}

		private static FieldInfo TextField(Type type, string name)
		{
			FieldInfo fieldInfo = AccessTools.Field(type, name);
			if (!(fieldInfo != null) || !(fieldInfo.FieldType == typeof(Text)))
			{
				return null;
			}
			return fieldInfo;
		}

		private static int IndexOf(ParameterInfo[] ps, string name)
		{
			for (int i = 0; i < ps.Length; i++)
			{
				if (ps[i].Name == name)
				{
					return i;
				}
			}
			return -1;
		}

		private static void Unexpected(string what)
		{
			Plugin.Log.LogWarning((object)("TalentTree found, but its tooltip is not as expected (" + what + "; different TalentTree version?). It keeps its look."));
		}

		internal static void ShowForPrefix(object __instance)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: 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_0042: 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_00bc: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				object? value = _title.GetValue(__instance);
				Text val = (Text)((value is Text) ? value : null);
				Image val2 = TokenImage(__instance);
				if (!_originalKnown && (Object)(object)val != (Object)null)
				{
					_originalTitle = ((Graphic)val).color;
					if ((Object)(object)val2 != (Object)null)
					{
						_originalToken = ((Graphic)val2).color;
					}
					_originalKnown = true;
				}
				if (_styledInstance != __instance)
				{
					_styledInstance = __instance;
					ApplyFont(__instance);
				}
				object? value2 = _costTokenText.GetValue(__instance);
				Text val3 = (Text)((value2 is Text) ? value2 : null);
				Outline val4 = (((Object)(object)val3 != (Object)null) ? ((Component)val3).GetComponent<Outline>() : null);
				if ((Object)(object)val4 != (Object)null && _tokenOutline > 0f)
				{
					Vector2 val5 = default(Vector2);
					((Vector2)(ref val5))..ctor(_tokenOutline, 0f - _tokenOutline);
					if (((Shadow)val4).effectDistance != val5)
					{
						((Shadow)val4).effectDistance = val5;
					}
				}
			}
			catch (Exception e)
			{
				LogOnce("preparing the tooltip", e);
			}
		}

		internal static void ShowForPostfix(object __instance, object[] __args)
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: 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_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: 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_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (!_originalKnown)
				{
					return;
				}
				Color accent;
				bool flag = TryAccent(__args[_iShowForDef], out accent);
				object? value = _title.GetValue(__instance);
				Text val = (Text)((value is Text) ? value : null);
				if ((Object)(object)val != (Object)null)
				{
					Color val2 = ((_titleByBranch && flag) ? accent : _originalTitle);
					if (((Graphic)val).color != val2)
					{
						((Graphic)val).color = val2;
					}
				}
				Image val3 = TokenImage(__instance);
				if ((Object)(object)val3 != (Object)null)
				{
					Color val4 = ((_tokenByBranch && flag) ? accent : _originalToken);
					if (((Graphic)val3).color != val4)
					{
						((Graphic)val3).color = val4;
					}
				}
			}
			catch (Exception e)
			{
				LogOnce("colouring the tooltip", e);
			}
		}

		internal static void UpdateRankRowsPostfix(object __instance, object[] __args)
		{
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (!_subtitlesByBranch || !_originalKnown || !TryAccent(__args[_iRowsDef], out var accent) || !(_rankRows.GetValue(__instance) is Text[] array))
				{
					return;
				}
				int num = (int)_keyGlyphRow.GetValue(__instance);
				string text = "<color=#" + ColorUtility.ToHtmlStringRGB(_originalTitle) + ">";
				string text2 = "<color=#" + ColorUtility.ToHtmlStringRGB(accent) + ">";
				for (int i = 0; i < array.Length; i++)
				{
					Text val = array[i];
					if (!((Object)(object)val == (Object)nul