class_name VesselLaserComponent extends "res://vessels/VesselCooldownFillComponent.gd" var capability_id := "laser" var damage: int = 6 var beam_range: float = 2900.0 var beam_half_width: float = 38.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 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") beam_half_width = state.vessel_stat(ship.vessel_type, "beam_half_width") cooldown_duration = state.vessel_stat(ship.vessel_type, "beam_cooldown") queue_redraw() # #90/#103 follow-up: the beam is a LaserBeamEffect in the world, not # something the fleet's controller draws. See the class comment there. const BEAM_EFFECT = preload("res://vfx/LaserBeamEffect.gd") # What one shot costs, and how much a garrisoned laser keeps beside it. Data # on the component rather than in the controller: a garrison spends the same # ammunition through a different trigger. const ENERGY_PER_SHOT: int = 8 func ability_range() -> float: return beam_range func ability_ammo_resource() -> String: return GameState.RESOURCE_ENERGY func ability_ammo_cost() -> int: return ENERGY_PER_SHOT func fire_ability(world: Node, origin: Vector2, at: Vector2) -> bool: if not consume_shot(): return false var direction: Vector2 = at - origin # A beam always reaches full range; the aim chooses its direction only. BEAM_EFFECT.fire(world, origin, direction, beam_range, damage, beam_half_width) return true func consume_shot() -> bool: return _begin_cooldown(cooldown_duration) func _ready_color() -> Color: return READY_COLOR func _cooling_color() -> Color: return COOLING_COLOR