xiandie/scene/ground/script/c02/小手讨东西.gd
2025-05-22 04:16:27 +08:00

237 lines
7.4 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
@export var accept_tin_coin := false
@export var accept_ball_or_plier := false
@export var enabled := true:
set(val):
enabled = val
if is_node_ready():
sign_mark.enabled = val
@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 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.base_scale = sign_mark.scale
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", "")
if holding_prop == "prop_弹珠":
animated_sprite.play("小手_弹珠_idle")
elif holding_prop == "prop_老虎钳":
animated_sprite.play("小手_老虎钳_idle")
elif is_holding_cup:
animated_sprite.play("小手_纸杯_idle")
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 _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 _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):
var interactable = false
if holding_prop != "" or is_holding_cup:
# 手持物品/纸杯电话时,允许交互,获得物品/对话
interactable = true
if key == "prop_锡箔元宝":
interactable = true
elif accept_ball_or_plier and key == "prop_老虎钳":
interactable = ArchiveManager.get_global_value("c02_pliers_to_ball", false)
elif accept_ball_or_plier and key == "prop_弹珠":
interactable = not ArchiveManager.get_global_value("c02_pliers_to_ball", false)
if interactable:
sign_mark.sprite2d.texture = matched_sign_texture
else:
sign_mark.sprite2d.texture = unmatched_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
var interact_mutex = Mutex.new()
var communicating = false
func _on_interacted() -> void:
if not interact_mutex.try_lock():
return
if holding_prop != "":
# 手持物品时,交互直接给玩家物品
SceneManager.enable_prop_item(holding_prop)
holding_prop = ""
animated_sprite.play("小手_idle")
interact_mutex.unlock()
return
if is_holding_cup:
# 对话
if not communicating:
communicating = true
# # 走到指定地点
# SceneManager.get_player().walk_to(Vector2(225, 98.0), 1.5)
# await get_tree().create_timer(1.6).timeout
animated_sprite.visible = false
# 7 拿起纸杯 8 监听纸杯
SceneManager.freeze_player(0, 7)
await SceneManager.get_player().animation_finished
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()
interact_mutex.unlock()
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
SceneManager.disable_prop_item("prop_锡箔元宝")
if accept_tin_coin:
# 叠成纸杯电话
animated_sprite.play("小手_锡箔_hide")
is_holding_cup = true
# TODO
SceneManager.pop_debug_dialog_info("美术", "叠成纸杯: 小手_锡箔_hide + 小手_纸杯_show + 小手_纸杯_idle")
await get_tree().create_timer(1.5).timeout
SceneManager.enable_prop_item("prop_小鞋子1")
ArchiveManager.set_global_entry("c02_mouse_follow_player", true)
# 稍等后显示小老鼠
await get_tree().create_timer(0.5).timeout
SceneManager.pop_debug_dialog_info("美术", "触发⼩⽼⿏跟在玩家身后")
var node = get_node("../自动跟随的老鼠") as Node2D
if node:
node.visible = true
else:
printerr("小手已接受锡箔;自动跟随的老鼠节点不存在")
else:
# 丢下元宝
animated_sprite.play("小手_锡箔_drop")
# TODO
SceneManager.pop_debug_dialog_info("美术", "丢下元宝: 小手_锡箔_drop + 小手_idle + 落地后的锡箔贴图")
# 先设置允许 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 accept_ball_or_plier and key == "prop_老虎钳" and pliers_to_ball:
interacted_success = true
SceneManager.disable_prop_item("prop_老虎钳")
animated_sprite.play("小手_老虎钳_hide")
# TODO
SceneManager.pop_debug_dialog_info("美术", "小手_老虎钳_hide + 小手_弹珠_show + 小手_弹珠_idle")
await get_tree().create_timer(1.5).timeout
holding_prop = "prop_弹珠"
elif accept_ball_or_plier and key == "prop_弹珠" and not pliers_to_ball:
interacted_success = true
SceneManager.disable_prop_item("prop_弹珠")
animated_sprite.play("小手_弹珠_hide")
# TODO
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()
sign_mark.invalid_shake()
SceneManager.release_player()
interact_mutex.unlock()