Untitled

Anonymous
plain_text
02/24/2026 12:49 AM
16.1 KB
10
Indexable
extends Node2D

@export var pultos_portrait: Texture2D
@export var drink_token_icon: Texture2D  # reward icon shown in overlay

var dialogue_ui
var note_ui
var fade_rect
var item_get_overlay
var main_ref

@onready var player = $Player
@onready var pultos_eicon: CanvasItem = get_node_or_null("Pultos/EIcon")

@onready var pultos = _get_pultos_interactable()

@onready var exit_to_hub = _get_exit_interactable()
@onready var exit_eicon: CanvasItem = get_node_or_null("ExitToHub/EIcon")

var has_reward := false

# Locks any interaction while we are showing post-reward lines or playing reward sequence
var interaction_locked := false

# Optional per-scene spawn (only works if you add these Marker2D nodes)
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 state if you revisit the scene
	has_reward = GameState.unlock_bank_center
	if has_reward:
		if exit_eicon:
			exit_eicon.visible = true
		if pultos_eicon:
			pultos_eicon.visible = false
	else:
		if exit_eicon:
			exit_eicon.visible = false

	if pultos != null and pultos.has_signal("interacted"):
		pultos.interacted.connect(_on_pultos_interacted)
	else:
		push_error("Aurora: Pultos Interactable not found. Name the node 'Pultos' and attach Interactable.gd (or add a child named 'Interactable').")

	# Exit wiring
	if exit_to_hub != null and exit_to_hub.has_signal("interacted"):
		exit_to_hub.interacted.connect(_on_exit_to_hub)
	else:
		push_error("Aurora: ExitToHub interactable not found. Make sure node is named 'ExitToHub' and has Interactable.gd (or a child 'Interactable').")

func _get_exit_interactable() -> Node:
	var n := get_node_or_null("ExitToHub")
	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

func _get_pultos_interactable() -> Node:
	var n := get_node_or_null("Pultos")
	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

func _apply_spawn_if_present() -> void:
	if spawn_left == null or spawn_right == null:
		return

	var target: Marker2D = spawn_left if _spawn_from == "left" else spawn_right
	if target == null:
		return

	player.set_can_move(false)

	var offset := Vector2(-32, 0) if _spawn_from == "left" else Vector2(32, 0)
	player.global_position = target.global_position + offset

	var t := create_tween()
	t.tween_property(player, "global_position", target.global_position, 0.35)\
		.set_trans(Tween.TRANS_SINE)\
		.set_ease(Tween.EASE_OUT)

	await t.finished
	player.set_can_move(true)

# -------------------------------------------------
# Choice connection helper (prevents double replies)
# -------------------------------------------------
func _connect_choice_once(handler: Callable) -> void:
	if dialogue_ui == null:
		push_error("Aurora: dialogue_ui is null (bind_ui not called?)")
		return
	if dialogue_ui.choice_selected.is_connected(handler):
		dialogue_ui.choice_selected.disconnect(handler)
	dialogue_ui.choice_selected.connect(handler, CONNECT_ONE_SHOT)

# -------------------------------------------------
# Debounced "press E to close dialogue" helper
# - Lets typewriter finish (DialogueUI handles E for rushing)
# - Then waits for a FRESH E press to close
# -------------------------------------------------
func _close_after_fresh_e() -> void:
	# Wait until typing ends
	while dialogue_ui != null and dialogue_ui.is_typing():
		await get_tree().process_frame

	# Debounce: wait release (if player is holding interact)
	while Input.is_action_pressed("interact"):
		await get_tree().process_frame

	# Fresh E press to close
	while true:
		await get_tree().process_frame
		if Input.is_action_just_pressed("interact"):
			if dialogue_ui != null:
				dialogue_ui.hide_dialogue()
			break

	# Wait for release to avoid instant re-trigger
	while Input.is_action_pressed("interact"):
		await get_tree().process_frame

	await get_tree().create_timer(0.05).timeout

# -------------------------------------------------
# Post-reward reinteraction line (debounced)
# -------------------------------------------------
func _show_reinteraction_line(speaker: String, text: String, portrait: Texture2D) -> void:
	if interaction_locked:
		return
	interaction_locked = true

	player.set_can_move(false)

	# Debounce the interact press that triggered the interaction
	await get_tree().process_frame
	while Input.is_action_pressed("interact"):
		await get_tree().process_frame

	dialogue_ui.show_dialogue(speaker, text, portrait, [])
	await _close_after_fresh_e()

	player.set_can_move(true)
	interaction_locked = false

# -------------------------------------------------
# Exit back to hub
# -------------------------------------------------
func _on_exit_to_hub() -> void:
	if interaction_locked:
		return
	if not has_reward:
		return

	if exit_eicon:
		exit_eicon.visible = false

	if main_ref != null and main_ref.has_method("go_hub"):
		main_ref.go_hub("left")
	else:
		push_error("Aurora: main_ref.go_hub missing")

# -------------------------------------------------
# Interaction entry
# -------------------------------------------------
func _on_pultos_interacted() -> void:
	if interaction_locked:
		return

	if has_reward:
		await _show_reinteraction_line(
			"Pultos",
			"Rádnéz, aztán a pultra.\n„Már megkaptad a tokent.”\n„Ne legyél telhetetlen.”",
			pultos_portrait
		)
		return

	player.set_can_move(false)
	_stage_start()

func _stage_start() -> void:
	dialogue_ui.show_dialogue(
		"Pultos",
		"Fél szemmel mér végig, mert közben valakivel beszélget a pult mögött.\n„Szia.”\n„Mit kérsz?”",
		pultos_portrait,
		[
			{"label": "Egy fröccsöt."},
			{"label": "Egy gin tonic-ot."},
			{"label": "Egy zéró kólát."},
			{"label": "Még gondolkodom."},
		]
	)
	_connect_choice_once(_choice_start)

func _choice_start(i: int) -> void:
	match i:
		0:
			_to_beer_picker("„Ugyan már. Te általában sörös vagy. Milyet kérsz?”")
		1:
			_to_beer_picker("„Ugyan már. Te általában sörös vagy. Milyet kérsz?”")
		2:
			_to_beer_picker("„Ugyan már. Te általában sörös vagy. Milyet kérsz?”")
		3:
			_return_to_start("„Figyelj, ha nem kérsz valamit állj ki a sorból.”")

func _return_to_start(reply: String) -> void:
	dialogue_ui.show_dialogue(
		"Pultos",
		reply,
		pultos_portrait,
		[
			{"label": "Egy fröccsöt."},
			{"label": "Egy gin tonic-ot."},
			{"label": "Egy zéró kólát."},
			{"label": "Még gondolkodom."},
		]
	)
	_connect_choice_once(_choice_start)

# -------------------------------------------------
# Beer picker -> birthday line -> reaction
# -------------------------------------------------
func _to_beer_picker(prompt: String) -> void:
	dialogue_ui.show_dialogue(
		"Pultos",
		prompt,
		pultos_portrait,
		[
			{"label": "Lager"},
			{"label": "IPA"},
			{"label": "Búza"},
			{"label": "Barna"},
		]
	)
	_connect_choice_once(_choice_beer)

func _choice_beer(_i: int) -> void:
	_stage_birthday_line("Akkor egy szülinapi korsó rendel. Remélem első a sok közül.")

func _stage_birthday_line(prompt: String) -> void:
	dialogue_ui.show_dialogue(
		"Pultos",
		prompt,
		pultos_portrait,
		[
			{"label": "Tessék?"},
			{"label": "Honnan tudod ezt?"},
			{"label": "Itt a falnak is füle van."},
		]
	)
	_connect_choice_once(_choice_birthday_react)

func _choice_birthday_react(i: int) -> void:
	match i:
		0:
			_stage_volunteer_info("Mindent tudok az önkéntesekről.")
		1:
			_stage_volunteer_info("Mindent tudok az önkéntesekről.")
		2:
			_stage_after_wall_ears()

func _stage_after_wall_ears() -> void:
	dialogue_ui.show_dialogue(
		"Pultos",
		"„Aha.”\n„Ez egy kicsi hely.”\nEgy pillanatra visszanéz a pult mögé, aztán megint rád.\n„De nem ezért mondtam.”",
		pultos_portrait,
		[
			{"label": "Hanem miért mondtad?"},
			{"label": "Oké. Csak mondd."},
			{"label": "Jó, hagyjuk."},
		]
	)
	_connect_choice_once(_choice_after_wall_ears)

func _choice_after_wall_ears(i: int) -> void:
	match i:
		0:
			_stage_volunteer_info("Mindent tudok az önkéntesekről.")
		1:
			_stage_volunteer_info("Mindent tudok az önkéntesekről.")
		2:
			_stage_volunteer_info("Mindent tudok az önkéntesekről.")

# -------------------------------------------------
# Volunteer info -> straight to reward (no preface menu)
# -------------------------------------------------
func _stage_volunteer_info(line: String) -> void:
	dialogue_ui.show_dialogue(
		"Pultos",
		line,
		pultos_portrait,
		[
			{"label": "Ez most… komoly?"},
			{"label": "Oké. Akkor mi lesz?"},
			{"label": "Jó, értem."},
		]
	)
	_connect_choice_once(_choice_volunteer_info)

func _choice_volunteer_info(_i: int) -> void:
	await _grant_reward()

# -------------------------------------------------
# Reward (FIXED: wait for fresh E before continuing)
# -------------------------------------------------
func _grant_reward() -> void:
	if interaction_locked:
		return
	interaction_locked = true

	has_reward = true
	GameState.unlock_bank_center = true

	dialogue_ui.show_dialogue(
		"Pultos",
		"„Ez most ingyen volt, és tessék itt egy kedvezmény token máskorra.\nNe vitázz, a közös jattos üvegből van, nem tőlem személyesen, nyugi.\n\nJa, amúgy a többiek ezt adták ide a feminista fesztivál után, hogy a zsebedből esett ki.\n*felmutat egy kettétört beléptetőkártyát*\nGondolom valami irodás cucc, lehet újat kellene csináltatnod.”",
		pultos_portrait,
		[]
	)

	# Let E finish the typewriter, then require a fresh E to close (so player can actually read).
	await _close_after_fresh_e()

	await _play_item_get_sequence(drink_token_icon)

	if pultos_eicon:
		pultos_eicon.visible = false

	# Enable exit prompt after reward
	if exit_eicon:
		exit_eicon.visible = true

	player.set_can_move(true)
	interaction_locked = false

# -------------------------------------------------
# Item get sequence (same as corridor)
# -------------------------------------------------
func _play_item_get_sequence(texture: Texture2D) -> void:
	if fade_rect == null or item_get_overlay == null:
		push_error("Aurora: Missing fade_rect / item_get_overlay")
		return
	if texture == null:
		push_error("Aurora: Reward texture is null")
		return

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

	player.set_can_move(false)

	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)
	icon.scale = Vector2(1.0, 1.0)

	var t := create_tween()
	t.set_pause_mode(Tween.TWEEN_PAUSE_PROCESS)
	t.tween_property(fade_rect, "modulate:a", 1.0, 0.25).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_OUT)
	await t.finished

	var t2 := create_tween()
	t2.set_pause_mode(Tween.TWEEN_PAUSE_PROCESS)

	t2.tween_property(icon, "modulate:a", 1.0, 0.18).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_OUT)
	t2.parallel().tween_property(icon, "scale", Vector2(1.12, 1.12), 0.18).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_OUT)
	t2.tween_property(icon, "scale", Vector2(1.0, 1.0), 0.18).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN)

	t2.tween_property(icon, "scale", Vector2(1.16, 1.16), 0.20).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_OUT)
	t2.tween_property(icon, "scale", Vector2(1.0, 1.0), 0.20).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN)

	t2.tween_interval(0.25)
	t2.tween_property(icon, "modulate:a", 0.0, 0.20).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN)
	await t2.finished

	icon.visible = false
	item_get_overlay.visible = false

	var t3 := create_tween()
	t3.set_pause_mode(Tween.TWEEN_PAUSE_PROCESS)
	t3.tween_property(fade_rect, "modulate:a", 0.0, 0.25).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN)
	await t3.finished

	fade_rect.visible = false
	player.set_can_move(true)
Editor is loading...
Leave a Comment