using System; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("RerollConfirmation")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.1.0.0")] [assembly: AssemblyInformationalVersion("0.1.0+8d153c8fb11564aca4df46996aab1080663fef17")] [assembly: AssemblyProduct("RerollConfirmation")] [assembly: AssemblyTitle("RerollConfirmation")] [assembly: AssemblyVersion("0.1.0.0")] [module: RefSafetyRules(11)] 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; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace RerollConfirmation { [BepInPlugin("RerollConfirmation", "RerollConfirmation", "0.1.0")] public class Plugin : BaseUnityPlugin { internal static ManualLogSource Logger = new ManualLogSource("RerollConfirmation"); internal static ConfigEntry Enabled = null; internal static ConfigEntry TrinketShopThreshold = null; internal static ConfigEntry OtherShopThreshold = null; public void Awake() { //IL_0084: Unknown result type (might be due to invalid IL or missing references) Logger = ((BaseUnityPlugin)this).Logger; Enabled = ((BaseUnityPlugin)this).Config.Bind("General", "Enabled", true, "Enables the reroll gold warning icon and confirmation dialog."); TrinketShopThreshold = ((BaseUnityPlugin)this).Config.Bind("Thresholds", "TrinketShopMinimumGold", 135, "Minimum gold to keep after a reroll at the Trinket (Merchant of Trinkets) shop before warning."); OtherShopThreshold = ((BaseUnityPlugin)this).Config.Bind("Thresholds", "OtherShopMinimumGold", 90, "Minimum gold to keep after a reroll at other shops (Card/Steel/Arms/Magic) before warning."); Logger.LogInfo((object)"Plugin RerollConfirmation is loaded!"); new Harmony("RerollConfirmation").PatchAll(); } } public static class MyPluginInfo { public const string PLUGIN_GUID = "RerollConfirmation"; public const string PLUGIN_NAME = "RerollConfirmation"; public const string PLUGIN_VERSION = "0.1.0"; } } namespace RerollConfirmation.Patches { [HarmonyPatch(typeof(MerchantGoodUIBase), "RefreshAffordable")] internal static class MerchantGoodUIBase_RerollWarningIcon_Patch { private static readonly ConditionalWeakTable WarningIcons = new ConditionalWeakTable(); private static void Postfix(MerchantGoodUIBase __instance, int ownedGold) { if (Plugin.Enabled.Value) { MerchantGoodState goodState = __instance.GoodState; if (((goodState != null) ? ((RewardState)goodState).RewardData : null) is RerollMerchantRewardData) { MerchantData value = Traverse.Create((object)__instance).Field("merchantData").Value; AllGameManagers instance = AllGameManagers.Instance; SaveManager saveManager = ((instance != null) ? instance.GetSaveManager() : null); int cost = __instance.GoodState.GetCost(value); int minimumGoldAfterReroll = RerollGoldThreshold.GetMinimumGoldAfterReroll(value, saveManager); bool active = __instance.Affordable && ownedGold - cost < minimumGoldAfterReroll; WarningIcons.GetValue(__instance, CreateWarningIcon).SetActive(active); } } } private static GameObject CreateWarningIcon(MerchantGoodUIBase goodUI) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0054: 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_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Expected O, but got Unknown GameObject val = new GameObject("RerollGoldWarningIcon", new Type[1] { typeof(RectTransform) }); val.transform.SetParent(goodUI.FloatingRewardRoot, false); RectTransform val2 = (RectTransform)val.transform; Vector2 val3 = default(Vector2); ((Vector2)(ref val3))..ctor(1f, 1f); val2.pivot = val3; Vector2 anchorMin = (val2.anchorMax = val3); val2.anchorMin = anchorMin; val2.anchoredPosition = new Vector2(-2f, -2f); val2.sizeDelta = new Vector2(20f, 20f); TextMeshProUGUI obj = val.AddComponent(); ((TMP_Text)obj).text = "!"; ((Graphic)obj).color = Color.red; ((TMP_Text)obj).fontSize = 20f; ((TMP_Text)obj).fontStyle = (FontStyles)1; ((TMP_Text)obj).alignment = (TextAlignmentOptions)514; return val; } } [HarmonyPatch(typeof(MerchantScreen), "TryPurchase")] internal static class MerchantScreen_RerollConfirmation_Patch { private static bool suppressConfirmation; private static bool Prefix(MerchantScreen __instance, MerchantGoodUIBase goodUI) { if (suppressConfirmation || !Plugin.Enabled.Value) { return true; } MerchantGoodUIBase obj = goodUI; object obj2; if (obj == null) { obj2 = null; } else { MerchantGoodState goodState = obj.GoodState; obj2 = ((goodState != null) ? ((RewardState)goodState).RewardData : null); } if (!(obj2 is RerollMerchantRewardData)) { return true; } SaveManager value = Traverse.Create((object)__instance).Field("saveManager").Value; MerchantData value2 = Traverse.Create((object)__instance).Field("sourceMerchantData").Value; int cost = goodUI.GoodState.GetCost(value2); if (!value.CanAfford(cost)) { return true; } int num = value.GetGold() - cost; int minimumGoldAfterReroll = RerollGoldThreshold.GetMinimumGoldAfterReroll(value2, value); if (num >= minimumGoldAfterReroll) { return true; } Traverse.Create((object)__instance).Field("screenManager").Value.ShowConfirmationDialog($"Rerolling will leave you with only {num} gold. Reroll anyway?", (Action)delegate { suppressConfirmation = true; try { Traverse.Create((object)__instance).Method("TryPurchase", new object[1] { goodUI }).GetValue(); } finally { suppressConfirmation = false; } }, (Action)null, (Anchor)0, false); return false; } } internal static class RerollGoldThreshold { private const string TrinketShopAssetNameMarker = "ArtifactMerchant"; private const string GuildMarkerRelicAssetKey = "CheaperMerchants"; private const double GuildMarkerDiscountMultiplier = 0.75; public static int GetMinimumGoldAfterReroll(MerchantData? merchantData, SaveManager? saveManager) { int num = (((Object)(object)merchantData != (Object)null && ((Object)merchantData).name.Contains("ArtifactMerchant")) ? Plugin.TrinketShopThreshold.Value : Plugin.OtherShopThreshold.Value); if (!((Object)(object)saveManager != (Object)null) || !saveManager.GetAllRelics().Any((RelicState relic) => relic.GetAssetName() == "CheaperMerchants")) { return num; } return (int)Math.Round((double)num * 0.75); } } }