A wave is an attack on what the player has built, not a hazard sitting in space waiting to be flown near. Wave enemies now ignore the detection radius their components otherwise respect and close on the nearest building from wherever they arrived. The flag is per INSTANCE rather than per definition: the same chaser is a wave when the director launches it and a garrison when a map author places it, and a planet garrison that chased the player across the system would be a very different thing from what the editor is used to place. The test pins both halves - a wave chaser 6000px out closed on a crafter, and an identically built one nobody sent held its station. What it fights on the way is unchanged: EnemyTargets already prefers a vessel inside 520px over a building further off, and already searches the player_ships group, so the fleet and an outpost's garrison both count. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
44 lines
1.8 KiB
GDScript
44 lines
1.8 KiB
GDScript
class_name EnemyPursuitComponent
|
|
extends Node
|
|
|
|
# Chases the nearest player ship. Moved out of Enemy.gd verbatim so the
|
|
# behaviour is opt-in per definition rather than hardcoded into every enemy.
|
|
|
|
var capability_id: String = "pursuit"
|
|
var velocity: Vector2 = Vector2.ZERO
|
|
|
|
# #69: used to beeline from anywhere on the map the instant it spawned,
|
|
# which read as omniscient rather than alert. Idle until the fleet actually
|
|
# comes within this radius. A persistent stalking threat wants the opposite
|
|
# of this - see EnemyPursuitComponentMothership.tscn, which overrides it to
|
|
# an effectively unlimited value for the mothership's own instance.
|
|
@export var detection_range: float = 850.0
|
|
|
|
|
|
func tick(delta: float) -> void:
|
|
var enemy: Node2D = get_parent()
|
|
# #101: a structure is a target now, not scenery. EnemyTargets keeps a
|
|
# ship in the enemy's face ahead of a building further off.
|
|
var target: Node2D = EnemyTargets.nearest_target(self, enemy.global_position)
|
|
if target == null:
|
|
return
|
|
# #113: a wave enemy closes on what the player built from wherever it
|
|
# arrived. Everything else keeps the radius that stops it reading as
|
|
# omniscient (#69).
|
|
if not EnemyTargets.ignores_range(enemy) \
|
|
and enemy.global_position.distance_to(target.global_position) > detection_range:
|
|
return
|
|
var to_target: Vector2 = target.global_position - enemy.global_position
|
|
|
|
if to_target.length() > 1.0:
|
|
var desired_velocity: Vector2 = to_target.normalized() * enemy.speed
|
|
velocity = velocity.move_toward(desired_velocity, enemy.acceleration * delta)
|
|
enemy.global_position += velocity * delta
|
|
|
|
if velocity.length() > 5.0:
|
|
var target_angle: float = velocity.angle() + PI / 2.0
|
|
enemy.rotation = lerp_angle(enemy.rotation, target_angle, enemy.rotation_speed * delta)
|
|
|
|
|
|
func _nearest_ship(enemy: Node2D) -> Node2D:
|
|
return EnemyTargets.nearest_ship(self, enemy.global_position)
|