Commit graph spaceship/GameController.gd
Author SHA1 Message Date
Loïc Wisniewski
d68aac6444 Fix pivot tap-spam speed exploit (#72)
_finish_pivot_tap() granted a full PIVOT_MIN_STEP rotation on every
button/key release with no rate limit, so tapping fast enough rotated
the formation far beyond PIVOT_SPEED's smooth held-rate cap - well
above what holding the button down can ever produce. Each of those
artificially-frequent re-seats (Fleet.apply_formation()) forced every
ship into a fresh max-speed catch-up dash toward its new slot with no
time to settle between dashes, and since outer-wedge ships swing
further per pivot than inner ones, spamming made them visibly diverge
in speed while each ship's own bounded max_speed made the fleet read
as constantly pinned at its speed ceiling.

Added a per-direction cooldown (the time a genuine hold needs to reach
PIVOT_MIN_STEP on its own) so tap-spam can't out-pace holding the
button. Deliberately NOT shared between CW/CCW: a quick correction tap
the other way right after an overshoot is normal play, and
test_keyboard_input.gd already covers Q and E each independently
producing their own minimum step back-to-back - only repeatedly
re-tapping the SAME direction needed capping.
2026-08-17 19:47:50 +02:00
Loïc Wisniewski
116e0f97d3 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).
2026-08-16 17:59:04 +02:00
Loïc Wisniewski
ed46cd77e6 Add laser ship vessel and its skill shot (#58)
A manually aimed instant beam, modelled on the gas bomber's press-drag-
release aiming (GasBombController/VesselGasBomberComponent) but firing
the moment the touch releases - no projectile travel time. Damage,
beam_range and cooldown are resolved per ship from base_stats/upgrades
(VesselLaserComponent.apply_stats(), the same pattern
VesselWeaponComponent uses) rather than hardcoded in the controller, so
the new damage/range/cooldown ship-lab upgrades actually reach them.
Cooldown lives on the component (per ship), not the controller (per
fleet) - two laser ships give two shots, the exact bug already fixed
for bombers in eb79efd.

LaserController.gd is reused unmodified by both Main.tscn and
PlanetSurface.tscn (relative ../Fleet, ../Camera2D, ../UI/LaserButton
paths, matching GasBombController), so it works identically in space
and on a landed surface. Wired into GameController's touch/drag
first-refusal chain alongside the bomb controller.

The crafter, hangar and ship-lab menus were already generic over
VesselDefinitions.fleet()/.all() - only the per-vessel Main.tscn nodes
are hand-placed, not the logic - so this repacks those rows to
5/5/6 columns and extends BuildController's onready arrays. No new
signal handlers were needed. Also fixes test_vessel_composition.gd's
hardcoded fleet-catalog size again (4 -> 5) now that laser is a fifth
fleet-eligible vessel.

Note for later tickets: a brand-new class_name script (LaserController)
resolves fine as a static type when its own file is the godot -s entry
point, but the identical type hint fails to parse ("Could not find
type") when the script holding it is only reached indirectly - e.g.
Main.tscn loaded from inside a _screenshot_tool.gd preview. Untyped
Node + duck-typed calls sidesteps it; GameController.gd's
laser_controller field documents this in place.
2026-08-16 17:29:53 +02:00
Loïc Wisniewski
1d9afcbc2e Add gas bomber skill-shot vessel 2026-08-15 04:45:15 +02:00
Loïc Wisniewski
85814ce88c Initial commit: SpaceshipTest, a top-down space RTS in Godot 4.7.1
A fleet of neon-outlined ships explores a procedurally generated, seeded
infinite world: tap/joystick steering, pinch zoom, formation pivoting,
planet landings, an ore economy with extractors and haulers, and player
built structures (mothership, ship crafter, command centre).

All art is hand-drawn with draw_* calls rather than textures, and the
backgrounds are camera-relative shaders so they stay precise at large
world coordinates.

Includes a 35-test headless suite (tests/run_tests.sh) plus screenshot
tooling that renders real frames through Xvfb and Mesa softpipe, since
--headless has no GPU.

Excluded from version control: .godot/ (import cache, and it holds
export credentials), builds/, android/build/ and packaged APKs - all
regenerable, and ~325 MB combined.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 18:41:58 +02:00