Decompiled source of BubbleGauge v1.0.1

plugins/BubbleGauge.dll

Decompiled a week ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using BubbleGauge.Logic;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("assembly_utils")]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("BubbleGauge")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: AssemblyInformationalVersion("1.0.1+8afb1ca387b5ba50a88e69d7188edf06c12f9a1e")]
[assembly: AssemblyProduct("BubbleGauge")]
[assembly: AssemblyTitle("BubbleGauge")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.1.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace BubbleGauge
{
	public enum PulseStyle
	{
		Dim,
		Flash
	}
	internal sealed class GaugeSettings
	{
		public BarSize BarSize;

		public float HeightPer100Hp;

		public float HpPerTick;

		public bool LiquidAnimation;

		public float OffsetX;

		public float OffsetY;

		public float Scale = 1f;

		public bool ShowHpNumber = true;

		public bool ShowTimeNumber = true;

		public Color BubbleColor;

		public Color MercuryColor;
	}
	internal sealed class GaugeView
	{
		private sealed class Gauge
		{
			private const float LightTileW = 48f;

			private const float LightTileH = 96f;

			private const float DarkTileW = 72f;

			private const float DarkTileH = 140f;

			private const float LiquidStrength = 0.5f;

			private readonly RectTransform _container;

			private readonly CanvasGroup _group;

			private readonly Image _flash;

			private readonly RectTransform _fill;

			private readonly RawImage _liquid;

			private readonly RawImage _lightLayer;

			private readonly RawImage _darkLayer;

			private readonly List<RectTransform> _ticks = new List<RectTransform>();

			private readonly TextMeshProUGUI _number;

			private readonly float _seed;

			private int _shownNumber = int.MinValue;

			public float Height { get; private set; }

			public Gauge(string name, RectTransform root, TextMeshProUGUI template, float seed)
			{
				//IL_0037: 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_00a2: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
				//IL_0120: 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_0176: Unknown result type (might be due to invalid IL or missing references)
				//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
				//IL_01de: Unknown result type (might be due to invalid IL or missing references)
				//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
				//IL_0208: Unknown result type (might be due to invalid IL or missing references)
				//IL_021d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0232: 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)
				//IL_02b6: Unknown result type (might be due to invalid IL or missing references)
				//IL_02bb: Unknown result type (might be due to invalid IL or missing references)
				//IL_02db: Unknown result type (might be due to invalid IL or missing references)
				//IL_02e0: Unknown result type (might be due to invalid IL or missing references)
				_seed = seed;
				_container = NewRect(name, (Transform)(object)root);
				_container.pivot = Vector2.zero;
				AddImage(_container, Background);
				_group = ((Component)_container).gameObject.AddComponent<CanvasGroup>();
				_group.interactable = false;
				_group.blocksRaycasts = false;
				_fill = Stretch(NewRect("Liquid", (Transform)(object)_container));
				_liquid = AddRaw(_fill, null, Color.white);
				_lightLayer = AddRaw(Stretch(NewRect("Swirl", (Transform)(object)_fill)), Liquid.Noise(light: true), new Color(1f, 1f, 1f, 0.5f));
				_darkLayer = AddRaw(Stretch(NewRect("Shade", (Transform)(object)_fill)), Liquid.Noise(light: false), new Color(1f, 1f, 1f, 0.5f));
				RectTransform val = Stretch(NewRect("Flash", (Transform)(object)_container));
				AddImage(val, Color.white);
				_flash = ((Component)val).GetComponent<Image>();
				((Graphic)_flash).color = new Color(1f, 1f, 1f, 0f);
				_number = (((Object)(object)template != (Object)null) ? Object.Instantiate<TextMeshProUGUI>(template, (Transform)(object)_container) : ((Component)NewRect("Number", (Transform)(object)_container)).gameObject.AddComponent<TextMeshProUGUI>());
				((Object)_number).name = "Number";
				RectTransform rectTransform = ((TMP_Text)_number).rectTransform;
				((Transform)rectTransform).localRotation = Quaternion.identity;
				((Transform)rectTransform).localScale = Vector3.one;
				rectTransform.anchorMin = new Vector2(0f, 0f);
				rectTransform.anchorMax = new Vector2(1f, 0f);
				rectTransform.pivot = new Vector2(0.5f, 0f);
				rectTransform.sizeDelta = new Vector2(-2f, 22f);
				rectTransform.anchoredPosition = new Vector2(0f, 2f);
				((TMP_Text)_number).enableAutoSizing = true;
				((TMP_Text)_number).fontSizeMin = 10f;
				((TMP_Text)_number).fontSizeMax = 18f;
				((TMP_Text)_number).fontStyle = (FontStyles)1;
				((TMP_Text)_number).alignment = (TextAlignmentOptions)1026;
				((TMP_Text)_number).textWrappingMode = (TextWrappingModes)0;
				((TMP_Text)_number).richText = false;
				((TMP_Text)_number).faceColor = Color32.op_Implicit(Color.white);
				((TMP_Text)_number).outlineWidth = 0f;
				((Graphic)_number).color = Color32.op_Implicit(NumberColor);
				((Graphic)_number).raycastTarget = false;
				Material fontSharedMaterial = ((TMP_Text)_number).fontSharedMaterial;
				Plugin.DebugLog(name + " number: font='" + (((Object)(object)((TMP_Text)_number).font != (Object)null) ? ((Object)((TMP_Text)_number).font).name : "none") + "' material='" + (((Object)(object)fontSharedMaterial != (Object)null) ? ((Object)fontSharedMaterial).name : "none") + "' shader='" + (((Object)(object)fontSharedMaterial != (Object)null && (Object)(object)fontSharedMaterial.shader != (Object)null) ? ((Object)fontSharedMaterial.shader).name : "none") + "' " + $"copiedFromHud={(Object)(object)template != (Object)null}");
			}

			public void SetDim(float alpha)
			{
				_group.alpha = alpha;
			}

			public void SetLook(Texture2D gradient, bool showNumber)
			{
				if ((Object)(object)_liquid.texture != (Object)(object)gradient)
				{
					_liquid.texture = (Texture)(object)gradient;
				}
				if (((Component)_number).gameObject.activeSelf != showNumber)
				{
					((Component)_number).gameObject.SetActive(showNumber);
				}
			}

			public void SetFlash(float strength)
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_002e: Unknown result type (might be due to invalid IL or missing references)
				if (!Mathf.Approximately(((Graphic)_flash).color.a, strength))
				{
					((Graphic)_flash).color = new Color(1f, 1f, 1f, strength);
				}
			}

			public void Place(float x, float width)
			{
				//IL_000c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0023: Unknown result type (might be due to invalid IL or missing references)
				_container.anchoredPosition = new Vector2(x, 0f);
				_container.sizeDelta = new Vector2(width, Height);
			}

			public void SetHeight(float height)
			{
				//IL_0013: Unknown result type (might be due to invalid IL or missing references)
				//IL_001e: Unknown result type (might be due to invalid IL or missing references)
				Height = height;
				_container.sizeDelta = new Vector2(_container.sizeDelta.x, height);
			}

			public void SetFill(float fraction)
			{
				//IL_000c: Unknown result type (might be due to invalid IL or missing references)
				_fill.anchorMax = new Vector2(1f, fraction);
			}

			public void SetTicks(float max, float step, float unitsPerValue)
			{
				//IL_0029: 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_0053: 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_0073: Unknown result type (might be due to invalid IL or missing references)
				//IL_0105: Unknown result type (might be due to invalid IL or missing references)
				int num = GaugeMath.TickCount(max, step);
				while (_ticks.Count < num)
				{
					RectTransform val = NewRect("Tick", (Transform)(object)_container);
					val.anchorMin = new Vector2(0f, 0f);
					val.anchorMax = new Vector2(1f, 0f);
					val.pivot = new Vector2(0.5f, 0.5f);
					val.sizeDelta = new Vector2(-2f, 1.5f);
					AddImage(val, TickColor);
					((Transform)val).SetSiblingIndex(((TMP_Text)_number).transform.GetSiblingIndex());
					_ticks.Add(val);
				}
				for (int i = 0; i < _ticks.Count; i++)
				{
					bool flag = i < num;
					if (((Component)_ticks[i]).gameObject.activeSelf != flag)
					{
						((Component)_ticks[i]).gameObject.SetActive(flag);
					}
					if (flag)
					{
						_ticks[i].anchoredPosition = new Vector2(0f, (float)(i + 1) * step * unitsPerValue);
					}
				}
			}

			public void SetNumber(int value, Func<float, string> format)
			{
				if (value != _shownNumber)
				{
					_shownNumber = value;
					((TMP_Text)_number).text = ((format != null) ? format(value) : value.ToString());
				}
			}

			public void AnimateLiquid(float time)
			{
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_000b: 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_009e: Unknown result type (might be due to invalid IL or missing references)
				Rect rect = _fill.rect;
				_lightLayer.uvRect = new Rect(_seed * 0.13f, _seed * 0.07f - time * 0.1f, ((Rect)(ref rect)).width / 48f, ((Rect)(ref rect)).height / 96f);
				_darkLayer.uvRect = new Rect(_seed * 0.29f + time * 0.03f, _seed * 0.17f + time * 0.06f, ((Rect)(ref rect)).width / 72f, ((Rect)(ref rect)).height / 140f);
			}

			private static void AddImage(RectTransform rt, Color color)
			{
				//IL_000c: Unknown result type (might be due to invalid IL or missing references)
				Image obj = ((Component)rt).gameObject.AddComponent<Image>();
				((Graphic)obj).color = color;
				((Graphic)obj).raycastTarget = false;
			}

			private static RawImage AddRaw(RectTransform rt, Texture2D texture, Color tint)
			{
				//IL_0013: Unknown result type (might be due to invalid IL or missing references)
				RawImage obj = ((Component)rt).gameObject.AddComponent<RawImage>();
				obj.texture = (Texture)(object)texture;
				((Graphic)obj).color = tint;
				((Graphic)obj).raycastTarget = false;
				return obj;
			}
		}

		private const float FullHeight = 150f;

		private const float MinHeight = 40f;

		private const float Gap = 4f;

		private const float LiftAboveIcon = 6f;

		private const float MinTickGap = 9f;

		private const float ResizeSpeed = 300f;

		private static readonly float[] HpTickSteps = new float[3] { 50f, 100f, 200f };

		private static readonly float[] TimeTickSteps = new float[3] { 10f, 30f, 60f };

		private static readonly Color Background = new Color(0f, 0f, 0f, 0.55f);

		private static readonly Color TickColor = new Color(0f, 0f, 0f, 0.45f);

		private static readonly Color32 NumberColor = new Color32((byte)28, (byte)18, (byte)4, byte.MaxValue);

		private const float NumberBottom = 2f;

		private const float NumberHeight = 22f;

		private const float TopMargin = 24f;

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

		private const float DimDepth = 0.65f;

		private const float FlashStrength = 0.7f;

		private readonly Hud _hud;

		private readonly RectTransform _root;

		private readonly CanvasGroup _rootGroup;

		private readonly Gauge _bubble;

		private readonly Gauge _mercury;

		public float HpTickStep { get; private set; }

		public float TimeTickStep { get; private set; }

		public bool IsAlive
		{
			get
			{
				if ((Object)(object)_root != (Object)null)
				{
					return (Object)(object)_hud != (Object)null;
				}
				return false;
			}
		}

		private GaugeView(Hud hud)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			_hud = hud;
			Transform parent = ((Transform)hud.m_gpRoot).parent;
			_root = NewRect("BubbleGauge", parent);
			_root.pivot = Vector2.zero;
			_rootGroup = ((Component)_root).gameObject.AddComponent<CanvasGroup>();
			_rootGroup.interactable = false;
			_rootGroup.blocksRaycasts = false;
			TMP_Text healthText = hud.m_healthText;
			TextMeshProUGUI template = (TextMeshProUGUI)(object)((healthText is TextMeshProUGUI) ? healthText : null);
			_bubble = new Gauge("BubbleBar", _root, template, 3f);
			_mercury = new Gauge("MercuryTube", _root, template, 11f);
			SetVisible(visible: false);
		}

		public static GaugeView TryCreate()
		{
			Hud instance = Hud.instance;
			if ((Object)(object)instance == (Object)null || (Object)(object)instance.m_gpRoot == (Object)null || (Object)(object)instance.m_healthBarRoot == (Object)null)
			{
				return null;
			}
			return new GaugeView(instance);
		}

		public void SetVisible(bool visible)
		{
			if (((Component)_root).gameObject.activeSelf != visible)
			{
				((Component)_root).gameObject.SetActive(visible);
			}
		}

		public void Show(BarrierReading r, GaugeSettings s)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			bool num = !((Component)_root).gameObject.activeSelf;
			SetVisible(visible: true);
			Rect rect = _hud.m_healthBarRoot.rect;
			float height = ((Rect)(ref rect)).height;
			float num2 = Mathf.Max(0.1f, s.Scale);
			Layout(s.OffsetX, s.OffsetY, num2);
			_bubble.Place(0f, height);
			_mercury.Place(height + 4f, height);
			_bubble.SetLook(Liquid.Gradient(s.BubbleColor), s.ShowHpNumber);
			_mercury.SetLook(Liquid.Gradient(s.MercuryColor), s.ShowTimeNumber);
			float num3 = GaugeMath.BubbleBarHeight(s.BarSize, r.Max, s.HeightPer100Hp, 150f, 40f);
			rect = ((RectTransform)((Transform)_root).parent).rect;
			float num4 = (((Rect)(ref rect)).yMax - ((Transform)_root).localPosition.y - 24f) / num2;
			num3 = Mathf.Min(num3, Mathf.Max(40f, num4));
			float num5 = (num ? num3 : GaugeMath.Approach(_bubble.Height, num3, 300f * Time.deltaTime));
			_bubble.SetHeight(num5);
			_bubble.SetFill(GaugeMath.Fill(r.Remaining, r.Max));
			float unitsPerValue = ((r.Max > 0f) ? (num5 / r.Max) : 0f);
			float num6 = ((s.BarSize == BarSize.Grow) ? s.HpPerTick : GaugeMath.TickStep(HpTickSteps, unitsPerValue, 9f));
			_bubble.SetTicks(r.Max, num6, unitsPerValue);
			HpTickStep = num6;
			_bubble.SetNumber(Mathf.CeilToInt(r.Remaining), null);
			_mercury.SetHeight(150f);
			_mercury.SetFill(GaugeMath.Fill(r.TimeLeft, r.Duration));
			float unitsPerValue2 = ((r.Duration > 0f) ? (150f / r.Duration) : 0f);
			TimeTickStep = GaugeMath.TickStep(TimeTickSteps, unitsPerValue2, 9f);
			_mercury.SetTicks(r.Duration, TimeTickStep, unitsPerValue2);
			_mercury.SetNumber(Mathf.CeilToInt(r.TimeLeft), TimeText.Format);
			float time = (s.LiquidAnimation ? Time.time : 0f);
			_bubble.AnimateLiquid(time);
			_mercury.AnimateLiquid(time);
		}

		public void ApplyPulse(PulseStyle style, float bothPulse, float tubePulse, float alpha)
		{
			if (style == PulseStyle.Dim)
			{
				_rootGroup.alpha = alpha * (1f - 0.65f * bothPulse);
				_mercury.SetDim(1f - 0.65f * tubePulse);
				_bubble.SetFlash(0f);
				_mercury.SetFlash(0f);
			}
			else
			{
				_rootGroup.alpha = alpha;
				_mercury.SetDim(1f);
				_bubble.SetFlash(0.7f * bothPulse);
				_mercury.SetFlash(0.7f * Mathf.Max(bothPulse, tubePulse));
			}
		}

		private void Layout(float offsetX, float offsetY, float scale)
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: 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_00de: Unknown result type (might be due to invalid IL or missing references)
			Transform parent = ((Transform)_root).parent;
			_hud.m_healthBarRoot.GetWorldCorners(Corners);
			float num = float.MinValue;
			for (int i = 0; i < 4; i++)
			{
				num = Mathf.Max(num, parent.InverseTransformPoint(Corners[i]).x);
			}
			float num2 = TopOf(_hud.m_gpRoot, parent);
			if ((Object)(object)_hud.m_gpName != (Object)null)
			{
				num2 = Mathf.Max(num2, TopOf(_hud.m_gpName.rectTransform, parent));
			}
			((Transform)_root).localPosition = new Vector3(num + 4f + offsetX, num2 + 6f + offsetY, 0f);
			if (!Mathf.Approximately(((Transform)_root).localScale.x, scale))
			{
				((Transform)_root).localScale = new Vector3(scale, scale, 1f);
			}
		}

		private static float TopOf(RectTransform rt, Transform space)
		{
			//IL_001d: 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)
			rt.GetWorldCorners(Corners);
			float num = float.MinValue;
			for (int i = 0; i < 4; i++)
			{
				num = Mathf.Max(num, space.InverseTransformPoint(Corners[i]).y);
			}
			return num;
		}

		internal static RectTransform NewRect(string name, Transform parent)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: 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_003d: 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_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Expected O, but got Unknown
			RectTransform val = (RectTransform)new GameObject(name, new Type[1] { typeof(RectTransform) })
			{
				layer = ((Component)parent).gameObject.layer
			}.transform;
			((Transform)val).SetParent(parent, false);
			Vector2 anchorMin = (val.anchorMax = Vector2.zero);
			val.anchorMin = anchorMin;
			return val;
		}

		internal static RectTransform Stretch(RectTransform rt)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: 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)
			rt.anchorMin = Vector2.zero;
			rt.anchorMax = Vector2.one;
			Vector2 offsetMin = (rt.offsetMax = Vector2.zero);
			rt.offsetMin = offsetMin;
			return rt;
		}
	}
	internal static class Liquid
	{
		private const int NoiseW = 64;

		private const int NoiseH = 128;

		private static Texture2D _lightNoise;

		private static Texture2D _darkNoise;

		private static readonly Dictionary<Color32, Texture2D> Gradients = new Dictionary<Color32, Texture2D>();

		public static readonly Color32 DefaultBubble = new Color32(byte.MaxValue, (byte)194, (byte)74, byte.MaxValue);

		public static readonly Color32 DefaultMercury = new Color32((byte)228, (byte)244, byte.MaxValue, byte.MaxValue);

		private static readonly Color32[] GoldStops = (Color32[])(object)new Color32[3]
		{
			new Color32((byte)107, (byte)58, (byte)6, byte.MaxValue),
			DefaultBubble,
			new Color32((byte)138, (byte)76, (byte)10, byte.MaxValue)
		};

		private static readonly Color32[] FrostStops = (Color32[])(object)new Color32[3]
		{
			new Color32((byte)93, (byte)127, (byte)154, byte.MaxValue),
			DefaultMercury,
			new Color32((byte)110, (byte)144, (byte)171, byte.MaxValue)
		};

		public static Texture2D Gradient(Color color)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: 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_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: 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_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: 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_0151: Unknown result type (might be due to invalid IL or missing references)
			Color32 val = Color32.op_Implicit(color);
			val.a = byte.MaxValue;
			if (Gradients.TryGetValue(val, out var value) && (Object)(object)value != (Object)null)
			{
				return value;
			}
			Color32[] array;
			if (((Color32)(ref val)).Equals(DefaultBubble))
			{
				array = GoldStops;
			}
			else if (((Color32)(ref val)).Equals(DefaultMercury))
			{
				array = FrostStops;
			}
			else
			{
				float num = default(float);
				float num2 = default(float);
				float num3 = default(float);
				Color.RGBToHSV(Color32.op_Implicit(val), ref num, ref num2, ref num3);
				array = (Color32[])(object)new Color32[3]
				{
					Color32.op_Implicit(Color.HSVToRGB(num, Mathf.Min(1f, num2 * 1.3f), num3 * 0.42f)),
					val,
					Color32.op_Implicit(Color.HSVToRGB(num, Mathf.Min(1f, num2 * 1.25f), num3 * 0.54f))
				};
			}
			Texture2D val2 = NewTexture(16, 1, (TextureWrapMode)1);
			for (int i = 0; i < 16; i++)
			{
				float num4 = (float)i / 15f;
				Color val3 = ((num4 < 0.5f) ? Color.Lerp(Color32.op_Implicit(array[0]), Color32.op_Implicit(array[1]), num4 * 2f) : Color.Lerp(Color32.op_Implicit(array[1]), Color32.op_Implicit(array[2]), (num4 - 0.5f) * 2f));
				val2.SetPixel(i, 0, val3);
			}
			val2.Apply();
			Gradients[val] = val2;
			return val2;
		}

		public static Texture2D Noise(bool light)
		{
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			Texture2D val = (light ? _lightNoise : _darkNoise);
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
			Texture2D val2 = NewTexture(64, 128, (TextureWrapMode)0);
			float seed = (light ? 17.3f : 41.9f);
			float num = (light ? 1f : 0f);
			for (int i = 0; i < 128; i++)
			{
				for (int j = 0; j < 64; j++)
				{
					float num2 = Mathf.Clamp01((TileableNoise(j, i, seed) - 0.42f) * 2.4f);
					val2.SetPixel(j, i, new Color(num, num, num, num2));
				}
			}
			val2.Apply();
			if (light)
			{
				_lightNoise = val2;
			}
			else
			{
				_darkNoise = val2;
			}
			return val2;
		}

		private static float TileableNoise(int x, int y, float seed)
		{
			float num = (float)x / 64f;
			float num2 = (float)y / 128f;
			return Sample(num, num2) * (1f - num) * (1f - num2) + Sample(num - 1f, num2) * num * (1f - num2) + Sample(num, num2 - 1f) * (1f - num) * num2 + Sample(num - 1f, num2 - 1f) * num * num2;
			float Sample(float sx, float sy)
			{
				return Mathf.PerlinNoise(seed + sx * 4f, seed + sy * 8f) * 0.65f + Mathf.PerlinNoise(seed + sx * 9f, seed + sy * 17f) * 0.35f;
			}
		}

		private static Texture2D NewTexture(int w, int h, TextureWrapMode wrap)
		{
			//IL_0004: 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)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			return new Texture2D(w, h, (TextureFormat)4, false)
			{
				wrapMode = wrap,
				filterMode = (FilterMode)1,
				hideFlags = (HideFlags)32
			};
		}
	}
	public enum MessagePosition
	{
		Center,
		TopLeft
	}
	[BepInPlugin("nerdosapiens.BubbleGauge", "BubbleGauge", "1.0.1")]
	public class Plugin : BaseUnityPlugin
	{
		public const string PluginGUID = "nerdosapiens.BubbleGauge";

		public const string PluginName = "BubbleGauge";

		public const string PluginVersion = "1.0.1";

		private const float EndPulseSeconds = 0.25f;

		private const float EndFadeSeconds = 0.4f;

		internal static ManualLogSource Log;

		private readonly Harmony _harmony = new Harmony("nerdosapiens.BubbleGauge");

		private readonly BarrierTracker _tracker = new BarrierTracker(5f);

		private readonly WarningAnnouncer _announcer = new WarningAnnouncer();

		private SE_Shield _tracked;

		private GaugeView _view;

		private float _logTimer;

		private bool _ending;

		private float _endStarted;

		private BarrierReading _endReading;

		private float _warnStarted;

		private string _lastMessage;

		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<bool> DebugLogging;

		private ConfigEntry<float> _offsetX;

		private ConfigEntry<float> _offsetY;

		private ConfigEntry<float> _scale;

		private ConfigEntry<bool> _showHpNumbers;

		private ConfigEntry<bool> _showTimeNumber;

		private ConfigEntry<string> _bubbleColor;

		private ConfigEntry<string> _mercuryColor;

		private readonly GaugeSettings _settings = new GaugeSettings();

		private readonly ColorSetting _bubbleColorCache = new ColorSetting(Color32.op_Implicit(Liquid.DefaultBubble));

		private readonly ColorSetting _mercuryColorCache = new ColorSetting(Color32.op_Implicit(Liquid.DefaultMercury));

		private ConfigEntry<BarSize> _barSize;

		private ConfigEntry<float> _heightPer100Hp;

		private ConfigEntry<float> _hpPerTick;

		private ConfigEntry<bool> _liquidAnimation;

		private ConfigEntry<PulseStyle> _pulseStyle;

		private ConfigEntry<int> _endPulses;

		private ConfigEntry<float> _warnSeconds;

		private ConfigEntry<float> _blinkSpeed;

		private ConfigEntry<WarningMode> _timeWarning;

		private ConfigEntry<float> _timeWarningSeconds;

		private ConfigEntry<WarningMode> _hpWarning;

		private ConfigEntry<float> _hpWarningPercent;

		private ConfigEntry<MessagePosition> _messagePosition;

		private ConfigEntry<string> _messageColor;

		private ConfigEntry<int> _messageSize;

		internal static ConfigEntry<bool> RefillOnRecast;

		private void Awake()
		{
			Log = ((BaseUnityPlugin)this).Logger;
			Log.LogInfo((object)("BubbleGauge 1.0.1 loaded (Valheim " + Version.GetVersionString(false) + ")"));
			BindConfig();
			_tracker.Started += delegate(BarrierReading r)
			{
				_announcer.Reset();
				DebugLog($"START  {Describe(r)}  refMax(skill100)={ReferenceMax(_tracked):0} worldLevel={Game.m_worldLevel}");
			};
			_tracker.Recast += delegate(BarrierReading r)
			{
				_announcer.Reset();
				DebugLog("RECAST  " + Describe(r));
			};
			_tracker.MaxChanged += delegate(float oldMax, float newMax)
			{
				DebugLog($"MAX CHANGED  {oldMax:0} -> {newMax:0}");
			};
			_tracker.WarningStarted += delegate
			{
				_warnStarted = Time.time;
				DebugLog("WARNING  " + TimeText.Format(_tracker.Current.TimeLeft) + " left");
			};
			_tracker.Ended += delegate(EndKind kind, BarrierReading r)
			{
				_announcer.Clear();
				_ending = true;
				_endStarted = Time.time;
				_endReading = r;
				DebugLog($"END {kind}  absorbed={r.Absorbed:0} max={r.Max:0} elapsed={r.Elapsed:0.0}/{r.Duration:0.0}");
			};
			_announcer.Announce += ShowWarning;
			_harmony.PatchAll();
		}

		private void BindConfig()
		{
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Expected O, but got Unknown
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Expected O, but got Unknown
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Expected O, but got Unknown
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0174: Expected O, but got Unknown
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Expected O, but got Unknown
			//IL_02a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b2: Expected O, but got Unknown
			//IL_02e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f0: Expected O, but got Unknown
			//IL_0324: Unknown result type (might be due to invalid IL or missing references)
			//IL_032e: Expected O, but got Unknown
			//IL_0383: Unknown result type (might be due to invalid IL or missing references)
			//IL_038d: Expected O, but got Unknown
			//IL_03e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ec: Expected O, but got Unknown
			//IL_045d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0467: Expected O, but got Unknown
			Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Master switch. Off: no gauges, no messages, and RefillOnRecast does nothing (pure vanilla).");
			DebugLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "DebugLogging", false, "Write detailed barrier readings to the BepInEx log (once a second while a barrier is up). Only useful when reporting a bug.");
			RefillOnRecast = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "RefillOnRecast", false, "Off (vanilla): recasting on an active barrier only resets its timer. On: recasting also restores the barrier's HP to the new cast's full amount. Affects only your own barrier, whoever casts it.");
			_barSize = ((BaseUnityPlugin)this).Config.Bind<BarSize>("Layout", "BarSize", BarSize.Grow, "Grow: the Bubble Bar gets taller with the caster's Blood Magic, like the health bar with better food. Fixed: the Bubble Bar is always full height and a stronger barrier shows more tick marks.");
			_heightPer100Hp = ((BaseUnityPlugin)this).Config.Bind<float>("Layout", "BubbleBarHeightPer100Hp", 38f, new ConfigDescription("Grow mode: how tall the Bubble Bar gets per 100 barrier HP, in HUD units. Default 38 (chosen in play testing): a skill-0 barrier is about half the Mercury Tube, a skill-100 barrier (700 HP) about 1.8x. 128 matches the vanilla health bar exactly. The bar never grows past the top of the screen.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 200f), Array.Empty<object>()));
			_hpPerTick = ((BaseUnityPlugin)this).Config.Bind<float>("Layout", "HpPerTick", 50f, new ConfigDescription("Grow mode: barrier HP between tick marks on the Bubble Bar.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 500f), Array.Empty<object>()));
			_offsetX = ((BaseUnityPlugin)this).Config.Bind<float>("Layout", "OffsetX", 0f, new ConfigDescription("Nudge the gauges left (-) or right (+), in HUD units - e.g. to make room for another HUD mod.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-500f, 500f), Array.Empty<object>()));
			_offsetY = ((BaseUnityPlugin)this).Config.Bind<float>("Layout", "OffsetY", 0f, new ConfigDescription("Nudge the gauges down (-) or up (+), in HUD units.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-500f, 500f), Array.Empty<object>()));
			_scale = ((BaseUnityPlugin)this).Config.Bind<float>("Layout", "Scale", 1f, new ConfigDescription("Overall size of both gauges.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 2f), Array.Empty<object>()));
			_liquidAnimation = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "LiquidAnimation", true, "Swirl the liquid inside the gauges. Turn off for a still fill.");
			_showHpNumbers = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "ShowHpNumbers", true, "Show the barrier HP number on the Bubble Bar.");
			_showTimeNumber = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "ShowTimeNumber", true, "Show the time left on the Mercury Tube.");
			_bubbleColor = ((BaseUnityPlugin)this).Config.Bind<string>("Display", "BubbleColor", "#FFC24A", "Colour of the Bubble Bar's liquid, as a hex code (default: barrier gold).");
			_mercuryColor = ((BaseUnityPlugin)this).Config.Bind<string>("Display", "MercuryColor", "#E4F4FF", "Colour of the Mercury Tube's liquid, as a hex code (default: frost blue).");
			_pulseStyle = ((BaseUnityPlugin)this).Config.Bind<PulseStyle>("Pulse", "PulseStyle", PulseStyle.Dim, "How the gauges pulse when the barrier ends and when time is running out. Dim: they briefly fade and return. Flash: they briefly flash white.");
			_endPulses = ((BaseUnityPlugin)this).Config.Bind<int>("Pulse", "EndPulses", 2, new ConfigDescription("Pulses when the barrier breaks or runs out, before the gauges fade away. 0 = just fade.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 5), Array.Empty<object>()));
			_warnSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Pulse", "WarnSeconds", 5f, new ConfigDescription("The Mercury Tube pulses when this many seconds are left. 0 = never.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 60f), Array.Empty<object>()));
			_blinkSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Pulse", "BlinkSpeed", 2f, new ConfigDescription("Pulses per second while time is running out.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 5f), Array.Empty<object>()));
			_timeWarning = ((BaseUnityPlugin)this).Config.Bind<WarningMode>("Messages", "TimeWarning", WarningMode.Off, "On-screen message as the barrier runs out. Once: when TimeWarningSeconds are left. EveryTick: at each tick mark on the Mercury Tube.");
			_timeWarningSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Messages", "TimeWarningSeconds", 10f, new ConfigDescription("For TimeWarning = Once: seconds left when the message appears.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 120f), Array.Empty<object>()));
			_hpWarning = ((BaseUnityPlugin)this).Config.Bind<WarningMode>("Messages", "HpWarning", WarningMode.Off, "On-screen message as the barrier takes damage. Once: when HP drops to HpWarningPercent. EveryTick: at each tick mark on the Bubble Bar.");
			_hpWarningPercent = ((BaseUnityPlugin)this).Config.Bind<float>("Messages", "HpWarningPercent", 25f, new ConfigDescription("For HpWarning = Once: percent of the barrier's HP left when the message appears.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 90f), Array.Empty<object>()));
			_messagePosition = ((BaseUnityPlugin)this).Config.Bind<MessagePosition>("Messages", "MessagePosition", MessagePosition.Center, "Center: the game's large centre-screen text, made smaller and green so it isn't mistaken for a boss or raid alert. TopLeft: the game's small top-left messages.");
			_messageColor = ((BaseUnityPlugin)this).Config.Bind<string>("Messages", "MessageColor", "#8FC93A", "Colour of centre messages, as a hex code (default: Yggdrasil porridge green).");
			_messageSize = ((BaseUnityPlugin)this).Config.Bind<int>("Messages", "MessageSize", 80, new ConfigDescription("Size of centre messages, as a percent of the game's own centre text.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(40, 100), Array.Empty<object>()));
		}

		private void OnDestroy()
		{
			_harmony.UnpatchSelf();
		}

		private void Update()
		{
			Player localPlayer = Player.m_localPlayer;
			SE_Shield val = (((Object)(object)localPlayer != (Object)null) ? FindShield(localPlayer) : null);
			_tracker.WarnSeconds = _warnSeconds.Value;
			_announcer.HpMode = _hpWarning.Value;
			_announcer.TimeMode = _timeWarning.Value;
			_announcer.HpWarningPercent = _hpWarningPercent.Value;
			_announcer.TimeWarningSeconds = _timeWarningSeconds.Value;
			if ((Object)(object)_tracked != (Object)null && val != _tracked)
			{
				_tracker.Update(Read(_tracked, active: false));
				_tracked = null;
			}
			if ((Object)(object)val != (Object)null)
			{
				_tracked = val;
			}
			if (!Enabled.Value)
			{
				if ((Object)(object)val != (Object)null)
				{
					_tracker.Update(Read(val, active: true));
				}
				_ending = false;
				_announcer.Clear();
				if (_view != null && _view.IsAlive)
				{
					_view.SetVisible(visible: false);
				}
				return;
			}
			FillSettings();
			if ((Object)(object)val != (Object)null)
			{
				_ending = false;
				_tracker.Update(Read(val, active: true));
				if (EnsureView())
				{
					_view.Show(_tracker.Current, _settings);
					float tubePulse = (_tracker.IsWarning ? PulseMath.Blink(Time.time - _warnStarted, _blinkSpeed.Value) : 0f);
					_view.ApplyPulse(_pulseStyle.Value, 0f, tubePulse, 1f);
					_announcer.Update(Time.time, _tracker.Current, _view.HpTickStep, _view.TimeTickStep, CanShowWarning());
					LogTick();
				}
				return;
			}
			if (_ending && EnsureView())
			{
				EndFrame endFrame = PulseMath.End(Time.time - _endStarted, _endPulses.Value, 0.25f, 0.4f);
				_view.Show(_endReading, _settings);
				_view.ApplyPulse(_pulseStyle.Value, endFrame.Pulse, 0f, endFrame.Alpha);
				if (!endFrame.Done)
				{
					return;
				}
				_ending = false;
			}
			if (_view != null && _view.IsAlive)
			{
				_view.SetVisible(visible: false);
			}
		}

		private void FillSettings()
		{
			//IL_00dd: 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_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			_settings.BarSize = _barSize.Value;
			_settings.HeightPer100Hp = _heightPer100Hp.Value;
			_settings.HpPerTick = _hpPerTick.Value;
			_settings.LiquidAnimation = _liquidAnimation.Value;
			_settings.OffsetX = _offsetX.Value;
			_settings.OffsetY = _offsetY.Value;
			_settings.Scale = _scale.Value;
			_settings.ShowHpNumber = _showHpNumbers.Value;
			_settings.ShowTimeNumber = _showTimeNumber.Value;
			_settings.BubbleColor = _bubbleColorCache.Get(_bubbleColor.Value);
			_settings.MercuryColor = _mercuryColorCache.Get(_mercuryColor.Value);
		}

		internal static void DebugLog(string message)
		{
			if (DebugLogging != null && DebugLogging.Value)
			{
				Log.LogInfo((object)message);
			}
		}

		private bool EnsureView()
		{
			if (_view == null || !_view.IsAlive)
			{
				_view = GaugeView.TryCreate();
			}
			return _view != null;
		}

		private bool CanShowWarning()
		{
			if (_messagePosition.Value != MessagePosition.Center)
			{
				return true;
			}
			MessageHud instance = MessageHud.instance;
			if ((Object)(object)instance == (Object)null || (Object)(object)instance.m_messageCenterText == (Object)null)
			{
				return false;
			}
			if (((Graphic)instance.m_messageCenterText).canvasRenderer.GetAlpha() > 0.05f)
			{
				return instance.m_messageCenterText.text == _lastMessage;
			}
			return true;
		}

		private void ShowWarning(string text)
		{
			MessageHud instance = MessageHud.instance;
			if (!((Object)(object)instance == (Object)null))
			{
				if (_messagePosition.Value == MessagePosition.TopLeft)
				{
					instance.ShowMessage((MessageType)1, text, 0, (Sprite)null, false, false);
					return;
				}
				string arg = (_messageColor.Value.StartsWith("#") ? _messageColor.Value : ("#" + _messageColor.Value));
				_lastMessage = $"<size={_messageSize.Value}%><color={arg}>{text}</color></size>";
				instance.ShowMessage((MessageType)2, _lastMessage, 0, (Sprite)null, false, false);
			}
		}

		private void LogTick()
		{
			if (DebugLogging.Value)
			{
				_logTimer -= Time.deltaTime;
				if (!(_logTimer > 0f))
				{
					_logTimer = 1f;
					DebugLog("tick  " + Describe(_tracker.Current));
				}
			}
		}

		private static SE_Shield FindShield(Player player)
		{
			List<StatusEffect> statusEffects = ((Character)player).GetSEMan().GetStatusEffects();
			for (int i = 0; i < statusEffects.Count; i++)
			{
				StatusEffect obj = statusEffects[i];
				SE_Shield val = (SE_Shield)(object)((obj is SE_Shield) ? obj : null);
				if (val != null)
				{
					return val;
				}
			}
			return null;
		}

		private static BarrierReading Read(SE_Shield s, bool active)
		{
			return new BarrierReading(s, active, s.m_totalAbsorbDamage, s.m_damage, ((StatusEffect)s).m_time, ((StatusEffect)s).m_ttl);
		}

		private static float ReferenceMax(SE_Shield s)
		{
			return GaugeMath.ReferenceMax(s.m_absorbDamage, s.m_absorbDamagePerSkillLevel, s.m_absorbDamageWorldLevel, Game.m_worldLevel);
		}

		private static string Describe(BarrierReading r)
		{
			return $"hp {r.Remaining:0}/{r.Max:0}  time {TimeText.Format(r.TimeLeft)} ({r.TimeLeft:0.0}/{r.Duration:0.0}s)";
		}
	}
	[HarmonyPatch(typeof(SE_Shield), "SetLevel")]
	internal static class RefillOnRecastPatch
	{
		private static void Postfix(SE_Shield __instance)
		{
			if (Plugin.RefillOnRecast != null && Plugin.RefillOnRecast.Value && Plugin.Enabled.Value && !((Object)(object)((StatusEffect)__instance).m_character == (Object)null) && !((Object)(object)((StatusEffect)__instance).m_character != (Object)(object)Player.m_localPlayer))
			{
				__instance.m_damage = 0f;
			}
		}
	}
	internal sealed class ColorSetting
	{
		private readonly Color _fallback;

		private string _text;

		private Color _color;

		public ColorSetting(Color fallback)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			_fallback = fallback;
			_color = fallback;
		}

		public Color Get(string text)
		{
			//IL_000f: 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_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			if (text == _text)
			{
				return _color;
			}
			_text = text;
			string text2 = ((text != null && !text.StartsWith("#")) ? ("#" + text.Trim()) : text);
			Color val = default(Color);
			_color = (ColorUtility.TryParseHtmlString(text2, ref val) ? val : _fallback);
			return _color;
		}
	}
	[HarmonyPatch(typeof(Player), "OnSpawned")]
	internal static class LogHudLayoutOnSpawn
	{
		private static void Postfix(Player __instance)
		{
			if (Plugin.DebugLogging.Value && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && !((Object)(object)Hud.instance == (Object)null))
			{
				LogRect("healthBarRoot", Hud.instance.m_healthBarRoot);
				LogRect("healthPanel", Hud.instance.m_healthPanel);
				LogRect("gpRoot", Hud.instance.m_gpRoot);
				if ((Object)(object)Hud.instance.m_gpName != (Object)null)
				{
					LogRect("gpName", Hud.instance.m_gpName.rectTransform);
				}
				if ((Object)(object)Hud.instance.m_gpCooldown != (Object)null)
				{
					LogRect("gpCooldown", Hud.instance.m_gpCooldown.rectTransform);
				}
			}
		}

		private static void LogRect(string label, RectTransform rt)
		{
			//IL_0060: 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)
			//IL_0076: 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_0096: 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_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)rt == (Object)null)
			{
				Plugin.DebugLog("HUD " + label + ": null");
				return;
			}
			Vector3[] array = (Vector3[])(object)new Vector3[4];
			rt.GetWorldCorners(array);
			object arg = ((Component)rt).gameObject.activeInHierarchy;
			Transform parent = ((Transform)rt).parent;
			Plugin.DebugLog($"HUD {label}: active={arg} parent='{((parent != null) ? ((Object)parent).name : null)}' " + $"anchorMin={rt.anchorMin} anchorMax={rt.anchorMax} pivot={rt.pivot} " + $"anchoredPos={rt.anchoredPosition} size={rt.sizeDelta} rotZ={((Transform)rt).localEulerAngles.z:0} " + $"screenBL={array[0]} screenTR={array[2]}");
		}
	}
}
namespace BubbleGauge.Logic
{
	public enum EndKind
	{
		Broke,
		Expired
	}
	public readonly struct BarrierReading
	{
		public readonly object Id;

		public readonly bool Active;

		public readonly float Max;

		public readonly float Absorbed;

		public readonly float Elapsed;

		public readonly float Duration;

		public float Remaining => GaugeMath.Remaining(Max, Absorbed);

		public float TimeLeft => Math.Max(0f, Duration - Elapsed);

		public BarrierReading(object id, bool active, float max, float absorbed, float elapsed, float duration)
		{
			Id = id;
			Active = active;
			Max = max;
			Absorbed = absorbed;
			Elapsed = elapsed;
			Duration = duration;
		}
	}
	public sealed class BarrierTracker
	{
		private const float RecastJumpSeconds = 0.5f;

		public float WarnSeconds { get; set; }

		public bool IsActive { get; private set; }

		public bool IsWarning { get; private set; }

		public BarrierReading Current { get; private set; }

		public event Action<BarrierReading> Started;

		public event Action<BarrierReading> Recast;

		public event Action<float, float> MaxChanged;

		public event Action WarningStarted;

		public event Action<EndKind, BarrierReading> Ended;

		public BarrierTracker(float warnSeconds)
		{
			WarnSeconds = warnSeconds;
		}

		public void Update(BarrierReading reading)
		{
			if (!reading.Active)
			{
				if (IsActive && reading.Id == Current.Id)
				{
					End(reading);
				}
				return;
			}
			if (!IsActive || reading.Id != Current.Id)
			{
				if (IsActive)
				{
					End(Current);
				}
				Start(reading);
				return;
			}
			BarrierReading current = Current;
			Current = reading;
			if (reading.Elapsed < current.Elapsed - 0.5f)
			{
				this.Recast?.Invoke(reading);
			}
			if (reading.Max != current.Max)
			{
				this.MaxChanged?.Invoke(current.Max, reading.Max);
			}
			UpdateWarning();
		}

		private void Start(BarrierReading reading)
		{
			Current = reading;
			IsActive = true;
			IsWarning = false;
			this.Started?.Invoke(reading);
			UpdateWarning();
		}

		private void End(BarrierReading final)
		{
			IsActive = false;
			IsWarning = false;
			Current = final;
			this.Ended?.Invoke((!(final.Absorbed > final.Max)) ? EndKind.Expired : EndKind.Broke, final);
		}

		private void UpdateWarning()
		{
			bool flag = GaugeMath.IsWarning(Current.TimeLeft, WarnSeconds);
			if (flag && !IsWarning)
			{
				this.WarningStarted?.Invoke();
			}
			IsWarning = flag;
		}
	}
	public enum BarSize
	{
		Grow,
		Fixed
	}
	public static class GaugeMath
	{
		public static float TickStep(float[] steps, float unitsPerValue, float minGap)
		{
			for (int i = 0; i < steps.Length; i++)
			{
				if (steps[i] * unitsPerValue >= minGap)
				{
					return steps[i];
				}
			}
			return steps[^1];
		}

		public static int TickCount(float max, float step)
		{
			if (max <= 0f || step <= 0f)
			{
				return 0;
			}
			int val = (int)Math.Ceiling(max / step - 0.0001f) - 1;
			return Math.Max(0, val);
		}

		public static float BubbleBarHeight(BarSize mode, float max, float heightPer100Hp, float fullHeight, float minHeight)
		{
			if (mode == BarSize.Fixed)
			{
				return fullHeight;
			}
			return Math.Max(minHeight, max * heightPer100Hp / 100f);
		}

		public static float Approach(float current, float target, float maxDelta)
		{
			if (Math.Abs(target - current) <= maxDelta)
			{
				return target;
			}
			return current + (float)Math.Sign(target - current) * maxDelta;
		}

		public static float Remaining(float max, float absorbed)
		{
			return Math.Max(0f, max - absorbed);
		}

		public static float Fill(float value, float max)
		{
			if (max <= 0f)
			{
				return 0f;
			}
			return Clamp01(value / max);
		}

		public static float ReferenceMax(float baseAbsorb, float perSkillLevel, float perWorldLevel, int worldLevel)
		{
			float num = baseAbsorb + perSkillLevel * 100f;
			if (worldLevel > 0)
			{
				num += perWorldLevel * (float)worldLevel;
			}
			return num;
		}

		public static bool IsWarning(float timeLeft, float warnSeconds)
		{
			if (warnSeconds > 0f)
			{
				return timeLeft <= warnSeconds;
			}
			return false;
		}

		private static float Clamp01(float v)
		{
			if (!(v < 0f))
			{
				if (!(v > 1f))
				{
					return v;
				}
				return 1f;
			}
			return 0f;
		}
	}
	public readonly struct EndFrame
	{
		public readonly float Pulse;

		public readonly float Alpha;

		public readonly bool Done;

		public EndFrame(float pulse, float alpha, bool done)
		{
			Pulse = pulse;
			Alpha = alpha;
			Done = done;
		}
	}
	public static class PulseMath
	{
		public static float Intensity(float phase)
		{
			return (1f - (float)Math.Cos(Math.PI * 2.0 * (double)phase)) * 0.5f;
		}

		public static float Blink(float time, float pulsesPerSecond)
		{
			double num = time * pulsesPerSecond;
			return Intensity((float)(num - Math.Floor(num)));
		}

		public static EndFrame End(float elapsed, int pulses, float pulseSeconds, float fadeSeconds)
		{
			float num = (float)Math.Max(0, pulses) * pulseSeconds;
			if (elapsed < num)
			{
				float num2 = elapsed / pulseSeconds;
				return new EndFrame(Intensity(num2 - (float)Math.Floor(num2)), 1f, done: false);
			}
			float num3 = ((fadeSeconds <= 0f) ? 1f : ((elapsed - num) / fadeSeconds));
			if (!(num3 >= 1f))
			{
				return new EndFrame(0f, 1f - num3, done: false);
			}
			return new EndFrame(0f, 0f, done: true);
		}
	}
	public static class TimeText
	{
		public static string Format(float seconds)
		{
			int num = ((!(seconds <= 0f)) ? ((int)Math.Ceiling(seconds)) : 0);
			if (num <= 99)
			{
				return num + "s";
			}
			return num / 60 + ":" + (num % 60).ToString("00");
		}

		public static string Spoken(int seconds)
		{
			if (seconds < 60 || (seconds <= 99 && seconds % 60 != 0))
			{
				if (seconds != 1)
				{
					return seconds + " seconds";
				}
				return "1 second";
			}
			if (seconds % 60 == 0)
			{
				if (seconds != 60)
				{
					return seconds / 60 + " minutes";
				}
				return "1 minute";
			}
			return seconds / 60 + ":" + (seconds % 60).ToString("00");
		}

		public static string Stack(string text)
		{
			if (string.IsNullOrEmpty(text))
			{
				return string.Empty;
			}
			StringBuilder stringBuilder = new StringBuilder(text.Length * 2);
			for (int i = 0; i < text.Length; i++)
			{
				if (i > 0)
				{
					stringBuilder.Append('\n');
				}
				stringBuilder.Append(text[i]);
			}
			return stringBuilder.ToString();
		}
	}
	public enum WarningMode
	{
		Off,
		Once,
		EveryTick
	}
	public sealed class WarningAnnouncer
	{
		private bool _hasBaseline;

		private float _lastRemaining;

		private float _lastTimeLeft;

		private bool _hpOnceDone;

		private bool _timeOnceDone;

		private string _waitingHp;

		private string _waitingTime;

		private float _nextAllowed = float.MinValue;

		public WarningMode HpMode { get; set; }

		public WarningMode TimeMode { get; set; }

		public float HpWarningPercent { get; set; } = 25f;

		public float TimeWarningSeconds { get; set; } = 10f;

		public float MinGapSeconds { get; set; } = 1.5f;

		public event Action<string> Announce;

		public void Reset()
		{
			_hasBaseline = false;
			_hpOnceDone = (_timeOnceDone = false);
			_waitingHp = (_waitingTime = null);
		}

		public void Clear()
		{
			Reset();
		}

		public void Update(float now, BarrierReading r, float hpStep, float timeStep, bool canShow)
		{
			float remaining = r.Remaining;
			float timeLeft = r.TimeLeft;
			if (_hasBaseline)
			{
				CheckHp(remaining, hpStep, r.Max);
				CheckTime(timeLeft, timeStep);
			}
			_hasBaseline = true;
			_lastRemaining = remaining;
			_lastTimeLeft = timeLeft;
			if (!canShow || now < _nextAllowed)
			{
				return;
			}
			bool flag = _waitingHp != null;
			string text = (flag ? _waitingHp : _waitingTime);
			if (text != null)
			{
				if (flag)
				{
					_waitingHp = null;
				}
				else
				{
					_waitingTime = null;
				}
				_nextAllowed = now + MinGapSeconds;
				this.Announce?.Invoke(text);
			}
		}

		private void CheckHp(float remaining, float step, float max)
		{
			if (remaining >= _lastRemaining)
			{
				return;
			}
			bool flag = false;
			if (HpMode == WarningMode.Once && !_hpOnceDone)
			{
				float num = max * HpWarningPercent / 100f;
				flag = _lastRemaining > num && remaining <= num;
				if (flag)
				{
					_hpOnceDone = true;
				}
			}
			else if (HpMode == WarningMode.EveryTick)
			{
				flag = Level(remaining, step) < Level(_lastRemaining, step);
			}
			if (flag)
			{
				_waitingHp = $"Barrier down to {(int)Math.Ceiling(remaining)} HP";
			}
		}

		private void CheckTime(float timeLeft, float step)
		{
			if (timeLeft >= _lastTimeLeft)
			{
				return;
			}
			if (TimeMode == WarningMode.Once && !_timeOnceDone)
			{
				if (_lastTimeLeft > TimeWarningSeconds && timeLeft <= TimeWarningSeconds)
				{
					_timeOnceDone = true;
					_waitingTime = "Barrier fades in " + TimeText.Spoken((int)Math.Round(TimeWarningSeconds));
				}
			}
			else if (TimeMode == WarningMode.EveryTick)
			{
				int num = Level(timeLeft, step);
				if (num < Level(_lastTimeLeft, step) && num > 0)
				{
					_waitingTime = "Barrier fades in " + TimeText.Spoken((int)Math.Round((float)num * step));
				}
			}
		}

		private static int Level(float value, float step)
		{
			if (!(step <= 0f))
			{
				return (int)Math.Ceiling(value / step - 0.0001f);
			}
			return 0;
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}