extends StaticBody3D @export var profile: NpcProfile @export var profile_id: StringName = &"" @onready var mesh: MeshInstance3D = $Mesh @onready var label: Label3D = $Label @onready var prompt: Label3D = $Prompt @onready var interact_area: Area3D = $InteractArea var nearby_player: Node = null func _enter_tree() -> void: set_multiplayer_authority(1) func _ready() -> void: add_to_group("npc") if profile == null and profile_id != &"": var path := "res://resources/npcs/%s.tres" % str(profile_id) if ResourceLoader.exists(path): profile = load(path) as NpcProfile if profile == null: profile = NpcProfile.new() profile.display_name = "Villager" profile.lore = "A simple villager." profile.personality = "Friendly, curious." profile.fallback_text = "Hello there!" label.text = profile.display_name prompt.visible = false if profile.color != Color.WHITE: var mat: StandardMaterial3D = StandardMaterial3D.new() mat.albedo_color = profile.color mesh.material_override = mat interact_area.body_entered.connect(_on_player_near) interact_area.body_exited.connect(_on_player_left) func _process(_delta: float) -> void: if nearby_player and nearby_player.is_multiplayer_authority(): prompt.visible = true if Input.is_action_just_pressed("interact"): EventBus.dialog_opened.emit(nearby_player, self) else: prompt.visible = false func _on_player_near(body: Node) -> void: if body.is_in_group("player"): if body.is_multiplayer_authority(): nearby_player = body func _on_player_left(body: Node) -> void: if body == nearby_player: nearby_player = null