模板脚本文件
This commit is contained in:
@@ -0,0 +1,267 @@
|
||||
class_name PlayerInventory
|
||||
extends RefCounted
|
||||
|
||||
const BASE_INVENTORY_SIZE := 16
|
||||
const BACKPACK_BONUS_SLOTS := 4
|
||||
const MAX_INVENTORY_SIZE := BASE_INVENTORY_SIZE + BACKPACK_BONUS_SLOTS
|
||||
var slots: Array[InventorySlot] = []
|
||||
var equipped_weapon: InventorySlot = InventorySlot.new()
|
||||
var equipped_hat: InventorySlot = InventorySlot.new()
|
||||
var equipped_backpack: InventorySlot = InventorySlot.new()
|
||||
|
||||
|
||||
func _init():
|
||||
_initialize_slots()
|
||||
|
||||
|
||||
func _initialize_slots():
|
||||
slots.clear()
|
||||
for i in range(MAX_INVENTORY_SIZE):
|
||||
slots.append(InventorySlot.new())
|
||||
|
||||
|
||||
func get_active_slot_count() -> int:
|
||||
return MAX_INVENTORY_SIZE if not equipped_backpack.is_empty() else BASE_INVENTORY_SIZE
|
||||
|
||||
|
||||
func is_slot_active(index: int) -> bool:
|
||||
return index >= 0 and index < get_active_slot_count()
|
||||
|
||||
|
||||
func get_slot(index: int) -> InventorySlot:
|
||||
if index >= 0 and index < slots.size():
|
||||
return slots[index]
|
||||
return null
|
||||
|
||||
|
||||
func get_equipped_slot(item_type: Item.ItemType) -> InventorySlot:
|
||||
match item_type:
|
||||
Item.ItemType.WEAPON:
|
||||
return equipped_weapon
|
||||
Item.ItemType.HAT:
|
||||
return equipped_hat
|
||||
Item.ItemType.BACKPACK:
|
||||
return equipped_backpack
|
||||
_:
|
||||
return null
|
||||
|
||||
|
||||
func equip_from_slot(index: int, item_type: Item.ItemType) -> bool:
|
||||
if not is_slot_active(index):
|
||||
return false
|
||||
|
||||
var backpack_slot: InventorySlot = get_slot(index)
|
||||
var equipped_slot: InventorySlot = get_equipped_slot(item_type)
|
||||
if not backpack_slot or backpack_slot.is_empty() or not equipped_slot:
|
||||
return false
|
||||
|
||||
var item: Item = ItemDatabase.get_item(backpack_slot.item_id)
|
||||
if not item or item.item_type != item_type:
|
||||
return false
|
||||
|
||||
var new_item_id: String = backpack_slot.item_id
|
||||
var new_quantity: int = backpack_slot.quantity
|
||||
backpack_slot.item_id = equipped_slot.item_id
|
||||
backpack_slot.quantity = equipped_slot.quantity
|
||||
equipped_slot.item_id = new_item_id
|
||||
equipped_slot.quantity = new_quantity
|
||||
if backpack_slot.is_empty():
|
||||
backpack_slot.clear()
|
||||
return true
|
||||
|
||||
|
||||
func unequip_to_slot(item_type: Item.ItemType, destination_index: int = -1) -> bool:
|
||||
var equipped_slot: InventorySlot = get_equipped_slot(item_type)
|
||||
if not equipped_slot or equipped_slot.is_empty():
|
||||
return false
|
||||
if item_type == Item.ItemType.BACKPACK:
|
||||
return _unequip_backpack_to_slot(equipped_slot, destination_index)
|
||||
|
||||
if destination_index < 0:
|
||||
destination_index = get_first_empty_slot()
|
||||
if not is_slot_active(destination_index):
|
||||
return false
|
||||
var destination: InventorySlot = get_slot(destination_index)
|
||||
if not destination or not destination.is_empty():
|
||||
return false
|
||||
|
||||
destination.item_id = equipped_slot.item_id
|
||||
destination.quantity = equipped_slot.quantity
|
||||
equipped_slot.clear()
|
||||
return true
|
||||
|
||||
|
||||
func _unequip_backpack_to_slot(equipped_slot: InventorySlot, destination_index: int) -> bool:
|
||||
if destination_index < 0:
|
||||
destination_index = _get_first_empty_base_slot()
|
||||
if destination_index < 0 or destination_index >= BASE_INVENTORY_SIZE:
|
||||
return false
|
||||
|
||||
var destination := get_slot(destination_index)
|
||||
if not destination or not destination.is_empty():
|
||||
return false
|
||||
|
||||
var occupied_bonus_slots: Array[int] = []
|
||||
for i in range(BASE_INVENTORY_SIZE, MAX_INVENTORY_SIZE):
|
||||
if not slots[i].is_empty():
|
||||
occupied_bonus_slots.append(i)
|
||||
|
||||
var available_base_slots: Array[int] = []
|
||||
for i in range(BASE_INVENTORY_SIZE):
|
||||
if i != destination_index and slots[i].is_empty():
|
||||
available_base_slots.append(i)
|
||||
if occupied_bonus_slots.size() > available_base_slots.size():
|
||||
return false
|
||||
|
||||
for i in range(occupied_bonus_slots.size()):
|
||||
var source := slots[occupied_bonus_slots[i]]
|
||||
var target := slots[available_base_slots[i]]
|
||||
target.item_id = source.item_id
|
||||
target.quantity = source.quantity
|
||||
source.clear()
|
||||
|
||||
destination.item_id = equipped_slot.item_id
|
||||
destination.quantity = equipped_slot.quantity
|
||||
equipped_slot.clear()
|
||||
return true
|
||||
|
||||
|
||||
func _get_first_empty_base_slot() -> int:
|
||||
for i in range(BASE_INVENTORY_SIZE):
|
||||
if slots[i].is_empty():
|
||||
return i
|
||||
return -1
|
||||
|
||||
|
||||
func add_item(item: Item, quantity: int = 1) -> int:
|
||||
var remaining = quantity
|
||||
var active_slot_count := get_active_slot_count()
|
||||
|
||||
if item.stackable:
|
||||
for i in range(active_slot_count):
|
||||
var slot := slots[i]
|
||||
if slot.item_id == item.id:
|
||||
remaining = slot.add_item(item, remaining)
|
||||
if remaining <= 0:
|
||||
break
|
||||
|
||||
if remaining > 0:
|
||||
for i in range(active_slot_count):
|
||||
var slot := slots[i]
|
||||
if slot.is_empty():
|
||||
remaining = slot.add_item(item, remaining)
|
||||
if remaining <= 0:
|
||||
break
|
||||
|
||||
return remaining
|
||||
|
||||
|
||||
func remove_item(item_id: String, quantity: int = 1) -> int:
|
||||
var removed = 0
|
||||
for i in range(get_active_slot_count()):
|
||||
var slot := slots[i]
|
||||
if slot.item_id == item_id:
|
||||
var slot_removed = slot.remove_item(quantity - removed)
|
||||
removed += slot_removed
|
||||
if removed >= quantity:
|
||||
break
|
||||
return removed
|
||||
|
||||
|
||||
func move_item(from_index: int, to_index: int, quantity: int = -1) -> bool:
|
||||
if (
|
||||
from_index == to_index
|
||||
or not is_slot_active(from_index)
|
||||
or not is_slot_active(to_index)
|
||||
or quantity == 0
|
||||
or quantity < -1
|
||||
):
|
||||
return false
|
||||
|
||||
var from_slot = get_slot(from_index)
|
||||
var to_slot = get_slot(to_index)
|
||||
|
||||
if not from_slot or not to_slot or from_slot.is_empty():
|
||||
return false
|
||||
|
||||
var move_amount = from_slot.quantity if quantity == -1 else quantity
|
||||
move_amount = min(move_amount, from_slot.quantity)
|
||||
|
||||
var item = ItemDatabase.get_item(from_slot.item_id)
|
||||
if not item:
|
||||
return false
|
||||
|
||||
var remaining = to_slot.add_item(item, move_amount)
|
||||
var moved_amount = move_amount - remaining
|
||||
if moved_amount > 0:
|
||||
from_slot.remove_item(moved_amount)
|
||||
|
||||
return moved_amount > 0
|
||||
|
||||
|
||||
func swap_items(from_index: int, to_index: int) -> bool:
|
||||
if not is_slot_active(from_index) or not is_slot_active(to_index):
|
||||
return false
|
||||
|
||||
var from_slot = get_slot(from_index)
|
||||
var to_slot = get_slot(to_index)
|
||||
|
||||
if not from_slot or not to_slot:
|
||||
return false
|
||||
|
||||
if from_slot.item_id == to_slot.item_id and not from_slot.is_empty() and not to_slot.is_empty():
|
||||
var item = ItemDatabase.get_item(from_slot.item_id)
|
||||
if item and item.stackable:
|
||||
var total_quantity = from_slot.quantity + to_slot.quantity
|
||||
if total_quantity <= item.max_stack:
|
||||
to_slot.quantity = total_quantity
|
||||
from_slot.clear()
|
||||
return true
|
||||
var space_available = item.max_stack - to_slot.quantity
|
||||
var amount_to_move = min(space_available, from_slot.quantity)
|
||||
to_slot.quantity += amount_to_move
|
||||
from_slot.quantity -= amount_to_move
|
||||
if from_slot.quantity <= 0:
|
||||
from_slot.clear()
|
||||
return true
|
||||
|
||||
var temp_item_id = from_slot.item_id
|
||||
var temp_quantity = from_slot.quantity
|
||||
|
||||
from_slot.item_id = to_slot.item_id
|
||||
from_slot.quantity = to_slot.quantity
|
||||
|
||||
to_slot.item_id = temp_item_id
|
||||
to_slot.quantity = temp_quantity
|
||||
|
||||
return true
|
||||
|
||||
|
||||
func get_first_empty_slot() -> int:
|
||||
for i in range(get_active_slot_count()):
|
||||
if slots[i].is_empty():
|
||||
return i
|
||||
return -1
|
||||
|
||||
|
||||
func to_dict() -> Dictionary:
|
||||
var data = []
|
||||
for slot in slots:
|
||||
data.append(slot.to_dict())
|
||||
return {
|
||||
"slots": data,
|
||||
"equipped_weapon": equipped_weapon.to_dict(),
|
||||
"equipped_hat": equipped_hat.to_dict(),
|
||||
"equipped_backpack": equipped_backpack.to_dict()
|
||||
}
|
||||
|
||||
|
||||
func from_dict(data: Dictionary) -> void:
|
||||
var slots_data = data.get("slots", [])
|
||||
for i in range(min(slots_data.size(), slots.size())):
|
||||
slots[i].from_dict(slots_data[i])
|
||||
for i in range(slots_data.size(), slots.size()):
|
||||
slots[i].clear()
|
||||
equipped_weapon.from_dict(data.get("equipped_weapon", {}))
|
||||
equipped_hat.from_dict(data.get("equipped_hat", {}))
|
||||
equipped_backpack.from_dict(data.get("equipped_backpack", {}))
|
||||
Reference in New Issue
Block a user