76 lines
2.9 KiB
GDScript
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))
|