Decompiled source of Effect Preview v1.2.0

EffectPreview.dll

Decompiled a month ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using DG.Tweening;
using DG.Tweening.Core;
using DG.Tweening.Plugins.Options;
using EffectPreview.Common;
using EffectPreview.Preview;
using EffectPreview.Ui;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Peak;
using Peak.Afflictions;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("EffectPreview")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.2.0.0")]
[assembly: AssemblyInformationalVersion("1.2.0+6228b2751bef0a0c8a85fda28e5fc9c85fe8dc2d")]
[assembly: AssemblyProduct("EffectPreview")]
[assembly: AssemblyTitle("EffectPreview")]
[assembly: AssemblyVersion("1.2.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace EffectPreview
{
	[BepInPlugin("OnlyCook.EffectPreview", "Effect Preview", "1.2.0")]
	public class Plugin : BaseUnityPlugin
	{
		private Harmony _harmony;

		internal static Plugin Instance { get; private set; }

		internal PluginConfig Cfg { get; private set; }

		internal ManualLogSource Log => ((BaseUnityPlugin)this).Logger;

		private void Awake()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Expected O, but got Unknown
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			Instance = this;
			Cfg = new PluginConfig(((BaseUnityPlugin)this).Config);
			_harmony = new Harmony("OnlyCook.EffectPreview");
			_harmony.PatchAll();
			GameObject val = new GameObject("EffectPreview.Runtime");
			Object.DontDestroyOnLoad((Object)val);
			val.AddComponent<HeldItemPreviewTracker>();
			val.AddComponent<GhostBarOverlay>();
			val.AddComponent<GhostJetpackFuelGauge>();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Effect Preview 1.2.0 loaded.");
		}
	}
	internal class PluginConfig
	{
		internal ConfigEntry<bool> EnablePreview;

		internal ConfigEntry<bool> EnableWasteIndicator;

		internal ConfigEntry<bool> EnableRemovalBlink;

		internal ConfigEntry<bool> ShowGhostBarCounts;

		internal ConfigEntry<bool> ShowVanillaBarCounts;

		internal ConfigEntry<bool> ShowAfflictionCountdowns;

		internal ConfigEntry<float> AfflictionCountdownFontScale;

		internal ConfigEntry<bool> PlainBarCounts;

		internal ConfigEntry<float> BarCountFontScale;

		internal ConfigEntry<bool> ShowSpecialStatusCounts;

		internal ConfigEntry<bool> ShowSpecialStatusDurationVisual;

		internal ConfigEntry<bool> StickyThornRemoval;

		internal ConfigEntry<bool> EnableWorldObjectPreviews;

		internal ConfigEntry<bool> EnablePlayerEntityPreviews;

		internal ConfigEntry<bool> EnableItemPickupPreviews;

		internal ConfigEntry<bool> EnableCookingPreview;

		internal ConfigEntry<KeyCode> CookingPreviewKey;

		internal ConfigEntry<bool> EnableWeightPreview;

		internal ConfigEntry<bool> EnableTimedUsagePreview;

		internal ConfigEntry<bool> EnableJetpackPreview;

		internal PluginConfig(ConfigFile config)
		{
			//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: Expected O, but got Unknown
			//IL_022a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0234: Expected O, but got Unknown
			EnablePreview = config.Bind<bool>("General", "enable-preview", true, "Show a ghost preview of status effect changes on both stamina bars while holding an item that would cause them.");
			EnableWorldObjectPreviews = config.Bind<bool>("Interactions", "enable-world-object-previews", true, "Show a preview when empty-handed and able to interact with a world object that changes your status effects (unlit campfires, ancient luggage).");
			EnablePlayerEntityPreviews = config.Bind<bool>("Interactions", "enable-player-entity-previews", true, "Show a preview when empty-handed and able to interact with a physical Thorn/Arrow stuck on your own body, or able to cannibalize another player.");
			EnableItemPickupPreviews = config.Bind<bool>("Interactions", "enable-item-pickup-previews", false, "Show a preview when empty-handed and aiming at an item on the ground in reach to pick up, for what its effect would be if held.");
			StickyThornRemoval = config.Bind<bool>("Interactions", "sticky-thorn-removal", true, "Keep removing a physical Thorn/Arrow you're holding interact on even if your aim drifts off it, instead of vanilla's behavior of cancelling the moment you're not looking straight at it.");
			EnableWeightPreview = config.Bind<bool>("Item Previews", "enable-weight-preview", true, "Whether to calculate and preview the Weight status effect.");
			EnableTimedUsagePreview = config.Bind<bool>("Item Previews", "enable-timed-usage-preview", true, "While holding certain items that remove status effect based on duration used, show a struck-through status icon for any status effect the item could fully remove if fully used, or both icons side by side if only partially.");
			EnableJetpackPreview = config.Bind<bool>("Item Previews", "enable-jetpack-preview", true, "While holding a fuel item and hovering the jetpack fuel slot, preview where its fuel gauge needle would land.");
			EnableCookingPreview = config.Bind<bool>("Item Previews", "enable-cooking-preview", true, "While holding an item you're able to cook (near a lit campfire or portable stove), hold the cooking preview key to preview what its next cook stage would do instead of its current stage.");
			CookingPreviewKey = config.Bind<KeyCode>("Item Previews", "cooking-preview-key", (KeyCode)99, "Key to hold to preview a held item's next cook stage instead of its current one.");
			EnableWasteIndicator = config.Bind<bool>("Bar Display", "enable-waste-indicator", false, "Show a marker on the ghost preview when the held item's effect would only be partially applied (some of it wasted).");
			EnableRemovalBlink = config.Bind<bool>("Bar Display", "enable-removal-blink", true, "Pulse the ghost bar for anything the held item would remove, instead of showing it as a steady translucent bar.");
			ShowGhostBarCounts = config.Bind<bool>("Bar Display", "show-ghost-bar-counts", false, "Show a number on each ghost preview bar (this mod's own) for how much it would add or remove.");
			ShowVanillaBarCounts = config.Bind<bool>("Bar Display", "show-vanilla-bar-counts", false, "Show a number on the game's own (non-ghost) bars for their current amount.");
			ShowAfflictionCountdowns = config.Bind<bool>("Bar Display", "show-affliction-countdowns", false, "Show a small countdown under the game's own affliction bars, like 10s+45: 10s is how long until the status effect is fully gone, +45 is how many seconds remain before it starts wearing off.");
			AfflictionCountdownFontScale = config.Bind<float>("Bar Display", "affliction-countdown-font-scale", 1f, new ConfigDescription("Multiplier for the size of the affliction countdown text, independent of bar-count-font-scale.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 3f), Array.Empty<object>()));
			PlainBarCounts = config.Bind<bool>("Bar Display", "plain-bar-counts", false, "Draw every bar count number as plain white with a dark gray border, instead of tinting it to match its bar's color.");
			BarCountFontScale = config.Bind<float>("Bar Display", "bar-count-font-scale", 1f, new ConfigDescription("Multiplier applied on top of the automatic size-to-fit bar scaling used by both ghost/vanilla bar count numbers.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 3f), Array.Empty<object>()));
			ShowSpecialStatusCounts = config.Bind<bool>("Bar Display", "show-special-status-counts", false, "Show a number (in seconds) for how much longer the real invincibility, infinite stamina and speed boost status effects will last - above the invincibility shield icon, appended to the infinite stamina bar label, and left of the speed boost line under the stamina bar.");
			ShowSpecialStatusDurationVisual = config.Bind<bool>("Bar Display", "show-special-status-duration-visual", true, "Visualize how much longer the real invincibility/infinite stamina/speed boost status effects will last: the invincibility border and infinite stamina rainbow overlay shrink from right to left on the bar itself, and a white line under the bar does the same for the speed boost.");
		}
	}
	public static class PluginInfo
	{
		public const string Guid = "OnlyCook.EffectPreview";

		public const string Name = "Effect Preview";

		public const string Version = "1.2.0";
	}
}
namespace EffectPreview.Ui
{
	internal class BarLabel
	{
		private const float OutlineWidth = 0.08f;

		private const float WidthPadding = 4f;

		private const float MinFontSize = 1f;

		private const float MaxFontSize = 24f;

		private const float BoxHeight = 40f;

		private const float VerticalOffset = 3f;

		private const float MinWidthToShow = 10f;

		private const float MinTextToOutlineContrast = 7f;

		private static readonly Color PlainOutline = new Color(0.2f, 0.2f, 0.2f, 1f);

		private const float GhostAlpha = 0.85f;

		private const float MinReadableFontSizeForFit = 13f;

		private const float EstimatedCharWidthFactor = 0.55f;

		private const string ArrowGlyph = "→";

		private readonly TextMeshProUGUI _text;

		private readonly Vector3[] _cornerBuffer = (Vector3[])(object)new Vector3[4];

		private static readonly Color ShadowColor = new Color(1f, 1f, 1f, 0.55f);

		private const float ShadowWidthPadding = 12f;

		private const float ShadowHeight = 22f;

		private const int ShadowTexSize = 32;

		private const int ShadowBorder = 14;

		private const float ShadowCornerRadius = 12f;

		private const float ShadowFade = 8f;

		private static Sprite _shadowSprite;

		private static readonly Dictionary<Transform, RectTransform> ShadowLayers = new Dictionary<Transform, RectTransform>();

		private const float CountdownScale = 0.64f;

		private const float CountdownMinBoxWidth = 80f;

		private const float CountdownVerticalOffset = -6f;

		private readonly RectTransform _shadow;

		private readonly Image _shadowImage;

		private const float FormatCountEpsilon = 0.0001f;

		internal static readonly Color CurseText = new Color(0.6f, 0.54f, 0.75f);

		internal static readonly Color CurseOutline = new Color(0.05f, 0.03f, 0.1f);

		internal static readonly Color PetrifyText = new Color(0.72f, 0.75f, 0.85f);

		internal static readonly Color PetrifyOutline = new Color(0.07f, 0.08f, 0.13f);

		internal bool IsValid => (Object)(object)_text != (Object)null;

		private BarLabel(TextMeshProUGUI text, RectTransform shadow, Image shadowImage)
		{
			_shadowImage = shadowImage;
			_text = text;
			_shadow = shadow;
		}

		private static Sprite GetShadowSprite()
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Expected O, but got Unknown
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_shadowSprite == (Object)null)
			{
				Texture2D val = new Texture2D(32, 32, (TextureFormat)4, false)
				{
					wrapMode = (TextureWrapMode)1,
					filterMode = (FilterMode)1
				};
				for (int i = 0; i < 32; i++)
				{
					for (int j = 0; j < 32; j++)
					{
						float num = 16f;
						float num2 = Mathf.Max(Mathf.Abs((float)j + 0.5f - num) - (num - 12f), 0f);
						float num3 = Mathf.Max(Mathf.Abs((float)i + 0.5f - num) - (num - 12f), 0f);
						float num4 = Mathf.Sqrt(num2 * num2 + num3 * num3) - 12f;
						float num5 = Mathf.SmoothStep(0f, 1f, Mathf.Clamp01((0f - num4) / 8f));
						val.SetPixel(j, i, new Color(0f, 0f, 0f, num5));
					}
				}
				val.Apply();
				_shadowSprite = Sprite.Create(val, new Rect(0f, 0f, 32f, 32f), new Vector2(0.5f, 0.5f), 100f, 0u, (SpriteMeshType)0, new Vector4(14f, 14f, 14f, 14f));
			}
			return _shadowSprite;
		}

		private static RectTransform GetShadowLayer(Transform parent)
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Expected O, but got Unknown
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Expected O, but got Unknown
			if (!ShadowLayers.TryGetValue(parent, out var value) || (Object)(object)value == (Object)null)
			{
				GameObject val = new GameObject("EffectPreview ShadowLayer", new Type[2]
				{
					typeof(RectTransform),
					typeof(LayoutElement)
				});
				value = (RectTransform)val.transform;
				((Transform)value).SetParent(parent, false);
				RectTransform obj = value;
				RectTransform obj2 = value;
				RectTransform obj3 = value;
				Vector2 val2 = default(Vector2);
				((Vector2)(ref val2))..ctor(0.5f, 0.5f);
				obj3.pivot = val2;
				Vector2 anchorMin = (obj2.anchorMax = val2);
				obj.anchorMin = anchorMin;
				val.GetComponent<LayoutElement>().ignoreLayout = true;
				GhostOwnershipTag.Attach(val);
				ShadowLayers[parent] = value;
			}
			return value;
		}

		internal static BarLabel Create(Transform parent, TMP_FontAsset font, Material fontMaterial, bool shadow = false)
		{
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Expected O, but got Unknown
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Expected O, but got Unknown
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Expected O, but got Unknown
			RectTransform val = null;
			Image shadowImage = null;
			Vector2 val3 = default(Vector2);
			Vector2 anchorMin;
			if (shadow)
			{
				RectTransform shadowLayer = GetShadowLayer(parent);
				GameObject val2 = new GameObject("EffectPreview LabelShadow", new Type[2]
				{
					typeof(RectTransform),
					typeof(Image)
				});
				val = (RectTransform)val2.transform;
				((Transform)val).SetParent((Transform)(object)shadowLayer, false);
				RectTransform obj = val;
				RectTransform obj2 = val;
				RectTransform obj3 = val;
				((Vector2)(ref val3))..ctor(0.5f, 0.5f);
				obj3.pivot = val3;
				anchorMin = (obj2.anchorMax = val3);
				obj.anchorMin = anchorMin;
				Image obj4 = (shadowImage = val2.GetComponent<Image>());
				obj4.sprite = GetShadowSprite();
				obj4.type = (Type)1;
				((Graphic)obj4).color = ShadowColor;
				((Graphic)obj4).raycastTarget = false;
				GhostOwnershipTag.Attach(val2);
				val2.SetActive(false);
			}
			GameObject val5 = new GameObject("EffectPreview BarLabel", new Type[2]
			{
				typeof(RectTransform),
				typeof(LayoutElement)
			});
			RectTransform val6 = (RectTransform)val5.transform;
			((Transform)val6).SetParent(parent, false);
			((Vector2)(ref val3))..ctor(0.5f, 0.5f);
			val6.pivot = val3;
			anchorMin = (val6.anchorMax = val3);
			val6.anchorMin = anchorMin;
			val5.GetComponent<LayoutElement>().ignoreLayout = true;
			TextMeshProUGUI val8 = val5.AddComponent<TextMeshProUGUI>();
			if ((Object)(object)font != (Object)null)
			{
				((TMP_Text)val8).font = font;
			}
			if ((Object)(object)fontMaterial != (Object)null)
			{
				((TMP_Text)val8).fontSharedMaterial = fontMaterial;
			}
			((TMP_Text)val8).alignment = (TextAlignmentOptions)514;
			((TMP_Text)val8).enableWordWrapping = false;
			((Graphic)val8).raycastTarget = false;
			((TMP_Text)val8).enableAutoSizing = true;
			((TMP_Text)val8).fontSizeMin = 1f;
			((TMP_Text)val8).fontSizeMax = 24f;
			((TMP_Text)val8).outlineWidth = 0.08f;
			GhostOwnershipTag.Attach(val5);
			val5.SetActive(false);
			return new BarLabel(val8, val, shadowImage);
		}

		internal static string FormatCount(float fraction)
		{
			return Mathf.FloorToInt(fraction * 100f + 0.0001f).ToString();
		}

		internal static void CountColors(Color barColor, bool ghost, out Color foreground, out Color outlineColor)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			barColor.a = 1f;
			float num = default(float);
			float num2 = default(float);
			float num3 = default(float);
			Color.RGBToHSV(barColor, ref num, ref num2, ref num3);
			float num4 = Mathf.Min(num2, 0.7f);
			Color val = Color.HSVToRGB(num, num4, 1f);
			float num5 = num2;
			float num6 = 0.22f;
			Color val2 = Color.HSVToRGB(num, num5, num6);
			for (int i = 0; i < 8; i++)
			{
				if (!(ColorUtil.ContrastRatio(val, val2) < 7f))
				{
					break;
				}
				num6 -= 0.03f;
				val2 = Color.HSVToRGB(num, num5, Mathf.Max(0f, num6));
			}
			foreground = val;
			outlineColor = val2;
			if (ghost)
			{
				foreground.a = 0.85f;
			}
		}

		internal static void PaletteCountColors(Color fg, Color outline, bool ghost, out Color foreground, out Color outlineColor)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			foreground = fg;
			outlineColor = outline;
			if (ghost)
			{
				foreground.a = 0.85f;
			}
		}

		internal void ApplyTransition(RectTransform target, float beforeFraction, float afterFraction, Color foreground, Color outlineColor, float scaleMultiplier, float fitWidthOverride = -1f)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)target == (Object)null || !((Component)target).gameObject.activeSelf)
			{
				Hide();
				return;
			}
			string text = FormatCount(beforeFraction);
			if (afterFraction >= beforeFraction - 0.0005f)
			{
				Apply(target, text, foreground, outlineColor, scaleMultiplier);
				return;
			}
			string text2 = text + " → " + FormatCount(afterFraction);
			float num;
			if (fitWidthOverride >= 0f)
			{
				num = fitWidthOverride;
			}
			else
			{
				target.GetWorldCorners(_cornerBuffer);
				num = _cornerBuffer[2].x - _cornerBuffer[0].x;
			}
			float num2 = (float)text2.Length * 0.55f * 13f;
			Apply(target, (num >= num2) ? text2 : text, foreground, outlineColor, scaleMultiplier);
		}

		internal void Apply(RectTransform target, string content, Color foreground, Color outlineColor, float scaleMultiplier, float extraVerticalOffset = 0f, bool bottomAnchored = false, float minBoxWidth = 0f)
		{
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_014b: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0213: Unknown result type (might be due to invalid IL or missing references)
			//IL_021f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0221: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0258: Unknown result type (might be due to invalid IL or missing references)
			//IL_0280: Unknown result type (might be due to invalid IL or missing references)
			//IL_0287: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cb: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)target == (Object)null || !((Component)target).gameObject.activeSelf || string.IsNullOrEmpty(content))
			{
				Hide();
				return;
			}
			target.GetWorldCorners(_cornerBuffer);
			float num = _cornerBuffer[2].x - _cornerBuffer[0].x;
			float num2 = _cornerBuffer[1].y - _cornerBuffer[0].y;
			if (num < 10f || num2 <= 1f)
			{
				Hide();
				return;
			}
			Vector3 val = (_cornerBuffer[0] + _cornerBuffer[2]) * 0.5f;
			((Component)_text).gameObject.SetActive(true);
			((TMP_Text)_text).transform.SetAsLastSibling();
			((TMP_Text)_text).rectTransform.sizeDelta = new Vector2(Mathf.Max(new float[3]
			{
				1f,
				num - 4f,
				minBoxWidth
			}), 40f);
			((TMP_Text)_text).transform.localScale = Vector3.one * Mathf.Max(0.01f, scaleMultiplier);
			Vector3 position = ((Transform)((TMP_Text)_text).rectTransform).position;
			position.x = val.x;
			position.y = (bottomAnchored ? _cornerBuffer[0].y : (val.y + 3f * ((TMP_Text)_text).transform.localScale.y)) + extraVerticalOffset * ((TMP_Text)_text).transform.parent.lossyScale.y;
			((Transform)((TMP_Text)_text).rectTransform).position = position;
			if (Plugin.Instance.Cfg.PlainBarCounts.Value)
			{
				((Color)(ref foreground))..ctor(1f, 1f, 1f, foreground.a);
				outlineColor = PlainOutline;
			}
			((TMP_Text)_text).text = content;
			((Graphic)_text).color = foreground;
			((TMP_Text)_text).outlineColor = Color32.op_Implicit(outlineColor);
			if ((Object)(object)_shadow != (Object)null)
			{
				((Component)_shadow).gameObject.SetActive(true);
				float x = ((TMP_Text)_text).transform.localScale.x;
				_shadow.sizeDelta = new Vector2(((TMP_Text)_text).renderedWidth + 12f, 22f) * x;
				_shadowImage.pixelsPerUnitMultiplier = Mathf.Max(0.01f, 14f / (22f * x * 0.5f));
				((Transform)_shadow).position = ((Transform)((TMP_Text)_text).rectTransform).position;
			}
		}

		internal void ApplyCountdown(RectTransform target, string content, Color foreground, Color outlineColor, float extraOffset = 0f)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			Apply(target, content, foreground, outlineColor, Plugin.Instance.Cfg.AfflictionCountdownFontScale.Value * 0.64f, -6f + extraOffset, bottomAnchored: true, 80f);
		}

		internal void Hide()
		{
			if ((Object)(object)_text != (Object)null)
			{
				((Component)_text).gameObject.SetActive(false);
			}
			if ((Object)(object)_shadow != (Object)null)
			{
				((Component)_shadow).gameObject.SetActive(false);
			}
		}
	}
	internal class BorderWarningBlink
	{
		private const float PulseSpeed = 6f;

		private const float PulseAmount = 0.6f;

		private const float LerpRate = 12f;

		private static readonly Color WarnColor = new Color(1f, 0.15f, 0.1f, 1f);

		private readonly Image[] _images;

		private readonly Color[] _originalColors;

		private float _sinTime;

		private float _blend;

		internal bool IsValid
		{
			get
			{
				for (int i = 0; i < _images.Length; i++)
				{
					if ((Object)(object)_images[i] == (Object)null)
					{
						return false;
					}
				}
				return true;
			}
		}

		internal BorderWarningBlink(params Image[] images)
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			_images = images;
			_originalColors = (Color[])(object)new Color[images.Length];
			for (int i = 0; i < images.Length; i++)
			{
				_originalColors[i] = (((Object)(object)images[i] != (Object)null) ? ((Graphic)images[i]).color : Color.white);
			}
		}

		internal void Apply(bool active)
		{
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			float num = (active ? 1f : 0f);
			_blend = Mathf.MoveTowards(_blend, num, Time.deltaTime * 12f);
			_sinTime = ((_blend > 0f) ? (_sinTime + Time.deltaTime * 6f) : 0f);
			float num2 = (Mathf.Sin(_sinTime) + 1f) * 0.5f * 0.6f * _blend;
			for (int i = 0; i < _images.Length; i++)
			{
				((Graphic)_images[i]).color = Color.Lerp(_originalColors[i], WarnColor, num2);
			}
		}

		internal void Hide()
		{
			Apply(active: false);
		}
	}
	internal class GhostBadge
	{
		private readonly struct Strip
		{
			internal readonly RectTransform Rtf;

			internal readonly Color FillColor;

			private readonly Image[] _images;

			private readonly float[] _baseAlphas;

			private readonly bool _isRemoval;

			private readonly RectTransform _iconRtf;

			private readonly RectTransform _strikethroughRtf;

			private readonly CanvasGroup _group;

			private const float StrikethroughThicknessRatio = 0.16f;

			private const float HideBelowWidth = 0.05f;

			private const float FadeStartWidth = 20f;

			private const float FadeEndWidth = 4f;

			internal bool IsValid => (Object)(object)Rtf != (Object)null;

			private Strip(RectTransform rtf, Color fillColor, Image[] images, float[] baseAlphas, bool isRemoval, RectTransform iconRtf, RectTransform strikethroughRtf, CanvasGroup group)
			{
				//IL_0008: Unknown result type (might be due to invalid IL or missing references)
				//IL_0009: Unknown result type (might be due to invalid IL or missing references)
				Rtf = rtf;
				FillColor = fillColor;
				_images = images;
				_baseAlphas = baseAlphas;
				_isRemoval = isRemoval;
				_iconRtf = iconRtf;
				_strikethroughRtf = strikethroughRtf;
				_group = group;
			}

			internal static Strip CloneFrom(RectTransform sourceBadge, Transform insertAfter, bool isRemoval = false)
			{
				//IL_006c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0071: Unknown result type (might be due to invalid IL or missing references)
				//IL_0072: Unknown result type (might be due to invalid IL or missing references)
				//IL_0060: Unknown result type (might be due to invalid IL or missing references)
				//IL_0091: Unknown result type (might be due to invalid IL or missing references)
				//IL_0096: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
				//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
				//IL_0113: Unknown result type (might be due to invalid IL or missing references)
				//IL_016f: Unknown result type (might be due to invalid IL or missing references)
				GameObject val = Object.Instantiate<GameObject>(((Component)sourceBadge).gameObject, ((Transform)sourceBadge).parent);
				((Object)val).name = ((Object)sourceBadge).name + " (EffectPreview Ghost)";
				BarAffliction component = val.GetComponent<BarAffliction>();
				Image val2 = (((Object)(object)component != (Object)null) ? component.icon : null);
				if ((Object)(object)component != (Object)null)
				{
					Object.Destroy((Object)(object)component);
				}
				if ((Object)(object)val2 != (Object)null)
				{
					((Component)val2).transform.localScale = Vector3.one;
				}
				Color val3 = WasteIndicator.SampleFillColor(val, val2);
				float num = default(float);
				float num2 = default(float);
				float num3 = default(float);
				Color.RGBToHSV(val3, ref num, ref num2, ref num3);
				if ((Object)(object)val2 != (Object)null && num2 < 0.15f)
				{
					val3 = ((Graphic)val2).color;
				}
				Image[] componentsInChildren = val.GetComponentsInChildren<Image>(true);
				float[] array = new float[componentsInChildren.Length];
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					Color val4 = Color.Lerp(((Graphic)componentsInChildren[i]).color, Color.white, 0.4f);
					val4.a = 0.65f;
					((Graphic)componentsInChildren[i]).color = val4;
					array[i] = val4.a;
				}
				RectTransform strikethroughRtf = ((isRemoval && (Object)(object)val2 != (Object)null) ? CreateStrikethrough(((Graphic)val2).rectTransform, ((Graphic)val2).color) : null);
				CanvasGroup val5 = val.GetComponent<CanvasGroup>();
				if ((Object)(object)val5 == (Object)null)
				{
					val5 = val.AddComponent<CanvasGroup>();
				}
				val5.blocksRaycasts = false;
				val5.interactable = false;
				val.transform.SetSiblingIndex(insertAfter.GetSiblingIndex() + 1);
				GhostOwnershipTag.Attach(val);
				val.SetActive(false);
				return new Strip(val.GetComponent<RectTransform>(), val3, componentsInChildren, array, isRemoval, ((Object)(object)val2 != (Object)null) ? ((Graphic)val2).rectTransform : null, strikethroughRtf, val5);
			}

			internal void Apply(float targetWidth, float lerpStep)
			{
				//IL_0021: Unknown result type (might be due to invalid IL or missing references)
				//IL_0063: Unknown result type (might be due to invalid IL or missing references)
				//IL_006d: Unknown result type (might be due to invalid IL or missing references)
				bool activeSelf = ((Component)Rtf).gameObject.activeSelf;
				float num = (activeSelf ? Rtf.sizeDelta.x : 0f);
				if (targetWidth <= 0f && num < 0.05f)
				{
					Hide();
					return;
				}
				float num2 = Mathf.Lerp(num, Mathf.Max(0f, targetWidth), lerpStep);
				Rtf.sizeDelta = new Vector2(num2, Rtf.sizeDelta.y);
				if (!activeSelf)
				{
					((Component)Rtf).gameObject.SetActive(true);
				}
				float num3 = ((targetWidth > 0f) ? 1f : Mathf.InverseLerp(4f, 20f, num2));
				if ((Object)(object)_group != (Object)null && _group.alpha != num3)
				{
					_group.alpha = num3;
				}
				if (!(num3 <= 0f))
				{
					if (_isRemoval)
					{
						RemovalPulse.Apply(_images, _baseAlphas);
					}
					UpdateStrikethrough();
				}
			}

			internal void Hide()
			{
				if ((Object)(object)Rtf != (Object)null)
				{
					((Component)Rtf).gameObject.SetActive(false);
				}
			}

			private void UpdateStrikethrough()
			{
				//IL_0023: Unknown result type (might be due to invalid IL or missing references)
				//IL_0028: Unknown result type (might be due to invalid IL or missing references)
				//IL_0036: Unknown result type (might be due to invalid IL or missing references)
				//IL_003b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0066: Unknown result type (might be due to invalid IL or missing references)
				if (!((Object)(object)_strikethroughRtf == (Object)null) && !((Object)(object)_iconRtf == (Object)null))
				{
					Rect rect = _iconRtf.rect;
					float width = ((Rect)(ref rect)).width;
					rect = _iconRtf.rect;
					float num = Mathf.Min(width, ((Rect)(ref rect)).height);
					if (!(num <= 0f))
					{
						_strikethroughRtf.sizeDelta = new Vector2(num * 1.4142135f, num * 0.16f);
					}
				}
			}

			private static RectTransform CreateStrikethrough(RectTransform iconRtf, Color tintColor)
			{
				//IL_0025: Unknown result type (might be due to invalid IL or missing references)
				//IL_002b: Expected O, but got Unknown
				//IL_0031: Unknown result type (might be due to invalid IL or missing references)
				//IL_0036: Unknown result type (might be due to invalid IL or missing references)
				//IL_003e: Unknown result type (might be due to invalid IL or missing references)
				//IL_003f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0040: Unknown result type (might be due to invalid IL or missing references)
				//IL_0052: Unknown result type (might be due to invalid IL or missing references)
				//IL_0058: Unknown result type (might be due to invalid IL or missing references)
				//IL_0059: Unknown result type (might be due to invalid IL or missing references)
				//IL_005a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0060: Unknown result type (might be due to invalid IL or missing references)
				//IL_0066: Unknown result type (might be due to invalid IL or missing references)
				//IL_0067: Unknown result type (might be due to invalid IL or missing references)
				//IL_0071: Unknown result type (might be due to invalid IL or missing references)
				//IL_0081: Unknown result type (might be due to invalid IL or missing references)
				//IL_0092: Unknown result type (might be due to invalid IL or missing references)
				//IL_009f: Expected O, but got Unknown
				GameObject val = new GameObject("GhostStrikethrough", new Type[2]
				{
					typeof(RectTransform),
					typeof(Image)
				});
				RectTransform val2 = (RectTransform)val.transform;
				((Transform)val2).SetParent((Transform)(object)iconRtf, false);
				Vector2 val3 = default(Vector2);
				((Vector2)(ref val3))..ctor(0.5f, 0.5f);
				val2.pivot = val3;
				Vector2 anchorMin = (val2.anchorMax = val3);
				val2.anchorMin = anchorMin;
				val2.anchoredPosition = Vector2.zero;
				((Transform)val2).localRotation = Quaternion.Euler(0f, 0f, 45f);
				Image component = val.GetComponent<Image>();
				((Graphic)component).color = tintColor;
				((Graphic)component).raycastTarget = false;
				return val2;
			}
		}

		private const float LerpStep100Fps = 0.1f;

		private static readonly FieldRef<ThornOnMe, float> ThornPopOutTime = AccessTools.FieldRefAccess<ThornOnMe, float>("popOutTime");

		private readonly RectTransform _realRtf;

		private readonly GameObject _realIcon;

		private readonly Strip _decreaseGhost;

		private readonly Strip _increaseGhost;

		private readonly WasteIndicator _decreaseWaste;

		private readonly WasteIndicator _increaseWaste;

		private readonly BarLabel _decreaseCountLabel;

		private readonly BarLabel _increaseCountLabel;

		private readonly BarLabel _realCountLabel;

		private readonly BarLabel _countdownLabel;

		private readonly GhostStatusCapIcon _capIcon;

		private readonly Color _vanillaForeground;

		private readonly Color _vanillaOutline;

		private readonly Color _ghostForeground;

		private readonly Color _ghostOutline;

		private readonly STATUSTYPE _statusType;

		private bool _realShrinking;

		private float _realDisplayedWidth;

		internal bool IsValid
		{
			get
			{
				if ((Object)(object)_realRtf != (Object)null && _decreaseGhost.IsValid && _increaseGhost.IsValid && _decreaseWaste.IsValid && _increaseWaste.IsValid && _decreaseCountLabel.IsValid && _increaseCountLabel.IsValid && _realCountLabel.IsValid && _countdownLabel.IsValid)
				{
					if (_capIcon != null)
					{
						return _capIcon.IsValid;
					}
					return true;
				}
				return false;
			}
		}

		internal RectTransform RowParent
		{
			get
			{
				Transform parent = ((Transform)_realRtf).parent;
				return (RectTransform)(object)((parent is RectTransform) ? parent : null);
			}
		}

		private GhostBadge(RectTransform realRtf, GameObject realIcon, Strip decreaseGhost, Strip increaseGhost, WasteIndicator decreaseWaste, WasteIndicator increaseWaste, BarLabel decreaseCountLabel, BarLabel increaseCountLabel, BarLabel realCountLabel, BarLabel countdownLabel, GhostStatusCapIcon capIcon, STATUSTYPE statusType)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Invalid comparison between Unknown and I4
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			_statusType = statusType;
			_realRtf = realRtf;
			_realIcon = realIcon;
			_decreaseGhost = decreaseGhost;
			_increaseGhost = increaseGhost;
			_decreaseWaste = decreaseWaste;
			_increaseWaste = increaseWaste;
			_decreaseCountLabel = decreaseCountLabel;
			_increaseCountLabel = increaseCountLabel;
			_realCountLabel = realCountLabel;
			_countdownLabel = countdownLabel;
			_capIcon = capIcon;
			if ((int)statusType == 5)
			{
				BarLabel.PaletteCountColors(BarLabel.CurseText, BarLabel.CurseOutline, ghost: false, out _vanillaForeground, out _vanillaOutline);
				BarLabel.PaletteCountColors(BarLabel.CurseText, BarLabel.CurseOutline, ghost: true, out _ghostForeground, out _ghostOutline);
			}
			else
			{
				BarLabel.CountColors(decreaseGhost.FillColor, ghost: false, out _vanillaForeground, out _vanillaOutline);
				BarLabel.CountColors(decreaseGhost.FillColor, ghost: true, out _ghostForeground, out _ghostOutline);
			}
		}

		internal static GhostBadge Create(BarAffliction realAffliction, TMP_FontAsset font, Material fontMaterial, Transform countdownParent)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			RectTransform rtf = realAffliction.rtf;
			Strip decreaseGhost = Strip.CloneFrom(rtf, (Transform)(object)rtf, isRemoval: true);
			Strip increaseGhost = Strip.CloneFrom(rtf, (Transform)(object)decreaseGhost.Rtf);
			WasteIndicator decreaseWaste = WasteIndicator.Create(((Transform)rtf).parent, decreaseGhost.FillColor);
			WasteIndicator increaseWaste = WasteIndicator.Create(((Transform)rtf).parent, increaseGhost.FillColor);
			BarLabel decreaseCountLabel = BarLabel.Create(((Transform)rtf).parent, font, fontMaterial);
			BarLabel increaseCountLabel = BarLabel.Create(((Transform)rtf).parent, font, fontMaterial);
			BarLabel realCountLabel = BarLabel.Create(((Transform)rtf).parent, font, fontMaterial);
			BarLabel countdownLabel = BarLabel.Create(countdownParent, font, fontMaterial, shadow: true);
			GhostStatusCapIcon capIcon = GhostStatusCapIcon.Create(realAffliction.icon);
			GameObject realIcon = (((Object)(object)realAffliction.icon != (Object)null) ? ((Component)realAffliction.icon).gameObject : null);
			return new GhostBadge(rtf, realIcon, decreaseGhost, increaseGhost, decreaseWaste, increaseWaste, decreaseCountLabel, increaseCountLabel, realCountLabel, countdownLabel, capIcon, realAffliction.afflictionType);
		}

		internal void ApplyRemovalCap(float liveValue, float cap, bool decreaseActive)
		{
			if (_capIcon != null)
			{
				if (decreaseActive || cap <= 0f || liveValue <= 0f)
				{
					_capIcon.Hide();
				}
				else
				{
					_capIcon.Apply(liveValue <= cap);
				}
			}
		}

		internal void ApplyWidths(float fullLocalWidth, float liveValue, float decreaseAmount, float increaseAmount)
		{
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			float num = AnimUtil.LerpStep(0.1f);
			float num2 = Mathf.Min(decreaseAmount, liveValue);
			if (num2 > 0f)
			{
				float num3 = Mathf.Max(0f, liveValue - num2);
				float num4 = fullLocalWidth * num3;
				if (!_realShrinking)
				{
					_realDisplayedWidth = _realRtf.sizeDelta.x;
				}
				_realShrinking = true;
				_realDisplayedWidth = Mathf.Lerp(_realDisplayedWidth, num4, num);
				_realRtf.sizeDelta = new Vector2(_realDisplayedWidth, _realRtf.sizeDelta.y);
				if ((Object)(object)_realIcon != (Object)null)
				{
					_realIcon.SetActive(num3 > 0.001f);
				}
			}
			else if (_realShrinking)
			{
				_realShrinking = false;
				if ((Object)(object)_realIcon != (Object)null)
				{
					_realIcon.SetActive(true);
				}
			}
			float num5 = Mathf.Min(num2, increaseAmount);
			_decreaseGhost.Apply(fullLocalWidth * (num2 - num5), num);
			_increaseGhost.Apply(fullLocalWidth * increaseAmount, num);
		}

		internal float GetTargetRowWidth(float fullLocalWidth, float liveValue, float decreaseAmount, float increaseAmount)
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.Min(decreaseAmount, liveValue);
			float num3;
			if (num > 0f)
			{
				float num2 = Mathf.Max(0f, liveValue - num);
				num3 = fullLocalWidth * num2;
			}
			else
			{
				num3 = (((Component)_realRtf).gameObject.activeSelf ? _realRtf.sizeDelta.x : 0f);
			}
			float num4 = Mathf.Min(num, increaseAmount);
			float num5 = fullLocalWidth * (num - num4);
			float num6 = fullLocalWidth * increaseAmount;
			return num3 + num5 + num6;
		}

		internal void ApplyOverlays(float liveValue, float decreaseAmount, float increaseAmount, float statusCap, float wasteHeight)
		{
			//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_0240: Unknown result type (might be due to invalid IL or missing references)
			//IL_0246: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.Min(decreaseAmount, liveValue);
			bool value = Plugin.Instance.Cfg.EnableWasteIndicator.Value;
			if (value && num > 0.0005f && decreaseAmount - num > 0.0005f)
			{
				_decreaseWaste.Apply(_decreaseGhost.Rtf, _realRtf, wasteHeight, rightEdge: false);
			}
			else
			{
				_decreaseWaste.Hide();
			}
			float num2 = Mathf.Max(0f, liveValue - num);
			float num3 = Mathf.Max(0f, statusCap - num2);
			float num4 = Mathf.Min(increaseAmount, num3);
			if (value && num4 > 0.0005f && increaseAmount - num4 > 0.0005f)
			{
				_increaseWaste.Apply(_increaseGhost.Rtf, _realRtf, wasteHeight, rightEdge: false);
			}
			else
			{
				_increaseWaste.Hide();
			}
			float value2 = Plugin.Instance.Cfg.BarCountFontScale.Value;
			if (Plugin.Instance.Cfg.ShowGhostBarCounts.Value)
			{
				float num5 = Mathf.Min(num, increaseAmount);
				float num6 = num - num5;
				_decreaseCountLabel.Apply(_decreaseGhost.Rtf, (num6 > 0.0005f) ? BarLabel.FormatCount(num6) : null, _ghostForeground, _ghostOutline, value2);
				_increaseCountLabel.Apply(_increaseGhost.Rtf, (increaseAmount > 0.0005f) ? BarLabel.FormatCount(increaseAmount) : null, _ghostForeground, _ghostOutline, value2);
			}
			else
			{
				_decreaseCountLabel.Hide();
				_increaseCountLabel.Hide();
			}
			bool value3 = Plugin.Instance.Cfg.ShowVanillaBarCounts.Value;
			bool value4 = Plugin.Instance.Cfg.ShowAfflictionCountdowns.Value;
			bool flag = num2 > 0.0005f;
			if (value3 && flag)
			{
				_realCountLabel.Apply(_realRtf, BarLabel.FormatCount(num2), _vanillaForeground, _vanillaOutline, value2);
			}
			else
			{
				_realCountLabel.Hide();
			}
			string text = ((value4 && flag) ? FormatCountdown(num2) : null);
			if (text != null)
			{
				_countdownLabel.ApplyCountdown(_realRtf, text, _vanillaForeground, _vanillaOutline);
			}
			else
			{
				_countdownLabel.Hide();
			}
		}

		private string FormatCountdown(float value)
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Invalid comparison between Unknown and I4
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Invalid comparison between Unknown and I4
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Expected I4, but got Unknown
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			CharacterAfflictions val = Character.localCharacter?.refs.afflictions;
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			if ((int)_statusType == 9)
			{
				float num = 0f;
				for (int i = 0; i < val.physicalThorns.Count; i++)
				{
					ThornOnMe val2 = val.physicalThorns[i];
					if ((Object)(object)val2 != (Object)null && val2.stuckIn && val2.isThorn && val2.popsOutAutomatically)
					{
						num = Mathf.Max(num, ThornPopOutTime.Invoke(val2));
					}
				}
				float num2 = num - Time.time;
				if (!(num2 > 0f))
				{
					return null;
				}
				return "(" + Mathf.CeilToInt(num2) + "s)";
			}
			STATUSTYPE statusType = _statusType;
			float num3;
			float num4;
			if ((int)statusType != 3)
			{
				switch (statusType - 6)
				{
				case 0:
					num3 = val.drowsyReductionPerSecond;
					num4 = val.drowsyReductionCooldown;
					break;
				case 2:
					num3 = val.hotReductionPerSecond;
					num4 = val.hotReductionCooldown;
					break;
				case 4:
					num3 = val.sporesReductionPerSecond;
					num4 = val.sporesReductionCooldown;
					break;
				default:
					return null;
				}
			}
			else
			{
				num3 = val.poisonReductionPerSecond;
				num4 = val.poisonReductionCooldown;
			}
			if (num3 <= 0f)
			{
				return null;
			}
			float num5 = Mathf.Max(0f, num4 - (Time.time - val.LastAddedStatus(_statusType)));
			int num6 = Mathf.CeilToInt(value / num3 - 0.0005f);
			if (!(num5 > 0f))
			{
				return "(" + num6 + "s)";
			}
			return "(" + num6 + "s+" + Mathf.CeilToInt(num5) + ")";
		}

		internal void Hide()
		{
			_realShrinking = false;
			_decreaseGhost.Hide();
			_increaseGhost.Hide();
			_decreaseWaste.Hide();
			_increaseWaste.Hide();
			_decreaseCountLabel.Hide();
			_increaseCountLabel.Hide();
			_realCountLabel.Hide();
			_countdownLabel.Hide();
			_capIcon?.Hide();
			if ((Object)(object)_realIcon != (Object)null)
			{
				_realIcon.SetActive(true);
			}
		}
	}
	internal class GhostBarOverlay : MonoBehaviour
	{
		private StaminaBar _bar;

		private RectTransform _fullBar;

		private bool _built;

		private static readonly HashSet<STATUSTYPE> CurableStatuses = new HashSet<STATUSTYPE>
		{
			(STATUSTYPE)0,
			(STATUSTYPE)1,
			(STATUSTYPE)2,
			(STATUSTYPE)3,
			(STATUSTYPE)6,
			(STATUSTYPE)8,
			(STATUSTYPE)10,
			(STATUSTYPE)11,
			(STATUSTYPE)14
		};

		private readonly Dictionary<STATUSTYPE, GhostBadge> _statusGhosts = new Dictionary<STATUSTYPE, GhostBadge>();

		private readonly Dictionary<STATUSTYPE, float> _dynamicHealBreakdown = new Dictionary<STATUSTYPE, float>();

		private readonly HashSet<STATUSTYPE> _netDeltaVisited = new HashSet<STATUSTYPE>();

		private GhostExtraStaminaArea _extraStaminaArea;

		private GhostPetrifyArea _petrifyArea;

		private GhostStaminaArea _staminaArea;

		private GhostRainbowStamina _rainbowArea;

		private GhostInvincibilityShield _shieldArea;

		private BorderWarningBlink _passOutBorderBlink;

		private BorderWarningBlink _petrifyDeathBorderBlink;

		private BarLabel _staminaCountLabel;

		private const float StaminaCountdownRaise = 12f;

		private BarLabel _staminaCountdownLabel;

		private InvincibilityBorderVisual _invincibilityBorderVisual;

		private InfiniteStaminaDurationVisual _infiniteStaminaDurationVisual;

		private BarLabel _invincibilityCountLabel;

		private SpeedBoostDurationLine _speedBoostLine;

		private RectTransform _shieldIconRect;

		private Color _staminaVanillaForeground;

		private Color _staminaVanillaOutline;

		private TMP_FontAsset _font;

		private Material _fontMaterial;

		private readonly InfiniteStaminaGraceTracker _infiniteStaminaGraceTracker = new InfiniteStaminaGraceTracker();

		private readonly InfiniteStaminaUnifiedTimer _infiniteStaminaUnifiedTimer = new InfiniteStaminaUnifiedTimer();

		private readonly ExternalInfiniteStaminaDetector _externalInfiniteStamina = new ExternalInfiniteStaminaDetector();

		private readonly InfiniteStaminaGraceTracker _speedBoostGraceTracker = new InfiniteStaminaGraceTracker();

		private void LateUpdate()
		{
			if (!TryGetBar())
			{
				HideAll();
				return;
			}
			if (_built && IsStale())
			{
				_statusGhosts.Clear();
				_extraStaminaArea = null;
				_petrifyArea = null;
				_staminaArea = null;
				_rainbowArea = null;
				_shieldArea = null;
				_passOutBorderBlink = null;
				_petrifyDeathBorderBlink = null;
				_staminaCountLabel = null;
				_staminaCountdownLabel = null;
				_invincibilityBorderVisual = null;
				_infiniteStaminaDurationVisual = null;
				_invincibilityCountLabel = null;
				_speedBoostLine = null;
				_shieldIconRect = null;
				_built = false;
			}
			if (!_built)
			{
				Safe.Run("GhostBarOverlay.Build", Build);
			}
			if (_built)
			{
				Safe.Run("GhostBarOverlay.Refresh", Refresh);
			}
		}

		private bool IsStale()
		{
			foreach (GhostBadge value in _statusGhosts.Values)
			{
				if (!value.IsValid)
				{
					return true;
				}
			}
			if (_extraStaminaArea != null && !_extraStaminaArea.IsValid)
			{
				return true;
			}
			if (_petrifyArea != null && !_petrifyArea.IsValid)
			{
				return true;
			}
			if (_rainbowArea != null && !_rainbowArea.IsValid)
			{
				return true;
			}
			if (_shieldArea != null && !_shieldArea.IsValid)
			{
				return true;
			}
			if (_passOutBorderBlink != null && !_passOutBorderBlink.IsValid)
			{
				return true;
			}
			if (_petrifyDeathBorderBlink != null && !_petrifyDeathBorderBlink.IsValid)
			{
				return true;
			}
			if (_staminaCountdownLabel != null && !_staminaCountdownLabel.IsValid)
			{
				return true;
			}
			if (_staminaCountLabel != null && !_staminaCountLabel.IsValid)
			{
				return true;
			}
			if (_invincibilityBorderVisual != null && !_invincibilityBorderVisual.IsValid)
			{
				return true;
			}
			if (_infiniteStaminaDurationVisual != null && !_infiniteStaminaDurationVisual.IsValid)
			{
				return true;
			}
			if (_invincibilityCountLabel != null && !_invincibilityCountLabel.IsValid)
			{
				return true;
			}
			if (_speedBoostLine != null && !_speedBoostLine.IsValid)
			{
				return true;
			}
			if (_staminaArea != null)
			{
				return !_staminaArea.IsValid;
			}
			return false;
		}

		private bool TryGetBar()
		{
			GUIManager instance = GUIManager.instance;
			if ((Object)(object)instance == (Object)null || (Object)(object)instance.bar == (Object)null || (Object)(object)instance.bar.fullBar == (Object)null || instance.bar.afflictions == null)
			{
				return false;
			}
			_bar = instance.bar;
			_fullBar = _bar.fullBar;
			return true;
		}

		private void Build()
		{
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0280: Unknown result type (might be due to invalid IL or missing references)
			TMP_FontAsset val = (((Object)(object)_bar.moraleBoostText != (Object)null) ? ((TMP_Text)_bar.moraleBoostText).font : null);
			Material fontMaterial = (((Object)(object)_bar.moraleBoostText != (Object)null) ? ((TMP_Text)_bar.moraleBoostText).fontSharedMaterial : null);
			_font = val;
			_fontMaterial = fontMaterial;
			BarAffliction[] afflictions = _bar.afflictions;
			foreach (BarAffliction val2 in afflictions)
			{
				if (!((Object)(object)val2 == (Object)null) && !val2.isPetrify && !_statusGhosts.ContainsKey(val2.afflictionType))
				{
					_statusGhosts[val2.afflictionType] = GhostBadge.Create(val2, val, fontMaterial, ((Object)(object)_bar.extraBar != (Object)null) ? ((Component)_bar.extraBar).transform.parent : ((Transform)val2.rtf).parent);
				}
			}
			if (_extraStaminaArea == null && (Object)(object)_bar.extraBar != (Object)null && (Object)(object)_bar.extraBarStamina != (Object)null && (Object)(object)_bar.extraBarOutline != (Object)null && (Object)(object)_bar.extraStaminaIcon != (Object)null)
			{
				_extraStaminaArea = new GhostExtraStaminaArea(_bar.extraBar, _bar.extraBarStamina, _bar.extraBarOutline, _bar.extraStaminaIcon, val, fontMaterial);
			}
			if (_petrifyArea == null && (Object)(object)_bar.petrifyAffliction != (Object)null && (Object)(object)_bar.petrifyAffliction.rtf != (Object)null)
			{
				_petrifyArea = new GhostPetrifyArea(_bar.petrifyAffliction, val, fontMaterial);
			}
			if (_staminaCountLabel == null && (Object)(object)_bar.staminaBar != (Object)null && (Object)(object)val != (Object)null)
			{
				_staminaCountLabel = BarLabel.Create(FindUnmaskedAncestorParent((Transform)(object)_bar.maxStaminaBar), val, fontMaterial);
				_staminaCountdownLabel = BarLabel.Create(((Object)(object)_bar.extraBar != (Object)null) ? ((Component)_bar.extraBar).transform.parent : FindUnmaskedAncestorParent((Transform)(object)_bar.maxStaminaBar), val, fontMaterial, shadow: true);
				BarLabel.CountColors(WasteIndicator.SampleFillColor(((Component)_bar.staminaBar).gameObject, null), ghost: false, out _staminaVanillaForeground, out _staminaVanillaOutline);
			}
			if (_staminaArea == null && (Object)(object)_bar.maxStaminaBar != (Object)null && (Object)(object)_bar.staminaBar != (Object)null)
			{
				_staminaArea = new GhostStaminaArea(_bar.maxStaminaBar, _bar.staminaBar);
			}
			if (_rainbowArea == null && (Object)(object)_bar.rainbowStamina != (Object)null)
			{
				_rainbowArea = GhostRainbowStamina.Create(_bar.rainbowStamina);
			}
			if (_shieldArea == null && (Object)(object)_bar.shield != (Object)null)
			{
				_shieldArea = GhostInvincibilityShield.Create(_bar.shield);
			}
			Transform val3 = (((Object)(object)_bar.staminaBarOutline != (Object)null) ? ((Transform)_bar.staminaBarOutline).Find("OutlineImage") : null);
			Transform obj = (((Object)(object)_bar.staminaBarOutline != (Object)null) ? ((Transform)_bar.staminaBarOutline).Find("OutlineCap") : null);
			RectTransform val4 = (RectTransform)(object)((val3 is RectTransform) ? val3 : null);
			RectTransform val5 = (RectTransform)(object)((obj is RectTransform) ? obj : null);
			if (_passOutBorderBlink == null && (Object)(object)_bar.staminaBarOutline != (Object)null)
			{
				Image val6 = (((Object)(object)val4 != (Object)null) ? ((Component)val4).GetComponent<Image>() : null);
				Image val7 = (((Object)(object)val5 != (Object)null) ? ((Component)val5).GetComponent<Image>() : null);
				if ((Object)(object)val6 != (Object)null && (Object)(object)val7 != (Object)null)
				{
					_passOutBorderBlink = new BorderWarningBlink(val6, val7);
				}
				else if ((Object)(object)val6 != (Object)null)
				{
					_passOutBorderBlink = new BorderWarningBlink(val6);
				}
			}
			RectTransform val8 = (((Object)(object)_bar.shield != (Object)null) ? _bar.shield.GetComponent<RectTransform>() : null);
			if (_invincibilityBorderVisual == null && (Object)(object)val8 != (Object)null)
			{
				_invincibilityBorderVisual = new InvincibilityBorderVisual(val8);
			}
			if (_infiniteStaminaDurationVisual == null && (Object)(object)_bar.rainbowStamina != (Object)null)
			{
				_infiniteStaminaDurationVisual = new InfiniteStaminaDurationVisual(((Graphic)_bar.rainbowStamina).rectTransform);
			}
			if (_speedBoostLine == null && (Object)(object)_bar.staminaBarOutline != (Object)null && (Object)(object)_bar.extraBarOutline != (Object)null && (Object)(object)((Transform)_bar.extraBarOutline).parent != (Object)null)
			{
				_speedBoostLine = SpeedBoostDurationLine.Create(_bar.staminaBarOutline, _bar.extraBarOutline, FindUnmaskedAncestorParent((Transform)(((Object)(object)_bar.extraBar != (Object)null) ? ((object)((Component)_bar.extraBar).transform) : ((object)_bar.extraBarOutline))), val, fontMaterial);
			}
			_shieldIconRect = val8;
			if (_petrifyDeathBorderBlink == null && (Object)(object)_bar.extraBarOutline != (Object)null)
			{
				Image component = ((Component)_bar.extraBarOutline).GetComponent<Image>();
				if ((Object)(object)component != (Object)null)
				{
					_petrifyDeathBorderBlink = new BorderWarningBlink(component);
				}
			}
			_built = true;
		}

		private void Refresh()
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0209: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0724: Unknown result type (might be due to invalid IL or missing references)
			//IL_0748: Unknown result type (might be due to invalid IL or missing references)
			//IL_0752: Unknown result type (might be due to invalid IL or missing references)
			//IL_0682: Unknown result type (might be due to invalid IL or missing references)
			//IL_0688: Unknown result type (might be due to invalid IL or missing references)
			//IL_057d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0583: Unknown result type (might be due to invalid IL or missing references)
			//IL_0634: Unknown result type (might be due to invalid IL or missing references)
			//IL_063a: Unknown result type (might be due to invalid IL or missing references)
			//IL_09de: Unknown result type (might be due to invalid IL or missing references)
			//IL_09e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_0aba: Unknown result type (might be due to invalid IL or missing references)
			//IL_0abf: Unknown result type (might be due to invalid IL or missing references)
			Character observedCharacter = Character.observedCharacter;
			if ((Object)(object)observedCharacter == (Object)null)
			{
				HideAll();
				return;
			}
			ItemPreview current = HeldItemPreviewTracker.Instance.Current;
			float x = _fullBar.sizeDelta.x;
			_dynamicHealBreakdown.Clear();
			if ((Object)(object)current.HealingGemAction != (Object)null)
			{
				DynamicPetrifyPreview.ComputeHealBreakdown(current, observedCharacter, _dynamicHealBreakdown);
			}
			float wasteHeight = (((Object)(object)_bar.extraBarStamina != (Object)null) ? WasteIndicator.MeasureHeight(_bar.extraBarStamina) : 0f);
			float num = 0f;
			float remainingSeconds;
			foreach (KeyValuePair<STATUSTYPE, GhostBadge> statusGhost in _statusGhosts)
			{
				GetStatusPreview(observedCharacter, current, statusGhost.Key, out var live, out var decrease, out var increase, out remainingSeconds);
				statusGhost.Value.ApplyWidths(x, live, decrease, increase);
				num += statusGhost.Value.GetTargetRowWidth(x, live, decrease, increase);
			}
			float num2 = ComputeNetStatusSumDelta(observedCharacter, current);
			float maxAllowedWidthPx = Mathf.Max(0f, x - num);
			_staminaArea?.Apply(x, observedCharacter.GetMaxStamina(), observedCharacter.data.currentStamina, Mathf.Max(0f, num2), maxAllowedWidthPx);
			RectTransform val = null;
			using (Dictionary<STATUSTYPE, GhostBadge>.ValueCollection.Enumerator enumerator2 = _statusGhosts.Values.GetEnumerator())
			{
				if (enumerator2.MoveNext())
				{
					val = enumerator2.Current.RowParent;
				}
			}
			if ((Object)(object)val != (Object)null)
			{
				LayoutRebuilder.ForceRebuildLayoutImmediate(val);
			}
			foreach (KeyValuePair<STATUSTYPE, GhostBadge> statusGhost2 in _statusGhosts)
			{
				GetStatusPreview(observedCharacter, current, statusGhost2.Key, out var live2, out var decrease2, out var increase2, out var statusCap);
				statusGhost2.Value.ApplyOverlays(live2, decrease2, increase2, statusCap, wasteHeight);
				float value = 0f;
				bool value2 = Plugin.Instance.Cfg.EnableTimedUsagePreview.Value;
				if (value2)
				{
					current.StatusRemovalCaps.TryGetValue(statusGhost2.Key, out value);
				}
				bool decreaseActive = Mathf.Min(decrease2, live2) > 0f;
				statusGhost2.Value.ApplyRemovalCap(live2, value2 ? value : 0f, decreaseActive);
			}
			bool value3 = Plugin.Instance.Cfg.ShowSpecialStatusCounts.Value;
			bool value4 = Plugin.Instance.Cfg.ShowSpecialStatusDurationVisual.Value;
			if (!observedCharacter.infiniteStam)
			{
				_infiniteStaminaGraceTracker.Reset();
				_infiniteStaminaUnifiedTimer.Reset();
				_externalInfiniteStamina.Reset();
			}
			float num3 = 0f;
			float num4 = 0f;
			string text = null;
			string text2 = null;
			bool flag = false;
			Affliction_InfiniteStamina affliction;
			bool flag2 = SpecialStatusDuration.TryGetDirectInfiniteStaminaAffliction(observedCharacter, out affliction);
			float num5 = (flag2 ? Mathf.Max(0f, ((Affliction)affliction).totalTime - ((Affliction)affliction).timeElapsed) : 0f);
			Affliction_RadiateInfiniteStam affliction2;
			bool flag3 = SpecialStatusDuration.TryGetRadiateInfiniteStamAffliction(observedCharacter, out affliction2);
			float num6 = _infiniteStaminaUnifiedTimer.Tick(flag3, flag3 ? ((Affliction)affliction2).totalTime : 0f, flag3 ? ((Affliction)affliction2).timeElapsed : 0f, flag2, num5);
			_externalInfiniteStamina.Tick(flag2, flag2 ? ((Affliction)affliction).timeElapsed : 0f);
			bool flag4 = num6 < 0f && _externalInfiniteStamina.IsExternal;
			bool flag5;
			if (flag4)
			{
				flag5 = false;
				_infiniteStaminaGraceTracker.Reset();
			}
			else if (num6 >= 0f)
			{
				flag5 = true;
				num3 = num6;
				num4 = ((_infiniteStaminaUnifiedTimer.TotalDuration > 0f) ? Mathf.Clamp01(num6 / _infiniteStaminaUnifiedTimer.TotalDuration) : 0f);
				_infiniteStaminaGraceTracker.Reset();
			}
			else if (flag2)
			{
				flag5 = true;
				num3 = num5;
				num4 = ((((Affliction)affliction).totalTime > 0f) ? Mathf.Clamp01(num5 / ((Affliction)affliction).totalTime) : 0f);
				if (_infiniteStaminaGraceTracker.TryGetRemainingGrace((Affliction)(object)affliction, affliction.climbDelay, out var remainingGraceSeconds))
				{
					text = "+" + Mathf.CeilToInt(remainingGraceSeconds);
				}
			}
			else
			{
				flag5 = false;
				_infiniteStaminaGraceTracker.Reset();
			}
			if (_staminaCountLabel != null)
			{
				if (observedCharacter.infiniteStam && flag5 && value3)
				{
					text2 = "(" + Mathf.CeilToInt(num3) + "s" + text + ")";
					if (Plugin.Instance.Cfg.ShowVanillaBarCounts.Value)
					{
						_staminaCountLabel.Apply(_bar.maxStaminaBar, "∞", _staminaVanillaForeground, _staminaVanillaOutline, Plugin.Instance.Cfg.BarCountFontScale.Value);
					}
					else
					{
						_staminaCountLabel.Hide();
					}
				}
				else if (observedCharacter.infiniteStam && !flag5 && !flag4 && value3)
				{
					flag = true;
				}
				else if (!Plugin.Instance.Cfg.ShowVanillaBarCounts.Value)
				{
					_staminaCountLabel.Hide();
				}
				else if (observedCharacter.infiniteStam)
				{
					_staminaCountLabel.Apply(_bar.maxStaminaBar, "∞", _staminaVanillaForeground, _staminaVanillaOutline, Plugin.Instance.Cfg.BarCountFontScale.Value);
				}
				else if (observedCharacter.data.currentStamina > 0.0005f)
				{
					float maxStamina = observedCharacter.GetMaxStamina();
					float num7 = Mathf.Min(observedCharacter.data.currentStamina, maxStamina);
					float num8 = Mathf.Max(0f, maxStamina - num2);
					float afterFraction = Mathf.Min(num7, num8);
					RectTransform target = ((observedCharacter.data.currentStamina > maxStamina) ? _bar.maxStaminaBar : _bar.staminaBar);
					_staminaCountLabel.ApplyTransition(target, num7, afterFraction, _staminaVanillaForeground, _staminaVanillaOutline, Plugin.Instance.Cfg.BarCountFontScale.Value);
				}
				else
				{
					_staminaCountLabel.Hide();
				}
				if (text2 != null)
				{
					_staminaCountdownLabel.ApplyCountdown(_bar.maxStaminaBar, text2, _staminaVanillaForeground, _staminaVanillaOutline, 12f);
				}
				else if (!flag)
				{
					_staminaCountdownLabel.Hide();
				}
			}
			float num9 = observedCharacter.refs.afflictions.statusSum + num2;
			bool active = num9 > 0.99f;
			_passOutBorderBlink?.Apply(active);
			if ((Object)(object)_bar.staminaBarOutline != (Object)null)
			{
				float num10 = Mathf.Max(14f + Mathf.Max(1f, num9) * x, 14f + Mathf.Max(x, num));
				if (num10 > _bar.staminaBarOutline.sizeDelta.x)
				{
					_bar.staminaBarOutline.sizeDelta = new Vector2(num10, _bar.staminaBarOutline.sizeDelta.y);
				}
			}
			if (num9 > 1.005f && (Object)(object)_bar.staminaBarOutlineOverflowBar != (Object)null)
			{
				((Component)_bar.staminaBarOutlineOverflowBar).gameObject.SetActive(true);
			}
			float num11 = Mathf.Max(0f, current.PetrifyDelta + DynamicPetrifyPreview.Compute(current, observedCharacter));
			float num12 = Mathf.Max(0f, 1f - (float)observedCharacter.data.petrifyAmount * 0.01f);
			float num13 = Mathf.Min(num11, num12);
			float currentPetrifyFraction = (float)observedCharacter.data.petrifyAmount * 0.01f;
			float shrinkDelta = Mathf.Max(0f, current.PetrifyReductionOnUse);
			bool active2 = num12 > 0.0005f && num13 >= num12 - 0.0005f;
			_petrifyDeathBorderBlink?.Apply(active2);
			bool flag6 = (Object)(object)_bar.petrifyAffliction != (Object)null && ((Component)_bar.petrifyAffliction).gameObject.activeSelf;
			_petrifyArea?.Apply(x, num13, num11, shrinkDelta, currentPetrifyFraction, flag6, wasteHeight);
			bool petrifyGhostVisible = (_petrifyArea?.DisplayedDelta ?? 0f) > 0.002f;
			float petrifyPreviewDelta = _petrifyArea?.DisplayedDelta ?? num13;
			_extraStaminaArea?.Apply(x, observedCharacter.data.extraStamina, current.ExtraStaminaDelta, observedCharacter.data.petrifyAmount, flag6, petrifyPreviewDelta, petrifyGhostVisible);
			_rainbowArea?.Apply(current.GrantsInfiniteStaminaOnUse, observedCharacter.infiniteStam);
			Affliction val2 = default(Affliction);
			bool realActive = observedCharacter.refs.afflictions.HasAfflictionType((AfflictionType)16, ref val2);
			_shieldArea?.Apply(current.GrantsInvincibilityOnUse, realActive);
			bool flag7 = (Object)(object)_bar.shield != (Object)null && _bar.shield.gameObject.activeSelf;
			float remainingSeconds2;
			bool flag8 = SpecialStatusDuration.TryGetInvincibilityRemaining(observedCharacter, out remainingSeconds2, out remainingSeconds) && value3;
			if (flag7 && flag8 && (Object)(object)_shieldIconRect != (Object)null)
			{
				if (_invincibilityCountLabel == null && (Object)(object)_font != (Object)null)
				{
					_invincibilityCountLabel = BarLabel.Create(FindUnmaskedAncestorParent((Transform)(object)_shieldIconRect), _font, _fontMaterial);
				}
				_invincibilityCountLabel?.Apply(_shieldIconRect, Mathf.CeilToInt(remainingSeconds2).ToString(), _staminaVanillaForeground, _staminaVanillaOutline, Plugin.Instance.Cfg.BarCountFontScale.Value, 3f);
			}
			else if (!flag7)
			{
				_invincibilityCountLabel?.Hide();
			}
			float remainingFraction;
			bool flag9 = SpecialStatusDuration.TryGetInvincibilityRemaining(observedCharacter, out remainingSeconds, out remainingFraction) && value4;
			if (flag7 && flag9)
			{
				_invincibilityBorderVisual?.Apply(remainingFraction);
			}
			else if (!flag7)
			{
				_invincibilityBorderVisual?.Hide();
			}
			bool flag10 = flag5 && value4;
			if (!observedCharacter.infiniteStam)
			{
				_infiniteStaminaDurationVisual?.Hide();
			}
			else if (flag4)
			{
				_infiniteStaminaDurationVisual?.Hide();
			}
			else if (flag10)
			{
				InfiniteStaminaDurationVisual infiniteStaminaDurationVisual = _infiniteStaminaDurationVisual;
				if (infiniteStaminaDurationVisual != null)
				{
					float remainingFraction2 = num4;
					Rect rect = _bar.maxStaminaBar.rect;
					infiniteStaminaDurationVisual.Apply(remainingFraction2, ((Rect)(ref rect)).width);
				}
			}
			RefreshSpeedBoost(observedCharacter, value3, value4);
		}

		private void RefreshSpeedBoost(Character character, bool showCounts, bool showVisual)
		{
			if (_speedBoostLine == null)
			{
				return;
			}
			if ((!showCounts && !showVisual) || !SpecialStatusDuration.TryGetSpeedBoostAffliction(character, out var affliction) || ((Affliction)affliction).totalTime <= 0f)
			{
				_speedBoostGraceTracker.Reset();
				_speedBoostLine.Hide();
				return;
			}
			float num = Mathf.Max(0f, ((Affliction)affliction).totalTime - ((Affliction)affliction).timeElapsed);
			string text = Mathf.CeilToInt(num) + "s";
			if (_speedBoostGraceTracker.TryGetRemainingGrace((Affliction)(object)affliction, affliction.climbDelay, out var remainingGraceSeconds))
			{
				text = text + "+" + Mathf.CeilToInt(remainingGraceSeconds);
			}
			_speedBoostLine.Apply(num / ((Affliction)affliction).totalTime, text, showVisual, showCounts, Plugin.Instance.Cfg.BarCountFontScale.Value);
		}

		private void GetStatusPreview(Character character, ItemPreview preview, STATUSTYPE type, out float live, out float decrease, out float increase, out float statusCap)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			preview.StatusIncreases.TryGetValue(type, out increase);
			preview.StatusDecreases.TryGetValue(type, out decrease);
			_dynamicHealBreakdown.TryGetValue(type, out var value);
			decrease += value;
			live = character.refs.afflictions.GetCurrentStatus(type);
			if (preview.ClearsCurableStatusOnUse && CurableStatuses.Contains(type))
			{
				decrease = live;
			}
			statusCap = character.refs.afflictions.GetStatusCap(type);
		}

		private float ComputeNetStatusSumDelta(Character character, ItemPreview preview)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			float num = 0f;
			HashSet<STATUSTYPE> netDeltaVisited = _netDeltaVisited;
			netDeltaVisited.Clear();
			foreach (STATUSTYPE key in preview.StatusIncreases.Keys)
			{
				if (netDeltaVisited.Add(key))
				{
					num += NetStatusDelta(character, preview, key);
				}
			}
			foreach (STATUSTYPE key2 in preview.StatusDecreases.Keys)
			{
				if (netDeltaVisited.Add(key2))
				{
					num += NetStatusDelta(character, preview, key2);
				}
			}
			return num;
		}

		private float NetStatusDelta(Character character, ItemPreview preview, STATUSTYPE type)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			GetStatusPreview(character, preview, type, out var live, out var decrease, out var increase, out var _);
			float num = Mathf.Min(decrease, live);
			return increase - num;
		}

		private static Transform FindUnmaskedAncestorParent(Transform start)
		{
			Transform parent = start.parent;
			Transform val = start;
			while ((Object)(object)val != (Object)null)
			{
				if ((Object)(object)((Component)val).GetComponent<Mask>() != (Object)null || (Object)(object)((Component)val).GetComponent<RectMask2D>() != (Object)null)
				{
					parent = val.parent;
				}
				val = val.parent;
			}
			return parent;
		}

		private void HideAll()
		{
			foreach (GhostBadge value in _statusGhosts.Values)
			{
				value.Hide();
			}
			_extraStaminaArea?.Hide();
			_petrifyArea?.Hide();
			_staminaArea?.Release();
			_rainbowArea?.Hide();
			_shieldArea?.Hide();
			_passOutBorderBlink?.Hide();
			_petrifyDeathBorderBlink?.Hide();
			_staminaCountLabel?.Hide();
			_staminaCountdownLabel?.Hide();
			_invincibilityBorderVisual?.Hide();
			_infiniteStaminaDurationVisual?.Hide();
			_invincibilityCountLabel?.Hide();
			_speedBoostLine?.Hide();
			_speedBoostGraceTracker.Reset();
			_infiniteStaminaGraceTracker.Reset();
			_infiniteStaminaUnifiedTimer.Reset();
			_externalInfiniteStamina.Reset();
		}
	}
	internal class GhostExtraStaminaArea
	{
		private static readonly Vector2 ShownExtraBarSize = new Vector2(45f, 45f);

		private const float OutlinePadding = 12f;

		private const float MinOutlineWidth = 20f;

		private const float HiddenThreshold = 0.0001f;

		private const float SeamOverlap = 3f;

		private const float RightEdgePaddingGhostOnly = 9f;

		private const float RightEdgePaddingWithReal = 1f;

		private const float ShrinkLerpStep100Fps = 0.14f;

		private const float GrowLerpStep100Fps = 0.6f;

		private const float DisplayedDeltaSnapEpsilon = 0.003f;

		private readonly RectTransform _extraBar;

		private readonly RectTransform _extraBarStamina;

		private readonly RectTransform _extraBarOutline;

		private readonly Image _extraStaminaIcon;

		private readonly GhostSegment _fillGhost;

		private readonly GhostIcon _icon;

		private readonly WasteIndicator _waste;

		private readonly BarLabel _ghostCountLabel;

		private readonly BarLabel _realCountLabel;

		private readonly Color _vanillaForeground;

		private readonly Color _vanillaOutline;

		private readonly Color _ghostForeground;

		private readonly Color _ghostOutline;

		private readonly Transform _fillParent;

		private readonly Vector3[] _cornerBuffer = (Vector3[])(object)new Vector3[4];

		private Tween _tween;

		private float _tweenTarget;

		private float _animatedDelta;

		private float _displayedDelta;

		private float _lastRealExtraStamina;

		private bool _catchUpWidthControl;

		private float _catchUpDisplayedWidth;

		private float _displayedOutlineWidth;

		private bool _hasDisplayedOutlineWidth;

		internal bool IsValid
		{
			get
			{
				if ((Object)(object)_extraBar != (Object)null && (Object)(object)_extraBarStamina != (Object)null && (Object)(object)_extraBarOutline != (Object)null && _fillGhost.IsValid && (_icon == null || _icon.IsValid) && _waste.IsValid && _ghostCountLabel.IsValid)
				{
					return _realCountLabel.IsValid;
				}
				return false;
			}
		}

		internal GhostExtraStaminaArea(RectTransform extraBar, RectTransform extraBarStamina, RectTransform extraBarOutline, Image extraStaminaIcon, TMP_FontAsset font, Material fontMaterial)
		{
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			_extraBar = extraBar;
			_extraBarStamina = extraBarStamina;
			_extraBarOutline = extraBarOutline;
			_extraStaminaIcon = extraStaminaIcon;
			_fillParent = ((Transform)extraBarStamina).parent;
			_fillGhost = GhostSegment.Create(_fillParent, extraBarStamina);
			_icon = (((Object)(object)extraStaminaIcon != (Object)null) ? GhostIcon.Create(extraStaminaIcon) : null);
			Color val = WasteIndicator.SampleFillColor(((Component)extraBarStamina).gameObject, null);
			_waste = WasteIndicator.Create(_fillParent, val);
			_ghostCountLabel = BarLabel.Create(_fillParent, font, fontMaterial);
			_realCountLabel = BarLabel.Create(_fillParent, font, fontMaterial);
			BarLabel.CountColors(val, ghost: false, out _vanillaForeground, out _vanillaOutline);
			BarLabel.CountColors(val, ghost: true, out _ghostForeground, out _ghostOutline);
		}

		internal void Apply(float fullLocalWidth, float realExtraStamina, float delta, int petrifyAmount, bool petrifyActive, float petrifyPreviewDelta, bool petrifyGhostVisible)
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0247: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0340: Unknown result type (might be due to invalid IL or missing references)
			//IL_034a: Unknown result type (might be due to invalid IL or missing references)
			//IL_03af: Unknown result type (might be due to invalid IL or missing references)
			//IL_0410: Unknown result type (might be due to invalid IL or missing references)
			//IL_041a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0549: Unknown result type (might be due to invalid IL or missing references)
			//IL_054f: Unknown result type (might be due to invalid IL or missing references)
			float num = delta;
			float num2 = realExtraStamina - _lastRealExtraStamina;
			if (num2 > 0.0001f)
			{
				_animatedDelta = Mathf.Max(0f, _animatedDelta - num2);
				Tween tween = _tween;
				if (tween != null)
				{
					TweenExtensions.Kill(tween, false);
				}
				_tweenTarget = _animatedDelta;
				delta = 0f;
				_catchUpWidthControl = true;
				_catchUpDisplayedWidth = _extraBarStamina.sizeDelta.x;
			}
			_lastRealExtraStamina = realExtraStamina;
			float num3 = Mathf.Max(0f, 1f - (float)petrifyAmount * 0.01f);
			float num4 = Mathf.Max(0f, num3 - Mathf.Max(0f, petrifyPreviewDelta));
			float num5 = Mathf.Max(0f, num4 - Mathf.Max(0f, realExtraStamina));
			float num6 = ((delta > 0f) ? Mathf.Min(delta, num5) : 0f);
			if (!Mathf.Approximately(num6, _tweenTarget))
			{
				bool flag = num6 > _animatedDelta;
				Tween tween2 = _tween;
				if (tween2 != null)
				{
					TweenExtensions.Kill(tween2, false);
				}
				_tweenTarget = num6;
				_tween = (Tween)(object)TweenSettingsExtensions.SetEase<TweenerCore<float, float, FloatOptions>>(DOTween.To((DOGetter<float>)(() => _animatedDelta), (DOSetter<float>)delegate(float animatedDelta)
				{
					_animatedDelta = animatedDelta;
				}, num6, flag ? 0.46f : 0.36f), (Ease)(flag ? 9 : 8));
			}
			_displayedDelta = ((Mathf.Abs(_animatedDelta - _tweenTarget) < 0.003f) ? _tweenTarget : _animatedDelta);
			float num7 = Mathf.Max(0f, realExtraStamina) * fullLocalWidth;
			float num8 = Mathf.Min(num7, num4 * fullLocalWidth);
			bool flag2 = num8 < num7 - 0.01f;
			float settledLocalWidth = (flag2 ? num8 : num7);
			if (num6 <= 0f && _animatedDelta < 0.0001f && !flag2 && !_catchUpWidthControl && !petrifyGhostVisible)
			{
				_fillGhost.Hide();
				_icon?.Hide();
				_waste.Hide();
				_ghostCountLabel.Hide();
				ApplyRealCountLabel(realExtraStamina, realExtraStamina, settledLocalWidth);
				if (realExtraStamina <= 0f && !petrifyActive)
				{
					ResetOutlineToResting();
				}
				else
				{
					_hasDisplayedOutlineWidth = false;
				}
				return;
			}
			((Component)_extraBar).gameObject.SetActive(true);
			_extraBar.sizeDelta = ShownExtraBarSize;
			bool active = num7 > 6.1f;
			((Component)_extraBarStamina).gameObject.SetActive(active);
			if ((Object)(object)_extraStaminaIcon != (Object)null)
			{
				((Component)_extraStaminaIcon).gameObject.SetActive(active);
			}
			if (realExtraStamina > 0f)
			{
				_icon?.Hide();
			}
			else if (num6 > 0f)
			{
				_icon?.Show();
			}
			else
			{
				_icon?.Hide();
			}
			if (flag2)
			{
				_catchUpWidthControl = false;
				_extraBarStamina.sizeDelta = new Vector2(num8, _extraBarStamina.sizeDelta.y);
			}
			else if (_catchUpWidthControl)
			{
				float num9 = AnimUtil.LerpStep(0.14f);
				_catchUpDisplayedWidth = Mathf.Lerp(_catchUpDisplayedWidth, num7, num9);
				_extraBarStamina.sizeDelta = new Vector2(_catchUpDisplayedWidth, _extraBarStamina.sizeDelta.y);
				if (Mathf.Abs(_catchUpDisplayedWidth - num7) < 0.5f)
				{
					_catchUpWidthControl = false;
				}
			}
			float num10 = _animatedDelta * fullLocalWidth;
			bool num11 = petrifyActive || petrifyGhostVisible;
			float num12 = (num11 ? fullLocalWidth : (num7 + num10));
			float num13 = Mathf.Max(20f, num12 + 12f);
			if (!_hasDisplayedOutlineWidth)
			{
				_displayedOutlineWidth = _extraBarOutline.sizeDelta.x;
				_hasDisplayedOutlineWidth = true;
			}
			float num14 = ((num13 > _displayedOutlineWidth) ? AnimUtil.LerpStep(0.6f) : AnimUtil.LerpStep(0.14f));
			_displayedOutlineWidth = Mathf.Lerp(_displayedOutlineWidth, num13, num14);
			_extraBarOutline.sizeDelta = new Vector2(_displayedOutlineWidth, _extraBarOutline.sizeDelta.y);
			_extraBarStamina.GetWorldCorners(_cornerBuffer);
			float x = _cornerBuffer[2].x;
			float num15 = Mathf.Min(3f, num10);
			float num16 = ((realExtraStamina > 0f) ? 1f : 9f);
			float num17 = (num11 ? 0f : Mathf.Min(num16, num10 + num15));
			_fillGhost.Apply(x - num15, num10 + num15 - num17);
			if (Plugin.Instance.Cfg.EnableWasteIndicator.Value && num6 > 0.0005f && Mathf.Max(0f, num) - num6 > 0.0005f)
			{
				_waste.Apply(_fillGhost.Rtf, _extraBarStamina, WasteIndicator.MeasureHeight(_extraBarStamina), rightEdge: true);
			}
			else
			{
				_waste.Hide();
			}
			if (Plugin.Instance.Cfg.ShowGhostBarCounts.Value && _displayedDelta > 0.0005f)
			{
				_ghostCountLabel.Apply(_fillGhost.Rtf, BarLabel.FormatCount(_displayedDelta), _ghostForeground, _ghostOutline, Plugin.Instance.Cfg.BarCountFontScale.Value);
			}
			else
			{
				_ghostCountLabel.Hide();
			}
			float afterExtraStamina = Mathf.Min(realExtraStamina + num6, num4);
			ApplyRealCountLabel(realExtraStamina, afterExtraStamina, settledLocalWidth);
		}

		private void ResetOutlineToResting()
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			_displayedOutlineWidth = 20f;
			_hasDisplayedOutlineWidth = true;
			_extraBarOutline.sizeDelta = new Vector2(20f, _extraBarOutline.sizeDelta.y);
		}

		private void ApplyRealCountLabel(float realExtraStamina, float afterExtraStamina, float settledLocalWidth)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			if (Plugin.Instance.Cfg.ShowVanillaBarCounts.Value && realExtraStamina > 0.0005f)
			{
				float fitWidthOverride = settledLocalWidth * ((Transform)_extraBarStamina).lossyScale.x;
				_realCountLabel.ApplyTransition(_extraBarStamina, realExtraStamina, afterExtraStamina, _vanillaForeground, _vanillaOutline, Plugin.Instance.Cfg.BarCountFontScale.Value, fitWidthOverride);
			}
			else
			{
				_realCountLabel.Hide();
			}
		}

		internal void Hide()
		{
			Tween tween = _tween;
			if (tween != null)
			{
				TweenExtensions.Kill(tween, false);
			}
			_tween = null;
			_tweenTarget = 0f;
			_animatedDelta = 0f;
			_displayedDelta = 0f;
			_lastRealExtraStamina = 0f;
			_catchUpWidthControl = false;
			Character observedCharacter = Character.observedCharacter;
			if ((Object)(object)observedCharacter != (Object)null && (observedCharacter.data.extraStamina > 0f || observedCharacter.data.petrifyAmount > 0))
			{
				_hasDisplayedOutlineWidth = false;
			}
			else
			{
				ResetOutlineToResting();
			}
			_fillGhost.Hide();
			_icon?.Hide();
			_waste.Hide();
			_ghostCountLabel.Hide();
			_realCountLabel.Hide();
		}
	}
	internal class GhostIcon
	{
		private readonly RectTransform _rtf;

		internal bool IsValid => (Object)(object)_rtf != (Object)null;

		private GhostIcon(RectTransform rtf)
		{
			_rtf = rtf;
		}

		internal static GhostIcon Create(Image template, Transform reparentTo = null)
		{
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = Object.Instantiate<GameObject>(((Component)template).gameObject, ((Component)template).transform.parent);
			((Object)val).name = ((Object)template).name + " (EffectPreview Ghost)";
			if ((Object)(object)reparentTo != (Object)null)
			{
				val.transform.SetParent(reparentTo, true);
			}
			Image[] componentsInChildren = val.GetComponentsInChildren<Image>(true);
			foreach (Image obj in componentsInChildren)
			{
				Color color = Color.Lerp(((Graphic)obj).color, Color.white, 0.4f);
				color.a *= 0.65f;
				((Graphic)obj).color = color;
			}
			val.transform.localScale = Vector3.one;
			GhostOwnershipTag.Attach(val);
			val.SetActive(false);
			return new GhostIcon(val.GetComponent<RectTransform>());
		}

		internal void Show()
		{
			Transform val = ((Component)_rtf).transform;
			while ((Object)(object)val != (Object)null && !((Component)val).gameObject.activeSelf)
			{
				((Component)val).gameObject.SetActive(true);
				val = val.parent;
			}
		}

		internal void Hide()
		{
			if ((Object)(object)_rtf != (Object)null)
			{
				((Component)_rtf).gameObject.SetActive(false);
			}
		}
	}
	internal class GhostInvincibilityShield
	{
		private readonly GameObject _ghost;

		internal bool IsValid => (Object)(object)_ghost != (Object)null;

		private GhostInvincibilityShield(GameObject ghost)
		{
			_ghost = ghost;
		}

		internal static GhostInvincibilityShield Create(GameObject realShield)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = Object.Instantiate<GameObject>(realShield, realShield.transform.parent);
			((Object)val).name = ((Object)realShield).name + " (EffectPreview Ghost)";
			Image[] componentsInChildren = val.GetComponentsInChildren<Image>(true);
			foreach (Image obj in componentsInChildren)
			{
				Color color = Color.Lerp(((Graphic)obj).color, Color.white, 0.4f);
				color.a *= 0.65f;
				((Graphic)obj).color = color;
			}
			val.transform.SetAsLastSibling();
			GhostOwnershipTag.Attach(val);
			val.SetActive(false);
			return new GhostInvincibilityShield(val);
		}

		internal void Apply(bool show, bool realActive)
		{
			_ghost.SetActive(show && !realActive);
		}

		internal void Hide()
		{
			if ((Object)(object)_ghost != (Object)null)
			{
				_ghost.SetActive(false);
			}
		}
	}
	internal class GhostJetpackFuelGauge : MonoBehaviour
	{
		private BackpackWheel _wheel;

		private Transform _sourceArrow;

		private RectTransform _ghostRtf;

		private void LateUpdate()
		{
			if (!Plugin.Instance.Cfg.EnableJetpackPreview.Value || !TryGetWheel())
			{
				Hide();
			}
			else
			{
				Safe.Run("GhostJetpackFuelGauge.Refresh", Refresh);
			}
		}

		private bool TryGetWheel()
		{
			GUIManager instance = GUIManager.instance;
			if ((Object)(object)instance == (Object)null || (Object)(object)instance.backpackWheel == (Object)null)
			{
				return false;
			}
			_wheel = instance.backpackWheel;
			return true;
		}

		private void Refresh()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Invalid comparison between Unknown and I4
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0164: Unknown result type (might be due to invalid IL or missing references)
			if (!((Component)_wheel).gameObject.activeSelf || (int)_wheel.backpackType != 3 || (Object)(object)_wheel.fuelGaugeArrow == (Object)null || !_wheel.chosenSlice.IsSome || !_wheel.chosenSlice.Value.isJetpackFuelSlice)
			{
				Hide();
				return;
			}
			Character localCharacter = Character.localCharacter;
			Item val = (((Object)(object)localCharacter != (Object)null) ? localCharacter.data.currentItem : null);
			if ((Object)(object)val == (Object)null)
			{
				Hide();
				return;
			}
			if ((Object)(object)_ghostRtf == (Object)null || (Object)(object)_sourceArrow != (Object)(object)_wheel.fuelGaugeArrow)
			{
				Build(_wheel.fuelGaugeArrow);
			}
			if (!((Object)(object)_ghostRtf == (Object)null))
			{
				float num = 0f;
				ItemInstanceData itemInstanceData = ((BackpackReference)(ref _wheel.backpack)).GetItemInstanceData();
				FloatItemData val2 = default(FloatItemData);
				if (itemInstanceData != null && itemInstanceData.TryGetDataEntry<FloatItemData>((DataEntryKey)11, ref val2))
				{
					num = val2.Value;
				}
				int num2 = JetpackFuelPreviewCalculator.ComputeAddedFuel(val);
				float num3 = Mathf.Clamp01(num + (float)num2 / 100f);
				((Component)_ghostRtf).gameObject.SetActive(true);
				((Transform)_ghostRtf).position = _sourceArrow.position;
				((Transform)_ghostRtf).localRotation = Quaternion.Euler(0f, 0f, 50f - num3 * 100f);
			}
		}

		private void Build(Transform arrow)
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			_sourceArrow = arrow;
			GameObject val = Object.Instantiate<GameObject>(((Component)arrow).gameObject, arrow.parent);
			((Object)val).name = ((Object)arrow).name + " (EffectPreview Ghost)";
			Image[] componentsInChildren = val.GetComponentsInChildren<Image>(true);
			foreach (Image obj in componentsInChildren)
			{
				Color color = Color.Lerp(((Graphic)obj).color, Color.white, 0.4f);
				color.a *= 0.65f;
				((Graphic)obj).color = color;
			}
			val.transform.localScale = Vector3.one;
			_ghostRtf = val.GetComponent<RectTransform>();
			val.SetActive(false);
		}

		private void Hide()
		{
			if ((Object)(object)_ghostRtf != (Object)null)
			{
				((Component)_ghostRtf).gameObject.SetActive(false);
			}
		}
	}
	internal class GhostPetrifyArea
	{
		private const float SeamOverlap = 6f;

		private const float RightEdgePadding = 6f;

		private const float HiddenThreshold = 0.0001f;

		private const float LerpStep100Fps = 0.09f;

		private const float IconHideDelay = 0.2f;

		private const float DisplayedDeltaSnapEpsilon = 0.003f;

		private readonly RectTransform _petrifyRtf;

		private readonly GhostSegment _ghost;

		private readonly GhostSegment _decreaseGhost;

		private readonly GhostIcon _icon;

		private readonly WasteIndicator _increaseWaste;

		private readonly WasteIndicator _decreaseWaste;

		private readonly BarLabel _increaseCountLabel;

		private readonly BarLabel _decreaseCountLabel;

		private readonly BarLabel _realCountLabel;

		private readonly Color _vanillaForeground;

		private readonly Color _vanillaOutline;

		private readonly Color _ghostForeground;

		private readonly Color _ghostOutline;

		private readonly Vector3[] _cornerBuffer = (Vector3[])(object)new Vector3[4];

		private Tween _tween;

		private float _tweenTarget;

		private float _animatedDelta;

		private float _displayedDelta;

		private float _timeSinceTargetZero;

		private float _displayedShrinkWidth;

		internal bool IsValid
		{
			get
			{
				if ((Object)(object)_petrifyRtf != (Object)null && _ghost.IsValid && _decreaseGhost.IsValid && (_icon == null || _icon.IsValid) && _increaseWaste.IsValid && _decreaseWaste.IsValid && _increaseCountLabel.IsValid && _decreaseCountLabel.IsValid)
				{
					return _realCountLabel.IsValid;
				}
				return false;
			}
		}

		internal float DisplayedDelta => _animatedDelta;

		internal GhostPetrifyArea(BarAffliction petrifyAffliction, TMP_FontAsset font, Material fontMaterial)
		{
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			_petrifyRtf = petrifyAffliction.rtf;
			_ghost = GhostSegment.Create(((Transform)_petrifyRtf).parent, _petrifyRtf);
			_decreaseGhost = GhostSegment.Create(((Transform)_petrifyRtf).parent, _petrifyRtf, isRemoval: true);
			_icon = (((Object)(object)petrifyAffliction.icon != (Object)null) ? GhostIcon.Create(petrifyAffliction.icon, ((Transform)_petrifyRtf).parent) : null);
			Color color = WasteIndicator.SampleFillColor(((Component)_petrifyRtf).gameObject, petrifyAffliction.icon);
			_increaseWaste = WasteIndicator.Create(((Transform)_petrifyRtf).parent, color);
			_decreaseWaste = WasteIndicator.Create(((Transform)_petrifyRtf).parent, color);
			_increaseCountLabel = BarLabel.Create(((Transform)_petrifyRtf).parent, font, fontMaterial);
			_decreaseCountLabel = BarLabel.Create(((Transform)_petrifyRtf).parent, font, fontMaterial);
			_realCountLabel = BarLabel.Create(((Transform)_petrifyRtf).parent, font, fontMaterial);
			BarLabel.PaletteCountColors(BarLabel.PetrifyText, BarLabel.PetrifyOutline, ghost: false, out _vanillaForeground, out _vanillaOutline);
			BarLabel.PaletteCountColors(BarLabel.PetrifyText, BarLabel.PetrifyOutline, ghost: true, out _ghostForeground, out _ghostOutline);
		}

		internal void Apply(float fullLocalWidth, float delta, float rawDelta, float shrinkDelta, float currentPetrifyFraction, bool realPetrifyActive, float wasteHeight)
		{
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_0492: Unknown result type (might be due to invalid IL or missing references)
			//IL_0498: Unknown result type (might be due to invalid IL or missing references)
			float num = AnimUtil.LerpStep(0.09f);
			float num2 = Mathf.Clamp(shrinkDelta, 0f, currentPetrifyFraction);
			float num3 = fullLocalWidth * num2;
			_displayedShrinkWidth = Mathf.Lerp(_displayedShrinkWidth, num3, num);
			float currentPetrifyFraction2 = currentPetrifyFraction;
			if (num2 > 0.0001f || _displayedShrinkWidth > 0.5f)
			{
				float num4 = fullLocalWidth * currentPetrifyFraction;
				float num5 = Mathf.Max(0f, num4 - _displayedShrinkWidth);
				currentPetrifyFraction2 = ((fullLocalWidth > 0f) ? (num5 / fullLocalWidth) : currentPetrifyFraction);
				((Component)_petrifyRtf).gameObject.SetActive(true);
				_petrifyRtf.sizeDelta = new Vector2(num5, _petrifyRtf.sizeDelta.y);
				_petrifyRtf.GetWorldCorners(_cornerBuffer);
				float num6 = _cornerBuffer[2].x - num4;
				_decreaseGhost.Apply(num6 + _displayedShrinkWidth, _displayedShrinkWidth);
				if (Plugin.Instance.Cfg.EnableWasteIndicator.Value && num2 > 0.0005f && shrinkDelta - num2 > 0.0005f)
				{
					_decreaseWaste.Apply(_decreaseGhost.Rtf, _petrifyRtf, wasteHeight, rightEdge: false);
				}
				else
				{
					_decreaseWaste.Hide();
				}
				if (Plugin.Instance.Cfg.ShowGhostBarCounts.Value && _displayedShrinkWidth > 0.5f)
				{
					_decreaseCountLabel.Apply(_decreaseGhost.Rtf, BarLabel.FormatCount(num2), _ghostForeground, _ghostOutline, Plugin.Instance.Cfg.BarCountFontScale.Value);
				}
				else
				{
					_decreaseCountLabel.Hide();
				}
			}
			els