# HelpUI (P11 / §8.3) —— 游戏内帮助窗(1:1 迁移 `assets/root/uihelp.py` 的 # `HelpWindow`,单页版:`ENABLE_HELP_MULTIPAGE = 0` → `LoadDialogSinglePage()`)。 # # var hw := preload("res://ui/help_ui.gd").new() # add_child(hw) # hw.setup(ui_manager, m2client, assets_root) # hw.toggle() # H 键(非 Ctrl) # hw.open() # ESC 系统菜单 help_button # # 布局走真 `assets/uiscript/uiscript/helpwindow.py`(UiScript → UiBuild)。 # 文本逐字对齐 `uiScriptLocale.HELP_*`(`locale/locale//locale_interface.txt`); # `ui_manager` 没接 locale 回调时,`helpwindow.py` 里的 `uiScriptLocale.X` 会被 # UiScript 解析成 `` 占位,`_relabel()` 再用本工程的 `Locale` 表 + 英文兜底补回。 # # 入口逐字对照 `game.py:459 __PressHKey()`:非 Ctrl → `interface.OpenHelpWindow()` # (Ctrl+H 是 `net.SendChatPacket("/user_horse_ride")`,不在本窗职责内)。 # 关闭对照 `helpwindow.py` 的 `HelpWindow`:`close_button` / `OnPressEscapeKey` / # `OnPressExitKey` / `OnKeyDown(DIK_H)` 都调用 `eventClose`。ESC 由 `UiManager` # 的窗口栈统一处理(关最顶层);H 键复用 `toggle()`。 extends Node # helpwindow.py 的 name → uiScriptLocale key(逐字,含原脚本里重名的两个 `help_02`)。 const FLOAT_ROWS := { "help_01": "HELP_MOVE_KEY", "help_02": "HELP_CONTROL_CAMERA_BY_MIDDLEBUTTON", # 原脚本第二个 help_02(后者覆盖) "help_03": "HELP_SHOW_ALL_NAME", "help_04": "HELP_OPEN_CHAT", "help_05": "HELP_OPEN_WHISPER", "help_06": "HELP_ATTACK_KEY", "help_07": "HELP_OPEN_CHARACTER", "help_08": "HELP_OPEN_SKILL", "help_09": "HELP_OPEN_QUEST", "help_10": "HELP_OPEN_INVENTORY", "help_11": "HELP_OPEN_LOG", "help_12": "HELP_OPEN_ZONEMAP", "help_13": "HELP_OPEN_MINIMAP", "help_14": "HELP_CHANGE_PK_MODE", "help_15": "HELP_PICK_ITEM", "help_16": "HELP_SCREEN_CAPTURE", "help_17": "HELP_GUILD_WINDOW", "help_18": "HELP_MESSENGER_WINDOW", "help_19": "HELP_HELP", } # 任务栏贴纸标签(helpwindow.py 的 `taskbar_help_*` 文本)。 const TASKBAR_ROWS := { "taskbar_help_01": "HELP_FURY", "taskbar_help_02": "HELP_HP", "taskbar_help_03": "HELP_SP", "taskbar_help_04": "HELP_EXP", "taskbar_help_05": "HELP_MOUSE_LEFT", "taskbar_help_06": "HELP_MOUSE_RIGHT", "taskbar_help_07": "HELP_QUICKSLOT", "taskbar_help_08a": "HELP_SYSTEM_BUTTON", "taskbar_help_08b": "HELP_CHARACTER_BUTTON1", "taskbar_help_08c": "HELP_CHARACTER_BUTTON2", } # uiScriptLocale 兜底(逐字取自 `locale/locale/en/locale_interface.txt`)—— # 资产缺 locale 表或 UiManager 没接 locale 回调时用这份。 const FALLBACK := { "HELP_MOVE_KEY": "Panel: W, A, S, D or arrow keys", "HELP_CONTROL_CAMERA_BY_RIGHTBUTTON": "Camera View: right or middle mouse button", "HELP_CONTROL_CAMERA_BY_MIDDLEBUTTON": "Camera View: middle or right mouse button", "HELP_SHOW_ALL_NAME": "Display Names: Alt", "HELP_OPEN_CHAT": "Open chat window: Enter", "HELP_OPEN_WHISPER": "Open Whisper Window: Shift + Enter", "HELP_ATTACK_KEY": "Attack: left mouse button or space bar", "HELP_OPEN_CHARACTER": "Open character window: C", "HELP_OPEN_SKILL": "Open Skill Window: V", "HELP_OPEN_QUEST": "Open Task Window: N", "HELP_OPEN_INVENTORY": "Open inventory window: I", "HELP_OPEN_LOG": "Open Chatlog: L", "HELP_OPEN_ZONEMAP": "Open Large Map: M", "HELP_OPEN_MINIMAP": "Open mini map: Shift + M", "HELP_CHANGE_PK_MODE": "Change attack mode: change setting of left mouse button", "HELP_PICK_ITEM": "Collect Items: ^ or Y or left mouse button", "HELP_SCREEN_CAPTURE": "Save Screenshot: Print (will be saved in file \"Metin2\\screenshot\")", "HELP_GUILD_WINDOW": "Open Guild Window: Alt + G", "HELP_MESSENGER_WINDOW": "Open Friends List: Alt + M", "HELP_HELP": "Display help: H", "HELP_FURY": "Ingame Item Shop", "HELP_HP": "Hit Points (HP)", "HELP_SP": "Spell Points (SP)", "HELP_EXP": "Experience", "HELP_MOUSE_LEFT": "Function of the Left Mouse button", "HELP_MOUSE_RIGHT": "Function of the Right Mouse button", "HELP_QUICKSLOT": "Fast Access Fields", "HELP_SYSTEM_BUTTON": "System buttons", "HELP_CHARACTER_BUTTON1": "(Character Window, Inventory Window,", "HELP_CHARACTER_BUTTON2": "List of Friends and Options)", "CLOSE": "Close", } var ui: CanvasLayer var client: Node var assets_root := "" var uiscript_dir := "" var _win: Dictionary = {} var _loc # Locale(res://locale.gd) func setup(ui_manager: CanvasLayer, m2client: Node = null, assets := "") -> void: ui = ui_manager client = m2client assets_root = assets if assets_root == "" and ui and "assets_root" in ui: assets_root = ui.assets_root uiscript_dir = assets_root.path_join("uiscript/uiscript") if not DirAccess.dir_exists_absolute(uiscript_dir): uiscript_dir = assets_root.path_join("uiscript") var LocaleScript = load("res://locale.gd") if LocaleScript: _loc = LocaleScript.new() _loc.setup(assets_root, "en") # --- open / close --------------------------------------------------- func is_open() -> bool: return not _win.is_empty() and is_instance_valid(_win.get("root")) func toggle() -> void: if is_open(): close() else: open() func close() -> void: if is_open(): ui.close(_win["root"]) _win = {} func open() -> void: if is_open(): return var path := uiscript_dir.path_join("helpwindow.py") if not FileAccess.file_exists(path): push_warning("HelpUI: no helpwindow.py at " + path) return _win = ui.open_script(path, assets_root) if not is_open(): return _relabel() _wire() func _node(nm: String) -> Control: if _win.is_empty(): return null var n = _win.get("nodes", {}).get(nm, null) return n if n is Control else null # --- content (uihelp.py.LoadDialogSinglePage + helpwindow.py 文本) --------- # 解析 `` 占位 / 应用 name→key 映射:先扫所有 Label(覆盖原脚本重名的两个 # `help_02`),再按映射兜一遍(nodes dict 只留最后一个同名)。 func _relabel() -> void: var root: Control = _win.get("root") if root: for lbl in root.find_children("*", "Label", true, false): var t := String(lbl.text) if t.length() >= 2 and t.begins_with("<") and t.ends_with(">"): lbl.text = _text(t.substr(1, t.length() - 2)) for nm in FLOAT_ROWS: _set_text(nm, _text(FLOAT_ROWS[nm])) for nm in TASKBAR_ROWS: _set_text(nm, _text(TASKBAR_ROWS[nm])) _set_text("close_button", _text("CLOSE")) func _set_text(nm: String, s: String) -> void: var n := _node(nm) if n == null: return if n.has_method("set_text"): n.set_text(s) elif "text" in n: n.text = s # uiScriptLocale. 的取值:优先本工程 Locale 表,否则英文兜底,否则原样 key。 func _text(key: String) -> String: if _loc != null and _loc.has(key): return _loc.t(key) return FALLBACK.get(key, key) # 已绑定的帮助行文本(供自检 / 调试)。 func rows() -> Array: var out: Array = [] for nm in FLOAT_ROWS: var n := _node(nm) if n and "text" in n: out.append(String(n.text)) return out # --- wiring (uihelp.py.HelpWindow.SetCloseEvent) ------------------------ func _wire() -> void: var btn := _node("close_button") if btn is BaseButton: btn.pressed.connect(close) # helpwindow.py2 的多页按钮在单页版不存在;此处不绑。