Add space-time distorder vessel and fleet speed fader (#59)

GameState.fleet_speed_multiplier (1.0-3.0) is applied at the point of
use - Fleet's cruise anchor and Ship's own max_speed/acceleration -
rather than baked into stored stats, so a stat upgrade researched
mid-boost can't corrupt the base value and the fader takes effect
immediately with no re-apply step.

Ship.arrive_radius is scaled by the same multiplier: at higher speeds
each physics tick covers a proportionally larger step, and once that
step outgrows a fixed arrive_radius the ship can overshoot its
snap-to-target zone every tick while chasing a target that's now also
receding faster - visible as the fleet stretching apart under boost.
Scaling it preserves the same "snaps onto its slot" tightness at any
boost level that 1.0x already has.

SpeedFader.gd is a self-contained vertical drag control (TouchJoystick's
raw-touch idiom, not _gui_input) that writes straight to the autoload
rather than reporting a value for something else to apply. It also
resets the multiplier to 1.0 the instant fleet.has_capability("distorder")
goes false, so a fleet can never be left permanently boosted by a vessel
it no longer has.

VesselDistorderComponent carries no per-shot behaviour (energy drain
while boosted is #62) - its presence is what matters. Registered in
VesselDefinitions, wired into the crafter/hangar/ship-lab menus per
#57's note (5/5/6 -> 6/6/7 columns).
This commit is contained in:
Loïc Wisniewski 2026-08-16 17:59:04 +02:00
commit 116e0f97d3
14 changed files with 675 additions and 86 deletions

View file

@ -28,6 +28,7 @@ extends Node2D
# indirectly - e.g. Main.tscn loaded from inside a _screenshot_tool.gd
# preview - for a class_name this new. Node + duck-typed calls sidesteps it.
@onready var laser_controller: Node = get_node_or_null("LaserController")
@onready var speed_fader: Node = get_node_or_null("UI/SpeedFader")
var touches: Dictionary = {}
var pinch_active: bool = false
@ -263,6 +264,8 @@ func _handle_touch(event: InputEventScreenTouch) -> void:
return
if laser_controller != null and laser_controller.handle_touch(event):
return
if speed_fader != null and speed_fader.handle_touch(event):
return
if _handle_pivot_touch(event):
return
if joystick != null and joystick.visible and joystick.handle_touch(event):
@ -287,6 +290,8 @@ func _handle_drag(event: InputEventScreenDrag) -> void:
return
if laser_controller != null and laser_controller.handle_drag(event):
return
if speed_fader != null and speed_fader.handle_drag(event):
return
if joystick != null and joystick.visible and joystick.handle_drag(event):
return
if not touches.has(event.index):