spaceship/VesselLaserComponent.gd

30 lines
814 B
GDScript3
Raw Normal View History

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
class_name VesselLaserComponent
extends "res://VesselCooldownFillComponent.gd"
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
var capability_id := "laser"
var damage: int = 2
var beam_range: float = 950.0
const READY_COLOR := Color(0.3, 0.9, 1.0)
const COOLING_COLOR := Color(0.08, 0.28, 0.34)
func _init() -> void:
cooldown_duration = 4.0
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
func apply_stats() -> void:
var ship: Node = get_parent()
var state: Node = ship.get_tree().root.get_node("GameState")
damage = int(state.vessel_stat(ship.vessel_type, "damage"))
beam_range = state.vessel_stat(ship.vessel_type, "beam_range")
cooldown_duration = state.vessel_stat(ship.vessel_type, "beam_cooldown")
queue_redraw()
func consume_shot() -> bool:
return _begin_cooldown(cooldown_duration)
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
func _ready_color() -> Color: return READY_COLOR
func _cooling_color() -> Color: return COOLING_COLOR