2026-08-15 21:23:43 +02:00
|
|
|
class_name EnemyArtilleryComponent
|
|
|
|
|
extends Node
|
|
|
|
|
|
#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>
2026-08-23 21:58:56 +02:00
|
|
|
# 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.
|
2026-08-15 21:23:43 +02:00
|
|
|
|
|
|
|
|
var capability_id: String = "artillery"
|
|
|
|
|
|
#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>
2026-08-23 21:58:56 +02:00
|
|
|
@export var fire_cooldown: float = 4.0
|
2026-08-15 21:23:43 +02:00
|
|
|
@export var fire_range: float = 900.0
|
#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>
2026-08-23 21:58:56 +02:00
|
|
|
# #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
|
2026-08-15 21:23:43 +02:00
|
|
|
@export var aoe_radius: float = 220.0
|
|
|
|
|
@export var damage: int = 3
|
#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>
2026-08-23 21:58:56 +02:00
|
|
|
# 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
|
2026-08-15 21:23:43 +02:00
|
|
|
@export var color: Color = Color(1.0, 0.5, 0.2)
|
|
|
|
|
|
|
|
|
|
var cooldown_left: float = 0.0
|
#84: move 215 root files into a folder hierarchy
Everything lived in one flat directory, so a diff gave no clue what area it
touched and finding the file you wanted meant knowing its exact name. Twelve
folders now, grouped by what a thing IS rather than what type it is - a
vessel's definition, its component scenes and its upgrade resources sit
together, because that is the set you read when you change one of them.
buildings core controllers enemies logistics planets
resources shaders surface ui vessels vfx world
332 files moved and every res:// reference rewritten - 306 files touched,
including the autoload and main-scene paths in project.godot. Nothing renamed:
this is purely where files sit, so the diff is a pile of pure moves and no
behaviour is buried in it. ui_theme.tres, icon.svg and web_shell.html stay at
the root, where Godot and the export preset expect them.
Verified three ways, because a suite alone would not have caught all of it:
the full 117 pass, the web export builds clean, and the game renders.
The export is why that matters. The FIRST export after the move failed with
"Attempt to open script 'res://GameState.gd'" - the old path - while
project.godot on disk plainly said res://core/GameState.gd. That is this
project's documented Android FUSE mtime trap: Godot served a cached copy of a
file whose content had changed. A `touch` fixed it. Nothing in the test suite
would have found that, because the suite runs from a copy on a native
filesystem - the one place the bug cannot happen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 19:44:14 +02:00
|
|
|
var shell_scene: PackedScene = preload("res://enemies/ArtilleryShell.tscn")
|
2026-08-15 21:23:43 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
func tick(delta: float) -> void:
|
|
|
|
|
var enemy: Node2D = get_parent()
|
|
|
|
|
_drift(enemy, delta)
|
|
|
|
|
|
|
|
|
|
cooldown_left -= delta
|
|
|
|
|
if cooldown_left > 0.0:
|
|
|
|
|
return
|
|
|
|
|
|
#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>
2026-08-23 21:58:56 +02:00
|
|
|
# #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:
|
2026-08-15 21:23:43 +02:00
|
|
|
return
|
#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>
2026-08-23 21:58:56 +02:00
|
|
|
var centroid: Vector2 = target.global_position
|
2026-08-15 21:23:43 +02:00
|
|
|
if enemy.global_position.distance_to(centroid) > fire_range:
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
var shell: Node2D = shell_scene.instantiate()
|
|
|
|
|
shell.shell_speed = shell_speed
|
|
|
|
|
shell.aoe_radius = aoe_radius
|
|
|
|
|
shell.damage = damage
|
|
|
|
|
shell.color = color
|
|
|
|
|
enemy.get_tree().root.add_child(shell)
|
|
|
|
|
shell.launch(enemy.global_position, centroid)
|
|
|
|
|
cooldown_left = fire_cooldown
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func _drift(enemy: Node2D, delta: float) -> void:
|
#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>
2026-08-23 21:58:56 +02:00
|
|
|
var target: Node2D = EnemyTargets.nearest_target(self, enemy.global_position)
|
|
|
|
|
if target == null:
|
2026-08-15 21:23:43 +02:00
|
|
|
return
|
#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>
2026-08-23 21:58:56 +02:00
|
|
|
var to_target: Vector2 = target.global_position - enemy.global_position
|
|
|
|
|
var distance: float = to_target.length()
|
|
|
|
|
if distance < 1.0:
|
2026-08-17 19:47:37 +02:00
|
|
|
return
|
#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>
2026-08-23 21:58:56 +02:00
|
|
|
# #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):
|
2026-08-15 21:23:43 +02:00
|
|
|
return
|
#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>
2026-08-23 21:58:56 +02:00
|
|
|
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)
|