Decompiled source of PotionPool v1.0.0

plugins\PotionPool.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using HarmonyLib;
using Il2CppInterop.Runtime.Injection;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem;
using Microsoft.CodeAnalysis;
using ProjectM.UI;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("PotionPool")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Client-only V Rising plugin: hovering a Blood Potion shows the Blood Pool I-V bonus lines for its type and quality.")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("PotionPool")]
[assembly: AssemblyTitle("PotionPool")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[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 PotionPool
{
	internal static class BloodBonuses
	{
		internal const string Cyan = "#5EC8D4";

		internal const string Locked = "#5A6270";

		internal const string Mute = "#8B95A3";

		internal const string VText = "All bonuses above increased by <color=#5EC8D4>+20%</color>, including the blood effect cap.";

		internal static readonly float[] Unlock = new float[5] { 0f, 30f, 60f, 90f, 100f };

		internal static bool TryParse(string blob, out string type, out float quality)
		{
			type = null;
			quality = 0f;
			if (string.IsNullOrEmpty(blob))
			{
				return false;
			}
			type = MatchType(blob);
			quality = MatchQuality(blob);
			if (type != null)
			{
				return quality > 0f;
			}
			return false;
		}

		internal static string Build(string type, float quality)
		{
			string text = Normalize(type);
			string[] array;
			char c;
			switch (text)
			{
			case "frail":
			case "frailed":
				return "";
			default:
				switch (text.Length)
				{
				case 8:
					break;
				case 6:
					goto IL_007b;
				case 5:
					goto IL_009b;
				case 7:
					goto IL_00bb;
				case 9:
					goto IL_0183;
				default:
					goto IL_01ec;
				}
				c = text[0];
				if (c != 'c')
				{
					if (c != 'd')
					{
						if (c == 'i' && text == "immortal")
						{
							array = Immortal(quality);
							break;
						}
					}
					else if (text == "draculin")
					{
						array = Draculin(quality);
						break;
					}
				}
				else if (text == "creature")
				{
					array = Creature(quality);
					break;
				}
				goto IL_01ec;
			case null:
				goto IL_01ec;
				IL_0183:
				if (!(text == "corrupted"))
				{
					goto IL_01ec;
				}
				array = Corrupted(quality);
				break;
				IL_007b:
				c = text[0];
				if (c != 'm')
				{
					if (c == 'w' && text == "worker")
					{
						array = Worker(quality);
						break;
					}
				}
				else if (text == "mutant")
				{
					array = Mutant(quality);
					break;
				}
				goto IL_01ec;
				IL_00bb:
				c = text[0];
				if (c != 's')
				{
					if (c == 'w' && text == "warrior")
					{
						array = Warrior(quality);
						break;
					}
				}
				else if (text == "scholar")
				{
					array = Scholar(quality);
					break;
				}
				goto IL_01ec;
				IL_01ec:
				array = null;
				break;
				IL_009b:
				c = text[0];
				if (c != 'b')
				{
					if (c == 'r' && text == "rogue")
					{
						array = Rogue(quality);
						break;
					}
				}
				else if (text == "brute")
				{
					array = Brute(quality);
					break;
				}
				goto IL_01ec;
			}
			string[] array2 = array;
			if (array2 == null)
			{
				return FallbackGates();
			}
			return string.Join("\n", array2);
		}

		private static string[] Creature(float q)
		{
			return new string[5]
			{
				L(1, q, N(q, 0f, 8f, 16f) + " maximum health. " + Lit("+40%") + " health regeneration."),
				L(2, q, N(q, 30f, 4f, 8f) + " movement speed. " + Lit("+8%") + " shapeshift speed."),
				L(3, q, N(q, 60f, 12f, 24f) + " healing received. " + Lit("+20") + " all resistances."),
				L(4, q, "Bite heals 5% of maximum health and grants " + Lit("+25%") + " attack speed and physical damage."),
				V(q)
			};
		}

		private static string[] Worker(float q)
		{
			return new string[5]
			{
				L(1, q, N(q, 0f, 12f, 24f) + " resource yield."),
				L(2, q, N(q, 30f, 12f, 24f) + " damage to resource objects."),
				L(3, q, N(q, 60f, 8f, 16f) + " mount speed."),
				L(4, q, N(q, 90f, 3f, 3f) + " chance to instantly destroy a resource node and trigger a burst of speed."),
				V(q)
			};
		}

		private static string[] Brute(float q)
		{
			return new string[5]
			{
				L(1, q, N(q, 0f, 7f, 14f) + " primary attack speed. " + Lit("+5%") + " physical power."),
				L(2, q, N(q, 30f, 5f, 10f) + " primary attack life leech. " + Lit("+4%") + " damage reduction."),
				L(3, q, N(q, 60f, 8f, 16f) + " maximum health. Heal for 5% of victim health on killing blow."),
				L(4, q, Lit("15%") + " chance to parry, reducing damage taken by 25%. Parrying grants " + Lit("+15%") + " physical power for 3.5s."),
				V(q)
			};
		}

		private static string[] Rogue(float q)
		{
			return new string[5]
			{
				L(1, q, N(q, 0f, 8f, 16f) + " physical critical chance. " + Lit("+8%") + " physical critical power."),
				L(2, q, N(q, 30f, 4f, 8f) + " movement speed. " + Lit("+10%") + " additional speed for 3s on killing blow."),
				L(3, q, N(q, 60f, 7f, 14f) + " veil cooldown rate. 100% physical critical chance after using a Veil."),
				L(4, q, "50% chance on critical strike to expose armor, " + Lit("+15%") + " damage taken for 4s."),
				V(q)
			};
		}

		private static string[] Warrior(float q)
		{
			return new string[5]
			{
				L(1, q, Lit("+10%") + " physical power. Veil attacks deal " + Lit("+40%") + " damage."),
				L(2, q, Lit("+14%") + " weapon cooldown rate. " + Lit("+5%") + " weapon skill leech."),
				L(3, q, Lit("+18%") + " weapon skill power. " + Lit("+24%") + " damage to full-health enemies."),
				L(4, q, Lit("+12%") + " weapon charge gain."),
				V(q)
			};
		}

		private static string[] Scholar(float q)
		{
			return new string[5]
			{
				L(1, q, N(q, 0f, 6f, 12f) + " spell power. " + Lit("+10%") + " shield efficiency."),
				L(2, q, N(q, 30f, 6f, 12f) + " spell cooldown rate. Shield self for 25% of spell power when casting."),
				L(3, q, N(q, 60f, 10f, 20f) + " ultimate power. Reset spell cooldowns when using an Ultimate."),
				L(4, q, Lit("+12") + " spell charge gain."),
				V(q)
			};
		}

		private static string[] Mutant(float q)
		{
			return new string[5]
			{
				L(1, q, N(q, 0f, 7f, 14f) + " spell power. " + Lit("+10%") + " shapeshift speed."),
				L(2, q, N(q, 30f, 14f, 28f) + " ultimate cooldown rate. Spawn 2 Mutant Rats when casting an Ultimate."),
				L(3, q, N(q, 60f, 10f, 20f) + " ultimate power. " + Lit("+12%") + " minion damage."),
				L(4, q, Lit("+7%") + " veil cooldown rate. Veil attacks reduce ultimate cooldown by 7s."),
				V(q)
			};
		}

		private static string[] Draculin(float q)
		{
			return new string[5]
			{
				L(1, q, N(q, 0f, 6f, 12f) + " spell power. " + Lit("+8%") + " spell critical power."),
				L(2, q, N(q, 30f, 8f, 16f) + " spell critical chance. Spell hits grant " + Lit("+6%") + " movement speed for 3s."),
				L(3, q, N(q, 60f, 4f, 8f) + " spell leech. " + Lit("+3") + " spell charge gain."),
				L(4, q, "Spell critical strikes increase spell cooldown rate by " + Lit("+30%") + " for 3s."),
				V(q)
			};
		}

		private static string[] Corrupted(float q)
		{
			return new string[5]
			{
				L(1, q, N(q, 0f, 25f, 50f) + " reduced damage from Corrupted attacks. " + Lit("+5%") + " life leech, but " + Lit("+10%") + " damage taken from other sources."),
				L(2, q, "Vile Corruption stack cap " + N(q, 30f, 4f, 8f, percent: false) + ", but " + N(q, 30f, 50f, 100f) + " increased blood drain."),
				L(3, q, N(q, 60f, 8f, 12f) + " movement speed. " + Lit("+14%") + " attack speed. 25% chance on hit taken to erupt and snare for 2s."),
				L(4, q, Lit("+10") + " spell and weapon charge gain. 30% chance to spawn a shadow that attacks you when using a spell."),
				V(q)
			};
		}

		private static string[] Immortal(float q)
		{
			return new string[5]
			{
				L(1, q, Lit("+100%") + " physical power and spell power."),
				L(2, q, Lit("+15%") + " movement speed. " + Lit("+30%") + " primary attack speed."),
				L(3, q, Lit("+40%") + " damage reduction."),
				L(4, q, Lit("+100%") + " veil cooldown rate."),
				L(5, q, Lit("+40") + " spell and weapon charge gain.")
			};
		}

		private static string V(float q)
		{
			return L(5, q, "All bonuses above increased by <color=#5EC8D4>+20%</color>, including the blood effect cap.");
		}

		private static string Lit(string s)
		{
			return "<color=#5EC8D4>" + s + "</color>";
		}

		private static string FallbackGates()
		{
			return "I  0%+\nII  30%+\nIII  60%+\nIV  90%+\nV  100%";
		}

		private static string L(int tier, float quality, string body)
		{
			string text = tier switch
			{
				1 => "I", 
				2 => "II", 
				3 => "III", 
				4 => "IV", 
				_ => "V", 
			} + " " + tier switch
			{
				1 => "0%", 
				2 => "30%", 
				3 => "60%", 
				4 => "90%", 
				_ => "100%", 
			};
			bool num = quality + 0.001f >= Unlock[tier - 1];
			string text2 = (num ? "#8B95A3" : "#5A6270");
			string text3 = (num ? body : ("<color=#5A6270>" + StripColors(body) + "</color>"));
			return "<indent=0><color=" + text2 + ">" + text + "</color><indent=5.6em>" + text3;
		}

		internal static string N(float quality, float thresh, float min, float max, bool percent = true)
		{
			float num = ((quality >= 100f) ? 1f : ((!(quality <= thresh) && !(max <= min)) ? ((quality - thresh) / (100f - thresh)) : 0f));
			if (num < 0f)
			{
				num = 0f;
			}
			if (num > 1f)
			{
				num = 1f;
			}
			float num2 = min + num * (max - min);
			string text = ((num2 > 0f) ? "+" : "");
			return "<color=#5EC8D4>" + text + Fmt(num2) + (percent ? "%" : "") + "</color>";
		}

		private static string Fmt(float v)
		{
			double num = Math.Round(v, 1);
			if (Math.Abs(num - Math.Round(num)) < 0.049)
			{
				return ((int)Math.Round(num)).ToString();
			}
			return num.ToString("0.0");
		}

		private static string StripColors(string s)
		{
			if (string.IsNullOrEmpty(s))
			{
				return s;
			}
			while (true)
			{
				int num = s.IndexOf("<color=", StringComparison.OrdinalIgnoreCase);
				if (num < 0)
				{
					break;
				}
				int num2 = s.IndexOf(">", num, StringComparison.Ordinal);
				if (num2 < 0)
				{
					break;
				}
				s = s.Remove(num, num2 - num + 1);
			}
			return s.Replace("</color>", "");
		}

		private static string Normalize(string type)
		{
			if (string.IsNullOrEmpty(type))
			{
				return "";
			}
			string text = type.Trim().ToLowerInvariant();
			if (text.StartsWith("blood of the "))
			{
				text = text.Substring(13);
			}
			if (text.StartsWith("blood type"))
			{
				text = text.Substring(10).Trim().TrimStart(':', ' ');
			}
			if (text == "frailed")
			{
				text = "frail";
			}
			return text;
		}

		private static string MatchType(string blob)
		{
			string[] array = new string[13]
			{
				"Blood of the Immortal", "Immortal", "Draculin", "Corrupted", "Creature", "Worker", "Brute", "Rogue", "Warrior", "Scholar",
				"Mutant", "Frailed", "Frail"
			};
			int num = IndexOfIgnore(blob, "Blood Type:");
			if (num >= 0)
			{
				int num2 = num + "Blood Type:".Length;
				int i;
				for (i = num2; i < blob.Length && blob[i] != '\n' && blob[i] != '\r'; i++)
				{
				}
				string s = blob.Substring(num2, i - num2).Trim();
				s = StripTags(s);
				int num3 = s.IndexOf('/');
				if (num3 > 0)
				{
					s = s.Substring(0, num3).Trim();
				}
				string text = MatchType(s);
				if (text != null)
				{
					return text;
				}
				if (s.Length > 0)
				{
					return s;
				}
			}
			string[] array2 = array;
			foreach (string text2 in array2)
			{
				if (IndexOfIgnore(blob, text2) >= 0)
				{
					return text2;
				}
			}
			return null;
		}

		private static float MatchQuality(string blob)
		{
			int num = IndexOfIgnore(blob, "Blood Quality:");
			if (num >= 0)
			{
				int i = num + "Blood Quality:".Length;
				i = SkipSpacesAndTags(blob, i);
				float num2 = ReadNumber(blob, i);
				if (num2 > 0f)
				{
					return num2;
				}
			}
			int num3 = -1;
			float result = 0f;
			for (int j = 0; j < blob.Length; j++)
			{
				if (blob[j] == '%')
				{
					int num4 = j - 1;
					while (num4 >= 0 && (char.IsDigit(blob[num4]) || blob[num4] == '.' || blob[num4] == ' '))
					{
						num4--;
					}
					float num5 = ReadNumber(blob, num4 + 1);
					if (!(num5 <= 0f) && !(num5 > 100f) && j > num3)
					{
						num3 = j;
						result = num5;
					}
				}
			}
			return result;
		}

		private static int SkipSpacesAndTags(string s, int i)
		{
			while (i < s.Length)
			{
				switch (s[i])
				{
				case '\t':
				case ' ':
				case ':':
					i++;
					continue;
				case '<':
				{
					int num = s.IndexOf('>', i);
					if (num >= 0)
					{
						i = num + 1;
						continue;
					}
					break;
				}
				}
				break;
			}
			return i;
		}

		private static string StripTags(string s)
		{
			if (string.IsNullOrEmpty(s) || s.IndexOf('<') < 0)
			{
				return s;
			}
			StringBuilder stringBuilder = new StringBuilder(s.Length);
			bool flag = false;
			foreach (char c in s)
			{
				switch (c)
				{
				case '<':
					flag = true;
					continue;
				case '>':
					flag = false;
					continue;
				}
				if (!flag)
				{
					stringBuilder.Append(c);
				}
			}
			return stringBuilder.ToString().Trim();
		}

		private static float ReadNumber(string s, int i)
		{
			while (i < s.Length && (s[i] == ' ' || s[i] == '\t' || s[i] == ':'))
			{
				i++;
			}
			int num = i;
			bool flag = false;
			while (i < s.Length && (char.IsDigit(s[i]) || (s[i] == '.' && !flag)))
			{
				if (s[i] == '.')
				{
					flag = true;
				}
				i++;
			}
			if (i == num)
			{
				return 0f;
			}
			if (float.TryParse(s.Substring(num, i - num), NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
			{
				return result;
			}
			return 0f;
		}

		private static int IndexOfIgnore(string hay, string needle)
		{
			return hay.IndexOf(needle, StringComparison.OrdinalIgnoreCase);
		}
	}
	[HarmonyPatch(typeof(GridSelectionEntry), "OnPointerEnter")]
	internal static class ItemGridPointerEnterPatch
	{
		[HarmonyPostfix]
		private static void Postfix(GridSelectionEntry __instance)
		{
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if ((Object)(object)__instance == (Object)null || ((Il2CppObjectBase)__instance).WasCollected)
				{
					return;
				}
				ItemGridSelectionEntry val = ((Il2CppObjectBase)__instance).TryCast<ItemGridSelectionEntry>();
				if ((Object)(object)val == (Object)null || ((Il2CppObjectBase)val).WasCollected)
				{
					ThresholdAppender.CancelIfNotPotion("non-item-grid enter");
					return;
				}
				Data slotData = val.SlotData;
				if (slotData == null || slotData.IsEmpty)
				{
					ThresholdAppender.CancelIfNotPotion("empty-slot enter");
					return;
				}
				int value = slotData.EntryId._Value;
				if (!PotionGuids.IsBloodPotion(value))
				{
					ThresholdAppender.CancelIfNotPotion("non-potion enter guid=" + value);
				}
				else
				{
					ThresholdAppender.Request(((Il2CppObjectBase)val).Pointer, value, "Grid.OnPointerEnter");
				}
			}
			catch (Exception ex)
			{
				ManualLogSource logger = Plugin.Logger;
				if (logger != null)
				{
					logger.LogDebug((object)("PotionPool OnPointerEnter postfix: " + ex.Message));
				}
			}
		}
	}
	[HarmonyPatch(typeof(GridSelectionEntry), "OnPointerExit")]
	internal static class ItemGridPointerExitPatch
	{
		[HarmonyPostfix]
		private static void Postfix(GridSelectionEntry __instance)
		{
			try
			{
				if (!((Object)(object)__instance == (Object)null) && !((Il2CppObjectBase)__instance).WasCollected)
				{
					ItemGridSelectionEntry val = ((Il2CppObjectBase)__instance).TryCast<ItemGridSelectionEntry>();
					if (!((Object)(object)val == (Object)null) && !((Il2CppObjectBase)val).WasCollected)
					{
						ThresholdAppender.NotifyPointerExit(((Il2CppObjectBase)val).Pointer);
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource logger = Plugin.Logger;
				if (logger != null)
				{
					logger.LogDebug((object)("PotionPool OnPointerExit postfix: " + ex.Message));
				}
			}
		}
	}
	[HarmonyPatch(typeof(ActionBarEntry), "OnPointerEnter")]
	internal static class ActionBarPointerEnterPatch
	{
		[HarmonyPostfix]
		private static void Postfix(ActionBarEntry __instance)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if ((Object)(object)__instance == (Object)null || ((Il2CppObjectBase)__instance).WasCollected)
				{
					return;
				}
				int num = 0;
				try
				{
					num = __instance.EntryId._Value;
				}
				catch
				{
				}
				if (num == 0)
				{
					try
					{
						num = __instance._CurrentItemType._Value;
					}
					catch
					{
					}
				}
				if (!PotionGuids.IsBloodPotion(num))
				{
					ThresholdAppender.CancelIfNotPotion("non-potion actionbar guid=" + num);
				}
				else
				{
					ThresholdAppender.Request(((Il2CppObjectBase)__instance).Pointer, num, "ActionBar.OnPointerEnter");
				}
			}
			catch (Exception ex)
			{
				ManualLogSource logger = Plugin.Logger;
				if (logger != null)
				{
					logger.LogDebug((object)("PotionPool ActionBar OnPointerEnter: " + ex.Message));
				}
			}
		}
	}
	[HarmonyPatch(typeof(ActionBarEntry), "OnPointerExit")]
	internal static class ActionBarPointerExitPatch
	{
		[HarmonyPostfix]
		private static void Postfix(ActionBarEntry __instance)
		{
			try
			{
				if (!((Object)(object)__instance == (Object)null) && !((Il2CppObjectBase)__instance).WasCollected)
				{
					ThresholdAppender.NotifyPointerExit(((Il2CppObjectBase)__instance).Pointer);
				}
			}
			catch (Exception ex)
			{
				ManualLogSource logger = Plugin.Logger;
				if (logger != null)
				{
					logger.LogDebug((object)("PotionPool ActionBar OnPointerExit: " + ex.Message));
				}
			}
		}
	}
	[HarmonyPatch(typeof(LocalizedText), "LateUpdate")]
	internal static class LocalizedTextLateUpdatePatch
	{
		[HarmonyPrefix]
		private static bool Prefix(LocalizedText __instance)
		{
			try
			{
				return !ThresholdAppender.ShouldStopBinder(__instance);
			}
			catch
			{
				return true;
			}
		}

		[HarmonyPostfix]
		private static void Postfix(LocalizedText __instance)
		{
			try
			{
				ThresholdAppender.NotifyBinderTick(__instance);
			}
			catch (Exception ex)
			{
				ManualLogSource logger = Plugin.Logger;
				if (logger != null)
				{
					logger.LogDebug((object)("PotionPool LocalizedText LateUpdate: " + ex.Message));
				}
			}
		}
	}
	[BepInPlugin("fangly.PotionPool", "PotionPool", "1.0.0")]
	[BepInProcess("VRising.exe")]
	public class Plugin : BasePlugin
	{
		internal const string GUID = "fangly.PotionPool";

		internal const string NAME = "PotionPool";

		internal const string VERSION = "1.0.0";

		private Harmony _harmony;

		private ThresholdAppender _appender;

		internal static Plugin Instance { get; private set; }

		internal static ManualLogSource Logger { get; private set; }

		public override void Load()
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Expected O, but got Unknown
			Instance = this;
			Logger = ((BasePlugin)this).Log;
			if (Application.productName == "VRisingServer")
			{
				((BasePlugin)this).Log.LogInfo((object)"PotionPool is a client-only plugin; not loading on VRisingServer.");
				return;
			}
			ClassInjector.RegisterTypeInIl2Cpp<ThresholdAppender>();
			_appender = ((BasePlugin)this).AddComponent<ThresholdAppender>();
			_harmony = new Harmony("fangly.PotionPool");
			_harmony.PatchAll(typeof(ItemGridPointerEnterPatch));
			_harmony.PatchAll(typeof(ItemGridPointerExitPatch));
			_harmony.PatchAll(typeof(ActionBarPointerEnterPatch));
			_harmony.PatchAll(typeof(ActionBarPointerExitPatch));
			_harmony.PatchAll(typeof(LocalizedTextLateUpdatePatch));
			((BasePlugin)this).Log.LogInfo((object)"PotionPool 1.0.0 loaded (client). Inventory GridSelectionEntry + hotbar ActionBarEntry. Potion hover shows Blood Pool I-V bonus lines. FakeTooltip is NOT Harmony-patched.");
		}

		public override bool Unload()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			if ((Object)(object)_appender != (Object)null)
			{
				Object.Destroy((Object)(object)_appender);
				_appender = null;
			}
			return true;
		}
	}
	internal static class PluginInfo
	{
		public const string GUID = "fangly.PotionPool";

		public const string Name = "PotionPool";

		public const string Version = "1.0.0";
	}
	internal static class PotionGuids
	{
		internal const int PrisonPotion = 828432508;

		internal const int PrisonPotionBloodwine = 1223264867;

		internal const int PrisonPotionMixed = 2063723255;

		private static readonly HashSet<int> Hashes = new HashSet<int> { 828432508, 1223264867, 2063723255 };

		internal static bool IsBloodPotion(int guidHash)
		{
			if (guidHash != 0)
			{
				return Hashes.Contains(guidHash);
			}
			return false;
		}
	}
	internal static class Preview
	{
		internal const string Marker = "\n<size=95%><line-height=110%><noparse></noparse>";

		internal const string OldMarker80 = "\n<size=80%><noparse></noparse>";

		internal const string OldMarker90 = "\n\n<size=90%><line-height=108%><noparse></noparse>";

		internal const string VisibleAnchor = "I 0%";

		internal const string BonusAnchor = "All bonuses above increased";

		internal const string OldBonusAnchor = "Boost all above effects";

		internal static bool HasMarker(string text)
		{
			if (string.IsNullOrEmpty(text))
			{
				return false;
			}
			if (text.IndexOf("\n<size=95%><line-height=110%><noparse></noparse>", StringComparison.Ordinal) >= 0)
			{
				return true;
			}
			if (text.IndexOf("All bonuses above increased", StringComparison.Ordinal) >= 0)
			{
				return true;
			}
			if (text.IndexOf("Boost all above effects", StringComparison.Ordinal) >= 0)
			{
				return true;
			}
			return text.IndexOf("I 0%", StringComparison.Ordinal) >= 0;
		}

		internal static string Append(string existing, string type, float quality)
		{
			string text = BloodBonuses.Build(type, quality);
			if (string.IsNullOrEmpty(text))
			{
				return Strip(existing);
			}
			string text2 = Strip(existing).TrimEnd();
			if (text2.Length > 0 && text2.IndexOf("<i>", StringComparison.OrdinalIgnoreCase) < 0)
			{
				text2 = "<i>" + text2 + "</i>";
			}
			return text2 + "\n<size=95%><line-height=110%><noparse></noparse>" + text + "</line-height></size>";
		}

		internal static string Strip(string text)
		{
			if (string.IsNullOrEmpty(text))
			{
				return "";
			}
			int num = text.IndexOf("\n<size=95%><line-height=110%><noparse></noparse>", StringComparison.Ordinal);
			if (num < 0)
			{
				num = text.IndexOf("\n\n<size=90%><line-height=108%><noparse></noparse>", StringComparison.Ordinal);
			}
			if (num < 0)
			{
				num = text.IndexOf("\n<size=80%><noparse></noparse>", StringComparison.Ordinal);
			}
			if (num < 0)
			{
				num = text.IndexOf("\nI 0%", StringComparison.Ordinal);
			}
			if (num < 0)
			{
				num = text.IndexOf("\nI  ", StringComparison.Ordinal);
			}
			if (num < 0)
			{
				num = text.IndexOf("I 0%", StringComparison.Ordinal);
			}
			if (num >= 0)
			{
				return text.Substring(0, num);
			}
			return text;
		}
	}
	public class ThresholdAppender : MonoBehaviour
	{
		private const int MaxWatchFrames = 3600;

		private const int TooltipGoneFrames = 12;

		private static bool _pending;

		private static int _frames;

		private static int _tooltipGoneFrames;

		private static int _appendsThisHover;

		private static int _rebuildsThisHover;

		private static bool _loggedStart;

		private static bool _loggedApply;

		private static bool _loggedRebuild;

		private static bool _loggedFail;

		private static bool _loggedBinder;

		private static bool _hadMarkerLast;

		private static int _guid;

		private static string _source;

		private static string _fieldName;

		private static FakeTooltip _cached;

		private static IntPtr _hoverPtr;

		private static LocalizedText _appliedLoc;

		private static TextMeshProUGUI _appliedTmp;

		private static bool _binderStopped;

		private static bool _locWasEnabled;

		private static bool _clippersHeld;

		private static string _bloodType;

		private static float _bloodQuality;

		private static bool _loggedMeta;

		private static string _lastBlock;

		private static readonly List<Behaviour> Clippers = new List<Behaviour>(8);

		private static readonly List<bool> ClipperWasEnabled = new List<bool>(8);

		private UnityAction _beforeRender;

		private WillRenderCanvases _preWillRender;

		private WillRenderCanvases _willRender;

		private static int _pollFrames;

		private static bool _loggedPoll;

		private static FakeTooltip[] _pollCache;

		private static float _pollCacheAt = -100f;

		private static CanvasGroup _raycastGroup;

		private static bool _raycastGroupAdded;

		private static bool _raycastWasBlocking;

		private static bool _loggedRaycast;

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

		internal static void Request(IntPtr hoverPtr, int guid, string source)
		{
			if (!_pending || !(hoverPtr != IntPtr.Zero) || !(_hoverPtr == hoverPtr) || _guid != guid)
			{
				ResetHoverState();
			}
			_pending = true;
			_frames = 0;
			_tooltipGoneFrames = 0;
			_hoverPtr = hoverPtr;
			_guid = guid;
			_source = source;
			_cached = null;
			if (!_loggedStart)
			{
				_loggedStart = true;
				ManualLogSource logger = Plugin.Logger;
				if (logger != null)
				{
					logger.LogInfo((object)("PotionPool 1.0.0 hover start guid=" + guid + " source=" + source));
				}
			}
		}

		internal static void NotifyPointerExit(IntPtr hoverPtr)
		{
			if (_pending && !(hoverPtr == IntPtr.Zero) && !(_hoverPtr != hoverPtr))
			{
				StopAndStrip("OnPointerExit");
			}
		}

		internal static void CancelIfNotPotion(string why)
		{
			if (_pending)
			{
				StopAndStrip(why);
			}
		}

		internal static bool ShouldStopBinder(LocalizedText loc)
		{
			if (!_pending || !_binderStopped || (Object)(object)loc == (Object)null)
			{
				return false;
			}
			if ((Object)(object)_appliedLoc == (Object)null || ((Il2CppObjectBase)_appliedLoc).WasCollected)
			{
				return false;
			}
			return ((Il2CppObjectBase)loc).Pointer == ((Il2CppObjectBase)_appliedLoc).Pointer;
		}

		internal static void NotifyBinderTick(LocalizedText loc)
		{
			if (_pending && !((Object)(object)loc == (Object)null) && !((Object)(object)_appliedLoc == (Object)null) && !((Il2CppObjectBase)_appliedLoc).WasCollected && !(((Il2CppObjectBase)loc).Pointer != ((Il2CppObjectBase)_appliedLoc).Pointer))
			{
				Tick("LocalizedText.LateUpdate");
			}
		}

		private static void ResetHoverState()
		{
			try
			{
				StripApplied();
			}
			catch
			{
			}
			RestoreBinderAndClippers();
			_appendsThisHover = 0;
			_rebuildsThisHover = 0;
			_loggedStart = false;
			_loggedApply = false;
			_loggedRebuild = false;
			_loggedFail = false;
			_loggedBinder = false;
			_loggedMeta = false;
			_hadMarkerLast = false;
			_bloodType = null;
			_bloodQuality = 0f;
			_lastBlock = null;
			_fieldName = null;
			_appliedLoc = null;
			_appliedTmp = null;
			_binderStopped = false;
			_locWasEnabled = false;
			_clippersHeld = false;
		}

		private static void StopAndStrip(string why)
		{
			try
			{
				bool flag = StripApplied();
				ManualLogSource logger = Plugin.Logger;
				if (logger != null)
				{
					logger.LogInfo((object)("PotionPool 1.0.0 hover stop guid=" + _guid + " why=" + why + " stripped=" + flag + " appends=" + _appendsThisHover + " rebuilt=" + _rebuildsThisHover + " binderStopped=" + _binderStopped));
				}
			}
			catch (Exception ex)
			{
				ManualLogSource logger2 = Plugin.Logger;
				if (logger2 != null)
				{
					logger2.LogDebug((object)("PotionPool stop: " + ex.Message));
				}
			}
			finally
			{
				RestoreBinderAndClippers();
				_pending = false;
				_hoverPtr = IntPtr.Zero;
				_cached = null;
				_appliedLoc = null;
				_appliedTmp = null;
				ResetHoverState();
			}
		}

		private void OnEnable()
		{
			try
			{
				_beforeRender = UnityAction.op_Implicit((Action)OnBeforeRender);
				Application.onBeforeRender += _beforeRender;
			}
			catch (Exception ex)
			{
				ManualLogSource logger = Plugin.Logger;
				if (logger != null)
				{
					logger.LogDebug((object)("PotionPool onBeforeRender subscribe: " + ex.Message));
				}
			}
			try
			{
				Action action = OnPreWillRenderCanvases;
				_preWillRender = WillRenderCanvases.op_Implicit(action);
				Canvas.preWillRenderCanvases += _preWillRender;
			}
			catch (Exception ex2)
			{
				ManualLogSource logger2 = Plugin.Logger;
				if (logger2 != null)
				{
					logger2.LogDebug((object)("PotionPool preWillRenderCanvases subscribe: " + ex2.Message));
				}
			}
			try
			{
				Action action2 = OnWillRenderCanvases;
				_willRender = WillRenderCanvases.op_Implicit(action2);
				Canvas.willRenderCanvases += _willRender;
			}
			catch (Exception ex3)
			{
				ManualLogSource logger3 = Plugin.Logger;
				if (logger3 != null)
				{
					logger3.LogDebug((object)("PotionPool willRenderCanvases subscribe: " + ex3.Message));
				}
			}
		}

		private void OnDisable()
		{
			try
			{
				if ((Delegate)(object)_beforeRender != (Delegate)null)
				{
					Application.onBeforeRender -= _beforeRender;
				}
			}
			catch
			{
			}
			try
			{
				if ((Delegate)(object)_preWillRender != (Delegate)null)
				{
					Canvas.preWillRenderCanvases -= _preWillRender;
				}
			}
			catch
			{
			}
			try
			{
				if ((Delegate)(object)_willRender != (Delegate)null)
				{
					Canvas.willRenderCanvases -= _willRender;
				}
			}
			catch
			{
			}
			if (_pending)
			{
				StopAndStrip("appender-disable");
			}
		}

		private void LateUpdate()
		{
			if (!_pending && ++_pollFrames >= 20)
			{
				_pollFrames = 0;
				PollTooltip();
			}
			Tick("LateUpdate");
		}

		private static void PollTooltip()
		{
			try
			{
				float unscaledTime = Time.unscaledTime;
				if (_pollCache == null || unscaledTime - _pollCacheAt > 5f)
				{
					_pollCache = Il2CppArrayBase<FakeTooltip>.op_Implicit(Object.FindObjectsByType<FakeTooltip>((FindObjectsInactive)1, (FindObjectsSortMode)0));
					_pollCacheAt = unscaledTime;
				}
				FakeTooltip[] pollCache = _pollCache;
				if (pollCache == null)
				{
					return;
				}
				FakeTooltip[] array = pollCache;
				foreach (FakeTooltip val in array)
				{
					if ((Object)(object)val == (Object)null || ((Il2CppObjectBase)val).WasCollected || !((Component)val).gameObject.activeInHierarchy)
					{
						continue;
					}
					LocalizedText bloodPotion = val.BloodPotion;
					if ((Object)(object)bloodPotion == (Object)null || ((Il2CppObjectBase)bloodPotion).WasCollected || !((Component)bloodPotion).gameObject.activeInHierarchy)
					{
						continue;
					}
					string value = null;
					try
					{
						value = (((Object)(object)bloodPotion.Text != (Object)null) ? ((TMP_Text)bloodPotion.Text).text : null);
					}
					catch
					{
					}
					if (string.IsNullOrWhiteSpace(value))
					{
						continue;
					}
					if (!_loggedPoll)
					{
						_loggedPoll = true;
						ManualLogSource logger = Plugin.Logger;
						if (logger != null)
						{
							logger.LogInfo((object)"PotionPool 1.0.0 tooltip poll picked up a potion tooltip without a pointer enter.");
						}
					}
					Request(((Il2CppObjectBase)val).Pointer, 0, "tooltip-poll");
					break;
				}
			}
			catch (Exception ex)
			{
				ManualLogSource logger2 = Plugin.Logger;
				if (logger2 != null)
				{
					logger2.LogDebug((object)("PotionPool poll: " + ex.Message));
				}
			}
		}

		private static void OnBeforeRender()
		{
			Tick("onBeforeRender");
		}

		private static void OnPreWillRenderCanvases()
		{
			Tick("preWillRenderCanvases");
		}

		private static void OnWillRenderCanvases()
		{
			Tick("willRenderCanvases");
		}

		private static void Tick(string phase)
		{
			if (!_pending)
			{
				return;
			}
			try
			{
				if (phase == "LateUpdate")
				{
					_frames++;
				}
				if (_frames >= 3600)
				{
					_frames = 0;
				}
				if (!TryGetTarget(out var loc, out var tmp, out var tt, out var field))
				{
					_tooltipGoneFrames++;
					if (_tooltipGoneFrames >= 12)
					{
						StopAndStrip("tooltip-gone");
					}
					else if (!_loggedFail)
					{
						_loggedFail = true;
						ManualLogSource logger = Plugin.Logger;
						if (logger != null)
						{
							logger.LogInfo((object)("PotionPool 1.0.0 apply failed guid=" + _guid + " phase=" + phase + " reason=no-visible-potion-TMP"));
						}
					}
				}
				else
				{
					_tooltipGoneFrames = 0;
					TryAppend(loc, tmp, tt, field, phase);
				}
			}
			catch (Exception ex)
			{
				ManualLogSource logger2 = Plugin.Logger;
				if (logger2 != null)
				{
					logger2.LogDebug((object)("PotionPool I-V tick " + phase + ": " + ex.Message));
				}
			}
		}

		private static void TryAppend(LocalizedText loc, TextMeshProUGUI tmp, FakeTooltip tt, string field, string phase)
		{
			string text = ((TMP_Text)tmp).text;
			if (string.IsNullOrEmpty(text))
			{
				return;
			}
			bool flag = Preview.HasMarker(text);
			if (_hadMarkerLast && !flag)
			{
				_rebuildsThisHover++;
				if (!_loggedRebuild)
				{
					_loggedRebuild = true;
					ManualLogSource logger = Plugin.Logger;
					if (logger != null)
					{
						logger.LogInfo((object)("PotionPool 1.0.0 tooltip rebuilt guid=" + _guid + " field=" + field + " phase=" + phase));
					}
				}
			}
			TryFillBloodMeta(tt, tmp);
			string text2 = Preview.Append(text, _bloodType, _bloodQuality);
			if (!string.Equals(text, text2, StringComparison.Ordinal))
			{
				((TMP_Text)tmp).text = text2;
				_appendsThisHover++;
				_lastBlock = text2;
			}
			HoldLayout(tmp, tt);
			StopBinder(loc);
			HoldClippers(tmp, tt);
			HoldRaycasts(tt);
			_appliedLoc = loc;
			_appliedTmp = tmp;
			_fieldName = field;
			_cached = tt;
			string text3 = ((TMP_Text)tmp).text;
			bool flag2 = (_hadMarkerLast = Preview.HasMarker(text3));
			if (!_loggedApply)
			{
				_loggedApply = true;
				ManualLogSource logger2 = Plugin.Logger;
				if (logger2 != null)
				{
					logger2.LogInfo((object)("PotionPool 1.0.0 applied I-V guid=" + _guid + " field=" + field + " tmpHasIV=" + flag2 + " type=" + (_bloodType ?? "?") + " quality=" + _bloodQuality.ToString("0.##") + " binderStopped=" + _binderStopped + " locEnabled=" + ((Object)(object)loc != (Object)null && !((Il2CppObjectBase)loc).WasCollected && ((Behaviour)loc).enabled) + " rebuilt=" + (_rebuildsThisHover > 0) + " phase=" + phase + " len=" + (text3?.Length ?? 0)));
				}
			}
			else if (!flag2 && !_loggedFail)
			{
				_loggedFail = true;
				ManualLogSource logger3 = Plugin.Logger;
				if (logger3 != null)
				{
					logger3.LogInfo((object)("PotionPool 1.0.0 apply failed guid=" + _guid + " field=" + field + " tmpHasIV=false phase=" + phase));
				}
			}
		}

		private static void StopBinder(LocalizedText loc)
		{
			if ((Object)(object)loc == (Object)null || ((Il2CppObjectBase)loc).WasCollected)
			{
				return;
			}
			loc._IsForceSet = true;
			loc._TextHasBeenModified = true;
			loc._HasTextBeenSet = true;
			loc.SetRectSizeToTextSize = true;
			if (_binderStopped && (Object)(object)_appliedLoc != (Object)null && !((Il2CppObjectBase)_appliedLoc).WasCollected && ((Il2CppObjectBase)_appliedLoc).Pointer == ((Il2CppObjectBase)loc).Pointer)
			{
				return;
			}
			if (_binderStopped)
			{
				RestoreBinderAndClippers();
			}
			_locWasEnabled = ((Behaviour)loc).enabled;
			_appliedLoc = loc;
			_binderStopped = true;
			try
			{
				if (((Behaviour)loc).enabled)
				{
					((Behaviour)loc).enabled = false;
				}
			}
			catch (Exception ex)
			{
				ManualLogSource logger = Plugin.Logger;
				if (logger != null)
				{
					logger.LogDebug((object)("PotionPool disable LocalizedText: " + ex.Message));
				}
			}
			if (!_loggedBinder)
			{
				_loggedBinder = true;
				bool flag = false;
				try
				{
					flag = ((Behaviour)loc).enabled;
				}
				catch
				{
				}
				ManualLogSource logger2 = Plugin.Logger;
				if (logger2 != null)
				{
					logger2.LogInfo((object)("PotionPool 1.0.0 binder stopped guid=" + _guid + " locEnabled=" + flag));
				}
			}
		}

		private static void TryFillBloodMeta(FakeTooltip tt, TextMeshProUGUI written)
		{
			if (_bloodType != null && _bloodQuality > 0f)
			{
				return;
			}
			StringBuilder blob = new StringBuilder(256);
			try
			{
				if ((Object)(object)written != (Object)null && !((Il2CppObjectBase)written).WasCollected)
				{
					string text = ((TMP_Text)written).text;
					if (!string.IsNullOrEmpty(text))
					{
						blob.Append('\n').Append(text);
					}
				}
			}
			catch
			{
			}
			if ((Object)(object)tt != (Object)null && !((Il2CppObjectBase)tt).WasCollected)
			{
				Add(tt.BloodPotion);
				Add(tt.Description);
				Add(tt.SubText);
				Add(tt.PreSubText);
				try
				{
					Il2CppArrayBase<LocalizedText> componentsInChildren = ((Component)tt).GetComponentsInChildren<LocalizedText>(true);
					if (componentsInChildren != null)
					{
						for (int i = 0; i < componentsInChildren.Length; i++)
						{
							Add(componentsInChildren[i]);
						}
					}
				}
				catch
				{
				}
			}
			if (!BloodBonuses.TryParse(blob.ToString(), out var type, out var quality))
			{
				return;
			}
			_bloodType = type;
			_bloodQuality = quality;
			if (!_loggedMeta)
			{
				_loggedMeta = true;
				ManualLogSource logger = Plugin.Logger;
				if (logger != null)
				{
					logger.LogInfo((object)("PotionPool 1.0.0 parsed guid=" + _guid + " type=" + type + " quality=" + quality.ToString("0.##")));
				}
			}
			void Add(LocalizedText loc)
			{
				if (!TryReadLoc(loc, out var _, out var tmp))
				{
					return;
				}
				try
				{
					string text2 = ((TMP_Text)tmp).text;
					if (!string.IsNullOrEmpty(text2))
					{
						blob.Append('\n').Append(text2);
					}
				}
				catch
				{
				}
			}
		}

		private static void HoldLayout(TextMeshProUGUI tmp, FakeTooltip tt)
		{
			try
			{
				((TMP_Text)tmp).overflowMode = (TextOverflowModes)0;
				((TMP_Text)tmp).enableWordWrapping = true;
				((TMP_Text)tmp).maxVisibleLines = 32;
				((TMP_Text)tmp).maxVisibleCharacters = 99999;
				((TMP_Text)tmp).ForceMeshUpdate(true, true);
			}
			catch
			{
			}
			float num = 0f;
			try
			{
				num = ((TMP_Text)tmp).preferredHeight;
			}
			catch
			{
			}
			try
			{
				Grow(((TMP_Text)tmp).rectTransform, num);
				SetMinHeight(((Component)tmp).gameObject, num);
				GameObject val = (((Object)(object)tt != (Object)null) ? tt.DescriptionFrame : null);
				if ((Object)(object)val != (Object)null && !((Il2CppObjectBase)val).WasCollected)
				{
					Transform transform = val.transform;
					RectTransform val2 = (RectTransform)(object)((transform is RectTransform) ? transform : null);
					if ((Object)(object)val2 != (Object)null)
					{
						Grow(val2, num + 16f);
					}
					SetMinHeight(val, num + 16f);
					Transform transform2 = val.transform;
					LayoutRebuilder.ForceRebuildLayoutImmediate((RectTransform)(object)((transform2 is RectTransform) ? transform2 : null));
					if ((Object)(object)val2 != (Object)null)
					{
						Grow(val2, num + 16f);
					}
				}
				Grow(((TMP_Text)tmp).rectTransform, num);
				if ((Object)(object)_appliedLoc != (Object)null && !((Il2CppObjectBase)_appliedLoc).WasCollected)
				{
					Transform transform3 = ((Component)_appliedLoc).transform;
					RectTransform val3 = (RectTransform)(object)((transform3 is RectTransform) ? transform3 : null);
					if ((Object)(object)val3 != (Object)null)
					{
						LayoutRebuilder.ForceRebuildLayoutImmediate(val3);
					}
				}
				else if ((Object)(object)((TMP_Text)tmp).rectTransform != (Object)null)
				{
					LayoutRebuilder.ForceRebuildLayoutImmediate(((TMP_Text)tmp).rectTransform);
				}
			}
			catch
			{
			}
		}

		private static void HoldClippers(TextMeshProUGUI tmp, FakeTooltip tt)
		{
			if (_clippersHeld || (Object)(object)tmp == (Object)null || ((Il2CppObjectBase)tmp).WasCollected)
			{
				return;
			}
			try
			{
				Transform val = null;
				try
				{
					GameObject val2 = (((Object)(object)tt != (Object)null) ? tt.DescriptionFrame : null);
					if ((Object)(object)val2 != (Object)null && !((Il2CppObjectBase)val2).WasCollected)
					{
						val = val2.transform;
					}
				}
				catch
				{
				}
				Transform val3 = ((TMP_Text)tmp).transform;
				while ((Object)(object)val3 != (Object)null)
				{
					CaptureClipper((Behaviour)(object)((Component)val3).GetComponent<RectMask2D>());
					CaptureClipper((Behaviour)(object)((Component)val3).GetComponent<Mask>());
					if ((Object)(object)val != (Object)null && (Object)(object)val3 == (Object)(object)val)
					{
						break;
					}
					val3 = val3.parent;
				}
				_clippersHeld = true;
			}
			catch (Exception ex)
			{
				ManualLogSource logger = Plugin.Logger;
				if (logger != null)
				{
					logger.LogDebug((object)("PotionPool unclip: " + ex.Message));
				}
			}
		}

		private static void HoldRaycasts(FakeTooltip tt)
		{
			if ((Object)(object)_raycastGroup != (Object)null || (Object)(object)tt == (Object)null)
			{
				return;
			}
			try
			{
				if (((Il2CppObjectBase)tt).WasCollected)
				{
					return;
				}
				GameObject gameObject = ((Component)tt).gameObject;
				CanvasGroup val = gameObject.GetComponent<CanvasGroup>();
				if ((Object)(object)val == (Object)null)
				{
					val = gameObject.AddComponent<CanvasGroup>();
					_raycastGroupAdded = true;
					_raycastWasBlocking = true;
				}
				else
				{
					_raycastGroupAdded = false;
					_raycastWasBlocking = val.blocksRaycasts;
				}
				val.blocksRaycasts = false;
				_raycastGroup = val;
				if (!_loggedRaycast)
				{
					_loggedRaycast = true;
					ManualLogSource logger = Plugin.Logger;
					if (logger != null)
					{
						logger.LogInfo((object)("PotionPool 1.0.0 tooltip raycasts off (group " + (_raycastGroupAdded ? "added" : "existing") + ")."));
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource logger2 = Plugin.Logger;
				if (logger2 != null)
				{
					logger2.LogDebug((object)("PotionPool raycast hold: " + ex.Message));
				}
			}
		}

		private static void RestoreRaycasts()
		{
			try
			{
				if ((Object)(object)_raycastGroup != (Object)null && !((Il2CppObjectBase)_raycastGroup).WasCollected)
				{
					if (_raycastGroupAdded)
					{
						Object.Destroy((Object)(object)_raycastGroup);
					}
					else
					{
						_raycastGroup.blocksRaycasts = _raycastWasBlocking;
					}
				}
			}
			catch
			{
			}
			_raycastGroup = null;
			_raycastGroupAdded = false;
		}

		private static void CaptureClipper(Behaviour clipper)
		{
			if ((Object)(object)clipper == (Object)null)
			{
				return;
			}
			try
			{
				if (((Il2CppObjectBase)clipper).WasCollected)
				{
					return;
				}
			}
			catch
			{
				return;
			}
			Clippers.Add(clipper);
			bool flag = false;
			try
			{
				flag = clipper.enabled;
			}
			catch
			{
			}
			ClipperWasEnabled.Add(flag);
			try
			{
				if (flag)
				{
					clipper.enabled = false;
				}
			}
			catch
			{
			}
		}

		private static void RestoreBinderAndClippers()
		{
			try
			{
				if ((Object)(object)_appliedLoc != (Object)null && !((Il2CppObjectBase)_appliedLoc).WasCollected)
				{
					try
					{
						((Behaviour)_appliedLoc).enabled = _locWasEnabled || !_binderStopped;
					}
					catch
					{
					}
					try
					{
						_appliedLoc._IsForceSet = false;
						_appliedLoc._TextHasBeenModified = false;
					}
					catch
					{
					}
				}
			}
			catch
			{
			}
			for (int i = 0; i < Clippers.Count; i++)
			{
				try
				{
					Behaviour val = Clippers[i];
					if ((Object)(object)val == (Object)null)
					{
						continue;
					}
					try
					{
						if (((Il2CppObjectBase)val).WasCollected)
						{
							continue;
						}
					}
					catch
					{
						goto end_IL_0060;
					}
					val.enabled = i < ClipperWasEnabled.Count && ClipperWasEnabled[i];
					end_IL_0060:;
				}
				catch
				{
				}
			}
			Clippers.Clear();
			ClipperWasEnabled.Clear();
			_binderStopped = false;
			_clippersHeld = false;
			_locWasEnabled = false;
			RestoreRaycasts();
		}

		private static void Grow(RectTransform rt, float minHeight)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: 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)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)rt == (Object)null) && !(minHeight <= 0f))
			{
				Vector2 sizeDelta = rt.sizeDelta;
				if (sizeDelta.y < minHeight)
				{
					rt.sizeDelta = new Vector2(sizeDelta.x, minHeight);
				}
			}
		}

		private static void SetMinHeight(GameObject go, float minHeight)
		{
			if ((Object)(object)go == (Object)null || minHeight <= 0f)
			{
				return;
			}
			try
			{
				LayoutElement component = go.GetComponent<LayoutElement>();
				if (!((Object)(object)component == (Object)null) && !((Il2CppObjectBase)component).WasCollected)
				{
					if (component.minHeight < minHeight)
					{
						component.minHeight = minHeight;
					}
					if (component.preferredHeight < minHeight)
					{
						component.preferredHeight = minHeight;
					}
				}
			}
			catch
			{
			}
		}

		private static bool StripApplied()
		{
			bool result = false;
			try
			{
				if ((Object)(object)_appliedTmp != (Object)null && !((Il2CppObjectBase)_appliedTmp).WasCollected)
				{
					string text = ((TMP_Text)_appliedTmp).text;
					if (Preview.HasMarker(text))
					{
						((TMP_Text)_appliedTmp).text = Preview.Strip(text);
						result = true;
					}
				}
			}
			catch
			{
			}
			try
			{
				if ((Object)(object)_cached != (Object)null && !((Il2CppObjectBase)_cached).WasCollected)
				{
					if (StripIfMarked(_cached.Description))
					{
						result = true;
					}
					FakeTooltip tooltipPrefab = _cached.TooltipPrefab;
					if ((Object)(object)tooltipPrefab != (Object)null && !((Il2CppObjectBase)tooltipPrefab).WasCollected && ((Il2CppObjectBase)tooltipPrefab).Pointer != ((Il2CppObjectBase)_cached).Pointer && StripIfMarked(tooltipPrefab.Description))
					{
						result = true;
					}
				}
			}
			catch
			{
			}
			try
			{
				if ((Object)(object)_cached != (Object)null && !((Il2CppObjectBase)_cached).WasCollected)
				{
					StripIfMarked(_cached.BloodPotion);
				}
			}
			catch
			{
			}
			return result;
		}

		private static bool StripIfMarked(LocalizedText loc)
		{
			if ((Object)(object)loc == (Object)null || ((Il2CppObjectBase)loc).WasCollected)
			{
				return false;
			}
			TextMeshProUGUI text = loc.Text;
			if ((Object)(object)text == (Object)null || ((Il2CppObjectBase)text).WasCollected)
			{
				return false;
			}
			string text2 = ((TMP_Text)text).text;
			if (!Preview.HasMarker(text2))
			{
				return false;
			}
			((TMP_Text)text).text = Preview.Strip(text2);
			try
			{
				loc._IsForceSet = false;
				loc._TextHasBeenModified = false;
			}
			catch
			{
			}
			return true;
		}

		private static bool TryGetTarget(out LocalizedText loc, out TextMeshProUGUI tmp, out FakeTooltip tt, out string field)
		{
			loc = null;
			tmp = null;
			tt = null;
			field = null;
			if (TryPickFrom(_cached, out loc, out tmp, out field))
			{
				tt = _cached;
				return true;
			}
			_cached = null;
			Il2CppArrayBase<FakeTooltip> val = Object.FindObjectsByType<FakeTooltip>((FindObjectsInactive)0, (FindObjectsSortMode)0);
			if (val == null || val.Length == 0)
			{
				return false;
			}
			FakeTooltip val2 = null;
			int num = int.MinValue;
			LocalizedText val3 = null;
			TextMeshProUGUI val4 = null;
			string text = null;
			for (int i = 0; i < val.Length; i++)
			{
				FakeTooltip val5 = val[i];
				if ((Object)(object)val5 == (Object)null || ((Il2CppObjectBase)val5).WasCollected || !((Behaviour)val5).isActiveAndEnabled)
				{
					continue;
				}
				try
				{
					if (!((Component)val5).gameObject.activeInHierarchy)
					{
						continue;
					}
				}
				catch
				{
					continue;
				}
				if (!TryPickFrom(val5, out var loc2, out var tmp2, out var field2))
				{
					continue;
				}
				int num2 = FlavorScore(tmp2, field2);
				try
				{
					num2 += val5.SortingLayerOrder;
				}
				catch
				{
				}
				if (IsNestedPrefab(val5, Il2CppArrayBase<FakeTooltip>.op_Implicit(val)))
				{
					num2 += 300;
				}
				try
				{
					CanvasGroup informationGroup = val5.InformationGroup;
					if ((Object)(object)informationGroup != (Object)null && !((Il2CppObjectBase)informationGroup).WasCollected && informationGroup.alpha <= 0.01f)
					{
						num2 -= 500;
					}
				}
				catch
				{
				}
				if ((Object)(object)val2 == (Object)null || num2 > num)
				{
					val2 = val5;
					num = num2;
					val3 = loc2;
					val4 = tmp2;
					text = field2;
				}
			}
			if ((Object)(object)val2 == (Object)null)
			{
				return false;
			}
			_cached = val2;
			tt = val2;
			loc = val3;
			tmp = val4;
			field = text;
			return true;
		}

		private static int FlavorScore(TextMeshProUGUI tmp, string field)
		{
			int num = 0;
			if (field == "Description")
			{
				num += 80;
			}
			if (field == "BloodPotion")
			{
				num += 20;
			}
			if (field == "Child")
			{
				num += 60;
			}
			string text = null;
			try
			{
				text = (((Object)(object)tmp != (Object)null) ? ((TMP_Text)tmp).text : null);
			}
			catch
			{
			}
			if (string.IsNullOrEmpty(text))
			{
				return num;
			}
			if (Preview.HasMarker(text))
			{
				num += 40;
			}
			if (text.IndexOf("potion", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				num += 80;
			}
			if (text.Length > 24)
			{
				num += 10;
			}
			return num;
		}

		private static bool IsNestedPrefab(FakeTooltip candidate, FakeTooltip[] all)
		{
			foreach (FakeTooltip val in all)
			{
				if ((Object)(object)val == (Object)null || ((Il2CppObjectBase)val).WasCollected || (Object)(object)val == (Object)(object)candidate)
				{
					continue;
				}
				try
				{
					FakeTooltip tooltipPrefab = val.TooltipPrefab;
					if ((Object)(object)tooltipPrefab != (Object)null && !((Il2CppObjectBase)tooltipPrefab).WasCollected && ((Il2CppObjectBase)tooltipPrefab).Pointer == ((Il2CppObjectBase)candidate).Pointer)
					{
						return true;
					}
				}
				catch
				{
				}
			}
			return false;
		}

		private static bool TryPickFrom(FakeTooltip tt, out LocalizedText loc, out TextMeshProUGUI tmp, out string field)
		{
			loc = null;
			tmp = null;
			field = null;
			if ((Object)(object)tt == (Object)null || ((Il2CppObjectBase)tt).WasCollected)
			{
				return false;
			}
			if (!((Behaviour)tt).isActiveAndEnabled)
			{
				return false;
			}
			try
			{
				FakeTooltip tooltipPrefab = tt.TooltipPrefab;
				if ((Object)(object)tooltipPrefab != (Object)null && !((Il2CppObjectBase)tooltipPrefab).WasCollected && ((Il2CppObjectBase)tooltipPrefab).Pointer != ((Il2CppObjectBase)tt).Pointer && ((Behaviour)tooltipPrefab).isActiveAndEnabled && TryPickOwn(tooltipPrefab, out loc, out tmp, out field))
				{
					return true;
				}
			}
			catch
			{
			}
			return TryPickOwn(tt, out loc, out tmp, out field);
		}

		private static bool TryPickOwn(FakeTooltip tt, out LocalizedText loc, out TextMeshProUGUI tmp, out string field)
		{
			loc = null;
			tmp = null;
			field = null;
			if ((Object)(object)tt == (Object)null || ((Il2CppObjectBase)tt).WasCollected)
			{
				return false;
			}
			if (TryReadLoc(tt.Description, out loc, out tmp) && FrameAllows(tt.DescriptionFrame))
			{
				field = "Description";
				return true;
			}
			if (TryReadFlavorChild(tt, out loc, out tmp))
			{
				field = "Child";
				return true;
			}
			if (TryReadLoc(tt.BloodPotion, out loc, out tmp))
			{
				field = "BloodPotion";
				return true;
			}
			if (TryReadLoc(tt.Description, out loc, out tmp))
			{
				field = "Description";
				return true;
			}
			if (TryReadLoc(tt.SubText, out loc, out tmp))
			{
				field = "SubText";
				return true;
			}
			return false;
		}

		private static bool TryReadFlavorChild(FakeTooltip tt, out LocalizedText loc, out TextMeshProUGUI tmp)
		{
			loc = null;
			tmp = null;
			LocalizedText val = null;
			try
			{
				val = tt.Description;
			}
			catch
			{
			}
			LocalizedText[] array;
			try
			{
				array = Il2CppArrayBase<LocalizedText>.op_Implicit(((Component)tt).GetComponentsInChildren<LocalizedText>(false));
			}
			catch
			{
				return false;
			}
			if (array == null || array.Length == 0)
			{
				return false;
			}
			LocalizedText val2 = null;
			TextMeshProUGUI val3 = null;
			int num = 0;
			foreach (LocalizedText val4 in array)
			{
				if (!TryReadLoc(val4, out var outLoc, out var tmp2) || ((Object)(object)val != (Object)null && !((Il2CppObjectBase)val).WasCollected && ((Il2CppObjectBase)val4).Pointer == ((Il2CppObjectBase)val).Pointer))
				{
					continue;
				}
				string text = null;
				try
				{
					text = ((TMP_Text)tmp2).text;
				}
				catch
				{
				}
				if (!string.IsNullOrEmpty(text))
				{
					int num2 = 0;
					if (Preview.HasMarker(text))
					{
						num2 += 40;
					}
					if (text.IndexOf("potion", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						num2 += 80;
					}
					if (text.Length > 24)
					{
						num2 += 10;
					}
					if (num2 != 0 && ((Object)(object)val2 == (Object)null || num2 > num))
					{
						val2 = outLoc;
						val3 = tmp2;
						num = num2;
					}
				}
			}
			if ((Object)(object)val2 == (Object)null)
			{
				return false;
			}
			loc = val2;
			tmp = val3;
			return true;
		}

		private static bool FrameAllows(GameObject frame)
		{
			if ((Object)(object)frame == (Object)null || ((Il2CppObjectBase)frame).WasCollected)
			{
				return true;
			}
			try
			{
				return frame.activeInHierarchy;
			}
			catch
			{
				return true;
			}
		}

		private static bool TryReadLoc(LocalizedText loc, out LocalizedText outLoc, out TextMeshProUGUI tmp)
		{
			outLoc = null;
			tmp = null;
			if ((Object)(object)loc == (Object)null || ((Il2CppObjectBase)loc).WasCollected)
			{
				return false;
			}
			try
			{
				if (!((Component)loc).gameObject.activeInHierarchy)
				{
					return false;
				}
			}
			catch
			{
				return false;
			}
			tmp = loc.Text;
			if ((Object)(object)tmp == (Object)null || ((Il2CppObjectBase)tmp).WasCollected)
			{
				return false;
			}
			try
			{
				if (!((Behaviour)tmp).isActiveAndEnabled)
				{
					return false;
				}
				if (!((Component)tmp).gameObject.activeInHierarchy)
				{
					return false;
				}
			}
			catch
			{
				return false;
			}
			outLoc = loc;
			return true;
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "fangly.PotionPool";

		public const string PLUGIN_NAME = "PotionPool";

		public const string PLUGIN_VERSION = "1.0.0";
	}
}