Browse Source

[2.0.5.2] custom crafter support

Zariteis 3 years ago
parent
commit
d9f0acc23a

+ 50 - 1
API/RecipePage.cs

@@ -13,6 +13,11 @@ namespace RecipeMenuCore.API
     /// </summary>
     public readonly RecipePageType Type;
 
+    /// <summary>
+    /// The id of this crafter for RecipePageType = Custom
+    /// </summary>
+    public readonly string CrafterId;
+
     /// <summary>
     /// The Title displayed on top of this RecipePage.
     /// </summary>
@@ -35,6 +40,8 @@ namespace RecipeMenuCore.API
     /// </summary>
     public RecipePage(RecipePageType Type, string Title, Texture Tex)
     {
+      if (Type == RecipePageType.Custom)
+        throw new System.Exception("RecipePageType.Custom requires a crafter name to be set.");
       this.Type = Type;
       this.Title = Title;
       this.Tex = Tex;
@@ -45,11 +52,39 @@ namespace RecipeMenuCore.API
     /// </summary>
     public RecipePage(RecipePageType Type, string Title, Material Mat)
     {
+      if (Type == RecipePageType.Custom)
+        throw new System.Exception("RecipePageType.Custom requires a crafter name to be set.");
       this.Type = Type;
       this.Title = Title;
       this.Mat = Mat;
     }
 
+    /// <summary>
+    /// Use to create a new RecipePage. Make sure to call Register on it to enable your RecipePage.
+    /// </summary>
+    public RecipePage(RecipePageType Type, string Title, Texture Tex, string CrafterId)
+    {
+      if (Type != RecipePageType.Custom)
+        throw new System.Exception("CrafterId is only used for RecipePageType = Custom.");
+      this.Type = Type;
+      this.Title = Title;
+      this.Tex = Tex;
+      this.CrafterId = CrafterId;
+    }
+
+    /// <summary>
+    /// Use to create a new RecipePage. Make sure to call Register on it to enable your RecipePage.
+    /// </summary>
+    public RecipePage(RecipePageType Type, string Title, Material Mat, string CrafterId)
+    {
+      if (Type != RecipePageType.Custom)
+        throw new System.Exception("CrafterId is only used for RecipePageType = Custom.");
+      this.Type = Type;
+      this.Title = Title;
+      this.Mat = Mat;
+      this.CrafterId = CrafterId;
+    }
+
     /// <summary>
     /// Used to register the page and make it show.
     /// </summary>
@@ -70,6 +105,11 @@ namespace RecipeMenuCore.API
         case RecipePageType.UniversalCrafter:
           Core.pageUniversalCrafterInfoList.Add(this);
           break;
+        case RecipePageType.Custom:
+          if (!Core.pageCustomCrafterInfoLists.ContainsKey(CrafterId))
+            Core.pageCustomCrafterInfoLists.Add(CrafterId, new List<RecipePage>());
+          Core.pageCustomCrafterInfoLists[CrafterId].Add(this);
+          break;
       }
       return this;
     }
@@ -79,6 +119,8 @@ namespace RecipeMenuCore.API
     /// </summary>
     public virtual RecipePage RegisterAsVanilla(int i)
     {
+      if (Type != RecipePageType.GearForge && Type != RecipePageType.AlchemyStation && Type != RecipePageType.UltimateForge)
+        throw new System.Exception("RegisterAsVanilla can only be used for vanilla crafters.");
       PostRegister();
       switch (Type)
       {
@@ -123,6 +165,8 @@ namespace RecipeMenuCore.API
     /// </summary>
     public void AddRecipePageEntry(RecipePageEntry row)
     {
+      if (Type != RecipePageType.Custom && row.IsReverse)
+        throw new System.Exception("Reverse recipes are only supported in custom crafting stations.");
       Rows.Add(row);
     }
 
@@ -158,6 +202,11 @@ namespace RecipeMenuCore.API
     /// <summary>
     /// This recipe is for the Gadget Core Universal Crafter.
     /// </summary>
-    UniversalCrafter
+    UniversalCrafter,
+
+    /// <summary>
+    /// This recipe is for a custom Crafter.
+    /// </summary>
+    Custom
   }
 }

+ 101 - 14
API/RecipePageEntry.cs

@@ -1,32 +1,106 @@
-namespace RecipeMenuCore.API
+using System;
+
+namespace RecipeMenuCore.API
 {
   public class RecipePageEntry
   {
+
     /// <summary>
     /// The ultimate items in UltimateFore recipes or the inputs in other recipes.
     /// </summary>
-    public int[] ItemIdExtension { get; protected set; }
+    [Obsolete]
+    public int[] ItemIdExtension
+    {
+      get
+      {
+        if (ItemIds != null && ItemIds.Length == 4)
+          return new int[] { ItemIds[0], ItemIds[1], ItemIds[2] };
+        return new int[3];
+      }
+    }
 
     /// <summary>
     /// The normal item in UltimateFore recipes or the output in other recipes.
     /// </summary>
-    public int ItemIdBase { get; protected set; }
+    [Obsolete]
+    public int ItemIdBase
+    {
+      get
+      {
+        if (ItemIds != null && ItemIds.Length == 4)
+          return ItemIds[3];
+        return 0;
+      }
+    }
 
     /// <summary>
     /// The MinAmount of items created from a recipe.
     /// </summary>
-    public int MinAmount { get; protected set; }
+    [Obsolete]
+    public int MinAmount
+    {
+      get
+      {
+        if (MinAmounts != null && MinAmounts.Length == 4)
+          return MinAmounts[3];
+        return 1;
+      }
+    }
 
     /// <summary>
     /// The MaxBonusAmount to be added to the base value.
     /// </summary>
-    public int MaxBonusAmount { get; protected set; }
+    [Obsolete]
+    public int MaxBonusAmount
+    {
+      get
+      {
+        if (MaxBonusAmounts != null && MaxBonusAmounts.Length == 4)
+          return MaxBonusAmounts[3];
+        return 0;
+      }
+    }
 
     /// <summary>
     /// Should the input be visible, if the craft has never been done before.
     /// </summary>
     public bool AllwaysShowInput { get; protected set; }
 
+    /// <summary>
+    /// All 4 items used in the recipe.
+    /// </summary>
+    public int[] ItemIds { get; protected set; }
+
+    /// <summary>
+    /// The Minimum amount of items required or created of each of the 4 items.
+    /// </summary>
+    public int[] MinAmounts { get; protected set; }
+
+    /// <summary>
+    /// The MaxBonusAmount to be added to the base value (output only).
+    /// </summary>
+    public int[] MaxBonusAmounts { get; protected set; }
+
+    /// <summary>
+    /// States if the recipe is a 3 to 1 or a 1 to 3 items recipe.
+    /// </summary>
+    public bool IsReverse { get; protected set; }
+
+    /// <summary>
+    /// Use to create a new RecipePageEntry.
+    /// </summary>
+    /// <param name="id1">The first ultimate item in UltimateFore recipes or the first input in other recipes.</param>
+    /// <param name="id2">The second ultimate item in UltimateFore recipes or the second input in other recipes.</param>
+    /// <param name="id3">The third ultimate item in UltimateFore recipes or the third input in other recipes.</param>
+    /// <param name="idBase">The normal item in UltimateFore recipes or the output in other recipes.</param>
+    public RecipePageEntry(int id1, int id2, int id3, int idBase)
+    {
+      ItemIds = new int[] { id1, id2, id3, idBase };
+      MinAmounts = new int[] { 1, 1, 1, 1 };
+      MaxBonusAmounts = new int[] { 0, 0, 0, 0 };
+      AllwaysShowInput = false;
+    }
+
     /// <summary>
     /// Use to create a new RecipePageEntry.
     /// </summary>
@@ -38,10 +112,9 @@
     /// <param name="maxBonus">The maximum bonus amount of items created from a recipe.</param>
     public RecipePageEntry(int id1, int id2, int id3, int idBase, int min, int maxBonus)
     {
-      ItemIdExtension = new int[] { id1, id2, id3 };
-      ItemIdBase = idBase;
-      MinAmount = min;
-      MaxBonusAmount = maxBonus;
+      ItemIds = new int[] { id1, id2, id3, idBase };
+      MinAmounts = new int[] { 1, 1, 1, min };
+      MaxBonusAmounts = new int[] { 0, 0, 0, maxBonus };
     }
 
     /// <summary>
@@ -53,13 +126,27 @@
     /// <param name="idBase">The normal item in UltimateFore recipes or the output in other recipes.</param>
     /// <param name="min">The minimum amount of items created from a recipe.</param>
     /// <param name="maxBonus">The maximum bonus amount of items created from a recipe.</param>
-    public RecipePageEntry(int id1, int id2, int id3, int idBase, int min = 1, int maxBonus = 0, bool allwaysShowInput = false)
+    public RecipePageEntry(int id1, int id2, int id3, int idBase, int min, int maxBonus, bool allwaysShowInput)
     {
-      ItemIdExtension = new int[] { id1, id2, id3 };
-      ItemIdBase = idBase;
-      MinAmount = min;
-      MaxBonusAmount = maxBonus;
+      ItemIds = new int[] { id1, id2, id3, idBase };
+      MinAmounts = new int[] { 1, 1, 1, min };
+      MaxBonusAmounts = new int[] { 0, 0, 0, maxBonus };
       AllwaysShowInput = allwaysShowInput;
     }
+
+    /// <summary>
+    /// Use to create a new RecipePageEntry.
+    /// </summary>
+    /// <param name="idIn">The input item id.</param>
+    /// <param name="idOut1">The first output item id.</param>
+    /// <param name="idOut2">The second output item id.</param>
+    /// <param name="idOut3">The third output item id.</param>
+    public RecipePageEntry(int idIn, int idOut1, int idOut2, int idOut3, int minOut1, int minOut2, int minOut3, int maxBonusOut1, int maxBonusOut2, int maxBonusOut3)
+    {
+      ItemIds = new int[] { idIn, idOut1, idOut2, idOut3 };
+      MinAmounts = new int[] { 1, minOut1, minOut2, minOut3 };
+      MaxBonusAmounts = new int[] { 0, maxBonusOut1, maxBonusOut2, maxBonusOut3 };
+      IsReverse = true;
+    }
   }
 }

+ 1 - 0
Core.cs

@@ -11,6 +11,7 @@ namespace RecipeMenuCore
     internal static List<RecipePage> pageAlchemyStationInfoList = new List<RecipePage>();
     internal static List<RecipePage> pageUltimateForgeInfoList = new List<RecipePage>();
     internal static List<RecipePage> pageUniversalCrafterInfoList = new List<RecipePage>();
+    internal static Dictionary<string, List<RecipePage>> pageCustomCrafterInfoLists = new Dictionary<string, List<RecipePage>>();
 
     internal static RecipePage[] pageGearForgeInfoListVanilla = new RecipePage[6];
     internal static RecipePage[] pageAlchemyStationInfoListVanilla = new RecipePage[2];

+ 27 - 0
CraftTypeHelper.cs

@@ -0,0 +1,27 @@
+using GadgetCore.API;
+
+namespace RecipeMenuCore
+{
+  static class CraftTypeHelper
+  {
+    internal static bool IsCraftTypeRegisteredAsCustom(int craftType)
+    {
+      foreach (var crafter in Core.pageCustomCrafterInfoLists.Keys)
+      {
+        if (craftType == MenuRegistry.Singleton[crafter].GetID())
+          return true;
+      }
+      return false;
+    }
+
+    internal static string GetNameFromCraftTypeRegisteredAsCustom(int craftType)
+    {
+      foreach (var crafter in Core.pageCustomCrafterInfoLists.Keys)
+      {
+        if (craftType == MenuRegistry.Singleton[crafter].GetID())
+          return crafter;
+      }
+      return null;
+    }
+  }
+}

+ 8 - 0
Patches/Patch_CraftMenuInfo_AllowQuickCrafting.cs

@@ -20,6 +20,14 @@ namespace RecipeMenuCore.Patches
         __result = Core.pageUniversalCrafterInfoList.Count > 0;
         return false;
       }
+      foreach(var crafter in Core.pageCustomCrafterInfoLists.Keys)
+      {
+        if (__instance.GetRegistryName() == crafter)
+        {
+          __result = Core.pageCustomCrafterInfoLists[crafter].Count > 0;
+          return false;
+        }
+      }
       return true;
     }
   }

+ 10 - 1
Patches/Patch_GameScript_HoverRecipeSelect.cs

@@ -22,7 +22,8 @@ namespace RecipeMenuCore.Patches
       if (!Core.settingUseDialog)
         return true;
 
-      if (___craftType == 0 || ___craftType == 1 || ___craftType == MenuRegistry.Singleton["Gadget Core:Crafter Menu"].GetID())
+      if (___craftType == 0 || ___craftType == 1 || ___craftType == MenuRegistry.Singleton["Gadget Core:Crafter Menu"].GetID()
+        || CraftTypeHelper.IsCraftTypeRegisteredAsCustom(___craftType))
       {
         if (id >= 12 || ___recipeLock[id].active)
         {
@@ -122,6 +123,14 @@ namespace RecipeMenuCore.Patches
         return Core.pageUltimateForgeInfoList[curRecipePage - 6].GetRecipePageEntries()[index].ItemIdBase;
       else if (craftType == MenuRegistry.Singleton["Gadget Core:Crafter Menu"].GetID())
         return Core.pageUniversalCrafterInfoList[curRecipePage].GetRecipePageEntries()[index].ItemIdBase;
+      else if (CraftTypeHelper.IsCraftTypeRegisteredAsCustom(craftType))
+      {
+        string s = CraftTypeHelper.GetNameFromCraftTypeRegisteredAsCustom(craftType);
+        if (!Core.pageCustomCrafterInfoLists[s][curRecipePage].GetRecipePageEntries()[index].IsReverse)
+          return Core.pageCustomCrafterInfoLists[s][curRecipePage].GetRecipePageEntries()[index].ItemIdBase;
+        else
+          return Core.pageCustomCrafterInfoLists[s][curRecipePage].GetRecipePageEntries()[index].ItemIds[0];
+      }
 
       else if (craftType == 0 && curRecipePage < 6 && Core.pageGearForgeInfoListVanilla[curRecipePage] != null)
         return Core.pageGearForgeInfoListVanilla[curRecipePage].GetRecipePageEntries()[index].ItemIdBase;

+ 5 - 0
Patches/Patch_GameScript_RecipeDown.cs

@@ -22,6 +22,11 @@ namespace RecipeMenuCore.Patches
         pages = 6 + Core.pageUltimateForgeInfoList.Count;
       else if (___craftType == MenuRegistry.Singleton["Gadget Core:Crafter Menu"].GetID())
         pages = Core.pageUniversalCrafterInfoList.Count;
+      else if (CraftTypeHelper.IsCraftTypeRegisteredAsCustom(___craftType))
+      {
+        string s = CraftTypeHelper.GetNameFromCraftTypeRegisteredAsCustom(___craftType);
+        pages =  Core.pageCustomCrafterInfoLists[s].Count;
+      }
 
       ___curRecipePage = (___curRecipePage + pages - 1) % pages;
       __instance.RefreshRecipe();

+ 5 - 0
Patches/Patch_GameScript_RecipeUp.cs

@@ -22,6 +22,11 @@ namespace RecipeMenuCore.Patches
         pages = 6 + Core.pageUltimateForgeInfoList.Count;
       else if (___craftType == MenuRegistry.Singleton["Gadget Core:Crafter Menu"].GetID())
         pages = Core.pageUniversalCrafterInfoList.Count;
+      else if (CraftTypeHelper.IsCraftTypeRegisteredAsCustom(___craftType))
+      {
+        string s = CraftTypeHelper.GetNameFromCraftTypeRegisteredAsCustom(___craftType);
+        pages = Core.pageCustomCrafterInfoLists[s].Count;
+      }
 
       ___curRecipePage = (___curRecipePage + 1) % pages;
       __instance.RefreshRecipe();

+ 16 - 1
Patches/Patch_GameScript_RefreshRecipe.cs

@@ -33,6 +33,12 @@ namespace RecipeMenuCore.Patches
         __instance.txtRecipeName[0].text = string.Empty + __instance.GetRecipeName2(___curRecipePage);
         __instance.txtRecipeUnlocked[0].text = "Page " + (___curRecipePage + 1) + "/" + (Core.pageUniversalCrafterInfoList.Count);
       }
+      else if (CraftTypeHelper.IsCraftTypeRegisteredAsCustom(___craftType))
+      {
+        string s = CraftTypeHelper.GetNameFromCraftTypeRegisteredAsCustom(___craftType);
+        __instance.txtRecipeName[0].text = string.Empty + __instance.GetRecipeName2(___curRecipePage);
+        __instance.txtRecipeUnlocked[0].text = "Page " + (___curRecipePage + 1) + "/" + (Core.pageCustomCrafterInfoLists[s].Count);
+      }
       __instance.txtRecipeUnlocked[0].gameObject.GetComponent<Animation>().Play();
       __instance.txtRecipeName[0].gameObject.GetComponent<Animation>().Play();
       __instance.txtRecipeName[1].text = __instance.txtRecipeName[0].text;
@@ -40,7 +46,8 @@ namespace RecipeMenuCore.Patches
       if ((___craftType != 0 || (___curRecipePage <= 5 && Core.pageGearForgeInfoListVanilla[___curRecipePage] == null))
         && (___craftType != 1 || (___curRecipePage <= 1 && Core.pageAlchemyStationInfoListVanilla[___curRecipePage] == null))
         && (___craftType != 2 || (___curRecipePage <= 5 && Core.pageUltimateForgeInfoListVanilla[___curRecipePage] == null))
-        && (___craftType != MenuRegistry.Singleton["Gadget Core:Crafter Menu"].GetID()))
+        && (___craftType != MenuRegistry.Singleton["Gadget Core:Crafter Menu"].GetID())
+        && (!CraftTypeHelper.IsCraftTypeRegisteredAsCustom(___craftType)))
       {
         __instance.menuRecipe.GetComponent<Renderer>().material = (Material)Resources.Load(string.Concat(new object[] { "mat/r", ___curRecipePage, "t", ___craftType }));
       }
@@ -74,6 +81,14 @@ namespace RecipeMenuCore.Patches
           __instance.txtRecipeName[1].text = __instance.txtRecipeName[0].text;
           __instance.menuRecipe.GetComponent<Renderer>().material = page.Mat;
         }
+        else if (CraftTypeHelper.IsCraftTypeRegisteredAsCustom(___craftType))
+        {
+          string s = CraftTypeHelper.GetNameFromCraftTypeRegisteredAsCustom(___craftType);
+          var page = Core.pageCustomCrafterInfoLists[s][___curRecipePage];
+          __instance.txtRecipeName[0].text = page.Title;
+          __instance.txtRecipeName[1].text = __instance.txtRecipeName[0].text;
+          __instance.menuRecipe.GetComponent<Renderer>().material = page.Mat;
+        }
       }
       __instance.RefreshRecipeUnlock();
       return false;

+ 32 - 2
Patches/Patch_GameScript_RefreshRecipeUnlock.cs

@@ -25,7 +25,8 @@ namespace RecipeMenuCore.Patches
     public static bool Prefix(GameScript __instance, int ___craftType, int ___curRecipePage, GameObject ___ultLocksObj, GameObject ___recipeButtons,
       GameObject[] ___recipeLock, GameObject[] ___ultLocks, int[,] ___ultLocksUnlocked)
     {
-      if (___craftType == 0 || ___craftType == 1 || ___craftType == MenuRegistry.Singleton["Gadget Core:Crafter Menu"].GetID())
+      if (___craftType == 0 || ___craftType == 1 || ___craftType == MenuRegistry.Singleton["Gadget Core:Crafter Menu"].GetID()
+        || CraftTypeHelper.IsCraftTypeRegisteredAsCustom(___craftType))
       {
         for (int i = 0; i < 12; i++)
         {
@@ -80,7 +81,7 @@ namespace RecipeMenuCore.Patches
         }
         return false;
       }
-      else if (___craftType == 1 && (___curRecipePage >=2  || Core.pageAlchemyStationInfoListVanilla[___curRecipePage] != null))
+      else if (___craftType == 1 && (___curRecipePage >= 2 || Core.pageAlchemyStationInfoListVanilla[___curRecipePage] != null))
       {
         ___ultLocksObj.SetActive(false);
         ___recipeButtons.SetActive(true);
@@ -168,6 +169,35 @@ namespace RecipeMenuCore.Patches
         }
         return false;
       }
+      else if (CraftTypeHelper.IsCraftTypeRegisteredAsCustom(___craftType))
+      {
+        string s = CraftTypeHelper.GetNameFromCraftTypeRegisteredAsCustom(___craftType);
+        ___ultLocksObj.SetActive(false);
+        ___recipeButtons.SetActive(true);
+        var page = Core.pageCustomCrafterInfoLists[s][___curRecipePage];
+        for (int i = 0; i < 12; i++)
+        {
+          if (page.GetRecipePageEntries().Length > i)
+          {
+            var revers = page.GetRecipePageEntries()[i].IsReverse;
+            int itemID = page.GetRecipePageEntries()[i].ItemIds[revers ? 0 : 3];
+            if (((CraftMenuInfo)MenuRegistry.Singleton[s]).IsRecipeUnlocked(itemID))
+              ___recipeLock[i].SetActive(false);
+            else
+            {
+              if (page.GetRecipePageEntries()[i].AllwaysShowInput)
+                ___recipeLock[i].GetComponent<Renderer>().material = recipeLockSmall;
+              ___recipeLock[i].SetActive(true);
+            }
+          }
+          else
+          {
+            ___recipeLock[i].SetActive(false);
+            ___recipeButtons.transform.GetChild(i).gameObject.SetActive(false);
+          }
+        }
+        return false;
+      }
       return true;
     }
   }

+ 82 - 5
Patches/Patch_GameScript_Update.cs

@@ -51,6 +51,11 @@ namespace RecipeMenuCore.Patches
                     __instance.StartCoroutine(QuickCraft(__instance, ___curRecipePage, slotID, ___craftType, ___inventory, ___craft));
                     acted = true;
                   }
+                  else if (CraftTypeHelper.IsCraftTypeRegisteredAsCustom(___craftType))
+                  {
+                    __instance.StartCoroutine(QuickCraft(__instance, ___curRecipePage, slotID, ___craftType, ___inventory, ___craft));
+                    acted = true;
+                  }
                 }
               }
             }
@@ -114,13 +119,35 @@ namespace RecipeMenuCore.Patches
                 price.Add(itemID);
             }
           }
-          if (craftingItemID == 0 
-            || !(___craftType == MenuRegistry.Singleton["Gadget Core:Crafter Menu"].GetID()
-            ? ((CraftMenuInfo)MenuRegistry.Singleton["Gadget Core:Crafter Menu"]).IsRecipeUnlocked(craftingItemID)
-            : __instance.RecipeCraftedAlready(craftingItemID, 0) ))
+          else if (CraftTypeHelper.IsCraftTypeRegisteredAsCustom(___craftType))
           {
-            yield break;
+            string s = CraftTypeHelper.GetNameFromCraftTypeRegisteredAsCustom(___craftType);
+            var recipePageEntry = Core.pageCustomCrafterInfoLists[s][___curRecipePage].GetRecipePageEntries()[slot];
+            if (recipePageEntry.IsReverse)
+            {
+              QuickCraftReverse(__instance, ___curRecipePage, slot, ___craftType, ___inventory, ___craft);
+              yield break;
+            }
+            craftingItemID = recipePageEntry.ItemIdBase;
+            craftingItemAmount = recipePageEntry.MinAmount + Random.Range(0, 1 + recipePageEntry.MaxBonusAmount);
+            for (int i = 0; i < recipePageEntry.ItemIdExtension.Length; i++)
+            {
+              var itemID = recipePageEntry.ItemIdExtension[i];
+              if (itemID > 0)
+                price.Add(itemID);
+            }
           }
+          if (craftingItemID == 0)
+            yield break;
+          if ((___craftType == 0 || ___craftType == 1 || ___craftType == 2 || ___craftType == 3)
+            && !__instance.RecipeCraftedAlready(craftingItemID, 0))
+            yield break;
+          if (___craftType == MenuRegistry.Singleton["Gadget Core:Crafter Menu"].GetID()
+            && !((CraftMenuInfo)MenuRegistry.Singleton["Gadget Core:Crafter Menu"]).IsRecipeUnlocked(craftingItemID))
+            yield break;
+          if (CraftTypeHelper.IsCraftTypeRegisteredAsCustom(___craftType)
+            && !((CraftMenuInfo)MenuRegistry.Singleton[CraftTypeHelper.GetNameFromCraftTypeRegisteredAsCustom(___craftType)]).IsRecipeUnlocked(craftingItemID))
+            yield break;
           for (int i = 0; i < price.Count; i++)
           {
             int itemSlotPlayerInventory = __instance.ItemExistsSlot(price[i]);
@@ -196,5 +223,55 @@ namespace RecipeMenuCore.Patches
       }
       yield break;
     }
+
+    private static void QuickCraftReverse(GameScript __instance, int ___curRecipePage, int slot, int ___craftType, Item[] ___inventory, Item[] ___craft)
+    {
+      List<KeyValuePair<int, int>> craftingItems = new List<KeyValuePair<int, int>>();
+      int priceId;
+
+      if (CraftTypeHelper.IsCraftTypeRegisteredAsCustom(___craftType))
+      {
+        string s = CraftTypeHelper.GetNameFromCraftTypeRegisteredAsCustom(___craftType);
+        var recipePageEntry = Core.pageCustomCrafterInfoLists[s][___curRecipePage].GetRecipePageEntries()[slot];
+        craftingItems.Add(new KeyValuePair<int, int>(recipePageEntry.ItemIds[1], recipePageEntry.MinAmounts[1] + Random.Range(0, 1 + recipePageEntry.MaxBonusAmounts[1])));
+        craftingItems.Add(new KeyValuePair<int, int>(recipePageEntry.ItemIds[2], recipePageEntry.MinAmounts[2] + Random.Range(0, 1 + recipePageEntry.MaxBonusAmounts[2])));
+        craftingItems.Add(new KeyValuePair<int, int>(recipePageEntry.ItemIds[3], recipePageEntry.MinAmounts[3] + Random.Range(0, 1 + recipePageEntry.MaxBonusAmounts[3])));
+        priceId = recipePageEntry.ItemIds[0];
+      }
+      else return;
+
+      if (!((CraftMenuInfo)MenuRegistry.Singleton[CraftTypeHelper.GetNameFromCraftTypeRegisteredAsCustom(___craftType)]).IsRecipeUnlocked(priceId))
+        return;
+
+      var invPos = __instance.ItemExistsSlot(priceId);
+      if (invPos != -1)
+      {
+        Object.Instantiate(Resources.Load("clickBurst"), new Vector3(Camera.main.ScreenToWorldPoint(Input.mousePosition).x, Camera.main.ScreenToWorldPoint(Input.mousePosition).y, 0f), Quaternion.identity);
+        __instance.GetComponent<AudioSource>().PlayOneShot((AudioClip)Resources.Load("Au/create"), Menuu.soundLevel / 10f);
+
+        foreach (var item in craftingItems)
+        {
+          if (item.Key > 0)
+          {
+            ItemInfo itemInfo = ItemRegistry.GetItem(item.Key);
+            ItemType slotItemType = itemInfo != null ? (itemInfo.Type & (ItemType.EQUIP_MASK | ItemType.TYPE_MASK)) : ItemRegistry.GetDefaultTypeByID(item.Key);
+            if ((slotItemType & ItemType.NONSTACKING) == ItemType.STACKING)
+            {
+              GadgetCoreAPI.DropItem(InstanceTracker.PlayerScript.transform.position, new Item(item.Key, item.Value, 0, 0, 0, new int[3], new int[3]));
+            }
+            else
+            {
+              for (int i = 0; i < item.Value; i++)
+                GadgetCoreAPI.DropItem(InstanceTracker.PlayerScript.transform.position, new Item(item.Key, 1, 0, __instance.GetRandomTier(), 0, new int[3], new int[3]));
+            }
+          }
+        }
+
+        Core.logger.LogConsole(___inventory[invPos].q);
+        ___inventory[invPos].q--;
+        __instance.RefreshSlot(invPos);
+      }
+      return;
+    }
   }
 }

+ 1 - 1
RecipeMenuCore.cs

@@ -11,7 +11,7 @@ namespace RecipeMenuCore
   [Gadget("RecipeMenuCore", RequiredOnClients: false)]
   public class RecipeMenuCore : Gadget<RecipeMenuCore>
   {
-    public const string MOD_VERSION = "1.8"; // Set this to the version of your mod.
+    public const string MOD_VERSION = "2.0"; // Set this to the version of your mod.
     public const string CONFIG_VERSION = "1.0"; // Increment this whenever you change your mod's config file.
 
     protected override void LoadConfig()