diff --git a/assets/icons/resources/copper.svg b/assets/icons/resources/copper.svg
new file mode 100644
index 0000000..f8245cc
--- /dev/null
+++ b/assets/icons/resources/copper.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/icons/resources/copper.svg.import b/assets/icons/resources/copper.svg.import
new file mode 100644
index 0000000..80a4476
--- /dev/null
+++ b/assets/icons/resources/copper.svg.import
@@ -0,0 +1,43 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://43c7sinoianv"
+path="res://.godot/imported/copper.svg-c4834a0ae790a1aca61a3ea757550082.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://assets/icons/resources/copper.svg"
+dest_files=["res://.godot/imported/copper.svg-c4834a0ae790a1aca61a3ea757550082.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/assets/icons/resources/mercury.svg b/assets/icons/resources/mercury.svg
new file mode 100644
index 0000000..93cfca3
--- /dev/null
+++ b/assets/icons/resources/mercury.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/icons/resources/mercury.svg.import b/assets/icons/resources/mercury.svg.import
new file mode 100644
index 0000000..486fed6
--- /dev/null
+++ b/assets/icons/resources/mercury.svg.import
@@ -0,0 +1,43 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://dhpa3d5vmo1xt"
+path="res://.godot/imported/mercury.svg-3546da7d239e034406cb1796c7686f29.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://assets/icons/resources/mercury.svg"
+dest_files=["res://.godot/imported/mercury.svg-3546da7d239e034406cb1796c7686f29.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/assets/icons/resources/nickel.svg b/assets/icons/resources/nickel.svg
new file mode 100644
index 0000000..ab3dd6c
--- /dev/null
+++ b/assets/icons/resources/nickel.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/icons/resources/nickel.svg.import b/assets/icons/resources/nickel.svg.import
new file mode 100644
index 0000000..6493083
--- /dev/null
+++ b/assets/icons/resources/nickel.svg.import
@@ -0,0 +1,43 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://iwgmkvim18x7"
+path="res://.godot/imported/nickel.svg-74a50f81c6a0062c599a21d76004d8b5.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://assets/icons/resources/nickel.svg"
+dest_files=["res://.godot/imported/nickel.svg-74a50f81c6a0062c599a21d76004d8b5.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/assets/icons/resources/silicon.svg b/assets/icons/resources/silicon.svg
new file mode 100644
index 0000000..ca1ca23
--- /dev/null
+++ b/assets/icons/resources/silicon.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/icons/resources/silicon.svg.import b/assets/icons/resources/silicon.svg.import
new file mode 100644
index 0000000..c9f4181
--- /dev/null
+++ b/assets/icons/resources/silicon.svg.import
@@ -0,0 +1,43 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://d30h5prcd37f1"
+path="res://.godot/imported/silicon.svg-47711e837a4f7b234816e567c07748c8.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://assets/icons/resources/silicon.svg"
+dest_files=["res://.godot/imported/silicon.svg-47711e837a4f7b234816e567c07748c8.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/assets/icons/resources/tungsten.svg b/assets/icons/resources/tungsten.svg
new file mode 100644
index 0000000..350c7e8
--- /dev/null
+++ b/assets/icons/resources/tungsten.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/icons/resources/tungsten.svg.import b/assets/icons/resources/tungsten.svg.import
new file mode 100644
index 0000000..3565545
--- /dev/null
+++ b/assets/icons/resources/tungsten.svg.import
@@ -0,0 +1,43 @@
+[remap]
+
+importer="texture"
+type="CompressedTexture2D"
+uid="uid://b1w6koagwn8x5"
+path="res://.godot/imported/tungsten.svg-59167c98018d9a1577b7791d34661e4e.ctex"
+metadata={
+"vram_texture": false
+}
+
+[deps]
+
+source_file="res://assets/icons/resources/tungsten.svg"
+dest_files=["res://.godot/imported/tungsten.svg-59167c98018d9a1577b7791d34661e4e.ctex"]
+
+[params]
+
+compress/mode=0
+compress/high_quality=false
+compress/lossy_quality=0.7
+compress/uastc_level=0
+compress/rdo_quality_loss=0.0
+compress/hdr_compression=1
+compress/normal_map=0
+compress/channel_pack=0
+mipmaps/generate=false
+mipmaps/limit=-1
+roughness/mode=0
+roughness/src_normal=""
+process/channel_remap/red=0
+process/channel_remap/green=1
+process/channel_remap/blue=2
+process/channel_remap/alpha=3
+process/fix_alpha_border=true
+process/premult_alpha=false
+process/normal_map_invert_y=false
+process/hdr_as_srgb=false
+process/hdr_clamp_exposure=false
+process/size_limit=0
+detect_3d/compress_to=1
+svg/scale=1.0
+editor/scale_with_editor_scale=false
+editor/convert_colors_with_editor_theme=false
diff --git a/scripts/game/distant_sector.gd b/scripts/game/distant_sector.gd
index e62df01..a5118a9 100644
--- a/scripts/game/distant_sector.gd
+++ b/scripts/game/distant_sector.gd
@@ -25,8 +25,8 @@ func _ready() -> void:
panel.set_anchors_and_offsets_preset(Control.PRESET_CENTER_TOP)
panel.offset_left = -195
panel.offset_right = 195
- panel.offset_top = 104
- panel.offset_bottom = 174
+ panel.offset_top = 136
+ panel.offset_bottom = 206
var ui := preload("res://scripts/planets/freighter_menu.gd")
ui.style(panel,8,0.5)
var column := VBoxContainer.new()
diff --git a/scripts/game/flight_hud.gd b/scripts/game/flight_hud.gd
index 577350b..28073b5 100644
--- a/scripts/game/flight_hud.gd
+++ b/scripts/game/flight_hud.gd
@@ -45,8 +45,8 @@ func _create_navigation() -> void:
navigation.set_anchors_and_offsets_preset(Control.PRESET_CENTER_TOP)
navigation.offset_left = -32
navigation.offset_right = 32
- navigation.offset_top = 12
- navigation.offset_bottom = 92
+ navigation.offset_top = 44
+ navigation.offset_bottom = 124
navigation.add_theme_constant_override("separation", 10)
_captain_skills_ui = CanvasLayer.new()
_captain_skills_ui.set_script(preload("res://scripts/ui/captain_skills_ui.gd"))
@@ -62,6 +62,14 @@ func _create_navigation() -> void:
func _ready() -> void:
layer = RENDER_LAYERS.HUD
+ var resource_layer := CanvasLayer.new()
+ resource_layer.name = "ResourceLedger"
+ resource_layer.layer = 70
+ resource_layer.process_mode = Node.PROCESS_MODE_ALWAYS
+ add_child(resource_layer)
+ var resource_bar := Control.new()
+ resource_bar.set_script(preload("res://scripts/ui/resource_bar.gd"))
+ resource_layer.add_child(resource_bar)
var cursor := Node.new()
cursor.name = "FlightCursor"
cursor.set_script(preload("res://scripts/ui/flight_cursor.gd"))
@@ -119,7 +127,7 @@ func _ready() -> void:
func _create_sidebar() -> void:
_captain_panel = $HUDRoot/CaptainPanel
_captain_panel.set_anchors_and_offsets_preset(Control.PRESET_TOP_LEFT)
- _captain_panel.position = Vector2(12, 12)
+ _captain_panel.position = Vector2(12, 44)
_captain_panel.size = _captain_panel.get_combined_minimum_size()
_captain_panel.resized.connect(_layout_debug)
_create_system_badge()
@@ -213,8 +221,8 @@ func _create_sidebar() -> void:
_sidebar_toggle.set_anchors_and_offsets_preset(Control.PRESET_TOP_RIGHT)
_sidebar_toggle.offset_left = -233
_sidebar_toggle.offset_right = -12
- _sidebar_toggle.offset_top = 12
- _sidebar_toggle.offset_bottom = 83.5
+ _sidebar_toggle.offset_top = 44
+ _sidebar_toggle.offset_bottom = 115.5
_sidebar_toggle.pressed.connect(_toggle_sidebar)
_cockpit = Control.new()
_cockpit.name = "Cockpit"
@@ -290,7 +298,7 @@ func _layout_sidebar() -> void:
var scroll := _sidebar.get_node("Scroll") as ScrollContainer
scroll.vertical_scroll_mode = ScrollContainer.SCROLL_MODE_DISABLED
var content_height: float = scroll.get_node("Contents").get_combined_minimum_size().y + 16.0
- var available_height := maxf(100.0, $HUDRoot.size.y - 148.0 - _ship_passive_reserved_height)
+ var available_height := maxf(100.0, $HUDRoot.size.y - 180.0 - _ship_passive_reserved_height)
var panel_scale := minf(EQUIPMENT_UI_SCALE, available_height / content_height)
_sidebar.scale = Vector2.ONE * panel_scale
_sidebar.size = Vector2(maxf(SIDEBAR_WIDTH, _sidebar.get_combined_minimum_size().x), content_height)
@@ -307,7 +315,7 @@ func _layout_sidebar() -> void:
_captain_skills_ui.call_deferred("_layout")
_layout_debug()
if not _sidebar.has_meta("floating_window_dragged"):
- _sidebar.position = Vector2($HUDRoot.size.x - _sidebar.size.x * _sidebar.scale.x - 8, 136)
+ _sidebar.position = Vector2($HUDRoot.size.x - _sidebar.size.x * _sidebar.scale.x - 8, 168)
else:
_window_manager.call("clamp_window", _sidebar)
_sidebar.visible = _sidebar_open
diff --git a/scripts/items/time_crystal_pickup.gd b/scripts/items/time_crystal_pickup.gd
index 4022699..31c425f 100644
--- a/scripts/items/time_crystal_pickup.gd
+++ b/scripts/items/time_crystal_pickup.gd
@@ -2,6 +2,8 @@ extends Node2D
const PICKUP_RADIUS := 48.0
const ATTRACTION_RADIUS := 150.0
const POPUP := preload("res://scenes/game/damage_popup.tscn")
+# Retain the texture for the lifetime of the queued canvas draw commands.
+const ICON := preload("res://assets/icons/resources/time_crystals.png")
var amount := 0
var _player: CharacterBody2D
var _collected := false
@@ -13,8 +15,7 @@ func _ready() -> void:
func _draw() -> void:
for radius in [27.0,22.0,18.0]: draw_circle(Vector2.ZERO,radius,Color(0.42,0.86,1.0,0.07))
- var icon := load("res://assets/icons/resources/time_crystals.png") as Texture2D
- if icon != null: draw_texture_rect(icon,Rect2(-18,-18,36,36),false)
+ draw_texture_rect(ICON,Rect2(-18,-18,36,36),false)
func _physics_process(delta: float) -> void:
if _collected or not is_instance_valid(_player) or bool(_player.get("_is_destroyed")): return
diff --git a/scripts/planets/distant_expeditions.gd b/scripts/planets/distant_expeditions.gd
index e79d1de..39ab0b3 100644
--- a/scripts/planets/distant_expeditions.gd
+++ b/scripts/planets/distant_expeditions.gd
@@ -1,5 +1,5 @@
extends RefCounted
-const HERMIT_CHANCE := 0.35
+const HERMIT_CHANCE := 0.70
const CREDITS_PER_LEVEL := 1000
const DEUTER_PER_LEVEL := 1000
diff --git a/scripts/planets/freighter_screen.gd b/scripts/planets/freighter_screen.gd
index deee33d..ca41452 100644
--- a/scripts/planets/freighter_screen.gd
+++ b/scripts/planets/freighter_screen.gd
@@ -21,6 +21,7 @@ var _economy_labels: Dictionary = {}
@onready var _audio: Node = $FreighterAudio
func _ready() -> void:
+ offset_top = preload("res://scripts/ui/resource_bar.gd").HEIGHT
if captain == null:
captain = GameState.captain
captain.expedition.freighter_rooms["expansion_3"] = "module_storage"
diff --git a/scripts/planets/mining_network.gd b/scripts/planets/mining_network.gd
index ca6f574..cd0ee7c 100644
--- a/scripts/planets/mining_network.gd
+++ b/scripts/planets/mining_network.gd
@@ -53,7 +53,8 @@ static func has_recruit(profile: Dictionary) -> bool:
static func recruit(profile: Dictionary) -> Dictionary:
var rng := planet_roll(profile, 0x50455253)
- var rating := clampi(1 + roundi(clampf(float(profile.get("difficulty", 0)), 0, 1) * 80) + rng.randi_range(0, 19), 1, 100)
+ var level := clampi(int(profile.get("system_level",1)),1,100)
+ var rating := rng.randi_range(maxi(1,level-5),mini(100,level+5))
return {"id":str(profile.id)+":crew", "name":FIRST_NAMES[rng.randi_range(0,9)]+" "+LAST_NAMES[rng.randi_range(0,9)], "management":rating, "planet_id":str(profile.id), "planet_name":str(profile.name), "cabin":""}
static func free_cabin(progress: Resource) -> String:
diff --git a/scripts/planets/poi_rules.gd b/scripts/planets/poi_rules.gd
index b18957a..e0ef316 100644
--- a/scripts/planets/poi_rules.gd
+++ b/scripts/planets/poi_rules.gd
@@ -1,5 +1,5 @@
extends RefCounted
-const NAMES := {"deposit":"Złoże surowców", "ruins":"Starożytna struktura", "warehouse":"Opuszczony magazyn", "village":"Opuszczona wioska", "cave":"Jaskinia", "deep_deposit":"Głębokie złoże deuteru", "crew":"Domek specjalisty", "hermit":"Pustelnik / Kartograf", "time_engineer":"Inżynier chronalny"}
+const NAMES := {"deposit":"Złoże surowców", "ruins":"Starożytna struktura", "warehouse":"Opuszczony magazyn", "village":"Opuszczona wioska", "cave":"Jaskinia", "deep_deposit":"Głębokie złoże deuteru", "crew":"Obóz specjalisty", "hermit":"Pustelnik / Kartograf", "time_engineer":"Inżynier chronalny"}
const STAGES := {
"deposit":["Zbierz odsłonięte minerały", "Wykonaj odwiert", "Wydobądź głęboką żyłę"],
"ruins":["Przeszukaj przedsionek", "Otwórz komorę", "Zbadaj rdzeń"],
diff --git a/scripts/planets/surface_screen.gd b/scripts/planets/surface_screen.gd
index db7b66a..9d9c7eb 100644
--- a/scripts/planets/surface_screen.gd
+++ b/scripts/planets/surface_screen.gd
@@ -37,6 +37,7 @@ var _surface_viewport: SubViewport
func _ready() -> void:
set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
+ offset_top = preload("res://scripts/ui/resource_bar.gd").HEIGHT
mouse_filter = Control.MOUSE_FILTER_STOP
_rng.seed = progress.visit_seed ^ 90317
if planet_texture == null:
@@ -53,7 +54,7 @@ func _ready() -> void:
add_child(container)
var viewport := SubViewport.new()
_surface_viewport = viewport
- viewport.size = Vector2i(get_viewport_rect().size * SURFACE_RENDER_SCALE)
+ viewport.size = Vector2i(size * SURFACE_RENDER_SCALE)
viewport.render_target_update_mode = SubViewport.UPDATE_ALWAYS
viewport.world_2d = World2D.new()
container.add_child(viewport)
@@ -128,18 +129,18 @@ func _ready() -> void:
_threat = _telemetry.threat
var back := POI_CARD.button(self, "POWRÓT NA STATEK [L]", func(): _return(true))
back.set_anchors_and_offsets_preset(Control.PRESET_TOP_LEFT)
- back.position = Vector2(get_viewport_rect().size.x-285, 24)
+ back.position = Vector2(size.x-285, 24)
back.size.x = 260
var help := UI.panel(self)
help.name = "SurfaceControls"
help.custom_minimum_size.x = 350
help.set_anchors_and_offsets_preset(Control.PRESET_TOP_LEFT)
- help.position = Vector2(24, get_viewport_rect().size.y-84)
+ help.position = Vector2(24, size.y-84)
POI_CARD.panel_style(help)
POI_CARD.text(help, "W — ciąg · S — hamuj / wstecz · A/D — obrót\nQ/E — ruch boczny · TAB — dopalanie · F — zbadaj", 13)
var map_frame := UI.panel(self, Vector2(195,195))
map_frame.set_anchors_and_offsets_preset(Control.PRESET_TOP_LEFT)
- map_frame.position = get_viewport_rect().size-Vector2(220,220)
+ map_frame.position = size-Vector2(220,220)
var minimap := Control.new()
minimap.set_script(preload("res://scripts/planets/surface_minimap.gd"))
minimap.world = world
@@ -403,7 +404,7 @@ func _event_action(action: String) -> void:
func _layout_dialog() -> void:
if not is_instance_valid(_dialog):
return
- var view := get_viewport_rect().size
+ var view := size
var width := minf(450,maxf(280,view.x-32))
var height := minf(600,maxf(180,view.y-48))
_dialog.size = Vector2(width,height)
@@ -423,7 +424,7 @@ func _show_colony_poi(message: String) -> void:
art.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED
art.custom_minimum_size.y = 170
_choices.add_child(art)
- POI_CARD.text(_choices, "GŁĘBOKIE ZŁOŻE / DEUTER" if is_deposit else "DOMEK SPECJALISTY / REKRUTACJA", 15, POI_CARD.GOLD)
+ POI_CARD.text(_choices, "GŁĘBOKIE ZŁOŻE / DEUTER" if is_deposit else "OBÓZ SPECJALISTY / REKRUTACJA", 15, POI_CARD.GOLD)
if not message.is_empty(): POI_CARD.text(_choices, message, 13, POI_CARD.GOLD)
if is_deposit:
var id := str(progress.active_profile.id)
@@ -444,7 +445,7 @@ func _show_colony_poi(message: String) -> void:
build.name = "BuildMiningOutpost"
build.disabled = captain.parts < cost
else:
- POI_CARD.text(_choices, "Mieszkaniec domku szuka pracy. Obejrzyj umiejętności i zdecyduj — możesz wrócić później. Koszt zatrudnienia: 1000 kredytów × zarządzanie.", 12)
+ POI_CARD.text(_choices, "Specjalista z obozu szuka pracy. Obejrzyj umiejętności i zdecyduj — możesz wrócić później. Koszt zatrudnienia: 1000 kredytów × zarządzanie.", 12)
var candidate: Dictionary = network.recruit(progress.active_profile)
var hire_cost: int = network.recruitment_cost(candidate)
POI_CARD.text(_choices, "Rekrutacja: %d kredytów · posiadasz: %d" % [hire_cost, captain.credits], 13, POI_CARD.GOLD)
diff --git a/scripts/planets/surface_world.gd b/scripts/planets/surface_world.gd
index 8b8a429..14de16d 100644
--- a/scripts/planets/surface_world.gd
+++ b/scripts/planets/surface_world.gd
@@ -75,8 +75,8 @@ func _ready() -> void:
if sprite.texture != null and poi.kind != "cave":
sprite.scale = Vector2.ONE * 125.0*BUILDING_SCALE / maxf(sprite.texture.get_width(), sprite.texture.get_height())
sprite.z_index = 10
- if poi.kind == "crew":
- sprite.set_script(preload("res://scripts/planets/specialist_house.gd"))
+ if poi.kind == "crew" and sprite.texture != null:
+ sprite.scale = Vector2.ONE * 170.0 / maxf(sprite.texture.get_width(),sprite.texture.get_height())
add_child(sprite)
_poi_sprites[poi.id] = sprite
var label := Label.new()
@@ -163,7 +163,7 @@ func refresh_pois(lander_position: Vector2) -> void:
label.text = "Pustelnik / Kartograf" + (" · mapa kupiona" if owned else ("\n[F] Kup mapę" if lander_position.distance_to(poi.position) <= 150 else ""))
continue
if poi.kind == "crew":
- label.text = "Domek specjalisty" + (" · zatrudniono" if poi.complete else ("\n[F] Porozmawiaj" if lander_position.distance_to(poi.position) <= 150 else ""))
+ label.text = "Obóz specjalisty" + (" · zatrudniono" if poi.complete else ("\n[F] Porozmawiaj" if lander_position.distance_to(poi.position) <= 150 else ""))
continue
var title: String = preload("res://scripts/planets/poi_rules.gd").NAMES[poi.kind]
label.text = title + ((" · zatrudniono" if poi.kind == "crew" else " · zbadano") if poi.complete else ("\n[F] Zbadaj" if lander_position.distance_to(poi.position) <= 150 else ""))
diff --git a/scripts/planets/time_engineer.gd b/scripts/planets/time_engineer.gd
index 527dd67..0ab3bc2 100644
--- a/scripts/planets/time_engineer.gd
+++ b/scripts/planets/time_engineer.gd
@@ -1,5 +1,5 @@
extends RefCounted
-const CHANCE := 0.30
+const CHANCE := 0.70
const CRYSTALS_PER_LEVEL := 10
const AFFIXES := preload("res://resources/items/affix_database.tres")
diff --git a/scripts/ui/floating_window_manager.gd b/scripts/ui/floating_window_manager.gd
index 0af2dfe..8e2f7c8 100644
--- a/scripts/ui/floating_window_manager.gd
+++ b/scripts/ui/floating_window_manager.gd
@@ -124,7 +124,8 @@ func clamp_window(root: Control) -> void:
return
var viewport_size := get_viewport().get_visible_rect().size
var dimensions := root.size * root.get_global_transform().get_scale().abs()
- root.global_position = root.global_position.clamp(Vector2(8, 8), (viewport_size - dimensions - Vector2(8, 8)).max(Vector2(8, 8)))
+ var minimum := Vector2(8, preload("res://scripts/ui/resource_bar.gd").HEIGHT + 8)
+ root.global_position = root.global_position.clamp(minimum, (viewport_size - dimensions - Vector2(8, 8)).max(minimum))
func _clamp_all() -> void:
for entry in _windows:
diff --git a/scripts/ui/resource_bar.gd b/scripts/ui/resource_bar.gd
new file mode 100644
index 0000000..0f11027
--- /dev/null
+++ b/scripts/ui/resource_bar.gd
@@ -0,0 +1,117 @@
+extends Control
+const HEIGHT := 32.0
+const ENTRIES := [
+ ["credits","Kredyty","svg",Color("efd48e")],
+ ["parts","Części","png",Color("dfded2")],
+ ["deuter","Deuter","svg",Color("9cdeef")],
+ ["time_crystals","Kryształy czasu","png",Color("d4b6ff")],
+ ["iron","Żelazo","png",Color("d3dce0")],
+ ["titanium","Tytan","png",Color("d3dce0")],
+ ["aluminium","Aluminium","png",Color("d3dce0")],
+ ["uranium","Uran","png",Color("d3dce0")],
+ ["sulfur","Siarka","png",Color("d3dce0")],
+ ["silicon","Krzem","svg",Color("d3dce0")],
+ ["copper","Miedź","svg",Color("d3dce0")],
+ ["nickel","Nikiel","svg",Color("d3dce0")],
+ ["tungsten","Wolfram","svg",Color("d3dce0")],
+ ["mercury","Rtęć","svg",Color("d3dce0")]
+]
+var _row: HBoxContainer
+var _labels: Dictionary = {}
+var _cells: Dictionary = {}
+var _style: StyleBoxFlat
+var _elapsed := 0.0
+
+func _ready() -> void:
+ name = "ResourceBar"
+ process_mode = Node.PROCESS_MODE_ALWAYS
+ set_anchors_and_offsets_preset(Control.PRESET_TOP_WIDE)
+ offset_bottom = HEIGHT
+ mouse_filter = Control.MOUSE_FILTER_STOP
+ _style = StyleBoxFlat.new()
+ _style.bg_color = Color("0a171ff0")
+ _style.border_color = Color("46666a")
+ _style.border_width_bottom = 1
+ _row = HBoxContainer.new()
+ _row.add_theme_constant_override("separation",8)
+ _row.mouse_filter = Control.MOUSE_FILTER_PASS
+ add_child(_row)
+ for index in ENTRIES.size():
+ var entry: Array = ENTRIES[index]
+ var key := str(entry[0])
+ if index in [4,9]:
+ var separator := VSeparator.new()
+ separator.mouse_filter = Control.MOUSE_FILTER_IGNORE
+ separator.modulate = Color("48636a")
+ _row.add_child(separator)
+ var cell := HBoxContainer.new()
+ cell.name = key.to_pascal_case()
+ cell.size_flags_horizontal = Control.SIZE_EXPAND_FILL
+ cell.add_theme_constant_override("separation",4)
+ cell.mouse_filter = Control.MOUSE_FILTER_PASS
+ _row.add_child(cell)
+ var icon := TextureRect.new()
+ icon.texture = load("res://assets/icons/resources/%s.%s" % [key,entry[2]])
+ icon.custom_minimum_size = Vector2(18,18)
+ icon.expand_mode = TextureRect.EXPAND_IGNORE_SIZE
+ icon.stretch_mode = TextureRect.STRETCH_KEEP_ASPECT_CENTERED
+ icon.texture_filter = CanvasItem.TEXTURE_FILTER_LINEAR
+ icon.mouse_filter = Control.MOUSE_FILTER_IGNORE
+ cell.add_child(icon)
+ var label := Label.new()
+ label.custom_minimum_size.x = 36
+ label.add_theme_font_override("font",ThemeDB.fallback_font)
+ label.add_theme_font_size_override("font_size",11)
+ label.add_theme_color_override("font_color",entry[3])
+ label.mouse_filter = Control.MOUSE_FILTER_IGNORE
+ label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
+ cell.add_child(label)
+ _labels[key] = label
+ _cells[key] = cell
+ GameState.captain.changed.connect(refresh)
+ GameState.captain.expedition.changed.connect(refresh)
+ resized.connect(_layout)
+ _row.minimum_size_changed.connect(_layout.call_deferred)
+ refresh()
+ _layout.call_deferred()
+
+static func compact(value: float) -> String:
+ if value >= 1000000: return ("%.1fM" % (floorf(value/100000.0)/10.0)).replace(".0M","M")
+ if value >= 1000: return ("%.1fK" % (floorf(value/100.0)/10.0)).replace(".0K","K")
+ return str(floori(value))
+
+func refresh() -> void:
+ if _labels.is_empty(): return
+ var captain: Resource = GameState.captain
+ var progress: Resource = captain.expedition
+ for entry in ENTRIES:
+ var key := str(entry[0])
+ var amount := float(captain.minerals.get(key,0))
+ match key:
+ "credits": amount = captain.credits
+ "parts": amount = captain.parts
+ "deuter": amount = progress.deuter
+ "time_crystals": amount = progress.time_crystals
+ var label: Label = _labels[key]
+ label.text = compact(amount)
+ var exact := "%.1f" % amount if key == "deuter" else str(floori(amount))
+ _cells[key].tooltip_text = "%s: %s" % [entry[1],exact]
+
+func _process(delta: float) -> void:
+ _elapsed += delta
+ if _elapsed >= 0.25:
+ _elapsed = 0
+ refresh()
+
+func _layout() -> void:
+ if not is_instance_valid(_row): return
+ var minimum := _row.get_combined_minimum_size()
+ var available := maxf(1,size.x-24)
+ var factor := minf(1.0,available/maxf(1,minimum.x))
+ _row.scale = Vector2.ONE*factor
+ _row.size = Vector2(available/factor,minimum.y)
+ _row.position = Vector2(12,(HEIGHT-minimum.y*factor)*0.5)
+ queue_redraw()
+
+func _draw() -> void:
+ if _style != null: draw_style_box(_style,Rect2(Vector2.ZERO,size))
diff --git a/scripts/ui/resource_bar.gd.uid b/scripts/ui/resource_bar.gd.uid
new file mode 100644
index 0000000..b388d97
--- /dev/null
+++ b/scripts/ui/resource_bar.gd.uid
@@ -0,0 +1 @@
+uid://3hrqurqwqdcu
diff --git a/tests/crew_level_checks.gd b/tests/crew_level_checks.gd
new file mode 100644
index 0000000..5baa9bf
--- /dev/null
+++ b/tests/crew_level_checks.gd
@@ -0,0 +1,17 @@
+@tool
+extends Node
+func run_checks() -> Dictionary:
+ var network := preload("res://scripts/planets/mining_network.gd")
+ var failures: Array[String] = []
+ for level in [1,5,20,50,80,100,120]:
+ var center := clampi(level,1,100)
+ for seed_value in 1000:
+ var profile := {"id":"test:%d" % seed_value,"seed":seed_value,"name":"Test","difficulty":1.0,"system_level":level}
+ var candidate: Dictionary = network.recruit(profile)
+ if int(candidate.management) < maxi(1,center-5) or int(candidate.management) > mini(100,center+5): failures.append("Out of level bounds")
+ if candidate != network.recruit(profile): failures.append("Rerolled on revisit")
+ var safe := profile.duplicate()
+ safe.difficulty = 0.0
+ if candidate.management != network.recruit(safe).management: failures.append("Biome changed rating")
+ if network.recruitment_cost(candidate) != int(candidate.management)*1000: failures.append("Wrong price")
+ return {"failures":failures,"rolls_checked":7000,"passed":failures.is_empty()}
diff --git a/tests/crew_level_checks.gd.uid b/tests/crew_level_checks.gd.uid
new file mode 100644
index 0000000..0c900b4
--- /dev/null
+++ b/tests/crew_level_checks.gd.uid
@@ -0,0 +1 @@
+uid://lpfj0avxfgt8
diff --git a/tests/time_crystal_visual.gd b/tests/time_crystal_visual.gd
new file mode 100644
index 0000000..6ef2cab
--- /dev/null
+++ b/tests/time_crystal_visual.gd
@@ -0,0 +1,18 @@
+extends Node2D
+func _ready() -> void:
+ var background := ColorRect.new()
+ background.color = Color("0b1826")
+ background.size = Vector2(1280,720)
+ add_child(background)
+ var crystal := Node2D.new()
+ crystal.set_script(preload("res://scripts/items/time_crystal_pickup.gd"))
+ crystal.position = Vector2(640,340)
+ crystal.scale = Vector2.ONE*3
+ crystal.amount = 10
+ add_child(crystal)
+ crystal.set_physics_process(false)
+ var label := Label.new()
+ label.text = "KRYSZTAŁY CZASU"
+ label.position = Vector2(500,440)
+ label.add_theme_font_size_override("font_size",20)
+ add_child(label)
diff --git a/tests/time_crystal_visual.gd.uid b/tests/time_crystal_visual.gd.uid
new file mode 100644
index 0000000..9a3d6d8
--- /dev/null
+++ b/tests/time_crystal_visual.gd.uid
@@ -0,0 +1 @@
+uid://cmhvnvlru1bep
diff --git a/tests/time_crystal_visual.tscn b/tests/time_crystal_visual.tscn
new file mode 100644
index 0000000..9341818
--- /dev/null
+++ b/tests/time_crystal_visual.tscn
@@ -0,0 +1,6 @@
+[gd_scene format=3 uid="uid://dr6cwynsabgda"]
+
+[ext_resource type="Script" uid="uid://cmhvnvlru1bep" path="res://tests/time_crystal_visual.gd" id="1_7w67k"]
+
+[node name="time_crystal_visual" type="Node2D" unique_id=651484583]
+script = ExtResource("1_7w67k")