2019-10-28 01:21:41 +01:00
|
|
|
extends Path
|
|
|
|
|
|
|
|
var _current_nav_path: PoolVector3Array
|
|
|
|
|
2019-10-30 00:45:37 +01:00
|
|
|
var _current_nav_index
|
|
|
|
var _current_path_index
|
2019-10-28 01:21:41 +01:00
|
|
|
|
|
|
|
var _arrived_distance_threshold = 0.1
|
|
|
|
|
|
|
|
export(float) var speed = 8
|
|
|
|
export(NodePath) var body_nodepath
|
|
|
|
|
|
|
|
var navigation: Navigation
|
2019-11-11 10:24:29 +01:00
|
|
|
var body: NPC
|
2019-10-28 01:21:41 +01:00
|
|
|
|
|
|
|
|
2019-10-30 00:45:37 +01:00
|
|
|
# React to the NodeGroupNotifier of the Navigation
|
|
|
|
func set_navigator_node(navigation_node: Navigation):
|
|
|
|
navigation = navigation_node as Navigation
|
|
|
|
|
|
|
|
# Our path could change significantly with the Navigation node, so restart
|
|
|
|
_restart_navigation()
|
|
|
|
|
|
|
|
|
2019-10-28 01:21:41 +01:00
|
|
|
func _ready():
|
2019-10-30 00:45:37 +01:00
|
|
|
_restart_navigation()
|
|
|
|
|
|
|
|
|
|
|
|
# Reset the body to the starting position and start the navigation freshly
|
|
|
|
func _restart_navigation():
|
|
|
|
_current_nav_index = 0
|
|
|
|
_current_path_index = 1
|
|
|
|
|
2019-10-28 01:21:41 +01:00
|
|
|
body = get_node(body_nodepath) as KinematicBody
|
|
|
|
|
|
|
|
# Initialize the position
|
2019-11-11 10:44:20 +01:00
|
|
|
body.set_position(curve.get_point_position(0))
|
2019-10-28 01:21:41 +01:00
|
|
|
|
|
|
|
# Get the first goal
|
|
|
|
_get_new_navigation()
|
|
|
|
|
|
|
|
|
|
|
|
func _process(delta):
|
2019-11-11 10:44:20 +01:00
|
|
|
# Use either the NPC's current target or the paths next goal
|
|
|
|
var current_goal = body.current_target if body.current_target else _get_current_goal()
|
2019-10-28 01:21:41 +01:00
|
|
|
|
|
|
|
# Move towards the current goal
|
2019-11-11 10:16:03 +01:00
|
|
|
var direction: Vector3 = (current_goal - _get_body_position())
|
|
|
|
var direction_normalized: Vector3 = direction.normalized()
|
2019-10-28 01:21:41 +01:00
|
|
|
|
2019-11-11 10:44:20 +01:00
|
|
|
body.move_towards(direction_normalized * speed)
|
2019-10-28 01:21:41 +01:00
|
|
|
|
|
|
|
# Look towards that goal as well
|
2019-11-11 10:16:03 +01:00
|
|
|
# Avoid look_at if we're already (almost) there, since that'd be an invalid look direction
|
|
|
|
# that can be identical to the up vector (which causes problems)
|
|
|
|
if direction.length() > 0.5:
|
|
|
|
body.look_at(_get_body_position() + direction_normalized, Vector3.UP)
|
2019-10-28 01:21:41 +01:00
|
|
|
|
|
|
|
|
|
|
|
# Returns the point we should currently be moving towards
|
|
|
|
func _get_current_goal():
|
|
|
|
# If we haven't arrived at the current goal, then that's still the goal
|
|
|
|
if _current_nav_path[_current_nav_index].distance_to(_get_body_position()) > _arrived_distance_threshold:
|
|
|
|
return _current_nav_path[_current_nav_index]
|
|
|
|
|
|
|
|
if _current_nav_index < _current_nav_path.size() - 1:
|
|
|
|
# We still have points left in the current navigation -> use the next one
|
2019-11-11 10:16:03 +01:00
|
|
|
Logger.trace("Using next point of current navigation")
|
2019-10-28 01:21:41 +01:00
|
|
|
_current_nav_index += 1
|
|
|
|
else:
|
|
|
|
# We're done following the current navigation to the next path point
|
|
|
|
if _current_path_index < curve.get_point_count() - 1:
|
|
|
|
# We still have points left in the path -> use the next one and generate the navigation to it
|
2019-11-11 10:16:03 +01:00
|
|
|
Logger.trace("Generating navigation to the next path point")
|
2019-10-28 01:21:41 +01:00
|
|
|
_current_path_index += 1
|
|
|
|
else:
|
|
|
|
# We're done following the path -> Go back to the start
|
2019-11-11 10:16:03 +01:00
|
|
|
Logger.trace("Returning to the start of the path")
|
2019-10-28 01:21:41 +01:00
|
|
|
_current_nav_index = 0
|
|
|
|
_current_path_index = 0
|
|
|
|
|
|
|
|
_get_new_navigation()
|
|
|
|
|
|
|
|
return _current_nav_path[_current_nav_index]
|
|
|
|
|
|
|
|
|
|
|
|
# Reset the navigation and build a new one for the current path index
|
|
|
|
func _get_new_navigation():
|
|
|
|
_current_nav_index = 0
|
|
|
|
|
|
|
|
var goal = curve.get_point_position(_current_path_index)
|
2019-10-30 00:45:37 +01:00
|
|
|
|
|
|
|
if navigation:
|
|
|
|
_current_nav_path = navigation.get_simple_path(_get_body_position(), goal)
|
|
|
|
else:
|
|
|
|
_current_nav_path = PoolVector3Array([goal])
|
2019-10-28 01:21:41 +01:00
|
|
|
|
|
|
|
|
|
|
|
# Return the current position of the body we're controlling
|
|
|
|
func _get_body_position():
|
|
|
|
return body.transform.origin
|