extends CanvasLayer @onready var _grid: GridContainer = $VBoxContainer/AchievementGrid @onready var _counter: Label = $VBoxContainer/CounterLabel @onready var _info_title: Label = $VBoxContainer/InfoPanel/InfoVBox/InfoTitle @onready var _info_desc: Label = $VBoxContainer/InfoPanel/InfoVBox/InfoDesc @onready var _info_reward: Label = $VBoxContainer/InfoPanel/InfoVBox/InfoReward var _font = preload("res://assets/fonts/slkscre.ttf") var _frame_tex = preload("res://assets/Tiny RPG Mana Soul GUI v1.0/20250420manaSoul9SlicesA-Sheet.png") func _ready() -> void: AchievementManager.check_all() _update_counter() _build_grid() _clear_info() func _build_grid() -> void: for ach in AchievementManager.achievements: _grid.add_child(_make_slot(ach)) func _make_slot(ach: Dictionary) -> Control: var slot := Control.new() slot.custom_minimum_size = Vector2(80, 80) slot.mouse_filter = Control.MOUSE_FILTER_STOP var bg := ColorRect.new() bg.mouse_filter = Control.MOUSE_FILTER_IGNORE bg.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) bg.color = ach.color if ach.unlocked else Color(0.06, 0.06, 0.1, 1.0) slot.add_child(bg) var frame := NinePatchRect.new() frame.mouse_filter = Control.MOUSE_FILTER_IGNORE frame.texture = _frame_tex frame.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) frame.patch_margin_left = 8 frame.patch_margin_right = 8 frame.patch_margin_top = 8 frame.patch_margin_bottom = 8 if not ach.unlocked: frame.modulate = Color(0.4, 0.4, 0.4, 1.0) slot.add_child(frame) var lbl := Label.new() lbl.mouse_filter = Control.MOUSE_FILTER_IGNORE lbl.text = ach.icon_char lbl.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT) lbl.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER lbl.vertical_alignment = VERTICAL_ALIGNMENT_CENTER lbl.add_theme_font_override("font", _font) lbl.add_theme_font_size_override("font_size", 26) if ach.unlocked: lbl.add_theme_color_override("font_color", Color(1.0, 1.0, 0.9, 1.0)) lbl.add_theme_color_override("font_outline_color", Color(0.0, 0.0, 0.0, 0.9)) lbl.add_theme_constant_override("outline_size", 2) else: lbl.add_theme_color_override("font_color", Color(0.22, 0.22, 0.22, 1.0)) slot.add_child(lbl) slot.mouse_entered.connect(_on_slot_enter.bind(ach)) slot.mouse_exited.connect(_on_slot_exit) return slot func _on_slot_enter(ach: Dictionary) -> void: if ach.unlocked: _info_title.text = ach.title + " [UNLOCKED]" _info_title.add_theme_color_override("font_color", Color(1.0, 1.0, 0.55, 1.0)) else: _info_title.text = ach.title + " [LOCKED]" _info_title.add_theme_color_override("font_color", Color(0.75, 0.45, 1.0, 1.0)) _info_desc.text = ach.description _info_reward.text = "Reward: " + ach.reward func _on_slot_exit() -> void: _clear_info() func _clear_info() -> void: _info_title.text = "" _info_desc.text = "Hover over an achievement to see details." _info_reward.text = "" func _update_counter() -> void: var n := AchievementManager.get_unlocked_count() var total := AchievementManager.achievements.size() _counter.text = "Unlocked: %d of %d" % [n, total] func _on_back_button_pressed() -> void: get_tree().change_scene_to_file("res://scenes/mainmenu.tscn")