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 +20%, 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 +20%, including the blood effect cap.");
}
private static string Lit(string s)
{
return "" + s + "";
}
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 : ("" + StripColors(body) + ""));
return "" + text + "" + 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 "" + text + Fmt(num2) + (percent ? "%" : "") + "";
}
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("", num, StringComparison.Ordinal);
if (num2 < 0)
{
break;
}
s = s.Remove(num, num2 - num + 1);
}
return s.Replace("", "");
}
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();
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();
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();
_appender = ((BasePlugin)this).AddComponent();
_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 Hashes = new HashSet { 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";
internal const string OldMarker80 = "\n";
internal const string OldMarker90 = "\n\n";
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", 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("", StringComparison.OrdinalIgnoreCase) < 0)
{
text2 = "" + text2 + "";
}
return text2 + "\n" + text + "";
}
internal static string Strip(string text)
{
if (string.IsNullOrEmpty(text))
{
return "";
}
int num = text.IndexOf("\n", StringComparison.Ordinal);
if (num < 0)
{
num = text.IndexOf("\n\n", StringComparison.Ordinal);
}
if (num < 0)
{
num = text.IndexOf("\n", 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 Clippers = new List(8);
private static readonly List ClipperWasEnabled = new List(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.op_Implicit(Object.FindObjectsByType((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 componentsInChildren = ((Component)tt).GetComponentsInChildren(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());
CaptureClipper((Behaviour)(object)((Component)val3).GetComponent());
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();
if ((Object)(object)val == (Object)null)
{
val = gameObject.AddComponent();
_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();
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 val = Object.FindObjectsByType((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.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.op_Implicit(((Component)tt).GetComponentsInChildren(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";
}
}