diff --git a/.github/workflows/ci-build.yml b/.github/workflows/ci-build.yml index 384abb2bb9..5b7e9c9a14 100644 --- a/.github/workflows/ci-build.yml +++ b/.github/workflows/ci-build.yml @@ -21,7 +21,7 @@ jobs: runs-on: ubuntu-20.04 container: # If you change this version, change the number in the cache step too. - image: emscripten/emsdk:2.0.31 + image: emscripten/emsdk:3.1.28 steps: - name: Checkout @@ -38,7 +38,7 @@ jobs: uses: actions/cache@v3 with: path: /emsdk/upstream/emscripten/cache - key: 2.0.31-${{ runner.os }} + key: 3.1.28-${{ runner.os }} - name: Patch Emscripten to support LZMA run: | diff --git a/.github/workflows/preview_build.yml b/.github/workflows/preview_build.yml index d2935cefbc..68ca5f083f 100644 --- a/.github/workflows/preview_build.yml +++ b/.github/workflows/preview_build.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-20.04 container: # If you change this version, change the number in the cache step too. - image: emscripten/emsdk:2.0.31 + image: emscripten/emsdk:3.1.28 steps: - name: Update deployment status to in progress @@ -44,7 +44,7 @@ jobs: uses: actions/cache@v3 with: path: /emsdk/upstream/emscripten/cache - key: 2.0.31-${{ runner.os }} + key: 3.1.28-${{ runner.os }} - name: Patch Emscripten to support LZMA run: | diff --git a/cmake/CompileFlags.cmake b/cmake/CompileFlags.cmake index 440c4751e0..5b7711a880 100644 --- a/cmake/CompileFlags.cmake +++ b/cmake/CompileFlags.cmake @@ -61,7 +61,7 @@ macro(compile_flags) if(MSVC) add_compile_options(/W3) - if(MSVC_VERSION GREATER 1929) + if(MSVC_VERSION GREATER 1929 AND CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") # Starting with version 19.30, there is an optimisation bug, see #9966 for details # This flag disables the broken optimisation to work around the bug add_compile_options(/d2ssa-rse-) diff --git a/os/emscripten/Dockerfile b/os/emscripten/Dockerfile index 5d54b54114..ae3579ec0a 100644 --- a/os/emscripten/Dockerfile +++ b/os/emscripten/Dockerfile @@ -1,4 +1,4 @@ -FROM emscripten/emsdk:2.0.34 +FROM emscripten/emsdk:3.1.28 COPY emsdk-liblzma.patch / RUN cd /emsdk/upstream/emscripten && patch -p1 < /emsdk-liblzma.patch diff --git a/os/emscripten/README.md b/os/emscripten/README.md index c78dc6727b..cf8e3ed692 100644 --- a/os/emscripten/README.md +++ b/os/emscripten/README.md @@ -1,40 +1,38 @@ ## How to build with Emscripten -Building with Emscripten works with emsdk 2.0.31 and above. +Please use docker with the supplied `Dockerfile` to build for emscripten. +It takes care of a few things: +- Use a version of emscripten we know works +- Patch in LibLZMA support (as this is not supported by upstream) -Currently there is no LibLZMA support upstream; for this we suggest to apply -the provided patch in this folder to your emsdk installation. - -For convenience, a Dockerfile is supplied that does this patches for you -against upstream emsdk docker. Best way to use it: - -Build the docker image: +First, build the docker image by navigating in the folder this `README.md` is in, and executing: ``` docker build -t emsdk-lzma . ``` -Build the host tools first: +Next, navigate back to the root folder of this project. + +Now we build the host tools first: ``` mkdir build-host docker run -it --rm -v $(pwd):$(pwd) -u $(id -u):$(id -g) --workdir $(pwd)/build-host emsdk-lzma cmake .. -DOPTION_TOOLS_ONLY=ON - docker run -it --rm -v $(pwd):$(pwd) -u $(id -u):$(id -g) --workdir $(pwd)/build-host emsdk-lzma make -j5 tools + docker run -it --rm -v $(pwd):$(pwd) -u $(id -u):$(id -g) --workdir $(pwd)/build-host emsdk-lzma make -j$(nproc) tools ``` -Next, build the game with emscripten: - +Finally, we build the actual game: ``` mkdir build docker run -it --rm -v $(pwd):$(pwd) -u $(id -u):$(id -g) --workdir $(pwd)/build emsdk-lzma emcmake cmake .. -DHOST_BINARY_DIR=../build-host -DCMAKE_BUILD_TYPE=Release -DOPTION_USE_ASSERTS=OFF - docker run -it --rm -v $(pwd):$(pwd) -u $(id -u):$(id -g) --workdir $(pwd)/build emsdk-lzma emmake make -j5 + docker run -it --rm -v $(pwd):$(pwd) -u $(id -u):$(id -g) --workdir $(pwd)/build emsdk-lzma emmake make -j$(nproc) ``` -And now you have in your build folder files like "openttd.html". +In the `build` folder you will now see `openttd.html`. -To run it locally, you would have to start a local webserver, like: +To run it locally, you would have to start a local webserver; something like: ``` cd build python3 -m http.server ```` -Now you can play the game via http://127.0.0.1:8000/openttd.html . +You can now play the game via http://127.0.0.1:8000/openttd.html . diff --git a/os/emscripten/emsdk-liblzma.patch b/os/emscripten/emsdk-liblzma.patch index aa75fa5a49..fbb24e7ca9 100644 --- a/os/emscripten/emsdk-liblzma.patch +++ b/os/emscripten/emsdk-liblzma.patch @@ -13,7 +13,7 @@ of emsdk. diff --git a/tools/settings.py b/tools/settings.py --- a/tools/settings.py +++ b/tools/settings.py -@@ -38,6 +38,7 @@ +@@ -40,6 +40,7 @@ PORTS_SETTINGS = { 'USE_SDL_NET', 'USE_SDL_GFX', 'USE_LIBJPEG', @@ -24,24 +24,23 @@ diff --git a/tools/settings.py b/tools/settings.py diff --git a/src/settings.js b/src/settings.js --- a/src/settings.js +++ b/src/settings.js -@@ -1382,8 +1382,12 @@ var USE_BZIP2 = 0; - // 1 = use libjpeg from emscripten-ports - // [link] - var USE_LIBJPEG = 0; +@@ -1450,6 +1450,10 @@ var USE_GIFLIB = false; + // [compile+link] + var USE_LIBJPEG = false; +// 1 = use liblzma from emscripten-ports -+// [link] -+var USE_LIBLZMA = 0; ++// [compile+link] ++var USE_LIBLZMA = false; + // 1 = use libpng from emscripten-ports - // [link] - var USE_LIBPNG = 0; + // [compile+link] + var USE_LIBPNG = false; diff --git a/tools/ports/liblzma.py b/tools/ports/liblzma.py new file mode 100644 --- /dev/null +++ b/tools/ports/liblzma.py -@@ -0,0 +1,160 @@ +@@ -0,0 +1,151 @@ +# Copyright 2020 The Emscripten Authors. All rights reserved. +# Emscripten is available under two separate licenses, the MIT license and the +# University of Illinois/NCSA Open Source License. Both these licenses can be @@ -52,8 +51,8 @@ new file mode 100644 +import logging +from pathlib import Path + -+VERSION = '5.2.5' -+HASH = '7443674247deda2935220fbc4dfc7665e5bb5a260be8ad858c8bd7d7b9f0f868f04ea45e62eb17c0a5e6a2de7c7500ad2d201e2d668c48ca29bd9eea5a73a3ce' ++VERSION = '5.4.0' ++HASH = '29b2cd25bb5b234b329ffe9547692d2c29be393db9d8d4ce70a66dfdaebd54433e79a89d80c57e58cd4559c3c68b9845507d5fedf3eec1c528a81e3d9ddbd811' + + +def needed(settings): @@ -61,40 +60,31 @@ new file mode 100644 + + +def get(ports, settings, shared): -+ ports.fetch_project('liblzma', 'https://tukaani.org/xz/xz-' + VERSION + '.tar.gz', 'xz-' + VERSION, sha512hash=HASH) ++ ports.fetch_project('liblzma', f'https://tukaani.org/xz/xz-{VERSION}.tar.gz', sha512hash=HASH) + + def create(final): + logging.info('building port: liblzma') + + ports.clear_project_build('liblzma') + -+ source_path = os.path.join(ports.get_dir(), 'liblzma', 'xz-' + VERSION) -+ dest_path = os.path.join(ports.get_build_dir(), 'liblzma') -+ -+ shared.try_delete(dest_path) -+ os.makedirs(dest_path) -+ shutil.rmtree(dest_path, ignore_errors=True) -+ shutil.copytree(source_path, dest_path) ++ source_path = os.path.join(ports.get_dir(), 'liblzma', f'xz-{VERSION}', 'src', 'liblzma') ++ ports.write_file(os.path.join(source_path, 'config.h'), config_h) ++ ports.install_headers(os.path.join(source_path, 'api'), pattern='lzma.h') ++ ports.install_headers(os.path.join(source_path, 'api', 'lzma'), pattern='*.h', target='lzma') + + build_flags = ['-DHAVE_CONFIG_H', '-DTUKLIB_SYMBOL_PREFIX=lzma_', '-fvisibility=hidden'] -+ exclude_dirs = ['xzdec', 'xz', 'lzmainfo'] -+ exclude_files = ['crc32_small.c', 'crc64_small.c', 'crc32_tablegen.c', 'crc64_tablegen.c', 'price_tablegen.c', 'fastpos_tablegen.c' ++ exclude_files = ['crc32_small.c', 'crc64_small.c', 'crc32_tablegen.c', 'crc64_tablegen.c', 'price_tablegen.c', 'fastpos_tablegen.c', + 'tuklib_exit.c', 'tuklib_mbstr_fw.c', 'tuklib_mbstr_width.c', 'tuklib_open_stdxxx.c', 'tuklib_progname.c'] -+ include_dirs_rel = ['../common', 'api', 'common', 'check', 'lz', 'rangecoder', 'lzma', 'delta', 'simple'] -+ -+ Path(dest_path, os.path.join('src', 'config.h')).write_text(config_h) -+ -+ include_dirs = [os.path.join(dest_path, 'src', 'liblzma', p) for p in include_dirs_rel] -+ ports.build_port(os.path.join(dest_path, 'src'), final, flags=build_flags, exclude_dirs=exclude_dirs, exclude_files=exclude_files, includes=include_dirs) ++ include_dirs_rel = ['../common', 'api', 'check', 'common', 'delta', 'lz', 'lzma', 'rangecoder', 'simple'] + -+ ports.install_headers(os.path.join(dest_path, 'src', 'liblzma', 'api'), 'lzma.h') -+ ports.install_headers(os.path.join(dest_path, 'src', 'liblzma', 'api', 'lzma'), '*.h', 'lzma') ++ include_dirs = [os.path.join(source_path, p) for p in include_dirs_rel] ++ ports.build_port(source_path, final, 'liblzma', flags=build_flags, exclude_files=exclude_files, includes=include_dirs) + -+ return [shared.Cache.get_lib('liblzma.a', create, what='port')] ++ return [shared.cache.get_lib('liblzma.a', create, what='port')] + + +def clear(ports, settings, shared): -+ shared.Cache.erase_lib('liblzma.a') ++ shared.cache.erase_lib('liblzma.a') + + +def process_args(ports): @@ -105,7 +95,7 @@ new file mode 100644 + return 'liblzma (USE_LIBLZMA=1; public domain)' + + -+config_h = r''' ++config_h = ''' +#define ASSUME_RAM 128 +#define ENABLE_NLS 1 +#define HAVE_CHECK_CRC32 1 @@ -177,9 +167,9 @@ new file mode 100644 +#define PACKAGE "xz" +#define PACKAGE_BUGREPORT "lasse.collin@tukaani.org" +#define PACKAGE_NAME "XZ Utils" -+#define PACKAGE_STRING "XZ Utils 5.2.5" ++#define PACKAGE_STRING "XZ Utils 5.4.0" +#define PACKAGE_TARNAME "xz" -+#define PACKAGE_VERSION "5.2.5" ++#define PACKAGE_VERSION "5.4.0" +#define SIZEOF_SIZE_T 4 +#define STDC_HEADERS 1 +#define TUKLIB_CPUCORES_SYSCONF 1 @@ -200,5 +190,5 @@ new file mode 100644 +#ifndef __EXTENSIONS__ +# define __EXTENSIONS__ 1 +#endif -+#define VERSION "5.2.5" ++#define VERSION "5.4.0" +''' diff --git a/src/3rdparty/squirrel/squirrel/sqstate.cpp b/src/3rdparty/squirrel/squirrel/sqstate.cpp index 7ccef9d849..51289b6a4c 100644 --- a/src/3rdparty/squirrel/squirrel/sqstate.cpp +++ b/src/3rdparty/squirrel/squirrel/sqstate.cpp @@ -450,7 +450,7 @@ void RefTable::Resize(SQUnsignedInteger size) SQUnsignedInteger oldnumofslots = _numofslots; AllocNodes(size); //rehash - SQUnsignedInteger nfound = 0; + [[maybe_unused]] SQUnsignedInteger nfound = 0; for(SQUnsignedInteger n = 0; n < oldnumofslots; n++) { if(type(t->obj) != OT_NULL) { //add back; diff --git a/src/ai/ai.hpp b/src/ai/ai.hpp index f9112fc177..1e2e99d22f 100644 --- a/src/ai/ai.hpp +++ b/src/ai/ai.hpp @@ -128,11 +128,6 @@ public: */ static void Save(CompanyID company); - /** - * Load data for an AI from a savegame. - */ - static void Load(CompanyID company, int version); - /** * Get the number of days before the next AI should start. */ diff --git a/src/ai/ai_core.cpp b/src/ai/ai_core.cpp index f12b9e02a5..3e18409690 100644 --- a/src/ai/ai_core.cpp +++ b/src/ai/ai_core.cpp @@ -59,6 +59,8 @@ assert(c->ai_instance == nullptr); c->ai_instance = new AIInstance(); c->ai_instance->Initialize(info); + c->ai_instance->LoadOnStack(config->GetToLoadData()); + config->SetToLoadData(nullptr); cur_company.Restore(); @@ -287,21 +289,6 @@ } } -/* static */ void AI::Load(CompanyID company, int version) -{ - if (!_networking || _network_server) { - Company *c = Company::GetIfValid(company); - assert(c != nullptr && c->ai_instance != nullptr); - - Backup cur_company(_current_company, company, FILE_LINE); - c->ai_instance->Load(version); - cur_company.Restore(); - } else { - /* Read, but ignore, the load data */ - AIInstance::LoadEmpty(); - } -} - /* static */ int AI::GetStartNextTime() { /* Find the first company which doesn't exist yet */ diff --git a/src/build_vehicle_gui.cpp b/src/build_vehicle_gui.cpp index 1b2465c11c..d4362ee9a2 100644 --- a/src/build_vehicle_gui.cpp +++ b/src/build_vehicle_gui.cpp @@ -1757,7 +1757,7 @@ struct BuildVehicleWindow : BuildVehicleWindowBase { for (const auto &variant : variants) { if (std::find(this->eng_list.begin(), this->eng_list.end(), variant) == this->eng_list.end()) { const Engine *e = Engine::Get(variant); - list.emplace_back(variant, e->info.variant_id, e->display_flags | EngineDisplayFlags::Shaded, 0); + this->eng_list.emplace_back(variant, e->info.variant_id, e->display_flags | EngineDisplayFlags::Shaded, 0); } } diff --git a/src/engine.cpp b/src/engine.cpp index b6adc44b60..d708dbdeb1 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -559,7 +559,7 @@ void SetupEngines() _engine_pool.CleanPool(); assert(_engine_mngr.size() >= _engine_mngr.NUM_DEFAULT_ENGINES); - uint index = 0; + [[maybe_unused]] uint index = 0; for (const EngineIDMapping &eid : _engine_mngr) { /* Assert is safe; there won't be more than 256 original vehicles * in any case, and we just cleaned the pool. */ diff --git a/src/game/game.hpp b/src/game/game.hpp index c72b081be6..98f436d397 100644 --- a/src/game/game.hpp +++ b/src/game/game.hpp @@ -87,11 +87,6 @@ public: */ static void Save(); - /** - * Load data for a GameScript from a savegame. - */ - static void Load(int version); - /** Wrapper function for GameScanner::GetConsoleList */ static std::string GetConsoleList(bool newest_only = false); /** Wrapper function for GameScanner::GetConsoleLibraryList */ diff --git a/src/game/game_core.cpp b/src/game/game_core.cpp index 4a9fcc651a..d933f69401 100644 --- a/src/game/game_core.cpp +++ b/src/game/game_core.cpp @@ -88,6 +88,8 @@ Game::info = info; Game::instance = new GameInstance(); Game::instance->Initialize(info); + Game::instance->LoadOnStack(config->GetToLoadData()); + config->SetToLoadData(nullptr); cur_company.Restore(); @@ -211,18 +213,6 @@ } } -/* static */ void Game::Load(int version) -{ - if (Game::instance != nullptr && (!_networking || _network_server)) { - Backup cur_company(_current_company, OWNER_DEITY, FILE_LINE); - Game::instance->Load(version); - cur_company.Restore(); - } else { - /* Read, but ignore, the load data */ - GameInstance::LoadEmpty(); - } -} - /* static */ std::string Game::GetConsoleList(bool newest_only) { return Game::scanner_info->GetConsoleList(newest_only); diff --git a/src/lang/brazilian_portuguese.txt b/src/lang/brazilian_portuguese.txt index 2e7caca57e..cc404c39bd 100644 --- a/src/lang/brazilian_portuguese.txt +++ b/src/lang/brazilian_portuguese.txt @@ -2864,6 +2864,7 @@ STR_FOUND_TOWN_RANDOM_TOWN_BUTTON :{BLACK}Cidade A STR_FOUND_TOWN_RANDOM_TOWN_TOOLTIP :{BLACK}Constrói cidade num local aleatório STR_FOUND_TOWN_MANY_RANDOM_TOWNS :{BLACK}Várias cidades aleatórias STR_FOUND_TOWN_RANDOM_TOWNS_TOOLTIP :{BLACK}Cobrir o mapa com cidades colocadas aleatoriamente +STR_FOUND_TOWN_EXPAND_ALL_TOWNS_TOOLTIP :{BLACK}Fazer com que todas as cidades cresçam ligeiramente STR_FOUND_TOWN_NAME_TITLE :{YELLOW}Nome da cidade: STR_FOUND_TOWN_NAME_EDITOR_TITLE :{BLACK}Coloque o nome da cidade @@ -4535,7 +4536,7 @@ STR_TIMETABLE_CLEAR_TIME :{BLACK}Limpar H STR_TIMETABLE_CLEAR_TIME_TOOLTIP :{BLACK}Limpar a quantidade de tempo para a ordem destacada STR_TIMETABLE_CHANGE_SPEED :{BLACK}Alterar Limite de Vel. -STR_TIMETABLE_CHANGE_SPEED_TOOLTIP :{BLACK}Altera a velocidade máxima de viagem para a ordem selecionada +STR_TIMETABLE_CHANGE_SPEED_TOOLTIP :{BLACK}Altera a velocidade máxima de viagem para a ordem selecionada. Ctrl+Clique define a velocidade para todas as ordens STR_TIMETABLE_CLEAR_SPEED :{BLACK}Limpa Limite de Vel. STR_TIMETABLE_CLEAR_SPEED_TOOLTIP :{BLACK}Limpar a velocidade máxima de viagem para a ordem selecionada diff --git a/src/lang/catalan.txt b/src/lang/catalan.txt index d62b8eea22..45bb3928a8 100644 --- a/src/lang/catalan.txt +++ b/src/lang/catalan.txt @@ -3346,6 +3346,7 @@ STR_SPRITE_ALIGNER_SPRITE_TOOLTIP :{BLACK}Represen STR_SPRITE_ALIGNER_MOVE_TOOLTIP :{BLACK}Desplaça l'sprite un píxel en el sentit indicat. Amb Ctrl+Clic el desplaça 8 píxels. ###length 2 +STR_SPRITE_ALIGNER_CENTRE_SPRITE :{BLACK}Sprite centrat STR_SPRITE_ALIGNER_RESET_BUTTON :{BLACK}Restableix relatius diff --git a/src/lang/english_AU.txt b/src/lang/english_AU.txt index f0f81701b5..4bdef34b96 100644 --- a/src/lang/english_AU.txt +++ b/src/lang/english_AU.txt @@ -2890,6 +2890,8 @@ STR_FOUND_TOWN_RANDOM_TOWN_BUTTON :{BLACK}Random T STR_FOUND_TOWN_RANDOM_TOWN_TOOLTIP :{BLACK}Found town in random location STR_FOUND_TOWN_MANY_RANDOM_TOWNS :{BLACK}Many random towns STR_FOUND_TOWN_RANDOM_TOWNS_TOOLTIP :{BLACK}Cover the map with randomly placed towns +STR_FOUND_TOWN_EXPAND_ALL_TOWNS :{BLACK}Expand all towns +STR_FOUND_TOWN_EXPAND_ALL_TOWNS_TOOLTIP :{BLACK}Make all towns grow slightly STR_FOUND_TOWN_NAME_TITLE :{YELLOW}Town name: STR_FOUND_TOWN_NAME_EDITOR_TITLE :{BLACK}Enter town name @@ -4555,22 +4557,22 @@ STR_TIMETABLE_STARTING_DATE :{BLACK}Start da STR_TIMETABLE_STARTING_DATE_TOOLTIP :{BLACK}Select a date as starting point of this timetable. Ctrl+Click distributes all vehicles sharing this order evenly from the given date based on their relative order, if the order is completely timetabled STR_TIMETABLE_CHANGE_TIME :{BLACK}Change Time -STR_TIMETABLE_WAIT_TIME_TOOLTIP :{BLACK}Change the amount of time that the highlighted order should take +STR_TIMETABLE_WAIT_TIME_TOOLTIP :{BLACK}Change the amount of time that the highlighted order should take. Ctrl+Click sets the time for all orders STR_TIMETABLE_CLEAR_TIME :{BLACK}Clear Time -STR_TIMETABLE_CLEAR_TIME_TOOLTIP :{BLACK}Clear the amount of time for the highlighted order +STR_TIMETABLE_CLEAR_TIME_TOOLTIP :{BLACK}Clear the amount of time for the highlighted order. Ctrl+Click clears the time for all orders STR_TIMETABLE_CHANGE_SPEED :{BLACK}Change Speed Limit -STR_TIMETABLE_CHANGE_SPEED_TOOLTIP :{BLACK}Change the maximum travel speed of the highlighted order +STR_TIMETABLE_CHANGE_SPEED_TOOLTIP :{BLACK}Change the maximum travel speed of the highlighted order. Ctrl+Click sets the speed for all orders STR_TIMETABLE_CLEAR_SPEED :{BLACK}Clear Speed Limit -STR_TIMETABLE_CLEAR_SPEED_TOOLTIP :{BLACK}Clear the maximum travel speed of the highlighted order +STR_TIMETABLE_CLEAR_SPEED_TOOLTIP :{BLACK}Clear the maximum travel speed of the highlighted order. Ctrl+Click clears the speed for all orders STR_TIMETABLE_RESET_LATENESS :{BLACK}Reset Late Counter STR_TIMETABLE_RESET_LATENESS_TOOLTIP :{BLACK}Reset the lateness counter, so the vehicle will be on time STR_TIMETABLE_AUTOFILL :{BLACK}Autofill -STR_TIMETABLE_AUTOFILL_TOOLTIP :{BLACK}Fill the timetable automatically with the values from the next journey (Ctrl+Click to try to keep waiting times) +STR_TIMETABLE_AUTOFILL_TOOLTIP :{BLACK}Fill the timetable automatically with the values from the next journey. Ctrl+Click to try to keep waiting times STR_TIMETABLE_EXPECTED :{BLACK}Expected STR_TIMETABLE_SCHEDULED :{BLACK}Scheduled @@ -4826,6 +4828,7 @@ STR_ERROR_TOO_MANY_INDUSTRIES :{WHITE}... too STR_ERROR_CAN_T_GENERATE_INDUSTRIES :{WHITE}Can't generate industries... STR_ERROR_CAN_T_BUILD_HERE :{WHITE}Can't build {STRING} here... STR_ERROR_CAN_T_CONSTRUCT_THIS_INDUSTRY :{WHITE}Can't construct this industry type here... +STR_ERROR_CAN_T_PROSPECT_INDUSTRY :{WHITE}Can't prospect industry... STR_ERROR_INDUSTRY_TOO_CLOSE :{WHITE}... too close to another industry STR_ERROR_MUST_FOUND_TOWN_FIRST :{WHITE}... must found town first STR_ERROR_ONLY_ONE_ALLOWED_PER_TOWN :{WHITE}... only one allowed per town @@ -4840,6 +4843,8 @@ STR_ERROR_FOREST_CAN_ONLY_BE_PLANTED :{WHITE}... fore STR_ERROR_CAN_ONLY_BE_BUILT_ABOVE_SNOW_LINE :{WHITE}... can only be built above the snow-line STR_ERROR_CAN_ONLY_BE_BUILT_BELOW_SNOW_LINE :{WHITE}... can only be built below the snow-line +STR_ERROR_PROSPECTING_WAS_UNLUCKY :{WHITE}The funding failed to prospect due to bad luck; try again +STR_ERROR_NO_SUITABLE_PLACES_FOR_PROSPECTING :{WHITE}There were no suitable places to prospect for this industry STR_ERROR_NO_SUITABLE_PLACES_FOR_INDUSTRIES :{WHITE}There were no suitable places for '{STRING}' industries STR_ERROR_NO_SUITABLE_PLACES_FOR_INDUSTRIES_EXPLANATION :{WHITE}Change the map generation parameters to get a better map diff --git a/src/lang/english_US.txt b/src/lang/english_US.txt index 3aa42a1952..d479ff9a93 100644 --- a/src/lang/english_US.txt +++ b/src/lang/english_US.txt @@ -2891,6 +2891,8 @@ STR_FOUND_TOWN_RANDOM_TOWN_BUTTON :{BLACK}Random T STR_FOUND_TOWN_RANDOM_TOWN_TOOLTIP :{BLACK}Found town in random location STR_FOUND_TOWN_MANY_RANDOM_TOWNS :{BLACK}Many random towns STR_FOUND_TOWN_RANDOM_TOWNS_TOOLTIP :{BLACK}Cover the map with randomly placed towns +STR_FOUND_TOWN_EXPAND_ALL_TOWNS :{BLACK}Expand all towns +STR_FOUND_TOWN_EXPAND_ALL_TOWNS_TOOLTIP :{BLACK}Make all towns grow slightly STR_FOUND_TOWN_NAME_TITLE :{YELLOW}Town name: STR_FOUND_TOWN_NAME_EDITOR_TITLE :{BLACK}Enter town name @@ -4556,22 +4558,22 @@ STR_TIMETABLE_STARTING_DATE :{BLACK}Start Da STR_TIMETABLE_STARTING_DATE_TOOLTIP :{BLACK}Select a date as starting point of this timetable. Ctrl+Click distributes all vehicles sharing this order evenly from the given date based on their relative order, if the order is completely timetabled STR_TIMETABLE_CHANGE_TIME :{BLACK}Change Time -STR_TIMETABLE_WAIT_TIME_TOOLTIP :{BLACK}Change the amount of time that the highlighted order should take +STR_TIMETABLE_WAIT_TIME_TOOLTIP :{BLACK}Change the amount of time that the highlighted order should take. Ctrl+Click sets the time for all orders STR_TIMETABLE_CLEAR_TIME :{BLACK}Clear Time -STR_TIMETABLE_CLEAR_TIME_TOOLTIP :{BLACK}Clear the amount of time for the highlighted order +STR_TIMETABLE_CLEAR_TIME_TOOLTIP :{BLACK}Clear the amount of time for the highlighted order. Ctrl+Click clears the time for all orders STR_TIMETABLE_CHANGE_SPEED :{BLACK}Change Speed Limit -STR_TIMETABLE_CHANGE_SPEED_TOOLTIP :{BLACK}Change the maximum travel speed of the highlighted order +STR_TIMETABLE_CHANGE_SPEED_TOOLTIP :{BLACK}Change the maximum travel speed of the highlighted order. Ctrl+Click sets the speed for all orders STR_TIMETABLE_CLEAR_SPEED :{BLACK}Clear Speed Limit -STR_TIMETABLE_CLEAR_SPEED_TOOLTIP :{BLACK}Clear the maximum travel speed of the highlighted order +STR_TIMETABLE_CLEAR_SPEED_TOOLTIP :{BLACK}Clear the maximum travel speed of the highlighted order. Ctrl+Click clears the speed for all orders STR_TIMETABLE_RESET_LATENESS :{BLACK}Reset Late Counter STR_TIMETABLE_RESET_LATENESS_TOOLTIP :{BLACK}Reset the lateness counter, so the vehicle will be on time STR_TIMETABLE_AUTOFILL :{BLACK}Autofill -STR_TIMETABLE_AUTOFILL_TOOLTIP :{BLACK}Fill the timetable automatically with the values from the next journey (Ctrl+Click to try to keep waiting times) +STR_TIMETABLE_AUTOFILL_TOOLTIP :{BLACK}Fill the timetable automatically with the values from the next journey. Ctrl+Click to try to keep waiting times STR_TIMETABLE_EXPECTED :{BLACK}Expected STR_TIMETABLE_SCHEDULED :{BLACK}Scheduled @@ -4827,6 +4829,7 @@ STR_ERROR_TOO_MANY_INDUSTRIES :{WHITE}... too STR_ERROR_CAN_T_GENERATE_INDUSTRIES :{WHITE}Can't generate industries... STR_ERROR_CAN_T_BUILD_HERE :{WHITE}Can't build {STRING} here... STR_ERROR_CAN_T_CONSTRUCT_THIS_INDUSTRY :{WHITE}Can't construct this industry type here... +STR_ERROR_CAN_T_PROSPECT_INDUSTRY :{WHITE}Can't prospect industry... STR_ERROR_INDUSTRY_TOO_CLOSE :{WHITE}... too close to another industry STR_ERROR_MUST_FOUND_TOWN_FIRST :{WHITE}... must found town first STR_ERROR_ONLY_ONE_ALLOWED_PER_TOWN :{WHITE}... only one allowed per town @@ -4841,6 +4844,8 @@ STR_ERROR_FOREST_CAN_ONLY_BE_PLANTED :{WHITE}... fore STR_ERROR_CAN_ONLY_BE_BUILT_ABOVE_SNOW_LINE :{WHITE}... can only be built above the snow-line STR_ERROR_CAN_ONLY_BE_BUILT_BELOW_SNOW_LINE :{WHITE}... can only be built below the snow-line +STR_ERROR_PROSPECTING_WAS_UNLUCKY :{WHITE}The funding failed to prospect due to bad luck; try again +STR_ERROR_NO_SUITABLE_PLACES_FOR_PROSPECTING :{WHITE}There were no suitable places to prospect for this industry STR_ERROR_NO_SUITABLE_PLACES_FOR_INDUSTRIES :{WHITE}There were no suitable places for '{STRING}' industries STR_ERROR_NO_SUITABLE_PLACES_FOR_INDUSTRIES_EXPLANATION :{WHITE}Change the map generation parameters to get a better map diff --git a/src/lang/finnish.txt b/src/lang/finnish.txt index b25163d83c..34d97ba514 100644 --- a/src/lang/finnish.txt +++ b/src/lang/finnish.txt @@ -4801,6 +4801,7 @@ STR_ERROR_TOO_MANY_INDUSTRIES :{WHITE}... liik STR_ERROR_CAN_T_GENERATE_INDUSTRIES :{WHITE}Teollisuuslaitoksia ei voi luoda... STR_ERROR_CAN_T_BUILD_HERE :{WHITE}{STRING}: tähän ei voi rakentaa... STR_ERROR_CAN_T_CONSTRUCT_THIS_INDUSTRY :{WHITE}Teollisuustyyppiä ei voi rakentaa tähän... +STR_ERROR_CAN_T_PROSPECT_INDUSTRY :{WHITE}Ei voida koekaivaa… STR_ERROR_INDUSTRY_TOO_CLOSE :{WHITE}... liian lähellä toista teollisuuslaitosta STR_ERROR_MUST_FOUND_TOWN_FIRST :{WHITE}... kunta pitää perustaa ensin STR_ERROR_ONLY_ONE_ALLOWED_PER_TOWN :{WHITE}... vain yksi on sallittu kuntaa kohden @@ -4815,6 +4816,8 @@ STR_ERROR_FOREST_CAN_ONLY_BE_PLANTED :{WHITE}... mets STR_ERROR_CAN_ONLY_BE_BUILT_ABOVE_SNOW_LINE :{WHITE}... voidaan rakentaa vain lumirajan yläpuolelle STR_ERROR_CAN_ONLY_BE_BUILT_BELOW_SNOW_LINE :{WHITE}... voidaan rakentaa vain lumirajan alapuolelle +STR_ERROR_PROSPECTING_WAS_UNLUCKY :{WHITE}Rahoittamasi koekaivaus epäonnistui; yritä uudelleen +STR_ERROR_NO_SUITABLE_PLACES_FOR_PROSPECTING :{WHITE}Ei ollut sopivia paikkoja tämän teollisuuslaitoksen koekaivauksille STR_ERROR_NO_SUITABLE_PLACES_FOR_INDUSTRIES :{WHITE}Ei ollut sopivia paikkoja ”{STRING}”-teollisuuslaitoksille STR_ERROR_NO_SUITABLE_PLACES_FOR_INDUSTRIES_EXPLANATION :{WHITE}Muuta kartan parametreja saadaksesi paremman kartan diff --git a/src/lang/italian.txt b/src/lang/italian.txt index e25820e98d..77c9c7e119 100644 --- a/src/lang/italian.txt +++ b/src/lang/italian.txt @@ -4843,6 +4843,7 @@ STR_ERROR_TOO_MANY_INDUSTRIES :{WHITE}... trop STR_ERROR_CAN_T_GENERATE_INDUSTRIES :{WHITE}Impossibile generare industrie... STR_ERROR_CAN_T_BUILD_HERE :{WHITE}Impossibile costruire {STRING} qui... STR_ERROR_CAN_T_CONSTRUCT_THIS_INDUSTRY :{WHITE}Impossibile costruire l'industria qui... +STR_ERROR_CAN_T_PROSPECT_INDUSTRY :{WHITE}Non si può eseguire la prospezione... STR_ERROR_INDUSTRY_TOO_CLOSE :{WHITE}... troppo vicina ad un'altra industria STR_ERROR_MUST_FOUND_TOWN_FIRST :{WHITE}... bisogna fondare una città prima STR_ERROR_ONLY_ONE_ALLOWED_PER_TOWN :{WHITE}... ne è ammessa solo una per città @@ -4857,6 +4858,8 @@ STR_ERROR_FOREST_CAN_ONLY_BE_PLANTED :{WHITE}... una STR_ERROR_CAN_ONLY_BE_BUILT_ABOVE_SNOW_LINE :{WHITE}... può essere costruita solo al di sopra della linea delle nevi perenni STR_ERROR_CAN_ONLY_BE_BUILT_BELOW_SNOW_LINE :{WHITE}... può essere costruita solo al di sotto della linea delle nevi perenni +STR_ERROR_PROSPECTING_WAS_UNLUCKY :{WHITE}Nonostante il finanziamento la prospezione è fallita per sfortunate circostanze; riprova +STR_ERROR_NO_SUITABLE_PLACES_FOR_PROSPECTING :{WHITE}Non c'erano luoghi adatti per la prospezione di questa industria STR_ERROR_NO_SUITABLE_PLACES_FOR_INDUSTRIES :{WHITE}Nessun luogo adatto per le industrie '{STRING}' STR_ERROR_NO_SUITABLE_PLACES_FOR_INDUSTRIES_EXPLANATION :{WHITE}Modificare i parametri di generazione delle mappa in modo da ottenerne una migliore diff --git a/src/lang/korean.txt b/src/lang/korean.txt index dc9f884734..9d8561a934 100644 --- a/src/lang/korean.txt +++ b/src/lang/korean.txt @@ -3815,6 +3815,8 @@ STR_FOUND_TOWN_RANDOM_TOWN_BUTTON :{BLACK}무작 STR_FOUND_TOWN_RANDOM_TOWN_TOOLTIP :{BLACK}무작위 위치에 도시를 건설합니다 STR_FOUND_TOWN_MANY_RANDOM_TOWNS :{BLACK}무작위로 여러 도시 건설 STR_FOUND_TOWN_RANDOM_TOWNS_TOOLTIP :{BLACK}무작위로 도시를 건설합니다 +STR_FOUND_TOWN_EXPAND_ALL_TOWNS :{BLACK}모든 도시 확장 +STR_FOUND_TOWN_EXPAND_ALL_TOWNS_TOOLTIP :{BLACK}모든 도시를 조금씩 확장시킵니다 STR_FOUND_TOWN_NAME_TITLE :{YELLOW}도시 이름: STR_FOUND_TOWN_NAME_EDITOR_TITLE :{BLACK}도시 이름 입력 @@ -4345,8 +4347,8 @@ STR_SPRITE_ALIGNER_SPRITE_TOOLTIP :{BLACK}현재 STR_SPRITE_ALIGNER_MOVE_TOOLTIP :{BLACK}X축이나 Y축 방향으로 스프라이트를 이동시킵니다. CTRL+클릭하면 한 번에 8씩 이동시킬 수 있습니다 ###length 2 -STR_SPRITE_ALIGNER_CENTRE_OFFSET :{BLACK}오프셋 가운데로 -STR_SPRITE_ALIGNER_CENTRE_SPRITE :{BLACK}스프라이트 가운데로 +STR_SPRITE_ALIGNER_CENTRE_OFFSET :{BLACK}오프셋 가운데 정렬 +STR_SPRITE_ALIGNER_CENTRE_SPRITE :{BLACK}스프라이트 가운데 정렬 STR_SPRITE_ALIGNER_CROSSHAIR :{BLACK}십자선 @@ -5908,22 +5910,22 @@ STR_TIMETABLE_STARTING_DATE :{BLACK}시작 STR_TIMETABLE_STARTING_DATE_TOOLTIP :{BLACK}이 시간표의 시작 날짜를 선택하세요. CTRL+클릭하면, 시간표가 모두 작성되어 있다는 가정 하에, 주어진 경로를 기반으로 설정한 날짜부터 이 경로를 공유하는 모든 차량을 균등하게 출발시킵니다 STR_TIMETABLE_CHANGE_TIME :{BLACK}시간값 변경 -STR_TIMETABLE_WAIT_TIME_TOOLTIP :{BLACK}선택한 경로에서 소요되는 시간 값을 변경합니다 (CTRL+클릭하면 모든 경로의 시간을 설정합니다) +STR_TIMETABLE_WAIT_TIME_TOOLTIP :{BLACK}선택한 경로에서 소요되는 시간 값을 변경합니다. CTRL+클릭하면 모든 경로에 그 시간 값을 설정합니다 STR_TIMETABLE_CLEAR_TIME :{BLACK}시간값 초기화 -STR_TIMETABLE_CLEAR_TIME_TOOLTIP :{BLACK}선택한 경로에서 소요되는 시간 값을 초기화합니다 (CTRL+클릭하면 모든 경로의 시간을 초기화합니다) +STR_TIMETABLE_CLEAR_TIME_TOOLTIP :{BLACK}선택한 경로에서 소요되는 시간 값을 초기화합니다. CTRL+클릭하면 모든 경로의 시간을 초기화합니다 STR_TIMETABLE_CHANGE_SPEED :{BLACK}속력 제한 -STR_TIMETABLE_CHANGE_SPEED_TOOLTIP :{BLACK}선택한 경로의 최대 여행 속력을 제한합니다 (CTRL+클릭하면 모든 경로의 속력을 설정합니다) +STR_TIMETABLE_CHANGE_SPEED_TOOLTIP :{BLACK}선택한 경로의 최대 여행 속력을 제한합니다. CTRL+클릭하면 모든 경로에 그 속력 값을 설정합니다 STR_TIMETABLE_CLEAR_SPEED :{BLACK}속력 제한값 초기화 -STR_TIMETABLE_CLEAR_SPEED_TOOLTIP :{BLACK}선택한 경로의 최대 여행 속력 제한값을 초기화합니다 (CTRL+클릭하면 모든 경로의 속력을 초기화합니다) +STR_TIMETABLE_CLEAR_SPEED_TOOLTIP :{BLACK}선택한 경로의 최대 여행 속력 제한값을 초기화합니다. CTRL+클릭하면 모든 경로의 속력을 초기화합니다 STR_TIMETABLE_RESET_LATENESS :{BLACK}지연 시간 초기화 STR_TIMETABLE_RESET_LATENESS_TOOLTIP :{BLACK}이 차량의 지연 시간값을 초기화하여, 정시운행 상태로 바꿉니다 STR_TIMETABLE_AUTOFILL :{BLACK}자동 시간 설정 -STR_TIMETABLE_AUTOFILL_TOOLTIP :{BLACK}다음 운행시 자동으로 값을 얻어 시간표를 완성합니다 (역에 머무르는 시간값을 유지하려면 CTRL+클릭하십시오) +STR_TIMETABLE_AUTOFILL_TOOLTIP :{BLACK}다음 운행시 자동으로 값을 얻어 시간표를 완성합니다. 역에 머무르는 시간값을 유지하려면 CTRL+클릭하세요 STR_TIMETABLE_AUTOMATE :{BLACK}자동 STR_TIMETABLE_AUTOMATE_TOOLTIP :{BLACK}각 운행마다 자동으로 값을 얻어 시간표를 만듭니다. @@ -6289,6 +6291,7 @@ STR_ERROR_TOO_MANY_INDUSTRIES :{WHITE}... 산 STR_ERROR_CAN_T_GENERATE_INDUSTRIES :{WHITE}산업시설을 생성할 수 없습니다... STR_ERROR_CAN_T_BUILD_HERE :{WHITE}여기에 {STRING}{G 0 "을" "를"} 건설할 수 없습니다... STR_ERROR_CAN_T_CONSTRUCT_THIS_INDUSTRY :{WHITE}여기에 산업시설을 건설할 수 없습니다... +STR_ERROR_CAN_T_PROSPECT_INDUSTRY :{WHITE}산업시설에 투자할 수 없습니다... STR_ERROR_INDUSTRY_TOO_CLOSE :{WHITE}... 다른 산업시설과 너무 가깝습니다 STR_ERROR_MUST_FOUND_TOWN_FIRST :{WHITE}... 도시를 먼저 만들어야 합니다 STR_ERROR_ONLY_ONE_ALLOWED_PER_TOWN :{WHITE}... 한 도시에 하나만 지을 수 있습니다 @@ -6303,6 +6306,8 @@ STR_ERROR_FOREST_CAN_ONLY_BE_PLANTED :{WHITE}... 숲 STR_ERROR_CAN_ONLY_BE_BUILT_ABOVE_SNOW_LINE :{WHITE}... 만년설 고도 위에만 지을 수 있습니다 STR_ERROR_CAN_ONLY_BE_BUILT_BELOW_SNOW_LINE :{WHITE}... 만년설 고도 아래에만 지을 수 있습니다 +STR_ERROR_PROSPECTING_WAS_UNLUCKY :{WHITE}운이 나빠 투자에 실패했습니다. 다시 시도해주세요. +STR_ERROR_NO_SUITABLE_PLACES_FOR_PROSPECTING :{WHITE}이 산업시설을 투자하기에 적합한 장소가 없습니다 STR_ERROR_NO_SUITABLE_PLACES_FOR_INDUSTRIES :{WHITE}적당한 장소가 없어 '{STRING}'{G 0 "이" "가"} 지어지지 않았습니다 STR_ERROR_NO_SUITABLE_PLACES_FOR_INDUSTRIES_EXPLANATION :{WHITE}더 나은 지도가 생성되도록 설정 값을 변경해보십시오 diff --git a/src/lang/portuguese.txt b/src/lang/portuguese.txt index 1b5cb9cfeb..a018abc871 100644 --- a/src/lang/portuguese.txt +++ b/src/lang/portuguese.txt @@ -1315,11 +1315,11 @@ STR_CONFIG_SETTING_MAX_TUNNEL_LENGTH :Tamanho máximo STR_CONFIG_SETTING_MAX_TUNNEL_LENGTH_HELPTEXT :Tamanho máximo para construção de túneis STR_CONFIG_SETTING_RAW_INDUSTRY_CONSTRUCTION_METHOD :Método de financiamento de indústrias primárias: {STRING} -STR_CONFIG_SETTING_RAW_INDUSTRY_CONSTRUCTION_METHOD_HELPTEXT :Método de financiar uma indústria primária. 'nenhum' significa que não é possível financiar nenhuma, 'prospecção' significa que é possível financiar, mas a construção é feita num local arbitrário no mapa e até pode falhar, 'como as outras' significa que as indústrias de matérias primas podem ser construídas em qualquer sítio pelas empresas, como se fossem indústrias de processamento +STR_CONFIG_SETTING_RAW_INDUSTRY_CONSTRUCTION_METHOD_HELPTEXT :Método de financiar uma indústria primária. 'nenhum' significa que não é possível financiar nenhuma; 'em prospeção' significa que é possível financiar, mas a construção é feita num local aleatório no mapa e pode até falhar; 'como as outras' significa que as indústrias de matérias primas podem ser construídas em qualquer local escolhido pelas empresas, como se fossem indústrias de processamento ###length 3 STR_CONFIG_SETTING_RAW_INDUSTRY_CONSTRUCTION_METHOD_NONE :Nenhum STR_CONFIG_SETTING_RAW_INDUSTRY_CONSTRUCTION_METHOD_NORMAL :Como as outras -STR_CONFIG_SETTING_RAW_INDUSTRY_CONSTRUCTION_METHOD_PROSPECTING :Prospecção +STR_CONFIG_SETTING_RAW_INDUSTRY_CONSTRUCTION_METHOD_PROSPECTING :Em prospeção STR_CONFIG_SETTING_INDUSTRY_PLATFORM :Área plana à volta das industrias: {STRING} STR_CONFIG_SETTING_INDUSTRY_PLATFORM_HELPTEXT :Quantidade de terreno plano á volta de uma industria. Isto garante que terreno vazio esteja disponível para construir linhas, etc @@ -2900,7 +2900,7 @@ STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_TOOLTIP :{BLACK}Cobrir o STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_CAPTION :{WHITE}Criar indústrias aleatórias STR_FUND_INDUSTRY_MANY_RANDOM_INDUSTRIES_QUERY :{YELLOW}Tem a certeza que deseja criar muitas indústrias aleatórias? STR_FUND_INDUSTRY_INDUSTRY_BUILD_COST :{BLACK}Custo: {YELLOW}{CURRENCY_LONG} -STR_FUND_INDUSTRY_PROSPECT_NEW_INDUSTRY :{BLACK}Prospectar +STR_FUND_INDUSTRY_PROSPECT_NEW_INDUSTRY :{BLACK}Prospetar STR_FUND_INDUSTRY_BUILD_NEW_INDUSTRY :{BLACK}Construir STR_FUND_INDUSTRY_FUND_NEW_INDUSTRY :{BLACK}Criar STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES :{BLACK}Remover todas as indústrias @@ -4804,6 +4804,7 @@ STR_ERROR_TOO_MANY_INDUSTRIES :{WHITE}... dema STR_ERROR_CAN_T_GENERATE_INDUSTRIES :{WHITE}Não é possível gerar indústrias... STR_ERROR_CAN_T_BUILD_HERE :{WHITE}Não é possível construir {STRING} aqui... STR_ERROR_CAN_T_CONSTRUCT_THIS_INDUSTRY :{WHITE}Não é possível construir este tipo de indústria aqui... +STR_ERROR_CAN_T_PROSPECT_INDUSTRY :{WHITE}Não é possível prospetar indústria... STR_ERROR_INDUSTRY_TOO_CLOSE :{WHITE}... muito perto de outra indústria STR_ERROR_MUST_FOUND_TOWN_FIRST :{WHITE}... é necessário construir uma localidade primeiro STR_ERROR_ONLY_ONE_ALLOWED_PER_TOWN :{WHITE}... só é permitido uma por localidade @@ -4818,6 +4819,8 @@ STR_ERROR_FOREST_CAN_ONLY_BE_PLANTED :{WHITE}... a fl STR_ERROR_CAN_ONLY_BE_BUILT_ABOVE_SNOW_LINE :{WHITE}... só se pode construir acima da linha da neve STR_ERROR_CAN_ONLY_BE_BUILT_BELOW_SNOW_LINE :{WHITE}... só se pode construir abaixo da linha da neve +STR_ERROR_PROSPECTING_WAS_UNLUCKY :{WHITE}O financiamento falhou em prospetar devido ao azar; tente novamente +STR_ERROR_NO_SUITABLE_PLACES_FOR_PROSPECTING :{WHITE}Não havia locais adequados para prospetar esta indústria STR_ERROR_NO_SUITABLE_PLACES_FOR_INDUSTRIES :{WHITE}Não foram encontrados locais adequados para '{STRING}' indústrias STR_ERROR_NO_SUITABLE_PLACES_FOR_INDUSTRIES_EXPLANATION :{WHITE}Altera os parâmetros de geração do mapa para obter um mapa melhor diff --git a/src/lang/romanian.txt b/src/lang/romanian.txt index 65630d38f6..9a55c07c57 100644 --- a/src/lang/romanian.txt +++ b/src/lang/romanian.txt @@ -4800,6 +4800,7 @@ STR_ERROR_TOO_MANY_INDUSTRIES :{WHITE}... prea STR_ERROR_CAN_T_GENERATE_INDUSTRIES :{WHITE}Nu pot genera industrii... STR_ERROR_CAN_T_BUILD_HERE :{WHITE}Nu se poate construi {STRING} aici... STR_ERROR_CAN_T_CONSTRUCT_THIS_INDUSTRY :{WHITE}Acest tip de industrie nu se poate construi aici... +STR_ERROR_CAN_T_PROSPECT_INDUSTRY :{WHITE}Nu pot prospecta industria... STR_ERROR_INDUSTRY_TOO_CLOSE :{WHITE}... prea aproape de altă industrie STR_ERROR_MUST_FOUND_TOWN_FIRST :{WHITE}... mai întâi trebuie creat un oraş STR_ERROR_ONLY_ONE_ALLOWED_PER_TOWN :{WHITE}... un singur obiectiv de acest tip este permis per oraş @@ -4814,6 +4815,7 @@ STR_ERROR_FOREST_CAN_ONLY_BE_PLANTED :{WHITE}... păd STR_ERROR_CAN_ONLY_BE_BUILT_ABOVE_SNOW_LINE :{WHITE}... poate fi construit doar deasupra liniei zăpezii STR_ERROR_CAN_ONLY_BE_BUILT_BELOW_SNOW_LINE :{WHITE}... poate fi construit doar sub linia zăpezii +STR_ERROR_NO_SUITABLE_PLACES_FOR_PROSPECTING :{WHITE}Nu există locuri potrivite de prospectat pentru această industrie STR_ERROR_NO_SUITABLE_PLACES_FOR_INDUSTRIES :{WHITE}Nu s-au găsit locuri potrivite pentru industriile '{STRING}' STR_ERROR_NO_SUITABLE_PLACES_FOR_INDUSTRIES_EXPLANATION :{WHITE}Modifică parametrii generatorului ca să obții o hartă mai bună diff --git a/src/lang/russian.txt b/src/lang/russian.txt index 9301892bb5..4a986047c3 100644 --- a/src/lang/russian.txt +++ b/src/lang/russian.txt @@ -5010,6 +5010,7 @@ STR_ERROR_TOO_MANY_INDUSTRIES :{WHITE}... сл STR_ERROR_CAN_T_GENERATE_INDUSTRIES :{WHITE}Невозможно создать предприятия... STR_ERROR_CAN_T_BUILD_HERE :{WHITE}Здесь нельзя создать {STRING}... STR_ERROR_CAN_T_CONSTRUCT_THIS_INDUSTRY :{WHITE}Построить это предприятие невозможно... +STR_ERROR_CAN_T_PROSPECT_INDUSTRY :{WHITE}Не удалось разведать месторождение... STR_ERROR_INDUSTRY_TOO_CLOSE :{WHITE}... слишком близко к другому предприятию STR_ERROR_MUST_FOUND_TOWN_FIRST :{WHITE}... сначала постройте город STR_ERROR_ONLY_ONE_ALLOWED_PER_TOWN :{WHITE}... такой объект уже есть в городе @@ -5024,6 +5025,8 @@ STR_ERROR_FOREST_CAN_ONLY_BE_PLANTED :{WHITE}... ле STR_ERROR_CAN_ONLY_BE_BUILT_ABOVE_SNOW_LINE :{WHITE}... можно строить только выше снеговой линии STR_ERROR_CAN_ONLY_BE_BUILT_BELOW_SNOW_LINE :{WHITE}... можно строить только ниже снеговой линии +STR_ERROR_PROSPECTING_WAS_UNLUCKY :{WHITE}Геологоразведка не принесла результатов; попробуйте снова. +STR_ERROR_NO_SUITABLE_PLACES_FOR_PROSPECTING :{WHITE}Нет подходящего места для геологоразведки. STR_ERROR_NO_SUITABLE_PLACES_FOR_INDUSTRIES :{WHITE}Нет подходящего места для {STRING.gen} STR_ERROR_NO_SUITABLE_PLACES_FOR_INDUSTRIES_EXPLANATION :{WHITE}Измените настройки создания карты для получения более подходящей карты diff --git a/src/lang/simplified_chinese.txt b/src/lang/simplified_chinese.txt index 9d3d994dcc..66711c125b 100644 --- a/src/lang/simplified_chinese.txt +++ b/src/lang/simplified_chinese.txt @@ -2807,7 +2807,7 @@ STR_LANDSCAPING_TOOLBAR :{WHITE}景观 STR_LANDSCAPING_TOOLTIP_LOWER_A_CORNER_OF_LAND :{BLACK}降低地块的一角 STR_LANDSCAPING_TOOLTIP_RAISE_A_CORNER_OF_LAND :{BLACK}升高地块的一角 STR_LANDSCAPING_LEVEL_LAND_TOOLTIP :{BLACK}拉平地面 -STR_LANDSCAPING_TOOLTIP_PURCHASE_LAND :{BLACK}购买土地以备将来使用,按住 Shift 键操作可以显示所需资金 +STR_LANDSCAPING_TOOLTIP_PURCHASE_LAND :{BLACK}购买土地以备将来使用。按 Ctrl 键可选择对角线区域。按 Shift 键可以预览所需资金。 # Object construction window STR_OBJECT_BUILD_CAPTION :{WHITE}物体选单 diff --git a/src/lang/spanish.txt b/src/lang/spanish.txt index ba27df85e0..d57af4dce6 100644 --- a/src/lang/spanish.txt +++ b/src/lang/spanish.txt @@ -2083,7 +2083,7 @@ STR_INTRO_CONFIG_SETTINGS_TREE :{BLACK}Configur STR_INTRO_NEWGRF_SETTINGS :{BLACK}Configuración NewGRF STR_INTRO_ONLINE_CONTENT :{BLACK}Contenido Online STR_INTRO_AI_SETTINGS :{BLACK}Configuración de IA -STR_INTRO_GAMESCRIPT_SETTINGS :{BLACK}Scripts de juego +STR_INTRO_GAMESCRIPT_SETTINGS :{BLACK}Scripts de Juego STR_INTRO_QUIT :{BLACK}Salir STR_INTRO_TOOLTIP_NEW_GAME :{BLACK}Comeenza una partida nueva. Ctrl+clic omite la configuración del escenario @@ -2866,6 +2866,8 @@ STR_FOUND_TOWN_RANDOM_TOWN_BUTTON :{BLACK}Municipi STR_FOUND_TOWN_RANDOM_TOWN_TOOLTIP :{BLACK}Funda un municipio en un lugar aleatorio STR_FOUND_TOWN_MANY_RANDOM_TOWNS :{BLACK}Varios municipios al azar STR_FOUND_TOWN_RANDOM_TOWNS_TOOLTIP :{BLACK}Cubre el mapa con municipios colocados al azar +STR_FOUND_TOWN_EXPAND_ALL_TOWNS :{BLACK}Expandir todos los municipios +STR_FOUND_TOWN_EXPAND_ALL_TOWNS_TOOLTIP :{BLACK}Expande levemente todos los municipios STR_FOUND_TOWN_NAME_TITLE :{YELLOW}Nombre del municipio: STR_FOUND_TOWN_NAME_EDITOR_TITLE :{BLACK}Introducir nombre de municipio @@ -3346,7 +3348,10 @@ STR_SPRITE_ALIGNER_SPRITE_TOOLTIP :{BLACK}Represen STR_SPRITE_ALIGNER_MOVE_TOOLTIP :{BLACK}Mover el sprite, cambiando los ajustes X e Y. Ctrl+clic mueve el sprite ocho unidades de una sola vez ###length 2 +STR_SPRITE_ALIGNER_CENTRE_OFFSET :{BLACK}Desviación (offset) centrada +STR_SPRITE_ALIGNER_CENTRE_SPRITE :{BLACK}Sprite centrado +STR_SPRITE_ALIGNER_CROSSHAIR :{BLACK}Punto de mira STR_SPRITE_ALIGNER_RESET_BUTTON :{BLACK}Reiniciar coordenadas relativas STR_SPRITE_ALIGNER_RESET_TOOLTIP :{BLACK}Reinicia las coordenadas relativas actuales @@ -4528,22 +4533,22 @@ STR_TIMETABLE_STARTING_DATE :{BLACK}Fecha de STR_TIMETABLE_STARTING_DATE_TOOLTIP :{BLACK}Selecciona la fecha de inicio del horario. Ctrl+click distribuye uniformemente todos los vehículos que compartan este horario a partir de la fecha proporcionada, basados en su orden relativo, siempre que el horario esté completamente rellenado STR_TIMETABLE_CHANGE_TIME :{BLACK}Modificar duración -STR_TIMETABLE_WAIT_TIME_TOOLTIP :{BLACK}Modifica la duración de la orden seleccionada +STR_TIMETABLE_WAIT_TIME_TOOLTIP :{BLACK}Modifica la duración de la orden seleccionada. Ctrl+clic establece la duración para todas las órdenes STR_TIMETABLE_CLEAR_TIME :{BLACK}Borrar duración -STR_TIMETABLE_CLEAR_TIME_TOOLTIP :{BLACK}Borra la duración de la orden resaltada +STR_TIMETABLE_CLEAR_TIME_TOOLTIP :{BLACK}Borra la duración de la orden resaltada.Ctrl+clic elimina la duración de todas las órdenes STR_TIMETABLE_CHANGE_SPEED :{BLACK}Modificar límite de velocidad -STR_TIMETABLE_CHANGE_SPEED_TOOLTIP :{BLACK}Cambia el límite de velocidad de la orden resaltada +STR_TIMETABLE_CHANGE_SPEED_TOOLTIP :{BLACK}Cambia el límite de velocidad de la orden resaltada. Ctrl+clic establece el límite para todas las órdenes STR_TIMETABLE_CLEAR_SPEED :{BLACK}Borrar límite de velocidad -STR_TIMETABLE_CLEAR_SPEED_TOOLTIP :{BLACK}Borra el límite de velocidad de la orden resaltada +STR_TIMETABLE_CLEAR_SPEED_TOOLTIP :{BLACK}Borra el límite de velocidad de la orden resaltada. Ctrl+clic elimina el límite de todas las órdenes STR_TIMETABLE_RESET_LATENESS :{BLACK}Reiniciar retraso STR_TIMETABLE_RESET_LATENESS_TOOLTIP :{BLACK}Establece en cero el retraso acumulado del vehículo para que sea puntual STR_TIMETABLE_AUTOFILL :{BLACK}Rellenar automáticamente -STR_TIMETABLE_AUTOFILL_TOOLTIP :{BLACK}Rellena el horario automáticamente con los valores del siguiente recorrido (Ctrl+clic para intentar mantener los tiempos de permanencia en estación) +STR_TIMETABLE_AUTOFILL_TOOLTIP :{BLACK}Rellena el horario automáticamente con los valores del siguiente recorrido. Ctrl+clic para intentar mantener los tiempos de permanencia en estación STR_TIMETABLE_EXPECTED :{BLACK}Previsto STR_TIMETABLE_SCHEDULED :{BLACK}Programado @@ -4579,7 +4584,7 @@ STR_AI_DEBUG_MATCH_CASE_TOOLTIP :{BLACK}Activa/d STR_AI_DEBUG_CONTINUE :{BLACK}Continuar STR_AI_DEBUG_CONTINUE_TOOLTIP :{BLACK}Quita la pausa y hace que la IA continúe STR_AI_DEBUG_SELECT_AI_TOOLTIP :{BLACK}Mostrar salida de depuración de esta IA -STR_AI_GAME_SCRIPT :{BLACK}Script de juego +STR_AI_GAME_SCRIPT :{BLACK}Script de Juego STR_AI_GAME_SCRIPT_TOOLTIP :{BLACK}Analizar el registro del script de juego STR_ERROR_AI_NO_AI_FOUND :No se encontró ninguna IA apropiada para cargar.{}Ésta es una IA por defecto que no realiza acción alguna.{}Puedes descargar nuevas IA mediante el sistema de 'Contenido Online' @@ -4799,6 +4804,7 @@ STR_ERROR_TOO_MANY_INDUSTRIES :{WHITE}... dema STR_ERROR_CAN_T_GENERATE_INDUSTRIES :{WHITE}No se pueden crear industrias... STR_ERROR_CAN_T_BUILD_HERE :{WHITE}No puede construirse {STRING} aquí... STR_ERROR_CAN_T_CONSTRUCT_THIS_INDUSTRY :{WHITE}No se puede construir este tipo de industria aquí... +STR_ERROR_CAN_T_PROSPECT_INDUSTRY :{WHITE}No se puede realizar prospección para la industria... STR_ERROR_INDUSTRY_TOO_CLOSE :{WHITE}... demasiado cerca de otra industria STR_ERROR_MUST_FOUND_TOWN_FIRST :{WHITE}... debe construirse un municipio primero STR_ERROR_ONLY_ONE_ALLOWED_PER_TOWN :{WHITE}... solo se permite uno por municipio @@ -4813,7 +4819,9 @@ STR_ERROR_FOREST_CAN_ONLY_BE_PLANTED :{WHITE}... solo STR_ERROR_CAN_ONLY_BE_BUILT_ABOVE_SNOW_LINE :{WHITE}... solo puede construirse por encima de la cota de nieve STR_ERROR_CAN_ONLY_BE_BUILT_BELOW_SNOW_LINE :{WHITE}... solo puede construirse por debajo de la cota de nieve -STR_ERROR_NO_SUITABLE_PLACES_FOR_INDUSTRIES :{WHITE}No había sitios apropiados disponibles para industrias '{STRING}' +STR_ERROR_PROSPECTING_WAS_UNLUCKY :{WHITE}La fundación ha fallado debido a una prospeccion desafortunada; intentar de nuevo +STR_ERROR_NO_SUITABLE_PLACES_FOR_PROSPECTING :{WHITE}No había lugares apropiados para realizar prospecciones para esta industria +STR_ERROR_NO_SUITABLE_PLACES_FOR_INDUSTRIES :{WHITE}No había lugares apropiados para industrias '{STRING}' STR_ERROR_NO_SUITABLE_PLACES_FOR_INDUSTRIES_EXPLANATION :{WHITE}Cambia los parámetros de generación del mapa para obtener un mapa mejor # Station construction related errors diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index 8e1106a46b..c74e95ec79 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -42,6 +42,7 @@ #include "../road_cmd.h" #include "../ai/ai.hpp" #include "../ai/ai_gui.hpp" +#include "../game/game.hpp" #include "../town.h" #include "../economy_base.h" #include "../animated_tile_func.h" @@ -317,7 +318,6 @@ static void InitializeWindowsAndCaches() CheckTrainsLengths(); ShowNewGRFError(); - ShowAIDebugWindowIfAIError(); /* Rebuild the smallmap list of owners. */ BuildOwnerLegend(); @@ -613,6 +613,22 @@ TileIndex GetOtherTunnelBridgeEndOld(TileIndex tile) } +/** + * Start the scripts. + */ +static void StartScripts() +{ + /* Start the GameScript. */ + Game::StartNew(); + + /* Start the AIs. */ + for (const Company *c : Company::Iterate()) { + if (Company::IsValidAiID(c->index)) AI::StartNew(c->index, false); + } + + ShowAIDebugWindowIfAIError(); +} + /** * Perform a (large) amount of savegame conversion *magic* in order to * load older savegames and to fill the caches for various purposes. @@ -966,13 +982,6 @@ bool AfterLoadGame() /* Update template vehicles */ AfterLoadTemplateVehicles(); - /* Make sure there is an AI attached to an AI company */ - { - for (const Company *c : Company::Iterate()) { - if (c->is_ai && c->ai_instance == nullptr) AI::StartNew(c->index); - } - } - /* make sure there is a town in the game */ if (_game_mode == GM_NORMAL && Town::GetNumItems() == 0) { SetSaveLoadError(STR_ERROR_NO_TOWN_IN_SCENARIO); @@ -4191,6 +4200,9 @@ bool AfterLoadGame() _game_load_tick_skip_counter = _tick_skip_counter; _game_load_time = time(nullptr); + /* Start the scripts. This MUST happen after everything else. */ + StartScripts(); + return true; } diff --git a/src/saveload/ai_sl.cpp b/src/saveload/ai_sl.cpp index b4839647d3..0b5b9f6e54 100644 --- a/src/saveload/ai_sl.cpp +++ b/src/saveload/ai_sl.cpp @@ -104,11 +104,8 @@ static void Load_AIPL() config->StringToSettings(_ai_saveload_settings); - /* Start the AI directly if it was active in the savegame */ - if (Company::IsValidAiID(index)) { - AI::StartNew(index, false); - AI::Load(index, _ai_saveload_version); - } + /* Load the AI saved data */ + if (Company::IsValidAiID(index)) config->SetToLoadData(AIInstance::Load(_ai_saveload_version)); } } diff --git a/src/saveload/game_sl.cpp b/src/saveload/game_sl.cpp index 13b6f3b02e..7da7da71ed 100644 --- a/src/saveload/game_sl.cpp +++ b/src/saveload/game_sl.cpp @@ -95,9 +95,8 @@ static void Load_GSDT() config->StringToSettings(_game_saveload_settings); - /* Start the GameScript directly if it was active in the savegame */ - Game::StartNew(); - Game::Load(_game_saveload_version); + /* Load the GameScript saved data */ + config->SetToLoadData(GameInstance::Load(_game_saveload_version)); if ((CompanyID)SlIterateArray() != (CompanyID)-1) SlErrorCorrupt("Too many GameScript configs"); } diff --git a/src/saveload/upstream/ai_sl.cpp b/src/saveload/upstream/ai_sl.cpp index c3ac9b70c5..f099cb0ca4 100644 --- a/src/saveload/upstream/ai_sl.cpp +++ b/src/saveload/upstream/ai_sl.cpp @@ -114,11 +114,8 @@ struct AIPLChunkHandler : ChunkHandler { config->StringToSettings(_ai_saveload_settings); - /* Start the AI directly if it was active in the savegame */ - if (Company::IsValidAiID(index)) { - AI::StartNew(index, false); - AI::Load(index, _ai_saveload_version); - } + /* Load the AI saved data */ + if (Company::IsValidAiID(index)) config->SetToLoadData(AIInstance::Load(_ai_saveload_version)); } } diff --git a/src/saveload/upstream/game_sl.cpp b/src/saveload/upstream/game_sl.cpp index 4843afc992..7dddbf2ba7 100644 --- a/src/saveload/upstream/game_sl.cpp +++ b/src/saveload/upstream/game_sl.cpp @@ -106,9 +106,8 @@ struct GSDTChunkHandler : ChunkHandler { config->StringToSettings(_game_saveload_settings); - /* Start the GameScript directly if it was active in the savegame */ - Game::StartNew(); - Game::Load(_game_saveload_version); + /* Load the GameScript saved data */ + config->SetToLoadData(GameInstance::Load(_game_saveload_version)); if (SlIterateArray() != -1) SlErrorCorrupt("Too many GameScript configs"); } diff --git a/src/script/script_config.cpp b/src/script/script_config.cpp index 340b3b3f13..07be966052 100644 --- a/src/script/script_config.cpp +++ b/src/script/script_config.cpp @@ -26,6 +26,7 @@ void ScriptConfig::Change(const char *name, int version, bool force_exact_match, if (this->config_list != nullptr) delete this->config_list; this->config_list = (info == nullptr) ? nullptr : new ScriptConfigItemList(); if (this->config_list != nullptr) this->PushExtraConfigList(); + this->to_load_data.reset(); this->ClearConfigList(); @@ -49,6 +50,7 @@ ScriptConfig::ScriptConfig(const ScriptConfig *config) this->version = config->version; this->config_list = nullptr; this->is_random = config->is_random; + this->to_load_data.reset(); for (const auto &item : config->settings) { this->settings[stredup(item.first)] = item.second; @@ -63,6 +65,7 @@ ScriptConfig::~ScriptConfig() free(this->name); this->ResetSettings(); if (this->config_list != nullptr) delete this->config_list; + this->to_load_data.reset(); } ScriptInfo *ScriptConfig::GetInfo() const @@ -238,3 +241,14 @@ const char *ScriptConfig::GetTextfile(TextfileType type, CompanyID slot) const return ::GetTextfile(type, (slot == OWNER_DEITY) ? GAME_DIR : AI_DIR, this->GetInfo()->GetMainScript()); } + +void ScriptConfig::SetToLoadData(ScriptInstance::ScriptData *data) +{ + this->to_load_data.reset(data); +} + +ScriptInstance::ScriptData *ScriptConfig::GetToLoadData() +{ + return this->to_load_data.get(); +} + diff --git a/src/script/script_config.hpp b/src/script/script_config.hpp index 13a136cbbf..f8b2a43dc9 100644 --- a/src/script/script_config.hpp +++ b/src/script/script_config.hpp @@ -16,6 +16,7 @@ #include "../core/string_compare_type.hpp" #include "../company_type.h" #include "../textfile_gui.h" +#include "script_instance.hpp" /** Bitmask of flags for Script settings. */ enum ScriptConfigFlags { @@ -63,7 +64,8 @@ public: version(-1), info(nullptr), config_list(nullptr), - is_random(false) + is_random(false), + to_load_data(nullptr) {} /** @@ -185,13 +187,17 @@ public: */ const char *GetTextfile(TextfileType type, CompanyID slot) const; + void SetToLoadData(ScriptInstance::ScriptData *data); + ScriptInstance::ScriptData *GetToLoadData(); + protected: - const char *name; ///< Name of the Script - int version; ///< Version of the Script - class ScriptInfo *info; ///< ScriptInfo object for related to this Script version - SettingValueList settings; ///< List with all setting=>value pairs that are configure for this Script - ScriptConfigItemList *config_list; ///< List with all settings defined by this Script - bool is_random; ///< True if the AI in this slot was randomly chosen. + const char *name; ///< Name of the Script + int version; ///< Version of the Script + class ScriptInfo *info; ///< ScriptInfo object for related to this Script version + SettingValueList settings; ///< List with all setting=>value pairs that are configure for this Script + ScriptConfigItemList *config_list; ///< List with all settings defined by this Script + bool is_random; ///< True if the AI in this slot was randomly chosen. + std::unique_ptr to_load_data; ///< Data to load after the Script start. /** * In case you have mandatory non-Script-definable config entries in your diff --git a/src/script/script_instance.cpp b/src/script/script_instance.cpp index ec3bc3ac39..4fd9c9668d 100644 --- a/src/script/script_instance.cpp +++ b/src/script/script_instance.cpp @@ -366,17 +366,6 @@ void *ScriptInstance::GetLogPointer() * - null: No data. */ -/** The type of the data that follows in the savegame. */ -enum SQSaveLoadType { - SQSL_INT = 0x00, ///< The following data is an integer. - SQSL_STRING = 0x01, ///< The following data is an string. - SQSL_ARRAY = 0x02, ///< The following data is an array. - SQSL_TABLE = 0x03, ///< The following data is an table. - SQSL_BOOL = 0x04, ///< The following data is a boolean. - SQSL_NULL = 0x05, ///< A null variable. - SQSL_ARRAY_TABLE_END = 0xFF, ///< Marks the end of an array or table, no data follows. -}; - static byte _script_sl_byte; ///< Used as source/target by the script saveload code to store/load a single byte. /** SaveLoad array that saves/loads exactly one byte. */ @@ -595,14 +584,14 @@ bool ScriptInstance::IsPaused() return this->is_paused; } -/* static */ bool ScriptInstance::LoadObjects(HSQUIRRELVM vm) +/* static */ bool ScriptInstance::LoadObjects(ScriptData *data) { SlObject(nullptr, _script_byte); switch (_script_sl_byte) { case SQSL_INT: { int64 value; SlArray(&value, 1, (IsSavegameVersionBefore(SLV_SCRIPT_INT64) && SlXvIsFeatureMissing(XSLFI_SCRIPT_INT64)) ? SLE_FILE_I32 | SLE_VAR_I64 : SLE_INT64); - if (vm != nullptr) sq_pushinteger(vm, (SQInteger)value); + if (data != nullptr) data->push_back((SQInteger)value); return true; } @@ -611,37 +600,79 @@ bool ScriptInstance::IsPaused() static char buf[std::numeric_limits::max()]; SlArray(buf, _script_sl_byte, SLE_CHAR); StrMakeValidInPlace(buf, buf + _script_sl_byte); - if (vm != nullptr) sq_pushstring(vm, buf, -1); + if (data != nullptr) data->push_back(std::string(buf)); + return true; + } + + case SQSL_ARRAY: + case SQSL_TABLE: { + if (data != nullptr) data->push_back((SQSaveLoadType)_script_sl_byte); + while (LoadObjects(data)); + return true; + } + + case SQSL_BOOL: { + SlObject(nullptr, _script_byte); + if (data != nullptr) data->push_back((SQBool)(_script_sl_byte != 0)); + return true; + } + + case SQSL_NULL: { + if (data != nullptr) data->push_back((SQSaveLoadType)_script_sl_byte); return true; } + case SQSL_ARRAY_TABLE_END: { + if (data != nullptr) data->push_back((SQSaveLoadType)_script_sl_byte); + return false; + } + + default: SlErrorCorrupt("Invalid script data type"); + } +} + +/* static */ bool ScriptInstance::LoadObjects(HSQUIRRELVM vm, ScriptData *data) +{ + ScriptDataVariant value = data->front(); + data->pop_front(); + + if (std::holds_alternative(value)) { + sq_pushinteger(vm, std::get(value)); + return true; + } + + if (std::holds_alternative(value)) { + sq_pushstring(vm, std::get(value).c_str(), -1); + return true; + } + + if (std::holds_alternative(value)) { + sq_pushbool(vm, std::get(value)); + return true; + } + + switch (std::get(value)) { case SQSL_ARRAY: { - if (vm != nullptr) sq_newarray(vm, 0); - while (LoadObjects(vm)) { - if (vm != nullptr) sq_arrayappend(vm, -2); + sq_newarray(vm, 0); + while (LoadObjects(vm, data)) { + sq_arrayappend(vm, -2); /* The value is popped from the stack by squirrel. */ } return true; } case SQSL_TABLE: { - if (vm != nullptr) sq_newtable(vm); - while (LoadObjects(vm)) { - LoadObjects(vm); - if (vm != nullptr) sq_rawset(vm, -3); + sq_newtable(vm); + while (LoadObjects(vm, data)) { + LoadObjects(vm, data); + sq_rawset(vm, -3); /* The key (-2) and value (-1) are popped from the stack by squirrel. */ } return true; } - case SQSL_BOOL: { - SlObject(nullptr, _script_byte); - if (vm != nullptr) sq_pushbool(vm, (SQBool)(_script_sl_byte != 0)); - return true; - } - case SQSL_NULL: { - if (vm != nullptr) sq_pushnull(vm); + sq_pushnull(vm); return true; } @@ -662,22 +693,35 @@ bool ScriptInstance::IsPaused() LoadObjects(nullptr); } -void ScriptInstance::Load(int version) +/* static */ ScriptInstance::ScriptData *ScriptInstance::Load(int version) { - ScriptObject::ActiveInstance active(this); - - if (this->engine == nullptr || version == -1) { + if (version == -1) { LoadEmpty(); - return; + return nullptr; } - HSQUIRRELVM vm = this->engine->GetVM(); SlObject(nullptr, _script_byte); /* Check if there was anything saved at all. */ - if (_script_sl_byte == 0) return; + if (_script_sl_byte == 0) return nullptr; + + ScriptData *data = new ScriptData(); + data->push_back((SQInteger)version); + LoadObjects(data); + return data; +} + +void ScriptInstance::LoadOnStack(ScriptData *data) +{ + ScriptObject::ActiveInstance active(this); + + if (data == nullptr) return; + + HSQUIRRELVM vm = this->engine->GetVM(); - sq_pushinteger(vm, version); - LoadObjects(vm); + ScriptDataVariant version = data->front(); + data->pop_front(); + sq_pushinteger(vm, std::get(version)); + LoadObjects(vm, data); this->is_save_data_on_stack = true; } diff --git a/src/script/script_instance.hpp b/src/script/script_instance.hpp index c43a9bd401..c29b8d5606 100644 --- a/src/script/script_instance.hpp +++ b/src/script/script_instance.hpp @@ -10,6 +10,8 @@ #ifndef SCRIPT_INSTANCE_HPP #define SCRIPT_INSTANCE_HPP +#include +#include #include #include "script_suspend.hpp" @@ -21,10 +23,25 @@ static const uint SQUIRREL_MAX_DEPTH = 25; ///< The maximum recursive depth for /** Runtime information about a script like a pointer to the squirrel vm and the current state. */ class ScriptInstance { +private: + /** The type of the data that follows in the savegame. */ + enum SQSaveLoadType { + SQSL_INT = 0x00, ///< The following data is an integer. + SQSL_STRING = 0x01, ///< The following data is an string. + SQSL_ARRAY = 0x02, ///< The following data is an array. + SQSL_TABLE = 0x03, ///< The following data is an table. + SQSL_BOOL = 0x04, ///< The following data is a boolean. + SQSL_NULL = 0x05, ///< A null variable. + SQSL_ARRAY_TABLE_END = 0xFF, ///< Marks the end of an array or table, no data follows. + }; + public: friend class ScriptObject; friend class ScriptController; + typedef std::variant ScriptDataVariant; + typedef std::list ScriptData; + /** * Create a new script. */ @@ -146,11 +163,18 @@ public: static void SaveEmpty(); /** - * Load data from a savegame and store it on the stack. + * Load data from a savegame. * @param version The version of the script when saving, or -1 if this was * not the original script saving the game. + * @return a pointer to loaded data. */ - void Load(int version); + static ScriptData *Load(int version); + + /** + * Store loaded data on the stack. + * @param data The loaded data to store on the stack. + */ + void LoadOnStack(ScriptData *data); /** * Load and discard data from a savegame. @@ -295,7 +319,9 @@ private: * Load all objects from a savegame. * @return True if the loading was successful. */ - static bool LoadObjects(HSQUIRRELVM vm); + static bool LoadObjects(ScriptData *data); + + static bool LoadObjects(HSQUIRRELVM vm, ScriptData *data); }; #endif /* SCRIPT_INSTANCE_HPP */ diff --git a/src/textfile_gui.cpp b/src/textfile_gui.cpp index 5d374edb74..e490491f50 100644 --- a/src/textfile_gui.cpp +++ b/src/textfile_gui.cpp @@ -167,9 +167,9 @@ void TextfileWindow::SetupScrollbars(bool force_reflow) int y_offset = (line.top - pos) * line_height; if (IsWidgetLowered(WID_TF_WRAPTEXT)) { - DrawStringMultiLine(0, fr.right, y_offset, fr.bottom, line.text, TC_WHITE, SA_TOP | SA_LEFT, false, FS_MONO); + DrawStringMultiLine(0, fr.right, y_offset, fr.bottom, line.text, TC_BLACK, SA_TOP | SA_LEFT, false, FS_MONO); } else { - DrawString(-this->hscroll->GetPosition(), fr.right, y_offset, line.text, TC_WHITE, SA_TOP | SA_LEFT, false, FS_MONO); + DrawString(-this->hscroll->GetPosition(), fr.right, y_offset, line.text, TC_BLACK, SA_TOP | SA_LEFT, false, FS_MONO); } }