79 lines
2.1 KiB
GDScript
79 lines
2.1 KiB
GDScript
extends CharacterBody3D
|
|
|
|
@export var have_dialog : bool = false
|
|
@export var alrdy_talking : bool = false
|
|
@export var can_wander : bool = false
|
|
|
|
@onready var sprite_label: Sprite3D = $Sprite3D
|
|
@onready var anim_player: AnimationPlayer = $character/AnimationPlayer
|
|
|
|
# navigation
|
|
@export var dest_array:Array[Marker3D]
|
|
@onready var navigation_agent: NavigationAgent3D = $NavigationAgent3D
|
|
@onready var idle_timer: Timer = $Timer
|
|
enum NPCSTATE {
|
|
IDLE,
|
|
WALKING
|
|
}
|
|
var cur_state : NPCSTATE
|
|
var cur_destination: Marker3D
|
|
var speed = 2
|
|
|
|
func _ready() -> void:
|
|
sprite_label.visible = false
|
|
if alrdy_talking:
|
|
await get_tree().create_timer( randf_range(1.0, 2.5) ).timeout
|
|
anim_player.play("RootAction")
|
|
|
|
if can_wander:
|
|
_set_state( NPCSTATE.IDLE )
|
|
|
|
func _on_timer_timeout() -> void:
|
|
decide_next_state()
|
|
|
|
func _set_state(new_state:NPCSTATE):
|
|
cur_state = new_state
|
|
match cur_state:
|
|
NPCSTATE.IDLE:
|
|
idle_timer.start( randf_range(1, 2) )
|
|
anim_player.play("RootAction", -1, 10)
|
|
NPCSTATE.WALKING:
|
|
anim_player.play("RootAction_001", -1, 2.5)
|
|
|
|
|
|
func _physics_process(delta: float) -> void:
|
|
match cur_state:
|
|
NPCSTATE.IDLE:
|
|
pass
|
|
NPCSTATE.WALKING:
|
|
var next_path_pos:Vector3 = navigation_agent.get_next_path_position()
|
|
var new_vel : Vector3 = global_position.direction_to( next_path_pos ) * speed
|
|
velocity = new_vel
|
|
var look_at_target : Vector3 = Vector3( next_path_pos.x, global_position.y, next_path_pos.z )
|
|
if not global_position.is_equal_approx( look_at_target ):
|
|
look_at( look_at_target )
|
|
|
|
move_and_slide()
|
|
|
|
|
|
|
|
func decide_next_state():
|
|
if cur_state == NPCSTATE.IDLE:
|
|
cur_destination = dest_array.pick_random()
|
|
navigation_agent.target_position = cur_destination.global_position
|
|
_set_state( NPCSTATE.WALKING )
|
|
|
|
func _on_area_3d_body_entered(body: Node3D) -> void:
|
|
if have_dialog and body.is_in_group("player"):
|
|
sprite_label.visible = true
|
|
body.set_dialog_mode( global_position )
|
|
|
|
func _on_area_3d_body_exited(body: Node3D) -> void:
|
|
if have_dialog and body.is_in_group("player"):
|
|
sprite_label.visible = false
|
|
body.set_dialog_mode()
|
|
|
|
|
|
func _on_navigation_agent_3d_navigation_finished() -> void:
|
|
_set_state( NPCSTATE.IDLE )
|