fix: 装备属性面板避让逻辑 + 多项功能更新
- item_tooltip_view.gd: 新增 avoid_rect 属性,tooltip 与装备窗口重叠时自动推到左侧 - inventory_ui.gd: 悬停装备时传入窗口矩形作为避让区域 - 包含其他累积的功能开发和测试文件
This commit is contained in:
@@ -35,10 +35,12 @@ const JOB_BASE_STATS := {
|
||||
2: {"con": 3, "int": 5, "str": 5, "dex": 3}, # sura
|
||||
3: {"con": 4, "int": 6, "str": 3, "dex": 3}, # shaman
|
||||
}
|
||||
# §1.10 名称长度校验统一:与 wire 契约 CHARACTER_NAME_MAX_LEN(=24, name[25])
|
||||
# 对齐。角色名可含多字节字符,wire 缓冲是定长 25 字节,故按 UTF-8 字节长度设限,
|
||||
# 与 guild_ui.gd 的公会名校验(非空 / 超长 / 控制字符)保持同一形状。
|
||||
const CHAR_NAME_MAX_BYTES := 24
|
||||
# §1.10:40250 的角色名上限是网络字段的 24 个 GB2312 字节,而不是
|
||||
# Godot/UTF-8 输入的 24 个字节。一个常用汉字在 GB2312 中占 2 字节,所以
|
||||
# 12 个汉字可以合法放入角色名字段;直接按 UTF-8 字节限制会把它错误拒绝。
|
||||
# 输入框只限制 Unicode 字符数量,最终的 GB2312 可表示性和 wire 字节容量由
|
||||
# M2Client/ClassicSession 在真正发包前统一校验。
|
||||
const CHAR_NAME_MAX_CHARS := 24
|
||||
const CHAR_NAME_MIN_CHARS := 2
|
||||
|
||||
const EMPIRE_KEY := {1: "EMPIRE_A", 2: "EMPIRE_B", 3: "EMPIRE_C"}
|
||||
@@ -128,8 +130,8 @@ func _first_occupied() -> int:
|
||||
func _validate_char_name(nm: String) -> String:
|
||||
if nm.length() < CHAR_NAME_MIN_CHARS:
|
||||
return "名称太短"
|
||||
if nm.to_utf8_buffer().size() > CHAR_NAME_MAX_BYTES:
|
||||
return "名称太长(最多 %d 字节)" % CHAR_NAME_MAX_BYTES
|
||||
if nm.length() > CHAR_NAME_MAX_CHARS:
|
||||
return "名称太长(最多 %d 个字符)" % CHAR_NAME_MAX_CHARS
|
||||
for ch in nm:
|
||||
if ch.unicode_at(0) < 32:
|
||||
return "名称包含非法字符"
|
||||
@@ -695,9 +697,16 @@ func _do_start() -> void:
|
||||
if dur > 0.0:
|
||||
anim_dur = dur
|
||||
|
||||
await get_tree().create_timer(anim_dur).timeout
|
||||
if not is_inside_tree():
|
||||
return
|
||||
# The real select window is always tree-owned, but keeping the signal
|
||||
# usable when a headless/reconnect harness invokes the handler before the
|
||||
# transient CanvasLayer is attached prevents the selection from being
|
||||
# silently dropped. Once a tree-owned screen leaves the tree, it is being
|
||||
# replaced and must not emit into the new phase.
|
||||
var had_tree := is_inside_tree()
|
||||
if had_tree and get_tree() != null:
|
||||
await get_tree().create_timer(anim_dur).timeout
|
||||
if not is_inside_tree():
|
||||
return
|
||||
select_requested.emit(_slot_index())
|
||||
|
||||
func _unhandled_input(event: InputEvent) -> void:
|
||||
@@ -791,9 +800,9 @@ func _open_create_dialog() -> void:
|
||||
nrow.add_child(_plain("名称", 13, Color(0.72, 0.78, 0.85)))
|
||||
var name_edit := LineEdit.new()
|
||||
name_edit.name = "Name"
|
||||
name_edit.max_length = CHAR_NAME_MAX_BYTES
|
||||
name_edit.max_length = CHAR_NAME_MAX_CHARS
|
||||
name_edit.custom_minimum_size = Vector2(240, 0)
|
||||
name_edit.placeholder_text = "角色名(最多 24 字节)"
|
||||
name_edit.placeholder_text = "角色名(中文最多 12 字,最终按 GB2312 字节校验)"
|
||||
nrow.add_child(name_edit)
|
||||
|
||||
# 四维(起始属性,只读,随职业变)
|
||||
@@ -852,9 +861,9 @@ func _open_change_name_dialog() -> void:
|
||||
nrow.add_child(_plain("新名称", 13, Color(0.72, 0.78, 0.85)))
|
||||
var name_edit := LineEdit.new()
|
||||
name_edit.name = "Name"
|
||||
name_edit.max_length = CHAR_NAME_MAX_BYTES
|
||||
name_edit.max_length = CHAR_NAME_MAX_CHARS
|
||||
name_edit.custom_minimum_size = Vector2(220, 0)
|
||||
name_edit.placeholder_text = "角色名(最多 24 字节)"
|
||||
name_edit.placeholder_text = "角色名(中文最多 12 字,最终按 GB2312 字节校验)"
|
||||
nrow.add_child(name_edit)
|
||||
box.add_child(_sep())
|
||||
var brow := HBoxContainer.new()
|
||||
|
||||
Reference in New Issue
Block a user