Decompiled source of Cosmetics UI v1.0.0

plugins/CosmeticsUI.dll

Decompiled 5 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: AssemblyTitle("REPO Cosmetics Display")]
[assembly: AssemblyDescription("A BepInEx mod that displays unlocked cosmetics on the map screen")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("REPO Cosmetics Display")]
[assembly: AssemblyCopyright("Copyright © 2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("87654321-4321-4321-4321-210987654321")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("1.0.0.0")]
namespace REPOCosmeticsDisplay;

[BepInPlugin("com.repo.cosmetics.display", "REPO Cosmetics Display", "1.0.0")]
public class REPOCosmeticsMod : BaseUnityPlugin
{
	public static REPOCosmeticsMod Instance;

	public static ManualLogSource Log;

	private readonly Harmony harmony = new Harmony("com.repo.cosmetics.display");

	public static GameObject TextInstance;

	public static TextMeshProUGUI CosmeticsText;

	private static bool _resolved = false;

	private static FieldInfo _fieldRarity = null;

	private static int _rarityCommon = -2;

	private static int _rarityUncommon = -2;

	private static int _rarityRare = -2;

	private static int _rarityUltraRare = -2;

	private static readonly Color ColCommon = new Color(0.4f, 0.9f, 0.4f, 1f);

	private static readonly Color ColUncommon = new Color(0.4f, 0.75f, 1f, 1f);

	private static readonly Color ColRare = new Color(0.72f, 0.4f, 1f, 1f);

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

	private static readonly Color ColDefault = new Color(0.79f, 0.91f, 0.9f, 1f);

	private static FieldInfo _fieldCosmeticAssets = null;

	private static FieldInfo _fieldCosmeticUnlocks = null;

	private static FieldInfo _metaManagerInstanceField = null;

	private void Awake()
	{
		Instance = this;
		Log = ((BaseUnityPlugin)this).Logger;
		Log.LogInfo((object)"REPO Cosmetics Display loaded");
		harmony.PatchAll();
	}

	public static void ResolveReflection()
	{
		if (_resolved)
		{
			return;
		}
		_resolved = true;
		Assembly assembly = null;
		Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
		foreach (Assembly assembly2 in assemblies)
		{
			if (assembly2.GetName().Name == "Assembly-CSharp")
			{
				assembly = assembly2;
				break;
			}
		}
		if (assembly == null)
		{
			Log.LogWarning((object)"Assembly-CSharp not found");
			return;
		}
		Type[] types = assembly.GetTypes();
		foreach (Type type in types)
		{
			if (!(type.Name != "MetaManager"))
			{
				_fieldCosmeticAssets = type.GetField("cosmeticAssets", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				_fieldCosmeticUnlocks = type.GetField("cosmeticUnlocks", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				_metaManagerInstanceField = type.GetField("instance", BindingFlags.Static | BindingFlags.Public);
				break;
			}
		}
		Log.LogInfo((object)("MetaManager — cosmeticAssets=" + (_fieldCosmeticAssets != null) + "  cosmeticUnlocks=" + (_fieldCosmeticUnlocks != null) + "  instance=" + (_metaManagerInstanceField != null)));
		Type[] types2 = assembly.GetTypes();
		foreach (Type type2 in types2)
		{
			if (!(type2.Name != "CosmeticAsset"))
			{
				_fieldRarity = type2.GetField("rarity", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				Log.LogInfo((object)("CosmeticAsset found — rarity field=" + (_fieldRarity != null)));
				break;
			}
		}
		if (_fieldRarity == null)
		{
			Log.LogWarning((object)"rarity field not found");
			return;
		}
		Type fieldType = _fieldRarity.FieldType;
		if (!fieldType.IsEnum)
		{
			return;
		}
		string[] names = Enum.GetNames(fieldType);
		Array values = Enum.GetValues(fieldType);
		for (int l = 0; l < names.Length; l++)
		{
			string text = names[l].ToLower();
			int num = (int)values.GetValue(l);
			if (text.Contains("ultra"))
			{
				_rarityUltraRare = num;
			}
			else if (text.Contains("rare"))
			{
				_rarityRare = num;
			}
			else if (text.Contains("uncommon"))
			{
				_rarityUncommon = num;
			}
			else if (text.Contains("common"))
			{
				_rarityCommon = num;
			}
		}
		Log.LogInfo((object)$"Rarity — Common:{_rarityCommon}  Uncommon:{_rarityUncommon}  Rare:{_rarityRare}  UltraRare:{_rarityUltraRare}");
	}

	public static void ReadCosmeticCounts(out int totalAll, out int ownedAll, out int ownedCommon, out int totalCommon, out int ownedUncommon, out int totalUncommon, out int ownedRare, out int totalRare, out int ownedUltra, out int totalUltra)
	{
		totalAll = (ownedAll = 0);
		ownedCommon = (totalCommon = 0);
		ownedUncommon = (totalUncommon = 0);
		ownedRare = (totalRare = 0);
		ownedUltra = (totalUltra = 0);
		if (_metaManagerInstanceField == null || _fieldCosmeticAssets == null || _fieldCosmeticUnlocks == null)
		{
			return;
		}
		try
		{
			object value = _metaManagerInstanceField.GetValue(null);
			if (value == null)
			{
				return;
			}
			IList list = _fieldCosmeticAssets.GetValue(value) as IList;
			IList list2 = _fieldCosmeticUnlocks.GetValue(value) as IList;
			if (list == null || list2 == null)
			{
				return;
			}
			HashSet<int> hashSet = new HashSet<int>();
			foreach (object item in list2)
			{
				hashSet.Add((int)item);
			}
			for (int i = 0; i < list.Count; i++)
			{
				object obj = list[i];
				if (obj == null)
				{
					continue;
				}
				int num = ((!(_fieldRarity != null)) ? (-1) : ((int)_fieldRarity.GetValue(obj)));
				bool flag = hashSet.Contains(i);
				totalAll++;
				if (flag)
				{
					ownedAll++;
				}
				if (num == _rarityCommon)
				{
					totalCommon++;
					if (flag)
					{
						ownedCommon++;
					}
				}
				else if (num == _rarityUncommon)
				{
					totalUncommon++;
					if (flag)
					{
						ownedUncommon++;
					}
				}
				else if (num == _rarityRare)
				{
					totalRare++;
					if (flag)
					{
						ownedRare++;
					}
				}
				else if (num == _rarityUltraRare)
				{
					totalUltra++;
					if (flag)
					{
						ownedUltra++;
					}
				}
			}
		}
		catch (Exception ex)
		{
			Log.LogDebug((object)("CosmeticsDisplay read failed: " + ex.Message));
		}
	}

	public static string BuildHudText(int ownedAll, int totalAll, int ownedCommon, int totalCommon, int ownedUncommon, int totalUncommon, int ownedRare, int totalRare, int ownedUltra, int totalUltra)
	{
		//IL_000a: 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_007b: 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_00ef: Unknown result type (might be due to invalid IL or missing references)
		string text = string.Format("<color={0}>Cosmetics: {1} / {2}</color>", "#" + ColorUtility.ToHtmlStringRGB(ColDefault), ownedAll, totalAll);
		List<string> list = new List<string>();
		if (totalCommon > 0)
		{
			list.Add(string.Format("<color={0}>● {1}/{2}</color>", "#" + ColorUtility.ToHtmlStringRGB(ColCommon), ownedCommon, totalCommon));
		}
		if (totalUncommon > 0)
		{
			list.Add(string.Format("<color={0}>● {1}/{2}</color>", "#" + ColorUtility.ToHtmlStringRGB(ColUncommon), ownedUncommon, totalUncommon));
		}
		if (totalRare > 0)
		{
			list.Add(string.Format("<color={0}>● {1}/{2}</color>", "#" + ColorUtility.ToHtmlStringRGB(ColRare), ownedRare, totalRare));
		}
		if (totalUltra > 0)
		{
			list.Add(string.Format("<color={0}>● {1}/{2}</color>", "#" + ColorUtility.ToHtmlStringRGB(ColUltraRare), ownedUltra, totalUltra));
		}
		return (list.Count <= 0) ? text : (text + "\n" + string.Join("\n", list.ToArray()));
	}

	public static bool EnsureUI()
	{
		//IL_005d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0067: Expected O, but got Unknown
		//IL_00b6: 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_0105: 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_012f: 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)
		if ((Object)(object)TextInstance != (Object)null)
		{
			return true;
		}
		GameObject val = GameObject.Find("Game Hud");
		GameObject val2 = GameObject.Find("Tax Haul");
		if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null)
		{
			return false;
		}
		TMP_Text component = val2.GetComponent<TMP_Text>();
		TMP_FontAsset font = ((component != null) ? component.font : null);
		TextInstance = new GameObject("CosmeticsDisplay");
		TextInstance.transform.SetParent(val.transform, false);
		TextInstance.SetActive(false);
		CosmeticsText = TextInstance.AddComponent<TextMeshProUGUI>();
		((TMP_Text)CosmeticsText).font = font;
		((TMP_Text)CosmeticsText).fontSize = 15f;
		((Graphic)CosmeticsText).color = Color.white;
		((TMP_Text)CosmeticsText).alignment = (TextAlignmentOptions)260;
		((TMP_Text)CosmeticsText).richText = true;
		RectTransform component2 = TextInstance.GetComponent<RectTransform>();
		component2.anchorMin = new Vector2(1f, 1f);
		component2.anchorMax = new Vector2(1f, 1f);
		component2.pivot = new Vector2(1f, 1f);
		component2.anchoredPosition = new Vector2(-20f, -50f);
		component2.sizeDelta = new Vector2(320f, 400f);
		Log.LogInfo((object)"Cosmetics HUD text element created");
		return true;
	}
}
[HarmonyPatch(typeof(RoundDirector), "Update")]
public static class RoundDirectorUpdatePatch
{
	private static int _frameCounter = 0;

	private const int RefreshEvery = 120;

	private static int _cachedTotalAll = 0;

	private static int _cachedOwnedAll = 0;

	private static int _cachedTotalCommon = 0;

	private static int _cachedOwnedCommon = 0;

	private static int _cachedTotalUncommon = 0;

	private static int _cachedOwnedUncommon = 0;

	private static int _cachedTotalRare = 0;

	private static int _cachedOwnedRare = 0;

	private static int _cachedTotalUltra = 0;

	private static int _cachedOwnedUltra = 0;

	[HarmonyPostfix]
	public static void Postfix()
	{
		if (!SemiFunc.InputHold((InputKey)8) && (!((Object)(object)MapToolController.instance != (Object)null) || !Traverse.Create((object)MapToolController.instance).Field("mapToggled").GetValue<bool>()))
		{
			if ((Object)(object)REPOCosmeticsMod.TextInstance != (Object)null)
			{
				REPOCosmeticsMod.TextInstance.SetActive(false);
			}
			return;
		}
		REPOCosmeticsMod.ResolveReflection();
		if (REPOCosmeticsMod.EnsureUI())
		{
			_frameCounter++;
			if (_frameCounter >= 120 || _cachedTotalAll == 0)
			{
				_frameCounter = 0;
				REPOCosmeticsMod.ReadCosmeticCounts(out _cachedTotalAll, out _cachedOwnedAll, out _cachedOwnedCommon, out _cachedTotalCommon, out _cachedOwnedUncommon, out _cachedTotalUncommon, out _cachedOwnedRare, out _cachedTotalRare, out _cachedOwnedUltra, out _cachedTotalUltra);
			}
			REPOCosmeticsMod.TextInstance.SetActive(true);
			((TMP_Text)REPOCosmeticsMod.CosmeticsText).SetText(REPOCosmeticsMod.BuildHudText(_cachedOwnedAll, _cachedTotalAll, _cachedOwnedCommon, _cachedTotalCommon, _cachedOwnedUncommon, _cachedTotalUncommon, _cachedOwnedRare, _cachedTotalRare, _cachedOwnedUltra, _cachedTotalUltra), true);
		}
	}
}