Decompiled source of SagaPro HUD v3.0.3

BepInEx/plugins/MMC-CharacterPanel/MMCCharacterPanel.dll

Decompiled a week ago
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using HarmonyLib;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInPlugin("local.mmc.characterpanel", "Saga Vitals", "3.0.1")]
public sealed class MMCCharacterPanel : BaseUnityPlugin
{
	private sealed class BarBoost
	{
		public Image Icon;

		public Image Wipe;

		public TMP_Text Value;

		public readonly SagaBoostWipe Clock = new SagaBoostWipe();
	}

	private sealed class BarTextStroke
	{
		public TMP_Text Value;

		public readonly List<TMP_Text> Copies = new List<TMP_Text>();
	}

	public struct StaminaSnapshot
	{
		public bool Valid;

		public float Value;

		public float Maximum;
	}

	private sealed class SpendVisual
	{
		public RectTransform Root;

		public TMP_Text Text;

		public CanvasGroup Group;

		public float Born = -100f;

		public float Amount;
	}

	public struct SpendSnapshot
	{
		public bool Valid;

		public float Stamina;
	}

	private const float HealthY = 30f;

	private const float StaminaY = 72f;

	private const float BarX = 190f;

	private const float BarHeight = 28f;

	private BarBoost[] barBoosts;

	private static readonly FieldInfo barBoostTimer = AccessTools.Field(typeof(Player), "m_foodUpdateTimer");

	private ConfigEntry<bool> enabledPanel;

	private ConfigEntry<bool> previewEnabled;

	private ConfigEntry<bool> showPower;

	private ConfigEntry<float> scale;

	private ConfigEntry<float> bottomMargin;

	private ConfigEntry<float> barWidth;

	private Hud hud;

	private SagaPanelAppearance appearance;

	private ConfigEntry<bool> hideForTools;

	private ConfigEntry<float> toolHideDelay;

	private float toolEquippedAt = -1f;

	private Image panelBackground;

	private Image panelTop;

	private Image panelBottom;

	private Image panelLeft;

	private Image panelRight;

	private Image panelHeader;

	private TMP_Text panelTitle;

	private GameObject canvasObject;

	private RectTransform root;

	public static Rect HealthBarScreenRect;

	public static Vector2 HealingPopupScreenPosition;

	public static bool HealthBarVisible;

	private Image health;

	private Image stamina;

	private Image ghost;

	private Image marker;

	private TMP_Text hpValue;

	private TMP_Text staminaValue;

	private TMP_Text nextHeal;

	private TMP_Text ghostValue;

	private RectTransform eitrRoot;

	private RectTransform adrenalineRoot;

	private RectTransform weightRoot;

	private Image weightFill;

	private TMP_Text weightValue;

	private ConfigEntry<bool> showWeight;

	private Image eitr;

	private Image adrenaline;

	private TMP_Text eitrValue;

	private TMP_Text adrenalineValue;

	private float lastMaxEitr;

	private float lastMaxAdrenaline;

	private float builtWidth;

	private RectTransform nativePower;

	private Vector2 originalPowerPosition;

	private Vector3 originalPowerScale;

	private readonly List<BarTextStroke> strokes = new List<BarTextStroke>();

	private bool failed;

	private readonly Dictionary<GameObject, bool> nativeStamina = new Dictionary<GameObject, bool>();

	private readonly Dictionary<CanvasGroup, float> hidden = new Dictionary<CanvasGroup, float>();

	private readonly List<CanvasGroup> createdGroups = new List<CanvasGroup>();

	private readonly List<Object> owned = new List<Object>();

	private Sprite rounded;

	private Sprite gradient;

	private static MMCCharacterPanel instance;

	private Harmony harmony;

	private readonly MMCStaminaRate refill = new MMCStaminaRate();

	private RectTransform refillRoot;

	private TMP_Text refillValue;

	private TMP_Text healthRateValue;

	private float healthRateAlpha;

	private CanvasGroup healthRateGroup;

	private CanvasGroup refillGroup;

	private float refillAlpha;

	private CanvasGroup powerVisibility;

	private float originalPowerAlpha;

	private readonly SpendVisual[] spendVisuals = new SpendVisual[5];

	private int spendIndex;

	private float emptyUntil;

	private float pendingSpend;

	private float pendingSpendUntil;

	private float DesiredBarWidth => appearance.Size(new Vector2(barWidth.Value, 104f), 240f, 104f).x / appearance.Scale;

	private void BuildBarBoosts(Image heart, Image lightning)
	{
		//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ab: 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_00bf: 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_00f1: 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_011a: 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_0120: Unknown result type (might be due to invalid IL or missing references)
		//IL_0127: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
		barBoosts = new BarBoost[2];
		Image[] array = (Image[])(object)new Image[2] { heart, lightning };
		for (int i = 0; i < 2; i++)
		{
			Image val = array[i];
			Texture2D texture = val.sprite.texture;
			Color[] pixels = texture.GetPixels();
			int tw = ((Texture)texture).width;
			int th = ((Texture)texture).height;
			Sprite sprite = MakeSprite(tw, th, delegate(float x, float y)
			{
				//IL_005b: Unknown result type (might be due to invalid IL or missing references)
				int num = Mathf.Clamp((int)(x * (float)tw), 0, tw - 1);
				int num2 = Mathf.Clamp((int)(y * (float)th), 0, th - 1);
				return new Color(0.45f, 0.45f, 0.45f, pixels[num2 * tw + num].a);
			}, sliced: false);
			Transform transform = ((Component)val).transform;
			Rect rect = ((Graphic)val).rectTransform.rect;
			float width = ((Rect)(ref rect)).width;
			Rect rect2 = ((Graphic)val).rectTransform.rect;
			Image val2 = ImageNode("Food bonus decrease wipe", transform, 0f, 0f, width, ((Rect)(ref rect2)).height, new Color(1f, 1f, 1f, 0.85f), sprite);
			((Graphic)val2).rectTransform.anchorMin = Vector2.zero;
			((Graphic)val2).rectTransform.anchorMax = Vector2.one;
			RectTransform rectTransform = ((Graphic)val2).rectTransform;
			Vector2 offsetMin = (((Graphic)val2).rectTransform.offsetMax = Vector2.zero);
			rectTransform.offsetMin = offsetMin;
			val2.type = (Type)3;
			val2.fillMethod = (FillMethod)4;
			val2.fillOrigin = 2;
			val2.fillClockwise = true;
			val2.fillAmount = 0f;
			TMP_Text val3 = Text((i == 0) ? "Food health bonus" : "Food stamina bonus", (Transform)(object)root, 99f, (i == 0) ? 30f : 72f, 43f, 28f, 15f, new Color(0.35f, 1f, 0.4f, 1f));
			val3.alignment = (TextAlignmentOptions)516;
			AddBarTextStroke(val3);
			barBoosts[i] = new BarBoost
			{
				Icon = val,
				Wipe = val2,
				Value = val3
			};
		}
	}

	private void UpdateBarBoosts(Player player)
	{
		//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
		if (barBoosts == null)
		{
			return;
		}
		List<Food> foods = player.GetFoods();
		double timer = ((barBoostTimer == null) ? 0f : ((float)barBoostTimer.GetValue(player)));
		double num = 0.0;
		foreach (Food item in foods)
		{
			num += (double)item.m_time;
		}
		for (int i = 0; i < 2; i++)
		{
			SagaFoodBoostForecast.Food[] array = new SagaFoodBoostForecast.Food[foods.Count];
			for (int j = 0; j < foods.Count; j++)
			{
				Food val = foods[j];
				SharedData shared = val.m_item.m_shared;
				ref SagaFoodBoostForecast.Food reference = ref array[j];
				reference = new SagaFoodBoostForecast.Food
				{
					Remaining = val.m_time,
					Duration = shared.m_foodBurnTime,
					Base = ((i == 0) ? shared.m_food : shared.m_foodStamina),
					Current = ((i == 0) ? val.m_health : val.m_stamina)
				};
			}
			int num2 = SagaFoodBoostForecast.Bonus(array);
			double seconds;
			int drop;
			bool predicted = SagaFoodBoostForecast.Predict(array, timer, 1.0, out seconds, out drop);
			BarBoost barBoost = barBoosts[i];
			barBoost.Value.text = ((num2 > 0) ? ("+" + num2.ToString(CultureInfo.InvariantCulture)) : "");
			float num3 = barBoost.Clock.Update(num2, num, seconds, predicted);
			barBoost.Wipe.fillAmount = num3;
			((Graphic)barBoost.Icon).color = new Color(1f, 1f, 1f, 1f - 0.25f * num3);
		}
	}

	private static void BeforeStats(Player __instance, out StaminaSnapshot __state)
	{
		__state = default(StaminaSnapshot);
		if (!((Object)(object)instance == (Object)null) && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer))
		{
			__state.Valid = true;
			__state.Value = __instance.GetStamina();
			__state.Maximum = ((Character)__instance).GetMaxStamina();
		}
	}

	private static void AfterStats(Player __instance, float __0, StaminaSnapshot __state)
	{
		if (!((Object)(object)instance == (Object)null) && __state.Valid)
		{
			instance.refill.Observe(Time.unscaledTime, __state.Value, __instance.GetStamina(), __state.Maximum, ((Character)__instance).GetMaxStamina(), __0);
		}
	}

	private void UpdateRefill(float stamina, float maximum)
	{
		//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00da: 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_00ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f1: 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_0141: Unknown result type (might be due to invalid IL or missing references)
		bool flag = refill.Visible(Time.unscaledTime) && stamina < maximum - 0.001f;
		refillAlpha = Mathf.MoveTowards(refillAlpha, (float)(flag ? 1 : 0), Time.unscaledDeltaTime / (flag ? 0.15f : 0.4f));
		if (flag)
		{
			refillValue.text = "+" + refill.Rate.ToString("0.0", CultureInfo.InvariantCulture) + "/s";
		}
		float num = ((flag && maximum > 0f) ? (1f - Mathf.Clamp01(stamina / maximum)) : 0f);
		Color val = Color.Lerp(new Color(0.62f, 0.52f, 0.18f, 1f), new Color(1f, 0.95f, 0.32f, 1f), num);
		((Graphic)refillValue).color = Color.Lerp(((Graphic)refillValue).color, val, 1f - Mathf.Exp((0f - Time.unscaledDeltaTime) / 0.2f));
		refillGroup.alpha = refillAlpha;
		refillRoot.anchoredPosition = new Vector2(190f + builtWidth + 12f, -72f);
	}

	private void Awake()
	{
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Expected O, but got Unknown
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: Expected O, but got Unknown
		//IL_0083: Unknown result type (might be due to invalid IL or missing references)
		//IL_008d: Expected O, but got Unknown
		//IL_00cd: 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_00ef: Expected O, but got Unknown
		//IL_00ef: Expected O, but got Unknown
		//IL_0168: Unknown result type (might be due to invalid IL or missing references)
		//IL_0172: Expected O, but got Unknown
		//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b1: Expected O, but got Unknown
		//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f0: Expected O, but got Unknown
		instance = this;
		appearance = new SagaPanelAppearance(((BaseUnityPlugin)this).Config, true, 0f);
		toolHideDelay = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "Build Tool Hide Delay", 0f, new ConfigDescription("Seconds after equipping a hoe or cultivator before vitals hide.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 30f), new object[0]));
		hideForTools = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "Hide While Using Build Tools", true, "Hide the vitals panel while a hoe or cultivator is equipped. Automatically restore it on switching away. F1 preview stays visible.");
		harmony = new Harmony("local.mmc.characterpanel.refill");
		harmony.Patch((MethodBase)AccessTools.Method(typeof(Player), "UpdateStats", new Type[1] { typeof(float) }, (Type[])null), new HarmonyMethod(typeof(MMCCharacterPanel), "BeforeStats", (Type[])null), new HarmonyMethod(typeof(MMCCharacterPanel), "AfterStats", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		PatchFeedback();
		showWeight = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "Show Carry Weight", true, "Show current inventory weight and maximum carrying capacity beneath the resource bars.");
		enabledPanel = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "Enabled", true, "Use the bottom-center health, stamina, eitr and adrenaline HUD.");
		scale = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "Scale", 1f, new ConfigDescription("HUD size.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.6f, 2f), new object[0]));
		bottomMargin = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "Bottom Margin", 122f, new ConfigDescription("Pixels between the HUD and bottom screen edge.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 400f), new object[0]));
		barWidth = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "Bar Width", 380f, new ConfigDescription("Width of each bar before scaling.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(240f, 640f), new object[0]));
		previewEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "Next Heal Preview", true, "Show the full incoming healing amount immediately, with its existing tick timer.");
		showPower = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "Show Forsaken Power", true, "Show selected power and ready/cooldown status to the left.");
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Bottom-center 2D vitals enabled. No portrait renderer, lights, camera or inventory assets.");
	}

	private RectTransform Node(string name, Transform parent, float x, float y, float w, float h)
	{
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: 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_0052: Unknown result type (might be due to invalid IL or missing references)
		//IL_0061: Unknown result type (might be due to invalid IL or missing references)
		//IL_0070: Unknown result type (might be due to invalid IL or missing references)
		RectTransform component = new GameObject(name, new Type[1] { typeof(RectTransform) }).GetComponent<RectTransform>();
		((Transform)component).SetParent(parent, false);
		Vector2 anchorMin = (component.anchorMax = new Vector2(0f, 1f));
		component.anchorMin = anchorMin;
		component.pivot = new Vector2(0f, 1f);
		component.anchoredPosition = new Vector2(x, 0f - y);
		component.sizeDelta = new Vector2(w, h);
		return component;
	}

	private Image ImageNode(string name, Transform parent, float x, float y, float w, float h, Color color, Sprite sprite)
	{
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		Image val = ((Component)Node(name, parent, x, y, w, h)).gameObject.AddComponent<Image>();
		((Graphic)val).color = color;
		val.sprite = sprite;
		((Graphic)val).raycastTarget = false;
		if ((Object)(object)sprite == (Object)(object)rounded)
		{
			val.type = (Type)1;
		}
		return val;
	}

	private TMP_Text Text(string name, Transform parent, float x, float y, float w, float h, float size, Color color)
	{
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		TextMeshProUGUI val = ((Component)Node(name, parent, x, y, w, h)).gameObject.AddComponent<TextMeshProUGUI>();
		((TMP_Text)val).font = hud.m_healthText.font;
		((TMP_Text)val).fontSize = size;
		((TMP_Text)val).fontStyle = (FontStyles)1;
		((TMP_Text)val).alignment = (TextAlignmentOptions)514;
		((Graphic)val).color = color;
		((Graphic)val).raycastTarget = false;
		((TMP_Text)val).richText = false;
		((TMP_Text)val).enableAutoSizing = true;
		((TMP_Text)val).fontSizeMin = 10f;
		((TMP_Text)val).fontSizeMax = size;
		((TMP_Text)val).textWrappingMode = (TextWrappingModes)0;
		((TMP_Text)val).overflowMode = (TextOverflowModes)1;
		return (TMP_Text)(object)val;
	}

	private void AddBarTextStroke(TMP_Text value)
	{
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		BarTextStroke barTextStroke = new BarTextStroke();
		barTextStroke.Value = value;
		BarTextStroke barTextStroke2 = barTextStroke;
		for (int i = 0; i < 8; i++)
		{
			TMP_Text component = Object.Instantiate<GameObject>(((Component)value).gameObject, value.transform.parent).GetComponent<TMP_Text>();
			((Object)component).name = ((Object)value).name + " black outline " + i;
			((Graphic)component).color = Color.black;
			((Graphic)component).raycastTarget = false;
			component.transform.SetSiblingIndex(value.transform.GetSiblingIndex());
			barTextStroke2.Copies.Add(component);
		}
		strokes.Add(barTextStroke2);
	}

	private void UpdateBarTextStrokes(float factor)
	{
		//IL_0077: 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_00a1: 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)
		float num = 1f / Mathf.Max(0.01f, factor);
		foreach (BarTextStroke stroke in strokes)
		{
			int num2 = 0;
			for (int i = -1; i <= 1; i++)
			{
				for (int j = -1; j <= 1; j++)
				{
					if (j != 0 || i != 0)
					{
						TMP_Text val = stroke.Copies[num2++];
						val.text = stroke.Value.text;
						val.rectTransform.sizeDelta = stroke.Value.rectTransform.sizeDelta;
						val.rectTransform.anchoredPosition = stroke.Value.rectTransform.anchoredPosition + new Vector2((float)j * num, (float)i * num);
					}
				}
			}
		}
	}

	private Sprite MakeSprite(int width, int height, Func<float, float, Color> sample, bool sliced)
	{
		//IL_0004: Unknown result type (might be due to invalid IL or missing references)
		//IL_000a: Expected O, but got Unknown
		//IL_007a: 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_00b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_0099: 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_0049: Unknown result type (might be due to invalid IL or missing references)
		Texture2D val = new Texture2D(width, height, (TextureFormat)4, false);
		((Texture)val).wrapMode = (TextureWrapMode)1;
		Color[] array = (Color[])(object)new Color[width * height];
		for (int i = 0; i < height; i++)
		{
			for (int j = 0; j < width; j++)
			{
				ref Color reference = ref array[i * width + j];
				reference = sample(((float)j + 0.5f) / (float)width, ((float)i + 0.5f) / (float)height);
			}
		}
		val.SetPixels(array);
		val.Apply();
		Sprite val2 = Sprite.Create(val, new Rect(0f, 0f, (float)width, (float)height), new Vector2(0.5f, 0.5f), 100f, 0u, (SpriteMeshType)0, (Vector4)(sliced ? new Vector4(8f, 8f, 8f, 8f) : Vector4.zero));
		owned.Add((Object)(object)val2);
		owned.Add((Object)(object)val);
		return val2;
	}

	private Sprite MakeWeightIcon()
	{
		Sprite val = MakeSprite(24, 28, delegate(float x, float y)
		{
			//IL_0048: 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_00c7: 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_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: 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_011b: Unknown result type (might be due to invalid IL or missing references)
			int num = Mathf.FloorToInt(x * 24f);
			int num2 = Mathf.FloorToInt(y * 28f);
			int[] array = new int[28]
			{
				0, 0, 7, 9, 10, 10, 10, 10, 9, 9,
				8, 8, 7, 7, 6, 5, 4, 3, 3, 4,
				4, 5, 6, 6, 0, 0, 0, 0
			};
			int num3 = array[num2];
			int num4 = Mathf.Abs(num * 2 - 23);
			if (num3 == 0 || num4 >= num3 * 2)
			{
				return Color.clear;
			}
			if (num4 >= (num3 - 1) * 2 || num2 == 2 || num2 == 23 || array[Mathf.Max(0, num2 - 1)] * 2 <= num4 || array[Mathf.Min(27, num2 + 1)] * 2 <= num4)
			{
				return new Color(0.1f, 0.065f, 0.035f, 1f);
			}
			if (num2 == 18 || num2 == 19)
			{
				return new Color(0.29f, 0.15f, 0.055f, 1f);
			}
			if (num2 > 19 && (num == 9 || num == 13))
			{
				return new Color(0.38f, 0.2f, 0.075f, 1f);
			}
			return (Color)((num2 > 5 && num2 < 13 && (num == 6 || num == 7)) ? new Color(1f, 0.72f, 0.36f, 1f) : Color.Lerp(new Color(0.65f, 0.34f, 0.12f, 1f), new Color(0.94f, 0.6f, 0.25f, 1f), 1f - x));
		}, sliced: false);
		((Texture)val.texture).filterMode = (FilterMode)0;
		return val;
	}

	private bool InsideBolt(float x, float y)
	{
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_001f: 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_0052: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_006e: 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_008a: Unknown result type (might be due to invalid IL or missing references)
		//IL_008f: 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_00ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c2: 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)
		Vector2[] array = (Vector2[])(object)new Vector2[7]
		{
			new Vector2(0.55f, 1f),
			new Vector2(0.18f, 0.48f),
			new Vector2(0.46f, 0.48f),
			new Vector2(0.31f, 0f),
			new Vector2(0.86f, 0.61f),
			new Vector2(0.57f, 0.61f),
			new Vector2(0.77f, 1f)
		};
		bool flag = false;
		int num = 0;
		int num2 = array.Length - 1;
		while (num < array.Length)
		{
			if (array[num].y > y != array[num2].y > y && x < (array[num2].x - array[num].x) * (y - array[num].y) / (array[num2].y - array[num].y) + array[num].x)
			{
				flag = !flag;
			}
			num2 = num++;
		}
		return flag;
	}

	private Image Bar(string name, float y, Color color, Transform parent = null)
	{
		//IL_0051: 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_0109: Unknown result type (might be due to invalid IL or missing references)
		//IL_0157: Unknown result type (might be due to invalid IL or missing references)
		ImageNode(name + " shadow", (Transform)(((Object)(object)parent == (Object)null) ? ((object)root) : ((object)parent)), 188f, y - 2f, builtWidth + 4f, 32f, new Color(0f, 0f, 0f, 0.8f), rounded);
		ImageNode(name + " gold edge", (Transform)(((Object)(object)parent == (Object)null) ? ((object)root) : ((object)parent)), 190f, y, builtWidth, 28f, new Color(0.7f, 0.47f, 0.2f, 1f), rounded);
		ImageNode(name + " inner iron", (Transform)(((Object)(object)parent == (Object)null) ? ((object)root) : ((object)parent)), 192f, y + 2f, builtWidth - 4f, 24f, new Color(0.055f, 0.07f, 0.07f, 0.95f), rounded);
		return ImageNode(name + " fill", (Transform)(((Object)(object)parent == (Object)null) ? ((object)root) : ((object)parent)), 194f, y + 4f, builtWidth - 8f, 20f, color, gradient);
	}

	private RectTransform Resource(string name, Color color, out Image fill, out TMP_Text value)
	{
		//IL_003b: 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)
		RectTransform val = Node(name + " row", (Transform)(object)root, 0f, 114f, 190f + builtWidth, 42f);
		fill = Bar(name, 0f, color, (Transform)(object)val);
		value = Text(name + " amount", (Transform)(object)val, 194f, 0f, builtWidth - 8f, 28f, 22f, Color.white);
		AddBarTextStroke(value);
		return val;
	}

	private void UpdateResource(RectTransform group, Image fill, TMP_Text text, string name, float current, float maximum, float y)
	{
		//IL_0009: 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)
		group.anchoredPosition = new Vector2(0f, 0f - y);
		maximum = Mathf.Max(1f, maximum);
		current = Mathf.Clamp(current, 0f, maximum);
		((Graphic)fill).rectTransform.sizeDelta = new Vector2((builtWidth - 8f) * current / maximum, 20f);
		text.text = name + "  " + Mathf.CeilToInt(current) + " / " + Mathf.CeilToInt(maximum);
	}

	private void UpdateWeight(Player player, float y)
	{
		//IL_0034: 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_00cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_0095: Unknown result type (might be due to invalid IL or missing references)
		float num = Mathf.Max(0f, ((Humanoid)player).GetInventory().GetTotalWeight());
		float num2 = Mathf.Max(1f, player.GetMaxCarryWeight());
		weightRoot.anchoredPosition = new Vector2(0f, 0f - y);
		((Graphic)weightFill).rectTransform.sizeDelta = new Vector2((builtWidth - 8f) * Mathf.Clamp01(num / num2), 20f);
		((Graphic)weightFill).color = ((num > num2) ? new Color(1f, 0.22f, 0.12f, 1f) : ((num >= num2 * 0.85f) ? new Color(1f, 0.72f, 0.22f, 1f) : new Color(0.56f, 0.48f, 0.32f, 1f)));
		weightValue.text = num.ToString("0.#", CultureInfo.InvariantCulture) + " / " + num2.ToString("0.#", CultureInfo.InvariantCulture);
	}

	private void DisableNativeStamina(GameObject obj)
	{
		if (!((Object)(object)obj == (Object)null))
		{
			if (!nativeStamina.ContainsKey(obj))
			{
				nativeStamina.Add(obj, obj.activeSelf);
			}
			if (obj.activeSelf)
			{
				obj.SetActive(false);
			}
		}
	}

	private void HideNativeStamina()
	{
		DisableNativeStamina(((Component)hud.m_staminaBar2Root).gameObject);
		if ((Object)(object)hud.m_staminaBar2Fast != (Object)null && !((Component)hud.m_staminaBar2Fast).transform.IsChildOf((Transform)(object)hud.m_staminaBar2Root))
		{
			DisableNativeStamina(((Component)hud.m_staminaBar2Fast).gameObject);
		}
		if ((Object)(object)hud.m_staminaBar2Slow != (Object)null && !((Component)hud.m_staminaBar2Slow).transform.IsChildOf((Transform)(object)hud.m_staminaBar2Root))
		{
			DisableNativeStamina(((Component)hud.m_staminaBar2Slow).gameObject);
		}
		if ((Object)(object)hud.m_staminaText != (Object)null && !hud.m_staminaText.transform.IsChildOf((Transform)(object)hud.m_staminaBar2Root))
		{
			DisableNativeStamina(((Component)hud.m_staminaText).gameObject);
		}
	}

	private void Remember(GameObject obj)
	{
		CanvasGroup val = obj.GetComponent<CanvasGroup>();
		if ((Object)(object)val == (Object)null)
		{
			val = obj.AddComponent<CanvasGroup>();
			createdGroups.Add(val);
		}
		if (!hidden.ContainsKey(val))
		{
			hidden.Add(val, val.alpha);
		}
	}

	private void Initialize(Hud current)
	{
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Expected O, but got Unknown
		//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_012a: Unknown result type (might be due to invalid IL or missing references)
		//IL_015b: Unknown result type (might be due to invalid IL or missing references)
		//IL_018c: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bd: 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_02de: Unknown result type (might be due to invalid IL or missing references)
		//IL_030a: 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_0385: Unknown result type (might be due to invalid IL or missing references)
		//IL_03cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_03ff: Unknown result type (might be due to invalid IL or missing references)
		//IL_043c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0478: Unknown result type (might be due to invalid IL or missing references)
		//IL_04ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_04f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_0526: Unknown result type (might be due to invalid IL or missing references)
		//IL_0561: Unknown result type (might be due to invalid IL or missing references)
		//IL_0616: Unknown result type (might be due to invalid IL or missing references)
		//IL_06d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_0730: Unknown result type (might be due to invalid IL or missing references)
		//IL_0772: Unknown result type (might be due to invalid IL or missing references)
		Cleanup();
		hud = current;
		builtWidth = DesiredBarWidth;
		canvasObject = new GameObject("MMC_BottomVitalsCanvas", new Type[2]
		{
			typeof(RectTransform),
			typeof(Canvas)
		});
		Canvas component = canvasObject.GetComponent<Canvas>();
		component.renderMode = (RenderMode)0;
		component.sortingOrder = 5;
		root = Node("MMC_BottomVitals", canvasObject.transform, 0f, 0f, 190f + builtWidth, 104f);
		panelBackground = ImageNode("Vitals background", (Transform)(object)root, 136f, 0f, builtWidth + 316f, 104f, Color.clear, null);
		panelTop = ImageNode("Vitals top border", (Transform)(object)root, 0f, 0f, 1f, 1f, Color.clear, null);
		panelBottom = ImageNode("Vitals bottom border", (Transform)(object)root, 0f, 0f, 1f, 1f, Color.clear, null);
		panelLeft = ImageNode("Vitals left border", (Transform)(object)root, 0f, 0f, 1f, 1f, Color.clear, null);
		panelRight = ImageNode("Vitals right border", (Transform)(object)root, 0f, 0f, 1f, 1f, Color.clear, null);
		panelHeader = ImageNode("Vitals header", (Transform)(object)root, 0f, 0f, 1f, 1f, Color.clear, null);
		panelTitle = Text("Vitals title", (Transform)(object)root, 144f, -28f, 200f, 24f, 16f, Color.white);
		panelTitle.text = "Vitals";
		panelTitle.alignment = (TextAlignmentOptions)513;
		rounded = MakeSprite(32, 32, delegate(float x, float y)
		{
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			float num2 = Mathf.Max(Mathf.Abs(x - 0.5f) * 32f - 10f, 0f);
			float num3 = Mathf.Max(Mathf.Abs(y - 0.5f) * 32f - 10f, 0f);
			return new Color(1f, 1f, 1f, Mathf.Clamp01(6f - Mathf.Sqrt(num2 * num2 + num3 * num3)));
		}, sliced: true);
		gradient = MakeSprite(4, 32, delegate(float x, float y)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			float num2 = Mathf.Lerp(0.65f, 1f, y);
			return new Color(num2, num2, num2, 1f);
		}, sliced: false);
		Sprite sprite = MakeSprite(64, 64, delegate(float x, float y)
		{
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			float num2 = (x - 0.5f) * 2.7f;
			float num3 = (y - 0.46f) * 2.7f;
			float num4 = num2 * num2 + num3 * num3 - 1f;
			bool flag = num4 * num4 * num4 - num2 * num2 * num3 * num3 * num3 <= 0f;
			return new Color(1f, 0.2f + y * 0.15f, 0.16f + y * 0.12f, (float)(flag ? 1 : 0));
		}, sliced: false);
		Sprite sprite2 = MakeSprite(48, 64, (float x, float y) => new Color(1f, 0.65f + y * 0.3f, 0.15f + y * 0.25f, (float)(InsideBolt(x, y) ? 1 : 0)), sliced: false);
		Image heart = ImageNode("Heart", (Transform)(object)root, 147f, 29f, 32f, 32f, Color.white, sprite);
		Image lightning = ImageNode("Lightning", (Transform)(object)root, 150f, 69f, 26f, 35f, Color.white, sprite2);
		BuildBarBoosts(heart, lightning);
		health = Bar("Health", 30f, new Color(0.8f, 0.12f, 0.105f, 1f));
		ghost = ImageNode("Next heal segment", (Transform)(object)root, 194f, 34f, 0f, 20f, new Color(1f, 0.65f, 0.58f, 0.5f), gradient);
		marker = ImageNode("Next heal marker", (Transform)(object)root, 194f, 28f, 2f, 32f, new Color(1f, 0.77f, 0.37f, 1f), null);
		stamina = Bar("Stamina", 72f, new Color(1f, 0.72f, 0.12f, 1f));
		hpValue = Text("Health amount", (Transform)(object)root, 194f, 30f, builtWidth - 8f, 28f, 22f, Color.white);
		staminaValue = Text("Stamina amount", (Transform)(object)root, 194f, 72f, builtWidth - 8f, 28f, 22f, Color.white);
		AddBarTextStroke(hpValue);
		AddBarTextStroke(staminaValue);
		eitrRoot = Resource("Eitr", new Color(0.62f, 0.23f, 0.95f, 1f), out eitr, out eitrValue);
		adrenalineRoot = Resource("Adrenaline", new Color(1f, 0.36f, 0.075f, 1f), out adrenaline, out adrenalineValue);
		weightRoot = Resource("Carry Weight", new Color(0.56f, 0.48f, 0.32f, 1f), out weightFill, out weightValue);
		ImageNode("Carry weight sack", (Transform)(object)weightRoot, 148f, -3f, 30f, 35f, Color.white, MakeWeightIcon());
		refillRoot = Node("Stamina refill rate", (Transform)(object)root, 190f + builtWidth + 12f, 72f, 110f, 28f);
		refillGroup = ((Component)refillRoot).gameObject.AddComponent<CanvasGroup>();
		refillGroup.alpha = 0f;
		refillGroup.blocksRaycasts = false;
		refillValue = Text("Refill per second", (Transform)(object)refillRoot, 0f, 0f, 110f, 28f, 19f, new Color(1f, 0.86f, 0.38f, 1f));
		refillValue.alignment = (TextAlignmentOptions)513;
		AddBarTextStroke(refillValue);
		RectTransform val = Node("Health rate", (Transform)(object)root, 190f + builtWidth + 140f, 30f, 110f, 28f);
		healthRateGroup = ((Component)val).gameObject.AddComponent<CanvasGroup>();
		healthRateGroup.alpha = 0f;
		healthRateGroup.blocksRaycasts = false;
		healthRateValue = Text("Health regeneration rate", (Transform)(object)val, 0f, 0f, 110f, 28f, 19f, new Color(0.35f, 1f, 0.4f, 1f));
		healthRateValue.alignment = (TextAlignmentOptions)513;
		AddBarTextStroke(healthRateValue);
		BuildFeedback();
		ghostValue = Text("Next heal amount", (Transform)(object)root, 190f, 30f, 50f, 28f, 18f, Color.white);
		nextHeal = Text("Next heal countdown", (Transform)(object)root, 190f + builtWidth + 12f, 30f, 70f, 28f, 17f, Color.white);
		nextHeal.alignment = (TextAlignmentOptions)4097;
		if ((Object)(object)hud.m_eitrBarRoot != (Object)null)
		{
			Remember(((Component)hud.m_eitrBarRoot).gameObject);
		}
		if ((Object)(object)hud.m_adrenalineBarRoot != (Object)null)
		{
			Remember(((Component)hud.m_adrenalineBarRoot).gameObject);
		}
		if ((Object)(object)hud.m_eitrText != (Object)null && ((Object)(object)hud.m_eitrBarRoot == (Object)null || !hud.m_eitrText.transform.IsChildOf((Transform)(object)hud.m_eitrBarRoot)))
		{
			Remember(((Component)hud.m_eitrText).gameObject);
		}
		if ((Object)(object)hud.m_adrenalineText != (Object)null && ((Object)(object)hud.m_adrenalineBarRoot == (Object)null || !hud.m_adrenalineText.transform.IsChildOf((Transform)(object)hud.m_adrenalineBarRoot)))
		{
			Remember(((Component)hud.m_adrenalineText).gameObject);
		}
		if ((Object)(object)hud.m_healthPanel != (Object)null)
		{
			Graphic[] componentsInChildren = ((Component)hud.m_healthPanel).GetComponentsInChildren<Graphic>(true);
			foreach (Graphic val2 in componentsInChildren)
			{
				Transform transform = ((Component)val2).transform;
				Transform val3 = (((Object)(object)hud.m_gpRoot != (Object)null) ? ((Component)hud.m_gpRoot).transform : null);
				Transform statusEffectListRoot = (Transform)(object)hud.m_statusEffectListRoot;
				if ((!((Object)(object)val3 != (Object)null) || (!transform.IsChildOf(val3) && !val3.IsChildOf(transform))) && (!((Object)(object)statusEffectListRoot != (Object)null) || (!transform.IsChildOf(statusEffectListRoot) && !statusEffectListRoot.IsChildOf(transform))))
				{
					Remember(((Component)val2).gameObject);
				}
			}
		}
		Remember(((Component)hud.m_healthBarRoot).gameObject);
		if (!hud.m_healthText.transform.IsChildOf((Transform)(object)hud.m_healthBarRoot))
		{
			Remember(((Component)hud.m_healthText).gameObject);
		}
		Remember(((Component)hud.m_staminaBar2Root).gameObject);
		if (!hud.m_staminaText.transform.IsChildOf((Transform)(object)hud.m_staminaBar2Root))
		{
			Remember(((Component)hud.m_staminaText).gameObject);
		}
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Bottom-center 2D bars created; portrait rendering completely removed.");
	}

	private bool ShouldHideForTool(Player player)
	{
		ItemData rightItem = ((Humanoid)player).RightItem;
		if (rightItem == null)
		{
			toolEquippedAt = -1f;
			return false;
		}
		string text = (((Object)(object)rightItem.m_dropPrefab == (Object)null) ? rightItem.m_shared.m_name : ((Object)rightItem.m_dropPrefab).name);
		if (text.IndexOf("hoe", StringComparison.OrdinalIgnoreCase) < 0 && text.IndexOf("cultivator", StringComparison.OrdinalIgnoreCase) < 0)
		{
			toolEquippedAt = -1f;
			return false;
		}
		if (toolEquippedAt < 0f)
		{
			toolEquippedAt = Time.unscaledTime;
		}
		return Time.unscaledTime - toolEquippedAt >= toolHideDelay.Value;
	}

	private void LateUpdate()
	{
		//IL_0268: Unknown result type (might be due to invalid IL or missing references)
		//IL_0274: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_030b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0332: Unknown result type (might be due to invalid IL or missing references)
		//IL_0357: Unknown result type (might be due to invalid IL or missing references)
		//IL_0385: Unknown result type (might be due to invalid IL or missing references)
		//IL_03da: Unknown result type (might be due to invalid IL or missing references)
		//IL_03d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_04fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0502: Unknown result type (might be due to invalid IL or missing references)
		//IL_0574: Unknown result type (might be due to invalid IL or missing references)
		//IL_0579: Unknown result type (might be due to invalid IL or missing references)
		//IL_058a: Unknown result type (might be due to invalid IL or missing references)
		//IL_058f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0594: Unknown result type (might be due to invalid IL or missing references)
		//IL_05b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_05e4: Unknown result type (might be due to invalid IL or missing references)
		//IL_05e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_0622: Unknown result type (might be due to invalid IL or missing references)
		//IL_0627: Unknown result type (might be due to invalid IL or missing references)
		//IL_06fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_071d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0739: Unknown result type (might be due to invalid IL or missing references)
		//IL_0755: Unknown result type (might be due to invalid IL or missing references)
		//IL_0908: Unknown result type (might be due to invalid IL or missing references)
		//IL_0924: Unknown result type (might be due to invalid IL or missing references)
		//IL_0957: Unknown result type (might be due to invalid IL or missing references)
		//IL_0972: Unknown result type (might be due to invalid IL or missing references)
		//IL_09e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a03: Unknown result type (might be due to invalid IL or missing references)
		HealthBarVisible = false;
		if (failed)
		{
			return;
		}
		try
		{
			Player localPlayer = Player.m_localPlayer;
			if (!enabledPanel.Value || (Object)(object)localPlayer == (Object)null || (Object)(object)Hud.instance == (Object)null)
			{
				Hide();
				return;
			}
			if ((Object)(object)hud != (Object)(object)Hud.instance || (Object)(object)root == (Object)null || builtWidth != DesiredBarWidth)
			{
				Initialize(Hud.instance);
			}
			bool flag = (SagaConfigPreview.Open || !hideForTools.Value || !ShouldHideForTool(localPlayer)) && appearance.InventoryVisible && (SagaConfigPreview.HudVisible(hud) || InventoryGui.IsVisible()) && !((Character)localPlayer).IsDead() && !SagaConfigPreview.MapVisible() && !SagaConfigPreview.StoreVisible() && !SagaConfigPreview.MenuVisible();
			((Component)root).gameObject.SetActive(flag);
			if (!flag)
			{
				refill.Reset();
				refillAlpha = 0f;
				healthRateAlpha = 0f;
				pendingSpend = 0f;
				pendingSpendUntil = 0f;
				SuppressNativeVitals();
				return;
			}
			float num = Mathf.Max(0f, ((Character)localPlayer).GetMaxEitr());
			float num2 = Mathf.Max(0f, localPlayer.GetEitr());
			float num3 = Mathf.Max(0f, ((Character)localPlayer).GetMaxAdrenaline());
			float num4 = Mathf.Max(0f, localPlayer.GetAdrenaline());
			if (num > 0f)
			{
				lastMaxEitr = num;
			}
			if (num3 > 0f)
			{
				lastMaxAdrenaline = num3;
			}
			bool flag2 = num > 0f || num2 > 0f;
			bool flag3 = num3 > 0f || num4 > 0f;
			((Component)eitrRoot).gameObject.SetActive(flag2);
			((Component)adrenalineRoot).gameObject.SetActive(flag3);
			((Component)weightRoot).gameObject.SetActive(showWeight.Value);
			if (showWeight.Value)
			{
				UpdateWeight(localPlayer, 114 + (flag2 ? 42 : 0) + (flag3 ? 42 : 0));
			}
			float num5 = 104 + (flag2 ? 42 : 0) + (flag3 ? 42 : 0) + (showWeight.Value ? 42 : 0);
			num5 = appearance.Size(new Vector2(builtWidth, num5), 240f, num5).y / appearance.Scale;
			root.sizeDelta = new Vector2(190f + builtWidth, num5);
			float num6 = 136f;
			float num7 = builtWidth + 316f;
			float headerHeight = appearance.HeaderHeight;
			SetPanelImage(panelBackground, num6, 0f - headerHeight, num7, num5 + headerHeight, appearance.Background(1f));
			SetPanelImage(panelTop, num6, 0f - headerHeight, num7, 1f, appearance.Border);
			SetPanelImage(panelBottom, num6, num5 - 1f, num7, 1f, appearance.Border);
			SetPanelImage(panelLeft, num6, 0f - headerHeight, 1f, num5 + headerHeight, appearance.Border);
			SetPanelImage(panelRight, num6 + num7 - 1f, 0f - headerHeight, 1f, num5 + headerHeight, appearance.Border);
			SetPanelImage(panelHeader, num6 + 1f, 0f - headerHeight + 1f, num7 - 2f, Mathf.Max(0f, headerHeight - 2f), appearance.ToolWindow ? Color.clear : appearance.Header);
			((Component)panelTitle).gameObject.SetActive(!appearance.ToolWindow);
			UpdateResource(eitrRoot, eitr, eitrValue, "Eitr", num2, (num > 0f) ? num : Mathf.Max(lastMaxEitr, num2), 114f);
			UpdateResource(adrenalineRoot, adrenaline, adrenalineValue, "Adrenaline", num4, (num3 > 0f) ? num3 : Mathf.Max(lastMaxAdrenaline, num4), flag2 ? 156 : 114);
			float num8 = Mathf.Min(scale.Value * appearance.Scale, Mathf.Min((float)(Screen.width - 32) / Mathf.Max(190f + builtWidth, builtWidth + 500f), Mathf.Max(0.1f, ((float)Screen.height - bottomMargin.Value - 16f) / (num5 + headerHeight))));
			((Transform)root).localScale = Vector3.one * num8;
			float num9 = Mathf.Max(8f, (float)Screen.width * 0.5f - (190f + builtWidth * 0.5f) * num8);
			float num10 = Mathf.Max(8f + headerHeight * num8, (float)Screen.height - bottomMargin.Value - num5 * num8);
			SagaPanelAppearance obj = appearance;
			float num11 = num9;
			float num12 = num10;
			Rect rect = root.rect;
			Rect val = obj.Position(new Rect(num11, num12, ((Rect)(ref rect)).width * num8, num5 * num8));
			num9 = ((Rect)(ref val)).x;
			num10 = ((Rect)(ref val)).y;
			root.anchoredPosition = new Vector2(num9, 0f - num10);
			HealthBarScreenRect = new Rect(num9 + 190f * num8, num10 + 30f * num8, builtWidth * num8, 28f * num8);
			HealingPopupScreenPosition = new Vector2(Mathf.Min((float)(Screen.width - 58), ((Rect)(ref HealthBarScreenRect)).xMax + 145f * num8), ((Rect)(ref HealthBarScreenRect)).y - 20f * num8);
			HealthBarVisible = true;
			foreach (KeyValuePair<CanvasGroup, float> item in hidden)
			{
				if ((Object)(object)item.Key != (Object)null)
				{
					item.Key.alpha = 0f;
				}
			}
			HideNativeStamina();
			float num13 = Mathf.Max(1f, ((Character)localPlayer).GetMaxHealth());
			float num14 = Mathf.Clamp(((Character)localPlayer).GetHealth(), 0f, num13);
			float num15 = Mathf.Max(1f, ((Character)localPlayer).GetMaxStamina());
			float num16 = Mathf.Clamp(localPlayer.GetStamina(), 0f, num15);
			float num17 = builtWidth - 8f;
			((Graphic)health).rectTransform.sizeDelta = new Vector2(num17 * num14 / num13, 20f);
			((Graphic)stamina).rectTransform.sizeDelta = new Vector2(num17 * num16 / num15, 20f);
			hpValue.rectTransform.sizeDelta = new Vector2(num17, 28f);
			staminaValue.rectTransform.sizeDelta = new Vector2(num17, 28f);
			hpValue.text = Mathf.CeilToInt(num14) + " / " + Mathf.CeilToInt(num13);
			staminaValue.text = Mathf.CeilToInt(num16) + " / " + Mathf.CeilToInt(num15);
			UpdateRefill(num16, num15);
			UpdateFeedback(num8);
			UpdateBarBoosts(localPlayer);
			UpdateBarTextStrokes(num8);
			float seconds = float.PositiveInfinity;
			float amount = 0f;
			float interval = 0f;
			float rate = 0f;
			MMCPanelHealing.Predict(localPlayer, out seconds, out amount, out interval, out rate);
			healthRateAlpha = Mathf.MoveTowards(healthRateAlpha, (rate > 0f && num14 < num13 - 0.001f) ? 1f : 0f, Time.unscaledDeltaTime / 0.25f);
			if (rate > 0f)
			{
				healthRateValue.text = "+" + rate.ToString("0.0", CultureInfo.InvariantCulture) + "/s";
			}
			healthRateGroup.alpha = healthRateAlpha;
			if (!previewEnabled.Value)
			{
				amount = 0f;
			}
			amount = MMCHealForecast.Cap(amount, num14, num13);
			bool flag4 = amount > 0f && !float.IsInfinity(seconds);
			Image obj2 = ghost;
			bool enabled = (((Behaviour)marker).enabled = flag4);
			((Behaviour)obj2).enabled = enabled;
			float num18 = 194f + num17 * num14 / num13;
			float num19 = num17 * amount / num13;
			((Graphic)ghost).rectTransform.anchoredPosition = new Vector2(num18, -34f);
			((Graphic)ghost).rectTransform.sizeDelta = new Vector2(num19, 20f);
			((Graphic)marker).rectTransform.anchoredPosition = new Vector2(Mathf.Min(190f + builtWidth - 4f, num18), -28f);
			float num20 = hpValue.GetPreferredValues(hpValue.text).x * 0.5f + 6f;
			float num21 = 190f + builtWidth * 0.5f;
			bool enabled2 = flag4 && num19 >= 24f && (num18 + num19 < num21 - num20 || num18 > num21 + num20);
			((Behaviour)ghostValue).enabled = enabled2;
			ghostValue.rectTransform.anchoredPosition = new Vector2(num18, -30f);
			ghostValue.rectTransform.sizeDelta = new Vector2(num19, 28f);
			ghostValue.text = "+" + amount.ToString("0.#", CultureInfo.InvariantCulture);
			((Behaviour)nextHeal).enabled = flag4;
			nextHeal.text = (flag4 ? (seconds.ToString("0.0", CultureInfo.InvariantCulture) + "s") : "");
			if (SagaPanelUI.PowerOnHotbar)
			{
				RestoreNativePower();
				SetNativePowerHidden(hide: true);
			}
			else
			{
				SetNativePowerHidden(hide: false);
				DockNativePower(num8);
			}
		}
		catch (Exception ex)
		{
			failed = true;
			((BaseUnityPlugin)this).Logger.LogError((object)("Bottom vitals disabled; native HUD restored. " + ex));
			Cleanup();
		}
	}

	private void SetNativePowerHidden(bool hide)
	{
		if ((Object)(object)hud == (Object)null || (Object)(object)hud.m_gpRoot == (Object)null)
		{
			return;
		}
		if ((Object)(object)powerVisibility == (Object)null)
		{
			powerVisibility = ((Component)hud.m_gpRoot).GetComponent<CanvasGroup>();
			if ((Object)(object)powerVisibility == (Object)null)
			{
				powerVisibility = ((Component)hud.m_gpRoot).gameObject.AddComponent<CanvasGroup>();
				createdGroups.Add(powerVisibility);
			}
			originalPowerAlpha = powerVisibility.alpha;
		}
		powerVisibility.alpha = (hide ? 0f : originalPowerAlpha);
	}

	private void SuppressNativeVitals()
	{
		foreach (KeyValuePair<CanvasGroup, float> item in hidden)
		{
			if ((Object)(object)item.Key != (Object)null)
			{
				item.Key.alpha = 0f;
			}
		}
		HideNativeStamina();
		SetNativePowerHidden(hide: true);
	}

	private void RestoreNativePower()
	{
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)nativePower == (Object)null))
		{
			nativePower.anchoredPosition = originalPowerPosition;
			((Transform)nativePower).localScale = originalPowerScale;
			nativePower = null;
		}
	}

	private void DockNativePower(float factor)
	{
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		//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_0092: Unknown result type (might be due to invalid IL or missing references)
		//IL_0097: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_011c: Unknown result type (might be due to invalid IL or missing references)
		//IL_013a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0152: Unknown result type (might be due to invalid IL or missing references)
		//IL_0157: Unknown result type (might be due to invalid IL or missing references)
		//IL_015c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0161: Unknown result type (might be due to invalid IL or missing references)
		//IL_0179: Unknown result type (might be due to invalid IL or missing references)
		//IL_017e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0183: Unknown result type (might be due to invalid IL or missing references)
		//IL_0188: Unknown result type (might be due to invalid IL or missing references)
		//IL_018b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0199: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_01af: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
		if (!showPower.Value || (Object)(object)hud.m_gpRoot == (Object)null)
		{
			RestoreNativePower();
			return;
		}
		Transform transform = ((Component)hud.m_gpRoot).transform;
		RectTransform val = (RectTransform)(object)((transform is RectTransform) ? transform : null);
		if ((Object)(object)val == (Object)null)
		{
			return;
		}
		if ((Object)(object)nativePower != (Object)(object)val)
		{
			RestoreNativePower();
			nativePower = val;
			originalPowerPosition = val.anchoredPosition;
			originalPowerScale = ((Transform)val).localScale;
		}
		Transform parent = ((Transform)val).parent;
		RectTransform val2 = (RectTransform)(object)((parent is RectTransform) ? parent : null);
		if (!((Object)(object)val2 == (Object)null))
		{
			Bounds val3 = RectTransformUtility.CalculateRelativeRectTransformBounds((Transform)(object)val, (Transform)(object)val);
			float num = Mathf.Min(100f / Mathf.Max(1f, ((Bounds)(ref val3)).size.x), 103f / Mathf.Max(1f, ((Bounds)(ref val3)).size.y)) * factor;
			((Transform)val).localScale = new Vector3(num / Mathf.Max(0.001f, Mathf.Abs(((Transform)val2).lossyScale.x)), num / Mathf.Max(0.001f, Mathf.Abs(((Transform)val2).lossyScale.y)), originalPowerScale.z);
			Canvas componentInParent = ((Component)val).GetComponentInParent<Canvas>();
			Camera val4 = (((Object)(object)componentInParent == (Object)null || (int)componentInParent.renderMode == 0) ? null : componentInParent.worldCamera);
			Vector2 val5 = RectTransformUtility.WorldToScreenPoint(val4, ((Transform)val).TransformPoint(((Bounds)(ref val3)).center));
			Vector2 val6 = RectTransformUtility.WorldToScreenPoint((Camera)null, ((Transform)root).TransformPoint(new Vector3(42f, -51.5f, 0f)));
			Vector2 val7 = default(Vector2);
			Vector2 val8 = default(Vector2);
			if (RectTransformUtility.ScreenPointToLocalPointInRectangle(val2, val5, val4, ref val7) && RectTransformUtility.ScreenPointToLocalPointInRectangle(val2, val6, val4, ref val8))
			{
				val.anchoredPosition += val8 - val7;
			}
		}
	}

	private void Restore(bool restoreStamina = true)
	{
		if ((Object)(object)powerVisibility != (Object)null)
		{
			powerVisibility.alpha = originalPowerAlpha;
		}
		RestoreNativePower();
		if (restoreStamina)
		{
			foreach (KeyValuePair<GameObject, bool> item in nativeStamina)
			{
				if ((Object)(object)item.Key != (Object)null)
				{
					item.Key.SetActive(item.Value);
				}
			}
			nativeStamina.Clear();
		}
		foreach (KeyValuePair<CanvasGroup, float> item2 in hidden)
		{
			if ((Object)(object)item2.Key != (Object)null)
			{
				item2.Key.alpha = item2.Value;
			}
		}
	}

	private static void SetPanelImage(Image image, float x, float y, float width, float height, Color color)
	{
		//IL_0009: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		((Graphic)image).rectTransform.anchoredPosition = new Vector2(x, 0f - y);
		((Graphic)image).rectTransform.sizeDelta = new Vector2(width, height);
		((Graphic)image).color = color;
	}

	private void Hide()
	{
		HealthBarVisible = false;
		refill.Reset();
		refillAlpha = 0f;
		healthRateAlpha = 0f;
		pendingSpend = 0f;
		pendingSpendUntil = 0f;
		if ((Object)(object)root != (Object)null)
		{
			((Component)root).gameObject.SetActive(false);
		}
		if (enabledPanel.Value && (Object)(object)hud != (Object)null && (Object)(object)hud == (Object)(object)Hud.instance)
		{
			SuppressNativeVitals();
		}
		else
		{
			Restore();
		}
	}

	private void Cleanup()
	{
		refill.Reset();
		refillAlpha = 0f;
		healthRateAlpha = 0f;
		pendingSpend = 0f;
		pendingSpendUntil = 0f;
		Restore();
		powerVisibility = null;
		hidden.Clear();
		strokes.Clear();
		lastMaxEitr = (lastMaxAdrenaline = 0f);
		foreach (CanvasGroup createdGroup in createdGroups)
		{
			if ((Object)(object)createdGroup != (Object)null)
			{
				Object.Destroy((Object)(object)createdGroup);
			}
		}
		createdGroups.Clear();
		if ((Object)(object)canvasObject != (Object)null)
		{
			Object.Destroy((Object)(object)canvasObject);
		}
		root = null;
		hud = null;
		HealthBarVisible = false;
		foreach (Object item in owned)
		{
			if (item != (Object)null)
			{
				Object.Destroy(item);
			}
		}
		owned.Clear();
	}

	private void OnDestroy()
	{
		Cleanup();
		if (harmony != null)
		{
			harmony.UnpatchSelf();
		}
		if ((Object)(object)instance == (Object)(object)this)
		{
			instance = null;
		}
	}

	private void PatchFeedback()
	{
		//IL_002c: 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_004e: Expected O, but got Unknown
		//IL_004e: Expected O, but got Unknown
		//IL_007c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0089: Expected O, but got Unknown
		harmony.Patch((MethodBase)AccessTools.Method(typeof(Player), "RPC_UseStamina", (Type[])null, (Type[])null), new HarmonyMethod(typeof(MMCCharacterPanel), "BeforeSpend", (Type[])null), new HarmonyMethod(typeof(MMCCharacterPanel), "AfterSpend", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		harmony.Patch((MethodBase)AccessTools.Method(typeof(Hud), "StaminaBarEmptyFlash", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(MMCCharacterPanel), "EmptyFlash", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
	}

	private static void BeforeSpend(Player __instance, out SpendSnapshot __state)
	{
		__state = default(SpendSnapshot);
		if (!((Object)(object)instance == (Object)null) && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer))
		{
			__state.Valid = true;
			__state.Stamina = __instance.GetStamina();
		}
	}

	private static void AfterSpend(Player __instance, SpendSnapshot __state)
	{
		if (!((Object)(object)instance == (Object)null) && __state.Valid && !((Object)(object)instance.root == (Object)null) && ((Component)instance.root).gameObject.activeInHierarchy)
		{
			float num = __state.Stamina - __instance.GetStamina();
			if (num > 0.0001f && !float.IsInfinity(num) && !float.IsNaN(num))
			{
				instance.refill.Reset();
				instance.refillAlpha = 0f;
				instance.refillGroup.alpha = 0f;
				instance.QueueSpend(num);
			}
		}
	}

	private static void EmptyFlash()
	{
		if ((Object)(object)instance != (Object)null && (Object)(object)instance.root != (Object)null && ((Component)instance.root).gameObject.activeInHierarchy)
		{
			instance.emptyUntil = Time.unscaledTime + 0.55f;
		}
	}

	private bool HasVisibleSpend()
	{
		if (pendingSpend > 0f)
		{
			return true;
		}
		SpendVisual[] array = spendVisuals;
		foreach (SpendVisual spendVisual in array)
		{
			if (spendVisual != null && Time.unscaledTime - spendVisual.Born < 1.2f)
			{
				return true;
			}
		}
		return false;
	}

	private void BuildFeedback()
	{
		//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
		emptyUntil = 0f;
		spendIndex = 0;
		pendingSpend = 0f;
		pendingSpendUntil = 0f;
		for (int i = 0; i < spendVisuals.Length; i++)
		{
			SpendVisual spendVisual = new SpendVisual();
			spendVisual.Root = Node("Stamina cost " + i, (Transform)(object)root, 190f + builtWidth + 140f, 72f, 110f, 28f);
			spendVisual.Group = ((Component)spendVisual.Root).gameObject.AddComponent<CanvasGroup>();
			spendVisual.Group.alpha = 0f;
			spendVisual.Group.blocksRaycasts = false;
			spendVisual.Text = Text("Spent", (Transform)(object)spendVisual.Root, 0f, 0f, 110f, 28f, 20f, new Color(1f, 0.12f, 0.08f, 1f));
			spendVisual.Text.alignment = (TextAlignmentOptions)513;
			AddBarTextStroke(spendVisual.Text);
			spendVisuals[i] = spendVisual;
		}
	}

	private void FlushSpend()
	{
		if (!(pendingSpend <= 0f))
		{
			ShowSpend(pendingSpend);
			pendingSpend = 0f;
			pendingSpendUntil = 0f;
		}
	}

	private void QueueSpend(float amount)
	{
		if (pendingSpend > 0f && Time.unscaledTime >= pendingSpendUntil)
		{
			FlushSpend();
		}
		if (amount >= 1f)
		{
			FlushSpend();
			ShowSpend(amount);
			return;
		}
		if (pendingSpend <= 0f)
		{
			pendingSpendUntil = Time.unscaledTime + 0.35f;
		}
		pendingSpend += amount;
	}

	private void ShowSpend(float amount)
	{
		SpendVisual spendVisual = spendVisuals[spendIndex];
		if (spendVisual != null)
		{
			spendIndex = (spendIndex + 1) % spendVisuals.Length;
			spendVisual.Amount = amount;
			spendVisual.Born = Time.unscaledTime;
		}
	}

	private void UpdateFeedback(float factor)
	{
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: 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_00cf: 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 (pendingSpend > 0f && Time.unscaledTime >= pendingSpendUntil)
		{
			FlushSpend();
		}
		float num = Mathf.Clamp01((emptyUntil - Time.unscaledTime) / 0.55f);
		((Graphic)staminaValue).color = Color.Lerp(Color.white, new Color(1f, 0.1f, 0.06f, 1f), Mathf.Min(1f, num * 3f));
		float num2 = ((num > 0f) ? (Mathf.Sin((0.55f - (emptyUntil - Time.unscaledTime)) * 55f) * 3f * num / Mathf.Max(0.1f, factor)) : 0f);
		staminaValue.rectTransform.anchoredPosition = new Vector2(194f + num2, -72f);
		SpendVisual[] array = spendVisuals;
		foreach (SpendVisual spendVisual in array)
		{
			float num3 = Time.unscaledTime - spendVisual.Born;
			spendVisual.Group.alpha = ((num3 < 0f || num3 > 1.2f) ? 0f : Mathf.Clamp01((1.2f - num3) / 0.45f));
			spendVisual.Root.anchoredPosition = new Vector2(190f + builtWidth + 140f, -72f + Mathf.Clamp(num3, 0f, 1.2f) * 12f);
			spendVisual.Text.text = "-" + spendVisual.Amount.ToString("0.#", CultureInfo.InvariantCulture);
		}
	}
}
internal static class MMCBuffTime
{
	public static string Format(double seconds)
	{
		if (double.IsNaN(seconds) || double.IsInfinity(seconds))
		{
			return "--";
		}
		seconds = Math.Max(0.0, seconds);
		if (!(seconds > 60.0))
		{
			return Math.Ceiling(seconds).ToString("0") + "s";
		}
		return Math.Ceiling(seconds / 60.0).ToString("0") + "m";
	}

	public static bool Warn(double seconds)
	{
		if (seconds > 0.0)
		{
			return seconds <= 60.0;
		}
		return false;
	}
}
public static class MMCFoodStaminaForecast
{
	public struct Food
	{
		public double Remaining;

		public double Duration;

		public double BaseStamina;

		public double CurrentStamina;
	}

	public static bool Predict(Food[] foods, double maximum, double timer, double rate, out double seconds, out int amount)
	{
		seconds = 0.0;
		amount = 0;
		if (rate <= 0.0 || foods.Length == 0)
		{
			return false;
		}
		double num = 0.0;
		double num2 = 0.0;
		for (int i = 0; i < foods.Length; i++)
		{
			Food food = foods[i];
			num += food.CurrentStamina;
			num2 = Math.Max(num2, food.Remaining);
		}
		double baseline = maximum - num;
		int num3 = (int)Math.Ceiling(maximum);
		int num4 = (int)Math.Min(1000000.0, Math.Ceiling(num2));
		if (num4 < 1 || Remaining(foods, baseline, num4) >= num3)
		{
			return false;
		}
		int num5 = 1;
		while (num5 < num4)
		{
			int num6 = num5 + (num4 - num5) / 2;
			if (Remaining(foods, baseline, num6) < num3)
			{
				num4 = num6;
			}
			else
			{
				num5 = num6 + 1;
			}
		}
		amount = num3 - Remaining(foods, baseline, num5);
		seconds = Math.Max(0.0, ((double)num5 - Math.Max(0.0, Math.Min(1.0, timer))) / rate);
		return amount > 0;
	}

	private static int Remaining(Food[] foods, double baseline, int ticks)
	{
		double num = baseline;
		for (int i = 0; i < foods.Length; i++)
		{
			Food food = foods[i];
			if (food.Remaining > (double)ticks && food.Duration > 0.0)
			{
				num += food.BaseStamina * Math.Pow(Math.Min(1.0, (food.Remaining - (double)ticks) / food.Duration), 0.3);
			}
		}
		return (int)Math.Ceiling(Math.Max(1.0, num));
	}
}
public static class MMCHealForecast
{
	public static void Include(float seconds, float amount, ref float nextSeconds, ref float nextAmount)
	{
		if (!(amount <= 0f) && !float.IsNaN(amount) && !float.IsInfinity(amount) && !float.IsNaN(seconds) && !float.IsInfinity(seconds))
		{
			seconds = Math.Max(0f, seconds);
			if (seconds < nextSeconds - 0.021f)
			{
				nextSeconds = seconds;
				nextAmount = amount;
			}
			else if (Math.Abs(seconds - nextSeconds) <= 0.021f)
			{
				nextSeconds = Math.Min(seconds, nextSeconds);
				nextAmount += amount;
			}
		}
	}

	public static void IncludeTimed(float seconds, float amount, float interval, ref float nextSeconds, ref float nextAmount, ref float nextInterval)
	{
		if (!(amount <= 0f) && !float.IsNaN(amount) && !float.IsInfinity(amount) && !float.IsNaN(seconds) && !float.IsInfinity(seconds))
		{
			seconds = Math.Max(0f, seconds);
			if (seconds < nextSeconds - 0.021f)
			{
				nextInterval = interval;
			}
			else if (Math.Abs(seconds - nextSeconds) <= 0.021f)
			{
				nextInterval = Math.Max(nextInterval, interval);
			}
			Include(seconds, amount, ref nextSeconds, ref nextAmount);
		}
	}

	public static float Progress(float seconds, float interval)
	{
		if (interval <= 0f || float.IsNaN(interval) || float.IsInfinity(interval) || float.IsNaN(seconds) || float.IsInfinity(seconds))
		{
			return 0f;
		}
		return Math.Max(0f, Math.Min(1f, 1f - seconds / interval));
	}

	public static float Cap(float amount, float health, float maxHealth)
	{
		return Math.Max(0f, Math.Min(amount, maxHealth - health));
	}
}
public static class MMCPanelHealing
{
	private static readonly FieldInfo foodTimer = AccessTools.Field(typeof(Player), "m_foodRegenTimer");

	private static readonly FieldInfo tickTimer = AccessTools.Field(typeof(SE_Stats), "m_tickTimer");

	private static readonly FieldInfo hotTimer = AccessTools.Field(typeof(SE_Stats), "m_healthOverTimeTimer");

	private static readonly FieldInfo hotTicks = AccessTools.Field(typeof(SE_Stats), "m_healthOverTimeTicks");

	private static readonly FieldInfo hotHP = AccessTools.Field(typeof(SE_Stats), "m_healthOverTimeTickHP");

	public static void Predict(Player player, out float seconds, out float amount, out float interval, out float rate)
	{
		seconds = float.PositiveInfinity;
		amount = 0f;
		interval = 0f;
		rate = 0f;
		if (((Character)player).IsTeleporting() || ((Character)player).InIntro())
		{
			return;
		}
		float num = Mathf.Max(0f, 10f - (float)foodTimer.GetValue(player));
		float num2 = 0f;
		foreach (Food food in player.GetFoods())
		{
			if (food.m_item != null && food.m_time > num * Game.m_foodRate)
			{
				num2 += food.m_item.m_shared.m_foodRegen;
			}
		}
		float num3 = 1f;
		((Character)player).GetSEMan().ModifyHealthRegen(ref num3);
		MMCHealForecast.IncludeTimed(num, num2 * num3, 10f, ref seconds, ref amount, ref interval);
		rate += Mathf.Max(0f, num2 * num3) / 10f;
		foreach (StatusEffect statusEffect in ((Character)player).GetSEMan().GetStatusEffects())
		{
			SE_Stats val = (SE_Stats)(object)((statusEffect is SE_Stats) ? statusEffect : null);
			if ((Object)(object)val == (Object)null)
			{
				continue;
			}
			float num4 = ((statusEffect.m_ttl > 0f) ? statusEffect.GetRemaningTime() : float.PositiveInfinity);
			if (val.m_tickInterval > 0f && val.m_healthPerTick > 0f && ((Character)player).GetHealthPercentage() >= val.m_healthPerTickMinHealthPercentage)
			{
				float num5 = Mathf.Max(0f, val.m_tickInterval - (float)tickTimer.GetValue(val));
				if (num5 <= num4)
				{
					MMCHealForecast.IncludeTimed(num5, val.m_healthPerTick, val.m_tickInterval, ref seconds, ref amount, ref interval);
					rate += val.m_healthPerTick / val.m_tickInterval;
				}
			}
			if ((float)hotTicks.GetValue(val) > 0f)
			{
				float num6 = Mathf.Max(0f, val.m_healthOverTimeInterval - (float)hotTimer.GetValue(val));
				if (num6 <= num4 && val.m_healthOverTimeInterval > 0f)
				{
					float num7 = (float)hotHP.GetValue(val);
					MMCHealForecast.IncludeTimed(num6, num7, val.m_healthOverTimeInterval, ref seconds, ref amount, ref interval);
					rate += Mathf.Max(0f, num7) / val.m_healthOverTimeInterval;
				}
			}
		}
	}
}
public sealed class MMCStaminaRate
{
	private const double SampleGrace = 0.35;

	public double Rate;

	public double LastSample;

	public bool Refilling;

	private double recovered;

	public void Reset()
	{
		Rate = 0.0;
		LastSample = 0.0;
		Refilling = false;
		recovered = 0.0;
	}

	public void Observe(double now, double before, double after, double oldMaximum, double maximum, double dt)
	{
		double num = after - before;
		if (dt <= 0.0 || dt > 1.0 || double.IsNaN(num) || double.IsInfinity(num) || double.IsNaN(maximum) || double.IsInfinity(maximum) || maximum <= 0.0 || maximum > oldMaximum + 0.001 || after >= maximum - 0.001 || num < -1E-05)
		{
			Reset();
			return;
		}
		if (Refilling && (now - LastSample >= 0.35 || now < LastSample))
		{
			Reset();
		}
		if (!(num <= 1E-05))
		{
			double num2 = num / dt;
			Rate = ((!Refilling) ? num2 : (Rate + (num2 - Rate) * (1.0 - Math.Exp((0.0 - dt) / 0.2))));
			recovered += num;
			LastSample = now;
			Refilling = true;
		}
	}

	public bool Visible(double now)
	{
		if (Refilling && recovered >= 9.999999 && now >= LastSample)
		{
			return now - LastSample < 0.35;
		}
		return false;
	}
}
public sealed class SagaBoostWipe
{
	private bool initialized;

	private int previousBonus;

	private double previousFoodTime;

	private double span;

	public float Update(int bonus, double foodTime, double ticksRemaining, bool predicted)
	{
		if (bonus <= 0 || !predicted || double.IsNaN(ticksRemaining) || double.IsInfinity(ticksRemaining))
		{
			initialized = false;
			return 0f;
		}
		if (!initialized || bonus != previousBonus || foodTime > previousFoodTime + 0.5 || ticksRemaining > span + 0.01)
		{
			span = Math.Max(0.001, ticksRemaining);
		}
		initialized = true;
		previousBonus = bonus;
		previousFoodTime = foodTime;
		return (float)Math.Max(0.0, Math.Min(1.0, 1.0 - ticksRemaining / span));
	}
}
internal static class SagaConfigPreview
{
	private static BaseUnityPlugin manager;

	private static PropertyInfo displaying;

	private static float retry;

	private static int frame = -1;

	private static bool open;

	internal static bool Open
	{
		get
		{
			if (frame == Time.frameCount)
			{
				return open;
			}
			frame = Time.frameCount;
			open = false;
			if ((Object)(object)manager == (Object)null && Time.unscaledTime >= retry)
			{
				retry = Time.unscaledTime + 2f;
				if (Chainloader.PluginInfos.TryGetValue("com.bepis.bepinex.configurationmanager", out var value))
				{
					manager = value.Instance;
					displaying = ((object)manager).GetType().GetProperty("DisplayingWindow", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				}
			}
			if ((Object)(object)manager != (Object)null && displaying != null)
			{
				try
				{
					open = (bool)displaying.GetValue(manager, null);
				}
				catch
				{
					open = false;
				}
			}
			return open;
		}
	}

	internal static bool HudVisible(Hud hud)
	{
		if ((Object)(object)hud != (Object)null)
		{
			if (!Open)
			{
				return hud.IsVisible();
			}
			return true;
		}
		return false;
	}

	internal static bool MenuVisible()
	{
		if (!Open)
		{
			return Menu.IsVisible();
		}
		return false;
	}

	internal static bool MapVisible()
	{
		if (!Open)
		{
			return Minimap.IsOpen();
		}
		return false;
	}

	internal static bool StoreVisible()
	{
		if (!Open)
		{
			return StoreGui.IsVisible();
		}
		return false;
	}

	internal static bool InventoryHidesHud()
	{
		if (!Open)
		{
			return InventoryGui.IsVisible();
		}
		return false;
	}
}
public static class SagaFoodBoostForecast
{
	public struct Food
	{
		public float Remaining;

		public float Duration;

		public float Base;

		public float Current;
	}

	public static int Bonus(Food[] foods)
	{
		float num = 0f;
		for (int i = 0; i < foods.Length; i++)
		{
			Food food = foods[i];
			num += Math.Max(0f, food.Current);
		}
		return (int)Math.Ceiling(num);
	}

	private static int At(Food[] foods, int ticks)
	{
		float num = 0f;
		for (int i = 0; i < foods.Length; i++)
		{
			Food food = foods[i];
			if (!(food.Duration <= 0f) && !(food.Remaining <= (float)ticks))
			{
				float num2 = Math.Max(0f, Math.Min(1f, (food.Remaining - (float)ticks) / food.Duration));
				num += food.Base * (float)Math.Pow(num2, 0.30000001192092896);
			}
		}
		return (int)Math.Ceiling(Math.Max(0f, num));
	}

	public static bool Predict(Food[] foods, double timer, double rate, out double seconds, out int drop)
	{
		seconds = 0.0;
		drop = 0;
		if (foods == null || foods.Length == 0 || rate <= 0.0 || double.IsNaN(rate) || double.IsInfinity(rate) || double.IsNaN(timer) || double.IsInfinity(timer))
		{
			return false;
		}
		int num = Bonus(foods);
		if (num <= 0)
		{
			return false;
		}
		double num2 = 0.0;
		for (int i = 0; i < foods.Length; i++)
		{
			Food food = foods[i];
			num2 = Math.Max(num2, food.Remaining);
		}
		int num3 = (int)Math.Min(1000000.0, Math.Ceiling(num2));
		if (num3 < 1 || At(foods, num3) >= num)
		{
			return false;
		}
		int num4 = 1;
		while (num4 < num3)
		{
			int num5 = num4 + (num3 - num4) / 2;
			if (At(foods, num5) < num)
			{
				num3 = num5;
			}
			else
			{
				num4 = num5 + 1;
			}
		}
		drop = num - At(foods, num4);
		seconds = Math.Max(0.0, ((double)num4 - timer) / rate);
		return drop > 0;
	}
}

BepInEx/plugins/MMC-ClockDock/MMCClockDock.dll

Decompiled a week ago
using System;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;
using UnityEngine.UI;

[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: CompilationRelaxations(8)]
[assembly: AssemblyVersion("0.0.0.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[DefaultExecutionOrder(11000)]
[BepInPlugin("local.mmc.clockdock", "Saga Minimap", "3.0.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public sealed class MMCClockDock : BaseUnityPlugin
{
	private static MMCClockDock instance;

	private static readonly MethodInfo currentDay = AccessTools.Method(typeof(EnvMan), "GetCurrentDay", (Type[])null, (Type[])null);

	private static readonly FieldInfo smoothDay = AccessTools.Field(typeof(EnvMan), "m_smoothDayFraction");

	private Harmony harmony;

	private ConfigEntry<bool> enabledPanel;

	private ConfigEntry<bool> enabledAddon;

	private SagaPanelWindow drag;

	private FieldInfo clockStyle;

	private FieldInfo clockText;

	private FieldInfo clockWindow;

	private RectTransform smallRoot;

	private RectTransform frame;

	private RectTransform header;

	private Vector2 originalPosition;

	private Vector3 originalScale;

	private Image mapBackground;

	private Image mapBorder;

	private ConfigEntry<bool> footerBackground;

	private ConfigEntry<Color> footerColor;

	private ConfigEntry<Color> footerTextColor;

	private ConfigEntry<Color> footerStrokeColor;

	private ConfigEntry<float> footerOpacity;

	private ConfigEntry<int> footerStroke;

	private GUIStyle outlineStyle;

	private Rect panel;

	private Rect defaultPanel;

	private bool active;

	private float footerHeight = 32f;

	private GUIStyle textStyle;

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

	private void Awake()
	{
		//IL_006d: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bb: Expected O, but got Unknown
		//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_012e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0138: 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_01e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f1: Expected O, but got Unknown
		//IL_0214: Unknown result type (might be due to invalid IL or missing references)
		//IL_0222: Expected O, but got Unknown
		instance = this;
		enabledAddon = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "Enabled", true, "Enable Saga minimap layout and day/time styling. Disable to restore the native map and original AzuClock.");
		footerBackground = ((BaseUnityPlugin)this).Config.Bind<bool>("Day and Time", "Show Background", true, "Show the background behind day and time. Disable for text over the world.");
		footerColor = ((BaseUnityPlugin)this).Config.Bind<Color>("Day and Time", "Background Color", new Color(0.035f, 0.04f, 0.035f, 1f), "Footer background color; its alpha multiplies Background Opacity.");
		footerOpacity = ((BaseUnityPlugin)this).Config.Bind<float>("Day and Time", "Background Opacity", 1f, new ConfigDescription("0 is clear, 1 is fully opaque.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), new object[0]));
		footerTextColor = ((BaseUnityPlugin)this).Config.Bind<Color>("Day and Time", "Text Color", Color.white, "Color of both day and time. Keeps the existing font.");
		footerStrokeColor = ((BaseUnityPlugin)this).Config.Bind<Color>("Day and Time", "Stroke Color", Color.black, "Text outline color.");
		footerStroke = ((BaseUnityPlugin)this).Config.Bind<int>("Day and Time", "Stroke Width", 1, new ConfigDescription("Outline thickness in screen pixels. 0 disables it; default 1 px.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 3), new object[0]));
		enabledPanel = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "Dock Below Minimap", true, "Enable Saga minimap frame with day and time in its draggable footer. Retains the previous clock-dock setting key.");
		drag = new SagaPanelWindow(((BaseUnityPlugin)this).Config, "SagaMinimap");
		drag.MinimumWidth = 120f;
		drag.MinimumHeight = 150f;
		Type type = ((object)Chainloader.PluginInfos["Azumatt.AzuClock"].Instance).GetType();
		clockStyle = AccessTools.Field(type, "Style");
		clockText = AccessTools.Field(type, "NewTimeString");
		clockWindow = AccessTools.Field(type, "_windowRect");
		harmony = new Harmony("local.mmc.clockdock");
		harmony.Patch((MethodBase)AccessTools.Method(type, "OnGUI", (Type[])null, (Type[])null), new HarmonyMethod(typeof(MMCClockDock), "DrawOriginalClock", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
	}

	private static bool DrawOriginalClock()
	{
		if (!((Object)(object)instance == (Object)null))
		{
			return !instance.active;
		}
		return true;
	}

	private static Camera UICamera(RectTransform rect)
	{
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		Canvas componentInParent = ((Component)rect).GetComponentInParent<Canvas>();
		if (!((Object)(object)componentInParent == (Object)null) && (int)componentInParent.renderMode != 0)
		{
			return componentInParent.worldCamera;
		}
		return null;
	}

	private Rect Bounds(RectTransform rect)
	{
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: 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_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0076: Unknown result type (might be due to invalid IL or missing references)
		rect.GetWorldCorners(corners);
		Camera val = UICamera(rect);
		Vector2 val2 = RectTransformUtility.WorldToScreenPoint(val, corners[0]);
		Vector2 val3 = RectTransformUtility.WorldToScreenPoint(val, corners[2]);
		return new Rect(val2.x, (float)Screen.height - val3.y, val3.x - val2.x, val3.y - val2.y);
	}

	private static Image Image(Transform parent, string name, Color color)
	{
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: Expected O, but got Unknown
		//IL_0039: 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_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_0056: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: 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)
		GameObject val = new GameObject(name, new Type[2]
		{
			typeof(RectTransform),
			typeof(Image)
		});
		RectTransform component = val.GetComponent<RectTransform>();
		((Transform)component).SetParent(parent, false);
		component.anchorMin = Vector2.zero;
		component.anchorMax = Vector2.one;
		Vector2 offsetMin = (component.offsetMax = Vector2.zero);
		component.offsetMin = offsetMin;
		Image component2 = val.GetComponent<Image>();
		((Graphic)component2).color = color;
		((Graphic)component2).raycastTarget = false;
		return component2;
	}

	private void Build(RectTransform root)
	{
		//IL_000f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0014: 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_0020: 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_0060: 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_008b: Unknown result type (might be due to invalid IL or missing references)
		//IL_008c: 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_009e: 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)
		//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_011e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0138: Unknown result type (might be due to invalid IL or missing references)
		//IL_0152: Unknown result type (might be due to invalid IL or missing references)
		Cleanup();
		smallRoot = root;
		originalPosition = root.anchoredPosition;
		originalScale = ((Transform)root).localScale;
		frame = ((Graphic)Image((Transform)(object)root, "Saga minimap frame", new Color(0.38f, 0.26f, 0.13f, 1f))).rectTransform;
		mapBorder = Image((Transform)(object)frame, "Map border", Color.clear);
		((Transform)frame).SetAsFirstSibling();
		RectTransform obj = frame;
		Vector2 anchorMin = (frame.anchorMax = Vector2.zero);
		obj.anchorMin = anchorMin;
		frame.pivot = Vector2.zero;
		RectTransform rectTransform = ((Graphic)Image((Transform)(object)frame, "Dark panel", new Color(0.035f, 0.04f, 0.035f, 1f))).rectTransform;
		rectTransform.offsetMin = Vector2.one;
		rectTransform.offsetMax = -Vector2.one;
		mapBackground = ((Component)rectTransform).GetComponent<Image>();
		header = ((Graphic)Image((Transform)(object)frame, "Day and time footer", new Color(0.16f, 0.105f, 0.055f, 1f))).rectTransform;
		header.anchorMin = Vector2.zero;
		header.anchorMax = new Vector2(1f, 0f);
	}

	private void LateUpdate()
	{
		//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c1: 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_00dc: 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_0111: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bb: Expected O, but got Unknown
		//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0277: Unknown result type (might be due to invalid IL or missing references)
		//IL_027c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0289: Unknown result type (might be due to invalid IL or missing references)
		//IL_028e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0293: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_02cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_034e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0355: Unknown result type (might be due to invalid IL or missing references)
		//IL_036b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0370: Unknown result type (might be due to invalid IL or missing references)
		//IL_0417: Unknown result type (might be due to invalid IL or missing references)
		//IL_0423: Unknown result type (might be due to invalid IL or missing references)
		//IL_04f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0512: Unknown result type (might be due to invalid IL or missing references)
		//IL_0479: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_0550: Unknown result type (might be due to invalid IL or missing references)
		//IL_0555: Unknown result type (might be due to invalid IL or missing references)
		//IL_0540: Unknown result type (might be due to invalid IL or missing references)
		//IL_04a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_04c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_04c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_04ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_04cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_04d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_058f: Unknown result type (might be due to invalid IL or missing references)
		//IL_05b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_05f4: Unknown result type (might be due to invalid IL or missing references)
		//IL_0625: Unknown result type (might be due to invalid IL or missing references)
		//IL_0635: Unknown result type (might be due to invalid IL or missing references)
		//IL_0637: Unknown result type (might be due to invalid IL or missing references)
		//IL_0639: Unknown result type (might be due to invalid IL or missing references)
		//IL_064f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0654: Unknown result type (might be due to invalid IL or missing references)
		//IL_067c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0693: Unknown result type (might be due to invalid IL or missing references)
		//IL_06af: Unknown result type (might be due to invalid IL or missing references)
		//IL_06c4: Unknown result type (might be due to invalid IL or missing references)
		//IL_06e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_06fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0700: Unknown result type (might be due to invalid IL or missing references)
		//IL_0717: Unknown result type (might be due to invalid IL or missing references)
		//IL_0762: Unknown result type (might be due to invalid IL or missing references)
		active = false;
		if (!enabledAddon.Value || !enabledPanel.Value || (Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)Minimap.instance == (Object)null)
		{
			Cleanup();
			return;
		}
		Minimap val = Minimap.instance;
		Transform transform = val.m_smallRoot.transform;
		RectTransform val2 = (RectTransform)(object)((transform is RectTransform) ? transform : null);
		if ((Object)(object)val2 != (Object)(object)smallRoot)
		{
			Build(val2);
		}
		if (!val.m_smallRoot.activeInHierarchy || SagaConfigPreview.MapVisible() || SagaConfigPreview.MenuVisible())
		{
			if ((Object)(object)frame != (Object)null)
			{
				((Component)frame).gameObject.SetActive(false);
			}
			return;
		}
		smallRoot.anchoredPosition = originalPosition;
		((Transform)smallRoot).localScale = originalScale;
		Rect val3 = Bounds(((Graphic)val.m_mapImageSmall).rectTransform);
		if ((Object)(object)val.m_biomeNameSmall != (Object)null && ((Component)val.m_biomeNameSmall).gameObject.activeInHierarchy)
		{
			Rect val4 = Bounds(val.m_biomeNameSmall.rectTransform);
			((Rect)(ref val3)).xMin = Mathf.Min(((Rect)(ref val3)).xMin, ((Rect)(ref val4)).xMin);
			((Rect)(ref val3)).xMax = Mathf.Max(((Rect)(ref val3)).xMax, ((Rect)(ref val4)).xMax);
			((Rect)(ref val3)).yMin = Mathf.Min(((Rect)(ref val3)).yMin, ((Rect)(ref val4)).yMin);
			((Rect)(ref val3)).yMax = Mathf.Max(((Rect)(ref val3)).yMax, ((Rect)(ref val4)).yMax);
		}
		object? value = clockStyle.GetValue(null);
		GUIStyle val5 = (GUIStyle)((value is GUIStyle) ? value : null);
		string text = (clockText.GetValue(null) as string) ?? "";
		Vector2 val6 = (Vector2)((val5 == null) ? new Vector2(100f, 24f) : val5.CalcSize(new GUIContent(text)));
		footerHeight = Mathf.Max(54f, 2f * ((val5 == null) ? 22f : val5.lineHeight) + 10f);
		float num = ((!drag.ToolWindow) ? 12 : 0);
		float num2 = ((!drag.ToolWindow) ? 4 : 0);
		float num3 = Mathf.Max(((Rect)(ref val3)).width + num, 150f);
		float num4 = ((Rect)(ref val3)).height + footerHeight + drag.HeaderHeight + num;
		defaultPanel = new Rect(Mathf.Max(0f, (float)Screen.width - num3 - num2), num2, num3, num4);
		defaultPanel = drag.Sized(defaultPanel);
		((Rect)(ref defaultPanel)).x = Mathf.Max(0f, (float)Screen.width - ((Rect)(ref defaultPanel)).width - num2);
		panel = drag.Resolve(defaultPanel);
		float num5 = Mathf.Min(Mathf.Max(1f, ((Rect)(ref panel)).width - num) / Mathf.Max(1f, ((Rect)(ref val3)).width), Mathf.Max(1f, ((Rect)(ref panel)).height - footerHeight - drag.HeaderHeight - num) / Mathf.Max(1f, ((Rect)(ref val3)).height));
		((Transform)smallRoot).localScale = originalScale * num5;
		val3 = Bounds(((Graphic)val.m_mapImageSmall).rectTransform);
		if ((Object)(object)val.m_biomeNameSmall != (Object)null && ((Component)val.m_biomeNameSmall).gameObject.activeInHierarchy)
		{
			Rect val7 = Bounds(val.m_biomeNameSmall.rectTransform);
			((Rect)(ref val3)).xMin = Mathf.Min(((Rect)(ref val3)).xMin, ((Rect)(ref val7)).xMin);
			((Rect)(ref val3)).xMax = Mathf.Max(((Rect)(ref val3)).xMax, ((Rect)(ref val7)).xMax);
			((Rect)(ref val3)).yMin = Mathf.Min(((Rect)(ref val3)).yMin, ((Rect)(ref val7)).yMin);
			((Rect)(ref val3)).yMax = Mathf.Max(((Rect)(ref val3)).yMax, ((Rect)(ref val7)).yMax);
		}
		Vector2 val8 = default(Vector2);
		((Vector2)(ref val8))..ctor(((Rect)(ref panel)).center.x - ((Rect)(ref val3)).center.x, ((Rect)(ref panel)).y + drag.HeaderHeight + num * 0.5f - ((Rect)(ref val3)).y);
		Transform parent = ((Transform)smallRoot).parent;
		RectTransform val9 = (RectTransform)(object)((parent is RectTransform) ? parent : null);
		Vector2 val10 = default(Vector2);
		Vector2 val11 = default(Vector2);
		if ((Object)(object)val9 != (Object)null && RectTransformUtility.ScreenPointToLocalPointInRectangle(val9, Vector2.zero, UICamera(smallRoot), ref val10) && RectTransformUtility.ScreenPointToLocalPointInRectangle(val9, new Vector2(val8.x, 0f - val8.y), UICamera(smallRoot), ref val11))
		{
			RectTransform obj = smallRoot;
			obj.anchoredPosition += val11 - val10;
		}
		((Component)frame).gameObject.SetActive(true);
		((Graphic)((Component)frame).GetComponent<Image>()).color = Color.clear;
		((Graphic)mapBorder).color = drag.Appearance.Border;
		if ((Object)(object)mapBackground != (Object)null)
		{
			((Graphic)mapBackground).color = drag.Appearance.Background(1f);
		}
		Color value2 = footerColor.Value;
		value2.a *= (footerBackground.Value ? footerOpacity.Value : 0f);
		((Graphic)((Component)header).GetComponent<Image>()).color = value2;
		Vector2 val12 = default(Vector2);
		RectTransformUtility.ScreenPointToLocalPointInRectangle(smallRoot, new Vector2(((Rect)(ref panel)).x, (float)Screen.height - ((Rect)(ref panel)).yMax), UICamera(smallRoot), ref val12);
		Vector2 val13 = default(Vector2);
		RectTransformUtility.ScreenPointToLocalPointInRectangle(smallRoot, new Vector2(((Rect)(ref panel)).xMax, (float)Screen.height - ((Rect)(ref panel)).y), UICamera(smallRoot), ref val13);
		((Transform)frame).localPosition = new Vector3(val12.x, val12.y, 0f);
		frame.sizeDelta = val13 - val12;
		float num6 = footerHeight;
		Rect rect = frame.rect;
		float num7 = num6 * (((Rect)(ref rect)).height / Mathf.Max(1f, ((Rect)(ref panel)).height));
		header.offsetMin = Vector2.zero;
		header.offsetMax = new Vector2(0f, num7);
		((Graphic)mapBorder).rectTransform.offsetMin = new Vector2(0f, num7);
		((Graphic)mapBorder).rectTransform.offsetMax = Vector2.zero;
		((Graphic)mapBackground).rectTransform.offsetMin = new Vector2(1f, num7 + 1f);
		((Graphic)mapBackground).rectTransform.offsetMax = -Vector2.one;
		clockWindow.SetValue(null, (object)new Rect(((Rect)(ref panel)).center.x - val6.x * 0.5f, ((Rect)(ref panel)).y + 5f, Mathf.Max(1f, val6.x), Mathf.Max(1f, val6.y)));
		drag.ContentVisible(((Component)smallRoot).gameObject, !drag.Minimized);
		active = true;
	}

	private void OnGUI()
	{
		//IL_0369: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_009b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0157: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f8: 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_00be: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_0102: Expected O, but got Unknown
		//IL_0109: Unknown result type (might be due to invalid IL or missing references)
		//IL_0113: Expected O, but got Unknown
		//IL_0219: Unknown result type (might be due to invalid IL or missing references)
		//IL_021e: 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_0261: Unknown result type (might be due to invalid IL or missing references)
		//IL_0277: Unknown result type (might be due to invalid IL or missing references)
		//IL_0293: Unknown result type (might be due to invalid IL or missing references)
		//IL_0298: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_0350: Unknown result type (might be due to invalid IL or missing references)
		//IL_035a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0318: Unknown result type (might be due to invalid IL or missing references)
		if (!active || !drag.Appearance.InventoryVisible)
		{
			drag.Hide();
			return;
		}
		panel = drag.Place(defaultPanel, 65f);
		if (drag.Minimized)
		{
			return;
		}
		drag.DrawHeader();
		if (!drag.ToolWindow && InventoryGui.IsVisible() && GUI.Button(new Rect(((Rect)(ref panel)).xMax - 92f, ((Rect)(ref panel)).y + 5f, 54f, 22f), "Reset", SagaPanelUI.ButtonStyle()))
		{
			drag.ResetPosition();
			panel = defaultPanel;
		}
		object? value = clockStyle.GetValue(null);
		GUIStyle val = (GUIStyle)((value is GUIStyle) ? value : null);
		if (textStyle == null)
		{
			textStyle = ((val == null) ? new GUIStyle(GUI.skin.label) : new GUIStyle(val));
			outlineStyle = new GUIStyle(textStyle);
		}
		if (val != null)
		{
			textStyle.font = val.font;
		}
		textStyle.fontSize = 16;
		textStyle.fontStyle = (FontStyle)0;
		textStyle.alignment = (TextAnchor)4;
		textStyle.normal.textColor = Color.white;
		string text = (clockText.GetValue(null) as string) ?? "";
		text = (((Object)(object)EnvMan.instance == (Object)null) ? "" : SagaClockDisplay.Format((int)currentDay.Invoke(EnvMan.instance, null), (float)smoothDay.GetValue(EnvMan.instance)));
		textStyle.wordWrap = false;
		Rect val2 = default(Rect);
		((Rect)(ref val2))..ctor(((Rect)(ref panel)).x + 8f, ((Rect)(ref panel)).yMax - footerHeight + 2f, ((Rect)(ref panel)).width - 16f, footerHeight - 4f);
		Color color = GUI.color;
		GUI.color = Color.white;
		try
		{
			outlineStyle.font = textStyle.font;
			outlineStyle.fontSize = textStyle.fontSize;
			outlineStyle.fontStyle = textStyle.fontStyle;
			outlineStyle.alignment = textStyle.alignment;
			outlineStyle.wordWrap = false;
			Color value2 = footerStrokeColor.Value;
			value2.a *= footerTextColor.Value.a;
			outlineStyle.normal.textColor = value2;
			int value3 = footerStroke.Value;
			if (value3 > 0)
			{
				for (int i = -1; i <= 1; i++)
				{
					for (int j = -1; j <= 1; j++)
					{
						if (j != 0 || i != 0)
						{
							GUI.Label(new Rect(((Rect)(ref val2)).x + (float)(j * value3), ((Rect)(ref val2)).y + (float)(i * value3), ((Rect)(ref val2)).width, ((Rect)(ref val2)).height), text, outlineStyle);
						}
					}
				}
			}
			textStyle.normal.textColor = footerTextColor.Value;
			GUI.Label(val2, text, textStyle);
		}
		finally
		{
			GUI.color = color;
		}
	}

	private void Cleanup()
	{
		//IL_0033: 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)
		active = false;
		if ((Object)(object)smallRoot != (Object)null)
		{
			drag.ContentVisible(((Component)smallRoot).gameObject, true);
			smallRoot.anchoredPosition = originalPosition;
			((Transform)smallRoot).localScale = originalScale;
		}
		if ((Object)(object)frame != (Object)null)
		{
			Object.Destroy((Object)(object)((Component)frame).gameObject);
		}
		frame = null;
		smallRoot = null;
	}

	private void OnDestroy()
	{
		Cleanup();
		if (drag != null)
		{
			drag.Dispose();
		}
		if (harmony != null)
		{
			harmony.UnpatchSelf();
		}
		instance = null;
	}
}
public static class SagaClockDisplay
{
	public static string Format(int day, double fraction)
	{
		double num = fraction - Math.Floor(fraction);
		int num2 = (int)(num * 1440.0);
		int num3 = num2 / 60;
		int num4 = num2 % 60;
		int num5 = num3 % 12;
		if (num5 == 0)
		{
			num5 = 12;
		}
		return "DAY " + day.ToString(CultureInfo.InvariantCulture) + "\n" + num5.ToString(CultureInfo.InvariantCulture) + ":" + num4.ToString("00", CultureInfo.InvariantCulture) + ((num3 < 12) ? "AM" : "PM");
	}
}
internal static class SagaConfigPreview
{
	private static BaseUnityPlugin manager;

	private static PropertyInfo displaying;

	private static float retry;

	private static int frame = -1;

	private static bool open;

	internal static bool Open
	{
		get
		{
			if (frame == Time.frameCount)
			{
				return open;
			}
			frame = Time.frameCount;
			open = false;
			if ((Object)(object)manager == (Object)null && Time.unscaledTime >= retry)
			{
				retry = Time.unscaledTime + 2f;
				if (Chainloader.PluginInfos.TryGetValue("com.bepis.bepinex.configurationmanager", out var value))
				{
					manager = value.Instance;
					displaying = ((object)manager).GetType().GetProperty("DisplayingWindow", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				}
			}
			if ((Object)(object)manager != (Object)null && displaying != null)
			{
				try
				{
					open = (bool)displaying.GetValue(manager, null);
				}
				catch
				{
					open = false;
				}
			}
			return open;
		}
	}

	internal static bool HudVisible(Hud hud)
	{
		if ((Object)(object)hud != (Object)null)
		{
			if (!Open)
			{
				return hud.IsVisible();
			}
			return true;
		}
		return false;
	}

	internal static bool MenuVisible()
	{
		if (!Open)
		{
			return Menu.IsVisible();
		}
		return false;
	}

	internal static bool MapVisible()
	{
		if (!Open)
		{
			return Minimap.IsOpen();
		}
		return false;
	}

	internal static bool StoreVisible()
	{
		if (!Open)
		{
			return StoreGui.IsVisible();
		}
		return false;
	}

	internal static bool InventoryHidesHud()
	{
		if (!Open)
		{
			return InventoryGui.IsVisible();
		}
		return false;
	}
}

BepInEx/plugins/MMC-FoodPower/SagaFoodPower.dll

Decompiled a week ago
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: CompilationRelaxations(8)]
[assembly: AssemblyVersion("0.0.0.0")]
internal static class SagaConfigPreview
{
	private static BaseUnityPlugin manager;

	private static PropertyInfo displaying;

	private static float retry;

	private static int frame = -1;

	private static bool open;

	internal static bool Open
	{
		get
		{
			if (frame == Time.frameCount)
			{
				return open;
			}
			frame = Time.frameCount;
			open = false;
			if ((Object)(object)manager == (Object)null && Time.unscaledTime >= retry)
			{
				retry = Time.unscaledTime + 2f;
				if (Chainloader.PluginInfos.TryGetValue("com.bepis.bepinex.configurationmanager", out var value))
				{
					manager = value.Instance;
					displaying = ((object)manager).GetType().GetProperty("DisplayingWindow", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				}
			}
			if ((Object)(object)manager != (Object)null && displaying != null)
			{
				try
				{
					open = (bool)displaying.GetValue(manager, null);
				}
				catch
				{
					open = false;
				}
			}
			return open;
		}
	}

	internal static bool HudVisible(Hud hud)
	{
		if ((Object)(object)hud != (Object)null)
		{
			if (!Open)
			{
				return hud.IsVisible();
			}
			return true;
		}
		return false;
	}

	internal static bool MenuVisible()
	{
		if (!Open)
		{
			return Menu.IsVisible();
		}
		return false;
	}

	internal static bool MapVisible()
	{
		if (!Open)
		{
			return Minimap.IsOpen();
		}
		return false;
	}

	internal static bool StoreVisible()
	{
		if (!Open)
		{
			return StoreGui.IsVisible();
		}
		return false;
	}

	internal static bool InventoryHidesHud()
	{
		if (!Open)
		{
			return InventoryGui.IsVisible();
		}
		return false;
	}
}
[BepInPlugin("local.mmc.foodpower", "Saga Food and Power", "3.0.0")]
[DefaultExecutionOrder(12000)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public sealed class SagaFoodPower : BaseUnityPlugin
{
	private SagaPanelWindow window;

	private ConfigEntry<bool> show;

	private ConfigEntry<bool> vertical;

	private ConfigEntry<bool> hideBuildTools;

	private ConfigEntry<float> buildHideDelay;

	private float buildSince = -1f;

	private ConfigEntry<float> slotSize;

	private ConfigEntry<float> gap;

	private Rect bounds;

	private RectTransform power;

	private Image wipe;

	private bool visible;

	private float keyAt;

	private string key = "";

	private void Awake()
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Expected O, but got Unknown
		//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b2: Expected O, but got Unknown
		//IL_0108: Unknown result type (might be due to invalid IL or missing references)
		//IL_0112: Expected O, but got Unknown
		//IL_0147: Unknown result type (might be due to invalid IL or missing references)
		//IL_0151: Expected O, but got Unknown
		window = new SagaPanelWindow(((BaseUnityPlugin)this).Config, "Food and Power");
		window.MinimumWidth = 40f;
		window.MinimumHeight = 40f;
		show = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "Enabled", true, "Display three food slots and selected forsaken power.");
		hideBuildTools = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "Hide While Using Build Tools", true, "Hide food and selected power while a hammer, hoe, cultivator or other native placement tool is equipped. F1 still previews it.");
		buildHideDelay = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "Build Tool Hide Delay", 0f, new ConfigDescription("Seconds before hiding while using a build tool.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 30f), new object[0]));
		vertical = ((BaseUnityPlugin)this).Config.Bind<bool>("Layout", "Vertical", false, "Vertical column when enabled; otherwise horizontal row.");
		slotSize = ((BaseUnityPlugin)this).Config.Bind<float>("Layout", "Slot Size", 64f, new ConfigDescription("Slot size before layout scale.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(32f, 160f), new object[0]));
		gap = ((BaseUnityPlugin)this).Config.Bind<float>("Layout", "Gap", 10f, new ConfigDescription("Space between slots.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 80f), new object[0]));
	}

	private static Camera CameraFor(RectTransform rt)
	{
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		Canvas componentInParent = ((Component)rt).GetComponentInParent<Canvas>();
		if (!((Object)(object)componentInParent == (Object)null) && (int)componentInParent.renderMode != 0)
		{
			return componentInParent.worldCamera;
		}
		return null;
	}

	private static void Fit(RectTransform rt, Rect screen)
	{
		//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_0011: 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_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_0040: 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_0092: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00aa: 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_00b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00be: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c3: 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_0101: Unknown result type (might be due to invalid IL or missing references)
		//IL_0119: Unknown result type (might be due to invalid IL or missing references)
		//IL_0129: Unknown result type (might be due to invalid IL or missing references)
		//IL_012e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0130: Unknown result type (might be due to invalid IL or missing references)
		//IL_0132: Unknown result type (might be due to invalid IL or missing references)
		//IL_0137: Unknown result type (might be due to invalid IL or missing references)
		((Transform)rt).localScale = Vector3.one;
		Bounds val = RectTransformUtility.CalculateRelativeRectTransformBounds((Transform)(object)rt);
		Camera val2 = CameraFor(rt);
		Vector2 val3 = RectTransformUtility.WorldToScreenPoint(val2, ((Transform)rt).TransformPoint(((Bounds)(ref val)).min));
		Vector2 val4 = RectTransformUtility.WorldToScreenPoint(val2, ((Transform)rt).TransformPoint(((Bounds)(ref val)).max));
		float num = Mathf.Min(((Rect)(ref screen)).width / Mathf.Max(1f, val4.x - val3.x), ((Rect)(ref screen)).height / Mathf.Max(1f, val4.y - val3.y));
		((Transform)rt).localScale = Vector3.one * num;
		val3 = RectTransformUtility.WorldToScreenPoint(val2, ((Transform)rt).TransformPoint(((Bounds)(ref val)).min));
		val4 = RectTransformUtility.WorldToScreenPoint(val2, ((Transform)rt).TransformPoint(((Bounds)(ref val)).max));
		Transform parent = ((Transform)rt).parent;
		RectTransform val5 = (RectTransform)(object)((parent is RectTransform) ? parent : null);
		Vector2 val6 = default(Vector2);
		RectTransformUtility.ScreenPointToLocalPointInRectangle(val5, new Vector2((val3.x + val4.x) * 0.5f, val4.y), val2, ref val6);
		Vector2 val7 = default(Vector2);
		RectTransformUtility.ScreenPointToLocalPointInRectangle(val5, new Vector2(((Rect)(ref screen)).center.x, (float)Screen.height - ((Rect)(ref screen)).y), val2, ref val7);
		rt.anchoredPosition += val7 - val6;
	}

	private void LateUpdate()
	{
		//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_0204: Unknown result type (might be due to invalid IL or missing references)
		//IL_0336: Unknown result type (might be due to invalid IL or missing references)
		//IL_0575: Unknown result type (might be due to invalid IL or missing references)
		//IL_055a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0446: Unknown result type (might be due to invalid IL or missing references)
		//IL_044d: Expected O, but got Unknown
		//IL_0470: Unknown result type (might be due to invalid IL or missing references)
		//IL_047c: Unknown result type (might be due to invalid IL or missing references)
		//IL_048a: Unknown result type (might be due to invalid IL or missing references)
		//IL_048f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0490: Unknown result type (might be due to invalid IL or missing references)
		//IL_0497: Unknown result type (might be due to invalid IL or missing references)
		//IL_04d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_06d2: Unknown result type (might be due to invalid IL or missing references)
		Player localPlayer = Player.m_localPlayer;
		Hud instance = Hud.instance;
		List<RectTransform> foodSlots = MMCSkillDrainClock.FoodSlots;
		bool flag = (Object)(object)localPlayer != (Object)null && ((Character)localPlayer).InPlaceMode();
		if (!flag)
		{
			buildSince = -1f;
		}
		else if (buildSince < 0f)
		{
			buildSince = Time.unscaledTime;
		}
		bool flag2 = hideBuildTools.Value && flag && Time.unscaledTime - buildSince >= buildHideDelay.Value && !SagaConfigPreview.Open;
		visible = !flag2 && show.Value && (Object)(object)localPlayer != (Object)null && (Object)(object)instance != (Object)null && (SagaConfigPreview.HudVisible(instance) || InventoryGui.IsVisible()) && !((Character)localPlayer).IsDead() && window.Appearance.InventoryVisible && !SagaConfigPreview.MenuVisible() && !SagaConfigPreview.MapVisible();
		SagaPanelUI.PowerOnHotbar = show.Value;
		if (foodSlots != null)
		{
			foreach (RectTransform item in foodSlots)
			{
				if ((Object)(object)item != (Object)null)
				{
					((Component)item).gameObject.SetActive(visible);
				}
			}
		}
		if (!visible)
		{
			if ((Object)(object)power != (Object)null)
			{
				((Component)power).gameObject.SetActive(false);
			}
			window.Hide();
			return;
		}
		float num = 4f * slotSize.Value + 3f * gap.Value;
		bounds = window.Resolve(new Rect((float)Screen.width * 0.5f - num * 0.5f, (float)(Screen.height - 340), vertical.Value ? slotSize.Value : num, vertical.Value ? num : slotSize.Value));
		if (window.Minimized)
		{
			if (foodSlots != null)
			{
				foreach (RectTransform item2 in foodSlots)
				{
					((Component)item2).gameObject.SetActive(false);
				}
			}
			if ((Object)(object)power != (Object)null)
			{
				((Component)power).gameObject.SetActive(false);
			}
			return;
		}
		float headerHeight = window.HeaderHeight;
		float width = (vertical.Value ? ((Rect)(ref bounds)).width : ((((Rect)(ref bounds)).width - 3f * gap.Value) / 4f));
		float height = (vertical.Value ? ((((Rect)(ref bounds)).height - headerHeight - 3f * gap.Value) / 4f) : (((Rect)(ref bounds)).height - headerHeight));
		if (foodSlots != null)
		{
			for (int i = 0; i < foodSlots.Count; i++)
			{
				if (i >= 3)
				{
					((Component)foodSlots[i]).gameObject.SetActive(false);
				}
				else
				{
					Fit(foodSlots[i], Slot(i, width, height, headerHeight));
				}
			}
		}
		StatusEffect val = default(StatusEffect);
		float num2 = default(float);
		localPlayer.GetGuardianPowerHUD(ref val, ref num2);
		if ((Object)(object)power == (Object)null)
		{
			power = Object.Instantiate<RectTransform>(instance.m_statusEffectTemplate, (Transform)(object)instance.m_statusEffectListRoot);
			((Object)power).name = "Selected forsaken power";
			Animator[] componentsInChildren = ((Component)power).GetComponentsInChildren<Animator>(true);
			foreach (Animator val2 in componentsInChildren)
			{
				((Behaviour)val2).enabled = false;
			}
			Graphic[] componentsInChildren2 = ((Component)power).GetComponentsInChildren<Graphic>(true);
			foreach (Graphic val3 in componentsInChildren2)
			{
				val3.raycastTarget = false;
			}
			Transform val4 = ((Transform)power).Find("Cooldown");
			if ((Object)(object)val4 != (Object)null)
			{
				((Component)val4).gameObject.SetActive(false);
			}
			GameObject val5 = new GameObject("Power reverse wipe", new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			RectTransform component = val5.GetComponent<RectTransform>();
			((Transform)component).SetParent(((Transform)power).Find("Icon"), false);
			component.anchorMin = Vector2.zero;
			component.anchorMax = Vector2.one;
			Vector2 offsetMin = (component.offsetMax = Vector2.zero);
			component.offsetMin = offsetMin;
			wipe = val5.GetComponent<Image>();
			((Graphic)wipe).raycastTarget = false;
			((Graphic)wipe).color = new Color(0.42f, 0.42f, 0.42f, 0.85f);
			wipe.type = (Type)3;
			wipe.fillMethod = (FillMethod)4;
			wipe.fillOrigin = 2;
			wipe.fillClockwise = false;
		}
		((Component)power).gameObject.SetActive(true);
		Image component2 = ((Component)((Transform)power).Find("Icon")).GetComponent<Image>();
		component2.sprite = (((Object)(object)val == (Object)null) ? null : val.m_icon);
		((Graphic)component2).color = (Color)(((Object)(object)val == (Object)null) ? new Color(0.2f, 0.2f, 0.2f, 0.5f) : Color.white);
		((Behaviour)wipe).enabled = (Object)(object)val != (Object)null && num2 > 0f;
		if (((Behaviour)wipe).enabled)
		{
			wipe.sprite = val.m_icon;
			wipe.fillAmount = Mathf.Clamp01(num2 / Mathf.Max(1f, val.m_cooldown));
		}
		if (Time.unscaledTime >= keyAt)
		{
			keyAt = Time.unscaledTime + 0.5f;
			key = ((ZInput.instance == null) ? "" : ZInput.instance.GetBoundKeyString("GP", false));
		}
		((Component)power).GetComponentInChildren<TMP_Text>().text = key;
		TMP_Text component3 = ((Component)((Transform)power).Find("TimeText")).GetComponent<TMP_Text>();
		((Component)component3).gameObject.SetActive(true);
		component3.text = (((Object)(object)val == (Object)null) ? "" : ((!(num2 > 0f)) ? "Ready" : ((num2 > 60f) ? (Mathf.CeilToInt(num2 / 60f) + "m") : (Mathf.CeilToInt(num2) + "s"))));
		Fit(power, Slot(3, width, height, headerHeight));
	}

	private Rect Slot(int i, float width, float height, float header)
	{
		//IL_0079: Unknown result type (might be due to invalid IL or missing references)
		return new Rect(((Rect)(ref bounds)).x + (vertical.Value ? 0f : ((float)i * (width + gap.Value))), ((Rect)(ref bounds)).y + header + (vertical.Value ? ((float)i * (height + gap.Value)) : 0f), Mathf.Max(8f, width), Mathf.Max(8f, height));
	}

	private void OnGUI()
	{
		//IL_0011: 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_0020: 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)
		if (visible)
		{
			bounds = window.Place(bounds, 0f);
			if (!window.Minimized)
			{
				window.Appearance.Draw(bounds, 0.4f, "Food and Power");
			}
		}
	}

	private void OnDestroy()
	{
		if ((Object)(object)power != (Object)null)
		{
			Object.Destroy((Object)(object)((Component)power).gameObject);
		}
		if (window != null)
		{
			window.Dispose();
		}
		SagaPanelUI.PowerOnHotbar = false;
	}
}

BepInEx/plugins/MMC-GroupDamage/MMCGroupDamage.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("0.0.0.0")]
public sealed class MMCEncounterLedger
{
	public sealed class Entry
	{
		public long Actor;

		public double Damage;

		public int Skill;
	}

	public readonly Dictionary<long, Entry> Entries = new Dictionary<long, Entry>();

	private readonly HashSet<string> seen = new HashSet<string>();

	private readonly Queue<string> seenOrder = new Queue<string>();

	private readonly HashSet<string> targetNames = new HashSet<string>();

	public bool Active;

	public bool HasEncounter;

	public double Started;

	public double LastHit;

	public double LastActivity;

	public double Ended;

	public string TargetName = "Combat";

	public double IdleSeconds = 60.0;

	public void Advance(double now)
	{
		if (Active && now - LastActivity >= IdleSeconds)
		{
			Active = false;
			Ended = LastActivity;
		}
	}

	public void Combat(double now)
	{
		Advance(now);
		if (!Active)
		{
			Entries.Clear();
			targetNames.Clear();
			Active = (HasEncounter = true);
			Started = now;
			LastHit = 0.0;
			TargetName = "Combat";
		}
		LastActivity = now;
	}

	public bool Add(string id, double now, long actor, double damage, string target, string targetName, bool killed, int skill)
	{
		if (string.IsNullOrEmpty(id) || actor == 0 || damage <= 0.0 || double.IsNaN(damage) || double.IsInfinity(damage) || !seen.Add(id))
		{
			return false;
		}
		seenOrder.Enqueue(id);
		if (seenOrder.Count > 4096)
		{
			seen.Remove(seenOrder.Dequeue());
		}
		Combat(now);
		LastHit = now;
		targetNames.Add(targetName);
		TargetName = ((targetNames.Count == 1) ? targetName : "Combat");
		if (!Entries.TryGetValue(actor, out var value))
		{
			Entry entry = new Entry();
			entry.Actor = actor;
			value = entry;
			Entries.Add(actor, value);
		}
		value.Damage += damage;
		value.Skill = skill;
		return true;
	}

	public double Remaining(double now)
	{
		if (!Active)
		{
			return 0.0;
		}
		return Math.Max(0.0, IdleSeconds - (now - LastActivity));
	}

	public double Duration(double now)
	{
		if (!HasEncounter)
		{
			return 1.0;
		}
		return Math.Max(1.0, (Active ? LastActivity : Ended) - Started);
	}

	public void Reset()
	{
		Entries.Clear();
		targetNames.Clear();
		seen.Clear();
		seenOrder.Clear();
		Active = (HasEncounter = false);
		Started = (LastHit = (LastActivity = (Ended = 0.0)));
		TargetName = "Combat";
	}
}
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInPlugin("local.mmc.groupdamage", "SagaDamagePro", "3.0.0")]
public sealed class MMCGroupDamage : BaseUnityPlugin
{
	public sealed class Capture
	{
		public Character Target;

		public float Health;

		public float NestedLoss;

		public long Actor;

		public string Name;

		public string TargetID;

		public string TargetName;

		public int Skill;
	}

	private sealed class Report
	{
		public string ID;

		public string Name;

		public string TargetID;

		public string TargetName;

		public long Origin;

		public long Actor;

		public float Damage;

		public bool Killed;

		public int Skill;
	}

	private sealed class Member
	{
		public long ID;

		public string Name;

		public double Damage;

		public int Skill;
	}

	private const string HelloRPC = "MMC_Damage_Hello_v1";

	private const string ReportRPC = "MMC_Damage_Report_v1";

	private static MMCGroupDamage instance;

	private static readonly List<Capture> captures = new List<Capture>();

	private readonly MMCEncounterLedger ledger = new MMCEncounterLedger();

	private readonly Dictionary<long, string> roster = new Dictionary<long, string>();

	private readonly HashSet<long> linked = new HashSet<long>();

	private readonly List<Member> display = new List<Member>();

	private readonly string session = Guid.NewGuid().ToString("N");

	private long sequence;

	private Harmony harmony;

	private ZRoutedRpc registered;

	private bool announcePending;

	private MethodInfo groupPlayers;

	private FieldInfo peerID;

	private FieldInfo peerName;

	private FieldInfo skillsBounds;

	private FieldInfo clockStyle;

	private object skillsPanel;

	private float nextRoster;

	private float nextRows;

	private float nextCombatShare;

	private ConfigEntry<bool> autoHide;

	private ConfigEntry<float> hideDelay;

	private readonly HashSet<long> activityPeers = new HashSet<long>();

	private string rosterKey = "";

	private Player currentPlayer;

	private ConfigEntry<bool> visible;

	private ConfigEntry<float> idleTime;

	private ConfigEntry<float> panelWidth;

	private ConfigEntry<float> opacity;

	private ConfigEntry<int> maximumRows;

	private GUIStyle textStyle;

	private GUIStyle numberStyle;

	private GUIStyle titleStyle;

	private GUIStyle smallStyle;

	private Vector2 scroll;

	private SagaPanelWindow window;

	private readonly Color[] colors = (Color[])(object)new Color[5]
	{
		new Color(0.68f, 0.43f, 0.15f, 0.8f),
		new Color(0.19f, 0.48f, 0.68f, 0.8f),
		new Color(0.35f, 0.55f, 0.23f, 0.8f),
		new Color(0.53f, 0.3f, 0.65f, 0.8f),
		new Color(0.66f, 0.27f, 0.25f, 0.8f)
	};

	private static readonly Dictionary<GUIStyle, GUIStyle> shadowStyles = new Dictionary<GUIStyle, GUIStyle>();

	private long OwnID
	{
		get
		{
			if (!((Object)(object)ZNet.instance == (Object)null))
			{
				return ZNet.GetUID();
			}
			return 0L;
		}
	}

	private void Awake()
	{
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Expected O, but got Unknown
		//IL_008d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0097: Expected O, but got Unknown
		//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d6: Expected O, but got Unknown
		//IL_0100: Unknown result type (might be due to invalid IL or missing references)
		//IL_010a: Expected O, but got Unknown
		//IL_0160: Unknown result type (might be due to invalid IL or missing references)
		//IL_016a: Expected O, but got Unknown
		//IL_019f: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a9: Expected O, but got Unknown
		//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01be: Expected O, but got Unknown
		//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_0201: Unknown result type (might be due to invalid IL or missing references)
		//IL_020c: Expected O, but got Unknown
		//IL_020c: Expected O, but got Unknown
		//IL_023a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0247: Expected O, but got Unknown
		instance = this;
		window = new SagaPanelWindow(((BaseUnityPlugin)this).Config, "SagaDamagePro");
		window.MinimumWidth = 340f;
		window.MinimumHeight = 140f;
		visible = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "Enabled", true, "Show the group damage meter beside the skills panel.");
		panelWidth = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "Width", 420f, new ConfigDescription("Panel width in screen pixels.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(340f, 650f), new object[0]));
		opacity = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "Opacity", 0.85f, new ConfigDescription("Background opacity.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.2f, 1f), new object[0]));
		maximumRows = ((BaseUnityPlugin)this).Config.Bind<int>("Display", "Visible Rows", 6, new ConfigDescription("Larger groups scroll within the panel.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(4, 12), new object[0]));
		autoHide = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "Auto Hide Out Of Combat", true, "Hide idle results; inventory and F1 reveal them for layout.");
		hideDelay = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "Hide Delay", 30f, new ConfigDescription("Seconds since the latest combat activity.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 600f), new object[0]));
		idleTime = ((BaseUnityPlugin)this).Config.Bind<float>("Combat", "End Fight After Idle", 60f, new ConfigDescription("Seconds without combat activity before a new encounter can start. Last results remain visible.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 300f), new object[0]));
		harmony = new Harmony("local.mmc.groupdamage");
		harmony.Patch((MethodBase)AccessTools.Method(typeof(Character), "ApplyDamage", (Type[])null, (Type[])null), new HarmonyMethod(typeof(MMCGroupDamage), "BeforeDamage", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(MMCGroupDamage), "AfterDamage", (Type[])null), (HarmonyMethod)null);
		harmony.Patch((MethodBase)AccessTools.Method(typeof(Player), "RPC_OnTargeted", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(MMCGroupDamage), "OnTargeted", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Group damage meter enabled. Records owner-confirmed enemy HP loss; peers/server need this addon to report damage they own.");
	}

	private static void BeforeDamage(Character __instance, HitData __0, out Capture __state)
	{
		//IL_0109: Unknown result type (might be due to invalid IL or missing references)
		//IL_010e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0132: Unknown result type (might be due to invalid IL or missing references)
		//IL_013c: Expected I4, but got Unknown
		__state = null;
		if ((Object)(object)instance == (Object)null || (Object)(object)__instance == (Object)null || __0 == null)
		{
			return;
		}
		if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer)
		{
			Character attacker = __0.GetAttacker();
			if ((Object)(object)attacker != (Object)null && !attacker.IsPlayer() && !attacker.IsTamed())
			{
				instance.LocalCombat();
			}
		}
		if (__instance.IsPlayer() || __instance.IsTamed())
		{
			return;
		}
		ZNetView component = ((Component)__instance).GetComponent<ZNetView>();
		if ((Object)(object)component == (Object)null || !component.IsValid() || !component.IsOwner())
		{
			return;
		}
		Character attacker2 = __0.GetAttacker();
		Player val = (Player)(object)((attacker2 is Player) ? attacker2 : null);
		if ((Object)(object)val == (Object)null)
		{
			return;
		}
		ZNetView component2 = ((Component)val).GetComponent<ZNetView>();
		if (!((Object)(object)component2 == (Object)null) && component2.IsValid())
		{
			long owner = component2.GetZDO().GetOwner();
			if (owner != 0)
			{
				__state = new Capture
				{
					Target = __instance,
					Health = Mathf.Max(0f, __instance.GetHealth()),
					Actor = owner,
					Name = val.GetPlayerName(),
					TargetID = ((object)__instance.GetZDOID()/*cast due to .constrained prefix*/).ToString(),
					TargetName = __instance.m_name,
					Skill = (int)__0.m_skill
				};
				captures.Add(__state);
			}
		}
	}

	private static Exception AfterDamage(Exception __exception, Capture __state)
	{
		if (__state == null)
		{
			return __exception;
		}
		captures.Remove(__state);
		if (__exception != null || (Object)(object)instance == (Object)null || (Object)(object)__state.Target == (Object)null)
		{
			return __exception;
		}
		try
		{
			float num = Mathf.Max(0f, __state.Target.GetHealth());
			float num2 = Mathf.Max(0f, __state.Health - num);
			for (int num3 = captures.Count - 1; num3 >= 0; num3--)
			{
				if ((Object)(object)captures[num3].Target == (Object)(object)__state.Target)
				{
					captures[num3].NestedLoss += num2;
					break;
				}
			}
			float num4 = Mathf.Max(0f, num2 - __state.NestedLoss);
			if (num4 > 0f && !float.IsNaN(num4) && !float.IsInfinity(num4))
			{
				instance.Measured(__state, num4, num <= 0f);
			}
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)instance).Logger.LogWarning((object)("Damage report skipped: " + ex.Message));
		}
		return __exception;
	}

	private void Measured(Capture state, float amount, bool killed)
	{
		if (OwnID != 0 && registered != null)
		{
			Report report = new Report();
			report.ID = session + ":" + ++sequence;
			report.Origin = OwnID;
			report.Actor = state.Actor;
			report.Name = state.Name;
			report.TargetID = state.TargetID;
			report.TargetName = state.TargetName;
			report.Damage = amount;
			report.Killed = killed;
			report.Skill = state.Skill;
			Report report2 = report;
			Accept(report2);
			if (report2.Actor == OwnID)
			{
				Share(report2);
			}
			else if (linked.Contains(report2.Actor))
			{
				Send(report2.Actor, report2);
			}
		}
	}

	private void Share(Report report)
	{
		foreach (long key in roster.Keys)
		{
			if (key != OwnID && linked.Contains(key))
			{
				Send(key, report);
			}
		}
	}

	private void Send(long peer, Report report)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0006: Expected O, but got Unknown
		ZPackage val = new ZPackage();
		val.Write(report.ID);
		val.Write(report.Origin);
		val.Write(report.Actor);
		val.Write(report.Name ?? "");
		val.Write(report.TargetID);
		val.Write(report.TargetName ?? "Combat");
		val.Write(report.Damage);
		val.Write(report.Killed);
		val.Write(report.Skill);
		registered.InvokeRoutedRPC(peer, "MMC_Damage_Report_v1", new object[1] { val });
	}

	private void Receive(long sender, ZPackage package)
	{
		if (!linked.Contains(sender))
		{
			return;
		}
		try
		{
			if (package.Size() > 2048)
			{
				return;
			}
			Report report = new Report();
			report.ID = package.ReadString();
			report.Origin = package.ReadLong();
			report.Actor = package.ReadLong();
			report.Name = package.ReadString();
			report.TargetID = package.ReadString();
			report.TargetName = package.ReadString();
			report.Damage = package.ReadSingle();
			report.Killed = package.ReadBool();
			report.Skill = package.ReadInt();
			Report report2 = report;
			if (report2.ID.Length > 100 || report2.TargetID.Length > 100 || report2.Name.Length > 80 || report2.TargetName.Length > 160 || report2.Damage > 100000000f || report2.Damage <= 0f)
			{
				return;
			}
			bool flag = report2.Actor == OwnID && sender == report2.Origin;
			bool flag2 = sender == report2.Actor && roster.ContainsKey(report2.Actor);
			if (flag || flag2)
			{
				bool flag3 = Accept(report2);
				if (flag && flag3)
				{
					Share(report2);
				}
			}
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogDebug((object)("Ignored incompatible damage packet: " + ex.Message));
		}
	}

	private bool Accept(Report report)
	{
		if ((Object)(object)Player.m_localPlayer == (Object)null || !roster.ContainsKey(report.Actor))
		{
			return false;
		}
		return ledger.Add(report.ID, Time.unscaledTime, report.Actor, report.Damage, report.TargetID, report.TargetName, report.Killed, report.Skill);
	}

	private void Hello(long sender, int version)
	{
		if ((version == 1 || version == 2) && sender != OwnID)
		{
			if (version >= 2)
			{
				activityPeers.Add(sender);
			}
			if (linked.Add(sender))
			{
				registered.InvokeRoutedRPC(sender, "MMC_Damage_Hello_v1", new object[1] { 1 });
				registered.InvokeRoutedRPC(sender, "MMC_Damage_Hello_v1", new object[1] { 2 });
			}
		}
	}

	private void RegisterNetwork()
	{
		if (ZRoutedRpc.instance != registered)
		{
			registered = ZRoutedRpc.instance;
			linked.Clear();
			activityPeers.Clear();
			nextCombatShare = 0f;
			ledger.Reset();
			rosterKey = "";
			if (registered != null)
			{
				registered.Register<int>("MMC_Damage_Hello_v1", (Action<long, int>)Hello);
				registered.Register<ZPackage>("MMC_Damage_Report_v1", (Action<long, ZPackage>)Receive);
				registered.Register<int>("MMC_Damage_Combat_v2", (Action<long, int>)ReceiveCombat);
				announcePending = true;
			}
		}
	}

	private static void OnTargeted(Player __instance, bool __2)
	{
		if ((Object)(object)instance != (Object)null && (Object)(object)__instance == (Object)(object)Player.m_localPlayer && __2)
		{
			instance.LocalCombat();
		}
	}

	private void LocalCombat()
	{
		if ((Object)(object)Player.m_localPlayer == (Object)null || OwnID == 0)
		{
			return;
		}
		ledger.Combat(Time.unscaledTime);
		SagaPanelUI.LastCombatAt = Time.unscaledTime;
		if (registered == null || Time.unscaledTime < nextCombatShare)
		{
			return;
		}
		nextCombatShare = Time.unscaledTime + 1f;
		foreach (long key in roster.Keys)
		{
			if (key != OwnID && activityPeers.Contains(key))
			{
				registered.InvokeRoutedRPC(key, "MMC_Damage_Combat_v2", new object[1] { 1 });
			}
		}
	}

	private void ReceiveCombat(long sender, int value)
	{
		if (value == 1 && (Object)(object)Player.m_localPlayer != (Object)null && activityPeers.Contains(sender) && roster.ContainsKey(sender))
		{
			ledger.Combat(Time.unscaledTime);
			SagaPanelUI.LastCombatAt = Time.unscaledTime;
		}
	}

	private void RefreshRoster()
	{
		roster.Clear();
		if ((Object)(object)Player.m_localPlayer == (Object)null)
		{
			return;
		}
		if (groupPlayers == null)
		{
			Type type = AccessTools.TypeByName("Groups.API");
			if (type != null)
			{
				groupPlayers = type.GetMethod("GroupPlayers", BindingFlags.Static | BindingFlags.Public);
			}
		}
		if (groupPlayers != null && groupPlayers.Invoke(null, null) is IEnumerable enumerable)
		{
			foreach (object item in enumerable)
			{
				if (peerID == null)
				{
					peerID = item.GetType().GetField("peerId");
					peerName = item.GetType().GetField("name");
				}
				long num = (long)peerID.GetValue(item);
				string value = (string)peerName.GetValue(item);
				if (num != 0)
				{
					roster[num] = value;
				}
			}
		}
		roster[OwnID] = Player.m_localPlayer.GetPlayerName();
		List<long> list = new List<long>(roster.Keys);
		list.Sort();
		string text = string.Join(",", list.ConvertAll((long id) => id.ToString()).ToArray());
		if (text != rosterKey)
		{
			ledger.Reset();
			rosterKey = text;
		}
	}

	private void Update()
	{
		RegisterNetwork();
		if (announcePending && registered != null && OwnID != 0 && ((Object)(object)Player.m_localPlayer != (Object)null || ZNet.instance.IsDedicated()))
		{
			announcePending = false;
			registered.InvokeRoutedRPC(0L, "MMC_Damage_Hello_v1", new object[1] { 1 });
			registered.InvokeRoutedRPC(0L, "MMC_Damage_Hello_v1", new object[1] { 2 });
		}
		if ((Object)(object)currentPlayer != (Object)(object)Player.m_localPlayer)
		{
			currentPlayer = Player.m_localPlayer;
			ledger.Reset();
			nextRoster = 0f;
		}
		if (Time.unscaledTime >= nextRoster)
		{
			RefreshRoster();
			nextRoster = Time.unscaledTime + 1f;
		}
		ledger.IdleSeconds = idleTime.Value;
		ledger.Advance(Time.unscaledTime);
		if (!(Time.unscaledTime >= nextRows))
		{
			return;
		}
		display.Clear();
		foreach (KeyValuePair<long, string> item in roster)
		{
			ledger.Entries.TryGetValue(item.Key, out var value);
			display.Add(new Member
			{
				ID = item.Key,
				Name = item.Value,
				Damage = (value?.Damage ?? 0.0),
				Skill = (value?.Skill ?? 0)
			});
		}
		display.Sort(delegate(Member a, Member b)
		{
			int num = b.Damage.CompareTo(a.Damage);
			return (num == 0) ? string.Compare(a.Name, b.Name, StringComparison.Ordinal) : num;
		});
		nextRows = Time.unscaledTime + 0.15f;
	}

	private void FindUI()
	{
		//IL_0094: Unknown result type (might be due to invalid IL or missing references)
		//IL_009e: Expected O, but got Unknown
		//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b2: Expected O, but got Unknown
		//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00db: 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_010b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0115: Expected O, but got Unknown
		//IL_01de: Unknown result type (might be due to invalid IL or missing references)
		//IL_0200: Unknown result type (might be due to invalid IL or missing references)
		//IL_0197: Unknown result type (might be due to invalid IL or missing references)
		if (skillsPanel == null && Chainloader.PluginInfos.TryGetValue("local.mmc.skillspanel", out var value))
		{
			skillsPanel = value.Instance;
			skillsBounds = skillsPanel.GetType().GetField("ScreenRect");
		}
		if (clockStyle == null && Chainloader.PluginInfos.TryGetValue("Azumatt.AzuClock", out value))
		{
			clockStyle = AccessTools.Field(((object)value.Instance).GetType(), "Style");
		}
		if (textStyle == null)
		{
			textStyle = new GUIStyle(GUI.skin.label);
			textStyle.padding = new RectOffset(0, 0, 0, 0);
			textStyle.richText = false;
			textStyle.wordWrap = false;
			numberStyle = new GUIStyle(textStyle);
			numberStyle.alignment = (TextAnchor)5;
			titleStyle = new GUIStyle(textStyle);
			titleStyle.fontStyle = (FontStyle)1;
			smallStyle = new GUIStyle(textStyle);
		}
		GUIStyle val = (GUIStyle)((clockStyle == null) ? null : /*isinst with value type is only supported in some contexts*/);
		GUIStyle[] array = (GUIStyle[])(object)new GUIStyle[4] { textStyle, numberStyle, titleStyle, smallStyle };
		foreach (GUIStyle val2 in array)
		{
			val2.font = ((val == null) ? GUI.skin.label.font : val.font);
			val2.normal.textColor = Color.white;
			val2.fontSize = 16;
		}
		titleStyle.fontSize = 19;
		titleStyle.normal.textColor = new Color(1f, 0.76f, 0.4f);
		smallStyle.fontSize = 16;
		smallStyle.normal.textColor = Color.white;
	}

	private static void Fill(Rect rect, Color color)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0005: 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_000c: 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)
		Color color2 = GUI.color;
		GUI.color = color;
		GUI.DrawTexture(rect, (Texture)(object)Texture2D.whiteTexture);
		GUI.color = color2;
	}

	private void Label(Rect rect, string value, GUIStyle style)
	{
		//IL_003c: 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_0058: Unknown result type (might be due to invalid IL or missing references)
		//IL_008a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0096: 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_0016: Expected O, but got Unknown
		if (!shadowStyles.TryGetValue(style, out var value2))
		{
			value2 = new GUIStyle(style);
			shadowStyles.Add(style, value2);
		}
		value2.font = style.font;
		value2.fontSize = style.fontSize;
		value2.fontStyle = style.fontStyle;
		value2.alignment = style.alignment;
		value2.normal.textColor = Color.black;
		GUI.Label(new Rect(((Rect)(ref rect)).x + 1f, ((Rect)(ref rect)).y + 1f, ((Rect)(ref rect)).width, ((Rect)(ref rect)).height), value, value2);
		GUI.Label(rect, value, style);
	}

	private void DrawSkillIcon(Rect rect, int type)
	{
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Invalid comparison between Unknown and I4
		//IL_0055: 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_00c3: 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)Player.m_localPlayer == (Object)null)
		{
			return;
		}
		foreach (SkillDef skill in ((Character)Player.m_localPlayer).GetSkills().m_skills)
		{
			if ((int)skill.m_skill == type && !((Object)(object)skill.m_icon == (Object)null))
			{
				Sprite icon = skill.m_icon;
				Rect textureRect = icon.textureRect;
				((Rect)(ref textureRect)).x = ((Rect)(ref textureRect)).x / (float)((Texture)icon.texture).width;
				((Rect)(ref textureRect)).width = ((Rect)(ref textureRect)).width / (float)((Texture)icon.texture).width;
				((Rect)(ref textureRect)).y = ((Rect)(ref textureRect)).y / (float)((Texture)icon.texture).height;
				((Rect)(ref textureRect)).height = ((Rect)(ref textureRect)).height / (float)((Texture)icon.texture).height;
				GUI.DrawTextureWithTexCoords(rect, (Texture)(object)icon.texture, textureRect);
				break;
			}
		}
	}

	private void OnGUI()
	{
		//IL_097b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0108: 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_010d: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0243: Unknown result type (might be due to invalid IL or missing references)
		//IL_0248: Unknown result type (might be due to invalid IL or missing references)
		//IL_024a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0254: Unknown result type (might be due to invalid IL or missing references)
		//IL_026c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0281: Unknown result type (might be due to invalid IL or missing references)
		//IL_0286: Unknown result type (might be due to invalid IL or missing references)
		//IL_0292: Unknown result type (might be due to invalid IL or missing references)
		//IL_0297: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c6: 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)
		//IL_02e4: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_0319: Unknown result type (might be due to invalid IL or missing references)
		//IL_0329: Unknown result type (might be due to invalid IL or missing references)
		//IL_035c: Unknown result type (might be due to invalid IL or missing references)
		//IL_04a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_04d6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0506: Unknown result type (might be due to invalid IL or missing references)
		//IL_053b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0570: Unknown result type (might be due to invalid IL or missing references)
		//IL_05a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_05f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_05f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_061e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0625: Unknown result type (might be due to invalid IL or missing references)
		//IL_062a: Unknown result type (might be due to invalid IL or missing references)
		//IL_069a: Unknown result type (might be due to invalid IL or missing references)
		//IL_06b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_06da: Unknown result type (might be due to invalid IL or missing references)
		//IL_06df: Unknown result type (might be due to invalid IL or missing references)
		//IL_0707: Unknown result type (might be due to invalid IL or missing references)
		//IL_070c: Unknown result type (might be due to invalid IL or missing references)
		//IL_072b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0760: Unknown result type (might be due to invalid IL or missing references)
		//IL_078b: Unknown result type (might be due to invalid IL or missing references)
		//IL_07f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0841: Unknown result type (might be due to invalid IL or missing references)
		//IL_0967: Unknown result type (might be due to invalid IL or missing references)
		if (!SagaConfigPreview.Open && !InventoryGui.IsVisible() && autoHide.Value && (!ledger.HasEncounter || (double)Time.unscaledTime - ledger.LastActivity > (double)hideDelay.Value))
		{
			window.Hide();
			return;
		}
		if (!window.Appearance.InventoryVisible || !visible.Value || (Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)Hud.instance == (Object)null || (!SagaConfigPreview.HudVisible(Hud.instance) && !SagaConfigPreview.InventoryHidesHud()) || SagaConfigPreview.MapVisible() || SagaConfigPreview.StoreVisible() || SagaConfigPreview.MenuVisible())
		{
			window.Hide();
			return;
		}
		FindUI();
		Rect val = ((skillsBounds == null) ? new Rect(12f, (float)(Screen.height - 300), 300f, 288f) : ((Rect)skillsBounds.GetValue(skillsPanel)));
		if (((Rect)(ref val)).width <= 0f)
		{
			((Rect)(ref val))..ctor(12f, (float)(Screen.height - 300), 300f, 288f);
		}
		int num = Math.Min(Math.Max(4, display.Count), maximumRows.Value);
		float num2 = Mathf.Min(panelWidth.Value, (float)(Screen.width - 16));
		float num3 = 100 + num * 28;
		float num4 = Mathf.Clamp(((Rect)(ref val)).xMax + 12f, 8f, Mathf.Max(8f, (float)Screen.width - num2 - 8f));
		float num5 = Mathf.Clamp(((Rect)(ref val)).yMax - num3, 8f, Mathf.Max(8f, (float)Screen.height - num3 - 8f));
		Rect rect = window.Place(new Rect(num4, num5, num2, num3), 65f);
		if (window.Minimized)
		{
			return;
		}
		num4 = ((Rect)(ref rect)).x;
		num5 = ((Rect)(ref rect)).y;
		num2 = ((Rect)(ref rect)).width;
		num3 = ((Rect)(ref rect)).height;
		float num6 = (window.ToolWindow ? 31 : 0);
		Color color = GUI.color;
		GUI.color = Color.white;
		try
		{
			Fill(rect, window.Appearance.Background(opacity.Value));
			Color border = window.Appearance.Border;
			Fill(new Rect(num4, num5, num2, 1f), border);
			Fill(new Rect(num4, num5 + num3 - 1f, num2, 1f), border);
			Fill(new Rect(num4, num5, 1f, num3), border);
			Fill(new Rect(num4 + num2 - 1f, num5, 1f, num3), border);
			if (!window.ToolWindow)
			{
				Fill(new Rect(num4 + 2f, num5 + 2f, num2 - 4f, 29f), window.Appearance.Header);
			}
			if (!window.ToolWindow && GUI.Button(new Rect(num4 + num2 - 90f, num5 + 5f, 48f, 21f), "Reset", SagaPanelUI.ButtonStyle()))
			{
				ledger.Reset();
			}
			string value = ((!ledger.HasEncounter) ? "Waiting for combat" : ((ledger.Active ? "Current: " : "Last: ") + Localization.instance.Localize(ledger.TargetName)));
			if (ledger.Active && (double)Time.unscaledTime - ledger.LastActivity > 1.5)
			{
				value = "Reset ready in " + Math.Ceiling(ledger.Remaining(Time.unscaledTime)).ToString("0") + "s";
			}
			double num7 = (ledger.HasEncounter ? ledger.Duration(Time.unscaledTime) : 0.0);
			string value2 = ((int)num7 / 60).ToString("00") + ":" + ((int)num7 % 60).ToString("00");
			Label(new Rect(num4 + 12f, num5 + 35f - num6, num2 - 85f, 21f), value, smallStyle);
			Label(new Rect(num4 + num2 - 65f, num5 + 35f - num6, 53f, 21f), value2, smallStyle);
			Label(new Rect(num4 + 12f, num5 + 58f - num6, 24f, 20f), "#", smallStyle);
			Label(new Rect(num4 + 42f, num5 + 58f - num6, num2 - 202f, 20f), "Name", smallStyle);
			Label(new Rect(num4 + num2 - 148f, num5 + 58f - num6, 76f, 20f), "Damage", smallStyle);
			Label(new Rect(num4 + num2 - 57f, num5 + 58f - num6, 47f, 20f), "DPS", smallStyle);
			Rect val2 = default(Rect);
			((Rect)(ref val2))..ctor(num4 + 8f, num5 + 80f - num6, num2 - 16f, Mathf.Max(1f, num3 - 100f + num6));
			scroll = GUI.BeginScrollView(val2, scroll, new Rect(0f, 0f, num2 - 34f, (float)(Math.Max(num, display.Count) * 28)), false, false);
			double num8 = ((display.Count == 0) ? 1.0 : Math.Max(1.0, display[0].Damage));
			for (int i = 0; i < display.Count; i++)
			{
				Member member = display[i];
				float num9 = i * 28;
				Fill(new Rect(0f, num9, num2 - 34f, 26f), new Color(0.05f, 0.055f, 0.05f, 0.6f));
				Color color2 = colors[(uint)((ulong)member.ID % (ulong)colors.Length)];
				Fill(new Rect(51f, num9 + 3f, (float)((double)(num2 - 226f) * member.Damage / num8), 20f), color2);
				Label(new Rect(4f, num9 + 2f, 22f, 23f), (i + 1).ToString(), smallStyle);
				DrawSkillIcon(new Rect(25f, num9 + 2f, 23f, 23f), member.Skill);
				Label(new Rect(53f, num9 + 2f, num2 - 227f, 23f), member.Name, textStyle);
				bool flag = member.ID == OwnID || linked.Contains(member.ID) || member.Damage > 0.0;
				Label(new Rect(num2 - 174f, num9 + 2f, 82f, 23f), flag ? member.Damage.ToString("N0", CultureInfo.InvariantCulture) : "--", numberStyle);
				Label(new Rect(num2 - 82f, num9 + 2f, 47f, 23f), flag ? (member.Damage / ledger.Duration(Time.unscaledTime)).ToString("0", CultureInfo.InvariantCulture) : "--", numberStyle);
			}
			GUI.EndScrollView();
			int num10 = 0;
			foreach (long key in roster.Keys)
			{
				if (key == OwnID || linked.Contains(key))
				{
					num10++;
				}
			}
			string value3 = "Observed damage  ·  " + num10 + "/" + roster.Count + " meters linked";
			Label(new Rect(num4 + 12f, num5 + num3 - 19f, num2 - 24f, 17f), value3, smallStyle);
		}
		finally
		{
			GUI.color = color;
		}
		window.DrawHeader();
	}

	private void OnDestroy()
	{
		if (window != null)
		{
			window.Dispose();
		}
		if (harmony != null)
		{
			harmony.UnpatchSelf();
		}
		captures.Clear();
		instance = null;
	}
}
internal static class SagaConfigPreview
{
	private static BaseUnityPlugin manager;

	private static PropertyInfo displaying;

	private static float retry;

	private static int frame = -1;

	private static bool open;

	internal static bool Open
	{
		get
		{
			if (frame == Time.frameCount)
			{
				return open;
			}
			frame = Time.frameCount;
			open = false;
			if ((Object)(object)manager == (Object)null && Time.unscaledTime >= retry)
			{
				retry = Time.unscaledTime + 2f;
				if (Chainloader.PluginInfos.TryGetValue("com.bepis.bepinex.configurationmanager", out var value))
				{
					manager = value.Instance;
					displaying = ((object)manager).GetType().GetProperty("DisplayingWindow", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				}
			}
			if ((Object)(object)manager != (Object)null && displaying != null)
			{
				try
				{
					open = (bool)displaying.GetValue(manager, null);
				}
				catch
				{
					open = false;
				}
			}
			return open;
		}
	}

	internal static bool HudVisible(Hud hud)
	{
		if ((Object)(object)hud != (Object)null)
		{
			if (!Open)
			{
				return hud.IsVisible();
			}
			return true;
		}
		return false;
	}

	internal static bool MenuVisible()
	{
		if (!Open)
		{
			return Menu.IsVisible();
		}
		return false;
	}

	internal static bool MapVisible()
	{
		if (!Open)
		{
			return Minimap.IsOpen();
		}
		return false;
	}

	internal static bool StoreVisible()
	{
		if (!Open)
		{
			return StoreGui.IsVisible();
		}
		return false;
	}

	internal static bool InventoryHidesHud()
	{
		if (!Open)
		{
			return InventoryGui.IsVisible();
		}
		return false;
	}
}

BepInEx/plugins/MMC-LootFeed/SagaLootFeed.dll

Decompiled a week ago
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using EpicLoot;
using EpicLoot.Crafting;
using HarmonyLib;
using UnityEngine;

[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: CompilationRelaxations(8)]
[assembly: AssemblyVersion("0.0.0.0")]
internal static class SagaConfigPreview
{
	private static BaseUnityPlugin manager;

	private static PropertyInfo displaying;

	private static float retry;

	private static int frame = -1;

	private static bool open;

	internal static bool Open
	{
		get
		{
			if (frame == Time.frameCount)
			{
				return open;
			}
			frame = Time.frameCount;
			open = false;
			if ((Object)(object)manager == (Object)null && Time.unscaledTime >= retry)
			{
				retry = Time.unscaledTime + 2f;
				if (Chainloader.PluginInfos.TryGetValue("com.bepis.bepinex.configurationmanager", out var value))
				{
					manager = value.Instance;
					displaying = ((object)manager).GetType().GetProperty("DisplayingWindow", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				}
			}
			if ((Object)(object)manager != (Object)null && displaying != null)
			{
				try
				{
					open = (bool)displaying.GetValue(manager, null);
				}
				catch
				{
					open = false;
				}
			}
			return open;
		}
	}

	internal static bool HudVisible(Hud hud)
	{
		if ((Object)(object)hud != (Object)null)
		{
			if (!Open)
			{
				return hud.IsVisible();
			}
			return true;
		}
		return false;
	}

	internal static bool MenuVisible()
	{
		if (!Open)
		{
			return Menu.IsVisible();
		}
		return false;
	}

	internal static bool MapVisible()
	{
		if (!Open)
		{
			return Minimap.IsOpen();
		}
		return false;
	}

	internal static bool StoreVisible()
	{
		if (!Open)
		{
			return StoreGui.IsVisible();
		}
		return false;
	}

	internal static bool InventoryHidesHud()
	{
		if (!Open)
		{
			return InventoryGui.IsVisible();
		}
		return false;
	}
}
public static class SagaLootDelta
{
	public static Dictionary<string, int> Gains(Dictionary<string, int> previous, Dictionary<string, int> current)
	{
		Dictionary<string, int> dictionary = new Dictionary<string, int>();
		foreach (KeyValuePair<string, int> item in current)
		{
			previous.TryGetValue(item.Key, out var value);
			if (item.Value > value)
			{
				dictionary.Add(item.Key, item.Value - value);
			}
		}
		return dictionary;
	}
}
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInPlugin("local.mmc.lootfeed", "Saga Loot Feed", "3.0.3")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public sealed class SagaLootFeed : BaseUnityPlugin
{
	private sealed class ItemView
	{
		public string Key;

		public string Name;

		public string Rarity;

		public Color Color;

		public int Tier;

		public Sprite Icon;
	}

	private sealed class Drop
	{
		public ItemView Item;

		public int Quantity;

		public float Born;

		public float Y;

		public bool Placed;

		public bool Centered;

		public string QuantityText;

		public string DisplayName;

		public int MeasuredQuantity;

		public float MeasuredWidth;

		public float QuantityWidth;
	}

	private static SagaLootFeed instance;

	private Harmony harmony;

	private ConfigEntry<bool> enabledFeed;

	private ConfigEntry<bool> effects;

	private ConfigEntry<float> lifetime;

	private ConfigEntry<float> right;

	private ConfigEntry<float> bottom;

	private ConfigEntry<int> rows;

	private Inventory tracked;

	private Player player;

	private Dictionary<string, int> baseline = new Dictionary<string, int>();

	private readonly Dictionary<string, ItemView> views = new Dictionary<string, ItemView>();

	private readonly List<Drop> drops = new List<Drop>();

	private bool dirty;

	private bool addition;

	private float due;

	private float warmup;

	private int loading;

	private GUIStyle text;

	private GUIStyle small;

	private GUIStyle shadow;

	private FieldInfo clockStyle;

	private FieldInfo realClockRect;

	private FieldInfo realClockVisible;

	private FieldInfo dockRect;

	private FieldInfo dockVisible;

	private SagaPanelAppearance appearance;

	private readonly Dictionary<int, ConfigEntry<Color>> rarityColors = new Dictionary<int, ConfigEntry<Color>>();

	private readonly Dictionary<int, ConfigEntry<LootEffect>> rarityEffects = new Dictionary<int, ConfigEntry<LootEffect>>();

	private ConfigEntry<Color> commonColor;

	private ConfigEntry<Color> quantityColor;

	private ConfigEntry<LootEffect> commonEffect;

	private ConfigEntry<float> motionStrength;

	private ConfigEntry<bool> manualPosition;

	private bool dragging;

	private Vector2 dragOffset;

	private int dragControl;

	private int transferDepth;

	private Dictionary<string, int> beforeTransfer;

	private void Awake()
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: Expected O, but got Unknown
		//IL_0095: Unknown result type (might be due to invalid IL or missing references)
		//IL_009f: Expected O, but got Unknown
		//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d3: Expected O, but got Unknown
		//IL_0108: Unknown result type (might be due to invalid IL or missing references)
		//IL_0112: Expected O, but got Unknown
		//IL_0147: Unknown result type (might be due to invalid IL or missing references)
		//IL_0151: Expected O, but got Unknown
		//IL_021c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0226: Expected O, but got Unknown
		//IL_0252: Unknown result type (might be due to invalid IL or missing references)
		//IL_0260: Expected O, but got Unknown
		//IL_028e: Unknown result type (might be due to invalid IL or missing references)
		//IL_029b: Expected O, but got Unknown
		//IL_02f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_030d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0318: Expected O, but got Unknown
		//IL_0318: Expected O, but got Unknown
		//IL_0342: Unknown result type (might be due to invalid IL or missing references)
		//IL_0350: Expected O, but got Unknown
		//IL_037a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0391: Unknown result type (might be due to invalid IL or missing references)
		//IL_039c: Expected O, but got Unknown
		//IL_039c: Expected O, but got Unknown
		appearance = new SagaPanelAppearance(((BaseUnityPlugin)this).Config, true, 1f);
		instance = this;
		BindLootOptions();
		enabledFeed = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "Enabled", true, "Stack item acquisition notifications in the bottom-right corner.");
		effects = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "Rarity Effects", true, "Enable the per-rarity effects configured below.");
		lifetime = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "Duration", 6f, new ConfigDescription("Seconds each acquisition stays visible.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 15f), new object[0]));
		rows = ((BaseUnityPlugin)this).Config.Bind<int>("Display", "Maximum Rows", 6, new ConfigDescription("Maximum visible notifications per stack (regular feed and center highlights).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 10), new object[0]));
		right = ((BaseUnityPlugin)this).Config.Bind<float>("Position", "Right Margin", 20f, new ConfigDescription("Pixels from screen right.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10000f), new object[0]));
		bottom = ((BaseUnityPlugin)this).Config.Bind<float>("Position", "Bottom Margin", 24f, new ConfigDescription("Pixels above screen bottom; entries grow upward.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10000f), new object[0]));
		if (Chainloader.PluginInfos.TryGetValue("Azumatt.AzuClock", out var value))
		{
			clockStyle = AccessTools.Field(((object)value.Instance).GetType(), "Style");
		}
		if (Chainloader.PluginInfos.TryGetValue("local.mmc.realclock", out var value2))
		{
			realClockRect = AccessTools.Field(((object)value2.Instance).GetType(), "ScreenRect");
			realClockVisible = AccessTools.Field(((object)value2.Instance).GetType(), "ScreenVisible");
		}
		if (Chainloader.PluginInfos.TryGetValue("local.mmc.panelui", out value2))
		{
			dockRect = AccessTools.Field(((object)value2.Instance).GetType(), "DockRect");
			dockVisible = AccessTools.Field(((object)value2.Instance).GetType(), "DockVisible");
		}
		harmony = new Harmony("local.mmc.lootfeed");
		harmony.Patch((MethodBase)AccessTools.Method(typeof(Character), "ShowPickupMessage", (Type[])null, (Type[])null), new HarmonyMethod(typeof(SagaLootFeed), "NativePickupMessage", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		harmony.Patch((MethodBase)AccessTools.Method(typeof(Inventory), "Changed", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(SagaLootFeed), "Changed", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		MethodInfo[] methods = typeof(Inventory).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
		foreach (MethodInfo methodInfo in methods)
		{
			if (methodInfo.Name == "MoveAll" || methodInfo.Name == "MoveItemToThis")
			{
				harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(SagaLootFeed), "BeforeTransfer", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(SagaLootFeed), "AfterTransfer", (Type[])null), (HarmonyMethod)null);
			}
			if (methodInfo.Name == "AddItem")
			{
				harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(SagaLootFeed), "Adding", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			if (methodInfo.Name == "Load")
			{
				harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(SagaLootFeed), "Loading", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(SagaLootFeed), "Loaded", (Type[])null), (HarmonyMethod)null);
			}
		}
	}

	private static bool NativePickupMessage(Character __instance)
	{
		if (!((Object)(object)instance == (Object)null) && instance.enabledFeed.Value)
		{
			return (Object)(object)__instance != (Object)(object)Player.m_localPlayer;
		}
		return true;
	}

	private static bool IsLocal(Inventory inventory)
	{
		if ((Object)(object)instance != (Object)null && (Object)(object)Player.m_localPlayer != (Object)null)
		{
			return inventory == ((Humanoid)Player.m_localPlayer).GetInventory();
		}
		return false;
	}

	private static void Changed(Inventory __instance)
	{
		if (IsLocal(__instance))
		{
			if (!instance.dirty)
			{
				instance.due = Time.unscaledTime + 0.12f;
			}
			instance.dirty = true;
		}
	}

	private static void Adding(Inventory __instance)
	{
		if (IsLocal(__instance))
		{
			instance.addition = true;
			Changed(__instance);
		}
	}

	private static void Loading(Inventory __instance, out bool __state)
	{
		__state = IsLocal(__instance);
		if (__state)
		{
			instance.loading++;
		}
	}

	private static Exception Loaded(Exception __exception, bool __state)
	{
		if (__state && (Object)(object)instance != (Object)null)
		{
			instance.loading = Math.Max(0, instance.loading - 1);
			instance.warmup = Time.unscaledTime + 0.5f;
			instance.addition = false;
		}
		return __exception;
	}

	private ItemView Describe(ItemData item)
	{
		//IL_003c: 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_0061: 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_009e: 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_00b1: 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_00d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d6: Expected I4, but got Unknown
		//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f3: 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)
		ItemView itemView = new ItemView();
		itemView.Name = Localization.instance.Localize(item.m_shared.m_name);
		itemView.Rarity = "Common";
		itemView.Color = new Color(0.82f, 0.82f, 0.79f);
		itemView.Tier = -1;
		itemView.Icon = item.GetIcon();
		MagicItem magicItem = ItemDataExtensions.GetMagicItem(item);
		ItemRarity val = (ItemRarity)0;
		bool flag = false;
		if (magicItem != null)
		{
			val = magicItem.Rarity;
			flag = true;
			if (!string.IsNullOrEmpty(magicItem.DisplayName))
			{
				itemView.Name = Localization.instance.Localize(magicItem.DisplayName);
			}
		}
		else if (CraftingItemExtensions.IsMagicCraftingMaterial(item))
		{
			val = CraftingItemExtensions.GetCraftingMaterialRarity(item);
			flag = true;
		}
		else if (CraftingItemExtensions.IsRunestone(item))
		{
			val = CraftingItemExtensions.GetRunestoneRarity(item);
			flag = true;
		}
		else if (CraftingItemExtensions.IsShardSlotChisel(item))
		{
			val = CraftingItemExtensions.GetShardSlotChiselRarity(item);
			flag = true;
		}
		if (flag)
		{
			itemView.Tier = (int)val;
			itemView.Rarity = Localization.instance.Localize(EpicLoot.GetRarityDisplayName(val));
			itemView.Color = EpicLoot.GetRarityColorARGB(val);
			itemView.Color.a = 1f;
		}
		itemView.Key = item.m_shared.m_name + "|" + item.m_quality + "|" + item.m_variant + "|" + itemView.Tier + "|" + itemView.Name;
		return itemView;
	}

	private Dictionary<string, int> Snapshot()
	{
		Dictionary<string, int> dictionary = new Dictionary<string, int>();
		views.Clear();
		foreach (ItemData allItem in tracked.GetAllItems())
		{
			if (allItem != null && allItem.m_shared != null && allItem.m_stack > 0)
			{
				ItemView itemView = Describe(allItem);
				dictionary.TryGetValue(itemView.Key, out var value);
				dictionary[itemView.Key] = value + allItem.m_stack;
				views[itemView.Key] = itemView;
			}
		}
		return dictionary;
	}

	private void Update()
	{
		Player localPlayer = Player.m_localPlayer;
		if ((Object)(object)localPlayer != (Object)(object)player || ((Object)(object)localPlayer != (Object)null && tracked != ((Humanoid)localPlayer).GetInventory()))
		{
			player = localPlayer;
			tracked = (((Object)(object)localPlayer == (Object)null) ? null : ((Humanoid)localPlayer).GetInventory());
			drops.Clear();
			baseline.Clear();
			dirty = (addition = false);
			loading = 0;
			warmup = Time.unscaledTime + 1f;
			if (tracked != null)
			{
				baseline = Snapshot();
			}
			return;
		}
		float unscaledTime = Time.unscaledTime;
		for (int num = drops.Count - 1; num >= 0; num--)
		{
			if (unscaledTime - drops[num].Born >= lifetime.Value)
			{
				drops.RemoveAt(num);
			}
		}
		if (tracked == null || !dirty || unscaledTime < due || loading > 0)
		{
			return;
		}
		Dictionary<string, int> current = Snapshot();
		if (enabledFeed.Value && addition && unscaledTime >= warmup)
		{
			foreach (KeyValuePair<string, int> item in SagaLootDelta.Gains(baseline, current))
			{
				Push(views[item.Key], item.Value, unscaledTime);
			}
		}
		baseline = current;
		dirty = (addition = false);
	}

	private void Push(ItemView item, int quantity, float now)
	{
		foreach (Drop drop in drops)
		{
			if (drop.Item.Key == item.Key && now - drop.Born < 1.2f)
			{
				drop.Quantity += quantity;
				drop.Born = now;
				return;
			}
		}
		bool flag = effects.Value && LootVisual(item) == LootEffect.CenterGlow;
		int num = 0;
		int num2 = -1;
		for (int i = 0; i < drops.Count; i++)
		{
			if (drops[i].Centered == flag)
			{
				num++;
				if (num2 < 0)
				{
					num2 = i;
				}
			}
		}
		if (num >= rows.Value && num2 >= 0)
		{
			drops.RemoveAt(num2);
		}
		drops.Add(new Drop
		{
			Item = item,
			Quantity = quantity,
			Born = now,
			Centered = flag
		});
	}

	private void EnsureStyles()
	{
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Expected O, but got Unknown
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: Expected O, but got Unknown
		//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bf: Expected O, but got Unknown
		//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dd: Expected O, but got Unknown
		if (text == null)
		{
			text = new GUIStyle(GUI.skin.label);
			text.fontSize = 18;
			text.fontStyle = (FontStyle)0;
			text.padding = new RectOffset();
			text.alignment = (TextAnchor)3;
			text.richText = false;
			text.wordWrap = false;
			text.clipping = (TextClipping)1;
			GUIStyle val = (GUIStyle)((clockStyle == null) ? null : /*isinst with value type is only supported in some contexts*/);
			if (val != null)
			{
				text.font = val.font;
			}
			small = new GUIStyle(text);
			small.fontSize = 13;
			shadow = new GUIStyle(text);
		}
	}

	private static void Fill(Rect r, Color c)
	{
		//IL_0000: 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)
		GUI.color = c;
		GUI.DrawTexture(r, (Texture)(object)Texture2D.whiteTexture);
	}

	private void Label(Rect r, string value, GUIStyle style, Color color, float alpha)
	{
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_005b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0065: Unknown result type (might be due to invalid IL or missing references)
		//IL_0097: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00be: Unknown result type (might be due to invalid IL or missing references)
		alpha *= color.a;
		shadow.font = style.font;
		shadow.fontSize = style.fontSize;
		shadow.alignment = style.alignment;
		shadow.normal.textColor = new Color(0f, 0f, 0f, alpha);
		GUI.color = Color.white;
		GUI.Label(new Rect(((Rect)(ref r)).x + 1f, ((Rect)(ref r)).y + 1f, ((Rect)(ref r)).width, ((Rect)(ref r)).height), value, shadow);
		color.a = alpha;
		style.normal.textColor = color;
		GUI.Label(r, value, style);
	}

	private string Fit(string value, float width)
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Expected O, but got Unknown
		//IL_000c: 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_0050: Expected O, but got Unknown
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		if (text.CalcSize(new GUIContent(value)).x <= width)
		{
			return value;
		}
		while (value.Length > 1 && text.CalcSize(new GUIContent(value + "…")).x > width)
		{
			value = value.Substring(0, value.Length - 1);
		}
		return value + "…";
	}

	private void OnGUI()
	{
		//IL_0a41: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a47: 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_0062: Unknown result type (might be due to invalid IL or missing references)
		//IL_0063: Unknown result type (might be due to invalid IL or missing references)
		//IL_0068: Unknown result type (might be due to invalid IL or missing references)
		//IL_0095: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b0: 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_01ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01df: Invalid comparison between Unknown and I4
		//IL_0224: Unknown result type (might be due to invalid IL or missing references)
		//IL_025f: Unknown result type (might be due to invalid IL or missing references)
		//IL_026f: Unknown result type (might be due to invalid IL or missing references)
		//IL_04b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_04ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_04fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_057a: Unknown result type (might be due to invalid IL or missing references)
		//IL_057c: Unknown result type (might be due to invalid IL or missing references)
		//IL_058f: Unknown result type (might be due to invalid IL or missing references)
		//IL_05cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_05f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_063c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0663: Unknown result type (might be due to invalid IL or missing references)
		//IL_0805: Unknown result type (might be due to invalid IL or missing references)
		//IL_080a: Unknown result type (might be due to invalid IL or missing references)
		//IL_081d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0841: Unknown result type (might be due to invalid IL or missing references)
		//IL_08a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_06b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_06e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_0908: Unknown result type (might be due to invalid IL or missing references)
		//IL_0912: Expected O, but got Unknown
		//IL_090d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0986: Unknown result type (might be due to invalid IL or missing references)
		//IL_0998: Unknown result type (might be due to invalid IL or missing references)
		//IL_09bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_09d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a01: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a18: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a21: Unknown result type (might be due to invalid IL or missing references)
		//IL_0770: Unknown result type (might be due to invalid IL or missing references)
		//IL_078c: Unknown result type (might be due to invalid IL or missing references)
		//IL_07aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_07c6: Unknown result type (might be due to invalid IL or missing references)
		if (!appearance.InventoryVisible || !enabledFeed.Value || (Object)(object)player == (Object)null || (Object)(object)Hud.instance == (Object)null || (!SagaConfigPreview.HudVisible(Hud.instance) && !SagaConfigPreview.InventoryHidesHud()) || SagaConfigPreview.MenuVisible() || SagaConfigPreview.MapVisible())
		{
			return;
		}
		EnsureStyles();
		Color color = GUI.color;
		Matrix4x4 matrix = GUI.matrix;
		int depth = GUI.depth;
		GUI.depth = -150;
		try
		{
			Vector2 val = appearance.Size(new Vector2(350f, 52f + appearance.HeaderHeight), 180f, 52f + appearance.HeaderHeight);
			float y = val.y;
			float num = Mathf.Min(val.x, (float)(Screen.width - 16));
			float num2 = Mathf.Clamp((float)Screen.width - right.Value - num, 8f, Mathf.Max(8f, (float)Screen.width - num - 8f));
			float num3 = Mathf.Clamp((float)Screen.height - bottom.Value - y, 8f, Mathf.Max(8f, (float)Screen.height - y - 8f));
			for (int i = 0; i < ((!manualPosition.Value) ? 2 : 0); i++)
			{
				num3 = ClearObstacle(num2, num, num3, y, realClockRect, realClockVisible);
				num3 = ClearObstacle(num2, num, num3, y, dockRect, dockVisible);
			}
			Rect val2 = appearance.Position(new Rect(num2, num3, num, y));
			num2 = ((Rect)(ref val2)).x;
			num3 = ((Rect)(ref val2)).y;
			HandlePlacement(val2);
			if ((int)Event.current.type != 7)
			{
				return;
			}
			if (!drops.Exists((Drop item) => !item.Centered) && (InventoryGui.IsVisible() || SagaConfigPreview.Open))
			{
				appearance.Draw(val2, 0.8f, "Item feed");
				Label(new Rect(num2 + 12f, num3 + appearance.HeaderHeight + 8f, num - 24f, 30f), "Item feed - drag to move", text, Color.white, 1f);
			}
			int num4 = 0;
			int num5 = 0;
			int num6 = 0;
			foreach (Drop drop2 in drops)
			{
				if (drop2.Centered)
				{
					num6++;
				}
			}
			int num7 = Mathf.Min(rows.Value, Mathf.Max(1, Mathf.FloorToInt((num3 + y) / (y + 5f))));
			int num8 = Mathf.Min(rows.Value, Mathf.Max(1, Mathf.FloorToInt((float)(Screen.height - 16) / (y + 5f))));
			float num9 = Mathf.Clamp((float)Screen.height * 0.35f, 8f, Mathf.Max(8f, (float)(Screen.height - 8) - (float)Mathf.Min(num6, num8) * (y + 5f)));
			Rect val3 = default(Rect);
			for (int num10 = 0; num10 < drops.Count; num10++)
			{
				Drop drop = drops[drops.Count - 1 - num10];
				float num11 = Time.unscaledTime - drop.Born;
				int num12 = (drop.Centered ? num5++ : num4++);
				if (num12 >= (drop.Centered ? num8 : num7))
				{
					continue;
				}
				float num13 = Mathf.Min(Mathf.Clamp01(num11 / 0.18f), Mathf.Clamp01((lifetime.Value - num11) / 0.8f));
				float num14 = (drop.Centered ? (num9 + (float)num12 * (y + 5f)) : (num3 - (float)num12 * (y + 5f)));
				if (!drop.Placed)
				{
					drop.Y = num14;
					drop.Placed = true;
				}
				drop.Y = Mathf.Lerp(drop.Y, num14, 1f - Mathf.Exp(-14f * Time.unscaledDeltaTime));
				float num15 = (drop.Centered ? (((float)Screen.width - num) * 0.5f) : num2) + 18f * (1f - Mathf.Clamp01(num11 / 0.25f));
				((Rect)(ref val3))..ctor(num15, drop.Y, num, y);
				Color val4 = LootColor(drop.Item);
				LootEffect lootEffect = (effects.Value ? LootVisual(drop.Item) : LootEffect.None);
				if (lootEffect == LootEffect.Wobble)
				{
					GUIUtility.RotateAroundPivot(Mathf.Sin(num11 * 7f) * motionStrength.Value, ((Rect)(ref val3)).center);
				}
				if (lootEffect == LootEffect.Shake)
				{
					((Rect)(ref val3)).x = ((Rect)(ref val3)).x + Mathf.Sin(num11 * 39f) * motionStrength.Value * Mathf.Exp(0f - num11);
					((Rect)(ref val3)).y = ((Rect)(ref val3)).y + Mathf.Cos(num11 * 31f) * motionStrength.Value * 0.6f * Mathf.Exp(0f - num11);
					num15 = ((Rect)(ref val3)).x;
				}
				DrawLootGlow(val3, val4, num13, num11, lootEffect);
				appearance.Draw(val3, 0.78f * num13, "Item acquired");
				float num16 = ((Rect)(ref val3)).y + appearance.HeaderHeight;
				Fill(new Rect(num15, num16, 3f, y - appearance.HeaderHeight), new Color(val4.r, val4.g, val4.b, num13 * val4.a));
				if (lootEffect != LootEffect.None)
				{
					float num17 = 0.06f + 0.025f * Mathf.Sin(num11 * 4f);
					Fill(new Rect(num15 + 3f, num16 + 1f, num - 3f, 50f), new Color(val4.r, val4.g, val4.b, num17 * num13 * val4.a));
					if (drop.Item.Tier >= 2)
					{
						float num18 = num15 + 5f + Mathf.Repeat(num11 * 0.32f, 1f) * (num - 10f);
						Fill(new Rect(num18, num16 + 1f, 2f, 50f), new Color(val4.r, val4.g, val4.b, num13 * 0.14f * val4.a));
					}
					if (drop.Item.Tier >= 3)
					{
						for (int num19 = 0; num19 < 3; num19++)
						{
							float num20 = num15 + num - 22f - (float)(num19 * 20);
							float num21 = num16 + 34f + Mathf.Sin(num11 * 3f + (float)num19) * 3f;
							float num22 = num13 * (0.35f + 0.3f * Mathf.Sin(num11 * 5f + (float)num19));
							Fill(new Rect(num20 - 2f, num21, 5f, 1f), new Color(val4.r, val4.g, val4.b, num22));
							Fill(new Rect(num20, num21 - 2f, 1f, 5f), new Color(val4.r, val4.g, val4.b, num22));
						}
					}
				}
				if ((Object)(object)drop.Item.Icon != (Object)null)
				{
					Sprite icon = drop.Item.Icon;
					Rect textureRect = icon.textureRect;
					GUI.color = new Color(1f, 1f, 1f, num13);
					GUI.DrawTextureWithTexCoords(new Rect(num15 + 10f, num16 + 8f, 36f, 36f), (Texture)(object)icon.texture, new Rect(((Rect)(ref textureRect)).x / (float)((Texture)icon.texture).width, ((Rect)(ref textureRect)).y / (float)((Texture)icon.texture).height, ((Rect)(ref textureRect)).width / (float)((Texture)icon.texture).width, ((Rect)(ref textureRect)).height / (float)((Texture)icon.texture).height));
				}
				if (drop.QuantityText == null || drop.MeasuredQuantity != drop.Quantity || drop.MeasuredWidth != num)
				{
					drop.QuantityText = "+" + drop.Quantity.ToString("N0", CultureInfo.InvariantCulture);
					drop.QuantityWidth = text.CalcSize(new GUIContent(drop.QuantityText)).x;
					drop.DisplayName = Fit(drop.Item.Name, num - drop.QuantityWidth - 78f);
					drop.MeasuredQuantity = drop.Quantity;
					drop.MeasuredWidth = num;
				}
				float quantityWidth = drop.QuantityWidth;
				Label(new Rect(num15 + 56f, num16 + 5f, num - quantityWidth - 78f, 24f), drop.DisplayName, text, val4, num13);
				Label(new Rect(num15 + num - quantityWidth - 12f, num16 + 5f, quantityWidth, 24f), drop.QuantityText, text, quantityColor.Value, num13);
				Label(new Rect(num15 + 56f, num16 + 29f, num - 70f, 18f), drop.Item.Rarity, small, val4, num13);
				GUI.matrix = matrix;
			}
		}
		finally
		{
			GUI.matrix = matrix;
			GUI.color = color;
			GUI.depth = depth;
		}
	}

	private static float ClearObstacle(float x, float width, float y, float height, FieldInfo rectField, FieldInfo visibleField)
	{
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: Unknown result type (might be due to invalid IL or missing references)
		if (rectField == null || visibleField == null || !(bool)visibleField.GetValue(null))
		{
			return y;
		}
		Rect val = (Rect)rectField.GetValue(null);
		return SagaLootLayout.ClearBottomRow(x, width, y, ((Rect)(ref val)).x, ((Rect)(ref val)).y, ((Rect)(ref val)).width, ((Rect)(ref val)).height, height);
	}

	private void OnDestroy()
	{
		if (harmony != null)
		{
			harmony.UnpatchSelf();
		}
		drops.Clear();
		instance = null;
	}

	private void BindLootOptions()
	{
		//IL_0025: 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_00a1: 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_00a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a9: Expected I4, but got Unknown
		//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00aa: 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_00ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_0180: Unknown result type (might be due to invalid IL or missing references)
		//IL_018a: Expected O, but got Unknown
		//IL_0112: Unknown result type (might be due to invalid IL or missing references)
		commonColor = ((BaseUnityPlugin)this).Config.Bind<Color>("Rarity Colors", "Common", new Color(0.82f, 0.82f, 0.79f, 1f), "Common item name, rarity stripe and effect color.");
		quantityColor = ((BaseUnityPlugin)this).Config.Bind<Color>("Rarity Colors", "Quantity", Color.white, "Acquired quantity text color.");
		commonEffect = ((BaseUnityPlugin)this).Config.Bind<LootEffect>("Rarity Effects", "Common", LootEffect.None, "Animation for common items.");
		foreach (ItemRarity value in Enum.GetValues(typeof(ItemRarity)))
		{
			int num = (int)value;
			Color rarityColorARGB = EpicLoot.GetRarityColorARGB(value);
			rarityColorARGB.a = 1f;
			rarityColors[num] = ((BaseUnityPlugin)this).Config.Bind<Color>("Rarity Colors", ((object)value).ToString(), rarityColorARGB, "Item name, rarity stripe and effect color.");
			LootEffect lootEffect = ((num >= 3) ? LootEffect.CenterGlow : (num switch
			{
				1 => LootEffect.Shake, 
				2 => LootEffect.Wobble, 
				_ => LootEffect.Glow, 
			}));
			rarityEffects[num] = ((BaseUnityPlugin)this).Config.Bind<LootEffect>("Rarity Effects", ((object)value).ToString(), lootEffect, "Choose no effect, glow, wobble, shake, or a center-screen glow. Centered acquisitions stack there until their normal Display Duration expires; changes affect the location of new acquisitions.");
		}
		motionStrength = ((BaseUnityPlugin)this).Config.Bind<float>("Rarity Effects", "Motion Strength", 1.5f, new ConfigDescription("Maximum wobble degrees or shake pixels.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 8f), new object[0]));
		manualPosition = ((BaseUnityPlugin)this).Config.Bind<bool>("Position", "Manual Placement", false, "Enabled by dragging. Turn off to restore automatic clock and dock avoidance; margins still apply.");
	}

	private Color LootColor(ItemView item)
	{
		//IL_0022: 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)
		if (!rarityColors.TryGetValue(item.Tier, out var value))
		{
			return commonColor.Value;
		}
		return value.Value;
	}

	private LootEffect LootVisual(ItemView item)
	{
		if (!rarityEffects.TryGetValue(item.Tier, out var value))
		{
			return commonEffect.Value;
		}
		return value.Value;
	}

	private void DrawLootGlow(Rect panel, Color tint, float alpha, float age, LootEffect effect)
	{
		//IL_0085: Unknown result type (might be due to invalid IL or missing references)
		//IL_008a: Unknown result type (might be due to invalid IL or missing references)
		if (effect != LootEffect.None)
		{
			float num = 0.65f + 0.35f * Mathf.Sin(age * 4f);
			Color c = default(Color);
			for (int num2 = 3; num2 >= 1; num2--)
			{
				float num3 = num2 * 2;
				((Color)(ref c))..ctor(tint.r, tint.g, tint.b, alpha * tint.a * num * 0.055f);
				Fill(new Rect(((Rect)(ref panel)).x - num3, ((Rect)(ref panel)).y - num3, ((Rect)(ref panel)).width + 2f * num3, ((Rect)(ref panel)).height + 2f * num3), c);
			}
		}
	}

	private void HandlePlacement(Rect anchor)
	{
		//IL_0117: Unknown result type (might be due to invalid IL or missing references)
		//IL_017b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0181: Invalid comparison between Unknown and I4
		//IL_0129: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e7: Invalid comparison between Unknown and I4
		//IL_0187: Unknown result type (might be due to invalid IL or missing references)
		//IL_018d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0192: Unknown result type (might be due to invalid IL or missing references)
		//IL_0197: Unknown result type (might be due to invalid IL or missing references)
		//IL_027e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0152: Unknown result type (might be due to invalid IL or missing references)
		//IL_0159: Unknown result type (might be due to invalid IL or missing references)
		//IL_015e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0163: Unknown result type (might be due to invalid IL or missing references)
		Event current = Event.current;
		int controlID = GUIUtility.GetControlID(5459014, (FocusType)2);
		if (!InventoryGui.IsVisible() || SagaConfigPreview.Open || StoreGui.IsVisible())
		{
			if (dragging && GUIUtility.hotControl == dragControl)
			{
				GUIUtility.hotControl = 0;
			}
			if (dragging)
			{
				((BaseUnityPlugin)this).Config.Save();
			}
			dragging = false;
			return;
		}
		int num = 0;
		foreach (Drop drop in drops)
		{
			if (!drop.Centered)
			{
				num++;
			}
		}
		num = Mathf.Min(num, rows.Value);
		Rect val = default(Rect);
		((Rect)(ref val))..ctor(((Rect)(ref anchor)).x, Mathf.Max(0f, ((Rect)(ref anchor)).y - (float)Mathf.Max(0, num - 1) * (((Rect)(ref anchor)).height + 5f)), ((Rect)(ref anchor)).width, ((Rect)(ref anchor)).height + (float)Mathf.Max(0, num - 1) * (((Rect)(ref anchor)).height + 5f));
		if ((int)current.type == 0 && current.button == 0 && ((Rect)(ref val)).Contains(current.mousePosition) && GUIUtility.hotControl == 0)
		{
			dragging = true;
			dragControl = controlID;
			GUIUtility.hotControl = controlID;
			dragOffset = current.mousePosition - ((Rect)(ref anchor)).position;
			current.Use();
		}
		else if (dragging && (int)current.type == 3)
		{
			Vector2 val2 = current.mousePosition - dragOffset;
			bool saveOnConfigSet = ((BaseUnityPlugin)this).Config.SaveOnConfigSet;
			((BaseUnityPlugin)this).Config.SaveOnConfigSet = false;
			try
			{
				right.Value = Mathf.Clamp((float)Screen.width - ((Rect)(ref anchor)).width - val2.x, 0f, Mathf.Max(0f, (float)Screen.width - ((Rect)(ref anchor)).width));
				bottom.Value = Mathf.Clamp((float)Screen.height - ((Rect)(ref anchor)).height - val2.y, 0f, Mathf.Max(0f, (float)Screen.height - ((Rect)(ref anchor)).height));
				manualPosition.Value = true;
				appearance.SavePosition(new Vector2((float)Screen.width - ((Rect)(ref anchor)).width - right.Value, (float)Screen.height - ((Rect)(ref anchor)).height - bottom.Value));
			}
			finally
			{
				((BaseUnityPlugin)this).Config.SaveOnConfigSet = saveOnConfigSet;
			}
			foreach (Drop drop2 in drops)
			{
				drop2.Placed = false;
			}
			current.Use();
		}
		else if (dragging && (int)current.type == 1)
		{
			dragging = false;
			GUIUtility.hotControl = 0;
			((BaseUnityPlugin)this).Config.Save();
			current.Use();
		}
	}

	private static void BeforeTransfer(Inventory __instance, Inventory __0, out bool __state)
	{
		__state = IsLocal(__instance) || IsLocal(__0);
		if (__state)
		{
			if (instance.tracked == null)
			{
				instance.tracked = ((Humanoid)Player.m_localPlayer).GetInventory();
			}
			if (instance.transferDepth++ == 0)
			{
				instance.beforeTransfer = instance.Snapshot();
			}
		}
	}

	private static Exception AfterTransfer(Exception __exception, bool __state)
	{
		if (!__state || (Object)(object)instance == (Object)null)
		{
			return __exception;
		}
		if (--instance.transferDepth == 0 && instance.beforeTransfer != null)
		{
			Dictionary<string, int> dictionary = instance.Snapshot();
			HashSet<string> hashSet = new HashSet<string>(instance.beforeTransfer.Keys);
			hashSet.UnionWith(dictionary.Keys);
			foreach (string item in hashSet)
			{
				instance.beforeTransfer.TryGetValue(item, out var value);
				dictionary.TryGetValue(item, out var value2);
				instance.baseline.TryGetValue(item, out var value3);
				instance.baseline[item] = SagaTransferAccounting.Baseline(value3, value, value2);
			}
			instance.beforeTransfer = null;
		}
		return __exception;
	}
}
public static class SagaLootLayout
{
	public static float ClearBottomRow(float x, float width, float y, float ox, float oy, float ow, float oh, float height = 52f)
	{
		if (ow <= 0f || oh <= 0f || x + width <= ox || x >= ox + ow)
		{
			return y;
		}
		if (y + height > oy - 8f && y < oy + oh + 8f)
		{
			return Math.Max(8f, Math.Min(y, oy - height - 8f));
		}
		return y;
	}
}
public enum LootEffect
{
	None,
	Glow,
	Wobble,
	Shake,
	CenterGlow
}
public static class SagaTransferAccounting
{
	public static int Baseline(int baseline, int before, int after)
	{
		return Math.Max(0, baseline + after - before);
	}
}

BepInEx/plugins/MMC-PanelUI/SagaPanelUI.dll

Decompiled a week ago
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security.Cryptography;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("0.0.0.0")]
public sealed class SagaSavedSetting
{
	public string Guid;

	public string Version;

	public string Section;

	public string Key;

	public string Value;

	public string Id => Guid + "\n" + Section + "\n" + Key;
}
public static class SagaConfigArchive
{
	public static bool ShouldRestore(bool force, string savedVersion, string currentVersion, bool isDefault)
	{
		if (!force && !(savedVersion != currentVersion))
		{
			return isDefault;
		}
		return true;
	}

	public static bool IsPrivate(string section, string key)
	{
		string text = (section + " " + key).ToLowerInvariant();
		string[] array = new string[9] { "password", "passwd", "secret", "token", "credential", "api key", "apikey", "private key", "authkey" };
		foreach (string value in array)
		{
			if (text.Contains(value))
			{
				return true;
			}
		}
		return false;
	}

	public static string Hash(string value)
	{
		using SHA256 sHA = SHA256.Create();
		return BitConverter.ToString(sHA.ComputeHash(Encoding.UTF8.GetBytes(value))).Replace("-", "").ToLowerInvariant();
	}

	private static string Encode(string value)
	{
		return Convert.ToBase64String(Encoding.UTF8.GetBytes(value ?? ""));
	}

	private static string Decode(string value)
	{
		return Encoding.UTF8.GetString(Convert.FromBase64String(value));
	}

	public static string Serialize(IEnumerable<SagaSavedSetting> values)
	{
		List<string> list = new List<string>();
		foreach (SagaSavedSetting value in values)
		{
			if (!IsPrivate(value.Section, value.Key))
			{
				list.Add(string.Join("\t", Encode(value.Guid), Encode(value.Version), Encode(value.Section), Encode(value.Key), Encode(value.Value)));
			}
		}
		list.Sort(StringComparer.Ordinal);
		string text = "SagaConfigBackup1\n" + string.Join("\n", list.ToArray()) + "\n";
		return text + "SHA256\t" + Hash(text) + "\n";
	}

	public static Dictionary<string, SagaSavedSetting> Parse(string text)
	{
		int num = text.LastIndexOf("SHA256\t", StringComparison.Ordinal);
		if (num < 0 || !text.StartsWith("SagaConfigBackup1\n", StringComparison.Ordinal) || Hash(text.Substring(0, num)) != text.Substring(num + 7).Trim())
		{
			throw new InvalidDataException("Config backup checksum mismatch.");
		}
		Dictionary<string, SagaSavedSetting> dictionary = new Dictionary<string, SagaSavedSetting>();
		string[] array = text.Substring(18, num - 18).Split(new char[1] { '\n' });
		foreach (string text2 in array)
		{
			if (text2.Length != 0)
			{
				string[] array2 = text2.Split(new char[1] { '\t' });
				if (array2.Length != 5)
				{
					throw new InvalidDataException("Malformed setting record.");
				}
				SagaSavedSetting sagaSavedSetting = new SagaSavedSetting();
				sagaSavedSetting.Guid = Decode(array2[0]);
				sagaSavedSetting.Version = Decode(array2[1]);
				sagaSavedSetting.Section = Decode(array2[2]);
				sagaSavedSetting.Key = Decode(array2[3]);
				sagaSavedSetting.Value = Decode(array2[4]);
				SagaSavedSetting sagaSavedSetting2 = sagaSavedSetting;
				if (!IsPrivate(sagaSavedSetting2.Section, sagaSavedSetting2.Key))
				{
					dictionary[sagaSavedSetting2.Id] = sagaSavedSetting2;
				}
			}
		}
		return dictionary;
	}

	public static void Write(string path, IEnumerable<SagaSavedSetting> values)
	{
		Directory.CreateDirectory(Path.GetDirectoryName(path));
		string text = Serialize(values);
		Parse(text);
		if (!File.Exists(path) || !(File.ReadAllText(path) == text))
		{
			string text2 = path + ".tmp";
			File.WriteAllText(text2, text, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
			if (File.Exists(path))
			{
				File.Replace(text2, path, path + ".previous");
			}
			else
			{
				File.Move(text2, path);
			}
		}
	}
}
[BepInPlugin("local.mmc.panelui", "Saga Panel Windows", "3.0.3")]
public sealed class SagaPanelUI : BaseUnityPlugin
{
	private ConfigEntry<bool> backupEnabled;

	private ConfigEntry<bool> restoreUpdates;

	private ConfigEntry<bool> backupNow;

	private ConfigEntry<bool> restoreNow;

	private readonly HashSet<ConfigFile> watchedConfigs = new HashSet<ConfigFile>();

	private Dictionary<string, SagaSavedSetting> savedConfigs = new Dictionary<string, SagaSavedSetting>();

	private string backupPath;

	private bool backupReady;

	private bool backupChanging;

	private bool backupBlocked;

	private bool backupDirty;

	private float backupDue;

	private float discoverDue;

	private ConfigEntry<bool> hideNative;

	private static ConfigEntry<bool> enabledSupport;

	private Hud nativeHud;

	private readonly Dictionary<Graphic, bool> nativeGraphics = new Dictionary<Graphic, bool>();

	private GameObject nativeTemplate;

	private bool templateWasActive;

	private readonly Dictionary<CanvasGroup, float> indicatorAlphas = new Dictionary<CanvasGroup, float>();

	private readonly List<CanvasGroup> addedIndicators = new List<CanvasGroup>();

	public static bool PowerOnHotbar;

	public static float LastCombatAt = float.NegativeInfinity;

	internal static readonly List<SagaPanelWindow> Windows = new List<SagaPanelWindow>();

	public static Rect DockRect;

	public static bool DockVisible;

	public static Rect HotbarRect;

	public static bool HotbarVisible;

	public static readonly Color TextColor = new Color(0.92f, 0.89f, 0.81f, 1f);

	private static readonly Dictionary<int, GUIStyle> styles = new Dictionary<int, GUIStyle>();

	private static GUIStyle buttonStyle;

	private static Font headerFont;

	private static bool fontResolved;

	private Transform previewRoot;

	private Vector3 previousHudPosition;

	private GameObject previewMap;

	private bool previousMapActive;

	private readonly List<SagaPanelWindow> queue = new List<SagaPanelWindow>();

	public static bool ManagementEnabled
	{
		get
		{
			if (enabledSupport != null)
			{
				return enabledSupport.Value;
			}
			return true;
		}
	}

	private void BindConfigPersistence()
	{
		backupEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Config Persistence", "Enabled", true, "Back up recognized loaded mods outside BepInEx, separately per profile. Passwords and secret fields are excluded.");
		restoreUpdates = ((BaseUnityPlugin)this).Config.Bind<bool>("Config Persistence", "Restore After Updates", true, "At startup restore saved settings when a mod version changes or a setting has reverted to its default. Non-default offline edits for unchanged versions are preserved.");
		backupNow = ((BaseUnityPlugin)this).Config.Bind<bool>("Config Persistence", "Save Now", false, "Check to save recognized settings now; automatically resets.");
		restoreNow = ((BaseUnityPlugin)this).Config.Bind<bool>("Config Persistence", "Restore Now", false, "Check to restore all compatible saved settings; automatically resets. Restart for mods that do not apply settings live.");
		string fullPath = Path.GetFullPath(Path.Combine(Paths.ConfigPath, "..", ".."));
		backupPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "SagaPro", "Valheim", "ConfigBackups", new DirectoryInfo(fullPath).Name + "-" + SagaConfigArchive.Hash(fullPath.ToLowerInvariant()).Substring(0, 12), "settings.saga");
	}

	private void Start()
	{
		try
		{
			if (File.Exists(backupPath))
			{
				savedConfigs = SagaConfigArchive.Parse(File.ReadAllText(backupPath));
			}
			DiscoverConfigs();
			if (backupEnabled.Value && restoreUpdates.Value)
			{
				RestoreConfigs(force: false);
			}
			backupReady = true;
			if (backupEnabled.Value)
			{
				SaveConfigs();
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Config persistence ready: " + backupPath));
		}
		catch (Exception ex)
		{
			backupBlocked = true;
			((BaseUnityPlugin)this).Logger.LogError((object)("Config backup left untouched: " + ex.Message));
		}
	}

	private void DiscoverConfigs()
	{
		foreach (PluginInfo value in Chainloader.PluginInfos.Values)
		{
			if (!((Object)(object)value.Instance == (Object)null))
			{
				ConfigFile config = value.Instance.Config;
				if (watchedConfigs.Add(config))
				{
					config.SettingChanged += ConfigChanged;
				}
			}
		}
		discoverDue = Time.unscaledTime + 30f;
	}

	private void ConfigChanged(object sender, SettingChangedEventArgs e)
	{
		if (!backupChanging)
		{
			backupDirty = true;
			backupDue = Time.unscaledTime + 2f;
		}
	}

	private void TickConfigPersistence()
	{
		if (!backupReady || backupBlocked || !backupEnabled.Value)
		{
			return;
		}
		try
		{
			if (Time.unscaledTime >= discoverDue)
			{
				DiscoverConfigs();
				backupDirty = true;
			}
			if (restoreNow.Value)
			{
				restoreNow.Value = false;
				RestoreConfigs(force: true);
				backupDirty = true;
				backupDue = 0f;
			}
			if (backupNow.Value)
			{
				backupNow.Value = false;
				backupDirty = true;
				backupDue = 0f;
			}
			if (backupDirty && Time.unscaledTime >= backupDue)
			{
				SaveConfigs();
			}
		}
		catch (Exception ex)
		{
			backupBlocked = true;
			((BaseUnityPlugin)this).Logger.LogError((object)("Config persistence paused; existing backup preserved: " + ex.Message));
		}
	}

	private bool KeepSetting(ConfigEntryBase entry)
	{
		if (entry.ConfigFile == ((BaseUnityPlugin)this).Config && entry.Definition.Section == "Config Persistence")
		{
			return false;
		}
		return !SagaConfigArchive.IsPrivate(entry.Definition.Section, entry.Definition.Key);
	}

	private void RestoreConfigs(bool force)
	{
		backupChanging = true;
		int num = 0;
		try
		{
			foreach (PluginInfo value3 in Chainloader.PluginInfos.Values)
			{
				if ((Object)(object)value3.Instance == (Object)null)
				{
					continue;
				}
				ConfigFile config = value3.Instance.Config;
				bool flag = false;
				foreach (KeyValuePair<ConfigDefinition, ConfigEntryBase> item in config)
				{
					ConfigEntryBase value = item.Value;
					if (!KeepSetting(value))
					{
						continue;
					}
					string key = value3.Metadata.GUID + "\n" + item.Key.Section + "\n" + item.Key.Key;
					if (savedConfigs.TryGetValue(key, out var value2) && SagaConfigArchive.ShouldRestore(force, value2.Version, value3.Metadata.Version.ToString(), object.Equals(value.BoxedValue, value.DefaultValue)) && !(value.GetSerializedValue() == value2.Value))
					{
						try
						{
							value.SetSerializedValue(value2.Value);
							flag = true;
							num++;
						}
						catch (Exception)
						{
							((BaseUnityPlugin)this).Logger.LogWarning((object)("Skipped incompatible saved setting: " + value3.Metadata.GUID + " / " + item.Key.Section + " / " + item.Key.Key));
						}
					}
				}
				if (flag)
				{
					config.Save();
				}
			}
		}
		finally
		{
			backupChanging = false;
		}
		((BaseUnityPlugin)this).Logger.LogInfo((object)("Config persistence restored " + num + " settings."));
	}

	private void SaveConfigs()
	{
		foreach (PluginInfo value2 in Chainloader.PluginInfos.Values)
		{
			if ((Object)(object)value2.Instance == (Object)null)
			{
				continue;
			}
			foreach (KeyValuePair<ConfigDefinition, ConfigEntryBase> item in value2.Instance.Config)
			{
				ConfigEntryBase value = item.Value;
				if (KeepSetting(value))
				{
					SagaSavedSetting sagaSavedSetting = new SagaSavedSetting();
					sagaSavedSetting.Guid = value2.Metadata.GUID;
					sagaSavedSetting.Version = value2.Metadata.Version.ToString();
					sagaSavedSetting.Section = item.Key.Section;
					sagaSavedSetting.Key = item.Key.Key;
					sagaSavedSetting.Value = value.GetSerializedValue();
					SagaSavedSetting sagaSavedSetting2 = sagaSavedSetting;
					savedConfigs[sagaSavedSetting2.Id] = sagaSavedSetting2;
				}
			}
		}
		SagaConfigArchive.Write(backupPath, savedConfigs.Values);
		backupDirty = false;
	}

	private void StopConfigPersistence()
	{
		if (backupReady && !backupBlocked && backupEnabled.Value)
		{
			try
			{
				SaveConfigs();
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Config backup could not save: " + ex.Message));
			}
		}
		foreach (ConfigFile watchedConfig in watchedConfigs)
		{
			watchedConfig.SettingChanged -= ConfigChanged;
		}
		watchedConfigs.Clear();
	}

	private void BeforeHudRender()
	{
		if (ManagementEnabled)
		{
			HideNativeIndicators();
		}
	}

	private void SuppressGraphicTree(Transform root)
	{
		if ((Object)(object)root == (Object)null)
		{
			return;
		}
		Graphic[] componentsInChildren = ((Component)root).GetComponentsInChildren<Graphic>(true);
		foreach (Graphic val in componentsInChildren)
		{
			Transform transform = ((Component)val).transform;
			if ((!((Object)(object)nativeHud.m_statusEffectListRoot != (Object)null) || !transform.IsChildOf((Transform)(object)nativeHud.m_statusEffectListRoot)) && (!((Object)(object)nativeHud.m_gpRoot != (Object)null) || !transform.IsChildOf(((Component)nativeHud.m_gpRoot).transform)) && !nativeGraphics.ContainsKey(val))
			{
				nativeGraphics.Add(val, ((Behaviour)val).enabled);
			}
		}
	}

	private void Awake()
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: Expected O, but got Unknown
		BindConfigPersistence();
		Canvas.willRenderCanvases += new WillRenderCanvases(BeforeHudRender);
		enabledSupport = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "Enabled", true, "Enable shared dragging, headers, minimized-window dock and native HUD suppression. Other Saga addons retain their own enable settings.");
		hideNative = ((BaseUnityPlugin)this).Config.Bind<bool>("Native HUD", "Hide Health And Fork", true, "Suppress vanilla health and food/fork indicators, including while inventory is open.");
	}

	private void HideNativeIndicators()
	{
		Hud instance = Hud.instance;
		if ((Object)(object)instance != (Object)(object)nativeHud)
		{
			RestoreNativeIndicators();
			nativeHud = instance;
		}
		if ((Object)(object)instance == (Object)null || !hideNative.Value)
		{
			RestoreNativeIndicators();
			return;
		}
		if (indicatorAlphas.Count == 0)
		{
			SuppressGraphicTree((Transform)(object)instance.m_healthPanel);
			SuppressGraphicTree((Transform)(object)instance.m_healthBarRoot);
			SuppressGraphicTree((Transform)(object)instance.m_foodBarRoot);
			SuppressGraphicTree((Transform)(object)instance.m_foodBaseBar);
			SuppressGraphicTree(((Object)(object)instance.m_foodIcon == (Object)null) ? null : ((Component)instance.m_foodIcon).transform);
			RememberIndicator(((Object)(object)instance.m_healthBarRoot == (Object)null) ? null : ((Component)instance.m_healthBarRoot).gameObject);
			RememberIndicator(((Object)(object)instance.m_healthText == (Object)null) ? null : ((Component)instance.m_healthText).gameObject);
			RememberIndicator(((Object)(object)instance.m_foodIcon == (Object)null) ? null : ((Component)instance.m_foodIcon).gameObject);
			RememberIndicator(((Object)(object)instance.m_foodText == (Object)null) ? null : ((Component)instance.m_foodText).gameObject);
			RememberIndicator(((Object)(object)instance.m_foodBarRoot == (Object)null) ? null : ((Component)instance.m_foodBarRoot).gameObject);
		}
		foreach (KeyValuePair<CanvasGroup, float> indicatorAlpha in indicatorAlphas)
		{
			if ((Object)(object)indicatorAlpha.Key != (Object)null)
			{
				indicatorAlpha.Key.alpha = 0f;
			}
		}
		foreach (KeyValuePair<Graphic, bool> nativeGraphic in nativeGraphics)
		{
			if ((Object)(object)nativeGraphic.Key != (Object)null)
			{
				((Behaviour)nativeGraphic.Key).enabled = false;
			}
		}
		if ((Object)(object)instance.m_statusEffectTemplate != (Object)null)
		{
			if ((Object)(object)nativeTemplate == (Object)null)
			{
				nativeTemplate = ((Component)instance.m_statusEffectTemplate).gameObject;
				templateWasActive = nativeTemplate.activeSelf;
			}
			nativeTemplate.SetActive(false);
		}
	}

	private void RememberIndicator(GameObject obj)
	{
		if (!((Object)(object)obj == (Object)null))
		{
			CanvasGroup val = obj.GetComponent<CanvasGroup>();
			if ((Object)(object)val == (Object)null)
			{
				val = obj.AddComponent<CanvasGroup>();
				addedIndicators.Add(val);
			}
			if (!indicatorAlphas.ContainsKey(val))
			{
				indicatorAlphas.Add(val, val.alpha);
			}
		}
	}

	private void RestoreNativeIndicators()
	{
		foreach (KeyValuePair<Graphic, bool> nativeGraphic in nativeGraphics)
		{
			if ((Object)(object)nativeGraphic.Key != (Object)null)
			{
				((Behaviour)nativeGraphic.Key).enabled = nativeGraphic.Value;
			}
		}
		nativeGraphics.Clear();
		if ((Object)(object)nativeTemplate != (Object)null)
		{
			nativeTemplate.SetActive(templateWasActive);
		}
		nativeTemplate = null;
		foreach (KeyValuePair<CanvasGroup, float> indicatorAlpha in indicatorAlphas)
		{
			if ((Object)(object)indicatorAlpha.Key != (Object)null)
			{
				indicatorAlpha.Key.alpha = indicatorAlpha.Value;
			}
		}
		foreach (CanvasGroup addedIndicator in addedIndicators)
		{
			if ((Object)(object)addedIndicator != (Object)null)
			{
				Object.Destroy((Object)(object)addedIndicator);
			}
		}
		indicatorAlphas.Clear();
		addedIndicators.Clear();
	}

	public static TMP_FontAsset NativeFont(TMP_FontAsset fallback)
	{
		return fallback;
	}

	public static GUIStyle TextStyle(int size, TextAnchor alignment)
	{
		//IL_0004: Unknown result type (might be due to invalid IL or missing references)
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Expected I4, but got Unknown
		//IL_0084: Unknown result type (might be due to invalid IL or missing references)
		//IL_008a: Expected O, but got Unknown
		//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d7: Expected O, but got Unknown
		int key = size * 16 + alignment;
		if (styles.TryGetValue(key, out var value))
		{
			return value;
		}
		if (!fontResolved)
		{
			fontResolved = true;
			if (Chainloader.PluginInfos.TryGetValue("Azumatt.AzuClock", out var value2))
			{
				FieldInfo field = ((object)value2.Instance).GetType().GetField("Style", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				GUIStyle val = (GUIStyle)((field == null) ? null : /*isinst with value type is only supported in some contexts*/);
				if (val != null)
				{
					headerFont = val.font;
				}
			}
		}
		value = new GUIStyle(GUI.skin.label);
		if ((Object)(object)headerFont != (Object)null)
		{
			value.font = headerFont;
		}
		value.fontSize = 16;
		value.fontStyle = (FontStyle)0;
		value.normal.textColor = Color.white;
		value.alignment = alignment;
		value.padding = new RectOffset(0, 0, 0, 0);
		value.wordWrap = false;
		styles.Add(key, value);
		return value;
	}

	public static GUIStyle ButtonStyle()
	{
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Expected O, but got Unknown
		if (buttonStyle != null)
		{
			return buttonStyle;
		}
		buttonStyle = new GUIStyle(GUI.skin.button);
		buttonStyle.fontSize = 16;
		buttonStyle.fontStyle = (FontStyle)0;
		return buttonStyle;
	}

	internal static void Fill(Rect r, Color c)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0005: 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_000c: 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)
		Color color = GUI.color;
		GUI.color = c;
		GUI.DrawTexture(r, (Texture)(object)Texture2D.whiteTexture);
		GUI.color = color;
	}

	private void RestorePreview()
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)previewRoot != (Object)null)
		{
			previewRoot.localPosition = previousHudPosition;
		}
		if ((Object)(object)previewMap != (Object)null)
		{
			previewMap.SetActive(previousMapActive);
		}
		previewRoot = null;
		previewMap = null;
	}

	private void LateUpdate()
	{
		//IL_0087: Unknown result type (might be due to invalid IL or missing references)
		//IL_007c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0081: Unknown result type (might be due to invalid IL or missing references)
		TickConfigPersistence();
		if (!ManagementEnabled)
		{
			RestorePreview();
			RestoreNativeIndicators();
			return;
		}
		HideNativeIndicators();
		if ((!SagaConfigPreview.Open && !InventoryGui.IsVisible()) || (Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)Hud.instance == (Object)null)
		{
			RestorePreview();
			return;
		}
		Transform transform = Hud.instance.m_rootObject.transform;
		if ((Object)(object)previewRoot != (Object)(object)transform)
		{
			RestorePreview();
			previewRoot = transform;
			previousHudPosition = transform.localPosition;
		}
		transform.localPosition = Vector3.zero;
		if (!((Object)(object)Minimap.instance != (Object)null) || Minimap.IsOpen())
		{
			return;
		}
		GameObject smallRoot = Minimap.instance.m_smallRoot;
		if ((Object)(object)previewMap != (Object)(object)smallRoot)
		{
			if ((Object)(object)previewMap != (Object)null)
			{
				previewMap.SetActive(previousMapActive);
			}
			previewMap = smallRoot;
			previousMapActive = smallRoot.activeSelf;
		}
		smallRoot.SetActive(true);
	}

	private void OnDestroy()
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: Expected O, but got Unknown
		StopConfigPersistence();
		Canvas.willRenderCanvases -= new WillRenderCanvases(BeforeHudRender);
		RestorePreview();
		RestoreNativeIndicators();
	}

	private void OnGUI()
	{
		//IL_012c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0125: 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_0162: Unknown result type (might be due to invalid IL or missing references)
		//IL_016c: Expected O, but got Unknown
		//IL_0167: Unknown result type (might be due to invalid IL or missing references)
		//IL_025b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0260: 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_01fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0272: Unknown result type (might be due to invalid IL or missing references)
		DockVisible = false;
		if (!ManagementEnabled || (Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)Hud.instance == (Object)null || (!SagaConfigPreview.HudVisible(Hud.instance) && !SagaConfigPreview.InventoryHidesHud()) || SagaConfigPreview.MapVisible() || SagaConfigPreview.MenuVisible())
		{
			return;
		}
		GUI.depth = (SagaConfigPreview.Open ? 1000 : (-1000));
		queue.Clear();
		foreach (SagaPanelWindow window in Windows)
		{
			if (window.Available && window.Minimized)
			{
				queue.Add(window);
			}
		}
		if (queue.Count == 0)
		{
			return;
		}
		queue.Sort(delegate(SagaPanelWindow a, SagaPanelWindow b)
		{
			int num3 = a.Order.CompareTo(b.Order);
			return (num3 != 0) ? num3 : string.CompareOrdinal(a.Title, b.Title);
		});
		Rect val = (Rect)((((Rect)(ref HotbarRect)).width > 0f) ? HotbarRect : new Rect((float)Screen.width * 0.25f, (float)(Screen.height - 80), (float)Screen.width * 0.5f, 64f));
		float[] array = new float[queue.Count];
		for (int num = 0; num < queue.Count; num++)
		{
			array[num] = Mathf.Ceil(TextStyle(16, (TextAnchor)3).CalcSize(new GUIContent(queue[num].Title)).x) + 70f;
		}
		SagaDockLayout.Slot[] array2 = SagaDockLayout.Arrange(Screen.width, Screen.height, ((Rect)(ref val)).xMax, ((Rect)(ref val)).y, ((Rect)(ref val)).yMax, array);
		Rect val2 = default(Rect);
		for (int num2 = 0; num2 < queue.Count; num2++)
		{
			((Rect)(ref val2))..ctor(array2[num2].X, array2[num2].Y, array2[num2].Width, 28f);
			if (num2 == 0)
			{
				DockRect = val2;
			}
			else
			{
				DockRect = Rect.MinMaxRect(Mathf.Min(((Rect)(ref DockRect)).xMin, ((Rect)(ref val2)).xMin), Mathf.Min(((Rect)(ref DockRect)).yMin, ((Rect)(ref val2)).yMin), Mathf.Max(((Rect)(ref DockRect)).xMax, ((Rect)(ref val2)).xMax), Mathf.Max(((Rect)(ref DockRect)).yMax, ((Rect)(ref val2)).yMax));
			}
			queue[num2].DrawTab(val2);
		}
		DockVisible = queue.Count > 0;
	}
}
internal static class SagaConfigPreview
{
	private static BaseUnityPlugin manager;

	private static PropertyInfo displaying;

	private static float retry;

	private static int frame = -1;

	private static bool open;

	internal static bool Open
	{
		get
		{
			if (frame == Time.frameCount)
			{
				return open;
			}
			frame = Time.frameCount;
			open = false;
			if ((Object)(object)manager == (Object)null && Time.unscaledTime >= retry)
			{
				retry = Time.unscaledTime + 2f;
				if (Chainloader.PluginInfos.TryGetValue("com.bepis.bepinex.configurationmanager", out var value))
				{
					manager = value.Instance;
					displaying = ((object)manager).GetType().GetProperty("DisplayingWindow", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				}
			}
			if ((Object)(object)manager != (Object)null && displaying != null)
			{
				try
				{
					open = (bool)displaying.GetValue(manager, null);
				}
				catch
				{
					open = false;
				}
			}
			return open;
		}
	}

	internal static bool HudVisible(Hud hud)
	{
		if ((Object)(object)hud != (Object)null)
		{
			if (!Open)
			{
				return hud.IsVisible();
			}
			return true;
		}
		return false;
	}

	internal static bool MenuVisible()
	{
		if (!Open)
		{
			return Menu.IsVisible();
		}
		return false;
	}

	internal static bool MapVisible()
	{
		if (!Open)
		{
			return Minimap.IsOpen();
		}
		return false;
	}

	internal static bool StoreVisible()
	{
		if (!Open)
		{
			return StoreGui.IsVisible();
		}
		return false;
	}

	internal static bool InventoryHidesHud()
	{
		if (!Open)
		{
			return InventoryGui.IsVisible();
		}
		return false;
	}
}
public static class SagaDockLayout
{
	public struct Slot
	{
		public float X;

		public float Y;

		public float Width;

		public Slot(float x, float y, float w)
		{
			X = x;
			Y = y;
			Width = w;
		}
	}

	public static long NextOrder(long clock, IEnumerable<long> existing)
	{
		long num = Math.Max(1L, clock);
		foreach (long item in existing)
		{
			num = Math.Max(num, item + 1);
		}
		return num;
	}

	public static Slot[] Arrange(float screenWidth, float screenHeight, float hotbarRight, float hotbarTop, float hotbarBottom, float[] widths)
	{
		Slot[] array = new Slot[widths.Length];
		if (widths.Length == 0)
		{
			return array;
		}
		float num = 0f;
		foreach (float val in widths)
		{
			num = Math.Max(num, Math.Min(val, screenWidth - 8f));
		}
		bool flag = hotbarRight + 8f + num <= screenWidth - 4f;
		float num2 = (flag ? (hotbarRight + 8f) : Math.Max(4f, screenWidth - num - 4f));
		float num3 = num2;
		float num4 = Math.Max(4f, Math.Min(screenHeight - 32f, flag ? (hotbarBottom - 28f) : (hotbarTop - 32f)));
		for (int j = 0; j < widths.Length; j++)
		{
			float num5 = Math.Max(1f, Math.Min(widths[j], screenWidth - 8f));
			if (num3 + num5 > screenWidth - 4f)
			{
				num3 = num2;
				num4 -= 32f;
			}
			ref Slot reference = ref array[j];
			reference = new Slot(num3, Math.Max(4f, num4), num5);
			num3 += num5 + 5f;
		}
		return array;
	}
}
public sealed class SagaEffectLayout
{
	private readonly ConfigEntry<float> x;

	private readonly ConfigEntry<float> y;

	private readonly ConfigEntry<float> width;

	private readonly ConfigEntry<float> height;

	private readonly ConfigEntry<float> scale;

	private readonly ConfigEntry<bool> inventory;

	public bool Visible
	{
		get
		{
			if (!SagaConfigPreview.Open && InventoryGui.IsVisible())
			{
				return inventory.Value;
			}
			return true;
		}
	}

	public SagaEffectLayout(ConfigFile config, string section)
	{
		//IL_0065: Unknown result type (might be due to invalid IL or missing references)
		//IL_006f: Expected O, but got Unknown
		//IL_009b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a5: Expected O, but got Unknown
		//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00db: Expected O, but got Unknown
		x = config.Bind<float>(section, "X", -1f, "Screen X anchor in pixels; -1 follows its usual target.");
		y = config.Bind<float>(section, "Y", -1f, "Screen Y anchor in pixels; -1 follows its usual target.");
		width = config.Bind<float>(section, "Width", 0f, new ConfigDescription("Visual width; 0 retains native proportions.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2000f), new object[0]));
		height = config.Bind<float>(section, "Height", 0f, new ConfigDescription("Visual height; 0 retains native proportions.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2000f), new object[0]));
		scale = config.Bind<float>(section, "Scale", 1f, new ConfigDescription("Visual scale; existing font asset is retained.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.25f, 3f), new object[0]));
		inventory = config.Bind<bool>(section, "Show In Inventory", true, "Show this effect while inventory is open. F1 preview overrides hiding.");
	}

	public void Anchor(ref float px, ref float py, float originX, float originY)
	{
		if (x.Value >= 0f)
		{
			px += x.Value - originX;
		}
		if (y.Value >= 0f)
		{
			py += y.Value - originY;
		}
	}

	public void ScaleAt(float px, float py, float originalWidth, float originalHeight)
	{
		//IL_0079: Unknown result type (might be due to invalid IL or missing references)
		//IL_0080: Unknown result type (might be due to invalid IL or missing references)
		GUIUtility.ScaleAroundPivot(new Vector2(scale.Value * ((width.Value > 0f) ? (width.Value / Mathf.Max(1f, originalWidth)) : 1f), scale.Value * ((height.Value > 0f) ? (height.Value / Mathf.Max(1f, originalHeight)) : 1f)), new Vector2(px, py));
	}
}
public enum SagaVisibilityTrigger
{
	Always,
	InCombat,
	OutOfCombat
}
public sealed class SagaPanelAppearance
{
	private readonly ConfigEntry<float> width;

	private readonly ConfigEntry<float> height;

	private readonly ConfigEntry<float> x;

	private readonly ConfigEntry<float> y;

	private readonly ConfigEntry<float> scale;

	public bool ForceToolWindow;

	private readonly ConfigEntry<SagaVisibilityTrigger> trigger;

	private readonly ConfigEntry<float> visibilityDelay;

	private readonly ConfigEntry<bool> tool;

	private readonly ConfigEntry<bool> persistInventory;

	private readonly ConfigEntry<Color> background;

	private readonly ConfigEntry<Color> border;

	public bool InventoryVisible
	{
		get
		{
			if (SagaConfigPreview.Open)
			{
				return true;
			}
			if (InventoryGui.IsVisible())
			{
				return persistInventory.Value;
			}
			if (trigger.Value == SagaVisibilityTrigger.Always)
			{
				return true;
			}
			bool flag = (Object)(object)Player.m_localPlayer != (Object)null && (Player.m_localPlayer.IsSensed() || Time.unscaledTime - SagaPanelUI.LastCombatAt <= visibilityDelay.Value);
			if (trigger.Value != SagaVisibilityTrigger.InCombat)
			{
				return !flag;
			}
			return flag;
		}
	}

	public float Scale => scale.Value;

	public bool ToolWindow
	{
		get
		{
			if (SagaPanelUI.ManagementEnabled && !ForceToolWindow)
			{
				return tool.Value;
			}
			return true;
		}
	}

	public float HeaderHeight => (!ToolWindow) ? 31 : 0;

	public Color Border
	{
		get
		{
			//IL_0014: 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)
			if (!ToolWindow)
			{
				return border.Value;
			}
			return Color.clear;
		}
	}

	public Color Header
	{
		get
		{
			//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_003a: Unknown result type (might be due to invalid IL or missing references)
			Color value = border.Value;
			return new Color(value.r * 0.45f, value.g * 0.45f, value.b * 0.45f, value.a);
		}
	}

	public SagaPanelAppearance(ConfigFile config, bool toolDefault, float backgroundAlpha = 1f)
	{
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: Expected O, but got Unknown
		//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d1: Expected O, but got Unknown
		//IL_011d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0127: Expected O, but got Unknown
		//IL_0157: Unknown result type (might be due to invalid IL or missing references)
		//IL_0161: Expected O, but got Unknown
		//IL_019e: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
		trigger = config.Bind<SagaVisibilityTrigger>("Visibility", "Trigger", SagaVisibilityTrigger.Always, "Always, only during combat, or only outside combat. Inventory/F1 reveal it for layout.");
		visibilityDelay = config.Bind<float>("Visibility", "Combat Hide Delay", 5f, new ConfigDescription("Seconds after the latest combat activity before combat visibility ends.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 300f), new object[0]));
		x = config.Bind<float>("Window Appearance", "X", -1f, "Horizontal position in screen pixels from the left. -1 uses the default/saved drag position.");
		y = config.Bind<float>("Window Appearance", "Y", -1f, "Vertical position in screen pixels from the top. -1 uses the default/saved drag position.");
		scale = config.Bind<float>("Window Appearance", "Scale", 1f, new ConfigDescription("Independent layout scale.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.25f, 3f), new object[0]));
		persistInventory = config.Bind<bool>("Window Appearance", "Persist Through Inventory", true, "Keep this panel visible while Tab/inventory is open. Disable to hide it during inventory. F1 preview remains visible; enable this to drag the panel with Tab.");
		width = config.Bind<float>("Window Appearance", "Width", 0f, new ConfigDescription("Window width in screen pixels. 0 uses the existing automatic size. Content-safe minimums and screen bounds apply.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 7680f), new object[0]));
		height = config.Bind<float>("Window Appearance", "Height", 0f, new ConfigDescription("Window height in screen pixels. 0 uses the existing automatic size. Content-safe minimums and screen bounds apply.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 4320f), new object[0]));
		tool = config.Bind<bool>("Window Appearance", "Tool Window", toolDefault, "Hide the window header and border. Content remains visible; drag while inventory is open. Turn this off to restore the header controls.");
		background = config.Bind<Color>("Window Appearance", "Background Color", new Color(0.035f, 0.04f, 0.035f, backgroundAlpha), "Panel background color. Alpha multiplies the existing opacity; alpha 0 gives a transparent background.");
		border = config.Bind<Color>("Window Appearance", "Border Color", new Color(0.38f, 0.26f, 0.13f, 1f), "Panel border and header accent color. Does not recolor health, stamina, rarity, or damage indicators.");
	}

	public Rect Position(Rect rect)
	{
		//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
		if (x.Value >= 0f)
		{
			((Rect)(ref rect)).x = x.Value;
		}
		if (y.Value >= 0f)
		{
			((Rect)(ref rect)).y = y.Value;
		}
		((Rect)(ref rect)).x = Mathf.Clamp(((Rect)(ref rect)).x, 0f, Mathf.Max(0f, (float)Screen.width - ((Rect)(ref rect)).width));
		((Rect)(ref rect)).y = Mathf.Clamp(((Rect)(ref rect)).y, 0f, Mathf.Max(0f, (float)Screen.height - ((Rect)(ref rect)).height));
		return rect;
	}

	public void SavePosition(Vector2 value)
	{
		x.Value = value.x;
		y.Value = value.y;
	}

	public void ResetPosition()
	{
		ConfigEntry<float> obj = x;
		float value = (y.Value = -1f);
		obj.Value = value;
	}

	public Color Background(float opacity)
	{
		//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_001b: Unknown result type (might be due to invalid IL or missing references)
		Color value = background.Value;
		value.a *= opacity;
		return value;
	}

	public void Draw(Rect rect, float opacity, string title)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0005: 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_0008: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: 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_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_007e: 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_00d6: 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_011c: Unknown result type (might be due to invalid IL or missing references)
		//IL_012b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0161: Unknown result type (might be due to invalid IL or missing references)
		Color color = GUI.color;
		try
		{
			GUI.color = Background(opacity);
			GUI.DrawTexture(rect, (Texture)(object)Texture2D.whiteTexture);
			if (!ToolWindow)
			{
				GUI.color = Border;
				GUI.DrawTexture(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, ((Rect)(ref rect)).width, 1f), (Texture)(object)Texture2D.whiteTexture);
				GUI.DrawTexture(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).yMax - 1f, ((Rect)(ref rect)).width, 1f), (Texture)(object)Texture2D.whiteTexture);
				GUI.DrawTexture(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, 1f, ((Rect)(ref rect)).height), (Texture)(object)Texture2D.whiteTexture);
				GUI.DrawTexture(new Rect(((Rect)(ref rect)).xMax - 1f, ((Rect)(ref rect)).y, 1f, ((Rect)(ref rect)).height), (Texture)(object)Texture2D.whiteTexture);
				GUI.color = Header;
				GUI.DrawTexture(new Rect(((Rect)(ref rect)).x + 1f, ((Rect)(ref rect)).y + 1f, ((Rect)(ref rect)).width - 2f, 29f), (Texture)(object)Texture2D.whiteTexture);
				GUI.color = Color.white;
				GUI.Label(new Rect(((Rect)(ref rect)).x + 8f, ((Rect)(ref rect)).y + 3f, ((Rect)(ref rect)).width - 16f, 24f), title, SagaPanelUI.TextStyle(16, (TextAnchor)3));
			}
		}
		finally
		{
			GUI.color = color;
		}
	}

	public Vector2 Size(Vector2 automatic, float minWidth, float minHeight)
	{
		//IL_0086: Unknown result type (might be due to invalid IL or missing references)
		return new Vector2(Mathf.Min((float)Screen.width, Mathf.Max(minWidth, ((width.Value > 0f) ? width.Value : automatic.x) * scale.Value)), Mathf.Min((float)Screen.height, Mathf.Max(minHeight, ((height.Value > 0f) ? height.Value : automatic.y) * scale.Value)));
	}
}
public sealed class SagaPanelWindow
{
	private readonly ConfigEntry<float> x;

	private readonly ConfigEntry<float> y;

	private readonly ConfigEntry<long> order;

	public readonly string Title;

	public readonly SagaPanelAppearance Appearance;

	public float MinimumWidth = 180f;

	public float MinimumHeight = 60f;

	private Vector2 sizedSource;

	private Vector2 sizedResult;

	public bool AllowDrag = true;

	private Rect last;

	private float reserved;

	private bool dragging;

	private Vector2 offset;

	private Vector2 position;

	private int control;

	private GameObject blocker;

	private RectTransform blockRect;

	private readonly Dictionary<TMP_Text, float> textSizes = new Dictionary<TMP_Text, float>();

	private readonly Dictionary<CanvasGroup, float> alphas = new Dictionary<CanvasGroup, float>();

	private readonly List<CanvasGroup> addedGroups = new List<CanvasGroup>();

	public bool Available { get; private set; }

	public bool Minimized
	{
		get
		{
			if (!ToolWindow)
			{
				return order.Value > 0;
			}
			return false;
		}
	}

	public bool ToolWindow => Appearance.ToolWindow;

	public float HeaderHeight => Appearance.HeaderHeight;

	public long Order => order.Value;

	public Rect Sized(Rect rect)
	{
		//IL_0002: 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_002a: 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_0048: Unknown result type (might be due to invalid IL or missing references)
		//IL_004d: 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_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		if (((Rect)(ref rect)).size != sizedResult)
		{
			sizedSource = ((Rect)(ref rect)).size;
		}
		((Rect)(ref rect)).size = Appearance.Size(sizedSource, MinimumWidth, MinimumHeight);
		sizedResult = ((Rect)(ref rect)).size;
		return rect;
	}

	public void MatchText(TMP_Text text)
	{
		if (!((Object)(object)text == (Object)null) && !textSizes.ContainsKey(text))
		{
			textSizes.Add(text, text.fontSize);
			text.fontSize = 16f;
		}
	}

	public SagaPanelWindow(ConfigFile config, string name)
	{
		Appearance = new SagaPanelAppearance(config, toolDefault: true);
		Title = name.Replace("Saga", "").Replace("Pro", "").Replace("Minimap", "Map");
		x = config.Bind<float>("Window", "Position X", -1f, "Saved horizontal position (0 to 1); -1 restores default.");
		y = config.Bind<float>("Window", "Position Y", -1f, "Saved vertical position (0 to 1). Drag anywhere on the panel while inventory is open.");
		order = config.Bind<long>("Window", "Minimized Order", 0L, "0 = open; positive values persist FIFO minimization order.");
		SagaPanelUI.Windows.Add(this);
	}

	public void Open()
	{
		order.Value = 0L;
		RestoreContent();
	}

	private void Minimize()
	{
		List<long> list = new List<long>();
		foreach (SagaPanelWindow window in SagaPanelUI.Windows)
		{
			list.Add(window.Order);
		}
		order.Value = SagaDockLayout.NextOrder(DateTime.UtcNow.Ticks, list);
		StopDrag();
	}

	public void ResetPosition()
	{
		StopDrag();
		ConfigEntry<float> obj = x;
		float value = (y.Value = -1f);
		obj.Value = value;
		Appearance.ResetPosition();
	}

	public Rect Resolve(Rect rect)
	{
		//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_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_010e: 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_00a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ac: 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)
		rect = Sized(rect);
		if (dragging)
		{
			((Rect)(ref rect)).position = position;
		}
		else if (x.Value >= 0f && y.Value >= 0f)
		{
			((Rect)(ref rect)).position = new Vector2(x.Value * Mathf.Max(0f, (float)Screen.width - ((Rect)(ref rect)).width), y.Value * Mathf.Max(0f, (float)Screen.height - ((Rect)(ref rect)).height));
		}
		if (!dragging)
		{
			rect = Appearance.Position(rect);
		}
		((Rect)(ref rect)).x = Mathf.Clamp(((Rect)(ref rect)).x, 0f, Mathf.Max(0f, (float)Screen.width - ((Rect)(ref rect)).width));
		((Rect)(ref rect)).y = Mathf.Clamp(((Rect)(ref rect)).y, 0f, Mathf.Max(0f, (float)Screen.height - ((Rect)(ref rect)).height));
		return rect;
	}

	public Rect Place(Rect rect, float reservedRight)
	{
		//IL_0001: 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)
		return Place(rect, reservedRight, 31f);
	}

	public Rect Place(Rect rect, float reservedRight, float unusedHeaderHeight)
	{
		//IL_001b: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: 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_0032: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: 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_0048: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ae: 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_00fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_011e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0192: Unknown result type (might be due to invalid IL or missing references)
		//IL_0198: Invalid comparison between Unknown and I4
		//IL_01fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_0205: Unknown result type (might be due to invalid IL or missing references)
		//IL_019c: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bd: 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_01c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_0130: 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_01f5: Invalid comparison between Unknown and I4
		//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e6: Invalid comparison between Unknown and I4
		//IL_0160: Unknown result type (might be due to invalid IL or missing references)
		//IL_0167: Unknown result type (might be due to invalid IL or missing references)
		//IL_016c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0171: Unknown result type (might be due to invalid IL or missing references)
		//IL_0179: Unknown result type (might be due to invalid IL or missing references)
		//IL_017e: Unknown result type (might be due to invalid IL or missing references)
		if (!SagaPanelUI.ManagementEnabled || !Appearance.InventoryVisible)
		{
			Hide();
			return Resolve(rect);
		}
		Available = true;
		reserved = reservedRight;
		rect = Resolve(rect);
		last = rect;
		if (Minimized)
		{
			return rect;
		}
		bool flag = InventoryGui.IsVisible() && !SagaConfigPreview.Open && AllowDrag;
		Event current = Event.current;
		int controlID = GUIUtility.GetControlID(Title.GetHashCode(), (FocusType)2);
		int num;
		if (!ToolWindow)
		{
			Rect val = new Rect(((Rect)(ref rect)).xMax - reservedRight - 34f, ((Rect)(ref rect)).y, reservedRight + 34f, 31f);
			num = (((Rect)(ref val)).Contains(current.mousePosition) ? 1 : 0);
		}
		else
		{
			num = 0;
		}
		bool flag2 = (byte)num != 0;
		bool flag3 = (Title == "Damage" || Title == "Skills") && current.mousePosition.x > ((Rect)(ref rect)).xMax - 24f && current.mousePosition.y > ((Rect)(ref rect)).y + HeaderHeight;
		if (flag && (int)current.type == 0 && current.button == 0 && ((Rect)(ref rect)).Contains(current.mousePosition) && !flag2 && !flag3 && GUIUtility.hotControl == 0)
		{
			dragging = true;
			control = controlID;
			GUIUtility.hotControl = controlID;
			offset = current.mousePosition - ((Rect)(ref rect)).position;
			position = ((Rect)(ref rect)).position;
			current.Use();
		}
		if (dragging && (int)current.type == 3)
		{
			position = current.mousePosition - offset;
			rect = Resolve(rect);
			position = ((Rect)(ref rect)).position;
			last = rect;
			current.Use();
		}
		if (dragging && (!flag || (int)current.type == 1))
		{
			StopDrag();
			if ((int)current.type == 1)
			{
				current.Use();
			}
		}
		SetBlocker(rect, flag);
		return rect;
	}

	private void StopDrag()
	{
		//IL_0085: Unknown result type (might be due to invalid IL or missing references)
		if (dragging)
		{
			x.Value = Mathf.Clamp01(((Rect)(ref last)).x / Mathf.Max(1f, (float)Screen.width - ((Rect)(ref last)).width));
			y.Value = Mathf.Clamp01(((Rect)(ref last)).y / Mathf.Max(1f, (float)Screen.height - ((Rect)(ref last)).height));
			Appearance.SavePosition(((Rect)(ref last)).position);
			dragging = false;
			if (GUIUtility.hotControl == control)
			{
				GUIUtility.hotControl = 0;
			}
		}
	}

	public void DrawHeader()
	{
		//IL_0137: 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_0023: 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_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_0082: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_0119: Unknown result type (might be due to invalid IL or missing references)
		if (!Appearance.InventoryVisible || Minimized || ToolWindow)
		{
			return;
		}
		Color color = GUI.color;
		GUI.color = Color.white;
		try
		{
			SagaPanelUI.Fill(new Rect(((Rect)(ref last)).x + 2f, ((Rect)(ref last)).y + 2f, Mathf.Max(0f, ((Rect)(ref last)).width - reserved - 36f), 27f), Appearance.Header);
			GUI.Label(new Rect(((Rect)(ref last)).x + 10f, ((Rect)(ref last)).y + 3f, Mathf.Max(0f, ((Rect)(ref last)).width - reserved - 48f), 24f), Title, SagaPanelUI.TextStyle(16, (TextAnchor)3));
			if (GUI.Button(new Rect(((Rect)(ref last)).xMax - 29f, ((Rect)(ref last)).y + 5f, 24f, 21f), "−", SagaPanelUI.ButtonStyle()))
			{
				Minimize();
			}
		}
		finally
		{
			GUI.color = color;
		}
	}

	internal void DrawTab(Rect rect)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0005: 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_0101: 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_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_0065: 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_00d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
		Color color = GUI.color;
		GUI.color = Color.white;
		try
		{
			SagaPanelUI.Fill(rect, Appearance.Border);
			SagaPanelUI.Fill(new Rect(((Rect)(ref rect)).x + 1f, ((Rect)(ref rect)).y + 1f, ((Rect)(ref rect)).width - 2f, ((Rect)(ref rect)).height - 2f), Appearance.Background(0.95f));
			GUI.Label(new Rect(((Rect)(ref rect)).x + 8f, ((Rect)(ref rect)).y + 2f, ((Rect)(ref rect)).width - 64f, 24f), Title, SagaPanelUI.TextStyle(16, (TextAnchor)3));
			if (GUI.Button(new Rect(((Rect)(ref rect)).xMax - 52f, ((Rect)(ref rect)).y + 4f, 47f, 20f), "Open", SagaPanelUI.ButtonStyle()))
			{
				Open();
			}
			SetBlocker(rect, InventoryGui.IsVisible());
		}
		finally
		{
			GUI.color = color;
		}
	}

	public void ContentVisible(GameObject obj, bool visible)
	{
		if ((Object)(object)obj == (Object)null)
		{
			return;
		}
		visible = visible && Appearance.InventoryVisible;
		CanvasGroup val = obj.GetComponent<CanvasGroup>();
		if ((Object)(object)val == (Object)null)
		{
			if (visible)
			{
				return;
			}
			val = obj.AddComponent<CanvasGroup>();
			addedGroups.Add(val);
		}
		if (!alphas.ContainsKey(val))
		{
			alphas.Add(val, val.alpha);
		}
		val.alpha = (visible ? alphas[val] : 0f);
	}

	public void RestoreContent()
	{
		foreach (KeyValuePair<CanvasGroup, float> alpha in alphas)
		{
			if ((Object)(object)alpha.Key != (Object)null)
			{
				alpha.Key.alpha = alpha.Value;
			}
		}
	}

	private void SetBlocker(Rect rect, bool active)
	{
		//IL_013e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0150: 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_0056: Expected O, but got Unknown
		//IL_009b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a1: Expected O, but got Unknown
		//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e5: 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_00ed: 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_00f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0104: Unknown result type (might be due to invalid IL or missing references)
		if (active && (Object)(object)blocker == (Object)null)
		{
			blocker = new GameObject("Panel click shield", new Type[3]
			{
				typeof(RectTransform),
				typeof(Canvas),
				typeof(GraphicRaycaster)
			});
			Canvas component = blocker.GetComponent<Canvas>();
			component.renderMode = (RenderMode)0;
			component.sortingOrder = 32760;
			GameObject val = new GameObject("Area", new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			blockRect = val.GetComponent<RectTransform>();
			((Transform)blockRect).SetParent(blocker.transform, false);
			RectTransform obj = blockRect;
			RectTransform obj2 = blockRect;
			Vector2 val2 = (blockRect.pivot = new Vector2(0f, 1f));
			Vector2 anchorMin = (obj2.anchorMax = val2);
			obj.anchorMin = anchorMin;
			((Graphic)val.GetComponent<Image>()).color = Color.clear;
		}
		if (!((Object)(object)blocker == (Object)null))
		{
			blocker.SetActive(active);
			blockRect.anchoredPosition = new Vector2(((Rect)(ref rect)).x, 0f - ((Rect)(ref rect)).y);
			blockRect.sizeDelta = ((Rect)(ref rect)).size;
		}
	}

	public void Hide()
	{
		Available = false;
		StopDrag();
		if ((Object)(object)blocker != (Object)null)
		{
			blocker.SetActive(false);
		}
	}

	public void Dispose()
	{
		Hide();
		RestoreContent();
		foreach (KeyValuePair<TMP_Text, float> textSize in textSizes)
		{
			if ((Object)(object)textSize.Key != (Object)null)
			{
				textSize.Key.fontSize = textSize.Value;
			}
		}
		foreach (CanvasGroup addedGroup in addedGroups)
		{
			if ((Object)(object)addedGroup != (Object)null)
			{
				Object.Destroy((Object)(object)addedGroup);
			}
		}
		SagaPanelUI.Windows.Remove(this);
		if ((Object)(object)blocker != (Object)null)
		{
			Object.Destroy((Object)(object)blocker);
		}
	}
}

BepInEx/plugins/MMC-QuickMultiplayer/MMCQuickMultiplayer.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[BepInPlugin("local.mmc.quickmultiplayer", "Saga Quick Multiplayer", "3.0.0")]
public sealed class MMCQuickMultiplayer : BaseUnityPlugin
{
	private const string Title = "Start Multiplayer Game";

	private static MMCQuickMultiplayer instance;

	private Harmony harmony;

	private ConfigEntry<bool> enabledAddon;

	private FejdStartup knownMenu;

	private Button button;

	private TMP_Text label;

	private FejdStartup startup;

	private Button[] originalButtons;

	private readonly Dictionary<RectTransform, Vector2> moved = new Dictionary<RectTransform, Vector2>();

	private static readonly FieldInfo menuButtons = AccessTools.Field(typeof(FejdStartup), "m_menuButtons");

	private static readonly FieldInfo favoritesField = AccessTools.Field(typeof(ServerListGui), "m_favoriteServersList");

	private static readonly MethodInfo locations = AccessTools.Method(typeof(ServerListGui), "GetServerListLocations", (Type[])null, (Type[])null);

	private static readonly MethodInfo proceed = AccessTools.Method(typeof(FejdStartup), "ProceedJoinRequest", (Type[])null, (Type[])null);

	private void Awake()
	{
		//IL_0044: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: Expected O, but got Unknown
		//IL_007b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0088: Expected O, but got Unknown
		instance = this;
		enabledAddon = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "Enabled", true, "Enable the Start Multiplayer Game shortcut.");
		enabledAddon.SettingChanged += delegate
		{
			try
			{
				((MonoBehaviour)this).StopAllCoroutines();
				if (!enabledAddon.Value)
				{
					Cleanup();
				}
				else if ((Object)(object)knownMenu != (Object)null)
				{
					Build(knownMenu);
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not refresh multiplayer shortcut: " + ex.GetType().Name));
				Cleanup();
			}
		};
		harmony = new Harmony("local.mmc.quickmultiplayer");
		harmony.Patch((MethodBase)AccessTools.Method(typeof(FejdStartup), "Start", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(MMCQuickMultiplayer), "MenuReady", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
	}

	private static void MenuReady(FejdStartup __instance)
	{
		if ((Object)(object)instance == (Object)null)
		{
			return;
		}
		instance.knownMenu = __instance;
		if (!instance.enabledAddon.Value)
		{
			return;
		}
		try
		{
			instance.Build(__instance);
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)instance).Logger.LogError((object)("Could not add multiplayer shortcut: " + ex.GetType().Name));
			instance.Cleanup();
		}
	}

	private void Build(FejdStartup menu)
	{
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_002d: Expected O, but got Unknown
		//IL_00db: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e5: Expected O, but got Unknown
		//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0101: Expected O, but got Unknown
		//IL_03ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_03ef: Unknown result type (might be due to invalid IL or missing references)
		//IL_03ff: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ff: Expected O, but got Unknown
		//IL_0233: Unknown result type (might be due to invalid IL or missing references)
		//IL_023f: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_02aa: Expected O, but got Unknown
		//IL_0363: Unknown result type (might be due to invalid IL or missing references)
		//IL_036f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0374: Unknown result type (might be due to invalid IL or missing references)
		//IL_02de: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_0306: Unknown result type (might be due to invalid IL or missing references)
		//IL_0313: Unknown result type (might be due to invalid IL or missing references)
		//IL_031f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0324: Unknown result type (might be due to invalid IL or missing references)
		Cleanup();
		startup = menu;
		GameObject val = (GameObject)AccessTools.Field(typeof(FejdStartup), "m_menuList").GetValue(menu);
		Button val2 = null;
		Button[] componentsInChildren = val.GetComponentsInChildren<Button>(true);
		foreach (Button val3 in componentsInChildren)
		{
			for (int j = 0; j < ((UnityEventBase)val3.onClick).GetPersistentEventCount(); j++)
			{
				if (((UnityEventBase)val3.onClick).GetPersistentMethodName(j) == "OnStartGame")
				{
					val2 = val3;
					break;
				}
			}
			if ((Object)(object)val2 != (Object)null)
			{
				break;
			}
		}
		if ((Object)(object)val2 == (Object)null)
		{
			throw new InvalidOperationException("Native Start Game button unavailable");
		}
		Transform transform = ((Component)val2).transform;
		RectTransform val4 = (RectTransform)(object)((transform is RectTransform) ? transform : null);
		button = Object.Instantiate<Button>(val2, ((Component)val2).transform.parent, false);
		((Object)button).name = "Start Multiplayer Game";
		button.onClick = new ButtonClickedEvent();
		((UnityEvent)button.onClick).AddListener(new UnityAction(JoinFirstFavorite));
		((Component)button).transform.SetSiblingIndex(((Component)val2).transform.GetSiblingIndex() + 1);
		label = ((Component)button).GetComponentInChildren<TMP_Text>(true);
		if ((Object)(object)label != (Object)null)
		{
			label.text = "Start Multiplayer Game";
			label.enableAutoSizing = true;
			label.fontSizeMin = 16f;
			label.fontSizeMax = label.fontSize;
			label.textWrappingMode = (TextWrappingModes)0;
		}
		((Component)button).gameObject.SetActive(true);
		if ((Object)(object)((Component)((Component)val2).transform.parent).GetComponent<LayoutGroup>() == (Object)null && (Object)(object)val4 != (Object)null)
		{
			Rect rect = val4.rect;
			float num = ((Rect)(ref rect)).height + 8f;
			foreach (Transform item in ((Component)val2).transform.parent)
			{
				Transform val5 = item;
				RectTransform val6 = (RectTransform)(object)((val5 is RectTransform) ? val5 : null);
				if (!((Object)(object)val6 == (Object)null) && !((Object)(object)val6 == (Object)(object)val4) && !((Object)(object)val6 == (Object)(object)((Component)button).transform))
				{
					float num2 = val4.anchoredPosition.y - val6.anchoredPosition.y;
					if (num2 > 1f && num2 < num * 2f)
					{
						num = num2;
					}
				}
			}
			foreach (Transform item2 in ((Component)val2).transform.parent)
			{
				Transform val7 = item2;
				RectTransform val8 = (RectTransform)(object)((val7 is RectTransform) ? val7 : null);
				if (!((Object)(object)val8 == (Object)null) && !((Object)(object)val8 == (Object)(object)val4) && !((Object)(object)val8 == (Object)(object)((Component)button).transform) && !(val8.anchoredPosition.y > val4.anchoredPosition.y - 1f))
				{
					moved.Add(val8, val8.anchoredPosition);
					val8.anchoredPosition -= new Vector2(0f, num);
				}
			}
			Transform transform2 = ((Component)button).transform;
			((RectTransform)((transform2 is RectTransform) ? transform2 : null)).anchoredPosition = val4.anchoredPosition - new Vector2(0f, num);
		}
		originalButtons = menuButtons.GetValue(menu) as Button[];
		if (originalButtons != null)
		{
			List<Button> list = new List<Button>(originalButtons);
			int num3 = list.IndexOf(val2);
			list.Insert((num3 < 0) ? list.Count : (num3 + 1), button);
			menuButtons.SetValue(menu, list.ToArray());
		}
		Navigation navigation = ((Selectable)button).navigation;
		((Navigation)(ref navigation)).mode = (Mode)3;
		((Selectable)button).navigation = navigation;
	}

	private void JoinFirstFavorite()
	{
		//IL_0075: Unknown result type (might be due to invalid IL or missing references)
		//IL_007b: Expected O, but got Unknown
		//IL_009e: 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_00d8: Unknown result type (might be due to invalid IL or missing references)
		if (!enabledAddon.Value || (Object)(object)startup == (Object)null)
		{
			return;
		}
		LocalServerList val = null;
		try
		{
			ServerListGui componentInChildren = ((Component)startup).GetComponentInChildren<ServerListGui>(true);
			LocalServerList val2 = (LocalServerList)(((Object)(object)componentInChildren == (Object)null) ? null : /*isinst with value type is only supported in some contexts*/);
			if (val2 == null)
			{
				FileLocation[] array = (FileLocation[])locations.Invoke(null, new object[1] { "favorite" });
				val = new LocalServerList("$menu_favorite", array);
				val2 = val;
			}
			if (val2.Count == 0)
			{
				((MonoBehaviour)this).StartCoroutine(Notice("No favorites — add a server first"));
				return;
			}
			ServerJoinData val3 = val2[0];
			if (!((ServerJoinData)(ref val3)).IsValid)
			{
				((MonoBehaviour)this).StartCoroutine(Notice("First favorite is unavailable"));
				return;
			}
			proceed.Invoke(startup, new object[1] { val3 });
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)("Multiplayer shortcut could not start: " + ex.GetType().Name));
			((MonoBehaviour)this).StartCoroutine(Notice("Could not open first favorite"));
		}
		finally
		{
			if (val != null)
			{
				val.Dispose();
			}
		}
	}

	private IEnumerator Notice(string message)
	{
		if ((Object)(object)label != (Object)null)
		{
			label.text = message;
		}
		yield return (object)new WaitForSecondsRealtime(4f);
		if ((Object)(object)label != (Object)null)
		{
			label.text = "Start Multiplayer Game";
		}
	}

	private void Cleanup()
	{
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)startup != (Object)null && originalButtons != null)
		{
			menuButtons.SetValue(startup, originalButtons);
		}
		foreach (KeyValuePair<RectTransform, Vector2> item in moved)
		{
			if ((Object)(object)item.Key != (Object)null)
			{
				item.Key.anchoredPosition = item.Value;
			}
		}
		moved.Clear();
		if ((Object)(object)button != (Object)null)
		{
			Object.Destroy((Object)(object)((Component)button).gameObject);
		}
		button = null;
		label = null;
		startup = null;
		originalButtons = null;
	}

	private void OnDestroy()
	{
		((MonoBehaviour)this).StopAllCoroutines();
		Cleanup();
		if (harmony != null)
		{
			harmony.UnpatchSelf();
		}
		instance = null;
	}
}

BepInEx/plugins/MMC-RealClock/MMCRealClock.dll

Decompiled a week ago
using System;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using UnityEngine;

[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: CompilationRelaxations(8)]
[assembly: AssemblyVersion("0.0.0.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInPlugin("local.mmc.realclock", "Saga Real Clock", "3.0.0")]
public sealed class MMCRealClock : BaseUnityPlugin
{
	public static Rect ScreenRect;

	public static bool ScreenVisible;

	private ConfigEntry<int> fontSize;

	private ConfigEntry<int> rightMargin;

	private ConfigEntry<int> bottomMargin;

	private ConfigEntry<bool> hideInMenus;

	private Font font;

	private bool ownsFont;

	private bool foundGameFont;

	private float nextFontCheck;

	private GUIStyle style;

	private readonly GUIContent content = new GUIContent();

	private long lastMinute = -1L;

	private bool visible = true;

	private ConfigEntry<bool> enabledClock;

	private SagaPanelAppearance appearance;

	private void Awake()
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: Expected O, but got Unknown
		//IL_005f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0069: Expected O, but got Unknown
		//IL_0097: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a1: Expected O, but got Unknown
		//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d9: Expected O, but got Unknown
		appearance = new SagaPanelAppearance(((BaseUnityPlugin)this).Config, true, 0f);
		enabledClock = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "Enabled", true, "Enable the real-world clock. The Home key remains a temporary visibility toggle.");
		fontSize = ((BaseUnityPlugin)this).Config.Bind<int>("Display", "Font Size", 32, new ConfigDescription("Clock font size.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(12, 72), new object[0]));
		rightMargin = ((BaseUnityPlugin)this).Config.Bind<int>("Display", "Right Margin", 28, new ConfigDescription("Distance from the right screen edge in pixels.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 400), new object[0]));
		bottomMargin = ((BaseUnityPlugin)this).Config.Bind<int>("Display", "Bottom Margin", 24, new ConfigDescription("Distance from the bottom screen edge in pixels.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 400), new object[0]));
		hideInMenus = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "Hide In Menus", true, "Hide with the full map, inventory, store and pause menu.");
		font = Font.CreateDynamicFontFromOSFont(new string[2] { "Segoe UI", "Arial" }, fontSize.Value);
		ownsFont = true;
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Bottom-right local clock enabled: DDMMMYYYY hh:mm AM/PM, uppercase English month.");
	}

	private void Update()
	{
		if (Input.GetKeyDown((KeyCode)278))
		{
			visible = !visible;
		}
	}

	private void OnGUI()
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Invalid comparison between Unknown and I4
		//IL_0143: Unknown result type (might be due to invalid IL or missing references)
		//IL_014d: Expected O, but got Unknown
		//IL_0198: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a2: Expected O, but got Unknown
		//IL_020a: Unknown result type (might be due to invalid IL or missing references)
		//IL_020f: Unknown result type (might be due to invalid IL or missing references)
		//IL_029b: 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_0322: Unknown result type (might be due to invalid IL or missing references)
		//IL_0324: Unknown result type (might be due to invalid IL or missing references)
		//IL_0329: Unknown result type (might be due to invalid IL or missing references)
		//IL_032b: Unknown result type (might be due to invalid IL or missing references)
		//IL_032d: Unknown result type (might be due to invalid IL or missing references)
		//IL_033e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0381: Unknown result type (might be due to invalid IL or missing references)
		//IL_0386: Unknown result type (might be due to invalid IL or missing references)
		//IL_0388: Unknown result type (might be due to invalid IL or missing references)
		//IL_039d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0420: Unknown result type (might be due to invalid IL or missing references)
		//IL_042a: Unknown result type (might be due to invalid IL or missing references)
		//IL_043d: Unknown result type (might be due to invalid IL or missing references)
		//IL_03d5: Unknown result type (might be due to invalid IL or missing references)
		if ((int)Event.current.type != 7)
		{
			return;
		}
		ScreenVisible = false;
		if (!enabledClock.Value || !appearance.InventoryVisible || !visible || (Object)(object)Player.m_localPlayer == (Object)null || (!SagaConfigPreview.Open && hideInMenus.Value && (SagaConfigPreview.MapVisible() || SagaConfigPreview.StoreVisible() || SagaConfigPreview.MenuVisible())))
		{
			return;
		}
		if (!foundGameFont && Time.unscaledTime >= nextFontCheck)
		{
			nextFontCheck = Time.unscaledTime + 2f;
			Font[] array = Resources.FindObjectsOfTypeAll<Font>();
			foreach (Font val in array)
			{
				if (!(((Object)val).name != "AveriaSerifLibre-Bold"))
				{
					if (ownsFont && (Object)(object)font != (Object)null)
					{
						Object.Destroy((Object)(object)font);
					}
					font = val;
					ownsFont = false;
					foundGameFont = true;
					if (style != null)
					{
						style.font = font;
					}
					((BaseUnityPlugin)this).Logger.LogInfo((object)"Using Valheim Averia Serif Libre Bold font.");
					break;
				}
			}
		}
		if (style == null)
		{
			style = new GUIStyle(GUI.skin.label);
			style.font = font;
			style.fontStyle = (FontStyle)1;
			style.alignment = (TextAnchor)5;
			style.richText = false;
			style.wordWrap = false;
			style.padding = new RectOffset(0, 0, 0, 0);
		}
		style.fontSize = fontSize.Value;
		DateTime now = DateTime.Now;
		long num = now.Ticks / 600000000;
		if (num != lastMinute)
		{
			content.text = now.ToString("ddMMMyyyy hh:mm tt", CultureInfo.InvariantCulture).ToUpperInvariant();
			lastMinute = num;
		}
		Vector2 val2 = style.CalcSize(content);
		Rect val3 = default(Rect);
		((Rect)(ref val3))..ctor(Mathf.Max(2f, (float)Screen.width - val2.x - (float)rightMargin.Value), Mathf.Max(2f, (float)Screen.height - val2.y - (float)bottomMargin.Value), val2.x + 1f, val2.y + 1f);
		Vector2 val4 = appearance.Size(new Vector2(((Rect)(ref val3)).width, ((Rect)(ref val3)).height + appearance.HeaderHeight), 100f, 24f + appearance.HeaderHeight);
		((Rect)(ref val3))..ctor(Mathf.Max(0f, (float)Screen.width - val4.x - (float)rightMargin.Value), Mathf.Max(0f, (float)Screen.height - val4.y - (float)bottomMargin.Value), val4.x, val4.y);
		val3 = (ScreenRect = appearance.Position(val3));
		ScreenVisible = true;
		appearance.Draw(val3, 0.6f, "Clock");
		((Rect)(ref val3)).y = ((Rect)(ref val3)).y + appearance.HeaderHeight;
		((Rect)(ref val3)).height = ((Rect)(ref val3)).height - appearance.HeaderHeight;
		Color color = GUI.color;
		GUI.color = Color.white;
		style.normal.textColor = Color.black;
		for (int j = -1; j <= 1; j += 2)
		{
			for (int k = -1; k <= 1; k += 2)
			{
				GUI.Label(new Rect(((Rect)(ref val3)).x + (float)j, ((Rect)(ref val3)).y + (float)k, ((Rect)(ref val3)).width, ((Rect)(ref val3)).height), content, style);
			}
		}
		style.normal.textColor = new Color(1f, 93f / 145f, 0f, 1f);
		GUI.Label(val3, content, style);
		GUI.color = color;
	}

	private void OnDestroy()
	{
		ScreenVisible = false;
		if (ownsFont && (Object)(object)font != (Object)null)
		{
			Object.Destroy((Object)(object)font);
		}
	}
}
internal static class SagaConfigPreview
{
	private static BaseUnityPlugin manager;

	private static PropertyInfo displaying;

	private static float retry;

	private static int frame = -1;

	private static bool open;

	internal static bool Open
	{
		get
		{
			if (frame == Time.frameCount)
			{
				return open;
			}
			frame = Time.frameCount;
			open = false;
			if ((Object)(object)manager == (Object)null && Time.unscaledTime >= retry)
			{
				retry = Time.unscaledTime + 2f;
				if (Chainloader.PluginInfos.TryGetValue("com.bepis.bepinex.configurationmanager", out var value))
				{
					manager = value.Instance;
					displaying = ((object)manager).GetType().GetProperty("DisplayingWindow", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				}
			}
			if ((Object)(object)manager != (Object)null && displaying != null)
			{
				try
				{
					open = (bool)displaying.GetValue(manager, null);
				}
				catch
				{
					open = false;
				}
			}
			return open;
		}
	}

	internal static bool HudVisible(Hud hud)
	{
		if ((Object)(object)hud != (Object)null)
		{
			if (!Open)
			{
				return hud.IsVisible();
			}
			return true;
		}
		return false;
	}

	internal static bool MenuVisible()
	{
		if (!Open)
		{
			return Menu.IsVisible();
		}
		return false;
	}

	internal static bool MapVisible()
	{
		if (!Open)
		{
			return Minimap.IsOpen();
		}
		return false;
	}

	internal static bool StoreVisible()
	{
		if (!Open)
		{
			return StoreGui.IsVisible();
		}
		return false;
	}

	internal static bool InventoryHidesHud()
	{
		if (!Open)
		{
			return InventoryGui.IsVisible();
		}
		return false;
	}
}

BepInEx/plugins/MMC-RememberPassword/MMCRememberPassword.dll

Decompiled a week ago
using System;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security.Cryptography;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using TMPro;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("0.0.0.0")]
public sealed class MMCPasswordStore
{
	private readonly string directory;

	private static readonly byte[] Entropy = Encoding.UTF8.GetBytes("MMC Remember Server Password v1");

	public MMCPasswordStore(string directory)
	{
		this.directory = directory;
	}

	private string PathFor(string server)
	{
		if (string.IsNullOrEmpty(server))
		{
			throw new ArgumentException("Missing server identity");
		}
		using SHA256 sHA = SHA256.Create();
		return Path.Combine(directory, BitConverter.ToString(sHA.ComputeHash(Encoding.UTF8.GetBytes(server))).Replace("-", "") + ".bin");
	}

	public string Read(string server)
	{
		string path = PathFor(server);
		if (!File.Exists(path))
		{
			return null;
		}
		return Encoding.UTF8.GetString(ProtectedData.Unprotect(File.ReadAllBytes(path), Entropy, (DataProtectionScope)0));
	}

	public void Save(string server, string password)
	{
		if (!string.IsNullOrEmpty(password))
		{
			byte[] bytes = ProtectedData.Protect(Encoding.UTF8.GetBytes(password), Entropy, (DataProtectionScope)0);
			Directory.CreateDirectory(directory);
			string text = PathFor(server);
			string text2 = text + ".tmp";
			File.WriteAllBytes(text2, bytes);
			if (File.Exists(text))
			{
				File.Replace(text2, text, null);
			}
			else
			{
				File.Move(text2, text);
			}
		}
	}

	public void Forget(string server)
	{
		string path = PathFor(server);
		if (File.Exists(path))
		{
			File.Delete(path);
		}
	}
}
[BepInPlugin("local.mmc.rememberpassword", "Saga Remember Password", "3.0.0")]
public sealed class MMCRememberPassword : BaseUnityPlugin
{
	private static MMCRememberPassword instance;

	private MMCPasswordStore store;

	private Harmony harmony;

	private ConfigEntry<bool> autoUse;

	private ConfigEntry<bool> enabledAddon;

	private string server;

	private string pendingPassword;

	private bool remember;

	private bool submitted;

	private bool bypass;

	private bool savedThisAttempt;

	private ZNet attempt;

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

	private static readonly MethodInfo Enter = AccessTools.Method(typeof(ZNet), "OnPasswordEntered", (Type[])null, (Type[])null);

	private static readonly FieldInfo PasswordRPC = AccessTools.Field(typeof(ZNet), "m_tempPasswordRPC");

	private void Awake()
	{
		//IL_0068: Unknown result type (might be due to invalid IL or missing references)
		//IL_0072: Expected O, but got Unknown
		//IL_009e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c0: Expected O, but got Unknown
		//IL_00c0: Expected O, but got Unknown
		//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ea: Expected O, but got Unknown
		//IL_0117: Unknown result type (might be due to invalid IL or missing references)
		//IL_0125: Expected O, but got Unknown
		instance = this;
		enabledAddon = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "Enabled", true, "Enable remember-password controls and saved-password handling. Disabling preserves already saved passwords but does not use or update them.");
		store = new MMCPasswordStore(Path.Combine(Paths.ConfigPath, "MMC-RememberPassword"));
		autoUse = ((BaseUnityPlugin)this).Config.Bind<bool>("Login", "Automatically Use Saved Password", true, "Automatically submit saved passwords. Disable to show the prompt and replace or forget a saved password. Hold Left Shift when the password prompt opens to bypass automatic login once.");
		harmony = new Harmony("local.mmc.rememberpassword");
		harmony.Patch((MethodBase)AccessTools.Method(typeof(ZNet), "RPC_ClientHandshake", (Type[])null, (Type[])null), new HarmonyMethod(typeof(MMCRememberPassword), "BeforeHandshake", (Type[])null), new HarmonyMethod(typeof(MMCRememberPassword), "AfterHandshake", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		harmony.Patch((MethodBase)Enter, new HarmonyMethod(typeof(MMCRememberPassword), "BeforeSubmit", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		harmony.Patch((MethodBase)AccessTools.Method(typeof(ZNet), "RPC_Error", (Type[])null, (Type[])null), new HarmonyMethod(typeof(MMCRememberPassword), "OnError", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
	}

	private static void BeforeHandshake(ZNet __instance, bool __1)
	{
		if ((Object)(object)instance == (Object)null || !instance.enabledAddon.Value || !__1)
		{
			return;
		}
		instance.attempt = __instance;
		instance.server = ZNet.GetServerString(true);
		instance.pendingPassword = null;
		instance.submitted = false;
		instance.savedThisAttempt = false;
		instance.bypass = !instance.autoUse.Value || Input.GetKey((KeyCode)304) || Input.GetKey((KeyCode)303);
		instance.remember = false;
		try
		{
			instance.remember = !string.IsNullOrEmpty(instance.store.Read(instance.server));
		}
		catch
		{
			((BaseUnityPlugin)instance).Logger.LogWarning((object)"Saved server password could not be read; enter it again.");
		}
	}

	private static void AfterHandshake(ZNet __instance, bool __1)
	{
		if ((Object)(object)instance == (Object)null || !instance.enabledAddon.Value || !__1 || instance.bypass || instance.submitted || (Object)(object)__instance.m_passwordDialog == (Object)null || !((Component)__instance.m_passwordDialog).gameObject.activeInHierarchy)
		{
			return;
		}
		try
		{
			string text = instance.store.Read(instance.server);
			if (!string.IsNullOrEmpty(text))
			{
				Enter.Invoke(__instance, new object[1] { text });
			}
		}
		catch
		{
			((BaseUnityPlugin)instance).Logger.LogWarning((object)"Saved password could not be submitted; use the password prompt.");
		}
	}

	private static void BeforeSubmit(ZNet __instance, string __0)
	{
		if ((Object)(object)instance == (Object)null || !instance.enabledAddon.Value || (Object)(object)instance.attempt != (Object)(object)__instance || string.IsNullOrEmpty(__0))
		{
			return;
		}
		object? value = PasswordRPC.GetValue(__instance);
		ZRpc val = (ZRpc)((value is ZRpc) ? value : null);
		if (val != null && val.IsConnected())
		{
			instance.pendingPassword = (instance.remember ? __0 : null);
			instance.submitted = true;
			if (!instance.remember)
			{
				instance.Forget();
			}
		}
	}

	private void Forget()
	{
		if (string.IsNullOrEmpty(server))
		{
			return;
		}
		try
		{
			store.Forget(server);
		}
		catch
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)"Could not remove the saved server password.");
		}
	}

	private static void OnError(int __1)
	{
		if (!((Object)(object)instance == (Object)null) && instance.enabledAddon.Value && instance.submitted)
		{
			if (__1 == 6)
			{
				instance.Forget();
				instance.remember = false;
				((BaseUnityPlugin)instance).Logger.LogInfo((object)"Server rejected the password. Join again to enter and remember its updated password.");
			}
			instance.pendingPassword = null;
			instance.submitted = false;
		}
	}

	private void Update()
	{
		//IL_0062: Unknown result type (might be due to invalid IL or missing references)
		//IL_0068: Invalid comparison between Unknown and I4
		if (!enabledAddon.Value)
		{
			pendingPassword = null;
			submitted = false;
			attempt = null;
		}
		else if ((Object)(object)attempt == (Object)null || (Object)(object)attempt != (Object)(object)ZNet.instance)
		{
			pendingPassword = null;
			submitted = false;
		}
		else
		{
			if (!submitted || savedThisAttempt || (int)ZNet.GetConnectionStatus() != 2)
			{
				return;
			}
			savedThisAttempt = true;
			if (!string.IsNullOrEmpty(pendingPassword))
			{
				try
				{
					store.Save(server, pendingPassword);
				}
				catch
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)"Login succeeded, but the server password could not be saved.");
				}
			}
			pendingPassword = null;
		}
	}

	private void OnGUI()
	{
		//IL_0090: 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_00bf: 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_00d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_0167: Unknown result type (might be due to invalid IL or missing references)
		//IL_0182: Unknown result type (might be due to invalid IL or missing references)
		if (enabledAddon.Value && !((Object)(object)attempt == (Object)null) && !((Object)(object)attempt != (Object)(object)ZNet.instance) && !((Object)(object)attempt.m_passwordDialog == (Object)null) && ((Component)attempt.m_passwordDialog).gameObject.activeInHierarchy)
		{
			TMP_InputField componentInChildren = ((Component)attempt.m_passwordDialog).GetComponentInChildren<TMP_InputField>();
			if (!((Object)(object)componentInChildren == (Object)null))
			{
				Transform transform = ((Component)componentInChildren).transform;
				RectTransform val = (RectTransform)(object)((transform is RectTransform) ? transform : null);
				Canvas componentInParent = ((Component)val).GetComponentInParent<Canvas>();
				Camera val2 = (((Object)(object)componentInParent == (Object)null || (int)componentInParent.renderMode == 0) ? null : componentInParent.worldCamera);
				val.GetWorldCorners(corners);
				Vector2 val3 = RectTransformUtility.WorldToScreenPoint(val2, corners[0]);
				float num = Mathf.Max(230f, RectTransformUtility.WorldToScreenPoint(val2, corners[2]).x - val3.x);
				float num2 = Mathf.Clamp(val3.x, 4f, Mathf.Max(4f, (float)Screen.width - num - 4f));
				float num3 = Mathf.Min((float)(Screen.height - 32), (float)Screen.height - val3.y + 8f);
				GUI.Box(new Rect(num2 - 4f, num3 - 3f, num + 8f, 30f), GUIContent.none);
				remember = GUI.Toggle(new Rect(num2, num3, num, 25f), remember, "Remember password");
			}
		}
	}

	private void OnDestroy()
	{
		pendingPassword = null;
		if (harmony != null)
		{
			harmony.UnpatchSelf();
		}
		instance = null;
	}
}

BepInEx/plugins/MMC-SagaChatPro/SagaChatPro.dll

Decompiled a week ago
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using HarmonyLib;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: CompilationRelaxations(8)]
[assembly: AssemblyVersion("0.0.0.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInPlugin("local.mmc.sagachatpro", "SagaChatPro", "3.0.3")]
public sealed class SagaChatPro : BaseUnityPlugin
{
	private sealed class SavedRect
	{
		public RectTransform Rect;

		public Transform Parent;

		public int Index;

		public Vector2 Min;

		public Vector2 Max;

		public Vector2 Pivot;

		public Vector2 Position;

		public Vector2 Size;

		public Vector3 Scale;

		public SavedRect(RectTransform r)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: 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_0038: 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_0044: 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_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: 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_0063: 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)
			Rect = r;
			Parent = ((Transform)r).parent;
			Index = ((Transform)r).GetSiblingIndex();
			Min = r.anchorMin;
			Max = r.anchorMax;
			Pivot = r.pivot;
			Position = r.anchoredPosition;
			Size = r.sizeDelta;
			Scale = ((Transform)r).localScale;
		}

		public void Restore()
		{
			//IL_0047: 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_0069: 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_008b: 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)
			if (!((Object)(object)Rect == (Object)null) && !((Object)(object)Parent == (Object)null))
			{
				((Transform)Rect).SetParent(Parent, false);
				((Transform)Rect).SetSiblingIndex(Index);
				Rect.anchorMin = Min;
				Rect.anchorMax = Max;
				Rect.pivot = Pivot;
				Rect.anchoredPosition = Position;
				Rect.sizeDelta = Size;
				((Transform)Rect).localScale = Scale;
			}
		}
	}

	private ConfigEntry<bool> autoHideChat;

	private ConfigEntry<bool> rememberMode;

	private ConfigEntry<float> chatHideDelay;

	private ConfigEntry<string> lastMode;

	private ConfigEntry<string> extraModes;

	private float lastMessage;

	private bool wasTyping;

	private static SagaChatPro instance;

	private Harmony harmony;

	private SagaPanelWindow window;

	private ConfigEntry<bool> enabledPanel;

	private ConfigEntry<float> width;

	private ConfigEntry<float> height;

	private ConfigEntry<float> opacity;

	private Chat chat;

	private GameObject canvasObject;

	private RectTransform root;

	private RectTransform chatBody;

	private Image panelBackground;

	private Image panelHeader;

	private readonly List<Image> panelEdges = new List<Image>();

	private TMP_Text hint;

	private CanvasGroup searchGroup;

	private float searchAlpha;

	private bool addedSearchGroup;

	private CanvasGroup nativeGroup;

	private float nativeAlpha;

	private bool addedGroup;

	private bool failed;

	private float oldFontSize;

	private Color oldTextColor;

	private TextAlignmentOptions oldAlignment;

	private TextOverflowModes oldOverflow;

	private bool oldAutoSize;

	private Rect placed;

	private readonly Dictionary<MaskableGraphic, bool> maskStates = new Dictionary<MaskableGraphic, bool>();

	private readonly List<SavedRect> saved = new List<SavedRect>();

	private void BindChatBehavior()
	{
		//IL_0051: Unknown result type (might be due to invalid IL or missing references)
		//IL_005b: Expected O, but got Unknown
		//IL_010c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0119: Expected O, but got Unknown
		//IL_0146: Unknown result type (might be due to invalid IL or missing references)
		//IL_0154: Expected O, but got Unknown
		//IL_0181: Unknown result type (might be due to invalid IL or missing references)
		//IL_018f: Expected O, but got Unknown
		autoHideChat = ((BaseUnityPlugin)this).Config.Bind<bool>("Behavior", "Auto Hide", true, "Hide chat after inactivity; typing, inventory and F1 reveal it.");
		chatHideDelay = ((BaseUnityPlugin)this).Config.Bind<float>("Behavior", "Hide Delay", 20f, new ConfigDescription("Seconds since latest chat message.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 600f), new object[0]));
		rememberMode = ((BaseUnityPlugin)this).Config.Bind<bool>("Behavior", "Remember Chat Mode", true, "Prefill the last /s, /say, /w or /whisper mode when opening chat.");
		extraModes = ((BaseUnityPlugin)this).Config.Bind<string>("Behavior", "Additional Chat Modes", "/g,/p", "Comma-separated modded chat commands to remember when used, such as group or party chat. This does not add chat commands.");
		lastMode = ((BaseUnityPlugin)this).Config.Bind<string>("Behavior", "Last Chat Mode", "", "Saved chat prefix. Empty means normal say.");
		harmony.Patch((MethodBase)AccessTools.Method(typeof(Terminal), "AddString", new Type[1] { typeof(string) }, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(SagaChatPro), "MessageArrived", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		harmony.Patch((MethodBase)AccessTools.Method(typeof(Chat), "SendInput", (Type[])null, (Type[])null), new HarmonyMethod(typeof(SagaChatPro), "RememberInput", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		harmony.Patch((MethodBase)AccessTools.Method(typeof(Terminal), "TryRunCommand", (Type[])null, (Type[])null), new HarmonyMethod(typeof(SagaChatPro), "EmptyChannelCommand", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		lastMessage = Time.unscaledTime;
	}

	private static bool EmptyChannelCommand(Terminal __instance, string __0)
	{
		if (!((Object)(object)instance == (Object)null) && instance.enabledPanel.Value && __instance is Chat)
		{
			return !SagaChatMode.IsEmptyChannel("/" + (__0 ?? "").Trim(), instance.extraModes.Value);
		}
		return true;
	}

	private static void MessageArrived(Terminal __instance)
	{
		if ((Object)(object)instance != (Object)null && __instance is Chat)
		{
			instance.lastMessage = Time.unscaledTime;
		}
	}

	private static bool RememberInput(Chat __instance)
	{
		if ((Object)(object)instance == (Object)null || !instance.enabledPanel.Value)
		{
			return true;
		}
		string text = ((TMP_InputField)((Terminal)__instance).m_input).text.TrimStart(new char[0]);
		if (SagaChatMode.IsEmptyChannel(text, instance.extraModes.Value))
		{
			((TMP_InputField)((Terminal)__instance).m_input).text = "";
			((Component)((Terminal)__instance).m_input).gameObject.SetActive(false);
			instance.wasTyping = false;
			return false;
		}
		if (!instance.rememberMode.Value)
		{
			return true;
		}
		string value = SagaChatMode.Remember(text, instance.lastMode.Value);
		string text2 = text.Split(new char[1] { ' ' })[0].ToLowerInvariant();
		string[] array = instance.extraModes.Value.Split(new char[1] { ',' });
		foreach (string text3 in array)
		{
			if (text2 == text3.Trim().ToLowerInvariant() && text2.Length > 1)
			{
				value = text2;
			}
		}
		instance.lastMode.Value = value;
		return true;
	}

	private void UpdateChatMode()
	{
		bool activeSelf = ((Component)((Terminal)chat).m_input).gameObject.activeSelf;
		if ((Object)(object)Player.m_localPlayer != (Object)null && activeSelf && !wasTyping && rememberMode.Value && string.IsNullOrEmpty(((TMP_InputField)((Terminal)chat).m_input).text) && !string.IsNullOrEmpty(lastMode.Value))
		{
			((TMP_InputField)((Terminal)chat).m_input).text = lastMode.Value + " ";
			((TMP_InputField)((Terminal)chat).m_input).caretPosition = ((TMP_InputField)((Terminal)chat).m_input).text.Length;
		}
		if (activeSelf)
		{
			lastMessage = Time.unscaledTime;
		}
		wasTyping = activeSelf;
	}

	private bool ChatRecentlyActive()
	{
		if (!SagaConfigPreview.Open && !InventoryGui.IsVisible() && autoHideChat.Value && !((Component)((Terminal)chat).m_input).gameObject.activeSelf)
		{
			return Time.unscaledTime - lastMessage <= chatHideDelay.Value;
		}
		return true;
	}

	private void Awake()
	{
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_0061: Expected O, but got Unknown
		//IL_0096: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a0: Expected O, but got Unknown
		//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00df: Expected O, but got Unknown
		//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fa: Expected O, but got Unknown
		//IL_0120: Unknown result type (might be due to invalid IL or missing references)
		//IL_012a: Expected O, but got Unknown
		//IL_0156: Unknown result type (might be due to invalid IL or missing references)
		//IL_0164: Expected O, but got Unknown
		//IL_0192: Unknown result type (might be due to invalid IL or missing references)
		//IL_019f: Expected O, but got Unknown
		instance = this;
		enabledPanel = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "Enabled", true, "Keep chat visible in a SagaPro frame.");
		width = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "Width", 460f, new ConfigDescription("Window width in pixels.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(300f, 900f), new object[0]));
		height = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "Height", 250f, new ConfigDescription("Window height in pixels.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(150f, 600f), new object[0]));
		opacity = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "Background Opacity", 0.6f, new ConfigDescription("Background opacity; text stays opaque.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), new object[0]));
		window = new SagaPanelWindow(((BaseUnityPlugin)this).Config, "SagaChatPro");
		window.MinimumWidth = 260f;
		window.MinimumHeight = 100f;
		harmony = new Harmony("local.mmc.sagachatpro");
		harmony.Patch((MethodBase)AccessTools.Method(typeof(Chat), "Update", (Type[])null, (Type[])null), new HarmonyMethod(typeof(SagaChatPro), "BeforeChatUpdate", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		harmony.Patch((MethodBase)AccessTools.Method(typeof(Chat), "IsChatDialogWindowVisible", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(SagaChatPro), "DialogVisible", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		BindChatBehavior();
		((BaseUnityPlugin)this).Logger.LogInfo((object)"SagaChatPro: persistent history; native Enter typing/sending. Drag header with inventory open.");
	}

	private static void BeforeChatUpdate(Chat __instance, ref float ___m_hideTimer)
	{
		if ((Object)(object)instance != (Object)null && !instance.failed && instance.enabledPanel.Value && (Object)(object)Player.m_localPlayer != (Object)null)
		{
			___m_hideTimer = 0f;
		}
	}

	private static void DialogVisible(Chat __instance, ref bool __result)
	{
		if ((Object)(object)instance != (Object)null && (Object)(object)instance.chat == (Object)(object)__instance && (Object)(object)instance.root != (Object)null && ((Component)instance.root).gameObject.activeInHierarchy)
		{
			__result = __instance.HasFocus();
		}
	}

	private RectTransform Node(string name, Transform parent)
	{
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		RectTransform component = new GameObject(name, new Type[1] { typeof(RectTransform) }).GetComponent<RectTransform>();
		((Transform)component).SetParent(parent, false);
		return component;
	}

	private static void Stretch(RectTransform r, float left, float bottom, float right, float top)
	{
		//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_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: 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)
		r.anchorMin = Vector2.zero;
		r.anchorMax = Vector2.one;
		r.pivot = new Vector2(0.5f, 0.5f);
		r.offsetMin = new Vector2(left, bottom);
		r.offsetMax = new Vector2(0f - right, 0f - top);
		((Transform)r).localScale = Vector3.one;
	}

	private Image Box(string name, Transform parent, Color color)
	{
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		Image val = ((Component)Node(name, parent)).gameObject.AddComponent<Image>();
		((Graphic)val).color = color;
		((Graphic)val).raycastTarget = false;
		return val;
	}

	private TMP_Text Label(string name, Transform parent, string value, int size, Color color)
	{
		//IL_003c: 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_0077: Unknown result type (might be due to invalid IL or missing references)
		TMP_Text val = (TMP_Text)(object)((Component)Node(name, parent)).gameObject.AddComponent<TextMeshProUGUI>();
		val.font = ((TMP_Text)((Terminal)chat).m_output).font;
		val.text = value;
		val.fontSize = 16f;
		((Graphic)val).color = color;
		val.alignment = (TextAlignmentOptions)4097;
		((Graphic)val).raycastTarget = false;
		Outline val2 = ((Component)val).gameObject.AddComponent<Outline>();
		((Shadow)val2).effectColor = Color.black;
		((Shadow)val2).effectDistance = new Vector2(1f, -1f);
		return val;
	}

	private void Move(RectTransform r, Transform parent)
	{
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		saved.Add(new SavedRect(r));
		((Transform)r).SetParent(parent, false);
		((Transform)r).localScale = Vector3.one;
		MaskableGraphic[] componentsInChildren = ((Component)r).GetComponentsInChildren<MaskableGraphic>(true);
		foreach (MaskableGraphic val in componentsInChildren)
		{
			if (!maskStates.ContainsKey(val))
			{
				maskStates.Add(val, val.maskable);
			}
			val.maskable = true;
			val.RecalculateClipping();
		}
	}

	private void Build(Chat current)
	{
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: Expected O, but got Unknown
		//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b3: 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_00bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_0143: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_02cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0304: Unknown result type (might be due to invalid IL or missing references)
		//IL_031a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0330: Unknown result type (might be due to invalid IL or missing references)
		//IL_0346: Unknown result type (might be due to invalid IL or missing references)
		//IL_035f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0255: Unknown result type (might be due to invalid IL or missing references)
		//IL_026a: 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_01fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_020f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0225: Unknown result type (might be due to invalid IL or missing references)
		//IL_0403: Unknown result type (might be due to invalid IL or missing references)
		//IL_0408: Unknown result type (might be due to invalid IL or missing references)
		//IL_0445: Unknown result type (might be due to invalid IL or missing references)
		//IL_044a: Unknown result type (might be due to invalid IL or missing references)
		//IL_045b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0460: Unknown result type (might be due to invalid IL or missing references)
		//IL_058f: Unknown result type (might be due to invalid IL or missing references)
		//IL_05a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_05bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_05d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_05e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_070b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0725: Unknown result type (might be due to invalid IL or missing references)
		//IL_0744: Unknown result type (might be due to invalid IL or missing references)
		//IL_0763: Unknown result type (might be due to invalid IL or missing references)
		//IL_0782: Unknown result type (might be due to invalid IL or missing references)
		//IL_07a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_07ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_07b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_029a: Unknown result type (might be due to invalid IL or missing references)
		//IL_023e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0699: Unknown result type (might be due to invalid IL or missing references)
		//IL_06af: Unknown result type (might be due to invalid IL or missing references)
		//IL_06c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_06db: Unknown result type (might be due to invalid IL or missing references)
		//IL_06f1: Unknown result type (might be due to invalid IL or missing references)
		Cleanup();
		chat = current;
		canvasObject = new GameObject("SagaChatPro Canvas", new Type[3]
		{
			typeof(RectTransform),
			typeof(Canvas),
			typeof(GraphicRaycaster)
		});
		Canvas component = canvasObject.GetComponent<Canvas>();
		component.renderMode = (RenderMode)0;
		component.sortingOrder = 10;
		root = Node("SagaChatPro", canvasObject.transform);
		RectTransform obj = root;
		RectTransform obj2 = root;
		Vector2 val = (root.pivot = new Vector2(0f, 1f));
		Vector2 anchorMin = (obj2.anchorMax = val);
		obj.anchorMin = anchorMin;
		((Component)root).gameObject.AddComponent<RectMask2D>();
		Image val4 = Box("Bronze frame", (Transform)(object)root, new Color(0.38f, 0.26f, 0.13f, 1f));
		Stretch(((Graphic)val4).rectTransform, 0f, 0f, 0f, 0f);
		Image val5 = Box("Dark panel", (Transform)(object)root, new Color(0.035f, 0.04f, 0.035f, opacity.Value));
		Stretch(((Graphic)val5).rectTransform, 2f, 2f, 2f, 2f);
		panelBackground = val5;
		((Component)val4).gameObject.SetActive(false);
		for (int i = 0; i < 4; i++)
		{
			Image val6 = Box("Frame edge " + i, (Transform)(object)root, new Color(0.38f, 0.26f, 0.13f, 1f));
			panelEdges.Add(val6);
			RectTransform rectTransform = ((Graphic)val6).rectTransform;
			Stretch(rectTransform, 0f, 0f, 0f, 0f);
			if (i < 2)
			{
				rectTransform.anchorMin = new Vector2((float)i, 0f);
				rectTransform.anchorMax = new Vector2((float)i, 1f);
				rectTransform.sizeDelta = new Vector2(2f, 0f);
				rectTransform.anchoredPosition = new Vector2((float)((i == 0) ? 1 : (-1)), 0f);
			}
			else
			{
				rectTransform.anchorMin = new Vector2(0f, (float)(i - 2));
				rectTransform.anchorMax = new Vector2(1f, (float)(i - 2));
				rectTransform.sizeDelta = new Vector2(0f, 2f);
				rectTransform.anchoredPosition = new Vector2(0f, (float)((i == 2) ? 1 : (-1)));
			}
		}
		RectTransform rectTransform2 = ((Graphic)(panelHeader = Box("Header", (Transform)(object)root, new Color(0.16f, 0.105f, 0.055f, 0.93f)))).rectTransform;
		rectTransform2.anchorMin = new Vector2(0f, 1f);
		rectTransform2.anchorMax = Vector2.one;
		rectTransform2.pivot = new Vector2(0.5f, 1f);
		rectTransform2.sizeDelta = new Vector2(-4f, 29f);
		rectTransform2.anchoredPosition = new Vector2(0f, -2f);
		TMP_Text val7 = Label("Title", (Transform)(object)rectTransform2, "", 16, Color.white);
		Stretch(val7.rectTransform, 10f, 0f, 10f, 0f);
		nativeGroup = ((Component)((Terminal)chat).m_chatWindow).GetComponent<CanvasGroup>();
		addedGroup = (Object)(object)nativeGroup == (Object)null;
		if (addedGroup)
		{
			nativeGroup = ((Component)((Terminal)chat).m_chatWindow).gameObject.AddComponent<CanvasGroup>();
		}
		nativeAlpha = nativeGroup.alpha;
		nativeGroup.alpha = 0f;
		oldTextColor = ((Graphic)((Terminal)chat).m_output).color;
		oldFontSize = ((TMP_Text)((Terminal)chat).m_output).fontSize;
		oldAutoSize = ((TMP_Text)((Terminal)chat).m_output).enableAutoSizing;
		oldAlignment = ((TMP_Text)((Terminal)chat).m_output).alignment;
		oldOverflow = ((TMP_Text)((Terminal)chat).m_output).overflowMode;
		RectTransform val8 = (chatBody = Node("Clipped chat body", (Transform)(object)root));
		Stretch(val8, 2f, 2f, 2f, 33f);
		((Component)val8).gameObject.AddComponent<RectMask2D>();
		RectTransform val9 = Node("Clipped message history", (Transform)(object)val8);
		Stretch(val9, 10f, 41f, 10f, 6f);
		((Component)val9).gameObject.AddComponent<RectMask2D>();
		Move(((TMP_Text)((Terminal)chat).m_output).rectTransform, (Transform)(object)val9);
		Stretch(((TMP_Text)((Terminal)chat).m_output).rectTransform, 0f, 0f, 0f, 0f);
		((TMP_Text)((Terminal)chat).m_output).enableAutoSizing = false;
		((TMP_Text)((Terminal)chat).m_output).fontSize = 16f;
		((TMP_Text)((Terminal)chat).m_output).alignment = (TextAlignmentOptions)1025;
		((TMP_Text)((Terminal)chat).m_output).overflowMode = (TextOverflowModes)0;
		Transform transform = ((Component)((Terminal)chat).m_input).transform;
		RectTransform val10 = (RectTransform)(object)((transform is RectTransform) ? transform : null);
		Move(val10, (Transform)(object)val8);
		val10.anchorMin = Vector2.zero;
		val10.anchorMax = new Vector2(1f, 0f);
		val10.pivot = new Vector2(0.5f, 0f);
		val10.sizeDelta = new Vector2(-20f, 29f);
		val10.anchoredPosition = new Vector2(0f, 8f);
		if ((Object)(object)((Terminal)chat).m_search != (Object)null)
		{
			searchGroup = ((Component)((Terminal)chat).m_search).GetComponent<CanvasGroup>();
			addedSearchGroup = (Object)(object)searchGroup == (Object)null;
			if (addedSearchGroup)
			{
				searchGroup = ((Component)((Terminal)chat).m_search).gameObject.AddComponent<CanvasGroup>();
			}
			searchAlpha = searchGroup.alpha;
			Move(((Terminal)chat).m_search.rectTransform, (Transform)(object)val8);
			RectTransform rectTransform3 = ((Terminal)chat).m_search.rectTransform;
			rectTransform3.anchorMin = new Vector2(0f, 0f);
			rectTransform3.anchorMax = new Vector2(1f, 0f);
			rectTransform3.pivot = new Vector2(0.5f, 0f);
			rectTransform3.sizeDelta = new Vector2(-24f, 55f);
			rectTransform3.anchoredPosition = new Vector2(0f, 39f);
		}
		hint = Label("Enter hint", (Transform)(object)val8, "Enter to chat", 14, Color.white);
		hint.rectTransform.anchorMin = Vector2.zero;
		hint.rectTransform.anchorMax = new Vector2(1f, 0f);
		hint.rectTransform.pivot = new Vector2(0.5f, 0f);
		hint.rectTransform.sizeDelta = new Vector2(-24f, 29f);
		hint.rectTransform.anchoredPosition = new Vector2(0f, 8f);
		placed = DefaultRect();
		ApplyPosition();
	}

	private Rect DefaultRect()
	{
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		float num = Mathf.Min(width.Value, (float)Mathf.Max(100, Screen.width - 24));
		float num2 = Mathf.Min(height.Value, (float)Mathf.Max(100, Screen.height - 24));
		return new Rect((float)Screen.width - num - 16f, (float)Screen.height - num2 - 16f, num, num2);
	}

	private void ApplyPosition()
	{
		//IL_001d: 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_0067: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
		root.anchoredPosition = new Vector2(((Rect)(ref placed)).x, 0f - ((Rect)(ref placed)).y);
		root.sizeDelta = ((Rect)(ref placed)).size;
		if ((Object)(object)panelBackground != (Object)null)
		{
			((Graphic)panelBackground).color = window.Appearance.Background(opacity.Value);
		}
		if ((Object)(object)panelHeader != (Object)null)
		{
			((Behaviour)panelHeader).enabled = !window.ToolWindow;
			((Graphic)panelHeader).color = window.Appearance.Header;
		}
		foreach (Image panelEdge in panelEdges)
		{
			if ((Object)(object)panelEdge != (Object)null)
			{
				((Behaviour)panelEdge).enabled = !window.ToolWindow;
				((Graphic)panelEdge).color = window.Appearance.Border;
			}
		}
		if ((Object)(object)chatBody != (Object)null)
		{
			Stretch(chatBody, 2f, 2f, 2f, window.HeaderHeight + 2f);
		}
	}

	private void LateUpdate()
	{
		if (failed)
		{
			return;
		}
		try
		{
			if (!enabledPanel.Value || (Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)Chat.instance == (Object)null)
			{
				if ((Object)(object)chat != (Object)null || (Object)(object)canvasObject != (Object)null)
				{
					Cleanup();
				}
				return;
			}
			if ((Object)(object)chat != (Object)(object)Chat.instance || (Object)(object)root == (Object)null)
			{
				Build(Chat.instance);
			}
			UpdateChatMode();
			bool flag = ChatRecentlyActive() && window.Appearance.InventoryVisible && (Object)(object)Hud.instance != (Object)null && (SagaConfigPreview.HudVisible(Hud.instance) || InventoryGui.IsVisible());
			bool activeSelf = ((Component)root).gameObject.activeSelf;
			((Component)root).gameObject.SetActive(flag);
			if (flag && !activeSelf && ((Component)((Terminal)chat).m_input).gameObject.activeSelf)
			{
				((Terminal)chat).m_input.ActivateInputField();
			}
			nativeGroup.alpha = 0f;
			if (flag)
			{
				((Component)((Terminal)chat).m_chatWindow).gameObject.SetActive(true);
			}
			bool activeSelf2 = ((Component)((Terminal)chat).m_input).gameObject.activeSelf;
			if (activeSelf2 && window.Minimized)
			{
				window.Open();
			}
			window.ContentVisible(((Component)root).gameObject, !window.Minimized);
			window.AllowDrag = !activeSelf2;
			((Component)hint).gameObject.SetActive(!activeSelf2);
			if ((Object)(object)searchGroup != (Object)null)
			{
				searchGroup.alpha = (activeSelf2 ? searchAlpha : 0f);
			}
			if (!flag)
			{
				window.Hide();
			}
		}
		catch (Exception ex)
		{
			failed = true;
			((BaseUnityPlugin)this).Logger.LogError((object)("SagaChatPro restored native chat: " + ex));
			Cleanup();
		}
	}

	private void OnGUI()
	{
		//IL_0029: 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_0038: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)root == (Object)null) && ((Component)root).gameObject.activeInHierarchy)
		{
			placed = window.Place(DefaultRect(), 0f);
			ApplyPosition();
			window.DrawHeader();
		}
	}

	private void Cleanup()
	{
		//IL_0101: Unknown result type (might be due to invalid IL or missing references)
		//IL_0143: Unknown result type (might be due to invalid IL or missing references)
		//IL_0159: Unknown result type (might be due to invalid IL or missing references)
		if (window != null)
		{
			window.Hide();
		}
		panelEdges.Clear();
		panelBackground = (panelHeader = null);
		chatBody = null;
		for (int num = saved.Count - 1; num >= 0; num--)
		{
			saved[num].Restore();
		}
		saved.Clear();
		foreach (KeyValuePair<MaskableGraphic, bool> maskState in maskStates)
		{
			if ((Object)(object)maskState.Key != (Object)null)
			{
				maskState.Key.maskable = maskState.Value;
				maskState.Key.RecalculateClipping();
			}
		}
		maskStates.Clear();
		if ((Object)(object)chat != (Object)null && (Object)(object)((Terminal)chat).m_output != (Object)null)
		{
			((Graphic)((Terminal)chat).m_output).color = oldTextColor;
			((TMP_Text)((Terminal)chat).m_output).fontSize = oldFontSize;
			((TMP_Text)((Terminal)chat).m_output).enableAutoSizing = oldAutoSize;
			((TMP_Text)((Terminal)chat).m_output).alignment = oldAlignment;
			((TMP_Text)((Terminal)chat).m_output).overflowMode = oldOverflow;
		}
		if ((Object)(object)nativeGroup != (Object)null)
		{
			nativeGroup.alpha = nativeAlpha;
			if (addedGroup)
			{
				Object.Destroy((Object)(object)nativeGroup);
			}
		}
		nativeGroup = null;
		addedGroup = false;
		if ((Object)(object)searchGroup != (Object)null)
		{
			searchGroup.alpha = searchAlpha;
			if (addedSearchGroup)
			{
				Object.Destroy((Object)(object)searchGroup);
			}
		}
		searchGroup = null;
		addedSearchGroup = false;
		if ((Object)(object)canvasObject != (Object)null)
		{
			Object.Destroy((Object)(object)canvasObject);
		}
		canvasObject = null;
		root = null;
		chat = null;
	}

	private void OnDestroy()
	{
		if (harmony != null)
		{
			harmony.UnpatchSelf();
		}
		Cleanup();
		if (window != null)
		{
			window.Dispose();
		}
		instance = null;
	}
}
public static class SagaChatMode
{
	public static bool IsEmptyChannel(string text, string extras)
	{
		string text2 = (text ?? "").Trim().ToLowerInvariant();
		if (text2.Length == 0)
		{
			return true;
		}
		switch (text2)
		{
		case "/s":
		case "/shout":
		case "/say":
		case "/w":
		case "/whisper":
			return true;
		default:
		{
			string[] array = (extras ?? "").Split(new char[1] { ',' });
			foreach (string text3 in array)
			{
				if (text3.Trim().StartsWith("/") && text2 == text3.Trim().ToLowerInvariant())
				{
					return true;
				}
			}
			return false;
		}
		}
	}

	public static string Remember(string text, string previous)
	{
		text = (text ?? "").TrimStart(new char[0]);
		if (text.Length == 0)
		{
			return previous;
		}
		string text2 = text.Split(new char[1] { ' ' })[0].ToLowerInvariant();
		switch (text2)
		{
		case "/s":
		case "/shout":
		case "/w":
		case "/whisper":
			return text2;
		default:
			if (text.StartsWith("/"))
			{
				return previous;
			}
			goto case "/say";
		case "/say":
			return "";
		}
	}
}
internal static class SagaConfigPreview
{
	private static BaseUnityPlugin manager;

	private static PropertyInfo displaying;

	private static float retry;

	private static int frame = -1;

	private static bool open;

	internal static bool Open
	{
		get
		{
			if (frame == Time.frameCount)
			{
				return open;
			}
			frame = Time.frameCount;
			open = false;
			if ((Object)(object)manager == (Object)null && Time.unscaledTime >= retry)
			{
				retry = Time.unscaledTime + 2f;
				if (Chainloader.PluginInfos.TryGetValue("com.bepis.bepinex.configurationmanager", out var value))
				{
					manager = value.Instance;
					displaying = ((object)manager).GetType().GetProperty("DisplayingWindow", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				}
			}
			if ((Object)(object)manager != (Object)null && displaying != null)
			{
				try
				{
					open = (bool)displaying.GetValue(manager, null);
				}
				catch
				{
					open = false;
				}
			}
			return open;
		}
	}

	internal static bool HudVisible(Hud hud)
	{
		if ((Object)(object)hud != (Object)null)
		{
			if (!Open)
			{
				return hud.IsVisible();
			}
			return true;
		}
		return false;
	}

	internal static bool MenuVisible()
	{
		if (!Open)
		{
			return Menu.IsVisible();
		}
		return false;
	}

	internal static bool MapVisible()
	{
		if (!Open)
		{
			return Minimap.IsOpen();
		}
		return false;
	}

	internal static bool StoreVisible()
	{
		if (!Open)
		{
			return StoreGui.IsVisible();
		}
		return false;
	}

	internal static bool InventoryHidesHud()
	{
		if (!Open)
		{
			return InventoryGui.IsVisible();
		}
		return false;
	}
}

BepInEx/plugins/MMC-SagaHitsPro/SagaHitsPro.dll

Decompiled a week ago
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[BepInPlugin("local.mmc.sagahits", "SagaHitsPro", "3.0.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public sealed class SagaHitsPro : BaseUnityPlugin
{
	private sealed class EnemyContact
	{
		public Character Target;

		public Vector3 Point;

		public float Time;

		public bool Poison;

		public bool Critical;
	}

	public sealed class Capture
	{
		public Character Target;

		public float Before;

		public float Nested;

		public Vector3 Position;

		public bool Poison;

		public bool Critical;
	}

	private sealed class Splash
	{
		public bool Preview;

		public int FountainSide;

		public Vector3 Position;

		public float Born;

		public float Lane;

		public float Amount;

		public string Text;

		public int Kind;

		public Character Follow;

		public bool Critical;

		public Vector2 ScreenAnchor;

		public bool HasScreenAnchor;

		public int AnchorFrame = -1;
	}

	public struct FoodSnapshot
	{
		public bool Valid;

		public float Maximum;

		public float FoodStamina;
	}

	private Texture2D comicTexture;

	private Texture2D[] hologramFrames;

	private GUIStyle comicLabel;

	private GUIStyle comicOutline;

	private ConfigEntry<bool> enemyHits;

	private readonly List<EnemyContact> enemyContacts = new List<EnemyContact>();

	private Texture2D heartTexture;

	private Texture2D enemyHeartTexture;

	private ConfigEntry<bool> showStaggers;

	private readonly Dictionary<Character, float> staggerTimes = new Dictionary<Character, float>();

	private readonly List<Character> oldStaggers = new List<Character>();

	private ConfigEntry<float> normalMin;

	private ConfigEntry<float> normalMax;

	private ConfigEntry<float> critMin;

	private ConfigEntry<float> critMax;

	private ConfigEntry<float> critSize;

	private ConfigEntry<float> critPop;

	private ConfigEntry<float> critShake;

	private ConfigEntry<float> critRise;

	private ConfigEntry<float> fountainWidth;

	private ConfigEntry<float> fountainHeight;

	private ConfigEntry<float> fountainDrop;

	private ConfigEntry<bool> fountain;

	private ConfigEntry<bool> previewSamples;

	private ConfigEntry<Color> ownDamage;

	private ConfigEntry<Color> enemyDamage;

	private ConfigEntry<Color> ownCrit;

	private ConfigEntry<Color> enemyCrit;

	private ConfigEntry<Color> ownPoison;

	private ConfigEntry<Color> enemyPoison;

	private ConfigEntry<Color> blockedColor;

	private ConfigEntry<Color> ownHealText;

	private ConfigEntry<Color> enemyHealText;

	private readonly SagaHitLanes fountainLanes = new SagaHitLanes();

	private float nextPreview;

	private int previewSequence;

	private static SagaHitsPro instance;

	private SagaEffectLayout personalLayout;

	private SagaEffectLayout enemyLayout;

	private SagaEffectLayout healingLayout;

	private SagaEffectLayout staggerLayout;

	private static readonly List<Capture> captures = new List<Capture>();

	private readonly List<Splash> splashes = new List<Splash>();

	private Harmony harmony;

	private ConfigEntry<bool> show;

	private ConfigEntry<bool> burst;

	private ConfigEntry<float> duration;

	private ConfigEntry<float> rise;

	private ConfigEntry<float> maxHeartHeal;

	private ConfigEntry<float> maxSplatDamage;

	private ConfigEntry<int> fontSize;

	private GUIStyle style;

	private GUIStyle shadowStyle;

	private static readonly List<Capture> heals = new List<Capture>();

	private FieldInfo clockStyle;

	private Texture2D burstTexture;

	private Player owner;

	private int sequence;

	private float pendingStaminaLoss;

	private bool BlueBlock(TextType type, Vector3 point, string value)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0002: Invalid comparison between Unknown and I4
		//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)
		//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_00a5: Unknown result type (might be due to invalid IL or missing references)
		if ((int)type != 6 || (Object)(object)Player.m_localPlayer == (Object)null)
		{
			return false;
		}
		if (!float.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out var result) || float.IsNaN(result) || Mathf.Abs(result) > 0.0001f)
		{
			return false;
		}
		Character follow = null;
		float num = 2.25f;
		foreach (Character allCharacter in Character.GetAllCharacters())
		{
			if (!((Object)(object)allCharacter == (Object)null))
			{
				Vector3 val = allCharacter.GetCenterPoint() - point;
				float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude;
				if (sqrMagnitude < num)
				{
					num = sqrMagnitude;
					follow = allCharacter;
				}
			}
		}
		Add(0f, point, 8, follow);
		return true;
	}

	private void EnsureComic()
	{
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Expected O, but got Unknown
		//IL_0353: Unknown result type (might be due to invalid IL or missing references)
		//IL_035d: Expected O, but got Unknown
		//IL_037c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0386: Expected O, but got Unknown
		//IL_0112: Unknown result type (might be due to invalid IL or missing references)
		//IL_0117: Unknown result type (might be due to invalid IL or missing references)
		//IL_0303: Unknown result type (might be due to invalid IL or missing references)
		//IL_030a: Expected O, but got Unknown
		//IL_0268: Unknown result type (might be due to invalid IL or missing references)
		//IL_026d: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_02da: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)comicTexture != (Object)null)
		{
			return;
		}
		comicTexture = new Texture2D(64, 32, (TextureFormat)4, false);
		((Texture)comicTexture).wrapMode = (TextureWrapMode)1;
		((Texture)comicTexture).filterMode = (FilterMode)0;
		Color[] array = (Color[])(object)new Color[2048];
		for (int i = 0; i < 32; i++)
		{
			for (int j = 0; j < 64; j++)
			{
				float num = ((float)j + 0.5f - 32f) / 32f;
				float num2 = ((float)i + 0.5f - 16f) / 16f;
				float num3 = Mathf.Atan2(num2, num);
				float num4 = Mathf.Sqrt(num * num + num2 * num2);
				float num5 = Mathf.Pow((Mathf.Cos(num3 * 11f + 0.4f) + 1f) * 0.5f, 3f);
				float num6 = 0.7f + 0.24f * num5 + 0.035f * Mathf.Sin(num3 * 5f);
				ref Color reference = ref array[i * 64 + j];
				reference = new Color(1f, 1f, 1f, (num4 <= num6) ? 1f : 0f);
			}
		}
		comicTexture.SetPixels(array);
		comicTexture.Apply();
		hologramFrames = (Texture2D[])(object)new Texture2D[12];
		for (int k = 0; k < hologramFrames.Length; k++)
		{
			Color[] array2 = (Color[])(object)new Color[array.Length];
			for (int l = 0; l < 32; l++)
			{
				for (int m = 0; m < 64; m++)
				{
					int num7 = l * 64 + m;
					if (array[num7].a != 0f)
					{
						bool flag = m == 0 || l == 0 || m == 63 || l == 31 || array[num7 - 1].a == 0f || array[num7 + 1].a == 0f || array[num7 - 64].a == 0f || array[num7 + 64].a == 0f;
						float num8 = Mathf.Repeat((float)m / 64f + (float)l / 48f - (float)k / 12f, 1f);
						Color val = Color.HSVToRGB(Mathf.Repeat((float)m / 90f + (float)l / 60f + (float)k / 12f, 1f), 0.48f, 0.86f);
						float num9 = Mathf.Pow(Mathf.Max(0f, 1f - Mathf.Abs(num8 - 0.5f) * 9f), 2f);
						ref Color reference2 = ref array2[num7];
						reference2 = (Color)(flag ? new Color(0.08f, 0.1f, 0.15f, 1f) : Color.Lerp(val, Color.white, num9 * 0.9f));
					}
				}
			}
			Texture2D val2 = new Texture2D(64, 32, (TextureFormat)4, false);
			((Texture)val2).wrapMode = (TextureWrapMode)1;
			((Texture)val2).filterMode = (FilterMode)0;
			val2.SetPixels(array2);
			val2.Apply(false, true);
			hologramFrames[k] = val2;
		}
		comicLabel = new GUIStyle(style);
		comicLabel.fontStyle = (FontStyle)3;
		comicLabel.alignment = (TextAnchor)4;
		comicOutline = new GUIStyle(comicLabel);
	}

	private void DrawComicStagger(float x, float y, string text, float age, float pop, float fade)
	{
		//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_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a7: 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_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_00db: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e5: Expected O, but got Unknown
		//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e5: 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_0142: Unknown result type (might be due to invalid IL or missing references)
		//IL_0147: Unknown result type (might be due to invalid IL or missing references)
		//IL_015a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0190: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_0214: Unknown result type (might be due to invalid IL or missing references)
		//IL_028a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0291: 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)
		EnsureComic();
		Matrix4x4 matrix = GUI.matrix;
		Color color = GUI.color;
		try
		{
			fade = 0.9f * Mathf.Clamp01(fade * 3f);
			GUIUtility.ScaleAroundPivot(new Vector2(0.6f, 0.6f), new Vector2(x, y));
			float num = 1f + 0.14f * Mathf.Sin(age * 23f) * Mathf.Exp((0f - age) * 9f);
			comicLabel.font = style.font;
			comicLabel.fontSize = Mathf.RoundToInt((float)fontSize.Value * 1.1f * pop * num);
			comicOutline.font = comicLabel.font;
			comicOutline.fontSize = comicLabel.fontSize;
			Vector2 val = comicLabel.CalcSize(new GUIContent(text));
			float num2 = val.x + 48f * pop;
			float num3 = val.y + 40f * pop;
			GUIUtility.RotateAroundPivot(-8f + 3f * Mathf.Sin(age * 19f) * Mathf.Exp((0f - age) * 7f), new Vector2(x, y));
			Color textColor = StaggerColor(age, fade);
			GUI.color = new Color(1f, 1f, 1f, fade);
			int num4 = (int)(age * 12f) % hologramFrames.Length;
			GUI.DrawTexture(new Rect(x - num2 * 0.5f, y - num3 * 0.5f, num2, num3), (Texture)(object)hologramFrames[num4]);
			Rect val2 = default(Rect);
			((Rect)(ref val2))..ctor(x - val.x * 0.5f - 5f, y - val.y * 0.5f - 4f, val.x + 10f, val.y + 8f);
			GUI.color = Color.white;
			comicOutline.normal.textColor = new Color(0f, 0f, 0f, fade);
			for (int i = -1; i <= 1; i++)
			{
				for (int j = -1; j <= 1; j++)
				{
					if (j != 0 || i != 0)
					{
						GUI.Label(new Rect(((Rect)(ref val2)).x + (float)(j * 2), ((Rect)(ref val2)).y + (float)(i * 2), ((Rect)(ref val2)).width, ((Rect)(ref val2)).height), text, comicOutline);
					}
				}
			}
			comicLabel.normal.textColor = textColor;
			GUI.Label(val2, text, comicLabel);
		}
		finally
		{
			GUI.matrix = matrix;
			GUI.color = color;
		}
	}

	private void PatchEnemyHits()
	{
		//IL_004d: Unknown result type (might be due to invalid IL or missing references)
		//IL_005b: Expected O, but got Unknown
		enemyHits = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "Enemy Damage Splats", true, "Replace nearby hostile-creature damage numbers with smaller desaturated, color-coded splats and healing hearts. Includes replicated damage from multiplayer.");
		harmony.Patch((MethodBase)AccessTools.Method(typeof(Character), "Damage", (Type[])null, (Type[])null), new HarmonyMethod(typeof(SagaHitsPro), "EnemyContactHit", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
	}

	private static void EnemyContactHit(Character __instance, HitData __0)
	{
		//IL_0099: 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)
		if (!((Object)(object)instance == (Object)null) && instance.show.Value && instance.enemyHits.Value && !((Object)(object)Player.m_localPlayer == (Object)null) && __0 != null && !__instance.IsPlayer() && !__instance.IsTamed() && BaseAI.IsEnemy((Character)(object)Player.m_localPlayer, __instance))
		{
			if (instance.enemyContacts.Count >= 64)
			{
				instance.enemyContacts.RemoveAt(0);
			}
			instance.enemyContacts.Add(new EnemyContact
			{
				Target = __instance,
				Point = __0.m_point,
				Time = Time.unscaledTime,
				Critical = __instance.IsStaggering(),
				Poison = (__0.m_damage.m_poison > 0f)
			});
		}
	}

	private bool EnemyText(TextType type, Vector3 point, string text)
	{
		//IL_001a: 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_001f: Invalid comparison between Unknown and I4
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: Invalid comparison between Unknown and I4
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: Invalid comparison between Unknown and I4
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Invalid comparison between Unknown and I4
		//IL_005d: 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_0089: Unknown result type (might be due to invalid IL or missing references)
		//IL_008b: Invalid comparison between Unknown and I4
		//IL_00de: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
		//IL_0257: Unknown result type (might be due to invalid IL or missing references)
		//IL_025c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0266: Unknown result type (might be due to invalid IL or missing references)
		//IL_026b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0253: Unknown result type (might be due to invalid IL or missing references)
		//IL_0193: Unknown result type (might be due to invalid IL or missing references)
		//IL_0198: Unknown result type (might be due to invalid IL or missing references)
		//IL_0199: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
		if (!enemyHits.Value || (Object)(object)Player.m_localPlayer == (Object)null || ((int)type != 0 && (int)type != 1 && (int)type != 2 && (int)type != 7 && (int)type != 4))
		{
			return false;
		}
		if (!float.TryParse(text, NumberStyles.Float, CultureInfo.InvariantCulture, out var result) || result <= 0f || float.IsNaN(result) || float.IsInfinity(result))
		{
			return false;
		}
		if (Vector3.SqrMagnitude(point - ((Component)Player.m_localPlayer).transform.position) > 5625f)
		{
			return false;
		}
		Character val = null;
		bool flag = false;
		bool flag2 = false;
		bool flag3 = false;
		bool flag4 = (int)type == 4;
		for (int num = enemyContacts.Count - 1; num >= 0; num--)
		{
			EnemyContact enemyContact = enemyContacts[num];
			if (Time.unscaledTime - enemyContact.Time > 2.5f)
			{
				enemyContacts.RemoveAt(num);
			}
			else if (!flag4 && !flag && Vector3.SqrMagnitude(enemyContact.Point - point) < 0.16f)
			{
				val = enemyContact.Target;
				flag2 = enemyContact.Poison;
				flag3 = enemyContact.Critical;
				flag = true;
				enemyContacts.RemoveAt(num);
			}
		}
		if (!flag)
		{
			float num2 = 0.64f;
			foreach (Character allCharacter in Character.GetAllCharacters())
			{
				if ((Object)(object)allCharacter == (Object)null || allCharacter.IsPlayer() || allCharacter.IsTamed() || !BaseAI.IsEnemy((Character)(object)Player.m_localPlayer, allCharacter))
				{
					continue;
				}
				float num3 = allCharacter.GetHeight() + 2f;
				if (Vector3.SqrMagnitude(allCharacter.GetCenterPoint() - point) > num3 * num3)
				{
					continue;
				}
				Collider collider = (Collider)(object)allCharacter.GetCollider();
				if (!((Object)(object)collider == (Object)null) && collider.enabled)
				{
					Vector3 val2 = collider.ClosestPoint(point) - point;
					float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude;
					if (sqrMagnitude < num2)
					{
						num2 = sqrMagnitude;
						val = allCharacter;
					}
				}
			}
			flag = (Object)(object)val != (Object)null;
			if (flag && !flag4 && val.IsStaggering())
			{
				flag3 = !staggerTimes.TryGetValue(val, out var value) || Time.unscaledTime - value > 0.15f;
			}
		}
		if (!flag)
		{
			return false;
		}
		Add(result, ((Object)(object)val != (Object)null) ? (val.GetCenterPoint() + Vector3.up * 0.35f) : point, flag4 ? 6 : (flag2 ? 7 : 5), val, !flag4 && flag3);
		return true;
	}

	private void PatchStagger()
	{
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_005b: Expected O, but got Unknown
		showStaggers = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "Enemy Stagger Splats", true, "Rainbow STAGGERED splat for nearby hostile creatures when the replicated stagger animation begins.");
		harmony.Patch((MethodBase)AccessTools.Method(typeof(ZSyncAnimation), "RPC_SetTrigger", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(SagaHitsPro), "AfterAnimationTrigger", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
	}

	private static void AfterAnimationTrigger(ZSyncAnimation __instance, string __1)
	{
		//IL_007e: Unknown result type (might be due to invalid IL or missing references)
		//IL_008d: 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_00b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
		if (__1 != "stagger" || (Object)(object)instance == (Object)null || !instance.show.Value || !instance.showStaggers.Value || (Object)(object)Player.m_localPlayer == (Object)null)
		{
			return;
		}
		Character componentInParent = ((Component)__instance).GetComponentInParent<Character>();
		if ((Object)(object)componentInParent == (Object)null || componentInParent.IsPlayer() || componentInParent.IsDead() || !BaseAI.IsEnemy((Character)(object)Player.m_localPlayer, componentInParent) || Vector3.SqrMagnitude(((Component)componentInParent).transform.position - ((Component)Player.m_localPlayer).transform.position) > 5625f)
		{
			return;
		}
		Camera main = Camera.main;
		if ((Object)(object)main == (Object)null)
		{
			return;
		}
		Vector3 val = main.WorldToViewportPoint(componentInParent.GetCenterPoint());
		if (val.z <= 0f || val.x < 0f || val.x > 1f || val.y < 0f || val.y > 1f)
		{
			return;
		}
		if ((Object)(object)instance.owner != (Object)(object)Player.m_localPlayer)
		{
			instance.splashes.Clear();
			instance.staggerTimes.Clear();
			instance.owner = Player.m_localPlayer;
		}
		if (!instance.staggerTimes.TryGetValue(componentInParent, out var value) || !(Time.unscaledTime - value < 0.35f))
		{
			instance.staggerTimes[componentInParent] = Time.unscaledTime;
			if (instance.splashes.Count >= 32)
			{
				instance.splashes.RemoveAt(0);
			}
			instance.splashes.Add(new Splash
			{
				Position = componentInParent.GetCenterPoint(),
				Born = Time.unscaledTime,
				Lane = 0f,
				Kind = 4,
				Text = "STAGGERED!",
				Follow = componentInParent
			});
		}
	}

	private void PruneStaggers()
	{
		oldStaggers.Clear();
		foreach (KeyValuePair<Character, float> staggerTime in staggerTimes)
		{
			if ((Object)(object)staggerTime.Key == (Object)null || Time.unscaledTime - staggerTime.Value > 5f)
			{
				oldStaggers.Add(staggerTime.Key);
			}
		}
		foreach (Character oldStagger in oldStaggers)
		{
			staggerTimes.Remove(oldStagger);
		}
	}

	private static bool InsideHeart(float x, float y)
	{
		float num = (x - 0.5f) * 2.7f;
		float num2 = (y - 0.46f) * 2.7f;
		float num3 = num * num + num2 * num2 - 1f;
		return num3 * num3 * num3 - num * num * num2 * num2 * num2 <= 0f;
	}

	private void EnsureHeart()
	{
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Expected O, but got Unknown
		//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ae: Expected O, but got Unknown
		//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
		//IL_0204: 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_0164: Unknown result type (might be due to invalid IL or missing references)
		//IL_0149: Unknown result type (might be due to invalid IL or missing references)
		//IL_0121: Unknown result type (might be due to invalid IL or missing references)
		//IL_0106: Unknown result type (might be due to invalid IL or missing references)
		//IL_0169: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)heartTexture != (Object)null)
		{
			return;
		}
		heartTexture = new Texture2D(96, 96, (TextureFormat)4, false);
		((Texture)heartTexture).wrapMode = (TextureWrapMode)1;
		((Texture)heartTexture).filterMode = (FilterMode)1;
		Color[] array = (Color[])(object)new Color[9216];
		for (int i = 0; i < 96; i++)
		{
			for (int j = 0; j < 96; j++)
			{
				float num = ((float)j + 0.5f) / 96f;
				float num2 = ((float)i + 0.5f) / 96f;
				float num3 = 1f / 48f;
				bool flag = InsideHeart(num, num2);
				bool flag2 = !InsideHeart(num - num3, num2) || !InsideHeart(num + num3, num2) || !InsideHeart(num, num2 - num3) || !InsideHeart(num, num2 + num3);
				bool flag3 = InsideHeart(num - num3, num2) || InsideHeart(num + num3, num2) || InsideHeart(num, num2 - num3) || InsideHeart(num, num2 + num3);
				ref Color reference = ref array[i * 96 + j];
				reference = (Color)(flag ? (flag2 ? new Color(0.12f, 0.9f, 0.25f, 1f) : new Color(0.025f, 0.27f + 0.12f * num2, 0.055f, 0.95f)) : (flag3 ? new Color(0f, 0f, 0f, 0.95f) : Color.clear));
			}
		}
		heartTexture.SetPixels(array);
		heartTexture.Apply();
		enemyHeartTexture = new Texture2D(96, 96, (TextureFormat)4, false);
		((Texture)enemyHeartTexture).wrapMode = (TextureWrapMode)1;
		((Texture)enemyHeartTexture).filterMode = (FilterMode)1;
		for (int k = 0; k < array.Length; k++)
		{
			Color val = array[k];
			float grayscale = ((Color)(ref val)).grayscale;
			ref Color reference2 = ref array[k];
			reference2 = Color.Lerp(new Color(grayscale, grayscale, grayscale, val.a), val, 0.4f);
		}
		enemyHeartTexture.SetPixels(array);
		enemyHeartTexture.Apply();
	}

	private static Color StaggerColor(float age, float alpha)
	{
		//IL_0026: 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_0034: Unknown result type (might be due to invalid IL or missing references)
		Color result = Color.HSVToRGB(Mathf.Repeat(Mathf.Floor(age * 8f) / 7f, 1f), 0.85f, 1f);
		result.a = alpha;
		return result;
	}

	private void DrawStaggerBurst(float x, float y, Vector2 textSize, float age, float pop, float fade)
	{
		//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_0027: 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_0126: Unknown result type (might be due to invalid IL or missing references)
		//IL_012b: 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_016c: Unknown result type (might be due to invalid IL or missing references)
		Color val = StaggerColor(age, fade);
		GUI.color = new Color(val.r, val.g, val.b, fade * 0.85f);
		float num = textSize.x + 44f * pop;
		float num2 = textSize.y + 38f * pop;
		GUI.DrawTexture(new Rect(x - num * 0.5f, y - num2 * 0.5f, num, num2), (Texture)(object)burstTexture);
		float num3 = Mathf.Clamp01(age / 0.32f);
		float a = fade * Mathf.Clamp01(1f - age / 0.65f);
		for (int i = 0; i < 8; i++)
		{
			float num4 = (float)i * (float)Math.PI * 0.25f;
			float num5 = Mathf.Cos(num4) * (textSize.x * 0.5f + 10f + num3 * 24f);
			float num6 = Mathf.Sin(num4) * (textSize.y * 0.5f + 8f + num3 * 19f);
			Color color = Color.HSVToRGB(Mathf.Repeat(age * 0.8f + (float)i / 8f, 1f), 0.85f, 1f);
			color.a = a;
			GUI.color = color;
			float num7 = (float)((i % 2 == 0) ? 10 : 7) * pop;
			GUI.DrawTexture(new Rect(x + num5 - num7 * 0.5f, y + num6 - num7 * 0.5f, num7, num7), (Texture)(object)burstTexture);
		}
	}

	private ConfigEntry<float> Slider(string section, string key, float value, float min, float max, string help)
	{
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Expected O, but got Unknown
		return ((BaseUnityPlugin)this).Config.Bind<float>(section, key, value, new ConfigDescription(help, (AcceptableValueBase)(object)new AcceptableValueRange<float>(min, max), new object[0]));
	}

	private void BindHitOptions()
	{
		//IL_0214: Unknown result type (might be due to invalid IL or missing references)
		//IL_024d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0286: Unknown result type (might be due to invalid IL or missing references)
		//IL_02bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0331: Unknown result type (might be due to invalid IL or missing references)
		//IL_036a: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_03dc: Unknown result type (might be due to invalid IL or missing references)
		normalMin = Slider("Normal Splats", "Minimum Size", 0.55f, 0.25f, 3f, "Minimum whole-splat scale. 1 is the original 68 by 56 pixel backdrop; numbers fit inside it. Reversed minimum/maximum values are sorted at runtime.");
		normalMax = Slider("Normal Splats", "Maximum Size", 1f, 0.25f, 3f, "Maximum whole-splat scale, including the impact pop. Larger damage grows toward this cap.");
		critMin = Slider("Critical Splats", "Minimum Size", 0.65f, 0.25f, 3f, "Minimum critical splat scale, before the critical Size Multiplier. Reversed minimum/maximum values are sorted at runtime.");
		critMax = Slider("Critical Splats", "Maximum Size", 1.18f, 0.25f, 3f, "Maximum critical splat scale, including the impact pop, before Size Multiplier.");
		critSize = Slider("Critical Splats", "Size Multiplier", 1f, 0.5f, 2f, "Enlarge or shrink all critical splats, multiplying both size limits. Updates live.");
		critPop = Slider("Critical Splats", "Impact Pop", 0.28f, 0f, 1f, "Initial expansion strength; the selected maximum size still caps the result.");
		critShake = Slider("Critical Splats", "Shake Strength", 4f, 0f, 12f, "Initial shake in screen pixels; 0 disables it. Incoming crits use 75 percent of this amount.");
		critRise = Slider("Critical Splats", "Rise Distance", 110f, 20f, 250f, "How far critical hits rise straight up the target center in screen pixels.");
		fountain = ((BaseUnityPlugin)this).Config.Bind<bool>("Motion", "Fountain Normal Hits", true, "Normal damage and blocked-zero splats alternate left/right per target and follow an arc. Critical hits rise up the center. Healing hearts and STAGGERED keep their existing motion.");
		fountainWidth = Slider("Motion", "Fountain Spread", 70f, 0f, 220f, "Horizontal travel on each side, in screen pixels.");
		fountainHeight = Slider("Motion", "Fountain Arc Height", 65f, 10f, 180f, "Upward height of the normal-hit arc in screen pixels.");
		fountainDrop = Slider("Motion", "Fountain End Drop", 25f, 0f, 150f, "How far below the launch point a normal hit finishes as it fades.");
		ownDamage = ((BaseUnityPlugin)this).Config.Bind<Color>("Colors", "Your Damage", new Color(1f, 0.08f, 0.055f, 1f), "Normal damage taken by your character: text and splat tint.");
		enemyDamage = ((BaseUnityPlugin)this).Config.Bind<Color>("Colors", "Enemy Damage", new Color(0.78f, 0.47f, 0.45f, 1f), "Normal damage shown on enemies: text and splat tint.");
		ownCrit = ((BaseUnityPlugin)this).Config.Bind<Color>("Colors", "Your Critical Damage", new Color(1f, 0.55f, 0.04f, 1f), "Incoming damage while your character is staggered. This visual classification does not change game damage.");
		enemyCrit = ((BaseUnityPlugin)this).Config.Bind<Color>("Colors", "Enemy Critical Damage", new Color(1f, 0.95f, 0.08f, 1f), "Critical/stagger damage shown on enemies; defaults to vivid yellow.");
		ownPoison = ((BaseUnityPlugin)this).Config.Bind<Color>("Colors", "Your Poison Damage", new Color(0.35f, 1f, 0.07f, 1f), "Poison damage on your character.");
		enemyPoison = ((BaseUnityPlugin)this).Config.Bind<Color>("Colors", "Enemy Poison Damage", new Color(0.51f, 0.76f, 0.54f, 1f), "Poison damage on enemies.");
		blockedColor = ((BaseUnityPlugin)this).Config.Bind<Color>("Colors", "Blocked Zero", new Color(0.15f, 0.72f, 1f, 1f), "Zero-damage blocked splats.");
		ownHealText = ((BaseUnityPlugin)this).Config.Bind<Color>("Colors", "Your Healing Text", new Color(0.18f, 1f, 0.25f, 1f), "Numbers inside your healing hearts. Heart artwork remains green.");
		enemyHealText = ((BaseUnityPlugin)this).Config.Bind<Color>("Colors", "Enemy Healing Text", new Color(0.51f, 0.76f, 0.54f, 1f), "Numbers inside enemy healing hearts. Heart artwork remains muted green.");
		previewSamples = ((BaseUnityPlugin)this).Config.Bind<bool>("Preview", "Show Samples While F1 Is Open", false, "Cycle normal/critical incoming and enemy samples while configuration is open in a loaded game. Visual only: no damage, XP, or combat reports. Samples clear when you close F1 or disable this.");
	}

	private static bool IsDamageKind(int kind)
	{
		if (kind != 0 && kind != 1 && kind != 5 && kind != 7)
		{
			return kind == 8;
		}
		return true;
	}

	private Color SplatColor(Splash splash, float fade)
	{
		//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_00f7: 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_00c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ab: 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)
		//IL_0091: 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_0077: Unknown result type (might be due to invalid IL or missing references)
		bool flag = splash.Kind == 0 || splash.Kind == 1 || (splash.Kind == 8 && (Object)(object)splash.Follow == (Object)(object)Player.m_localPlayer);
		Color result = ((splash.Kind == 8) ? blockedColor.Value : ((!splash.Critical) ? ((splash.Kind == 0) ? ownDamage.Value : ((splash.Kind == 1) ? ownPoison.Value : ((splash.Kind == 5) ? enemyDamage.Value : ((splash.Kind == 7) ? enemyPoison.Value : ((splash.Kind == 2) ? ownHealText.Value : enemyHealText.Value))))) : (flag ? ownCrit.Value : enemyCrit.Value)));
		result.a *= fade;
		return result;
	}

	private void UpdatePreview()
	{
		if (!previewSamples.Value || !SagaConfigPreview.Open)
		{
			splashes.RemoveAll((Splash s) => s.Preview);
			nextPreview = 0f;
		}
		else if (!(Time.unscaledTime < nextPreview) && splashes.Count < 32)
		{
			nextPreview = Time.unscaledTime + 0.65f;
			int num = previewSequence++ % 6;
			bool flag = num == 2 || num == 5;
			int num2 = ((num >= 3) ? 5 : 0);
			float amount = (flag ? 80 : ((num % 3 == 0) ? 12 : 40));
			splashes.Add(new Splash
			{
				Born = Time.unscaledTime,
				Kind = num2,
				Amount = amount,
				Critical = flag,
				Preview = true,
				FountainSide = fountainLanes.Next((num2 == 0) ? int.MinValue : (-2147483647), Time.unscaledTime, flag),
				Text = ((num2 == 0) ? "-" : "") + amount.ToString("0")
			});
		}
	}

	private void Awake()
	{
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Expected O, but got Unknown
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: Expected O, but got Unknown
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: Expected O, but got Unknown
		//IL_0054: Unknown result type (might be due to invalid IL or missing references)
		//IL_005e: Expected O, but got Unknown
		//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00da: Expected O, but got Unknown
		//IL_010f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0119: Expected O, but got Unknown
		//IL_0145: Unknown result type (might be due to invalid IL or missing references)
		//IL_014f: Expected O, but got Unknown
		//IL_0184: Unknown result type (might be due to invalid IL or missing references)
		//IL_018e: Expected O, but got Unknown
		//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cd: Expected O, but got Unknown
		//IL_01de: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e8: Expected O, but got Unknown
		//IL_0220: Unknown result type (might be due to invalid IL or missing references)
		//IL_0237: Unknown result type (might be due to invalid IL or missing references)
		//IL_0242: Expected O, but got Unknown
		//IL_0242: Expected O, but got Unknown
		//IL_026f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0286: Unknown result type (might be due to invalid IL or missing references)
		//IL_0291: Expected O, but got Unknown
		//IL_0291: Expected O, but got Unknown
		//IL_02be: Unknown result type (might be due to invalid IL or missing references)
		//IL_02cc: Expected O, but got Unknown
		instance = this;
		personalLayout = new SagaEffectLayout(((BaseUnityPlugin)this).Config, "Your Hits Layout");
		enemyLayout = new SagaEffectLayout(((BaseUnityPlugin)this).Config, "Enemy Hits Layout");
		healingLayout = new SagaEffectLayout(((BaseUnityPlugin)this).Config, "Healing Layout");
		staggerLayout = new SagaEffectLayout(((BaseUnityPlugin)this).Config, "Stagger Layout");
		show = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "Enabled", true, "Show damage taken as red hitsplats rising from your character.");
		burst = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "Burst Backdrop", true, "Dark-red jagged hitsplat behind the outlined red number.");
		duration = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "Duration", 1.6f, new ConfigDescription("Seconds before a hitsplat fades out.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 4f), new object[0]));
		rise = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "Rise", 85f, new ConfigDescription("How many screen pixels the damage number rises.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(20f, 180f), new object[0]));
		fontSize = ((BaseUnityPlugin)this).Config.Bind<int>("Display", "Font Size", 28, new ConfigDescription("Damage number size.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(16, 48), new object[0]));
		maxHeartHeal = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "Healing Amount For Maximum Heart", 30f, new ConfigDescription("Actual HP restored at which the healing heart reaches its previous full size. Smaller heals use smaller hearts.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 500f), new object[0]));
		maxSplatDamage = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "Damage For Maximum Splat", 100f, new ConfigDescription("Damage at which splats reach the configured maximum size. Normal and critical size limits are configured separately.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 2000f), new object[0]));
		BindHitOptions();
		harmony = new Harmony("local.mmc.sagahits");
		PatchStagger();
		PatchEnemyHits();
		harmony.Patch((MethodBase)AccessTools.Method(typeof(Character), "ApplyDamage", (Type[])null, (Type[])null), new HarmonyMethod(typeof(SagaHitsPro), "BeforeDamage", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(SagaHitsPro), "AfterDamage", (Type[])null), (HarmonyMethod)null);
		harmony.Patch((MethodBase)AccessTools.Method(typeof(Character), "RPC_Heal", (Type[])null, (Type[])null), new HarmonyMethod(typeof(SagaHitsPro), "BeforeHeal", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(typeof(SagaHitsPro), "AfterHeal", (Type[])null), (HarmonyMethod)null);
		harmony.Patch((MethodBase)AccessTools.Method(typeof(DamageText), "AddInworldText", (Type[])null, (Type[])null), new HarmonyMethod(typeof(SagaHitsPro), "NativeText", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		((BaseUnityPlugin)this).Logger.LogInfo((object)"SagaHitsPro enabled: actual local-player HP loss, red outlined hitsplats.");
	}

	private static void BeforeDamage(Character __instance, HitData __0, out Capture __state)
	{
		//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_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_007b: Unknown result type (might be due to invalid IL or missing references)
		__state = null;
		if (!((Object)(object)instance == (Object)null) && instance.show.Value && !((Object)(object)Player.m_localPlayer == (Object)null) && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer))
		{
			__state = new Capture
			{
				Target = __instance,
				Before = Mathf.Max(0f, __instance.GetHealth()),
				Position = __instance.GetCenterPoint() + Vector3.up * 0.35f,
				Critical = (__instance.IsStaggering() && __0 != null && (Object)(object)__0.GetAttacker() != (Object)null),
				Poison = (__0 != null && __0.m_damage.m_poison > 0f)
			};
			captures.Add(__state);
		}
	}

	private static Exception AfterDamage(Exception __exception, Capture __state)
	{
		//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
		if (__state == null)
		{
			return __exception;
		}
		captures.Remove(__state);
		if (__exception != null || (Object)(object)instance == (Object)null || (Object)(object)__state.Target == (Object)null)
		{
			return __exception;
		}
		try
		{
			float num = Mathf.Max(0f, __state.Before - Mathf.Max(0f, __state.Target.GetHealth()));
			for (int num2 = captures.Count - 1; num2 >= 0; num2--)
			{
				if ((Object)(object)captures[num2].Target == (Object)(object)__state.Target)
				{
					captures[num2].Nested += num;
					break;
				}
			}
			float num3 = Mathf.Max(0f, num - __state.Nested);
			if (num3 > 0.0001f && !float.IsNaN(num3) && !float.IsInfinity(num3))
			{
				instance.Add(num3, __state.Position, __state.Poison ? 1 : 0, __state.Target, __state.Critical);
			}
		}
		catch
		{
			((BaseUnityPlugin)instance).Logger.LogDebug((object)"Skipped an unavailable damage visual.");
		}
		return __exception;
	}

	private void Add(float damage, Vector3 position, int kind, Character follow = null, bool critical = false)
	{
		//IL_012c: 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)
		if ((Object)(object)owner != (Object)(object)Player.m_localPlayer)
		{
			splashes.Clear();
			fountainLanes.Clear();
			pendingStaminaLoss = 0f;
			owner = Player.m_localPlayer;
		}
		if (splashes.Count >= 32)
		{
			int num = splashes.FindIndex((Splash s) => s.Kind >= 5);
			if (num < 0 && kind >= 5)
			{
				return;
			}
			splashes.RemoveAt((num >= 0) ? num : 0);
		}
		int num2 = sequence++ % ((kind < 2) ? 3 : 5);
		float lane = ((num2 != 0) ? (((num2 % 2 != 1) ? 1 : (-1)) * ((num2 + 1) / 2)) : 0);
		Character val = (Character)(((Object)(object)follow != (Object)null) ? ((object)follow) : ((object)((kind < 2) ? Player.m_localPlayer : null)));
		int fountainSide = (IsDamageKind(kind) ? fountainLanes.Next(((Object)(object)val != (Object)null) ? ((Object)val).GetInstanceID() : 0, Time.unscaledTime, critical) : 0);
		splashes.Add(new Splash
		{
			FountainSide = fountainSide,
			Position = position,
			Born = Time.unscaledTime,
			Lane = lane,
			Kind = kind,
			Amount = damage,
			Critical = critical,
			Follow = (Character)(((Object)(object)follow != (Object)null) ? ((object)follow) : ((object)((kind < 2) ? Player.m_localPlayer : null))),
			Text = ((kind == 8) ? "0" : (((kind == 2 || kind == 6) ? "+" : ((kind >= 5) ? "" : "-")) + ((damage < 1f) ? Mathf.Max(0.1f, damage).ToString("0.0", CultureInfo.InvariantCulture) : damage.ToString("0.#", CultureInfo.InvariantCulture)) + ((kind == 3) ? " max stamina" : "")))
		});
	}

	private static float FoodStamina(Player player)
	{
		float num = 0f;
		foreach (Food food in player.GetFoods())
		{
			num += food.m_stamina;
		}
		return num;
	}

	private static void BeforeFood(Player __instance, bool __1, out FoodSnapshot __state)
	{
		__state = default(FoodSnapshot);
		if (!((Object)(object)instance == (Object)null) && instance.show.Value && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && !((Character)__instance).IsDead() && !__1)
		{
			if ((Object)(object)instance.owner != (Object)(object)__instance)
			{
				instance.splashes.Clear();
				instance.pendingStaminaLoss = 0f;
				instance.owner = __instance;
			}
			__state.Valid = true;
			__state.Maximum = ((Character)__instance).GetMaxStamina();
			__state.FoodStamina = FoodStamina(__instance);
		}
	}

	private static void AfterFood(Player __instance, FoodSnapshot __state)
	{
		//IL_00ba: 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_00c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)instance == (Object)null || !__state.Valid || ((Character)__instance).IsDead())
		{
			return;
		}
		float num = __state.FoodStamina - FoodStamina(__instance);
		float num2 = __state.Maximum - ((Character)__instance).GetMaxStamina();
		if (!(num <= 0f) && !(num2 <= 0f) && !float.IsNaN(num2) && !float.IsInfinity(num2))
		{
			instance.pendingStaminaLoss += Mathf.Min(num, num2);
			int num3 = Mathf.FloorToInt(instance.pendingStaminaLoss + 1E-05f);
			if (num3 >= 1)
			{
				instance.pendingStaminaLoss = Mathf.Max(0f, instance.pendingStaminaLoss - (float)num3);
				instance.Add(num3, ((Character)__instance).GetCenterPoint() + Vector3.up * 0.15f, 3);
			}
		}
	}

	private static bool NativeText(TextType __0, Vector3 __1, string __3, bool __4)
	{
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: 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_003c: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)instance == (Object)null || !instance.show.Value)
		{
			return true;
		}
		if (instance.BlueBlock(__0, __1, __3))
		{
			return false;
		}
		if (__4)
		{
			return false;
		}
		return !instance.EnemyText(__0, __1, __3);
	}

	private static void BeforeHeal(Character __instance, out Capture __state)
	{
		//IL_0058: 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_0067: 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_0071: Unknown result type (might be due to invalid IL or missing references)
		__state = null;
		if (!((Object)(object)instance == (Object)null) && instance.show.Value && !((Object)(object)Player.m_localPlayer == (Object)null) && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer))
		{
			__state = new Capture
			{
				Target = __instance,
				Before = __instance.GetHealth(),
				Position = __instance.GetCenterPoint() + Vector3.up * 0.65f
			};
			heals.Add(__state);
		}
	}

	private static Exception AfterHeal(Exception __exception, Capture __state)
	{
		//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
		if (__state == null)
		{
			return __exception;
		}
		heals.Remove(__state);
		if (__exception != null || (Object)(object)instance == (Object)null || (Object)(object)__state.Target == (Object)null)
		{
			return __exception;
		}
		try
		{
			float num = Mathf.Max(0f, __state.Target.GetHealth() - __state.Before);
			for (int num2 = heals.Count - 1; num2 >= 0; num2--)
			{
				if ((Object)(object)heals[num2].Target == (Object)(object)__state.Target)
				{
					heals[num2].Nested += num;
					break;
				}
			}
			float num3 = Mathf.Max(0f, num - __state.Nested);
			if (num3 > 0.0001f && !float.IsNaN(num3) && !float.IsInfinity(num3))
			{
				instance.Add(num3, __state.Position, 2);
			}
		}
		catch
		{
			((BaseUnityPlugin)instance).Logger.LogDebug((object)"Skipped an unavailable healing visual.");
		}
		return __exception;
	}

	private void Update()
	{
		if (!show.Value || (Object)(object)owner != (Object)(object)Player.m_localPlayer || (Object)(object)Player.m_localPlayer == (Object)null)
		{
			splashes.Clear();
			fountainLanes.Clear();
			enemyContacts.Clear();
			pendingStaminaLoss = 0f;
			owner = Player.m_localPlayer;
		}
		else
		{
			UpdatePreview();
			PruneStaggers();
			float now = Time.unscaledTime;
			splashes.RemoveAll((Splash splash) => now - splash.Born >= ((splash.Kind == 4) ? (duration.Value * 0.5f) : duration.Value));
		}
	}

	private void EnsureStyle()
	{
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Expected O, but got Unknown
		//IL_002f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Expected O, but got Unknown
		//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
		//IL_0107: Expected O, but got Unknown
		//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
		//IL_01dc: 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)
		if (style == null)
		{
			style = new GUIStyle(GUI.skin.label);
			style.alignment = (TextAnchor)4;
			style.padding = new RectOffset();
			style.fontStyle = (FontStyle)1;
			style.richText = false;
			style.wordWrap = false;
		}
		if (clockStyle == null && Chainloader.PluginInfos.TryGetValue("Azumatt.AzuClock", out var value))
		{
			clockStyle = AccessTools.Field(((object)value.Instance).GetType(), "Style");
		}
		GUIStyle val = (GUIStyle)((clockStyle == null) ? null : /*isinst with value type is only supported in some contexts*/);
		style.font = ((val == null) ? GUI.skin.label.font : val.font);
		EnsureHeart();
		if ((Object)(object)burstTexture != (Object)null)
		{
			return;
		}
		burstTexture = new Texture2D(64, 64, (TextureFormat)4, false);
		((Texture)burstTexture).wrapMode = (TextureWrapMode)1;
		Color[] array = (Color[])(object)new Color[4096];
		for (int i = 0; i < 64; i++)
		{
			for (int j = 0; j < 64; j++)
			{
				float num = ((float)j - 31.5f) / 31.5f;
				float num2 = ((float)i - 31.5f) / 31.5f;
				float num3 = Mathf.Atan2(num2, num);
				float num4 = Mathf.Sqrt(num * num + num2 * num2);
				float num5 = 0.71f + 0.12f * Mathf.Cos(num3 * 8f) + 0.055f * Mathf.Cos(num3 * 13f);
				float num6 = Mathf.Clamp01((num5 - num4) * 32f);
				ref Color reference = ref array[i * 64 + j];
				reference = ((num4 > num5 - 0.075f) ? new Color(0.015f, 0f, 0f, num6 * 0.9f) : new Color(0.29f, 0.29f, 0.29f, num6 * 0.85f));
			}
		}
		burstTexture.SetPixels(array);
		burstTexture.Apply();
	}

	private void OnGUI()
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Invalid comparison between Unknown and I4
		//IL_0c21: Unknown result type (might be due to invalid IL or missing references)
		//IL_0c27: 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_005e: Unknown result type (might be due to invalid IL or missing references)
		//IL_005f: 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_009a: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_0249: Unknown result type (might be due to invalid IL or missing references)
		//IL_024b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0250: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_021e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0223: Unknown result type (might be due to invalid IL or missing references)
		//IL_028a: Unknown result type (might be due to invalid IL or missing references)
		//IL_028c: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_02cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_02dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_02df: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_073c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0746: Expected O, but got Unknown
		//IL_0741: Unknown result type (might be due to invalid IL or missing references)
		//IL_0746: Unknown result type (might be due to invalid IL or missing references)
		//IL_0857: Unknown result type (might be due to invalid IL or missing references)
		//IL_0893: Unknown result type (might be due to invalid IL or missing references)
		//IL_096b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0975: Expected O, but got Unknown
		//IL_0970: Unknown result type (might be due to invalid IL or missing references)
		//IL_0975: Unknown result type (might be due to invalid IL or missing references)
		//IL_07f0: Unknown result type (might be due to invalid IL or missing references)
		//IL_07fa: Expected O, but got Unknown
		//IL_07f5: Unknown result type (might be due to invalid IL or missing references)
		//IL_07fa: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a73: Unknown result type (might be due to invalid IL or missing references)
		//IL_09fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a2b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0ade: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a8c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a96: Expected O, but got Unknown
		//IL_0999: Unknown result type (might be due to invalid IL or missing references)
		//IL_09a3: Expected O, but got Unknown
		//IL_099e: Unknown result type (might be due to invalid IL or missing references)
		//IL_09a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b1f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b29: Unknown result type (might be due to invalid IL or missing references)
		//IL_0bda: Unknown result type (might be due to invalid IL or missing references)
		//IL_0be4: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b6d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0bce: Unknown result type (might be due to invalid IL or missing references)
		if ((int)Event.current.type != 7 || !show.Value || splashes.Count == 0 || (Object)(object)Player.m_localPlayer == (Object)null || SagaConfigPreview.MenuVisible() || SagaConfigPreview.MapVisible())
		{
			return;
		}
		Camera main = Camera.main;
		if ((Object)(object)main == (Object)null)
		{
			return;
		}
		EnsureStyle();
		Color color = GUI.color;
		Matrix4x4 matrix = GUI.matrix;
		try
		{
			Vector3 val2 = default(Vector3);
			Vector2 val3 = default(Vector2);
			Rect val5 = default(Rect);
			for (int i = 0; i < 2; i++)
			{
				foreach (Splash splash in splashes)
				{
					if (splash.Kind == 4 != (i == 0))
					{
						continue;
					}
					GUI.matrix = matrix;
					SagaEffectLayout val = ((splash.Kind == 4) ? staggerLayout : ((splash.Kind == 2 || splash.Kind == 6) ? healingLayout : ((splash.Kind == 5 || splash.Kind == 7) ? enemyLayout : personalLayout)));
					if (!val.Visible)
					{
						continue;
					}
					float num = Time.unscaledTime - splash.Born;
					float num2 = Mathf.Clamp01(num / ((splash.Kind == 4) ? (duration.Value * 0.5f) : duration.Value));
					if (splash.Kind == 4 && (Object)(object)splash.Follow == (Object)null)
					{
						continue;
					}
					bool flag = splash.Kind == 0 || splash.Kind == 1 || (splash.Kind == 8 && (Object)(object)splash.Follow == (Object)(object)Player.m_localPlayer);
					if ((Object)(object)splash.Follow != (Object)null)
					{
						splash.Position = splash.Follow.GetCenterPoint() + Vector3.up * (flag ? 0.1f : 0.35f);
					}
					Vector3 position = splash.Position;
					if (splash.Preview)
					{
						((Vector3)(ref val2))..ctor((float)Screen.width * 0.72f, (float)Screen.height * 0.48f, 1f);
					}
					else if (splash.Kind == 2)
					{
						if (!MMCCharacterPanel.HealthBarVisible)
						{
							continue;
						}
						Vector2 healingPopupScreenPosition = MMCCharacterPanel.HealingPopupScreenPosition;
						((Vector3)(ref val2))..ctor(healingPopupScreenPosition.x, (float)Screen.height - healingPopupScreenPosition.y, 1f);
					}
					else
					{
						val2 = main.WorldToScreenPoint(position);
					}
					if (val2.z <= 0f)
					{
						continue;
					}
					if (flag)
					{
						((Vector2)(ref val3))..ctor(val2.x, val2.y);
						if (!splash.HasScreenAnchor)
						{
							splash.ScreenAnchor = val3;
							splash.HasScreenAnchor = true;
						}
						if (splash.AnchorFrame != Time.frameCount)
						{
							splash.ScreenAnchor = Vector2.Lerp(splash.ScreenAnchor, val3, 1f - Mathf.Exp(-18f * Time.unscaledDeltaTime));
							splash.ScreenAnchor = val3 + Vector2.ClampMagnitude(splash.ScreenAnchor - val3, 32f);
							splash.AnchorFrame = Time.frameCount;
						}
						val2.x = splash.ScreenAnchor.x;
						val2.y = splash.ScreenAnchor.y;
					}
					float num3 = (flag ? 0.75f : 0.6f);
					float num4 = ((num2 < num3) ? 1f : (1f - (num2 - num3) / (1f - num3)));
					float num5 = 1f + 0.28f * Mathf.Sin(Mathf.Clamp01(num / 0.22f) * (float)Math.PI);
					if (splash.Kind == 2 || splash.Kind == 6)
					{
						num5 = 1f + 0.22f * Mathf.Exp(0f - Mathf.Pow((num - 0.1f) / 0.065f, 2f)) + 0.13f * Mathf.Exp(0f - Mathf.Pow((num - 0.29f) / 0.07f, 2f));
					}
					float num6 = val2.x + (flag ? (splash.Lane * (22f + 7f * num2) + Mathf.Sin(num * 4f + splash.Lane) * 3f) : ((splash.Kind == 2) ? (splash.Lane * 8f * num2) : (splash.Lane * (18f + 16f * num2))));
					float num7 = (float)Screen.height - val2.y - (flag ? (22f * (1f - Mathf.Exp(-2f * num2))) : (rise.Value * num2));
					bool flag2 = flag || splash.Kind == 5 || splash.Kind == 7 || splash.Kind == 8;
					if (flag2)
					{
						if (splash.Critical)
						{
							num5 = 1f + critPop.Value * Mathf.Sin(Mathf.Clamp01(num / 0.22f) * (float)Math.PI);
							SagaHitMotion.Offset offset = SagaHitMotion.Critical(num2, critRise.Value);
							num6 = val2.x + offset.X;
							num7 = (float)Screen.height - val2.y + offset.Y;
						}
						else if (fountain.Value)
						{
							SagaHitMotion.Offset offset2 = SagaHitMotion.Fountain(num2, splash.FountainSide, fountainWidth.Value, fountainHeight.Value, fountainDrop.Value);
							num6 = val2.x + offset2.X;
							num7 = (float)Screen.height - val2.y + offset2.Y;
						}
					}
					float num8 = (flag2 ? (SagaHitMotion.Size(splash.Amount, maxSplatDamage.Value, splash.Critical ? critMin.Value : normalMin.Value, splash.Critical ? critMax.Value : normalMax.Value, splash.Critical ? critSize.Value : 1f, num5) / num5) : 1f);
					if (splash.Critical && flag2)
					{
						float num9 = SagaHitSizing.Shake(num) * (critShake.Value / 4f) * (flag ? 0.75f : 1f);
						num6 += Mathf.Sin(num * 95f) * num9;
						num7 += Mathf.Cos(num * 113f) * num9 * 0.65f;
					}
					val.Anchor(ref num6, ref num7, val2.x, (float)Screen.height - val2.y);
					val.ScaleAt(num6, num7, (float)((splash.Kind == 4) ? 180 : 68), (float)((splash.Kind == 4) ? 80 : 56));
					style.fontSize = Mathf.RoundToInt((float)fontSize.Value * num5 * num8 * ((splash.Kind == 3) ? 0.75f : ((splash.Kind >= 5) ? 0.85f : 1f)));
					Vector2 val4 = style.CalcSize(new GUIContent(splash.Text));
					((Rect)(ref val5))..ctor(num6 - val4.x * 0.5f - 8f, num7 - val4.y * 0.5f - 4f, val4.x + 16f, val4.y + 8f);
					if (flag2)
					{
						float num10 = 68f * num5 * num8 * 0.72f - 4f;
						float num11 = 56f * num5 * num8 * 0.5f - 4f;
						while (style.fontSize > 6 && (val4.x > num10 || val4.y > num11))
						{
							GUIStyle obj = style;
							obj.fontSize -= 1;
							val4 = style.CalcSize(new GUIContent(splash.Text));
						}
						((Rect)(ref val5))..ctor(num6 - num10 * 0.5f, num7 - num11 * 0.5f, num10, num11);
					}
					if (burst.Value && flag2)
					{
						GUI.color = SplatColor(splash, num4);
						GUI.DrawTexture(new Rect(num6 - 34f * num5 * num8, num7 - 28f * num5 * num8, 68f * num5 * num8, 56f * num5 * num8), (Texture)(object)burstTexture);
					}
					if (splash.Kind == 2 || splash.Kind == 6)
					{
						float num12 = Mathf.Lerp(0.55f, 1f, Mathf.Sqrt(Mathf.Clamp01(splash.Amount / maxHeartHeal.Value)));
						if (splash.Kind == 6)
						{
							num12 *= 0.85f;
						}
						float num13 = 84f * num5 * num12;
						float num14 = 72f * num5 * num12;
						float num15 = num13 * 0.64f - 4f;
						float num16 = num14 * 0.36f - 4f;
						style.fontSize = Mathf.Max(6, Mathf.RoundToInt((float)fontSize.Value * num5 * num12));
						val4 = style.CalcSize(new GUIContent(splash.Text));
						while (style.fontSize > 6 && (val4.x > num15 || val4.y > num16))
						{
							GUIStyle obj2 = style;
							obj2.fontSize -= 1;
							val4 = style.CalcSize(new GUIContent(splash.Text));
						}
						((Rect)(ref val5))..ctor(num6 - num15 * 0.5f, num7 - num16 * 0.5f, num15, num16);
						GUI.color = new Color(1f, 1f, 1f, num4);
						GUI.DrawTexture(new Rect(num6 - num13 * 0.5f, num7 - num14 * 0.5f + 4f * num5 * num12, num13, num14), (Texture)(object)((splash.Kind == 6) ? enemyHeartTexture : heartTexture));
					}
					if (splash.Kind == 4)
					{
						DrawComicStagger(num6, num7, splash.Text, num, num5, num4);
						continue;
					}
					GUI.color = Color.white;
					if (shadowStyle == null)
					{
						shadowStyle = new GUIStyle(style);
					}
					shadowStyle.font = style.font;
					shadowStyle.fontSize = style.fontSize;
					shadowStyle.normal.textColor = new Color(0f, 0f, 0f, num4);
					if (flag2 || splash.Kind == 2 || splash.Kind == 6)
					{
						shadowStyle.normal.textColor = new Color(0f, 0f, 0f, SplatColor(splash, num4).a);
					}
					for (int j = -1; j <= 1; j++)
					{
						for (int k = -1; k <= 1; k++)
						{
							if (k != 0 || j != 0)
							{
								GUI.Label(new Rect(((Rect)(ref val5)).x + (float)(k * 2), ((Rect)(ref val5)).y + (float)(j * 2), ((Rect)(ref val5)).width, ((Rect)(ref val5)).height), splash.Text, shadowStyle);
							}
						}
					}
					style.normal.textColor = (Color)((flag2 || splash.Kind == 2 || splash.Kind == 6) ? SplatColor(splash, num4) : new Color(1f, 0.72f, 0.18f, num4));
					GUI.Label(val5, splash.Text, style);
				}
			}
		}
		finally
		{
			GUI.color = color;
			GUI.matrix = matrix;
		}
	}

	private void OnDestroy()
	{
		if (harmony != null)
		{
			harmony.UnpatchSelf();
		}
		if ((Object)(object)burstTexture != (Object)null)
		{
			Object.Destroy((Object)(object)burstTexture);
		}
		if ((Object)(object)comicTexture != (Object)null)
		{
			Object.Destroy((Object)(object)comicTexture);
		}
		if (hologramFrames != null)
		{
			Texture2D[] array = hologramFrames;
			foreach (Texture2D val in array)
			{
				if ((Object)(object)val != (Object)null)
				{
					Object.Destroy((Object)(object)val);
				}
			}
		}
		if ((Object)(object)heartTexture != (Object)null)
		{
			Object.Destroy((Object)(object)heartTexture);
		}
		if ((Object)(object)enemyHeartTexture != (Object)null)
		{
			Object.Destroy((Object)(object)enemyHeartTexture);
		}
		fountainLanes.Clear();
		staggerTimes.Clear();
		captures.Clear();
		heals.Clear();
		splashes.Clear();
		if ((Object)(object)instance == (Object)(object)this)
		{
			instance = null;
		}
	}
}
internal static class SagaConfigPreview
{
	private static BaseUnityPlugin manager;

	private static PropertyInfo displaying;

	private static float retry;

	private static int frame = -1;

	private static bool open;

	internal static bool Open
	{
		get
		{
			if (frame == Time.frameCount)
			{
				return open;
			}
			frame = Time.frameCount;
			open = false;
			if ((Object)(object)manager == (Object)null && Time.unscaledTime >= retry)
			{
				retry = Time.unscaledTime + 2f;
				if (Chainloader.PluginInfos.TryGetValue("com.bepis.bepinex.configurationmanager", out var value))
				{
					manager = value.Instance;
					displaying = ((object)manager).GetType().GetProperty("DisplayingWindow", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				}
			}
			if ((Object)(object)manager != (Object)null && displaying != null)
			{
				try
				{
					open = (bool)displaying.GetValue(manager, null);
				}
				catch
				{
					open = false;
				}
			}
			return open;
		}
	}

	internal static bool HudVisible(Hud hud)
	{
		if ((Object)(object)hud != (Object)null)
		{
			if (!Open)
			{
				return hud.IsVisible();
			}
			return true;
		}
		return false;
	}

	internal static bool MenuVisible()
	{
		if (!Open)
		{
			return Menu.IsVisible();
		}
		return false;
	}

	internal static bool MapVisible()
	{
		if (!Open)
		{
			return Minimap.IsOpen();
		}
		return false;
	}

	internal static bool StoreVisible()
	{
		if (!Open)
		{
			return StoreGui.IsVisible();
		}
		return false;
	}

	internal static bool InventoryHidesHud()
	{
		if (!Open)
		{
			return InventoryGui.IsVisible();
		}
		return false;
	}
}
public static class SagaHitMotion
{
	public struct Offset
	{
		public float X;

		public float Y;

		public Offset(float x, float y)
		{
			X = x;
			Y = y;
		}
	}

	private static float Clamp(float value, float lo, float hi)
	{
		return Math.Max(lo, Math.Min(hi, value));
	}

	public static float Size(float damage, float threshold, float minimum, float maximum, float multiplier, float pop)
	{
		if (float.IsNaN(damage) || float.IsInfinity(damage) || damage < 0f)
		{
			damage = 0f;
		}
		float num = Math.Min(minimum, maximum) * multiplier;
		float num2 = Math.Max(minimum, maximum) * multiplier;
		float num3 = Clamp(damage / Math.Max(1f, threshold), 0f, 1f);
		float num4 = num + (num2 - num) * (float)Math.Sqrt(num3);
		return Clamp(num4 * pop, num, num2);
	}

	public static Offset Fountain(float progress, float side, float spread, float height, float drop)
	{
		float num = Clamp(progress, 0f, 1f);
		return new Offset((float)((!(side < 0f)) ? 1 : (-1)) * (12f + spread * num), -4f * height * num * (1f - num) + drop * num * num);
	}

	public static Offset Critical(float progress, float height)
	{
		return new Offset(0f, (0f - height) * Clamp(progress, 0f, 1f));
	}
}
public sealed class SagaHitLanes
{
	private sealed class State
	{
		public bool Right;

		public double Last;
	}

	private readonly Dictionary<int, State> targets = new Dictionary<int, State>();

	public int Count => targets.Count;

	public void Clear()
	{
		targets.Clear();
	}

	public int Next(int target, double now, bool critical)
	{
		if (critical)
		{
			return 0;
		}
		if (!targets.TryGetValue(target, out var value))
		{
			if (targets.Count >= 128)
			{
				int key = 0;
				double num = double.PositiveInfinity;
				foreach (KeyValuePair<int, State> target2 in targets)
				{
					if (target2.Value.Last < num)
					{
						key = target2.Key;
						num = target2.Value.Last;
					}
				}
				targets.Remove(key);
			}
			value = new State();
			targets.Add(target, value);
		}
		if (now - value.Last > 10.0 || now < value.Last)
		{
			value.Right = false;
		}
		int result = (value.Right ? 1 : (-1));
		value.Right = !value.Right;
		value.Last = now;
		return result;
	}
}
public static class SagaHitSizing
{
	public static float Scale(float damage, float maximum, bool critical)
	{
		if (float.IsNaN(damage) || float.IsInfinity(damage) || damage < 0f)
		{
			damage = 0f;
		}
		float num = Math.Max(0f, Math.Min(1f, damage / Math.Max(1f, maximum)));
		return (0.55f + 0.45f * (float)Math.Sqrt(num)) * (critical ? 1.18f : 1f);
	}

	public static float Shake(float age)
	{
		return 4f * Math.Max(0f, 1f - age / 0.38f);
	}
}

BepInEx/plugins/MMC-SagaHotbarPro/SagaHotbarPro.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("0.0.0.0")]
internal static class SagaConfigPreview
{
	private static BaseUnityPlugin manager;

	private static PropertyInfo displaying;

	private static float retry;

	private static int frame = -1;

	private static bool open;

	internal static bool Open
	{
		get
		{
			if (frame == Time.frameCount)
			{
				return open;
			}
			frame = Time.frameCount;
			open = false;
			if ((Object)(object)manager == (Object)null && Time.unscaledTime >= retry)
			{
				retry = Time.unscaledTime + 2f;
				if (Chainloader.PluginInfos.TryGetValue("com.bepis.bepinex.configurationmanager", out var value))
				{
					manager = value.Instance;
					displaying = ((object)manager).GetType().GetProperty("DisplayingWindow", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				}
			}
			if ((Object)(object)manager != (Object)null && displaying != null)
			{
				try
				{
					open = (bool)displaying.GetValue(manager, null);
				}
				catch
				{
					open = false;
				}
			}
			return open;
		}
	}

	internal static bool HudVisible(Hud hud)
	{
		if ((Object)(object)hud != (Object)null)
		{
			if (!Open)
			{
				return hud.IsVisible();
			}
			return true;
		}
		return false;
	}

	internal static bool MenuVisible()
	{
		if (!Open)
		{
			return Menu.IsVisible();
		}
		return false;
	}

	internal static bool MapVisible()
	{
		if (!Open)
		{
			return Minimap.IsOpen();
		}
		return false;
	}

	internal static bool StoreVisible()
	{
		if (!Open)
		{
			return StoreGui.IsVisible();
		}
		return false;
	}

	internal static bool InventoryHidesHud()
	{
		if (!Open)
		{
			return InventoryGui.IsVisible();
		}
		return false;
	}
}
[DefaultExecutionOrder(10000)]
[BepInPlugin("local.mmc.sagahotbar", "SagaHotbarPro", "3.0.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public sealed class SagaHotbarPro : BaseUnityPlugin
{
	private sealed class Slot
	{
		public RectTransform Rect;

		public Vector3 Position;

		public Vector3 Scale;

		public GameObject Skin;

		public Image Background;

		public Color BackgroundColor;
	}

	private readonly Dictionary<RectTransform, Slot> saved = new Dictionary<RectTransform, Slot>();

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

	private ConfigEntry<bool> show;

	private ConfigEntry<float> size;

	private ConfigEntry<float> bottom;

	private Hud hud;

	private SagaPanelAppearance appearance;

	private Image[] frameImages;

	private Rect panelBounds;

	private static readonly FieldInfo elementsField = typeof(HotkeyBar).GetField("m_elements", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

	private RectTransform frame;

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

	private RectTransform powerSlot;

	private Image powerIcon;

	private Image powerWipe;

	private TMP_Text powerKey;

	private TMP_Text powerTimer;

	private float nextKeyRefresh;

	private void Awake()
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: Expected O, but got Unknown
		//IL_0068: Unknown result type (might be due to invalid IL or missing references)
		//IL_0072: Expected O, but got Unknown
		//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b1: Expected O, but got Unknown
		appearance = new SagaPanelAppearance(((BaseUnityPlugin)this).Config, true, 1f);
		show = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "Enabled", true, "Dock the native item bar and Extended Player Inventory quick slots at bottom center.");
		size = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "Slot Size", 64f, new ConfigDescription("Slot size in screen pixels.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(40f, 80f), new object[0]));
		bottom = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "Bottom Margin", 12f, new ConfigDescription("Space beneath the item strip.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), new object[0]));
		((BaseUnityPlugin)this).Logger.LogInfo((object)"SagaHotbarPro docks existing hotkey slots; inventory and keybindings remain native.");
	}

	private static Image Box(Transform parent, string name, Vector2 min, Vector2 max, Vector2 insetMin, Vector2 insetMax, Color color)
	{
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: Expected O, but got Unknown
		//IL_0039: 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_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_005e: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = new GameObject(name, new Type[2]
		{
			typeof(RectTransform),
			typeof(Image)
		});
		RectTransform component = val.GetComponent<RectTransform>();
		((Transform)component).SetParent(parent, false);
		component.anchorMin = min;
		component.anchorMax = max;
		component.offsetMin = insetMin;
		component.offsetMax = insetMax;
		Image component2 = val.GetComponent<Image>();
		((Graphic)component2).color = color;
		((Graphic)component2).raycastTarget = false;
		return component2;
	}

	private static void Border(Transform parent, float thickness)
	{
		//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_003c: 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_0053: 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_0072: Unknown result type (might be due to invalid IL or missing references)
		//IL_0077: 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_0093: Unknown result type (might be due to invalid IL or missing references)
		//IL_0098: 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_00bf: 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_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_00da: Unknown result type (might be due to invalid IL or missing references)
		Color color = default(Color);
		((Color)(ref color))..ctor(0.52f, 0.35f, 0.17f, 1f);
		Box(parent, "Bronze top", new Vector2(0f, 1f), Vector2.one, new Vector2(0f, 0f - thickness), Vector2.zero, color);
		Box(parent, "Bronze bottom", Vector2.zero, new Vector2(1f, 0f), Vector2.zero, new Vector2(0f, thickness), color);
		Box(parent, "Bronze left", Vector2.zero, new Vector2(0f, 1f), Vector2.zero, new Vector2(thickness, 0f), color);
		Box(parent, "Bronze right", new Vector2(1f, 0f), Vector2.one, new Vector2(0f - thickness, 0f), Vector2.zero, color);
	}

	private void Skin(RectTransform rect)
	{
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Unknown result type (might be due to invalid IL or missing references)
		//IL_002f: 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_00a8: Expected O, but got Unknown
		//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d5: 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_0057: 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_007b: Unknown result type (might be due to invalid IL or missing references)
		if (!saved.ContainsKey(rect))
		{
			Slot slot = new Slot();
			slot.Rect = rect;
			slot.Position = ((Transform)rect).localPosition;
			slot.Scale = ((Transform)rect).localScale;
			Slot slot2 = slot;
			slot2.Background = ((Component)rect).GetComponent<Image>();
			if ((Object)(object)slot2.Background != (Object)null)
			{
				slot2.BackgroundColor = ((Graphic)slot2.Background).color;
				((Graphic)slot2.Background).color = new Color(0.1f, 0.105f, 0.085f, 0.95f);
			}
			GameObject val = new GameObject("Saga bronze slot frame", new Type[1] { typeof(RectTransform) });
			RectTransform component = val.GetComponent<RectTransform>();
			((Transform)component).SetParent((Transform)(object)rect, false);
			component.anchorMin = Vector2.zero;
			component.anchorMax = Vector2.one;
			Vector2 offsetMin = (component.offsetMax = Vector2.zero);
			component.offsetMin = offsetMin;
			Border((Transform)(object)component, 1.5f);
			slot2.Skin = val;
			saved.Add(rect, slot2);
		}
	}

	private static Camera UICamera(RectTransform rect)
	{
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		Canvas componentInParent = ((Component)rect).GetComponentInParent<Canvas>();
		if (!((Object)(object)componentInParent == (Object)null) && (int)componentInParent.renderMode != 0)
		{
			return componentInParent.worldCamera;
		}
		return null;
	}

	private static void Position(RectTransform rect, Rect screen)
	{
		//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_002c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: 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_0052: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: Unknown result type (might be due to invalid IL or missing references)
		//IL_0080: Unknown result type (might be due to invalid IL or missing references)
		//IL_0085: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ab: 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_00e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f3: 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_011d: Unknown result type (might be due to invalid IL or missing references)
		Transform parent = ((Transform)rect).parent;
		RectTransform val = (RectTransform)(object)((parent is RectTransform) ? parent : null);
		if ((Object)(object)val == (Object)null)
		{
			return;
		}
		Rect rect2 = rect.rect;
		if (((Rect)(ref rect2)).width <= 0f)
		{
			return;
		}
		Rect rect3 = rect.rect;
		if (!(((Rect)(ref rect3)).height <= 0f))
		{
			Vector3 lossyScale = ((Transform)val).lossyScale;
			float width = ((Rect)(ref screen)).width;
			Rect rect4 = rect.rect;
			float num = width / ((Rect)(ref rect4)).width / Mathf.Max(0.001f, Mathf.Abs(lossyScale.x));
			float height = ((Rect)(ref screen)).height;
			Rect rect5 = rect.rect;
			((Transform)rect).localScale = new Vector3(num, height / ((Rect)(ref rect5)).height / Mathf.Max(0.001f, Mathf.Abs(lossyScale.y)), 1f);
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor(((Rect)(ref screen)).x + ((Rect)(ref screen)).width * rect.pivot.x, ((Rect)(ref screen)).y + ((Rect)(ref screen)).height * rect.pivot.y);
			Vector2 val3 = default(Vector2);
			if (RectTransformUtility.ScreenPointToLocalPointInRectangle(val, val2, UICamera(rect), ref val3))
			{
				((Transform)rect).localPosition = new Vector3(val3.x, val3.y, ((Transform)rect).localPosition.z);
			}
		}
	}

	private void MakeFrame()
	{
		//IL_0045: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Expected O, but got Unknown
		//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_0076: Unknown result type (might be due to invalid IL or missing references)
		//IL_007c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0088: 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_00c2: 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)
		//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
		Transform val = ((Component)hud).transform.Find("hudroot");
		if ((Object)(object)val == (Object)null)
		{
			val = ((Component)hud).transform;
		}
		GameObject val2 = new GameObject("SagaHotbarPro strip", new Type[1] { typeof(RectTransform) });
		frame = val2.GetComponent<RectTransform>();
		((Transform)frame).SetParent(val, false);
		RectTransform obj = frame;
		Vector2 anchorMin = (frame.anchorMax = Vector2.zero);
		obj.anchorMin = anchorMin;
		frame.pivot = Vector2.zero;
		frame.sizeDelta = new Vector2(800f, 76f);
		((Transform)frame).SetAsFirstSibling();
		Box((Transform)(object)frame, "Dark panel", Vector2.zero, Vector2.one, Vector2.zero, Vector2.zero, new Color(0.035f, 0.04f, 0.035f, 0.88f));
		Border((Transform)(object)frame, 1f);
		frameImages = ((Component)frame).GetComponentsInChildren<Image>(true);
	}

	private void LateUpdate()
	{
		//IL_033d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0366: Unknown result type (might be due to invalid IL or missing references)
		//IL_036b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0494: Unknown result type (might be due to invalid IL or missing references)
		//IL_0499: Unknown result type (might be due to invalid IL or missing references)
		//IL_049e: Unknown result type (might be due to invalid IL or missing references)
		//IL_04c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_04de: Unknown result type (might be due to invalid IL or missing references)
		//IL_04fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0500: Unknown result type (might be due to invalid IL or missing references)
		//IL_0506: Unknown result type (might be due to invalid IL or missing references)
		//IL_050b: Unknown result type (might be due to invalid IL or missing references)
		//IL_054d: Unknown result type (might be due to invalid IL or missing references)
		//IL_05b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_044e: Unknown result type (might be due to invalid IL or missing references)
		//IL_043c: Unknown result type (might be due to invalid IL or missing references)
		SagaPanelUI.HotbarVisible = false;
		SagaPanelUI.PowerOnHotbar = show.Value;
		if (!show.Value || (Object)(object)Hud.instance == (Object)null || (Object)(object)Player.m_localPlayer == (Object)null)
		{
			Restore();
			return;
		}
		if ((Object)(object)hud != (Object)(object)Hud.instance)
		{
			Restore();
			hud = Hud.instance;
		}
		visibleSlots.Clear();
		HotkeyBar[] componentsInChildren = ((Component)hud).GetComponentsInChildren<HotkeyBar>(true);
		Array.Sort(componentsInChildren, (HotkeyBar a, HotkeyBar b) => IsQuick(a).CompareTo(IsQuick(b)));
		HotkeyBar[] array = componentsInChildren;
		foreach (HotkeyBar val in array)
		{
			if (!((Component)val).gameObject.activeInHierarchy || !(elementsField.GetValue(val) is IEnumerable enumerable))
			{
				continue;
			}
			foreach (object item in enumerable)
			{
				object? value = item.GetType().GetField("m_go", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).GetValue(item);
				GameObject val2 = (GameObject)((value is GameObject) ? value : null);
				if (!((Object)(object)val2 == (Object)null) && val2.activeInHierarchy)
				{
					Transform transform = val2.transform;
					RectTransform val3 = (RectTransform)(object)((transform is RectTransform) ? transform : null);
					if ((Object)(object)val3 != (Object)null)
					{
						visibleSlots.Add(val3);
					}
				}
			}
		}
		expired.Clear();
		foreach (KeyValuePair<RectTransform, Slot> item2 in saved)
		{
			if ((Object)(object)item2.Key == (Object)null)
			{
				expired.Add(item2.Key);
			}
		}
		foreach (RectTransform item3 in expired)
		{
			saved.Remove(item3);
		}
		if (visibleSlots.Count <= 0 || !appearance.InventoryVisible || (!SagaConfigPreview.HudVisible(hud) && !InventoryGui.IsVisible()) || ((Character)Player.m_localPlayer).IsDead())
		{
			if ((Object)(object)frame != (Object)null)
			{
				((Component)frame).gameObject.SetActive(false);
			}
			return;
		}
		if ((Object)(object)frame == (Object)null)
		{
			MakeFrame();
		}
		((Component)frame).gameObject.SetActive(true);
		StatusEffect val4 = default(StatusEffect);
		float num2 = default(float);
		Player.m_localPlayer.GetGuardianPowerHUD(ref val4, ref num2);
		int num3 = 0;
		int num4 = visibleSlots.Count + num3;
		float num5 = (float)num4 * (size.Value + 4f) + 16f;
		float num6 = Mathf.Min(1f, (float)(Screen.width - 24) / num5);
		float num7 = size.Value * num6;
		float num8 = 4f * num6;
		float num9 = num5 * num6;
		float num10 = (size.Value + 12f) * num6;
		Vector2 val5 = appearance.Size(new Vector2(num9, num10 + appearance.HeaderHeight), (float)Mathf.Min(num4 * 24 + 16, Screen.width), 40f + appearance.HeaderHeight);
		num9 = val5.x;
		num10 = val5.y;
		num7 = Mathf.Min(Mathf.Max(12f, num10 - 12f - appearance.HeaderHeight), Mathf.Max(12f, (num9 - 16f) / (float)num4 - 4f));
		num8 = ((num4 > 1) ? Mathf.Max(0f, (num9 - 16f - (float)num4 * num7) / (float)(num4 - 1)) : 0f);
		Image[] array2 = frameImages;
		foreach (Image val6 in array2)
		{
			bool flag = ((Object)val6).name == "Dark panel";
			((Behaviour)val6).enabled = flag || !appearance.ToolWindow;
			((Graphic)val6).color = (flag ? appearance.Background(0.88f) : appearance.Border);
		}
		Rect val7 = appearance.Position(new Rect(((float)Screen.width - num9) * 0.5f, (float)Screen.height - bottom.Value - num10, num9, num10));
		float x = ((Rect)(ref val7)).x;
		float num12 = (float)Screen.height - ((Rect)(ref val7)).y - num10;
		frame.sizeDelta = new Vector2(num9, num10);
		Position(frame, new Rect(x, num12, num9, num10));
		panelBounds = new Rect(x, (float)Screen.height - num12 - num10, num9, num10);
		SagaPanelUI.HotbarRect = panelBounds;
		SagaPanelUI.HotbarVisible = true;
		UpdatePowerSlot(null, 0f, new Rect(x + 8f, num12 + Mathf.Max(6f, (num10 - appearance.HeaderHeight - num7) * 0.5f), num7, num7));
		for (int num13 = 0; num13 < visibleSlots.Count; num13++)
		{
			RectTransform rect = visibleSlots[num13];
			Skin(rect);
			Position(rect, new Rect(x + 8f + (float)(num13 + num3) * (num7 + num8), num12 + Mathf.Max(6f, (num10 - appearance.HeaderHeight - num7) * 0.5f), num7, num7));
		}
	}

	private void OnGUI()
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//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_0072: 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_00cb: Unknown result type (might be due to invalid IL or missing references)
		if (SagaPanelUI.HotbarVisible && !appearance.ToolWindow)
		{
			Color color = GUI.color;
			GUI.color = appearance.Header;
			GUI.DrawTexture(new Rect(((Rect)(ref panelBounds)).x + 1f, ((Rect)(ref panelBounds)).y + 1f, ((Rect)(ref panelBounds)).width - 2f, 29f), (Texture)(object)Texture2D.whiteTexture);
			GUI.color = Color.white;
			GUI.Label(new Rect(((Rect)(ref panelBounds)).x + 8f, ((Rect)(ref panelBounds)).y + 3f, ((Rect)(ref panelBounds)).width - 16f, 24f), "Hotbar", SagaPanelUI.TextStyle(16, (TextAnchor)3));
			GUI.color = color;
		}
	}

	private static bool IsQuick(HotkeyBar bar)
	{
		if (((Object)bar).name.IndexOf("Quick", StringComparison.OrdinalIgnoreCase) < 0)
		{
			return ((Object)bar).name.IndexOf("Azu", StringComparison.OrdinalIgnoreCase) >= 0;
		}
		return true;
	}

	private void Restore()
	{
		//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_0060: Unknown result type (might be due to invalid IL or missing references)
		foreach (Slot value in saved.Values)
		{
			if ((Object)(object)value.Rect != (Object)null)
			{
				((Transform)value.Rect).localPosition = value.Position;
				((Transform)value.Rect).localScale = value.Scale;
			}
			if ((Object)(object)value.Background != (Object)null)
			{
				((Graphic)value.Background).color = value.BackgroundColor;
			}
			if ((Object)(object)value.Skin != (Object)null)
			{
				Object.Destroy((Object)(object)value.Skin);
			}
		}
		saved.Clear();
		powerSlot = null;
		powerIcon = (powerWipe = null);
		powerKey = (powerTimer = null);
		if ((Object)(object)frame != (Object)null)
		{
			Object.Destroy((Object)(object)((Component)frame).gameObject);
		}
		frame = null;
		hud = null;
	}

	private void OnDestroy()
	{
		SagaPanelUI.PowerOnHotbar = false;
		Restore();
	}

	private TMP_Text PowerLabel(string name, Vector2 min, Vector2 max, TextAlignmentOptions align)
	{
		//IL_0027: Unknown result type (might be due to invalid IL or missing references)
		//IL_002d: 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)
		//IL_005a: Unknown result type (might be due to invalid IL or missing references)
		//IL_006f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00db: 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)
		GameObject val = new GameObject(name, new Type[2]
		{
			typeof(RectTransform),
			typeof(TextMeshProUGUI)
		});
		RectTransform component = val.GetComponent<RectTransform>();
		((Transform)component).SetParent((Transform)(object)powerSlot, false);
		component.anchorMin = min;
		component.anchorMax = max;
		component.offsetMin = new Vector2(3f, 0f);
		component.offsetMax = new Vector2(-3f, 0f);
		TMP_Text component2 = val.GetComponent<TMP_Text>();
		TMP_Text val2 = ((visibleSlots.Count > 0) ? ((Component)visibleSlots[0]).GetComponentInChildren<TMP_Text>(true) : hud.m_gpCooldown);
		if ((Object)(object)val2 != (Object)null)
		{
			component2.font = val2.font;
			component2.fontSharedMaterial = val2.fontSharedMaterial;
		}
		component2.fontSize = 16f;
		((Graphic)component2).color = Color.white;
		component2.alignment = align;
		((Graphic)component2).raycastTarget = false;
		component2.enableAutoSizing = true;
		component2.fontSizeMin = 8f;
		component2.fontSizeMax = 16f;
		return component2;
	}

	private void UpdatePowerSlot(StatusEffect power, float cooldown, Rect screen)
	{
		//IL_023d: 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: Expected O, but got Unknown
		//IL_0088: Unknown result type (might be due to invalid IL or missing references)
		//IL_0098: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b7: 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_00d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f1: 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_010f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0114: Unknown result type (might be due to invalid IL or missing references)
		//IL_013b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0140: Unknown result type (might be due to invalid IL or missing references)
		//IL_014f: Unknown result type (might be due to invalid IL or missing references)
		//IL_015e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0177: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0203: Unknown result type (might be due to invalid IL or missing references)
		//IL_0212: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)power == (Object)null)
		{
			if ((Object)(object)powerSlot != (Object)null)
			{
				((Component)powerSlot).gameObject.SetActive(false);
			}
			return;
		}
		if ((Object)(object)powerSlot == (Object)null)
		{
			GameObject val = new GameObject("Forsaken power hotbar slot", new Type[1] { typeof(RectTransform) });
			powerSlot = val.GetComponent<RectTransform>();
			((Transform)powerSlot).SetParent((Transform)(object)frame, false);
			powerSlot.sizeDelta = new Vector2(64f, 64f);
			powerSlot.pivot = Vector2.zero;
			Box((Transform)(object)powerSlot, "Background", Vector2.zero, Vector2.one, Vector2.zero, Vector2.zero, new Color(0.1f, 0.105f, 0.085f, 0.95f));
			powerIcon = Box((Transform)(object)powerSlot, "Native power icon", Vector2.zero, Vector2.one, new Vector2(6f, 6f), new Vector2(-6f, -6f), Color.white);
			powerIcon.preserveAspect = true;
			powerWipe = Box((Transform)(object)powerSlot, "Cooldown reverse wipe", Vector2.zero, Vector2.one, new Vector2(6f, 6f), new Vector2(-6f, -6f), new Color(0.42f, 0.42f, 0.42f, 0.85f));
			powerWipe.preserveAspect = true;
			powerWipe.type = (Type)3;
			powerWipe.fillMethod = (FillMethod)4;
			powerWipe.fillOrigin = 2;
			powerWipe.fillClockwise = false;
			Border((Transform)(object)powerSlot, 1.5f);
			powerKey = PowerLabel("Bound power key", new Vector2(0f, 0.65f), Vector2.one, (TextAlignmentOptions)257);
			powerTimer = PowerLabel("Power cooldown", Vector2.zero, new Vector2(1f, 0.35f), (TextAlignmentOptions)1028);
		}
		((Component)powerSlot).gameObject.SetActive(true);
		Position(powerSlot, screen);
		powerIcon.sprite = power.m_icon;
		powerWipe.sprite = power.m_icon;
		((Behaviour)powerWipe).enabled = cooldown > 0f;
		powerWipe.fillAmount = Mathf.Clamp01(cooldown / Mathf.Max(1f, power.m_cooldown));
		powerTimer.text = ((cooldown <= 0f) ? "" : ((cooldown > 60f) ? (Mathf.CeilToInt(cooldown / 60f) + "m") : (Mathf.CeilToInt(cooldown) + "s")));
		if (Time.unscaledTime >= nextKeyRefresh)
		{
			nextKeyRefresh = Time.unscaledTime + 0.5f;
			powerKey.text = ((ZInput.instance == null) ? "" : ZInput.instance.GetBoundKeyString("GP", false));
		}
	}
}

BepInEx/plugins/MMC-SagaTickPro/SagaTickPro.dll

Decompiled a week ago
using System;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("0.0.0.0")]
public sealed class CombatBeat
{
	private double next;

	public bool Active { get; private set; }

	public bool White { get; private set; }

	public bool Advance(double now, bool engaged, double interval)
	{
		if (!engaged)
		{
			Active = false;
			White = false;
			next = 0.0;
			return false;
		}
		interval = Math.Max(0.15, interval);
		if (!Active)
		{
			Active = true;
			White = true;
			next = now + interval;
			return true;
		}
		if (now < next)
		{
			return false;
		}
		long num = (long)Math.Floor((now - next) / interval) + 1;
		if ((num & 1) != 0)
		{
			White = !White;
		}
		next += (double)num * interval;
		return true;
	}
}
internal static class SagaConfigPreview
{
	private static BaseUnityPlugin manager;

	private static PropertyInfo displaying;

	private static float retry;

	private static int frame = -1;

	private static bool open;

	internal static bool Open
	{
		get
		{
			if (frame == Time.frameCount)
			{
				return open;
			}
			frame = Time.frameCount;
			open = false;
			if ((Object)(object)manager == (Object)null && Time.unscaledTime >= retry)
			{
				retry = Time.unscaledTime + 2f;
				if (Chainloader.PluginInfos.TryGetValue("com.bepis.bepinex.configurationmanager", out var value))
				{
					manager = value.Instance;
					displaying = ((object)manager).GetType().GetProperty("DisplayingWindow", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				}
			}
			if ((Object)(object)manager != (Object)null && displaying != null)
			{
				try
				{
					open = (bool)displaying.GetValue(manager, null);
				}
				catch
				{
					open = false;
				}
			}
			return open;
		}
	}

	internal static bool HudVisible(Hud hud)
	{
		if ((Object)(object)hud != (Object)null)
		{
			if (!Open)
			{
				return hud.IsVisible();
			}
			return true;
		}
		return false;
	}

	internal static bool MenuVisible()
	{
		if (!Open)
		{
			return Menu.IsVisible();
		}
		return false;
	}

	internal static bool MapVisible()
	{
		if (!Open)
		{
			return Minimap.IsOpen();
		}
		return false;
	}

	internal static bool StoreVisible()
	{
		if (!Open)
		{
			return StoreGui.IsVisible();
		}
		return false;
	}

	internal static bool InventoryHidesHud()
	{
		if (!Open)
		{
			return InventoryGui.IsVisible();
		}
		return false;
	}
}
internal sealed class SagaTickWindow
{
	private readonly ConfigEntry<float> x;

	private readonly ConfigEntry<float> y;

	private SagaPanelAppearance appearance;

	private readonly int hint;

	private bool dragging;

	private int control;

	private Vector2 offset;

	private Vector2 position;

	private GameObject blocker;

	private RectTransform blockRect;

	public SagaTickWindow(ConfigFile config, string name)
	{
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Expected O, but got Unknown
		hint = name.GetHashCode();
		appearance = new SagaPanelAppearance(config, true, 1f);
		x = config.Bind<float>("Window", "Position X", -1f, "Saved horizontal position, 0 to 1. Set both positions to -1 to restore automatic placement.");
		y = config.Bind<float>("Window", "Position Y", -1f, "Saved vertical position, 0 to 1. Drag the square while inventory is open to move it.");
	}

	private void Save(Rect rect)
	{
		//IL_0008: Unknown result type (might be due to invalid IL or missing references)
		appearance.SavePosition(((Rect)(ref rect)).position);
		x.Value = Mathf.Clamp01(((Rect)(ref rect)).x / Mathf.Max(1f, (float)Screen.width - ((Rect)(ref rect)).width));
		y.Value = Mathf.Clamp01(((Rect)(ref rect)).y / Mathf.Max(1f, (float)Screen.height - ((Rect)(ref rect)).height));
	}

	public Rect Place(Rect rect, float reservedRight)
	{
		//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b4: 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_0104: Unknown result type (might be due to invalid IL or missing references)
		//IL_0257: Unknown result type (might be due to invalid IL or missing references)
		//IL_025e: 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_020d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0177: Unknown result type (might be due to invalid IL or missing references)
		//IL_017d: Invalid comparison between Unknown and I4
		//IL_0116: Unknown result type (might be due to invalid IL or missing references)
		//IL_0216: Unknown result type (might be due to invalid IL or missing references)
		//IL_021c: Invalid comparison between Unknown and I4
		//IL_0182: Unknown result type (might be due to invalid IL or missing references)
		//IL_0188: Unknown result type (might be due to invalid IL or missing references)
		//IL_018d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0138: Unknown result type (might be due to invalid IL or missing references)
		//IL_013f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0144: Unknown result type (might be due to invalid IL or missing references)
		//IL_0149: 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)
		//IL_0156: Unknown result type (might be due to invalid IL or missing references)
		//IL_0241: Unknown result type (might be due to invalid IL or missing references)
		//IL_0248: Unknown result type (might be due to invalid IL or missing references)
		//IL_024e: Invalid comparison between Unknown and I4
		bool flag = InventoryGui.IsVisible() && !SagaConfigPreview.Open;
		if (!dragging && x.Value >= 0f && y.Value >= 0f)
		{
			((Rect)(ref rect)).position = new Vector2(x.Value * Mathf.Max(0f, (float)Screen.width - ((Rect)(ref rect)).width), y.Value * Mathf.Max(0f, (float)Screen.height - ((Rect)(ref rect)).height));
		}
		if (!dragging)
		{
			rect = appearance.Position(rect);
		}
		if (dragging)
		{
			((Rect)(ref rect)).position = position;
		}
		Event current = Event.current;
		int controlID = GUIUtility.GetControlID(hint, (FocusType)2);
		Rect val = default(Rect);
		((Rect)(ref val))..ctor(((Rect)(ref rect)).x, ((Rect)(ref rect)).y, Mathf.Max(0f, ((Rect)(ref rect)).width - reservedRight), ((Rect)(ref rect)).height);
		if (flag && (int)current.type == 0 && current.button == 0 && ((Rect)(ref val)).Contains(current.mousePosition))
		{
			dragging = true;
			control = controlID;
			GUIUtility.hotControl = controlID;
			offset = current.mousePosition - ((Rect)(ref rect)).position;
			position = ((Rect)(ref rect)).position;
			current.Use();
		}
		if (dragging && GUIUtility.hotControl == control && (int)current.type == 3)
		{
			((Rect)(ref rect)).position = current.mousePosition - offset;
			current.Use();
		}
		((Rect)(ref rect)).x = Mathf.Clamp(((Rect)(ref rect)).x, 0f, Mathf.Max(0f, (float)Screen.width - ((Rect)(ref rect)).width));
		((Rect)(ref rect)).y = Mathf.Clamp(((Rect)(ref rect)).y, 0f, Mathf.Max(0f, (float)Screen.height - ((Rect)(ref rect)).height));
		if (dragging)
		{
			position = ((Rect)(ref rect)).position;
			if (!flag || ((int)current.type == 1 && current.button == 0))
			{
				dragging = false;
				if (GUIUtility.hotControl == control)
				{
					GUIUtility.hotControl = 0;
				}
				Save(rect);
				if ((int)current.type == 1)
				{
					current.Use();
				}
			}
		}
		SetBlocker(rect, flag);
		return rect;
	}

	private void SetBlocker(Rect rect, bool active)
	{
		//IL_014b: Unknown result type (might be due to invalid IL or missing references)
		//IL_015d: 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_0056: Expected O, but got Unknown
		//IL_009f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a5: Expected O, but got Unknown
		//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f4: 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_010a: Unknown result type (might be due to invalid IL or missing references)
		if (active && (Object)(object)blocker == (Object)null)
		{
			blocker = new GameObject("Saga panel inventory click shield", new Type[3]
			{
				typeof(RectTransform),
				typeof(Canvas),
				typeof(GraphicRaycaster)
			});
			Canvas component = blocker.GetComponent<Canvas>();
			component.renderMode = (RenderMode)0;
			component.sortingOrder = 32760;
			GameObject val = new GameObject("Panel area", new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			blockRect = val.GetComponent<RectTransform>();
			((Transform)blockRect).SetParent(blocker.transform, false);
			RectTransform obj = blockRect;
			RectTransform obj2 = blockRect;
			Vector2 val2 = (blockRect.pivot = new Vector2(0f, 1f));
			Vector2 anchorMin = (obj2.anchorMax = val2);
			obj.anchorMin = anchorMin;
			Image component2 = val.GetComponent<Image>();
			((Graphic)component2).color = Color.clear;
			((Graphic)component2).raycastTarget = true;
		}
		if (!((Object)(object)blocker == (Object)null))
		{
			blocker.SetActive(active);
			blockRect.anchoredPosition = new Vector2(((Rect)(ref rect)).x, 0f - ((Rect)(ref rect)).y);
			blockRect.sizeDelta = ((Rect)(ref rect)).size;
		}
	}

	public void Hide()
	{
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_0055: 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_007d: Unknown result type (might be due to invalid IL or missing references)
		//IL_008c: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)blocker != (Object)null)
		{
			blocker.SetActive(false);
		}
		if (dragging)
		{
			float num = position.x;
			float num2 = position.y;
			float num3;
			if (!((Object)(object)blockRect == (Object)null))
			{
				Rect rect = blockRect.rect;
				num3 = ((Rect)(ref rect)).width;
			}
			else
			{
				num3 = 0f;
			}
			float num4;
			if (!((Object)(object)blockRect == (Object)null))
			{
				Rect rect2 = blockRect.rect;
				num4 = ((Rect)(ref rect2)).height;
			}
			else
			{
				num4 = 0f;
			}
			Save(new Rect(num, num2, num3, num4));
			dragging = false;
			if (GUIUtility.hotControl == control)
			{
				GUIUtility.hotControl = 0;
			}
		}
	}

	public void Dispose()
	{
		Hide();
		if ((Object)(object)blocker != (Object)null)
		{
			Object.Destroy((Object)(object)blocker);
		}
	}
}
[BepInPlugin("local.mmc.sagatick", "Saga Combat Metronome", "3.0.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public sealed class SagaTickPro : BaseUnityPlugin
{
	private static SagaTickPro instance;

	private Harmony harmony;

	private ConfigEntry<bool> enabledPanel;

	private ConfigEntry<bool> soundEnabled;

	private ConfigEntry<int> size;

	private ConfigEntry<float> interval;

	private ConfigEntry<float> volume;

	private ConfigEntry<float> linger;

	private SagaTickWindow window;

	private SagaPanelAppearance appearance;

	private readonly CombatBeat beat = new CombatBeat();

	private AudioSource source;

	private AudioClip tick;

	private AudioClip tock;

	private float lastCombat = float.NegativeInfinity;

	private Player player;

	private bool showing;

	private void Awake()
	{
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Expected O, but got Unknown
		//IL_0065: Unknown result type (might be due to invalid IL or missing references)
		//IL_006f: Expected O, but got Unknown
		//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ae: Expected O, but got Unknown
		//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ed: Expected O, but got Unknown
		//IL_0143: Unknown result type (might be due to invalid IL or missing references)
		//IL_014d: Expected O, but got Unknown
		//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01eb: Expected O, but got Unknown
		//IL_0218: Unknown result type (might be due to invalid IL or missing references)
		//IL_0225: Expected O, but got Unknown
		//IL_0252: Unknown result type (might be due to invalid IL or missing references)
		//IL_0260: Expected O, but got Unknown
		//IL_028d: Unknown result type (might be due to invalid IL or missing references)
		//IL_029b: Expected O, but got Unknown
		instance = this;
		appearance = new SagaPanelAppearance(((BaseUnityPlugin)this).Config, true, 1f);
		enabledPanel = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "Enabled", true, "Show the square only during local combat.");
		size = ((BaseUnityPlugin)this).Config.Bind<int>("Display", "Size", 24, new ConfigDescription("Square size with 1px black border. Drag it while inventory is open during combat.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(12, 64), new object[0]));
		interval = ((BaseUnityPlugin)this).Config.Bind<float>("Timing", "Beat Interval Seconds", 0.6f, new ConfigDescription("Practice rhythm, not an enemy attack predictor or a server tick. Seconds between alternating beats.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.15f, 3f), new object[0]));
		linger = ((BaseUnityPlugin)this).Config.Bind<float>("Timing", "Combat Grace Seconds", 5f, new ConfigDescription("Hide after this long without alerted targeting or hits involving you.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 30f), new object[0]));
		soundEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Audio", "Enabled", true, "Play a quiet alternating tick and tock during combat.");
		volume = ((BaseUnityPlugin)this).Config.Bind<float>("Audio", "Volume", 0.08f, new ConfigDescription("Tick volume, 0 to 1.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), new object[0]));
		window = new SagaTickWindow(((BaseUnityPlugin)this).Config, "Combat metronome");
		source = ((Component)this).gameObject.AddComponent<AudioSource>();
		source.playOnAwake = false;
		source.loop = false;
		source.spatialBlend = 0f;
		source.volume = 1f;
		tick = MakeClick("Combat tick", 1250f);
		tock = MakeClick("Combat tock", 850f);
		harmony = new Harmony("local.mmc.sagatick");
		harmony.Patch((MethodBase)AccessTools.Method(typeof(Player), "RPC_OnTargeted", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(SagaTickPro), "Targeted", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		harmony.Patch((MethodBase)AccessTools.Method(typeof(Character), "Damage", (Type[])null, (Type[])null), new HarmonyMethod(typeof(SagaTickPro), "Hit", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		harmony.Patch((MethodBase)AccessTools.Method(typeof(Character), "RPC_Damage", (Type[])null, (Type[])null), new HarmonyMethod(typeof(SagaTickPro), "Received", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
	}

	private static AudioClip MakeClick(string name, float frequency)
	{
		float[] array = new float[882];
		for (int i = 0; i < array.Length; i++)
		{
			double num = (double)i / 22050.0;
			double num2 = Math.Min(1.0, num / 0.002) * Math.Exp((0.0 - num) * 130.0) * (1.0 - (double)i / (double)array.Length);
			array[i] = (float)(Math.Sin(Math.PI * 2.0 * (double)frequency * num) * num2 * 0.65);
		}
		AudioClip val = AudioClip.Create(name, array.Length, 1, 22050, false);
		typeof(AudioClip).GetMethod("SetData", new Type[2]
		{
			typeof(float[]),
			typeof(int)
		}).Invoke(val, new object[2] { array, 0 });
		return val;
	}

	private static void Targeted(Player __instance, bool __2)
	{
		if ((Object)(object)instance != (Object)null && (Object)(object)__instance == (Object)(object)Player.m_localPlayer && __2)
		{
			instance.lastCombat = Time.unscaledTime;
		}
	}

	private static void Received(Character __instance, HitData __1)
	{
		Hit(__instance, __1);
	}

	private static void Hit(Character __instance, HitData __0)
	{
		if ((Object)(object)instance == (Object)null || (Object)(object)Player.m_localPlayer == (Object)null || __0 == null)
		{
			return;
		}
		Character attacker = __0.GetAttacker();
		if (!((Object)(object)attacker == (Object)null))
		{
			Player localPlayer = Player.m_localPlayer;
			Character val = (((Object)(object)__instance == (Object)(object)localPlayer) ? attacker : (((Object)(object)attacker == (Object)(object)localPlayer) ? __instance : null));
			if ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)localPlayer && !val.IsTamed() && !val.IsPlayer())
			{
				instance.lastCombat = Time.unscaledTime;
			}
		}
	}

	private void Update()
	{
		Player localPlayer = Player.m_localPlayer;
		if ((Object)(object)player != (Object)(object)localPlayer)
		{
			player = localPlayer;
			lastCombat = float.NegativeInfinity;
			beat.Advance(0.0, engaged: false, interval.Value);
		}
		bool flag = appearance.InventoryVisible && enabledPanel.Value && (Object)(object)player != (Object)null && !((Character)player).IsDead() && (Object)(object)Hud.instance != (Object)null && (SagaConfigPreview.HudVisible(Hud.instance) || InventoryGui.IsVisible()) && !SagaConfigPreview.MenuVisible() && !SagaConfigPreview.MapVisible() && Time.timeScale > 0f;
		bool flag2 = Time.unscaledTime - lastCombat < linger.Value;
		showing = flag && (flag2 || SagaConfigPreview.Open || InventoryGui.IsVisible());
		bool flag3 = beat.Advance(Time.unscaledTime, flag && flag2, interval.Value);
		if (!showing)
		{
			if (source.isPlaying)
			{
				source.Stop();
			}
			window.Hide();
			return;
		}
		if (flag3 && soundEnabled.Value && volume.Value > 0f && Application.isFocused)
		{
			source.PlayOneShot(beat.White ? tick : tock, volume.Value);
		}
		if ((!soundEnabled.Value || !Application.isFocused) && source.isPlaying)
		{
			source.Stop();
		}
	}

	private void OnGUI()
	{
		//IL_004b: 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)
		//IL_009d: 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_00ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b1: 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_00bd: Invalid comparison between Unknown and I4
		//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
		//IL_0140: 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)
		//IL_015d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0188: Unknown result type (might be due to invalid IL or missing references)
		//IL_0193: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f7: 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_022c: Unknown result type (might be due to invalid IL or missing references)
		if (!showing)
		{
			window.Hide();
			return;
		}
		int depth = GUI.depth;
		GUI.depth = -100;
		try
		{
			Vector2 val = appearance.Size(new Vector2((float)size.Value, (float)size.Value + appearance.HeaderHeight), 12f, 12f + appearance.HeaderHeight);
			Rect val2 = window.Place(appearance.Position(new Rect((float)Screen.width * 0.5f + 230f, 110f, val.x, val.y)), 0f);
			if ((int)Event.current.type == 7)
			{
				appearance.Draw(val2, 1f, "Combat");
				((Rect)(ref val2)).y = ((Rect)(ref val2)).y + appearance.HeaderHeight;
				((Rect)(ref val2)).height = ((Rect)(ref val2)).height - appearance.HeaderHeight;
				Fill(new Rect(((Rect)(ref val2)).x + 1f, ((Rect)(ref val2)).y + 1f, ((Rect)(ref val2)).width - 2f, ((Rect)(ref val2)).height - 2f), beat.White ? Color.white : appearance.Background(0.5f));
				Fill(new Rect(((Rect)(ref val2)).x, ((Rect)(ref val2)).y, ((Rect)(ref val2)).width, 1f), appearance.Border);
				Fill(new Rect(((Rect)(ref val2)).x, ((Rect)(ref val2)).yMax - 1f, ((Rect)(ref val2)).width, 1f), appearance.Border);
				Fill(new Rect(((Rect)(ref val2)).x, ((Rect)(ref val2)).y, 1f, ((Rect)(ref val2)).height), appearance.Border);
				Fill(new Rect(((Rect)(ref val2)).xMax - 1f, ((Rect)(ref val2)).y, 1f, ((Rect)(ref val2)).height), appearance.Border);
			}
		}
		finally
		{
			GUI.depth = depth;
		}
	}

	private static void Fill(Rect rect, Color color)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0005: 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_000c: 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)
		Color color2 = GUI.color;
		GUI.color = color;
		GUI.DrawTexture(rect, (Texture)(object)Texture2D.whiteTexture);
		GUI.color = color2;
	}

	private void OnDestroy()
	{
		if (harmony != null)
		{
			harmony.UnpatchSelf();
		}
		if (window != null)
		{
			window.Dispose();
		}
		if ((Object)(object)source != (Object)null)
		{
			source.Stop();
			Object.Destroy((Object)(object)source);
		}
		if ((Object)(object)tick != (Object)null)
		{
			Object.Destroy((Object)(object)tick);
		}
		if ((Object)(object)tock != (Object)null)
		{
			Object.Destroy((Object)(object)tock);
		}
		instance = null;
	}
}

BepInEx/plugins/MMC-ServerSocial/SagaServerSocial.dll

Decompiled a week ago
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("0.0.0.0")]
public static class SagaBedOrder
{
	public static int Rank(long entered, long[] entries)
	{
		if (entered <= 0)
		{
			return 0;
		}
		int num = 1;
		foreach (long num2 in entries)
		{
			if (num2 > 0 && num2 < entered)
			{
				num++;
			}
		}
		return num;
	}
}
internal static class SagaConfigPreview
{
	private static BaseUnityPlugin manager;

	private static PropertyInfo displaying;

	private static float retry;

	private static int frame = -1;

	private static bool open;

	internal static bool Open
	{
		get
		{
			if (frame == Time.frameCount)
			{
				return open;
			}
			frame = Time.frameCount;
			open = false;
			if ((Object)(object)manager == (Object)null && Time.unscaledTime >= retry)
			{
				retry = Time.unscaledTime + 2f;
				if (Chainloader.PluginInfos.TryGetValue("com.bepis.bepinex.configurationmanager", out var value))
				{
					manager = value.Instance;
					displaying = ((object)manager).GetType().GetProperty("DisplayingWindow", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				}
			}
			if ((Object)(object)manager != (Object)null && displaying != null)
			{
				try
				{
					open = (bool)displaying.GetValue(manager, null);
				}
				catch
				{
					open = false;
				}
			}
			return open;
		}
	}

	internal static bool HudVisible(Hud hud)
	{
		if ((Object)(object)hud != (Object)null)
		{
			if (!Open)
			{
				return hud.IsVisible();
			}
			return true;
		}
		return false;
	}

	internal static bool MenuVisible()
	{
		if (!Open)
		{
			return Menu.IsVisible();
		}
		return false;
	}

	internal static bool MapVisible()
	{
		if (!Open)
		{
			return Minimap.IsOpen();
		}
		return false;
	}

	internal static bool StoreVisible()
	{
		if (!Open)
		{
			return StoreGui.IsVisible();
		}
		return false;
	}

	internal static bool InventoryHidesHud()
	{
		if (!Open)
		{
			return InventoryGui.IsVisible();
		}
		return false;
	}
}
[BepInPlugin("local.mmc.serversocial", "Saga Sleep and Server Notices", "3.0.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public sealed class SagaServerSocial : BaseUnityPlugin
{
	private sealed class Entry
	{
		public string ID;

		public string Name;

		public bool Bed;

		public bool Known;

		public long Entered;

		public int Rank;
	}

	private readonly Dictionary<string, Entry> roster = new Dictionary<string, Entry>();

	private readonly HashSet<long> subscribers = new HashSet<long>();

	private readonly Dictionary<long, float> requested = new Dictionary<long, float>();

	private readonly List<Entry> display = new List<Entry>();

	private ZRoutedRpc rpc;

	private float poll;

	private float received = -100f;

	private float lastInBed = -100f;

	private bool wasInBed;

	private bool serverSeeded;

	private ZDOID character;

	private SagaPanelWindow window;

	private ConfigEntry<bool> show;

	private ConfigEntry<bool> notices;

	private ConfigEntry<bool> teasing;

	private ConfigEntry<bool> onlyInBed;

	private ConfigEntry<float> hideDelay;

	private Rect rect;

	private GUIStyle label;

	private Vector2 scroll;

	private void Awake()
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Expected O, but got Unknown
		//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b2: Expected O, but got Unknown
		window = new SagaPanelWindow(((BaseUnityPlugin)this).Config, "Bed roster");
		window.MinimumWidth = 240f;
		window.MinimumHeight = 80f;
		show = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "Enabled", true, "Display online player sleep status.");
		onlyInBed = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "Only While In Bed", true, "Disable to keep the roster visible while awake.");
		hideDelay = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "Hide Delay", 3f, new ConfigDescription("Seconds to keep the roster after leaving bed.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 120f), new object[0]));
		notices = ((BaseUnityPlugin)this).Config.Bind<bool>("Chat", "Disconnect Notices", true, "Show a local chat notice when a player leaves. Requires the server component.");
		teasing = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "Playful Labels", true, "Highlight first to bed and gently tease the last when everyone is in bed.");
	}

	private void Update()
	{
		//IL_00df: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fd: 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)
		if (!show.Value)
		{
			display.Clear();
			window.Hide();
			return;
		}
		if (ZRoutedRpc.instance == null || (Object)(object)ZNet.instance == (Object)null)
		{
			ResetSession();
			return;
		}
		if (rpc != ZRoutedRpc.instance)
		{
			ResetSession();
			rpc = ZRoutedRpc.instance;
			rpc.Register<int>("Saga2_BedRequest", (Action<long, int>)Request);
			rpc.Register<ZPackage>("Saga2_BedRoster", (Action<long, ZPackage>)Receive);
			rpc.Register<string>("Saga2_Left", (Action<long, string>)Left);
		}
		Player localPlayer = Player.m_localPlayer;
		if ((Object)(object)localPlayer != (Object)null)
		{
			ZNetView component = ((Component)localPlayer).GetComponent<ZNetView>();
			if ((Object)(object)component != (Object)null && component.IsValid())
			{
				if (character != component.GetZDO().m_uid)
				{
					character = component.GetZDO().m_uid;
					wasInBed = false;
				}
				bool flag = ((Character)localPlayer).InBed();
				if (flag && !wasInBed)
				{
					component.GetZDO().Set("Saga2BedEntered", ZNet.instance.GetTime().Ticks);
				}
				if (flag)
				{
					lastInBed = Time.unscaledTime;
				}
				wasInBed = flag;
			}
		}
		if (Time.unscaledTime < poll)
		{
			return;
		}
		poll = Time.unscaledTime + 1f;
		if (ZNet.instance.IsServer())
		{
			PollServer();
			return;
		}
		ZNetPeer serverPeer = ZNet.instance.GetServerPeer();
		if (serverPeer != null)
		{
			rpc.InvokeRoutedRPC(serverPeer.m_uid, "Saga2_BedRequest", new object[1] { 1 });
		}
	}

	private void ResetSession()
	{
		rpc = null;
		subscribers.Clear();
		requested.Clear();
		roster.Clear();
		display.Clear();
		serverSeeded = false;
		wasInBed = false;
		received = -100f;
		lastInBed = -100f;
		poll = 0f;
	}

	private void Request(long sender, int value)
	{
		if (show.Value && ZNet.instance.IsServer() && value == 1 && ZNet.instance.GetPeer(sender) != null && (!requested.TryGetValue(sender, out var value2) || !(Time.unscaledTime - value2 < 0.75f)))
		{
			requested[sender] = Time.unscaledTime;
			subscribers.Add(sender);
		}
	}

	private unsafe void PollServer()
	{
		//IL_0022: Unknown result type (might be due to invalid IL or missing references)
		//IL_0027: 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_002f: 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_0047: 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_02c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c7: Expected O, but got Unknown
		List<PlayerInfo> playerList = ZNet.instance.GetPlayerList();
		HashSet<string> hashSet = new HashSet<string>();
		bool flag = false;
		foreach (PlayerInfo item in playerList)
		{
			ZDOID characterID = item.m_characterID;
			string text = ((object)(*(ZDOID*)(&characterID))/*cast due to .constrained prefix*/).ToString();
			if (!(item.m_characterID == ZDOID.None))
			{
				hashSet.Add(text);
				if (!roster.TryGetValue(text, out var value))
				{
					Entry entry = new Entry();
					entry.ID = text;
					value = entry;
					roster.Add(text, value);
				}
				value.Name = item.m_name;
				ZDO val = ((ZDOMan.instance == null) ? null : ZDOMan.instance.GetZDO(item.m_characterID));
				value.Known = val != null;
				bool flag2 = val != null && val.GetBool(ZDOVars.s_inBed, false);
				if (flag2 && !value.Bed)
				{
					value.Entered = val.GetLong("Saga2BedEntered", ZNet.instance.GetTime().Ticks);
				}
				value.Bed = flag2;
				flag = flag || flag2;
			}
		}
		List<string> list = new List<string>();
		foreach (KeyValuePair<string, Entry> item2 in roster)
		{
			if (!hashSet.Contains(item2.Key))
			{
				list.Add(item2.Key);
			}
		}
		foreach (string item3 in list)
		{
			string text2 = Safe(roster[item3].Name) + " left the server. Fair winds!";
			if (serverSeeded)
			{
				foreach (long subscriber in subscribers)
				{
					if (ZNet.instance.GetPeer(subscriber) != null)
					{
						rpc.InvokeRoutedRPC(subscriber, "Saga2_Left", new object[1] { text2 });
					}
				}
				if ((Object)(object)Player.m_localPlayer != (Object)null)
				{
					ShowLeft(text2);
				}
			}
			roster.Remove(item3);
		}
		if (!flag)
		{
			foreach (Entry value2 in roster.Values)
			{
				value2.Entered = 0L;
			}
		}
		serverSeeded = true;
		ZPackage val2 = new ZPackage();
		val2.Write(roster.Count);
		foreach (Entry value3 in roster.Values)
		{
			val2.Write(value3.ID);
			val2.Write(value3.Name ?? "Player");
			val2.Write(value3.Known);
			val2.Write(value3.Bed);
			val2.Write(value3.Entered);
		}
		List<long> list2 = new List<long>();
		foreach (long subscriber2 in subscribers)
		{
			if (ZNet.instance.GetPeer(subscriber2) == null)
			{
				list2.Add(subscriber2);
				continue;
			}
			rpc.InvokeRoutedRPC(subscriber2, "Saga2_BedRoster", new object[1] { val2 });
		}
		foreach (long item4 in list2)
		{
			subscribers.Remove(item4);
			requested.Remove(item4);
		}
		if ((Object)(object)Player.m_localPlayer != (Object)null)
		{
			display.Clear();
			display.AddRange(roster.Values);
			PrepareDisplay();
			received = Time.unscaledTime;
		}
	}

	private void PrepareDisplay()
	{
		long[] array = new long[display.Count];
		for (int i = 0; i < display.Count; i++)
		{
			array[i] = display[i].Entered;
		}
		foreach (Entry item in display)
		{
			item.Rank = SagaBedOrder.Rank(item.Entered, array);
		}
		display.Sort(delegate(Entry a, Entry b)
		{
			int num = ((a.Rank == 0) ? int.MaxValue : a.Rank);
			int value = ((b.Rank == 0) ? int.MaxValue : b.Rank);
			int num2 = num.CompareTo(value);
			return (num2 == 0) ? string.Compare(a.Name, b.Name, StringComparison.OrdinalIgnoreCase) : num2;
		});
	}

	private bool FromServer(long sender)
	{
		ZNetPeer val = (((Object)(object)ZNet.instance == (Object)null) ? null : ZNet.instance.GetServerPeer());
		if (val != null)
		{
			return val.m_uid == sender;
		}
		return false;
	}

	private void Receive(long sender, ZPackage packet)
	{
		if (!FromServer(sender))
		{
			return;
		}
		try
		{
			int num = packet.ReadInt();
			if (num >= 0 && num <= 256)
			{
				List<Entry> list = new List<Entry>();
				for (int i = 0; i < num; i++)
				{
					list.Add(new Entry
					{
						ID = packet.ReadString(),
						Name = packet.ReadString(),
						Known = packet.ReadBool(),
						Bed = packet.ReadBool(),
						Entered = packet.ReadLong()
					});
				}
				display.Clear();
				display.AddRange(list);
				PrepareDisplay();
				received = Time.unscaledTime;
			}
		}
		catch (Exception ex)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)("Ignored incomplete bed roster: " + ex.Message));
		}
	}

	private void Left(long sender, string message)
	{
		if (FromServer(sender))
		{
			ShowLeft(message);
		}
	}

	private void ShowLeft(string message)
	{
		if (show.Value && notices.Value && (Object)(object)Chat.instance != (Object)null)
		{
			((Terminal)Chat.instance).AddString(Safe(message));
		}
	}

	private static string Safe(string text)
	{
		return (text ?? "Player").Replace("<", "").Replace(">", "");
	}

	private void OnGUI()
	{
		//IL_044b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00db: 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)
		//IL_011f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0129: Expected O, but got Unknown
		//IL_018c: Unknown result type (might be due to invalid IL or missing references)
		//IL_028a: Unknown result type (might be due to invalid IL or missing references)
		//IL_028d: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c2: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_02cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_03d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_03f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_03bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a6: Unknown result type (might be due to invalid IL or missing references)
		if (!show.Value || (Object)(object)Player.m_localPlayer == (Object)null || !window.Appearance.InventoryVisible || SagaConfigPreview.MenuVisible() || SagaConfigPreview.MapVisible())
		{
			window.Hide();
			return;
		}
		if (onlyInBed.Value && !SagaConfigPreview.Open && !InventoryGui.IsVisible() && Time.unscaledTime - lastInBed > hideDelay.Value)
		{
			window.Hide();
			return;
		}
		rect = window.Place(new Rect((float)Screen.width * 0.5f - 180f, (float)Screen.height * 0.25f, 360f, (float)Mathf.Min(400, 55 + display.Count * 25)), 0f);
		if (window.Minimized)
		{
			return;
		}
		window.Appearance.Draw(rect, 0.8f, "Bed roster");
		if (label == null)
		{
			label = new GUIStyle(SagaPanelUI.TextStyle(16, (TextAnchor)3));
			label.richText = false;
		}
		if (Time.unscaledTime - received > 5f)
		{
			GUI.Label(new Rect(((Rect)(ref rect)).x + 8f, ((Rect)(ref rect)).y + window.HeaderHeight + 4f, ((Rect)(ref rect)).width - 16f, 45f), "Waiting for server sleep status...", label);
			return;
		}
		long num = long.MaxValue;
		long num2 = 0L;
		bool flag = display.Count > 1;
		foreach (Entry item in display)
		{
			flag &= item.Known && item.Bed;
			if (item.Entered > 0)
			{
				num = Math.Min(num, item.Entered);
				num2 = Math.Max(num2, item.Entered);
			}
		}
		Rect val = default(Rect);
		((Rect)(ref val))..ctor(((Rect)(ref rect)).x + 8f, ((Rect)(ref rect)).y + window.HeaderHeight + 4f, ((Rect)(ref rect)).width - 16f, ((Rect)(ref rect)).height - window.HeaderHeight - 8f);
		scroll = GUI.BeginScrollView(val, scroll, new Rect(0f, 0f, Mathf.Max(1f, ((Rect)(ref val)).width - 20f), (float)(display.Count * 25)));
		try
		{
			for (int i = 0; i < display.Count; i++)
			{
				Entry entry = display[i];
				string text = ((!entry.Known) ? "Unknown" : (entry.Bed ? ("In bed #" + entry.Rank) : "Awake"));
				bool flag2 = entry.Entered > 0 && entry.Entered == num;
				bool flag3 = flag && entry.Entered == num2 && num2 != num;
				if (teasing.Value && flag2)
				{
					text += " - First!";
				}
				else if (teasing.Value && flag3)
				{
					text += " - Finally, sleepyhead!";
				}
				label.normal.textColor = (Color)(flag2 ? new Color(1f, 0.85f, 0.3f) : (flag3 ? new Color(1f, 0.6f, 0.35f) : Color.white));
				GUI.Label(new Rect(0f, (float)(i * 25), ((Rect)(ref val)).width - 20f, 25f), Safe(entry.Name) + "  " + text, label);
			}
		}
		finally
		{
			GUI.EndScrollView();
			label.normal.textColor = Color.white;
		}
	}

	private void OnDestroy()
	{
		if (window != null)
		{
			window.Dispose();
		}
	}
}

BepInEx/plugins/MMC-SkillDrainClock/MMCSkillDrainClock.dll

Decompiled a week ago
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using HarmonyLib;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInPlugin("local.mmc.skilldrainclock", "Saga Buff Bar", "3.0.2")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public sealed class MMCSkillDrainClock : BaseUnityPlugin
{
	private sealed class BoostIcon
	{
		public RectTransform Root;

		public TMP_Text Value;

		public Image Wipe;

		public readonly SagaBoostWipe Clock = new SagaBoostWipe();
	}

	private const string HungryText = "You feel a lil' hungry.";

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

	private readonly List<BoostIcon> boostIcons = new List<BoostIcon>();

	private readonly List<Object> boostAssets = new List<Object>();

	private static readonly FieldInfo boostFoodTimer = AccessTools.Field(typeof(Player), "m_foodUpdateTimer");

	private static readonly Vector2[] BoostBolt = (Vector2[])(object)new Vector2[7]
	{
		new Vector2(0.55f, 1f),
		new Vector2(0.18f, 0.48f),
		new Vector2(0.46f, 0.48f),
		new Vector2(0.31f, 0f),
		new Vector2(0.86f, 0.61f),
		new Vector2(0.57f, 0.61f),
		new Vector2(0.77f, 1f)
	};

	private SagaPanelWindow buffWindow;

	private readonly HashSet<RectTransform> sizedEffects = new HashSet<RectTransform>();

	private Rect buffDefaultPanel;

	private Vector2 buffPanelShift;

	private RectTransform buffHeader;

	private bool buffPanelVisible;

	private ConfigEntry<float> panelOpacity;

	private ConfigEntry<float> panelScale;

	private readonly Dictionary<RectTransform, Vector3> originalBuffScales = new Dictionary<RectTransform, Vector3>();

	private RectTransform panelLayer;

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

	private readonly List<Rect> occupiedRows = new List<Rect>();

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

	private readonly Dictionary<Image, Image> foodHealWipes = new Dictionary<Image, Image>();

	private static readonly FieldInfo regenTimer = AccessTools.Field(typeof(Player), "m_foodRegenTimer");

	private static readonly FieldInfo restingTime = AccessTools.Field(typeof(StatusEffect), "m_time");

	private static MMCSkillDrainClock instance;

	private ConfigEntry<bool> enabledBar;

	private Harmony harmony;

	private FieldInfo clockRect;

	private RectTransform target;

	private RectTransform restedTarget;

	private RectTransform corpseRunTarget;

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

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

	private readonly Dictionary<CanvasGroup, float> foodOriginals = new Dictionary<CanvasGroup, float>();

	private readonly List<CanvasGroup> foodAddedGroups = new List<CanvasGroup>();

	private Hud foodHud;

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

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

	private ConfigEntry<string> debuffNames;

	private readonly Dictionary<Food, bool> foodReadiness = new Dictionary<Food, bool>();

	private readonly List<Food> staleFood = new List<Food>();

	private ConfigEntry<float> anchorX;

	private ConfigEntry<float> anchorY;

	private ConfigEntry<float> gap;

	private ConfigEntry<float> verticalOffset;

	private bool reported;

	private readonly List<MMCBuffWarning> warnings = new List<MMCBuffWarning>();

	public static List<RectTransform> FoodSlots
	{
		get
		{
			if (!((Object)(object)instance == (Object)null))
			{
				return instance.foodTargets;
			}
			return null;
		}
	}

	private static bool BoostShape(int kind, float x, float y)
	{
		switch (kind)
		{
		case 0:
		{
			float num5 = (x - 0.5f) * 2.7f;
			float num6 = (y - 0.46f) * 2.7f;
			float num7 = num5 * num5 + num6 * num6 - 1f;
			return num7 * num7 * num7 - num5 * num5 * num6 * num6 * num6 <= 0f;
		}
		case 2:
		{
			float num3 = (x - 0.5f) / 0.36f;
			float num4 = (y - 0.4f) / 0.36f;
			if (!(y < 0.5f))
			{
				return Mathf.Abs(x - 0.5f) < (0.97f - y) * 0.67f;
			}
			return num3 * num3 + num4 * num4 < 1f;
		}
		default:
		{
			bool flag = false;
			int num = 0;
			int num2 = BoostBolt.Length - 1;
			while (num < BoostBolt.Length)
			{
				if (BoostBolt[num].y > y != BoostBolt[num2].y > y && x < (BoostBolt[num2].x - BoostBolt[num].x) * (y - BoostBolt[num].y) / (BoostBolt[num2].y - BoostBolt[num].y) + BoostBolt[num].x)
				{
					flag = !flag;
				}
				num2 = num++;
			}
			return flag;
		}
		}
	}

	private Sprite BoostSprite(int kind)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Expected O, but got Unknown
		//IL_00af: Unknown result type (might be due to invalid IL or missing references)
		//IL_00be: 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)
		Texture2D val = new Texture2D(64, 64, (TextureFormat)4, false);
		((Texture)val).wrapMode = (TextureWrapMode)1;
		((Texture)val).filterMode = (FilterMode)1;
		Color[] array = (Color[])(object)new Color[4096];
		for (int i = 0; i < 64; i++)
		{
			for (int j = 0; j < 64; j++)
			{
				ref Color reference = ref array[i * 64 + j];
				reference = new Color(1f, 1f, 1f, (float)(BoostShape(kind, ((float)j + 0.5f) / 64f, ((float)i + 0.5f) / 64f) ? 1 : 0));
			}
		}
		val.SetPixels(array);
		val.Apply();
		Sprite val2 = Sprite.Create(val, new Rect(0f, 0f, 64f, 64f), new Vector2(0.5f, 0.5f), 100f);
		boostAssets.Add((Object)(object)val2);
		boostAssets.Add((Object)(object)val);
		return val2;
	}

	private BoostIcon CreateBoost(Hud hud, int kind)
	{
		//IL_014e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0191: Unknown result type (might be due to invalid IL or missing references)
		//IL_0198: Expected O, but got Unknown
		//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01be: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_020d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0288: Unknown result type (might be due to invalid IL or missing references)
		//IL_0133: Unknown result type (might be due to invalid IL or missing references)
		//IL_0118: Unknown result type (might be due to invalid IL or missing references)
		//IL_02dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_032e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0333: Unknown result type (might be due to invalid IL or missing references)
		//IL_0334: Unknown result type (might be due to invalid IL or missing references)
		//IL_033b: Unknown result type (might be due to invalid IL or missing references)
		//IL_034e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0364: Unknown result type (might be due to invalid IL or missing references)
		//IL_037a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0386: Unknown result type (might be due to invalid IL or missing references)
		RectTransform val = Object.Instantiate<RectTransform>(hud.m_statusEffectTemplate, (Transform)(object)hud.m_statusEffectListRoot);
		((Object)val).name = "Saga food boost " + kind;
		Animator[] componentsInChildren = ((Component)val).GetComponentsInChildren<Animator>(true);
		foreach (Animator val2 in componentsInChildren)
		{
			((Behaviour)val2).enabled = false;
		}
		Graphic[] componentsInChildren2 = ((Component)val).GetComponentsInChildren<Graphic>(true);
		foreach (Graphic val3 in componentsInChildren2)
		{
			val3.raycastTarget = false;
		}
		TMP_Text[] componentsInChildren3 = ((Component)val).GetComponentsInChildren<TMP_Text>(true);
		foreach (TMP_Text val4 in componentsInChildren3)
		{
			val4.text = "";
		}
		Transform val5 = ((Transform)val).Find("Cooldown");
		if ((Object)(object)val5 != (Object)null)
		{
			((Component)val5).gameObject.SetActive(false);
		}
		Image component = ((Component)((Transform)val).Find("Icon")).GetComponent<Image>();
		component.sprite = BoostSprite(kind);
		component.type = (Type)0;
		component.preserveAspect = true;
		((Graphic)component).color = (Color)(kind switch
		{
			1 => new Color(1f, 0.8f, 0.12f, 1f), 
			0 => new Color(1f, 0.14f, 0.1f, 1f), 
			_ => new Color(0.7f, 0.3f, 1f, 1f), 
		});
		GameObject val6 = new GameObject("Next boost decrease clock", new Type[3]
		{
			typeof(RectTransform),
			typeof(CanvasRenderer),
			typeof(Image)
		});
		RectTransform component2 = val6.GetComponent<RectTransform>();
		((Transform)component2).SetParent(((Component)component).transform, false);
		component2.anchorMin = Vector2.zero;
		component2.anchorMax = Vector2.one;
		Vector2 offsetMin = (component2.offsetMax = Vector2.zero);
		component2.offsetMin = offsetMin;
		Image component3 = val6.GetComponent<Image>();
		component3.sprite = component.sprite;
		((Graphic)component3).color = new Color(0.42f, 0.42f, 0.42f, 0.85f);
		component3.type = (Type)3;
		component3.fillMethod = (FillMethod)4;
		component3.fillOrigin = 2;
		component3.fillClockwise = true;
		component3.fillAmount = 0f;
		component3.preserveAspect = true;
		((Graphic)component3).raycastTarget = false;
		TMP_Text component4 = ((Component)((Transform)val).Find("TimeText")).GetComponent<TMP_Text>();
		((Component)component4).gameObject.SetActive(true);
		((Graphic)component4).color = new Color(0.35f, 1f, 0.4f, 1f);
		component4.alignment = (TextAlignmentOptions)514;
		TMP_Text val7 = Object.Instantiate<TMP_Text>(component4, ((Component)component).transform);
		((Object)val7).name = "Boost name";
		val7.text = kind switch
		{
			1 => "Max Stamina", 
			0 => "Max Health", 
			_ => "Max Eitr", 
		};
		((Graphic)val7).color = Color.white;
		val7.fontSize = 16f;
		val7.enableAutoSizing = false;
		val7.enableWordWrapping = false;
		val7.alignment = (TextAlignmentOptions)514;
		((Graphic)val7).raycastTarget = false;
		RectTransform rectTransform = val7.rectTransform;
		Vector2 anchorMin = (rectTransform.anchorMax = new Vector2(0.5f, 1f));
		rectTransform.anchorMin = anchorMin;
		rectTransform.pivot = new Vector2(0.5f, 0f);
		rectTransform.anchoredPosition = new Vector2(0f, 4f);
		rectTransform.sizeDelta = new Vector2(120f, 24f);
		((Transform)rectTransform).localScale = Vector3.one;
		((Component)val).gameObject.SetActive(true);
		BoostIcon boostIcon = new BoostIcon();
		boostIcon.Root = val;
		boostIcon.Value = component4;
		boostIcon.Wipe = component3;
		BoostIcon result = boostIcon;
		boostTargets.Add(val);
		return result;
	}

	private void UpdateBoostIcons()
	{
		Hud val = Hud.instance;
		Player localPlayer = Player.m_localPlayer;
		if ((Object)(object)val == (Object)null || (Object)(object)localPlayer == (Object)null)
		{
			return;
		}
		List<Food> foods = localPlayer.GetFoods();
		bool flag = SagaConfigPreview.HudVisible(val) && !((Character)localPlayer).IsDead();
		while (boostIcons.Count < 1)
		{
			boostIcons.Add(CreateBoost(val, 2));
		}
		double timer = ((boostFoodTimer == null) ? 0f : ((float)boostFoodTimer.GetValue(localPlayer)));
		double num = 0.0;
		foreach (Food item in foods)
		{
			num += (double)item.m_time;
		}
		for (int i = 2; i < 3; i++)
		{
			SagaFoodBoostForecast.Food[] array = new SagaFoodBoostForecast.Food[foods.Count];
			for (int j = 0; j < foods.Count; j++)
			{
				Food val2 = foods[j];
				SharedData shared = val2.m_item.m_shared;
				ref SagaFoodBoostForecast.Food reference = ref array[j];
				reference = new SagaFoodBoostForecast.Food
				{
					Remaining = val2.m_time,
					Duration = shared.m_foodBurnTime,
					Base = i switch
					{
						1 => shared.m_foodStamina, 
						0 => shared.m_food, 
						_ => shared.m_foodEitr, 
					},
					Current = i switch
					{
						1 => val2.m_stamina, 
						0 => val2.m_health, 
						_ => val2.m_eitr, 
					}
				};
			}
			int num2 = SagaFoodBoostForecast.Bonus(array);
			BoostIcon boostIcon = boostIcons[i - 2];
			((Component)boostIcon.Root).gameObject.SetActive(flag && num2 > 0);
			boostIcon.Value.text = "+" + num2.ToString(CultureInfo.InvariantCulture);
			double seconds;
			int drop;
			bool predicted = SagaFoodBoostForecast.Predict(array, timer, 1.0, out seconds, out drop);
			boostIcon.Wipe.fillAmount = boostIcon.Clock.Update(num2, num, seconds, predicted);
		}
	}

	private void CleanupBoostIcons()
	{
		foreach (RectTransform boostTarget in boostTargets)
		{
			if ((Object)(object)boostTarget != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)boostTarget).gameObject);
			}
		}
		boostTargets.Clear();
		boostIcons.Clear();
		foreach (Object boostAsset in boostAssets)
		{
			if (boostAsset != (Object)null)
			{
				Object.Destroy(boostAsset);
			}
		}
		boostAssets.Clear();
	}

	private void ApplyBuffScale(RectTransform effect)
	{
		//IL_0025: 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_0046: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		if (!originalBuffScales.TryGetValue(effect, out var value))
		{
			value = ((Transform)effect).localScale;
			originalBuffScales.Add(effect, value);
		}
		((Transform)effect).localScale = value * panelScale.Value * buffWindow.Appearance.Scale;
	}

	private void RestoreBuffScales()
	{
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		foreach (KeyValuePair<RectTransform, Vector3> originalBuffScale in originalBuffScales)
		{
			if ((Object)(object)originalBuffScale.Key != (Object)null)
			{
				((Transform)originalBuffScale.Key).localScale = originalBuffScale.Value;
			}
		}
		originalBuffScales.Clear();
	}

	private void OnGUI()
	{
		//IL_004a: 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)
		if (!enabledBar.Value || !buffPanelVisible || buffWindow == null || !buffWindow.Appearance.InventoryVisible)
		{
			if (buffWindow != null)
			{
				buffWindow.Hide();
			}
		}
		else
		{
			buffWindow.Place(buffDefaultPanel, 0f);
			buffWindow.DrawHeader();
		}
	}

	private void CleanupBuffPanels()
	{
		//IL_004d: 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)
		RestoreBuffScales();
		if (buffWindow != null)
		{
			buffWindow.RestoreContent();
		}
		if ((Object)(object)panelLayer != (Object)null)
		{
			Object.Destroy((Object)(object)((Component)panelLayer).gameObject);
		}
		panelLayer = null;
		buffHeader = null;
		buffPanelVisible = false;
		buffPanelShift = Vector2.zero;
		if (buffWindow != null)
		{
			buffWindow.Hide();
		}
		panelRows.Clear();
		occupiedRows.Clear();
		panelEffects.Clear();
		sizedEffects.Clear();
	}

	private Image PanelImage(string name, Transform parent, Color color)
	{
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0036: Expected O, but got Unknown
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = new GameObject(name, new Type[3]
		{
			typeof(RectTransform),
			typeof(CanvasRenderer),
			typeof(Image)
		});
		val.transform.SetParent(parent, false);
		Image component = val.GetComponent<Image>();
		((Graphic)component).color = color;
		((Graphic)component).raycastTarget = false;
		return component;
	}

	private RectTransform CreatePanelRow()
	{
		//IL_0026: 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_004a: 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_0052: 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_0055: 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_0085: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_011b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0130: 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_00bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
		//IL_0167: Unknown result type (might be due to invalid IL or missing references)
		//IL_0104: Unknown result type (might be due to invalid IL or missing references)
		Image val = PanelImage("Saga buff row", (Transform)(object)panelLayer, new Color(0.035f, 0.04f, 0.035f, panelOpacity.Value));
		RectTransform rectTransform = ((Graphic)val).rectTransform;
		Vector2 val2 = (rectTransform.pivot = new Vector2(0.5f, 0.5f));
		Vector2 anchorMin = (rectTransform.anchorMax = val2);
		rectTransform.anchorMin = anchorMin;
		for (int i = 0; i < 4; i++)
		{
			Image val5 = PanelImage("Bronze edge", (Transform)(object)rectTransform, new Color(0.48f, 0.33f, 0.17f, 0.65f));
			RectTransform rectTransform2 = ((Graphic)val5).rectTransform;
			rectTransform2.pivot = new Vector2(0.5f, 0.5f);
			if (i < 2)
			{
				rectTransform2.anchorMin = new Vector2((float)i, 0f);
				rectTransform2.anchorMax = new Vector2((float)i, 1f);
				rectTransform2.sizeDelta = new Vector2(1f, 0f);
				rectTransform2.anchoredPosition = new Vector2((i == 0) ? 0.5f : (-0.5f), 0f);
			}
			else
			{
				rectTransform2.anchorMin = new Vector2(0f, (float)(i - 2));
				rectTransform2.anchorMax = new Vector2(1f, (float)(i - 2));
				rectTransform2.sizeDelta = new Vector2(0f, 1f);
				rectTransform2.anchoredPosition = new Vector2(0f, (i == 2) ? 0.5f : (-0.5f));
			}
		}
		return rectTransform;
	}

	private void UpdateBuffPanels()
	{
		//IL_009b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_03db: Unknown result type (might be due to invalid IL or missing references)
		//IL_03e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_03c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_03ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_020b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0210: Unknown result type (might be due to invalid IL or missing references)
		//IL_0217: Unknown result type (might be due to invalid IL or missing references)
		//IL_021c: 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_0226: Unknown result type (might be due to invalid IL or missing references)
		//IL_022d: 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_0237: Unknown result type (might be due to invalid IL or missing references)
		//IL_023c: Unknown result type (might be due to invalid IL or missing references)
		//IL_028a: Unknown result type (might be due to invalid IL or missing references)
		//IL_028f: Unknown result type (might be due to invalid IL or missing references)
		//IL_03f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_03f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0446: Unknown result type (might be due to invalid IL or missing references)
		//IL_044b: Unknown result type (might be due to invalid IL or missing references)
		//IL_04d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_04dd: Unknown result type (might be due to invalid IL or missing references)
		//IL_04e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_04ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_04f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_05b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_05bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_02c8: Unknown result type (might be due to invalid IL or missing references)
		//IL_031c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0321: Unknown result type (might be due to invalid IL or missing references)
		//IL_0377: Unknown result type (might be due to invalid IL or missing references)
		//IL_030b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0760: Unknown result type (might be due to invalid IL or missing references)
		//IL_090c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0937: Unknown result type (might be due to invalid IL or missing references)
		//IL_0960: Unknown result type (might be due to invalid IL or missing references)
		//IL_0974: Unknown result type (might be due to invalid IL or missing references)
		//IL_0976: Unknown result type (might be due to invalid IL or missing references)
		//IL_0978: Unknown result type (might be due to invalid IL or missing references)
		//IL_0988: Unknown result type (might be due to invalid IL or missing references)
		//IL_098a: Unknown result type (might be due to invalid IL or missing references)
		//IL_098c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0996: Unknown result type (might be due to invalid IL or missing references)
		//IL_099b: Unknown result type (might be due to invalid IL or missing references)
		//IL_079c: Unknown result type (might be due to invalid IL or missing references)
		//IL_07cc: Unknown result type (might be due to invalid IL or missing references)
		//IL_07d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_07d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_07d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_07db: Unknown result type (might be due to invalid IL or missing references)
		//IL_07dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_07e3: Unknown result type (might be due to invalid IL or missing references)
		//IL_0823: Unknown result type (might be due to invalid IL or missing references)
		//IL_082a: Expected O, but got Unknown
		//IL_0843: Unknown result type (might be due to invalid IL or missing references)
		//IL_084f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0865: Unknown result type (might be due to invalid IL or missing references)
		//IL_087b: Unknown result type (might be due to invalid IL or missing references)
		//IL_08ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_0648: Unknown result type (might be due to invalid IL or missing references)
		//IL_065f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0664: Unknown result type (might be due to invalid IL or missing references)
		//IL_0669: Unknown result type (might be due to invalid IL or missing references)
		//IL_066b: Unknown result type (might be due to invalid IL or missing references)
		//IL_066d: Unknown result type (might be due to invalid IL or missing references)
		//IL_066f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0671: Unknown result type (might be due to invalid IL or missing references)
		//IL_0678: Unknown result type (might be due to invalid IL or missing references)
		//IL_067d: 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_0684: Unknown result type (might be due to invalid IL or missing references)
		//IL_0689: Unknown result type (might be due to invalid IL or missing references)
		//IL_068e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0695: Unknown result type (might be due to invalid IL or missing references)
		//IL_06a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_06b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_06c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_06c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_06c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_06c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_06ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a23: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a28: Unknown result type (might be due to invalid IL or missing references)
		//IL_0a5e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0aa6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0ab6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0ab8: 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_0ac6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0ac8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0aca: Unknown result type (might be due to invalid IL or missing references)
		//IL_0ad4: Unknown result type (might be due to invalid IL or missing references)
		//IL_0ad9: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b00: Unknown result type (might be due to invalid IL or missing references)
		//IL_0b4b: Unknown result type (might be due to invalid IL or missing references)
		buffPanelVisible = false;
		Hud val = Hud.instance;
		if ((Object)(object)val == (Object)null || (Object)(object)Player.m_localPlayer == (Object)null || ((Character)Player.m_localPlayer).IsDead() || (!SagaConfigPreview.HudVisible(val) && !SagaConfigPreview.InventoryHidesHud()))
		{
			if ((Object)(object)panelLayer != (Object)null)
			{
				((Component)panelLayer).gameObject.SetActive(false);
			}
			return;
		}
		RectTransform statusEffectListRoot = val.m_statusEffectListRoot;
		if ((Object)(object)statusEffectListRoot == (Object)null)
		{
			return;
		}
		if ((Object)(object)panelLayer == (Object)null)
		{
			panelLayer = new GameObject("Saga buff panels", new Type[1] { typeof(RectTransform) }).GetComponent<RectTransform>();
			((Transform)panelLayer).SetParent((Transform)(object)statusEffectListRoot, false);
			((Transform)panelLayer).localPosition = Vector3.zero;
			((Transform)panelLayer).SetAsFirstSibling();
		}
		Canvas componentInParent = ((Component)statusEffectListRoot).GetComponentInParent<Canvas>();
		Camera val2 = (((Object)(object)componentInParent == (Object)null || (int)componentInParent.renderMode == 0) ? null : componentInParent.worldCamera);
		occupiedRows.Clear();
		panelEffects.Clear();
		panelEffects.Add(target);
		panelEffects.Add(restedTarget);
		panelEffects.Add(corpseRunTarget);
		panelEffects.AddRange(boostTargets);
		panelEffects.AddRange(powerTargets);
		panelEffects.AddRange(otherTargets);
		panelEffects.AddRange(debuffTargets);
		foreach (RectTransform panelEffect in panelEffects)
		{
			if ((Object)(object)panelEffect == (Object)null || !((Component)panelEffect).gameObject.activeInHierarchy)
			{
				continue;
			}
			if (!boostTargets.Contains(panelEffect) && sizedEffects.Add(panelEffect))
			{
				TMP_Text[] componentsInChildren = ((Component)panelEffect).GetComponentsInChildren<TMP_Text>(true);
				foreach (TMP_Text val3 in componentsInChildren)
				{
					buffWindow.MatchText(val3);
				}
			}
			Bounds val4 = RectTransformUtility.CalculateRelativeRectTransformBounds((Transform)(object)panelEffect);
			Vector2 val5 = RectTransformUtility.WorldToScreenPoint(val2, ((Transform)panelEffect).TransformPoint(((Bounds)(ref val4)).min));
			Vector2 val6 = RectTransformUtility.WorldToScreenPoint(val2, ((Transform)panelEffect).TransformPoint(((Bounds)(ref val4)).max));
			Rect item = Rect.MinMaxRect(Mathf.Min(val5.x, val6.x), Mathf.Min(val5.y, val6.y), Mathf.Max(val5.x, val6.x), Mathf.Max(val5.y, val6.y));
			if (((Rect)(ref item)).width <= 0f || ((Rect)(ref item)).height <= 0f)
			{
				continue;
			}
			int num = -1;
			for (int j = 0; j < occupiedRows.Count; j++)
			{
				Rect val7 = occupiedRows[j];
				if (Mathf.Abs(((Rect)(ref val7)).yMax - ((Rect)(ref item)).yMax) < 8f)
				{
					num = j;
					break;
				}
			}
			if (num < 0)
			{
				occupiedRows.Add(item);
				continue;
			}
			Rect val8 = occupiedRows[num];
			occupiedRows[num] = Rect.MinMaxRect(Mathf.Min(((Rect)(ref val8)).xMin, ((Rect)(ref item)).xMin), Mathf.Min(((Rect)(ref val8)).yMin, ((Rect)(ref item)).yMin), Mathf.Max(((Rect)(ref val8)).xMax, ((Rect)(ref item)).xMax), Mathf.Max(((Rect)(ref val8)).yMax, ((Rect)(ref item)).yMax));
		}
		((Component)panelLayer).gameObject.SetActive(occupiedRows.Count > 0);
		if (occupiedRows.Count == 0)
		{
			buffPanelShift = Vector2.zero;
			return;
		}
		Rect val9 = occupiedRows[0];
		foreach (Rect occupiedRow in occupiedRows)
		{
			Rect current2 = occupiedRow;
			val9 = Rect.MinMaxRect(Mathf.Min(((Rect)(ref val9)).xMin, ((Rect)(ref current2)).xMin), Mathf.Min(((Rect)(ref val9)).yMin, ((Rect)(ref current2)).yMin), Mathf.Max(((Rect)(ref val9)).xMax, ((Rect)(ref current2)).xMax), Mathf.Max(((Rect)(ref val9)).yMax, ((Rect)(ref current2)).yMax));
		}
		buffDefaultPanel = new Rect(Mathf.Max(0f, ((Rect)(ref val9)).xMin - 6f), Mathf.Max(4f, (float)Screen.height - ((Rect)(ref val9)).yMax - buffWindow.HeaderHeight - 6f), Mathf.Max(180f, ((Rect)(ref val9)).width + 12f), ((Rect)(ref val9)).height + buffWindow.HeaderHeight + 12f);
		Rect val10 = buffWindow.Resolve(buffDefaultPanel);
		float num2 = Mathf.Min(1f, Mathf.Min(Mathf.Max(1f, ((Rect)(ref val10)).width - 12f) / Mathf.Max(1f, ((Rect)(ref val9)).width), Mathf.Max(1f, ((Rect)(ref val10)).height - buffWindow.HeaderHeight - 12f) / Mathf.Max(1f, ((Rect)(ref val9)).height)));
		Vector2 val11 = default(Vector2);
		((Vector2)(ref val11))..ctor(((Rect)(ref val9)).xMin, ((Rect)(ref val9)).yMax);
		buffPanelShift = new Vector2(((Rect)(ref val10)).x + 6f - ((Rect)(ref val9)).xMin, ((Rect)(ref val10)).y + buffWindow.HeaderHeight + 6f - ((float)Screen.height - ((Rect)(ref val9)).yMax));
		Vector2 val12 = default(Vector2);
		((Vector2)(ref val12))..ctor(buffPanelShift.x, 0f - buffPanelShift.y);
		Vector2 val17 = default(Vector2);
		Vector2 val18 = default(Vector2);
		foreach (RectTransform panelEffect2 in panelEffects)
		{
			if ((Object)(object)panelEffect2 == (Object)null || !((Component)panelEffect2).gameObject.activeInHierarchy)
			{
				continue;
			}
			Transform parent = ((Transform)panelEffect2).parent;
			RectTransform val13 = (RectTransform)(object)((parent is RectTransform) ? parent : null);
			if (!((Object)(object)val13 == (Object)null))
			{
				Canvas componentInParent2 = ((Component)panelEffect2).GetComponentInParent<Canvas>();
				Camera val14 = (((Object)(object)componentInParent2 == (Object)null || (int)componentInParent2.renderMode == 0) ? null : componentInParent2.worldCamera);
				Vector2 val15 = RectTransformUtility.WorldToScreenPoint(val14, ((Transform)panelEffect2).position);
				Vector2 val16 = val11 + (val15 - val11) * num2 + val12;
				((Transform)panelEffect2).localScale = ((Transform)panelEffect2).localScale * num2;
				if (RectTransformUtility.ScreenPointToLocalPointInRectangle(val13, val15, val14, ref val17) && RectTransformUtility.ScreenPointToLocalPointInRectangle(val13, val16, val14, ref val18))
				{
					panelEffect2.anchoredPosition += val18 - val17;
				}
			}
		}
		occupiedRows.Clear();
		occupiedRows.Add(new Rect(((Rect)(ref val10)).x + 6f, (float)Screen.height - ((Rect)(ref val10)).yMax + 6f, Mathf.Max(1f, ((Rect)(ref val10)).width - 12f), Mathf.Max(1f, ((Rect)(ref val10)).height - buffWindow.HeaderHeight - 12f)));
		if ((Object)(object)buffHeader == (Object)null)
		{
			buffHeader = ((Graphic)PanelImage("SagaBuffsPro header", (Transform)(object)panelLayer, new Color(0.16f, 0.105f, 0.055f, 0.93f))).rectTransform;
			RectTransform obj = buffHeader;
			RectTransform obj2 = buffHeader;
			Vector2 val19 = (buffHeader.pivot = new Vector2(0.5f, 0.5f));
			Vector2 anchorMin = (obj2.anchorMax = val19);
			obj.anchorMin = anchorMin;
			GameObject val22 = new GameObject("Title", new Type[3]
			{
				typeof(RectTransform),
				typeof(CanvasRenderer),
				typeof(TextMeshProUGUI)
			});
			RectTransform component = val22.GetComponent<RectTransform>();
			((Transform)component).SetParent((Transform)(object)buffHeader, false);
			component.anchorMin = Vector2.zero;
			component.anchorMax = Vector2.one;
			component.offsetMin = new Vector2(10f, 0f);
			component.offsetMax = new Vector2(-10f, 0f);
			TMP_Text component2 = val22.GetComponent<TMP_Text>();
			component2.font = val.m_healthText.font;
			component2.fontSize = 16f;
			component2.text = "";
			((Graphic)component2).color = SagaPanelUI.TextColor;
			component2.alignment = (TextAlignmentOptions)4097;
			((Graphic)component2).raycastTarget = false;
		}
		((Component)buffHeader).gameObject.SetActive(!buffWindow.ToolWindow);
		((Graphic)((Component)buffHeader).GetComponent<Image>()).color = buffWindow.Appearance.Header;
		Vector2 val23 = default(Vector2);
		RectTransformUtility.ScreenPointToLocalPointInRectangle(panelLayer, new Vector2(((Rect)(ref val10)).x, (float)Screen.height - ((Rect)(ref val10)).y - 31f), val2, ref val23);
		Vector2 val24 = default(Vector2);
		RectTransformUtility.ScreenPointToLocalPointInRectangle(panelLayer, new Vector2(((Rect)(ref val10)).xMax, (float)Screen.height - ((Rect)(ref val10)).y), val2, ref val24);
		buffHeader.sizeDelta = val24 - val23;
		((Transform)buffHeader).localPosition = Vector2.op_Implicit((val23 + val24) * 0.5f);
		buffPanelVisible = true;
		while (panelRows.Count < occupiedRows.Count)
		{
			panelRows.Add(CreatePanelRow());
		}
		Vector2 val27 = default(Vector2);
		Vector2 val28 = default(Vector2);
		for (int k = 0; k < panelRows.Count; k++)
		{
			RectTransform val25 = panelRows[k];
			((Component)val25).gameObject.SetActive(k < occupiedRows.Count);
			if (k >= occupiedRows.Count)
			{
				continue;
			}
			Rect val26 = occupiedRows[k];
			RectTransformUtility.ScreenPointToLocalPointInRectangle(panelLayer, new Vector2(Mathf.Max(1f, ((Rect)(ref val26)).xMin - 6f), Mathf.Max(1f, ((Rect)(ref val26)).yMin - 6f)), val2, ref val27);
			RectTransformUtility.ScreenPointToLocalPointInRectangle(panelLayer, new Vector2(Mathf.Min((float)(Screen.width - 1), ((Rect)(ref val26)).xMax + 6f), Mathf.Min((float)(Screen.height - 1), ((Rect)(ref val26)).yMax + 6f)), val2, ref val28);
			val25.sizeDelta = val28 - val27;
			((Transform)val25).localPosition = Vector2.op_Implicit((val27 + val28) * 0.5f);
			((Graphic)((Component)val25).GetComponent<Image>()).color = buffWindow.Appearance.Background(panelOpacity.Value);
			for (int l = 0; l < ((Transform)val25).childCount; l++)
			{
				Image component3 = ((Component)((Transform)val25).GetChild(l)).GetComponent<Image>();
				if ((Object)(object)component3 != (Object)null)
				{
					((Behaviour)component3).enabled = !buffWindow.ToolWindow;
					((Graphic)component3).color = buffWindow.Appearance.Border;
				}
			}
		}
		((Transform)panelLayer).SetAsFirstSibling();
		buffWindow.ContentVisible(((Component)panelLayer).gameObject, !buffWindow.Minimized);
		foreach (RectTransform panelEffect3 in panelEffects)
		{
			if ((Object)(object)panelEffect3 != (Object)null)
			{
				buffWindow.ContentVisible(((Component)panelEffect3).gameObject, !buffWindow.Minimized);
			}
		}
	}

	private void UpdateFoodHealWipe(Image icon, Food food)
	{
		//IL_010b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0112: Expected O, but got Unknown
		//IL_012b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0137: Unknown result type (might be due to invalid IL or missing references)
		//IL_0145: Unknown result type (might be due to invalid IL or missing references)
		//IL_014a: 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_0152: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
		Player localPlayer = Player.m_localPlayer;
		float num = 0f;
		bool flag = (Object)(object)localPlayer != (Object)null && !((Character)localPlayer).IsDead() && !((Character)localPlayer).IsTeleporting() && !((Character)localPlayer).InIntro() && food.m_item != null && food.m_item.m_shared.m_foodRegen > 0f && ((Character)localPlayer).GetHealth() < ((Character)localPlayer).GetMaxHealth() - 0.001f;
		if (flag)
		{
			num = Mathf.Clamp(10f - (float)regenTimer.GetValue(localPlayer), 0f, 10f);
			float num2 = 1f;
			((Character)localPlayer).GetSEMan().ModifyHealthRegen(ref num2);
			flag = num2 > 0f && food.m_time > num * Game.m_foodRate;
		}
		if (!foodHealWipes.TryGetValue(icon, out var value))
		{
			if (!flag)
			{
				return;
			}
			GameObject val = new GameObject("Food healing reverse wipe", new Type[3]
			{
				typeof(RectTransform),
				typeof(CanvasRenderer),
				typeof(Image)
			});
			RectTransform component = val.GetComponent<RectTransform>();
			((Transform)component).SetParent(((Component)icon).transform, false);
			component.anchorMin = Vector2.zero;
			component.anchorMax = Vector2.one;
			Vector2 offsetMin = (component.offsetMax = Vector2.zero);
			component.offsetMin = offsetMin;
			value = val.GetComponent<Image>();
			((Graphic)value).raycastTarget = false;
			value.type = (Type)3;
			value.fillMethod = (FillMethod)4;
			value.fillOrigin = 2;
			value.fillClockwise = false;
			((Graphic)value).color = new Color(0.42f, 0.42f, 0.42f, 0.85f);
			value.preserveAspect = icon.preserveAspect;
			foodHealWipes.Add(icon, value);
		}
		((Behaviour)value).enabled = flag;
		if (flag)
		{
			value.sprite = icon.sprite;
			value.fillAmount = num / 10f;
		}
	}

	private void CleanupFoodHealWipes()
	{
		foreach (Image value in foodHealWipes.Values)
		{
			if ((Object)(object)value != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)value).gameObject);
			}
		}
		foodHealWipes.Clear();
	}

	private void UpdateRestingSweep(RectTransform item, StatusEffect effect)
	{
		//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ab: Expected O, but got Unknown
		//IL_00bf: 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_00d9: 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)
		//IL_00df: 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_0134: Unknown result type (might be due to invalid IL or missing references)
		Transform val = ((Transform)item).Find("Icon");
		if ((Object)(object)val == (Object)null)
		{
			return;
		}
		Transform val2 = val.Find("Resting countdown");
		SE_Cozy val3 = (SE_Cozy)(object)((effect is SE_Cozy) ? effect : null);
		float num = (((Object)(object)val3 == (Object)null) ? 0f : Mathf.Max(0f, val3.m_delay - (float)restingTime.GetValue(val3)));
		if ((Object)(object)val2 == (Object)null && num <= 0f)
		{
			return;
		}
		Image component2;
		if ((Object)(object)val2 == (Object)null)
		{
			GameObject val4 = new GameObject("Resting countdown", new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			RectTransform component = val4.GetComponent<RectTransform>();
			((Transform)component).SetParent(val, false);
			component.anchorMin = Vector2.zero;
			component.anchorMax = Vector2.one;
			Vector2 offsetMin = (component.offsetMax = Vector2.zero);
			component.offsetMin = offsetMin;
			component2 = val4.GetComponent<Image>();
			((Graphic)component2).raycastTarget = false;
			component2.type = (Type)3;
			component2.fillMethod = (FillMethod)4;
			component2.fillOrigin = 2;
			component2.fillClockwise = false;
			((Graphic)component2).color = new Color(0.42f, 0.42f, 0.42f, 0.85f);
		}
		else
		{
			component2 = ((Component)val2).GetComponent<Image>();
		}
		((Behaviour)component2).enabled = num > 0f;
		if (num > 0f)
		{
			component2.sprite = ((Component)val).GetComponent<Image>().sprite;
			component2.fillAmount = num / Mathf.Max(0.01f, val3.m_delay);
			Transform val5 = ((Transform)item).Find("TimeText");
			if ((Object)(object)val5 != (Object)null)
			{
				TMP_Text component3 = ((Component)val5).GetComponent<TMP_Text>();
				((Component)component3).gameObject.SetActive(true);
				component3.text = MMCBuffTime.Format(num);
			}
			SetWarning(item, warn: false);
		}
	}

	private void Awake()
	{
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: Expected O, but got Unknown
		//IL_007e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0088: Expected O, but got Unknown
		//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c7: Expected O, but got Unknown
		//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fb: Expected O, but got Unknown
		//IL_0228: Unknown result type (might be due to invalid IL or missing references)
		//IL_0235: Expected O, but got Unknown
		//IL_0262: Unknown result type (might be due to invalid IL or missing references)
		//IL_0270: Expected O, but got Unknown
		instance = this;
		enabledBar = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "Enabled", true, "Enable the custom buff/debuff bar. Disabling restores native status-effect placement; Food and Power keeps its separate setting.");
		buffWindow = new SagaPanelWindow(((BaseUnityPlugin)this).Config, "Buff Bar");
		buffWindow.Appearance.ForceToolWindow = true;
		panelScale = ((BaseUnityPlugin)this).Config.Bind<float>("Panel", "Scale", 1f, new ConfigDescription("Live size of buff, debuff and food icons, labels and timer effects. 1 = original size; 0.5 = half; 2 = double. The panel resizes and wraps automatically.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 2f), new object[0]));
		panelOpacity = ((BaseUnityPlugin)this).Config.Bind<float>("Panel", "Background Opacity", 0.28f, new ConfigDescription("Opacity of the dynamic buff/debuff panels.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), new object[0]));
		debuffNames = ((BaseUnityPlugin)this).Config.Bind<string>("Position", "Debuff Names", "Wet,Cold,Freezing,Burning,Poison,Frost,Spirit,Tared,Puke,Smoked,Slimed", "Comma-separated internal status-effect names to place farther left. Add names from modded debuffs here.");
		anchorX = ((BaseUnityPlugin)this).Config.Bind<float>("Position", "Buff Anchor X", 0.48f, "Horizontal screen fraction for the independent center buff anchor.");
		anchorY = ((BaseUnityPlugin)this).Config.Bind<float>("Position", "Buff Anchor Y", 0f, "Vertical screen fraction for the independent center buff anchor.");
		gap = ((BaseUnityPlugin)this).Config.Bind<float>("Position", "Gap", 20f, "Pixels between the clock and its status effects.");
		verticalOffset = ((BaseUnityPlugin)this).Config.Bind<float>("Position", "Vertical Offset", 0f, "Pixels below the clock's top edge. Positive moves down.");
		Type type = ((object)Chainloader.PluginInfos["Azumatt.AzuClock"].Instance).GetType();
		clockRect = AccessTools.Field(type, "_windowRect");
		if (clockRect == null || clockRect.FieldType != typeof(Rect))
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"Unsupported AzuClock version: clock rectangle missing. HUD left unchanged.");
			return;
		}
		harmony = new Harmony("local.mmc.skilldrainclock");
		harmony.Patch((MethodBase)AccessTools.Method(typeof(Hud), "UpdateStatusEffects", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(typeof(MMCSkillDrainClock), "AfterStatusEffects", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		harmony.Patch((MethodBase)AccessTools.Method(typeof(Character), "Message", (Type[])null, (Type[])null), new HarmonyMethod(typeof(MMCSkillDrainClock), "FoodMessage", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Rested, Corpse Run and active Forsaken powers appear left of AzuClock; No skill drain appears right.");
	}

	private static void FoodMessage(Character __instance, ref string __1)
	{
		if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer && __1 == "$msg_food_done")
		{
			__1 = "You feel a lil' hungry.";
		}
	}

	private static void AfterStatusEffects(List<StatusEffect> __0, List<RectTransform> ___m_statusEffects, float ___m_statusEffectSpacing, int ___m_effectsPerRow)
	{
		//IL_029f: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)instance == (Object)null)
		{
			return;
		}
		if (!instance.enabledBar.Value)
		{
			foreach (RectTransform ___m_statusEffect in ___m_statusEffects)
			{
				if ((Object)(object)___m_statusEffect != (Object)null)
				{
					MMCBuffWarning componentInChildren = ((Component)___m_statusEffect).GetComponentInChildren<MMCBuffWarning>(true);
					if ((Object)(object)componentInChildren != (Object)null)
					{
						((Component)componentInChildren).gameObject.SetActive(false);
					}
					Transform val = ((Transform)___m_statusEffect).Find("Icon");
					Transform val2 = (((Object)(object)val == (Object)null) ? null : val.Find("Resting countdown"));
					if ((Object)(object)val2 != (Object)null)
					{
						((Behaviour)((Component)val2).GetComponent<Image>()).enabled = false;
					}
				}
			}
			return;
		}
		instance.target = null;
		instance.restedTarget = null;
		instance.corpseRunTarget = null;
		instance.powerTargets.Clear();
		instance.otherTargets.Clear();
		instance.debuffTargets.Clear();
		int num = 0;
		for (int i = 0; i < ___m_statusEffects.Count && i < __0.Count; i++)
		{
			RectTransform val3 = ___m_statusEffects[i];
			if ((Object)(object)val3 == (Object)null)
			{
				continue;
			}
			StatusEffect val4 = __0[i];
			bool flag = (Object)(object)val4 != (Object)null && !val4.m_hidden;
			((Component)val3).gameObject.SetActive(flag);
			if (!flag)
			{
				continue;
			}
			if ((Object)(object)val4 != (Object)null && !val4.m_hidden && val4.m_ttl > 0f)
			{
				instance.UpdateBuffTimer(val3, Mathf.Max(0f, val4.GetRemaningTime()), timerVisible: true);
			}
			else
			{
				instance.SetWarning(val3, warn: false);
			}
			instance.UpdateRestingSweep(val3, val4);
			bool flag2 = (Object)(object)val4 != (Object)null && (((Object)val4).name == "SoftDeath" || ((Object)val4).name == "SoftDeath(Clone)");
			bool flag3 = (Object)(object)val4 != (Object)null && (((Object)val4).name == "Rested" || ((Object)val4).name == "Rested(Clone)");
			bool flag4 = (Object)(object)val4 != (Object)null && (((Object)val4).name == "CorpseRun" || ((Object)val4).name == "CorpseRun(Clone)");
			bool flag5 = (Object)(object)val4 != (Object)null && ((Object)val4).name.StartsWith("GP_", StringComparison.Ordinal);
			int num2 = num / Math.Max(1, ___m_effectsPerRow);
			int num3 = num % Math.Max(1, ___m_effectsPerRow);
			val3.anchoredPosition = new Vector2(-4f - (float)num3 * ___m_statusEffectSpacing, (float)(-num2) * ___m_statusEffectSpacing);
			num++;
			if (flag2)
			{
				instance.target = val3;
			}
			else if (flag3)
			{
				instance.restedTarget = val3;
			}
			else if (flag4)
			{
				instance.corpseRunTarget = val3;
			}
			else if (flag5)
			{
				instance.powerTargets.Add(val3);
			}
			else if ((Object)(object)val4 != (Object)null && !val4.m_hidden)
			{
				if (instance.IsDebuff(val4))
				{
					instance.debuffTargets.Add(val3);
				}
				else
				{
					instance.otherTargets.Add(val3);
				}
			}
		}
		instance.PlaceTimer();
	}

	private void UpdateBuffTimer(RectTransform item, float seconds, bool timerVisible)
	{
		Transform val = ((Transform)item).Find("TimeText");
		if ((Object)(object)val != (Object)null)
		{
			TMP_Text component = ((Component)val).GetComponent<TMP_Text>();
			if ((Object)(object)component != (Object)null)
			{
				((Component)component).gameObject.SetActive(timerVisible);
				component.text = MMCBuffTime.Format(seconds);
			}
		}
		SetWarning(item, MMCFoodReadiness.Expiry(seconds));
	}

	private void SetWarning(RectTransform item, bool warn)
	{
		SetWarning(item, warn ? MMCBuffBorder.ExpiringRed : MMCBuffBorder.None);
	}

	private void SetWarning(RectTransform item, MMCBuffBorder mode)
	{
		//IL_007c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0083: Expected O, but got Unknown
		//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_00b1: 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_00b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00be: Unknown result type (might be due to invalid IL or missing references)
		bool flag = mode != MMCBuffBorder.None;
		Transform val = ((Transform)item).Find("Icon");
		if ((Object)(object)val == (Object)null)
		{
			return;
		}
		Transform val2 = val.Find("MMC Expiry Warning");
		if ((Object)(object)val2 == (Object)null && !flag)
		{
			return;
		}
		MMCBuffWarning component2;
		if ((Object)(object)val2 == (Object)null)
		{
			GameObject val3 = new GameObject("MMC Expiry Warning", new Type[3]
			{
				typeof(RectTransform),
				typeof(CanvasRenderer),
				typeof(MMCBuffWarning)
			});
			RectTransform component = val3.GetComponent<RectTransform>();
			((Transform)component).SetParent(val, false);
			component.anchorMin = Vector2.zero;
			component.anchorMax = Vector2.one;
			Vector2 offsetMin = (component.offsetMax = Vector2.zero);
			component.offsetMin = offsetMin;
			component2 = val3.GetComponent<MMCBuffWarning>();
			warnings.Add(component2);
		}
		else
		{
			component2 = ((Component)val2).GetComponent<MMCBuffWarning>();
		}
		if (!((Object)(object)component2 == (Object)null))
		{
			component2.Mode = mode;
			((Component)component2).gameObject.SetActive(flag);
			if (flag)
			{
				component2.Pulse();
			}
		}
	}

	private void LateUpdate()
	{
		UpdateFoods();
		foreach (RectTransform foodTarget in foodTargets)
		{
			if ((Object)(object)foodTarget != (Object)null)
			{
				((Component)foodTarget).gameObject.SetActive(false);
			}
		}
		if (enabledBar.Value)
		{
			UpdateBoostIcons();
			PlaceTimer();
			UpdateBuffPanels();
		}
		else
		{
			if ((Object)(object)panelLayer != (Object)null)
			{
				CleanupBuffPanels();
			}
			foreach (RectTransform boostTarget in boostTargets)
			{
				if ((Object)(object)boostTarget != (Object)null)
				{
					((Component)boostTarget).gameObject.SetActive(false);
				}
			}
		}
		warnings.RemoveAll((MMCBuffWarning w) => (Object)(object)w == (Object)null);
		foreach (MMCBuffWarning warning in warnings)
		{
			if (((Component)warning).gameObject.activeInHierarchy)
			{
				warning.Pulse();
			}
		}
	}

	private void PlaceTimer()
	{
		//IL_000e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		if (!enabledBar.Value)
		{
			return;
		}
		Vector3 layout = Vector3.zero;
		PlaceEffect(target, leftOfClock: false, ref layout);
		layout = Vector3.zero;
		for (int num = boostTargets.Count - 1; num >= 0; num--)
		{
			RectTransform val = boostTargets[num];
			if ((Object)(object)val != (Object)null && ((Component)val).gameObject.activeSelf)
			{
				PlaceEffect(val, leftOfClock: true, ref layout);
			}
		}
		PlaceEffect(restedTarget, leftOfClock: true, ref layout);
		PlaceEffect(corpseRunTarget, leftOfClock: true, ref layout);
		foreach (RectTransform powerTarget in powerTargets)
		{
			PlaceEffect(powerTarget, leftOfClock: true, ref layout);
		}
		foreach (RectTransform foodTarget in foodTargets)
		{
			if ((Object)(object)foodTarget != (Object)null && ((Component)foodTarget).gameObject.activeSelf)
			{
				PlaceEffect(foodTarget, leftOfClock: true, ref layout);
			}
		}
		foreach (RectTransform otherTarget in otherTargets)
		{
			PlaceEffect(otherTarget, leftOfClock: true, ref layout);
		}
		if (debuffTargets.Count > 0 && layout.x > 0f)
		{
			layout.x += 12f * panelScale.Value;
		}
		foreach (RectTransform debuffTarget in debuffTargets)
		{
			PlaceEffect(debuffTarget, leftOfClock: true, ref layout);
		}
	}

	private bool IsDebuff(StatusEffect effect)
	{
		string a = ((Object)effect).name.Replace("(Clone)", "").Trim();
		string[] array = debuffNames.Value.Split(new char[1] { ',' });
		foreach (string text in array)
		{
			if (string.Equals(a, text.Trim(), StringComparison.OrdinalIgnoreCase))
			{
				return true;
			}
		}
		return false;
	}

	private static Rect GetBaseBuffAnchor()
	{
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_004f: 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_00c6: Unknown result type (might be due to invalid IL or missing references)
		Rect val = (((Object)(object)instance != (Object)null && instance.clockRect != null) ? ((Rect)instance.clockRect.GetValue(null)) : new Rect(0f, 0f, 100f, 30f));
		return new Rect((float)Screen.width * (((Object)(object)instance == (Object)null) ? 0.48f : instance.anchorX.Value), (float)Screen.height * (((Object)(object)instance == (Object)null) ? 0f : instance.anchorY.Value), Mathf.Max(1f, ((Rect)(ref val)).width), Mathf.Max(1f, ((Rect)(ref val)).height));
	}

	public static Rect GetBuffAnchor()
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0005: 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_0016: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		Rect baseBuffAnchor = GetBaseBuffAnchor();
		if ((Object)(object)instance != (Object)null)
		{
			((Rect)(ref baseBuffAnchor)).position = ((Rect)(ref baseBuffAnchor)).position + instance.buffPanelShift;
		}
		return baseBuffAnchor;
	}

	private void PlaceEffect(RectTransform target, bool leftOfClock, ref Vector3 layout)
	{
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_0069: 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_0080: 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_008b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0090: Unknown result type (might be due to invalid IL or missing references)
		//IL_0095: Unknown result type (might be due to invalid IL or missing references)
		//IL_009b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_0206: 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_0221: Unknown result type (might be due to invalid IL or missing references)
		//IL_0226: Unknown result type (might be due to invalid IL or missing references)
		//IL_0228: Unknown result type (might be due to invalid IL or missing references)
		//IL_022a: Unknown result type (might be due to invalid IL or missing references)
		//IL_022f: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)target == (Object)null || clockRect == null)
		{
			return;
		}
		ApplyBuffScale(target);
		Rect baseBuffAnchor = GetBaseBuffAnchor();
		if (((Rect)(ref baseBuffAnchor)).width <= 0f || ((Rect)(ref baseBuffAnchor)).height <= 0f)
		{
			return;
		}
		Transform parent = ((Transform)target).parent;
		RectTransform val = (RectTransform)(object)((parent is RectTransform) ? parent : null);
		Canvas componentInParent = ((Component)target).GetComponentInParent<Canvas>();
		if ((Object)(object)val == (Object)null || (Object)(object)componentInParent == (Object)null)
		{
			return;
		}
		Camera val2 = (((int)componentInParent.renderMode == 0) ? null : componentInParent.worldCamera);
		Bounds val3 = RectTransformUtility.CalculateRelativeRectTransformBounds((Transform)(object)target);
		Vector2 val4 = RectTransformUtility.WorldToScreenPoint(val2, ((Transform)target).TransformPoint(((Bounds)(ref val3)).min));
		Vector2 val5 = RectTransformUtility.WorldToScreenPoint(val2, ((Transform)target).TransformPoint(((Bounds)(ref val3)).max));
		float num = val5.x - val4.x;
		float num2 = val5.y - val4.y;
		float num3 = Mathf.Max(0f, gap.Value) * panelScale.Value;
		if (leftOfClock && layout.x > 0f && ((Rect)(ref baseBuffAnchor)).xMin - num3 - layout.x - num < 4f)
		{
			layout.y += layout.z + 12f * panelScale.Value;
			layout.x = 0f;
			layout.z = 0f;
		}
		float num4 = Mathf.Clamp(leftOfClock ? (((Rect)(ref baseBuffAnchor)).xMin - num3 - layout.x - num) : (((Rect)(ref baseBuffAnchor)).xMax + num3), 4f, Mathf.Max(4f, (float)Screen.width - num - 4f));
		float num5 = Mathf.Clamp(((Rect)(ref baseBuffAnchor)).yMin + verticalOffset.Value + layout.y, 4f, Mathf.Max(4f, (float)Screen.height - num2 - 4f));
		Vector2 val6 = default(Vector2);
		((Vector2)(ref val6))..ctor(val4.x, val5.y);
		Vector2 val7 = default(Vector2);
		((Vector2)(ref val7))..ctor(num4, (float)Screen.height - num5);
		Vector2 val8 = default(Vector2);
		Vector2 val9 = default(Vector2);
		if (RectTransformUtility.ScreenPointToLocalPointInRectangle(val, val6, val2, ref val8) && RectTransformUtility.ScreenPointToLocalPointInRectangle(val, val7, val2, ref val9))
		{
			target.anchoredPosition += val9 - val8;
			layout.x += num + num3;
			layout.z = Mathf.Max(layout.z, num2);
			if (!reported)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Positioned native status effect beside AzuClock.");
				reported = true;
			}
		}
	}

	private void HideFoodObject(GameObject obj)
	{
		CanvasGroup val = obj.GetComponent<CanvasGroup>();
		if ((Object)(object)val == (Object)null)
		{
			val = obj.AddComponent<CanvasGroup>();
			foodAddedGroups.Add(val);
		}
		if (!foodOriginals.ContainsKey(val))
		{
			foodOriginals.Add(val, val.alpha);
		}
		val.alpha = 0f;
	}

	private void CleanupFoods()
	{
		CleanupBoostIcons();
		CleanupBuffPanels();
		foreach (KeyValuePair<CanvasGroup, float> foodOriginal in foodOriginals)
		{
			if ((Object)(object)foodOriginal.Key != (Object)null)
			{
				foodOriginal.Key.alpha = foodOriginal.Value;
			}
		}
		foodOriginals.Clear();
		foreach (CanvasGroup foodAddedGroup in foodAddedGroups)
		{
			if ((Object)(object)foodAddedGroup != (Object)null)
			{
				Object.Destroy((Object)(object)foodAddedGroup);
			}
		}
		foodAddedGroups.Clear();
		CleanupFoodHealWipes();
		foreach (RectTransform foodTarget in foodTargets)
		{
			if ((Object)(object)foodTarget != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)foodTarget).gameObject);
			}
		}
		foodTargets.Clear();
		foodReadiness.Clear();
		foodHud = null;
	}

	private void UpdateFoods()
	{
		//IL_031d: Unknown result type (might be due to invalid IL or missing references)
		//IL_026c: Unknown result type (might be due to invalid IL or missing references)
		Hud val = Hud.instance;
		Player localPlayer = Player.m_localPlayer;
		if ((Object)(object)val == (Object)null || (Object)(object)localPlayer == (Object)null)
		{
			if ((Object)(object)foodHud != (Object)null || foodTargets.Count > 0)
			{
				CleanupFoods();
			}
			return;
		}
		if ((Object)(object)foodHud != (Object)(object)val)
		{
			CleanupFoods();
			foodHud = val;
		}
		List<Food> foods = localPlayer.GetFoods();
		bool flag = false;
		staleFood.Clear();
		foreach (Food key in foodReadiness.Keys)
		{
			if (!foods.Contains(key))
			{
				staleFood.Add(key);
			}
		}
		foreach (Food item in staleFood)
		{
			foodReadiness.Remove(item);
		}
		while (foodTargets.Count < Mathf.Max(3, foods.Count))
		{
			RectTransform val2 = Object.Instantiate<RectTransform>(val.m_statusEffectTemplate, (Transform)(object)val.m_statusEffectListRoot);
			((Object)val2).name = "MMC_FoodBuff_" + foodTargets.Count;
			Animator[] componentsInChildren = ((Component)val2).GetComponentsInChildren<Animator>(true);
			foreach (Animator val3 in componentsInChildren)
			{
				((Behaviour)val3).enabled = false;
			}
			Graphic[] componentsInChildren2 = ((Component)val2).GetComponentsInChildren<Graphic>(true);
			foreach (Graphic val4 in componentsInChildren2)
			{
				val4.raycastTarget = false;
			}
			Transform val5 = ((Transform)val2).Find("Cooldown");
			if ((Object)(object)val5 != (Object)null)
			{
				((Component)val5).gameObject.SetActive(false);
			}
			((Component)val2).gameObject.SetActive(true);
			foodTargets.Add(val2);
		}
		for (int k = 0; k < foodTargets.Count; k++)
		{
			RectTransform val6 = foodTargets[k];
			((Component)val6).gameObject.SetActive(k < foods.Count && (SagaConfigPreview.HudVisible(val) || InventoryGui.IsVisible()) && !((Character)localPlayer).IsDead());
			if (k >= foods.Count)
			{
				Image component = ((Component)((Transform)val6).Find("Icon")).GetComponent<Image>();
				component.sprite = null;
				((Graphic)component).color = new Color(0.2f, 0.2f, 0.2f, 0.5f);
				TMP_Text[] componentsInChildren3 = ((Component)val6).GetComponentsInChildren<TMP_Text>(true);
				foreach (TMP_Text val7 in componentsInChildren3)
				{
					val7.text = "";
				}
				Image[] componentsInChildren4 = ((Component)component).GetComponentsInChildren<Image>(true);
				foreach (Image val8 in componentsInChildren4)
				{
					if ((Object)(object)val8 != (Object)(object)component)
					{
						((Behaviour)val8).enabled = false;
					}
				}
				SetWarning(val6, warn: false);
				continue;
			}
			Food val9 = foods[k];
			Image component2 = ((Component)((Transform)val6).Find("Icon")).GetComponent<Image>();
			component2.sprite = val9.m_item.GetIcon();
			((Graphic)component2).color = Color.white;
			UpdateFoodHealWipe(component2, val9);
			TMP_Text componentInChildren = ((Component)val6).GetComponentInChildren<TMP_Text>();
			componentInChildren.text = Localization.instance.Localize(val9.m_item.m_shared.m_name);
			TMP_Text component3 = ((Component)((Transform)val6).Find("TimeText")).GetComponent<TMP_Text>();
			((Component)component3).gameObject.SetActive(true);
			float num = ((Game.m_foodRate > 0f) ? Mathf.Max(0f, val9.m_time / Game.m_foodRate) : float.PositiveInfinity);
			UpdateBuffTimer(val6, num, timerVisible: true);
			double readySeconds = MMCFoodReadiness.UntilReady(val9.m_time, val9.m_item.m_shared.m_foodBurnTime, Game.m_foodRate);
			bool flag2 = localPlayer.CanEat(val9.m_item, false);
			if (foodReadiness.TryGetValue(val9, out var value) && !value && flag2)
			{
				flag = true;
			}
			foodReadiness[val9] = flag2;
			SetWarning(val6, MMCFoodReadiness.Select(num, flag2, readySeconds));
		}
		if (flag && !((Character)localPlayer).IsDead())
		{
			((Character)localPlayer).Message((MessageType)2, "You feel a lil' hungry.", 0, (Sprite)null, false);
		}
		Image[] foodIcons = val.m_foodIcons;
		foreach (Image val10 in foodIcons)
		{
			if (!((Object)(object)val10 == (Object)null))
			{
				HideFoodObject(((Component)val10).gameObject);
				Transform parent = ((Component)val10).transform.parent;
				while ((Object)(object)parent != (Object)null && (Object)(object)parent != (Object)(object)((Component)val).transform && ((Object)parent).name.StartsWith("food", StringComparison.OrdinalIgnoreCase) && !((Transform)val.m_statusEffectListRoot).IsChildOf(parent))
				{
					HideFoodObject(((Component)parent).gameObject);
					parent = parent.parent;
				}
			}
		}
		if ((Object)(object)val.m_foodBarRoot != (Object)null)
		{
			HideFoodObject(((Component)val.m_foodBarRoot).gameObject);
		}
		if ((Object)(object)val.m_foodBaseBar != (Object)null)
		{
			HideFoodObject(((Component)val.m_foodBaseBar).gameObject);
		}
		if ((Object)(object)val.m_foodIcon != (Object)null)
		{
			HideFoodObject(((Component)val.m_foodIcon).gameObject);
		}
		if ((Object)(object)val.m_foodText != (Object)null)
		{
			HideFoodObject(((Component)val.m_foodText).gameObject);
		}
		TMP_Text[] foodTime = val.m_foodTime;
		foreach (TMP_Text val11 in foodTime)
		{
			if ((Object)(object)val11 != (Object)null)
			{
				HideFoodObject(((Component)val11).gameObject);
			}
		}
		Image[] foodBars = val.m_foodBars;
		foreach (Image val12 in foodBars)
		{
			if ((Object)(object)val12 != (Object)null)
			{
				HideFoodObject(((Component)val12).gameObject);
			}
		}
	}

	private void OnDestroy()
	{
		CleanupFoods();
		if (harmony != null)
		{
			harmony.UnpatchSelf();
		}
		if (buffWindow != null)
		{
			buffWindow.Dispose();
		}
		instance = null;
	}
}
internal static class MMCBuffTime
{
	public static string Format(double seconds)
	{
		if (double.IsNaN(seconds) || double.IsInfinity(seconds))
		{
			return "--";
		}
		seconds = Math.Max(0.0, seconds);
		if (!(seconds > 60.0))
		{
			return Math.Ceiling(seconds).ToString("0") + "s";
		}
		return Math.Ceiling(seconds / 60.0).ToString("0") + "m";
	}

	public static bool Warn(double seconds)
	{
		if (seconds > 0.0)
		{
			return seconds <= 60.0;
		}
		return false;
	}
}
public sealed class MMCBuffWarning : MaskableGraphic
{
	public MMCBuffBorder Mode = MMCBuffBorder.ExpiringRed;

	public void Pulse()
	{
		((Graphic)this).raycastTarget = false;
		((Graphic)this).SetVerticesDirty();
	}

	protected override void OnPopulateMesh(VertexHelper mesh)
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0011: 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_0067: Unknown result type (might be due to invalid IL or missing references)
		//IL_0088: Unknown result type (might be due to invalid IL or missing references)
		//IL_0093: 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_012c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0114: 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_017d: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01da: Unknown result type (might be due to invalid IL or missing references)
		//IL_0211: Unknown result type (might be due to invalid IL or missing references)
		//IL_0223: Unknown result type (might be due to invalid IL or missing references)
		//IL_024c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0257: Unknown result type (might be due to invalid IL or missing references)
		//IL_0282: Unknown result type (might be due to invalid IL or missing references)
		//IL_028d: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b8: Unknown result type (might be due to invalid IL or missing references)
		mesh.Clear();
		Rect rect = ((Graphic)this).rectTransform.rect;
		float num = 0.5f + 0.5f * Mathf.Sin(Time.unscaledTime * (float)Math.PI * 1.5f);
		float num2 = Mathf.Max(0.1f, Mathf.Abs(((Transform)((Graphic)this).rectTransform).lossyScale.x));
		float num3 = 1f / num2;
		if (Mode == MMCBuffBorder.ReadyYellow)
		{
			Ring(mesh, rect, 0f, 2f * num3, new Color(1f, 0.84f, 0.04f, 1f));
			Ring(mesh, rect, 2f * num3, 2f * num3, new Color(1f, 0.77f, 0.02f, 0.3f));
		}
		else if (Mode == MMCBuffBorder.SoonYellow || Mode == MMCBuffBorder.UrgentRed)
		{
			float num4 = 0.5f + 0.5f * Mathf.Sin(Time.unscaledTime * (float)Math.PI * 3f);
			Color color = ((Mode == MMCBuffBorder.UrgentRed) ? new Color(1f, 0.025f, 0.01f, num4) : new Color(1f, 0.86f, 0.025f, num4));
			float num5 = Mathf.Min(2f * num3, Mathf.Min(((Rect)(ref rect)).width, ((Rect)(ref rect)).height) / 2f);
			DashSide(mesh, ((Rect)(ref rect)).xMin, ((Rect)(ref rect)).yMax - num5, ((Rect)(ref rect)).width, num5, horizontal: true, reverse: false, 0f, num3, color);
			DashSide(mesh, ((Rect)(ref rect)).xMax - num5, ((Rect)(ref rect)).yMin, ((Rect)(ref rect)).height, num5, horizontal: false, reverse: true, ((Rect)(ref rect)).width, num3, color);
			DashSide(mesh, ((Rect)(ref rect)).xMin, ((Rect)(ref rect)).yMin, ((Rect)(ref rect)).width, num5, horizontal: true, reverse: true, ((Rect)(ref rect)).width + ((Rect)(ref rect)).height, num3, color);
			DashSide(mesh, ((Rect)(ref rect)).xMin, ((Rect)(ref rect)).yMin, ((Rect)(ref rect)).height, num5, horizontal: false, reverse: false, 2f * ((Rect)(ref rect)).width + ((Rect)(ref rect)).height, num3, color);
		}
		else if (Mode != MMCBuffBorder.None)
		{
			Ring(mesh, rect, 0f, 2f * num3, new Color(0.65f + 0.35f * num, 0.015f, 0.01f, 1f));
			Ring(mesh, rect, 2f * num3, 2f * num3, new Color(1f, 0.025f, 0.01f, 0.24f + 0.28f * num));
			Ring(mesh, rect, 4f * num3, 2f * num3, new Color(1f, 0.025f, 0.01f, 0.06f + 0.14f * num));
		}
	}

	private static void DashSide(VertexHelper mesh, float x, float y, float length, float thickness, bool horizontal, bool reverse, float perimeterOffset, float unit, Color color)
	{
		//IL_0082: 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)
		float num = 10f * unit;
		float num2 = 4f * unit;
		float num3 = 0f - Mathf.Repeat(perimeterOffset - Time.unscaledTime * 24f * unit, num);
		for (float num4 = num3; num4 < length; num4 += num)
		{
			float num5 = Mathf.Max(0f, num4);
			float num6 = Mathf.Min(length, num4 + num2);
			if (!(num6 <= num5))
			{
				float num7 = (reverse ? (length - num6) : num5);
				if (horizontal)
				{
					Quad(mesh, x + num7, y, num6 - num5, thickness, color);
				}
				else
				{
					Quad(mesh, x, y + num7, thickness, num6 - num5, color);
				}
			}
		}
	}

	private static void Ring(VertexHelper mesh, Rect rect, float inset, float thickness, Color color)
	{
		//IL_0060: 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_008b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
		float num = ((Rect)(ref rect)).xMin + inset;
		float num2 = ((Rect)(ref rect)).yMin + inset;
		float num3 = ((Rect)(ref rect)).width - 2f * inset;
		float num4 = ((Rect)(ref rect)).height - 2f * inset;
		if (!(num3 <= 0f) && !(num4 <= 0f))
		{
			float num5 = Mathf.Min(thickness, Mathf.Min(num3, num4) * 0.5f);
			Quad(mesh, num, num2, num3, num5, color);
			Quad(mesh, num, num2 + num4 - num5, num3, num5, color);
			Quad(mesh, num, num2 + num5, num5, num4 - 2f * num5, color);
			Quad(mesh, num + num3 - num5, num2 + num5, num5, num4 - 2f * num5, color);
		}
	}

	private static void Quad(VertexHelper mesh, float x, float y, float w, float h, Color color)
	{
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0021: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0044: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: Unknown result type (might be due to invalid IL or missing references)
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0060: Unknown result type (might be due to invalid IL or missing references)
		//IL_0065: 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_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_0080: Unknown result type (might be due to invalid IL or missing references)
		//IL_0085: Unknown result type (might be due to invalid IL or missing references)
		//IL_0087: Unknown result type (might be due to invalid IL or missing references)
		//IL_008c: 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)
		if (!(w <= 0f) && !(h <= 0f))
		{
			int currentVertCount = mesh.currentVertCount;
			mesh.AddVert(new Vector3(x, y), Color32.op_Implicit(color), Vector4.op_Implicit(Vector2.zero));
			mesh.AddVert(new Vector3(x, y + h), Color32.op_Implicit(color), Vector4.op_Implicit(Vector2.zero));
			mesh.AddVert(new Vector3(x + w, y + h), Color32.op_Implicit(color), Vector4.op_Implicit(Vector2.zero));
			mesh.AddVert(new Vector3(x + w, y), Color32.op_Implicit(color), Vector4.op_Implicit(Vector2.zero));
			mesh.AddTriangle(currentVertCount, currentVertCount + 1, currentVertCount + 2);
			mesh.AddTriangle(currentVertCount, currentVertCount + 2, currentVertCount + 3);
		}
	}
}
public enum MMCBuffBorder
{
	None,
	ExpiringRed,
	ReadyYellow,
	SoonYellow,
	UrgentRed
}
internal static class MMCFoodReadiness
{
	public static MMCBuffBorder Expiry(double seconds)
	{
		if (seconds > 0.0 && seconds <= 15.0)
		{
			return MMCBuffBorder.UrgentRed;
		}
		if (seconds > 0.0 && seconds <= 60.0)
		{
			return MMCBuffBorder.ExpiringRed;
		}
		return MMCBuffBorder.None;
	}

	public static MMCBuffBorder Select(double expirySeconds, bool canEat, double readySeconds)
	{
		MMCBuffBorder mMCBuffBorder = Expiry(expirySeconds);
		if (mMCBuffBorder != MMCBuffBorder.None)
		{
			return mMCBuffBorder;
		}
		if (canEat)
		{
			return MMCBuffBorder.ReadyYellow;
		}
		if (readySeconds >= 0.0 && readySeconds <= 15.0)
		{
			return MMCBuffBorder.SoonYellow;
		}
		return MMCBuffBorder.None;
	}

	public static double UntilReady(double remaining, double total, double rate)
	{
		if (!(rate > 0.0))
		{
			return double.PositiveInfinity;
		}
		return Math.Max(0.0, (remaining - total * 0.5) / rate);
	}
}
public sealed class SagaBoostWipe
{
	private bool initialized;

	private int previousBonus;

	private double previousFoodTime;

	private double span;

	public float Update(int bonus, double foodTime, double ticksRemaining, bool predicted)
	{
		if (bonus <= 0 || !predicted || double.IsNaN(ticksRemaining) || double.IsInfinity(ticksRemaining))
		{
			initialized = false;
			return 0f;
		}
		if (!initialized || bonus != previousBonus || foodTime > previousFoodTime + 0.5 || ticksRemaining > span + 0.01)
		{
			span = Math.Max(0.001, ticksRemaining);
		}
		initialized = true;
		previousBonus = bonus;
		previousFoodTime = foodTime;
		return (float)Math.Max(0.0, Math.Min(1.0, 1.0 - ticksRemaining / span));
	}
}
internal static class SagaConfigPreview
{
	private static BaseUnityPlugin manager;

	private static PropertyInfo displaying;

	private static float retry;

	private static int frame = -1;

	private static bool open;

	internal static bool Open
	{
		get
		{
			if (frame == Time.frameCount)
			{
				return open;
			}
			frame = Time.frameCount;
			open = false;
			if ((Object)(object)manager == (Object)null && Time.unscaledTime >= retry)
			{
				retry = Time.unscaledTime + 2f;
				if (Chainloader.PluginInfos.TryGetValue("com.bepis.bepinex.configurationmanager", out var value))
				{
					manager = value.Instance;
					displaying = ((object)manager).GetType().GetProperty("DisplayingWindow", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				}
			}
			if ((Object)(object)manager != (Object)null && displaying != null)
			{
				try
				{
					open = (bool)displaying.GetValue(manager, null);
				}
				catch
				{
					open = false;
				}
			}
			return open;
		}
	}

	internal static bool HudVisible(Hud hud)
	{
		if ((Object)(object)hud != (Object)null)
		{
			if (!Open)
			{
				return hud.IsVisible();
			}
			return true;
		}
		return false;
	}

	internal static bool MenuVisible()
	{
		if (!Open)
		{
			return Menu.IsVisible();
		}
		return false;
	}

	internal static bool MapVisible()
	{
		if (!Open)
		{
			return Minimap.IsOpen();
		}
		return false;
	}

	internal static bool StoreVisible()
	{
		if (!Open)
		{
			return StoreGui.IsVisible();
		}
		return false;
	}

	internal static bool InventoryHidesHud()
	{
		if (!Open)
		{
			return InventoryGui.IsVisible();
		}
		return false;
	}
}
public static class SagaFoodBoostForecast
{
	public struct Food
	{
		public float Remaining;

		public float Duration;

		public float Base;

		public float Current;
	}

	public static int Bonus(Food[] foods)
	{
		float num = 0f;
		for (int i = 0; i < foods.Length; i++)
		{
			Food food = foods[i];
			num += Math.Max(0f, food.Current);
		}
		return (int)Math.Ceiling(num);
	}

	private static int At(Food[] foods, int ticks)
	{
		float num = 0f;
		for (int i = 0; i < foods.Length; i++)
		{
			Food food = foods[i];
			if (!(food.Duration <= 0f) && !(food.Remaining <= (float)ticks))
			{
				float num2 = Math.Max(0f, Math.Min(1f, (food.Remaining - (float)ticks) / food.Duration));
				num += food.Base * (float)Math.Pow(num2, 0.30000001192092896);
			}
		}
		return (int)Math.Ceiling(Math.Max(0f, num));
	}

	public static bool Predict(Food[] foods, double timer, double rate, out double seconds, out int drop)
	{
		seconds = 0.0;
		drop = 0;
		if (foods == null || foods.Length == 0 || rate <= 0.0 || double.IsNaN(rate) || double.IsInfinity(rate) || double.IsNaN(timer) || double.IsInfinity(timer))
		{
			return false;
		}
		int num = Bonus(foods);
		if (num <= 0)
		{
			return false;
		}
		double num2 = 0.0;
		for (int i = 0; i < foods.Length; i++)
		{
			Food food = foods[i];
			num2 = Math.Max(num2, food.Remaining);
		}
		int num3 = (int)Math.Min(1000000.0, Math.Ceiling(num2));
		if (num3 < 1 || At(foods, num3) >= num)
		{
			return false;
		}
		int num4 = 1;
		while (num4 < num3)
		{
			int num5 = num4 + (num3 - num4) / 2;
			if (At(foods, num5) < num)
			{
				num3 = num5;
			}
			else
			{
				num4 = num5 + 1;
			}
		}
		drop = num - At(foods, num4);
		seconds = Math.Max(0.0, ((double)num4 - timer) / rate);
		return drop > 0;
	}
}

BepInEx/plugins/MMC-SkillsPanel/MMCSkillsPanel.dll

Decompiled a week ago
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInPlugin("local.mmc.skillspanel", "SagaSkillsPro", "3.0.0")]
public sealed class MMCSkillsPanel : BaseUnityPlugin
{
	private sealed class Row
	{
		public string Name;

		public string Value;

		public string ETA;

		public SkillType SkillType;

		public float Progress;
	}

	public struct XPSnapshot
	{
		public bool Valid;

		public float Level;

		public float XP;

		public float Requirement;
	}

	public Rect ScreenRect;

	public bool PanelVisible;

	private readonly List<Row> rows = new List<Row>();

	private ConfigEntry<bool> enabledPanel;

	private ConfigEntry<bool> hideMenus;

	private ConfigEntry<bool> actionMode;

	private ConfigEntry<float> rowSpacing;

	private ConfigEntry<float> opacity;

	private ConfigEntry<float> maxHeight;

	private ConfigEntry<int> leftMargin;

	private ConfigEntry<int> bottomMargin;

	private ConfigEntry<int> fontSize;

	private FieldInfo clockStyle;

	private GUIStyle label;

	private GUIStyle rightLabel;

	private GUIStyle heading;

	private GUIStyle etaLabel;

	private SagaPanelWindow window;

	private readonly Dictionary<SkillType, ConfigEntry<bool>> visibleSkills = new Dictionary<SkillType, ConfigEntry<bool>>();

	private Vector2 contentScroll;

	private float nextRefresh;

	private Player lastPlayer;

	private static MMCSkillsPanel instance;

	private Harmony harmony;

	private readonly SagaSkillRate rate = new SagaSkillRate();

	private Player ratePlayer;

	private static readonly FieldInfo skillData = AccessTools.Field(typeof(Skills), "m_skillData");

	private static readonly MethodInfo nextRequirement = AccessTools.Method(typeof(Skill), "GetNextLevelRequirement", (Type[])null, (Type[])null);

	private static readonly Dictionary<GUIStyle, GUIStyle> shadowStyles = new Dictionary<GUIStyle, GUIStyle>();

	private ConfigEntry<bool> SkillVisibility(SkillType type)
	{
		//IL_0006: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: 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: Expected I4, but got Unknown
		//IL_007d: Unknown result type (might be due to invalid IL or missing references)
		if (visibleSkills.TryGetValue(type, out var value))
		{
			return value;
		}
		string text = ((object)type).ToString();
		value = ((BaseUnityPlugin)this).Config.Bind<bool>("Skill Visibility", "Show " + text, true, "Show " + text + " in the skills panel once it has XP. Right-click its row while inventory is open to hide it; enable this setting to restore it. Skill ID: " + (int)type);
		value.SettingChanged += delegate
		{
			nextRefresh = 0f;
		};
		visibleSkills.Add(type, value);
		return value;
	}

	private void EnsureRatePlayer()
	{
		if ((Object)(object)ratePlayer != (Object)(object)Player.m_localPlayer)
		{
			rate.Clear();
			ratePlayer = Player.m_localPlayer;
		}
	}

	private static void BeforeRaise(Skill __instance, out XPSnapshot __state)
	{
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		__state = default(XPSnapshot);
		if (!((Object)(object)instance == (Object)null) && !((Object)(object)Player.m_localPlayer == (Object)null) && __instance.m_info != null)
		{
			instance.EnsureRatePlayer();
			Skills skills = ((Character)Player.m_localPlayer).GetSkills();
			if (!((Object)(object)skills == (Object)null) && skillData.GetValue(skills) is Dictionary<SkillType, Skill> dictionary && dictionary.TryGetValue(__instance.m_info.m_skill, out var value) && object.ReferenceEquals(value, __instance))
			{
				__state.Valid = true;
				__state.Level = __instance.m_level;
				__state.XP = __instance.m_accumulator;
				__state.Requirement = (float)nextRequirement.Invoke(__instance, null);
			}
		}
	}

	private static void AfterRaise(Skill __instance, XPSnapshot __state)
	{
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: Expected I4, but got Unknown
		if (!((Object)(object)instance == (Object)null) && __state.Valid)
		{
			double xp = SagaSkillRate.RetainedGain(__state.Level, __state.XP, __state.Requirement, __instance.m_level, __instance.m_accumulator);
			instance.rate.Add((int)__instance.m_info.m_skill, Time.realtimeSinceStartup, xp);
		}
	}

	private void Awake()
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Expected O, but got Unknown
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Expected O, but got Unknown
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_0049: Expected O, but got Unknown
		//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_00bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00be: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c4: Invalid comparison between Unknown and I4
		//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0102: Expected O, but got Unknown
		//IL_0152: Unknown result type (might be due to invalid IL or missing references)
		//IL_015c: Expected O, but got Unknown
		//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bc: Expected O, but got Unknown
		//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01fb: Expected O, but got Unknown
		//IL_026b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0275: Expected O, but got Unknown
		//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
		instance = this;
		harmony = new Harmony("local.mmc.skillspanel.eta");
		HarmonyMethod val = new HarmonyMethod(typeof(MMCSkillsPanel), "BeforeRaise", (Type[])null);
		val.priority = 0;
		HarmonyMethod val2 = new HarmonyMethod(typeof(MMCSkillsPanel), "AfterRaise", (Type[])null);
		val2.priority = 0;
		harmony.Patch((MethodBase)AccessTools.Method(typeof(Skill), "Raise", (Type[])null, (Type[])null), val, val2, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		actionMode = ((BaseUnityPlugin)this).Config.Bind<bool>("Estimates", "Show Actions Instead Of Time", false, "Estimate remaining XP-gaining skill uses instead of time. Both use the last 60 seconds of observations; passive skills count XP ticks as uses.");
		foreach (SkillType value in Enum.GetValues(typeof(SkillType)))
		{
			if ((int)value != 0 && (int)value != 999)
			{
				SkillVisibility(value);
			}
		}
		window = new SagaPanelWindow(((BaseUnityPlugin)this).Config, "SagaSkillsPro");
		window.MinimumWidth = 230f;
		window.MinimumHeight = 100f;
		rowSpacing = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "Row Spacing", 8f, new ConfigDescription("Empty buffer in pixels between skill entries.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 48f), new object[0]));
		enabledPanel = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "Enabled", true, "Show the skills panel.");
		opacity = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "Background Opacity", 0.6f, new ConfigDescription("Background opacity; text remains fully opaque.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), new object[0]));
		maxHeight = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "Maximum Height", 0.85f, new ConfigDescription("Maximum fraction of screen height. Font and columns fit automatically.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.25f, 0.95f), new object[0]));
		leftMargin = ((BaseUnityPlugin)this).Config.Bind<int>("Display", "Left Margin", 12, "Distance from left screen edge in pixels.");
		bottomMargin = ((BaseUnityPlugin)this).Config.Bind<int>("Display", "Bottom Margin", 12, "Distance from bottom screen edge in pixels.");
		fontSize = ((BaseUnityPlugin)this).Config.Bind<int>("Display", "Font Size", 20, new ConfigDescription("Preferred font size; shrinks to fit when necessary.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(12, 32), new object[0]));
		hideMenus = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "Hide In Menus", true, "Hide while full map, store or pause menu is open. Inventory stays visible for dragging.");
		clockStyle = ((object)Chainloader.PluginInfos["Azumatt.AzuClock"].Instance).GetType().GetField("Style", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Bottom-left skills panel enabled. Background opacity 60%; AzuClock font with italic text.");
	}

	private void Update()
	{
		//IL_009c: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f8: Invalid comparison between Unknown and I4
		//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_013a: Unknown result type (might be due to invalid IL or missing references)
		//IL_018e: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_0217: Unknown result type (might be due to invalid IL or missing references)
		//IL_026d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0320: Unknown result type (might be due to invalid IL or missing references)
		//IL_0325: 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_0301: Expected I4, but got Unknown
		//IL_02ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e0: Expected I4, but got Unknown
		EnsureRatePlayer();
		Player localPlayer = Player.m_localPlayer;
		if ((Object)(object)localPlayer == (Object)null)
		{
			rows.Clear();
			lastPlayer = null;
		}
		else
		{
			if ((Object)(object)localPlayer == (Object)(object)lastPlayer && Time.unscaledTime < nextRefresh)
			{
				return;
			}
			lastPlayer = localPlayer;
			nextRefresh = Time.unscaledTime + 0.5f;
			Skills skills = ((Character)localPlayer).GetSkills();
			if ((Object)(object)skills == (Object)null)
			{
				return;
			}
			Dictionary<SkillType, Skill> dictionary = new Dictionary<SkillType, Skill>();
			foreach (Skill skill in skills.GetSkillList())
			{
				if (skill != null && skill.m_info != null)
				{
					dictionary[skill.m_info.m_skill] = skill;
				}
			}
			Dictionary<SkillType, SkillDef> dictionary2 = new Dictionary<SkillType, SkillDef>();
			foreach (SkillDef skill2 in skills.m_skills)
			{
				if (skill2 != null && (int)skill2.m_skill != 0 && (int)skill2.m_skill != 999)
				{
					dictionary2[skill2.m_skill] = skill2;
				}
			}
			foreach (KeyValuePair<SkillType, Skill> item in dictionary)
			{
				dictionary2[item.Key] = item.Value.m_info;
			}
			rows.Clear();
			foreach (KeyValuePair<SkillType, SkillDef> item2 in dictionary2)
			{
				if (!SkillVisibility(item2.Key).Value)
				{
					continue;
				}
				dictionary.TryGetValue(item2.Key, out var value);
				if (value != null && (!(value.m_level <= 0f) || !(value.m_accumulator <= 0f)))
				{
					float num = value?.m_level ?? 0f;
					float num2 = ((num >= 100f) ? 1f : ((value == null) ? 0f : value.GetLevelPercentage()));
					string text = "$skill_" + ((object)item2.Key).ToString().ToLowerInvariant();
					string text2 = Localization.instance.Localize(text);
					if (text2 == text || text2 == "[" + text.Substring(1) + "]")
					{
						text2 = ((object)item2.Key).ToString();
					}
					double remaining = ((value == null) ? 1f : Math.Max(0f, (float)nextRequirement.Invoke(value, null) - value.m_accumulator));
					string eTA = ((num >= 100f) ? "Maximum level" : (actionMode.Value ? SagaSkillRate.FormatActions(rate.Actions((int)item2.Key, Time.realtimeSinceStartup, remaining)) : SagaSkillRate.Format(rate.Seconds((int)item2.Key, Time.realtimeSinceStartup, remaining))));
					rows.Add(new Row
					{
						SkillType = item2.Key,
						Name = text2,
						ETA = eTA,
						Progress = Mathf.Clamp01(num2),
						Value = "Lv " + Mathf.FloorToInt(num) + "   " + ((num >= 100f) ? "MAX" : (Mathf.FloorToInt(num2 * 100f) + "%"))
					});
				}
			}
			rows.Sort((Row a, Row b) => StringComparer.CurrentCultureIgnoreCase.Compare(a.Name, b.Name));
		}
	}

	private void OnGUI()
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Invalid comparison between Unknown and I4
		//IL_08d2: 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_00fc: Unknown result type (might be due to invalid IL or missing references)
		//IL_0106: Expected O, but got Unknown
		//IL_0110: Unknown result type (might be due to invalid IL or missing references)
		//IL_011a: Expected O, but got Unknown
		//IL_0139: Unknown result type (might be due to invalid IL or missing references)
		//IL_0143: Expected O, but got Unknown
		//IL_014a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0154: Expected O, but got Unknown
		//IL_015b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0165: Expected O, but got Unknown
		//IL_0338: Unknown result type (might be due to invalid IL or missing references)
		//IL_0381: Unknown result type (might be due to invalid IL or missing references)
		//IL_02dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_02e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_02f6: Unknown result type (might be due to invalid IL or missing references)
		//IL_03b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_03c3: Expected O, but got Unknown
		//IL_03be: Unknown result type (might be due to invalid IL or missing references)
		//IL_03f3: Unknown result type (might be due to invalid IL or missing references)
		//IL_03fd: Expected O, but got Unknown
		//IL_03f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_0467: Unknown result type (might be due to invalid IL or missing references)
		//IL_0471: Unknown result type (might be due to invalid IL or missing references)
		//IL_0476: Unknown result type (might be due to invalid IL or missing references)
		//IL_0524: Unknown result type (might be due to invalid IL or missing references)
		//IL_0529: Unknown result type (might be due to invalid IL or missing references)
		//IL_052b: Unknown result type (might be due to invalid IL or missing references)
		//IL_053c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0557: Unknown result type (might be due to invalid IL or missing references)
		//IL_056c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0571: 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_0582: Unknown result type (might be due to invalid IL or missing references)
		//IL_059c: Unknown result type (might be due to invalid IL or missing references)
		//IL_05a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_05b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_05b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_05d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_05d6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0606: Unknown result type (might be due to invalid IL or missing references)
		//IL_0616: Unknown result type (might be due to invalid IL or missing references)
		//IL_06b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_06bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_06d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_06df: Unknown result type (might be due to invalid IL or missing references)
		//IL_06e4: Unknown result type (might be due to invalid IL or missing references)
		//IL_0649: Unknown result type (might be due to invalid IL or missing references)
		//IL_07c2: Unknown result type (might be due to invalid IL or missing references)
		//IL_07db: Unknown result type (might be due to invalid IL or missing references)
		//IL_0804: Unknown result type (might be due to invalid IL or missing references)
		//IL_081d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0845: Unknown result type (might be due to invalid IL or missing references)
		//IL_086d: Unknown result type (might be due to invalid IL or missing references)
		//IL_089c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0754: Unknown result type (might be due to invalid IL or missing references)
		//IL_076f: Unknown result type (might be due to invalid IL or missing references)
		//IL_077e: Unknown result type (might be due to invalid IL or missing references)
		if ((int)Event.current.type == 7)
		{
			PanelVisible = false;
		}
		if (!enabledPanel.Value || (Object)(object)Player.m_localPlayer == (Object)null || rows.Count == 0)
		{
			ScreenRect = default(Rect);
			PanelVisible = false;
			window.Hide();
			return;
		}
		if (!window.Appearance.InventoryVisible || (Object)(object)Hud.instance == (Object)null || (!SagaConfigPreview.HudVisible(Hud.instance) && !SagaConfigPreview.InventoryHidesHud()))
		{
			window.Hide();
			return;
		}
		if (hideMenus.Value && (SagaConfigPreview.MapVisible() || SagaConfigPreview.StoreVisible() || SagaConfigPreview.MenuVisible()))
		{
			window.Hide();
			return;
		}
		GUIStyle val = (GUIStyle)((clockStyle == null) ? null : /*isinst with value type is only supported in some contexts*/);
		if (label == null)
		{
			label = new GUIStyle(GUI.skin.label);
			label.padding = new RectOffset(0, 0, 0, 0);
			label.wordWrap = false;
			label.richText = false;
			rightLabel = new GUIStyle(label);
			heading = new GUIStyle(label);
			etaLabel = new GUIStyle(label);
		}
		float num = Mathf.Clamp(leftMargin.Value, 0, Mathf.Max(0, Screen.width - 180));
		float num2 = Mathf.Clamp(bottomMargin.Value, 0, Mathf.Max(0, Screen.height - 100));
		float num3 = Mathf.Max(60f, Mathf.Min((float)Screen.height * maxHeight.Value, (float)Screen.height - num2 - 8f));
		int num4 = 16;
		while (num4 > 12 && (float)(40 + rows.Count * (num4 + num4 + 14)) > num3)
		{
			num4--;
		}
		float num5 = num4;
		float num6 = (float)num4 + num5 + 8f;
		float num7 = num6 + rowSpacing.Value;
		int val2 = Mathf.Max(1, Mathf.FloorToInt((num3 - 40f) / num7));
		val2 = Math.Min(rows.Count, val2);
		int num8 = (rows.Count + val2 - 1) / val2;
		GUIStyle[] array = (GUIStyle[])(object)new GUIStyle[4] { label, rightLabel, heading, etaLabel };
		foreach (GUIStyle val3 in array)
		{
			val3.font = ((val == null) ? GUI.skin.label.font : val.font);
			val3.fontSize = num4;
			val3.fontStyle = (FontStyle)0;
			Color white = Color.white;
			white.a = 1f;
			val3.normal.textColor = white;
			val3.alignment = (TextAnchor)3;
		}
		etaLabel.fontSize = (int)num5;
		etaLabel.fontStyle = (FontStyle)0;
		etaLabel.normal.textColor = Color.white;
		rightLabel.alignment = (TextAnchor)5;
		heading.fontStyle = (FontStyle)1;
		heading.fontSize = 19;
		heading.normal.textColor = new Color(1f, 0.76f, 0.4f);
		float num9 = 0f;
		foreach (Row row2 in rows)
		{
			num9 = Mathf.Max(num9, label.CalcSize(new GUIContent(row2.Name)).x);
		}
		float x = rightLabel.CalcSize(new GUIContent("Lv 100   100%")).x;
		float num10 = Mathf.Max(230f, num9 + x + 36f);
		num10 = Mathf.Min(num10, ((float)Screen.width - num - 8f) / (float)num8);
		float num11 = num10 * (float)num8;
		float num12 = 40f + (float)val2 * num7;
		float num13 = (float)Screen.height - num2 - num12;
		ScreenRect = window.Place(new Rect(num, num13, num11, num12), 74f);
		if (window.Minimized)
		{
			PanelVisible = false;
			return;
		}
		num = ((Rect)(ref ScreenRect)).x;
		num13 = ((Rect)(ref ScreenRect)).y;
		num11 = ((Rect)(ref ScreenRect)).width;
		num12 = ((Rect)(ref ScreenRect)).height;
		num8 = Mathf.Max(1, Mathf.FloorToInt(num11 / Mathf.Max(230f, num10)));
		val2 = Mathf.Max(1, Mathf.CeilToInt((float)rows.Count / (float)num8));
		num10 = (num11 - 18f) / (float)num8;
		float num14 = window.HeaderHeight + 1f;
		PanelVisible = true;
		Color color = GUI.color;
		GUI.color = Color.white;
		try
		{
			Fill(new Rect(num, num13, num11, num12), window.Appearance.Background(opacity.Value));
			Color border = window.Appearance.Border;
			Fill(new Rect(num, num13, num11, 1f), border);
			Fill(new Rect(num, num13 + num12 - 1f, num11, 1f), border);
			Fill(new Rect(num, num13, 1f, num12), border);
			Fill(new Rect(num + num11 - 1f, num13, 1f, num12), border);
			if (!window.ToolWindow)
			{
				Fill(new Rect(num + 2f, num13 + 2f, num11 - 4f, 29f), window.Appearance.Header);
			}
			if (!window.ToolWindow && GUI.Button(new Rect(num + num11 - 102f, num13 + 5f, 62f, 21f), actionMode.Value ? "Actions" : "Time", SagaPanelUI.ButtonStyle()))
			{
				actionMode.Value = !actionMode.Value;
				nextRefresh = 0f;
			}
			contentScroll = GUI.BeginScrollView(new Rect(num, num13 + num14, num11, Mathf.Max(1f, num12 - num14 - 4f)), contentScroll, new Rect(0f, 0f, num11 - 18f, (float)val2 * num7), false, false);
			Rect val4 = default(Rect);
			for (int j = 0; j < rows.Count; j++)
			{
				Row row = rows[j];
				float num15 = (float)(j / val2) * num10 + 12f;
				float num16 = (float)(j % val2) * num7;
				float num17 = num10 - 24f;
				((Rect)(ref val4))..ctor(num15 - 4f, num16, num17 + 8f, num6);
				if (!SagaConfigPreview.Open && InventoryGui.IsVisible() && (int)Event.current.type == 0 && Event.current.button == 1 && ((Rect)(ref val4)).Contains(Event.current.mousePosition))
				{
					SkillVisibility(row.SkillType).Value = false;
					((BaseUnityPlugin)this).Config.Save();
					nextRefresh = 0f;
					Event.current.Use();
				}
				Fill(new Rect(num15 - 4f, num16, num17 + 8f, num6), new Color(0.05f, 0.055f, 0.05f, 0.35f));
				Fill(new Rect(num15 - 4f, num16, (num17 + 8f) * row.Progress, (float)(num4 + 5)), new Color(0.72f, 0.47f, 0.16f, 0.42f));
				Label(new Rect(num15, num16, Mathf.Max(0f, num17 - x - 10f), (float)(num4 + 3)), row.Name, label);
				Label(new Rect(num15 + num17 - x, num16, x, (float)(num4 + 3)), row.Value, rightLabel);
				Label(new Rect(num15, num16 + (float)num4 + 3f, num17, num5 + 3f), row.ETA, etaLabel);
			}
			GUI.EndScrollView();
		}
		finally
		{
			GUI.color = color;
		}
		window.DrawHeader();
	}

	private static void Label(Rect rect, string text, GUIStyle style)
	{
		//IL_003c: 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_0058: Unknown result type (might be due to invalid IL or missing references)
		//IL_008a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0096: 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_0016: Expected O, but got Unknown
		if (!shadowStyles.TryGetValue(style, out var value))
		{
			value = new GUIStyle(style);
			shadowStyles.Add(style, value);
		}
		value.font = style.font;
		value.fontSize = style.fontSize;
		value.fontStyle = style.fontStyle;
		value.alignment = style.alignment;
		value.normal.textColor = Color.black;
		GUI.Label(new Rect(((Rect)(ref rect)).x + 1f, ((Rect)(ref rect)).y + 1f, ((Rect)(ref rect)).width, ((Rect)(ref rect)).height), text, value);
		GUI.Label(rect, text, style);
	}

	private void OnDestroy()
	{
		if (window != null)
		{
			window.Dispose();
		}
		if (harmony != null)
		{
			harmony.UnpatchSelf();
		}
		if ((Object)(object)instance == (Object)(object)this)
		{
			instance = null;
		}
	}

	private static void Fill(Rect rect, Color color)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0005: 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_000c: 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)
		Color color2 = GUI.color;
		GUI.color = color;
		GUI.DrawTexture(rect, (Texture)(object)Texture2D.whiteTexture);
		GUI.color = color2;
	}
}
internal static class SagaConfigPreview
{
	private static BaseUnityPlugin manager;

	private static PropertyInfo displaying;

	private static float retry;

	private static int frame = -1;

	private static bool open;

	internal static bool Open
	{
		get
		{
			if (frame == Time.frameCount)
			{
				return open;
			}
			frame = Time.frameCount;
			open = false;
			if ((Object)(object)manager == (Object)null && Time.unscaledTime >= retry)
			{
				retry = Time.unscaledTime + 2f;
				if (Chainloader.PluginInfos.TryGetValue("com.bepis.bepinex.configurationmanager", out var value))
				{
					manager = value.Instance;
					displaying = ((object)manager).GetType().GetProperty("DisplayingWindow", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				}
			}
			if ((Object)(object)manager != (Object)null && displaying != null)
			{
				try
				{
					open = (bool)displaying.GetValue(manager, null);
				}
				catch
				{
					open = false;
				}
			}
			return open;
		}
	}

	internal static bool HudVisible(Hud hud)
	{
		if ((Object)(object)hud != (Object)null)
		{
			if (!Open)
			{
				return hud.IsVisible();
			}
			return true;
		}
		return false;
	}

	internal static bool MenuVisible()
	{
		if (!Open)
		{
			return Menu.IsVisible();
		}
		return false;
	}

	internal static bool MapVisible()
	{
		if (!Open)
		{
			return Minimap.IsOpen();
		}
		return false;
	}

	internal static bool StoreVisible()
	{
		if (!Open)
		{
			return StoreGui.IsVisible();
		}
		return false;
	}

	internal static bool InventoryHidesHud()
	{
		if (!Open)
		{
			return InventoryGui.IsVisible();
		}
		return false;
	}
}
public sealed class SagaSkillRate
{
	private struct Sample
	{
		public double Time;

		public double XP;
	}

	private readonly Dictionary<int, Queue<Sample>> samples = new Dictionary<int, Queue<Sample>>();

	public void Clear()
	{
		samples.Clear();
	}

	public void Add(int skill, double now, double xp)
	{
		if (!(xp <= 0.0) && !double.IsNaN(xp) && !double.IsInfinity(xp))
		{
			if (!samples.TryGetValue(skill, out var value))
			{
				value = new Queue<Sample>();
				samples.Add(skill, value);
			}
			Trim(value, now);
			value.Enqueue(new Sample
			{
				Time = now,
				XP = xp
			});
		}
	}

	private static void Trim(Queue<Sample> queue, double now)
	{
		while (queue.Count > 0 && queue.Peek().Time <= now - 60.0)
		{
			queue.Dequeue();
		}
	}

	public double Seconds(int skill, double now, double remaining)
	{
		if (!samples.TryGetValue(skill, out var value))
		{
			return double.PositiveInfinity;
		}
		Trim(value, now);
		double num = 0.0;
		foreach (Sample item in value)
		{
			num += item.XP;
		}
		if (!(num > 0.0))
		{
			return double.PositiveInfinity;
		}
		return Math.Max(0.0, remaining) * 60.0 / num;
	}

	public double Actions(int skill, double now, double remaining)
	{
		if (!samples.TryGetValue(skill, out var value))
		{
			return double.PositiveInfinity;
		}
		Trim(value, now);
		double num = 0.0;
		foreach (Sample item in value)
		{
			num += item.XP;
		}
		if (!(num > 0.0) || value.Count <= 0)
		{
			return double.PositiveInfinity;
		}
		return Math.Ceiling(Math.Max(0.0, remaining) * (double)value.Count / num);
	}

	public static string FormatActions(double count)
	{
		if (double.IsInfinity(count) || double.IsNaN(count))
		{
			return "";
		}
		return "Next level: ~" + count.ToString("0", CultureInfo.InvariantCulture) + ((count == 1.0) ? " action" : " actions");
	}

	public static double RetainedGain(double oldLevel, double oldXP, double requirement, double level, double xp)
	{
		if (oldLevel >= 100.0 || level < oldLevel || level > oldLevel + 1.001)
		{
			return 0.0;
		}
		return Math.Max(0.0, xp - oldXP + ((level > oldLevel) ? requirement : 0.0));
	}

	public static string Format(double seconds)
	{
		if (double.IsInfinity(seconds) || double.IsNaN(seconds))
		{
			return "";
		}
		if (seconds < 1.0)
		{
			return "Next level: <1s";
		}
		if (seconds >= 86400.0)
		{
			return "Next level: ~" + (seconds / 86400.0).ToString("0.0") + "d";
		}
		int num = (int)Math.Ceiling(seconds);
		return "Next level: ~" + ((num >= 3600) ? (num / 3600 + "h " + num % 3600 / 60 + "m") : ((num >= 60) ? (num / 60 + "m " + num % 60 + "s") : (num + "s")));
	}
}

BepInEx/plugins/MMC-XPDrops/MMCXPDrops.dll

Decompiled a week ago
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;

[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: CompilationRelaxations(8)]
[assembly: AssemblyVersion("0.0.0.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInPlugin("local.mmc.xpdrops", "Saga XP Drops", "3.0.0")]
public sealed class MMCXPDrops : BaseUnityPlugin
{
	public struct Snapshot
	{
		public bool Valid;

		public float Level;

		public float XP;

		public float Requirement;
	}

	private sealed class Drop
	{
		public SkillType Skill;

		public float XP;

		public float Born;

		public string Text;
	}

	private static MMCXPDrops instance;

	private static readonly FieldInfo skillData = AccessTools.Field(typeof(Skills), "m_skillData");

	private static readonly MethodInfo nextRequirement = AccessTools.Method(typeof(Skill), "GetNextLevelRequirement", (Type[])null, (Type[])null);

	private readonly List<Drop> pending = new List<Drop>();

	private readonly List<Drop> active = new List<Drop>();

	private Harmony harmony;

	private object buffs;

	private FieldInfo clockRect;

	private FieldInfo clockStyle;

	private FieldInfo rested;

	private FieldInfo corpse;

	private FieldInfo powers;

	private FieldInfo foods;

	private FieldInfo others;

	private FieldInfo debuffs;

	private ConfigEntry<bool> show;

	private ConfigEntry<int> fontSize;

	private ConfigEntry<float> duration;

	private ConfigEntry<float> distance;

	private ConfigEntry<float> gap;

	private GUIStyle style;

	private GUIStyle shadowStyle;

	private float nextDrop;

	private Player lastPlayer;

	private SagaEffectLayout layout;

	private void Awake()
	{
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Expected O, but got Unknown
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_006e: Expected O, but got Unknown
		//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ad: Expected O, but got Unknown
		//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ec: Expected O, but got Unknown
		//IL_0121: Unknown result type (might be due to invalid IL or missing references)
		//IL_012b: Expected O, but got Unknown
		//IL_0298: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a2: Expected O, but got Unknown
		//IL_02b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_02b8: Expected O, but got Unknown
		//IL_02cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_02d5: Expected O, but got Unknown
		instance = this;
		layout = new SagaEffectLayout(((BaseUnityPlugin)this).Config, "XP Drops Layout");
		show = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "Enabled", true, "Show scrolling skill XP gains.");
		fontSize = ((BaseUnityPlugin)this).Config.Bind<int>("Display", "Font Size", 18, new ConfigDescription("XP text size.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(12, 32), new object[0]));
		duration = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "Duration", 3f, new ConfigDescription("Seconds each drop remains visible.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 8f), new object[0]));
		distance = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "Scroll Distance", 90f, new ConfigDescription("Upward travel in pixels. Drops start below the clock and rise toward it.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(20f, 240f), new object[0]));
		gap = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "Gap", 18f, new ConfigDescription("Pixels left of the leftmost clock buff.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 200f), new object[0]));
		Type type = ((object)Chainloader.PluginInfos["Azumatt.AzuClock"].Instance).GetType();
		clockRect = AccessTools.Field(type, "_windowRect");
		clockStyle = AccessTools.Field(type, "Style");
		buffs = Chainloader.PluginInfos["local.mmc.skilldrainclock"].Instance;
		rested = AccessTools.Field(buffs.GetType(), "restedTarget");
		corpse = AccessTools.Field(buffs.GetType(), "corpseRunTarget");
		powers = AccessTools.Field(buffs.GetType(), "powerTargets");
		foods = AccessTools.Field(buffs.GetType(), "foodTargets");
		others = AccessTools.Field(buffs.GetType(), "otherTargets");
		debuffs = AccessTools.Field(buffs.GetType(), "debuffTargets");
		if (skillData == null || nextRequirement == null || clockRect == null || rested == null || corpse == null || powers == null)
		{
			((BaseUnityPlugin)this).Logger.LogError((object)"XP drops could not find compatible game/clock fields.");
			((Behaviour)this).enabled = false;
			return;
		}
		harmony = new Harmony("local.mmc.xpdrops");
		HarmonyMethod val = new HarmonyMethod(typeof(MMCXPDrops), "BeforeRaise", (Type[])null);
		val.priority = 0;
		HarmonyMethod val2 = new HarmonyMethod(typeof(MMCXPDrops), "AfterRaise", (Type[])null);
		val2.priority = 0;
		harmony.Patch((MethodBase)AccessTools.Method(typeof(Skill), "Raise", (Type[])null, (Type[])null), val, val2, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Scrolling XP gains enabled to the left of the clock buffs.");
	}

	private static void BeforeRaise(Skill __instance, out Snapshot __state)
	{
		//IL_006b: Unknown result type (might be due to invalid IL or missing references)
		__state = default(Snapshot);
		if (!((Object)(object)instance == (Object)null) && instance.show.Value && !((Object)(object)Player.m_localPlayer == (Object)null) && __instance.m_info != null)
		{
			Skills skills = ((Character)Player.m_localPlayer).GetSkills();
			if (!((Object)(object)skills == (Object)null) && skillData.GetValue(skills) is Dictionary<SkillType, Skill> dictionary && dictionary.TryGetValue(__instance.m_info.m_skill, out var value) && object.ReferenceEquals(value, __instance))
			{
				__state.Valid = true;
				__state.Level = __instance.m_level;
				__state.XP = __instance.m_accumulator;
				__state.Requirement = (float)nextRequirement.Invoke(__instance, null);
			}
		}
	}

	private static void AfterRaise(Skill __instance, Snapshot __state)
	{
		//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
		if (!__state.Valid || (Object)(object)instance == (Object)null || __state.Level >= 100f)
		{
			return;
		}
		float num = __instance.m_accumulator - __state.XP;
		if (__instance.m_level > __state.Level)
		{
			num += __state.Requirement;
			for (float num2 = __state.Level + 1f; num2 < __instance.m_level; num2 += 1f)
			{
				num += Mathf.Pow(Mathf.Floor(num2 + 1f), 1.5f) * 0.5f + 0.5f;
			}
		}
		if (!(__instance.m_level < __state.Level) && !(num <= 0f) && !float.IsNaN(num) && !float.IsInfinity(num))
		{
			instance.Enqueue(__instance.m_info.m_skill, num);
		}
	}

	private void Enqueue(SkillType skill, float xp)
	{
		//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_00a0: 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)
		if ((Object)(object)lastPlayer != (Object)(object)Player.m_localPlayer)
		{
			pending.Clear();
			active.Clear();
			lastPlayer = Player.m_localPlayer;
		}
		if (!CanDraw())
		{
			return;
		}
		foreach (Drop item in pending)
		{
			if (item.Skill == skill)
			{
				item.XP += xp;
				return;
			}
		}
		if (pending.Count < 64)
		{
			pending.Add(new Drop
			{
				Skill = skill,
				XP = xp,
				Born = Time.unscaledTime
			});
		}
	}

	private bool CanDraw()
	{
		if (show.Value && layout.Visible && (Object)(object)Player.m_localPlayer != (Object)null && (Object)(object)Hud.instance != (Object)null && (SagaConfigPreview.HudVisible(Hud.instance) || InventoryGui.IsVisible()) && !SagaConfigPreview.MapVisible() && !SagaConfigPreview.StoreVisible())
		{
			return !SagaConfigPreview.MenuVisible();
		}
		return false;
	}

	private void Update()
	{
		//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_012e: Unknown result type (might be due to invalid IL or missing references)
		if (!CanDraw() || (Object)(object)lastPlayer != (Object)(object)Player.m_localPlayer)
		{
			active.Clear();
			pending.Clear();
			lastPlayer = Player.m_localPlayer;
			return;
		}
		float now = Time.unscaledTime;
		active.RemoveAll((Drop drop2) => now - drop2.Born >= duration.Value);
		if (pending.Count != 0 && !(now < nextDrop) && !(now - pending[0].Born < 0.25f) && active.Count < 6)
		{
			Drop drop = pending[0];
			pending.RemoveAt(0);
			drop.Born = now;
			string text = "$skill_" + ((object)drop.Skill).ToString().ToLowerInvariant();
			string text2 = Localization.instance.Localize(text);
			if (text2 == text || text2 == "[" + text.Substring(1) + "]")
			{
				text2 = ((object)drop.Skill).ToString();
			}
			drop.Text = "+" + ((drop.XP < 0.01f) ? drop.XP.ToString("0.####", CultureInfo.InvariantCulture) : drop.XP.ToString("0.##", CultureInfo.InvariantCulture)) + " XP  " + text2;
			active.Add(drop);
			nextDrop = now + Mathf.Max(0.35f, ((float)fontSize.Value + 6f) * duration.Value / distance.Value);
		}
	}

	private void IncludeBuff(RectTransform rect, ref float left)
	{
		//IL_0029: 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_0040: 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_004d: 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)
		if (!((Object)(object)rect == (Object)null) && ((Component)rect).gameObject.activeInHierarchy)
		{
			Canvas componentInParent = ((Component)rect).GetComponentInParent<Canvas>();
			if (!((Object)(object)componentInParent == (Object)null))
			{
				Camera val = (((int)componentInParent.renderMode == 0) ? null : componentInParent.worldCamera);
				Bounds val2 = RectTransformUtility.CalculateRelativeRectTransformBounds((Transform)(object)rect);
				left = Mathf.Min(left, RectTransformUtility.WorldToScreenPoint(val, ((Transform)rect).TransformPoint(((Bounds)(ref val2)).min)).x);
			}
		}
	}

	private void OnGUI()
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Invalid comparison between Unknown and I4
		//IL_0522: Unknown result type (might be due to invalid IL or missing references)
		//IL_0529: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c1: Expected O, but got Unknown
		//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d1: Expected O, but got Unknown
		//IL_028f: Unknown result type (might be due to invalid IL or missing references)
		//IL_02a5: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_02cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_024d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0257: Expected O, but got Unknown
		//IL_0307: Unknown result type (might be due to invalid IL or missing references)
		//IL_0311: Expected O, but got Unknown
		//IL_030c: Unknown result type (might be due to invalid IL or missing references)
		//IL_037f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0384: Unknown result type (might be due to invalid IL or missing references)
		//IL_0386: Unknown result type (might be due to invalid IL or missing references)
		//IL_038b: Unknown result type (might be due to invalid IL or missing references)
		//IL_040f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0482: Unknown result type (might be due to invalid IL or missing references)
		//IL_04b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_04cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_04d0: Unknown result type (might be due to invalid IL or missing references)
		//IL_04e9: Unknown result type (might be due to invalid IL or missing references)
		//IL_04f0: Unknown result type (might be due to invalid IL or missing references)
		if ((int)Event.current.type != 7 || !CanDraw() || active.Count == 0)
		{
			return;
		}
		Rect buffAnchor = MMCSkillDrainClock.GetBuffAnchor();
		if (((Rect)(ref buffAnchor)).width <= 0f)
		{
			return;
		}
		float left = ((Rect)(ref buffAnchor)).xMin;
		object? value = rested.GetValue(buffs);
		IncludeBuff((RectTransform)((value is RectTransform) ? value : null), ref left);
		object? value2 = corpse.GetValue(buffs);
		IncludeBuff((RectTransform)((value2 is RectTransform) ? value2 : null), ref left);
		if (powers.GetValue(buffs) is List<RectTransform> list)
		{
			foreach (RectTransform item in list)
			{
				IncludeBuff(item, ref left);
			}
		}
		if (!(foods == null))
		{
			foods.GetValue(buffs);
		}
		FieldInfo[] array = new FieldInfo[2] { others, debuffs };
		foreach (FieldInfo fieldInfo in array)
		{
			List<RectTransform> list2 = ((fieldInfo == null) ? null : (fieldInfo.GetValue(buffs) as List<RectTransform>));
			if (list2 == null)
			{
				continue;
			}
			foreach (RectTransform item2 in list2)
			{
				IncludeBuff(item2, ref left);
			}
		}
		GUIStyle val = (GUIStyle)((clockStyle == null) ? null : /*isinst with value type is only supported in some contexts*/);
		if (style == null)
		{
			style = new GUIStyle(GUI.skin.label);
			style.padding = new RectOffset();
			style.wordWrap = false;
			style.richText = false;
		}
		style.font = ((val == null) ? GUI.skin.label.font : val.font);
		style.fontStyle = (FontStyle)2;
		style.fontSize = fontSize.Value;
		style.alignment = (TextAnchor)5;
		if (shadowStyle == null)
		{
			shadowStyle = new GUIStyle(style);
		}
		shadowStyle.font = style.font;
		shadowStyle.fontSize = style.fontSize;
		shadowStyle.fontStyle = style.fontStyle;
		shadowStyle.alignment = style.alignment;
		shadowStyle.normal.textColor = Color.black;
		style.normal.textColor = Color.white;
		float num = 0f;
		foreach (Drop item3 in active)
		{
			num = Mathf.Max(num, style.CalcSize(new GUIContent(item3.Text)).x);
		}
		float num2 = left - gap.Value;
		float num3 = Mathf.Max(4f, ((Rect)(ref buffAnchor)).yMin);
		if (num2 < num + 4f)
		{
			num2 = num + 4f;
			num3 += 110f;
		}
		float num4 = -1000f;
		Color color = GUI.color;
		Matrix4x4 matrix = GUI.matrix;
		try
		{
			Rect val2 = default(Rect);
			foreach (Drop item4 in active)
			{
				float num5 = (Time.unscaledTime - item4.Born) / duration.Value;
				float num6 = Mathf.Clamp01((1f - num5) / 0.3f);
				float num7 = Mathf.Max(num4 + (float)fontSize.Value + 6f, num3 + distance.Value * (1f - num5));
				num4 = num7;
				GUI.matrix = matrix;
				float num8 = num2 - num;
				float num9 = num7;
				layout.Anchor(ref num8, ref num9, num2 - num, num3);
				layout.ScaleAt(num8, num9, num, (float)(fontSize.Value + 6));
				((Rect)(ref val2))..ctor(num8, num9, num, (float)(fontSize.Value + 6));
				GUI.color = new Color(1f, 1f, 1f, num6);
				GUI.Label(new Rect(((Rect)(ref val2)).x + 1f, ((Rect)(ref val2)).y + 1f, ((Rect)(ref val2)).width, ((Rect)(ref val2)).height), item4.Text, shadowStyle);
				Color white = Color.white;
				white.a = 1f;
				style.normal.textColor = white;
				GUI.Label(val2, item4.Text, style);
			}
		}
		finally
		{
			GUI.color = color;
			GUI.matrix = matrix;
		}
	}

	private void OnDestroy()
	{
		if (harmony != null)
		{
			harmony.UnpatchSelf();
		}
		instance = null;
	}
}
internal static class SagaConfigPreview
{
	private static BaseUnityPlugin manager;

	private static PropertyInfo displaying;

	private static float retry;

	private static int frame = -1;

	private static bool open;

	internal static bool Open
	{
		get
		{
			if (frame == Time.frameCount)
			{
				return open;
			}
			frame = Time.frameCount;
			open = false;
			if ((Object)(object)manager == (Object)null && Time.unscaledTime >= retry)
			{
				retry = Time.unscaledTime + 2f;
				if (Chainloader.PluginInfos.TryGetValue("com.bepis.bepinex.configurationmanager", out var value))
				{
					manager = value.Instance;
					displaying = ((object)manager).GetType().GetProperty("DisplayingWindow", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				}
			}
			if ((Object)(object)manager != (Object)null && displaying != null)
			{
				try
				{
					open = (bool)displaying.GetValue(manager, null);
				}
				catch
				{
					open = false;
				}
			}
			return open;
		}
	}

	internal static bool HudVisible(Hud hud)
	{
		if ((Object)(object)hud != (Object)null)
		{
			if (!Open)
			{
				return hud.IsVisible();
			}
			return true;
		}
		return false;
	}

	internal static bool MenuVisible()
	{
		if (!Open)
		{
			return Menu.IsVisible();
		}
		return false;
	}

	internal static bool MapVisible()
	{
		if (!Open)
		{
			return Minimap.IsOpen();
		}
		return false;
	}

	internal static bool StoreVisible()
	{
		if (!Open)
		{
			return StoreGui.IsVisible();
		}
		return false;
	}

	internal static bool InventoryHidesHud()
	{
		if (!Open)
		{
			return InventoryGui.IsVisible();
		}
		return false;
	}
}