I'm trying to create bullet hell patterns for a shooter. The bullets are supposed to fly in a spiral pattern around the boss. However, that only works when the boss is at position (0,0,0). As soon as it deviates, the bullets will all fly in the direction of the deviation. So if it is at (1,0,0), the bullets all incline towards that direction. It gets worse the further away the boss is from the center.
Can anyone tell me how I can remedy this? I can't figure it out.
Here is a video that illustrates the issue - I moved the boss placeholder around manually

This is my code for a bullet (currently doesn't have collision yet):

extends Spatial

var speed = 2

func _process(delta):
     self.transform.origin += self.transform.origin * speed * delta

Note: I tried to use translate(Vector3(1, 0, 0) * delta) here, but then it ignores where the object is facing.

This is my code for the bullet spawners:

extends Spatial

const radius = 0.25
const bullet_scene = preload("res://3d/boss_shot.tscn")
export (float) var rotate_speed = 100.0
export (float) var shooter_timer_wait_time = 0.05
export (int) var spawn_point_count = 4
onready var shoot_timer = $ShootTimer
onready var rotator = $Rotator

func _ready():
	var step = 2 * PI / spawn_point_count
	
	for i in range(spawn_point_count):
		var spawn_point = Spatial.new()
		var pos = Vector3(radius, 0, 0)
		var rot = step * i
		spawn_point.transform.origin = pos
		spawn_point.transform = spawn_point.transform.rotated(Vector3(0,0,1), rot)

		rotator.add_child(spawn_point)
		
	shoot_timer.wait_time = shooter_timer_wait_time
	shoot_timer.start()

func _process(delta):
	var new_rotation = rotator.transform.basis.get_euler().z + deg2rad(rotate_speed * delta)
	new_rotation = fmod(new_rotation, 2 * PI)  #ensure rotation is within 0 to 2*PI (360 degrees)
	var new_basis = Basis(Vector3(0, 0, 1), new_rotation)
	rotator.transform.basis = new_basis
	
	#update child objects' positions and orientations, it should do that automatically, but doesn't
	#I have NO idea why this is necessary. Bug because they're being added through code?
	for s in rotator.get_children():
		var spawn_point = s as Spatial  #assuming the child nodes are Spatial nodes
		var rotated_pos = spawn_point.transform.origin.rotated(Vector3(0,0,1), deg2rad(rotate_speed*2 * delta))
		
		spawn_point.transform.origin = rotated_pos
		spawn_point.transform.basis = new_basis

func _on_ShootTimer_timeout():
	var step = 2 * PI / spawn_point_count
	var i = 0	
	for s in rotator.get_children():
		var rot = step * i
		var bullet = bullet_scene.instance()
		get_tree().root.add_child(bullet)
		
		var spawn_point_rotation = s.transform.basis.get_euler().z  #get rotation in radians of spawn_point
		var rotator_rotation = rotator.transform.basis.get_euler().z  #get rotation in radians of rotator
		var total_rotation_degrees = rad2deg(spawn_point_rotation + rotator_rotation)
		var rotated_transform = bullet.transform.rotated(Vector3(0,0,1), rot)
		
		bullet.transform.origin = s.global_transform.origin
		bullet.transform.basis = Basis(Vector3(0, 0, 1), deg2rad(total_rotation_degrees))  #rotate around Z-axis