Need help running physic in child for parent velocity

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By shipx7

Thanks for any help, sorry if its too long I wanted to provide everything useful.
I am trying to incorporate a grapplehook into my game with a smooth swinging pendulum. I have code to shoot the grapplehook and have code for a pendulum, each of which are their own scenes for compartmentalization (brought together. So Player has a GrappleHook which has a Pendulum each with its own script).
My problem comes in with trying to move my parent based on code in its grand child’s func process_velocity(delta).

To paint a picture of what Im wanting my code to do, the player should shoot the grapplehook (which is a child) and while hooked is affected by the pendulum physics (which is a child of the grapplehook). In my mind’s eye I see calling a func and getting back a velocity which is applied to my players current velocity, but Im not sure how get that to work properly. The pendulum needs to know where the pivot and the pendulum are located

What I want is to have my player’s script free of all of the coding for the grapplehook (except necessities like calling a shoot func and whatnot), and the grapplehook to be reasonably free of the pendulum code so it can be modular in how it functions.
Other grapplehook tutorials have the move code pretty much entirely in the player, but Im not fond of that since I figure it would dampen variety later on.

Here is the pendulum code. As a scene itself it shows what it does and works. _ready func and down is simply to make it work standalone as a test. (if you copy it, the script is attached to a position2d node which is a child of a node2d. make sure the position2d node is not on top of the node2d)

extends Position2D
class_name Pendulum

var pivot_point: Vector2 						#Point pedulum rotates around
export (Vector2) var end_position = Vector2()	#Pendulum itself
var arm_length: float
var angle										#Get angle between position + add godot angle offset

export (float) var gravity = 0.4 * 60
export (float) var damping = 0.995				#Arbitrary dampening force (slows down each swing)

var angular_velocity = 0.0						#Speed of rotation
var angular_acceleration = 0.0					#Causes speed to increase or decrease?

func set_start_position(start_pos:Vector2, end_pos:Vector2):
	pivot_point = start_pos
	end_position = end_pos
	arm_length = Vector2.ZERO.distance_to(end_position - pivot_point)
	angle = Vector2.ZERO.angle_to(end_position - pivot_point) - deg2rad(-90) #Angle of pivot point to end_position, corrected for Godot's default angle facing right
	angular_velocity = 0.0
	angular_acceleration = 0.0

func _ready()->void:
	set_start_position(global_position, end_position)

func process_velocity(delta:float)->void:
	angular_acceleration = ((-gravity*delta) / arm_length) * sin(angle) #Caluclate acceleration (see: http://www.myphysicslab.com/pendulum1.html)
	angular_velocity += angular_acceleration							#Increment velocity
	angular_velocity *= damping											#Arbitrary damping
	angle += angular_velocity											#Increment angle
	end_position = pivot_point + Vector2(arm_length*sin(angle), arm_length*cos(angle))
	print(end_position)

func add_angular_velocity(force:float)->void:
	angular_velocity += force


func game_input()->void:
	var dir:float = 0
	if Input.is_action_just_pressed("ui_right"):
		dir += 1
	elif Input.is_action_just_pressed("ui_left"):
		dir -= 1
	add_angular_velocity(dir * 0.02)					#give a kick to the swing

func _physics_process(delta)->void:
	game_input()

	process_velocity(delta)
	update()

func _draw()->void:
	draw_line(Vector2.ZERO, end_position - pivot_point, Color.white, 1.0, false)
	draw_circle(end_position - pivot_point, 3, Color.red)

Here is my grapplehook code, which is largely a mess since Ive been testing and following rabbitholes.

onready var links = $Links		# A slightly easier reference to the links
onready var hookTip = $Tip
onready var pendulum = $Pendulum/Position2D

var direction := Vector2(0,0)	# The direction in which the chain was shot
var tip := Vector2(0,0)			# The global position the tip should be in
								# We use an extra var for this, because the chain is 
								# connected to the player and thus all .position
								# properties would get messed with when the player
								# moves.

const SPEED = 10	# The speed with which the chain moves

var flying = false	# Whether the chain is moving through the air
var hooked = false	# Whether the chain has connected to a wall

# shoot() shoots the chain in a given direction
func shoot(dir: Vector2) -> void:
	direction = dir.normalized()	# Normalize the direction and save it
	flying = true					# Keep track of our current scan
	tip = self.global_position		# reset the tip position to the player's position

# release() the chain
func release() -> void:
	flying = false	# Not flying anymore	
	hooked = false	# Not attached anymore

# Every graphics frame we update the visuals
func _process(_delta: float) -> void:
	self.visible = flying or hooked	# Only visible if flying or attached to something
	if not self.visible:
		return	# Not visible -> nothing to draw
	var tip_loc = to_local(tip)	# Easier to work in local coordinates
	# We rotate the links (= chain) and the tip to fit on the line between self.position (= origin = player.position) and the tip
	links.rotation = self.position.angle_to_point(tip_loc) - deg2rad(90)
	hookTip.rotation = self.position.angle_to_point(tip_loc) - deg2rad(90)
	links.position = tip_loc						# The links are moved to start at the tip
	links.region_rect.size.y = tip_loc.length()		# and get extended for the distance between (0,0) and the tip
	

# Every physics frame we update the tip position
func _physics_process(_delta: float) -> void:
	hookTip.global_position = tip	# The player might have moved and thus updated the position of the tip -> reset it
	if flying:
		# `if move_and_collide()` always moves, but returns true if we did collide
		if hookTip.move_and_collide(direction * SPEED):
			hooked = true	# Got something!
			flying = false	# Not flying anymore
	tip = hookTip.global_position	# set `tip` as starting position for next frame
	pendulum.global_position = tip
	pendulum.end_position = self.position

TL:DR How do I access/run physics code from a (grand)child on the grandparent