Files
mtgodot-poc/project/ui/skill_ui.gd
T

229 lines
7.3 KiB
GDScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# SkillUI (P6) —— 技能窗:主动 / 辅助(被动·支援) / 坐骑 三个分类页 + 等级 + 加点。
#
# var sk := preload("res://ui/skill_ui.gd").new()
# add_child(sk)
# sk.setup(m2client, skill_table, ui_manager)
# sk.set_job("WARRIOR")
# sk.toggle() # K 键
#
# 每行:名字 + Lv X(/M/G/P) + [](被动 / CANNOT_LEVEL_UP 无加点)+ [被动]/[切换] 标签。
# 点名字 -> drag_skill_idquickbar 落点读)。`skills_changed` 刷新。
# §3.10[] 的显隐逐行对齐 uicharacter.py RefreshSkillPlusButtonList /
# __RefreshSkillPlusButton / CanShowPlusButton —— 技能组门(get_skill_group()==0)、
# 三个技能点来源分开取、skillGrade==0、马术页 skillLevel<20、主动页 CanLevelUpSkill、
# 辅助页 HIDE_SUPPORT_SKILL_POINT 整页隐藏。升级结果仍由 GC_SKILL_LEVEL 回包驱动。
extends Node
const TABS := ["主动", "辅助", "坐骑"]
const MASTER_SUFFIX := ["", " M", " G", " P"] # master_type 0..3
# uicharacter.py:21 HIDE_SUPPORT_SKILL_POINT —— 本 migration 资源为 True,辅助页整页不出加号。
const HIDE_SUPPORT_SKILL_POINT := true
# uicharacter.py __RefreshSkillPlusButton 的 HORSE 分支硬编码 `if skillLevel < 20`。
const RIDING_SKILL_MAX_LEVEL := 20
var client: Node
var table: RefCounted # SkillTable
var ui: CanvasLayer # UiManager
var job := "WARRIOR"
var drag_skill_id := 0
var _tab := 0
var _win: Control
var _rows := {} # skill_id -> {lv, up}
func setup(m2client: Node, skill_table: RefCounted, ui_manager: CanvasLayer) -> void:
client = m2client
table = skill_table
ui = ui_manager
if client.has_signal("skills_changed"):
client.skills_changed.connect(refresh)
func set_job(j: String) -> void:
job = j
if is_open():
_rebuild()
func is_open() -> bool:
return _win != null and is_instance_valid(_win)
func toggle() -> void:
if is_open(): close()
else: open()
func close() -> void:
if is_open():
ui.close(_win)
_win = null
_rows.clear()
func _cat_key() -> String:
match _tab:
1: return "SUPPORT"
2: return "HORSE"
_: return job
func open() -> void:
if is_open() or table == null:
return
_win = Control.new()
_win.set_anchors_preset(Control.PRESET_CENTER_RIGHT)
_win.position = Vector2(-300, -240)
_win.size = Vector2(290, 470)
_win.set_meta("is_titlebar", true)
var panel := Panel.new()
panel.set_anchors_preset(Control.PRESET_FULL_RECT)
var sb := StyleBoxFlat.new()
sb.bg_color = Color(0.08, 0.09, 0.12, 0.95)
sb.set_corner_radius_all(4)
panel.add_theme_stylebox_override("panel", sb)
_win.add_child(panel)
var title := Label.new()
title.text = "技能"
title.position = Vector2(12, 8)
_win.add_child(title)
# 分类页签
var tabrow := HBoxContainer.new()
tabrow.name = "tabs"
tabrow.position = Vector2(10, 30)
_win.add_child(tabrow)
for i in TABS.size():
var b := Button.new()
b.text = TABS[i]
b.toggle_mode = true
b.button_pressed = (i == _tab)
var ti: int = i
b.pressed.connect(func(): _switch_tab(ti))
tabrow.add_child(b)
var vb := VBoxContainer.new()
vb.name = "list"
vb.position = Vector2(10, 60)
vb.custom_minimum_size = Vector2(270, 0)
vb.add_theme_constant_override("separation", 2)
_win.add_child(vb)
ui.open(_win)
_rebuild()
func _switch_tab(i: int) -> void:
_tab = i
if is_open():
var tabrow: HBoxContainer = _win.get_node("tabs")
for j in tabrow.get_child_count():
(tabrow.get_child(j) as Button).button_pressed = (j == i)
_rebuild()
func _rebuild() -> void:
var vb: VBoxContainer = _win.get_node("list")
for c in vb.get_children():
c.queue_free()
_rows.clear()
var ids: Array = table.for_category(_cat_key())
if ids.is_empty():
var e := Label.new()
e.text = "(无)"
vb.add_child(e)
return
for id in ids:
var row := HBoxContainer.new()
row.custom_minimum_size = Vector2(268, 26)
var nm := Label.new()
nm.text = table.name_of(id)
nm.custom_minimum_size = Vector2(140, 0)
nm.add_theme_font_size_override("font_size", 12)
row.add_child(nm)
var lv := Label.new()
lv.name = "lv"
lv.custom_minimum_size = Vector2(58, 0)
lv.add_theme_font_size_override("font_size", 12)
row.add_child(lv)
var tag := Label.new()
tag.custom_minimum_size = Vector2(40, 0)
tag.add_theme_font_size_override("font_size", 10)
if table.is_passive(id):
tag.text = "被动"
tag.modulate = Color(0.6, 0.8, 1.0)
elif table.is_toggle(id):
tag.text = "切换"
tag.modulate = Color(0.9, 0.8, 0.5)
row.add_child(tag)
var sid: int = id
if table.can_level_up(id) and not table.is_passive(id):
var up := Button.new()
up.text = ""
up.custom_minimum_size = Vector2(28, 22)
up.pressed.connect(func(): client.skill_up(sid))
row.add_child(up)
_rows[id] = {"lv": lv, "up": up}
else:
_rows[id] = {"lv": lv, "up": null}
nm.gui_input.connect(func(e: InputEvent):
if e is InputEventMouseButton and e.pressed and e.button_index == MOUSE_BUTTON_LEFT:
drag_skill_id = sid)
vb.add_child(row)
refresh()
func refresh() -> void:
if not is_open():
return
var lv := {}
var ms := {}
for s in client.get_skills():
lv[int(s["id"])] = int(s["level"])
ms[int(s["id"])] = int(s.get("master", 0))
# RefreshSkillPlusButtonListuicharacter.py:984)→ __RefreshSkillPlusButton:937):
# 每页的技能点来源分开取,技能组未选时整列隐藏加号。
var page := _cat_key()
var can_use_now := _can_use_skill_now()
var stat_point := _stat_point_for(page)
var plv := _player_level()
for id in _rows:
var lvl: int = lv.get(id, 0)
var m: int = clampi(ms.get(id, 0), 0, 3)
_rows[id]["lv"].text = "Lv %d%s" % [lvl, MASTER_SUFFIX[m]]
var up: Button = _rows[id]["up"]
if up != null:
up.visible = _can_show_plus(id, lvl, m, page, can_use_now, stat_point, plv)
# __CanUseSkillNowuicharacter.py:1270):net.GetMainActorSkillGroup()==0 -> False。
func _can_use_skill_now() -> bool:
if client.has_method("get_skill_group"):
return int(client.get_skill_group()) != 0
return true
# skillPageStatDictuicharacter.py:225):SUPPORT=POINT_SUB_SKILL(27) /
# ACTIVE=POINT_SKILL(28) / HORSE=POINT_HORSE_SKILL(113)。三个来源分开取,不合并成一个。
func _stat_point_for(page: String) -> int:
if not client.has_method("get_points"):
return 1
var p: Dictionary = client.get_points()
match page:
"SUPPORT": return int(p.get("skill_support", 0))
"HORSE": return int(p.get("skill_horse", 0))
_: return int(p.get("skill_active", 0))
func _player_level() -> int:
if not client.has_method("get_points"):
return 1
return int(client.get_points().get("level", 1))
# __RefreshSkillPlusButton 每槽体(uicharacter.py:937+ CanShowPlusButton:925):
# 技能组未选 -> 全隐藏;辅助页 HIDE_SUPPORT_SKILL_POINT -> 整页隐藏;
# statPoint <= 0 -> 不显示;skillGrade != 0(已过 0 级,走大师书)-> 跳过;
# HORSE 页:GetStatus(LEVEL) >= GetSkillLevelLimit(idx) 时,skillLevel < 20 才显示;
# 其余页:skill.CanLevelUpSkill(idx, level)。
func _can_show_plus(id: int, level: int, grade: int, page: String,
can_use_now: bool, stat_point: int, plv: int) -> bool:
if not can_use_now:
return false
if page == "SUPPORT" and HIDE_SUPPORT_SKILL_POINT:
return false
if stat_point <= 0:
return false
if grade != 0:
return false
if page == "HORSE":
if plv >= table.skill_level_limit(id):
return level < RIDING_SKILL_MAX_LEVEL
return false
return table.can_level_up_skill(id, level)