Implement 40250 classic client port

This commit is contained in:
shenlei
2026-09-01 18:49:28 +09:00
parent 2277b1dd60
commit 8f61990a83
481 changed files with 169826 additions and 293 deletions
+51 -4
View File
@@ -18,14 +18,14 @@ const ROLE_ATTACKER := 2
const ROLE_TANKER := 3
const ROLE_BUFFER := 4
const ROLE_SKILL_MASTER := 5
const ROLE_BERSERKER := 6
const ROLE_HASTE := 6
const ROLE_DEFENDER := 7
const ROLE_LABEL := {
0: "", 1: "", 2: "", 3: "", 4: "", 5: "", 6: "", 7: "",
0: "", 1: "", 2: "", 3: "", 4: "", 5: "", 6: "", 7: "",
}
const ROLE_MENU := [
[ROLE_NORMAL, "普通"], [ROLE_ATTACKER, "攻击"], [ROLE_TANKER, "坦克"],
[ROLE_BERSERKER, "狂战"], [ROLE_BUFFER, "辅助"], [ROLE_SKILL_MASTER, "宗师"],
[ROLE_HASTE, "迅捷"], [ROLE_BUFFER, "辅助"], [ROLE_SKILL_MASTER, "宗师"],
[ROLE_DEFENDER, "防御"],
]
# Packet.h EPartyExpDistributionType
@@ -34,13 +34,15 @@ const EXP_PARITY := 1 # 均分
# uiparty.PartyMemberInfoBoard.PARTY_SKILL_*
const PARTY_SKILL_HEAL := 1
# affects[7] 槽位含义(暂定,按 partymemberinfoboard.py 图标顺序)
const AFFECT_LABEL := ["经验", "攻击", "防御", "辅助", "宗师", "时间", "回复"]
const AFFECT_LABEL := ["经验", "攻击", "坦克", "辅助", "宗师", "迅捷", "防御"]
var client: Node
var dialogs: Node
var _root: Control
var _list: VBoxContainer
var _dist_btn: Button
var _heal_btn: Button
var _notice: Label
var _role_popup: Control = null
func setup(m2client: Node, parent: Node, dlg: Node = null) -> void:
@@ -51,6 +53,8 @@ func setup(m2client: Node, parent: Node, dlg: Node = null) -> void:
client.party_changed.connect(refresh)
if client.has_signal("party_invite_ask"):
client.party_invite_ask.connect(_on_invite)
if client.has_signal("party_request_denied"):
client.party_request_denied.connect(_on_request_denied)
if client.has_signal("vitals_changed"):
client.vitals_changed.connect(func(_v): if is_open(): refresh())
refresh()
@@ -91,6 +95,37 @@ func _refresh_dist_btn() -> void:
var mode := int(client.get_party_distribute_mode()) if client.has_method("get_party_distribute_mode") else 0
_dist_btn.text = "EXP:均分" if mode == EXP_PARITY else "EXP:不均分"
_dist_btn.disabled = not _local_is_leader()
if is_instance_valid(_heal_btn):
var leadership := _leadership_level()
_heal_btn.disabled = not _local_is_leader() or (leadership >= 0 and leadership < 18)
_heal_btn.tooltip_text = "队长 Leadership 达到 18 级后可用" if _heal_btn.disabled and leadership >= 0 and leadership < 18 else "组队治疗"
func _leadership_level() -> int:
# The server's CParty::Update gates party roles/heal using the leader's
# Leadership skill. -1 means that the snapshot has not arrived yet; in
# that case the server remains authoritative and the controls stay usable.
if client == null or not client.has_method("get_skills"):
return -1
var skills: Array = client.get_skills()
for skill in skills:
if int(skill.get("id", -1)) == 121: # SKILL_LEADERSHIP in 40250
return int(skill.get("level", 0))
return -1
func _role_unlock_level(role: int) -> int:
match role:
ROLE_ATTACKER: return 10
ROLE_TANKER, ROLE_HASTE: return 20
ROLE_BUFFER: return 25
ROLE_SKILL_MASTER: return 35
ROLE_DEFENDER: return 40
_: return 0
func _role_allowed(role: int, current_role: int = -1) -> bool:
if role == ROLE_NORMAL or role == current_role:
return true
var leadership := _leadership_level()
return leadership < 0 or leadership >= _role_unlock_level(role)
# --- 한 명 strip ------------------------------------------------------
@@ -178,6 +213,9 @@ func _open_role_popup(anchor: Control, pid: int, cur_role: int) -> void:
var b := Button.new()
b.text = entry[1] + ("" if r == cur_role else "")
b.custom_minimum_size = Vector2(84, 22)
b.disabled = not _role_allowed(r, cur_role)
if b.disabled:
b.tooltip_text = "Leadership %d 级解锁" % _role_unlock_level(r)
b.pressed.connect(func() -> void:
if r == ROLE_NORMAL:
# OnSelectState(-1): 清掉当前角色
@@ -213,6 +251,10 @@ func _on_invite(leader_pid: int) -> void:
else:
accept.call()
func _on_request_denied() -> void:
if is_instance_valid(_notice):
_notice.text = "组队请求被拒绝"
# --- EXP 분배 / 组队治疗 --------------------------------------------
func _toggle_distribute() -> void:
@@ -255,7 +297,12 @@ func _build(parent: Node) -> void:
heal.text = "组队治疗"
heal.add_theme_font_size_override("font_size", 11)
heal.pressed.connect(_party_heal)
_heal_btn = heal
header.add_child(heal)
_notice = Label.new()
_notice.add_theme_font_size_override("font_size", 10)
_notice.add_theme_color_override("font_color", Color(1, 0.65, 0.55))
header.add_child(_notice)
_list = VBoxContainer.new()
_list.position = Vector2(8, 32)