Shared Dictionary causes duplicate items

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By pbij

I have a hotbar that shares the first few slots of a dictionary with my main inventory. The problem is that when an item is moved to an empty slot, like merging two items together:

Inventory Before Merge

Inventory After Merge

In the hotbar, the original item stays there and never goes away. But it’s not really there, just its image is leftover:

Hotbar before merge
Hotbar after merge

Here’s my code:
For the inentory:

extends Node2D

const SLOT_CLASS = preload("res://UI/SlotScript.gd")

onready var inventorySlots = $InventoryContainer

var holdingItem = null

var tempItem
var stackSize
var ableToAdd


func _ready():
	var slots = inventorySlots.get_children()
	for i in range(slots.size()):
#		slots[i].connect("gui_input", self, "_slot_gui_input", [slots[i]])
		slots[i].slotIndex = i
		slots[i].slotType = SLOT_CLASS.SLOT_TYPE.INVENTORY
	
	_initialize_inventory()


func _initialize_inventory():
	var slots = inventorySlots.get_children()
	for i in range(slots.size()):
		if PlayerInventoryScript.inventory.has(i):
			slots[i]._initialize_item(PlayerInventoryScript.inventory[i][0], PlayerInventoryScript.inventory[i][1])

For the hotbar:

extends Node2D

const SLOT_CLASS = preload("res://UI/SlotScript.gd")

onready var inventorySlots = $HotbarContainer

var holdingItem = null

var tempItem
var stackSize
var ableToAdd


func _process(_delta):
	var slots = inventorySlots.get_children()
	for i in range(slots.size()):
#		slots[i].connect("gui_input", self, "_slot_gui_input", [slots[i]])
		slots[i].slotIndex = i
		slots[i].slotType = SLOT_CLASS.SLOT_TYPE.HOTBAR
	
	_initialize_inventory()


func _initialize_inventory():
	var slots = inventorySlots.get_children()
	for i in range(slots.size()):
		if PlayerInventoryScript.inventory.has(i):
			slots[i]._initialize_item(PlayerInventoryScript.inventory[i][0], PlayerInventoryScript.inventory[i][1])

For the dictionary:

var inventory = {
	0: ["Axe", 1],
	1: ["Tree Branch", 5],
	2: ["Weeds", 98],
	3: ["Weeds", 18],
	4: ["Weeds", 45],
	5: ["Rock", 2],
	6: ["Rock", 19],
	}

And, for the slots:

extends Panel

onready var itemScene = find_node("ItemScript.gd")
var defaultTexture = preload("res://UI/PeriwinkleBtn.png")
var emptyTexture = preload("res://UI/EmptyPeriwinkleBtn.png")
var selectedTexture = preload("res://UI/HotbarSlot.png")
var itemClass = preload("res://Items/ItemScene.tscn")

var defaultStyle: StyleBoxTexture = null
var emptyStyle: StyleBoxTexture = null
var selectedStyle: StyleBoxTexture = null

var item = null

var inventoryNode
var slotIndex
var slotType

enum SLOT_TYPE{
	HOTBAR = 0,
	INVENTORY}


func _ready():
	defaultStyle = StyleBoxTexture.new()
	emptyStyle = StyleBoxTexture.new()
	selectedStyle = StyleBoxTexture.new()
	defaultStyle.texture = defaultTexture
	emptyStyle.texture = emptyTexture
	selectedStyle.texture = selectedTexture
	
#	if randi() % 2 == 0:
#		item = itemClass.instance()
#		add_child(item) 
	
	_refresh_style()


func _refresh_style():
	if SLOT_TYPE.HOTBAR == slotType and PlayerInventoryScript.activeItemSlot == slotIndex:
		set('custom_styles/panel', selectedStyle)
	elif item == null:
		set('custom_styles/panel', emptyStyle)
	else:
		set('custom_styles/panel', defaultStyle)


func _pick_from_slot():
	remove_child(item)
	inventoryNode = find_parent("UserInterfaceGroup")
	inventoryNode.add_child(item)
	item = null
	_refresh_style()


func _put_into_slot(newItem):
	item = newItem
	item.position = Vector2(0,0)
	inventoryNode = find_parent("UserInterfaceGroup")
	inventoryNode.remove_child(item)
	add_child(item)
	_refresh_style()


func _initialize_item(itemName, itemQuantity):
	if item == null:
		item = itemClass.instance()	
		add_child(item)
		#print(itemQuantity)
		item._set_item(itemName, itemQuantity)
		item._set_item(itemName, itemQuantity)
	else:
		pass
		item._set_item(itemName,itemQuantity)
	
	_refresh_style()

Any input would be appreciated.

:bust_in_silhouette: Reply From: Inces

To be honest I didn’t read all these code
Dictionary works fine, You just need a method to let UI know whenever a change occured in it. Design some kind of signal, that will fire when dictionary is changed, connect it to both bars, and let them use the same method to visualize changes.
Hint : signals introduced and kept in Autoload script don’t need hard references to be connected

Thank you! I’ll see what I come up with and write what works.

pbij | 2022-09-12 15:15

Yeah :slight_smile:
Remember to start designing it on dictionary, not on Inventory or UI bars. They all share this one variable, so it will require much less code this way.
good luck :slight_smile:

Inces | 2022-09-12 15:40