changed laser build up logic to allow for actual enemy tracking

main
Artur 2026-06-03 18:19:57 +02:00
parent c3375d6305
commit c6b60ea002
2 changed files with 40 additions and 19 deletions

View File

@ -6,6 +6,7 @@ extends Area2D
@onready var shape: CollisionShape2D = $CollisionShape2D @onready var shape: CollisionShape2D = $CollisionShape2D
func _ready() -> void: func _ready() -> void:
scale = Vector2(0.7, 0.7)
if sprite.sprite_frames.has_animation(beam_type): if sprite.sprite_frames.has_animation(beam_type):
sprite.play(beam_type) sprite.play(beam_type)
shape.disabled = beam_type != "middle" shape.disabled = beam_type != "middle"

View File

@ -5,8 +5,10 @@ const PRIMARY_TICK_DMG := 40
const SPLASH_TICK_DMG := 3 const SPLASH_TICK_DMG := 3
const TICK_INTERVAL := 0.5 const TICK_INTERVAL := 0.5
const SWEEP_RATE := 22.0 const SWEEP_RATE := 22.0
const FADE_IN := 0.3
const FADE_OUT := 0.5
@export var segment_size := 16.0 @export var segment_size := 8.0
@export var start_offset := 24.0 @export var start_offset := 24.0
@onready var perk_effects = get_node("/root/Game/PerkEffects") @onready var perk_effects = get_node("/root/Game/PerkEffects")
@ -19,7 +21,7 @@ var tick_timer := 0.0
var elapsed := 0.0 var elapsed := 0.0
var done := false var done := false
var current_angle := 0.0 var current_angle := 0.0
var sweep_to := 0.0 var sweep_dest_angle := 0.0
var sweeping := false var sweeping := false
func _ready() -> void: func _ready() -> void:
@ -36,13 +38,26 @@ func _process(delta: float) -> void:
elapsed += delta elapsed += delta
tick_timer += delta tick_timer += delta
if (not is_instance_valid(target) or target.is_dying) and perk_effects.laser_retarget_enabled:
var new_target := get_highest_hp_enemy()
if new_target != null:
target = new_target
sweep_dest_angle = global_position.direction_to(target.global_position).angle()
sweeping = true
if is_instance_valid(target) and not target.is_dying:
var live_angle := global_position.direction_to(target.global_position).angle()
if sweeping: if sweeping:
current_angle = lerp_angle(current_angle, sweep_to, 1.0 - exp(-SWEEP_RATE * delta)) current_angle = lerp_angle(current_angle, sweep_dest_angle, 1.0 - exp(-SWEEP_RATE * delta))
if abs(angle_difference(current_angle, sweep_to)) < 0.005: if abs(angle_difference(current_angle, sweep_dest_angle)) < 0.01:
current_angle = sweep_to
sweeping = false sweeping = false
current_angle = live_angle
else:
current_angle = live_angle
rebuild_segments() rebuild_segments()
_update_alpha()
if tick_timer >= TICK_INTERVAL: if tick_timer >= TICK_INTERVAL:
tick_timer -= TICK_INTERVAL tick_timer -= TICK_INTERVAL
do_damage_tick() do_damage_tick()
@ -51,18 +66,20 @@ func _process(delta: float) -> void:
cleanup() cleanup()
func rebuild_segments() -> void: func rebuild_segments() -> void:
if not is_instance_valid(target):
return
var dir := Vector2.from_angle(current_angle) var dir := Vector2.from_angle(current_angle)
var beam_start := global_position + dir * start_offset var beam_start := global_position + dir * start_offset
var dest_dist := global_position.distance_to(target.global_position) var dest_dist := global_position.distance_to(target.global_position)
var beam_dist := dest_dist - start_offset var beam_dist := dest_dist - start_offset
var n_mid := int(max(0.0, beam_dist - segment_size) / segment_size) var n_mid: int = max(0, ceili(beam_dist / segment_size) - 1)
var positions: Array = [beam_start] var positions: Array = [beam_start]
var types: Array = ["start"] var types: Array = ["start"]
for i in range(n_mid): for i in range(n_mid):
positions.append(beam_start + dir * (segment_size * float(i + 1))) positions.append(beam_start + dir * (segment_size * float(i + 1)))
types.append("middle") types.append("middle")
positions.append(beam_start + dir * (segment_size * float(n_mid + 1))) positions.append(beam_start + dir * beam_dist)
types.append("end") types.append("end")
while all_segs.size() < positions.size(): while all_segs.size() < positions.size():
@ -100,15 +117,10 @@ func rebuild_segments() -> void:
func retarget(new_target: Node2D) -> void: func retarget(new_target: Node2D) -> void:
target = new_target target = new_target
sweep_to = global_position.direction_to(new_target.global_position).angle() sweep_dest_angle = global_position.direction_to(target.global_position).angle()
sweeping = true sweeping = true
func do_damage_tick() -> void: func do_damage_tick() -> void:
if (not is_instance_valid(target) or target.is_dying) and perk_effects.laser_retarget_enabled:
var new_target = get_highest_hp_enemy()
if new_target != null:
retarget(new_target)
if is_instance_valid(target) and not target.is_dying: if is_instance_valid(target) and not target.is_dying:
target.take_damage(PRIMARY_TICK_DMG) target.take_damage(PRIMARY_TICK_DMG)
@ -122,6 +134,14 @@ func do_damage_tick() -> void:
body.take_damage(SPLASH_TICK_DMG) body.take_damage(SPLASH_TICK_DMG)
hit.append(body) hit.append(body)
func _update_alpha() -> void:
var alpha := clampf(elapsed / FADE_IN, 0.0, 1.0)
if elapsed > BEAM_DURATION - FADE_OUT:
alpha = minf(alpha, clampf((BEAM_DURATION - elapsed) / FADE_OUT, 0.0, 1.0))
for seg in all_segs:
if is_instance_valid(seg):
seg.modulate.a = alpha
func cleanup() -> void: func cleanup() -> void:
for seg in all_segs: for seg in all_segs:
if is_instance_valid(seg): if is_instance_valid(seg):