From 0949eddd55259ec0695a18926c5bc56dcfd3f14d Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Fri, 22 Dec 2023 23:34:23 +0000 Subject: [PATCH 01/19] Change: Move colour selection dropdowns to bottom of window. This stops them looking similar to how filter controls are used elsewhere, and matches action dropdowns on other windows. --- src/company_gui.cpp | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/company_gui.cpp b/src/company_gui.cpp index 2d9753323e..b9723ad884 100644 --- a/src/company_gui.cpp +++ b/src/company_gui.cpp @@ -1092,7 +1092,7 @@ public: } }; -static const NWidgetPart _nested_select_company_livery_widgets [] = { +static const NWidgetPart _nested_select_company_livery_widgets[] = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), NWidget(WWT_CAPTION, COLOUR_GREY, WID_SCL_CAPTION), SetDataTip(STR_LIVERY_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), @@ -1110,17 +1110,14 @@ static const NWidgetPart _nested_select_company_livery_widgets [] = { NWidget(WWT_PANEL, COLOUR_GREY), SetMinimalSize(90, 22), SetFill(1, 1), EndContainer(), EndContainer(), NWidget(NWID_HORIZONTAL), - NWidget(WWT_PANEL, COLOUR_GREY, WID_SCL_SPACER_DROPDOWN), SetMinimalSize(150, 12), SetFill(1, 1), EndContainer(), - NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_SCL_PRI_COL_DROPDOWN), SetMinimalSize(125, 12), SetFill(0, 1), SetDataTip(STR_JUST_STRING, STR_LIVERY_PRIMARY_TOOLTIP), - NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_SCL_SEC_COL_DROPDOWN), SetMinimalSize(125, 12), SetFill(0, 1), - SetDataTip(STR_JUST_STRING, STR_LIVERY_SECONDARY_TOOLTIP), + NWidget(WWT_MATRIX, COLOUR_GREY, WID_SCL_MATRIX), SetMinimalSize(275, 0), SetResize(1, 0), SetFill(1, 1), SetMatrixDataTip(1, 0, STR_LIVERY_PANEL_TOOLTIP), SetScrollbar(WID_SCL_MATRIX_SCROLLBAR), + NWidget(NWID_VSCROLLBAR, COLOUR_GREY, WID_SCL_MATRIX_SCROLLBAR), EndContainer(), NWidget(NWID_HORIZONTAL), - NWidget(WWT_MATRIX, COLOUR_GREY, WID_SCL_MATRIX), SetMinimalSize(275, 0), SetResize(1, 0), SetFill(1, 1), SetMatrixDataTip(1, 0, STR_LIVERY_PANEL_TOOLTIP), SetScrollbar(WID_SCL_MATRIX_SCROLLBAR), - NWidget(NWID_VERTICAL), - NWidget(NWID_VSCROLLBAR, COLOUR_GREY, WID_SCL_MATRIX_SCROLLBAR), - NWidget(WWT_RESIZEBOX, COLOUR_GREY), - EndContainer(), + NWidget(WWT_PANEL, COLOUR_GREY, WID_SCL_SPACER_DROPDOWN), SetMinimalSize(150, 12), SetFill(1, 1), EndContainer(), + NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_SCL_PRI_COL_DROPDOWN), SetMinimalSize(125, 12), SetFill(0, 1), SetDataTip(STR_JUST_STRING, STR_LIVERY_PRIMARY_TOOLTIP), + NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_SCL_SEC_COL_DROPDOWN), SetMinimalSize(125, 12), SetFill(0, 1), SetDataTip(STR_JUST_STRING, STR_LIVERY_SECONDARY_TOOLTIP), + NWidget(WWT_RESIZEBOX, COLOUR_GREY), EndContainer(), }; From eda0dd24fec0747af7b8a85c8314abaf91d328f7 Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Fri, 22 Dec 2023 23:42:52 +0000 Subject: [PATCH 02/19] Change: Remove hardcoded minimum sizes and allow resize. This stops the window being needlessly large. --- src/company_gui.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/company_gui.cpp b/src/company_gui.cpp index b9723ad884..80da94c850 100644 --- a/src/company_gui.cpp +++ b/src/company_gui.cpp @@ -799,7 +799,7 @@ public: this->square = GetSpriteSize(SPR_SQUARE); this->line_height = std::max(this->square.height, (uint)GetCharacterHeight(FS_NORMAL)) + padding.height; - size->height = 11 * this->line_height; + size->height = 5 * this->line_height; resize->width = 1; resize->height = this->line_height; break; @@ -1107,16 +1107,16 @@ static const NWidgetPart _nested_select_company_livery_widgets[] = { NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_GROUPS_ROAD), SetMinimalSize(22, 22), SetFill(0, 1), SetDataTip(SPR_GROUP_LIVERY_ROADVEH, STR_LIVERY_ROAD_VEHICLE_TOOLTIP), NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_GROUPS_SHIP), SetMinimalSize(22, 22), SetFill(0, 1), SetDataTip(SPR_GROUP_LIVERY_SHIP, STR_LIVERY_SHIP_TOOLTIP), NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_GROUPS_AIRCRAFT), SetMinimalSize(22, 22), SetFill(0, 1), SetDataTip(SPR_GROUP_LIVERY_AIRCRAFT, STR_LIVERY_AIRCRAFT_TOOLTIP), - NWidget(WWT_PANEL, COLOUR_GREY), SetMinimalSize(90, 22), SetFill(1, 1), EndContainer(), + NWidget(WWT_PANEL, COLOUR_GREY), SetFill(1, 1), SetResize(1, 0), EndContainer(), EndContainer(), NWidget(NWID_HORIZONTAL), NWidget(WWT_MATRIX, COLOUR_GREY, WID_SCL_MATRIX), SetMinimalSize(275, 0), SetResize(1, 0), SetFill(1, 1), SetMatrixDataTip(1, 0, STR_LIVERY_PANEL_TOOLTIP), SetScrollbar(WID_SCL_MATRIX_SCROLLBAR), NWidget(NWID_VSCROLLBAR, COLOUR_GREY, WID_SCL_MATRIX_SCROLLBAR), EndContainer(), NWidget(NWID_HORIZONTAL), - NWidget(WWT_PANEL, COLOUR_GREY, WID_SCL_SPACER_DROPDOWN), SetMinimalSize(150, 12), SetFill(1, 1), EndContainer(), - NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_SCL_PRI_COL_DROPDOWN), SetMinimalSize(125, 12), SetFill(0, 1), SetDataTip(STR_JUST_STRING, STR_LIVERY_PRIMARY_TOOLTIP), - NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_SCL_SEC_COL_DROPDOWN), SetMinimalSize(125, 12), SetFill(0, 1), SetDataTip(STR_JUST_STRING, STR_LIVERY_SECONDARY_TOOLTIP), + NWidget(WWT_PANEL, COLOUR_GREY, WID_SCL_SPACER_DROPDOWN), SetFill(1, 1), SetResize(1, 0), EndContainer(), + NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_SCL_PRI_COL_DROPDOWN), SetFill(0, 1), SetDataTip(STR_JUST_STRING, STR_LIVERY_PRIMARY_TOOLTIP), + NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_SCL_SEC_COL_DROPDOWN), SetFill(0, 1), SetDataTip(STR_JUST_STRING, STR_LIVERY_SECONDARY_TOOLTIP), NWidget(WWT_RESIZEBOX, COLOUR_GREY), EndContainer(), }; From 513c7e7b53dbf7aa26c08916ff0df999fc58d289 Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Fri, 22 Dec 2023 23:57:46 +0000 Subject: [PATCH 03/19] Change: Add distinct tooltips for vehicle group colour schemes. --- src/company_gui.cpp | 8 ++++---- src/lang/english.txt | 4 ++++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/company_gui.cpp b/src/company_gui.cpp index 80da94c850..5ab64659e5 100644 --- a/src/company_gui.cpp +++ b/src/company_gui.cpp @@ -1103,10 +1103,10 @@ static const NWidgetPart _nested_select_company_livery_widgets[] = { NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_CLASS_ROAD), SetMinimalSize(22, 22), SetFill(0, 1), SetDataTip(SPR_IMG_TRUCKLIST, STR_LIVERY_ROAD_VEHICLE_TOOLTIP), NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_CLASS_SHIP), SetMinimalSize(22, 22), SetFill(0, 1), SetDataTip(SPR_IMG_SHIPLIST, STR_LIVERY_SHIP_TOOLTIP), NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_CLASS_AIRCRAFT), SetMinimalSize(22, 22), SetFill(0, 1), SetDataTip(SPR_IMG_AIRPLANESLIST, STR_LIVERY_AIRCRAFT_TOOLTIP), - NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_GROUPS_RAIL), SetMinimalSize(22, 22), SetFill(0, 1), SetDataTip(SPR_GROUP_LIVERY_TRAIN, STR_LIVERY_TRAIN_TOOLTIP), - NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_GROUPS_ROAD), SetMinimalSize(22, 22), SetFill(0, 1), SetDataTip(SPR_GROUP_LIVERY_ROADVEH, STR_LIVERY_ROAD_VEHICLE_TOOLTIP), - NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_GROUPS_SHIP), SetMinimalSize(22, 22), SetFill(0, 1), SetDataTip(SPR_GROUP_LIVERY_SHIP, STR_LIVERY_SHIP_TOOLTIP), - NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_GROUPS_AIRCRAFT), SetMinimalSize(22, 22), SetFill(0, 1), SetDataTip(SPR_GROUP_LIVERY_AIRCRAFT, STR_LIVERY_AIRCRAFT_TOOLTIP), + NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_GROUPS_RAIL), SetMinimalSize(22, 22), SetFill(0, 1), SetDataTip(SPR_GROUP_LIVERY_TRAIN, STR_LIVERY_TRAIN_GROUP_TOOLTIP), + NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_GROUPS_ROAD), SetMinimalSize(22, 22), SetFill(0, 1), SetDataTip(SPR_GROUP_LIVERY_ROADVEH, STR_LIVERY_ROAD_VEHICLE_GROUP_TOOLTIP), + NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_GROUPS_SHIP), SetMinimalSize(22, 22), SetFill(0, 1), SetDataTip(SPR_GROUP_LIVERY_SHIP, STR_LIVERY_SHIP_GROUP_TOOLTIP), + NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_GROUPS_AIRCRAFT), SetMinimalSize(22, 22), SetFill(0, 1), SetDataTip(SPR_GROUP_LIVERY_AIRCRAFT, STR_LIVERY_AIRCRAFT_GROUP_TOOLTIP), NWidget(WWT_PANEL, COLOUR_GREY), SetFill(1, 1), SetResize(1, 0), EndContainer(), EndContainer(), NWidget(NWID_HORIZONTAL), diff --git a/src/lang/english.txt b/src/lang/english.txt index 3aa24bce81..6904e795ac 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -2196,6 +2196,10 @@ STR_LIVERY_TRAIN_TOOLTIP :{BLACK}Show tra STR_LIVERY_ROAD_VEHICLE_TOOLTIP :{BLACK}Show road vehicle colour schemes STR_LIVERY_SHIP_TOOLTIP :{BLACK}Show ship colour schemes STR_LIVERY_AIRCRAFT_TOOLTIP :{BLACK}Show aircraft colour schemes +STR_LIVERY_TRAIN_GROUP_TOOLTIP :{BLACK}Show colours of train groups +STR_LIVERY_ROAD_VEHICLE_GROUP_TOOLTIP :{BLACK}Show colours of road vehicle groups +STR_LIVERY_SHIP_GROUP_TOOLTIP :{BLACK}Show colours of ship groups +STR_LIVERY_AIRCRAFT_GROUP_TOOLTIP :{BLACK}Show colours of aircraft groups STR_LIVERY_PRIMARY_TOOLTIP :{BLACK}Choose the primary colour for the selected scheme. Ctrl+Click will set this colour for every scheme STR_LIVERY_SECONDARY_TOOLTIP :{BLACK}Choose the secondary colour for the selected scheme. Ctrl+Click will set this colour for every scheme STR_LIVERY_PANEL_TOOLTIP :{BLACK}Select a colour scheme to change, or multiple schemes with Ctrl+Click. Click on the box to toggle use of the scheme From 3436b5f0903b7fb07f9a9074144fbec22d54de5f Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Fri, 22 Dec 2023 23:58:25 +0000 Subject: [PATCH 04/19] Change: Show a message in livery window if vehicle type has no groups. --- src/company_gui.cpp | 6 ++++++ src/lang/english.txt | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/src/company_gui.cpp b/src/company_gui.cpp index 5ab64659e5..0b55641d17 100644 --- a/src/company_gui.cpp +++ b/src/company_gui.cpp @@ -942,6 +942,12 @@ public: SetDParam(0, g->index); draw_livery(STR_GROUP_NAME, livery_set ? g->livery : c->livery[LS_DEFAULT], this->sel == g->index, livery_set, this->indents[i] * WidgetDimensions::scaled.hsep_indent); } + + if (this->vscroll->GetCount() == 0) { + const StringID empty_labels[] = { STR_LIVERY_TRAIN_GROUP_EMPTY, STR_LIVERY_ROAD_VEHICLE_GROUP_EMPTY, STR_LIVERY_SHIP_GROUP_EMPTY, STR_LIVERY_AIRCRAFT_GROUP_EMPTY }; + VehicleType vtype = (VehicleType)(this->livery_class - LC_GROUP_RAIL); + DrawString(ir.left, ir.right, y + text_offs, empty_labels[vtype], TC_BLACK); + } } } diff --git a/src/lang/english.txt b/src/lang/english.txt index 6904e795ac..95143d81bc 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -2203,6 +2203,10 @@ STR_LIVERY_AIRCRAFT_GROUP_TOOLTIP :{BLACK}Show col STR_LIVERY_PRIMARY_TOOLTIP :{BLACK}Choose the primary colour for the selected scheme. Ctrl+Click will set this colour for every scheme STR_LIVERY_SECONDARY_TOOLTIP :{BLACK}Choose the secondary colour for the selected scheme. Ctrl+Click will set this colour for every scheme STR_LIVERY_PANEL_TOOLTIP :{BLACK}Select a colour scheme to change, or multiple schemes with Ctrl+Click. Click on the box to toggle use of the scheme +STR_LIVERY_TRAIN_GROUP_EMPTY :No train groups are set up +STR_LIVERY_ROAD_VEHICLE_GROUP_EMPTY :No road vehicle groups are set up +STR_LIVERY_SHIP_GROUP_EMPTY :No ship groups are set up +STR_LIVERY_AIRCRAFT_GROUP_EMPTY :No aircraft groups are set up ###length 23 STR_LIVERY_DEFAULT :Standard Livery From c0cdf3460e4bb06662828a62a1ad3fa603103d27 Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Sat, 23 Dec 2023 00:02:10 +0000 Subject: [PATCH 05/19] Change: Rename Standard Livery to Default Livery. --- src/lang/english.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lang/english.txt b/src/lang/english.txt index 95143d81bc..05a5884905 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -2209,7 +2209,7 @@ STR_LIVERY_SHIP_GROUP_EMPTY :No ship groups STR_LIVERY_AIRCRAFT_GROUP_EMPTY :No aircraft groups are set up ###length 23 -STR_LIVERY_DEFAULT :Standard Livery +STR_LIVERY_DEFAULT :Default Livery STR_LIVERY_STEAM :Steam Engine STR_LIVERY_DIESEL :Diesel Engine STR_LIVERY_ELECTRIC :Electric Engine From af8b8c2cfc60ed26cc66987637b73277309b51f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Guilloux?= Date: Sun, 24 Dec 2023 01:08:18 +0100 Subject: [PATCH 06/19] Fix 4a2038e301: fully restore script break filter on reopen (#11622) --- src/script/script_gui.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/script/script_gui.cpp b/src/script/script_gui.cpp index 52f33023d4..28d9356cc3 100644 --- a/src/script/script_gui.cpp +++ b/src/script/script_gui.cpp @@ -800,8 +800,9 @@ struct ScriptDebugWindow : public Window { SetWidgetsDisabledState(!this->show_break_box, WID_SCRD_BREAK_STR_ON_OFF_BTN, WID_SCRD_BREAK_STR_EDIT_BOX, WID_SCRD_MATCH_CASE_BTN); this->hscroll->SetStepSize(10); // Speed up horizontal scrollbar - /* Restore the break string value from static variable */ + /* Restore the break string value from static variable, and enable the filter. */ this->break_editbox.text.Assign(this->filter.break_string); + this->break_string_filter.SetFilterTerm(this->filter.break_string); if (show_company == INVALID_COMPANY) { this->SelectValidDebugCompany(); From 4ecc107d30a6ddaa200c664e1bca75ba6ac99c61 Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Fri, 22 Dec 2023 16:01:32 +0000 Subject: [PATCH 07/19] Codechange: Perform simpler comparison first when checking for palette updates. This avoids unnecessarily comparing contents of an array. --- src/gfx.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/gfx.cpp b/src/gfx.cpp index 3896647611..461875df61 100644 --- a/src/gfx.cpp +++ b/src/gfx.cpp @@ -1368,12 +1368,10 @@ void DoPaletteAnimations() if (blitter != nullptr && blitter->UsePaletteAnimation() == Blitter::PALETTE_ANIMATION_NONE) { palette_animation_counter = old_tc; - } else { - if (memcmp(old_val, &_cur_palette.palette[PALETTE_ANIM_START], sizeof(old_val)) != 0 && _cur_palette.count_dirty == 0) { - /* Did we changed anything on the palette? Seems so. Mark it as dirty */ - _cur_palette.first_dirty = PALETTE_ANIM_START; - _cur_palette.count_dirty = PALETTE_ANIM_SIZE; - } + } else if (_cur_palette.count_dirty == 0 && memcmp(old_val, &_cur_palette.palette[PALETTE_ANIM_START], sizeof(old_val)) != 0) { + /* Did we changed anything on the palette? Seems so. Mark it as dirty */ + _cur_palette.first_dirty = PALETTE_ANIM_START; + _cur_palette.count_dirty = PALETTE_ANIM_SIZE; } } From daec0e2ca431f7a9f9331fea2941e637888c60c8 Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Fri, 22 Dec 2023 16:01:32 +0000 Subject: [PATCH 08/19] Codechange: Split palette handling to separate file. --- src/CMakeLists.txt | 2 + src/gfx.cpp | 169 -------------------------------- src/gfx_func.h | 58 ----------- src/gfxinit.cpp | 1 + src/palette.cpp | 190 ++++++++++++++++++++++++++++++++++++ src/palette_func.h | 79 +++++++++++++++ src/widgets/dropdown_type.h | 1 + src/widgets/slider.cpp | 1 + 8 files changed, 274 insertions(+), 227 deletions(-) create mode 100644 src/palette.cpp create mode 100644 src/palette_func.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index dfa123509b..dc1e696a53 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -325,6 +325,8 @@ add_files( order_gui.cpp order_type.h osk_gui.cpp + palette.cpp + palette_func.h pbs.cpp pbs.h progress.cpp diff --git a/src/gfx.cpp b/src/gfx.cpp index 461875df61..0d8321d9f0 100644 --- a/src/gfx.cpp +++ b/src/gfx.cpp @@ -20,12 +20,10 @@ #include "window_gui.h" #include "window_func.h" #include "newgrf_debug.h" -#include "thread.h" #include "core/backup_type.hpp" #include "core/container_func.hpp" #include "viewport_func.h" -#include "table/palettes.h" #include "table/string_colours.h" #include "table/sprites.h" #include "table/control_codes.h" @@ -50,13 +48,9 @@ GameMode _game_mode; SwitchMode _switch_mode; ///< The next mainloop command. std::chrono::steady_clock::time_point _switch_mode_time; ///< The time when the switch mode was requested. PauseMode _pause_mode; -Palette _cur_palette; static byte _stringwidth_table[FS_END][224]; ///< Cache containing width of often used characters. @see GetCharacterWidth() DrawPixelInfo *_cur_dpi; -byte _colour_gradient[COLOUR_END][8]; - -static std::recursive_mutex _palette_mutex; ///< To coordinate access to _cur_palette. static void GfxMainBlitterViewport(const Sprite *sprite, int x, int y, BlitterMode mode, const SubSprite *sub = nullptr, SpriteID sprite_id = SPR_CURSOR_MOUSE); static void GfxMainBlitter(const Sprite *sprite, int x, int y, BlitterMode mode, const SubSprite *sub = nullptr, SpriteID sprite_id = SPR_CURSOR_MOUSE, ZoomLevel zoom = ZOOM_LVL_NORMAL); @@ -1228,169 +1222,6 @@ static void GfxMainBlitter(const Sprite *sprite, int x, int y, BlitterMode mode, GfxBlitter<1, true>(sprite, x, y, mode, sub, sprite_id, zoom); } -void DoPaletteAnimations(); - -void GfxInitPalettes() -{ - std::lock_guard lock(_palette_mutex); - memcpy(&_cur_palette, &_palette, sizeof(_cur_palette)); - DoPaletteAnimations(); -} - -/** - * Copy the current palette if the palette was updated. - * Used by video-driver to get a current up-to-date version of the palette, - * to avoid two threads accessing the same piece of memory (with a good chance - * one is already updating the palette while the other is drawing based on it). - * @param local_palette The location to copy the palette to. - * @param force_copy Whether to ignore if there is an update for the palette. - * @return True iff a copy was done. - */ -bool CopyPalette(Palette &local_palette, bool force_copy) -{ - std::lock_guard lock(_palette_mutex); - - if (!force_copy && _cur_palette.count_dirty == 0) return false; - - local_palette = _cur_palette; - _cur_palette.count_dirty = 0; - - if (force_copy) { - local_palette.first_dirty = 0; - local_palette.count_dirty = 256; - } - - return true; -} - -#define EXTR(p, q) (((uint16_t)(palette_animation_counter * (p)) * (q)) >> 16) -#define EXTR2(p, q) (((uint16_t)(~palette_animation_counter * (p)) * (q)) >> 16) - -void DoPaletteAnimations() -{ - std::lock_guard lock(_palette_mutex); - - /* Animation counter for the palette animation. */ - static int palette_animation_counter = 0; - palette_animation_counter += 8; - - Blitter *blitter = BlitterFactory::GetCurrentBlitter(); - const Colour *s; - const ExtraPaletteValues *ev = &_extra_palette_values; - Colour old_val[PALETTE_ANIM_SIZE]; - const uint old_tc = palette_animation_counter; - uint j; - - if (blitter != nullptr && blitter->UsePaletteAnimation() == Blitter::PALETTE_ANIMATION_NONE) { - palette_animation_counter = 0; - } - - Colour *palette_pos = &_cur_palette.palette[PALETTE_ANIM_START]; // Points to where animations are taking place on the palette - /* Makes a copy of the current animation palette in old_val, - * so the work on the current palette could be compared, see if there has been any changes */ - memcpy(old_val, palette_pos, sizeof(old_val)); - - /* Fizzy Drink bubbles animation */ - s = ev->fizzy_drink; - j = EXTR2(512, EPV_CYCLES_FIZZY_DRINK); - for (uint i = 0; i != EPV_CYCLES_FIZZY_DRINK; i++) { - *palette_pos++ = s[j]; - j++; - if (j == EPV_CYCLES_FIZZY_DRINK) j = 0; - } - - /* Oil refinery fire animation */ - s = ev->oil_refinery; - j = EXTR2(512, EPV_CYCLES_OIL_REFINERY); - for (uint i = 0; i != EPV_CYCLES_OIL_REFINERY; i++) { - *palette_pos++ = s[j]; - j++; - if (j == EPV_CYCLES_OIL_REFINERY) j = 0; - } - - /* Radio tower blinking */ - { - byte i = (palette_animation_counter >> 1) & 0x7F; - byte v; - - if (i < 0x3f) { - v = 255; - } else if (i < 0x4A || i >= 0x75) { - v = 128; - } else { - v = 20; - } - palette_pos->r = v; - palette_pos->g = 0; - palette_pos->b = 0; - palette_pos++; - - i ^= 0x40; - if (i < 0x3f) { - v = 255; - } else if (i < 0x4A || i >= 0x75) { - v = 128; - } else { - v = 20; - } - palette_pos->r = v; - palette_pos->g = 0; - palette_pos->b = 0; - palette_pos++; - } - - /* Handle lighthouse and stadium animation */ - s = ev->lighthouse; - j = EXTR(256, EPV_CYCLES_LIGHTHOUSE); - for (uint i = 0; i != EPV_CYCLES_LIGHTHOUSE; i++) { - *palette_pos++ = s[j]; - j++; - if (j == EPV_CYCLES_LIGHTHOUSE) j = 0; - } - - /* Dark blue water */ - s = (_settings_game.game_creation.landscape == LT_TOYLAND) ? ev->dark_water_toyland : ev->dark_water; - j = EXTR(320, EPV_CYCLES_DARK_WATER); - for (uint i = 0; i != EPV_CYCLES_DARK_WATER; i++) { - *palette_pos++ = s[j]; - j++; - if (j == EPV_CYCLES_DARK_WATER) j = 0; - } - - /* Glittery water */ - s = (_settings_game.game_creation.landscape == LT_TOYLAND) ? ev->glitter_water_toyland : ev->glitter_water; - j = EXTR(128, EPV_CYCLES_GLITTER_WATER); - for (uint i = 0; i != EPV_CYCLES_GLITTER_WATER / 3; i++) { - *palette_pos++ = s[j]; - j += 3; - if (j >= EPV_CYCLES_GLITTER_WATER) j -= EPV_CYCLES_GLITTER_WATER; - } - - if (blitter != nullptr && blitter->UsePaletteAnimation() == Blitter::PALETTE_ANIMATION_NONE) { - palette_animation_counter = old_tc; - } else if (_cur_palette.count_dirty == 0 && memcmp(old_val, &_cur_palette.palette[PALETTE_ANIM_START], sizeof(old_val)) != 0) { - /* Did we changed anything on the palette? Seems so. Mark it as dirty */ - _cur_palette.first_dirty = PALETTE_ANIM_START; - _cur_palette.count_dirty = PALETTE_ANIM_SIZE; - } -} - -/** - * Determine a contrasty text colour for a coloured background. - * @param background Background colour. - * @param threshold Background colour brightness threshold below which the background is considered dark and TC_WHITE is returned, range: 0 - 255, default 128. - * @return TC_BLACK or TC_WHITE depending on what gives a better contrast. - */ -TextColour GetContrastColour(uint8_t background, uint8_t threshold) -{ - Colour c = _cur_palette.palette[background]; - /* Compute brightness according to http://www.w3.org/TR/AERT#color-contrast. - * The following formula computes 1000 * brightness^2, with brightness being in range 0 to 255. */ - uint sq1000_brightness = c.r * c.r * 299 + c.g * c.g * 587 + c.b * c.b * 114; - /* Compare with threshold brightness which defaults to 128 (50%) */ - return sq1000_brightness < ((uint) threshold) * ((uint) threshold) * 1000 ? TC_WHITE : TC_BLACK; -} - /** * Initialize _stringwidth_table cache * @param monospace Whether to load the monospace cache or the normal fonts. diff --git a/src/gfx_func.h b/src/gfx_func.h index 9210c4fedf..e12e8d4153 100644 --- a/src/gfx_func.h +++ b/src/gfx_func.h @@ -147,8 +147,6 @@ void DrawDirtyBlocks(); void AddDirtyBlock(int left, int top, int right, int bottom); void MarkWholeScreenDirty(); -bool CopyPalette(Palette &local_palette, bool force_copy = false); -void GfxInitPalettes(); void CheckBlitter(); bool FillDrawPixelInfo(DrawPixelInfo *n, int left, int top, int width, int height); @@ -191,60 +189,4 @@ int GetCharacterHeight(FontSize size); extern DrawPixelInfo *_cur_dpi; -/** - * Checks if a Colours value is valid. - * - * @param colours The value to check - * @return true if the given value is a valid Colours. - */ -static inline bool IsValidColours(Colours colours) -{ - return colours < COLOUR_END; -} - -TextColour GetContrastColour(uint8_t background, uint8_t threshold = 128); - -/** - * All 16 colour gradients - * 8 colours per gradient from darkest (0) to lightest (7) - */ -extern byte _colour_gradient[COLOUR_END][8]; - -/** - * Return the colour for a particular greyscale level. - * @param level Intensity, 0 = black, 15 = white - * @return colour - */ -#define GREY_SCALE(level) (level) - -static const uint8_t PC_BLACK = GREY_SCALE(1); ///< Black palette colour. -static const uint8_t PC_DARK_GREY = GREY_SCALE(6); ///< Dark grey palette colour. -static const uint8_t PC_GREY = GREY_SCALE(10); ///< Grey palette colour. -static const uint8_t PC_WHITE = GREY_SCALE(15); ///< White palette colour. - -static const uint8_t PC_VERY_DARK_RED = 0xB2; ///< Almost-black red palette colour. -static const uint8_t PC_DARK_RED = 0xB4; ///< Dark red palette colour. -static const uint8_t PC_RED = 0xB8; ///< Red palette colour. - -static const uint8_t PC_VERY_DARK_BROWN = 0x56; ///< Almost-black brown palette colour. - -static const uint8_t PC_ORANGE = 0xC2; ///< Orange palette colour. - -static const uint8_t PC_YELLOW = 0xBF; ///< Yellow palette colour. -static const uint8_t PC_LIGHT_YELLOW = 0x44; ///< Light yellow palette colour. -static const uint8_t PC_VERY_LIGHT_YELLOW = 0x45; ///< Almost-white yellow palette colour. - -static const uint8_t PC_GREEN = 0xD0; ///< Green palette colour. - -static const uint8_t PC_VERY_DARK_BLUE = 0x9A; ///< Almost-black blue palette colour. -static const uint8_t PC_DARK_BLUE = 0x9D; ///< Dark blue palette colour. -static const uint8_t PC_LIGHT_BLUE = 0x98; ///< Light blue palette colour. - -static const uint8_t PC_ROUGH_LAND = 0x52; ///< Dark green palette colour for rough land. -static const uint8_t PC_GRASS_LAND = 0x54; ///< Dark green palette colour for grass land. -static const uint8_t PC_BARE_LAND = 0x37; ///< Brown palette colour for bare land. -static const uint8_t PC_RAINFOREST = 0x5C; ///< Pale green palette colour for rainforest. -static const uint8_t PC_FIELDS = 0x25; ///< Light brown palette colour for fields. -static const uint8_t PC_TREES = 0x57; ///< Green palette colour for trees. -static const uint8_t PC_WATER = 0xC9; ///< Dark blue palette colour for water. #endif /* GFX_FUNC_H */ diff --git a/src/gfxinit.cpp b/src/gfxinit.cpp index 943c5bb102..785dbde159 100644 --- a/src/gfxinit.cpp +++ b/src/gfxinit.cpp @@ -17,6 +17,7 @@ #include "blitter/factory.hpp" #include "video/video_driver.hpp" #include "window_func.h" +#include "palette_func.h" /* The type of set we're replacing */ #define SET_TYPE "graphics" diff --git a/src/palette.cpp b/src/palette.cpp new file mode 100644 index 0000000000..e8e5d3f870 --- /dev/null +++ b/src/palette.cpp @@ -0,0 +1,190 @@ +/* + * This file is part of OpenTTD. + * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. + * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . + */ + +/** @file palette.cpp Handling of palettes. */ + +#include "stdafx.h" +#include "blitter/base.hpp" +#include "blitter/factory.hpp" +#include "gfx_type.h" +#include "landscape_type.h" +#include "palette_func.h" +#include "settings_type.h" +#include "thread.h" + +#include "table/palettes.h" + +#include "safeguards.h" + +Palette _cur_palette; + +byte _colour_gradient[COLOUR_END][8]; + +static std::recursive_mutex _palette_mutex; ///< To coordinate access to _cur_palette. + +void DoPaletteAnimations(); + +void GfxInitPalettes() +{ + std::lock_guard lock(_palette_mutex); + memcpy(&_cur_palette, &_palette, sizeof(_cur_palette)); + DoPaletteAnimations(); +} + +/** + * Copy the current palette if the palette was updated. + * Used by video-driver to get a current up-to-date version of the palette, + * to avoid two threads accessing the same piece of memory (with a good chance + * one is already updating the palette while the other is drawing based on it). + * @param local_palette The location to copy the palette to. + * @param force_copy Whether to ignore if there is an update for the palette. + * @return True iff a copy was done. + */ +bool CopyPalette(Palette &local_palette, bool force_copy) +{ + std::lock_guard lock(_palette_mutex); + + if (!force_copy && _cur_palette.count_dirty == 0) return false; + + local_palette = _cur_palette; + _cur_palette.count_dirty = 0; + + if (force_copy) { + local_palette.first_dirty = 0; + local_palette.count_dirty = 256; + } + + return true; +} + +#define EXTR(p, q) (((uint16_t)(palette_animation_counter * (p)) * (q)) >> 16) +#define EXTR2(p, q) (((uint16_t)(~palette_animation_counter * (p)) * (q)) >> 16) + +void DoPaletteAnimations() +{ + std::lock_guard lock(_palette_mutex); + + /* Animation counter for the palette animation. */ + static int palette_animation_counter = 0; + palette_animation_counter += 8; + + Blitter *blitter = BlitterFactory::GetCurrentBlitter(); + const Colour *s; + const ExtraPaletteValues *ev = &_extra_palette_values; + Colour old_val[PALETTE_ANIM_SIZE]; + const uint old_tc = palette_animation_counter; + uint j; + + if (blitter != nullptr && blitter->UsePaletteAnimation() == Blitter::PALETTE_ANIMATION_NONE) { + palette_animation_counter = 0; + } + + Colour *palette_pos = &_cur_palette.palette[PALETTE_ANIM_START]; // Points to where animations are taking place on the palette + /* Makes a copy of the current animation palette in old_val, + * so the work on the current palette could be compared, see if there has been any changes */ + memcpy(old_val, palette_pos, sizeof(old_val)); + + /* Fizzy Drink bubbles animation */ + s = ev->fizzy_drink; + j = EXTR2(512, EPV_CYCLES_FIZZY_DRINK); + for (uint i = 0; i != EPV_CYCLES_FIZZY_DRINK; i++) { + *palette_pos++ = s[j]; + j++; + if (j == EPV_CYCLES_FIZZY_DRINK) j = 0; + } + + /* Oil refinery fire animation */ + s = ev->oil_refinery; + j = EXTR2(512, EPV_CYCLES_OIL_REFINERY); + for (uint i = 0; i != EPV_CYCLES_OIL_REFINERY; i++) { + *palette_pos++ = s[j]; + j++; + if (j == EPV_CYCLES_OIL_REFINERY) j = 0; + } + + /* Radio tower blinking */ + { + byte i = (palette_animation_counter >> 1) & 0x7F; + byte v; + + if (i < 0x3f) { + v = 255; + } else if (i < 0x4A || i >= 0x75) { + v = 128; + } else { + v = 20; + } + palette_pos->r = v; + palette_pos->g = 0; + palette_pos->b = 0; + palette_pos++; + + i ^= 0x40; + if (i < 0x3f) { + v = 255; + } else if (i < 0x4A || i >= 0x75) { + v = 128; + } else { + v = 20; + } + palette_pos->r = v; + palette_pos->g = 0; + palette_pos->b = 0; + palette_pos++; + } + + /* Handle lighthouse and stadium animation */ + s = ev->lighthouse; + j = EXTR(256, EPV_CYCLES_LIGHTHOUSE); + for (uint i = 0; i != EPV_CYCLES_LIGHTHOUSE; i++) { + *palette_pos++ = s[j]; + j++; + if (j == EPV_CYCLES_LIGHTHOUSE) j = 0; + } + + /* Dark blue water */ + s = (_settings_game.game_creation.landscape == LT_TOYLAND) ? ev->dark_water_toyland : ev->dark_water; + j = EXTR(320, EPV_CYCLES_DARK_WATER); + for (uint i = 0; i != EPV_CYCLES_DARK_WATER; i++) { + *palette_pos++ = s[j]; + j++; + if (j == EPV_CYCLES_DARK_WATER) j = 0; + } + + /* Glittery water */ + s = (_settings_game.game_creation.landscape == LT_TOYLAND) ? ev->glitter_water_toyland : ev->glitter_water; + j = EXTR(128, EPV_CYCLES_GLITTER_WATER); + for (uint i = 0; i != EPV_CYCLES_GLITTER_WATER / 3; i++) { + *palette_pos++ = s[j]; + j += 3; + if (j >= EPV_CYCLES_GLITTER_WATER) j -= EPV_CYCLES_GLITTER_WATER; + } + + if (blitter != nullptr && blitter->UsePaletteAnimation() == Blitter::PALETTE_ANIMATION_NONE) { + palette_animation_counter = old_tc; + } else if (_cur_palette.count_dirty == 0 && memcmp(old_val, &_cur_palette.palette[PALETTE_ANIM_START], sizeof(old_val)) != 0) { + /* Did we changed anything on the palette? Seems so. Mark it as dirty */ + _cur_palette.first_dirty = PALETTE_ANIM_START; + _cur_palette.count_dirty = PALETTE_ANIM_SIZE; + } +} + +/** + * Determine a contrasty text colour for a coloured background. + * @param background Background colour. + * @param threshold Background colour brightness threshold below which the background is considered dark and TC_WHITE is returned, range: 0 - 255, default 128. + * @return TC_BLACK or TC_WHITE depending on what gives a better contrast. + */ +TextColour GetContrastColour(uint8_t background, uint8_t threshold) +{ + Colour c = _cur_palette.palette[background]; + /* Compute brightness according to http://www.w3.org/TR/AERT#color-contrast. + * The following formula computes 1000 * brightness^2, with brightness being in range 0 to 255. */ + uint sq1000_brightness = c.r * c.r * 299 + c.g * c.g * 587 + c.b * c.b * 114; + /* Compare with threshold brightness which defaults to 128 (50%) */ + return sq1000_brightness < ((uint) threshold) * ((uint) threshold) * 1000 ? TC_WHITE : TC_BLACK; +} diff --git a/src/palette_func.h b/src/palette_func.h new file mode 100644 index 0000000000..5b317781ab --- /dev/null +++ b/src/palette_func.h @@ -0,0 +1,79 @@ +/* + * This file is part of OpenTTD. + * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. + * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . + */ + +/** @file palette_func.h Functions related to palettes. */ + +#ifndef PALETTE_FUNC_H +#define PALETTE_FUNC_H + +#include "gfx_type.h" +#include "strings_type.h" +#include "string_type.h" + +extern Palette _cur_palette; ///< Current palette + +bool CopyPalette(Palette &local_palette, bool force_copy = false); +void GfxInitPalettes(); + +/** + * Checks if a Colours value is valid. + * + * @param colours The value to check + * @return true if the given value is a valid Colours. + */ +static inline bool IsValidColours(Colours colours) +{ + return colours < COLOUR_END; +} + +TextColour GetContrastColour(uint8_t background, uint8_t threshold = 128); + +/** + * All 16 colour gradients + * 8 colours per gradient from darkest (0) to lightest (7) + */ +extern byte _colour_gradient[COLOUR_END][8]; + +/** + * Return the colour for a particular greyscale level. + * @param level Intensity, 0 = black, 15 = white + * @return colour + */ +#define GREY_SCALE(level) (level) + +static const uint8_t PC_BLACK = GREY_SCALE(1); ///< Black palette colour. +static const uint8_t PC_DARK_GREY = GREY_SCALE(6); ///< Dark grey palette colour. +static const uint8_t PC_GREY = GREY_SCALE(10); ///< Grey palette colour. +static const uint8_t PC_WHITE = GREY_SCALE(15); ///< White palette colour. + +static const uint8_t PC_VERY_DARK_RED = 0xB2; ///< Almost-black red palette colour. +static const uint8_t PC_DARK_RED = 0xB4; ///< Dark red palette colour. +static const uint8_t PC_RED = 0xB8; ///< Red palette colour. + +static const uint8_t PC_VERY_DARK_BROWN = 0x56; ///< Almost-black brown palette colour. + +static const uint8_t PC_ORANGE = 0xC2; ///< Orange palette colour. + +static const uint8_t PC_YELLOW = 0xBF; ///< Yellow palette colour. +static const uint8_t PC_LIGHT_YELLOW = 0x44; ///< Light yellow palette colour. +static const uint8_t PC_VERY_LIGHT_YELLOW = 0x45; ///< Almost-white yellow palette colour. + +static const uint8_t PC_GREEN = 0xD0; ///< Green palette colour. + +static const uint8_t PC_VERY_DARK_BLUE = 0x9A; ///< Almost-black blue palette colour. +static const uint8_t PC_DARK_BLUE = 0x9D; ///< Dark blue palette colour. +static const uint8_t PC_LIGHT_BLUE = 0x98; ///< Light blue palette colour. + +static const uint8_t PC_ROUGH_LAND = 0x52; ///< Dark green palette colour for rough land. +static const uint8_t PC_GRASS_LAND = 0x54; ///< Dark green palette colour for grass land. +static const uint8_t PC_BARE_LAND = 0x37; ///< Brown palette colour for bare land. +static const uint8_t PC_RAINFOREST = 0x5C; ///< Pale green palette colour for rainforest. +static const uint8_t PC_FIELDS = 0x25; ///< Light brown palette colour for fields. +static const uint8_t PC_TREES = 0x57; ///< Green palette colour for trees. +static const uint8_t PC_WATER = 0xC9; ///< Dark blue palette colour for water. + +#endif /* PALETTE_FUNC_H */ diff --git a/src/widgets/dropdown_type.h b/src/widgets/dropdown_type.h index 6a60179aac..8ca6472c2d 100644 --- a/src/widgets/dropdown_type.h +++ b/src/widgets/dropdown_type.h @@ -13,6 +13,7 @@ #include "../window_type.h" #include "../gfx_func.h" #include "../gfx_type.h" +#include "../palette_func.h" #include "../string_func.h" #include "../strings_func.h" #include "../table/strings.h" diff --git a/src/widgets/slider.cpp b/src/widgets/slider.cpp index 29fc1138aa..43ddbb335a 100644 --- a/src/widgets/slider.cpp +++ b/src/widgets/slider.cpp @@ -8,6 +8,7 @@ /** @file slider.cpp Implementation of the horizontal slider widget. */ #include "../stdafx.h" +#include "../palette_func.h" #include "../window_gui.h" #include "../window_func.h" #include "../strings_func.h" From 0bc22dd310c2bf5380f64095b087a2a446be1a41 Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Fri, 22 Dec 2023 16:01:32 +0000 Subject: [PATCH 09/19] Add: 32bpp-to-8bpp palette index lookup. Lookups are calculated on demand and caches in a 256KB in-memory table. --- src/palette.cpp | 107 +++++++++++++++++++++++++++++++++++++++++++++ src/palette_func.h | 7 +++ 2 files changed, 114 insertions(+) diff --git a/src/palette.cpp b/src/palette.cpp index e8e5d3f870..c2311ed08a 100644 --- a/src/palette.cpp +++ b/src/palette.cpp @@ -10,6 +10,7 @@ #include "stdafx.h" #include "blitter/base.hpp" #include "blitter/factory.hpp" +#include "fileio_func.h" #include "gfx_type.h" #include "landscape_type.h" #include "palette_func.h" @@ -26,6 +27,112 @@ byte _colour_gradient[COLOUR_END][8]; static std::recursive_mutex _palette_mutex; ///< To coordinate access to _cur_palette. +/** + * PALETTE_BITS reduces the bits-per-channel of 32bpp graphics data to allow faster palette lookups from + * a smaller lookup table. + * + * 6 bpc is chosen as this results in a palette lookup table of 256KiB with adequate fidelty. + * In constract, a 5 bpc lookup table would be 32KiB, and 7 bpc would be 2MiB. + * + * Values in the table are filled as they are first encountered -- larger lookup table means more colour + * distance calculations, and is therefore slower. + */ +const uint PALETTE_BITS = 6; +const uint PALETTE_SHIFT = 8 - PALETTE_BITS; +const uint PALETTE_BITS_MASK = ((1U << PALETTE_BITS) - 1) << PALETTE_SHIFT; +const uint PALETTE_BITS_OR = (1U << (PALETTE_SHIFT - 1)); + +/* Palette and reshade lookup table. */ +using PaletteLookup = std::array; +static PaletteLookup _palette_lookup{}; + +/** + * Reduce bits per channel to PALETTE_BITS, and place value in the middle of the reduced range. + * This is to counteract the information lost between bright and dark pixels, e.g if PALETTE_BITS was 2: + * 0 - 63 -> 32 + * 64 - 127 -> 96 + * 128 - 191 -> 160 + * 192 - 255 -> 224 + * @param c 8 bit colour component. + * @returns Colour component reduced to PALETTE_BITS. + */ +inline uint CrunchColour(uint c) +{ + return (c & PALETTE_BITS_MASK) | PALETTE_BITS_OR; +} + +/** + * Calculate distance between two colours. + * @param col1 First colour. + * @param r2 Red component of second colour. + * @param g2 Green component of second colour. + * @param b2 Blue component of second colour. + * @returns Euclidean distance between first and second colour. + */ +static uint CalculateColourDistance(const Colour &col1, int r2, int g2, int b2) +{ + /* Euclidean colour distance for sRGB based on https://en.wikipedia.org/wiki/Color_difference#sRGB */ + int r = (int)col1.r - (int)r2; + int g = (int)col1.g - (int)g2; + int b = (int)col1.b - (int)b2; + + int avgr = (col1.r + r2) / 2; + return ((2 + (avgr / 256.0)) * r * r) + (4 * g * g) + ((2 + ((255 - avgr) / 256.0)) * b * b); +} + +/* Palette indexes for conversion. See docs/palettes/palette_key.png */ +const uint8_t PALETTE_INDEX_CC_START = 198; ///< Palette index of start of company colour remap area. +const uint8_t PALETTE_INDEX_CC_END = PALETTE_INDEX_CC_START + 8; ///< Palette index of end of company colour remap area. +const uint8_t PALETTE_INDEX_START = 1; ///< Palette index of start of defined palette. +const uint8_t PALETTE_INDEX_END = 215; ///< Palette index of end of defined palette. + +/** + * Find nearest colour palette index for a 32bpp pixel. + * @param r Red component. + * @param g Green component. + * @param b Blue component. + * @returns palette index of nearest colour. + */ +static uint8_t FindNearestColourIndex(uint8_t r, uint8_t g, uint8_t b) +{ + r = CrunchColour(r); + g = CrunchColour(g); + b = CrunchColour(b); + + uint best_index = 0; + uint best_distance = UINT32_MAX; + + for (uint i = PALETTE_INDEX_START; i < PALETTE_INDEX_CC_START; i++) { + if (uint distance = CalculateColourDistance(_palette.palette[i], r, g, b); distance < best_distance) { + best_index = i; + best_distance = distance; + } + } + /* There's a hole in the palette reserved for company colour remaps. */ + for (uint i = PALETTE_INDEX_CC_END; i < PALETTE_INDEX_END; i++) { + if (uint distance = CalculateColourDistance(_palette.palette[i], r, g, b); distance < best_distance) { + best_index = i; + best_distance = distance; + } + } + return best_index; +} + +/** + * Get nearest colour palette index from an RGB colour. + * A search is performed if this colour is not already in the lookup table. + * @param r Red component. + * @param g Green component. + * @param b Blue component. + * @returns nearest colour palette index. + */ +uint8_t GetNearestColourIndex(uint8_t r, uint8_t g, uint8_t b) +{ + uint32_t key = (r >> PALETTE_SHIFT) | (g >> PALETTE_SHIFT) << PALETTE_BITS | (b >> PALETTE_SHIFT) << (PALETTE_BITS * 2); + if (_palette_lookup[key] == 0) _palette_lookup[key] = FindNearestColourIndex(r, g, b); + return _palette_lookup[key]; +} + void DoPaletteAnimations(); void GfxInitPalettes() diff --git a/src/palette_func.h b/src/palette_func.h index 5b317781ab..c0920faceb 100644 --- a/src/palette_func.h +++ b/src/palette_func.h @@ -19,6 +19,13 @@ extern Palette _cur_palette; ///< Current palette bool CopyPalette(Palette &local_palette, bool force_copy = false); void GfxInitPalettes(); +uint8_t GetNearestColourIndex(uint8_t r, uint8_t g, uint8_t b); + +static inline uint8_t GetNearestColourIndex(const Colour colour) +{ + return GetNearestColourIndex(colour.r, colour.g, colour.b); +} + /** * Checks if a Colours value is valid. * From 9ce1626bb48b58f40c12ea8ed9af715d3206b876 Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Fri, 22 Dec 2023 16:01:33 +0000 Subject: [PATCH 10/19] Change: Support custom transparency remaps with 32bpp blitters. This closes a 15 year old TODO... --- src/blitter/32bpp_anim.cpp | 24 ++++++++++++++++++++---- src/blitter/32bpp_anim_sse4.cpp | 19 ++++++++++++++++++- src/blitter/32bpp_optimized.cpp | 21 +++++++++++++++++---- src/blitter/32bpp_simple.cpp | 16 +++++++++++----- src/blitter/32bpp_sse_func.hpp | 13 +++++++++++++ src/blitter/40bpp_anim.cpp | 28 ++++++++++++++++++++++++---- src/blitter/8bpp_optimized.cpp | 3 ++- src/blitter/8bpp_simple.cpp | 1 + src/blitter/base.hpp | 3 ++- src/gfx.cpp | 10 ++++++---- 10 files changed, 114 insertions(+), 24 deletions(-) diff --git a/src/blitter/32bpp_anim.cpp b/src/blitter/32bpp_anim.cpp index 19c48deae8..9ca6229eb5 100644 --- a/src/blitter/32bpp_anim.cpp +++ b/src/blitter/32bpp_anim.cpp @@ -9,6 +9,7 @@ #include "../stdafx.h" #include "../video/video_driver.hpp" +#include "../palette_func.h" #include "32bpp_anim.hpp" #include "common.hpp" @@ -190,10 +191,6 @@ inline void Blitter_32bppAnim::Draw(const Blitter::BlitterParams *bp, ZoomLevel break; case BM_TRANSPARENT: - /* TODO -- We make an assumption here that the remap in fact is transparency, not some colour. - * This is never a problem with the code we produce, but newgrfs can make it fail... or at least: - * we produce a result the newgrf maker didn't expect ;) */ - /* Make the current colour a bit more black, so it looks like this image is transparent */ src_n += n; if (src_px->a == 255) { @@ -215,6 +212,24 @@ inline void Blitter_32bppAnim::Draw(const Blitter::BlitterParams *bp, ZoomLevel } break; + case BM_TRANSPARENT_REMAP: + /* Apply custom transparency remap. */ + src_n += n; + if (src_px->a != 0) { + src_px += n; + do { + *dst = this->LookupColourInPalette(bp->remap[GetNearestColourIndex(*dst)]); + *anim = 0; + anim++; + dst++; + } while (--n != 0); + } else { + dst += n; + anim += n; + src_px += n; + } + break; + default: if (src_px->a == 255) { do { @@ -264,6 +279,7 @@ void Blitter_32bppAnim::Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomL case BM_NORMAL: Draw (bp, zoom); return; case BM_COLOUR_REMAP: Draw(bp, zoom); return; case BM_TRANSPARENT: Draw (bp, zoom); return; + case BM_TRANSPARENT_REMAP: Draw(bp, zoom); return; case BM_CRASH_REMAP: Draw (bp, zoom); return; case BM_BLACK_REMAP: Draw (bp, zoom); return; } diff --git a/src/blitter/32bpp_anim_sse4.cpp b/src/blitter/32bpp_anim_sse4.cpp index 6c60a5fb4e..c80505ee0d 100644 --- a/src/blitter/32bpp_anim_sse4.cpp +++ b/src/blitter/32bpp_anim_sse4.cpp @@ -7,6 +7,7 @@ /** @file 32bpp_anim_sse4.cpp Implementation of the SSE4 32 bpp blitter with animation support. */ +#include "palette_func.h" #ifdef WITH_SSE #include "../stdafx.h" @@ -317,6 +318,21 @@ bmcr_alpha_blend_single: } break; + case BM_TRANSPARENT_REMAP: + /* Apply custom transparency remap. */ + for (uint x = (uint) bp->width; x > 0; x--) { + if (src->a != 0) { + *dst = this->LookupColourInPalette(bp->remap[GetNearestColourIndex(*dst)]); + *anim = 0; + } + src_mv++; + dst++; + src++; + anim++; + } + break; + + case BM_CRASH_REMAP: for (uint x = (uint) bp->width; x > 0; x--) { if (src_mv->m == 0) { @@ -351,7 +367,7 @@ bmcr_alpha_blend_single: } next_line: - if (mode != BM_TRANSPARENT) src_mv_line += si->sprite_width; + if (mode != BM_TRANSPARENT && mode != BM_TRANSPARENT_REMAP) src_mv_line += si->sprite_width; src_rgba_line = (const Colour*) ((const byte*) src_rgba_line + si->sprite_line_size); dst_line += bp->pitch; anim_line += this->anim_buf_pitch; @@ -414,6 +430,7 @@ bm_normal: } break; case BM_TRANSPARENT: Draw(bp, zoom); return; + case BM_TRANSPARENT_REMAP: Draw(bp, zoom); return; case BM_CRASH_REMAP: Draw(bp, zoom); return; case BM_BLACK_REMAP: Draw(bp, zoom); return; } diff --git a/src/blitter/32bpp_optimized.cpp b/src/blitter/32bpp_optimized.cpp index 5492178b51..9a28ad7d50 100644 --- a/src/blitter/32bpp_optimized.cpp +++ b/src/blitter/32bpp_optimized.cpp @@ -10,6 +10,7 @@ #include "../stdafx.h" #include "../zoom_func.h" #include "../settings_type.h" +#include "../palette_func.h" #include "32bpp_optimized.hpp" #include "../safeguards.h" @@ -185,10 +186,6 @@ inline void Blitter_32bppOptimized::Draw(const Blitter::BlitterParams *bp, ZoomL break; case BM_TRANSPARENT: - /* TODO -- We make an assumption here that the remap in fact is transparency, not some colour. - * This is never a problem with the code we produce, but newgrfs can make it fail... or at least: - * we produce a result the newgrf maker didn't expect ;) */ - /* Make the current colour a bit more black, so it looks like this image is transparent */ src_n += n; if (src_px->a == 255) { @@ -206,6 +203,21 @@ inline void Blitter_32bppOptimized::Draw(const Blitter::BlitterParams *bp, ZoomL } break; + case BM_TRANSPARENT_REMAP: + /* Apply custom transparency remap. */ + src_n += n; + if (src_px->a != 0) { + src_px += n; + do { + *dst = this->LookupColourInPalette(bp->remap[GetNearestColourIndex(*dst)]); + dst++; + } while (--n != 0); + } else { + dst += n; + src_px += n; + } + break; + default: if (src_px->a == 255) { /* faster than memcpy(), n is usually low */ @@ -252,6 +264,7 @@ void Blitter_32bppOptimized::Draw(Blitter::BlitterParams *bp, BlitterMode mode, case BM_NORMAL: Draw(bp, zoom); return; case BM_COLOUR_REMAP: Draw(bp, zoom); return; case BM_TRANSPARENT: Draw(bp, zoom); return; + case BM_TRANSPARENT_REMAP: Draw(bp, zoom); return; case BM_CRASH_REMAP: Draw(bp, zoom); return; case BM_BLACK_REMAP: Draw(bp, zoom); return; } diff --git a/src/blitter/32bpp_simple.cpp b/src/blitter/32bpp_simple.cpp index 30aff86b76..00c0497109 100644 --- a/src/blitter/32bpp_simple.cpp +++ b/src/blitter/32bpp_simple.cpp @@ -9,6 +9,7 @@ #include "../stdafx.h" #include "../zoom_func.h" +#include "../palette_func.h" #include "32bpp_simple.hpp" #include "../table/sprites.h" @@ -63,12 +64,17 @@ void Blitter_32bppSimple::Draw(Blitter::BlitterParams *bp, BlitterMode mode, Zoo break; case BM_TRANSPARENT: - /* TODO -- We make an assumption here that the remap in fact is transparency, not some colour. - * This is never a problem with the code we produce, but newgrfs can make it fail... or at least: - * we produce a result the newgrf maker didn't expect ;) */ - /* Make the current colour a bit more black, so it looks like this image is transparent */ - if (src->a != 0) *dst = MakeTransparent(*dst, 192); + if (src->a != 0) { + *dst = MakeTransparent(*dst, 192); + } + break; + + case BM_TRANSPARENT_REMAP: + /* Apply custom transparency remap. */ + if (src->a != 0) { + *dst = this->LookupColourInPalette(bp->remap[GetNearestColourIndex(*dst)]); + } break; default: diff --git a/src/blitter/32bpp_sse_func.hpp b/src/blitter/32bpp_sse_func.hpp index 6215e093b6..4ed788f3de 100644 --- a/src/blitter/32bpp_sse_func.hpp +++ b/src/blitter/32bpp_sse_func.hpp @@ -392,6 +392,18 @@ bmcr_alpha_blend_single: } break; + case BM_TRANSPARENT_REMAP: + /* Apply custom transparency remap. */ + for (uint x = (uint) bp->width; x > 0; x--) { + if (src->a != 0) { + *dst = this->LookupColourInPalette(bp->remap[GetNearestColourIndex(*dst)]); + } + src_mv++; + dst++; + src++; + } + break; + case BM_CRASH_REMAP: for (uint x = (uint) bp->width; x > 0; x--) { if (src_mv->m == 0) { @@ -471,6 +483,7 @@ bm_normal: Draw(bp, zoom); return; } case BM_TRANSPARENT: Draw(bp, zoom); return; + case BM_TRANSPARENT_REMAP: Draw(bp, zoom); return; case BM_CRASH_REMAP: Draw(bp, zoom); return; case BM_BLACK_REMAP: Draw(bp, zoom); return; } diff --git a/src/blitter/40bpp_anim.cpp b/src/blitter/40bpp_anim.cpp index 0b6d7410c2..e1ee0a0fec 100644 --- a/src/blitter/40bpp_anim.cpp +++ b/src/blitter/40bpp_anim.cpp @@ -11,6 +11,7 @@ #include "../zoom_func.h" #include "../settings_type.h" #include "../video/video_driver.hpp" +#include "../palette_func.h" #include "40bpp_anim.hpp" #include "common.hpp" @@ -234,10 +235,6 @@ inline void Blitter_40bppAnim::Draw(const Blitter::BlitterParams *bp, ZoomLevel break; case BM_TRANSPARENT: - /* TODO -- We make an assumption here that the remap in fact is transparency, not some colour. - * This is never a problem with the code we produce, but newgrfs can make it fail... or at least: - * we produce a result the newgrf maker didn't expect ;) */ - /* Make the current colour a bit more black, so it looks like this image is transparent */ src_n += n; if (src_px->a == 255) { @@ -263,6 +260,28 @@ inline void Blitter_40bppAnim::Draw(const Blitter::BlitterParams *bp, ZoomLevel } break; + case BM_TRANSPARENT_REMAP: + /* Apply custom transparency remap. */ + src_n += n; + if (src_px->a != 0) { + src_px += n; + do { + if (*anim != 0) { + *anim = bp->remap[*anim]; + } else { + *dst = this->LookupColourInPalette(bp->remap[GetNearestColourIndex(*dst)]); + *anim = 0; + } + anim++; + dst++; + } while (--n != 0); + } else { + dst += n; + anim += n; + src_px += n; + } + break; + default: if (src_px->a == 255) { do { @@ -323,6 +342,7 @@ void Blitter_40bppAnim::Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomL case BM_NORMAL: Draw (bp, zoom); return; case BM_COLOUR_REMAP: Draw(bp, zoom); return; case BM_TRANSPARENT: Draw (bp, zoom); return; + case BM_TRANSPARENT_REMAP: Draw(bp, zoom); return; case BM_CRASH_REMAP: Draw (bp, zoom); return; case BM_BLACK_REMAP: Draw (bp, zoom); return; } diff --git a/src/blitter/8bpp_optimized.cpp b/src/blitter/8bpp_optimized.cpp index e86a2a2ff8..3758e3a80a 100644 --- a/src/blitter/8bpp_optimized.cpp +++ b/src/blitter/8bpp_optimized.cpp @@ -100,7 +100,8 @@ void Blitter_8bppOptimized::Draw(Blitter::BlitterParams *bp, BlitterMode mode, Z dst += pixels; break; - case BM_TRANSPARENT: { + case BM_TRANSPARENT: + case BM_TRANSPARENT_REMAP: { const uint8_t *remap = bp->remap; src += pixels; do { diff --git a/src/blitter/8bpp_simple.cpp b/src/blitter/8bpp_simple.cpp index be86ddcbe4..a80ceba115 100644 --- a/src/blitter/8bpp_simple.cpp +++ b/src/blitter/8bpp_simple.cpp @@ -42,6 +42,7 @@ void Blitter_8bppSimple::Draw(Blitter::BlitterParams *bp, BlitterMode mode, Zoom break; case BM_TRANSPARENT: + case BM_TRANSPARENT_REMAP: if (*src != 0) colour = bp->remap[*dst]; break; diff --git a/src/blitter/base.hpp b/src/blitter/base.hpp index e55f9294e4..26ed39eb6d 100644 --- a/src/blitter/base.hpp +++ b/src/blitter/base.hpp @@ -17,7 +17,8 @@ enum BlitterMode { BM_NORMAL, ///< Perform the simple blitting. BM_COLOUR_REMAP, ///< Perform a colour remapping. - BM_TRANSPARENT, ///< Perform transparency colour remapping. + BM_TRANSPARENT, ///< Perform transparency darkening remapping. + BM_TRANSPARENT_REMAP, ///< Perform transparency colour remapping. BM_CRASH_REMAP, ///< Perform a crash remapping. BM_BLACK_REMAP, ///< Perform remapping to a completely blackened sprite }; diff --git a/src/gfx.cpp b/src/gfx.cpp index 0d8321d9f0..6912e4abf5 100644 --- a/src/gfx.cpp +++ b/src/gfx.cpp @@ -978,8 +978,9 @@ void DrawSpriteViewport(SpriteID img, PaletteID pal, int x, int y, const SubSpri { SpriteID real_sprite = GB(img, 0, SPRITE_WIDTH); if (HasBit(img, PALETTE_MODIFIER_TRANSPARENT)) { - _colour_remap_ptr = GetNonSprite(GB(pal, 0, PALETTE_WIDTH), SpriteType::Recolour) + 1; - GfxMainBlitterViewport(GetSprite(real_sprite, SpriteType::Normal), x, y, BM_TRANSPARENT, sub, real_sprite); + pal = GB(pal, 0, PALETTE_WIDTH); + _colour_remap_ptr = GetNonSprite(pal, SpriteType::Recolour) + 1; + GfxMainBlitterViewport(GetSprite(real_sprite, SpriteType::Normal), x, y, pal == PALETTE_TO_TRANSPARENT ? BM_TRANSPARENT : BM_TRANSPARENT_REMAP, sub, real_sprite); } else if (pal != PAL_NONE) { if (HasBit(pal, PALETTE_TEXT_RECOLOUR)) { SetColourRemap((TextColour)GB(pal, 0, PALETTE_WIDTH)); @@ -1005,8 +1006,9 @@ void DrawSprite(SpriteID img, PaletteID pal, int x, int y, const SubSprite *sub, { SpriteID real_sprite = GB(img, 0, SPRITE_WIDTH); if (HasBit(img, PALETTE_MODIFIER_TRANSPARENT)) { - _colour_remap_ptr = GetNonSprite(GB(pal, 0, PALETTE_WIDTH), SpriteType::Recolour) + 1; - GfxMainBlitter(GetSprite(real_sprite, SpriteType::Normal), x, y, BM_TRANSPARENT, sub, real_sprite, zoom); + pal = GB(pal, 0, PALETTE_WIDTH); + _colour_remap_ptr = GetNonSprite(pal, SpriteType::Recolour) + 1; + GfxMainBlitter(GetSprite(real_sprite, SpriteType::Normal), x, y, pal == PALETTE_TO_TRANSPARENT ? BM_TRANSPARENT : BM_TRANSPARENT_REMAP, sub, real_sprite, zoom); } else if (pal != PAL_NONE) { if (HasBit(pal, PALETTE_TEXT_RECOLOUR)) { SetColourRemap((TextColour)GB(pal, 0, PALETTE_WIDTH)); From 6c5a4aa2cbaaae6a71ae8a03be44e954bd0b3f4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Guilloux?= Date: Mon, 25 Dec 2023 18:42:13 +0100 Subject: [PATCH 11/19] Fix 2d3af14: Don't draw script log over panel borders (#11621) --- src/script/script_gui.cpp | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/script/script_gui.cpp b/src/script/script_gui.cpp index 28d9356cc3..1450de8d7a 100644 --- a/src/script/script_gui.cpp +++ b/src/script/script_gui.cpp @@ -899,8 +899,19 @@ struct ScriptDebugWindow : public Window { ScriptLogTypes::LogData &log = this->GetLogData(); if (log.empty()) return; - Rect br = r.Shrink(WidgetDimensions::scaled.bevel); - Rect tr = r.Shrink(WidgetDimensions::scaled.framerect); + Rect fr = r.Shrink(WidgetDimensions::scaled.framerect); + + /* Setup a clipping rectangle... */ + DrawPixelInfo tmp_dpi; + if (!FillDrawPixelInfo(&tmp_dpi, fr)) return; + /* ...but keep coordinates relative to the window. */ + tmp_dpi.left += fr.left; + tmp_dpi.top += fr.top; + + AutoRestoreBackup dpi_backup(_cur_dpi, &tmp_dpi); + + fr.left -= this->hscroll->GetPosition(); + for (int i = this->vscroll->GetPosition(); this->vscroll->IsVisible(i) && (size_t)i < log.size(); i++) { const ScriptLogTypes::LogLine &line = log[i]; @@ -916,12 +927,13 @@ struct ScriptDebugWindow : public Window { /* Check if the current line should be highlighted */ if (i == this->highlight_row) { - GfxFillRect(br.left, tr.top, br.right, tr.top + this->resize.step_height - 1, PC_BLACK); + fr.bottom = fr.top + this->resize.step_height - 1; + GfxFillRect(fr, PC_BLACK); if (colour == TC_BLACK) colour = TC_WHITE; // Make black text readable by inverting it to white. } - DrawString(-this->hscroll->GetPosition(), tr.right, tr.top, line.text, colour, SA_LEFT | SA_FORCE); - tr.top += this->resize.step_height; + DrawString(fr, line.text, colour, SA_LEFT | SA_FORCE); + fr.top += this->resize.step_height; } } From 947e77267a4a3d7d55e601b3c71b088c51e34ebe Mon Sep 17 00:00:00 2001 From: SamuXarick <43006711+SamuXarick@users.noreply.github.com> Date: Mon, 25 Dec 2023 17:42:29 +0000 Subject: [PATCH 12/19] Doc 0ca4b4e: Script debug window numbers are now ascending (#11623) --- src/window_type.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/window_type.h b/src/window_type.h index 96a591c30e..e546c405ad 100644 --- a/src/window_type.h +++ b/src/window_type.h @@ -657,7 +657,7 @@ enum WindowClass { /** * Script debug window; %Window numbers: - * - 0 = #ScriptDebugWidgets + * - Ascending value = #ScriptDebugWidgets */ WC_SCRIPT_DEBUG, From fdf6cbf848d6c4a1a7c21f9d281e3ef64538b1ee Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Mon, 25 Dec 2023 20:08:13 +0000 Subject: [PATCH 13/19] Change: Scale sprites to requested highest resolution level. (#11600) Sprites from graphics sets which only provide high resolution sprites are now scaled up from scaled down versions. --- src/spritecache.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/spritecache.cpp b/src/spritecache.cpp index 5857146348..af40f171f4 100644 --- a/src/spritecache.cpp +++ b/src/spritecache.cpp @@ -397,6 +397,12 @@ static bool ResizeSprites(SpriteLoader::SpriteCollection &sprite, uint8_t sprite if (!HasBit(sprite_avail, zoom)) ResizeSpriteOut(sprite, zoom); } + /* Upscale to desired sprite_min_zoom if provided sprite only had zoomed in versions. */ + if (first_avail < _settings_client.gui.sprite_zoom_min) { + if (_settings_client.gui.sprite_zoom_min >= ZOOM_LVL_OUT_4X) ResizeSpriteIn(sprite, ZOOM_LVL_OUT_4X, ZOOM_LVL_OUT_2X); + if (_settings_client.gui.sprite_zoom_min >= ZOOM_LVL_OUT_2X) ResizeSpriteIn(sprite, ZOOM_LVL_OUT_2X, ZOOM_LVL_NORMAL); + } + return true; } From a2a7ecf88eb74c89f905f3035a1a6ae59f718ed8 Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Mon, 25 Dec 2023 20:59:37 +0000 Subject: [PATCH 14/19] Fix 9ce1626b: Some blitters have `bp->remap` aliased to `remap` for performance. (#11626) While this probably doesn't make a huge difference for the custom transparent remap code path, the alias is there so use it. --- src/blitter/32bpp_anim.cpp | 2 +- src/blitter/32bpp_anim_sse4.cpp | 2 +- src/blitter/32bpp_optimized.cpp | 2 +- src/blitter/32bpp_sse_func.hpp | 2 +- src/blitter/40bpp_anim.cpp | 4 ++-- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/blitter/32bpp_anim.cpp b/src/blitter/32bpp_anim.cpp index 9ca6229eb5..0c2612fcde 100644 --- a/src/blitter/32bpp_anim.cpp +++ b/src/blitter/32bpp_anim.cpp @@ -218,7 +218,7 @@ inline void Blitter_32bppAnim::Draw(const Blitter::BlitterParams *bp, ZoomLevel if (src_px->a != 0) { src_px += n; do { - *dst = this->LookupColourInPalette(bp->remap[GetNearestColourIndex(*dst)]); + *dst = this->LookupColourInPalette(remap[GetNearestColourIndex(*dst)]); *anim = 0; anim++; dst++; diff --git a/src/blitter/32bpp_anim_sse4.cpp b/src/blitter/32bpp_anim_sse4.cpp index c80505ee0d..b01420ef6d 100644 --- a/src/blitter/32bpp_anim_sse4.cpp +++ b/src/blitter/32bpp_anim_sse4.cpp @@ -322,7 +322,7 @@ bmcr_alpha_blend_single: /* Apply custom transparency remap. */ for (uint x = (uint) bp->width; x > 0; x--) { if (src->a != 0) { - *dst = this->LookupColourInPalette(bp->remap[GetNearestColourIndex(*dst)]); + *dst = this->LookupColourInPalette(remap[GetNearestColourIndex(*dst)]); *anim = 0; } src_mv++; diff --git a/src/blitter/32bpp_optimized.cpp b/src/blitter/32bpp_optimized.cpp index 9a28ad7d50..15b607a9a7 100644 --- a/src/blitter/32bpp_optimized.cpp +++ b/src/blitter/32bpp_optimized.cpp @@ -209,7 +209,7 @@ inline void Blitter_32bppOptimized::Draw(const Blitter::BlitterParams *bp, ZoomL if (src_px->a != 0) { src_px += n; do { - *dst = this->LookupColourInPalette(bp->remap[GetNearestColourIndex(*dst)]); + *dst = this->LookupColourInPalette(remap[GetNearestColourIndex(*dst)]); dst++; } while (--n != 0); } else { diff --git a/src/blitter/32bpp_sse_func.hpp b/src/blitter/32bpp_sse_func.hpp index 4ed788f3de..62cb705fef 100644 --- a/src/blitter/32bpp_sse_func.hpp +++ b/src/blitter/32bpp_sse_func.hpp @@ -396,7 +396,7 @@ bmcr_alpha_blend_single: /* Apply custom transparency remap. */ for (uint x = (uint) bp->width; x > 0; x--) { if (src->a != 0) { - *dst = this->LookupColourInPalette(bp->remap[GetNearestColourIndex(*dst)]); + *dst = this->LookupColourInPalette(remap[GetNearestColourIndex(*dst)]); } src_mv++; dst++; diff --git a/src/blitter/40bpp_anim.cpp b/src/blitter/40bpp_anim.cpp index e1ee0a0fec..e65a1d7151 100644 --- a/src/blitter/40bpp_anim.cpp +++ b/src/blitter/40bpp_anim.cpp @@ -267,9 +267,9 @@ inline void Blitter_40bppAnim::Draw(const Blitter::BlitterParams *bp, ZoomLevel src_px += n; do { if (*anim != 0) { - *anim = bp->remap[*anim]; + *anim = remap[*anim]; } else { - *dst = this->LookupColourInPalette(bp->remap[GetNearestColourIndex(*dst)]); + *dst = this->LookupColourInPalette(remap[GetNearestColourIndex(*dst)]); *anim = 0; } anim++; From 2072e532f7a664ca53abd84d409fadf5ea96c6f3 Mon Sep 17 00:00:00 2001 From: Rubidium Date: Tue, 26 Dec 2023 00:24:59 +0100 Subject: [PATCH 15/19] Codechange: replace NULL with nullptr --- src/network/core/http_winhttp.cpp | 2 +- src/network/core/os_abstraction.cpp | 4 ++-- src/video/cocoa/cocoa_v.mm | 2 +- src/video/cocoa/cocoa_wnd.mm | 14 +++++++------- src/video/win32_v.cpp | 10 +++++----- 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/network/core/http_winhttp.cpp b/src/network/core/http_winhttp.cpp index c37711119a..df57fc138a 100644 --- a/src/network/core/http_winhttp.cpp +++ b/src/network/core/http_winhttp.cpp @@ -67,7 +67,7 @@ static std::string GetLastErrorAsString() DWORD error_code = GetLastError(); if (FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_IGNORE_INSERTS, GetModuleHandleA("winhttp.dll"), error_code, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buffer, sizeof(buffer), NULL) == 0) { + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buffer, sizeof(buffer), nullptr) == 0) { return fmt::format("unknown error {}", error_code); } diff --git a/src/network/core/os_abstraction.cpp b/src/network/core/os_abstraction.cpp index 8da0a3f3d0..792ee8b2f4 100644 --- a/src/network/core/os_abstraction.cpp +++ b/src/network/core/os_abstraction.cpp @@ -81,8 +81,8 @@ const std::string &NetworkError::AsString() const if (this->message.empty()) { #if defined(_WIN32) char buffer[512]; - if (FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, this->error, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buffer, sizeof(buffer), NULL) == 0) { + if (FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, this->error, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buffer, sizeof(buffer), nullptr) == 0) { this->message.assign(fmt::format("Unknown error {}", this->error)); } else { this->message.assign(buffer); diff --git a/src/video/cocoa/cocoa_v.mm b/src/video/cocoa/cocoa_v.mm index 2a9ae02424..0be6745b0c 100644 --- a/src/video/cocoa/cocoa_v.mm +++ b/src/video/cocoa/cocoa_v.mm @@ -664,7 +664,7 @@ void VideoDriver_CocoaQuartz::AllocateBackingStore(bool) kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host ); - assert(this->cgcontext != NULL); + assert(this->cgcontext != nullptr); CGContextSetShouldAntialias(this->cgcontext, FALSE); CGContextSetAllowsAntialiasing(this->cgcontext, FALSE); CGContextSetInterpolationQuality(this->cgcontext, kCGInterpolationNone); diff --git a/src/video/cocoa/cocoa_wnd.mm b/src/video/cocoa/cocoa_wnd.mm index 52823a7a6c..f6957ff6ef 100644 --- a/src/video/cocoa/cocoa_wnd.mm +++ b/src/video/cocoa/cocoa_wnd.mm @@ -929,16 +929,16 @@ void CocoaDialog(const char *title, const char *message, const char *buttonLabel NSString *s = [ aString isKindOfClass:[ NSAttributedString class ] ] ? [ aString string ] : (NSString *)aString; - const char *insert_point = NULL; - const char *replace_range = NULL; + const char *insert_point = nullptr; + const char *replace_range = nullptr; if (replacementRange.location != NSNotFound) { /* Calculate the part to be replaced. */ insert_point = Utf8AdvanceByUtf16Units(_focused_window->GetFocusedTextbuf()->GetText(), replacementRange.location); replace_range = Utf8AdvanceByUtf16Units(insert_point, replacementRange.length); } - HandleTextInput(NULL, true); - HandleTextInput([ s UTF8String ], false, NULL, insert_point, replace_range); + HandleTextInput(nullptr, true); + HandleTextInput([ s UTF8String ], false, nullptr, insert_point, replace_range); } /** Insert the given text at the caret. */ @@ -955,9 +955,9 @@ void CocoaDialog(const char *title, const char *message, const char *buttonLabel NSString *s = [ aString isKindOfClass:[ NSAttributedString class ] ] ? [ aString string ] : (NSString *)aString; const char *utf8 = [ s UTF8String ]; - if (utf8 != NULL) { - const char *insert_point = NULL; - const char *replace_range = NULL; + if (utf8 != nullptr) { + const char *insert_point = nullptr; + const char *replace_range = nullptr; if (replacementRange.location != NSNotFound) { /* Calculate the part to be replaced. */ NSRange marked = [ self markedRange ]; diff --git a/src/video/win32_v.cpp b/src/video/win32_v.cpp index cf7a909451..833f4bf72d 100644 --- a/src/video/win32_v.cpp +++ b/src/video/win32_v.cpp @@ -275,7 +275,7 @@ static bool DrawIMECompositionString() static void SetCompositionPos(HWND hwnd) { HIMC hIMC = ImmGetContext(hwnd); - if (hIMC != NULL) { + if (hIMC != nullptr) { COMPOSITIONFORM cf; cf.dwStyle = CFS_POINT; @@ -297,7 +297,7 @@ static void SetCompositionPos(HWND hwnd) static void SetCandidatePos(HWND hwnd) { HIMC hIMC = ImmGetContext(hwnd); - if (hIMC != NULL) { + if (hIMC != nullptr) { CANDIDATEFORM cf; cf.dwIndex = 0; cf.dwStyle = CFS_EXCLUDE; @@ -332,7 +332,7 @@ static LRESULT HandleIMEComposition(HWND hwnd, WPARAM wParam, LPARAM lParam) { HIMC hIMC = ImmGetContext(hwnd); - if (hIMC != NULL) { + if (hIMC != nullptr) { if (lParam & GCS_RESULTSTR) { /* Read result string from the IME. */ LONG len = ImmGetCompositionString(hIMC, GCS_RESULTSTR, nullptr, 0); // Length is always in bytes, even in UNICODE build. @@ -391,7 +391,7 @@ static LRESULT HandleIMEComposition(HWND hwnd, WPARAM wParam, LPARAM lParam) static void CancelIMEComposition(HWND hwnd) { HIMC hIMC = ImmGetContext(hwnd); - if (hIMC != NULL) ImmNotifyIME(hIMC, NI_COMPOSITIONSTR, CPS_CANCEL, 0); + if (hIMC != nullptr) ImmNotifyIME(hIMC, NI_COMPOSITIONSTR, CPS_CANCEL, 0); ImmReleaseContext(hwnd, hIMC); /* Clear any marked string from the current edit box. */ HandleTextInput(nullptr, true); @@ -688,7 +688,7 @@ LRESULT CALLBACK WndProcGdi(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) /* Resize the window to match the new DPI setting. */ RECT *prcNewWindow = (RECT *)lParam; SetWindowPos(hwnd, - NULL, + nullptr, prcNewWindow->left, prcNewWindow->top, prcNewWindow->right - prcNewWindow->left, From e0c670cbe8c229f35e206737bf93cce0ce40db06 Mon Sep 17 00:00:00 2001 From: Rubidium Date: Tue, 26 Dec 2023 00:31:57 +0100 Subject: [PATCH 16/19] Codechange: replace NULL with nullptr --- src/3rdparty/squirrel/sqstdlib/sqstdmath.cpp | 2 +- src/3rdparty/squirrel/sqstdlib/sqstdrex.cpp | 52 +++++++++---------- .../squirrel/sqstdlib/sqstdstring.cpp | 6 +-- src/3rdparty/squirrel/squirrel/sqbaselib.cpp | 22 ++++---- src/3rdparty/squirrel/squirrel/sqobject.h | 4 +- src/3rdparty/squirrel/squirrel/sqstate.cpp | 2 +- src/3rdparty/squirrel/squirrel/sqvm.h | 4 +- 7 files changed, 46 insertions(+), 46 deletions(-) diff --git a/src/3rdparty/squirrel/sqstdlib/sqstdmath.cpp b/src/3rdparty/squirrel/sqstdlib/sqstdmath.cpp index 3ba6811a6c..7f07271f20 100644 --- a/src/3rdparty/squirrel/sqstdlib/sqstdmath.cpp +++ b/src/3rdparty/squirrel/sqstdlib/sqstdmath.cpp @@ -84,7 +84,7 @@ static SQRegFunction mathlib_funcs[] = { _DECL_FUNC(exp,2,".n"), #ifdef EXPORT_DEFAULT_SQUIRREL_FUNCTIONS _DECL_FUNC(srand,2,".n"), - _DECL_FUNC(rand,1,NULL), + _DECL_FUNC(rand,1,nullptr), #endif /* EXPORT_DEFAULT_SQUIRREL_FUNCTIONS */ _DECL_FUNC(fabs,2,".n"), _DECL_FUNC(abs,2,".n"), diff --git a/src/3rdparty/squirrel/sqstdlib/sqstdrex.cpp b/src/3rdparty/squirrel/sqstdlib/sqstdrex.cpp index 2bc3684a5e..16e87b3d24 100644 --- a/src/3rdparty/squirrel/sqstdlib/sqstdrex.cpp +++ b/src/3rdparty/squirrel/sqstdlib/sqstdrex.cpp @@ -378,8 +378,8 @@ static const SQChar *sqstd_rex_matchnode(SQRex* exp,SQRexNode *node,const SQChar SQRexNodeType type = node->type; switch(type) { case OP_GREEDY: { - //SQRexNode *greedystop = (node->next != -1) ? &exp->_nodes[node->next] : NULL; - SQRexNode *greedystop = NULL; + //SQRexNode *greedystop = (node->next != -1) ? &exp->_nodes[node->next] : nullptr; + SQRexNode *greedystop = nullptr; SQInteger p0 = (node->right >> 16)&0x0000FFFF, p1 = node->right&0x0000FFFF, nmaches = 0; const SQChar *s=str, *good = str; @@ -403,7 +403,7 @@ static const SQChar *sqstd_rex_matchnode(SQRex* exp,SQRexNode *node,const SQChar if(greedystop->type != OP_GREEDY || (greedystop->type == OP_GREEDY && ((greedystop->right >> 16)&0x0000FFFF) != 0)) { - SQRexNode *gnext = NULL; + SQRexNode *gnext = nullptr; if(greedystop->next != -1) { gnext = &exp->_nodes[greedystop->next]; }else if(next && next->next != -1){ @@ -425,12 +425,12 @@ static const SQChar *sqstd_rex_matchnode(SQRex* exp,SQRexNode *node,const SQChar if(p0 == p1 && p0 == nmaches) return good; else if(nmaches >= p0 && p1 == 0xFFFF) return good; else if(nmaches >= p0 && nmaches <= p1) return good; - return NULL; + return nullptr; } case OP_OR: { const SQChar *asd = str; SQRexNode *temp=&exp->_nodes[node->left]; - while( (asd = sqstd_rex_matchnode(exp,temp,asd,NULL)) ) { + while( (asd = sqstd_rex_matchnode(exp,temp,asd,nullptr)) ) { if(temp->next != -1) temp = &exp->_nodes[temp->next]; else @@ -438,13 +438,13 @@ static const SQChar *sqstd_rex_matchnode(SQRex* exp,SQRexNode *node,const SQChar } asd = str; temp = &exp->_nodes[node->right]; - while( (asd = sqstd_rex_matchnode(exp,temp,asd,NULL)) ) { + while( (asd = sqstd_rex_matchnode(exp,temp,asd,nullptr)) ) { if(temp->next != -1) temp = &exp->_nodes[temp->next]; else return asd; } - return NULL; + return nullptr; break; } case OP_EXPR: @@ -459,7 +459,7 @@ static const SQChar *sqstd_rex_matchnode(SQRex* exp,SQRexNode *node,const SQChar } do { - SQRexNode *subnext = NULL; + SQRexNode *subnext = nullptr; if(n->next != -1) { subnext = &exp->_nodes[n->next]; }else { @@ -470,7 +470,7 @@ static const SQChar *sqstd_rex_matchnode(SQRex* exp,SQRexNode *node,const SQChar exp->_matches[capture].begin = 0; exp->_matches[capture].len = 0; } - return NULL; + return nullptr; } } while((n->next != -1) && (n = &exp->_nodes[n->next])); @@ -483,15 +483,15 @@ static const SQChar *sqstd_rex_matchnode(SQRex* exp,SQRexNode *node,const SQChar || (str == exp->_eol && !isspace(*(str-1))) || (!isspace(*str) && isspace(*(str+1))) || (isspace(*str) && !isspace(*(str+1))) ) { - return (node->left == 'b')?str:NULL; + return (node->left == 'b')?str:nullptr; } - return (node->left == 'b')?NULL:str; + return (node->left == 'b')?nullptr:str; case OP_BOL: if(str == exp->_bol) return str; - return NULL; + return nullptr; case OP_EOL: if(str == exp->_eol) return str; - return NULL; + return nullptr; case OP_DOT:{ *str++; } @@ -502,26 +502,26 @@ static const SQChar *sqstd_rex_matchnode(SQRex* exp,SQRexNode *node,const SQChar *str++; return str; } - return NULL; + return nullptr; case OP_CCLASS: if(sqstd_rex_matchcclass(node->left,*str)) { *str++; return str; } - return NULL; + return nullptr; default: /* char */ - if(*str != (SQChar)node->type) return NULL; + if(*str != (SQChar)node->type) return nullptr; *str++; return str; } - return NULL; + return nullptr; } /* public api */ SQRex *sqstd_rex_compile(const SQChar *pattern,const SQChar **error) { SQRex *exp = (SQRex *)sq_malloc(sizeof(SQRex)); - exp->_eol = exp->_bol = NULL; + exp->_eol = exp->_bol = nullptr; exp->_p = pattern; exp->_nallocated = (SQInteger)strlen(pattern) * sizeof(SQChar); exp->_nodes = (SQRexNode *)sq_malloc(exp->_nallocated * sizeof(SQRexNode)); @@ -558,7 +558,7 @@ SQRex *sqstd_rex_compile(const SQChar *pattern,const SQChar **error) } catch (...) { sqstd_rex_free(exp); - return NULL; + return nullptr; } return exp; } @@ -574,19 +574,19 @@ void sqstd_rex_free(SQRex *exp) SQBool sqstd_rex_match(SQRex* exp,const SQChar* text) { - const SQChar* res = NULL; + const SQChar* res = nullptr; exp->_bol = text; exp->_eol = text + strlen(text); exp->_currsubexp = 0; - res = sqstd_rex_matchnode(exp,exp->_nodes,text,NULL); - if(res == NULL || res != exp->_eol) + res = sqstd_rex_matchnode(exp,exp->_nodes,text,nullptr); + if(res == nullptr || res != exp->_eol) return SQFalse; return SQTrue; } SQBool sqstd_rex_searchrange(SQRex* exp,const SQChar* text_begin,const SQChar* text_end,const SQChar** out_begin, const SQChar** out_end) { - const SQChar *cur = NULL; + const SQChar *cur = nullptr; SQInteger node = exp->_first; if(text_begin >= text_end) return SQFalse; exp->_bol = text_begin; @@ -595,15 +595,15 @@ SQBool sqstd_rex_searchrange(SQRex* exp,const SQChar* text_begin,const SQChar* t cur = text_begin; while(node != -1) { exp->_currsubexp = 0; - cur = sqstd_rex_matchnode(exp,&exp->_nodes[node],cur,NULL); + cur = sqstd_rex_matchnode(exp,&exp->_nodes[node],cur,nullptr); if(!cur) break; node = exp->_nodes[node].next; } *text_begin++; - } while(cur == NULL && text_begin != text_end); + } while(cur == nullptr && text_begin != text_end); - if(cur == NULL) + if(cur == nullptr) return SQFalse; --text_begin; diff --git a/src/3rdparty/squirrel/sqstdlib/sqstdstring.cpp b/src/3rdparty/squirrel/sqstdlib/sqstdstring.cpp index 300fed08e9..f042ac7df8 100644 --- a/src/3rdparty/squirrel/sqstdlib/sqstdstring.cpp +++ b/src/3rdparty/squirrel/sqstdlib/sqstdstring.cpp @@ -112,16 +112,16 @@ static SQInteger _string_split(HSQUIRRELVM v) memcpy(stemp,str,memsize); tok = scstrtok(stemp,seps); sq_newarray(v,0); - while( tok != NULL ) { + while( tok != nullptr ) { sq_pushstring(v,tok,-1); sq_arrayappend(v,-2); - tok = scstrtok( NULL, seps ); + tok = scstrtok( nullptr, seps ); } return 1; } #define SETUP_REX(v) \ - SQRex *self = NULL; \ + SQRex *self = nullptr; \ sq_getinstanceup(v,1,(SQUserPointer *)&self,0); static SQInteger _rexobj_releasehook(SQUserPointer p, SQInteger size) diff --git a/src/3rdparty/squirrel/squirrel/sqbaselib.cpp b/src/3rdparty/squirrel/squirrel/sqbaselib.cpp index a875f4b882..26c02510dd 100644 --- a/src/3rdparty/squirrel/squirrel/sqbaselib.cpp +++ b/src/3rdparty/squirrel/squirrel/sqbaselib.cpp @@ -101,7 +101,7 @@ static SQInteger base_getstackinfos(HSQUIRRELVM v) SQInteger level; SQStackInfos si; SQInteger seq = 0; - const SQChar *name = NULL; + const SQChar *name = nullptr; sq_getinteger(v, -1, &level); if (SQ_SUCCEEDED(sq_stackinfos(v, level, &si))) { @@ -180,7 +180,7 @@ static SQInteger base_print(HSQUIRRELVM v) static SQInteger base_compilestring(HSQUIRRELVM v) { SQInteger nargs=sq_gettop(v); - const SQChar *src=NULL,*name="unnamedbuffer"; + const SQChar *src=nullptr,*name="unnamedbuffer"; SQInteger size; sq_getstring(v,2,&src); size=sq_getsize(v,2); @@ -239,26 +239,26 @@ static SQInteger base_type(HSQUIRRELVM v) static SQRegFunction base_funcs[]={ //generic #ifdef EXPORT_DEFAULT_SQUIRREL_FUNCTIONS - {"seterrorhandler",base_seterrorhandler,2, NULL}, - {"setdebughook",base_setdebughook,2, NULL}, - {"enabledebuginfo",base_enabledebuginfo,2, NULL}, + {"seterrorhandler",base_seterrorhandler,2, nullptr}, + {"setdebughook",base_setdebughook,2, nullptr}, + {"enabledebuginfo",base_enabledebuginfo,2, nullptr}, {"getstackinfos",base_getstackinfos,2, ".n"}, - {"getroottable",base_getroottable,1, NULL}, - {"setroottable",base_setroottable,2, NULL}, - {"getconsttable",base_getconsttable,1, NULL}, - {"setconsttable",base_setconsttable,2, NULL}, + {"getroottable",base_getroottable,1, nullptr}, + {"setroottable",base_setroottable,2, nullptr}, + {"getconsttable",base_getconsttable,1, nullptr}, + {"setconsttable",base_setconsttable,2, nullptr}, #endif {"assert",base_assert,2, nullptr}, {"print",base_print,2, nullptr}, #ifdef EXPORT_DEFAULT_SQUIRREL_FUNCTIONS {"compilestring",base_compilestring,-2, ".ss"}, {"newthread",base_newthread,2, ".c"}, - {"suspend",base_suspend,-1, NULL}, + {"suspend",base_suspend,-1, nullptr}, #endif {"array",base_array,-2, ".n"}, {"type",base_type,2, nullptr}, #ifdef EXPORT_DEFAULT_SQUIRREL_FUNCTIONS - {"dummy",base_dummy,0,NULL}, + {"dummy",base_dummy,0,nullptr}, #ifndef NO_GARBAGE_COLLECTOR {"collectgarbage",base_collectgarbage,1, "t"}, #endif diff --git a/src/3rdparty/squirrel/squirrel/sqobject.h b/src/3rdparty/squirrel/squirrel/sqobject.h index 03d6dcca34..67f74deb7a 100644 --- a/src/3rdparty/squirrel/squirrel/sqobject.h +++ b/src/3rdparty/squirrel/squirrel/sqobject.h @@ -107,7 +107,7 @@ struct SQObjectPtr; (obj)->_uiRef--; \ if((obj)->_uiRef == 0) \ (obj)->Release(); \ - (obj) = NULL; \ + (obj) = nullptr; \ } \ } @@ -417,7 +417,7 @@ public: #define ADD_TO_CHAIN(chain,obj) AddToChain(chain,obj) #define REMOVE_FROM_CHAIN(chain,obj) {if(!(_uiRef&MARK_FLAG))RemoveFromChain(chain,obj);} #define CHAINABLE_OBJ SQCollectable -#define INIT_CHAIN() {_next=NULL;_prev=NULL;_sharedstate=ss;} +#define INIT_CHAIN() {_next=nullptr;_prev=nullptr;_sharedstate=ss;} #else #define ADD_TO_CHAIN(chain,obj) ((void)0) diff --git a/src/3rdparty/squirrel/squirrel/sqstate.cpp b/src/3rdparty/squirrel/squirrel/sqstate.cpp index b9afb8b134..3adb4d8f98 100644 --- a/src/3rdparty/squirrel/squirrel/sqstate.cpp +++ b/src/3rdparty/squirrel/squirrel/sqstate.cpp @@ -201,7 +201,7 @@ SQSharedState::~SQSharedState() t = nx; } } -// assert(_gc_chain==NULL); //just to proove a theory +// assert(_gc_chain==nullptr); //just to proove a theory while(_gc_chain){ _gc_chain->_uiRef--; _gc_chain->Release(); diff --git a/src/3rdparty/squirrel/squirrel/sqvm.h b/src/3rdparty/squirrel/squirrel/sqvm.h index d38c1e461f..577300a237 100644 --- a/src/3rdparty/squirrel/squirrel/sqvm.h +++ b/src/3rdparty/squirrel/squirrel/sqvm.h @@ -194,7 +194,7 @@ inline SQObjectPtr &stack_get(HSQUIRRELVM v,SQInteger idx){return ((idx>=0)?(v-> #ifndef NO_GARBAGE_COLLECTOR #define _opt_ss(_vm_) (_vm_)->_sharedstate #else -#define _opt_ss(_vm_) NULL +#define _opt_ss(_vm_) nullptr #endif #define PUSH_CALLINFO(v,nci){ \ @@ -218,6 +218,6 @@ inline SQObjectPtr &stack_get(HSQUIRRELVM v,SQInteger idx){return ((idx>=0)?(v-> if(v->_callsstacksize) \ v->ci = &v->_callsstack[v->_callsstacksize-1] ; \ else \ - v->ci = NULL; \ + v->ci = nullptr; \ } #endif //_SQVM_H_ From 2b914c7a2f76f3d932a2eaedce0c308f2a674dff Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Tue, 26 Dec 2023 21:00:13 +0000 Subject: [PATCH 17/19] Fix: Memory leak in WindowDescTestsFixture --- src/tests/test_window_desc.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tests/test_window_desc.cpp b/src/tests/test_window_desc.cpp index 1a5be4a1c6..ab89c12ccc 100644 --- a/src/tests/test_window_desc.cpp +++ b/src/tests/test_window_desc.cpp @@ -95,4 +95,5 @@ TEST_CASE_METHOD(WindowDescTestsFixture, "WindowDesc - NWidgetPart validity") REQUIRE_NOTHROW(root = MakeWindowNWidgetTree(window_desc->nwid_begin, window_desc->nwid_end, &biggest_index, &shade_select)); CHECK((root != nullptr)); + delete root; } From ce6a65d7b5174da6556057e10f05081fdfb7d8a5 Mon Sep 17 00:00:00 2001 From: translators Date: Wed, 27 Dec 2023 18:38:01 +0000 Subject: [PATCH 18/19] Update: Translations from eints english (au): 2 changes by krysclarke chinese (simplified): 37 changes by WenSimEHRP romanian: 28 changes by bnegrut russian: 13 changes by Ln-Wolf finnish: 36 changes by hpiirai danish: 16 changes by bscargo dutch: 17 changes by Afoklala --- src/lang/danish.txt | 22 ++++++++++++----- src/lang/dutch.txt | 23 ++++++++++++----- src/lang/english_AU.txt | 4 +-- src/lang/finnish.txt | 43 ++++++++++++++++++++++++++------ src/lang/romanian.txt | 28 +++++++++++++++++++++ src/lang/russian.txt | 26 +++++++++---------- src/lang/simplified_chinese.txt | 44 +++++++++++++++++++++++++++------ 7 files changed, 149 insertions(+), 41 deletions(-) diff --git a/src/lang/danish.txt b/src/lang/danish.txt index 63ef2596cf..6f51fc9060 100644 --- a/src/lang/danish.txt +++ b/src/lang/danish.txt @@ -256,6 +256,7 @@ STR_UNITS_HEIGHT_METRIC :{DECIMAL} m STR_UNITS_HEIGHT_SI :{DECIMAL} m STR_UNITS_DAYS :{COMMA}{NBSP}dag{P "" s} +STR_UNITS_SECONDS :{COMMA}{NBSP}sekund{P "" er} # Common window strings STR_LIST_FILTER_TITLE :{BLACK}Filtrer udtryk: @@ -1489,7 +1490,7 @@ STR_CONFIG_SETTING_LAND_GENERATOR_ORIGINAL :Original STR_CONFIG_SETTING_LAND_GENERATOR_TERRA_GENESIS :TerraGenesis STR_CONFIG_SETTING_TERRAIN_TYPE :Terræn type: {STRING} -STR_CONFIG_SETTING_TERRAIN_TYPE_HELPTEXT :(Kun TerraGenesis) Størrelse af højderygge +STR_CONFIG_SETTING_TERRAIN_TYPE_HELPTEXT :Vælg højden på bakker og bjerge i landskabet STR_CONFIG_SETTING_INDUSTRY_DENSITY :Industri tæthed: {STRING} STR_CONFIG_SETTING_INDUSTRY_DENSITY_HELPTEXT :Angiv hvor mange industrier skal genereres og hvilket niveau der bevares i løbet af spillet @@ -1498,18 +1499,18 @@ STR_CONFIG_SETTING_OIL_REF_EDGE_DISTANCE :Maksimal afstan STR_CONFIG_SETTING_OIL_REF_EDGE_DISTANCE_HELPTEXT :Grænse for hvor langt fra kortets kant olieraffinaderier kan blive bygget. På ø-kort sikrer dette at de er nær kysten. På kort større end 256 felter bliver denne værdi automatisk skaleret op. STR_CONFIG_SETTING_SNOWLINE_HEIGHT :Snelinjehøjden: {STRING} -STR_CONFIG_SETTING_SNOWLINE_HEIGHT_HELPTEXT :Styrer ved hvilken højde sneen starter i det sub-arktiske landskab. Sne påvirker også industri-generering og byers krav for at vokse.Kan kun ændres i Scenarieeditoren, og beregnes ellers via "snedække". +STR_CONFIG_SETTING_SNOWLINE_HEIGHT_HELPTEXT :Vælg, i hvilken højde sneen starter i det subarktiske landskab. Sne påvirker også industriproduktion og byvækstkrav. Kan kun ændres via Scenario Editor eller på anden måde beregnes via "snedækning" STR_CONFIG_SETTING_SNOW_COVERAGE :Snedække: {STRING} -STR_CONFIG_SETTING_SNOW_COVERAGE_HELPTEXT :Styrer den omtrentlige mængde sne i det sub-arktiske landskab. Sne påvirker også industri-generering og byernes krav for at vokse. Anvendes kun under landskabsgenerering. Land lige over havniveau er altid snefrit. +STR_CONFIG_SETTING_SNOW_COVERAGE_HELPTEXT :Vælg den omtrentlige mængde sne på det subarktiske landskab. Sne påvirker også industriproduktion og byvækstkrav. Bruges kun under kortgenerering. Havniveau og kystfliser har aldrig sne. STR_CONFIG_SETTING_SNOW_COVERAGE_VALUE :{NUM}% STR_CONFIG_SETTING_DESERT_COVERAGE :Ørkendækning: {STRING} -STR_CONFIG_SETTING_DESERT_COVERAGE_HELPTEXT :Styrer den omtrentlige mængde ørken i det tropiske landskab. Ørken påvirker også industri-generering. Anvendes kun under landskabsgenerering. +STR_CONFIG_SETTING_DESERT_COVERAGE_HELPTEXT :Vælg den omtrentlige mængde ørken i det tropiske landskab. Ørken påvirker også industriproduktion og byvækstkrav. Bruges kun under kortgenerering STR_CONFIG_SETTING_DESERT_COVERAGE_VALUE :{NUM}% STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN :Tærrenets hårdhed (kun TerraGenesis) : {STRING} -STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_HELPTEXT :(TerraGenesis kun) Vælg frekvensen af bakkerne: Glatte landskaber har færre, mere udbredt bakker. Ujævne landskaber har mange bakker, der kan se gentaget ud +STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_HELPTEXT :Vælg formen og antallet af bakker. Glatte landskaber har færre, bredere bakker, mens barske landskaber har flere mindre bakker. ###length 4 STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_VERY_SMOOTH :Meget blødt STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_SMOOTH :Blødt @@ -1517,7 +1518,7 @@ STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_ROUGH :Råt STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_VERY_ROUGH :Meget råt STR_CONFIG_SETTING_VARIETY :Forskelligheds fordeling: {STRING} -STR_CONFIG_SETTING_VARIETY_HELPTEXT :(TerraGenesis kun) Kontrollere, om kortet indeholder både bjerg- og flade områder. Da dette kun gør kortet fladere bør andre indstillinger sættes til bjergrigt +STR_CONFIG_SETTING_VARIETY_HELPTEXT :Vælg om kortet indeholder både bjerge og flade områder. Jo højere sorten er, jo flere højdeforskelle mellem bjergrige og flade områder. STR_CONFIG_SETTING_RIVER_AMOUNT :Floder antal: {STRING} STR_CONFIG_SETTING_RIVER_AMOUNT_HELPTEXT :Vælg, hvor mange floder at skabe @@ -1658,6 +1659,7 @@ STR_CONFIG_SETTING_ADVANCED_VEHICLE_LISTS_HELPTEXT :Aktiver brug af STR_CONFIG_SETTING_LOADING_INDICATORS :Benyt laste-indikatorer: {STRING} STR_CONFIG_SETTING_LOADING_INDICATORS_HELPTEXT :Vælg om lastnings-indikatorer vises ved pålæsning og aflæsning af køretøjer +STR_CONFIG_SETTING_TIMETABLE_MODE :Tidsenheder for køreplaner: {STRING} STR_CONFIG_SETTING_TIMETABLE_MODE_HELPTEXT :Vælg de tidsenheder, der skal bruges til køreplaner ###length 3 STR_CONFIG_SETTING_TIMETABLE_MODE_DAYS :Dage @@ -3211,7 +3213,9 @@ STR_MAPGEN_TOWN_NAME_DROPDOWN_TOOLTIP :{BLACK}Vælg st STR_MAPGEN_DATE :{BLACK}Dato: STR_MAPGEN_DATE_TOOLTIP :{BLACK}Vælg startdato STR_MAPGEN_NUMBER_OF_INDUSTRIES :{BLACK}Antal industrier: +STR_MAPGEN_NUMBER_OF_INDUSTRIES_TOOLTIP :{BLACK}Vælg tætheden af industrier eller et brugerdefineret tal STR_MAPGEN_HEIGHTMAP_HEIGHT :{BLACK}Højeste bjergtop: +STR_MAPGEN_HEIGHTMAP_HEIGHT_TOOLTIP :{BLACK}Vælg den højeste top, som spillet vil forsøge at skabe, målt i højde over havets overflade STR_MAPGEN_HEIGHTMAP_HEIGHT_UP :{BLACK}Forøger den maksimale højde på højeste bjergtop på kortet med én STR_MAPGEN_HEIGHTMAP_HEIGHT_DOWN :{BLACK}Sænker den maksimale højde på højeste bjergtop på kortet med én STR_MAPGEN_SNOW_COVERAGE :{BLACK}Snedække: @@ -3224,6 +3228,7 @@ STR_MAPGEN_DESERT_COVERAGE_DOWN :{BLACK}Sænker STR_MAPGEN_DESERT_COVERAGE_TEXT :{BLACK}{NUM}% STR_MAPGEN_TERRAIN_TYPE :{BLACK}Terræntype: STR_MAPGEN_SEA_LEVEL :{BLACK}Havniveau +STR_MAPGEN_SEA_LEVEL_TOOLTIP :{BLACK}Vælg havniveau STR_MAPGEN_QUANTITY_OF_RIVERS :{BLACK}Floder: STR_MAPGEN_SMOOTHNESS :{BLACK}Blødhed: STR_MAPGEN_VARIETY :{BLACK}Varietet af distributionen: @@ -3261,6 +3266,7 @@ STR_MAPGEN_TOWN_NAME_CATALAN :Catalanske # Strings for map borders at game generation STR_MAPGEN_BORDER_TYPE :{BLACK}Kortkanter: +STR_MAPGEN_BORDER_TYPE_TOOLTIP :Vælg ydre grænser for spilverdenen STR_MAPGEN_NORTHWEST :{BLACK}Nordvest STR_MAPGEN_NORTHEAST :{BLACK}Nordøst STR_MAPGEN_SOUTHEAST :{BLACK}Sydøst @@ -3273,7 +3279,9 @@ STR_MAPGEN_BORDER_MANUAL :{BLACK}Manuel STR_MAPGEN_HEIGHTMAP_ROTATION :{BLACK}Højdekortets rotation: STR_MAPGEN_HEIGHTMAP_NAME :{BLACK}Højdekortets navn: +STR_MAPGEN_HEIGHTMAP_NAME_TOOLTIP :{BLACK}Navnet på højdekort-billedfilen STR_MAPGEN_HEIGHTMAP_SIZE_LABEL :{BLACK}Størrelse: +STR_MAPGEN_HEIGHTMAP_SIZE_LABEL_TOOLTIP :{BLACK}Størrelsen på kildehøjdekortbilledet. For de bedste resultater skal hver kant matche en tilgængelig kortkantlængde i OpenTTD, såsom 256, 512, 1024 osv. STR_MAPGEN_HEIGHTMAP_SIZE :{ORANGE}{NUM} x {NUM} STR_MAPGEN_TERRAIN_TYPE_QUERY_CAPT :{WHITE}Ønsket højeste bjergtop @@ -3288,6 +3296,7 @@ STR_SE_MAPGEN_FLAT_WORLD :{WHITE}Fladt la STR_SE_MAPGEN_FLAT_WORLD_TOOLTIP :{BLACK}Generer fladt landskab STR_SE_MAPGEN_RANDOM_LAND :{WHITE}Tilfældigt land STR_SE_MAPGEN_FLAT_WORLD_HEIGHT :{BLACK}Højde af fladt landskab: +STR_SE_MAPGEN_FLAT_WORLD_HEIGHT_TOOLTIP :{BLACK}Vælg højden af landet over havets overflade STR_SE_MAPGEN_FLAT_WORLD_HEIGHT_DOWN :{BLACK}Sæt højden af fladt landskab en ned STR_SE_MAPGEN_FLAT_WORLD_HEIGHT_UP :{BLACK}Sæt højden af fladt landskab en op @@ -4614,6 +4623,7 @@ STR_TIMETABLE_EXPECTED_TOOLTIP :{BLACK}Skift me STR_TIMETABLE_ARRIVAL_DATE :A: {COLOUR}{DATE_TINY} STR_TIMETABLE_DEPARTURE_DATE :D: {COLOUR}{DATE_TINY} STR_TIMETABLE_ARRIVAL_SECONDS_IN_FUTURE :A: {COLOUR}{COMMA} sek +STR_TIMETABLE_DEPARTURE_SECONDS_IN_FUTURE :D: {COLOUR}{COMMA} sek # Date window (for timetable) diff --git a/src/lang/dutch.txt b/src/lang/dutch.txt index 5ddd1e5dc5..60fead6ee5 100644 --- a/src/lang/dutch.txt +++ b/src/lang/dutch.txt @@ -1491,7 +1491,7 @@ STR_CONFIG_SETTING_LAND_GENERATOR_ORIGINAL :Origineel STR_CONFIG_SETTING_LAND_GENERATOR_TERRA_GENESIS :TerraGenesis STR_CONFIG_SETTING_TERRAIN_TYPE :Terreintype: {STRING} -STR_CONFIG_SETTING_TERRAIN_TYPE_HELPTEXT :(Alleen TerraGenesis) Heuvelachtigheid van het landschap +STR_CONFIG_SETTING_TERRAIN_TYPE_HELPTEXT :Kies de hoogte van heuvels en bergen in het landschap STR_CONFIG_SETTING_INDUSTRY_DENSITY :Industriedichtheid: {STRING} STR_CONFIG_SETTING_INDUSTRY_DENSITY_HELPTEXT :Stelt in hoeveel industrieën worden gegenereerd en welk niveau tijdens het spel moet worden gehandhaafd @@ -1500,18 +1500,18 @@ STR_CONFIG_SETTING_OIL_REF_EDGE_DISTANCE :Maximumafstand STR_CONFIG_SETTING_OIL_REF_EDGE_DISTANCE_HELPTEXT :Olieraffinaderijen worden alleen gebouwd nabij de kaartgrens, dat is aan de kust van eilandkaarten STR_CONFIG_SETTING_SNOWLINE_HEIGHT :Sneeuwhoogte: {STRING} -STR_CONFIG_SETTING_SNOWLINE_HEIGHT_HELPTEXT :Stelt in op welke hoogte de sneeuw begint in subarctisch landschap. Sneeuw heeft ook invloed op het ontstaan van industrieën en op de vereisten voor stadsgroei. Kan alleen worden aangepast in de scenariobewerker of wordt berekend met behulp van 'sneeuwoppervlak' +STR_CONFIG_SETTING_SNOWLINE_HEIGHT_HELPTEXT :Kies op welke hoogte de sneeuw begint in subarctisch landschap. Sneeuw heeft ook invloed op het ontstaan van industrieën en op de vereisten voor stadsgroei. Kan alleen worden aangepast in de scenariobewerker of wordt berekend met behulp van 'sneeuwoppervlak' STR_CONFIG_SETTING_SNOW_COVERAGE :Sneeuwoppervlak: {STRING} -STR_CONFIG_SETTING_SNOW_COVERAGE_HELPTEXT :Bepaalt de hoeveelheid sneeuw in het subarctische landschap. Sneeuw is ook van invloed op de industrieën en de groei van steden. Wordt alleen gebruikt tijdens het maken van de kaart. Land net boven zeeniveau krijgt nooit sneeuw +STR_CONFIG_SETTING_SNOW_COVERAGE_HELPTEXT :Kies de hoeveelheid sneeuw in het subarctische landschap. Sneeuw is ook van invloed op de industrieën en de groei van steden. Wordt alleen gebruikt tijdens het maken van de kaart. Land op zeeniveau of aan de kust krijgt nooit sneeuw. STR_CONFIG_SETTING_SNOW_COVERAGE_VALUE :{NUM}% STR_CONFIG_SETTING_DESERT_COVERAGE :Woestijnoppervlak: {STRING} -STR_CONFIG_SETTING_DESERT_COVERAGE_HELPTEXT :Bepaalt de hoeveelheid woestijn in het tropische landschap. Woestijn is ook van invloed op industrieën. Wordt alleen gebruikt tijdens het maken van de kaart +STR_CONFIG_SETTING_DESERT_COVERAGE_HELPTEXT :Kies de hoeveelheid woestijn in het tropische landschap. Woestijn is ook van invloed op het ontstaan van industrieën en de vereisten voor stadsgroei. Wordt alleen gebruikt tijdens het maken van de kaart STR_CONFIG_SETTING_DESERT_COVERAGE_VALUE :{NUM}% STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN :Ruwheid van het terrein: {STRING} -STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_HELPTEXT :(Alleen TerraGenesis) Selecteer de frequentie van heuvels: gladde landschappen hebben minder, meer wijdverspreide heuvels. Ruwe landschappen hebben veel heuvels, die repetitief kunnen lijken. +STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_HELPTEXT :Kies vorm en aantal heuvels. Gladde landschappen hebben minder en bredere heuvels. Ruwe landschappen hebben meer, maar kleinere heuvels. ###length 4 STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_VERY_SMOOTH :Erg glad STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_SMOOTH :Glad @@ -1519,7 +1519,7 @@ STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_ROUGH :Ruig STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_VERY_ROUGH :Erg ruig STR_CONFIG_SETTING_VARIETY :Variëteit distributie: {STRING} -STR_CONFIG_SETTING_VARIETY_HELPTEXT :(Alleen TerraGenesis) Bepaalt of de kaart zowel bergachtige als vlakke gebieden bevat. Aangezien dit de kaart alleen platter maakt, moeten andere instellingen worden ingesteld op bergachtig. +STR_CONFIG_SETTING_VARIETY_HELPTEXT :Kies of de kaart zowel bergachtige als vlakke gebieden bevat. Hoe groter de variatie, hoe meer verschillen in hoogte tussen bergachtige en vlakke gebieden. STR_CONFIG_SETTING_RIVER_AMOUNT :Hoeveelheid rivieren: {STRING} STR_CONFIG_SETTING_RIVER_AMOUNT_HELPTEXT :Selecteer hoeveel rivieren er gegenereerd worden @@ -1539,6 +1539,7 @@ STR_CONFIG_SETTING_ROAD_SIDE_LEFT :Links rijden STR_CONFIG_SETTING_ROAD_SIDE_RIGHT :Rechts rijden STR_CONFIG_SETTING_HEIGHTMAP_ROTATION :Draaiing van hoogtekaart: {STRING} +STR_CONFIG_SETTING_HEIGHTMAP_ROTATION_TOOLTIP :Kies in welke richting de hoogtekaart wordt gedraaid om deze aan te passen aan de spelwereld ###length 2 STR_CONFIG_SETTING_HEIGHTMAP_ROTATION_COUNTER_CLOCKWISE :Tegen de klok in STR_CONFIG_SETTING_HEIGHTMAP_ROTATION_CLOCKWISE :Met de klok mee @@ -3208,11 +3209,15 @@ STR_MAPGEN_MAPSIZE :{BLACK}Kaartgro STR_MAPGEN_MAPSIZE_TOOLTIP :{BLACK}Selecteer het formaat van de kaart in tegels. Het aantal beschikbare tegels zal iets kleiner zijn STR_MAPGEN_BY :{BLACK}* STR_MAPGEN_NUMBER_OF_TOWNS :{BLACK}Aantal steden: +STR_MAPGEN_NUMBER_OF_TOWNS_TOOLTIP :{BLACK}Kies de dichtheid van steden of een aangepast getal STR_MAPGEN_TOWN_NAME_LABEL :{BLACK}Plaatsnamen: STR_MAPGEN_TOWN_NAME_DROPDOWN_TOOLTIP :{BLACK}Stijl voor plaatsnamen kiezen STR_MAPGEN_DATE :{BLACK}Datum: +STR_MAPGEN_DATE_TOOLTIP :{BLACK}Kies de startdatum STR_MAPGEN_NUMBER_OF_INDUSTRIES :{BLACK}Aantal industrieën: +STR_MAPGEN_NUMBER_OF_INDUSTRIES_TOOLTIP :{BLACK}Kies de dichtheid van industrieën of een aangepast getal STR_MAPGEN_HEIGHTMAP_HEIGHT :{BLACK}Hoogste berg: +STR_MAPGEN_HEIGHTMAP_HEIGHT_TOOLTIP :{BLACK}Kies de hoogste piek die het spel probeert te creëren, gemeten in hoogte boven zeeniveau STR_MAPGEN_HEIGHTMAP_HEIGHT_UP :{BLACK}Verhoogt de maximale hoogte van de hoogste berg op de kaart met één STR_MAPGEN_HEIGHTMAP_HEIGHT_DOWN :{BLACK}Verlaagt de maximale hoogte van de hoogste berg op de kaart met één STR_MAPGEN_SNOW_COVERAGE :{BLACK}Sneeuwoppervlak: @@ -3225,10 +3230,12 @@ STR_MAPGEN_DESERT_COVERAGE_DOWN :{BLACK}Verklein STR_MAPGEN_DESERT_COVERAGE_TEXT :{BLACK}{NUM}% STR_MAPGEN_TERRAIN_TYPE :{BLACK}Terreintype: STR_MAPGEN_SEA_LEVEL :{BLACK}Zeeniveau: +STR_MAPGEN_SEA_LEVEL_TOOLTIP :{BLACK}Kies het zeeniveau STR_MAPGEN_QUANTITY_OF_RIVERS :{BLACK}Rivieren: STR_MAPGEN_SMOOTHNESS :{BLACK}Gladheid: STR_MAPGEN_VARIETY :{BLACK}Landschapsvariatie: STR_MAPGEN_GENERATE :{WHITE}Maken +STR_MAPGEN_GENERATE_TOOLTIP :{BLACK}Creëer de wereld en speel OpenTTD! STR_MAPGEN_NEWGRF_SETTINGS :{BLACK}NewGRF-instellingen STR_MAPGEN_NEWGRF_SETTINGS_TOOLTIP :{BLACK}NewGRF-instellingen weergeven STR_MAPGEN_AI_SETTINGS :{BLACK}AI-instellingen @@ -3261,6 +3268,7 @@ STR_MAPGEN_TOWN_NAME_CATALAN :Catalaans # Strings for map borders at game generation STR_MAPGEN_BORDER_TYPE :{BLACK}Kaartranden: +STR_MAPGEN_BORDER_TYPE_TOOLTIP :{BLACK}Kies de grenzen van de spelwereld STR_MAPGEN_NORTHWEST :{BLACK}Noordwest STR_MAPGEN_NORTHEAST :{BLACK}Noordoost STR_MAPGEN_SOUTHEAST :{BLACK}Zuidoost @@ -3273,7 +3281,9 @@ STR_MAPGEN_BORDER_MANUAL :{BLACK}Handmati STR_MAPGEN_HEIGHTMAP_ROTATION :{BLACK}Rotatie van hoogtekaart: STR_MAPGEN_HEIGHTMAP_NAME :{BLACK}Naam van hoogtekaart: +STR_MAPGEN_HEIGHTMAP_NAME_TOOLTIP :{BLACK}De naam van het hoogtekaart-bestand STR_MAPGEN_HEIGHTMAP_SIZE_LABEL :{BLACK}Grootte: +STR_MAPGEN_HEIGHTMAP_SIZE_LABEL_TOOLTIP :{BLACK}De grootte van de bron-hoogtekaart. Voor optimaal resultaat kies je de lengten van de zijden gelijk aan de beschikbare kaartmaten in OpenTTD, zoals 256, 512, 1024 enz. STR_MAPGEN_HEIGHTMAP_SIZE :{ORANGE}{NUM} x {NUM} STR_MAPGEN_TERRAIN_TYPE_QUERY_CAPT :{WHITE}Gewenste hoogte van bergen @@ -3288,6 +3298,7 @@ STR_SE_MAPGEN_FLAT_WORLD :{WHITE}Vlak lan STR_SE_MAPGEN_FLAT_WORLD_TOOLTIP :{BLACK}Genereer een vlakke kaart STR_SE_MAPGEN_RANDOM_LAND :{WHITE}Willekeurig land STR_SE_MAPGEN_FLAT_WORLD_HEIGHT :{BLACK}Hoogte van vlak land: +STR_SE_MAPGEN_FLAT_WORLD_HEIGHT_TOOLTIP :{BLACK}Kies de hoogte van het land boven zee STR_SE_MAPGEN_FLAT_WORLD_HEIGHT_DOWN :{BLACK}Verlaag de hoogte van vlak land met één STR_SE_MAPGEN_FLAT_WORLD_HEIGHT_UP :{BLACK}Verhoog de hoogte van vlak land met één diff --git a/src/lang/english_AU.txt b/src/lang/english_AU.txt index a5f3bd9d8c..0278f5a4ee 100644 --- a/src/lang/english_AU.txt +++ b/src/lang/english_AU.txt @@ -4467,9 +4467,9 @@ STR_ORDER_CONDITIONAL_COMPARATOR_TOOLTIP :{BLACK}How to c STR_ORDER_CONDITIONAL_COMPARATOR_EQUALS :is equal to STR_ORDER_CONDITIONAL_COMPARATOR_NOT_EQUALS :is not equal to STR_ORDER_CONDITIONAL_COMPARATOR_LESS_THAN :is less than -STR_ORDER_CONDITIONAL_COMPARATOR_LESS_EQUALS :is less or equal to +STR_ORDER_CONDITIONAL_COMPARATOR_LESS_EQUALS :is less than or equal to STR_ORDER_CONDITIONAL_COMPARATOR_MORE_THAN :is more than -STR_ORDER_CONDITIONAL_COMPARATOR_MORE_EQUALS :is more or equal to +STR_ORDER_CONDITIONAL_COMPARATOR_MORE_EQUALS :is more than or equal to STR_ORDER_CONDITIONAL_COMPARATOR_IS_TRUE :is true STR_ORDER_CONDITIONAL_COMPARATOR_IS_FALSE :is false diff --git a/src/lang/finnish.txt b/src/lang/finnish.txt index 066c967b3a..d161ecb8c3 100644 --- a/src/lang/finnish.txt +++ b/src/lang/finnish.txt @@ -255,6 +255,9 @@ STR_UNITS_HEIGHT_IMPERIAL :{DECIMAL}{NBSP} STR_UNITS_HEIGHT_METRIC :{DECIMAL}{NBSP}m STR_UNITS_HEIGHT_SI :{DECIMAL}{NBSP}m +STR_UNITS_DAYS :{COMMA}{NBSP}vrk +STR_UNITS_SECONDS :{COMMA}{NBSP}sekunti{P "" a} +STR_UNITS_TICKS :{COMMA}{NBSP}räpäys{P "" tä} # Common window strings STR_LIST_FILTER_TITLE :{BLACK}Suodatin: @@ -719,6 +722,7 @@ STR_PLAYLIST_TOOLTIP_CLICK_TO_ADD_TRACK :{BLACK}Valitse STR_PLAYLIST_TOOLTIP_CLICK_TO_REMOVE_TRACK :{BLACK}Poista musiikkiraita nykyiseltä soittolistalta napsauttamalla (vain oma{NBSP}1 tai oma{NBSP}2) # Highscore window +STR_HIGHSCORE_TOP_COMPANIES :{BIG_FONT}{BLACK}Huippuyhtiöt STR_HIGHSCORE_POSITION :{BIG_FONT}{BLACK}{COMMA}. STR_HIGHSCORE_PERFORMANCE_TITLE_BUSINESSMAN :Kaupantekijä STR_HIGHSCORE_PERFORMANCE_TITLE_ENTREPRENEUR :Yrittäjä @@ -1487,7 +1491,7 @@ STR_CONFIG_SETTING_LAND_GENERATOR_ORIGINAL :Alkuperäinen STR_CONFIG_SETTING_LAND_GENERATOR_TERRA_GENESIS :TerraGenesis STR_CONFIG_SETTING_TERRAIN_TYPE :Maaston tyyppi: {STRING} -STR_CONFIG_SETTING_TERRAIN_TYPE_HELPTEXT :(Vain TerraGenesis) Maaston mäkisyys +STR_CONFIG_SETTING_TERRAIN_TYPE_HELPTEXT :Valitse maiseman mäkien ja vuorten korkeus STR_CONFIG_SETTING_INDUSTRY_DENSITY :Teollisuuden määrä: {STRING} STR_CONFIG_SETTING_INDUSTRY_DENSITY_HELPTEXT :Määritä, kuinka paljon teollisuutta tulisi luoda ja millä tasolla teollisuuden tulisi pysytellä pelin aikana @@ -1496,18 +1500,18 @@ STR_CONFIG_SETTING_OIL_REF_EDGE_DISTANCE :Suurin sallittu STR_CONFIG_SETTING_OIL_REF_EDGE_DISTANCE_HELPTEXT :Öljynjalostamojen ja öljynporauslauttojen suurin etäisyys kartan reunasta. Saarikartoilla tämä takaa sen, että ne ovat lähellä rannikkoa. Yli 256 ruudun kartoilla tämä arvo suhteutetaan kartan kokoon. STR_CONFIG_SETTING_SNOWLINE_HEIGHT :Lumirajan korkeus: {STRING} -STR_CONFIG_SETTING_SNOWLINE_HEIGHT_HELPTEXT :Määritä, millä korkeudella lumiraja on pohjoisessa maastotyypissä. Lumi vaikuttaa teollisuuslaitosten luontiin sekä kuntien kasvuedellytyksiin. Voidaan muuttaa vain Skenaariomuokkaimessa, muuten lasketaan ”lumen peiton” perusteella +STR_CONFIG_SETTING_SNOWLINE_HEIGHT_HELPTEXT :Säätää lumirajan korkeutta pohjoisessa maastossa. Lumi vaikuttaa myös teollisuuslaitosten luontiin ja kuntien kasvuedellytyksiin. Voidaan muuttaa vain skenaariomuokkaimessa, lasketaan muutoin ”lumen peiton” perusteella STR_CONFIG_SETTING_SNOW_COVERAGE :Lumen peitto: {STRING} -STR_CONFIG_SETTING_SNOW_COVERAGE_HELPTEXT :Säätele lumen määrän suuruusluokkaa pohjoisessa maastossa. Lumi vaikuttaa myös teollisuuden luontiin ja kuntien kasvuedellytyksiin. Käytetään vain karttaa luodessa. Juuri merenpinnan yläpuolella oleva maa on aina lumetonta +STR_CONFIG_SETTING_SNOW_COVERAGE_HELPTEXT :Säätää lumen määrän suuruusluokkaa pohjoisessa maastossa. Lumi vaikuttaa myös teollisuuslaitosten luontiin ja kuntien kasvuedellytyksiin. Käytetään vain karttaa luotaessa. Merenpinnan tasolla sijaitsevat ruudut ja rannikkoruudut ovat aina lumettomat. STR_CONFIG_SETTING_SNOW_COVERAGE_VALUE :{NUM}{NBSP}% STR_CONFIG_SETTING_DESERT_COVERAGE :Aavikon peitto: {STRING} -STR_CONFIG_SETTING_DESERT_COVERAGE_HELPTEXT :Säätele aavikon määrän suuruusluokkaa subtrooppisessa maastossa. Aavikko vaikuttaa myös teollisuuden luontiin. Käytetään vain karttaa luodessa +STR_CONFIG_SETTING_DESERT_COVERAGE_HELPTEXT :Säätele aavikon määrän suuruusluokkaa subtrooppisessa maastossa. Aavikko vaikuttaa myös teollisuuslaitosten luontiin ja kuntien kasvuedellytyksiin. Käytetään vain karttaa luotaessa. STR_CONFIG_SETTING_DESERT_COVERAGE_VALUE :{NUM}{NBSP}% STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN :Maaston epätasaisuus: {STRING} -STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_HELPTEXT :(Vain TerraGenesis) Määritä mäkien tiheys: Tasaisessa maastossa mäet ovat laajempia ja niitä on vähemmän. Epätasaisessa maastossa on enemmän mäkiä, mikä voi saada maaston näyttämään itseään toistavalta +STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_HELPTEXT :Määritä mäkien muoto ja tiheys. Tasaisessa maastossa mäkiä on vähemmän ja ne ovat laajempia, kun taas epätasaisessa maastossa on useampia pienempiä mäkiä. ###length 4 STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_VERY_SMOOTH :Erittäin tasainen STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_SMOOTH :Tasainen @@ -1515,7 +1519,7 @@ STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_ROUGH :Epätasainen STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_VERY_ROUGH :Erittäin epätasainen STR_CONFIG_SETTING_VARIETY :Maaston vaihtelu: {STRING} -STR_CONFIG_SETTING_VARIETY_HELPTEXT :(Vain TerraGenesis) Valitse, onko kartalla sekä vuoristoisia että tasaisia alueita. Koska tämä asetus tekee maastosta tasaisempaa, muut asetukset tulisi määrittää vuoristoisiksi +STR_CONFIG_SETTING_VARIETY_HELPTEXT :Valitse, onko kartalla sekä vuoristoisia että tasaisia alueita. Mitä suurempi on vaihtelu, sitä suurempia ovat korkeuserot vuoristoisten ja tasaisten alueiden välillä. STR_CONFIG_SETTING_RIVER_AMOUNT :Jokien määrä: {STRING} STR_CONFIG_SETTING_RIVER_AMOUNT_HELPTEXT :Valitse, kuinka paljon jokia luodaan @@ -1535,6 +1539,7 @@ STR_CONFIG_SETTING_ROAD_SIDE_LEFT :Vasemmanpuoline STR_CONFIG_SETTING_ROAD_SIDE_RIGHT :Oikeanpuolinen liikenne STR_CONFIG_SETTING_HEIGHTMAP_ROTATION :Korkeuskartan pyöritys:{STRING} +STR_CONFIG_SETTING_HEIGHTMAP_ROTATION_TOOLTIP :Valitse, mihin suuntaan korkeuskartan kuvaa kierretään pelimaailmaan sopiakseen ###length 2 STR_CONFIG_SETTING_HEIGHTMAP_ROTATION_COUNTER_CLOCKWISE :Vastapäivään STR_CONFIG_SETTING_HEIGHTMAP_ROTATION_CLOCKWISE :Myötäpäivään @@ -1655,7 +1660,12 @@ STR_CONFIG_SETTING_ADVANCED_VEHICLE_LISTS_HELPTEXT :Salli kehittyne STR_CONFIG_SETTING_LOADING_INDICATORS :Lastausilmaisimet: {STRING} STR_CONFIG_SETTING_LOADING_INDICATORS_HELPTEXT :Määritä näytetäänkö lastausilmaisimet kulkuneuvojen yläpuolella lastatessa ja purettaessa rahtia +STR_CONFIG_SETTING_TIMETABLE_MODE :Aikataulujen aikayksikkö: {STRING} +STR_CONFIG_SETTING_TIMETABLE_MODE_HELPTEXT :Valitse kulkuneuvojen aikatauluissa käytettävä aikayksikkö ###length 3 +STR_CONFIG_SETTING_TIMETABLE_MODE_DAYS :Vuorokaudet +STR_CONFIG_SETTING_TIMETABLE_MODE_SECONDS :Sekunnit +STR_CONFIG_SETTING_TIMETABLE_MODE_TICKS :Räpäykset STR_CONFIG_SETTING_TIMETABLE_SHOW_ARRIVAL_DEPARTURE :Näytä saapuminen ja lähtö aikatauluissa: {STRING} STR_CONFIG_SETTING_TIMETABLE_SHOW_ARRIVAL_DEPARTURE_HELPTEXT :Näytä odotetut saapumis- ja lähtemisajat aikatauluissa @@ -2344,7 +2354,7 @@ STR_NETWORK_START_SERVER_NEW_GAME_NAME_TOOLTIP :{BLACK}Nimi nä STR_NETWORK_START_SERVER_SET_PASSWORD :{BLACK}Aseta salasana STR_NETWORK_START_SERVER_PASSWORD_TOOLTIP :{BLACK}Jos peliin ei halua ulkopuolisia, voi sen suojata salasanalla -STR_NETWORK_START_SERVER_VISIBILITY_LABEL :{BLACK}Näkyvyys +STR_NETWORK_START_SERVER_VISIBILITY_LABEL :{BLACK}Näkyvyys: STR_NETWORK_START_SERVER_VISIBILITY_TOOLTIP :{BLACK}Näkyykö palvelimesi muille julkisessa listauksessa STR_NETWORK_START_SERVER_CLIENTS_SELECT :{BLACK}{NUM} asiakas{P "" ta} STR_NETWORK_START_SERVER_NUMBER_OF_CLIENTS :{BLACK}Pelaajien enimmäismäärä: @@ -3199,11 +3209,15 @@ STR_MAPGEN_MAPSIZE :{BLACK}Kartan k STR_MAPGEN_MAPSIZE_TOOLTIP :{BLACK}Valitse kartan koko ruutuina. Saatavilla olevien ruutujen määrä on hieman alhaisempi STR_MAPGEN_BY :{BLACK}× STR_MAPGEN_NUMBER_OF_TOWNS :{BLACK}Kuntien määrä: +STR_MAPGEN_NUMBER_OF_TOWNS_TOOLTIP :{BLACK}Valitse kuntien tiheys tai valinnainen määrä STR_MAPGEN_TOWN_NAME_LABEL :{BLACK}Kuntien nimet: STR_MAPGEN_TOWN_NAME_DROPDOWN_TOOLTIP :{BLACK}Valitse kuntien nimien tyyli STR_MAPGEN_DATE :{BLACK}Päivämäärä: +STR_MAPGEN_DATE_TOOLTIP :{BLACK}Valitse aloituspäivä STR_MAPGEN_NUMBER_OF_INDUSTRIES :{BLACK}Teollisuuden määrä: +STR_MAPGEN_NUMBER_OF_INDUSTRIES_TOOLTIP :{BLACK}Valitse teollisuuden tiheys tai valinnainen määrä STR_MAPGEN_HEIGHTMAP_HEIGHT :{BLACK}Korkein huippu: +STR_MAPGEN_HEIGHTMAP_HEIGHT_TOOLTIP :{BLACK}Valitse korkein huippu, jonka peli pyrkii luomaan, mitattuna korkeutena merenpinnasta STR_MAPGEN_HEIGHTMAP_HEIGHT_UP :{BLACK}Korota kartan korkeimman huipun maksimikorkeutta yhdellä STR_MAPGEN_HEIGHTMAP_HEIGHT_DOWN :{BLACK}Madalla kartan korkeimman huipun maksimikorkeutta yhdellä STR_MAPGEN_SNOW_COVERAGE :{BLACK}Lumen peitto: @@ -3216,10 +3230,12 @@ STR_MAPGEN_DESERT_COVERAGE_DOWN :{BLACK}Vähenn STR_MAPGEN_DESERT_COVERAGE_TEXT :{BLACK}{NUM}{NBSP}% STR_MAPGEN_TERRAIN_TYPE :{BLACK}Maaston tyyppi: STR_MAPGEN_SEA_LEVEL :{BLACK}Merenpinta: +STR_MAPGEN_SEA_LEVEL_TOOLTIP :{BLACK}Valitse merenpinnan taso STR_MAPGEN_QUANTITY_OF_RIVERS :{BLACK}Joet: STR_MAPGEN_SMOOTHNESS :{BLACK}Tasaisuus: STR_MAPGEN_VARIETY :{BLACK}Vaihtelu: STR_MAPGEN_GENERATE :{WHITE}Generoi +STR_MAPGEN_GENERATE_TOOLTIP :{BLACK}Luo maailma ja pelaa OpenTTD:tä! STR_MAPGEN_NEWGRF_SETTINGS :{BLACK}NewGRF-asetukset STR_MAPGEN_NEWGRF_SETTINGS_TOOLTIP :{BLACK}Näytä NewGRF-asetukset STR_MAPGEN_AI_SETTINGS :{BLACK}Tekoälyasetukset @@ -3252,6 +3268,7 @@ STR_MAPGEN_TOWN_NAME_CATALAN :Katalonialainen # Strings for map borders at game generation STR_MAPGEN_BORDER_TYPE :{BLACK}Kartan reunat: +STR_MAPGEN_BORDER_TYPE_TOOLTIP :{BLACK}Valitse pelimaailman reunukset STR_MAPGEN_NORTHWEST :{BLACK}Luode STR_MAPGEN_NORTHEAST :{BLACK}Koillinen STR_MAPGEN_SOUTHEAST :{BLACK}Kaakko @@ -3264,7 +3281,9 @@ STR_MAPGEN_BORDER_MANUAL :{BLACK}Manuaali STR_MAPGEN_HEIGHTMAP_ROTATION :{BLACK}Korkeuskartan kierto: STR_MAPGEN_HEIGHTMAP_NAME :{BLACK}Korkeuskartan nimi: +STR_MAPGEN_HEIGHTMAP_NAME_TOOLTIP :{BLACK}Korkeuskartan kuvatiedoston nimi STR_MAPGEN_HEIGHTMAP_SIZE_LABEL :{BLACK}Koko: +STR_MAPGEN_HEIGHTMAP_SIZE_LABEL_TOOLTIP :{BLACK}Korkeuskartan lähdekuvan koko. Paras tulos tulee, kun kuvan mitat vastaavat OpenTTD:n karttojen reunamittoja, kuten 256, 512, 1024, jne. STR_MAPGEN_HEIGHTMAP_SIZE :{ORANGE}{NUM}×{NUM} STR_MAPGEN_TERRAIN_TYPE_QUERY_CAPT :{WHITE}Huipun tavoitekorkeus @@ -3279,6 +3298,7 @@ STR_SE_MAPGEN_FLAT_WORLD :{WHITE}Tasainen STR_SE_MAPGEN_FLAT_WORLD_TOOLTIP :{BLACK}Luo tasainen maa STR_SE_MAPGEN_RANDOM_LAND :{WHITE}Satunnainen maa STR_SE_MAPGEN_FLAT_WORLD_HEIGHT :{BLACK}Tasaisen maan korkeus: +STR_SE_MAPGEN_FLAT_WORLD_HEIGHT_TOOLTIP :{BLACK}Valitse merenpinnan yläpuolisen maan korkeus STR_SE_MAPGEN_FLAT_WORLD_HEIGHT_DOWN :{BLACK}Siirrä tasaista maata yksi alaspäin STR_SE_MAPGEN_FLAT_WORLD_HEIGHT_UP :{BLACK}Siirrä tasaista maata yksi ylöspäin @@ -4572,8 +4592,13 @@ STR_TIMETABLE_STATUS_ON_TIME :{BLACK}Kulkuneu STR_TIMETABLE_STATUS_LATE :{BLACK}Kulkuneuvo on {STRING} myöhässä STR_TIMETABLE_STATUS_EARLY :{BLACK}Kulkuneuvo on {STRING} etuajassa STR_TIMETABLE_STATUS_NOT_STARTED :{BLACK}Tämä aikataulu ei ole vielä alkanut +STR_TIMETABLE_STATUS_START_AT_DATE :{BLACK}Tämä aikataulu alkaa {STRING} +STR_TIMETABLE_STATUS_START_IN_SECONDS :{BLACK}Tämä aikataulu alkaa {COMMA} sekunnin päästä +STR_TIMETABLE_START :{BLACK}Käynnistä aikataulu +STR_TIMETABLE_START_TOOLTIP :{BLACK}Valitse tämän aikataulun alkamisajankohta. Ctrl+napsautus jakaa tasaisesti kaikkien tätä käskyä jakavien kulkuneuvojen lähtöajat niiden keskinäisen järjestyksen mukaan, mikäli käsky on kokonaan aikataulutettu +STR_TIMETABLE_START_SECONDS_QUERY :Sekunteja aikataulun alkamiseen STR_TIMETABLE_CHANGE_TIME :{BLACK}Muuta aikaa STR_TIMETABLE_WAIT_TIME_TOOLTIP :{BLACK}Muuta aikaa, jonka valitun käskyn tulisi kestää. Ctrl+napsautus asettaa keston kaikille käskyille @@ -4597,6 +4622,10 @@ STR_TIMETABLE_EXPECTED :{BLACK}Odotettu STR_TIMETABLE_SCHEDULED :{BLACK}Aikataulu STR_TIMETABLE_EXPECTED_TOOLTIP :{BLACK}Vaihda odotetun ja aikataulun välillä +STR_TIMETABLE_ARRIVAL_DATE :T: {COLOUR}{DATE_TINY} +STR_TIMETABLE_DEPARTURE_DATE :L: {COLOUR}{DATE_TINY} +STR_TIMETABLE_ARRIVAL_SECONDS_IN_FUTURE :T: {COLOUR}{COMMA} s +STR_TIMETABLE_DEPARTURE_SECONDS_IN_FUTURE :L: {COLOUR}{COMMA} s # Date window (for timetable) diff --git a/src/lang/romanian.txt b/src/lang/romanian.txt index c3cd99252c..0c99dab235 100644 --- a/src/lang/romanian.txt +++ b/src/lang/romanian.txt @@ -719,6 +719,7 @@ STR_PLAYLIST_TOOLTIP_CLICK_TO_ADD_TRACK :{BLACK}Click pe STR_PLAYLIST_TOOLTIP_CLICK_TO_REMOVE_TRACK :{BLACK}Apasă pe melodie pentru a o elimina din programul actual (doar Custom1 sau Custom2) # Highscore window +STR_HIGHSCORE_TOP_COMPANIES :{BIG_FONT}{BLACK}Companii de top STR_HIGHSCORE_POSITION :{BIG_FONT}{BLACK}{COMMA}. STR_HIGHSCORE_PERFORMANCE_TITLE_BUSINESSMAN :Om de afaceri STR_HIGHSCORE_PERFORMANCE_TITLE_ENTREPRENEUR :Întreprinzător @@ -1533,6 +1534,7 @@ STR_CONFIG_SETTING_ROAD_SIDE_LEFT :Pe partea stân STR_CONFIG_SETTING_ROAD_SIDE_RIGHT :Pe partea dreaptă STR_CONFIG_SETTING_HEIGHTMAP_ROTATION :Rotaţie hartă înălţimi: {STRING} +STR_CONFIG_SETTING_HEIGHTMAP_ROTATION_TOOLTIP :Alegeți modul în care imaginea hărții de înălțime este rotită pentru a se potrivi în lumea jocului ###length 2 STR_CONFIG_SETTING_HEIGHTMAP_ROTATION_COUNTER_CLOCKWISE :Spre stânga STR_CONFIG_SETTING_HEIGHTMAP_ROTATION_CLOCKWISE :Spre dreapta @@ -1653,7 +1655,11 @@ STR_CONFIG_SETTING_ADVANCED_VEHICLE_LISTS_HELPTEXT :Activează folo STR_CONFIG_SETTING_LOADING_INDICATORS :Foloseşte indicatorii de încărcare: {STRING} STR_CONFIG_SETTING_LOADING_INDICATORS_HELPTEXT :Alege dacă indicatori de încărcare sunt afișați deasupra unor vehicule care sunt în proces de încărcare sau descărcare +STR_CONFIG_SETTING_TIMETABLE_MODE :Unități de timp pentru orare: {STRING} +STR_CONFIG_SETTING_TIMETABLE_MODE_HELPTEXT :Selectați unitățile de timp utilizate pentru orarele vehiculelor ###length 3 +STR_CONFIG_SETTING_TIMETABLE_MODE_DAYS :Zile +STR_CONFIG_SETTING_TIMETABLE_MODE_SECONDS :Secunde STR_CONFIG_SETTING_TIMETABLE_SHOW_ARRIVAL_DEPARTURE :Afișează plecările și sosirile din orare: {STRING} STR_CONFIG_SETTING_TIMETABLE_SHOW_ARRIVAL_DEPARTURE_HELPTEXT :Arată timpii estimați de plecare și sosire din orar @@ -3197,11 +3203,15 @@ STR_MAPGEN_MAPSIZE :{BLACK}Mărime STR_MAPGEN_MAPSIZE_TOOLTIP :{BLACK}Alege mărimea hărții folosind ca unitate de măsură suprafețele. Numărul de suprafețe disponibile va fi puțin mai mic decât această valoare STR_MAPGEN_BY :{BLACK}* STR_MAPGEN_NUMBER_OF_TOWNS :{BLACK}Nr. de oraşe: +STR_MAPGEN_NUMBER_OF_TOWNS_TOOLTIP :{BLACK}Selectați densitatea orașelor sau un număr personalizat STR_MAPGEN_TOWN_NAME_LABEL :{BLACK}Numele orașelor: STR_MAPGEN_TOWN_NAME_DROPDOWN_TOOLTIP :{BLACK}Alege naţionalitatea numelor oraşelor STR_MAPGEN_DATE :{BLACK}Data: +STR_MAPGEN_DATE_TOOLTIP :{BLACK}Selectați data de începere STR_MAPGEN_NUMBER_OF_INDUSTRIES :{BLACK}Nr. de industrii: +STR_MAPGEN_NUMBER_OF_INDUSTRIES_TOOLTIP :{BLACK}Selectați densitatea industriilor sau un număr personalizat STR_MAPGEN_HEIGHTMAP_HEIGHT :{BLACK}Cel mai înalt vârf: +STR_MAPGEN_HEIGHTMAP_HEIGHT_TOOLTIP :{BLACK}Alegeți cel mai înalt vârf pe care jocul va încerca să îl creeze, măsurat în altitudine deasupra nivelului mării STR_MAPGEN_HEIGHTMAP_HEIGHT_UP :{BLACK}Crește cu o unitate înălțimea maximă a celui mai înalt vârf al hărții STR_MAPGEN_HEIGHTMAP_HEIGHT_DOWN :{BLACK}Redu cu o unitate înălțimea maximă a celui mai înalt vârf al hărții STR_MAPGEN_SNOW_COVERAGE :{BLACK}Acoperire cu zăpadă: @@ -3214,10 +3224,12 @@ STR_MAPGEN_DESERT_COVERAGE_DOWN :{BLACK}Reduce STR_MAPGEN_DESERT_COVERAGE_TEXT :{BLACK}{NUM}% STR_MAPGEN_TERRAIN_TYPE :{BLACK}Tip teren: STR_MAPGEN_SEA_LEVEL :{BLACK}Nivelul mării: +STR_MAPGEN_SEA_LEVEL_TOOLTIP :{BLACK}Selectați nivelul mării STR_MAPGEN_QUANTITY_OF_RIVERS :{BLACK}Râuri: STR_MAPGEN_SMOOTHNESS :{BLACK}Netezime: STR_MAPGEN_VARIETY :{BLACK}Distribuţia varietăţii: STR_MAPGEN_GENERATE :{WHITE}Generează +STR_MAPGEN_GENERATE_TOOLTIP :{BLACK}Creează lumea și joacă OpenTTD! STR_MAPGEN_NEWGRF_SETTINGS :{BLACK}Setări NewGRF STR_MAPGEN_NEWGRF_SETTINGS_TOOLTIP :{BLACK}Afişează setările NewGRF STR_MAPGEN_AI_SETTINGS :{BLACK}Configurație AI @@ -3250,6 +3262,7 @@ STR_MAPGEN_TOWN_NAME_CATALAN :Catalană # Strings for map borders at game generation STR_MAPGEN_BORDER_TYPE :{BLACK}Margine: +STR_MAPGEN_BORDER_TYPE_TOOLTIP :{BLACK}Alegeți granițele lumii jocului STR_MAPGEN_NORTHWEST :{BLACK}Nord-vest STR_MAPGEN_NORTHEAST :{BLACK}Nord-est STR_MAPGEN_SOUTHEAST :{BLACK}Sud-est @@ -3262,7 +3275,9 @@ STR_MAPGEN_BORDER_MANUAL :{BLACK}Manual STR_MAPGEN_HEIGHTMAP_ROTATION :{BLACK}Rotaţie hartă înălţimi: STR_MAPGEN_HEIGHTMAP_NAME :{BLACK}Nume hartă înălţimi: +STR_MAPGEN_HEIGHTMAP_NAME_TOOLTIP :{BLACK}Numele fișierului al hărții de înălțime STR_MAPGEN_HEIGHTMAP_SIZE_LABEL :{BLACK}Dimensiune: +STR_MAPGEN_HEIGHTMAP_SIZE_LABEL_TOOLTIP :{BLACK}Dimensiunea imaginii hărții de înălțime. Pentru cele mai bune rezultate, fiecare margine ar trebui să se potrivească cu o lungime disponibilă a marginii hărții în OpenTTD, cum ar fi 256, 512, 1024 etc. STR_MAPGEN_HEIGHTMAP_SIZE :{ORANGE}{NUM} x {NUM} STR_MAPGEN_TERRAIN_TYPE_QUERY_CAPT :{WHITE}Înălțimea maximă dorită @@ -3277,6 +3292,7 @@ STR_SE_MAPGEN_FLAT_WORLD :{WHITE}Teren pl STR_SE_MAPGEN_FLAT_WORLD_TOOLTIP :{BLACK}Generează un teren plat STR_SE_MAPGEN_RANDOM_LAND :{WHITE}Teren aleator STR_SE_MAPGEN_FLAT_WORLD_HEIGHT :{BLACK}Înălţimea terenului plat: +STR_SE_MAPGEN_FLAT_WORLD_HEIGHT_TOOLTIP :{BLACK}Alegeți înălțimea terenului deasupra nivelului mării STR_SE_MAPGEN_FLAT_WORLD_HEIGHT_DOWN :{BLACK}Mută înălţimea terenului plat cu o unitate în jos STR_SE_MAPGEN_FLAT_WORLD_HEIGHT_UP :{BLACK}Mută înălţimea terenului plat cu o unitate în sus @@ -4570,8 +4586,13 @@ STR_TIMETABLE_STATUS_ON_TIME :{BLACK}Acest ve STR_TIMETABLE_STATUS_LATE :{BLACK}Vehiculul are întârziere de {STRING} STR_TIMETABLE_STATUS_EARLY :{BLACK}Momentan, acest vehicul și-a devansat programul {STRING} STR_TIMETABLE_STATUS_NOT_STARTED :{BLACK}Acest orar nu a început încă +STR_TIMETABLE_STATUS_START_AT_DATE :{BLACK}Acest orar va începe la {STRING} +STR_TIMETABLE_STATUS_START_IN_SECONDS :{BLACK}Acest orar va începe în {COMMA} secunde +STR_TIMETABLE_START :{BLACK}Începe orarul +STR_TIMETABLE_START_TOOLTIP :{BLACK}Selectați când începe acest orar. Ctrl+Click distribuie uniform pornirea tuturor vehiculelor care partajează această comandă pe baza ordinii lor relative, dacă comanda este complet programată +STR_TIMETABLE_START_SECONDS_QUERY :Secunde până la începerea orarului STR_TIMETABLE_CHANGE_TIME :{BLACK}Modifică timpul STR_TIMETABLE_WAIT_TIME_TOOLTIP :{BLACK}Modificați timpul pe care ar trebui să o dureze comanda evidențiată. Ctrl+Click setează ora pentru toate comenzile @@ -4595,6 +4616,10 @@ STR_TIMETABLE_EXPECTED :{BLACK}Estimat STR_TIMETABLE_SCHEDULED :{BLACK}Planificat STR_TIMETABLE_EXPECTED_TOOLTIP :{BLACK}Comută între estimare şi orar +STR_TIMETABLE_ARRIVAL_DATE :S: {COLOUR}{DATE_TINY} +STR_TIMETABLE_DEPARTURE_DATE :P: {COLOUR}{DATE_TINY} +STR_TIMETABLE_ARRIVAL_SECONDS_IN_FUTURE :S: {COLOUR}{COMMA} sec +STR_TIMETABLE_DEPARTURE_SECONDS_IN_FUTURE :P: {COLOUR}{COMMA} sec # Date window (for timetable) @@ -4698,8 +4723,11 @@ STR_TEXTFILE_NAVFORWARD_TOOLTIP :{BLACK}Reveniț STR_TEXTFILE_WRAP_TEXT :{WHITE}Încadrează textul STR_TEXTFILE_WRAP_TEXT_TOOLTIP :{BLACK}Încadrează textul ferestrei ca să fie vizibil integral, fără derulare STR_TEXTFILE_VIEW_README :{BLACK}Vezi fișierul readme +STR_TEXTFILE_VIEW_README_TOOLTIP :Vizualizați "citiți-mă / readme" pentru acest conținut STR_TEXTFILE_VIEW_CHANGELOG :{BLACK}Listă modificări +STR_TEXTFILE_VIEW_CHANGELOG_TOOLTIP :Vizualizați jurnalul de modificări pentru acest conținut STR_TEXTFILE_VIEW_LICENCE :{BLACK}Licenţă +STR_TEXTFILE_VIEW_LICENCE_TOOLTIP :Vedeți licența pentru acest conținut ###length 5 STR_TEXTFILE_README_CAPTION :{WHITE}{STRING}, fișier readme al {STRING} STR_TEXTFILE_CHANGELOG_CAPTION :{WHITE}{STRING}, lista de modificări a {STRING} diff --git a/src/lang/russian.txt b/src/lang/russian.txt index 177ac17012..05305c66c0 100644 --- a/src/lang/russian.txt +++ b/src/lang/russian.txt @@ -1259,8 +1259,8 @@ STR_NUM_VERY_LOW :Очень ма STR_NUM_LOW :Малое STR_NUM_NORMAL :Среднее STR_NUM_HIGH :Большое -STR_NUM_CUSTOM :Указанное -STR_NUM_CUSTOM_NUMBER :Заданный ({NUM}) +STR_NUM_CUSTOM :Указанное... +STR_NUM_CUSTOM_NUMBER :Указанное: {NUM} STR_VARIETY_NONE :Нет STR_VARIETY_VERY_LOW :Очень низкое @@ -1285,8 +1285,8 @@ STR_SEA_LEVEL_MEDIUM :Среднее STR_SEA_LEVEL_MEDIUM.p :Средние STR_SEA_LEVEL_HIGH :Большое STR_SEA_LEVEL_HIGH.p :Высокие -STR_SEA_LEVEL_CUSTOM :Заданный -STR_SEA_LEVEL_CUSTOM_PERCENTAGE :Заданный ({NUM}%) +STR_SEA_LEVEL_CUSTOM :Заданное... +STR_SEA_LEVEL_CUSTOM_PERCENTAGE :Заданное: {NUM}% ###length 4 STR_RIVERS_NONE :Нет @@ -1317,8 +1317,8 @@ STR_TERRAIN_TYPE_FLAT :Равнинн STR_TERRAIN_TYPE_HILLY :Холмистый STR_TERRAIN_TYPE_MOUNTAINOUS :Преимущественно горный STR_TERRAIN_TYPE_ALPINIST :Исключительно горный -STR_TERRAIN_TYPE_CUSTOM :Установить высоту вручную -STR_TERRAIN_TYPE_CUSTOM_VALUE :Установленная высота ({NUM}) +STR_TERRAIN_TYPE_CUSTOM :Указанная высота... +STR_TERRAIN_TYPE_CUSTOM_VALUE :Указанная высота: {NUM} ###length 4 STR_CITY_APPROVAL_LENIENT :снисходительное @@ -2281,10 +2281,10 @@ STR_INTRO_TOOLTIP_PLAY_SCENARIO :{BLACK}Нача STR_INTRO_TOOLTIP_SCENARIO_EDITOR :{BLACK}Создать собственный сценарий STR_INTRO_TOOLTIP_MULTIPLAYER :{BLACK}Начать сетевую игру -STR_INTRO_TOOLTIP_TEMPERATE :{BLACK}Выбрать умеренный климат -STR_INTRO_TOOLTIP_SUB_ARCTIC_LANDSCAPE :{BLACK}Выбрать субарктический климат -STR_INTRO_TOOLTIP_SUB_TROPICAL_LANDSCAPE :{BLACK}Выбрать субтропический климат -STR_INTRO_TOOLTIP_TOYLAND_LANDSCAPE :{BLACK}Выбрать игрушечный мир +STR_INTRO_TOOLTIP_TEMPERATE :{BLACK}Умеренный климат +STR_INTRO_TOOLTIP_SUB_ARCTIC_LANDSCAPE :{BLACK}Субарктический климат +STR_INTRO_TOOLTIP_SUB_TROPICAL_LANDSCAPE :{BLACK}Субтропический климат +STR_INTRO_TOOLTIP_TOYLAND_LANDSCAPE :{BLACK}Детский мир STR_INTRO_TOOLTIP_GAME_OPTIONS :{BLACK}Изменить основные настройки игры STR_INTRO_TOOLTIP_HIGHSCORE :{BLACK}Показать таблицу рекордов @@ -3404,8 +3404,8 @@ STR_MAPGEN_DESERT_COVERAGE_UP :{BLACK}Увел STR_MAPGEN_DESERT_COVERAGE_DOWN :{BLACK}Уменьшить площадь песчаного покрытия на 10% STR_MAPGEN_DESERT_COVERAGE_TEXT :{BLACK}{NUM}% STR_MAPGEN_TERRAIN_TYPE :{BLACK}Тип ландшафта: -STR_MAPGEN_SEA_LEVEL :{BLACK}Количество морей и озёр: -STR_MAPGEN_SEA_LEVEL_TOOLTIP :{BLACK}Выберите значение уровня моря +STR_MAPGEN_SEA_LEVEL :{BLACK}Количество водоёмов: +STR_MAPGEN_SEA_LEVEL_TOOLTIP :{BLACK}Выберите количество морей и озёр на карте STR_MAPGEN_QUANTITY_OF_RIVERS :{BLACK}Количество рек: STR_MAPGEN_SMOOTHNESS :{BLACK}Грубость ландшафта: STR_MAPGEN_VARIETY :{BLACK}Разнообразие ландшафта: @@ -4799,7 +4799,7 @@ STR_TIMETABLE_CHANGE_SPEED_TOOLTIP :{BLACK}Изме STR_TIMETABLE_CLEAR_SPEED :{BLACK}Сбросить огранич. скорости STR_TIMETABLE_CLEAR_SPEED_TOOLTIP :{BLACK}Сбросить ограничение скорости движения для выделенного задания. Ctrl+щелчок - сбросить время для всех заданий. -STR_TIMETABLE_RESET_LATENESS :{BLACK}Сбросить счетчик опозд. +STR_TIMETABLE_RESET_LATENESS :{BLACK}Сбросить счётчик опозд. STR_TIMETABLE_RESET_LATENESS_TOOLTIP :{BLACK}Сбросить счётчик опоздания, чтобы ТС считалось идущим по графику. Ctrl+щелчок сбросит счётчики у всей группы, так что последнее ТС будет идти по графику, а остальные - раньше графика. STR_TIMETABLE_AUTOFILL :{BLACK}Авторасчёт diff --git a/src/lang/simplified_chinese.txt b/src/lang/simplified_chinese.txt index 6ab2b8c4c6..4768d82107 100644 --- a/src/lang/simplified_chinese.txt +++ b/src/lang/simplified_chinese.txt @@ -255,6 +255,9 @@ STR_UNITS_HEIGHT_IMPERIAL :{DECIMAL}{NBSP} STR_UNITS_HEIGHT_METRIC :{DECIMAL}{NBSP}米 STR_UNITS_HEIGHT_SI :{DECIMAL}{NBSP}米 +STR_UNITS_DAYS :{COMMA}{NBSP} 日 +STR_UNITS_SECONDS :{COMMA}{NBSP} 秒 +STR_UNITS_TICKS :{COMMA}{NBSP} 刻 # Common window strings STR_LIST_FILTER_TITLE :{BLACK}关键字词: @@ -719,6 +722,7 @@ STR_PLAYLIST_TOOLTIP_CLICK_TO_ADD_TRACK :{BLACK}点击 STR_PLAYLIST_TOOLTIP_CLICK_TO_REMOVE_TRACK :{BLACK}点击音乐曲目以从当前播放列表中删除{}(仅限自定义1或自定义2) # Highscore window +STR_HIGHSCORE_TOP_COMPANIES :{BIG_FONT}{BLACK}顶级公司 STR_HIGHSCORE_POSITION :{BIG_FONT}{BLACK}{COMMA}. STR_HIGHSCORE_PERFORMANCE_TITLE_BUSINESSMAN :运输个体户 STR_HIGHSCORE_PERFORMANCE_TITLE_ENTREPRENEUR :运输代理商 @@ -1072,6 +1076,7 @@ STR_GAME_OPTIONS_BASE_MUSIC :{BLACK}基础 STR_GAME_OPTIONS_BASE_MUSIC_TOOLTIP :{BLACK}选择要使用的基础音乐组 STR_GAME_OPTIONS_BASE_MUSIC_DESCRIPTION_TOOLTIP :{BLACK}有关基础音乐组的附加信息 +STR_BASESET_STATUS :{STRING} {RED}(共有{NUM}份缺失或损坏的文件) STR_ERROR_RESOLUTION_LIST_FAILED :{WHITE}无法撷取可用的屏幕分辨率清单 STR_ERROR_FULLSCREEN_FAILED :{WHITE}无法切换到全屏模式{}尝试使用不同的分辨率 @@ -1486,7 +1491,7 @@ STR_CONFIG_SETTING_LAND_GENERATOR_ORIGINAL :原始算法 STR_CONFIG_SETTING_LAND_GENERATOR_TERRA_GENESIS :新算法 STR_CONFIG_SETTING_TERRAIN_TYPE :地貌类型: {STRING} -STR_CONFIG_SETTING_TERRAIN_TYPE_HELPTEXT :(仅限生成地图时) 多丘陵地形 +STR_CONFIG_SETTING_TERRAIN_TYPE_HELPTEXT :选择生成地图的起伏度 STR_CONFIG_SETTING_INDUSTRY_DENSITY :工业布局: {STRING} STR_CONFIG_SETTING_INDUSTRY_DENSITY_HELPTEXT :设置地图生成过程中,工业数量及一、二级工业比例。 @@ -1498,15 +1503,15 @@ STR_CONFIG_SETTING_SNOWLINE_HEIGHT :雪线高度: STR_CONFIG_SETTING_SNOWLINE_HEIGHT_HELPTEXT :控制在寒带气候中雪线高度。大雪会影响工业和城镇发展需求。只能在场景编辑器中更改或由“积雪覆盖率”计算得到。 STR_CONFIG_SETTING_SNOW_COVERAGE :积雪覆盖率:{STRING} -STR_CONFIG_SETTING_SNOW_COVERAGE_HELPTEXT :控制寒带气候中大致的雪量。雪会影响工业和城镇发展需求。只在地图生成时使用。海平面以上一格的土地永远没有积雪 +STR_CONFIG_SETTING_SNOW_COVERAGE_HELPTEXT :控制寒带气候中大致的雪量。雪会影响工业和城镇发展需求。只在地图生成时使用。海岸线上的土地永远没有积雪 STR_CONFIG_SETTING_SNOW_COVERAGE_VALUE :{NUM}% STR_CONFIG_SETTING_DESERT_COVERAGE :沙漠覆盖率:{STRING} -STR_CONFIG_SETTING_DESERT_COVERAGE_HELPTEXT :控制热带气候中大致的沙漠量。沙漠会影响工业生成。只在地图生成时使用 +STR_CONFIG_SETTING_DESERT_COVERAGE_HELPTEXT :控制热带气候中大致的沙漠量。沙漠会影响工业生成和城镇发展需求。只在地图生成时有效 STR_CONFIG_SETTING_DESERT_COVERAGE_VALUE :{NUM}% STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN :地面粗糙度 (仅限生成地图时):{STRING} -STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_HELPTEXT :(仅限新算法) 选择在地图上的山丘密度。光滑的地形会包含较少、相互之间较分散的山丘。粗糙的地形的山丘较密集,但可能会使地图显得重复 +STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_HELPTEXT :选择在地图上的山丘密度。光滑的地形会包含较少且相互之间较分散的山丘;粗糙的地形的山丘较密集,但可能会使地图显得重复 ###length 4 STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_VERY_SMOOTH :非常光滑 STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_SMOOTH :光滑 @@ -1514,7 +1519,7 @@ STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_ROUGH :粗糙 STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_VERY_ROUGH :非常粗糙 STR_CONFIG_SETTING_VARIETY :多样的分发: {STRING} -STR_CONFIG_SETTING_VARIETY_HELPTEXT :(仅限新算法) 此设置控制地图是否同时包含多山及平坦的地带。由于此设置只会使地图的一部份変得较平坦,请把其他相关设置(如 "地形特点")的值设为 "山地" +STR_CONFIG_SETTING_VARIETY_HELPTEXT :此设置控制地图是否同时包含多山及平坦的地带。由于此设置只会使地图的一部份変得较平坦,请把其他相关设置(如 "地形特点")的值设为 "山地" STR_CONFIG_SETTING_RIVER_AMOUNT :河流数量: {STRING} STR_CONFIG_SETTING_RIVER_AMOUNT_HELPTEXT :选择生成河流的数量 @@ -1534,6 +1539,7 @@ STR_CONFIG_SETTING_ROAD_SIDE_LEFT :左侧通行 STR_CONFIG_SETTING_ROAD_SIDE_RIGHT :右侧通行 STR_CONFIG_SETTING_HEIGHTMAP_ROTATION :高度图旋转:{STRING} +STR_CONFIG_SETTING_HEIGHTMAP_ROTATION_TOOLTIP :选择高度图旋转的方向以创建地图 ###length 2 STR_CONFIG_SETTING_HEIGHTMAP_ROTATION_COUNTER_CLOCKWISE :逆时针 STR_CONFIG_SETTING_HEIGHTMAP_ROTATION_CLOCKWISE :顺时针 @@ -1654,7 +1660,12 @@ STR_CONFIG_SETTING_ADVANCED_VEHICLE_LISTS_HELPTEXT :允许使用高 STR_CONFIG_SETTING_LOADING_INDICATORS :使用装货进度指示: {STRING} STR_CONFIG_SETTING_LOADING_INDICATORS_HELPTEXT :选择是否在车辆上方显示装卸货物进度 +STR_CONFIG_SETTING_TIMETABLE_MODE :时刻表使用的时间单位: {STRING} +STR_CONFIG_SETTING_TIMETABLE_MODE_HELPTEXT :选择载具时刻表所使用的时间单位 ###length 3 +STR_CONFIG_SETTING_TIMETABLE_MODE_DAYS :日 +STR_CONFIG_SETTING_TIMETABLE_MODE_SECONDS :秒 +STR_CONFIG_SETTING_TIMETABLE_MODE_TICKS :刻 STR_CONFIG_SETTING_TIMETABLE_SHOW_ARRIVAL_DEPARTURE :在时刻表中显示到达时间和出发时间: {STRING} STR_CONFIG_SETTING_TIMETABLE_SHOW_ARRIVAL_DEPARTURE_HELPTEXT :在时刻表中显示预期的到达和出发时间 @@ -1956,7 +1967,7 @@ STR_CONFIG_SETTING_CITY_SIZE_MULTIPLIER_HELPTEXT :游戏开局时 STR_CONFIG_SETTING_LINKGRAPH_RECALC_INTERVAL :每 {STRING} 更新货物分配 STR_CONFIG_SETTING_LINKGRAPH_RECALC_INTERVAL_HELPTEXT :两次连结图的重新计算间隔。每次重新计算会计算图中一个部分的计划。这意味着填入的值X不意味着整张图会每X秒更新一次,只有其中的一部分会被更新。此设定赋值越小,则更多的CPU时间会被用来重新计算。此设定赋值越大,则在线路改变时货物再分配所需时间会变长。 -STR_CONFIG_SETTING_LINKGRAPH_RECALC_TIME :花费 {STRING} 在货物分配的重新计算上 +STR_CONFIG_SETTING_LINKGRAPH_RECALC_TIME :在货物分配的重新计算上花费 {STRING} STR_CONFIG_SETTING_LINKGRAPH_RECALC_TIME_HELPTEXT :每一个连结图的重新计算时间。当一次重新计算开始,一个线程会被允许运行这个秒数。此设定赋值越小,则线程无法按时结束的可能性越大,从而导致游戏运行延迟。此设定赋值越大,则在线路改变时货物再分配所需时间会变长。 STR_CONFIG_SETTING_DISTRIBUTION_PAX :乗客分配方式:{STRING} @@ -3198,11 +3209,15 @@ STR_MAPGEN_MAPSIZE :{BLACK}地图 STR_MAPGEN_MAPSIZE_TOOLTIP :{BLACK}选择地图尺寸(单位:格)。可用的数值会略小。 STR_MAPGEN_BY :{BLACK}* STR_MAPGEN_NUMBER_OF_TOWNS :{BLACK}城镇数量: +STR_MAPGEN_NUMBER_OF_TOWNS_TOOLTIP :{BLACK}选择城镇密度,或者输入一个自定义数字 STR_MAPGEN_TOWN_NAME_LABEL :{BLACK}城镇名称: STR_MAPGEN_TOWN_NAME_DROPDOWN_TOOLTIP :{BLACK}选择城镇名称的命名风格 STR_MAPGEN_DATE :{BLACK}日期: +STR_MAPGEN_DATE_TOOLTIP :{BLACK}选择起始日期 STR_MAPGEN_NUMBER_OF_INDUSTRIES :{BLACK}工业数量: +STR_MAPGEN_NUMBER_OF_INDUSTRIES_TOOLTIP :{BLACK}选择工业密度,或者输入一个自定义数字 STR_MAPGEN_HEIGHTMAP_HEIGHT :{BLACK}最高峰: +STR_MAPGEN_HEIGHTMAP_HEIGHT_TOOLTIP :{BLACK}选择游戏地图中最高峰的海拔,以海平面为原点计。 STR_MAPGEN_HEIGHTMAP_HEIGHT_UP :{BLACK}提高最高峰的最大高度一格 STR_MAPGEN_HEIGHTMAP_HEIGHT_DOWN :{BLACK}降低最高峰的最大高度一格 STR_MAPGEN_SNOW_COVERAGE :{BLACK}积雪覆盖率: @@ -3215,10 +3230,12 @@ STR_MAPGEN_DESERT_COVERAGE_DOWN :{BLACK}减少 1 STR_MAPGEN_DESERT_COVERAGE_TEXT :{BLACK}{NUM}% STR_MAPGEN_TERRAIN_TYPE :{BLACK}地形特点: STR_MAPGEN_SEA_LEVEL :{BLACK}海洋面积: +STR_MAPGEN_SEA_LEVEL_TOOLTIP :{BLACK} 选择覆盖率 STR_MAPGEN_QUANTITY_OF_RIVERS :{BLACK}河流数量: STR_MAPGEN_SMOOTHNESS :{BLACK}平滑度: STR_MAPGEN_VARIETY :{BLACK}多样的分发: STR_MAPGEN_GENERATE :{WHITE}生成 +STR_MAPGEN_GENERATE_TOOLTIP :{BLACK} 创建世界并开始游玩OpenTTD! STR_MAPGEN_NEWGRF_SETTINGS :{BLACK}NewGRF设置 STR_MAPGEN_NEWGRF_SETTINGS_TOOLTIP :{BLACK}显示NewGRF设置 STR_MAPGEN_AI_SETTINGS :{BLACK}AI 设置 @@ -3251,6 +3268,7 @@ STR_MAPGEN_TOWN_NAME_CATALAN :加泰罗尼亚 # Strings for map borders at game generation STR_MAPGEN_BORDER_TYPE :{BLACK}地图边缘: +STR_MAPGEN_BORDER_TYPE_TOOLTIP :{BLACK}选择地图边界的样式 STR_MAPGEN_NORTHWEST :{BLACK}西北 STR_MAPGEN_NORTHEAST :{BLACK}东北 STR_MAPGEN_SOUTHEAST :{BLACK}东南 @@ -3263,7 +3281,9 @@ STR_MAPGEN_BORDER_MANUAL :{BLACK}手动 STR_MAPGEN_HEIGHTMAP_ROTATION :{BLACK}高度图旋转: STR_MAPGEN_HEIGHTMAP_NAME :{BLACK}高度图名称: +STR_MAPGEN_HEIGHTMAP_NAME_TOOLTIP :{BLACK}高度图图像文件的名字 STR_MAPGEN_HEIGHTMAP_SIZE_LABEL :{BLACK}地图尺寸: +STR_MAPGEN_HEIGHTMAP_SIZE_LABEL_TOOLTIP :{BLACK}高度图的长宽大小。建议选择长宽符合游戏地图大小的图片作为高度图,如256、512、1024等 STR_MAPGEN_HEIGHTMAP_SIZE :{ORANGE}{NUM} × {NUM} STR_MAPGEN_TERRAIN_TYPE_QUERY_CAPT :{WHITE}最高峰目标高度 @@ -3278,6 +3298,7 @@ STR_SE_MAPGEN_FLAT_WORLD :{WHITE}平坦 STR_SE_MAPGEN_FLAT_WORLD_TOOLTIP :{BLACK}生成平坦水面 STR_SE_MAPGEN_RANDOM_LAND :{WHITE}随机地面 STR_SE_MAPGEN_FLAT_WORLD_HEIGHT :{BLACK}地面高度: +STR_SE_MAPGEN_FLAT_WORLD_HEIGHT_TOOLTIP :{BLACK}选择地面海拔高度 STR_SE_MAPGEN_FLAT_WORLD_HEIGHT_DOWN :{BLACK}提升地面高度 STR_SE_MAPGEN_FLAT_WORLD_HEIGHT_UP :{BLACK}降低地面高度 @@ -3303,7 +3324,7 @@ STR_GENERATION_PREPARING_GAME :{BLACK}准备 # NewGRF settings STR_NEWGRF_SETTINGS_CAPTION :{WHITE}NewGRF 设置 STR_NEWGRF_SETTINGS_INFO_TITLE :{WHITE}NewGRF 详细信息 -STR_NEWGRF_SETTINGS_ACTIVE_LIST :{WHITE}激活 NewGRF +STR_NEWGRF_SETTINGS_ACTIVE_LIST :{WHITE}已激活 NewGRF STR_NEWGRF_SETTINGS_INACTIVE_LIST :{WHITE}停用 NewGRF STR_NEWGRF_SETTINGS_SELECT_PRESET :{ORANGE}选择预设 STR_NEWGRF_FILTER_TITLE :{ORANGE}关键字词搜索: @@ -4571,8 +4592,13 @@ STR_TIMETABLE_STATUS_ON_TIME :{BLACK}该车 STR_TIMETABLE_STATUS_LATE :{BLACK}该车辆目前晚点 {STRING} STR_TIMETABLE_STATUS_EARLY :{BLACK}该车辆目前提前 {STRING} STR_TIMETABLE_STATUS_NOT_STARTED :{BLACK}此时刻表尚未开始 +STR_TIMETABLE_STATUS_START_AT_DATE :{BLACK}本时刻表将在 {STRING} 开始 +STR_TIMETABLE_STATUS_START_IN_SECONDS :{BLACK}本时刻表将会在 {COMMA} 秒内开始 +STR_TIMETABLE_START :{BLACK}开始时刻表 +STR_TIMETABLE_START_TOOLTIP :{BLACK}选择此时刻表开始的时间。如果订单完全按时刻表安排,则按住Ctrl键并单击会根据它们的相对顺序,且均匀分配共享此订单的所有车辆的开始时间。 +STR_TIMETABLE_START_SECONDS_QUERY :直至时刻表开始的秒数 STR_TIMETABLE_CHANGE_TIME :{BLACK}改变时间 STR_TIMETABLE_WAIT_TIME_TOOLTIP :{BLACK}改变高亮选择的命令执行的时间,按住Ctrl单击可为所有命令设置时间 @@ -4596,6 +4622,10 @@ STR_TIMETABLE_EXPECTED :{BLACK}预期 STR_TIMETABLE_SCHEDULED :{BLACK}表定时间 STR_TIMETABLE_EXPECTED_TOOLTIP :{BLACK}切换显示(根据实际情况计算的)预期时间或表定时间 +STR_TIMETABLE_ARRIVAL_DATE :抵: {COLOUR}{DATE_TINY} +STR_TIMETABLE_DEPARTURE_DATE :发:{COLOUR}{DATE_TINY} +STR_TIMETABLE_ARRIVAL_SECONDS_IN_FUTURE :抵: {COLOUR}{COMMA} 秒 +STR_TIMETABLE_DEPARTURE_SECONDS_IN_FUTURE :发: {COLOUR}{COMMA} 秒 # Date window (for timetable) From 5cf9c46b29b3aa02dcb1aca0cd1bf48723c62b30 Mon Sep 17 00:00:00 2001 From: Richard Wheeler <2762690+zephyris@users.noreply.github.com> Date: Wed, 27 Dec 2023 22:44:21 +0000 Subject: [PATCH 19/19] Feature: Toyland-specific river graphics (#11523) Replaces the old solution of reusing temperate sprites for toyland. --- media/baseset/orig_extra.grf | Bin 420256 -> 445331 bytes media/baseset/orig_extra.grf.hash | 2 +- media/baseset/orig_extra/CMakeLists.txt | 3 + media/baseset/orig_extra/orig_extra.nfo | 1 + media/baseset/orig_extra/rivers/toyland.nfo | 2 +- media/baseset/orig_extra/rivers/toyland.png | Bin 16127 -> 34644 bytes .../orig_extra/rivers/toyland_rapids.nfo | 73 ++++++++++++++++++ .../orig_extra/rivers/toyland_rapids.png | Bin 0 -> 22458 bytes .../rivers/toyland_rapids_shading.png | Bin 0 -> 18865 bytes 9 files changed, 79 insertions(+), 2 deletions(-) create mode 100644 media/baseset/orig_extra/rivers/toyland_rapids.nfo create mode 100644 media/baseset/orig_extra/rivers/toyland_rapids.png create mode 100644 media/baseset/orig_extra/rivers/toyland_rapids_shading.png diff --git a/media/baseset/orig_extra.grf b/media/baseset/orig_extra.grf index 9adc6e04f8daf499c9a659472fde96a6cc9c0924..25193b8020b8ce02fcc300d300640ae128f180d8 100644 GIT binary patch delta 44771 zcmeFa2Xqt1+wkkzm4uBcCYat60>Ok%=*2c9kV;JonJ}X(qK>qiA-|wD#&Ue0hkB;zYSC(XHH1o{w z`OU-r+#V5PudZHRv*y3_L;JQp+s01u^72x^wW)(Dx~s15j2Gl~yM>>B`|0w}R`&m5 z`MT9B`+o#KK3@I7hW;zQ?f>1XbsvBG#p(_HpPRq>gO8Vgv9kZ$AFo>V>8dY=xE=*5 zks@M3zkv}8di9Lh(63(v2S1PY>(`}?{J4aYK%VDw-P6!-;LzqXqRW`rs=b;gCdyF+AXH3snX{_f}ulAf@<7s^2X?*Hwto1ZL^E5v9 zG}b{Q;?Hq$5#+cf=!J;)$Mt*WzwTF4Vh@e)-~7p+^gL3O{7AY9)`)WxddBJ}dOrDb z&-n^Zqter;@-(VFjXThYST?zr8r}=9h6kR*Hcz9*)3AFQ4o}1BY1Dceb)H7Or_tbP zGrvh zq>UATf!`&aUS8co0iit83Epbfq_B6GiS_@p0!*s zj+Dk3Gc3DEb&ajwI1kyW3)YuOr=!kzz;a3#NY0osLziMwTY@bMB?>tur7pvAof&RC zjA|@TOYf!zq8d|5_CzydRajp${%v`g`4r9s=#H4!4pB~43%55sRXU->_Gacp%bDS|U zIgUHVCB;rNEYXiIP0SkDGbSfp#_vlSAlcIl*>BkI=*5-Ul9Dj=LX80lTv?i76 znAJCYcnm|oLG_5~6LW_-z#P{MqaAF!V}B4DKkCcyUv#A?&~yl?gD5FUi-JvQXeP6a zeVx)X=P8Lk#9n2s^t`aL*n`LQgr)=i5j#KntHgReidJRaGbf@MIwkcb$8k%UuXnx7 zT;+Df^+fed0H@`L5Sn(ok_xVIn2C&bQ1$w%EPG--|2(JV(zw^SKbZdU{rQji!+d|z zu4$`|bTA($yvTAly3%mxFh|1M{8`~8?pq;Um=f>gDBgMEGNJM26Y*30Y~d;GT;>7o z2!D|9J064k;d%HqyodS=Uyt%7G%Ea+@Uw7-{|+12JM10i0lv@Y;TmBNjuia3&N!CP zD1;1VEAE4z#}#4`s=K{Yjiz%I5qF9t6qHh=z01sIk8!^U7x7kh54=1=Xu`SpF0R9a zcN>_UMgFKhOjUeeb5CbSjnryKS>iakyNQ2*b;44tF4CrJKj81-5BRqDMLq#1GV6FfY5Tp+ z?%vuzggXMm4&(a^-ROS8CV17=Ou*5e#J+ZT@$O0ZK>S(u82*R<6)Oa9;Yhxj_{opE z$d$lv)p7%wubCqDO(NW%s%AT-Tr8TSEfLzrUOO2}uswJk-XpBjt|xZ1?StoPYipoi zz9TLlKn_*gYN(ae2I_|+VQrmuo5SvKIBJ~KA5=VbKJj~GlO`)`>~NvBQx9k|wYH6; z#$kscMe>$r5H>sQO;4a_!8~g-PBS*bP|(IW0|qEK{2l#`Ys5%yK$3)I2F7I%V|@SWfozpG43?JoE6G!q;1Bd$YzSyH(9=w8Z8}> z)52KW8rz~8+B@`&HCES@24{>}*?uOa6iWYdaDyp|a60r}X-&vx@sgf0vZz6N$J*Vv zo1K(%#}s9mX4;b7WIS!%YHBhl%-5{D4F&Ax(h=4*mMs?b-J?y0R6{$%-^g~Pkk)1m zHJveUO8eZ@WNdHfT<)JyXx(cqIOAoyfBBiTrlijgG?l-O>XQp%!mQDx%~7w9y4<9! zk%#H*&(oT$a}7QPk$YdQ7<@UZe4?pIVRH@9XrUBbt}yI~Zptb=vL!LcVAHQ4+yk?E zre&LXCf!v2&XF^*C(R#~*IK8w49FETP+c-ZH(j1oelj%&*)o#}M~!^l=9Dxq)M(me3BF2JTopE4A8s9)99^*?I*@2+v}RgU z(`tq27&0fi;%4a@((atD4uJ9?pQ$SSE!ku4gN{KRUh300GN*LKn?kgx~(pNV0s(JA!p)bU4PA3-89_{-E7?=(#iKqT%;MH>96}< zLutZ~Y$d{agnp0}lbEIpMYW-OHCw4Ay4%%V4-qB(7B(i3oKV8j? z4!agJh<+-1QuNQ!gXp1D5WO^eDRH24*t<+-^aZ9^To+CHtC=^#R>$sVC$NWN^N%$# z^O!%vFR~@nN_t;zE^)*U!i921+%<;_-~!kW=uf%xtdWgn;_0-!8^rOBY#mz{QNVZP zPQWFPI~eCpy-Qy#x`Z0&S^N;LzNnEn)t=kHZD13GZu}161uB!B%Ra-8;a}rF7gh;# z)WU&;>qJaD!6bC&4)GiLWFZ-@BZOR`PRPdoI8^u*zl-11nu&N{9Em@{-uN^8lrUGA zf6*_!o8; ze~*aw=AB}P6178kf&K_j#*A>HXGYP;|BUxW9fD(5@m}^Ko|robDTNTcj9tyY1oz&o%{KQ!f#&`wi0+v@76qH9 zp_#%wOyFuYuEtKdR^toD2O)(p1mD2DnAqJV_=eCEIg+~Qdq(%m_APxwo*@OtU%v?UL&lj!2x5%z$o~66MrNnh&1pJ*B=ru&V7kx#TfMc5v-p42CF6<;GfcemM zp1jA9yY2mu?k=BW~<|h&d+6nK>5PCEJaIXn}iFE~Y3*N+Mab3ay zd?{)dv9AOBHdR0;B_C%NmDI%wOgv8EcHxEjp~TOAVgq|qsN{EQEzGxAOlwc}n~kSq zlkjWGt-?2PdDLkltgB!Y#<9sbNgQx0jNrRdz3^x%8^2VNNiaRRQNndRyQGo$u{YjJ zHI$f%ZGDB&b{I^Sh#}|5ZsN!l!41?JP}!a}lV9x_BS}CPmE6vya zOh@StSq@uPOE!I!Wu1<_3@sg!Wjlq<9yJ5PqPWsL=im0j6oj~=*(3Tm-r1r7ZwDn!O)VF<|eh{(&QUrrvx@SInHs`MMO29^aOuq?1Q zS|gP9y1LrNQaMp0)TzdL0bKZe$Lmo4UYhZ3LdE88XB0oFhVsak;5&spx)W6FOF)b*dku@BfAU;{Z)5K^QZ2H=0rv{YDYawkD$JzwucRi{zQ{NZ`aToF?zY8 zzgqL&kzd0H(z{6eagtdPzCLCGy)rO#ZF7S*V`x zlXy@k=_)n%vWm@D<SxR`DaQ*Fhl8pXW|;Y3wOM$(~Bs zNlBqnR%xQd-(;eYk4~v6)~Vqpw~V`dV-m#n!UN$mJcT{Qo?`mbS+M%Z67s`_QxYXX zq+ZS~Bb}PI*ygzTf#CXvocb_%rlgA@5uLzqlEj~C{%lUGiq~tEAo!m zUnnAVlyn8#LZfW>~SE!4wfbBa8$g6Y7_5iiczCZne>)0oF0w~ z5`wjf+8NjFuo&Ye2uBi_+d3HV-icgS5(q1dySmeSYDsnRbu}y@N?{T_%fHHe8TWDA z7o_8Ne>O~9TQWI|4%L@Due+f6RS$m*pU1w3kMa?*EBOG_z_ZY&PUKTfc{=?mB<6l-nm zh#h@#x%Q63)qC$Ile5(AU}$pKAlirM-btOO?$bopG#>}709+Biv|ZtZz@HvWkE35C zYib-u2eM1sQ4Iiummya9lHMpySK91A1*ET~Z6*breUUy&CmtPV{0;^>8w_(!%honE zb_nxrPCApeYc?BCTE^*`EYqz>`L@GWW4BA&kd0O{lgz^jN4+IV3b1I28mB2R2N5-} z7=QuN$*g5Qy&NSaz~W+qrA;y-><(!vQDe7UV@}2VrH|6DwY*^Z;vh27I+_aFFP`)# zd#l%&0uLhN0-fGih#agR@-hV+h>{wPAs8@q3o`WP&d9cBmep)sVH#kql>V~bJBC#9 zP`PBW0U7n?Fw2d-|ClP$qRPjlBeT{xjaUYwDEx_y<{3F*sGbToA2pH4X+@?7ImozK znwk-ugEGU)BO|Pqs#10IF{E(9n3@%6e2MUFpN@>BR^Ny`>+*_E!eQa#ntsYGG(_n!0ba)adg?K_<4r?2Q#2mtf}-(?dV76cm=~(6d?`;^@sFe|D-<>t*^)@Iu8sGB!1Aft zwUzxWefjH$-bf>}f|3HO{PeXI`8Nv$$KeZEgB7-#+FI#{%c;n>>`i@bK^b(^xi93t zR;84J4AYQrPM7No1dO+qd}ZE`8Y&w|XJZ@d8RT1h;p_q&gVXZAH5-lF6wXFp->R+Y zT`D8-9o%#zxb*kxG}KuA*u-`i8or!bPE`8!4F z=t8bW=|`BS-eITkZwW8+CxwsrlN=*F z%{W=_6B8g1g!q0H*CZ?w4sdsb*?bXSB;0n*I7#E{+;xnz*XpF?t{>>FkjkFTZK2` z4!AoTqm3u+@uctuH&3`FmT4#Bc>Fn@Ox07BR6Xs-^cO$vLH1H>%>}inZD|wog~^Oy zI-MS>8;{zrK_`;Hi^TxDn14aHH5P zOp`V7ZSWV^C|HCvh~A&2Rr1rpld8m@wAJ|6l1kLTT*IX}@Ax1!@`jK;l7ABi2pa_h z+_eksfY;GZxC=pYsZfE3iRu$qVc8-C<4|rR_XjsvdzER&^kN!WZ>AmhHU3E$!=#FD z3w5~u?;zyMOE?N26=Lw~>{ILjPQi89)t&3W9TkS~g?O4^=5tOJ!-@*-vWMF!sAEzt zp?a=6H<)kB`}2KqCp?iG%>9NXW(4O%r-WT4hfy70znjr5DY>Nk5ZWF2z5)__cX!c! zli~s0^SCP_y8NRF`*}?!%}`%SU7SG zTrxJMIMtLMLfu5+B3$<2C|LiUI`x3~y%YNbuEA_d4XTCr`4HX;?Y%{9VH#Qsm$CU{ zVWEl-P&dV`+VfNb9!LF&e*E3qzmI!=Zj@DEPD zaSK+)La9*C?+pE^WRf8zgJQWYkY=-zOb$&k@&F>ZxqVq z=)GT9II`El>^Bdt3a@TnfnKI2FUVzy_#D~2w+bdbn*&HTOgq#^)K}DwjLi_B*4TBy zgm{-DyF!TEg6KnKM4!}NwPdjkSQ)_bAKKK^)XDTr_Y%=iBlV!i(lflhyxjANlp?v< zJ>V<_2~(}5J#x75{ef{RchqgvAiGg5u}VN|HmAu?>I9Q#j^!Omq&sDA^szf@eAKS^ z+gKx=H%^fJ;q(MK4}hhumPLv4=okyIo{YdOjb)N6Tada9;61SW)OmEcOyNu;kRvNZ zr%~289;OSzfs|cBHsc4DU!*){II1!J0hlc*D^TR ziPVr2ha9ParpcxTCc`o=M>2GiiF|5Ec}E>&2_jowMuX`& z>x$BKd*iINWJ3*P1%N%(Rc!1iH+qBgIPZ}tFVG{gM8#D98+GC9`_{3zd20?`E?4p>&PVkodNxIZ2_YB z>qbyLbhF8t@Sceab#pW`bjzsMHLvSF(QOqwj92tgf2ny!Q>}4&*X-*mgA3O<8z!^= zVZi=hZN>h(p@z`R?4N=C>mm|=m512S6ZDS&k%0L}-#c0w_P1dY9QILj!ECBl)WC1E~jYMs3y#Rsw zokBD6N&bR9l<<3zzdZ2E>4{rdUY_7RIEMO*Ef?g>03V>1Qv<@w5$%gjFsa`=y*lA< z=CGV{aOWok15U=b1uf}log<((QTI~L^UrX%3rETKjdpOk0D6M|*@xVzffQg218>)% zT5%EkO+pqt$_Meo^acq!;(oCbA3iAIMn> zc(3MRIVr$5(jlS_hS{Q{`?$BLYr81?LGB$GwWo8r5&1>eP*C#Q32Sa#As{)BA*_e2 z1j`|A0)LHHY7fU|pvKT^#fLPf3%V7xy-q`tfSa&;l6H>vIPODh@$Aj`742`ZR5?NY zr1=#x1wxWLQ-JRZIjmjy*_A2ahVGuLErCd3O8zWYo`87+@&sC9hbv7`51sxyIZY7K zTk@elr8kASn7$nED_uhh5}j(qhq!C zTNr{I@B+3WIY^%|qqI$_fB8bQy1?Kcv&;N`=}FyhXlh=XhiHueUs@hm5S;vH)KuUg?6nY**GfTY zuB-rivSOU&mXy9HkO;1&o043)fYOr{nz9$H$^#)pu)21SD-m$$Wcgs^EDb3eM@*ld zlu86Q=FyiSAy7Uz_vGn5W#jcJq!Zr$V5>ZI!a03YWNyU=*-@1v3m`dQy^!bhc1)ih z6dc^pm|AFRlJf(4(sJLl0$6{2;o8#A%7-CaIZShPH&wbqcZPr_E4QdCCsj_Znhqm= zW%?B-fBE-Q0NL+u07#XX}?)v zc&B<=(P%N+o9q@CU*#-bU+Hk?1I~25J=OSQmAyG1kY6_F=1E*DuNU^bQhg4Ol3Un# z3*-B8Ei|A=Z7j^q)ich~y`8QL18RD;wd4@jihWJ!e_;MNIXHRkk z(~z$X8^myigqYKSpXb z_E7XB>fn(Rp%>7?h+ksoTxaGmy4YmW?&19OxuiSv0_sHcdKjrP*`wS`>{Vtm>5xG` z-!-CuWlx+irvS-5kAj%z!vmQ)F^f=esTZ2buReQ8>|-UnsZV#*mFgs_lKGg@qnV|} zE^yr$X#b1CoX224{Z2wMb&sl#ol8lY%EWtkvydokXGhAwA7X4@p)Fs5EAVF!T%Le= zq#>r-aF(*u2;12(80F$y5r5W>-@&(pQ=EE8LI&&2cB8v6og%!2b9@AyqWyzAs=bR- zV7cJUUlLy{ad4lrPswzj_u~3+&ocq+ASM7Zvy?Cd!7YO5L9UR-srtK~h8uF`Q^?>VyE9`3FK2ZG4YJQ8j7S#&D!aQyc|LX2wR7=Ci zjjP#UF4dvV)f=`bHBvNQ49csajPSiE};3Qp>xz4r*(p9u3!nlO+3nOmg& zMEG9dkqv)|w+kEbx-eh%B3~%@XzlqyZnWQvU5%Hk@lh_GTZVt-l_@lu4)az7rZJt| z3pHXpKUxUp2bCnqfPWAG{v~)em&~5xQz09+oh>hENB6^Y?4XigA$u@F_*QuO$Sqjg zK~N5f1pJ*)29W<%Kv=5;NB)KI0PUBBPZxGJwBwbmR_LxB?Lz%({DpuybIDbR_t&6$ zJWX6D9KfmCYsju$a@MP48Xk*J-PqGGN{2*;hG z%&>qJ8xt_jmU9BIz}So%6F${$2GI2(^b$Ab=V!1RxHaqsTp$*3zwqi4d_A8atiX-= zhh2mp``~yP@M9fbh;KvY<0$R}3vQu2@@cI?TT%ECe<^M$u&!lzly)=!A?f(pPv|J* z0o`A_>kfC3?I9e)6UZ9zDPbaBfY;**{F;axLd5Z2u+rx?i2JY!f2B<;?$k{E$IIBC zK{$!Mt9=QuKi5vi{@jTYJ79lUd_@5EFK}c3Kbo#DkIDg2{TDJ#nOIW-6R$mvzoG-C{ERY1ys6lp2bh`iRR`h25#?VCq9SY-WTS zvTf3Gi#Ac6YH=JR6!sd8pLMb&)jZ0gv$i+*C#FhA_xdaBw&PEk-!)lGB{}_whUxnL zL~xMlb4y)vKZtU3-j3-&~)mbXi`w{!PTCW`RM~%{8P@r(t$1(SrhVT@Yk6Ffk%;YjP)LeRT><#9UrkSy`sqg_YAJf-eNc|;dA@?3T zmoDSpV2p8ewcWnjzP6fDIL!8d<)cQ;;uXPAs*OKMQV?Z6fUt_~9JQUGvULBAa<>=OE@CzN-08($wtb>zDpuY5~DX^B6cPI%|*S33QOIWM4;biXB5rm z`Ux>dQeE5|h_{=2zXjxEbgnn+|(Ps@{m5z+K3%07xiuwE0f8<&JLTM3Zi1D zwA3tsvo?n`O(h1NCIi(A7Bo|AC6HPdD^_XqOMd~o|Ln)U^tL(0N?sCx=j`5O%u=k4)f6u zw_Vt~)L`6Jv7~4k9CIP>(g}qN%Reb4v!5zEg2f*WlATqd+j8zy6pDRElYK{2D_y}U zfbE>;A)=V<3Rn7@^X%>+VzI$STW{&1r z%~;Lbn$5c9q|-&hKM?zmR18&Tzv78hLz`(gNGs~-^GB*7Z60h*H0UD0RE8 zN7yCmJDQAn4zdOj^hg&5PoycxYGw(cf1-uVQ08oM0(H<(5VQa2$YvA{37u|~5cUE+ zojL(1d|qrY!0>rl*C6B1E@jn2%(EaqeGL}jvWy2aZopyr9dZt}z{`(-5l8c4Z*}k%yjkBXY6^2)PT87xkd>sNxtMm8rRw=z`?@ zNLtHt@%k1-9>0SBk^51dy95%e7n36mA5eO#6gc@?K+K<}uhV4-;iMym*sV?2DEvbC zADMCXMJ9@o_yXgOtk6aU3`N@0MGujdZZ4!y2{m%bYVI;ivL-H>7Qx}m7xDp>r(hq^h06H=n&BskvruE< zYkVqyjq`y-Kn1;uZ30nHc3r;3YsJX?qbNSUBMv|2#Gxr>y$S}~E5dc4!uKLO@};yN zH%f-*oK=SB`7%7m9m1V5I;VYcfm-MSxzDRY6>CZ;6RNm6nVJiWnNBB1LQD+<`#vEp zB^K1qt`Jc^NNFq?i-Pc%oG$WjR40y&J4_GMrn=!dy%>ZTZ_LV$W8?+e4+l{73_y7H zulU{UK4BhX1;FlwhtZ4Seel`+sepwncz#rOW|TG{+98zS2iVC);`!`8EXf3&tLB{e zguJc*b`JzS<$>Nee+07xrwf!A!9CCJW6wZl;(ewQU(Pv&r}HyqFDVOO6|!Qw@^-<( zZW4wI6ZlgyLWel`!`L+5#;?xb4vLe=#vKr*CY&i$_bIw3yidJ^J28adSK{P*;9}|} zT1B1XtoeOqfZmDQNS&a2GU?bUT;w;TIAJ9M=$x64=byMF8&~Jpa{_|r2<5%_)9_L+ zLFyq&=*d3=x`>;bGZpv}rx8EKkpSOgU`1Pi$KLqLMa(C#a+3QzuH)Z^%=KMiC>|`_ zC-wm`$70EOn2~v5H-7`z)MUJjTf?^jR*oIiS)s2unIrqnKlMG(aL(?c;qU0dxc+tdo<&4JP}qj&Jv>whx64g93HtD*%5e~FNmpg6~q2} zD!OqU1h>sJ`w0_0BS5CuZU>!k+Klt0Jfa3Dw%bA{oV6JNQmjir=l?}OKN28qfd_Bx zoUWZG^TPui9&cI)TH9*n$Y>is{}&BGF+Z$wACar3__=G5EtUjUg~ z^m6!a9AG*#FS6~JKV-g4?+E{e?aG{Id}N`VwzL+?)zKcKocWraPk+UXqO-ymGU;pr z_agv|cUe38H>!t)`=cIt+@`og?C+d`xp5-xVV2TulT%w{qRdCiM0plJj#JT-A~#2W z%5vPSlV^36iFQ|#Qswr^)lUfJc&?Di9ERa-jHwDR`hCFY^)g2Hh~+MP{7@_h6FUUZ z>wPU{wz?oX*xiZs|4xtj<-2=xB6FC}%P*1{I>f~48;lU;fyXUgIk$~h!+Nuq6w8G)etyCV{vZs^d-U`4Z=qW1-d}5qPd1C?!g`@e*d+GB zMKmyE+M!(wa^7Uz2yr!wzsOf#mEm!-SY?32t#oO9&Rg=hlP-MV?lvLRRc z$ijJOh(|Xs0JIkB6Y!{y(zMAEnI*$BQ;^vZGS|ib(&zj{e`)(OV7vP5do>j9Tc-zb35W zw=s>vfk(9Tgk)W5Vx>!Htp6|M^rRBXuB!)IMMe8kssFcvdPx&Q(1`9QUvL#JQ48mo zw?%N&TX3~3sW&_7`IEt7XINc+-VWNPh^)2}=s zrx(rvlVu>&mF^M~!0y3~C6AJ8kkWx%8$41v^DHx#9mI}gCt?EtHVR$h9^Ra7Ue*?mzLA*ex3 z7hZ$wRPEa^bH9iG#Y+d>-wR|OKirEd)@Q+E|3cj(Ydl&yByQuPhQr#U5nH1Vm2^#h zR(q7%@Pv|HjKQBd4C|Yt__y$7h601prKPJqUb@g*e1-pz>Oq~xfw65-EqgEWCihRi z5!T3HhZKkvCAzq!!X0D_TTxP^`3a}6zv5h(U5i->rIbMZisPx&=mG2r;n*oqOj_Xe z?FLBMD#gVmXM~7^=SZ8(us!BFZjYy=k#@JaE+cGlz>x>7&Gl43*vvP~1whyjTAS<4 z>m-ajga03!>#}VgMt^$rU&VExQ4s!n*Vx?Ji}49{-7*c5#hax?-cGw)dy%eL=0EDL z8*B6-V6D63Z{0O&d(JeY+GDMoYGnQ$YDSiMkWsd01%d_hD{5t|Tc=rg{fsuvI(ar{ zyy$V&O&L}Kcz0@xOTMSsSU0z`yz1+OEnGI)AGg^o`^+yO&6CVd^DL`+oPoAv zC+C?84K40Eu)v0#OVU=uYcb$-K9triH3q-(AoENnPakQ1vz4r_hX*kCJqCVyc>$}B zoo(B=`zS8S9O;Usi($x?7%NwM`5`dxGBqwuR>5~!;%~P? zzxUa*|`gyE1;*%5&w4(#?}8X3FD5mD9a1RY01cC&RJ!yUg+lPmMH7T*-;j7$ukkT zP%ZDXhkRYuV@`Pt^6a)aysK_8;Pr$0+GJEQ-Fz<1D;c1=u}4m1i$9){7;@|}b-Zvo zQQMdn67$d=2YI}71nFp;u9pdYOtV9-_DJOVww05;9W{*&vSydpRo2d1+2pW=bXpk! z@?k^8-<9W|l*&!#ZcdScu1w8QJe0}{8!P`RI8!cZ;#{tq_ERke@osO0kaEj)MjKTGAXomj6amgPRTSkC>sSe|g(lm$uA>#*Ud zKFI14E|TS98W$~!?dGS;q7Ezj@z+mxLtm>o0kh;!BBf%9)PuGVaKU9 z>{DQIx07%GN70<#p^a4+S8?6J&6@hWQ_|VUDkgV_|<1Y{10o0AZjQ!2gIR!kx$P zuWBnfC;x+t$sda5-1(H7av}f+hygOO=i}IYu$Q!0{8js?a1J{*V}yRfz?7S)u^=PN zuVjR-9&!Mm09)TD=t?SO>->ZhfH^k0Jeum=XVkhS!USeBpIK5}cs^kkS5e|@<(t;Dggj}Q7yOC)2)mi{z|E6oZhlPB;+TuWnOyn>Ap_51my-^U zUyfHqSf8-Vix#`=@;xnfIpmSwJwDu{m$%~SPwM3|Pj3UG#z;BH9{gYXjhxosR$Lj7uwg z>>iQCvcovsG+C{C!X3AqLN;9>njr<6##`j7FaK(eo07-|`*fJkK*=^Hn%qUCgJUwp5t+)Mf?xz*%WX@-N1>r`pSn=vQ44d8=wK zviBYKr1wpCiy7#t^#Z>4zVH^`J7!zVI2p&gb#FEGCA+HNebYWyy_Z(yULyKar{!`l z|H1mEA1n95z057(_S02heJ^FX!hBb`m)6!dvpH`QRUcZPWe=@~bxfLOOMDvNKSo_0 zpZtXN&EG9NQy7k>(~i)318fD4yvpx|nlH}@Q=+B_e+s>+{1UR2@4fr8qO(Qms4+}c z(4@Ine6F~6bM=>I$J-T^E{1vJ)&|mM?vM@4A1Y)kBGYXh{X*Fm4_C0ih-ThTc=&1ZimI zmv&)KiVL10yOUsTi=RD14(V!2LC*3Wrduayw}u@SB`etCfiOj%Im2Wjr91%!A{Q8^ z$+B^kP1fw2>c{=+%0NAn&Iot*UpyFnvqi4HOvy0ZTvOOzmaDDbi~KIK`?HV8)CH6O zU8WXKd6PZdDs{z%{}q*5?r%`-3RG&ftWtaGqwICpM~Pmda<*)Uq1#8h3#GJHtaa>LpeL}N#ms8;a3?1n8^!k6(tla?ndMFdf1j=f)yPgWazo-$Nis88p z%rZ`bf-34UP)TLXjnCL;*k^!T|GQ%?7gXVsOV+>`+NJ0NAqw~1{U01_%;CHnQ|SAA z*R!!DUGyrv3-%TMgU@J(vn%r5l~rI&*zNMHhw#tx&#Ljj=2EyLJpX<8b|;ZV+C-A+tI#7;|DO?71WQ2U-r-)0M z33ann?Kvw$205LT^!I8SJ@NBZ9?Nl z;RwXJR=k8OV!in!cxtU;d;8=fP35O|^3 zcL+J!yTxMe_dPjs1gOb!MUsD0lbb7&c+_Mc_^J*3pR38zRNcR8$o%+E?GHufv!cD)Z6kY3W~mAa0QNPll+kN`2JUS_&-7_14G5 zWUGQ`sFy~QK|ytvI~fCW2sGJt@S&Y7<63DnQCDZmIOuPA?h!#byr1FQ7BQLWm($Ps zf*3!P9IBMx+5rz4>wnWRW{H?0H!J@uA!Yh6>7-a8pN!&oF`2dWx zSt`E8t6Np+h+oxG3FJDL7P*uEfLY#(nm!bai@$!%RF*~M?;&ULi*Q1QokH1SgP=|a=J7AE0eB9o zFZ&*%z^qWokcfihjdZZmzb%~HorV|wo1_f)XgDKM_Xu-U=?;jv8SU64!)EV4+la;j!{E}-yZ^2Sxklmx6D^TOn%K( zkYf!$n=J(~ncXfI1pm%9T{X0lf*E8@ww^7|fM~4631$#%__sGZ!D^6#O@|}CEZ=Yt8Rr?!8DKA* zOfB6i@IjQVku6|Z_sRnkIO|tK0eHYsP*zB0iw>Mb8X77RVcT`;<2vwVuZJ@5%~#9L5;YBJfmb{>F!X5I28IDEE%5pR zb+ZpVxo~0S%ihjqTze)d251#9y&T z2O|)O^vLgqX&at9t4B5HER#$}#Pjw9O)5B!<4zlGN*<$&M0b|L&YM00hidoa{ za{h|&2e*JP!i1~l1!%m@l`bCFc=1TN(1oy)UiF_eUeGc(acl5fxE4mjG$9A`EXLmo z`D}>HBk6hWVizAf7 zE|$AgQtxtc8f8b z7P5js6;tk_2AF3DQa|C%Vxzl)1^Bpf1q+^^Eb_WxP@>}^caa{1lN03n6|$4de;k?1 zkZX-Vh}0z z4^WLngT{O=gs{Lnl zt@IH?3KjmuG*Zl-pc;dwiNT`j98jrnC}kD2Qtl)J#OYOvYiOz1v09OcmNoZ{_nQ00`^|l0 zxw~(yaQBT5n)}Ae=DxAY-8VjT_l=Jp=^G!D;@q3i6^A{qDiRZIiXgPw-AT|IZ4Wzq zsOS@S=lHa_bF6Ld9G^9Jj?bGr$GYauvHtPS@rAo{Y;boDrTiZgq=^ImfHybf2j$bE zvtGdxUp9A=uf#Qt&`G{_cam?KJIS|?b&~Jgon+G!on&)!C)wieB;U90Bx-G6Lb(*7 z5O*gbwvt-Y`>JsW{h%#UD#s#XTXQGb?(QTz+?`~ntCKM3M|ba_+`WT-*gFs-`n6TQ zg~G&-+A1w5T%6~typAHo!R?efv}<>J?YCH9zG<^ozLDPdN+yD*ofAOhNlZp_B47`b~W0 zDdiDjKPjfXsnnwb;y<00ZxRPd@y=VySI{AGoxgG}IxMF7E8j-Hi#@u)qy8bz?V=ot z{uDQNQI0@I#1mbVFQcPkO&6tEc?@0;DGt~N-)Lu7r4_6e@sD?vmC6%ve26?q^b}(j zE4AX09?HeUNmA48en6Ze#hpu)>y#R}^D=SNb%np!ahdXUA{qwEWy;A! z3@QE$Kb5g?ev+6L0^jMXWy$~|jud;or+kHoC&drnQ(94i_*)O`i&3t4 zZJ3fqdE%ns$}Plo*9_AGRy@kJ=!QJa>_qwEtr5yeNGDG)Q;}YtTc#m{JgvN}EPxki z7T)H*d&eMt`wplrjkwiJH;SYl^k&#wfiJQ9_DCzgB*vG{W5$iu3L& zx{4>iRt6C!=r~_1*Aiw@eD53hNJ~la{5SAUmXTupH_GAYraXFd6+_19Dv!e5*EEj)ozf&&5Wj%4{xnJE$zm9q#7e1CjY{l!lvDkY^A?lITh zr8;a;UK4{RE7zcM@x)~1R#YJlpQ8K*Rf>O3QEpdO!96#)`_s&+@NrkWMj3zc%vAWS z@3@AVE+R1v`t)6SyqSsai5sRV7ohvvOVgAckn#ci{snoI86uK_|5tbK0v|5$#ZI*9MA4o=)f3vPsE8M;zvs**2=?v!*SGEecS%0k&Cbrbeb4ti-^+7m zhOSrkIa%l?`ZoETt%%Xj$$oZioG!(cJ0HgBEb=9rI)Pq``_jBHfnKV7-3Kf2Q)xaq zz-FBaaQHi0eJVXc`KAw0cArX*CEvCWuEYvc9BTVj6RDplL~T!;M#F?EcnHR^Y5g** z=y0MqRrcW|`U^!>*)`Sl=ak}v1Y5ovV$GRM=P8=XR!pWVsSC%)v*mNN!K|r_evs08TeqVm{4h$JWxvluVWVrIuPW3&%fTBcH{} z-8Ge(O18=#oko`^IVvlgPM0bJRJLI{ggg-E{Y=`XTo#!@uTXMT_S+eBoH9sdAIzZR zmBFgCO}Xsk(`lKKr?SgVr`2=_3bolv$6h?0Hq)W_yfN+0+;#@NgAT*z)vR{1Hj+&| z6H*<{wwy`dQu0yP0D1;Ff_-!rove&d*`k4TDk)&Mo=wkIMyhOREXV`I$OQV%0{r_&mtFl-+k8{g8(6+JRS2 zLdw`<=hMqcIV-q;UP4B(UtB;J(a|{T5TJtVbHRo5WO5W+hc|jOzC8q{$QU+cCII9Z zHfJXN3kkF7v*;tru_`Pm0p|UX}Ap8BZ=@ZIvD)Sc5OUdzU*u}uf6IAv}0li8Y ztFq`wIvZ|J%_VdU8OLsrZzr*hmq49PRu93dQ`(Q3Lt{k2(@VOF&{(AXg3IUtLZa=9 z=0c-MjIFqwUQgoez~z9b32f07fT&Z^-|rx57O7-2ucQ-{i7FdXhRRN3e|R14rwvV2 ztb88iKba-w(XUAjyM8|1Po}UX3+QLG7S#-7odOE8av}XYnaXayirxZ0Cu0#^0YB%L zi|B1+1{=N@2Ty1BE(Qdh!FDgE5#`K26*+MUROBpG`Y^fdr%UJw^}DyoR=s^V&x)1ysPxDZiG^rRSsFL!by=&PUhM1>{0@;WEtFOtx(qDw@T`0uCkVs=}q(slsgo2u2iMl+lM*xFxg>@O=6BRA0@{_&I?p_^>{i% zS*W(B#sdPVe4^3g2c4Vy$s$&I6WvJ{^Y|W{_H10#qSvG5>h@ukFl($$ z$G1Q0LnCqn`;&{Cf8*#!Rh(vzQ{`5owbIBlyxdwFF#CO0~!1Zo&2!h4EkBi8fwx;9P10R8X0|&HsNz$khQLX-a+ne zpUG(sfiD$ZN3SBytZf~v%m$UU?S)=lxQotG?onB62Q=>WUGxm)*D4#e8_IYuJEoBy zquhtN*iDb3_oLbgtTh)d!aKWZSow|Gj=1X-LR#AM??y18JfODU{yrL_58_NaPS(Z;p>j{DZ2w+5R@q{!Torv9 z#m;G8{s{~tyXALuJnh7Re73>~Pio(%n0&ew2g=s$qo1?)HqztiGx&H)TJOd^OiKva z#%8zDI`S<0TPy70bC}aFsIEM3+rPmqcN1Nxya34b(4nk(6RdlRy}XG|Als$B4Pqsa zKngFivmODE?T|n=h;4m@zDHj{GjB*kIG8>2D1CM6RZ4egeUGp5hk?z6a#q66epxaH)(F@^o9l&Au zT+5%Q%ap(MDOtt~DDfdX`2{H1M{M~EK)8=p_C-LOuIyFYCueFtLO(%G&!iozsoQCz z@~JAr`$`smk={){V_h%OFO+?@w&gPZ64un`D!X!kHk0m0!DVTcd+KEf;R}`34AkZ* zU-n@gLj8QWU{CFUYxOnTy93_90oy)KB!6#T_zFFf&~H#hj;(Es4%WVg2L^~chEN9{ zKvtU8vZG(6S@6Uti@io~Rusx!cnx#x#0l4>{jIBpX_rwIpBJY+`;UidKXJ(nfCy5y z=u3+1&FesTWHxSn9p1f*O7A|dxG5X>23#*6ZNK~t37{F2ZGB%I$yU8dyA?lW^DO$6 z7C^l|!WO{`Vz+eDPn1l`u78W(sbo=>^)^i?*_5q%o7U4DoVX&bbmMkH=Lb;s+nw;Z z22%EyoiMApG!1sKcW8(VVu48r7FWCj{29#7pQPn6^Bu}*9xAbO1S8lV-=$s35H#|U z8e}j12`vt#?Xx(|Cdx3#VjW!wKWu$S8_NFPL#vd0dI-)PffM?1j*MVPg^z_>cJXdV zb|hQ9n;uOI(a<3%M~d3B{tOp@1ly;+C*O4ooB&*NOV(1Q+D*dG^!klc>v5QM^X0Zz4Q#U ze;B~gG5EaYppDI8m;a46D92FtxBKak7lNn6@|AJVsws@j_a*}eY}7FY$F^f8@H zkHaa4U>`iTlD+8439NoEkbNv=4?hT}@As4rQ z=+QicUSfCMPFVo`IQ!g(%-S5v$a4UJOY!BQ7xJTUt5v?|&dcm-P& z&|=D!`052%+Ieh$K$}74w^wIs8H6rCMNb`6z(RIcmUatS$Ud&nCZ=KVDn@d&kKp`4 z_m+{x?1}-}EJ*t>{3BPh$pf`Z$u&~#2FgTdzOt0EEjyrl*Rs4^?KrZG)#hrak)O7& z$+yQ@=H_))ndwQBjQdPW;)wNuPXAj>T(-F}Evf>`WS6 z(WE2!(5p{A6TA&w-)Or82{TW%TQAg)!ILHZ8FuSu%0`Ru(2 zh{btGZ)kYV9gD~8?Y;Vw^+9JW786AjV~s}*r6njT#T2nb4{j(h3;5MWwNW5eizT4$ z3apS`ZxrB$uUqiCbNgR-LN^MM6n{lHP>`I~JrA!-nj4b0C7W(XFMnqXI0pjm`PQEn zu#`~0fUQ0$9mlIg5qf)GO9;b>$Mj|T)n-tQqDOjj!^6A^U5w%)n^;s&HM~h;qDqvB zauV0ioCcv5TBG!kQ7j6qGRSMP9Q-;@T19OSG3!zN2i~#-KvDt1RZk4k$yEe`#Uvgm?x@~Sj;LHr|S)=-zZ)W zFOuq@Kbd;T)&es`;^G>ex5zQ#LsXyFj8UdSMriv9!X)v|kREIe;wh0*tW~X5*5};? z7!uBcET4QJQD7}LPL*PnugMZyz^CKCMN%b_cfY76A5Cssh2G7yh3tVI2OK^}Ku#_0 zg(YVbUqEVj8Gy~#F_CNQN-7r}E7oFhITJ0pW;XiQkShWryCIjKzz26s6Eo{;cw!}q z3cYo)xKVE)jyurKrG4#WIllaMkb`Dq*wvew>d)|JwB`t(2zce}$>u%Y&VY(OM8!ZW zM+_JFsH_lwL8sRf6C=a`evBwp<56q~JjKf80lt8HMJN@(y~?7dekWQZ7qeB1=%6#D z5B12ic% zsBjLtkh+LbNSINjQy&^M}Wfl-e z!qkXk4N4qqmrxxUfT3XyFF+_g-Z*69R$_6Ht;C}|4>uOh6kdWUMbpLH%TRQbT~szE z7npoLGnRXXsW~wvTq7C6X=ZV^Ih4x`lGo9IA}88Ks3YUV@1q{Rv?ajhrJWQSudPI}h1jETm^NMyX}GqamBI`Z86-iSmnS5bYmK9)3!DH2a2ShQM< zYA%9z#WvMdK=&F#C`R} zXl%iCdt7d_#9Ap_NKokSiqZTC3;J{-znPz|#3-Mow^?VI=XI7SnoB&Sk7_v28I49d z9@eMpt=3NQy684S#_jlT)b`qS=zhu$X%a5{X!>ORJW;HoD{j49Pw;B1NS~_T?{v95 zVzH>vuWs0(MI+H@Ow-rucz|>y!b{Z%#%*}&i=DX8O_b@ydNlyH*th_7yJ?Ki*B2T$ zcM+nAQAU&D?5#1J#*XeO#N9K>Xf#4<6cXuO7dEyUQ=CBIo-%ZAanBMXl$_0r0dB=4 zYAjCbyO?u)BxbPWLlFC~Q1|09^coJaQ>sNEoPBylL(sFHY96;6U9!sYJl>gnfpcF| zqX_yv5F6x+If$au<@#BoL9=D<7D2fbc}P%wMQ6Dcv?gm9pUdq^ty-I0cDBrq-Nc=22U3^ddd%cQ~5*v?dZ+pw~83dmAIR+Qb$V=~uTb^nIr= z%k{O*cOeFxnBbF@{Bio0)*bFQny98>jA9K5>bo1N-BJ`#7MH%TezTK8or)A!kzU=f zS#CF64jpXMWjcvcB>zg8xcn_@10{vYh)Wei$M4nD) zSBT^rp>-Nr-xDGUcdyG}_h?E}WABunTC!ZSD%C{f-Syc_k`+Em9WxYHD*(BX5Ul*n|&ps-M}luwg3J{qwGK~bYXgYn#l z$@0m`GHaxAnZEV5gE}aY0j;u^FZvkm$Z??y(4A;&jytViZWkZS$2yy!S~+OOW93+< z@bP^LWt~JKxSv%tVqQWVW)9Dm3!@qROIs!vMlby<8wTyk=N^Du|J3857L5rpxF0Vv zV+TP(jv^{D6u`(3%|;O_jVNnaO;?g+f z*&@IPV^$>O-h&cp+;rNIJJ8`i)8UW<$8v_0fUz;*^+8Ig135y-$@^=R3E_i^-$Sq# zQZqFly4Kj3mXpY%9;t)(;{2GMJnM(aLq=>306-4wAF$ui_??WE+_-IgCW=^covg5tnoI?gIqqH$3Qx3rp9iyB_0FKb7Gx~8=(vx?!9mH~T>yf)mo&k7PRU!td0RTG~TG>dzO z8gtv0@*3jmJt_6MQQxwxd!`bPbq&Xj8ap;byH0^8^?@0Jm4XwMXVhb*ZIAZk!>fvR z4evSC=os1janC6@-IcsS5B0PrNpfRqTCybh+V;7r1@~jD*)riXED=Fx;cba1{UYM^ zpr`uTisK7WO*~uV^6wqp7tToyLhTq_E>uPuyu>Z$iW!@1c5o z{m!1vSa2a7mnM-&*Ski?9g}-^cE6jPZd7-_ovckRgiiK6*1I!Va>wTF?cR{ zjZM8-#MAq8`M40$)O)ky@^p`d8Jk&u4gBt(7-N&=drl^ez2~6q-ivxKG*+(tqtY1d z9m`9USR}b{?L$L)XK|(nlNcEexVTTRZp(!@eAwg(uX{nmB#2YW z%Ok3dX${4q&vic6C z=h0rM*RRH^axTSU#pmn2t8V%uv)uiY*?U!T^PM**mCr(#MC;aZbxca z-R`2ez~JdP|!w!`W0+0YN2$5A^3Ff&z&2WF1+Cj$}qU&fgH3CtfOFtZ$fc5sSw(V{WSY~h9O?gsv*TeaY#wi~ zj_Ti`2eWMgU#g|)G5vOU0UIO1ILj=whKnO$vLl^-Q3!W0?#7dW;-+7P)ZGy7kpO>) z2r8Iu2GCR7wJvf(b&ETfPaHb6aB+9)&J???O3M|ZWx~4lk!p%pD z!DdJdHlpYirS zmIROob`EW1O7RKLfIg(@lNjb1((=Mmj1dEfqZI{Dwwu*#gL;_7;$A5nGa!6YIDRqQ z8YJ>CqjqL?O=*m2IfQwCjM+m~ed6?=QsB{U#2z>~z;>Y4LElB3vOtB&?U| zCukMn%5b>Snob(^8G4zR?y9H^#}Q!QOM{n@N^u=>9-j4hbl>&-9^4U6+^1i!gVm6i zAUa8gRgPzKm$im)6R#u9>58{P>>zQYYSr1(F)90ds?p0hzDsOH^2ew$?%z71`x$)h z>fXv{C>3F2o$*y~XHOMwyEWng`C9eBBGns?HzqGjUbDR_S(jYbUG?I|O&HlDGNm>= zQ4wy`3-qH!&=rmPD#Gz5y{hAE8Rzhziauq)(uFz;B{U<$QH+>P*48kMpUOwNFi;HM z3salnZGO-!6qjPfK^Wl*09heq9OJrqDGxazf%*rnOFCy;Q;4_a((X|LIp2!Pib_$S zT1NAn4K={U2T7%6G|Vv;ija6sFEs9a1igHS%{&6V^vX*#^`rIiW)Pl5nLekvjO6P# z>h%!vMt!}@@AFnxgv0u4`Y!5-qX#g+wg?zisU9ZgprP9+Pr}G01R0CKWJ$wkT^le&T^ND(&ve>E&g5xpkTXeQ^Ta zrliW#;yi8z~qid*%9`f`4TXyaEHKQ(@u+GO1Qz(c=B zzte7TIt<7FJUeVHhN{YeK<9z9T85n8{;_lpqTh`oR}A7O^5WDWm(+%)ibR-?>lg$r z5TIKh2GfYP9TVD(_E z4KthP@6?hy6g^PjpsWX z{XUWD4OiG}JQ0&)LZ3$qznLk<0g6ib4C3H}HlylNyK3pF4@K?*CL)?~fbn9u);#M(6d zZeyIalsD(u3PFR2f$C=x)7h7T(WM9Q*bJx4)6BHQv~4 zzmf@EZ|)kEyvF!u>$fO?yHQNoBgHn} zf`NK?ZJzjyZ`5CHeO0OScc0WdPQSdRs3*^fm84I6yvQo#`@4rE$F&B#hxCjyZmh3H zDAuI!yW=*q$hbGzh8uX?n|ux7!qXV0-`0nrcC;YFUi@VEaIkFA5$6Mhp`tq z1AzeC^csDVnB)v(29VWSqF)7{xr9u>e{1+v3WW5u{t|zZ2K-Wwmgw*)G2tcp5@QId zFiS|K5jG+;ZAC`u?;CScQl{!D!Nt$4p@ zF9{^`lErW3zLl4ZBv0=7c+Ys_<>cb7moYUHU?O#E2{hp4aJ$+%?o zsw=yTl;uUq1#92#9-(9wAqr}?N{v$y3zd-t#vhY{IJRPp7usV?`}sZxj4U+P>GEg# z)9H9XVvgny$c3CpWg{IEXw9|)B*1g53UM+&LWFs?ImOC^Ciu;%sX`GDGf8DC#|l^r zk$DZL<`Ks;Xy&}WW+Z40a=0Wi;0VmBgZq4_9*QEH_Vb}irk}%;1@a9ueeip;oc_!( z&uAT40A=kwl1G8#XPMn({?>HOL=@5o`G~gj-6Nhb$zUo|jbRk#-enpL{6tVA8hW z$00o2Eix^i8Nim_u$7^PaUw6|?iWz#n1k&~t7~TjARi6uCR1d{MQwTj*bogLVP%;f zGLDbo$D~j&O(*ob;t87+kTB)4ymBE}0dO7xc-@1n08HDUR2KJ}Loin_p{!*$`r{bU z`tw!f`#^nBLTXM~VG>|;nt)a++S zgUBo`InKBw`kbGQhz^@g^uMF;dc} z8?M-1px4(Q=pJdz(-V&(TTo!|-ajIwjDgittpj*1-E}-(Cv7?huZuRV!0XywEj!Tb z9rnER6R9%JmOM{nUpg|bMu=pb1@ETRZIubYBQ?}IN>~4-MCezKnS%)jaVmwy-{P3 zv1GG+UDq}j)Au1r$w#}QT)s<+H6p3jtxk z!`k(us8$($A40Zj$k-xw(zjSUY%0(Si6XtQLC&BEp+&v29)zpZE`4rWg``|lA-%Yz zk8*WJ_U$tkrK)-gNFr`CuXi?AZ7tB>G75Ts&;PC*RIa9paAUs$}z?hj9y~tyo2Wz_2d1XX~FbvRLd9;fJpDF|vuyfd>iM z)?6r$WHVdv50Xz=&3Ly!%XUr^v-KLW1kZpHdh-Q(1KKjt)}?)I{R^z@=pRVScFCdr zXIR-+?W*OaWd8wH_BB*qW{c^Eva)|fiT@!h`#OrI*@Yj>%D#ajQM-Rg_e6gPD+>w| zfQx)cG$M5=3##ITKD>#Fo=%gq@Mk#1yLlKh+uqO2zLL5{w1Sqch*56yvZ=VrK@7utFES}-=nYvBNhUn(&T zF-7&-Db}~W*wF@>d`fS1Ppy#v{|%NrWW2OJB-R;=^>?jr2{opG6))*_Np`&Vnx1K3 zS1)!s(o&K9c;~3(`s7C9cpFpjuMw?<|25OvN3`xl{b`~#`Y#Zz@1T}**oG~1Kq5m5 zPm;8fa_r2JnQGqV>RcH*t@9m zEL-;uV_5CU#I_AzX5X40KOXK`--_phoe6Bfz*Y{bA^$#DjIfDS*MC8*{t4CpIAWEf zL>l_~b18^Sih9Ds;+}gT~Uq8gTM#$@F_%NH`)zEw4#P>#XUs z{QVj$2DlCm6b>n1aiGYO8aqIoxEtkm*{%FrI92$wiT|CPDk#+v|CCexGsb$rzL0F_ z|J|f2TuG3sZ@q)Z0@|c1KArx=MR>igp;U6Hsi`1PU;In=dl>MZzR5kDK23a|KSfr@ zbC5nIE)hIPpEd_w;KxC+c;F4&>}h?e2-$297LUHIxz;*Oh3_91s=lXrEf0!nFqO3r zjDY2=!p6UH#pX*(`Ft@=vZXJ9`>ef?S4paL!<|-9@43Av=%uU9@BLZt30wnDIzT&b-UO1&PGjtWdTnMjSt2GPMdmX)l9TPJ56Lj3qwY86G(7nC>AF`EuWhTVktFB` z5Xt4X8vLh7(C=}e0u5dwGqEZ{`u_n5I!sQwBtenVC{sW%f&xX@lFGCE{0!vL$EN~j zwwT-*;Dw#TdePW|gQGiy^}Oi6qCKr6Bv07KdP2`LMVj;kp9d}HN19`-ks?P7khW*K z86&RL6p(RoYZkBM3$T$k%x{KX-@tF&gJ%CjROeq%^^c%Bs}H9-|BBKwTOyP2X{r;{ z#X+i*YuNY$Ge^N=c;Fa|3=*?ENHt`b?!VbP-v=G!IIV!h1P`R-@`FR}hXEvFK(>P6 zl;Zmkt&O!?>rbnsDOr0@&VR#jV*e!g&6MvWlz-MPFL%V*e1~KZZ1xO2OtYI%0TDz( zuc8t${PC&-R1I>I$YIXVXNodx3#>$f<$7JWz-;nqPLM@uV$*TKZ9xNdN(HRZ+)3((3kpGo2P!C zzC<3!xN|T1^x!|?FCosGKz_{7TkF?r|2Fax?C(F4m*6f3|08+%2|Cx7CNCw2>ywEm zC&)`g{e4ph@=_+b!O?MYVZ! zDhEG#7Ha?Z5|sO7#rCy#{~{;(IV!5Phc7#L2qy{Z!31w;uS}k)N=6c)HyH4^WF&dI5cD4O{q|X7K6i4JX1j~yI@BnaHSrFHdFL3UUBO|{&SUYtj zYC#Mnjdt@X=2oUm#410{JY^NMz4xpz)Zq=#eMM^mSH3}p9kNG=K|z3xwX9|W7|+xjw@kla)k zHeRlqX1uIa#=#^;x<4i1y1VLrz3Wz9^bJJup@WTl7&J1p`-d@z@%TXo(VT({Uyzpm zbIK+W#Z)yuAwB`u`t;F=6htk)t~$sgiqT4ZpE0H5Adwi?Z%Y%22~lsbt#jM38Et}Y zZ7%3KO`U)%dvs6*Ju&`9(h delta 8095 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 QJzkV}NY&7%9cFL&e|xZ?m;e9( diff --git a/media/baseset/orig_extra.grf.hash b/media/baseset/orig_extra.grf.hash index 3d6fe3d451..6ca3b2ee0c 100644 --- a/media/baseset/orig_extra.grf.hash +++ b/media/baseset/orig_extra.grf.hash @@ -1 +1 @@ -3e860a0e880e3dc90615facf5f455fc6 +5fdc049a7a0ada4c280239f15bc38174 diff --git a/media/baseset/orig_extra/CMakeLists.txt b/media/baseset/orig_extra/CMakeLists.txt index ceae83ca70..997e309a16 100644 --- a/media/baseset/orig_extra/CMakeLists.txt +++ b/media/baseset/orig_extra/CMakeLists.txt @@ -10,6 +10,7 @@ if(GRFCODEC_FOUND) ${CMAKE_CURRENT_SOURCE_DIR}/rivers/rapids.nfo ${CMAKE_CURRENT_SOURCE_DIR}/rivers/temperate.nfo ${CMAKE_CURRENT_SOURCE_DIR}/rivers/toyland.nfo + ${CMAKE_CURRENT_SOURCE_DIR}/rivers/toyland_rapids.nfo ${CMAKE_CURRENT_SOURCE_DIR}/rivers/tropic.nfo ${CMAKE_CURRENT_SOURCE_DIR}/airports_orig_extra.nfo ${CMAKE_CURRENT_SOURCE_DIR}/canals_extra.nfo @@ -24,6 +25,8 @@ if(GRFCODEC_FOUND) ${CMAKE_CURRENT_SOURCE_DIR}/rivers/rapids_shading.png ${CMAKE_CURRENT_SOURCE_DIR}/rivers/temperate.png ${CMAKE_CURRENT_SOURCE_DIR}/rivers/toyland.png + ${CMAKE_CURRENT_SOURCE_DIR}/rivers/toyland_rapids.png + ${CMAKE_CURRENT_SOURCE_DIR}/rivers/toyland_rapids_shading.png ${CMAKE_CURRENT_SOURCE_DIR}/rivers/tropic_desert.png ${CMAKE_CURRENT_SOURCE_DIR}/rivers/tropic_forest.png ${CMAKE_CURRENT_SOURCE_DIR}/fix_graphics.png diff --git a/media/baseset/orig_extra/orig_extra.nfo b/media/baseset/orig_extra/orig_extra.nfo index e6ecca8a00..ad1c7b72fb 100644 --- a/media/baseset/orig_extra/orig_extra.nfo +++ b/media/baseset/orig_extra/orig_extra.nfo @@ -79,6 +79,7 @@ #include "airports_orig_extra.nfo" #include "canals_extra.nfo" #include "rivers/rapids.nfo" +#include "rivers/toyland_rapids.nfo" #include "rivers/temperate.nfo" #include "rivers/arctic.nfo" #include "rivers/tropic.nfo" diff --git a/media/baseset/orig_extra/rivers/toyland.nfo b/media/baseset/orig_extra/rivers/toyland.nfo index 8b6dedd386..41d6ff5666 100644 --- a/media/baseset/orig_extra/rivers/toyland.nfo +++ b/media/baseset/orig_extra/rivers/toyland.nfo @@ -3,7 +3,7 @@ // OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. // See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . // - -1 * 0 0C "Toyland river graphics by andythenorth (Andrew Parkhouse)" + -1 * 0 0C "Toyland river graphics by zephyris (Richard Wheeler)" -1 * 4 01 05 01 3C -1 sprites/toyland.png 8bpp 10 10 38 19 -5 0 normal -1 sprites/toyland.png 8bpp 58 10 38 18 -5 13 normal diff --git a/media/baseset/orig_extra/rivers/toyland.png b/media/baseset/orig_extra/rivers/toyland.png index 61ff224301bda30cbbb2f9e78dbd82a2d6c67715..80db3e2ab2dd12a3d54fa85bad93356de87d5793 100644 GIT binary patch literal 34644 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 XcA. +// + -1 * 0 0C "Toyland rapid graphics by zephyris (Richard Wheeler)" + -1 * 4 01 05 01 04 + -1 sprites/toyland_rapids.png 8bpp 10 10 64 23 -31 0 normal + | sprites/toyland_rapids_shading.png 32bpp 10 10 64 23 -31 0 normal + | sprites/toyland_rapids.png mask 10 10 + -1 sprites/toyland_rapids.png 8bpp 90 10 64 39 -31 -8 normal + | sprites/toyland_rapids_shading.png 32bpp 90 10 64 39 -31 -8 normal + | sprites/toyland_rapids.png mask 90 10 + -1 sprites/toyland_rapids.png 8bpp 170 10 64 23 -31 0 normal + | sprites/toyland_rapids_shading.png 32bpp 170 10 64 23 -31 0 normal + | sprites/toyland_rapids.png mask 170 10 + -1 sprites/toyland_rapids.png 8bpp 250 10 64 39 -31 -8 normal + | sprites/toyland_rapids_shading.png 32bpp 250 10 64 39 -31 -8 normal + | sprites/toyland_rapids.png mask 250 10 + -1 * 7 02 05 00 01 00 00 00 + + -1 * 4 01 05 01 04 + -1 sprites/toyland_rapids.png 8bpp 10 60 64 23 -31 0 normal + | sprites/toyland_rapids_shading.png 32bpp 10 60 64 23 -31 0 normal + | sprites/toyland_rapids.png mask 10 60 + -1 sprites/toyland_rapids.png 8bpp 90 60 64 39 -31 -8 normal + | sprites/toyland_rapids_shading.png 32bpp 90 60 64 39 -31 -8 normal + | sprites/toyland_rapids.png mask 90 60 + -1 sprites/toyland_rapids.png 8bpp 170 60 64 23 -31 0 normal + | sprites/toyland_rapids_shading.png 32bpp 170 60 64 23 -31 0 normal + | sprites/toyland_rapids.png mask 170 60 + -1 sprites/toyland_rapids.png 8bpp 250 60 64 39 -31 -8 normal + | sprites/toyland_rapids_shading.png 32bpp 250 60 64 39 -31 -8 normal + | sprites/toyland_rapids.png mask 250 60 + -1 * 7 02 05 01 01 00 00 00 + + -1 * 4 01 05 01 04 + -1 sprites/toyland_rapids.png 8bpp 10 110 64 23 -31 0 normal + | sprites/toyland_rapids_shading.png 32bpp 10 110 64 23 -31 0 normal + | sprites/toyland_rapids.png mask 10 110 + -1 sprites/toyland_rapids.png 8bpp 90 110 64 39 -31 -8 normal + | sprites/toyland_rapids_shading.png 32bpp 90 110 64 39 -31 -8 normal + | sprites/toyland_rapids.png mask 90 110 + -1 sprites/toyland_rapids.png 8bpp 170 110 64 23 -31 0 normal + | sprites/toyland_rapids_shading.png 32bpp 170 110 64 23 -31 0 normal + | sprites/toyland_rapids.png mask 170 110 + -1 sprites/toyland_rapids.png 8bpp 250 110 64 39 -31 -8 normal + | sprites/toyland_rapids_shading.png 32bpp 250 110 64 39 -31 -8 normal + | sprites/toyland_rapids.png mask 250 110 + -1 * 7 02 05 02 01 00 00 00 + + -1 * 4 01 05 01 04 + -1 sprites/toyland_rapids.png 8bpp 10 160 64 23 -31 0 normal + | sprites/toyland_rapids_shading.png 32bpp 10 160 64 23 -31 0 normal + | sprites/toyland_rapids.png mask 10 160 + -1 sprites/toyland_rapids.png 8bpp 90 160 64 39 -31 -8 normal + | sprites/toyland_rapids_shading.png 32bpp 90 160 64 39 -31 -8 normal + | sprites/toyland_rapids.png mask 90 160 + -1 sprites/toyland_rapids.png 8bpp 170 160 64 23 -31 0 normal + | sprites/toyland_rapids_shading.png 32bpp 170 160 64 23 -31 0 normal + | sprites/toyland_rapids.png mask 170 160 + -1 sprites/toyland_rapids.png 8bpp 250 160 64 39 -31 -8 normal + | sprites/toyland_rapids_shading.png 32bpp 250 160 64 39 -31 -8 normal + | sprites/toyland_rapids.png mask 250 160 + -1 * 7 02 05 03 01 00 00 00 + + -1 * 39 02 05 10 80 00 01 04 + 00 00 + 01 00 + 02 00 + 03 00 + -1 * 6 07 83 01 \7! 03 01 + -1 * 7 03 05 01 05 00 10 00 diff --git a/media/baseset/orig_extra/rivers/toyland_rapids.png b/media/baseset/orig_extra/rivers/toyland_rapids.png new file mode 100644 index 0000000000000000000000000000000000000000..7216b1b44847a163fa5a041075fae972903b65bf GIT binary patch literal 22458 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 VSz*#>2ldU4=Ct0;uG+>=^dDhxzxV(E literal 0 HcmV?d00001 diff --git a/media/baseset/orig_extra/rivers/toyland_rapids_shading.png b/media/baseset/orig_extra/rivers/toyland_rapids_shading.png new file mode 100644 index 0000000000000000000000000000000000000000..946a0ef0903b622c24822e582ac7f47d4a47b72f GIT binary patch literal 18865 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