Untitled

Anonymous
plain_text
02/23/2026 11:11 PM
10.7 KB
8
Indexable
extends Node2D

@export var delivery_icon: Texture2D # optional overlay reward icon (can be null)

const LOCKER_NODE_NAME := "FoxpostSzekreny" # rename if your node is different
const EXIT_NODE_NAME := "ExitToHub"

var dialogue_ui
var note_ui
var fade_rect
var item_get_overlay
var main_ref

@onready var player = $Player
@onready var sfx_wrong: AudioStreamPlayer = get_node_or_null("Sounds/SFXWrong")
@onready var sfx_right: AudioStreamPlayer = get_node_or_null("Sounds/SFXRight")

@onready var exit_eicon: CanvasItem = get_node_or_null(EXIT_NODE_NAME + "/EIcon")

var has_package := false
var interaction_locked := false

@onready var locker = _get_interactable_by_name(LOCKER_NODE_NAME)
@onready var exit_to_hub = _get_interactable_by_name(EXIT_NODE_NAME)

# Optional spawn markers
var _spawn_from := "left"
@onready var spawn_left: Marker2D = get_node_or_null("SpawnLeft")
@onready var spawn_right: Marker2D = get_node_or_null("SpawnRight")

func set_spawn_from(side: String) -> void:
	_spawn_from = side

func bind_ui(d, n, f, i, m) -> void:
	dialogue_ui = d
	note_ui = n
	fade_rect = f
	item_get_overlay = i
	main_ref = m

func _ready() -> void:
	await _apply_spawn_if_present()

	# Persist if revisiting
	has_package = GameState.unlock_home
	if exit_eicon:
		exit_eicon.visible = has_package

	if locker != null:
		locker.interacted.connect(_on_locker_interacted)
	else:
		push_error("Foxpost: Interactable not found: " + LOCKER_NODE_NAME)

	if exit_to_hub != null:
		exit_to_hub.interacted.connect(_on_exit_to_hub)
	else:
		push_error("Foxpost: ExitToHub interactable not found (optional).")

# -------------------------------------------------
# Robust UI binding (no dependency on Main bind_ui)
# -------------------------------------------------
func _ensure_ui_bound() -> bool:
	if dialogue_ui != null:
		return true

	var root := get_tree().root
	var ui_root := root.find_child("UIRoot", true, false)
	if ui_root != null:
		dialogue_ui = ui_root.get_node_or_null("DialogueUI")
		note_ui = ui_root.get_node_or_null("NoteUI")
		fade_rect = ui_root.get_node_or_null("FadeRect")
		item_get_overlay = ui_root.get_node_or_null("ItemGetOverlay")

	# main_ref is only needed for go_hub; we can survive without it
	if main_ref == null:
		main_ref = root.find_child("Main", true, false)

	if dialogue_ui == null:
		push_error("Foxpost: dialogue_ui is null. Could not find UIRoot/DialogueUI.")
		return false

	return true

# -------------------------------------------------
# Interactable resolver (node itself OR child named Interactable)
# -------------------------------------------------
func _get_interactable_by_name(node_name: String) -> Node:
	var n := find_child(node_name, true, false)
	if n == null:
		return null
	if n.has_signal("interacted"):
		return n
	var child := n.get_node_or_null("Interactable")
	if child != null and child.has_signal("interacted"):
		return child
	return null

# -------------------------------------------------
# Spawn
# -------------------------------------------------
func _apply_spawn_if_present() -> void:
	if spawn_left == null or spawn_right == null:
		return
	var target := spawn_left if _spawn_from == "left" else spawn_right
	player.set_can_move(false)
	player.global_position = target.global_position
	await get_tree().create_timer(0.2).timeout
	player.set_can_move(true)

# -------------------------------------------------
# Choice helper
# -------------------------------------------------
func _connect_choice_once(handler: Callable) -> void:
	if not _ensure_ui_bound():
		return
	if dialogue_ui.choice_selected.is_connected(handler):
		dialogue_ui.choice_selected.disconnect(handler)
	dialogue_ui.choice_selected.connect(handler, CONNECT_ONE_SHOT)

# -------------------------------------------------
# Reinteraction lock (closable with E)
# -------------------------------------------------
func _show_reinteraction_line(speaker: String, text: String) -> void:
	if not _ensure_ui_bound():
		return
	if interaction_locked:
		return
	interaction_locked = true

	player.set_can_move(false)

	await get_tree().process_frame
	while Input.is_action_pressed("interact"):
		await get_tree().process_frame

	dialogue_ui.show_dialogue(speaker, text, null, [])

	while dialogue_ui != null and dialogue_ui.is_typing():
		await get_tree().process_frame

	while true:
		await get_tree().process_frame
		if Input.is_action_just_pressed("interact"):
			if dialogue_ui != null:
				dialogue_ui.hide_dialogue()
			break

	while Input.is_action_pressed("interact"):
		await get_tree().process_frame

	await get_tree().create_timer(0.05).timeout
	player.set_can_move(true)
	interaction_locked = false

# -------------------------------------------------
# Main interaction
# -------------------------------------------------
func _on_locker_interacted() -> void:
	if has_package:
		await _show_reinteraction_line("Foxpost szekrény", "Már megvan a csomagod.")
		return

	if interaction_locked:
		return
	interaction_locked = true
	player.set_can_move(false)

	await get_tree().process_frame
	while Input.is_action_pressed("interact"):
		await get_tree().process_frame

	_show_picker()

func _show_picker() -> void:
	if not _ensure_ui_bound():
		player.set_can_move(true)
		interaction_locked = false
		return

	dialogue_ui.show_dialogue(
		"Foxpost szekrény",
		"",
		null,
		[
			{"label": "21-es rekesz"},
			{"label": "32-es rekesz"},
			{"label": "53-as rekesz"},
			{"label": "64-es rekesz"},
		]
	)
	_connect_choice_once(_on_picker_choice)

func _on_picker_choice(i: int) -> void:
	match i:
		0, 1, 3:
			_wrong_choice()
		2:
			await _right_choice()

func _wrong_choice() -> void:
	if sfx_wrong != null and sfx_wrong.stream != null:
		sfx_wrong.play()

	dialogue_ui.show_dialogue(
		"Foxpost szekrény",
		"Sajnos ez nem az. Próbálj egy másikat.",
		null,
		[]
	)

	# Wait until typing ends, then return to picker automatically
	await _wait_typing_done()

	_show_picker()

func _right_choice() -> void:
	if sfx_right != null and sfx_right.stream != null:
		sfx_right.play()

	dialogue_ui.show_dialogue(
		"Foxpost szekrény",
		"**A rekesz kinyílik...**\n\nVedd át a csomagod, már régóta vár rád.",
		null,
		[]
	)

	# Wait until typing ends, then grant reward (no extra click needed)
	await _wait_typing_done()

	has_package = true
	GameState.unlock_home = true

	if exit_eicon:
		exit_eicon.visible = true

	# Optional overlay reward animation
	if delivery_icon != null:
		await _play_item_get_sequence(delivery_icon)

	# Now let player close with E and move on
	while true:
		await get_tree().process_frame
		if Input.is_action_just_pressed("interact"):
			if dialogue_ui != null:
				dialogue_ui.hide_dialogue()
			break

	while Input.is_action_pressed("interact"):
		await get_tree().process_frame

	player.set_can_move(true)
	interaction_locked = false

func _wait_typing_done() -> void:
	while dialogue_ui != null and dialogue_ui.is_typing():
		await get_tree().process_frame

# -------------------------------------------------
# Exit
# -------------------------------------------------
func _on_exit_to_hub() -> void:
	if not has_package:
		return
	if main_ref != null and main_ref.has_method("go_hub"):
		main_ref.go_hub("left")

# -------------------------------------------------
# Optional reward overlay
# -------------------------------------------------
func _play_item_get_sequence(texture: Texture2D) -> void:
	if fade_rect == null or item_get_overlay == null:
		return

	var icon := item_get_overlay.get_node("Center/ItemIcon") as TextureRect
	if icon == null:
		return

	fade_rect.visible = true
	fade_rect.modulate.a = 0.0
	item_get_overlay.visible = true
	icon.visible = true
	icon.texture = texture
	icon.modulate = Color(1, 1, 1, 0)

	var t := create_tween()
	t.tween_property(fade_rect, "modulate:a", 1.0, 0.25)
	await t.finished

	var t2 := create_tween()
	t2.tween_property(icon, "modulate:a", 1.0, 0.2)
	await t2.finished

	await get_tree().create_timer(0.4).timeout

	var t3 := create_tween()
	t3.tween_property(icon, "modulate:a", 0.0, 0.2)
	await t3.finished

	item_get_overlay.visible = false

	var t4 := create_tween()
	t4.tween_property(fade_rect, "modulate:a", 0.0, 0.25)
	await t4.finished

	fade_rect.visible = false
Editor is loading...
Leave a Comment