#Crafting System Kerfuffle

33 messages · Page 1 of 1 (latest)

fervent yacht
#

I'm running into some hurdles with my crafting system that I thought I would have to deal with later on, but the problems are cropping up now. I have types of recipes, ingredient, simple, complex, and custom.

Ingredient recipes are almost like substitution for real life recipes, sometimes an ingredient can change its state and act as a substitution for a simple, complex, or custom recipe. Here is a rudimentary implementation for how this works:

func _on_ChangeIngredient_pressed() -> void:
    var old_stack: ItemStack = n_hotbar_inventory.get_item_stack(0)
    var item: Item = old_stack.item
    
    if not item:
        return
    if not item.type ==  Recipe.Type.INGREDIENT:
        return
    if not recipe_data.has(item.name):
        return
    
    var recipe = recipe_data[item.name]
    
    # This is a temporary way to circumvent making a menu so that players can
    # decide how many stacks of this item they want to make.
    # We likely need to keep the math around.
    var req_quantity = recipe.requirements[item.name]
    var new_quantity: int = 1
    var remainder = old_stack.quantity % req_quantity
    if req_quantity != old_stack.quantity:
        new_quantity = (old_stack.quantity - remainder) / req_quantity
        if new_quantity == 0:
            return
    
    var dupe_stack = old_stack._duplicate(true)
    dupe_stack.quantity = new_quantity
    dupe_stack.item = recipe.product
    
    old_stack.quantity = remainder
    if remainder == 0:
        old_stack.item = null
    
    emit_signal("craft", old_stack, dupe_stack, Recipe.Type.INGREDIENT)```

This system works exactly as intended. There is a recipe dictionary, this one represents the "ingredient" type recipes. The name of the ingredient is the key, the pair/value is the recipe itself. Etc etc, the rest is pretty boilerplate edge case detection and data management.
#

Simple recipes require two ingredients, and each has a required quantity. Again, this is boilerplate, there is nothing special here.

The problem comes from this substitution system. Some ingredients have attributes, not all, and when you craft something thats a simple recipe with said ingredients, the end product is given those attributes. For clarifications, attributes for the end product is simply an array called "attributes" that's given an array with each ingredient attribute. Sometimes, its one, two, later on it could be three or more. So the issue here is that this becomes a unique object in memory, distinct from all other items, because of those attributes.

#

In otherwords, unlike me, the game dev, making a custom resource item that fills out those exact values in the editor, the player "created" their own variation of that item that is not recognizable throughout the rest of my code.

#

It has not created a ton of issues right now, in fact the work arounds are pretty simple, but its veering into spaghetti code territory and I wanna cut the head off this snake before it bites me.

#

Here is a video demonstrating how this system works

#

It also demonstrates one small way this is a problem.

#

You can see that I crafted 2 of this Cripple potion, and I can split that stack, and then stack those items together. If I craft another Cripple potion with the same ingredients, it treats it as a different item instance, and therefore, it cannot stack with the previous one.

fervent yacht
fervent yacht
#

Part of me even doubts that if I did use ResourceSaver that it would actually reflect in game. I also do not know what sort of data gymnastics I'd have to do in order to prevent cases of crafting duplicate custom items.

obtuse maple
fervent yacht
obtuse maple
#

Thats why I mentioned the string. Just use the ingredients appended together as the "type" of the item

#

Make sure and normalize everything. Ie, sort the ingredient list, then use string.Join (or whatever options you have for that)

fervent yacht
#

Heard

obtuse maple
#

And, to be clear, its the ingredients used to make 1 item that specifies the type

#

(or whatever your smallest item size is for that product)

fervent yacht
#

Got you

obtuse maple
#

Cool cool. I have a type called Symbol that is a string, and a hash. This makes it VERY fast, but if 2 things hash to the same value, it still works correctly

fervent yacht
#

Would it be worth it to make a dictionary that stores that hash as a key and pair it with the product?

obtuse maple
#

(godot's StringName might be the same thing. Im not positive though)

obtuse maple
#

Interning is the usual way to do this, which is effectively what youre mentioning

fervent yacht
#

heard, that makes the most sense to me

obtuse maple
#

(looked it up) And yes, StringName is godots version of this. So just use that

fervent yacht
#

Will work on all this tomorrow

obtuse maple
#

Fun stuff. I love crafting heavy games.

fervent yacht
#

thanks for the suggestions

obtuse maple
#

Welcomes

fervent yacht
#

its good enough and will save me having to fuck around with my inventory code for the bajillionth time

#

thanks