class_name Adventurer extends CharacterBody2D const popup_template = preload("res://profile_popup.tscn") var profile_popup @onready var bt_player : BTPlayer = $BTPlayer @export var movement_speed : float = 400.0 @onready var movement_target_position : Vector2 = global_position @onready var nav_agent : NavigationAgent2D = $NavigationAgent2D var data : AdventurerData = null var interaction_target = null var last_position : Vector2 = Vector2.ZERO var stuck : bool = false var stuck_time_remaining : float = 0 @onready var bubble : SpeechBubble = $SpeechBubble @export var interaction_range : float = 75 @export var stop_range : float = 25 signal navigation_finished() signal navigation_failed() func _ready() -> void: nav_agent.navigation_finished.connect(_on_nav_agent_finished) pass func _physics_process(delta: float) -> void: if nav_agent.is_navigation_finished(): if interaction_target: try_interact(interaction_target) #If they have an interaction target within range #clear the target #try_interact return var curr_pos: Vector2 = global_position var next_path_pos: Vector2 = nav_agent.get_next_path_position() velocity = curr_pos.direction_to(next_path_pos) * movement_speed move_and_slide() #If they virtually didn't move if !stuck: if (global_position - last_position).length_squared() < 5: stuck = true stuck_time_remaining = 1 else: if stuck_time_remaining > 0: stuck_time_remaining -= delta if stuck_time_remaining <= 0: nav_agent.target_position = global_position navigation_failed.emit() last_position = global_position func approach(pos : Vector2) -> void: stuck = false var rid = get_world_2d().get_navigation_map() var point : Vector2 = NavigationServer2D.map_get_closest_point(rid, pos) set_movement_target(point) func approach_and_interact(obj : Interactable) -> void: set_movement_target(obj.global_position) nav_agent.target_desired_distance = interaction_range - 5 interaction_target = obj func try_interact(obj : Interactable) -> void: var df = obj.global_position - global_position if df.length() > interaction_range: approach_and_interact(obj) else: interact(obj) interaction_target = null func interact(obj : Interactable) -> void: obj.interact(self) func set_movement_target(target : Vector2) -> void: nav_agent.target_position = target func show_speech_bubble(bubble_type : String) -> void: bubble.try_show_speech(bubble_type) func _on_nav_agent_finished() -> void: navigation_finished.emit() func _on_mouse_entered() -> void: profile_popup = popup_template.instantiate() add_child(profile_popup) profile_popup.setup(data.name, data.level, data.job, "Nothing") func _on_mouse_exited() -> void: profile_popup.queue_free()