- 桥梁与静态物体高度采样修复: - 严格对齐 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 客户端对拍缺陷发现与修复工程指南
128 lines
3.7 KiB
GDScript
128 lines
3.7 KiB
GDScript
# 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()
|