From ead5ad119c1faffc35438b284a9be7dcaf861ba7 Mon Sep 17 00:00:00 2001 From: translators Date: Thu, 28 Dec 2023 18:38:31 +0000 Subject: [PATCH 1/7] Update: Translations from eints english (au): 11 changes by krysclarke danish: 9 changes by bscargo portuguese (brazilian): 10 changes by pasantoro --- src/lang/brazilian_portuguese.txt | 12 ++++++++++-- src/lang/danish.txt | 11 +++++++++-- src/lang/english_AU.txt | 14 +++++++++++--- 3 files changed, 30 insertions(+), 7 deletions(-) diff --git a/src/lang/brazilian_portuguese.txt b/src/lang/brazilian_portuguese.txt index ae5ffeb53c..10e5f90af3 100644 --- a/src/lang/brazilian_portuguese.txt +++ b/src/lang/brazilian_portuguese.txt @@ -2197,9 +2197,17 @@ STR_LIVERY_TRAIN_TOOLTIP :{BLACK}Exibe es STR_LIVERY_ROAD_VEHICLE_TOOLTIP :{BLACK}Exibir os esquemas de cor de automóveis STR_LIVERY_SHIP_TOOLTIP :{BLACK}Exibir esquemas de cor de embarcação STR_LIVERY_AIRCRAFT_TOOLTIP :{BLACK}Exibir esquemas de cor de aviões +STR_LIVERY_TRAIN_GROUP_TOOLTIP :{BLACK}Exibir cores de grupos de trens +STR_LIVERY_ROAD_VEHICLE_GROUP_TOOLTIP :{BLACK}Exibir cores dos grupos de veículos +STR_LIVERY_SHIP_GROUP_TOOLTIP :{BLACK}Exibir cores de grupos de embarcações +STR_LIVERY_AIRCRAFT_GROUP_TOOLTIP :{BLACK}Exibir cores dos grupos de aeronaves STR_LIVERY_PRIMARY_TOOLTIP :{BLACK}Escolha a cor principal para o esquema selecionado. Ctrl+Clique seleciona essa cor para todos os esquemas STR_LIVERY_SECONDARY_TOOLTIP :{BLACK}Escolha a cor secundária para o esquema selecionado. Ctrl+Clique seleciona essa cor para todos os esquemas STR_LIVERY_PANEL_TOOLTIP :{BLACK}Selecionar um esquema de cores para mudar, ou múltiplos esquemas com CTRL+clique. Marque a opção para utilizar o esquema +STR_LIVERY_TRAIN_GROUP_EMPTY :Não há grupos de trens configurados +STR_LIVERY_ROAD_VEHICLE_GROUP_EMPTY :Não há grupos de veículos configurados +STR_LIVERY_SHIP_GROUP_EMPTY :Não há grupos de embarcações configurados +STR_LIVERY_AIRCRAFT_GROUP_EMPTY :Não há grupos de aeronaves configurados ###length 23 STR_LIVERY_DEFAULT :Cores padrão @@ -4654,9 +4662,9 @@ STR_AI_DEBUG_MATCH_CASE :{BLACK}Correspo STR_AI_DEBUG_MATCH_CASE_TOOLTIP :{BLACK}Alternar correspondencia de "case" quando comparar mensagens de resgisto da IA contra a sequencia de falhas STR_AI_DEBUG_CONTINUE :{BLACK}Continuar STR_AI_DEBUG_CONTINUE_TOOLTIP :{BLACK}Despausar e continuar o AI -STR_AI_DEBUG_SELECT_AI_TOOLTIP :{BLACK}Ver a depuração produzida desta IA +STR_AI_DEBUG_SELECT_AI_TOOLTIP :{BLACK}Ver saída de depuração desta IA STR_AI_GAME_SCRIPT :{BLACK}Game Script -STR_AI_GAME_SCRIPT_TOOLTIP :{BLACK}Checando o log do Game Script +STR_AI_GAME_SCRIPT_TOOLTIP :{BLACK}Verifique o registo do Script de jogo STR_ERROR_AI_NO_AI_FOUND :Nenhuma IA adequada encontrada para carregar.{} Esta IA é falsa e não irá fazer nada.{} Você pode pode baixar várias IA através do sistema de 'Conteúdo Online' STR_ERROR_AI_PLEASE_REPORT_CRASH :{WHITE}Um dos scripts em execução travou. Favor relatar isto ao autor do script com uma captura de tela da Janela de Depuração da I.A./Script do jogo diff --git a/src/lang/danish.txt b/src/lang/danish.txt index 6f51fc9060..af5f1af464 100644 --- a/src/lang/danish.txt +++ b/src/lang/danish.txt @@ -2194,12 +2194,19 @@ STR_LIVERY_TRAIN_TOOLTIP :{BLACK}Vis farv STR_LIVERY_ROAD_VEHICLE_TOOLTIP :{BLACK}Vis farveskemaer for køretøjer STR_LIVERY_SHIP_TOOLTIP :{BLACK}Vis farveskemaer for skibe STR_LIVERY_AIRCRAFT_TOOLTIP :{BLACK}Vis farveskemaer for fly +STR_LIVERY_TRAIN_GROUP_TOOLTIP :{BLACK}Vis farver på toggrupper +STR_LIVERY_ROAD_VEHICLE_GROUP_TOOLTIP :{BLACK}Vis farver på vejkøretøjsgrupper +STR_LIVERY_SHIP_GROUP_TOOLTIP :{BLACK}Vis farver på skibsgrupper +STR_LIVERY_AIRCRAFT_GROUP_TOOLTIP :{BLACK}Vis farverne på flygrupper STR_LIVERY_PRIMARY_TOOLTIP :{BLACK}Vælg den primære farve for det valgte farveskema. Ctrl+Click vil sætte denne farve for alle farveskemaer STR_LIVERY_SECONDARY_TOOLTIP :{BLACK}Vælg den sekundære farve for det valgte farveskema. Ctrl+Click vil sætte denne farve for alle farveskemaer STR_LIVERY_PANEL_TOOLTIP :{BLACK}Vælg et farveskema, som skal ændres, eller flere farveskemaer vha. CTRL+klik. Klik på boksen for at slå brug af farveskemaet til/fra +STR_LIVERY_ROAD_VEHICLE_GROUP_EMPTY :Der er ikke oprettet grupper af vejkøretøjer +STR_LIVERY_SHIP_GROUP_EMPTY :Der er ikke oprettet skibsgrupper +STR_LIVERY_AIRCRAFT_GROUP_EMPTY :Der er ikke oprettet flygrupper ###length 23 -STR_LIVERY_DEFAULT :Standardfarver +STR_LIVERY_DEFAULT :Standard Livery STR_LIVERY_STEAM :Damplokomotiv STR_LIVERY_DIESEL :Diesellokomotiv STR_LIVERY_ELECTRIC :Elektrisk lokomotiv @@ -4651,7 +4658,7 @@ STR_AI_DEBUG_MATCH_CASE :{BLACK}Match st STR_AI_DEBUG_MATCH_CASE_TOOLTIP :{BLACK}Vis matchende stort/lille bogstav ved sammenligning af AI log beskeder messages mod teksten STR_AI_DEBUG_CONTINUE :{BLACK}Fortsæt STR_AI_DEBUG_CONTINUE_TOOLTIP :{BLACK}Sæt spillet i gang, og start den kunstige intelligens igen -STR_AI_DEBUG_SELECT_AI_TOOLTIP :{BLACK}Se debug output for denne AI +STR_AI_DEBUG_SELECT_AI_TOOLTIP :{BLACK}Se fejlretningsoutput af denne AI. Ctrl-klik for at åbne i et nyt vindue STR_AI_GAME_SCRIPT :{BLACK}Spil Script STR_AI_GAME_SCRIPT_TOOLTIP :{BLACK}Tjek SpilScript-loggen diff --git a/src/lang/english_AU.txt b/src/lang/english_AU.txt index 0278f5a4ee..eb94bd140d 100644 --- a/src/lang/english_AU.txt +++ b/src/lang/english_AU.txt @@ -2196,12 +2196,20 @@ 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 +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 +STR_LIVERY_DEFAULT :Default Livery STR_LIVERY_STEAM :Steam Engine STR_LIVERY_DIESEL :Diesel Engine STR_LIVERY_ELECTRIC :Electric Engine @@ -4653,9 +4661,9 @@ STR_AI_DEBUG_MATCH_CASE :{BLACK}Match ca STR_AI_DEBUG_MATCH_CASE_TOOLTIP :{BLACK}Toggle matching case when comparing AI log messages against the break string STR_AI_DEBUG_CONTINUE :{BLACK}Continue STR_AI_DEBUG_CONTINUE_TOOLTIP :{BLACK}Unpause and continue the AI -STR_AI_DEBUG_SELECT_AI_TOOLTIP :{BLACK}View debug output of this AI +STR_AI_DEBUG_SELECT_AI_TOOLTIP :{BLACK}View debug output of this AI. Ctrl-Click to open in a new window STR_AI_GAME_SCRIPT :{BLACK}Game Script -STR_AI_GAME_SCRIPT_TOOLTIP :{BLACK}Check the Game Script log +STR_AI_GAME_SCRIPT_TOOLTIP :{BLACK}Check the Game Script log. Ctrl-Click to open in a new window STR_ERROR_AI_NO_AI_FOUND :No suitable AI found to load.{}This AI is a dummy AI and won't do anything.{}You can download several AIs via the 'Online Content' system STR_ERROR_AI_PLEASE_REPORT_CRASH :{WHITE}One of the running scripts crashed. Please report this to the script author with a screenshot of the AI/Game Script Debug Window From 7b2c143df076673f46cc0d26952cbbd6ff8d61d0 Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Thu, 28 Dec 2023 18:08:39 +0000 Subject: [PATCH 2/7] Fix: Prevent underflow if engine base life is less than 8 years. --- src/engine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engine.cpp b/src/engine.cpp index bbccfa6ffd..1481bb6b92 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -724,7 +724,7 @@ void StartupOneEngine(Engine *e, TimerGameCalendar::Date aging_date, uint32_t se r = Random(); e->reliability_final = GB(r, 16, 14) + 0x3FFF; e->duration_phase_1 = GB(r, 0, 5) + 7; - e->duration_phase_2 = GB(r, 5, 4) + ei->base_life.base() * 12 - 96; + e->duration_phase_2 = std::max(0, int(GB(r, 5, 4)) + ei->base_life.base() * 12 - 96); e->duration_phase_3 = GB(r, 9, 7) + 120; RestoreRandomSeeds(saved_seeds); From bd3b28551e9a45cba654af770f10f06795f65206 Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Thu, 28 Dec 2023 18:11:26 +0000 Subject: [PATCH 3/7] Codechange: Replace reliability magic numbers with constants. These are derived as a percentage of UINT16_MAX. --- src/engine.cpp | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/engine.cpp b/src/engine.cpp index 1481bb6b92..0293eba1f8 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -717,12 +717,23 @@ void StartupOneEngine(Engine *e, TimerGameCalendar::Date aging_date, uint32_t se e->type ^ e->GetGRFID()); - r = Random(); - e->reliability_start = GB(r, 16, 14) + 0x7AE0; - e->reliability_max = GB(r, 0, 14) + 0xBFFF; + /* Base reliability defined as a percentage of UINT16_MAX. */ + const uint16_t RELIABILITY_START = UINT16_MAX * 48 / 100; + const uint16_t RELIABILITY_MAX = UINT16_MAX * 75 / 100; + const uint16_t RELIABILITY_FINAL = UINT16_MAX * 25 / 100; + + static_assert(RELIABILITY_START == 0x7AE0); + static_assert(RELIABILITY_MAX == 0xBFFF); + static_assert(RELIABILITY_FINAL == 0x3FFF); r = Random(); - e->reliability_final = GB(r, 16, 14) + 0x3FFF; + /* 14 bits gives a value between 0 and 16383, which is up to an additional 25%p reliability on top of the base reliability. */ + e->reliability_start = GB(r, 16, 14) + RELIABILITY_START; + e->reliability_max = GB(r, 0, 14) + RELIABILITY_MAX; + + r = Random(); + e->reliability_final = GB(r, 16, 14) + RELIABILITY_FINAL; + e->duration_phase_1 = GB(r, 0, 5) + 7; e->duration_phase_2 = std::max(0, int(GB(r, 5, 4)) + ei->base_life.base() * 12 - 96); e->duration_phase_3 = GB(r, 9, 7) + 120; From 33ff64ef74ded23751621f1f574a40efdd56460d Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Thu, 28 Dec 2023 21:34:08 +0000 Subject: [PATCH 4/7] Codechange: Simplify ConvertDateToYMD by returning YearMonthDay instead of outputting to a pointer. (#11637) --- src/build_vehicle_gui.cpp | 3 +-- src/cheat_gui.cpp | 3 +-- src/console_cmds.cpp | 3 +-- src/crashlog.cpp | 3 +-- src/date_gui.cpp | 2 +- src/engine.cpp | 3 +-- src/landscape.cpp | 3 +-- src/network/network_gui.cpp | 8 +++----- src/newgrf.cpp | 3 +-- src/saveload/oldloader_sl.cpp | 3 +-- src/script/api/script_date.cpp | 9 +++------ src/strings.cpp | 9 +++------ src/subsidy_gui.cpp | 3 +-- src/survey.cpp | 3 +-- src/timer/timer_game_calendar.cpp | 22 ++++++++++------------ src/timer/timer_game_calendar.h | 2 +- 16 files changed, 31 insertions(+), 51 deletions(-) diff --git a/src/build_vehicle_gui.cpp b/src/build_vehicle_gui.cpp index 52ccb4a14e..1398b6c280 100644 --- a/src/build_vehicle_gui.cpp +++ b/src/build_vehicle_gui.cpp @@ -920,8 +920,7 @@ void TestedEngineDetails::FillDefaultCapacities(const Engine *e) int DrawVehiclePurchaseInfo(int left, int right, int y, EngineID engine_number, TestedEngineDetails &te) { const Engine *e = Engine::Get(engine_number); - TimerGameCalendar::YearMonthDay ymd; - TimerGameCalendar::ConvertDateToYMD(e->intro_date, &ymd); + TimerGameCalendar::YearMonthDay ymd = TimerGameCalendar::ConvertDateToYMD(e->intro_date); bool refittable = IsArticulatedVehicleRefittable(engine_number); bool articulated_cargo = false; diff --git a/src/cheat_gui.cpp b/src/cheat_gui.cpp index 16ca022c30..93e6b61623 100644 --- a/src/cheat_gui.cpp +++ b/src/cheat_gui.cpp @@ -104,8 +104,7 @@ static int32_t ClickChangeDateCheat(int32_t new_value, int32_t) auto new_year = Clamp(TimerGameCalendar::Year(new_value), CalendarTime::MIN_YEAR, CalendarTime::MAX_YEAR); if (new_year == TimerGameCalendar::year) return TimerGameCalendar::year.base(); - TimerGameCalendar::YearMonthDay ymd; - TimerGameCalendar::ConvertDateToYMD(TimerGameCalendar::date, &ymd); + TimerGameCalendar::YearMonthDay ymd = TimerGameCalendar::ConvertDateToYMD(TimerGameCalendar::date); TimerGameCalendar::Date new_date = TimerGameCalendar::ConvertYMDToDate(new_year, ymd.month, ymd.day); /* Shift cached dates before we change the date. */ diff --git a/src/console_cmds.cpp b/src/console_cmds.cpp index 9a1bf76590..eec523eeb3 100644 --- a/src/console_cmds.cpp +++ b/src/console_cmds.cpp @@ -1442,8 +1442,7 @@ DEF_CONSOLE_CMD(ConGetDate) return true; } - TimerGameCalendar::YearMonthDay ymd; - TimerGameCalendar::ConvertDateToYMD(TimerGameCalendar::date, &ymd); + TimerGameCalendar::YearMonthDay ymd = TimerGameCalendar::ConvertDateToYMD(TimerGameCalendar::date); IConsolePrint(CC_DEFAULT, "Date: {:04d}-{:02d}-{:02d}", ymd.year, ymd.month + 1, ymd.day); return true; } diff --git a/src/crashlog.cpp b/src/crashlog.cpp index 4be2605652..682d35f7c1 100644 --- a/src/crashlog.cpp +++ b/src/crashlog.cpp @@ -57,8 +57,7 @@ static void SurveyRecentNews(nlohmann::json &json) int i = 0; for (NewsItem *news = _latest_news; i < 32 && news != nullptr; news = news->prev, i++) { - TimerGameCalendar::YearMonthDay ymd; - TimerGameCalendar::ConvertDateToYMD(news->date, &ymd); + TimerGameCalendar::YearMonthDay ymd = TimerGameCalendar::ConvertDateToYMD(news->date); json.push_back(fmt::format("({}-{:02}-{:02}) StringID: {}, Type: {}, Ref1: {}, {}, Ref2: {}, {}", ymd.year, ymd.month + 1, ymd.day, news->string_id, news->type, news->reftype1, news->ref1, news->reftype2, news->ref2)); diff --git a/src/date_gui.cpp b/src/date_gui.cpp index c81252f70f..f928345a43 100644 --- a/src/date_gui.cpp +++ b/src/date_gui.cpp @@ -51,7 +51,7 @@ struct SetDateWindow : Window { this->InitNested(window_number); if (initial_date == 0) initial_date = TimerGameCalendar::date; - TimerGameCalendar::ConvertDateToYMD(initial_date, &this->date); + this->date = TimerGameCalendar::ConvertDateToYMD(initial_date); this->date.year = Clamp(this->date.year, min_year, max_year); } diff --git a/src/engine.cpp b/src/engine.cpp index 0293eba1f8..80b8896cff 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -663,8 +663,7 @@ void SetYearEngineAgingStops() if (e->type == VEH_TRAIN && e->u.rail.railveh_type == RAILVEH_WAGON) continue; /* Base year ending date on half the model life */ - TimerGameCalendar::YearMonthDay ymd; - TimerGameCalendar::ConvertDateToYMD(ei->base_intro + (ei->lifelength.base() * CalendarTime::DAYS_IN_LEAP_YEAR) / 2, &ymd); + TimerGameCalendar::YearMonthDay ymd = TimerGameCalendar::ConvertDateToYMD(ei->base_intro + (ei->lifelength.base() * CalendarTime::DAYS_IN_LEAP_YEAR) / 2); _year_engine_aging_stops = std::max(_year_engine_aging_stops, ymd.year); } diff --git a/src/landscape.cpp b/src/landscape.cpp index b534c8345a..880c77b576 100644 --- a/src/landscape.cpp +++ b/src/landscape.cpp @@ -609,8 +609,7 @@ byte GetSnowLine() { if (_snow_line == nullptr) return _settings_game.game_creation.snow_line_height; - TimerGameCalendar::YearMonthDay ymd; - TimerGameCalendar::ConvertDateToYMD(TimerGameCalendar::date, &ymd); + TimerGameCalendar::YearMonthDay ymd = TimerGameCalendar::ConvertDateToYMD(TimerGameCalendar::date); return _snow_line->table[ymd.month][ymd.day]; } diff --git a/src/network/network_gui.cpp b/src/network/network_gui.cpp index ddd6f62985..669de4954c 100644 --- a/src/network/network_gui.cpp +++ b/src/network/network_gui.cpp @@ -381,8 +381,7 @@ protected: if (const NWidgetBase *nwid = this->GetWidget(WID_NG_DATE); nwid->current_x != 0) { /* current date */ Rect date = nwid->GetCurrentRect(); - TimerGameCalendar::YearMonthDay ymd; - TimerGameCalendar::ConvertDateToYMD(cur_item->info.game_date, &ymd); + TimerGameCalendar::YearMonthDay ymd = TimerGameCalendar::ConvertDateToYMD(cur_item->info.game_date); SetDParam(0, ymd.year); DrawString(date.left, date.right, y + text_y_offset, STR_JUST_INT, TC_BLACK, SA_HOR_CENTER); } @@ -390,9 +389,8 @@ protected: if (const NWidgetBase *nwid = this->GetWidget(WID_NG_YEARS); nwid->current_x != 0) { /* number of years the game is running */ Rect years = nwid->GetCurrentRect(); - TimerGameCalendar::YearMonthDay ymd_cur, ymd_start; - TimerGameCalendar::ConvertDateToYMD(cur_item->info.game_date, &ymd_cur); - TimerGameCalendar::ConvertDateToYMD(cur_item->info.start_date, &ymd_start); + TimerGameCalendar::YearMonthDay ymd_cur = TimerGameCalendar::ConvertDateToYMD(cur_item->info.game_date); + TimerGameCalendar::YearMonthDay ymd_start = TimerGameCalendar::ConvertDateToYMD(cur_item->info.start_date); SetDParam(0, ymd_cur.year - ymd_start.year); DrawString(years.left, years.right, y + text_y_offset, STR_JUST_INT, TC_BLACK, SA_HOR_CENTER); } diff --git a/src/newgrf.cpp b/src/newgrf.cpp index 72687655ca..b1268a4249 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -6520,8 +6520,7 @@ bool GetGlobalVariable(byte param, uint32_t *value, const GRFFile *grffile) return true; case 0x02: { // detailed date information: month of year (bit 0-7), day of month (bit 8-12), leap year (bit 15), day of year (bit 16-24) - TimerGameCalendar::YearMonthDay ymd; - TimerGameCalendar::ConvertDateToYMD(TimerGameCalendar::date, &ymd); + TimerGameCalendar::YearMonthDay ymd = TimerGameCalendar::ConvertDateToYMD(TimerGameCalendar::date); TimerGameCalendar::Date start_of_year = TimerGameCalendar::ConvertYMDToDate(ymd.year, 0, 1); *value = ymd.month | (ymd.day - 1) << 8 | (TimerGameCalendar::IsLeapYear(ymd.year) ? 1 << 15 : 0) | (TimerGameCalendar::date - start_of_year).base() << 16; return true; diff --git a/src/saveload/oldloader_sl.cpp b/src/saveload/oldloader_sl.cpp index 7589e87708..9668054b9d 100644 --- a/src/saveload/oldloader_sl.cpp +++ b/src/saveload/oldloader_sl.cpp @@ -844,8 +844,7 @@ static bool LoadOldIndustry(LoadgameState *ls, int num) if (i->type > 0x06) i->type++; // Printing Works were added if (i->type == 0x0A) i->type = 0x12; // Iron Ore Mine has different ID - TimerGameCalendar::YearMonthDay ymd; - TimerGameCalendar::ConvertDateToYMD(TimerGameCalendar::date, &ymd); + TimerGameCalendar::YearMonthDay ymd = TimerGameCalendar::ConvertDateToYMD(TimerGameCalendar::date); i->last_prod_year = ymd.year; i->random_colour = RemapTTOColour(i->random_colour); diff --git a/src/script/api/script_date.cpp b/src/script/api/script_date.cpp index d82c2815f4..4d3a3866cf 100644 --- a/src/script/api/script_date.cpp +++ b/src/script/api/script_date.cpp @@ -29,8 +29,7 @@ { if (date < 0) return DATE_INVALID; - ::TimerGameCalendar::YearMonthDay ymd; - ::TimerGameCalendar::ConvertDateToYMD(date, &ymd); + ::TimerGameCalendar::YearMonthDay ymd = ::TimerGameCalendar::ConvertDateToYMD(date); return ymd.year.base(); } @@ -38,8 +37,7 @@ { if (date < 0) return DATE_INVALID; - ::TimerGameCalendar::YearMonthDay ymd; - ::TimerGameCalendar::ConvertDateToYMD(date, &ymd); + ::TimerGameCalendar::YearMonthDay ymd = ::TimerGameCalendar::ConvertDateToYMD(date); return ymd.month + 1; } @@ -47,8 +45,7 @@ { if (date < 0) return DATE_INVALID; - ::TimerGameCalendar::YearMonthDay ymd; - ::TimerGameCalendar::ConvertDateToYMD(date, &ymd); + ::TimerGameCalendar::YearMonthDay ymd = ::TimerGameCalendar::ConvertDateToYMD(date); return ymd.day; } diff --git a/src/strings.cpp b/src/strings.cpp index 841f55d76b..a0f1387972 100644 --- a/src/strings.cpp +++ b/src/strings.cpp @@ -483,8 +483,7 @@ static void FormatBytes(StringBuilder &builder, int64_t number) static void FormatYmdString(StringBuilder &builder, TimerGameCalendar::Date date, uint case_index) { - TimerGameCalendar::YearMonthDay ymd; - TimerGameCalendar::ConvertDateToYMD(date, &ymd); + TimerGameCalendar::YearMonthDay ymd = TimerGameCalendar::ConvertDateToYMD(date); auto tmp_params = MakeParameters(ymd.day + STR_DAY_NUMBER_1ST - 1, STR_MONTH_ABBREV_JAN + ymd.month, ymd.year); FormatString(builder, GetStringPtr(STR_FORMAT_DATE_LONG), tmp_params, case_index); @@ -492,8 +491,7 @@ static void FormatYmdString(StringBuilder &builder, TimerGameCalendar::Date date static void FormatMonthAndYear(StringBuilder &builder, TimerGameCalendar::Date date, uint case_index) { - TimerGameCalendar::YearMonthDay ymd; - TimerGameCalendar::ConvertDateToYMD(date, &ymd); + TimerGameCalendar::YearMonthDay ymd = TimerGameCalendar::ConvertDateToYMD(date); auto tmp_params = MakeParameters(STR_MONTH_JAN + ymd.month, ymd.year); FormatString(builder, GetStringPtr(STR_FORMAT_DATE_SHORT), tmp_params, case_index); @@ -501,8 +499,7 @@ static void FormatMonthAndYear(StringBuilder &builder, TimerGameCalendar::Date d static void FormatTinyOrISODate(StringBuilder &builder, TimerGameCalendar::Date date, StringID str) { - TimerGameCalendar::YearMonthDay ymd; - TimerGameCalendar::ConvertDateToYMD(date, &ymd); + TimerGameCalendar::YearMonthDay ymd = TimerGameCalendar::ConvertDateToYMD(date); /* Day and month are zero-padded with ZEROFILL_NUM, hence the two 2s. */ auto tmp_params = MakeParameters(ymd.day, 2, ymd.month + 1, 2, ymd.year); diff --git a/src/subsidy_gui.cpp b/src/subsidy_gui.cpp index c55c9409b4..68837bb6b2 100644 --- a/src/subsidy_gui.cpp +++ b/src/subsidy_gui.cpp @@ -142,8 +142,7 @@ struct SubsidyListWindow : Window { { if (widget != WID_SUL_PANEL) return; - TimerGameCalendar::YearMonthDay ymd; - TimerGameCalendar::ConvertDateToYMD(TimerGameCalendar::date, &ymd); + TimerGameCalendar::YearMonthDay ymd = TimerGameCalendar::ConvertDateToYMD(TimerGameCalendar::date); Rect tr = r.Shrink(WidgetDimensions::scaled.framerect); diff --git a/src/survey.cpp b/src/survey.cpp index f9d0ac3ca8..046291ee35 100644 --- a/src/survey.cpp +++ b/src/survey.cpp @@ -311,8 +311,7 @@ void SurveyTimers(nlohmann::json &survey) survey["ticks"] = TimerGameTick::counter; survey["seconds"] = std::chrono::duration_cast(std::chrono::steady_clock::now() - _switch_mode_time).count(); - TimerGameCalendar::YearMonthDay ymd; - TimerGameCalendar::ConvertDateToYMD(TimerGameCalendar::date, &ymd); + TimerGameCalendar::YearMonthDay ymd = TimerGameCalendar::ConvertDateToYMD(TimerGameCalendar::date); survey["calendar"] = fmt::format("{:04}-{:02}-{:02} ({})", ymd.year, ymd.month + 1, ymd.day, TimerGameCalendar::date_fract); } diff --git a/src/timer/timer_game_calendar.cpp b/src/timer/timer_game_calendar.cpp index 4b62da7f6a..369b002cd2 100644 --- a/src/timer/timer_game_calendar.cpp +++ b/src/timer/timer_game_calendar.cpp @@ -66,9 +66,9 @@ static const uint16_t _accum_days_for_month[] = { /** * Converts a Date to a Year, Month & Day. * @param date the date to convert from - * @param ymd the year, month and day to write to + * @returns YearMonthDay representation of the Date. */ -/* static */ void TimerGameCalendar::ConvertDateToYMD(TimerGameCalendar::Date date, TimerGameCalendar::YearMonthDay *ymd) +/* static */ TimerGameCalendar::YearMonthDay TimerGameCalendar::ConvertDateToYMD(TimerGameCalendar::Date date) { /* Year determination in multiple steps to account for leap * years. First do the large steps, then the smaller ones. @@ -77,7 +77,6 @@ static const uint16_t _accum_days_for_month[] = { /* There are 97 leap years in 400 years */ TimerGameCalendar::Year yr = 400 * (date.base() / (CalendarTime::DAYS_IN_YEAR * 400 + 97)); int rem = date.base() % (CalendarTime::DAYS_IN_YEAR * 400 + 97); - uint16_t x; if (rem >= CalendarTime::DAYS_IN_YEAR * 100 + 25) { /* There are 25 leap years in the first 100 years after @@ -110,11 +109,13 @@ static const uint16_t _accum_days_for_month[] = { /* Skip the 29th of February in non-leap years */ if (!TimerGameCalendar::IsLeapYear(yr) && rem >= ACCUM_MAR - 1) rem++; - ymd->year = yr; + uint16_t x = _month_date_from_year_day[rem]; - x = _month_date_from_year_day[rem]; - ymd->month = x >> 5; - ymd->day = x & 0x1F; + YearMonthDay ymd; + ymd.year = yr; + ymd.month = x >> 5; + ymd.day = x & 0x1F; + return ymd; } /** @@ -153,11 +154,9 @@ static const uint16_t _accum_days_for_month[] = { { assert(fract < Ticks::DAY_TICKS); - TimerGameCalendar::YearMonthDay ymd; - TimerGameCalendar::date = date; TimerGameCalendar::date_fract = fract; - TimerGameCalendar::ConvertDateToYMD(date, &ymd); + TimerGameCalendar::YearMonthDay ymd = TimerGameCalendar::ConvertDateToYMD(date); TimerGameCalendar::year = ymd.year; TimerGameCalendar::month = ymd.month; } @@ -195,8 +194,7 @@ void TimerManager::Elapsed([[maybe_unused]] TimerGameCalendar /* increase day counter */ TimerGameCalendar::date++; - TimerGameCalendar::YearMonthDay ymd; - TimerGameCalendar::ConvertDateToYMD(TimerGameCalendar::date, &ymd); + TimerGameCalendar::YearMonthDay ymd = TimerGameCalendar::ConvertDateToYMD(TimerGameCalendar::date); /* check if we entered a new month? */ bool new_month = ymd.month != TimerGameCalendar::month; diff --git a/src/timer/timer_game_calendar.h b/src/timer/timer_game_calendar.h index 0b82db80c6..ab29063f54 100644 --- a/src/timer/timer_game_calendar.h +++ b/src/timer/timer_game_calendar.h @@ -101,7 +101,7 @@ public: }; static bool IsLeapYear(Year yr); - static void ConvertDateToYMD(Date date, YearMonthDay * ymd); + static YearMonthDay ConvertDateToYMD(Date date); static Date ConvertYMDToDate(Year year, Month month, Day day); static void SetDate(Date date, DateFract fract); From 3b18877b87d59b781398e6aa84133efeca843a25 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Thu, 28 Dec 2023 21:43:05 +0000 Subject: [PATCH 5/7] Fix #11629: AirportGetNearestTown for rotated airports (#11631) Add rotation parameter to AirportGetNearestTown Add wrapper for existing stations Remove unnecessary iterator cloning --- src/script/api/script_airport.cpp | 5 ++-- src/station_cmd.cpp | 46 +++++++++++++++++++------------ src/station_cmd.h | 2 +- 3 files changed, 32 insertions(+), 21 deletions(-) diff --git a/src/script/api/script_airport.cpp b/src/script/api/script_airport.cpp index c0b28408c7..81e24fe0f6 100644 --- a/src/script/api/script_airport.cpp +++ b/src/script/api/script_airport.cpp @@ -137,9 +137,8 @@ if (!as->IsWithinMapBounds(0, tile)) return -1; if (_settings_game.economy.station_noise_level) { - AirportTileTableIterator it(as->table[0], tile); uint dist; - AirportGetNearestTown(as, tile, it, dist); + AirportGetNearestTown(as, as->rotation[0], tile, AirportTileTableIterator(as->table[0], tile), dist); return GetAirportNoiseLevelForDistance(as, dist); } @@ -155,7 +154,7 @@ if (!as->IsWithinMapBounds(0, tile)) return INVALID_TOWN; uint dist; - return AirportGetNearestTown(as, tile, AirportTileTableIterator(as->table[0], tile), dist)->index; + return AirportGetNearestTown(as, as->rotation[0], tile, AirportTileTableIterator(as->table[0], tile), dist)->index; } /* static */ SQInteger ScriptAirport::GetMaintenanceCostFactor(AirportType type) diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index 619bf02aea..230e7dac3c 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -2303,28 +2303,32 @@ uint8_t GetAirportNoiseLevelForDistance(const AirportSpec *as, uint distance) * Finds the town nearest to given airport. Based on minimal manhattan distance to any airport's tile. * If two towns have the same distance, town with lower index is returned. * @param as airport's description + * @param rotation airport's rotation * @param tile origin tile (top corner of the airport) - * @param it An iterator over all airport tiles + * @param it An iterator over all airport tiles (consumed) * @param[out] mindist Minimum distance to town * @return nearest town to airport */ -Town *AirportGetNearestTown(const AirportSpec *as, TileIndex tile, const TileIterator &it, uint &mindist) +Town *AirportGetNearestTown(const AirportSpec *as, Direction rotation, TileIndex tile, TileIterator &&it, uint &mindist) { assert(Town::GetNumItems() > 0); Town *nearest = nullptr; + auto width = as->size_x; + auto height = as->size_y; + if (rotation == DIR_E || rotation == DIR_W) std::swap(width, height); + uint perimeter_min_x = TileX(tile); uint perimeter_min_y = TileY(tile); - uint perimeter_max_x = perimeter_min_x + as->size_x - 1; - uint perimeter_max_y = perimeter_min_y + as->size_y - 1; + uint perimeter_max_x = perimeter_min_x + width - 1; + uint perimeter_max_y = perimeter_min_y + height - 1; mindist = UINT_MAX - 1; // prevent overflow - std::unique_ptr copy(it.Clone()); - for (TileIndex cur_tile = *copy; cur_tile != INVALID_TILE; cur_tile = ++*copy) { - assert(IsInsideBS(TileX(cur_tile), perimeter_min_x, as->size_x)); - assert(IsInsideBS(TileY(cur_tile), perimeter_min_y, as->size_y)); + for (TileIndex cur_tile = *it; cur_tile != INVALID_TILE; cur_tile = ++it) { + assert(IsInsideBS(TileX(cur_tile), perimeter_min_x, width)); + assert(IsInsideBS(TileY(cur_tile), perimeter_min_y, height)); if (TileX(cur_tile) == perimeter_min_x || TileX(cur_tile) == perimeter_max_x || TileY(cur_tile) == perimeter_min_y || TileY(cur_tile) == perimeter_max_y) { Town *t = CalcClosestTownFromTile(cur_tile, mindist + 1); if (t == nullptr) continue; @@ -2341,6 +2345,18 @@ Town *AirportGetNearestTown(const AirportSpec *as, TileIndex tile, const TileIte return nearest; } +/** + * Finds the town nearest to given existing airport. Based on minimal manhattan distance to any airport's tile. + * If two towns have the same distance, town with lower index is returned. + * @param station existing station with airport + * @param[out] mindist Minimum distance to town + * @return nearest town to airport + */ +static Town *AirportGetNearestTown(const Station *st, uint &mindist) +{ + return AirportGetNearestTown(st->airport.GetSpec(), st->airport.rotation, st->airport.tile, AirportTileIterator(st), mindist); +} + /** Recalculate the noise generated by the airports of each town */ void UpdateAirportsNoise() @@ -2349,11 +2365,9 @@ void UpdateAirportsNoise() for (const Station *st : Station::Iterate()) { if (st->airport.tile != INVALID_TILE && st->airport.type != AT_OILRIG) { - const AirportSpec *as = st->airport.GetSpec(); - AirportTileIterator it(st); uint dist; - Town *nearest = AirportGetNearestTown(as, st->airport.tile, it, dist); - nearest->noise_reached += GetAirportNoiseLevelForDistance(as, dist); + Town *nearest = AirportGetNearestTown(st, dist); + nearest->noise_reached += GetAirportNoiseLevelForDistance(st->airport.GetSpec(), dist); } } } @@ -2402,7 +2416,7 @@ CommandCost CmdBuildAirport(DoCommandFlag flags, TileIndex tile, byte airport_ty /* The noise level is the noise from the airport and reduce it to account for the distance to the town center. */ uint dist; - Town *nearest = AirportGetNearestTown(as, tile, tile_iter, dist); + Town *nearest = AirportGetNearestTown(as, rotation, tile, std::move(tile_iter), dist); uint newnoise_level = GetAirportNoiseLevelForDistance(as, dist); /* Check if local auth would allow a new airport */ @@ -2524,14 +2538,12 @@ static CommandCost RemoveAirport(TileIndex tile, DoCommandFlag flags) CloseWindowById(WC_VEHICLE_DEPOT, tile_cur); } - const AirportSpec *as = st->airport.GetSpec(); /* The noise level is the noise from the airport and reduce it to account for the distance to the town center. * And as for construction, always remove it, even if the setting is not set, in order to avoid the * need of recalculation */ - AirportTileIterator it(st); uint dist; - Town *nearest = AirportGetNearestTown(as, st->airport.tile, it, dist); - nearest->noise_reached -= GetAirportNoiseLevelForDistance(as, dist); + Town *nearest = AirportGetNearestTown(st, dist); + nearest->noise_reached -= GetAirportNoiseLevelForDistance(st->airport.GetSpec(), dist); if (_settings_game.economy.station_noise_level) { SetWindowDirty(WC_TOWN_VIEW, nearest->index); diff --git a/src/station_cmd.h b/src/station_cmd.h index 38f393fd00..ed3a117653 100644 --- a/src/station_cmd.h +++ b/src/station_cmd.h @@ -16,7 +16,7 @@ enum StationClassID : byte; enum RoadStopClassID : byte; -extern Town *AirportGetNearestTown(const struct AirportSpec *as, TileIndex tile, const TileIterator &it, uint &mindist); +extern Town *AirportGetNearestTown(const struct AirportSpec *as, Direction rotation, TileIndex tile, TileIterator &&it, uint &mindist); extern uint8_t GetAirportNoiseLevelForDistance(const struct AirportSpec *as, uint distance); CommandCost CmdBuildAirport(DoCommandFlag flags, TileIndex tile, byte airport_type, byte layout, StationID station_to_join, bool allow_adjacent); From bfb42542266ff0816d87ab5583ee2adb6ffb3b68 Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Wed, 27 Dec 2023 15:26:33 +0000 Subject: [PATCH 6/7] Fix: Changing default livery did not propagate to group liveries. #11614 attempted to address this but did not handle 2CC properly, and changes to the default livery were not handled. --- src/company_cmd.cpp | 22 ++++++++++++++------ src/company_func.h | 1 + src/company_gui.cpp | 15 +++++++------- src/group.h | 1 + src/group_cmd.cpp | 42 +++++++++++++++++++++++++++----------- src/saveload/afterload.cpp | 4 ++++ 6 files changed, 59 insertions(+), 26 deletions(-) diff --git a/src/company_cmd.cpp b/src/company_cmd.cpp index 0e13ea05e5..5413ba437c 100644 --- a/src/company_cmd.cpp +++ b/src/company_cmd.cpp @@ -949,6 +949,20 @@ CommandCost CmdSetCompanyManagerFace(DoCommandFlag flags, CompanyManagerFace cmf return CommandCost(); } +/** + * Update liveries for a company. This is called when the LS_DEFAULT scheme is changed, to update schemes with colours + * set to default. + * @param c Company to update. + */ +void UpdateCompanyLiveries(Company *c) +{ + for (int i = 1; i < LS_END; i++) { + if (!HasBit(c->livery[i].in_use, 0)) c->livery[i].colour1 = c->livery[LS_DEFAULT].colour1; + if (!HasBit(c->livery[i].in_use, 1)) c->livery[i].colour2 = c->livery[LS_DEFAULT].colour2; + } + UpdateCompanyGroupLiveries(c); +} + /** * Change the company's company-colour * @param flags operation to perform @@ -982,9 +996,7 @@ CommandCost CmdSetCompanyColour(DoCommandFlag flags, LiveryScheme scheme, bool p /* If setting the first colour of the default scheme, adjust the * original and cached company colours too. */ if (scheme == LS_DEFAULT) { - for (int i = 1; i < LS_END; i++) { - if (!HasBit(c->livery[i].in_use, 0)) c->livery[i].colour1 = colour; - } + UpdateCompanyLiveries(c); _company_colours[_current_company] = colour; c->colour = colour; CompanyAdminUpdate(c); @@ -995,9 +1007,7 @@ CommandCost CmdSetCompanyColour(DoCommandFlag flags, LiveryScheme scheme, bool p c->livery[scheme].colour2 = colour; if (scheme == LS_DEFAULT) { - for (int i = 1; i < LS_END; i++) { - if (!HasBit(c->livery[i].in_use, 1)) c->livery[i].colour2 = colour; - } + UpdateCompanyGroupLiveries(c); } } diff --git a/src/company_func.h b/src/company_func.h index 60b70fbf97..3f43e7530e 100644 --- a/src/company_func.h +++ b/src/company_func.h @@ -24,6 +24,7 @@ void ShowBuyCompanyDialog(CompanyID company, bool hostile_takeover); void CompanyAdminUpdate(const Company *company); void CompanyAdminBankrupt(CompanyID company_id); void UpdateLandscapingLimits(); +void UpdateCompanyLiveries(Company *c); bool CheckCompanyHasMoney(CommandCost &cost); void SubtractMoneyFromCompany(const CommandCost& cost); diff --git a/src/company_gui.cpp b/src/company_gui.cpp index 0b55641d17..a19430b3b6 100644 --- a/src/company_gui.cpp +++ b/src/company_gui.cpp @@ -907,18 +907,18 @@ public: int y = ir.top; /* Helper function to draw livery info. */ - auto draw_livery = [&](StringID str, const Livery &liv, bool sel, bool def, int indent) { + auto draw_livery = [&](StringID str, const Livery &livery, bool is_selected, bool is_default_scheme, int indent) { /* Livery Label. */ - DrawString(sch.left + (rtl ? 0 : indent), sch.right - (rtl ? indent : 0), y + text_offs, str, sel ? TC_WHITE : TC_BLACK); + DrawString(sch.left + (rtl ? 0 : indent), sch.right - (rtl ? indent : 0), y + text_offs, str, is_selected ? TC_WHITE : TC_BLACK); /* Text below the first dropdown. */ - DrawSprite(SPR_SQUARE, GENERAL_SPRITE_COLOUR(liv.colour1), pri_squ.left, y + square_offs); - DrawString(pri.left, pri.right, y + text_offs, (def || HasBit(liv.in_use, 0)) ? STR_COLOUR_DARK_BLUE + liv.colour1 : STR_COLOUR_DEFAULT, sel ? TC_WHITE : TC_GOLD); + DrawSprite(SPR_SQUARE, GENERAL_SPRITE_COLOUR(livery.colour1), pri_squ.left, y + square_offs); + DrawString(pri.left, pri.right, y + text_offs, (is_default_scheme || HasBit(livery.in_use, 0)) ? STR_COLOUR_DARK_BLUE + livery.colour1 : STR_COLOUR_DEFAULT, is_selected ? TC_WHITE : TC_GOLD); /* Text below the second dropdown. */ if (sec.right > sec.left) { // Second dropdown has non-zero size. - DrawSprite(SPR_SQUARE, GENERAL_SPRITE_COLOUR(liv.colour2), sec_squ.left, y + square_offs); - DrawString(sec.left, sec.right, y + text_offs, (def || HasBit(liv.in_use, 1)) ? STR_COLOUR_DARK_BLUE + liv.colour2 : STR_COLOUR_DEFAULT, sel ? TC_WHITE : TC_GOLD); + DrawSprite(SPR_SQUARE, GENERAL_SPRITE_COLOUR(livery.colour2), sec_squ.left, y + square_offs); + DrawString(sec.left, sec.right, y + text_offs, (is_default_scheme || HasBit(livery.in_use, 1)) ? STR_COLOUR_DARK_BLUE + livery.colour2 : STR_COLOUR_DEFAULT, is_selected ? TC_WHITE : TC_GOLD); } y += this->line_height; @@ -938,9 +938,8 @@ public: uint max = static_cast(std::min(this->vscroll->GetPosition() + this->vscroll->GetCapacity(), this->groups.size())); for (uint i = this->vscroll->GetPosition(); i < max; ++i) { const Group *g = this->groups[i]; - const bool livery_set = HasBit(g->livery.in_use, 0); 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); + draw_livery(STR_GROUP_NAME, g->livery, this->sel == g->index, false, this->indents[i] * WidgetDimensions::scaled.hsep_indent); } if (this->vscroll->GetCount() == 0) { diff --git a/src/group.h b/src/group.h index 05a203a53c..e664d22e4d 100644 --- a/src/group.h +++ b/src/group.h @@ -112,5 +112,6 @@ void SetTrainGroupID(Train *v, GroupID grp); void UpdateTrainGroupID(Train *v); void RemoveAllGroupsForCompany(const CompanyID company); bool GroupIsInGroup(GroupID search, GroupID group); +void UpdateCompanyGroupLiveries(const Company *c); #endif /* GROUP_H */ diff --git a/src/group_cmd.cpp b/src/group_cmd.cpp index 4fded9ebbf..a908fb830e 100644 --- a/src/group_cmd.cpp +++ b/src/group_cmd.cpp @@ -275,17 +275,20 @@ const Livery *GetParentLivery(const Group *g) /** - * Propagate a livery change to a group's children. - * @param g Group. + * Propagate a livery change to a group's children, and optionally update cached vehicle colourmaps. + * @param g Group to propagate colours to children. + * @param reset_cache Reset colourmap of vehicles in this group. */ -void PropagateChildLivery(const Group *g) +static void PropagateChildLivery(const Group *g, bool reset_cache) { - /* Company colour data is indirectly cached. */ - for (Vehicle *v : Vehicle::Iterate()) { - if (v->group_id == g->index && (!v->IsGroundVehicle() || v->IsFrontEngine())) { - for (Vehicle *u = v; u != nullptr; u = u->Next()) { - u->colourmap = PAL_NONE; - u->InvalidateNewGRFCache(); + if (reset_cache) { + /* Company colour data is indirectly cached. */ + for (Vehicle *v : Vehicle::Iterate()) { + if (v->group_id == g->index && (!v->IsGroundVehicle() || v->IsFrontEngine())) { + for (Vehicle *u = v; u != nullptr; u = u->Next()) { + u->colourmap = PAL_NONE; + u->InvalidateNewGRFCache(); + } } } } @@ -294,11 +297,26 @@ void PropagateChildLivery(const Group *g) if (cg->parent == g->index) { if (!HasBit(cg->livery.in_use, 0)) cg->livery.colour1 = g->livery.colour1; if (!HasBit(cg->livery.in_use, 1)) cg->livery.colour2 = g->livery.colour2; - PropagateChildLivery(cg); + PropagateChildLivery(cg, reset_cache); } } } +/** + * Update group liveries for a company. This is called when the LS_DEFAULT scheme is changed, to update groups with + * colours set to default. + * @param c Company to update. + */ +void UpdateCompanyGroupLiveries(const Company *c) +{ + for (Group *g : Group::Iterate()) { + if (g->owner == c->index && g->parent == INVALID_GROUP) { + if (!HasBit(g->livery.in_use, 0)) g->livery.colour1 = c->livery[LS_DEFAULT].colour1; + if (!HasBit(g->livery.in_use, 1)) g->livery.colour2 = c->livery[LS_DEFAULT].colour2; + PropagateChildLivery(g, false); + } + } +} Group::Group(Owner owner) { @@ -453,7 +471,7 @@ CommandCost CmdAlterGroup(DoCommandFlag flags, AlterGroupMode mode, GroupID grou g->livery.colour1 = livery->colour1; g->livery.colour2 = livery->colour2; - PropagateChildLivery(g); + PropagateChildLivery(g, true); MarkWholeScreenDirty(); } } @@ -661,7 +679,7 @@ CommandCost CmdSetGroupLivery(DoCommandFlag flags, GroupID group_id, bool primar g->livery.colour2 = colour; } - PropagateChildLivery(g); + PropagateChildLivery(g, true); MarkWholeScreenDirty(); } diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index bc0c7253a8..ac75e3abcb 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -3262,6 +3262,10 @@ bool AfterLoadGame() } } + for (Company *c : Company::Iterate()) { + UpdateCompanyLiveries(c); + } + AfterLoadLabelMaps(); AfterLoadCompanyStats(); AfterLoadStoryBook(); From 5d2ed80c95673dc73f390c3b5d007caffc8bb17d Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Wed, 27 Dec 2023 20:25:38 +0000 Subject: [PATCH 7/7] Fix: Changing group parent did not properly update partially-default liveries. --- src/group_cmd.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/group_cmd.cpp b/src/group_cmd.cpp index a908fb830e..a96d65585c 100644 --- a/src/group_cmd.cpp +++ b/src/group_cmd.cpp @@ -466,10 +466,11 @@ CommandCost CmdAlterGroup(DoCommandFlag flags, AlterGroupMode mode, GroupID grou g->parent = (pg == nullptr) ? INVALID_GROUP : pg->index; GroupStatistics::UpdateAutoreplace(g->owner); - if (g->livery.in_use == 0) { + if (!HasBit(g->livery.in_use, 0) || !HasBit(g->livery.in_use, 1)) { + /* Update livery with new parent's colours if either colour is default. */ const Livery *livery = GetParentLivery(g); - g->livery.colour1 = livery->colour1; - g->livery.colour2 = livery->colour2; + if (!HasBit(g->livery.in_use, 0)) g->livery.colour1 = livery->colour1; + if (!HasBit(g->livery.in_use, 1)) g->livery.colour2 = livery->colour2; PropagateChildLivery(g, true); MarkWholeScreenDirty();