Sharpen upgrades, mark the convoy's destination, and give the world sound

#204 the Beam Collimator widens the beam instead of adding range to one that
already crosses the screen; beam width becomes a per-shot vessel stat.
#205 the Energy Propulser gains three upgrades - dash recharge, dash reach,
and boosted-cruise drain - which turns three constants into vessel stats.
#206 three further doctrines carry the fleet from ten to twenty.
#207 the prologue's World Ship gets a marker, through the scanner's own
guidance arrow rather than a second one.
#208 #210 #213 #214 four new synthesised sounds: the breach opening, cargo
reaching the hold, a rock breaking, and a gas bomb blooming.
#215 building health bars are larger, plated and framed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019AJMdB7iuHuLFZM1aBu3GD
This commit is contained in:
Loïc Wisniewski 2026-09-05 12:16:17 +02:00
commit 78836882af
33 changed files with 716 additions and 52 deletions

View file

@ -4,6 +4,12 @@ extends Control
const PLANET_DEFINITIONS = preload("res://planets/PlanetDefinitions.gd")
const EDGE_MARGIN: float = 34.0
# The scene sets process_mode = ALWAYS. A narration line stops the tree
# (NarrationBanner, #128) and the prologue is nearly all narration, so a
# pausable marker would be absent for most of the run it exists to guide
# (#207). Nothing here simulates anything - it reads a target and points at
# it - so running while the game is stopped costs nothing and stops the
# marker blinking out every time somebody speaks.
@onready var indicator: Control = $Indicator
@onready var target_label: Label = $TargetLabel
@ -16,8 +22,11 @@ func _ready() -> void:
func _process(_delta: float) -> void:
var target: Dictionary = GameState.active_scanner_target()
if target.is_empty() or GameState.intro_active or _modal_is_open():
# #207: the prologue's destination comes through the same marker, so this
# no longer hides for the intro - GameState decides which target is live,
# and an empty answer is what hides it.
var target: Dictionary = GameState.active_guidance_target()
if target.is_empty() or _modal_is_open():
visible = false
return
if fleet == null or not is_instance_valid(fleet):
@ -39,8 +48,11 @@ func _process(_delta: float) -> void:
if toward_target.length_squared() > 0.01:
indicator.rotation = toward_target.angle() + PI / 2.0
# A scanned planet colours the arrow with its own map colour. The World
# Ship is not a planet and has no definition, so it keeps the indicator's
# authored colour rather than being forced into one.
var definition: Resource = PLANET_DEFINITIONS.get_definition(
String(target.definition_id))
String(target.get("definition_id", "")))
if definition != null:
indicator.glow_color = definition.map_color
indicator.queue_redraw()

View file

@ -6,6 +6,7 @@
[node name="ScannerGuidance" type="Control"]
visible = false
mouse_filter = 2
process_mode = 3
anchor_right = 1.0
anchor_bottom = 1.0
script = ExtResource("1")