104 lines
2.6 KiB
GDScript
104 lines
2.6 KiB
GDScript
class_name Inventory
|
|
extends RefCounted
|
|
|
|
const MAX_STACK: int = 64
|
|
const TOTAL_SLOTS: int = 36
|
|
const HOTBAR_SIZE: int = 9
|
|
|
|
signal inventory_changed
|
|
|
|
var slots: Array = []
|
|
var selected_hotbar: int = 0
|
|
|
|
|
|
func _init() -> void:
|
|
slots.resize(TOTAL_SLOTS)
|
|
for i: int in range(TOTAL_SLOTS):
|
|
slots[i] = null
|
|
|
|
|
|
func add_item(item_id: int, count: int = 1) -> int:
|
|
var remaining: int = count
|
|
# First pass: stack into existing slots
|
|
for i: int in range(TOTAL_SLOTS):
|
|
if remaining <= 0:
|
|
break
|
|
if slots[i] != null and slots[i]["item_id"] == item_id:
|
|
var space: int = MAX_STACK - slots[i]["count"]
|
|
if space > 0:
|
|
var add_amount: int = mini(space, remaining)
|
|
slots[i]["count"] += add_amount
|
|
remaining -= add_amount
|
|
# Second pass: fill empty slots
|
|
for i: int in range(TOTAL_SLOTS):
|
|
if remaining <= 0:
|
|
break
|
|
if slots[i] == null:
|
|
var add_amount: int = mini(MAX_STACK, remaining)
|
|
slots[i] = {"item_id": item_id, "count": add_amount}
|
|
remaining -= add_amount
|
|
inventory_changed.emit()
|
|
return remaining
|
|
|
|
|
|
func remove_item_from_slot(slot_index: int, count: int = 1) -> bool:
|
|
if slot_index < 0 or slot_index >= TOTAL_SLOTS:
|
|
return false
|
|
if slots[slot_index] == null:
|
|
return false
|
|
if slots[slot_index]["count"] < count:
|
|
return false
|
|
slots[slot_index]["count"] -= count
|
|
if slots[slot_index]["count"] <= 0:
|
|
slots[slot_index] = null
|
|
inventory_changed.emit()
|
|
return true
|
|
|
|
|
|
func get_selected_item() -> Variant:
|
|
return slots[selected_hotbar]
|
|
|
|
|
|
func scroll_hotbar(direction: int) -> void:
|
|
selected_hotbar = (selected_hotbar + direction + HOTBAR_SIZE) % HOTBAR_SIZE
|
|
inventory_changed.emit()
|
|
|
|
|
|
func has_items(requirements: Array) -> bool:
|
|
for req: Dictionary in requirements:
|
|
var needed: int = req["count"]
|
|
for i: int in range(TOTAL_SLOTS):
|
|
if slots[i] != null and slots[i]["item_id"] == req["item_id"]:
|
|
needed -= slots[i]["count"]
|
|
if needed > 0:
|
|
return false
|
|
return true
|
|
|
|
|
|
func get_all_slots() -> Array:
|
|
return slots.duplicate(true)
|
|
|
|
|
|
func load_slots(saved_slots: Array) -> void:
|
|
for i: int in range(min(saved_slots.size(), TOTAL_SLOTS)):
|
|
slots[i] = saved_slots[i]
|
|
inventory_changed.emit()
|
|
|
|
|
|
func consume_items(requirements: Array) -> bool:
|
|
if not has_items(requirements):
|
|
return false
|
|
for req: Dictionary in requirements:
|
|
var to_consume: int = req["count"]
|
|
for i: int in range(TOTAL_SLOTS):
|
|
if to_consume <= 0:
|
|
break
|
|
if slots[i] != null and slots[i]["item_id"] == req["item_id"]:
|
|
var take: int = mini(slots[i]["count"], to_consume)
|
|
slots[i]["count"] -= take
|
|
to_consume -= take
|
|
if slots[i]["count"] <= 0:
|
|
slots[i] = null
|
|
inventory_changed.emit()
|
|
return true
|