Godot Version
4.3
Question
I am trying to make my inventory script more modular to support other inventories like a hot bar and chests. My current inventory script has been working perfectly fine until I tried using the same script to make my hot bar.
I thought I could use the same script in a separate scene to create a separate inventory. But since i add the items in the script it adds it to every instance of the script.
I tried changing the inventory to an array to make it more modular but now I dont know how to add the items from the array to my grid based inventory. As well as make each instance of the inventory script its own inventory.
class_name Inventory
extends Control
@export var inventory_size: int
@export var slotSize: int = 48
@onready var grid = get_node("Grid")
@export var inventory: Array[Item_Data] = []
func _ready() -> void:
inventory.resize(inventory_size)
for i in inventory:
var slot = InventorySlot.new()
slot.init(Item_Data.ItemType.EMPTY, Vector2(slotSize, slotSize))
grid.add_child(slot)
add_item("Sword")
func add_item(itemName:String) -> void:
var item = InventoryItem.new()
item.init(Game.items[itemName])
if item.data.stackable:
for i in inventory.size():
if grid.get_child(i).get_child_count() > 0:
if grid.get_child(i).get_child(0).data == item.data:
#Update the counter
grid.get_child(i).get_child(0).data.count += 1
#Update label counter
grid.get_child(i).get_child(0).get_child(0).text = str(grid.get_child(i).get_child(0).data.count)
break
else:
grid.get_child(i).add_child(item)
break
else:
for i in inventory.size():
if grid.get_child(i).get_child_count() == 0:
grid.get_child(i).add_child(item)
break
``
Here is the script where I hold the item data in the inventory
class_name InventoryItem
extends TextureRect
@export var data: Item_Data
func _ready() -> void:
if data:
expand_mode = TextureRect.EXPAND_IGNORE_SIZE
stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED
texture = data.itemTexture
tooltip_text = "Name: %s\n %s\n" % [data.itemName, data.description]
if data.stackable:
var label = Label.new()
label.text = str(data.count)
label.position = Vector2(24, 16)
add_child(label)
label.show()
if data.count <= 1:
label.hide()
func init(d: Item_Data) -> void:
data = d
func _get_drag_data(at_position: Vector2) -> Variant:
set_drag_preview(make_drag_preview(at_position))
return self
func make_drag_preview(at_position: Vector2) -> Control:
var t := TextureRect.new()
t.texture = self.texture
t.expand_mode = TextureRect.EXPAND_IGNORE_SIZE
t.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED
t.custom_minimum_size = self.size
t.modulate.a = 0.5
t.position = Vector2(-at_position)
var c := Control.new()
c.add_child(t)
return c
and here is where I keep the data for the inventory slots
class_name InventorySlot
extends PanelContainer
var slotType: Item_Data.ItemType
func _ready() -> void:
self.process_mode = Node.PROCESS_MODE_ALWAYS
func init(t: Item_Data.ItemType, cms: Vector2) -> void:
slotType = t
custom_minimum_size = cms
func _can_drop_data(at_position: Vector2, data: Variant) -> bool:
if data is InventoryItem:
if slotType == Item_Data.ItemType.EMPTY:
#Check if item in slot
if get_child_count() == 0:
return true
else:
if slotType == data.get_parent().slotType:
return true
return get_child(0).data.type == data.data.type
else:
return data.data.type == slotType
else:
return false
func _drop_data(at_position: Vector2, data: Variant) -> void:
if get_child_count() > 0:
var item := get_child(0)
if item == data:
return
if item.data == data.data:
if item.data.stackable:
#Update the counter
item.data.count += 1
#Show hidden counter
item.get_child(0).show()
#Update label counter
item.get_child(0).text = str(item.data.count)
#Dragged item moves to new slot
data.reparent(self)
#Clear dragged item
data.queue_free()
item.reparent(data.get_parent())
data.reparent(self)
func _gui_input(event: InputEvent) -> void:
if event is InputEventMouseButton:
if (event.button_index == 2) and (event.button_mask == 0):
if get_child_count() > 0:
if (get_child(0).data.type == Item_Data.ItemType.CONSUMABLE):
Game.healPlayer(get_child(0).data.healAmount)
get_child(0).data.count -= 1
get_child(0).get_child(0).text = str(get_child(0).data.count)
if get_child(0).data.count <= 0:
get_child(0).queue_free()
I guess I’m asking if I can adapt this to be more modular or if i need to rebuild a new inventory system. If so is there a better design pattern to for a modular inventory system