I'm tired of my inventory system implementation

Godot Version

4.3 stable

Question

here is a quick over view of what’s happening . i defined an inventory class extending recourse which has an array of another class called inventory slot . each slot has to properties item and quantity . item is an other defined class which holds onto texture , name and max slot quantity(to define how many of each item could be contained in one slot)

class_name Item

@export var name : String
@export var texture : Texture2D
@export var max_quantity : int

class_name InventorySlot

@export var item : Item
@export var quantity : int

var empty_space : int :
	get():
		return item.max_quantity - quantity

func is_full() -> bool:
	return quantity < item.max_quantity

func is_empty() -> bool:
	return quantity<=0 or !is_instance_valid(item)

func is_item(new_item:Item) -> bool:
	return new_item == item

class_name Inventory

@export var slots : Array[InventorySlot]
@export var weapons : Array[InventorySlot]

i also have collectable class which an other class name collectable_item inherits from it , it basicly is an area2d which calls collect() on what ever coms in it and passes it self to it . in this case is more like player.collect(collectable)

class_name Collectable

func _on_body_entered(body):
	if body is Player : 
		body.collect(self)
extends Collectable
class_name CollectableItem

@export var item : Item
@export var quantity : int

i made a inventory resource file in my project and assighned it to export variable of my player and gui .
here is player code:

extends CharacterBody2D

signal player_health_update(hp:float, max_hp:float)

@export var states : Status
@export var inventory : Inventory
@export var player_body_sprite : PlayerBodySprite
@export var can_move : bool = true
@export var is_rolling : bool = false

func _ready() -> void:
	assert(is_instance_valid(states),"Player Stats Hasnt Been Set!")
	assert(is_instance_valid(inventory),"Player inventory Hasnt Been Set!")
	await owner.ready
	self.player_health_update.emit(states.health,states.max_health)
#	states.died.connect(on_player_died)

func _process(delta: float) -> void:	
	move()	

func move():
	if !can_move : return
	
	var direction = Input.get_vector("left","right","up","down")
	if direction == Vector2.ZERO :
		player_body_sprite.idle()
		return
	player_body_sprite.walk()
	velocity = states.move_speed * direction
	move_and_slide()	

func buff_effects():
	pass

func _input(event: InputEvent) -> void:
	if event.is_action_pressed("right"):
		player_body_sprite.scale.x= abs(player_body_sprite.scale.x)
	elif event.is_action_pressed("left"):
		player_body_sprite.scale.x= -1*abs(player_body_sprite.scale.x)

func hurt(attack : Attack):
	states.health -= attack.damage
	player_health_update.emit(states.health,states.max_health)

func collect(collectable : Collectable):
	if collectable is CollectableXp:
		pass
	elif collectable is CollectableItem:
		var collected_item := collectable as CollectableItem
		
		for i in inventory.slots.size() :
			if collected_item.quantity <= 0 : break
			print("collected : "+str(collected_item.quantity)+collected_item.name)
			if inventory.slots[i].is_item(collectable.item):
				while inventory.slots[i].empty_space>0 and collected_item.quantity>0 :
					collected_item.quantity-=1
					inventory.slots[i].quantity+=1
					print("added to existing")
			elif inventory.slots[i].is_empty() :
				print("slot is empty so:")
				inventory.slots[i].item=collected_item.item
				inventory.slots[i].quantity=0
				
				print("slot item:"+inventory.slots[i].item.name)
				print("slot quantity:"+str(inventory.slots[i].quantity))
				while inventory.slots[i].empty_space>0 and collected_item.quantity>0 :
					collected_item.quantity-=1
					inventory.slots[i].quantity+=1
					print("added as new")
				
				print("slot item:"+inventory.slots[i].item.name)
				print("slot quantity:"+str(inventory.slots[i].quantity))
			else: continue
			
			
		if collected_item.quantity<=0 :
			print("item collected")
			collected_item.queue_free()

func die()->void:
	pass

Problem : it basically collects the fu*king item off the ground , and prints it , but GUI doesn’t show it and its not even GUIs fault the item is no where to be seen even in remote player properties after being picked !

I’d assume it’s because you are looping while collected_item.quantity is greater than 0, then later you free the collected_item if the quantity is less than or equal to zero.

I think this means the inventory_slot.item is getting freed and will be invalid. If that is the case, I am surprised you aren’t getting an error somewhere :thinking:

You could test this theory by removing the queue_free or setting the collectable quantity to something larger than the inventory can hold.

nope , deleting queue free() didn’t fix it , i also tried items with bigger amounts than slots and nope didn’t work either :frowning:

Oh no! Then I’m not sure what is wrong. I can’t spot anything else obviously wrong with the code you’ve posted.

You haven’t actually posted the GUI code, how does it try and display the inventory?

1 Like

you know , isn’t it because instead of a resource I’m referring to a resource file ? isn’t there any extra steps to add a element like that ?
and btw as i sayed even checking inventory in remote tab properties at runtime shows that items are not added actually , funny since all those print() callse in the collect() func say other wise