Problem with Recursion in combinable resources

Godot Version

4.1.2.stable

Question

I’m getting an Recursion error when trying to set up combinable items, which are custom resources. Here’s my approach:

Item A: can be combined with item B to create item C.
Item B: can be combined with item A to create item C.

I’m setting the reference to which item an item can be combined with inside of it.
When I assign item B to be the combinable item within item A, it works.
When i then go to assign item A to be the combinable item within item B, Godot throws the Recursion error.

How can I get around this? Or is my approach wrong?
Thanks in advance!

Not enough info. Show some code about how this is done.

1 Like

Here’s an excerpt of the item resource. I’m just storing references here:

extends Resource
class_name InventoryItemPD

## The item that this item combines with
@export var target_item_combine : InventoryItemPD = null
## The item that gets created when this item is combined with the one above.
@export var resulting_item : InventorySlotPD = null

And here’s the truncated region of my inventory system script that handles combining items:

func drop_single_slot_data(grabbed_slot_data: InventorySlotPD, index: int) -> InventorySlotPD:
   var slot_data = inventory_slots[index]

   [... some other if-statements]
   # Check if grabbed item is a combinable AND check if slot item is the target combine item:
	elif grabbed_slot_data.inventory_item.item_type == 2 and slot_data.inventory_item == grabbed_slot_data.inventory_item.target_item_combine :
		# Reduce/destroy both items.
		remove_slot_data(slot_data)
		grabbed_slot_data.quantity -= 1
		
		# Add resulting item to inventory:
		pick_up_slot_data(grabbed_slot_data.inventory_item.resulting_item)
		
	inventory_updated.emit(self)

Hope this helps/is enough for now. Can otherwise just link to the Github, though it’s currently set to private.

Yeah, that truncated source doesn’t help, sorry.
Recursion means you are calling a function that somehow calls itself unconditionally, none of what you posted is enough to know.
At least post the entire inventory handler code. That’s the bare minimum.

1 Like

Okay, appreciate the hint withe function, that gives me something to look into.
I’ve set the repository public just now. It’s prob not the cleanest code, but you can view it here: COGITO on Github

The item resource script is here: InventoryItemPD
The script that handles item combination is here: InventoryPD.gd

Might be wrong, but it looks like this might also be running into the thing where Godot doesn’t like it when two resources reference each other, which is a known issue with proposals on how to fix, Though I may be wrong

2 Likes

On one hand, I cloned your repo and tried it and I didn’t get an error when combining items.
On the other, I think you may be confusing the purpose of the Resource class?
It is for things that can be read from a file and instantiated, should not be an actual game object when running.
Either way, I cannot reproduce the issue with your code, sorry.

1 Like

@Efi : I really appreciate you taking the effort. :raised_hands:
Maybe to clarify a bit using the repo: In game, the combining of items works when using Diamond Half A with Diamond Half B, as that reference is set on Diamond Half A.
But combining in the “other direction”, Diamond Half B with Diamond Half A currently doesn’t work, as the Godot Editor doesn’t let me set the reference to Diamond Half A within the Diamond Half B item resource without giving me the “Recursion detected.” error.

I have an idea for a workaround against this, but it’ll make the inventory system a bit less intuitive so I wanted to avoid it.

@intangiblematter : Thanks for this, yeah this seems related. Gonna read up on this to understand whats happening and how to hopefully avoid it.

Just to close this out:
I’ve worked around this issue by referring to a resource property instead of the resource itself (ie checking for the name of an item (string) another item can be combined with, instead of the item resource).

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.