diff --git a/scenes/player/inventory/Inventory.gd b/scenes/player/inventory/Inventory.gd index c24fc002..7649a686 100644 --- a/scenes/player/inventory/Inventory.gd +++ b/scenes/player/inventory/Inventory.gd @@ -70,8 +70,8 @@ func get_panel_at_pos(pos: Vector2) -> InventoryPanel: func get_panels(occupied_only: bool) -> Array[InventoryPanel]: var output: Array[InventoryPanel] = [] - var temp_arr: Array = [] - + var temp_arr: Array = [] + if occupied_only: for row: Array in panels: for panel: InventoryPanel in row: @@ -80,7 +80,7 @@ func get_panels(occupied_only: bool) -> Array[InventoryPanel]: else: for row: Array in panels: temp_arr += row - + output.assign(temp_arr) return output @@ -96,41 +96,39 @@ func update_inventory(): var occupied_panels: Array[InventoryPanel] = get_panels(true) var panel_item_uuid_dictionary: Dictionary = {} var panels_with_invalid_items: Dictionary = {} - + #Ensure all panels have an item assert( - occupied_panels.all( - func(panel_occupied: InventoryPanel): - return panel_occupied.item is Item - ) + occupied_panels.all( + func(panel_occupied: InventoryPanel): return panel_occupied.item is Item ) - + ) + #Store the uuid of the item that each panel has to accelerate the rest of the update. for panel: InventoryPanel in occupied_panels: panel_item_uuid_dictionary[panel.item.uuid] = panel - + #All panels are assumed invalid until proven otherwise. panels_with_invalid_items = panel_item_uuid_dictionary.duplicate() - + #Check every inventory item for inv_item: Item in player.inventory.items: - #Unmark as invalid those who have been found in the inventory panels_with_invalid_items.erase(inv_item.uuid) - + #No item with this uuid has been found in the displayed inventory, add it. if not inv_item.uuid in panel_item_uuid_dictionary.keys(): place_item_at_free_slot(inv_item) - + else: #Item found, update it. panel_item_uuid_dictionary[inv_item.uuid].item = inv_item panel_item_uuid_dictionary[inv_item.uuid].queue_redraw() - + #Clear any panels with items that are NOT in the inventory for item_uuid: String in panels_with_invalid_items: panels_with_invalid_items[item_uuid].item = null - + func place_item_at_free_slot(item: Item) -> bool: for y in range(SIZE.y): diff --git a/scenes/player/inventory/InventoryPanel.gd b/scenes/player/inventory/InventoryPanel.gd index 70081347..3b6dae29 100644 --- a/scenes/player/inventory/InventoryPanel.gd +++ b/scenes/player/inventory/InventoryPanel.gd @@ -7,18 +7,17 @@ const DEFAULT_FONT: Font = preload("res://addons/gut/fonts/LobsterTwo-Regular.tt @export var item: Item: set(new_item): if item is Item and item.amount_changed.is_connected(on_item_amount_changed): - item.amount_changed.disconnect(on_item_amount_changed) - + item.amount_changed.disconnect(on_item_amount_changed) + item = new_item - + if item is Item: if not item.amount_changed.is_connected(on_item_amount_changed): - item.amount_changed.connect(on_item_amount_changed) + item.amount_changed.connect(on_item_amount_changed) $TextureRect.texture = item.get_node("Icon").texture else: - $TextureRect.texture = null - + queue_redraw() @onready var inventory: Inventory = $"../.." @@ -34,14 +33,18 @@ func _ready(): mouse_exited.connect(_on_mouse_exited) - - - func _draw(): - if item is Item: + if item is Item and item.amount != 1: var font_height: int = 14 - draw_string(DEFAULT_FONT, Vector2(0, size.y - font_height), str(item.amount),HORIZONTAL_ALIGNMENT_CENTER, -1, font_height) - + draw_string( + DEFAULT_FONT, + Vector2(0, size.y - font_height), + str(item.amount), + HORIZONTAL_ALIGNMENT_CENTER, + -1, + font_height + ) + func _gui_input(event: InputEvent): if event.is_action_pressed("j_left_click"): @@ -69,7 +72,7 @@ func _gui_input(event: InputEvent): drag_panel.hide() -func _physics_process(_delta): +func _physics_process(_delta: float): if selected: drag_panel.position = get_local_mouse_position() + drag_panel_offset @@ -82,5 +85,5 @@ func _on_mouse_exited(): inventory.mouse_above_this_panel = null -func on_item_amount_changed(item: Item, amount: int): +func on_item_amount_changed(_amount: int): queue_redraw() diff --git a/scripts/classes/Item.gd b/scripts/classes/Item.gd index dfd9fb59..61641e8e 100644 --- a/scripts/classes/Item.gd +++ b/scripts/classes/Item.gd @@ -2,7 +2,7 @@ extends StaticBody2D class_name Item -signal amount_changed(this: Item, new_amount: int) +signal amount_changed(new_amount: int) enum MODE { LOOT, ITEMSLOT } @@ -28,8 +28,8 @@ var amount_max: int = 1 var amount: int = 1: set(val): amount = val + amount_changed.emit(amount) - amount_changed.emit(self, amount) var price: int = 0 var value: int = 0 @@ -96,10 +96,18 @@ func use(player: Player) -> bool: ITEM_TYPE.CONSUMABLE: if boost.hp > 0: player.stats.heal(self.name, boost.hp) + + if amount <= 1: + player.inventory.remove_item(uuid) + else: + player.inventory.set_item_amount(uuid, amount - 1) return true + ITEM_TYPE.EQUIPMENT: if player.equipment and player.equipment.equip_item(self): + player.inventory.remove_item(uuid) return true + else: GodotLogger.info("%s could not equip item %s" % [player.name, item_class]) return false diff --git a/scripts/components/player/equipmentsynchronizercomponent/EquipmentSynchronizerComponent.gd b/scripts/components/player/equipmentsynchronizercomponent/EquipmentSynchronizerComponent.gd index 028a65cf..3ea6e835 100644 --- a/scripts/components/player/equipmentsynchronizercomponent/EquipmentSynchronizerComponent.gd +++ b/scripts/components/player/equipmentsynchronizercomponent/EquipmentSynchronizerComponent.gd @@ -10,7 +10,7 @@ signal item_removed(item_uuid: String) var target_node: Node -var items = { +var items: Dictionary = { "Head": null, "Body": null, "Legs": null, @@ -99,7 +99,7 @@ func _unequip_item(item_uuid: String) -> Item: func get_item(item_uuid: String) -> Item: - for equipment_slot in items: + for equipment_slot: String in items: var item: Item = items[equipment_slot] if item != null and item.uuid == item_uuid: return item @@ -111,7 +111,7 @@ func get_boost() -> Boost: var boost: Boost = Boost.new() boost.identifier = "equipment" - for equipment_slot in items: + for equipment_slot: String in items: var item: Item = items[equipment_slot] if item != null: boost.combine_boost(item.boost) @@ -122,7 +122,7 @@ func get_boost() -> Boost: func to_json() -> Dictionary: var output: Dictionary = {} - for slot in items: + for slot: String in items: if items[slot] != null: var item: Item = items[slot] output[slot] = item.to_json() @@ -131,7 +131,7 @@ func to_json() -> Dictionary: func from_json(data: Dictionary) -> bool: - for slot in data: + for slot: String in data: if not slot in items: GodotLogger.warn("Slot=[%s] does not exist in equipment items" % slot) return false diff --git a/scripts/components/player/inventorysynchronizercomponent/InventorySynchronizerComponent.gd b/scripts/components/player/inventorysynchronizercomponent/InventorySynchronizerComponent.gd index 613b24f5..147335f1 100644 --- a/scripts/components/player/inventorysynchronizercomponent/InventorySynchronizerComponent.gd +++ b/scripts/components/player/inventorysynchronizercomponent/InventorySynchronizerComponent.gd @@ -34,37 +34,37 @@ func _ready(): func add_item(item: Item) -> bool: if not G.is_server(): return false - + #Currency is directly added to gold if item.item_type == Item.ITEM_TYPE.CURRENCY: add_gold(item.amount) return true item.collision_layer = 0 - + #Inventory full if items.size() >= size: return false - + #Try to stack var existing_item: Item = get_item_by_class(item.item_class) if existing_item is Item and existing_item.amount < existing_item.amount_max: var remaining_space: int = existing_item.amount_max - existing_item.amount var amount_to_add: int = min(item.amount, remaining_space) - + #If there's space remaining, add some of this item's to the stack. - if remaining_space > 0: + if remaining_space > 0: existing_item.amount += amount_to_add - + item.amount -= amount_to_add - + if item.amount > 0: add_item(item) - + sync_item_amount.rpc_id(target_node.peer_id, item.uuid, item.amount) - + return true - + #Adding the item from scratch else: items.append(item) @@ -80,27 +80,33 @@ func get_item_by_class(item_class: String) -> Item: if item.item_class == item_class: return item - GodotLogger.warn("Could not find item of class '{0}'.".format([item_class])) return null -func remove_item(item_uuid: String, amount: int = 1): +func remove_item(item_uuid: String): if not G.is_server(): return false var item: Item = get_item(item_uuid) - + if item != null: - item.amount -= amount - if item.amount <= 0: - items.erase(item) - sync_remove_item.rpc_id(target_node.peer_id, item_uuid) - else: - sync_item_amount.rpc_id(target_node.peer_id, item.uuid, item.amount) + items.erase(item) + sync_remove_item.rpc_id(target_node.peer_id, item_uuid) return item +func set_item_amount(item_uuid: String, new_amount: int): + if not G.is_server(): + return false + + var item: Item = get_item(item_uuid) + + if item != null: + item.amount = new_amount + sync_item_amount.rpc_id(target_node.peer_id, item_uuid, new_amount) + + func get_item(item_uuid: String) -> Item: for item in items: if item.uuid == item_uuid: @@ -109,13 +115,12 @@ func get_item(item_uuid: String) -> Item: return null -func use_item(item_uuid: String): +func use_item(item_uuid: String) -> bool: if not G.is_server(): return false var item: Item = get_item(item_uuid) if item and item.use(target_node): - remove_item(item_uuid) return true return false @@ -211,7 +216,7 @@ func sync_response(inventory: Dictionary): @rpc("call_remote", "authority", "reliable") func sync_add_item(item_uuid: String, item_class: String, amount: int): - var item = J.item_scenes[item_class].instantiate() + var item: Item = J.item_scenes[item_class].instantiate() item.uuid = item_uuid item.item_class = item_class item.amount = amount @@ -235,7 +240,9 @@ func sync_remove_item(item_uuid: String): @rpc("call_remote", "authority", "reliable") func sync_item_amount(item_uuid: String, new_amount: int): var item: Item = get_item(item_uuid) - item.amount = new_amount + + if item is Item: + item.amount = new_amount @rpc("call_remote", "authority", "reliable")