Complete remaining client gap features
This commit is contained in:
+121
-1
@@ -43,6 +43,7 @@ const SystemMenuUI = preload("res://ui/system_menu_ui.gd")
|
||||
const Quickbar = preload("res://ui/quickbar.gd")
|
||||
const QuestDialog = preload("res://ui/quest_dialog.gd")
|
||||
const QuestLog = preload("res://ui/quest_log.gd")
|
||||
const DungeonResultUI = preload("res://ui/dungeon_result_ui.gd")
|
||||
const SelectItemUI = preload("res://ui/select_item_ui.gd")
|
||||
const PartyUI = preload("res://ui/party_ui.gd")
|
||||
const FriendUI = preload("res://ui/friend_ui.gd")
|
||||
@@ -95,6 +96,7 @@ var system_menu_ui: Node # SystemMenuUI
|
||||
var quickbar: Node # Quickbar
|
||||
var quest_dialog: Node # QuestDialog
|
||||
var quest_log: Node # QuestLog
|
||||
var dungeon_result_ui: Node # DungeonResultUI
|
||||
var select_item_ui: Node # SelectItemUI
|
||||
var party_ui: Node # PartyUI
|
||||
var friend_ui: Node # FriendUI
|
||||
@@ -171,6 +173,10 @@ func setup(m2client: Node, assets_root: String,
|
||||
add_child(net_world)
|
||||
net_world.world = world
|
||||
net_world.setup(client, _mount)
|
||||
# §8.8 屏幕空间实体血条:明确绑定轨道相机,避免依赖 viewport 当前相机,
|
||||
# 也让地图切换 / 多视口时投影来源稳定。
|
||||
if net_world.has_method("set_camera"):
|
||||
net_world.set_camera(cam)
|
||||
net_world.set_local_node(player)
|
||||
net_world.entity_added.connect(func(node: Node3D, _vid: int):
|
||||
if node not in pc.pickables:
|
||||
@@ -195,6 +201,9 @@ func setup(m2client: Node, assets_root: String,
|
||||
# §8.6 targetBoard.GetTargetVID() -> net_world:选中目标始终强显名字。
|
||||
if net_play.has_signal("target_changed") and net_world and net_world.has_method("set_target_vid"):
|
||||
net_play.target_changed.connect(func(vid: int): net_world.set_target_vid(int(vid)))
|
||||
# §8.8 game.py OnRender chr.Pick() -> ShowCharacterTextTail:悬停角色也强显名字(pick_show.gd)。
|
||||
if pc.has_signal("hover_entity_changed") and net_world and net_world.has_method("set_hover_vid"):
|
||||
pc.hover_entity_changed.connect(func(vid: int): net_world.set_hover_vid(int(vid)))
|
||||
if _assets != "":
|
||||
net_play.set_asset_root(_assets) # §3.5:加载 playersettingmodule.py 连击段表
|
||||
|
||||
@@ -225,6 +234,10 @@ func setup(m2client: Node, assets_root: String,
|
||||
chat.setup(client, ui, _assets)
|
||||
if net_play and net_play.has_signal("fishing_feedback") and chat.has_method("on_fishing_feedback"):
|
||||
net_play.fishing_feedback.connect(chat.on_fishing_feedback)
|
||||
# §8.8 / §5.4 game.py SetPCTargetBoard :804 —— 按住 LCONTROL 点同阵营他人 PC 时
|
||||
# self.interface.OpenWhisperDialog(name)。chat.start_whisper 打开独立私聊窗口。
|
||||
if net_play and net_play.has_signal("whisper_requested") and chat.has_method("start_whisper"):
|
||||
net_play.whisper_requested.connect(chat.start_whisper)
|
||||
if net_world and net_world.has_signal("main_bubble"):
|
||||
net_world.main_bubble.connect(_player_bubble)
|
||||
|
||||
@@ -295,6 +308,15 @@ func setup(m2client: Node, assets_root: String,
|
||||
quest_dialog = QuestDialog.new()
|
||||
add_child(quest_dialog)
|
||||
quest_dialog.setup(client, ui, proto, assets_root)
|
||||
if quest_dialog.has_signal("camera_event_requested_full"):
|
||||
quest_dialog.camera_event_requested_full.connect(_on_quest_camera_event)
|
||||
if quest_dialog.has_signal("fade_event_requested_full"):
|
||||
quest_dialog.fade_event_requested_full.connect(_on_quest_fade_event)
|
||||
if quest_dialog.has_signal("dungeon_result_requested"):
|
||||
quest_dialog.dungeon_result_requested.connect(_on_dungeon_result)
|
||||
dungeon_result_ui = DungeonResultUI.new()
|
||||
add_child(dungeon_result_ui)
|
||||
dungeon_result_ui.setup(ui)
|
||||
quest_log = QuestLog.new()
|
||||
add_child(quest_log)
|
||||
quest_log.setup(client, ui)
|
||||
@@ -330,6 +352,8 @@ func setup(m2client: Node, assets_root: String,
|
||||
await _yield()
|
||||
if chat and chat.has_method("set_proto"):
|
||||
chat.set_proto(proto)
|
||||
if quest_dialog and quest_dialog.has_method("set_proto"):
|
||||
quest_dialog.set_proto(proto)
|
||||
var mp := assets_root.path_join("locale/locale/en/mob_proto")
|
||||
if FileAccess.file_exists(mp):
|
||||
proto.call("load_mob_proto", mp)
|
||||
@@ -367,7 +391,16 @@ func setup(m2client: Node, assets_root: String,
|
||||
# 地面掉落物
|
||||
ground_items = GroundItems.new()
|
||||
add_child(ground_items)
|
||||
ground_items.setup(client, _mount, func() -> Node: return player, proto, item_list)
|
||||
# SetItemTextTailOwner :722:strOwnership = ApplicationStringTable(IDS_POSSESSIVE_MORPHENE)
|
||||
# 为空则字面 "'s"。poc 用 EterLocale 的 POSSESSIVE_MORPHENE 键作对应物(缺则回 "")。
|
||||
var _possessive := ""
|
||||
if assets_root != "":
|
||||
var _poss_loc: RefCounted = load("res://locale.gd").new()
|
||||
_poss_loc.setup(assets_root, "en")
|
||||
if _poss_loc.has("POSSESSIVE_MORPHENE"):
|
||||
_possessive = _poss_loc.t("POSSESSIVE_MORPHENE")
|
||||
ground_items.setup(client, _mount, func() -> Node: return player, proto, item_list,
|
||||
func() -> Camera3D: return cam, _possessive)
|
||||
pc.set_input_surfaces(cursor_manager, ui, ground_items,
|
||||
Callable(net_play, "cancel_fishing"), Callable(net_play, "on_ground_click"))
|
||||
view_equipment_ui = ViewEquipmentUI.new()
|
||||
@@ -489,6 +522,15 @@ func setup(m2client: Node, assets_root: String,
|
||||
game_option_ui.display_option_changed.connect(_on_display_option)
|
||||
if net_world and net_world.has_method("set_always_show_name") and game_option_ui.has_method("display_value"):
|
||||
net_world.set_always_show_name(game_option_ui.display_value("always_show_name") == 1)
|
||||
# §8.8 / §5.4「伤害数字」radio -> net_world(CPythonSystem::SetShowDamageFlag)。
|
||||
if net_world and net_world.has_method("set_show_damage") and game_option_ui.has_method("display_value"):
|
||||
net_world.set_show_damage(game_option_ui.display_value("show_damage") == 1)
|
||||
# §8.4「名字色」radio -> net_world(uigameoption.__SetNameColorMode → chrmgr.SetEmpireNameMode)。
|
||||
if net_world and net_world.has_method("set_empire_name_mode") and game_option_ui.has_method("display_value"):
|
||||
net_world.set_empire_name_mode(game_option_ui.display_value("name_color") == 1)
|
||||
# §8.4「看他国玩家目标框」radio -> net_play(uitarget.TargetBoard.Open 前置过滤)。
|
||||
if net_play and net_play.has_method("set_view_other_empire_target") and game_option_ui.has_method("display_value"):
|
||||
net_play.set_view_other_empire_target(game_option_ui.display_value("target_board") == 1)
|
||||
system_menu_ui = SystemMenuUI.new()
|
||||
add_child(system_menu_ui)
|
||||
system_menu_ui.setup(ui, client, assets_root, system_option_ui, game_option_ui)
|
||||
@@ -614,6 +656,69 @@ func _queue_shot(skill: int) -> void:
|
||||
_pending_shots.pop_front()
|
||||
|
||||
var _flash_rect: ColorRect
|
||||
var _quest_fade_rect: ColorRect
|
||||
var _quest_fade_tween: Tween
|
||||
|
||||
func _on_quest_camera_event(kind: String, setting: Dictionary, blendtime: float) -> void:
|
||||
if cam == null or not is_instance_valid(cam):
|
||||
return
|
||||
match kind:
|
||||
"SET_CAMERA":
|
||||
if cam.has_method("set_event_camera"):
|
||||
cam.set_event_camera(setting)
|
||||
"BLEND_CAMERA":
|
||||
if cam.has_method("blend_event_camera"):
|
||||
cam.blend_event_camera(setting, blendtime)
|
||||
"RESTORE_CAMERA":
|
||||
if cam.has_method("set_default_camera"):
|
||||
cam.set_default_camera()
|
||||
|
||||
func _on_quest_fade_event(kind: String, speed: float) -> void:
|
||||
if ui == null:
|
||||
if quest_dialog and quest_dialog.has_method("end_event_process"):
|
||||
quest_dialog.end_event_process()
|
||||
return
|
||||
if _quest_fade_rect == null or not is_instance_valid(_quest_fade_rect):
|
||||
_quest_fade_rect = ColorRect.new()
|
||||
_quest_fade_rect.name = "QuestFade"
|
||||
_quest_fade_rect.set_anchors_preset(Control.PRESET_FULL_RECT)
|
||||
_quest_fade_rect.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||
_quest_fade_rect.z_index = 100
|
||||
ui.add_child(_quest_fade_rect)
|
||||
var white := kind.begins_with("WHITE_")
|
||||
_quest_fade_rect.color = Color(1, 1, 1, _quest_fade_rect.color.a) if white \
|
||||
else Color(0, 0, 0, _quest_fade_rect.color.a)
|
||||
var fade_in := kind.ends_with("_IN")
|
||||
var target_alpha := 0.0 if fade_in else 1.0
|
||||
_quest_fade_rect.visible = target_alpha > 0.0 or _quest_fade_rect.color.a > 0.001
|
||||
if _quest_fade_tween and _quest_fade_tween.is_valid():
|
||||
_quest_fade_tween.kill()
|
||||
# uiquest.py advances alpha by speed once per frame. At 60 FPS this is
|
||||
# equivalent to 1 / (speed * 60) seconds; malformed zero speeds use the
|
||||
# reference default to avoid permanently blocking the event set.
|
||||
var frame_speed := maxf(absf(speed), 0.035)
|
||||
var duration := absf(target_alpha - _quest_fade_rect.color.a) / (frame_speed * 60.0)
|
||||
_quest_fade_tween = create_tween()
|
||||
_quest_fade_tween.tween_property(_quest_fade_rect, "color:a", target_alpha, duration)
|
||||
_quest_fade_tween.tween_callback(func():
|
||||
_quest_fade_rect.visible = target_alpha > 0.0
|
||||
if quest_dialog and quest_dialog.has_method("end_event_process"):
|
||||
quest_dialog.end_event_process())
|
||||
|
||||
func _on_dungeon_result(result: Dictionary) -> void:
|
||||
if dungeon_result_ui and dungeon_result_ui.has_method("show_result"):
|
||||
dungeon_result_ui.show_result(result)
|
||||
|
||||
func _clear_quest_presentation() -> void:
|
||||
if _quest_fade_tween and _quest_fade_tween.is_valid():
|
||||
_quest_fade_tween.kill()
|
||||
_quest_fade_tween = null
|
||||
if _quest_fade_rect and is_instance_valid(_quest_fade_rect):
|
||||
_quest_fade_rect.color.a = 0.0
|
||||
_quest_fade_rect.visible = false
|
||||
if cam and cam.has_method("set_default_camera"):
|
||||
cam.set_default_camera()
|
||||
|
||||
func _screen_flash(secs: float) -> void:
|
||||
if hud == null:
|
||||
return
|
||||
@@ -661,6 +766,9 @@ func _on_world_reset() -> void:
|
||||
widget.call("_close")
|
||||
if atlas_ui and atlas_ui.has_method("close"):
|
||||
atlas_ui.close()
|
||||
if dungeon_result_ui and dungeon_result_ui.has_method("close"):
|
||||
dungeon_result_ui.close()
|
||||
_clear_quest_presentation()
|
||||
if ui and ui.has_method("close_top"):
|
||||
while ui.close_top():
|
||||
pass
|
||||
@@ -731,6 +839,12 @@ func _unhandled_input(e: InputEvent) -> void:
|
||||
if key == KEY_SHIFT:
|
||||
_quick_page_mode = e.pressed
|
||||
return
|
||||
# game.py SetPCTargetBoard :807 —— app.IsPressed(app.DIK_LCONTROL)。参考端在点 PC 的
|
||||
# 那一刻轮询 LCONTROL 按住态;poc 把按下 / 松开喂给 net_play,点 PC 时再查(seam ⑫)。
|
||||
if key == KEY_CTRL:
|
||||
if net_play and net_play.has_method("set_lcontrol_down"):
|
||||
net_play.set_lcontrol_down(e.pressed)
|
||||
return
|
||||
if not e.pressed:
|
||||
match key:
|
||||
KEY_SPACE:
|
||||
@@ -855,6 +969,12 @@ func _set_names(visible: bool) -> void:
|
||||
func _on_display_option(key: String, value: int) -> void:
|
||||
if key == "always_show_name" and net_world and net_world.has_method("set_always_show_name"):
|
||||
net_world.set_always_show_name(value == 1)
|
||||
elif key == "show_damage" and net_world and net_world.has_method("set_show_damage"):
|
||||
net_world.set_show_damage(value == 1)
|
||||
elif key == "name_color" and net_world and net_world.has_method("set_empire_name_mode"):
|
||||
net_world.set_empire_name_mode(value == 1)
|
||||
elif key == "target_board" and net_play and net_play.has_method("set_view_other_empire_target"):
|
||||
net_play.set_view_other_empire_target(value == 1)
|
||||
|
||||
func _send_command(text: String) -> void:
|
||||
if client and client.has_method("say"):
|
||||
|
||||
Reference in New Issue
Block a user