151 lines
3.7 KiB
GDScript
151 lines
3.7 KiB
GDScript
class_name AbstractTeslaProjectile
|
|
extends AbstractDirectHitProjectile
|
|
|
|
|
|
@export_range(0.01, 0.5) var jink_min_delay: float = 0.01
|
|
@export_range(0.01, 0.5) var jink_max_delay: float = 0.01
|
|
@export_range(0, 360) var deviation_angle: int = 0
|
|
@export_range(0, 1000) var no_deviation_distance: int = 0
|
|
|
|
|
|
var _collided_foes : Array[AbstractShip] = []
|
|
var _current_line: Line2D
|
|
var _audio_player: AudioStreamPlayer2D
|
|
|
|
|
|
@onready var jink_timer : Timer = $JinkTimer
|
|
@onready var life_timer : Timer = $LifeTimer
|
|
|
|
@onready var line_thin : Line2D = $LineThin
|
|
@onready var line_thick : Line2D = $LineThick
|
|
|
|
|
|
func _ready() -> void:
|
|
super._ready()
|
|
_start_jink_timer()
|
|
|
|
line_thin.hide()
|
|
_current_line = line_thick
|
|
_current_line.add_point(position)
|
|
|
|
_prepare_line(line_thin)
|
|
_prepare_line(line_thick)
|
|
|
|
var stream : AudioStream = SoundManager.sfx_weapon_tesla_shot
|
|
_audio_player = SoundManager.play_sfx_stream(stream, global_position)
|
|
|
|
|
|
func _prepare_line(line: Line2D) -> void:
|
|
line.reparent(get_tree().current_scene)
|
|
line.global_position = Vector2.ZERO
|
|
|
|
|
|
func _process(_delta: float) -> void:
|
|
_update_line_points()
|
|
|
|
|
|
func _process_hit_for_projectile(collided_body: Node2D) -> void:
|
|
if collided_body is AbstractShip:
|
|
_collided_foes.append(collided_body)
|
|
|
|
damage.value = floor(damage.value/2.0)
|
|
if damage.value == 0:
|
|
_start_fading()
|
|
collision_layer = 0
|
|
collision_mask = 0
|
|
|
|
_velocity = _apply_random_deviation(_velocity)
|
|
_start_jink_timer()
|
|
|
|
|
|
func delete() -> void:
|
|
line_thin.queue_free()
|
|
line_thick.queue_free()
|
|
super.delete()
|
|
|
|
|
|
func _on_out_of_screen_timer_timeout() -> void:
|
|
_start_fading()
|
|
|
|
|
|
func _update_line_points() -> void:
|
|
_current_line.add_point(position)
|
|
|
|
if weapon != null:
|
|
var points := _move_points_follow_weapon(_current_line.points)
|
|
_current_line.clear_points()
|
|
for point : Vector2 in points:
|
|
_current_line.add_point(point)
|
|
|
|
|
|
func _move_points_follow_weapon(points: PackedVector2Array) -> Array[Vector2]:
|
|
var new_points : Array[Vector2] = []
|
|
|
|
var new_point := weapon.global_position
|
|
for i in range(points.size() - 1):
|
|
new_points.append(new_point)
|
|
|
|
var distance_old := points[i].distance_to(points[i+1])
|
|
var distance_new := new_points[i].distance_to(points[i+1])
|
|
var distance := distance_old - (distance_old - distance_new)/2
|
|
|
|
new_point = new_points[i] + points[i].direction_to(points[i+1]) * distance
|
|
new_points.append(points[points.size()-1])
|
|
|
|
return new_points
|
|
|
|
|
|
func _start_jink_timer() -> void:
|
|
var random_delay := randf_range(jink_min_delay, jink_max_delay)
|
|
jink_timer.start(random_delay)
|
|
|
|
|
|
func _on_jink_timer_timeout() -> void:
|
|
var foe := _get_nearest_foe(_collided_foes)
|
|
if foe:
|
|
_target_foe(foe)
|
|
if position.distance_to(foe.position) > no_deviation_distance:
|
|
_velocity = _apply_random_deviation(_velocity)
|
|
else:
|
|
_velocity = _apply_random_deviation(_velocity)
|
|
|
|
_start_jink_timer()
|
|
|
|
|
|
func _target_foe(foe: AbstractShip) -> void:
|
|
var current_speed := _velocity.length()
|
|
var foe_direction := position.direction_to(foe.position)
|
|
_velocity = current_speed * foe_direction
|
|
|
|
|
|
func _apply_random_deviation(vector: Vector2) -> Vector2:
|
|
var deviation_rad := deg_to_rad(deviation_angle)
|
|
var random_angle := randfn(0.0, deviation_rad)
|
|
return vector.rotated(random_angle)
|
|
|
|
|
|
func _start_fading() -> void:
|
|
line_thick.hide()
|
|
line_thin.show()
|
|
|
|
line_thin.clear_points()
|
|
for point in line_thick.points:
|
|
line_thin.add_point(point)
|
|
|
|
_current_line = line_thin
|
|
|
|
life_timer.start()
|
|
|
|
if _audio_player.playing:
|
|
var old_volume := _audio_player.volume_linear
|
|
var tween := create_tween()
|
|
tween.tween_property(_audio_player, "volume_linear", 0, life_timer.wait_time)
|
|
tween.finished.connect(func() -> void:
|
|
_audio_player.stop();
|
|
_audio_player.volume_linear = old_volume
|
|
)
|
|
|
|
|
|
func _on_life_timer_timeout() -> void:
|
|
delete()
|