客户端问题修改

This commit is contained in:
shen
2026-09-07 14:53:36 +08:00
parent b19d5b5dd3
commit 61272b75e9
32 changed files with 1023 additions and 95 deletions
+103 -4
View File
@@ -15,6 +15,14 @@
extends Node
const PlayerSkill := preload("res://player_skill.gd")
const UiAssets := preload("res://ui/ui_assets.gd")
const JOB_DIR := {
"WARRIOR": "warrior",
"ASSASSIN": "assassin",
"SURA": "sura",
"SHAMAN": "shaman",
}
signal skill_activated(skill_id: int) # game_scene 接它播技能特效
# §3.8 修改 1:三层校验挡下(code = OnCannotUseSkill 字符串码),game_scene 弹文案
@@ -33,16 +41,19 @@ var _skill_gate: RefCounted # PlayerSkill(§3.8 修改 1
var _player_getter: Callable
var _root: Control
var item_mouse: Node
var _slots := [] # 当前页 UI[{btn, cd, lbl}]
var _assets_root := ""
var _slots := [] # 当前页 UI[{btn, cd, lbl, icon, grade}]
var _state := [] # 36 个服务端槽:[{kind, id, cd_end:float}]
var _page := 0
var _move_from := -1
var _mobile_mode := false
func setup(m2client: Node, skill_table: RefCounted, parent: Node, player_getter: Callable) -> void:
func setup(m2client: Node, skill_table: RefCounted, parent: Node, player_getter: Callable,
assets_root_override := "") -> void:
client = m2client
table = skill_table
_player_getter = player_getter
_assets_root = assets_root_override if assets_root_override != "" else AssetRoot.path()
_skill_gate = PlayerSkill.new()
_skill_gate.setup(client, table)
for _i in SLOT_COUNT:
@@ -52,6 +63,8 @@ func setup(m2client: Node, skill_table: RefCounted, parent: Node, player_getter:
client.skill_cooldown_end.connect(_on_cd_end)
if client.has_signal("quickslots_changed"):
client.quickslots_changed.connect(restore_from_server)
if client.has_signal("skills_changed"):
client.skills_changed.connect(_refresh_page)
restore_from_server()
# 从服务器 GC_QUICKSLOT_* 恢复全部 36 个快捷栏槽位。
@@ -314,17 +327,40 @@ func _build(parent: Node) -> void:
num.text = str(i + 1)
num.position = Vector2(3, 1)
num.add_theme_font_size_override("font_size", 10)
num.mouse_filter = Control.MOUSE_FILTER_IGNORE
slot.add_child(num)
var icon := TextureRect.new()
icon.name = "icon"
icon.position = Vector2(4, 4)
icon.size = Vector2(32, 32)
icon.expand_mode = TextureRect.EXPAND_IGNORE_SIZE
icon.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED
icon.mouse_filter = Control.MOUSE_FILTER_IGNORE
slot.add_child(icon)
var lbl := Label.new()
lbl.name = "lbl"
lbl.position = Vector2(3, 15)
lbl.add_theme_font_size_override("font_size", 9)
lbl.mouse_filter = Control.MOUSE_FILTER_IGNORE
slot.add_child(lbl)
var grade := Label.new()
grade.name = "grade"
grade.position = Vector2(25, 25)
grade.size = Vector2(13, 13)
grade.horizontal_alignment = HORIZONTAL_ALIGNMENT_RIGHT
grade.add_theme_font_size_override("font_size", 9)
grade.add_theme_color_override("font_color", Color(1.0, 0.9, 0.45))
grade.add_theme_color_override("font_shadow_color", Color(0, 0, 0, 0.95))
grade.add_theme_constant_override("shadow_offset_x", 1)
grade.add_theme_constant_override("shadow_offset_y", 1)
grade.mouse_filter = Control.MOUSE_FILTER_IGNORE
slot.add_child(grade)
var cd := ColorRect.new()
cd.name = "cd"
cd.color = Color(0, 0, 0, 0.55)
cd.set_anchors_preset(Control.PRESET_FULL_RECT)
cd.visible = false
cd.mouse_filter = Control.MOUSE_FILTER_IGNORE
slot.add_child(cd)
var idx := i
slot.gui_input.connect(func(e: InputEvent):
@@ -334,7 +370,7 @@ func _build(parent: Node) -> void:
elif e.button_index == MOUSE_BUTTON_RIGHT:
_clear(idx))
row.add_child(slot)
_slots.append({"btn": slot, "cd": cd, "lbl": lbl})
_slots.append({"btn": slot, "cd": cd, "lbl": lbl, "icon": icon, "grade": grade})
if item_mouse and item_mouse.has_method("register_target"):
var local_idx: int = i
item_mouse.register_target(slot,
@@ -378,11 +414,74 @@ func _refresh_slot(slot: int) -> void:
return
var s: Dictionary = _state[_global_slot(slot)]
var txt := ""
var tex: Texture2D = null
var grade_text := ""
if s.kind == "skill" and table:
txt = table.name_of(s.id).substr(0, 5)
tex = _skill_icon(int(s.id))
grade_text = _skill_grade_text(int(s.id))
elif s.kind == "item":
txt = "#%d" % s.id
_slots[slot].lbl.text = txt
var icon: TextureRect = _slots[slot].icon
icon.texture = tex
icon.visible = tex != null
_slots[slot].lbl.text = txt if tex == null else ""
_slots[slot].grade.text = grade_text
_slots[slot].grade.visible = grade_text != "" and tex != null
func _skill_grade(skill_id: int) -> int:
if client and client.has_method("get_skills"):
for skill in client.get_skills():
if int(skill.get("id", 0)) == skill_id:
return clampi(int(skill.get("master", 0)), 0, 3)
return 0
func _skill_grade_text(skill_id: int) -> String:
match _skill_grade(skill_id):
1: return "M"
2: return "G"
3: return "P"
_: return ""
func _skill_icon(skill_id: int) -> Texture2D:
if _assets_root == "" or table == null or not table.has_method("entry"):
return null
var data: Dictionary = table.entry(skill_id)
var job := String(data.get("job", "")).to_upper()
var motion := String(data.get("motion", "")).strip_edges()
if motion == "":
return null
var candidates: Array[String] = []
if JOB_DIR.has(job):
var dir := String(JOB_DIR[job])
for suffix in _skill_icon_suffixes(skill_id):
candidates.append("ETC/ymir work/ui/skill/%s/%s%s.sub" % [dir, motion, suffix])
elif job == "SUPPORT":
for suffix in _skill_icon_suffixes(skill_id):
candidates.append("ETC/ymir work/ui/skill/common/support/%s%s.sub" % [motion, suffix])
candidates.append("ETC/ymir work/ui/skill/common/support/%s.sub" % motion)
elif job == "HORSE":
candidates.append("ETC/ymir work/ui/skill/common/horse/%s.sub" % motion)
elif job == "GUILD":
candidates.append("ETC/ymir work/ui/skill/common/guild/%s.sub" % motion)
for rel in candidates:
var tex: Texture2D = UiAssets.load_tex(_assets_root, rel)
if tex != null:
return tex
return null
func _skill_icon_suffixes(skill_id: int) -> Array[String]:
var grade := _skill_grade(skill_id)
var first := "_01"
if grade == 1:
first = "_02"
elif grade >= 2:
first = "_03"
var out: Array[String] = [first]
for suffix in ["_03", "_02", "_01"]:
if not out.has(suffix):
out.append(suffix)
return out
func _refresh_page() -> void:
if _root and _root.has_node("page"):