@tool class_name Note2D extends Sprite2D signal read_note signal sign_mark_offset_updated # sign_mark 节点在 ready 时会直接读取 @export var sign_mark_offset := Vector2.ZERO: set(val): sign_mark_offset = val sign_mark_offset_updated.emit(val) @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", "c06") var dialogue := "items": 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 "c06": dialogue_res = dialogue_c06 if is_node_ready() and Engine.is_editor_hint(): notify_property_list_changed() var note_key := "" @export_enum("none", "notes", "c01", "c02", "c03", "c04", "c05") var title_filter := "none": set(val): title_filter = val if is_node_ready() and Engine.is_editor_hint(): notify_property_list_changed() @export var note_sign_texture: Texture2D @onready var sign_mark = %Sign as Sign @onready var area2d = %Area2D as Area2D 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") var dialogue_c06 = preload("res://asset/dialogue/c06.dialogue") var dialogue_res = dialogue_items var interacting = false var mutex = Mutex.new() 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(): notify_property_list_changed() 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 # setup default value ground_archive = ArchiveManager.archive.ground_archive() tried_times = ground_archive.get_value(name, "tried_times", 0) func _on_interacted() -> void: if interacting: return if not note_key: printerr("Note key is not set") return tried_times += 1 %Sfx.play() match mode: "os": _show_os() "ballon": var _res = dialogue_res var title = note_key # items 条目特殊处理,不使用标题 if dialogue == "items": title = "start" var content = tr(note_key).replace("
", "\n") var text = "~ " + title + "\n" + content + "\n=> END" _res = DialogueManager.create_resource_from_text(text) as DialogueResource _show_balloon(_res, title) read_note.emit() func _show_os(): interacting = true SceneManager.freeze_player(0.0, action) create_tween().tween_property(sign_mark, "modulate:a", 0.0, 0.3) var tween = await SceneManager.pop_os_with_str(note_key, false, true) tween.tween_property(sign_mark, "modulate:a", 1.0, 0.3) tween.tween_callback(_on_os_finished) func _on_os_finished(): interacting = false SceneManager.release_player() func _show_balloon(res, title): # SceneManager.focus_node(self) 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() 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) return [ { "name": "note_key", "type": TYPE_STRING, "hint": PROPERTY_HINT_ENUM_SUGGESTION, "hint_string": titles } ] func _filter_property(property: StringName) -> bool: return property.find(title_filter) >= 0 func _on_cancel(_body = null): interacting = false func _reset(_body): interacting = false