Godot Version
Godot Engine v4.2.2.stable.official
Question
I am trying to transfer item from player inventory to chest inventory. Item gets transferred by selecting slot in player inventory and pressing ‘enter’:
When I try to transfer item from chest inventory to player inventory it gets weird:
If item is still in player inventory - it gets transferred (stacks)
If item has to be transferred to a empty slot I get in my output:
‘Error: Null item’
Could anyone please help me out? I’ve been trying to figure this out for a while with no success.
Code
extends Resource
class_name Inventory
signal update
@export var slots: Array[InventorySlot]
func insert(item: InventoryItem):
# Stack item to the same slot
var item_slots = slots.filter(func(slot): return slot.item == item)
if !item_slots.is_empty():
item_slots[0].amount += 1
else:
# Add item to the new slot
var empty_slots = slots.filter(func(slot): return slot.item == null)
if !empty_slots.is_empty():
empty_slots[0].item = item
empty_slots[0].amount = 1
update.emit()
func remove_item(item: InventoryItem):
# Reduce item amount / remove item in slot
for slot in slots:
if slot.item != null and slot.item.name == item.name:
if slot.amount > 1:
slot.amount -= 1
else:
slot.item = null
slot.amount = 0
update.emit()
return
print('Item not found in inventory')
### Inventory_ui.gd
extends Control
@onready var inventory: Inventory = preload("res://scenes/inventory/player_inventory.tres")
@onready var chest_inventory: Chest_inventory = preload("res://scenes/inventory/chest/chest_inventory.tres")
@onready var chest_ui = $"../Chest_UI"
@onready var slots: Array = $inventory_background/inventory_slots.get_children()
@onready var is_open = false
func _ready():
# Get signal from func in backend inventory
inventory.update.connect(update_slots)
chest_inventory.update.connect(update_slots)
update_slots()
close()
func _process(_delta):
inputs()
func inputs():
# Arrow up to check inventory slots
if Input.is_action_just_pressed("nav_up"):
print('Slot1: ', inventory.slots[0].item, ' item name: ', inventory.slots[0].item.name)
# 'ENTER' to transfer selected items from inventory
if is_open and chest_ui.is_open and Input.is_action_just_pressed("enter"):
var selected_slot = null
for i in range(slots.size()):
if slots[i].is_selected:
selected_slot = inventory.slots[i]
transfer_item(selected_slot.item)
# 'E' to open inventory
if Input.is_action_just_pressed("use"):
toggle_inventory()
chest_ui.close()
# 'ESC' to close all inventories
if Input.is_action_just_pressed("esc"):
close()
chest_ui.close()
func transfer_item(item: InventoryItem):
if item == null:
print('Error: Null item')
# Transfer items to chest inventory from player inventory
if chest_ui.is_open:
# Check if chest inventory can accept items
chest_inventory.transfer_item(item)
inventory.remove_item(item)
update_slots()
chest_ui.update_slots()
func update_slots():
for i in range(min(inventory.slots.size(), slots.size())):
slots[i].update(inventory.slots[i])
# Funcs to open/close inventory
func toggle_inventory():
if is_open:
close()
else:
open()
func close():
# Remove selected slots
for i in range(slots.size()):
if slots[i].is_selected:
slots[i].item_selected.visible = false
# Close inventory
visible = false
is_open = false
func open():
# Open inventory
visible = true
is_open = true
### Chest_inventory.gd
extends Resource
class_name Chest_inventory
signal update
@export var slots: Array[InventorySlot]
func transfer_item(item: InventoryItem):
# Stack item to the same slot
var item_slots = slots.filter(func(slot): return slot.item == item)
if !item_slots.is_empty():
item_slots[0].amount += 1
else:
# Add item to the new slot
var empty_slots = slots.filter(func(slot): return slot.item == null)
if !empty_slots.is_empty():
empty_slots[0].item = item
empty_slots[0].amount = 1
update.emit()
func remove_item(item: InventoryItem):
# Reduce item amount / remove item in slot
for slot in slots:
if slot.item == item:
if slot.amount > 1:
slot.amount -= 1
else:
slot.item = null
slot.amount = 0
update.emit()
return
print('Item not found in inventory')
###Chest_ui.gd
extends Control
@onready var chest_inventory: Chest_inventory = preload("res://scenes/inventory/chest/chest_inventory.tres")
@onready var inventory: Inventory = preload("res://scenes/inventory/player_inventory.tres")
@onready var inventory_ui = $"../Inventory_UI"
@onready var slots: Array = $inventory_background/inventory_slots.get_children()
@onready var is_open = false
func _ready():
# Get signal from func in backend inventory
chest_inventory.update.connect(update_slots)
inventory.update.connect(update_slots)
update_slots()
close()
func _process(_delta):
if Input.is_action_just_pressed("enter"):
var selected_slot = null
for i in range(slots.size()):
if slots[i].is_selected:
selected_slot = inventory.slots[i]
transfer_item(selected_slot.item)
func transfer_item(item: InventoryItem):
if item == null:
print('Error: Null item')
if inventory_ui.is_open:
inventory.insert(item)
chest_inventory.remove_item(item)
update_slots()
inventory_ui.update_slots()
func update_slots():
for i in range(min(chest_inventory.slots.size(), slots.size())):
slots[i].update(chest_inventory.slots[i])
# Funcs to open/close chest UI
func toggle_chest():
if is_open:
close()
else:
open()
func close():
# Remove selected slots
for i in range(slots.size()):
if slots[i].is_selected:
slots[i].item_selected.visible = false
# Close chest
visible = false
is_open = false
func open():
# Open chest
visible = true
is_open = true