extends RigidBody

var player_id : int

var mouse_over_player : RigidBody = null

var thrust_plan : Plan = Plan.new()
var weapons_plan : Plan = Plan.new()
var is_local : bool = false
var running_plan : bool = false
var using_full_plan : bool = false
var was_running_plan : bool = false
var plan_time : float = 0.0
var last_translation : Vector3 = get_translation()
var last_rotation : Vector3 = get_rotation()
var initial_translation : Vector3 = get_translation()
var initial_rotation : Vector3 = get_rotation()
var initial_velocity : Vector3 = Vector3(0,0,0)
var initial_rotational_velocity : Vector3 = Vector3(0,0,0)
var enable_physics : bool = false

var end_translation : Vector3 = Vector3.ZERO
var end_rotation : Vector3 = Vector3.ZERO
var end_linear_velocity : Vector3 = Vector3.ZERO
var end_rotational_velocity : Vector3 = Vector3.ZERO

var round_time : float = 0.0
var turn_counter : int = 0
var end_of_round_translation : Vector3 = get_translation()
var end_of_round_rotation : Vector3 = get_rotation()

var time_of_death : float = -1
var is_alive : bool = true
var health : float = 100.0
var end_health : float = 100.0
var energy : float = 100.0
var end_energy : float = 100.0

var players_in_firing_arc = []

onready var arrow_obj : Spatial = $ArrowContainer
onready var arrow_scale_obj : Spatial = $ArrowContainer/ArrowScaleContainer
onready var rotate_arrow_obj : Spatial = $RotateArrowContainer
onready var rotate_arrow_scale_obj : Spatial = $RotateArrowContainer/RotateArrowScaleContainer

onready var turn_end_banner : TextureRect = $TurnEndBanner

onready var health_bar : ColorRect = $StatusPanel/HealthBarContainer/HealthBar

const TIME_STEP : float = 0.01
const MAX_LIN_THRUST : float = 1.0
const MAX_ROT_THRUST : float = 0.01

const BASE_DPS : float = 300.0
const BASE_ENERGY_USAGE : float = 75.0
const BASE_ENERGY_REGEN : float = 150.0
const BASE_OVERCHARGE_DAMAGE : float = 5.0
const OOB_DAMAGE : float = 100.0

func init(id : int, color : Color) -> void:
	player_id = id
	last_rotation = get_rotation()
	last_translation = get_translation()
	initial_rotation = get_rotation()
	initial_translation = get_translation()
	enable_physics = true
	get_parent().get_parent().console_print("Player is set to local? " + String(is_local))
	if is_local:
		$MainPanel.visible = true
		$ThrustPanel.visible = true
		$WeaponsPanel.visible = true
		$InfoPanel.visible = true
		$StatusPanel.visible = true
	set_colors(color)

func send_thrust_plan() -> void:
	for element in thrust_plan.current_elements:
		get_parent().get_parent().console_print('Sending data = ' + String(element.time) + String(element.linear_thrust) + String(element.rotational_thrust))
		rpc_id(1, "add_thrust_element", element.time, element.linear_thrust, element.rotational_thrust)

func send_weapons_plan() -> void:
	for element in weapons_plan.current_elements:
		get_parent().get_parent().console_print('Sending data = ' + String(element.time) + String(element.firing))
		rpc_id(1, "add_weapons_element", element.time, element.firing)

remote func add_thrust_element(time: float, linear_thrust : Vector3, rotational_thrust : Vector3) -> void:
	if is_local:
		return
	var element : ThrustElement = ThrustElement.new()
	element.time = time
	element.linear_thrust = linear_thrust
	element.rotational_thrust = rotational_thrust
	get_parent().get_parent().console_print(String(is_local) + ": Adding thrust element with the following params: time = " + String(time) + ", lin = " + String(linear_thrust) + ", rot = " + String(rotational_thrust) + ".")
	thrust_plan.add_element(element)

remote func add_weapons_element(time : float, firing : bool) -> void:
	if is_local:
		return
	var element : WeaponsElement = WeaponsElement.new()
	element.time = time
	element.firing = firing
	get_parent().get_parent().console_print(String(is_local) + ": Adding weapons element with the following params: time = " + String(time) + ", firing = " + String(firing))
	weapons_plan.add_element(element)

remote func r_end_turn(
			r_time_of_death : float,
			r_end_translation : Vector3,
			r_end_rotation : Vector3,
			r_end_linear_velocity : Vector3,
			r_end_rotational_velocity : Vector3,
			r_end_health : float,
			r_end_energy : float) -> void:
	self._on_PlayButton_pressed()
	time_of_death = r_time_of_death
	end_translation = r_end_translation
	end_rotation = r_end_rotation
	end_linear_velocity = r_end_linear_velocity
	end_rotational_velocity = r_end_rotational_velocity
	end_health = r_end_health
	end_energy = r_end_energy
	turn_counter += 1
	if is_local:
		$MainPanel/EndTurnButton.disabled = false
		$MainPanel/TimeBar.value = 0
		$TurnEndBanner.visible = true
		$TurnEndBanner/AnimationPlayer.play()
		return
	thrust_plan.new_turn()
	weapons_plan.new_turn()

func _on_TimeBar_value_changed(value : float) -> void:
	var min_time : float = thrust_plan.current_time()
	#get_parent().get_parent().console_print(String(is_local) + ": Current plan time is " + String(min_time))
	if value <= min_time:
		$MainPanel/TimeBar.value = min_time

func _on_AddButton_pressed() -> void:
	var new_thrust_element : ThrustElement = ThrustElement.new()
	new_thrust_element.linear_thrust = get_linear_vector()
	new_thrust_element.rotational_thrust = get_rotational_vector()
	new_thrust_element.time = $MainPanel/TimeBar.value - thrust_plan.current_time()
	if (thrust_plan.add_element(new_thrust_element)):
		get_parent().get_parent().console_print(String(is_local) + ": Added thrust element with " + String(new_thrust_element.time) + String(new_thrust_element.rotational_thrust) + String(new_thrust_element.linear_thrust))
	else:
		get_parent().get_parent().console_print(String(is_local) + ": Failed to add thrust element")
	var new_weapons_element : WeaponsElement = WeaponsElement.new()
	new_weapons_element.firing = $WeaponsPanel/WeaponsSwitch.pressed
	new_weapons_element.time = $MainPanel/TimeBar.value - weapons_plan.current_time()
	if (weapons_plan.add_element(new_weapons_element)):
		get_parent().get_parent().console_print(String(is_local) + ": Added weapons element with " + String(new_weapons_element.firing))
	else:
		get_parent().get_parent().console_print(String(is_local) + ": Failed to add weapons element")

func _on_RemoveButton_pressed() -> void:
	thrust_plan.remove_last_element()
	weapons_plan.remove_last_element()

func _on_ClearButton_pressed() -> void:
	thrust_plan.remove_all_elements()
	weapons_plan.remove_all_elements()

func _on_EndTurnButton_pressed() -> void:
	fix_plans()
	$MainPanel/EndTurnButton.disabled = true
	send_thrust_plan()
	send_weapons_plan()
	rpc_id(1, "end_turn")
	thrust_plan.new_turn()
	weapons_plan.new_turn()
	round_time += 5

func _update_arrow() -> void:
	var linear_thrust : Vector3 = get_linear_vector()
	var linear_thrust_normalized : Vector3 = linear_thrust.normalized()
	var linear_thrust_magnitude : float = linear_thrust.length()
	var phi : float 
	if linear_thrust_normalized.x == 0 and linear_thrust_normalized.z == 0:
		phi = PI/2
	else:
		phi = asin(linear_thrust_normalized.x / sqrt(pow(linear_thrust_normalized.x, 2) + pow(linear_thrust_normalized.z,2)))
		
	if linear_thrust_normalized.z < 0:
		phi = PI - phi
	var theta : float = -asin(linear_thrust_normalized.y)
	arrow_obj.rotation = Vector3(0,0,0)
	arrow_obj.rotate(Vector3(1,0,0), theta)
	arrow_obj.rotate(Vector3(0,1,0), phi)
	arrow_scale_obj.scale = Vector3(linear_thrust_magnitude, linear_thrust_magnitude, linear_thrust_magnitude)

func _update_rotate_arrow() -> void:
	var rotational_thrust : Vector3 = get_rotational_vector()
	var rotational_thrust_normalized : Vector3 = rotational_thrust.normalized()
	var rotational_thrust_magnitude : float = rotational_thrust.length()
	var phi : float 
	if rotational_thrust_normalized.x == 0 and rotational_thrust_normalized.z == 0:
		phi = PI/2
	else:
		phi = asin(rotational_thrust_normalized.x / sqrt(pow(rotational_thrust_normalized.x, 2) + pow(rotational_thrust_normalized.z,2)))
		
	if rotational_thrust_normalized.z < 0:
		phi = PI - phi
	var theta : float = -asin(rotational_thrust_normalized.y)
	rotate_arrow_obj.rotation = Vector3(0,0,0)
	rotate_arrow_obj.rotate(Vector3(1,0,0), theta)
	rotate_arrow_obj.rotate(Vector3(0,1,0), phi)
	rotate_arrow_scale_obj.scale = Vector3(rotational_thrust_magnitude, rotational_thrust_magnitude, rotational_thrust_magnitude)*100

func get_linear_vector() -> Vector3:
	return Vector3($ThrustPanel/XLin.value, -$ThrustPanel/YLin.value, $ThrustPanel/ZLin.value) * MAX_LIN_THRUST

func get_rotational_vector() -> Vector3:
	return Vector3($ThrustPanel/XRot.value, -$ThrustPanel/YRot.value, $ThrustPanel/ZRot.value) * MAX_ROT_THRUST

func _on_XLin_value_changed(value : float) -> void:
	self._update_arrow()
	if get_linear_vector().length() < 1.0:
		return
	$ThrustPanel/XLin.value = sign($ThrustPanel/XLin.value) * \
		sqrt(1 - pow($ThrustPanel/YLin.value, 2) - pow($ThrustPanel/ZLin.value, 2))

func _on_XRot_value_changed(value : float) -> void:
	self._update_rotate_arrow()
	if get_rotational_vector().length() < 1.0:
		return
	$ThrustPanel/XRot.value = sign($ThrustPanel/XRot.value) * \
		sqrt(1 - pow($ThrustPanel/YRot.value, 2) - pow($ThrustPanel/ZRot.value, 2))

func _on_YLin_value_changed(value : float) -> void:
	self._update_arrow()
	if get_linear_vector().length() < 1.0:
		return
	$ThrustPanel/YLin.value = sign($ThrustPanel/YLin.value) * \
		sqrt(1 - pow($ThrustPanel/XLin.value, 2) - pow($ThrustPanel/ZLin.value, 2))

func _on_YRot_value_changed(value : float) -> void:
	self._update_rotate_arrow()
	if get_rotational_vector().length() < 1.0:
		return
	$ThrustPanel/YRot.value = sign($ThrustPanel/YRot.value) * \
		sqrt(1 - pow($ThrustPanel/XRot.value, 2) - pow($ThrustPanel/ZRot.value, 2))

func _on_ZLin_value_changed(value : float) -> void:
	self._update_arrow()
	if get_linear_vector().length() < 1.0:
		return
	$ThrustPanel/ZLin.value = sign($ThrustPanel/ZLin.value) * \
		sqrt(1 - pow($ThrustPanel/YLin.value, 2) - pow($ThrustPanel/XLin.value, 2))

func _on_ZRot_value_changed(value : float) -> void:
	self._update_rotate_arrow()
	if get_rotational_vector().length() < 1.0:
		return
	$ThrustPanel/ZRot.value = sign($ThrustPanel/ZRot.value) * \
		sqrt(1 - pow($ThrustPanel/YRot.value, 2) - pow($ThrustPanel/XRot.value, 2))

func _on_ResetButton_pressed():
	$ThrustPanel/XLin.value = 0
	$ThrustPanel/XRot.value = 0
	$ThrustPanel/YLin.value = 0
	$ThrustPanel/YRot.value = 0
	$ThrustPanel/ZLin.value = 0
	$ThrustPanel/ZRot.value = 0

func _get_current_plan_element(all_elements) -> PlanElement:
	var summed_time : float = 0.0
	for element in all_elements:
		summed_time += element.time
		if summed_time > plan_time:
			return element
	return null

func _get_all_thrust_elements():
	var all_elements = []
	for element in thrust_plan.elements:
		all_elements.append(element)
	for element in thrust_plan.current_elements:
		all_elements.append(element)
	return all_elements

func _get_all_weapons_elements():
	var all_elements = []
	for element in weapons_plan.elements:
		all_elements.append(element)
	for element in weapons_plan.current_elements:
		all_elements.append(element)
	return all_elements

func _physics_process(delta : float) -> void:
	if !enable_physics:
		return
	if !running_plan:
		if is_local and was_running_plan:
			get_parent().show_winner()
		$GunContainer/RayCast.visible = false
		arrow_obj.visible = true
		rotate_arrow_obj.visible = true
		disable_all_engine_particles()
		set_translation(last_translation)
		set_rotation(last_rotation)
		was_running_plan = false
		return
	
	if !was_running_plan:
		players_in_firing_arc = $GunContainer/Cone.get_overlapping_bodies()
		if using_full_plan:
			set_linear_velocity(initial_velocity)
			set_angular_velocity(initial_rotational_velocity)
			set_translation(initial_translation)
			set_rotation(initial_rotation)
		else:
			set_linear_velocity(end_linear_velocity)
			set_angular_velocity(end_rotational_velocity)
			set_translation(end_translation)
			set_rotation(end_rotation)
		
	was_running_plan = true
	if time_of_death > 0 and plan_time > time_of_death:
		self.visible = false
		$CollisionShape.disabled = true
		is_alive = false
	else:
		self.visible = true
		$CollisionShape.disabled = false
		is_alive = true
	var all_thrust_elements = _get_all_thrust_elements()
	var current_thrust_element : ThrustElement = _get_current_plan_element(all_thrust_elements)
	if current_thrust_element == null:
		last_translation = get_translation()
		last_rotation = get_rotation()
		running_plan = false
		print("thrust plan set running plan to false")
		return
	arrow_obj.visible = false
	rotate_arrow_obj.visible = false
	add_central_force(self.transform.basis.xform(current_thrust_element.linear_thrust))
	add_torque(self.transform.basis.xform(current_thrust_element.rotational_thrust))
	update_engine_particles(current_thrust_element.linear_thrust, current_thrust_element.rotational_thrust)
	
	var all_weapons_elements = _get_all_weapons_elements()
	var current_weapons_element : WeaponsElement = _get_current_plan_element(all_weapons_elements)
	if current_weapons_element == null:
		$GunContainer/RayCast.visible = false
		running_plan = false
		return
	if current_weapons_element.firing and is_alive:
		_fire_gun(delta)
	elif energy < 100:
		$GunContainer/RayCast.visible = false
		energy += BASE_ENERGY_REGEN * delta
	else:
		$GunContainer/RayCast.visible = false
	
	calculate_other_damage(delta)
	plan_time += delta

func _process(delta : float) -> void:
	_update_battery_visuals(energy)
	_update_health_bar(health)
	if mouse_over_player:
		display_data(mouse_over_player)

func disable_all_engine_particles() -> void:
	var engine_particles = [
		$"EngineParticleContainer/S-X,R+Y",
		$"EngineParticleContainer/S+X,R-Y",
		$"EngineParticleContainer/S-X,R-Y",
		$"EngineParticleContainer/S+X,R+Y",
		$"EngineParticleContainer/S-Y,R+Z,R+X",
		$"EngineParticleContainer/S-Y,R-Z,R+X",
		$"EngineParticleContainer/S-Y,R-Z,R-X",
		$"EngineParticleContainer/S-Y,R+Z,R-X",
		$"EngineParticleContainer/S+Y,R-Z,R+X",
		$"EngineParticleContainer/S+Y,R+Z,R+X",
		$"EngineParticleContainer/S+Y,R-Z,R-X",
		$"EngineParticleContainer/S+Y,R+Z,R-X",
		$EngineParticleContainer/SZ,
		$EngineParticleContainer/SZ2
	]
	for ep in engine_particles:
		ep.emitting = false

func update_engine_particles(linear_thrust : Vector3, rotational_thrust : Vector3) -> void:
	var engine_particles : Particles = $"EngineParticleContainer/S-X,R-Y"
	if linear_thrust.x < 0 or rotational_thrust.y > 0:
		engine_particles.emitting = true
		engine_particles.scale = Vector3.ONE * (max(-linear_thrust.x, 0)+max(rotational_thrust.y, 0)) * 0.005
	else:
		engine_particles.emitting = false
	
	engine_particles = $"EngineParticleContainer/S+X,R+Y"
	if linear_thrust.x > 0 or rotational_thrust.y < 0:
		engine_particles.emitting = true
		engine_particles.scale = Vector3.ONE * (max(linear_thrust.x, 0)+max(-rotational_thrust.y, 0)) * 0.005
	else:
		engine_particles.emitting = false
	
	engine_particles = $"EngineParticleContainer/S-X,R+Y"
	if linear_thrust.x < 0 or rotational_thrust.y < 0:
		engine_particles.emitting = true
		engine_particles.scale = Vector3.ONE * (max(-linear_thrust.x, 0)+max(-rotational_thrust.y, 0)) * 0.005
	else:
		engine_particles.emitting = false
	
	engine_particles = $"EngineParticleContainer/S+X,R-Y"
	if linear_thrust.x > 0 or rotational_thrust.y > 0:
		engine_particles.emitting = true
		engine_particles.scale = Vector3.ONE * (max(linear_thrust.x, 0)+max(rotational_thrust.y, 0)) * 0.005
	else:
		engine_particles.emitting = false
	
	engine_particles = $"EngineParticleContainer/S-Y,R+Z,R+X"
	if linear_thrust.y < 0 or rotational_thrust.z > 0 or rotational_thrust.x > 0:
		engine_particles.emitting = true
		engine_particles.scale = Vector3.ONE * (max(-linear_thrust.y, 0)+max(rotational_thrust.z, 0)+max(rotational_thrust.x, 0)) * 0.01/3
	else:
		engine_particles.emitting = false
	
	engine_particles = $"EngineParticleContainer/S-Y,R-Z,R+X"
	if linear_thrust.y < 0 or rotational_thrust.z < 0 or rotational_thrust.x > 0:
		engine_particles.emitting = true
		engine_particles.scale = Vector3.ONE * (max(-linear_thrust.y, 0)+max(-rotational_thrust.z, 0)+max(rotational_thrust.x, 0)) * 0.01/3
	else:
		engine_particles.emitting = false
	
	engine_particles = $"EngineParticleContainer/S-Y,R-Z,R-X"
	if linear_thrust.y < 0 or rotational_thrust.z < 0 or rotational_thrust.x < 0:
		engine_particles.emitting = true
		engine_particles.scale = Vector3.ONE * (max(-linear_thrust.y, 0)+max(-rotational_thrust.z, 0)+max(-rotational_thrust.x, 0)) * 0.01/3
	else:
		engine_particles.emitting = false
	
	engine_particles = $"EngineParticleContainer/S-Y,R+Z,R-X"
	if linear_thrust.y < 0 or rotational_thrust.z > 0 or rotational_thrust.x < 0:
		engine_particles.emitting = true
		engine_particles.scale = Vector3.ONE * (max(-linear_thrust.y, 0)+max(rotational_thrust.z, 0)+max(-rotational_thrust.x, 0)) * 0.01/3
	else:
		engine_particles.emitting = false
	
	engine_particles = $"EngineParticleContainer/S+Y,R-Z,R+X"
	if linear_thrust.y > 0 or rotational_thrust.z < 0 or rotational_thrust.x > 0:
		engine_particles.emitting = true
		engine_particles.scale = Vector3.ONE * (max(linear_thrust.y, 0)+max(-rotational_thrust.z, 0)+max(rotational_thrust.x, 0)) * 0.01/3
	else:
		engine_particles.emitting = false
	
	engine_particles = $"EngineParticleContainer/S+Y,R+Z,R+X"
	if linear_thrust.y > 0 or rotational_thrust.z > 0 or rotational_thrust.x > 0:
		engine_particles.emitting = true
		engine_particles.scale = Vector3.ONE * (max(linear_thrust.y, 0)+max(rotational_thrust.z, 0)+max(rotational_thrust.x, 0)) * 0.01/3
	else:
		engine_particles.emitting = false
	
	engine_particles = $"EngineParticleContainer/S+Y,R-Z,R-X"
	if linear_thrust.y > 0 or rotational_thrust.z < 0 or rotational_thrust.x < 0:
		engine_particles.emitting = true
		engine_particles.scale = Vector3.ONE * (max(linear_thrust.y, 0)+max(-rotational_thrust.z, 0)+max(-rotational_thrust.x, 0)) * 0.01/3
	else:
		engine_particles.emitting = false
	
	engine_particles = $"EngineParticleContainer/S+Y,R+Z,R-X"
	if linear_thrust.y > 0 or rotational_thrust.z > 0 or rotational_thrust.x < 0:
		engine_particles.emitting = true
		engine_particles.scale = Vector3.ONE * (max(linear_thrust.y, 0)+max(rotational_thrust.z, 0)+max(-rotational_thrust.x, 0)) * 0.01/3
	else:
		engine_particles.emitting = false
	
	engine_particles = $EngineParticleContainer/SZ
	var engine_particles2 : Particles = $EngineParticleContainer/SZ2
	if linear_thrust.z != 0:
		engine_particles.emitting = true
		engine_particles2.emitting = true
		var modz : float = linear_thrust.z
		if modz < 0:
			modz = -modz
		engine_particles.scale = Vector3.ONE * (modz) * 0.02
		engine_particles2.scale = Vector3.ONE * (modz) * 0.02
	else:
		engine_particles.emitting = false
		engine_particles2.emitting = false

func play_current_plan() -> void:
	
	health = end_health
	energy = end_energy
	using_full_plan = false
	running_plan = true
	plan_time = 5 * turn_counter

func play_all_plans() -> void:
	get_parent().play_full_plans()

func play_full_plan() -> void:
	running_plan = true
	using_full_plan = true
	plan_time = 0.0
	health = 100.0
	energy = 100.0

func _on_PlayButton_pressed() -> void:
	play_all_plans()

func _update_battery_visuals(value : float) -> void:
	$WeaponsPanel/FillingBlocker.margin_bottom = 65 - (clamp(value, 0.0, 100.0) * 1.2)

func _update_laser(length : float) -> void:
	$GunContainer/RayCast/CSGCylinder.height = length*10
	$GunContainer/RayCast/CSGCylinder.translation = Vector3(0, 0, -length*5)

func _fire_gun(delta : float) -> void:
	$GunContainer/RayCast.visible = true
	
	var closest_enemy = null
	var distance_of_closest = -1
	for player in players_in_firing_arc:
		if player.player_id == player_id or !player.is_alive:
			continue
		var player_distance : float = (player.translation - translation).length()
		if distance_of_closest == -1 or player_distance < distance_of_closest:
			closest_enemy = player
			distance_of_closest = player_distance
	
	
	if closest_enemy != null:
		$GunContainer/RayCast.look_at($GunContainer/RayCast.global_transform.origin - translation, Vector3(0,1,0))
		var raycast_pos : Vector3 = $GunContainer/RayCast.global_transform.origin
		var target_pos : Vector3 = $GunContainer/RayCast.get_collision_point()
		_update_laser(raycast_pos.distance_to(target_pos))
	else:
		$GunContainer/RayCast.rotation = Vector3.ZERO
		_update_laser(-$GunContainer/RayCast.cast_to.z)
	energy -= delta * BASE_ENERGY_USAGE
	if closest_enemy != null:
		closest_enemy.take_damage(BASE_DPS * delta)

func get_display_name() -> String:
	return get_parent().get_parent().name_dict[player_id]

func get_human_readable_vector(vector : Vector3) -> String:
	return "(" + String(round(vector.x * 10)/10) + ", " + \
		String(round(vector.y * 10)/10) + ", " + \
		String(round(vector.z * 10)/10) + ")"

func display_data(player_obj : RigidBody) -> void:
	var text = "Name: " + player_obj.get_display_name() + "\n"
	text += "Position: " + get_human_readable_vector(player_obj.translation) + "\n"
	text += "Rotation: " + get_human_readable_vector(player_obj.rotation_degrees) + "\n"
	text += "Hull Integrity: " + String(player_obj.health) + "%\n"
	
	$InfoPanel/Label.text = text
	mouse_over_player = player_obj

func clear_info_panel() -> void:
	$InfoPanel/Label.text = ""
	mouse_over_player = null

func _on_Player_mouse_entered():
	get_parent().mouse_enter(self)

func _on_Player_mouse_exited():
	get_parent().mouse_exit(self)

func _on_PlayLastButton_pressed():
	if len(thrust_plan.elements) == 0:
		play_full_plan()
	else:
		play_current_plan()

func set_colors(color : Color):
	var insideMaterial : Material = preload("res://Shaders/InsideSpaceship.tres").duplicate()
	insideMaterial.emission = color
	
	var outsideMaterial : Material = preload("res://Shaders/OutsideSpaceship.material").duplicate()
	outsideMaterial.emission = color
	outsideMaterial.albedo_color = color
	
	var particleMaterial : Material = preload("res://Shaders/ParticleSpaceship.tres").duplicate()
	particleMaterial.emission = color
	
	for child in $EngineParticleContainer.get_children():
		child.draw_pass_1.material = particleMaterial
	for child in $spaceship.get_children():
		if child.name == "Cube":
			child.set_surface_material(0, insideMaterial)
		else:
			child.set_surface_material(0, outsideMaterial)

func take_damage(damage : float) -> void:
	health -= damage

func calculate_other_damage(delta : float):
	if (translation.length_squared() > 100):
		take_damage(OOB_DAMAGE * delta)
	if energy < 0:
		take_damage(-energy * BASE_OVERCHARGE_DAMAGE * delta)

func _update_health_bar(value : float) -> void:
	health_bar.anchor_left = 0.5 - clamp(value, 0.0, 100.0)/200
	health_bar.anchor_right = 0.5 + clamp(value, 0.0, 100.0)/200

func fix_plans() -> void:
	if thrust_plan.current_time() < 5.0:
		var new_thrust_element : ThrustElement = ThrustElement.new()
		new_thrust_element.linear_thrust = Vector3.ZERO
		new_thrust_element.rotational_thrust = Vector3.ZERO
		new_thrust_element.time = 5.0 - thrust_plan.current_time()
	if weapons_plan.current_time() < 5.0:
		var new_weapons_element : WeaponsElement = WeaponsElement.new()
		new_weapons_element.firing = false
		new_weapons_element.time = 5.0 - weapons_plan.current_time()

func _on_player_enter_firing_arc(body):
	players_in_firing_arc.append(body)
	print(body.name)

func _on_player_exit_firing_arc(body):
	players_in_firing_arc.erase(body)
	print(body.name)

func set_firing_arc_visibility(toggle : bool) -> void:
	$GunContainer/Cone/CollisionShape/Cone.visible = toggle

func _on_WeaponVisualiserMenu_item_selected(index):
	if index == 0:
		get_parent().set_all_firing_arc_visibilities(false)
	elif index == 1:
		get_parent().set_all_firing_arc_visibilities(false)
		set_firing_arc_visibility(true)
	elif index == 2:
		get_parent().set_all_firing_arc_visibilities(true)
