How to add recipes to a Crafter during runtime?

Fjord

New member
Hi,
I tried the following: For every recipe my Player can get I make an Item which holds a recipe as an attribute.
Before I trigger the crafter I'll find every Item from the category "Crafting Recipe" in the players inventory and then get the Recipe-value of those items. Those i want to add to the recipes of the crafter but somehow it doesn't work.

What am I doing wrong? (Or is there a even a simpler way than this?)

1622990818129.png

I am puzzled about the two DebugLogs inside the forloop: The first is giving me the name of the craftingRecipe, so it is not null. But when I check the first entry of the MiscellaneousRecipes-array after adding this Recipe it is null.

And indeed, using this method before I open the crafter leads to an empty first field above the items I can craft (the items I added as default recipes to the crafter in the Inspector.)

Thanks for your help :)
 
Sorry for the confusion.
MiscellaneousRecipes is the field in the inspector. The elements in that array are added to the recipe list only during Initialize.

I think you are looking for the SetRecipes function instead. This assigns the recipes directly to the list of recipes that will be used in the Crafting UI.

These are the functions that directly affect the crafting recipe list:
Code:
/// <summary>
/// Add a recipe to the list of recipes.
/// </summary>
/// <param name="recipe">The recipe to add.</param>
public virtual void AddRecipe(CraftingRecipe recipe)
{
    if (m_CraftingRecipes.Contains(recipe)) { return; }
    m_CraftingRecipes.Add(recipe);
}
/// <summary>
/// Remove a recipe.
/// </summary>
/// <param name="recipe">The recipe to remove.</param>
public virtual void RemoveRecipe(CraftingRecipe recipe)
{
    if (m_CraftingRecipes.Contains(recipe)) { return; }
    m_CraftingRecipes.Remove(recipe);
}
/// <summary>
/// Set all the recipes.
/// </summary>
/// <param name="recipes">The recipes to set.</param>
public virtual void SetRecipes(ListSlice<CraftingRecipe> recipes)
{
    m_CraftingRecipes.Clear();
    for (int i = 0; i < recipes.Count; i++) {
        m_CraftingRecipes.Add(recipes[i]);
    }
}

Note: ListSlice is a custom type we created, you can pass in both Arrays and Lists as parameter.
 
And why is AddRecipe not working? This was my first approach. I will now try it with SetRecipes.

EDIT:
Ah no. I see now that SetRecipes deletes every CraftingRecipe befpre adding the new ones. I want to keep those I inserted in the editor and just add some new. So the question remains. What could be the reason that AddRecipes is not working in my case?

1623061696019.png
 
Last edited:
Yes, set recipes removes the one you set in the inspector.

You can add them back using a for loop
(Untested code):
Code:
for (int i = 0; i < m_MiscellaneousRecipes.Value.Count; i++) {
        m_Crafter.AddRecipe(m_MiscellaneousRecipes.Value[i]);
    }

Or you can keep a List of all your crafting recipes in your custom script and set it each time.


When that AddRecipes does not work, what do you mean? If Nothing is happening my guess is that you are drawing the craft menu after you are setting the recipes.
When do you call your custom function AddForgeRecipes?
 
Mh okay that must be the mistake. I call AddForgeRecipe first and then I call the Function to open the crafter. I also tried to do it the other way around but the result is the same: I see no further recipe in the opened crafter menu. When do I have to call the AddRecipe function?
 
before you open the UI.
I can't think of a reason why it wouldn't work.

I'm actually working the Crafting for the Adventure Kit right now and I wanted to do something similar to what you described.
I created a component that overrides the Crafter component. such that I can edit the GetRecipes function. This I can add the recipes whenever I Draw the UI

I'm attaching the script I'm using below.

It works for me, either use that, or compare to see what you are doing differently
 

Attachments

  • InventoryItemsCrafter.cs
    3.5 KB · Views: 8
Thanks for sharing the file! I see you are using CraftingRecipe while I am using DynamicCraftingRecipe. What is the difference? I found only DynamicCraftingRecipe as a type so now I use this type to add a recipe to an item.
 
I did not understand your answers fully. Your are saying "If Nothing is happening my guess is that you are drawing the craft menu after you are setting the recipes." What do you mean by "drawing the craft menu"? So I have to call my function between the drawing of the crafting menu and before I open the UI? In my logic I can call the AddForgeRecipe-method at any time because it changes a list of the recipes my crafter will show once i open it through the CraftingMenuOpener. Maybe this is my mistake and once I know what the "drawing the craft menu"-event is I can fix this.
 
DynamicCraftingRecipe is used to get the Crafting Recipe by name at runtime. It was added to reduce errors when people were duplicating stuff from the demo. Since the demo has a different Inventory database the recipes, categories and definition would throw errors. Having the Dynamic type lets us swap out the object with one with the same name that actually exists in the current database.
It won't matter much which one you use, either should work.

If you open the Craft Menu source code you'll see a function called "DrawRecipes" this happens when the Menu is opened and when the Inventory is updated.
If you set the recipes before that I can't think of a reason why it wouldn't.

If I were you I would try adding some Debug.Logs in a few places within the "Crafter" script, to make sure you are indeed adding your recipes in the list. Perhaps you are adding nulls or you are adding duplicates by mistake. Those won't be added in the recipe list.
 
very frustrating. I could not figure out why it is not working. A Debug.Log shows me the correct name of the Recipe I expect. Now I tried your script and I get a an error at line 96: NullReferenceException: Object reference not set to an instance of an object

It is this line: if (!m_ItemCategoryWithRecipe.Value.InherentlyContains(item)) { return; }

Any idea what could be the problem here?

EDIT: I commented the line out and now it is working as expected. Thanks for your help!
 
Last edited:
Great!
I'll change that line to make it optional.
Code:
if (m_ItemCategoryWithRecipe.HasValue && !m_ItemCategoryWithRecipe.Value.InherentlyContains(item)) { return; }

Essentially that line is checking that your item is part of an ItemCategory specified in the inspector.
 
Top