2025-05-13 11:45:33 +00:00
|
|
|
|
@tool
|
|
|
|
|
extends Sprite2D
|
|
|
|
|
|
2025-06-04 14:02:22 +00:00
|
|
|
|
signal interacted
|
|
|
|
|
|
2025-06-04 11:46:27 +00:00
|
|
|
|
# 0保卫科 1二楼内侧
|
|
|
|
|
@export_enum("保卫科", "二楼内侧") var id := 0
|
2025-05-13 11:45:33 +00:00
|
|
|
|
@export var enabled := true:
|
|
|
|
|
set(val):
|
|
|
|
|
enabled = val
|
|
|
|
|
if is_node_ready():
|
2025-06-05 14:01:47 +00:00
|
|
|
|
_check_sign_mark_display()
|
|
|
|
|
|
2025-06-04 11:46:27 +00:00
|
|
|
|
@export var unrevealed_sign_texture: Texture2D
|
2025-05-13 11:45:33 +00:00
|
|
|
|
@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
|
2025-05-14 20:43:55 +00:00
|
|
|
|
@onready var sfx_bgm = $SfxBgm as AudioStreamPlayer
|
2025-05-13 11:45:33 +00:00
|
|
|
|
@onready var sign_mark = %Sign as Sign
|
|
|
|
|
@onready var area2d = %Area2D as Area2D
|
|
|
|
|
|
2025-05-14 20:43:55 +00:00
|
|
|
|
@onready var animated_sprite = $"小手" as AnimatedSprite2D
|
2025-05-13 11:45:33 +00:00
|
|
|
|
|
|
|
|
|
var ground_archive: GroundArchive
|
|
|
|
|
|
|
|
|
|
static var item_config_res = preload("res://asset/dialogue/item_description.dialogue")
|
|
|
|
|
|
|
|
|
|
# 当前小手手持的 prop
|
2025-05-14 20:43:55 +00:00
|
|
|
|
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()
|
2025-06-04 11:46:27 +00:00
|
|
|
|
# 尝试互动的次数
|
|
|
|
|
var tried_times: int:
|
|
|
|
|
set(val):
|
|
|
|
|
tried_times = val
|
|
|
|
|
ground_archive.set_pair(name, "tried_times", val)
|
2025-05-14 20:43:55 +00:00
|
|
|
|
|
|
|
|
|
var coin: Pickable2D
|
2025-05-13 11:45:33 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func _ready() -> void:
|
|
|
|
|
if Engine.is_editor_hint():
|
|
|
|
|
return
|
|
|
|
|
area2d.body_entered.connect(_reset)
|
2025-05-14 20:43:55 +00:00
|
|
|
|
area2d.body_exited.connect(_on_exit)
|
2025-05-13 11:45:33 +00:00
|
|
|
|
sign_mark.interacted.connect(_on_interacted)
|
|
|
|
|
sign_mark.cancel.connect(_on_cancel)
|
|
|
|
|
sign_mark.base_scale = sign_mark.scale
|
|
|
|
|
sign_mark.enabled = enabled
|
2025-05-14 20:43:55 +00:00
|
|
|
|
|
2025-05-13 11:45:33 +00:00
|
|
|
|
# setup default value
|
2025-05-14 20:43:55 +00:00
|
|
|
|
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", "")
|
2025-06-04 11:46:27 +00:00
|
|
|
|
tried_times = ground_archive.get_value(name, "tried_times", 0)
|
2025-05-14 20:43:55 +00:00
|
|
|
|
|
|
|
|
|
if holding_prop == "prop_弹珠":
|
|
|
|
|
animated_sprite.play("小手_弹珠_idle")
|
|
|
|
|
elif holding_prop == "prop_老虎钳":
|
|
|
|
|
animated_sprite.play("小手_老虎钳_idle")
|
|
|
|
|
elif is_holding_cup:
|
|
|
|
|
animated_sprite.play("小手_纸杯_idle")
|
2025-06-04 14:02:22 +00:00
|
|
|
|
elif tried_times > 0:
|
|
|
|
|
animated_sprite.play("小手_show")
|
|
|
|
|
|
2025-05-14 20:43:55 +00:00
|
|
|
|
coin = get_node("Pickable元宝")
|
|
|
|
|
tin_coin_drop = ground_archive.get_value(name, "tin_coin_drop", false)
|
|
|
|
|
coin.triggered.connect(func(): tin_coin_drop = false)
|
2025-05-13 11:45:33 +00:00
|
|
|
|
|
|
|
|
|
|
2025-06-05 14:01:47 +00:00
|
|
|
|
func _check_sign_mark_display():
|
|
|
|
|
sign_mark.enabled = enabled and not interacting
|
|
|
|
|
|
|
|
|
|
|
2025-05-13 11:45:33 +00:00
|
|
|
|
func _reset(_body = null) -> void:
|
|
|
|
|
_reset_sign_testure_to_prop()
|
|
|
|
|
var prop_hud = SceneManager.get_prop_hud() as PropHud
|
|
|
|
|
if not prop_hud.current_item_changed.is_connected(_set_sign_texture_to_prop):
|
|
|
|
|
prop_hud.current_item_changed.connect(_set_sign_texture_to_prop)
|
|
|
|
|
|
|
|
|
|
|
2025-06-04 11:46:27 +00:00
|
|
|
|
# 在场景中调用该方法,可以跳过小手初次交互的伸出过程
|
|
|
|
|
func do_first_interact(immediatelly := false):
|
|
|
|
|
if immediatelly:
|
|
|
|
|
animated_sprite.play("小手_idle")
|
|
|
|
|
else:
|
|
|
|
|
animated_sprite.play("小手_show")
|
|
|
|
|
_reset_sign_testure_to_prop()
|
|
|
|
|
|
|
|
|
|
|
2025-05-13 11:45:33 +00:00
|
|
|
|
func _reset_sign_testure_to_prop():
|
|
|
|
|
var key = SceneManager.get_current_prop(false)
|
|
|
|
|
_set_sign_texture_to_prop(key)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 根据当前 prop,调整 sign 所显示的 texture
|
|
|
|
|
func _set_sign_texture_to_prop(key):
|
2025-06-05 14:01:47 +00:00
|
|
|
|
_check_sign_mark_display()
|
2025-06-04 11:46:27 +00:00
|
|
|
|
if tried_times == 0:
|
|
|
|
|
# 首次交互前 unrevealed
|
|
|
|
|
sign_mark.sprite2d.texture = unrevealed_sign_texture
|
|
|
|
|
return
|
|
|
|
|
sign_mark.sprite2d.texture = matched_sign_texture
|
2025-05-13 11:45:33 +00:00
|
|
|
|
|
2025-06-05 14:01:47 +00:00
|
|
|
|
|
2025-05-14 20:43:55 +00:00
|
|
|
|
func _on_exit(_body = null) -> void:
|
2025-05-13 11:45:33 +00:00
|
|
|
|
# disconnect signal
|
|
|
|
|
var prop_hud = SceneManager.get_prop_hud() as PropHud
|
|
|
|
|
if prop_hud and prop_hud.current_item_changed.is_connected(_set_sign_texture_to_prop):
|
|
|
|
|
prop_hud.current_item_changed.disconnect(_set_sign_texture_to_prop)
|
|
|
|
|
|
|
|
|
|
|
2025-05-14 20:43:55 +00:00
|
|
|
|
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
|
2025-06-07 09:04:08 +00:00
|
|
|
|
animated_sprite.play("小手_纸杯_show")
|
2025-05-14 20:43:55 +00:00
|
|
|
|
|
|
|
|
|
|
2025-06-05 14:01:47 +00:00
|
|
|
|
var interacting := false:
|
|
|
|
|
set(val):
|
|
|
|
|
interacting = val
|
|
|
|
|
_check_sign_mark_display()
|
2025-05-13 11:45:33 +00:00
|
|
|
|
|
2025-05-14 20:43:55 +00:00
|
|
|
|
var communicating = false
|
|
|
|
|
|
2025-05-13 11:45:33 +00:00
|
|
|
|
|
|
|
|
|
func _on_interacted() -> void:
|
2025-06-05 14:01:47 +00:00
|
|
|
|
if interacting:
|
|
|
|
|
print("小手 interacting 锁定中")
|
2025-05-13 11:45:33 +00:00
|
|
|
|
return
|
2025-06-05 14:01:47 +00:00
|
|
|
|
interacting = true
|
2025-06-04 14:02:22 +00:00
|
|
|
|
interacted.emit()
|
2025-06-04 11:46:27 +00:00
|
|
|
|
tried_times += 1
|
2025-06-04 14:02:22 +00:00
|
|
|
|
if tried_times == 1:
|
2025-06-04 11:46:27 +00:00
|
|
|
|
do_first_interact(false)
|
|
|
|
|
return
|
2025-05-13 11:45:33 +00:00
|
|
|
|
if holding_prop != "":
|
|
|
|
|
# 手持物品时,交互直接给玩家物品
|
|
|
|
|
SceneManager.enable_prop_item(holding_prop)
|
|
|
|
|
holding_prop = ""
|
2025-06-04 11:46:27 +00:00
|
|
|
|
animated_sprite.play("小手_show")
|
2025-06-05 14:01:47 +00:00
|
|
|
|
interacting = false
|
2025-05-13 11:45:33 +00:00
|
|
|
|
return
|
|
|
|
|
|
2025-05-14 20:43:55 +00:00
|
|
|
|
if is_holding_cup:
|
|
|
|
|
# 对话
|
|
|
|
|
if not communicating:
|
|
|
|
|
communicating = true
|
|
|
|
|
# # 走到指定地点
|
|
|
|
|
# SceneManager.get_player().walk_to(Vector2(225, 98.0), 1.5)
|
2025-06-04 11:46:27 +00:00
|
|
|
|
# await SceneManager.get_player().animation_finished
|
2025-05-14 20:43:55 +00:00
|
|
|
|
animated_sprite.visible = false
|
|
|
|
|
# 7 拿起纸杯 8 监听纸杯
|
|
|
|
|
SceneManager.freeze_player(0, 7)
|
|
|
|
|
SceneManager.get_player().force_play_animation("c00_吕萍_听纸杯")
|
|
|
|
|
SceneManager.pop_debug_dialog_info("音效", "纸杯电话童谣")
|
|
|
|
|
sfx_bgm.play()
|
|
|
|
|
# 交互时,已经在对话中
|
|
|
|
|
sfx_bgm.finished.connect(_quit_communicating, CONNECT_ONE_SHOT)
|
|
|
|
|
else:
|
|
|
|
|
_quit_communicating()
|
2025-06-05 14:01:47 +00:00
|
|
|
|
interacting = false
|
2025-05-14 20:43:55 +00:00
|
|
|
|
return
|
|
|
|
|
|
2025-05-13 11:45:33 +00:00
|
|
|
|
var key = SceneManager.get_current_prop(false)
|
|
|
|
|
var interacted_success = false
|
|
|
|
|
SceneManager.freeze_player(0)
|
|
|
|
|
|
|
|
|
|
# accept_tin_coin
|
|
|
|
|
if key == "prop_锡箔元宝":
|
|
|
|
|
interacted_success = true
|
|
|
|
|
SceneManager.disable_prop_item("prop_锡箔元宝")
|
2025-06-04 11:46:27 +00:00
|
|
|
|
if id == 1:
|
2025-05-13 11:45:33 +00:00
|
|
|
|
# 叠成纸杯电话
|
|
|
|
|
animated_sprite.play("小手_锡箔_hide")
|
2025-05-14 20:43:55 +00:00
|
|
|
|
is_holding_cup = true
|
2025-05-13 11:45:33 +00:00
|
|
|
|
SceneManager.pop_debug_dialog_info("美术", "叠成纸杯: 小手_锡箔_hide + 小手_纸杯_show + 小手_纸杯_idle")
|
2025-06-04 11:46:27 +00:00
|
|
|
|
await get_tree().create_timer(2).timeout
|
|
|
|
|
# 稍等片刻再给小鞋子
|
2025-05-13 11:45:33 +00:00
|
|
|
|
SceneManager.enable_prop_item("prop_小鞋子1")
|
|
|
|
|
ArchiveManager.set_global_entry("c02_mouse_follow_player", true)
|
|
|
|
|
var node = get_node("../自动跟随的老鼠") as Node2D
|
|
|
|
|
if node:
|
|
|
|
|
node.visible = true
|
|
|
|
|
else:
|
|
|
|
|
printerr("小手已接受锡箔;自动跟随的老鼠节点不存在")
|
|
|
|
|
else:
|
|
|
|
|
# 丢下元宝
|
|
|
|
|
animated_sprite.play("小手_锡箔_drop")
|
2025-05-14 20:43:55 +00:00
|
|
|
|
# 先设置允许 pickable,然后再设置可见性,等待动画播完再显示
|
|
|
|
|
tin_coin_drop = true
|
|
|
|
|
coin.visible = false
|
2025-05-13 11:45:33 +00:00
|
|
|
|
await get_tree().create_timer(1.5).timeout
|
|
|
|
|
coin.visible = true
|
|
|
|
|
|
|
|
|
|
# 是否允许老虎钳换弹珠
|
2025-05-21 20:16:27 +00:00
|
|
|
|
var pliers_to_ball = ArchiveManager.get_global_value("c02_pliers_to_ball", false)
|
2025-06-04 11:46:27 +00:00
|
|
|
|
if id == 0 and key == "prop_老虎钳" and pliers_to_ball:
|
2025-05-13 11:45:33 +00:00
|
|
|
|
interacted_success = true
|
|
|
|
|
SceneManager.disable_prop_item("prop_老虎钳")
|
|
|
|
|
animated_sprite.play("小手_老虎钳_hide")
|
|
|
|
|
SceneManager.pop_debug_dialog_info("美术", "小手_老虎钳_hide + 小手_弹珠_show + 小手_弹珠_idle")
|
|
|
|
|
await get_tree().create_timer(1.5).timeout
|
|
|
|
|
holding_prop = "prop_弹珠"
|
2025-06-04 11:46:27 +00:00
|
|
|
|
elif id == 0 and key == "prop_弹珠" and not pliers_to_ball:
|
2025-05-13 11:45:33 +00:00
|
|
|
|
interacted_success = true
|
|
|
|
|
SceneManager.disable_prop_item("prop_弹珠")
|
|
|
|
|
animated_sprite.play("小手_弹珠_hide")
|
|
|
|
|
SceneManager.pop_debug_dialog_info("美术", "小手_弹珠_hide + 小手_老虎钳_show + 小手_老虎钳_idle")
|
|
|
|
|
await get_tree().create_timer(1.5).timeout
|
|
|
|
|
holding_prop = "prop_老虎钳"
|
|
|
|
|
|
|
|
|
|
if interacted_success:
|
|
|
|
|
# sfx_success.play()
|
|
|
|
|
EventManager.prop_interacted(name, key, 1)
|
|
|
|
|
_reset_sign_testure_to_prop()
|
|
|
|
|
else:
|
|
|
|
|
sfx_invalid.play()
|
2025-06-04 11:46:27 +00:00
|
|
|
|
sign_mark.invalid_shake(matched_sign_texture, unmatched_sign_texture)
|
2025-05-13 11:45:33 +00:00
|
|
|
|
|
|
|
|
|
SceneManager.release_player()
|
2025-06-05 14:01:47 +00:00
|
|
|
|
interacting = false
|