From 76c40a8395c3691377fffd7cebc465c7b93dc8c7 Mon Sep 17 00:00:00 2001 From: Tomasz Boruc Date: Tue, 20 Oct 2026 20:32:50 +0200 Subject: [PATCH] Zmiany --- assets/icons/resources/copper.svg | 1 + assets/icons/resources/copper.svg.import | 43 ++++++++ assets/icons/resources/mercury.svg | 1 + assets/icons/resources/mercury.svg.import | 43 ++++++++ assets/icons/resources/nickel.svg | 1 + assets/icons/resources/nickel.svg.import | 43 ++++++++ assets/icons/resources/silicon.svg | 1 + assets/icons/resources/silicon.svg.import | 43 ++++++++ assets/icons/resources/tungsten.svg | 1 + assets/icons/resources/tungsten.svg.import | 43 ++++++++ scripts/game/distant_sector.gd | 4 +- scripts/game/flight_hud.gd | 22 ++-- scripts/items/time_crystal_pickup.gd | 5 +- scripts/planets/distant_expeditions.gd | 2 +- scripts/planets/freighter_screen.gd | 1 + scripts/planets/mining_network.gd | 3 +- scripts/planets/poi_rules.gd | 2 +- scripts/planets/surface_screen.gd | 15 +-- scripts/planets/surface_world.gd | 6 +- scripts/planets/time_engineer.gd | 2 +- scripts/ui/floating_window_manager.gd | 3 +- scripts/ui/resource_bar.gd | 117 +++++++++++++++++++++ scripts/ui/resource_bar.gd.uid | 1 + tests/crew_level_checks.gd | 17 +++ tests/crew_level_checks.gd.uid | 1 + tests/time_crystal_visual.gd | 18 ++++ tests/time_crystal_visual.gd.uid | 1 + tests/time_crystal_visual.tscn | 6 ++ 28 files changed, 420 insertions(+), 26 deletions(-) create mode 100644 assets/icons/resources/copper.svg create mode 100644 assets/icons/resources/copper.svg.import create mode 100644 assets/icons/resources/mercury.svg create mode 100644 assets/icons/resources/mercury.svg.import create mode 100644 assets/icons/resources/nickel.svg create mode 100644 assets/icons/resources/nickel.svg.import create mode 100644 assets/icons/resources/silicon.svg create mode 100644 assets/icons/resources/silicon.svg.import create mode 100644 assets/icons/resources/tungsten.svg create mode 100644 assets/icons/resources/tungsten.svg.import create mode 100644 scripts/ui/resource_bar.gd create mode 100644 scripts/ui/resource_bar.gd.uid create mode 100644 tests/crew_level_checks.gd create mode 100644 tests/crew_level_checks.gd.uid create mode 100644 tests/time_crystal_visual.gd create mode 100644 tests/time_crystal_visual.gd.uid create mode 100644 tests/time_crystal_visual.tscn 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")