using 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 EnableMod; internal static ConfigEntry ShowInShop; internal static ConfigEntry ShowInCosmeticsMenu; internal static ConfigEntry HideOnCosmeticColorPage; internal static ConfigEntry HideOnCosmeticPopup; internal static ConfigEntry ShowAllCosmetics; internal static ConfigEntry ShowRarityBreakdown; internal static ConfigEntry UseRarityNameColor; internal static ConfigEntry IncludeOnlyValidPrefab; internal static ConfigEntry ShopPositionX; internal static ConfigEntry ShopPositionY; internal static ConfigEntry CosmeticsMenuPositionX; internal static ConfigEntry CosmeticsMenuPositionY; internal static ConfigEntry FontSize; internal static ConfigEntry TextAlpha; internal static ConfigEntry PercentDecimals; internal static ConfigEntry CommonColor; internal static ConfigEntry UncommonColor; internal static ConfigEntry RareColor; internal static ConfigEntry UltraRareColor; internal static ConfigEntry 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(); 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("General", "EnableMod", true, "Enable or disable this mod."); ShowInShop = ((BaseUnityPlugin)this).Config.Bind("Display", "ShowInShop", true, "Show progress while in the shop level."); ShowInCosmeticsMenu = ((BaseUnityPlugin)this).Config.Bind("Display", "ShowInCosmeticsMenu", true, "Show progress while the normal cosmetics menu page is open."); HideOnCosmeticColorPage = ((BaseUnityPlugin)this).Config.Bind("Display", "HideOnCosmeticColorPage", true, "Hide progress while the cosmetic color page is open."); HideOnCosmeticPopup = ((BaseUnityPlugin)this).Config.Bind("Display", "HideOnCosmeticPopup", true, "Hide progress while cosmetic popups are open."); ShowAllCosmetics = ((BaseUnityPlugin)this).Config.Bind("Text", "ShowAllCosmetics", true, "Show the AllCosmetics line."); ShowRarityBreakdown = ((BaseUnityPlugin)this).Config.Bind("Text", "ShowRarityBreakdown", true, "Show rarity breakdown lines."); UseRarityNameColor = ((BaseUnityPlugin)this).Config.Bind("Text", "UseRarityNameColor", true, "Color only the rarity name labels."); IncludeOnlyValidPrefab = ((BaseUnityPlugin)this).Config.Bind("Count", "IncludeOnlyValidPrefab", true, "Count only cosmetics with a valid prefab reference."); ShopPositionX = ((BaseUnityPlugin)this).Config.Bind("Position", "ShopPositionX", -30f, "HUD X position while in shop. Negative values move left from the top-right anchor."); ShopPositionY = ((BaseUnityPlugin)this).Config.Bind("Position", "ShopPositionY", -180f, "HUD Y position while in shop. Negative values move down from the top-right anchor."); CosmeticsMenuPositionX = ((BaseUnityPlugin)this).Config.Bind("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("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("Style", "FontSize", 20, new ConfigDescription("Text font size.", (AcceptableValueBase)(object)new AcceptableValueRange(8, 60), Array.Empty())); TextAlpha = ((BaseUnityPlugin)this).Config.Bind("Style", "TextAlpha", 0.95f, new ConfigDescription("Text alpha.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 1f), Array.Empty())); PercentDecimals = ((BaseUnityPlugin)this).Config.Bind("Style", "PercentDecimals", 2, new ConfigDescription("Percent decimal places.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 4), Array.Empty())); CommonColor = ((BaseUnityPlugin)this).Config.Bind("Colors", "CommonColor", "#00C807", "Common rarity color."); UncommonColor = ((BaseUnityPlugin)this).Config.Bind("Colors", "UncommonColor", "#0398CB", "Uncommon rarity color."); RareColor = ((BaseUnityPlugin)this).Config.Bind("Colors", "RareColor", "#BD06BB", "Rare rarity color."); UltraRareColor = ((BaseUnityPlugin)this).Config.Bind("Colors", "UltraRareColor", "#B89005", "Ultra Rare rarity color."); DefaultTextColor = ((BaseUnityPlugin)this).Config.Bind("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.renderMode = (RenderMode)0; canvas.sortingOrder = 30000; CanvasScaler val = canvasObject.AddComponent(); 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(); 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(); ((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(""); builder.Append(rarityName); builder.Append(": "); } 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 cosmeticUnlocks = GetCosmeticUnlocks(); if (cosmeticUnlocks == null) { return false; } HashSet hashSet = new HashSet(cosmeticUnlocks); List 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 GetCosmeticUnlocks() { if ((Object)(object)MetaManager.instance == (Object)null || CosmeticUnlocksField == null) { return null; } try { return CosmeticUnlocksField.GetValue(MetaManager.instance) as List; } 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(); } } }