İlk commit: Stepstead Godot istemci (4.6 Mobile)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
commit
6a1706051d
346 changed files with 14415 additions and 0 deletions
116
scripts/skills_panel.gd
Normal file
116
scripts/skills_panel.gd
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
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
|
||||
Loading…
Add table
Add a link
Reference in a new issue