From cf0ba2e939fedeb4901dd1dbbda6cb403b2f6455 Mon Sep 17 00:00:00 2001 From: Ryan Reed Date: Tue, 8 Apr 2025 13:50:44 -0400 Subject: [PATCH] feat: Add creative mode --- autoloads/game_settings_manager.gd | 6 +++++ autoloads/inventory_manager.gd | 23 ++++++++++++++++++- .../game_options_settings_resource.gd | 1 + scenes/player/ray_cast_look.gd | 5 +++- scenes/ui/inventory/item_rect.gd | 5 +++- scenes/ui/pause_menu/settings_menu.gd | 6 +++++ scenes/ui/pause_menu/settings_menu.tscn | 20 ++++++++++++++-- scenes/ui/quickslots/quick_slots.gd | 7 ++++++ scenes/ui/quickslots/quickslots_slot.gd | 10 ++++---- 9 files changed, 74 insertions(+), 9 deletions(-) diff --git a/autoloads/game_settings_manager.gd b/autoloads/game_settings_manager.gd index ca951b3..9caff31 100644 --- a/autoloads/game_settings_manager.gd +++ b/autoloads/game_settings_manager.gd @@ -4,6 +4,7 @@ extends Node #region Game Options Signals signal game_options_autosaves_changed(autosaves_enabled: bool) signal game_options_block_highlight_changed(block_highlight_enabled: bool) +signal game_options_creative_mode_changed(creative_mode_enabled: bool) signal game_options_held_block_ui_changed(held_block_enabled: bool) signal game_options_quickslots_ui_changed(quickslots_enabled: bool) signal game_options_screenshot_saves_changed(screenshots_enabled: bool) @@ -37,6 +38,7 @@ var settings: GameSettingsResource = GameSettingsResource.new() func _init() -> void: game_options_autosaves_changed.connect(_on_game_options_autosaves_changed) game_options_block_highlight_changed.connect(_on_game_options_block_highlight_changed) + game_options_creative_mode_changed.connect(_on_game_options_creative_mode_changed) game_options_held_block_ui_changed.connect(_on_game_options_held_block_ui_changed) game_options_quickslots_ui_changed.connect(_on_game_options_quickslots_ui_changed) game_options_screenshot_saves_changed.connect(_on_game_options_screenshot_saves_changed) @@ -61,6 +63,10 @@ func _on_game_options_block_highlight_changed(highlight_enabled: bool) -> void: settings.game_options.enable_block_highlight = highlight_enabled save_settings() +func _on_game_options_creative_mode_changed(creative_mode_enabled: bool) -> void: + settings.game_options.enable_creative_mode = creative_mode_enabled + save_settings() + func _on_game_options_held_block_ui_changed(held_block_enabled: bool) -> void: settings.game_options.enable_held_block = held_block_enabled save_settings() diff --git a/autoloads/inventory_manager.gd b/autoloads/inventory_manager.gd index 9710a9e..8096bf9 100644 --- a/autoloads/inventory_manager.gd +++ b/autoloads/inventory_manager.gd @@ -4,6 +4,10 @@ extends Node signal item_dropped(item: DBItemResource) signal item_picked_up(item: DBItemResource) +signal creative_mode_disabled +signal creative_mode_enabled +signal toggle_creative_mode(enabled: bool) + #region Inventory Specific signal add_to_inventory(item_id: String, amount: int) signal clear_inventory ## Remove all items in inventory @@ -28,6 +32,7 @@ signal select_quick_slot(slot_index: int) var max_inventory_items: int = 40 # 4 rows of 10 var quick_slot_count: int = 10 var selected_quick_slot: int = 0 +var creative_mode: bool = false var inventory: Array[DBItemResource] = [] ## To ensure inventory is automatically sorted, "empty" inventory cells will be replaced with null to keep positions var _inventory_cache: Dictionary[String, Dictionary] = {} ## Used for caching certain information @@ -43,6 +48,7 @@ func _ready() -> void: self.remove_from_inventory.connect(_on_remove_from_inventory) self.remove_from_quickslot.connect(_on_remove_from_quickslot) self.remove_from_slot.connect(_on_remove_from_slot) + self.toggle_creative_mode.connect(_on_toggle_creative_mode) func available_space(item_id: String) -> int: @@ -66,6 +72,8 @@ func get_inventory_item(item_slot: int = selected_quick_slot) -> DBItemResource: return inventory.get(item_slot) func get_quick_slot_item_id(item_slot: int = selected_quick_slot) -> String: + if item_slot >= inventory.size(): return "" + return inventory[item_slot].id @@ -84,6 +92,8 @@ func _find_stacks_with_space(item_resource: DBItemResource, item_id: String) -> ## Removes an amount of items from a specific slot ## If the amount exceeds the amount of the slot, will NOT remove from other stacks func _remove_from_slot(slot_index: int, amount: int) -> void: + if creative_mode: return + if slot_index >= max_inventory_items: printerr("Slot Index ", slot_index, " out of inventory range") return @@ -95,6 +105,8 @@ func _remove_from_slot(slot_index: int, amount: int) -> void: inventory_slot_updated.emit(slot_index) func _update_cache_total(item_id: String, amount: int) -> void: + if creative_mode: return + if not _inventory_cache.get(item_id): _inventory_cache[item_id] = {"total": 0} _inventory_cache[item_id].total += amount @@ -131,7 +143,7 @@ func _on_add_to_inventory(item_id: String, amount: int = 1) -> void: amount_remaining -= stack_resource.max_stack_size inventory_slot_updated.emit(inventory.size() - 1) - elif first_stack_index > -1: + elif first_stack_index > -1 and not creative_mode: if inventory[first_stack_index] == null: # Empty slot inventory[first_stack_index] = item_resource.duplicate() @@ -152,6 +164,8 @@ func _on_add_to_inventory(item_id: String, amount: int = 1) -> void: item_added.emit(item_id, amount - amount_remaining) func _on_remove_from_inventory(item_id: String, amount: int = 1) -> void: + if creative_mode: return + var amount_remaining: int = amount while amount_remaining > 0: var last_stack_index: int = inventory.rfind_custom(_find_stacks_by_id.bind(item_id)) @@ -195,3 +209,10 @@ func _on_remove_from_slot(slot_index: int, amount: int) -> void: func _on_remove_from_quickslot(amount: int) -> void: _remove_from_slot(selected_quick_slot, amount) + +func _on_toggle_creative_mode(enabled: bool) -> void: + creative_mode = enabled + if creative_mode: + creative_mode_enabled.emit() + else: + creative_mode_disabled.emit() diff --git a/resources/game_settings/game_options_settings_resource.gd b/resources/game_settings/game_options_settings_resource.gd index ea9f323..60c08c7 100644 --- a/resources/game_settings/game_options_settings_resource.gd +++ b/resources/game_settings/game_options_settings_resource.gd @@ -8,3 +8,4 @@ extends Resource @export var enable_held_block: bool = true @export var enable_save_screenshots: bool = true ## Take a screenshot during save to use as the save icon @export var enable_autosaves: bool = true +@export var enable_creative_mode: bool = false diff --git a/scenes/player/ray_cast_look.gd b/scenes/player/ray_cast_look.gd index 73cbf0f..7b68621 100644 --- a/scenes/player/ray_cast_look.gd +++ b/scenes/player/ray_cast_look.gd @@ -17,7 +17,10 @@ func _process(_delta: float) -> void: if !is_valid_placement_target(block_pos): return - EntityManager.create_block.emit(InventoryManager.get_quick_slot_item_id(), block_pos) + var quickslot_item: String = InventoryManager.get_quick_slot_item_id() + if quickslot_item == "": return + + EntityManager.create_block.emit(quickslot_item, block_pos) InventoryManager.remove_from_quickslot.emit(1) if Waila.ref.get_target() == collider: diff --git a/scenes/ui/inventory/item_rect.gd b/scenes/ui/inventory/item_rect.gd index f4968d8..d7d26fa 100644 --- a/scenes/ui/inventory/item_rect.gd +++ b/scenes/ui/inventory/item_rect.gd @@ -27,8 +27,11 @@ func update_rect() -> void: if not item_resource: clear_rect() else: + if InventoryManager.creative_mode: + amount_label.text = "∞" + else: + amount_label.text = "x" + str(item_resource.amount) item_texture.texture_normal = load(item_resource.item_texture) - amount_label.text = "x" + str(item_resource.amount) item_texture.tooltip_text = item_resource.name + "\n" + item_resource.description func on_stack_full(is_full: bool) -> void: diff --git a/scenes/ui/pause_menu/settings_menu.gd b/scenes/ui/pause_menu/settings_menu.gd index dbbcf41..0a2706d 100644 --- a/scenes/ui/pause_menu/settings_menu.gd +++ b/scenes/ui/pause_menu/settings_menu.gd @@ -5,6 +5,7 @@ extends BaseMenu @export_group("Game Option Nodes") @export var autosaves_input: CheckButton @export var block_highlight_input: CheckButton +@export var creative_mode_input: CheckButton @export var held_block_ui_input: CheckButton @export var quick_slots_ui_input: CheckButton @export var screenshot_icon_input: CheckButton @@ -28,6 +29,7 @@ func init() -> void: func apply_default_values() -> void: #region Game Options autosaves_input.button_pressed = GameSettingsManager.settings.game_options.enable_autosaves + creative_mode_input.button_pressed = GameSettingsManager.settings.game_options.enable_creative_mode block_highlight_input.set_pressed_no_signal(GameSettingsManager.settings.game_options.enable_block_highlight) held_block_ui_input.set_pressed_no_signal(GameSettingsManager.settings.game_options.enable_held_block) quick_slots_ui_input.set_pressed_no_signal(GameSettingsManager.settings.game_options.enable_quickslots_ui) @@ -53,6 +55,10 @@ func apply_default_values() -> void: func _on_block_highlighting_toggled(toggled_on: bool) -> void: GameSettingsManager.game_options_block_highlight_changed.emit(toggled_on) +func _on_creative_mode_toggled(toggled_on: bool) -> void: + GameSettingsManager.game_options_creative_mode_changed.emit(toggled_on) + InventoryManager.toggle_creative_mode.emit(toggled_on) + func _on_held_block_ui_toggled(toggled_on: bool) -> void: GameSettingsManager.game_options_held_block_ui_changed.emit(toggled_on) diff --git a/scenes/ui/pause_menu/settings_menu.tscn b/scenes/ui/pause_menu/settings_menu.tscn index 5b85866..366a65b 100644 --- a/scenes/ui/pause_menu/settings_menu.tscn +++ b/scenes/ui/pause_menu/settings_menu.tscn @@ -14,11 +14,11 @@ corner_radius_top_right = 2 corner_radius_bottom_right = 2 corner_radius_bottom_left = 2 -[node name="SettingsMenu" node_paths=PackedStringArray("autosaves_input", "block_highlight_input", "held_block_ui_input", "quick_slots_ui_input", "screenshot_icon_input", "waila_input", "fov_slider", "fov_value_label", "resolution_input", "vsync_input", "window_mode_input") instance=ExtResource("1_oec81")] -visible = false +[node name="SettingsMenu" node_paths=PackedStringArray("autosaves_input", "block_highlight_input", "creative_mode_input", "held_block_ui_input", "quick_slots_ui_input", "screenshot_icon_input", "waila_input", "fov_slider", "fov_value_label", "resolution_input", "vsync_input", "window_mode_input") instance=ExtResource("1_oec81")] script = ExtResource("1_govsn") autosaves_input = NodePath("MainContent/MenuContainer/TabContainer/Game/Autosaves/CheckButton") block_highlight_input = NodePath("MainContent/MenuContainer/TabContainer/Game/BlockHighlight/CheckButton") +creative_mode_input = NodePath("MainContent/MenuContainer/TabContainer/Game/CreativeMode/CheckButton") held_block_ui_input = NodePath("MainContent/MenuContainer/TabContainer/Game/HeldBlockUI/CheckButton") quick_slots_ui_input = NodePath("MainContent/MenuContainer/TabContainer/Game/QuickslotsUI/CheckButton") screenshot_icon_input = NodePath("MainContent/MenuContainer/TabContainer/Game/ScreenshotIcon/CheckButton") @@ -121,6 +121,21 @@ layout_mode = 2 tooltip_text = "Enable/Disable the taking of a screenshot to utilize as the save icon." button_pressed = true +[node name="CreativeMode" type="HBoxContainer" parent="MainContent/MenuContainer/TabContainer/Game" index="6"] +layout_mode = 2 + +[node name="Label" type="Label" parent="MainContent/MenuContainer/TabContainer/Game/CreativeMode" index="0"] +layout_mode = 2 +size_flags_horizontal = 3 +tooltip_text = "Enable/Disable the taking of a screenshot to utilize as the save icon." +mouse_filter = 1 +text = "Enable Creative Mode" + +[node name="CheckButton" type="CheckButton" parent="MainContent/MenuContainer/TabContainer/Game/CreativeMode" index="1"] +layout_mode = 2 +tooltip_text = "Enable/Disable the taking of a screenshot to utilize as the save icon." +button_pressed = true + [node name="Graphics" type="VBoxContainer" parent="MainContent/MenuContainer/TabContainer" index="2"] visible = false layout_mode = 2 @@ -235,6 +250,7 @@ text = "Close Settings" [connection signal="toggled" from="MainContent/MenuContainer/TabContainer/Game/HeldBlockUI/CheckButton" to="." method="_on_held_block_ui_toggled"] [connection signal="toggled" from="MainContent/MenuContainer/TabContainer/Game/ScreenshotIcon/CheckButton" to="." method="_on_screenshot_icon_button_toggled"] [connection signal="toggled" from="MainContent/MenuContainer/TabContainer/Game/Autosaves/CheckButton" to="." method="_on_autosaves_button_toggled"] +[connection signal="toggled" from="MainContent/MenuContainer/TabContainer/Game/CreativeMode/CheckButton" to="." method="_on_creative_mode_toggled"] [connection signal="value_changed" from="MainContent/MenuContainer/TabContainer/Graphics/FOV/HSlider" to="." method="_on_fov_slider_changed"] [connection signal="pressed" from="MainContent/MenuContainer/TabContainer/Graphics/CenterContainer/ApplyButton" to="." method="_on_graphics_apply_button_pressed"] [connection signal="pressed" from="BottomRow/CloseButton" to="." method="_on_close_button_pressed"] diff --git a/scenes/ui/quickslots/quick_slots.gd b/scenes/ui/quickslots/quick_slots.gd index acb48ad..f2e20e1 100644 --- a/scenes/ui/quickslots/quick_slots.gd +++ b/scenes/ui/quickslots/quick_slots.gd @@ -21,6 +21,8 @@ func _init() -> void: InventoryManager.next_quick_slot.connect(select_next_item) InventoryManager.previous_quick_slot.connect(select_previous_item) InventoryManager.select_quick_slot.connect(select_quick_slot) + InventoryManager.creative_mode_disabled.connect(_on_creative_mode_toggled) + InventoryManager.creative_mode_enabled.connect(_on_creative_mode_toggled) func _ready() -> void: remove_slots() @@ -90,3 +92,8 @@ func update_highlighted_slot() -> void: var current_slot: Panel = slots_container.get_child(_selected_item) current_slot.set("theme_override_styles/panel", highlight_theme) + + +func _on_creative_mode_toggled() -> void: + for slot: QuickSlotsSlot in slots_container.get_children(): + slot.refresh() diff --git a/scenes/ui/quickslots/quickslots_slot.gd b/scenes/ui/quickslots/quickslots_slot.gd index c7923ec..6fa7859 100644 --- a/scenes/ui/quickslots/quickslots_slot.gd +++ b/scenes/ui/quickslots/quickslots_slot.gd @@ -22,16 +22,18 @@ func clear() -> void: slot_texture.tooltip_text = "" func refresh() -> void: - if InventoryManager.inventory.size() < 1: - return clear() - elif not InventoryManager.inventory.get(slot_index): + if InventoryManager.inventory.size() < 1 or slot_index >= InventoryManager.inventory.size(): return clear() + elif InventoryManager.inventory[slot_index] == null: return clear() + elif InventoryManager.creative_mode: + amount_label.text = "∞" + return slot_texture.texture = load(InventoryManager.inventory[slot_index].item_texture) - amount_label.text = "x" + str(InventoryManager.inventory[slot_index].amount) slot_texture.tooltip_text = InventoryManager.inventory[slot_index].name + "\n" + InventoryManager.inventory[slot_index].description + amount_label.text = "x" + str(InventoryManager.inventory[slot_index].amount) func _on_inventory_slot_updated(_slot_index: int) -> void: