Compare commits
3 Commits
9c3c470f3e
...
3be55f41e7
Author | SHA1 | Date | |
---|---|---|---|
3be55f41e7 | |||
4063434c26 | |||
70f9d35d07 |
@ -114,19 +114,20 @@ c01_s08_书店工钱,这个月的工钱还没拿。,,,,,I haven't collected this
|
||||
mem_偷听对话,偷听对话,,,,,Eavesdropping
|
||||
mem_疯子看井,疯子看井,,,,,Madman Guards Well
|
||||
c01_鸡毛掸子,这是鸡毛掸子吗?,,,,,Is this a feather duster?
|
||||
c01_院长书桌,桌上放着一本《圣经》。{br}「得著生命的,將要失喪生命...」,,,,,There's a Bible on the desk.{br}'Whoever finds their life will lose it...'
|
||||
c01_院长书桌,桌上放着一本《圣经》。{br}「凡要救自己生命的,必丧掉生命...」,,,,,"There's a Bible on the table.{br}'Whoever wants to save their life will lose it, but whoever loses their life for me will find it...'"
|
||||
c01_院长床,这本书已经看过了。{br}...那些句子是什么意思呢?,,,,,I've already read this book.{br}...What do those sentences mean?
|
||||
c01_院长座钟,这西洋钟没坏的时候,走针会咔哒、咔哒地响...{br}停在未时一刻不动了。,,,,,"When this Western clock wasn't broken, the hands would tick and tock...{br}It's stopped at a quarter past one in the afternoon."
|
||||
c01_院长座钟,咦?这西洋钟为什么倒着走?,,,,,Huh? Why is this Western clock running backwards?
|
||||
c01_倾斜的洋相片,哇啊,这张洋相片要掉下来了!{br}我得做点什么...,,,,,"Oh no, this Western photograph is about to fall!{br}I need to do something..."
|
||||
c01_摆正的洋相片,这是院长的儿子吗?,,,,,Is this the director's son?
|
||||
c01_s06_院长房间,这是院长的房间,,,,,This is the director's room
|
||||
c01_s06_小朋友房间,这是其他小朋友的房间,,,,,This is the other children's room
|
||||
c01_s06_熟悉的墙画,墙上的画看起来好熟悉。{br}过去问问看吧,没准他们几个知道些什么。,,,,,The painting on the wall looks so familiar.{br}Let me go ask them. Maybe they know something.
|
||||
c01_s06_四小孩对话结束,怪人、花、门...{br}他在找什么东西,或是什么人?,,,,,"Strange man, flowers, door...{br}What is he looking for, or who?"
|
||||
c01_s06_四小孩对话结束,怪人、花...{br}有时候真搞不懂他们在说些什么。,,,,,"Strange people, flowers...{br}Sometimes I really don't understand what they're talking about."
|
||||
c01_s07_钱碗,碗里只有一枚铜钱。,,,,,There's only one copper coin in the bowl.
|
||||
c01_s07_获得报纸,这是什么?,,,,,What is this?
|
||||
c01_s07_书店展柜,院长说,读一百本书,就可以成为无所不能的大人。{br}如果我再大一些,没准可以求店长把我留下,我会干很多活,也能吃苦...,,,,,"The director said that reading a hundred books would make me an all-capable adult.{br}If I were a bit older, maybe I could ask the shop owner to keep me. I'd work hard and endure hardship..."
|
||||
c01_s08_书架游戏完成,这些书都被老鼠啃坏了,连木头架子都没放过。,,,,,"These books have all been gnawed by mice, even the wooden shelves weren't spared."
|
||||
c01_s08_书架游戏完成,?!{br}刚才那是什么?,,,,,?!{br}What was that just now?
|
||||
c01_s08_书架游戏恢复记忆,...{br}这是...我之前工作的地方。{br}...{br}现在老板不在了,我也该走了...,,,,,"...{br}This is... where I used to work.{br}...{br}Now that the boss is gone, I should leave too..."
|
||||
c01_s08_获得袁大头后,工钱还在老地方。,,,,,The wages are still in the usual place.
|
||||
c02_海报_剪辫子侦探,剪辫悬梁上侦探奇闻,,,,,Detective Tales of the Queue-Cutting Mystery
|
||||
c02_海报_戏法班,朱连魁全班戏法——「各有幻女...演技新奇」,,,,,Zhu Liankui's Magic Troupe—'Each with enchanting women... performances most novel'
|
||||
|
|
@ -168,9 +168,9 @@
|
||||
~ Notes_c01
|
||||
# c01-s05 院长房间
|
||||
这是鸡毛掸子吗? [ID:c01_鸡毛掸子]
|
||||
桌上放着一本《圣经》。{br}「得著生命的,將要失喪生命...」 [ID:c01_院长书桌]
|
||||
桌上放着一本《圣经》。{br}「凡要救自己生命的,必丧掉生命...」 [ID:c01_院长书桌]
|
||||
这本书已经看过了。{br}...那些句子是什么意思呢? [ID:c01_院长床]
|
||||
这西洋钟没坏的时候,走针会咔哒、咔哒地响...{br}停在未时一刻不动了。 [ID:c01_院长座钟]
|
||||
咦?这西洋钟为什么倒着走? [ID:c01_院长座钟]
|
||||
哇啊,这张洋相片要掉下来了!{br}我得做点什么... [ID:c01_倾斜的洋相片]
|
||||
这是院长的儿子吗? [ID:c01_摆正的洋相片]
|
||||
# c01-s06 院子
|
||||
@ -178,13 +178,14 @@
|
||||
这是其他小朋友的房间 [ID:c01_s06_小朋友房间]
|
||||
# 院子里四个小孩交谈结束后
|
||||
墙上的画看起来好熟悉。{br}过去问问看吧,没准他们几个知道些什么。 [ID:c01_s06_熟悉的墙画]
|
||||
怪人、花、门...{br}他在找什么东西,或是什么人? [ID:c01_s06_四小孩对话结束]
|
||||
怪人、花...{br}有时候真搞不懂他们在说些什么。 [ID:c01_s06_四小孩对话结束]
|
||||
# c01-s07 书店外
|
||||
碗里只有一枚铜钱。 [ID:c01_s07_钱碗]
|
||||
这是什么? [ID:c01_s07_获得报纸]
|
||||
院长说,读一百本书,就可以成为无所不能的大人。{br}如果我再大一些,没准可以求店长把我留下,我会干很多活,也能吃苦... [ID:c01_s07_书店展柜]
|
||||
# c01-s08 书店
|
||||
这些书都被老鼠啃坏了,连木头架子都没放过。 [ID:c01_s08_书架游戏完成]
|
||||
?!{br}刚才那是什么? [ID:c01_s08_书架游戏完成]
|
||||
...{br}这是...我之前工作的地方。{br}...{br}现在老板不在了,我也该走了... [ID:c01_s08_书架游戏恢复记忆]
|
||||
工钱还在老地方。 [ID:c01_s08_获得袁大头后]
|
||||
=> END
|
||||
|
||||
|
@ -13,10 +13,11 @@ const RES_FILE_FORMAT = ".tres"
|
||||
const CANVAS_LAYER_SETTINGS = 30
|
||||
# note
|
||||
const CANVAS_LAYER_NOTE = 25
|
||||
# dialog
|
||||
const CANVAS_LAYER_DIALOG = 24
|
||||
const CANVAS_LAYER_MEM_ITEM = 23
|
||||
const CANVAS_LAYER_UX_PANEL = 22
|
||||
# dialog
|
||||
const CANVAS_LAYER_DIALOG_MEM = 30
|
||||
const CANVAS_LAYER_DIALOG = 22
|
||||
# main 场景的 UI 层(prop hud、上下mask、notification)
|
||||
const CANVAS_LAYER_UI = 21
|
||||
# 道具 inspector(prop/local)
|
||||
@ -33,6 +34,8 @@ const CANVAS_LAYER_LITTLE_GAME = 5
|
||||
const CANVAS_LAYER_FG = 2
|
||||
|
||||
const DIALOG_IGNORE_INPUT = "ignore_input"
|
||||
# memory layer: 30
|
||||
const DIALOG_MEM_LAYER = "mem_layer"
|
||||
|
||||
const CHARACTER_COLOR_MAP = {
|
||||
"default": Color.LIGHT_SEA_GREEN,
|
||||
|
@ -153,6 +153,8 @@ func _notification(what: int) -> void:
|
||||
func start(
|
||||
dialogue_resource: DialogueResource, title: String, extra_game_states: Array = []
|
||||
) -> void:
|
||||
if extra_game_states.has(GlobalConfig.DIALOG_MEM_LAYER):
|
||||
pass
|
||||
temporary_game_states = [self] + extra_game_states
|
||||
is_waiting_for_input = false
|
||||
resource = dialogue_resource
|
||||
|
@ -10,7 +10,7 @@ func _ready() -> void:
|
||||
var tween: Tween
|
||||
|
||||
|
||||
func dizzy(duration := 3.5, intensity := 1.5):
|
||||
func dizzy(duration := 3.5, intensity := 1.5) -> void:
|
||||
if duration < 0.6:
|
||||
return
|
||||
if tween and tween.is_valid():
|
||||
|
@ -2,10 +2,15 @@
|
||||
class_name Npc2D extends AnimatedSprite2D
|
||||
|
||||
signal interacted
|
||||
# 在 unlock player 之前发射
|
||||
signal talk_finished
|
||||
signal talk_finished # 在 unlock player 之前发射
|
||||
|
||||
# <0 means no walk to edge
|
||||
# 常量定义
|
||||
const SPEAKING_SIGN_FADE_DURATION := 0.3
|
||||
const SPEAKING_SCALE_MULTIPLIER := 1.3
|
||||
|
||||
enum SpeakingSignMode { HIDDEN = 0, SILENT = 1, SPEAKING = 2 }
|
||||
|
||||
# 导出变量
|
||||
@export var snap_to_edge := true
|
||||
@export var walk_to_edge_width := 25.0
|
||||
@export var action_key := 4
|
||||
@ -14,41 +19,47 @@ signal talk_finished
|
||||
enabled = val
|
||||
if is_node_ready():
|
||||
_align_signs_status()
|
||||
|
||||
@export var sign_mark_height := 10.0:
|
||||
set(val):
|
||||
sign_mark_height = val
|
||||
if is_node_ready():
|
||||
if is_node_ready() and sign_mark:
|
||||
sign_mark.sign_mark_offset.y = -sign_mark_height
|
||||
|
||||
@export var speaking_sign_height := 60.0:
|
||||
set(val):
|
||||
speaking_sign_height = val
|
||||
if is_node_ready():
|
||||
if is_node_ready() and speaking_sign:
|
||||
speaking_sign.position.y = -speaking_sign_height
|
||||
|
||||
@export var sign_x_offset := 0.0:
|
||||
set(val):
|
||||
sign_x_offset = val
|
||||
if is_node_ready():
|
||||
speaking_sign.position.x = sign_x_offset
|
||||
sign_mark.position.x = sign_x_offset
|
||||
_update_sign_x_positions()
|
||||
|
||||
@export var collision_width_and_x := Vector2(20.0, 0):
|
||||
set(val):
|
||||
collision_width_and_x = val
|
||||
if is_node_ready():
|
||||
var shape = area2d.get_node("CollisionShape2D").shape
|
||||
shape.size.x = collision_width_and_x.x
|
||||
area2d.position.x = collision_width_and_x.y
|
||||
_update_collision_shape()
|
||||
|
||||
# 节点引用
|
||||
@onready var speaking_animation = %SpeakingAnimationPlayer
|
||||
@onready var speaking_sign = %SpeakingSign2D as Node2D
|
||||
@onready var sign_mark = %Sign as Sign
|
||||
@onready var sign_snapper = %SignSnapper as SignSnapper
|
||||
@onready var area2d = %Area2D as Area2D
|
||||
|
||||
# 内部变量
|
||||
var ground_archive: GroundArchive
|
||||
# 尝试互动的次数
|
||||
var icount: int:
|
||||
set(val):
|
||||
if icount == val:
|
||||
return
|
||||
icount = val
|
||||
ground_archive.set_pair(name, "icount", val)
|
||||
if ground_archive:
|
||||
ground_archive.set_pair(name, "icount", val)
|
||||
_align_signs_status()
|
||||
|
||||
var dialogue_title := ""
|
||||
@ -56,105 +67,246 @@ var dialogue_res = preload("res://asset/dialogue/npc.dialogue")
|
||||
|
||||
var base_scale := Vector2.ONE
|
||||
var base_mod := Color.WHITE_SMOKE
|
||||
|
||||
var speaking_sign_tween: Tween
|
||||
|
||||
# 0 hide; 1 silent; 2 speaking
|
||||
var speaking_sign_mode := 0:
|
||||
var speaking_sign_mode := SpeakingSignMode.HIDDEN:
|
||||
set(val):
|
||||
if speaking_sign_mode != val:
|
||||
speaking_sign_mode = val
|
||||
if speaking_sign_tween and speaking_sign_tween.is_valid():
|
||||
speaking_sign_tween.kill()
|
||||
speaking_sign_tween = create_tween()
|
||||
if val == 0:
|
||||
speaking_sign_tween.tween_property(speaking_sign, "modulate:a", 0.0, 0.3)
|
||||
speaking_animation.stop()
|
||||
elif val == 1:
|
||||
speaking_sign_tween.tween_property(speaking_sign, "modulate", base_mod, 0.3)
|
||||
speaking_sign_tween.parallel().tween_property(
|
||||
speaking_sign, "scale", base_scale, 0.3
|
||||
)
|
||||
speaking_animation.play("speaking")
|
||||
elif val == 2:
|
||||
speaking_sign_tween.tween_property(speaking_sign, "modulate", Color.WHITE, 0.3)
|
||||
speaking_sign_tween.parallel().tween_property(
|
||||
speaking_sign, "scale", base_scale * 1.3, 0.3
|
||||
)
|
||||
speaking_animation.play("speaking")
|
||||
if speaking_sign_mode == val:
|
||||
return
|
||||
speaking_sign_mode = val
|
||||
_update_speaking_sign_mode()
|
||||
|
||||
# 强制播放状态管理
|
||||
var is_hooked := false
|
||||
var hook_id := 0 # 用于追踪hook会话,避免异步问题
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
# sign position
|
||||
sign_mark.sign_mark_offset.y = -sign_mark_height
|
||||
speaking_sign.position.y = -speaking_sign_height
|
||||
sign_mark.position.x = sign_x_offset
|
||||
speaking_sign.position.x = sign_x_offset
|
||||
# collisiong shape
|
||||
var shape = area2d.get_node("CollisionShape2D").shape
|
||||
shape.size.x = collision_width_and_x.x
|
||||
area2d.position.x = collision_width_and_x.y
|
||||
sign_snapper.action_on_arrived = action_key
|
||||
sign_snapper.radius = walk_to_edge_width
|
||||
sign_snapper.enabled = snap_to_edge
|
||||
# 设置 speaking_sign 默认值
|
||||
base_scale = speaking_sign.scale
|
||||
base_mod = speaking_sign.modulate
|
||||
speaking_sign.modulate.a = 0.0
|
||||
_initialize_components()
|
||||
|
||||
if Engine.is_editor_hint():
|
||||
# editor 下都显示
|
||||
_setup_editor_preview()
|
||||
return
|
||||
|
||||
_setup_game_mode()
|
||||
_align_signs_status()
|
||||
|
||||
|
||||
func _initialize_components() -> void:
|
||||
# 设置标记位置
|
||||
if sign_mark:
|
||||
sign_mark.sign_mark_offset.y = -sign_mark_height
|
||||
sign_mark.position.x = sign_x_offset
|
||||
|
||||
if speaking_sign:
|
||||
speaking_sign.position.y = -speaking_sign_height
|
||||
speaking_sign.position.x = sign_x_offset
|
||||
base_scale = speaking_sign.scale
|
||||
base_mod = speaking_sign.modulate
|
||||
speaking_sign.modulate.a = 0.0
|
||||
|
||||
# 设置碰撞形状
|
||||
_update_collision_shape()
|
||||
|
||||
# 配置 sign_snapper
|
||||
if sign_snapper:
|
||||
sign_snapper.action_on_arrived = action_key
|
||||
sign_snapper.radius = walk_to_edge_width
|
||||
sign_snapper.enabled = snap_to_edge
|
||||
|
||||
|
||||
func _setup_editor_preview() -> void:
|
||||
if speaking_sign:
|
||||
speaking_sign.visible = true
|
||||
speaking_sign.modulate.a = 1.0
|
||||
speaking_sign.get_node("Sprite2D").position.x = -60.0
|
||||
speaking_sign.get_node("Sprite2D").frame = 2
|
||||
var sprite = speaking_sign.get_node_or_null("Sprite2D")
|
||||
if sprite:
|
||||
sprite.position.x = -60.0
|
||||
sprite.frame = 2
|
||||
|
||||
if sign_mark:
|
||||
sign_mark.display_sign = true
|
||||
return
|
||||
# setup default value
|
||||
|
||||
|
||||
func _setup_game_mode() -> void:
|
||||
# 获取存档数据
|
||||
ground_archive = ArchiveManager.archive.ground_archive()
|
||||
icount = ground_archive.get_value(name, "icount", 0)
|
||||
if snap_to_edge:
|
||||
|
||||
# 连接信号
|
||||
if snap_to_edge and sign_snapper:
|
||||
sign_snapper.arrived.connect(_on_interacted)
|
||||
else:
|
||||
elif sign_mark:
|
||||
sign_mark.interacted.connect(_on_interacted)
|
||||
# sign_mark.cancel.connect(_stop_speaking)
|
||||
sign_mark.toggle_active.connect(_on_toggle_active)
|
||||
|
||||
if sign_mark:
|
||||
sign_mark.toggle_active.connect(_on_toggle_active)
|
||||
|
||||
visibility_changed.connect(_on_visibility_changed)
|
||||
|
||||
# 开始动画
|
||||
if sprite_frames and animation:
|
||||
play()
|
||||
|
||||
|
||||
func _update_sign_x_positions() -> void:
|
||||
if speaking_sign:
|
||||
speaking_sign.position.x = sign_x_offset
|
||||
if sign_mark:
|
||||
sign_mark.position.x = sign_x_offset
|
||||
|
||||
|
||||
func _update_collision_shape() -> void:
|
||||
if not area2d:
|
||||
return
|
||||
|
||||
var collision_shape = area2d.get_node_or_null("CollisionShape2D")
|
||||
if collision_shape and collision_shape.shape:
|
||||
collision_shape.shape.size.x = collision_width_and_x.x
|
||||
area2d.position.x = collision_width_and_x.y
|
||||
|
||||
|
||||
func _update_speaking_sign_mode() -> void:
|
||||
if not speaking_sign:
|
||||
return
|
||||
|
||||
# 清理之前的补间动画
|
||||
if speaking_sign_tween and speaking_sign_tween.is_valid():
|
||||
speaking_sign_tween.kill()
|
||||
|
||||
speaking_sign_tween = create_tween()
|
||||
|
||||
match speaking_sign_mode:
|
||||
SpeakingSignMode.HIDDEN:
|
||||
speaking_sign_tween.tween_property(
|
||||
speaking_sign, "modulate:a", 0.0, SPEAKING_SIGN_FADE_DURATION
|
||||
)
|
||||
if speaking_animation:
|
||||
speaking_animation.stop()
|
||||
|
||||
SpeakingSignMode.SILENT:
|
||||
speaking_sign_tween.tween_property(
|
||||
speaking_sign, "modulate", base_mod, SPEAKING_SIGN_FADE_DURATION
|
||||
)
|
||||
speaking_sign_tween.parallel().tween_property(
|
||||
speaking_sign, "scale", base_scale, SPEAKING_SIGN_FADE_DURATION
|
||||
)
|
||||
if speaking_animation:
|
||||
speaking_animation.play("speaking")
|
||||
|
||||
SpeakingSignMode.SPEAKING:
|
||||
speaking_sign_tween.tween_property(
|
||||
speaking_sign, "modulate", Color.WHITE, SPEAKING_SIGN_FADE_DURATION
|
||||
)
|
||||
speaking_sign_tween.parallel().tween_property(
|
||||
speaking_sign,
|
||||
"scale",
|
||||
base_scale * SPEAKING_SCALE_MULTIPLIER,
|
||||
SPEAKING_SIGN_FADE_DURATION
|
||||
)
|
||||
if speaking_animation:
|
||||
speaking_animation.play("speaking")
|
||||
|
||||
|
||||
func _on_visibility_changed() -> void:
|
||||
_align_signs_status()
|
||||
|
||||
|
||||
func _align_signs_status():
|
||||
sign_mark.enabled = enabled and is_visible_in_tree()
|
||||
sign_mark.display_sign = icount == 0
|
||||
speaking_sign.visible = enabled and icount > 0
|
||||
func _align_signs_status() -> void:
|
||||
if not is_node_ready():
|
||||
return
|
||||
var is_active = enabled and is_visible_in_tree()
|
||||
if sign_mark:
|
||||
sign_mark.enabled = is_active
|
||||
sign_mark.display_sign = icount == 0
|
||||
if speaking_sign:
|
||||
speaking_sign.visible = enabled and (icount > 0 or is_hooked)
|
||||
|
||||
|
||||
func _on_toggle_active(activated: bool) -> void:
|
||||
# 如果处于hook状态,不响应正常的toggle
|
||||
if is_hooked:
|
||||
return
|
||||
if not activated:
|
||||
speaking_sign_mode = 0
|
||||
elif speaking_sign_mode == 0:
|
||||
speaking_sign_mode = 1
|
||||
speaking_sign_mode = SpeakingSignMode.HIDDEN
|
||||
elif speaking_sign_mode == SpeakingSignMode.HIDDEN:
|
||||
speaking_sign_mode = SpeakingSignMode.SILENT
|
||||
|
||||
|
||||
func _on_interacted() -> void:
|
||||
# play dialogue
|
||||
if dialogue_title:
|
||||
SceneManager.lock_player(0, action_key)
|
||||
icount += 1
|
||||
if not dialogue_title:
|
||||
return
|
||||
|
||||
# 如果正在hook播放,先取消hook
|
||||
if is_hooked:
|
||||
_cancel_hook()
|
||||
|
||||
SceneManager.lock_player(0, action_key)
|
||||
icount += 1
|
||||
|
||||
if ground_archive:
|
||||
ground_archive.set_pair(name, "icount", icount)
|
||||
DialogueManager.show_dialogue_balloon(dialogue_res, dialogue_title)
|
||||
interacted.emit()
|
||||
var out_of_range = speaking_sign_mode == 0
|
||||
speaking_sign_mode = 2
|
||||
await DialogueManager.dialogue_ended
|
||||
speaking_sign_mode = 0 if out_of_range else 1
|
||||
# 在 unlock 之前发射
|
||||
talk_finished.emit()
|
||||
SceneManager.unlock_player()
|
||||
|
||||
DialogueManager.show_dialogue_balloon(dialogue_res, dialogue_title)
|
||||
interacted.emit()
|
||||
|
||||
var was_out_of_range = speaking_sign_mode == SpeakingSignMode.HIDDEN
|
||||
speaking_sign_mode = SpeakingSignMode.SPEAKING
|
||||
|
||||
await DialogueManager.dialogue_ended
|
||||
|
||||
speaking_sign_mode = SpeakingSignMode.HIDDEN if was_out_of_range else SpeakingSignMode.SILENT
|
||||
talk_finished.emit()
|
||||
SceneManager.unlock_player()
|
||||
|
||||
|
||||
# 新增:强制播放说话动画
|
||||
func hook_speaking() -> int:
|
||||
# 强制显示说话气泡动画
|
||||
# 返回值:hook会话ID,用于验证unhook的有效性
|
||||
is_hooked = true
|
||||
hook_id += 1
|
||||
var current_hook_id = hook_id
|
||||
|
||||
# 确保speaking_sign可见
|
||||
if speaking_sign and not speaking_sign.visible:
|
||||
speaking_sign.visible = true
|
||||
|
||||
# 保存当前状态并切换到说话模式
|
||||
speaking_sign_mode = SpeakingSignMode.SPEAKING
|
||||
|
||||
return current_hook_id
|
||||
|
||||
|
||||
# 新增:退出强制播放
|
||||
func unhook_speaking(session_id: int = -1) -> void:
|
||||
# 退出强制播放模式
|
||||
# 参数:
|
||||
# session_id: hook会话ID,如果不匹配则忽略此次unhook
|
||||
# 如果已经不在hook状态,或session_id不匹配,则忽略
|
||||
if not is_hooked or (session_id != -1 and session_id != hook_id):
|
||||
return
|
||||
_cancel_hook()
|
||||
|
||||
|
||||
# 新增:内部取消hook的方法
|
||||
func _cancel_hook() -> void:
|
||||
# 内部使用的取消hook方法
|
||||
is_hooked = false
|
||||
|
||||
# 恢复到适当的状态
|
||||
if sign_mark and sign_mark.activated:
|
||||
speaking_sign_mode = SpeakingSignMode.SILENT
|
||||
else:
|
||||
speaking_sign_mode = SpeakingSignMode.HIDDEN
|
||||
|
||||
# 重新对齐显示状态
|
||||
_align_signs_status()
|
||||
|
||||
|
||||
# 新增:检查是否正在hook播放
|
||||
func is_hook_speaking() -> bool:
|
||||
"""返回当前是否处于强制播放状态"""
|
||||
return is_hooked
|
||||
|
||||
|
||||
func _get(property: StringName) -> Variant:
|
||||
@ -172,8 +324,9 @@ func _set(property: StringName, value: Variant) -> bool:
|
||||
|
||||
func _get_property_list() -> Array[Dictionary]:
|
||||
var hint_str = ""
|
||||
if Engine.is_editor_hint():
|
||||
if Engine.is_editor_hint() and dialogue_res:
|
||||
hint_str = ",".join(dialogue_res.get_ordered_titles())
|
||||
|
||||
return [
|
||||
{
|
||||
"name": "dialogue_title",
|
||||
|
@ -94,8 +94,10 @@ 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)
|
||||
@ -123,14 +125,17 @@ func game_intro() -> void:
|
||||
# DialogueManager.show_dialogue_balloon(
|
||||
# dialogue_c01, "c01_s06_谈论鬼差与猫鼠游戏", [GlobalConfig.DIALOG_IGNORE_INPUT]
|
||||
# )
|
||||
_hook_npc3_speaking()
|
||||
DialogueManager.show_dialogue_balloon(dialogue_c01, "c01_s06_谈论鬼差与猫鼠游戏")
|
||||
DialogueManager.dialogue_ended.connect(_game_counting_down, CONNECT_ONE_SHOT)
|
||||
await DialogueManager.dialogue_ended
|
||||
_game_counting_down()
|
||||
|
||||
|
||||
func _game_counting_down(_res = null):
|
||||
$"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()
|
||||
@ -145,6 +150,14 @@ 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
|
||||
|
@ -71,7 +71,7 @@ func _knock_door():
|
||||
await Util.wait(2.2)
|
||||
$"敲门音效".play()
|
||||
await Util.wait(1.2)
|
||||
var stream = preload("res://asset/audio/sfx/交互/序章/03_书店外黄昏_开门.ogg")
|
||||
var stream = preload("uid://ehgd455wq8to")
|
||||
AudioManager.play_sfx(stream)
|
||||
|
||||
|
||||
@ -95,3 +95,14 @@ func seller_interacted():
|
||||
# 播放获得动画
|
||||
SceneManager.enable_prop_item("prop_信碎片2")
|
||||
SceneManager.release_player()
|
||||
|
||||
|
||||
func jiandu_dialog_triggered() -> void:
|
||||
var jiandu = $"../DeployLayer/举碗小孩/Npc监督小孩"
|
||||
jiandu.hook_speaking()
|
||||
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()
|
||||
|
@ -203,12 +203,6 @@ sprite_frames = ExtResource("6_thm8f")
|
||||
animation = &"杂戏团黄昏-其余小孩"
|
||||
autoplay = "杂戏团黄昏-其余小孩"
|
||||
|
||||
[node name="Ambush监督小孩" parent="Ground/DeployLayer/其余小孩" instance=ExtResource("9_f61dl")]
|
||||
position = Vector2(-688, 53)
|
||||
cooldown_time = 0.1
|
||||
lock_player_on_playing_dialogue = false
|
||||
hook_dialogue_title = "c01_s07_监督小孩吉祥话"
|
||||
|
||||
[node name="Npc吉祥话1" parent="Ground/DeployLayer/其余小孩" instance=ExtResource("6_fw22n")]
|
||||
position = Vector2(-44, 78)
|
||||
sign_mark_height = 23.0
|
||||
@ -237,6 +231,20 @@ autoplay = "杂戏团黄昏_举碗小孩"
|
||||
position = Vector2(6, 57)
|
||||
note_key = "c01_s07_钱碗"
|
||||
|
||||
[node name="Npc监督小孩" parent="Ground/DeployLayer/举碗小孩" instance=ExtResource("6_fw22n")]
|
||||
position = Vector2(6, 72)
|
||||
snap_to_edge = false
|
||||
enabled = false
|
||||
sign_mark_height = 11.0
|
||||
speaking_sign_height = 54.0
|
||||
|
||||
[node name="Ambush监督小孩" parent="Ground/DeployLayer/举碗小孩" instance=ExtResource("9_f61dl")]
|
||||
position = Vector2(-825, 53)
|
||||
cooldown_time = 0.1
|
||||
lock_player_on_playing_dialogue = false
|
||||
hook_dialogue_title = "c01_s07_监督小孩吉祥话"
|
||||
hook_method = "jiandu_dialog_triggered"
|
||||
|
||||
[node name="报童" parent="Ground/DeployLayer" index="10" instance=ExtResource("9_slaub")]
|
||||
position = Vector2(2080, 6)
|
||||
sprite_frames = ExtResource("6_thm8f")
|
||||
|
@ -33,6 +33,7 @@ var shelf_game_success = false
|
||||
var envelope_game_success = false
|
||||
var manager
|
||||
var mice
|
||||
var fall_off
|
||||
|
||||
|
||||
func _on_ground_ready() -> void:
|
||||
@ -44,6 +45,7 @@ func _on_ground_ready() -> void:
|
||||
coin = $"../DeployLayer/Ambush银元"
|
||||
mice = $"../DeployLayer/自动跟随的老鼠"
|
||||
manager = $"../DeployLayer/老板"
|
||||
fall_off = $"../DeployLayer/小小蝶坠落"
|
||||
# 首先放报纸,触发动画,领取任务
|
||||
if counter.interacted_times > 0:
|
||||
ladder.enabled = true
|
||||
@ -127,9 +129,6 @@ func _on_shelf_game_exiting() -> void:
|
||||
SceneManager.release_player()
|
||||
|
||||
|
||||
var fall_off
|
||||
|
||||
|
||||
func _on_shelf_game_success() -> void:
|
||||
ArchiveManager.set_global_entry(&"c01_shelf_game_success", true)
|
||||
shelf_game_success = true
|
||||
@ -143,7 +142,6 @@ func _on_shelf_game_success() -> void:
|
||||
# 相机抖动
|
||||
SceneManager.get_camera_marker().shake_camera()
|
||||
# 播放小蝶从书架跌倒的动画
|
||||
fall_off = $"../DeployLayer/小小蝶坠落"
|
||||
fall_off.visible = true
|
||||
fall_off.play()
|
||||
fall_off.animation_finished.connect(_on_fall_off_finished)
|
||||
@ -154,11 +152,16 @@ func _on_shelf_game_success() -> void:
|
||||
|
||||
func _on_fall_off_finished() -> void:
|
||||
fall_off.visible = false
|
||||
SceneManager.get_player().hide_sprite = false
|
||||
await Util.wait(0.3)
|
||||
await SceneManager.pop_os_with_str("c01_s08_书架游戏完成")
|
||||
# 耳鸣与眩晕
|
||||
$"Sfx头痛耳鸣".play()
|
||||
$"../DizzyShader".dizzy()
|
||||
await Util.wait(2.5)
|
||||
await SceneManager.pop_os_with_str("c01_s08_书架游戏恢复记忆")
|
||||
# 最后释放玩家
|
||||
SceneManager.release_player()
|
||||
SceneManager.get_player().hide_sprite = false
|
||||
await Util.wait(1.2)
|
||||
SceneManager.pop_os_with_str("c01_s08_书架游戏完成")
|
||||
|
||||
|
||||
func _setup_weird_bookstore() -> void:
|
||||
|
@ -1,4 +1,4 @@
|
||||
[gd_scene load_steps=21 format=3 uid="uid://cwu4dhayra8pg"]
|
||||
[gd_scene load_steps=23 format=3 uid="uid://cwu4dhayra8pg"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://dayyx4jerj7io" path="res://scene/ground/ground.tscn" id="1_b3cca"]
|
||||
[ext_resource type="Script" uid="uid://6q2pfbqsw10t" path="res://scene/ground/scene/c01/s08_书店.gd" id="2_0lque"]
|
||||
@ -16,7 +16,9 @@
|
||||
[ext_resource type="AudioStream" uid="uid://bnjyw5v85s6qe" path="res://asset/audio/sfx/交互/序章/04_书店内_主角摔倒.ogg" id="8_p6k3c"]
|
||||
[ext_resource type="Texture2D" uid="uid://bho8xal4ha50l" path="res://asset/art/scene/c01/s08_书店/l_打光.png" id="9_i4dqp"]
|
||||
[ext_resource type="AudioStream" uid="uid://cniawn37n8888" path="res://asset/audio/sfx/交互/序章/04_书店内_递交报纸.ogg" id="9_lfr41"]
|
||||
[ext_resource type="AudioStream" uid="uid://b8sbtn3l37uh" path="res://asset/audio/sfx/旧版/c02/红屏.ogg" id="9_srknn"]
|
||||
[ext_resource type="Texture2D" uid="uid://bp4y3vujvsl7r" path="res://asset/art/scene/c01/s08_书店/fg_前景.png" id="10_4e3a1"]
|
||||
[ext_resource type="PackedScene" uid="uid://decfqoe5v0y6n" path="res://scene/effect/dizzy_shader.tscn" id="18_wg16e"]
|
||||
|
||||
[sub_resource type="AnimationLibrary" id="AnimationLibrary_xqgjo"]
|
||||
|
||||
@ -81,6 +83,12 @@ bus = &"game_sfx"
|
||||
script = ExtResource("4_p6k3c")
|
||||
metadata/_custom_type_script = "uid://rq6w1vuhuq1m"
|
||||
|
||||
[node name="Sfx头痛耳鸣" type="AudioStreamPlayer" parent="Ground/AnimationPlayer" index="5"]
|
||||
stream = ExtResource("9_srknn")
|
||||
bus = &"game_sfx"
|
||||
script = ExtResource("4_p6k3c")
|
||||
metadata/_custom_type_script = "uid://rq6w1vuhuq1m"
|
||||
|
||||
[node name="BGSprite2D" parent="Ground" index="2"]
|
||||
material = SubResource("ShaderMaterial_ddd5v")
|
||||
texture = ExtResource("3_322m4")
|
||||
@ -198,6 +206,8 @@ points = PackedVector2Array(22, 150, 545, 150)
|
||||
energy = 0.0
|
||||
blend_mode = 1
|
||||
|
||||
[node name="DizzyShader" parent="Ground" instance=ExtResource("18_wg16e")]
|
||||
|
||||
[node name="参考" type="Sprite2D" parent="."]
|
||||
visible = false
|
||||
modulate = Color(1, 1, 1, 0.580392)
|
||||
|
@ -1,4 +1,4 @@
|
||||
[gd_scene load_steps=11 format=3 uid="uid://c4ycvdsabi7lw"]
|
||||
[gd_scene load_steps=12 format=3 uid="uid://c4ycvdsabi7lw"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://b4rw4hk7ns4m8" path="res://scene/index_page.gd" id="1_c7y7r"]
|
||||
[ext_resource type="Texture2D" uid="uid://bcc0bk34l5gbc" path="res://asset/art/ui/index/菜单背景.png" id="1_jxn4k"]
|
||||
@ -6,6 +6,7 @@
|
||||
[ext_resource type="Script" uid="uid://rq6w1vuhuq1m" path="res://scene/entity/audio/sfx.gd" id="3_5oc6i"]
|
||||
[ext_resource type="Script" uid="uid://bbg4vopj4apl6" path="res://scene/entity/audio/bgm_control.gd" id="4_5oc6i"]
|
||||
[ext_resource type="AudioStream" uid="uid://b3b4a6nm8557i" path="res://asset/audio/专用/衔蝶_主菜单music剪辑人声版.ogg" id="5_5oc6i"]
|
||||
[ext_resource type="FontFile" uid="uid://bjmhscwn1ixj1" path="res://asset/font/字体/ChillJinshuSongMedium.otf" id="7_1sxgt"]
|
||||
|
||||
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_gu56a"]
|
||||
content_margin_top = 4.0
|
||||
@ -137,6 +138,18 @@ theme_override_styles/pressed = SubResource("StyleBoxFlat_scxsv")
|
||||
theme_override_styles/normal = SubResource("StyleBoxEmpty_vyh3d")
|
||||
text = "index_退出游戏"
|
||||
|
||||
[node name="ButtonQuery" type="LinkButton" parent="."]
|
||||
layout_mode = 0
|
||||
offset_left = 439.0
|
||||
offset_top = 27.0
|
||||
offset_right = 535.0
|
||||
offset_bottom = 67.0
|
||||
theme_override_fonts/font = ExtResource("7_1sxgt")
|
||||
theme_override_font_sizes/font_size = 12
|
||||
text = "衔蝶内测反馈问卷"
|
||||
underline = 2
|
||||
uri = "https://wj.qq.com/s2/23189494/a237/"
|
||||
|
||||
[node name="Mask" type="ColorRect" parent="."]
|
||||
visible = false
|
||||
layout_mode = 1
|
||||
|
Loading…
Reference in New Issue
Block a user