open-fpsz/entities/components/inventory.gd
2025-02-07 21:52:19 -05:00

77 lines
2.5 KiB
GDScript

# This file is part of open-fpsz.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
@tool
## This component allows its entity to hold [Weapon] nodes.
class_name Inventory extends Node3D
signal selection_changed(index : int)
signal selected(node: Node)
signal unselected(node: Node)
const _max_items = 3
## This is the total capacity of inventory.
@export_range(0, _max_items) var capacity : int = _max_items:
set(value):
capacity = clamp(value, 1, _max_items)
@export_range(0, _max_items - 1) var cursor : int = 0:
set = set_cursor
# Function to set the cursor position in the inventory
func set_cursor(new_cursor: int) -> void:
# Ensure the cursor is within the valid range
if new_cursor >= 0 and new_cursor < _max_items:
# emit unselected signal
_emit_child(unselected, cursor)
# update cursor position
cursor = new_cursor
# emit selected signal
_emit_child(selected, cursor)
# helper function to emit the selected signal for the current cursor position
func _emit_child(sig: Signal, idx: int) -> void:
var child : Node = get_child(idx)
if child:
sig.emit(child)
func _ready() -> void:
unselected.connect(_on_unselected)
selected.connect(_on_selected)
func _on_unselected(node: Node) -> void:
node.hide()
func _on_selected(node: Node) -> void:
node.show()
## This method overrides [method Node.add_child] to make sure not to exceed
## inventory capacity.
func _add_child(node: Node, force_readable_name: bool = false,
internal: InternalMode = InternalMode.INTERNAL_MODE_DISABLED) -> void:
if get_child_count() <= capacity:
super.add_child(node, force_readable_name, internal)
else:
push_warning("inventory is full")
## This method moves the [member selection] cursor to specified item index.
func select(index : int) -> void:
cursor = wrapi(index, 0, get_child_count())
## This method cycles through items in the inventory.
func cycle(shift : int = 1) -> void:
select(cursor + shift)