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))