extends PanelContainer ## Skill paneli — 10 skill, level + bir sonraki seviyeye XP ilerlemesi. ## Eğri sunucuyla aynı: level N eşiği = 100 × N² XP. Kod ile kurulur. Node adı "SkillsPanel". const PANEL_HEIGHT := 560.0 const SKILL_TR := { "mining": "⛏ Madencilik", "fishing": "🎣 Balıkçılık", "foraging": "🌿 Toplama", "woodcutting": "🪓 Ağaç Kesme", "hunting": "🏹 Avcılık", "combat": "⚔ Savaş", "smithing": "🔨 Demircilik", "alchemy": "⚗ Simya", "cooking": "🍳 Aşçılık", "construction": "🏠 İnşaat", } var _list: VBoxContainer func _ready() -> void: name = "SkillsPanel" visible = false _build_ui() GameState.character_loaded.connect(func(_c: Dictionary) -> void: if visible: _render()) func _build_ui() -> void: set_anchors_preset(Control.PRESET_BOTTOM_WIDE) offset_top = -PANEL_HEIGHT offset_left = 8 offset_right = -8 offset_bottom = -8 var sb := StyleBoxFlat.new() sb.bg_color = Color(0.10, 0.10, 0.13, 0.97) sb.set_corner_radius_all(10) add_theme_stylebox_override("panel", sb) var margin := MarginContainer.new() margin.add_theme_constant_override("margin_left", 14) margin.add_theme_constant_override("margin_right", 14) margin.add_theme_constant_override("margin_top", 10) margin.add_theme_constant_override("margin_bottom", 10) add_child(margin) var vbox := VBoxContainer.new() vbox.add_theme_constant_override("separation", 6) margin.add_child(vbox) var top := HBoxContainer.new() var title := Label.new() title.text = "📊 Yetenekler" title.add_theme_font_size_override("font_size", 18) title.size_flags_horizontal = Control.SIZE_EXPAND_FILL top.add_child(title) var close_btn := Button.new() close_btn.text = "✕" close_btn.pressed.connect(func() -> void: visible = false) top.add_child(close_btn) vbox.add_child(top) var scroll := ScrollContainer.new() scroll.size_flags_vertical = Control.SIZE_EXPAND_FILL scroll.horizontal_scroll_mode = ScrollContainer.SCROLL_MODE_DISABLED vbox.add_child(scroll) _list = VBoxContainer.new() _list.size_flags_horizontal = Control.SIZE_EXPAND_FILL _list.add_theme_constant_override("separation", 8) scroll.add_child(_list) func open() -> void: visible = true _render() func _render() -> void: for c in _list.get_children(): c.queue_free() var skills: Array = GameState.skills.duplicate() skills.sort_custom(func(a: Dictionary, b: Dictionary) -> bool: return int(a.get("xp", 0)) > int(b.get("xp", 0))) for s in skills: if s is Dictionary: _list.add_child(_skill_row(s)) func _skill_row(s: Dictionary) -> VBoxContainer: var box := VBoxContainer.new() box.add_theme_constant_override("separation", 2) var skill_name := str(s.get("skill_name", "")) var lvl := int(s.get("level", 1)) var xp := int(s.get("xp", 0)) var top := HBoxContainer.new() var name_lbl := Label.new() name_lbl.text = str(SKILL_TR.get(skill_name, skill_name)) name_lbl.add_theme_font_size_override("font_size", 15) name_lbl.size_flags_horizontal = Control.SIZE_EXPAND_FILL top.add_child(name_lbl) var lvl_lbl := Label.new() lvl_lbl.add_theme_font_size_override("font_size", 14) lvl_lbl.add_theme_color_override("font_color", Color(0.9, 0.78, 0.5)) top.add_child(lvl_lbl) box.add_child(top) var bar := ProgressBar.new() bar.custom_minimum_size = Vector2(0, 14) bar.show_percentage = false if lvl >= 50: lvl_lbl.text = "Lv %d (MAX)" % lvl bar.max_value = 1 bar.value = 1 else: # level N eşiği = 100×N²; sonraki seviye eşiği 100×(N+1)² var cur_floor := 100 * lvl * lvl var next_need := 100 * (lvl + 1) * (lvl + 1) lvl_lbl.text = "Lv %d • %d / %d XP" % [lvl, xp, next_need] bar.max_value = next_need - cur_floor bar.value = clampi(xp - cur_floor, 0, next_need - cur_floor) box.add_child(bar) return box