diff --git a/manager/config_manager/global_config.gd b/manager/config_manager/global_config.gd index 9fb472ee..4b8fa777 100644 --- a/manager/config_manager/global_config.gd +++ b/manager/config_manager/global_config.gd @@ -1,6 +1,7 @@ class_name GlobalConfig extends Resource static var DEBUG = false +const DEBUG_CHARACTER_PREFIX = "[debug]" # .res would be binary encoded, .tres is text encoded const RES_FILE_FORMAT = ".tres" diff --git a/manager/scene/scene_manager.gd b/manager/scene/scene_manager.gd index e98b0858..751800de 100644 --- a/manager/scene/scene_manager.gd +++ b/manager/scene/scene_manager.gd @@ -148,7 +148,7 @@ func pop_debug_dialog_info(character: String, content: String) -> void: debug_balloon_node.queue_free() var title = "title" var body = "~ " + title + "\n" - body += character + ": " + content + "\n" + body += GlobalConfig.DEBUG_CHARACTER_PREFIX + character + ": " + content + "\n" body += "=> END" var res = DialogueManager.create_resource_from_text(body) debug_balloon_node = DialogueManager.show_dialogue_balloon_scene( diff --git a/scene/entity/npc.gd b/scene/entity/npc.gd index ff40e767..cef20ba9 100644 --- a/scene/entity/npc.gd +++ b/scene/entity/npc.gd @@ -44,6 +44,10 @@ enum SpeakingSignMode { HIDDEN = 0, SILENT = 1, SPEAKING = 2 } if is_node_ready(): _update_collision_shape() +# DialogueLine 播放 hook_character_name 的对话时,显示 speaking 标志 +# 为空时不 hook +@export var hook_character_name := "" + # 节点引用 @onready var speaking_animation = %SpeakingAnimationPlayer @onready var speaking_sign = %SpeakingSign2D as Node2D @@ -89,6 +93,34 @@ func _ready() -> void: _setup_game_mode() _align_signs_status() + DialogueManager.dialogue_ended.connect(_on_dialogue_ended) + DialogueManager.got_dialogue.connect(_on_got_dialogue) + +var _last_line_session := -1 + +func _on_got_dialogue(line: DialogueLine) -> void: + if not hook_character_name: + return + # 去除 debug + if line.character.begins_with(GlobalConfig.DEBUG_CHARACTER_PREFIX): + return + # 其他角色说话时会自动停止 + if line.character == hook_character_name: + # 未在 speaking 状态 + if _last_line_session < 0: + _last_line_session = hook_speaking() + if GlobalConfig.DEBUG: + print("[Npc2D] Hook speaking for character: ", hook_character_name, " line.character:", line.character) + elif _last_line_session >= 0: + if GlobalConfig.DEBUG: + print("[Npc2D] Unhook speaking for character: ", hook_character_name, " line.character:", line.character) + unhook_speaking(_last_line_session) + _last_line_session = -1 + + +# dialog 结束时会自动 unhook 从 line 播放的 speaking +func _on_dialogue_ended(_res) -> void: + unhook_speaking(_last_line_session) func _initialize_components() -> void: @@ -214,6 +246,9 @@ func _on_visibility_changed() -> void: func _align_signs_status() -> void: if not is_node_ready(): return + if Engine.is_editor_hint(): + _setup_editor_preview() + return var is_active = enabled and is_visible_in_tree() if sign_mark: sign_mark.enabled = is_active @@ -281,7 +316,7 @@ func hook_speaking() -> int: func unhook_speaking(session_id: int = -1) -> void: # 退出强制播放模式 # 参数: - # session_id: hook会话ID,如果不匹配则忽略此次unhook + # session_id: hook会话ID,如果不匹配则忽略此次unhook # 如果已经不在hook状态,或session_id不匹配,则忽略 if not is_hooked or (session_id != -1 and session_id != hook_id): return @@ -305,7 +340,7 @@ func _cancel_hook() -> void: # 新增:检查是否正在hook播放 func is_hook_speaking() -> bool: - """返回当前是否处于强制播放状态""" + # 返回当前是否处于强制播放状态 return is_hooked diff --git a/scene/ground/scene/c01/s06_孤儿院长廊围墙.gd b/scene/ground/scene/c01/s06_孤儿院长廊围墙.gd index 5e5170de..290166a0 100644 --- a/scene/ground/scene/c01/s06_孤儿院长廊围墙.gd +++ b/scene/ground/scene/c01/s06_孤儿院长廊围墙.gd @@ -94,10 +94,8 @@ func pre_game_intro(): var p = $"../DeployLayer/四小孩画鬼差的对话ambush/FocusPoint" camera.focus_node(p, 3.0) await Util.wait(2.0) - _hook_npc3_speaking() DialogueManager.show_dialogue_balloon(dialogue_c01, "c01_s06_四个小孩画鬼差的对话") await DialogueManager.dialogue_ended - _unhook_npc3_speaking() # 重置镜头 SceneManager.focus_player_and_reset_zoom(2.5) await Util.wait(2.5) @@ -120,25 +118,28 @@ func game_intro() -> void: # 只有 1、2 是跟班,3 不参与 # standing_kid3.play("【站立小孩-3】转身") game_kid.play("【胖小孩背着残疾小孩】侧面呼吸") + # 转身后,大胖 speaking sign 也跟随过去 + game_kid.get_node("Npc大胖").position.x += 18 + game_kid.get_node("Npc对话3").position.x -= 5 SceneManager.get_player().set_facing_direction(Vector2.LEFT) SceneManager.freeze_player(0) # DialogueManager.show_dialogue_balloon( # dialogue_c01, "c01_s06_谈论鬼差与猫鼠游戏", [GlobalConfig.DIALOG_IGNORE_INPUT] # ) - _hook_npc3_speaking() DialogueManager.show_dialogue_balloon(dialogue_c01, "c01_s06_谈论鬼差与猫鼠游戏") await DialogueManager.dialogue_ended - _game_counting_down() - - -func _game_counting_down(_res = null): + # BGM 开始后小段对话 $"Sfx猫鼠游戏".play() DialogueManager.show_dialogue_balloon(dialogue_c01, "c01_s06_猫鼠游戏BGM开始") await DialogueManager.dialogue_ended - _unhook_npc3_speaking() # 重置镜头 SceneManager.focus_player_and_reset_zoom(2.5) SceneManager.release_player() + # 倒计时开始,无需展示 hook speaking 气泡 + game_kid.get_node("Npc对话3").hook_character_name = "" + game_kid.get_node("Npc对话3").unhook_speaking() + game_kid.get_node("Npc大胖").hook_character_name = "" + game_kid.get_node("Npc大胖").unhook_speaking() DialogueManager.show_dialogue_balloon(dialogue_c01, "c01_s06_猫鼠游戏倒计时") # 禁止玩家向左移动,同时可以使右侧腾出空间,玩家可以继续向右移动 var player = SceneManager.get_player() as MainPlayer @@ -150,14 +151,6 @@ func _game_counting_down(_res = null): cat.get_node("猫咪嘶吼音效").play() -func _hook_npc3_speaking(_res = null) -> void: - game_kid.get_node("Npc对话3").hook_speaking() - - -func _unhook_npc3_speaking(_res = null) -> void: - game_kid.get_node("Npc对话3").unhook_speaking() - - # 玩家与三个小孩的互动计数 func _on_talked(id: int): #talk count diff --git a/scene/ground/scene/c01/s06_孤儿院长廊围墙.tscn b/scene/ground/scene/c01/s06_孤儿院长廊围墙.tscn index 051e9ec1..f89a1509 100644 --- a/scene/ground/scene/c01/s06_孤儿院长廊围墙.tscn +++ b/scene/ground/scene/c01/s06_孤儿院长廊围墙.tscn @@ -448,6 +448,7 @@ shape = SubResource("RectangleShape2D_7cdhx") [node name="Npc对话1" parent="Ground/DeployLayer/【站立小孩-1】" instance=ExtResource("24_phfqg")] position = Vector2(0, 71) speaking_sign_height = 39.23 +hook_character_name = "小肉圆" dialogue_title = "c01_s06_四个小孩_对话1" [node name="【站立小孩-2】" parent="Ground/DeployLayer" index="15" instance=ExtResource("8_ouldg")] @@ -511,6 +512,7 @@ shape = SubResource("RectangleShape2D_7cdhx") [node name="Npc对话2" parent="Ground/DeployLayer/【站立小孩-2】" instance=ExtResource("24_phfqg")] position = Vector2(2, 52) speaking_sign_height = 34.95 +hook_character_name = "小竹竿" dialogue_title = "c01_s06_四个小孩_对话2" [node name="【墙上黑猫】" parent="Ground/DeployLayer" index="16" instance=ExtResource("8_ouldg")] @@ -631,10 +633,17 @@ enabled = false shape = SubResource("RectangleShape2D_7cdhx") [node name="Npc对话3" parent="Ground/DeployLayer/【胖小孩背着残疾小孩】" instance=ExtResource("24_phfqg")] -position = Vector2(3, 53) +position = Vector2(4, 53) speaking_sign_height = 39.23 +hook_character_name = "孩子王" dialogue_title = "c01_s06_四个小孩_对话3" +[node name="Npc大胖" parent="Ground/DeployLayer/【胖小孩背着残疾小孩】" instance=ExtResource("24_phfqg")] +position = Vector2(-6, 63) +enabled = false +speaking_sign_height = 38.52 +hook_character_name = "大胖" + [node name="猫鼠游戏胜利ambush" parent="Ground/DeployLayer" index="19" instance=ExtResource("11_tudob")] position = Vector2(4546, 45) one_shot = false diff --git a/scene/ground/scene/c01/s07_书店外.gd b/scene/ground/scene/c01/s07_书店外.gd index 47d7650a..ac12f789 100644 --- a/scene/ground/scene/c01/s07_书店外.gd +++ b/scene/ground/scene/c01/s07_书店外.gd @@ -101,10 +101,6 @@ func jiandu_dialog_triggered() -> void: var jiandu = $"../DeployLayer/举碗小孩/Npc监督小孩" jiandu.hook_speaking() SceneManager.hold_player() - DialogueManager.dialogue_ended.connect(_on_jiandu_dialog_ended, CONNECT_ONE_SHOT) - - -func _on_jiandu_dialog_ended(_res) -> void: - var jiandu = $"../DeployLayer/举碗小孩/Npc监督小孩" - jiandu.unhook_speaking() + await DialogueManager.dialogue_ended SceneManager.unhold_player() + jiandu.unhook_speaking()