Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of CosmeticUnlockProgressHUD v4.0.0
CosmeticUnlockProgressHUD.dll
Decompiled 3 weeks agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; 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: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: IgnoresAccessChecksTo("")] [assembly: AssemblyCompany("REPOJP")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("zabuMod")] [assembly: AssemblyTitle("zabuMod")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace REPOJP.CosmeticUnlockProgressHUD { [BepInPlugin("REPOJP.CosmeticUnlockProgressHUD", "Cosmetic Unlock Progress HUD", "4.0.0")] public sealed class CosmeticUnlockProgressHUDPlugin : BaseUnityPlugin { public const string PluginGuid = "REPOJP.CosmeticUnlockProgressHUD"; public const string PluginName = "Cosmetic Unlock Progress HUD"; public const string PluginVersion = "4.0.0"; internal static ManualLogSource LogSource; internal static Harmony HarmonyInstance; internal static ConfigEntry<bool> EnableMod; internal static ConfigEntry<bool> ShowInShop; internal static ConfigEntry<bool> ShowInCosmeticsMenu; internal static ConfigEntry<bool> HideOnCosmeticColorPage; internal static ConfigEntry<bool> HideOnCosmeticPopup; internal static ConfigEntry<bool> ShowAllCosmetics; internal static ConfigEntry<bool> ShowRarityBreakdown; internal static ConfigEntry<bool> UseRarityNameColor; internal static ConfigEntry<bool> IncludeOnlyValidPrefab; internal static ConfigEntry<float> ShopPositionX; internal static ConfigEntry<float> ShopPositionY; internal static ConfigEntry<float> CosmeticsMenuPositionX; internal static ConfigEntry<float> CosmeticsMenuPositionY; internal static ConfigEntry<int> FontSize; internal static ConfigEntry<float> TextAlpha; internal static ConfigEntry<int> PercentDecimals; internal static ConfigEntry<string> CommonColor; internal static ConfigEntry<string> UncommonColor; internal static ConfigEntry<string> RareColor; internal static ConfigEntry<string> UltraRareColor; internal static ConfigEntry<string> DefaultTextColor; private CosmeticUnlockProgressController controller; private void Awake() { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown try { LogSource = ((BaseUnityPlugin)this).Logger; ((Component)this).transform.parent = null; ((Object)((Component)this).gameObject).hideFlags = (HideFlags)52; Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject); BindConfig(); HarmonyInstance = new Harmony("REPOJP.CosmeticUnlockProgressHUD"); HarmonyInstance.PatchAll(); controller = ((Component)this).gameObject.AddComponent<CosmeticUnlockProgressController>(); controller.Initialize(); LogSource.LogInfo((object)"Cosmetic Unlock Progress HUD loaded."); } catch (Exception ex) { if (LogSource != null) { LogSource.LogError((object)("Failure: Awake\n" + ex)); } } } private void OnDestroy() { try { if (HarmonyInstance != null) { HarmonyInstance.UnpatchSelf(); } } catch (Exception ex) { if (LogSource != null) { LogSource.LogError((object)("Failure: OnDestroy\n" + ex)); } } } private void BindConfig() { //IL_01d5: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Expected O, but got Unknown //IL_0212: Unknown result type (might be due to invalid IL or missing references) //IL_021c: Expected O, but got Unknown //IL_0243: Unknown result type (might be due to invalid IL or missing references) //IL_024d: Expected O, but got Unknown EnableMod = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnableMod", true, "Enable or disable this mod."); ShowInShop = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "ShowInShop", true, "Show progress while in the shop level."); ShowInCosmeticsMenu = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "ShowInCosmeticsMenu", true, "Show progress while the normal cosmetics menu page is open."); HideOnCosmeticColorPage = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "HideOnCosmeticColorPage", true, "Hide progress while the cosmetic color page is open."); HideOnCosmeticPopup = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "HideOnCosmeticPopup", true, "Hide progress while cosmetic popups are open."); ShowAllCosmetics = ((BaseUnityPlugin)this).Config.Bind<bool>("Text", "ShowAllCosmetics", true, "Show the AllCosmetics line."); ShowRarityBreakdown = ((BaseUnityPlugin)this).Config.Bind<bool>("Text", "ShowRarityBreakdown", true, "Show rarity breakdown lines."); UseRarityNameColor = ((BaseUnityPlugin)this).Config.Bind<bool>("Text", "UseRarityNameColor", true, "Color only the rarity name labels."); IncludeOnlyValidPrefab = ((BaseUnityPlugin)this).Config.Bind<bool>("Count", "IncludeOnlyValidPrefab", true, "Count only cosmetics with a valid prefab reference."); ShopPositionX = ((BaseUnityPlugin)this).Config.Bind<float>("Position", "ShopPositionX", -30f, "HUD X position while in shop. Negative values move left from the top-right anchor."); ShopPositionY = ((BaseUnityPlugin)this).Config.Bind<float>("Position", "ShopPositionY", -180f, "HUD Y position while in shop. Negative values move down from the top-right anchor."); CosmeticsMenuPositionX = ((BaseUnityPlugin)this).Config.Bind<float>("Position", "CosmeticsMenuPositionX", -30f, "HUD X position while the cosmetics menu is open. Negative values move left from the top-right anchor."); CosmeticsMenuPositionY = ((BaseUnityPlugin)this).Config.Bind<float>("Position", "CosmeticsMenuPositionY", -180f, "HUD Y position while the cosmetics menu is open. Negative values move down from the top-right anchor."); FontSize = ((BaseUnityPlugin)this).Config.Bind<int>("Style", "FontSize", 20, new ConfigDescription("Text font size.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(8, 60), Array.Empty<object>())); TextAlpha = ((BaseUnityPlugin)this).Config.Bind<float>("Style", "TextAlpha", 0.95f, new ConfigDescription("Text alpha.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); PercentDecimals = ((BaseUnityPlugin)this).Config.Bind<int>("Style", "PercentDecimals", 2, new ConfigDescription("Percent decimal places.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 4), Array.Empty<object>())); CommonColor = ((BaseUnityPlugin)this).Config.Bind<string>("Colors", "CommonColor", "#00C807", "Common rarity color."); UncommonColor = ((BaseUnityPlugin)this).Config.Bind<string>("Colors", "UncommonColor", "#0398CB", "Uncommon rarity color."); RareColor = ((BaseUnityPlugin)this).Config.Bind<string>("Colors", "RareColor", "#BD06BB", "Rare rarity color."); UltraRareColor = ((BaseUnityPlugin)this).Config.Bind<string>("Colors", "UltraRareColor", "#B89005", "Ultra Rare rarity color."); DefaultTextColor = ((BaseUnityPlugin)this).Config.Bind<string>("Colors", "DefaultTextColor", "#FFFFFF", "Default text color."); } } internal sealed class CosmeticUnlockProgressController : MonoBehaviour { private static CosmeticUnlockProgressController instance; private GameObject canvasObject; private Canvas canvas; private RectTransform textRect; private TextMeshProUGUI textMesh; private bool initialized; private bool dirty = true; private bool lastVisible; private bool lastCosmeticsMenuContext; private int lastAssetsCount = -1; private int lastUnlocksCount = -1; private float nextCountCheckTime; private float nextPeriodicRefreshTime; private float nextMissingFieldLogTime; internal static void MarkDirty() { if ((Object)(object)instance != (Object)null) { instance.dirty = true; } } internal void Initialize() { instance = this; initialized = true; dirty = true; } private void OnDestroy() { if ((Object)(object)instance == (Object)(object)this) { instance = null; } if ((Object)(object)canvasObject != (Object)null) { Object.Destroy((Object)(object)canvasObject); canvasObject = null; } } private void Update() { if (!initialized) { return; } try { if (!ShouldShow(out var cosmeticsMenuContext)) { SetVisible(visible: false); lastVisible = false; return; } EnsureCanvas(); if (!((Object)(object)textMesh == (Object)null)) { SetVisible(visible: true); ApplyTextStyle(cosmeticsMenuContext); if (!lastVisible || lastCosmeticsMenuContext != cosmeticsMenuContext) { dirty = true; } CheckCountChanges(); if (Time.unscaledTime >= nextPeriodicRefreshTime) { nextPeriodicRefreshTime = Time.unscaledTime + 1f; dirty = true; } if (dirty) { RefreshText(); dirty = false; } lastVisible = true; lastCosmeticsMenuContext = cosmeticsMenuContext; } } catch (Exception ex) { SetVisible(visible: false); if (CosmeticUnlockProgressHUDPlugin.LogSource != null) { CosmeticUnlockProgressHUDPlugin.LogSource.LogError((object)("Failure: Update\n" + ex)); } } } private bool ShouldShow(out bool cosmeticsMenuContext) { cosmeticsMenuContext = false; if (!CosmeticUnlockProgressHUDPlugin.EnableMod.Value) { return false; } if (!CosmeticUnlockProgressCounter.IsMetaSaveReady()) { return false; } if (IsCosmeticsMenuNormalPageVisible()) { cosmeticsMenuContext = true; return true; } if (IsShopVisible()) { cosmeticsMenuContext = false; return true; } return false; } private bool IsShopVisible() { if (!CosmeticUnlockProgressHUDPlugin.ShowInShop.Value) { return false; } if ((Object)(object)RunManager.instance == (Object)null) { return false; } if ((Object)(object)GameDirector.instance == (Object)null) { return false; } try { return SemiFunc.RunIsShop(); } catch { return false; } } private bool IsCosmeticsMenuNormalPageVisible() { //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Invalid comparison between Unknown and I4 //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Invalid comparison between Unknown and I4 //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Invalid comparison between Unknown and I4 //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Invalid comparison between Unknown and I4 if (!CosmeticUnlockProgressHUDPlugin.ShowInCosmeticsMenu.Value) { return false; } if ((Object)(object)MenuManager.instance == (Object)null) { return false; } MenuPage currentMenuPage = CosmeticUnlockProgressCounter.GetCurrentMenuPage(); if ((Object)(object)currentMenuPage == (Object)null) { return false; } if (!CosmeticUnlockProgressCounter.TryGetCurrentMenuPageIndex(out var pageIndex)) { return false; } if (CosmeticUnlockProgressHUDPlugin.HideOnCosmeticColorPage.Value && (int)pageIndex == 10) { return false; } if (CosmeticUnlockProgressHUDPlugin.HideOnCosmeticPopup.Value && ((int)pageIndex == 9 || (int)pageIndex == 7)) { return false; } return (int)pageIndex == 20; } private void EnsureCanvas() { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown //IL_00a0: 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_00c2: Expected O, but got Unknown //IL_00ff: 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_0135: 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) if (!((Object)(object)canvasObject != (Object)null) || !((Object)(object)textMesh != (Object)null)) { canvasObject = new GameObject("CosmeticUnlockProgressHUDCanvas"); ((Object)canvasObject).hideFlags = (HideFlags)52; Object.DontDestroyOnLoad((Object)(object)canvasObject); canvas = canvasObject.AddComponent<Canvas>(); canvas.renderMode = (RenderMode)0; canvas.sortingOrder = 30000; CanvasScaler val = canvasObject.AddComponent<CanvasScaler>(); val.uiScaleMode = (ScaleMode)1; val.referenceResolution = new Vector2(1920f, 1080f); val.matchWidthOrHeight = 0.5f; GameObject val2 = new GameObject("CosmeticUnlockProgressHUDText"); ((Object)val2).hideFlags = (HideFlags)52; val2.transform.SetParent(canvasObject.transform, false); textRect = val2.AddComponent<RectTransform>(); textRect.anchorMin = new Vector2(1f, 1f); textRect.anchorMax = new Vector2(1f, 1f); textRect.pivot = new Vector2(1f, 1f); textRect.sizeDelta = new Vector2(760f, 260f); textMesh = val2.AddComponent<TextMeshProUGUI>(); ((Graphic)textMesh).raycastTarget = false; ((TMP_Text)textMesh).richText = true; ((TMP_Text)textMesh).alignment = (TextAlignmentOptions)260; ((TMP_Text)textMesh).enableWordWrapping = false; ((TMP_Text)textMesh).overflowMode = (TextOverflowModes)0; ((TMP_Text)textMesh).text = string.Empty; dirty = true; } } private void SetVisible(bool visible) { if ((Object)(object)canvasObject != (Object)null && canvasObject.activeSelf != visible) { canvasObject.SetActive(visible); } } private void ApplyTextStyle(bool cosmeticsMenuContext) { //IL_0071: 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_00a5: 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) if (!((Object)(object)textMesh == (Object)null) && !((Object)(object)textRect == (Object)null)) { if (cosmeticsMenuContext) { textRect.anchoredPosition = new Vector2(CosmeticUnlockProgressHUDPlugin.CosmeticsMenuPositionX.Value, CosmeticUnlockProgressHUDPlugin.CosmeticsMenuPositionY.Value); } else { textRect.anchoredPosition = new Vector2(CosmeticUnlockProgressHUDPlugin.ShopPositionX.Value, CosmeticUnlockProgressHUDPlugin.ShopPositionY.Value); } ((TMP_Text)textMesh).fontSize = CosmeticUnlockProgressHUDPlugin.FontSize.Value; ((Graphic)textMesh).color = GetConfiguredColor(CosmeticUnlockProgressHUDPlugin.DefaultTextColor.Value, Color.white, CosmeticUnlockProgressHUDPlugin.TextAlpha.Value); } } private void CheckCountChanges() { if (!(Time.unscaledTime < nextCountCheckTime)) { nextCountCheckTime = Time.unscaledTime + 0.25f; int cosmeticAssetsCount = CosmeticUnlockProgressCounter.GetCosmeticAssetsCount(); int cosmeticUnlocksCount = CosmeticUnlockProgressCounter.GetCosmeticUnlocksCount(); if (cosmeticAssetsCount != lastAssetsCount || cosmeticUnlocksCount != lastUnlocksCount) { lastAssetsCount = cosmeticAssetsCount; lastUnlocksCount = cosmeticUnlocksCount; dirty = true; } } } private void RefreshText() { if (!((Object)(object)textMesh == (Object)null)) { if (!CosmeticUnlockProgressCounter.TryCount(out var result)) { ((TMP_Text)textMesh).text = string.Empty; LogMissingFieldOnce(); } else { ((TMP_Text)textMesh).text = BuildDisplayText(result); } } } private string BuildDisplayText(CosmeticUnlockProgressResult result) { StringBuilder stringBuilder = new StringBuilder(256); int decimals = Mathf.Clamp(CosmeticUnlockProgressHUDPlugin.PercentDecimals.Value, 0, 4); if (CosmeticUnlockProgressHUDPlugin.ShowAllCosmetics.Value) { stringBuilder.Append("AllCosmetics: "); stringBuilder.Append(result.All.Unlocked.ToString(CultureInfo.InvariantCulture)); stringBuilder.Append(" / "); stringBuilder.Append(result.All.Total.ToString(CultureInfo.InvariantCulture)); stringBuilder.Append(" | "); stringBuilder.Append(FormatPercent(result.All.Percent, decimals)); stringBuilder.AppendLine("%"); } if (CosmeticUnlockProgressHUDPlugin.ShowAllCosmetics.Value && CosmeticUnlockProgressHUDPlugin.ShowRarityBreakdown.Value) { stringBuilder.AppendLine(); } if (CosmeticUnlockProgressHUDPlugin.ShowRarityBreakdown.Value) { AppendRarityLine(stringBuilder, "Common", result.Common, CosmeticUnlockProgressHUDPlugin.CommonColor.Value, decimals); AppendRarityLine(stringBuilder, "Uncommon", result.Uncommon, CosmeticUnlockProgressHUDPlugin.UncommonColor.Value, decimals); AppendRarityLine(stringBuilder, "Rare", result.Rare, CosmeticUnlockProgressHUDPlugin.RareColor.Value, decimals); AppendRarityLine(stringBuilder, "Ultra Rare", result.UltraRare, CosmeticUnlockProgressHUDPlugin.UltraRareColor.Value, decimals); } return stringBuilder.ToString().TrimEnd('\r', '\n'); } private void AppendRarityLine(StringBuilder builder, string rarityName, CosmeticUnlockProgressPart part, string htmlColor, int decimals) { if (CosmeticUnlockProgressHUDPlugin.UseRarityNameColor.Value) { builder.Append("<color="); builder.Append(NormalizeHtmlColor(htmlColor, "#FFFFFF")); builder.Append(">"); builder.Append(rarityName); builder.Append(":</color> "); } else { builder.Append(rarityName); builder.Append(": "); } builder.Append(part.Unlocked.ToString(CultureInfo.InvariantCulture)); builder.Append(" / "); builder.Append(part.Total.ToString(CultureInfo.InvariantCulture)); builder.Append(" | "); builder.Append(FormatPercent(part.Percent, decimals)); builder.AppendLine("%"); } private string FormatPercent(float value, int decimals) { return value.ToString("F" + decimals.ToString(CultureInfo.InvariantCulture), CultureInfo.InvariantCulture); } private Color GetConfiguredColor(string htmlColor, Color fallback, float alpha) { //IL_002c: 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_001c: 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_0030: Unknown result type (might be due to invalid IL or missing references) Color result = default(Color); if (!ColorUtility.TryParseHtmlString(NormalizeHtmlColor(htmlColor, "#FFFFFF"), ref result)) { result = fallback; } result.a = Mathf.Clamp01(alpha); return result; } private string NormalizeHtmlColor(string htmlColor, string fallback) { if (string.IsNullOrWhiteSpace(htmlColor)) { return fallback; } string text = htmlColor.Trim(); if (!text.StartsWith("#", StringComparison.Ordinal)) { text = "#" + text; } if (text.Length != 7 && text.Length != 9) { return fallback; } return text; } private void LogMissingFieldOnce() { if (!(Time.unscaledTime < nextMissingFieldLogTime)) { nextMissingFieldLogTime = Time.unscaledTime + 10f; if (CosmeticUnlockProgressHUDPlugin.LogSource != null) { CosmeticUnlockProgressHUDPlugin.LogSource.LogWarning((object)"Cosmetic progress could not be counted yet."); } } } } internal static class CosmeticUnlockProgressCounter { private static readonly FieldInfo CosmeticUnlocksField = AccessTools.Field(typeof(MetaManager), "cosmeticUnlocks"); private static readonly FieldInfo SaveReadyField = AccessTools.Field(typeof(MetaManager), "saveReady"); private static readonly FieldInfo CurrentMenuPageIndexField = AccessTools.Field(typeof(MenuManager), "currentMenuPageIndex"); private static readonly FieldInfo CurrentMenuPageField = AccessTools.Field(typeof(MenuManager), "currentMenuPage"); internal static bool IsMetaSaveReady() { if ((Object)(object)MetaManager.instance == (Object)null) { return false; } if (SaveReadyField == null) { return true; } try { object value = SaveReadyField.GetValue(MetaManager.instance); if (value is bool) { return (bool)value; } } catch { return false; } return false; } internal static int GetCosmeticAssetsCount() { if ((Object)(object)MetaManager.instance == (Object)null || MetaManager.instance.cosmeticAssets == null) { return -1; } return MetaManager.instance.cosmeticAssets.Count; } internal static int GetCosmeticUnlocksCount() { return GetCosmeticUnlocks()?.Count ?? (-1); } internal static MenuPage GetCurrentMenuPage() { if ((Object)(object)MenuManager.instance == (Object)null || CurrentMenuPageField == null) { return null; } try { object? value = CurrentMenuPageField.GetValue(MenuManager.instance); return (MenuPage)((value is MenuPage) ? value : null); } catch { return null; } } internal static bool TryGetCurrentMenuPageIndex(out MenuPageIndex pageIndex) { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Expected I4, but got Unknown pageIndex = (MenuPageIndex)0; if ((Object)(object)MenuManager.instance == (Object)null || CurrentMenuPageIndexField == null) { return false; } try { object value = CurrentMenuPageIndexField.GetValue(MenuManager.instance); if (value is MenuPageIndex) { pageIndex = (MenuPageIndex)(int)(MenuPageIndex)value; return true; } } catch { return false; } return false; } internal static bool TryCount(out CosmeticUnlockProgressResult result) { //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Invalid comparison between Unknown and I4 //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Invalid comparison between Unknown and I4 //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Invalid comparison between Unknown and I4 //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Invalid comparison between Unknown and I4 result = new CosmeticUnlockProgressResult(); if ((Object)(object)MetaManager.instance == (Object)null || MetaManager.instance.cosmeticAssets == null) { return false; } List<int> cosmeticUnlocks = GetCosmeticUnlocks(); if (cosmeticUnlocks == null) { return false; } HashSet<int> hashSet = new HashSet<int>(cosmeticUnlocks); List<CosmeticAsset> cosmeticAssets = MetaManager.instance.cosmeticAssets; for (int i = 0; i < cosmeticAssets.Count; i++) { CosmeticAsset val = cosmeticAssets[i]; if (IsCountTarget(val)) { bool unlocked = hashSet.Contains(i); AddToPart(result.All, unlocked); if ((int)val.rarity == 0) { AddToPart(result.Common, unlocked); } else if ((int)val.rarity == 1) { AddToPart(result.Uncommon, unlocked); } else if ((int)val.rarity == 2) { AddToPart(result.Rare, unlocked); } else if ((int)val.rarity == 3) { AddToPart(result.UltraRare, unlocked); } } } result.Calculate(); return true; } private static List<int> GetCosmeticUnlocks() { if ((Object)(object)MetaManager.instance == (Object)null || CosmeticUnlocksField == null) { return null; } try { return CosmeticUnlocksField.GetValue(MetaManager.instance) as List<int>; } catch { return null; } } private static bool IsCountTarget(CosmeticAsset asset) { if ((Object)(object)asset == (Object)null) { return false; } if (!CosmeticUnlockProgressHUDPlugin.IncludeOnlyValidPrefab.Value) { return true; } if (asset.prefab == null) { return false; } return asset.prefab.IsValid(); } private static void AddToPart(CosmeticUnlockProgressPart part, bool unlocked) { part.Total++; if (unlocked) { part.Unlocked++; } } } internal sealed class CosmeticUnlockProgressResult { internal CosmeticUnlockProgressPart All = new CosmeticUnlockProgressPart(); internal CosmeticUnlockProgressPart Common = new CosmeticUnlockProgressPart(); internal CosmeticUnlockProgressPart Uncommon = new CosmeticUnlockProgressPart(); internal CosmeticUnlockProgressPart Rare = new CosmeticUnlockProgressPart(); internal CosmeticUnlockProgressPart UltraRare = new CosmeticUnlockProgressPart(); internal void Calculate() { All.Calculate(); Common.Calculate(); Uncommon.Calculate(); Rare.Calculate(); UltraRare.Calculate(); } } internal sealed class CosmeticUnlockProgressPart { internal int Total; internal int Unlocked; internal float Percent; internal void Calculate() { if (Total <= 0) { Percent = 0f; } else { Percent = (float)Unlocked * 100f / (float)Total; } } } [HarmonyPatch(typeof(MetaManager), "CosmeticUnlock")] internal static class MetaManagerCosmeticUnlockPatch { private static void Postfix() { CosmeticUnlockProgressController.MarkDirty(); } } }