Zmiany
BIN
artifacts/alien_research_progress.png
Normal file
|
After Width: | Height: | Size: 1.0 MiB |
40
artifacts/alien_research_progress.png.import
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://c3qnxtk20gsdo"
|
||||||
|
path="res://.godot/imported/alien_research_progress.png-4e5d04e60f097403ec0c28ff48037d60.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://artifacts/alien_research_progress.png"
|
||||||
|
dest_files=["res://.godot/imported/alien_research_progress.png-4e5d04e60f097403ec0c28ff48037d60.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
|
||||||
|
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 1.3 MiB |
|
Before Width: | Height: | Size: 891 KiB After Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 914 KiB After Width: | Height: | Size: 1.0 MiB |
|
Before Width: | Height: | Size: 920 KiB |
BIN
artifacts/load_en.png
Normal file
|
After Width: | Height: | Size: 251 KiB |
40
artifacts/load_en.png.import
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://b5a06k3qmlmfh"
|
||||||
|
path="res://.godot/imported/load_en.png-83aa43132dd9ea251d247a2ac0112c34.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://artifacts/load_en.png"
|
||||||
|
dest_files=["res://.godot/imported/load_en.png-83aa43132dd9ea251d247a2ac0112c34.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
|
||||||
BIN
artifacts/load_pl.png
Normal file
|
After Width: | Height: | Size: 257 KiB |
40
artifacts/load_pl.png.import
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://cgal3tyfa8886"
|
||||||
|
path="res://.godot/imported/load_pl.png-378ea7b5ca010d43a872c9ebc55660e0.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://artifacts/load_pl.png"
|
||||||
|
dest_files=["res://.godot/imported/load_pl.png-378ea7b5ca010d43a872c9ebc55660e0.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
|
||||||
BIN
artifacts/menu_en.png
Normal file
|
After Width: | Height: | Size: 984 KiB |
40
artifacts/menu_en.png.import
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://cw326a8sik63r"
|
||||||
|
path="res://.godot/imported/menu_en.png-72dd67b30eaa21f347b4212c2929fccf.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://artifacts/menu_en.png"
|
||||||
|
dest_files=["res://.godot/imported/menu_en.png-72dd67b30eaa21f347b4212c2929fccf.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
|
||||||
BIN
artifacts/menu_guide_pl.png
Normal file
|
After Width: | Height: | Size: 248 KiB |
40
artifacts/menu_guide_pl.png.import
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://dqashyeitlj5c"
|
||||||
|
path="res://.godot/imported/menu_guide_pl.png-5226b4638f3800c932cdfbe51a6d7ebf.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://artifacts/menu_guide_pl.png"
|
||||||
|
dest_files=["res://.godot/imported/menu_guide_pl.png-5226b4638f3800c932cdfbe51a6d7ebf.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
|
||||||
BIN
artifacts/menu_hangar_pl.png
Normal file
|
After Width: | Height: | Size: 330 KiB |
40
artifacts/menu_hangar_pl.png.import
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://cik4hh7dymmwb"
|
||||||
|
path="res://.godot/imported/menu_hangar_pl.png-25c816b540579d3c47e233d9051b3b05.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://artifacts/menu_hangar_pl.png"
|
||||||
|
dest_files=["res://.godot/imported/menu_hangar_pl.png-25c816b540579d3c47e233d9051b3b05.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
|
||||||
BIN
artifacts/menu_pl.png
Normal file
|
After Width: | Height: | Size: 989 KiB |
40
artifacts/menu_pl.png.import
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://017a1h77y8ov"
|
||||||
|
path="res://.godot/imported/menu_pl.png-80a4d2c9e287b5a7689462443ecf1715.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://artifacts/menu_pl.png"
|
||||||
|
dest_files=["res://.godot/imported/menu_pl.png-80a4d2c9e287b5a7689462443ecf1715.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
|
||||||
BIN
artifacts/named_save_en.png
Normal file
|
After Width: | Height: | Size: 343 KiB |
40
artifacts/named_save_en.png.import
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://cp2yr8fiegbg0"
|
||||||
|
path="res://.godot/imported/named_save_en.png-65dccf89fd0b085edf697bee47fcaa84.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://artifacts/named_save_en.png"
|
||||||
|
dest_files=["res://.godot/imported/named_save_en.png-65dccf89fd0b085edf697bee47fcaa84.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
|
||||||
35
artifacts/named_saves_validation.md
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
# Nazwane zapisy i wygląd menu — 27.10.2026
|
||||||
|
|
||||||
|
- Zapis ręczny i F6 otwierają okno z nazwą zapisu (do 48 znaków).
|
||||||
|
- Nowy zapis tworzy osobny slot. Wybór karty pozwala nadpisać zapis lub zmienić
|
||||||
|
jego nazwę; poprzednia wersja zostaje w kopii zapasowej tego slotu.
|
||||||
|
- Nazwy gracza nie są tłumaczone ani używane jako nazwy plików.
|
||||||
|
- Wczytywanie w menu głównym i pauzie pokazuje nazwę, datę, statek,
|
||||||
|
poziom układu i kapitana oraz szczegóły wybranej wyprawy.
|
||||||
|
- Autosave nie zastępuje zapisów ręcznych. Kontynuuj wybiera najnowszy
|
||||||
|
poprawny zapis. Obsługiwane są również dotychczasowe pliki last_game.res.
|
||||||
|
- Wczytanie nadal rozpoczyna bieżący poziom od początku, bez cooldownów.
|
||||||
|
- Zapis i wyjście do menu/z gry wymagają zatwierdzenia nazwanego zapisu;
|
||||||
|
anulowanie wraca do pauzy i nie wykonuje akcji wyjścia.
|
||||||
|
- Wspólna warstwa menu obejmuje opcje, zapis, wczytywanie, pauzę i komunikaty.
|
||||||
|
Instrukcja i hangar używają tej samej palety, ramek oraz przycisków.
|
||||||
|
|
||||||
|
## Walidacja
|
||||||
|
|
||||||
|
- `tests/named_save_test.tscn`: PASS, 0 niepowodzeń, kod zakończenia 0.
|
||||||
|
Osobne sloty, Unicode i ukośniki w nazwie, sortowanie, wybór starszego zapisu,
|
||||||
|
nadpisanie i zmiana nazwy, kopia slotu, izolacja autosave, pusta nazwa,
|
||||||
|
odrzucanie ścieżek spoza katalogu, formularz UI, sygnał wyboru,
|
||||||
|
zachowanie nazw w obcym języku, anulowanie i wykonanie akcji po zapisie.
|
||||||
|
- `tests/save_settings_test.tscn`: PASS, 0 niepowodzeń, kod zakończenia 0.
|
||||||
|
- `tests/menu_options_preview.tscn`: PASS, kod zakończenia 0.
|
||||||
|
Podglądy pięciu języków, sprawdzenie wyśrodkowania listy, pauza, zapis,
|
||||||
|
opcje podczas gry, instrukcja i wybór statku.
|
||||||
|
- `tools/build_localization.py`: 1079 wpisów, zgodne parametry formatowania.
|
||||||
|
- `git diff --check`: bez błędów.
|
||||||
|
|
||||||
|
Zrzuty: `load_pl.png`, `load_en.png`, `options_pl.png`, `options_en.png`,
|
||||||
|
`named_save_en.png`, `menu_guide_pl.png`, `menu_hangar_pl.png` w artifacts/.
|
||||||
|
Testy używały osobnego katalogu danych; nie zmieniały zapisów użytkownika.
|
||||||
|
Nie przebudowywano pliku EXE. Ostrzeżenie Camera2D pochodzi z interpolacji
|
||||||
|
fizyki; starszy test zapisu może przy kończeniu zgłosić 4 obiekty ObjectDB.
|
||||||
BIN
artifacts/options_en.png
Normal file
|
After Width: | Height: | Size: 268 KiB |
40
artifacts/options_en.png.import
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://dp310xwkdh1rd"
|
||||||
|
path="res://.godot/imported/options_en.png-801fa53375ff3d69f8b1c23faa9470cd.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://artifacts/options_en.png"
|
||||||
|
dest_files=["res://.godot/imported/options_en.png-801fa53375ff3d69f8b1c23faa9470cd.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
|
||||||
BIN
artifacts/options_pl.png
Normal file
|
After Width: | Height: | Size: 273 KiB |
40
artifacts/options_pl.png.import
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://b6j7ka8rk8a2"
|
||||||
|
path="res://.godot/imported/options_pl.png-7300fb0ac2f8c2059ac3c0f65f2f6693.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://artifacts/options_pl.png"
|
||||||
|
dest_files=["res://.godot/imported/options_pl.png-7300fb0ac2f8c2059ac3c0f65f2f6693.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
|
||||||
41
artifacts/planet_exploration_balance.json
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
{
|
||||||
|
"bonus_fraction": 0.239,
|
||||||
|
"failures": [],
|
||||||
|
"statistics": [
|
||||||
|
{
|
||||||
|
"level": 1,
|
||||||
|
"mean_damage": 3.0,
|
||||||
|
"mean_difficulty": 0.0,
|
||||||
|
"mean_materials": 22.95,
|
||||||
|
"mean_recovery": 1.0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 10,
|
||||||
|
"mean_damage": 3.5,
|
||||||
|
"mean_difficulty": 0.181849574397679,
|
||||||
|
"mean_materials": 37.485,
|
||||||
|
"mean_recovery": 1.01624732860126
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 30,
|
||||||
|
"mean_damage": 4.495,
|
||||||
|
"mean_difficulty": 0.476566741391365,
|
||||||
|
"mean_materials": 71.395,
|
||||||
|
"mean_recovery": 1.00788772210352
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 60,
|
||||||
|
"mean_damage": 5.865,
|
||||||
|
"mean_difficulty": 0.732818183297586,
|
||||||
|
"mean_materials": 120.955,
|
||||||
|
"mean_recovery": 0.98072989632556
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level": 120,
|
||||||
|
"mean_damage": 7.38,
|
||||||
|
"mean_difficulty": 0.920596468134915,
|
||||||
|
"mean_materials": 209.155,
|
||||||
|
"mean_recovery": 0.949410793431032
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
29
artifacts/planet_exploration_validation.md
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
# Weryfikacja eksploracji planet — 27.10.2026
|
||||||
|
|
||||||
|
Zaimplementowano progresję trudności i łupu, znaczenie poszczególnych elementów sprzętu, podgląd POI przed akcją oraz uszkodzenia i zniszczenie lądownika.
|
||||||
|
|
||||||
|
## Balans
|
||||||
|
|
||||||
|
200 planet na każdy poziom, sprzęt o poziomie planety. Wartości łupu dotyczą przeciętnego złoża; uszkodzenia zwykłego POI.
|
||||||
|
|
||||||
|
| Poziom | Średni łup | Średnie uszkodzenia HP |
|
||||||
|
|---|---:|---:|
|
||||||
|
| 1 | 22,95 | 3,00 |
|
||||||
|
| 10 | 37,49 | 3,50 |
|
||||||
|
| 30 | 71,40 | 4,50 |
|
||||||
|
| 60 | 120,96 | 5,87 |
|
||||||
|
| 120 | 209,16 | 7,38 |
|
||||||
|
|
||||||
|
Na poziomie 1: 100% odzysku podstawowego łupu, zwykły POI 2–4 HP, dodatkowe przeszukanie 8–18 HP. Po lądowaniu i dziesięciu zwykłych POI pozostaje 55–75 HP. W próbie 2000 POI dodatkowe znaleziska wystąpiły w 23,9% przypadków.
|
||||||
|
|
||||||
|
## Testy zakończone powodzeniem
|
||||||
|
|
||||||
|
- `planet_exploration_balance_test`: progresja na 1000 planetach, wagi sprzętu, brak odporności od poziomu 50, zgodność nagrody z podglądem, brak ponownego losowania, ograniczenia dodatkowego przeszukania, utrata ładunku po zniszczeniu.
|
||||||
|
- `single_visit_surface_test`: rzeczywiste E → podgląd → potwierdzenie, brak kosztu otwarcia okna, blokada powtórnej nagrody, osobny przycisk dodatkowych znalezisk, ostrzeżenie i pełny przebieg zniszczenia lądownika.
|
||||||
|
- `ruins_loot_layout_test`: czytelne trzy moduły przy 1280×720 i 800×600.
|
||||||
|
- `planet_threats_test`, `poi_rewards_test`, `planet_expeditions_test`, `surface_events_test`: progresja, transakcje, zapisy danych, powroty, obsługa specjalnych miejsc i istniejących wydarzeń.
|
||||||
|
- `planet_reward_scaling_test`: 30000 losowań premii, 3600 zwykłych akcji POI, 600 wyników wydarzeń.
|
||||||
|
- `captain_equipment_preview`: rozmiar okna, poziomy sprzętu, przeciąganie i zamykanie Esc.
|
||||||
|
- `save_settings_test`: zapis i odczyt, kopia zapasowa, pięć języków, głośność oraz pauza.
|
||||||
|
|
||||||
|
Katalogi językowe zbudowano offline; walidacja zgodności placeholderów przeszła. Podglądy: `planet_poi_forecast.png`, `planet_poi_bonus.png`, `single_visit_planet_poi.png`.
|
||||||
BIN
artifacts/planet_poi_bonus.png
Normal file
|
After Width: | Height: | Size: 1.4 MiB |
40
artifacts/planet_poi_bonus.png.import
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://bgesypgow2von"
|
||||||
|
path="res://.godot/imported/planet_poi_bonus.png-cc1fcd55f6d644db0d7d15e5217141ed.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://artifacts/planet_poi_bonus.png"
|
||||||
|
dest_files=["res://.godot/imported/planet_poi_bonus.png-cc1fcd55f6d644db0d7d15e5217141ed.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
|
||||||
BIN
artifacts/planet_poi_forecast.png
Normal file
|
After Width: | Height: | Size: 1.4 MiB |
40
artifacts/planet_poi_forecast.png.import
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://1e50q1nyo8cv"
|
||||||
|
path="res://.godot/imported/planet_poi_forecast.png-5424b6424be854e50c01d697253c8c8f.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://artifacts/planet_poi_forecast.png"
|
||||||
|
dest_files=["res://.godot/imported/planet_poi_forecast.png-5424b6424be854e50c01d697253c8c8f.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
|
||||||
13
artifacts/research_progression_validation.md
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# Progresja badań — 27.10.2026
|
||||||
|
|
||||||
|
- Laboratorium: 23 projekty, pełna pula od początku, bez progów poziomu kapitana, 600 sekund bazowo. Naukowiec zachowuje skrócenie do 540/480/420 sekund. Dotychczasowe koszty minerałów zachowane.
|
||||||
|
- Obcy: 28 technologii, brak progów poziomu, zachowane zależności drzewa, 600 sekund na technologię, 715 próbek za całość. Efekt aktywuje się po zakończeniu.
|
||||||
|
- Dwa niezależne stanowiska, pojedynczy projekt na każde. SAVE/LOAD zachowuje projekt i dokładny pozostały czas; nie nalicza czasu poza grą.
|
||||||
|
|
||||||
|
Testy zakończone powodzeniem: research_progression_test, save_settings_test, laboratory_test (również praca równoległa), laboratory_loot_test, alien_research_test, alien_hull_technologies_test, alien_shield_technologies_test, alien_weapon_technologies_test, new_skills_test, auxiliary_shield_test, external_turret_test, pulse_laser_test.
|
||||||
|
|
||||||
|
Zapis testowano przez rzeczywistą usługę SAVE/LOAD, z licznikami 387,5 i 245,25 s. Oba wróciły bez zmiany, przy poprawnym resecie cooldownów walki. Testy korzystały z osobnego APPDATA.
|
||||||
|
|
||||||
|
Katalogi pięciu języków zbudowano offline i sprawdzono placeholdery. Układ trwającego badania sprawdzono w natywnym podglądzie artifacts/alien_research_progress.png.
|
||||||
|
|
||||||
|
Korekta przetestowana: wszystkie 23 projekty i 28 technologii można ukończyć na poziomie kapitana 1. Zmiana poziomu nie zmienia istniejących propozycji.
|
||||||
|
Before Width: | Height: | Size: 1.4 MiB After Width: | Height: | Size: 1.4 MiB |
37
artifacts/save_settings_validation.md
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
# Zapis, kontynuacja i opcje — 27.10.2026
|
||||||
|
|
||||||
|
## Zachowanie
|
||||||
|
|
||||||
|
- Wczytanie zaczyna bieżący poziom od początku: pozycja startowa, pełny kadłub,
|
||||||
|
tarcze i energia, nowe starcia, bez cooldownów i czasowych efektów.
|
||||||
|
- Postęp kapitana, ekwipunek z indywidualnymi rollami i orbami, amunicja,
|
||||||
|
odblokowania, badania, załoga i gospodarka zostają zachowane.
|
||||||
|
- Zapis na powierzchni normalizuje kopię wyprawy do bezpiecznego powrotu
|
||||||
|
z bieżącym łupem; nie zmienia trwającej rozgrywki.
|
||||||
|
- Kontynuuj jest nieaktywne bez poprawnego zapisu. Uszkodzony główny plik
|
||||||
|
powoduje odczyt ostatniej poprawnej kopii zapasowej.
|
||||||
|
- Esc otwiera pauzę i zapis; F6 zapisuje bez zajmowania F1–F5 umiejętności.
|
||||||
|
- Ustawienia dźwięku, obrazu i języka są zapisane oddzielnie od rozgrywki.
|
||||||
|
- 1048 lokalnych tekstów: PL, DE, ES, EN, FR. Tłumaczenia przygotowane przez AI,
|
||||||
|
bez przekazywania katalogu do zewnętrznego tłumacza. Generator działa offline.
|
||||||
|
|
||||||
|
## Sprawdzenie w Godot 4.7.2
|
||||||
|
|
||||||
|
- `tests/save_settings_test.tscn`: PASS, 0 niepowodzeń, kod zakończenia 0.
|
||||||
|
Obejmuje odczyt/zapis, kopię i jej odzyskanie, indywidualne parametry broni,
|
||||||
|
orby, załogę, badania, reset poziomu i cooldownów, łup powierzchniowy,
|
||||||
|
trwałość ustawień, pięć języków, liczby i nazwy w tekstach składanych,
|
||||||
|
pauzę i przejście do opcji.
|
||||||
|
- `tests/distant_integration.tscn`: PASS, kod zakończenia 0.
|
||||||
|
- `tests/levels/planet_expeditions_test.tscn`: PASS, kod zakończenia 0.
|
||||||
|
Poprawiono dotychczasowe oczekiwania testu o amunicję, rakiety i kredyty
|
||||||
|
losowo zdobywane w POI przed kontrolowanym powrotem.
|
||||||
|
- `tests/menu_options_preview.tscn`: PASS, kod zakończenia 0.
|
||||||
|
Wizualnie sprawdzone menu i opcje pięciu języków oraz opcje podczas pauzy.
|
||||||
|
- `tools/build_localization.py`: 1048 tekstów, brak brakujących wpisów
|
||||||
|
w wyodrębnionym katalogu, zgodne znaczniki parametrów we wszystkich językach.
|
||||||
|
- `git diff --check`: bez błędów.
|
||||||
|
|
||||||
|
Silnik zgłasza istniejącą korektę trybu Camera2D z powodu interpolacji fizyki.
|
||||||
|
Test zapisu przy zakończeniu może zgłosić 4 obiekty ObjectDB; podgląd zwykłego
|
||||||
|
menu i gry kończy się bez tego ostrzeżenia. Nie przebudowywano pliku EXE.
|
||||||
BIN
artifacts/session_menu_en.png
Normal file
|
After Width: | Height: | Size: 468 KiB |
40
artifacts/session_menu_en.png.import
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://bt0ecddgwvfnt"
|
||||||
|
path="res://.godot/imported/session_menu_en.png-e61bd101cd3a2226f0d2f5c44c1e02fc.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://artifacts/session_menu_en.png"
|
||||||
|
dest_files=["res://.godot/imported/session_menu_en.png-e61bd101cd3a2226f0d2f5c44c1e02fc.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
|
||||||
BIN
artifacts/session_options_en.png
Normal file
|
After Width: | Height: | Size: 379 KiB |
40
artifacts/session_options_en.png.import
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://03kyty7ry5js"
|
||||||
|
path="res://.godot/imported/session_options_en.png-843bd47a1b19a7b3329f0a2129fbfa9f.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://artifacts/session_options_en.png"
|
||||||
|
dest_files=["res://.godot/imported/session_options_en.png-843bd47a1b19a7b3329f0a2129fbfa9f.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
|
||||||
|
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 1.4 MiB |
@ -249,3 +249,77 @@ Wyższy poziom zwiększa zakres obrażeń, a przez niego koszt. Czterokrotnie wy
|
|||||||
ś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.
|
||||||
Parametry energy_damage_exponent i energy_per_addon edytuje się w definicji broni.
|
Parametry energy_damage_exponent i energy_per_addon edytuje się w definicji broni.
|
||||||
|
|
||||||
|
|
||||||
|
ZAPIS GRY I OPCJE (27.10.2026)
|
||||||
|
- Menu główne: Kontynuuj wczytuje ostatni poprawny zapis; przy braku zapisu
|
||||||
|
przycisk jest nieaktywny. Zapis rozgrywki pokazuje datę, poziom i umożliwia wczytanie.
|
||||||
|
- Esc w grze: pauza, zapis ręczny, opcje, zapis i menu, zapis i wyjście.
|
||||||
|
F6 otwiera okno nazwanego zapisu. Automatyczny zapis co 60 sekund poza powierzchnią,
|
||||||
|
przy rozpoczęciu poziomu, powrocie z lokacji i zamykaniu okna gry.
|
||||||
|
- Wczytanie zawsze zaczyna bieżący poziom od początku: punkt startowy,
|
||||||
|
pełne kadłub/tarcze/energia, odnowieni przeciwnicy i eksploracja, bez cooldownów
|
||||||
|
i czasowych efektów. Inne odwiedzone układy i trwały postęp są zachowane.
|
||||||
|
- Zachowane są wyposażenie, amunicja, odblokowane sloty, kapitan, oferowane
|
||||||
|
umiejętności, badania, załoga, fregata, magazyny, placówki i mapy wypraw.
|
||||||
|
Zapis na powierzchni zachowuje bieżący łup jako zakończoną wyprawę;
|
||||||
|
po wczytaniu gracz rozpoczyna poziom w kosmosie.
|
||||||
|
- Pliki: user://last_game.res, user://last_game_backup.res, user://settings.cfg.
|
||||||
|
Zapis przechodzi przez plik tymczasowy i kontrolny odczyt. Przy uszkodzeniu
|
||||||
|
głównego pliku Kontynuuj używa poprawnej kopii zapasowej.
|
||||||
|
- Opcje: głośność ogólna i muzyki, okno/pełny ekran, sześć rozdzielczości
|
||||||
|
od 1024×576 do 3840×2160 (okno ograniczone do dostępnego ekranu), język.
|
||||||
|
- Języki: polski, niemiecki, hiszpański, angielski i francuski.
|
||||||
|
Teksty przygotowano przy użyciu AI, bez zewnętrznej usługi tłumaczącej.
|
||||||
|
Lokalne katalogi zawierają 1048 tekstów, łącznie z instrukcją i opisami.
|
||||||
|
Obsługiwane są też teksty składane i parametry liczbowe istniejącego interfejsu.
|
||||||
|
tools/build_localization.py odtwarza katalogi offline i sprawdza znaczniki formatu.
|
||||||
|
- Test integracyjny: tests/save_settings_test.tscn. Podgląd wizualny:
|
||||||
|
tests/menu_options_preview.tscn; zrzuty w artifacts/menu_*.png i options_*.png.
|
||||||
|
|
||||||
|
|
||||||
|
NAZWANE ZAPISY I OKNA MENU (27.10.2026)
|
||||||
|
- Zapisz grę / F6 otwiera archiwum w trybie zapisu. Nazwa do 48 znaków,
|
||||||
|
także ze znakami narodowymi; nazwa nie jest ścieżką pliku i nie jest tłumaczona.
|
||||||
|
- Nowy zapis tworzy oddzielny slot. Wybór istniejącej karty i Nadpisz zapis
|
||||||
|
aktualizuje ten slot (można też zmienić nazwę) z zachowaniem kopii zapasowej.
|
||||||
|
- Wczytaj grę w menu głównym i pauzie pokazuje karty z nazwą, datą, statkiem,
|
||||||
|
poziomem układu i kapitana. Panel po prawej podaje szczegóły i zasadę restartu.
|
||||||
|
- Kontynuuj wybiera najnowszy poprawny zapis, ręczny lub automatyczny.
|
||||||
|
Dotychczasowe last_game.res i last_game_backup.res pozostają obsługiwane.
|
||||||
|
- Ręczne pliki: user://saves/slot_*.res, osobne *.backup.res i *.pending.res.
|
||||||
|
Autosave nadal korzysta z last_game.res i nigdy nie nadpisuje nazwanych slotów.
|
||||||
|
- Zapisz i wróć do menu / wyjdź najpierw prosi o nazwę lub wybór slotu.
|
||||||
|
Anulowanie wraca do pauzy bez wykonywania wyjścia.
|
||||||
|
- menu_modal.gd: wspólna responsywna warstwa z przyciemnieniem, nagłówkiem,
|
||||||
|
turkusowymi obramowaniami, złotą akcją główną i przyciskiem zamknięcia/Esc.
|
||||||
|
Używają jej opcje, zapis, odczyt, pauza i komunikaty. Instrukcja i hangar
|
||||||
|
korzystają ze wspólnej palety oraz stylu przycisków.
|
||||||
|
- Opcje: sekcje Dźwięk, Obraz i Język, Anuluj bez zmiany preferencji,
|
||||||
|
Zastosuj zapisuje preferencje. Nowe teksty mają cztery dodatkowe tłumaczenia AI.
|
||||||
|
- Testy: tests/named_save_test.tscn, tests/save_settings_test.tscn,
|
||||||
|
tests/menu_options_preview.tscn. Podglądy: artifacts/load_pl.png,
|
||||||
|
options_pl.png, named_save_en.png, menu_guide_pl.png i menu_hangar_pl.png.
|
||||||
|
|
||||||
|
POI: progresja planet i podgląd wyprawy (27.10.2026)
|
||||||
|
- Pierwszy poziom: łagodne planety; wyposażenie poziomu 1 odzyskuje 100% podstawowego łupu. Lądowanie kosztuje 5 HP, zwykły POI 2–4 HP.
|
||||||
|
- Poziom planety zwiększa zasobność oraz trudność. Sprzęt jest porównywany z poziomem i warunkami planety; każdy rodzaj POI inaczej wykorzystuje aparat oddechowy, kombinezon i ochronę biologiczną.
|
||||||
|
- E przy POI otwiera podgląd nagrody oraz przedziału uszkodzeń. Dopiero potwierdzenie wykonuje akcję. Podgląd jest stały dla danej wizyty i nie losuje ponownie łupu.
|
||||||
|
- Około 25% zwykłych POI oferuje dodatkowe, jednorazowe przeszukanie: dodatkowy łup za większe uszkodzenia. Akcja wymaga osobnego przycisku. Mapa oznacza pozostałe znaleziska kolorem złotym.
|
||||||
|
- Brak statystyk zagrożeń, tlenu, temperatury i mnożników w podglądzie/HUD. Przed ryzykowną akcją pojawia się ostrzeżenie o możliwym zniszczeniu lądownika.
|
||||||
|
- HP równe zero kończy wyprawę i odbiera jej niezabezpieczony łup. Bezpieczny powrót zachowuje znaleziska. Samo otwarcie okna nigdy nie przyznaje nagrody ani nie zadaje obrażeń.
|
||||||
|
- Instrukcja oraz nowe teksty interfejsu przetłumaczone offline na DE/ES/EN/FR. Esc zamyka ekwipunek przed otwarciem pauzy.
|
||||||
|
- Wyniki i testy: artifacts/planet_exploration_validation.md, artifacts/planet_exploration_balance.json.
|
||||||
|
|
||||||
|
Progresja badań (27.10.2026)
|
||||||
|
- Poziom oznacza poziom kapitana. Laboratorium: projekty od poziomu 1, 4, 8, 12, 16, 20, 25 i 30; na 30 dostępna cała pula 23 projektów. Koszty surowców zachowane.
|
||||||
|
- Badania obcych: progi głębokości drzewa 1, 8, 20, 40, 60 i 80. Zachowane zależności i łączny koszt 715 próbek. Końcowe technologie wymagają poziomu 80.
|
||||||
|
- Laboratorium: 600 sekund bazowego czasu gry, z premią Naukowca 540/480/420 sekund. Obcy: 600 sekund. Po jednym projekcie na stanowisko; oba stanowiska mogą działać równolegle. Odkrycie aktywuje się dopiero po zakończeniu.
|
||||||
|
- Zapis przechowuje identyfikator projektu, czas całkowity i dokładny czas pozostały dla obu stanowisk. LOAD nie zeruje badań, nie kończy ich automatycznie i nie nalicza czasu poza grą. Zwykła pauza zatrzymuje badania; eksploracja i dokowanie pozwalają im działać.
|
||||||
|
- Nowe napisy mają tłumaczenia offline DE/ES/EN/FR. Interfejs pokazuje wymagany poziom, czas i trwający projekt.
|
||||||
|
- Testy: research_progression_test (wszystkie 23+28 odkryć, progi, koszty i czas), save_settings_test (rzeczywisty SAVE/LOAD obu liczników), laboratory_test (równoległe badania, pauza, efekty odkrycia), laboratory_loot_test, new_skills_test i testy technologii obcych.
|
||||||
|
|
||||||
|
Korekta zasad badań (27.10.2026)
|
||||||
|
- Usunięto wszystkie progi poziomu kapitana. Od początku losowanie trzech projektów laboratorium korzysta z całej puli nieodkrytych projektów. Poziom kapitana nie wpływa na dostępność ani losowanie.
|
||||||
|
- W badaniach obcych pozostały wyłącznie zależności drzewa, próbki oraz jeden aktywny projekt; brak wymagań poziomu.
|
||||||
|
- Zachowano koszty, 10 minut bazowego badania, dotychczasową umiejętność Naukowiec i pełny zapis liczników. Wcześniejszy opis progów 30/80 jest nieaktualny.
|
||||||
|
|||||||
@ -398,7 +398,7 @@ Ustalono:
|
|||||||
- Naprawa kosztuje 1 część za 1 punkt procentowy HP.
|
- Naprawa kosztuje 1 część za 1 punkt procentowy HP.
|
||||||
- Powrót jest dobrowolny; zniszczenie powoduje utratę bieżącego lootu.
|
- Powrót jest dobrowolny; zniszczenie powoduje utratę bieżącego lootu.
|
||||||
- Wyjście z gry działa jak powrót; docelowo następuje po nim zapis.
|
- Wyjście z gry działa jak powrót; docelowo następuje po nim zapis.
|
||||||
- Zapisu gry na razie nie ma.
|
- Zapis gry jest dostępny od 27.10.2026: Esc lub F6; wczytanie rozpoczyna bieżący poziom od początku.
|
||||||
- Frachtowiec i stałe zasoby pozostają po śmierci.
|
- Frachtowiec i stałe zasoby pozostają po śmierci.
|
||||||
- Nie ma osobnego magazynu frachtowca.
|
- Nie ma osobnego magazynu frachtowca.
|
||||||
- Aktywna walka blokuje lądowanie; sama obecność wrogów w układzie nie.
|
- Aktywna walka blokuje lądowanie; sama obecność wrogów w układzie nie.
|
||||||
@ -1146,3 +1146,26 @@ Efekty lotu i pogoda (18.10.2026)
|
|||||||
- Pogoda biomów: doliny i mokradła deszcz, jesienne lasy liście, wyżyny podmuchy, kaniony pył, tundra śnieg. Natężenie przechodzi płynnie między stanami co 38–85 sekund.
|
- Pogoda biomów: doliny i mokradła deszcz, jesienne lasy liście, wyżyny podmuchy, kaniony pył, tundra śnieg. Natężenie przechodzi płynnie między stanami co 38–85 sekund.
|
||||||
- Niska mgła nad dolinami pozostaje pod statkiem. Nad sceną są delikatne opady i smugi światła; przy silnym deszczu na mokradłach rzadki słaby błysk. Korony drzew lekko kołyszą się z wiatrem.
|
- Niska mgła nad dolinami pozostaje pod statkiem. Nad sceną są delikatne opady i smugi światła; przy silnym deszczu na mokradłach rzadki słaby błysk. Korony drzew lekko kołyszą się z wiatrem.
|
||||||
- Istniejący ambient wiatru reaguje na natężenie pogody. Efekty są kosmetyczne i nie zmieniają szans POI ani zagrożenia.
|
- Istniejący ambient wiatru reaguje na natężenie pogody. Efekty są kosmetyczne i nie zmieniają szans POI ani zagrożenia.
|
||||||
|
|
||||||
|
POI: progresja planet i podgląd wyprawy (27.10.2026)
|
||||||
|
- Pierwszy poziom: łagodne planety; wyposażenie poziomu 1 odzyskuje 100% podstawowego łupu. Lądowanie kosztuje 5 HP, zwykły POI 2–4 HP.
|
||||||
|
- Poziom planety zwiększa zasobność oraz trudność. Sprzęt jest porównywany z poziomem i warunkami planety; każdy rodzaj POI inaczej wykorzystuje aparat oddechowy, kombinezon i ochronę biologiczną.
|
||||||
|
- E przy POI otwiera podgląd nagrody oraz przedziału uszkodzeń. Dopiero potwierdzenie wykonuje akcję. Podgląd jest stały dla danej wizyty i nie losuje ponownie łupu.
|
||||||
|
- Około 25% zwykłych POI oferuje dodatkowe, jednorazowe przeszukanie: dodatkowy łup za większe uszkodzenia. Akcja wymaga osobnego przycisku. Mapa oznacza pozostałe znaleziska kolorem złotym.
|
||||||
|
- Brak statystyk zagrożeń, tlenu, temperatury i mnożników w podglądzie/HUD. Przed ryzykowną akcją pojawia się ostrzeżenie o możliwym zniszczeniu lądownika.
|
||||||
|
- HP równe zero kończy wyprawę i odbiera jej niezabezpieczony łup. Bezpieczny powrót zachowuje znaleziska. Samo otwarcie okna nigdy nie przyznaje nagrody ani nie zadaje obrażeń.
|
||||||
|
- Instrukcja oraz nowe teksty interfejsu przetłumaczone offline na DE/ES/EN/FR. Esc zamyka ekwipunek przed otwarciem pauzy.
|
||||||
|
- Wyniki i testy: artifacts/planet_exploration_validation.md, artifacts/planet_exploration_balance.json.
|
||||||
|
|
||||||
|
Progresja badań (27.10.2026)
|
||||||
|
- Poziom oznacza poziom kapitana. Laboratorium: projekty od poziomu 1, 4, 8, 12, 16, 20, 25 i 30; na 30 dostępna cała pula 23 projektów. Koszty surowców zachowane.
|
||||||
|
- Badania obcych: progi głębokości drzewa 1, 8, 20, 40, 60 i 80. Zachowane zależności i łączny koszt 715 próbek. Końcowe technologie wymagają poziomu 80.
|
||||||
|
- Laboratorium: 600 sekund bazowego czasu gry, z premią Naukowca 540/480/420 sekund. Obcy: 600 sekund. Po jednym projekcie na stanowisko; oba stanowiska mogą działać równolegle. Odkrycie aktywuje się dopiero po zakończeniu.
|
||||||
|
- Zapis przechowuje identyfikator projektu, czas całkowity i dokładny czas pozostały dla obu stanowisk. LOAD nie zeruje badań, nie kończy ich automatycznie i nie nalicza czasu poza grą. Zwykła pauza zatrzymuje badania; eksploracja i dokowanie pozwalają im działać.
|
||||||
|
- Nowe napisy mają tłumaczenia offline DE/ES/EN/FR. Interfejs pokazuje wymagany poziom, czas i trwający projekt.
|
||||||
|
- Testy: research_progression_test (wszystkie 23+28 odkryć, progi, koszty i czas), save_settings_test (rzeczywisty SAVE/LOAD obu liczników), laboratory_test (równoległe badania, pauza, efekty odkrycia), laboratory_loot_test, new_skills_test i testy technologii obcych.
|
||||||
|
|
||||||
|
Korekta zasad badań (27.10.2026)
|
||||||
|
- Usunięto wszystkie progi poziomu kapitana. Od początku losowanie trzech projektów laboratorium korzysta z całej puli nieodkrytych projektów. Poziom kapitana nie wpływa na dostępność ani losowanie.
|
||||||
|
- W badaniach obcych pozostały wyłącznie zależności drzewa, próbki oraz jeden aktywny projekt; brak wymagań poziomu.
|
||||||
|
- Zachowano koszty, 10 minut bazowego badania, dotychczasową umiejętność Naukowiec i pełny zapis liczników. Wcześniejszy opis progów 30/80 jest nieaktualny.
|
||||||
|
|||||||
@ -17,6 +17,7 @@ config/icon="res://icon.svg"
|
|||||||
|
|
||||||
[autoload]
|
[autoload]
|
||||||
|
|
||||||
|
GameSettings="*res://scripts/game/game_settings.gd"
|
||||||
GameState="*res://scripts/game/game_state.gd"
|
GameState="*res://scripts/game/game_state.gd"
|
||||||
MCPRuntimeServer="*res://addons/godot_mcp_toolkit/runtime/mcp_runtime_server.gd"
|
MCPRuntimeServer="*res://addons/godot_mcp_toolkit/runtime/mcp_runtime_server.gd"
|
||||||
|
|
||||||
|
|||||||
637
resources/localization/authored.tsv
Normal file
1105
resources/localization/de_catalog.gd
Normal file
1
resources/localization/de_catalog.gd.uid
Normal file
@ -0,0 +1 @@
|
|||||||
|
uid://cw37g2vl88y4o
|
||||||
1105
resources/localization/en_catalog.gd
Normal file
1
resources/localization/en_catalog.gd.uid
Normal file
@ -0,0 +1 @@
|
|||||||
|
uid://d16fsi6s03mud
|
||||||
1105
resources/localization/es_catalog.gd
Normal file
1
resources/localization/es_catalog.gd.uid
Normal file
@ -0,0 +1 @@
|
|||||||
|
uid://ejhaweptx5e7
|
||||||
1105
resources/localization/fr_catalog.gd
Normal file
1
resources/localization/fr_catalog.gd.uid
Normal file
@ -0,0 +1 @@
|
|||||||
|
uid://b6rtmtbskfm8b
|
||||||
95
resources/localization/interface.csv
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
key,pl,de,es,en,fr
|
||||||
|
NOWA WYPRAWA,NOWA WYPRAWA,NEUE EXPEDITION,NUEVA EXPEDICIÓN,NEW EXPEDITION,NOUVELLE EXPÉDITION
|
||||||
|
KONTYNUUJ,KONTYNUUJ,FORTSETZEN,CONTINUAR,CONTINUE,CONTINUER
|
||||||
|
INSTRUKCJA,INSTRUKCJA,ANLEITUNG,INSTRUCCIONES,HOW TO PLAY,INSTRUCTIONS
|
||||||
|
ZAPIS ROZGRYWKI,ZAPIS ROZGRYWKI,SPIELSTAND,PARTIDA GUARDADA,SAVED GAME,SAUVEGARDE
|
||||||
|
OPCJE,OPCJE,OPTIONEN,OPCIONES,OPTIONS,OPTIONS
|
||||||
|
WYJŚCIE,WYJŚCIE,BEENDEN,SALIR,EXIT,QUITTER
|
||||||
|
Wybierz statek i ruszaj w nieznane,Wybierz statek i ruszaj w nieznane,Wähle dein Schiff und starte,Elige tu nave y explora,Choose your ship and explore,Choisissez votre vaisseau et explorez
|
||||||
|
Wczytaj ostatnią wyprawę,Wczytaj ostatnią wyprawę,Letzte Expedition laden,Cargar la última expedición,Load your last expedition,Charger la dernière expédition
|
||||||
|
Pierwszy lot? Zacznij tutaj,Pierwszy lot? Zacznij tutaj,Dein erster Flug? Hier starten,¿Primer vuelo? Empieza aquí,First flight? Start here,Premier vol ? Commencez ici
|
||||||
|
Ostatni zapis i kopia zapasowa,Ostatni zapis i kopia zapasowa,Letzter Spielstand und Sicherung,Última partida y copia de seguridad,Latest save and backup,Dernière sauvegarde et copie
|
||||||
|
"Dźwięk, obraz i język","Dźwięk, obraz i język","Ton, Grafik und Sprache","Sonido, imagen e idioma","Sound, display and language","Son, affichage et langue"
|
||||||
|
Zakończ grę,Zakończ grę,Spiel beenden,Salir del juego,Exit the game,Quitter le jeu
|
||||||
|
DZIENNIK POKŁADOWY / NOWA WYPRAWA,DZIENNIK POKŁADOWY / NOWA WYPRAWA,BORDBUCH / NEUE EXPEDITION,DIARIO DE A BORDO / NUEVA EXPEDICIÓN,SHIP LOG / NEW EXPEDITION,JOURNAL DE BORD / NOUVELLE EXPÉDITION
|
||||||
|
Nieznany kosmos. Niepowtarzalny łup.,Nieznany kosmos. Niepowtarzalny łup.,Unbekanntes All. Einzigartige Beute.,Espacio desconocido. Botín único.,Unknown space. Unique loot.,Espace inconnu. Butin unique.
|
||||||
|
Głośność ogólna,Głośność ogólna,Gesamtlautstärke,Volumen general,Master volume,Volume général
|
||||||
|
Głośność muzyki,Głośność muzyki,Musiklautstärke,Volumen de música,Music volume,Volume de la musique
|
||||||
|
Rozdzielczość,Rozdzielczość,Auflösung,Resolución,Resolution,Résolution
|
||||||
|
Pełny ekran,Pełny ekran,Vollbild,Pantalla completa,Fullscreen,Plein écran
|
||||||
|
Język,Język,Sprache,Idioma,Language,Langue
|
||||||
|
Zastosuj,Zastosuj,Anwenden,Aplicar,Apply,Appliquer
|
||||||
|
Anuluj,Anuluj,Abbrechen,Cancelar,Cancel,Annuler
|
||||||
|
Zamknij,Zamknij,Schließen,Cerrar,Close,Fermer
|
||||||
|
Pauza,Pauza,Pause,Pausa,Paused,Pause
|
||||||
|
Wróć do gry,Wróć do gry,Zurück zum Spiel,Volver al juego,Resume game,Reprendre la partie
|
||||||
|
Zapisz grę,Zapisz grę,Spiel speichern,Guardar partida,Save game,Sauvegarder
|
||||||
|
Zapisz i wróć do menu,Zapisz i wróć do menu,Speichern und zum Menü,Guardar y volver al menú,Save and return to menu,Sauvegarder et revenir au menu
|
||||||
|
Zapisz i wyjdź,Zapisz i wyjdź,Speichern und beenden,Guardar y salir,Save and quit,Sauvegarder et quitter
|
||||||
|
Zapisano grę.,Zapisano grę.,Spiel gespeichert.,Partida guardada.,Game saved.,Partie sauvegardée.
|
||||||
|
Nie udało się zapisać gry.,Nie udało się zapisać gry.,Spiel konnte nicht gespeichert werden.,No se pudo guardar la partida.,Could not save the game.,Impossible de sauvegarder la partie.
|
||||||
|
Nie udało się zapisać ustawień.,Nie udało się zapisać ustawień.,Einstellungen konnten nicht gespeichert werden.,No se pudieron guardar los ajustes.,Could not save settings.,Impossible de sauvegarder les paramètres.
|
||||||
|
Brak poprawnego zapisu gry.,Brak poprawnego zapisu gry.,Kein gültiger Spielstand vorhanden.,No hay ninguna partida válida.,No valid saved game found.,Aucune sauvegarde valide trouvée.
|
||||||
|
"Ostatni zapis: %s
|
||||||
|
Układ: %d · Kapitan: %d","Ostatni zapis: %s
|
||||||
|
Układ: %d · Kapitan: %d","Letzter Spielstand: %s
|
||||||
|
System: %d · Kapitän: %d","Última partida: %s
|
||||||
|
Sistema: %d · Capitán: %d","Last saved: %s
|
||||||
|
System: %d · Captain: %d","Dernière sauvegarde : %s
|
||||||
|
Système : %d · Capitaine : %d"
|
||||||
|
Wróć,Wróć,Zurück,Volver,Back,Retour
|
||||||
|
POWRÓT,POWRÓT,ZURÜCK,VOLVER,BACK,RETOUR
|
||||||
|
ZAMKNIJ,ZAMKNIJ,SCHLIESSEN,CERRAR,CLOSE,FERMER
|
||||||
|
KAPITAN,KAPITAN,KAPITÄN,CAPITÁN,CAPTAIN,CAPITAINE
|
||||||
|
Kapitan,Kapitan,Kapitän,Capitán,Captain,Capitaine
|
||||||
|
STATEK,STATEK,SCHIFF,NAVE,SHIP,VAISSEAU
|
||||||
|
Statek,Statek,Schiff,Nave,Ship,Vaisseau
|
||||||
|
WYPOSAŻENIE,WYPOSAŻENIE,AUSRÜSTUNG,EQUIPO,EQUIPMENT,ÉQUIPEMENT
|
||||||
|
Wyposażenie,Wyposażenie,Ausrüstung,Equipo,Equipment,Équipement
|
||||||
|
ŁADOWNIA,ŁADOWNIA,FRACHTRAUM,BODEGA,CARGO,SOUTE
|
||||||
|
Ładownia,Ładownia,Frachtraum,Bodega,Cargo,Soute
|
||||||
|
BROŃ,BROŃ,WAFFEN,ARMAS,WEAPONS,ARMES
|
||||||
|
Broń,Broń,Waffen,Armas,Weapons,Armes
|
||||||
|
KADŁUB,KADŁUB,RUMPF,CASCO,HULL,COQUE
|
||||||
|
Kadłub,Kadłub,Rumpf,Casco,Hull,Coque
|
||||||
|
TARCZE,TARCZE,SCHILDE,ESCUDOS,SHIELDS,BOUCLIERS
|
||||||
|
Tarcze,Tarcze,Schilde,Escudos,Shields,Boucliers
|
||||||
|
ENERGIA,ENERGIA,ENERGIE,ENERGÍA,ENERGY,ÉNERGIE
|
||||||
|
Energia,Energia,Energie,Energía,Energy,Énergie
|
||||||
|
Pancerz,Pancerz,Panzerung,Blindaje,Armor,Blindage
|
||||||
|
Silnik,Silnik,Triebwerk,Motor,Engine,Moteur
|
||||||
|
Reaktor,Reaktor,Reaktor,Reactor,Reactor,Réacteur
|
||||||
|
Komputer,Komputer,Computer,Computadora,Computer,Ordinateur
|
||||||
|
HANGAR,HANGAR,HANGAR,HANGAR,HANGAR,HANGAR
|
||||||
|
WARSZTAT,WARSZTAT,WERKSTATT,TALLER,WORKSHOP,ATELIER
|
||||||
|
LABORATORIUM,LABORATORIUM,LABOR,LABORATORIO,LABORATORY,LABORATOIRE
|
||||||
|
BADANIA OBCYCH,BADANIA OBCYCH,ALIENFORSCHUNG,INVESTIGACIÓN ALIENÍGENA,ALIEN RESEARCH,RECHERCHE EXTRATERRESTRE
|
||||||
|
ZAŁOGA,ZAŁOGA,BESATZUNG,TRIPULACIÓN,CREW,ÉQUIPAGE
|
||||||
|
HANDEL,HANDEL,HANDEL,COMERCIO,TRADE,COMMERCE
|
||||||
|
KUP,KUP,KAUFEN,COMPRAR,BUY,ACHETER
|
||||||
|
SPRZEDAJ,SPRZEDAJ,VERKAUFEN,VENDER,SELL,VENDRE
|
||||||
|
NAPRAW,NAPRAW,REPARIEREN,REPARAR,REPAIR,RÉPARER
|
||||||
|
ZBUDUJ,ZBUDUJ,BAUEN,CONSTRUIR,BUILD,CONSTRUIRE
|
||||||
|
ODLOKUJ,ODLOKUJ,FREISCHALTEN,DESBLOQUEAR,UNLOCK,DÉBLOQUER
|
||||||
|
USUŃ,USUŃ,ENTFERNEN,ELIMINAR,REMOVE,SUPPRIMER
|
||||||
|
ZAMONTUJ,ZAMONTUJ,EINBAUEN,INSTALAR,INSTALL,INSTALLER
|
||||||
|
ZDEMONTUJ,ZDEMONTUJ,AUSBAUEN,DESMONTAR,UNINSTALL,DÉMONTER
|
||||||
|
Żelazo,Żelazo,Eisen,Hierro,Iron,Fer
|
||||||
|
Aluminium,Aluminium,Aluminium,Aluminio,Aluminium,Aluminium
|
||||||
|
Tytan,Tytan,Titan,Titanio,Titanium,Titane
|
||||||
|
Uran,Uran,Uran,Uranio,Uranium,Uranium
|
||||||
|
Siarka,Siarka,Schwefel,Azufre,Sulfur,Soufre
|
||||||
|
Deuter,Deuter,Deuterium,Deuterio,Deuterium,Deutérium
|
||||||
|
Kredyty,Kredyty,Credits,Créditos,Credits,Crédits
|
||||||
|
Części,Części,Teile,Piezas,Parts,Pièces
|
||||||
|
Amunicja,Amunicja,Munition,Munición,Ammunition,Munitions
|
||||||
|
Rakiety,Rakiety,Raketen,Misiles,Missiles,Missiles
|
||||||
|
Próbki,Próbki,Proben,Muestras,Samples,Échantillons
|
||||||
|
Poziom,Poziom,Stufe,Nivel,Level,Niveau
|
||||||
|
Doświadczenie,Doświadczenie,Erfahrung,Experiencia,Experience,Expérience
|
||||||
|
Umiejętności,Umiejętności,Fähigkeiten,Habilidades,Skills,Compétences
|
||||||
|
UMIEJĘTNOŚCI,UMIEJĘTNOŚCI,FÄHIGKEITEN,HABILIDADES,SKILLS,COMPÉTENCES
|
||||||
|
Zbadano,Zbadano,Erforscht,Investigado,Researched,Recherché
|
||||||
|
Za mało próbek,Za mało próbek,Zu wenige Proben,Muestras insuficientes,Not enough samples,Échantillons insuffisants
|
||||||
|
Magazyn pełny,Magazyn pełny,Lager voll,Almacén lleno,Storage full,Stockage plein
|
||||||
|
Brak miejsca,Brak miejsca,Kein Platz,Sin espacio,No space,Pas de place
|
||||||
|
19
resources/localization/interface.csv.import
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="csv_translation"
|
||||||
|
type="Translation"
|
||||||
|
uid="uid://cbo6qynjf4ie6"
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
files=["res://resources/localization/interface.pl.translation", "res://resources/localization/interface.de.translation", "res://resources/localization/interface.es.translation", "res://resources/localization/interface.en.translation", "res://resources/localization/interface.fr.translation"]
|
||||||
|
|
||||||
|
source_file="res://resources/localization/interface.csv"
|
||||||
|
dest_files=["res://resources/localization/interface.pl.translation", "res://resources/localization/interface.de.translation", "res://resources/localization/interface.es.translation", "res://resources/localization/interface.en.translation", "res://resources/localization/interface.fr.translation"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress=1
|
||||||
|
delimiter=0
|
||||||
|
unescape_keys=false
|
||||||
|
unescape_translations=true
|
||||||
BIN
resources/localization/interface.de.translation
Normal file
BIN
resources/localization/interface.en.translation
Normal file
BIN
resources/localization/interface.es.translation
Normal file
BIN
resources/localization/interface.fr.translation
Normal file
BIN
resources/localization/interface.pl.translation
Normal file
700
resources/localization/source_strings.json
Normal file
@ -0,0 +1,700 @@
|
|||||||
|
[
|
||||||
|
"\nBrak miejsca: %d modułów czeka we frachtowcu.",
|
||||||
|
"\nEARTHLIKE · LĄDOWANIE",
|
||||||
|
"\nKoszt: ",
|
||||||
|
"\nORB DOPALACZA · TAB bez kosztu energii. Działa po zamontowaniu silnika.",
|
||||||
|
"\nORB PRZEBICIA · 50% obrażeń omija tarcze. Tylko ta broń.",
|
||||||
|
"\nPASYWNE • Bez kosztu i cooldownu.\nDuplikaty nie sumują efektu — działa najlepszy egzemplarz.",
|
||||||
|
"\nPodleć, aby przeszukać",
|
||||||
|
"\nRedukcja zagrożenia: %d pp (2 pp/poziom, maks. 100 pp).\nPoziom 50 całkowicie neutralizuje odpowiadające zagrożenie.",
|
||||||
|
"\nSprawdź wymagane zasoby i aktualne zagrożenie.",
|
||||||
|
"\nTen etap ma 0% szans przy obecnym zagrożeniu.",
|
||||||
|
"\nUSŁUGI DOSTĘPNE",
|
||||||
|
"\nUkład oczyszczony",
|
||||||
|
"\nZa mało próbek",
|
||||||
|
"\nZamontowane — najpierw zdejmij do ładowni.",
|
||||||
|
"\n[E] Kup mapę",
|
||||||
|
"\n[E] Placówka",
|
||||||
|
" · +1 część (Zbieracz złomu)",
|
||||||
|
" [ZAŁOŻONE]",
|
||||||
|
" kadłuba",
|
||||||
|
" · Moduły: %d",
|
||||||
|
" · brak zakresu",
|
||||||
|
"%d KREDYTÓW\n%d CZĘŚCI\n%d KRYSZTAŁÓW CZASU",
|
||||||
|
"%d kredytów%s",
|
||||||
|
"%d%% szansy na 1 dodatkową część z przeszukanego wraku. Losowanie raz na wrak. Premie rang nie sumują się.",
|
||||||
|
"%s\n\n%s\nR • Zużywa jedną sztukę z zasobów.",
|
||||||
|
"%s\n%s\nPrzeciągnij przedmiot do pasującego slotu. Dwuklik zakłada lub zdejmuje.",
|
||||||
|
"%s\nMagazyn pełny",
|
||||||
|
"%s\nStatystyki bazowe przed bonusami modułów.\n%s",
|
||||||
|
"%s\nStos: %d\n\n%s\n\nDwuklik: wybierz orb. Następnie kliknij odpowiedni moduł lub broń. PPM lub Esc anuluje.",
|
||||||
|
"%s\nZarządzanie: %d / 100\nPremia do wydobycia: +%d%%",
|
||||||
|
"%s\nŁadownia pełna",
|
||||||
|
"%s / POZIOM %d",
|
||||||
|
"%s · %s\nTLEN %d%% · TEMP %d°C · BIO %d/50\nZAGROŻENIE: %.1f%% / 300%%\nŁUP POI: ×%.2f · odzysk %.0f%%\nPOI: podleć i naciśnij E\nLądowanie −%d HP · Lądownik %d%%",
|
||||||
|
"%s · %s\nTLEN %d%% · zagrożenie %.0f%% → %.0f%%\nTEMPERATURA %d°C · zagrożenie %.0f%% → %.0f%%\nBIOLOGICZNE %d/50 · zagrożenie %.0f%% → %.0f%%\nZAGROŻENIE GLOBALNE: %.1f%% / 300%%\nBez sprzętu: %.1f%% · redukcja 2 pp/poziom\nŁUP POI: ×%.2f · odzysk %.0f%% · sprzęt ×%.2f\nPOI: podleć i naciśnij E, aby odebrać znaleziska.\nLądowanie: −%d HP · Lądownik: %d%%",
|
||||||
|
"%s · poziom %d",
|
||||||
|
"%s · poziom %d\n%s\n[%s] · Odnowienie %d s%s",
|
||||||
|
"%s · poziom %d\nKoszt: %s\nWytwarza i zakłada nowy przedmiot.",
|
||||||
|
"%s · poziom %d / 3\n%s",
|
||||||
|
"%s · poziom wyprawy %d",
|
||||||
|
"%s · zarządzanie %d/100 · %.1f deuteru/min",
|
||||||
|
"%s • Poziom %d",
|
||||||
|
"%s: %d partii = %d szt.\nKoszt: %s",
|
||||||
|
"+%d KREDYTÓW",
|
||||||
|
"+%d KRYSZTAŁÓW CZASU",
|
||||||
|
"+%d doświadczenia · +1 moduł",
|
||||||
|
"+%d szt. surowca z każdej zniszczonej asteroidy.",
|
||||||
|
"+%d wraków na nowej planszy. Premia ustalana przy rozpoczęciu systemu; nie zmienia bieżącej planszy. Premie rang nie sumują się.",
|
||||||
|
"+1 000 000 kredytów i deuteru\n+10 000 każdego minerału, części i kryształów czasu\n+1000 próbek, +25 każdego orba, +100 punktów nauki\n+10 000 amunicji, +1000 radiacyjnej i rakiet, +100 powerbanków\nMapy: poziomy 2, obecny +1/+5, 120, 125 i 130 (bez duplikatów)\nPo 1 każdego rodzaju wyposażenia do magazynu fregaty oraz sprzęt kapitana.",
|
||||||
|
"+10 zwykłej amunicji, +10 radiacyjnej amunicji i +10 rakiet",
|
||||||
|
"01 / POKŁAD GŁÓWNY · POŁĄCZENIE ZABEZPIECZONE",
|
||||||
|
"01 / PANCERZ I OCHRONA",
|
||||||
|
"02 / TARCZE I ENERGIA",
|
||||||
|
"03 / SIŁA OGNIA",
|
||||||
|
"04 / NAPĘD I NAWIGACJA",
|
||||||
|
"05 / ŁADOWNIA I ZAOPATRZENIE",
|
||||||
|
"1 KLIKNIĘCIE = 1 RECEPTURA • PRODUKCJA BEZPOŚREDNIO Z MINERAŁÓW",
|
||||||
|
"50 amunicji → 1 działko z 50 pociskami",
|
||||||
|
"50% obrażeń broni omija tarcze i trafia bezpośrednio w kadłub. Tylko broń.",
|
||||||
|
"AKTYWNE SLOTY F1–F5 · MAKSYMALNIE 5 UMIEJĘTNOŚCI",
|
||||||
|
"AMUNICJA I RAKIETY",
|
||||||
|
"AWANSUJ +1 POZIOM",
|
||||||
|
"Absorpcja obrażeń energetycznych",
|
||||||
|
"Absorpcja obrażeń kinetycznych",
|
||||||
|
"Absorpcja obrażeń radiacyjnych",
|
||||||
|
"Aktywne rozszerzenie statku. Tworzy dodatkową, większą warstwę ochronną. Zamontuj w slocie rozszerzeń i użyj przypisanego klawisza 1–5.",
|
||||||
|
"Aktywne rozszerzenie statku. Zamontuj w slocie rozszerzeń i użyj przypisanego klawisza 1–5.",
|
||||||
|
"Aluminium",
|
||||||
|
"Amunicja do wyrzutni rakiet. Obrażenia kinetyczne.",
|
||||||
|
"Amunicja zwykła",
|
||||||
|
"Amunicja: 1 rakieta / strzał • Cooldown bazowy: 5 s • Bez kosztu energii",
|
||||||
|
"Analiza częstotliwości",
|
||||||
|
"Archiwum bez głosu",
|
||||||
|
"Automatyczne dostawy z obsadzonych placówek · %.0f / min",
|
||||||
|
"Autorzy dźwięków",
|
||||||
|
"Awansuje przedmiot o 1 poziom i ponownie losuje jego parametry oraz wartości obecnych addonów. Zachowuje ich typy, liczbę i efekty orbów. Wyniki losowania mogą być niższe. Jedna sztuka daje jeden awans. Kolejny awans wymaga nowego orba (główna progresja do 120; 1000 to limit techniczny). Nie działa na materiały zużywalne.",
|
||||||
|
"BOSS",
|
||||||
|
"BRAK SUROWCÓW",
|
||||||
|
"BRAKUJE SUROWCÓW — NAJEDŹ NA RECEPTURĘ, ABY SPRAWDZIĆ KOSZT",
|
||||||
|
"BROŃ",
|
||||||
|
"BROŃ %d / %s",
|
||||||
|
"BROŃ [%s]",
|
||||||
|
"Bardzo szybkostrzelna broń kinetyczna. Zużywa 1 sztukę amunicji na strzał.",
|
||||||
|
"Bez przydziału",
|
||||||
|
"Bezpieczny układ · zaopatrzenie",
|
||||||
|
"Bezpośrednie trafienie kadłuba dobija zwykłego obcego przy maksymalnie 8% kadłuba, a bossa przy 2%. Statek rozpada się na fragmenty.",
|
||||||
|
"Bezpośrednie trafienie odsłoniętego kadłuba otwiera wyrwę na 5 s. Kolejne twoje trafienia ignorują połowę absorpcji tego statku. Wyrwy nie sumują się.",
|
||||||
|
"Boss",
|
||||||
|
"Brak bezpiecznego miejsca na teleport",
|
||||||
|
"Brak części",
|
||||||
|
"Brak dostępnych addonów.",
|
||||||
|
"Brak energii",
|
||||||
|
"Brak modułu",
|
||||||
|
"Brak odpowiedniego przedmiotu",
|
||||||
|
"Brak placówek. Szukaj głębokich złóż na planetach (szansa 60%). Budowa: zasobność × 10 części.",
|
||||||
|
"Brak poprawnego zapisu gry.",
|
||||||
|
"Brak połączenia z wyposażeniem statku.",
|
||||||
|
"Brak przedmiotów z addonami na statku. Zabierz wyposażenie z magazynu fregaty przed lądowaniem.",
|
||||||
|
"Brak rozszerzenia",
|
||||||
|
"Brak sektorów do zbadania. Szukaj pustelnika na planecie lub map w łupach z wypraw.",
|
||||||
|
"Brak wolnej, zbudowanej kajuty. Przygotuj pokój na fregacie.",
|
||||||
|
"Brak zamontowanej broni",
|
||||||
|
"Brak załogantów. Przygotuj kajutę i zatrudnij specjalistę spotkanego na planecie.",
|
||||||
|
"Brakuje %d kryształów czasu.",
|
||||||
|
"Brakuje kryształów, addon jest już maksymalny lub przedmiot jest niedostępny.",
|
||||||
|
"Brakuje zasobów. Koszt: ",
|
||||||
|
"Broń",
|
||||||
|
"Broń obcych zadaje o 10% mniej obrażeń.",
|
||||||
|
"Broń ręczna",
|
||||||
|
"Budowa kosztuje zasobność × 10 części. Do wydobycia potrzebny jest załogant.",
|
||||||
|
"Budowa wymaga po 100 każdego z pięciu surowców kosmicznych.",
|
||||||
|
"Burza pyłowa",
|
||||||
|
"CECHA GŁÓWNA",
|
||||||
|
"Celny strzał",
|
||||||
|
"Ciężki, szybki pocisk kinetyczny. Silne pojedyncze uderzenie co 2,2 s. Zużywa 10 zwykłej amunicji, bez energii.",
|
||||||
|
"Ciężkie drzwi ustępują. W niszy pośród zatartych reliefów czeka kolejny fragment dawnej technologii.",
|
||||||
|
"Czas między wystrzeleniem rakiet krótszy o %d%%. Działa po premiach sprzętu; minimalny odstęp to 1 s. Premie rang nie sumują się.",
|
||||||
|
"Czeka na załoganta",
|
||||||
|
"Części",
|
||||||
|
"DEUTER / PALIWO FREGATY",
|
||||||
|
"DPS jednego działka",
|
||||||
|
"DPS uwzględnia premie wyposażenia, kapitana, krytyki i promieniowanie. To wartość teoretyczna, przed obroną celu; rzeczywisty wynik zależy od trafień, energii i amunicji.",
|
||||||
|
"DZIAŁANIE %d s",
|
||||||
|
"DZIENNIK POKŁADOWY / NOWA WYPRAWA",
|
||||||
|
"Daleko od światła powierzchni leży podziemny zbiornik. Wokół niego przetrwały najcenniejsze próbki — i najtrudniejsza droga powrotna.",
|
||||||
|
"Deuter",
|
||||||
|
"Deuter: %.1f · Produkcja: %.0f/min",
|
||||||
|
"Do 3% maksymalnych tarcz na sekundę.",
|
||||||
|
"Dodaj amunicję",
|
||||||
|
"Dodano pełny pakiet zasobów, amunicję, wszystkie orby i %d map.\n%d przedmiotów czeka w magazynie fregaty; dodano też sprzęt kapitana i punkty nauki.",
|
||||||
|
"Dodatkowa tarcza już działa",
|
||||||
|
"Dodatkowe 5% obrażeń tarczom obcych. Sumuje się z Wiedzą o tarczach.",
|
||||||
|
"Dodatkowe 5% szansy uniknięcia obrażeń od wrogich obcych. Łączy się niezależnie z pozostałymi unikami.",
|
||||||
|
"Dopalacz już działa",
|
||||||
|
"Dopalacz pod TAB nie zużywa energii i działa również przy pustym generatorze. Tylko silnik.",
|
||||||
|
"Dowódca dronów",
|
||||||
|
"Doładowanie tarcz",
|
||||||
|
"Doświadczenie",
|
||||||
|
"Doświadczenie (EXP)",
|
||||||
|
"Drony już walczą",
|
||||||
|
"Duże obrażenia na krótkim dystansie. Cztery strzały na sekundę.",
|
||||||
|
"Działka zewnętrzne",
|
||||||
|
"Działko gamma",
|
||||||
|
"Działko maszynowe",
|
||||||
|
"Działko plazmowe",
|
||||||
|
"Działo artyleryjskie",
|
||||||
|
"Dźwięk, obraz i język",
|
||||||
|
"ENERGIA",
|
||||||
|
"Elite",
|
||||||
|
"Energia",
|
||||||
|
"Energia na strzał",
|
||||||
|
"Ewakuuj pracowników",
|
||||||
|
"FREGATA / POKŁAD OPERACYJNY",
|
||||||
|
"FREGATA • PANCERZ",
|
||||||
|
"GROŹNA FAUNA",
|
||||||
|
"Globalnie odnawia tarcze z faktycznie zadanych obrażeń. Łącznie do 10% obrażeń; tempo odzysku do 5% maksymalnych tarcz/s, z rezerwą na jedno takie odnowienie.",
|
||||||
|
"Gorąca biosfera",
|
||||||
|
"Górnik",
|
||||||
|
"Gęsta mgła",
|
||||||
|
"GŁĘBOKIE ZŁOŻE / DEUTER",
|
||||||
|
"Głośność muzyki",
|
||||||
|
"Głośność ogólna",
|
||||||
|
"Główna progresja: poziomy 1–120. HP, tarcze i atak wrogów rosną o 10% wartości bazowej na poziom, po 120 o 20%. Bazowe parametry łupu rosną o 7% na poziom przedmiotu. Bonusy procentowe mają limity. Poziom 1000 to limit techniczny wyposażenia.",
|
||||||
|
"Głębokie złoże deuteru",
|
||||||
|
"HANGAR",
|
||||||
|
"HANGAR / OBSŁUGA",
|
||||||
|
"HANGAR / WYBÓR STATKU",
|
||||||
|
"IDŹ DO NASTĘPNEGO POZIOMU",
|
||||||
|
"INICJALIZACJA NAPĘDU SKOKOWEGO",
|
||||||
|
"INŻYNIER CHRONALNY",
|
||||||
|
"Inżynier chronalny",
|
||||||
|
"Inżynierka rozłożyła stanowisko pomiarowe daleko od zabudowań. Potrzebuje lądownika do krótkiego testu nowego układu zasilania. Zapewnia podstawową zapłatę niezależnie od wyniku i dodatkową premię za poprawny przebieg próby. Gdy pytasz o ryzyko, bez słowa przesyła zapis poprzedniego testu. Widać na nim nagły skok napięcia.",
|
||||||
|
"Izolowane próbki i komora do badań obcych organizmów.",
|
||||||
|
"Jeden załogant obsługuje jedną placówkę. Nowy przydział przenosi go z poprzedniej.",
|
||||||
|
"Jednorazowa wyprawa. Zużywa mapę i pobiera %d deuteru.",
|
||||||
|
"Jednorazowy powerbank. Przywraca 10% maksymalnej energii statku, do jego aktualnego limitu. Użyj klawiszem R podczas lotu.",
|
||||||
|
"Język",
|
||||||
|
"KADŁUB",
|
||||||
|
"KAPITAN",
|
||||||
|
"KAPITAN · PASYWNE",
|
||||||
|
"KOMPUTER",
|
||||||
|
"KORSARZ • ENERGIA",
|
||||||
|
"KOSZT BUDOWY",
|
||||||
|
"KOSZT · posiadasz / wymagane\n",
|
||||||
|
"KUP 100 AMUNICJI — 100 KREDYTÓW",
|
||||||
|
"KUP MAPĘ · %d KREDYTÓW",
|
||||||
|
"Kadłub",
|
||||||
|
"Kadłub jest pełny",
|
||||||
|
"Kadłub jest w pełni sprawny. Naprawa nie jest potrzebna.",
|
||||||
|
"Kadłub nie wymaga naprawy",
|
||||||
|
"Kadłub: %d · Tarcze: %d\nEnergia: %d · Prędkość: %d px/s",
|
||||||
|
"Kamuflaż",
|
||||||
|
"Kamuflaż już działa",
|
||||||
|
"Kapsuły do działka gamma. Obrażenia radiacyjne.",
|
||||||
|
"Każda nadlatująca wroga rakieta ma 25% szansy zostać przechwycona w zasięgu 240 px od statku. Przechwycona rakieta wybucha bez zadawania obrażeń. Jeden rzut na rakietę.",
|
||||||
|
"Każde bezpośrednie trafienie twojej broni zadaje obcym dodatkowe 5 obrażeń przed absorpcją.",
|
||||||
|
"Każde bezpośrednie trafienie zadaje pełne obrażenia jednocześnie tarczom i kadłubowi obcego. Nadal działa absorpcja.",
|
||||||
|
"Każdy orb jest jednorazowy i znika po użyciu. Kolejny awans wymaga kolejnej sztuki. Efekty tego samego orba nie sumują się. Orby typu obrażeń zastępują się. Replika trafia do magazynu.",
|
||||||
|
"Każdy punkt: +1 punkt procentowy szansy na trafienie krytyczne. Maksymalnie +20 przy 20 punktach.",
|
||||||
|
"Każdy punkt: +2% obrażeń wszystkich broni. Maksymalnie +40% przy 20 punktach.",
|
||||||
|
"Każdy strzał / impuls losuje obrażenia z tego zakresu.",
|
||||||
|
"Każdy strzał ma 1% szansy wyłączyć na 5 sekund losowy system obcego: silnik, broń lub tarcze. Czerwona ikona nad wrogiem wskazuje wyłączony system. Obrażenia okresowe nie losują ponownie.",
|
||||||
|
"Każdy zebrany odłamek asteroidy odnawia %.1f%% maksymalnych tarcz i energii.",
|
||||||
|
"Kliknij, aby otworzyć ekwipunek kapitana",
|
||||||
|
"Kliknij, aby wytworzyć",
|
||||||
|
"Kliknięcie rozstawia autonomiczne działko lewitujące w miejscu. Koszt: dokładnie 50 amunicji, która trafia do jego magazynka. Działko samodzielnie celuje i oddaje 50 strzałów; potem znika. Obrażenia każdego pocisku są o 50% niższe niż działka maszynowego z takimi samymi parametrami. Nie zużywa dalszej amunicji statku. Znika przy dokowaniu lub zniszczeniu statku.",
|
||||||
|
"Kolekcjoner minerałów",
|
||||||
|
"Komputer",
|
||||||
|
"Kontynuuj wyprawę",
|
||||||
|
"Kontynuuj wyprawę [E]",
|
||||||
|
"Korytarz rozszerza się w chłodną grotę. Na wapiennych ścianach widać kolejne skupiska nieznanych form życia.",
|
||||||
|
"Korzenie rozsunęły kamienie przy wejściu. Za progiem spoczywa porzucone urządzenie, pokryte pyłem minionych wieków.",
|
||||||
|
"Koszt każdej technologii w tym rzędzie: %d próbek.",
|
||||||
|
"Koszt: %d próbek",
|
||||||
|
"Koszt: 10 kryształów × poziom przedmiotu. Gotowe maksima nie pobierają opłaty.",
|
||||||
|
"Kredyty",
|
||||||
|
"Kredyty: %d",
|
||||||
|
"Kredyty: %d · części: %d\nWydatki pobierane są od razu. Nowe nagrody zachowasz po bezpiecznym powrocie.",
|
||||||
|
"Kryształy czasu",
|
||||||
|
"Kryształy czasu: %d",
|
||||||
|
"Kup 1 rakietę za %d kredytów.",
|
||||||
|
"Kup 10 pocisków radiacyjnych za %d kredytów.",
|
||||||
|
"Kup 100 zwykłych pocisków za %d kredytów.",
|
||||||
|
"Kup amunicję do działka maszynowego.",
|
||||||
|
"Kup kontener · zawartość nieznana",
|
||||||
|
"Kup zestaw surowców",
|
||||||
|
"LEĆ",
|
||||||
|
"LEĆ DO UKŁADU",
|
||||||
|
"Laser",
|
||||||
|
"Laser pulsacyjny",
|
||||||
|
"Laser radiacyjny",
|
||||||
|
"Laser wiązkowy",
|
||||||
|
"Losowanie zakresu obrażeń broni (poziom 1)",
|
||||||
|
"Losuje przedmiot i addony dla poziomu aktualnego układu.",
|
||||||
|
"Lot: poziom × 1000 deuteru. Powrót bezpłatny. Mapa zużywa się przy wylocie. Każdy sektor można odwiedzić tylko raz.",
|
||||||
|
"LĄDOWNIK ZNISZCZONY · Utracono łup bieżącej wyprawy.",
|
||||||
|
"LĄDOWNIK ZNISZCZONY — utracono łup wyprawy",
|
||||||
|
"Lądownik %d / 100 HP · Energia %d%%",
|
||||||
|
"Lądownik wymaga naprawy do 100% we frachtowcu.",
|
||||||
|
"Lądownik · %d%%",
|
||||||
|
"MAGAZYN / ZASOBY I WYPOSAŻENIE",
|
||||||
|
"MAKSYMALIZUJ · %d KRYSZTAŁÓW",
|
||||||
|
"MODUŁY / Kliknij ikonę, aby przenieść przedmiot",
|
||||||
|
"MODUŁY STATKU",
|
||||||
|
"MYŚLIWIEC • SZYBKOŚĆ",
|
||||||
|
"Ma 50%% szans na przejęcie uciekającego wroga (poniżej 10%% kadłuba). Jedna próba na statek; losowanie następuje, gdy jest wolne miejsce na przejęcie. Zamiast uciekać atakują swoich dawnych sojuszników. Bossowie są odporni na wirusa. Wrogowie atakują zawirusowane statki, gdy gracza nie ma w pobliżu. Nadal możesz uszkodzić i zniszczyć je własną bronią. Limit jednocześnie kontrolowanych: %d.",
|
||||||
|
"Magazyn jest pełny — zwolnij miejsce.",
|
||||||
|
"Magazyn pełny — zwolnij miejsce.",
|
||||||
|
"Malejące korzyści: 37,5% × punkty / (punkty + 10). Maksymalnie 25% uniku przy 20 punktach. Unik anuluje całe trafienie.",
|
||||||
|
"Malejące korzyści: 50% × punkty / (punkty + 10). Maksymalnie 33,3% redukcji przy 20 punktach, przed tarczami i kadłubem.",
|
||||||
|
"Manewr wyprzedzający",
|
||||||
|
"Mapa odległych systemów · poz. %d",
|
||||||
|
"Mapa z tej wizyty została kupiona. Wróć po kolejnym lądowaniu po nową ofertę.",
|
||||||
|
"Mapa została już kupiona lub brakuje kredytów.",
|
||||||
|
"Mapa: %d kredytów\nPaliwo na lot: %d deuteru\nPosiadasz: %d kredytów",
|
||||||
|
"Miedź",
|
||||||
|
"Miejsce na przyszłe badanie.",
|
||||||
|
"Między pustymi domami zarosła dawna ścieżka. W pozostawionych schowkach mogą jeszcze leżeć drobne oszczędności.",
|
||||||
|
"Mnożnik krytyka",
|
||||||
|
"Moduł",
|
||||||
|
"Mokradła",
|
||||||
|
"Może później",
|
||||||
|
"Możesz wybrać tylko jedną ofertę.",
|
||||||
|
"NAJEDŹ NA IKONĘ, ABY ZOBACZYĆ KOSZT",
|
||||||
|
"NAWIGACJA / ODKRYTE UKŁADY",
|
||||||
|
"NAWIGACJA / PLACÓWKI",
|
||||||
|
"NAŁÓŻ ORB",
|
||||||
|
"NIEPOWODZENIE · utrata %d HP. Wcześniejszy łup pozostaje w ładowni.",
|
||||||
|
"NIEZNANY UKŁAD. TWOJA WYPRAWA.",
|
||||||
|
"NISKI KADŁUB — %d%%",
|
||||||
|
"NOWA UMIEJĘTNOŚĆ",
|
||||||
|
"Na skraju polany stoi warsztat na szerokich gąsienicach. Mechanik odbiera sygnał z twojego lądownika i po chwili przesyła listę uszkodzeń. Ma części wystarczające na jedną szybką naprawę. Podaje cenę oraz dokładny zakres prac, po czym uruchamia spawarkę i czeka na odpowiedź.",
|
||||||
|
"Na stole ocalały dzienniki mieszkańców. Ich notatki mogą nauczyć cię, jak przetrwać na tej planecie.",
|
||||||
|
"Nad małym obozem zbiera się burza, a jego transport ewakuacyjny stoi z rozebranym silnikiem. Pierwsza grupa ludzi czeka już przy awaryjnym schronieniu. Dalej pozostali pracownicy zabezpieczający sprzęt i ranni, których trudniej przenieść. Koordynator może zapłacić za każdy ukończony etap pomocy, ale z każdą minutą warunki będą gorsze.",
|
||||||
|
"Najedź na nazwę przedmiotu, aby zobaczyć wszystkie addony i parametry.",
|
||||||
|
"Napraw do 100%% · koszt %d części. Pełny kadłub wymagany do lądowania.",
|
||||||
|
"Napraw lądownik: +%d HP",
|
||||||
|
"Naprawiają tyle kadłuba, ile pozwalają części i brakujące punkty. Koszt: 1 część za 1 punkt kadłuba. Nie zużywają energii.",
|
||||||
|
"Naprawiono lądownik: +%d HP.",
|
||||||
|
"Naprowadzana rakieta z małym uderzeniem. Zostawia płonący gaz na 5 s w promieniu 95 px: 110% obrażeń uderzenia na sekundę, kinetyczne. Nakładające się chmury nie sumują obrażeń.",
|
||||||
|
"Natychmiast naprawia %d%% maksymalnego kadłuba za 1 część. Wymaga uszkodzonego statku i aktywnego lotu.",
|
||||||
|
"Nie masz jeszcze umiejętności. To początek Twojej specjalizacji.",
|
||||||
|
"Nie można zbudować placówki. Sprawdź liczbę części.",
|
||||||
|
"Nie udało się otworzyć menu: %s",
|
||||||
|
"Nie udało się przenieść do układu: %s",
|
||||||
|
"Nie udało się zapisać gry.",
|
||||||
|
"Nie udało się zapisać ustawień.",
|
||||||
|
"Nieznany kosmos. Niepowtarzalny łup.",
|
||||||
|
"Niweluje obrażenia tego typu przed tarczą i pancerzem. Łączny limit statku: 60%.",
|
||||||
|
"Normal",
|
||||||
|
"Nowe badania w laboratorium trwają o %d%% krócej. Premie rang nie sumują się.",
|
||||||
|
"Nowe układy odblokujesz, przechodząc dalej przez tunel po pokonaniu przeciwników.",
|
||||||
|
"Nowy poziom",
|
||||||
|
"O %d%% więcej kredytów za pokonanych wrogów. Premia obejmuje kredyty do zebrania po walce. Premie rang nie sumują się.",
|
||||||
|
"OBÓZ SPECJALISTY / REKRUTACJA",
|
||||||
|
"ODCZYT PARAMETRÓW",
|
||||||
|
"ODCZYT: części zamienne. Ilość nieznana.",
|
||||||
|
"ODCZYT: podzespół statku. Poziomu i parametrów nie udało się ustalić.",
|
||||||
|
"ODCZYT: próbki mineralne. Dokładny skład i ilość nieznane.",
|
||||||
|
"ODKRYTE · DOSTĘPNE W ŁUPACH",
|
||||||
|
"ODLEGŁY SEKTOR",
|
||||||
|
"ODŁÓŻ DO PLECAKA",
|
||||||
|
"ODŁÓŻ →",
|
||||||
|
"OSTATNI UKŁAD",
|
||||||
|
"OSŁONA %.0f / %.0f",
|
||||||
|
"OTWÓRZ WORMHOLE",
|
||||||
|
"Obcy trafiający twoją aktywną tarczę otrzymuje wyładowanie równe 20% obrażeń faktycznie pochłoniętych przez osłonę. Bez kolejnych efektów trafienia.",
|
||||||
|
"Obok niewielkiej instalacji wydobywczej stoi łazik załadowany po same osie. Jego operator od tygodni wydobywa ten sam minerał, ale zabrakło mu materiałów do naprawy urządzeń. Proponuje wymianę części swojego zapasu na surowce z twojej ładowni. Przesyła dokładny wykaz towarów.",
|
||||||
|
"Obrażenia",
|
||||||
|
"Obrażenia broni",
|
||||||
|
"Obrażenia dronów bojowych większe o %d%%. Premie rang nie sumują się.",
|
||||||
|
"Obrażenia kadłubów obcych",
|
||||||
|
"Obrażenia krytyczne",
|
||||||
|
"Obrażenia tarcz obcych",
|
||||||
|
"Obrażenia trafienia",
|
||||||
|
"Obrażenia z addonów",
|
||||||
|
"Obrażenia: %s",
|
||||||
|
"Obóz specjalisty",
|
||||||
|
"Odbierz do ładowni statku. Przedmioty bez miejsca pozostają na fregacie.",
|
||||||
|
"Odblokuj 1 slot ładowni w hangarze: 100 żelaza + 50 aluminium.",
|
||||||
|
"Odległy sektor %03d",
|
||||||
|
"Odstęp między strzałami",
|
||||||
|
"Odstęp rozstawiania",
|
||||||
|
"Odstęp strzałów działka",
|
||||||
|
"Odstęp strzałów działka: %.2f s • Kolejne rozstawienie: %.2f s",
|
||||||
|
"Odstęp strzałów: %.2f s",
|
||||||
|
"Odwrócona polaryzacja",
|
||||||
|
"Odzysk tarcz z obrażeń",
|
||||||
|
"Odzyskane moduły · %d",
|
||||||
|
"Odłóż wszystko →",
|
||||||
|
"Odłóż wyposażenie kapitana",
|
||||||
|
"Ogólna wiedza",
|
||||||
|
"Opady śniegu",
|
||||||
|
"Orb elektryczności",
|
||||||
|
"Orb silników atomowych",
|
||||||
|
"Osiągnięto limit.",
|
||||||
|
"Ostatni zapis: %s\nUkład: %d · Kapitan: %d",
|
||||||
|
"Ostatnie zapasy ukryto pod zawaloną częścią budynku. Belki skrzypią przy każdym kroku.",
|
||||||
|
"Oszczędny laser wiązkowy: małe obrażenia i zasięg około jednego ekranu. Koszt impulsu rośnie z obrażeniami i addonami egzemplarza.",
|
||||||
|
"Oszczędny magazynek",
|
||||||
|
"Osłabienie broni obcych",
|
||||||
|
"Otwórz przeskanowaną skrytkę",
|
||||||
|
"Otwórz statek i sloty wyposażenia",
|
||||||
|
"PANCERZ",
|
||||||
|
"PANCERZ REAKTYWNY",
|
||||||
|
"POKÓJ 01",
|
||||||
|
"POKÓJ 02",
|
||||||
|
"POKÓJ 03",
|
||||||
|
"POKÓJ 04",
|
||||||
|
"POKÓJ 05",
|
||||||
|
"POSIADANE UMIEJĘTNOŚCI",
|
||||||
|
"POWRÓT NA STATEK [L]",
|
||||||
|
"POWRÓT Z WYPRAWY",
|
||||||
|
"POWRÓT Z WYPRAWY · ",
|
||||||
|
"POZIOM %d",
|
||||||
|
"POZIOM %s / III · %s",
|
||||||
|
"PROJEKTY BRONI I ROZSZERZEŃ",
|
||||||
|
"PRZEJDŹ DO HARD",
|
||||||
|
"PRÓBKI / %d",
|
||||||
|
"PRĘDKOŚĆ: %.0f",
|
||||||
|
"Pancerz",
|
||||||
|
"Pancerz reaktywny",
|
||||||
|
"Pancerz z tytanu",
|
||||||
|
"Parametry statku, uzbrojenie, pancerz i systemy",
|
||||||
|
"Pasywne rozszerzenie statku. Działa po zamontowaniu. Przy niskim kadłubie pochłania 50% otrzymywanych obrażeń.",
|
||||||
|
"Pasywne rozszerzenie statku. Działa po zamontowaniu. Uciekający wrogowie przechodzą pod kontrolę wirusa i atakują inne wrogie statki.",
|
||||||
|
"Pasywne rozszerzenie statku. Działa po zamontowaniu. Zebrany odłamek asteroidy przywraca tarcze i energię.",
|
||||||
|
"Pasywny moduł prędkości. Na poziomie 1 bonus wynosi 1–5 px/s i rośnie wraz z poziomem przedmiotu.",
|
||||||
|
"Pewna wypłata albo ryzyko",
|
||||||
|
"Pełne zachmurzenie",
|
||||||
|
"Pełny ekran",
|
||||||
|
"Pierwsze trafienie sięgające kadłuba po utracie tarcz zadaje kadłubowi o 70% mniej obrażeń. Odnowienie: 15 s aktywnego lotu.",
|
||||||
|
"Pierwsze trafienie w aktywną tarczę zadaje tylko 10% obrażeń. Odnowienie: 60 s. Redukcja obejmuje też przebicie tego trafienia na kadłub.",
|
||||||
|
"Pierwszy cel: pokonaj wrogów → pokonaj bossa → znajdź zamieszkaną planetę.",
|
||||||
|
"Pilotaż",
|
||||||
|
"Placówka gotowa. Przydziel operatora w centrum dowodzenia.",
|
||||||
|
"Placówka górnicza",
|
||||||
|
"Placówka zbudowana · %.1f deuteru/min",
|
||||||
|
"Placówka: ",
|
||||||
|
"Po uszkodzeniu kadłuba pocisk lub laser przebija jeden dodatkowy cel za 50% obrażeń. Rakieta wypuszcza dodatkowy pocisk penetrujący bez kolejnej eksplozji. Bez łańcuchowych przestrzałów i dodatkowego kosztu strzału.",
|
||||||
|
"Po zbiciu tarcz natychmiast odzyskujesz 25% ich maksimum. Przez 2 s obrażenia kierowane w tarczę są zmniejszone o 50%. Odnowienie: 30 s. Nie sumuje redukcji z Rozproszeniem salwy; działa silniejsza. Dokowanie nie resetuje odnowienia.",
|
||||||
|
"Pochłania 50%% otrzymywanych obrażeń, gdy kadłub ma nie więcej niż %d%% maksimum. Próg sprawdzany przed trafieniem.",
|
||||||
|
"Pociski do działka maszynowego. Obrażenia kinetyczne.",
|
||||||
|
"Pociski, rakiety i lasery obcych mogą trafiać także innych wrogich obcych. Trafienie własnego statku strzelca jest wykluczone.",
|
||||||
|
"Pod cienką warstwą gruntu żyła schodzi głębiej. Odwiert odsłoni bogatszy pokład, jeśli skała pozostanie stabilna.",
|
||||||
|
"Pod zapadniętą podłogą kryje się sejf osady. Dotarcie do niego wymaga wejścia pod niestabilne stropy.",
|
||||||
|
"Pokonaj wszystkich wrogów",
|
||||||
|
"Pokój załogi z łóżkiem, biurkiem i miejscem na rzeczy osobiste.",
|
||||||
|
"Pomieszczenie jest wyposażone. Jego mechanika zostanie dodana w kolejnym etapie.",
|
||||||
|
"Powerbank przywraca %d%% maksymalnej energii zamiast 10%%. Umiejętność pasywna; premie rang nie sumują się.",
|
||||||
|
"Poziom %d",
|
||||||
|
"Pozostałe wybory po tym awansie: %d",
|
||||||
|
"Pozostało",
|
||||||
|
"Pozostało: %d s gry",
|
||||||
|
"Premia biomu: materiały ×%.1f · moduły +%d…+%d poz.\nLiczba amunicji i rakiet nie wzrasta.",
|
||||||
|
"Premia do doświadczenia",
|
||||||
|
"Premia do kredytów",
|
||||||
|
"Premia do obrażeń",
|
||||||
|
"Premia ze sprzętu: do +100%. Umiejętności kapitana działają osobno.",
|
||||||
|
"Produkcja zwykłej i radiacyjnej amunicji daje o %d%% więcej sztuk za ten sam koszt. Nie dotyczy rakiet. Premie rang nie sumują się.",
|
||||||
|
"Przeciągnij, aby przesunąć okno",
|
||||||
|
"Przeciążenie osłon",
|
||||||
|
"Przeciążenie reaktora",
|
||||||
|
"Przejaśnienia",
|
||||||
|
"Przeniesiono %d przedmiotów.",
|
||||||
|
"Przenieś rannych",
|
||||||
|
"Przestrzał",
|
||||||
|
"Przez 10 s statek staje się niemal niewidoczny. Przeciwnicy nie wykrywają go ani nie śledzą. Oddanie strzału przerywa kamuflaż. Nie zapewnia odporności na już wystrzelone pociski. Odnowienie: 60 s.",
|
||||||
|
"Przy zakurzonym transporterze miga przenośny nadajnik. Właściciel przedstawia się jako niezależny dostawca, choć oznaczenia na skrzyniach należą do kilku różnych firm. Twierdzi, że kończy interesy na tej planecie i woli sprzedać zapasy taniej, niż zabierać je z powrotem na orbitę.",
|
||||||
|
"Przydziel załoganta w centrum dowodzenia fregaty. Deuter trafia automatycznie do magazynu, również gdy jesteś poza tą planetą.",
|
||||||
|
"Przygotowana dla jednego załoganta. Specjalistów możesz zatrudniać na planetach.",
|
||||||
|
"Przypisz umiejętność do slotu F1–F5 w panelu kapitana",
|
||||||
|
"Przywraca 100 punktów tarcz, do ich maksimum. Wymaga i zużywa 100% energii.",
|
||||||
|
"Przywracają 10% maksymalnej energii. Użyj klawiszem R.",
|
||||||
|
"Próbki",
|
||||||
|
"Próbki do analizy",
|
||||||
|
"Prędkość",
|
||||||
|
"Prędkość aktualna",
|
||||||
|
"Prędkość lecącej wiązki: %.0f px/s",
|
||||||
|
"Prędkość maksymalna",
|
||||||
|
"Prędkość obrotu",
|
||||||
|
"Prędkość statku",
|
||||||
|
"Pusty slot\nMiejsce na przyszłe badanie.",
|
||||||
|
"Pęknięcie poszycia",
|
||||||
|
"Płatny skan skrytki",
|
||||||
|
"RAKIETY",
|
||||||
|
"RANDOLOOT / EKSPLORUJ • WALCZ • ROZWIJAJ STATEK",
|
||||||
|
"REAKTOR",
|
||||||
|
"RESET SKILLI — 100 KREDYTÓW",
|
||||||
|
"REZERWA KONDENSATORÓW",
|
||||||
|
"Radiacyjna kula. Napromieniowanie: 10 s, 25% obrażeń trafienia/s. Kolejne trafienia odświeżają czas. Zużywa napromieniowaną amunicję.",
|
||||||
|
"Rakieta",
|
||||||
|
"Rakiety",
|
||||||
|
"Reaktor",
|
||||||
|
"Redukcja obrażeń",
|
||||||
|
"Regały, pojemniki i stanowiska do przechowywania modułów.",
|
||||||
|
"Regeneracja energii +%d%% przez 7 sekund. Zużywa wszystkie tarcze i blokuje ich odzysk na czas działania. Wymaga min. 25%% tarcz.",
|
||||||
|
"Rekrutacja: %d kredytów · posiadasz: %d",
|
||||||
|
"Rezerwa kondensatorów",
|
||||||
|
"Rozbity przekaźnik",
|
||||||
|
"Rozdzielczość",
|
||||||
|
"Rozłóż przedmiot: +10 części",
|
||||||
|
"Rtęć",
|
||||||
|
"SIEĆ WYDOBYWCZA",
|
||||||
|
"SILNIK",
|
||||||
|
"SKŁAD MODUŁÓW W REMONCIE",
|
||||||
|
"SPACJA — pomiń intro",
|
||||||
|
"SPRZĘT KAPITANA · %d szt. ODZYSKANE MODUŁY · %d",
|
||||||
|
"SPRÓBUJ PONOWNIE [R]",
|
||||||
|
"STATEK GRACZA",
|
||||||
|
"STATEK ZABEZPIECZONY",
|
||||||
|
"STATEK ZNISZCZONY",
|
||||||
|
"STATEK · %d / %d",
|
||||||
|
"STATEK · PASYWNE",
|
||||||
|
"STAŁY EFEKT",
|
||||||
|
"SYSTEMY I MODUŁY",
|
||||||
|
"SYSTEMY POKŁADOWE",
|
||||||
|
"Sektory poza znanymi szlakami. Podwójna liczba wrogów, jeden boss. Kryształy czasu z każdego wroga. Zwykli wrogowie: mapy i powerbanki po 15%. Boss zawsze zostawia 1 mapę i 1 losowy orb, a dodatkowo ma 5% szansy na Orb replikacji.",
|
||||||
|
"Silnik",
|
||||||
|
"Skaliste wyżyny",
|
||||||
|
"Skan ujawni rodzaj zawartości, ale nie jej ilość ani stan. Otwarcie wymaga osobnej opłaty.",
|
||||||
|
"Skan zakończony. Możesz opłacić otwarcie lub wrócić później.",
|
||||||
|
"Skrócenie cooldownu rakiet",
|
||||||
|
"Spadek kadłuba z co najmniej 30% poniżej tego progu uruchamia naprawę 15% maksymalnego kadłuba przez 5 s. Odnowienie: 45 s. Trafienia nie przerywają naprawy.",
|
||||||
|
"Spadek tarcz z co najmniej 30% poniżej tego progu zmniejsza koszt energii broni o 50% przez 2 s. Odnowienie: 15 s.",
|
||||||
|
"Specjalista z obozu szuka pracy. Obejrzyj umiejętności i zdecyduj — możesz wrócić później. Koszt zatrudnienia: 1000 kredytów × zarządzanie.",
|
||||||
|
"Specjalista został już zatrudniony.",
|
||||||
|
"Spotkanie zakończone. Nagrody w ładowni wyprawy przepadną po zniszczeniu lądownika.",
|
||||||
|
"Sprzedaj próbki",
|
||||||
|
"Sprzęt: do +100% mnożnika bazowego, maksymalnie ×4.",
|
||||||
|
"Sprzęt: do 15% pojemności generatora/s. Ładowanie przy gwieździe i czasowe umiejętności dodają osobne premie.",
|
||||||
|
"Sprzęt: do 40%. Łącznie z umiejętnościami: do 60%.",
|
||||||
|
"Stanowiska analityczne, aparatura i stół do doświadczeń.",
|
||||||
|
"Starożytna struktura",
|
||||||
|
"Start",
|
||||||
|
"Statek i kapitan",
|
||||||
|
"Statek jest zniszczony",
|
||||||
|
"Statek niedostępny",
|
||||||
|
"Strzał w 10",
|
||||||
|
"Sukces: %.2f%% · w razie porażki: −%d–%d HP\nSzansa uwzględnia warunki planety i sprzęt kapitana.",
|
||||||
|
"Sygnał prowadzi do samotnego badacza pochylonego nad analizatorem próbek. Na widok twojego spisu ładunku nagle przerywa rozmowę. Jednego z przewożonych przez ciebie surowców potrzebuje do ukończenia badań. Ma środki z kończącego się grantu i jest gotów zapłacić więcej niż zwykły skup.",
|
||||||
|
"Szansa szczęścia",
|
||||||
|
"Szansa uniku wynosi %d%% przez 5 sekund. Unik anuluje całe trafienie.",
|
||||||
|
"Szczęście",
|
||||||
|
"Szczęście (limit 60%)",
|
||||||
|
"Szczęście: %d%% szans na przedmiot o 1 poziom wyższy niż bazowy loot planszy. Dotyczy lootu z wrogów i znalezisk. Bazowo: 0%%. Sumuje się ze sprzętem do limitu 60%%. Premie rang nie sumują się.",
|
||||||
|
"Szerszeń",
|
||||||
|
"Szybko rozpędza do 300% zwykłej prędkości (+200%), następnie wytraca nadmiar prędkości. Bez kosztu energii.",
|
||||||
|
"Szybko rozpędza do 300% zwykłej prędkości (+200%), następnie wytraca nadmiar prędkości. Wymaga i zużywa 100% energii.",
|
||||||
|
"Szybkostrzelność",
|
||||||
|
"Słaby punkt",
|
||||||
|
"Słaby sygnał alarmowy dobiega z przewróconego łazika. Jego kierowca żyje, lecz nie może wydostać się z kabiny. Do uniesienia wraku potrzebny jest prowizoryczny podnośnik zbudowany z twoich części. Czujniki ostrzegają, że uszkodzona bateria pojazdu jest niestabilna. Uwięziony obiecuje zapłatę, jeśli pomożesz mu wrócić do obozu.",
|
||||||
|
"Ta decyzja jest niedostępna.",
|
||||||
|
"Tajemniczy łup: 50% części, 35% minerały, 10% rakiety, 5% moduł. Wartość może być niższa od opłaty.",
|
||||||
|
"Tarcza zewnętrzna",
|
||||||
|
"Tarcze są pełne",
|
||||||
|
"Tarcze wyłączone przez Przekierowanie zasilania",
|
||||||
|
"Teleportuje w losowe, bezpieczne miejsce systemu. Zużywa całą aktualną energię (wymaga dodatniej energii). Odnowienie: 60 s.",
|
||||||
|
"Ten addon ma już maksymalną wartość lub nie posiada zakresu losowania.",
|
||||||
|
"Ten etap ma 0% szans. Obniż zagrożenie odpowiednim wyposażeniem.",
|
||||||
|
"Teoretyczny DPS: uwzględnia krytyki i promieniowanie; przed obroną celu, przy dostępnej energii i amunicji.",
|
||||||
|
"To miejsce zostało już odwiedzone.",
|
||||||
|
"To spotkanie jest już niedostępne.",
|
||||||
|
"Trafienie dowolną bronią razi też obcych do 10 px od obrysu trafionego statku. Promień eksplozji twoich rakiet rośnie o 10 px. Bez łańcuchowych rykoszetów.",
|
||||||
|
"Trafienie tarczy obcego blokuje regenerację na 5 s. Kolejne trafienia odświeżają czas.",
|
||||||
|
"Trwa wyprawa do sektora %d. Użyj przycisku POWRÓT Z WYPRAWY na pokładzie, aby wrócić do układu startowego przed kolejnym lotem.",
|
||||||
|
"Trwale zmienia typ obrażeń broni na energetyczny (jak laser). Nie zwiększa obrażeń ani kosztu strzału. Zastępuje poprzedni orb typu obrażeń.",
|
||||||
|
"Trwale zmienia typ obrażeń broni na kinetyczny. Nie zwiększa obrażeń ani kosztu strzału. Zastępuje poprzedni orb typu obrażeń.",
|
||||||
|
"Trwale zmienia typ obrażeń broni na radiacyjny. Nie zwiększa obrażeń ani kosztu strzału. Zastępuje poprzedni orb typu obrażeń.",
|
||||||
|
"Twoja broń zadaje dodatkowe 5% obrażeń kadłubom obcych. Sumuje się z Wiedzą o kadłubie.",
|
||||||
|
"Twoja broń zadaje o 10% więcej obrażeń kadłubom obcych.",
|
||||||
|
"Twoja broń zadaje o 10% więcej obrażeń tarczom obcych.",
|
||||||
|
"Tworzy dokładną, niezależną kopię wyposażenia w magazynie frachtowca. Oryginał zostaje. Kopiuje poziom, addony i efekty orbów. Drop: dodatkowe 5% z bossa dalekiej wyprawy.",
|
||||||
|
"Tylko silnik. Trwale zmniejsza zużycie energii dopalacza TAB o 50%. Nie sumuje się. Orb darmowego dopalacza ma pierwszeństwo.",
|
||||||
|
"Tylko tarcze. Trafienie w tarcze odnawia do 5% maksymalnych tarcz jako energię, nie więcej niż faktycznie stracone tarcze. Tempo odzysku: do 5% pojemności generatora/s, z rezerwą na jedno takie odnowienie. Uniki i trafienia w sam kadłub nie aktywują efektu.",
|
||||||
|
"Typ obrażeń: %s",
|
||||||
|
"Tytan",
|
||||||
|
"U podnóża góry otwiera się ciemna szczelina. Przy wilgotnych skałach rosną organizmy warte dokładniejszej analizy.",
|
||||||
|
"UMIEJĘTNOŚCI KAPITANA",
|
||||||
|
"USŁUGI TUBYLCÓW",
|
||||||
|
"Ujawnia paski HP i tarcz wrogów.",
|
||||||
|
"Układ %d\nWyposażenie i zapasy zostają zachowane.",
|
||||||
|
"Układ bezpieczny. Usługi dostępne.",
|
||||||
|
"Umiejętności kapitana",
|
||||||
|
"Umiejętności kapitana · punkty do wydania: %d",
|
||||||
|
"Umiejętność nie jest odblokowana",
|
||||||
|
"Uran",
|
||||||
|
"Uwzględnia mechanika i aktywny efekt pancerza z tytanu.",
|
||||||
|
"W ruinach starego magazynu ktoś odnalazł pancerną skrytkę. Stojąca obok operatorka ma skaner zdolny zajrzeć przez jej osłonę, lecz urządzenie zużywa drogie ogniwa. Za niewielką opłatą sprawdzi, co może znajdować się w środku. Otwarcie zamka będzie kosztować osobno. Uprzedza, że skorodowana obudowa zakłóca odczyt.",
|
||||||
|
"W sercu budowli ocalał niezwykły mechanizm. Aby go wydobyć, trzeba poruszyć konstrukcję, która od dawna nie powinna stać.",
|
||||||
|
"W zaciszu chaty pustelnik przechowuje współrzędne miejsc poza znanymi szlakami. Oferuje ci jedną ze swoich map.",
|
||||||
|
"W zasięgu gwiazdy przywraca 20% maksymalnych tarcz na sekundę przez maksymalnie 5 s. Opuszczenie zasięgu kończy efekt. Odnowienie: 30 s.",
|
||||||
|
"W — ciąg · S — hamuj / wstecz · A/D — obrót\nQ/R — ruch boczny · TAB — dopalanie · E — odwiedź POI",
|
||||||
|
"WORMHOLE\nWleć, aby przejść do następnego układu",
|
||||||
|
"WORMHOLE — następny układ",
|
||||||
|
"WRÓĆ DO LOTU",
|
||||||
|
"WRÓĆ DO UKŁADU %d [R]",
|
||||||
|
"WYJŚCIE",
|
||||||
|
"WYTWÓRZ",
|
||||||
|
"Wczytaj ostatnią wyprawę",
|
||||||
|
"Weź gwarantowany zestaw",
|
||||||
|
"Wiatr przesuwa kurz po podłodze pustego magazynu. Kilka skrzyń wciąż ma nienaruszone zamknięcia.",
|
||||||
|
"Wiedza o kadłubie",
|
||||||
|
"Wleć w wormhole, aby przejść dalej.",
|
||||||
|
"Wrogie pociski i lasery mają 25% szansy na dodatkowy szeroki rozrzut celowania.",
|
||||||
|
"Wróć do gry",
|
||||||
|
"Wróć do wyprawy",
|
||||||
|
"Wróć na pokład",
|
||||||
|
"Wszystkie dostępne projekty zostały wynalezione.",
|
||||||
|
"Wybierz aktywną umiejętność dla F%d. Pasywne działają bez zajmowania slotu.",
|
||||||
|
"Wybierz jednostkę i rozpocznij wyprawę.",
|
||||||
|
"Wybierz jedną umiejętność. Wybór obowiązuje przez całą rozgrywkę.",
|
||||||
|
"Wybierz moduł lub broń\nPPM / Esc — anuluj",
|
||||||
|
"Wybierz pomieszczenie na pokładzie.",
|
||||||
|
"Wybierz pomieszczenie na pokładzie. · Warsztat i hangar są dostępne.",
|
||||||
|
"Wybierz projekt. Nowe badanie trwa %d sekund gry. Odkryta broń lub rozszerzenie zacznie pojawiać się w łupach. Od początku dostępne jest działko plazmowe.",
|
||||||
|
"Wybierz przedmiot i konkretny addon. Inżynier ustawi tylko jego wartość na maksimum dla obecnego poziomu przedmiotu.",
|
||||||
|
"Wybierz statek i ruszaj w nieznane",
|
||||||
|
"Wybierz umiejętność · oczekujące awanse: %d",
|
||||||
|
"Wybrany addon ma teraz maksymalną wartość dla obecnego poziomu przedmiotu.",
|
||||||
|
"Wydobycie = zasobność × (1 + zarządzanie / 100). Bez załoganta: 0. Części: %d / %d",
|
||||||
|
"Wydobycie: zasobność × (1 + zarządzanie / 100) deuteru/min. Bez załoganta: 0. Złoża nie wyczerpują się.",
|
||||||
|
"Wydobywany z asteroid. Składnik receptur warsztatu.",
|
||||||
|
"Wyjście",
|
||||||
|
"Wymagana 1 część",
|
||||||
|
"Wymagana dodatnia maksymalna pojemność tarcz",
|
||||||
|
"Wymagana pełna energia",
|
||||||
|
"Wymagana zamontowana broń",
|
||||||
|
"Wymagane 50 szt. zwykłej amunicji",
|
||||||
|
"Wymagany zasięg gwiazdy",
|
||||||
|
"Wymiana towarów",
|
||||||
|
"Wymień surowce",
|
||||||
|
"Wymień surowce na 3 rakiety",
|
||||||
|
"Wyprawa zakończona. Mapa została zużyta.\nPowrót do układu %d.\nWyposażenie i zapasy zostają zachowane.",
|
||||||
|
"Wypuszcza 3 drony na 10 s. Strzelają działkami mechanicznymi; łącznie zadają 50% DPS statku w momencie startu. Koszt: 50 szt. zwykłej amunicji. Odnowienie: 30 s.",
|
||||||
|
"Wypuszcza trzy flary na 10 s. Wrogowie w zasięgu obierają je za cel zamiast gracza. Odnowienie: 30 s.",
|
||||||
|
"Wyrzutnia rakiet zapalających",
|
||||||
|
"Wystrzeliwuje naprowadzaną rakietę z eksplozją obszarową. Cooldown: 5 s.",
|
||||||
|
"Wystrzeliwuje pojedyncze krótkie czerwone wiązki, które szybko lecą przez przestrzeń. Każdy impuls ma 50% szansy całkowicie ominąć tarcze i trafić w kadłub. Zadaje o 30% mniej obrażeń niż laser wiązkowy z takimi samymi parametrami i zużywa o 30% więcej energii.",
|
||||||
|
"Wystrzeliwuje rakietę prosto w kierunku celownika. Większe obrażenia i eksplozja obszarowa. Zużywa amunicję rakietową.",
|
||||||
|
"Wytwarzane z minerałów, odzyskiwane z przedmiotów i wraków. Do napraw.",
|
||||||
|
"Wąska szczelina prowadzi do najbogatszej części złoża. Każde uderzenie narzędzia odbija się głuchym echem.",
|
||||||
|
"Wędrowiec",
|
||||||
|
"Wędrowny handlarz",
|
||||||
|
"Wśród zwietrzałych skał połyskują drobiny rzadkich minerałów. Wystarczy ostrożnie oddzielić je od podłoża.",
|
||||||
|
"Z załogantem: %.1f–%.1f deuteru/min (zarządzanie 1–100).",
|
||||||
|
"ZATRUDNIJ · %d KREDYTÓW",
|
||||||
|
"ZBUDUJ PLACÓWKĘ · %d CZĘŚCI",
|
||||||
|
"ZBUDUJ SEKCJĘ",
|
||||||
|
"ZBUDUJ SKŁAD",
|
||||||
|
"ZUŻYTY",
|
||||||
|
"ZUŻYWALNY",
|
||||||
|
"ZWOLNIJ ZAŁOGANTA",
|
||||||
|
"ZWYKŁE %02d",
|
||||||
|
"Za stalową kratą zachowały się regały z wojskowym zaopatrzeniem. Rdza utrudnia dostęp do ciężkich pojemników.",
|
||||||
|
"Zadokuj statkiem, aby rozbudować sloty.",
|
||||||
|
"Zagrożenie %.1f%% / 300%% · Łup POI ×%.2f",
|
||||||
|
"Zagrożenie po sprzęcie: %.1f%% / 300%% (bez sprzętu %.1f%%).",
|
||||||
|
"Zajęte miejsca",
|
||||||
|
"Zakończ grę",
|
||||||
|
"Zakończ pomoc i zachowaj dotychczasową zapłatę",
|
||||||
|
"Zakończ wyprawę i wróć do układu startowego. Powrót jest bezpłatny.",
|
||||||
|
"Zakończono pomoc. Dotychczasowa zapłata pozostaje w ładowni wyprawy.",
|
||||||
|
"Zakres przed krytykiem i obroną przeciwnika.",
|
||||||
|
"Zakupy za kredyty tańsze o %d%%.",
|
||||||
|
"Zakłócenia systemów obcych",
|
||||||
|
"Zamieć śnieżna",
|
||||||
|
"Zapisano grę.",
|
||||||
|
"Zapisz grę",
|
||||||
|
"Zapisz i wróć do menu",
|
||||||
|
"Zapisz i wyjdź",
|
||||||
|
"Zarządca opuszczanego punktu przeładunkowego sprzedaje ostatnie zapasy. Za podaną kwotę możesz zabrać przygotowany zestaw części albo jeden z zaplombowanych pakietów odzyskanych z transportu. Otwarty zestaw jest skromny, ale sprawdzony. W zamkniętych pakietach zdarzały się wartościowe podzespoły — oraz materiały, których nikt nie chciał kupić.",
|
||||||
|
"Zarządzanie: %d / 100\nPremia do wydobycia: +%d%%\nPochodzenie: %s",
|
||||||
|
"Zasady łączenia",
|
||||||
|
"Zasięg",
|
||||||
|
"Zasięg działka: %.0f px • Magazynek: 50 pocisków • Koszt rozstawienia: 50 amunicji",
|
||||||
|
"Zasięg skanera",
|
||||||
|
"Zasięg: %.0f px • Amunicja: %d / strzał",
|
||||||
|
"Zasięg: %.0f px • Energia: %.1f / strzał",
|
||||||
|
"Zasięg: %.0f px • Napromieniowana amunicja: 1 / strzał",
|
||||||
|
"Zasobność: %d / 100",
|
||||||
|
"Zasobność: %d / 100 · złoże niewyczerpywalne",
|
||||||
|
"Zatrudnienie wymaga wolnej, zbudowanej kajuty i kredytów: 1000 × zarządzanie.",
|
||||||
|
"Załogant zajął wolną kajutę na fregacie. Przydziel go do stacji w centrum dowodzenia.",
|
||||||
|
"Zbicie tarczy obcego razi pozostałych obcych w promieniu 120 px za 400% obrażeń trafienia, które zbiło tarczę. Bez reakcji łańcuchowych. Ten sam wróg wywołuje impuls najwyżej raz na 10 s.",
|
||||||
|
"Zbieracz złomu",
|
||||||
|
"Zbierz łup i wróć do frachtowca",
|
||||||
|
"Zbuduj podnośnik i pomóż kierowcy",
|
||||||
|
"Zdobądź brakujące surowce z asteroid",
|
||||||
|
"Zielony laser pulsacyjny. Trafienie napromieniowuje: 100% obrażeń impulsu na sekundę przez 10 s. Kolejne impulsy odświeżają czas, działa najmocniejsze napromieniowanie.",
|
||||||
|
"Zleć skan skrytki",
|
||||||
|
"Znajdź zamieszkaną planetę",
|
||||||
|
"Znaleziono moduł",
|
||||||
|
"Znaleziska są w ładowni wyprawy. Zachowasz je po bezpiecznym powrocie na statek.",
|
||||||
|
"Zostawia minę na 60 s. Uzbraja się po 0,7 s. Trafiony wróg otrzymuje obrażenia równe 5% maksymalnego kadłuba (bez redukcji absorpcji) i zwalnia o 50% na 5 s. Zrzut co 5 s.",
|
||||||
|
"Zostawia minę na 60 s. Uzbraja się po 0,7 s. Wykrywa bliski przelot wroga. Wybuch w promieniu 140 jednostek zadaje każdemu wrogowi 50% aktualnego kadłuba bez redukcji absorpcji (tarcze pochłaniają obrażenia) i spowalnia o 50% na 5 s.",
|
||||||
|
"Zużycie amunicji mniejsze o %d%%. Obejmuje zwykłą i napromieniowaną amunicję, bez rakiet.",
|
||||||
|
"Zużywa 70% maksymalnej energii i tworzy osobną tarczę o pojemności 50% aktualnych maksymalnych tarcz statku. Większa, fioletowa osłona pochłania obrażenia przed zwykłymi tarczami. Działa do wyczerpania, nie regeneruje się i nie nakłada się na kolejną kopię. Dokowanie i Przekierowanie zasilania ją wyłączają.",
|
||||||
|
"Zwiększa maksymalne tarcze o 10%. Zakup nie uzupełnia osłon.",
|
||||||
|
"Zwiększa maksymalny kadłub twojego statku o 10%. Zakup nie odnawia utraconego kadłuba.",
|
||||||
|
"Zwiększa maksymalną pojemność energii.",
|
||||||
|
"Zwiększa maksymalną pojemność tarcz i stale je regeneruje.",
|
||||||
|
"Zwiększa maksymalną pojemność tarcz statku i stale je regeneruje.",
|
||||||
|
"Zwiększa maksymalną wytrzymałość kadłuba.",
|
||||||
|
"Zwiększa szansę na przedmiot o 1 poziom wyższy. Sumuje się z Farciarzem, do wspólnego limitu 60%.",
|
||||||
|
"Zwiększa tempo strzałów tej broni. Koszt pojedynczego strzału pozostaje bez zmian. Limit bonusu: 25%.",
|
||||||
|
"Zwiększa zasięg stałego skanera wykrywającego wrogów, asteroidy, wraki i antyczne znaleziska.",
|
||||||
|
"Zwykła",
|
||||||
|
"Zwykła amunicja",
|
||||||
|
"Zwykły",
|
||||||
|
"Zwykły lot: do 240 px/s. TAB: do 480 px/s. Aktywny dopalacz: do 600 px/s.",
|
||||||
|
"Złomiarz wyciągnął z wraku zamknięty kontener. Plomba wygląda na nienaruszoną, ale tabliczka ładunkowa została wypalona podczas wejścia w atmosferę. Sprzedawca nie zamierza tracić czasu na otwieranie zabezpieczeń. Podaje cenę za całość i zapewnia, że poprzedni kupujący trafił świetnie. O wcześniejszych klientach mówi już mniej chętnie.",
|
||||||
|
"Złoże surowców",
|
||||||
|
"[font_size=16][color=#f1bd79]Buduj własny styl gry[/color][/font_size]\n\n[color=#91dbea][b]Wyposażenie[/b][/color]\nKliknij panel statku w prawym górnym rogu i otwórz magazyn. Przeciągaj przedmioty do pasujących slotów: maksymalnie 3 bronie, 5 modułów i 5 rozszerzeń. Na początku dostępny jest 1 slot broni i 1 rozszerzenia. Pierwszy dodatkowy slot broni kosztuje 100 tytanu, drugi 500. Rozszerzenia kosztują po 40 żelaza, aluminium i tytanu, a każdy kolejny slot podwaja ten koszt (80, 160, 320). Ładownia zaczyna z 5 miejscami; każde kolejne miejsce kosztuje 100 żelaza i 50 aluminium. Sloty odblokowujesz w hangarze fregaty. Po zbudowaniu składu modułów zakładka Magazyn na frachtowcu pozwala odkładać i odbierać wyposażenie. Aktywne rozszerzenia uruchamiasz klawiszami 1–5; pasywne (oznaczone P) działają automatycznie w tych samych slotach. Najedź kursorem, żeby sprawdzić parametry i porównanie wyposażenia.\n\n[color=#91dbea][b]Nie każdy duplikat jest taki sam[/b][/color]\nBroń i moduły mogą mieć różne parametry oraz addony. Aktywne rozszerzenia losują cooldown od 30 do 5 pełnych sekund. Pasywne mają losowaną siłę efektu: Recykler odnawia tarcze i energię po zebraniu odłamka, Wirus przejmuje uciekających wrogów, a Pancerz z tytanu ogranicza obrażenia przy niskim kadłubie. Krótsze odnowienia są rzadkie — przed rozłożeniem porównaj egzemplarze. Rozszerzenia tego samego typu dzielą aktywne odnowienie.\n\n[color=#91dbea][b]Umiejętności kapitana[/b][/color]\nZa pokonanych wrogów zdobywasz doświadczenie i kredyty. Trudniejsze układy dają więcej bazowego XP. Jeśli kapitan przewyższa poziom układu o ponad 2 poziomy, XP za przeciwników i ruiny maleje; przy przewadze 8 poziomów spada do zera. Kredyty i surowce nadal zbierasz. Po awansie wybierasz umiejętność. Pasywne działają stale, aktywne przypisujesz do F1–F5.\n\n[color=#f1bd79][b]Okno umiejętności nie pauzuje gry.[/b][/color]\nOtwieraj je w bezpiecznym miejscu. Przed kolejnym układem uzupełnij zapasy i sprawdź wyposażenie.",
|
||||||
|
"[font_size=16][color=#f1bd79]Dźwięki otoczenia[/color][/font_size]\n\n[b]Blender Foundation — Ambient Bird, Cricket and Frog (Yo Frankie!)[/b]\nOdgłosy świerszcza i żaby, udostępnione przez Lamoot:\nhttps://opengameart.org/content/ambient-bird-cricket-and-frog\nLicencja Creative Commons Attribution 3.0:\nhttps://creativecommons.org/licenses/by/3.0/\nZmiany: filtrowanie, płynne początki i zakończenia, zmiana wysokości żaby oraz konwersja do stereo 48 kHz. Autorzy nie są powiązani z tą grą.\n\n[b]Nagrania na licencji CC0[/b]\nThimras — Park ambiences (wiatr).\nIwan „qubodup” Gabovitch — 20 Rustles of dry leaves.\nisaiah658 — Ambient Bird Sounds.\nRudmer_Rotteveel — Wood Creak Single V7.\n\n[b]Wnętrze fregaty — CC0[/b]\nLEGIT Audio — The Shop (bezpłatne próbki OpenGameArt).\nbart — 68 Workshop Sounds i Steam release sounds.\nKenney — Sci-Fi Sounds.\n\nSzczegółowe źródła i zakres obróbki znajdują się w plikach CREDITS.md i manifest.json przy zasobach audio.",
|
||||||
|
"[font_size=16][color=#f1bd79]Opanuj statek[/color][/font_size]\n\n[color=#91dbea][b]W[/b][/color] — ciąg do przodu.\n[color=#91dbea][b]S[/b][/color] — hamowanie; po zatrzymaniu lot wstecz.\n[color=#91dbea][b]A / D[/b][/color] — obracanie statku.\n[color=#91dbea][b]Q / E[/b][/color] — ruch boczny w lewo / prawo.\n[color=#91dbea][b]TAB[/b][/color] — dopalanie: większa prędkość kosztem energii.\n\n[color=#91dbea][b]Kursor myszy[/b][/color] — celowanie.\n[color=#91dbea][b]LPM / PPM / ŚPM[/b][/color] — strzelanie z trzech slotów broni.\n[color=#91dbea][b]1–5[/b][/color] — użycie zamontowanych rozszerzeń.\n[color=#91dbea][b]F1–F5[/b][/color] — aktywne umiejętności kapitana.\n[color=#91dbea][b]R[/b][/color] — użycie powerbanku, jeśli masz go w zapasach.\n\nStatek ma bezwładność. Obrót nie zatrzymuje ruchu — hamuj wcześniej i wykorzystuj ruch boczny, żeby unikać ostrzału.",
|
||||||
|
"[font_size=16][color=#f1bd79]Twój pierwszy układ[/color][/font_size]\n\nWybierz statek przyciskiem [b]Nowa wyprawa[/b]. Każdy kadłub ma inne parametry — na początek wybierz ten, który pasuje do Twojego stylu.\n\n[color=#91dbea][b]1. Pokonaj zwykłych wrogów[/b][/color]\nOdszukuj przeciwników, rozwijaj wyposażenie i pilnuj zasobów. Aktualny cel znajdziesz w lewym dolnym rogu ekranu.\n\n[color=#91dbea][b]2. Pokonaj bossa[/b][/color]\nGdy zniszczysz pozostałych wrogów, w układzie pojawi się boss. Przygotuj zapas amunicji i sprawdź kadłub przed walką.\n\n[color=#91dbea][b]3. Znajdź zamieszkaną planetę[/b][/color]\nPo zwycięstwie podleć do zamieszkanej planety. Skorzystaj z usług i otwórz wormhole. Wleć w jego środek, żeby przejść do następnego, trudniejszego układu.",
|
||||||
|
"[font_size=16][color=#f1bd79]Wróć z wyprawy[/color][/font_size]\n\n[color=#91dbea][b]Tarcze, kadłub i energia[/b][/color]\nTarcze pochłaniają obrażenia przed kadłubem. Utrata całego kadłuba oznacza zniszczenie statku. Energia zasila część broni oraz dopalanie; odnawia się z czasem, szybciej przy gwieździe.\n\n[color=#91dbea][b]Dobieraj broń do zapasów[/b][/color]\nBroń energetyczna zużywa energię. Działko maszynowe potrzebuje zwykłej amunicji, gamma — napromieniowanej, a wyrzutnie — rakiet. Puste zapasy oznaczają brak strzału. Absorpcja ogranicza obrażenia danego typu.\n\n[color=#91dbea][b]Korzystaj z rozszerzeń[/b][/color]\nMiny atakują obszarowo, flary odciągają uwagę, kamuflaż pomaga zerwać kontakt, teleport przenosi w bezpieczne miejsce, a drony wspierają ostrzał. Doładowanie tarcz działa przy gwieździe. Sprawdzaj koszt i cooldown w opisie.\n\n[color=#f1bd79][b]Uważaj na uciekających przeciwników[/b][/color]\nWróg z kadłubem poniżej 10% ucieka wolniej, ale może zostawić minę. Nie leć bezmyślnie prosto za nim.",
|
||||||
|
"[b]Wyprawy na planety[/b]\n\nPierwsze planety są łagodne. W kolejnych układach eksploracja jest trudniejsza, ale znaleziska są bogatsze. Dopasuj poziom wyposażenia kapitana do poziomu planety: aparat oddechowy pomaga w jaskiniach, skafander przy wydobyciu i ruinach, a broń ręczna w magazynach i osadach.\n\nPodleć do planety EARTHLIKE. F pokazuje informacje, a L rozpoczyna lądowanie. Lądownik musi mieć 100 HP przed startem; lądowanie uszkadza kadłub. Podczas walki nie można lądować.\n\nNa powierzchni: W — ciąg, S — hamowanie i wstecz, A/D — obrót, Q/R — ruch boczny, TAB — dopalanie. Przy POI naciśnij E. Najpierw zobaczysz przewidywaną nagrodę i uszkodzenia. Samo otwarcie okna niczego nie zużywa. Potwierdź eksplorację przyciskiem lub drugim naciśnięciem E.\n\nNiektóre miejsca oferują dodatkowe znaleziska. Przeszukanie głębiej daje więcej łupu, ale mocniej uszkadza lądownik. Niski kadłub może oznaczać utratę całej zdobyczy tej wyprawy. L pozwala wrócić z dotychczasowym łupem. Spotkania oznaczone pytajnikiem również otwierasz klawiszem E.\n\n[b]Frachtowiec i postęp[/b]\nPrzy gwieździe centralnej zadokuj klawiszem L. Hangar naprawia lądownik za części. Warsztat produkuje zaopatrzenie i kolejne poziomy wyposażenia kapitana. Laboratorium prowadzi badania.\n\nEsc otwiera pauzę, nazwane zapisy i opcje. Wczytanie zachowuje postęp oraz wyposażenie i zaczyna bieżący poziom od początku.",
|
||||||
|
"[font_size=16][color=#f1bd79]Zbieraj. Porównuj. Twórz.[/color][/font_size]\n\n[color=#91dbea][b]Łup zbierasz przez podlecenie[/b][/color]\nPrzedmioty w pobliżu są przyciągane do statku. Magazyn mieści 20 przedmiotów; przy pełnym magazynie zwolnij miejsce, żeby zebrać kolejny.\n\n[color=#91dbea][b]Asteroidy zostawiają fizyczne odłamki[/b][/color]\nStrzelaj do asteroid. Po zniszczeniu rozpadają się bazowo na 5–7 poszarpanych fragmentów. Każdy to jedna jednostka surowca — musisz go zebrać. Umiejętność górnika zwiększa uzysk.\n\n[color=#91dbea][b]Przeszukuj wraki[/b][/color]\nPodleć do wraku i przytrzymaj E, aby go przeszukać. Wraki dają surowce (65%), amunicję lub rakiety (łącznie 20%) albo moduł (15%).\n\n[color=#91dbea][b]Warsztat fregaty — produkcja[/b][/color]\nZadokuj na fregacie i wybierz Warsztat. Tam wytworzysz amunicję, rakiety, części, powerbanki i wyposażenie kapitana. Koszt sprawdzisz w podpowiedzi przycisku produkcji.\n\n[color=#91dbea][b]Odzyskuj części[/b][/color]\nNajedź na zbędny przedmiot w magazynie i użyj przycisku rozłożenia. Części przydadzą się do napraw.",
|
||||||
|
"_boss_spawned",
|
||||||
|
"aluminium",
|
||||||
|
"beam_laser",
|
||||||
|
"boss",
|
||||||
|
"boss_spawned",
|
||||||
|
"brak",
|
||||||
|
"brak łupu",
|
||||||
|
"deuter",
|
||||||
|
"hangar",
|
||||||
|
"is_boss_alive",
|
||||||
|
"normal",
|
||||||
|
"normal_font",
|
||||||
|
"normal_font_size",
|
||||||
|
"pending_boss",
|
||||||
|
"player_start",
|
||||||
|
"przenieś na fregatę",
|
||||||
|
"pulse_laser",
|
||||||
|
"radiation_laser",
|
||||||
|
"start",
|
||||||
|
"start_boost",
|
||||||
|
"zwykły",
|
||||||
|
"Ładowanie słoneczne",
|
||||||
|
"Ładowanie tarcz",
|
||||||
|
"Ładownia",
|
||||||
|
"Łagodna biosfera",
|
||||||
|
"Łowca nagród",
|
||||||
|
"Łup i wytwarzanie",
|
||||||
|
"Łup ×%.2f · sprzęt ×%.2f · odzysk %.0f%%\nZagrożenie po ochronie: %.1f%% / 300%%",
|
||||||
|
"Łup: ",
|
||||||
|
"Łącznie do 10% faktycznie zadanych obrażeń. Tempo: do 5% maksymalnych tarcz/s, z rezerwą na jedno takie odnowienie.",
|
||||||
|
"Łączny DPS",
|
||||||
|
"ŚPM",
|
||||||
|
"Śmiertelne trafienie zostawia 1 punkt kadłuba i daje 2 s niewrażliwości. Raz na wyprawę lub wejście do zwykłego układu. Dokowanie ani restart po porażce nie odnawiają efektu.",
|
||||||
|
"Źródło: %s · poziom %d",
|
||||||
|
"Żelazo",
|
||||||
|
"Żelazo %d · Części %d",
|
||||||
|
"Żmija",
|
||||||
|
"żelaza",
|
||||||
|
"‹ WRÓĆ / ESC"
|
||||||
|
]
|
||||||
376
resources/localization/supplemental.tsv
Normal file
@ -0,0 +1,376 @@
|
|||||||
|
Naukowiec Wissenschaftler Científico Scientist Scientifique
|
||||||
|
PRZEWIDYWANA NAGRODA ERWARTETE BELOHNUNG RECOMPENSA PREVISTA EXPECTED REWARD RÉCOMPENSE PRÉVUE
|
||||||
|
Podejmij eksplorację [E] Erkundung starten [E] Iniciar exploración [E] Begin exploration [E] Commencer l'exploration [E]
|
||||||
|
DODATKOWE ZNALEZISKA ZUSÄTZLICHE FUNDE HALLAZGOS ADICIONALES ADDITIONAL FINDS TROUVAILLES SUPPLÉMENTAIRES
|
||||||
|
Przeszukaj głębiej Tiefer durchsuchen Explorar más a fondo Search deeper Fouiller plus profondément
|
||||||
|
Moduły: %d · poziom %d–%d Module: %d · Stufe %d–%d Módulos: %d · nivel %d–%d Modules: %d · level %d–%d Modules : %d · niveau %d–%d
|
||||||
|
Uszkodzenia lądownika: %d–%d HP Landemodul-Schaden: %d–%d HP Daño al módulo: %d–%d PV Lander damage: %d–%d HP Dégâts à l'atterrisseur : %d–%d PV
|
||||||
|
Uszkodzenia lądownika: −%d HP Landemodul-Schaden: −%d HP Daño al módulo: −%d PV Lander damage: −%d HP Dégâts à l'atterrisseur : −%d PV
|
||||||
|
Lądownik może zostać zniszczony. Utracisz cały łup tej wyprawy. Das Landemodul kann zerstört werden. Du verlierst die gesamte Beute dieser Expedition. El módulo puede ser destruido. Perderás todo el botín de esta expedición. The lander may be destroyed. You will lose all loot from this expedition. L'atterrisseur risque d'être détruit. Vous perdrez tout le butin de cette expédition.
|
||||||
|
Przewidywane uszkodzenia lądownika: 0–%d HP Erwarteter Landemodul-Schaden: 0–%d HP Daño previsto al módulo: 0–%d PV Expected lander damage: 0–%d HP Dégâts prévus à l'atterrisseur : 0–%d PV
|
||||||
|
Ten etap jest niedostępny z obecnym wyposażeniem. Diese Etappe ist mit der aktuellen Ausrüstung nicht verfügbar. Esta etapa no está disponible con el equipo actual. This stage is unavailable with your current equipment. Cette étape est indisponible avec votre équipement actuel.
|
||||||
|
Sprawdź wymagane zasoby. Prüfe die benötigten Ressourcen. Comprueba los recursos necesarios. Check the required resources. Vérifiez les ressources requises.
|
||||||
|
· dodatkowe znaleziska · zusätzliche Funde · hallazgos adicionales · additional finds · trouvailles supplémentaires
|
||||||
|
[E] Zaplanuj eksplorację [E] Erkundung planen [E] Planear exploración [E] Plan exploration [E] Préparer l'exploration
|
||||||
|
%s · Poziom %d\nLądowanie: −%d HP\nLądownik: %d / 100 HP\nPOI: podleć i naciśnij E, aby zaplanować eksplorację. %s · Stufe %d\nLandung: −%d HP\nLandemodul: %d / 100 HP\nPOI: nähern und E drücken, um die Erkundung zu planen. %s · Nivel %d\nAterrizaje: −%d PV\nMódulo: %d / 100 PV\nPOI: acércate y pulsa E para planear la exploración. %s · Level %d\nLanding: −%d HP\nLander: %d / 100 HP\nPOI: approach and press E to plan exploration. %s · Niveau %d\nAtterrissage : −%d PV\nAtterrisseur : %d / 100 PV\nPOI : approchez et appuyez sur E pour préparer l'exploration.
|
||||||
|
Dopasuj poziom wyposażenia do planety, aby odzyskać więcej łupu i ograniczyć uszkodzenia lądownika. Passe die Ausrüstungsstufe dem Planeten an, um mehr Beute zu bergen und Landemodul-Schäden zu verringern. Adapta el nivel del equipo al planeta para recuperar más botín y reducir daños al módulo. Match equipment level to the planet to recover more loot and reduce lander damage. Adaptez le niveau de l'équipement à la planète pour récupérer plus de butin et limiter les dégâts à l'atterrisseur.
|
||||||
|
Pomaga podczas eksploracji jaskiń i miejsc z trudną atmosferą. Hilft bei der Erkundung von Höhlen und schwierigen Atmosphären. Ayuda a explorar cuevas y lugares de atmósfera difícil. Helps explore caves and difficult atmospheres. Aide à explorer les grottes et les atmosphères difficiles.
|
||||||
|
Pomaga przy wydobyciu i eksploracji niestabilnych ruin. Hilft beim Abbau und der Erkundung instabiler Ruinen. Ayuda a extraer recursos y explorar ruinas inestables. Helps with extraction and exploring unstable ruins. Aide à l'extraction et à l'exploration de ruines instables.
|
||||||
|
Pomaga przeszukiwać magazyny i osady opanowane przez faunę. Hilft beim Durchsuchen von Lagern und von Tieren besetzten Siedlungen. Ayuda a registrar almacenes y asentamientos ocupados por fauna. Helps search warehouses and settlements occupied by wildlife. Aide à fouiller les entrepôts et colonies occupés par la faune.
|
||||||
|
Dopasuj poziom wyposażenia do poziomu planety. Passe die Ausrüstungsstufe der Planetenstufe an. Adapta el nivel del equipo al nivel del planeta. Match equipment level to planet level. Adaptez le niveau de l'équipement au niveau de la planète.
|
||||||
|
RANDOLOOT / SYSTEMY POKŁADOWE RANDOLOOT / BORDSYSTEME RANDOLOOT / SISTEMAS DE A BORDO RANDOLOOT / ONBOARD SYSTEMS RANDOLOOT / SYSTÈMES DE BORD
|
||||||
|
Dostosuj dźwięk, ekran i język swojej wyprawy. Passe Ton, Anzeige und Sprache deiner Expedition an. Ajusta sonido, pantalla e idioma de tu expedición. Adjust sound, display and language for your expedition. Réglez le son, l'affichage et la langue de votre expédition.
|
||||||
|
USTAWIENIA / KOMPUTER POKŁADOWY EINSTELLUNGEN / BORDCOMPUTER AJUSTES / COMPUTADORA DE A BORDO SETTINGS / ONBOARD COMPUTER PARAMÈTRES / ORDINATEUR DE BORD
|
||||||
|
01 / DŹWIĘK 01 / TON 01 / SONIDO 01 / SOUND 01 / SON
|
||||||
|
02 / OBRAZ 02 / ANZEIGE 02 / PANTALLA 02 / DISPLAY 02 / AFFICHAGE
|
||||||
|
03 / JĘZYK 03 / SPRACHE 03 / IDIOMA 03 / LANGUAGE 03 / LANGUE
|
||||||
|
Język interfejsu Oberflächensprache Idioma de interfaz Interface language Langue de l'interface
|
||||||
|
Ustawienia są zapamiętywane między uruchomieniami. Einstellungen bleiben nach dem Neustart erhalten. Los ajustes se conservan entre sesiones. Settings are remembered between sessions. Les paramètres sont conservés entre les sessions.
|
||||||
|
ZAPISZ WYPRAWĘ EXPEDITION SPEICHERN GUARDAR EXPEDICIÓN SAVE EXPEDITION SAUVEGARDER L'EXPÉDITION
|
||||||
|
WCZYTAJ WYPRAWĘ EXPEDITION LADEN CARGAR EXPEDICIÓN LOAD EXPEDITION CHARGER L'EXPÉDITION
|
||||||
|
Nadaj nazwę nowemu zapisowi lub wybierz zapis do nadpisania. Benenne einen neuen Spielstand oder wähle einen zum Überschreiben. Nombra una nueva partida o elige una para sobrescribir. Name a new save or choose one to overwrite. Nommez une nouvelle sauvegarde ou choisissez-en une à remplacer.
|
||||||
|
Wybierz zapis i wróć do swojej wyprawy. Wähle einen Spielstand und kehre zur Expedition zurück. Elige una partida y vuelve a tu expedición. Choose a save and return to your expedition. Choisissez une sauvegarde et reprenez votre expédition.
|
||||||
|
ARCHIWUM / DZIENNIK POKŁADOWY ARCHIV / BORDBUCH ARCHIVO / DIARIO DE A BORDO ARCHIVE / SHIP LOG ARCHIVES / JOURNAL DE BORD
|
||||||
|
Nazwa zapisu Spielstandname Nombre de partida Save name Nom de sauvegarde
|
||||||
|
Nowy zapis Neuer Spielstand Nueva partida guardada New save Nouvelle sauvegarde
|
||||||
|
ZAPISANE WYPRAWY GESPEICHERTE EXPEDITIONEN EXPEDICIONES GUARDADAS SAVED EXPEDITIONS EXPÉDITIONS SAUVEGARDÉES
|
||||||
|
DANE WYPRAWY EXPEDITIONSDATEN DATOS DE EXPEDICIÓN EXPEDITION DETAILS DÉTAILS DE L'EXPÉDITION
|
||||||
|
Wczytanie rozpoczyna poziom od początku. Postęp i wyposażenie zostają zachowane. Laden startet das Level neu. Fortschritt und Ausrüstung bleiben erhalten. Cargar reinicia el nivel. Se conservan el progreso y el equipo. Loading restarts the level. Progress and equipment are retained. Charger reprend au début du niveau. Progression et équipement conservés.
|
||||||
|
Nie ma jeszcze zapisanych wypraw. Noch keine gespeicherten Expeditionen. Aún no hay expediciones guardadas. No saved expeditions yet. Aucune expédition sauvegardée pour le moment.
|
||||||
|
Układ %d · Kapitan %d System %d · Kapitän %d Sistema %d · Capitán %d System %d · Captain %d Système %d · Capitaine %d
|
||||||
|
Układ %d\nKapitan · poziom %d\nKredyty: %d System %d\nKapitän · Stufe %d\nCredits: %d Sistema %d\nCapitán · nivel %d\nCréditos: %d System %d\nCaptain · level %d\nCredits: %d Système %d\nCapitaine · niveau %d\nCrédits : %d
|
||||||
|
Nowy zapis\nUkład %d\nKapitan · poziom %d Neuer Spielstand\nSystem %d\nKapitän · Stufe %d Nueva partida\nSistema %d\nCapitán · nivel %d New save\nSystem %d\nCaptain · level %d Nouvelle sauvegarde\nSystème %d\nCapitaine · niveau %d
|
||||||
|
Odzyskano z kopii zapasowej Aus Sicherung wiederhergestellt Recuperado de copia de seguridad Recovered from backup Récupéré depuis la copie de secours
|
||||||
|
Nadpisz zapis Spielstand überschreiben Sobrescribir partida Overwrite save Remplacer la sauvegarde
|
||||||
|
Automatyczny zapis Automatischer Spielstand Guardado automático Autosave Sauvegarde automatique
|
||||||
|
Zapis rozgrywki Spielstand Partida guardada Saved game Sauvegarde
|
||||||
|
Wczytaj grę Spiel laden Cargar partida Load game Charger une partie
|
||||||
|
WCZYTAJ GRĘ SPIEL LADEN CARGAR PARTIDA LOAD GAME CHARGER UNE PARTIE
|
||||||
|
Wybierz wyprawę z archiwum zapisów Expedition aus dem Archiv wählen Elige una expedición del archivo Choose an expedition from the save archive Choisissez une expédition dans les archives
|
||||||
|
Twoja wyprawa czeka. Wybierz, co chcesz zrobić. Deine Expedition wartet. Wähle eine Aktion. Tu expedición espera. Elige qué hacer. Your expedition awaits. Choose what to do. Votre expédition vous attend. Choisissez une action.
|
||||||
|
ŁĄCZE / MENU POKŁADOWE VERBINDUNG / BORDMENÜ ENLACE / MENÚ DE A BORDO LINK / ONBOARD MENU LIAISON / MENU DE BORD
|
||||||
|
Gwiazda centralna Zentralstern Estrella central Central star Étoile centrale
|
||||||
|
ADDONY (aktywne po zamontowaniu) ATTRIBUTE (nach Einbau aktiv) ATRIBUTOS (activos al instalar) MODIFIERS (active when installed) MODIFICATEURS (actifs après installation)
|
||||||
|
ADDONY (aktywne ATTRIBUTE (aktiv ATRIBUTOS (activos MODIFIERS (active MODIFICATEURS (actifs
|
||||||
|
Cooldown po addonach: %.2f s\nZapas rakiet: %d Abklingzeit nach Attributen: %.2f s\nRaketen: %d Recarga tras atributos: %.2f s\nMisiles: %d Cooldown after modifiers: %.2f s\nMissiles: %d Recharge après modificateurs : %.2f s\nMissiles : %d
|
||||||
|
Kliknij: Klicken: Pulsa: Click: Cliquez :
|
||||||
|
Odbierz w Hangarze. Im Hangar abholen. Recoger en el hangar. Collect in the hangar. Récupérer au hangar.
|
||||||
|
Odnowienie: %d s. Abklingzeit: %d s. Recarga: %d s. Cooldown: %d s. Recharge : %d s.
|
||||||
|
Pogoda: Wetter: Clima: Weather: Météo :
|
||||||
|
Uwzględnia utratę bonusów zdejmowanego przedmiotu. Berücksichtigt verlorene Boni des abgelegten Gegenstands. Incluye perder bonus del objeto retirado. Includes lost bonuses from the removed item. Inclut les bonus perdus de l'objet retiré.
|
||||||
|
Wymaga: Benötigt: Requiere: Requires: Nécessite :
|
||||||
|
Zapas: Vorrat: Reservas: Stock: Réserve :
|
||||||
|
[E] Buduj [E] Bauen [E] Construir [E] Build [E] Construire
|
||||||
|
[E] Maksymalizuj addon [E] Attribut maximieren [E] Maximizar atributo [E] Maximize modifier [E] Maximiser le modificateur
|
||||||
|
[E] Porozmawiaj [E] Sprechen [E] Hablar [E] Talk [E] Parler
|
||||||
|
[E] Przeszukaj [E] Durchsuchen [E] Registrar [E] Search [E] Fouiller
|
||||||
|
[E] Zbierz znaleziska [E] Funde sammeln [E] Recoger hallazgos [E] Collect finds [E] Récupérer les trouvailles
|
||||||
|
· rabat %d%% · Rabatt %d%% · descuento %d%% · discount %d%% · remise %d%%
|
||||||
|
(obok planety) (neben Planet) (junto al planeta) (near planet) (près de la planète)
|
||||||
|
· mapa kupiona · Karte gekauft · mapa comprado · map purchased · carte achetée
|
||||||
|
· odwiedzono · besucht · visitado · visited · visité
|
||||||
|
· partia: %d szt. · Charge: %d Stück · lote: %d uds. · batch: %d units · lot : %d unités
|
||||||
|
· zatrudniono · rekrutiert · contratado · hired · recruté
|
||||||
|
— zamieszkana — bewohnt — habitado — inhabited — habitée
|
||||||
|
%d / %d ZBADANO %d / %d ERFORSCHT %d / %d INVESTIGADO %d / %d RESEARCHED %d / %d RECHERCHÉ
|
||||||
|
%d kr. %d Cr. %d cr. %d cr. %d cr.
|
||||||
|
%d pkt %d Pkt. %d pts. %d pts %d pts
|
||||||
|
Zapas: %s Vorrat: %s Reservas: %s Stock: %s Réserve : %s
|
||||||
|
ODNOWIENIE %d s ABKLINGZEIT %d s RECARGA %d s COOLDOWN %d s RECHARGE %d s
|
||||||
|
%s · %d szt. %s · %d Stück %s · %d uds. %s · %d units %s · %d unités
|
||||||
|
ADDONY: %d/5 ATTRIBUTE: %d/5 ATRIBUTOS: %d/5 MODIFIERS: %d/5 MODIFICATEURS : %d/5
|
||||||
|
poz. %d St. %d Niv. %d Lv. %d Niv. %d
|
||||||
|
+%d amunicji +%d Munition +%d municiones +%d ammunition +%d munitions
|
||||||
|
+%d rakiet +%d Raketen +%d misiles +%d missiles +%d missiles
|
||||||
|
06 / PREMIE I BADANIA 06 / BONI UND FORSCHUNG 06 / BONUS E INVESTIGACIÓN 06 / BONUSES AND RESEARCH 06 / BONUS ET RECHERCHE
|
||||||
|
Absorpcja: Absorption: Absorción: Absorption: Absorption :
|
||||||
|
DALEKIE WYPRAWY / SEKTORY DO ZBADANIA FERNEXPEDITIONEN / UNERFORSCHTE SEKTOREN EXPEDICIONES LEJANAS / SECTORES POR EXPLORAR DISTANT EXPEDITIONS / UNEXPLORED SECTORS EXPÉDITIONS LOINTAINES / SECTEURS À EXPLORER
|
||||||
|
DZIENNIK PLANETARNY / WYPRAWA PLANETENLOG / EXPEDITION DIARIO PLANETARIO / EXPEDICIÓN PLANET LOG / EXPEDITION JOURNAL PLANÉTAIRE / EXPÉDITION
|
||||||
|
DZIENNIK WYPRAWY / %s EXPEDITIONSLOG / %s DIARIO DE EXPEDICIÓN / %s EXPEDITION LOG / %s JOURNAL D'EXPÉDITION / %s
|
||||||
|
Etap %d/3 · %s Etappe %d/3 · %s Etapa %d/3 · %s Stage %d/3 · %s Étape %d/3 · %s
|
||||||
|
INSTRUKCJA / AKADEMIA PILOTA ANLEITUNG / PILOTENAKADEMIE INSTRUCCIONES / ACADEMIA DE PILOTOS GUIDE / PILOT ACADEMY GUIDE / ACADÉMIE DE PILOTAGE
|
||||||
|
Każdy strzał Jeder Schuss Cada disparo Each shot Chaque tir
|
||||||
|
Kup %d rakiet · sklep: %d kr. %d Raketen kaufen · Laden: %d Cr. Comprar %d misiles · tienda: %d cr. Buy %d missiles · shop: %d cr. Acheter %d missiles · boutique : %d cr.
|
||||||
|
Kup: %s · poz. %d Kaufen: %s · St. %d Comprar: %s · niv. %d Buy: %s · lv. %d Acheter : %s · niv. %d
|
||||||
|
LĄDUJ [L] LANDEN [L] ATERRIZAR [L] LAND [L] ATTERRIR [L]
|
||||||
|
MAGAZYN · %d / %d LAGER · %d / %d ALMACÉN · %d / %d STORAGE · %d / %d STOCKAGE · %d / %d
|
||||||
|
Nagroda za sukces: Erfolgsbelohnung: Premio por éxito: Success reward: Récompense de réussite :
|
||||||
|
ODCZYT: amunicja rakietowa. Liczba sztuk nieznana. SCAN: Raketenmunition. Menge unbekannt. ESCÁNER: munición de misiles. Cantidad desconocida. SCAN: missile ammunition. Quantity unknown. SCAN : munitions de missiles. Quantité inconnue.
|
||||||
|
ORBY / SPECJALNE ULEPSZENIA ORBS / SPEZIALVERBESSERUNGEN ORBES / MEJORAS ESPECIALES ORBS / SPECIAL UPGRADES ORBES / AMÉLIORATIONS SPÉCIALES
|
||||||
|
Obecnie: %.2f %s → maksimum: %.2f %s Aktuell: %.2f %s → Maximum: %.2f %s Actual: %.2f %s → máximo: %.2f %s Current: %.2f %s → maximum: %.2f %s Actuel : %.2f %s → maximum : %.2f %s
|
||||||
|
Obecnie: %s Aktuell: %s Actual: %s Current: %s Actuel : %s
|
||||||
|
Obecny: System %d · Najdalszy odkryty: %d Aktuell: System %d · Weitestes entdeckt: %d Actual: sistema %d · Más lejano descubierto: %d Current: System %d · Furthest discovered: %d Actuel : système %d · Plus lointain découvert : %d
|
||||||
|
Obraż. krytyczne Krit. Schaden Daño crítico Crit. damage Dégâts critiques
|
||||||
|
Odnowienie: %.0f s Abklingzeit: %.0f s Recarga: %.0f s Cooldown: %.0f s Recharge : %.0f s
|
||||||
|
Otrzymano: Erhalten: Recibido: Received: Reçu :
|
||||||
|
Otrzymasz: Du erhältst: Recibirás: You receive: Vous recevrez :
|
||||||
|
POSIADASZ / WYMAGANE VORHANDEN / BENÖTIGT DISPONIBLE / REQUERIDO OWNED / REQUIRED DISPONIBLE / REQUIS
|
||||||
|
PUSTELNIK / KARTOGRAF EINSIEDLER / KARTOGRAF ERMITAÑO / CARTÓGRAFO HERMIT / CARTOGRAPHER ERMITE / CARTOGRAPHE
|
||||||
|
Pustelnik / Kartograf Einsiedler / Kartograf Ermitaño / Cartógrafo Hermit / Cartographer Ermite / Cartographe
|
||||||
|
Paliwo: %d deuteru Treibstoff: %d Deuterium Combustible: %d deuterio Fuel: %d deuterium Carburant : %d deutérium
|
||||||
|
Regeneracja generatora: +%.1f /s Generatorregeneration: +%.1f /s Regeneración del generador: +%.1f /s Generator regeneration: +%.1f /s Régénération du générateur : +%.1f /s
|
||||||
|
Regeneracja tarcz: +%.1f pkt/s Schildregeneration: +%.1f Pkt./s Regeneración de escudos: +%.1f pts/s Shield regeneration: +%.1f pts/s Régénération des boucliers : +%.1f pts/s
|
||||||
|
Skróc. cooldownu rakiet Raketen-Abklingzeitreduktion Reducción recarga misiles Missile cooldown reduction Réduction recharge missiles
|
||||||
|
Slot zablokowany. Odblokowuj kolejne miejsca w hangarze fregaty.\nNastępny slot: Slot gesperrt. Weitere Plätze im Fregattenhangar freischalten.\nNächster Slot: Ranura bloqueada. Desbloquea más en hangar de fragata.\nPróxima ranura: Slot locked. Unlock more in the frigate hangar.\nNext slot: Emplacement bloqué. Débloquez au hangar de la frégate.\nProchain emplacement :
|
||||||
|
Slot: %s Slot: %s Ranura: %s Slot: %s Emplacement : %s
|
||||||
|
Typ obrażeń: Schadenstyp: Tipo de daño: Damage type: Type de dégâts :
|
||||||
|
Typ: Typ: Tipo: Type: Type :
|
||||||
|
Uruchom prototyp · podstawa: %d kr. Prototyp starten · Basis: %d Cr. Iniciar prototipo · base: %d cr. Start prototype · base: %d cr. Lancer le prototype · base : %d cr.
|
||||||
|
WYTWORZONO: %s ×%d HERGESTELLT: %s ×%d FABRICADO: %s ×%d CRAFTED: %s ×%d FABRIQUÉ : %s ×%d
|
||||||
|
Z PLANET: VON PLANETEN: DE PLANETAS: FROM PLANETS: DES PLANÈTES :
|
||||||
|
ZMIANY PO ZAŁOŻENIU ÄNDERUNGEN NACH AUSRÜSTEN CAMBIOS AL EQUIPAR CHANGES WHEN EQUIPPED CHANGEMENTS APRÈS ÉQUIPEMENT
|
||||||
|
Zadokuj, aby naprawić lądownik, rozbudować statek i przenieść wyposażenie. Andocken, um Landemodul zu reparieren, Schiff auszubauen und Ausrüstung zu übertragen. Atraca para reparar módulo, ampliar nave y transferir equipo. Dock to repair the lander, expand your ship and transfer gear. Amarrez-vous pour réparer l'atterrisseur, agrandir le vaisseau et transférer l'équipement.
|
||||||
|
Zakwaterowanie: Kajuta %02d Unterkunft: Kabine %02d Alojamiento: camarote %02d Accommodation: cabin %02d Logement : cabine %02d
|
||||||
|
Zapas paliwa: %.1f deuteru Treibstoffvorrat: %.1f Deuterium Reserva: %.1f deuterio Fuel stock: %.1f deuterium Réserve de carburant : %.1f deutérium
|
||||||
|
Zapas: %d Vorrat: %d Reservas: %d Stock: %d Réserve : %d
|
||||||
|
Zmiana statystyk statku: Änderung der Schiffswerte: Cambio de estadísticas: Ship stat changes: Changements des statistiques :
|
||||||
|
[%s] Pusty slot — przypisz skill w panelu kapitana [%s] Leerer Slot — Fähigkeit im Kapitänsfenster zuweisen [%s] Ranura vacía — asigna habilidad en el panel del capitán [%s] Empty slot — assign a skill in the captain panel [%s] Emplacement vide — affectez une compétence dans le panneau du capitaine
|
||||||
|
[R] +10% energii [R] +10% Energie [R] +10% energía [R] +10% energy [R] +10% énergie
|
||||||
|
odbierz do statku ins Schiff übernehmen recoger a la nave retrieve into ship récupérer dans le vaisseau
|
||||||
|
Średni DPS z krytykami i cooldownem.\nBez ograniczeń energii i amunicji.\nAddony uwzględniają zdjęcie obecnej broni. Mittlerer DPS mit kritischen Treffern und Abklingzeit.\nOhne Energie- und Munitionsgrenzen.\nAttribute berücksichtigen Entfernen der aktuellen Waffe. DPS medio con críticos y recarga.\nSin límites de energía ni munición.\nIncluye retirar el arma actual. Average DPS with critical hits and cooldown.\nWithout energy or ammunition limits.\nModifiers include removing the current weapon. DPS moyen avec critiques et recharge.\nSans limites d'énergie ni de munitions.\nLes modificateurs incluent le retrait de l'arme actuelle.
|
||||||
|
← ODBIERZ ← ABHOLEN ← RECOGER ← RETRIEVE ← RÉCUPÉRER
|
||||||
|
← Odbierz wszystko ← Alles abholen ← Recoger todo ← Retrieve all ← Tout récupérer
|
||||||
|
● FREGATA / POŁĄCZENIE GOTOWE ● FREGATTE / VERBINDUNG BEREIT ● FRAGATA / CONEXIÓN LISTA ● FRIGATE / CONNECTION READY ● FRÉGATE / CONNEXION PRÊTE
|
||||||
|
● OPERACYJNE ● BETRIEBSBEREIT ● OPERATIVO ● OPERATIONAL ● OPÉRATIONNEL
|
||||||
|
● RAPORT WYPRAWY ● EXPEDITIONSBERICHT ● INFORME DE EXPEDICIÓN ● EXPEDITION REPORT ● RAPPORT D'EXPÉDITION
|
||||||
|
● STACJA / ZAOPATRZENIE ● STATION / VERSORGUNG ● ESTACIÓN / SUMINISTROS ● STATION / SUPPLIES ● STATION / RAVITAILLEMENT
|
||||||
|
● TELEMETRIA / DANE PLANETY ● TELEMETRIE / PLANETENDATEN ● TELEMETRÍA / DATOS DEL PLANETA ● TELEMETRY / PLANET DATA ● TÉLÉMÉTRIE / DONNÉES PLANÉTAIRES
|
||||||
|
● W REMONCIE ● IM UMBAU ● EN OBRAS ● UNDER CONSTRUCTION ● EN TRAVAUX
|
||||||
|
● ŁĄCZE ORBITALNE ● ORBITALVERBINDUNG ● ENLACE ORBITAL ● ORBITAL LINK ● LIAISON ORBITALE
|
||||||
|
Wczytaj Laden Cargar Load Charger
|
||||||
|
WYBIERZ I WYSTARTUJ › WÄHLEN UND STARTEN › ELEGIR Y DESPEGAR › SELECT AND LAUNCH › CHOISIR ET DÉCOLLER ›
|
||||||
|
Rusznikarz Waffenschmied Armero Gunsmith Armurier
|
||||||
|
Specjalista rakietowy Raketenspezialist Especialista en misiles Missile specialist Spécialiste des missiles
|
||||||
|
Procedura awaryjna Notfallprozedur Procedimiento de emergencia Emergency procedure Procédure d'urgence
|
||||||
|
Elektryk Elektriker Electricista Electrician Électricien
|
||||||
|
Farciarz Glückspilz Afortunado Lucky Chanceux
|
||||||
|
Eksplorator Entdecker Explorador Explorer Explorateur
|
||||||
|
Rekin biznesu Geschäftshai Tiburón de negocios Business shark Requin des affaires
|
||||||
|
Manewr taktyczny Taktisches Manöver Maniobra táctica Tactical maneuver Manœuvre tactique
|
||||||
|
Przekierowanie zasilania Energieumleitung Redirección de energía Power redirect Redirection d'énergie
|
||||||
|
Regeneracja energii +%d%% przez 15 sekund. Energieregeneration +%d%% für 15 s. Regeneración de energía +%d%% durante 15 s. Energy regeneration +%d%% for 15 s. Régénération d'énergie +%d%% pendant 15 s.
|
||||||
|
ADDON DO MAKSYMALIZACJI ATTRIBUT ZUM MAXIMIEREN ATRIBUTO PARA MAXIMIZAR MODIFIER TO MAXIMIZE MODIFICATEUR À MAXIMISER
|
||||||
|
ADDONY · PO ZAMONTOWANIU ATTRIBUTE · EINGEBAUT ATRIBUTOS · INSTALADO MODIFIERS · WHEN INSTALLED MODIFICATEURS · INSTALLÉ
|
||||||
|
AKTYWNA AKTIV ACTIVA ACTIVE ACTIVE
|
||||||
|
AKTYWNA %.1f s AKTIV %.1f s ACTIVA %.1f s ACTIVE %.1f s ACTIVE %.1f s
|
||||||
|
AMUNICJA MUNITION MUNICIÓN AMMUNITION MUNITIONS
|
||||||
|
AWANS KAPITANA KAPITÄNSAUFSTIEG ASCENSO DEL CAPITÁN CAPTAIN LEVEL UP NIVEAU DU CAPITAINE
|
||||||
|
AWARYJNE GRODZIE NOTSCHOTTEN MAMPAROS DE EMERGENCIA EMERGENCY BULKHEADS CLOISONS D'URGENCE
|
||||||
|
Absorpcja energetyczna Energieabsorption Absorción energética Energy absorption Absorption énergétique
|
||||||
|
Absorpcja kinetyczna Kinetische Absorption Absorción cinética Kinetic absorption Absorption cinétique
|
||||||
|
Absorpcja radiacyjna Strahlungsabsorption Absorción radiativa Radiation absorption Absorption radiative
|
||||||
|
Akcja ratunkowa Rettungsaktion Operación de rescate Rescue operation Opération de secours
|
||||||
|
Aktywne rozszerzenie naprawcze. Aktive Reparaturerweiterung. Extensión activa de reparación. Active repair extension. Extension active de réparation.
|
||||||
|
Aktywne rozszerzenie silnika. Aktive Antriebserweiterung. Extensión activa de motor. Active engine extension. Extension active de moteur.
|
||||||
|
Aktywne rozszerzenie tarcz. Aktive Schilderweiterung. Extensión activa de escudos. Active shield extension. Extension active de boucliers.
|
||||||
|
Alpejska tundra Alpine Tundra Tundra alpina Alpine tundra Toundra alpine
|
||||||
|
Amunicja radiacyjna Strahlungsmunition Munición irradiada Irradiated ammunition Munitions irradiées
|
||||||
|
Analiza konstrukcji Strukturanalyse Análisis estructural Structural analysis Analyse structurelle
|
||||||
|
Antyczne znalezisko Antiker Fund Hallazgo antiguo Ancient discovery Découverte ancienne
|
||||||
|
Awaryjne grodzie Notschotten Mamparos de emergencia Emergency bulkheads Cloisons d'urgence
|
||||||
|
BLOKADA GESPERRT BLOQUEO LOCKED VERROUILLÉ
|
||||||
|
Bank energii Energiebank Batería Power bank Batterie
|
||||||
|
Banki energii Energiebanken Baterías Power banks Batteries
|
||||||
|
Bez zmian w bonusach. Keine Bonusänderungen. Sin cambios en bonificaciones. No bonus changes. Aucun changement de bonus.
|
||||||
|
Blokada regeneracji Regenerationssperre Bloqueo de regeneración Regeneration lock Blocage de régénération
|
||||||
|
Brakuje %.1f deuteru %.1f Deuterium fehlen Faltan %.1f deuterio Missing %.1f deuterium Il manque %.1f deutérium
|
||||||
|
Brama zapomnianych Tor der Vergessenen Puerta de los olvidados Gate of the forgotten Porte des oubliés
|
||||||
|
Burza z piorunami Gewitter Tormenta eléctrica Thunderstorm Orage
|
||||||
|
CELE ZIELE OBJETIVOS OBJECTIVES OBJECTIFS
|
||||||
|
CENTRUM DOWODZENIA KOMMANDOZENTRUM CENTRO DE MANDO COMMAND CENTER CENTRE DE COMMANDEMENT
|
||||||
|
Celne oko Scharfes Auge Ojo certero Keen eye Œil précis
|
||||||
|
Chmury i wiatr Wolken und Wind Nubes y viento Clouds and wind Nuages et vent
|
||||||
|
Cmentarz maszyn Maschinenfriedhof Cementerio de máquinas Machine graveyard Cimetière de machines
|
||||||
|
DOKUJ [L] ANDOCKEN [L] ATRACAR [L] DOCK [L] AMARRER [L]
|
||||||
|
DPS broni Waffen-DPS DPS del arma Weapon DPS DPS de l'arme
|
||||||
|
Daleka wyprawa %d Fernexpedition %d Expedición lejana %d Distant expedition %d Expédition lointaine %d
|
||||||
|
Dezorientacja celowania Zielstörung Desorientación de puntería Aim disruption Désorientation de visée
|
||||||
|
Dodaj wszystko Alles hinzufügen Añadir todo Add all Tout ajouter
|
||||||
|
Dopalacz Booster Propulsor Booster Propulseur
|
||||||
|
Dozwolone przedmioty Erlaubte Gegenstände Objetos permitidos Allowed items Objets autorisés
|
||||||
|
Drony bojowe Kampfdrohnen Drones de combate Combat drones Drones de combat
|
||||||
|
Drony naprawcze Reparaturdrohnen Drones de reparación Repair drones Drones de réparation
|
||||||
|
Dystans Distanz Distancia Distance Distance
|
||||||
|
Dzika biosfera Wilde Biosphäre Biosfera salvaje Wild biosphere Biosphère sauvage
|
||||||
|
EKWIPUNEK KAPITANA KAPITÄNSAUSRÜSTUNG INVENTARIO DEL CAPITÁN CAPTAIN INVENTORY INVENTAIRE DU CAPITAINE
|
||||||
|
ELITA ELITE ÉLITE ELITE ÉLITE
|
||||||
|
Echo dawnej cywilizacji Echo einer alten Zivilisation Eco de una civilización antigua Echo of an ancient civilization Écho d'une ancienne civilisation
|
||||||
|
Energetyczne Energie Energético Energy Énergétique
|
||||||
|
Epicki Episch Épico Epic Épique
|
||||||
|
Ewakuacja etapami Schrittweise Evakuierung Evacuación por etapas Staged evacuation Évacuation par étapes
|
||||||
|
FRACHTOWIEC FRACHTER CARGUERO FREIGHTER CARGO
|
||||||
|
Hangar · Warsztat · Magazyn Hangar · Werkstatt · Lager Hangar · Taller · Almacén Hangar · Workshop · Storage Hangar · Atelier · Stockage
|
||||||
|
FREGATA · %d FREGATTE · %d FRAGATA · %d FRIGATE · %d FRÉGATE · %d
|
||||||
|
Flary Leuchtköder Bengalas Flares Leurres
|
||||||
|
GOTOWA BEREIT LISTA READY PRÊTE
|
||||||
|
GOTOWE BEREIT LISTO READY PRÊT
|
||||||
|
GOTOWY BEREIT LISTO READY PRÊT
|
||||||
|
Jaskinia Höhle Cueva Cave Grotte
|
||||||
|
Jesienne lasy Herbstwälder Bosques otoñales Autumn forests Forêts automnales
|
||||||
|
KAJUTA %02d KABINE %02d CAMAROTE %02d CABIN %02d CABINE %02d
|
||||||
|
KRYT! KRIT! ¡CRÍT! CRIT! CRIT!
|
||||||
|
KUP %d KAUFEN %d COMPRAR %d BUY %d ACHETER %d
|
||||||
|
Kinetyczne Kinetisch Cinético Kinetic Cinétique
|
||||||
|
Kontener w ciemno Überraschungscontainer Contenedor misterioso Mystery container Conteneur mystère
|
||||||
|
Krzem Silizium Silicio Silicon Silicium
|
||||||
|
LOSUJ PRZEDMIOT · POZ. %d GEGENSTAND WÜRFELN · ST. %d SORTEAR OBJETO · NIV. %d ROLL ITEM · LV. %d TIRER UN OBJET · NIV. %d
|
||||||
|
LPM LMT Botón izquierdo LMB Bouton gauche
|
||||||
|
Legendarny Legendär Legendario Legendary Légendaire
|
||||||
|
Losowa Zufällig Aleatoria Random Aléatoire
|
||||||
|
MAGAZYN LAGER ALMACÉN STORAGE STOCKAGE
|
||||||
|
MAGAZYN FRACHTOWCA FRACHTERLAGER ALMACÉN DEL CARGUERO FREIGHTER STORAGE STOCKAGE DU CARGO
|
||||||
|
MIEJSCE ODKRYTE ORT ENTDECKT LUGAR DESCUBIERTO LOCATION DISCOVERED LIEU DÉCOUVERT
|
||||||
|
Magazyn fregaty Fregattenlager Almacén de fragata Frigate storage Stockage de la frégate
|
||||||
|
Mechanik Mechaniker Mecánico Mechanic Mécanicien
|
||||||
|
Miny Minen Minas Mines Mines
|
||||||
|
Mobilny serwis Mobiler Service Servicio móvil Mobile repairs Réparations mobiles
|
||||||
|
NAPRAWA REPARATUR REPARACIÓN REPAIR RÉPARATION
|
||||||
|
NATYCHMIAST SOFORT INSTANTÁNEO INSTANT IMMÉDIAT
|
||||||
|
NORMALNY NORMAL NORMAL NORMAL NORMAL
|
||||||
|
Napraw Reparieren Reparar Repair Réparer
|
||||||
|
Napromieniowana amunicja Strahlungsmunition Munición irradiada Irradiated ammunition Munitions irradiées
|
||||||
|
Niepospolity Ungewöhnlich Poco común Uncommon Inhabituel
|
||||||
|
Nieznana planeta Unbekannter Planet Planeta desconocido Unknown planet Planète inconnue
|
||||||
|
Nikiel Nickel Níquel Nickel Nickel
|
||||||
|
ODLOT [L] ABFLUG [L] PARTIR [L] DEPART [L] DÉPART [L]
|
||||||
|
ODWIEDZONO BESUCHT VISITADO VISITED VISITÉ
|
||||||
|
OPERACYJNY BETRIEBSBEREIT OPERATIVO OPERATIONAL OPÉRATIONNEL
|
||||||
|
OSTATNI BASTION LETZTE BASTION ÚLTIMO BASTIÓN LAST BASTION DERNIER BASTION
|
||||||
|
Odbierz Abholen Recoger Collect Récupérer
|
||||||
|
Odblokuj 1 slot · 1 Slot freischalten · Desbloquear 1 ranura · Unlock 1 slot · Débloquer 1 emplacement ·
|
||||||
|
Oddychanie Atmung Respiración Breathing Respiration
|
||||||
|
Odzysk tarcz z obr. Schilde aus Schaden Escudos por daño Shields from damage Boucliers par dégâts
|
||||||
|
Opuszczona wioska Verlassenes Dorf Aldea abandonada Abandoned village Village abandonné
|
||||||
|
Opuszczony magazyn Verlassenes Lager Almacén abandonado Abandoned warehouse Entrepôt abandonné
|
||||||
|
Orb awansu Aufwertungsorb Orbe de mejora Upgrade orb Orbe d'amélioration
|
||||||
|
Orb dopalacza Booster-Orb Orbe propulsor Booster orb Orbe propulseur
|
||||||
|
Orb kinetyczny Kinetischer Orb Orbe cinético Kinetic orb Orbe cinétique
|
||||||
|
Orb polaryzacyjny Polarisationsorb Orbe de polaridad Polarization orb Orbe de polarisation
|
||||||
|
Orb przebicia Durchschlag-Orb Orbe perforante Piercing orb Orbe perforant
|
||||||
|
Orb radiacji Strahlungsorb Orbe radiactivo Radiation orb Orbe radiatif
|
||||||
|
Orb replikacji Replikationsorb Orbe de réplica Replication orb Orbe de réplication
|
||||||
|
Ostatni bastion Letzte Bastion Último bastión Last bastion Dernier bastion
|
||||||
|
PARAMETRY PARAMETER PARÁMETROS PARAMETERS PARAMÈTRES
|
||||||
|
PASYWNA PASSIV PASIVA PASSIVE PASSIVE
|
||||||
|
PASYWNE PASSIV PASIVAS PASSIVE PASSIF
|
||||||
|
POZ. %d ST. %d NIV. %d LV. %d NIV. %d
|
||||||
|
PPM RMT Botón derecho RMB Bouton droit
|
||||||
|
PROCEDURA AWARYJNA NOTFALLPROZEDUR PROCEDIMIENTO DE EMERGENCIA EMERGENCY PROCEDURE PROCÉDURE D'URGENCE
|
||||||
|
PRODUKCJA HERSTELLUNG FABRICACIÓN CRAFTING FABRICATION
|
||||||
|
PRZEDMIOT GEGENSTAND OBJETO ITEM OBJET
|
||||||
|
PRZEDMIOTY GEGENSTÄNDE OBJETOS ITEMS OBJETS
|
||||||
|
PRZYDZIEL ZUWEISEN ASIGNAR ASSIGN AFFECTER
|
||||||
|
PRZYSPIESZANIE · TRASA ZABEZPIECZONA BESCHLEUNIGEN · ROUTE GESICHERT ACELERANDO · RUTA SEGURA ACCELERATING · ROUTE SECURED ACCÉLÉRATION · ROUTE SÉCURISÉE
|
||||||
|
PUSTY LEER VACÍO EMPTY VIDE
|
||||||
|
Paliwo gotowe Treibstoff bereit Combustible listo Fuel ready Carburant prêt
|
||||||
|
Pierwsza wyprawa Erste Expedition Primera expedición First expedition Première expédition
|
||||||
|
Planety i frachtowiec Planeten und Frachter Planetas y carguero Planets and freighter Planètes et cargo
|
||||||
|
Pojemne kondensatory Große Kondensatoren Condensadores amplios Large capacitors Grands condensateurs
|
||||||
|
Pokonaj bossa Boss besiegen Derrota al jefe Defeat the boss Vaincre le boss
|
||||||
|
Posiadane Vorhanden Disponible Owned Disponible
|
||||||
|
Powerbank Energiebank Batería Power bank Batterie
|
||||||
|
Powerbanki Energiebanken Baterías Power banks Batteries
|
||||||
|
Poz. %d St. %d Niv. %d Lv. %d Niv. %d
|
||||||
|
Przyspieszenie Beschleunigung Aceleración Acceleration Accélération
|
||||||
|
Pusta stocznia Leere Werft Astillero vacío Empty shipyard Chantier naval vide
|
||||||
|
Pusty slot Leerer Slot Ranura vacía Empty slot Emplacement vide
|
||||||
|
REPLIKUJ REPLIZIEREN REPLICAR REPLICATE RÉPLIQUER
|
||||||
|
ROZBUDOWA STATKU SCHIFFSAUSBAU AMPLIACIÓN DE NAVE SHIP EXPANSION AGRANDISSEMENT DU VAISSEAU
|
||||||
|
ROZPOCZNIJ BADANIE · %d s FORSCHUNG STARTEN · %d s INICIAR INVESTIGACIÓN · %d s START RESEARCH · %d s LANCER LA RECHERCHE · %d s
|
||||||
|
ROZPROSZENIE SALWY SALVENSTREUUNG DISPERSIÓN DE SALVA SALVO DISPERSION DISPERSION DE SALVE
|
||||||
|
ROZSZ. [%d] ERW. [%d] EXT. [%d] EXT. [%d] EXT. [%d]
|
||||||
|
ROZSZERZENIA ERWEITERUNGEN EXTENSIONES EXTENSIONS EXTENSIONS
|
||||||
|
ROZSZERZENIE ERWEITERUNG EXTENSIÓN EXTENSION EXTENSION
|
||||||
|
Radiacyjna Strahlung Irradiada Irradiated Irradiée
|
||||||
|
Radiacyjne Strahlung Radiativo Radiation Radiatif
|
||||||
|
Receptura Rezept Receta Recipe Recette
|
||||||
|
Recykler Recycler Reciclador Recycler Recycleur
|
||||||
|
Regener. energii Energiereg. Regen. energía Energy regen. Régén. énergie
|
||||||
|
Regener. tarcz Schildreg. Regen. escudos Shield regen. Régén. boucliers
|
||||||
|
Regeneracja energii Energieregeneration Regeneración de energía Energy regeneration Régénération d'énergie
|
||||||
|
Regeneracja tarcz Schildregeneration Regeneración de escudos Shield regeneration Régénération des boucliers
|
||||||
|
Rozpad konstrukcji Strukturzerfall Colapso estructural Structural collapse Effondrement structurel
|
||||||
|
Rozproszenie salwy Salvenstreuung Dispersión de salva Salvo dispersion Dispersion de salve
|
||||||
|
Rozszerzenia Erweiterungen Extensiones Extensions Extensions
|
||||||
|
Rozszerzenie Erweiterung Extensión Extension Extension
|
||||||
|
Rykoszet Abpraller Rebote Ricochet Ricochet
|
||||||
|
Rzadki Selten Raro Rare Rare
|
||||||
|
SEKCJA 02 SEKTION 02 SECCIÓN 02 SECTION 02 SECTION 02
|
||||||
|
SEKCJA 03 SEKTION 03 SECCIÓN 03 SECTION 03 SECTION 03
|
||||||
|
SEKCJA 04 SEKTION 04 SECCIÓN 04 SECTION 04 SECTION 04
|
||||||
|
SEKCJA ROZWOJOWA AUSBAUSEKTION SECCIÓN DE EXPANSIÓN EXPANSION SECTION SECTION D'AGRANDISSEMENT
|
||||||
|
SKOK WARP WARPSPRUNG SALTO WARP WARP JUMP SAUT WARP
|
||||||
|
SLOT %d SLOT %d RANURA %d SLOT %d EMPLACEMENT %d
|
||||||
|
STATYSTYKI STATKU SCHIFFSSTATISTIK ESTADÍSTICAS DE NAVE SHIP STATISTICS STATISTIQUES DU VAISSEAU
|
||||||
|
SUROWCE ROHSTOFFE RECURSOS RESOURCES RESSOURCES
|
||||||
|
SUROWCE Z ASTEROID ASTEROIDENROHSTOFFE RECURSOS DE ASTEROIDES ASTEROID RESOURCES RESSOURCES D'ASTÉROÏDES
|
||||||
|
Sektor dodany do listy wypraw na frachtowcu. Mapa pozwala na jeden lot. Sektor zur Expeditionsliste hinzugefügt. Karte erlaubt einen Flug. Sector añadido a expediciones. El mapa permite un vuelo. Sector added to the expedition list. Map allows one flight. Secteur ajouté aux expéditions. La carte permet un vol.
|
||||||
|
Skafander Raumanzug Traje espacial Spacesuit Combinaison spatiale
|
||||||
|
Slot zablokowany • Odblokuj w hangarze Slot gesperrt • Im Hangar freischalten Ranura bloqueada • Desbloquea en hangar Slot locked • Unlock in hangar Emplacement bloqué • Débloquez au hangar
|
||||||
|
Spotkanie Begegnung Encuentro Encounter Rencontre
|
||||||
|
Statystyki Statistik Estadísticas Statistics Statistiques
|
||||||
|
Sterowanie Steuerung Controles Controls Commandes
|
||||||
|
Strzelec Schütze Artillero Gunner Tireur
|
||||||
|
Suche kaniony Trockene Canyons Cañones secos Dry canyons Canyons arides
|
||||||
|
Surowiec pozyskiwany z asteroid. Rohstoff aus Asteroiden. Recurso de asteroides. Resource mined from asteroids. Ressource extraite d'astéroïdes.
|
||||||
|
Surowiec z asteroid. Do produkcji amunicji i rakiet. Asteroidenrohstoff für Munition und Raketen. Recurso de asteroides para munición y misiles. Asteroid resource used for ammunition and missiles. Ressource d'astéroïdes pour munitions et missiles.
|
||||||
|
Surowiec z asteroid. Do produkcji napromieniowanej amunicji. Asteroidenrohstoff für Strahlungsmunition. Recurso de asteroides para munición irradiada. Asteroid resource used for irradiated ammunition. Ressource d'astéroïdes pour munitions irradiées.
|
||||||
|
System obrony przed obcymi Alienabwehrsystem Sistema de defensa alienígena Alien defense system Système de défense contre les aliens
|
||||||
|
System oddychania Atemsystem Sistema respiratorio Breathing system Système respiratoire
|
||||||
|
Szansa na krytyk Kritische Chance Probabilidad crítica Critical chance Chance critique
|
||||||
|
Szansa na trafienie krytyczne Kritische Trefferchance Probabilidad de impacto crítico Critical hit chance Chance de coup critique
|
||||||
|
Szansa na unik Ausweichchance Probabilidad de evasión Evasion chance Chance d'esquive
|
||||||
|
TARCZA SCHILD ESCUDO SHIELD BOUCLIER
|
||||||
|
TARCZA AWARYJNA NOTSCHILD ESCUDO DE EMERGENCIA EMERGENCY SHIELD BOUCLIER D'URGENCE
|
||||||
|
TEMPERATURA TEMPERATUR TEMPERATURA TEMPERATURE TEMPÉRATURE
|
||||||
|
TLEN SAUERSTOFF OXÍGENO OXYGEN OXYGÈNE
|
||||||
|
Taran Rammen Embestida Ram Éperonnage
|
||||||
|
Tarcza awaryjna Notschild Escudo de emergencia Emergency shield Bouclier d'urgence
|
||||||
|
Test prototypu Prototyptest Prueba de prototipo Prototype test Test de prototype
|
||||||
|
Tlen %d · Temp. %d · Fauna %d pp Sauerstoff %d · Temp. %d · Fauna %d pp Oxígeno %d · Temp. %d · Fauna %d pp Oxygen %d · Temp. %d · Fauna %d pp Oxygène %d · Temp. %d · Faune %d pp
|
||||||
|
ULEPSZ DO %s AUFWERTEN AUF %s MEJORAR A %s UPGRADE TO %s AMÉLIORER VERS %s
|
||||||
|
ULEPSZENIE %s → %s AUFWERTUNG %s → %s MEJORA %s → %s UPGRADE %s → %s AMÉLIORATION %s → %s
|
||||||
|
UNIK AUSGEWICHEN EVASIÓN EVADE ESQUIVE
|
||||||
|
UZBROJENIE BEWAFFNUNG ARMAMENTO ARMAMENT ARMEMENT
|
||||||
|
Ulewa Starkregen Lluvia intensa Downpour Pluie torrentielle
|
||||||
|
W REMONCIE IM UMBAU EN OBRAS UNDER CONSTRUCTION EN TRAVAUX
|
||||||
|
WIRUS VIRUS VIRUS VIRUS VIRUS
|
||||||
|
WOLNA KAJUTA FREIE KABINE CAMAROTE LIBRE FREE CABIN CABINE LIBRE
|
||||||
|
WORMHOLE OTWARTY WURMLOCH OFFEN AGUJERO DE GUSANO ABIERTO WORMHOLE OPEN TROU DE VER OUVERT
|
||||||
|
WROGOWIE GEGNER ENEMIGOS ENEMIES ENNEMIS
|
||||||
|
WYBIERZ WÄHLEN ELEGIR SELECT CHOISIR
|
||||||
|
Walka i przetrwanie Kampf und Überleben Combate y supervivencia Combat and survival Combat et survie
|
||||||
|
Wiedza o broni Waffenwissen Conocimiento de armas Weapon knowledge Connaissance des armes
|
||||||
|
Wiedza o tarczach Schildwissen Conocimiento de escudos Shield knowledge Connaissance des boucliers
|
||||||
|
Wirus Virus Virus Virus Virus
|
||||||
|
Wolfram Wolfram Wolframio Tungsten Tungstène
|
||||||
|
Wolny slot Freier Slot Ranura libre Free slot Emplacement libre
|
||||||
|
Wrak konwoju Konvoiwrack Pecio de convoy Convoy wreck Épave de convoi
|
||||||
|
Wrak statku Schiffswrack Pecio de nave Shipwreck Épave
|
||||||
|
Wybierz tajemniczy pakiet Überraschungspaket wählen Elegir paquete misterioso Choose mystery package Choisir le paquet mystère
|
||||||
|
Wymagane 70% maksymalnej energii 70% maximaler Energie erforderlich Requiere 70% de energía máxima Requires 70% maximum energy Nécessite 70% d'énergie maximale
|
||||||
|
Wymagane min. 25% tarcz Mindestens 25% Schilde erforderlich Requiere al menos 25% de escudos Requires at least 25% shields Nécessite au moins 25% de boucliers
|
||||||
|
Wymagany aktywny lot Aktiver Flug erforderlich Requiere vuelo activo Requires active flight Vol actif requis
|
||||||
|
Wyprawa %d Expedition %d Expedición %d Expedition %d Expédition %d
|
||||||
|
Wyrzutnia rakiet naprowadzanych Lenkraketenwerfer Lanzamisiles guiados Guided missile launcher Lance-missiles guidés
|
||||||
|
Wyrzutnia rakiet niekierowanych Ungelenkter Raketenwerfer Lanzacohetes no guiados Unguided rocket launcher Lance-roquettes non guidées
|
||||||
|
Wzmocnione poszycie Verstärkte Hülle Revestimiento reforzado Reinforced plating Revêtement renforcé
|
||||||
|
ZAMKNIJ [ESC] SCHLIESSEN [ESC] CERRAR [ESC] CLOSE [ESC] FERMER [ÉCHAP]
|
||||||
|
ZAMONTOWANE NA STATKU AUF SCHIFF EINGEBAUT INSTALADO EN NAVE INSTALLED ON SHIP INSTALLÉ SUR LE VAISSEAU
|
||||||
|
ZAOPATRZENIE VERSORGUNG SUMINISTROS SUPPLIES RAVITAILLEMENT
|
||||||
|
ZAPASY VORRÄTE RESERVAS STOCK RÉSERVES
|
||||||
|
ZAPASY GRACZA SPIELERVORRÄTE RESERVAS DEL JUGADOR PLAYER SUPPLIES RÉSERVES DU JOUEUR
|
||||||
|
ZBUDOWANO GEBAUT CONSTRUIDO BUILT CONSTRUIT
|
||||||
|
ZDOBYTO ERHALTEN OBTENIDO ACQUIRED OBTENU
|
||||||
|
ZMIANY PO WYMIANIE BRONI ÄNDERUNGEN BEIM WAFFENTAUSCH CAMBIOS AL CAMBIAR ARMA CHANGES AFTER WEAPON SWAP CHANGEMENTS APRÈS REMPLACEMENT
|
||||||
|
ZWIADEK • TARCZE SPÄHER • SCHILDE EXPLORADOR • ESCUDOS SCOUT • SHIELDS ÉCLAIREUR • BOUCLIERS
|
||||||
|
Zabezpiecz schronienie Unterkunft sichern Asegurar refugio Secure the shelter Sécuriser l'abri
|
||||||
|
Zablokowany Gesperrt Bloqueado Locked Verrouillé
|
||||||
|
Zakres i skalowanie Bereich und Skalierung Intervalo y escalado Range and scaling Plage et progression
|
||||||
|
Zamknij okno statku Schiffsfenster schließen Cerrar ventana de nave Close ship window Fermer la fenêtre du vaisseau
|
||||||
|
Zielone doliny Grüne Täler Valles verdes Green valleys Vallées verdoyantes
|
||||||
|
Zimna biosfera Kalte Biosphäre Biosfera fría Cold biosphere Biosphère froide
|
||||||
|
Zapis przywraca początek bieżącego poziomu. Cooldowny i efekty czasowe są zerowane. Laden startet das aktuelle Level neu. Abklingzeiten und temporäre Effekte werden zurückgesetzt. Cargar reinicia el nivel actual. Se reinician recargas y efectos temporales. Loading restarts the current level. Cooldowns and temporary effects are reset. Le chargement reprend au début du niveau actuel. Recharges et effets temporaires sont réinitialisés.
|
||||||
|
Dopasuj poziom sprzętu do planety. Passe die Ausrüstungsstufe dem Planeten an. Adapta el nivel del equipo al planeta. Match equipment level to the planet. Adaptez le niveau de l’équipement à la planète.
|
||||||
|
Wymagany poziom kapitana: %d Erforderliche Kapitänsstufe: %d Nivel de capitán requerido: %d Required captain level: %d Niveau de capitaine requis : %d
|
||||||
|
Czas badania: 10 minut gry Forschungsdauer: 10 Spielminuten Tiempo de investigación: 10 minutos de juego Research time: 10 minutes of play Durée de recherche : 10 minutes de jeu
|
||||||
|
@ -23,7 +23,7 @@ func _draw() -> void:
|
|||||||
draw_polyline(hexagon,Color(tint,0.045*pulse),0.7,true)
|
draw_polyline(hexagon,Color(tint,0.045*pulse),0.7,true)
|
||||||
# Counter-rotate the readout so it stays legible as the ship turns.
|
# Counter-rotate the readout so it stays legible as the ship turns.
|
||||||
draw_set_transform(Vector2.ZERO,-global_rotation)
|
draw_set_transform(Vector2.ZERO,-global_rotation)
|
||||||
draw_string(ThemeDB.fallback_font,Vector2(-65,-shield_radius-12),"OSŁONA %.0f / %.0f" % [current_shields,max_shields],HORIZONTAL_ALIGNMENT_CENTER,130,11,Color("d7bfff"))
|
draw_string(ThemeDB.fallback_font,Vector2(-65,-shield_radius-12), tr("OSŁONA %.0f / %.0f" % [current_shields,max_shields]),HORIZONTAL_ALIGNMENT_CENTER,130,11,Color("d7bfff"))
|
||||||
draw_set_transform(Vector2.ZERO)
|
draw_set_transform(Vector2.ZERO)
|
||||||
# Keep the existing directional impact ripples on the larger perimeter.
|
# Keep the existing directional impact ripples on the larger perimeter.
|
||||||
if not _hits.is_empty(): _draw_impacts()
|
if not _hits.is_empty(): _draw_impacts()
|
||||||
|
|||||||
@ -27,6 +27,7 @@ var _pending_boss: Dictionary = {}
|
|||||||
var _boss_spawned := false
|
var _boss_spawned := false
|
||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
|
_finish_save_setup.call_deferred()
|
||||||
if not GameState.active_distant_map.is_empty():
|
if not GameState.active_distant_map.is_empty():
|
||||||
var distant := Node.new()
|
var distant := Node.new()
|
||||||
distant.set_script(preload("res://scripts/game/distant_sector.gd"))
|
distant.set_script(preload("res://scripts/game/distant_sector.gd"))
|
||||||
@ -69,6 +70,14 @@ func _ready() -> void:
|
|||||||
player.position = expeditions.freighter.position
|
player.position = expeditions.freighter.position
|
||||||
expeditions.open_freighter.call_deferred()
|
expeditions.open_freighter.call_deferred()
|
||||||
|
|
||||||
|
func _finish_save_setup() -> void:
|
||||||
|
var layer := CanvasLayer.new()
|
||||||
|
layer.name = "SessionMenu"
|
||||||
|
layer.layer = 120
|
||||||
|
layer.set_script(preload("res://scripts/ui/session_menu.gd"))
|
||||||
|
add_child(layer)
|
||||||
|
GameState.save_game()
|
||||||
|
|
||||||
func _spawn_celestial_bodies() -> void:
|
func _spawn_celestial_bodies() -> void:
|
||||||
var bodies := Node2D.new()
|
var bodies := Node2D.new()
|
||||||
bodies.name = "CelestialBodies"
|
bodies.name = "CelestialBodies"
|
||||||
|
|||||||
77
scripts/game/game_settings.gd
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
extends Node
|
||||||
|
|
||||||
|
signal settings_changed
|
||||||
|
const PATH := "user://settings.cfg"
|
||||||
|
const INTERFACE_TRANSLATION := preload("res://scripts/game/interface_translation.gd")
|
||||||
|
const LOCALES := ["pl", "de", "es", "en", "fr"]
|
||||||
|
const CATALOGS := {
|
||||||
|
"de": preload("res://resources/localization/de_catalog.gd").MESSAGES,
|
||||||
|
"es": preload("res://resources/localization/es_catalog.gd").MESSAGES,
|
||||||
|
"en": preload("res://resources/localization/en_catalog.gd").MESSAGES,
|
||||||
|
"fr": preload("res://resources/localization/fr_catalog.gd").MESSAGES,
|
||||||
|
}
|
||||||
|
const LANGUAGES := ["Polski", "Deutsch", "Español", "English", "Français"]
|
||||||
|
const RESOLUTIONS := [Vector2i(1024,576), Vector2i(1280,720), Vector2i(1600,900), Vector2i(1920,1080), Vector2i(2560,1440), Vector2i(3840,2160)]
|
||||||
|
var volume := 0.8
|
||||||
|
var music_volume := 0.8
|
||||||
|
var resolution := Vector2i(1280,720)
|
||||||
|
var fullscreen := false
|
||||||
|
var locale := "pl"
|
||||||
|
var _translations: Array[Translation] = []
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
process_mode = Node.PROCESS_MODE_ALWAYS
|
||||||
|
_load_translations()
|
||||||
|
var config := ConfigFile.new()
|
||||||
|
if config.load(PATH) == OK:
|
||||||
|
volume = clampf(float(config.get_value("audio", "master", 0.8)), 0, 1)
|
||||||
|
music_volume = clampf(float(config.get_value("audio", "music", 0.8)), 0, 1)
|
||||||
|
var stored: Variant = config.get_value("display", "resolution", Vector2i(1280,720))
|
||||||
|
if stored is Vector2i and stored in RESOLUTIONS: resolution = stored
|
||||||
|
fullscreen = bool(config.get_value("display", "fullscreen", false))
|
||||||
|
locale = str(config.get_value("language", "locale", "pl"))
|
||||||
|
if locale not in LOCALES: locale = "pl"
|
||||||
|
apply()
|
||||||
|
|
||||||
|
func _load_translations() -> void:
|
||||||
|
for code in LOCALES:
|
||||||
|
var catalog: Dictionary = CATALOGS.get(code, {})
|
||||||
|
var translation := INTERFACE_TRANSLATION.new()
|
||||||
|
translation.configure(code, catalog)
|
||||||
|
TranslationServer.add_translation(translation)
|
||||||
|
_translations.append(translation)
|
||||||
|
|
||||||
|
func _exit_tree() -> void:
|
||||||
|
# Unregister scripted callbacks before Godot tears down script resources.
|
||||||
|
for translation in _translations: TranslationServer.remove_translation(translation)
|
||||||
|
_translations.clear()
|
||||||
|
|
||||||
|
func apply() -> void:
|
||||||
|
AudioServer.set_bus_volume_db(0, linear_to_db(maxf(volume, 0.0001)))
|
||||||
|
AudioServer.set_bus_mute(0, volume <= 0.0)
|
||||||
|
var music_bus := AudioServer.get_bus_index("Music")
|
||||||
|
if music_bus < 0:
|
||||||
|
AudioServer.add_bus()
|
||||||
|
music_bus = AudioServer.bus_count - 1
|
||||||
|
AudioServer.set_bus_name(music_bus, "Music")
|
||||||
|
AudioServer.set_bus_send(music_bus, "Master")
|
||||||
|
AudioServer.set_bus_volume_db(music_bus, linear_to_db(maxf(music_volume, 0.0001)))
|
||||||
|
AudioServer.set_bus_mute(music_bus, music_volume <= 0.0)
|
||||||
|
TranslationServer.set_locale(locale)
|
||||||
|
if DisplayServer.get_name() != "headless":
|
||||||
|
DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_FULLSCREEN if fullscreen else DisplayServer.WINDOW_MODE_WINDOWED)
|
||||||
|
if not fullscreen:
|
||||||
|
var available := DisplayServer.screen_get_usable_rect()
|
||||||
|
var actual := Vector2i(mini(resolution.x, available.size.x), mini(resolution.y, available.size.y))
|
||||||
|
DisplayServer.window_set_size(actual)
|
||||||
|
DisplayServer.window_set_position(available.position + (available.size - actual) / 2)
|
||||||
|
settings_changed.emit()
|
||||||
|
|
||||||
|
func save_settings() -> Error:
|
||||||
|
var config := ConfigFile.new()
|
||||||
|
config.set_value("audio", "master", volume)
|
||||||
|
config.set_value("audio", "music", music_volume)
|
||||||
|
config.set_value("display", "resolution", resolution)
|
||||||
|
config.set_value("display", "fullscreen", fullscreen)
|
||||||
|
config.set_value("language", "locale", locale)
|
||||||
|
return config.save(PATH)
|
||||||
1
scripts/game/game_settings.gd.uid
Normal file
@ -0,0 +1 @@
|
|||||||
|
uid://cbe4mi5lsyllc
|
||||||
@ -20,6 +20,27 @@ var explored_pois: Dictionary = {}
|
|||||||
var asteroid_retry_seeds: Dictionary = {}
|
var asteroid_retry_seeds: Dictionary = {}
|
||||||
var exploration_wreck_bonuses: Dictionary = {}
|
var exploration_wreck_bonuses: Dictionary = {}
|
||||||
var hud_panel_state: Dictionary = {}
|
var hud_panel_state: Dictionary = {}
|
||||||
|
const SAVES := preload("res://scripts/game/save_service.gd")
|
||||||
|
var _autosave_time := 0.0
|
||||||
|
var last_save_error: Error = OK
|
||||||
|
|
||||||
|
func save_game() -> Error:
|
||||||
|
last_save_error = SAVES.write(self, get_tree().current_scene)
|
||||||
|
return last_save_error
|
||||||
|
|
||||||
|
func has_save() -> bool:
|
||||||
|
return SAVES.available()
|
||||||
|
|
||||||
|
func continue_game() -> bool:
|
||||||
|
return SAVES.restore_state(self)
|
||||||
|
|
||||||
|
func save_named_game(save_name: String, slot_id: String = "") -> Error:
|
||||||
|
if save_name.strip_edges().is_empty(): return ERR_INVALID_PARAMETER
|
||||||
|
last_save_error = SAVES.write(self, get_tree().current_scene, save_name, slot_id)
|
||||||
|
return last_save_error
|
||||||
|
|
||||||
|
func load_game(slot_id: String) -> bool:
|
||||||
|
return SAVES.restore_state(self, slot_id)
|
||||||
|
|
||||||
func depart_distant(map_id: String) -> bool:
|
func depart_distant(map_id: String) -> bool:
|
||||||
if not active_distant_map.is_empty() or not captain.expedition.distant_maps.has(map_id): return false
|
if not active_distant_map.is_empty() or not captain.expedition.distant_maps.has(map_id): return false
|
||||||
@ -63,6 +84,7 @@ func reset_current_system_exploration() -> void:
|
|||||||
explored_pois.erase(id)
|
explored_pois.erase(id)
|
||||||
|
|
||||||
func start_new_run() -> void:
|
func start_new_run() -> void:
|
||||||
|
_autosave_time = 0.0
|
||||||
hull_bastion_used = false
|
hull_bastion_used = false
|
||||||
captain = CAPTAIN_PROGRESS.new()
|
captain = CAPTAIN_PROGRESS.new()
|
||||||
system_level = 1
|
system_level = 1
|
||||||
@ -101,6 +123,12 @@ func seed_for_system(level: int) -> int:
|
|||||||
|
|
||||||
func _process(delta: float) -> void:
|
func _process(delta: float) -> void:
|
||||||
advance_play_time(delta, get_tree().current_scene)
|
advance_play_time(delta, get_tree().current_scene)
|
||||||
|
var scene := get_tree().current_scene
|
||||||
|
if scene == null or not scene.has_node("PlayerShip"): return
|
||||||
|
_autosave_time += delta
|
||||||
|
if _autosave_time >= 60.0 and not captain.expedition.active:
|
||||||
|
_autosave_time = 0.0
|
||||||
|
save_game()
|
||||||
|
|
||||||
func advance_play_time(delta: float, scene: Node) -> void:
|
func advance_play_time(delta: float, scene: Node) -> void:
|
||||||
if scene == null or not scene.has_node("PlayerShip"): return
|
if scene == null or not scene.has_node("PlayerShip"): return
|
||||||
@ -109,6 +137,12 @@ func advance_play_time(delta: float, scene: Node) -> void:
|
|||||||
var location_open := expedition != null and is_instance_valid(expedition.screen)
|
var location_open := expedition != null and is_instance_valid(expedition.screen)
|
||||||
if get_tree().paused and not location_open: return
|
if get_tree().paused and not location_open: return
|
||||||
var researching := preload("res://scripts/planets/laboratory.gd").advance(captain.expedition,delta)
|
var researching := preload("res://scripts/planets/laboratory.gd").advance(captain.expedition,delta)
|
||||||
|
var alien_was_active: bool = not captain.expedition.alien_project.is_empty()
|
||||||
|
researching = preload("res://scripts/planets/alien_research.gd").advance(captain.expedition,delta) or researching
|
||||||
|
if alien_was_active and captain.expedition.alien_project.is_empty():
|
||||||
|
captain.emit_changed()
|
||||||
|
var inventory := scene.get_node_or_null("PlayerShip/ShipInventory")
|
||||||
|
if inventory != null: inventory._recalculate_ship_stats()
|
||||||
var network := preload("res://scripts/planets/mining_network.gd")
|
var network := preload("res://scripts/planets/mining_network.gd")
|
||||||
if network.advance(captain.expedition, delta) <= 0 and not researching: return
|
if network.advance(captain.expedition, delta) <= 0 and not researching: return
|
||||||
_production_signal_time += delta
|
_production_signal_time += delta
|
||||||
|
|||||||
96
scripts/game/interface_translation.gd
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
extends Translation
|
||||||
|
## Matches formatted legacy text as well as ordinary Godot translation keys.
|
||||||
|
var catalog_messages: Dictionary = {}
|
||||||
|
var _cache: Dictionary = {}
|
||||||
|
var _patterns: Array[Dictionary] = []
|
||||||
|
var _case_messages: Dictionary = {}
|
||||||
|
var _letters := RegEx.create_from_string("[\\p{L}]")
|
||||||
|
|
||||||
|
func configure(code: String, catalog: Dictionary) -> void:
|
||||||
|
locale = code
|
||||||
|
catalog_messages = catalog
|
||||||
|
for key: String in catalog:
|
||||||
|
_case_messages[key.to_upper()] = str(catalog[key]).to_upper()
|
||||||
|
_case_messages[key.to_lower()] = str(catalog[key]).to_lower()
|
||||||
|
var keys := catalog.keys()
|
||||||
|
keys.sort_custom(func(a: String, b: String) -> bool: return a.length() > b.length())
|
||||||
|
for key: String in keys:
|
||||||
|
if key.length() < 4: continue
|
||||||
|
var expression := ""
|
||||||
|
var tokens: Array[String] = []
|
||||||
|
var placeholder := RegEx.create_from_string("%(?:[0-9]*(?:\\.[0-9]+)?[sdif]|%)")
|
||||||
|
var offset := 0
|
||||||
|
for found in placeholder.search_all(key):
|
||||||
|
expression += _escape(key.substr(offset, found.get_start()-offset))
|
||||||
|
var token := found.get_string()
|
||||||
|
if token == "%%": expression += "%"
|
||||||
|
else:
|
||||||
|
tokens.append(token)
|
||||||
|
if token.ends_with("s"):
|
||||||
|
expression += "([^\\n]+)" if found.get_end() == key.length() else "([^\\n]+?)"
|
||||||
|
else: expression += "([-+]?[0-9]+(?:[.,][0-9]+)?)"
|
||||||
|
offset = found.get_end()
|
||||||
|
expression += _escape(key.substr(offset))
|
||||||
|
if expression.is_empty(): continue
|
||||||
|
# Word boundaries avoid replacing a noun inside a longer Polish word.
|
||||||
|
var start := "(?<![\\p{L}\\p{N}_])" if key.left(1).is_valid_identifier() else ""
|
||||||
|
var end := "(?![\\p{L}\\p{N}_])" if key.right(1).is_valid_identifier() else ""
|
||||||
|
var regex := RegEx.create_from_string(start+expression+end)
|
||||||
|
var hint := ""
|
||||||
|
for part in placeholder.sub(key, "\u0001", true).split("\u0001"):
|
||||||
|
if part.length() > hint.length(): hint = part
|
||||||
|
_patterns.append({"regex":regex,"target":str(catalog[key]),"tokens":tokens,"hint":hint})
|
||||||
|
|
||||||
|
func _escape(value: String) -> String:
|
||||||
|
var result := ""
|
||||||
|
for character in value:
|
||||||
|
if character in "\\.^$|?*+()[]{}": result += "\\"
|
||||||
|
result += character
|
||||||
|
return result
|
||||||
|
|
||||||
|
func _get_message(source: StringName, _context: StringName) -> StringName:
|
||||||
|
var text := str(source)
|
||||||
|
if catalog_messages.has(text): return StringName(catalog_messages[text])
|
||||||
|
if _case_messages.has(text): return StringName(_case_messages[text])
|
||||||
|
if _cache.has(text): return StringName(_cache[text])
|
||||||
|
if text.is_empty() or _letters.search(text) == null: return source
|
||||||
|
var candidates: Array[Dictionary] = []
|
||||||
|
for pattern in _patterns:
|
||||||
|
if not text.contains(pattern.hint): continue
|
||||||
|
for found in pattern.regex.search_all(text):
|
||||||
|
var start: int = found.get_start()
|
||||||
|
var end: int = found.get_end()
|
||||||
|
var target: String = pattern.target
|
||||||
|
# Replace format specifiers in order, retaining original numeric values.
|
||||||
|
var token_regex := RegEx.create_from_string("%(?:[0-9]*(?:\\.[0-9]+)?[sdif]|%)")
|
||||||
|
var matches := token_regex.search_all(target)
|
||||||
|
var capture := 1
|
||||||
|
var rebuilt := ""
|
||||||
|
var offset := 0
|
||||||
|
for token in matches:
|
||||||
|
rebuilt += target.substr(offset, token.get_start()-offset)
|
||||||
|
if token.get_string() == "%%": rebuilt += "%"
|
||||||
|
else:
|
||||||
|
var value: String = found.get_string(capture)
|
||||||
|
rebuilt += str(_get_message(value, &"")) if token.get_string().ends_with("s") else value
|
||||||
|
capture += 1
|
||||||
|
offset = token.get_end()
|
||||||
|
rebuilt += target.substr(offset)
|
||||||
|
candidates.append({"start":start,"end":end,"value":rebuilt})
|
||||||
|
# Prefer the longest rendered phrase, then translate its captured names too.
|
||||||
|
candidates.sort_custom(func(a: Dictionary,b: Dictionary) -> bool: return int(a.end)-int(a.start) > int(b.end)-int(b.start))
|
||||||
|
var replacements: Array[Dictionary] = []
|
||||||
|
for candidate in candidates:
|
||||||
|
var overlaps := false
|
||||||
|
for replacement in replacements:
|
||||||
|
if int(candidate.start) < int(replacement.end) and int(candidate.end) > int(replacement.start):
|
||||||
|
overlaps = true
|
||||||
|
break
|
||||||
|
if not overlaps: replacements.append(candidate)
|
||||||
|
replacements.sort_custom(func(a: Dictionary,b: Dictionary) -> bool: return a.start > b.start)
|
||||||
|
for replacement in replacements:
|
||||||
|
text = text.substr(0,replacement.start)+replacement.value+text.substr(replacement.end)
|
||||||
|
if _cache.size() > 4096: _cache.clear()
|
||||||
|
_cache[str(source)] = text
|
||||||
|
return StringName(text)
|
||||||
|
|
||||||
1
scripts/game/interface_translation.gd.uid
Normal file
@ -0,0 +1 @@
|
|||||||
|
uid://dj1u2bfsnida5
|
||||||
11
scripts/game/save_data.gd
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
extends Resource
|
||||||
|
|
||||||
|
@export var version: int = 1
|
||||||
|
@export var saved_at: String = ""
|
||||||
|
@export var saved_unix: float = 0.0
|
||||||
|
@export var save_name: String = ""
|
||||||
|
@export var slot_id: String = ""
|
||||||
|
@export var state: Dictionary = {}
|
||||||
|
@export var captain: Resource
|
||||||
|
@export var inventory: Dictionary = {}
|
||||||
|
@export var skill_offers: Array[String] = []
|
||||||
1
scripts/game/save_data.gd.uid
Normal file
@ -0,0 +1 @@
|
|||||||
|
uid://cpkf3svhjov1n
|
||||||
117
scripts/game/save_service.gd
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
extends RefCounted
|
||||||
|
|
||||||
|
const DATA := preload("res://scripts/game/save_data.gd")
|
||||||
|
const PATH := "user://last_game.res"
|
||||||
|
const BACKUP := "user://last_game_backup.res"
|
||||||
|
const TEMP := "user://last_game_pending.res"
|
||||||
|
const DIRECTORY := "user://saves"
|
||||||
|
const STATE_FIELDS := ["selected_ship_path", "system_level", "system_seed", "active_distant_map", "distant_home", "highest_system", "system_seeds", "cleared_systems", "explored_pois", "asteroid_retry_seeds", "exploration_wreck_bonuses", "hud_panel_state"]
|
||||||
|
|
||||||
|
static func read_save(path: String = PATH) -> Resource:
|
||||||
|
if not FileAccess.file_exists(path): return null
|
||||||
|
var file := FileAccess.open(path, FileAccess.READ)
|
||||||
|
if file == null: return null
|
||||||
|
var header := file.get_buffer(4).get_string_from_ascii()
|
||||||
|
file.close()
|
||||||
|
if header not in ["RSRC", "RSCC"]: return null
|
||||||
|
var data := ResourceLoader.load(path, "", ResourceLoader.CACHE_MODE_IGNORE_DEEP)
|
||||||
|
if data == null or data.get_script() != DATA or data.version != 1: return null
|
||||||
|
if not data.captain is CaptainProgress or data.state.get("system_seed", 0) == 0: return null
|
||||||
|
for key in ["cargo", "weapon", "module", "extension"]:
|
||||||
|
if not data.inventory.get(key) is Array: return null
|
||||||
|
return data
|
||||||
|
|
||||||
|
static func available() -> bool:
|
||||||
|
return not list_saves().is_empty()
|
||||||
|
|
||||||
|
static func valid_slot(id: String) -> bool:
|
||||||
|
return RegEx.create_from_string("^slot_[a-zA-Z0-9_-]{1,72}$").search(id) != null
|
||||||
|
|
||||||
|
static func slot_path(id: String) -> String:
|
||||||
|
return DIRECTORY.path_join(id+".res") if valid_slot(id) else ""
|
||||||
|
|
||||||
|
static func list_saves() -> Array[Dictionary]:
|
||||||
|
var entries: Array[Dictionary] = []
|
||||||
|
var ids: Array[String] = ["auto"]
|
||||||
|
if DirAccess.dir_exists_absolute(DIRECTORY):
|
||||||
|
for file in DirAccess.get_files_at(DIRECTORY):
|
||||||
|
if not file.ends_with(".res") or file.ends_with(".pending.res"): continue
|
||||||
|
var id := file.trim_suffix(".backup.res") if file.ends_with(".backup.res") else file.trim_suffix(".res")
|
||||||
|
if valid_slot(id) and id not in ids: ids.append(id)
|
||||||
|
for id in ids:
|
||||||
|
var path := PATH if id == "auto" else slot_path(id)
|
||||||
|
var backup := BACKUP if id == "auto" else path.trim_suffix(".res")+".backup.res"
|
||||||
|
var data := read_save(path)
|
||||||
|
var recovered := false
|
||||||
|
if data == null:
|
||||||
|
data = read_save(backup)
|
||||||
|
recovered = data != null
|
||||||
|
if data == null: continue
|
||||||
|
var timestamp: float = data.saved_unix if data.saved_unix > 0 else float(FileAccess.get_modified_time(backup if recovered else path))
|
||||||
|
entries.append({"id":id,"path":backup if recovered else path,"name":data.save_name if not data.save_name.is_empty() else ("Automatyczny zapis" if id == "auto" else "Zapis rozgrywki"),"saved_at":data.saved_at,"timestamp":timestamp,"level":int(data.state.system_level),"captain_level":data.captain.level,"credits":data.captain.credits,"ship_path":str(data.state.get("selected_ship_path","")),"recovered":recovered})
|
||||||
|
entries.sort_custom(func(a: Dictionary,b: Dictionary) -> bool: return float(a.timestamp) > float(b.timestamp))
|
||||||
|
return entries
|
||||||
|
|
||||||
|
static func write(state: Node, game: Node, save_name: String = "", id: String = "") -> Error:
|
||||||
|
var named := not save_name.is_empty()
|
||||||
|
if named and (save_name.strip_edges().is_empty() or save_name.length() > 48): return ERR_INVALID_PARAMETER
|
||||||
|
if not id.is_empty() and (not named or not valid_slot(id)): return ERR_INVALID_PARAMETER
|
||||||
|
if game == null or not game.has_node("PlayerShip") or bool(game.get("_transitioning")): return ERR_UNAVAILABLE
|
||||||
|
var ship := game.get_node("PlayerShip")
|
||||||
|
if bool(ship.get("_is_destroyed")): return ERR_UNAVAILABLE
|
||||||
|
var data := DATA.new()
|
||||||
|
data.saved_at = Time.get_datetime_string_from_system()
|
||||||
|
data.saved_unix = Time.get_unix_time_from_system()
|
||||||
|
data.save_name = save_name.strip_edges() if named else "Automatyczny zapis"
|
||||||
|
data.slot_id = id if not id.is_empty() else ("slot_%d_%08x" % [Time.get_ticks_usec(),randi()] if named else "auto")
|
||||||
|
for key in STATE_FIELDS: data.state[key] = state.get(key)
|
||||||
|
data.captain = state.captain.duplicate(true)
|
||||||
|
data.captain.skill_offers.assign(state.captain.skill_offers)
|
||||||
|
# A saved surface expedition returns safely to orbit with its current cargo.
|
||||||
|
if state.captain.expedition.active:
|
||||||
|
for key in ["active", "cargo", "cargo_modules", "cargo_records", "cargo_credits", "cargo_parts", "cargo_missiles", "active_profile", "visit_seed"]:
|
||||||
|
var value: Variant = state.captain.expedition.get(key)
|
||||||
|
data.captain.expedition.set(key, value.duplicate(true) if value is Dictionary or value is Array else value)
|
||||||
|
data.captain.expedition.finish_visit(data.captain, true)
|
||||||
|
data.skill_offers.assign(data.captain.skill_offers)
|
||||||
|
var inventory := ship.get_node("ShipInventory")
|
||||||
|
var previous: Dictionary = state.restart_inventory
|
||||||
|
inventory.preserve_for_restart()
|
||||||
|
data.inventory = state.restart_inventory
|
||||||
|
state.restart_inventory = previous
|
||||||
|
if named:
|
||||||
|
var directory_error := DirAccess.make_dir_recursive_absolute(DIRECTORY)
|
||||||
|
if directory_error != OK: return directory_error
|
||||||
|
return _commit(data, slot_path(data.slot_id), slot_path(data.slot_id).trim_suffix(".res")+".backup.res", slot_path(data.slot_id).trim_suffix(".res")+".pending.res")
|
||||||
|
return _commit(data, PATH, BACKUP, TEMP)
|
||||||
|
|
||||||
|
static func _commit(data: Resource, path: String, backup: String, temporary: String) -> Error:
|
||||||
|
var error := ResourceSaver.save(data, temporary)
|
||||||
|
if error != OK: return error
|
||||||
|
if read_save(temporary) == null: return ERR_FILE_CORRUPT
|
||||||
|
if read_save(path) != null:
|
||||||
|
error = DirAccess.copy_absolute(path, backup)
|
||||||
|
if error != OK: return error
|
||||||
|
return DirAccess.rename_absolute(temporary, path)
|
||||||
|
|
||||||
|
static func restore_state(state: Node, id: String = "") -> bool:
|
||||||
|
var entries := list_saves()
|
||||||
|
var data: Resource
|
||||||
|
for entry in entries:
|
||||||
|
if id.is_empty() or entry.id == id:
|
||||||
|
data = read_save(entry.path)
|
||||||
|
break
|
||||||
|
if data == null: return false
|
||||||
|
for key in STATE_FIELDS:
|
||||||
|
if data.state.has(key): state.set(key, data.state[key])
|
||||||
|
state.captain = data.captain
|
||||||
|
state.captain.skill_offers.assign(data.skill_offers)
|
||||||
|
state.captain.reset_combat_state()
|
||||||
|
state.restart_inventory = data.inventory
|
||||||
|
state.return_to_freighter = false
|
||||||
|
state.distant_warp_arrival = false
|
||||||
|
state.hull_bastion_used = false
|
||||||
|
# Loading always starts the current sector again, with fresh encounters.
|
||||||
|
if state.active_distant_map.is_empty(): state.cleared_systems.erase(state.system_level)
|
||||||
|
state.reset_current_system_exploration()
|
||||||
|
return true
|
||||||
1
scripts/game/save_service.gd.uid
Normal file
@ -0,0 +1 @@
|
|||||||
|
uid://4cxl6q1fxqtn
|
||||||
@ -4,6 +4,7 @@ extends AudioStreamPlayer
|
|||||||
@export_range(-30.0, 0.0, 0.5, "suffix:dB") var playback_volume_db := -14.0
|
@export_range(-30.0, 0.0, 0.5, "suffix:dB") var playback_volume_db := -14.0
|
||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
|
bus = &"Music"
|
||||||
if track_path.is_empty():
|
if track_path.is_empty():
|
||||||
push_error("SceneMusicPlayer has no track_path configured.")
|
push_error("SceneMusicPlayer has no track_path configured.")
|
||||||
return
|
return
|
||||||
|
|||||||
@ -47,7 +47,7 @@ static func generate(level: int, seed_value: int) -> Dictionary:
|
|||||||
if bool(planets[index].protected):
|
if bool(planets[index].protected):
|
||||||
planets[index].texture = earthlike[texture_rng.randi_range(0, earthlike.size() - 1)]
|
planets[index].texture = earthlike[texture_rng.randi_range(0, earthlike.size() - 1)]
|
||||||
planets[index].earthlike = profiles.is_earthlike(planets[index].texture)
|
planets[index].earthlike = profiles.is_earthlike(planets[index].texture)
|
||||||
planets[index].profile = profiles.generate(seed_value, index, planets[index].name) if bool(planets[index].earthlike) else {}
|
planets[index].profile = profiles.generate(seed_value, index, planets[index].name, level) if bool(planets[index].earthlike) else {}
|
||||||
if not planets[index].profile.is_empty():
|
if not planets[index].profile.is_empty():
|
||||||
planets[index].profile.system_level = level
|
planets[index].profile.system_level = level
|
||||||
var enemies: Array[Dictionary] = []
|
var enemies: Array[Dictionary] = []
|
||||||
|
|||||||
@ -67,13 +67,28 @@ static func bonus(progress: Resource, branch: String) -> float:
|
|||||||
var learned: Dictionary = progress.alien_skills
|
var learned: Dictionary = progress.alien_skills
|
||||||
return 0.1 if branch in BRANCHES and learned.get(branch, false) else 0.0
|
return 0.1 if branch in BRANCHES and learned.get(branch, false) else 0.0
|
||||||
|
|
||||||
static func purchase(progress: Resource, id: String) -> bool:
|
static func can_start(progress: Resource, id: String) -> bool:
|
||||||
if id not in ACTIVE_IDS: return false
|
if id not in ACTIVE_IDS or not progress.alien_project.is_empty(): return false
|
||||||
if progress.alien_skills.get(id,false): return false
|
if progress.alien_skills.get(id,false): return false
|
||||||
var prerequisite := parent(id)
|
var prerequisite := parent(id)
|
||||||
if prerequisite != "" and not progress.alien_skills.get(prerequisite, false): return false
|
if not prerequisite.is_empty() and not progress.alien_skills.get(prerequisite,false): return false
|
||||||
if progress.analysis_samples < cost(id): return false
|
return progress.analysis_samples >= cost(id)
|
||||||
|
|
||||||
|
static func purchase(progress: Resource, id: String) -> bool:
|
||||||
|
if not can_start(progress,id): return false
|
||||||
progress.analysis_samples -= cost(id)
|
progress.analysis_samples -= cost(id)
|
||||||
progress.alien_skills[id] = true
|
progress.alien_project = id
|
||||||
|
progress.alien_duration = 600.0
|
||||||
|
progress.alien_remaining = progress.alien_duration
|
||||||
|
progress.emit_changed()
|
||||||
|
return true
|
||||||
|
|
||||||
|
static func advance(progress: Resource, delta: float) -> bool:
|
||||||
|
if progress.alien_project.is_empty() or delta <= 0: return false
|
||||||
|
progress.alien_remaining = maxf(0,progress.alien_remaining-delta)
|
||||||
|
if progress.alien_remaining <= 0.00001:
|
||||||
|
progress.alien_remaining = 0
|
||||||
|
progress.alien_skills[progress.alien_project] = true
|
||||||
|
progress.alien_project = ""
|
||||||
progress.emit_changed()
|
progress.emit_changed()
|
||||||
return true
|
return true
|
||||||
|
|||||||
@ -8,12 +8,23 @@ const COST_COLUMN_WIDTH := 48.0
|
|||||||
var progress: Resource
|
var progress: Resource
|
||||||
var refreshed: Callable
|
var refreshed: Callable
|
||||||
var points: Dictionary = {}
|
var points: Dictionary = {}
|
||||||
|
var _state := ""
|
||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
custom_minimum_size = Vector2(330, 300)
|
custom_minimum_size = Vector2(330, 300)
|
||||||
resized.connect(_build)
|
resized.connect(_build)
|
||||||
_build()
|
_build()
|
||||||
|
|
||||||
|
func _process(_delta: float) -> void:
|
||||||
|
var state := str(progress.alien_skills)+str(progress.alien_project)+str(progress.analysis_samples)
|
||||||
|
if state != _state:
|
||||||
|
_state = state
|
||||||
|
_build()
|
||||||
|
if not progress.alien_project.is_empty():
|
||||||
|
var active_button := get_node_or_null(NodePath(progress.alien_project)) as Button
|
||||||
|
if active_button != null:
|
||||||
|
active_button.tooltip_text = str(active_button.get_meta("base_tooltip",""))+"\n"+("Pozostało: %d s gry" % ceili(progress.alien_remaining))
|
||||||
|
|
||||||
func _build() -> void:
|
func _build() -> void:
|
||||||
for child in get_children():
|
for child in get_children():
|
||||||
remove_child(child)
|
remove_child(child)
|
||||||
@ -56,12 +67,14 @@ func _add_skill(id: String, center: Vector2, color: Color) -> void:
|
|||||||
button.name = id
|
button.name = id
|
||||||
button.position = center - TILE_SIZE*0.5
|
button.position = center - TILE_SIZE*0.5
|
||||||
button.size = TILE_SIZE
|
button.size = TILE_SIZE
|
||||||
button.disabled = learned or not unlocked or progress.analysis_samples < DATA.cost(id)
|
button.disabled = not DATA.can_start(progress,id)
|
||||||
if "_" in id: _style_path(button,DATA.path_color(id))
|
if "_" in id: _style_path(button,DATA.path_color(id))
|
||||||
var status := "Zbadano" if learned else "Koszt: %d próbek" % DATA.cost(id)
|
var status := "Zbadano" if learned else "Koszt: %d próbek" % DATA.cost(id)
|
||||||
if not unlocked: status += "\nWymaga: " + DATA.title(prerequisite)
|
if not unlocked: status += "\nWymaga: " + DATA.title(prerequisite)
|
||||||
elif not learned and progress.analysis_samples < DATA.cost(id): status += "\nZa mało próbek"
|
elif not learned and progress.analysis_samples < DATA.cost(id): status += "\nZa mało próbek"
|
||||||
|
if not learned: status += "\n" + "Czas badania: 10 minut gry"
|
||||||
button.tooltip_text = DATA.title(id) + "\n" + DATA.description(id) + "\n" + status
|
button.tooltip_text = DATA.title(id) + "\n" + DATA.description(id) + "\n" + status
|
||||||
|
button.set_meta("base_tooltip",button.tooltip_text)
|
||||||
var icon := TextureRect.new()
|
var icon := TextureRect.new()
|
||||||
icon.texture = load("res://assets/freighter/research/" + id + ".png")
|
icon.texture = load("res://assets/freighter/research/" + id + ".png")
|
||||||
icon.expand_mode = TextureRect.EXPAND_IGNORE_SIZE
|
icon.expand_mode = TextureRect.EXPAND_IGNORE_SIZE
|
||||||
|
|||||||
@ -172,10 +172,7 @@ func _layout_prompt() -> void:
|
|||||||
_prompt.position = CONTACT.beside(canvas.origin,radius*canvas.x.length(),_prompt.size,viewport_size,obstacles,true,vertical*canvas.y.length())
|
_prompt.position = CONTACT.beside(canvas.origin,radius*canvas.x.length(),_prompt.size,viewport_size,obstacles,true,vertical*canvas.y.length())
|
||||||
|
|
||||||
func _compact_scan(profile: Dictionary) -> String:
|
func _compact_scan(profile: Dictionary) -> String:
|
||||||
var captain: Resource = GameState.captain
|
return PROFILES.scan_description(profile,GameState.captain)
|
||||||
var report: Dictionary = PROFILES.threat_report(profile,captain)
|
|
||||||
var loot := PROFILES.poi_loot_report(profile,captain)
|
|
||||||
return "%s · %s\nTLEN %d%% · TEMP %d°C · BIO %d/50\nZAGROŻENIE: %.1f%% / 300%%\nŁUP POI: ×%.2f · odzysk %.0f%%\nPOI: podleć i naciśnij E\nLądowanie −%d HP · Lądownik %d%%" % [profile.name,PROFILES.biome_name(profile),profile.oxygen,profile.temperature,profile.flora,report.total,loot.multiplier,loot.recovery*100.0,profile.landing_damage,ceili(captain.expedition.lander_hp)]
|
|
||||||
|
|
||||||
|
|
||||||
func _unhandled_key_input(event: InputEvent) -> void:
|
func _unhandled_key_input(event: InputEvent) -> void:
|
||||||
@ -256,6 +253,7 @@ func _leave() -> void:
|
|||||||
player.is_docked = _previous_docked
|
player.is_docked = _previous_docked
|
||||||
game.get_node("HUD/HUDRoot").visible = _hud_was_visible
|
game.get_node("HUD/HUDRoot").visible = _hud_was_visible
|
||||||
get_tree().paused = _previous_pause
|
get_tree().paused = _previous_pause
|
||||||
|
GameState.save_game()
|
||||||
|
|
||||||
func _notice(message: String) -> void:
|
func _notice(message: String) -> void:
|
||||||
_message = message
|
_message = message
|
||||||
@ -266,6 +264,7 @@ func _notification(what: int) -> void:
|
|||||||
if what == NOTIFICATION_WM_CLOSE_REQUEST:
|
if what == NOTIFICATION_WM_CLOSE_REQUEST:
|
||||||
if GameState.captain.expedition.active:
|
if GameState.captain.expedition.active:
|
||||||
GameState.captain.expedition.finish_visit(GameState.captain,true)
|
GameState.captain.expedition.finish_visit(GameState.captain,true)
|
||||||
|
GameState.save_game()
|
||||||
get_tree().quit()
|
get_tree().quit()
|
||||||
|
|
||||||
func _exit_tree() -> void:
|
func _exit_tree() -> void:
|
||||||
|
|||||||
@ -215,5 +215,5 @@ func _draw_tag(section: Dictionary) -> void:
|
|||||||
_tag_styles[section.id] = box
|
_tag_styles[section.id] = box
|
||||||
draw_style_box(box,Rect2(point,Vector2(width,43)))
|
draw_style_box(box,Rect2(point,Vector2(width,43)))
|
||||||
draw_circle(point+Vector2(10,13),2.8,Color(color,0.65+0.25*sin(_time*1.8)))
|
draw_circle(point+Vector2(10,13),2.8,Color(color,0.65+0.25*sin(_time*1.8)))
|
||||||
draw_string(font,point+Vector2(20,19),section.title,HORIZONTAL_ALIGNMENT_LEFT,width-25,13 if section.id == "expansion_2" else 16,color)
|
draw_string(font,point+Vector2(20,19), tr(section.title),HORIZONTAL_ALIGNMENT_LEFT,width-25,13 if section.id == "expansion_2" else 16,color)
|
||||||
draw_string(font,point+Vector2(10,35),section.status,HORIZONTAL_ALIGNMENT_LEFT,width-15,13,Color("899a9b"))
|
draw_string(font,point+Vector2(10,35), tr(section.status),HORIZONTAL_ALIGNMENT_LEFT,width-15,13,Color("899a9b"))
|
||||||
|
|||||||
@ -17,6 +17,8 @@ var _owned_open := false
|
|||||||
var _storage_columns: GridContainer
|
var _storage_columns: GridContainer
|
||||||
var _storage_notice := ""
|
var _storage_notice := ""
|
||||||
var _economy_labels: Dictionary = {}
|
var _economy_labels: Dictionary = {}
|
||||||
|
var _alien_timer: Label
|
||||||
|
var _alien_signature := ""
|
||||||
@onready var deck: Control = $Deck
|
@onready var deck: Control = $Deck
|
||||||
@onready var _audio: Node = $FreighterAudio
|
@onready var _audio: Node = $FreighterAudio
|
||||||
|
|
||||||
@ -47,6 +49,11 @@ func _ready() -> void:
|
|||||||
_layout()
|
_layout()
|
||||||
_refresh()
|
_refresh()
|
||||||
|
|
||||||
|
func _process(_delta: float) -> void:
|
||||||
|
if is_instance_valid(_alien_timer):
|
||||||
|
var progress: Resource = captain.expedition
|
||||||
|
_alien_timer.text = "Czas badania: 10 minut gry" if progress.alien_project.is_empty() else preload("res://scripts/planets/alien_research.gd").title(progress.alien_project)+" · "+("Pozostało: %d s gry" % ceili(progress.alien_remaining))
|
||||||
|
|
||||||
func _build_header() -> void:
|
func _build_header() -> void:
|
||||||
var header := HBoxContainer.new()
|
var header := HBoxContainer.new()
|
||||||
header.name = "Header"
|
header.name = "Header"
|
||||||
@ -605,6 +612,10 @@ func _dismiss_crew(member_id: String) -> void:
|
|||||||
_refresh()
|
_refresh()
|
||||||
|
|
||||||
func _refresh_live_labels() -> void:
|
func _refresh_live_labels() -> void:
|
||||||
|
var alien_signature := str(captain.expedition.alien_skills)+str(captain.expedition.alien_project)
|
||||||
|
if _tab == "expansion_2" and is_instance_valid(_drawer) and _drawer.visible and alien_signature != _alien_signature:
|
||||||
|
_alien_signature = alien_signature
|
||||||
|
_refresh.call_deferred()
|
||||||
for key in _economy_labels:
|
for key in _economy_labels:
|
||||||
var label: Label = _economy_labels[key]
|
var label: Label = _economy_labels[key]
|
||||||
if not is_instance_valid(label): continue
|
if not is_instance_valid(label): continue
|
||||||
@ -627,10 +638,12 @@ func _equip(kind: String, uid: int) -> void:
|
|||||||
|
|
||||||
func _build_alien_research() -> void:
|
func _build_alien_research() -> void:
|
||||||
var progress: Resource = captain.expedition
|
var progress: Resource = captain.expedition
|
||||||
|
_alien_signature = str(progress.alien_skills)+str(progress.alien_project)
|
||||||
var row := MENU.row(_content)
|
var row := MENU.row(_content)
|
||||||
var balance := MENU.label(row, "PRÓBKI / %d" % progress.analysis_samples, 15, MENU.GOLD)
|
var balance := MENU.label(row, "PRÓBKI / %d" % progress.analysis_samples, 15, MENU.GOLD)
|
||||||
balance.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
balance.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||||
MENU.label(row, "%d / %d ZBADANO" % [preload("res://scripts/planets/alien_research.gd").learned_count(progress),preload("res://scripts/planets/alien_research.gd").ACTIVE_IDS.size()], 12, MENU.MUTED).custom_minimum_size.x = 110
|
MENU.label(row, "%d / %d ZBADANO" % [preload("res://scripts/planets/alien_research.gd").learned_count(progress),preload("res://scripts/planets/alien_research.gd").ACTIVE_IDS.size()], 12, MENU.MUTED).custom_minimum_size.x = 110
|
||||||
|
_alien_timer = MENU.label(_content,"Czas badania: 10 minut gry",12,MENU.GOLD)
|
||||||
var tree := preload("res://scripts/planets/alien_research_tree.gd").new()
|
var tree := preload("res://scripts/planets/alien_research_tree.gd").new()
|
||||||
tree.progress = progress
|
tree.progress = progress
|
||||||
tree.refreshed = _research_completed
|
tree.refreshed = _research_completed
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
extends RefCounted
|
extends RefCounted
|
||||||
const DURATION := 60.0
|
const DURATION := 600.0
|
||||||
const IDS := [
|
const IDS := [
|
||||||
"gamma_cannon", "beam_laser", "machine_gun", "missile_launcher", "unguided_missile",
|
"gamma_cannon", "beam_laser", "machine_gun", "missile_launcher", "unguided_missile",
|
||||||
"incendiary_missile", "radiation_laser", "artillery_cannon", "external_turret", "pulse_laser",
|
"incendiary_missile", "radiation_laser", "artillery_cannon", "external_turret", "pulse_laser",
|
||||||
|
|||||||
@ -23,6 +23,7 @@ func _process(_delta: float) -> void:
|
|||||||
if is_instance_valid(_buttons[id]): _buttons[id].disabled = not LAB.can_start(captain,id)
|
if is_instance_valid(_buttons[id]): _buttons[id].disabled = not LAB.can_start(captain,id)
|
||||||
|
|
||||||
func _build() -> void:
|
func _build() -> void:
|
||||||
|
LAB.ensure_offers(captain.expedition)
|
||||||
for child in get_children():
|
for child in get_children():
|
||||||
remove_child(child)
|
remove_child(child)
|
||||||
child.queue_free()
|
child.queue_free()
|
||||||
|
|||||||
@ -44,7 +44,7 @@ static func station_richness(station: Dictionary) -> int:
|
|||||||
var identity := str(station.id).split(":")
|
var identity := str(station.id).split(":")
|
||||||
var profile := {"id":str(station.id), "seed":int(station.get("planet_seed", 0))}
|
var profile := {"id":str(station.id), "seed":int(station.get("planet_seed", 0))}
|
||||||
if identity.size() == 3 and identity[1] == "planet":
|
if identity.size() == 3 and identity[1] == "planet":
|
||||||
profile = preload("res://scripts/planets/planet_profiles.gd").generate(int(identity[0]), int(identity[2]), str(station.planet_name))
|
profile = preload("res://scripts/planets/planet_profiles.gd").generate(int(identity[0]), int(identity[2]), str(station.planet_name),int(station.get("system",1)))
|
||||||
station.richness = deposit_richness(profile, int(station.get("system", 1)))
|
station.richness = deposit_richness(profile, int(station.get("system", 1)))
|
||||||
return clampi(int(station.richness), 1, 100)
|
return clampi(int(station.richness), 1, 100)
|
||||||
|
|
||||||
|
|||||||
@ -1,102 +1,97 @@
|
|||||||
extends RefCounted
|
extends RefCounted
|
||||||
# These visually inspected families contain land, oceans and atmospheric clouds.
|
|
||||||
const EARTHLIKE_FAMILIES := ["Terrestrial", "Lush", "Tropical"]
|
const EARTHLIKE_FAMILIES := ["Terrestrial", "Lush", "Tropical"]
|
||||||
const MATERIALS := ["silicon", "copper", "nickel", "tungsten", "mercury"]
|
const MATERIALS := ["silicon", "copper", "nickel", "tungsten", "mercury"]
|
||||||
const MATERIAL_NAMES := {"silicon":"Krzem","copper":"Miedź","nickel":"Nikiel","tungsten":"Wolfram","mercury":"Rtęć"}
|
const MATERIAL_NAMES := {"silicon":"Krzem","copper":"Miedź","nickel":"Nikiel","tungsten":"Wolfram","mercury":"Rtęć"}
|
||||||
|
const THREAT_KEYS := ["oxygen","temperature","biology"]
|
||||||
|
const POI_SAFE_CHANCES := [0.90,0.70,0.40]
|
||||||
|
const POI_DANGER_CHANCES := [0.15,0.05,0.0]
|
||||||
|
|
||||||
static func is_earthlike(texture: Texture2D) -> bool:
|
static func is_earthlike(texture: Texture2D) -> bool:
|
||||||
if texture == null:
|
if texture == null: return false
|
||||||
return false
|
|
||||||
for family in EARTHLIKE_FAMILIES:
|
for family in EARTHLIKE_FAMILIES:
|
||||||
if texture.resource_path.contains("/Solid/%s/" % family):
|
if texture.resource_path.contains("/Solid/%s/" % family): return true
|
||||||
return true
|
|
||||||
return false
|
return false
|
||||||
|
|
||||||
static func earthlike_textures() -> Array[Texture2D]:
|
static func earthlike_textures() -> Array[Texture2D]:
|
||||||
var found: Array[Texture2D] = []
|
var found: Array[Texture2D] = []
|
||||||
for texture in preload("res://scripts/levels/celestial_texture_catalog.gd").PLANET_TEXTURES:
|
for texture in preload("res://scripts/levels/celestial_texture_catalog.gd").PLANET_TEXTURES:
|
||||||
if is_earthlike(texture):
|
if is_earthlike(texture): found.append(texture)
|
||||||
found.append(texture)
|
|
||||||
return found
|
return found
|
||||||
|
|
||||||
static func generate(system_seed: int, index: int, name: String) -> Dictionary:
|
static func level(profile: Dictionary) -> int:
|
||||||
|
return clampi(int(profile.get("system_level",1)),1,1000)
|
||||||
|
|
||||||
|
static func generate(system_seed: int, index: int, name: String, system_level: int = 1) -> Dictionary:
|
||||||
var rng := RandomNumberGenerator.new()
|
var rng := RandomNumberGenerator.new()
|
||||||
rng.seed = system_seed ^ (index*0x504c414e) ^ 0x42494f4d
|
rng.seed = system_seed ^ (index*0x504c414e) ^ 0x42494f4d
|
||||||
var easy := rng.randf() < 0.7
|
var progression := 1.0-exp(-float(maxi(1,system_level)-1)/45.0)
|
||||||
var oxygen := rng.randi_range(81, 100) if easy else rng.randi_range(0, 80)
|
var difficulty := clampf(progression*rng.randf_range(0.85,1.15),0,1)
|
||||||
var temperature := rng.randi_range(-10, 40) if easy else rng.randi_range(-50, 100)
|
var oxygen := roundi(95.0-difficulty*rng.randf_range(55,95))
|
||||||
var flora := 0 if easy else rng.randi_range(5, 50)
|
var extreme_temperature := rng.randf_range(65,100) if rng.randf() < 0.5 else rng.randf_range(-50,-20)
|
||||||
var raw := raw_threats({"oxygen":oxygen,"temperature":temperature,"flora":flora})
|
var temperature := roundi(lerpf(20.0,extreme_temperature,difficulty))
|
||||||
var difficulty := (float(raw.oxygen)+float(raw.temperature)+float(raw.biology))/300.0
|
var flora := roundi(difficulty*rng.randf_range(15,50))
|
||||||
return {"id": "%d:planet:%d" % [system_seed, index], "name": name, "oxygen": oxygen, "temperature": temperature, "flora": flora, "easy": easy, "difficulty": difficulty, "landing_damage": roundi(lerpf(5.0, 20.0, difficulty)), "seed": rng.randi(), "index": index}
|
return {"id":"%d:planet:%d" % [system_seed,index],"name":name,"system_level":maxi(1,system_level),"oxygen":oxygen,"temperature":temperature,"flora":flora,"easy":difficulty < 0.18,"difficulty":difficulty,"landing_damage":roundi(5+10*difficulty),"seed":rng.randi(),"index":index}
|
||||||
|
|
||||||
const THREAT_KEYS := ["oxygen","temperature","biology"]
|
|
||||||
const POI_SAFE_CHANCES := [0.90,0.70,0.40]
|
|
||||||
const POI_DANGER_CHANCES := [0.15,0.05,0.0]
|
|
||||||
|
|
||||||
static func raw_threats(profile: Dictionary) -> Dictionary:
|
static func raw_threats(profile: Dictionary) -> Dictionary:
|
||||||
var oxygen := clampf((80.0-float(profile.oxygen))/80.0,0.0,1.0)*100.0
|
var oxygen := clampf((80.0-float(profile.get("oxygen",95)))/80.0,0,1)*100
|
||||||
var temperature := float(profile.temperature)
|
var temperature := float(profile.get("temperature",20))
|
||||||
var thermal := 0.0
|
var thermal := 0.0
|
||||||
if temperature < -10.0:
|
if temperature < -10: thermal = clampf((-10-temperature)/40,0,1)*100
|
||||||
thermal = clampf((-10.0-temperature)/40.0,0.0,1.0)*100.0
|
elif temperature > 40: thermal = clampf((temperature-40)/60,0,1)*100
|
||||||
elif temperature > 40.0:
|
return {"oxygen":oxygen,"temperature":thermal,"biology":clampf(float(profile.get("flora",0))/50.0,0,1)*100}
|
||||||
thermal = clampf((temperature-40.0)/60.0,0.0,1.0)*100.0
|
|
||||||
var biology := clampf(float(profile.flora)/50.0,0.0,1.0)*100.0
|
|
||||||
return {"oxygen":oxygen,"temperature":thermal,"biology":biology}
|
|
||||||
|
|
||||||
static func threat_report(profile: Dictionary, captain: Resource) -> Dictionary:
|
static func equipment_report(profile: Dictionary, captain: Resource, weights: Array = [1.0,1.0,1.0]) -> Dictionary:
|
||||||
var gear := preload("res://scripts/planets/captain_equipment.gd")
|
var gear := preload("res://scripts/planets/captain_equipment.gd")
|
||||||
var raw := raw_threats(profile)
|
var raw := raw_threats(profile)
|
||||||
|
var deficit := 0.0
|
||||||
|
var surplus := 0.0
|
||||||
|
var weight_total := 0.0
|
||||||
var effective := {}
|
var effective := {}
|
||||||
var raw_total := 0.0
|
var requirements := {}
|
||||||
var total := 0.0
|
|
||||||
for index in 3:
|
for index in 3:
|
||||||
var key: String = THREAT_KEYS[index]
|
var key: String = THREAT_KEYS[index]
|
||||||
var protection := minf(100.0,2.0*maxi(0,gear.level(captain,gear.KINDS[index])))
|
var required := maxf(1.0,level(profile)*(0.85+0.45*float(raw[key])/100.0))
|
||||||
effective[key] = maxf(0.0,float(raw[key])-protection)
|
var ratio := float(gear.level(captain,gear.KINDS[index]))/required
|
||||||
raw_total += float(raw[key])
|
var shortfall := clampf(1.0-ratio,0,1)
|
||||||
total += float(effective[key])
|
effective[key] = shortfall*100
|
||||||
return {"raw":raw,"effective":effective,"raw_total":raw_total,"total":total}
|
requirements[key] = required
|
||||||
|
deficit += shortfall*float(weights[index])
|
||||||
|
surplus += clampf(ratio-1.0,0,1)*float(weights[index])
|
||||||
|
weight_total += float(weights[index])
|
||||||
|
return {"deficit":deficit/weight_total,"surplus":surplus/weight_total,"raw":raw,"effective":effective,"requirements":requirements}
|
||||||
|
|
||||||
|
static func threat_report(profile: Dictionary, captain: Resource) -> Dictionary:
|
||||||
|
var report := equipment_report(profile,captain)
|
||||||
|
var raw_total := 0.0
|
||||||
|
var total := 0.0
|
||||||
|
for key in THREAT_KEYS:
|
||||||
|
raw_total += float(report.raw[key])
|
||||||
|
total += float(report.effective[key])
|
||||||
|
return {"raw":report.raw,"effective":report.effective,"raw_total":raw_total,"total":total}
|
||||||
|
|
||||||
static func global_threat(profile: Dictionary, captain: Resource) -> float:
|
static func global_threat(profile: Dictionary, captain: Resource) -> float:
|
||||||
return float(threat_report(profile,captain).total)
|
return float(threat_report(profile,captain).total)
|
||||||
|
|
||||||
static func poi_loot_report(profile: Dictionary, captain: Resource) -> Dictionary:
|
static func poi_loot_report(profile: Dictionary, captain: Resource, weights: Array = [1.0,1.0,1.0]) -> Dictionary:
|
||||||
var gear := preload("res://scripts/planets/captain_equipment.gd")
|
var gear := equipment_report(profile,captain,weights)
|
||||||
var equipped_levels := 0.0
|
var recovery := 1.0-0.5*float(gear.deficit)
|
||||||
for kind in gear.KINDS: equipped_levels += clampi(gear.level(captain,kind),0,50)
|
var gear_multiplier := 1.0+0.1*float(gear.surplus)
|
||||||
var gear_multiplier := 1.0+(equipped_levels/3.0)*0.02
|
return {"multiplier":recovery*gear_multiplier,"recovery":recovery,"gear_multiplier":gear_multiplier,"threat":float(gear.deficit)*300,"deficit":gear.deficit,"surplus":gear.surplus}
|
||||||
var threat := global_threat(profile,captain)
|
|
||||||
var recovery := clampf(1.0-threat/300.0,0.15,1.0)
|
|
||||||
return {"multiplier":gear_multiplier*recovery,"recovery":recovery,"gear_multiplier":gear_multiplier,"threat":threat}
|
|
||||||
|
|
||||||
static func success_chance(profile: Dictionary, captain: Resource, stage: int) -> float:
|
static func success_chance(profile: Dictionary, captain: Resource, stage: int) -> float:
|
||||||
var index := clampi(stage,0,2)
|
var index := clampi(stage,0,2)
|
||||||
var severity := clampf(global_threat(profile,captain)/150.0,0.0,1.0)
|
return lerpf(POI_SAFE_CHANCES[index],POI_DANGER_CHANCES[index],clampf(global_threat(profile,captain)/150,0,1))
|
||||||
return lerpf(POI_SAFE_CHANCES[index],POI_DANGER_CHANCES[index],severity)
|
|
||||||
|
|
||||||
static func average_success_chance(profile: Dictionary, captain: Resource) -> float:
|
static func average_success_chance(profile: Dictionary, captain: Resource) -> float:
|
||||||
var total := 0.0
|
var total := 0.0
|
||||||
for stage in 3:
|
for stage in 3: total += success_chance(profile,captain,stage)
|
||||||
total += success_chance(profile,captain,stage)
|
return total/3
|
||||||
return total/3.0
|
|
||||||
|
|
||||||
static func biome_name(profile: Dictionary) -> String:
|
static func biome_name(profile: Dictionary) -> String:
|
||||||
if bool(profile.easy):
|
if bool(profile.get("easy",false)): return "Łagodna biosfera"
|
||||||
return "Łagodna biosfera"
|
if int(profile.get("temperature",20)) < -10: return "Zimna biosfera"
|
||||||
if int(profile.temperature) < -10:
|
if int(profile.get("temperature",20)) > 40: return "Gorąca biosfera"
|
||||||
return "Zimna biosfera"
|
|
||||||
if int(profile.temperature) > 40:
|
|
||||||
return "Gorąca biosfera"
|
|
||||||
return "Dzika biosfera"
|
return "Dzika biosfera"
|
||||||
|
|
||||||
static func scan_description(profile: Dictionary, captain: Resource) -> String:
|
static func scan_description(profile: Dictionary, captain: Resource) -> String:
|
||||||
var report := threat_report(profile,captain)
|
return "%s · Poziom %d\nLądowanie: −%d HP\nLądownik: %d / 100 HP\nPOI: podleć i naciśnij E, aby zaplanować eksplorację." % [profile.name,level(profile),profile.landing_damage,ceili(captain.expedition.lander_hp)]
|
||||||
var loot := poi_loot_report(profile,captain)
|
|
||||||
return "%s · %s\nTLEN %d%% · zagrożenie %.0f%% → %.0f%%\nTEMPERATURA %d°C · zagrożenie %.0f%% → %.0f%%\nBIOLOGICZNE %d/50 · zagrożenie %.0f%% → %.0f%%\nZAGROŻENIE GLOBALNE: %.1f%% / 300%%\nBez sprzętu: %.1f%% · redukcja 2 pp/poziom\nŁUP POI: ×%.2f · odzysk %.0f%% · sprzęt ×%.2f\nPOI: podleć i naciśnij E, aby odebrać znaleziska.\nLądowanie: −%d HP · Lądownik: %d%%" % [
|
|
||||||
profile.name,biome_name(profile),profile.oxygen,report.raw.oxygen,report.effective.oxygen,
|
|
||||||
profile.temperature,report.raw.temperature,report.effective.temperature,
|
|
||||||
profile.flora,report.raw.biology,report.effective.biology,
|
|
||||||
report.total,report.raw_total,loot.multiplier,loot.recovery*100.0,loot.gear_multiplier,
|
|
||||||
profile.landing_damage,ceili(captain.expedition.lander_hp)]
|
|
||||||
|
|||||||
@ -8,11 +8,14 @@ const PROFILES := preload("res://scripts/planets/planet_profiles.gd")
|
|||||||
@export var delivered_modules: Array[Resource] = []
|
@export var delivered_modules: Array[Resource] = []
|
||||||
@export var research_records: Dictionary = {}
|
@export var research_records: Dictionary = {}
|
||||||
@export var alien_skills: Dictionary = {}
|
@export var alien_skills: Dictionary = {}
|
||||||
|
@export var alien_project := ""
|
||||||
|
@export var alien_remaining := 0.0
|
||||||
|
@export var alien_duration := 600.0
|
||||||
@export var laboratory_unlocks: Dictionary = {}
|
@export var laboratory_unlocks: Dictionary = {}
|
||||||
@export var laboratory_offers: Array[String] = []
|
@export var laboratory_offers: Array[String] = []
|
||||||
@export var laboratory_project: String = ""
|
@export var laboratory_project: String = ""
|
||||||
@export var laboratory_remaining: float = 0.0
|
@export var laboratory_remaining: float = 0.0
|
||||||
@export var laboratory_duration: float = 60.0
|
@export var laboratory_duration: float = 600.0
|
||||||
@export var freighter_rooms: Dictionary = {"expansion_3":"module_storage"}
|
@export var freighter_rooms: Dictionary = {"expansion_3":"module_storage"}
|
||||||
@export var mining_stations: Dictionary = {}
|
@export var mining_stations: Dictionary = {}
|
||||||
@export var distant_maps: Dictionary = {}
|
@export var distant_maps: Dictionary = {}
|
||||||
@ -82,20 +85,31 @@ func add_material(key: String, amount: int) -> void:
|
|||||||
cargo[key] = int(cargo.get(key, 0)) + amount
|
cargo[key] = int(cargo.get(key, 0)) + amount
|
||||||
emit_changed()
|
emit_changed()
|
||||||
|
|
||||||
func resolve_poi(captain: Resource, poi: Dictionary, rng: RandomNumberGenerator) -> Dictionary:
|
func resolve_poi(captain: Resource, poi: Dictionary, _rng: RandomNumberGenerator = null, risky: bool = false) -> Dictionary:
|
||||||
var rules := preload("res://scripts/planets/poi_rules.gd")
|
var rules := preload("res://scripts/planets/poi_rules.gd")
|
||||||
if not active or lander_hp <= 0.0 or bool(poi.get("complete", false)) or str(poi.get("kind", "")) not in rules.KINDS:
|
if not active or lander_hp <= 0 or str(poi.get("kind","")) not in rules.KINDS: return {}
|
||||||
return {}
|
if risky:
|
||||||
poi.complete = true
|
if not bool(poi.get("complete",false)) or bool(poi.get("bonus_complete",false)) or not rules.has_bonus(poi,active_profile): return {}
|
||||||
var result := {"success":true,"damage":0,"materials":rules.reward(str(poi.kind),rng,active_profile,captain),"module":null,"modules":[],"loot":PROFILES.poi_loot_report(active_profile,captain)}
|
elif bool(poi.get("complete",false)): return {}
|
||||||
|
var plan: Dictionary = rules.preview(active_profile,captain,poi,visit_seed,risky)
|
||||||
|
var bounds: Vector2i = plan.damage
|
||||||
|
var rolled_damage := rules.rng_for(visit_seed,poi,11 if risky else 1).randi_range(bounds.x,bounds.y)
|
||||||
|
var result := {"success":true,"damage":rolled_damage,"materials":plan.materials.duplicate(),"module":null,"modules":[],"loot":rules.report(str(poi.kind),active_profile,captain),"bonus":risky}
|
||||||
for key in result.materials: add_material(key,int(result.materials[key]))
|
for key in result.materials: add_material(key,int(result.materials[key]))
|
||||||
if str(poi.kind) == "ruins":
|
if poi.kind == "ruins":
|
||||||
for index in rules.module_count(active_profile,captain):
|
var module_rng := rules.rng_for(visit_seed,poi,12 if risky else 2)
|
||||||
var item: ItemInstance = REWARDS.generate_module(rng,active_profile,GameState.system_level,null,0,rules.module_bonus(rng,active_profile,captain))
|
for index in int(plan.modules):
|
||||||
|
var item: ItemInstance = REWARDS.generate_module(module_rng,active_profile,PROFILES.level(active_profile),null,0,rules.module_bonus(module_rng,active_profile,captain,risky))
|
||||||
cargo_modules.append(item)
|
cargo_modules.append(item)
|
||||||
result.modules.append(item)
|
result.modules.append(item)
|
||||||
result.module = result.modules[0]
|
result.module = result.modules[0]
|
||||||
poi["loot_result"] = result
|
damage(rolled_damage)
|
||||||
|
if risky:
|
||||||
|
poi.bonus_complete = true
|
||||||
|
poi.bonus_result = result
|
||||||
|
else:
|
||||||
|
poi.complete = true
|
||||||
|
poi.loot_result = result
|
||||||
emit_changed()
|
emit_changed()
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|||||||
@ -1,32 +1,66 @@
|
|||||||
extends RefCounted
|
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":"Obóz 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 KINDS := ["deposit","ruins","warehouse","village","cave"]
|
const KINDS := ["deposit","ruins","warehouse","village","cave"]
|
||||||
|
const WEIGHTS := {"deposit":[0.1,0.7,0.2],"ruins":[0.2,0.5,0.3],"warehouse":[0.1,0.25,0.65],"village":[0.15,0.2,0.65],"cave":[0.7,0.2,0.1]}
|
||||||
const PROFILES := preload("res://scripts/planets/planet_profiles.gd")
|
const PROFILES := preload("res://scripts/planets/planet_profiles.gd")
|
||||||
const REWARDS := preload("res://scripts/planets/planet_rewards.gd")
|
const REWARDS := preload("res://scripts/planets/planet_rewards.gd")
|
||||||
|
|
||||||
static func reward(kind: String, rng: RandomNumberGenerator, profile: Dictionary, captain: Resource) -> Dictionary:
|
static func report(kind: String, profile: Dictionary, captain: Resource) -> Dictionary:
|
||||||
|
return PROFILES.poi_loot_report(profile,captain,WEIGHTS.get(kind,[1.0,1.0,1.0]))
|
||||||
|
|
||||||
|
static func richness(profile: Dictionary) -> float:
|
||||||
|
return REWARDS.material_multiplier(profile)*(1.0+0.02*(PROFILES.level(profile)-1))
|
||||||
|
|
||||||
|
static func reward(kind: String, rng: RandomNumberGenerator, profile: Dictionary, captain: Resource, risky: bool = false) -> Dictionary:
|
||||||
var result := {}
|
var result := {}
|
||||||
var multiplier: float = PROFILES.poi_loot_report(profile,captain).multiplier
|
var multiplier: float = report(kind,profile,captain).multiplier*(0.35 if risky else 1.0)
|
||||||
|
var supplies := 1.0+0.5*REWARDS.difficulty(profile)+0.005*(PROFILES.level(profile)-1)
|
||||||
match kind:
|
match kind:
|
||||||
"deposit":
|
"deposit":
|
||||||
var key: String = PROFILES.MATERIALS[rng.randi_range(0,PROFILES.MATERIALS.size()-1)]
|
var key: String = PROFILES.MATERIALS[rng.randi_range(0,PROFILES.MATERIALS.size()-1)]
|
||||||
result[key] = rng.randi_range(18,28)*REWARDS.material_multiplier(profile)
|
result[key] = rng.randi_range(18,28)*richness(profile)
|
||||||
"warehouse":
|
"warehouse":
|
||||||
result.ammunition = rng.randi_range(130,210)
|
result.ammunition = rng.randi_range(130,210)*supplies
|
||||||
result.missile = rng.randi_range(2,4)
|
result.missile = rng.randi_range(2,4)*supplies
|
||||||
if rng.randf() < 0.25: result.irradiated_ammunition = rng.randi_range(20,35)
|
if rng.randf() < 0.25: result.irradiated_ammunition = rng.randi_range(20,35)*supplies
|
||||||
var keys := ["iron","titanium","aluminium","uranium","sulfur"]
|
var keys := ["iron","titanium","aluminium","uranium","sulfur"]
|
||||||
result[keys[rng.randi_range(0,4)]] = rng.randi_range(8,16)*REWARDS.material_multiplier(profile)
|
result[keys[rng.randi_range(0,4)]] = rng.randi_range(8,16)*richness(profile)
|
||||||
"village":
|
"village":
|
||||||
result.credits = rng.randi_range(140,220)
|
result.credits = rng.randi_range(140,220)*richness(profile)
|
||||||
result.experience = maxi(1,ceili(maxi(0,captain.get_xp_required()-captain.experience)*0.05))
|
var xp: int = captain.encounter_xp(6.0*pow(PROFILES.level(profile),0.75),PROFILES.level(profile))
|
||||||
"cave": result.samples = rng.randi_range(3,5)
|
if xp > 0: result.experience = xp
|
||||||
|
"cave": result.samples = rng.randi_range(3,5)*sqrt(richness(profile))
|
||||||
for key in result: result[key] = maxi(1,roundi(float(result[key])*multiplier))
|
for key in result: result[key] = maxi(1,roundi(float(result[key])*multiplier))
|
||||||
return result
|
return result
|
||||||
|
|
||||||
static func module_count(profile: Dictionary, captain: Resource) -> int:
|
static func module_count(profile: Dictionary, captain: Resource, risky: bool = false) -> int:
|
||||||
return clampi(roundi(1.5*float(PROFILES.poi_loot_report(profile,captain).multiplier)),1,3)
|
if risky: return 1
|
||||||
|
return clampi(roundi((1.0+REWARDS.difficulty(profile))*float(report("ruins",profile,captain).multiplier)),1,3)
|
||||||
|
|
||||||
static func module_bonus(rng: RandomNumberGenerator, profile: Dictionary, captain: Resource) -> int:
|
static func module_bonus(rng: RandomNumberGenerator, profile: Dictionary, captain: Resource, risky: bool = false) -> int:
|
||||||
var report := PROFILES.poi_loot_report(profile,captain)
|
var equipment := roundi((float(report("ruins",profile,captain).gear_multiplier)-1.0)*10)
|
||||||
return maxi(0,roundi(REWARDS.roll_module_bonus(rng,profile)*float(report.recovery)))+roundi((float(report.gear_multiplier)-1.0)*2.0)
|
return REWARDS.roll_module_bonus(rng,profile)+equipment+(2 if risky else 0)
|
||||||
|
|
||||||
|
static func has_bonus(poi: Dictionary, profile: Dictionary) -> bool:
|
||||||
|
if str(poi.get("kind","")) not in KINDS: return false
|
||||||
|
if poi.has("bonus_available"): return bool(poi.bonus_available)
|
||||||
|
var rng := rng_for(int(profile.get("seed",1)),poi,24)
|
||||||
|
return rng.randf() < 0.25
|
||||||
|
|
||||||
|
static func rng_for(visit_seed: int, poi: Dictionary, salt: int = 0) -> RandomNumberGenerator:
|
||||||
|
var rng := RandomNumberGenerator.new()
|
||||||
|
rng.seed = visit_seed ^ (int(poi.get("id",0))*7919) ^ str(poi.get("kind","")).hash() ^ ((salt+1)*104729)
|
||||||
|
return rng
|
||||||
|
|
||||||
|
static func damage_range(kind: String, profile: Dictionary, captain: Resource, risky: bool = false) -> Vector2i:
|
||||||
|
var equipment := report(kind,profile,captain)
|
||||||
|
var base := 13.0+5.0*REWARDS.difficulty(profile)+20.0*float(equipment.deficit)-3.0*float(equipment.surplus) if risky else 3.0+3.0*REWARDS.difficulty(profile)+16.0*float(equipment.deficit)-1.5*float(equipment.surplus)
|
||||||
|
var spread := 5 if risky else 1
|
||||||
|
return Vector2i(maxi(1,floori(base)-spread),maxi(1,ceili(base)+spread))
|
||||||
|
|
||||||
|
static func preview(profile: Dictionary, captain: Resource, poi: Dictionary, visit_seed: int, risky: bool = false) -> Dictionary:
|
||||||
|
var kind := str(poi.get("kind",""))
|
||||||
|
if kind not in KINDS: return {}
|
||||||
|
var bounds := REWARDS.module_bonus_range(profile)
|
||||||
|
var equipment := roundi((float(report("ruins",profile,captain).gear_multiplier)-1.0)*10)+(2 if risky else 0)
|
||||||
|
return {"materials":reward(kind,rng_for(visit_seed,poi,10 if risky else 0),profile,captain,risky),"modules":module_count(profile,captain,risky) if kind == "ruins" else 0,"module_levels":Vector2i(clampi(PROFILES.level(profile)+bounds.x+equipment,1,1000),clampi(PROFILES.level(profile)+bounds.y+equipment,1,1000)),"damage":damage_range(kind,profile,captain,risky),"bonus":risky}
|
||||||
|
|||||||
@ -197,7 +197,7 @@ static func resolve(event: Dictionary, action: String, captain: Resource, progre
|
|||||||
if not can_pay(captain,progress,selected.cost):
|
if not can_pay(captain,progress,selected.cost):
|
||||||
return {"success":false,"reason":"Brakuje zasobów. Koszt: "+reward_text(selected.cost)}
|
return {"success":false,"reason":"Brakuje zasobów. Koszt: "+reward_text(selected.cost)}
|
||||||
if event.kind in ["prototype","rescue","evacuation"] and action != "stop" and chance(event,captain,progress) <= 0.0:
|
if event.kind in ["prototype","rescue","evacuation"] and action != "stop" and chance(event,captain,progress) <= 0.0:
|
||||||
return {"success":false,"blocked":true,"reason":"Ten etap ma 0% szans. Obniż zagrożenie odpowiednim wyposażeniem."}
|
return {"success":false,"blocked":true,"reason":"Ten etap jest niedostępny z obecnym wyposażeniem."}
|
||||||
_pay(captain,progress,selected.cost)
|
_pay(captain,progress,selected.cost)
|
||||||
var reward: Dictionary = selected.reward.duplicate()
|
var reward: Dictionary = selected.reward.duplicate()
|
||||||
var success := true
|
var success := true
|
||||||
|
|||||||
@ -87,6 +87,10 @@ static func generate(seed_value: int, profile: Dictionary) -> Dictionary:
|
|||||||
chosen = Vector2.from_angle(index * TAU / kinds.size()) * 1250
|
chosen = Vector2.from_angle(index * TAU / kinds.size()) * 1250
|
||||||
pois.append({"id": index, "kind": kind, "position": chosen, "complete": false, "discovered": false})
|
pois.append({"id": index, "kind": kind, "position": chosen, "complete": false, "discovered": false})
|
||||||
_attach_caves(pois,mountains)
|
_attach_caves(pois,mountains)
|
||||||
|
# A separate stream keeps bonus selection independent of terrain generation.
|
||||||
|
for poi in pois:
|
||||||
|
poi.bonus_available = preload("res://scripts/planets/poi_rules.gd").has_bonus(poi,profile)
|
||||||
|
poi.bonus_complete = false
|
||||||
# Clear vegetation around explorable structures so entrances stay readable.
|
# Clear vegetation around explorable structures so entrances stay readable.
|
||||||
for poi in pois:
|
for poi in pois:
|
||||||
trees = trees.filter(func(prop): return prop.position.distance_to(poi.position) > 100)
|
trees = trees.filter(func(prop): return prop.position.distance_to(poi.position) > 100)
|
||||||
|
|||||||
@ -20,7 +20,8 @@ func _draw() -> void:
|
|||||||
for poi in world.data.pois:
|
for poi in world.data.pois:
|
||||||
if poi.discovered:
|
if poi.discovered:
|
||||||
var at: Vector2 = (poi.position / total + Vector2.ONE * 0.5) * size
|
var at: Vector2 = (poi.position / total + Vector2.ONE * 0.5) * size
|
||||||
var color := Color("708377") if poi.complete else Color("f4cb80")
|
var bonus_pending := bool(poi.get("bonus_available",false)) and not bool(poi.get("bonus_complete",false))
|
||||||
|
var color := Color("708377") if poi.complete and not bonus_pending else Color("f4cb80")
|
||||||
if poi.kind == "time_engineer":
|
if poi.kind == "time_engineer":
|
||||||
color = Color("9be7ff")
|
color = Color("9be7ff")
|
||||||
draw_colored_polygon(PackedVector2Array([at+Vector2(0,-4),at+Vector2(4,0),at+Vector2(0,4),at+Vector2(-4,0)]),color)
|
draw_colored_polygon(PackedVector2Array([at+Vector2(0,-4),at+Vector2(4,0),at+Vector2(0,4),at+Vector2(-4,0)]),color)
|
||||||
|
|||||||
@ -4,6 +4,7 @@ const UI := preload("res://scripts/planets/expedition_ui.gd")
|
|||||||
const PROFILES := preload("res://scripts/planets/planet_profiles.gd")
|
const PROFILES := preload("res://scripts/planets/planet_profiles.gd")
|
||||||
const EVENTS := preload("res://scripts/planets/surface_events.gd")
|
const EVENTS := preload("res://scripts/planets/surface_events.gd")
|
||||||
const GENERATOR := preload("res://scripts/planets/surface_generator.gd")
|
const GENERATOR := preload("res://scripts/planets/surface_generator.gd")
|
||||||
|
const RULES := preload("res://scripts/planets/poi_rules.gd")
|
||||||
const POI_CARD := preload("res://scripts/planets/poi_presentation.gd")
|
const POI_CARD := preload("res://scripts/planets/poi_presentation.gd")
|
||||||
var captain: Resource
|
var captain: Resource
|
||||||
var progress: Resource
|
var progress: Resource
|
||||||
@ -157,6 +158,7 @@ func _ready() -> void:
|
|||||||
_choices.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
_choices.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||||
_choices.add_theme_constant_override("separation", 10)
|
_choices.add_theme_constant_override("separation", 10)
|
||||||
scroll.add_child(_choices)
|
scroll.add_child(_choices)
|
||||||
|
_choices.minimum_size_changed.connect(_layout_dialog.call_deferred)
|
||||||
_layout_dialog()
|
_layout_dialog()
|
||||||
_dialog.hide()
|
_dialog.hide()
|
||||||
_update_hud()
|
_update_hud()
|
||||||
@ -207,8 +209,10 @@ func _input(event: InputEvent) -> void:
|
|||||||
_dialog.hide()
|
_dialog.hide()
|
||||||
else:
|
else:
|
||||||
_return(true)
|
_return(true)
|
||||||
elif event.keycode == KEY_E and _dialog.visible and not _poi.is_empty() and _poi.kind in preload("res://scripts/planets/poi_rules.gd").KINDS and _poi.complete:
|
elif event.keycode == KEY_E and _dialog.visible:
|
||||||
_dialog.hide()
|
if _poi.is_empty() or str(_poi.get("kind","")) not in RULES.KINDS: return
|
||||||
|
if not bool(_poi.get("complete",false)): _attempt()
|
||||||
|
else: _dialog.hide()
|
||||||
elif event.keycode == KEY_E and not _dialog.visible:
|
elif event.keycode == KEY_E and not _dialog.visible:
|
||||||
for encounter in world.data.events:
|
for encounter in world.data.events:
|
||||||
if not encounter.complete and lander.position.distance_to(encounter.position) <= 180:
|
if not encounter.complete and lander.position.distance_to(encounter.position) <= 180:
|
||||||
@ -217,7 +221,7 @@ func _input(event: InputEvent) -> void:
|
|||||||
get_viewport().set_input_as_handled()
|
get_viewport().set_input_as_handled()
|
||||||
return
|
return
|
||||||
for poi in world.data.pois:
|
for poi in world.data.pois:
|
||||||
if not poi.complete and lander.position.distance_to(poi.position) <= 150:
|
if (not poi.complete or (RULES.has_bonus(poi,progress.active_profile) and not bool(poi.get("bonus_complete",false)))) and lander.position.distance_to(poi.position) <= 150:
|
||||||
_poi = poi
|
_poi = poi
|
||||||
_show_poi()
|
_show_poi()
|
||||||
break
|
break
|
||||||
@ -227,9 +231,6 @@ func _input(event: InputEvent) -> void:
|
|||||||
|
|
||||||
func _show_poi(message := "") -> void:
|
func _show_poi(message := "") -> void:
|
||||||
_active_event = {}
|
_active_event = {}
|
||||||
if _poi.kind in preload("res://scripts/planets/poi_rules.gd").KINDS and not _poi.complete:
|
|
||||||
_attempt()
|
|
||||||
return
|
|
||||||
for child in _choices.get_children():
|
for child in _choices.get_children():
|
||||||
_choices.remove_child(child)
|
_choices.remove_child(child)
|
||||||
child.queue_free()
|
child.queue_free()
|
||||||
@ -246,11 +247,36 @@ func _show_poi(message := "") -> void:
|
|||||||
if _poi.kind in ["deep_deposit", "crew"]:
|
if _poi.kind in ["deep_deposit", "crew"]:
|
||||||
_show_colony_poi(message)
|
_show_colony_poi(message)
|
||||||
return
|
return
|
||||||
POI_CARD.header(_choices,str(_poi.kind),0,true)
|
POI_CARD.header(_choices,str(_poi.kind),0,bool(_poi.get("complete",false)))
|
||||||
|
if not bool(_poi.get("complete",false)):
|
||||||
|
_show_forecast(false)
|
||||||
|
POI_CARD.button(_choices,"Podejmij eksplorację [E]",_attempt,true).name = "ExploreButton"
|
||||||
|
POI_CARD.button(_choices,"Wróć do wyprawy",func(): _dialog.hide())
|
||||||
|
return
|
||||||
var result: Dictionary = _poi.get("loot_result",{})
|
var result: Dictionary = _poi.get("loot_result",{})
|
||||||
if result.is_empty():
|
if not result.is_empty(): _show_findings(result)
|
||||||
POI_CARD.text(_choices,"To miejsce zostało już odwiedzone.",14,POI_CARD.GOLD)
|
var bonus_result: Dictionary = _poi.get("bonus_result",{})
|
||||||
else:
|
if not bonus_result.is_empty(): _show_findings(bonus_result)
|
||||||
|
elif RULES.has_bonus(_poi,progress.active_profile) and not bool(_poi.get("bonus_complete",false)):
|
||||||
|
POI_CARD.text(_choices,"DODATKOWE ZNALEZISKA",13,POI_CARD.GOLD)
|
||||||
|
_show_forecast(true)
|
||||||
|
POI_CARD.button(_choices,"Przeszukaj głębiej",func(): _attempt(true),true).name = "BonusExploreButton"
|
||||||
|
POI_CARD.text(_choices,"Znaleziska są w ładowni wyprawy. Zachowasz je po bezpiecznym powrocie na statek.",12,POI_CARD.MUTED)
|
||||||
|
POI_CARD.button(_choices,"Kontynuuj wyprawę [E]",func(): _dialog.hide())
|
||||||
|
|
||||||
|
func _show_forecast(risky: bool) -> void:
|
||||||
|
var plan := RULES.preview(progress.active_profile,captain,_poi,progress.visit_seed,risky)
|
||||||
|
POI_CARD.text(_choices,"PRZEWIDYWANA NAGRODA",13,POI_CARD.GOLD)
|
||||||
|
if not plan.materials.is_empty(): POI_CARD.text(_choices,UI.material_text(plan.materials),16)
|
||||||
|
if int(plan.modules) > 0:
|
||||||
|
var levels: Vector2i = plan.module_levels
|
||||||
|
POI_CARD.text(_choices,"Moduły: %d · poziom %d–%d" % [plan.modules,levels.x,levels.y],16)
|
||||||
|
var bounds: Vector2i = plan.damage
|
||||||
|
POI_CARD.text(_choices,"Uszkodzenia lądownika: %d–%d HP" % [bounds.x,bounds.y],16,Color("e9b18a"))
|
||||||
|
if float(bounds.y) >= progress.lander_hp:
|
||||||
|
POI_CARD.text(_choices,"Lądownik może zostać zniszczony. Utracisz cały łup tej wyprawy.",14,Color("f08370"))
|
||||||
|
|
||||||
|
func _show_findings(result: Dictionary) -> void:
|
||||||
POI_CARD.text(_choices,"ZDOBYTO",13,POI_CARD.GOLD)
|
POI_CARD.text(_choices,"ZDOBYTO",13,POI_CARD.GOLD)
|
||||||
if not result.materials.is_empty(): POI_CARD.text(_choices,UI.material_text(result.materials),15)
|
if not result.materials.is_empty(): POI_CARD.text(_choices,UI.material_text(result.materials),15)
|
||||||
for item in result.modules:
|
for item in result.modules:
|
||||||
@ -271,15 +297,12 @@ func _show_poi(message := "") -> void:
|
|||||||
name_label.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
name_label.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||||
name_label.size_flags_vertical = Control.SIZE_SHRINK_CENTER
|
name_label.size_flags_vertical = Control.SIZE_SHRINK_CENTER
|
||||||
name_label.tooltip_text = item.get_tooltip_text()
|
name_label.tooltip_text = item.get_tooltip_text()
|
||||||
var loot: Dictionary = result.loot
|
POI_CARD.text(_choices,"Uszkodzenia lądownika: −%d HP" % int(result.get("damage",0)),13,Color("e9b18a"))
|
||||||
POI_CARD.text(_choices,"Łup ×%.2f · sprzęt ×%.2f · odzysk %.0f%%\nZagrożenie po ochronie: %.1f%% / 300%%" % [loot.multiplier,loot.gear_multiplier,loot.recovery*100.0,loot.threat],12,POI_CARD.MUTED)
|
|
||||||
POI_CARD.text(_choices,"Znaleziska są w ładowni wyprawy. Zachowasz je po bezpiecznym powrocie na statek.",12,POI_CARD.MUTED)
|
|
||||||
POI_CARD.button(_choices, "Kontynuuj wyprawę [E]", func(): _dialog.hide(),true)
|
|
||||||
|
|
||||||
func _attempt() -> void:
|
func _attempt(risky: bool = false) -> void:
|
||||||
if _ending:
|
if _ending or _poi.is_empty(): return
|
||||||
return
|
if _poi.has("position") and lander.position.distance_to(_poi.position) > 150: return
|
||||||
var result: Dictionary = progress.resolve_poi(captain, _poi, _rng)
|
var result: Dictionary = progress.resolve_poi(captain, _poi, _rng, risky)
|
||||||
if result.is_empty():
|
if result.is_empty():
|
||||||
return
|
return
|
||||||
var rarity := 0
|
var rarity := 0
|
||||||
@ -287,9 +310,9 @@ func _attempt() -> void:
|
|||||||
preload("res://scripts/items/loot_reveal_effect.gd").spawn(lander.get_parent(),lander.position,Color("f1cd86"),rarity,true)
|
preload("res://scripts/items/loot_reveal_effect.gd").spawn(lander.get_parent(),lander.position,Color("f1cd86"),rarity,true)
|
||||||
_update_hud()
|
_update_hud()
|
||||||
world.refresh_pois(lander.position)
|
world.refresh_pois(lander.position)
|
||||||
_show_poi()
|
|
||||||
if progress.lander_hp <= 0:
|
if progress.lander_hp <= 0:
|
||||||
await _destroy_lander()
|
await _destroy_lander()
|
||||||
|
else: _show_poi()
|
||||||
|
|
||||||
func _destroy_lander() -> void:
|
func _destroy_lander() -> void:
|
||||||
if _ending:
|
if _ending:
|
||||||
@ -309,8 +332,8 @@ func _update_hud() -> void:
|
|||||||
_hp.value = progress.lander_hp
|
_hp.value = progress.lander_hp
|
||||||
if not _ending:
|
if not _ending:
|
||||||
_status.text = "Lądownik %d / 100 HP · Energia %d%%" % [ceili(progress.lander_hp),roundi(_motion.energy)] + ("\nPogoda: " + weather.display_name() if is_instance_valid(weather) else "")
|
_status.text = "Lądownik %d / 100 HP · Energia %d%%" % [ceili(progress.lander_hp),roundi(_motion.energy)] + ("\nPogoda: " + weather.display_name() if is_instance_valid(weather) else "")
|
||||||
var loot_report := PROFILES.poi_loot_report(progress.active_profile,captain)
|
_threat.text = ""
|
||||||
_threat.text = "Zagrożenie %.1f%% / 300%% · Łup POI ×%.2f" % [loot_report.threat,loot_report.multiplier]
|
_threat.hide()
|
||||||
var loot_data: Dictionary = progress.cargo.duplicate()
|
var loot_data: Dictionary = progress.cargo.duplicate()
|
||||||
if progress.cargo_parts > 0: loot_data.parts = progress.cargo_parts
|
if progress.cargo_parts > 0: loot_data.parts = progress.cargo_parts
|
||||||
if progress.cargo_missiles > 0: loot_data.missile = progress.cargo_missiles
|
if progress.cargo_missiles > 0: loot_data.missile = progress.cargo_missiles
|
||||||
@ -336,10 +359,7 @@ func _check_events() -> void:
|
|||||||
var distance: float = lander.position.distance_to(event.position)
|
var distance: float = lander.position.distance_to(event.position)
|
||||||
if distance > 260:
|
if distance > 260:
|
||||||
_event_armed = true
|
_event_armed = true
|
||||||
elif distance <= 180 and _event_armed and not _dialog.visible:
|
# Encounters, like ordinary POIs, open only after pressing E.
|
||||||
_event_armed = false
|
|
||||||
_show_event(event)
|
|
||||||
return
|
|
||||||
|
|
||||||
func _event_text(text: String, color := Color("d5e4e8"), font_size := 15) -> Label:
|
func _event_text(text: String, color := Color("d5e4e8"), font_size := 15) -> Label:
|
||||||
var label := POI_CARD.text(_choices,text,font_size,color)
|
var label := POI_CARD.text(_choices,text,font_size,color)
|
||||||
@ -360,11 +380,6 @@ func _show_event(event: Dictionary, result: Dictionary = {}) -> void:
|
|||||||
_layout_dialog()
|
_layout_dialog()
|
||||||
_event_text(str(EVENTS.TITLES.get(event.kind,"Spotkanie")).to_upper(),UI.CYAN,22)
|
_event_text(str(EVENTS.TITLES.get(event.kind,"Spotkanie")).to_upper(),UI.CYAN,22)
|
||||||
_event_text(str(EVENTS.STORIES.get(event.kind,"")))
|
_event_text(str(EVENTS.STORIES.get(event.kind,"")))
|
||||||
var threat := PROFILES.threat_report(progress.active_profile,captain)
|
|
||||||
_event_text("Zagrożenie po sprzęcie: %.1f%% / 300%% (bez sprzętu %.1f%%)." % [threat.total,threat.raw_total],Color("efca8a"),13)
|
|
||||||
var reward_profile: Dictionary = event.get("reward_profile",progress.active_profile)
|
|
||||||
var bonus: Vector2i = EVENTS.REWARDS.module_bonus_range(reward_profile)
|
|
||||||
_event_text("Premia biomu: materiały ×%.1f · moduły +%d…+%d poz.\nLiczba amunicji i rakiet nie wzrasta." % [EVENTS.REWARDS.material_multiplier(reward_profile),bonus.x,bonus.y],Color("9bc4c7"),13)
|
|
||||||
if not result.is_empty():
|
if not result.is_empty():
|
||||||
_event_text(str(result.get("message",result.get("reason",""))),Color("efca8a"))
|
_event_text(str(result.get("message",result.get("reason",""))),Color("efca8a"))
|
||||||
if not event.complete:
|
if not event.complete:
|
||||||
@ -377,7 +392,7 @@ func _show_event(event: Dictionary, result: Dictionary = {}) -> void:
|
|||||||
_event_text("Możesz wybrać tylko jedną ofertę.",Color("efca8a"))
|
_event_text("Możesz wybrać tylko jedną ofertę.",Color("efca8a"))
|
||||||
if event.kind in ["prototype","rescue","evacuation"]:
|
if event.kind in ["prototype","rescue","evacuation"]:
|
||||||
var limits: Vector2i = EVENTS.damage_range(event,progress)
|
var limits: Vector2i = EVENTS.damage_range(event,progress)
|
||||||
_event_text("Sukces: %.2f%% · w razie porażki: −%d–%d HP\nSzansa uwzględnia warunki planety i sprzęt kapitana." % [EVENTS.chance(event,captain,progress)*100,limits.x,limits.y],Color("efca8a"))
|
_event_text("Przewidywane uszkodzenia lądownika: 0–%d HP" % limits.y,Color("efca8a"))
|
||||||
if event.kind in ["blind_cache","safe_bet"]:
|
if event.kind in ["blind_cache","safe_bet"]:
|
||||||
_event_text("Tajemniczy łup: 50% części, 35% minerały, 10% rakiety, 5% moduł. Wartość może być niższa od opłaty.",Color("9bc4c7"),13)
|
_event_text("Tajemniczy łup: 50% części, 35% minerały, 10% rakiety, 5% moduł. Wartość może być niższa od opłaty.",Color("9bc4c7"),13)
|
||||||
for option in EVENTS.options(event,captain,progress):
|
for option in EVENTS.options(event,captain,progress):
|
||||||
@ -394,9 +409,9 @@ func _show_event(event: Dictionary, result: Dictionary = {}) -> void:
|
|||||||
button.disabled = not EVENTS.can_pay(captain,progress,option.cost)
|
button.disabled = not EVENTS.can_pay(captain,progress,option.cost)
|
||||||
if event.kind in ["prototype","rescue","evacuation"] and action != "stop" and EVENTS.chance(event,captain,progress) <= 0.0:
|
if event.kind in ["prototype","rescue","evacuation"] and action != "stop" and EVENTS.chance(event,captain,progress) <= 0.0:
|
||||||
button.disabled = true
|
button.disabled = true
|
||||||
button.tooltip_text += "\nTen etap ma 0% szans przy obecnym zagrożeniu."
|
button.tooltip_text += "\nTen etap jest niedostępny z obecnym wyposażeniem."
|
||||||
if button.disabled:
|
if button.disabled:
|
||||||
button.tooltip_text += "\nSprawdź wymagane zasoby i aktualne zagrożenie."
|
button.tooltip_text += "\nSprawdź wymagane zasoby."
|
||||||
POI_CARD.button(_choices,"Może później",func(): _dialog.hide())
|
POI_CARD.button(_choices,"Może później",func(): _dialog.hide())
|
||||||
else:
|
else:
|
||||||
_event_text("Spotkanie zakończone. Nagrody w ładowni wyprawy przepadną po zniszczeniu lądownika.",Color("9bc4c7"),13)
|
_event_text("Spotkanie zakończone. Nagrody w ładowni wyprawy przepadną po zniszczeniu lądownika.",Color("9bc4c7"),13)
|
||||||
@ -417,7 +432,7 @@ func _layout_dialog() -> void:
|
|||||||
return
|
return
|
||||||
var view := size
|
var view := size
|
||||||
var width := minf(450,maxf(280,view.x-32))
|
var width := minf(450,maxf(280,view.x-32))
|
||||||
var height := minf(600,maxf(180,view.y-48))
|
var height := minf(minf(600,maxf(180,view.y-48)),maxf(240,_choices.get_combined_minimum_size().y+20))
|
||||||
_dialog.size = Vector2(width,height)
|
_dialog.size = Vector2(width,height)
|
||||||
_dialog.position = Vector2(view.x-width-20,maxf(16,(view.y-height)*0.5))
|
_dialog.position = Vector2(view.x-width-20,maxf(16,(view.y-height)*0.5))
|
||||||
|
|
||||||
|
|||||||
@ -81,25 +81,9 @@ func _ready() -> void:
|
|||||||
text(title,str(source.progress.active_profile.name),19,GOLD)
|
text(title,str(source.progress.active_profile.name),19,GOLD)
|
||||||
text(title,str(source.world.data.landscape.name),12)
|
text(title,str(source.world.data.landscape.name),12)
|
||||||
text(title,preload("res://scripts/planets/planet_profiles.gd").biome_name(source.progress.active_profile),10,MUTED)
|
text(title,preload("res://scripts/planets/planet_profiles.gd").biome_name(source.progress.active_profile),10,MUTED)
|
||||||
var conditions := HBoxContainer.new()
|
text(title,"Poziom %d" % preload("res://scripts/planets/planet_profiles.gd").level(source.progress.active_profile),12,MUTED)
|
||||||
conditions.add_theme_constant_override("separation",6)
|
|
||||||
stack.add_child(conditions)
|
|
||||||
var profile: Dictionary = source.progress.active_profile
|
|
||||||
for entry in [["TLEN","%d%%" % profile.oxygen],["TEMPERATURA","%d°C" % profile.temperature],["GROŹNA FAUNA","%d" % profile.flora]]:
|
|
||||||
var cell := PanelContainer.new()
|
|
||||||
cell.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
|
||||||
var style := StyleBoxFlat.new()
|
|
||||||
style.bg_color = Color("30382a")
|
|
||||||
style.set_corner_radius_all(4)
|
|
||||||
style.set_content_margin_all(6)
|
|
||||||
cell.add_theme_stylebox_override("panel",style)
|
|
||||||
conditions.add_child(cell)
|
|
||||||
var column := VBoxContainer.new()
|
|
||||||
column.add_theme_constant_override("separation",1)
|
|
||||||
cell.add_child(column)
|
|
||||||
text(column,entry[0],9,MUTED)
|
|
||||||
text(column,entry[1],13,INK)
|
|
||||||
threat = text(stack,"",11,GOLD)
|
threat = text(stack,"",11,GOLD)
|
||||||
|
threat.hide()
|
||||||
health = ProgressBar.new()
|
health = ProgressBar.new()
|
||||||
health.custom_minimum_size.y = 6
|
health.custom_minimum_size.y = 6
|
||||||
health.show_percentage = false
|
health.show_percentage = false
|
||||||
|
|||||||
@ -181,7 +181,10 @@ func refresh_pois(lander_position: Vector2) -> void:
|
|||||||
label.text = "Obóz specjalisty" + (" · zatrudniono" if poi.complete else ("\n[E] Porozmawiaj" if lander_position.distance_to(poi.position) <= 150 else ""))
|
label.text = "Obóz specjalisty" + (" · zatrudniono" if poi.complete else ("\n[E] Porozmawiaj" if lander_position.distance_to(poi.position) <= 150 else ""))
|
||||||
continue
|
continue
|
||||||
var title: String = preload("res://scripts/planets/poi_rules.gd").NAMES[poi.kind]
|
var title: String = preload("res://scripts/planets/poi_rules.gd").NAMES[poi.kind]
|
||||||
label.text = title + (" · odwiedzono" if poi.complete else ("\n[E] Zbierz znaleziska" if lander_position.distance_to(poi.position) <= 150 else ""))
|
var bonus: bool = poi.complete and preload("res://scripts/planets/poi_rules.gd").has_bonus(poi,data.profile) and not bool(poi.get("bonus_complete",false))
|
||||||
|
if bonus: sprite.modulate = Color("f2d49a")
|
||||||
|
label.text = title + (" · dodatkowe znaleziska" if bonus else (" · odwiedzono" if poi.complete else ""))
|
||||||
|
if lander_position.distance_to(poi.position) <= 150 and (not poi.complete or bonus): label.text += "\n[E] Zaplanuj eksplorację"
|
||||||
|
|
||||||
func _draw() -> void:
|
func _draw() -> void:
|
||||||
if terrain == null:
|
if terrain == null:
|
||||||
|
|||||||
@ -33,6 +33,7 @@ func _create_wardrobe() -> void:
|
|||||||
doll.custom_minimum_size = Vector2(228,252)
|
doll.custom_minimum_size = Vector2(228,252)
|
||||||
body.add_child(doll)
|
body.add_child(doll)
|
||||||
_protection = MENU.label(contents,"",10,MENU.MUTED)
|
_protection = MENU.label(contents,"",10,MENU.MUTED)
|
||||||
|
_protection.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
|
||||||
get_parent().get_node("FloatingWindows").register_window(_wardrobe,_wardrobe,header)
|
get_parent().get_node("FloatingWindows").register_window(_wardrobe,_wardrobe,header)
|
||||||
_wardrobe.minimum_size_changed.connect(_fit_window.call_deferred)
|
_wardrobe.minimum_size_changed.connect(_fit_window.call_deferred)
|
||||||
_wardrobe.hide()
|
_wardrobe.hide()
|
||||||
@ -73,4 +74,5 @@ func _refresh_wardrobe() -> void:
|
|||||||
var signature := str(captain.gear_items)+str(captain.gear_slots)
|
var signature := str(captain.gear_items)+str(captain.gear_slots)
|
||||||
if signature == _gear_signature: return
|
if signature == _gear_signature: return
|
||||||
_gear_signature = signature
|
_gear_signature = signature
|
||||||
_protection.text = "Tlen %d · Temp. %d · Fauna %d pp" % [mini(100,2*GEAR.level(captain,"breathing")),mini(100,2*GEAR.level(captain,"suit")),mini(100,2*GEAR.level(captain,"sidearm"))]
|
_protection.text = "Dopasuj poziom sprzętu do planety."
|
||||||
|
_protection.tooltip_text = "Dopasuj poziom wyposażenia do planety, aby odzyskać więcej łupu i ograniczyć uszkodzenia lądownika."
|
||||||
|
|||||||
@ -47,7 +47,8 @@ func refresh() -> void:
|
|||||||
_label.add_theme_font_size_override("font_size",11)
|
_label.add_theme_font_size_override("font_size",11)
|
||||||
tooltip_text = "Odłóż wyposażenie kapitana" if return_slot else "%s\n%s\nPrzeciągnij przedmiot do pasującego slotu. Dwuklik zakłada lub zdejmuje." % [GEAR.NAMES.get(kind, kind), "Poziom %d" % int(gear.level) if not gear.is_empty() else "Pusty slot"]
|
tooltip_text = "Odłóż wyposażenie kapitana" if return_slot else "%s\n%s\nPrzeciągnij przedmiot do pasującego slotu. Dwuklik zakłada lub zdejmuje." % [GEAR.NAMES.get(kind, kind), "Poziom %d" % int(gear.level) if not gear.is_empty() else "Pusty slot"]
|
||||||
if not return_slot and not gear.is_empty():
|
if not return_slot and not gear.is_empty():
|
||||||
tooltip_text += "\nRedukcja zagrożenia: %d pp (2 pp/poziom, maks. 100 pp).\nPoziom 50 całkowicie neutralizuje odpowiadające zagrożenie." % mini(100,2*int(gear.level))
|
var uses := {"breathing":"Pomaga podczas eksploracji jaskiń i miejsc z trudną atmosferą.","suit":"Pomaga przy wydobyciu i eksploracji niestabilnych ruin.","sidearm":"Pomaga przeszukiwać magazyny i osady opanowane przez faunę."}
|
||||||
|
tooltip_text += "\n"+str(uses.get(kind,""))+"\n"+"Dopasuj poziom wyposażenia do poziomu planety."
|
||||||
_style()
|
_style()
|
||||||
|
|
||||||
func _style() -> void:
|
func _style() -> void:
|
||||||
|
|||||||
@ -48,7 +48,8 @@ func _ready() -> void:
|
|||||||
|
|
||||||
func _refresh_reductions() -> void:
|
func _refresh_reductions() -> void:
|
||||||
for kind in _reductions:
|
for kind in _reductions:
|
||||||
_reductions[kind].text = "−%d%%" % mini(100,2*GEAR.level(GameState.captain,kind))
|
var rank: int = GEAR.level(GameState.captain,kind)
|
||||||
|
_reductions[kind].text = "Poz. %d" % rank if rank > 0 else "—"
|
||||||
|
|
||||||
func _draw() -> void:
|
func _draw() -> void:
|
||||||
draw_style_box(_background(),Rect2(Vector2.ZERO,size))
|
draw_style_box(_background(),Rect2(Vector2.ZERO,size))
|
||||||
|
|||||||
@ -30,4 +30,4 @@ func _draw() -> void:
|
|||||||
if is_instance_valid(navigation):
|
if is_instance_valid(navigation):
|
||||||
warning_top = navigation.get_global_rect().end.y - global_position.y + 12.0
|
warning_top = navigation.get_global_rect().end.y - global_position.y + 12.0
|
||||||
var baseline := warning_top + FONT.get_ascent(18)
|
var baseline := warning_top + FONT.get_ascent(18)
|
||||||
draw_string(FONT, Vector2(0, baseline), warning, HORIZONTAL_ALIGNMENT_CENTER, size.x, 18, warning_color)
|
draw_string(FONT, Vector2(0, baseline), tr(warning), HORIZONTAL_ALIGNMENT_CENTER, size.x, 18, warning_color)
|
||||||
|
|||||||
@ -39,9 +39,10 @@ func fitted_font_size(value: String, width: float, requested: int) -> int:
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
func _text(value: String, point: Vector2, width: float, font_size: int, color: Color) -> void:
|
func _text(value: String, point: Vector2, width: float, font_size: int, color: Color) -> void:
|
||||||
|
value = tr(value)
|
||||||
var fitted := fitted_font_size(value, width, font_size)
|
var fitted := fitted_font_size(value, width, font_size)
|
||||||
draw_string_outline(FONT, point, value, HORIZONTAL_ALIGNMENT_CENTER, width, fitted, 2, Color("030a12cc"))
|
draw_string_outline(FONT, point, value, HORIZONTAL_ALIGNMENT_CENTER, width, fitted, 2, Color("030a12cc"))
|
||||||
draw_string(FONT, point, value, HORIZONTAL_ALIGNMENT_CENTER, width, fitted, color)
|
draw_string(FONT, point, tr(value), HORIZONTAL_ALIGNMENT_CENTER, width, fitted, color)
|
||||||
|
|
||||||
func _draw() -> void:
|
func _draw() -> void:
|
||||||
if _inventory == null or not is_instance_valid(player): return
|
if _inventory == null or not is_instance_valid(player): return
|
||||||
|
|||||||
@ -11,6 +11,9 @@ var _launching := false
|
|||||||
var _drawer_tween: Tween
|
var _drawer_tween: Tween
|
||||||
var _guide: Control
|
var _guide: Control
|
||||||
var _instruction_button: Button
|
var _instruction_button: Button
|
||||||
|
var _continue_button: Button
|
||||||
|
var _message: CanvasLayer
|
||||||
|
var _modal: CanvasLayer
|
||||||
|
|
||||||
func _style_menu() -> void:
|
func _style_menu() -> void:
|
||||||
$Background.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
$Background.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||||
@ -48,19 +51,27 @@ func _style_menu() -> void:
|
|||||||
_instruction_button.name = "InstructionsButton"
|
_instruction_button.name = "InstructionsButton"
|
||||||
layout.add_child(_instruction_button)
|
layout.add_child(_instruction_button)
|
||||||
layout.move_child(_instruction_button, start_button.get_index() + 1)
|
layout.move_child(_instruction_button, start_button.get_index() + 1)
|
||||||
|
_continue_button = Button.new()
|
||||||
|
_continue_button.name = "ContinueButton"
|
||||||
|
layout.add_child(_continue_button)
|
||||||
|
layout.move_child(_continue_button, start_button.get_index())
|
||||||
var entries := [
|
var entries := [
|
||||||
[start_button, "NOWA WYPRAWA", "Wybierz statek i ruszaj w nieznane", "01", true],
|
[start_button, "NOWA WYPRAWA", "Wybierz statek i ruszaj w nieznane", "01", true],
|
||||||
[_instruction_button, "INSTRUKCJA", "Pierwszy lot? Zacznij tutaj", "02", false],
|
[_instruction_button, "INSTRUKCJA", "Pierwszy lot? Zacznij tutaj", "02", false],
|
||||||
[$MenuLayout/SaveButton, "ZAPIS ROZGRYWKI", "Wgraj / zapisz — wkrótce", "03", false],
|
[_continue_button, "KONTYNUUJ", "Wczytaj ostatnią wyprawę", "00", false],
|
||||||
[$MenuLayout/OptionsButton, "OPCJE", "Ustawienia — wkrótce", "04", false],
|
[$MenuLayout/SaveButton, "WCZYTAJ GRĘ", "Wybierz wyprawę z archiwum zapisów", "03", false],
|
||||||
|
[$MenuLayout/OptionsButton, "OPCJE", "Dźwięk, obraz i język", "04", false],
|
||||||
[exit_button, "WYJŚCIE", "Zakończ grę", "05", false],
|
[exit_button, "WYJŚCIE", "Zakończ grę", "05", false],
|
||||||
]
|
]
|
||||||
for entry in entries:
|
for entry in entries:
|
||||||
var button: Button = entry[0]
|
var button: Button = entry[0]
|
||||||
button.set_script(preload("res://scripts/ui/main_menu_button.gd"))
|
button.set_script(preload("res://scripts/ui/main_menu_button.gd"))
|
||||||
button.call("configure", entry[1], entry[2], entry[3], entry[4])
|
button.call("configure", entry[1], entry[2], entry[3], entry[4])
|
||||||
$MenuLayout/SaveButton.disabled = true
|
_continue_button.disabled = not GameState.has_save()
|
||||||
$MenuLayout/OptionsButton.disabled = true
|
_continue_button.pressed.connect(_continue_game)
|
||||||
|
$MenuLayout/SaveButton.pressed.connect(_show_save)
|
||||||
|
$MenuLayout/OptionsButton.pressed.connect(_open_options)
|
||||||
|
GameSettings.settings_changed.connect(_refresh_language)
|
||||||
_guide = Control.new()
|
_guide = Control.new()
|
||||||
_guide.set_script(preload("res://scripts/ui/player_guide.gd"))
|
_guide.set_script(preload("res://scripts/ui/player_guide.gd"))
|
||||||
add_child(_guide)
|
add_child(_guide)
|
||||||
@ -72,7 +83,7 @@ func _style_menu() -> void:
|
|||||||
func _layout_menu() -> void:
|
func _layout_menu() -> void:
|
||||||
var layout := $MenuLayout as VBoxContainer
|
var layout := $MenuLayout as VBoxContainer
|
||||||
layout.set_anchors_and_offsets_preset(Control.PRESET_TOP_LEFT)
|
layout.set_anchors_and_offsets_preset(Control.PRESET_TOP_LEFT)
|
||||||
var factor := minf(1.0, minf((size.y - 120.0) / 520.0, (size.x - 64.0) / 420.0))
|
var factor := minf(1.0, minf((size.y - 100.0) / maxf(580.0, layout.get_combined_minimum_size().y), (size.x - 64.0) / 420.0))
|
||||||
layout.scale = Vector2.ONE * factor
|
layout.scale = Vector2.ONE * factor
|
||||||
layout.size = Vector2(420, layout.get_combined_minimum_size().y)
|
layout.size = Vector2(420, layout.get_combined_minimum_size().y)
|
||||||
layout.position = Vector2(maxf(32.0, size.x * 0.065), maxf(68.0, (size.y - layout.size.y * factor) * 0.5))
|
layout.position = Vector2(maxf(32.0, size.x * 0.065), maxf(68.0, (size.y - layout.size.y * factor) * 0.5))
|
||||||
@ -132,3 +143,55 @@ func _launch_game() -> void:
|
|||||||
|
|
||||||
func _exit_game() -> void:
|
func _exit_game() -> void:
|
||||||
get_tree().quit()
|
get_tree().quit()
|
||||||
|
|
||||||
|
func _continue_game() -> void:
|
||||||
|
if _launching: return
|
||||||
|
if not GameState.continue_game():
|
||||||
|
_show_message(tr("Brak poprawnego zapisu gry."))
|
||||||
|
return
|
||||||
|
_launching = true
|
||||||
|
get_tree().paused = false
|
||||||
|
var error := get_tree().change_scene_to_file(GAME_SCENE)
|
||||||
|
if error != OK:
|
||||||
|
_launching = false
|
||||||
|
_show_message(error_string(error))
|
||||||
|
|
||||||
|
func _open_options() -> void:
|
||||||
|
if is_instance_valid(_modal): return
|
||||||
|
_modal = CanvasLayer.new()
|
||||||
|
_modal.set_script(preload("res://scripts/ui/options_dialog.gd"))
|
||||||
|
add_child(_modal)
|
||||||
|
|
||||||
|
func _show_save() -> void:
|
||||||
|
if is_instance_valid(_modal): return
|
||||||
|
_modal = CanvasLayer.new()
|
||||||
|
_modal.set_script(preload("res://scripts/ui/save_browser.gd"))
|
||||||
|
_modal.connect("load_requested",_load_selected)
|
||||||
|
add_child(_modal)
|
||||||
|
|
||||||
|
func _load_selected(id: String) -> void:
|
||||||
|
if _launching: return
|
||||||
|
if not GameState.load_game(id):
|
||||||
|
_modal._status.text = tr("Brak poprawnego zapisu gry.")
|
||||||
|
_modal._status.show()
|
||||||
|
return
|
||||||
|
_launching = true
|
||||||
|
get_tree().paused = false
|
||||||
|
var error := get_tree().change_scene_to_file(GAME_SCENE)
|
||||||
|
if error != OK:
|
||||||
|
_launching = false
|
||||||
|
_show_message(error_string(error))
|
||||||
|
|
||||||
|
func _show_message(message: String) -> void:
|
||||||
|
if is_instance_valid(_message): _message.queue_free()
|
||||||
|
_message = CanvasLayer.new()
|
||||||
|
_message.set_script(preload("res://scripts/ui/menu_modal.gd"))
|
||||||
|
_message.heading = "ZAPIS ROZGRYWKI"
|
||||||
|
_message.subtitle = message
|
||||||
|
_message.preferred_size = Vector2(600,320)
|
||||||
|
add_child(_message)
|
||||||
|
preload("res://scripts/ui/menu_modal.gd").button(_message.footer,tr("Zamknij"),_message._close,true)
|
||||||
|
|
||||||
|
func _refresh_language() -> void:
|
||||||
|
for button in $MenuLayout.get_children():
|
||||||
|
if button is Button: button.queue_redraw()
|
||||||
|
|||||||
@ -49,7 +49,7 @@ func _draw() -> void:
|
|||||||
var label_color := Color("f4ead9") if primary else Color("e0edf3")
|
var label_color := Color("f4ead9") if primary else Color("e0edf3")
|
||||||
if disabled:
|
if disabled:
|
||||||
label_color = Color("82909d")
|
label_color = Color("82909d")
|
||||||
draw_string(DISPLAY_FONT, Vector2(62 + _hover * 3, 29 if primary else 24), caption, HORIZONTAL_ALIGNMENT_LEFT, -1, 17 if primary else 14, label_color)
|
draw_string(DISPLAY_FONT, Vector2(62 + _hover * 3, 29 if primary else 24), tr(caption), HORIZONTAL_ALIGNMENT_LEFT, size.x - 90, 17 if primary else 14, label_color)
|
||||||
draw_string(body_font, Vector2(62, 50 if primary else 43), detail, HORIZONTAL_ALIGNMENT_LEFT, size.x - 104, 12, Color("a1acb9") if disabled else Color("a9bcc8"))
|
draw_string(body_font, Vector2(62, 50 if primary else 43), tr(detail), HORIZONTAL_ALIGNMENT_LEFT, size.x - 90, 12, Color("a1acb9") if disabled else Color("a9bcc8"))
|
||||||
var tip := Vector2(size.x - 23 + _hover * 3, size.y * 0.5)
|
var tip := Vector2(size.x - 23 + _hover * 3, size.y * 0.5)
|
||||||
draw_polyline(PackedVector2Array([tip + Vector2(-5, -5), tip, tip + Vector2(-5, 5)]), Color(accent, 0.5 + _hover * 0.5), 1.5, true)
|
draw_polyline(PackedVector2Array([tip + Vector2(-5, -5), tip, tip + Vector2(-5, 5)]), Color(accent, 0.5 + _hover * 0.5), 1.5, true)
|
||||||
|
|||||||
@ -11,5 +11,5 @@ func _draw() -> void:
|
|||||||
draw_line(Vector2(32, 36), Vector2(90, 36), Color("91dbea"), 2)
|
draw_line(Vector2(32, 36), Vector2(90, 36), Color("91dbea"), 2)
|
||||||
draw_line(Vector2(32, 36), Vector2(32, 62), Color(0.57, 0.86, 0.92, 0.4), 1)
|
draw_line(Vector2(32, 36), Vector2(32, 62), Color(0.57, 0.86, 0.92, 0.4), 1)
|
||||||
draw_line(Vector2(32, size.y - 36), Vector2(size.x - 32, size.y - 36), Color(0.57, 0.86, 0.92, 0.17), 1)
|
draw_line(Vector2(32, size.y - 36), Vector2(size.x - 32, size.y - 36), Color(0.57, 0.86, 0.92, 0.17), 1)
|
||||||
draw_string(ThemeDB.fallback_font, Vector2(48, size.y - 16), "RANDOLOOT / EKSPLORUJ • WALCZ • ROZWIJAJ STATEK", HORIZONTAL_ALIGNMENT_LEFT, -1, 11, Color("91a4b7"))
|
draw_string(ThemeDB.fallback_font, Vector2(48, size.y - 16), tr("RANDOLOOT / EKSPLORUJ • WALCZ • ROZWIJAJ STATEK"), HORIZONTAL_ALIGNMENT_LEFT, -1, 11, Color("91a4b7"))
|
||||||
draw_string(ThemeDB.fallback_font, Vector2(size.x - 215, size.y - 16), "NIEZNANY UKŁAD. TWOJA WYPRAWA.", HORIZONTAL_ALIGNMENT_LEFT, -1, 10, Color("829aac"))
|
draw_string(ThemeDB.fallback_font, Vector2(size.x - 215, size.y - 16), tr("NIEZNANY UKŁAD. TWOJA WYPRAWA."), HORIZONTAL_ALIGNMENT_LEFT, -1, 10, Color("829aac"))
|
||||||
|
|||||||
147
scripts/ui/menu_modal.gd
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
extends CanvasLayer
|
||||||
|
## Shared responsive menu shell. No native window chrome or system dialogs.
|
||||||
|
signal closed
|
||||||
|
|
||||||
|
const INK := Color("ecf2ed")
|
||||||
|
const MUTED := Color("8fa8b7")
|
||||||
|
const CYAN := Color("83d4df")
|
||||||
|
const GOLD := Color("edbc7c")
|
||||||
|
const DISPLAY_FONT := preload("res://assets/fonts/font2.ttf")
|
||||||
|
var heading := ""
|
||||||
|
var subtitle := ""
|
||||||
|
var marker := "RANDOLOOT / SYSTEMY POKŁADOWE"
|
||||||
|
var preferred_size := Vector2(780,590)
|
||||||
|
var body: VBoxContainer
|
||||||
|
var footer: HBoxContainer
|
||||||
|
var panel: PanelContainer
|
||||||
|
var _root: Control
|
||||||
|
var _closing := false
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
process_mode = Node.PROCESS_MODE_ALWAYS
|
||||||
|
layer = 140
|
||||||
|
_root = Control.new()
|
||||||
|
_root.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
||||||
|
add_child(_root)
|
||||||
|
var shade := ColorRect.new()
|
||||||
|
shade.color = Color(0.005,0.012,0.025,0.78)
|
||||||
|
shade.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
||||||
|
_root.add_child(shade)
|
||||||
|
panel = PanelContainer.new()
|
||||||
|
panel.add_theme_stylebox_override("panel", box(Color("0b1825"),Color("416471"),24))
|
||||||
|
_root.add_child(panel)
|
||||||
|
var column := VBoxContainer.new()
|
||||||
|
column.add_theme_constant_override("separation",16)
|
||||||
|
panel.add_child(column)
|
||||||
|
var top := HBoxContainer.new()
|
||||||
|
column.add_child(top)
|
||||||
|
var eyebrow := label(top,tr(marker),10,CYAN)
|
||||||
|
eyebrow.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||||
|
var close_button := button(top,"×",_close,false)
|
||||||
|
close_button.custom_minimum_size = Vector2(32,30)
|
||||||
|
close_button.add_theme_font_size_override("font_size",20)
|
||||||
|
close_button.tooltip_text = tr("Zamknij") + " · Esc"
|
||||||
|
var title := label(column,tr(heading),28,INK)
|
||||||
|
title.add_theme_font_override("font",DISPLAY_FONT)
|
||||||
|
if not subtitle.is_empty():
|
||||||
|
var description := label(column,tr(subtitle),13,MUTED)
|
||||||
|
description.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
|
||||||
|
column.add_child(rule())
|
||||||
|
var scroll := ScrollContainer.new()
|
||||||
|
scroll.size_flags_vertical = Control.SIZE_EXPAND_FILL
|
||||||
|
scroll.horizontal_scroll_mode = ScrollContainer.SCROLL_MODE_DISABLED
|
||||||
|
column.add_child(scroll)
|
||||||
|
body = VBoxContainer.new()
|
||||||
|
body.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||||
|
body.add_theme_constant_override("separation",16)
|
||||||
|
scroll.add_child(body)
|
||||||
|
column.add_child(rule())
|
||||||
|
footer = HBoxContainer.new()
|
||||||
|
footer.alignment = BoxContainer.ALIGNMENT_END
|
||||||
|
footer.add_theme_constant_override("separation",10)
|
||||||
|
column.add_child(footer)
|
||||||
|
get_viewport().size_changed.connect(_layout)
|
||||||
|
panel.minimum_size_changed.connect(_layout)
|
||||||
|
_layout.call_deferred()
|
||||||
|
|
||||||
|
func _layout() -> void:
|
||||||
|
var viewport_size := get_viewport().get_visible_rect().size
|
||||||
|
var extent := preferred_size.min(viewport_size-Vector2(48,48))
|
||||||
|
panel.size = extent
|
||||||
|
var factor := minf(1.0,minf((viewport_size.x-48)/maxf(1,panel.size.x),(viewport_size.y-48)/maxf(1,panel.size.y)))
|
||||||
|
panel.scale = Vector2.ONE*factor
|
||||||
|
panel.position = (viewport_size-panel.size*factor)*0.5
|
||||||
|
|
||||||
|
func _unhandled_input(event: InputEvent) -> void:
|
||||||
|
if visible and event is InputEventKey and event.pressed and not event.echo and event.keycode == KEY_ESCAPE:
|
||||||
|
get_viewport().set_input_as_handled()
|
||||||
|
_close()
|
||||||
|
|
||||||
|
func _close() -> void:
|
||||||
|
if _closing: return
|
||||||
|
_closing = true
|
||||||
|
hide()
|
||||||
|
closed.emit()
|
||||||
|
queue_free()
|
||||||
|
|
||||||
|
func popup_centered() -> void:
|
||||||
|
show()
|
||||||
|
_layout()
|
||||||
|
|
||||||
|
static func box(background: Color, border: Color, margin: int = 14) -> StyleBoxFlat:
|
||||||
|
var style := StyleBoxFlat.new()
|
||||||
|
style.bg_color = background
|
||||||
|
style.border_color = border
|
||||||
|
style.set_border_width_all(1)
|
||||||
|
style.set_corner_radius_all(9)
|
||||||
|
style.set_content_margin_all(margin)
|
||||||
|
style.shadow_color = Color(0,0,0,0.25)
|
||||||
|
style.shadow_size = 12
|
||||||
|
return style
|
||||||
|
|
||||||
|
static func rule() -> ColorRect:
|
||||||
|
var line := ColorRect.new()
|
||||||
|
line.custom_minimum_size.y = 1
|
||||||
|
line.color = Color("304653")
|
||||||
|
return line
|
||||||
|
|
||||||
|
static func label(parent: Node, caption: String, font_size: int = 14, color: Color = INK) -> Label:
|
||||||
|
var node := Label.new()
|
||||||
|
node.text = caption
|
||||||
|
node.add_theme_font_override("font",ThemeDB.fallback_font)
|
||||||
|
node.add_theme_font_size_override("font_size",font_size)
|
||||||
|
node.add_theme_color_override("font_color",color)
|
||||||
|
parent.add_child(node)
|
||||||
|
return node
|
||||||
|
|
||||||
|
static func button(parent: Node, caption: String, action: Callable, primary: bool = false) -> Button:
|
||||||
|
var node := Button.new()
|
||||||
|
node.text = caption
|
||||||
|
node.custom_minimum_size = Vector2(112,42)
|
||||||
|
node.mouse_default_cursor_shape = Control.CURSOR_POINTING_HAND
|
||||||
|
node.add_theme_font_override("font",ThemeDB.fallback_font)
|
||||||
|
node.add_theme_font_size_override("font_size",14)
|
||||||
|
style_button(node, primary)
|
||||||
|
node.pressed.connect(action)
|
||||||
|
parent.add_child(node)
|
||||||
|
return node
|
||||||
|
|
||||||
|
static func style_button(node: Button, primary: bool = false) -> void:
|
||||||
|
var accent := GOLD if primary else CYAN
|
||||||
|
node.add_theme_color_override("font_color",INK)
|
||||||
|
node.add_theme_color_override("font_hover_color",Color.WHITE)
|
||||||
|
node.add_theme_color_override("font_disabled_color",Color("617681"))
|
||||||
|
node.add_theme_stylebox_override("normal",box(Color("30291f") if primary else Color("102431"),Color(accent,0.45),10))
|
||||||
|
node.add_theme_stylebox_override("hover",box(Color("453725") if primary else Color("1b3b4a"),accent,10))
|
||||||
|
node.add_theme_stylebox_override("pressed",box(Color("3c3023") if primary else Color("183b47"),accent,10))
|
||||||
|
node.add_theme_stylebox_override("disabled",box(Color("101b24"),Color("293d48"),10))
|
||||||
|
node.add_theme_stylebox_override("focus",box(Color(0,0,0,0),accent,10))
|
||||||
|
|
||||||
|
static func input_style(node: Control) -> void:
|
||||||
|
node.add_theme_font_override("font",ThemeDB.fallback_font)
|
||||||
|
node.add_theme_font_size_override("font_size",15)
|
||||||
|
node.add_theme_color_override("font_color",INK)
|
||||||
|
if node is LineEdit:
|
||||||
|
node.add_theme_stylebox_override("normal",box(Color("07131d"),Color("345461"),12))
|
||||||
|
node.add_theme_stylebox_override("focus",box(Color("0c1e2b"),CYAN,12))
|
||||||
|
elif node is Button: style_button(node)
|
||||||
1
scripts/ui/menu_modal.gd.uid
Normal file
@ -0,0 +1 @@
|
|||||||
|
uid://d13vdtahpj43v
|
||||||