@tool class_name Interactable2D extends Sprite2D signal interacted @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 @export var one_shot := true @export var disable_prop_after_interacted := false @export var interacted_texture: Texture2D var prop_key := "" @onready var sfx_invalid = $SfxInvalid as Sfx @onready var sfx_success = $SfxSuccess as Sfx @onready var sign_mark = %Sign as Sign @onready var area2d = %Area2D as Area2D var ground_archive: GroundArchive var interacted_times: int: set(val): interacted_times = val ground_archive.set_pair(name, "interacted_times", val) static var item_config_res = preload("res://asset/dialogue/item_description.dialogue") 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.base_scale = sign_mark.scale sign_mark.enabled = enabled # setup default value ground_archive = ArchiveManager.archive.ground_archive() interacted_times = ground_archive.get_value(name, "interacted_times", 0) if interacted_times and interacted_texture: texture = interacted_texture _check_sign_display() func _check_sign_display(): if not enabled or (one_shot and interacted_times): sign_mark.enabled = 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): if not prop_key or prop_key == key: sign_mark.sprite2d.texture = matched_sign_texture else: sign_mark.sprite2d.texture = unmatched_sign_texture # if prop_hud.cached_inventory_textures.has(key): # var prop_texture = prop_hud.cached_inventory_textures[key] # sign_mark.draw_shadow = true # else: # sign_mark.sprite2d.texture = deaulte_sign_texture # sign_mark.draw_shadow = false # sign_mark.queue_redraw() func _on_cancel(_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) var interact_mutex = Mutex.new() func _on_interacted() -> void: interact_mutex.lock() if one_shot and interacted_times: interact_mutex.unlock() return var key = SceneManager.get_current_prop(false) if prop_key and key != prop_key: sfx_invalid.play() sign_mark.invalid_shake() # SceneManager.on_toggle_invalid_prop() interact_mutex.unlock() return sfx_success.play() if disable_prop_after_interacted and prop_key: SceneManager.disable_prop_item(prop_key) interacted_times += 1 if interacted_texture: texture = interacted_texture interacted.emit() EventManager.prop_interacted(name, prop_key, interacted_times) # print("%s interacted with %s. total times: %s" % [name, prop_key, interacted_times]) interact_mutex.unlock() _check_sign_display() _reset_sign_testure_to_prop() func _get_property_list() -> Array[Dictionary]: var items = [] if Engine.is_editor_hint(): var id = item_config_res.titles["PropItems"] var current_line = item_config_res.lines[id] while current_line: if current_line.has("translation_key"): items.append(current_line.translation_key) if not current_line.has("next_id") or current_line.next_id == "end": break current_line = item_config_res.lines[current_line.next_id] return [ { "name": "prop_key", "type": TYPE_STRING, "hint": PROPERTY_HINT_ENUM_SUGGESTION, "hint_string": ",".join(items), } ] func _get(property: StringName) -> Variant: if property == "prop_key": return prop_key return null func _set(property: StringName, value: Variant) -> bool: if property == "prop_key": prop_key = value return true return false