Ładowanei solarne
This commit is contained in:
parent
769d74b046
commit
d0c79cafe9
@ -244,7 +244,7 @@ KOSZT ENERGII WYLOSOWANEJ BRONI
|
|||||||
|
|
||||||
ItemInstance.get_energy_cost() jest wspólne dla tooltipów i strzelania każdą bronią.
|
ItemInstance.get_energy_cost() jest wspólne dla tooltipów i strzelania każdą bronią.
|
||||||
Koszt = bazowy energy_cost * (średnie obrażenia / średnie obrażenia startowe)^0.5
|
Koszt = bazowy energy_cost * (średnie obrażenia / średnie obrażenia startowe)^0.5
|
||||||
* (1 + liczba addonów * 0.05), zaokrąglony do 0.1 pkt.
|
* (1 + liczba addonów * 0.05), zaokrąglony do 0.1 pkt.
|
||||||
Wyższy poziom zwiększa zakres obrażeń, a przez niego koszt. Czterokrotnie wyższe
|
Wyższy poziom zwiększa zakres obrażeń, a przez niego koszt. Czterokrotnie wyższe
|
||||||
średnie obrażenia dają dwukrotny koszt przed addonami. Każdy addon dodaje 5% kosztu.
|
średnie obrażenia dają dwukrotny koszt przed addonami. Każdy addon dodaje 5% kosztu.
|
||||||
Bonusy kapitana i innych zamontowanych przedmiotów nie zmieniają kosztu tego egzemplarza.
|
Bonusy kapitana i innych zamontowanych przedmiotów nie zmieniają kosztu tego egzemplarza.
|
||||||
|
|||||||
23
scripts/game/combat_flash.gd
Normal file
23
scripts/game/combat_flash.gd
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
extends Node2D
|
||||||
|
|
||||||
|
var flash_color := Color("77e8bc")
|
||||||
|
var _age := 0.0
|
||||||
|
const DURATION := 0.45
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
z_index = 25
|
||||||
|
|
||||||
|
func _process(delta: float) -> void:
|
||||||
|
_age += delta
|
||||||
|
if _age >= DURATION:
|
||||||
|
queue_free()
|
||||||
|
else:
|
||||||
|
queue_redraw()
|
||||||
|
|
||||||
|
func _draw() -> void:
|
||||||
|
var progress := _age / DURATION
|
||||||
|
var color := Color(flash_color, 1.0 - progress)
|
||||||
|
draw_arc(Vector2.ZERO, 24 + progress * 36, 0, TAU, 48, color, 3.0 * (1.0 - progress) + 1.0, true)
|
||||||
|
for index in 6:
|
||||||
|
var direction := Vector2.RIGHT.rotated(TAU * index / 6.0)
|
||||||
|
draw_line(direction * (20 + progress * 20), direction * (30 + progress * 42), color, 2.0, true)
|
||||||
1
scripts/game/combat_flash.gd.uid
Normal file
1
scripts/game/combat_flash.gd.uid
Normal file
@ -0,0 +1 @@
|
|||||||
|
uid://cex3lvclwdgjk
|
||||||
@ -2,6 +2,7 @@ extends Label
|
|||||||
|
|
||||||
@export var text_color := Color(1.0, 0.78, 0.28, 1.0)
|
@export var text_color := Color(1.0, 0.78, 0.28, 1.0)
|
||||||
@export var is_critical := false
|
@export var is_critical := false
|
||||||
|
@export var is_evade := false
|
||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
z_index = 30
|
z_index = 30
|
||||||
@ -9,7 +10,10 @@ func _ready() -> void:
|
|||||||
add_theme_color_override("font_shadow_color", Color(0.05, 0.08, 0.12, 0.95))
|
add_theme_color_override("font_shadow_color", Color(0.05, 0.08, 0.12, 0.95))
|
||||||
add_theme_constant_override("shadow_offset_x", 2)
|
add_theme_constant_override("shadow_offset_x", 2)
|
||||||
add_theme_constant_override("shadow_offset_y", 2)
|
add_theme_constant_override("shadow_offset_y", 2)
|
||||||
add_theme_font_size_override("font_size", 25 if is_critical else 19)
|
add_theme_font_size_override("font_size", 28 if is_critical else (24 if is_evade else 19))
|
||||||
|
if is_critical or is_evade:
|
||||||
|
scale = Vector2.ONE * 1.2
|
||||||
|
create_tween().tween_property(self, "scale", Vector2.ONE, 0.18).set_trans(Tween.TRANS_BACK).set_ease(Tween.EASE_OUT)
|
||||||
var tween := create_tween()
|
var tween := create_tween()
|
||||||
tween.set_parallel(true)
|
tween.set_parallel(true)
|
||||||
tween.tween_property(self, "position:y", position.y - 48.0, 0.8).set_ease(Tween.EASE_OUT)
|
tween.tween_property(self, "position:y", position.y - 48.0, 0.8).set_ease(Tween.EASE_OUT)
|
||||||
|
|||||||
@ -123,6 +123,12 @@ func _spawn_destruction_effect() -> void:
|
|||||||
effect.call("configure", true, Color(1.0, 0.36, 0.18))
|
effect.call("configure", true, Color(1.0, 0.36, 0.18))
|
||||||
|
|
||||||
func _show_damage_popup(amount: float, critical: bool = false) -> void:
|
func _show_damage_popup(amount: float, critical: bool = false) -> void:
|
||||||
|
if critical:
|
||||||
|
var flash := Node2D.new()
|
||||||
|
flash.set_script(preload("res://scripts/game/combat_flash.gd"))
|
||||||
|
flash.set("flash_color", Color("ffbc5c"))
|
||||||
|
flash.position = position
|
||||||
|
get_parent().add_child(flash)
|
||||||
var popup := DAMAGE_POPUP_SCENE.instantiate() as Label
|
var popup := DAMAGE_POPUP_SCENE.instantiate() as Label
|
||||||
popup.text = "%s-%s DMG" % ["KRYT! " if critical else "", _format_damage(amount)]
|
popup.text = "%s-%s DMG" % ["KRYT! " if critical else "", _format_damage(amount)]
|
||||||
popup.set("is_critical", critical)
|
popup.set("is_critical", critical)
|
||||||
|
|||||||
@ -9,8 +9,20 @@ extends CanvasLayer
|
|||||||
var _debug_expanded := true
|
var _debug_expanded := true
|
||||||
var _ability_buttons: Dictionary = {}
|
var _ability_buttons: Dictionary = {}
|
||||||
var _ability_bar: HBoxContainer
|
var _ability_bar: HBoxContainer
|
||||||
|
var _ability_ready_style: StyleBoxFlat
|
||||||
|
var _ability_blocked_style: StyleBoxFlat
|
||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
|
var energy_indicator := Node2D.new()
|
||||||
|
energy_indicator.name = "EnergyIndicator"
|
||||||
|
energy_indicator.set_script(preload("res://scripts/game/ship_energy_indicator.gd"))
|
||||||
|
energy_indicator.set("player", player)
|
||||||
|
player.add_child(energy_indicator)
|
||||||
|
var feedback := Control.new()
|
||||||
|
feedback.name = "CombatFeedback"
|
||||||
|
feedback.set_script(preload("res://scripts/ui/combat_feedback.gd"))
|
||||||
|
feedback.set("player", player)
|
||||||
|
$HUDRoot.add_child(feedback)
|
||||||
debug_info.add_theme_font_size_override("font_size", 9)
|
debug_info.add_theme_font_size_override("font_size", 9)
|
||||||
# Establish anchor layout before applying offsets; absolute layout resets anchors.
|
# Establish anchor layout before applying offsets; absolute layout resets anchors.
|
||||||
var equipment := $HUDRoot/ShipEquipmentPanel as Control
|
var equipment := $HUDRoot/ShipEquipmentPanel as Control
|
||||||
@ -81,7 +93,7 @@ OBRÓT: %.2f rad/s""" % [
|
|||||||
roundi(float(player.get("hull"))), roundi(float(player.get("max_hull"))),
|
roundi(float(player.get("hull"))), roundi(float(player.get("max_hull"))),
|
||||||
roundi(float(player.get("shields"))), roundi(float(player.get("max_shields"))),
|
roundi(float(player.get("shields"))), roundi(float(player.get("max_shields"))),
|
||||||
roundi(float(player.get("energy"))), roundi(float(player.get("max_energy"))),
|
roundi(float(player.get("energy"))), roundi(float(player.get("max_energy"))),
|
||||||
float(player.get("energy_regeneration")),
|
float(player.get("energy_regeneration")) + float(player.call("get_solar_regeneration")),
|
||||||
float(player.get("shield_regeneration")),
|
float(player.get("shield_regeneration")),
|
||||||
ship_velocity.length(), ship_velocity.x, ship_velocity.y,
|
ship_velocity.length(), ship_velocity.x, ship_velocity.y,
|
||||||
ship_position.x, ship_position.y, rad_to_deg(player.rotation), angular_speed,
|
ship_position.x, ship_position.y, rad_to_deg(player.rotation), angular_speed,
|
||||||
@ -109,6 +121,7 @@ Szansa na unik: %.1f%%
|
|||||||
Redukcja obrażeń: %.1f%%
|
Redukcja obrażeń: %.1f%%
|
||||||
|
|
||||||
Regeneracja energii: %.1f pkt/s (%+.1f)
|
Regeneracja energii: %.1f pkt/s (%+.1f)
|
||||||
|
Ładowanie solarne: +%.1f pkt/s
|
||||||
Regeneracja tarcz: %.1f pkt/s (%+.1f)
|
Regeneracja tarcz: %.1f pkt/s (%+.1f)
|
||||||
Maks. kadłub: %.1f (%+.1f pkt)
|
Maks. kadłub: %.1f (%+.1f pkt)
|
||||||
Maks. tarcze: %.1f (%+.1f pkt)
|
Maks. tarcze: %.1f (%+.1f pkt)
|
||||||
@ -125,6 +138,7 @@ Zdobywane kredyty: %+.1f%%""" % [
|
|||||||
float(player.call("get_damage_reduction")) * 100.0,
|
float(player.call("get_damage_reduction")) * 100.0,
|
||||||
float(player.get("energy_regeneration")),
|
float(player.get("energy_regeneration")),
|
||||||
float(player.get("energy_regeneration")) - float(player.get("base_energy_regeneration")),
|
float(player.get("energy_regeneration")) - float(player.get("base_energy_regeneration")),
|
||||||
|
float(player.call("get_solar_regeneration")),
|
||||||
float(player.get("shield_regeneration")),
|
float(player.get("shield_regeneration")),
|
||||||
float(player.get("shield_regeneration")) - float(player.get("base_shield_regeneration")),
|
float(player.get("shield_regeneration")) - float(player.get("base_shield_regeneration")),
|
||||||
float(player.get("max_hull")), float(player.get("max_hull")) - float(player.get("base_max_hull")),
|
float(player.get("max_hull")), float(player.get("max_hull")) - float(player.get("base_max_hull")),
|
||||||
@ -136,6 +150,8 @@ Zdobywane kredyty: %+.1f%%""" % [
|
|||||||
]
|
]
|
||||||
|
|
||||||
func _create_ability_bar() -> void:
|
func _create_ability_bar() -> void:
|
||||||
|
_ability_ready_style = _make_ability_style(true)
|
||||||
|
_ability_blocked_style = _make_ability_style(false)
|
||||||
var panel := PanelContainer.new()
|
var panel := PanelContainer.new()
|
||||||
panel.name = "ActiveAbilities"
|
panel.name = "ActiveAbilities"
|
||||||
$HUDRoot.add_child(panel)
|
$HUDRoot.add_child(panel)
|
||||||
@ -168,6 +184,20 @@ func _update_ability_bar() -> void:
|
|||||||
any_equipped = true
|
any_equipped = true
|
||||||
var reason: String = player.call("ability_unavailable_reason", index)
|
var reason: String = player.call("ability_unavailable_reason", index)
|
||||||
button.disabled = not reason.is_empty()
|
button.disabled = not reason.is_empty()
|
||||||
button.text = "[%d] %s" % [index + 1, ability.display_name]
|
button.text = "[%d] %s\n%s" % [index + 1, ability.display_name, "GOTOWE" if reason.is_empty() else reason]
|
||||||
|
var style := _ability_ready_style if reason.is_empty() else _ability_blocked_style
|
||||||
|
button.add_theme_stylebox_override("normal", style)
|
||||||
|
button.add_theme_stylebox_override("disabled", style)
|
||||||
|
button.add_theme_stylebox_override("hover", style)
|
||||||
|
button.add_theme_color_override("font_color", Color("a5ffda"))
|
||||||
|
button.add_theme_color_override("font_disabled_color", Color("a3aebb"))
|
||||||
button.tooltip_text = ability.description + ("\n" + reason if not reason.is_empty() else "\nGotowe")
|
button.tooltip_text = ability.description + ("\n" + reason if not reason.is_empty() else "\nGotowe")
|
||||||
_ability_bar.get_parent().visible = any_equipped
|
_ability_bar.get_parent().visible = any_equipped
|
||||||
|
|
||||||
|
func _make_ability_style(ready: bool) -> StyleBoxFlat:
|
||||||
|
var style := StyleBoxFlat.new()
|
||||||
|
style.bg_color = Color("174237") if ready else Color("202731")
|
||||||
|
style.border_color = Color("77e8bc") if ready else Color("526071")
|
||||||
|
style.set_border_width_all(2 if ready else 1)
|
||||||
|
style.set_content_margin_all(6)
|
||||||
|
return style
|
||||||
|
|||||||
@ -71,6 +71,12 @@ func _spawn_celestial_bodies() -> void:
|
|||||||
star.set("radius", 140.0)
|
star.set("radius", 140.0)
|
||||||
star.set("is_star", true)
|
star.set("is_star", true)
|
||||||
bodies.add_child(star)
|
bodies.add_child(star)
|
||||||
|
player.set("charging_star", star)
|
||||||
|
var solar_effect := Node2D.new()
|
||||||
|
solar_effect.name = "SolarEnergyEffect"
|
||||||
|
solar_effect.set_script(preload("res://scripts/game/solar_energy_effect.gd"))
|
||||||
|
solar_effect.set("player", player)
|
||||||
|
player.add_child(solar_effect)
|
||||||
for index in system_data["planets"].size():
|
for index in system_data["planets"].size():
|
||||||
var data: Dictionary = system_data["planets"][index]
|
var data: Dictionary = system_data["planets"][index]
|
||||||
var planet := Node2D.new()
|
var planet := Node2D.new()
|
||||||
|
|||||||
@ -6,6 +6,7 @@ const DAMAGE_POPUP_SCENE := preload("res://scenes/game/damage_popup.tscn")
|
|||||||
const COMBAT_ROLLS := preload("res://scripts/game/combat_rolls.gd")
|
const COMBAT_ROLLS := preload("res://scripts/game/combat_rolls.gd")
|
||||||
const CAPTAIN_BALANCE := preload("res://scripts/captain/captain_balance.gd")
|
const CAPTAIN_BALANCE := preload("res://scripts/captain/captain_balance.gd")
|
||||||
const SHIP_CATALOG := preload("res://scripts/game/ship_catalog.gd")
|
const SHIP_CATALOG := preload("res://scripts/game/ship_catalog.gd")
|
||||||
|
const COMBAT_FLASH := preload("res://scripts/game/combat_flash.gd")
|
||||||
|
|
||||||
@export var max_speed := 76.0
|
@export var max_speed := 76.0
|
||||||
@export var reverse_max_speed := 210.0
|
@export var reverse_max_speed := 210.0
|
||||||
@ -36,6 +37,10 @@ var experience_multiplier := 1.0
|
|||||||
var credits_multiplier := 1.0
|
var credits_multiplier := 1.0
|
||||||
var critical_chance_bonus := 0.0
|
var critical_chance_bonus := 0.0
|
||||||
var critical_damage_bonus := 0.0
|
var critical_damage_bonus := 0.0
|
||||||
|
@export var solar_charge_radius := 550.0
|
||||||
|
@export var solar_charge_full_radius := 300.0
|
||||||
|
@export var solar_charge_fraction_per_second := 0.25
|
||||||
|
var charging_star: Node2D
|
||||||
|
|
||||||
var angular_velocity := 0.0
|
var angular_velocity := 0.0
|
||||||
var _sprite: Sprite2D
|
var _sprite: Sprite2D
|
||||||
@ -114,8 +119,14 @@ func take_damage(amount: float) -> void:
|
|||||||
return
|
return
|
||||||
var hit := COMBAT_ROLLS.incoming_hit(amount, get_evasion_chance(), get_damage_reduction())
|
var hit := COMBAT_ROLLS.incoming_hit(amount, get_evasion_chance(), get_damage_reduction())
|
||||||
if hit["evaded"]:
|
if hit["evaded"]:
|
||||||
|
var flash := Node2D.new()
|
||||||
|
flash.set_script(COMBAT_FLASH)
|
||||||
|
flash.set("flash_color", Color("77e8bc"))
|
||||||
|
flash.position = position
|
||||||
|
get_parent().add_child(flash)
|
||||||
var popup := DAMAGE_POPUP_SCENE.instantiate() as Label
|
var popup := DAMAGE_POPUP_SCENE.instantiate() as Label
|
||||||
popup.text = "UNIK"
|
popup.text = "UNIK"
|
||||||
|
popup.set("is_evade", true)
|
||||||
popup.set("text_color", Color("77e8bc"))
|
popup.set("text_color", Color("77e8bc"))
|
||||||
popup.position = position + Vector2(-20, -38)
|
popup.position = position + Vector2(-20, -38)
|
||||||
get_parent().add_child(popup)
|
get_parent().add_child(popup)
|
||||||
@ -191,7 +202,7 @@ func _physics_process(delta: float) -> void:
|
|||||||
if _is_destroyed or is_docked:
|
if _is_destroyed or is_docked:
|
||||||
return
|
return
|
||||||
_contact_damage_timer = maxf(0.0, _contact_damage_timer - delta)
|
_contact_damage_timer = maxf(0.0, _contact_damage_timer - delta)
|
||||||
energy = minf(max_energy, energy + energy_regeneration * delta)
|
energy = minf(max_energy, energy + (energy_regeneration + get_solar_regeneration()) * delta)
|
||||||
var was_boosting := is_boosting()
|
var was_boosting := is_boosting()
|
||||||
if _boost_target > 0.0:
|
if _boost_target > 0.0:
|
||||||
_boost_speed = move_toward(_boost_speed, _boost_target, _boost_acceleration * delta)
|
_boost_speed = move_toward(_boost_speed, _boost_target, _boost_acceleration * delta)
|
||||||
@ -265,6 +276,13 @@ func _clamp_velocity_to_max_speed() -> void:
|
|||||||
func is_boosting() -> bool:
|
func is_boosting() -> bool:
|
||||||
return _boost_target > 0.0 or _boost_speed > 0.0
|
return _boost_target > 0.0 or _boost_speed > 0.0
|
||||||
|
|
||||||
|
func get_solar_regeneration() -> float:
|
||||||
|
if _is_destroyed or is_docked or not is_instance_valid(charging_star):
|
||||||
|
return 0.0
|
||||||
|
var distance := global_position.distance_to(charging_star.global_position)
|
||||||
|
var strength := 1.0 - smoothstep(solar_charge_full_radius, solar_charge_radius, distance)
|
||||||
|
return max_energy * solar_charge_fraction_per_second * strength
|
||||||
|
|
||||||
func start_boost(speed_bonus: float, acceleration_time: float) -> void:
|
func start_boost(speed_bonus: float, acceleration_time: float) -> void:
|
||||||
_boost_target = max_speed * maxf(0.0, speed_bonus)
|
_boost_target = max_speed * maxf(0.0, speed_bonus)
|
||||||
_boost_acceleration = _boost_target / maxf(0.01, acceleration_time)
|
_boost_acceleration = _boost_target / maxf(0.01, acceleration_time)
|
||||||
|
|||||||
52
scripts/game/ship_energy_indicator.gd
Normal file
52
scripts/game/ship_energy_indicator.gd
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
extends Node2D
|
||||||
|
|
||||||
|
const FONT := preload("res://assets/fonts/font2.ttf")
|
||||||
|
var player: CharacterBody2D
|
||||||
|
var _display_ratio := 1.0
|
||||||
|
var _background: StyleBoxFlat
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
# World rendering interpolates this position together with the ship and camera.
|
||||||
|
top_level = true
|
||||||
|
process_physics_priority = 1
|
||||||
|
global_position = player.global_position
|
||||||
|
reset_physics_interpolation()
|
||||||
|
z_index = 24
|
||||||
|
_display_ratio = _energy_ratio()
|
||||||
|
_background = StyleBoxFlat.new()
|
||||||
|
_background.bg_color = Color("101925")
|
||||||
|
_background.border_color = Color("456277")
|
||||||
|
_background.set_border_width_all(1)
|
||||||
|
|
||||||
|
func _physics_process(_delta: float) -> void:
|
||||||
|
if is_instance_valid(player):
|
||||||
|
var teleported := global_position.distance_to(player.global_position) > 600.0
|
||||||
|
global_position = player.global_position
|
||||||
|
if teleported:
|
||||||
|
reset_physics_interpolation()
|
||||||
|
|
||||||
|
func _process(delta: float) -> void:
|
||||||
|
if not is_instance_valid(player):
|
||||||
|
return
|
||||||
|
visible = not bool(player.get("_is_destroyed"))
|
||||||
|
var target := _energy_ratio()
|
||||||
|
_display_ratio = lerpf(_display_ratio, target, 1.0 - exp(-20.0 * delta))
|
||||||
|
if absf(_display_ratio - target) < 0.001:
|
||||||
|
_display_ratio = target
|
||||||
|
queue_redraw()
|
||||||
|
|
||||||
|
func _energy_ratio() -> float:
|
||||||
|
return clampf(float(player.get("energy")) / maxf(1.0, float(player.get("max_energy"))), 0.0, 1.0)
|
||||||
|
|
||||||
|
func _draw() -> void:
|
||||||
|
if not is_instance_valid(player):
|
||||||
|
return
|
||||||
|
var color := Color("71e3ff") if _energy_ratio() >= 0.25 else Color("ffbd66")
|
||||||
|
var bar_position := Vector2(-44, 48)
|
||||||
|
draw_style_box(_background, Rect2(bar_position - Vector2(2, 2), Vector2(92, 10)))
|
||||||
|
draw_rect(Rect2(bar_position, Vector2(88 * _display_ratio, 6)), color)
|
||||||
|
var charging := float(player.call("get_solar_regeneration")) > 0.0 and _energy_ratio() < 1.0
|
||||||
|
var caption := "ENERGIA %d%%" % roundi(_energy_ratio() * 100)
|
||||||
|
draw_string(FONT, bar_position + Vector2(0, 22), caption, HORIZONTAL_ALIGNMENT_CENTER, 88, 10, color)
|
||||||
|
if charging:
|
||||||
|
draw_string(FONT, bar_position + Vector2(-18, 36), "ŁADOWANIE SOLARNE", HORIZONTAL_ALIGNMENT_CENTER, 124, 9, Color("71e3ff"))
|
||||||
1
scripts/game/ship_energy_indicator.gd.uid
Normal file
1
scripts/game/ship_energy_indicator.gd.uid
Normal file
@ -0,0 +1 @@
|
|||||||
|
uid://bcs2adil8qg4e
|
||||||
54
scripts/game/solar_energy_effect.gd
Normal file
54
scripts/game/solar_energy_effect.gd
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
extends Node2D
|
||||||
|
|
||||||
|
var player: CharacterBody2D
|
||||||
|
var _particles: Array[Dictionary] = []
|
||||||
|
var _emission := 0.0
|
||||||
|
var _phase := 0.0
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
top_level = true
|
||||||
|
process_physics_priority = 1
|
||||||
|
global_position = player.global_position
|
||||||
|
reset_physics_interpolation()
|
||||||
|
z_index = 22
|
||||||
|
|
||||||
|
func _physics_process(_delta: float) -> void:
|
||||||
|
if is_instance_valid(player):
|
||||||
|
global_position = player.global_position
|
||||||
|
|
||||||
|
func _process(delta: float) -> void:
|
||||||
|
if not is_instance_valid(player):
|
||||||
|
return
|
||||||
|
_phase += delta
|
||||||
|
var bonus := float(player.call("get_solar_regeneration"))
|
||||||
|
var charging := bonus > 0.0 and float(player.get("energy")) < float(player.get("max_energy"))
|
||||||
|
if charging:
|
||||||
|
_emission += delta * 30.0
|
||||||
|
while _emission >= 1.0 and _particles.size() < 32:
|
||||||
|
_emission -= 1.0
|
||||||
|
var star: Node2D = player.get("charging_star")
|
||||||
|
var direction := (global_position - star.global_position).normalized()
|
||||||
|
var source := star.global_position + direction * float(star.get("radius"))
|
||||||
|
source += direction.orthogonal() * randf_range(-35.0, 35.0)
|
||||||
|
_particles.append({"source": source, "age": 0.0, "duration": randf_range(0.45, 0.8)})
|
||||||
|
else:
|
||||||
|
_emission = 0.0
|
||||||
|
for index in range(_particles.size() - 1, -1, -1):
|
||||||
|
_particles[index]["age"] += delta
|
||||||
|
if _particles[index]["age"] >= _particles[index]["duration"]:
|
||||||
|
_particles.remove_at(index)
|
||||||
|
queue_redraw()
|
||||||
|
|
||||||
|
func _draw() -> void:
|
||||||
|
if not is_instance_valid(player) or bool(player.get("_is_destroyed")):
|
||||||
|
return
|
||||||
|
for particle in _particles:
|
||||||
|
var progress: float = particle["age"] / particle["duration"]
|
||||||
|
var source: Vector2 = particle["source"] - global_position
|
||||||
|
var point := source.lerp(Vector2.ZERO, progress * progress)
|
||||||
|
var tail := source.lerp(Vector2.ZERO, maxf(0, progress - 0.06) ** 2)
|
||||||
|
var color := Color(0.35, 0.92, 1.0, sin(progress * PI))
|
||||||
|
draw_line(tail, point, color, 2.0, true)
|
||||||
|
draw_circle(point, 2.5, color)
|
||||||
|
if not _particles.is_empty():
|
||||||
|
draw_arc(Vector2.ZERO, 31.0 + sin(_phase * 5.0) * 2.0, 0, TAU, 48, Color(0.35, 0.92, 1.0, 0.45), 2.0, true)
|
||||||
1
scripts/game/solar_energy_effect.gd.uid
Normal file
1
scripts/game/solar_energy_effect.gd.uid
Normal file
@ -0,0 +1 @@
|
|||||||
|
uid://og6r3ft88u16
|
||||||
27
scripts/ui/combat_feedback.gd
Normal file
27
scripts/ui/combat_feedback.gd
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
extends Control
|
||||||
|
|
||||||
|
const FONT := preload("res://assets/fonts/font2.ttf")
|
||||||
|
const LOW_HULL_RATIO := 0.25
|
||||||
|
var player: CharacterBody2D
|
||||||
|
var _elapsed := 0.0
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||||
|
set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
||||||
|
|
||||||
|
func _process(delta: float) -> void:
|
||||||
|
_elapsed += delta
|
||||||
|
queue_redraw()
|
||||||
|
|
||||||
|
func _draw() -> void:
|
||||||
|
if not is_instance_valid(player) or bool(player.get("_is_destroyed")):
|
||||||
|
return
|
||||||
|
var hull := float(player.get("hull"))
|
||||||
|
var max_hull := maxf(1.0, float(player.get("max_hull")))
|
||||||
|
if hull / max_hull > LOW_HULL_RATIO or bool(player.get("is_docked")):
|
||||||
|
return
|
||||||
|
var pulse := 0.55 + 0.25 * (sin(_elapsed * TAU) + 1.0) * 0.5
|
||||||
|
var warning_color := Color(1.0, 0.32, 0.26, pulse)
|
||||||
|
draw_rect(Rect2(Vector2(3, 3), size - Vector2(6, 6)), warning_color, false, 3)
|
||||||
|
var warning := "NISKI KADŁUB — %d%%" % roundi(hull / max_hull * 100)
|
||||||
|
draw_string(FONT, Vector2(0, 34), warning, HORIZONTAL_ALIGNMENT_CENTER, size.x, 18, warning_color)
|
||||||
1
scripts/ui/combat_feedback.gd.uid
Normal file
1
scripts/ui/combat_feedback.gd.uid
Normal file
@ -0,0 +1 @@
|
|||||||
|
uid://dxso36ob0ovm5
|
||||||
@ -63,6 +63,7 @@ func _ready() -> void:
|
|||||||
assert(before == Vector2(float(player.get("hull")), float(player.get("shields"))))
|
assert(before == Vector2(float(player.get("hull")), float(player.get("shields"))))
|
||||||
profile.skills["piloting"] = 0
|
profile.skills["piloting"] = 0
|
||||||
profile.skills["mechanic"] = 50
|
profile.skills["mechanic"] = 50
|
||||||
|
player.set("shields", 100.0) # Fixed fixture, independent of selected chassis capacity.
|
||||||
player.call("take_damage", 100.0)
|
player.call("take_damage", 100.0)
|
||||||
assert(float(player.get("shields")) == 50 and float(player.get("hull")) == 100)
|
assert(float(player.get("shields")) == 50 and float(player.get("hull")) == 100)
|
||||||
player.set("shields", 0.0)
|
player.set("shields", 0.0)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user