xiandie/scene/ground/script/c02/小手讨东西.gd
2025-06-30 18:33:40 +08:00

246 lines
7.7 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 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
if icount == 1:
var stage = EventManager.get_stage(&"c02_little_hand")
if stage == 0:
# 首次交互小手
EventManager.set_stage(&"c02_little_hand", 1)
# 9 小手交互,吓摔倒
SceneManager.lock_player(0, 9, true)
SceneManager.pop_os_with_str("c02_小手出现摔倒")
Util.timer(1.5, $"Sfx摔倒".play)
await SceneManager.get_player().animation_finished
SceneManager.unlock_player()
elif stage == 1:
# 第二次交互小手
EventManager.set_stage(&"c02_little_hand", 2)
SceneManager.pop_os_with_str("c02_小手再次出现")
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 _on_interacted() -> void:
if interacting:
print("小手 interacting 锁定中")
# SceneManager.release_player()
return
interacting = true
interact_start.emit()
icount += 1
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
SceneManager.pop_os_with_str("c02_锡箔换小鞋子")
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"):
SceneManager.pop_os_with_str("c02_小手要东西")
ArchiveManager.set_global_entry(&"c02_little_hand_dropped_tin", 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 Util.wait(1.5)
holding_prop = "prop_弹珠"
EventManager.set_stage_if_greater("handnote_stage", 4)
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