68 lines
1.7 KiB
GDScript
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()]
|