Make decor occupy individual inventory slots
This commit is contained in:
parent
f2239d248a
commit
4196cda1d5
9 changed files with 516 additions and 79 deletions
|
|
@ -4,6 +4,7 @@ extends Node
|
||||||
const ItemCatalogType = preload("res://items/item_catalog.gd")
|
const ItemCatalogType = preload("res://items/item_catalog.gd")
|
||||||
const ItemDataType = preload("res://items/item_data.gd")
|
const ItemDataType = preload("res://items/item_data.gd")
|
||||||
const OwnedItemType = preload("res://items/owned_item.gd")
|
const OwnedItemType = preload("res://items/owned_item.gd")
|
||||||
|
const DecorCatalogType = preload("res://homes/decor_catalog.gd")
|
||||||
|
|
||||||
const DEFAULT_UNLOCKED_BAIT_IDS: Array[StringName] = [&"worms"]
|
const DEFAULT_UNLOCKED_BAIT_IDS: Array[StringName] = [&"worms"]
|
||||||
const MIN_STORAGE_SLOT_COUNT: int = 15
|
const MIN_STORAGE_SLOT_COUNT: int = 15
|
||||||
|
|
@ -62,9 +63,35 @@ func add_item(item_id: StringName, quantity: int = 1) -> bool:
|
||||||
|
|
||||||
func add_item_to_storage(item_id: StringName, quantity: int = 1) -> bool:
|
func add_item_to_storage(item_id: StringName, quantity: int = 1) -> bool:
|
||||||
var existing: OwnedItemType = get_owned_item(item_id)
|
var existing: OwnedItemType = get_owned_item(item_id)
|
||||||
|
var item: ItemDataType = _resolve_available_item(item_id)
|
||||||
|
if item != null and DecorCatalogType.has_product(item_id):
|
||||||
|
if (
|
||||||
|
not _can_own_quantity(item, existing, quantity)
|
||||||
|
or _inventory_layout == null
|
||||||
|
or not _inventory_layout.can_accept_item_in_storage(
|
||||||
|
item_id, quantity
|
||||||
|
)
|
||||||
|
):
|
||||||
|
return false
|
||||||
|
for _unit: int in quantity:
|
||||||
|
if not _inventory_layout.prepare_new_item_in_first_free(
|
||||||
|
item_id,
|
||||||
|
PlayerInventoryLayout.InventoryContainer.STORAGE,
|
||||||
|
):
|
||||||
|
_inventory_layout.cancel_prepared_item_placement(item_id)
|
||||||
|
return false
|
||||||
|
if existing != null:
|
||||||
|
existing.quantity += quantity
|
||||||
|
else:
|
||||||
|
var owned := OwnedItemType.new()
|
||||||
|
owned.item_id = item_id
|
||||||
|
owned.quantity = quantity
|
||||||
|
owned.storage_slot = _first_available_storage_slot(item, _items)
|
||||||
|
_items.append(owned)
|
||||||
|
contents_changed.emit()
|
||||||
|
return true
|
||||||
if existing != null:
|
if existing != null:
|
||||||
return add_item(item_id, quantity)
|
return add_item(item_id, quantity)
|
||||||
var item: ItemDataType = _resolve_available_item(item_id)
|
|
||||||
if (
|
if (
|
||||||
item == null
|
item == null
|
||||||
or quantity <= 0
|
or quantity <= 0
|
||||||
|
|
@ -87,6 +114,14 @@ func can_add_item(item_id: StringName, quantity: int = 1) -> bool:
|
||||||
if item == null or quantity <= 0:
|
if item == null or quantity <= 0:
|
||||||
return false
|
return false
|
||||||
var existing: OwnedItemType = get_owned_item(item_id)
|
var existing: OwnedItemType = get_owned_item(item_id)
|
||||||
|
if DecorCatalogType.has_product(item_id):
|
||||||
|
return (
|
||||||
|
_can_own_quantity(item, existing, quantity)
|
||||||
|
and (
|
||||||
|
_inventory_layout == null
|
||||||
|
or _inventory_layout.can_accept_item(item_id, quantity)
|
||||||
|
)
|
||||||
|
)
|
||||||
if existing != null:
|
if existing != null:
|
||||||
return (
|
return (
|
||||||
item.stackable
|
item.stackable
|
||||||
|
|
@ -226,7 +261,7 @@ func replace_all_items(items: Array[OwnedItemType]) -> bool:
|
||||||
var item: ItemDataType = _resolve_valid_item(owned.item_id)
|
var item: ItemDataType = _resolve_valid_item(owned.item_id)
|
||||||
if item == null:
|
if item == null:
|
||||||
return false
|
return false
|
||||||
var maximum: int = item.max_stack if item.stackable else 1
|
var maximum: int = _maximum_owned_quantity(item)
|
||||||
if owned.quantity > maximum:
|
if owned.quantity > maximum:
|
||||||
return false
|
return false
|
||||||
seen[owned.item_id] = true
|
seen[owned.item_id] = true
|
||||||
|
|
@ -319,3 +354,22 @@ func _resolve_valid_item(item_id: StringName) -> ItemDataType:
|
||||||
func _resolve_available_item(item_id: StringName) -> ItemDataType:
|
func _resolve_available_item(item_id: StringName) -> ItemDataType:
|
||||||
var item: ItemDataType = _resolve_valid_item(item_id)
|
var item: ItemDataType = _resolve_valid_item(item_id)
|
||||||
return item if item != null and item.active else null
|
return item if item != null and item.active else null
|
||||||
|
|
||||||
|
|
||||||
|
func _can_own_quantity(
|
||||||
|
item: ItemDataType,
|
||||||
|
existing: OwnedItemType,
|
||||||
|
quantity: int,
|
||||||
|
) -> bool:
|
||||||
|
if item == null or quantity <= 0:
|
||||||
|
return false
|
||||||
|
var current: int = existing.quantity if existing != null else 0
|
||||||
|
return current + quantity <= _maximum_owned_quantity(item)
|
||||||
|
|
||||||
|
|
||||||
|
func _maximum_owned_quantity(item: ItemDataType) -> int:
|
||||||
|
if item == null:
|
||||||
|
return 0
|
||||||
|
if DecorCatalogType.has_product(item.item_id):
|
||||||
|
return mini(item.max_stack, DecorCatalogType.MAX_OWNED_PER_PRODUCT)
|
||||||
|
return item.max_stack if item.stackable else 1
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ const PlayerCoolerCapacityType = preload(
|
||||||
"res://progression/player_cooler_capacity.gd"
|
"res://progression/player_cooler_capacity.gd"
|
||||||
)
|
)
|
||||||
const PlayerWalletType = preload("res://economy/player_wallet.gd")
|
const PlayerWalletType = preload("res://economy/player_wallet.gd")
|
||||||
|
const DecorCatalogType = preload("res://homes/decor_catalog.gd")
|
||||||
|
|
||||||
const INVENTORY_COLUMNS: int = 9
|
const INVENTORY_COLUMNS: int = 9
|
||||||
const INVENTORY_CAPACITIES: Array[int] = [9, 18, 27, 36]
|
const INVENTORY_CAPACITIES: Array[int] = [9, 18, 27, 36]
|
||||||
|
|
@ -37,7 +38,7 @@ var _fish_inventory: FishInventoryType
|
||||||
var _item_catalog: ItemCatalogType
|
var _item_catalog: ItemCatalogType
|
||||||
var _storage_capacity: PlayerCoolerCapacityType
|
var _storage_capacity: PlayerCoolerCapacityType
|
||||||
var _placements: Dictionary[String, Dictionary] = {}
|
var _placements: Dictionary[String, Dictionary] = {}
|
||||||
var _prepared_item_placements: Dictionary[String, Dictionary] = {}
|
var _prepared_item_placements: Dictionary[StringName, Array] = {}
|
||||||
var _reconciling: bool = false
|
var _reconciling: bool = false
|
||||||
var _backpack_level: int = 0
|
var _backpack_level: int = 0
|
||||||
|
|
||||||
|
|
@ -69,14 +70,31 @@ func setup(
|
||||||
_reconcile(true)
|
_reconcile(true)
|
||||||
|
|
||||||
|
|
||||||
func can_accept_item(item_id: StringName) -> bool:
|
func can_accept_item(item_id: StringName, quantity: int = 1) -> bool:
|
||||||
if not is_managed_item(item_id):
|
if not is_managed_item(item_id):
|
||||||
return true
|
return true
|
||||||
var key := item_key(item_id)
|
if quantity <= 0:
|
||||||
|
return false
|
||||||
|
if _uses_individual_item_slots(item_id):
|
||||||
|
var available: int = _available_new_item_slots(
|
||||||
|
item_id, InventoryContainer.INVENTORY
|
||||||
|
)
|
||||||
|
for value: Variant in _prepared_item_placements.get(item_id, []):
|
||||||
|
if typeof(value) != TYPE_DICTIONARY:
|
||||||
|
continue
|
||||||
|
var placement := value as Dictionary
|
||||||
|
if (
|
||||||
|
int(placement.get("container", -1))
|
||||||
|
!= InventoryContainer.INVENTORY
|
||||||
|
and _prepared_item_placement_available(placement)
|
||||||
|
):
|
||||||
|
available += 1
|
||||||
|
return available >= quantity
|
||||||
|
var key := _find_entry_key(EntryKind.ITEM, item_id)
|
||||||
return (
|
return (
|
||||||
_placements.has(key)
|
not key.is_empty()
|
||||||
or _is_prepared_item_placement_available(key)
|
or _has_available_prepared_item_placement(item_id)
|
||||||
or _first_free_slot(InventoryContainer.INVENTORY) >= 0
|
or _first_available_slot(InventoryContainer.INVENTORY) >= 0
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -87,30 +105,53 @@ func prepare_new_item_placement(
|
||||||
) -> bool:
|
) -> bool:
|
||||||
if not is_managed_item(item_id):
|
if not is_managed_item(item_id):
|
||||||
return false
|
return false
|
||||||
var key := item_key(item_id)
|
|
||||||
if (
|
if (
|
||||||
_placements.has(key)
|
(not _uses_individual_item_slots(item_id)
|
||||||
|
and not _find_entry_key(EntryKind.ITEM, item_id).is_empty())
|
||||||
or not _is_slot_valid(target_container, target_slot)
|
or not _is_slot_valid(target_container, target_slot)
|
||||||
or not _key_at(target_container, target_slot).is_empty()
|
or not _key_at(target_container, target_slot).is_empty()
|
||||||
or _prepared_slot_is_occupied(target_container, target_slot)
|
or _prepared_slot_is_occupied(target_container, target_slot)
|
||||||
):
|
):
|
||||||
return false
|
return false
|
||||||
_prepared_item_placements[key] = {
|
var prepared: Array = _prepared_item_placements.get(item_id, [])
|
||||||
|
prepared.append({
|
||||||
"container": int(target_container),
|
"container": int(target_container),
|
||||||
"slot": target_slot,
|
"slot": target_slot,
|
||||||
}
|
})
|
||||||
|
_prepared_item_placements[item_id] = prepared
|
||||||
return true
|
return true
|
||||||
|
|
||||||
|
|
||||||
func cancel_prepared_item_placement(item_id: StringName) -> void:
|
func cancel_prepared_item_placement(item_id: StringName) -> void:
|
||||||
_prepared_item_placements.erase(item_key(item_id))
|
_prepared_item_placements.erase(item_id)
|
||||||
|
|
||||||
|
|
||||||
func can_accept_item_in_storage(item_id: StringName) -> bool:
|
func prepare_new_item_in_first_free(
|
||||||
|
item_id: StringName,
|
||||||
|
target_container: InventoryContainer,
|
||||||
|
) -> bool:
|
||||||
|
var slot := _first_available_slot(target_container)
|
||||||
|
return slot >= 0 and prepare_new_item_placement(
|
||||||
|
item_id, target_container, slot
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
func can_accept_item_in_storage(
|
||||||
|
item_id: StringName,
|
||||||
|
quantity: int = 1,
|
||||||
|
) -> bool:
|
||||||
if not is_managed_item(item_id):
|
if not is_managed_item(item_id):
|
||||||
return true
|
return true
|
||||||
var key := item_key(item_id)
|
if quantity <= 0:
|
||||||
return _placements.has(key) or _first_free_slot(InventoryContainer.STORAGE) >= 0
|
return false
|
||||||
|
if _uses_individual_item_slots(item_id):
|
||||||
|
return _available_new_item_slots(
|
||||||
|
item_id, InventoryContainer.STORAGE
|
||||||
|
) >= quantity
|
||||||
|
return (
|
||||||
|
not _find_entry_key(EntryKind.ITEM, item_id).is_empty()
|
||||||
|
or _first_available_slot(InventoryContainer.STORAGE) >= 0
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
func can_accept_catch(catch_id: StringName = StringName()) -> bool:
|
func can_accept_catch(catch_id: StringName = StringName()) -> bool:
|
||||||
|
|
@ -128,19 +169,23 @@ func is_managed_item(item_id: StringName) -> bool:
|
||||||
|
|
||||||
|
|
||||||
func is_item_in_inventory(item_id: StringName) -> bool:
|
func is_item_in_inventory(item_id: StringName) -> bool:
|
||||||
return _is_entry_in_container(item_key(item_id), InventoryContainer.INVENTORY)
|
return _has_entry_in_container(
|
||||||
|
EntryKind.ITEM, item_id, InventoryContainer.INVENTORY
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
func is_catch_in_inventory(catch_id: StringName) -> bool:
|
func is_catch_in_inventory(catch_id: StringName) -> bool:
|
||||||
return _is_entry_in_container(catch_key(catch_id), InventoryContainer.INVENTORY)
|
return _has_entry_in_container(
|
||||||
|
EntryKind.CATCH, catch_id, InventoryContainer.INVENTORY
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
func is_item_carried(item_id: StringName) -> bool:
|
func is_item_carried(item_id: StringName) -> bool:
|
||||||
return _is_entry_carried(item_key(item_id))
|
return _has_carried_entry(EntryKind.ITEM, item_id)
|
||||||
|
|
||||||
|
|
||||||
func is_catch_carried(catch_id: StringName) -> bool:
|
func is_catch_carried(catch_id: StringName) -> bool:
|
||||||
return _is_entry_carried(catch_key(catch_id))
|
return _has_carried_entry(EntryKind.CATCH, catch_id)
|
||||||
|
|
||||||
|
|
||||||
func get_inventory_count() -> int:
|
func get_inventory_count() -> int:
|
||||||
|
|
@ -223,7 +268,9 @@ func get_entries(container: InventoryContainer) -> Array[Dictionary]:
|
||||||
|
|
||||||
|
|
||||||
func get_entry(kind: EntryKind, identity: StringName) -> Dictionary:
|
func get_entry(kind: EntryKind, identity: StringName) -> Dictionary:
|
||||||
var key := _entry_key(kind, identity)
|
var key := _find_entry_key(kind, identity)
|
||||||
|
if key.is_empty():
|
||||||
|
return {}
|
||||||
return _placements.get(key, {}).duplicate(true)
|
return _placements.get(key, {}).duplicate(true)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -252,7 +299,17 @@ func move_entry(
|
||||||
target_container: InventoryContainer,
|
target_container: InventoryContainer,
|
||||||
target_slot: int,
|
target_slot: int,
|
||||||
) -> bool:
|
) -> bool:
|
||||||
var key := _entry_key(kind, identity)
|
var key := _find_entry_key_for_move(
|
||||||
|
kind, identity, target_container, target_slot
|
||||||
|
)
|
||||||
|
return move_entry_by_key(key, target_container, target_slot)
|
||||||
|
|
||||||
|
|
||||||
|
func move_entry_by_key(
|
||||||
|
key: String,
|
||||||
|
target_container: InventoryContainer,
|
||||||
|
target_slot: int,
|
||||||
|
) -> bool:
|
||||||
if not _placements.has(key) or not _is_slot_valid(target_container, target_slot):
|
if not _placements.has(key) or not _is_slot_valid(target_container, target_slot):
|
||||||
return false
|
return false
|
||||||
var source: Dictionary = _placements[key]
|
var source: Dictionary = _placements[key]
|
||||||
|
|
@ -285,15 +342,20 @@ func move_entry_to_first_free(
|
||||||
return slot >= 0 and move_entry(kind, identity, target_container, slot)
|
return slot >= 0 and move_entry(kind, identity, target_container, slot)
|
||||||
|
|
||||||
|
|
||||||
|
func move_entry_key_to_first_free(
|
||||||
|
key: String,
|
||||||
|
target_container: InventoryContainer,
|
||||||
|
) -> bool:
|
||||||
|
var slot := _first_free_slot(target_container)
|
||||||
|
return slot >= 0 and move_entry_by_key(key, target_container, slot)
|
||||||
|
|
||||||
|
|
||||||
func return_hotbar_entry_to_inventory(slot: int) -> bool:
|
func return_hotbar_entry_to_inventory(slot: int) -> bool:
|
||||||
var key := _key_at(InventoryContainer.HOTBAR, slot)
|
var key := _key_at(InventoryContainer.HOTBAR, slot)
|
||||||
if key.is_empty():
|
if key.is_empty():
|
||||||
return true
|
return true
|
||||||
var placement: Dictionary = _placements[key]
|
return move_entry_key_to_first_free(
|
||||||
return move_entry_to_first_free(
|
key, InventoryContainer.INVENTORY
|
||||||
int(placement.get("kind", -1)) as EntryKind,
|
|
||||||
StringName(str(placement.get("identity", ""))),
|
|
||||||
InventoryContainer.INVENTORY,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -302,10 +364,8 @@ func return_all_hotbar_entries_to_inventory() -> bool:
|
||||||
if get_inventory_count() + entries.size() > get_inventory_capacity():
|
if get_inventory_count() + entries.size() > get_inventory_capacity():
|
||||||
return false
|
return false
|
||||||
for entry: Dictionary in entries:
|
for entry: Dictionary in entries:
|
||||||
if not move_entry_to_first_free(
|
if not move_entry_key_to_first_free(
|
||||||
int(entry.get("kind", -1)) as EntryKind,
|
str(entry.get("key", "")), InventoryContainer.INVENTORY
|
||||||
StringName(str(entry.get("identity", ""))),
|
|
||||||
InventoryContainer.INVENTORY,
|
|
||||||
):
|
):
|
||||||
return false
|
return false
|
||||||
return true
|
return true
|
||||||
|
|
@ -321,6 +381,7 @@ func to_save_data() -> Dictionary:
|
||||||
serialized.append({
|
serialized.append({
|
||||||
"kind": int(placement.get("kind", EntryKind.ITEM)),
|
"kind": int(placement.get("kind", EntryKind.ITEM)),
|
||||||
"identity": str(placement.get("identity", "")),
|
"identity": str(placement.get("identity", "")),
|
||||||
|
"unit": int(placement.get("unit", -1)),
|
||||||
"container": int(placement.get("container", InventoryContainer.INVENTORY)),
|
"container": int(placement.get("container", InventoryContainer.INVENTORY)),
|
||||||
"slot": int(placement.get("slot", -1)),
|
"slot": int(placement.get("slot", -1)),
|
||||||
})
|
})
|
||||||
|
|
@ -339,6 +400,7 @@ func restore_from_save_data(data: Dictionary) -> bool:
|
||||||
return false
|
return false
|
||||||
_backpack_level = clampi(int(level_value), 0, MAX_BACKPACK_LEVEL)
|
_backpack_level = clampi(int(level_value), 0, MAX_BACKPACK_LEVEL)
|
||||||
var restored: Dictionary[String, Dictionary] = {}
|
var restored: Dictionary[String, Dictionary] = {}
|
||||||
|
var restored_item_units: Dictionary[StringName, Dictionary] = {}
|
||||||
var values: Variant = data.get("placements", [])
|
var values: Variant = data.get("placements", [])
|
||||||
if typeof(values) != TYPE_ARRAY:
|
if typeof(values) != TYPE_ARRAY:
|
||||||
return false
|
return false
|
||||||
|
|
@ -361,12 +423,27 @@ func restore_from_save_data(data: Dictionary) -> bool:
|
||||||
or not _is_slot_valid(container as InventoryContainer, slot)
|
or not _is_slot_valid(container as InventoryContainer, slot)
|
||||||
):
|
):
|
||||||
continue
|
continue
|
||||||
var key := _entry_key(kind as EntryKind, identity)
|
var unit: int = -1
|
||||||
|
var key: String
|
||||||
|
if (
|
||||||
|
kind == EntryKind.ITEM
|
||||||
|
and _uses_individual_item_slots(identity)
|
||||||
|
):
|
||||||
|
var used_units: Dictionary = restored_item_units.get(identity, {})
|
||||||
|
unit = int(record.get("unit", -1))
|
||||||
|
if unit < 0 or used_units.has(unit):
|
||||||
|
unit = _first_unused_unit(used_units)
|
||||||
|
used_units[unit] = true
|
||||||
|
restored_item_units[identity] = used_units
|
||||||
|
key = item_unit_key(identity, unit)
|
||||||
|
else:
|
||||||
|
key = _entry_key(kind as EntryKind, identity)
|
||||||
if restored.has(key) or _placement_slot_occupied(restored, container, slot):
|
if restored.has(key) or _placement_slot_occupied(restored, container, slot):
|
||||||
continue
|
continue
|
||||||
restored[key] = {
|
restored[key] = {
|
||||||
"kind": kind,
|
"kind": kind,
|
||||||
"identity": identity,
|
"identity": identity,
|
||||||
|
"unit": unit,
|
||||||
"container": container,
|
"container": container,
|
||||||
"slot": slot,
|
"slot": slot,
|
||||||
}
|
}
|
||||||
|
|
@ -390,6 +467,10 @@ static func item_key(item_id: StringName) -> String:
|
||||||
return "item:%s" % String(item_id)
|
return "item:%s" % String(item_id)
|
||||||
|
|
||||||
|
|
||||||
|
static func item_unit_key(item_id: StringName, unit: int) -> String:
|
||||||
|
return "%s:unit:%d" % [item_key(item_id), unit]
|
||||||
|
|
||||||
|
|
||||||
static func catch_key(catch_id: StringName) -> String:
|
static func catch_key(catch_id: StringName) -> String:
|
||||||
return "catch:%s" % String(catch_id)
|
return "catch:%s" % String(catch_id)
|
||||||
|
|
||||||
|
|
@ -398,15 +479,27 @@ func _entry_key(kind: EntryKind, identity: StringName) -> String:
|
||||||
return item_key(identity) if kind == EntryKind.ITEM else catch_key(identity)
|
return item_key(identity) if kind == EntryKind.ITEM else catch_key(identity)
|
||||||
|
|
||||||
|
|
||||||
func _is_entry_in_container(key: String, container: InventoryContainer) -> bool:
|
func _has_entry_in_container(
|
||||||
var placement: Dictionary = _placements.get(key, {})
|
kind: EntryKind,
|
||||||
return int(placement.get("container", -1)) == int(container)
|
identity: StringName,
|
||||||
|
container: InventoryContainer,
|
||||||
|
) -> bool:
|
||||||
|
for key: String in _placements:
|
||||||
|
var placement: Dictionary = _placements[key]
|
||||||
|
if (
|
||||||
|
int(placement.get("kind", -1)) == int(kind)
|
||||||
|
and StringName(str(placement.get("identity", ""))) == identity
|
||||||
|
and int(placement.get("container", -1)) == int(container)
|
||||||
|
):
|
||||||
|
return true
|
||||||
|
return false
|
||||||
|
|
||||||
|
|
||||||
func _is_entry_carried(key: String) -> bool:
|
func _has_carried_entry(kind: EntryKind, identity: StringName) -> bool:
|
||||||
var placement: Dictionary = _placements.get(key, {})
|
return (
|
||||||
var container: int = int(placement.get("container", -1))
|
_has_entry_in_container(kind, identity, InventoryContainer.INVENTORY)
|
||||||
return container in [InventoryContainer.INVENTORY, InventoryContainer.HOTBAR]
|
or _has_entry_in_container(kind, identity, InventoryContainer.HOTBAR)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
func _on_contents_changed() -> void:
|
func _on_contents_changed() -> void:
|
||||||
|
|
@ -425,8 +518,17 @@ func _reconcile(force_signal: bool) -> void:
|
||||||
for owned in _bag.get_all_items():
|
for owned in _bag.get_all_items():
|
||||||
if owned == null or not is_managed_item(owned.item_id):
|
if owned == null or not is_managed_item(owned.item_id):
|
||||||
continue
|
continue
|
||||||
var key := item_key(owned.item_id)
|
if _uses_individual_item_slots(owned.item_id):
|
||||||
expected[key] = {"kind": EntryKind.ITEM, "identity": owned.item_id}
|
_add_expected_individual_items(
|
||||||
|
expected, owned.item_id, owned.quantity
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
var key := item_key(owned.item_id)
|
||||||
|
expected[key] = {
|
||||||
|
"kind": EntryKind.ITEM,
|
||||||
|
"identity": owned.item_id,
|
||||||
|
"unit": -1,
|
||||||
|
}
|
||||||
for fish_catch in _fish_inventory.get_all_catches():
|
for fish_catch in _fish_inventory.get_all_catches():
|
||||||
if fish_catch == null or not fish_catch.is_valid():
|
if fish_catch == null or not fish_catch.is_valid():
|
||||||
continue
|
continue
|
||||||
|
|
@ -442,15 +544,15 @@ func _reconcile(force_signal: bool) -> void:
|
||||||
for key: String in expected:
|
for key: String in expected:
|
||||||
if _placements.has(key):
|
if _placements.has(key):
|
||||||
continue
|
continue
|
||||||
var prepared: Dictionary = _prepared_item_placements.get(key, {})
|
var identity := StringName(str(expected[key].get("identity", "")))
|
||||||
|
var prepared: Dictionary = _take_prepared_item_placement(identity)
|
||||||
var target_container := InventoryContainer.INVENTORY
|
var target_container := InventoryContainer.INVENTORY
|
||||||
var target_slot: int = -1
|
var target_slot: int = -1
|
||||||
if _is_prepared_item_placement_available(key):
|
if not prepared.is_empty():
|
||||||
target_container = int(
|
target_container = int(
|
||||||
prepared["container"]
|
prepared["container"]
|
||||||
) as InventoryContainer
|
) as InventoryContainer
|
||||||
target_slot = int(prepared["slot"])
|
target_slot = int(prepared["slot"])
|
||||||
_prepared_item_placements.erase(key)
|
|
||||||
if target_slot < 0:
|
if target_slot < 0:
|
||||||
target_slot = _first_free_slot(target_container)
|
target_slot = _first_free_slot(target_container)
|
||||||
if target_slot < 0:
|
if target_slot < 0:
|
||||||
|
|
@ -469,6 +571,59 @@ func _reconcile(force_signal: bool) -> void:
|
||||||
layout_changed.emit()
|
layout_changed.emit()
|
||||||
|
|
||||||
|
|
||||||
|
func _add_expected_individual_items(
|
||||||
|
expected: Dictionary[String, Dictionary],
|
||||||
|
item_id: StringName,
|
||||||
|
quantity: int,
|
||||||
|
) -> void:
|
||||||
|
var existing_keys: Array[String] = _item_entry_keys(item_id)
|
||||||
|
existing_keys.sort_custom(
|
||||||
|
func(left: String, right: String) -> bool:
|
||||||
|
return _placement_preservation_priority(left) < (
|
||||||
|
_placement_preservation_priority(right)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
var used_units: Dictionary[int, bool] = {}
|
||||||
|
var retained: int = 0
|
||||||
|
for key: String in existing_keys:
|
||||||
|
if retained >= quantity:
|
||||||
|
break
|
||||||
|
var placement: Dictionary = _placements[key]
|
||||||
|
var unit: int = int(placement.get("unit", -1))
|
||||||
|
if unit < 0 or used_units.has(unit):
|
||||||
|
continue
|
||||||
|
used_units[unit] = true
|
||||||
|
expected[key] = {
|
||||||
|
"kind": EntryKind.ITEM,
|
||||||
|
"identity": item_id,
|
||||||
|
"unit": unit,
|
||||||
|
}
|
||||||
|
retained += 1
|
||||||
|
while retained < quantity:
|
||||||
|
var unit := _first_unused_unit(used_units)
|
||||||
|
used_units[unit] = true
|
||||||
|
var key := item_unit_key(item_id, unit)
|
||||||
|
expected[key] = {
|
||||||
|
"kind": EntryKind.ITEM,
|
||||||
|
"identity": item_id,
|
||||||
|
"unit": unit,
|
||||||
|
}
|
||||||
|
retained += 1
|
||||||
|
|
||||||
|
|
||||||
|
func _placement_preservation_priority(key: String) -> int:
|
||||||
|
var placement: Dictionary = _placements.get(key, {})
|
||||||
|
var container: int = int(placement.get("container", -1))
|
||||||
|
match container:
|
||||||
|
InventoryContainer.HOTBAR:
|
||||||
|
return 0
|
||||||
|
InventoryContainer.INVENTORY:
|
||||||
|
return 1
|
||||||
|
InventoryContainer.STORAGE:
|
||||||
|
return 2
|
||||||
|
return 3
|
||||||
|
|
||||||
|
|
||||||
func _normalize_existing_placements() -> void:
|
func _normalize_existing_placements() -> void:
|
||||||
var occupied_inventory: Dictionary[int, bool] = {}
|
var occupied_inventory: Dictionary[int, bool] = {}
|
||||||
var occupied_storage: Dictionary[int, bool] = {}
|
var occupied_storage: Dictionary[int, bool] = {}
|
||||||
|
|
@ -528,15 +683,55 @@ func _first_free_slot(container: InventoryContainer) -> int:
|
||||||
else get_storage_capacity()
|
else get_storage_capacity()
|
||||||
)
|
)
|
||||||
for slot: int in capacity:
|
for slot: int in capacity:
|
||||||
if _key_at(container, slot).is_empty():
|
if (
|
||||||
|
_key_at(container, slot).is_empty()
|
||||||
|
and not _prepared_slot_is_occupied(container, slot)
|
||||||
|
):
|
||||||
return slot
|
return slot
|
||||||
return -1
|
return -1
|
||||||
|
|
||||||
|
|
||||||
func _is_prepared_item_placement_available(key: String) -> bool:
|
func _first_available_slot(container: InventoryContainer) -> int:
|
||||||
var placement: Dictionary = _prepared_item_placements.get(key, {})
|
var capacity := (
|
||||||
if placement.is_empty():
|
get_inventory_capacity() if container == InventoryContainer.INVENTORY
|
||||||
return false
|
else HOTBAR_SLOT_COUNT if container == InventoryContainer.HOTBAR
|
||||||
|
else get_storage_capacity()
|
||||||
|
)
|
||||||
|
for slot: int in capacity:
|
||||||
|
if (
|
||||||
|
_key_at(container, slot).is_empty()
|
||||||
|
and not _prepared_slot_is_occupied(container, slot)
|
||||||
|
):
|
||||||
|
return slot
|
||||||
|
return -1
|
||||||
|
|
||||||
|
|
||||||
|
func _has_available_prepared_item_placement(item_id: StringName) -> bool:
|
||||||
|
for value: Variant in _prepared_item_placements.get(item_id, []):
|
||||||
|
if typeof(value) != TYPE_DICTIONARY:
|
||||||
|
continue
|
||||||
|
if _prepared_item_placement_available(value as Dictionary):
|
||||||
|
return true
|
||||||
|
return false
|
||||||
|
|
||||||
|
|
||||||
|
func _take_prepared_item_placement(item_id: StringName) -> Dictionary:
|
||||||
|
var prepared: Array = _prepared_item_placements.get(item_id, [])
|
||||||
|
while not prepared.is_empty():
|
||||||
|
var value: Variant = prepared.pop_front()
|
||||||
|
if prepared.is_empty():
|
||||||
|
_prepared_item_placements.erase(item_id)
|
||||||
|
else:
|
||||||
|
_prepared_item_placements[item_id] = prepared
|
||||||
|
if (
|
||||||
|
typeof(value) == TYPE_DICTIONARY
|
||||||
|
and _prepared_item_placement_available(value as Dictionary)
|
||||||
|
):
|
||||||
|
return (value as Dictionary).duplicate(true)
|
||||||
|
return {}
|
||||||
|
|
||||||
|
|
||||||
|
func _prepared_item_placement_available(placement: Dictionary) -> bool:
|
||||||
var container: int = int(placement.get("container", -1))
|
var container: int = int(placement.get("container", -1))
|
||||||
var slot: int = int(placement.get("slot", -1))
|
var slot: int = int(placement.get("slot", -1))
|
||||||
if (
|
if (
|
||||||
|
|
@ -555,13 +750,120 @@ func _prepared_slot_is_occupied(
|
||||||
container: InventoryContainer,
|
container: InventoryContainer,
|
||||||
slot: int,
|
slot: int,
|
||||||
) -> bool:
|
) -> bool:
|
||||||
for placement: Dictionary in _prepared_item_placements.values():
|
for prepared: Array in _prepared_item_placements.values():
|
||||||
|
for value: Variant in prepared:
|
||||||
|
if typeof(value) != TYPE_DICTIONARY:
|
||||||
|
continue
|
||||||
|
var placement := value as Dictionary
|
||||||
|
if (
|
||||||
|
int(placement.get("container", -1)) == int(container)
|
||||||
|
and int(placement.get("slot", -1)) == slot
|
||||||
|
):
|
||||||
|
return true
|
||||||
|
return false
|
||||||
|
|
||||||
|
|
||||||
|
func _available_new_item_slots(
|
||||||
|
item_id: StringName,
|
||||||
|
container: InventoryContainer,
|
||||||
|
) -> int:
|
||||||
|
var available: int = 0
|
||||||
|
for value: Variant in _prepared_item_placements.get(item_id, []):
|
||||||
|
if typeof(value) != TYPE_DICTIONARY:
|
||||||
|
continue
|
||||||
|
var placement := value as Dictionary
|
||||||
if (
|
if (
|
||||||
int(placement.get("container", -1)) == int(container)
|
int(placement.get("container", -1)) == int(container)
|
||||||
and int(placement.get("slot", -1)) == slot
|
and _prepared_item_placement_available(placement)
|
||||||
):
|
):
|
||||||
return true
|
available += 1
|
||||||
return false
|
var capacity := (
|
||||||
|
get_inventory_capacity() if container == InventoryContainer.INVENTORY
|
||||||
|
else HOTBAR_SLOT_COUNT if container == InventoryContainer.HOTBAR
|
||||||
|
else get_storage_capacity()
|
||||||
|
)
|
||||||
|
for slot: int in capacity:
|
||||||
|
if (
|
||||||
|
_key_at(container, slot).is_empty()
|
||||||
|
and not _prepared_slot_is_occupied(container, slot)
|
||||||
|
):
|
||||||
|
available += 1
|
||||||
|
return available
|
||||||
|
|
||||||
|
|
||||||
|
func _uses_individual_item_slots(item_id: StringName) -> bool:
|
||||||
|
return DecorCatalogType.has_product(item_id)
|
||||||
|
|
||||||
|
|
||||||
|
func _item_entry_keys(item_id: StringName) -> Array[String]:
|
||||||
|
var result: Array[String] = []
|
||||||
|
for key: String in _placements:
|
||||||
|
var placement: Dictionary = _placements[key]
|
||||||
|
if (
|
||||||
|
int(placement.get("kind", -1)) == EntryKind.ITEM
|
||||||
|
and StringName(str(placement.get("identity", ""))) == item_id
|
||||||
|
):
|
||||||
|
result.append(key)
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
func _find_entry_key(kind: EntryKind, identity: StringName) -> String:
|
||||||
|
var preferred_key: String = ""
|
||||||
|
var preferred_priority: int = 99
|
||||||
|
for key: String in _placements:
|
||||||
|
var placement: Dictionary = _placements[key]
|
||||||
|
if (
|
||||||
|
int(placement.get("kind", -1)) != int(kind)
|
||||||
|
or StringName(str(placement.get("identity", ""))) != identity
|
||||||
|
):
|
||||||
|
continue
|
||||||
|
var priority := _placement_preservation_priority(key)
|
||||||
|
if priority < preferred_priority:
|
||||||
|
preferred_key = key
|
||||||
|
preferred_priority = priority
|
||||||
|
return preferred_key
|
||||||
|
|
||||||
|
|
||||||
|
func _find_entry_key_for_move(
|
||||||
|
kind: EntryKind,
|
||||||
|
identity: StringName,
|
||||||
|
target_container: InventoryContainer,
|
||||||
|
target_slot: int,
|
||||||
|
) -> String:
|
||||||
|
var target_key := _key_at(target_container, target_slot)
|
||||||
|
if not target_key.is_empty():
|
||||||
|
var target: Dictionary = _placements[target_key]
|
||||||
|
if (
|
||||||
|
int(target.get("kind", -1)) == int(kind)
|
||||||
|
and StringName(str(target.get("identity", ""))) == identity
|
||||||
|
):
|
||||||
|
return target_key
|
||||||
|
var preferred_key: String = ""
|
||||||
|
var preferred_priority: int = 99
|
||||||
|
for key: String in _placements:
|
||||||
|
var placement: Dictionary = _placements[key]
|
||||||
|
if (
|
||||||
|
int(placement.get("kind", -1)) != int(kind)
|
||||||
|
or StringName(str(placement.get("identity", ""))) != identity
|
||||||
|
):
|
||||||
|
continue
|
||||||
|
var container: int = int(placement.get("container", -1))
|
||||||
|
var priority: int = (
|
||||||
|
0 if container == InventoryContainer.INVENTORY
|
||||||
|
else 1 if container == InventoryContainer.STORAGE
|
||||||
|
else 2
|
||||||
|
)
|
||||||
|
if priority < preferred_priority:
|
||||||
|
preferred_key = key
|
||||||
|
preferred_priority = priority
|
||||||
|
return preferred_key
|
||||||
|
|
||||||
|
|
||||||
|
func _first_unused_unit(used_units: Dictionary) -> int:
|
||||||
|
var unit: int = 0
|
||||||
|
while used_units.has(unit):
|
||||||
|
unit += 1
|
||||||
|
return unit
|
||||||
|
|
||||||
|
|
||||||
func _key_at(container: InventoryContainer, slot: int) -> String:
|
func _key_at(container: InventoryContainer, slot: int) -> String:
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ display_name = "basic cube"
|
||||||
description = "a simple piece of decor for testing your RV layout."
|
description = "a simple piece of decor for testing your RV layout."
|
||||||
category = 6
|
category = 6
|
||||||
icon = ExtResource("2_icon")
|
icon = ExtResource("2_icon")
|
||||||
stackable = true
|
stackable = false
|
||||||
max_stack = 32
|
max_stack = 32
|
||||||
usable = false
|
usable = false
|
||||||
equippable = true
|
equippable = true
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,6 @@ func is_valid() -> bool:
|
||||||
not item_id.is_empty()
|
not item_id.is_empty()
|
||||||
and not display_name.strip_edges().is_empty()
|
and not display_name.strip_edges().is_empty()
|
||||||
and max_stack >= 1
|
and max_stack >= 1
|
||||||
and (stackable or max_stack == 1)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,31 @@ func _run() -> void:
|
||||||
assert(bag.move_item_to_storage_slot(&"worms", shrimp_slot))
|
assert(bag.move_item_to_storage_slot(&"worms", shrimp_slot))
|
||||||
assert(bag.get_storage_slot(&"worms") == shrimp_slot)
|
assert(bag.get_storage_slot(&"worms") == shrimp_slot)
|
||||||
assert(bag.get_storage_slot(&"shrimp") == worms_slot)
|
assert(bag.get_storage_slot(&"shrimp") == worms_slot)
|
||||||
|
|
||||||
|
# Exhausting bait removes its owned record while retaining the unlock. A
|
||||||
|
# later refill therefore receives whichever inventory slot happens to be free
|
||||||
|
# at that moment. The tackle page must keep catalog order instead of exposing
|
||||||
|
# that incidental refill order.
|
||||||
|
for item_id: StringName in EXPECTED_BAIT_ORDER:
|
||||||
|
if bag.get_quantity(item_id) == 0:
|
||||||
|
assert(bag.add_item(item_id, 1))
|
||||||
|
for item_id: StringName in EXPECTED_BAIT_ORDER:
|
||||||
|
assert(bag.remove_item(item_id, 1))
|
||||||
|
var reverse_refill_order: Array[StringName] = EXPECTED_BAIT_ORDER.duplicate()
|
||||||
|
reverse_refill_order.reverse()
|
||||||
|
for item_id: StringName in reverse_refill_order:
|
||||||
|
assert(bag.add_item(item_id, 1))
|
||||||
|
var refilled_items: Array[OwnedItem] = bag.get_unlocked_bait_items()
|
||||||
|
refilled_items.sort_custom(
|
||||||
|
func(first: OwnedItem, second: OwnedItem) -> bool:
|
||||||
|
return bool(player_menu.call(
|
||||||
|
"_sort_tackle_items", first, second
|
||||||
|
))
|
||||||
|
)
|
||||||
|
var refilled_ids: Array[StringName] = []
|
||||||
|
for owned: OwnedItem in refilled_items:
|
||||||
|
refilled_ids.append(owned.item_id)
|
||||||
|
assert(refilled_ids == EXPECTED_BAIT_ORDER)
|
||||||
bag.free()
|
bag.free()
|
||||||
player_menu.free()
|
player_menu.free()
|
||||||
print("Tackle order validation: PASS")
|
print("Tackle order validation: PASS")
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@ func _run() -> void:
|
||||||
assert(basic_cube != null)
|
assert(basic_cube != null)
|
||||||
assert(basic_cube.icon != null)
|
assert(basic_cube.icon != null)
|
||||||
assert(basic_cube.hotbar_allowed)
|
assert(basic_cube.hotbar_allowed)
|
||||||
|
assert(not basic_cube.stackable)
|
||||||
assert(bag.add_item(&"basic_cube"))
|
assert(bag.add_item(&"basic_cube"))
|
||||||
assert(layout.is_item_in_inventory(&"basic_cube"))
|
assert(layout.is_item_in_inventory(&"basic_cube"))
|
||||||
assert(hotbar.assign_item(0, &"basic_cube"))
|
assert(hotbar.assign_item(0, &"basic_cube"))
|
||||||
|
|
@ -73,6 +74,40 @@ func _run() -> void:
|
||||||
assert(hotbar.get_selected_item_id() == &"basic_cube")
|
assert(hotbar.get_selected_item_id() == &"basic_cube")
|
||||||
assert(bag.remove_item(&"basic_cube"))
|
assert(bag.remove_item(&"basic_cube"))
|
||||||
|
|
||||||
|
# Decor ownership remains an aggregate count for persistence, but each
|
||||||
|
# physical piece receives its own movable inventory placement.
|
||||||
|
assert(bag.add_item(&"basic_cube", 3))
|
||||||
|
assert(bag.get_quantity(&"basic_cube") == 3)
|
||||||
|
assert(layout.get_inventory_count() == 3)
|
||||||
|
var decor_entries := layout.get_entries(
|
||||||
|
PlayerInventoryLayout.InventoryContainer.INVENTORY
|
||||||
|
)
|
||||||
|
assert(decor_entries.size() == 3)
|
||||||
|
var decor_keys: Dictionary[String, bool] = {}
|
||||||
|
for entry: Dictionary in decor_entries:
|
||||||
|
assert(StringName(str(entry.get("identity", ""))) == &"basic_cube")
|
||||||
|
assert(int(entry.get("unit", -1)) >= 0)
|
||||||
|
decor_keys[str(entry.get("key", ""))] = true
|
||||||
|
assert(decor_keys.size() == 3)
|
||||||
|
var moved_decor_key: String = str(decor_entries[1].get("key", ""))
|
||||||
|
assert(layout.move_entry_key_to_first_free(
|
||||||
|
moved_decor_key,
|
||||||
|
PlayerInventoryLayout.InventoryContainer.STORAGE,
|
||||||
|
))
|
||||||
|
assert(layout.get_inventory_count() == 2)
|
||||||
|
assert(layout.get_storage_count() == 1)
|
||||||
|
var decor_layout_save := layout.to_save_data()
|
||||||
|
assert(layout.move_entry_key_to_first_free(
|
||||||
|
moved_decor_key,
|
||||||
|
PlayerInventoryLayout.InventoryContainer.INVENTORY,
|
||||||
|
))
|
||||||
|
assert(layout.restore_from_save_data(decor_layout_save))
|
||||||
|
assert(layout.get_inventory_count() == 2)
|
||||||
|
assert(layout.get_storage_count() == 1)
|
||||||
|
assert(bag.remove_item(&"basic_cube", 3))
|
||||||
|
assert(layout.get_inventory_count() == 0)
|
||||||
|
assert(layout.get_storage_count() == 0)
|
||||||
|
|
||||||
assert(bag.add_item(&"coffee", 3))
|
assert(bag.add_item(&"coffee", 3))
|
||||||
assert(layout.get_inventory_count() == 1)
|
assert(layout.get_inventory_count() == 1)
|
||||||
assert(layout.get_inventory_capacity() == 9)
|
assert(layout.get_inventory_capacity() == 9)
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ var slot_index: int = -1
|
||||||
var container: int = -1
|
var container: int = -1
|
||||||
var entry_kind: int = -1
|
var entry_kind: int = -1
|
||||||
var entry_identity: StringName
|
var entry_identity: StringName
|
||||||
|
var entry_key: String = ""
|
||||||
var _locked: bool = false
|
var _locked: bool = false
|
||||||
|
|
||||||
var _layout: PlayerInventoryLayout
|
var _layout: PlayerInventoryLayout
|
||||||
|
|
@ -107,6 +108,7 @@ func refresh() -> void:
|
||||||
call_deferred("_update_context_presence")
|
call_deferred("_update_context_presence")
|
||||||
entry_kind = -1
|
entry_kind = -1
|
||||||
entry_identity = StringName()
|
entry_identity = StringName()
|
||||||
|
entry_key = ""
|
||||||
_context_text = ""
|
_context_text = ""
|
||||||
_quality_tier = -1
|
_quality_tier = -1
|
||||||
_icon.texture = null
|
_icon.texture = null
|
||||||
|
|
@ -142,6 +144,7 @@ func refresh() -> void:
|
||||||
return
|
return
|
||||||
entry_kind = int(entry.get("kind", -1))
|
entry_kind = int(entry.get("kind", -1))
|
||||||
entry_identity = StringName(str(entry.get("identity", "")))
|
entry_identity = StringName(str(entry.get("identity", "")))
|
||||||
|
entry_key = str(entry.get("key", ""))
|
||||||
if entry_kind == PlayerInventoryLayout.EntryKind.ITEM:
|
if entry_kind == PlayerInventoryLayout.EntryKind.ITEM:
|
||||||
var item: ItemDataType = (
|
var item: ItemDataType = (
|
||||||
_item_catalog.get_item_by_id(entry_identity)
|
_item_catalog.get_item_by_id(entry_identity)
|
||||||
|
|
@ -150,7 +153,11 @@ func refresh() -> void:
|
||||||
if item == null:
|
if item == null:
|
||||||
return
|
return
|
||||||
_icon.texture = item.icon
|
_icon.texture = item.icon
|
||||||
var quantity := _bag.get_quantity(entry_identity) if _bag != null else 0
|
var quantity := (
|
||||||
|
1
|
||||||
|
if int(entry.get("unit", -1)) >= 0
|
||||||
|
else _bag.get_quantity(entry_identity) if _bag != null else 0
|
||||||
|
)
|
||||||
_quantity.text = "×%d" % quantity if quantity > 1 else ""
|
_quantity.text = "×%d" % quantity if quantity > 1 else ""
|
||||||
_context_text = _item_context_text(item, quantity)
|
_context_text = _item_context_text(item, quantity)
|
||||||
accessibility_name = "%s, slot %d" % [item.display_name, slot_index + 1]
|
accessibility_name = "%s, slot %d" % [item.display_name, slot_index + 1]
|
||||||
|
|
@ -273,6 +280,7 @@ func _get_drag_data(_at_position: Vector2) -> Variant:
|
||||||
return {
|
return {
|
||||||
"kind": "bag_item",
|
"kind": "bag_item",
|
||||||
"item_id": String(entry_identity),
|
"item_id": String(entry_identity),
|
||||||
|
"entry_key": entry_key,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -310,7 +318,12 @@ func _drop_data(_at_position: Vector2, data: Variant) -> void:
|
||||||
"",
|
"",
|
||||||
)
|
)
|
||||||
))
|
))
|
||||||
moved = _layout.move_entry(kind, identity, container, slot_index)
|
var source_key: String = str(payload.get("entry_key", ""))
|
||||||
|
moved = (
|
||||||
|
_layout.move_entry_by_key(source_key, container, slot_index)
|
||||||
|
if not source_key.is_empty()
|
||||||
|
else _layout.move_entry(kind, identity, container, slot_index)
|
||||||
|
)
|
||||||
if moved:
|
if moved:
|
||||||
entry_moved.emit()
|
entry_moved.emit()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -359,6 +359,7 @@ var _selected_inventory_kind: int = -1
|
||||||
var _selected_inventory_identity: StringName
|
var _selected_inventory_identity: StringName
|
||||||
var _inventory_move_kind: int = -1
|
var _inventory_move_kind: int = -1
|
||||||
var _inventory_move_identity: StringName
|
var _inventory_move_identity: StringName
|
||||||
|
var _inventory_move_key: String = ""
|
||||||
var _context_tooltip: PanelContainer
|
var _context_tooltip: PanelContainer
|
||||||
var _context_tooltip_label: Label
|
var _context_tooltip_label: Label
|
||||||
var _context_tooltip_source: Control
|
var _context_tooltip_source: Control
|
||||||
|
|
@ -3865,6 +3866,7 @@ func _on_general_inventory_slot_activated(
|
||||||
return
|
return
|
||||||
_inventory_move_kind = slot.entry_kind
|
_inventory_move_kind = slot.entry_kind
|
||||||
_inventory_move_identity = slot.entry_identity
|
_inventory_move_identity = slot.entry_identity
|
||||||
|
_inventory_move_key = slot.entry_key
|
||||||
_selected_inventory_kind = slot.entry_kind
|
_selected_inventory_kind = slot.entry_kind
|
||||||
_selected_inventory_identity = slot.entry_identity
|
_selected_inventory_identity = slot.entry_identity
|
||||||
_selected_bag_item_id = (
|
_selected_bag_item_id = (
|
||||||
|
|
@ -3883,15 +3885,23 @@ func _on_general_inventory_slot_activated(
|
||||||
return
|
return
|
||||||
var move_kind: int = _inventory_move_kind
|
var move_kind: int = _inventory_move_kind
|
||||||
var move_identity: StringName = _inventory_move_identity
|
var move_identity: StringName = _inventory_move_identity
|
||||||
|
var move_key: String = _inventory_move_key
|
||||||
_cancel_inventory_move(false)
|
_cancel_inventory_move(false)
|
||||||
if _inventory_layout == null:
|
if _inventory_layout == null:
|
||||||
return
|
return
|
||||||
_inventory_layout.move_entry(
|
if not move_key.is_empty():
|
||||||
move_kind,
|
_inventory_layout.move_entry_by_key(
|
||||||
move_identity,
|
move_key,
|
||||||
PlayerInventoryLayout.InventoryContainer.INVENTORY,
|
PlayerInventoryLayout.InventoryContainer.INVENTORY,
|
||||||
slot.slot_index,
|
slot.slot_index,
|
||||||
)
|
)
|
||||||
|
else:
|
||||||
|
_inventory_layout.move_entry(
|
||||||
|
move_kind,
|
||||||
|
move_identity,
|
||||||
|
PlayerInventoryLayout.InventoryContainer.INVENTORY,
|
||||||
|
slot.slot_index,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
func _open_general_inventory_notepad(
|
func _open_general_inventory_notepad(
|
||||||
|
|
@ -3944,6 +3954,7 @@ func _cancel_inventory_move(hide_tooltip: bool = true) -> bool:
|
||||||
return false
|
return false
|
||||||
_inventory_move_kind = -1
|
_inventory_move_kind = -1
|
||||||
_inventory_move_identity = StringName()
|
_inventory_move_identity = StringName()
|
||||||
|
_inventory_move_key = ""
|
||||||
if _general_inventory_grid != null:
|
if _general_inventory_grid != null:
|
||||||
for slot: GeneralInventorySlotType in _general_inventory_grid.get_slots():
|
for slot: GeneralInventorySlotType in _general_inventory_grid.get_slots():
|
||||||
slot.set_move_source(false)
|
slot.set_move_source(false)
|
||||||
|
|
@ -4316,12 +4327,6 @@ func _sort_bag_storage_items(a: OwnedItemType, b: OwnedItemType) -> bool:
|
||||||
|
|
||||||
|
|
||||||
func _sort_tackle_items(a: OwnedItemType, b: OwnedItemType) -> bool:
|
func _sort_tackle_items(a: OwnedItemType, b: OwnedItemType) -> bool:
|
||||||
if a.storage_slot >= 0 and b.storage_slot >= 0:
|
|
||||||
return a.storage_slot < b.storage_slot
|
|
||||||
if a.storage_slot >= 0:
|
|
||||||
return true
|
|
||||||
if b.storage_slot >= 0:
|
|
||||||
return false
|
|
||||||
var order_a := FishingShopStockType.get_stock_order_index(a.item_id)
|
var order_a := FishingShopStockType.get_stock_order_index(a.item_id)
|
||||||
var order_b := FishingShopStockType.get_stock_order_index(b.item_id)
|
var order_b := FishingShopStockType.get_stock_order_index(b.item_id)
|
||||||
if order_a >= 0 and order_b >= 0 and order_a != order_b:
|
if order_a >= 0 and order_b >= 0 and order_a != order_b:
|
||||||
|
|
|
||||||
|
|
@ -59,13 +59,13 @@ func setup(
|
||||||
item_catalog,
|
item_catalog,
|
||||||
PlayerInventoryLayout.InventoryContainer.STORAGE,
|
PlayerInventoryLayout.InventoryContainer.STORAGE,
|
||||||
)
|
)
|
||||||
_inventory_grid.entry_selected.connect(
|
_inventory_grid.slot_activated.connect(
|
||||||
_on_entry_selected.bind(
|
_on_slot_activated.bind(
|
||||||
PlayerInventoryLayout.InventoryContainer.STORAGE
|
PlayerInventoryLayout.InventoryContainer.STORAGE
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
_storage_grid.entry_selected.connect(
|
_storage_grid.slot_activated.connect(
|
||||||
_on_entry_selected.bind(
|
_on_slot_activated.bind(
|
||||||
PlayerInventoryLayout.InventoryContainer.INVENTORY
|
PlayerInventoryLayout.InventoryContainer.INVENTORY
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
@ -170,20 +170,24 @@ func consume_escape() -> bool:
|
||||||
|
|
||||||
|
|
||||||
func _unhandled_input(event: InputEvent) -> void:
|
func _unhandled_input(event: InputEvent) -> void:
|
||||||
if not visible or not event.is_action_pressed("ui_cancel"):
|
if not visible:
|
||||||
|
return
|
||||||
|
var close_requested: bool = event.is_action_pressed("ui_cancel") or (
|
||||||
|
_home_access and event.is_action_pressed("interact")
|
||||||
|
)
|
||||||
|
if not close_requested or (event is InputEventKey and event.echo):
|
||||||
return
|
return
|
||||||
close_storage()
|
close_storage()
|
||||||
get_viewport().set_input_as_handled()
|
get_viewport().set_input_as_handled()
|
||||||
|
|
||||||
|
|
||||||
func _on_entry_selected(
|
func _on_slot_activated(
|
||||||
kind: int,
|
slot: GeneralInventorySlot,
|
||||||
identity: StringName,
|
|
||||||
target_container: int,
|
target_container: int,
|
||||||
) -> void:
|
) -> void:
|
||||||
if kind < 0 or identity.is_empty() or _layout == null:
|
if slot == null or slot.entry_key.is_empty() or _layout == null:
|
||||||
return
|
return
|
||||||
if _layout.move_entry_to_first_free(kind, identity, target_container):
|
if _layout.move_entry_key_to_first_free(slot.entry_key, target_container):
|
||||||
_feedback.text = (
|
_feedback.text = (
|
||||||
"moved to storage"
|
"moved to storage"
|
||||||
if target_container == PlayerInventoryLayout.InventoryContainer.STORAGE
|
if target_container == PlayerInventoryLayout.InventoryContainer.STORAGE
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue