diff --git a/common/game_data/scripts/game_data.gd b/common/game_data/scripts/game_data.gd index 1c80e77..c753ef5 100644 --- a/common/game_data/scripts/game_data.gd +++ b/common/game_data/scripts/game_data.gd @@ -14,7 +14,7 @@ signal current_region_data_updated(p : RegionData) @export var last_game_scene : Scene = null func start_run(): - player_data.inventory.clear() + player_data.inventory.clear_items() current_run = RunData.new() current_run.current_run_point_changed.connect( func(rp : RunPoint): diff --git a/common/icons/bar.png b/common/icons/bar.png new file mode 100644 index 0000000..8bb60a4 Binary files /dev/null and b/common/icons/bar.png differ diff --git a/common/icons/bar.png.import b/common/icons/bar.png.import new file mode 100644 index 0000000..f604b1a --- /dev/null +++ b/common/icons/bar.png.import @@ -0,0 +1,40 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://dw80a4c5iekir" +path="res://.godot/imported/bar.png-623df5fbea38f9d862a997485a02d36c.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://common/icons/bar.png" +dest_files=["res://.godot/imported/bar.png-623df5fbea38f9d862a997485a02d36c.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/entities/interactables/item_object/script/item_object.gd b/entities/interactables/item_object/script/item_object.gd index d94e64c..cf6a8b2 100644 --- a/entities/interactables/item_object/script/item_object.gd +++ b/entities/interactables/item_object/script/item_object.gd @@ -41,13 +41,13 @@ func card_info() -> CardInfo: return item.card_info() func interact(player : Player) -> bool: - await pickup_animation(player) - - queue_free() + if player.can_pick_item(item): + await pickup_animation(player) + queue_free() + player.pick_item(item) + return true - player.pick_item(item) - - return true + return false func pickup_animation(player : Player): available = false diff --git a/entities/player/inventory/scripts/inventory.gd b/entities/player/inventory/scripts/inventory.gd index aa87341..549e15d 100644 --- a/entities/player/inventory/scripts/inventory.gd +++ b/entities/player/inventory/scripts/inventory.gd @@ -4,23 +4,37 @@ class_name Inventory signal updated(inventory: Inventory) @export var items: Array[Item] = [] -@export var current_item_ind: int = 0 -@export var size = 0 : - set(s): - size = s - items.resize(size) - updated.emit(self) +@export var current_item_ind: int = 0 # over both tools and items +@export var n_tools: int = 0 func _init(inventory_size: int = 1): - size = inventory_size - + set_size(inventory_size) + +func get_n_item_slots() -> int: + return items.size() - n_tools + +func set_size(new_size: int): + if new_size >= 0: + items.resize(n_tools + new_size) + updated.emit(self ) + +func change_size(size_mod: int): + set_size(items.size() - n_tools + size_mod) + +func current_is_tool() -> bool: + return current_item_ind >= 0 && current_item_ind < n_tools + func get_best_available_slot_ind(): - if items[current_item_ind] == null: + if !current_is_tool() && items[current_item_ind] == null: return current_item_ind - for i in items.size(): + for i in range(n_tools, items.size()): if items[i] == null: return i - return current_item_ind + # it's full + if !current_is_tool(): + return current_item_ind + else: + return n_tools func set_current_item(new_ind: int): if new_ind >= items.size(): @@ -28,7 +42,7 @@ func set_current_item(new_ind: int): if new_ind != current_item_ind: current_item_ind = new_ind - updated.emit(self) + updated.emit(self ) func change_current_item(ind_mod: int): if items.size() == 0: @@ -40,11 +54,16 @@ func change_current_item(ind_mod: int): new_ind += items.size() set_current_item(new_ind) -func add_item(item: Item): - var best_ind = get_best_available_slot_ind() - if best_ind != current_item_ind: - set_item(item, best_ind) - updated.emit(self) +func add_item(item: Item) -> bool: + if item.type != Item.ItemType.TOOL_ITEM: + var best_ind = get_best_available_slot_ind() + return set_item(item, best_ind) + elif item.type == Item.ItemType.TOOL_ITEM && !items.has(item): + items.insert(n_tools, item) + if current_item_ind >= n_tools: + current_item_ind += 1 + n_tools += 1 + updated.emit(self ) return true else: return false @@ -52,51 +71,61 @@ func add_item(item: Item): func set_item(item: Item, ind: int = 0) -> bool: if ind < 0 || ind >= items.size(): return false - while len(items) <= ind: - items.append(null) items[ind] = item - updated.emit(self) + updated.emit(self ) return true func get_item(ind: int = current_item_ind) -> Item: - if ind < 0 || items.size() <= ind: + if ind < 0 || ind > items.size(): return null return items[ind] func has_item(item: Item) -> bool: - return item in items + return items.has(item) func remove_item(item: Item): - var ind = items.find(item) - if ind >= 0: - items[ind] = null - updated.emit(self) + if item.type == Item.ItemType.TOOL_ITEM: + printerr("trying to remove a tool") + else: + var ind = items.find(item) + if ind >= 0: + items[ind] = null + updated.emit(self ) func remove_item_at(ind: int = current_item_ind): - if items.size() <= ind: + if ind < 0 || ind > items.size(): + return + + if ind < n_tools: + printerr("trying to remove a tool") return items[ind] = null - updated.emit(self) + updated.emit(self ) func remove_current_item(): remove_item_at() func pop_item(ind: int = current_item_ind) -> Item: - if items.size() == 0: + if ind < 0 || ind > items.size(): + return + + if ind < n_tools: + printerr("trying to remove a tool") return var item_removed: Item = items[ind] items[ind] = null - updated.emit(self) + updated.emit(self ) return item_removed func is_full(): - for i in items: - if i == null : return false + for i in range(n_tools, items.size()): + if items[i] == null: + return false return true -func clear(): - for i in range(len(items)): +func clear_items(): + for i in range(n_tools, items.size()): items[i] = null - updated.emit(self) + updated.emit(self ) diff --git a/entities/player/inventory/scripts/item.gd b/entities/player/inventory/scripts/item.gd index e7ecea7..1ff31d0 100644 --- a/entities/player/inventory/scripts/item.gd +++ b/entities/player/inventory/scripts/item.gd @@ -6,7 +6,10 @@ const ACTION_ICON = preload("res://common/icons/swipe-down.svg") const ENERGY_ICON = preload("res://common/icons/bolt.svg") const ONE_TIME_ICON = preload("res://common/icons/circle-number-1.svg") +enum ItemType {TOOL_ITEM, CONSUMABLE_ITEM} + @export var name: String : get = get_item_name +@export var type: ItemType : get = get_item_type @export var description: String : get = get_description @export var icon: Texture2D : get = get_icon @export var usage_zone_radius: int = 5 : get = get_usage_zone_radius @@ -15,6 +18,9 @@ const ONE_TIME_ICON = preload("res://common/icons/circle-number-1.svg") func get_item_name() -> String: return name +func get_item_type() -> ItemType: + return type + func get_description() -> String: return description diff --git a/entities/player/inventory/scripts/items/package.gd b/entities/player/inventory/scripts/items/package.gd index e3a3423..389e378 100644 --- a/entities/player/inventory/scripts/items/package.gd +++ b/entities/player/inventory/scripts/items/package.gd @@ -12,6 +12,9 @@ func _init(_scene : PackedScene = null): func get_item_name() -> String: return package_name +func get_item_type() -> ItemType: + return Item.ItemType.CONSUMABLE_ITEM + func get_description() -> String: return package_description diff --git a/entities/player/inventory/scripts/items/seed.gd b/entities/player/inventory/scripts/items/seed.gd index 760aed5..ee42d37 100644 --- a/entities/player/inventory/scripts/items/seed.gd +++ b/entities/player/inventory/scripts/items/seed.gd @@ -47,6 +47,9 @@ static func generate_random() -> Seed: func get_item_name() -> String: return tr("%s_SEED") % plant_name +func get_item_type() -> ItemType: + return Item.ItemType.CONSUMABLE_ITEM + func get_description() -> String: return tr("PLANT_%s_MUST_BE_USED_IN_DECONTAMINATED_ZONE") % plant_name diff --git a/entities/player/inventory/scripts/items/trowel.gd b/entities/player/inventory/scripts/items/trowel.gd index 0ae9279..95957fd 100644 --- a/entities/player/inventory/scripts/items/trowel.gd +++ b/entities/player/inventory/scripts/items/trowel.gd @@ -6,6 +6,9 @@ const TROWEL_ZONE_RADIUS = 50 func get_item_name() -> String: return tr("TROWEL") +func get_item_type() -> ItemType: + return Item.ItemType.TOOL_ITEM + func get_description() -> String: return tr("TROWEL_DESC_TEXT") diff --git a/entities/player/scripts/player.gd b/entities/player/scripts/player.gd index 00d334f..19a2b45 100644 --- a/entities/player/scripts/player.gd +++ b/entities/player/scripts/player.gd @@ -123,37 +123,33 @@ func try_interact(interactable : Interactable): func try_move(move_to : Vector2): instruction = MoveInstruction.new(move_to) -func pick_item(item : Item) -> Item: - AudioManager.play_sfx("PickUp") - if data.inventory.is_full(): +func can_pick_item(item: Item): + return item.type == Item.ItemType.TOOL_ITEM || !data.inventory.is_full() || !data.inventory.current_is_tool() + +func pick_item(item : Item): + if item.type != Item.ItemType.TOOL_ITEM && data.inventory.is_full(): await drop_item() - var current_item : Item = null + AudioManager.play_sfx("PickUp") - var available_slot_ind = data.inventory.get_best_available_slot_ind() - if ( - available_slot_ind == data.inventory.current_item_ind - && data.inventory.items[available_slot_ind] != null - ): - current_item = data.inventory.get_item() - data.inventory.set_item(item, available_slot_ind) - else : - if data.inventory.set_item(item, available_slot_ind): - data.inventory.set_current_item(available_slot_ind); + data.inventory.add_item(item) # Save after a timer to let the time to the item to disappear get_tree().create_timer(0.1).timeout.connect(region.save) - return current_item -func drop_item(): - var item_to_drop = data.inventory.pop_item() +func drop_item(): + var ind_to_drop := data.inventory.current_item_ind + if data.inventory.current_is_tool(): + ind_to_drop = data.inventory.n_tools + var item_to_drop = data.inventory.pop_item(ind_to_drop) if item_to_drop: terrain.drop_item(item_to_drop, global_position) AudioManager.play_sfx("Drop") region.save() func delete_item(item: Item): - data.inventory.remove_item(item) + if !data.inventory.current_is_tool(): + data.inventory.remove_item(item) func try_use_item(item : Item, use_position : Vector2): await setup_action_zone(use_position, item) @@ -195,7 +191,7 @@ func upgrade_max_energy(amount = 1): player_updated.emit(self) func upgrade_inventory_size(amount = 1): - data.inventory.size += amount + data.inventory.change_size(amount) upgraded.emit() player_updated.emit(self) diff --git a/entities/player/scripts/player_data.gd b/entities/player/scripts/player_data.gd index cc2ddcc..60a2e07 100644 --- a/entities/player/scripts/player_data.gd +++ b/entities/player/scripts/player_data.gd @@ -14,4 +14,4 @@ const DEFAULT_INVENTORY_SIZE = 3 set(v): energy = v updated.emit(self) -@export var inventory = Inventory.new(DEFAULT_INVENTORY_SIZE) \ No newline at end of file +@export var inventory := Inventory.new(DEFAULT_INVENTORY_SIZE) \ No newline at end of file diff --git a/gui/game/inventory_gui/inventory_gui.tscn b/gui/game/inventory_gui/inventory_gui.tscn index e624c85..08e7a57 100644 --- a/gui/game/inventory_gui/inventory_gui.tscn +++ b/gui/game/inventory_gui/inventory_gui.tscn @@ -1,9 +1,10 @@ -[gd_scene load_steps=3 format=3 uid="uid://clicjf8ts51h8"] +[gd_scene format=3 uid="uid://clicjf8ts51h8"] [ext_resource type="Script" uid="uid://dplbbs2dlq308" path="res://gui/game/inventory_gui/scripts/inventory_gui.gd" id="1_himlj"] [ext_resource type="PackedScene" uid="uid://dadihouw8o3jx" path="res://gui/game/inventory_gui/inventory_item/inventory_gui_item.tscn" id="2_0vvyy"] +[ext_resource type="Texture2D" uid="uid://dw80a4c5iekir" path="res://common/icons/bar.png" id="3_hqvrf"] -[node name="Inventory" type="HBoxContainer"] +[node name="Inventory" type="HBoxContainer" unique_id=1144799110 node_paths=PackedStringArray("bar")] custom_minimum_size = Vector2(48, 48) offset_right = 156.0 offset_bottom = 153.0 @@ -11,3 +12,8 @@ size_flags_horizontal = 0 size_flags_vertical = 0 script = ExtResource("1_himlj") inventory_item_scene = ExtResource("2_0vvyy") +bar = NodePath("Bar") + +[node name="Bar" type="TextureRect" parent="." unique_id=60027067] +layout_mode = 2 +texture = ExtResource("3_hqvrf") diff --git a/gui/game/inventory_gui/scripts/inventory_gui.gd b/gui/game/inventory_gui/scripts/inventory_gui.gd index 150d62f..81b1b8c 100644 --- a/gui/game/inventory_gui/scripts/inventory_gui.gd +++ b/gui/game/inventory_gui/scripts/inventory_gui.gd @@ -2,30 +2,35 @@ extends HBoxContainer class_name InventoryGui @export var inventory_item_scene: PackedScene +@export var bar: TextureRect var inventory_item_objects: Array[InventoryGuiItem] func _ready(): - GameInfo.game_data.player_data.inventory.updated.connect(update) - update(GameInfo.game_data.player_data.inventory) + GameInfo.game_data.player_data.inventory.updated.connect(update) + update(GameInfo.game_data.player_data.inventory) func update(inventory: Inventory): - if len(inventory_item_objects) == 0 or len(inventory_item_objects) != inventory.items.size(): - for o in inventory_item_objects: - o.queue_free() - inventory_item_objects = generate_inventory_item_objects(inventory, inventory.items.size()) + if len(inventory_item_objects) == 0 or len(inventory_item_objects) != inventory.items.size(): + for o in inventory_item_objects: + o.queue_free() + inventory_item_objects = generate_inventory_item_objects(inventory, inventory.items.size()) - for i in range(inventory.items.size()): - inventory_item_objects[i].update(inventory.get_item(i), i == inventory.current_item_ind) + for i in range(inventory.items.size()): + inventory_item_objects[i].update(inventory.get_item(i), i == inventory.current_item_ind) + + move_child(bar, inventory.n_tools) + bar.visible = inventory.n_tools > 0 && inventory.items.size() > inventory.n_tools func generate_inventory_item_objects(inventory: Inventory, nb: int = 1) -> Array[InventoryGuiItem]: - var objects: Array[InventoryGuiItem] = [] - for i in range(nb): - var o = inventory_item_scene.instantiate() as InventoryGuiItem - add_child(o) - objects.append(o) - o.item_clicked.connect(func(): change_current_item_ind(inventory, i)) - return objects + var objects: Array[InventoryGuiItem] = [] + for i in range(nb): + var o = inventory_item_scene.instantiate() as InventoryGuiItem + add_child(o) + move_child(o, i) + objects.append(o) + o.item_clicked.connect(func(): change_current_item_ind(inventory, i)) + return objects func change_current_item_ind(inventory: Inventory, new_ind: int): - inventory.set_current_item(new_ind) + inventory.set_current_item(new_ind)