xiandie/scene/ground/script/c02/小手讨东西.gd
2025-06-18 21:48:59 +08:00

255 lines
7.6 KiB
GDScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

@tool
extends Sprite2D
signal interacted
# 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 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 tried_times: int:
set(val):
tried_times = val
ground_archive.set_pair(name, "tried_times", val)
var coin: Pickable2D
func _ready() -> void:
if Engine.is_editor_hint():
return
area2d.body_entered.connect(_reset)
area2d.body_exited.connect(_on_exit)
sign_mark.interacted.connect(_on_interacted)
sign_mark.cancel.connect(_on_cancel)
sign_mark.enabled = enabled
# 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", "")
tried_times = ground_archive.get_value(name, "tried_times", 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 tried_times > 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 _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)
# 在场景中调用该方法,可以跳过小手初次交互的伸出过程
func do_first_interact(immediatelly := false):
if immediatelly:
animated_sprite.play("小手_idle")
else:
animated_sprite.play("小手_show")
_reset_sign_testure_to_prop()
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):
_check_sign_mark_display()
if tried_times == 0:
# 首次交互前 unrevealed
sign_mark.sprite2d.texture = unrevealed_sign_texture
return
sign_mark.sprite2d.texture = matched_sign_texture
func _on_exit(_body = null) -> void:
# 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)
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 _on_interacted() -> void:
if interacting:
print("小手 interacting 锁定中")
return
interacting = true
interacted.emit()
tried_times += 1
if tried_times == 1:
do_first_interact(false)
interacting = false
return
if holding_prop != "":
# 手持物品时,交互直接给玩家物品
SceneManager.enable_prop_item(holding_prop)
holding_prop = ""
animated_sprite.play("小手_show")
interacting = false
return
if is_holding_cup:
# 对话
if not communicating:
communicating = true
# # 走到指定地点
# SceneManager.get_player().walk_to(Vector2(225, 98.0), 1.5)
# await SceneManager.get_player().animation_finished
animated_sprite.visible = false
# 7 拿起纸杯 8 监听纸杯
SceneManager.freeze_player(0, 7)
await SceneManager.get_player().animation_finished
SceneManager.freeze_player(0, 8)
SceneManager.pop_debug_dialog_info("音效", "纸杯电话童谣")
sfx_bgm.play()
# 交互时,已经在对话中
sfx_bgm.finished.connect(_quit_communicating, CONNECT_ONE_SHOT)
else:
_quit_communicating()
interacting = false
return
var key = SceneManager.get_current_prop(false)
var interacted_success = false
SceneManager.freeze_player(0)
# accept_tin_coin
if key == "prop_锡箔元宝":
interacted_success = true
sfx_success.play()
SceneManager.disable_prop_item("prop_锡箔元宝")
if id == 1:
# 叠成纸杯电话
animated_sprite.play("小手_锡箔_hide")
is_holding_cup = true
SceneManager.pop_debug_dialog_info("美术", "叠成纸杯: 小手_锡箔_hide + 小手_纸杯_show + 小手_纸杯_idle")
await get_tree().create_timer(2).timeout
# 稍等片刻再给小鞋子
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")
# 先设置允许 pickable然后再设置可见性等待动画播完再显示
tin_coin_drop = true
coin.visible = false
await get_tree().create_timer(1.5).timeout
coin.visible = true
# 是否允许老虎钳换弹珠
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 get_tree().create_timer(1.5).timeout
holding_prop = "prop_弹珠"
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 get_tree().create_timer(1.5).timeout
holding_prop = "prop_老虎钳"
if interacted_success:
EventManager.prop_interacted(name, key, 1)
_reset_sign_testure_to_prop()
else:
sfx_invalid.play()
sign_mark.invalid_shake(matched_sign_texture, unmatched_sign_texture)
SceneManager.release_player()
interacting = false