extends Node const WORLD_SIZE := preload("res://scripts/levels/system_generator.gd").WORLD_SIZE const PULSE := preload("res://scripts/game/extension_pulse.gd") var cooldowns: Dictionary = {} var cloak_remaining := 0.0 var solar_remaining := 0.0 var _cloak_material: ShaderMaterial var _old_material: Material var _shadow_was_visible := false var _visual_colors: Dictionary = {} var _destination := Vector2.ZERO var _has_destination := false @onready var ship: CharacterBody2D = get_parent() func reset_combat_state() -> void: cooldowns.clear() solar_remaining = 0.0 if cloak_remaining > 0.0: _end_cloak() func _physics_process(delta: float) -> void: for id in cooldowns.keys(): cooldowns[id] = maxf(0.0, float(cooldowns[id]) - delta) if cloak_remaining > 0.0: cloak_remaining = maxf(0.0, cloak_remaining - delta) if _cloak_material != null: _cloak_material.set_shader_parameter("elapsed", 10.0 - cloak_remaining) if cloak_remaining <= 0.0 or bool(ship.get("_is_destroyed")): _end_cloak() if solar_remaining > 0.0: var available_time := minf(delta, solar_remaining) solar_remaining = maxf(0.0, solar_remaining - delta) if bool(ship.get("_is_destroyed")) or bool(ship.get("is_docked")) or float(ship.call("get_solar_regeneration")) <= 0.0 or GameState.captain.is_skill_active("power_redirect"): solar_remaining = 0.0 return var maximum := float(ship.get("max_shields")) ship.set("shields", minf(maximum, float(ship.get("shields")) + maximum * available_time / 5.0)) ship.call("_update_shield_visual") ship.get_node("ShieldVisual").call("flash_hit") if float(ship.get("shields")) >= maximum: solar_remaining = 0.0 func _safe_destination(point: Vector2) -> bool: var query := PhysicsShapeQueryParameters2D.new() var shape := CircleShape2D.new() shape.radius = 65.0 query.shape = shape query.transform = Transform2D(0.0, point) query.collision_mask = 5 query.exclude = [ship.get_rid()] return ship.get_world_2d().direct_space_state.intersect_shape(query, 1).is_empty() func has_teleport_destination() -> bool: if _has_destination and _destination.distance_to(ship.global_position) >= 400.0 and _safe_destination(_destination): return true var half := WORLD_SIZE * 0.5 - Vector2(160, 160) for attempt in 48: var candidate := Vector2(randf_range(-half.x, half.x), randf_range(-half.y, half.y)) if candidate.distance_to(ship.global_position) >= 400.0 and _safe_destination(candidate): _destination = candidate _has_destination = true return true _has_destination = false return false func activate(kind: int) -> void: match kind: 0: if not has_teleport_destination(): return _teleport_effect(ship.global_position, false) ship.global_position = _destination _has_destination = false ship.velocity = Vector2.ZERO ship.set("angular_velocity", 0.0) ship.set("_boost_target", 0.0) ship.set("_boost_speed", 0.0) ship.set("_mini_boost_coast_speed", 0.0) ship.set("energy", 0.0) ship.reset_physics_interpolation() ship.get_node("Camera2D").reset_smoothing() _teleport_effect(ship.global_position, true) 1: _start_cloak() 2: var mine := Node2D.new() mine.set_script(preload("res://scripts/game/deployed_mine.gd")) var drop_direction := Vector2.DOWN.rotated(ship.rotation) mine.position = ship.position + drop_direction * 42.0 mine.set("drift", drop_direction * 36.0) _deployment_effect(mine.position, drop_direction, Color("8ad7e7")) ship.get_parent().add_child(mine) 3: _deployment_effect(ship.position + Vector2.DOWN.rotated(ship.rotation) * 28.0, Vector2.DOWN.rotated(ship.rotation), Color("ffb15c")) for index in 3: var flare := StaticBody2D.new() flare.set_script(preload("res://scripts/game/deployed_flare.gd")) var direction := Vector2.DOWN.rotated(ship.rotation + (float(index) - 1.0) * 0.8) flare.position = ship.position + direction * 48.0 flare.set("drift", direction * 90.0 + ship.velocity * 0.25) ship.get_parent().add_child(flare) 4: solar_remaining = 5.0 _pulse(ship.global_position, Color("70dfff"), 50.0) func _teleport_effect(point: Vector2, arriving: bool) -> void: var effect := Node2D.new() effect.set_script(preload("res://scripts/game/teleport_vortex.gd")) effect.position = point effect.set("arriving", arriving) effect.set("ship_texture", ship.get_node("Sprite2D").get("texture")) effect.set("ship_rotation", ship.rotation) ship.get_parent().add_child(effect) func _deployment_effect(point: Vector2, direction: Vector2, color: Color) -> void: var effect := Node2D.new() effect.set_script(preload("res://scripts/game/deployment_flash.gd")) effect.position = point effect.set("direction", direction) effect.set("color", color) ship.get_parent().add_child(effect) func _start_cloak() -> void: cloak_remaining = 10.0 var sprite := ship.get_node("Sprite2D") as Sprite2D _old_material = sprite.material _cloak_material = ShaderMaterial.new() _cloak_material.shader = preload("res://resources/ui/cloak.gdshader") sprite.material = _cloak_material var shadow := sprite.get_node_or_null("ShipShadow") as CanvasItem if shadow != null: _shadow_was_visible = shadow.visible shadow.hide() for name in ["ShieldVisual", "EngineVisual", "SolarEnergyEffect", "EnergyIndicator"]: var visual := ship.get_node_or_null(name) as CanvasItem if visual != null: _visual_colors[name] = visual.modulate visual.modulate = Color(visual.modulate, 0.08) _pulse(ship.global_position, Color("81e4ef"), 40.0) func _end_cloak() -> void: cloak_remaining = 0.0 ship.get_node("Sprite2D").set("material", _old_material) _cloak_material = null var shadow := ship.get_node_or_null("Sprite2D/ShipShadow") as CanvasItem if shadow != null: shadow.visible = _shadow_was_visible for name in _visual_colors: var visual := ship.get_node_or_null(NodePath(name)) as CanvasItem if visual != null: visual.modulate = _visual_colors[name] _visual_colors.clear() func _pulse(point: Vector2, color: Color, radius: float) -> void: var pulse := Node2D.new() pulse.set_script(PULSE) pulse.position = point pulse.set("color", color) pulse.set("radius", radius) ship.get_parent().add_child(pulse)