Decompiled source of Shop Prestige v1.3.3
BepInEx/plugins/ShopPrestige/ShopPrestige.dll
Decompiled a day ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using CC; using HarmonyLib; using Microsoft.CodeAnalysis; using Pathfinding; using PhoneOverhaul.API; using ShopPrestige.Ui; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("Shop Prestige")] [assembly: AssemblyDescription("The better your shop is decorated, the more it attracts.")] [assembly: AssemblyCompany("Dimwit's")] [assembly: AssemblyProduct("Shop Prestige")] [assembly: AssemblyCopyright("Copyright (c) 2026 Dimwit's")] [assembly: AssemblyVersion("1.0.0.0")] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } } namespace ShopPrestige { internal static class Art { private static readonly Dictionary<string, Sprite?> Cache = new Dictionary<string, Sprite>(); private static readonly string[] TierFiles = new string[4] { "tier_1_hole_in_the_wall", "tier_2_neighborhood_shop", "tier_3_destination_store", "tier_4_collectors_paradise" }; public static Sprite? Tier(int tier) { return Get(TierFiles[Math.Max(0, Math.Min(tier, TierFiles.Length - 1))]); } public static void Preload() { try { string path = Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)Plugin.Instance).Info.Location) ?? "", "art"); if (Directory.Exists(path)) { string[] files = Directory.GetFiles(path, "*.png"); for (int i = 0; i < files.Length; i++) { Get(Path.GetFileNameWithoutExtension(files[i])); } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("Couldn't preload the icons: " + ex.Message)); } } public static Sprite? Get(string name) { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Expected O, but got Unknown //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) if (Cache.TryGetValue(name, out Sprite value)) { return value; } Sprite val = null; try { string path = Path.Combine(Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)Plugin.Instance).Info.Location) ?? "", "art"), name + ".png"); if (File.Exists(path)) { Texture2D val2 = new Texture2D(2, 2, (TextureFormat)4, true) { filterMode = (FilterMode)2, wrapMode = (TextureWrapMode)1, name = "ShopPrestige_" + name }; if (ImageConversion.LoadImage(val2, File.ReadAllBytes(path))) { Object.DontDestroyOnLoad((Object)(object)val2); val = Sprite.Create(val2, new Rect(0f, 0f, (float)((Texture)val2).width, (float)((Texture)val2).height), new Vector2(0.5f, 0.5f), 100f); ((Object)val).name = "ShopPrestige_" + name; } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("Couldn't load art/" + name + ".png: " + ex.Message)); } Cache[name] = val; return val; } } internal static class CapPatches { public static void Apply(Harmony harmony) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Expected O, but got Unknown //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Expected O, but got Unknown HarmonyMethod val = new HarmonyMethod(AccessTools.Method(typeof(CustomerCapTranspiler), "Transpiler", (Type[])null, (Type[])null)); harmony.Patch((MethodBase)AccessTools.Method(typeof(CustomerManager), "EvaluateMaxCustomerCount", (Type[])null, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null); MethodInfo methodInfo = AccessTools.Method("FurnitureOverhaul.CustomerCountFix:Evaluate", (Type[])null, (Type[])null); if (methodInfo != null) { harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null); } MethodInfo methodInfo2 = AccessTools.Method("DecoBonusOverlay.Overlay:DrawReadings", (Type[])null, (Type[])null); MethodInfo methodInfo3 = AccessTools.Method("DecoBonusOverlay.DecoReading:get_IsCapped", (Type[])null, (Type[])null); if (methodInfo2 != null && methodInfo3 != null) { harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(OverlayTranspilers), "CapLabel", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)methodInfo3, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(OverlayTranspilers), "CapCheck", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null); } } } internal static class BonusMath { public static float ApplyCap(float raw) { Perf.CountCapCall(); Perf.Mark start = Perf.Start(); raw += Finishes.Total(); raw += Themes.Extra(); raw += Guards.Prestige(); raw += Outside.Total(raw); Prestige.Capture(raw); Perf.Stop("the customer-limit recalculation", start); if (Plugin.DeferToWeeklyTraffic) { return 0f; } float value = Plugin.DecoBonusCap.Value; if (raw <= 0f) { return 0f; } if (!Plugin.SoftCapEnabled.Value) { return Mathf.Min(raw, value); } float num = Mathf.Min(Plugin.SoftCapStart.Value, value); if (raw <= num) { return raw; } float num2 = value - num; if (!(num2 <= 0f)) { return num + num2 * (1f - Mathf.Exp((0f - (raw - num)) / num2)); } return value; } public static float EffectiveCount(int count, float falloff) { if (count <= 0) { return 0f; } if (!(falloff >= 1f)) { return (1f - Mathf.Pow(falloff, (float)count)) / (1f - falloff); } return count; } public static float DecoCount(int count) { return EffectiveCount(count, Plugin.DuplicateFalloff.Value); } public static float FurnitureCount(int count) { return EffectiveCount(count, Plugin.FalloffAppliesToFurniture.Value ? Plugin.DuplicateFalloff.Value : 1f); } public static int GetBaseCustomerCap() { if (!Plugin.DeferToWeeklyTraffic) { return Plugin.BaseCustomerCap.Value; } return 30; } public static float GetDecoBonusCap() { return Plugin.DecoBonusCap.Value; } public static float GetCappedThreshold() { if (!Plugin.SoftCapEnabled.Value) { return Plugin.DecoBonusCap.Value; } return Plugin.DecoBonusCap.Value - 0.5f; } public static float ResetCardTotal(float runningTotal) { if (!Plugin.FixDisplayCaseSnowball.Value) { return runningTotal; } return 0f; } } internal static class OverlayTranspilers { public static IEnumerable<CodeInstruction> CapLabel(IEnumerable<CodeInstruction> instructions, MethodBase original) { return ReplaceTwenty(instructions, original, AccessTools.Method(typeof(BonusMath), "GetDecoBonusCap", (Type[])null, (Type[])null)); } public static IEnumerable<CodeInstruction> CapCheck(IEnumerable<CodeInstruction> instructions, MethodBase original) { return ReplaceTwenty(instructions, original, AccessTools.Method(typeof(BonusMath), "GetCappedThreshold", (Type[])null, (Type[])null)); } private static IEnumerable<CodeInstruction> ReplaceTwenty(IEnumerable<CodeInstruction> instructions, MethodBase original, MethodInfo getter) { List<CodeInstruction> list = new List<CodeInstruction>(instructions); int num = 0; foreach (CodeInstruction item in list) { if (item.opcode == OpCodes.Ldc_R4 && (float)item.operand == 20f) { item.opcode = OpCodes.Call; item.operand = getter; num++; } } string text = original.DeclaringType.FullName + "." + original.Name; if (num == 1) { Plugin.Log.LogInfo((object)("Pointed " + text + " at the configured cap.")); } else { Plugin.Log.LogWarning((object)(text + ": expected 1 cap constant, replaced " + num + ". The overlay may have changed.")); } return list; } } internal static class CustomerCapTranspiler { private static readonly HashSet<string> Reported = new HashSet<string>(); public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, MethodBase original) { //IL_041b: Unknown result type (might be due to invalid IL or missing references) //IL_0421: Expected O, but got Unknown //IL_042a: Unknown result type (might be due to invalid IL or missing references) //IL_0430: Expected O, but got Unknown MethodInfo methodInfo = AccessTools.Method(typeof(Mathf), "Clamp", new Type[3] { typeof(int), typeof(int), typeof(int) }, (Type[])null); MethodInfo methodInfo2 = AccessTools.Method(typeof(List<int>), "get_Item", (Type[])null, (Type[])null); MethodInfo methodInfo3 = AccessTools.Method(typeof(KeyValuePair<int, int>), "get_Value", (Type[])null, (Type[])null); MethodInfo[] array = new MethodInfo[2] { AccessTools.Method(typeof(BonusMath), "DecoCount", (Type[])null, (Type[])null), AccessTools.Method(typeof(BonusMath), "FurnitureCount", (Type[])null, (Type[])null) }; MethodInfo methodInfo4 = AccessTools.Method(typeof(BonusMath), "ResetCardTotal", (Type[])null, (Type[])null); List<CodeInstruction> list = new List<CodeInstruction>(instructions); int num = 0; int num2 = 0; int num3 = 0; int num4 = 0; for (int i = 0; i < list.Count; i++) { if (num == 0 && i > 0 && i + 3 < list.Count && IsLdcR4(list[i], 20f) && (list[i + 1].opcode == OpCodes.Ble_Un_S || list[i + 1].opcode == OpCodes.Ble_Un) && IsLdcR4(list[i + 2], 20f) && IsStloc(list[i + 3])) { list[i].opcode = OpCodes.Call; list[i].operand = AccessTools.Method(typeof(BonusMath), "ApplyCap", (Type[])null, (Type[])null); list[i + 1].opcode = list[i + 3].opcode; list[i + 1].operand = list[i + 3].operand; list[i + 2].opcode = OpCodes.Nop; list[i + 2].operand = null; list[i + 3].opcode = OpCodes.Nop; list[i + 3].operand = null; num++; i += 3; } else if (num2 == 0 && IsLdcI4(list[i], 30) && i + 1 < list.Count && CodeInstructionExtensions.Calls(list[i + 1], methodInfo)) { list[i].opcode = OpCodes.Call; list[i].operand = AccessTools.Method(typeof(BonusMath), "GetBaseCustomerCap", (Type[])null, (Type[])null); num2++; } else if (num3 < array.Length && i > 0 && i + 1 < list.Count && list[i].opcode == OpCodes.Conv_R4 && list[i + 1].opcode == OpCodes.Mul && (CodeInstructionExtensions.Calls(list[i - 1], methodInfo2) || CodeInstructionExtensions.Calls(list[i - 1], methodInfo3))) { list[i].opcode = OpCodes.Call; list[i].operand = array[num3]; num3++; } else { if (num4 != 0 || i + 2 >= list.Count || !IsLdloc(list[i]) || !IsLdcR4(list[i + 1], 50000f) || !(list[i + 2].opcode == OpCodes.Div)) { continue; } CodeInstruction val = list[i]; for (int j = i + 3; j < list.Count && j < i + 12; j++) { if (IsStloc(list[j])) { list.InsertRange(j + 1, (IEnumerable<CodeInstruction>)(object)new CodeInstruction[3] { new CodeInstruction(val.opcode, val.operand), new CodeInstruction(OpCodes.Call, (object)methodInfo4), StoreFor(val) }); num4++; break; } } } } string text = original.DeclaringType.FullName + "." + original.Name; if (!Reported.Add(text + num + num2 + num3 + num4)) { return list; } if (num == 1 && num2 == 1 && num3 == 2 && num4 == 1) { Plugin.Log.LogInfo((object)("Patched customer caps, Prestige capture and the display-case fix in " + text + ".")); } if (num != 1) { Plugin.Log.LogWarning((object)(text + ": decoration cap not found, so Prestige can't be read there. The code may have changed.")); } if (num2 != 1) { Plugin.Log.LogWarning((object)(text + ": base customer limit not found. The code may have changed.")); } if (num3 != 2) { Plugin.Log.LogWarning((object)(text + ": expected 2 per-type counts for duplicate falloff, found " + num3 + ". The code may have changed.")); } if (num4 != 1) { Plugin.Log.LogWarning((object)(text + ": display-case card total not found, so the display-case fix is off there. The code may have changed.")); } return list; } private static CodeInstruction StoreFor(CodeInstruction load) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Expected O, but got Unknown //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Expected O, but got Unknown //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Expected O, but got Unknown if (!(load.opcode == OpCodes.Ldloc_0)) { if (!(load.opcode == OpCodes.Ldloc_1)) { if (!(load.opcode == OpCodes.Ldloc_2)) { if (!(load.opcode == OpCodes.Ldloc_3)) { return new CodeInstruction((load.opcode == OpCodes.Ldloc_S) ? OpCodes.Stloc_S : OpCodes.Stloc, load.operand); } return new CodeInstruction(OpCodes.Stloc_3, (object)null); } return new CodeInstruction(OpCodes.Stloc_2, (object)null); } return new CodeInstruction(OpCodes.Stloc_1, (object)null); } return new CodeInstruction(OpCodes.Stloc_0, (object)null); } private static bool IsLdcR4(CodeInstruction c, float value) { if (c.opcode == OpCodes.Ldc_R4) { return (float)c.operand == value; } return false; } private static bool IsLdcI4(CodeInstruction c, int value) { if (c.opcode == OpCodes.Ldc_I4_S || c.opcode == OpCodes.Ldc_I4) { return Convert.ToInt32(c.operand) == value; } return false; } private static bool IsStloc(CodeInstruction c) { if (!(c.opcode == OpCodes.Stloc_S) && !(c.opcode == OpCodes.Stloc) && !(c.opcode == OpCodes.Stloc_0) && !(c.opcode == OpCodes.Stloc_1) && !(c.opcode == OpCodes.Stloc_2)) { return c.opcode == OpCodes.Stloc_3; } return true; } private static bool IsLdloc(CodeInstruction c) { if (!(c.opcode == OpCodes.Ldloc_S) && !(c.opcode == OpCodes.Ldloc) && !(c.opcode == OpCodes.Ldloc_0) && !(c.opcode == OpCodes.Ldloc_1) && !(c.opcode == OpCodes.Ldloc_2)) { return c.opcode == OpCodes.Ldloc_3; } return true; } } public sealed class DisplayFilterRule { public bool Enabled; public string Element = ""; public string Set = ""; public string Rarity = ""; public string Border = ""; public string Monster = ""; public int Foil; public int Graded; public double MinimumValue; public double MaximumValue; public bool NoDuplicates; private const char Sep = '|'; public bool IsDefault { get { if (!Enabled && Element.Length == 0 && Set.Length == 0 && Rarity.Length == 0 && Border.Length == 0 && Monster.Length == 0 && Foil == 0 && Graded == 0 && MinimumValue == 0.0 && MaximumValue == 0.0) { return !NoDuplicates; } return false; } } public string Reject(CardFilterFacts card, IEnumerable<string> existing) { if (!Enabled) { return ""; } if (Element.Length > 0 && Element != card.Element) { return "only " + Element + " cards"; } if (Set.Length > 0 && Set != card.Set) { return "only " + Set + " cards"; } if (Rarity.Length > 0 && Rarity != card.Rarity) { return "only " + Rarity + " cards"; } if (Border.Length > 0 && Border != card.Border) { return "only " + Border + " border cards"; } if (Monster.Length > 0 && Monster != card.Monster) { return "only " + ((card.MonsterWanted.Length > 0) ? card.MonsterWanted : "one monster") + " cards"; } if (Foil == 1 && !card.Foil) { return "only foil cards"; } if (Foil == 2 && card.Foil) { return "only non-foil cards"; } if (Graded == 1 && !card.Graded) { return "only graded cards"; } if (Graded == 2 && card.Graded) { return "only ungraded cards"; } if ((MinimumValue > 0.0 || MaximumValue > 0.0) && (double.IsNaN(card.Value) || double.IsInfinity(card.Value))) { return "this card's value isn't known"; } if (card.Value < MinimumValue) { return "only cards worth " + MinimumValue.ToString("N0", CultureInfo.InvariantCulture) + " or more"; } if (MaximumValue > 0.0 && card.Value > MaximumValue) { return "only cards worth up to " + MaximumValue.ToString("N0", CultureInfo.InvariantCulture); } if (NoDuplicates && existing.Any((string identity) => identity == card.Identity)) { return "that card is already in this case"; } return ""; } public void Clear() { Enabled = false; Element = (Set = (Rarity = (Border = (Monster = "")))); Foil = (Graded = 0); MinimumValue = (MaximumValue = 0.0); NoDuplicates = false; } public string Write() { return string.Join('|'.ToString(), "1", Enabled ? "1" : "0", Clean(Element), Clean(Set), Clean(Rarity), Clean(Border), Clean(Monster), Foil.ToString(CultureInfo.InvariantCulture), Graded.ToString(CultureInfo.InvariantCulture), MinimumValue.ToString("R", CultureInfo.InvariantCulture), MaximumValue.ToString("R", CultureInfo.InvariantCulture), NoDuplicates ? "1" : "0"); } public static DisplayFilterRule? Read(string? line) { string[] array = (line ?? "").Split('|'); if (array.Length != 12 || array[0] != "1") { return null; } if (!int.TryParse(array[7], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result) || result < 0 || result > 2) { return null; } if (!int.TryParse(array[8], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result2) || result2 < 0 || result2 > 2) { return null; } if (!double.TryParse(array[9], NumberStyles.Float, CultureInfo.InvariantCulture, out var result3) || !double.TryParse(array[10], NumberStyles.Float, CultureInfo.InvariantCulture, out var result4)) { return null; } if (result3 < 0.0 || result4 < 0.0 || double.IsNaN(result3) || double.IsNaN(result4) || double.IsInfinity(result3) || double.IsInfinity(result4) || (result4 > 0.0 && result4 < result3)) { return null; } return new DisplayFilterRule { Enabled = (array[1] == "1"), Element = array[2], Set = array[3], Rarity = array[4], Border = array[5], Monster = array[6], Foil = result, Graded = result2, MinimumValue = result3, MaximumValue = result4, NoDuplicates = (array[11] == "1") }; } private static string Clean(string s) { return (s ?? "").Replace('|'.ToString(), "").Replace("\n", "").Replace("\r", ""); } } public sealed class CardFilterFacts { public string Element = ""; public string Set = ""; public string Rarity = ""; public string Border = ""; public string Monster = ""; public string Identity = ""; public string MonsterWanted = ""; public bool Foil; public bool Graded; public double Value; } internal static class DisplayFilters { [Serializable] private sealed class SaveData { public string[] cases = Array.Empty<string>(); public string[] rules = Array.Empty<string>(); } private static readonly Dictionary<CardShelf, DisplayFilterRule> Live = new Dictionary<CardShelf, DisplayFilterRule>(); private static readonly Dictionary<string, DisplayFilterRule> Pending = new Dictionary<string, DisplayFilterRule>(); private static float _nextNotice; internal static bool Ready { get; private set; } internal static void Apply(Harmony harmony) { //IL_003e: 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_0057: Expected O, but got Unknown //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Expected O, but got Unknown //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Expected O, but got Unknown //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Expected O, but got Unknown MethodInfo methodInfo = AccessTools.Method(typeof(InteractableCardCompartment), "OnMouseButtonUp", (Type[])null, (Type[])null) ?? throw new MissingMethodException("InteractableCardCompartment.OnMouseButtonUp"); harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(AccessTools.Method(typeof(DisplayFilters), "BeforePlace", (Type[])null, (Type[])null)) { priority = 800 }, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(typeof(CardShelf), "OnStartMoveObject", (Type[])null, (Type[])null), new HarmonyMethod(AccessTools.Method(typeof(DisplayFilters), "BeforeMove", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(typeof(CardShelf), "BoxUpObject", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(DisplayFilters), "AfterBox", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(typeof(CardShelf), "OnDestroyed", (Type[])null, (Type[])null), new HarmonyMethod(AccessTools.Method(typeof(DisplayFilters), "Destroyed", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Ready = true; } private static string Key(CardShelf s) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) Vector3 position = ((Component)s).transform.position; return ((object)Unsafe.As<EObjectType, EObjectType>(ref ((InteractableObject)s).m_ObjectType)/*cast due to .constrained prefix*/).ToString() + "/" + position.x.ToString("F2", CultureInfo.InvariantCulture) + "/" + position.y.ToString("F2", CultureInfo.InvariantCulture) + "/" + position.z.ToString("F2", CultureInfo.InvariantCulture); } internal static DisplayFilterRule Get(CardShelf shelf) { if (Live.TryGetValue(shelf, out DisplayFilterRule value)) { return value; } string key = Key(shelf); if (Pending.TryGetValue(key, out value)) { Pending.Remove(key); } else { value = new DisplayFilterRule(); } Live[shelf] = value; return value; } private static void BeforeMove(CardShelf __instance) { if (__instance.m_ItemNotForSale) { Get(__instance); } } private static void AfterBox(CardShelf __instance) { if (((InteractableObject)__instance).GetIsBoxedUp()) { Live.Remove(__instance); } } private static void Destroyed(CardShelf __instance) { Live.Remove(__instance); } internal static IEnumerable<CardData> Cards(CardShelf shelf) { foreach (InteractableCardCompartment cardCompartment in shelf.GetCardCompartmentList()) { foreach (InteractableCard3d storedCard in cardCompartment.m_StoredCardList) { object obj; if (!((Object)(object)storedCard != (Object)null)) { obj = null; } else { Card3dUIGroup card3dUI = storedCard.m_Card3dUI; if (card3dUI == null) { obj = null; } else { CardUI cardUI = card3dUI.m_CardUI; obj = ((cardUI != null) ? cardUI.GetCardData() : null); } } CardData val = (CardData)obj; if (val != null) { yield return val; } } } } internal static CardFilterFacts Facts(CardData card, DisplayFilterRule rule) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: 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) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: 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_00c4: Unknown result type (might be due to invalid IL or missing references) CardFilterFacts cardFilterFacts = new CardFilterFacts(); EElementIndex? val = Themes.Element(card); cardFilterFacts.Element = (val.HasValue ? ((object)val.GetValueOrDefault()/*cast due to .constrained prefix*/).ToString() : null) ?? ""; cardFilterFacts.Set = ((object)Unsafe.As<ECardExpansionType, ECardExpansionType>(ref card.expansionType)/*cast due to .constrained prefix*/).ToString(); cardFilterFacts.Rarity = ((object)Themes.Rarity(card)/*cast due to .constrained prefix*/).ToString(); cardFilterFacts.Border = ((object)Themes.Border(card)/*cast due to .constrained prefix*/).ToString(); cardFilterFacts.Monster = ((object)Unsafe.As<EMonsterType, EMonsterType>(ref card.monsterType)/*cast due to .constrained prefix*/).ToString(); cardFilterFacts.MonsterWanted = ((rule.Monster.Length > 0 && Enum.TryParse<EMonsterType>(rule.Monster, out EMonsterType result)) ? Themes.MonsterName(result) : ""); cardFilterFacts.Identity = Themes.Identity(card); cardFilterFacts.Foil = card.isFoil; cardFilterFacts.Graded = card.cardGrade > 0; cardFilterFacts.Value = CPlayerData.GetCardMarketPrice(card); return cardFilterFacts; } private static bool BeforePlace(InteractableCardCompartment __instance) { try { CardShelf cardShelf = __instance.GetCardShelf(); if (!Ready || (Object)(object)cardShelf == (Object)null || !cardShelf.m_ItemNotForSale || __instance.m_StoredCardList.Count != 0) { return true; } if (!Live.TryGetValue(cardShelf, out DisplayFilterRule value) && !Pending.ContainsKey(Key(cardShelf))) { return true; } value = Get(cardShelf); if (!value.Enabled) { return true; } InteractableCard3d currentHoldCard = InteractionPlayerController.GetCurrentHoldCard(); if ((Object)(object)currentHoldCard == (Object)null || currentHoldCard.IsDisplayedOnShelf()) { return true; } Card3dUIGroup card3dUI = currentHoldCard.m_Card3dUI; object obj; if (card3dUI == null) { obj = null; } else { CardUI cardUI = card3dUI.m_CardUI; obj = ((cardUI != null) ? cardUI.GetCardData() : null); } CardData val = (CardData)obj; if (val == null) { return true; } string text = value.Reject(Facts(val, value), Cards(cardShelf).Select(Themes.Identity)); if (text.Length == 0) { return true; } Notice("This case takes " + text + "."); return false; } catch (Exception ex) { Plugin.Log.LogWarning((object)("Display filter couldn't check a card, so it was let through: " + ex.Message)); return true; } } internal static void Notice(string message) { if (!(Time.unscaledTime < _nextNotice)) { _nextNotice = Time.unscaledTime + 1f; Toast.Show("src_card_displays", message); } } private static string PathFor(int slot) { return Path.Combine(Application.persistentDataPath, "ShopPrestige", "DisplayFilters_" + slot + ".json"); } public static void Save(int slot) { try { List<string> list = new List<string>(); List<string> list2 = new List<string>(); ShelfManager val = Object.FindObjectOfType<ShelfManager>(); foreach (CardShelf item in ((Object)(object)val != (Object)null) ? val.m_CardShelfList : new List<CardShelf>()) { if (!((Object)(object)item == (Object)null) && item.m_ItemNotForSale && !((InteractableObject)item).GetIsBoxedUp() && !((InteractableObject)item).GetIsMovingObject()) { DisplayFilterRule displayFilterRule = Get(item); if (!displayFilterRule.IsDefault) { list.Add(Key(item)); list2.Add(displayFilterRule.Write()); } } } foreach (KeyValuePair<string, DisplayFilterRule> item2 in Pending) { if (!item2.Value.IsDefault && !list.Contains(item2.Key)) { list.Add(item2.Key); list2.Add(item2.Value.Write()); } } string path = PathFor(slot); if (list.Count != 0 || File.Exists(path)) { Directory.CreateDirectory(Path.GetDirectoryName(path)); File.WriteAllText(path, JsonUtility.ToJson((object)new SaveData { cases = list.ToArray(), rules = list2.ToArray() })); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("Couldn't save display filters: " + ex.Message)); } } public static void Load(int slot) { Reset(); try { string path = PathFor(slot); if (!File.Exists(path)) { return; } SaveData saveData = JsonUtility.FromJson<SaveData>(File.ReadAllText(path)); if (saveData?.cases == null || saveData.rules == null) { return; } int num = 0; for (int i = 0; i < saveData.cases.Length && i < saveData.rules.Length; i++) { DisplayFilterRule displayFilterRule = DisplayFilterRule.Read(saveData.rules[i]); if (displayFilterRule == null || string.IsNullOrEmpty(saveData.cases[i])) { num++; } else { Pending[saveData.cases[i]] = displayFilterRule; } } Plugin.Log.LogInfo((object)($"Display filters: {Pending.Count} case(s) with filters in save slot {slot}" + ((num > 0) ? $" ({num} damaged line(s) skipped)." : "."))); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Couldn't load display filters (cases keep no filters): " + ex.Message)); } } public static void Reset() { Live.Clear(); Pending.Clear(); } } internal static class Effects { private static readonly FieldRef<CustomerManager, float> MaxMoney = AccessTools.FieldRefAccess<CustomerManager, float>("m_CustomerMaxMoney"); private static readonly Dictionary<ConfigEntry<string>, (string Raw, float[] Values)> Parsed = new Dictionary<ConfigEntry<string>, (string, float[])>(); private static readonly HashSet<string> Reported = new HashSet<string>(); public static float VanillaWallet { get; private set; } = -1f; public static float Wallet { get; private set; } = -1f; private static float Score => Math.Max(0f, Prestige.Active); public static void Apply(Harmony harmony) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Expected O, but got Unknown //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Expected O, but got Unknown harmony.Patch((MethodBase)AccessTools.Method(typeof(CustomerManager), "EvaluateMaxCustomerCount", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(Effects), "WalletPostfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(typeof(CustomerManager), "GetCustomerMaxMoney", (Type[])null, (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(Effects), "RichOddsTranspiler", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(typeof(CustomerManager), "GetCustomerBuyItemChance", (Type[])null, (Type[])null), new HarmonyMethod(AccessTools.Method(typeof(Effects), "PriceTolerancePrefix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } public static float[] Values(ConfigEntry<string> entry) { string value = entry.Value; if (Parsed.TryGetValue(entry, out (string, float[]) value2) && (object)value2.Item1 == value) { return value2.Item2; } float[] array = ParseValues(entry, value); Parsed[entry] = (value, array); return array; } private static float[] ParseValues(ConfigEntry<string> entry, string raw) { float[] array = Parse(raw); if (array.Length != 4 || array.Any(float.IsNaN)) { array = Parse((string)((ConfigEntryBase)entry).DefaultValue); } return array; static float[] Parse(string s) { float result; return (from p in s.Split(',') select (!float.TryParse(p.Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out result)) ? float.NaN : result).ToArray(); } } public static float At(float[] values, float score) { float[] array = Prestige.Thresholds(); if (score <= array[0]) { return values[0]; } for (int i = 1; i < array.Length; i++) { if (score < array[i]) { float num = Math.Max(0.001f, array[i] - array[i - 1]); return Mathf.Lerp(values[i - 1], values[i], (score - array[i - 1]) / num); } } return values[array.Length - 1]; } public static float Step(float value) { float num = Math.Max(0.01f, Plugin.BonusStep.Value); return Mathf.Floor(value / num + 0.0001f) * num; } public static float WalletPercent(float score) { if (!Plugin.WalletEnabled.Value) { return 0f; } return Step(At(Values(Plugin.WalletBonus), score)); } public static float WalletLimit(float score) { return At(Values(Plugin.WalletLimit), score); } public static float RichPercent(float score) { if (!Plugin.RichOddsEnabled.Value) { return 4.7f; } return At(Values(Plugin.RichChance), score); } public static float VeryRichPercent(float score) { if (!Plugin.RichOddsEnabled.Value) { return 0.3f; } return At(Values(Plugin.VeryRichChance), score); } public static float TolerancePoints(float score) { if (!Plugin.PriceToleranceEnabled.Value) { return 0f; } return Step(At(Values(Plugin.PriceTolerance), score)); } private static void WalletPostfix(CustomerManager __instance) { try { float num = MaxMoney.Invoke(__instance); float num2 = Math.Max(num, Math.Min(num * (1f + WalletPercent(Score) / 100f), WalletLimit(Score))); MaxMoney.Invoke(__instance) = num2; if (Math.Abs(num2 - Wallet) > 0.5f) { Plugin.Log.LogInfo((object)$"Wallet ceiling {num:N0} -> {num2:N0} (Prestige {Score:0.0})."); } VanillaWallet = num; Wallet = num2; } catch (Exception ex) { Plugin.Log.LogWarning((object)("Wallet ceiling not changed: " + ex.Message)); } } public static void RefreshWallet() { if (!(VanillaWallet < 0f)) { CustomerManager val = Object.FindObjectOfType<CustomerManager>(); if (!((Object)(object)val == (Object)null) && !(Math.Abs(MaxMoney.Invoke(val) - Wallet) > 0.5f)) { MaxMoney.Invoke(val) = VanillaWallet; WalletPostfix(val); } } } public static int VeryRichPerMille() { return Mathf.Clamp(Mathf.RoundToInt(VeryRichPercent(Score) * 10f), 0, 1000); } public static int RichPerMille() { return Mathf.Clamp(VeryRichPerMille() + Mathf.RoundToInt(RichPercent(Score) * 10f), 0, 1000); } private static IEnumerable<CodeInstruction> RichOddsTranspiler(IEnumerable<CodeInstruction> instructions, MethodBase original) { List<CodeInstruction> list = new List<CodeInstruction>(instructions); int num = 0; int num2 = 0; for (int i = 0; i + 1 < list.Count; i++) { if (IsBranch(list[i + 1])) { if (num == 0 && IsLdcI4(list[i], 3)) { list[i].opcode = OpCodes.Call; list[i].operand = AccessTools.Method(typeof(Effects), "VeryRichPerMille", (Type[])null, (Type[])null); num++; } else if (num == 1 && num2 == 0 && IsLdcI4(list[i], 50)) { list[i].opcode = OpCodes.Call; list[i].operand = AccessTools.Method(typeof(Effects), "RichPerMille", (Type[])null, (Type[])null); num2++; } } } if (Reported.Add($"{num}{num2}")) { if (num == 1 && num2 == 1) { Plugin.Log.LogInfo((object)"Patched rich customer odds."); } else { Plugin.Log.LogWarning((object)"Rich customer odds not found in GetCustomerMaxMoney, so they stay the game's. The code may have changed."); } } return list; } private static void PriceTolerancePrefix(ref float currentPrice, float marketPrice) { if (!(marketPrice <= 0f)) { float num = TolerancePoints(Score) + Wealthy.ExtraTolerance() + Whales.ExtraTolerance(); if (num > 0f) { currentPrice -= marketPrice * num / 100f; } } } private static bool IsBranch(CodeInstruction c) { if (!(c.opcode == OpCodes.Bge) && !(c.opcode == OpCodes.Bge_S) && !(c.opcode == OpCodes.Blt) && !(c.opcode == OpCodes.Blt_S) && !(c.opcode == OpCodes.Bge_Un) && !(c.opcode == OpCodes.Bge_Un_S) && !(c.opcode == OpCodes.Blt_Un)) { return c.opcode == OpCodes.Blt_Un_S; } return true; } private static bool IsLdcI4(CodeInstruction c, int value) { if (value != 3 || !(c.opcode == OpCodes.Ldc_I4_3)) { if (c.opcode == OpCodes.Ldc_I4_S || c.opcode == OpCodes.Ldc_I4) { return Convert.ToInt32(c.operand) == value; } return false; } return true; } } internal enum Surface { Wall, Floor, Ceiling } internal sealed class Area { public string Name = ""; public Func<Surface, int> Equipped = (Surface _) => 0; public Action<Surface, int> Equip = delegate { }; } internal sealed class Finish { public Surface Surface; public int Index; public string Name = ""; public float Price; public int Tier; public float Prestige; public bool Owned; public Sprite? Icon; } internal static class Finishes { public static readonly string[] TierNames = new string[5] { "Basic", "Standard", "Quality", "Premium", "Luxury" }; private static readonly float[] Prices = new float[5] { 0f, 1000f, 2500f, 5000f, 10000f }; private static readonly float[] Base = new float[5] { 0f, 0.1f, 0.25f, 0.5f, 1f }; private const float TopTierMax = 1.5f; public static readonly string[] SurfaceNames = new string[3] { "Walls", "Floors", "Ceilings" }; private static readonly string[] SurfaceWords = new string[3] { "wall", "floor", "ceiling" }; private static Dictionary<(Surface, int), float>? _custom; private static bool _looked; private static FieldInfo? _shopCUnlocked; private static MethodInfo? _shopCEffective; private static MethodInfo? _shopCEquip; private static MethodInfo? _upEffective; private static MethodInfo? _upEquip; private static MethodInfo? _upOwned; private static float _total; private static float _totalUntil; public static int TierOfPrice(float price) { int result = 0; for (int i = 0; i < Prices.Length; i++) { if (price >= Prices[i] - 0.5f) { result = i; } } return result; } public static float BaseOf(int tier) { if (tier != 0) { return Base[tier]; } return Math.Min(0f, Plugin.CheapestFinishPrestige.Value); } public static (float Min, float Max) Range(int tier) { return (Min: (tier > 0) ? BaseOf(tier - 1) : BaseOf(0), Max: (tier < Base.Length - 1) ? BaseOf(tier + 1) : (BaseOf(Base.Length - 1) * 1.5f)); } public static float PrestigeOf(Surface surface, int index, float price) { int tier = TierOfPrice(price); float result = BaseOf(tier); if (Custom().TryGetValue((surface, index), out var value)) { (float Min, float Max) tuple = Range(tier); float item = tuple.Min; float item2 = tuple.Max; result = Mathf.Clamp(value, item, item2); } return result; } private static Dictionary<(Surface, int), float> Custom() { if (_custom != null) { return _custom; } _custom = new Dictionary<(Surface, int), float>(); try { string path = Path.Combine(Path.GetDirectoryName(((BaseUnityPlugin)Plugin.Instance).Info.Location) ?? "", "finish-prestige.txt"); if (!File.Exists(path)) { return _custom; } string[] array = File.ReadAllLines(path); for (int i = 0; i < array.Length; i++) { string text = array[i].Split('#')[0].Trim(); int num = text.IndexOf('='); if (num < 0) { continue; } string[] array2 = text.Substring(0, num).Trim().Split(new char[2] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries); if (array2.Length == 2 && int.TryParse(array2[1], out var result) && float.TryParse(text.Substring(num + 1).Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out var result2)) { int num2 = Array.IndexOf(SurfaceWords, array2[0].ToLowerInvariant()); if (num2 >= 0 && result >= 1) { _custom[((Surface)num2, result - 1)] = result2; } } } Plugin.Log.LogInfo((object)$"Read {_custom.Count} finish Prestige values from finish-prestige.txt."); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Couldn't read finish-prestige.txt: " + ex.Message)); } return _custom; } private static List<ShopDecoData> List(Surface surface) { ShelfData_ScriptableObject objectData_SO = CSingleton<InventoryBase>.Instance.m_ObjectData_SO; return surface switch { Surface.Wall => objectData_SO.m_WallDecoDataList, Surface.Floor => objectData_SO.m_FloorDecoDataList, _ => objectData_SO.m_CeilingDecoDataList, }; } public static bool IsOwned(Surface surface, int index) { if (index == 0) { return true; } try { return surface switch { Surface.Wall => CPlayerData.IsDecoWallUnlocked(index), Surface.Floor => CPlayerData.IsDecoFloorUnlocked(index), _ => CPlayerData.IsDecoCeilingUnlocked(index), }; } catch (Exception) { return false; } } public static Finish? Get(Surface surface, int index) { List<ShopDecoData> list = List(surface); if (index < 0 || index >= list.Count || list[index] == null) { return null; } ShopDecoData val = list[index]; string text; try { text = val.GetName(); } catch (Exception) { text = val.name; } if (string.IsNullOrWhiteSpace(text) || text.StartsWith("Missing", StringComparison.OrdinalIgnoreCase)) { text = $"{SurfaceWords[(int)surface]} {index + 1}"; } return new Finish { Surface = surface, Index = index, Name = text, Price = val.price, Tier = TierOfPrice(val.price), Prestige = PrestigeOf(surface, index, val.price), Owned = IsOwned(surface, index), Icon = val.icon }; } public static List<Finish> All(Surface surface) { List<Finish> list = new List<Finish>(); int count = List(surface).Count; for (int i = 0; i < count; i++) { Finish finish = Get(surface, i); if (finish != null) { list.Add(finish); } } return (from f in list orderby f.Prestige descending, f.Price descending, f.Name select f).ToList(); } private static void Look() { if (!_looked) { _looked = true; _shopCUnlocked = AccessTools.Field(AccessTools.TypeByName("ShopLotC.ShopCState"), "Unlocked"); _shopCEffective = AccessTools.Method("ShopLotC.ShopCMaterials:EffectiveIndexForCategory", (Type[])null, (Type[])null); _shopCEquip = AccessTools.Method("ShopLotC.ShopCMaterials:EquipForCategory", (Type[])null, (Type[])null); _upOwned = AccessTools.PropertyGetter(AccessTools.TypeByName("Upstairs.UpState"), "AnyOwned"); _upEffective = AccessTools.Method("Upstairs.UpMaterials:EffectiveIndexForCategory", (Type[])null, (Type[])null); _upEquip = AccessTools.Method("Upstairs.UpMaterials:EquipForCategory", (Type[])null, (Type[])null); } } public static List<Area> Areas() { Look(); List<Area> list = new List<Area> { new Area { Name = "Shop A", Equipped = (Surface s) => s switch { Surface.Wall => CPlayerData.m_EquippedWallDecoIndex, Surface.Floor => CPlayerData.m_EquippedFloorDecoIndex, _ => CPlayerData.m_EquippedCeilingDecoIndex, }, Equip = delegate(Surface s, int i) { EquipVanilla(s, i, lotB: false); } } }; if (CPlayerData.m_IsWarehouseRoomUnlocked) { list.Add(new Area { Name = "Shop B", Equipped = (Surface s) => s switch { Surface.Wall => CPlayerData.m_EquippedWallDecoIndexB, Surface.Floor => CPlayerData.m_EquippedFloorDecoIndexB, _ => CPlayerData.m_EquippedCeilingDecoIndexB, }, Equip = delegate(Surface s, int i) { EquipVanilla(s, i, lotB: true); } }); } try { object obj = _shopCUnlocked?.GetValue(null); if (obj is bool && (bool)obj && _shopCEffective != null && _shopCEquip != null) { list.Add(new Area { Name = "Shop C", Equipped = (Surface s) => (int)_shopCEffective.Invoke(null, new object[1] { (int)s }), Equip = delegate(Surface s, int i) { _shopCEquip.Invoke(null, new object[2] { (int)s, i }); } }); } obj = _upOwned?.Invoke(null, null); if (obj is bool && (bool)obj && _upEffective != null && _upEquip != null) { list.Add(new Area { Name = "Upstairs", Equipped = (Surface s) => (int)_upEffective.Invoke(null, new object[1] { (int)s }), Equip = delegate(Surface s, int i) { _upEquip.Invoke(null, new object[2] { (int)s, i }); } }); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("Couldn't read Shop C or Upstairs finishes: " + (ex.InnerException ?? ex).Message)); } return list; } private static void EquipVanilla(Surface surface, int index, bool lotB) { switch (surface) { case Surface.Wall: ShopCustomizationManager.ChangeWallMaterial(index, lotB); if (lotB) { CPlayerData.m_EquippedWallDecoIndexB = index; } else { CPlayerData.m_EquippedWallDecoIndex = index; } break; case Surface.Floor: ShopCustomizationManager.ChangeFloorMaterial(index, lotB); if (lotB) { CPlayerData.m_EquippedFloorDecoIndexB = index; } else { CPlayerData.m_EquippedFloorDecoIndex = index; } break; default: ShopCustomizationManager.ChangeCeilingMaterial(index, lotB); if (lotB) { CPlayerData.m_EquippedCeilingDecoIndexB = index; } else { CPlayerData.m_EquippedCeilingDecoIndex = index; } break; } } public static float Total(List<Source>? sources = null) { if (sources == null && Time.unscaledTime < _totalUntil) { return _total; } float num = 0f; try { if ((Object)(object)CSingleton<InventoryBase>.Instance == (Object)null) { return 0f; } foreach (Area item in Areas()) { float num2 = 0f; List<string> list = new List<string>(); foreach (Surface value in Enum.GetValues(typeof(Surface))) { Finish finish = Get(value, item.Equipped(value)); if (finish != null) { num2 += finish.Prestige; list.Add(finish.Name); } } num += num2; sources?.Add(new Source { Name = item.Name + ": " + string.Join(", ", list), Kind = "Finishes", Count = 3, Points = num2 }); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("Couldn't count finishes: " + ex.Message)); } _total = num; _totalUntil = Time.unscaledTime + 1f; return num; } public static void Invalidate() { _totalUntil = 0f; } public static string? Buy(Finish f) { //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Expected O, but got Unknown if (f.Owned) { return "You already own it."; } if (CPlayerData.m_CoinAmountDouble < (double)f.Price) { return "Not enough money."; } CPlayerData.m_GameReportDataCollect.upgradeCost -= f.Price; CPlayerData.m_GameReportDataCollectPermanent.upgradeCost -= f.Price; PriceChangeManager.AddTransaction(0f - f.Price, (ETransactionType)10, (int)f.Surface, f.Index, (CardData)null); CEventManager.QueueEvent((CEvent)new CEventPlayer_ReduceCoin(f.Price, false)); switch (f.Surface) { case Surface.Wall: CPlayerData.SetUnlockDecoWall(f.Index, true); break; case Surface.Floor: CPlayerData.SetUnlockDecoFloor(f.Index, true); break; default: CPlayerData.SetUnlockDecoCeiling(f.Index, true); break; } try { SoundManager.PlayAudio("SFX_CustomerBuy", 0.6f, 1f); } catch (Exception) { } Plugin.Log.LogInfo((object)$"Bought {SurfaceWords[(int)f.Surface]} \"{f.Name}\" for {f.Price:N0}."); return null; } public static string? Equip(Area area, Finish f) { if (!f.Owned) { return "Buy it first."; } try { area.Equip(f.Surface, f.Index); } catch (Exception ex) { return "Couldn't equip it: " + (ex.InnerException ?? ex).Message; } Recount(); Plugin.Log.LogInfo((object)("Equipped " + SurfaceWords[(int)f.Surface] + " \"" + f.Name + "\" in " + area.Name + ".")); return null; } public static void Recount() { try { Prestige.Invalidate(); if (Plugin.DeferToWeeklyTraffic) { if (Prestige.GameReady()) { Breakdown breakdown = Prestige.Calculate(); if (breakdown != null) { Prestige.Capture(breakdown.Total); Effects.RefreshWallet(); } } } else { CustomerManager val = Object.FindObjectOfType<CustomerManager>(); if ((Object)(object)val != (Object)null) { AccessTools.Method(typeof(CustomerManager), "EvaluateMaxCustomerCount", (Type[])null, (Type[])null)?.Invoke(val, null); } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("Couldn't recalculate the customer limit: " + (ex.InnerException ?? ex).Message)); } } } internal sealed class GuardBody : MonoBehaviour { private static bool _apparelLogged; private Animator? _anim; private Seeker? _seeker; private Path? _path; private int _waypoint; private float _nextRepath; private float _returnStarted; private Vector3 _postPosition; private Vector3 _lastPosition; private Quaternion _postRotation; private Quaternion _facing; private Customer? _target; private bool _returning; public bool IsHome { get { if ((Object)(object)_target == (Object)null) { return !_returning; } return false; } } public static GuardBody? Create(Transform parent, int index) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Expected O, but got Unknown CustomerManager instance = CSingleton<CustomerManager>.Instance; Customer val = (((Object)(object)instance != (Object)null) ? instance.m_CustomerPrefab : null); if ((Object)(object)val == (Object)null) { return null; } GameObject val2 = new GameObject("ShopPrestigeGuardHolder"); val2.SetActive(false); try { GameObject val3 = Object.Instantiate<GameObject>(((Component)val).gameObject, val2.transform); ((Object)val3).name = "ShopPrestigeGuard" + (index + 1); Customer component = val3.GetComponent<Customer>(); CharacterCustomization characterCustom = component.m_CharacterCustom; Animator anim = component.m_Anim; Seeker seeker = component.m_Seeker; if ((Object)(object)component.m_InteractCollider != (Object)null) { component.m_InteractCollider.SetActive(false); } Object.DestroyImmediate((Object)(object)component); List<string> list = new List<string>(); MonoBehaviour[] componentsInChildren = val3.GetComponentsInChildren<MonoBehaviour>(true); foreach (MonoBehaviour val4 in componentsInChildren) { string text = ((object)val4).GetType().Namespace ?? ""; if (!(val4 is CharacterCustomization) && !(text == "CC") && !text.StartsWith("Pathfinding") && !(val4 is Seeker)) { ((Behaviour)val4).enabled = false; list.Add(((object)val4).GetType().Name); } } Rigidbody[] componentsInChildren2 = val3.GetComponentsInChildren<Rigidbody>(true); for (int i = 0; i < componentsInChildren2.Length; i++) { componentsInChildren2[i].isKinematic = true; } Collider[] componentsInChildren3 = val3.GetComponentsInChildren<Collider>(true); for (int i = 0; i < componentsInChildren3.Length; i++) { componentsInChildren3[i].enabled = false; } if (list.Count > 0 && index == 0) { Plugin.Log.LogInfo((object)("Guard character: switched off " + string.Join(", ", list.Distinct()))); } GuardBody guardBody = val3.AddComponent<GuardBody>(); guardBody._anim = anim; if ((Object)(object)anim != (Object)null) { anim.applyRootMotion = false; } guardBody._seeker = seeker; val3.transform.SetParent(parent, false); val3.SetActive(true); if ((Object)(object)characterCustom != (Object)null) { Dress(characterCustom, index); } return guardBody; } catch (Exception ex) { Plugin.Log.LogWarning((object)("Couldn't make a guard character: " + ex)); return null; } finally { Object.Destroy((Object)(object)val2); } } private static void Dress(CharacterCustomization custom, int index) { //IL_01c9: 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_02ad: Unknown result type (might be due to invalid IL or missing references) List<string> list = (((Object)(object)custom.Presets != (Object)null) ? (from p in custom.Presets.Presets select p.CharacterName into n where n?.StartsWith("Male") ?? false select n).ToList() : new List<string>()); custom.CharacterName = ((list.Count > 0) ? list[(index * 5 + 2) % list.Count] : "ShopPrestigeGuard"); custom.Initialize(); if (!_apparelLogged) { _apparelLogged = true; for (int num = 0; num < custom.ApparelTables.Count; num++) { List<Apparel> list2 = custom.ApparelTables[num]?.Items; if (list2 != null) { Plugin.Log.LogInfo((object)($"Outfit slot {num}: " + string.Join(", ", list2.Select((Apparel i) => i.Name)))); } } } CC_CharacterData data = custom.StoredCharacterData; int slot; for (slot = 0; slot < custom.ApparelTables.Count; slot++) { List<Apparel> list3 = custom.ApparelTables[slot]?.Items; if (list3 != null && data != null && slot < data.ApparelNames.Count) { int num2 = list3.FindIndex((Apparel i) => i.Name == data.ApparelNames[slot]); if (num2 >= 0) { custom.setApparel(num2, slot, Darkest(list3[num2])); } } } for (int num3 = 0; num3 < custom.ApparelTables.Count; num3++) { List<Apparel> list4 = custom.ApparelTables[num3]?.Items; if (list4 == null) { continue; } int num4 = list4.FindIndex((Apparel i) => i.Name != null && i.Name.IndexOf("BlackSunglasses", StringComparison.OrdinalIgnoreCase) >= 0); if (num4 < 0) { num4 = list4.FindIndex((Apparel i) => i.Name != null && i.Name.IndexOf("Sunglasses", StringComparison.OrdinalIgnoreCase) >= 0); } if (num4 >= 0) { custom.setApparel(num4, num3, Darkest(list4[num4])); if (index == 0) { Plugin.Log.LogInfo((object)$"Guards wear \"{list4[num4].Name}\" (outfit slot {num3})."); } return; } } if (index == 0) { Plugin.Log.LogWarning((object)"No sunglasses found in the game's outfit tables; guards go without."); } } private static int Darkest(Apparel item) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0008: 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_0024: Unknown result type (might be due to invalid IL or missing references) if (item.Materials == null || item.Materials.Count <= 1) { return 0; } int result = 0; float num = float.MaxValue; for (int i = 0; i < item.Materials.Count; i++) { List<CC_Apparel_Material_Definition> materialDefinitions = item.Materials[i].MaterialDefinitions; if (materialDefinitions != null && materialDefinitions.Count != 0) { float num2 = materialDefinitions.Average((CC_Apparel_Material_Definition d) => Light(d.MainTint) + Light(d.TintR) + Light(d.TintG) + Light(d.TintB)); if (num2 < num) { num = num2; result = i; } } } return result; } private static float Light(Color c) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) return 0.2126f * c.r + 0.7152f * c.g + 0.0722f * c.b; } public void Teleport((Vector3 Position, Quaternion Rotation) post) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000e: 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_001f: 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_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: 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_0042: Unknown result type (might be due to invalid IL or missing references) (_postPosition, _postRotation) = post; ((Component)this).transform.SetPositionAndRotation(post.Position, post.Rotation); _facing = post.Rotation; _lastPosition = post.Position; _path = null; _returning = false; } public void SetPost((Vector3 Position, Quaternion Rotation) post) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: 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_0011: 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_0027: 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_0033: Unknown result type (might be due to invalid IL or missing references) Vector3 val = post.Position - _postPosition; bool num = ((Vector3)(ref val)).sqrMagnitude > 0.0001f; (_postPosition, _postRotation) = post; if (num && IsHome) { Teleport(post); } } public void Follow(Customer? customer) { if (!((Object)(object)customer == (Object)(object)_target)) { if ((Object)(object)customer == (Object)null && (Object)(object)_target != (Object)null) { _returning = true; _returnStarted = Time.time; _nextRepath = 0f; } _target = customer; if ((Object)(object)customer != (Object)null) { _returning = false; _nextRepath = 0f; } } } private void Update() { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0059: 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_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0067: 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: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0302: Unknown result type (might be due to invalid IL or missing references) //IL_030d: Unknown result type (might be due to invalid IL or missing references) //IL_0312: Unknown result type (might be due to invalid IL or missing references) //IL_0317: Unknown result type (might be due to invalid IL or missing references) //IL_0367: Unknown result type (might be due to invalid IL or missing references) //IL_036d: Unknown result type (might be due to invalid IL or missing references) //IL_0383: Unknown result type (might be due to invalid IL or missing references) //IL_0393: Unknown result type (might be due to invalid IL or missing references) //IL_0399: Unknown result type (might be due to invalid IL or missing references) //IL_039e: Unknown result type (might be due to invalid IL or missing references) //IL_03a3: Unknown result type (might be due to invalid IL or missing references) //IL_03b6: Unknown result type (might be due to invalid IL or missing references) //IL_03bb: 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_0356: Unknown result type (might be due to invalid IL or missing references) //IL_0334: Unknown result type (might be due to invalid IL or missing references) //IL_0336: Unknown result type (might be due to invalid IL or missing references) //IL_033b: Unknown result type (might be due to invalid IL or missing references) //IL_0340: 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_018d: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Expected O, but got Unknown //IL_0239: Unknown result type (might be due to invalid IL or missing references) //IL_023e: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Unknown result type (might be due to invalid IL or missing references) //IL_0217: 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_028c: Unknown result type (might be due to invalid IL or missing references) //IL_029a: Unknown result type (might be due to invalid IL or missing references) //IL_02a4: Unknown result type (might be due to invalid IL or missing references) //IL_02ac: Unknown result type (might be due to invalid IL or missing references) //IL_02b1: 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_0260: Unknown result type (might be due to invalid IL or missing references) //IL_0265: Unknown result type (might be due to invalid IL or missing references) //IL_02d6: 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_02dd: Unknown result type (might be due to invalid IL or missing references) //IL_02e2: Unknown result type (might be due to invalid IL or missing references) float num = Math.Max(Time.deltaTime, 0.0001f); Vector3? val = null; float num2 = 0.15f; Vector3 val2; if ((Object)(object)_target != (Object)null) { Vector3 value = ((Component)_target).transform.position - ((Component)_target).transform.forward * Plugin.GuardFollowDistance.Value; val = value; num2 = 0.35f; val2 = ((Component)_target).transform.position - ((Component)this).transform.position; if (((Vector3)(ref val2)).sqrMagnitude <= Plugin.GuardFollowDistance.Value * Plugin.GuardFollowDistance.Value * 1.1f) { val = null; _path = null; } } else if (_returning) { val = _postPosition; val2 = ((Component)this).transform.position - _postPosition; if (((Vector3)(ref val2)).sqrMagnitude < 0.05f || Time.time - _returnStarted > 25f) { Teleport((Position: _postPosition, Rotation: _postRotation)); val = null; } } if (val.HasValue && (Object)(object)_seeker != (Object)null && Time.time >= _nextRepath && _seeker.IsDone()) { _nextRepath = Time.time + 0.8f; _seeker.StartPath(((Component)this).transform.position, val.Value, new OnPathDelegate(OnPathComplete)); } if (val.HasValue && _path != null && _path.vectorPath.Count > 0) { while (_waypoint < _path.vectorPath.Count - 1 && Vector3.Distance(((Component)this).transform.position, _path.vectorPath[_waypoint]) < 0.1f) { _waypoint++; } Vector3 val3 = _path.vectorPath[_waypoint]; if (_waypoint == _path.vectorPath.Count - 1 && Vector3.Distance(((Component)this).transform.position, val3) < num2) { _path = null; } else { ((Component)this).transform.position = Vector3.MoveTowards(((Component)this).transform.position, val3, Plugin.GuardWalkSpeed.Value * num); Vector3 val4 = val3 - ((Component)this).transform.position; val4.y = 0f; if (((Vector3)(ref val4)).sqrMagnitude > 0.0001f) { _facing = Quaternion.LookRotation(val4, Vector3.up); } } } else if ((Object)(object)_target != (Object)null) { Vector3 val5 = ((Component)_target).transform.position - ((Component)this).transform.position; val5.y = 0f; if (((Vector3)(ref val5)).sqrMagnitude > 0.0001f) { _facing = Quaternion.LookRotation(val5, Vector3.up); } } else if (!_returning) { _facing = _postRotation; } ((Component)this).transform.rotation = Quaternion.Slerp(((Component)this).transform.rotation, _facing, Math.Min(1f, num * 6f)); val2 = ((Component)this).transform.position - _lastPosition; float num3 = ((Vector3)(ref val2)).magnitude / num; _lastPosition = ((Component)this).transform.position; if ((Object)(object)_anim != (Object)null) { _anim.SetFloat("MoveSpeed", num3); } } private void OnPathComplete(Path p) { p.Claim((object)this); if (!p.error) { Path? path = _path; if (path != null) { path.Release((object)this, false); } _path = p; _waypoint = 0; } else { p.Release((object)this, false); } } private void OnDestroy() { Path? path = _path; if (path != null) { path.Release((object)this, false); } _path = null; } } internal static class Guards { [Serializable] private sealed class SaveData { public int guards; } private static readonly FieldRef<Customer, bool> InsideShop = AccessTools.FieldRefAccess<Customer, bool>("m_IsInsideShop"); private static readonly FieldRef<CustomerManager, float> MaxMoney = AccessTools.FieldRefAccess<CustomerManager, float>("m_CustomerMaxMoney"); private static readonly List<GuardBody> Bodies = new List<GuardBody>(); private static GameObject? _parent; private static float _nextLook; private static bool _bodiesFailed; private static bool _ready; private static float _nextReadyCheck; private static float _nextPosts; public static int Count { get; private set; } public static Customer? Following { get; private set; } public static int Max => Mathf.Clamp(Plugin.MaxGuards.Value, 0, 2); public static bool Unlocked => CPlayerData.m_ShopLevel + 1 >= Plugin.GuardUnlockLevel.Value; public static float Wages { get { if (!Plugin.GuardsEnabled.Value) { return 0f; } return (float)Count * Plugin.GuardWage.Value; } } public static int OnDutyBodies => Bodies.Count((GuardBody b) => (Object)(object)b != (Object)null); public static void Apply(Harmony harmony) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Expected O, but got Unknown //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Expected O, but got Unknown //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Expected O, but got Unknown //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Expected O, but got Unknown HarmonyMethod val = new HarmonyMethod(AccessTools.Method(typeof(Guards), "SalaryPostfix", (Type[])null, (Type[])null)); val.after = new string[1] { "com.qolmods.staffoverhaul" }; HarmonyMethod val2 = val; harmony.Patch((MethodBase)AccessTools.Method(typeof(WorkerManager), "GetTotalSalaryCost", (Type[])null, (Type[])null), (HarmonyMethod)null, val2, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(typeof(CGameData), "SaveGameData", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(Guards), "AfterSave", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(typeof(CSaveLoad), "Load", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(Guards), "AfterLoad", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(typeof(CSaveLoad), "LoadBackup", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(Guards), "AfterLoad", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); harmony.Patch((MethodBase)AccessTools.Method(typeof(CPlayerData), "CreateDefaultData", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(Guards), "AfterNewGame", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } public static float Prestige() { return PrestigeFor(Count); } public static float PrestigeFor(int count) { if (!Plugin.GuardsEnabled.Value) { return 0f; } float num = 0f; for (int i = 0; i < count; i++) { num += Plugin.GuardPrestige.Value * Mathf.Pow(Plugin.DuplicateFalloff.Value, (float)i); } return num; } private static void SalaryPostfix(WorkerManager __instance, ref float __result) { float wages = Wages; if (wages > 0f) { __result += wages; __instance.m_TotalSalaryCost = __result; } } public static string Hire() { //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Expected O, but got Unknown if (!Plugin.GuardsEnabled.Value) { return "Guards are off in the settings."; } if (!Unlocked) { return $"Guards unlock at shop level {Plugin.GuardUnlockLevel.Value}."; } if (Count >= Max) { return "You already have every guard you can hire."; } if (LightManager.GetHasDayEnded()) { return "The day has ended. Hire guards once the next day starts."; } int value = Plugin.GuardHireCost.Value; if (CPlayerData.m_CoinAmountDouble < (double)value) { return "Not enough money."; } PriceChangeManager.AddTransaction(0f - (float)value, (ETransactionType)8, 0, 0, (CardData)null); CEventManager.QueueEvent((CEvent)new CEventPlayer_ReduceCoin((float)value, false)); CPlayerData.m_GameReportDataCollect.employeeCost -= value; CPlayerData.m_GameReportDataCollectPermanent.employeeCost -= value; Count++; try { SoundManager.PlayAudio("SFX_CustomerBuy", 0.6f, 1f); } catch (Exception) { } Finishes.Recount(); Plugin.Log.LogInfo((object)$"Hired guard {Count} for {value:N0}."); return $"Hired guard {Count}. He takes his post at the door."; } public static string Dismiss() { if (Count <= 0) { return "No guards to dismiss."; } Count--; Finishes.Recount(); Plugin.Log.LogInfo((object)$"Dismissed a guard ({Count} left)."); return "Guard dismissed. No refund."; } private static string PathFor(int slot) { return Path.Combine(Application.persistentDataPath, "ShopPrestige", "Guards_" + slot + ".json"); } private static void AfterSave(int saveSlotIndex) { try { Directory.CreateDirectory(Path.GetDirectoryName(PathFor(saveSlotIndex))); File.WriteAllText(PathFor(saveSlotIndex), JsonUtility.ToJson((object)new SaveData { guards = Count })); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Couldn't save guards: " + ex.Message)); } Outside.Save(saveSlotIndex); DisplayFilters.Save(saveSlotIndex); } private static void AfterLoad(int slotIndex, bool __result) { if (!__result) { return; } ShopPrestige.Prestige.Invalidate(); Perf.QuietWhileLoading(); Art.Preload(); Count = 0; Outside.Load(slotIndex); DisplayFilters.Load(slotIndex); try { string path = PathFor(slotIndex); if (File.Exists(path)) { Count = Mathf.Clamp(JsonUtility.FromJson<SaveData>(File.ReadAllText(path))?.guards ?? 0, 0, 2); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("Couldn't load guards: " + ex.Message)); } if (Count > 0) { Plugin.Log.LogInfo((object)$"{Count} guard(s) on the payroll in save slot {slotIndex}."); } } private static void AfterNewGame() { Count = 0; Outside.Reset(); DisplayFilters.Reset(); ShopPrestige.Prestige.Invalidate(); Perf.QuietWhileLoading(); Art.Preload(); } public static void Update() { try { int num = ((Plugin.GuardsEnabled.Value && Count > 0 && Prestige_GameReady() && !LightManager.GetHasDayEnded()) ? Math.Min(Count, Max) : 0); Bodies.RemoveAll((GuardBody b) => (Object)(object)b == (Object)null); while (Bodies.Count > num) { GuardBody guardBody = Bodies[Bodies.Count - 1]; Bodies.RemoveAt(Bodies.Count - 1); Object.Destroy((Object)(object)((Component)guardBody).gameObject); } if (num == 0) { Following = null; return; } CustomerManager instance = CSingleton<CustomerManager>.Instance; if ((Object)(object)instance == (Object)null || (Object)(object)instance.m_ShopEntranceLocationPoint == (Object)null) { return; } while (Bodies.Count < num && !_bodiesFailed) { GuardBody guardBody2 = GuardBody.Create(Parent(), Bodies.Count); if ((Object)(object)guardBody2 == (Object)null) { _bodiesFailed = true; Plugin.Log.LogWarning((object)"Guards can't be shown (no character could be made). They still add Prestige and are paid."); break; } Bodies.Add(guardBody2); guardBody2.Teleport(Post(instance, Bodies.Count - 1)); } if (Time.unscaledTime >= _nextPosts) { _nextPosts = Time.unscaledTime + 2f; for (int num2 = 0; num2 < Bodies.Count; num2++) { Bodies[num2].SetPost(Post(instance, num2)); } } PickTarget(instance); } catch (Exception ex) { Plugin.Log.LogWarning((object)("Guards update failed: " + ex)); _bodiesFailed = true; } } private static bool Prestige_GameReady() { if (Time.unscaledTime >= _nextReadyCheck) { _nextReadyCheck = Time.unscaledTime + 1f; _ready = ShopPrestige.Prestige.GameReady(); } return _ready; } private static Transform Parent() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown if ((Object)(object)_parent == (Object)null) { _parent = new GameObject("ShopPrestigeGuards"); } return _parent.transform; } public static (Vector3 Position, Quaternion Rotation) Post(CustomerManager manager, int index) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0107: 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_012a: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) Vector3 door = manager.m_ShopEntranceLocationPoint.position; List<Vector3> list = (from t in manager.m_ShopLocationPointList ?? new List<Transform>() where (Object)(object)t != (Object)null && Math.Abs(t.position.y - door.y) < 1.5f select t.position).OrderBy(delegate(Vector3 p) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: 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) Vector3 val4 = p - door; return ((Vector3)(ref val4)).sqrMagnitude; }).Take(4).ToList(); Vector3 val = list.Aggregate(Vector3.zero, (Vector3 sum, Vector3 p) => sum + p); int count = list.Count; Vector3 val2 = ((count > 0) ? (door - val / (float)count) : manager.m_ShopEntranceLocationPoint.forward); val2.y = 0f; val2 = ((Math.Abs(val2.x) >= Math.Abs(val2.z)) ? new Vector3((float)Math.Sign(val2.x), 0f, 0f) : new Vector3(0f, 0f, (float)Math.Sign(val2.z))); if (val2 == Vector3.zero) { val2 = Vector3.forward; } Vector3 val3 = Vector3.Cross(Vector3.up, val2) * ((index == 0) ? (-1f) : 1f); return (Position: door - val2 * Plugin.GuardInsideOffset.Value + val3 * Plugin.GuardSideOffset.Value, Rotation: Quaternion.LookRotation(val2, Vector3.up)); } private static void PickTarget(CustomerManager manager) { GuardBody follower = ((Bodies.Count >= 2) ? Bodies[1] : Bodies[0]); if ((Object)(object)Following != (Object)null && !StillShopping(Following)) { Following = null; } if ((Object)(object)Following == (Object)null && follower.IsHome && Time.time >= _nextLook) { _nextLook = Time.time + 1f; Following = (from c in Candidates(manager) orderby c.m_MaxMoney descending select c).FirstOrDefault(); if ((Object)(object)Following != (Object)null) { Plugin.Log.LogInfo((object)$"A guard is following a wealthy customer with {Following.m_MaxMoney:N0} to spend."); } } follower.Follow(Following); foreach (GuardBody item in Bodies.Where((GuardBody b) => (Object)(object)b != (Object)(object)follower)) { item.Follow(null); } } private static IEnumerable<Customer> Candidates(CustomerManager manager) { return Wealthy.InShop(); } private static bool StillShopping(Customer c) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Invalid comparison between Unknown and I4 if ((Object)(object)c != (Object)null && c.m_IsActive && ((Component)c).gameObject.activeInHierarchy && InsideShop.Invoke(c)) { return (int)c.m_CurrentState != 7; } return false; } } internal static class HudLine { private const float Gap = 2f; private static GameUIScreen? _screen; private static TextMeshProUGUI? _text; private static float _next; private static float _nextLive; private static float _live = -1f; private static bool _failed; public static void Update() { if (_failed || Time.unscaledTime < _next) { return; } _next = Time.unscaledTime + 0.5f; try { if (!Plugin.HudLineEnabled.Value) { if ((Object)(object)_text != (Object)null) { ((Component)_text).gameObject.SetActive(false); } } else { if (!Prestige.GameReady()) { return; } if ((Object)(object)_screen == (Object)null) { _text = null; _screen = Object.FindObjectOfType<GameUIScreen>(); if ((Object)(object)_screen == (Object)null || (Object)(object)_screen.m_ShopLevelText == (Object)null || (Object)(object)_screen.m_ShopExpBar == (Object)null) { return; } } if ((Object)(object)_text == (Object)null) { _text = Make(_screen.m_ShopLevelText, ((Graphic)_screen.m_ShopExpBar).rectTransform); } Place(((TMP_Text)_text).rectTransform, ((Graphic)_screen.m_ShopExpBar).rectTransform); ((Component)_text).gameObject.SetActive(true); ((TMP_Text)_text).text = Line(); } } catch (Exception ex) { _failed = true; Plugin.Log.LogWarning((object)("The Prestige line under the shop level is turned off: " + ex.Message)); } } private static string Line() { float num = Prestige.Active; if (num < 0f) { if (Time.unscaledTime >= _nextLive) { _nextLive = Time.unscaledTime + 5f; _live = Prestige.Calculate()?.Total ?? 0f; } num = _live; } return $"Prestige {num:0.0} · {Prestige.TierName(num)}"; } private static TextMeshProUGUI Make(TextMeshProUGUI levelText, RectTransform bar) { GameObject val = Object.Instantiate<GameObject>(((Component)levelText).gameObject, ((TMP_Text)levelText).transform.parent, false); ((Object)val).name = "ShopPrestigeLine"; for (int num = val.transform.childCount - 1; num >= 0; num--) { Object.Destroy((Object)(object)((Component)val.transform.GetChild(num)).gameObject); } MonoBehaviour[] components = val.GetComponents<MonoBehaviour>(); foreach (MonoBehaviour val2 in components) { if (!(val2 is TextMeshProUGUI)) { Object.Destroy((Object)(object)val2); } } val.AddComponent<LayoutElement>().ignoreLayout = true; TextMeshProUGUI component = val.GetComponent<TextMeshProUGUI>(); ((TMP_Text)component).enableAutoSizing = false; ((TMP_Text)component).fontSize = Math.Max(10f, ((TMP_Text)levelText).fontSize * 0.72f); ((TMP_Text)component).alignment = (TextAlignmentOptions)258; ((TMP_Text)component).enableWordWrapping = false; ((TMP_Text)component).overflowMode = (TextOverflowModes)0; ((Graphic)component).raycastTarget = false; return component; } private static void Place(RectTransform line, RectTransform bar) { //IL_0013: 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_002a: 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_004b: 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_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: 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_0079: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(0.5f, 0.5f); line.anchorMax = val; line.anchorMin = val; line.pivot = new Vector2(0.5f, 1f); Vector3[] array = (Vector3[])(object)new Vector3[4]; bar.GetWorldCorners(array); Vector3 val2 = (array[0] + array[3]) / 2f; Vector3 val3 = ((Transform)(RectTransform)((Transform)line).parent).InverseTransformPoint(val2); ((Transform)line).localPosition = new Vector3(val3.x, val3.y - 2f, 0f); Rect rect = bar.rect; line.sizeDelta = new Vector2(((Rect)(ref rect)).width * 1.4f, ((TMP_Text)((Component)line).GetComponent<TextMeshProUGUI>()).fontSize * 1.3f); } } public static class Links { public const int Version = 2; public static float Score => Math.Max(0f, Prestige.Active); public static int Tier() { return Prestige.Tier(Score); } public static float TierProgress() { float[] array = Prestige.Thresholds(); float score = Score; int num = Prestige.Tier(score); float num2 = array[num]; float num3 = ((num < array.Length - 1) ? array[num + 1] : (array[num] * 2f)); if (!(num3 > num2)) { return 1f; } return Math.Max(0f, Math.Min(1f, (score - num2) / (num3 - num2))); } public static int SpreeSize() { return Whales.SpreeSize(Score); } public static bool IsWhale(Customer c) { return Whales.Is(c); } public static bool IsWealthy(Customer c) { return Wealthy.Is(c); } public static void TournamentFinished(int players) { Outside.TournamentFinished(players); } public static void Refresh() { Outside.RefreshSoon(); } public static void Notice(string icon, string text) { Toast.Show(icon, text); } } internal sealed class LookCard { private const float Width = 24f; private const float Pad = 1f; private const float Gap = 0.35f; private const float Line = 1.25f; private const float Icon = 1.5f; private const float BodySize = 0.85f; private const float SmallSize = 0.75f; private const float TitleSize = 1.15f; private const float PixelsPerUnit = 17f; private Palette _pal = Palette.Phone; private IUiKit? _kit; private bool _phoneLookFailed; private bool _failed; private GameObject? _canvas; private RectTransform? _root; private InteractionPlayerController? _player; private CardShelf? _shelf; private float _nextRay; private float _nextBuild; private int _mask; private string _shown = ""; private Color AccentLight => _pal.AccentLight; private Color Surface => _pal.Surface; private Color Teal => _pal.Teal; private Color Empty => _pal.Dashed; public void Update(bool panelOpen) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Invalid comparison between Unknown and I4 if (_failed) { return; } try { if (!(Time.unscaledTime < _nextRay)) { _nextRay = Time.unscaledTime + 0.1f; CardShelf val = ((!panelOpen && Plugin.LookAtCardEnabled.Value && (int)Cursor.lockState == 1) ? Aimed() : null); if ((Object)(object)val == (Object)null) { Hide(); } else if ((Object)(object)val != (Object)(object)_shelf || Time.unscaledTime >= _nextBuild) { _shelf = val; _nextBuild = Time.unscaledTime + 1f; Show(val); } } } catch (Exception e) { Fail(e); } } public void Destroy() { if ((Object)(object)_canvas != (Object)null) { Object.Destroy((Object)(object)_canvas); } _canvas = null; _root = null; } public void ResetLook() { Destroy(); _kit = null; _shelf = null; _shown = ""; } private void Hide() { _shelf = null; _shown = ""; if ((Object)(object)_canvas != (Object)null && _canvas.activeSelf) { _canvas.SetActive(false); } } private void Fail(Exception e) { bool flag = _kit != null && !(_kit is BuiltInUiKit); Plugin.Log.LogWarning((object)((flag ? "The case card failed with the Phone - Overhaul look; switching to the built-in look. " : "The case card failed and is turned off. ") + e)); Destroy(); _kit = null; if (flag) { _phoneLookFailed = true; } else { _failed = true; } } private CardShelf? Aimed() { //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_player == (Object)null) { _player = Object.FindObjectOfType<InteractionPlayerController>(); if ((Object)(object)_player == (Object)null) { return null; } } Camera cam = _player.m_Cam; if ((Object)(object)cam == (Object)null) { return null; } if (_mask == 0) { _mask = LayerMask.GetMask(new string[4] { "ShopModel", "Physics", "ItemCompartment", "Obstacles" }); } int mask = _mask; RaycastHit val = default(RaycastHit); if (!Physics.Raycast(new Ray(((Component)cam).transform.position, ((Component)cam).transform.forward), ref val, 4f, mask)) { return null; } CardShelf componentInParent = ((Component)((RaycastHit)(ref val)).transform).GetComponentInParent<CardShelf>(); if (!((Object)(object)componentInParent != (Object)null) || !componentInParent.m_ItemNotForSale) { return null; } return componentInParent; } private IUiKit Kit() { if (_kit == null) { _pal = Looks.Palette(); _kit = Looks.Kit(_phoneLookFailed); } return _kit; } private void EnsureCanvas() { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_0100: 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_012a: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_canvas != (Object)null)) { IUiKit uiKit = Kit(); _canvas = new GameObject("ShopPrestigeCaseCard", new Type[1] { typeof(RectTransform) }); Object.DontDestroyOnLoad((Object)(object)_canvas); Canvas obj = _canvas.AddComponent<Canvas>(); obj.renderMode = (RenderMode)0; obj.sortingOrder = 400; CanvasScaler obj2 = _canvas.AddComponent<CanvasScaler>(); obj2.uiScaleMode = (ScaleMode)1; obj2.referenceResolution = new Vector2(1920f, 1080f); obj2.matchWidthOrHeight = 1f; _root = uiKit.Node(_canvas.transform, "Root"); RectTransform? root = _root; RectTransform? root2 = _root; Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(1f, 0.5f); root2.anchorMax = val; root.anchorMin = val; _root.pivot = new Vector2(1f, 0.5f); _root.anchoredPosition = new Vector2(-60f, 0f); _root.sizeDelta = new Vector2(24f, 40f); ((Transform)_root).localScale = Vector3.one * 17f; _canvas.SetActive(false); } } private void Show(CardShelf shelf) { //IL_01cf: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_026a: Unknown result type (might be due to invalid IL or missing references) //IL_02bc: Unknown result type (might be due to invalid IL or missing references) //IL_02b4: Unknown result type (might be due to invalid IL or missing references) //IL_032f: Unknown result type (might be due to invalid IL or missing references) //IL_040d: Unknown result type (might be due to invalid IL or missing references) //IL_04b6: Unknown result type (might be due to invalid IL or missing references) //IL_0465: Unknown result type (might be due to invalid IL or missing references) //IL_045d: Unknown result type (might be due to invalid IL or missing references) //IL_0716: Unknown result type (might be due to invalid IL or missing references) //IL_075e: Unknown result type (might be due to invalid IL or missing references) //IL_07bb: Unknown result type (might be due to invalid IL or missing references) //IL_0818: Unknown result type (might be due to invalid IL or missing references) //IL_03c3: Unknown result type (might be due to invalid IL or missing references) //IL_03bb: Unknown result type (might be due to invalid IL or missing references) //IL_0662: Unknown result type (might be due to invalid IL or missing references) //IL_06c5: Unknown result type (might be due to invalid IL or missing references) CaseReport caseReport = Themes.Find(Themes.Evaluate(), shelf); if (caseReport == null) { Hide(); return; } string text = $"{caseReport.Name}|{caseReport.Cards}|{caseReport.Slots}|{caseReport.Value}|{caseReport.Multiplier}|{caseReport.Points}|" + string.Join(",", caseReport.Themes.Select((ThemeHit t) => t.Label + t.Applied)) + "|" + string.Join(",", caseReport.Quality.Select((QualityHit q) => q.Label)) + "|" + string.Join(",", caseReport.Near.Select((ThemeHit n) => n.Label + n.Have)); if (text == _shown && (Object)(object)_canvas != (Object)null && _canvas.activeSelf) { return; } _shown = text; EnsureCanvas(); IUiKit kit = Kit(); for (int num = ((Transform)_root).childCount - 1; num >= 0; num--) { Object.Destroy((Object)(object)((Component)((Transform)_root).GetChild(num)).gameObject); } Image val = kit.Panel((Transform)(object)_root, "Card", kit.Bg, 1.4f, raycast: false); kit.Border(((Component)val).transform, kit.Outline, 1.4f); RectTransform content = ((Graphic)val).rectTransform; float inner = 22f; float y = 1f; string text2 = "x" + caseReport.Multiplier.ToString("0.00"); Text(caseReport.Name, 1f, inner - 6.2f, 1.6f, 1.15f, kit.Text, (TextAlignmentOptions)4097, bold: true); Text(text2, 1f + inner - 6f, 6f, 2f, 1.9f, (caseReport.Multiplier > 1.001f) ? AccentLight : kit.TextMuted, (TextAlignmentOptions)4100, bold: true); y += 1.6f; Text($"{caseReport.Cards} of {caseReport.Slots} cards, worth {caseReport.Value:N0}", 1f, inner - 6.2f, 1.1f, 0.75f, kit.TextMuted, (TextAlignmentOptions)4097, bold: true); y += 1.8f; if (caseReport.Slots > 0 && caseReport.Slots <= 12) { float num2 = (inner - 0.3f * (float)(caseReport.Slots - 1)) / (float)caseReport.Slots; for (int num3 = 0; num3 < caseReport.Slots; num3++) { Block(1f + (float)num3 * (num2 + 0.3f), y, num2, 0.6f, (num3 < caseReport.Cards) ? Teal : Empty, 0.25f); } } else if (caseReport.Slots > 0) { Block(1f, y, inner, 0.6f, Empty, 0.3f); Block(1f, y, Math.Max(0.6f, inner * (float)caseReport.Cards / (float)caseReport.Slots), 0.6f, caseReport.Full ? Teal : kit.TextMuted, 0.3f); } y += 1.65f; if (!Plugin.ThemesEnabled.Value) { Text("Themes are off in the settings.", 1f, inner, 1.25f, 0.75f, kit.TextMuted, (TextAlignmentOptions)4097, bold: true); y += 1.25f; } else { foreach (ThemeHit theme in caseReport.Themes) { Row(theme.Icon, (theme.Applied < theme.Bonus - 0.001f) ? (theme.Label + " (extra)") : theme.Label, "+" + Percent(theme.Applied), muted: false); } foreach (QualityHit item in caseReport.Quality) { Row(item.Icon, item.Label, "+" + Percent(item.Bonus), muted: false); } foreach (ThemeHit item2 in caseReport.Near.Take(3)) { Row(item2.Icon, $"{item2.Label} {item2.Have} of {item2.Need}", "", muted: true); } if (!caseReport.Full) { Text("Fill every slot to earn a bonus.", 1f, inner, 1.25f, 0.75f, kit.TextMuted, (TextAlignmentOptions)4097, bold: true); y += 1.25f; } else if (caseReport.Themes.Count == 0 && caseReport.Quality.Count == 0) { Text("No bonus yet.", 1f, inner, 1.25f, 0.75f, kit.TextMuted, (TextAlignmentOptions)4097, bold: true); y += 1.25f; } } y += 0.35f; Block(1f, y, inner, 2.6f, Surface, 0.8f); Text($"{caseReport.Base:0.00} from cards", 1.8f, inner / 2f, 2.6f, 0.75f, kit.TextMuted, (TextAlignmentOptions)4097, bold: true); Text($"{caseReport.Points:0.00} Prestige",