Randoloot/scripts/game/extension_systems.gd
2026-10-16 22:04:36 +02:00

161 lines
6.1 KiB
GDScript

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)