Decompiled source of UnlockHints v1.0.3

UnlockHints.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text.RegularExpressions;
using BepInEx;
using RoR2;
using RoR2.Skills;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace UnlockHints;

[BepInPlugin("local.unlockhints", "UnlockHints", "0.8.0")]
public class UnlockHintsPlugin : BaseUnityPlugin
{
	private struct LockedAbility
	{
		public string Name;

		public string Hint;

		public Sprite Icon;
	}

	private const float ReferenceHeight = 1080f;

	private const float ReferenceWidth = 1920f;

	private const float PanelWidth = 340f;

	private const float Padding = 12f;

	private const float IconSize = 40f;

	private const float TextGap = 10f;

	private const float RowSpacing = 10f;

	private const float Margin = 20f;

	private const float TopOffset = 230f;

	private const float BracketLength = 14f;

	private const int CanvasSortOrder = -10;

	private static readonly Regex RichTextTag = new Regex("<[^>]+>");

	private static readonly Regex RequiresLine = new Regex("^Requires[^\\n]*\\n?", RegexOptions.Multiline);

	private static readonly Color Fill = new Color(0.07f, 0.06f, 0.09f, 0.75f);

	private static readonly Color Bracket = new Color(0.9f, 0.9f, 0.92f, 0.85f);

	private static readonly Color Divider = new Color(0.9f, 0.9f, 0.92f, 0.25f);

	private static readonly Color IconGrey = new Color(0.18f, 0.18f, 0.2f, 0.8f);

	private static readonly Color NameColor = new Color(0.95f, 0.85f, 0.55f, 1f);

	private static readonly Color HintColor = new Color(0.78f, 0.78f, 0.82f, 1f);

	private GameObject root;

	private RectTransform panel;

	private TextMeshProUGUI header;

	private Sprite solidSprite;

	private TMP_FontAsset gameFont;

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

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

	private string shownKey = "";

	private void Update()
	{
		EnsureCanvas();
		if (!Input.GetKey((KeyCode)9))
		{
			root.SetActive(false);
			return;
		}
		CharacterBody localBody = GetLocalBody();
		if ((Object)(object)localBody == (Object)null)
		{
			root.SetActive(false);
			return;
		}
		List<LockedAbility> lockedAbilities = GetLockedAbilities(localBody);
		root.SetActive(true);
		string text = localBody.GetDisplayName() + "|" + string.Join("|", lockedAbilities.ConvertAll((LockedAbility l) => l.Name + "#" + l.Hint).ToArray());
		if (text != shownKey)
		{
			shownKey = text;
			Rebuild(localBody, lockedAbilities);
		}
	}

	private void EnsureCanvas()
	{
		//IL_001a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Expected O, but got Unknown
		//IL_0029: 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_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_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_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_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_009e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a8: Expected O, but got Unknown
		//IL_00f0: 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_0132: Expected O, but got Unknown
		//IL_0151: Unknown result type (might be due to invalid IL or missing references)
		//IL_015b: Expected O, but got Unknown
		//IL_016b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0186: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d7: 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_0221: 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_0264: Unknown result type (might be due to invalid IL or missing references)
		//IL_0287: Unknown result type (might be due to invalid IL or missing references)
		//IL_02ad: 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_0303: 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_0351: Unknown result type (might be due to invalid IL or missing references)
		//IL_039a: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)root != (Object)null))
		{
			Texture2D val = new Texture2D(2, 2);
			val.SetPixels((Color[])(object)new Color[4]
			{
				Color.white,
				Color.white,
				Color.white,
				Color.white
			});
			val.Apply();
			solidSprite = Sprite.Create(val, new Rect(0f, 0f, 2f, 2f), new Vector2(0.5f, 0.5f));
			root = new GameObject("UnlockHintsCanvas");
			Object.DontDestroyOnLoad((Object)(object)root);
			Canvas val2 = root.AddComponent<Canvas>();
			val2.renderMode = (RenderMode)0;
			val2.sortingOrder = -10;
			CanvasScaler val3 = root.AddComponent<CanvasScaler>();
			val3.uiScaleMode = (ScaleMode)1;
			val3.referenceResolution = new Vector2(1920f, 1080f);
			val3.matchWidthOrHeight = 1f;
			GameObject val4 = new GameObject("Panel", new Type[2]
			{
				typeof(RectTransform),
				typeof(Image)
			});
			val4.transform.SetParent(root.transform, false);
			panel = (RectTransform)val4.transform;
			panel.anchorMin = new Vector2(0f, 1f);
			panel.anchorMax = new Vector2(0f, 1f);
			panel.pivot = new Vector2(0f, 1f);
			panel.anchoredPosition = new Vector2(20f, -230f);
			panel.sizeDelta = new Vector2(340f, 200f);
			Image component = val4.GetComponent<Image>();
			component.sprite = solidSprite;
			((Graphic)component).color = Fill;
			float num = 340f;
			AddBar(0f, 0f, 14f, 1f, Bracket);
			AddBar(0f, 0f, 1f, 14f, Bracket);
			AddBar(num - 14f, 0f, 14f, 1f, Bracket);
			AddBar(num - 1f, 0f, 1f, 14f, Bracket);
			bottomBrackets.Add(AddBar(0f, 0f, 14f, 1f, Bracket));
			bottomBrackets.Add(AddBar(0f, 0f, 1f, 14f, Bracket));
			bottomBrackets.Add(AddBar(0f, 0f, 14f, 1f, Bracket));
			bottomBrackets.Add(AddBar(0f, 0f, 1f, 14f, Bracket));
			header = CreateText((Transform)(object)panel, 18f, (FontStyles)1, (TextAlignmentOptions)514, Color.white);
			Place(((TMP_Text)header).rectTransform, 12f, -12f, 316f, 22f);
			AddBar(12f, -38f, 316f, 1f, Divider);
			root.SetActive(false);
		}
	}

	private void Rebuild(CharacterBody body, List<LockedAbility> locked)
	{
		//IL_009e: Unknown result type (might be due to invalid IL or missing references)
		//IL_012d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0134: Expected O, but got Unknown
		//IL_0161: Unknown result type (might be due to invalid IL or missing references)
		//IL_0371: Unknown result type (might be due to invalid IL or missing references)
		//IL_0207: Unknown result type (might be due to invalid IL or missing references)
		//IL_0221: Expected O, but got Unknown
		//IL_0234: 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_01a1: 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_01f4: Unknown result type (might be due to invalid IL or missing references)
		((TMP_Text)header).text = "Unlocks: " + body.GetDisplayName();
		ApplyFont((TMP_Text)(object)header);
		foreach (GameObject row in rows)
		{
			Object.Destroy((Object)(object)row);
		}
		rows.Clear();
		float width = 266f;
		float num = -46f;
		if (locked.Count == 0)
		{
			TextMeshProUGUI val = CreateText((Transform)(object)panel, 13f, (FontStyles)0, (TextAlignmentOptions)257, HintColor);
			((TMP_Text)val).text = "All abilities unlocked.";
			Place(((TMP_Text)val).rectTransform, 12f, num, 316f, 20f);
			rows.Add(((Component)val).gameObject);
			num -= 20f;
		}
		foreach (LockedAbility item in locked)
		{
			GameObject val2 = new GameObject("Icon", new Type[2]
			{
				typeof(RectTransform),
				typeof(RawImage)
			});
			val2.transform.SetParent((Transform)(object)panel, false);
			rows.Add(val2);
			RawImage component = val2.GetComponent<RawImage>();
			((Graphic)component).color = IconGrey;
			Sprite icon = item.Icon;
			if ((Object)(object)icon != (Object)null && (Object)(object)icon.texture != (Object)null)
			{
				Texture2D texture = icon.texture;
				Rect textureRect = icon.textureRect;
				component.texture = (Texture)(object)texture;
				component.uvRect = new Rect(((Rect)(ref textureRect)).x / (float)((Texture)texture).width, ((Rect)(ref textureRect)).y / (float)((Texture)texture).height, ((Rect)(ref textureRect)).width / (float)((Texture)texture).width, ((Rect)(ref textureRect)).height / (float)((Texture)texture).height);
			}
			Place((RectTransform)val2.transform, 12f, num, 40f, 40f);
			TextMeshProUGUI val3 = CreateText((Transform)(object)panel, 15f, (FontStyles)1, (TextAlignmentOptions)257, NameColor);
			((TMP_Text)val3).text = item.Name;
			Place(((TMP_Text)val3).rectTransform, 62f, num, width, 18f);
			rows.Add(((Component)val3).gameObject);
			TextMeshProUGUI val4 = CreateText((Transform)(object)panel, 13f, (FontStyles)0, (TextAlignmentOptions)257, HintColor);
			((TMP_Text)val4).text = item.Hint;
			Place(((TMP_Text)val4).rectTransform, 62f, num - 18f, width, 14f);
			float preferredHeight = ((TMP_Text)val4).preferredHeight;
			Place(((TMP_Text)val4).rectTransform, 62f, num - 18f, width, Mathf.Max(14f, preferredHeight));
			rows.Add(((Component)val4).gameObject);
			float num2 = Mathf.Max(40f, 18f + Mathf.Max(14f, preferredHeight) + 4f);
			num -= num2 + 10f;
		}
		float num3 = 0f - num + 12f - 6f;
		panel.sizeDelta = new Vector2(340f, num3);
		PlaceBottomBrackets(num3);
	}

	private void PlaceBottomBrackets(float h)
	{
		if (bottomBrackets.Count >= 4)
		{
			float num = 340f;
			Place(bottomBrackets[0], 0f, 0f - (h - 1f), 14f, 1f);
			Place(bottomBrackets[1], 0f, 0f - (h - 14f), 1f, 14f);
			Place(bottomBrackets[2], num - 14f, 0f - (h - 1f), 14f, 1f);
			Place(bottomBrackets[3], num - 1f, 0f - (h - 14f), 1f, 14f);
		}
	}

	private RectTransform AddBar(float x, float y, float width, float height, Color color)
	{
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Expected O, but got Unknown
		//IL_0054: 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_0068: Expected O, but got Unknown
		GameObject val = new GameObject("Bar", new Type[2]
		{
			typeof(RectTransform),
			typeof(Image)
		});
		val.transform.SetParent((Transform)(object)panel, false);
		Image component = val.GetComponent<Image>();
		component.sprite = solidSprite;
		((Graphic)component).color = color;
		RectTransform val2 = (RectTransform)val.transform;
		Place(val2, x, y, width, height);
		return val2;
	}

	private TextMeshProUGUI CreateText(Transform parent, float fontSize, FontStyles style, TextAlignmentOptions alignment, Color color)
	{
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_002c: Expected O, but got Unknown
		//IL_0052: 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_0063: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = new GameObject("Text", new Type[2]
		{
			typeof(RectTransform),
			typeof(TextMeshProUGUI)
		});
		val.transform.SetParent(parent, false);
		TextMeshProUGUI component = val.GetComponent<TextMeshProUGUI>();
		ApplyFont((TMP_Text)(object)component);
		((TMP_Text)component).fontSize = fontSize;
		((TMP_Text)component).fontStyle = style;
		((TMP_Text)component).alignment = alignment;
		((Graphic)component).color = color;
		((TMP_Text)component).enableWordWrapping = true;
		((TMP_Text)component).overflowMode = (TextOverflowModes)0;
		((Graphic)component).raycastTarget = false;
		return component;
	}

	private TMP_FontAsset GetFont()
	{
		if ((Object)(object)gameFont != (Object)null)
		{
			return gameFont;
		}
		TMP_Text[] array = Resources.FindObjectsOfTypeAll<TMP_Text>();
		foreach (TMP_Text val in array)
		{
			if (!((Object)(object)val == (Object)null) && !((Object)(object)val.font == (Object)null) && !((Object)val.font).name.StartsWith("LiberationSans"))
			{
				gameFont = val.font;
				return gameFont;
			}
		}
		return null;
	}

	private void ApplyFont(TMP_Text text)
	{
		TMP_FontAsset font = GetFont();
		if ((Object)(object)font != (Object)null)
		{
			text.font = font;
		}
	}

	private static void Place(RectTransform rt, float x, float yTop, float width, float height)
	{
		//IL_000c: 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_0038: 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_0055: Unknown result type (might be due to invalid IL or missing references)
		rt.anchorMin = new Vector2(0f, 1f);
		rt.anchorMax = new Vector2(0f, 1f);
		rt.pivot = new Vector2(0f, 1f);
		rt.anchoredPosition = new Vector2(x, yTop);
		rt.sizeDelta = new Vector2(width, height);
	}

	private static CharacterBody GetLocalBody()
	{
		if (PlayerCharacterMasterController.instances.Count == 0)
		{
			return null;
		}
		CharacterMaster master = PlayerCharacterMasterController.instances[0].master;
		return ((Object)(object)master != (Object)null) ? master.GetBody() : null;
	}

	private static List<LockedAbility> GetLockedAbilities(CharacterBody body)
	{
		//IL_0074: Unknown result type (might be due to invalid IL or missing references)
		//IL_0079: Unknown result type (might be due to invalid IL or missing references)
		//IL_007c: 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)
		List<LockedAbility> list = new List<LockedAbility>();
		LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser();
		UserProfile val = ((firstLocalUser != null) ? firstLocalUser.userProfile : null);
		if (val == null)
		{
			return list;
		}
		GenericSkill[] components = ((Component)body).GetComponents<GenericSkill>();
		foreach (GenericSkill val2 in components)
		{
			if ((Object)(object)val2.skillFamily == (Object)null)
			{
				continue;
			}
			Variant[] variants = val2.skillFamily.variants;
			foreach (Variant val3 in variants)
			{
				UnlockableDef unlockableDef = val3.unlockableDef;
				if (!((Object)(object)unlockableDef == (Object)null) && !val.HasUnlockable(unlockableDef))
				{
					SkillDef skillDef = val3.skillDef;
					list.Add(new LockedAbility
					{
						Name = StripTags(Language.GetString(skillDef.skillNameToken)),
						Hint = RemoveRequiresLine(StripTags(unlockableDef.getHowToUnlockString())),
						Icon = skillDef.icon
					});
				}
			}
		}
		return list;
	}

	private static string StripTags(string text)
	{
		return string.IsNullOrEmpty(text) ? "" : RichTextTag.Replace(text, "").Trim();
	}

	private static string RemoveRequiresLine(string text)
	{
		return string.IsNullOrEmpty(text) ? "" : RequiresLine.Replace(text, "").Trim();
	}
}