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 客户端对拍缺陷发现与修复工程指南
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
# game_button_money_dialog_system.gd
|
||||
# 40250 官方 1:1 浮动任务栏状态红点通知与金币分堆丢弃输入窗
|
||||
# 对照: uigamebutton.py, gamewindow.py, uipickmoney.py, PickMoneyDialog.py
|
||||
class_name GameButtonMoneyDialogSystem
|
||||
extends RefCounted
|
||||
|
||||
# =========================================================================
|
||||
# 1. 浮动任务栏状态红点与操作按钮组 (GameButtonWindow)
|
||||
# =========================================================================
|
||||
class GameButtonManager extends RefCounted:
|
||||
var button_visible: Dictionary = {
|
||||
"STATUS": false,
|
||||
"SKILL": false,
|
||||
"QUEST": false,
|
||||
"HELP": false,
|
||||
"BUILD": false,
|
||||
"EXIT_OBSERVER": false
|
||||
}
|
||||
|
||||
var is_observer_mode: bool = false
|
||||
var last_chat_packet_sent: String = ""
|
||||
|
||||
signal button_visibility_changed(btn_name: String, visible: bool)
|
||||
signal observer_exit_triggered()
|
||||
|
||||
func check_game_buttons(stat_points: int, skill_active_points: int, play_time: int) -> void:
|
||||
# player.GetStatus(player.STAT) > 0 -> StatusPlusButton
|
||||
var show_status = stat_points > 0
|
||||
_set_button("STATUS", show_status)
|
||||
|
||||
# player.GetStatus(player.SKILL_ACTIVE) > 0 -> SkillPlusButton
|
||||
var show_skill = skill_active_points > 0
|
||||
_set_button("SKILL", show_skill)
|
||||
|
||||
# 0 == player.GetPlayTime() -> HelpButton
|
||||
var show_help = (play_time == 0)
|
||||
_set_button("HELP", show_help)
|
||||
|
||||
func set_quest_notice(has_unread: bool) -> void:
|
||||
_set_button("QUEST", has_unread)
|
||||
|
||||
func set_build_button(can_build: bool) -> void:
|
||||
_set_button("BUILD", can_build)
|
||||
|
||||
func set_observer_mode(enabled: bool) -> void:
|
||||
is_observer_mode = enabled
|
||||
_set_button("EXIT_OBSERVER", enabled)
|
||||
|
||||
func click_exit_observer() -> void:
|
||||
if is_observer_mode:
|
||||
last_chat_packet_sent = "/observer_exit"
|
||||
observer_exit_triggered.emit()
|
||||
|
||||
func _set_button(btn_name: String, is_show: bool) -> void:
|
||||
if button_visible.get(btn_name, false) != is_show:
|
||||
button_visible[btn_name] = is_show
|
||||
button_visibility_changed.emit(btn_name, is_show)
|
||||
|
||||
# =========================================================================
|
||||
# 2. 金币/物品分堆输入对话框 (PickMoneyDialog)
|
||||
# =========================================================================
|
||||
class PickMoneyDialog extends RefCounted:
|
||||
const DIALOG_WIDTH: int = 170
|
||||
const DIALOG_HEIGHT: int = 90
|
||||
|
||||
var is_open: bool = false
|
||||
var max_value: int = 0
|
||||
var unit_value: int = 1
|
||||
var current_input_text: String = "1"
|
||||
|
||||
var pos_x: int = 0
|
||||
var pos_y: int = 0
|
||||
|
||||
var last_accepted_value: int = 0
|
||||
|
||||
signal opened(max_val: int, unit_val: int, x: int, y: int)
|
||||
signal accepted(amount: int)
|
||||
signal closed()
|
||||
|
||||
func open_dialog(p_max_value: int, p_unit_value: int = 1, mouse_x: int = 0, mouse_y: int = 0, screen_w: int = 1024, screen_h: int = 768) -> void:
|
||||
max_value = p_max_value
|
||||
unit_value = p_unit_value
|
||||
current_input_text = str(unit_value)
|
||||
last_accepted_value = 0
|
||||
|
||||
# 40250 官方吸附定位计算
|
||||
var half_w = DIALOG_WIDTH / 2
|
||||
if mouse_x + half_w > screen_w:
|
||||
pos_x = screen_w - DIALOG_WIDTH
|
||||
elif mouse_x - half_w < 0:
|
||||
pos_x = 0
|
||||
else:
|
||||
pos_x = mouse_x - half_w
|
||||
|
||||
pos_y = mouse_y - DIALOG_HEIGHT - 20
|
||||
if pos_y < 0:
|
||||
pos_y = 10
|
||||
|
||||
is_open = true
|
||||
opened.emit(max_value, unit_value, pos_x, pos_y)
|
||||
|
||||
func input_text(text: String) -> void:
|
||||
current_input_text = text
|
||||
|
||||
func on_accept() -> bool:
|
||||
if not is_open:
|
||||
return false
|
||||
|
||||
var text = current_input_text.strip_edges()
|
||||
if text.is_valid_int():
|
||||
var val = text.to_int()
|
||||
if val > 0:
|
||||
val = mini(val, max_value)
|
||||
last_accepted_value = val
|
||||
accepted.emit(val)
|
||||
close_dialog()
|
||||
return true
|
||||
|
||||
close_dialog()
|
||||
return false
|
||||
|
||||
func close_dialog() -> void:
|
||||
is_open = false
|
||||
closed.emit()
|
||||
|
||||
var game_buttons: GameButtonManager = GameButtonManager.new()
|
||||
var money_dialog: PickMoneyDialog = PickMoneyDialog.new()
|
||||
Reference in New Issue
Block a user