xiandie/scene/entity/note.gd

189 lines
5.0 KiB
GDScript3
Raw Normal View History

2025-01-10 07:43:55 +00:00
@tool
class_name Note2D extends Sprite2D
2025-01-12 12:15:18 +00:00
signal read_note
@export var enabled := true:
set(val):
enabled = val
if is_node_ready():
sign_mark.enabled = val
@export var action := 4 #3为none; 4为lookup_wall; 之后为其他动作,请参考 PlayerAnimationConfig
@export_enum("os", "ballon") var mode = "os"
@export_enum("items", "c01", "c02", "c03", "c04", "c05") var dialogue := "items":
2025-01-10 07:43:55 +00:00
set(val):
dialogue = val
match dialogue:
"items":
dialogue_res = dialogue_items
"c01":
dialogue_res = dialogue_c01
"c02":
dialogue_res = dialogue_c02
"c03":
dialogue_res = dialogue_c03
"c04":
dialogue_res = dialogue_c04
"c05":
dialogue_res = dialogue_c05
2025-01-21 10:52:36 +00:00
if is_node_ready() and Engine.is_editor_hint():
2025-01-10 07:43:55 +00:00
notify_property_list_changed()
var note_key := ""
@export_enum("none", "notes", "c01", "c02", "c03", "c04", "c05") var title_filter := "none":
2025-01-10 07:43:55 +00:00
set(val):
2025-01-13 08:09:57 +00:00
title_filter = val
2025-01-21 10:52:36 +00:00
if is_node_ready() and Engine.is_editor_hint():
2025-01-10 07:43:55 +00:00
notify_property_list_changed()
2025-06-04 11:46:27 +00:00
@export var note_sign_texture: Texture2D
2025-01-08 00:51:09 +00:00
@onready var sign_mark = %Sign as Sign
@onready var area2d = %Area2D as Area2D
2025-01-10 07:43:55 +00:00
var dialogue_items = preload("res://asset/dialogue/item_description.dialogue")
var dialogue_c01 = preload("res://asset/dialogue/c01.dialogue")
var dialogue_c02 = preload("res://asset/dialogue/c02.dialogue")
var dialogue_c03 = preload("res://asset/dialogue/c03.dialogue")
var dialogue_c04 = preload("res://asset/dialogue/c04.dialogue")
var dialogue_c05 = preload("res://asset/dialogue/c05.dialogue")
2025-01-10 07:43:55 +00:00
var dialogue_res = dialogue_items
var interacting = false
var mutex = Mutex.new()
2025-06-04 11:46:27 +00:00
var ground_archive: GroundArchive
# 尝试互动的次数
var tried_times: int:
set(val):
tried_times = val
ground_archive.set_pair(name, "tried_times", val)
if tried_times >= 1 and sign_mark:
sign_mark.sprite2d.texture = note_sign_texture
func _ready() -> void:
if Engine.is_editor_hint():
return
area2d.body_entered.connect(_reset)
area2d.body_exited.connect(_on_cancel)
sign_mark.interacted.connect(_on_interacted)
sign_mark.cancel.connect(_on_cancel)
sign_mark.enabled = enabled
2025-06-04 11:46:27 +00:00
# setup default value
ground_archive = ArchiveManager.archive.ground_archive()
tried_times = ground_archive.get_value(name, "tried_times", 0)
func _on_interacted() -> void:
2025-01-10 07:43:55 +00:00
if interacting:
return
2025-01-10 07:43:55 +00:00
if not note_key:
printerr("Note key is not set")
return
2025-06-04 11:46:27 +00:00
tried_times += 1
%Sfx.play()
2025-01-13 08:09:57 +00:00
var _res = dialogue_res
var title = note_key
# items 条目特殊处理,不使用标题
if dialogue == "items":
title = "start"
var content = tr(note_key)
var text = "~ " + title + "\n" + content + "\n=> END"
_res = DialogueManager.create_resource_from_text(text) as DialogueResource
match mode:
"os":
2025-01-13 08:09:57 +00:00
_show_os(_res, title)
"ballon":
2025-01-13 08:09:57 +00:00
_show_balloon(_res, title)
2025-01-12 12:15:18 +00:00
read_note.emit()
2025-01-13 08:09:57 +00:00
func _show_os(res, title):
var lines = await DialogueUtil.get_lines(res, title)
SceneManager.pop_os(lines)
interacting = true
var player = SceneManager.get_player()
if player:
player.freeze_player(0.0, action, false)
player.os_finished.connect(_on_os_finished, CONNECT_ONE_SHOT)
func _on_os_finished():
interacting = false
SceneManager.release_player()
2025-01-10 07:43:55 +00:00
2025-01-13 08:09:57 +00:00
func _show_balloon(res, title):
# SceneManager.focus_node(self)
2025-01-13 08:09:57 +00:00
DialogueManager.show_dialogue_balloon(res, title)
# TODO note viewing animation
SceneManager.freeze_player(0, action)
interacting = true
DialogueManager.dialogue_ended.connect(_on_ballon_ended, CONNECT_ONE_SHOT)
# var player = SceneManager.get_player()
# DialogueManager.show_dialogue_balloon_scene(player, dialogue_res, note_key)
func _on_ballon_ended(_res):
interacting = false
SceneManager.release_player()
# SceneManager.focus_player_and_reset_zoom()
2025-01-10 07:43:55 +00:00
func _set(property: StringName, value: Variant) -> bool:
if property == "note_key":
note_key = value
return true
return false
func _get(property: StringName) -> Variant:
if property == "note_key":
return note_key
elif property == "dialogue_res":
return dialogue_res
return null
func _get_property_list() -> Array[Dictionary]:
# only show notes_ properties in editor
var titles = ""
if Engine.is_editor_hint():
var title_arr = []
if dialogue == "items":
var id = dialogue_items.titles["Notes"]
var current_line = dialogue_items.lines[id]
while current_line:
if current_line.has("translation_key"):
title_arr.append(current_line.translation_key)
if not current_line.has("next_id") or current_line.next_id == "end":
break
current_line = dialogue_items.lines[current_line.next_id]
else:
title_arr = dialogue_res.get_ordered_titles()
if title_filter and title_filter != "none":
var filted_titles = title_arr.filter(_filter_property)
titles = ",".join(filted_titles)
else:
titles = ",".join(title_arr)
2025-01-10 07:43:55 +00:00
return [
{
"name": "note_key",
"type": TYPE_STRING,
"hint": PROPERTY_HINT_ENUM_SUGGESTION,
"hint_string": titles
}
]
func _filter_property(property: StringName) -> bool:
2025-01-13 08:09:57 +00:00
return property.find(title_filter) >= 0
2025-01-10 07:43:55 +00:00
func _on_cancel(_body = null):
2025-01-10 07:43:55 +00:00
interacting = false
func _reset(_body):
2025-01-10 07:43:55 +00:00
interacting = false