Decompiled source of ShowForgiveMeTimer v1.0.2

ShowForgiveMeTimer.dll

Decompiled 18 hours ago
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using RiskOfOptions;
using RiskOfOptions.OptionConfigs;
using RiskOfOptions.Options;
using RoR2;
using RoR2.Projectile;
using RoR2.UI;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("ShowForgiveMeTimer")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.2.0")]
[assembly: AssemblyInformationalVersion("1.0.2")]
[assembly: AssemblyProduct("ShowForgiveMeTimer")]
[assembly: AssemblyTitle("ShowForgiveMeTimer")]
[assembly: AssemblyVersion("1.0.2.0")]
namespace ShowForgiveMeTimer;

[DisallowMultipleComponent]
internal sealed class BarsDisplay : MonoBehaviour
{
	private sealed class Column
	{
		public GameObject Root;

		public RectTransform RootRect;

		public RectTransform Bar;

		public RectTransform Inner;

		public RectTransform Fill;

		public Image FillImage;

		public RectTransform Label;

		public TextMeshProUGUI Text;

		public string LastText;

		public float LastFontMax;

		public bool Visible;
	}

	private const int Slots = 3;

	private static readonly Color FrameColor = new Color(0.8f, 0.85f, 0.89f, 0.75f);

	private static readonly Color BackColor = new Color(0.06f, 0.08f, 0.1f, 0.82f);

	private static readonly Color CalmColor = new Color(0.36f, 0.87f, 0.75f, 1f);

	private static readonly Color ShortColor = new Color(1f, 0.75f, 0.3f, 1f);

	private static readonly Color LastColor = new Color(1f, 0.39f, 0.39f, 1f);

	private static readonly Color WaitingColor = new Color(0.62f, 0.68f, 0.76f, 1f);

	private HUD hud;

	private EquipmentIcon icon;

	private Canvas canvas;

	private RectTransform panel;

	private CanvasGroup group;

	private Column[] columns;

	private bool panelVisible;

	private bool reportedError;

	private readonly TrackedDoll[] assigned = new TrackedDoll[3];

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

	private void Awake()
	{
		hud = ((Component)this).GetComponent<HUD>();
	}

	private void LateUpdate()
	{
		try
		{
			Refresh();
		}
		catch (Exception ex)
		{
			if (!reportedError)
			{
				reportedError = true;
				Plugin.Log.LogError((object)("Erro ao desenhar as barras: " + ex));
			}
		}
	}

	private void OnDisable()
	{
		SetPanelVisible(visible: false);
	}

	private void OnDestroy()
	{
		DestroyPanel();
	}

	private void Refresh()
	{
		Settings settings = Plugin.Settings;
		if (!Object.op_Implicit((Object)(object)hud) || settings == null || !EnsureBuilt())
		{
			return;
		}
		CharacterMaster targetMaster = hud.targetMaster;
		UpdateAssignments(targetMaster);
		bool value = settings.Preview.Value;
		bool flag = false;
		for (int i = 0; i < 3; i++)
		{
			flag |= assigned[i] != null;
		}
		if (!((Component)icon).gameObject.activeInHierarchy || !(value || flag))
		{
			SetPanelVisible(visible: false);
			return;
		}
		SetPanelVisible(visible: true);
		group.alpha = settings.Opacity.Value;
		Layout(settings);
		bool value2 = settings.ShowTenths.Value;
		float sinceFixedStep = Time.time - Time.fixedTime;
		for (int j = 0; j < 3; j++)
		{
			DrawColumn(j, value, value2, sinceFixedStep);
		}
	}

	private void UpdateAssignments(CharacterMaster master)
	{
		for (int i = 0; i < 3; i++)
		{
			TrackedDoll trackedDoll = assigned[i];
			if (trackedDoll != null && (!trackedDoll.Alive || !Object.op_Implicit((Object)(object)master) || (Object)(object)trackedDoll.OwnerMaster != (Object)(object)master))
			{
				assigned[i] = null;
			}
		}
		if (!Object.op_Implicit((Object)(object)master))
		{
			return;
		}
		IReadOnlyList<TrackedDoll> all = DollTracker.All;
		for (int j = 0; j < all.Count; j++)
		{
			TrackedDoll trackedDoll2 = all[j];
			if (trackedDoll2.Alive && !((Object)(object)trackedDoll2.OwnerMaster != (Object)(object)master) && !IsAssigned(trackedDoll2))
			{
				int num = FirstFreeSlot();
				if (num < 0)
				{
					break;
				}
				assigned[num] = trackedDoll2;
			}
		}
	}

	private bool IsAssigned(TrackedDoll d)
	{
		for (int i = 0; i < 3; i++)
		{
			if (assigned[i] == d)
			{
				return true;
			}
		}
		return false;
	}

	private int FirstFreeSlot()
	{
		for (int i = 0; i < 3; i++)
		{
			if (assigned[i] == null)
			{
				return i;
			}
		}
		return -1;
	}

	private void DrawColumn(int i, bool preview, bool tenths, float sinceFixedStep)
	{
		//IL_00d0: 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_00e2: 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_0106: 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_010a: 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_00f8: 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)
		Column column = columns[i];
		float remaining;
		float fullLifetime;
		bool flag;
		string text;
		if (preview)
		{
			float num = (Time.unscaledTime + (float)i * 3f) % 9f;
			remaining = 9f - num;
			fullLifetime = 9f;
			flag = false;
			text = TimerMath.Format(remaining, tenths);
		}
		else
		{
			TrackedDoll trackedDoll = assigned[i];
			if (trackedDoll == null)
			{
				SetColumnVisible(column, visible: false);
				return;
			}
			if (!trackedDoll.EverStuck)
			{
				remaining = 1f;
				fullLifetime = 1f;
				flag = true;
				text = "...";
			}
			else
			{
				remaining = (trackedDoll.Paused ? trackedDoll.Remaining : TimerMath.Smooth(trackedDoll.Remaining, sinceFixedStep, Time.fixedDeltaTime));
				fullLifetime = trackedDoll.FullLifetime;
				flag = trackedDoll.Paused;
				text = TimerMath.Format(remaining, tenths);
			}
		}
		SetColumnVisible(column, visible: true);
		float num2 = TimerMath.Fraction(remaining, fullLifetime);
		column.Fill.anchorMax = new Vector2(1f, num2);
		Color color = (Color)(flag ? WaitingColor : (TimerMath.Urgency(remaining) switch
		{
			2 => LastColor, 
			1 => ShortColor, 
			_ => CalmColor, 
		}));
		((Graphic)column.FillImage).color = color;
		if (!string.Equals(column.LastText, text, StringComparison.Ordinal))
		{
			column.LastText = text;
			((TMP_Text)column.Text).text = text;
		}
	}

	private void Layout(Settings s)
	{
		//IL_0006: 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_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_0051: 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_005b: 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_0062: 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_0074: 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_017c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0181: Unknown result type (might be due to invalid IL or missing references)
		//IL_0182: Unknown result type (might be due to invalid IL or missing references)
		//IL_018c: Expected O, but got Unknown
		//IL_018d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0197: Expected O, but got Unknown
		//IL_019e: 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_01b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c6: 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_01df: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e6: 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_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_0211: Unknown result type (might be due to invalid IL or missing references)
		//IL_0218: Unknown result type (might be due to invalid IL or missing references)
		//IL_0295: 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_02da: Unknown result type (might be due to invalid IL or missing references)
		//IL_02fb: Unknown result type (might be due to invalid IL or missing references)
		//IL_0310: Unknown result type (might be due to invalid IL or missing references)
		//IL_0327: Unknown result type (might be due to invalid IL or missing references)
		//IL_033f: 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)
		Camera val = (((int)canvas.renderMode == 0) ? null : canvas.worldCamera);
		((RectTransform)((Component)icon).transform).GetWorldCorners(corners);
		Vector2 val2 = RectTransformUtility.WorldToScreenPoint(val, corners[0]);
		Vector2 val3 = RectTransformUtility.WorldToScreenPoint(val, corners[2]);
		float num = Mathf.Min(val2.x, val3.x);
		float num2 = Mathf.Max(val2.x, val3.x);
		float num3 = Mathf.Max(val2.y, val3.y);
		num3 = Mathf.Max(num3, StockTextTop(val));
		float dpi = Screen.dpi;
		float num4 = TimerMath.CmToPixels(s.HeightCm.Value, dpi);
		float num5 = TimerMath.CmToPixels(s.GapAboveIconCm.Value, dpi);
		float num6 = TimerMath.CmToPixels(s.HorizontalOffsetCm.Value, dpi);
		float num7 = Mathf.Max(6f, (num2 - num) * s.GroupWidth.Value);
		float num8 = num7 / 3f;
		float num9 = Mathf.Clamp(num8 * 0.75f, 10f, 48f) * s.TextSize.Value;
		float num10 = (num + num2) * 0.5f + num6;
		Vector2 val4 = default(Vector2);
		((Vector2)(ref val4))..ctor(num10 - num7 * 0.5f, num3 + num5);
		Vector2 val5 = default(Vector2);
		((Vector2)(ref val5))..ctor(num10 + num7 * 0.5f, num3 + num5 + num4 + num9);
		RectTransform val6 = (RectTransform)((Transform)panel).parent;
		Vector2 val7 = default(Vector2);
		RectTransformUtility.ScreenPointToLocalPointInRectangle(val6, val4, val, ref val7);
		Vector2 val8 = default(Vector2);
		RectTransformUtility.ScreenPointToLocalPointInRectangle(val6, val5, val, ref val8);
		((Transform)panel).localPosition = new Vector3(val7.x, val7.y, 0f);
		panel.sizeDelta = new Vector2(Mathf.Max(1f, val8.x - val7.x), Mathf.Max(1f, val8.y - val7.y));
		float num11 = (val8.x - val7.x) / Mathf.Max(1f, val5.x - val4.x);
		float num12 = num4 / (num4 + num9);
		float num13 = Mathf.Clamp01(s.BarThickness.Value);
		float num14 = Mathf.Max(1f, Mathf.Round(num8 * 0.06f)) * num11;
		float num15 = num9 * 0.9f * num11;
		for (int i = 0; i < 3; i++)
		{
			Column column = columns[i];
			column.RootRect.anchorMin = new Vector2((float)i / 3f, 0f);
			column.RootRect.anchorMax = new Vector2((float)(i + 1) / 3f, 1f);
			column.Bar.anchorMin = new Vector2((1f - num13) * 0.5f, 0f);
			column.Bar.anchorMax = new Vector2((1f + num13) * 0.5f, num12);
			column.Inner.offsetMin = new Vector2(num14, num14);
			column.Inner.offsetMax = new Vector2(0f - num14, 0f - num14);
			column.Label.anchorMin = new Vector2(0f, num12);
			column.Label.anchorMax = new Vector2(1f, 1f);
			if (!Mathf.Approximately(column.LastFontMax, num15))
			{
				column.LastFontMax = num15;
				((TMP_Text)column.Text).fontSizeMax = num15;
				((TMP_Text)column.Text).fontSizeMin = num15 * 0.35f;
				((Graphic)column.Text).SetVerticesDirty();
			}
		}
	}

	private float StockTextTop(Camera cam)
	{
		//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_003d: 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_0068: 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_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)
		//IL_0083: 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)
		TextMeshProUGUI stockText = icon.stockText;
		if (!Object.op_Implicit((Object)(object)stockText) || !((Component)stockText).gameObject.activeInHierarchy || string.IsNullOrEmpty(((TMP_Text)stockText).text))
		{
			return float.MinValue;
		}
		Bounds textBounds = ((TMP_Text)stockText).textBounds;
		if (((Bounds)(ref textBounds)).size.y <= 0f)
		{
			return float.MinValue;
		}
		Vector3 val = ((Transform)((TMP_Text)stockText).rectTransform).TransformPoint(new Vector3(((Bounds)(ref textBounds)).center.x, ((Bounds)(ref textBounds)).max.y, 0f));
		return RectTransformUtility.WorldToScreenPoint(cam, val).y;
	}

	private bool EnsureBuilt()
	{
		EquipmentIcon val = FindEquipmentIcon();
		if (Object.op_Implicit((Object)(object)panel) && Object.op_Implicit((Object)(object)canvas) && Object.op_Implicit((Object)(object)val) && (Object)(object)val == (Object)(object)icon)
		{
			return true;
		}
		DestroyPanel();
		icon = val;
		if (!Object.op_Implicit((Object)(object)icon))
		{
			return false;
		}
		canvas = ((Component)icon).GetComponentInParent<Canvas>();
		if (!Object.op_Implicit((Object)(object)canvas))
		{
			return false;
		}
		BuildPanel();
		return true;
	}

	private EquipmentIcon FindEquipmentIcon()
	{
		EquipmentIcon[] equipmentIcons = hud.equipmentIcons;
		if (equipmentIcons == null)
		{
			return null;
		}
		for (int i = 0; i < equipmentIcons.Length; i++)
		{
			if (Object.op_Implicit((Object)(object)equipmentIcons[i]) && !equipmentIcons[i].displayAlternateEquipment)
			{
				return equipmentIcons[i];
			}
		}
		for (int j = 0; j < equipmentIcons.Length; j++)
		{
			if (Object.op_Implicit((Object)(object)equipmentIcons[j]))
			{
				return equipmentIcons[j];
			}
		}
		return null;
	}

	private void BuildPanel()
	{
		//IL_004a: 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_005c: 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_012f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0135: Unknown result type (might be due to invalid IL or missing references)
		//IL_0162: 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_0168: Unknown result type (might be due to invalid IL or missing references)
		//IL_016e: 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_01a6: 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_01c8: 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_0204: 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_0222: 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_0237: 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_0272: Unknown result type (might be due to invalid IL or missing references)
		//IL_0273: Unknown result type (might be due to invalid IL or missing references)
		//IL_0279: Unknown result type (might be due to invalid IL or missing references)
		//IL_0300: Unknown result type (might be due to invalid IL or missing references)
		int layer = ((Component)canvas).gameObject.layer;
		panel = CreateRect("ShowForgiveMeTimer", ((Component)canvas).transform, layer);
		RectTransform obj = panel;
		RectTransform obj2 = panel;
		Vector2 val = default(Vector2);
		((Vector2)(ref val))..ctor(0.5f, 0.5f);
		obj2.anchorMax = val;
		obj.anchorMin = val;
		panel.pivot = Vector2.zero;
		((Transform)panel).SetAsLastSibling();
		((Component)panel).gameObject.AddComponent<LayoutElement>().ignoreLayout = true;
		group = ((Component)panel).gameObject.AddComponent<CanvasGroup>();
		group.interactable = false;
		group.blocksRaycasts = false;
		TMP_FontAsset font = null;
		Material material = null;
		PickFont(ref font, ref material);
		columns = new Column[3];
		for (int i = 0; i < 3; i++)
		{
			Column column = new Column();
			column.RootRect = CreateRect("Boneco" + (i + 1), (Transform)(object)panel, layer);
			column.Root = ((Component)column.RootRect).gameObject;
			val = (column.RootRect.offsetMin = (column.RootRect.offsetMax = Vector2.zero));
			column.Bar = CreateRect("Barra", (Transform)(object)column.RootRect, layer);
			val = (column.Bar.offsetMin = (column.Bar.offsetMax = Vector2.zero));
			AddImage(column.Bar, FrameColor);
			column.Inner = CreateRect("Fundo", (Transform)(object)column.Bar, layer);
			column.Inner.anchorMin = Vector2.zero;
			column.Inner.anchorMax = Vector2.one;
			AddImage(column.Inner, BackColor);
			column.Fill = CreateRect("Tempo", (Transform)(object)column.Inner, layer);
			column.Fill.anchorMin = Vector2.zero;
			column.Fill.anchorMax = Vector2.one;
			val = (column.Fill.offsetMin = (column.Fill.offsetMax = Vector2.zero));
			column.FillImage = AddImage(column.Fill, CalmColor);
			column.Label = CreateRect("Segundos", (Transform)(object)column.RootRect, layer);
			val = (column.Label.offsetMin = (column.Label.offsetMax = Vector2.zero));
			TextMeshProUGUI val6 = ((Component)column.Label).gameObject.AddComponent<TextMeshProUGUI>();
			if (Object.op_Implicit((Object)(object)font))
			{
				((TMP_Text)val6).font = font;
			}
			if (Object.op_Implicit((Object)(object)material))
			{
				((TMP_Text)val6).fontSharedMaterial = material;
			}
			((TMP_Text)val6).alignment = (TextAlignmentOptions)1026;
			((TMP_Text)val6).enableWordWrapping = false;
			((TMP_Text)val6).overflowMode = (TextOverflowModes)0;
			((TMP_Text)val6).enableAutoSizing = true;
			((TMP_Text)val6).fontSizeMin = 6f;
			((TMP_Text)val6).fontSizeMax = 14f;
			((TMP_Text)val6).richText = false;
			((Graphic)val6).raycastTarget = false;
			((Graphic)val6).color = Color.white;
			((TMP_Text)val6).text = string.Empty;
			column.Text = val6;
			column.Root.SetActive(false);
			column.Visible = false;
			columns[i] = column;
		}
		((Component)panel).gameObject.SetActive(false);
		panelVisible = false;
		Array.Clear(assigned, 0, assigned.Length);
	}

	private void PickFont(ref TMP_FontAsset font, ref Material material)
	{
		TMP_Text val = null;
		if (Object.op_Implicit((Object)(object)icon.cooldownText) && Object.op_Implicit((Object)(object)((TMP_Text)icon.cooldownText).font))
		{
			val = (TMP_Text)(object)icon.cooldownText;
		}
		else if (Object.op_Implicit((Object)(object)icon.stockText) && Object.op_Implicit((Object)(object)((TMP_Text)icon.stockText).font))
		{
			val = (TMP_Text)(object)icon.stockText;
		}
		if (Object.op_Implicit((Object)(object)val))
		{
			font = val.font;
			material = val.fontSharedMaterial;
			return;
		}
		font = HGTextMeshProUGUI.defaultLanguageFont;
		if (!Object.op_Implicit((Object)(object)font))
		{
			font = TMP_Settings.defaultFontAsset;
		}
	}

	private static RectTransform CreateRect(string name, Transform parent, int layer)
	{
		//IL_0014: Unknown result type (might be due to invalid IL or missing references)
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_0032: 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_003d: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: 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_0053: 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_005e: 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_0073: Unknown result type (might be due to invalid IL or missing references)
		//IL_0074: Unknown result type (might be due to invalid IL or missing references)
		//IL_007e: Unknown result type (might be due to invalid IL or missing references)
		//IL_007f: Unknown result type (might be due to invalid IL or missing references)
		//IL_008a: Expected O, but got Unknown
		RectTransform val = (RectTransform)new GameObject(name, new Type[1] { typeof(RectTransform) })
		{
			layer = layer
		}.transform;
		((Transform)val).SetParent(parent, false);
		((Transform)val).localScale = Vector3.one;
		((Transform)val).localRotation = Quaternion.identity;
		val.anchorMin = Vector2.zero;
		val.anchorMax = Vector2.one;
		val.pivot = new Vector2(0.5f, 0.5f);
		val.offsetMin = Vector2.zero;
		val.offsetMax = Vector2.zero;
		return val;
	}

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

	private void SetPanelVisible(bool visible)
	{
		if (Object.op_Implicit((Object)(object)panel) && panelVisible != visible)
		{
			panelVisible = visible;
			((Component)panel).gameObject.SetActive(visible);
		}
	}

	private static void SetColumnVisible(Column col, bool visible)
	{
		if (col.Visible != visible)
		{
			col.Visible = visible;
			col.Root.SetActive(visible);
		}
	}

	private void DestroyPanel()
	{
		if (Object.op_Implicit((Object)(object)panel))
		{
			Object.Destroy((Object)(object)((Component)panel).gameObject);
		}
		panel = null;
		group = null;
		columns = null;
		panelVisible = false;
	}
}
internal sealed class TrackedDoll
{
	public readonly DeathProjectile Doll;

	public readonly ProjectileController Controller;

	public readonly ProjectileStickOnImpact Stick;

	public readonly int Order;

	public CharacterMaster OwnerMaster;

	public bool EverStuck;

	public float FullLifetime;

	public float Remaining;

	public bool Paused;

	public bool Alive => Object.op_Implicit((Object)(object)Doll);

	public TrackedDoll(DeathProjectile doll, int order)
	{
		Doll = doll;
		Order = order;
		Controller = ((Component)doll).GetComponent<ProjectileController>();
		Stick = ((Component)doll).GetComponent<ProjectileStickOnImpact>();
	}
}
internal static class DollTracker
{
	private static readonly List<TrackedDoll> dolls = new List<TrackedDoll>();

	private static int nextOrder;

	private static FieldRef<DeathProjectile, float> durationRef;

	private static FieldRef<DeathProjectile, float> fixedAgeRef;

	public static bool Ready { get; private set; }

	public static IReadOnlyList<TrackedDoll> All => dolls;

	public static bool Init()
	{
		try
		{
			FieldInfo fieldInfo = AccessTools.Field(typeof(DeathProjectile), "duration");
			FieldInfo fieldInfo2 = AccessTools.Field(typeof(DeathProjectile), "fixedAge");
			if (fieldInfo == null || fieldInfo2 == null || fieldInfo.FieldType != typeof(float) || fieldInfo2.FieldType != typeof(float))
			{
				Plugin.Log.LogError((object)"Não achei os campos 'duration'/'fixedAge' do Forgive Me Please. O jogo pode ter mudado; o cronômetro ficará desligado.");
				return Ready = false;
			}
			durationRef = AccessTools.FieldRefAccess<DeathProjectile, float>(fieldInfo);
			fixedAgeRef = AccessTools.FieldRefAccess<DeathProjectile, float>(fieldInfo2);
			return Ready = true;
		}
		catch (Exception ex)
		{
			Plugin.Log.LogError((object)("Falha ao preparar o cronômetro: " + ex));
			return Ready = false;
		}
	}

	public static void Register(DeathProjectile doll)
	{
		if (!Object.op_Implicit((Object)(object)doll))
		{
			return;
		}
		for (int i = 0; i < dolls.Count; i++)
		{
			if ((Object)(object)dolls[i].Doll == (Object)(object)doll)
			{
				return;
			}
		}
		dolls.Add(new TrackedDoll(doll, nextOrder++));
	}

	public static void Tick()
	{
		for (int num = dolls.Count - 1; num >= 0; num--)
		{
			if (!dolls[num].Alive)
			{
				dolls.RemoveAt(num);
			}
		}
		if (!Ready)
		{
			return;
		}
		float fixedDeltaTime = Time.fixedDeltaTime;
		for (int i = 0; i < dolls.Count; i++)
		{
			TrackedDoll trackedDoll = dolls[i];
			if (!Object.op_Implicit((Object)(object)trackedDoll.OwnerMaster))
			{
				trackedDoll.OwnerMaster = FindOwner(trackedDoll);
			}
			float num2 = durationRef.Invoke(trackedDoll.Doll);
			float fixedAge = fixedAgeRef.Invoke(trackedDoll.Doll);
			float removalTime = trackedDoll.Doll.removalTime;
			bool flag = Object.op_Implicit((Object)(object)trackedDoll.Stick) && trackedDoll.Stick.stuck;
			if (num2 <= 0f)
			{
				trackedDoll.Remaining = TimerMath.Remaining(num2, fixedAge, removalTime, fixedDeltaTime);
				if (!trackedDoll.EverStuck)
				{
					trackedDoll.EverStuck = true;
					trackedDoll.FullLifetime = Mathf.Max(trackedDoll.Remaining, 0.01f);
				}
				trackedDoll.Paused = false;
			}
			else if (flag)
			{
				trackedDoll.Remaining = TimerMath.Remaining(num2, fixedAge, removalTime, fixedDeltaTime);
				if (!trackedDoll.EverStuck)
				{
					trackedDoll.EverStuck = true;
					trackedDoll.FullLifetime = Mathf.Max(trackedDoll.Remaining, 0.01f);
				}
				trackedDoll.Paused = false;
			}
			else if (trackedDoll.EverStuck)
			{
				trackedDoll.Paused = true;
			}
		}
	}

	public static void Clear()
	{
		dolls.Clear();
	}

	private static CharacterMaster FindOwner(TrackedDoll d)
	{
		GameObject val = (Object.op_Implicit((Object)(object)d.Controller) ? d.Controller.owner : null);
		if (Object.op_Implicit((Object)(object)val))
		{
			CharacterBody component = val.GetComponent<CharacterBody>();
			if (Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)component.master))
			{
				return component.master;
			}
			CharacterMaster component2 = val.GetComponent<CharacterMaster>();
			if (Object.op_Implicit((Object)(object)component2))
			{
				return component2;
			}
		}
		Deployable component3 = ((Component)d.Doll).GetComponent<Deployable>();
		if (Object.op_Implicit((Object)(object)component3) && Object.op_Implicit((Object)(object)component3.ownerMaster))
		{
			return component3.ownerMaster;
		}
		return null;
	}
}
[HarmonyPatch(typeof(DeathProjectile), "Awake")]
internal static class DeathProjectileAwakePatch
{
	[HarmonyPostfix]
	private static void Postfix(DeathProjectile __instance)
	{
		try
		{
			DollTracker.Register(__instance);
		}
		catch (Exception ex)
		{
			Plugin.Log.LogError((object)ex);
		}
	}
}
[BepInPlugin("com.samuelcallai.showforgivemetimer", "Show Forgive Me Timer", "1.0.2")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public sealed class Plugin : BaseUnityPlugin
{
	public const string Guid = "com.samuelcallai.showforgivemetimer";

	public const string Name = "Show Forgive Me Timer";

	public const string Version = "1.0.2";

	internal static ManualLogSource Log;

	internal static Settings Settings;

	private Harmony harmony;

	private float nextHudScan;

	private void Awake()
	{
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		//IL_0032: Expected O, but got Unknown
		Log = ((BaseUnityPlugin)this).Logger;
		Settings = new Settings(((BaseUnityPlugin)this).Config);
		if (DollTracker.Init())
		{
			harmony = new Harmony("com.samuelcallai.showforgivemetimer");
			harmony.CreateClassProcessor(typeof(DeathProjectileAwakePatch)).Patch();
		}
		if (Chainloader.PluginInfos.ContainsKey("com.rune580.riskofoptions"))
		{
			try
			{
				RiskOfOptionsCompat.Register(Settings);
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Não foi possível colocar as opções no menu do Risk of Options: " + ex.Message));
			}
		}
		Run.onRunDestroyGlobal += delegate
		{
			DollTracker.Clear();
		};
		Log.LogInfo((object)"Show Forgive Me Timer 1.0.2 carregado.");
	}

	private void Update()
	{
		DollTracker.Tick();
		if (!(Time.unscaledTime >= nextHudScan))
		{
			return;
		}
		nextHudScan = Time.unscaledTime + 0.5f;
		ReadOnlyCollection<HUD> readOnlyInstanceList = HUD.readOnlyInstanceList;
		for (int i = 0; i < readOnlyInstanceList.Count; i++)
		{
			HUD val = readOnlyInstanceList[i];
			if (Object.op_Implicit((Object)(object)val) && !Object.op_Implicit((Object)(object)((Component)val).GetComponent<BarsDisplay>()))
			{
				((Component)val).gameObject.AddComponent<BarsDisplay>();
			}
		}
	}
}
internal static class RiskOfOptionsCompat
{
	public const string Guid = "com.rune580.riskofoptions";

	[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
	public static void Register(Settings s)
	{
		//IL_0111: Unknown result type (might be due to invalid IL or missing references)
		//IL_0125: Expected O, but got Unknown
		//IL_012b: Unknown result type (might be due to invalid IL or missing references)
		//IL_013f: Expected O, but got Unknown
		ModSettingsManager.SetModDescription("Uma barra vertical para cada boneco do Forgive Me Please (máximo de 3), acima do ícone do equipamento (Q), com os segundos até ele sumir e liberar a vaga para lançar outro. Ligue a Prévia para ajustar a posição.", "com.samuelcallai.showforgivemetimer", "Show Forgive Me Timer");
		Sprite val = LoadIcon();
		if (Object.op_Implicit((Object)(object)val))
		{
			ModSettingsManager.SetModIcon(val, "com.samuelcallai.showforgivemetimer", "Show Forgive Me Timer");
		}
		Step(s.HeightCm, 1f, 10f, 0.1f, "{0:0.0} cm");
		Step(s.GapAboveIconCm, 0f, 5f, 0.1f, "{0:0.0} cm");
		Step(s.GroupWidth, 0.5f, 2f, 0.05f, "{0:0%}");
		Step(s.BarThickness, 0.2f, 1f, 0.05f, "{0:0%}");
		Step(s.HorizontalOffsetCm, -5f, 5f, 0.1f, "{0:0.0} cm");
		Step(s.Opacity, 0.2f, 1f, 0.05f, "{0:0%}");
		Step(s.TextSize, 0.5f, 2f, 0.05f, "{0:0%}");
		ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(s.ShowTenths), "com.samuelcallai.showforgivemetimer", "Show Forgive Me Timer");
		ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(s.Preview), "com.samuelcallai.showforgivemetimer", "Show Forgive Me Timer");
	}

	private static void Step(ConfigEntry<float> entry, float min, float max, float increment, string format)
	{
		//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_000c: 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_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: Expected O, but got Unknown
		//IL_0025: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Expected O, but got Unknown
		StepSliderConfig val = new StepSliderConfig
		{
			min = min,
			max = max,
			increment = increment,
			FormatString = format
		};
		ModSettingsManager.AddOption((BaseOption)new StepSliderOption(entry, val), "com.samuelcallai.showforgivemetimer", "Show Forgive Me Timer");
	}

	private static Sprite LoadIcon()
	{
		//IL_0059: Unknown result type (might be due to invalid IL or missing references)
		//IL_005f: Expected O, but got Unknown
		//IL_0086: 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)
		try
		{
			using Stream stream = typeof(RiskOfOptionsCompat).Assembly.GetManifestResourceStream("ShowForgiveMeTimer.icon.png");
			if (stream == null)
			{
				return null;
			}
			byte[] array = new byte[stream.Length];
			int num;
			for (int i = 0; i < array.Length; i += num)
			{
				num = stream.Read(array, i, array.Length - i);
				if (num <= 0)
				{
					break;
				}
			}
			Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false);
			if (!ImageConversion.LoadImage(val, array))
			{
				return null;
			}
			return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f));
		}
		catch (IOException)
		{
			return null;
		}
	}
}
internal sealed class Settings
{
	internal const string SectionBars = "Barras";

	internal const string SectionText = "Texto";

	internal const string SectionTest = "Teste";

	public readonly ConfigEntry<float> HeightCm;

	public readonly ConfigEntry<float> GapAboveIconCm;

	public readonly ConfigEntry<float> GroupWidth;

	public readonly ConfigEntry<float> BarThickness;

	public readonly ConfigEntry<float> HorizontalOffsetCm;

	public readonly ConfigEntry<float> Opacity;

	public readonly ConfigEntry<float> TextSize;

	public readonly ConfigEntry<bool> ShowTenths;

	public readonly ConfigEntry<bool> Preview;

	public Settings(ConfigFile config)
	{
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: Expected O, but got Unknown
		//IL_0069: Unknown result type (might be due to invalid IL or missing references)
		//IL_0073: Expected O, but got Unknown
		//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ac: 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_0114: Unknown result type (might be due to invalid IL or missing references)
		//IL_011e: Expected O, but got Unknown
		//IL_014d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0157: Expected O, but got Unknown
		//IL_0186: Unknown result type (might be due to invalid IL or missing references)
		//IL_0190: Expected O, but got Unknown
		HeightCm = config.Bind<float>("Barras", "AlturaCm", 3.2f, new ConfigDescription("Altura das barras, em centímetros (aproximado: usa o DPI do Windows).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 10f), Array.Empty<object>()));
		GapAboveIconCm = config.Bind<float>("Barras", "DistanciaAcimaDoQCm", 0.1f, new ConfigDescription("Espaço entre o topo do ícone do Q (ou do número de cargas) e o pé das barras, em centímetros.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 5f), Array.Empty<object>()));
		GroupWidth = config.Bind<float>("Barras", "LarguraDoConjunto", 1f, new ConfigDescription("Largura das três barras juntas, comparada com o ícone do Q. 1 = mesma largura do ícone.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 2f), Array.Empty<object>()));
		BarThickness = config.Bind<float>("Barras", "GrossuraDasBarras", 0.6f, new ConfigDescription("Quanto de cada coluna a barra ocupa. 1 = barras encostadas umas nas outras.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.2f, 1f), Array.Empty<object>()));
		HorizontalOffsetCm = config.Bind<float>("Barras", "DeslocamentoHorizontalCm", 0f, new ConfigDescription("Empurra as barras para a esquerda (negativo) ou para a direita (positivo), em centímetros.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-5f, 5f), Array.Empty<object>()));
		Opacity = config.Bind<float>("Barras", "Opacidade", 0.3f, new ConfigDescription("Opacidade das barras e dos números. 1 = totalmente sólido.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.2f, 1f), Array.Empty<object>()));
		TextSize = config.Bind<float>("Texto", "TamanhoDoTexto", 1f, new ConfigDescription("Tamanho dos números acima das barras (1 = padrão).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 2f), Array.Empty<object>()));
		ShowTenths = config.Bind<bool>("Texto", "MostrarDecimos", true, "Mostra os segundos com uma casa decimal (6.4). Desligado, mostra só segundos inteiros (7).");
		Preview = config.Bind<bool>("Teste", "Previa", false, "Mostra três barras de exemplo durante a partida, sem precisar lançar bonecos. Serve para ajustar a posição e o tamanho. Lembre de desligar depois.");
	}
}
public static class TimerMath
{
	public const float ShortTimeThreshold = 3f;

	public const float LastSecondThreshold = 1f;

	public static float Remaining(float duration, float fixedAge, float removalTime)
	{
		float num = Math.Max(0f, removalTime);
		float num2 = Math.Max(0f, fixedAge);
		if (duration > 0f)
		{
			float num3 = (float)Math.Ceiling(duration);
			return Math.Max(0f, num3 - Math.Min(num2, 1f) + num);
		}
		return Math.Max(0f, num - num2);
	}

	public static float Remaining(float duration, float fixedAge, float removalTime, float fixedDeltaTime)
	{
		if (!(fixedDeltaTime > 0.0005f) || !(fixedDeltaTime <= 0.5f))
		{
			return Remaining(duration, fixedAge, removalTime);
		}
		float target = Math.Max(0f, removalTime);
		float start = Math.Max(0f, fixedAge);
		if (duration > 0f)
		{
			int num = (int)Math.Ceiling(duration);
			return (float)(StepsUntil(start, 1f, fixedDeltaTime) + (num - 1) * StepsUntil(0f, 1f, fixedDeltaTime) + StepsUntil(0f, target, fixedDeltaTime)) * fixedDeltaTime;
		}
		return (float)StepsUntil(start, target, fixedDeltaTime) * fixedDeltaTime;
	}

	public static int StepsUntil(float start, float target, float dt)
	{
		float num = start;
		int num2 = 0;
		do
		{
			num += dt;
			num2++;
		}
		while (num < target && num2 < 100000);
		return num2;
	}

	public static float Smooth(float remaining, float sinceLastFixedStep, float fixedDeltaTime)
	{
		float val = Math.Max(0f, fixedDeltaTime);
		float num = Math.Min(Math.Max(0f, sinceLastFixedStep), val);
		return Math.Max(0f, remaining - num);
	}

	public static float Fraction(float remaining, float fullLifetime)
	{
		if (fullLifetime <= 0.01f)
		{
			if (!(remaining > 0f))
			{
				return 0f;
			}
			return 1f;
		}
		float num = remaining / fullLifetime;
		if (num < 0f)
		{
			return 0f;
		}
		if (num > 1f)
		{
			return 1f;
		}
		return num;
	}

	public static int Urgency(float remaining)
	{
		if (remaining <= 1f)
		{
			return 2;
		}
		if (remaining <= 3f)
		{
			return 1;
		}
		return 0;
	}

	public static string Format(float remaining, bool tenths)
	{
		float num = Math.Max(0f, remaining);
		if (tenths)
		{
			double num2 = Math.Ceiling((double)num * 10.0 - 0.0001) / 10.0;
			if (num2 <= 0.0)
			{
				return "0.0";
			}
			return num2.ToString("0.0", CultureInfo.InvariantCulture);
		}
		return Math.Max(0, (int)Math.Ceiling((double)num - 0.0001)).ToString(CultureInfo.InvariantCulture);
	}

	public static float CmToPixels(float cm, float dpi)
	{
		float num = ((dpi >= 50f && dpi <= 600f) ? dpi : 96f);
		return cm / 2.54f * num;
	}
}