feat: implement loadout management system, interactive pause menu, and weapon slot switching functionality

This commit is contained in:
DottsGit
2026-06-04 09:12:16 -04:00
parent 45fb7f0f38
commit 8eea7d6e36
8 changed files with 423 additions and 10 deletions
+250
View File
@@ -0,0 +1,250 @@
extends CanvasLayer
var bg: ColorRect
var main_vbox: VBoxContainer
var resume_btn: Button
var loadouts_btn: Button
var exit_btn: Button
var loadout_editor: Control
var loadout_list_vbox: VBoxContainer
var edit_panel: PanelContainer
var name_edit: LineEdit
var primary1_opt: OptionButton
var primary2_opt: OptionButton
var special_opt: OptionButton
var save_loadout_btn: Button
var back_to_main_btn: Button
var editing_index: int = -1
var quit_dialog: ConfirmationDialog
func _ready() -> void:
process_mode = Node.PROCESS_MODE_ALWAYS
layer = 100 # Ensure it's on top
visible = false
_build_ui()
_connect_signals()
func _input(event: InputEvent) -> void:
if event.is_action_pressed("ui_cancel"):
if visible:
_resume()
else:
_pause()
func _pause() -> void:
visible = true
get_tree().paused = true
Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
_show_main_menu()
func _resume() -> void:
visible = false
get_tree().paused = false
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
func _build_ui() -> void:
bg = ColorRect.new()
bg.color = Color(0, 0, 0, 0.7)
bg.set_anchors_preset(Control.PRESET_FULL_RECT)
add_child(bg)
# Main Menu
main_vbox = VBoxContainer.new()
main_vbox.set_anchors_preset(Control.PRESET_CENTER)
main_vbox.add_theme_constant_override("separation", 20)
bg.add_child(main_vbox)
var title = Label.new()
title.text = "PAUSED"
title.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
title.add_theme_font_size_override("font_size", 48)
main_vbox.add_child(title)
resume_btn = Button.new()
resume_btn.text = "Resume"
resume_btn.custom_minimum_size = Vector2(200, 50)
main_vbox.add_child(resume_btn)
loadouts_btn = Button.new()
loadouts_btn.text = "Loadouts"
loadouts_btn.custom_minimum_size = Vector2(200, 50)
main_vbox.add_child(loadouts_btn)
exit_btn = Button.new()
exit_btn.text = "Exit Game"
exit_btn.custom_minimum_size = Vector2(200, 50)
main_vbox.add_child(exit_btn)
# Loadout Editor Root
loadout_editor = Control.new()
loadout_editor.set_anchors_preset(Control.PRESET_FULL_RECT)
bg.add_child(loadout_editor)
var editor_hbox = HBoxContainer.new()
editor_hbox.set_anchors_preset(Control.PRESET_CENTER)
editor_hbox.add_theme_constant_override("separation", 40)
loadout_editor.add_child(editor_hbox)
# Loadout List
var left_vbox = VBoxContainer.new()
editor_hbox.add_child(left_vbox)
var list_title = Label.new()
list_title.text = "Your Loadouts"
list_title.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
left_vbox.add_child(list_title)
loadout_list_vbox = VBoxContainer.new()
left_vbox.add_child(loadout_list_vbox)
back_to_main_btn = Button.new()
back_to_main_btn.text = "Back to Menu"
back_to_main_btn.custom_minimum_size = Vector2(0, 40)
left_vbox.add_child(back_to_main_btn)
# Edit Panel
edit_panel = PanelContainer.new()
editor_hbox.add_child(edit_panel)
var edit_vbox = VBoxContainer.new()
edit_vbox.add_theme_constant_override("separation", 10)
edit_panel.add_child(edit_vbox)
var edit_title = Label.new()
edit_title.text = "Edit Loadout"
edit_title.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
edit_vbox.add_child(edit_title)
name_edit = LineEdit.new()
name_edit.placeholder_text = "Loadout Name"
name_edit.custom_minimum_size = Vector2(250, 0)
edit_vbox.add_child(name_edit)
edit_vbox.add_child(_create_label("Primary 1:"))
primary1_opt = OptionButton.new()
edit_vbox.add_child(primary1_opt)
edit_vbox.add_child(_create_label("Primary 2:"))
primary2_opt = OptionButton.new()
edit_vbox.add_child(primary2_opt)
edit_vbox.add_child(_create_label("Special:"))
special_opt = OptionButton.new()
edit_vbox.add_child(special_opt)
save_loadout_btn = Button.new()
save_loadout_btn.text = "Save Loadout"
save_loadout_btn.custom_minimum_size = Vector2(0, 40)
edit_vbox.add_child(save_loadout_btn)
# Quit Dialog
quit_dialog = ConfirmationDialog.new()
quit_dialog.title = "Quit Game"
quit_dialog.dialog_text = "Are you sure you want to close the game?"
add_child(quit_dialog)
func _create_label(text: String) -> Label:
var l = Label.new()
l.text = text
return l
func _connect_signals() -> void:
resume_btn.pressed.connect(_resume)
loadouts_btn.pressed.connect(_show_loadouts)
exit_btn.pressed.connect(_show_exit_dialog)
back_to_main_btn.pressed.connect(_show_main_menu)
save_loadout_btn.pressed.connect(_save_current_loadout)
quit_dialog.confirmed.connect(_quit_game)
func _show_main_menu() -> void:
main_vbox.visible = true
loadout_editor.visible = false
func _show_loadouts() -> void:
main_vbox.visible = false
loadout_editor.visible = true
edit_panel.visible = false
_populate_loadout_list()
func _populate_loadout_list() -> void:
for c in loadout_list_vbox.get_children():
c.queue_free()
for i in range(LoadoutManager.loadouts.size()):
var l = LoadoutManager.loadouts[i]
var hbox = HBoxContainer.new()
var btn = Button.new()
var is_active = (i == LoadoutManager.active_loadout_index)
btn.text = l["name"] + (" (Active)" if is_active else "")
btn.custom_minimum_size = Vector2(200, 40)
btn.pressed.connect(func(): _edit_loadout(i))
hbox.add_child(btn)
var equip_btn = Button.new()
equip_btn.text = "Equip"
equip_btn.disabled = is_active
equip_btn.pressed.connect(func(): _equip_loadout(i))
hbox.add_child(equip_btn)
loadout_list_vbox.add_child(hbox)
func _equip_loadout(idx: int) -> void:
LoadoutManager.active_loadout_index = idx
LoadoutManager.save_loadouts()
_populate_loadout_list()
func _edit_loadout(idx: int) -> void:
editing_index = idx
var l = LoadoutManager.loadouts[idx]
name_edit.text = l["name"]
_populate_options(primary1_opt, "primary", l["primary_1"])
_populate_options(primary2_opt, "primary", l["primary_2"])
_populate_options(special_opt, "special", l["special"])
edit_panel.visible = true
func _populate_options(opt: OptionButton, category: String, current_id: String) -> void:
opt.clear()
var idx = 0
var select_idx = 0
# Always add "none" as first option
opt.add_item("None", 0)
opt.set_item_metadata(0, "none")
if current_id == "none": select_idx = 0
idx += 1
for key in LoadoutManager.weapon_db:
if key == "none": continue
var w = LoadoutManager.weapon_db[key]
if w["category"] == category:
opt.add_item(w["name"], idx)
opt.set_item_metadata(idx, key)
if key == current_id:
select_idx = idx
idx += 1
opt.select(select_idx)
func _save_current_loadout() -> void:
if editing_index >= 0 and editing_index < LoadoutManager.loadouts.size():
var l = LoadoutManager.loadouts[editing_index]
l["name"] = name_edit.text
l["primary_1"] = primary1_opt.get_item_metadata(primary1_opt.get_selected_id())
l["primary_2"] = primary2_opt.get_item_metadata(primary2_opt.get_selected_id())
l["special"] = special_opt.get_item_metadata(special_opt.get_selected_id())
LoadoutManager.save_loadouts()
_populate_loadout_list()
edit_panel.visible = false
func _show_exit_dialog() -> void:
quit_dialog.popup_centered()
func _quit_game() -> void:
get_tree().quit()
+1
View File
@@ -0,0 +1 @@
uid://bcvjb1h4fxcct