diff --git a/COMPILING.md b/COMPILING.md index 66708e751d..352aa3df93 100644 --- a/COMPILING.md +++ b/COMPILING.md @@ -29,7 +29,7 @@ open most older savegames or use the content downloading system. ## Windows -You need Microsoft Visual Studio 2017 or more recent. +You need Microsoft Visual Studio 2022 or more recent. You can download the free Visual Studio Community Edition from Microsoft at https://visualstudio.microsoft.com/vs/community/. @@ -65,7 +65,7 @@ To install both the x64 (64bit) and x86 (32bit) variants (though only one is nec You can open the folder (as a CMake project). CMake will be detected, and you can compile from there. If libraries are installed but not found, you need to set VCPKG_TARGET_TRIPLET in CMake parameters. -For Visual Studio 2017 you also need to set CMAKE_TOOLCHAIN_FILE. +For Visual Studio 2022 you also need to set CMAKE_TOOLCHAIN_FILE. (Typical values are shown in the MSVC project file command line example) Alternatively, you can create a MSVC project file via CMake. For this @@ -75,7 +75,7 @@ that comes with vcpkg. After that, you can run something similar to this: ```powershell mkdir build cd build -cmake.exe .. -G"Visual Studio 16 2019" -DCMAKE_TOOLCHAIN_FILE="\vcpkg\scripts\buildsystems\vcpkg.cmake" -DVCPKG_TARGET_TRIPLET="x64-windows-static" +cmake.exe .. -G"Visual Studio 17 2022" -DCMAKE_TOOLCHAIN_FILE="\vcpkg\scripts\buildsystems\vcpkg.cmake" -DVCPKG_TARGET_TRIPLET="x64-windows-static" ``` Change `` to where you have installed vcpkg. After this @@ -83,7 +83,7 @@ in the build folder are MSVC project files. MSVC can rebuild the project files himself via the `ZERO_CHECK` project. ## All other platforms -Minimum required version of CMake is 3.9. +Minimum required version of CMake is 3.16. By default this produces a Debug build with assertations enabled. This is a far slower build than release builds. @@ -115,9 +115,9 @@ builds. ## Supported compilers -Every compiler that is supported by CMake and supports C++17, should be +Every compiler that is supported by CMake and supports C++20, should be able to compile OpenTTD. As the exact list of compilers changes constantly, -we refer to the compiler manual to see if it supports C++17, and to CMake +we refer to the compiler manual to see if it supports C++20, and to CMake to see if it supports your compiler. ## Compilation of base sets diff --git a/src/bootstrap_gui.cpp b/src/bootstrap_gui.cpp index 4093b9484e..4ea757429d 100644 --- a/src/bootstrap_gui.cpp +++ b/src/bootstrap_gui.cpp @@ -290,10 +290,10 @@ public: # include "video/video_driver.hpp" class BootstrapEmscripten : public ContentCallback { - bool downloading{false}; - uint total_files{0}; - uint total_bytes{0}; - uint downloaded_bytes{0}; + bool downloading = false; + uint total_files = 0; + uint total_bytes = 0; + uint downloaded_bytes = 0; public: BootstrapEmscripten() diff --git a/src/build_vehicle_gui.cpp b/src/build_vehicle_gui.cpp index 3fecfe8996..22e86a3dfb 100644 --- a/src/build_vehicle_gui.cpp +++ b/src/build_vehicle_gui.cpp @@ -1658,7 +1658,7 @@ struct BuildVehicleWindow : BuildVehicleWindowBase { /* Select the first unshaded engine in the list as default when opening the window */ EngineID engine = INVALID_ENGINE; - auto it = std::find_if(this->eng_list.begin(), this->eng_list.end(), [&](GUIEngineListItem &item){ return (item.flags & EngineDisplayFlags::Shaded) == EngineDisplayFlags::None; }); + auto it = std::find_if(this->eng_list.begin(), this->eng_list.end(), [&](GUIEngineListItem &item) { return (item.flags & EngineDisplayFlags::Shaded) == EngineDisplayFlags::None; }); if (it != this->eng_list.end()) engine = it->engine_id; this->SelectEngine(engine); } diff --git a/src/cargotype.h b/src/cargotype.h index f8737a6fe4..e13d0aada6 100644 --- a/src/cargotype.h +++ b/src/cargotype.h @@ -67,21 +67,21 @@ static const uint TOWN_PRODUCTION_DIVISOR = 256; /** Specification of a cargo type. */ struct CargoSpec { - CargoLabel label; ///< Unique label of the cargo type. - uint8_t bitnum{INVALID_CARGO_BITNUM}; ///< Cargo bit number, is #INVALID_CARGO_BITNUM for a non-used spec. + CargoLabel label; ///< Unique label of the cargo type. + uint8_t bitnum = INVALID_CARGO_BITNUM; ///< Cargo bit number, is #INVALID_CARGO_BITNUM for a non-used spec. uint8_t legend_colour; uint8_t rating_colour; - uint8_t weight; ///< Weight of a single unit of this cargo type in 1/16 ton (62.5 kg). - uint16_t multiplier{0x100}; ///< Capacity multiplier for vehicles. (8 fractional bits) - uint16_t classes; ///< Classes of this cargo type. @see CargoClass - int32_t initial_payment; ///< Initial payment rate before inflation is applied. + uint8_t weight; ///< Weight of a single unit of this cargo type in 1/16 ton (62.5 kg). + uint16_t multiplier = 0x100; ///< Capacity multiplier for vehicles. (8 fractional bits) + uint16_t classes; ///< Classes of this cargo type. @see CargoClass + int32_t initial_payment; ///< Initial payment rate before inflation is applied. uint8_t transit_periods[2]; - bool is_freight; ///< Cargo type is considered to be freight (affects train freight multiplier). - TownAcceptanceEffect town_acceptance_effect; ///< The effect that delivering this cargo type has on towns. Also affects destination of subsidies. - TownProductionEffect town_production_effect{INVALID_TPE}; ///< The effect on town cargo production. - uint16_t town_production_multiplier{TOWN_PRODUCTION_DIVISOR}; ///< Town production multipler, if commanded by TownProductionEffect. - uint8_t callback_mask; ///< Bitmask of cargo callbacks that have to be called + bool is_freight; ///< Cargo type is considered to be freight (affects train freight multiplier). + TownAcceptanceEffect town_acceptance_effect; ///< The effect that delivering this cargo type has on towns. Also affects destination of subsidies. + TownProductionEffect town_production_effect = INVALID_TPE; ///< The effect on town cargo production. + uint16_t town_production_multiplier = TOWN_PRODUCTION_DIVISOR; ///< Town production multipler, if commanded by TownProductionEffect. + uint8_t callback_mask; ///< Bitmask of cargo callbacks that have to be called StringID name; ///< Name of this type of cargo. StringID name_single; ///< Name of a single entity of this type of cargo. diff --git a/src/console_cmds.cpp b/src/console_cmds.cpp index 5f4fe13f68..82a57dce56 100644 --- a/src/console_cmds.cpp +++ b/src/console_cmds.cpp @@ -2440,10 +2440,10 @@ DEF_CONSOLE_CMD(ConFont) IConsolePrint(CC_HELP, " Print out the fonts configuration."); IConsolePrint(CC_HELP, " The \"Currently active\" configuration is the one actually in effect (after interface scaling and replacing unavailable fonts)."); IConsolePrint(CC_HELP, " The \"Requested\" configuration is the one requested via console command or config file."); - IConsolePrint(CC_HELP, "Usage 'font [medium|small|large|mono] [] [] [aa|noaa]'."); + IConsolePrint(CC_HELP, "Usage 'font [medium|small|large|mono] [] []'."); IConsolePrint(CC_HELP, " Change the configuration for a font."); IConsolePrint(CC_HELP, " Omitting an argument will keep the current value."); - IConsolePrint(CC_HELP, " Set to \"\" for the default font. Note that and aa/noaa have no effect if the default font is in use, and fixed defaults are used instead."); + IConsolePrint(CC_HELP, " Set to \"\" for the default font. Note that has no effect if the default font is in use, and fixed defaults are used instead."); IConsolePrint(CC_HELP, " If the sprite font is enabled in Game Options, it is used instead of the default font."); IConsolePrint(CC_HELP, " The is automatically multiplied by the current interface scaling."); return true; @@ -2461,38 +2461,23 @@ DEF_CONSOLE_CMD(ConFont) FontCacheSubSetting *setting = GetFontCacheSubSetting(argfs); std::string font = setting->font; uint size = setting->size; - bool aa = setting->aa; - + uint v; uint8_t arg_index = 2; - /* We may encounter "aa" or "noaa" but it must be the last argument. */ - if (StrEqualsIgnoreCase(argv[arg_index], "aa") || StrEqualsIgnoreCase(argv[arg_index], "noaa")) { - aa = !StrStartsWithIgnoreCase(argv[arg_index++], "no"); - if (argc > arg_index) return false; - } else { - /* For we want a string. */ - uint v; - if (!GetArgumentInteger(&v, argv[arg_index])) { - font = argv[arg_index++]; - } + /* For we want a string. */ + + if (!GetArgumentInteger(&v, argv[arg_index])) { + font = argv[arg_index++]; } if (argc > arg_index) { /* For we want a number. */ - uint v; if (GetArgumentInteger(&v, argv[arg_index])) { size = v; arg_index++; } } - if (argc > arg_index) { - /* Last argument must be "aa" or "noaa". */ - if (!StrEqualsIgnoreCase(argv[arg_index], "aa") && !StrEqualsIgnoreCase(argv[arg_index], "noaa")) return false; - aa = !StrStartsWithIgnoreCase(argv[arg_index++], "no"); - if (argc > arg_index) return false; - } - - SetFont(argfs, font, size, aa); + SetFont(argfs, font, size); } for (FontSize fs = FS_BEGIN; fs < FS_END; fs++) { @@ -2504,8 +2489,8 @@ DEF_CONSOLE_CMD(ConFont) fc = FontCache::Get(fs); } IConsolePrint(CC_DEFAULT, "{} font:", FontSizeToName(fs)); - IConsolePrint(CC_DEFAULT, "Currently active: \"{}\", size {}, {}", fc->GetFontName(), fc->GetFontSize(), GetFontAAState(fs) ? "aa" : "noaa"); - IConsolePrint(CC_DEFAULT, "Requested: \"{}\", size {}, {}", setting->font, setting->size, setting->aa ? "aa" : "noaa"); + IConsolePrint(CC_DEFAULT, "Currently active: \"{}\", size {}", fc->GetFontName(), fc->GetFontSize()); + IConsolePrint(CC_DEFAULT, "Requested: \"{}\", size {}", setting->font, setting->size); } FontChanged(); diff --git a/src/fontcache.cpp b/src/fontcache.cpp index 543ed7d73e..c7c9226c19 100644 --- a/src/fontcache.cpp +++ b/src/fontcache.cpp @@ -74,15 +74,15 @@ void UpdateFontHeightCache() } /* Check if a glyph should be rendered with anti-aliasing. */ -bool GetFontAAState(FontSize size, bool check_blitter) +bool GetFontAAState() { /* AA is only supported for 32 bpp */ - if (check_blitter && BlitterFactory::GetCurrentBlitter()->GetScreenDepth() != 32) return false; + if (BlitterFactory::GetCurrentBlitter()->GetScreenDepth() != 32) return false; - return _fcsettings.global_aa || GetFontCacheSubSetting(size)->aa; + return _fcsettings.global_aa; } -void SetFont(FontSize fontsize, const std::string &font, uint size, bool aa) +void SetFont(FontSize fontsize, const std::string &font, uint size) { FontCacheSubSetting *setting = GetFontCacheSubSetting(fontsize); bool changed = false; @@ -97,11 +97,6 @@ void SetFont(FontSize fontsize, const std::string &font, uint size, bool aa) changed = true; } - if (setting->aa != aa) { - setting->aa = aa; - changed = true; - } - if (!changed) return; if (fontsize != FS_MONO) { @@ -216,19 +211,6 @@ void UninitFontCache() #endif /* WITH_FREETYPE */ } -/** - * Should any of the active fonts be anti-aliased? - * @return True if any of the loaded fonts want anti-aliased drawing. - */ -bool HasAntialiasedFonts() -{ - for (FontSize fs = FS_BEGIN; fs < FS_END; fs++) { - if (!FontCache::Get(fs)->IsBuiltInFont() && GetFontAAState(fs, false)) return true; - } - - return false; -} - #if !defined(_WIN32) && !defined(__APPLE__) && !defined(WITH_FONTCONFIG) && !defined(WITH_COCOA) bool SetFallbackFont(FontCacheSettings *, const std::string &, int, MissingGlyphSearcher *) { return false; } diff --git a/src/fontcache.h b/src/fontcache.h index 6c47953105..e563ac7451 100644 --- a/src/fontcache.h +++ b/src/fontcache.h @@ -211,7 +211,6 @@ inline bool GetDrawGlyphShadow(FontSize size) struct FontCacheSubSetting { std::string font; ///< The name of the font, or path to the font. uint size; ///< The (requested) size of the font. - bool aa; ///< Whether to do anti aliasing or not. const void *os_handle = nullptr; ///< Optional native OS font info. Only valid during font search. }; @@ -246,9 +245,8 @@ inline FontCacheSubSetting *GetFontCacheSubSetting(FontSize fs) void InitFontCache(bool monospace); void UninitFontCache(); -bool HasAntialiasedFonts(); -bool GetFontAAState(FontSize size, bool check_blitter = true); -void SetFont(FontSize fontsize, const std::string &font, uint size, bool aa); +bool GetFontAAState(); +void SetFont(FontSize fontsize, const std::string &font, uint size); #endif /* FONTCACHE_H */ diff --git a/src/fontcache/truetypefontcache.cpp b/src/fontcache/truetypefontcache.cpp index 78e787bea0..5bbe5d304e 100644 --- a/src/fontcache/truetypefontcache.cpp +++ b/src/fontcache/truetypefontcache.cpp @@ -91,7 +91,7 @@ void TrueTypeFontCache::SetGlyphPtr(GlyphID key, const GlyphEntry *glyph, bool d bool TrueTypeFontCache::GetDrawGlyphShadow() { - return this->fs == FS_NORMAL && GetFontAAState(FS_NORMAL); + return this->fs == FS_NORMAL && GetFontAAState(); } uint TrueTypeFontCache::GetGlyphWidth(GlyphID key) @@ -162,7 +162,7 @@ const Sprite *TrueTypeFontCache::GetGlyph(GlyphID key) } } - return this->InternalGetGlyph(key, GetFontAAState(this->fs)); + return this->InternalGetGlyph(key, GetFontAAState()); } const void *TrueTypeFontCache::GetFontTable(uint32_t tag, size_t &length) diff --git a/src/genworld.cpp b/src/genworld.cpp index 45a30bbc80..531c51e1a8 100644 --- a/src/genworld.cpp +++ b/src/genworld.cpp @@ -115,6 +115,10 @@ static void _GenerateWorld() IncreaseGeneratingWorldProgress(GWP_MAP_INIT); /* Must start economy early because of the costs. */ StartupEconomy(); + if (!CheckTownRoadTypes()) { + HandleGeneratingWorldAbortion(); + return; + } bool landscape_generated = false; diff --git a/src/gfx_layout_icu.cpp b/src/gfx_layout_icu.cpp index 431d7caa65..4f3f7a6362 100644 --- a/src/gfx_layout_icu.cpp +++ b/src/gfx_layout_icu.cpp @@ -151,7 +151,7 @@ void ICURun::Shape(UChar *buff, size_t buff_length) { auto hbfont = hb_ft_font_create_referenced(*(static_cast(font->fc->GetOSHandle()))); /* Match the flags with how we render the glyphs. */ - hb_ft_font_set_load_flags(hbfont, GetFontAAState(this->font->fc->GetSize()) ? FT_LOAD_TARGET_NORMAL : FT_LOAD_TARGET_MONO); + hb_ft_font_set_load_flags(hbfont, GetFontAAState() ? FT_LOAD_TARGET_NORMAL : FT_LOAD_TARGET_MONO); /* ICU buffer is in UTF-16. */ auto hbbuf = hb_buffer_create(); diff --git a/src/gfxinit.cpp b/src/gfxinit.cpp index 6a795e770d..05d9cfe751 100644 --- a/src/gfxinit.cpp +++ b/src/gfxinit.cpp @@ -325,7 +325,7 @@ static bool SwitchNewGRFBlitter() if (c->palette & GRFP_BLT_32BPP) depth_wanted_by_grf = 32; } /* We need a 32bpp blitter for font anti-alias. */ - if (HasAntialiasedFonts()) depth_wanted_by_grf = 32; + if (GetFontAAState()) depth_wanted_by_grf = 32; /* Search the best blitter. */ static const struct { diff --git a/src/lang/brazilian_portuguese.txt b/src/lang/brazilian_portuguese.txt index bdf6cfa9ed..9ba9130d8c 100644 --- a/src/lang/brazilian_portuguese.txt +++ b/src/lang/brazilian_portuguese.txt @@ -446,7 +446,7 @@ STR_SETTINGS_MENU_CONFIG_SETTINGS_TREE :Configurações STR_SETTINGS_MENU_AI_SETTINGS :Configurações de IA STR_SETTINGS_MENU_GAMESCRIPT_SETTINGS :Configurações de Script de Jogo STR_SETTINGS_MENU_NEWGRF_SETTINGS :Configurações de NewGRF -STR_SETTINGS_MENU_SANDBOX_OPTIONS :Opções de trapaças +STR_SETTINGS_MENU_SANDBOX_OPTIONS :Opções da sandbox STR_SETTINGS_MENU_TRANSPARENCY_OPTIONS :Opções de transparência STR_SETTINGS_MENU_TOWN_NAMES_DISPLAYED :Mostrar nomes de localidades STR_SETTINGS_MENU_STATION_NAMES_DISPLAYED :Mostrar nomes de estações @@ -2242,7 +2242,7 @@ STR_HELP_WINDOW_BUGTRACKER :{BLACK}Relatar STR_HELP_WINDOW_COMMUNITY :{BLACK}Comunidade # Cheat window -STR_CHEATS :{WHITE}Trapaças +STR_CHEATS :{WHITE}Opções da Sandbox STR_CHEAT_MONEY :{LTBLUE}Aumentar dinheiro em {CURRENCY_LONG} STR_CHEAT_CHANGE_COMPANY :{LTBLUE}Jogando como empresa: {ORANGE}{COMMA} STR_CHEAT_EXTRA_DYNAMITE :{LTBLUE}Escavadeira mágica (remove indústrias, objetos estáticos): {ORANGE}{STRING} diff --git a/src/lang/english.txt b/src/lang/english.txt index b4a235122b..09508cacd7 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -5286,6 +5286,11 @@ STR_ERROR_NO_VEHICLES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}Change y STR_ERROR_NO_VEHICLES_AVAILABLE_YET :{WHITE}No vehicles are available yet STR_ERROR_NO_VEHICLES_AVAILABLE_YET_EXPLANATION :{WHITE}Start a new game after {DATE_SHORT} or use a NewGRF that provides early vehicles +STR_ERROR_NO_TOWN_ROADTYPES_AVAILABLE_AT_ALL :{WHITE}No town-buildable road types are available +STR_ERROR_NO_TOWN_ROADTYPES_AVAILABLE_AT_ALL_EXPLANATION :{WHITE}Change your NewGRF configuration +STR_ERROR_NO_TOWN_ROADTYPES_AVAILABLE_YET :{WHITE}No town-buildable road types are available yet +STR_ERROR_NO_TOWN_ROADTYPES_AVAILABLE_YET_EXPLANATION :{WHITE}Start a new game after {DATE_SHORT} or use a NewGRF that provides early town-buildable road types + # Specific vehicle errors STR_ERROR_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Can't make train pass signal at danger... STR_ERROR_CAN_T_REVERSE_DIRECTION_TRAIN :{WHITE}Can't reverse direction of train... diff --git a/src/newgrf_storage.h b/src/newgrf_storage.h index dc895aa6fb..65f35db2ae 100644 --- a/src/newgrf_storage.h +++ b/src/newgrf_storage.h @@ -137,7 +137,7 @@ struct TemporaryStorageArray { StorageType storage{}; ///< Memory for the storage array StorageInitType init{}; ///< Storage has been assigned, if this equals 'init_key'. - uint16_t init_key{1}; ///< Magic key to 'init'. + uint16_t init_key = 1; ///< Magic key to 'init'. /** * Stores some value at a given position. diff --git a/src/newgrf_townname.cpp b/src/newgrf_townname.cpp index 89dfb550a3..64cfbde913 100644 --- a/src/newgrf_townname.cpp +++ b/src/newgrf_townname.cpp @@ -27,7 +27,7 @@ static std::vector _grf_townname_names; GRFTownName *GetGRFTownName(uint32_t grfid) { - auto found = std::find_if(std::begin(_grf_townnames), std::end(_grf_townnames), [&grfid](const GRFTownName &t){ return t.grfid == grfid; }); + auto found = std::find_if(std::begin(_grf_townnames), std::end(_grf_townnames), [&grfid](const GRFTownName &t) { return t.grfid == grfid; }); if (found != std::end(_grf_townnames)) return &*found; return nullptr; } @@ -44,7 +44,7 @@ GRFTownName *AddGRFTownName(uint32_t grfid) void DelGRFTownName(uint32_t grfid) { - _grf_townnames.erase(std::find_if(std::begin(_grf_townnames), std::end(_grf_townnames), [&grfid](const GRFTownName &t){ return t.grfid == grfid; })); + _grf_townnames.erase(std::find_if(std::begin(_grf_townnames), std::end(_grf_townnames), [&grfid](const GRFTownName &t) { return t.grfid == grfid; })); } static void RandomPart(StringBuilder builder, const GRFTownName *t, uint32_t seed, uint8_t id) diff --git a/src/rail_gui.cpp b/src/rail_gui.cpp index 7634c7d96e..9ddfa890ba 100644 --- a/src/rail_gui.cpp +++ b/src/rail_gui.cpp @@ -2759,7 +2759,7 @@ static void SetDefaultRailGui() case 0: { /* Use first available type */ std::vector::const_iterator it = std::find_if(_sorted_railtypes.begin(), _sorted_railtypes.end(), - [](RailType r){ return HasRailTypeAvail(_local_company, r); }); + [](RailType r) { return HasRailTypeAvail(_local_company, r); }); rt = it != _sorted_railtypes.end() ? *it : RAILTYPE_BEGIN; break; } diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index 109039e04f..dccf3bfb25 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -1144,7 +1144,7 @@ CommandCost CheckFlatLandRoadStop(TileArea tile_area, const RoadStopSpec *spec, return ClearTile_Station(cur_tile, DC_AUTO); // Get error message. } /* Drive-through station in the wrong direction. */ - if (is_drive_through && IsDriveThroughStopTile(cur_tile) && DiagDirToAxis(GetRoadStopDir(cur_tile)) != axis){ + if (is_drive_through && IsDriveThroughStopTile(cur_tile) && DiagDirToAxis(GetRoadStopDir(cur_tile)) != axis) { return_cmd_error(STR_ERROR_DRIVE_THROUGH_DIRECTION); } StationID st = GetStationIndex(cur_tile); diff --git a/src/table/settings/misc_settings.ini b/src/table/settings/misc_settings.ini index 7d08826bd8..03bff1a3f9 100644 --- a/src/table/settings/misc_settings.ini +++ b/src/table/settings/misc_settings.ini @@ -247,30 +247,6 @@ def = 0 min = 0 max = 72 -[SDTG_BOOL] -ifdef = HAS_TRUETYPE_FONT -name = ""small_aa"" -var = _fcsettings.small.aa -def = false - -[SDTG_BOOL] -ifdef = HAS_TRUETYPE_FONT -name = ""medium_aa"" -var = _fcsettings.medium.aa -def = false - -[SDTG_BOOL] -ifdef = HAS_TRUETYPE_FONT -name = ""large_aa"" -var = _fcsettings.large.aa -def = false - -[SDTG_BOOL] -ifdef = HAS_TRUETYPE_FONT -name = ""mono_aa"" -var = _fcsettings.mono.aa -def = false - [SDTG_BOOL] ifdef = HAS_TRUETYPE_FONT name = ""global_aa"" diff --git a/src/textfile_gui.h b/src/textfile_gui.h index 79c3571544..60c5ae2d58 100644 --- a/src/textfile_gui.h +++ b/src/textfile_gui.h @@ -56,10 +56,10 @@ protected: void ConstructWindow(); struct Line { - int top{0}; ///< Top scroll position in visual lines. - int bottom{0}; ///< Bottom scroll position in visual lines. - std::string text{}; ///< Contents of the line. - TextColour colour{TC_WHITE}; ///< Colour to render text line in. + int top = 0; ///< Top scroll position in visual lines. + int bottom = 0; ///< Bottom scroll position in visual lines. + std::string text{}; ///< Contents of the line. + TextColour colour = TC_WHITE; ///< Colour to render text line in. Line(int top, std::string_view text) : top(top), bottom(top + 1), text(text) {} Line() {} @@ -85,8 +85,8 @@ protected: std::vector links; ///< Clickable links in lines. std::vector link_anchors; ///< Anchor names of headings that can be linked to. std::vector history; ///< Browsing history in this window. - size_t history_pos{0}; ///< Position in browsing history (for forward movement). - bool trusted{false}; ///< Whether the content is trusted (read: not from content like NewGRFs, etc). + size_t history_pos = 0; ///< Position in browsing history (for forward movement). + bool trusted = false; ///< Whether the content is trusted (read: not from content like NewGRFs, etc). void LoadText(std::string_view buf); void FindHyperlinksInMarkdown(Line &line, size_t line_index); @@ -109,8 +109,8 @@ protected: void NavigateHistory(int delta); private: - uint search_iterator{0}; ///< Iterator for the font check search. - uint max_length{0}; ///< Maximum length of unwrapped text line. + uint search_iterator = 0; ///< Iterator for the font check search. + uint max_length = 0; ///< Maximum length of unwrapped text line. uint ReflowContent(); uint GetContentHeight(); diff --git a/src/tgp.cpp b/src/tgp.cpp index 2e9174d0d3..15ad3b3b6a 100644 --- a/src/tgp.cpp +++ b/src/tgp.cpp @@ -446,7 +446,7 @@ static int *HeightMapMakeHistogram(Height h_min, [[maybe_unused]] Height h_max, int *hist = hist_buf - h_min; /* Count the heights and fill the histogram */ - for (const Height &h : _height_map.h){ + for (const Height &h : _height_map.h) { assert(h >= h_min); assert(h <= h_max); hist[h]++; diff --git a/src/town.h b/src/town.h index 62a2b74496..fdd563d4e6 100644 --- a/src/town.h +++ b/src/town.h @@ -382,6 +382,7 @@ inline uint16_t TownTicksToGameTicks(uint16_t ticks) RoadType GetTownRoadType(); +bool CheckTownRoadTypes(); bool MayTownModifyRoad(TileIndex tile); #endif /* TOWN_H */ diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp index 9a0439eba8..70cd052548 100644 --- a/src/town_cmd.cpp +++ b/src/town_cmd.cpp @@ -1088,6 +1088,45 @@ bool MayTownModifyRoad(TileIndex tile) return true; } +/** + * Get the calendar date of the earliest town-buildable road type. + * @return introduction date of earliest road type, or INT32_MAX if none available. + */ +static CalTime::Date GetTownRoadTypeFirstIntroductionDate() +{ + const RoadTypeInfo *best = nullptr; + for (RoadType rt = ROADTYPE_BEGIN; rt != ROADTYPE_END; rt++) { + if (RoadTypeIsTram(rt)) continue; + const RoadTypeInfo *rti = GetRoadTypeInfo(rt); + if (rti->label == 0) continue; // Unused road type. + if (!HasBit(rti->flags, ROTF_TOWN_BUILD)) continue; // Town can't build this road type. + + if (best != nullptr && rti->introduction_date >= best->introduction_date) continue; + best = rti; + } + + if (best == nullptr) return INT32_MAX; + return best->introduction_date; +} + +/** + * Check if towns are able to build road. + * @return true iff the towns are currently able to build road. + */ +bool CheckTownRoadTypes() +{ + auto min_date = GetTownRoadTypeFirstIntroductionDate(); + if (min_date <= CalTime::CurDate()) return true; + + if (min_date < INT32_MAX) { + SetDParam(0, min_date); + ShowErrorMessage(STR_ERROR_NO_TOWN_ROADTYPES_AVAILABLE_YET, STR_ERROR_NO_TOWN_ROADTYPES_AVAILABLE_YET_EXPLANATION, WL_CRITICAL); + } else { + ShowErrorMessage(STR_ERROR_NO_TOWN_ROADTYPES_AVAILABLE_AT_ALL, STR_ERROR_NO_TOWN_ROADTYPES_AVAILABLE_AT_ALL_EXPLANATION, WL_CRITICAL); + } + return false; +} + /** * Check for parallel road inside a given distance. * Assuming a road from (tile - TileOffsByDiagDir(dir)) to tile,