#114: the enemy bomber flies, and its bombs arrive
It was a siege piece that crept at 20px/s and lobbed a shell taking five seconds to cross the gap. That read as a thing that was stuck rather than a thing that was dangerous: by the time a shell landed the fleet had wandered off, and the tower was still approaching. It now moves at 150px/s, faces where it is going, and its bombs travel at 460 - fast enough to arrive while the target is roughly where it was aimed, slow enough that the impact cross is a warning rather than a formality. The hull is a bomber rather than a lumpy octagon: swept wings, a short fuselage, a bay under it. The bomb has fins and a hot core down its smoke trail, and the blast throws real debris - a BombBlastVFX built from the same LightBurstVFX as every other explosion, plus a second ring chasing the first outwards and a white flash that is gone almost at once. It also bombs what the player has BUILT, through the shared targeting rather than the fleet alone, and its blast damages structures - it had been asking Fleet directly and hitting only player_ships, which was already out of step with #101. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
1a2a27b6e8
commit
0c48b5e739
4 changed files with 109 additions and 31 deletions
|
|
@ -1,20 +1,32 @@
|
|||
class_name EnemyArtilleryComponent
|
||||
extends Node
|
||||
|
||||
# Stationary siege piece: drifts slowly toward the fleet (deliberately no
|
||||
# pursuit component - closing distance is incidental, not its purpose) and
|
||||
# fires a slow, clearly visible AOE shell on a long cooldown via a
|
||||
# standalone ArtilleryShell, so an already-launched shot survives this
|
||||
# enemy dying mid-flight, same as EnemyProjectile/Projectile already do.
|
||||
# The bomber: it moves to where its bombs will land and drops them there.
|
||||
#
|
||||
# #114 turned it from a siege piece into an aircraft. It used to creep at
|
||||
# 20px/s and lob a shell that took five seconds to arrive, which read as a
|
||||
# thing that was stuck rather than a thing that was dangerous - by the time
|
||||
# a shell landed the fleet had wandered off, and the tower was still
|
||||
# approaching. It now flies at its own speed and its bombs travel at 460.
|
||||
#
|
||||
# The shell is still a standalone ArtilleryShell added to the root, so an
|
||||
# already-dropped bomb survives this enemy dying mid-flight, same as
|
||||
# EnemyProjectile/Projectile already do.
|
||||
|
||||
var capability_id: String = "artillery"
|
||||
|
||||
@export var fire_cooldown: float = 6.0
|
||||
@export var fire_cooldown: float = 4.0
|
||||
@export var fire_range: float = 900.0
|
||||
@export var shell_speed: float = 180.0
|
||||
# #114: fast enough that the bomb arrives while the target is still roughly
|
||||
# where it was aimed, and slow enough that the impact cross is a warning
|
||||
# rather than a formality.
|
||||
@export var shell_speed: float = 460.0
|
||||
@export var aoe_radius: float = 220.0
|
||||
@export var damage: int = 3
|
||||
@export var drift_speed: float = 20.0
|
||||
# It flies now rather than creeping. Kept as its own number rather than the
|
||||
# definition's `speed` so a run-in can be deliberately slower than a chaser's
|
||||
# top speed without making the hull slow.
|
||||
@export var drift_speed: float = 150.0
|
||||
@export var color: Color = Color(1.0, 0.5, 0.2)
|
||||
|
||||
var cooldown_left: float = 0.0
|
||||
|
|
@ -29,10 +41,12 @@ func tick(delta: float) -> void:
|
|||
if cooldown_left > 0.0:
|
||||
return
|
||||
|
||||
var fleet: Node2D = get_tree().get_first_node_in_group("player_fleet")
|
||||
if fleet == null or fleet.ships.is_empty():
|
||||
# #101/#113: it bombs what the player has BUILT as readily as what they
|
||||
# are flying, and asks the shared targeting rather than the fleet alone.
|
||||
var target: Node2D = EnemyTargets.nearest_target(self, enemy.global_position)
|
||||
if target == null:
|
||||
return
|
||||
var centroid: Vector2 = fleet.get_centroid()
|
||||
var centroid: Vector2 = target.global_position
|
||||
if enemy.global_position.distance_to(centroid) > fire_range:
|
||||
return
|
||||
|
||||
|
|
@ -47,18 +61,22 @@ func tick(delta: float) -> void:
|
|||
|
||||
|
||||
func _drift(enemy: Node2D, delta: float) -> void:
|
||||
# Local position throughout, same convention as EnemyPursuitComponent/
|
||||
# EnemyStandoffComponent: valid as long as the enemy's container and
|
||||
# Fleet share a common origin, which every scene in this project does.
|
||||
var fleet: Node2D = get_tree().get_first_node_in_group("player_fleet")
|
||||
if fleet == null or fleet.ships.is_empty():
|
||||
var target: Node2D = EnemyTargets.nearest_target(self, enemy.global_position)
|
||||
if target == null:
|
||||
return
|
||||
var to_fleet: Vector2 = fleet.get_centroid() - enemy.position
|
||||
# #69: gated by the same fire_range it already shells within, rather
|
||||
# than a second tunable that could drift out of sync - outside its own
|
||||
# firing envelope it has nothing to be drifting toward yet.
|
||||
if to_fleet.length() > fire_range:
|
||||
var to_target: Vector2 = target.global_position - enemy.global_position
|
||||
var distance: float = to_target.length()
|
||||
if distance < 1.0:
|
||||
return
|
||||
if to_fleet.length() < 1.0:
|
||||
# #69: gated by the same fire_range it already bombs within, rather than
|
||||
# a second tunable that could drift out of sync - outside its own firing
|
||||
# envelope it has nothing to be flying toward yet. #113: unless it came
|
||||
# in with a wave, in which case it has somewhere to be.
|
||||
if distance > fire_range and not EnemyTargets.ignores_range(enemy):
|
||||
return
|
||||
enemy.position += to_fleet.normalized() * drift_speed * delta
|
||||
var heading: Vector2 = to_target / distance
|
||||
enemy.global_position += heading * drift_speed * delta
|
||||
# #114: it faces where it is going. A bomber that flew sideways was most
|
||||
# of why the old one read as scenery being nudged along.
|
||||
enemy.rotation = lerp_angle(enemy.rotation, heading.angle() + PI / 2.0,
|
||||
enemy.rotation_speed * delta)
|
||||
|
|
|
|||
Loading…
Reference in a new issue