Randoloot/scripts/game/deployed_mine.gd
2026-10-17 14:28:20 +02:00

76 lines
2.9 KiB
GDScript

extends Node2D
const VFX := preload("res://scripts/game/extension_vfx.gd")
const MINE_TEXTURE := preload("res://assets/icons/extensions/mine_art.png")
const LIFETIME := 60.0
const ARM_TIME := 0.7
const TRIGGER_RADIUS := 60.0
const BLAST_RADIUS := 140.0
var drift := Vector2.ZERO
var _age := 0.0
var _triggered := false
func _ready() -> void:
add_to_group("player_mines")
z_index = 12
func _physics_process(delta: float) -> void:
_age += delta
position += drift * delta
drift = drift.move_toward(Vector2.ZERO, 100.0 * delta)
if _age >= LIFETIME:
queue_free()
return
queue_redraw()
if _triggered or _age < ARM_TIME:
return
for enemy in get_tree().get_nodes_in_group("enemies"):
if enemy.is_queued_for_deletion() or float(enemy.get("hull")) <= 0.0:
continue
if global_position.distance_to(enemy.global_position) <= TRIGGER_RADIUS + float(enemy.call("get_visual_size")) * 0.35:
_detonate()
return
func _detonate() -> void:
if _triggered:
return
_triggered = true
# Resolve the entire blast once; each nearby enemy receives one hit.
for enemy in get_tree().get_nodes_in_group("enemies"):
if enemy.is_queued_for_deletion() or float(enemy.get("hull")) <= 0.0:
continue
var hull_radius := float(enemy.call("get_visual_size")) * 0.35
if global_position.distance_to(enemy.global_position) <= BLAST_RADIUS + hull_radius:
enemy.call("apply_mine_hit")
var explosion := Node2D.new()
explosion.set_script(preload("res://scripts/game/deployment_flash.gd"))
explosion.set("color", Color("ffbc75"))
explosion.set("blast", true)
# The shockwave reaches the same radius as the area damage.
explosion.scale = Vector2.ONE * (BLAST_RADIUS / 88.0)
explosion.position = position
get_parent().add_child(explosion)
queue_free()
func _draw() -> void:
var armed := _age >= ARM_TIME
var deployment := smoothstep(0.0, 0.35, _age)
var fade := clampf(LIFETIME - _age, 0.0, 1.0)
var accent := Color("ff9957") if armed else Color("8ad7e7")
var pulse := 0.65 + 0.35 * sin(_age * 5.0)
var glow_radius := 28.0 + pulse * 4.0
draw_texture_rect(VFX.radial_texture(), Rect2(-glow_radius, -glow_radius, glow_radius * 2, glow_radius * 2), false, Color(accent, 0.22 * fade))
if armed:
for segment in 3:
var angle := _age * 0.35 + float(segment) * TAU / 3.0
draw_arc(Vector2.ZERO, 27.0, angle, angle + 0.6, 16, Color(accent, 0.22 * fade), 1.0, true)
else:
draw_arc(Vector2.ZERO, 23.0, -PI * 0.5, -PI * 0.5 + TAU * clampf(_age / ARM_TIME, 0.0, 1.0), 48, Color(accent, fade * 0.7), 1.5, true)
var scale_factor := lerpf(0.35, 1.0, deployment)
var spin := (1.0 - deployment) * -0.85
draw_set_transform(Vector2.ZERO, spin, Vector2.ONE * scale_factor)
draw_texture_rect(MINE_TEXTURE, Rect2(-21, -21, 42, 42), false, Color(1, 1, 1, fade))
draw_set_transform(Vector2.ZERO)
var sensor_radius := 7.0 + pulse * 2.0
draw_texture_rect(VFX.radial_texture(), Rect2(-sensor_radius, -sensor_radius, sensor_radius * 2, sensor_radius * 2), false, Color(accent, (0.55 + pulse * 0.35) * fade))