SchildDerStaerke/scripts/interaction_manager.gd

68 lines
1.7 KiB
GDScript

extends Node2D
const ACTION_INTERACT := "interact"
@onready var player: Player = get_tree().get_first_node_in_group("player")
@onready var label: Label = $Label
var base_prompt_text: String = ""
var areas_in_range: Array[InteractionArea] = []
var can_interact: bool = true
func _ready() -> void:
base_prompt_text = _build_base_prompt_text()
label.hide()
func register_area(area: InteractionArea) -> void:
areas_in_range.push_back(area)
func unregister_area(area: InteractionArea) -> void:
var index := areas_in_range.find(area)
if index != -1:
areas_in_range.remove_at(index)
func _process(_delta: float) -> void:
if not can_interact:
label.hide()
return
var nearest := _get_nearest_area()
if nearest:
label.text = "%s%s" % [base_prompt_text, nearest.action_name]
label.show()
else:
label.hide()
func _input(event: InputEvent) -> void:
if not (can_interact and event.is_action_pressed(ACTION_INTERACT)):
return
var nearest := _get_nearest_area()
if nearest:
can_interact = false
label.hide()
await nearest.interact.call()
can_interact = true
func _get_nearest_area() -> InteractionArea:
if areas_in_range.is_empty():
return null
areas_in_range.sort_custom(self._compare_by_distance_to_player)
return areas_in_range[0]
func _compare_by_distance_to_player(a: InteractionArea, b: InteractionArea) -> bool:
var d1 := player.global_position.distance_to(a.global_position)
var d2 := player.global_position.distance_to(b.global_position)
return d1 < d2
func _build_base_prompt_text() -> String:
var events := InputMap.action_get_events(ACTION_INTERACT)
if events.is_empty():
return "Interact with "
return "%s to " % [events[0].as_text()]