@tool extends Sprite2D signal interact_start # 0保卫科 1二楼内侧 @export_enum("保卫科", "二楼内侧") var id := 0 @export var enabled := true: set(val): enabled = val if is_node_ready(): _check_sign_mark_display() @export var unrevealed_sign_texture: Texture2D @export var unmatched_sign_texture: Texture2D @export var matched_sign_texture: Texture2D @onready var sfx_invalid = $SfxInvalid as Sfx @onready var sfx_success = $SfxSuccess as Sfx @onready var sfx_bgm = $SfxBgm as AudioStreamPlayer @onready var sign_mark = %Sign as Sign @onready var sign_snapper = %SignSnapper as SignSnapper @onready var area2d = %Area2D as Area2D @onready var animated_sprite = $"小手" as AnimatedSprite2D var ground_archive: GroundArchive static var item_config_res = preload("res://asset/dialogue/item_description.dialogue") # 当前小手手持的 prop var holding_prop = "": set(val): holding_prop = val ground_archive.set_pair(name, "holding_prop", val) # 是否手持纸杯电话 var is_holding_cup = false: set(val): is_holding_cup = val ground_archive.set_pair(name, "is_holding_cup", val) # 锡纸是否在地上 var tin_coin_drop = false: set(val): tin_coin_drop = val ground_archive.set_pair(name, "tin_coin_drop", tin_coin_drop) if is_node_ready(): coin.enabled = val if tin_coin_drop: coin.reset() # 尝试互动的次数 var icount: int: set(val): icount = val ground_archive.set_pair(name, "icount", val) # update sign texture if icount == 0: # 首次交互前 unrevealed sign_mark.sprite2d.texture = unrevealed_sign_texture else: sign_mark.sprite2d.texture = matched_sign_texture var coin: Pickable2D func _ready() -> void: if Engine.is_editor_hint(): return # sign_mark.interacted.connect(_on_interacted) sign_snapper.arrived.connect(_on_interacted) sign_mark.cancel.connect(_on_cancel) _check_sign_mark_display() # setup default value ground_archive = ArchiveManager.archive.ground_archive() as GroundArchive is_holding_cup = ground_archive.get_value(name, "is_holding_cup", false) holding_prop = ground_archive.get_value(name, "holding_prop", "") icount = ground_archive.get_value(name, "icount", 0) if holding_prop == "prop_弹珠": animated_sprite.play("小手_弹珠_idle") elif holding_prop == "prop_老虎钳": animated_sprite.play("小手_老虎钳_idle") elif is_holding_cup: animated_sprite.play("小手_纸杯_idle") elif icount > 0: animated_sprite.play("小手_show") coin = get_node("Pickable元宝") tin_coin_drop = ground_archive.get_value(name, "tin_coin_drop", false) coin.triggered.connect(func(): tin_coin_drop = false) func _check_sign_mark_display(): sign_mark.enabled = enabled and not interacting # 在场景中调用该方法,可以跳过小手初次交互的伸出过程 func do_first_interact(immediatelly := false): if immediatelly: animated_sprite.play("小手_idle") else: animated_sprite.play("小手_show") await animated_sprite.animation_changed func _on_cancel(_body = null) -> void: if communicating: _quit_communicating() return func _quit_communicating() -> void: sfx_bgm.stop() if sfx_bgm.finished.is_connected(_quit_communicating): sfx_bgm.finished.disconnect(_quit_communicating) communicating = false SceneManager.release_player() # 重置动画 SceneManager.get_player().set_facing_direction(Vector2.ONE) animated_sprite.visible = true animated_sprite.play("小手_纸杯_show") var interacting := false: set(val): interacting = val _check_sign_mark_display() var communicating = false func _increase_icount(): icount += 1 if icount == 1: var stage = EventManager.get_stage(&"c02_little_hand") if stage == 0: # 首次交互小手 EventManager.set_stage(&"c02_little_hand", 1) # 9 小手交互,吓摔倒 Util.timer(1.5, $"Sfx摔倒".play) SceneManager.pop_os_with_str("c02_小手出现摔倒") await SceneManager.lock_player(0, 9, true) await SceneManager.pop_os_with_str("c02_小手是什么鬼") SceneManager.unlock_player() elif stage == 1: # 第二次交互小手 EventManager.set_stage(&"c02_little_hand", 2) # 无需 await SceneManager.pop_os_with_str("c02_小手再次出现") func _on_interacted() -> void: if interacting: print("小手 interacting 锁定中") # SceneManager.release_player() return interacting = true interact_start.emit() await _increase_icount() if icount == 1: await do_first_interact(false) elif holding_prop != "": # 手持物品时,交互直接给玩家物品 SceneManager.enable_prop_item(holding_prop) holding_prop = "" animated_sprite.play("小手_show") await animated_sprite.animation_changed elif is_holding_cup: # 对话 if not communicating: communicating = true # animated_sprite.visible = false # 7 拿起纸杯 8 监听纸杯 SceneManager.freeze_player(0, 7) # 小手收回 play backwards animated_sprite.play("小手_纸杯_hide") await SceneManager.get_player().animation_finished SceneManager.player_action(8) SceneManager.pop_debug_dialog_info("音效", "纸杯电话童谣") sfx_bgm.play() # 交互时,已经在对话中 sfx_bgm.finished.connect(_quit_communicating, CONNECT_ONE_SHOT) else: _quit_communicating() else: var key = SceneManager.get_current_prop(false) var interacted_success = false SceneManager.lock_player(0, 4) # accept_tin_coin if key == "prop_锡箔元宝": interacted_success = true sfx_success.play() SceneManager.disable_prop_item("prop_锡箔元宝") if id == 1: SceneManager.enable_prop_item_silently("prop_小鞋子1") ArchiveManager.set_global_entry(&"c02_mouse_follow_player", true) # 叠成纸杯电话 animated_sprite.play("小手_锡箔_hide") is_holding_cup = true SceneManager.pop_debug_dialog_info( "美术", "叠成纸杯: 小手_锡箔_hide + 小手_纸杯_show + 小手_纸杯_idle" ) await Util.wait(2.0) # 稍等片刻再给小鞋子 SceneManager.enable_prop_item("prop_小鞋子1") await SceneManager.get_inspector().quit_and_hidden await SceneManager.pop_os_with_str("c02_锡箔换小鞋子") EventManager.set_stage_if_greater(&"handnote_c02_hand_requireCoin", 2) var node = get_node("../自动跟随的老鼠") as Node2D if node: node.visible = true else: printerr("小手已接受锡箔;自动跟随的老鼠节点不存在") else: # 丢下元宝 animated_sprite.play("小手_锡箔_drop") # 先设置允许 pickable,然后再设置可见性,等待动画播完再显示 tin_coin_drop = true coin.visible = false await Util.wait(1.5) coin.visible = true if not ArchiveManager.get_global_value(&"c02_little_hand_dropped_tin"): ArchiveManager.set_global_entry(&"c02_little_hand_dropped_tin", true) await SceneManager.pop_os_with_str("c02_小手还能换什么") # 是否允许老虎钳换弹珠 var pliers_to_ball = ArchiveManager.get_global_value(&"c02_pliers_to_ball", false) if id == 0 and key == "prop_老虎钳" and pliers_to_ball: interacted_success = true sfx_success.play() SceneManager.disable_prop_item("prop_老虎钳") animated_sprite.play("小手_老虎钳_hide") SceneManager.pop_debug_dialog_info("美术", "小手_老虎钳_hide + 小手_弹珠_show + 小手_弹珠_idle") await Util.wait(1.5) holding_prop = "prop_弹珠" # 换回弹珠后完全结束 EventManager.set_stage_if_greater(&"handnote_c02_hand_exchange", 2) elif id == 0 and key == "prop_弹珠" and not pliers_to_ball: interacted_success = true sfx_success.play() SceneManager.disable_prop_item("prop_弹珠") animated_sprite.play("小手_弹珠_hide") SceneManager.pop_debug_dialog_info("美术", "小手_弹珠_hide + 小手_老虎钳_show + 小手_老虎钳_idle") await Util.wait(1.5) holding_prop = "prop_老虎钳" if interacted_success: EventManager.prop_interacted(name, key, 1) else: sfx_invalid.play() sign_mark.invalid_shake(matched_sign_texture, unmatched_sign_texture) SceneManager.unlock_player() interacting = false if id == 0: EventManager.set_stage_if_greater(&"handnote_c02_hand_exchange", 1) elif id == 1: EventManager.set_stage_if_greater(&"handnote_c02_hand_requireCoin", 1)