Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of ForgeOfIdols v1.0.1
ForgeOfIdols.dll
Decompiled 5 days agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using ConditionalConfigSync; 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("ForgeOfIdols")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.1.0")] [assembly: AssemblyInformationalVersion("1.0.1+8aaa0b37ff523a621352b5b4dd9ec923550834fc")] [assembly: AssemblyProduct("ForgeOfIdols")] [assembly: AssemblyTitle("ForgeOfIdols")] [assembly: AssemblyVersion("1.0.1.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [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 ForgeOfIdols { internal enum IdolTab { Upgrade, Convert } internal static class ForgeTabs { private sealed class RectState { private readonly RectTransform transform; private readonly Vector2 anchorMin; private readonly Vector2 anchorMax; private readonly Vector2 pivot; private readonly Vector2 position; private readonly Vector2 size; internal RectState(RectTransform transform) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //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_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: 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) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003f: 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) this.transform = transform; anchorMin = transform.anchorMin; anchorMax = transform.anchorMax; pivot = transform.pivot; position = transform.anchoredPosition; size = transform.sizeDelta; } internal void ApplyTo(RectTransform target) { //IL_0002: 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_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) target.anchorMin = anchorMin; target.anchorMax = anchorMax; target.pivot = pivot; target.sizeDelta = size; target.anchoredPosition = position; } internal void Restore() { ApplyTo(transform); } } private static InventoryGui owner; private static CraftingStation station; private static string craftLabel; private static RectState craftRect; private static RectState upgradeRect; internal static IdolTab Selected { get; private set; } internal static void Prepare(InventoryGui gui) { Player localPlayer = Player.m_localPlayer; CraftingStation val = ((localPlayer != null) ? localPlayer.GetCurrentCraftingStation() : null); if (!((Object)(object)owner == (Object)(object)gui) || !((Object)(object)station == (Object)(object)val)) { Restore(); owner = gui; station = val; Selected = IdolTab.Upgrade; craftLabel = ((Component)gui.m_tabCraft).GetComponentInChildren<TMP_Text>(true).text; } } internal static void Select(InventoryGui gui, IdolTab tab) { Prepare(gui); if (Crafting.AtForge(Player.m_localPlayer)) { Selected = tab; } } internal static bool ShowConversions(InventoryGui gui) { Prepare(gui); if (Crafting.AtForge(Player.m_localPlayer)) { return Selected == IdolTab.Convert; } return false; } internal static void Apply(InventoryGui gui) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Expected O, but got Unknown //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Expected O, but got Unknown //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Expected O, but got Unknown Prepare(gui); if (Crafting.AtForge(Player.m_localPlayer)) { if (craftRect == null) { craftRect = new RectState((RectTransform)((Component)gui.m_tabCraft).transform); upgradeRect = new RectState((RectTransform)((Component)gui.m_tabUpgrade).transform); craftRect.ApplyTo((RectTransform)((Component)gui.m_tabUpgrade).transform); upgradeRect.ApplyTo((RectTransform)((Component)gui.m_tabCraft).transform); } ((Component)gui.m_tabCraft).gameObject.SetActive(true); ((Component)gui.m_tabUpgrade).gameObject.SetActive(true); ((Selectable)gui.m_tabCraft).interactable = Selected != IdolTab.Convert; ((Selectable)gui.m_tabUpgrade).interactable = Selected != IdolTab.Upgrade; RefreshCaption(gui); } } internal static void RefreshCaption(InventoryGui gui) { if (!((Object)(object)owner != (Object)(object)gui) && Crafting.AtForge(Player.m_localPlayer)) { ((Component)gui.m_tabCraft).GetComponentInChildren<TMP_Text>(true).text = "CONVERT"; } } private static void Restore() { if ((Object)(object)owner != (Object)null && craftLabel != null) { ((Component)owner.m_tabCraft).GetComponentInChildren<TMP_Text>(true).text = craftLabel; craftRect?.Restore(); upgradeRect?.Restore(); } craftRect = (upgradeRect = null); } internal static void Clear() { Restore(); owner = null; station = null; craftLabel = null; Selected = IdolTab.Upgrade; } } [HarmonyPatch(typeof(InventoryGui), "UpdateCraftingPanel")] internal static class ForgePanelPatch { private static void Prefix(InventoryGui __instance) { ForgeTabs.Prepare(__instance); } private static void Postfix(InventoryGui __instance) { ForgeTabs.Apply(__instance); } } [HarmonyPatch(typeof(InventoryGui), "OnTabCraftPressed")] internal static class IdolTabPatch { private static void Prefix(InventoryGui __instance) { ForgeTabs.Select(__instance, IdolTab.Convert); } } [HarmonyPatch(typeof(InventoryGui), "OnTabUpgradePressed")] internal static class GearTabPatch { private static void Prefix(InventoryGui __instance) { ForgeTabs.Select(__instance, IdolTab.Upgrade); } } [BepInPlugin("MerlinofMines.ForgeOfIdols", "Forge of Idols", "1.0.1")] [BepInDependency("_shudnal.ConditionalConfigSync", "1.0.9")] public sealed class Plugin : BaseUnityPlugin { public const string Id = "MerlinofMines.ForgeOfIdols"; public const string Version = "1.0.1"; private const string ReloadStateKey = "MerlinofMines.ForgeOfIdols.ReloadState.v1"; internal static ConfigSync Sync; internal static ConfigEntry<int> ConversionCost; internal static ConfigEntry<int> UpgradeCost; internal static ConfigEntry<double> ConversionChance; internal static ConfigEntry<double> UpgradeChance; internal static Action<string> LogAttempt; internal static bool Pending; private Harmony harmony; internal static bool Ready { get { if (!Pending) { if (Sync != null && !((Object)(object)ZNet.instance == (Object)null) && !ZNet.instance.IsServer()) { return ((ConditionalConfigSync)Sync).InitialSyncDone; } return true; } return false; } } private void Awake() { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Expected O, but got Unknown //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Expected O, but got Unknown //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Expected O, but got Unknown //IL_01dc: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Expected O, but got Unknown LogAttempt = delegate(string message) { ((BaseUnityPlugin)this).Logger.LogInfo((object)message); }; if (AppDomain.CurrentDomain.GetData("MerlinofMines.ForgeOfIdols.ReloadState.v1") is object[] array) { Sync = (ConfigSync)array[0]; AccessTools.Field(typeof(BaseUnityPlugin), "<Config>k__BackingField").SetValue(this, array[1]); } else { Sync = new ConfigSync("MerlinofMines.ForgeOfIdols"); } ((ConditionalConfigSync)Sync).DisplayName = "Forge of Idols"; ((ConditionalConfigSync)Sync).CurrentVersion = (((ConditionalConfigSync)Sync).MinimumRequiredVersion = "1.0.1"); ((ConditionalConfigSync)Sync).ModRequired = true; ((ConditionalConfigSync)Sync).ModRequirementMode = (ModRequirementMode)0; ((ConditionalConfigSync)Sync).IsLocked = true; ((ConditionalConfigSync)Sync).AllowClientConfigUpdatesWhenUnlocked = false; ConversionCost = Cost("Conversion", 1, "Input idols consumed per attempt to convert protection to battle, or battle to protection, at the same tier."); ConversionChance = Chance("Conversion"); UpgradeCost = Cost("Tier Upgrading", 3, "Lower tier idols consumed per attempt to create one idol of the next tier, of the same type."); UpgradeChance = Chance("Tier Upgrading"); ((BaseUnityPlugin)this).Config.Bind<bool>("Server", "Lock Configuration", true, new ConfigDescription("Legacy setting; removed.", (AcceptableValueBase)null, Array.Empty<object>())); ((BaseUnityPlugin)this).Config.Remove(new ConfigDefinition("Server", "Lock Configuration")); ((BaseUnityPlugin)this).Config.Save(); AppDomain.CurrentDomain.SetData("MerlinofMines.ForgeOfIdols.ReloadState.v1", new object[2] { Sync, ((BaseUnityPlugin)this).Config }); ((BaseUnityPlugin)this).Config.SettingChanged += Changed; ((ConditionalConfigSync)Sync).InitialSyncCompleted += QueueRefresh; ((ConditionalConfigSync)Sync).ServerConnectionReset += QueueRefresh; ((ConditionalConfigSync)Sync).SourceOfTruthChanged += OwnershipChanged; harmony = new Harmony("MerlinofMines.ForgeOfIdols"); harmony.PatchAll(typeof(Plugin).Assembly); Pending = true; ((BaseUnityPlugin)this).Logger.LogInfo((object)"Forge of Idols loaded: protection conversion and idol tier upgrades."); } private ConfigEntry<int> Cost(string section, int value, string description) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown ConfigEntry<int> val = ((BaseUnityPlugin)this).Config.Bind<int>(section, "Input Idols", value, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 10000), Array.Empty<object>())); ((ConditionalConfigSync)Sync).AddConfigEntry<int>(val, (ConfigSyncMode)0); return val; } private ConfigEntry<double> Chance(string section) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Expected O, but got Unknown ConfigEntry<double> val = ((BaseUnityPlugin)this).Config.Bind<double>(section, "Success Probability", 80.0, new ConfigDescription("Success chance (%). Zero disables attempts without cost. Failed attempts consume the input idols and produce nothing.", (AcceptableValueBase)(object)new AcceptableValueRange<double>(0.0, 100.0), Array.Empty<object>())); ((ConditionalConfigSync)Sync).AddConfigEntry<double>(val, (ConfigSyncMode)0); return val; } private void Changed(object sender, SettingChangedEventArgs args) { QueueRefresh(); } private void OwnershipChanged(bool local) { QueueRefresh(); } private void QueueRefresh() { Pending = true; } private void LateUpdate() { if ((Object)(object)InventoryGui.instance != (Object)null) { ForgeTabs.RefreshCaption(InventoryGui.instance); } if (Pending && !ConditionalConfigSync.ProcessingServerUpdate) { Pending = false; Catalog.UpdateCosts(); if ((Object)(object)InventoryGui.instance != (Object)null && Crafting.AtForge(Player.m_localPlayer)) { Menu.Refresh(InventoryGui.instance); } } } private void OnDestroy() { ((BaseUnityPlugin)this).Config.SettingChanged -= Changed; if (Sync != null) { ((ConditionalConfigSync)Sync).InitialSyncCompleted -= QueueRefresh; ((ConditionalConfigSync)Sync).ServerConnectionReset -= QueueRefresh; ((ConditionalConfigSync)Sync).SourceOfTruthChanged -= OwnershipChanged; } Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } ForgeTabs.Clear(); if ((Object)(object)InventoryGui.instance != (Object)null) { Menu.ClearIdolSelection(InventoryGui.instance); } Catalog.Clear(); if ((Object)(object)InventoryGui.instance != (Object)null && Crafting.AtForge(Player.m_localPlayer)) { Menu.Refresh(InventoryGui.instance); } LogAttempt = null; } } internal sealed class Rule { internal readonly Recipe Recipe; internal readonly bool Upgrade; internal int Cost => (Upgrade ? Plugin.UpgradeCost : Plugin.ConversionCost).Value; internal double Chance => (Upgrade ? Plugin.UpgradeChance : Plugin.ConversionChance).Value; internal Rule(Recipe recipe, bool upgrade) { Recipe = recipe; Upgrade = upgrade; } } internal static class Catalog { internal static readonly Dictionary<Recipe, Rule> Rules = new Dictionary<Recipe, Rule>(); private static ObjectDB database; internal static void Clear() { foreach (Recipe key in Rules.Keys) { Object.Destroy((Object)(object)key); } Rules.Clear(); database = null; } internal static void Ensure() { if ((Object)(object)ObjectDB.instance == (Object)null || ((Object)(object)database == (Object)(object)ObjectDB.instance && Rules.Count > 0)) { return; } Clear(); database = ObjectDB.instance; for (int i = 0; i <= 7; i++) { Add("Upgrader" + i + "Armor", "Upgrader" + i + "Weapon", upgrade: false); Add("Upgrader" + i + "Weapon", "Upgrader" + i + "Armor", upgrade: false); if (i != 7) { string[] array = new string[2] { "Armor", "Weapon" }; foreach (string text in array) { Add("Upgrader" + i + text, "Upgrader" + (i + 1) + text, upgrade: true); } } } } private static void Add(string input, string output, bool upgrade) { //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0083: 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_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Expected O, but got Unknown GameObject itemPrefab = database.GetItemPrefab(input); ItemDrop val = ((itemPrefab != null) ? itemPrefab.GetComponent<ItemDrop>() : null); GameObject itemPrefab2 = database.GetItemPrefab(output); ItemDrop val2 = ((itemPrefab2 != null) ? itemPrefab2.GetComponent<ItemDrop>() : null); if (!((Object)(object)val == (Object)null) && !((Object)(object)val2 == (Object)null)) { Recipe val3 = ScriptableObject.CreateInstance<Recipe>(); ((Object)val3).name = "ForgeOfIdols_" + input + "_" + output; val3.m_item = val2; val3.m_amount = 1; val3.m_resources = (Requirement[])(object)new Requirement[1] { new Requirement { m_resItem = val, m_amount = (upgrade ? Plugin.UpgradeCost : Plugin.ConversionCost).Value, m_amountPerLevel = 0, m_upgraderResource = true, m_recover = false } }; Rules.Add(val3, new Rule(val3, upgrade)); } } internal static void UpdateCosts() { foreach (KeyValuePair<Recipe, Rule> rule in Rules) { rule.Key.m_resources[0].m_amount = rule.Value.Cost; } } } internal static class Crafting { internal static bool AtForge(Player player) { if ((Object)(object)player != (Object)null && (Object)(object)player.GetCurrentCraftingStation() != (Object)null) { return player.GetCurrentCraftingStation().m_upgrader; } return false; } internal static bool Free(Player player) { if (!player.NoCostCheat()) { return ZoneSystem.instance.GetGlobalKey((GlobalKeys)25); } return true; } internal static bool OutputDiscovered(Player player, Recipe recipe) { return player.IsKnownMaterial(recipe.m_item.m_itemData.m_shared.m_name); } internal static bool Eligible(Player player, Recipe recipe) { if (!Plugin.Ready || !AtForge(player) || (Object)(object)recipe == (Object)null || !Catalog.Rules.TryGetValue(recipe, out var value)) { return false; } if (!OutputDiscovered(player, recipe)) { return false; } if (value.Cost < 1 || value.Cost > 10000 || double.IsNaN(value.Chance) || value.Chance <= 0.0 || value.Chance > 100.0) { return false; } if (player.GetCurrentCraftingStation().CheckUsable(player, false) && ((Humanoid)player).GetInventory().CanAddItem(recipe.m_item.m_itemData, 1)) { if (!Free(player)) { return player.HaveRequirements(recipe, false, 1, 1); } return true; } return false; } internal static bool Succeeds(double chance, double roll) { if (!(chance >= 100.0)) { if (chance > 0.0) { return roll < chance / 100.0; } return false; } return true; } internal static void Attempt(InventoryGui gui, Player player, Recipe recipe) { //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) if (!Eligible(player, recipe)) { return; } Rule rule = Catalog.Rules[recipe]; bool flag = Free(player); bool flag2 = flag || ((Humanoid)player).GetInventory().ItemCheated(recipe.m_resources, -1, true); double chance = rule.Chance; double num = Random.value; bool flag3 = Succeeds(chance, num); if (flag3) { ItemData val = recipe.m_item.m_itemData.Clone(); val.m_dropPrefab = ((Component)recipe.m_item).gameObject; val.m_quality = 1; val.m_stack = 1; val.m_worldLevel = (byte)Game.m_worldLevel; val.m_cheated = flag2 && !PlayerProfile.s_bypassCheatChecks; if (!((Humanoid)player).GetInventory().AddItem(val)) { return; } if (!flag) { player.ConsumeResources(recipe.m_resources, 1, -1, 1); } ((Character)player).Message((MessageType)2, rule.Upgrade ? "Upgrade successful" : "Conversion successful", 0, (Sprite)null, false); player.GetCurrentCraftingStation().m_craftItemDoneEffects.Create(((Component)player).transform.position, Quaternion.identity, (Transform)null, 1f, -1, default(ZDOID)); } else { if (!flag) { player.ConsumeResources(recipe.m_resources, 1, -1, 1); } ((Character)player).Message((MessageType)2, rule.Upgrade ? "Upgrade failed" : "Conversion failed", 0, (Sprite)null, false); } Plugin.LogAttempt?.Invoke(string.Format("{0} {1}: chance={2:0.####}%, roll={3:0.####}%, result={4}", rule.Upgrade ? "Upgrade" : "Conversion", ((Object)recipe).name, chance, num * 100.0, flag3 ? "success" : "failure")); Game.instance.GetPlayerProfile().IncrementStat((PlayerStatType)1, 1f, flag2); Menu.Refresh(gui); } } internal static class Menu { private static readonly FieldInfo Selected = AccessTools.Field(typeof(InventoryGui), "m_selectedRecipe"); private static readonly PropertyInfo SelectedRecipe = AccessTools.Property(Selected.FieldType, "Recipe"); private static readonly MethodInfo RefreshMethod = AccessTools.Method(typeof(InventoryGui), "UpdateCraftingPanel", (Type[])null, (Type[])null); private static readonly MethodInfo Add = AccessTools.Method(typeof(InventoryGui), "AddRecipeToList", (Type[])null, (Type[])null); internal static Recipe Selection(InventoryGui gui) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown return (Recipe)SelectedRecipe.GetValue(Selected.GetValue(gui)); } internal static void ClearIdolSelection(InventoryGui gui) { Recipe val = Selection(gui); if ((Object)(object)val != (Object)null && Catalog.Rules.ContainsKey(val)) { Selected.SetValue(gui, Activator.CreateInstance(Selected.FieldType)); } } internal static void Refresh(InventoryGui gui) { RefreshMethod.Invoke(gui, new object[1] { false }); } internal static void AddRows(InventoryGui gui, Player player, bool? upgrade = null) { Catalog.Ensure(); Catalog.UpdateCosts(); foreach (Rule value in Catalog.Rules.Values) { if (!upgrade.HasValue || value.Upgrade == upgrade.Value) { string name = value.Recipe.m_resources[0].m_resItem.m_itemData.m_shared.m_name; if (((Humanoid)player).GetInventory().CountItems(name, -1, true) != 0 && Crafting.OutputDiscovered(player, value.Recipe)) { Add.Invoke(gui, new object[4] { player, value.Recipe, null, Crafting.Eligible(player, value.Recipe) }); } } } } } [HarmonyPatch(typeof(InventoryGui), "UpdateRecipeList")] internal static class RecipeListPatch { private static readonly FieldInfo Rows = AccessTools.Field(typeof(InventoryGui), "m_availableRecipes"); private static void Prefix(InventoryGui __instance, ref List<Recipe> recipes) { ForgeTabs.Apply(__instance); if (ForgeTabs.ShowConversions(__instance)) { recipes = new List<Recipe>(); } } private static void Postfix(InventoryGui __instance, RectTransform ___m_recipeListRoot, float ___m_recipeListSpace, float ___m_recipeListBaseSize) { if (Crafting.AtForge(Player.m_localPlayer)) { Menu.AddRows(__instance, Player.m_localPlayer, ForgeTabs.Selected == IdolTab.Upgrade); ___m_recipeListRoot.SetSizeWithCurrentAnchors((Axis)1, Math.Max(___m_recipeListBaseSize, (float)((IList)Rows.GetValue(__instance)).Count * ___m_recipeListSpace)); } } } [HarmonyPatch(typeof(InventoryGui), "OnCraftPressed")] internal static class StartPatch { [HarmonyPriority(800)] [HarmonyBefore(new string[] { "MerlinofMines.ForgeRework" })] private static bool Prefix(InventoryGui __instance, ref Recipe ___m_craftRecipe, ref ItemData ___m_craftUpgradeItem, ref float ___m_craftTimer, ref bool ___m_multiCrafting, ref bool ___m_touchMultiCrafting) { //IL_0061: 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_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) Recipe val = Menu.Selection(__instance); if ((Object)(object)val == (Object)null || !Catalog.Rules.ContainsKey(val)) { return true; } Player localPlayer = Player.m_localPlayer; if (___m_craftTimer >= 0f || !Crafting.Eligible(localPlayer, val)) { return false; } ___m_craftRecipe = val; ___m_craftUpgradeItem = null; ___m_multiCrafting = (___m_touchMultiCrafting = false); ___m_craftTimer = 0f; localPlayer.GetCurrentCraftingStation().m_craftItemEffects.Create(((Component)localPlayer).transform.position, Quaternion.identity, (Transform)null, 1f, -1, default(ZDOID)); return false; } } [HarmonyPatch(typeof(InventoryGui), "DoCrafting")] internal static class CraftPatch { [HarmonyPriority(800)] [HarmonyBefore(new string[] { "MerlinofMines.ForgeRework" })] private static bool Prefix(InventoryGui __instance, Player player, Recipe ___m_craftRecipe) { if ((Object)(object)___m_craftRecipe == (Object)null || !Catalog.Rules.ContainsKey(___m_craftRecipe)) { return true; } Crafting.Attempt(__instance, player, ___m_craftRecipe); return false; } } [HarmonyPatch(typeof(InventoryGui), "UpdateRecipe")] internal static class DisplayPatch { [HarmonyPriority(0)] [HarmonyAfter(new string[] { "MerlinofMines.ForgeRework" })] private static void Postfix(InventoryGui __instance, Player player) { Recipe val = Menu.Selection(__instance); if (!((Object)(object)val == (Object)null) && Catalog.Rules.TryGetValue(val, out var value)) { ((Component)__instance.m_itemCraftType).gameObject.SetActive(true); string arg = (value.Upgrade ? "Upgrade" : "Convert"); __instance.m_itemCraftType.text = (Plugin.Ready ? $"Chance To {arg}: {value.Chance:0.##}%" : "Syncing settings..."); ((Selectable)__instance.m_craftButton).interactable = Crafting.Eligible(player, val); ((Component)__instance.m_craftButton).GetComponentInChildren<TMP_Text>().text = (value.Upgrade ? "Attempt Upgrade" : "Attempt Conversion"); } } } }