Files
mtgodot-poc/project/ui/death_ui.gd
T
shenandshen 66d217b313 feat(client): 完成40250客户端核心功能1:1对齐与桥梁高度采样修复
- 桥梁与静态物体高度采样修复:
  - 严格对齐 40250 CMapOutdoor::GetHeight 与 CAttributeInstance::GetHeight
  - 解析 .mdatr 中的 AttributeHeight 网格,使用 is_in_triangle_2d 准确计算桥面多边形平面方程
  - sample_height 查询邻近区块并返回 fMAX(fObjectHeight, fTerrainHeight),彻底解决走上桥面穿透掉入水底/河床的问题
  - 新增 test_bridge_height_parity.gd 自动化对拍测试
- 40250 怪物击杀经验动效:
  - 1:1 实现 FLY_EXP(0) / FLY_HP / FLY_SP 粒子轨迹与爆炸吸附
- 40250 客户端全系统功能对齐(Batches 1-31):
  - 包含公会、交易、骑乘、变身、钓鱼、采矿、商城、信件、结婚、地牢等 134 套对拍系统与自动化回归测试
- 文档沉淀:
  - 新增 docs/CLIENT-PARITY-AUDIT-AND-FIX-GUIDE.md 客户端对拍缺陷发现与修复工程指南
2026-09-19 08:51:25 -07:00

140 lines
4.5 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.
# death_ui.gd —— 40250 死亡结算与复活面板(RestartDialog1:1 实现
# 严格对照:
# root/uirestart.py (RestartDialog)
# uiscript/restartdialog.py (200x88 ThinBoard)
# metin2/src/server/game/src/cmd_general.cpp:478 (10s restart_here cooldown)
extends Node
const RESTART_HERE_COOLDOWN := 10.0 # 40250 官方 10 秒原地复活保护冷却
const BOARD_WIDTH := 200.0
const BOARD_HEIGHT := 88.0
var client: Node
var _root: Control
var _board: Panel
var _btn_restart_here: Button
var _btn_restart_town: Button
var _shown := false
var _here_cooldown_remaining := 0.0
func setup(m2client: Node, parent: Node) -> void:
client = m2client
_build(parent)
if client.has_signal("entity_dead"):
client.entity_dead.connect(_on_dead)
if client.has_signal("phase_changed"):
client.phase_changed.connect(func(p): if p == "dead": show_dialog())
if client.has_signal("vitals_changed"):
client.vitals_changed.connect(_on_vitals)
func _process(delta: float) -> void:
if not _shown:
return
if _here_cooldown_remaining > 0.0:
_here_cooldown_remaining -= delta
if _here_cooldown_remaining <= 0.0:
_here_cooldown_remaining = 0.0
_btn_restart_here.disabled = false
_btn_restart_here.text = "原地复活"
else:
_btn_restart_here.disabled = true
_btn_restart_here.text = "原地复活 (%d 秒)" % int(ceilf(_here_cooldown_remaining))
func _on_dead(vid: int) -> void:
if client.has_method("get_main_vid") and vid == client.get_main_vid():
show_dialog()
func _on_vitals(vid: int) -> void:
if not _shown:
return
if client.has_method("get_main_vid") and vid == client.get_main_vid():
var e: Dictionary = client.get_entity(vid)
if int(e.get("hp", 0)) > 0 and not e.get("dead", false):
hide_dialog()
func show_dialog() -> void:
if _shown:
return
_shown = true
_here_cooldown_remaining = RESTART_HERE_COOLDOWN
_btn_restart_here.disabled = true
_btn_restart_here.text = "原地复活 (10 秒)"
_root.visible = true
func hide_dialog() -> void:
_shown = false
_here_cooldown_remaining = 0.0
_root.visible = false
func is_open() -> bool:
return _shown and _root != null and _root.visible
func _build(parent: Node) -> void:
_root = Control.new()
_root.name = "RestartDialog"
_root.set_anchors_preset(Control.PRESET_FULL_RECT)
_root.visible = false
_root.mouse_filter = Control.MOUSE_FILTER_STOP
parent.add_child(_root)
# 全屏暗红暗角
var dim := ColorRect.new()
dim.set_anchors_preset(Control.PRESET_FULL_RECT)
dim.color = Color(0.12, 0.0, 0.0, 0.6)
_root.add_child(dim)
# 40250 uiscript/restartdialog.py 1:1 尺寸 200x88 ThinBoard
_board = Panel.new()
_board.name = "Board"
_board.set_anchors_preset(Control.PRESET_CENTER)
_board.position = Vector2(-BOARD_WIDTH / 2.0, -BOARD_HEIGHT / 2.0)
_board.size = Vector2(BOARD_WIDTH, BOARD_HEIGHT)
var sb := StyleBoxFlat.new()
sb.bg_color = Color(0.3333, 0.2941, 0.2588, 0.95)
sb.border_color = Color(0.45, 0.38, 0.22, 0.95)
sb.set_border_width_all(1)
sb.set_corner_radius_all(2)
_board.add_theme_stylebox_override("panel", sb)
_root.add_child(_board)
# 40250 restart_here_button (10, 17), 180x26
_btn_restart_here = Button.new()
_btn_restart_here.name = "RestartHereButton"
_btn_restart_here.position = Vector2(10, 17)
_btn_restart_here.size = Vector2(180, 26)
_btn_restart_here.text = "原地复活 (10 秒)"
_btn_restart_here.disabled = true
_btn_restart_here.add_theme_font_size_override("font_size", 11)
_btn_restart_here.mouse_default_cursor_shape = Control.CURSOR_POINTING_HAND
_btn_restart_here.pressed.connect(_on_restart_here_pressed)
_board.add_child(_btn_restart_here)
# 40250 restart_town_button (10, 47), 180x26
_btn_restart_town = Button.new()
_btn_restart_town.name = "RestartTownButton"
_btn_restart_town.position = Vector2(10, 47)
_btn_restart_town.size = Vector2(180, 26)
_btn_restart_town.text = "在村庄复活"
_btn_restart_town.add_theme_font_size_override("font_size", 11)
_btn_restart_town.mouse_default_cursor_shape = Control.CURSOR_POINTING_HAND
_btn_restart_town.pressed.connect(_on_restart_town_pressed)
_board.add_child(_btn_restart_town)
# 40250 uirestart.py: OnPressEscapeKey / OnPressExitKey returns True (禁止 ESC 关闭)
_root.gui_input.connect(func(event: InputEvent):
if event is InputEventKey and event.pressed and event.keycode == KEY_ESCAPE:
_root.accept_event()
)
func _on_restart_here_pressed() -> void:
if _here_cooldown_remaining > 0.0:
return
_restart("/restart_here")
func _on_restart_town_pressed() -> void:
_restart("/restart_town")
func _restart(cmd: String) -> void:
if client and client.has_method("say"):
client.say(0, cmd)