Refactored inventory such that it can handle stacked items.

main
Martin Felis 2024-09-06 12:34:18 +02:00
parent b5835c3cff
commit 635655f7a6
20 changed files with 171 additions and 55 deletions

View File

@ -1,12 +0,0 @@
[gd_resource type="Resource" script_class="Item" load_steps=4 format=3 uid="uid://coser1y1y5unl"]
[ext_resource type="Texture2D" uid="uid://ojsbkfjeu088" path="res://assets/3rdparty/kenney/survival-kit/Previews/toolPickaxe.png" id="1_ev4xm"]
[ext_resource type="PackedScene" uid="uid://ca2l61b2j3y5b" path="res://assets/tools/Pickaxe.tscn" id="2_diiob"]
[ext_resource type="Script" path="res://model/item.gd" id="3_n4quc"]
[resource]
resource_name = "Pickaxe"
script = ExtResource("3_n4quc")
name = "Pickaxe"
scene = ExtResource("2_diiob")
icon = ExtResource("1_ev4xm")

View File

@ -10,3 +10,4 @@ script = ExtResource("1_0t4oi")
name = "Shovel" name = "Shovel"
scene = ExtResource("1_fne3r") scene = ExtResource("1_fne3r")
icon = ExtResource("1_oaqa4") icon = ExtResource("1_oaqa4")
max_stack_size = 1

View File

@ -10,3 +10,4 @@ script = ExtResource("3_45lxd")
name = "Stick" name = "Stick"
scene = ExtResource("2_mrxum") scene = ExtResource("2_mrxum")
icon = ExtResource("1_c3g8n") icon = ExtResource("1_c3g8n")
max_stack_size = 64

View File

@ -9,3 +9,5 @@ script = ExtResource("1_dao2u")
name = "Stone" name = "Stone"
scene = ExtResource("2_6nus0") scene = ExtResource("2_6nus0")
icon = ExtResource("1_t2qva") icon = ExtResource("1_t2qva")
stack_size = 1
max_stack_size = 64

View File

@ -9,3 +9,5 @@ script = ExtResource("1_tlj5a")
name = "Tree Log" name = "Tree Log"
scene = ExtResource("2_ufvdy") scene = ExtResource("2_ufvdy")
icon = ExtResource("1_ak0y2") icon = ExtResource("1_ak0y2")
stack_size = 1
max_stack_size = 64

View File

@ -9,3 +9,4 @@ script = ExtResource("3_c8yxb")
name = "Wood Planks" name = "Wood Planks"
scene = ExtResource("2_4oehn") scene = ExtResource("2_4oehn")
icon = ExtResource("1_plody") icon = ExtResource("1_plody")
max_stack_size = 64

View File

@ -1,16 +1,57 @@
class_name Inventory class_name Inventory
var _content:Array[Item] = [] var _content:Array[ItemStack] = []
const INVENTORY_SIZE:int = 36
func add_item(item:Item): func _init() -> void:
_content.append(item) _content.resize(INVENTORY_SIZE)
func get_free_item_stack_index() -> int:
for i:int in range(_content.size()):
if _content[i] == null:
return i
return -1
func add_item(item:Item) -> bool:
for item_stack:ItemStack in _content:
if item_stack == null:
continue
if item_stack.item.resource_path != item.resource_path:
continue
if item_stack.count < item_stack.item.max_stack_size:
item_stack.count = item_stack.count + 1
return true
var item_stack_index:int = get_free_item_stack_index()
if item_stack_index >= 0:
var item_stack:ItemStack = ItemStack.new()
item_stack.item = item
item_stack.count = 1
_content[item_stack_index] = item_stack
return true
return false
func remove_item(item:Item): func remove_item(item:Item):
_content.erase(item) for i in range(_content.size() - 1, -1, -1):
var item_stack:ItemStack = _content[i]
if item_stack == null:
continue
if item_stack.item.resource_path == item.resource_path:
if item_stack.count > 1:
item_stack.count = item_stack.count - 1
else:
_content[i] = null
return
func get_items() -> Array[Item]: func get_item_stacks() -> Array[ItemStack]:
return _content return _content
@ -21,7 +62,11 @@ func clear() -> void:
func has_all(items:Array[Item]) -> bool: func has_all(items:Array[Item]) -> bool:
var needed:Array[Item] = items.duplicate() var needed:Array[Item] = items.duplicate()
for available in _content: for item_stack:ItemStack in _content:
needed.erase(available) if item_stack == null:
continue
for i in range (item_stack.count):
needed.erase(item_stack.item)
return needed.is_empty() return needed.is_empty()

View File

@ -4,3 +4,4 @@ extends Resource
@export var name:String @export var name:String
@export var scene:PackedScene @export var scene:PackedScene
@export var icon:Texture2D @export var icon:Texture2D
@export var max_stack_size:int = 1

View File

@ -1,5 +1,5 @@
class_name Main class_name Main
extends Node3D extends Node
@onready var message_container:Control = %MessagesContainer @onready var message_container:Control = %MessagesContainer
@onready var message_textedit:TextEdit = %MessageTextEdit @onready var message_textedit:TextEdit = %MessageTextEdit

View File

@ -1,20 +1,19 @@
[gd_scene load_steps=14 format=3 uid="uid://ck104ww8vi7f1"] [gd_scene load_steps=13 format=3 uid="uid://ck104ww8vi7f1"]
[ext_resource type="Script" path="res://scenes/main.gd" id="1_yidnr"] [ext_resource type="Script" path="res://scenes/main.gd" id="1_yidnr"]
[ext_resource type="PackedScene" uid="uid://bo788o53t4rbq" path="res://scenes/startup_scene.tscn" id="2_imuae"] [ext_resource type="PackedScene" uid="uid://bo788o53t4rbq" path="res://scenes/startup_scene.tscn" id="2_imuae"]
[ext_resource type="PackedScene" uid="uid://cqie4cy0uy1t0" path="res://scenes/game.tscn" id="2_o3qua"] [ext_resource type="PackedScene" uid="uid://cqie4cy0uy1t0" path="res://scenes/game.tscn" id="2_o3qua"]
[ext_resource type="PackedScene" uid="uid://nob4ibnp0p5u" path="res://ui/tool_container.tscn" id="11_yj24a"]
[ext_resource type="Script" path="res://ui/tool_container.gd" id="12_duobv"]
[ext_resource type="Script" path="res://root_ui.gd" id="13_h24kl"] [ext_resource type="Script" path="res://root_ui.gd" id="13_h24kl"]
[ext_resource type="Theme" uid="uid://dmk7hc81l8gbw" path="res://ui/ui_theme.tres" id="14_bvivl"] [ext_resource type="Theme" uid="uid://dmk7hc81l8gbw" path="res://ui/ui_theme.tres" id="14_bvivl"]
[ext_resource type="Script" path="res://game_ui.gd" id="15_g7bf1"] [ext_resource type="Script" path="res://game_ui.gd" id="15_g7bf1"]
[ext_resource type="Script" path="res://ui/inventory_dialog.gd" id="16_18k4v"] [ext_resource type="Script" path="res://ui/inventory_dialog.gd" id="16_18k4v"]
[ext_resource type="PackedScene" uid="uid://dp3fi0g53qrt2" path="res://ui/item_slot.tscn" id="17_rucv3"] [ext_resource type="PackedScene" uid="uid://dp3fi0g53qrt2" path="res://ui/item_slot.tscn" id="17_rucv3"]
[ext_resource type="PackedScene" uid="uid://bwui4acukq4x6" path="res://ui/item_grid.tscn" id="18_fihac"] [ext_resource type="PackedScene" uid="uid://bwui4acukq4x6" path="res://ui/ItemGrid.tscn" id="18_fihac"]
[ext_resource type="Script" path="res://ui/game_menu_ui.gd" id="19_krapk"] [ext_resource type="Script" path="res://ui/game_menu_ui.gd" id="19_krapk"]
[ext_resource type="Texture2D" uid="uid://c7fu3paj3b4e8" path="res://assets/3rdparty/kenney/ui-pack-rpg-expansion/PNG/cursorSword_silver.png" id="20_7s1r5"]
[ext_resource type="Texture2D" uid="uid://drpl0ql1p3pfk" path="res://assets/3rdparty/kenney/ui-pack-rpg-expansion/PNG/cursorSword_gold.png" id="21_663i3"]
[ext_resource type="Texture2D" uid="uid://cq8ypeagpedq" path="res://assets/3rdparty/kenney/ui-pack-rpg-expansion/PNG/cursorSword_bronze.png" id="22_le7qn"]
[node name="Main" type="Node3D"] [node name="Main" type="Node"]
script = ExtResource("1_yidnr") script = ExtResource("1_yidnr")
[node name="RootUI" type="CanvasLayer" parent="."] [node name="RootUI" type="CanvasLayer" parent="."]
@ -183,7 +182,6 @@ text = "Start
[node name="GameUI" type="Control" parent="RootUI"] [node name="GameUI" type="Control" parent="RootUI"]
unique_name_in_owner = true unique_name_in_owner = true
visible = false
layout_mode = 3 layout_mode = 3
anchors_preset = 15 anchors_preset = 15
anchor_right = 1.0 anchor_right = 1.0
@ -319,6 +317,8 @@ size_flags_vertical = 3
[node name="IngredientsContainer" parent="RootUI/GameUI/InventoryDialog/Panel/PanelContainer/CraftingUI/HBoxContainer/CraftIngredients/Panel/CenterContainer" instance=ExtResource("18_fihac")] [node name="IngredientsContainer" parent="RootUI/GameUI/InventoryDialog/Panel/PanelContainer/CraftingUI/HBoxContainer/CraftIngredients/Panel/CenterContainer" instance=ExtResource("18_fihac")]
unique_name_in_owner = true unique_name_in_owner = true
layout_mode = 2 layout_mode = 2
columns = 3
rows = 3
[node name="HBoxContainer" type="HBoxContainer" parent="RootUI/GameUI/InventoryDialog/Panel/PanelContainer/CraftingUI/HBoxContainer/CraftIngredients"] [node name="HBoxContainer" type="HBoxContainer" parent="RootUI/GameUI/InventoryDialog/Panel/PanelContainer/CraftingUI/HBoxContainer/CraftIngredients"]
layout_mode = 2 layout_mode = 2
@ -357,6 +357,7 @@ grow_vertical = 2
[node name="ResultsContainer" parent="RootUI/GameUI/InventoryDialog/Panel/PanelContainer/CraftingUI/HBoxContainer/CraftResult/Panel/CenterContainer" instance=ExtResource("18_fihac")] [node name="ResultsContainer" parent="RootUI/GameUI/InventoryDialog/Panel/PanelContainer/CraftingUI/HBoxContainer/CraftResult/Panel/CenterContainer" instance=ExtResource("18_fihac")]
unique_name_in_owner = true unique_name_in_owner = true
layout_mode = 2 layout_mode = 2
columns = 1
[node name="HBoxContainer" type="HBoxContainer" parent="RootUI/GameUI/InventoryDialog/Panel/PanelContainer/CraftingUI/HBoxContainer/CraftResult"] [node name="HBoxContainer" type="HBoxContainer" parent="RootUI/GameUI/InventoryDialog/Panel/PanelContainer/CraftingUI/HBoxContainer/CraftResult"]
layout_mode = 2 layout_mode = 2
@ -387,6 +388,7 @@ unique_name_in_owner = true
layout_mode = 2 layout_mode = 2
size_flags_horizontal = 4 size_flags_horizontal = 4
size_flags_vertical = 4 size_flags_vertical = 4
rows = 3
[node name="GameMenuUI" type="PanelContainer" parent="RootUI/GameUI"] [node name="GameMenuUI" type="PanelContainer" parent="RootUI/GameUI"]
unique_name_in_owner = true unique_name_in_owner = true
@ -494,20 +496,10 @@ theme_override_constants/margin_bottom = 32
[node name="PanelContainer" type="PanelContainer" parent="RootUI/GameUI/ToolSlots"] [node name="PanelContainer" type="PanelContainer" parent="RootUI/GameUI/ToolSlots"]
layout_mode = 2 layout_mode = 2
[node name="HBoxContainer" type="HBoxContainer" parent="RootUI/GameUI/ToolSlots/PanelContainer"] [node name="ToolContainer" parent="RootUI/GameUI/ToolSlots/PanelContainer" instance=ExtResource("11_yj24a")]
layout_mode = 2 layout_mode = 2
script = ExtResource("12_duobv")
[node name="Button2" type="Button" parent="RootUI/GameUI/ToolSlots/PanelContainer/HBoxContainer"] slot_scene = ExtResource("17_rucv3")
layout_mode = 2
icon = ExtResource("20_7s1r5")
[node name="Button3" type="Button" parent="RootUI/GameUI/ToolSlots/PanelContainer/HBoxContainer"]
layout_mode = 2
icon = ExtResource("21_663i3")
[node name="Button" type="Button" parent="RootUI/GameUI/ToolSlots/PanelContainer/HBoxContainer"]
layout_mode = 2
icon = ExtResource("22_le7qn")
[node name="Scene" type="Node3D" parent="."] [node name="Scene" type="Node3D" parent="."]
unique_name_in_owner = true unique_name_in_owner = true

View File

@ -7,3 +7,6 @@
columns = 9 columns = 9
script = ExtResource("1_c5mg2") script = ExtResource("1_c5mg2")
slot_scene = ExtResource("2_o52f5") slot_scene = ExtResource("2_o52f5")
[node name="ItemSlot" parent="." instance=ExtResource("2_o52f5")]
layout_mode = 2

View File

@ -7,7 +7,7 @@
[ext_resource type="Texture2D" uid="uid://cq8ypeagpedq" path="res://assets/3rdparty/kenney/ui-pack-rpg-expansion/PNG/cursorSword_bronze.png" id="5_4e7rh"] [ext_resource type="Texture2D" uid="uid://cq8ypeagpedq" path="res://assets/3rdparty/kenney/ui-pack-rpg-expansion/PNG/cursorSword_bronze.png" id="5_4e7rh"]
[ext_resource type="Script" path="res://ui/inventory_dialog.gd" id="6_lssx5"] [ext_resource type="Script" path="res://ui/inventory_dialog.gd" id="6_lssx5"]
[ext_resource type="PackedScene" uid="uid://dp3fi0g53qrt2" path="res://ui/item_slot.tscn" id="7_2r38a"] [ext_resource type="PackedScene" uid="uid://dp3fi0g53qrt2" path="res://ui/item_slot.tscn" id="7_2r38a"]
[ext_resource type="PackedScene" uid="uid://bwui4acukq4x6" path="res://ui/item_grid.tscn" id="8_igemi"] [ext_resource type="PackedScene" uid="uid://bwui4acukq4x6" path="res://ui/ItemGrid.tscn" id="8_igemi"]
[node name="GameUI" type="Control"] [node name="GameUI" type="Control"]
layout_mode = 3 layout_mode = 3

View File

@ -26,7 +26,8 @@ func open(recipes:Array[Recipe], inventory:Inventory):
var index = recipe_list.add_item(recipe.name) var index = recipe_list.add_item(recipe.name)
recipe_list.set_item_metadata(index, recipe) recipe_list.set_item_metadata(index, recipe)
inventory_container.display(inventory.get_items()) inventory_container.displayStacks(inventory.get_item_stacks())
recipe_list.select(0) recipe_list.select(0)
_on_recipe_list_item_selected(0) _on_recipe_list_item_selected(0)
@ -65,5 +66,5 @@ func _on_craft_button_pressed():
for item in _selected_recipe.results: for item in _selected_recipe.results:
_inventory.add_item(item) _inventory.add_item(item)
inventory_container.display(_inventory.get_items()) inventory_container.displayStacks(_inventory.get_item_stacks())
update_crafting_widgets(_selected_recipe) update_crafting_widgets(_selected_recipe)

View File

@ -2,12 +2,36 @@ class_name ItemGrid
extends GridContainer extends GridContainer
@export var slot_scene:PackedScene @export var slot_scene:PackedScene
@export var rows:int = 1
func display(items:Array[Item]): func displayStacks(item_stacks:Array[ItemStack]):
for child in get_children(): for child in get_children():
child.queue_free() child.queue_free()
child.get_parent().remove_child(child)
for item in items:
for item_stack in item_stacks:
var slot:ItemSlot = slot_scene.instantiate() var slot:ItemSlot = slot_scene.instantiate()
add_child(slot) add_child(slot)
slot.display(item)
if item_stack != null:
slot.display(item_stack.item, item_stack.count)
var item_count = rows * columns
while get_child_count() < item_count:
add_child(slot_scene.instantiate())
func display(item_stacks:Array[Item]):
for child in get_children():
child.queue_free()
child.get_parent().remove_child(child)
for item in item_stacks:
var slot:ItemSlot = slot_scene.instantiate()
add_child(slot)
slot.display(item, 1)
var item_count = rows * columns
while get_child_count() < item_count:
add_child(slot_scene.instantiate())

View File

@ -2,6 +2,16 @@ class_name ItemSlot
extends PanelContainer extends PanelContainer
@onready var texture_rect:TextureRect = %TextureRect @onready var texture_rect:TextureRect = %TextureRect
@onready var count_label = %CountLabel
func display(item:Item): func display(item:Item, count:int):
texture_rect.texture = item.icon if item != null:
texture_rect.texture = item.icon
update_quantity_text(count)
func update_quantity_text(stack_size) -> void:
if stack_size <= 1:
count_label.hide()
else:
count_label.text = str(stack_size)
count_label.show()

View File

@ -1,14 +1,18 @@
[gd_scene load_steps=3 format=3 uid="uid://dp3fi0g53qrt2"] [gd_scene load_steps=2 format=3 uid="uid://dp3fi0g53qrt2"]
[ext_resource type="Script" path="res://ui/item_slot.gd" id="1_7v5l8"] [ext_resource type="Script" path="res://ui/item_slot.gd" id="1_7v5l8"]
[ext_resource type="Texture2D" uid="uid://ojsbkfjeu088" path="res://assets/3rdparty/kenney/survival-kit/Previews/toolPickaxe.png" id="1_mafu0"]
[node name="PanelContainer" type="PanelContainer"] [node name="ItemSlot" type="PanelContainer"]
custom_minimum_size = Vector2(64, 64) custom_minimum_size = Vector2(64, 64)
script = ExtResource("1_7v5l8") script = ExtResource("1_7v5l8")
[node name="TextureRect" type="TextureRect" parent="."] [node name="TextureRect" type="TextureRect" parent="."]
unique_name_in_owner = true unique_name_in_owner = true
layout_mode = 2 layout_mode = 2
texture = ExtResource("1_mafu0")
expand_mode = 3 expand_mode = 3
[node name="CountLabel" type="Label" parent="."]
unique_name_in_owner = true
layout_mode = 2
size_flags_horizontal = 8
size_flags_vertical = 8

9
ui/item_stack.gd Normal file
View File

@ -0,0 +1,9 @@
class_name ItemStack
extends Node
var item:Item = null
@export var count:int = 1
# Called when the node enters the scene tree for the first time.
func _ready():
pass # Replace with function body.

13
ui/tool_container.gd Normal file
View File

@ -0,0 +1,13 @@
class_name ToolContainer
extends HBoxContainer
@export var slot_scene:PackedScene
# Called when the node enters the scene tree for the first time.
func _ready():
pass # Replace with function body.
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
pass

19
ui/tool_container.tscn Normal file
View File

@ -0,0 +1,19 @@
[gd_scene load_steps=4 format=3 uid="uid://nob4ibnp0p5u"]
[ext_resource type="Texture2D" uid="uid://c7fu3paj3b4e8" path="res://assets/3rdparty/kenney/ui-pack-rpg-expansion/PNG/cursorSword_silver.png" id="1_wpvbc"]
[ext_resource type="Texture2D" uid="uid://drpl0ql1p3pfk" path="res://assets/3rdparty/kenney/ui-pack-rpg-expansion/PNG/cursorSword_gold.png" id="2_le4fl"]
[ext_resource type="Texture2D" uid="uid://cq8ypeagpedq" path="res://assets/3rdparty/kenney/ui-pack-rpg-expansion/PNG/cursorSword_bronze.png" id="3_jhcf7"]
[node name="ToolContainer" type="HBoxContainer"]
[node name="Button2" type="Button" parent="."]
layout_mode = 2
icon = ExtResource("1_wpvbc")
[node name="Button3" type="Button" parent="."]
layout_mode = 2
icon = ExtResource("2_le4fl")
[node name="Button" type="Button" parent="."]
layout_mode = 2
icon = ExtResource("3_jhcf7")

View File

@ -83,9 +83,9 @@ Button/styles/normal = SubResource("StyleBoxTexture_votra")
Button/styles/pressed = SubResource("StyleBoxTexture_bpyb5") Button/styles/pressed = SubResource("StyleBoxTexture_bpyb5")
Control/styles/normal = SubResource("StyleBoxTexture_72pk6") Control/styles/normal = SubResource("StyleBoxTexture_72pk6")
ItemList/styles/normal = SubResource("StyleBoxTexture_kl7i7") ItemList/styles/normal = SubResource("StyleBoxTexture_kl7i7")
Label/colors/font_color = Color(0.172833, 0.172833, 0.172833, 1) Label/colors/font_color = Color(1, 1, 1, 1)
Label/colors/font_outline_color = Color(1, 1, 1, 1) Label/colors/font_outline_color = Color(1, 1, 1, 1)
Label/colors/font_shadow_color = Color(0, 0, 0, 0) Label/colors/font_shadow_color = Color(0.223103, 0.223103, 0.223103, 0.843137)
Label/constants/line_spacing = 3 Label/constants/line_spacing = 3
Label/constants/outline_size = 0 Label/constants/outline_size = 0
Label/constants/shadow_offset_x = 1 Label/constants/shadow_offset_x = 1