diff --git a/.github/dependabot.yml b/.github/dependabot.yml index d97e315781b96..050a4cc0bc2df 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -8,3 +8,5 @@ updates: actions: patterns: - "*" + commit-message: + prefix: "Upgrade: " diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 0aaaea5e00dce..904ad6feed63f 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -21,6 +21,7 @@ jobs: actions: read contents: read security-events: write + packages: read steps: - name: Checkout diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 668d73d70091f..fe1687dacac98 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -196,6 +196,29 @@ These include: You may also want the guide to [compiling OpenTTD](./COMPILING.md). +## Use of AI + +OpenTTD is a labour of love, created by people. + +Please refrain from submitting issues or pull requests that have been generated by an LLM or other fully-automated tools. +Any submission that is in violation of this policy will be closed, and the submitter may be blocked from this repository without warning. + +If you submit an issue, you need to understand what your issue description is saying. +You need to be able to answer questions about your bug report or feature request. +Using an AI tool to _proofread_ your issue/comment text is acceptable. Using an AI tool to _write_ your issue/comment text is not. + +If you submit a pull request, you need to understand what every line of code you've changed does. +If you can't explain why your PR is doing something, then do not submit it. +Using an AI tool to generate entire lines of code is unacceptable. + +The rationale behind this policy is that automated contributions are a waste of the maintainers' time. +Humans spend their time and brainpower reviewing every submission. +Issues or pull requests generated by automation tools create an imbalance of effort between the submitter and the reviewer. +Nobody learns anything when a maintainer reviews code written by an LLM. + +Additionally, AI-generated code conflicts with this project's license (GPL v2), since you cannot truly release code for use if you didn't author it yourself. + + ## Project goals ### What are the goals of the official branch? diff --git a/cmake/scripts/Regression.cmake b/cmake/scripts/Regression.cmake index a6833e2dd1471..e9ce5ea6f29c1 100644 --- a/cmake/scripts/Regression.cmake +++ b/cmake/scripts/Regression.cmake @@ -25,6 +25,10 @@ if(EDITBIN_EXECUTABLE) execute_process(COMMAND ${EDITBIN_EXECUTABLE} /nologo /subsystem:console ${OPENTTD_EXECUTABLE}) endif() +# Remove previous crash files +file(GLOB CRASH_FILES "regression/crash*") +file(REMOVE ${CRASH_FILES}) + # Run the regression test execute_process(COMMAND ${OPENTTD_EXECUTABLE} -x @@ -40,6 +44,13 @@ execute_process(COMMAND ${OPENTTD_EXECUTABLE} OUTPUT_STRIP_TRAILING_WHITESPACE ) +# Detect any crash +file(GLOB CRASH_FILES "regression/crash*.log") +if (CRASH_FILES) + file(READ ${CRASH_FILES} CRASH_LOG) + message(FATAL_ERROR "OpenTTD crashed: ${CRASH_LOG}") +endif() + if(REGRESSION_OUTPUT) message(FATAL_ERROR "Unexpected output: ${REGRESSION_OUTPUT}") endif() diff --git a/media/baseset/openttd.grf b/media/baseset/openttd.grf index 620cc8ab981eb..4464c415f3a7c 100644 Binary files a/media/baseset/openttd.grf and b/media/baseset/openttd.grf differ diff --git a/media/baseset/openttd.grf.hash b/media/baseset/openttd.grf.hash index 5b07da7ff6484..f940ca5d62c7d 100644 --- a/media/baseset/openttd.grf.hash +++ b/media/baseset/openttd.grf.hash @@ -1 +1 @@ -eb8390a0569e66ec417c64ad254f9d05 +b779126d7cd1567eb09a0a7871f70a71 diff --git a/media/baseset/openttd/CMakeLists.txt b/media/baseset/openttd/CMakeLists.txt index f2df774d1b4eb..a7d768326e666 100644 --- a/media/baseset/openttd/CMakeLists.txt +++ b/media/baseset/openttd/CMakeLists.txt @@ -10,6 +10,7 @@ if(GRFCODEC_FOUND) ${CMAKE_CURRENT_SOURCE_DIR}/airport_preview.nfo ${CMAKE_CURRENT_SOURCE_DIR}/aqueduct.nfo ${CMAKE_CURRENT_SOURCE_DIR}/autorail.nfo + ${CMAKE_CURRENT_SOURCE_DIR}/bridge_decks.nfo ${CMAKE_CURRENT_SOURCE_DIR}/canals.nfo ${CMAKE_CURRENT_SOURCE_DIR}/chars.nfo ${CMAKE_CURRENT_SOURCE_DIR}/elrails.nfo @@ -31,6 +32,7 @@ if(GRFCODEC_FOUND) ${CMAKE_CURRENT_SOURCE_DIR}/airport_preview.png ${CMAKE_CURRENT_SOURCE_DIR}/aqueduct.png ${CMAKE_CURRENT_SOURCE_DIR}/autorail.png + ${CMAKE_CURRENT_SOURCE_DIR}/bridge_decks.png ${CMAKE_CURRENT_SOURCE_DIR}/canals.png ${CMAKE_CURRENT_SOURCE_DIR}/canal_locks.png ${CMAKE_CURRENT_SOURCE_DIR}/chars.png diff --git a/media/baseset/openttd/bridge_decks.nfo b/media/baseset/openttd/bridge_decks.nfo new file mode 100644 index 0000000000000..beced3f59fee1 --- /dev/null +++ b/media/baseset/openttd/bridge_decks.nfo @@ -0,0 +1,36 @@ +// 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 . +// + -1 * 0 0C "Bridge decks" + -1 * 3 05 1B 18 + + -1 sprites/bridge_decks.png 8bpp 96 16 64 31 -31 0 normal + -1 sprites/bridge_decks.png 8bpp 16 16 64 31 -31 0 normal + -1 sprites/bridge_decks.png 8bpp 176 16 64 39 -31 -8 normal + -1 sprites/bridge_decks.png 8bpp 256 16 64 23 -31 0 normal + -1 sprites/bridge_decks.png 8bpp 336 16 64 23 -31 0 normal + -1 sprites/bridge_decks.png 8bpp 416 16 64 39 -31 -8 normal + + -1 sprites/bridge_decks.png 8bpp 96 71 64 31 -31 0 normal + -1 sprites/bridge_decks.png 8bpp 16 71 64 31 -31 0 normal + -1 sprites/bridge_decks.png 8bpp 176 71 64 39 -31 -8 normal + -1 sprites/bridge_decks.png 8bpp 256 71 64 23 -31 0 normal + -1 sprites/bridge_decks.png 8bpp 336 71 64 23 -31 0 normal + -1 sprites/bridge_decks.png 8bpp 416 71 64 39 -31 -8 normal + + -1 sprites/bridge_decks.png 8bpp 96 126 64 31 -31 0 normal + -1 sprites/bridge_decks.png 8bpp 16 126 64 31 -31 0 normal + -1 sprites/bridge_decks.png 8bpp 176 126 64 39 -31 -8 normal + -1 sprites/bridge_decks.png 8bpp 256 126 64 23 -31 0 normal + -1 sprites/bridge_decks.png 8bpp 336 126 64 23 -31 0 normal + -1 sprites/bridge_decks.png 8bpp 416 126 64 39 -31 -8 normal + +// X and Y axis are swapped for road surface. + -1 sprites/bridge_decks.png 8bpp 16 181 64 31 -31 0 normal + -1 sprites/bridge_decks.png 8bpp 96 181 64 31 -31 0 normal + -1 sprites/bridge_decks.png 8bpp 176 181 64 39 -31 -8 normal + -1 sprites/bridge_decks.png 8bpp 256 181 64 23 -31 0 normal + -1 sprites/bridge_decks.png 8bpp 336 181 64 23 -31 0 normal + -1 sprites/bridge_decks.png 8bpp 416 181 64 39 -31 -8 normal diff --git a/media/baseset/openttd/bridge_decks.png b/media/baseset/openttd/bridge_decks.png new file mode 100644 index 0000000000000..a602e0ed73a5e Binary files /dev/null and b/media/baseset/openttd/bridge_decks.png differ diff --git a/media/baseset/openttd/openttd.nfo b/media/baseset/openttd/openttd.nfo index 9cfce9ffddda0..862345d11eaf2 100644 --- a/media/baseset/openttd/openttd.nfo +++ b/media/baseset/openttd/openttd.nfo @@ -100,3 +100,4 @@ #include "palette.nfo" #include "road_waypoints.nfo" #include "overlay_rocks.nfo" +#include "bridge_decks.nfo" diff --git a/regression/regression/main.nut b/regression/regression/main.nut index b9df4ebb4a51b..d029cea9968d0 100644 --- a/regression/regression/main.nut +++ b/regression/regression/main.nut @@ -461,6 +461,21 @@ function Regression::Company() } } +function Regression::CompanyGender() +{ + print(""); + print("--Company Gender--"); + /* Check gender switching behaviour matches API. */ + print(" GetPresidentGender(): " + AICompany.GetPresidentGender(AICompany.COMPANY_SELF)); + print(" SetPresidentGender(): " + AICompany.SetPresidentGender(AICompany.GENDER_MALE)); + print(" GetPresidentGender(): " + AICompany.GetPresidentGender(AICompany.COMPANY_SELF)); + print(" SetPresidentGender(): " + AICompany.SetPresidentGender(AICompany.GENDER_FEMALE)); + print(" GetPresidentGender(): " + AICompany.GetPresidentGender(AICompany.COMPANY_SELF)); + /* Setting to existing gender should fail. */ + print(" SetPresidentGender(): " + AICompany.SetPresidentGender(AICompany.GENDER_FEMALE)); + print(" GetPresidentGender(): " + AICompany.GetPresidentGender(AICompany.COMPANY_SELF)); +} + function Regression::Engine() { local j = 0; @@ -2096,6 +2111,7 @@ function Regression::Start() this.Vehicle(); /* Order has to be after Vehicle */ this.Order(); + this.CompanyGender(); print(""); print(" First Subsidy Test"); PrintSubsidy(0); diff --git a/regression/regression/result.txt b/regression/regression/result.txt index 6a88a5297da70..ec60ce3651709 100644 --- a/regression/regression/result.txt +++ b/regression/regression/result.txt @@ -10006,6 +10006,15 @@ ERROR: IsEnd() is invalid as Begin() is never called foreach(): 20 => 23596 +--Company Gender-- + GetPresidentGender(): 1 + SetPresidentGender(): true + GetPresidentGender(): 0 + SetPresidentGender(): true + GetPresidentGender(): 1 + SetPresidentGender(): false + GetPresidentGender(): 1 + First Subsidy Test --Subsidy (0) -- IsValidSubsidy(): true @@ -10107,7 +10116,7 @@ ERROR: IsEnd() is invalid as Begin() is never called constructor failed with: excessive CPU usage in list filter function Your script made an error: excessive CPU usage in valuator function -*FUNCTION [Start()] regression/main.nut line [2168] +*FUNCTION [Start()] regression/main.nut line [2184] [Infinite] CLOSURE [list] INSTANCE diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 16215e7f8d867..f0e44215211a7 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -541,6 +541,7 @@ add_files( transparency.h transparency_gui.cpp transparency_gui.h + transport_mapping.hpp transport_type.h tree_cmd.cpp tree_cmd.h diff --git a/src/ai/ai_gui.cpp b/src/ai/ai_gui.cpp index c13e313130f94..4dd4a8c671a57 100644 --- a/src/ai/ai_gui.cpp +++ b/src/ai/ai_gui.cpp @@ -28,7 +28,7 @@ /** Widgets for the configure AI window. */ -static constexpr NWidgetPart _nested_ai_config_widgets[] = { +static constexpr std::initializer_list _nested_ai_config_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_MAUVE), NWidget(WWT_CAPTION, COLOUR_MAUVE), SetStringTip(STR_AI_CONFIG_CAPTION_AI, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), diff --git a/src/ai/ai_scanner.cpp b/src/ai/ai_scanner.cpp index 70e5b55148133..f4b055268499c 100644 --- a/src/ai/ai_scanner.cpp +++ b/src/ai/ai_scanner.cpp @@ -137,5 +137,5 @@ AILibrary *AIScannerLibrary::FindLibrary(const std::string &library, int version ScriptInfoList::iterator it = this->info_list.find(library_name); if (it == this->info_list.end()) return nullptr; - return static_cast((*it).second); + return static_cast(it->second); } diff --git a/src/aircraft_cmd.cpp b/src/aircraft_cmd.cpp index 7a1b8b7a8cbb5..94d976e112e2f 100644 --- a/src/aircraft_cmd.cpp +++ b/src/aircraft_cmd.cpp @@ -16,7 +16,6 @@ #include "news_func.h" #include "newgrf_engine.h" #include "newgrf_sound.h" -#include "spritecache.h" #include "error_func.h" #include "strings_func.h" #include "command_func.h" @@ -136,7 +135,9 @@ static StationID FindNearestHangar(const Aircraft *v) next_dest = Station::GetIfValid(v->current_order.GetDestination().ToStationID()); } else { last_dest = GetTargetAirportIfValid(v); - next_dest = Station::GetIfValid(v->GetNextStoppingStation().value); + std::vector next_station; + v->GetNextStoppingStation(next_station); + if (!next_station.empty()) next_dest = Station::GetIfValid(next_station.back()); } } @@ -200,7 +201,7 @@ void GetRotorImage(const Aircraft *v, EngineImageType image_type, VehicleSpriteS static void GetAircraftIcon(EngineID engine, EngineImageType image_type, VehicleSpriteSeq *result) { const Engine *e = Engine::Get(engine); - uint8_t spritenum = e->u.air.image_index; + uint8_t spritenum = e->VehInfo().image_index; if (IsCustomVehicleSpriteNum(spritenum)) { GetCustomVehicleIcon(engine, DIR_W, image_type, result); @@ -267,7 +268,7 @@ void GetAircraftSpriteSize(EngineID engine, uint &width, uint &height, int &xoff */ CommandCost CmdBuildAircraft(DoCommandFlags flags, TileIndex tile, const Engine *e, Vehicle **ret) { - const AircraftVehicleInfo *avi = &e->u.air; + const AircraftVehicleInfo *avi = &e->VehInfo(); const Station *st = Station::GetByTile(tile); /* Prevent building aircraft types at places which can't handle them */ @@ -438,7 +439,7 @@ static void CheckIfAircraftNeedsService(Aircraft *v) Money Aircraft::GetRunningCost() const { const Engine *e = this->GetEngine(); - uint cost_factor = GetVehicleProperty(this, PROP_AIRCRAFT_RUNNING_COST_FACTOR, e->u.air.running_cost); + uint cost_factor = GetVehicleProperty(this, PROP_AIRCRAFT_RUNNING_COST_FACTOR, e->VehInfo().running_cost); return GetPrice(PR_RUNNING_AIRCRAFT, cost_factor, e->GetGRF()); } diff --git a/src/aircraft_gui.cpp b/src/aircraft_gui.cpp index 5b7d67582b92b..3709dfb7211ac 100644 --- a/src/aircraft_gui.cpp +++ b/src/aircraft_gui.cpp @@ -14,7 +14,6 @@ #include "strings_func.h" #include "vehicle_func.h" #include "window_gui.h" -#include "spritecache.h" #include "zoom_func.h" #include "table/strings.h" diff --git a/src/airport_gui.cpp b/src/airport_gui.cpp index 48b34bbd00692..b0bdd7cbb8f8a 100644 --- a/src/airport_gui.cpp +++ b/src/airport_gui.cpp @@ -84,7 +84,7 @@ static void PlaceAirport(TileIndex tile) /** Airport build toolbar window handler. */ struct BuildAirToolbarWindow : Window { - int last_user_action = INVALID_WID_AT; // Last started user action. + WidgetID last_user_action = INVALID_WIDGET; // Last started user action. BuildAirToolbarWindow(WindowDesc &desc, WindowNumber window_number) : Window(desc) { @@ -161,6 +161,11 @@ struct BuildAirToolbarWindow : Window { VpSelectTilesWithMethod(pt.x, pt.y, select_method); } + Point OnInitialPosition(int16_t sm_width, [[maybe_unused]] int16_t sm_height, [[maybe_unused]] int window_number) override + { + return AlignInitialConstructionToolbar(sm_width); + } + void OnPlaceMouseUp([[maybe_unused]] ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, [[maybe_unused]] Point pt, TileIndex start_tile, TileIndex end_tile) override { if (pt.x != -1 && select_proc == DDSP_DEMOLISH_AREA) { @@ -197,7 +202,7 @@ struct BuildAirToolbarWindow : Window { }, AirportToolbarGlobalHotkeys}; }; -static constexpr NWidgetPart _nested_air_toolbar_widgets[] = { +static constexpr std::initializer_list _nested_air_toolbar_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN), NWidget(WWT_CAPTION, COLOUR_DARK_GREEN), SetStringTip(STR_TOOLBAR_AIRCRAFT_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), @@ -211,7 +216,7 @@ static constexpr NWidgetPart _nested_air_toolbar_widgets[] = { }; static WindowDesc _air_toolbar_desc( - WDP_ALIGN_TOOLBAR, "toolbar_air", 0, 0, + WDP_MANUAL, "toolbar_air", 0, 0, WC_BUILD_TOOLBAR, WC_NONE, WindowDefaultFlag::Construction, _nested_air_toolbar_widgets, @@ -580,7 +585,7 @@ class BuildAirportWindow : public PickerWindowBase { }}; }; -static constexpr NWidgetPart _nested_build_airport_widgets[] = { +static constexpr std::initializer_list _nested_build_airport_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN), NWidget(WWT_CAPTION, COLOUR_DARK_GREEN), SetStringTip(STR_STATION_BUILD_AIRPORT_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), diff --git a/src/articulated_vehicles.cpp b/src/articulated_vehicles.cpp index 9ffc0a6e8f943..08c3c4416c370 100644 --- a/src/articulated_vehicles.cpp +++ b/src/articulated_vehicles.cpp @@ -365,10 +365,10 @@ void AddArticulatedParts(Vehicle *first) t->track = front->track; t->railtypes = front->railtypes; - t->spritenum = e_artic->u.rail.image_index; + t->spritenum = e_artic->VehInfo().image_index; if (e_artic->CanCarryCargo()) { t->cargo_type = e_artic->GetDefaultCargoType(); - t->cargo_cap = e_artic->u.rail.capacity; // Callback 36 is called when the consist is finished + t->cargo_cap = e_artic->VehInfo().capacity; // Callback 36 is called when the consist is finished } else { t->cargo_type = front->cargo_type; // Needed for livery selection t->cargo_cap = 0; @@ -392,11 +392,11 @@ void AddArticulatedParts(Vehicle *first) rv->roadtype = front->roadtype; rv->compatible_roadtypes = front->compatible_roadtypes; - rv->spritenum = e_artic->u.road.image_index; + rv->spritenum = e_artic->VehInfo().image_index; if (e_artic->CanCarryCargo()) { rv->cargo_type = e_artic->GetDefaultCargoType(); assert(IsValidCargoType(rv->cargo_type)); - rv->cargo_cap = e_artic->u.road.capacity; // Callback 36 is called when the consist is finished + rv->cargo_cap = e_artic->VehInfo().capacity; // Callback 36 is called when the consist is finished } else { rv->cargo_type = front->cargo_type; // Needed for livery selection rv->cargo_cap = 0; diff --git a/src/autoreplace_cmd.cpp b/src/autoreplace_cmd.cpp index 0798c679b3f3c..454450c6420d0 100644 --- a/src/autoreplace_cmd.cpp +++ b/src/autoreplace_cmd.cpp @@ -71,16 +71,16 @@ bool CheckAutoreplaceValidity(EngineID from, EngineID to, CompanyID company) switch (type) { case VEH_TRAIN: { /* make sure the railtypes are compatible */ - if (!GetAllCompatibleRailTypes(e_from->u.rail.railtypes).Any(GetAllCompatibleRailTypes(e_to->u.rail.railtypes))) return false; + if (!GetAllCompatibleRailTypes(e_from->VehInfo().railtypes).Any(GetAllCompatibleRailTypes(e_to->VehInfo().railtypes))) return false; /* make sure we do not replace wagons with engines or vice versa */ - if ((e_from->u.rail.railveh_type == RAILVEH_WAGON) != (e_to->u.rail.railveh_type == RAILVEH_WAGON)) return false; + if ((e_from->VehInfo().railveh_type == RAILVEH_WAGON) != (e_to->VehInfo().railveh_type == RAILVEH_WAGON)) return false; break; } case VEH_ROAD: /* make sure the roadtypes are compatible */ - if (!GetRoadTypeInfo(e_from->u.road.roadtype)->powered_roadtypes.Any(GetRoadTypeInfo(e_to->u.road.roadtype)->powered_roadtypes)) return false; + if (!GetRoadTypeInfo(e_from->VehInfo().roadtype)->powered_roadtypes.Any(GetRoadTypeInfo(e_to->VehInfo().roadtype)->powered_roadtypes)) return false; /* make sure that we do not replace a tram with a normal road vehicles or vice versa */ if (e_from->info.misc_flags.Test(EngineMiscFlag::RoadIsTram) != e_to->info.misc_flags.Test(EngineMiscFlag::RoadIsTram)) return false; @@ -88,7 +88,7 @@ bool CheckAutoreplaceValidity(EngineID from, EngineID to, CompanyID company) case VEH_AIRCRAFT: /* make sure that we do not replace a plane with a helicopter or vice versa */ - if ((e_from->u.air.subtype & AIR_CTOL) != (e_to->u.air.subtype & AIR_CTOL)) return false; + if ((e_from->VehInfo().subtype & AIR_CTOL) != (e_to->VehInfo().subtype & AIR_CTOL)) return false; break; default: break; diff --git a/src/autoreplace_cmd.h b/src/autoreplace_cmd.h index 5f9af672d2433..df4c268255367 100644 --- a/src/autoreplace_cmd.h +++ b/src/autoreplace_cmd.h @@ -18,7 +18,7 @@ CommandCost CmdAutoreplaceVehicle(DoCommandFlags flags, VehicleID veh_id); CommandCost CmdSetAutoReplace(DoCommandFlags flags, GroupID id_g, EngineID old_engine_type, EngineID new_engine_type, bool when_old); -DEF_CMD_TRAIT(CMD_AUTOREPLACE_VEHICLE, CmdAutoreplaceVehicle, {}, CMDT_VEHICLE_MANAGEMENT) -DEF_CMD_TRAIT(CMD_SET_AUTOREPLACE, CmdSetAutoReplace, {}, CMDT_VEHICLE_MANAGEMENT) +DEF_CMD_TRAIT(CMD_AUTOREPLACE_VEHICLE, CmdAutoreplaceVehicle, {}, CommandType::VehicleManagement) +DEF_CMD_TRAIT(CMD_SET_AUTOREPLACE, CmdSetAutoReplace, {}, CommandType::VehicleManagement) #endif /* AUTOREPLACE_CMD_H */ diff --git a/src/autoreplace_gui.cpp b/src/autoreplace_gui.cpp index 081a8a8acee39..d38708ce6b1b0 100644 --- a/src/autoreplace_gui.cpp +++ b/src/autoreplace_gui.cpp @@ -140,7 +140,7 @@ class ReplaceVehicleWindow : public Window { case VEH_ROAD: if (draw_left && this->sel_roadtype != INVALID_ROADTYPE) { /* Ensure that the roadtype is specific to the selected one */ - if (e->u.road.roadtype != this->sel_roadtype) continue; + if (e->VehInfo().roadtype != this->sel_roadtype) continue; } break; @@ -698,7 +698,7 @@ class ReplaceVehicleWindow : public Window { } }; -static constexpr NWidgetPart _nested_replace_rail_vehicle_widgets[] = { +static constexpr std::initializer_list _nested_replace_rail_vehicle_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), NWidget(WWT_CAPTION, COLOUR_GREY, WID_RV_CAPTION), @@ -762,7 +762,7 @@ static WindowDesc _replace_rail_vehicle_desc( _nested_replace_rail_vehicle_widgets ); -static constexpr NWidgetPart _nested_replace_road_vehicle_widgets[] = { +static constexpr std::initializer_list _nested_replace_road_vehicle_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), NWidget(WWT_CAPTION, COLOUR_GREY, WID_RV_CAPTION), @@ -820,7 +820,7 @@ static WindowDesc _replace_road_vehicle_desc( _nested_replace_road_vehicle_widgets ); -static constexpr NWidgetPart _nested_replace_vehicle_widgets[] = { +static constexpr std::initializer_list _nested_replace_vehicle_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), NWidget(WWT_CAPTION, COLOUR_GREY, WID_RV_CAPTION), SetMinimalSize(433, 14), diff --git a/src/base_media_func.h b/src/base_media_func.h index 8f1fac4c26d25..d5a96bcc93566 100644 --- a/src/base_media_func.h +++ b/src/base_media_func.h @@ -79,7 +79,7 @@ bool BaseSet::FillSetDetails(const IniFile &ini, const std::string &path, con /* Add the translations of the descriptions too. */ for (const IniItem &titem : metadata->items) { - if (titem.name.compare(0, 12, "description.") != 0) continue; + if (!titem.name.starts_with("description.")) continue; this->description[titem.name.substr(12)] = titem.value.value_or(""); } diff --git a/src/bitmap_type.h b/src/bitmap_type.h index 4dd356e48a6bb..acf3b3d22b56f 100644 --- a/src/bitmap_type.h +++ b/src/bitmap_type.h @@ -118,9 +118,9 @@ class BitmapTileIterator : public OrthogonalTileIterator { inline TileIterator& operator ++() override { - (*this).OrthogonalTileIterator::operator++(); + this->OrthogonalTileIterator::operator++(); while (this->tile != INVALID_TILE && !this->bitmap->HasTile(TileIndex(this->tile))) { - (*this).OrthogonalTileIterator::operator++(); + this->OrthogonalTileIterator::operator++(); } return *this; } diff --git a/src/blitter/32bpp_sse2.cpp b/src/blitter/32bpp_sse2.cpp index 6fc08ca6cd4c0..791952a09522f 100644 --- a/src/blitter/32bpp_sse2.cpp +++ b/src/blitter/32bpp_sse2.cpp @@ -113,7 +113,7 @@ Sprite *Blitter_32bppSSE_Base::Encode(SpriteType sprite_type, const SpriteLoader else break; dst_rgba++; } - (*dst_rgba_line).data = nb_pix_transp; + dst_rgba_line->data = nb_pix_transp; Colour *nb_right = dst_rgba_line + 1; dst_rgba_line = reinterpret_cast(reinterpret_cast(dst_rgba_line) + info.sprite_line_size); @@ -126,7 +126,7 @@ Sprite *Blitter_32bppSSE_Base::Encode(SpriteType sprite_type, const SpriteLoader else break; dst_rgba--; } - (*nb_right).data = nb_pix_transp; + nb_right->data = nb_pix_transp; } } diff --git a/src/bootstrap_gui.cpp b/src/bootstrap_gui.cpp index 80620f303b4ae..3dcdeae43aab5 100644 --- a/src/bootstrap_gui.cpp +++ b/src/bootstrap_gui.cpp @@ -33,7 +33,7 @@ #include "safeguards.h" /** Widgets for the background window to prevent smearing. */ -static constexpr NWidgetPart _background_widgets[] = { +static constexpr std::initializer_list _background_widgets = { NWidget(WWT_PANEL, COLOUR_DARK_BLUE, WID_BB_BACKGROUND), SetResize(1, 1), EndContainer(), }; @@ -60,13 +60,13 @@ class BootstrapBackground : public Window { void DrawWidget(const Rect &r, WidgetID) const override { - GfxFillRect(r.left, r.top, r.right, r.bottom, PixelColour{4}, FILLRECT_OPAQUE); - GfxFillRect(r.left, r.top, r.right, r.bottom, PixelColour{0}, FILLRECT_CHECKER); + GfxFillRect(r, PixelColour{4}, FILLRECT_OPAQUE); + GfxFillRect(r, PixelColour{0}, FILLRECT_CHECKER); } }; /** Nested widgets for the error window. */ -static constexpr NWidgetPart _nested_bootstrap_errmsg_widgets[] = { +static constexpr std::initializer_list _nested_bootstrap_errmsg_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CAPTION, COLOUR_GREY, WID_BEM_CAPTION), SetStringTip(STR_MISSING_GRAPHICS_ERROR_TITLE), EndContainer(), @@ -123,7 +123,7 @@ class BootstrapErrorWindow : public Window { }; /** Nested widgets for the download window. */ -static constexpr NWidgetPart _nested_bootstrap_download_status_window_widgets[] = { +static constexpr std::initializer_list _nested_bootstrap_download_status_window_widgets = { NWidget(WWT_CAPTION, COLOUR_GREY), SetStringTip(STR_CONTENT_DOWNLOAD_TITLE, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), NWidget(WWT_PANEL, COLOUR_GREY), NWidget(NWID_VERTICAL), SetPIP(0, WidgetDimensions::unscaled.vsep_wide, 0), SetPadding(WidgetDimensions::unscaled.modalpopup), @@ -174,7 +174,7 @@ struct BootstrapContentDownloadStatusWindow : public BaseNetworkContentDownloadS }; /** The widgets for the query. It has no close box as that sprite does not exist yet. */ -static constexpr NWidgetPart _bootstrap_query_widgets[] = { +static constexpr std::initializer_list _bootstrap_query_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CAPTION, COLOUR_GREY), SetStringTip(STR_MISSING_GRAPHICS_SET_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), EndContainer(), @@ -380,7 +380,7 @@ bool HandleBootstrap() /* Initialise the font cache. */ InitializeUnicodeGlyphMap(); /* Next "force" finding a suitable non-sprite font as the local font is missing. */ - CheckForMissingGlyphs(false); + CheckForMissingGlyphs(); /* Initialise the palette. The biggest step is 'faking' some recolour sprites. * This way the mauve and gray colours work and we can show the user interface. */ diff --git a/src/bridge_gui.cpp b/src/bridge_gui.cpp index c29d8bb86db5a..f27cd65fe3242 100644 --- a/src/bridge_gui.cpp +++ b/src/bridge_gui.cpp @@ -54,7 +54,7 @@ typedef GUIList GUIBridgeList; ///< List of bridges, used in #B * @param tile_start start tile * @param transport_type transport type. */ -void CcBuildBridge(Commands, const CommandCost &result, TileIndex end_tile, TileIndex tile_start, TransportType transport_type, BridgeType, uint8_t) +void CcBuildBridge(Commands, const CommandCost &result, TileIndex end_tile, TileIndex tile_start, TransportType transport_type, BridgeType, RailType, RoadType) { if (result.Failed()) return; if (_settings_client.sound.confirm) SndPlayTileFx(SND_27_CONSTRUCTION_BRIDGE, end_tile); @@ -86,7 +86,8 @@ class BuildBridgeWindow : public Window { TileIndex start_tile = INVALID_TILE; TileIndex end_tile = INVALID_TILE; TransportType transport_type = INVALID_TRANSPORT; - uint8_t road_rail_type = 0; + RailType railtype = INVALID_RAILTYPE; + RoadType roadtype = INVALID_ROADTYPE; GUIBridgeList bridges{}; int icon_width = 0; ///< Scaled width of the the bridge icon sprite. Scrollbar *vscroll = nullptr; @@ -117,7 +118,7 @@ class BuildBridgeWindow : public Window { default: break; } Command::Post(STR_ERROR_CAN_T_BUILD_BRIDGE_HERE, CcBuildBridge, - this->end_tile, this->start_tile, this->transport_type, type, this->road_rail_type); + this->end_tile, this->start_tile, this->transport_type, type, this->railtype, this->roadtype); } /** Sort the builable bridges */ @@ -154,11 +155,12 @@ class BuildBridgeWindow : public Window { } public: - BuildBridgeWindow(WindowDesc &desc, TileIndex start, TileIndex end, TransportType transport_type, uint8_t road_rail_type, GUIBridgeList &&bl) : Window(desc), + BuildBridgeWindow(WindowDesc &desc, TileIndex start, TileIndex end, TransportType transport_type, RailType railtype, RoadType roadtype, GUIBridgeList &&bl) : Window(desc), start_tile(start), end_tile(end), transport_type(transport_type), - road_rail_type(road_rail_type), + railtype(railtype), + roadtype(roadtype), bridges(std::move(bl)) { this->CreateNestedTree(); @@ -309,7 +311,7 @@ const std::initializer_list BuildBridgeWind }; /** Widgets of the bridge gui. */ -static constexpr NWidgetPart _nested_build_bridge_widgets[] = { +static constexpr std::initializer_list _nested_build_bridge_widgets = { /* Header */ NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN), @@ -354,7 +356,7 @@ static WindowDesc _build_bridge_desc( * @param transport_type The transport type * @param road_rail_type The road/rail type */ -void ShowBuildBridgeWindow(TileIndex start, TileIndex end, TransportType transport_type, uint8_t road_rail_type) +void ShowBuildBridgeWindow(TileIndex start, TileIndex end, TransportType transport_type, RailType railtype, RoadType roadtype) { CloseWindowByClass(WC_BUILD_BRIDGE); @@ -373,13 +375,13 @@ void ShowBuildBridgeWindow(TileIndex start, TileIndex end, TransportType transpo default: break; // water ways and air routes don't have bridge types } if (_ctrl_pressed && CheckBridgeAvailability(last_bridge_type, bridge_len).Succeeded()) { - Command::Post(STR_ERROR_CAN_T_BUILD_BRIDGE_HERE, CcBuildBridge, end, start, transport_type, last_bridge_type, road_rail_type); + Command::Post(STR_ERROR_CAN_T_BUILD_BRIDGE_HERE, CcBuildBridge, end, start, transport_type, last_bridge_type, railtype, roadtype); return; } /* only query bridge building possibility once, result is the same for all bridges! * returns CMD_ERROR on failure, and price on success */ - CommandCost ret = Command::Do(CommandFlagsToDCFlags(GetCommandFlags()) | DoCommandFlag::QueryCost, end, start, transport_type, 0, road_rail_type); + CommandCost ret = Command::Do(CommandFlagsToDCFlags(GetCommandFlags()) | DoCommandFlag::QueryCost, end, start, transport_type, 0, railtype, roadtype); GUIBridgeList bl; if (!ret.Failed()) { @@ -396,10 +398,10 @@ void ShowBuildBridgeWindow(TileIndex start, TileIndex end, TransportType transpo road_rt = GetRoadTypeRoad(start); tram_rt = GetRoadTypeTram(start); } - if (RoadTypeIsRoad((RoadType)road_rail_type)) { - road_rt = (RoadType)road_rail_type; + if (RoadTypeIsRoad(roadtype)) { + road_rt = roadtype; } else { - tram_rt = (RoadType)road_rail_type; + tram_rt = roadtype; } if (road_rt != INVALID_ROADTYPE) infra_cost += (bridge_len + 2) * 2 * RoadBuildCost(road_rt); @@ -407,7 +409,7 @@ void ShowBuildBridgeWindow(TileIndex start, TileIndex end, TransportType transpo break; } - case TRANSPORT_RAIL: infra_cost = (bridge_len + 2) * RailBuildCost((RailType)road_rail_type); break; + case TRANSPORT_RAIL: infra_cost = (bridge_len + 2) * RailBuildCost(railtype); break; default: break; } @@ -432,7 +434,7 @@ void ShowBuildBridgeWindow(TileIndex start, TileIndex end, TransportType transpo } if (!bl.empty()) { - new BuildBridgeWindow(_build_bridge_desc, start, end, transport_type, road_rail_type, std::move(bl)); + new BuildBridgeWindow(_build_bridge_desc, start, end, transport_type, railtype, roadtype, std::move(bl)); } else { ShowErrorMessage(GetEncodedString(STR_ERROR_CAN_T_BUILD_BRIDGE_HERE), TileX(end) * TILE_SIZE, TileY(end) * TILE_SIZE, ret); } diff --git a/src/bridge_map.h b/src/bridge_map.h index 5ced7b5d2f27b..28ca5f052c264 100644 --- a/src/bridge_map.h +++ b/src/bridge_map.h @@ -135,6 +135,7 @@ inline void MakeBridgeRamp(Tile t, Owner o, BridgeType bridgetype, DiagDirection t.m4() = 0; t.m5() = 1 << 7 | tt << 2 | d; SB(t.m6(), 2, 4, bridgetype); + SB(t.m6(), 6, 2, 0); t.m7() = 0; t.m8() = 0; } @@ -147,15 +148,15 @@ inline void MakeBridgeRamp(Tile t, Owner o, BridgeType bridgetype, DiagDirection * @param owner_tram the new owner of the tram on the bridge * @param bridgetype the type of bridge this bridge ramp belongs to * @param d the direction this ramp must be facing - * @param road_rt the road type of the bridge - * @param tram_rt the tram type of the bridge + * @param map_roadtype the map road type of the bridge + * @param map_tramtype the map tram type of the bridge */ -inline void MakeRoadBridgeRamp(Tile t, Owner o, Owner owner_road, Owner owner_tram, BridgeType bridgetype, DiagDirection d, RoadType road_rt, RoadType tram_rt) +inline void MakeRoadBridgeRamp(Tile t, Owner o, Owner owner_road, Owner owner_tram, BridgeType bridgetype, DiagDirection d, MapRoadType map_roadtype, MapTramType map_tramtype) { MakeBridgeRamp(t, o, bridgetype, d, TRANSPORT_ROAD); SetRoadOwner(t, RTT_ROAD, owner_road); if (owner_tram != OWNER_TOWN) SetRoadOwner(t, RTT_TRAM, owner_tram); - SetRoadTypes(t, road_rt, tram_rt); + SetMapRoadTypes(t, map_roadtype, map_tramtype); } /** @@ -164,12 +165,12 @@ inline void MakeRoadBridgeRamp(Tile t, Owner o, Owner owner_road, Owner owner_tr * @param o the new owner of the bridge ramp * @param bridgetype the type of bridge this bridge ramp belongs to * @param d the direction this ramp must be facing - * @param rt the rail type of the bridge + * @param map_railtype the map rail type of the bridge */ -inline void MakeRailBridgeRamp(Tile t, Owner o, BridgeType bridgetype, DiagDirection d, RailType rt) +inline void MakeRailBridgeRamp(Tile t, Owner o, BridgeType bridgetype, DiagDirection d, MapRailType map_railtype) { MakeBridgeRamp(t, o, bridgetype, d, TRANSPORT_RAIL); - SetRailType(t, rt); + SetMapRailType(t, map_railtype); } /** diff --git a/src/build_vehicle_gui.cpp b/src/build_vehicle_gui.cpp index a40ad4ef359e0..27deb5f430617 100644 --- a/src/build_vehicle_gui.cpp +++ b/src/build_vehicle_gui.cpp @@ -58,7 +58,7 @@ uint GetEngineListHeight(VehicleType type) return std::max(GetCharacterHeight(FS_NORMAL) + WidgetDimensions::scaled.matrix.Vertical(), GetVehicleImageCellSize(type, EIT_PURCHASE).height); } -static constexpr NWidgetPart _nested_build_vehicle_widgets[] = { +static constexpr std::initializer_list _nested_build_vehicle_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), NWidget(WWT_CAPTION, COLOUR_GREY, WID_BV_CAPTION), SetTextStyle(TC_WHITE), @@ -726,8 +726,8 @@ static int DrawShipPurchaseInfo(int left, int right, int y, EngineID engine_numb /* Purchase cost - Max speed */ uint raw_speed = e->GetDisplayMaxSpeed(); - uint ocean_speed = e->u.ship.ApplyWaterClassSpeedFrac(raw_speed, true); - uint canal_speed = e->u.ship.ApplyWaterClassSpeedFrac(raw_speed, false); + uint ocean_speed = e->VehInfo().ApplyWaterClassSpeedFrac(raw_speed, true); + uint canal_speed = e->VehInfo().ApplyWaterClassSpeedFrac(raw_speed, false); if (ocean_speed == canal_speed) { if (te.cost != 0) { @@ -885,10 +885,10 @@ int DrawVehiclePurchaseInfo(int left, int right, int y, EngineID engine_number, switch (e->type) { default: NOT_REACHED(); case VEH_TRAIN: - if (e->u.rail.railveh_type == RAILVEH_WAGON) { - y = DrawRailWagonPurchaseInfo(left, right, y, engine_number, &e->u.rail, te); + if (e->VehInfo().railveh_type == RAILVEH_WAGON) { + y = DrawRailWagonPurchaseInfo(left, right, y, engine_number, &e->VehInfo(), te); } else { - y = DrawRailEnginePurchaseInfo(left, right, y, engine_number, &e->u.rail, te); + y = DrawRailEnginePurchaseInfo(left, right, y, engine_number, &e->VehInfo(), te); } articulated_cargo = true; break; @@ -920,7 +920,7 @@ int DrawVehiclePurchaseInfo(int left, int right, int y, EngineID engine_number, } /* Draw details that apply to all types except rail wagons. */ - if (e->type != VEH_TRAIN || e->u.rail.railveh_type != RAILVEH_WAGON) { + if (e->type != VEH_TRAIN || e->VehInfo().railveh_type != RAILVEH_WAGON) { /* Design date - Life length */ DrawString(left, right, y, GetString(STR_PURCHASE_INFO_DESIGNED_LIFE, ymd.year, TimerGameCalendar::DateToYear(e->GetLifeLengthInDays()))); y += GetCharacterHeight(FS_NORMAL); @@ -1030,7 +1030,7 @@ void DrawEngineList(VehicleType type, const Rect &r, const GUIEngineList &eng_li if (has_variants) { Rect fr = tr.WithWidth(circle_width, rtl); - DrawSpriteIgnorePadding(is_folded ? SPR_CIRCLE_FOLDED : SPR_CIRCLE_UNFOLDED, PAL_NONE, {fr.left, textr.top, fr.right, textr.bottom}, SA_CENTER); + DrawSpriteIgnorePadding(is_folded ? SPR_CIRCLE_FOLDED : SPR_CIRCLE_UNFOLDED, PAL_NONE, fr.WithY(textr), SA_CENTER); } tr = tr.Indent(circle_width + WidgetDimensions::scaled.hsep_normal, rtl); @@ -1395,7 +1395,7 @@ struct BuildVehicleWindow : Window { for (const Engine *e : Engine::IterateType(VEH_TRAIN)) { if (!this->show_hidden_engines && e->IsVariantHidden(_local_company)) continue; EngineID eid = e->index; - const RailVehicleInfo *rvi = &e->u.rail; + const RailVehicleInfo *rvi = &e->VehInfo(); if (this->filter.railtype != INVALID_RAILTYPE && !HasPowerOnRail(rvi->railtypes, this->filter.railtype)) continue; if (!IsEngineBuildable(eid, VEH_TRAIN, _local_company)) continue; @@ -1426,7 +1426,7 @@ struct BuildVehicleWindow : Window { if (std::ranges::find(list, variant, &GUIEngineListItem::engine_id) == list.end()) { const Engine *e = Engine::Get(variant); list.emplace_back(variant, e->info.variant_id, e->display_flags | EngineDisplayFlag::Shaded, 0); - if (e->u.rail.railveh_type != RAILVEH_WAGON) num_engines++; + if (e->VehInfo().railveh_type != RAILVEH_WAGON) num_engines++; } } @@ -1461,7 +1461,7 @@ struct BuildVehicleWindow : Window { if (!this->show_hidden_engines && e->IsVariantHidden(_local_company)) continue; EngineID eid = e->index; if (!IsEngineBuildable(eid, VEH_ROAD, _local_company)) continue; - if (this->filter.roadtype != INVALID_ROADTYPE && !HasPowerOnRoad(e->u.road.roadtype, this->filter.roadtype)) continue; + if (this->filter.roadtype != INVALID_ROADTYPE && !HasPowerOnRoad(e->VehInfo().roadtype, this->filter.roadtype)) continue; if (!bdf.Filter(e->badges)) continue; /* Filter by name or NewGRF extra text */ @@ -1731,7 +1731,8 @@ struct BuildVehicleWindow : Window { default: if (IsInsideMM(widget, this->badge_filters.first, this->badge_filters.second)) { - ShowDropDownList(this, this->GetWidget(widget)->GetDropDownList(), -1, widget, 0, false); + PaletteID palette = SPR_2CCMAP_BASE + Company::Get(_local_company)->GetCompanyRecolourOffset(LS_DEFAULT); + ShowDropDownList(this, this->GetWidget(widget)->GetDropDownList(palette), -1, widget, 0, false); } break; } @@ -1931,7 +1932,6 @@ struct BuildVehicleWindow : Window { /* We need to refresh if a filter is removed. */ this->eng_list.ForceRebuild(); - this->SetDirty(); break; } @@ -1943,7 +1943,6 @@ struct BuildVehicleWindow : Window { SetBadgeFilter(this->badge_filter_choices, BadgeID(index)); } this->eng_list.ForceRebuild(); - this->SetDirty(); } break; } diff --git a/src/cargopacket.cpp b/src/cargopacket.cpp index 38d94894900ea..8be991034ecdd 100644 --- a/src/cargopacket.cpp +++ b/src/cargopacket.cpp @@ -404,13 +404,13 @@ void VehicleCargoList::AgeCargo() * @return MoveToAction to be performed. */ /* static */ VehicleCargoList::MoveToAction VehicleCargoList::ChooseAction(const CargoPacket *cp, StationID cargo_next, - StationID current_station, bool accepted, StationIDStack next_station) + StationID current_station, bool accepted, std::span next_station) { if (cargo_next == StationID::Invalid()) { return (accepted && cp->first_station != current_station) ? MTA_DELIVER : MTA_KEEP; } else if (cargo_next == current_station) { return MTA_DELIVER; - } else if (next_station.Contains(cargo_next)) { + } else if (std::ranges::find(next_station, cargo_next) != std::end(next_station)) { return MTA_KEEP; } else { return MTA_TRANSFER; @@ -432,7 +432,7 @@ void VehicleCargoList::AgeCargo() * @param current_tile Current tile the cargo handling is happening on. * return If any cargo will be unloaded. */ -bool VehicleCargoList::Stage(bool accepted, StationID current_station, StationIDStack next_station, uint8_t order_flags, const GoodsEntry *ge, CargoType cargo, CargoPayment *payment, TileIndex current_tile) +bool VehicleCargoList::Stage(bool accepted, StationID current_station, std::span next_station, uint8_t order_flags, const GoodsEntry *ge, CargoType cargo, CargoPayment *payment, TileIndex current_tile) { this->AssertCountConsistency(); assert(this->action_counts[MTA_LOAD] == 0); @@ -468,9 +468,9 @@ bool VehicleCargoList::Stage(bool accepted, StationID current_station, StationID } else { FlowStat new_shares = flow_it->second; new_shares.ChangeShare(current_station, INT_MIN); - StationIDStack excluded = next_station; - while (!excluded.IsEmpty() && !new_shares.GetShares()->empty()) { - new_shares.ChangeShare(excluded.Pop(), INT_MIN); + for (auto station_it = next_station.rbegin(); station_it != next_station.rend(); ++station_it) { + if (new_shares.GetShares()->empty()) break; + new_shares.ChangeShare(*station_it, INT_MIN); } if (new_shares.GetShares()->empty()) { cargo_next = StationID::Invalid(); @@ -739,11 +739,11 @@ bool StationCargoList::ShiftCargo(Taction &action, StationID next) * @return Amount of cargo actually moved. */ template -uint StationCargoList::ShiftCargo(Taction action, StationIDStack next, bool include_invalid) +uint StationCargoList::ShiftCargo(Taction action, std::span next, bool include_invalid) { uint max_move = action.MaxMove(); - while (!next.IsEmpty()) { - this->ShiftCargo(action, next.Pop()); + for (auto it = next.rbegin(); it != next.rend(); ++it) { + this->ShiftCargo(action, *it); if (action.MaxMove() == 0) break; } if (include_invalid && action.MaxMove() > 0) { @@ -814,7 +814,7 @@ uint StationCargoList::Truncate(uint max_move, StationCargoAmountMap *cargo_per_ * @param current_tile Current tile the cargo handling is happening on. * @return Amount of cargo actually reserved. */ -uint StationCargoList::Reserve(uint max_move, VehicleCargoList *dest, StationIDStack next_station, TileIndex current_tile) +uint StationCargoList::Reserve(uint max_move, VehicleCargoList *dest, std::span next_station, TileIndex current_tile) { return this->ShiftCargo(CargoReservation(this, dest, max_move, current_tile), next_station, true); } @@ -831,7 +831,7 @@ uint StationCargoList::Reserve(uint max_move, VehicleCargoList *dest, StationIDS * modes of loading are exclusive, though. If cargo is reserved we don't * need to load unreserved cargo. */ -uint StationCargoList::Load(uint max_move, VehicleCargoList *dest, StationIDStack next_station, TileIndex current_tile) +uint StationCargoList::Load(uint max_move, VehicleCargoList *dest, std::span next_station, TileIndex current_tile) { uint move = std::min(dest->ActionCount(VehicleCargoList::MTA_LOAD), max_move); if (move > 0) { @@ -839,7 +839,7 @@ uint StationCargoList::Load(uint max_move, VehicleCargoList *dest, StationIDStac dest->Reassign(move); return move; } else { - return this->ShiftCargo(CargoLoad(this, dest, max_move, current_tile), next_station, true); + return this->ShiftCargo(CargoLoad{this, dest, max_move, current_tile}, next_station, true); } } @@ -853,7 +853,7 @@ uint StationCargoList::Load(uint max_move, VehicleCargoList *dest, StationIDStac */ uint StationCargoList::Reroute(uint max_move, StationCargoList *dest, StationID avoid, StationID avoid2, const GoodsEntry *ge) { - return this->ShiftCargo(StationCargoReroute(this, dest, max_move, avoid, avoid2, ge), avoid, false); + return this->ShiftCargo(StationCargoReroute(this, dest, max_move, avoid, avoid2, ge), {&avoid, 1}, false); } /* diff --git a/src/cargopacket.h b/src/cargopacket.h index 8b4c7b6d40148..35cfd2cce466c 100644 --- a/src/cargopacket.h +++ b/src/cargopacket.h @@ -371,7 +371,7 @@ class VehicleCargoList : public CargoList { void RemoveFromMeta(const CargoPacket *cp, MoveToAction action, uint count); static MoveToAction ChooseAction(const CargoPacket *cp, StationID cargo_next, - StationID current_station, bool accepted, StationIDStack next_station); + StationID current_station, bool accepted, std::span next_station); public: /** The station cargo list needs to control the unloading. */ @@ -469,7 +469,7 @@ class VehicleCargoList : public CargoList { void InvalidateCache(); - bool Stage(bool accepted, StationID current_station, StationIDStack next_station, uint8_t order_flags, const GoodsEntry *ge, CargoType cargo, CargoPayment *payment, TileIndex current_tile); + bool Stage(bool accepted, StationID current_station, std::span next_station, uint8_t order_flags, const GoodsEntry *ge, CargoType cargo, CargoPayment *payment, TileIndex current_tile); /** * Marks all cargo in the vehicle as to be kept. This is mostly useful for @@ -543,7 +543,7 @@ class StationCargoList : public CargoList - uint ShiftCargo(Taction action, StationIDStack next, bool include_invalid); + uint ShiftCargo(Taction action, std::span next, bool include_invalid); void Append(CargoPacket *cp, StationID next); @@ -552,10 +552,10 @@ class StationCargoList : public CargoList next) const { - while (!next.IsEmpty()) { - if (this->packets.find(next.Pop()) != this->packets.end()) return true; + for (const StationID &station : next) { + if (this->packets.find(station) != this->packets.end()) return true; } /* Packets for StationID::Invalid() can go anywhere. */ return this->packets.find(StationID::Invalid()) != this->packets.end(); @@ -603,8 +603,8 @@ class StationCargoList : public CargoList next, TileIndex current_tile); + uint Load(uint max_move, VehicleCargoList *dest, std::span next, TileIndex current_tile); uint Truncate(uint max_move = UINT_MAX, StationCargoAmountMap *cargo_per_source = nullptr); uint Reroute(uint max_move, StationCargoList *dest, StationID avoid, StationID avoid2, const GoodsEntry *ge); diff --git a/src/cheat_gui.cpp b/src/cheat_gui.cpp index 5cbdb1f78f4bc..af45b55ac727a 100644 --- a/src/cheat_gui.cpp +++ b/src/cheat_gui.cpp @@ -219,7 +219,7 @@ static const CheatEntry _cheats_ui[] = { static_assert(CHT_NUM_CHEATS == lengthof(_cheats_ui)); /** Widget definitions of the cheat GUI. */ -static constexpr NWidgetPart _nested_cheat_widgets[] = { +static constexpr std::initializer_list _nested_cheat_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), NWidget(WWT_CAPTION, COLOUR_GREY), SetStringTip(STR_CHEATS, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), diff --git a/src/clear_map.h b/src/clear_map.h index a1a58612ce489..6f24800f99d21 100644 --- a/src/clear_map.h +++ b/src/clear_map.h @@ -274,7 +274,7 @@ inline void MakeField(Tile t, uint field_type, IndustryID industry) t.m3() = field_type; t.m4() = 0 << 5 | 0 << 2; SetClearGroundDensity(t, CLEAR_FIELDS, 3); - SB(t.m6(), 2, 4, 0); + SB(t.m6(), 2, 6, 0); t.m7() = 0; t.m8() = 0; } diff --git a/src/command.cpp b/src/command.cpp index c11289902e2fb..2cdc9ed3ad4ec 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -144,21 +144,21 @@ std::string_view GetCommandName(Commands cmd) bool IsCommandAllowedWhilePaused(Commands cmd) { /* Lookup table for the command types that are allowed for a given pause level setting. */ - static const int command_type_lookup[] = { - CMDPL_ALL_ACTIONS, ///< CMDT_LANDSCAPE_CONSTRUCTION - CMDPL_NO_LANDSCAPING, ///< CMDT_VEHICLE_CONSTRUCTION - CMDPL_NO_LANDSCAPING, ///< CMDT_MONEY_MANAGEMENT - CMDPL_NO_CONSTRUCTION, ///< CMDT_VEHICLE_MANAGEMENT - CMDPL_NO_CONSTRUCTION, ///< CMDT_ROUTE_MANAGEMENT - CMDPL_NO_CONSTRUCTION, ///< CMDT_OTHER_MANAGEMENT - CMDPL_NO_ACTIONS, ///< CMDT_COMPANY_SETTING - CMDPL_NO_ACTIONS, ///< CMDT_SERVER_SETTING - CMDPL_NO_ACTIONS, ///< CMDT_CHEAT + static constexpr CommandPauseLevel command_type_lookup[] = { + CommandPauseLevel::AllActions, // CommandType::LandscapeConstruction + CommandPauseLevel::NoLandscaping, // CommandType::VehicleConstruction + CommandPauseLevel::NoLandscaping, // CommandType::MoneyManagement + CommandPauseLevel::NoConstruction, // CommandType::VehicleManagement + CommandPauseLevel::NoConstruction, // CommandType::RouteManagement + CommandPauseLevel::NoConstruction, // CommandType::OtherManagement + CommandPauseLevel::NoActions, // CommandType::CompanySetting + CommandPauseLevel::NoActions, // CommandType::ServerSetting + CommandPauseLevel::NoActions, // CommandType::Cheat }; - static_assert(lengthof(command_type_lookup) == CMDT_END); + static_assert(std::size(command_type_lookup) == to_underlying(CommandType::End)); assert(IsValidCommand(cmd)); - return _game_mode == GM_EDITOR || command_type_lookup[_command_proc_table[cmd].type] <= _settings_game.construction.command_pause_level; + return _game_mode == GM_EDITOR || command_type_lookup[to_underlying(_command_proc_table[cmd].type)] <= _settings_game.construction.command_pause_level; } /** @@ -384,7 +384,7 @@ CommandCost CommandHelperBase::InternalExecuteProcessResult(Commands cmd, Comman SubtractMoneyFromCompany(res_exec); /* Record if there was a command issues during pause; ignore pause/other setting related changes. */ - if (_pause_mode.Any() && _command_proc_table[cmd].type != CMDT_SERVER_SETTING) _pause_mode.Set(PauseMode::CommandDuringPause); + if (_pause_mode.Any() && _command_proc_table[cmd].type != CommandType::ServerSetting) _pause_mode.Set(PauseMode::CommandDuringPause); /* update signals if needed */ UpdateSignalsInBuffer(); diff --git a/src/command_type.h b/src/command_type.h index 893a03d44cc8a..babf32dd5489f 100644 --- a/src/command_type.h +++ b/src/command_type.h @@ -380,7 +380,7 @@ enum Commands : uint8_t { * * This enums defines some flags which can be used for the commands. */ -enum DoCommandFlag : uint8_t { +enum class DoCommandFlag : uint8_t { Execute, ///< execute the given command Auto, ///< don't allow building on structures QueryCost, ///< query cost only, don't build. @@ -417,26 +417,27 @@ enum class CommandFlag : uint8_t { using CommandFlags = EnumBitSet; /** Types of commands we have. */ -enum CommandType : uint8_t { - CMDT_LANDSCAPE_CONSTRUCTION, ///< Construction and destruction of objects on the map. - CMDT_VEHICLE_CONSTRUCTION, ///< Construction, modification (incl. refit) and destruction of vehicles. - CMDT_MONEY_MANAGEMENT, ///< Management of money, i.e. loans. - CMDT_VEHICLE_MANAGEMENT, ///< Stopping, starting, sending to depot, turning around, replace orders etc. - CMDT_ROUTE_MANAGEMENT, ///< Modifications to route management (orders, groups, etc). - CMDT_OTHER_MANAGEMENT, ///< Renaming stuff, changing company colours, placing signs, etc. - CMDT_COMPANY_SETTING, ///< Changing settings related to a company. - CMDT_SERVER_SETTING, ///< Pausing/removing companies/server settings. - CMDT_CHEAT, ///< A cheat of some sorts. - - CMDT_END, ///< Magic end marker. +enum class CommandType : uint8_t { + LandscapeConstruction, ///< Construction and destruction of objects on the map. + VehicleConstruction, ///< Construction, modification (incl. refit) and destruction of vehicles. + MoneyManagement, ///< Management of money, i.e. loans. + VehicleManagement, ///< Stopping, starting, sending to depot, turning around, replace orders etc. + RouteManagement, ///< Modifications to route management (orders, groups, etc). + OtherManagement, ///< Renaming stuff, changing company colours, placing signs, etc. + CompanySetting, ///< Changing settings related to a company. + ServerSetting, ///< Pausing/removing companies/server settings. + Cheat, ///< A cheat of some sorts. + + End, ///< End marker. }; /** Different command pause levels. */ -enum CommandPauseLevel : uint8_t { - CMDPL_NO_ACTIONS, ///< No user actions may be executed. - CMDPL_NO_CONSTRUCTION, ///< No construction actions may be executed. - CMDPL_NO_LANDSCAPING, ///< No landscaping actions may be executed. - CMDPL_ALL_ACTIONS, ///< All actions may be executed. + +enum class CommandPauseLevel : uint8_t { + NoActions, ///< No user actions may be executed. + NoConstruction, ///< No construction actions may be executed. + NoLandscaping, ///< No landscaping actions may be executed. + AllActions, ///< All actions may be executed. }; diff --git a/src/company_base.h b/src/company_base.h index cdaca96dc4a4c..a5b028aa06a6d 100644 --- a/src/company_base.h +++ b/src/company_base.h @@ -30,8 +30,8 @@ struct CompanyEconomyEntry { }; struct CompanyInfrastructure { - std::array rail{}; ///< Count of company owned track bits for each rail type. - std::array road{}; ///< Count of company owned track bits for each road type. + std::map rail{}; ///< Count of company owned track bits for each rail type. + std::map road{}; ///< Count of company owned track bits for each road type. uint32_t signal = 0; ///< Count of company owned signals. uint32_t water = 0; ///< Count of company owned track bits for canals. uint32_t station = 0; ///< Count of company owned station tiles. @@ -39,14 +39,23 @@ struct CompanyInfrastructure { auto operator<=>(const CompanyInfrastructure &) const = default; - /** Get total sum of all owned track bits. */ - uint32_t GetRailTotal() const + uint32_t GetRailTotal() const; + uint32_t GetRoadTramTotal(RoadTramType rtt) const; + + inline uint32_t GetRoadTotal() const { return GetRoadTramTotal(RTT_ROAD); } + inline uint32_t GetTramTotal() const { return GetRoadTramTotal(RTT_TRAM); } + + inline uint32_t GetRailCount(RailType railtype) const { - return std::accumulate(std::begin(this->rail), std::end(this->rail), 0U); + auto it = this->rail.find(railtype); + return it == std::end(this->rail) ? 0 : it->second; } - uint32_t GetRoadTotal() const; - uint32_t GetTramTotal() const; + inline uint32_t GetRoadCount(RoadType roadtype) const + { + auto it = this->road.find(roadtype); + return it == std::end(this->road) ? 0 : it->second; + } }; class FreeUnitIDGenerator { @@ -178,6 +187,18 @@ struct Company : CompanyProperties, CompanyPool::PoolItem<&_company_pool> { return !Company::Get(index)->is_ai; } + /** + * Get offset for recolour palette of specific company. + * @param livery_scheme Scheme to use for recolour. + * @param use_secondary Specify whether to add secondary colour offset to the result. + * @return palette offset. + */ + inline uint8_t GetCompanyRecolourOffset(LiveryScheme livery_scheme, bool use_secondary = true) const + { + const Livery &l = this->livery[livery_scheme]; + return use_secondary ? l.colour1 + l.colour2 * 16 : l.colour1; + } + static void PostDestructor(size_t index); }; diff --git a/src/company_cmd.cpp b/src/company_cmd.cpp index e9fc5f94ff882..30414d1b7b4e9 100644 --- a/src/company_cmd.cpp +++ b/src/company_cmd.cpp @@ -574,14 +574,14 @@ restart:; void ResetCompanyLivery(Company *c) { for (LiveryScheme scheme = LS_BEGIN; scheme < LS_END; scheme++) { - c->livery[scheme].in_use = 0; + c->livery[scheme].in_use.Reset(); c->livery[scheme].colour1 = c->colour; c->livery[scheme].colour2 = c->colour; } for (Group *g : Group::Iterate()) { if (g->owner == c->index) { - g->livery.in_use = 0; + g->livery.in_use.Reset(); g->livery.colour1 = c->colour; g->livery.colour2 = c->colour; } @@ -925,7 +925,7 @@ CommandCost CmdCompanyCtrl(DoCommandFlags flags, CompanyCtrlAction cca, CompanyI if (!_company_manager_face.empty()) { auto cmf = ParseCompanyManagerFaceCode(_company_manager_face); if (cmf.has_value()) { - Command::SendNet(STR_NULL, c->index, cmf->bits, cmf->style); + Command::SendNet(STR_NULL, c->index, cmf->style, cmf->bits); } } @@ -1050,11 +1050,11 @@ CommandCost CmdCompanyAllowListCtrl(DoCommandFlags flags, CompanyAllowListCtrlAc /** * Change the company manager's face. * @param flags operation to perform - * @param bits The bits of company manager face. * @param style The style of the company manager face. + * @param bits The bits of company manager face. * @return the cost of this operation or an error */ -CommandCost CmdSetCompanyManagerFace(DoCommandFlags flags, uint32_t bits, uint style) +CommandCost CmdSetCompanyManagerFace(DoCommandFlags flags, uint style, uint32_t bits) { CompanyManagerFace tmp_face{style, bits, {}}; if (!IsValidCompanyManagerFace(tmp_face)) return CMD_ERROR; @@ -1077,8 +1077,8 @@ CommandCost CmdSetCompanyManagerFace(DoCommandFlags flags, uint32_t bits, uint s 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; + if (!c->livery[i].in_use.Test(Livery::Flag::Primary)) c->livery[i].colour1 = c->livery[LS_DEFAULT].colour1; + if (!c->livery[i].in_use.Test(Livery::Flag::Secondary)) c->livery[i].colour2 = c->livery[LS_DEFAULT].colour2; } UpdateCompanyGroupLiveries(c); } @@ -1109,7 +1109,7 @@ CommandCost CmdSetCompanyColour(DoCommandFlags flags, LiveryScheme scheme, bool if (flags.Test(DoCommandFlag::Execute)) { if (primary) { - if (scheme != LS_DEFAULT) AssignBit(c->livery[scheme].in_use, 0, colour != INVALID_COLOUR); + if (scheme != LS_DEFAULT) c->livery[scheme].in_use.Set(Livery::Flag::Primary, colour != INVALID_COLOUR); if (colour == INVALID_COLOUR) colour = c->livery[LS_DEFAULT].colour1; c->livery[scheme].colour1 = colour; @@ -1122,7 +1122,7 @@ CommandCost CmdSetCompanyColour(DoCommandFlags flags, LiveryScheme scheme, bool CompanyAdminUpdate(c); } } else { - if (scheme != LS_DEFAULT) AssignBit(c->livery[scheme].in_use, 1, colour != INVALID_COLOUR); + if (scheme != LS_DEFAULT) c->livery[scheme].in_use.Set(Livery::Flag::Secondary, colour != INVALID_COLOUR); if (colour == INVALID_COLOUR) colour = c->livery[LS_DEFAULT].colour2; c->livery[scheme].colour2 = colour; @@ -1131,16 +1131,16 @@ CommandCost CmdSetCompanyColour(DoCommandFlags flags, LiveryScheme scheme, bool } } - if (c->livery[scheme].in_use != 0) { + if (c->livery[scheme].in_use.Any({Livery::Flag::Primary, Livery::Flag::Secondary})) { /* If enabling a scheme, set the default scheme to be in use too */ - c->livery[LS_DEFAULT].in_use = 1; + c->livery[LS_DEFAULT].in_use.Set(Livery::Flag::Primary); } else { /* Else loop through all schemes to see if any are left enabled. * If not, disable the default scheme too. */ - c->livery[LS_DEFAULT].in_use = 0; + c->livery[LS_DEFAULT].in_use.Reset({Livery::Flag::Primary, Livery::Flag::Secondary}); for (scheme = LS_DEFAULT; scheme < LS_END; scheme++) { - if (c->livery[scheme].in_use != 0) { - c->livery[LS_DEFAULT].in_use = 1; + if (c->livery[scheme].in_use.Any({Livery::Flag::Primary, Livery::Flag::Secondary})) { + c->livery[LS_DEFAULT].in_use.Set(Livery::Flag::Primary); break; } } @@ -1290,27 +1290,29 @@ int CompanyServiceInterval(const Company *c, VehicleType type) } /** - * Get total sum of all owned road bits. - * @return Combined total road road bits. + * Get total sum of all owned track bits. + * @return Combined total rail track bits. */ -uint32_t CompanyInfrastructure::GetRoadTotal() const +uint32_t CompanyInfrastructure::GetRailTotal() const { uint32_t total = 0; - for (RoadType rt = ROADTYPE_BEGIN; rt != ROADTYPE_END; rt++) { - if (RoadTypeIsRoad(rt)) total += this->road[rt]; + for (const auto &[_, count] : this->rail) { + total += count; } return total; } /** - * Get total sum of all owned tram bits. - * @return Combined total of tram road bits. + * Get total sum of all owned road bits. + * @param rtt RoadTramType to get total for. + * @return Combined total road road bits. */ -uint32_t CompanyInfrastructure::GetTramTotal() const +uint32_t CompanyInfrastructure::GetRoadTramTotal(RoadTramType rtt) const { uint32_t total = 0; - for (RoadType rt = ROADTYPE_BEGIN; rt != ROADTYPE_END; rt++) { - if (RoadTypeIsTram(rt)) total += this->road[rt]; + auto mask = GetMaskForRoadTramType(rtt); + for (const auto &[roadtype, count] : this->road) { + if (mask.Test(roadtype)) total += count; } return total; } diff --git a/src/company_cmd.h b/src/company_cmd.h index eb30f9b361b07..a18af2f8cb7eb 100644 --- a/src/company_cmd.h +++ b/src/company_cmd.h @@ -25,12 +25,12 @@ CommandCost CmdRenamePresident(DoCommandFlags flags, const std::string &text); CommandCost CmdSetCompanyManagerFace(DoCommandFlags flags, uint style, uint32_t bits); CommandCost CmdSetCompanyColour(DoCommandFlags flags, LiveryScheme scheme, bool primary, Colours colour); -DEF_CMD_TRAIT(CMD_COMPANY_CTRL, CmdCompanyCtrl, CommandFlags({CommandFlag::Spectator, CommandFlag::ClientID, CommandFlag::NoEst}), CMDT_SERVER_SETTING) -DEF_CMD_TRAIT(CMD_COMPANY_ALLOW_LIST_CTRL, CmdCompanyAllowListCtrl, CommandFlag::NoEst, CMDT_SERVER_SETTING) -DEF_CMD_TRAIT(CMD_GIVE_MONEY, CmdGiveMoney, {}, CMDT_MONEY_MANAGEMENT) -DEF_CMD_TRAIT(CMD_RENAME_COMPANY, CmdRenameCompany, {}, CMDT_COMPANY_SETTING) -DEF_CMD_TRAIT(CMD_RENAME_PRESIDENT, CmdRenamePresident, {}, CMDT_COMPANY_SETTING) -DEF_CMD_TRAIT(CMD_SET_COMPANY_MANAGER_FACE, CmdSetCompanyManagerFace, {}, CMDT_COMPANY_SETTING) -DEF_CMD_TRAIT(CMD_SET_COMPANY_COLOUR, CmdSetCompanyColour, {}, CMDT_COMPANY_SETTING) +DEF_CMD_TRAIT(CMD_COMPANY_CTRL, CmdCompanyCtrl, CommandFlags({CommandFlag::Spectator, CommandFlag::ClientID, CommandFlag::NoEst}), CommandType::ServerSetting) +DEF_CMD_TRAIT(CMD_COMPANY_ALLOW_LIST_CTRL, CmdCompanyAllowListCtrl, CommandFlag::NoEst, CommandType::ServerSetting) +DEF_CMD_TRAIT(CMD_GIVE_MONEY, CmdGiveMoney, {}, CommandType::MoneyManagement) +DEF_CMD_TRAIT(CMD_RENAME_COMPANY, CmdRenameCompany, {}, CommandType::CompanySetting) +DEF_CMD_TRAIT(CMD_RENAME_PRESIDENT, CmdRenamePresident, {}, CommandType::CompanySetting) +DEF_CMD_TRAIT(CMD_SET_COMPANY_MANAGER_FACE, CmdSetCompanyManagerFace, {}, CommandType::CompanySetting) +DEF_CMD_TRAIT(CMD_SET_COMPANY_COLOUR, CmdSetCompanyColour, {}, CommandType::CompanySetting) #endif /* COMPANY_CMD_H */ diff --git a/src/company_gui.cpp b/src/company_gui.cpp index 9debd59c5bbed..30c77add9cc9e 100644 --- a/src/company_gui.cpp +++ b/src/company_gui.cpp @@ -286,7 +286,7 @@ static void DrawYearColumn(const Rect &r, TimerGameEconomy::Year year, const Exp DrawPrice(sum, r.left, r.right, y, TC_WHITE); } -static constexpr NWidgetPart _nested_company_finances_widgets[] = { +static constexpr std::initializer_list _nested_company_finances_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), NWidget(WWT_CAPTION, COLOUR_GREY, WID_CF_CAPTION), @@ -655,7 +655,7 @@ struct SelectCompanyLiveryWindow : public Window { } uint8_t sel; - if (default_livery == nullptr || HasBit(livery->in_use, primary ? 0 : 1)) { + if (default_livery == nullptr || livery->in_use.Test(primary ? Livery::Flag::Primary : Livery::Flag::Secondary)) { sel = primary ? livery->colour1 : livery->colour2; } else { sel = default_col; @@ -819,7 +819,7 @@ struct SelectCompanyLiveryWindow : public Window { } if (scheme == LS_END) scheme = LS_DEFAULT; const Livery *livery = &c->livery[scheme]; - if (scheme == LS_DEFAULT || HasBit(livery->in_use, primary ? 0 : 1)) { + if (scheme == LS_DEFAULT || livery->in_use.Test(primary ? Livery::Flag::Primary : Livery::Flag::Secondary)) { colour = STR_COLOUR_DARK_BLUE + (primary ? livery->colour1 : livery->colour2); } } @@ -827,7 +827,7 @@ struct SelectCompanyLiveryWindow : public Window { if (this->sel != GroupID::Invalid()) { const Group *g = Group::Get(this->sel); const Livery *livery = &g->livery; - if (HasBit(livery->in_use, primary ? 0 : 1)) { + if (livery->in_use.Test(primary ? Livery::Flag::Primary : Livery::Flag::Secondary)) { colour = STR_COLOUR_DARK_BLUE + (primary ? livery->colour1 : livery->colour2); } } @@ -875,12 +875,12 @@ struct SelectCompanyLiveryWindow : public Window { /* Text below the first dropdown. */ DrawSprite(SPR_SQUARE, GetColourPalette(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); + DrawString(pri.left, pri.right, y + text_offs, (is_default_scheme || livery.in_use.Test(Livery::Flag::Primary)) ? 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, GetColourPalette(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); + DrawString(sec.left, sec.right, y + text_offs, (is_default_scheme || livery.in_use.Test(Livery::Flag::Secondary)) ? STR_COLOUR_DARK_BLUE + livery.colour2 : STR_COLOUR_DEFAULT, is_selected ? TC_WHITE : TC_GOLD); } y += this->line_height; @@ -1062,7 +1062,7 @@ struct SelectCompanyLiveryWindow : public Window { } }; -static constexpr NWidgetPart _nested_select_company_livery_widgets[] = { +static constexpr std::initializer_list _nested_select_company_livery_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), NWidget(WWT_CAPTION, COLOUR_GREY, WID_SCL_CAPTION), @@ -1161,7 +1161,7 @@ void DrawCompanyManagerFace(const CompanyManagerFace &cmf, Colours colour, const } /** Nested widget description for the company manager face selection dialog */ -static constexpr NWidgetPart _nested_select_company_manager_face_widgets[] = { +static constexpr std::initializer_list _nested_select_company_manager_face_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), NWidget(WWT_CAPTION, COLOUR_GREY, WID_SCMF_CAPTION), SetStringTip(STR_FACE_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), @@ -1333,8 +1333,8 @@ class SelectCompanyManagerFaceWindow : public Window Rect ir = r.Shrink(WidgetDimensions::scaled.frametext, RectPadding::zero).WithHeight(this->line_height); bool rtl = _current_text_dir == TD_RTL; - Rect br = ir.CentreTo(ir.Width(), SETTING_BUTTON_HEIGHT).WithWidth(SETTING_BUTTON_WIDTH, rtl); - Rect tr = ir.Shrink(RectPadding::zero, WidgetDimensions::scaled.matrix).CentreTo(ir.Width(), GetCharacterHeight(FS_NORMAL)).Indent(SETTING_BUTTON_WIDTH + WidgetDimensions::scaled.hsep_wide, rtl); + Rect br = ir.CentreToHeight(SETTING_BUTTON_HEIGHT).WithWidth(SETTING_BUTTON_WIDTH, rtl); + Rect tr = ir.Shrink(RectPadding::zero, WidgetDimensions::scaled.matrix).CentreToHeight(GetCharacterHeight(FS_NORMAL)).Indent(SETTING_BUTTON_WIDTH + WidgetDimensions::scaled.hsep_wide, rtl); DrawArrowButtons(br.left, br.top, COLOUR_YELLOW, this->selected_var == UINT_MAX - 1 ? this->click_state : 0, true, true); DrawString(tr, GetString(STR_FACE_SETTING_NUMERIC, STR_FACE_STYLE, this->face.style + 1, GetNumCompanyManagerFaceStyles()), TC_WHITE); @@ -1352,8 +1352,8 @@ class SelectCompanyManagerFaceWindow : public Window const uint8_t var = static_cast(*it - vars.data()); const FaceVar &facevar = **it; - Rect br = ir.CentreTo(ir.Width(), SETTING_BUTTON_HEIGHT).WithWidth(SETTING_BUTTON_WIDTH, rtl); - Rect tr = ir.Shrink(RectPadding::zero, WidgetDimensions::scaled.matrix).CentreTo(ir.Width(), GetCharacterHeight(FS_NORMAL)).Indent(SETTING_BUTTON_WIDTH + WidgetDimensions::scaled.hsep_wide, rtl); + Rect br = ir.CentreToHeight(SETTING_BUTTON_HEIGHT).WithWidth(SETTING_BUTTON_WIDTH, rtl); + Rect tr = ir.Shrink(RectPadding::zero, WidgetDimensions::scaled.matrix).CentreToHeight(GetCharacterHeight(FS_NORMAL)).Indent(SETTING_BUTTON_WIDTH + WidgetDimensions::scaled.hsep_wide, rtl); uint val = vars[var].GetBits(this->face); if (facevar.type == FaceVarType::Toggle) { @@ -1384,7 +1384,7 @@ class SelectCompanyManagerFaceWindow : public Window /* OK button */ case WID_SCMF_ACCEPT: - Command::Post(this->face.bits, this->face.style); + Command::Post(this->face.style, this->face.bits); [[fallthrough]]; /* Cancel button */ @@ -1536,7 +1536,7 @@ static void DoSelectCompanyManagerFace(Window *parent) new SelectCompanyManagerFaceWindow(_select_company_manager_face_desc, parent); } -static constexpr NWidgetPart _nested_company_infrastructure_widgets[] = { +static constexpr std::initializer_list _nested_company_infrastructure_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), NWidget(WWT_CAPTION, COLOUR_GREY, WID_CI_CAPTION), @@ -1604,10 +1604,11 @@ struct CompanyInfrastructureWindow : Window this->list.emplace_back(InfrastructureItemType::Header, STR_COMPANY_INFRASTRUCTURE_VIEW_RAIL_SECT); for (const RailType &rt : _sorted_railtypes) { - if (c->infrastructure.rail[rt] == 0) continue; - Money monthly_cost = RailMaintenanceCost(rt, c->infrastructure.rail[rt], rail_total); + auto it = c->infrastructure.rail.find(rt); + if (it == std::end(c->infrastructure.rail) || it->second == 0) continue; + Money monthly_cost = RailMaintenanceCost(rt, it->second, rail_total); total_monthly_cost += monthly_cost; - this->list.emplace_back(InfrastructureItemType::Value, GetRailTypeInfo(rt)->strings.name, c->infrastructure.rail[rt], monthly_cost); + this->list.emplace_back(InfrastructureItemType::Value, GetRailTypeInfo(rt)->strings.name, it->second, monthly_cost); } if (c->infrastructure.signal > 0) { @@ -1624,10 +1625,11 @@ struct CompanyInfrastructureWindow : Window for (const RoadType &rt : _sorted_roadtypes) { if (!RoadTypeIsRoad(rt)) continue; - if (c->infrastructure.road[rt] == 0) continue; - Money monthly_cost = RoadMaintenanceCost(rt, c->infrastructure.road[rt], road_total); + auto it = c->infrastructure.road.find(rt); + if (it == std::end(c->infrastructure.road) || it->second == 0) continue; + Money monthly_cost = RoadMaintenanceCost(rt, it->second, road_total); total_monthly_cost += monthly_cost; - this->list.emplace_back(InfrastructureItemType::Value, GetRoadTypeInfo(rt)->strings.name, c->infrastructure.road[rt], monthly_cost); + this->list.emplace_back(InfrastructureItemType::Value, GetRoadTypeInfo(rt)->strings.name, it->second, monthly_cost); } } @@ -1638,10 +1640,11 @@ struct CompanyInfrastructureWindow : Window for (const RoadType &rt : _sorted_roadtypes) { if (!RoadTypeIsTram(rt)) continue; - if (c->infrastructure.road[rt] == 0) continue; - Money monthly_cost = RoadMaintenanceCost(rt, c->infrastructure.road[rt], tram_total); + auto it = c->infrastructure.road.find(rt); + if (it == std::end(c->infrastructure.road) || it->second == 0) continue; + Money monthly_cost = RoadMaintenanceCost(rt, it->second, tram_total); total_monthly_cost += monthly_cost; - this->list.emplace_back(InfrastructureItemType::Value, GetRoadTypeInfo(rt)->strings.name, c->infrastructure.road[rt], monthly_cost); + this->list.emplace_back(InfrastructureItemType::Value, GetRoadTypeInfo(rt)->strings.name, it->second, monthly_cost); } } @@ -1840,7 +1843,7 @@ static void ShowCompanyInfrastructure(CompanyID company) AllocateWindowDescFront(_company_infrastructure_desc, company); } -static constexpr NWidgetPart _nested_company_widgets[] = { +static constexpr std::initializer_list _nested_company_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), NWidget(WWT_CAPTION, COLOUR_GREY, WID_C_CAPTION), @@ -2072,8 +2075,7 @@ struct CompanyWindow : Window y += GetCharacterHeight(FS_NORMAL); } - /* GetRoadTotal() skips tram pieces, but we actually want road and tram here. */ - uint road_pieces = std::accumulate(std::begin(c->infrastructure.road), std::end(c->infrastructure.road), 0U); + uint road_pieces = c->infrastructure.GetRoadTotal() + c->infrastructure.GetTramTotal(); if (road_pieces != 0) { DrawString(r.left, r.right, y, GetString(STR_COMPANY_VIEW_INFRASTRUCTURE_ROAD, road_pieces)); y += GetCharacterHeight(FS_NORMAL); @@ -2405,7 +2407,7 @@ struct BuyCompanyWindow : Window { Money company_value{}; ///< The value of the company for which the user can buy it. }; -static constexpr NWidgetPart _nested_buy_company_widgets[] = { +static constexpr std::initializer_list _nested_buy_company_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_LIGHT_BLUE), NWidget(WWT_CAPTION, COLOUR_LIGHT_BLUE, WID_BC_CAPTION), diff --git a/src/console_cmds.cpp b/src/console_cmds.cpp index 338c9a209ab0d..1e4479fc162b4 100644 --- a/src/console_cmds.cpp +++ b/src/console_cmds.cpp @@ -46,6 +46,10 @@ #include "company_cmd.h" #include "misc_cmd.h" +#if defined(WITH_ZLIB) +#include "network/network_content.h" +#endif /* WITH_ZLIB */ + #include "table/strings.h" #include "safeguards.h" @@ -2163,7 +2167,7 @@ static bool ConNetworkAuthorizedKey(std::span argv) } for (auto [name, authorized_keys] : _console_cmd_authorized_keys) { - if (StrEqualsIgnoreCase(type, name)) continue; + if (!StrEqualsIgnoreCase(type, name)) continue; PerformNetworkAuthorizedKeyAction(name, authorized_keys, action, authorized_key); return true; @@ -2176,7 +2180,6 @@ static bool ConNetworkAuthorizedKey(std::span argv) /* Content downloading only is available with ZLIB */ #if defined(WITH_ZLIB) -#include "network/network_content.h" /** Resolve a string to a content type. */ static ContentType StringToContentType(std::string_view str) @@ -2699,7 +2702,7 @@ static std::string FormatLabel(uint32_t label) return fmt::format("{:c}{:c}{:c}{:c}", GB(label, 24, 8), GB(label, 16, 8), GB(label, 8, 8), GB(label, 0, 8)); } - return fmt::format("{:08X}", std::byteswap(label)); + return fmt::format("{:08X}", label); } static void ConDumpRoadTypes() @@ -2712,7 +2715,7 @@ static void ConDumpRoadTypes() IConsolePrint(CC_DEFAULT, " T = buildable by towns"); std::map grfs; - for (RoadType rt = ROADTYPE_BEGIN; rt < ROADTYPE_END; rt++) { + for (RoadType rt = ROADTYPE_BEGIN; rt < GetNumRoadTypes(); rt++) { const RoadTypeInfo *rti = GetRoadTypeInfo(rt); if (rti->label == 0) continue; uint32_t grfid = 0; @@ -2750,7 +2753,7 @@ static void ConDumpRailTypes() IConsolePrint(CC_DEFAULT, " d = always disallow 90 degree turns"); std::map grfs; - for (RailType rt = RAILTYPE_BEGIN; rt < RAILTYPE_END; rt++) { + for (RailType rt = RAILTYPE_BEGIN; rt < GetNumRailTypes(); rt++) { const RailTypeInfo *rti = GetRailTypeInfo(rt); if (rti->label == 0) continue; uint32_t grfid = 0; diff --git a/src/console_gui.cpp b/src/console_gui.cpp index db8831f25923e..1dba122e92c2d 100644 --- a/src/console_gui.cpp +++ b/src/console_gui.cpp @@ -133,7 +133,7 @@ static inline void IConsoleResetHistoryPos() static std::optional IConsoleHistoryAdd(std::string_view cmd); static void IConsoleHistoryNavigate(int direction); -static constexpr NWidgetPart _nested_console_window_widgets[] = { +static constexpr std::initializer_list _nested_console_window_widgets = { NWidget(WWT_EMPTY, INVALID_COLOUR, WID_C_BACKGROUND), SetResize(1, 1), }; @@ -453,7 +453,7 @@ void IConsoleClose() static std::optional IConsoleHistoryAdd(std::string_view cmd) { /* Strip all spaces at the begin */ - while (IsWhitespace(cmd[0])) cmd.remove_prefix(1); + while (!cmd.empty() && IsWhitespace(cmd[0])) cmd.remove_prefix(1); /* Do not put empty command in history */ if (cmd.empty()) return std::nullopt; diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 224cfba0eba13..fa76393137a7d 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -22,7 +22,6 @@ add_files( pool_type.hpp random_func.cpp random_func.hpp - smallstack_type.hpp string_builder.cpp string_builder.hpp string_consumer.cpp diff --git a/src/core/base_bitset_type.hpp b/src/core/base_bitset_type.hpp index 9ce8528d3160a..3b50d4e033b9f 100644 --- a/src/core/base_bitset_type.hpp +++ b/src/core/base_bitset_type.hpp @@ -254,8 +254,8 @@ class BaseBitSet { return std::nullopt; } - auto begin() const { return SetBitIterator(this->data).begin(); } - auto end() const { return SetBitIterator(this->data).end(); } + auto begin() const { return SetBitIterator(this->data).begin(); } + auto end() const { return SetBitIterator(this->data).end(); } private: Tstorage data; ///< Bitmask of values. diff --git a/src/core/flatset_type.hpp b/src/core/flatset_type.hpp index 2dc42d0b48107..f114c302f316a 100644 --- a/src/core/flatset_type.hpp +++ b/src/core/flatset_type.hpp @@ -54,7 +54,7 @@ class FlatSet { * @param key Key to test. * @return true iff the key exists in the set. */ - bool contains(const Tkey &key) + bool contains(const Tkey &key) const { return std::ranges::binary_search(this->data, key, Tcompare{}); } @@ -73,4 +73,61 @@ class FlatSet { auto operator<=>(const FlatSet &) const = default; }; +/** + * Adapter for FlatSet that provides part of the (Base)BitSet-like interface. + * @tparam Tkey key type. + * @tparam Tcompare key comparator. + */ +template > +struct FlatBitSet : FlatSet { + FlatBitSet() = default; + + FlatBitSet(Tkey value) + { + this->Set(value); + } + + FlatBitSet(std::initializer_list values) + { + for (const Tkey &value : values) { + this->Set(value); + } + } + + void Set(Tkey value) { this->insert(value); } + + void Set(Tkey value, bool set) + { + if (set) { + this->insert(value); + } else { + this->erase(value); + } + } + + bool Test(Tkey value) const { return this->contains(value); } + + bool Any() const { return this->size() != 0; } + + void Set(const FlatBitSet &other) + { + std::ranges::for_each(other, [this](const Tkey &value) { this->insert(value); }); + } + + void Reset(const FlatBitSet &other) + { + std::ranges::for_each(other, [this](const Tkey &value) { this->erase(value); }); + } + + bool Any(const FlatBitSet &other) const + { + return std::ranges::any_of(other, [this](const Tkey &value) { return this->contains(value); }); + } + + bool All(const FlatBitSet &other) const + { + return std::ranges::all_of(other, [this](const Tkey &value) { return this->contains(value); }); + } +}; + #endif /* FLATSET_TYPE_HPP */ diff --git a/src/core/geometry_type.hpp b/src/core/geometry_type.hpp index b3400c2cc3eff..e46315899ebb0 100644 --- a/src/core/geometry_type.hpp +++ b/src/core/geometry_type.hpp @@ -62,14 +62,14 @@ struct Dimension { bool operator< (const Dimension &other) const { - int x = (*this).width - other.width; + int x = this->width - other.width; if (x != 0) return x < 0; - return (*this).height < other.height; + return this->height < other.height; } bool operator== (const Dimension &other) const { - return (*this).width == other.width && (*this).height == other.height; + return this->width == other.width && this->height == other.height; } }; @@ -211,8 +211,8 @@ struct Rect { [[nodiscard]] inline Rect WithWidth(int width, bool end) const { return end - ? Rect {this->right - width + 1, this->top, this->right, this->bottom} - : Rect {this->left, this->top, this->left + width - 1, this->bottom}; + ? this->WithX(this->right - width + 1, this->right) + : this->WithX(this->left, this->left + width - 1); } /** @@ -224,21 +224,21 @@ struct Rect { [[nodiscard]] inline Rect Indent(int indent, bool end) const { return end - ? Rect {this->left, this->top, this->right - indent, this->bottom} - : Rect {this->left + indent, this->top, this->right, this->bottom}; + ? this->WithX(this->left, this->right - indent) + : this->WithX(this->left + indent, this->right); } /** * Copy Rect and set its height. - * @param width height in pixels for new Rect. + * @param height height in pixels for new Rect. * @param end if set, set height at end of Rect, i.e. at bottom. * @return the new resized Rect. */ [[nodiscard]] inline Rect WithHeight(int height, bool end = false) const { return end - ? Rect {this->left, this->bottom - height + 1, this->right, this->bottom} - : Rect {this->left, this->top, this->right, this->top + height - 1}; + ? this->WithY(this->bottom - height + 1, this->bottom) + : this->WithY(this->top, this->top + height - 1); } /** @@ -253,17 +253,45 @@ struct Rect { } /** - * Centre a dimension within this Rect. - * @param width The horizontal dimension. + * Centre a vertical dimension within this Rect. * @param height The vertical dimension. * @return the new resized Rect. */ - [[nodiscard]] inline Rect CentreTo(int width, int height) const + [[nodiscard]] inline Rect CentreToHeight(int height) const { - int new_left = CentreBounds(this->left, this->right, width); - int new_right = CentreBounds(this->top, this->bottom, height); - return {new_left, new_right, new_left + width, new_right + height}; + int new_top = CentreBounds(this->top, this->bottom, height); + return {this->left, new_top, this->right, new_top + height - 1}; } + + /** + * Create a new Rect, replacing the left and right coordiates. + * @param new_left New left coordinate. + * @param new_right New right coordinate. + * @return The new Rect. + */ + [[nodiscard]] inline Rect WithX(int new_left, int new_right) const { return {new_left, this->top, new_right, this->bottom}; } + + /** + * Create a new Rect, replacing the top and bottom coordiates. + * @param new_top New top coordinate. + * @param new_bottom New bottom coordinate. + * @return The new Rect. + */ + [[nodiscard]] inline Rect WithY(int new_top, int new_bottom) const { return {this->left, new_top, this->right, new_bottom}; } + + /** + * Create a new Rect, replacing the left and right coordiates. + * @param other Rect containing the new left and right coordinates. + * @return The new Rect. + */ + [[nodiscard]] inline Rect WithX(const Rect &other) const { return this->WithX(other.left, other.right); } + + /** + * Create a new Rect, replacing the top and bottom coordiates. + * @param other Rect containing the new top and bottom coordinates. + * @return The new Rect. + */ + [[nodiscard]] inline Rect WithY(const Rect &other) const { return this->WithY(other.top, other.bottom); } }; /** diff --git a/src/core/smallstack_type.hpp b/src/core/smallstack_type.hpp deleted file mode 100644 index 3b26951453bbf..0000000000000 --- a/src/core/smallstack_type.hpp +++ /dev/null @@ -1,266 +0,0 @@ -/* - * 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 smallstack_type.hpp Minimal stack that uses a pool to avoid pointers and doesn't allocate any heap memory if there is only one valid item. */ - -#ifndef SMALLSTACK_TYPE_HPP -#define SMALLSTACK_TYPE_HPP - -/** - * A simplified pool which stores values instead of pointers and doesn't - * redefine operator new/delete. It also never zeroes memory and always reuses - * it. - */ -template -class SimplePool { -public: - inline SimplePool() : first_unused(0), first_free(0) {} - - /** - * Get the item at position index. - * @return Item at index. - */ - inline Titem &Get(Tindex index) { return this->data[index]; } - - /** - * Create a new item and return its index. - * @return Index of new item. - */ - inline Tindex Create() - { - Tindex index = this->FindFirstFree(); - if (index < Tmax_size) { - this->data[index].valid = true; - this->first_free = index + 1; - this->first_unused = std::max(this->first_unused, this->first_free); - } - return index; - } - - /** - * Destroy (or rather invalidate) the item at the given index. - * @param index Index of item to be destroyed. - */ - inline void Destroy(Tindex index) - { - this->data[index].valid = false; - this->first_free = std::min(this->first_free, index); - } - -private: - - inline Tindex FindFirstFree() - { - Tindex index = this->first_free; - for (; index < this->first_unused; index++) { - if (!this->data[index].valid) return index; - } - - if (index >= this->data.size() && index < Tmax_size) { - this->data.resize(index + 1); - } - return index; - } - - struct SimplePoolPoolItem : public Titem { - bool valid; - }; - - Tindex first_unused; - Tindex first_free; - - std::vector data; -}; - -/** - * Base class for SmallStack. We cannot add this into SmallStack itself as - * certain compilers don't like it. - */ -template -struct SmallStackItem { - Tindex next; ///< Pool index of next item. - Titem value; ///< Value of current item. - - /** - * Create a new item. - * @param value Value of the item. - * @param next Next item in the stack. - */ - inline SmallStackItem(const Titem &value, Tindex next) : - next(next), value(value) {} - SmallStackItem() = default; -}; - -/** - * Minimal stack that uses a pool to avoid pointers. It has some peculiar - * properties that make it useful for passing around lists of IDs but not much - * else: - * 1. It always includes an invalid item as bottom. - * 2. It doesn't have a deep copy operation but uses smart pointers instead. - * Every copy is thus implicitly shared. - * 3. Its items are immutable. - * 4. Due to 2. and 3. memory management can be done by "branch counting". - * Whenever you copy a smallstack, the first item on the heap increases its - * branch_count, signifying that there are multiple items "in front" of it. - * When deleting a stack items are deleted up to the point where - * branch_count > 0. - * 5. You can choose your own index type, so that you can align it with your - * value type. E.G. value types of 16 bits length like to be combined with - * index types of the same length. - * @tparam Titem Value type to be used. - * @tparam Tindex Index type to use for the pool. - * @tparam Tinvalid_value Value to construct invalid item to keep at the bottom of each stack. - * @tparam Tgrowth_step Growth step for pool. - * @tparam Tmax_size Maximum size for pool. - */ -template -class SmallStack : public SmallStackItem { -public: - static constexpr Titem Tinvalid{Tinvalid_value}; - - typedef SmallStackItem Item; - - /** - * SmallStack item that can be kept in a pool. - */ - struct PooledSmallStack : public Item { - Tindex branch_count; ///< Number of branches in the tree structure this item is parent of - }; - - typedef SimplePool SmallStackPool; - - /** - * Constructor for a stack with one or two items in it. - * @param value Initial item. If not missing or Tinvalid there will be Tinvalid below it. - */ - inline SmallStack(const Titem &value = Tinvalid) : Item(value, Tmax_size) {} - - /** - * Remove the head of stack and all other items members that are unique to it. - */ - inline ~SmallStack() - { - while (this->next != Tmax_size) this->Pop(); - } - - /** - * Shallow copy the stack, marking the first item as branched. - * @param other Stack to copy from - */ - inline SmallStack(const SmallStack &other) : Item(other) { this->Branch(); } - - /** - * Shallow copy the stack, marking the first item as branched. - * @param other Stack to copy from - * @return This smallstack. - */ - inline SmallStack &operator=(const SmallStack &other) - { - if (this == &other) return *this; - while (this->next != Tmax_size) this->Pop(); - this->next = other.next; - this->value = other.value; - /* Deleting and branching are independent operations, so it's fine to - * acquire separate locks for them. */ - this->Branch(); - return *this; - } - - /** - * Pushes a new item onto the stack if there is still space in the - * underlying pool. Otherwise the topmost item's value gets overwritten. - * @param item Item to be pushed. - */ - inline void Push(const Titem &item) - { - if (this->value != Tinvalid) { - Tindex new_item = SmallStack::GetPool().Create(); - if (new_item != Tmax_size) { - PooledSmallStack &pushed = SmallStack::GetPool().Get(new_item); - pushed.value = this->value; - pushed.next = this->next; - pushed.branch_count = 0; - this->next = new_item; - } - } - this->value = item; - } - - /** - * Pop an item from the stack. - * @return Current top of stack. - */ - inline Titem Pop() - { - Titem ret = this->value; - if (this->next == Tmax_size) { - this->value = Tinvalid; - } else { - PooledSmallStack &popped = SmallStack::GetPool().Get(this->next); - this->value = popped.value; - if (popped.branch_count == 0) { - SmallStack::GetPool().Destroy(this->next); - } else { - --popped.branch_count; - if (popped.next != Tmax_size) { - ++(SmallStack::GetPool().Get(popped.next).branch_count); - } - } - /* Accessing popped here is no problem as the pool will only set - * the validity flag, not actually delete the item, on Destroy(). */ - this->next = popped.next; - } - return ret; - } - - /** - * Check if the stack is empty. - * @return If the stack is empty. - */ - inline bool IsEmpty() const - { - return this->value == Tinvalid && this->next == Tmax_size; - } - - /** - * Check if the given item is contained in the stack. - * @param item Item to look for. - * @return If the item is in the stack. - */ - inline bool Contains(const Titem &item) const - { - if (item == Tinvalid || item == this->value) return true; - if (this->next != Tmax_size) { - const SmallStack *in_list = this; - do { - in_list = static_cast( - static_cast(&SmallStack::GetPool().Get(in_list->next))); - if (in_list->value == item) return true; - } while (in_list->next != Tmax_size); - } - return false; - } - -protected: - static SmallStackPool &GetPool() - { - static SmallStackPool pool; - return pool; - } - - /** - * Create a branch in the pool if necessary. - */ - inline void Branch() - { - if (this->next != Tmax_size) { - ++(SmallStack::GetPool().Get(this->next).branch_count); - } - } -}; - -#endif diff --git a/src/core/strong_typedef_type.hpp b/src/core/strong_typedef_type.hpp index a89ec0460f08d..e818228d5057c 100644 --- a/src/core/strong_typedef_type.hpp +++ b/src/core/strong_typedef_type.hpp @@ -158,4 +158,31 @@ namespace StrongType { }; } +/** + * Implementation of std::hash for StrongType::Typedef. + * + * This specialization of std::hash allows hashing of StrongType::Typedef instances + * by leveraging the hash of the base type. + * + * Example Usage: + * using MyType = StrongType::Typedef; + * std::unordered_map my_map; + * + * @tparam TBaseType The underlying type of the StrongType::Typedef. + * @tparam TProperties Additional properties for the StrongType::Typedef. + */ +template +struct std::hash> { + /** + * Computes the hash value for a StrongType::Typedef instance. + * + * @param t The StrongType::Typedef instance to hash. + * @return The hash value of the base type of t. + */ + std::size_t operator()(const StrongType::Typedef &t) const noexcept + { + return std::hash()(t.base()); + } +}; + #endif /* STRONG_TYPEDEF_TYPE_HPP */ diff --git a/src/date_gui.cpp b/src/date_gui.cpp index 02ab436d6335d..81dbbd5ffcfdf 100644 --- a/src/date_gui.cpp +++ b/src/date_gui.cpp @@ -173,7 +173,7 @@ struct SetDateWindow : Window { }; /** Widgets for the date setting window. */ -static constexpr NWidgetPart _nested_set_date_widgets[] = { +static constexpr std::initializer_list _nested_set_date_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_BROWN), NWidget(WWT_CAPTION, COLOUR_BROWN), SetStringTip(STR_DATE_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), diff --git a/src/depot_cmd.h b/src/depot_cmd.h index abd3e1900e9fe..69f558f6c5cab 100644 --- a/src/depot_cmd.h +++ b/src/depot_cmd.h @@ -16,7 +16,7 @@ CommandCost CmdRenameDepot(DoCommandFlags flags, DepotID depot_id, const std::string &text); -DEF_CMD_TRAIT(CMD_RENAME_DEPOT, CmdRenameDepot, {}, CMDT_OTHER_MANAGEMENT) +DEF_CMD_TRAIT(CMD_RENAME_DEPOT, CmdRenameDepot, {}, CommandType::OtherManagement) void CcCloneVehicle(Commands cmd, const CommandCost &result, VehicleID veh_id); diff --git a/src/depot_gui.cpp b/src/depot_gui.cpp index d4ad2baa9ce43..bfec17d9aafa5 100644 --- a/src/depot_gui.cpp +++ b/src/depot_gui.cpp @@ -17,7 +17,7 @@ #include "viewport_func.h" #include "command_func.h" #include "depot_base.h" -#include "spritecache.h" +#include "spritecache_type.h" #include "strings_func.h" #include "sound_func.h" #include "vehicle_func.h" @@ -47,7 +47,7 @@ */ /** Nested widget definition for train depots. */ -static constexpr NWidgetPart _nested_train_depot_widgets[] = { +static constexpr std::initializer_list _nested_train_depot_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), NWidget(NWID_SELECTION, INVALID_COLOUR, WID_D_SHOW_RENAME), SetAspect(WidgetDimensions::ASPECT_RENAME), // rename button @@ -229,7 +229,7 @@ void InitDepotWindowBlockSizes() if (!e->IsEnabled()) continue; uint w = TRAININFO_DEFAULT_VEHICLE_WIDTH; - if (e->GetGRF() != nullptr && IsCustomVehicleSpriteNum(e->u.rail.image_index)) { + if (e->GetGRF() != nullptr && IsCustomVehicleSpriteNum(e->VehInfo().image_index)) { w = e->GetGRF()->traininfo_vehicle_width; if (w != VEHICLEINFO_FULL_VEHICLE_WIDTH) { /* Hopeless. @@ -260,7 +260,7 @@ struct DepotWindow : Window { VehicleType type = VEH_INVALID; bool generate_list = true; bool check_unitnumber_digits = true; - WidgetID hovered_widget = -1; ///< Index of the widget being hovered during drag/drop. -1 if no drag is in progress. + WidgetID hovered_widget = INVALID_WIDGET; ///< Index of the widget being hovered during drag/drop. \c INVALID_WIDGET if no drag is in progress. VehicleList vehicle_list{}; VehicleList wagon_list{}; uint unitnumber_digits = 2; @@ -1001,10 +1001,10 @@ struct DepotWindow : Window { this->vehicle_over = VehicleID::Invalid(); this->SetWidgetDirty(WID_D_MATRIX); - if (this->hovered_widget != -1) { + if (this->hovered_widget != INVALID_WIDGET) { this->SetWidgetLoweredState(this->hovered_widget, false); this->SetWidgetDirty(this->hovered_widget); - this->hovered_widget = -1; + this->hovered_widget = INVALID_WIDGET; } } @@ -1116,7 +1116,7 @@ struct DepotWindow : Window { this->SetDirty(); break; } - this->hovered_widget = -1; + this->hovered_widget = INVALID_WIDGET; _cursor.vehchain = false; } diff --git a/src/dock_gui.cpp b/src/dock_gui.cpp index 4e44efc3d992a..82aec53970eb5 100644 --- a/src/dock_gui.cpp +++ b/src/dock_gui.cpp @@ -98,7 +98,7 @@ static TileIndex GetOtherAqueductEnd(TileIndex tile_from, TileIndex *tile_to = n /** Toolbar window for constructing water infrastructure. */ struct BuildDocksToolbarWindow : Window { - DockToolbarWidgets last_clicked_widget = WID_DT_INVALID; ///< Contains the last widget that has been clicked on this toolbar. + WidgetID last_clicked_widget = INVALID_WIDGET; ///< Contains the last widget that has been clicked on this toolbar. BuildDocksToolbarWindow(WindowDesc &desc, WindowNumber window_number) : Window(desc) { @@ -189,7 +189,7 @@ struct BuildDocksToolbarWindow : Window { default: return; } - this->last_clicked_widget = (DockToolbarWidgets)widget; + this->last_clicked_widget = widget; } void OnPlaceObject([[maybe_unused]] Point pt, TileIndex tile) override @@ -238,7 +238,7 @@ struct BuildDocksToolbarWindow : Window { break; case WID_DT_BUILD_AQUEDUCT: // Build aqueduct button - Command::Post(STR_ERROR_CAN_T_BUILD_AQUEDUCT_HERE, CcBuildBridge, tile, GetOtherAqueductEnd(tile), TRANSPORT_WATER, 0, 0); + Command::Post(STR_ERROR_CAN_T_BUILD_AQUEDUCT_HERE, CcBuildBridge, tile, GetOtherAqueductEnd(tile), TRANSPORT_WATER, 0, INVALID_RAILTYPE, INVALID_ROADTYPE); break; default: NOT_REACHED(); @@ -250,6 +250,11 @@ struct BuildDocksToolbarWindow : Window { VpSelectTilesWithMethod(pt.x, pt.y, select_method); } + Point OnInitialPosition(int16_t sm_width, [[maybe_unused]] int16_t sm_height, [[maybe_unused]] int window_number) override + { + return AlignInitialConstructionToolbar(sm_width); + } + void OnPlaceMouseUp([[maybe_unused]] ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, [[maybe_unused]] Point pt, TileIndex start_tile, TileIndex end_tile) override { if (pt.x != -1) { @@ -333,7 +338,7 @@ struct BuildDocksToolbarWindow : Window { * Nested widget parts of docks toolbar, game version. * Position of #WID_DT_RIVER widget has changed. */ -static constexpr NWidgetPart _nested_build_docks_toolbar_widgets[] = { +static constexpr std::initializer_list _nested_build_docks_toolbar_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN), NWidget(WWT_CAPTION, COLOUR_DARK_GREEN), SetStringTip(STR_WATERWAYS_TOOLBAR_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), @@ -352,7 +357,7 @@ static constexpr NWidgetPart _nested_build_docks_toolbar_widgets[] = { }; static WindowDesc _build_docks_toolbar_desc( - WDP_ALIGN_TOOLBAR, "toolbar_water", 0, 0, + WDP_MANUAL, "toolbar_water", 0, 0, WC_BUILD_TOOLBAR, WC_NONE, WindowDefaultFlag::Construction, _nested_build_docks_toolbar_widgets, @@ -378,7 +383,7 @@ Window *ShowBuildDocksToolbar() * Nested widget parts of docks toolbar, scenario editor version. * Positions of #WID_DT_DEPOT, #WID_DT_STATION, and #WID_DT_BUOY widgets have changed. */ -static constexpr NWidgetPart _nested_build_docks_scen_toolbar_widgets[] = { +static constexpr std::initializer_list _nested_build_docks_scen_toolbar_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN), NWidget(WWT_CAPTION, COLOUR_DARK_GREEN), SetStringTip(STR_WATERWAYS_TOOLBAR_CAPTION_SE, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), @@ -412,21 +417,12 @@ Window *ShowBuildDocksScenToolbar() return AllocateWindowDescFront(_build_docks_scen_toolbar_desc, TRANSPORT_WATER); } -/** Widget numbers of the build-dock GUI. */ -enum BuildDockStationWidgets { - BDSW_BACKGROUND, ///< Background panel. - BDSW_LT_OFF, ///< 'Off' button of coverage high light. - BDSW_LT_ON, ///< 'On' button of coverage high light. - BDSW_INFO, ///< 'Coverage highlight' label. - BDSW_ACCEPTANCE, ///< Acceptance info. -}; - struct BuildDocksStationWindow : public PickerWindowBase { public: BuildDocksStationWindow(WindowDesc &desc, Window *parent) : PickerWindowBase(desc, parent) { this->InitNested(TRANSPORT_WATER); - this->LowerWidget(_settings_client.gui.station_show_coverage + BDSW_LT_OFF); + this->LowerWidget(_settings_client.gui.station_show_coverage + WID_BDSW_LT_OFF); } void Close([[maybe_unused]] int data = 0) override @@ -448,7 +444,7 @@ struct BuildDocksStationWindow : public PickerWindowBase { } /* strings such as 'Size' and 'Coverage Area' */ - Rect r = this->GetWidget(BDSW_ACCEPTANCE)->GetCurrentRect(); + Rect r = this->GetWidget(WID_BDSW_ACCEPTANCE)->GetCurrentRect(); const int bottom = r.bottom; r.bottom = INT_MAX; // Allow overflow as we want to know the required height. r.top = DrawStationCoverageAreaText(r, SCT_ALL, rad, false) + WidgetDimensions::scaled.vsep_normal; @@ -464,11 +460,11 @@ struct BuildDocksStationWindow : public PickerWindowBase { void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override { switch (widget) { - case BDSW_LT_OFF: - case BDSW_LT_ON: - this->RaiseWidget(_settings_client.gui.station_show_coverage + BDSW_LT_OFF); - _settings_client.gui.station_show_coverage = (widget != BDSW_LT_OFF); - this->LowerWidget(_settings_client.gui.station_show_coverage + BDSW_LT_OFF); + case WID_BDSW_LT_OFF: + case WID_BDSW_LT_ON: + this->RaiseWidget(_settings_client.gui.station_show_coverage + WID_BDSW_LT_OFF); + _settings_client.gui.station_show_coverage = (widget != WID_BDSW_LT_OFF); + this->LowerWidget(_settings_client.gui.station_show_coverage + WID_BDSW_LT_OFF); SndClickBeep(); this->SetDirty(); SetViewportCatchmentStation(nullptr, true); @@ -487,21 +483,21 @@ struct BuildDocksStationWindow : public PickerWindowBase { }; /** Nested widget parts of a build dock station window. */ -static constexpr NWidgetPart _nested_build_dock_station_widgets[] = { +static constexpr std::initializer_list _nested_build_dock_station_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN), NWidget(WWT_CAPTION, COLOUR_DARK_GREEN), SetStringTip(STR_STATION_BUILD_DOCK_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), EndContainer(), - NWidget(WWT_PANEL, COLOUR_DARK_GREEN, BDSW_BACKGROUND), + NWidget(WWT_PANEL, COLOUR_DARK_GREEN, WID_BDSW_BACKGROUND), NWidget(NWID_VERTICAL), SetPIP(0, WidgetDimensions::unscaled.vsep_normal, 0), SetPadding(WidgetDimensions::unscaled.picker), NWidget(NWID_VERTICAL), SetPIP(0, WidgetDimensions::unscaled.vsep_picker, 0), - NWidget(WWT_LABEL, INVALID_COLOUR, BDSW_INFO), SetStringTip(STR_STATION_BUILD_COVERAGE_AREA_TITLE), SetFill(1, 0), + NWidget(WWT_LABEL, INVALID_COLOUR, WID_BDSW_INFO), SetStringTip(STR_STATION_BUILD_COVERAGE_AREA_TITLE), SetFill(1, 0), NWidget(NWID_HORIZONTAL, NWidContainerFlag::EqualSize), SetPIP(14, 0, 14), - NWidget(WWT_TEXTBTN, COLOUR_GREY, BDSW_LT_OFF), SetMinimalSize(60, 12), SetFill(1, 0), SetStringTip(STR_STATION_BUILD_COVERAGE_OFF, STR_STATION_BUILD_COVERAGE_AREA_OFF_TOOLTIP), - NWidget(WWT_TEXTBTN, COLOUR_GREY, BDSW_LT_ON), SetMinimalSize(60, 12), SetFill(1, 0), SetStringTip(STR_STATION_BUILD_COVERAGE_ON, STR_STATION_BUILD_COVERAGE_AREA_ON_TOOLTIP), + NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_BDSW_LT_OFF), SetMinimalSize(60, 12), SetFill(1, 0), SetStringTip(STR_STATION_BUILD_COVERAGE_OFF, STR_STATION_BUILD_COVERAGE_AREA_OFF_TOOLTIP), + NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_BDSW_LT_ON), SetMinimalSize(60, 12), SetFill(1, 0), SetStringTip(STR_STATION_BUILD_COVERAGE_ON, STR_STATION_BUILD_COVERAGE_AREA_ON_TOOLTIP), EndContainer(), EndContainer(), - NWidget(WWT_EMPTY, INVALID_COLOUR, BDSW_ACCEPTANCE), SetResize(0, 1), SetMinimalTextLines(2, WidgetDimensions::unscaled.vsep_normal), + NWidget(WWT_EMPTY, INVALID_COLOUR, WID_BDSW_ACCEPTANCE), SetResize(0, 1), SetMinimalTextLines(2, WidgetDimensions::unscaled.vsep_normal), EndContainer(), EndContainer(), }; @@ -588,7 +584,7 @@ struct BuildDocksDepotWindow : public PickerWindowBase { } }; -static constexpr NWidgetPart _nested_build_docks_depot_widgets[] = { +static constexpr std::initializer_list _nested_build_docks_depot_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN), NWidget(WWT_CAPTION, COLOUR_DARK_GREEN), SetStringTip(STR_DEPOT_BUILD_SHIP_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), diff --git a/src/driver.cpp b/src/driver.cpp index 70e2071524379..10b0f890b4dc1 100644 --- a/src/driver.cpp +++ b/src/driver.cpp @@ -145,11 +145,12 @@ bool DriverFactoryBase::SelectDriverImpl(const std::string &name, Driver::Type t /* Keep old driver in case we need to switch back, or may still need to process an OS callback. */ auto oldd = std::move(GetActiveDriver(type)); - GetActiveDriver(type) = d->CreateInstance(); + auto newd = d->CreateInstance(); - auto err = GetActiveDriver(type)->Start({}); + auto err = newd->Start({}); if (!err) { Debug(driver, 1, "Successfully probed {} driver '{}'", GetDriverTypeName(type), d->name); + GetActiveDriver(type) = std::move(newd); return true; } diff --git a/src/dropdown.cpp b/src/dropdown.cpp index 2b2570f3db8ad..30e56c3fb2b30 100644 --- a/src/dropdown.cpp +++ b/src/dropdown.cpp @@ -56,7 +56,7 @@ std::unique_ptr MakeDropDownListCheckedItem(bool checked, Stri return std::make_unique(indent, checked, GetString(str), value, masked, shaded); } -static constexpr NWidgetPart _nested_dropdown_menu_widgets[] = { +static constexpr std::initializer_list _nested_dropdown_menu_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_PANEL, COLOUR_END, WID_DM_ITEMS), SetScrollbar(WID_DM_SCROLL), EndContainer(), NWidget(NWID_SELECTION, INVALID_COLOUR, WID_DM_SHOW_SCROLL), @@ -248,7 +248,7 @@ struct DropdownWindow : Window { if (y < item_height) { if (item->masked || !item->Selectable()) return false; result = item->result; - click_result = item->OnClick({r.left, 0, r.right, item_height - 1}, {_cursor.pos.x - this->left, y}); + click_result = item->OnClick(r.WithY(0, item_height - 1), {_cursor.pos.x - this->left, y}); return true; } @@ -274,7 +274,7 @@ struct DropdownWindow : Window { if (--pos >= 0) continue; if (y + item_height - 1 <= ir.bottom) { - Rect full{ir.left, y, ir.right, y + item_height - 1}; + Rect full = ir.WithY(y, y + item_height - 1); bool selected = (this->selected_result == item->result) && item->Selectable(); if (selected) GfxFillRect(full, PC_BLACK); diff --git a/src/dropdown_common_type.h b/src/dropdown_common_type.h index 80362f6712f17..dac1500d46139 100644 --- a/src/dropdown_common_type.h +++ b/src/dropdown_common_type.h @@ -41,8 +41,8 @@ class DropDownDivider : public TBase { PixelColour c2 = GetColourGradient(bg_colour, SHADE_LIGHTEST); int mid = CentreBounds(full.top, full.bottom, 0); - GfxFillRect(full.left, mid - WidgetDimensions::scaled.bevel.bottom, full.right, mid - 1, c1); - GfxFillRect(full.left, mid, full.right, mid + WidgetDimensions::scaled.bevel.top - 1, c2); + GfxFillRect(full.WithY(mid - WidgetDimensions::scaled.bevel.bottom, mid - 1), c1); + GfxFillRect(full.WithY(mid, mid + WidgetDimensions::scaled.bevel.top - 1), c2); } }; @@ -216,7 +216,7 @@ class DropDownToggle : public TBase { bool rtl = TEnd ^ (_current_text_dir == TD_RTL); int w = SETTING_BUTTON_WIDTH; - if (r.WithWidth(w, rtl).CentreTo(w, SETTING_BUTTON_HEIGHT).Contains(pt)) return this->click; + if (r.WithWidth(w, rtl).CentreToHeight(SETTING_BUTTON_HEIGHT).Contains(pt)) return this->click; return this->TBase::OnClick(r.Indent(w + WidgetDimensions::scaled.hsep_wide, rtl), pt); } @@ -226,7 +226,7 @@ class DropDownToggle : public TBase { bool rtl = TEnd ^ (_current_text_dir == TD_RTL); int w = SETTING_BUTTON_WIDTH; - Rect br = r.WithWidth(w, rtl).CentreTo(w, SETTING_BUTTON_HEIGHT); + Rect br = r.WithWidth(w, rtl).CentreToHeight(SETTING_BUTTON_HEIGHT); DrawBoolButton(br.left, br.top, this->button_colour, this->background_colour, this->on, true); this->TBase::Draw(full, r.Indent(w + WidgetDimensions::scaled.hsep_wide, rtl), sel, click_result, bg_colour); @@ -260,6 +260,32 @@ class DropDownIndent : public TBase { } }; +/** + * Drop down spacer component. + * @tparam TBase Base component. + * @tparam TEnd Position space at end if true, or start if false. + */ +template +class DropDownSpacer : public TBase { +public: + template + explicit DropDownSpacer(Args&&... args) : TBase(std::forward(args)...) {} + + uint Width() const override { return WidgetDimensions::scaled.hsep_wide + this->TBase::Width(); } + + int OnClick(const Rect &r, const Point &pt) const override + { + bool rtl = TEnd ^ (_current_text_dir == TD_RTL); + return this->TBase::OnClick(r.Indent(WidgetDimensions::scaled.hsep_wide, rtl), pt); + } + + void Draw(const Rect &full, const Rect &r, bool sel, int click_result, Colours bg_colour) const override + { + bool rtl = TEnd ^ (_current_text_dir == TD_RTL); + this->TBase::Draw(full, r.Indent(WidgetDimensions::scaled.hsep_wide, rtl), sel, click_result, bg_colour); + } +}; + /** * Drop down component that makes the item unselectable. * @tparam TBase Base component. diff --git a/src/economy.cpp b/src/economy.cpp index 824066e898e2b..d8d4cecc5926c 100644 --- a/src/economy.cpp +++ b/src/economy.cpp @@ -655,14 +655,14 @@ static void CompaniesGenStatistics() CommandCost cost(EXPENSES_PROPERTY); uint32_t rail_total = c->infrastructure.GetRailTotal(); - for (RailType rt = RAILTYPE_BEGIN; rt < RAILTYPE_END; rt++) { - if (c->infrastructure.rail[rt] != 0) cost.AddCost(RailMaintenanceCost(rt, c->infrastructure.rail[rt], rail_total)); + for (const auto &[railtype, count] : c->infrastructure.rail) { + if (count != 0) cost.AddCost(RailMaintenanceCost(railtype, count, rail_total)); } cost.AddCost(SignalMaintenanceCost(c->infrastructure.signal)); uint32_t road_total = c->infrastructure.GetRoadTotal(); uint32_t tram_total = c->infrastructure.GetTramTotal(); - for (RoadType rt = ROADTYPE_BEGIN; rt < ROADTYPE_END; rt++) { - if (c->infrastructure.road[rt] != 0) cost.AddCost(RoadMaintenanceCost(rt, c->infrastructure.road[rt], RoadTypeIsRoad(rt) ? road_total : tram_total)); + for (const auto &[roadtype, count] : c->infrastructure.road) { + if (count != 0) cost.AddCost(RoadMaintenanceCost(roadtype, count, RoadTypeIsRoad(roadtype) ? road_total : tram_total)); } cost.AddCost(CanalMaintenanceCost(c->infrastructure.water)); cost.AddCost(StationMaintenanceCost(c->infrastructure.station)); @@ -1270,7 +1270,8 @@ void PrepareUnload(Vehicle *front_v) assert(CargoPayment::CanAllocateItem()); front_v->cargo_payment = new CargoPayment(front_v); - StationIDStack next_station = front_v->GetNextStoppingStation(); + std::vector next_station; + front_v->GetNextStoppingStation(next_station); if (front_v->orders == nullptr || (front_v->current_order.GetUnloadType() & OUFB_NO_UNLOAD) == 0) { Station *st = Station::Get(front_v->last_station_visited); for (Vehicle *v = front_v; v != nullptr; v = v->Next()) { @@ -1433,7 +1434,7 @@ struct FinalizeRefitAction { CargoArray &consist_capleft; ///< Capacities left in the consist. Station *st; ///< Station to reserve cargo from. - StationIDStack &next_station; ///< Next hops to reserve cargo for. + std::span next_station; ///< Next hops to reserve cargo for. bool do_reserve; ///< If the vehicle should reserve. /** @@ -1443,7 +1444,7 @@ struct FinalizeRefitAction * @param next_station Next hops to reserve cargo for. * @param do_reserve If we should reserve cargo or just add up the capacities. */ - FinalizeRefitAction(CargoArray &consist_capleft, Station *st, StationIDStack &next_station, bool do_reserve) : + FinalizeRefitAction(CargoArray &consist_capleft, Station *st, std::span next_station, bool do_reserve) : consist_capleft(consist_capleft), st(st), next_station(next_station), do_reserve(do_reserve) {} /** @@ -1471,7 +1472,7 @@ struct FinalizeRefitAction * @param next_station Possible next stations the vehicle can travel to. * @param new_cargo_type Target cargo for refit. */ -static void HandleStationRefit(Vehicle *v, CargoArray &consist_capleft, Station *st, StationIDStack next_station, CargoType new_cargo_type) +static void HandleStationRefit(Vehicle *v, CargoArray &consist_capleft, Station *st, std::span next_station, CargoType new_cargo_type) { Vehicle *v_start = v->GetFirstEnginePart(); if (!IterateVehicleParts(v_start, IsEmptyAction())) return; @@ -1538,16 +1539,16 @@ static bool MayLoadUnderExclusiveRights(const Station *st, const Vehicle *v) struct ReserveCargoAction { Station *st; - StationIDStack *next_station; + std::span next_station; - ReserveCargoAction(Station *st, StationIDStack *next_station) : + ReserveCargoAction(Station *st, std::span next_station) : st(st), next_station(next_station) {} bool operator()(Vehicle *v) { if (v->cargo_cap > v->cargo.RemainingCount() && MayLoadUnderExclusiveRights(st, v)) { st->goods[v->cargo_type].GetOrCreateData().cargo.Reserve(v->cargo_cap - v->cargo.RemainingCount(), - &v->cargo, *next_station, v->GetCargoTile()); + &v->cargo, next_station, v->GetCargoTile()); } return true; @@ -1563,7 +1564,7 @@ struct ReserveCargoAction { * @param consist_capleft If given, save free capacities after reserving there. * @param next_station Station(s) the vehicle will stop at next. */ -static void ReserveConsist(Station *st, Vehicle *u, CargoArray *consist_capleft, StationIDStack *next_station) +static void ReserveConsist(Station *st, Vehicle *u, CargoArray *consist_capleft, std::span next_station) { /* If there is a cargo payment not all vehicles of the consist have tried to do the refit. * In that case, only reserve if it's a fixed refit and the equivalent of "articulated chain" @@ -1618,14 +1619,15 @@ static void LoadUnloadVehicle(Vehicle *front) StationID last_visited = front->last_station_visited; Station *st = Station::Get(last_visited); - StationIDStack next_station = front->GetNextStoppingStation(); + std::vector next_station; + front->GetNextStoppingStation(next_station); bool use_autorefit = front->current_order.IsRefit() && front->current_order.GetRefitCargo() == CARGO_AUTO_REFIT; CargoArray consist_capleft{}; if (_settings_game.order.improved_load && use_autorefit ? front->cargo_payment == nullptr : (front->current_order.GetLoadType() & OLFB_FULL_LOAD) != 0) { ReserveConsist(st, front, (use_autorefit && front->load_unload_ticks != 0) ? &consist_capleft : nullptr, - &next_station); + next_station); } /* We have not waited enough time till the next round of loading/unloading */ diff --git a/src/economy_cmd.h b/src/economy_cmd.h index 15825aa7b8ff5..37aa5eb38e8e4 100644 --- a/src/economy_cmd.h +++ b/src/economy_cmd.h @@ -15,6 +15,6 @@ CommandCost CmdBuyCompany(DoCommandFlags flags, CompanyID target_company, bool hostile_takeover); -DEF_CMD_TRAIT(CMD_BUY_COMPANY, CmdBuyCompany, {}, CMDT_MONEY_MANAGEMENT) +DEF_CMD_TRAIT(CMD_BUY_COMPANY, CmdBuyCompany, {}, CommandType::MoneyManagement) #endif /* ECONOMY_CMD_H */ diff --git a/src/elrail.cpp b/src/elrail.cpp index 720da0f26ba0b..14b145713c8b0 100644 --- a/src/elrail.cpp +++ b/src/elrail.cpp @@ -582,7 +582,7 @@ void UpdateDisableElrailSettingState(bool disable, bool update_vehicles) { /* walk through all train engines */ for (Engine *e : Engine::IterateType(VEH_TRAIN)) { - RailVehicleInfo *rv_info = &e->u.rail; + RailVehicleInfo *rv_info = &e->VehInfo(); /* update railtype of engines intended to use elrail */ if (rv_info->intended_railtypes.Test(RAILTYPE_ELECTRIC)) { rv_info->railtypes.Set(RAILTYPE_ELECTRIC, !disable); diff --git a/src/engine.cpp b/src/engine.cpp index 68b9e1b0d1a9d..2b80951da8274 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -78,24 +78,19 @@ Engine::Engine(VehicleType type, uint16_t local_id) /* Check if this base engine is within the original engine data range */ if (local_id >= _engine_counts[type]) { - /* 'power' defaults to zero, so we also have to default to 'wagon' */ - if (type == VEH_TRAIN) this->u.rail.railveh_type = RAILVEH_WAGON; + /* Initialise default type-specific information. */ + switch (type) { + case VEH_TRAIN: this->vehicle_info.emplace(); break; + case VEH_ROAD: this->vehicle_info.emplace(); break; + case VEH_SHIP: this->vehicle_info.emplace(); break; + case VEH_AIRCRAFT: this->vehicle_info.emplace(); break; + default: break; + } /* Set model life to maximum to make wagons available */ this->info.base_life = TimerGameCalendar::Year{0xFF}; - /* Set road vehicle tractive effort to the default value */ - if (type == VEH_ROAD) this->u.road.tractive_effort = 0x4C; /* Aircraft must have CT_INVALID as default, as there is no property */ this->info.cargo_type = INVALID_CARGO; this->info.cargo_label = (type == VEH_AIRCRAFT) ? CT_INVALID : CT_PASSENGERS; - /* Ships must have a non-zero acceleration. */ - if (type == VEH_SHIP) this->u.ship.acceleration = 1; - /* Set visual effect to the default value */ - switch (type) { - case VEH_TRAIN: this->u.rail.visual_effect = VE_DEFAULT; break; - case VEH_ROAD: this->u.road.visual_effect = VE_DEFAULT; break; - case VEH_SHIP: this->u.ship.visual_effect = VE_DEFAULT; break; - default: break; // The aircraft, disasters and especially visual effects have no NewGRF configured visual effects - } /* Set cargo aging period to the default value. */ this->info.cargo_age_period = Ticks::CARGO_AGING_TICKS; /* Not a variant */ @@ -110,33 +105,37 @@ Engine::Engine(VehicleType type, uint16_t local_id) switch (type) { default: NOT_REACHED(); - case VEH_TRAIN: - this->u.rail = _orig_rail_vehicle_info[local_id]; - this->original_image_index = this->u.rail.image_index; + case VEH_TRAIN: { + RailVehicleInfo &rvi = this->vehicle_info.emplace(_orig_rail_vehicle_info[local_id]); + this->original_image_index = rvi.image_index; this->info.string_id = STR_VEHICLE_NAME_TRAIN_ENGINE_RAIL_KIRBY_PAUL_TANK_STEAM + local_id; /* Set the default model life of original wagons to "infinite" */ - if (this->u.rail.railveh_type == RAILVEH_WAGON) this->info.base_life = TimerGameCalendar::Year{0xFF}; + if (rvi.railveh_type == RAILVEH_WAGON) this->info.base_life = TimerGameCalendar::Year{0xFF}; break; + } - case VEH_ROAD: - this->u.road = _orig_road_vehicle_info[local_id]; - this->original_image_index = this->u.road.image_index; + case VEH_ROAD: { + RoadVehicleInfo &rvi = this->vehicle_info.emplace(_orig_road_vehicle_info[local_id]); + this->original_image_index = rvi.image_index; this->info.string_id = STR_VEHICLE_NAME_ROAD_VEHICLE_MPS_REGAL_BUS + local_id; break; + } - case VEH_SHIP: - this->u.ship = _orig_ship_vehicle_info[local_id]; - this->original_image_index = this->u.ship.image_index; + case VEH_SHIP: { + ShipVehicleInfo &svi = this->vehicle_info.emplace(_orig_ship_vehicle_info[local_id]); + this->original_image_index = svi.image_index; this->info.string_id = STR_VEHICLE_NAME_SHIP_MPS_OIL_TANKER + local_id; break; + } - case VEH_AIRCRAFT: - this->u.air = _orig_aircraft_vehicle_info[local_id]; - this->original_image_index = this->u.air.image_index; + case VEH_AIRCRAFT: { + AircraftVehicleInfo &avi = this->vehicle_info.emplace(_orig_aircraft_vehicle_info[local_id]); + this->original_image_index = avi.image_index; this->info.string_id = STR_VEHICLE_NAME_AIRCRAFT_SAMPSON_U52 + local_id; break; + } } } @@ -174,11 +173,11 @@ bool Engine::CanCarryCargo() const */ switch (this->type) { case VEH_TRAIN: - if (this->u.rail.capacity == 0) return false; + if (this->VehInfo().capacity == 0) return false; break; case VEH_ROAD: - if (this->u.road.capacity == 0) return false; + if (this->VehInfo().capacity == 0) return false; break; case VEH_SHIP: @@ -210,7 +209,7 @@ uint Engine::DetermineCapacity(const Vehicle *v, uint16_t *mail_capacity) const CargoType cargo_type = (v != nullptr) ? v->cargo_type : default_cargo; if (mail_capacity != nullptr && this->type == VEH_AIRCRAFT && IsCargoInClass(cargo_type, CargoClass::Passengers)) { - *mail_capacity = GetEngineProperty(this->index, PROP_AIRCRAFT_MAIL_CAPACITY, this->u.air.mail_capacity, v); + *mail_capacity = GetEngineProperty(this->index, PROP_AIRCRAFT_MAIL_CAPACITY, this->VehInfo().mail_capacity, v); } /* Check the refit capacity callback if we are not in the default configuration, or if we are using the new multiplier algorithm. */ @@ -225,24 +224,24 @@ uint Engine::DetermineCapacity(const Vehicle *v, uint16_t *mail_capacity) const uint extra_mail_cap = 0; switch (this->type) { case VEH_TRAIN: - capacity = GetEngineProperty(this->index, PROP_TRAIN_CARGO_CAPACITY, this->u.rail.capacity, v); + capacity = GetEngineProperty(this->index, PROP_TRAIN_CARGO_CAPACITY, this->VehInfo().capacity, v); /* In purchase list add the capacity of the second head. Always use the plain property for this. */ - if (v == nullptr && this->u.rail.railveh_type == RAILVEH_MULTIHEAD) capacity += this->u.rail.capacity; + if (v == nullptr && this->VehInfo().railveh_type == RAILVEH_MULTIHEAD) capacity += this->VehInfo().capacity; break; case VEH_ROAD: - capacity = GetEngineProperty(this->index, PROP_ROADVEH_CARGO_CAPACITY, this->u.road.capacity, v); + capacity = GetEngineProperty(this->index, PROP_ROADVEH_CARGO_CAPACITY, this->VehInfo().capacity, v); break; case VEH_SHIP: - capacity = GetEngineProperty(this->index, PROP_SHIP_CARGO_CAPACITY, this->u.ship.capacity, v); + capacity = GetEngineProperty(this->index, PROP_SHIP_CARGO_CAPACITY, this->VehInfo().capacity, v); break; case VEH_AIRCRAFT: - capacity = GetEngineProperty(this->index, PROP_AIRCRAFT_PASSENGER_CAPACITY, this->u.air.passenger_capacity, v); + capacity = GetEngineProperty(this->index, PROP_AIRCRAFT_PASSENGER_CAPACITY, this->VehInfo().passenger_capacity, v); if (!IsCargoInClass(cargo_type, CargoClass::Passengers)) { - extra_mail_cap = GetEngineProperty(this->index, PROP_AIRCRAFT_MAIL_CAPACITY, this->u.air.mail_capacity, v); + extra_mail_cap = GetEngineProperty(this->index, PROP_AIRCRAFT_MAIL_CAPACITY, this->VehInfo().mail_capacity, v); } if (IsValidCargoType(GetCargoTypeByLabel(CT_MAIL))) { if (!new_multipliers && cargo_type == GetCargoTypeByLabel(CT_MAIL)) return capacity + extra_mail_cap; @@ -284,25 +283,25 @@ Money Engine::GetRunningCost() const uint cost_factor; switch (this->type) { case VEH_ROAD: - base_price = this->u.road.running_cost_class; + base_price = this->VehInfo().running_cost_class; if (base_price == INVALID_PRICE) return 0; - cost_factor = GetEngineProperty(this->index, PROP_ROADVEH_RUNNING_COST_FACTOR, this->u.road.running_cost); + cost_factor = GetEngineProperty(this->index, PROP_ROADVEH_RUNNING_COST_FACTOR, this->VehInfo().running_cost); break; case VEH_TRAIN: - base_price = this->u.rail.running_cost_class; + base_price = this->VehInfo().running_cost_class; if (base_price == INVALID_PRICE) return 0; - cost_factor = GetEngineProperty(this->index, PROP_TRAIN_RUNNING_COST_FACTOR, this->u.rail.running_cost); + cost_factor = GetEngineProperty(this->index, PROP_TRAIN_RUNNING_COST_FACTOR, this->VehInfo().running_cost); break; case VEH_SHIP: base_price = PR_RUNNING_SHIP; - cost_factor = GetEngineProperty(this->index, PROP_SHIP_RUNNING_COST_FACTOR, this->u.ship.running_cost); + cost_factor = GetEngineProperty(this->index, PROP_SHIP_RUNNING_COST_FACTOR, this->VehInfo().running_cost); break; case VEH_AIRCRAFT: base_price = PR_RUNNING_AIRCRAFT; - cost_factor = GetEngineProperty(this->index, PROP_AIRCRAFT_RUNNING_COST_FACTOR, this->u.air.running_cost); + cost_factor = GetEngineProperty(this->index, PROP_AIRCRAFT_RUNNING_COST_FACTOR, this->VehInfo().running_cost); break; default: NOT_REACHED(); @@ -322,27 +321,27 @@ Money Engine::GetCost() const switch (this->type) { case VEH_ROAD: base_price = PR_BUILD_VEHICLE_ROAD; - cost_factor = GetEngineProperty(this->index, PROP_ROADVEH_COST_FACTOR, this->u.road.cost_factor); + cost_factor = GetEngineProperty(this->index, PROP_ROADVEH_COST_FACTOR, this->VehInfo().cost_factor); break; case VEH_TRAIN: - if (this->u.rail.railveh_type == RAILVEH_WAGON) { + if (this->VehInfo().railveh_type == RAILVEH_WAGON) { base_price = PR_BUILD_VEHICLE_WAGON; - cost_factor = GetEngineProperty(this->index, PROP_TRAIN_COST_FACTOR, this->u.rail.cost_factor); + cost_factor = GetEngineProperty(this->index, PROP_TRAIN_COST_FACTOR, this->VehInfo().cost_factor); } else { base_price = PR_BUILD_VEHICLE_TRAIN; - cost_factor = GetEngineProperty(this->index, PROP_TRAIN_COST_FACTOR, this->u.rail.cost_factor); + cost_factor = GetEngineProperty(this->index, PROP_TRAIN_COST_FACTOR, this->VehInfo().cost_factor); } break; case VEH_SHIP: base_price = PR_BUILD_VEHICLE_SHIP; - cost_factor = GetEngineProperty(this->index, PROP_SHIP_COST_FACTOR, this->u.ship.cost_factor); + cost_factor = GetEngineProperty(this->index, PROP_SHIP_COST_FACTOR, this->VehInfo().cost_factor); break; case VEH_AIRCRAFT: base_price = PR_BUILD_VEHICLE_AIRCRAFT; - cost_factor = GetEngineProperty(this->index, PROP_AIRCRAFT_COST_FACTOR, this->u.air.cost_factor); + cost_factor = GetEngineProperty(this->index, PROP_AIRCRAFT_COST_FACTOR, this->VehInfo().cost_factor); break; default: NOT_REACHED(); @@ -359,22 +358,22 @@ uint Engine::GetDisplayMaxSpeed() const { switch (this->type) { case VEH_TRAIN: - return GetEngineProperty(this->index, PROP_TRAIN_SPEED, this->u.rail.max_speed); + return GetEngineProperty(this->index, PROP_TRAIN_SPEED, this->VehInfo().max_speed); case VEH_ROAD: { uint max_speed = GetEngineProperty(this->index, PROP_ROADVEH_SPEED, 0); - return (max_speed != 0) ? max_speed * 2 : this->u.road.max_speed / 2; + return (max_speed != 0) ? max_speed * 2 : this->VehInfo().max_speed / 2; } case VEH_SHIP: - return GetEngineProperty(this->index, PROP_SHIP_SPEED, this->u.ship.max_speed) / 2; + return GetEngineProperty(this->index, PROP_SHIP_SPEED, this->VehInfo().max_speed) / 2; case VEH_AIRCRAFT: { uint max_speed = GetEngineProperty(this->index, PROP_AIRCRAFT_SPEED, 0); if (max_speed != 0) { return (max_speed * 128) / 10; } - return this->u.air.max_speed; + return this->VehInfo().max_speed; } default: NOT_REACHED(); @@ -392,9 +391,9 @@ uint Engine::GetPower() const /* Only trains and road vehicles have 'power'. */ switch (this->type) { case VEH_TRAIN: - return GetEngineProperty(this->index, PROP_TRAIN_POWER, this->u.rail.power); + return GetEngineProperty(this->index, PROP_TRAIN_POWER, this->VehInfo().power); case VEH_ROAD: - return GetEngineProperty(this->index, PROP_ROADVEH_POWER, this->u.road.power) * 10; + return GetEngineProperty(this->index, PROP_ROADVEH_POWER, this->VehInfo().power) * 10; default: NOT_REACHED(); } @@ -410,9 +409,9 @@ uint Engine::GetDisplayWeight() const /* Only trains and road vehicles have 'weight'. */ switch (this->type) { case VEH_TRAIN: - return GetEngineProperty(this->index, PROP_TRAIN_WEIGHT, this->u.rail.weight) << (this->u.rail.railveh_type == RAILVEH_MULTIHEAD ? 1 : 0); + return GetEngineProperty(this->index, PROP_TRAIN_WEIGHT, this->VehInfo().weight) << (this->VehInfo().railveh_type == RAILVEH_MULTIHEAD ? 1 : 0); case VEH_ROAD: - return GetEngineProperty(this->index, PROP_ROADVEH_WEIGHT, this->u.road.weight) / 4; + return GetEngineProperty(this->index, PROP_ROADVEH_WEIGHT, this->VehInfo().weight) / 4; default: NOT_REACHED(); } @@ -428,9 +427,9 @@ uint Engine::GetDisplayMaxTractiveEffort() const /* Only trains and road vehicles have 'tractive effort'. */ switch (this->type) { case VEH_TRAIN: - return (GROUND_ACCELERATION * this->GetDisplayWeight() * GetEngineProperty(this->index, PROP_TRAIN_TRACTIVE_EFFORT, this->u.rail.tractive_effort)) / 256; + return (GROUND_ACCELERATION * this->GetDisplayWeight() * GetEngineProperty(this->index, PROP_TRAIN_TRACTIVE_EFFORT, this->VehInfo().tractive_effort)) / 256; case VEH_ROAD: - return (GROUND_ACCELERATION * this->GetDisplayWeight() * GetEngineProperty(this->index, PROP_ROADVEH_TRACTIVE_EFFORT, this->u.road.tractive_effort)) / 256; + return (GROUND_ACCELERATION * this->GetDisplayWeight() * GetEngineProperty(this->index, PROP_ROADVEH_TRACTIVE_EFFORT, this->VehInfo().tractive_effort)) / 256; default: NOT_REACHED(); } @@ -454,7 +453,7 @@ uint16_t Engine::GetRange() const { switch (this->type) { case VEH_AIRCRAFT: - return GetEngineProperty(this->index, PROP_AIRCRAFT_RANGE, this->u.air.max_range); + return GetEngineProperty(this->index, PROP_AIRCRAFT_RANGE, this->VehInfo().max_range); default: NOT_REACHED(); } @@ -468,7 +467,7 @@ StringID Engine::GetAircraftTypeText() const { switch (this->type) { case VEH_AIRCRAFT: - switch (this->u.air.subtype) { + switch (this->VehInfo().subtype) { case AIR_HELI: return STR_LIVERY_HELICOPTER; case AIR_CTOL: return STR_LIVERY_SMALL_PLANE; case AIR_CTOL | AIR_FAST: return STR_LIVERY_LARGE_PLANE; @@ -625,7 +624,7 @@ void ShowEnginePreviewWindow(EngineID engine); static bool IsWagon(EngineID index) { const Engine *e = Engine::Get(index); - return e->type == VEH_TRAIN && e->u.rail.railveh_type == RAILVEH_WAGON; + return e->type == VEH_TRAIN && e->VehInfo().railveh_type == RAILVEH_WAGON; } /** @@ -700,7 +699,7 @@ void SetYearEngineAgingStops() /* Exclude certain engines */ if (!ei->climates.Test(_settings_game.game_creation.landscape)) continue; - if (e->type == VEH_TRAIN && e->u.rail.railveh_type == RAILVEH_WAGON) continue; + if (e->type == VEH_TRAIN && e->VehInfo().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); @@ -1107,13 +1106,19 @@ static void NewVehicleAvailable(Engine *e) if (e->type == VEH_TRAIN) { /* maybe make another rail type available */ - assert(e->u.rail.railtypes != RailTypes{}); - RailTypes introduced = GetAllIntroducesRailTypes(e->u.rail.railtypes); - for (Company *c : Company::Iterate()) c->avail_railtypes = AddDateIntroducedRailTypes(c->avail_railtypes | introduced, TimerGameCalendar::date); + assert(e->VehInfo().railtypes != RailTypes{}); + RailTypes introduced = GetAllIntroducesRailTypes(e->VehInfo().railtypes); + for (Company *c : Company::Iterate()) { + c->avail_railtypes.Set(introduced); + c->avail_railtypes = AddDateIntroducedRailTypes(c->avail_railtypes, TimerGameCalendar::date); + } } else if (e->type == VEH_ROAD) { /* maybe make another road type available */ - assert(e->u.road.roadtype < ROADTYPE_END); - for (Company *c : Company::Iterate()) c->avail_roadtypes = AddDateIntroducedRoadTypes(c->avail_roadtypes | GetRoadTypeInfo(e->u.road.roadtype)->introduces_roadtypes, TimerGameCalendar::date); + assert(e->VehInfo().roadtype < GetNumRoadTypes()); + for (Company *c : Company::Iterate()) { + c->avail_roadtypes.Set(GetRoadTypeInfo(e->VehInfo().roadtype)->introduces_roadtypes); + c->avail_roadtypes = AddDateIntroducedRoadTypes(c->avail_roadtypes, TimerGameCalendar::date); + } } /* Only broadcast event if AIs are able to build this vehicle type. */ @@ -1268,12 +1273,12 @@ bool IsEngineBuildable(EngineID engine, VehicleType type, CompanyID company) if (type == VEH_TRAIN && company != OWNER_DEITY) { /* Check if the rail type is available to this company */ const Company *c = Company::Get(company); - if (!GetAllCompatibleRailTypes(e->u.rail.railtypes).Any(c->avail_railtypes)) return false; + if (!GetAllCompatibleRailTypes(e->VehInfo().railtypes).Any(c->avail_railtypes)) return false; } if (type == VEH_ROAD && company != OWNER_DEITY) { /* Check if the road type is available to this company */ const Company *c = Company::Get(company); - if (!GetRoadTypeInfo(e->u.road.roadtype)->powered_roadtypes.Any(c->avail_roadtypes)) return false; + if (!GetRoadTypeInfo(e->VehInfo().roadtype)->powered_roadtypes.Any(c->avail_roadtypes)) return false; } return true; @@ -1319,7 +1324,7 @@ void CheckEngines() if (!e->IsEnabled()) continue; /* Don't consider train wagons, we need a powered engine available. */ - if (e->type == VEH_TRAIN && e->u.rail.railveh_type == RAILVEH_WAGON) continue; + if (e->type == VEH_TRAIN && e->VehInfo().railveh_type == RAILVEH_WAGON) continue; /* We have an available engine... yay! */ if (e->flags.Test(EngineFlag::Available) && e->company_avail.Any()) return; diff --git a/src/engine_base.h b/src/engine_base.h index 82ea41cd8ffec..d8e6052524b11 100644 --- a/src/engine_base.h +++ b/src/engine_base.h @@ -35,7 +35,8 @@ using EngineDisplayFlags = EnumBitSet; typedef Pool EnginePool; extern EnginePool _engine_pool; -struct Engine : EnginePool::PoolItem<&_engine_pool> { +class Engine : public EnginePool::PoolItem<&_engine_pool> { +public: CompanyMask company_avail{}; ///< Bit for each company whether the engine is available for that company. CompanyMask company_hidden{}; ///< Bit for each company whether the engine is normally hidden in the build gui for that company. CompanyMask preview_asked{}; ///< Bit for each company which has already been offered a preview. @@ -64,13 +65,6 @@ struct Engine : EnginePool::PoolItem<&_engine_pool> { EngineID display_last_variant = EngineID::Invalid(); ///< NOSAVE client-side-only last variant selected. EngineInfo info{}; - union { - RailVehicleInfo rail; - RoadVehicleInfo road; - ShipVehicleInfo ship; - AircraftVehicleInfo air; - } u{}; - uint16_t list_position = 0; /* NewGRF related data */ @@ -78,6 +72,11 @@ struct Engine : EnginePool::PoolItem<&_engine_pool> { std::vector overrides{}; std::vector badges{}; +private: + /* Vehicle-type specific information. */ + std::variant vehicle_info{}; + +public: Engine() {} Engine(VehicleType type, uint16_t local_id); bool IsEnabled() const; @@ -177,6 +176,18 @@ struct Engine : EnginePool::PoolItem<&_engine_pool> { bool operator() (size_t index) { return Engine::Get(index)->type == this->vt; } }; + template + inline T &VehInfo() + { + return std::get(this->vehicle_info); + } + + template + inline const T &VehInfo() const + { + return std::get(this->vehicle_info); + } + /** * Returns an iterable ensemble of all valid engines of the given type * @param vt the VehicleType for engines to be valid @@ -234,22 +245,22 @@ inline const EngineInfo *EngInfo(EngineID e) inline const RailVehicleInfo *RailVehInfo(EngineID e) { - return &Engine::Get(e)->u.rail; + return &Engine::Get(e)->VehInfo(); } inline const RoadVehicleInfo *RoadVehInfo(EngineID e) { - return &Engine::Get(e)->u.road; + return &Engine::Get(e)->VehInfo(); } inline const ShipVehicleInfo *ShipVehInfo(EngineID e) { - return &Engine::Get(e)->u.ship; + return &Engine::Get(e)->VehInfo(); } inline const AircraftVehicleInfo *AircraftVehInfo(EngineID e) { - return &Engine::Get(e)->u.air; + return &Engine::Get(e)->VehInfo(); } #endif /* ENGINE_BASE_H */ diff --git a/src/engine_cmd.h b/src/engine_cmd.h index 0f9911914577d..153a5055e1a0c 100644 --- a/src/engine_cmd.h +++ b/src/engine_cmd.h @@ -17,9 +17,9 @@ CommandCost CmdEngineCtrl(DoCommandFlags flags, EngineID engine_id, CompanyID co CommandCost CmdRenameEngine(DoCommandFlags flags, EngineID engine_id, const std::string &text); CommandCost CmdSetVehicleVisibility(DoCommandFlags flags, EngineID engine_id, bool hide); -DEF_CMD_TRAIT(CMD_WANT_ENGINE_PREVIEW, CmdWantEnginePreview, {}, CMDT_VEHICLE_MANAGEMENT) -DEF_CMD_TRAIT(CMD_ENGINE_CTRL, CmdEngineCtrl, CommandFlag::Deity, CMDT_VEHICLE_MANAGEMENT) -DEF_CMD_TRAIT(CMD_RENAME_ENGINE, CmdRenameEngine, CommandFlag::Server, CMDT_OTHER_MANAGEMENT) -DEF_CMD_TRAIT(CMD_SET_VEHICLE_VISIBILITY, CmdSetVehicleVisibility, {}, CMDT_COMPANY_SETTING) +DEF_CMD_TRAIT(CMD_WANT_ENGINE_PREVIEW, CmdWantEnginePreview, {}, CommandType::VehicleManagement) +DEF_CMD_TRAIT(CMD_ENGINE_CTRL, CmdEngineCtrl, CommandFlag::Deity, CommandType::VehicleManagement) +DEF_CMD_TRAIT(CMD_RENAME_ENGINE, CmdRenameEngine, CommandFlag::Server, CommandType::OtherManagement) +DEF_CMD_TRAIT(CMD_SET_VEHICLE_VISIBILITY, CmdSetVehicleVisibility, {}, CommandType::CompanySetting) #endif /* ENGINE_CMD_H */ diff --git a/src/engine_gui.cpp b/src/engine_gui.cpp index 210cf3bdf190a..d942a7a80ed5b 100644 --- a/src/engine_gui.cpp +++ b/src/engine_gui.cpp @@ -43,16 +43,16 @@ StringID GetEngineCategoryName(EngineID engine) switch (e->type) { default: NOT_REACHED(); case VEH_ROAD: - return GetRoadTypeInfo(e->u.road.roadtype)->strings.new_engine; + return GetRoadTypeInfo(e->VehInfo().roadtype)->strings.new_engine; case VEH_AIRCRAFT: return STR_ENGINE_PREVIEW_AIRCRAFT; case VEH_SHIP: return STR_ENGINE_PREVIEW_SHIP; case VEH_TRAIN: - assert(e->u.rail.railtypes.Any()); - return GetRailTypeInfo(e->u.rail.railtypes.GetNthSetBit(0).value())->strings.new_loco; + assert(e->VehInfo().railtypes.Any()); + return GetRailTypeInfo(*e->VehInfo().railtypes.begin())->strings.new_loco; } } -static constexpr NWidgetPart _nested_engine_preview_widgets[] = { +static constexpr std::initializer_list _nested_engine_preview_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_LIGHT_BLUE), NWidget(WWT_CAPTION, COLOUR_LIGHT_BLUE), SetStringTip(STR_ENGINE_PREVIEW_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), @@ -182,12 +182,12 @@ static std::string GetTrainEngineInfoString(const Engine &e) res << GetString(STR_ENGINE_PREVIEW_COST_WEIGHT, e.GetCost(), e.GetDisplayWeight()); res << '\n'; - if (e.u.rail.railtypes.Count() > 1) { + if (e.VehInfo().railtypes.size() > 1) { std::string railtypes{}; std::string_view list_separator = GetListSeparator(); for (const auto &rt : _sorted_railtypes) { - if (!e.u.rail.railtypes.Test(rt)) continue; + if (!e.VehInfo().railtypes.Test(rt)) continue; if (!railtypes.empty()) railtypes += list_separator; AppendStringInPlace(railtypes, GetRailTypeInfo(rt)->strings.name); @@ -197,7 +197,7 @@ static std::string GetTrainEngineInfoString(const Engine &e) } bool is_maglev = true; - for (RailType rt : e.u.rail.railtypes) { + for (RailType rt : e.VehInfo().railtypes) { is_maglev &= GetRailTypeInfo(rt)->acceleration_type == VehicleAccelerationModel::Maglev; } diff --git a/src/engine_type.h b/src/engine_type.h index 1fefbe1ba1fa0..640a99b73f1b6 100644 --- a/src/engine_type.h +++ b/src/engine_type.h @@ -25,7 +25,7 @@ /** Unique identification number of an engine. */ using EngineID = PoolID; -struct Engine; +class Engine; /** Available types of rail vehicles. */ enum RailVehicleTypes : uint8_t { @@ -50,10 +50,30 @@ enum class VehicleAccelerationModel : uint8_t { Maglev, ///< Maglev acceleration model. }; +/** Meaning of the various bits of the visual effect. */ +enum VisualEffect : uint8_t { + VE_OFFSET_START = 0, ///< First bit that contains the offset (0 = front, 8 = centre, 15 = rear) + VE_OFFSET_COUNT = 4, ///< Number of bits used for the offset + VE_OFFSET_CENTRE = 8, ///< Value of offset corresponding to a position above the centre of the vehicle + + VE_TYPE_START = 4, ///< First bit used for the type of effect + VE_TYPE_COUNT = 2, ///< Number of bits used for the effect type + VE_TYPE_DEFAULT = 0, ///< Use default from engine class + VE_TYPE_STEAM = 1, ///< Steam plumes + VE_TYPE_DIESEL = 2, ///< Diesel fumes + VE_TYPE_ELECTRIC = 3, ///< Electric sparks + + VE_DISABLE_EFFECT = 6, ///< Flag to disable visual effect + VE_ADVANCED_EFFECT = VE_DISABLE_EFFECT, ///< Flag for advanced effects + VE_DISABLE_WAGON_POWER = 7, ///< Flag to disable wagon power + + VE_DEFAULT = 0xFF, ///< Default value to indicate that visual effect should be based on engine class +}; + /** Information about a rail vehicle. */ struct RailVehicleInfo { uint8_t image_index = 0; - RailVehicleTypes railveh_type{}; + RailVehicleTypes railveh_type = RAILVEH_WAGON; uint8_t cost_factor = 0; ///< Purchase cost factor; For multiheaded engines the sum of both engine prices. RailTypes railtypes{}; ///< Railtypes, mangled if elrail is disabled. RailTypes intended_railtypes{}; ///< Intended railtypes, regardless of elrail being enabled or disabled. @@ -67,7 +87,7 @@ struct RailVehicleInfo { uint8_t capacity = 0; ///< Cargo capacity of vehicle; For multiheaded engines the capacity of each single engine. uint16_t pow_wag_power = 0; ///< Extra power applied to consist if wagon should be powered uint8_t pow_wag_weight = 0; ///< Extra weight applied to consist if wagon should be powered - uint8_t visual_effect = 0; ///< Bitstuffed NewGRF visual effect data + uint8_t visual_effect = VE_DEFAULT; ///< Bitstuffed NewGRF visual effect data uint8_t shorten_factor = 0; ///< length on main map for this type is 8 - shorten_factor uint8_t tractive_effort = 0; ///< Tractive effort coefficient uint8_t air_drag = 0; ///< Coefficient of air drag @@ -80,12 +100,12 @@ struct ShipVehicleInfo { uint8_t image_index = 0; uint8_t cost_factor = 0; uint8_t running_cost = 0; - uint8_t acceleration = 0; ///< Acceleration (1 unit = 1/3.2 mph per tick = 0.5 km-ish/h per tick) + uint8_t acceleration = 1; ///< Acceleration (1 unit = 1/3.2 mph per tick = 0.5 km-ish/h per tick) uint16_t max_speed = 0; ///< Maximum speed (1 unit = 1/3.2 mph = 0.5 km-ish/h) uint16_t capacity = 0; SoundID sfx{}; bool old_refittable = 0; ///< Is ship refittable; only used during initialisation. Later use EngineInfo::refit_mask. - uint8_t visual_effect = 0; ///< Bitstuffed NewGRF visual effect data + uint8_t visual_effect = VE_DEFAULT; ///< Bitstuffed NewGRF visual effect data uint8_t ocean_speed_frac = 0; ///< Fraction of maximum speed for ocean tiles. uint8_t canal_speed_frac = 0; ///< Fraction of maximum speed for canal/river tiles. @@ -133,9 +153,9 @@ struct RoadVehicleInfo { uint8_t capacity = 0; uint8_t weight = 0; ///< Weight in 1/4t units uint8_t power = 0; ///< Power in 10hp units - uint8_t tractive_effort = 0; ///< Coefficient of tractive effort + uint8_t tractive_effort = 0x4C; ///< Coefficient of tractive effort uint8_t air_drag = 0; ///< Coefficient of air drag - uint8_t visual_effect = 0; ///< Bitstuffed NewGRF visual effect data + uint8_t visual_effect = VE_DEFAULT; ///< Bitstuffed NewGRF visual effect data uint8_t shorten_factor = 0; ///< length on main map for this type is 8 - shorten_factor RoadType roadtype{}; ///< Road type }; diff --git a/src/error_gui.cpp b/src/error_gui.cpp index 182ac7229fa5a..7fe4cc6f12b23 100644 --- a/src/error_gui.cpp +++ b/src/error_gui.cpp @@ -33,7 +33,7 @@ #include "safeguards.h" -static constexpr NWidgetPart _nested_errmsg_widgets[] = { +static constexpr std::initializer_list _nested_errmsg_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_RED), NWidget(WWT_CAPTION, COLOUR_RED, WID_EM_CAPTION), SetStringTip(STR_ERROR_MESSAGE_CAPTION), @@ -50,7 +50,7 @@ static WindowDesc _errmsg_desc( _nested_errmsg_widgets ); -static constexpr NWidgetPart _nested_errmsg_face_widgets[] = { +static constexpr std::initializer_list _nested_errmsg_face_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_RED), NWidget(WWT_CAPTION, COLOUR_RED, WID_EM_CAPTION), @@ -209,7 +209,7 @@ struct ErrmsgWindow : public Window, ErrorMessageData { /* Note: NewGRF supplied error message often do not start with a colour code, so default to white. */ Rect top_section = r.WithHeight(this->height_summary + extra, false); Rect bottom_section = r.WithHeight(this->height_extra + extra, true); - Rect middle_section = { top_section.left, top_section.bottom, top_section.right, bottom_section.top }; + Rect middle_section = top_section.WithY(top_section.bottom, bottom_section.top); DrawStringMultiLineWithClipping(top_section, this->summary_msg.GetDecodedString(), TC_WHITE, SA_CENTER); DrawStringMultiLineWithClipping(middle_section, this->detailed_msg.GetDecodedString(), TC_WHITE, SA_CENTER); DrawStringMultiLineWithClipping(bottom_section, this->extra_msg.GetDecodedString(), TC_WHITE, SA_CENTER); diff --git a/src/fileio.cpp b/src/fileio.cpp index 981d37c8cde90..da9ae826abfd5 100644 --- a/src/fileio.cpp +++ b/src/fileio.cpp @@ -593,7 +593,7 @@ bool ExtractTar(const std::string &tar_filename, Subdirectory subdir) /* We don't know the file. */ if (it == _tar_list[subdir].end()) return false; - const auto &dirname = (*it).second; + const auto &dirname = it->second; /* The file doesn't have a sub directory! */ if (dirname.empty()) { diff --git a/src/fios.cpp b/src/fios.cpp index fc02d43da789c..67eec48b44594 100644 --- a/src/fios.cpp +++ b/src/fios.cpp @@ -507,7 +507,7 @@ std::tuple FiosGetHeightmapListCallback(SaveLoadOperation for (Searchpath sp : _valid_searchpaths) { std::string buf = FioGetDirectory(sp, HEIGHTMAP_DIR); - if (buf.compare(0, buf.size(), it->second.tar_filename, 0, buf.size()) == 0) { + if (it->second.tar_filename.starts_with(buf)) { match = true; break; } diff --git a/src/fios_gui.cpp b/src/fios_gui.cpp index 10e05908eb788..a4d593dbcfbce 100644 --- a/src/fios_gui.cpp +++ b/src/fios_gui.cpp @@ -65,7 +65,7 @@ void LoadCheckData::Clear() } /** Load game/scenario with optional content download */ -static constexpr NWidgetPart _nested_load_dialog_widgets[] = { +static constexpr std::initializer_list _nested_load_dialog_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), NWidget(WWT_CAPTION, COLOUR_GREY, WID_SL_CAPTION), @@ -128,7 +128,7 @@ static constexpr NWidgetPart _nested_load_dialog_widgets[] = { }; /** Load heightmap with content download */ -static constexpr NWidgetPart _nested_load_heightmap_dialog_widgets[] = { +static constexpr std::initializer_list _nested_load_heightmap_dialog_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), NWidget(WWT_CAPTION, COLOUR_GREY, WID_SL_CAPTION), @@ -175,7 +175,7 @@ static constexpr NWidgetPart _nested_load_heightmap_dialog_widgets[] = { }; /** Load town data */ -static constexpr NWidgetPart _nested_load_town_data_dialog_widgets[] = { +static constexpr std::initializer_list _nested_load_town_data_dialog_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), NWidget(WWT_CAPTION, COLOUR_GREY, WID_SL_CAPTION), @@ -217,7 +217,7 @@ static constexpr NWidgetPart _nested_load_town_data_dialog_widgets[] = { }; /** Save game/scenario */ -static constexpr NWidgetPart _nested_save_dialog_widgets[] = { +static constexpr std::initializer_list _nested_save_dialog_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), NWidget(WWT_CAPTION, COLOUR_GREY, WID_SL_CAPTION), @@ -527,9 +527,9 @@ struct SaveLoadWindow : public Window { const FiosItem *item = *it; if (item == this->selected) { - GfxFillRect(br.left, tr.top, br.right, tr.bottom, PC_DARK_BLUE); + GfxFillRect(br.WithY(tr), PC_DARK_BLUE); } else if (item == this->highlighted) { - GfxFillRect(br.left, tr.top, br.right, tr.bottom, PC_VERY_DARK_BLUE); + GfxFillRect(br.WithY(tr), PC_VERY_DARK_BLUE); } DrawString(tr, item->title.GetDecodedString(), _fios_colours[item->type.detailed]); tr = tr.Translate(0, this->resize.step_height); diff --git a/src/fontcache.h b/src/fontcache.h index 099f9b17e631a..b03f84514d25e 100644 --- a/src/fontcache.h +++ b/src/fontcache.h @@ -10,9 +10,9 @@ #ifndef FONTCACHE_H #define FONTCACHE_H +#include "gfx_type.h" #include "provider_manager.h" -#include "string_type.h" -#include "spritecache.h" +#include "spritecache_type.h" /** Glyphs are characters from a font. */ typedef uint32_t GlyphID; @@ -229,8 +229,8 @@ class FontCacheFactory : public BaseProvider { ProviderManager::Unregister(*this); } - virtual std::unique_ptr LoadFont(FontSize fs, FontType fonttype) = 0; - virtual bool FindFallbackFont(struct FontCacheSettings *settings, const std::string &language_isocode, class MissingGlyphSearcher *callback) = 0; + virtual std::unique_ptr LoadFont(FontSize fs, FontType fonttype) const = 0; + virtual bool FindFallbackFont(struct FontCacheSettings *settings, const std::string &language_isocode, class MissingGlyphSearcher *callback) const = 0; }; class FontProviderManager : ProviderManager { diff --git a/src/fontcache/freetypefontcache.cpp b/src/fontcache/freetypefontcache.cpp index 9d52ab8f77c32..254b7224158c6 100644 --- a/src/fontcache/freetypefontcache.cpp +++ b/src/fontcache/freetypefontcache.cpp @@ -7,6 +7,8 @@ /** @file freetypefontcache.cpp FreeType font cache implementation. */ +#ifdef WITH_FREETYPE + #include "../stdafx.h" #include "../debug.h" @@ -20,14 +22,13 @@ #include "../table/control_codes.h" -#include "../safeguards.h" - -#ifdef WITH_FREETYPE #include #include FT_FREETYPE_H #include FT_GLYPH_H #include FT_TRUETYPE_TABLES_H +#include "../safeguards.h" + /** Font cache for fonts that are based on a freetype font. */ class FreeTypeFontCache : public TrueTypeFontCache { private: @@ -225,7 +226,7 @@ class FreeTypeFontCacheFactory : public FontCacheFactory { * format is 'font family name' or 'font family name, font style'. * @param fs The font size to load. */ - std::unique_ptr LoadFont(FontSize fs, FontType fonttype) override + std::unique_ptr LoadFont(FontSize fs, FontType fonttype) const override { if (fonttype != FontType::TrueType) return nullptr; @@ -271,7 +272,7 @@ class FreeTypeFontCacheFactory : public FontCacheFactory { return LoadFont(fs, face, font, GetFontCacheFontSize(fs)); } - bool FindFallbackFont(struct FontCacheSettings *settings, const std::string &language_isocode, class MissingGlyphSearcher *callback) override + bool FindFallbackFont(struct FontCacheSettings *settings, const std::string &language_isocode, class MissingGlyphSearcher *callback) const override { #ifdef WITH_FONTCONFIG if (FontConfigFindFallbackFont(settings, language_isocode, callback)) return true; diff --git a/src/fontcache/spritefontcache.cpp b/src/fontcache/spritefontcache.cpp index 96f9fd8cc3d67..8d6723726696c 100644 --- a/src/fontcache/spritefontcache.cpp +++ b/src/fontcache/spritefontcache.cpp @@ -10,6 +10,7 @@ #include "../stdafx.h" #include "../fontcache.h" #include "../gfx_layout.h" +#include "../spritecache.h" #include "../string_func.h" #include "../zoom_func.h" #include "spritefontcache.h" @@ -93,6 +94,7 @@ void InitializeUnicodeGlyphMap(FontSize fs) SetUnicodeGlyph(fs, unicode_map.code, 0); } else { SpriteID sprite = base + key - ASCII_LETTERSTART; + if (!SpriteExists(sprite)) continue; SetUnicodeGlyph(fs, unicode_map.code, sprite); } } @@ -156,14 +158,14 @@ class SpriteFontCacheFactory : public FontCacheFactory { public: SpriteFontCacheFactory() : FontCacheFactory("sprite", "Sprite font provider") {} - std::unique_ptr LoadFont(FontSize fs, FontType fonttype) override + std::unique_ptr LoadFont(FontSize fs, FontType fonttype) const override { if (fonttype != FontType::Sprite) return nullptr; return std::make_unique(fs); } - bool FindFallbackFont(struct FontCacheSettings *, const std::string &, class MissingGlyphSearcher *) override + bool FindFallbackFont(struct FontCacheSettings *, const std::string &, class MissingGlyphSearcher *) const override { return false; } diff --git a/src/framerate_gui.cpp b/src/framerate_gui.cpp index 72c0aa2f970b7..df390d28223b6 100644 --- a/src/framerate_gui.cpp +++ b/src/framerate_gui.cpp @@ -377,7 +377,7 @@ static std::string_view GetAIName(int ai_index) } /** @hideinitializer */ -static constexpr NWidgetPart _framerate_window_widgets[] = { +static constexpr std::initializer_list _framerate_window_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), NWidget(WWT_CAPTION, COLOUR_GREY, WID_FRW_CAPTION), @@ -695,7 +695,7 @@ static WindowDesc _framerate_display_desc( /** @hideinitializer */ -static constexpr NWidgetPart _frametime_graph_window_widgets[] = { +static constexpr std::initializer_list _frametime_graph_window_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), NWidget(WWT_CAPTION, COLOUR_GREY, WID_FGW_CAPTION), SetTextStyle(TC_WHITE), diff --git a/src/game/game_gui.cpp b/src/game/game_gui.cpp index ec47cd6eb5b19..34e2e30342d41 100644 --- a/src/game/game_gui.cpp +++ b/src/game/game_gui.cpp @@ -33,7 +33,7 @@ /** Widgets for the configure GS window. */ -static constexpr NWidgetPart _nested_gs_config_widgets[] = { +static constexpr std::initializer_list _nested_gs_config_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_MAUVE), NWidget(WWT_CAPTION, COLOUR_MAUVE), SetStringTip(STR_AI_CONFIG_CAPTION_GAMESCRIPT, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), diff --git a/src/game/game_text.cpp b/src/game/game_text.cpp index 27e4314f5ac8c..021d5fec57a64 100644 --- a/src/game/game_text.cpp +++ b/src/game/game_text.cpp @@ -225,15 +225,15 @@ static std::shared_ptr LoadTranslations() if (!tar_filename.empty() && (iter = _tar_list[GAME_DIR].find(tar_filename)) != _tar_list[GAME_DIR].end()) { /* The main script is in a tar file, so find all files that * are in the same tar and add them to the langfile scanner. */ - for (const auto &tar : _tar_filelist[GAME_DIR]) { + for (const auto &[name, entry] : _tar_filelist[GAME_DIR]) { /* Not in the same tar. */ - if (tar.second.tar_filename != iter->first) continue; + if (entry.tar_filename != iter->first) continue; /* Check the path and extension. */ - if (tar.first.size() <= ldir.size() || tar.first.compare(0, ldir.size(), ldir) != 0) continue; - if (tar.first.compare(tar.first.size() - 4, 4, ".txt") != 0) continue; + if (!name.starts_with(ldir)) continue; + if (!name.ends_with(".txt")) continue; - scanner.AddFile(tar.first, 0, tar_filename); + scanner.AddFile(name, 0, tar_filename); } } else { /* Scan filesystem */ diff --git a/src/genworld.cpp b/src/genworld.cpp index effa9e16e72ec..1e52fd9a24efa 100644 --- a/src/genworld.cpp +++ b/src/genworld.cpp @@ -139,11 +139,13 @@ static void _GenerateWorld() if (_game_mode != GM_MENU) FlatEmptyWorld(_settings_game.game_creation.se_flat_world_height); ConvertGroundTilesIntoWaterTiles(); + Map::CountLandTiles(); IncreaseGeneratingWorldProgress(GWP_OBJECT); _settings_game.game_creation.snow_line_height = DEF_SNOWLINE_HEIGHT; } else { GenerateClearTile(); + Map::CountLandTiles(); /* Only generate towns, tree and industries in newgame mode. */ if (_game_mode != GM_EDITOR) { diff --git a/src/genworld.h b/src/genworld.h index 0bfd8455ec2ea..f571971260aaf 100644 --- a/src/genworld.h +++ b/src/genworld.h @@ -64,7 +64,8 @@ enum GenWorldProgress : uint8_t { GWP_RIVER, ///< Create the rivers GWP_ROUGH_ROCKY, ///< Make rough and rocky areas GWP_TOWN, ///< Generate towns - GWP_INDUSTRY, ///< Generate industries + GWP_LAND_INDUSTRY, ///< Generate industries + GWP_WATER_INDUSTRY, ///< Generate industries GWP_OBJECT, ///< Generate objects (radio tower, light houses) GWP_TREE, ///< Generate trees GWP_GAME_INIT, ///< Initialize the game diff --git a/src/genworld_gui.cpp b/src/genworld_gui.cpp index b91a51945e323..602ae8d406b9e 100644 --- a/src/genworld_gui.cpp +++ b/src/genworld_gui.cpp @@ -74,7 +74,7 @@ void SetNewLandscapeType(LandscapeType landscape) } /** Widgets of GenerateLandscapeWindow when generating world */ -static constexpr NWidgetPart _nested_generate_landscape_widgets[] = { +static constexpr std::initializer_list _nested_generate_landscape_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_BROWN), NWidget(WWT_CAPTION, COLOUR_BROWN), SetStringTip(STR_MAPGEN_WORLD_GENERATION_CAPTION), @@ -115,7 +115,7 @@ static constexpr NWidgetPart _nested_generate_landscape_widgets[] = { NWidget(WWT_DROPDOWN, COLOUR_ORANGE, WID_GL_VARIETY_PULLDOWN), SetToolTip(STR_CONFIG_SETTING_VARIETY_HELPTEXT), SetFill(1, 1), NWidget(WWT_DROPDOWN, COLOUR_ORANGE, WID_GL_SMOOTHNESS_PULLDOWN), SetToolTip(STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_HELPTEXT), SetFill(1, 1), NWidget(WWT_DROPDOWN, COLOUR_ORANGE, WID_GL_RIVER_PULLDOWN), SetToolTip(STR_CONFIG_SETTING_RIVER_AMOUNT_HELPTEXT), SetFill(1, 1), - NWidget(WWT_TEXTBTN, COLOUR_ORANGE, WID_GL_BORDERS_RANDOM), SetToolTip(STR_MAPGEN_BORDER_TYPE_TOOLTIP), SetFill(1, 1), + NWidget(WWT_DROPDOWN, COLOUR_ORANGE, WID_GL_BORDERS_PULLDOWN), SetToolTip(STR_MAPGEN_BORDER_TYPE_TOOLTIP), SetFill(1, 1), EndContainer(), EndContainer(), @@ -172,14 +172,14 @@ static constexpr NWidgetPart _nested_generate_landscape_widgets[] = { NWidget(NWID_VERTICAL), NWidget(NWID_HORIZONTAL, NWidContainerFlag::EqualSize), NWidget(WWT_TEXT, INVALID_COLOUR), SetStringTip(STR_MAPGEN_NORTHWEST), SetPadding(0, WidgetDimensions::unscaled.hsep_normal, 0, 0), SetFill(1, 1), SetAlignment(SA_RIGHT | SA_VERT_CENTER), - NWidget(WWT_TEXTBTN, COLOUR_ORANGE, WID_GL_WATER_NW), SetToolTip(STR_MAPGEN_NORTHWEST), SetFill(1, 1), - NWidget(WWT_TEXTBTN, COLOUR_ORANGE, WID_GL_WATER_NE), SetToolTip(STR_MAPGEN_NORTHEAST), SetFill(1, 1), + NWidget(WWT_TEXTBTN, COLOUR_ORANGE, WID_GL_WATER_NW), SetToolTip(STR_MAPGEN_NORTHWEST_TOOLTIP), SetFill(1, 1), + NWidget(WWT_TEXTBTN, COLOUR_ORANGE, WID_GL_WATER_NE), SetToolTip(STR_MAPGEN_NORTHEAST_TOOLTIP), SetFill(1, 1), NWidget(WWT_TEXT, INVALID_COLOUR), SetStringTip(STR_MAPGEN_NORTHEAST), SetPadding(0, 0, 0, WidgetDimensions::unscaled.hsep_normal), SetFill(1, 1), EndContainer(), NWidget(NWID_HORIZONTAL, NWidContainerFlag::EqualSize), NWidget(WWT_TEXT, INVALID_COLOUR), SetStringTip(STR_MAPGEN_SOUTHWEST), SetPadding(0, WidgetDimensions::unscaled.hsep_normal, 0, 0), SetFill(1, 1), SetAlignment(SA_RIGHT | SA_VERT_CENTER), - NWidget(WWT_TEXTBTN, COLOUR_ORANGE, WID_GL_WATER_SW), SetToolTip(STR_MAPGEN_SOUTHWEST), SetFill(1, 1), - NWidget(WWT_TEXTBTN, COLOUR_ORANGE, WID_GL_WATER_SE), SetToolTip(STR_MAPGEN_SOUTHEAST), SetFill(1, 1), + NWidget(WWT_TEXTBTN, COLOUR_ORANGE, WID_GL_WATER_SW), SetToolTip(STR_MAPGEN_SOUTHWEST_TOOLTIP), SetFill(1, 1), + NWidget(WWT_TEXTBTN, COLOUR_ORANGE, WID_GL_WATER_SE), SetToolTip(STR_MAPGEN_SOUTHEAST_TOOLTIP), SetFill(1, 1), NWidget(WWT_TEXT, INVALID_COLOUR), SetStringTip(STR_MAPGEN_SOUTHEAST), SetPadding(0, 0, 0, WidgetDimensions::unscaled.hsep_normal), SetFill(1, 1), EndContainer(), EndContainer(), @@ -198,7 +198,7 @@ static constexpr NWidgetPart _nested_generate_landscape_widgets[] = { }; /** Widgets of GenerateLandscapeWindow when loading heightmap */ -static constexpr NWidgetPart _nested_heightmap_load_widgets[] = { +static constexpr std::initializer_list _nested_heightmap_load_widgets = { /* Window header. */ NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_BROWN), @@ -379,6 +379,7 @@ static DropDownList BuildTownNameDropDown() static const StringID _elevations[] = {STR_TERRAIN_TYPE_VERY_FLAT, STR_TERRAIN_TYPE_FLAT, STR_TERRAIN_TYPE_HILLY, STR_TERRAIN_TYPE_MOUNTAINOUS, STR_TERRAIN_TYPE_ALPINIST, STR_TERRAIN_TYPE_CUSTOM}; static const StringID _sea_lakes[] = {STR_SEA_LEVEL_VERY_LOW, STR_SEA_LEVEL_LOW, STR_SEA_LEVEL_MEDIUM, STR_SEA_LEVEL_HIGH, STR_SEA_LEVEL_CUSTOM}; static const StringID _rivers[] = {STR_RIVERS_NONE, STR_RIVERS_FEW, STR_RIVERS_MODERATE, STR_RIVERS_LOT}; +static const StringID _borders[] = {STR_MAPGEN_BORDER_RANDOMIZE, STR_MAPGEN_BORDER_MANUAL, STR_MAPGEN_BORDER_INFINITE_WATER}; static const StringID _smoothness[] = {STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_VERY_SMOOTH, STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_SMOOTH, STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_ROUGH, STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN_VERY_ROUGH}; static const StringID _rotation[] = {STR_CONFIG_SETTING_HEIGHTMAP_ROTATION_COUNTER_CLOCKWISE, STR_CONFIG_SETTING_HEIGHTMAP_ROTATION_CLOCKWISE}; static const StringID _num_towns[] = {STR_NUM_VERY_LOW, STR_NUM_LOW, STR_NUM_NORMAL, STR_NUM_HIGH, STR_NUM_CUSTOM}; @@ -471,7 +472,7 @@ struct GenerateLandscapeWindow : public Window { case WID_GL_RIVER_PULLDOWN: return GetString(_rivers[_settings_newgame.game_creation.amount_of_rivers]); case WID_GL_SMOOTHNESS_PULLDOWN: return GetString(_smoothness[_settings_newgame.game_creation.tgen_smoothness]); case WID_GL_VARIETY_PULLDOWN: return GetString(_variety[_settings_newgame.game_creation.variety]); - case WID_GL_BORDERS_RANDOM: return GetString((_settings_newgame.game_creation.water_borders == BorderFlag::Random) ? STR_MAPGEN_BORDER_RANDOMIZE : STR_MAPGEN_BORDER_MANUAL); + case WID_GL_BORDERS_PULLDOWN: return GetString(_borders[_settings_newgame.game_creation.water_border_presets]); case WID_GL_WATER_NE: return GetString((_settings_newgame.game_creation.water_borders == BorderFlag::Random) ? STR_MAPGEN_BORDER_RANDOM : _settings_newgame.game_creation.water_borders.Test(BorderFlag::NorthEast) ? STR_MAPGEN_BORDER_WATER : STR_MAPGEN_BORDER_FREEFORM); case WID_GL_WATER_NW: return GetString((_settings_newgame.game_creation.water_borders == BorderFlag::Random) ? STR_MAPGEN_BORDER_RANDOM : _settings_newgame.game_creation.water_borders.Test(BorderFlag::NorthWest) ? STR_MAPGEN_BORDER_WATER : STR_MAPGEN_BORDER_FREEFORM); case WID_GL_WATER_SE: return GetString((_settings_newgame.game_creation.water_borders == BorderFlag::Random) ? STR_MAPGEN_BORDER_RANDOM : _settings_newgame.game_creation.water_borders.Test(BorderFlag::SouthEast) ? STR_MAPGEN_BORDER_WATER : STR_MAPGEN_BORDER_FREEFORM); @@ -507,12 +508,10 @@ struct GenerateLandscapeWindow : public Window { if (mode == GLWM_GENERATE) { this->SetWidgetDisabledState(WID_GL_SMOOTHNESS_PULLDOWN, _settings_newgame.game_creation.land_generator == LG_ORIGINAL); this->SetWidgetDisabledState(WID_GL_VARIETY_PULLDOWN, _settings_newgame.game_creation.land_generator == LG_ORIGINAL); - this->SetWidgetDisabledState(WID_GL_BORDERS_RANDOM, _settings_newgame.game_creation.land_generator == LG_ORIGINAL || !_settings_newgame.construction.freeform_edges); + this->SetWidgetDisabledState(WID_GL_BORDERS_PULLDOWN, _settings_newgame.game_creation.land_generator == LG_ORIGINAL); this->SetWidgetsDisabledState(_settings_newgame.game_creation.land_generator == LG_ORIGINAL || !_settings_newgame.construction.freeform_edges || _settings_newgame.game_creation.water_borders == BorderFlag::Random, WID_GL_WATER_NW, WID_GL_WATER_NE, WID_GL_WATER_SE, WID_GL_WATER_SW); - this->SetWidgetLoweredState(WID_GL_BORDERS_RANDOM, _settings_newgame.game_creation.water_borders == BorderFlag::Random); - this->SetWidgetLoweredState(WID_GL_WATER_NW, _settings_newgame.game_creation.water_borders.Test(BorderFlag::NorthWest)); this->SetWidgetLoweredState(WID_GL_WATER_NE, _settings_newgame.game_creation.water_borders.Test(BorderFlag::NorthEast)); this->SetWidgetLoweredState(WID_GL_WATER_SE, _settings_newgame.game_creation.water_borders.Test(BorderFlag::SouthEast)); @@ -622,10 +621,7 @@ struct GenerateLandscapeWindow : public Window { case WID_GL_SMOOTHNESS_PULLDOWN: strs = _smoothness; break; case WID_GL_VARIETY_PULLDOWN: strs = _variety; break; case WID_GL_HEIGHTMAP_ROTATION_PULLDOWN: strs = _rotation; break; - case WID_GL_BORDERS_RANDOM: - d = maxdim(GetStringBoundingBox(STR_MAPGEN_BORDER_RANDOMIZE), GetStringBoundingBox(STR_MAPGEN_BORDER_MANUAL)); - break; - + case WID_GL_BORDERS_PULLDOWN: strs = _borders; break; case WID_GL_WATER_NE: case WID_GL_WATER_NW: case WID_GL_WATER_SE: @@ -807,7 +803,11 @@ struct GenerateLandscapeWindow : public Window { ShowDropDownMenu(this, _variety, _settings_newgame.game_creation.variety, WID_GL_VARIETY_PULLDOWN, 0, 0); break; - /* Freetype map borders */ + /* Map borders */ + case WID_GL_BORDERS_PULLDOWN: + ShowDropDownMenu(this, _borders, _settings_newgame.game_creation.water_border_presets, WID_GL_BORDERS_PULLDOWN, 0, 0); + break; + case WID_GL_WATER_NW: _settings_newgame.game_creation.water_borders.Flip(BorderFlag::NorthWest); SndClickBeep(); @@ -832,16 +832,6 @@ struct GenerateLandscapeWindow : public Window { this->InvalidateData(); break; - case WID_GL_BORDERS_RANDOM: - if (_settings_newgame.game_creation.water_borders == BorderFlag::Random) { - _settings_newgame.game_creation.water_borders.Reset(); - } else { - _settings_newgame.game_creation.water_borders = BorderFlag::Random; - } - SndClickBeep(); - this->InvalidateData(); - break; - case WID_GL_AI_BUTTON: ///< AI Settings ShowAIConfigWindow(); break; @@ -908,6 +898,25 @@ struct GenerateLandscapeWindow : public Window { break; } + case WID_GL_BORDERS_PULLDOWN: { + switch (index) { + case BFP_RANDOM: + _settings_newgame.game_creation.water_borders = BorderFlag::Random; + _settings_newgame.construction.freeform_edges = true; + break; + case BFP_MANUAL: + _settings_newgame.game_creation.water_borders = {}; + _settings_newgame.construction.freeform_edges = true; + break; + case BFP_INFINITE_WATER: + _settings_newgame.game_creation.water_borders = BORDERFLAGS_ALL; + _settings_newgame.construction.freeform_edges = false; + break; + } + _settings_newgame.game_creation.water_border_presets = static_cast(index); + break; + } + case WID_GL_WATER_PULLDOWN: { if ((uint)index == CUSTOM_SEA_LEVEL_NUMBER_DIFFICULTY) { this->widget_id = widget; @@ -1235,7 +1244,7 @@ struct CreateScenarioWindow : public Window } }; -static constexpr NWidgetPart _nested_create_scenario_widgets[] = { +static constexpr std::initializer_list _nested_create_scenario_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_BROWN), NWidget(WWT_CAPTION, COLOUR_BROWN), SetStringTip(STR_SE_MAPGEN_CAPTION), @@ -1308,7 +1317,7 @@ void ShowCreateScenario() new CreateScenarioWindow(_create_scenario_desc, GLWM_SCENARIO); } -static constexpr NWidgetPart _nested_generate_progress_widgets[] = { +static constexpr std::initializer_list _nested_generate_progress_widgets = { NWidget(WWT_CAPTION, COLOUR_GREY), SetStringTip(STR_GENERATION_WORLD, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), NWidget(WWT_PANEL, COLOUR_GREY), NWidget(NWID_VERTICAL), SetPIP(0, WidgetDimensions::unscaled.vsep_wide, 0), SetPadding(WidgetDimensions::unscaled.modalpopup), @@ -1340,7 +1349,8 @@ static const StringID _generation_class_table[] = { STR_GENERATION_RIVER_GENERATION, STR_GENERATION_CLEARING_TILES, STR_GENERATION_TOWN_GENERATION, - STR_GENERATION_INDUSTRY_GENERATION, + STR_GENERATION_LAND_INDUSTRY_GENERATION, + STR_GENERATION_WATER_INDUSTRY_GENERATION, STR_GENERATION_OBJECT_GENERATION, STR_GENERATION_TREE_GENERATION, STR_GENERATION_SETTINGUP_GAME, @@ -1410,8 +1420,7 @@ struct GenerateProgressWindow : public Window { DrawFrameRect(r, COLOUR_GREY, {FrameFlag::BorderOnly, FrameFlag::Lowered}); Rect br = r.Shrink(WidgetDimensions::scaled.bevel); DrawFrameRect(br.WithWidth(br.Width() * GenWorldStatus::percent / 100, _current_text_dir == TD_RTL), COLOUR_MAUVE, {}); - DrawString(br.left, br.right, CentreBounds(br.top, br.bottom, GetCharacterHeight(FS_NORMAL)), - GetString(STR_GENERATION_PROGRESS, GenWorldStatus::percent), TC_FROMSTRING, SA_HOR_CENTER); + DrawString(br.CentreToHeight(GetCharacterHeight(FS_NORMAL)), GetString(STR_GENERATION_PROGRESS, GenWorldStatus::percent), TC_FROMSTRING, SA_HOR_CENTER); break; } @@ -1448,7 +1457,7 @@ void ShowGenerateWorldProgress() static void _SetGeneratingWorldProgress(GenWorldProgress cls, uint progress, uint total) { - static const int percent_table[] = {0, 5, 14, 17, 20, 40, 60, 65, 80, 85, 95, 99, 100 }; + static const int percent_table[] = {0, 5, 14, 17, 20, 40, 55, 60, 65, 80, 85, 95, 99, 100 }; static_assert(lengthof(percent_table) == GWP_CLASS_COUNT + 1); assert(cls < GWP_CLASS_COUNT); diff --git a/src/goal_cmd.h b/src/goal_cmd.h index 4cb017ede9f52..7002bad775f32 100644 --- a/src/goal_cmd.h +++ b/src/goal_cmd.h @@ -22,13 +22,13 @@ CommandCost CmdSetGoalCompleted(DoCommandFlags flags, GoalID goal, bool complete CommandCost CmdGoalQuestion(DoCommandFlags flags, uint16_t uniqueid, uint32_t target, bool is_client, uint32_t button_mask, GoalQuestionType type, const EncodedString &text); CommandCost CmdGoalQuestionAnswer(DoCommandFlags flags, uint16_t uniqueid, uint8_t button); -DEF_CMD_TRAIT(CMD_CREATE_GOAL, CmdCreateGoal, CommandFlags({CommandFlag::Deity, CommandFlag::StrCtrl}), CMDT_OTHER_MANAGEMENT) -DEF_CMD_TRAIT(CMD_REMOVE_GOAL, CmdRemoveGoal, CommandFlag::Deity, CMDT_OTHER_MANAGEMENT) -DEF_CMD_TRAIT(CMD_SET_GOAL_DESTINATION, CmdSetGoalDestination, CommandFlags({CommandFlag::Deity, CommandFlag::StrCtrl}), CMDT_OTHER_MANAGEMENT) -DEF_CMD_TRAIT(CMD_SET_GOAL_TEXT, CmdSetGoalText, CommandFlags({CommandFlag::Deity, CommandFlag::StrCtrl}), CMDT_OTHER_MANAGEMENT) -DEF_CMD_TRAIT(CMD_SET_GOAL_PROGRESS, CmdSetGoalProgress, CommandFlags({CommandFlag::Deity, CommandFlag::StrCtrl}), CMDT_OTHER_MANAGEMENT) -DEF_CMD_TRAIT(CMD_SET_GOAL_COMPLETED, CmdSetGoalCompleted, CommandFlags({CommandFlag::Deity, CommandFlag::StrCtrl}), CMDT_OTHER_MANAGEMENT) -DEF_CMD_TRAIT(CMD_GOAL_QUESTION, CmdGoalQuestion, CommandFlags({CommandFlag::Deity, CommandFlag::StrCtrl}), CMDT_OTHER_MANAGEMENT) -DEF_CMD_TRAIT(CMD_GOAL_QUESTION_ANSWER, CmdGoalQuestionAnswer, CommandFlag::Deity, CMDT_OTHER_MANAGEMENT) +DEF_CMD_TRAIT(CMD_CREATE_GOAL, CmdCreateGoal, CommandFlags({CommandFlag::Deity, CommandFlag::StrCtrl}), CommandType::OtherManagement) +DEF_CMD_TRAIT(CMD_REMOVE_GOAL, CmdRemoveGoal, CommandFlag::Deity, CommandType::OtherManagement) +DEF_CMD_TRAIT(CMD_SET_GOAL_DESTINATION, CmdSetGoalDestination, CommandFlags({CommandFlag::Deity, CommandFlag::StrCtrl}), CommandType::OtherManagement) +DEF_CMD_TRAIT(CMD_SET_GOAL_TEXT, CmdSetGoalText, CommandFlags({CommandFlag::Deity, CommandFlag::StrCtrl}), CommandType::OtherManagement) +DEF_CMD_TRAIT(CMD_SET_GOAL_PROGRESS, CmdSetGoalProgress, CommandFlags({CommandFlag::Deity, CommandFlag::StrCtrl}), CommandType::OtherManagement) +DEF_CMD_TRAIT(CMD_SET_GOAL_COMPLETED, CmdSetGoalCompleted, CommandFlags({CommandFlag::Deity, CommandFlag::StrCtrl}), CommandType::OtherManagement) +DEF_CMD_TRAIT(CMD_GOAL_QUESTION, CmdGoalQuestion, CommandFlags({CommandFlag::Deity, CommandFlag::StrCtrl}), CommandType::OtherManagement) +DEF_CMD_TRAIT(CMD_GOAL_QUESTION_ANSWER, CmdGoalQuestionAnswer, CommandFlag::Deity, CommandType::OtherManagement) #endif /* GOAL_CMD_H */ diff --git a/src/goal_gui.cpp b/src/goal_gui.cpp index ccf9d98b1efe3..e44e66644ccaa 100644 --- a/src/goal_gui.cpp +++ b/src/goal_gui.cpp @@ -275,7 +275,7 @@ struct GoalListWindow : public Window { }; /** Widgets of the #GoalListWindow. */ -static constexpr NWidgetPart _nested_goals_list_widgets[] = { +static constexpr std::initializer_list _nested_goals_list_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_BROWN), NWidget(WWT_CAPTION, COLOUR_BROWN, WID_GOAL_CAPTION), diff --git a/src/graph_gui.cpp b/src/graph_gui.cpp index 962b201405f51..74b916c168caf 100644 --- a/src/graph_gui.cpp +++ b/src/graph_gui.cpp @@ -133,7 +133,7 @@ static std::unique_ptr MakeNWidgetCompanyLines() return vert; } -static constexpr NWidgetPart _nested_graph_legend_widgets[] = { +static constexpr std::initializer_list _nested_graph_legend_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_BROWN), NWidget(WWT_CAPTION, COLOUR_BROWN), SetStringTip(STR_GRAPH_KEY_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), @@ -935,7 +935,7 @@ struct OperatingProfitGraphWindow : BaseCompanyGraphWindow { } }; -static constexpr NWidgetPart _nested_operating_profit_widgets[] = { +static constexpr std::initializer_list _nested_operating_profit_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_BROWN), NWidget(WWT_CAPTION, COLOUR_BROWN), SetStringTip(STR_GRAPH_OPERATING_PROFIT_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), @@ -988,7 +988,7 @@ struct IncomeGraphWindow : BaseCompanyGraphWindow { } }; -static constexpr NWidgetPart _nested_income_graph_widgets[] = { +static constexpr std::initializer_list _nested_income_graph_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_BROWN), NWidget(WWT_CAPTION, COLOUR_BROWN), SetStringTip(STR_GRAPH_INCOME_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), @@ -1039,7 +1039,7 @@ struct DeliveredCargoGraphWindow : BaseCompanyGraphWindow { } }; -static constexpr NWidgetPart _nested_delivered_cargo_graph_widgets[] = { +static constexpr std::initializer_list _nested_delivered_cargo_graph_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_BROWN), NWidget(WWT_CAPTION, COLOUR_BROWN), SetStringTip(STR_GRAPH_CARGO_DELIVERED_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), @@ -1096,7 +1096,7 @@ struct PerformanceHistoryGraphWindow : BaseCompanyGraphWindow { } }; -static constexpr NWidgetPart _nested_performance_history_widgets[] = { +static constexpr std::initializer_list _nested_performance_history_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_BROWN), NWidget(WWT_CAPTION, COLOUR_BROWN), SetStringTip(STR_GRAPH_COMPANY_PERFORMANCE_RATINGS_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), @@ -1148,7 +1148,7 @@ struct CompanyValueGraphWindow : BaseCompanyGraphWindow { } }; -static constexpr NWidgetPart _nested_company_value_graph_widgets[] = { +static constexpr std::initializer_list _nested_company_value_graph_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_BROWN), NWidget(WWT_CAPTION, COLOUR_BROWN), SetStringTip(STR_GRAPH_COMPANY_VALUES_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), @@ -1412,7 +1412,7 @@ struct PaymentRatesGraphWindow : BaseCargoGraphWindow { } }; -static constexpr NWidgetPart _nested_cargo_payment_rates_widgets[] = { +static constexpr std::initializer_list _nested_cargo_payment_rates_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_BROWN), NWidget(WWT_CAPTION, COLOUR_BROWN), SetStringTip(STR_GRAPH_CARGO_PAYMENT_RATES_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), @@ -1813,7 +1813,7 @@ struct IndustryProductionGraphWindow : BaseCargoGraphWindow { } }; -static constexpr NWidgetPart _nested_industry_production_widgets[] = { +static constexpr std::initializer_list _nested_industry_production_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_BROWN), NWidget(WWT_CAPTION, COLOUR_BROWN, WID_GRAPH_CAPTION), @@ -1957,7 +1957,7 @@ struct TownCargoGraphWindow : BaseCargoGraphWindow { } }; -static constexpr NWidgetPart _nested_town_cargo_graph_widgets[] = { +static constexpr std::initializer_list _nested_town_cargo_graph_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_BROWN), NWidget(WWT_CAPTION, COLOUR_BROWN, WID_GRAPH_CAPTION), @@ -2042,7 +2042,7 @@ std::unique_ptr MakeCompanyButtonRowsGraphGUI() return MakeCompanyButtonRows(WID_PRD_COMPANY_FIRST, WID_PRD_COMPANY_LAST, COLOUR_BROWN, 8, STR_PERFORMANCE_DETAIL_SELECT_COMPANY_TOOLTIP); } -static constexpr NWidgetPart _nested_performance_rating_detail_widgets[] = { +static constexpr std::initializer_list _nested_performance_rating_detail_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_BROWN), NWidget(WWT_CAPTION, COLOUR_BROWN), SetStringTip(STR_PERFORMANCE_DETAIL, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), diff --git a/src/group_cmd.cpp b/src/group_cmd.cpp index b0e4ce4ee57ab..2ba83c4dd892b 100644 --- a/src/group_cmd.cpp +++ b/src/group_cmd.cpp @@ -306,8 +306,8 @@ static void PropagateChildLivery(const Group *g, bool reset_cache) for (const GroupID &childgroup : g->children) { Group *cg = Group::Get(childgroup); - 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; + if (!cg->livery.in_use.Test(Livery::Flag::Primary)) cg->livery.colour1 = g->livery.colour1; + if (!cg->livery.in_use.Test(Livery::Flag::Secondary)) cg->livery.colour2 = g->livery.colour2; PropagateChildLivery(cg, reset_cache); } } @@ -321,8 +321,8 @@ void UpdateCompanyGroupLiveries(const Company *c) { for (Group *g : Group::Iterate()) { if (g->owner == c->index && g->parent == GroupID::Invalid()) { - 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; + if (!g->livery.in_use.Test(Livery::Flag::Primary)) g->livery.colour1 = c->livery[LS_DEFAULT].colour1; + if (!g->livery.in_use.Test(Livery::Flag::Secondary)) g->livery.colour2 = c->livery[LS_DEFAULT].colour2; PropagateChildLivery(g, false); } } @@ -480,11 +480,11 @@ CommandCost CmdAlterGroup(DoCommandFlags flags, AlterGroupMode mode, GroupID gro GroupStatistics::UpdateAutoreplace(g->owner); - if (!HasBit(g->livery.in_use, 0) || !HasBit(g->livery.in_use, 1)) { + if (!g->livery.in_use.All({Livery::Flag::Primary, Livery::Flag::Secondary})) { /* Update livery with new parent's colours if either colour is default. */ const Livery *livery = GetParentLivery(g); - if (!HasBit(g->livery.in_use, 0)) g->livery.colour1 = livery->colour1; - if (!HasBit(g->livery.in_use, 1)) g->livery.colour2 = livery->colour2; + if (!g->livery.in_use.Test(Livery::Flag::Primary)) g->livery.colour1 = livery->colour1; + if (!g->livery.in_use.Test(Livery::Flag::Secondary)) g->livery.colour2 = livery->colour2; PropagateChildLivery(g, true); MarkWholeScreenDirty(); @@ -684,11 +684,11 @@ CommandCost CmdSetGroupLivery(DoCommandFlags flags, GroupID group_id, bool prima if (flags.Test(DoCommandFlag::Execute)) { if (primary) { - AssignBit(g->livery.in_use, 0, colour != INVALID_COLOUR); + g->livery.in_use.Set(Livery::Flag::Primary, colour != INVALID_COLOUR); if (colour == INVALID_COLOUR) colour = GetParentLivery(g)->colour1; g->livery.colour1 = colour; } else { - AssignBit(g->livery.in_use, 1, colour != INVALID_COLOUR); + g->livery.in_use.Set(Livery::Flag::Secondary, colour != INVALID_COLOUR); if (colour == INVALID_COLOUR) colour = GetParentLivery(g)->colour2; g->livery.colour2 = colour; } diff --git a/src/group_cmd.h b/src/group_cmd.h index abef37b54270b..dea6d7120f116 100644 --- a/src/group_cmd.h +++ b/src/group_cmd.h @@ -34,14 +34,14 @@ CommandCost CmdRemoveAllVehiclesGroup(DoCommandFlags flags, GroupID group_id); CommandCost CmdSetGroupFlag(DoCommandFlags flags, GroupID group_id, GroupFlag flag, bool value, bool recursive); CommandCost CmdSetGroupLivery(DoCommandFlags flags, GroupID group_id, bool primary, Colours colour); -DEF_CMD_TRAIT(CMD_CREATE_GROUP, CmdCreateGroup, {}, CMDT_ROUTE_MANAGEMENT) -DEF_CMD_TRAIT(CMD_DELETE_GROUP, CmdDeleteGroup, {}, CMDT_ROUTE_MANAGEMENT) -DEF_CMD_TRAIT(CMD_ALTER_GROUP, CmdAlterGroup, {}, CMDT_OTHER_MANAGEMENT) -DEF_CMD_TRAIT(CMD_ADD_VEHICLE_GROUP, CmdAddVehicleGroup, {}, CMDT_ROUTE_MANAGEMENT) -DEF_CMD_TRAIT(CMD_ADD_SHARED_VEHICLE_GROUP, CmdAddSharedVehicleGroup, {}, CMDT_ROUTE_MANAGEMENT) -DEF_CMD_TRAIT(CMD_REMOVE_ALL_VEHICLES_GROUP, CmdRemoveAllVehiclesGroup, {}, CMDT_ROUTE_MANAGEMENT) -DEF_CMD_TRAIT(CMD_SET_GROUP_FLAG, CmdSetGroupFlag, {}, CMDT_ROUTE_MANAGEMENT) -DEF_CMD_TRAIT(CMD_SET_GROUP_LIVERY, CmdSetGroupLivery, {}, CMDT_ROUTE_MANAGEMENT) +DEF_CMD_TRAIT(CMD_CREATE_GROUP, CmdCreateGroup, {}, CommandType::RouteManagement) +DEF_CMD_TRAIT(CMD_DELETE_GROUP, CmdDeleteGroup, {}, CommandType::RouteManagement) +DEF_CMD_TRAIT(CMD_ALTER_GROUP, CmdAlterGroup, {}, CommandType::OtherManagement) +DEF_CMD_TRAIT(CMD_ADD_VEHICLE_GROUP, CmdAddVehicleGroup, {}, CommandType::RouteManagement) +DEF_CMD_TRAIT(CMD_ADD_SHARED_VEHICLE_GROUP, CmdAddSharedVehicleGroup, {}, CommandType::RouteManagement) +DEF_CMD_TRAIT(CMD_REMOVE_ALL_VEHICLES_GROUP, CmdRemoveAllVehiclesGroup, {}, CommandType::RouteManagement) +DEF_CMD_TRAIT(CMD_SET_GROUP_FLAG, CmdSetGroupFlag, {}, CommandType::RouteManagement) +DEF_CMD_TRAIT(CMD_SET_GROUP_LIVERY, CmdSetGroupLivery, {}, CommandType::RouteManagement) void CcCreateGroup(Commands cmd, const CommandCost &result, GroupID new_group, VehicleType vt, GroupID parent_group); void CcAddVehicleNewGroup(Commands cmd, const CommandCost &result, GroupID new_group, GroupID, VehicleID veh_id, bool, const VehicleListIdentifier &); diff --git a/src/group_gui.cpp b/src/group_gui.cpp index df081be946329..af4d073c1a3d2 100644 --- a/src/group_gui.cpp +++ b/src/group_gui.cpp @@ -38,7 +38,7 @@ #include "safeguards.h" -static constexpr NWidgetPart _nested_group_widgets[] = { +static constexpr std::initializer_list _nested_group_widgets = { NWidget(NWID_HORIZONTAL), // Window header NWidget(WWT_CLOSEBOX, COLOUR_GREY), NWidget(WWT_CAPTION, COLOUR_GREY, WID_GL_CAPTION), @@ -240,24 +240,24 @@ class VehicleGroupWindow : public BaseVehicleListWindow { */ uint ComputeGroupInfoSize() { - this->column_size[VGC_FOLD] = maxdim(GetSpriteSize(SPR_CIRCLE_FOLDED), GetSpriteSize(SPR_CIRCLE_UNFOLDED)); + this->column_size[VGC_FOLD] = maxdim(GetScaledSpriteSize(SPR_CIRCLE_FOLDED), GetScaledSpriteSize(SPR_CIRCLE_UNFOLDED)); this->tiny_step_height = this->column_size[VGC_FOLD].height; this->column_size[VGC_NAME] = maxdim(GetStringBoundingBox(STR_GROUP_DEFAULT_TRAINS + this->vli.vtype), GetStringBoundingBox(STR_GROUP_ALL_TRAINS + this->vli.vtype)); this->column_size[VGC_NAME].width = std::max(170u, this->column_size[VGC_NAME].width) + WidgetDimensions::scaled.hsep_indent; this->tiny_step_height = std::max(this->tiny_step_height, this->column_size[VGC_NAME].height); - this->column_size[VGC_PROTECT] = GetSpriteSize(SPR_GROUP_REPLACE_PROTECT); + this->column_size[VGC_PROTECT] = GetScaledSpriteSize(SPR_GROUP_REPLACE_PROTECT); this->tiny_step_height = std::max(this->tiny_step_height, this->column_size[VGC_PROTECT].height); - this->column_size[VGC_AUTOREPLACE] = GetSpriteSize(SPR_GROUP_REPLACE_ACTIVE); + this->column_size[VGC_AUTOREPLACE] = GetScaledSpriteSize(SPR_GROUP_REPLACE_ACTIVE); this->tiny_step_height = std::max(this->tiny_step_height, this->column_size[VGC_AUTOREPLACE].height); this->column_size[VGC_PROFIT].width = 0; this->column_size[VGC_PROFIT].height = 0; static const SpriteID profit_sprites[] = {SPR_PROFIT_NA, SPR_PROFIT_NEGATIVE, SPR_PROFIT_SOME, SPR_PROFIT_LOT}; for (const auto &profit_sprite : profit_sprites) { - Dimension d = GetSpriteSize(profit_sprite); + Dimension d = GetScaledSpriteSize(profit_sprite); this->column_size[VGC_PROFIT] = maxdim(this->column_size[VGC_PROFIT], d); } this->tiny_step_height = std::max(this->tiny_step_height, this->column_size[VGC_PROFIT].height); @@ -281,19 +281,17 @@ class VehicleGroupWindow : public BaseVehicleListWindow { /** * Draw a row in the group list. - * @param y Top of the row. - * @param left Left of the row. - * @param right Right of the row. + * @param r Rect to draw row in. * @param g_id Group to list. * @param indent Indentation level. * @param protection Whether autoreplace protection is set. * @param has_children Whether the group has children and should have a fold / unfold button. */ - void DrawGroupInfo(int y, int left, int right, GroupID g_id, uint16_t level_mask = 0, uint8_t indent = 0, bool protection = false, bool has_children = false) const + void DrawGroupInfo(Rect r, GroupID g_id, uint16_t level_mask = 0, uint8_t indent = 0, bool protection = false, bool has_children = false) const { /* Highlight the group if a vehicle is dragged over it */ if (g_id == this->group_over) { - GfxFillRect(left + WidgetDimensions::scaled.bevel.left, y + WidgetDimensions::scaled.framerect.top, right - WidgetDimensions::scaled.bevel.right, y + this->tiny_step_height - 1 - WidgetDimensions::scaled.framerect.bottom, GetColourGradient(COLOUR_GREY, SHADE_LIGHTEST)); + GfxFillRect(r.Shrink(WidgetDimensions::scaled.bevel), GetColourGradient(COLOUR_GREY, SHADE_LIGHTEST)); } if (g_id == NEW_GROUP) return; @@ -307,25 +305,29 @@ class VehicleGroupWindow : public BaseVehicleListWindow { const int level_width = rtl ? -WidgetDimensions::scaled.hsep_indent : WidgetDimensions::scaled.hsep_indent; const PixelColour linecolour = GetColourGradient(COLOUR_ORANGE, SHADE_NORMAL); + r = r.Shrink(WidgetDimensions::scaled.framerect, RectPadding::zero); if (indent > 0) { /* Draw tree continuation lines. */ - int tx = (rtl ? right - WidgetDimensions::scaled.framerect.right : left + WidgetDimensions::scaled.framerect.left) + offset; + int tx = (rtl ? r.right : r.left) + offset; for (uint lvl = 1; lvl <= indent; ++lvl) { - if (HasBit(level_mask, lvl)) GfxDrawLine(tx, y, tx, y + this->tiny_step_height - 1, linecolour, WidgetDimensions::scaled.fullbevel.top); + if (HasBit(level_mask, lvl)) GfxDrawLine(tx, r.top, tx, r.bottom, linecolour, WidgetDimensions::scaled.fullbevel.top); if (lvl < indent) tx += level_width; } /* Draw our node in the tree. */ - int ycentre = y + this->tiny_step_height / 2 - 1; - if (!HasBit(level_mask, indent)) GfxDrawLine(tx, y, tx, ycentre, linecolour, WidgetDimensions::scaled.fullbevel.top); + int ycentre = CentreBounds(r.top, r.bottom, WidgetDimensions::scaled.fullbevel.top); + if (!HasBit(level_mask, indent)) GfxDrawLine(tx, r.top, tx, ycentre, linecolour, WidgetDimensions::scaled.fullbevel.top); GfxDrawLine(tx, ycentre, tx + offset - (rtl ? -1 : 1), ycentre, linecolour, WidgetDimensions::scaled.fullbevel.top); } /* draw fold / unfold button */ - int x = rtl ? right - WidgetDimensions::scaled.framerect.right - this->column_size[VGC_FOLD].width + 1 : left + WidgetDimensions::scaled.framerect.left; + r = r.Indent(indent * WidgetDimensions::scaled.hsep_indent, rtl); if (has_children) { - DrawSprite(Group::Get(g_id)->folded ? SPR_CIRCLE_FOLDED : SPR_CIRCLE_UNFOLDED, PAL_NONE, x + indent * level_width, y + (this->tiny_step_height - this->column_size[VGC_FOLD].height) / 2); + DrawSpriteIgnorePadding(Group::Get(g_id)->folded ? SPR_CIRCLE_FOLDED : SPR_CIRCLE_UNFOLDED, PAL_NONE, r.WithWidth(this->column_size[VGC_FOLD].width, rtl), SA_CENTER); } + /* Group name text column shrinks to fit available space. */ + int text_width = this->column_size[VGC_NAME].width - indent * WidgetDimensions::scaled.hsep_indent; + /* draw group name */ std::string str; if (IsAllGroupID(g_id)) { @@ -335,19 +337,22 @@ class VehicleGroupWindow : public BaseVehicleListWindow { } else { str = GetString(STR_GROUP_NAME, g_id); } - x = rtl ? x - WidgetDimensions::scaled.hsep_normal - this->column_size[VGC_NAME].width : x + WidgetDimensions::scaled.hsep_normal + this->column_size[VGC_FOLD].width; - DrawString(x + (rtl ? 0 : indent * WidgetDimensions::scaled.hsep_indent), x + this->column_size[VGC_NAME].width - 1 - (rtl ? indent * WidgetDimensions::scaled.hsep_indent : 0), y + (this->tiny_step_height - this->column_size[VGC_NAME].height) / 2, std::move(str), colour); + r = r.Indent(this->column_size[VGC_FOLD].width + WidgetDimensions::scaled.hsep_normal, rtl); + DrawString(r.WithWidth(text_width, rtl).CentreToHeight(this->column_size[VGC_NAME].height), std::move(str), colour); /* draw autoreplace protection */ - x = rtl ? x - WidgetDimensions::scaled.hsep_wide - this->column_size[VGC_PROTECT].width : x + WidgetDimensions::scaled.hsep_wide + this->column_size[VGC_NAME].width; - if (protection) DrawSprite(SPR_GROUP_REPLACE_PROTECT, PAL_NONE, x, y + (this->tiny_step_height - this->column_size[VGC_PROTECT].height) / 2); + r = r.Indent(text_width + WidgetDimensions::scaled.hsep_wide, rtl); + if (protection) { + DrawSpriteIgnorePadding(SPR_GROUP_REPLACE_PROTECT, PAL_NONE, r.WithWidth(this->column_size[VGC_PROTECT].width, rtl), SA_CENTER); + } /* draw autoreplace status */ - x = rtl ? x - WidgetDimensions::scaled.hsep_normal - this->column_size[VGC_AUTOREPLACE].width : x + WidgetDimensions::scaled.hsep_normal + this->column_size[VGC_PROTECT].width; - if (stats.autoreplace_defined) DrawSprite(SPR_GROUP_REPLACE_ACTIVE, stats.autoreplace_finished ? PALETTE_CRASH : PAL_NONE, x, y + (this->tiny_step_height - this->column_size[VGC_AUTOREPLACE].height) / 2); + r = r.Indent(this->column_size[VGC_PROTECT].width + WidgetDimensions::scaled.hsep_normal, rtl); + if (stats.autoreplace_defined) { + DrawSpriteIgnorePadding(SPR_GROUP_REPLACE_ACTIVE, stats.autoreplace_finished ? PALETTE_CRASH : PAL_NONE, r.WithWidth(this->column_size[VGC_AUTOREPLACE].width, rtl), SA_CENTER); + } /* draw the profit icon */ - x = rtl ? x - WidgetDimensions::scaled.hsep_normal - this->column_size[VGC_PROFIT].width : x + WidgetDimensions::scaled.hsep_normal + this->column_size[VGC_AUTOREPLACE].width; SpriteID spr; uint num_vehicle_min_age = GetGroupNumVehicleMinAge(this->vli.company, g_id, this->vli.vtype); Money profit_last_year_min_age = GetGroupProfitLastYearMinAge(this->vli.company, g_id, this->vli.vtype); @@ -360,16 +365,18 @@ class VehicleGroupWindow : public BaseVehicleListWindow { } else { spr = SPR_PROFIT_LOT; } - DrawSprite(spr, PAL_NONE, x, y + (this->tiny_step_height - this->column_size[VGC_PROFIT].height) / 2); + + r = r.Indent(this->column_size[VGC_AUTOREPLACE].width + WidgetDimensions::scaled.hsep_normal, rtl); + DrawSpriteIgnorePadding(spr, PAL_NONE, r.WithWidth(this->column_size[VGC_PROFIT].width, rtl), SA_CENTER); /* draw the number of vehicles of the group */ - x = rtl ? x - WidgetDimensions::scaled.hsep_normal - this->column_size[VGC_NUMBER].width : x + WidgetDimensions::scaled.hsep_normal + this->column_size[VGC_PROFIT].width; + r = r.Indent(this->column_size[VGC_PROFIT].width + WidgetDimensions::scaled.hsep_normal, rtl); int num_vehicle_with_subgroups = GetGroupNumVehicle(this->vli.company, g_id, this->vli.vtype); int num_vehicle = GroupStatistics::Get(this->vli.company, g_id, this->vli.vtype).num_vehicle; if (IsAllGroupID(g_id) || IsDefaultGroupID(g_id) || num_vehicle_with_subgroups == num_vehicle) { - DrawString(x, x + this->column_size[VGC_NUMBER].width - 1, y + (this->tiny_step_height - this->column_size[VGC_NUMBER].height) / 2, GetString(STR_JUST_COMMA, num_vehicle), colour, SA_RIGHT | SA_FORCE, false, FS_SMALL); + DrawString(r.CentreToHeight(this->column_size[VGC_NUMBER].height), GetString(STR_JUST_COMMA, num_vehicle), colour, SA_RIGHT | SA_FORCE, false, FS_SMALL); } else { - DrawString(x, x + this->column_size[VGC_NUMBER].width - 1, y + (this->tiny_step_height - this->column_size[VGC_NUMBER].height) / 2, GetString(STR_GROUP_COUNT_WITH_SUBGROUP, num_vehicle, num_vehicle_with_subgroups - num_vehicle), colour, SA_RIGHT | SA_FORCE); + DrawString(r.CentreToHeight(this->column_size[VGC_NUMBER].height), GetString(STR_GROUP_COUNT_WITH_SUBGROUP, num_vehicle, num_vehicle_with_subgroups - num_vehicle), colour, SA_RIGHT | SA_FORCE); } } @@ -594,11 +601,11 @@ class VehicleGroupWindow : public BaseVehicleListWindow { { switch (widget) { case WID_GL_ALL_VEHICLES: - DrawGroupInfo(r.top, r.left, r.right, ALL_GROUP); + DrawGroupInfo(r, ALL_GROUP); break; case WID_GL_DEFAULT_VEHICLES: - DrawGroupInfo(r.top, r.left, r.right, DEFAULT_GROUP); + DrawGroupInfo(r, DEFAULT_GROUP); break; case WID_GL_INFO: { @@ -634,19 +641,18 @@ class VehicleGroupWindow : public BaseVehicleListWindow { } case WID_GL_LIST_GROUP: { - int y1 = r.top; + Rect row = r.WithHeight(this->tiny_step_height); + auto [first, last] = this->group_sb->GetVisibleRangeIterators(this->groups); for (auto it = first; it != last; ++it) { const Group *g = it->group; - assert(g->owner == this->owner); - DrawGroupInfo(y1, r.left, r.right, g->index, it->level_mask, it->indent, g->flags.Test(GroupFlag::ReplaceProtection), g->folded || (std::next(it) != std::end(this->groups) && std::next(it)->indent > it->indent)); - - y1 += this->tiny_step_height; + DrawGroupInfo(row, g->index, it->level_mask, it->indent, g->flags.Test(GroupFlag::ReplaceProtection), g->folded || (std::next(it) != std::end(this->groups) && std::next(it)->indent > it->indent)); + row = row.Translate(0, this->tiny_step_height); } if ((uint)this->group_sb->GetPosition() + this->group_sb->GetCapacity() > this->groups.size()) { - DrawGroupInfo(y1, r.left, r.right, NEW_GROUP); + DrawGroupInfo(row, NEW_GROUP); } break; } @@ -733,11 +739,10 @@ class VehicleGroupWindow : public BaseVehicleListWindow { if (it->group->folded || (std::next(it) != std::end(this->groups) && std::next(it)->indent > it->indent)) { /* The group has children, check if the user clicked the fold / unfold button. */ - NWidgetCore *group_display = this->GetWidget(widget); - int x = _current_text_dir == TD_RTL ? - group_display->pos_x + group_display->current_x - WidgetDimensions::scaled.framerect.right - it->indent * WidgetDimensions::scaled.hsep_indent - this->column_size[VGC_FOLD].width : - group_display->pos_x + WidgetDimensions::scaled.framerect.left + it->indent * WidgetDimensions::scaled.hsep_indent; - if (click_count > 1 || (pt.x >= x && pt.x < (int)(x + this->column_size[VGC_FOLD].width))) { + bool rtl = _current_text_dir == TD_RTL; + Rect r = this->GetWidget(widget)->GetCurrentRect().Shrink(WidgetDimensions::scaled.framerect, RectPadding::zero); + r = r.Indent(it->indent * WidgetDimensions::scaled.hsep_indent, rtl).WithWidth(this->column_size[VGC_FOLD].width, rtl); + if (click_count > 1 || r.Contains(pt)) { GroupID g = this->vli.ToGroupID(); if (!IsAllGroupID(g) && !IsDefaultGroupID(g)) { diff --git a/src/gui.h b/src/gui.h index 5cfded5c8f3a7..9c38a02e9db16 100644 --- a/src/gui.h +++ b/src/gui.h @@ -10,6 +10,8 @@ #ifndef GUI_H #define GUI_H +#include "rail_type.h" +#include "road_type.h" #include "strings_type.h" #include "vehicle_type.h" #include "economy_type.h" @@ -72,7 +74,7 @@ void ShowExtraViewportWindow(TileIndex tile = INVALID_TILE); void ShowExtraViewportWindowForTileUnderCursor(); /* bridge_gui.cpp */ -void ShowBuildBridgeWindow(TileIndex start, TileIndex end, TransportType transport_type, uint8_t bridge_type); +void ShowBuildBridgeWindow(TileIndex start, TileIndex end, TransportType transport_type, RailType railtype, RoadType roadtype); /* music_gui.cpp */ void ShowMusicWindow(); diff --git a/src/heightmap.cpp b/src/heightmap.cpp index 543ef179525a3..0bbc79cb3d57a 100644 --- a/src/heightmap.cpp +++ b/src/heightmap.cpp @@ -9,6 +9,7 @@ #include "stdafx.h" #include "heightmap.h" +#include "landscape.h" #include "clear_map.h" #include "strings_func.h" #include "void_map.h" @@ -21,6 +22,10 @@ #include "table/strings.h" +#ifdef WITH_PNG +#include +#endif /* WITH_PNG */ + #include "safeguards.h" /** @@ -71,8 +76,6 @@ static inline uint8_t RGBToGreyscale(uint8_t red, uint8_t green, uint8_t blue) #ifdef WITH_PNG -#include - /** * The PNG Heightmap loader. */ @@ -523,6 +526,10 @@ bool LoadHeightmap(DetailedFileType dft, std::string_view filename) GreyscaleToMapHeights(x, y, map); FixSlopes(); + + /* If all map borders are water, we will draw infinite water. */ + _settings_game.construction.freeform_edges = !IsMapSurroundedByWater(); + MarkWholeScreenDirty(); return true; diff --git a/src/help_gui.cpp b/src/help_gui.cpp index 14c18652a8848..b9fa907227cde 100644 --- a/src/help_gui.cpp +++ b/src/help_gui.cpp @@ -175,7 +175,7 @@ struct HelpWindow : public Window { } }; -static constexpr NWidgetPart _nested_helpwin_widgets[] = { +static constexpr std::initializer_list _nested_helpwin_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN), NWidget(WWT_CAPTION, COLOUR_DARK_GREEN), SetStringTip(STR_HELP_WINDOW_CAPTION), diff --git a/src/highscore.cpp b/src/highscore.cpp index 943edab559f71..e46a445c52d22 100644 --- a/src/highscore.cpp +++ b/src/highscore.cpp @@ -87,20 +87,19 @@ static bool HighScoreSorter(const Company * const &a, const Company * const &b) */ int8_t SaveHighScoreValueNetwork() { - const Company *cl[MAX_COMPANIES]; - size_t count = 0; + std::vector cl; int8_t local_company_place = -1; /* Sort all active companies with the highest score first */ - for (const Company *c : Company::Iterate()) cl[count++] = c; + for (const Company *c : Company::Iterate()) cl.push_back(c); - std::sort(std::begin(cl), std::begin(cl) + count, HighScoreSorter); + std::ranges::sort(cl, HighScoreSorter); /* Clear the high scores from the previous network game. */ auto &highscores = _highscore_table[SP_MULTIPLAYER]; std::fill(highscores.begin(), highscores.end(), HighScore{}); - for (size_t i = 0; i < count && i < highscores.size(); i++) { + for (size_t i = 0; i < cl.size() && i < highscores.size(); i++) { const Company *c = cl[i]; auto &highscore = highscores[i]; highscore.name = GetString(STR_HIGHSCORE_NAME, c->index, c->index); // get manager/company name string diff --git a/src/highscore_gui.cpp b/src/highscore_gui.cpp index fde61eb60bde8..e5e0a3da4fafe 100644 --- a/src/highscore_gui.cpp +++ b/src/highscore_gui.cpp @@ -217,7 +217,7 @@ struct HighScoreWindow : EndGameHighScoreBaseWindow { } }; -static constexpr NWidgetPart _nested_highscore_widgets[] = { +static constexpr std::initializer_list _nested_highscore_widgets = { NWidget(WWT_PANEL, COLOUR_BROWN, WID_H_BACKGROUND), SetResize(1, 1), EndContainer(), }; diff --git a/src/industry_cmd.cpp b/src/industry_cmd.cpp index d1e273ab4bfae..3cc143aa6b081 100644 --- a/src/industry_cmd.cpp +++ b/src/industry_cmd.cpp @@ -45,6 +45,7 @@ #include "industry_cmd.h" #include "landscape_cmd.h" #include "terraform_cmd.h" +#include "map_func.h" #include "timer/timer.h" #include "timer/timer_game_calendar.h" #include "timer/timer_game_economy.h" @@ -1761,17 +1762,25 @@ static void DoCreateNewIndustry(Industry *i, TileIndex tile, IndustryType type, auto &industries = Industry::industries[type]; industries.insert(i->index); + size_t produced_count = 0; for (size_t index = 0; index < std::size(indspec->produced_cargo); ++index) { - if (!IsValidCargoType(indspec->produced_cargo[index])) break; - + if (IsValidCargoType(indspec->produced_cargo[index])) { + produced_count = index + 1; + } + } + for (size_t index = 0; index < produced_count; ++index) { Industry::ProducedCargo &p = i->produced.emplace_back(); p.cargo = indspec->produced_cargo[index]; p.rate = indspec->production_rate[index]; } + size_t accepted_count = 0; for (size_t index = 0; index < std::size(indspec->accepts_cargo); ++index) { - if (!IsValidCargoType(indspec->accepts_cargo[index])) break; - + if (IsValidCargoType(indspec->accepts_cargo[index])) { + accepted_count = index + 1; + } + } + for (size_t index = 0; index < accepted_count; ++index) { Industry::AcceptedCargo &a = i->accepted.emplace_back(); a.cargo = indspec->accepts_cargo[index]; } @@ -1827,13 +1836,13 @@ static void DoCreateNewIndustry(Industry *i, TileIndex tile, IndustryType type, if (indspec->callback_mask.Test(IndustryCallbackMask::Production256Ticks)) { IndustryProductionCallback(i, 1); for (auto &p : i->produced) { - p.history[LAST_MONTH].production = ScaleByCargoScale(p.waiting * 8, false); + if (IsValidCargoType(p.cargo)) p.history[LAST_MONTH].production = ScaleByCargoScale(p.waiting * 8, false); p.waiting = 0; } } for (auto &p : i->produced) { - p.history[LAST_MONTH].production += ScaleByCargoScale(p.rate * 8, false); + if (IsValidCargoType(p.cargo)) p.history[LAST_MONTH].production += ScaleByCargoScale(p.rate * 8, false); } UpdateValidHistory(i->valid_history, HISTORY_YEAR, TimerGameEconomy::month); @@ -2282,12 +2291,15 @@ static Industry *CreateNewIndustry(TileIndex tile, IndustryType type, IndustryAv /** * Compute the appearance probability for an industry during map creation. * @param it Industry type to compute. + * @param water Whether to get probability of land-based, water-based, (or both, if std::nullopt), industry types. * @param[out] force_at_least_one Returns whether at least one instance should be forced on map creation. * @return Relative probability for the industry to appear. */ -static uint32_t GetScaledIndustryGenerationProbability(IndustryType it, bool *force_at_least_one) +static uint32_t GetScaledIndustryGenerationProbability(IndustryType it, std::optional water, bool *force_at_least_one) { const IndustrySpec *ind_spc = GetIndustrySpec(it); + if (water.has_value() && ind_spc->behaviour.Test(IndustryBehaviour::BuiltOnWater) != *water) return 0; + uint32_t chance = ind_spc->appear_creation[to_underlying(_settings_game.game_creation.landscape)]; if (!ind_spc->enabled || ind_spc->layouts.empty() || (_game_mode != GM_EDITOR && _settings_game.difficulty.industry_density == ID_FUND_ONLY) || @@ -2379,11 +2391,11 @@ static Industry *PlaceIndustry(IndustryType type, IndustryAvailabilityCallType c * @param type IndustryType of the desired industry * @param try_hard Try very hard to find a place. (Used to place at least one industry per type) */ -static void PlaceInitialIndustry(IndustryType type, bool try_hard) +static void PlaceInitialIndustry(IndustryType type, bool water, bool try_hard) { Backup cur_company(_current_company, OWNER_NONE); - IncreaseGeneratingWorldProgress(GWP_INDUSTRY); + IncreaseGeneratingWorldProgress(water ? GWP_WATER_INDUSTRY : GWP_LAND_INDUSTRY); PlaceIndustry(type, IACT_MAPGENERATION, try_hard); cur_company.Restore(); @@ -2437,6 +2449,31 @@ void IndustryBuildData::EconomyMonthlyLoop() } } +struct IndustryGenerationProbabilities { + std::array probs{}; + std::array force_one{}; + uint64_t total = 0; + uint num_forced = 0; +}; + +/** + * Get scaled industry generation probabilities. + * @param water Whether to get land or water industry probabilities. + * @returns Probability information. + */ +static IndustryGenerationProbabilities GetScaledProbabilities(bool water) +{ + IndustryGenerationProbabilities p{}; + + for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) { + p.probs[it] = GetScaledIndustryGenerationProbability(it, water, &p.force_one[it]); + p.total += p.probs[it];; + if (p.force_one[it]) p.num_forced++; + } + + return p; +} + /** * This function will create random industries during game creation. * It will scale the amount of industries by mapsize and difficulty level. @@ -2445,46 +2482,54 @@ void GenerateIndustries() { if (_game_mode != GM_EDITOR && _settings_game.difficulty.industry_density == ID_FUND_ONLY) return; // No industries in the game. - uint32_t industry_probs[NUM_INDUSTRYTYPES]; - bool force_at_least_one[NUM_INDUSTRYTYPES]; - uint32_t total_prob = 0; - uint num_forced = 0; + /* Get the probabilities for all industries. This is done first as we need the total of + * both land and water for scaling later. */ + IndustryGenerationProbabilities lprob = GetScaledProbabilities(false); + IndustryGenerationProbabilities wprob = GetScaledProbabilities(true); - for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) { - industry_probs[it] = GetScaledIndustryGenerationProbability(it, force_at_least_one + it); - total_prob += industry_probs[it]; - if (force_at_least_one[it]) num_forced++; - } + /* Run generation twice, for land and water industries in turn. */ + for (bool water = false;; water = true) { + auto &p = water ? wprob : lprob; - uint total_amount = GetNumberOfIndustries(); - if (total_prob == 0 || total_amount < num_forced) { - /* Only place the forced ones */ - total_amount = num_forced; - } + /* Total number of industries scaled by land/water proportion. */ + uint total_amount = p.total * GetNumberOfIndustries() / (lprob.total + wprob.total); - SetGeneratingWorldProgress(GWP_INDUSTRY, total_amount); + /* Scale land-based industries to the land proportion, unless the player has set a custom industry count. */ + if (!water && _settings_game.difficulty.industry_density != ID_CUSTOM) total_amount = Map::ScaleByLandProportion(total_amount); - /* Try to build one industry per type independent of any probabilities */ - for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) { - if (force_at_least_one[it]) { - assert(total_amount > 0); - total_amount--; - PlaceInitialIndustry(it, true); + /* Ensure that forced industries are generated even if the scaled amounts are too low. */ + if (p.total == 0 || total_amount < p.num_forced) { + /* Only place the forced ones */ + total_amount = p.num_forced; } - } - /* Add the remaining industries according to their probabilities */ - for (uint i = 0; i < total_amount; i++) { - uint32_t r = RandomRange(total_prob); - IndustryType it = 0; - while (r >= industry_probs[it]) { - r -= industry_probs[it]; - it++; - assert(it < NUM_INDUSTRYTYPES); + SetGeneratingWorldProgress(water ? GWP_WATER_INDUSTRY : GWP_LAND_INDUSTRY, total_amount); + + /* Try to build one industry per type independent of any probabilities */ + for (IndustryType it = 0; it < NUM_INDUSTRYTYPES; it++) { + if (p.force_one[it]) { + assert(total_amount > 0); + total_amount--; + PlaceInitialIndustry(it, water, true); + } } - assert(industry_probs[it] > 0); - PlaceInitialIndustry(it, false); + + /* Add the remaining industries according to their probabilities */ + for (uint i = 0; i < total_amount; i++) { + uint32_t r = RandomRange(p.total); + IndustryType it = 0; + while (r >= p.probs[it]) { + r -= p.probs[it]; + it++; + assert(it < NUM_INDUSTRYTYPES); + } + assert(p.probs[it] > 0); + PlaceInitialIndustry(it, water, false); + } + + if (water) break; } + _industry_builder.Reset(); } @@ -3111,7 +3156,7 @@ void CheckIndustries() if (Industry::GetIndustryTypeCount(it) > 0) continue; // Types of existing industries can be skipped. bool force_at_least_one; - uint32_t chance = GetScaledIndustryGenerationProbability(it, &force_at_least_one); + uint32_t chance = GetScaledIndustryGenerationProbability(it, std::nullopt, &force_at_least_one); if (chance == 0 || !force_at_least_one) continue; // Types that are not available can be skipped. const IndustrySpec *is = GetIndustrySpec(it); diff --git a/src/industry_cmd.h b/src/industry_cmd.h index f1d8b5f4dca01..78a7687cda153 100644 --- a/src/industry_cmd.h +++ b/src/industry_cmd.h @@ -21,10 +21,10 @@ CommandCost CmdIndustrySetExclusivity(DoCommandFlags flags, IndustryID ind_id, O CommandCost CmdIndustrySetText(DoCommandFlags flags, IndustryID ind_id, const EncodedString &text); CommandCost CmdIndustrySetProduction(DoCommandFlags flags, IndustryID ind_id, uint8_t prod_level, bool show_news, const EncodedString &text); -DEF_CMD_TRAIT(CMD_BUILD_INDUSTRY, CmdBuildIndustry, CommandFlag::Deity, CMDT_LANDSCAPE_CONSTRUCTION) -DEF_CMD_TRAIT(CMD_INDUSTRY_SET_FLAGS, CmdIndustrySetFlags, CommandFlag::Deity, CMDT_OTHER_MANAGEMENT) -DEF_CMD_TRAIT(CMD_INDUSTRY_SET_EXCLUSIVITY, CmdIndustrySetExclusivity, CommandFlag::Deity, CMDT_OTHER_MANAGEMENT) -DEF_CMD_TRAIT(CMD_INDUSTRY_SET_TEXT, CmdIndustrySetText, CommandFlags({CommandFlag::Deity, CommandFlag::StrCtrl}), CMDT_OTHER_MANAGEMENT) -DEF_CMD_TRAIT(CMD_INDUSTRY_SET_PRODUCTION, CmdIndustrySetProduction, CommandFlag::Deity, CMDT_OTHER_MANAGEMENT) +DEF_CMD_TRAIT(CMD_BUILD_INDUSTRY, CmdBuildIndustry, CommandFlag::Deity, CommandType::LandscapeConstruction) +DEF_CMD_TRAIT(CMD_INDUSTRY_SET_FLAGS, CmdIndustrySetFlags, CommandFlag::Deity, CommandType::OtherManagement) +DEF_CMD_TRAIT(CMD_INDUSTRY_SET_EXCLUSIVITY, CmdIndustrySetExclusivity, CommandFlag::Deity, CommandType::OtherManagement) +DEF_CMD_TRAIT(CMD_INDUSTRY_SET_TEXT, CmdIndustrySetText, CommandFlags({CommandFlag::Deity, CommandFlag::StrCtrl}), CommandType::OtherManagement) +DEF_CMD_TRAIT(CMD_INDUSTRY_SET_PRODUCTION, CmdIndustrySetProduction, CommandFlag::Deity, CommandType::OtherManagement) #endif /* INDUSTRY_CMD_H */ diff --git a/src/industry_gui.cpp b/src/industry_gui.cpp index a4f94228e232e..25ac005796492 100644 --- a/src/industry_gui.cpp +++ b/src/industry_gui.cpp @@ -257,7 +257,7 @@ void SortIndustryTypes() std::sort(_sorted_industry_types.begin(), _sorted_industry_types.end(), IndustryTypeNameSorter); } -static constexpr NWidgetPart _nested_build_industry_widgets[] = { +static constexpr std::initializer_list _nested_build_industry_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN), NWidget(WWT_CAPTION, COLOUR_DARK_GREEN), SetStringTip(STR_FUND_INDUSTRY_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), @@ -1204,7 +1204,7 @@ static void UpdateIndustryProduction(Industry *i) } /** Widget definition of the view industry gui */ -static constexpr NWidgetPart _nested_industry_view_widgets[] = { +static constexpr std::initializer_list _nested_industry_view_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_CREAM), NWidget(WWT_CAPTION, COLOUR_CREAM, WID_IV_CAPTION), @@ -1242,7 +1242,7 @@ void ShowIndustryViewWindow(IndustryID industry) } /** Widget definition of the industry directory gui */ -static constexpr NWidgetPart _nested_industry_directory_widgets[] = { +static constexpr std::initializer_list _nested_industry_directory_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_BROWN), NWidget(WWT_CAPTION, COLOUR_BROWN, WID_ID_CAPTION), @@ -1931,7 +1931,7 @@ void ShowIndustryDirectory() } /** Widgets of the industry cargoes window. */ -static constexpr NWidgetPart _nested_industry_cargoes_widgets[] = { +static constexpr std::initializer_list _nested_industry_cargoes_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_BROWN), NWidget(WWT_CAPTION, COLOUR_BROWN, WID_IC_CAPTION), diff --git a/src/industry_map.h b/src/industry_map.h index 92957fa9f22ef..1c8acbadbc666 100644 --- a/src/industry_map.h +++ b/src/industry_map.h @@ -285,7 +285,9 @@ inline void MakeIndustry(Tile t, IndustryID index, IndustryGfx gfx, uint8_t rand SetIndustryGfx(t, gfx); // m5, part of m6 SetIndustryRandomTriggers(t, {}); // rest of m6 SetWaterClass(t, wc); + SB(t.m6(), 6, 2, 0); t.m7() = 0; + t.m8() = 0; } #endif /* INDUSTRY_MAP_H */ diff --git a/src/ini_load.cpp b/src/ini_load.cpp index 7702eed8ce684..f134f6502e3a6 100644 --- a/src/ini_load.cpp +++ b/src/ini_load.cpp @@ -173,8 +173,7 @@ IniGroup &IniLoadFile::CreateGroup(std::string_view name) */ void IniLoadFile::RemoveGroup(std::string_view name) { - size_t len = name.length(); - this->groups.remove_if([&name, &len](const IniGroup &group) { return group.name.compare(0, len, name) == 0; }); + this->groups.remove_if([&name](const IniGroup &group) { return group.name.starts_with(name); }); } /** diff --git a/src/intro_gui.cpp b/src/intro_gui.cpp index 642b6f979280d..2d84c1ec6c5a6 100644 --- a/src/intro_gui.cpp +++ b/src/intro_gui.cpp @@ -343,7 +343,7 @@ struct SelectGameWindow : public Window { } }; -static constexpr NWidgetPart _nested_select_game_widgets[] = { +static constexpr std::initializer_list _nested_select_game_widgets = { NWidget(WWT_CAPTION, COLOUR_BROWN), SetStringTip(STR_INTRO_CAPTION), NWidget(WWT_PANEL, COLOUR_BROWN), NWidget(NWID_VERTICAL), SetPIP(0, WidgetDimensions::unscaled.vsep_wide, 0), SetPadding(WidgetDimensions::unscaled.sparse), diff --git a/src/landscape.cpp b/src/landscape.cpp index 61aa649874693..983c3e4f561d3 100644 --- a/src/landscape.cpp +++ b/src/landscape.cpp @@ -27,7 +27,6 @@ #include "effectvehicle_func.h" #include "landscape_type.h" #include "animated_tile_func.h" -#include "core/flatset_type.hpp" #include "core/random_func.hpp" #include "object_base.h" #include "company_func.h" @@ -43,6 +42,8 @@ #include "table/strings.h" #include "table/sprites.h" +#include + #include "safeguards.h" extern const TileTypeProcs @@ -637,6 +638,36 @@ void ClearSnowLine() _snow_line = nullptr; } +/** + * Check if all tiles on the map edge should be considered water borders. + * @return true If the edge of the map is flat and height 0, allowing for infinite water borders. + */ +bool IsMapSurroundedByWater() +{ + auto check_tile = [](uint x, uint y) -> bool { + auto [slope, h] = GetTilePixelSlopeOutsideMap(x, y); + return ((slope == SLOPE_FLAT) && (h == 0)); + }; + + /* Check the map corners. */ + if (!check_tile(0, 0)) return false; + if (!check_tile(0, Map::SizeY())) return false; + if (!check_tile(Map::SizeX(), 0)) return false; + if (!check_tile(Map::SizeX(), Map::SizeY())) return false; + + /* Check the map edges.*/ + for (uint x = 0; x <= Map::SizeX(); x++) { + if (!check_tile(x, 0)) return false; + if (!check_tile(x, Map::SizeY())) return false; + } + for (uint y = 1; y < Map::SizeY(); y++) { + if (!check_tile(0, y)) return false; + if (!check_tile(Map::SizeX(), y)) return false; + } + + return true; +} + /** * Clear a piece of landscape * @param flags of operation to conduct @@ -1210,28 +1241,29 @@ bool RiverFlowsDown(TileIndex begin, TileIndex end) */ static std::tuple FlowRiver(TileIndex spring, TileIndex begin, uint min_river_length) { - uint height_begin = TileHeight(begin); - if (IsWaterTile(begin)) { return { DistanceManhattan(spring, begin) > min_river_length, GetTileZ(begin) == 0 }; } - FlatSet marks; + int height_begin = TileHeight(begin); + + std::unordered_set marks; marks.insert(begin); - /* Breadth first search for the closest tile we can flow down to. */ - std::list queue; + std::vector queue; queue.push_back(begin); + /* Breadth first search for the closest tile we can flow down to. + * We keep the queue to find the Nth tile for lake guessing. The tiles + * in the queue are neatly ordered by insertion. + */ bool found = false; - uint count = 0; // Number of tiles considered; to be used for lake location guessing. TileIndex end; - do { - end = queue.front(); - queue.pop_front(); + for (size_t i = 0; i != queue.size(); i++) { + end = queue[i]; - uint height_end = TileHeight(end); - if (IsTileFlat(end) && (height_end < height_begin || (height_end == height_begin && IsWaterTile(end)))) { + int height_end; + if (IsTileFlat(end, &height_end) && (height_end < height_begin || (height_end == height_begin && IsWaterTile(end)))) { found = true; break; } @@ -1240,31 +1272,29 @@ static std::tuple FlowRiver(TileIndex spring, TileIndex begin, uint TileIndex t = end + TileOffsByDiagDir(d); if (IsValidTile(t) && !marks.contains(t) && RiverFlowsDown(end, t)) { marks.insert(t); - count++; queue.push_back(t); } } - } while (!queue.empty()); + } bool main_river = false; if (found) { /* Flow further down hill. */ std::tie(found, main_river) = FlowRiver(spring, end, min_river_length); - } else if (count > 32) { + } else if (queue.size() > 32) { /* Maybe we can make a lake. Find the Nth of the considered tiles. */ - auto cit = marks.cbegin(); - std::advance(cit, RandomRange(count - 1)); - TileIndex lake_centre = *cit; + TileIndex lake_centre = queue[RandomRange(static_cast(queue.size()))]; + int height_lake; if (IsValidTile(lake_centre) && - /* A river, or lake, can only be built on flat slopes. */ - IsTileFlat(lake_centre) && - /* We want the lake to be built at the height of the river. */ - TileHeight(begin) == TileHeight(lake_centre) && /* We don't want the lake at the entry of the valley. */ lake_centre != begin && /* We don't want lakes in the desert. */ (_settings_game.game_creation.landscape != LandscapeType::Tropic || GetTropicZone(lake_centre) != TROPICZONE_DESERT) && + /* A river, or lake, can only be built on flat slopes. */ + IsTileFlat(lake_centre, &height_lake) && + /* We want the lake to be built at the height of the river. */ + height_lake == height_begin && /* We only want a lake if the river is long enough. */ DistanceManhattan(spring, lake_centre) > min_river_length) { end = lake_centre; @@ -1274,7 +1304,7 @@ static std::tuple FlowRiver(TileIndex spring, TileIndex begin, uint /* Run the loop twice, so artefacts from going circular in one direction get (mostly) hidden. */ for (uint loops = 0; loops < 2; ++loops) { for (auto tile : SpiralTileSequence(lake_centre, diameter)) { - MakeLake(tile, height_begin); + MakeLake(tile, height_lake); } } @@ -1282,7 +1312,6 @@ static std::tuple FlowRiver(TileIndex spring, TileIndex begin, uint } } - marks.clear(); if (found) YapfBuildRiver(begin, end, spring, main_river); return { found, main_river }; } diff --git a/src/landscape.h b/src/landscape.h index db2a9781e47b1..3f33789694010 100644 --- a/src/landscape.h +++ b/src/landscape.h @@ -33,6 +33,8 @@ uint8_t HighestSnowLine(); uint8_t LowestSnowLine(); void ClearSnowLine(); +bool IsMapSurroundedByWater(); + int GetSlopeZInCorner(Slope tileh, Corner corner); std::tuple GetFoundationSlope(TileIndex tile); diff --git a/src/landscape_cmd.h b/src/landscape_cmd.h index 2062eac61950f..1ae5b7b1b2352 100644 --- a/src/landscape_cmd.h +++ b/src/landscape_cmd.h @@ -15,7 +15,7 @@ CommandCost CmdLandscapeClear(DoCommandFlags flags, TileIndex tile); std::tuple CmdClearArea(DoCommandFlags flags, TileIndex tile, TileIndex start_tile, bool diagonal); -DEF_CMD_TRAIT(CMD_LANDSCAPE_CLEAR, CmdLandscapeClear, CommandFlag::Deity, CMDT_LANDSCAPE_CONSTRUCTION) -DEF_CMD_TRAIT(CMD_CLEAR_AREA, CmdClearArea, CommandFlag::NoTest, CMDT_LANDSCAPE_CONSTRUCTION) // destroying multi-tile houses makes town rating differ between test and execution +DEF_CMD_TRAIT(CMD_LANDSCAPE_CLEAR, CmdLandscapeClear, CommandFlag::Deity, CommandType::LandscapeConstruction) +DEF_CMD_TRAIT(CMD_CLEAR_AREA, CmdClearArea, CommandFlag::NoTest, CommandType::LandscapeConstruction) // destroying multi-tile houses makes town rating differ between test and execution #endif /* LANDSCAPE_CMD_H */ diff --git a/src/lang/afrikaans.txt b/src/lang/afrikaans.txt index 0071396cda7c8..fe8ec701556e3 100644 --- a/src/lang/afrikaans.txt +++ b/src/lang/afrikaans.txt @@ -1839,7 +1839,7 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_SI :SI (kN) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT :Hoogte eenheid: {STRING} STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_HELPTEXT :Wanneer 'n hoogte word in die gebruikerskoppelvlak, wys dit in die geselekteerde eenhede -###length 3 +###length 4 STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_IMPERIAL :Empiries (vt) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_METRIC :Metries (m) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_SI :SI (m) @@ -2846,6 +2846,8 @@ STR_MAPGEN_SOUTHWEST :{BLACK}Suidwes STR_MAPGEN_BORDER_FREEFORM :{BLACK}Vryeform STR_MAPGEN_BORDER_WATER :{BLACK}Water STR_MAPGEN_BORDER_RANDOM :{BLACK}Lukraak + +###length 3 STR_MAPGEN_BORDER_RANDOMIZE :{BLACK}Lukraak STR_MAPGEN_BORDER_MANUAL :{BLACK}Handmatig @@ -3073,7 +3075,6 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}Tik 'n n # Town directory window STR_TOWN_DIRECTORY_NONE :{ORANGE}- Geen - STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) -STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (Stad){BLACK} ({COMMA}) STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}Dorpname - klik op 'n naam om skerm daarna te skuif. Ctrl+klik om 'n nuwe venster vir die dorp oop te maak STR_TOWN_POPULATION :{BLACK}Wêreldbevolking: {COMMA} diff --git a/src/lang/arabic_egypt.txt b/src/lang/arabic_egypt.txt index 446c7df5490fd..6323e068fc7f1 100644 --- a/src/lang/arabic_egypt.txt +++ b/src/lang/arabic_egypt.txt @@ -1716,7 +1716,7 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE ::وحدات ج STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_IMPERIAL :إمبراطوري (lbf) STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_METRIC :متري (كغ - قوة) -###length 3 +###length 4 STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_IMPERIAL :إمبراطوري (قدم) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_METRIC :متري (م) @@ -2769,6 +2769,8 @@ STR_MAPGEN_SOUTHWEST :{BLACK} الج STR_MAPGEN_BORDER_FREEFORM :{BLACK} حر STR_MAPGEN_BORDER_WATER :{BLACK} ماء STR_MAPGEN_BORDER_RANDOM :{BLACK} عشوائي + +###length 3 STR_MAPGEN_BORDER_RANDOMIZE :{BLACK} عشوائيا STR_MAPGEN_BORDER_MANUAL :{BLACK} يدوي @@ -2990,7 +2992,6 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}ادخل # Town directory window STR_TOWN_DIRECTORY_NONE :{ORANGE}-بدون- STR_TOWN_DIRECTORY_TOWN :{ORANGE}{RLE}{TOWN}{BLACK} {RLM}({COMMA}) -STR_TOWN_DIRECTORY_CITY :{ORANGE}{RLE}{TOWN}{YELLOW} (مدينة){BLACK} {RLM}({COMMA}) STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}اسم المدينة - اضغط على الاسم لتوسيط الشاشة عليها. اضغط + كنترول لفتح شاشة عرض جديدة للضاحية. STR_TOWN_POPULATION :{BLACK}سكان العالم: {COMMA} diff --git a/src/lang/basque.txt b/src/lang/basque.txt index 9ab90acd5461d..4267f20101f41 100644 --- a/src/lang/basque.txt +++ b/src/lang/basque.txt @@ -1731,7 +1731,7 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_METRIC :Metrikoa (kgf) STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_SI :SI (kN) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT :Garaiera unitateak: {STRING} -###length 3 +###length 4 STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_IMPERIAL :Inperiala (oin) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_METRIC :Metrikoa (m) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_SI :SI (m) @@ -2687,6 +2687,8 @@ STR_MAPGEN_SOUTHWEST :{BLACK}Hegomend STR_MAPGEN_BORDER_FREEFORM :{BLACK}Modu askea STR_MAPGEN_BORDER_WATER :{BLACK}Ura STR_MAPGEN_BORDER_RANDOM :{BLACK}Ausazkoa + +###length 3 STR_MAPGEN_BORDER_RANDOMIZE :{BLACK}Ausazkoa STR_MAPGEN_BORDER_MANUAL :{BLACK}Eskuz egin diff --git a/src/lang/belarusian.txt b/src/lang/belarusian.txt index 924bfd9c6faa5..22cd4a442dd28 100644 --- a/src/lang/belarusian.txt +++ b/src/lang/belarusian.txt @@ -2414,7 +2414,7 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_SI :СІ (кН) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT :Сыстэма адзінак для вышыні: {STRING} STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_HELPTEXT :Паказваць значэньні вышыні ў абранай сыстэме адзінак -###length 3 +###length 4 STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_IMPERIAL :ангельская (фут) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_METRIC :мэтрычная (м) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_SI :СІ (м) @@ -3631,6 +3631,8 @@ STR_MAPGEN_SOUTHWEST :{BLACK}Паўд STR_MAPGEN_BORDER_FREEFORM :{BLACK}Зямля STR_MAPGEN_BORDER_WATER :{BLACK}Вада STR_MAPGEN_BORDER_RANDOM :{BLACK}Выпадковы + +###length 3 STR_MAPGEN_BORDER_RANDOMIZE :{BLACK}Выпадковыя STR_MAPGEN_BORDER_MANUAL :{BLACK}Уручную @@ -3878,7 +3880,6 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}Увяд # Town directory window STR_TOWN_DIRECTORY_NONE :{ORANGE}- Няма - STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) -STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (Мегаполіс){BLACK} ({COMMA}) STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}Сьпіс гарадоў: пстрычка па назьве паказвае горад у асноўным вакне. Ctrl+пстрычка — у дадатковым вакне. STR_TOWN_POPULATION :{BLACK}Насельніцтва: {COMMA} diff --git a/src/lang/brazilian_portuguese.txt b/src/lang/brazilian_portuguese.txt index bb169f5799a4d..a187eae9394e5 100644 --- a/src/lang/brazilian_portuguese.txt +++ b/src/lang/brazilian_portuguese.txt @@ -255,6 +255,7 @@ STR_UNITS_FORCE_SI :{DECIMAL}{NBSP} STR_UNITS_HEIGHT_IMPERIAL :{DECIMAL}{NBSP}ft STR_UNITS_HEIGHT_METRIC :{DECIMAL}{NBSP}m STR_UNITS_HEIGHT_SI :{DECIMAL}{NBSP}m +STR_UNITS_HEIGHT_GAMEUNITS :{DECIMAL}{NBSP}níve{P l is} # Time units used in string control characters STR_UNITS_DAYS :{COMMA}{NBSP}dia{P "" s} @@ -2159,10 +2160,11 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_SI :SI (kN) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT :Unidades de altura: {STRING} STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_HELPTEXT :Sempre que uma altura for exibida na interface do usuário, mostrar nessas unidades -###length 3 +###length 4 STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_IMPERIAL :Imperial (ft) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_METRIC :Métrico (m) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_SI :SI (m) +STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_GAMEUNITS :Unidades do jogo (níveis) STR_CONFIG_SETTING_LOCALISATION :Localização STR_CONFIG_SETTING_GRAPHICS :Gráficos @@ -3426,11 +3428,18 @@ STR_MAPGEN_NORTHWEST :{BLACK}Noroeste STR_MAPGEN_NORTHEAST :{BLACK}Nordeste STR_MAPGEN_SOUTHEAST :{BLACK}Sudeste STR_MAPGEN_SOUTHWEST :{BLACK}Sudoeste +STR_MAPGEN_NORTHWEST_TOOLTIP :Alternar entre água ou borda livre na borda noroeste do mapa +STR_MAPGEN_NORTHEAST_TOOLTIP :Alternar entre água ou borda livre na borda nordeste do mapa +STR_MAPGEN_SOUTHEAST_TOOLTIP :Alternar entre água ou borda livre na borda sudeste do mapa +STR_MAPGEN_SOUTHWEST_TOOLTIP :Alternar entre água ou borda livre na borda sudoeste do mapa STR_MAPGEN_BORDER_FREEFORM :{BLACK}Forma livre STR_MAPGEN_BORDER_WATER :{BLACK}Água STR_MAPGEN_BORDER_RANDOM :{BLACK}Aleatório -STR_MAPGEN_BORDER_RANDOMIZE :{BLACK}Aleatório -STR_MAPGEN_BORDER_MANUAL :{BLACK}Manual + +###length 3 +STR_MAPGEN_BORDER_RANDOMIZE :Aleatório +STR_MAPGEN_BORDER_MANUAL :Manual +STR_MAPGEN_BORDER_INFINITE_WATER :Água Infinita STR_MAPGEN_HEIGHTMAP_ROTATION :{BLACK}Rotação do mapa de altitudes: STR_MAPGEN_HEIGHTMAP_NAME :{BLACK}Nome do mapa de altitudes: @@ -3469,7 +3478,8 @@ STR_GENERATION_LANDSCAPE_GENERATION :{BLACK}Geraçã STR_GENERATION_RIVER_GENERATION :{BLACK}Geração de rios STR_GENERATION_CLEARING_TILES :{BLACK}Geração de áreas irregulares e rochosas STR_GENERATION_TOWN_GENERATION :{BLACK}Geração de localidades -STR_GENERATION_INDUSTRY_GENERATION :{BLACK}Geração de indústrias +STR_GENERATION_LAND_INDUSTRY_GENERATION :{BLACK}Geração de indústrias terrestres +STR_GENERATION_WATER_INDUSTRY_GENERATION :{BLACK}Geração de indústrias fluviais STR_GENERATION_OBJECT_GENERATION :{BLACK}Geração de objetos STR_GENERATION_TREE_GENERATION :{BLACK}Geração de árvores STR_GENERATION_SETTINGUP_GAME :{BLACK}Configurando o jogo @@ -3689,7 +3699,7 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}Introduz STR_TOWN_DIRECTORY_CAPTION :{WHITE}Localidades ({COMMA} of {COMMA}) STR_TOWN_DIRECTORY_NONE :{ORANGE}- Nenhum - STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) -STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (Cidade){BLACK} ({COMMA}) +STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{BLACK} ({COMMA}) {YELLOW}{CITY_ICON} STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}Nomes das localidades - clique em um nome para centralizar a visualização principal na cidade. Ctrl+Clique para abrir uma nova visualização na localização da localidade STR_TOWN_POPULATION :{BLACK}População mundial: {COMMA} @@ -5267,13 +5277,13 @@ STR_ERROR_START_AND_END_MUST_BE_IN :{WHITE}Início STR_ERROR_ENDS_OF_BRIDGE_MUST_BOTH :{WHITE}... os extremos da ponte devem estar sobre a terra STR_ERROR_BRIDGE_TOO_LONG :{WHITE}... ponte muito longa STR_ERROR_BRIDGE_THROUGH_MAP_BORDER :{WHITE}A ponte terminaria fora do mapa -STR_ERROR_BRIDGE_TOO_LOW_FOR_STATION :{WHITE}Ponte é muito baixa para uma estação -STR_ERROR_BRIDGE_TOO_LOW_FOR_ROADSTOP :{WHITE}Ponte é muito baixa para uma parada rodoviária -STR_ERROR_BRIDGE_TOO_LOW_FOR_DOCK :{WHITE}A ponte é muito baixa para a doca -STR_ERROR_BRIDGE_TOO_LOW_FOR_BUOY :{WHITE}Ponte é muito baixa para uma boia -STR_ERROR_BRIDGE_TOO_LOW_FOR_RAIL_WAYPOINT :{WHITE}Ponte é muito baixa para um ponto de controle ferroviário -STR_ERROR_BRIDGE_TOO_LOW_FOR_ROAD_WAYPOINT :{WHITE}Ponte é muito baixa para um ponto de controle rodoviário -STR_ERROR_BRIDGE_TOO_LOW_FOR_LOCK :{WHITE}A ponte é muito baixa para eclusa +STR_ERROR_BRIDGE_TOO_LOW_FOR_STATION :{WHITE}A ponte está {HEIGHT} abaixo do necessário para a estação +STR_ERROR_BRIDGE_TOO_LOW_FOR_ROADSTOP :{WHITE}A ponte está {HEIGHT} abaixo do necessário para a parada rodoviária +STR_ERROR_BRIDGE_TOO_LOW_FOR_DOCK :{WHITE}A ponte está {HEIGHT} abaixo do necessário para a doca +STR_ERROR_BRIDGE_TOO_LOW_FOR_BUOY :{WHITE}A ponte está {HEIGHT} abaixo do necessário para a boia +STR_ERROR_BRIDGE_TOO_LOW_FOR_RAIL_WAYPOINT :{WHITE}A ponte está {HEIGHT} abaixo do necessário para o ponto de controle ferroviário +STR_ERROR_BRIDGE_TOO_LOW_FOR_ROAD_WAYPOINT :{WHITE}A ponte está {HEIGHT} abaixo do necessário para o ponto de controle rodoviário +STR_ERROR_BRIDGE_TOO_LOW_FOR_LOCK :{WHITE}A ponte está {HEIGHT} abaixo do necessário para a eclusa # Tunnel related errors STR_ERROR_CAN_T_BUILD_TUNNEL_HERE :{WHITE}Não é possível construir túnel aqui... @@ -5911,7 +5921,7 @@ STR_WAYPOINT_NAME :{WAYPOINT} STR_CURRENCY_SHORT_KILO :{NBSP}k STR_CURRENCY_SHORT_MEGA :{NBSP}M -STR_CURRENCY_SHORT_GIGA :{NBSP}G +STR_CURRENCY_SHORT_GIGA :{NBSP}B STR_CURRENCY_SHORT_TERA :{NBSP}T STR_JUST_CARGO :{CARGO_LONG} diff --git a/src/lang/bulgarian.txt b/src/lang/bulgarian.txt index 4fe06333387fa..1975b3a0faa7a 100644 --- a/src/lang/bulgarian.txt +++ b/src/lang/bulgarian.txt @@ -2125,7 +2125,7 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_SI :SI (kN) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT :Мерни единици за височина: {STRING} STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_HELPTEXT :Показваните височини ще бъдат изписвани в избраните мерни единици -###length 3 +###length 4 STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_IMPERIAL :Имперски (фут) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_METRIC :Метрични (м) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_SI :SI (м) @@ -3358,6 +3358,8 @@ STR_MAPGEN_SOUTHWEST :{BLACK}Югоз STR_MAPGEN_BORDER_FREEFORM :{BLACK}Произволни STR_MAPGEN_BORDER_WATER :{BLACK}Вода STR_MAPGEN_BORDER_RANDOM :{BLACK}Случаен + +###length 3 STR_MAPGEN_BORDER_RANDOMIZE :{BLACK}Случаен STR_MAPGEN_BORDER_MANUAL :{BLACK}Ръчно нагалсени @@ -3398,7 +3400,6 @@ STR_GENERATION_LANDSCAPE_GENERATION :{BLACK}Гене STR_GENERATION_RIVER_GENERATION :{BLACK}Генериране на реки STR_GENERATION_CLEARING_TILES :{BLACK}Генериране на твърда и скална повърност STR_GENERATION_TOWN_GENERATION :{BLACK}Генерация на град -STR_GENERATION_INDUSTRY_GENERATION :{BLACK}Генерация на индустрията STR_GENERATION_OBJECT_GENERATION :{BLACK}Генериране на обекти STR_GENERATION_TREE_GENERATION :{BLACK}Генериране на дървета STR_GENERATION_SETTINGUP_GAME :{BLACK}Настройване на играта @@ -3618,7 +3619,6 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}Въве STR_TOWN_DIRECTORY_CAPTION :{WHITE}Градове ({COMMA} от {COMMA}) STR_TOWN_DIRECTORY_NONE :{ORANGE}- Отсъства - STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) -STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (метрополис){BLACK} ({COMMA}) STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}Имена на градовете - натиснете на името, за да центрирате камерата върху този град. Ctrl+Click отваря прозорец с нов изглед към града STR_TOWN_POPULATION :{BLACK}Обща популация на картата: {COMMA} diff --git a/src/lang/catalan.txt b/src/lang/catalan.txt index c715650802757..bfcbcc843e72b 100644 --- a/src/lang/catalan.txt +++ b/src/lang/catalan.txt @@ -255,6 +255,7 @@ STR_UNITS_FORCE_SI :{G=Masculin}{DE STR_UNITS_HEIGHT_IMPERIAL :{DECIMAL}{NBSP}ft STR_UNITS_HEIGHT_METRIC :{DECIMAL}{NBSP}m STR_UNITS_HEIGHT_SI :{G=Masculin}{DECIMAL}{NBSP}m +STR_UNITS_HEIGHT_GAMEUNITS :{DECIMAL}{NBSP}nivell{P "" s} # Time units used in string control characters STR_UNITS_DAYS :{COMMA}{NBSP}di{P a es} @@ -2159,10 +2160,11 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_SI :SI (kN) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT :Unitats de longitud: {STRING} STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_HELPTEXT :Quan es mostren longituds a la interfície d'usuari, presenta-les en les unitats seleccionades -###length 3 +###length 4 STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_IMPERIAL :Imperial (peu) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_METRIC :Mètric (m) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_SI :SI (m) +STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_GAMEUNITS :Unitats de la partida (nivells) STR_CONFIG_SETTING_LOCALISATION :Localització STR_CONFIG_SETTING_GRAPHICS :Gràfics @@ -3349,6 +3351,8 @@ STR_SAVELOAD_DETAIL_GRFSTATUS :{SILVER}NewGRF: STR_SAVELOAD_FILTER_TITLE :{BLACK}Filtre: STR_SAVELOAD_OVERWRITE_TITLE :{WHITE}Sobreescriu fitxer STR_SAVELOAD_OVERWRITE_WARNING :{YELLOW}Esteu segur que voleu sobreescriure el fitxer? +STR_SAVELOAD_DELETE_TITLE :{WHITE}Esborra el fitxer +STR_SAVELOAD_DELETE_WARNING :{YELLOW}Esteu segur que voleu esborrar aquest fitxer? STR_SAVELOAD_DIRECTORY :{STRING} (carpeta) STR_SAVELOAD_PARENT_DIRECTORY :{STRING} (carpeta superior) @@ -3427,8 +3431,11 @@ STR_MAPGEN_SOUTHWEST :{BLACK}Sud-oest STR_MAPGEN_BORDER_FREEFORM :{BLACK}Forma lliure STR_MAPGEN_BORDER_WATER :{BLACK}Aigua STR_MAPGEN_BORDER_RANDOM :{BLACK}Aleatori -STR_MAPGEN_BORDER_RANDOMIZE :{BLACK}Aleatori -STR_MAPGEN_BORDER_MANUAL :{BLACK}Manual + +###length 3 +STR_MAPGEN_BORDER_RANDOMIZE :Aleatori +STR_MAPGEN_BORDER_MANUAL :Manual +STR_MAPGEN_BORDER_INFINITE_WATER :Aigua infinita STR_MAPGEN_HEIGHTMAP_ROTATION :{BLACK}Rotació del mapa d'alçades: STR_MAPGEN_HEIGHTMAP_NAME :{BLACK}Nom del mapa d'alçades: @@ -3467,7 +3474,8 @@ STR_GENERATION_LANDSCAPE_GENERATION :{BLACK}Generaci STR_GENERATION_RIVER_GENERATION :{BLACK}Generació de rius STR_GENERATION_CLEARING_TILES :{BLACK}Generació d'una àrea escarpada i rocosa STR_GENERATION_TOWN_GENERATION :{BLACK}Generació de poblacions -STR_GENERATION_INDUSTRY_GENERATION :{BLACK}Generació d'indústries +STR_GENERATION_LAND_INDUSTRY_GENERATION :{BLACK}Generació d'indústries terrestres +STR_GENERATION_WATER_INDUSTRY_GENERATION :{BLACK}Generació d'indústries a l'aigua STR_GENERATION_OBJECT_GENERATION :{BLACK}Generació inamovible STR_GENERATION_TREE_GENERATION :{BLACK}Generació d'arbres STR_GENERATION_SETTINGUP_GAME :{BLACK}Configurant la partida @@ -3687,7 +3695,7 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}Posa un STR_TOWN_DIRECTORY_CAPTION :{WHITE}Poblacions ({COMMA} de {COMMA}) STR_TOWN_DIRECTORY_NONE :{ORANGE}- Cap - STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) -STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{BLACK} ({COMMA} -{YELLOW} ciutat{BLACK}) +STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{BLACK} ({COMMA}) {YELLOW}{CITY_ICON} STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}Noms de les poblacions - feu clic al nom d'una població per a centrar-hi la vista principal. Amb Ctrl+clic, s'obre una vista nova centrada on hi ha la població. STR_TOWN_POPULATION :{BLACK}Població mundial: {COMMA} @@ -4126,7 +4134,7 @@ STR_GROUP_LIVERY_TOOLTIP :{BLACK}Canvia l STR_GROUP_REPLACE_PROTECTION_TOOLTIP :{BLACK}Clica per protegir aquest grup de l'autosubstitució global. Ctrl + clic també protegeix els subgrups. STR_QUERY_GROUP_DELETE_CAPTION :{WHITE}Esborrar grup -STR_GROUP_DELETE_QUERY_TEXT :{WHITE}Estàs segur que vols esborrar aquest grup i tots els seus subgrups? +STR_GROUP_DELETE_QUERY_TEXT :{WHITE}Esteu segur que voleu esborrar aquest grup i tots els seus subgrups? STR_GROUP_ADD_SHARED_VEHICLE :Afegeix vehicles compartits STR_GROUP_REMOVE_ALL_VEHICLES :Treu tots els vehicles @@ -4184,6 +4192,7 @@ STR_PURCHASE_INFO_ALL_BUT :Qualsevol excep STR_PURCHASE_INFO_MAX_TE :{BLACK}Esforç de tracció màxim: {GOLD}{FORCE} STR_PURCHASE_INFO_AIRCRAFT_RANGE :{BLACK}Abast: {GOLD}{COMMA} cel·les STR_PURCHASE_INFO_AIRCRAFT_TYPE :{BLACK}Tipus d'aeronau: {GOLD}{STRING} +STR_PURCHASE_INFO_RAILTYPES :{BLACK}Tipus de rail: {GOLD}{STRING} ###length 3 STR_CARGO_TYPE_FILTER_ALL :Tots els tipus de càrrega @@ -4367,6 +4376,7 @@ STR_ENGINE_PREVIEW_RUNCOST_YEAR :Cost d'utilitza STR_ENGINE_PREVIEW_RUNCOST_PERIOD :Cost d'utilització: {CURRENCY_LONG}/període STR_ENGINE_PREVIEW_CAPACITY :Capacitat: {CARGO_LONG} STR_ENGINE_PREVIEW_CAPACITY_2 :Capacitat: {CARGO_LONG}, {CARGO_LONG} +STR_ENGINE_PREVIEW_RAILTYPES :Tipus de rail: {STRING} # Autoreplace window STR_REPLACE_VEHICLES_WHITE :{WHITE}Substitueix {STRING} - {STRING} @@ -5263,13 +5273,13 @@ STR_ERROR_START_AND_END_MUST_BE_IN :{WHITE}Inici i STR_ERROR_ENDS_OF_BRIDGE_MUST_BOTH :{WHITE}... els extrems del pont han d'estar tots dos a terra STR_ERROR_BRIDGE_TOO_LONG :{WHITE}... el pont és massa llarg STR_ERROR_BRIDGE_THROUGH_MAP_BORDER :{WHITE}El pont acabaria fora del mapa -STR_ERROR_BRIDGE_TOO_LOW_FOR_STATION :{WHITE}El pont està massa baix per a l'estació. -STR_ERROR_BRIDGE_TOO_LOW_FOR_ROADSTOP :{WHITE}El pont està massa baix per a la parada. -STR_ERROR_BRIDGE_TOO_LOW_FOR_DOCK :{WHITE}El pont és massa baix per al port. -STR_ERROR_BRIDGE_TOO_LOW_FOR_BUOY :{WHITE}El pont està massa baix per a la boia. -STR_ERROR_BRIDGE_TOO_LOW_FOR_RAIL_WAYPOINT :{WHITE}El pont està massa baix per al punt de pas. -STR_ERROR_BRIDGE_TOO_LOW_FOR_ROAD_WAYPOINT :{WHITE}El pont està massa baix per al punt de pas de carretera. -STR_ERROR_BRIDGE_TOO_LOW_FOR_LOCK :{WHITE}El pont és massa baix per a la resclosa. +STR_ERROR_BRIDGE_TOO_LOW_FOR_STATION :{WHITE}El pont és {HEIGHT} massa baix per a l'estació. +STR_ERROR_BRIDGE_TOO_LOW_FOR_ROADSTOP :{WHITE}El pont és {HEIGHT} massa baix per a la parada de carretera. +STR_ERROR_BRIDGE_TOO_LOW_FOR_DOCK :{WHITE}El pont és {HEIGHT} massa baix per al moll. +STR_ERROR_BRIDGE_TOO_LOW_FOR_BUOY :{WHITE}El pont és {HEIGHT} massa baix per a la boia. +STR_ERROR_BRIDGE_TOO_LOW_FOR_RAIL_WAYPOINT :{WHITE}El pont és {HEIGHT} massa baix per al punt de pas. +STR_ERROR_BRIDGE_TOO_LOW_FOR_ROAD_WAYPOINT :{WHITE}El pont és {HEIGHT} massa baix per al punt de pas de carretera. +STR_ERROR_BRIDGE_TOO_LOW_FOR_LOCK :{WHITE}El pont és {HEIGHT} massa baix per a la resclosa. # Tunnel related errors STR_ERROR_CAN_T_BUILD_TUNNEL_HERE :{WHITE}Aquí no es pot construir el túnel... diff --git a/src/lang/chuvash.txt b/src/lang/chuvash.txt index 5bad0832c439e..49bc9aeb81183 100644 --- a/src/lang/chuvash.txt +++ b/src/lang/chuvash.txt @@ -853,7 +853,7 @@ STR_CONFIG_SETTING_TOWN_GROWTH_VERY_FAST :Питӗ хӑв ###length 3 -###length 3 +###length 4 STR_CONFIG_SETTING_INTERFACE :Интерфейс STR_CONFIG_SETTING_INTERFACE_CONSTRUCTION :Лартӑм @@ -1222,6 +1222,8 @@ STR_MAPGEN_TOWN_NAME_CATALAN :Катталу # Strings for map borders at game generation +###length 3 + # SE Map generation diff --git a/src/lang/croatian.txt b/src/lang/croatian.txt index 1f60e8431619e..7bc156fb652e2 100644 --- a/src/lang/croatian.txt +++ b/src/lang/croatian.txt @@ -1958,7 +1958,7 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_SI :SI (kN) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT :Jedinice visine: {STRING} STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_HELPTEXT :Uvijek kada je visina prikazana u korisničkom sučelju, prikaži je u odabranim jedinicama -###length 3 +###length 4 STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_IMPERIAL :Imperijalni (ft) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_METRIC :Metrički (m) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_SI :SI (m) @@ -3012,6 +3012,8 @@ STR_MAPGEN_SOUTHWEST :{BLACK}Jugozapa STR_MAPGEN_BORDER_FREEFORM :{BLACK}Slobodni oblik STR_MAPGEN_BORDER_WATER :{BLACK}Voda STR_MAPGEN_BORDER_RANDOM :{BLACK}Nasumično + +###length 3 STR_MAPGEN_BORDER_RANDOMIZE :{BLACK}Nasumično STR_MAPGEN_BORDER_MANUAL :{BLACK}Ručno @@ -3247,7 +3249,6 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}Unesi im # Town directory window STR_TOWN_DIRECTORY_NONE :{ORANGE}- Ništa - STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) -STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (Grad){BLACK} ({COMMA}) STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}Imena gradova - klikni na ime kako bi centrirao pogled na grad. Ctrl+klik otvara novi prozor sa lokacijom grada STR_TOWN_POPULATION :{BLACK}Svjetsko stanovništvo: {COMMA} diff --git a/src/lang/czech.txt b/src/lang/czech.txt index 51022ea0298f7..fd987da743e1d 100644 --- a/src/lang/czech.txt +++ b/src/lang/czech.txt @@ -2211,7 +2211,7 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_SI :SI (kN) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT :Výškové jednotky: {STRING} STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_HELPTEXT :Kdykoliv se v uživatelském rozhraní zobrazí výška, bude ve zvolených jednotkách -###length 3 +###length 4 STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_IMPERIAL :Imperiální (ft) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_METRIC :Metrické (m) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_SI :SI (m) @@ -3466,6 +3466,8 @@ STR_MAPGEN_SOUTHWEST :{BLACK}Jihozáp STR_MAPGEN_BORDER_FREEFORM :{BLACK}terén STR_MAPGEN_BORDER_WATER :{BLACK}voda STR_MAPGEN_BORDER_RANDOM :{BLACK}náhodně + +###length 3 STR_MAPGEN_BORDER_RANDOMIZE :{BLACK}náhodně STR_MAPGEN_BORDER_MANUAL :{BLACK}vlastní @@ -3506,7 +3508,6 @@ STR_GENERATION_LANDSCAPE_GENERATION :{BLACK}Generov STR_GENERATION_RIVER_GENERATION :{BLACK}Generování řek STR_GENERATION_CLEARING_TILES :{BLACK}Tvorba členitého a kamenitého území STR_GENERATION_TOWN_GENERATION :{BLACK}Generování měst -STR_GENERATION_INDUSTRY_GENERATION :{BLACK}Generování průmyslu STR_GENERATION_OBJECT_GENERATION :{BLACK}Výstavba nepřesunutelných objektů STR_GENERATION_TREE_GENERATION :{BLACK}Výsadba stromů STR_GENERATION_SETTINGUP_GAME :{BLACK}Nastavování hry @@ -3721,7 +3722,6 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}Zadej n STR_TOWN_DIRECTORY_CAPTION :{WHITE}Města ({COMMA} z {COMMA}) STR_TOWN_DIRECTORY_NONE :{ORANGE}- Nic - STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) -STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (velkoměsto){BLACK} ({COMMA}) STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}Jména měst - pohled na město zaměříš kliknutím na jeho jméno. Při stisknutém Ctrl otevřeš nový pohled STR_TOWN_POPULATION :{BLACK}Populace světa: {COMMA} diff --git a/src/lang/danish.txt b/src/lang/danish.txt index d498678ef3afb..c870b469880de 100644 --- a/src/lang/danish.txt +++ b/src/lang/danish.txt @@ -2158,7 +2158,7 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_SI :SI (kN) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT :Højdeenheder: {STRING} STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_HELPTEXT :Når højde er vist i brugergrænsefladen, så vis dem i de valgte enheder -###length 3 +###length 4 STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_IMPERIAL :Imperisk (fod) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_METRIC :Metrisk (m) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_SI :SI (m) @@ -3428,8 +3428,11 @@ STR_MAPGEN_SOUTHWEST :{BLACK}Sydvest STR_MAPGEN_BORDER_FREEFORM :{BLACK}Fri udformning STR_MAPGEN_BORDER_WATER :{BLACK}Vand STR_MAPGEN_BORDER_RANDOM :{BLACK}Tilfældige -STR_MAPGEN_BORDER_RANDOMIZE :{BLACK}Tilfældige -STR_MAPGEN_BORDER_MANUAL :{BLACK}Manuel + +###length 3 +STR_MAPGEN_BORDER_RANDOMIZE :Tilfældig +STR_MAPGEN_BORDER_MANUAL :Manuel +STR_MAPGEN_BORDER_INFINITE_WATER :Uendeligt vand STR_MAPGEN_HEIGHTMAP_ROTATION :{BLACK}Højdekortets rotation: STR_MAPGEN_HEIGHTMAP_NAME :{BLACK}Højdekortets navn: @@ -3468,7 +3471,6 @@ STR_GENERATION_LANDSCAPE_GENERATION :{BLACK}Landskab STR_GENERATION_RIVER_GENERATION :{BLACK}Flod-generering STR_GENERATION_CLEARING_TILES :{BLACK}Generer råt og stenet område STR_GENERATION_TOWN_GENERATION :{BLACK}By generation -STR_GENERATION_INDUSTRY_GENERATION :{BLACK}Industri generation STR_GENERATION_OBJECT_GENERATION :{BLACK}Ikke-flytbar generering STR_GENERATION_TREE_GENERATION :{BLACK}Trægenerering STR_GENERATION_SETTINGUP_GAME :{BLACK}Klargør spil @@ -3688,7 +3690,7 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}Indtast STR_TOWN_DIRECTORY_CAPTION :{WHITE}Byer ({COMMA} of {COMMA}) STR_TOWN_DIRECTORY_NONE :{ORANGE}- Ingen - STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) -STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (storby){BLACK} ({COMMA}) +STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{BLACK} ({COMMA}) {YELLOW}{CITY_ICON} STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}Bynavne - klik på et navn for at centrere skærmen over byen. Ctrl+Klik åbner et nyt vindue ved byens lokalitet. STR_TOWN_POPULATION :{BLACK}Verdens befolkning: {COMMA} @@ -5266,13 +5268,6 @@ STR_ERROR_START_AND_END_MUST_BE_IN :{WHITE}Start- o STR_ERROR_ENDS_OF_BRIDGE_MUST_BOTH :{WHITE}... begge ender af en bro skal være på land STR_ERROR_BRIDGE_TOO_LONG :{WHITE}... broen er for lang STR_ERROR_BRIDGE_THROUGH_MAP_BORDER :{WHITE}Broen ville slutte udenfor kortet -STR_ERROR_BRIDGE_TOO_LOW_FOR_STATION :{WHITE}Broen er for lav til en station -STR_ERROR_BRIDGE_TOO_LOW_FOR_ROADSTOP :{WHITE}Broen er for lav til et vej stoppested -STR_ERROR_BRIDGE_TOO_LOW_FOR_DOCK :{WHITE}Broen er for lav til havnen -STR_ERROR_BRIDGE_TOO_LOW_FOR_BUOY :{WHITE}Broen er for lav til en bøje -STR_ERROR_BRIDGE_TOO_LOW_FOR_RAIL_WAYPOINT :{WHITE}Broen er for lav til et rutepunkt -STR_ERROR_BRIDGE_TOO_LOW_FOR_ROAD_WAYPOINT :{WHITE}Broen er for lav til et rutepunkt -STR_ERROR_BRIDGE_TOO_LOW_FOR_LOCK :{WHITE}Bro er for lav til at låse # Tunnel related errors STR_ERROR_CAN_T_BUILD_TUNNEL_HERE :{WHITE}Kan ikke bygge en tunnel her... diff --git a/src/lang/dutch.txt b/src/lang/dutch.txt index ecd71919e2692..ce787417e8521 100644 --- a/src/lang/dutch.txt +++ b/src/lang/dutch.txt @@ -254,6 +254,7 @@ STR_UNITS_FORCE_SI :{DECIMAL}{NBSP} STR_UNITS_HEIGHT_IMPERIAL :{DECIMAL}{NBSP}ft STR_UNITS_HEIGHT_METRIC :{DECIMAL}{NBSP}m STR_UNITS_HEIGHT_SI :{DECIMAL}{NBSP}m +STR_UNITS_HEIGHT_GAMEUNITS :{DECIMAL}{NBSP}niveau{P "" s} # Time units used in string control characters STR_UNITS_DAYS :{COMMA}{NBSP}dag{P "" en} @@ -2158,10 +2159,11 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_SI :SI (kN) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT :Hoogte-eenheden: {STRING} STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_HELPTEXT :Wanneer hoogtes worden weergegeven in het gebruikersscherm, gebruik dan de geselecteerde eenheden -###length 3 +###length 4 STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_IMPERIAL :Imperiaal (ft) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_METRIC :Metrisch (m) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_SI :SI (m) +STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_GAMEUNITS :Speleenheden (niveaus) STR_CONFIG_SETTING_LOCALISATION :Lokalisatie STR_CONFIG_SETTING_GRAPHICS :Grafische elementen @@ -3428,8 +3430,11 @@ STR_MAPGEN_SOUTHWEST :{BLACK}Zuidwest STR_MAPGEN_BORDER_FREEFORM :{BLACK}Vrije vorm STR_MAPGEN_BORDER_WATER :{BLACK}Water STR_MAPGEN_BORDER_RANDOM :{BLACK}Willekeurig -STR_MAPGEN_BORDER_RANDOMIZE :{BLACK}Willekeurig -STR_MAPGEN_BORDER_MANUAL :{BLACK}Handmatig + +###length 3 +STR_MAPGEN_BORDER_RANDOMIZE :Willekeurig +STR_MAPGEN_BORDER_MANUAL :Handmatig +STR_MAPGEN_BORDER_INFINITE_WATER :Onbeperkt water STR_MAPGEN_HEIGHTMAP_ROTATION :{BLACK}Rotatie van hoogtekaart: STR_MAPGEN_HEIGHTMAP_NAME :{BLACK}Naam van hoogtekaart: @@ -3468,7 +3473,8 @@ STR_GENERATION_LANDSCAPE_GENERATION :{BLACK}Landscha STR_GENERATION_RIVER_GENERATION :{BLACK}Rivierplaatsing STR_GENERATION_CLEARING_TILES :{BLACK}Ontwikkeling van ruig en rotsachtig gebied STR_GENERATION_TOWN_GENERATION :{BLACK}Steden genereren -STR_GENERATION_INDUSTRY_GENERATION :{BLACK}Industrieën genereren +STR_GENERATION_LAND_INDUSTRY_GENERATION :{BLACK}Landindustrieontwikkeling +STR_GENERATION_WATER_INDUSTRY_GENERATION :{BLACK}Waterindustrieontwikkeling STR_GENERATION_OBJECT_GENERATION :{BLACK}Ontwikkeling van onverplaatsbare objecten STR_GENERATION_TREE_GENERATION :{BLACK}Bosplaatsing STR_GENERATION_SETTINGUP_GAME :{BLACK}Spel wordt geconfigureerd @@ -3688,7 +3694,7 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}Geef een STR_TOWN_DIRECTORY_CAPTION :{WHITE}Steden ({COMMA} van {COMMA}) STR_TOWN_DIRECTORY_NONE :{ORANGE} Geen STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) -STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (groeistad){BLACK} ({COMMA}) +STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{BLACK} ({COMMA}) {YELLOW}{CITY_ICON} STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}Plaatsnamen - klik op naam om het scherm te centreren op de stad. Ctrl+klik opent een nieuw kijkvenster op de locatie van de stad STR_TOWN_POPULATION :{BLACK}Wereldbevolking: {COMMA} @@ -5266,13 +5272,13 @@ STR_ERROR_START_AND_END_MUST_BE_IN :{WHITE}Begin en STR_ERROR_ENDS_OF_BRIDGE_MUST_BOTH :{WHITE}... uiteinden van brug moeten beiden op land zijn STR_ERROR_BRIDGE_TOO_LONG :{WHITE}... brug te lang STR_ERROR_BRIDGE_THROUGH_MAP_BORDER :{WHITE}Brug zou eindigen buiten de kaart -STR_ERROR_BRIDGE_TOO_LOW_FOR_STATION :{WHITE}Brug te laag voor station -STR_ERROR_BRIDGE_TOO_LOW_FOR_ROADSTOP :{WHITE}Brug te laag voor halte -STR_ERROR_BRIDGE_TOO_LOW_FOR_DOCK :{WHITE}De brug is te laag voor haven -STR_ERROR_BRIDGE_TOO_LOW_FOR_BUOY :{WHITE}Brug te laag voor boei -STR_ERROR_BRIDGE_TOO_LOW_FOR_RAIL_WAYPOINT :{WHITE}Brug te laag voor spoorroutepunt -STR_ERROR_BRIDGE_TOO_LOW_FOR_ROAD_WAYPOINT :{WHITE}Brug te laag voor wegroutepunt -STR_ERROR_BRIDGE_TOO_LOW_FOR_LOCK :{WHITE}Brug te laag voor sluis +STR_ERROR_BRIDGE_TOO_LOW_FOR_STATION :{WHITE}Brug is {HEIGHT} te laag voor station +STR_ERROR_BRIDGE_TOO_LOW_FOR_ROADSTOP :{WHITE}Brug is {HEIGHT} te laag voor halte +STR_ERROR_BRIDGE_TOO_LOW_FOR_DOCK :{WHITE}Brug is {HEIGHT} te laag voor dok +STR_ERROR_BRIDGE_TOO_LOW_FOR_BUOY :{WHITE}Brug {HEIGHT} te laag voor boei +STR_ERROR_BRIDGE_TOO_LOW_FOR_RAIL_WAYPOINT :{WHITE}Brug {HEIGHT} te laag voor spoorroutepunt +STR_ERROR_BRIDGE_TOO_LOW_FOR_ROAD_WAYPOINT :{WHITE}Brug is {HEIGHT} te laag voor wegroutepunt +STR_ERROR_BRIDGE_TOO_LOW_FOR_LOCK :{WHITE}Brug is {HEIGHT} te laag voor sluis # Tunnel related errors STR_ERROR_CAN_T_BUILD_TUNNEL_HERE :{WHITE}Kan hier geen tunnel bouwen... diff --git a/src/lang/english.txt b/src/lang/english.txt index f33f4848fc120..fa25b4009e50d 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -254,6 +254,7 @@ STR_UNITS_FORCE_SI :{DECIMAL}{NBSP} STR_UNITS_HEIGHT_IMPERIAL :{DECIMAL}{NBSP}ft STR_UNITS_HEIGHT_METRIC :{DECIMAL}{NBSP}m STR_UNITS_HEIGHT_SI :{DECIMAL}{NBSP}m +STR_UNITS_HEIGHT_GAMEUNITS :{DECIMAL}{NBSP}level{P "" s} # Time units used in string control characters STR_UNITS_DAYS :{COMMA}{NBSP}day{P "" s} @@ -2158,10 +2159,11 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_SI :SI (kN) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT :Heights units: {STRING2} STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_HELPTEXT :Whenever a height is shown in the user interface, show it in the selected units -###length 3 +###length 4 STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_IMPERIAL :Imperial (ft) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_METRIC :Metric (m) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_SI :SI (m) +STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_GAMEUNITS :Game units (levels) STR_CONFIG_SETTING_LOCALISATION :Localisation STR_CONFIG_SETTING_GRAPHICS :Graphics @@ -3425,11 +3427,18 @@ STR_MAPGEN_NORTHWEST :{BLACK}Northwes STR_MAPGEN_NORTHEAST :{BLACK}Northeast STR_MAPGEN_SOUTHEAST :{BLACK}Southeast STR_MAPGEN_SOUTHWEST :{BLACK}Southwest +STR_MAPGEN_NORTHWEST_TOOLTIP :Toggle water or freeform edge on the northwest map edge +STR_MAPGEN_NORTHEAST_TOOLTIP :Toggle water or freeform edge on the northeast map edge +STR_MAPGEN_SOUTHEAST_TOOLTIP :Toggle water or freeform edge on the southeast map edge +STR_MAPGEN_SOUTHWEST_TOOLTIP :Toggle water or freeform edge on the southwest map edge STR_MAPGEN_BORDER_FREEFORM :{BLACK}Freeform STR_MAPGEN_BORDER_WATER :{BLACK}Water STR_MAPGEN_BORDER_RANDOM :{BLACK}Random -STR_MAPGEN_BORDER_RANDOMIZE :{BLACK}Random -STR_MAPGEN_BORDER_MANUAL :{BLACK}Manual + +###length 3 +STR_MAPGEN_BORDER_RANDOMIZE :Random +STR_MAPGEN_BORDER_MANUAL :Manual +STR_MAPGEN_BORDER_INFINITE_WATER :Infinite Water STR_MAPGEN_HEIGHTMAP_ROTATION :{BLACK}Heightmap rotation: STR_MAPGEN_HEIGHTMAP_NAME :{BLACK}Heightmap name: @@ -3468,7 +3477,8 @@ STR_GENERATION_LANDSCAPE_GENERATION :{BLACK}Landscap STR_GENERATION_RIVER_GENERATION :{BLACK}River generation STR_GENERATION_CLEARING_TILES :{BLACK}Rough and rocky area generation STR_GENERATION_TOWN_GENERATION :{BLACK}Town generation -STR_GENERATION_INDUSTRY_GENERATION :{BLACK}Industry generation +STR_GENERATION_LAND_INDUSTRY_GENERATION :{BLACK}Land industry generation +STR_GENERATION_WATER_INDUSTRY_GENERATION :{BLACK}Water industry generation STR_GENERATION_OBJECT_GENERATION :{BLACK}Object generation STR_GENERATION_TREE_GENERATION :{BLACK}Tree generation STR_GENERATION_SETTINGUP_GAME :{BLACK}Setting up game @@ -3688,7 +3698,7 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}Enter a STR_TOWN_DIRECTORY_CAPTION :{WHITE}Towns ({COMMA} of {COMMA}) STR_TOWN_DIRECTORY_NONE :{ORANGE}- None - STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) -STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (City){BLACK} ({COMMA}) +STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{BLACK} ({COMMA}) {YELLOW}{CITY_ICON} STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}Town names - click on name to centre main view on town. Ctrl+Click to open a new viewport on town location STR_TOWN_POPULATION :{BLACK}World population: {COMMA} @@ -5221,6 +5231,7 @@ STR_ERROR_CAN_T_REMOVE_SIGNALS_FROM :{WHITE}Can't re STR_ERROR_SIGNAL_CAN_T_CONVERT_SIGNALS_HERE :{WHITE}Can't convert signals here... STR_ERROR_THERE_IS_NO_RAILROAD_TRACK :{WHITE}... there is no railway track STR_ERROR_THERE_ARE_NO_SIGNALS :{WHITE}... there are no signals +STR_ERROR_TOO_MANY_RAILTYPES :{WHITE}... too many rail types in use STR_ERROR_CAN_T_CONVERT_RAIL :{WHITE}Can't convert rail type here... @@ -5237,6 +5248,8 @@ STR_ERROR_CAN_T_CONVERT_ROAD :{WHITE}Can't co STR_ERROR_CAN_T_CONVERT_TRAMWAY :{WHITE}Can't convert tram type here... STR_ERROR_NO_SUITABLE_ROAD :{WHITE}No suitable road STR_ERROR_NO_SUITABLE_TRAMWAY :{WHITE}No suitable tramway +STR_ERROR_TOO_MANY_ROADTYPES :{WHITE}... too many road types in use +STR_ERROR_TOO_MANY_TRAMTYPES :{WHITE}... too many tram types in use # Waterway construction errors STR_ERROR_CAN_T_BUILD_CANALS :{WHITE}Can't build canals here... @@ -5266,13 +5279,13 @@ STR_ERROR_START_AND_END_MUST_BE_IN :{WHITE}Start an STR_ERROR_ENDS_OF_BRIDGE_MUST_BOTH :{WHITE}... ends of bridge must both be on land STR_ERROR_BRIDGE_TOO_LONG :{WHITE}... bridge too long STR_ERROR_BRIDGE_THROUGH_MAP_BORDER :{WHITE}Bridge would end out of the map -STR_ERROR_BRIDGE_TOO_LOW_FOR_STATION :{WHITE}Bridge is too low for station -STR_ERROR_BRIDGE_TOO_LOW_FOR_ROADSTOP :{WHITE}Bridge is too low for road stop -STR_ERROR_BRIDGE_TOO_LOW_FOR_DOCK :{WHITE}Bridge is too low for dock -STR_ERROR_BRIDGE_TOO_LOW_FOR_BUOY :{WHITE}Bridge is too low for buoy -STR_ERROR_BRIDGE_TOO_LOW_FOR_RAIL_WAYPOINT :{WHITE}Bridge is too low for rail waypoint -STR_ERROR_BRIDGE_TOO_LOW_FOR_ROAD_WAYPOINT :{WHITE}Bridge is too low for road waypoint -STR_ERROR_BRIDGE_TOO_LOW_FOR_LOCK :{WHITE}Bridge is too low for lock +STR_ERROR_BRIDGE_TOO_LOW_FOR_STATION :{WHITE}Bridge is {HEIGHT} too low for station +STR_ERROR_BRIDGE_TOO_LOW_FOR_ROADSTOP :{WHITE}Bridge is {HEIGHT} too low for road stop +STR_ERROR_BRIDGE_TOO_LOW_FOR_DOCK :{WHITE}Bridge is {HEIGHT} too low for dock +STR_ERROR_BRIDGE_TOO_LOW_FOR_BUOY :{WHITE}Bridge is {HEIGHT} too low for buoy +STR_ERROR_BRIDGE_TOO_LOW_FOR_RAIL_WAYPOINT :{WHITE}Bridge is {HEIGHT} too low for rail waypoint +STR_ERROR_BRIDGE_TOO_LOW_FOR_ROAD_WAYPOINT :{WHITE}Bridge is {HEIGHT} too low for road waypoint +STR_ERROR_BRIDGE_TOO_LOW_FOR_LOCK :{WHITE}Bridge is {HEIGHT} too low for lock # Tunnel related errors STR_ERROR_CAN_T_BUILD_TUNNEL_HERE :{WHITE}Can't build tunnel here... diff --git a/src/lang/english_AU.txt b/src/lang/english_AU.txt index 804b09d79c063..55c66782b15f4 100644 --- a/src/lang/english_AU.txt +++ b/src/lang/english_AU.txt @@ -254,6 +254,7 @@ STR_UNITS_FORCE_SI :{DECIMAL}{NBSP} STR_UNITS_HEIGHT_IMPERIAL :{DECIMAL}{NBSP}ft STR_UNITS_HEIGHT_METRIC :{DECIMAL}{NBSP}m STR_UNITS_HEIGHT_SI :{DECIMAL}{NBSP}m +STR_UNITS_HEIGHT_GAMEUNITS :{DECIMAL}{NBSP}level{P "" s} # Time units used in string control characters STR_UNITS_DAYS :{COMMA}{NBSP}day{P "" s} @@ -2158,10 +2159,11 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_SI :SI (kN) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT :Heights units: {STRING} STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_HELPTEXT :Whenever heights are shown in the user interface, show it in the selected units -###length 3 +###length 4 STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_IMPERIAL :Imperial (ft) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_METRIC :Metric (m) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_SI :SI (m) +STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_GAMEUNITS :Game units (levels) STR_CONFIG_SETTING_LOCALISATION :Localisation STR_CONFIG_SETTING_GRAPHICS :Graphics @@ -3425,11 +3427,18 @@ STR_MAPGEN_NORTHWEST :{BLACK}Northwes STR_MAPGEN_NORTHEAST :{BLACK}Northeast STR_MAPGEN_SOUTHEAST :{BLACK}Southeast STR_MAPGEN_SOUTHWEST :{BLACK}Southwest +STR_MAPGEN_NORTHWEST_TOOLTIP :Toggle water or freeform edge on the northwest map edge +STR_MAPGEN_NORTHEAST_TOOLTIP :Toggle water or freeform edge on the northeast map edge +STR_MAPGEN_SOUTHEAST_TOOLTIP :Toggle water or freeform edge on the southeast map edge +STR_MAPGEN_SOUTHWEST_TOOLTIP :Toggle water or freeform edge on the southwest map edge STR_MAPGEN_BORDER_FREEFORM :{BLACK}Freeform STR_MAPGEN_BORDER_WATER :{BLACK}Water STR_MAPGEN_BORDER_RANDOM :{BLACK}Random -STR_MAPGEN_BORDER_RANDOMIZE :{BLACK}Random -STR_MAPGEN_BORDER_MANUAL :{BLACK}Manual + +###length 3 +STR_MAPGEN_BORDER_RANDOMIZE :Random +STR_MAPGEN_BORDER_MANUAL :Manual +STR_MAPGEN_BORDER_INFINITE_WATER :Infinite Water STR_MAPGEN_HEIGHTMAP_ROTATION :{BLACK}Heightmap rotation: STR_MAPGEN_HEIGHTMAP_NAME :{BLACK}Heightmap name: @@ -3468,7 +3477,8 @@ STR_GENERATION_LANDSCAPE_GENERATION :{BLACK}Landscap STR_GENERATION_RIVER_GENERATION :{BLACK}River generation STR_GENERATION_CLEARING_TILES :{BLACK}Rough and rocky area generation STR_GENERATION_TOWN_GENERATION :{BLACK}Town generation -STR_GENERATION_INDUSTRY_GENERATION :{BLACK}Industry generation +STR_GENERATION_LAND_INDUSTRY_GENERATION :{BLACK}Land industry generation +STR_GENERATION_WATER_INDUSTRY_GENERATION :{BLACK}Water industry generation STR_GENERATION_OBJECT_GENERATION :{BLACK}Object generation STR_GENERATION_TREE_GENERATION :{BLACK}Tree generation STR_GENERATION_SETTINGUP_GAME :{BLACK}Setting up game @@ -3688,7 +3698,7 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}Enter a STR_TOWN_DIRECTORY_CAPTION :{WHITE}Towns ({COMMA} of {COMMA}) STR_TOWN_DIRECTORY_NONE :{ORANGE}- None - STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) -STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (City){BLACK} ({COMMA}) +STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{BLACK} ({COMMA}) {YELLOW}{CITY_ICON} STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}Town names - click on name to centre main view on town. Ctrl+Click to open a new viewport on town location STR_TOWN_POPULATION :{BLACK}World population: {COMMA} @@ -5266,13 +5276,13 @@ STR_ERROR_START_AND_END_MUST_BE_IN :{WHITE}Start an STR_ERROR_ENDS_OF_BRIDGE_MUST_BOTH :{WHITE}... ends of bridge must both be on land STR_ERROR_BRIDGE_TOO_LONG :{WHITE}... bridge too long STR_ERROR_BRIDGE_THROUGH_MAP_BORDER :{WHITE}Bridge would end out of the map -STR_ERROR_BRIDGE_TOO_LOW_FOR_STATION :{WHITE}Bridge is too low for station -STR_ERROR_BRIDGE_TOO_LOW_FOR_ROADSTOP :{WHITE}Bridge is too low for road stop -STR_ERROR_BRIDGE_TOO_LOW_FOR_DOCK :{WHITE}Bridge is too low for dock -STR_ERROR_BRIDGE_TOO_LOW_FOR_BUOY :{WHITE}Bridge is too low for buoy -STR_ERROR_BRIDGE_TOO_LOW_FOR_RAIL_WAYPOINT :{WHITE}Bridge is too low for rail waypoint -STR_ERROR_BRIDGE_TOO_LOW_FOR_ROAD_WAYPOINT :{WHITE}Bridge is too low for road waypoint -STR_ERROR_BRIDGE_TOO_LOW_FOR_LOCK :{WHITE}Bridge is too low for lock +STR_ERROR_BRIDGE_TOO_LOW_FOR_STATION :{WHITE}Bridge is {HEIGHT} too low for station +STR_ERROR_BRIDGE_TOO_LOW_FOR_ROADSTOP :{WHITE}Bridge is {HEIGHT} too low for road stop +STR_ERROR_BRIDGE_TOO_LOW_FOR_DOCK :{WHITE}Bridge is {HEIGHT} too low for dock +STR_ERROR_BRIDGE_TOO_LOW_FOR_BUOY :{WHITE}Bridge is {HEIGHT} too low for buoy +STR_ERROR_BRIDGE_TOO_LOW_FOR_RAIL_WAYPOINT :{WHITE}Bridge is {HEIGHT} too low for rail waypoint +STR_ERROR_BRIDGE_TOO_LOW_FOR_ROAD_WAYPOINT :{WHITE}Bridge is {HEIGHT} too low for road waypoint +STR_ERROR_BRIDGE_TOO_LOW_FOR_LOCK :{WHITE}Bridge is {HEIGHT} too low for lock # Tunnel related errors STR_ERROR_CAN_T_BUILD_TUNNEL_HERE :{WHITE}Can't build tunnel here... diff --git a/src/lang/english_US.txt b/src/lang/english_US.txt index c04f5ce88f638..63796fbe526ef 100644 --- a/src/lang/english_US.txt +++ b/src/lang/english_US.txt @@ -254,6 +254,7 @@ STR_UNITS_FORCE_SI :{DECIMAL}{NBSP} STR_UNITS_HEIGHT_IMPERIAL :{DECIMAL}{NBSP}ft STR_UNITS_HEIGHT_METRIC :{DECIMAL}{NBSP}m STR_UNITS_HEIGHT_SI :{DECIMAL}{NBSP}m +STR_UNITS_HEIGHT_GAMEUNITS :{DECIMAL}{NBSP}level{P "" s} # Time units used in string control characters STR_UNITS_DAYS :{COMMA}{NBSP}day{P "" s} @@ -2158,10 +2159,11 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_SI :SI (kN) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT :Heights units: {STRING} STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_HELPTEXT :Whenever a height is shown in the user interface, show it in the selected units -###length 3 +###length 4 STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_IMPERIAL :Imperial (ft) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_METRIC :Metric (m) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_SI :SI (m) +STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_GAMEUNITS :Game units (levels) STR_CONFIG_SETTING_LOCALISATION :Localization STR_CONFIG_SETTING_GRAPHICS :Graphics @@ -3425,11 +3427,18 @@ STR_MAPGEN_NORTHWEST :{BLACK}Northwes STR_MAPGEN_NORTHEAST :{BLACK}Northeast STR_MAPGEN_SOUTHEAST :{BLACK}Southeast STR_MAPGEN_SOUTHWEST :{BLACK}Southwest +STR_MAPGEN_NORTHWEST_TOOLTIP :Toggle water or freeform edge on the northwest map edge +STR_MAPGEN_NORTHEAST_TOOLTIP :Toggle water or freeform edge on the northeast map edge +STR_MAPGEN_SOUTHEAST_TOOLTIP :Toggle water or freeform edge on the southeast map edge +STR_MAPGEN_SOUTHWEST_TOOLTIP :Toggle water or freeform edge on the southwest map edge STR_MAPGEN_BORDER_FREEFORM :{BLACK}Freeform STR_MAPGEN_BORDER_WATER :{BLACK}Water STR_MAPGEN_BORDER_RANDOM :{BLACK}Random -STR_MAPGEN_BORDER_RANDOMIZE :{BLACK}Random -STR_MAPGEN_BORDER_MANUAL :{BLACK}Manual + +###length 3 +STR_MAPGEN_BORDER_RANDOMIZE :Random +STR_MAPGEN_BORDER_MANUAL :Manual +STR_MAPGEN_BORDER_INFINITE_WATER :Infinite Water STR_MAPGEN_HEIGHTMAP_ROTATION :{BLACK}Heightmap rotation: STR_MAPGEN_HEIGHTMAP_NAME :{BLACK}Heightmap name: @@ -3468,7 +3477,8 @@ STR_GENERATION_LANDSCAPE_GENERATION :{BLACK}Landscap STR_GENERATION_RIVER_GENERATION :{BLACK}River generation STR_GENERATION_CLEARING_TILES :{BLACK}Rough and rocky area generation STR_GENERATION_TOWN_GENERATION :{BLACK}Town generation -STR_GENERATION_INDUSTRY_GENERATION :{BLACK}Industry generation +STR_GENERATION_LAND_INDUSTRY_GENERATION :{BLACK}Land industry generation +STR_GENERATION_WATER_INDUSTRY_GENERATION :{BLACK}Water industry generation STR_GENERATION_OBJECT_GENERATION :{BLACK}Object generation STR_GENERATION_TREE_GENERATION :{BLACK}Tree generation STR_GENERATION_SETTINGUP_GAME :{BLACK}Setting up game @@ -3688,7 +3698,7 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}Enter a STR_TOWN_DIRECTORY_CAPTION :{WHITE}Towns ({COMMA} of {COMMA}) STR_TOWN_DIRECTORY_NONE :{ORANGE}- None - STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) -STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (City){BLACK} ({COMMA}) +STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{BLACK} ({COMMA}) {YELLOW}{CITY_ICON} STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}Town names - click on name to center main view on town. Ctrl+Click to open a new viewport on town location STR_TOWN_POPULATION :{BLACK}World population: {COMMA} @@ -5266,13 +5276,13 @@ STR_ERROR_START_AND_END_MUST_BE_IN :{WHITE}Start an STR_ERROR_ENDS_OF_BRIDGE_MUST_BOTH :{WHITE}... ends of bridge must both be on land STR_ERROR_BRIDGE_TOO_LONG :{WHITE}... bridge too long STR_ERROR_BRIDGE_THROUGH_MAP_BORDER :{WHITE}Bridge would end out of the map -STR_ERROR_BRIDGE_TOO_LOW_FOR_STATION :{WHITE}Bridge is too low for station -STR_ERROR_BRIDGE_TOO_LOW_FOR_ROADSTOP :{WHITE}Bridge is too low for road stop -STR_ERROR_BRIDGE_TOO_LOW_FOR_DOCK :{WHITE}Bridge is too low for dock -STR_ERROR_BRIDGE_TOO_LOW_FOR_BUOY :{WHITE}Bridge is too low for buoy -STR_ERROR_BRIDGE_TOO_LOW_FOR_RAIL_WAYPOINT :{WHITE}Bridge is too low for rail waypoint -STR_ERROR_BRIDGE_TOO_LOW_FOR_ROAD_WAYPOINT :{WHITE}Bridge is too low for road waypoint -STR_ERROR_BRIDGE_TOO_LOW_FOR_LOCK :{WHITE}Bridge is too low for lock +STR_ERROR_BRIDGE_TOO_LOW_FOR_STATION :{WHITE}Bridge is {HEIGHT} too low for station +STR_ERROR_BRIDGE_TOO_LOW_FOR_ROADSTOP :{WHITE}Bridge is {HEIGHT} too low for road stop +STR_ERROR_BRIDGE_TOO_LOW_FOR_DOCK :{WHITE}Bridge is {HEIGHT} too low for dock +STR_ERROR_BRIDGE_TOO_LOW_FOR_BUOY :{WHITE}Bridge is {HEIGHT} too low for buoy +STR_ERROR_BRIDGE_TOO_LOW_FOR_RAIL_WAYPOINT :{WHITE}Bridge is {HEIGHT} too low for rail waypoint +STR_ERROR_BRIDGE_TOO_LOW_FOR_ROAD_WAYPOINT :{WHITE}Bridge is {HEIGHT} too low for road waypoint +STR_ERROR_BRIDGE_TOO_LOW_FOR_LOCK :{WHITE}Bridge is {HEIGHT} too low for lock # Tunnel related errors STR_ERROR_CAN_T_BUILD_TUNNEL_HERE :{WHITE}Can't build tunnel here... diff --git a/src/lang/esperanto.txt b/src/lang/esperanto.txt index 1b9aa8ce116a0..8898cf08644d5 100644 --- a/src/lang/esperanto.txt +++ b/src/lang/esperanto.txt @@ -2099,7 +2099,7 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_SI :SI-unuoj (kN) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT :Altecunuoj: {STRING} STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_HELPTEXT :Kiam ajn montriĝas alteco en la uzantinterfaco, montru ĝin en la indikitaj unuoj -###length 3 +###length 4 STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_IMPERIAL :Angla-usona sistemo (futoj) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_METRIC :Metra (m) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_SI :SI-unuoj (m) @@ -3256,6 +3256,8 @@ STR_MAPGEN_SOUTHWEST :{BLACK}Sudokcid STR_MAPGEN_BORDER_FREEFORM :{BLACK}Libermana STR_MAPGEN_BORDER_WATER :{BLACK}Akvo STR_MAPGEN_BORDER_RANDOM :{BLACK}Hazarde + +###length 3 STR_MAPGEN_BORDER_RANDOMIZE :{BLACK}Hazarde STR_MAPGEN_BORDER_MANUAL :{BLACK}Permane @@ -3477,7 +3479,6 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}Enigu no # Town directory window STR_TOWN_DIRECTORY_NONE :{ORANGE}-Neniu - STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) -STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (Urbego){BLACK} ({COMMA}) STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}Urbonomoj - klaku nomon por centri vidpukto ĉe la urbo. Ctrl+Klak por malfermi novan vidujon ĉe la urba loko STR_TOWN_POPULATION :{BLACK}Monda enloĝantaro: {COMMA} diff --git a/src/lang/estonian.txt b/src/lang/estonian.txt index 49dab0b1c72d5..24edd3e26da02 100644 --- a/src/lang/estonian.txt +++ b/src/lang/estonian.txt @@ -2163,7 +2163,7 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_SI :SI-süsteem (kN STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT :Kõrgusühikud: {STRING} STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_HELPTEXT :Liideses näidatakse kõrgust valitud mõõdustikus -###length 3 +###length 4 STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_IMPERIAL :Inglise mõõdustik (ft) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_METRIC :Meetermõõdustik (m) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_SI :SI-süsteem (m) @@ -3376,6 +3376,8 @@ STR_MAPGEN_SOUTHWEST :{BLACK}Edel STR_MAPGEN_BORDER_FREEFORM :{BLACK}Vaba STR_MAPGEN_BORDER_WATER :{BLACK}Vesi STR_MAPGEN_BORDER_RANDOM :{BLACK}Suvaline + +###length 3 STR_MAPGEN_BORDER_RANDOMIZE :{BLACK}Suvaline STR_MAPGEN_BORDER_MANUAL :{BLACK}Määratud @@ -3416,7 +3418,6 @@ STR_GENERATION_LANDSCAPE_GENERATION :{BLACK}Maastiku STR_GENERATION_RIVER_GENERATION :{BLACK}Jõgede tekitamine STR_GENERATION_CLEARING_TILES :{BLACK}Mägise ja kivise maa-ala tekitamine STR_GENERATION_TOWN_GENERATION :{BLACK}Asulate tekitamine -STR_GENERATION_INDUSTRY_GENERATION :{BLACK}Tööstuse tekitamine STR_GENERATION_OBJECT_GENERATION :{BLACK}Objekti tekitamine STR_GENERATION_TREE_GENERATION :{BLACK}Puude tekitamine STR_GENERATION_SETTINGUP_GAME :{BLACK}Mängu seadistamine @@ -3626,7 +3627,6 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}Sisesta # Town directory window STR_TOWN_DIRECTORY_NONE :{ORANGE}- Puudub - STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) -STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (Linn){BLACK} ({COMMA}) STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}Astuste nimed - vajuta nimele, et viia vaade asustusele. Ctrl+klõps avab uue vaate linna asukohas STR_TOWN_POPULATION :{BLACK}Maailma rahvaarv: {COMMA} diff --git a/src/lang/faroese.txt b/src/lang/faroese.txt index 15dba5c7727fb..b2b65047adb36 100644 --- a/src/lang/faroese.txt +++ b/src/lang/faroese.txt @@ -1675,7 +1675,7 @@ STR_CONFIG_SETTING_LARGER_TOWNS_DISABLED :Eingin ###length 3 -###length 3 +###length 4 STR_CONFIG_SETTING_SOUND :Ljóð effektir STR_CONFIG_SETTING_INTERFACE :Takførisflati @@ -2524,6 +2524,8 @@ STR_MAPGEN_SOUTHWEST :{BLACK}Útsynni STR_MAPGEN_BORDER_FREEFORM :{BLACK}Freeform STR_MAPGEN_BORDER_WATER :{BLACK}Vatn STR_MAPGEN_BORDER_RANDOM :{BLACK}Tilvildarligt + +###length 3 STR_MAPGEN_BORDER_RANDOMIZE :{BLACK}Tilvildarligt STR_MAPGEN_BORDER_MANUAL :{BLACK}Manuelt diff --git a/src/lang/finnish.txt b/src/lang/finnish.txt index 2271da1991262..80a1c2f87b7fe 100644 --- a/src/lang/finnish.txt +++ b/src/lang/finnish.txt @@ -254,6 +254,7 @@ STR_UNITS_FORCE_SI :{DECIMAL}{NBSP} STR_UNITS_HEIGHT_IMPERIAL :{DECIMAL}{NBSP}ft STR_UNITS_HEIGHT_METRIC :{DECIMAL}{NBSP}m STR_UNITS_HEIGHT_SI :{DECIMAL}{NBSP}m +STR_UNITS_HEIGHT_GAMEUNITS :{DECIMAL}{NBSP}taso{P "" a} # Time units used in string control characters STR_UNITS_DAYS :{COMMA}{NBSP}vrk @@ -2124,8 +2125,8 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_HELPTEXT :Kun käyttölii STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_IMPERIAL :Brittiläinen (mph) STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_METRIC :Metrinen (km/h) STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_SI :SI (m/s) -STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_GAMEUNITS_DAYS :Pelin yksiköt (ruutua/vrk) -STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_GAMEUNITS_SECS :Pelin yksiköt (ruutua/s) +STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_GAMEUNITS_DAYS :Pelin yksiköt (ruutuja/vrk) +STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_GAMEUNITS_SECS :Pelin yksiköt (ruutuja/s) STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_KNOTS :Solmut STR_CONFIG_SETTING_LOCALISATION_UNITS_POWER :Kulkuneuvon tehon yksikkö: {STRING} @@ -2158,10 +2159,11 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_SI :SI (kN) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT :Korkeuden yksikkö: {STRING} STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_HELPTEXT :Kun käyttöliittymässä näytetään korkeus, näytä se valittua yksikköä käyttäen -###length 3 +###length 4 STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_IMPERIAL :Brittiläinen (ft) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_METRIC :Metrinen (m) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_SI :SI (m) +STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_GAMEUNITS :Pelin yksiköt (tasoja) STR_CONFIG_SETTING_LOCALISATION :Mittayksiköt ja päivämäärät STR_CONFIG_SETTING_GRAPHICS :Grafiikka @@ -2962,8 +2964,8 @@ STR_STATION_BUILD_BUS_ORIENTATION :{WHITE}Linja-au STR_STATION_BUILD_BUS_ORIENTATION_TOOLTIP :{BLACK}Valitse linja-autoaseman suunta STR_STATION_BUILD_TRUCK_ORIENTATION :{WHITE}Lastauslaiturin suunta STR_STATION_BUILD_TRUCK_ORIENTATION_TOOLTIP :{BLACK}Valitse lastauslaiturin suunta -STR_STATION_BUILD_PASSENGER_TRAM_ORIENTATION :{WHITE}Aseman suunta -STR_STATION_BUILD_PASSENGER_TRAM_ORIENTATION_TOOLTIP :{BLACK}Valitse aseman suunta +STR_STATION_BUILD_PASSENGER_TRAM_ORIENTATION :{WHITE}Raitiotien matkustaja-aseman suunta +STR_STATION_BUILD_PASSENGER_TRAM_ORIENTATION_TOOLTIP :{BLACK}Valitse raitiotien matkustaja-aseman suunta STR_STATION_BUILD_CARGO_TRAM_ORIENTATION :{WHITE}Rahtiaseman suunta STR_STATION_BUILD_CARGO_TRAM_ORIENTATION_TOOLTIP :{BLACK}Valitse rahtiaseman suunta @@ -3425,11 +3427,18 @@ STR_MAPGEN_NORTHWEST :{BLACK}Luode STR_MAPGEN_NORTHEAST :{BLACK}Koillinen STR_MAPGEN_SOUTHEAST :{BLACK}Kaakko STR_MAPGEN_SOUTHWEST :{BLACK}Lounas +STR_MAPGEN_NORTHWEST_TOOLTIP :Valitse, onko kartan luoteislaita vettä vai vapaamuotoista reunaa +STR_MAPGEN_NORTHEAST_TOOLTIP :Valitse, onko kartan koillislaita vettä vai vapaamuotoista reunaa +STR_MAPGEN_SOUTHEAST_TOOLTIP :Valitse, onko kartan kaakkoislaita vettä vai vapaamuotoista reunaa +STR_MAPGEN_SOUTHWEST_TOOLTIP :Valitse, onko kartan lounaislaita vettä vai vapaamuotoista reunaa STR_MAPGEN_BORDER_FREEFORM :{BLACK}Vapaa STR_MAPGEN_BORDER_WATER :{BLACK}Vesi STR_MAPGEN_BORDER_RANDOM :{BLACK}Sattumanvarainen -STR_MAPGEN_BORDER_RANDOMIZE :{BLACK}Sattumanvarainen -STR_MAPGEN_BORDER_MANUAL :{BLACK}Manuaalinen + +###length 3 +STR_MAPGEN_BORDER_RANDOMIZE :Satunnaiset +STR_MAPGEN_BORDER_MANUAL :Aseta käsin +STR_MAPGEN_BORDER_INFINITE_WATER :Ääretön vesi STR_MAPGEN_HEIGHTMAP_ROTATION :{BLACK}Korkeuskartan kierto: STR_MAPGEN_HEIGHTMAP_NAME :{BLACK}Korkeuskartan nimi: @@ -3468,7 +3477,8 @@ STR_GENERATION_LANDSCAPE_GENERATION :{BLACK}Maaston STR_GENERATION_RIVER_GENERATION :{BLACK}Jokien luominen STR_GENERATION_CLEARING_TILES :{BLACK}Karun ja kivisen alueen luominen STR_GENERATION_TOWN_GENERATION :{BLACK}Kuntien luominen -STR_GENERATION_INDUSTRY_GENERATION :{BLACK}Tuotantolaitosten luominen +STR_GENERATION_LAND_INDUSTRY_GENERATION :{BLACK}Teollisuuden luominen maalla +STR_GENERATION_WATER_INDUSTRY_GENERATION :{BLACK}Teollisuuden luominen vedessä STR_GENERATION_OBJECT_GENERATION :{BLACK}Siirtämättömän luominen STR_GENERATION_TREE_GENERATION :{BLACK}Puiden luominen STR_GENERATION_SETTINGUP_GAME :{BLACK}Valmistellaan peliä @@ -3688,7 +3698,7 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}Syötä STR_TOWN_DIRECTORY_CAPTION :{WHITE}Kunnat ({COMMA}/{COMMA}) STR_TOWN_DIRECTORY_NONE :{ORANGE}- Ei mitään - STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) -STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (kaupunki){BLACK} ({COMMA}) +STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{BLACK} ({COMMA}) {YELLOW}{CITY_ICON} STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}Kuntien nimet – keskitä päänäkymä kuntaan napsauttamalla nimeä. Ctrl+napsautus avaa uuden näkymäikkunan kunnan sijaintiin STR_TOWN_POPULATION :{BLACK}Maailman asukasluku: {COMMA} @@ -5266,13 +5276,13 @@ STR_ERROR_START_AND_END_MUST_BE_IN :{WHITE}Alku- ja STR_ERROR_ENDS_OF_BRIDGE_MUST_BOTH :{WHITE}... sillan molempien päiden pitää sijaita maalla. STR_ERROR_BRIDGE_TOO_LONG :{WHITE}... silta liian pitkä STR_ERROR_BRIDGE_THROUGH_MAP_BORDER :{WHITE}Silta päättyisi kartan ulkopuolelle -STR_ERROR_BRIDGE_TOO_LOW_FOR_STATION :{WHITE}Silta on liian matala aseman ylle -STR_ERROR_BRIDGE_TOO_LOW_FOR_ROADSTOP :{WHITE}Silta on liian matala pysäkin ylle -STR_ERROR_BRIDGE_TOO_LOW_FOR_DOCK :{WHITE}Silta on liian matala sataman ylle -STR_ERROR_BRIDGE_TOO_LOW_FOR_BUOY :{WHITE}Silta on liian matala poijun ylle -STR_ERROR_BRIDGE_TOO_LOW_FOR_RAIL_WAYPOINT :{WHITE}Silta on liian matala rautatien reittipisteen ylle -STR_ERROR_BRIDGE_TOO_LOW_FOR_ROAD_WAYPOINT :{WHITE}Silta on liian matala tien reittipisteen ylle -STR_ERROR_BRIDGE_TOO_LOW_FOR_LOCK :{WHITE}Silta on liian matala sulun ylle +STR_ERROR_BRIDGE_TOO_LOW_FOR_STATION :{WHITE}Silta on {HEIGHT} liian matala aseman ylle +STR_ERROR_BRIDGE_TOO_LOW_FOR_ROADSTOP :{WHITE}Silta on {HEIGHT} liian matala pysäkin ylle +STR_ERROR_BRIDGE_TOO_LOW_FOR_DOCK :{WHITE}Silta on {HEIGHT} liian matala sataman ylle +STR_ERROR_BRIDGE_TOO_LOW_FOR_BUOY :{WHITE}Silta on {HEIGHT} liian matala poijun ylle +STR_ERROR_BRIDGE_TOO_LOW_FOR_RAIL_WAYPOINT :{WHITE}Silta on {HEIGHT} liian matala rautatien reittipisteen ylle +STR_ERROR_BRIDGE_TOO_LOW_FOR_ROAD_WAYPOINT :{WHITE}Silta on {HEIGHT} liian matala tien reittipisteen ylle +STR_ERROR_BRIDGE_TOO_LOW_FOR_LOCK :{WHITE}Silta on {HEIGHT} liian matala sulun ylle # Tunnel related errors STR_ERROR_CAN_T_BUILD_TUNNEL_HERE :{WHITE}Tunnelia ei voi rakentaa... diff --git a/src/lang/french.txt b/src/lang/french.txt index d1b844e658630..d7912b71270bd 100644 --- a/src/lang/french.txt +++ b/src/lang/french.txt @@ -255,6 +255,7 @@ STR_UNITS_FORCE_SI :{DECIMAL}{NBSP} STR_UNITS_HEIGHT_IMPERIAL :{DECIMAL}{NBSP}ft STR_UNITS_HEIGHT_METRIC :{DECIMAL}{NBSP}m STR_UNITS_HEIGHT_SI :{DECIMAL}{NBSP}m +STR_UNITS_HEIGHT_GAMEUNITS :{DECIMAL}{NBSP}niveau{P "" x} # Time units used in string control characters STR_UNITS_DAYS :{G=m}{COMMA}{NBSP}jour{P "" s} @@ -2092,7 +2093,7 @@ STR_CONFIG_SETTING_CITY_SIZE_MULTIPLIER_HELPTEXT :Taille moyenne STR_CONFIG_SETTING_LINKGRAPH_RECALC_INTERVAL :Mise à jour du graphe de distribution toutes les {STRING} STR_CONFIG_SETTING_LINKGRAPH_RECALC_INTERVAL_HELPTEXT :Intervalle entre les recalculs successifs du graphe de liaison. Chaque recalcul planifie un composant du graphe. Cela signifie qu'une valeur X pour ce paramètre ne signifie pas que l'ensemble du graphe sera mis à jour toutes les X secondes. Seul un composant le sera. Plus vous définissez cet intervalle court, plus le temps de processeur nécessaire pour le calcul sera important. Plus vous définissez cet intervalle long, plus il faudra de temps pour que la distribution de marchandises commence sur de nouveaux itinéraires -STR_CONFIG_SETTING_LINKGRAPH_RECALC_TIME :Recalcul du graphe de distribution toutes les {STRING} +STR_CONFIG_SETTING_LINKGRAPH_RECALC_TIME :Prend {STRING} pour le recalcul du graphe de distribution STR_CONFIG_SETTING_LINKGRAPH_RECALC_TIME_HELPTEXT :Temps pris pour chaque recalcul d'un composant du graphe de liaison. Lorsqu'un recalcul est lancé, un fil d'exécution est créé et autorisé à fonctionner pendant ce nombre de secondes. Plus vous définissez cette durée courte, plus il est probable que le fil ne soit pas terminé lorsqu'il est censé l'être. Ensuite, le jeu s'arrête jusqu'à ce qu'il le soit ("lag"). Plus vous définissez cette durée longue, plus il faut de temps pour que la distribution soit mise à jour lorsque les itinéraires changent STR_CONFIG_SETTING_DISTRIBUTION_PAX :Type de distribution pour les passagers{NBSP}: {STRING} @@ -2159,10 +2160,11 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_SI :SI (kN) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT :Unité de hauteur{NBSP}: {STRING} STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_HELPTEXT :Quand une hauteur est affichée dans l'interface utilisateur, utiliser l'unité sélectionnée -###length 3 +###length 4 STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_IMPERIAL :Impérial (ft) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_METRIC :Métrique (m) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_SI :SI (m) +STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_GAMEUNITS :Unités de jeu (niveaux) STR_CONFIG_SETTING_LOCALISATION :Localisation STR_CONFIG_SETTING_GRAPHICS :Graphiques @@ -3429,8 +3431,11 @@ STR_MAPGEN_SOUTHWEST :{BLACK}Sud-Oues STR_MAPGEN_BORDER_FREEFORM :{BLACK}Forme libre STR_MAPGEN_BORDER_WATER :{BLACK}Eau STR_MAPGEN_BORDER_RANDOM :{BLACK}Aléatoire -STR_MAPGEN_BORDER_RANDOMIZE :{BLACK}Aléatoire -STR_MAPGEN_BORDER_MANUAL :{BLACK}Manuel + +###length 3 +STR_MAPGEN_BORDER_RANDOMIZE :Aléatoire +STR_MAPGEN_BORDER_MANUAL :Manuel +STR_MAPGEN_BORDER_INFINITE_WATER :Eau à l'infini STR_MAPGEN_HEIGHTMAP_ROTATION :{BLACK}Rotation de la carte d'altitude{NBSP}: STR_MAPGEN_HEIGHTMAP_NAME :{BLACK}Nom de la carte d'altitude{NBSP}: @@ -3469,7 +3474,8 @@ STR_GENERATION_LANDSCAPE_GENERATION :{BLACK}Généra STR_GENERATION_RIVER_GENERATION :{BLACK}Création des rivières STR_GENERATION_CLEARING_TILES :{BLACK}Création des zones rugueuses et rocheuses STR_GENERATION_TOWN_GENERATION :{BLACK}Génération des villes -STR_GENERATION_INDUSTRY_GENERATION :{BLACK}Génération des industries +STR_GENERATION_LAND_INDUSTRY_GENERATION :{BLACK}Génération des industries terrestres +STR_GENERATION_WATER_INDUSTRY_GENERATION :{BLACK}Génération des industries maritimes STR_GENERATION_OBJECT_GENERATION :{BLACK}Création des objets inamovibles STR_GENERATION_TREE_GENERATION :{BLACK}Création des arbres STR_GENERATION_SETTINGUP_GAME :{BLACK}Configuration du jeu @@ -3689,7 +3695,7 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}Entrer u STR_TOWN_DIRECTORY_CAPTION :{WHITE}Villes ({COMMA} de {COMMA}) STR_TOWN_DIRECTORY_NONE :{ORANGE}− Aucune − STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) -STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (Métropole){BLACK} ({COMMA}) +STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{BLACK} ({COMMA}) {YELLOW}{CITY_ICON} STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}Noms des villes - Cliquer sur un nom pour centrer la vue principale sur la ville. Ctrl-clic pour ouvrir une nouvelle vue sur la ville. STR_TOWN_POPULATION :{BLACK}Population mondiale{NBSP}: {COMMA} @@ -4186,7 +4192,7 @@ STR_PURCHASE_INFO_ALL_BUT :Tous sauf {CARG STR_PURCHASE_INFO_MAX_TE :{BLACK}Effort de traction max.{NBSP}: {GOLD}{FORCE} STR_PURCHASE_INFO_AIRCRAFT_RANGE :{BLACK}Rayon d'action{NBSP}: {GOLD}{COMMA}{NBSP}cases STR_PURCHASE_INFO_AIRCRAFT_TYPE :{BLACK}Type d'aéronef{NBSP}: {GOLD}{STRING} -STR_PURCHASE_INFO_RAILTYPES :{BLACK}Types de rail : {GOLD}{STRING} +STR_PURCHASE_INFO_RAILTYPES :{BLACK}Types de rail{NBSP}: {GOLD}{STRING} ###length 3 STR_CARGO_TYPE_FILTER_ALL :Tous les types de cargaison @@ -4370,7 +4376,7 @@ STR_ENGINE_PREVIEW_RUNCOST_YEAR :Coûts d'entret STR_ENGINE_PREVIEW_RUNCOST_PERIOD :Coûts d'entretien{NBSP}: {CURRENCY_LONG}/période STR_ENGINE_PREVIEW_CAPACITY :Capacité{NBSP}: {CARGO_LONG} STR_ENGINE_PREVIEW_CAPACITY_2 :Capacité{NBSP}: {CARGO_LONG}, {CARGO_LONG} -STR_ENGINE_PREVIEW_RAILTYPES :Types de rail : {STRING} +STR_ENGINE_PREVIEW_RAILTYPES :Types de rail{NBSP}: {STRING} # Autoreplace window STR_REPLACE_VEHICLES_WHITE :{WHITE}Remplacer {STRING} - {STRING} @@ -5267,12 +5273,13 @@ STR_ERROR_START_AND_END_MUST_BE_IN :{WHITE}Le débu STR_ERROR_ENDS_OF_BRIDGE_MUST_BOTH :{WHITE}... les deux extrémités du pont doivent être sur la terre ferme STR_ERROR_BRIDGE_TOO_LONG :{WHITE}... pont trop long STR_ERROR_BRIDGE_THROUGH_MAP_BORDER :{WHITE}Le pont finirait en dehors de la carte -STR_ERROR_BRIDGE_TOO_LOW_FOR_STATION :{WHITE}Le pont est trop bas pour les gares -STR_ERROR_BRIDGE_TOO_LOW_FOR_ROADSTOP :{WHITE}Le pont est trop bas pour les arrêts de bus -STR_ERROR_BRIDGE_TOO_LOW_FOR_BUOY :{WHITE}Le pont est trop bas pour les bouées -STR_ERROR_BRIDGE_TOO_LOW_FOR_RAIL_WAYPOINT :{WHITE}Le pont est trop bas pour les points de contrôle -STR_ERROR_BRIDGE_TOO_LOW_FOR_ROAD_WAYPOINT :{WHITE}Le pont est trop bas pour les points de contrôle de route -STR_ERROR_BRIDGE_TOO_LOW_FOR_LOCK :{WHITE}Ce pont est trop bas pour le verrouillage +STR_ERROR_BRIDGE_TOO_LOW_FOR_STATION :{WHITE}Le pont est {HEIGHT} trop bas pour les gares +STR_ERROR_BRIDGE_TOO_LOW_FOR_ROADSTOP :{WHITE}Le pont est {HEIGHT} trop bas pour les arrêts de bus +STR_ERROR_BRIDGE_TOO_LOW_FOR_DOCK :{WHITE}Le pont est {HEIGHT} trop bas pour le port +STR_ERROR_BRIDGE_TOO_LOW_FOR_BUOY :{WHITE}Le pont est {HEIGHT} trop bas pour les bouées +STR_ERROR_BRIDGE_TOO_LOW_FOR_RAIL_WAYPOINT :{WHITE}Le pont est {HEIGHT} trop bas pour les points de contrôle +STR_ERROR_BRIDGE_TOO_LOW_FOR_ROAD_WAYPOINT :{WHITE}Le pont est {HEIGHT} trop bas pour les points de contrôle de route +STR_ERROR_BRIDGE_TOO_LOW_FOR_LOCK :{WHITE}Le pont est {HEIGHT} trop bas pour l'écluse # Tunnel related errors STR_ERROR_CAN_T_BUILD_TUNNEL_HERE :{WHITE}Impossible de construire un tunnel ici... diff --git a/src/lang/frisian.txt b/src/lang/frisian.txt index 81441e30a46b7..6b3fc822a5b80 100644 --- a/src/lang/frisian.txt +++ b/src/lang/frisian.txt @@ -1785,7 +1785,7 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_SI :SI (kN) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT :Hichte-ienheid: {STRING} STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_HELPTEXT :Wannear't der hichten sichtber binne yn de interface de selektearre ienheiden brûke -###length 3 +###length 4 STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_IMPERIAL :Ymperiaal (ft) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_METRIC :Metrysk (m) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_SI :SI (m) @@ -2660,6 +2660,8 @@ STR_MAPGEN_SOUTHWEST :{BLACK}Súdwest STR_MAPGEN_BORDER_FREEFORM :{BLACK}Frij foarmje STR_MAPGEN_BORDER_WATER :{BLACK}Wetter STR_MAPGEN_BORDER_RANDOM :{BLACK}Samar wat + +###length 3 STR_MAPGEN_BORDER_RANDOMIZE :{BLACK}Samar wat STR_MAPGEN_BORDER_MANUAL :{BLACK}Hânmjittich diff --git a/src/lang/gaelic.txt b/src/lang/gaelic.txt index 4b246f9ae3212..c747f8bc6a186 100644 --- a/src/lang/gaelic.txt +++ b/src/lang/gaelic.txt @@ -2011,7 +2011,7 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_SI :SI (kN) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT :Aonadan àirde: {STRING} STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_HELPTEXT :Nuair a thèid àirde a shealltainn san eadar-aghaidh, seall i leis na h-aonadan a thagh thu -###length 3 +###length 4 STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_IMPERIAL :Impireil (ft) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_METRIC :Meatrach (m) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_SI :SI (m) @@ -3032,6 +3032,8 @@ STR_MAPGEN_SOUTHWEST :{BLACK}Iar-dhea STR_MAPGEN_BORDER_FREEFORM :{BLACK}Cruth saor STR_MAPGEN_BORDER_WATER :{BLACK}Uisge STR_MAPGEN_BORDER_RANDOM :{BLACK}Air thuaiream + +###length 3 STR_MAPGEN_BORDER_RANDOMIZE :{BLACK}Air thuaiream STR_MAPGEN_BORDER_MANUAL :{BLACK}A làimh diff --git a/src/lang/galician.txt b/src/lang/galician.txt index 4859d6aff2f10..e5f6f2b46c268 100644 --- a/src/lang/galician.txt +++ b/src/lang/galician.txt @@ -255,6 +255,7 @@ STR_UNITS_FORCE_SI :{DECIMAL} kN STR_UNITS_HEIGHT_IMPERIAL :{DECIMAL} pés STR_UNITS_HEIGHT_METRIC :{DECIMAL} m STR_UNITS_HEIGHT_SI :{DECIMAL} m +STR_UNITS_HEIGHT_GAMEUNITS :{DECIMAL}{NBSP}Nive{P "" is} # Time units used in string control characters STR_UNITS_DAYS :{COMMA}{NBSP}día{P "" s} @@ -1544,7 +1545,7 @@ STR_CONFIG_SETTING_TIMEKEEPING_UNITS_CALENDAR :Calendario STR_CONFIG_SETTING_TIMEKEEPING_UNITS_WALLCLOCK :Reloxo STR_CONFIG_SETTING_MINUTES_PER_YEAR :Minutos por ano: {STRING} -STR_CONFIG_SETTING_MINUTES_PER_YEAR_HELPTEXT :Selecciona o número de minutos dun ano do calendario. Por defecto son 12 minutos. Fíxao en 0 para para conxelar o calendario. Increemntar a duración do ano do calendario ralentiza a introdución de vehículos, casas e outra infraestrutura. Non afecta a velocidade dos vehículos ou a simulación económica excepto pola inflación. Este axuste só está dispoñible cando se usa o modo reloxo de cronometraxe +STR_CONFIG_SETTING_MINUTES_PER_YEAR_HELPTEXT :Selecciona o número de minutos dun ano do calendario. Por defecto son 12 minutos. Fíxao en 0 para para conxelar o calendario. Incrementar a duración do ano do calendario ralentiza a introdución de vehículos, casas e outra infraestrutura. Non afecta a velocidade dos vehículos ou a simulación económica excepto pola inflación. Este axuste só está dispoñible cando se usa o modo reloxo de cronometraxe STR_CONFIG_SETTING_MINUTES_PER_YEAR_VALUE :{NUM} ###setting-zero-is-special @@ -2159,10 +2160,11 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_SI :SI (kN) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT :Unidades para a altura (cota): {STRING} STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_HELPTEXT :Cando as cotas se amosen na interfaz de usuario, facelo coas unidades seleccionadas -###length 3 +###length 4 STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_IMPERIAL :Imperial (ft) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_METRIC :Métrico (m) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_SI :SI (m) +STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_GAMEUNITS :Unidades de xogo (niveis) STR_CONFIG_SETTING_LOCALISATION :Localización STR_CONFIG_SETTING_GRAPHICS :Gráficos @@ -2295,7 +2297,7 @@ STR_CHEAT_EDIT_MAX_HL_QUERY_CAPT :{WHITE}Trocar a STR_CHEAT_CHANGE_DATE :{LTBLUE}Cambiar data: {ORANGE}{DATE_SHORT} STR_CHEAT_CHANGE_DATE_QUERY_CAPT :{WHITE}Cambiar o ano actual STR_CHEAT_SETUP_PROD :{LTBLUE}Permitir a modificación dos valores de producción: {ORANGE}{STRING} -STR_CHEAT_STATION_RATING :{LTBLUE}Manter a puntuacuón das estacións ao 100%: {ORANGE}{STRING} +STR_CHEAT_STATION_RATING :{LTBLUE}Manter a puntuación das estacións ao 100%: {ORANGE}{STRING} # Livery window STR_LIVERY_CAPTION :{WHITE}{COMPANY} - Novo esquema de cor @@ -3349,6 +3351,8 @@ STR_SAVELOAD_DETAIL_GRFSTATUS :{SILVER}NewGRF: STR_SAVELOAD_FILTER_TITLE :{BLACK}Filtro: STR_SAVELOAD_OVERWRITE_TITLE :{WHITE}Sobrescribir arquivo STR_SAVELOAD_OVERWRITE_WARNING :{YELLOW}Estás seguro de que queres rescribir este arquivo? +STR_SAVELOAD_DELETE_TITLE :{WHITE}Borrar ficheiro +STR_SAVELOAD_DELETE_WARNING :{YELLOW}Estás seguro de que queres borrar este ficheiro? STR_SAVELOAD_DIRECTORY :{STRING} (Directorio) STR_SAVELOAD_PARENT_DIRECTORY :{STRING} (Directorio pai) @@ -3424,11 +3428,18 @@ STR_MAPGEN_NORTHWEST :{BLACK}Noroeste STR_MAPGEN_NORTHEAST :{BLACK}Nordés STR_MAPGEN_SOUTHEAST :{BLACK}Sueste STR_MAPGEN_SOUTHWEST :{BLACK}Suroeste +STR_MAPGEN_NORTHWEST_TOOLTIP :Alternar auga ou borde de forma libre na esquina noroeste do mapa +STR_MAPGEN_NORTHEAST_TOOLTIP :Alternar auga ou borde de forma libre na esquina nordeste do mapa +STR_MAPGEN_SOUTHEAST_TOOLTIP :Alternar auga ou borde de forma libre na esquina sudeste do mapa +STR_MAPGEN_SOUTHWEST_TOOLTIP :Alternar auga ou borde de forma libre na esquina sudoeste do mapa STR_MAPGEN_BORDER_FREEFORM :{BLACK}Forma libre STR_MAPGEN_BORDER_WATER :{BLACK}Auga STR_MAPGEN_BORDER_RANDOM :{BLACK}Aleatorio -STR_MAPGEN_BORDER_RANDOMIZE :{BLACK}Aleatorio -STR_MAPGEN_BORDER_MANUAL :{BLACK}Manual + +###length 3 +STR_MAPGEN_BORDER_RANDOMIZE :Aleatorio +STR_MAPGEN_BORDER_MANUAL :Manual +STR_MAPGEN_BORDER_INFINITE_WATER :Auga infinita STR_MAPGEN_HEIGHTMAP_ROTATION :{BLACK}Rotación do mapa de alturas: STR_MAPGEN_HEIGHTMAP_NAME :{BLACK}Nome do mapa de alturas: @@ -3467,7 +3478,8 @@ STR_GENERATION_LANDSCAPE_GENERATION :{BLACK}Xeració STR_GENERATION_RIVER_GENERATION :{BLACK}Xeración de ríos STR_GENERATION_CLEARING_TILES :{BLACK}Xeración de áreas rochosas e escarpadas STR_GENERATION_TOWN_GENERATION :{BLACK}Xeración de vilas -STR_GENERATION_INDUSTRY_GENERATION :{BLACK}Xeración da industria +STR_GENERATION_LAND_INDUSTRY_GENERATION :{BLACK}Xeración de industria terrestre +STR_GENERATION_WATER_INDUSTRY_GENERATION :{BLACK}Xeración de industria marítima STR_GENERATION_OBJECT_GENERATION :{BLACK}Xeración de obxectos STR_GENERATION_TREE_GENERATION :{BLACK}Xeración de árbores STR_GENERATION_SETTINGUP_GAME :{BLACK}Configurando partida @@ -3687,7 +3699,7 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}Escribe STR_TOWN_DIRECTORY_CAPTION :{WHITE}Vilas ({COMMA} de {COMMA}) STR_TOWN_DIRECTORY_NONE :{ORANGE}- Ningunha - STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) -STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (Vila){BLACK} ({COMMA}) +STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{BLACK} ({COMMA}) {YELLOW}{CITY_ICON} STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}Nomes de vilas - pincha no nome para centrar a vista na vila. Ctrl+Clic abre unha nova fiestra na localización da vila STR_TOWN_POPULATION :{BLACK}Poboación mundial: {COMMA} @@ -4184,6 +4196,7 @@ STR_PURCHASE_INFO_ALL_BUT :Todos excepto { STR_PURCHASE_INFO_MAX_TE :{BLACK}Esforzo máximo de tracción: {GOLD}{FORCE} STR_PURCHASE_INFO_AIRCRAFT_RANGE :{BLACK}Autonomía: {GOLD}{COMMA} cadros STR_PURCHASE_INFO_AIRCRAFT_TYPE :{BLACK}Tipo de aeronave: {GOLD}{STRING} +STR_PURCHASE_INFO_RAILTYPES :{BLACK}Tipos de ferrocarril: {GOLD}{STRING} ###length 3 STR_CARGO_TYPE_FILTER_ALL :Todos os tipos de carga @@ -4367,6 +4380,7 @@ STR_ENGINE_PREVIEW_RUNCOST_YEAR :Custo de mantem STR_ENGINE_PREVIEW_RUNCOST_PERIOD :Custo de mantemento: {CURRENCY_LONG}/período STR_ENGINE_PREVIEW_CAPACITY :Capacidade: {CARGO_LONG} STR_ENGINE_PREVIEW_CAPACITY_2 :Capacidade: {CARGO_LONG}, {CARGO_LONG} +STR_ENGINE_PREVIEW_RAILTYPES :Tipos de ferrocarril: {STRING} # Autoreplace window STR_REPLACE_VEHICLES_WHITE :{WHITE}Substituír {STRING} - {STRING} @@ -5263,11 +5277,13 @@ STR_ERROR_START_AND_END_MUST_BE_IN :{WHITE}O inicio STR_ERROR_ENDS_OF_BRIDGE_MUST_BOTH :{WHITE}... ambos extremos da ponte deben estar en terra STR_ERROR_BRIDGE_TOO_LONG :{WHITE}... ponte demasiado longa STR_ERROR_BRIDGE_THROUGH_MAP_BORDER :{WHITE}A ponte remataría fóra do mapa -STR_ERROR_BRIDGE_TOO_LOW_FOR_STATION :{WHITE}A ponte é demasiado baixa para a estación -STR_ERROR_BRIDGE_TOO_LOW_FOR_ROADSTOP :{WHITE}A ponte é demasiado baixa para unha estación de estrada -STR_ERROR_BRIDGE_TOO_LOW_FOR_BUOY :{WHITE}A ponte é demasiado baixa para a boia -STR_ERROR_BRIDGE_TOO_LOW_FOR_RAIL_WAYPOINT :{WHITE}A ponte é demasiado baixa para un punto de ruta de ferrocarril -STR_ERROR_BRIDGE_TOO_LOW_FOR_ROAD_WAYPOINT :{WHITE}A ponte é demasiado baixa para un punto de ruta de estrada +STR_ERROR_BRIDGE_TOO_LOW_FOR_STATION :{WHITE}A ponte é {HEIGHT} demasiado baixa para a estación +STR_ERROR_BRIDGE_TOO_LOW_FOR_ROADSTOP :{WHITE}A ponte é {HEIGHT} demasiado baixa para unha estación de estrada +STR_ERROR_BRIDGE_TOO_LOW_FOR_DOCK :{WHITE}A ponte é {HEIGHT} moi baixa para o porto +STR_ERROR_BRIDGE_TOO_LOW_FOR_BUOY :{WHITE}A ponte é {HEIGHT} demasiado baixa para a boia +STR_ERROR_BRIDGE_TOO_LOW_FOR_RAIL_WAYPOINT :{WHITE}A ponte é {HEIGHT} demasiado baixa para un punto de ruta de ferrocarril +STR_ERROR_BRIDGE_TOO_LOW_FOR_ROAD_WAYPOINT :{WHITE}A ponte é {HEIGHT} demasiado baixa para un punto de ruta de estrada +STR_ERROR_BRIDGE_TOO_LOW_FOR_LOCK :{WHITE}A ponte é {HEIGHT} moi baixa para a exclusa # Tunnel related errors STR_ERROR_CAN_T_BUILD_TUNNEL_HERE :{WHITE}Non se pode construír un túnel aí... diff --git a/src/lang/german.txt b/src/lang/german.txt index f02568c7c07e4..ff17c31330294 100644 --- a/src/lang/german.txt +++ b/src/lang/german.txt @@ -2157,7 +2157,7 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_SI :SI (kN) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT :Höheneinheiten: {STRING} STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_HELPTEXT :Immer wenn Höhen angezeigt werden, sie in den gewählten Einheiten anzeigen -###length 3 +###length 4 STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_IMPERIAL :Imperial (ft) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_METRIC :Metrisch (m) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_SI :SI (m) @@ -3425,6 +3425,8 @@ STR_MAPGEN_SOUTHWEST :{BLACK}Südwest STR_MAPGEN_BORDER_FREEFORM :{BLACK}Beliebig STR_MAPGEN_BORDER_WATER :{BLACK}Wasser STR_MAPGEN_BORDER_RANDOM :{BLACK}Zufällig + +###length 3 STR_MAPGEN_BORDER_RANDOMIZE :{BLACK}Zufällig STR_MAPGEN_BORDER_MANUAL :{BLACK}Manuell @@ -3465,7 +3467,6 @@ STR_GENERATION_LANDSCAPE_GENERATION :{BLACK}Landscha STR_GENERATION_RIVER_GENERATION :{BLACK}Flussgenerierung STR_GENERATION_CLEARING_TILES :{BLACK}Raue, felsige Landschaft wird erzeugt STR_GENERATION_TOWN_GENERATION :{BLACK}Stadterzeugung -STR_GENERATION_INDUSTRY_GENERATION :{BLACK}Industrieerzeugung STR_GENERATION_OBJECT_GENERATION :{BLACK}Unbewegliche Objekte werden erzeugt STR_GENERATION_TREE_GENERATION :{BLACK}Bäume werden erzeugt STR_GENERATION_SETTINGUP_GAME :{BLACK}Spiel wird vorbereitet @@ -3685,7 +3686,6 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}Text fü STR_TOWN_DIRECTORY_CAPTION :{WHITE}Städte ({COMMA} von {COMMA}) STR_TOWN_DIRECTORY_NONE :{ORANGE}- Keine - STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) -STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (Großstadt){BLACK} ({COMMA}) STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}Städtenamen – Klick auf den Namen zentriert Hauptansicht auf die Stadt. Mit Strg+Klick wird eine neue Zusatzansicht auf die Stadt geöffnet STR_TOWN_POPULATION :{BLACK}Weltbevölkerung: {COMMA} diff --git a/src/lang/greek.txt b/src/lang/greek.txt index 4ad2d4028b837..ca49e0fa51a44 100644 --- a/src/lang/greek.txt +++ b/src/lang/greek.txt @@ -316,6 +316,7 @@ STR_UNITS_FORCE_SI :{DECIMAL}{NBSP} STR_UNITS_HEIGHT_IMPERIAL :{DECIMAL}{NBSP}πόδ{P "ι" "ια"} STR_UNITS_HEIGHT_METRIC :{DECIMAL}{NBSP}μ STR_UNITS_HEIGHT_SI :{DECIMAL}{NBSP}m +STR_UNITS_HEIGHT_GAMEUNITS :{DECIMAL}{NBSP}επίπεδ{P "ο" "α"} # Time units used in string control characters STR_UNITS_DAYS :{COMMA}{NBSP}ημέρ{P 0 α ες} @@ -2251,10 +2252,11 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_SI :SI (kN) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT :Μονάδες μέτρησης ύψους: {STRING} STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_HELPTEXT :Όποτε εμφανίζεται ένα ύψος στη διεπαφή χρήστη, να εμφανίζεται στην επιλεγμένη μονάδα -###length 3 +###length 4 STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_IMPERIAL :Αυτοκρατορικό (πόδια) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_METRIC :Μετρικό (m) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_SI :SI (m) +STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_GAMEUNITS :Μονάδες παιχνιδιού (επίπεδα) STR_CONFIG_SETTING_LOCALISATION :Τοπικοποίηση STR_CONFIG_SETTING_GRAPHICS :Γραφικά @@ -3518,11 +3520,18 @@ STR_MAPGEN_NORTHWEST :{BLACK}Βορε STR_MAPGEN_NORTHEAST :{BLACK}Βορειοανατολικά STR_MAPGEN_SOUTHEAST :{BLACK}Νοτιοανατολικά STR_MAPGEN_SOUTHWEST :{BLACK}Νοτιοδυτικά +STR_MAPGEN_NORTHWEST_TOOLTIP :Εναλλαγή νερού ή ελεύθερης μορφής άκρης στο βορειοδυτικό άκρο του χάρτη +STR_MAPGEN_NORTHEAST_TOOLTIP :Εναλλαγή νερού ή ελεύθερης μορφής άκρης στο βορειοανατολικό άκρο του χάρτη +STR_MAPGEN_SOUTHEAST_TOOLTIP :Εναλλαγή νερού ή ελεύθερης μορφής άκρης στο νοτιοανατολικό άκρο του χάρτη +STR_MAPGEN_SOUTHWEST_TOOLTIP :Εναλλαγή νερού ή ελεύθερης μορφής άκρης στο νοτιοδυτικό άκρο του χάρτη STR_MAPGEN_BORDER_FREEFORM :{BLACK}Ελεύθερη μορφή STR_MAPGEN_BORDER_WATER :{BLACK}Νερό STR_MAPGEN_BORDER_RANDOM :{BLACK}Τυχαία -STR_MAPGEN_BORDER_RANDOMIZE :{BLACK}Τυχαία -STR_MAPGEN_BORDER_MANUAL :{BLACK}Χειροκίνητος + +###length 3 +STR_MAPGEN_BORDER_RANDOMIZE :Τυχαία +STR_MAPGEN_BORDER_MANUAL :Χειροκίνητος +STR_MAPGEN_BORDER_INFINITE_WATER :Απεριόριστo Νερό STR_MAPGEN_HEIGHTMAP_ROTATION :{BLACK}Περιστροφή χάρτη υψομετρίας: STR_MAPGEN_HEIGHTMAP_NAME :{BLACK}Όνομα χάρτη υψομετρίας: @@ -3561,7 +3570,8 @@ STR_GENERATION_LANDSCAPE_GENERATION :{BLACK}Δημι STR_GENERATION_RIVER_GENERATION :{BLACK}Δημιουργία ποταμού STR_GENERATION_CLEARING_TILES :{BLACK}Δημιουργία άγριας και πετρώδης περιοχής STR_GENERATION_TOWN_GENERATION :{BLACK}Δημιουργία πόλης -STR_GENERATION_INDUSTRY_GENERATION :{BLACK}Δημιουργία βιομηχανίας +STR_GENERATION_LAND_INDUSTRY_GENERATION :{BLACK}Δημιουργία βιομηχανίας γης +STR_GENERATION_WATER_INDUSTRY_GENERATION :{BLACK}Δημιουργία βιομηχανίας νερού STR_GENERATION_OBJECT_GENERATION :{BLACK}Δημιουργία μη μετακινούμενων STR_GENERATION_TREE_GENERATION :{BLACK}Δημιουργία δέντρων STR_GENERATION_SETTINGUP_GAME :{BLACK}Ρύθμιση παιχνιδιού @@ -3781,7 +3791,7 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}Δώστ STR_TOWN_DIRECTORY_CAPTION :{WHITE}Πόλεις ({COMMA} από {COMMA}) STR_TOWN_DIRECTORY_NONE :{ORANGE}- Τίποτα - STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) -STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (Πόλη){BLACK} ({COMMA}) +STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{BLACK} ({COMMA}) {YELLOW}{CITY_ICON} STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}Ονόματα πόλεων - πατήστε στο όνομα για κεντράρισμα της κύριας προβολής στην πόλη. Ctrl+Κλικ για άνοιγμα νέου παραθύρου προβολής στην τοποθεσία της πόλης STR_TOWN_POPULATION :{BLACK}Παγκόσμιος πληθυσμός: {COMMA} @@ -5367,13 +5377,13 @@ STR_ERROR_START_AND_END_MUST_BE_IN :{WHITE}Η αρ STR_ERROR_ENDS_OF_BRIDGE_MUST_BOTH :{WHITE}... και τα δύο άκρα της γέφυρας πρέπει να είναι σε έδαφος STR_ERROR_BRIDGE_TOO_LONG :{WHITE}... η γέφυρα είναι πολλή μακριά STR_ERROR_BRIDGE_THROUGH_MAP_BORDER :{WHITE}Η γέφυρα θα καταλήξει εκτός χάρτη -STR_ERROR_BRIDGE_TOO_LOW_FOR_STATION :{WHITE}Η γέφυρα είναι πολύ χαμηλή για σταθμό -STR_ERROR_BRIDGE_TOO_LOW_FOR_ROADSTOP :{WHITE}Η γέφυρα είναι πολύ χαμηλή για οδική στάση -STR_ERROR_BRIDGE_TOO_LOW_FOR_DOCK :{WHITE}Η γέφυρα είναι πολύ χαμηλή για αποβάθρα -STR_ERROR_BRIDGE_TOO_LOW_FOR_BUOY :{WHITE}Η γέφυρα είναι πολύ χαμηλή για σημαδούρα -STR_ERROR_BRIDGE_TOO_LOW_FOR_RAIL_WAYPOINT :{WHITE}Η γέφυρα είναι πολύ χαμηλή για σιδηροδρομικό σημείο αναφοράς -STR_ERROR_BRIDGE_TOO_LOW_FOR_ROAD_WAYPOINT :{WHITE}Η γέφυρα είναι πολύ χαμηλή για οδικό σημείο αναφοράς -STR_ERROR_BRIDGE_TOO_LOW_FOR_LOCK :{WHITE}Η γέφυρα είναι πολύ χαμηλή για κλείδωμα +STR_ERROR_BRIDGE_TOO_LOW_FOR_STATION :{WHITE}Η γέφυρα είναι {HEIGHT} πολύ χαμηλή για σταθμό +STR_ERROR_BRIDGE_TOO_LOW_FOR_ROADSTOP :{WHITE}Η γέφυρα είναι {HEIGHT} πολύ χαμηλή για οδική στάση +STR_ERROR_BRIDGE_TOO_LOW_FOR_DOCK :{WHITE}Η γέφυρα είναι {HEIGHT} πολύ χαμηλή για αποβάθρα +STR_ERROR_BRIDGE_TOO_LOW_FOR_BUOY :{WHITE}Η γέφυρα είναι {HEIGHT} πολύ χαμηλή για σημαδούρα +STR_ERROR_BRIDGE_TOO_LOW_FOR_RAIL_WAYPOINT :{WHITE}Η γέφυρα είναι {HEIGHT} πολύ χαμηλή για σιδηροδρομικό σημείο αναφοράς +STR_ERROR_BRIDGE_TOO_LOW_FOR_ROAD_WAYPOINT :{WHITE}Η γέφυρα είναι {HEIGHT} πολύ χαμηλή για οδικό σημείο αναφοράς +STR_ERROR_BRIDGE_TOO_LOW_FOR_LOCK :{WHITE}Η γέφυρα είναι {HEIGHT} πολύ χαμηλή για κλείδωμα # Tunnel related errors STR_ERROR_CAN_T_BUILD_TUNNEL_HERE :{WHITE}Δεν μπορεί να κατασκευαστεί σήραγγα εδώ... diff --git a/src/lang/hebrew.txt b/src/lang/hebrew.txt index 403a05aa87261..fe2efa775ce2e 100644 --- a/src/lang/hebrew.txt +++ b/src/lang/hebrew.txt @@ -1939,7 +1939,7 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_SI :בינלאומ STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT :יחידות גובה: {STRING} STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_HELPTEXT :כאשר מוצגים גבהים השתמש ביחידות שנבחרו -###length 3 +###length 4 STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_IMPERIAL :בריטית (רגל) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_METRIC :מטרי (מטר) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_SI :SI (מטר) @@ -3045,6 +3045,8 @@ STR_MAPGEN_SOUTHWEST :{BLACK}דרום STR_MAPGEN_BORDER_FREEFORM :{BLACK}יד חופשית STR_MAPGEN_BORDER_WATER :{BLACK}מים STR_MAPGEN_BORDER_RANDOM :{BLACK}אקראי + +###length 3 STR_MAPGEN_BORDER_RANDOMIZE :{BLACK}אקראי STR_MAPGEN_BORDER_MANUAL :{BLACK}ידני @@ -3080,7 +3082,6 @@ STR_GENERATION_LANDSCAPE_GENERATION :{BLACK}יציר STR_GENERATION_RIVER_GENERATION :{BLACK}יצירת נהרות STR_GENERATION_CLEARING_TILES :{BLACK}יצירת איזורים סלעיים STR_GENERATION_TOWN_GENERATION :{BLACK}יצירת עיירה -STR_GENERATION_INDUSTRY_GENERATION :{BLACK}יצירת תעשייה STR_GENERATION_OBJECT_GENERATION :{BLACK}יצירת מבנים בלתי ניידים STR_GENERATION_TREE_GENERATION :{BLACK}יצירת עצים STR_GENERATION_SETTINGUP_GAME :{BLACK}קביעת הגדרות המשחק @@ -3278,7 +3279,6 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}הכנס # Town directory window STR_TOWN_DIRECTORY_NONE :{ORANGE}- אין - STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) -STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (City){BLACK} ({COMMA}) STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}שמות ערים - לחץ על שם כדי למקד את התצוגה על העיר. Ctrl+לחיצה פותח חלונית תצוגה חדשה על מיקום העיר STR_TOWN_POPULATION :{BLACK}אוכלוסיית העולם: {COMMA} diff --git a/src/lang/hindi.txt b/src/lang/hindi.txt index 658351a121015..c103ddcb04793 100644 --- a/src/lang/hindi.txt +++ b/src/lang/hindi.txt @@ -719,7 +719,7 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_SI :अंतर् ###length 3 -###length 3 +###length 4 STR_CONFIG_SETTING_INTERFACE_GENERAL :सामान्य STR_CONFIG_SETTING_COMPANY :कंपनी @@ -1004,6 +1004,8 @@ STR_MAPGEN_TOWN_NAME_ITALIAN :इटैलि STR_MAPGEN_BORDER_WATER :{BLACK}जल STR_MAPGEN_BORDER_RANDOM :{BLACK}यादृच्छिक +###length 3 + # SE Map generation diff --git a/src/lang/hungarian.txt b/src/lang/hungarian.txt index 69da51259765a..0898e35329e24 100644 --- a/src/lang/hungarian.txt +++ b/src/lang/hungarian.txt @@ -317,6 +317,7 @@ STR_UNITS_FORCE_SI :{DECIMAL}{NBSP} STR_UNITS_HEIGHT_IMPERIAL :{DECIMAL}{NBSP}láb STR_UNITS_HEIGHT_METRIC :{DECIMAL}{NBSP}m STR_UNITS_HEIGHT_SI :{DECIMAL}{NBSP}m +STR_UNITS_HEIGHT_GAMEUNITS :{DECIMAL}{NBSP}szint # Time units used in string control characters STR_UNITS_DAYS :{COMMA}{NBSP}nap @@ -1404,7 +1405,7 @@ STR_CONFIG_SETTING_SUBSIDY_DURATION_VALUE :{UNITS_YEARS_OR STR_CONFIG_SETTING_SUBSIDY_DURATION_DISABLED :Nincsenek támogatások STR_CONFIG_SETTING_CONSTRUCTION_COSTS :Építkezési költségek: {STRING} -STR_CONFIG_SETTING_CONSTRUCTION_COSTS_HELPTEXT :Építkezések és beszerzésk költségeinek szintje +STR_CONFIG_SETTING_CONSTRUCTION_COSTS_HELPTEXT :Építkezések és beszerzések költségeinek szintje ###length 3 STR_CONFIG_SETTING_CONSTRUCTION_COSTS_LOW :Alacsony STR_CONFIG_SETTING_CONSTRUCTION_COSTS_MEDIUM :Közepes @@ -2222,10 +2223,11 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_SI :SI (kN) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT :Hosszúság mértékegysége: {STRING} STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_HELPTEXT :A magassági értékek a kiválasztott mértékegységben fognak megjelenni a felhasználói felületen -###length 3 +###length 4 STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_IMPERIAL :Angolszász (láb) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_METRIC :Metrikus (m) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_SI :SI (m) +STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_GAMEUNITS :Játékbeli mértékegység (szint) STR_CONFIG_SETTING_LOCALISATION :Honosítás STR_CONFIG_SETTING_GRAPHICS :Megjelenés @@ -3412,6 +3414,8 @@ STR_SAVELOAD_DETAIL_GRFSTATUS :{SILVER}NewGRF: STR_SAVELOAD_FILTER_TITLE :{BLACK}Szűrő: STR_SAVELOAD_OVERWRITE_TITLE :{WHITE}Fájl felülírása STR_SAVELOAD_OVERWRITE_WARNING :{YELLOW}Biztos vagy benne, hogy felülírod a létező fájlt? +STR_SAVELOAD_DELETE_TITLE :{WHITE}Fájl törlése +STR_SAVELOAD_DELETE_WARNING :{YELLOW}Biztosan törölni akarod ezt a fájlt? STR_SAVELOAD_DIRECTORY :{STRING} (Könyvtár) STR_SAVELOAD_PARENT_DIRECTORY :{STRING} (Szülőkönyvtár) @@ -3487,11 +3491,18 @@ STR_MAPGEN_NORTHWEST :{BLACK}Északny STR_MAPGEN_NORTHEAST :{BLACK}Északkelet STR_MAPGEN_SOUTHEAST :{BLACK}Délkelet STR_MAPGEN_SOUTHWEST :{BLACK}Délnyugat +STR_MAPGEN_NORTHWEST_TOOLTIP :Víz vagy szabad formájú térképszél bekapcsolása a térkép északnyugati szélén +STR_MAPGEN_NORTHEAST_TOOLTIP :Víz vagy szabad formájú térképszél bekapcsolása a térkép északkeleti szélén +STR_MAPGEN_SOUTHEAST_TOOLTIP :Víz vagy szabad formájú térképszél bekapcsolása a térkép délkeleti szélén +STR_MAPGEN_SOUTHWEST_TOOLTIP :Víz vagy szabad formájú térképszél bekapcsolása a térkép délnyugati szélén STR_MAPGEN_BORDER_FREEFORM :{BLACK}Szárazföld STR_MAPGEN_BORDER_WATER :{BLACK}Víz STR_MAPGEN_BORDER_RANDOM :{BLACK}Véletlen -STR_MAPGEN_BORDER_RANDOMIZE :{BLACK}Véletlen -STR_MAPGEN_BORDER_MANUAL :{BLACK}Kézi + +###length 3 +STR_MAPGEN_BORDER_RANDOMIZE :Véletlen +STR_MAPGEN_BORDER_MANUAL :Kézi +STR_MAPGEN_BORDER_INFINITE_WATER :Végtelen víz STR_MAPGEN_HEIGHTMAP_ROTATION :{BLACK}Magasságtérkép elforgatása: STR_MAPGEN_HEIGHTMAP_NAME :{BLACK}Magasságtérkép neve: @@ -3530,7 +3541,8 @@ STR_GENERATION_LANDSCAPE_GENERATION :{BLACK}Tájkép STR_GENERATION_RIVER_GENERATION :{BLACK}Folyó generálás STR_GENERATION_CLEARING_TILES :{BLACK}Durva és köves területek generálása STR_GENERATION_TOWN_GENERATION :{BLACK}Város generálás -STR_GENERATION_INDUSTRY_GENERATION :{BLACK}Ipar generálás +STR_GENERATION_LAND_INDUSTRY_GENERATION :{BLACK}Szárazföldi ipar generálás +STR_GENERATION_WATER_INDUSTRY_GENERATION :{BLACK}Vízi ipar generálás STR_GENERATION_OBJECT_GENERATION :{BLACK}Mozgathatatlan létesítmények létrehozása STR_GENERATION_TREE_GENERATION :{BLACK}Fák generálása STR_GENERATION_SETTINGUP_GAME :{BLACK}Játék beállítása @@ -3750,7 +3762,7 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}Felirat STR_TOWN_DIRECTORY_CAPTION :{WHITE}Városok ({COMMA}, {COMMA}) STR_TOWN_DIRECTORY_NONE :{ORANGE}- Nincs - STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) -STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (Város){BLACK} ({COMMA}) +STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{BLACK} ({COMMA}) {YELLOW}{CITY_ICON} STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}Városnevek - kattints egy névre a város megnézéséhez. Ctrl+kattintással új nézet nyílik a városnál STR_TOWN_POPULATION :{BLACK}Világnépesség: {COMMA} @@ -4247,6 +4259,7 @@ STR_PURCHASE_INFO_ALL_BUT :Mindenre, kivé STR_PURCHASE_INFO_MAX_TE :{BLACK}Maximális vonóerő: {GOLD}{FORCE} STR_PURCHASE_INFO_AIRCRAFT_RANGE :{BLACK}Hatótávolság: {GOLD}{COMMA} mező STR_PURCHASE_INFO_AIRCRAFT_TYPE :{BLACK}Típus: {GOLD}{STRING} +STR_PURCHASE_INFO_RAILTYPES :{BLACK}Sín típusok: {GOLD}{STRING} ###length 3 STR_CARGO_TYPE_FILTER_ALL :Minden rakománytípus @@ -4430,6 +4443,7 @@ STR_ENGINE_PREVIEW_RUNCOST_YEAR :Üzemeletetés: STR_ENGINE_PREVIEW_RUNCOST_PERIOD :Üzemeltetés: {CURRENCY_LONG}/időszak STR_ENGINE_PREVIEW_CAPACITY :Kapacitás: {CARGO_LONG} STR_ENGINE_PREVIEW_CAPACITY_2 :Kapacitás: {CARGO_LONG}, {CARGO_LONG} +STR_ENGINE_PREVIEW_RAILTYPES :Sín típusok: {STRING} # Autoreplace window STR_REPLACE_VEHICLES_WHITE :{WHITE}{STRING} lecserélése - {STRING} @@ -5326,12 +5340,13 @@ STR_ERROR_START_AND_END_MUST_BE_IN :{WHITE}A kezdet STR_ERROR_ENDS_OF_BRIDGE_MUST_BOTH :{WHITE}... a híd mindkét végének szárazföldön kell lennie STR_ERROR_BRIDGE_TOO_LONG :{WHITE}... a híd túl hosszú STR_ERROR_BRIDGE_THROUGH_MAP_BORDER :{WHITE}A híd a térképen túl végződne -STR_ERROR_BRIDGE_TOO_LOW_FOR_STATION :{WHITE}A híd túl alacsony az állomáshoz -STR_ERROR_BRIDGE_TOO_LOW_FOR_ROADSTOP :{WHITE}A híd túl alacsony a megállóhoz -STR_ERROR_BRIDGE_TOO_LOW_FOR_DOCK :{WHITE}A híd túl alacsony a kikötőhöz -STR_ERROR_BRIDGE_TOO_LOW_FOR_BUOY :{WHITE}A híd túl alacsony a bójához -STR_ERROR_BRIDGE_TOO_LOW_FOR_RAIL_WAYPOINT :{WHITE}A híd túl alacsony a vasúti ellenőrzőponthoz -STR_ERROR_BRIDGE_TOO_LOW_FOR_ROAD_WAYPOINT :{WHITE}BA híd túl alacsony az útponthoz +STR_ERROR_BRIDGE_TOO_LOW_FOR_STATION :{WHITE}A híd {HEIGHT} magas, túl alacsony az állomáshoz +STR_ERROR_BRIDGE_TOO_LOW_FOR_ROADSTOP :{WHITE}A híd {HEIGHT} magas, túl alacsony a megállóhoz +STR_ERROR_BRIDGE_TOO_LOW_FOR_DOCK :{WHITE}A híd {HEIGHT} magas, túl alacsony a kikötőhöz +STR_ERROR_BRIDGE_TOO_LOW_FOR_BUOY :{WHITE}A híd {HEIGHT} magas, túl alacsony a bójához +STR_ERROR_BRIDGE_TOO_LOW_FOR_RAIL_WAYPOINT :{WHITE}A híd {HEIGHT} magas, túl alacsony a vasúti ellenőrzőponthoz +STR_ERROR_BRIDGE_TOO_LOW_FOR_ROAD_WAYPOINT :{WHITE}A híd {HEIGHT} magas, túl alacsony az útponthoz +STR_ERROR_BRIDGE_TOO_LOW_FOR_LOCK :{WHITE}A híd {HEIGHT} magas, túl alacsony a zároláshoz # Tunnel related errors STR_ERROR_CAN_T_BUILD_TUNNEL_HERE :{WHITE}Nem áshatsz ide alagutat... diff --git a/src/lang/icelandic.txt b/src/lang/icelandic.txt index 8bcd7bb027cc6..d76cab670b860 100644 --- a/src/lang/icelandic.txt +++ b/src/lang/icelandic.txt @@ -1700,7 +1700,7 @@ STR_CONFIG_SETTING_CITY_SIZE_MULTIPLIER_HELPTEXT :Meðalstærð b ###length 3 -###length 3 +###length 4 STR_CONFIG_SETTING_SOUND :Hljóð STR_CONFIG_SETTING_INTERFACE :Viðmót @@ -2630,6 +2630,8 @@ STR_MAPGEN_SOUTHWEST :{BLACK}Suðvest STR_MAPGEN_BORDER_FREEFORM :{BLACK}Frjálsar STR_MAPGEN_BORDER_WATER :{BLACK}Vatn STR_MAPGEN_BORDER_RANDOM :{BLACK}Slembin + +###length 3 STR_MAPGEN_BORDER_RANDOMIZE :{BLACK}Slembnar STR_MAPGEN_BORDER_MANUAL :{BLACK}Forvaldar diff --git a/src/lang/ido.txt b/src/lang/ido.txt index b66649307a809..6a2107860f1eb 100644 --- a/src/lang/ido.txt +++ b/src/lang/ido.txt @@ -822,7 +822,7 @@ STR_CONFIG_SETTING_SMALLMAP_LAND_COLOUR_VIOLET :Violkolora ###length 3 -###length 3 +###length 4 @@ -1071,6 +1071,8 @@ STR_MAPGEN_BY :{BLACK}* # Strings for map borders at game generation +###length 3 + # SE Map generation diff --git a/src/lang/indonesian.txt b/src/lang/indonesian.txt index 606976eaaed89..4f6fb8ee18951 100644 --- a/src/lang/indonesian.txt +++ b/src/lang/indonesian.txt @@ -2056,7 +2056,7 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_SI :SI (kN) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT :Satuan ketinggian: {STRING} STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_HELPTEXT :Apabila ketinggian ditampilkan di antarmuka, nyatakan di satuan yang dipilih -###length 3 +###length 4 STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_IMPERIAL :Imperial (ft) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_METRIC :Metrik (m) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_SI :SI (m) @@ -3240,6 +3240,8 @@ STR_MAPGEN_SOUTHWEST :{BLACK}Barat Da STR_MAPGEN_BORDER_FREEFORM :{BLACK}Bebas STR_MAPGEN_BORDER_WATER :{BLACK}Perairan STR_MAPGEN_BORDER_RANDOM :{BLACK}Acak + +###length 3 STR_MAPGEN_BORDER_RANDOMIZE :{BLACK}Acak STR_MAPGEN_BORDER_MANUAL :{BLACK}Manual @@ -3485,7 +3487,6 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}Masukkan # Town directory window STR_TOWN_DIRECTORY_NONE :{ORANGE}- Tidak Ada - STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) -STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (Kota){BLACK} ({COMMA}) STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}Nama-nama kota - Klik pada nama untuk mengarahkan pandangan utama pada kota. Ctrl+Click akan membuka viewport baru pada lokasi kota STR_TOWN_POPULATION :{BLACK}Populasi Dunia: {COMMA} diff --git a/src/lang/irish.txt b/src/lang/irish.txt index 5bb301b9ee614..c11a13d9b35a0 100644 --- a/src/lang/irish.txt +++ b/src/lang/irish.txt @@ -1913,7 +1913,7 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_SI :SI (kN) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT :Aonaid airde: {STRING} STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_HELPTEXT :Aon áit a thaispeántar airde sa chomhéadan úsáideora, taispeain sna haonaid roghnaithe í -###length 3 +###length 4 STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_IMPERIAL :Impiriúil (tr) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_METRIC :Méadrach (m) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_SI :SI (m) @@ -3043,6 +3043,8 @@ STR_MAPGEN_SOUTHWEST :{BLACK}Iardheis STR_MAPGEN_BORDER_FREEFORM :{BLACK}Saorfhoirme STR_MAPGEN_BORDER_WATER :{BLACK}Uisce STR_MAPGEN_BORDER_RANDOM :{BLACK}Randamach + +###length 3 STR_MAPGEN_BORDER_RANDOMIZE :{BLACK}Randamach STR_MAPGEN_BORDER_MANUAL :{BLACK}De láimh @@ -3279,7 +3281,6 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}Iontrái # Town directory window STR_TOWN_DIRECTORY_NONE :{ORANGE}- Ceann ar bith - STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) -STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (Cathair){BLACK} ({COMMA}) STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}Ainmneacha bailte - cliceáil ar ainm le go mbeidh an baile i lár an scáileán. Osclaítear amharc nua ar shuíomh an bhaile le Ctrl+Cliceáil STR_TOWN_POPULATION :{BLACK}Daonra domhanda: {COMMA} diff --git a/src/lang/italian.txt b/src/lang/italian.txt index e3f80fa5c2c6a..7ed8445e02947 100644 --- a/src/lang/italian.txt +++ b/src/lang/italian.txt @@ -2172,7 +2172,7 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_SI :SI (kN) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT :Unità di altezza: {STRING} STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_HELPTEXT :Seleziona le unità di misura da utilizzare per mostrare le altezze nell'interfaccia utente -###length 3 +###length 4 STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_IMPERIAL :Imperiali (piedi) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_METRIC :Metriche (m) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_SI :SI (m) @@ -3428,6 +3428,8 @@ STR_MAPGEN_SOUTHWEST :{BLACK}Sud-oves STR_MAPGEN_BORDER_FREEFORM :{BLACK}Variabile STR_MAPGEN_BORDER_WATER :{BLACK}Acqua STR_MAPGEN_BORDER_RANDOM :{BLACK}Casuale + +###length 3 STR_MAPGEN_BORDER_RANDOMIZE :{BLACK}Casuale STR_MAPGEN_BORDER_MANUAL :{BLACK}Manuale @@ -3467,7 +3469,6 @@ STR_GENERATION_WORLD_GENERATION :{BLACK}Generazi STR_GENERATION_LANDSCAPE_GENERATION :{BLACK}Generazione paesaggio STR_GENERATION_RIVER_GENERATION :{BLACK}Generazione fiumi STR_GENERATION_CLEARING_TILES :{BLACK}Generazione aree brulle e rocciose -STR_GENERATION_INDUSTRY_GENERATION :{BLACK}Generazione industrie STR_GENERATION_OBJECT_GENERATION :{BLACK}Generazione oggetti inamovibili STR_GENERATION_TREE_GENERATION :{BLACK}Generazione alberi STR_GENERATION_SETTINGUP_GAME :{BLACK}Impostazione partita @@ -3680,7 +3681,6 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}Inserire # Town directory window STR_TOWN_DIRECTORY_NONE :{ORANGE}- Nessuna - STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) -STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (Metropoli){BLACK} ({COMMA}) STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}Nomi delle città - fare clic su un nome per centrare la visuale principale sulla città. Ctrl+Clic per aprire una nuova finestra di visualizzazione sulla posizione della città STR_TOWN_POPULATION :{BLACK}Popolazione mondiale: {COMMA} @@ -5246,7 +5246,6 @@ STR_ERROR_START_AND_END_MUST_BE_IN :{WHITE}Inizio e STR_ERROR_ENDS_OF_BRIDGE_MUST_BOTH :{WHITE}... gli estremi del ponte devono trovarsi entrambi sul terreno STR_ERROR_BRIDGE_TOO_LONG :{WHITE}... ponte troppo lungo STR_ERROR_BRIDGE_THROUGH_MAP_BORDER :{WHITE}Il ponte terminerebbe fuori dalla mappa -STR_ERROR_BRIDGE_TOO_LOW_FOR_ROADSTOP :{WHITE}Ponte troppo basso per una fermata # Tunnel related errors STR_ERROR_CAN_T_BUILD_TUNNEL_HERE :{WHITE}Impossibile costruire il tunnel qui... diff --git a/src/lang/japanese.txt b/src/lang/japanese.txt index f5170ca57f059..61999a9fbe93e 100644 --- a/src/lang/japanese.txt +++ b/src/lang/japanese.txt @@ -2011,7 +2011,7 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_SI :国際単位系 STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT :距離単位: {STRING} STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_HELPTEXT :ゲーム中の高度をいずれの単位系で表すか決定します -###length 3 +###length 4 STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_IMPERIAL :ヤード・ポンド法 (フィート(ft)) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_METRIC :メートル法 (m) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_SI :国際単位系 (m) @@ -3176,6 +3176,8 @@ STR_MAPGEN_SOUTHWEST :{BLACK}南西 STR_MAPGEN_BORDER_FREEFORM :{BLACK}自由形成 STR_MAPGEN_BORDER_WATER :{BLACK}水域 STR_MAPGEN_BORDER_RANDOM :{BLACK}ランダム + +###length 3 STR_MAPGEN_BORDER_RANDOMIZE :{BLACK}ランダム設定 STR_MAPGEN_BORDER_MANUAL :{BLACK}手動設定 @@ -3422,7 +3424,6 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}標識 STR_TOWN_DIRECTORY_CAPTION :{WHITE}街一覧 ({COMMA} の {COMMA}) STR_TOWN_DIRECTORY_NONE :{ORANGE}- なし- STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) -STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (都市){BLACK} ({COMMA}) STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}街の名前 - メイン画面を街の場所に移動するには名前をクリックします。Ctrl+クリックで新しいビューポートに表示します STR_TOWN_POPULATION :{BLACK}地域人口: {COMMA}人 diff --git a/src/lang/korean.txt b/src/lang/korean.txt index 9ad3186e14b12..e79cf65ee7147 100644 --- a/src/lang/korean.txt +++ b/src/lang/korean.txt @@ -255,6 +255,7 @@ STR_UNITS_FORCE_SI :{DECIMAL}kN STR_UNITS_HEIGHT_IMPERIAL :{DECIMAL}피트 STR_UNITS_HEIGHT_METRIC :{DECIMAL}m STR_UNITS_HEIGHT_SI :{DECIMAL}m +STR_UNITS_HEIGHT_GAMEUNITS :{DECIMAL}층 # Time units used in string control characters STR_UNITS_DAYS :{COMMA}일 @@ -2159,10 +2160,11 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_SI :국제표준규 STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT :높이 단위: {STRING} STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_HELPTEXT :높이를 표시할 때 선택한 단위를 사용하여 나타냅니다 -###length 3 +###length 4 STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_IMPERIAL :야드파운드법 (ft) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_METRIC :미터법 (m) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_SI :국제표준규격 (m) +STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_GAMEUNITS :게임 단위 (층) STR_CONFIG_SETTING_LOCALISATION :단위 설정 STR_CONFIG_SETTING_GRAPHICS :그래픽 @@ -3426,11 +3428,18 @@ STR_MAPGEN_NORTHWEST :{BLACK}북서 STR_MAPGEN_NORTHEAST :{BLACK}북동 STR_MAPGEN_SOUTHEAST :{BLACK}남동 STR_MAPGEN_SOUTHWEST :{BLACK}남서 +STR_MAPGEN_NORTHWEST_TOOLTIP :남서쪽 지도 맨 가장자리를 물로 할지 육지로 할지 고릅니다 +STR_MAPGEN_NORTHEAST_TOOLTIP :북동쪽 지도 맨 가장자리를 물로 할지 육지로 할지 고릅니다 +STR_MAPGEN_SOUTHEAST_TOOLTIP :남동쪽 지도 맨 가장자리를 물로 할지 육지로 할지 고릅니다 +STR_MAPGEN_SOUTHWEST_TOOLTIP :남서쪽 지도 맨 가장자리를 물로 할지 육지로 할지 고릅니다 STR_MAPGEN_BORDER_FREEFORM :{BLACK}변경 가능 STR_MAPGEN_BORDER_WATER :{BLACK}물 STR_MAPGEN_BORDER_RANDOM :{BLACK}임의 -STR_MAPGEN_BORDER_RANDOMIZE :{BLACK}임의 -STR_MAPGEN_BORDER_MANUAL :{BLACK}사용자 정의 + +###length 3 +STR_MAPGEN_BORDER_RANDOMIZE :임의 +STR_MAPGEN_BORDER_MANUAL :사용자 정의 +STR_MAPGEN_BORDER_INFINITE_WATER :물 (지도 밖까지 모두) STR_MAPGEN_HEIGHTMAP_ROTATION :{BLACK}높이맵 방향: STR_MAPGEN_HEIGHTMAP_NAME :{BLACK}높이맵 이름: @@ -3469,7 +3478,8 @@ STR_GENERATION_LANDSCAPE_GENERATION :{BLACK}지형 STR_GENERATION_RIVER_GENERATION :{BLACK}강 제작 STR_GENERATION_CLEARING_TILES :{BLACK}거친 암석지대 만드는 중 STR_GENERATION_TOWN_GENERATION :{BLACK}도시 생성 -STR_GENERATION_INDUSTRY_GENERATION :{BLACK}산업시설 생성 +STR_GENERATION_LAND_INDUSTRY_GENERATION :{BLACK}지상 산업시설 생성 +STR_GENERATION_WATER_INDUSTRY_GENERATION :{BLACK}수상 산업시설 생성 STR_GENERATION_OBJECT_GENERATION :{BLACK}움직일수 없는 객체 만드는 중 STR_GENERATION_TREE_GENERATION :{BLACK}나무 심는 중 STR_GENERATION_SETTINGUP_GAME :{BLACK}게임 설정 중 @@ -3689,7 +3699,7 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}팻말 STR_TOWN_DIRECTORY_CAPTION :{WHITE}도시 목록 ({1:COMMA}개 중 {0:COMMA}개) STR_TOWN_DIRECTORY_NONE :{ORANGE}(없음) STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) -STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (대도시){BLACK} ({COMMA}) +STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{BLACK} ({COMMA}) {YELLOW}{CITY_ICON} STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}도시 이름 - 이 도시로 시점을 변경하려면 클릭하세요. CTRL+클릭하면 이 도시 위치를 기준으로 새로운 외부 화면을 엽니다 STR_TOWN_POPULATION :{BLACK}총 인구 수: {COMMA} @@ -5267,13 +5277,13 @@ STR_ERROR_START_AND_END_MUST_BE_IN :{WHITE}시작 STR_ERROR_ENDS_OF_BRIDGE_MUST_BOTH :{WHITE}... 다리의 양 끝은 모두 땅이어야 합니다 STR_ERROR_BRIDGE_TOO_LONG :{WHITE}... 다리가 너무 깁니다! STR_ERROR_BRIDGE_THROUGH_MAP_BORDER :{WHITE}다리 끝이 지도 밖을 넘어갑니다 -STR_ERROR_BRIDGE_TOO_LOW_FOR_STATION :{WHITE}다리 밑에 역을 두기에는 다리 높이가 너무 낮습니다 -STR_ERROR_BRIDGE_TOO_LOW_FOR_ROADSTOP :{WHITE}다리 밑에 도로 정류장을 두기에는 다리 높이가 너무 낮습니다 -STR_ERROR_BRIDGE_TOO_LOW_FOR_DOCK :{WHITE}다리 밑에 항구를 두기에는 다리 높이가 너무 낮습니다 -STR_ERROR_BRIDGE_TOO_LOW_FOR_BUOY :{WHITE}다리 밑에 부표를 두기에는 다리 높이가 너무 낮습니다 -STR_ERROR_BRIDGE_TOO_LOW_FOR_RAIL_WAYPOINT :{WHITE}다리 밑에 철도 경유지를 두기에는 다리 높이가 너무 낮습니다 -STR_ERROR_BRIDGE_TOO_LOW_FOR_ROAD_WAYPOINT :{WHITE}다리 밑에 도로 경유지를 두기에는 다리 높이가 너무 낮습니다 -STR_ERROR_BRIDGE_TOO_LOW_FOR_LOCK :{WHITE}다리 밑에 항구를 두기에는 다리 높이가 너무 낮습니다 +STR_ERROR_BRIDGE_TOO_LOW_FOR_STATION :{WHITE}다리 밑에 역을 두기에는 다리 높이가 {HEIGHT}만큼 낮습니다 +STR_ERROR_BRIDGE_TOO_LOW_FOR_ROADSTOP :{WHITE}다리 밑에 도로 정류장을 두기에는 다리 높이가 {HEIGHT}만큼 낮습니다 +STR_ERROR_BRIDGE_TOO_LOW_FOR_DOCK :{WHITE}다리 밑에 항구를 두기에는 다리 높이가 {HEIGHT}만큼 낮습니다 +STR_ERROR_BRIDGE_TOO_LOW_FOR_BUOY :{WHITE}다리 밑에 부표를 두기에는 다리 높이가 {HEIGHT}만큼 낮습니다 +STR_ERROR_BRIDGE_TOO_LOW_FOR_RAIL_WAYPOINT :{WHITE}다리 밑에 철도 경유지를 두기에는 다리 높이가 {HEIGHT}만큼 낮습니다 +STR_ERROR_BRIDGE_TOO_LOW_FOR_ROAD_WAYPOINT :{WHITE}다리 밑에 도로 경유지를 두기에는 다리 높이가 {HEIGHT}만큼 낮습니다 +STR_ERROR_BRIDGE_TOO_LOW_FOR_LOCK :{WHITE}다리 밑에 항구를 두기에는 다리 높이가 {HEIGHT}만큼 낮습니다 # Tunnel related errors STR_ERROR_CAN_T_BUILD_TUNNEL_HERE :{WHITE}여기에 터널을 지을 수 없습니다... diff --git a/src/lang/latin.txt b/src/lang/latin.txt index 76eaa9afea59c..43c99cba6036b 100644 --- a/src/lang/latin.txt +++ b/src/lang/latin.txt @@ -2013,7 +2013,7 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_SI :SI (kN) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT :Unitates altitudinis: {STRING} STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_HELPTEXT :Quandocumque altitudo monstratur, monstrabitur his unitatibus electis -###length 3 +###length 4 STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_IMPERIAL :Anglicae (ft) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_METRIC :Metricae (m) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_SI :SI (m) @@ -3000,6 +3000,8 @@ STR_MAPGEN_SOUTHWEST :{BLACK}Africus STR_MAPGEN_BORDER_FREEFORM :{BLACK}Quilibet STR_MAPGEN_BORDER_WATER :{BLACK}Aqua STR_MAPGEN_BORDER_RANDOM :{BLACK}Fortuiti + +###length 3 STR_MAPGEN_BORDER_RANDOMIZE :{BLACK}Fortuiti STR_MAPGEN_BORDER_MANUAL :{BLACK}Manu @@ -3232,7 +3234,6 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}Inscribe # Town directory window STR_TOWN_DIRECTORY_NONE :{ORANGE}- Nulla - STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) -STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (Urbs){BLACK} ({COMMA}) STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}Nomina oppidorum - preme in nomen ut conspectus supra oppidum locetur. Ctrl+Preme ut novam fenestram conspectus supra oppidum aperiatur STR_TOWN_POPULATION :{BLACK}Incolae mundi: {COMMA} diff --git a/src/lang/latvian.txt b/src/lang/latvian.txt index a342fe2b9b565..8422f4c211919 100644 --- a/src/lang/latvian.txt +++ b/src/lang/latvian.txt @@ -2162,7 +2162,7 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_SI :SI, starptautis STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT :Augstuma mērvienības: {STRING} STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_HELPTEXT :Kad lietotāja saskarnē rāda augstumu, uzrādīt to norādītajās mērvienībās -###length 3 +###length 4 STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_IMPERIAL :impērijas, britu (pēda) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_METRIC :metriskās (m) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_SI :SI, starptautiskās (m) @@ -3353,6 +3353,8 @@ STR_SAVELOAD_DETAIL_GRFSTATUS :{SILVER}NewGRF: STR_SAVELOAD_FILTER_TITLE :{BLACK}Filtrs: STR_SAVELOAD_OVERWRITE_TITLE :{WHITE}Pārrakstīt datni STR_SAVELOAD_OVERWRITE_WARNING :{YELLOW}Vai tiešām vēlaties pārrakstīt esošās datnes? +STR_SAVELOAD_DELETE_TITLE :{WHITE}Dzēst Failu +STR_SAVELOAD_DELETE_WARNING :{YELLOW}Vai tiešām vēlaties dzēst failu? STR_SAVELOAD_DIRECTORY :{STRING} (Vietne) STR_SAVELOAD_PARENT_DIRECTORY :{STRING} (Īpašnieka katalogs) @@ -3431,8 +3433,11 @@ STR_MAPGEN_SOUTHWEST :{BLACK}Dienvidr STR_MAPGEN_BORDER_FREEFORM :{BLACK}Brīvā forma STR_MAPGEN_BORDER_WATER :{BLACK}Ūdens STR_MAPGEN_BORDER_RANDOM :{BLACK}Nejauša -STR_MAPGEN_BORDER_RANDOMIZE :{BLACK}Nejaušas -STR_MAPGEN_BORDER_MANUAL :{BLACK}Manuāli + +###length 3 +STR_MAPGEN_BORDER_RANDOMIZE :Nejaušas +STR_MAPGEN_BORDER_MANUAL :Manuāli +STR_MAPGEN_BORDER_INFINITE_WATER :Bezgalīgs Ūdens STR_MAPGEN_HEIGHTMAP_ROTATION :{BLACK}Augstumu kartes pagriešana: STR_MAPGEN_HEIGHTMAP_NAME :{BLACK}Augstumu kartes nosaukums: @@ -3471,7 +3476,6 @@ STR_GENERATION_LANDSCAPE_GENERATION :{BLACK}Ainavu v STR_GENERATION_RIVER_GENERATION :{BLACK}Upes radīšana STR_GENERATION_CLEARING_TILES :{BLACK}Nelīdzena un akmeņaina apvidus radīšana STR_GENERATION_TOWN_GENERATION :{BLACK}Pilsētas veidošana -STR_GENERATION_INDUSTRY_GENERATION :{BLACK}Nozares veidošana STR_GENERATION_OBJECT_GENERATION :{BLACK}Objekta radīšana STR_GENERATION_TREE_GENERATION :{BLACK}Koka radīšana STR_GENERATION_SETTINGUP_GAME :{BLACK}Iestatīt spēli @@ -3694,7 +3698,7 @@ STR_TOWN_DIRECTORY_CAPTION :{WHITE}Pilsēta STR_TOWN_DIRECTORY_NONE :{G=m}{ORANGE}- Neviens - STR_TOWN_DIRECTORY_NONE.kas :{ORANGE}- Neviena - STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) -STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (Pilsēta){BLACK} ({COMMA}) +STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{BLACK} ({COMMA}) {YELLOW}{CITY_ICON} STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}Pilsētu nosaukumi - klikšķināt uz nosaukuma, lai centrētu skatu uz to.Ctrl+klikšķis atvērs skatu uz pilsētu jaunā skatlaukā STR_TOWN_POPULATION :{BLACK}Pasaules iedzīvotāju skaits: {COMMA} @@ -4194,6 +4198,7 @@ STR_PURCHASE_INFO_ALL_BUT :visu, izņemot STR_PURCHASE_INFO_MAX_TE :{BLACK}Maksimālais vilces spēks: {GOLD}{FORCE} STR_PURCHASE_INFO_AIRCRAFT_RANGE :{BLACK}Apgabas: {GOLD}{COMMA} lauciņi STR_PURCHASE_INFO_AIRCRAFT_TYPE :{BLACK}Lidaparāta veids: {GOLD}{STRING} +STR_PURCHASE_INFO_RAILTYPES :{BLACK}Sliežu veidi: {GOLD}{STRING} ###length 3 STR_CARGO_TYPE_FILTER_ALL :Visi kravu veidi @@ -4377,6 +4382,7 @@ STR_ENGINE_PREVIEW_RUNCOST_YEAR :Darbības izmak STR_ENGINE_PREVIEW_RUNCOST_PERIOD :Darbības izmaksas: {CURRENCY_LONG}/periodā STR_ENGINE_PREVIEW_CAPACITY :Ietilpība: {CARGO_LONG} STR_ENGINE_PREVIEW_CAPACITY_2 :Ietilpība: {CARGO_LONG}, {CARGO_LONG} +STR_ENGINE_PREVIEW_RAILTYPES :Sliežu veidi: {STRING} # Autoreplace window STR_REPLACE_VEHICLES_WHITE :{WHITE}Nomainīt {STRING} - {STRING} @@ -5273,13 +5279,6 @@ STR_ERROR_START_AND_END_MUST_BE_IN :{WHITE}Sākumam STR_ERROR_ENDS_OF_BRIDGE_MUST_BOTH :{WHITE}... abiem tilta galiem jābūt uz zemes STR_ERROR_BRIDGE_TOO_LONG :{WHITE}... tilts ir pārāk garš STR_ERROR_BRIDGE_THROUGH_MAP_BORDER :{WHITE}Tilts beigtos ārpus kartes -STR_ERROR_BRIDGE_TOO_LOW_FOR_STATION :{WHITE}Tilts ir pārāk zems stacijai -STR_ERROR_BRIDGE_TOO_LOW_FOR_ROADSTOP :{WHITE}Tilts ir pārāk zems, ceļa pieturai -STR_ERROR_BRIDGE_TOO_LOW_FOR_DOCK :{WHITE}Tilts ir pārāk zems piestātnei -STR_ERROR_BRIDGE_TOO_LOW_FOR_BUOY :{WHITE}Tilts ir pārāk zems bojai -STR_ERROR_BRIDGE_TOO_LOW_FOR_RAIL_WAYPOINT :{WHITE}Tilts ir pārāk zems dzelzceļa pieturas punktam -STR_ERROR_BRIDGE_TOO_LOW_FOR_ROAD_WAYPOINT :{WHITE}Tilts ir pārāk zems ceļa punktam -STR_ERROR_BRIDGE_TOO_LOW_FOR_LOCK :{WHITE}Tilts ir pārāk zems slūžām # Tunnel related errors STR_ERROR_CAN_T_BUILD_TUNNEL_HERE :{WHITE}Šeit nevar būvēt tuneli... diff --git a/src/lang/lithuanian.txt b/src/lang/lithuanian.txt index 865935973c262..c4c4d96a55301 100644 --- a/src/lang/lithuanian.txt +++ b/src/lang/lithuanian.txt @@ -2274,7 +2274,7 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_SI :SI (kN) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT :Aukščio vienetai: {STRING} STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_HELPTEXT :Vienetai, kuriais matuojamas aukštis -###length 3 +###length 4 STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_IMPERIAL :imperiniai (ft) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_METRIC :metriniai (m) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_SI :SI (m) @@ -3463,6 +3463,8 @@ STR_MAPGEN_SOUTHWEST :{BLACK}Pietvaka STR_MAPGEN_BORDER_FREEFORM :{BLACK}Laisva forma STR_MAPGEN_BORDER_WATER :{BLACK}Vanduo STR_MAPGEN_BORDER_RANDOM :{BLACK}Atsitiktinis + +###length 3 STR_MAPGEN_BORDER_RANDOMIZE :{BLACK}Atsitiktiniai STR_MAPGEN_BORDER_MANUAL :{BLACK}Pasirinktiniai @@ -3501,7 +3503,6 @@ STR_GENERATION_LANDSCAPE_GENERATION :{BLACK}Peizažo STR_GENERATION_RIVER_GENERATION :{BLACK}Upių generavimas STR_GENERATION_CLEARING_TILES :{BLACK}Daubų ir uolų generacija STR_GENERATION_TOWN_GENERATION :{BLACK}Miestų generavimas -STR_GENERATION_INDUSTRY_GENERATION :{BLACK}Pramonės generavimas STR_GENERATION_OBJECT_GENERATION :{BLACK}Nejudinama generacija STR_GENERATION_TREE_GENERATION :{BLACK}Medžių generacija STR_GENERATION_SETTINGUP_GAME :{BLACK}Sukurti zaidima @@ -3714,7 +3715,6 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}Įrašyk STR_TOWN_DIRECTORY_CAPTION :{WHITE}Miestai ({COMMA} of {COMMA}) STR_TOWN_DIRECTORY_NONE :{ORANGE}Nėra STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) -STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (Miestas){BLACK} ({COMMA}) STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}Spragtelėjus ant pavadinimo, miestas bus parodytas ekrano centre. Spragtelėkite laikant nuspaudus „Ctrl“ klavišą, kad atverti papildomą peržiūros langą į pasirinktą miestą STR_TOWN_POPULATION :{BLACK}Pasaulio populiacija: {COMMA} diff --git a/src/lang/luxembourgish.txt b/src/lang/luxembourgish.txt index a1d3b19840213..81a43c962d74c 100644 --- a/src/lang/luxembourgish.txt +++ b/src/lang/luxembourgish.txt @@ -254,6 +254,7 @@ STR_UNITS_FORCE_SI :{DECIMAL}{NBSP} STR_UNITS_HEIGHT_IMPERIAL :{DECIMAL}{NBSP}ft STR_UNITS_HEIGHT_METRIC :{DECIMAL}{NBSP}m STR_UNITS_HEIGHT_SI :{DECIMAL}{NBSP}m +STR_UNITS_HEIGHT_GAMEUNITS :{DECIMAL}{NBSP}Niveau{P "" en} # Time units used in string control characters STR_UNITS_DAYS :{COMMA}{NBSP}D{P ag eeg} @@ -267,6 +268,7 @@ STR_UNITS_YEARS :{NUM}{NBSP}Joer STR_UNITS_PERIODS :{NUM}{NBSP}Period{P "" en} STR_LIST_SEPARATOR :,{SPACE} +STR_TRUNCATION_ELLIPSIS :... # Common window strings STR_LIST_FILTER_TITLE :{BLACK}Filter: @@ -285,7 +287,7 @@ STR_TOOLTIP_CLOSE_WINDOW :{BLACK}Fënster STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS :{BLACK}Fënstertitel - hei zéien fir d'Fënster ze bewegen STR_TOOLTIP_SHADE :{BLACK}Fenster verklengeren - Weis nëmmen Titelbar STR_TOOLTIP_DEBUG :{BLACK}Weis NewGRF Debug Informatioun -STR_TOOLTIP_DEFSIZE :{BLACK}Änner d'Fënster op d'Standardgréisst. Ctrl+Klick fir déi aktuell Gréisst als Standard ze späichern +STR_TOOLTIP_DEFSIZE :{BLACK}Änner d'Fënster op d'Standardgréisst. Ctrl+Klick fir déi aktuell Gréisst als Standard ze späichern. Dubel Ctrl+Klick fir op de Standard ze resetten STR_TOOLTIP_STICKY :{BLACK}Markéier dës Fënster fir net zougemeet ze ginn vun dem "All Fënsteren zoumaachen" Knäppchen. Ctrl+Klick späichert déi Actioun als Standard STR_TOOLTIP_RESIZE :{BLACK}Klicken an zéihen fir d'Fënstergréisst ze änneren STR_TOOLTIP_TOGGLE_LARGE_SMALL_WINDOW :{BLACK}Wiesselt grouss/kleng Fënstergréisst @@ -621,8 +623,14 @@ STR_GRAPH_COMPANY_VALUES_CAPTION :{WHITE}Firmewä STR_GRAPH_LAST_24_MINUTES_TIME_LABEL :{TINY_FONT}{BLACK}Lescht 24 Minuten STR_GRAPH_LAST_72_MINUTES_TIME_LABEL :{TINY_FONT}{BLACK}Dauert 72 Minutten +STR_GRAPH_LAST_288_MINUTES_TIME_LABEL :{TINY_FONT}{BLACK}Lescht 288 Minuten +STR_GRAPH_LAST_24_MONTHS :{TINY_FONT}{BLACK}2 Joer (pro Mount) +STR_GRAPH_LAST_24_QUARTERS :{TINY_FONT}{BLACK}6 Joer (véirelsjähreg) +STR_GRAPH_LAST_24_YEARS :{TINY_FONT}{BLACK}24 Joer (jährleg) +STR_GRAPH_TOGGLE_RANGE :Grafik emschalte fir des Data Range +STR_GRAPH_SELECT_SCALE :Horizontal Skala vun der Grafik änneren STR_GRAPH_CARGO_PAYMENT_RATES_CAPTION :{WHITE}Luedungs Bezuelraten STR_GRAPH_CARGO_PAYMENT_RATES_DAYS :{TINY_FONT}{BLACK}Deeg am Transit @@ -630,14 +638,20 @@ STR_GRAPH_CARGO_PAYMENT_RATES_SECONDS :{TINY_FONT}{BLA STR_GRAPH_CARGO_PAYMENT_RATES_TITLE :{TINY_FONT}{BLACK}Bezuelung fir Liwwerung vun 10 Eenheeten (oder 10.000 liter) Luedungen op Distanz vun 20 Felder STR_GRAPH_CARGO_ENABLE_ALL :{TINY_FONT}{BLACK}All STR_GRAPH_CARGO_DISABLE_ALL :{TINY_FONT}{BLACK}Keng -STR_GRAPH_CARGO_TOOLTIP_ENABLE_ALL :{BLACK}All Wueren op der Wuerewäertgrafik uweisen -STR_GRAPH_CARGO_TOOLTIP_DISABLE_ALL :{BLACK}Keng Wuer op der Wuerewäertgrafik uweisen +STR_GRAPH_CARGO_TOOLTIP_ENABLE_ALL :{BLACK}All Wueren op der Grafik uweisen +STR_GRAPH_CARGO_TOOLTIP_DISABLE_ALL :{BLACK}Keng Wuer op der Grafik uweisen STR_GRAPH_CARGO_PAYMENT_TOGGLE_CARGO :{BLACK}Schalt d'Grafik fir de Wuerentyp em STR_GRAPH_CARGO_PAYMENT_CARGO :{TINY_FONT}{BLACK}{STRING} +STR_GRAPH_INDUSTRY_CAPTION :{WHITE}{INDUSTRY} - Wuerenhistorie STR_GRAPH_INDUSTRY_RANGE_PRODUCED :Produzéiert STR_GRAPH_INDUSTRY_RANGE_TRANSPORTED :Transportéiert +STR_GRAPH_INDUSTRY_RANGE_DELIVERED :Geliwwert +STR_GRAPH_INDUSTRY_RANGE_WAITING :Warden +STR_GRAPH_TOWN_CARGO_CAPTION :{WHITE}{TOWN} - Wuerenhistorie +STR_GRAPH_TOWN_RANGE_PRODUCED :Angebot +STR_GRAPH_TOWN_RANGE_TRANSPORTED :Transportéiert STR_GRAPH_PERFORMANCE_DETAIL_TOOLTIP :{BLACK}Weis detailléiert Leeschtungsastellungen @@ -967,11 +981,14 @@ STR_GAME_OPTIONS_TAB_SOUND :Sound STR_GAME_OPTIONS_TAB_SOUND_TOOLTIP :Wiel Sound- a Musikastellungen aus STR_GAME_OPTIONS_TAB_SOCIAL :Social STR_GAME_OPTIONS_TAB_SOCIAL_TOOLTIP :Wiel Astellungen déi mat Social Media ze dinn hunn +STR_GAME_OPTIONS_TAB_ADVANCED :Erweidert +STR_GAME_OPTIONS_TAB_ADVANCED_TOOLTIP :Erweidert Astellungen änneren STR_GAME_OPTIONS_VOLUME :Volume STR_GAME_OPTIONS_SFX_VOLUME :Soundeffekter STR_GAME_OPTIONS_MUSIC_VOLUME :Musik +STR_GAME_OPTIONS_SETTING :{STRING}: {ORANGE}{STRING} STR_GAME_OPTIONS_VOLUME_MARK :{NUM}% @@ -1026,6 +1043,7 @@ STR_GAME_OPTIONS_CURRENCY_MYR :Malaysesche Rin STR_GAME_OPTIONS_CURRENCY_LVL :Lettesch Lat STR_GAME_OPTIONS_CURRENCY_PTE :Portugieseschen Escudo STR_GAME_OPTIONS_CURRENCY_UAH :Ukrainesch Hryvnia +STR_GAME_OPTIONS_CURRENCY_VND :Vietnamesesch Dong STR_GAME_OPTIONS_AUTOSAVE_FRAME :Autospäicheren STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_TOOLTIP :Wiel den Intervall aus fir d'Autospäicherung @@ -1059,6 +1077,7 @@ STR_GAME_OPTIONS_VIDEO_VSYNC_TOOLTIP :Wiel des Optiou STR_GAME_OPTIONS_VIDEO_DRIVER_INFO :Aktuellen Driver: {STRING} +STR_GAME_OPTIONS_INTERFACE :Interface STR_GAME_OPTIONS_GUI_SCALE_FRAME :Interfacegréisst STR_GAME_OPTIONS_GUI_SCALE_TOOLTIP :De Slider zéien fir d'Gréisst vum Interface ze änneren. Ctrl+Zéien fir eng kontinuéierlech Ännerung @@ -1083,6 +1102,7 @@ STR_GAME_OPTIONS_PARTICIPATE_SURVEY_LINK_TOOLTIP :Dëst start e B STR_GAME_OPTIONS_PARTICIPATE_SURVEY_PREVIEW :Preview op d'Emfroresultat STR_GAME_OPTIONS_PARTICIPATE_SURVEY_PREVIEW_TOOLTIP :Weis d'Resultat vun der Emfro vum aktuelle Spill un +STR_GAME_OPTIONS_DISPLAY :Display STR_GAME_OPTIONS_REFRESH_RATE :Bildfrequenz STR_GAME_OPTIONS_REFRESH_RATE_TOOLTIP :Wiel d'Frequenz vum Bildschirm aus @@ -1104,7 +1124,7 @@ STR_GAME_OPTIONS_BASE_MUSIC_DESCRIPTION_TOOLTIP :Méi Informatio STR_GAME_OPTIONS_ONLINE_CONTENT :Inhalt eroflueden STR_GAME_OPTIONS_ONLINE_CONTENT_TOOLTIP :Sich no neiem an geupdateten Inhalt fir erofzelueden -STR_GAME_OPTIONS_SOCIAL_PLUGINS_NONE :{LTBLUE}(keng Plugins déi mat Social Platforms kommunizéiren installéiert) +STR_GAME_OPTIONS_SOCIAL_PLUGINS_NONE :(keng Plugins déi mat Sozial-Platforme kommunizéiren installéiert) STR_GAME_OPTIONS_SOCIAL_PLUGIN_TITLE :{STRING} ({STRING}) STR_GAME_OPTIONS_SOCIAL_PLUGIN_PLATFORM :Plattform: @@ -1298,6 +1318,9 @@ STR_CONFIG_SETTING_INTEREST_RATE_HELPTEXT :Zënssaz; kontr STR_CONFIG_SETTING_RUNNING_COSTS :Betribskäschten: {STRING} STR_CONFIG_SETTING_RUNNING_COSTS_HELPTEXT :Fixéier den Niveau vun de Betribskäschten vu Gefierer an Infrastruktur ###length 3 +STR_CONFIG_SETTING_RUNNING_COSTS_LOW :Niddreg +STR_CONFIG_SETTING_RUNNING_COSTS_MEDIUM :Mëttel +STR_CONFIG_SETTING_RUNNING_COSTS_HIGH :Héich STR_CONFIG_SETTING_CONSTRUCTION_SPEED :Baugeschwindegkeet: {STRING} STR_CONFIG_SETTING_CONSTRUCTION_SPEED_HELPTEXT :Limitéier d'Unzuel u Bauaktiounen fir d'KI @@ -1320,6 +1343,9 @@ STR_CONFIG_SETTING_SUBSIDY_DURATION_DISABLED :Keng Subsiden STR_CONFIG_SETTING_CONSTRUCTION_COSTS :Konstruktiounskäschten: {STRING} STR_CONFIG_SETTING_CONSTRUCTION_COSTS_HELPTEXT :Bestëmm den Niveau vu Bau- a Kafkäschten ###length 3 +STR_CONFIG_SETTING_CONSTRUCTION_COSTS_LOW :Niddreg +STR_CONFIG_SETTING_CONSTRUCTION_COSTS_MEDIUM :Mëttel +STR_CONFIG_SETTING_CONSTRUCTION_COSTS_HIGH :Héich STR_CONFIG_SETTING_RECESSIONS :Rezessiounen: {STRING} STR_CONFIG_SETTING_RECESSIONS_HELPTEXT :Wann ugeschalt kann vun Zäit zur Zäit eng Rezessioun kommen. Während enger Rezessioun ass d'Produktioun däitlech méi niddreg (an klëmmt erëm op den alen Niveau no der Rezessioun) @@ -1665,6 +1691,8 @@ STR_CONFIG_SETTING_SCROLLMODE_LMB :Kaart mat der l STR_CONFIG_SETTING_SMOOTH_SCROLLING :Glaate Scrolling: {STRING} STR_CONFIG_SETTING_SMOOTH_SCROLLING_HELPTEXT :Kontrolléiert wéi d'Haptusiicht op eng bestëmmten Positioun scrollt, wann een op déi kléng Kaart klickt oder en Befehl fir ob en spezifescht Objet ze scrollen gëtt. Wann ugeschalt, gëtt bis dohin gescrollt, wann ausgeschalt, spréngt d'Vue op den Zielobjet +STR_CONFIG_SETTING_TOOLBAR_DROPDOWN_AUTOSELECT :Traditionellt Toolbarmenuselektiounsverhalen: {STRING} +STR_CONFIG_SETTING_TOOLBAR_DROPDOWN_AUTOSELECT_HELPTEXT :Wiel aus wéi d'Selektioun an den Toolbarmenus sech verhält. Wann ausgeschalt, bleiwen d'Menuer opgeklappt bis eng Selektioun gemet gouf. Wann ugeschalt, aktivéiren sech d'Menuer wann d'Maustast lassgelooss gëtt. STR_CONFIG_SETTING_MEASURE_TOOLTIP :Weis en Mooss-Tooltip wann verschidde Bau-Tools benotzt ginn: {STRING} STR_CONFIG_SETTING_MEASURE_TOOLTIP_HELPTEXT :Weis Felderdistanzen an Héichtenënnerscheed beim Zéien während dem Bauen un @@ -2026,9 +2054,9 @@ STR_CONFIG_SETTING_SOFT_LIMIT_VALUE :{COMMA} ###setting-zero-is-special STR_CONFIG_SETTING_SOFT_LIMIT_DISABLED :Ausgeschalt -STR_CONFIG_SETTING_ZOOM_MIN :Maximale Razoom Level: {STRING} +STR_CONFIG_SETTING_ZOOM_MIN :Maximale Razoomniveau: {STRING} STR_CONFIG_SETTING_ZOOM_MIN_HELPTEXT :Maximal Razoomstuf fir Usiichtsfënsteren. Et gëtt méi Späicher gebraucht wann d'Stufen ze grouss ginn -STR_CONFIG_SETTING_ZOOM_MAX :Maximalen Rauszoom Level: {STRING} +STR_CONFIG_SETTING_ZOOM_MAX :Maximale Rauszoomniveau: {STRING} STR_CONFIG_SETTING_ZOOM_MAX_HELPTEXT :Maximal Rauszoom-Stuf fir Usiichtsfënsteren. Méi grouss Rauszoom-Stufen kënnen Ruckeler verursaachen ###length 6 STR_CONFIG_SETTING_ZOOM_LVL_MIN :4x @@ -2063,7 +2091,7 @@ STR_CONFIG_SETTING_CITY_SIZE_MULTIPLIER :Ufangs-Gréisst STR_CONFIG_SETTING_CITY_SIZE_MULTIPLIER_HELPTEXT :Duerchschnëttsgréisst vu Stied an Proportioun zu normalen Dierfer um Spillstart STR_CONFIG_SETTING_LINKGRAPH_RECALC_INTERVAL :Update de Verdeelergraph all {STRING} -STR_CONFIG_SETTING_LINKGRAPH_RECALC_INTERVAL_HELPTEXT :Zäit tëschend zwou Neiberechnungen vun der Linkgrafik. All Neiberechnung berechent eng Komponent vun der Grafik. Dëst bedeit dass e Wäert X net heescht dass de ganze Graph all X Sekonne geupdate gëtt. Nëmmen eng Komponent gëtt berechent. Wat de Wäert méi kuerz gesat gëtt, wat méi CPU Leeschtung gebraucht gëtt fir alles ze berechnen. Je gréisser de Wäert gesat gëtt desto méi laang brauch et bis d'Wuereverdeelung op neie Route gestart gëtt +STR_CONFIG_SETTING_LINKGRAPH_RECALC_INTERVAL_HELPTEXT :Zäit tëschend zwou Neiberechnungen vun der Linkgrafik. All Neiberechnung berechent eng Komponent vun der Grafik. Dëst bedeit dass e Wäert X net heescht dass déi ganze Grafik all X Sekonne geupdate gëtt. Nëmmen eng Komponent gëtt berechent. Wat de Wäert méi kuerz gesat gëtt, wat méi CPU Leeschtung gebraucht gëtt fir alles ze berechnen. Je gréisser de Wäert gesat gëtt desto méi laang brauch et bis d'Wuereverdeelung op neie Route gestart gëtt STR_CONFIG_SETTING_LINKGRAPH_RECALC_TIME :Benotz {STRING} fir d'Neiberechnung vum Verdeelergraph STR_CONFIG_SETTING_LINKGRAPH_RECALC_TIME_HELPTEXT :Zäit déi gebrauch gëtt fir all Neiberechnung vun enger Komponent vun der Linkgrafik. Wann eng Neiberechnung gestart gëtt, gëtt e Prozess erstallt den fir des Unzuel u Sekonne lafen dierf. Wat d'Zäit méi kuerz gesat gëtt, wat d'Chance méi grouss ass dass d'Berechnung net fäerdeg gëtt. Dann stopt d'Spill bis d'Berechnung fäerdeg ass ("laggt"). Je länger d'Zäit gesat gëtt desto länger brauch et bis d'Verdeelung geupdate gëtt wann eng Route ännert @@ -2076,9 +2104,9 @@ STR_CONFIG_SETTING_DISTRIBUTION_ARMOURED_HELPTEXT :D'GEPANZERT Wue STR_CONFIG_SETTING_DISTRIBUTION_DEFAULT :Verdeelungsmodus fir aner Wuereklassen: {STRING} STR_CONFIG_SETTING_DISTRIBUTION_DEFAULT_HELPTEXT :"Asymmetresch" heescht dass eng beléiweg Unzuel un Wueren an béid Richtungen verschéckt ginn. "Manuell" heescht dass keng automatësch Verdeelung stattfënnt ###length 3 -STR_CONFIG_SETTING_DISTRIBUTION_MANUAL :manuell -STR_CONFIG_SETTING_DISTRIBUTION_ASYMMETRIC :asymmetresch -STR_CONFIG_SETTING_DISTRIBUTION_SYMMETRIC :symmetresch +STR_CONFIG_SETTING_DISTRIBUTION_MANUAL :Manuell +STR_CONFIG_SETTING_DISTRIBUTION_ASYMMETRIC :Asymmetresch +STR_CONFIG_SETTING_DISTRIBUTION_SYMMETRIC :Symmetresch STR_CONFIG_SETTING_LINKGRAPH_ACCURACY :Verdeelungsgenauegkeet: {STRING} STR_CONFIG_SETTING_LINKGRAPH_ACCURACY_HELPTEXT :Wat de Wäert méi héich ass, wat méi CPU benotzt gëtt fir d'Linkgrafik ze zeechnen. Wann ze héich gesat, kann et zu Lags kommen. Ze niddreg gesat kann d'Verdeelung ongenau ginn an d'Wueren net sou verdeelt ginn wéi geduet @@ -2131,10 +2159,11 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_SI :SI (kN) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT :Héichteneenheeten: {STRING} STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_HELPTEXT :Emmer wann Héichten am Userinterface ugewisen ginn, weis se an den ausgewielten Eenheeten un -###length 3 +###length 4 STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_IMPERIAL :Britesch (ft) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_METRIC :Metresch (m) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_SI :SI (m) +STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_GAMEUNITS :Spilleenheeten (Niveau) STR_CONFIG_SETTING_LOCALISATION :Lokaliséirung STR_CONFIG_SETTING_GRAPHICS :Grafik @@ -2193,6 +2222,8 @@ STR_VIDEO_DRIVER_ERROR_NO_HARDWARE_ACCELERATION :{WHITE}... keng STR_VIDEO_DRIVER_ERROR_HARDWARE_ACCELERATION_CRASH :{WHITE}... GPU driver huet d'Spill gecrasht. Hardwarebeschleunegung ausgeschalt # Intro window +STR_INTRO_CAPTION :{WHITE}OpenTTD +STR_INTRO_VERSION :OpenTTD {REV} STR_INTRO_NEW_GAME :{BLACK}Neit Spill STR_INTRO_LOAD_GAME :{BLACK}Spill lueden @@ -2326,16 +2357,19 @@ STR_FACE_SIMPLE_TOOLTIP :{BLACK}Einfach STR_FACE_LOAD :{BLACK}Lueden STR_FACE_LOAD_TOOLTIP :{BLACK}Favoriséiert Gesiicht lueden STR_FACE_LOAD_DONE :{WHITE}Äert favoriséiert Gesiicht ass aus der OpenTTD Konfiguratiounsdatei geluede ginn. -STR_FACE_FACECODE :{BLACK}Gesiicht N°. -STR_FACE_FACECODE_TOOLTIP :{BLACK}Kuckt an wielt d'Gesiichtsnummer vum Firmepresident -STR_FACE_FACECODE_CAPTION :{WHITE}Kuckt an wielt d'Gesiichtsnummer -STR_FACE_FACECODE_SET :{WHITE}Nei Gesiichtsnummer ass agestallt ginn -STR_FACE_FACECODE_ERR :{WHITE}Konnt d'Gesiichtsnummer net setzen - muss en numereschen Wäert tëscht 0 an 4,294,967,295 sinn! +STR_FACE_FACECODE :{BLACK}Gesiichtscode +STR_FACE_FACECODE_TOOLTIP :{BLACK}Kuckt a wielt de Gesiichtscode vum Firmepresident +STR_FACE_FACECODE_CAPTION :{WHITE}Kuckt a wielt de Gesiichtscode +STR_FACE_FACECODE_SET :{WHITE}Neit Presidentegesiicht ass agestallt ginn +STR_FACE_FACECODE_ERR :{WHITE}Konnt de Gesiichtscode net astellen - muss e gültege Label an Nummer sinn STR_FACE_SAVE :{BLACK}Späicheren STR_FACE_SAVE_TOOLTIP :{BLACK}Späichert favoriséiert Gesiicht STR_FACE_SAVE_DONE :{WHITE}Dëst Gesiicht gëtt als favoriséiert an der OpenTTD Konfiguratiounsdatei gespäichert. +STR_FACE_SETTING_TOGGLE :{STRING} {ORANGE}{STRING} +STR_FACE_SETTING_NUMERIC :{STRING} {ORANGE}{NUM} / {NUM} STR_FACE_YES :Jo STR_FACE_NO :Nee +STR_FACE_STYLE :Stil: STR_FACE_HAIR :Hoer: STR_FACE_EYEBROWS :Aperhoer: STR_FACE_EYECOLOUR :Aafaarf: @@ -2808,6 +2842,10 @@ STR_PICKER_MODE_USED_TOOLTIP :Wiesselen tësc STR_PICKER_MODE_SAVED :Gespäichert STR_PICKER_MODE_SAVED_TOOLTIP :Wiesselen tëschent gespäicherten Objeten +STR_PICKER_PREVIEW_SHRINK :- +STR_PICKER_PREVIEW_SHRINK_TOOLTIP :D'Héicht vun Virschaubiller erofsetzen. Ctrl+Klick fir op de Minimum ze setzen +STR_PICKER_PREVIEW_EXPAND :+ +STR_PICKER_PREVIEW_EXPAND_TOOLTIP :D'Héicht vun Virschaubiller eropsetzen. Ctrl+Klick fir op de Maximum ze setzen. STR_PICKER_STATION_CLASS_TOOLTIP :Wiel eng Statiounsklass fir unzeweisen STR_PICKER_STATION_TYPE_TOOLTIP :Wiel en Typ vu Statioun fir ze bauen. Ctrl+Klick fir en bei d'gespäichert Objeten dobäizesetzen oder ewechzehuelen @@ -3048,6 +3086,11 @@ STR_FOUND_TOWN_INITIAL_SIZE_TOOLTIP :{BLACK}Wiel d'S STR_FOUND_TOWN_CITY :{BLACK}Stad STR_FOUND_TOWN_CITY_TOOLTIP :{BLACK}Stied wuessen méi schnell wéi Dierfer{}Ofhängeg vun den Astellungen, sinn se méi grouss am Ufank +STR_FOUND_TOWN_EXPAND_MODE :{YELLOW}Stadvergéisserung: +STR_FOUND_TOWN_EXPAND_BUILDINGS :Gebaier +STR_FOUND_TOWN_EXPAND_BUILDINGS_TOOLTIP :Unzuel Gebaier vun der Stad erhéigen +STR_FOUND_TOWN_EXPAND_ROADS :Stroossen +STR_FOUND_TOWN_EXPAND_ROADS_TOOLTIP :Méi Stroossen an der Stad bauen STR_FOUND_TOWN_ROAD_LAYOUT :{YELLOW}Stroosselayout vun der Stad: STR_FOUND_TOWN_SELECT_LAYOUT_TOOLTIP :{BLACK}Stroosselayout fir des Stad wielen @@ -3307,6 +3350,8 @@ STR_SAVELOAD_DETAIL_GRFSTATUS :{SILVER}NewGRF: STR_SAVELOAD_FILTER_TITLE :{BLACK}Filter: STR_SAVELOAD_OVERWRITE_TITLE :{WHITE}Datei iwwerschreiwen STR_SAVELOAD_OVERWRITE_WARNING :{YELLOW}Bass du sécher, dass du d'existéirend Datei iwwerschreiwe wëlls? +STR_SAVELOAD_DELETE_TITLE :{WHITE}Datei läschen +STR_SAVELOAD_DELETE_WARNING :{YELLOW}}Bass du sécher, dass du des Datei läsche wëlls? STR_SAVELOAD_DIRECTORY :{STRING} (Verzeechnis) STR_SAVELOAD_PARENT_DIRECTORY :{STRING} (Een dossier zréck) @@ -3385,8 +3430,11 @@ STR_MAPGEN_SOUTHWEST :{BLACK}Südwest STR_MAPGEN_BORDER_FREEFORM :{BLACK}Fräiform STR_MAPGEN_BORDER_WATER :{BLACK}Waasser STR_MAPGEN_BORDER_RANDOM :{BLACK}Zoufälleg -STR_MAPGEN_BORDER_RANDOMIZE :{BLACK}Zoufall -STR_MAPGEN_BORDER_MANUAL :{BLACK}Manuell + +###length 3 +STR_MAPGEN_BORDER_RANDOMIZE :Zoufall +STR_MAPGEN_BORDER_MANUAL :Manuell +STR_MAPGEN_BORDER_INFINITE_WATER :Endlos Waasser STR_MAPGEN_HEIGHTMAP_ROTATION :{BLACK}Héichtekaart-Rotatioun: STR_MAPGEN_HEIGHTMAP_NAME :{BLACK}Héichtekaart-Numm: @@ -3425,7 +3473,8 @@ STR_GENERATION_LANDSCAPE_GENERATION :{BLACK}Landscha STR_GENERATION_RIVER_GENERATION :{BLACK}Generéiren vu Flëss STR_GENERATION_CLEARING_TILES :{BLACK}Generatioun vu knubbelegem a stengege Land STR_GENERATION_TOWN_GENERATION :{BLACK}Stiedgeneratioun -STR_GENERATION_INDUSTRY_GENERATION :{BLACK}Industriegeneratioun +STR_GENERATION_LAND_INDUSTRY_GENERATION :{BLACK}Landindustriegeneratioun +STR_GENERATION_WATER_INDUSTRY_GENERATION :{BLACK}Waasserindustriegeneratioun STR_GENERATION_OBJECT_GENERATION :{BLACK}Objets-Generatioun STR_GENERATION_TREE_GENERATION :{BLACK}Baam Generatioun STR_GENERATION_SETTINGUP_GAME :{BLACK}Spill gëtt opgestallt @@ -3645,7 +3694,7 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}Gëff en STR_TOWN_DIRECTORY_CAPTION :{WHITE}Stied ({COMMA} vu {COMMA}) STR_TOWN_DIRECTORY_NONE :{ORANGE}- Keng - STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) -STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (Stad){BLACK} ({COMMA}) +STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{BLACK} ({COMMA}) {YELLOW}{CITY_ICON} STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}Stiednimm - klick op den Numm fir d'Usiicht drop ze zentréieren. Ctrl+Klick erstellt eng nei Usiicht vun der Stad STR_TOWN_POPULATION :{BLACK}Weltbevölkerung: {COMMA} @@ -3669,9 +3718,15 @@ STR_TOWN_VIEW_CENTER_TOOLTIP :{BLACK}Zentréi STR_TOWN_VIEW_LOCAL_AUTHORITY_BUTTON :{BLACK}Gemeng STR_TOWN_VIEW_LOCAL_AUTHORITY_TOOLTIP :{BLACK}Weist d'Informatiounen zu der Gemeng STR_TOWN_VIEW_RENAME_TOOLTIP :{BLACK}Wiesselt de Stadnumm +STR_TOWN_VIEW_CARGO_GRAPH :Wueregrafik +STR_TOWN_VIEW_CARGO_GRAPH_TOOLTIP :Grafik vun der Stad hierer Wuerenhistorie uweisen STR_TOWN_VIEW_EXPAND_BUTTON :{BLACK}Erweideren STR_TOWN_VIEW_EXPAND_TOOLTIP :{BLACK}Stad méi grouss maachen +STR_TOWN_VIEW_EXPAND_BUILDINGS_BUTTON :{BLACK}Gebaier erweideren +STR_TOWN_VIEW_EXPAND_BUILDINGS_TOOLTIP :{BLACK}Gebaier vun der Stad vergréisseren +STR_TOWN_VIEW_EXPAND_ROADS_BUTTON :{BLACK}Stroossen erweideren +STR_TOWN_VIEW_EXPAND_ROADS_TOOLTIP :{BLACK}Stroosse vun der Stad erweideren STR_TOWN_VIEW_DELETE_BUTTON :{BLACK}Läschen STR_TOWN_VIEW_DELETE_TOOLTIP :{BLACK}Des Stad ganz läschen @@ -3997,7 +4052,9 @@ STR_INDUSTRY_VIEW_PRODUCTION_LAST_MONTH_TITLE :{BLACK}Produkti STR_INDUSTRY_VIEW_PRODUCTION_LAST_MINUTE_TITLE :{BLACK}Produktioun déi läscht Minutt: STR_INDUSTRY_VIEW_TRANSPORTED :{YELLOW}{CARGO_LONG}{STRING}{BLACK} ({COMMA}% transportéiert) STR_INDUSTRY_VIEW_LOCATION_TOOLTIP :{BLACK}Zentréiert d'Siicht op d'Industrie. Ctrl+Klick erstellt eng nei Usiicht op d'Industrie -STR_INDUSTRY_VIEW_PRODUCTION_LEVEL :{BLACK}Produktiounslevel: {YELLOW}{COMMA}% +STR_INDUSTRY_VIEW_CARGO_GRAPH :{BLACK}Wueregrafik +STR_INDUSTRY_VIEW_CARGO_GRAPH_TOOLTIP :{BLACK}Weist d'Grafik vun der Industriewuerenhistorie un +STR_INDUSTRY_VIEW_PRODUCTION_LEVEL :{BLACK}Produktiounsniveau: {YELLOW}{COMMA}% STR_INDUSTRY_VIEW_INDUSTRY_ANNOUNCED_CLOSURE :{YELLOW}D'Industrie annoncéiert dass se zougemaach gëtt STR_INDUSTRY_VIEW_REQUIRES_N_CARGO :{BLACK}Brauch: {YELLOW}{STRING}{STRING} @@ -4011,7 +4068,7 @@ STR_INDUSTRY_VIEW_ACCEPT_CARGO_NOSUFFIX :{YELLOW}{0:STRI STR_INDUSTRY_VIEW_ACCEPT_CARGO_AMOUNT_NOSUFFIX :{YELLOW}{0:STRING}{BLACK}: {1:CARGO_SHORT} warden STR_CONFIG_GAME_PRODUCTION :{WHITE}D'Produktioun änneren (Multipel vun 8, bis op 2040) -STR_CONFIG_GAME_PRODUCTION_LEVEL :{WHITE}Änner de Produktiounslevel (Prozenter, bis zu 800%) +STR_CONFIG_GAME_PRODUCTION_LEVEL :{WHITE}Änner de Produktiounsniveau (Prozenter, bis zu 800%) # Vehicle lists ###length VEHICLE_TYPES @@ -4134,6 +4191,7 @@ STR_PURCHASE_INFO_ALL_BUT :Alles ausser {C STR_PURCHASE_INFO_MAX_TE :{BLACK}Max. Zéikraaft: {GOLD}{FORCE} STR_PURCHASE_INFO_AIRCRAFT_RANGE :{BLACK}Distanz: {GOLD}{COMMA} Felder STR_PURCHASE_INFO_AIRCRAFT_TYPE :{BLACK}Fliger Typ: {GOLD}{STRING} +STR_PURCHASE_INFO_RAILTYPES :{BLACK}Schinnentypen: {GOLD}{STRING} ###length 3 STR_CARGO_TYPE_FILTER_ALL :All Wuerentyp @@ -4317,6 +4375,7 @@ STR_ENGINE_PREVIEW_RUNCOST_YEAR :Betribskäschte STR_ENGINE_PREVIEW_RUNCOST_PERIOD :Betribskäschten: {CURRENCY_LONG}/Period STR_ENGINE_PREVIEW_CAPACITY :Kapazitéit: {CARGO_LONG} STR_ENGINE_PREVIEW_CAPACITY_2 :Kapazitéit: {CARGO_LONG}, {CARGO_LONG} +STR_ENGINE_PREVIEW_RAILTYPES :Schinnentypen: {STRING} # Autoreplace window STR_REPLACE_VEHICLES_WHITE :{WHITE}Ersetz {STRING} - {STRING} @@ -4408,10 +4467,10 @@ STR_VEHICLE_VIEW_SHIP_ORDERS_TOOLTIP :{BLACK}Weist d' STR_VEHICLE_VIEW_AIRCRAFT_ORDERS_TOOLTIP :{BLACK}Weist d'Opträg vum Fliger. Ctrl+Klick weist den Zäitplang ###length VEHICLE_TYPES -STR_VEHICLE_VIEW_TRAIN_SHOW_DETAILS_TOOLTIP :{BLACK}Weist d'Detailer vum Zuch -STR_VEHICLE_VIEW_ROAD_VEHICLE_SHOW_DETAILS_TOOLTIP :{BLACK}Weist Stroossegefier Detailer -STR_VEHICLE_VIEW_SHIP_SHOW_DETAILS_TOOLTIP :{BLACK}Weis Schëffsdetailer -STR_VEHICLE_VIEW_AIRCRAFT_SHOW_DETAILS_TOOLTIP :{BLACK}Weist d'Fligerdetailer +STR_VEHICLE_VIEW_TRAIN_SHOW_DETAILS_TOOLTIP :{BLACK}Weist d'Detailer vum Zuch. Ctrl+Klick fir d'Zuchgrupp unzeweisen +STR_VEHICLE_VIEW_ROAD_VEHICLE_SHOW_DETAILS_TOOLTIP :{BLACK}Weist Gefier Detailer. Ctrl+Klick fir d'Gefierergrupp unzeweisen +STR_VEHICLE_VIEW_SHIP_SHOW_DETAILS_TOOLTIP :{BLACK}Weis Schëffsdetailer un. Ctrl+Klick fir d'Schëffsgrupp unzeweisen +STR_VEHICLE_VIEW_AIRCRAFT_SHOW_DETAILS_TOOLTIP :{BLACK}Weist d'Fligerdetailer un. Ctrl+Klick fir d'Fligergrupp unzeweisen ###length VEHICLE_TYPES STR_VEHICLE_VIEW_TRAIN_STATUS_START_STOP_TOOLTIP :{BLACK}Aktuell Zuchs-Aktioun - klick fir den Zuch ze stoppen/starten @@ -4735,14 +4794,15 @@ STR_TIMETABLE_TOOLTIP :{BLACK}Zäitpla STR_TIMETABLE_NO_TRAVEL :Net ënnerwee STR_TIMETABLE_NOT_TIMETABLEABLE :Rees (automatesch; Zäitplang durch manuell Opträg) STR_TIMETABLE_TRAVEL_NOT_TIMETABLED :Ënnerwee (ouni Zäitplang) +STR_TIMETABLE_TRAVEL_NOT_TIMETABLED_SPEED :Fuer maximal {VELOCITY} (ouni Zäitplang) STR_TIMETABLE_TRAVEL_FOR :Ënnerwee während {STRING} STR_TIMETABLE_TRAVEL_FOR_SPEED :Fiert während {STRING} mat maximal {VELOCITY} STR_TIMETABLE_TRAVEL_FOR_ESTIMATED :Fuer (während {STRING}, ouni Zäitplang) STR_TIMETABLE_TRAVEL_FOR_SPEED_ESTIMATED :Fuer (während {STRING}, ouni Zäitplang) mat maximal {VELOCITY} STR_TIMETABLE_STAY_FOR_ESTIMATED :{SPACE}(waard {STRING}, ouni Zäitplang) STR_TIMETABLE_AND_TRAVEL_FOR_ESTIMATED :{SPACE}(fuer während {STRING}, ouni Zäitplang) -STR_TIMETABLE_STAY_FOR :an bleif fir {STRING} -STR_TIMETABLE_AND_TRAVEL_FOR :an ënnerwee während {STRING} +STR_TIMETABLE_STAY_FOR :{SPACE} a bleif fir {STRING} +STR_TIMETABLE_AND_TRAVEL_FOR :{SPACE}an ënnerwee während {STRING} STR_TIMETABLE_APPROX_TIME :{BLACK}Dësen Zäitplang brauch ongeféier {STRING} fir fäerdeg ze ginn STR_TIMETABLE_TOTAL_TIME :{BLACK}Dësen Zäitplang brauch {STRING} fir fäerdeg ze ginn @@ -4971,6 +5031,7 @@ STR_ERROR_FLAT_LAND_REQUIRED :{WHITE}D'Land m STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION :{WHITE}Land ass an déi falsch Richtung geneigt STR_ERROR_CAN_T_DO_THIS :{WHITE}Kann dat net maachen... STR_ERROR_BUILDING_MUST_BE_DEMOLISHED :{WHITE}Gebai muss fir d'éischt ofgerapt ginn +STR_ERROR_BUILDING_IS_PROTECTED :{WHITE}... Gebai ass geschützt STR_ERROR_CAN_T_CLEAR_THIS_AREA :{WHITE}Kann des Plaz net raumen... STR_ERROR_SITE_UNSUITABLE :{WHITE}... Plaz net gëeegent STR_ERROR_ALREADY_BUILT :{WHITE}... scho gebaut @@ -5058,7 +5119,7 @@ STR_ERROR_CAN_T_BUILD_BUS_STATION :{WHITE}Kann de STR_ERROR_CAN_T_BUILD_TRUCK_STATION :{WHITE}Kann d'Camionsgare net bauen... STR_ERROR_CAN_T_BUILD_PASSENGER_TRAM_STATION :{WHITE}Kann d'Passagéier-Tramsarrêt net bauen... STR_ERROR_CAN_T_BUILD_CARGO_TRAM_STATION :{WHITE}Kann d'Wueren-Tramstatioun net bauen... -STR_ERROR_CAN_T_BUILD_DOCK_HERE :{WHITE}Kann den Dock hei net bauen... +STR_ERROR_CAN_T_BUILD_DOCK_HERE :{WHITE}Kann de Quai hei net bauen... STR_ERROR_CAN_T_BUILD_AIRPORT_HERE :{WHITE}Kann de Fluchhafen hei net bauen... STR_ERROR_ADJOINS_MORE_THAN_ONE_EXISTING :{WHITE}Grenzt un méi wéi eng Gare un @@ -5069,7 +5130,7 @@ STR_ERROR_TOO_MANY_STATIONS_LOADING :{WHITE}Ze vill STR_ERROR_TOO_MANY_STATION_SPECS :{WHITE}Ze vill Garesdeeler STR_ERROR_TOO_MANY_BUS_STOPS :{WHITE}Ze vill Busarrêten STR_ERROR_TOO_MANY_TRUCK_STOPS :{WHITE}Ze vill Camionsgaren -STR_ERROR_TOO_CLOSE_TO_ANOTHER_DOCK :{WHITE}Ze no un engem aaneren Hafen +STR_ERROR_TOO_CLOSE_TO_ANOTHER_DOCK :{WHITE}Ze no un engem aanere Quai STR_ERROR_TOO_CLOSE_TO_ANOTHER_AIRPORT :{WHITE}Ze no un engem aanere Fluchhafen STR_ERROR_CAN_T_RENAME_STATION :{WHITE}Kann d'Statioun net ëmbenennen... STR_ERROR_DRIVE_THROUGH_ON_TOWN_ROAD :{WHITE}... d'Strooss ass am Besëtz vun der Stad @@ -5092,7 +5153,7 @@ STR_ERROR_MUST_DEMOLISH_BUS_STATION_FIRST :{WHITE}Busarrê STR_ERROR_MUST_DEMOLISH_TRUCK_STATION_FIRST :{WHITE}Muss d'Camionsgare fir d'éischt ofrappen STR_ERROR_MUST_DEMOLISH_PASSENGER_TRAM_STATION_FIRST :{WHITE}Muss d'Tramstatioun fir d'éischt ofrappen STR_ERROR_MUST_DEMOLISH_CARGO_TRAM_STATION_FIRST :{WHITE}Muss d'Tramstatioun fir d'éischt ofrappen -STR_ERROR_MUST_DEMOLISH_DOCK_FIRST :{WHITE}Muss den Hafen fir déischt ofrappen +STR_ERROR_MUST_DEMOLISH_DOCK_FIRST :{WHITE}Muss de Quai fir déischt ofrappen STR_ERROR_MUST_DEMOLISH_AIRPORT_FIRST :{WHITE}Muss de Fluchhafe fir d'éischt ofrappen # Waypoint related errors @@ -5211,6 +5272,13 @@ STR_ERROR_START_AND_END_MUST_BE_IN :{WHITE}Start an STR_ERROR_ENDS_OF_BRIDGE_MUST_BOTH :{WHITE}... dei zwee Enner vun der Bréck mussen u Land sinn STR_ERROR_BRIDGE_TOO_LONG :{WHITE}... Bréck ze laang STR_ERROR_BRIDGE_THROUGH_MAP_BORDER :{WHITE}Bréck géif ausserhalb der Kaart ukommen +STR_ERROR_BRIDGE_TOO_LOW_FOR_STATION :{WHITE}Bréck ass {HEIGHT} ze niddreg fir d'Gare +STR_ERROR_BRIDGE_TOO_LOW_FOR_ROADSTOP :{WHITE}Bréck ass {HEIGHT} ze niddreg fir e Stroossestop +STR_ERROR_BRIDGE_TOO_LOW_FOR_DOCK :{WHITE}Bréck ass {HEIGHT} ze niddreg fir de Quai +STR_ERROR_BRIDGE_TOO_LOW_FOR_BUOY :{WHITE}Bréck as {HEIGHT} ze niddreg fir d'Boje +STR_ERROR_BRIDGE_TOO_LOW_FOR_RAIL_WAYPOINT :{WHITE}Bréck ass {HEIGHT} ze niddreg fir den Zuchweepunkt +STR_ERROR_BRIDGE_TOO_LOW_FOR_ROAD_WAYPOINT :{WHITE}Bréck ass {HEIGHT} ze niddreg fir de Stroosseweepunkt +STR_ERROR_BRIDGE_TOO_LOW_FOR_LOCK :{WHITE}Bréck ass {HEIGHT} ze niddreg fir d'Schleis # Tunnel related errors STR_ERROR_CAN_T_BUILD_TUNNEL_HERE :{WHITE}Kann den Tunnel hei net bauen... @@ -5359,7 +5427,7 @@ STR_ERROR_AIRCRAFT_NOT_ENOUGH_RANGE :{WHITE}... Flig STR_ERROR_NO_RAIL_STATION :{WHITE}Et gëtt keng Zuchgare/statioun STR_ERROR_NO_BUS_STATION :{WHITE}Et gëtt keen Busarrêt STR_ERROR_NO_TRUCK_STATION :{WHITE}Et gëtt keng Camionsgare -STR_ERROR_NO_DOCK :{WHITE}Et gëtt keen Dock +STR_ERROR_NO_DOCK :{WHITE}Et gëtt kee Quai STR_ERROR_NO_AIRPORT :{WHITE}Et gëtt keen Fluchhafen/Helikopterlandeplaz STR_ERROR_NO_STOP_COMPATIBLE_ROAD_TYPE :{WHITE}Et gëtt keen Arret mat engem kompatible Stroossentyp STR_ERROR_NO_STOP_COMPATIBLE_TRAM_TYPE :{WHITE}Et gëtt keen Arret mat engem kompatible Tramtyp @@ -5827,6 +5895,8 @@ STR_SAVEGAME_NAME_SPECTATOR :Zuschauer, {1:S # Viewport strings STR_VIEWPORT_TOWN_POP :{TOWN} ({COMMA}) +STR_VIEWPORT_TOWN_CITY :{TOWN} {CITY_ICON} +STR_VIEWPORT_TOWN_CITY_POP :{TOWN} ({COMMA}) {CITY_ICON} STR_VIEWPORT_STATION :{STATION} {STATION_FEATURES} # Simple strings to get specific types of data @@ -5850,6 +5920,7 @@ STR_CURRENCY_SHORT_GIGA :{NBSP}mia STR_CURRENCY_SHORT_TERA :{NBSP}bn STR_JUST_CARGO :{CARGO_LONG} +STR_JUST_LEFT_ARROW :{LEFT_ARROW} STR_JUST_RIGHT_ARROW :{RIGHT_ARROW} STR_JUST_CHECKMARK :{CHECKMARK} STR_JUST_COMMA :{COMMA} @@ -5889,3 +5960,11 @@ STR_SHIP :{BLACK}{SHIP} STR_TOOLBAR_RAILTYPE_VELOCITY :{STRING} ({VELOCITY}) STR_BADGE_NAME_LIST :{STRING}: {GOLD}{STRING} +STR_BADGE_CONFIG_MENU_TOOLTIP :Badgekonfiguratioun opman +STR_BADGE_CONFIG_RESET :Reset +STR_BADGE_CONFIG_ICONS :{WHITE}Badgeikoner +STR_BADGE_CONFIG_FILTERS :{WHITE}Badgefilter +STR_BADGE_CONFIG_PREVIEW :Bildvirschau +STR_BADGE_CONFIG_NAME :Numm +STR_BADGE_FILTER_ANY_LABEL :Iergendeen {STRING} +STR_BADGE_FILTER_IS_LABEL :{STRING} ass {STRING} diff --git a/src/lang/macedonian.txt b/src/lang/macedonian.txt index 552c372116dcc..24b1becdcb7db 100644 --- a/src/lang/macedonian.txt +++ b/src/lang/macedonian.txt @@ -1136,7 +1136,7 @@ STR_CONFIG_SETTING_ZOOM_LVL_OUT_8X :8x ###length 3 -###length 3 +###length 4 @@ -1460,6 +1460,8 @@ STR_MAPGEN_BY :{BLACK}* # Strings for map borders at game generation +###length 3 + # SE Map generation diff --git a/src/lang/malay.txt b/src/lang/malay.txt index b484731b797f8..5da82b66f22d4 100644 --- a/src/lang/malay.txt +++ b/src/lang/malay.txt @@ -1593,7 +1593,7 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_VOLUME_SI :Unit SI (m³) ###length 3 -###length 3 +###length 4 STR_CONFIG_SETTING_SOUND :Bunyi STR_CONFIG_SETTING_INTERFACE :Antaramuka (Interface) @@ -2527,6 +2527,8 @@ STR_MAPGEN_SOUTHWEST :{BLACK}Barat da STR_MAPGEN_BORDER_FREEFORM :{BLACK}Bebas STR_MAPGEN_BORDER_WATER :{BLACK}Air STR_MAPGEN_BORDER_RANDOM :{BLACK}Rambang + +###length 3 STR_MAPGEN_BORDER_RANDOMIZE :{BLACK}Rambang STR_MAPGEN_BORDER_MANUAL :{BLACK}Manual diff --git a/src/lang/maltese.txt b/src/lang/maltese.txt index 2b95200f6fed2..7d41aa8c9c014 100644 --- a/src/lang/maltese.txt +++ b/src/lang/maltese.txt @@ -754,7 +754,7 @@ STR_CONFIG_SETTING_ADVANCED_VEHICLE_LISTS_HELPTEXT :Ippermetti l-uz ###length 3 -###length 3 +###length 4 @@ -974,6 +974,8 @@ STR_MAPGEN_BY :{BLACK}* # Strings for map borders at game generation +###length 3 + # SE Map generation diff --git a/src/lang/maori.txt b/src/lang/maori.txt index 0e1f95a9fcd58..c48be32287fe2 100644 --- a/src/lang/maori.txt +++ b/src/lang/maori.txt @@ -2158,7 +2158,7 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_SI :SI (kN) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT :Waeine teitei: {STRING} STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_HELPTEXT :Ina whakaaria he teitei i te tāhono kaiwhakamahi, whakaaria i te waeine kua tīpakona -###length 3 +###length 4 STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_IMPERIAL :Ingarangi (ft) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_METRIC :Ngahuru (m) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_SI :SI (m) @@ -3426,6 +3426,8 @@ STR_MAPGEN_SOUTHWEST :{BLACK}Tongamā STR_MAPGEN_BORDER_FREEFORM :{BLACK}Hanga noa STR_MAPGEN_BORDER_WATER :{BLACK}Wai STR_MAPGEN_BORDER_RANDOM :{BLACK}Matapōkere + +###length 3 STR_MAPGEN_BORDER_RANDOMIZE :{BLACK}Matapōkere STR_MAPGEN_BORDER_MANUAL :{BLACK}Ā-ringa @@ -3466,7 +3468,6 @@ STR_GENERATION_LANDSCAPE_GENERATION :{BLACK}Hanga wh STR_GENERATION_RIVER_GENERATION :{BLACK}Hanga awa STR_GENERATION_CLEARING_TILES :{BLACK}Hanga rohe tuarangaranga, tokatoka hoki STR_GENERATION_TOWN_GENERATION :{BLACK}Hanga tāone -STR_GENERATION_INDUSTRY_GENERATION :{BLACK}Hanga ahumahi STR_GENERATION_OBJECT_GENERATION :{BLACK}Hanga mea STR_GENERATION_TREE_GENERATION :{BLACK}Hanga rākau STR_GENERATION_SETTINGUP_GAME :{BLACK}Whakatatū i te kēmu @@ -3686,7 +3687,6 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}Tāurua STR_TOWN_DIRECTORY_CAPTION :{WHITE}Tāone ({COMMA} o te {COMMA}) STR_TOWN_DIRECTORY_NONE :{ORANGE}- Kore - STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) -STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (Tāone nui){BLACK} ({COMMA}) STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}Ingoa o ngā tāone - pāwhiria he ingoa kia neke i te tirohanga matua ki te tāone. Pātaki+Pāwhiri kia huaki i tētahi atu tirohanga i te tauwāhi o te tāone STR_TOWN_POPULATION :{BLACK}Taupori o te ao: {COMMA} @@ -5262,11 +5262,6 @@ STR_ERROR_START_AND_END_MUST_BE_IN :{WHITE}Me tōti STR_ERROR_ENDS_OF_BRIDGE_MUST_BOTH :{WHITE}... me tū ki te whenua ngā pito e rua o te arawhiti STR_ERROR_BRIDGE_TOO_LONG :{WHITE}... he roa rawa te arawhiti STR_ERROR_BRIDGE_THROUGH_MAP_BORDER :{WHITE}Ka mutu te arawhiti i waho i te mahere -STR_ERROR_BRIDGE_TOO_LOW_FOR_STATION :{WHITE}He hakahaka rawa te arawhiti mō te teihana -STR_ERROR_BRIDGE_TOO_LOW_FOR_ROADSTOP :{WHITE}He hakahaka rawa te arawhiti mō te tūnga rori -STR_ERROR_BRIDGE_TOO_LOW_FOR_BUOY :{WHITE}He hakahaka rawa te arawhiti mō te kārewa -STR_ERROR_BRIDGE_TOO_LOW_FOR_RAIL_WAYPOINT :{WHITE}He hakahaka rawa te arawhiti mō te aratohu rerewhenua -STR_ERROR_BRIDGE_TOO_LOW_FOR_ROAD_WAYPOINT :{WHITE}He hakahaka rawa te arawhiti mō te aratohu rori # Tunnel related errors STR_ERROR_CAN_T_BUILD_TUNNEL_HERE :{WHITE}Tē taea te hanga te anaroa i konei... diff --git a/src/lang/marathi.txt b/src/lang/marathi.txt index 7df164e113c3f..cb308dabb23c6 100644 --- a/src/lang/marathi.txt +++ b/src/lang/marathi.txt @@ -1042,7 +1042,7 @@ STR_CONFIG_SETTING_STATUSBAR_POS :स्टेट ###length 3 -###length 3 +###length 4 @@ -1324,6 +1324,8 @@ STR_MAPGEN_TOWN_NAME_ITALIAN :ईटेलि # Strings for map borders at game generation STR_MAPGEN_BORDER_WATER :{BLACK}पाणी +###length 3 + STR_MAPGEN_HEIGHTMAP_SIZE :{ORANGE}{NUM} x {NUM} diff --git a/src/lang/norwegian_bokmal.txt b/src/lang/norwegian_bokmal.txt index da763e6bdb617..454c7c84819e0 100644 --- a/src/lang/norwegian_bokmal.txt +++ b/src/lang/norwegian_bokmal.txt @@ -256,6 +256,7 @@ STR_UNITS_FORCE_SI :{DECIMAL}{NBSP} STR_UNITS_HEIGHT_IMPERIAL :{DECIMAL}{NBSP}fot STR_UNITS_HEIGHT_METRIC :{DECIMAL}{NBSP}m STR_UNITS_HEIGHT_SI :{DECIMAL}{NBSP}m +STR_UNITS_HEIGHT_GAMEUNITS :{DECIMAL}{NBSP}nivå{P "" er} # Time units used in string control characters STR_UNITS_DAYS :{COMMA}{NBSP}dag{P "" er} @@ -2160,10 +2161,11 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_SI :SI (kN) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT :Høydeenheter: {STRING} STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_HELPTEXT :Når en høyde vises i brukergrensesnittet, vis den i de valgte enhetene -###length 3 +###length 4 STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_IMPERIAL :Imperisk (fot) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_METRIC :Metrisk (m) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_SI :SI (m) +STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_GAMEUNITS :Spillenheter (nivåer) STR_CONFIG_SETTING_LOCALISATION :Lokalisering STR_CONFIG_SETTING_GRAPHICS :Grafikk @@ -3427,11 +3429,18 @@ STR_MAPGEN_NORTHWEST :{BLACK}Nordvest STR_MAPGEN_NORTHEAST :{BLACK}Nordøst STR_MAPGEN_SOUTHEAST :{BLACK}Sørøst STR_MAPGEN_SOUTHWEST :{BLACK}Sørvest +STR_MAPGEN_NORTHWEST_TOOLTIP :Veksle mellom vann eller fri kant ved nordvestre kartkant +STR_MAPGEN_NORTHEAST_TOOLTIP :Veksle mellom vann eller fri kant ved nordøstre kartkant +STR_MAPGEN_SOUTHEAST_TOOLTIP :Veksle mellom vann eller fri kant ved sørøstre kartkant +STR_MAPGEN_SOUTHWEST_TOOLTIP :Veksle mellom vann eller fri kant ved sørvestre kartkant STR_MAPGEN_BORDER_FREEFORM :{BLACK}Frihånds STR_MAPGEN_BORDER_WATER :{BLACK}Sjø STR_MAPGEN_BORDER_RANDOM :{BLACK}Tilfeldig -STR_MAPGEN_BORDER_RANDOMIZE :{BLACK}Tilfeldige -STR_MAPGEN_BORDER_MANUAL :{BLACK}Manuelle + +###length 3 +STR_MAPGEN_BORDER_RANDOMIZE :Tilfeldige +STR_MAPGEN_BORDER_MANUAL :Manuelle +STR_MAPGEN_BORDER_INFINITE_WATER :Uendelig vann STR_MAPGEN_HEIGHTMAP_ROTATION :{BLACK}Høydekartrotering: STR_MAPGEN_HEIGHTMAP_NAME :{BLACK}Høydekartnavn: @@ -3467,10 +3476,11 @@ STR_GENERATION_PROGRESS :{WHITE}{NUM}{NB STR_GENERATION_PROGRESS_NUM :{BLACK}{NUM} / {NUM} STR_GENERATION_WORLD_GENERATION :{BLACK}Generer en verden STR_GENERATION_LANDSCAPE_GENERATION :{BLACK}Landskapsgenerering -STR_GENERATION_RIVER_GENERATION :{BLACK}Skap elver +STR_GENERATION_RIVER_GENERATION :{BLACK}Elvegenerering STR_GENERATION_CLEARING_TILES :{BLACK}Generering av ulendt og steinete område STR_GENERATION_TOWN_GENERATION :{BLACK}Bygenerering -STR_GENERATION_INDUSTRY_GENERATION :{BLACK}Industrigenerering +STR_GENERATION_LAND_INDUSTRY_GENERATION :{BLACK}Landindustrigenerering +STR_GENERATION_WATER_INDUSTRY_GENERATION :{BLACK}Vannindustrigenerering STR_GENERATION_OBJECT_GENERATION :{BLACK}Objektgenerering STR_GENERATION_TREE_GENERATION :{BLACK}Tregenerering STR_GENERATION_SETTINGUP_GAME :{BLACK}Klargjør spillet @@ -3690,7 +3700,7 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}Skriv in STR_TOWN_DIRECTORY_CAPTION :{WHITE}Byer ({COMMA} av {COMMA}) STR_TOWN_DIRECTORY_NONE :{ORANGE}- Ingen - STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) -STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (By){BLACK} ({COMMA}) +STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{BLACK} ({COMMA}) {YELLOW}{CITY_ICON} STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}Bynavn - klikk på navnet for å gå til byen. Ctrl+klikk for å åpne et nytt tilleggsvindu over byen STR_TOWN_POPULATION :{BLACK}Verdensbefolkning: {COMMA} @@ -5268,13 +5278,13 @@ STR_ERROR_START_AND_END_MUST_BE_IN :{WHITE}Start og STR_ERROR_ENDS_OF_BRIDGE_MUST_BOTH :{WHITE}...{NBSP}broens ender må være på land STR_ERROR_BRIDGE_TOO_LONG :{WHITE}... broen er for lang STR_ERROR_BRIDGE_THROUGH_MAP_BORDER :{WHITE}Bro vil ende utenfor kartet -STR_ERROR_BRIDGE_TOO_LOW_FOR_STATION :{WHITE}Broen er for lav for en stasjon -STR_ERROR_BRIDGE_TOO_LOW_FOR_ROADSTOP :{WHITE}Broen er for lav for en holdeplass -STR_ERROR_BRIDGE_TOO_LOW_FOR_DOCK :{WHITE}Broen er for lav for en havn -STR_ERROR_BRIDGE_TOO_LOW_FOR_BUOY :{WHITE}Broen er for lav for en bøye -STR_ERROR_BRIDGE_TOO_LOW_FOR_RAIL_WAYPOINT :{WHITE}Broen er for lav for et veipunkt -STR_ERROR_BRIDGE_TOO_LOW_FOR_ROAD_WAYPOINT :{WHITE}Broen er for lav for et veipunkt -STR_ERROR_BRIDGE_TOO_LOW_FOR_LOCK :{WHITE}Broen er for lav for en sluse +STR_ERROR_BRIDGE_TOO_LOW_FOR_STATION :{WHITE}Broen er {HEIGHT} for lav for en stasjon +STR_ERROR_BRIDGE_TOO_LOW_FOR_ROADSTOP :{WHITE}Broen er {HEIGHT} for lav for en holdeplass +STR_ERROR_BRIDGE_TOO_LOW_FOR_DOCK :{WHITE}Broen er {HEIGHT} for lav for en havn +STR_ERROR_BRIDGE_TOO_LOW_FOR_BUOY :{WHITE}Broen er {HEIGHT} for lav for en bøye +STR_ERROR_BRIDGE_TOO_LOW_FOR_RAIL_WAYPOINT :{WHITE}Broen er {HEIGHT} for lav for et veipunkt +STR_ERROR_BRIDGE_TOO_LOW_FOR_ROAD_WAYPOINT :{WHITE}Broen er {HEIGHT} for lav for et veipunkt +STR_ERROR_BRIDGE_TOO_LOW_FOR_LOCK :{WHITE}Broen er {HEIGHT} for lav for en sluse # Tunnel related errors STR_ERROR_CAN_T_BUILD_TUNNEL_HERE :{WHITE}Kan ikke bygge tunnel her... diff --git a/src/lang/norwegian_nynorsk.txt b/src/lang/norwegian_nynorsk.txt index 1c71fe8533e76..290c4c01b1a13 100644 --- a/src/lang/norwegian_nynorsk.txt +++ b/src/lang/norwegian_nynorsk.txt @@ -1747,7 +1747,7 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_SI :SI (kN) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT :Eining for høgde: {STRING} STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_HELPTEXT :Bruk vald eining for å vise høgde -###length 3 +###length 4 STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_IMPERIAL :Britisk eining (ft) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_METRIC :Metrisk (m) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_SI :SI (m) @@ -2710,6 +2710,8 @@ STR_MAPGEN_SOUTHWEST :{BLACK}Sørvest STR_MAPGEN_BORDER_FREEFORM :{BLACK}Frihands STR_MAPGEN_BORDER_WATER :{BLACK}Vatn STR_MAPGEN_BORDER_RANDOM :{BLACK}Tilfeldig + +###length 3 STR_MAPGEN_BORDER_RANDOMIZE :{BLACK}Tilfeldig STR_MAPGEN_BORDER_MANUAL :{BLACK}Manuell diff --git a/src/lang/persian.txt b/src/lang/persian.txt index 86037e1e7796a..b91113615007c 100644 --- a/src/lang/persian.txt +++ b/src/lang/persian.txt @@ -1728,7 +1728,7 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_METRIC :متریک (kgf STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_SI :SI (kN) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT :واحدهای ارتفاع: {STRING} -###length 3 +###length 4 STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_IMPERIAL :امپریال (ft) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_METRIC :متریک (m) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_SI :متر (m) @@ -2785,6 +2785,8 @@ STR_MAPGEN_SOUTHWEST :{BLACK}جنوب STR_MAPGEN_BORDER_FREEFORM :{BLACK}قالب آزاد STR_MAPGEN_BORDER_WATER :{BLACK}دریا STR_MAPGEN_BORDER_RANDOM :{BLACK}تصادفی + +###length 3 STR_MAPGEN_BORDER_RANDOMIZE :{BLACK}تصادفی STR_MAPGEN_BORDER_MANUAL :{BLACK}دستی @@ -3001,7 +3003,6 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}برای STR_TOWN_DIRECTORY_CAPTION :{WHITE}شهرها ({COMMA} از {COMMA}) STR_TOWN_DIRECTORY_NONE :{ORANGE}- هیچکدام - STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) -STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (City){BLACK} ({COMMA}) STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}نام شهرها - برای مرکز قرار دادن نمای اصلی روی شهر، روی نام کلیک کنید. Ctrl+Click برای باز کردن یک نمای جدید در موقعیت شهر. STR_TOWN_POPULATION :{BLACK}جمعیت جهان: {COMMA} diff --git a/src/lang/polish.txt b/src/lang/polish.txt index e620986c82d13..f4c6d6274b079 100644 --- a/src/lang/polish.txt +++ b/src/lang/polish.txt @@ -633,6 +633,7 @@ STR_UNITS_FORCE_SI :{DECIMAL}{NBSP} STR_UNITS_HEIGHT_IMPERIAL :{DECIMAL}{NBSP}st{P opa opy óp} STR_UNITS_HEIGHT_METRIC :{DECIMAL}{NBSP}m STR_UNITS_HEIGHT_SI :{DECIMAL}{NBSP}m +STR_UNITS_HEIGHT_GAMEUNITS :{DECIMAL}{NBSP}poziom{P "" y ów} # Time units used in string control characters STR_UNITS_DAYS :{COMMA}{NBSP}d{P zień ni ni} @@ -2538,10 +2539,11 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_SI :SI (kN) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT :Jednostki wysokości: {STRING} STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_HELPTEXT :Jeśli kiedykolwiek wysokości są pokazywane w interfejsie użytkownika, pokaż je w wybranych jednostkach -###length 3 +###length 4 STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_IMPERIAL :Imperialne (ft) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_METRIC :Metryczne (m) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_SI :SI (m) +STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_GAMEUNITS :Jednostki gry (poziomy) STR_CONFIG_SETTING_LOCALISATION :Lokalizacja STR_CONFIG_SETTING_GRAPHICS :Grafika @@ -2926,7 +2928,7 @@ STR_NETWORK_ASK_RELAY_NO :{BLACK}Nie STR_NETWORK_ASK_RELAY_YES_ONCE :{BLACK}Tak, ten jeden raz STR_NETWORK_ASK_RELAY_YES_ALWAYS :{BLACK}Tak, nie pytaj ponownie -STR_NETWORK_ASK_SURVEY_CAPTION :Uczestniczyć w automatycznej ankiecie? +STR_NETWORK_ASK_SURVEY_CAPTION :Uczestnictwo w automatycznej ankiecie? STR_NETWORK_ASK_SURVEY_TEXT :Czy chcesz wziąć udział w automatycznej ankiecie?{}OpenTTD prześle ankietę przy opuszczaniu gry.{}Możesz to zmienić w dowolnym momencie w „Opcjach gry”. STR_NETWORK_ASK_SURVEY_PREVIEW :Podejrzyj wynik ankiety STR_NETWORK_ASK_SURVEY_LINK :O ankiecie i prywatności @@ -3805,11 +3807,18 @@ STR_MAPGEN_NORTHWEST :{BLACK}Płn.-za STR_MAPGEN_NORTHEAST :{BLACK}Płn.-wsch. STR_MAPGEN_SOUTHEAST :{BLACK}Płd.-wsch. STR_MAPGEN_SOUTHWEST :{BLACK}Płd.-zach. +STR_MAPGEN_NORTHWEST_TOOLTIP :Przełącz między wodą a lądem na płn.-zach. krawędzi mapy +STR_MAPGEN_NORTHEAST_TOOLTIP :Przełącz między wodą a lądem na płn.-wsch. krawędzi mapy +STR_MAPGEN_SOUTHEAST_TOOLTIP :Przełącz między wodą a lądem na płd.-wsch. krawędzi mapy +STR_MAPGEN_SOUTHWEST_TOOLTIP :Przełącz między wodą a lądem na płd.-zach. krawędzi mapy STR_MAPGEN_BORDER_FREEFORM :{BLACK}Ląd STR_MAPGEN_BORDER_WATER :{BLACK}Woda STR_MAPGEN_BORDER_RANDOM :{BLACK}Losowe -STR_MAPGEN_BORDER_RANDOMIZE :{BLACK}Losowo -STR_MAPGEN_BORDER_MANUAL :{BLACK}Użytkownika + +###length 3 +STR_MAPGEN_BORDER_RANDOMIZE :Losowe +STR_MAPGEN_BORDER_MANUAL :Ustalone +STR_MAPGEN_BORDER_INFINITE_WATER :Bezkres Wód STR_MAPGEN_HEIGHTMAP_ROTATION :{BLACK}Obrót mapy wysokości: STR_MAPGEN_HEIGHTMAP_NAME :{BLACK}Nazwa mapy wysokosci: @@ -3848,7 +3857,8 @@ STR_GENERATION_LANDSCAPE_GENERATION :{BLACK}Tworzeni STR_GENERATION_RIVER_GENERATION :{BLACK}Tworzenie rzek STR_GENERATION_CLEARING_TILES :{BLACK}Tworzenie terenów skalistych i nierówności STR_GENERATION_TOWN_GENERATION :{BLACK}Tworzenie miast -STR_GENERATION_INDUSTRY_GENERATION :{BLACK}Rozmieszczanie przedsiębiorstw +STR_GENERATION_LAND_INDUSTRY_GENERATION :{BLACK}Tworzenie przemysłu na lądzie +STR_GENERATION_WATER_INDUSTRY_GENERATION :{BLACK}Tworzenie przemysłu na wodzie STR_GENERATION_OBJECT_GENERATION :{BLACK}Rozmieszczanie obiektów STR_GENERATION_TREE_GENERATION :{BLACK}Rozmieszczanie drzew STR_GENERATION_SETTINGUP_GAME :{BLACK}Konfigurowanie rozgrywki @@ -4068,7 +4078,7 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}Wpisz na STR_TOWN_DIRECTORY_CAPTION :{WHITE}Miasta ({COMMA} z {COMMA}) STR_TOWN_DIRECTORY_NONE :{ORANGE}- Żaden - STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) -STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (Metropolia){BLACK} ({COMMA}) +STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{BLACK} ({COMMA}) {YELLOW}{CITY_ICON} STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}Nazwy miast - kliknij na nazwę miasta, aby wyśrodkować na nim widok główny. Użyj Ctrl, aby otworzyć nowy podgląd na lokalizację miasta STR_TOWN_POPULATION :{BLACK}Populacja świata: {COMMA} @@ -5652,13 +5662,13 @@ STR_ERROR_START_AND_END_MUST_BE_IN :{WHITE}Począte STR_ERROR_ENDS_OF_BRIDGE_MUST_BOTH :{WHITE}... końce mostu muszą znajdować się na lądzie STR_ERROR_BRIDGE_TOO_LONG :{WHITE}... za długi most STR_ERROR_BRIDGE_THROUGH_MAP_BORDER :{WHITE}Koniec mostu poza mapą -STR_ERROR_BRIDGE_TOO_LOW_FOR_STATION :{WHITE}Most jest zbyt niski dla stacji -STR_ERROR_BRIDGE_TOO_LOW_FOR_ROADSTOP :{WHITE}Most jest zbyt niski dla przystanku -STR_ERROR_BRIDGE_TOO_LOW_FOR_DOCK :{WHITE}Most jest zbyt niski dla portu -STR_ERROR_BRIDGE_TOO_LOW_FOR_BUOY :{WHITE}Most jest zbyt niski dla boi -STR_ERROR_BRIDGE_TOO_LOW_FOR_RAIL_WAYPOINT :{WHITE}Most jest zbyt niski dla posterunku kolejowego -STR_ERROR_BRIDGE_TOO_LOW_FOR_ROAD_WAYPOINT :{WHITE}Most jest zbyt niski dla posterunku drogowego -STR_ERROR_BRIDGE_TOO_LOW_FOR_LOCK :{WHITE}Most jest zbyt niski dla śluzy +STR_ERROR_BRIDGE_TOO_LOW_FOR_STATION :{WHITE}Most jest o {HEIGHT} za niski dla stacji +STR_ERROR_BRIDGE_TOO_LOW_FOR_ROADSTOP :{WHITE}Most jest o {HEIGHT} za niski dla przystanku +STR_ERROR_BRIDGE_TOO_LOW_FOR_DOCK :{WHITE}Most jest o {HEIGHT} za niski dla portu +STR_ERROR_BRIDGE_TOO_LOW_FOR_BUOY :{WHITE}Most jest o {HEIGHT} za niski dla boi +STR_ERROR_BRIDGE_TOO_LOW_FOR_RAIL_WAYPOINT :{WHITE}Most jest o {HEIGHT} za niski dla posterunku kolejowego +STR_ERROR_BRIDGE_TOO_LOW_FOR_ROAD_WAYPOINT :{WHITE}Most jest o {HEIGHT} za niski dla posterunku drogowego +STR_ERROR_BRIDGE_TOO_LOW_FOR_LOCK :{WHITE}Most jest o {HEIGHT} za niski dla śluzy # Tunnel related errors STR_ERROR_CAN_T_BUILD_TUNNEL_HERE :{WHITE}Nie można tutaj zbudować tunelu... diff --git a/src/lang/portuguese.txt b/src/lang/portuguese.txt index 6c1aa845e9c74..d1c5d94cc7b12 100644 --- a/src/lang/portuguese.txt +++ b/src/lang/portuguese.txt @@ -138,7 +138,7 @@ STR_ABBREV_GOODS :BN STR_ABBREV_GRAIN :CR STR_ABBREV_WOOD :MD STR_ABBREV_IRON_ORE :FR -STR_ABBREV_STEEL :AC +STR_ABBREV_STEEL :AÇ STR_ABBREV_VALUABLES :VL STR_ABBREV_COPPER_ORE :CO STR_ABBREV_MAIZE :ML @@ -150,14 +150,14 @@ STR_ABBREV_GOLD :OU STR_ABBREV_WATER :AG STR_ABBREV_WHEAT :TR STR_ABBREV_RUBBER :BR -STR_ABBREV_SUGAR :AÇ +STR_ABBREV_SUGAR :AÚ STR_ABBREV_TOYS :BQ STR_ABBREV_SWEETS :DC STR_ABBREV_COLA :CL STR_ABBREV_CANDYFLOSS :AD STR_ABBREV_BUBBLES :BO STR_ABBREV_TOFFEE :CM -STR_ABBREV_BATTERIES :BA +STR_ABBREV_BATTERIES :PI STR_ABBREV_PLASTIC :PL STR_ABBREV_FIZZY_DRINKS :RF STR_ABBREV_ALL :TODOS @@ -255,6 +255,7 @@ STR_UNITS_FORCE_SI :{DECIMAL}{NBSP} STR_UNITS_HEIGHT_IMPERIAL :{DECIMAL}{NBSP}pé{P "" s} STR_UNITS_HEIGHT_METRIC :{DECIMAL}{NBSP}m STR_UNITS_HEIGHT_SI :{DECIMAL}{NBSP}m +STR_UNITS_HEIGHT_GAMEUNITS :{DECIMAL}{NBSP}níve{P l is} # Time units used in string control characters STR_UNITS_DAYS :{COMMA}{NBSP}dia{P "" s} @@ -618,7 +619,7 @@ STR_GRAPH_Y_LABEL_NUMBER :{TINY_FONT}{COM STR_GRAPH_OPERATING_PROFIT_CAPTION :{WHITE}Gráfico do Lucro Operacional STR_GRAPH_INCOME_CAPTION :{WHITE}Gráfico de Rendimentos STR_GRAPH_CARGO_DELIVERED_CAPTION :{WHITE}Unidades de carga entregues -STR_GRAPH_COMPANY_PERFORMANCE_RATINGS_CAPTION :{WHITE}Classificações do desempenho da empresa (máximo=1000) +STR_GRAPH_COMPANY_PERFORMANCE_RATINGS_CAPTION :{WHITE}Classificações do desempenho da empresa (máx. 1000) STR_GRAPH_COMPANY_VALUES_CAPTION :{WHITE}Gráfico de Valor da Empresa STR_GRAPH_LAST_24_MINUTES_TIME_LABEL :{TINY_FONT}{BLACK}Últimos 24 minutos @@ -635,7 +636,7 @@ STR_GRAPH_SELECT_SCALE :Alterar a escal STR_GRAPH_CARGO_PAYMENT_RATES_CAPTION :{WHITE}Tarifas por tipo de carga STR_GRAPH_CARGO_PAYMENT_RATES_DAYS :{TINY_FONT}{BLACK}Dias em trânsito STR_GRAPH_CARGO_PAYMENT_RATES_SECONDS :{TINY_FONT}{BLACK}Segundos em trânsito -STR_GRAPH_CARGO_PAYMENT_RATES_TITLE :{TINY_FONT}{BLACK}Pagamento por entregar 10 unidades (ou 10 000 litros) de carga numa distância de 20 quadrados +STR_GRAPH_CARGO_PAYMENT_RATES_TITLE :{TINY_FONT}{BLACK}Pagamento por entregar 10 unidades (ou 10 000 litros) de carga numa distância de 20 mosaicos STR_GRAPH_CARGO_ENABLE_ALL :{TINY_FONT}{BLACK}Todos STR_GRAPH_CARGO_DISABLE_ALL :{TINY_FONT}{BLACK}Nenhum STR_GRAPH_CARGO_TOOLTIP_ENABLE_ALL :{BLACK}Mostrar todas as cargas no gráfico @@ -760,7 +761,7 @@ STR_HIGHSCORE_PERFORMANCE_TITLE_ENTREPRENEUR :Empreendedor STR_HIGHSCORE_PERFORMANCE_TITLE_INDUSTRIALIST :Industrialista STR_HIGHSCORE_PERFORMANCE_TITLE_CAPITALIST :Capitalista STR_HIGHSCORE_PERFORMANCE_TITLE_MAGNATE :Magnata -STR_HIGHSCORE_PERFORMANCE_TITLE_MOGUL :Grande Magnata +STR_HIGHSCORE_PERFORMANCE_TITLE_MOGUL :Barão STR_HIGHSCORE_PERFORMANCE_TITLE_TYCOON_OF_THE_CENTURY :Magnata do Século STR_HIGHSCORE_NAME :{PRESIDENT_NAME}, {COMPANY} STR_HIGHSCORE_STATS :{BIG_FONT}"{STRING}" ({COMMA}) @@ -1057,7 +1058,7 @@ STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_60_MINUTES :A cada 60 minut STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_120_MINUTES :A cada 120 minutos STR_GAME_OPTIONS_LANGUAGE :Língua -STR_GAME_OPTIONS_LANGUAGE_TOOLTIP :Selecionar a Língua da interface do jogo +STR_GAME_OPTIONS_LANGUAGE_TOOLTIP :Selecionar a língua da interface do jogo STR_GAME_OPTIONS_LANGUAGE_PERCENTAGE :{STRING} ({NUM}% concluído) STR_GAME_OPTIONS_FULLSCREEN :Ecrã Inteiro @@ -1096,9 +1097,9 @@ STR_GAME_OPTIONS_GUI_SCALE_MARK :{DECIMAL}x STR_GAME_OPTIONS_PARTICIPATE_SURVEY_FRAME :Sondagem automatizada STR_GAME_OPTIONS_PARTICIPATE_SURVEY :Participar numa sondagem automatizada -STR_GAME_OPTIONS_PARTICIPATE_SURVEY_TOOLTIP :Quando ativo, o OpenTTD transmitirá uma sondagem ao deixar um jogo +STR_GAME_OPTIONS_PARTICIPATE_SURVEY_TOOLTIP :Quando ativo, o OpenTTD enviará dados para sondagem ao sair de um jogo STR_GAME_OPTIONS_PARTICIPATE_SURVEY_LINK :Sobre sondagem e privacidade -STR_GAME_OPTIONS_PARTICIPATE_SURVEY_LINK_TOOLTIP :Isto abre um navegador com mais informações sobre a sondagem automatizada +STR_GAME_OPTIONS_PARTICIPATE_SURVEY_LINK_TOOLTIP :Isto abre o navegador com mais informações sobre a sondagem automatizada STR_GAME_OPTIONS_PARTICIPATE_SURVEY_PREVIEW :Pré-visualizar resultado da sondagem STR_GAME_OPTIONS_PARTICIPATE_SURVEY_PREVIEW_TOOLTIP :Mostrar o resultado da sondagem do jogo atual a decorrer @@ -1159,11 +1160,11 @@ STR_CURRENCY_SET_CUSTOM_CURRENCY_PREFIX_TOOLTIP :{BLACK}Definir STR_CURRENCY_SUFFIX :{LTBLUE}Sufixo: {ORANGE}{STRING} STR_CURRENCY_SET_CUSTOM_CURRENCY_SUFFIX_TOOLTIP :{BLACK}Definir o sufixo para a sua moeda -STR_CURRENCY_SWITCH_TO_EURO :{LTBLUE}Mudar para o Euro: {ORANGE}{NUM} -STR_CURRENCY_SWITCH_TO_EURO_NEVER :{LTBLUE}Mudar para o Euro: {ORANGE}Nunca +STR_CURRENCY_SWITCH_TO_EURO :{LTBLUE}Mudar para o Euro em: {ORANGE}{NUM} +STR_CURRENCY_SWITCH_TO_EURO_NEVER :{LTBLUE}Mudar para o Euro em: {ORANGE}Nunca STR_CURRENCY_SET_CUSTOM_CURRENCY_TO_EURO_TOOLTIP :{BLACK}Definir o ano para mudar para o Euro -STR_CURRENCY_DECREASE_CUSTOM_CURRENCY_TO_EURO_TOOLTIP :{BLACK}Mudar para Euro mais cedo -STR_CURRENCY_INCREASE_CUSTOM_CURRENCY_TO_EURO_TOOLTIP :{BLACK}Mudar para Euro mais tarde +STR_CURRENCY_DECREASE_CUSTOM_CURRENCY_TO_EURO_TOOLTIP :{BLACK}Mudar para o Euro mais cedo +STR_CURRENCY_INCREASE_CUSTOM_CURRENCY_TO_EURO_TOOLTIP :{BLACK}Mudar para o Euro mais tarde STR_CURRENCY_PREVIEW :{LTBLUE}Pré-visualizar: {ORANGE}{CURRENCY_LONG} STR_CURRENCY_CUSTOM_CURRENCY_PREVIEW_TOOLTIP :{BLACK}10000 Libras (£) na sua moeda @@ -1262,8 +1263,8 @@ STR_CONFIG_SETTING_RESTRICT_CATEGORY :Categoria: STR_CONFIG_SETTING_RESTRICT_TYPE :Tipo: STR_CONFIG_SETTING_RESTRICT_DROPDOWN_HELPTEXT :Restringe a lista abaixo para mostrar apenas opções modificadas STR_CONFIG_SETTING_RESTRICT_BASIC :Opções básicas (mostrar apenas definições importantes) -STR_CONFIG_SETTING_RESTRICT_ADVANCED :Avançado (mostra grande parte das definições) -STR_CONFIG_SETTING_RESTRICT_ALL :Avançado (mostrar todas as definições, incluindo as que são estranhas) +STR_CONFIG_SETTING_RESTRICT_ADVANCED :Avançada (mostra grande parte das definições) +STR_CONFIG_SETTING_RESTRICT_ALL :Especialista (mostrar todas as definições, incluindo as que são mais estranhas) STR_CONFIG_SETTING_RESTRICT_CHANGED_AGAINST_DEFAULT :Opções com um valor diferente das de origem STR_CONFIG_SETTING_RESTRICT_CHANGED_AGAINST_NEW :Preferências com um valor diferente das preferências para novos jogos @@ -1370,7 +1371,7 @@ STR_CONFIG_SETTING_AUTOSLOPE :Permitir desní STR_CONFIG_SETTING_AUTOSLOPE_HELPTEXT :Permite alteração de terra sob edifícios e vias sem os remover STR_CONFIG_SETTING_CATCHMENT :Dimensionamento mais realista de áreas de abrangência: {STRING} -STR_CONFIG_SETTING_CATCHMENT_HELPTEXT :Haver diferentes áreas de cobertura para diferentes tipos de estações e aeroportos +STR_CONFIG_SETTING_CATCHMENT_HELPTEXT :Para ter diferentes áreas de cobertura para diferentes tipos de estações e aeroportos STR_CONFIG_SETTING_SERVE_NEUTRAL_INDUSTRIES :Estações da empresa podem servir indústrias com estações neutras anexadas: {STRING} STR_CONFIG_SETTING_SERVE_NEUTRAL_INDUSTRIES_HELPTEXT :Quando ativo, indústrias com estações incluídas (com as Petrolíferas) podem ser servidas por estações-da-empresa construídas nas redondezas. Quando inativo, estas indústrias só podem ser servidas pela sua própria estação. Qualquer estação da empresa não poderá servir a indústria, nem a estação incluída pode servir outra entidade senão a própria indústria @@ -1458,7 +1459,7 @@ STR_CONFIG_SETTING_AUTOSCROLL :Deslocar janela STR_CONFIG_SETTING_AUTOSCROLL_HELPTEXT :Quando ativo, os visualizadores começam a deslocar-se logo que o rato esteja no extremo da janela ###length 4 STR_CONFIG_SETTING_AUTOSCROLL_DISABLED :Desativado -STR_CONFIG_SETTING_AUTOSCROLL_MAIN_VIEWPORT_FULLSCREEN :Visualizador principal, só ecrã cheio +STR_CONFIG_SETTING_AUTOSCROLL_MAIN_VIEWPORT_FULLSCREEN :Visualizador principal, só em ecrã inteiro STR_CONFIG_SETTING_AUTOSCROLL_MAIN_VIEWPORT :Visualizador principal STR_CONFIG_SETTING_AUTOSCROLL_EVERY_VIEWPORT :Todos os visualizadores @@ -1488,7 +1489,7 @@ STR_CONFIG_SETTING_PLANE_SPEED :Fator de veloci STR_CONFIG_SETTING_PLANE_SPEED_HELPTEXT :Definir a velocidade relativa dos aviões em comparação com outros tipos de veículos, para reduzir o valor da receita do transporte por aeronave STR_CONFIG_SETTING_PLANE_SPEED_VALUE :1 / {COMMA} -STR_CONFIG_SETTING_PLANE_CRASHES :Número de acidentes de aeronaves: {STRING} +STR_CONFIG_SETTING_PLANE_CRASHES :Quantidade de acidentes de aeronaves: {STRING} STR_CONFIG_SETTING_PLANE_CRASHES_HELPTEXT :Indicar a hipótese da ocorrência de um acidente aéreo.{}* As aeronaves maiores tem um risco acrescido a despenhar quando aterram em aeroportos pequenos ###length 3 STR_CONFIG_SETTING_PLANE_CRASHES_NONE :Nenhum* @@ -1502,7 +1503,7 @@ STR_CONFIG_SETTING_STOP_ON_TOWN_ROAD :Permitir estaç STR_CONFIG_SETTING_STOP_ON_TOWN_ROAD_HELPTEXT :Permite a construção de estações de passagem nas ruas pertencentes a localidades. STR_CONFIG_SETTING_STOP_ON_COMPETITOR_ROAD :Permitir estações de passagem nas estradas detidas pelos competidores: {STRING} STR_CONFIG_SETTING_STOP_ON_COMPETITOR_ROAD_HELPTEXT :Permite a construção de estações de passagem nas estradas que são de outras empresas -STR_CONFIG_SETTING_DYNAMIC_ENGINES_EXISTING_VEHICLES :{WHITE}Não é possível mudar quando já existem veículos. +STR_CONFIG_SETTING_DYNAMIC_ENGINES_EXISTING_VEHICLES :{WHITE}Não é possível alterar esta configuração quando já existem veículos STR_CONFIG_SETTING_INFRASTRUCTURE_MAINTENANCE :Manutenção de infraestruturas: {STRING} STR_CONFIG_SETTING_INFRASTRUCTURE_MAINTENANCE_HELPTEXT :Quando ativo, as infraestruturas têm custos de manutenção. O custo cresce mais do que o proporcional com o tamanho da rede e assim afeta mais as empresas maiores do que as mais pequenas @@ -1559,7 +1560,7 @@ STR_CONFIG_SETTING_CARGO_SCALE_VALUE :{NUM}% STR_CONFIG_SETTING_AUTORENEW_VEHICLE :Renovar automaticamente os veículos quando estão a ficar velhos: {STRING} STR_CONFIG_SETTING_AUTORENEW_VEHICLE_HELPTEXT :Quando ativo, um veículo a chegar ao fim de vida é automaticamente substituído quando as condições de renovação estão reunidas -STR_CONFIG_SETTING_AUTORENEW_MONTHS :Renovar automaticamente quando um veículo chega a {STRING} a idade máxima +STR_CONFIG_SETTING_AUTORENEW_MONTHS :Renovar automaticamente quando um veículo chega a {STRING} da idade máxima STR_CONFIG_SETTING_AUTORENEW_MONTHS_HELPTEXT :Idade relativa a partir da qual um veículo deva ser indicado para a renovação automática ###length 2 STR_CONFIG_SETTING_AUTORENEW_MONTHS_VALUE_BEFORE :{COMMA} m{P 0 ês eses} antes @@ -1581,7 +1582,7 @@ STR_CONFIG_SETTING_POPULATION_IN_LABEL :Mostra populaç STR_CONFIG_SETTING_POPULATION_IN_LABEL_HELPTEXT :Mostrar a população das localidades na sua etiqueta no mapa STR_CONFIG_SETTING_GRAPH_LINE_THICKNESS :Espessura das linhas dos gráficos estatísticos: {STRING} -STR_CONFIG_SETTING_GRAPH_LINE_THICKNESS_HELPTEXT :Largura da linha nos gráficos. Uma linha mais estreita é de leitura mais precisa, enquanto uma linha mais espessa é mais fácil de ver e as cores distinguem-se melhor. +STR_CONFIG_SETTING_GRAPH_LINE_THICKNESS_HELPTEXT :Largura da linha nos gráficos estatísticos. Uma linha mais estreita é de leitura mais precisa, enquanto uma linha mais espessa é mais fácil de ver e as cores distinguem-se melhor. STR_CONFIG_SETTING_SHOW_NEWGRF_NAME :Mostrar o nome do NewGRF na janela de compra de veículos: {STRING} STR_CONFIG_SETTING_SHOW_NEWGRF_NAME_HELPTEXT :Adiciona uma linha à janela de compra de veículos, mostrando a qual "NewGRF" pertence o veículo selecionado @@ -1600,11 +1601,11 @@ STR_CONFIG_SETTING_LAND_GENERATOR_TERRA_GENESIS :TerraGenesis STR_CONFIG_SETTING_TERRAIN_TYPE :Tipo de terreno: {STRING} STR_CONFIG_SETTING_TERRAIN_TYPE_HELPTEXT :Escolher a altura das colinas e montanhas da paisagem -STR_CONFIG_SETTING_INDUSTRY_DENSITY :Densidade industrial: {STRING} +STR_CONFIG_SETTING_INDUSTRY_DENSITY :Nível de densidade industrial: {STRING} STR_CONFIG_SETTING_INDUSTRY_DENSITY_HELPTEXT :Define quantas indústrias devem ser geradas e que nível deve ser mantido durante o jogo STR_CONFIG_SETTING_OIL_REF_EDGE_DISTANCE :Distância máxima entre o limite do mapa e Refinarias de Petróleo: {STRING} -STR_CONFIG_SETTING_OIL_REF_EDGE_DISTANCE_HELPTEXT :Limite de distância entre a borda do mapa e o local de construção de refinarias e plataformas de petróleo. Em mapas de ilhas isto garante que elas fiquem perto da costa. Em mapas com mais de 256 quadrados esse valor é aumentado +STR_CONFIG_SETTING_OIL_REF_EDGE_DISTANCE_HELPTEXT :Limite de distância entre a borda do mapa e o local de construção de refinarias e plataformas de petróleo. Em mapas de ilhas isto garante que elas fiquem perto da costa. Em mapas com mais de 256 mosaicos esse valor é aumentado STR_CONFIG_SETTING_SNOWLINE_HEIGHT :Altura da linha de neve: {STRING} STR_CONFIG_SETTING_SNOWLINE_HEIGHT_HELPTEXT :Escolher a que altura a neve começa na paisagem subártica. A neve também afeta a geração de indústrias e os requisitos de crescimento das localidades. Só pode ser modificado através do Editor de Cenários ou é calculado através da "cobertura de neve" @@ -1656,11 +1657,11 @@ STR_CONFIG_SETTING_SE_FLAT_WORLD_HEIGHT :Altura com que STR_CONFIG_SETTING_EDGES_NOT_EMPTY :{WHITE}Um ou mais mosaicos no canto norte não estão vazios STR_CONFIG_SETTING_EDGES_NOT_WATER :{WHITE}Um ou mais mosaicos num dos cantos não têm água -STR_CONFIG_SETTING_STATION_SPREAD :Espalhamento das estações máximo: {STRING} -STR_CONFIG_SETTING_STATION_SPREAD_HELPTEXT :Área máxima pela qual uma estação pode estar distribuída. Nota que valores elevados irão abrandar o jogo +STR_CONFIG_SETTING_STATION_SPREAD :Máximo de distância de uma estação: {STRING} +STR_CONFIG_SETTING_STATION_SPREAD_HELPTEXT :Distância máxima pela qual uma estação pode estar distribuída. Nota que valores elevados irão abrandar o jogo STR_CONFIG_SETTING_SERVICEATHELIPAD :Manutenção automática de helicópteros em heliportos: {STRING} -STR_CONFIG_SETTING_SERVICEATHELIPAD_HELPTEXT :Efetuar manutenção aos helicópteros após cada aterragem, mesmo que não haja um hangar no aeroporto +STR_CONFIG_SETTING_SERVICEATHELIPAD_HELPTEXT :Efetuar manutenção aos helicópteros após cada aterragem, mesmo que não haja um hangar presente STR_CONFIG_SETTING_LINK_TERRAFORM_TOOLBAR :Ligar ferramentas de paisagem com as de construção: {STRING} STR_CONFIG_SETTING_LINK_TERRAFORM_TOOLBAR_HELPTEXT :Quando se abre a barra de construção para um tipo de transporte, abrir também a barra de terraplanagem @@ -1756,7 +1757,7 @@ STR_CONFIG_SETTING_DATE_FORMAT_IN_SAVE_NAMES_ISO :ISO (2008-12-31 STR_CONFIG_SETTING_PAUSE_ON_NEW_GAME :Pausar automaticamente ao iniciar um novo jogo: {STRING} STR_CONFIG_SETTING_PAUSE_ON_NEW_GAME_HELPTEXT :Quando ativo, o jogo ficará em pausa automaticamente num novo jogo, permitindo o estudo ao pormenor do mapa -STR_CONFIG_SETTING_COMMAND_PAUSE_LEVEL :Durante pausa permitir: {STRING} +STR_CONFIG_SETTING_COMMAND_PAUSE_LEVEL :Durante a pausa permitir: {STRING} STR_CONFIG_SETTING_COMMAND_PAUSE_LEVEL_HELPTEXT :Selecionar que ações podem ser feitas enquanto o jogo está em pausa ###length 4 STR_CONFIG_SETTING_COMMAND_PAUSE_LEVEL_NO_ACTIONS :Nenhuma ação @@ -1796,7 +1797,7 @@ STR_CONFIG_SETTING_SHOW_TRACK_RESERVATION_HELPTEXT :Dar cores difer STR_CONFIG_SETTING_PERSISTENT_BUILDINGTOOLS :Deixar ferramentas de construção ativas depois de usadas: {STRING} STR_CONFIG_SETTING_PERSISTENT_BUILDINGTOOLS_HELPTEXT :Manter as ferramentas de construção de pontes, túneis, etc. abertas após uso -STR_CONFIG_SETTING_AUTO_REMOVE_SIGNALS :Remover automaticamente os sinais durante a construção de vias férreas: {STRING} +STR_CONFIG_SETTING_AUTO_REMOVE_SIGNALS :Remover automaticamente os sinais durante a construção de linhas ferroviárias: {STRING} STR_CONFIG_SETTING_AUTO_REMOVE_SIGNALS_HELPTEXT :Remova automaticamente os sinais durante a construção da ferrovia se os sinais estiverem no caminho. Isto pode potencialmente causar acidentes de comboio STR_CONFIG_SETTING_FAST_FORWARD_SPEED_LIMIT :Limite de velocidade do avanço rápido: {STRING} @@ -1806,10 +1807,10 @@ STR_CONFIG_SETTING_FAST_FORWARD_SPEED_LIMIT_VAL :{NUM}% velocida STR_CONFIG_SETTING_FAST_FORWARD_SPEED_LIMIT_ZERO :Sem limite (tão rápido quanto o seu computador permitir) STR_CONFIG_SETTING_SOUND_TICKER :Notícias: {STRING} -STR_CONFIG_SETTING_SOUND_TICKER_HELPTEXT :Reproduzir efeito sonoro para notícias resumidas +STR_CONFIG_SETTING_SOUND_TICKER_HELPTEXT :Reproduzir um efeito sonoro para notícias resumidas STR_CONFIG_SETTING_SOUND_NEWS :Jornal: {STRING} -STR_CONFIG_SETTING_SOUND_NEWS_HELPTEXT :Reproduzir efeito sonoro ao mostrar um jornal +STR_CONFIG_SETTING_SOUND_NEWS_HELPTEXT :Reproduzir um efeito sonoro ao mostrar o jornal ###length 2 STR_CONFIG_SETTING_SOUND_NEW_YEAR :Fim do ano: {STRING} @@ -1820,7 +1821,7 @@ STR_CONFIG_SETTING_SOUND_NEW_YEAR_HELPTEXT :Reproduz um som STR_CONFIG_SETTING_SOUND_NEW_PERIOD_HELPTEXT :Reproduz um som no final do período e resume a performance da empresa desse período em comparação com a do período anterior STR_CONFIG_SETTING_SOUND_CONFIRM :Construção: {STRING} -STR_CONFIG_SETTING_SOUND_CONFIRM_HELPTEXT :Reproduzir efeito sonoro nas construções ou outras acções bem sucedidas +STR_CONFIG_SETTING_SOUND_CONFIRM_HELPTEXT :Reproduzir um efeito sonoro nas construções ou outras ações bem sucedidas STR_CONFIG_SETTING_SOUND_CLICK :Cliques de botões: {STRING} STR_CONFIG_SETTING_SOUND_CLICK_HELPTEXT :Reproduzir um bip quando botões são clicados @@ -2055,9 +2056,9 @@ STR_CONFIG_SETTING_SOFT_LIMIT_VALUE :{COMMA} STR_CONFIG_SETTING_SOFT_LIMIT_DISABLED :Desativado STR_CONFIG_SETTING_ZOOM_MIN :Nível máximo de ampliação: {STRING} -STR_CONFIG_SETTING_ZOOM_MIN_HELPTEXT :O nível máximo de zoom para visualizadores. Níveis máximos de zoom superiores aumenterão os requisitos de memória +STR_CONFIG_SETTING_ZOOM_MIN_HELPTEXT :O nível máximo de ampliação para visualizadores. Níveis máximos de ampliação superiores aumentarão os requisitos de memória do jogo STR_CONFIG_SETTING_ZOOM_MAX :Nível máximo de redução da câmara: {STRING} -STR_CONFIG_SETTING_ZOOM_MAX_HELPTEXT :O nível mínimo de zoom para visualizadores. Níveis mínimos de zoom superiores poderão causar lag quando utilizados +STR_CONFIG_SETTING_ZOOM_MAX_HELPTEXT :O nível mínimo de ampliação para visualizadores. Níveis mínimos de ampliação superiores poderão causar atrasos na execução do jogo quando utilizados ###length 6 STR_CONFIG_SETTING_ZOOM_LVL_MIN :4x STR_CONFIG_SETTING_ZOOM_LVL_IN_2X :2x @@ -2139,14 +2140,14 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_POWER_SI :SI (kW) STR_CONFIG_SETTING_LOCALISATION_UNITS_WEIGHT :Unidades de peso: {STRING} STR_CONFIG_SETTING_LOCALISATION_UNITS_WEIGHT_HELPTEXT :Quando um peso é mostrado na interface de utilizador, mostrar na unidade selecionada ###length 3 -STR_CONFIG_SETTING_LOCALISATION_UNITS_WEIGHT_IMPERIAL :Imperial (short ton) +STR_CONFIG_SETTING_LOCALISATION_UNITS_WEIGHT_IMPERIAL :Imperial (short t/ton) STR_CONFIG_SETTING_LOCALISATION_UNITS_WEIGHT_METRIC :Métrico (t/tonelada) STR_CONFIG_SETTING_LOCALISATION_UNITS_WEIGHT_SI :SI (kg) STR_CONFIG_SETTING_LOCALISATION_UNITS_VOLUME :Unidades de volume: {STRING} STR_CONFIG_SETTING_LOCALISATION_UNITS_VOLUME_HELPTEXT :Quando uma quantidade de volume é mostrada na interface de utilizador, mostrar na unidade selecionada ###length 3 -STR_CONFIG_SETTING_LOCALISATION_UNITS_VOLUME_IMPERIAL :Imperial (gal) +STR_CONFIG_SETTING_LOCALISATION_UNITS_VOLUME_IMPERIAL :Imperial (galões) STR_CONFIG_SETTING_LOCALISATION_UNITS_VOLUME_METRIC :Métrico (l) STR_CONFIG_SETTING_LOCALISATION_UNITS_VOLUME_SI :SI (m³) @@ -2159,10 +2160,11 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_SI :SI (kN) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT :Unidades de altura: {STRING} STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_HELPTEXT :Quando as alturas são mostradas no interface de utilizador, mostrar na unidade selecionada -###length 3 -STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_IMPERIAL :Imperial (ft/pé) +###length 4 +STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_IMPERIAL :Imperial (pés) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_METRIC :Métrico (m) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_SI :SI (m) +STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_GAMEUNITS :Unidades do jogo (níveis) STR_CONFIG_SETTING_LOCALISATION :Localização STR_CONFIG_SETTING_GRAPHICS :Gráficos @@ -2256,7 +2258,7 @@ STR_INTRO_TOOLTIP_ONLINE_CONTENT :{BLACK}Verifica STR_INTRO_TOOLTIP_QUIT :{BLACK}Sair de 'OpenTTD' STR_INTRO_BASESET :{BLACK}O conjunto de gráficos base selecionado tem {NUM} elemento{P "" s} visua{P l is} em falta. Por favor, verifique se existem atualizações para este conjunto. -STR_INTRO_TRANSLATION :{BLACK}Falta{P 0 "" m} traduzir {NUM} linha{P "" s} neste idioma. Por favor, ajude o OpenTTD em inscrever-se como tradutor. Leia readme.txt para mais detalhes. +STR_INTRO_TRANSLATION :{BLACK}Falta{P 0 "" m} traduzir {NUM} linha{P "" s} nesta língua. Por favor, ajude o OpenTTD em inscrever-se como tradutor. Leia readme.txt para mais detalhes. # Quit window STR_QUIT_CAPTION :{WHITE}Sair @@ -3023,7 +3025,7 @@ STR_LANDSCAPING_TOOLTIP_PURCHASE_LAND :{BLACK}Comprar # Object construction window STR_OBJECT_BUILD_CAPTION :{WHITE}Seleção de Objeto -STR_OBJECT_BUILD_PREVIEW_TOOLTIP :{BLACK}Pré-visualização do objecto +STR_OBJECT_BUILD_PREVIEW_TOOLTIP :{BLACK}Pré-visualização do objeto STR_OBJECT_BUILD_SIZE :{BLACK}Tamanho: {GOLD}{NUM} x {NUM} mosaicos STR_OBJECT_CLASS_LTHS :Faróis @@ -3140,9 +3142,9 @@ STR_LAND_AREA_INFORMATION_COST_TO_CLEAR :{BLACK}Custo de STR_LAND_AREA_INFORMATION_REVENUE_WHEN_CLEARED :{BLACK}Receitas apuradas: {LTBLUE}{CURRENCY_LONG} STR_LAND_AREA_INFORMATION_OWNER_N_A :N/D STR_LAND_AREA_INFORMATION_OWNER :{BLACK}Proprietário: {LTBLUE}{STRING} -STR_LAND_AREA_INFORMATION_ROAD_OWNER :{BLACK}Dono da estrada: {LTBLUE}{STRING} -STR_LAND_AREA_INFORMATION_TRAM_OWNER :{BLACK}Dono da linha de elétrico: {LTBLUE}{STRING} -STR_LAND_AREA_INFORMATION_RAIL_OWNER :{BLACK}Dono da linha férrea: {LTBLUE}{STRING} +STR_LAND_AREA_INFORMATION_ROAD_OWNER :{BLACK}Proprietário da estrada: {LTBLUE}{STRING} +STR_LAND_AREA_INFORMATION_TRAM_OWNER :{BLACK}Proprietário da linha de elétrico: {LTBLUE}{STRING} +STR_LAND_AREA_INFORMATION_RAIL_OWNER :{BLACK}Proprietário da linha de comboio: {LTBLUE}{STRING} STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY :{BLACK}Autoridade local: {LTBLUE}{STRING} STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY_NONE :Nenhuma STR_LAND_AREA_INFORMATION_LANDINFO_COORDS :{BLACK}Coordenadas: {LTBLUE}{NUM} x {NUM} x {NUM} @@ -3426,11 +3428,18 @@ STR_MAPGEN_NORTHWEST :{BLACK}Noroeste STR_MAPGEN_NORTHEAST :{BLACK}Nordeste STR_MAPGEN_SOUTHEAST :{BLACK}Sudeste STR_MAPGEN_SOUTHWEST :{BLACK}Sudoeste +STR_MAPGEN_NORTHWEST_TOOLTIP :Alternar entre água e modo livre no limite noroeste do mapa +STR_MAPGEN_NORTHEAST_TOOLTIP :Alternar entre água e modo livre no limite nordeste do mapa +STR_MAPGEN_SOUTHEAST_TOOLTIP :Alternar entre água e modo livre no limite sudeste do mapa +STR_MAPGEN_SOUTHWEST_TOOLTIP :Alternar entre água e modo livre no limite sudoeste do mapa STR_MAPGEN_BORDER_FREEFORM :{BLACK}Modo livre STR_MAPGEN_BORDER_WATER :{BLACK}Água STR_MAPGEN_BORDER_RANDOM :{BLACK}Aleatório -STR_MAPGEN_BORDER_RANDOMIZE :{BLACK}Aleatório -STR_MAPGEN_BORDER_MANUAL :{BLACK}Manual + +###length 3 +STR_MAPGEN_BORDER_RANDOMIZE :Aleatório +STR_MAPGEN_BORDER_MANUAL :Manual +STR_MAPGEN_BORDER_INFINITE_WATER :Água Infinita STR_MAPGEN_HEIGHTMAP_ROTATION :{BLACK}Rotação mapa de alt.: STR_MAPGEN_HEIGHTMAP_NAME :{BLACK}Nome mapa de alt.: @@ -3469,7 +3478,8 @@ STR_GENERATION_LANDSCAPE_GENERATION :{BLACK}A gerar STR_GENERATION_RIVER_GENERATION :{BLACK}A gerar rios STR_GENERATION_CLEARING_TILES :{BLACK}A gerar zonas rochosas e montanhosas STR_GENERATION_TOWN_GENERATION :{BLACK}A gerar localidades -STR_GENERATION_INDUSTRY_GENERATION :{BLACK}A gerar indústrias +STR_GENERATION_LAND_INDUSTRY_GENERATION :{BLACK}A gerar indústrias terrestres +STR_GENERATION_WATER_INDUSTRY_GENERATION :{BLACK}A gerar indústrias fluviais STR_GENERATION_OBJECT_GENERATION :{BLACK}A gerar objetos STR_GENERATION_TREE_GENERATION :{BLACK}A gerar árvores STR_GENERATION_SETTINGUP_GAME :{BLACK}A configurar jogo @@ -3557,10 +3567,10 @@ STR_NEWGRF_PARAMETERS_NUM_PARAM :{LTBLUE}Número # NewGRF inspect window STR_NEWGRF_INSPECT_CAPTION :{WHITE}Inspeccionar - {STRING} STR_NEWGRF_INSPECT_PARENT_BUTTON :{BLACK}Pai -STR_NEWGRF_INSPECT_PARENT_TOOLTIP :{BLACK}Inspecciona o objecto do escopo pai +STR_NEWGRF_INSPECT_PARENT_TOOLTIP :{BLACK}Inspeciona o objeto do escopo pai STR_NEWGRF_INSPECT_CAPTION_OBJECT_AT :{STRING} em {HEX} -STR_NEWGRF_INSPECT_CAPTION_OBJECT_AT_OBJECT :Objecto +STR_NEWGRF_INSPECT_CAPTION_OBJECT_AT_OBJECT :Objeto STR_NEWGRF_INSPECT_CAPTION_OBJECT_AT_RAIL_TYPE :Tipo de ferrovia STR_NEWGRF_INSPECT_CAPTION_OBJECT_AT_ROAD_TYPE :Tipo de estrada @@ -3689,7 +3699,7 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}Introduz STR_TOWN_DIRECTORY_CAPTION :{WHITE}Localidades ({COMMA} de {COMMA}) STR_TOWN_DIRECTORY_NONE :{ORANGE}- Nenhuma - STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) -STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (Cidade){BLACK} ({COMMA}) +STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{BLACK} ({COMMA}) {YELLOW}{CITY_ICON} STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}Nomes das localidades - clique no nome para centrar a visualização na cidade. Ctrl+Clique para abrir um novo visualizador na localização da localidade STR_TOWN_POPULATION :{BLACK}População Mundial: {COMMA} @@ -3763,7 +3773,7 @@ STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_BRIBE :{PUSH_COLOUR}{Y # Goal window STR_GOALS_CAPTION :{WHITE}Objetivos de {COMPANY} STR_GOALS_SPECTATOR_CAPTION :{WHITE}Objetivos globais -STR_GOALS_SPECTATOR :Objectivos Globais +STR_GOALS_SPECTATOR :Objetivos Globais STR_GOALS_GLOBAL_BUTTON :{BLACK}Global STR_GOALS_GLOBAL_BUTTON_HELPTEXT :{BLACK}Mostrar objetivos globais STR_GOALS_COMPANY_BUTTON :{BLACK}Empresa @@ -4982,7 +4992,7 @@ STR_GAME_SAVELOAD_ERROR_TOO_NEW_SAVEGAME :Jogo gravado nu STR_GAME_SAVELOAD_ERROR_FILE_NOT_READABLE :Ficheiro não é legível STR_GAME_SAVELOAD_ERROR_FILE_NOT_WRITEABLE :Não é possível escrever ficheiro STR_GAME_SAVELOAD_ERROR_DATA_INTEGRITY_CHECK_FAILED :Falha ao verificar integridade de dados -STR_GAME_SAVELOAD_ERROR_PATCHPACK :Salvar o jogo é feito com uma versão modificada +STR_GAME_SAVELOAD_ERROR_PATCHPACK :Jogo foi gravado com uma versão modificada STR_GAME_SAVELOAD_NOT_AVAILABLE : STR_WARNING_LOADGAME_REMOVED_TRAMS :{WHITE}O jogo foi guardado numa versão sem suporte para elétricos. Todos os elétricos foram removidos. @@ -5025,7 +5035,7 @@ STR_ERROR_NOT_ENOUGH_CASH_REQUIRES_CURRENCY :{WHITE}Dinheiro STR_ERROR_FLAT_LAND_REQUIRED :{WHITE}É necessário terreno plano STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION :{WHITE}Terreno inclinado na direção incorreta STR_ERROR_CAN_T_DO_THIS :{WHITE}Não é possível fazer isto... -STR_ERROR_BUILDING_MUST_BE_DEMOLISHED :{WHITE}O edifício deve ser demolido primeiro +STR_ERROR_BUILDING_MUST_BE_DEMOLISHED :{WHITE}O edifício tem que ser demolido primeiro STR_ERROR_BUILDING_IS_PROTECTED :{WHITE}... o edifício está protegido STR_ERROR_CAN_T_CLEAR_THIS_AREA :{WHITE}Não é possível limpar esta área... STR_ERROR_SITE_UNSUITABLE :{WHITE}... sítio inadequado @@ -5053,7 +5063,7 @@ STR_ERROR_EXCAVATION_WOULD_DAMAGE :{WHITE}A escava STR_ERROR_ALREADY_AT_SEA_LEVEL :{WHITE}... já está ao nível do mar STR_ERROR_TOO_HIGH :{WHITE}... demasiado alto STR_ERROR_ALREADY_LEVELLED :{WHITE}... já está nivelado -STR_ERROR_BRIDGE_TOO_HIGH_AFTER_LOWER_LAND :{WHITE}Ponte acima seria demasiado alta. +STR_ERROR_BRIDGE_TOO_HIGH_AFTER_LOWER_LAND :{WHITE}A ponte acima ficaria demasiado alta. # Company related errors STR_ERROR_CAN_T_CHANGE_COMPANY_NAME :{WHITE}Não é possível alterar o nome da empresa... @@ -5267,13 +5277,13 @@ STR_ERROR_START_AND_END_MUST_BE_IN :{WHITE}Início STR_ERROR_ENDS_OF_BRIDGE_MUST_BOTH :{WHITE}... ambos os extremos da ponte devem estar em terra STR_ERROR_BRIDGE_TOO_LONG :{WHITE}... ponte demasiado longa STR_ERROR_BRIDGE_THROUGH_MAP_BORDER :{WHITE}A ponte terminaria fora do mapa -STR_ERROR_BRIDGE_TOO_LOW_FOR_STATION :{WHITE}A ponte é demasiado baixa para a estação -STR_ERROR_BRIDGE_TOO_LOW_FOR_ROADSTOP :{WHITE}A ponte é demasiado baixa para a paragem rodoviária -STR_ERROR_BRIDGE_TOO_LOW_FOR_DOCK :{WHITE}A ponte é demasiado baixa para a doca -STR_ERROR_BRIDGE_TOO_LOW_FOR_BUOY :{WHITE}A ponte é demasiado baixa para a boia -STR_ERROR_BRIDGE_TOO_LOW_FOR_RAIL_WAYPOINT :{WHITE}A ponte é demasiado baixa para o ponto de controlo ferroviário -STR_ERROR_BRIDGE_TOO_LOW_FOR_ROAD_WAYPOINT :{WHITE}A ponte é demasiado baixa para o ponto de controlo rodoviário -STR_ERROR_BRIDGE_TOO_LOW_FOR_LOCK :{WHITE}A ponte é demasiado baixa para a eclusa +STR_ERROR_BRIDGE_TOO_LOW_FOR_STATION :{WHITE}A ponte está {HEIGHT} abaixo do necessário para a estação +STR_ERROR_BRIDGE_TOO_LOW_FOR_ROADSTOP :{WHITE}A ponte está {HEIGHT} abaixo do necessário para a paragem rodoviária +STR_ERROR_BRIDGE_TOO_LOW_FOR_DOCK :{WHITE}A ponte está {HEIGHT} abaixo do necessário para a doca +STR_ERROR_BRIDGE_TOO_LOW_FOR_BUOY :{WHITE}A ponte está {HEIGHT} abaixo do necessário para a boia +STR_ERROR_BRIDGE_TOO_LOW_FOR_RAIL_WAYPOINT :{WHITE}A ponte está {HEIGHT} abaixo do necessário para o ponto de controlo ferroviário +STR_ERROR_BRIDGE_TOO_LOW_FOR_ROAD_WAYPOINT :{WHITE}A ponte está {HEIGHT} abaixo do necessário para o ponto de controlo rodoviário +STR_ERROR_BRIDGE_TOO_LOW_FOR_LOCK :{WHITE}A ponte está {HEIGHT} abaixo do necessário para a eclusa # Tunnel related errors STR_ERROR_CAN_T_BUILD_TUNNEL_HERE :{WHITE}Não é possível construir túnel aqui... @@ -5286,12 +5296,12 @@ STR_ERROR_TUNNEL_TOO_LONG :{WHITE}... tún # Object related errors STR_ERROR_TOO_MANY_OBJECTS :{WHITE}... demasiados objetos -STR_ERROR_CAN_T_BUILD_OBJECT :{WHITE}Não é possível construir objecto... -STR_ERROR_OBJECT_IN_THE_WAY :{WHITE}Objecto no caminho +STR_ERROR_CAN_T_BUILD_OBJECT :{WHITE}Não é possível construir objeto... +STR_ERROR_OBJECT_IN_THE_WAY :{WHITE}Objeto no caminho STR_ERROR_COMPANY_HEADQUARTERS_IN :{WHITE}... sede de empresa no caminho STR_ERROR_CAN_T_PURCHASE_THIS_LAND :{WHITE}Não é possível comprar esta área de terreno... STR_ERROR_YOU_ALREADY_OWN_IT :{WHITE}... já lhe pertence! -STR_ERROR_BUILD_OBJECT_LIMIT_REACHED :{WHITE}... atingido o limite de construção de objeto +STR_ERROR_BUILD_OBJECT_LIMIT_REACHED :{WHITE}... foi atingido o limite de construção de objetos # Group related errors STR_ERROR_GROUP_CAN_T_CREATE :{WHITE}Não é possível criar grupo... @@ -5909,10 +5919,10 @@ STR_TOWN_NAME :{TOWN} STR_VEHICLE_NAME :{VEHICLE} STR_WAYPOINT_NAME :{WAYPOINT} -STR_CURRENCY_SHORT_KILO :{NBSP}k -STR_CURRENCY_SHORT_MEGA :{NBSP}M -STR_CURRENCY_SHORT_GIGA :{NBSP}G -STR_CURRENCY_SHORT_TERA :{NBSP}T +STR_CURRENCY_SHORT_KILO :{NBSP}mil +STR_CURRENCY_SHORT_MEGA :{NBSP}milh. +STR_CURRENCY_SHORT_GIGA :{NBSP}mil milh. +STR_CURRENCY_SHORT_TERA :{NBSP}bil. STR_JUST_CARGO :{CARGO_LONG} STR_JUST_LEFT_ARROW :{LEFT_ARROW} diff --git a/src/lang/romanian.txt b/src/lang/romanian.txt index eb1c78c72124e..2b6f5bcea7065 100644 --- a/src/lang/romanian.txt +++ b/src/lang/romanian.txt @@ -2127,7 +2127,7 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_SI :SI (kN) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT :Unitate înălțime: {STRING} STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_HELPTEXT :Afișează înălțimile în interfață folosind unitățile selectate -###length 3 +###length 4 STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_IMPERIAL :Imperial (ft) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_METRIC :Metric (m) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_SI :SI (m) @@ -3376,6 +3376,8 @@ STR_MAPGEN_SOUTHWEST :{BLACK}Sud-vest STR_MAPGEN_BORDER_FREEFORM :{BLACK}Pământ STR_MAPGEN_BORDER_WATER :{BLACK}Apă STR_MAPGEN_BORDER_RANDOM :{BLACK}Aleator + +###length 3 STR_MAPGEN_BORDER_RANDOMIZE :{BLACK}Aleator STR_MAPGEN_BORDER_MANUAL :{BLACK}Manual @@ -3416,7 +3418,6 @@ STR_GENERATION_LANDSCAPE_GENERATION :{BLACK}Generare STR_GENERATION_RIVER_GENERATION :{BLACK}Generarea râurilor STR_GENERATION_CLEARING_TILES :{BLACK}Generare zonă dură și pietroasă STR_GENERATION_TOWN_GENERATION :{BLACK}Generare oraș -STR_GENERATION_INDUSTRY_GENERATION :{BLACK}Generare industrie STR_GENERATION_OBJECT_GENERATION :{BLACK}Generare fixă STR_GENERATION_TREE_GENERATION :{BLACK}Generare arbori STR_GENERATION_SETTINGUP_GAME :{BLACK}Se configurează jocul @@ -3629,7 +3630,6 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}Introdu STR_TOWN_DIRECTORY_CAPTION :{WHITE}Orașe ({COMMA} din {COMMA}) STR_TOWN_DIRECTORY_NONE :{ORANGE}- Nimic - STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) -STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (oraș){BLACK} ({COMMA}) STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}Numele orașelor - clic pe un nume pentru a centra imaginea pe orașul respectiv. Ctrl+Click pentru a deshide o fereastra cu locația orașului STR_TOWN_POPULATION :{BLACK}Populația totală: {COMMA} diff --git a/src/lang/russian.txt b/src/lang/russian.txt index 277fbec78ed83..309c3a92e555a 100644 --- a/src/lang/russian.txt +++ b/src/lang/russian.txt @@ -380,6 +380,7 @@ STR_UNITS_FORCE_SI :{DECIMAL}{NBSP} STR_UNITS_HEIGHT_IMPERIAL :{DECIMAL}{NBSP}фут{P "" а ов} STR_UNITS_HEIGHT_METRIC :{DECIMAL}{NBSP}м STR_UNITS_HEIGHT_SI :{DECIMAL}{NBSP}м +STR_UNITS_HEIGHT_GAMEUNITS :{DECIMAL}{NBSP}уров{P ень ня ней} # Time units used in string control characters STR_UNITS_DAYS :{COMMA}{NBSP}д{P ень ня ней} @@ -2275,8 +2276,8 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_HELPTEXT :Показыв STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_IMPERIAL :английская (миль/ч) STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_METRIC :метрическая (км/ч) STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_SI :СИ (м/с) -STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_GAMEUNITS_DAYS :Внутренние единицы (клеток/день) -STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_GAMEUNITS_SECS :Внутренние единицы (клеток/сек.) +STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_GAMEUNITS_DAYS :Игровые единицы (клеток/день) +STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_GAMEUNITS_SECS :Игровые единицы (клеток/сек.) STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_KNOTS :узлы STR_CONFIG_SETTING_LOCALISATION_UNITS_POWER :Система единиц для мощности: {STRING} @@ -2309,10 +2310,11 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_SI :СИ (кН) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT :Система единиц для высоты: {STRING} STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_HELPTEXT :Показывать значения высоты в выбранной системе единиц -###length 3 +###length 4 STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_IMPERIAL :английская (фут) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_METRIC :метрическая (м) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_SI :СИ (м) +STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_GAMEUNITS :Игровые единицы (уровни) STR_CONFIG_SETTING_LOCALISATION :Локализация STR_CONFIG_SETTING_GRAPHICS :Графика @@ -3600,11 +3602,18 @@ STR_MAPGEN_NORTHWEST :{BLACK}Севе STR_MAPGEN_NORTHEAST :{BLACK}Северо-восток STR_MAPGEN_SOUTHEAST :{BLACK}Юго-восток STR_MAPGEN_SOUTHWEST :{BLACK}Юго-запад +STR_MAPGEN_NORTHWEST_TOOLTIP :Выбрать тип северо-западного края карты: водный или произвольной формы +STR_MAPGEN_NORTHEAST_TOOLTIP :Выбрать тип северо-восточного края карты: водный или произвольной формы +STR_MAPGEN_SOUTHEAST_TOOLTIP :Выбрать тип юго-восточного края карты: водный или произвольной формы +STR_MAPGEN_SOUTHWEST_TOOLTIP :Выбрать тип юго-западного края карты: водный или произвольной формы STR_MAPGEN_BORDER_FREEFORM :{BLACK}Свободный STR_MAPGEN_BORDER_WATER :{BLACK}Водный STR_MAPGEN_BORDER_RANDOM :{BLACK}Случайно -STR_MAPGEN_BORDER_RANDOMIZE :{BLACK}Случайно -STR_MAPGEN_BORDER_MANUAL :{BLACK}Вручную + +###length 3 +STR_MAPGEN_BORDER_RANDOMIZE :Случайно +STR_MAPGEN_BORDER_MANUAL :Вручную +STR_MAPGEN_BORDER_INFINITE_WATER :Бескрайний океан STR_MAPGEN_HEIGHTMAP_ROTATION :{BLACK}Поворот карты: STR_MAPGEN_HEIGHTMAP_NAME :{BLACK}Название карты: @@ -3643,7 +3652,8 @@ STR_GENERATION_LANDSCAPE_GENERATION :{BLACK}Созд STR_GENERATION_RIVER_GENERATION :{BLACK}Создание рек STR_GENERATION_CLEARING_TILES :{BLACK}Расстановка декораций и камней STR_GENERATION_TOWN_GENERATION :{BLACK}Создание городов -STR_GENERATION_INDUSTRY_GENERATION :{BLACK}Создание предприятий +STR_GENERATION_LAND_INDUSTRY_GENERATION :{BLACK}Создание наземных предприятий +STR_GENERATION_WATER_INDUSTRY_GENERATION :{BLACK}Создание водных предприятий STR_GENERATION_OBJECT_GENERATION :{BLACK}Создание объектов STR_GENERATION_TREE_GENERATION :{BLACK}Высадка лесов STR_GENERATION_SETTINGUP_GAME :{BLACK}Настройка @@ -3863,7 +3873,7 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}Введ STR_TOWN_DIRECTORY_CAPTION :{WHITE}Города ({COMMA} / {COMMA}) STR_TOWN_DIRECTORY_NONE :{ORANGE}- Нет - STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) -STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (Мегаполис){BLACK} ({COMMA}) +STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{BLACK} ({COMMA}) {YELLOW}{CITY_ICON} STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}Список городов. Щелчок по названию показывает город в основном окне. Ctrl+щелчок показывает в дополнительном окне. STR_TOWN_POPULATION :{BLACK}Население: {COMMA} @@ -5453,13 +5463,13 @@ STR_ERROR_START_AND_END_MUST_BE_IN :{WHITE}Нача STR_ERROR_ENDS_OF_BRIDGE_MUST_BOTH :{WHITE}... оба конца моста должны опираться на землю STR_ERROR_BRIDGE_TOO_LONG :{WHITE}... мост слишком длинный STR_ERROR_BRIDGE_THROUGH_MAP_BORDER :{WHITE}Мост выходит за пределы карты -STR_ERROR_BRIDGE_TOO_LOW_FOR_STATION :{WHITE}Высота моста недостаточна для строительства станции -STR_ERROR_BRIDGE_TOO_LOW_FOR_ROADSTOP :{WHITE}Высота моста недостаточна для строительства остановки -STR_ERROR_BRIDGE_TOO_LOW_FOR_DOCK :{WHITE}Высота моста недостаточна для строительства пристани -STR_ERROR_BRIDGE_TOO_LOW_FOR_BUOY :{WHITE}Высота моста недостаточна для установки буя -STR_ERROR_BRIDGE_TOO_LOW_FOR_RAIL_WAYPOINT :{WHITE}Высота моста недостаточна для строительства маршрутной точки -STR_ERROR_BRIDGE_TOO_LOW_FOR_ROAD_WAYPOINT :{WHITE}Высота моста недостаточна для строительства маршрутной точки -STR_ERROR_BRIDGE_TOO_LOW_FOR_LOCK :{WHITE}Высота моста недостаточна для строительства шлюза +STR_ERROR_BRIDGE_TOO_LOW_FOR_STATION :{WHITE}Высота моста {HEIGHT} недостаточна для строительства станции +STR_ERROR_BRIDGE_TOO_LOW_FOR_ROADSTOP :{WHITE}Высота моста {HEIGHT} недостаточна для строительства остановки +STR_ERROR_BRIDGE_TOO_LOW_FOR_DOCK :{WHITE}Высота моста {HEIGHT} недостаточна для строительства пристани +STR_ERROR_BRIDGE_TOO_LOW_FOR_BUOY :{WHITE}Высота моста {HEIGHT} недостаточна для установки буя +STR_ERROR_BRIDGE_TOO_LOW_FOR_RAIL_WAYPOINT :{WHITE}Высота моста {HEIGHT} недостаточна для строительства маршрутной точки +STR_ERROR_BRIDGE_TOO_LOW_FOR_ROAD_WAYPOINT :{WHITE}Высота моста {HEIGHT} недостаточна для строительства маршрутной точки +STR_ERROR_BRIDGE_TOO_LOW_FOR_LOCK :{WHITE}Высота моста {HEIGHT} недостаточна для строительства шлюза # Tunnel related errors STR_ERROR_CAN_T_BUILD_TUNNEL_HERE :{WHITE}Здесь невозможно построить туннель... diff --git a/src/lang/serbian.txt b/src/lang/serbian.txt index f14ffc78a18af..efdb5971ca568 100644 --- a/src/lang/serbian.txt +++ b/src/lang/serbian.txt @@ -2250,7 +2250,7 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_SI :SI (kN) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT :Mere visine: {STRING} STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_HELPTEXT :Kad visine budu pokazane u interfejsu, pokazi u željenoj meri -###length 3 +###length 4 STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_IMPERIAL :Imperijalne mere (ft) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_METRIC :Metričke mere (m) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_SI :SI (m) @@ -3431,6 +3431,8 @@ STR_MAPGEN_SOUTHWEST :{BLACK}Jugozapa STR_MAPGEN_BORDER_FREEFORM :{BLACK}Kopno STR_MAPGEN_BORDER_WATER :{BLACK}More STR_MAPGEN_BORDER_RANDOM :{BLACK}Proizvoljno + +###length 3 STR_MAPGEN_BORDER_RANDOMIZE :{BLACK}Proizvoljno STR_MAPGEN_BORDER_MANUAL :{BLACK}Podešeno @@ -3674,7 +3676,6 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}Unos naz # Town directory window STR_TOWN_DIRECTORY_NONE :{ORANGE}- Prazno - STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) -STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (City){BLACK} ({COMMA}) STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}Imena naselja - klikom na naziv glavni pogled se premešta na to naselje. Ctrl+klik otvara novi pogled na lokaciju naselja STR_TOWN_POPULATION :{BLACK}Svetska populacija: {COMMA} diff --git a/src/lang/simplified_chinese.txt b/src/lang/simplified_chinese.txt index 58a02c6686935..17e04752d0214 100644 --- a/src/lang/simplified_chinese.txt +++ b/src/lang/simplified_chinese.txt @@ -254,6 +254,7 @@ STR_UNITS_FORCE_SI :{DECIMAL}{NBSP} STR_UNITS_HEIGHT_IMPERIAL :{DECIMAL}{NBSP}英尺 STR_UNITS_HEIGHT_METRIC :{DECIMAL}{NBSP}米 STR_UNITS_HEIGHT_SI :{DECIMAL}{NBSP}米 +STR_UNITS_HEIGHT_GAMEUNITS :{DECIMAL}{NBSP}层 # Time units used in string control characters STR_UNITS_DAYS :{COMMA}{NBSP}日 @@ -2158,10 +2159,11 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_SI :国际单位制 STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT :高度单位:{STRING} STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_HELPTEXT :在界面上以所选择的单位表示高度 -###length 3 +###length 4 STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_IMPERIAL :英制(呎) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_METRIC :公制(米) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_SI :国际单位制(米) +STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_GAMEUNITS :游戏单位(层) STR_CONFIG_SETTING_LOCALISATION :本地化 STR_CONFIG_SETTING_GRAPHICS :图形 @@ -3348,6 +3350,8 @@ STR_SAVELOAD_DETAIL_GRFSTATUS :{SILVER}NewGRF STR_SAVELOAD_FILTER_TITLE :{BLACK}搜索: STR_SAVELOAD_OVERWRITE_TITLE :{WHITE}覆盖文件 STR_SAVELOAD_OVERWRITE_WARNING :{YELLOW}确定覆盖已有文件吗? +STR_SAVELOAD_DELETE_TITLE :{WHITE}删除文件 +STR_SAVELOAD_DELETE_WARNING :{YELLOW}确定删除文件吗? STR_SAVELOAD_DIRECTORY :{STRING}(目录) STR_SAVELOAD_PARENT_DIRECTORY :{STRING}(上级目录) @@ -3426,8 +3430,11 @@ STR_MAPGEN_SOUTHWEST :{BLACK}西南 STR_MAPGEN_BORDER_FREEFORM :{BLACK}自由形式 STR_MAPGEN_BORDER_WATER :{BLACK}水面 STR_MAPGEN_BORDER_RANDOM :{BLACK}随机 -STR_MAPGEN_BORDER_RANDOMIZE :{BLACK}随机 -STR_MAPGEN_BORDER_MANUAL :{BLACK}手动 + +###length 3 +STR_MAPGEN_BORDER_RANDOMIZE :随机 +STR_MAPGEN_BORDER_MANUAL :手动 +STR_MAPGEN_BORDER_INFINITE_WATER :无尽水域 STR_MAPGEN_HEIGHTMAP_ROTATION :{BLACK}高度图旋转: STR_MAPGEN_HEIGHTMAP_NAME :{BLACK}高度图名称: @@ -3466,7 +3473,8 @@ STR_GENERATION_LANDSCAPE_GENERATION :{BLACK}景观 STR_GENERATION_RIVER_GENERATION :{BLACK}生成河流 STR_GENERATION_CLEARING_TILES :{BLACK}生成岩石地貌 STR_GENERATION_TOWN_GENERATION :{BLACK}城镇生成 -STR_GENERATION_INDUSTRY_GENERATION :{BLACK}工业生成 +STR_GENERATION_LAND_INDUSTRY_GENERATION :{BLACK}生成陆上工业 +STR_GENERATION_WATER_INDUSTRY_GENERATION :{BLACK}生成水上工业 STR_GENERATION_OBJECT_GENERATION :{BLACK}生成固定设施 STR_GENERATION_TREE_GENERATION :{BLACK}生成树木 STR_GENERATION_SETTINGUP_GAME :{BLACK}设置游戏 @@ -3686,7 +3694,7 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}为标 STR_TOWN_DIRECTORY_CAPTION :{WHITE}城镇({COMMA} 座,共 {COMMA}座) STR_TOWN_DIRECTORY_NONE :{ORANGE}- 无 - STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK}({COMMA}) -STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW}(都市){BLACK}({COMMA}) +STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{BLACK}({COMMA}){YELLOW}{CITY_ICON} STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK} 城镇名称 - 点击名称可以将屏幕中心{}移动到城镇所在的位置。按住 点选将会在新视点中显示城镇位置 STR_TOWN_POPULATION :{BLACK}地图人口总数:{COMMA} @@ -4183,6 +4191,7 @@ STR_PURCHASE_INFO_ALL_BUT :所有货物( STR_PURCHASE_INFO_MAX_TE :{BLACK}最大牵引力:{GOLD}{FORCE} STR_PURCHASE_INFO_AIRCRAFT_RANGE :{BLACK}航行距离:{GOLD}{COMMA} 格 STR_PURCHASE_INFO_AIRCRAFT_TYPE :{BLACK}飞机类型:{GOLD}{STRING} +STR_PURCHASE_INFO_RAILTYPES :{BLACK}轨道类型:{GOLD}{STRING} ###length 3 STR_CARGO_TYPE_FILTER_ALL :所有货物类型 @@ -4366,6 +4375,7 @@ STR_ENGINE_PREVIEW_RUNCOST_YEAR :运行费用: STR_ENGINE_PREVIEW_RUNCOST_PERIOD :运行费用:{CURRENCY_LONG}/周期 STR_ENGINE_PREVIEW_CAPACITY :容量:{CARGO_LONG} STR_ENGINE_PREVIEW_CAPACITY_2 :容量:{CARGO_LONG}、{CARGO_LONG} +STR_ENGINE_PREVIEW_RAILTYPES :轨道类型:{STRING} # Autoreplace window STR_REPLACE_VEHICLES_WHITE :{WHITE}更新 {STRING} - {STRING} @@ -5262,13 +5272,13 @@ STR_ERROR_START_AND_END_MUST_BE_IN :{WHITE}起止 STR_ERROR_ENDS_OF_BRIDGE_MUST_BOTH :{WHITE}……桥梁两端必须都位于地面上 STR_ERROR_BRIDGE_TOO_LONG :{WHITE}……桥梁太长 STR_ERROR_BRIDGE_THROUGH_MAP_BORDER :{WHITE}桥梁终点将越出地图 -STR_ERROR_BRIDGE_TOO_LOW_FOR_STATION :{WHITE}桥梁过低,无法建设车站 -STR_ERROR_BRIDGE_TOO_LOW_FOR_ROADSTOP :{WHITE}桥梁过低,无法建设车站 -STR_ERROR_BRIDGE_TOO_LOW_FOR_DOCK :{WHITE}桥梁过低,无法建设码头 -STR_ERROR_BRIDGE_TOO_LOW_FOR_BUOY :{WHITE}桥梁过低,无法放置浮标 -STR_ERROR_BRIDGE_TOO_LOW_FOR_RAIL_WAYPOINT :{WHITE}桥梁过低,无法建设路点 -STR_ERROR_BRIDGE_TOO_LOW_FOR_ROAD_WAYPOINT :{WHITE}桥梁过低,无法建设路点 -STR_ERROR_BRIDGE_TOO_LOW_FOR_LOCK :{WHITE}桥梁过低,无法建设船闸 +STR_ERROR_BRIDGE_TOO_LOW_FOR_STATION :{WHITE}桥梁过低,尚需 {HEIGHT}净空以建设车站 +STR_ERROR_BRIDGE_TOO_LOW_FOR_ROADSTOP :{WHITE}桥梁过低,尚需 {HEIGHT}净空以建设车站 +STR_ERROR_BRIDGE_TOO_LOW_FOR_DOCK :{WHITE}桥梁过低,尚需 {HEIGHT}净空以建设码头 +STR_ERROR_BRIDGE_TOO_LOW_FOR_BUOY :{WHITE}桥梁过低,尚需 {HEIGHT}净空以放置浮标 +STR_ERROR_BRIDGE_TOO_LOW_FOR_RAIL_WAYPOINT :{WHITE}桥梁过低,尚需 {HEIGHT}净空以建设路点 +STR_ERROR_BRIDGE_TOO_LOW_FOR_ROAD_WAYPOINT :{WHITE}桥梁过低,尚需 {HEIGHT}净空以建设路点 +STR_ERROR_BRIDGE_TOO_LOW_FOR_LOCK :{WHITE}桥梁过低,尚需 {HEIGHT}净空以建设船闸 # Tunnel related errors STR_ERROR_CAN_T_BUILD_TUNNEL_HERE :{WHITE}不能在这里开凿隧道…… diff --git a/src/lang/slovak.txt b/src/lang/slovak.txt index daeb7280a01f0..fdd76be32ab99 100644 --- a/src/lang/slovak.txt +++ b/src/lang/slovak.txt @@ -2172,7 +2172,7 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_SI :SI (kN) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT :Jednotky výšky: {STRING} STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_HELPTEXT :Vždy, keď sa zobrazí výška v užívateľskom rozhraní, zobrazí sa vo vybraných jednotkách -###length 3 +###length 4 STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_IMPERIAL :Imperialne (ft) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_METRIC :Metrické (m) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_SI :SI (m) @@ -3378,6 +3378,8 @@ STR_MAPGEN_SOUTHWEST :{BLACK}Juho-zá STR_MAPGEN_BORDER_FREEFORM :{BLACK}Náhodne STR_MAPGEN_BORDER_WATER :{BLACK}Voda STR_MAPGEN_BORDER_RANDOM :{BLACK}Náhodne + +###length 3 STR_MAPGEN_BORDER_RANDOMIZE :{BLACK}Náhodne STR_MAPGEN_BORDER_MANUAL :{BLACK}Manuálne @@ -3418,7 +3420,6 @@ STR_GENERATION_LANDSCAPE_GENERATION :Generujem kraji STR_GENERATION_RIVER_GENERATION :{BLACK}Generovanie riek STR_GENERATION_CLEARING_TILES :{BLACK}Generovanie nerovností a skál STR_GENERATION_TOWN_GENERATION :Vytváranie mesta -STR_GENERATION_INDUSTRY_GENERATION :Vytváranie priemyslu STR_GENERATION_OBJECT_GENERATION :{BLACK}Generovanie objektov STR_GENERATION_TREE_GENERATION :{BLACK}Generovanie stromov STR_GENERATION_SETTINGUP_GAME :{BLACK}Nastavovanie hry @@ -3628,7 +3629,6 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}Zadajte # Town directory window STR_TOWN_DIRECTORY_NONE :{ORANGE}- Žiadne - STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) -STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (Veľkomesto){BLACK} ({COMMA}) STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}Názvy miest - kliknite na názov pre pohľad na mesto. Ctrl+Klik otvorí nové okno s pohľadom na mesto STR_TOWN_POPULATION :{BLACK}Svetová populácia: {COMMA} diff --git a/src/lang/slovenian.txt b/src/lang/slovenian.txt index a58b036798178..e6e9b9742f2db 100644 --- a/src/lang/slovenian.txt +++ b/src/lang/slovenian.txt @@ -1962,7 +1962,7 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_SI :SI (kN) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT :Višinske enote: {STRING} STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_HELPTEXT :Ko je omogočen prikaz višin na vmesniku, bodo prikazane v izbranih enotah. -###length 3 +###length 4 STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_IMPERIAL :Imperične (ft) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_METRIC :Metrične (m) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_SI :SI (m) @@ -2930,6 +2930,8 @@ STR_MAPGEN_SOUTHWEST :{BLACK}Jugozaho STR_MAPGEN_BORDER_FREEFORM :{BLACK}Poljubno STR_MAPGEN_BORDER_WATER :{BLACK}Voda STR_MAPGEN_BORDER_RANDOM :{BLACK}Naključno + +###length 3 STR_MAPGEN_BORDER_RANDOMIZE :{BLACK}Naključno STR_MAPGEN_BORDER_MANUAL :{BLACK}Ročno @@ -3155,7 +3157,6 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}Vpiši i # Town directory window STR_TOWN_DIRECTORY_NONE :{ORANGE}- Brez - STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) -STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (Mesto){BLACK} ({COMMA}) STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}Imena mest - klikni na ime za pogled na mesto. Ctrl+Klik odpre nov pogled na lokaciji mesta STR_TOWN_POPULATION :{BLACK}Svetovno prebivalstvo: {COMMA} diff --git a/src/lang/spanish.txt b/src/lang/spanish.txt index 5341c2ca88b1f..7627577713790 100644 --- a/src/lang/spanish.txt +++ b/src/lang/spanish.txt @@ -2137,7 +2137,7 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_SI :SI (kN) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT :Unidad de altura: {STRING} STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_HELPTEXT :Cada vez que se muestre una altura en la interfaz de usuario, se empleará la unidad seleccionada -###length 3 +###length 4 STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_IMPERIAL :Imperial (pies) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_METRIC :Métrico (m) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_SI :SI (m) @@ -3398,6 +3398,8 @@ STR_MAPGEN_SOUTHWEST :{BLACK}Suroeste STR_MAPGEN_BORDER_FREEFORM :{BLACK}Forma libre STR_MAPGEN_BORDER_WATER :{BLACK}Agua STR_MAPGEN_BORDER_RANDOM :{BLACK}Aleatorio + +###length 3 STR_MAPGEN_BORDER_RANDOMIZE :{BLACK}Aleatorio STR_MAPGEN_BORDER_MANUAL :{BLACK}Manual @@ -3438,7 +3440,6 @@ STR_GENERATION_LANDSCAPE_GENERATION :{BLACK}Generaci STR_GENERATION_RIVER_GENERATION :{BLACK}Generación de ríos STR_GENERATION_CLEARING_TILES :{BLACK}Generación de áreas ásperas o rocosas STR_GENERATION_TOWN_GENERATION :{BLACK}Generación de municipios -STR_GENERATION_INDUSTRY_GENERATION :{BLACK}Generación de industrias STR_GENERATION_OBJECT_GENERATION :{BLACK}Generación de inamovibles STR_GENERATION_TREE_GENERATION :{BLACK}Generación de árboles STR_GENERATION_SETTINGUP_GAME :{BLACK}Configurar juego @@ -3658,7 +3659,6 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}Introduc STR_TOWN_DIRECTORY_CAPTION :{WHITE}Municipios ({COMMA} of {COMMA}) STR_TOWN_DIRECTORY_NONE :{ORANGE}- Ninguna - STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) -STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (Ciudad){BLACK} ({COMMA}) STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}Nombres de los municipios - Clica sobre un nombre para centrar la vista principal en el municipio. Ctrl+clic abre una ventana de visualización en dicha posición STR_TOWN_POPULATION :{BLACK}Población mundial: {COMMA} diff --git a/src/lang/spanish_MX.txt b/src/lang/spanish_MX.txt index 351e2d84ea366..4d128a76f1164 100644 --- a/src/lang/spanish_MX.txt +++ b/src/lang/spanish_MX.txt @@ -2154,7 +2154,7 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_SI :SI (kN) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT :Unidades de altura: {STRING} STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_HELPTEXT :Cada vez que se muestre una altura en la interfaz de usuario, se emplearán las unidades elegidas -###length 3 +###length 4 STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_IMPERIAL :Imperial (pies) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_METRIC :Métrico (m) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_SI :SI (m) @@ -3422,6 +3422,8 @@ STR_MAPGEN_SOUTHWEST :{BLACK}Suroeste STR_MAPGEN_BORDER_FREEFORM :{BLACK}Forma libre STR_MAPGEN_BORDER_WATER :{BLACK}Agua STR_MAPGEN_BORDER_RANDOM :{BLACK}Aleatorio + +###length 3 STR_MAPGEN_BORDER_RANDOMIZE :{BLACK}Aleatorio STR_MAPGEN_BORDER_MANUAL :{BLACK}Manual @@ -3462,7 +3464,6 @@ STR_GENERATION_LANDSCAPE_GENERATION :{BLACK}Generaci STR_GENERATION_RIVER_GENERATION :{BLACK}Generación de ríos STR_GENERATION_CLEARING_TILES :{BLACK}Generación de áreas rugosas y rocosas STR_GENERATION_TOWN_GENERATION :{BLACK}Generación de pueblos -STR_GENERATION_INDUSTRY_GENERATION :{BLACK}Generación de industrias STR_GENERATION_OBJECT_GENERATION :{BLACK}Generación de objetos STR_GENERATION_TREE_GENERATION :{BLACK}Generación de árboles STR_GENERATION_SETTINGUP_GAME :{BLACK}Configurando partida @@ -3682,7 +3683,6 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}Indicar STR_TOWN_DIRECTORY_CAPTION :{WHITE}Pueblos ({COMMA} de {COMMA}) STR_TOWN_DIRECTORY_NONE :{ORANGE}- Ninguno - STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) -STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (ciudad){BLACK} ({COMMA}) STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}Nombres de pueblos. Clic en un nombre centra la vista principal en el pueblo. Ctrl+Clic abre una vista aparte en su ubicación STR_TOWN_POPULATION :{BLACK}Población mundial: {COMMA} diff --git a/src/lang/swedish.txt b/src/lang/swedish.txt index 298b9d86b2e75..488b609c9f271 100644 --- a/src/lang/swedish.txt +++ b/src/lang/swedish.txt @@ -254,6 +254,7 @@ STR_UNITS_FORCE_SI :{DECIMAL}{NBSP} STR_UNITS_HEIGHT_IMPERIAL :{DECIMAL}{NBSP}fot STR_UNITS_HEIGHT_METRIC :{DECIMAL}{NBSP}m STR_UNITS_HEIGHT_SI :{DECIMAL}{NBSP}m +STR_UNITS_HEIGHT_GAMEUNITS :{DECIMAL}{NBSP}nivå{P "" s} # Time units used in string control characters STR_UNITS_DAYS :{COMMA}{NBSP}dag{P "" ar} @@ -2158,10 +2159,11 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_SI :SI (kN) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT :Höjdenhet: {STRING} STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_HELPTEXT :Närhelst en höjd visas i användargränssnittet, visa den i de valda enheterna -###length 3 +###length 4 STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_IMPERIAL :Brittisk (ft) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_METRIC :Metrisk (m) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_SI :SI (m) +STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_GAMEUNITS :Spelenheter (nivåer) STR_CONFIG_SETTING_LOCALISATION :Lokalisering STR_CONFIG_SETTING_GRAPHICS :Grafik @@ -3428,8 +3430,11 @@ STR_MAPGEN_SOUTHWEST :{BLACK}Sydväst STR_MAPGEN_BORDER_FREEFORM :{BLACK}Fri form STR_MAPGEN_BORDER_WATER :{BLACK}Vatten STR_MAPGEN_BORDER_RANDOM :{BLACK}På måfå -STR_MAPGEN_BORDER_RANDOMIZE :{BLACK}På måfå -STR_MAPGEN_BORDER_MANUAL :{BLACK}Manuella + +###length 3 +STR_MAPGEN_BORDER_RANDOMIZE :Slumpmässig +STR_MAPGEN_BORDER_MANUAL :Manuellt +STR_MAPGEN_BORDER_INFINITE_WATER :Obegränsat vatten STR_MAPGEN_HEIGHTMAP_ROTATION :{BLACK}Höjdkartans rotation: STR_MAPGEN_HEIGHTMAP_NAME :{BLACK}Namn på höjdkarta: @@ -3468,7 +3473,8 @@ STR_GENERATION_LANDSCAPE_GENERATION :{BLACK}Landskap STR_GENERATION_RIVER_GENERATION :{BLACK}Generera Flod STR_GENERATION_CLEARING_TILES :{BLACK}Svår och stenig markgenerering STR_GENERATION_TOWN_GENERATION :{BLACK}Stadsgenerering -STR_GENERATION_INDUSTRY_GENERATION :{BLACK}Industrigenerering +STR_GENERATION_LAND_INDUSTRY_GENERATION :{BLACK}Generering av markindustri +STR_GENERATION_WATER_INDUSTRY_GENERATION :{BLACK}Generering av vattenindustri STR_GENERATION_OBJECT_GENERATION :{BLACK}Generera objekt STR_GENERATION_TREE_GENERATION :{BLACK}Generera Träd STR_GENERATION_SETTINGUP_GAME :{BLACK}Ställer in spel @@ -3688,7 +3694,7 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}Mata in STR_TOWN_DIRECTORY_CAPTION :{WHITE}Städer ({COMMA} av {COMMA}) STR_TOWN_DIRECTORY_NONE :{ORANGE}- Inga - STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) -STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (Stad){BLACK} ({COMMA}) +STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{BLACK} ({COMMA}) {YELLOW}{CITY_ICON} STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}Stadsnamn - klicka på ett namn för att centrera huvudvyn på staden. Ctrl+Klick för att öppna en ny fönstervy över stadens läge STR_TOWN_POPULATION :{BLACK}Global folkmängd: {COMMA} @@ -5266,13 +5272,13 @@ STR_ERROR_START_AND_END_MUST_BE_IN :{WHITE}Start- o STR_ERROR_ENDS_OF_BRIDGE_MUST_BOTH :{WHITE}... brons båda ändar måste vara på land STR_ERROR_BRIDGE_TOO_LONG :{WHITE}... för lång bro STR_ERROR_BRIDGE_THROUGH_MAP_BORDER :{WHITE}Bron slutar utanför kartans gränser -STR_ERROR_BRIDGE_TOO_LOW_FOR_STATION :{WHITE}Bro för låg för station -STR_ERROR_BRIDGE_TOO_LOW_FOR_ROADSTOP :{WHITE}Bro för låg för depå -STR_ERROR_BRIDGE_TOO_LOW_FOR_DOCK :{WHITE}Bron är för låg för en kaj -STR_ERROR_BRIDGE_TOO_LOW_FOR_BUOY :{WHITE}Bro för låg för boj -STR_ERROR_BRIDGE_TOO_LOW_FOR_RAIL_WAYPOINT :{WHITE}Bro för låg för järnvägsriktmärke -STR_ERROR_BRIDGE_TOO_LOW_FOR_ROAD_WAYPOINT :{WHITE}Bro för låg för vägriktmärke -STR_ERROR_BRIDGE_TOO_LOW_FOR_LOCK :{WHITE}Bro för låg för sluss +STR_ERROR_BRIDGE_TOO_LOW_FOR_STATION :{WHITE}Bron är {HEIGHT} för låg för station +STR_ERROR_BRIDGE_TOO_LOW_FOR_ROADSTOP :{WHITE}Bron är {HEIGHT} för låg för depå +STR_ERROR_BRIDGE_TOO_LOW_FOR_DOCK :{WHITE}Bron är {HEIGHT} för låg för en kaj +STR_ERROR_BRIDGE_TOO_LOW_FOR_BUOY :{WHITE}Bron är {HEIGHT} för låg för boj +STR_ERROR_BRIDGE_TOO_LOW_FOR_RAIL_WAYPOINT :{WHITE}Bron är {HEIGHT} för låg för järnvägsriktmärke +STR_ERROR_BRIDGE_TOO_LOW_FOR_ROAD_WAYPOINT :{WHITE}Bron är {HEIGHT} för låg för vägriktmärke +STR_ERROR_BRIDGE_TOO_LOW_FOR_LOCK :{WHITE}Bron är {HEIGHT} för låg för sluss # Tunnel related errors STR_ERROR_CAN_T_BUILD_TUNNEL_HERE :{WHITE}Kan inte bygga tunnel här... diff --git a/src/lang/tamil.txt b/src/lang/tamil.txt index fea48d823a807..516cfb1db30f1 100644 --- a/src/lang/tamil.txt +++ b/src/lang/tamil.txt @@ -1916,7 +1916,7 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_SI :SI (kN) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT :உயரங்கள் அலகுகள்: {STRING} STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_HELPTEXT :பயனர் இடைமுகத்தில் ஒரு உயரம் காட்டப்படும் போதெல்லாம், தேர்ந்தெடுக்கப்பட்ட அலகுகளில் அதைக் காட்டுங்கள் -###length 3 +###length 4 STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_IMPERIAL :இம்பீரியல் (அடி) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_METRIC :மெட்ரிக் (மீ) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_SI :அனைத்துலக முறை அலகு (மீ) @@ -3023,6 +3023,8 @@ STR_MAPGEN_SOUTHWEST :{BLACK}தெ STR_MAPGEN_BORDER_FREEFORM :{BLACK}இலவசமாக STR_MAPGEN_BORDER_WATER :{BLACK}தண்ணீர் STR_MAPGEN_BORDER_RANDOM :{BLACK}ஏதொவொன்று + +###length 3 STR_MAPGEN_BORDER_RANDOMIZE :{BLACK}ஏதோவொன்று STR_MAPGEN_BORDER_MANUAL :{BLACK}எனது @@ -3241,7 +3243,6 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}கு STR_TOWN_DIRECTORY_CAPTION :{WHITE}நகரங்கள் ({1:COMMA}இல் {0:COMMA}) STR_TOWN_DIRECTORY_NONE :{ORANGE}- ஒன்றுமில்லை - STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) -STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (மாநகரம்){BLACK} ({COMMA}) STR_TOWN_POPULATION :{BLACK}உலக மக்கள்தொகை: {COMMA} # Town view window diff --git a/src/lang/thai.txt b/src/lang/thai.txt index 8c4ffb9ab7151..c3c517a6fe84b 100644 --- a/src/lang/thai.txt +++ b/src/lang/thai.txt @@ -1829,7 +1829,7 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_SI :มาตรฐ STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT :หน่วยวัดความสูง: {STRING} STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_HELPTEXT :การแสดงหน่วยวัดความสูงเมื่อกดดูรายละเอียดของวัตถุต่างๆ -###length 3 +###length 4 STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_IMPERIAL :อิมพีเรียล (ฟุต) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_METRIC :เมตริก (เมตร) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_SI :มาตรฐานสากล (เมตร) @@ -2861,6 +2861,8 @@ STR_MAPGEN_SOUTHWEST :{BLACK}ตะ STR_MAPGEN_BORDER_FREEFORM :{BLACK}ไม่ยึดติดรูปแบบ STR_MAPGEN_BORDER_WATER :{BLACK}น้ำ STR_MAPGEN_BORDER_RANDOM :{BLACK}สุ่ม + +###length 3 STR_MAPGEN_BORDER_RANDOMIZE :{BLACK}สุ่ม STR_MAPGEN_BORDER_MANUAL :{BLACK}ปรับแต่งเอง @@ -3083,7 +3085,6 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}กร # Town directory window STR_TOWN_DIRECTORY_NONE :{ORANGE}- ไม่มี - STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) -STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (เมือง){BLACK} ({COMMA}) STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}ชื่อเมือง - คลิ๊กเมาส์ที่ชื่อเมือง STR_TOWN_POPULATION :{BLACK}ประชากรโดยรวมทั้งแผนที่: {COMMA} diff --git a/src/lang/traditional_chinese.txt b/src/lang/traditional_chinese.txt index 8acba78a68703..23c0ccb9e5bf6 100644 --- a/src/lang/traditional_chinese.txt +++ b/src/lang/traditional_chinese.txt @@ -241,11 +241,11 @@ STR_UNITS_WEIGHT_LONG_SI :{DECIMAL}{NBSP} STR_UNITS_VOLUME_SHORT_IMPERIAL :{DECIMAL}{NBSP}加侖 STR_UNITS_VOLUME_SHORT_METRIC :{DECIMAL}{NBSP}升 -STR_UNITS_VOLUME_SHORT_SI :{DECIMAL}{NBSP}米³ +STR_UNITS_VOLUME_SHORT_SI :{DECIMAL}{NBSP}立方公尺 STR_UNITS_VOLUME_LONG_IMPERIAL :{DECIMAL}{NBSP}加侖 STR_UNITS_VOLUME_LONG_METRIC :{DECIMAL}{NBSP}公升 -STR_UNITS_VOLUME_LONG_SI :{DECIMAL}{NBSP}立方米 +STR_UNITS_VOLUME_LONG_SI :{DECIMAL}{NBSP}立方公尺 STR_UNITS_FORCE_IMPERIAL :{DECIMAL}{NBSP}磅力 STR_UNITS_FORCE_METRIC :{DECIMAL}{NBSP}公斤力 @@ -254,6 +254,7 @@ STR_UNITS_FORCE_SI :{DECIMAL}{NBSP} STR_UNITS_HEIGHT_IMPERIAL :{DECIMAL}{NBSP}英呎 STR_UNITS_HEIGHT_METRIC :{DECIMAL}{NBSP}米 STR_UNITS_HEIGHT_SI :{DECIMAL}{NBSP}公尺 +STR_UNITS_HEIGHT_GAMEUNITS :{DECIMAL}{NBSP}層 # Time units used in string control characters STR_UNITS_DAYS :{COMMA}{NBSP}日 @@ -2158,10 +2159,11 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_SI :國際單位( STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT :高度單位:{STRING} STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_HELPTEXT :在界面上以所選擇的單位表示高度。 -###length 3 +###length 4 STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_IMPERIAL :英制(英呎) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_METRIC :米制(米) -STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_SI :國際單位(米) +STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_SI :國際單位(公尺) +STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_GAMEUNITS :遊戲單位(層) STR_CONFIG_SETTING_LOCALISATION :本地化 STR_CONFIG_SETTING_GRAPHICS :圖形 @@ -3428,8 +3430,11 @@ STR_MAPGEN_SOUTHWEST :{BLACK}西南 STR_MAPGEN_BORDER_FREEFORM :{BLACK}自由地形 STR_MAPGEN_BORDER_WATER :{BLACK}水域 STR_MAPGEN_BORDER_RANDOM :{BLACK}隨機 -STR_MAPGEN_BORDER_RANDOMIZE :{BLACK}隨機 -STR_MAPGEN_BORDER_MANUAL :{BLACK}手動 + +###length 3 +STR_MAPGEN_BORDER_RANDOMIZE :隨機 +STR_MAPGEN_BORDER_MANUAL :手動 +STR_MAPGEN_BORDER_INFINITE_WATER :無盡水域 STR_MAPGEN_HEIGHTMAP_ROTATION :{BLACK}高度圖旋轉: STR_MAPGEN_HEIGHTMAP_NAME :{BLACK}高度圖名稱: @@ -3468,7 +3473,8 @@ STR_GENERATION_LANDSCAPE_GENERATION :{BLACK}景觀 STR_GENERATION_RIVER_GENERATION :{BLACK}產生河流 STR_GENERATION_CLEARING_TILES :{BLACK}產生荒地與岩石地貌 STR_GENERATION_TOWN_GENERATION :{BLACK}市鎮生成 -STR_GENERATION_INDUSTRY_GENERATION :{BLACK}工業生成 +STR_GENERATION_LAND_INDUSTRY_GENERATION :{BLACK}產生陸上工業 +STR_GENERATION_WATER_INDUSTRY_GENERATION :{BLACK}產生水上工業 STR_GENERATION_OBJECT_GENERATION :{BLACK}無法移動 STR_GENERATION_TREE_GENERATION :{BLACK}產生樹木 STR_GENERATION_SETTINGUP_GAME :{BLACK}設定遊戲 @@ -3688,7 +3694,7 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}輸入 STR_TOWN_DIRECTORY_CAPTION :{WHITE}市鎮({COMMA} 座,總共 {COMMA} 座) STR_TOWN_DIRECTORY_NONE :{ORANGE}- 無 - STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) -STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (城市){BLACK} ({COMMA}) +STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{BLACK}({COMMA}){YELLOW}{CITY_ICON} STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}市鎮名稱 - 點選名稱可將市鎮置於畫面正中央。按住 點選可於市鎮位置開啟新檢視視窗 STR_TOWN_POPULATION :{BLACK}世界人口:{COMMA} @@ -5266,13 +5272,13 @@ STR_ERROR_START_AND_END_MUST_BE_IN :{WHITE}開始 STR_ERROR_ENDS_OF_BRIDGE_MUST_BOTH :{WHITE}... 橋樑的兩端應在陸地上 STR_ERROR_BRIDGE_TOO_LONG :{WHITE}……橋樑過長 STR_ERROR_BRIDGE_THROUGH_MAP_BORDER :{WHITE}橋的終點將會在地圖外 -STR_ERROR_BRIDGE_TOO_LOW_FOR_STATION :{WHITE}橋樑過低,無法興建車站 -STR_ERROR_BRIDGE_TOO_LOW_FOR_ROADSTOP :{WHITE}橋樑過低,無法興建車站 -STR_ERROR_BRIDGE_TOO_LOW_FOR_DOCK :{WHITE}橋樑過低,無法興建碼頭 -STR_ERROR_BRIDGE_TOO_LOW_FOR_BUOY :{WHITE}橋樑過低,無法放置浮標 -STR_ERROR_BRIDGE_TOO_LOW_FOR_RAIL_WAYPOINT :{WHITE}橋樑過低,無法興建中途站 -STR_ERROR_BRIDGE_TOO_LOW_FOR_ROAD_WAYPOINT :{WHITE}橋樑過低,無法興建中途站 -STR_ERROR_BRIDGE_TOO_LOW_FOR_LOCK :{WHITE}橋樑過低,無法興建水閘 +STR_ERROR_BRIDGE_TOO_LOW_FOR_STATION :{WHITE}橋高 {HEIGHT},不足以興建車站 +STR_ERROR_BRIDGE_TOO_LOW_FOR_ROADSTOP :{WHITE}橋高 {HEIGHT},不足以興建車站 +STR_ERROR_BRIDGE_TOO_LOW_FOR_DOCK :{WHITE}橋高 {HEIGHT},不足以興建碼頭 +STR_ERROR_BRIDGE_TOO_LOW_FOR_BUOY :{WHITE}橋高 {HEIGHT},不足以放置浮標 +STR_ERROR_BRIDGE_TOO_LOW_FOR_RAIL_WAYPOINT :{WHITE}橋高 {HEIGHT},不足以興建中途站 +STR_ERROR_BRIDGE_TOO_LOW_FOR_ROAD_WAYPOINT :{WHITE}橋高 {HEIGHT},不足以興建中途站 +STR_ERROR_BRIDGE_TOO_LOW_FOR_LOCK :{WHITE}橋高 {HEIGHT},不足以興建水閘 # Tunnel related errors STR_ERROR_CAN_T_BUILD_TUNNEL_HERE :{WHITE}無法在此挖掘隧道... diff --git a/src/lang/turkish.txt b/src/lang/turkish.txt index bbb8b60d96516..35d04b5311f50 100644 --- a/src/lang/turkish.txt +++ b/src/lang/turkish.txt @@ -2106,7 +2106,7 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_SI :SI (Uluslararas STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT :Yükseklik ölçü birimi: {STRING} STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_HELPTEXT :Kullanıcı arayüzünde yükseklikler görüntülendiğinde, bunları seçili ölçü biriminde göster -###length 3 +###length 4 STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_IMPERIAL :Imperial (Ingiliz ölçü birimleri) (ft) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_METRIC :Metrik (m) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_SI :SI (Uluslararası Ölçüm Sistemi) (m) @@ -3338,6 +3338,8 @@ STR_MAPGEN_SOUTHWEST :{BLACK}Güneyba STR_MAPGEN_BORDER_FREEFORM :{BLACK}Serbest STR_MAPGEN_BORDER_WATER :{BLACK}Su STR_MAPGEN_BORDER_RANDOM :{BLACK}Rastgele + +###length 3 STR_MAPGEN_BORDER_RANDOMIZE :{BLACK}Rastgele STR_MAPGEN_BORDER_MANUAL :{BLACK}El ile @@ -3378,7 +3380,6 @@ STR_GENERATION_LANDSCAPE_GENERATION :{BLACK}Peyzaj o STR_GENERATION_RIVER_GENERATION :{BLACK}Nehir oluşturma STR_GENERATION_CLEARING_TILES :{BLACK}Engebeli ve kayalık alan oluştur STR_GENERATION_TOWN_GENERATION :{BLACK}Kasaba Oluşumu -STR_GENERATION_INDUSTRY_GENERATION :{BLACK}Endüstri Oluşumu STR_GENERATION_OBJECT_GENERATION :{BLACK}Nesne oluşturma STR_GENERATION_TREE_GENERATION :{BLACK}Ağaç üretimi STR_GENERATION_SETTINGUP_GAME :{BLACK}Oyun ayarlanıyor @@ -3592,7 +3593,6 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}Tabela i # Town directory window STR_TOWN_DIRECTORY_NONE :{ORANGE}- Hiçbiri - STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) -STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (Şehir){BLACK} ({COMMA}) STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}Şehir isimleri - şehre bakmak için ismine tıkla. Ctrl + Sol Tıklama şehrin olduğu yere ait bir görünüm penceresi açar. STR_TOWN_POPULATION :{BLACK}Dünya nüfusu: {COMMA} diff --git a/src/lang/ukrainian.txt b/src/lang/ukrainian.txt index 72b8665bfd99a..c96a193178632 100644 --- a/src/lang/ukrainian.txt +++ b/src/lang/ukrainian.txt @@ -2273,7 +2273,7 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_SI :СІ (кН) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT :Одиниці висоти: {STRING} STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_HELPTEXT :Якщо висоти відображаються на інтерфейсі: показувати в обраній одиниці виміру -###length 3 +###length 4 STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_IMPERIAL :Імперські (фути) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_METRIC :Метричні (м) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_SI :СІ (м) @@ -3537,6 +3537,8 @@ STR_MAPGEN_SOUTHWEST :{BLACK}півд STR_MAPGEN_BORDER_FREEFORM :{BLACK}вільний формат STR_MAPGEN_BORDER_WATER :{BLACK}вода STR_MAPGEN_BORDER_RANDOM :{BLACK}довільно + +###length 3 STR_MAPGEN_BORDER_RANDOMIZE :{BLACK}довільно STR_MAPGEN_BORDER_MANUAL :{BLACK}вручну @@ -3577,7 +3579,6 @@ STR_GENERATION_LANDSCAPE_GENERATION :{BLACK}Гене STR_GENERATION_RIVER_GENERATION :{BLACK}Генерація річок STR_GENERATION_CLEARING_TILES :{BLACK}Розкидати каміння STR_GENERATION_TOWN_GENERATION :{BLACK}Генерація міст -STR_GENERATION_INDUSTRY_GENERATION :{BLACK}Генерація промисловості STR_GENERATION_OBJECT_GENERATION :{BLACK}Генерація нерухомості STR_GENERATION_TREE_GENERATION :{BLACK}Насадження дерев STR_GENERATION_SETTINGUP_GAME :{BLACK}Налаштування гри @@ -3797,7 +3798,6 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}Введ STR_TOWN_DIRECTORY_CAPTION :{WHITE}Міста ({COMMA} of {COMMA}) STR_TOWN_DIRECTORY_NONE :{ORANGE}- немає - STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) -STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (Мегаполіс){BLACK} ({COMMA}) STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}Назви міст - натисніть на назву, щоб показати місто у центрі екрану. Ctrl+клац мишею відкриває нове вікно з видом на місто STR_TOWN_POPULATION :{BLACK}Населення світу: {COMMA} diff --git a/src/lang/urdu.txt b/src/lang/urdu.txt index 63aade5047214..40e9f035a728d 100644 --- a/src/lang/urdu.txt +++ b/src/lang/urdu.txt @@ -1482,7 +1482,7 @@ STR_CONFIG_SETTING_CITY_SIZE_MULTIPLIER :شہر کا ش ###length 3 -###length 3 +###length 4 STR_CONFIG_SETTING_INTERFACE :انٹرفیس STR_CONFIG_SETTING_INTERFACE_CONSTRUCTION :تعمیرات @@ -2222,6 +2222,8 @@ STR_MAPGEN_BORDER_TYPE_TOOLTIP :{BLACK}کھیل STR_MAPGEN_BORDER_FREEFORM :{BLACK}فری فارم STR_MAPGEN_BORDER_WATER :{BLACK}پانی STR_MAPGEN_BORDER_RANDOM :{BLACK}بے ترتیب + +###length 3 STR_MAPGEN_BORDER_RANDOMIZE :{BLACK}بے ترتیب STR_MAPGEN_BORDER_MANUAL :{BLACK}دستی diff --git a/src/lang/vietnamese.txt b/src/lang/vietnamese.txt index ec663d1330e8b..4cbf272ae3258 100644 --- a/src/lang/vietnamese.txt +++ b/src/lang/vietnamese.txt @@ -2158,7 +2158,7 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_SI :SI (kN) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT :Đơn vị độ cao: {STRING} STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_HELPTEXT :Khi độ cao thể hiện trên giao diện, thì hiển thị nó trên đơn vị đã chọn -###length 3 +###length 4 STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_IMPERIAL :Hoàng Gia (ft) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_METRIC :Metric (m) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_SI :SI (m) @@ -3348,6 +3348,8 @@ STR_SAVELOAD_DETAIL_GRFSTATUS :{SILVER}NewGRF: STR_SAVELOAD_FILTER_TITLE :{BLACK}Lọc: STR_SAVELOAD_OVERWRITE_TITLE :{WHITE}Ghi đè file STR_SAVELOAD_OVERWRITE_WARNING :{YELLOW}Bạn có chắc chắn ghi đè lên file đang tồn tại? +STR_SAVELOAD_DELETE_TITLE :{WHITE}Xóa File +STR_SAVELOAD_DELETE_WARNING :{WHITE}Bạn có chắc chắn muốn xóa file này? STR_SAVELOAD_DIRECTORY :{STRING} (Thư mục) STR_SAVELOAD_PARENT_DIRECTORY :{STRING} (Thư mục cha) @@ -3426,6 +3428,8 @@ STR_MAPGEN_SOUTHWEST :{BLACK}Tây Nam STR_MAPGEN_BORDER_FREEFORM :{BLACK}Dạng Tự Do STR_MAPGEN_BORDER_WATER :{BLACK}Nước STR_MAPGEN_BORDER_RANDOM :{BLACK}Ngẫu Nhiên + +###length 3 STR_MAPGEN_BORDER_RANDOMIZE :{BLACK}Ngẫu Nhiên STR_MAPGEN_BORDER_MANUAL :{BLACK}Điều Chỉnh @@ -3466,7 +3470,6 @@ STR_GENERATION_LANDSCAPE_GENERATION :{BLACK}Khởi t STR_GENERATION_RIVER_GENERATION :{BLACK}Khởi tạo sông suối STR_GENERATION_CLEARING_TILES :{BLACK}Sinh đá và sự gồ ghề STR_GENERATION_TOWN_GENERATION :{BLACK}Khởi tạo thị trấn -STR_GENERATION_INDUSTRY_GENERATION :{BLACK}Khởi tạo nhà máy STR_GENERATION_OBJECT_GENERATION :{BLACK}Sinh đối tượng cứng STR_GENERATION_TREE_GENERATION :{BLACK}Trồng cây STR_GENERATION_SETTINGUP_GAME :{BLACK}Thiết lập ván chơi @@ -3686,7 +3689,6 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}Nhập t STR_TOWN_DIRECTORY_CAPTION :{WHITE}Đô Thị ({COMMA} đến {COMMA}) STR_TOWN_DIRECTORY_NONE :{ORANGE}- Không Có - STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) -STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (đô thị){BLACK} ({COMMA}) STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}Tên các đô thị - nháy vào tên để xem trung tâm đô thị. Ctrl+Click mở cửa sổ mới của đô thị STR_TOWN_POPULATION :{BLACK}Dân số thế giới: {COMMA} @@ -4183,6 +4185,7 @@ STR_PURCHASE_INFO_ALL_BUT :Tất cả tr STR_PURCHASE_INFO_MAX_TE :{BLACK}Lực kéo tối đa: {GOLD}{FORCE} STR_PURCHASE_INFO_AIRCRAFT_RANGE :{BLACK}Tầm xa: {GOLD}{COMMA} ô STR_PURCHASE_INFO_AIRCRAFT_TYPE :{BLACK}Kiểu máy bay: {GOLD}{STRING} +STR_PURCHASE_INFO_RAILTYPES :{BLACK}Kiểu đường ray: {GOLD}{STRING} ###length 3 STR_CARGO_TYPE_FILTER_ALL :Tất cả hàng hóa @@ -4366,6 +4369,7 @@ STR_ENGINE_PREVIEW_RUNCOST_YEAR :Chi phí hoạt STR_ENGINE_PREVIEW_RUNCOST_PERIOD :Chi phí hoạt động: {CURRENCY_LONG}/kỳ STR_ENGINE_PREVIEW_CAPACITY :Tải trọng: {CARGO_LONG} STR_ENGINE_PREVIEW_CAPACITY_2 :Tải trọng: {CARGO_LONG}, {CARGO_LONG} +STR_ENGINE_PREVIEW_RAILTYPES :Kiểu đường ray: {STRING} # Autoreplace window STR_REPLACE_VEHICLES_WHITE :{WHITE}Thay thế {STRING} - {STRING} @@ -5262,13 +5266,6 @@ STR_ERROR_START_AND_END_MUST_BE_IN :{WHITE}Điểu STR_ERROR_ENDS_OF_BRIDGE_MUST_BOTH :{WHITE}... hai đầu cầu phải được gá vào đất STR_ERROR_BRIDGE_TOO_LONG :{WHITE}... cầu quá dài STR_ERROR_BRIDGE_THROUGH_MAP_BORDER :{WHITE}Cầu có thể vượt quá phạm vi bản đồ -STR_ERROR_BRIDGE_TOO_LOW_FOR_STATION :{WHITE}Cầu quá thấp cho ga -STR_ERROR_BRIDGE_TOO_LOW_FOR_ROADSTOP :{WHITE}Cầu quá thấp cho điểm dừng chân -STR_ERROR_BRIDGE_TOO_LOW_FOR_DOCK :{WHITE}Cầu quá thấp để xây dựng cảng -STR_ERROR_BRIDGE_TOO_LOW_FOR_BUOY :{WHITE}Cầu quá thấp cho phao -STR_ERROR_BRIDGE_TOO_LOW_FOR_RAIL_WAYPOINT :{WHITE}Cầu quá thấp cho điểm mốc đường ray -STR_ERROR_BRIDGE_TOO_LOW_FOR_ROAD_WAYPOINT :{WHITE}Cầu quá thấp cho điểm mốc đường -STR_ERROR_BRIDGE_TOO_LOW_FOR_LOCK :Cầu thấp, tàu không qua được khóa # Tunnel related errors STR_ERROR_CAN_T_BUILD_TUNNEL_HERE :{WHITE}Không thể đào hầm ở đây... diff --git a/src/lang/welsh.txt b/src/lang/welsh.txt index 066674e3c2188..271efe20fba21 100644 --- a/src/lang/welsh.txt +++ b/src/lang/welsh.txt @@ -2146,7 +2146,7 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_FORCE_SI :SI (kN) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT :Unedau uchder: {STRING} STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_HELPTEXT :Pan y dangosir uchder yn y rhyngwyneb defnyddiwr, ei ddangos yn yr unedau a ddewiswyd -###length 3 +###length 4 STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_IMPERIAL :Imperial (ft) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_METRIC :Metrig (m) STR_CONFIG_SETTING_LOCALISATION_UNITS_HEIGHT_SI :SI (m) @@ -3414,6 +3414,8 @@ STR_MAPGEN_SOUTHWEST :{BLACK}De Orlle STR_MAPGEN_BORDER_FREEFORM :{BLACK}Ffurfrydd STR_MAPGEN_BORDER_WATER :{BLACK}Dŵr STR_MAPGEN_BORDER_RANDOM :{BLACK}Ar hap + +###length 3 STR_MAPGEN_BORDER_RANDOMIZE :{BLACK}Ar hap STR_MAPGEN_BORDER_MANUAL :{BLACK}Â Llaw @@ -3454,7 +3456,6 @@ STR_GENERATION_LANDSCAPE_GENERATION :{BLACK}Creu tir STR_GENERATION_RIVER_GENERATION :{BLACK}Cynhyrchu afonydd STR_GENERATION_CLEARING_TILES :{BLACK}Cynhyrchu ardaloedd creigiog a chnapiog STR_GENERATION_TOWN_GENERATION :{BLACK}Creu trefi -STR_GENERATION_INDUSTRY_GENERATION :{BLACK}Creu diwydiant STR_GENERATION_OBJECT_GENERATION :{BLACK}Cynhyrchu gwrthrych STR_GENERATION_TREE_GENERATION :{BLACK}Cynhyrchu coed STR_GENERATION_SETTINGUP_GAME :{BLACK}Gosod gêm yn ei le @@ -3674,7 +3675,6 @@ STR_EDIT_SIGN_SIGN_OSKTITLE :{BLACK}Rhowch e STR_TOWN_DIRECTORY_CAPTION :{WHITE}Trefi ({COMMA} o {COMMA}) STR_TOWN_DIRECTORY_NONE :{ORANGE}- Dim - STR_TOWN_DIRECTORY_TOWN :{ORANGE}{TOWN}{BLACK} ({COMMA}) -STR_TOWN_DIRECTORY_CITY :{ORANGE}{TOWN}{YELLOW} (Dinas){BLACK} ({COMMA}) STR_TOWN_DIRECTORY_LIST_TOOLTIP :{BLACK}Enwau trefi - cliciwch ar enw tref i ganoli'r brif olygfa ar y dref. Ctrl+Clic i agor ffenest golwg newydd ar leoliad y dref STR_TOWN_POPULATION :{BLACK}Poblogaeth y Byd: {COMMA} diff --git a/src/language.h b/src/language.h index 4f1a50a29d95e..3158154ed2709 100644 --- a/src/language.h +++ b/src/language.h @@ -67,10 +67,8 @@ struct LanguagePackHeader { */ uint8_t GetGenderIndex(std::string_view gender_str) const { - for (uint8_t i = 0; i < MAX_NUM_GENDERS; i++) { - if (gender_str.compare(this->genders[i]) == 0) return i; - } - return MAX_NUM_GENDERS; + auto it = std::ranges::find(this->genders, gender_str); + return static_cast(std::distance(std::begin(this->genders), it)); } /** @@ -80,10 +78,8 @@ struct LanguagePackHeader { */ uint8_t GetCaseIndex(std::string_view case_str) const { - for (uint8_t i = 0; i < MAX_NUM_CASES; i++) { - if (case_str.compare(this->cases[i]) == 0) return i; - } - return MAX_NUM_CASES; + auto it = std::ranges::find(this->cases, case_str); + return static_cast(std::distance(std::begin(this->cases), it)); } }; /** Make sure the size is right. */ diff --git a/src/league_cmd.h b/src/league_cmd.h index 89a58915a4124..83f9f3c5342f2 100644 --- a/src/league_cmd.h +++ b/src/league_cmd.h @@ -20,10 +20,10 @@ CommandCost CmdUpdateLeagueTableElementData(DoCommandFlags flags, LeagueTableEle CommandCost CmdUpdateLeagueTableElementScore(DoCommandFlags flags, LeagueTableElementID element, int64_t rating, const EncodedString &score); CommandCost CmdRemoveLeagueTableElement(DoCommandFlags flags, LeagueTableElementID element); -DEF_CMD_TRAIT(CMD_CREATE_LEAGUE_TABLE, CmdCreateLeagueTable, CommandFlags({CommandFlag::Deity, CommandFlag::StrCtrl}), CMDT_OTHER_MANAGEMENT) -DEF_CMD_TRAIT(CMD_CREATE_LEAGUE_TABLE_ELEMENT, CmdCreateLeagueTableElement, CommandFlags({CommandFlag::Deity, CommandFlag::StrCtrl}), CMDT_OTHER_MANAGEMENT) -DEF_CMD_TRAIT(CMD_UPDATE_LEAGUE_TABLE_ELEMENT_DATA, CmdUpdateLeagueTableElementData, CommandFlags({CommandFlag::Deity, CommandFlag::StrCtrl}), CMDT_OTHER_MANAGEMENT) -DEF_CMD_TRAIT(CMD_UPDATE_LEAGUE_TABLE_ELEMENT_SCORE, CmdUpdateLeagueTableElementScore, CommandFlags({CommandFlag::Deity, CommandFlag::StrCtrl}), CMDT_OTHER_MANAGEMENT) -DEF_CMD_TRAIT(CMD_REMOVE_LEAGUE_TABLE_ELEMENT, CmdRemoveLeagueTableElement, CommandFlag::Deity, CMDT_OTHER_MANAGEMENT) +DEF_CMD_TRAIT(CMD_CREATE_LEAGUE_TABLE, CmdCreateLeagueTable, CommandFlags({CommandFlag::Deity, CommandFlag::StrCtrl}), CommandType::OtherManagement) +DEF_CMD_TRAIT(CMD_CREATE_LEAGUE_TABLE_ELEMENT, CmdCreateLeagueTableElement, CommandFlags({CommandFlag::Deity, CommandFlag::StrCtrl}), CommandType::OtherManagement) +DEF_CMD_TRAIT(CMD_UPDATE_LEAGUE_TABLE_ELEMENT_DATA, CmdUpdateLeagueTableElementData, CommandFlags({CommandFlag::Deity, CommandFlag::StrCtrl}), CommandType::OtherManagement) +DEF_CMD_TRAIT(CMD_UPDATE_LEAGUE_TABLE_ELEMENT_SCORE, CmdUpdateLeagueTableElementScore, CommandFlags({CommandFlag::Deity, CommandFlag::StrCtrl}), CommandType::OtherManagement) +DEF_CMD_TRAIT(CMD_REMOVE_LEAGUE_TABLE_ELEMENT, CmdRemoveLeagueTableElement, CommandFlag::Deity, CommandType::OtherManagement) #endif /* LEAGUE_CMD_H */ diff --git a/src/league_gui.cpp b/src/league_gui.cpp index 52452e88efb29..9c1a6a40e4512 100644 --- a/src/league_gui.cpp +++ b/src/league_gui.cpp @@ -57,7 +57,7 @@ static inline StringID GetPerformanceTitleFromValue(uint value) class PerformanceLeagueWindow : public Window { private: GUIList companies{}; - uint ordinal_width = 0; ///< The width of the ordinal number + uint rank_width = 0; ///< The width of the rank uint text_width = 0; ///< The width of the actual text int line_height = 0; ///< Height of the text lines Dimension icon{}; ///< Dimension of the company icon. @@ -110,17 +110,17 @@ class PerformanceLeagueWindow : public Window { int text_y_offset = (this->line_height - GetCharacterHeight(FS_NORMAL)) / 2; bool rtl = _current_text_dir == TD_RTL; - Rect ordinal = ir.WithWidth(this->ordinal_width, rtl); - uint icon_left = ir.Indent(rtl ? this->text_width : this->ordinal_width, rtl).left; - Rect text = ir.WithWidth(this->text_width, !rtl); + Rect rank_rect = ir.WithWidth(this->rank_width, rtl); + Rect icon_rect = ir.Indent(this->rank_width + WidgetDimensions::scaled.hsep_wide, rtl).WithWidth(this->icon.width, rtl); + Rect text_rect = ir.Indent(this->rank_width + this->icon.width + WidgetDimensions::scaled.hsep_wide * 2, rtl); for (uint i = 0; i != this->companies.size(); i++) { const Company *c = this->companies[i]; - DrawString(ordinal.left, ordinal.right, ir.top + text_y_offset, GetString(STR_COMPANY_LEAGUE_COMPANY_RANK, i + 1)); + DrawString(rank_rect.left, rank_rect.right, ir.top + text_y_offset, GetString(STR_COMPANY_LEAGUE_COMPANY_RANK, i + 1)); - DrawCompanyIcon(c->index, icon_left, ir.top + icon_y_offset); + DrawCompanyIcon(c->index, icon_rect.left, ir.top + icon_y_offset); - DrawString(text.left, text.right, ir.top + text_y_offset, GetString(STR_COMPANY_LEAGUE_COMPANY_NAME, c->index, c->index, GetPerformanceTitleFromValue(c->old_economy[0].performance_history))); + DrawString(text_rect.left, text_rect.right, ir.top + text_y_offset, GetString(STR_COMPANY_LEAGUE_COMPANY_NAME, c->index, c->index, GetPerformanceTitleFromValue(c->old_economy[0].performance_history))); ir.top += this->line_height; } } @@ -129,11 +129,10 @@ class PerformanceLeagueWindow : public Window { { if (widget != WID_PLT_BACKGROUND) return; - this->ordinal_width = 0; + this->rank_width = 0; for (uint i = 0; i < MAX_COMPANIES; i++) { - this->ordinal_width = std::max(this->ordinal_width, GetStringBoundingBox(GetString(STR_COMPANY_LEAGUE_COMPANY_RANK, i + 1)).width); + this->rank_width = std::max(this->rank_width, GetStringBoundingBox(GetString(STR_COMPANY_LEAGUE_COMPANY_RANK, i + 1)).width); } - this->ordinal_width += WidgetDimensions::scaled.hsep_wide; // Keep some extra spacing uint widest_width = 0; StringID widest_title = STR_NULL; @@ -154,7 +153,7 @@ class PerformanceLeagueWindow : public Window { this->text_width = widest_width + WidgetDimensions::scaled.hsep_indent * 3; // Keep some extra spacing - size.width = WidgetDimensions::scaled.framerect.Horizontal() + this->ordinal_width + this->icon.width + this->text_width + WidgetDimensions::scaled.hsep_wide; + size.width = WidgetDimensions::scaled.framerect.Horizontal() + this->rank_width + WidgetDimensions::scaled.hsep_wide + this->icon.width + WidgetDimensions::scaled.hsep_wide + this->text_width; size.height = this->line_height * MAX_COMPANIES + WidgetDimensions::scaled.framerect.Vertical(); } @@ -181,7 +180,7 @@ class PerformanceLeagueWindow : public Window { } }; -static constexpr NWidgetPart _nested_performance_league_widgets[] = { +static constexpr std::initializer_list _nested_performance_league_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_BROWN), NWidget(WWT_CAPTION, COLOUR_BROWN), SetStringTip(STR_COMPANY_LEAGUE_TABLE_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), @@ -417,7 +416,7 @@ class ScriptLeagueWindow : public Window { } }; -static constexpr NWidgetPart _nested_script_league_widgets[] = { +static constexpr std::initializer_list _nested_script_league_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_BROWN), NWidget(WWT_CAPTION, COLOUR_BROWN, WID_SLT_CAPTION), diff --git a/src/linkgraph/linkgraph_gui.cpp b/src/linkgraph/linkgraph_gui.cpp index 5cb9320b418a3..e31dd166aaa4c 100644 --- a/src/linkgraph/linkgraph_gui.cpp +++ b/src/linkgraph/linkgraph_gui.cpp @@ -496,7 +496,7 @@ std::unique_ptr MakeCargoesLegendLinkGraphGUI() } -static constexpr NWidgetPart _nested_linkgraph_legend_widgets[] = { +static constexpr std::initializer_list _nested_linkgraph_legend_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN), NWidget(WWT_CAPTION, COLOUR_DARK_GREEN, WID_LGL_CAPTION), SetStringTip(STR_LINKGRAPH_LEGEND_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), diff --git a/src/linkgraph/linkgraphjob.cpp b/src/linkgraph/linkgraphjob.cpp index 5287fb633bb68..f83e3341a961d 100644 --- a/src/linkgraph/linkgraphjob.cpp +++ b/src/linkgraph/linkgraphjob.cpp @@ -132,11 +132,11 @@ LinkGraphJob::~LinkGraphJob() !(*lg)[node_id].HasEdgeTo(dest_id) || (*lg)[node_id][dest_id].LastUpdate() == EconomyTime::INVALID_DATE) { /* Edge has been removed. Delete flows. */ - StationIDStack erased = flows.DeleteFlows(to); + std::vector erased = flows.DeleteFlows(to); /* Delete old flows for source stations which have been deleted * from the new flows. This avoids flow cycles between old and * new flows. */ - while (!erased.IsEmpty()) geflows.erase(erased.Pop()); + for (const StationID &station : erased) geflows.erase(station); } else if ((*lg)[node_id][dest_id].last_unrestricted_update == EconomyTime::INVALID_DATE) { /* Edge is fully restricted. */ flows.RestrictFlows(to); diff --git a/src/livery.h b/src/livery.h index 2de27555d9782..31c39f78403ff 100644 --- a/src/livery.h +++ b/src/livery.h @@ -10,6 +10,7 @@ #ifndef LIVERY_H #define LIVERY_H +#include "core/enum_type.hpp" #include "company_type.h" #include "gfx_type.h" @@ -76,7 +77,13 @@ DECLARE_ENUM_AS_ADDABLE(LiveryClass) /** Information about a particular livery. */ struct Livery { - uint8_t in_use = 0; ///< Bit 0 set if this livery should override the default livery first colour, Bit 1 for the second colour. + enum class Flag : uint8_t { + Primary = 0, ///< Primary colour is set. + Secondary = 1, ///< Secondary colour is set. + }; + using Flags = EnumBitSet; + + Flags in_use{}; ///< Livery flags. Colours colour1 = COLOUR_BEGIN; ///< First colour, for all vehicles. Colours colour2 = COLOUR_BEGIN; ///< Second colour, for vehicles with 2CC support. }; diff --git a/src/main_gui.cpp b/src/main_gui.cpp index 2b7a9b9d8f2d3..9cf5411ec071f 100644 --- a/src/main_gui.cpp +++ b/src/main_gui.cpp @@ -177,7 +177,7 @@ void FixTitleGameZoom(int zoom_adjust) vp.virtual_height = ScaleByZoom(vp.height, vp.zoom); } -static constexpr NWidgetPart _nested_main_window_widgets[] = { +static constexpr std::initializer_list _nested_main_window_widgets = { NWidget(NWID_VIEWPORT, INVALID_COLOUR, WID_M_VIEWPORT), SetResize(1, 1), }; diff --git a/src/map.cpp b/src/map.cpp index efb5168cbfe77..a6dc2af46be48 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -23,6 +23,8 @@ /* static */ uint Map::size; ///< The number of tiles on the map /* static */ uint Map::tile_mask; ///< _map_size - 1 (to mask the mapsize) +/* static */ uint Map::initial_land_count; ///< Initial number of land tiles on the map. + /* static */ std::unique_ptr Tile::base_tiles; ///< Base tiles of the map /* static */ std::unique_ptr Tile::extended_tiles; ///< Extended tiles of the map @@ -58,6 +60,20 @@ AllocateWaterRegions(); } +/* static */ void Map::CountLandTiles() +{ + /* Count number of tiles that are land. */ + Map::initial_land_count = 0; + for (const auto tile : Map::Iterate()) { + Map::initial_land_count += IsWaterTile(tile) ? 0 : 1; + } + + /* Compensate for default values being set for (or users are most familiar with) at least + * very low sea level. Dividing by 12 adds roughly 8%. */ + Map::initial_land_count += Map::initial_land_count / 12; + Map::initial_land_count = std::min(Map::initial_land_count, Map::size); +} + #ifdef _DEBUG TileIndex TileAdd(TileIndex tile, TileIndexDiff offset) diff --git a/src/map_func.h b/src/map_func.h index e1929c2f91c8e..1854de91b30fa 100644 --- a/src/map_func.h +++ b/src/map_func.h @@ -239,8 +239,11 @@ struct Map { static uint size; ///< The number of tiles on the map static uint tile_mask; ///< _map_size - 1 (to mask the mapsize) + static uint initial_land_count; ///< Initial number of land tiles on the map. + public: static void Allocate(uint size_x, uint size_y); + static void CountLandTiles(); /** * Logarithm of the map size along the X side. @@ -307,6 +310,16 @@ struct Map { return Map::SizeY() - 1; } + /** + * Scales the given value by the number of water tiles. + * @param n the value to scale + * @return the scaled size + */ + static inline uint ScaleByLandProportion(uint n) + { + /* Use 64-bit arithmetic to avoid overflow. */ + return static_cast(static_cast(n) * Map::initial_land_count / Map::size); + } /** * 'Wraps' the given "tile" so it is within the map. diff --git a/src/misc.cpp b/src/misc.cpp index 101f089704541..f95ccbca1a641 100644 --- a/src/misc.cpp +++ b/src/misc.cpp @@ -167,4 +167,8 @@ void InitializeGame(uint size_x, uint size_y, bool reset_date, bool reset_settin _gamelog.Mode(); _gamelog.GRFAddList(_grfconfig); _gamelog.StopAction(); + + _railtype_mapping.Init(); + _roadtype_mapping.Init(); + _tramtype_mapping.Init(); } diff --git a/src/misc/dbg_helpers.cpp b/src/misc/dbg_helpers.cpp index 7e2d4314c400e..65076410f66e6 100644 --- a/src/misc/dbg_helpers.cpp +++ b/src/misc/dbg_helpers.cpp @@ -23,13 +23,13 @@ static const std::string_view trackdir_names[] = { /** Return name of given Trackdir. */ std::string ValueStr(Trackdir td) { - return fmt::format("{} ({})", to_underlying(td), ItemAtT(td, trackdir_names, "UNK", INVALID_TRACKDIR, "INV")); + return fmt::format("{} ({})", to_underlying(td), ItemAt(td, trackdir_names, "UNK", INVALID_TRACKDIR, "INV")); } /** Return composed name of given TrackdirBits. */ std::string ValueStr(TrackdirBits td_bits) { - return fmt::format("{} ({})", to_underlying(td_bits), ComposeNameT(td_bits, trackdir_names, "UNK", INVALID_TRACKDIR_BIT, "INV")); + return fmt::format("{} ({})", to_underlying(td_bits), ComposeName(td_bits, trackdir_names, "UNK", INVALID_TRACKDIR_BIT, "INV")); } @@ -41,7 +41,7 @@ static const std::string_view diagdir_names[] = { /** Return name of given DiagDirection. */ std::string ValueStr(DiagDirection dd) { - return fmt::format("{} ({})", to_underlying(dd), ItemAtT(dd, diagdir_names, "UNK", INVALID_DIAGDIR, "INV")); + return fmt::format("{} ({})", to_underlying(dd), ItemAt(dd, diagdir_names, "UNK", INVALID_DIAGDIR, "INV")); } @@ -53,7 +53,7 @@ static const std::string_view signal_type_names[] = { /** Return name of given SignalType. */ std::string ValueStr(SignalType t) { - return fmt::format("{} ({})", to_underlying(t), ItemAtT(t, signal_type_names, "UNK")); + return fmt::format("{} ({})", to_underlying(t), ItemAt(t, signal_type_names, "UNK")); } @@ -91,7 +91,7 @@ bool DumpTarget::FindKnownName(size_t type_id, const void *ptr, std::string &nam KNOWN_NAMES::const_iterator it = m_known_names.find(KnownStructKey(type_id, ptr)); if (it != m_known_names.end()) { /* we have found it */ - name = (*it).second; + name = it->second; return true; } return false; diff --git a/src/misc/dbg_helpers.h b/src/misc/dbg_helpers.h index 69e598fb74b3f..6cf520e861e26 100644 --- a/src/misc/dbg_helpers.h +++ b/src/misc/dbg_helpers.h @@ -18,24 +18,14 @@ #include "../track_type.h" #include "../core/format.hpp" -/** Helper template class that provides C array length and item type */ -template struct ArrayT; - -/** Helper template class that provides C array length and item type */ -template struct ArrayT { - static const size_t length = N; - using Item = T; -}; - - /** * Helper template function that returns item of array at given index * or t_unk when index is out of bounds. */ -template -inline typename ArrayT::Item ItemAtT(E idx, const T &t, typename ArrayT::Item t_unk) +template +inline std::string_view ItemAt(E idx, std::span t, std::string_view t_unk) { - if (static_cast(idx) >= ArrayT::length) { + if (static_cast(idx) >= std::size(t)) { return t_unk; } return t[idx]; @@ -46,16 +36,13 @@ inline typename ArrayT::Item ItemAtT(E idx, const T &t, typename ArrayT::I * or t_inv when index == idx_inv * or t_unk when index is out of bounds. */ -template -inline typename ArrayT::Item ItemAtT(E idx, const T &t, typename ArrayT::Item t_unk, E idx_inv, typename ArrayT::Item t_inv) +template +inline std::string_view ItemAt(E idx, std::span t, std::string_view t_unk, E idx_inv, std::string_view t_inv) { - if (static_cast(idx) < ArrayT::length) { - return t[idx]; - } if (idx == idx_inv) { return t_inv; } - return t_unk; + return ItemAt(idx, t, t_unk); } /** @@ -64,8 +51,8 @@ inline typename ArrayT::Item ItemAtT(E idx, const T &t, typename ArrayT::I * or t_inv when index == idx_inv * or t_unk when index is out of bounds. */ -template -inline std::string ComposeNameT(E value, T &t, std::string_view t_unk, E val_inv, std::string_view name_inv) +template +inline std::string ComposeName(E value, std::span t, std::string_view t_unk, E val_inv, std::string_view name_inv) { std::string out; if (value == val_inv) { @@ -73,7 +60,7 @@ inline std::string ComposeNameT(E value, T &t, std::string_view t_unk, E val_inv } else if (value == 0) { out = ""; } else { - for (size_t i = 0; i < ArrayT::length; i++) { + for (size_t i = 0; i < std::size(t); i++) { if ((value & (1 << i)) == 0) continue; out += (!out.empty() ? "+" : ""); out += t[i]; @@ -93,7 +80,7 @@ inline std::string ComposeNameT(E value, T &t, std::string_view t_unk, E val_inv * or unknown_name when index is out of bounds. */ template -inline std::string ComposeNameT(E value, std::span names, std::string_view unknown_name) +inline std::string ComposeName(E value, std::span names, std::string_view unknown_name) { std::string out; if (value.base() == 0) { diff --git a/src/misc_cmd.h b/src/misc_cmd.h index 3b60ec562573f..fb5279a7f3950 100644 --- a/src/misc_cmd.h +++ b/src/misc_cmd.h @@ -27,11 +27,11 @@ CommandCost CmdDecreaseLoan(DoCommandFlags flags, LoanCommand cmd, Money amount) CommandCost CmdSetCompanyMaxLoan(DoCommandFlags flags, CompanyID company, Money amount); CommandCost CmdPause(DoCommandFlags flags, PauseMode mode, bool pause); -DEF_CMD_TRAIT(CMD_MONEY_CHEAT, CmdMoneyCheat, CommandFlags({CommandFlag::Offline, CommandFlag::NoEst}), CMDT_CHEAT) -DEF_CMD_TRAIT(CMD_CHANGE_BANK_BALANCE, CmdChangeBankBalance, CommandFlag::Deity, CMDT_MONEY_MANAGEMENT) -DEF_CMD_TRAIT(CMD_INCREASE_LOAN, CmdIncreaseLoan, {}, CMDT_MONEY_MANAGEMENT) -DEF_CMD_TRAIT(CMD_DECREASE_LOAN, CmdDecreaseLoan, {}, CMDT_MONEY_MANAGEMENT) -DEF_CMD_TRAIT(CMD_SET_COMPANY_MAX_LOAN, CmdSetCompanyMaxLoan, CommandFlag::Deity, CMDT_MONEY_MANAGEMENT) -DEF_CMD_TRAIT(CMD_PAUSE, CmdPause, CommandFlags({CommandFlag::Server, CommandFlag::NoEst}), CMDT_SERVER_SETTING) +DEF_CMD_TRAIT(CMD_MONEY_CHEAT, CmdMoneyCheat, CommandFlags({CommandFlag::Offline, CommandFlag::NoEst}), CommandType::Cheat) +DEF_CMD_TRAIT(CMD_CHANGE_BANK_BALANCE, CmdChangeBankBalance, CommandFlag::Deity, CommandType::MoneyManagement) +DEF_CMD_TRAIT(CMD_INCREASE_LOAN, CmdIncreaseLoan, {}, CommandType::MoneyManagement) +DEF_CMD_TRAIT(CMD_DECREASE_LOAN, CmdDecreaseLoan, {}, CommandType::MoneyManagement) +DEF_CMD_TRAIT(CMD_SET_COMPANY_MAX_LOAN, CmdSetCompanyMaxLoan, CommandFlag::Deity, CommandType::MoneyManagement) +DEF_CMD_TRAIT(CMD_PAUSE, CmdPause, CommandFlags({CommandFlag::Server, CommandFlag::NoEst}), CommandType::ServerSetting) #endif /* MISC_CMD_H */ diff --git a/src/misc_gui.cpp b/src/misc_gui.cpp index 719f5a5dfabbc..5b9d683a554af 100644 --- a/src/misc_gui.cpp +++ b/src/misc_gui.cpp @@ -47,7 +47,7 @@ enum OskActivation : uint8_t { }; -static constexpr NWidgetPart _nested_land_info_widgets[] = { +static constexpr std::initializer_list _nested_land_info_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), NWidget(WWT_CAPTION, COLOUR_GREY), SetStringTip(STR_LAND_AREA_INFORMATION_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), @@ -319,7 +319,7 @@ void ShowLandInfo(TileIndex tile) new LandInfoWindow(tile); } -static constexpr NWidgetPart _nested_about_widgets[] = { +static constexpr std::initializer_list _nested_about_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), NWidget(WWT_CAPTION, COLOUR_GREY), SetStringTip(STR_ABOUT_OPENTTD, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), @@ -586,7 +586,7 @@ void HideFillingPercent(TextEffectID *te_id) *te_id = INVALID_TE_ID; } -static constexpr NWidgetPart _nested_tooltips_widgets[] = { +static constexpr std::initializer_list _nested_tooltips_widgets = { NWidget(WWT_EMPTY, INVALID_COLOUR, WID_TT_BACKGROUND), }; @@ -833,7 +833,7 @@ Rect QueryString::GetBoundingRect(const Window *w, WidgetID wid, size_t from, si const auto p1 = GetCharPosInString(tb->GetText(), from, FS_NORMAL); const auto p2 = from != to ? GetCharPosInString(tb->GetText(), to, FS_NORMAL) : p1; - return { Clamp(r.left + p1.left, r.left, r.right), r.top, Clamp(r.left + p2.right, r.left, r.right), r.bottom }; + return r.WithX(Clamp(r.left + p1.left, r.left, r.right), Clamp(r.left + p2.right, r.left, r.right)); } /** @@ -975,7 +975,7 @@ struct QueryStringWindow : public Window } }; -static constexpr NWidgetPart _nested_query_string_widgets[] = { +static constexpr std::initializer_list _nested_query_string_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), NWidget(WWT_CAPTION, COLOUR_GREY, WID_QS_CAPTION), SetTextStyle(TC_WHITE), @@ -1113,7 +1113,7 @@ struct QueryWindow : public Window { } }; -static constexpr NWidgetPart _nested_query_widgets[] = { +static constexpr std::initializer_list _nested_query_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_RED), NWidget(WWT_CAPTION, COLOUR_RED, WID_Q_CAPTION), diff --git a/src/music_gui.cpp b/src/music_gui.cpp index cbd30c6c40d7f..7bdbf2dead7db 100644 --- a/src/music_gui.cpp +++ b/src/music_gui.cpp @@ -621,7 +621,7 @@ struct MusicTrackSelectionWindow : public Window { } }; -static constexpr NWidgetPart _nested_music_track_selection_widgets[] = { +static constexpr std::initializer_list _nested_music_track_selection_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), NWidget(WWT_CAPTION, COLOUR_GREY, WID_MTS_CAPTION), @@ -857,7 +857,7 @@ struct MusicWindow : public Window { } }; -static constexpr NWidgetPart _nested_music_window_widgets[] = { +static constexpr std::initializer_list _nested_music_window_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), NWidget(WWT_CAPTION, COLOUR_GREY), SetStringTip(STR_MUSIC_JAZZ_JUKEBOX_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), diff --git a/src/network/network.cpp b/src/network/network.cpp index 6a02b82f5acc4..29cbcf7acff4c 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -875,14 +875,14 @@ static void CheckClientAndServerName() { static const std::string fallback_client_name = "Unnamed Client"; StrTrimInPlace(_settings_client.network.client_name); - if (_settings_client.network.client_name.empty() || _settings_client.network.client_name.compare(fallback_client_name) == 0) { + if (_settings_client.network.client_name.empty() || _settings_client.network.client_name == fallback_client_name) { Debug(net, 1, "No \"client_name\" has been set, using \"{}\" instead. Please set this now using the \"name \" command", fallback_client_name); _settings_client.network.client_name = fallback_client_name; } static const std::string fallback_server_name = "Unnamed Server"; StrTrimInPlace(_settings_client.network.server_name); - if (_settings_client.network.server_name.empty() || _settings_client.network.server_name.compare(fallback_server_name) == 0) { + if (_settings_client.network.server_name.empty() || _settings_client.network.server_name == fallback_server_name) { Debug(net, 1, "No \"server_name\" has been set, using \"{}\" instead. Please set this now using the \"server_name \" command", fallback_server_name); _settings_client.network.server_name = fallback_server_name; } diff --git a/src/network/network_admin.cpp b/src/network/network_admin.cpp index 5ede07f12b324..95694636d2583 100644 --- a/src/network/network_admin.cpp +++ b/src/network/network_admin.cpp @@ -633,8 +633,7 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_JOIN(Packet &p) std::string password = p.Recv_string(NETWORK_PASSWORD_LENGTH); - if (_settings_client.network.admin_password.empty() || - _settings_client.network.admin_password.compare(password) != 0) { + if (_settings_client.network.admin_password.empty() || _settings_client.network.admin_password != password) { /* Password is invalid */ return this->SendError(NETWORK_ERROR_WRONG_PASSWORD); } diff --git a/src/network/network_chat_gui.cpp b/src/network/network_chat_gui.cpp index 30bf187c10647..865036b424f58 100644 --- a/src/network/network_chat_gui.cpp +++ b/src/network/network_chat_gui.cpp @@ -411,7 +411,7 @@ struct NetworkChatWindow : public Window { }; /** The widgets of the chat window. */ -static constexpr NWidgetPart _nested_chat_window_widgets[] = { +static constexpr std::initializer_list _nested_chat_window_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY, WID_NC_CLOSE), NWidget(WWT_PANEL, COLOUR_GREY, WID_NC_BACKGROUND), diff --git a/src/network/network_client.cpp b/src/network/network_client.cpp index 6dccf9e5fe9d2..4313a9de0ae05 100644 --- a/src/network/network_client.cpp +++ b/src/network/network_client.cpp @@ -537,7 +537,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_CLIENT_INFO(Pac ci = NetworkClientInfo::GetByClientID(client_id); if (ci != nullptr) { - if (playas == ci->client_playas && name.compare(ci->client_name) != 0) { + if (playas == ci->client_playas && name != ci->client_name) { /* Client name changed, display the change */ NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, false, ci->client_name, name); } else if (playas != ci->client_playas) { @@ -1296,17 +1296,17 @@ void NetworkUpdateClientName(const std::string &client_name) if (ci == nullptr) return; /* Don't change the name if it is the same as the old name */ - if (client_name.compare(ci->client_name) != 0) { - if (!_network_server) { - MyClient::SendSetName(client_name); - } else { - /* Copy to a temporary buffer so no #n gets added after our name in the settings when there are duplicate names. */ - std::string temporary_name = client_name; - if (NetworkMakeClientNameUnique(temporary_name)) { - NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, false, ci->client_name, temporary_name); - ci->client_name = std::move(temporary_name); - NetworkUpdateClientInfo(CLIENT_ID_SERVER); - } + if (client_name == ci->client_name) return; + + if (!_network_server) { + MyClient::SendSetName(client_name); + } else { + /* Copy to a temporary buffer so no #n gets added after our name in the settings when there are duplicate names. */ + std::string temporary_name = client_name; + if (NetworkMakeClientNameUnique(temporary_name)) { + NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, false, ci->client_name, temporary_name); + ci->client_name = std::move(temporary_name); + NetworkUpdateClientInfo(CLIENT_ID_SERVER); } } } diff --git a/src/network/network_content_gui.cpp b/src/network/network_content_gui.cpp index 13600aedbaa56..76acaa217fac2 100644 --- a/src/network/network_content_gui.cpp +++ b/src/network/network_content_gui.cpp @@ -84,7 +84,7 @@ static void ShowContentTextfileWindow(Window *parent, TextfileType file_type, co } /** Nested widgets for the download window. */ -static constexpr NWidgetPart _nested_network_content_download_status_window_widgets[] = { +static constexpr std::initializer_list _nested_network_content_download_status_window_widgets = { NWidget(WWT_CAPTION, COLOUR_GREY), SetStringTip(STR_CONTENT_DOWNLOAD_TITLE, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), NWidget(WWT_PANEL, COLOUR_GREY), NWidget(NWID_VERTICAL), SetPIP(0, WidgetDimensions::unscaled.vsep_wide, 0), SetPadding(WidgetDimensions::unscaled.modalpopup), @@ -673,7 +673,7 @@ class NetworkContentListWindow : public Window, ContentCallback { case ContentInfo::State::DoesNotExist: sprite = SPR_BLOT; pal = PALETTE_TO_RED; break; default: NOT_REACHED(); } - DrawSpriteIgnorePadding(sprite, pal, {checkbox.left, mr.top, checkbox.right, mr.bottom}, SA_CENTER); + DrawSpriteIgnorePadding(sprite, pal, checkbox.WithY(mr), SA_CENTER); StringID str = STR_CONTENT_TYPE_BASE_GRAPHICS + ci->type - CONTENT_TYPE_BASE_GRAPHICS; DrawString(type.left, type.right, mr.top + text_y_offset, str, TC_BLACK, SA_HOR_CENTER); @@ -1025,7 +1025,7 @@ void BuildContentTypeStringList() } /** The widgets for the content list. */ -static constexpr NWidgetPart _nested_network_content_list_widgets[] = { +static constexpr std::initializer_list _nested_network_content_list_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_LIGHT_BLUE), NWidget(WWT_CAPTION, COLOUR_LIGHT_BLUE), SetStringTip(STR_CONTENT_TITLE), diff --git a/src/network/network_gui.cpp b/src/network/network_gui.cpp index 0aefc12bd9636..9aa146e95f6d5 100644 --- a/src/network/network_gui.cpp +++ b/src/network/network_gui.cpp @@ -476,12 +476,12 @@ class NetworkGameWindow : public Window { { switch (widget) { case WID_NG_MATRIX: - fill.height = resize.height = std::max(GetSpriteSize(SPR_BLOT).height, (uint)GetCharacterHeight(FS_NORMAL)) + padding.height; + fill.height = resize.height = std::max(this->blot.height, GetCharacterHeight(FS_NORMAL)) + padding.height; size.height = 12 * resize.height; break; case WID_NG_LASTJOINED: - size.height = std::max(GetSpriteSize(SPR_BLOT).height, (uint)GetCharacterHeight(FS_NORMAL)) + WidgetDimensions::scaled.matrix.Vertical(); + size.height = std::max(this->blot.height, GetCharacterHeight(FS_NORMAL)) + WidgetDimensions::scaled.matrix.Vertical(); break; case WID_NG_LASTJOINED_SPACER: @@ -854,7 +854,7 @@ static std::unique_ptr MakeResizableHeader() return std::make_unique(); } -static constexpr NWidgetPart _nested_network_game_widgets[] = { +static constexpr std::initializer_list _nested_network_game_widgets = { /* TOP */ NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_LIGHT_BLUE), @@ -1129,7 +1129,7 @@ struct NetworkStartServerWindow : public Window { } }; -static constexpr NWidgetPart _nested_network_start_server_window_widgets[] = { +static constexpr std::initializer_list _nested_network_start_server_window_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_LIGHT_BLUE), NWidget(WWT_CAPTION, COLOUR_LIGHT_BLUE), SetStringTip(STR_NETWORK_START_SERVER_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), @@ -1217,7 +1217,7 @@ static void ShowNetworkStartServerWindow() extern void DrawCompanyIcon(CompanyID cid, int x, int y); -static constexpr NWidgetPart _nested_client_list_widgets[] = { +static constexpr std::initializer_list _nested_client_list_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), NWidget(WWT_CAPTION, COLOUR_GREY), SetStringTip(STR_NETWORK_CLIENT_LIST_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), @@ -1339,7 +1339,7 @@ class ButtonCommon { colour(colour), disabled(disabled) { - Dimension d = GetSpriteSize(sprite); + Dimension d = GetScaledSpriteSize(sprite); this->height = d.height + WidgetDimensions::scaled.framerect.Vertical(); this->width = d.width + WidgetDimensions::scaled.framerect.Horizontal(); } @@ -1381,6 +1381,159 @@ class Button : public ButtonCommon { using CompanyButton = Button; using ClientButton = Button; +/** + * Base interface for a network client list line. + */ +class ButtonLine { +public: + std::vector> buttons{}; ///< Buttons for this line. + + virtual ~ButtonLine() = default; + + /** + * Draw the button line. + * @param r Rect to draw within. + */ + virtual void Draw(Rect r) const = 0; + + template + T &AddButton(TArgs &&... args) + { + auto &button = this->buttons.emplace_back(std::make_unique(std::forward(args)...)); + return static_cast(*button); + } + + /** + * Get the button at a given point on the line. + * @param r Rect of line. + * @param pt Point of interest. + * @return Button at point, or \c nullptr if button isn't pressed. + */ + ButtonCommon *GetButton(Rect r, const Point &pt) const + { + bool rtl = _current_text_dir == TD_RTL; + for (auto &button : this->buttons) { + if (r.WithWidth(button->width, !rtl).Contains(pt)) return button.get(); + r = r.Indent(button->width + WidgetDimensions::scaled.hsep_normal, !rtl); + } + return nullptr; + } + + /** + * Get tooptip for a given point on the line. + * @param r Rect of line. + * @param pt Point of interest. + * @return EncodedString of tooltip, or \c std::nullopt if none. + */ + virtual std::optional GetTooltip(Rect r, const Point &pt) const + { + ButtonCommon *button = this->GetButton(r, pt); + if (button == nullptr) return {}; + return GetEncodedString(button->tooltip); + } + +protected: + /** + * Draw the buttons for this line. + * @param r Rect to draw within. + * @return Rect of remaining space. + */ + Rect DrawButtons(Rect r) const + { + bool rtl = _current_text_dir == TD_RTL; + for (auto &button : buttons) { + Rect br = r.CentreToHeight(button->height).WithWidth(button->width, !rtl); + DrawFrameRect(br, button->colour, {}); + DrawSpriteIgnorePadding(button->sprite, PAL_NONE, br, SA_CENTER); + if (button->disabled) { + GfxFillRect(br.Shrink(WidgetDimensions::scaled.bevel), GetColourGradient(button->colour, SHADE_DARKER), FILLRECT_CHECKER); + } + r = r.Indent(button->width + WidgetDimensions::scaled.hsep_normal, !rtl); + } + return r; + } +}; + +class CompanyButtonLine : public ButtonLine { +public: + CompanyButtonLine(CompanyID company_id) : company_id(company_id) {} + + void Draw(Rect r) const override + { + bool rtl = _current_text_dir == TD_RTL; + r = this->DrawButtons(r); + + Dimension d = GetScaledSpriteSize(SPR_COMPANY_ICON); + PaletteID pal = Company::IsValidID(this->company_id) ? GetCompanyPalette(this->company_id) : PALETTE_TO_GREY; + DrawSpriteIgnorePadding(SPR_COMPANY_ICON, pal, r.WithWidth(d.width, rtl), SA_CENTER); + + Rect tr = r.CentreToHeight(GetCharacterHeight(FS_NORMAL)).Indent(d.width + WidgetDimensions::scaled.hsep_normal, rtl); + if (this->company_id == COMPANY_SPECTATOR) { + DrawString(tr, STR_NETWORK_CLIENT_LIST_SPECTATORS, TC_SILVER); + } else if (this->company_id == COMPANY_NEW_COMPANY) { + DrawString(tr, STR_NETWORK_CLIENT_LIST_NEW_COMPANY, TC_WHITE); + } else { + DrawString(tr, GetString(STR_COMPANY_NAME, this->company_id, this->company_id), TC_SILVER); + } + }; + +private: + CompanyID company_id; +}; + +class ClientButtonLine : public ButtonLine { +public: + ClientButtonLine(ClientPoolID client_pool_id) : client_pool_id(client_pool_id) {} + + void Draw(Rect r) const override + { + const NetworkClientInfo *ci = NetworkClientInfo::GetIfValid(this->client_pool_id); + if (ci == nullptr) return; + + bool rtl = _current_text_dir == TD_RTL; + r = this->DrawButtons(r); + + Rect tr = r.CentreToHeight(GetCharacterHeight(FS_NORMAL)); + + SpriteID player_icon = 0; + if (ci->client_id == _network_own_client_id) { + player_icon = SPR_PLAYER_SELF; + } else if (ci->client_id == CLIENT_ID_SERVER) { + player_icon = SPR_PLAYER_HOST; + } + + if (player_icon != 0) { + Dimension d = GetScaledSpriteSize(player_icon); + DrawSpriteIgnorePadding(player_icon, PALETTE_TO_GREY, r.WithWidth(d.width, rtl), SA_CENTER); + tr = tr.Indent(d.width + WidgetDimensions::scaled.hsep_normal, rtl); + } + + DrawString(tr, GetString(STR_JUST_RAW_STRING, ci->client_name), TC_BLACK); + } + + std::optional GetTooltip(Rect r, const Point &pt) const override + { + bool rtl = _current_text_dir == TD_RTL; + Dimension d = GetScaledSpriteSize(SPR_PLAYER_SELF); + + if (r.WithWidth(d.width, rtl).Contains(pt)) { + const NetworkClientInfo *ci = NetworkClientInfo::GetIfValid(this->client_pool_id); + if (ci != nullptr) { + if (ci->client_id == _network_own_client_id) { + return GetEncodedString(STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP); + } else if (ci->client_id == CLIENT_ID_SERVER) { + return GetEncodedString(STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP); + } + } + } + + return this->ButtonLine::GetTooltip(r, pt); + } + +private: + ClientPoolID client_pool_id; +}; + /** * Main handle for clientlist */ @@ -1393,12 +1546,9 @@ struct NetworkClientListWindow : Window { Scrollbar *vscroll = nullptr; ///< Vertical scrollbar of this window. uint line_height = 0; ///< Current lineheight of each entry in the matrix. - uint line_count = 0; ///< Amount of lines in the matrix. int hover_index = -1; ///< Index of the current line we are hovering over, or -1 if none. - int player_self_index = -1; ///< The line the current player is on. - int player_host_index = -1; ///< The line the host is on. - std::map>> buttons{}; ///< Per line which buttons are available. + std::vector> buttons{}; ///< Per line which buttons are available. /** * Chat button on a Company is clicked. @@ -1504,34 +1654,24 @@ struct NetworkClientListWindow : Window { */ void RebuildListCompany(CompanyID company_id, CompanyID client_playas, bool can_join_company) { - ButtonCommon *chat_button = new CompanyButton(SPR_CHAT, company_id == COMPANY_SPECTATOR ? STR_NETWORK_CLIENT_LIST_CHAT_SPECTATOR_TOOLTIP : STR_NETWORK_CLIENT_LIST_CHAT_COMPANY_TOOLTIP, COLOUR_ORANGE, company_id, &NetworkClientListWindow::OnClickCompanyChat); - - if (_network_server) this->buttons[line_count].push_back(std::make_unique(SPR_ADMIN, STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_TOOLTIP, COLOUR_RED, company_id, &NetworkClientListWindow::OnClickCompanyAdmin, company_id == COMPANY_SPECTATOR)); - this->buttons[line_count].emplace_back(chat_button); - if (can_join_company) this->buttons[line_count].push_back(std::make_unique(SPR_JOIN, STR_NETWORK_CLIENT_LIST_JOIN_TOOLTIP, COLOUR_ORANGE, company_id, &NetworkClientListWindow::OnClickCompanyJoin, company_id != COMPANY_SPECTATOR && Company::Get(company_id)->is_ai)); - - this->line_count += 1; + ButtonLine &company_line = *this->buttons.emplace_back(std::make_unique(company_id)); + if (_network_server) company_line.AddButton(SPR_ADMIN, STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_TOOLTIP, COLOUR_RED, company_id, &NetworkClientListWindow::OnClickCompanyAdmin, company_id == COMPANY_SPECTATOR); + ButtonCommon &chat_button = company_line.AddButton(SPR_CHAT, company_id == COMPANY_SPECTATOR ? STR_NETWORK_CLIENT_LIST_CHAT_SPECTATOR_TOOLTIP : STR_NETWORK_CLIENT_LIST_CHAT_COMPANY_TOOLTIP, COLOUR_ORANGE, company_id, &NetworkClientListWindow::OnClickCompanyChat); + if (can_join_company) company_line.AddButton(SPR_JOIN, STR_NETWORK_CLIENT_LIST_JOIN_TOOLTIP, COLOUR_ORANGE, company_id, &NetworkClientListWindow::OnClickCompanyJoin, company_id != COMPANY_SPECTATOR && Company::Get(company_id)->is_ai); bool has_players = false; for (const NetworkClientInfo *ci : NetworkClientInfo::Iterate()) { if (ci->client_playas != company_id) continue; has_players = true; - if (_network_server) this->buttons[line_count].push_back(std::make_unique(SPR_ADMIN, STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_TOOLTIP, COLOUR_RED, ci->client_id, &NetworkClientListWindow::OnClickClientAdmin, _network_own_client_id == ci->client_id)); - if (_network_own_client_id != ci->client_id) this->buttons[line_count].push_back(std::make_unique(SPR_CHAT, STR_NETWORK_CLIENT_LIST_CHAT_CLIENT_TOOLTIP, COLOUR_ORANGE, ci->client_id, &NetworkClientListWindow::OnClickClientChat)); - if (_network_own_client_id != ci->client_id && client_playas != COMPANY_SPECTATOR && !ci->CanJoinCompany(client_playas)) this->buttons[line_count].push_back(std::make_unique(SPR_JOIN, STR_NETWORK_CLIENT_LIST_COMPANY_AUTHORIZE_TOOLTIP, COLOUR_GREEN, ci->client_id, &NetworkClientListWindow::OnClickClientAuthorize)); - - if (ci->client_id == _network_own_client_id) { - this->player_self_index = this->line_count; - } else if (ci->client_id == CLIENT_ID_SERVER) { - this->player_host_index = this->line_count; - } - - this->line_count += 1; + ButtonLine &line = *this->buttons.emplace_back(std::make_unique(ci->index)); + if (_network_server) line.AddButton(SPR_ADMIN, STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_TOOLTIP, COLOUR_RED, ci->client_id, &NetworkClientListWindow::OnClickClientAdmin, _network_own_client_id == ci->client_id); + if (_network_own_client_id != ci->client_id) line.AddButton(SPR_CHAT, STR_NETWORK_CLIENT_LIST_CHAT_CLIENT_TOOLTIP, COLOUR_ORANGE, ci->client_id, &NetworkClientListWindow::OnClickClientChat); + if (_network_own_client_id != ci->client_id && client_playas != COMPANY_SPECTATOR && !ci->CanJoinCompany(client_playas)) line.AddButton(SPR_JOIN, STR_NETWORK_CLIENT_LIST_COMPANY_AUTHORIZE_TOOLTIP, COLOUR_GREEN, ci->client_id, &NetworkClientListWindow::OnClickClientAuthorize); } /* Disable the chat button when there are players in this company. */ - chat_button->disabled = !has_players; + chat_button.disabled = !has_players; } /** @@ -1543,14 +1683,11 @@ struct NetworkClientListWindow : Window { CompanyID client_playas = own_ci == nullptr ? COMPANY_SPECTATOR : own_ci->client_playas; this->buttons.clear(); - this->line_count = 0; - this->player_host_index = -1; - this->player_self_index = -1; /* As spectator, show a line to create a new company. */ if (client_playas == COMPANY_SPECTATOR && !NetworkMaxCompaniesReached()) { - this->buttons[line_count].push_back(std::make_unique(SPR_JOIN, STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP, COLOUR_ORANGE, COMPANY_SPECTATOR, &NetworkClientListWindow::OnClickCompanyNew)); - this->line_count += 1; + ButtonLine &line = *this->buttons.emplace_back(std::make_unique(COMPANY_NEW_COMPANY)); + line.AddButton(SPR_JOIN, STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP, COLOUR_ORANGE, COMPANY_SPECTATOR, &NetworkClientListWindow::OnClickCompanyNew); } if (client_playas != COMPANY_SPECTATOR) { @@ -1567,40 +1704,7 @@ struct NetworkClientListWindow : Window { /* Spectators */ this->RebuildListCompany(COMPANY_SPECTATOR, client_playas, client_playas != COMPANY_SPECTATOR); - this->vscroll->SetCount(this->line_count); - } - - /** - * Get the button at a specific point on the WID_CL_MATRIX. - * @param pt The point to look for a button. - * @return The button or a nullptr if there was none. - */ - ButtonCommon *GetButtonAtPoint(Point pt) - { - uint index = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_CL_MATRIX); - Rect matrix = this->GetWidget(WID_CL_MATRIX)->GetCurrentRect().Shrink(WidgetDimensions::scaled.framerect); - - bool rtl = _current_text_dir == TD_RTL; - uint x = rtl ? matrix.left : matrix.right; - - /* Find the buttons for this row. */ - auto button_find = this->buttons.find(index); - if (button_find == this->buttons.end()) return nullptr; - - /* Check if we want to display a tooltip for any of the buttons. */ - for (auto &button : button_find->second) { - uint left = rtl ? x : x - button->width; - uint right = rtl ? x + button->width : x; - - if (IsInsideMM(pt.x, left, right)) { - return button.get(); - } - - int width = button->width + WidgetDimensions::scaled.framerect.Horizontal(); - x += rtl ? width : -width; - } - - return nullptr; + this->vscroll->SetCount(this->buttons.size()); } public: @@ -1614,7 +1718,7 @@ struct NetworkClientListWindow : Window { void OnInit() override { - RebuildList(); + this->RebuildList(); } void OnInvalidateData([[maybe_unused]] int data = 0, [[maybe_unused]] bool gui_scope = true) override @@ -1650,7 +1754,7 @@ struct NetworkClientListWindow : Window { break; case WID_CL_MATRIX: { - uint height = std::max({GetSpriteSize(SPR_COMPANY_ICON).height, GetSpriteSize(SPR_JOIN).height, GetSpriteSize(SPR_ADMIN).height, GetSpriteSize(SPR_CHAT).height}); + uint height = std::max({GetScaledSpriteSize(SPR_COMPANY_ICON).height, GetScaledSpriteSize(SPR_JOIN).height, GetScaledSpriteSize(SPR_ADMIN).height, GetScaledSpriteSize(SPR_CHAT).height}); height += WidgetDimensions::scaled.framerect.Vertical(); this->line_height = std::max(height, (uint)GetCharacterHeight(FS_NORMAL)) + padding.height; @@ -1718,7 +1822,11 @@ struct NetworkClientListWindow : Window { break; case WID_CL_MATRIX: { - ButtonCommon *button = this->GetButtonAtPoint(pt); + auto it = this->vscroll->GetScrolledItemFromWidget(this->buttons, pt.y, this, WID_CL_MATRIX); + if (it == std::end(this->buttons)) break; + + Rect r = this->GetWidget(WID_CL_MATRIX)->GetCurrentRect().Shrink(WidgetDimensions::scaled.framerect); + ButtonCommon *button = (*it)->GetButton(r, pt); if (button == nullptr) break; button->OnClick(this, pt); @@ -1731,34 +1839,14 @@ struct NetworkClientListWindow : Window { { switch (widget) { case WID_CL_MATRIX: { - int index = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_CL_MATRIX); - - bool rtl = _current_text_dir == TD_RTL; - Rect matrix = this->GetWidget(WID_CL_MATRIX)->GetCurrentRect().Shrink(WidgetDimensions::scaled.framerect); - - Dimension d = GetSpriteSize(SPR_COMPANY_ICON); - uint text_left = matrix.left + (rtl ? 0 : d.width + WidgetDimensions::scaled.hsep_wide); - uint text_right = matrix.right - (rtl ? d.width + WidgetDimensions::scaled.hsep_wide : 0); + auto it = this->vscroll->GetScrolledItemFromWidget(this->buttons, pt.y, this, WID_CL_MATRIX); + if (it == std::end(this->buttons)) break; - Dimension d2 = GetSpriteSize(SPR_PLAYER_SELF); - uint offset_x = WidgetDimensions::scaled.hsep_indent - d2.width - ScaleGUITrad(3); + Rect r = this->GetWidget(WID_CL_MATRIX)->GetCurrentRect().Shrink(WidgetDimensions::scaled.framerect); + auto tooltip = (*it)->GetTooltip(r, pt); + if (!tooltip.has_value()) break; - uint player_icon_x = rtl ? text_right - offset_x - d2.width : text_left + offset_x; - - if (IsInsideMM(pt.x, player_icon_x, player_icon_x + d2.width)) { - if (index == this->player_self_index) { - GuiShowTooltips(this, GetEncodedString(STR_NETWORK_CLIENT_LIST_PLAYER_ICON_SELF_TOOLTIP), close_cond); - return true; - } else if (index == this->player_host_index) { - GuiShowTooltips(this, GetEncodedString(STR_NETWORK_CLIENT_LIST_PLAYER_ICON_HOST_TOOLTIP), close_cond); - return true; - } - } - - ButtonCommon *button = this->GetButtonAtPoint(pt); - if (button == nullptr) return false; - - GuiShowTooltips(this, GetEncodedString(button->tooltip), close_cond); + GuiShowTooltips(this, std::move(*tooltip), close_cond); return true; }; } @@ -1852,154 +1940,23 @@ struct NetworkClientListWindow : Window { } } - /** - * Draw the buttons for a single line in the matrix. - * - * The x-position in RTL is the most left or otherwise the most right pixel - * we can draw the buttons from. - * - * @param x The x-position to start with the buttons. Updated during this function. - * @param y The y-position to start with the buttons. - * @param buttons The buttons to draw. - */ - void DrawButtons(int &x, uint y, const std::vector> &buttons) const - { - Rect r; - - for (auto &button : buttons) { - bool rtl = _current_text_dir == TD_RTL; - - int offset = (this->line_height - button->height) / 2; - r.left = rtl ? x : x - button->width + 1; - r.right = rtl ? x + button->width - 1 : x; - r.top = y + offset; - r.bottom = r.top + button->height - 1; - - DrawFrameRect(r, button->colour, {}); - DrawSprite(button->sprite, PAL_NONE, r.left + WidgetDimensions::scaled.framerect.left, r.top + WidgetDimensions::scaled.framerect.top); - if (button->disabled) { - GfxFillRect(r.Shrink(WidgetDimensions::scaled.bevel), GetColourGradient(button->colour, SHADE_DARKER), FILLRECT_CHECKER); - } - - int width = button->width + WidgetDimensions::scaled.hsep_normal; - x += rtl ? width : -width; - } - } - - /** - * Draw a company and its clients on the matrix. - * @param company_id The company to draw. - * @param r The rect to draw within. - * @param line The Nth line we are drawing. Updated during this function. - */ - void DrawCompany(CompanyID company_id, const Rect &r, uint &line) const - { - bool rtl = _current_text_dir == TD_RTL; - int text_y_offset = CentreBounds(0, this->line_height, GetCharacterHeight(FS_NORMAL)); - - Dimension d = GetSpriteSize(SPR_COMPANY_ICON); - int offset = CentreBounds(0, this->line_height, d.height); - - uint line_start = this->vscroll->GetPosition(); - uint line_end = line_start + this->vscroll->GetCapacity(); - - uint y = r.top + (this->line_height * (line - line_start)); - - /* Draw the company line (if in range of scrollbar). */ - if (IsInsideMM(line, line_start, line_end)) { - int icon_left = r.WithWidth(d.width, rtl).left; - Rect tr = r.Indent(d.width + WidgetDimensions::scaled.hsep_normal, rtl); - int &x = rtl ? tr.left : tr.right; - - /* If there are buttons for this company, draw them. */ - auto button_find = this->buttons.find(line); - if (button_find != this->buttons.end()) { - this->DrawButtons(x, y, button_find->second); - } - - if (company_id == COMPANY_SPECTATOR) { - DrawSprite(SPR_COMPANY_ICON, PALETTE_TO_GREY, icon_left, y + offset); - DrawString(tr.left, tr.right, y + text_y_offset, STR_NETWORK_CLIENT_LIST_SPECTATORS, TC_SILVER); - } else if (company_id == COMPANY_NEW_COMPANY) { - DrawSprite(SPR_COMPANY_ICON, PALETTE_TO_GREY, icon_left, y + offset); - DrawString(tr.left, tr.right, y + text_y_offset, STR_NETWORK_CLIENT_LIST_NEW_COMPANY, TC_WHITE); - } else { - DrawCompanyIcon(company_id, icon_left, y + offset); - - DrawString(tr.left, tr.right, y + text_y_offset, GetString(STR_COMPANY_NAME, company_id, company_id), TC_SILVER); - } - } - - y += this->line_height; - line++; - - for (const NetworkClientInfo *ci : NetworkClientInfo::Iterate()) { - if (ci->client_playas != company_id) continue; - - /* Draw the player line (if in range of scrollbar). */ - if (IsInsideMM(line, line_start, line_end)) { - Rect tr = r.Indent(WidgetDimensions::scaled.hsep_indent, rtl); - - /* If there are buttons for this client, draw them. */ - auto button_find = this->buttons.find(line); - if (button_find != this->buttons.end()) { - int &x = rtl ? tr.left : tr.right; - this->DrawButtons(x, y, button_find->second); - } - - SpriteID player_icon = 0; - if (ci->client_id == _network_own_client_id) { - player_icon = SPR_PLAYER_SELF; - } else if (ci->client_id == CLIENT_ID_SERVER) { - player_icon = SPR_PLAYER_HOST; - } - - if (player_icon != 0) { - Dimension d2 = GetSpriteSize(player_icon); - int offset_y = CentreBounds(0, this->line_height, d2.height); - DrawSprite(player_icon, PALETTE_TO_GREY, rtl ? tr.right - d2.width : tr.left, y + offset_y); - tr = tr.Indent(d2.width + WidgetDimensions::scaled.hsep_normal, rtl); - } - - DrawString(tr.left, tr.right, y + text_y_offset, GetString(STR_JUST_RAW_STRING, ci->client_name), TC_BLACK); - } - - y += this->line_height; - line++; - } - } - void DrawWidget(const Rect &r, WidgetID widget) const override { switch (widget) { case WID_CL_MATRIX: { - Rect ir = r.Shrink(WidgetDimensions::scaled.framerect, RectPadding::zero); - uint line = 0; + Rect ir = r.WithHeight(this->line_height).Shrink(WidgetDimensions::scaled.framerect, RectPadding::zero); if (this->hover_index >= 0) { Rect br = r.WithHeight(this->line_height).Translate(0, this->hover_index * this->line_height); GfxFillRect(br.Shrink(WidgetDimensions::scaled.bevel), GREY_SCALE(9)); } - NetworkClientInfo *own_ci = NetworkClientInfo::GetByClientID(_network_own_client_id); - CompanyID client_playas = own_ci == nullptr ? COMPANY_SPECTATOR : own_ci->client_playas; - - if (client_playas == COMPANY_SPECTATOR && !NetworkMaxCompaniesReached()) { - this->DrawCompany(COMPANY_NEW_COMPANY, ir, line); - } - - if (client_playas != COMPANY_SPECTATOR) { - this->DrawCompany(client_playas, ir, line); - } - - for (const Company *c : Company::Iterate()) { - if (client_playas == c->index) continue; - this->DrawCompany(c->index, ir, line); + auto [first, last] = this->vscroll->GetVisibleRangeIterators(this->buttons); + for (auto it = first; it != last; ++it) { + (*it)->Draw(ir); + ir = ir.Translate(0, this->line_height); } - /* Spectators */ - this->DrawCompany(COMPANY_SPECTATOR, ir, line); - break; } } @@ -2140,7 +2097,7 @@ struct NetworkJoinStatusWindow : Window { } }; -static constexpr NWidgetPart _nested_network_join_status_window_widgets[] = { +static constexpr std::initializer_list _nested_network_join_status_window_widgets = { NWidget(WWT_CAPTION, COLOUR_GREY), SetStringTip(STR_NETWORK_CONNECTING_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), NWidget(WWT_PANEL, COLOUR_GREY), NWidget(NWID_VERTICAL), SetPIP(0, WidgetDimensions::unscaled.vsep_wide, 0), SetPadding(WidgetDimensions::unscaled.modalpopup), @@ -2241,7 +2198,7 @@ struct NetworkAskRelayWindow : public Window { } }; -static constexpr NWidgetPart _nested_network_ask_relay_widgets[] = { +static constexpr std::initializer_list _nested_network_ask_relay_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_RED), NWidget(WWT_CAPTION, COLOUR_RED, WID_NAR_CAPTION), SetStringTip(STR_NETWORK_ASK_RELAY_CAPTION), @@ -2336,7 +2293,7 @@ struct NetworkAskSurveyWindow : public Window { } }; -static constexpr NWidgetPart _nested_network_ask_survey_widgets[] = { +static constexpr std::initializer_list _nested_network_ask_survey_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), NWidget(WWT_CAPTION, COLOUR_GREY, WID_NAS_CAPTION), SetStringTip(STR_NETWORK_ASK_SURVEY_CAPTION), diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp index 3087db360efa8..ff39b2b854a17 100644 --- a/src/network/network_server.cpp +++ b/src/network/network_server.cpp @@ -1451,7 +1451,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_RCON(Packet &p) /* We are allowed, nothing more to validate. */ } else if (_settings_client.network.rcon_password.empty()) { return NETWORK_RECV_STATUS_OKAY; - } else if (_settings_client.network.rcon_password.compare(password) != 0) { + } else if (_settings_client.network.rcon_password != password) { Debug(net, 1, "[rcon] Wrong password from client-id {}", this->client_id); return NETWORK_RECV_STATUS_OKAY; } @@ -1648,7 +1648,7 @@ bool NetworkServerChangeClientName(ClientID client_id, const std::string &new_na { /* Check if the name's already in use */ for (NetworkClientInfo *ci : NetworkClientInfo::Iterate()) { - if (ci->client_name.compare(new_name) == 0) return false; + if (ci->client_name == new_name) return false; } NetworkClientInfo *ci = NetworkClientInfo::GetByClientID(client_id); diff --git a/src/newgrf.cpp b/src/newgrf.cpp index b6444a8e06ba1..ecbd4982f3944 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -148,9 +148,12 @@ GRFError *DisableGrf(StringID message, GRFConfig *config) if (message == STR_NULL) return nullptr; - config->error = {STR_NEWGRF_ERROR_MSG_FATAL, message}; - if (config == _cur_gps.grfconfig) config->error->param_value[0] = _cur_gps.nfo_line; - return &config->error.value(); + auto it = std::ranges::find(config->errors, _cur_gps.nfo_line, &GRFError::nfo_line); + if (it == std::end(config->errors)) { + it = config->errors.emplace(it, STR_NEWGRF_ERROR_MSG_FATAL, _cur_gps.nfo_line, message); + } + if (config == _cur_gps.grfconfig) it->param_value[0] = _cur_gps.nfo_line; + return &*it; } /** @@ -272,7 +275,7 @@ Engine *GetNewEngine(const GRFFile *file, VehicleType type, uint16_t internal_id } if (type == VEH_TRAIN) { _gted[e->index].railtypelabels.clear(); - for (RailType rt : e->u.rail.railtypes) _gted[e->index].railtypelabels.push_back(GetRailTypeInfo(rt)->label); + for (RailType rt : e->VehInfo().railtypes) _gted[e->index].railtypelabels.push_back(GetRailTypeInfo(rt)->label); } GrfMsg(5, "Created new engine at index {} for GRFID {:x}, type {}, index {}", e->index, std::byteswap(file->grfid), type, internal_id); @@ -392,7 +395,7 @@ static void ResetNewGRF() static void ResetNewGRFErrors() { for (const auto &c : _grfconfig) { - c->error.reset(); + c->errors.clear(); } } @@ -427,7 +430,7 @@ void ResetNewGRFData() /* Fill rail type label temporary data for default trains */ for (const Engine *e : Engine::IterateType(VEH_TRAIN)) { _gted[e->index].railtypelabels.clear(); - for (RailType rt : e->u.rail.railtypes) _gted[e->index].railtypelabels.push_back(GetRailTypeInfo(rt)->label); + for (RailType rt : e->VehInfo().railtypes) _gted[e->index].railtypelabels.push_back(GetRailTypeInfo(rt)->label); } /* Reset GRM reservations */ @@ -578,19 +581,16 @@ GRFFile::GRFFile(const GRFConfig &config) this->price_base_multipliers.fill(INVALID_PRICE_MODIFIER); /* Initialise rail type map with default rail types */ - this->railtype_map.fill(INVALID_RAILTYPE); - this->railtype_map[0] = RAILTYPE_RAIL; - this->railtype_map[1] = RAILTYPE_ELECTRIC; - this->railtype_map[2] = RAILTYPE_MONO; - this->railtype_map[3] = RAILTYPE_MAGLEV; + this->railtype_map.emplace_back(RAILTYPE_RAIL); + this->railtype_map.emplace_back(RAILTYPE_ELECTRIC); + this->railtype_map.emplace_back(RAILTYPE_MONO); + this->railtype_map.emplace_back(RAILTYPE_MAGLEV); /* Initialise road type map with default road types */ - this->roadtype_map.fill(INVALID_ROADTYPE); - this->roadtype_map[0] = ROADTYPE_ROAD; + this->roadtype_map.emplace_back(ROADTYPE_ROAD); /* Initialise tram type map with default tram types */ - this->tramtype_map.fill(INVALID_ROADTYPE); - this->tramtype_map[0] = ROADTYPE_TRAM; + this->tramtype_map.emplace_back(ROADTYPE_TRAM); /* Copy the initial parameter list */ this->param = config.param; @@ -661,7 +661,7 @@ static void CalculateRefitMasks() /* If the NewGRF did not set any cargo properties, we apply default values. */ if (_gted[engine].defaultcargo_grf == nullptr) { /* If the vehicle has any capacity, apply the default refit masks */ - if (e->type != VEH_TRAIN || e->u.rail.capacity != 0) { + if (e->type != VEH_TRAIN || e->VehInfo().capacity != 0) { static constexpr LandscapeType T = LandscapeType::Temperate; static constexpr LandscapeType A = LandscapeType::Arctic; static constexpr LandscapeType S = LandscapeType::Tropic; @@ -716,8 +716,8 @@ static void CalculateRefitMasks() } break; } - e->u.ship.old_refittable = true; - } else if (e->type == VEH_TRAIN && e->u.rail.railveh_type != RAILVEH_WAGON) { + e->VehInfo().old_refittable = true; + } else if (e->type == VEH_TRAIN && e->VehInfo().railveh_type != RAILVEH_WAGON) { /* Train engines default to all cargoes, so you can build single-cargo consists with fast engines. * Trains loading multiple cargoes may start stations accepting unwanted cargoes. */ _gted[engine].cargo_allowed = {CargoClass::Passengers, CargoClass::Mail, CargoClass::Armoured, CargoClass::Express, CargoClass::Bulk, CargoClass::PieceGoods, CargoClass::Liquid}; @@ -792,7 +792,7 @@ static void CalculateRefitMasks() /* Ensure that the vehicle is either not refittable, or that the default cargo is one of the refittable cargoes. * Note: Vehicles refittable to no cargo are handle differently to vehicle refittable to a single cargo. The latter might have subtypes. */ - if (!only_defaultcargo && (e->type != VEH_SHIP || e->u.ship.old_refittable) && IsValidCargoType(ei->cargo_type) && !HasBit(ei->refit_mask, ei->cargo_type)) { + if (!only_defaultcargo && (e->type != VEH_SHIP || e->VehInfo().old_refittable) && IsValidCargoType(ei->cargo_type) && !HasBit(ei->refit_mask, ei->cargo_type)) { ei->cargo_type = INVALID_CARGO; } @@ -819,7 +819,7 @@ static void CalculateRefitMasks() ei->cargo_type = (CargoType)FindFirstBit(ei->refit_mask); } } - if (!IsValidCargoType(ei->cargo_type) && e->type == VEH_TRAIN && e->u.rail.railveh_type != RAILVEH_WAGON && e->u.rail.capacity == 0) { + if (!IsValidCargoType(ei->cargo_type) && e->type == VEH_TRAIN && e->VehInfo().railveh_type != RAILVEH_WAGON && e->VehInfo().capacity == 0) { /* For train engines which do not carry cargo it does not matter if their cargo type is invalid. * Fallback to the first available instead, if the cargo type has not been changed (as indicated by * cargo_label not being CT_INVALID). */ @@ -830,7 +830,7 @@ static void CalculateRefitMasks() if (!IsValidCargoType(ei->cargo_type)) ei->climates = {}; /* Clear refit_mask for not refittable ships */ - if (e->type == VEH_SHIP && !e->u.ship.old_refittable) { + if (e->type == VEH_SHIP && !e->VehInfo().old_refittable) { ei->refit_mask = 0; } } @@ -867,16 +867,16 @@ static void FinaliseEngineArray() switch (e->type) { case VEH_TRAIN: - for (RailType rt : e->u.rail.railtypes) { + for (RailType rt : e->VehInfo().railtypes) { AppendCopyableBadgeList(e->badges, GetRailTypeInfo(rt)->badges, GSF_TRAINS); } break; - case VEH_ROAD: AppendCopyableBadgeList(e->badges, GetRoadTypeInfo(e->u.road.roadtype)->badges, GSF_ROADVEHICLES); break; + case VEH_ROAD: AppendCopyableBadgeList(e->badges, GetRoadTypeInfo(e->VehInfo().roadtype)->badges, GSF_ROADVEHICLES); break; default: break; } /* Skip wagons, there livery is defined via the engine */ - if (e->type != VEH_TRAIN || e->u.rail.railveh_type != RAILVEH_WAGON) { + if (e->type != VEH_TRAIN || e->VehInfo().railveh_type != RAILVEH_WAGON) { LiveryScheme ls = GetEngineLiveryScheme(e->index, EngineID::Invalid(), nullptr); SetBit(_loaded_newgrf_features.used_liveries, ls); /* Note: For ships and roadvehicles we assume that they cannot be refitted between passenger and freight */ @@ -1693,14 +1693,14 @@ static void AfterLoadGRFs() for (Engine *e : Engine::IterateType(VEH_ROAD)) { if (_gted[e->index].rv_max_speed != 0) { /* Set RV maximum speed from the mph/0.8 unit value */ - e->u.road.max_speed = _gted[e->index].rv_max_speed * 4; + e->VehInfo().max_speed = _gted[e->index].rv_max_speed * 4; } RoadTramType rtt = e->info.misc_flags.Test(EngineMiscFlag::RoadIsTram) ? RTT_TRAM : RTT_ROAD; const GRFFile *file = e->GetGRF(); if (file == nullptr || _gted[e->index].roadtramtype == 0) { - e->u.road.roadtype = (rtt == RTT_TRAM) ? ROADTYPE_TRAM : ROADTYPE_ROAD; + e->VehInfo().roadtype = (rtt == RTT_TRAM) ? ROADTYPE_TRAM : ROADTYPE_ROAD; continue; } @@ -1713,7 +1713,7 @@ static void AfterLoadGRFs() RoadTypeLabel rtl = (*list)[_gted[e->index].roadtramtype]; RoadType rt = GetRoadTypeByLabel(rtl); if (rt != INVALID_ROADTYPE && GetRoadTramType(rt) == rtt) { - e->u.road.roadtype = rt; + e->VehInfo().roadtype = rt; continue; } } @@ -1730,8 +1730,8 @@ static void AfterLoadGRFs() } if (railtypes.Any()) { - e->u.rail.railtypes = railtypes; - e->u.rail.intended_railtypes = railtypes; + e->VehInfo().railtypes = railtypes; + e->VehInfo().intended_railtypes = railtypes; } else { /* Rail type is not available, so disable this engine */ e->info.climates = {}; @@ -1841,7 +1841,7 @@ void LoadNewGRF(SpriteID load_index, uint num_baseset) if (num_non_static == NETWORK_MAX_GRF_COUNT) { Debug(grf, 0, "'{}' is not loaded as the maximum number of non-static GRFs has been reached", c->filename); c->status = GCS_DISABLED; - c->error = {STR_NEWGRF_ERROR_MSG_FATAL, STR_NEWGRF_ERROR_TOO_MANY_NEWGRFS_LOADED}; + c->errors.emplace_back(STR_NEWGRF_ERROR_MSG_FATAL, 0, STR_NEWGRF_ERROR_TOO_MANY_NEWGRFS_LOADED); continue; } num_non_static++; diff --git a/src/newgrf.h b/src/newgrf.h index beb5a0ed4f45b..97bc74dbf1bbf 100644 --- a/src/newgrf.h +++ b/src/newgrf.h @@ -140,13 +140,13 @@ struct GRFFile { std::unordered_map badge_map{}; std::vector railtype_list{}; ///< Railtype translation table - std::array railtype_map{}; + std::vector railtype_map{}; std::vector roadtype_list{}; ///< Roadtype translation table (road) - std::array roadtype_map{}; + std::vector roadtype_map{}; std::vector tramtype_list{}; ///< Roadtype translation table (tram) - std::array tramtype_map{}; + std::vector tramtype_map{}; std::array canal_local_properties{}; ///< Canal properties as set by this NewGRF diff --git a/src/newgrf/newgrf_act0_aircraft.cpp b/src/newgrf/newgrf_act0_aircraft.cpp index d246544784a08..d4e7df1298baa 100644 --- a/src/newgrf/newgrf_act0_aircraft.cpp +++ b/src/newgrf/newgrf_act0_aircraft.cpp @@ -35,7 +35,7 @@ static ChangeInfoResult AircraftVehicleChangeInfo(uint first, uint last, int pro if (e == nullptr) return CIR_INVALID_ID; // No engine could be allocated, so neither can any next vehicles EngineInfo *ei = &e->info; - AircraftVehicleInfo *avi = &e->u.air; + AircraftVehicleInfo *avi = &e->VehInfo(); switch (prop) { case 0x08: { // Sprite ID diff --git a/src/newgrf/newgrf_act0_globalvar.cpp b/src/newgrf/newgrf_act0_globalvar.cpp index b71fccfb9bdc2..18aa6d67a9f09 100644 --- a/src/newgrf/newgrf_act0_globalvar.cpp +++ b/src/newgrf/newgrf_act0_globalvar.cpp @@ -178,6 +178,7 @@ static ChangeInfoResult GlobalVarChangeInfo(uint first, uint last, int prop, Byt if (curidx < CURRENCY_END) { _currency_specs[curidx].separator.clear(); _currency_specs[curidx].separator.push_back(GB(options, 0, 8)); + StrMakeValidInPlace(_currency_specs[curidx].separator); /* By specifying only one bit, we prevent errors, * since newgrf specs said that only 0 and 1 can be set for symbol_pos */ _currency_specs[curidx].symbol_pos = GB(options, 8, 1); diff --git a/src/newgrf/newgrf_act0_railtypes.cpp b/src/newgrf/newgrf_act0_railtypes.cpp index 27394f8bf414c..4ac6090af4929 100644 --- a/src/newgrf/newgrf_act0_railtypes.cpp +++ b/src/newgrf/newgrf_act0_railtypes.cpp @@ -28,7 +28,7 @@ static ChangeInfoResult RailTypeChangeInfo(uint first, uint last, int prop, Byte { ChangeInfoResult ret = CIR_SUCCESS; - extern RailTypeInfo _railtypes[RAILTYPE_END]; + extern std::vector _railtypes; const auto &type_map = _cur_gps.grffile->railtype_map; if (last > std::size(type_map)) { @@ -163,13 +163,10 @@ static ChangeInfoResult RailTypeReserveInfo(uint first, uint last, int prop, Byt { ChangeInfoResult ret = CIR_SUCCESS; - extern RailTypeInfo _railtypes[RAILTYPE_END]; + extern std::vector _railtypes; auto &type_map = _cur_gps.grffile->railtype_map; - if (last > std::size(type_map)) { - GrfMsg(1, "RailTypeReserveInfo: Rail type {} is invalid, max {}, ignoring", last, std::size(type_map)); - return CIR_INVALID_ID; - } + if (type_map.size() < last) type_map.resize(last, INVALID_RAILTYPE); for (uint id = first; id < last; ++id) { switch (prop) { @@ -204,7 +201,7 @@ static ChangeInfoResult RailTypeReserveInfo(uint first, uint last, int prop, Byt if (type_map[id] != INVALID_RAILTYPE) { int n = buf.ReadByte(); for (int j = 0; j != n; j++) { - _railtypes[type_map[id]].alternate_labels.push_back(std::byteswap(buf.ReadDWord())); + _railtypes[type_map[id]].alternate_labels.insert(std::byteswap(buf.ReadDWord())); } break; } diff --git a/src/newgrf/newgrf_act0_roadtypes.cpp b/src/newgrf/newgrf_act0_roadtypes.cpp index 2eff6b05fde0d..b3765ada7a550 100644 --- a/src/newgrf/newgrf_act0_roadtypes.cpp +++ b/src/newgrf/newgrf_act0_roadtypes.cpp @@ -29,8 +29,8 @@ static ChangeInfoResult RoadTypeChangeInfo(uint first, uint last, int prop, Byte { ChangeInfoResult ret = CIR_SUCCESS; - extern RoadTypeInfo _roadtypes[ROADTYPE_END]; - const auto &type_map = (rtt == RTT_TRAM) ? _cur_gps.grffile->tramtype_map : _cur_gps.grffile->roadtype_map; + extern std::vector _roadtypes; + auto &type_map = (rtt == RTT_TRAM) ? _cur_gps.grffile->tramtype_map : _cur_gps.grffile->roadtype_map; if (last > std::size(type_map)) { GrfMsg(1, "RoadTypeChangeInfo: Road type {} is invalid, max {}, ignoring", last, std::size(type_map)); @@ -150,13 +150,10 @@ static ChangeInfoResult RoadTypeReserveInfo(uint first, uint last, int prop, Byt { ChangeInfoResult ret = CIR_SUCCESS; - extern RoadTypeInfo _roadtypes[ROADTYPE_END]; - auto &type_map = (rtt == RTT_TRAM) ? _cur_gps.grffile->tramtype_map : _cur_gps.grffile->roadtype_map; + extern std::vector _roadtypes; + auto &type_map = (rtt == RTT_TRAM) ? _cur_gps.grffile->tramtype_map : _cur_gps.grffile->roadtype_map; - if (last > std::size(type_map)) { - GrfMsg(1, "RoadTypeReserveInfo: Road type {} is invalid, max {}, ignoring", last, std::size(type_map)); - return CIR_INVALID_ID; - } + if (type_map.size() < last) type_map.resize(last, INVALID_ROADTYPE); for (uint id = first; id < last; ++id) { switch (prop) { @@ -192,7 +189,7 @@ static ChangeInfoResult RoadTypeReserveInfo(uint first, uint last, int prop, Byt if (type_map[id] != INVALID_ROADTYPE) { int n = buf.ReadByte(); for (int j = 0; j != n; j++) { - _roadtypes[type_map[id]].alternate_labels.push_back(std::byteswap(buf.ReadDWord())); + _roadtypes[type_map[id]].alternate_labels.insert(std::byteswap(buf.ReadDWord())); } break; } diff --git a/src/newgrf/newgrf_act0_roadvehs.cpp b/src/newgrf/newgrf_act0_roadvehs.cpp index e8cf67f6bb1e2..34fd862c98141 100644 --- a/src/newgrf/newgrf_act0_roadvehs.cpp +++ b/src/newgrf/newgrf_act0_roadvehs.cpp @@ -36,7 +36,7 @@ static ChangeInfoResult RoadVehicleChangeInfo(uint first, uint last, int prop, B if (e == nullptr) return CIR_INVALID_ID; // No engine could be allocated, so neither can any next vehicles EngineInfo *ei = &e->info; - RoadVehicleInfo *rvi = &e->u.road; + RoadVehicleInfo *rvi = &e->VehInfo(); switch (prop) { case 0x05: // Road/tram type diff --git a/src/newgrf/newgrf_act0_ships.cpp b/src/newgrf/newgrf_act0_ships.cpp index 0e1bfe0b178cd..3b9c32b15cfa6 100644 --- a/src/newgrf/newgrf_act0_ships.cpp +++ b/src/newgrf/newgrf_act0_ships.cpp @@ -37,7 +37,7 @@ static ChangeInfoResult ShipVehicleChangeInfo(uint first, uint last, int prop, B if (e == nullptr) return CIR_INVALID_ID; // No engine could be allocated, so neither can any next vehicles EngineInfo *ei = &e->info; - ShipVehicleInfo *svi = &e->u.ship; + ShipVehicleInfo *svi = &e->VehInfo(); switch (prop) { case 0x08: { // Sprite ID diff --git a/src/newgrf/newgrf_act0_trains.cpp b/src/newgrf/newgrf_act0_trains.cpp index 8f8a4c4121bfa..0e44e3a1b5b0a 100644 --- a/src/newgrf/newgrf_act0_trains.cpp +++ b/src/newgrf/newgrf_act0_trains.cpp @@ -35,7 +35,7 @@ ChangeInfoResult RailVehicleChangeInfo(uint first, uint last, int prop, ByteRead if (e == nullptr) return CIR_INVALID_ID; // No engine could be allocated, so neither can any next vehicles EngineInfo *ei = &e->info; - RailVehicleInfo *rvi = &e->u.rail; + RailVehicleInfo *rvi = &e->VehInfo(); switch (prop) { case 0x05: { // Track type diff --git a/src/newgrf/newgrf_act12.cpp b/src/newgrf/newgrf_act12.cpp index 2e0250775b834..124d2f1afe9ab 100644 --- a/src/newgrf/newgrf_act12.cpp +++ b/src/newgrf/newgrf_act12.cpp @@ -10,6 +10,7 @@ #include "../stdafx.h" #include "../debug.h" #include "../fontcache.h" +#include "../spritecache.h" #include "newgrf_bytereader.h" #include "newgrf_internal.h" diff --git a/src/newgrf/newgrf_act3.cpp b/src/newgrf/newgrf_act3.cpp index 3ec90c87b768a..75aab45e812b8 100644 --- a/src/newgrf/newgrf_act3.cpp +++ b/src/newgrf/newgrf_act3.cpp @@ -272,8 +272,7 @@ struct RailTypeMapSpriteGroupHandler : MapSpriteGroupHandler { RailType railtype = local_id < std::size(type_map) ? type_map[local_id] : INVALID_RAILTYPE; if (railtype == INVALID_RAILTYPE) return; - extern RailTypeInfo _railtypes[RAILTYPE_END]; - RailTypeInfo &rti = _railtypes[railtype]; + RailTypeInfo &rti = GetRailTypeInfo()[railtype]; rti.grffile[cid] = _cur_gps.grffile; rti.group[cid] = group; } @@ -291,8 +290,7 @@ struct RoadTypeMapSpriteGroupHandler : MapSpriteGroupHandler { RoadType roadtype = local_id < std::size(type_map) ? type_map[local_id] : INVALID_ROADTYPE; if (roadtype == INVALID_ROADTYPE) return; - extern RoadTypeInfo _roadtypes[ROADTYPE_END]; - RoadTypeInfo &rti = _roadtypes[roadtype]; + RoadTypeInfo &rti = GetRoadTypeInfo()[roadtype]; rti.grffile[cid] = _cur_gps.grffile; rti.group[cid] = group; } diff --git a/src/newgrf/newgrf_act5.cpp b/src/newgrf/newgrf_act5.cpp index e9b590dfb2f07..efa1f99d2a469 100644 --- a/src/newgrf/newgrf_act5.cpp +++ b/src/newgrf/newgrf_act5.cpp @@ -78,6 +78,7 @@ static constexpr auto _action5_types = std::to_array({ /* 0x18 */ { A5BLOCK_ALLOW_OFFSET, SPR_PALETTE_BASE, 1, PALETTE_SPRITE_COUNT, "Palette" }, /* 0x19 */ { A5BLOCK_ALLOW_OFFSET, SPR_ROAD_WAYPOINTS_BASE, 1, ROAD_WAYPOINTS_SPRITE_COUNT, "Road waypoints" }, /* 0x1A */ { A5BLOCK_ALLOW_OFFSET, SPR_OVERLAY_ROCKS_BASE, 1, OVERLAY_ROCKS_SPRITE_COUNT, "Overlay rocks" }, + /* 0x1B */ { A5BLOCK_ALLOW_OFFSET, SPR_BRIDGE_DECKS_BASE, 1, BRIDGE_DECKS_SPRITE_COUNT, "Bridge decks" }, }); /** diff --git a/src/newgrf/newgrf_actb.cpp b/src/newgrf/newgrf_actb.cpp index 53aed45267ec9..11a3f7e322ba0 100644 --- a/src/newgrf/newgrf_actb.cpp +++ b/src/newgrf/newgrf_actb.cpp @@ -73,9 +73,6 @@ static void GRFLoadError(ByteReader &buf) /* This is a fatal error, so make sure the GRF is deactivated and no * more of it gets loaded. */ DisableGrf(); - - /* Make sure we show fatal errors, instead of silly infos from before */ - _cur_gps.grfconfig->error.reset(); } if (message_id >= lengthof(msgstr) && message_id != 0xFF) { @@ -88,39 +85,41 @@ static void GRFLoadError(ByteReader &buf) return; } - /* For now we can only show one message per newgrf file. */ - if (_cur_gps.grfconfig->error.has_value()) return; + /* An error may be emitted multiple times in different loading stages. Re-use if so. */ + auto it = std::ranges::find(_cur_gps.grfconfig->errors, _cur_gps.nfo_line, &GRFError::nfo_line); + if (it == std::end(_cur_gps.grfconfig->errors)) { + it = _cur_gps.grfconfig->errors.emplace(it, sevstr[severity], _cur_gps.nfo_line); + } - _cur_gps.grfconfig->error = {sevstr[severity]}; - GRFError *error = &_cur_gps.grfconfig->error.value(); + GRFError &error = *it; if (message_id == 0xFF) { /* This is a custom error message. */ if (buf.HasData()) { std::string_view message = buf.ReadString(); - error->custom_message = TranslateTTDPatchCodes(_cur_gps.grffile->grfid, lang, true, message, SCC_RAW_STRING_POINTER); + error.custom_message = TranslateTTDPatchCodes(_cur_gps.grffile->grfid, lang, true, message, SCC_RAW_STRING_POINTER); } else { GrfMsg(7, "GRFLoadError: No custom message supplied."); - error->custom_message.clear(); + error.custom_message.clear(); } } else { - error->message = msgstr[message_id]; + error.message = msgstr[message_id]; } if (buf.HasData()) { std::string_view data = buf.ReadString(); - error->data = TranslateTTDPatchCodes(_cur_gps.grffile->grfid, lang, true, data); + error.data = TranslateTTDPatchCodes(_cur_gps.grffile->grfid, lang, true, data); } else { GrfMsg(7, "GRFLoadError: No message data supplied."); - error->data.clear(); + error.data.clear(); } /* Only two parameter numbers can be used in the string. */ - for (uint i = 0; i < error->param_value.size() && buf.HasData(); i++) { + for (uint i = 0; i < error.param_value.size() && buf.HasData(); i++) { uint param_number = buf.ReadByte(); - error->param_value[i] = _cur_gps.grffile->GetParam(param_number); + error.param_value[i] = _cur_gps.grffile->GetParam(param_number); } } diff --git a/src/newgrf/newgrf_actd.cpp b/src/newgrf/newgrf_actd.cpp index 8231c9a192d0c..b24d0cbc40c6f 100644 --- a/src/newgrf/newgrf_actd.cpp +++ b/src/newgrf/newgrf_actd.cpp @@ -424,16 +424,16 @@ static void ParamSet(ByteReader &buf) break; case 0x8F: { // Rail track type cost factors - extern RailTypeInfo _railtypes[RAILTYPE_END]; - _railtypes[RAILTYPE_RAIL].cost_multiplier = GB(res, 0, 8); + auto railtypes = GetRailTypeInfo(); + railtypes[RAILTYPE_RAIL].cost_multiplier = GB(res, 0, 8); if (_settings_game.vehicle.disable_elrails) { - _railtypes[RAILTYPE_ELECTRIC].cost_multiplier = GB(res, 0, 8); - _railtypes[RAILTYPE_MONO].cost_multiplier = GB(res, 8, 8); + railtypes[RAILTYPE_ELECTRIC].cost_multiplier = GB(res, 0, 8); + railtypes[RAILTYPE_MONO].cost_multiplier = GB(res, 8, 8); } else { - _railtypes[RAILTYPE_ELECTRIC].cost_multiplier = GB(res, 8, 8); - _railtypes[RAILTYPE_MONO].cost_multiplier = GB(res, 16, 8); + railtypes[RAILTYPE_ELECTRIC].cost_multiplier = GB(res, 8, 8); + railtypes[RAILTYPE_MONO].cost_multiplier = GB(res, 16, 8); } - _railtypes[RAILTYPE_MAGLEV].cost_multiplier = GB(res, 16, 8); + railtypes[RAILTYPE_MAGLEV].cost_multiplier = GB(res, 16, 8); break; } diff --git a/src/newgrf_badge.cpp b/src/newgrf_badge.cpp index 59a9a4a1caec6..ba9e803ac09ec 100644 --- a/src/newgrf_badge.cpp +++ b/src/newgrf_badge.cpp @@ -130,9 +130,9 @@ Badge *GetBadgeByLabel(std::string_view label) } /** - * Get the badge class of a badge label. - * @param label Label to get class of. - * @returns Badge class index of label. + * Get the badge for a badge class index. + * @param class_index Index of the badge class. + * @return Class badge for the class index, or nullptr if not present. */ Badge *GetClassBadge(BadgeClassID class_index) { diff --git a/src/newgrf_badge_config.h b/src/newgrf_badge_config.h index 1da4fa75b3483..3a4069022c9ad 100644 --- a/src/newgrf_badge_config.h +++ b/src/newgrf_badge_config.h @@ -16,8 +16,8 @@ class BadgeClassConfigItem { public: std::string label; ///< Class label. - int column = -1; ///< UI column, feature-dependent. - bool show_icon = false; ///< Set if the badge icons should be displayed for this class. + uint column = 0; ///< UI column, feature-dependent. + bool show_icon = true; ///< Set if the badge icons should be displayed for this class. bool show_filter = false; ///< Set if a drop down filter should be added for this class. }; diff --git a/src/newgrf_badge_gui.cpp b/src/newgrf_badge_gui.cpp index 0c6b1f82de162..93e133cf99214 100644 --- a/src/newgrf_badge_gui.cpp +++ b/src/newgrf_badge_gui.cpp @@ -81,7 +81,7 @@ GUIBadgeClasses::GUIBadgeClasses(GrfSpecFeature feature) : UsedBadgeClasses(feat const auto [config, sort_order] = GetBadgeClassConfigItem(feature, class_badge->label); this->gui_classes.emplace_back(class_index, config.column, config.show_icon, sort_order, size, class_badge->label); - if (size.width != 0 && config.show_icon) max_column = std::max(max_column, config.column); + if (size.width != 0 && config.show_icon) max_column = std::max(max_column, config.column); } std::sort(std::begin(this->gui_classes), std::end(this->gui_classes)); @@ -193,9 +193,12 @@ class DropDownBadges : public TBase { { for (const auto &gc : gui_classes->GetClasses()) { if (gc.column_group != 0) continue; - dim.width += gc.size.width + WidgetDimensions::scaled.hsep_normal; - dim.height = std::max(dim.height, gc.size.height); + dim.width += ScaleGUITrad(gc.size.width) + WidgetDimensions::scaled.hsep_normal; + dim.height = std::max(dim.height, ScaleGUITrad(gc.size.height)); } + + /* Remove trailing `hsep_normal` spacer. */ + if (dim.width > 0) dim.width -= WidgetDimensions::scaled.hsep_normal; } uint Height() const override @@ -206,7 +209,7 @@ class DropDownBadges : public TBase { uint Width() const override { if (this->dim.width == 0) return this->TBase::Width(); - return this->dim.width + WidgetDimensions::scaled.hsep_wide + this->TBase::Width(); + return this->dim.width + WidgetDimensions::scaled.hsep_normal + this->TBase::Width(); } int OnClick(const Rect &r, const Point &pt) const override @@ -215,7 +218,7 @@ class DropDownBadges : public TBase { return this->TBase::OnClick(r, pt); } else { bool rtl = TEnd ^ (_current_text_dir == TD_RTL); - return this->TBase::OnClick(r.Indent(this->dim.width + WidgetDimensions::scaled.hsep_wide, rtl), pt); + return this->TBase::OnClick(r.Indent(this->dim.width + WidgetDimensions::scaled.hsep_normal, rtl), pt); } } @@ -226,7 +229,7 @@ class DropDownBadges : public TBase { } else { bool rtl = TEnd ^ (_current_text_dir == TD_RTL); DrawBadgeColumn(r.WithWidth(this->dim.width, rtl), 0, *this->gui_classes, this->badges, this->feature, this->introduction_date, PAL_NONE); - this->TBase::Draw(full, r.Indent(this->dim.width + WidgetDimensions::scaled.hsep_wide, rtl), sel, click_result, bg_colour); + this->TBase::Draw(full, r.Indent(this->dim.width + WidgetDimensions::scaled.hsep_normal, rtl), sel, click_result, bg_colour); } } @@ -240,17 +243,22 @@ class DropDownBadges : public TBase { Dimension dim{}; }; -using DropDownListBadgeItem = DropDownBadges; -using DropDownListBadgeIconItem = DropDownBadges; +using DropDownListBadgeItem = DropDownBadges, FS_SMALL, true>>; +using DropDownListBadgeIconItem = DropDownBadges, FS_SMALL, true>>; std::unique_ptr MakeDropDownListBadgeItem(const std::shared_ptr &gui_classes, std::span badges, GrfSpecFeature feature, std::optional introduction_date, std::string &&str, int value, bool masked, bool shaded) { - return std::make_unique(gui_classes, badges, feature, introduction_date, std::move(str), value, masked, shaded); + return std::make_unique(gui_classes, badges, feature, introduction_date, "", std::move(str), value, masked, shaded); +} + +std::unique_ptr MakeDropDownListBadgeItem(const std::shared_ptr &gui_classes, std::span badges, GrfSpecFeature feature, std::optional introduction_date, Money cost, std::string &&str, int value, bool masked, bool shaded) +{ + return std::make_unique(gui_classes, badges, feature, introduction_date, GetString(STR_JUST_CURRENCY_SHORT, cost), std::move(str), value, masked, shaded); } -std::unique_ptr MakeDropDownListBadgeIconItem(const std::shared_ptr &gui_classes, std::span badges, GrfSpecFeature feature, std::optional introduction_date, const Dimension &dim, SpriteID sprite, PaletteID palette, std::string &&str, int value, bool masked, bool shaded) +std::unique_ptr MakeDropDownListBadgeIconItem(const std::shared_ptr &gui_classes, std::span badges, GrfSpecFeature feature, std::optional introduction_date, Money cost, const Dimension &dim, SpriteID sprite, PaletteID palette, std::string &&str, int value, bool masked, bool shaded) { - return std::make_unique(gui_classes, badges, feature, introduction_date, dim, sprite, palette, std::move(str), value, masked, shaded); + return std::make_unique(gui_classes, badges, feature, introduction_date, GetString(STR_JUST_CURRENCY_SHORT, cost), dim, sprite, palette, std::move(str), value, masked, shaded); } /** @@ -280,7 +288,7 @@ class DropDownMover : public TBase { bool rtl = (_current_text_dir == TD_RTL); int w = SETTING_BUTTON_WIDTH; - Rect br = r.WithWidth(w, TEnd ^ rtl).CentreTo(w, SETTING_BUTTON_HEIGHT); + Rect br = r.WithWidth(w, TEnd ^ rtl).CentreToHeight(SETTING_BUTTON_HEIGHT); if (br.WithWidth(w / 2, rtl).Contains(pt)) return this->click_up; if (br.WithWidth(w / 2, !rtl).Contains(pt)) return this->click_down; @@ -298,7 +306,7 @@ class DropDownMover : public TBase { if (click_result == this->click_down) state = 2; } - Rect br = r.WithWidth(w, TEnd ^ rtl).CentreTo(w, SETTING_BUTTON_HEIGHT); + Rect br = r.WithWidth(w, TEnd ^ rtl).CentreToHeight(SETTING_BUTTON_HEIGHT); DrawUpDownButtons(br.left, br.top, this->button_colour, state, this->click_up != 0, this->click_down != 0); this->TBase::Draw(full, r.Indent(w + WidgetDimensions::scaled.hsep_wide, TEnd ^ rtl), sel, click_result, bg_colour); @@ -431,7 +439,7 @@ static void BadgeClassMoveNext(GrfSpecFeature feature, Badge &class_badge, uint auto pos_cur = std::ranges::find(gui_classes.GetClasses(), class_badge.class_index, &GUIBadgeClasses::Element::class_index); if (std::next(pos_cur) == std::end(gui_classes.GetClasses())) { - if (it->column < static_cast(columns - 1)) ++it->column; + if (it->column < columns - 1) ++it->column; return; } @@ -500,9 +508,10 @@ std::string NWidgetBadgeFilter::GetStringParameter(const BadgeFilterChoices &cho /** * Get the drop down list of badges for this filter. + * @param palette Palette used to remap badge sprites. * @return Drop down list for filter. */ -DropDownList NWidgetBadgeFilter::GetDropDownList() const +DropDownList NWidgetBadgeFilter::GetDropDownList(PaletteID palette) const { DropDownList list; @@ -525,7 +534,7 @@ DropDownList NWidgetBadgeFilter::GetDropDownList() const if (badge.name == STR_NULL) continue; if (!badge.features.Test(this->feature)) continue; - PalSpriteID ps = GetBadgeSprite(badge, this->feature, std::nullopt, PAL_NONE); + PalSpriteID ps = GetBadgeSprite(badge, this->feature, std::nullopt, palette); if (ps.sprite == 0) { list.push_back(MakeDropDownListStringItem(badge.name, badge.index.base())); } else { diff --git a/src/newgrf_badge_gui.h b/src/newgrf_badge_gui.h index e73186d951d76..af2ed4cafcc97 100644 --- a/src/newgrf_badge_gui.h +++ b/src/newgrf_badge_gui.h @@ -5,7 +5,7 @@ * 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 newgrf_badge.h Functions related to NewGRF badges. */ +/** @file newgrf_badge_gui.h GUI functions related to NewGRF badges. */ #ifndef NEWGRF_BADGE_GUI_H #define NEWGRF_BADGE_GUI_H @@ -51,7 +51,8 @@ int DrawBadgeNameList(Rect r, std::span badges, GrfSpecFeature fe void DrawBadgeColumn(Rect r, int column_group, const GUIBadgeClasses &gui_classes, std::span badges, GrfSpecFeature feature, std::optional introduction_date, PaletteID remap); std::unique_ptr MakeDropDownListBadgeItem(const std::shared_ptr &gui_classes, std::span badges, GrfSpecFeature feature, std::optional introduction_date, std::string &&str, int value, bool masked = false, bool shaded = false); -std::unique_ptr MakeDropDownListBadgeIconItem(const std::shared_ptr &gui_classes, std::span badges, GrfSpecFeature feature, std::optional introduction_date, const Dimension &dim, SpriteID sprite, PaletteID palette, std::string &&str, int value, bool masked = false, bool shaded = false); +std::unique_ptr MakeDropDownListBadgeItem(const std::shared_ptr &gui_classes, std::span badges, GrfSpecFeature feature, std::optional introduction_date, Money cost, std::string &&str, int value, bool masked = false, bool shaded = false); +std::unique_ptr MakeDropDownListBadgeIconItem(const std::shared_ptr &gui_classes, std::span badges, GrfSpecFeature feature, std::optional introduction_date, Money cost, const Dimension &dim, SpriteID sprite, PaletteID palette, std::string &&str, int value, bool masked = false, bool shaded = false); DropDownList BuildBadgeClassConfigurationList(const class GUIBadgeClasses &badge_class, uint columns, std::span column_separators); bool HandleBadgeConfigurationDropDownClick(GrfSpecFeature feature, uint columns, int result, int click_result, BadgeFilterChoices &choices); @@ -64,7 +65,7 @@ class NWidgetBadgeFilter : public NWidgetLeaf { BadgeClassID GetBadgeClassID() const { return this->badge_class; } std::string GetStringParameter(const BadgeFilterChoices &choices) const; - DropDownList GetDropDownList() const; + DropDownList GetDropDownList(PaletteID palette = PAL_NONE) const; private: GrfSpecFeature feature; ///< Feature of this dropdown. diff --git a/src/newgrf_canal.cpp b/src/newgrf_canal.cpp index 4cb05922dd1c3..0e593ba74922a 100644 --- a/src/newgrf_canal.cpp +++ b/src/newgrf_canal.cpp @@ -13,7 +13,6 @@ #include "newgrf_canal.h" #include "water.h" #include "water_map.h" -#include "spritecache.h" #include "safeguards.h" diff --git a/src/newgrf_commons.h b/src/newgrf_commons.h index fb44120a60951..472f3a44b4639 100644 --- a/src/newgrf_commons.h +++ b/src/newgrf_commons.h @@ -473,7 +473,8 @@ struct SubstituteGRFFileProps : StandardGRFFileProps { /** Container for a label for rail or road type conversion. */ template struct LabelObject { - T label = {}; ///< Label of rail or road type. + T label{}; ///< Label of rail or road type. + uint8_t index = 0; ///< Local index of rail or road type. uint8_t subtype = 0; ///< Subtype of type (road or tram). }; diff --git a/src/newgrf_config.cpp b/src/newgrf_config.cpp index eb4862c7a0028..422fd57f4c667 100644 --- a/src/newgrf_config.cpp +++ b/src/newgrf_config.cpp @@ -40,7 +40,7 @@ GRFConfig::GRFConfig(const GRFConfig &config) : name(config.name), info(config.info), url(config.url), - error(config.error), + errors(config.errors), version(config.version), min_loadable_version(config.min_loadable_version), flags(config.flags), @@ -156,15 +156,6 @@ GRFConfigList _grfconfig_newgame; GRFConfigList _grfconfig_static; uint _missing_extra_graphics = 0; -/** - * Construct a new GRFError. - * @param severity The severity of this error. - * @param message The actual error-string. - */ -GRFError::GRFError(StringID severity, StringID message) : message(message), severity(severity) -{ -} - /** * Get the value of the given user-changeable parameter. * @param info The grf parameter info to get the value for. @@ -472,7 +463,7 @@ GRFListCompatibility IsGoodGRFConfigList(GRFConfigList &grfconfig) c->ident.md5sum = f->ident.md5sum; c->name = f->name; c->info = f->name; - c->error.reset(); + c->errors.clear(); c->version = f->version; c->min_loadable_version = f->min_loadable_version; c->num_valid_params = f->num_valid_params; diff --git a/src/newgrf_config.h b/src/newgrf_config.h index 337058f6b619d..8b03088f96f63 100644 --- a/src/newgrf_config.h +++ b/src/newgrf_config.h @@ -107,12 +107,14 @@ struct GRFIdentifier { /** Information about why GRF had problems during initialisation */ struct GRFError { - GRFError(StringID severity, StringID message = {}); + GRFError(StringID severity, uint32_t nfo_line, StringID message = {}) + : message(message), severity(severity), nfo_line(nfo_line) {} std::string custom_message{}; ///< Custom message (if present) std::string data{}; ///< Additional data for message and custom_message StringID message{}; ///< Default message StringID severity{}; ///< Info / Warning / Error / Fatal + uint32_t nfo_line; ///< Line within NewGRF of error. std::array param_value{}; ///< Values of GRF parameters to show for message and custom_message }; @@ -169,7 +171,7 @@ struct GRFConfig { GRFTextWrapper name{}; ///< NOSAVE: GRF name (Action 0x08) GRFTextWrapper info{}; ///< NOSAVE: GRF info (author, copyright, ...) (Action 0x08) GRFTextWrapper url{}; ///< NOSAVE: URL belonging to this GRF. - std::optional error = std::nullopt; ///< NOSAVE: Error/Warning during GRF loading (Action 0x0B) + std::vector errors; ///< NOSAVE: Error/Warning during GRF loading (Action 0x0B) uint32_t version = 0; ///< NOSAVE: Version a NewGRF can set so only the newest NewGRF is shown uint32_t min_loadable_version = 0; ///< NOSAVE: Minimum compatible version a NewGRF can define diff --git a/src/newgrf_debug_gui.cpp b/src/newgrf_debug_gui.cpp index f3780370bf05a..e9ba84f5c910d 100644 --- a/src/newgrf_debug_gui.cpp +++ b/src/newgrf_debug_gui.cpp @@ -624,7 +624,7 @@ struct NewGRFInspectWindow : Window { /* static */ uint32_t NewGRFInspectWindow::var60params[GSF_FAKE_END][0x20] = { {0} }; // Use spec to have 0s in whole array -static constexpr NWidgetPart _nested_newgrf_inspect_chain_widgets[] = { +static constexpr std::initializer_list _nested_newgrf_inspect_chain_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), NWidget(WWT_CAPTION, COLOUR_GREY, WID_NGRFI_CAPTION), SetStringTip(STR_NEWGRF_INSPECT_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), @@ -648,7 +648,7 @@ static constexpr NWidgetPart _nested_newgrf_inspect_chain_widgets[] = { EndContainer(), }; -static constexpr NWidgetPart _nested_newgrf_inspect_widgets[] = { +static constexpr std::initializer_list _nested_newgrf_inspect_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), NWidget(WWT_CAPTION, COLOUR_GREY, WID_NGRFI_CAPTION), SetStringTip(STR_NEWGRF_INSPECT_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), @@ -1119,7 +1119,7 @@ struct SpriteAlignerWindow : Window { bool SpriteAlignerWindow::centre = true; bool SpriteAlignerWindow::crosshair = true; -static constexpr NWidgetPart _nested_sprite_aligner_widgets[] = { +static constexpr std::initializer_list _nested_sprite_aligner_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), NWidget(WWT_CAPTION, COLOUR_GREY, WID_SA_CAPTION), diff --git a/src/newgrf_engine.cpp b/src/newgrf_engine.cpp index 5d1f7ba7fe8e6..f7de1b47e6c48 100644 --- a/src/newgrf_engine.cpp +++ b/src/newgrf_engine.cpp @@ -915,7 +915,7 @@ static uint32_t VehicleGetVariable(Vehicle *v, const VehicleScopeResolver *objec Train *t = Train::From(v); switch (variable - 0x80) { case 0x62: return t->track; - case 0x66: return t->railtypes.GetNthSetBit(0).value_or(RailType::INVALID_RAILTYPE); + case 0x66: return t->railtypes.empty() ? RailType::INVALID_RAILTYPE : *t->railtypes.begin(); case 0x73: return 0x80 + VEHICLE_LENGTH - t->gcache.cached_veh_length; case 0x74: return t->gcache.cached_power; case 0x75: return GB(t->gcache.cached_power, 8, 24); @@ -1138,7 +1138,7 @@ static void GetRotorOverrideSprite(EngineID engine, const struct Aircraft *v, En /* Only valid for helicopters */ assert(e->type == VEH_AIRCRAFT); - assert(!(e->u.air.subtype & AIR_CTOL)); + assert(!(e->VehInfo().subtype & AIR_CTOL)); /* We differ from TTDPatch by resolving the sprite using the primary vehicle 'v', and not using the rotor vehicle 'v->Next()->Next()'. * TTDPatch copies some variables between the vehicles each time, to somehow synchronize the rotor vehicle with the primary vehicle. diff --git a/src/newgrf_gui.cpp b/src/newgrf_gui.cpp index f33c298519340..60d7b70f08161 100644 --- a/src/newgrf_gui.cpp +++ b/src/newgrf_gui.cpp @@ -51,17 +51,20 @@ void ShowNewGRFError() for (const auto &c : _grfconfig) { /* Only show Fatal and Error level messages */ - if (!c->error.has_value() || (c->error->severity != STR_NEWGRF_ERROR_MSG_FATAL && c->error->severity != STR_NEWGRF_ERROR_MSG_ERROR)) continue; + if (c->errors.empty()) continue; + + const GRFError &error = c->errors.back(); + if (error.severity != STR_NEWGRF_ERROR_MSG_FATAL && error.severity != STR_NEWGRF_ERROR_MSG_ERROR) continue; std::vector params; params.emplace_back(c->GetName()); - params.emplace_back(c->error->message != STR_NULL ? c->error->message : STR_JUST_RAW_STRING); - params.emplace_back(c->error->custom_message); + params.emplace_back(error.message != STR_NULL ? error.message : STR_JUST_RAW_STRING); + params.emplace_back(error.custom_message); params.emplace_back(c->filename); - params.emplace_back(c->error->data); - for (const uint32_t &value : c->error->param_value) params.emplace_back(value); + params.emplace_back(error.data); + for (const uint32_t &value : error.param_value) params.emplace_back(value); - if (c->error->severity == STR_NEWGRF_ERROR_MSG_FATAL) { + if (error.severity == STR_NEWGRF_ERROR_MSG_FATAL) { ShowErrorMessage(GetEncodedStringWithArgs(STR_NEWGRF_ERROR_FATAL_POPUP, params), {}, WL_CRITICAL); } else { ShowErrorMessage(GetEncodedStringWithArgs(STR_NEWGRF_ERROR_POPUP, params), {}, WL_ERROR); @@ -81,15 +84,15 @@ static StringID GetGRFPaletteString(uint8_t palette) static void ShowNewGRFInfo(const GRFConfig &c, const Rect &r, bool show_params) { Rect tr = r.Shrink(WidgetDimensions::scaled.frametext); - if (c.error.has_value()) { - std::arrayparam_value)>> params{}; + for (const GRFError &error : c.errors) { + std::array> params{}; auto it = params.begin(); - *it++ = c.error->custom_message; // is skipped by built-in messages + *it++ = error.custom_message; // is skipped by built-in messages *it++ = c.filename; - *it++ = c.error->data; - for (const uint32_t &value : c.error->param_value) *it++ = value; + *it++ = error.data; + for (const uint32_t &value : error.param_value) *it++ = value; - tr.top = DrawStringMultiLine(tr, GetString(c.error->severity, GetStringWithArgs(c.error->message != STR_NULL ? c.error->message : STR_JUST_RAW_STRING, {params.begin(), it}))); + tr.top = DrawStringMultiLine(tr, GetString(error.severity, GetStringWithArgs(error.message != STR_NULL ? error.message : STR_JUST_RAW_STRING, {params.begin(), it}))); } /* Draw filename or not if it is not known (GRF sent over internet) */ @@ -497,7 +500,7 @@ struct NewGRFParametersWindow : public Window { GRFParameterInfo NewGRFParametersWindow::dummy_parameter_info(0); -static constexpr NWidgetPart _nested_newgrf_parameter_widgets[] = { +static constexpr std::initializer_list _nested_newgrf_parameter_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_MAUVE), NWidget(WWT_CAPTION, COLOUR_MAUVE, WID_NP_CAPTION), @@ -868,8 +871,8 @@ struct NewGRFWindow : public Window, NewGRFScanCallback { } } DrawSprite(SPR_SQUARE, pal, square_left, tr.top + square_offset_y); - if (c->error.has_value()) DrawSprite(SPR_WARNING_SIGN, 0, warning_left, tr.top + warning_offset_y); - uint txtoffset = !c->error.has_value() ? 0 : warning.width; + if (!c->errors.empty()) DrawSprite(SPR_WARNING_SIGN, 0, warning_left, tr.top + warning_offset_y); + uint txtoffset = c->errors.empty() ? 0 : warning.width; DrawString(text_left + (rtl ? 0 : txtoffset), text_right - (rtl ? txtoffset : 0), tr.top + offset_y, std::move(text), h ? TC_WHITE : TC_ORANGE); tr.top += step_height; } @@ -1740,7 +1743,7 @@ class NWidgetNewGRFDisplay : public NWidgetBase { const uint NWidgetNewGRFDisplay::MAX_EXTRA_INFO_WIDTH = 150; const uint NWidgetNewGRFDisplay::MIN_EXTRA_FOR_3_COLUMNS = 50; -static constexpr NWidgetPart _nested_newgrf_actives_widgets[] = { +static constexpr std::initializer_list _nested_newgrf_actives_widgets = { NWidget(NWID_VERTICAL), SetPIP(0, WidgetDimensions::unscaled.vsep_wide, 0), /* Left side, presets. */ NWidget(NWID_VERTICAL), @@ -1795,7 +1798,7 @@ static constexpr NWidgetPart _nested_newgrf_actives_widgets[] = { EndContainer(), }; -static constexpr NWidgetPart _nested_newgrf_availables_widgets[] = { +static constexpr std::initializer_list _nested_newgrf_availables_widgets = { NWidget(WWT_FRAME, COLOUR_MAUVE), SetStringTip(STR_NEWGRF_SETTINGS_INACTIVE_LIST), SetPIP(0, WidgetDimensions::unscaled.vsep_wide, 0), /* Left side, available grfs, filter edit box. */ NWidget(NWID_HORIZONTAL), SetPIP(0, WidgetDimensions::unscaled.hsep_wide, 0), @@ -1828,7 +1831,7 @@ static constexpr NWidgetPart _nested_newgrf_availables_widgets[] = { EndContainer(), }; -static constexpr NWidgetPart _nested_newgrf_infopanel_widgets[] = { +static constexpr std::initializer_list _nested_newgrf_infopanel_widgets = { NWidget(NWID_VERTICAL), SetPIP(0, WidgetDimensions::unscaled.vsep_wide, 0), /* Right side, info panel. */ NWidget(WWT_PANEL, COLOUR_MAUVE), @@ -1883,7 +1886,7 @@ std::unique_ptr NewGRFDisplay() } /* Widget definition of the manage newgrfs window */ -static constexpr NWidgetPart _nested_newgrf_widgets[] = { +static constexpr std::initializer_list _nested_newgrf_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_MAUVE), NWidget(WWT_CAPTION, COLOUR_MAUVE), SetStringTip(STR_NEWGRF_SETTINGS_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), @@ -1967,7 +1970,7 @@ void ShowNewGRFSettings(bool editable, bool show_params, bool exec_changes, GRFC } /** Widget parts of the save preset window. */ -static constexpr NWidgetPart _nested_save_preset_widgets[] = { +static constexpr std::initializer_list _nested_save_preset_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), NWidget(WWT_CAPTION, COLOUR_GREY), SetStringTip(STR_SAVE_PRESET_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), @@ -2120,7 +2123,7 @@ static void ShowSavePresetWindow(std::string_view initial_text) } /** Widgets for the progress window. */ -static constexpr NWidgetPart _nested_scan_progress_widgets[] = { +static constexpr std::initializer_list _nested_scan_progress_widgets = { NWidget(WWT_CAPTION, COLOUR_GREY), SetStringTip(STR_NEWGRF_SCAN_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), NWidget(WWT_PANEL, COLOUR_GREY), NWidget(NWID_VERTICAL), SetPIP(0, WidgetDimensions::unscaled.vsep_wide, 0), SetPadding(WidgetDimensions::unscaled.modalpopup), diff --git a/src/newgrf_industries.cpp b/src/newgrf_industries.cpp index 4f532ff1b2ab1..5a1fb6b80fc38 100644 --- a/src/newgrf_industries.cpp +++ b/src/newgrf_industries.cpp @@ -246,10 +246,8 @@ static uint32_t GetCountAndDistanceOfClosestInstance(const ResolverObject &objec const Company *c = Company::GetIfValid(this->industry->founder); if (c != nullptr) { - const Livery *l = &c->livery[LS_DEFAULT]; - is_ai = c->is_ai; - colours = l->colour1 + l->colour2 * 16; + colours = c->GetCompanyRecolourOffset(LS_DEFAULT); } return this->industry->founder.base() | (is_ai ? 0x10000 : 0) | (colours << 24); diff --git a/src/newgrf_railtype.cpp b/src/newgrf_railtype.cpp index 0d215971b85f1..73048fd6ddfb3 100644 --- a/src/newgrf_railtype.cpp +++ b/src/newgrf_railtype.cpp @@ -9,6 +9,7 @@ #include "stdafx.h" #include "core/container_func.hpp" +#include "core/flatset_type.hpp" #include "debug.h" #include "newgrf_railtype.h" #include "newgrf_roadtype.h" @@ -16,6 +17,7 @@ #include "depot_base.h" #include "town.h" #include "tunnelbridge_map.h" +#include "company_base.h" #include "safeguards.h" @@ -35,7 +37,7 @@ case 0x43: return TimerGameCalendar::date.base(); case 0x44: return to_underlying(HouseZone::TownEdge); case 0x45: { - auto rt = GetRailTypeInfoIndex(this->rti); + RailType rt = this->rti->Index(); uint8_t local = GetReverseRailTypeTranslation(rt, this->ro.grffile); if (local == 0xFF) local = 0xFE; return 0xFFFF | local << 16; @@ -152,7 +154,7 @@ RailType GetRailTypeTranslation(uint8_t railtype, const GRFFile *grffile) { if (grffile == nullptr || grffile->railtype_list.empty()) { /* No railtype table present. Return railtype as-is (if valid), so it works for original railtypes. */ - if (railtype >= RAILTYPE_END || GetRailTypeInfo(static_cast(railtype))->label == 0) return INVALID_RAILTYPE; + if (railtype >= GetNumRailTypes() || GetRailTypeInfo(static_cast(railtype))->label == 0) return INVALID_RAILTYPE; return static_cast(railtype); } else { @@ -187,13 +189,25 @@ uint8_t GetReverseRailTypeTranslation(RailType railtype, const GRFFile *grffile) std::vector> _railtype_list; +void PreloadRailTypeMaps() +{ + _railtype_mapping.Init(); + for (const auto &lo : _railtype_list) { + if (lo.label == 0) continue; + RailType rt = GetRailTypeByLabel(lo.label); + if (rt == INVALID_RAILTYPE) continue; + + _railtype_mapping.Set(static_cast(lo.index), rt); + } +} + /** * Test if any saved rail type labels are different to the currently loaded * rail types. Rail types stored in the map will be converted if necessary. */ void ConvertRailTypes() { - std::vector railtype_conversion_map; + std::vector railtype_conversion_map; bool needs_conversion = false; for (auto it = std::begin(_railtype_list); it != std::end(_railtype_list); ++it) { @@ -202,10 +216,13 @@ void ConvertRailTypes() rt = RAILTYPE_RAIL; } - railtype_conversion_map.push_back(rt); + railtype_conversion_map.push_back(_railtype_mapping.AllocateMapType(rt, true)); + + if (it->label == 0) continue; + if (needs_conversion) continue; /* Conversion is needed if the rail type is in a different position than the list. */ - if (it->label != 0 && rt != std::distance(std::begin(_railtype_list), it)) needs_conversion = true; + if (_railtype_mapping.GetMappedType(rt).base() != it->index) needs_conversion = true; } if (!needs_conversion) return; @@ -213,24 +230,24 @@ void ConvertRailTypes() for (const auto t : Map::Iterate()) { switch (GetTileType(t)) { case MP_RAILWAY: - SetRailType(t, railtype_conversion_map[GetRailType(t)]); + SetMapRailType(t, railtype_conversion_map[GetRailType(t)]); break; case MP_ROAD: if (IsLevelCrossing(t)) { - SetRailType(t, railtype_conversion_map[GetRailType(t)]); + SetMapRailType(t, railtype_conversion_map[GetRailType(t)]); } break; case MP_STATION: if (HasStationRail(t)) { - SetRailType(t, railtype_conversion_map[GetRailType(t)]); + SetMapRailType(t, railtype_conversion_map[GetRailType(t)]); } break; case MP_TUNNELBRIDGE: if (GetTunnelBridgeTransportType(t) == TRANSPORT_RAIL) { - SetRailType(t, railtype_conversion_map[GetRailType(t)]); + SetMapRailType(t, railtype_conversion_map[GetRailType(t)]); } break; @@ -244,9 +261,10 @@ void ConvertRailTypes() void SetCurrentRailTypeLabelList() { _railtype_list.clear(); - - for (RailType rt = RAILTYPE_BEGIN; rt != RAILTYPE_END; rt++) { - _railtype_list.emplace_back(GetRailTypeInfo(rt)->label, 0); + for (RailType rt = RAILTYPE_BEGIN; rt != GetNumRailTypes(); rt++) { + if (MapRailType map_railtype = _railtype_mapping.GetMappedType(rt); map_railtype != RailTypeMapping::INVALID_MAP_TYPE) { + _railtype_list.emplace_back(GetRailTypeInfo(rt)->label, map_railtype.base(), 0); + } } } diff --git a/src/newgrf_railtype.h b/src/newgrf_railtype.h index e0d36349ca732..62b9173b7f366 100644 --- a/src/newgrf_railtype.h +++ b/src/newgrf_railtype.h @@ -62,5 +62,6 @@ uint8_t GetReverseRailTypeTranslation(RailType railtype, const GRFFile *grffile) void ConvertRailTypes(); void SetCurrentRailTypeLabelList(); void ClearRailTypeLabelList(); +void PreloadRailTypeMaps(); #endif /* NEWGRF_RAILTYPE_H */ diff --git a/src/newgrf_roadstop.cpp b/src/newgrf_roadstop.cpp index da022d14f336b..f093c0b2b495c 100644 --- a/src/newgrf_roadstop.cpp +++ b/src/newgrf_roadstop.cpp @@ -561,20 +561,22 @@ const RoadStopSpec *GetRoadStopSpec(TileIndex t) /** * Allocate a RoadStopSpec to a Station. This is called once per build operation. - * @param statspec RoadStopSpec to allocate. + * @param spec RoadStopSpec to allocate. * @param st Station to allocate it to. - * @param exec Whether to actually allocate the spec. * @return Index within the Station's road stop spec list, or std::nullopt if the allocation failed. */ -std::optional AllocateSpecToRoadStop(const RoadStopSpec *statspec, BaseStation *st, bool exec) +std::optional AllocateSpecToRoadStop(const RoadStopSpec *spec, BaseStation *st) { uint i; - if (statspec == nullptr || st == nullptr) return 0; + if (spec == nullptr) return 0; + + /* If station doesn't exist yet then the first slot is available. */ + if (st == nullptr) return 1; /* Try to find the same spec and return that one */ for (i = 1; i < st->roadstop_speclist.size() && i < NUM_ROADSTOPSPECS_PER_STATION; i++) { - if (st->roadstop_speclist[i].spec == statspec) return i; + if (st->roadstop_speclist[i].spec == spec) return i; } /* Try to find an unused spec slot */ @@ -587,16 +589,25 @@ std::optional AllocateSpecToRoadStop(const RoadStopSpec *statspec, Base return std::nullopt; } - if (exec) { - if (i >= st->roadstop_speclist.size()) st->roadstop_speclist.resize(i + 1); - st->roadstop_speclist[i].spec = statspec; - st->roadstop_speclist[i].grfid = statspec->grf_prop.grfid; - st->roadstop_speclist[i].localidx = statspec->grf_prop.local_id; + return i; +} - RoadStopUpdateCachedTriggers(st); - } +/** + * Assign a previously allocated RoadStopSpec specindex to a Station. + * @param spec RoadStopSpec to assign.. + * @param st Station to allocate it to. + * @param specindex Spec index of allocation. + */ +void AssignSpecToRoadStop(const RoadStopSpec *spec, BaseStation *st, uint8_t specindex) +{ + if (specindex == 0) return; + if (specindex >= st->roadstop_speclist.size()) st->roadstop_speclist.resize(specindex + 1); - return i; + st->roadstop_speclist[specindex].spec = spec; + st->roadstop_speclist[specindex].grfid = spec->grf_prop.grfid; + st->roadstop_speclist[specindex].localidx = spec->grf_prop.local_id; + + RoadStopUpdateCachedTriggers(st); } /** diff --git a/src/newgrf_roadstop.h b/src/newgrf_roadstop.h index 3f826aac43867..73fa2e9db673c 100644 --- a/src/newgrf_roadstop.h +++ b/src/newgrf_roadstop.h @@ -177,7 +177,8 @@ bool GetIfClassHasNewStopsByType(const RoadStopClass *roadstopclass, RoadStopTyp bool GetIfStopIsForType(const RoadStopSpec *roadstopspec, RoadStopType rs, RoadType roadtype); const RoadStopSpec *GetRoadStopSpec(TileIndex t); -std::optional AllocateSpecToRoadStop(const RoadStopSpec *statspec, BaseStation *st, bool exec); +std::optional AllocateSpecToRoadStop(const RoadStopSpec *spec, BaseStation *st); +void AssignSpecToRoadStop(const RoadStopSpec *spec, BaseStation *st, uint8_t specindex); void DeallocateSpecFromRoadStop(BaseStation *st, uint8_t specindex); void RoadStopUpdateCachedTriggers(BaseStation *st); diff --git a/src/newgrf_roadtype.cpp b/src/newgrf_roadtype.cpp index e48a67b11a177..0395d2a862121 100644 --- a/src/newgrf_roadtype.cpp +++ b/src/newgrf_roadtype.cpp @@ -69,7 +69,7 @@ uint32_t GetTrackTypes(TileIndex tile, const GRFFile *grffile) case 0x43: return TimerGameCalendar::date.base(); case 0x44: return to_underlying(HouseZone::TownEdge); case 0x45: { - auto rt = GetRoadTypeInfoIndex(this->rti); + RoadType rt = this->rti->Index(); uint8_t local = GetReverseRoadTypeTranslation(rt, this->ro.grffile); if (local == 0xFF) local = 0xFE; if (RoadTypeIsRoad(rt)) { @@ -218,13 +218,31 @@ uint8_t GetReverseRoadTypeTranslation(RoadType roadtype, const GRFFile *grffile) std::vector> _roadtype_list; +void PreloadRoadTypeMaps() +{ + _roadtype_mapping.Init(); + _tramtype_mapping.Init(); + for (const auto &lo : _roadtype_list) { + if (lo.label == 0) continue; + RoadType rt = GetRoadTypeByLabel(lo.label); + if (rt == INVALID_ROADTYPE) continue; + + RoadTramType rtt = GetRoadTramType(rt); + if (static_cast(lo.subtype) != rtt) continue; + + if (rtt == RTT_ROAD) _roadtype_mapping.Set(static_cast(lo.index), rt); + if (rtt == RTT_TRAM) _tramtype_mapping.Set(static_cast(lo.index), rt); + } +} + /** * Test if any saved road type labels are different to the currently loaded * road types. Road types stored in the map will be converted if necessary. */ void ConvertRoadTypes() { - std::vector roadtype_conversion_map; + std::vector roadtype_conversion_map; + std::vector tramtype_conversion_map; bool needs_conversion = false; for (auto it = std::begin(_roadtype_list); it != std::end(_roadtype_list); ++it) { RoadType rt = GetRoadTypeByLabel(it->label); @@ -232,31 +250,46 @@ void ConvertRoadTypes() rt = it->subtype ? ROADTYPE_TRAM : ROADTYPE_ROAD; } - roadtype_conversion_map.push_back(rt); + if (it->subtype == 0) { + roadtype_conversion_map.push_back(_roadtype_mapping.AllocateMapType(rt, true)); + + if (it->label == 0) continue; + if (needs_conversion) continue; + + /* Conversion is needed if the road type is in a different position than the list. */ + if (_roadtype_mapping.GetMappedType(rt).base() != it->index) needs_conversion = true; + } + + if (it->subtype == 1) { + tramtype_conversion_map.push_back(_tramtype_mapping.AllocateMapType(rt, true)); + + if (it->label == 0) continue; + if (needs_conversion) continue; - /* Conversion is needed if the road type is in a different position than the list. */ - if (it->label != 0 && rt != std::distance(std::begin(_roadtype_list), it)) needs_conversion = true; + /* Conversion is needed if the road type is in a different position than the list. */ + if (_tramtype_mapping.GetMappedType(rt).base() != it->index) needs_conversion = true; + } } if (!needs_conversion) return; for (TileIndex t : Map::Iterate()) { switch (GetTileType(t)) { case MP_ROAD: - if (RoadType rt = GetRoadTypeRoad(t); rt != INVALID_ROADTYPE) SetRoadTypeRoad(t, roadtype_conversion_map[rt]); - if (RoadType rt = GetRoadTypeTram(t); rt != INVALID_ROADTYPE) SetRoadTypeTram(t, roadtype_conversion_map[rt]); + if (RoadType rt = GetRoadTypeRoad(t); rt != INVALID_ROADTYPE) SetMapRoadTypeRoad(t, roadtype_conversion_map[rt]); + if (RoadType rt = GetRoadTypeTram(t); rt != INVALID_ROADTYPE) SetMapRoadTypeTram(t, tramtype_conversion_map[rt]); break; case MP_STATION: if (IsAnyRoadStop(t)) { - if (RoadType rt = GetRoadTypeRoad(t); rt != INVALID_ROADTYPE) SetRoadTypeRoad(t, roadtype_conversion_map[rt]); - if (RoadType rt = GetRoadTypeTram(t); rt != INVALID_ROADTYPE) SetRoadTypeTram(t, roadtype_conversion_map[rt]); + if (RoadType rt = GetRoadTypeRoad(t); rt != INVALID_ROADTYPE) SetMapRoadTypeRoad(t, roadtype_conversion_map[rt]); + if (RoadType rt = GetRoadTypeTram(t); rt != INVALID_ROADTYPE) SetMapRoadTypeTram(t, tramtype_conversion_map[rt]); } break; case MP_TUNNELBRIDGE: if (GetTunnelBridgeTransportType(t) == TRANSPORT_ROAD) { - if (RoadType rt = GetRoadTypeRoad(t); rt != INVALID_ROADTYPE) SetRoadTypeRoad(t, roadtype_conversion_map[rt]); - if (RoadType rt = GetRoadTypeTram(t); rt != INVALID_ROADTYPE) SetRoadTypeTram(t, roadtype_conversion_map[rt]); + if (RoadType rt = GetRoadTypeRoad(t); rt != INVALID_ROADTYPE) SetMapRoadTypeRoad(t, roadtype_conversion_map[rt]); + if (RoadType rt = GetRoadTypeTram(t); rt != INVALID_ROADTYPE) SetMapRoadTypeTram(t, tramtype_conversion_map[rt]); } break; @@ -270,8 +303,13 @@ void ConvertRoadTypes() void SetCurrentRoadTypeLabelList() { _roadtype_list.clear(); - for (RoadType rt = ROADTYPE_BEGIN; rt != ROADTYPE_END; rt++) { - _roadtype_list.emplace_back(GetRoadTypeInfo(rt)->label, GetRoadTramType(rt)); + for (RoadType rt = ROADTYPE_BEGIN; rt != GetNumRoadTypes(); rt++) { + if (MapRoadType map_roadtype = _roadtype_mapping.GetMappedType(rt); map_roadtype != RoadTypeMapping::INVALID_MAP_TYPE) { + _roadtype_list.emplace_back(GetRoadTypeInfo(rt)->label, map_roadtype.base(), GetRoadTramType(rt)); + } + if (MapTramType map_tramtype = _tramtype_mapping.GetMappedType(rt); map_tramtype != TramTypeMapping::INVALID_MAP_TYPE) { + _roadtype_list.emplace_back(GetRoadTypeInfo(rt)->label, map_tramtype.base(), GetRoadTramType(rt)); + } } } diff --git a/src/newgrf_roadtype.h b/src/newgrf_roadtype.h index e0fc039856af6..82ab8b8b9aa63 100644 --- a/src/newgrf_roadtype.h +++ b/src/newgrf_roadtype.h @@ -64,5 +64,6 @@ uint32_t GetTrackTypes(TileIndex tile, const GRFFile *grffile); void ConvertRoadTypes(); void SetCurrentRoadTypeLabelList(); void ClearRoadTypeLabelList(); +void PreloadRoadTypeMaps(); #endif /* NEWGRF_ROADTYPE_H */ diff --git a/src/newgrf_station.cpp b/src/newgrf_station.cpp index d307e6dd9da5d..358f6505d54ac 100644 --- a/src/newgrf_station.cpp +++ b/src/newgrf_station.cpp @@ -692,16 +692,18 @@ CommandCost PerformStationTileSlopeCheck(TileIndex north_tile, TileIndex cur_til /** * Allocate a StationSpec to a Station. This is called once per build operation. - * @param statspec StationSpec to allocate. + * @param spec StationSpec to allocate. * @param st Station to allocate it to. - * @param exec Whether to actually allocate the spec. * @return Index within the Station's station spec list, or std::nullopt if the allocation failed. */ -std::optional AllocateSpecToStation(const StationSpec *statspec, BaseStation *st, bool exec) +std::optional AllocateSpecToStation(const StationSpec *spec, BaseStation *st) { uint i; - if (statspec == nullptr || st == nullptr) return 0; + if (spec == nullptr) return 0; + + /* If station doesn't exist yet then the first slot is available. */ + if (st == nullptr) return 1; for (i = 1; i < st->speclist.size() && i < NUM_STATIONSSPECS_PER_STATION; i++) { if (st->speclist[i].spec == nullptr && st->speclist[i].grfid == 0) break; @@ -714,24 +716,32 @@ std::optional AllocateSpecToStation(const StationSpec *statspec, BaseSt * but it's fairly unlikely that one reaches the limit anyways. */ for (i = 1; i < st->speclist.size() && i < NUM_STATIONSSPECS_PER_STATION; i++) { - if (st->speclist[i].spec == statspec) return i; + if (st->speclist[i].spec == spec) return i; } return std::nullopt; } - if (exec) { - if (i >= st->speclist.size()) st->speclist.resize(i + 1); - st->speclist[i].spec = statspec; - st->speclist[i].grfid = statspec->grf_prop.grfid; - st->speclist[i].localidx = statspec->grf_prop.local_id; - - StationUpdateCachedTriggers(st); - } - return i; } +/** + * Assign a previously allocated StationSpec specindex to a Station. + * @param spec StationSpec to assign.. + * @param st Station to allocate it to. + * @param specindex Spec index of allocation. + */ +void AssignSpecToStation(const StationSpec *spec, BaseStation *st, uint8_t specindex) +{ + if (specindex == 0) return; + if (specindex >= st->speclist.size()) st->speclist.resize(specindex + 1); + + st->speclist[specindex].spec = spec; + st->speclist[specindex].grfid = spec->grf_prop.grfid; + st->speclist[specindex].localidx = spec->grf_prop.local_id; + + StationUpdateCachedTriggers(st); +} /** * Deallocate a StationSpec from a Station. Called when removing a single station tile. diff --git a/src/newgrf_station.h b/src/newgrf_station.h index 2537209fd8744..990f0bc4a94f8 100644 --- a/src/newgrf_station.h +++ b/src/newgrf_station.h @@ -215,7 +215,8 @@ SpriteID GetCustomStationFoundationRelocation(const StationSpec *statspec, BaseS uint16_t GetStationCallback(CallbackID callback, uint32_t param1, uint32_t param2, const StationSpec *statspec, BaseStation *st, TileIndex tile, std::span regs100 = {}); CommandCost PerformStationTileSlopeCheck(TileIndex north_tile, TileIndex cur_tile, const StationSpec *statspec, Axis axis, uint8_t plat_len, uint8_t numtracks); -std::optional AllocateSpecToStation(const StationSpec *statspec, BaseStation *st, bool exec); +std::optional AllocateSpecToStation(const StationSpec *spec, BaseStation *st); +void AssignSpecToStation(const StationSpec *spec, BaseStation *st, uint8_t specindex); void DeallocateSpecFromStation(BaseStation *st, uint8_t specindex); bool DrawStationTile(int x, int y, RailType railtype, Axis axis, StationClassID sclass, uint station); diff --git a/src/newgrf_town.cpp b/src/newgrf_town.cpp index eb581d93280fa..370769cde668f 100644 --- a/src/newgrf_town.cpp +++ b/src/newgrf_town.cpp @@ -63,7 +63,7 @@ static uint16_t TownHistoryHelper(const Town *t, CargoLabel label, uint period, case 0x82: return ClampTo(this->t->cache.population); case 0x83: return GB(ClampTo(this->t->cache.population), 8, 8); case 0x8A: return this->t->grow_counter / Ticks::TOWN_GROWTH_TICKS; - case 0x92: return this->t->flags; // In original game, 0x92 and 0x93 are really one word. Since flags is a byte, this is to adjust + case 0x92: return this->t->flags.base(); // In original game, 0x92 and 0x93 are one word. case 0x93: return 0; case 0x94: return ClampTo(this->t->cache.squared_town_zone_radius[to_underlying(HouseZone::TownEdge)]); case 0x95: return GB(ClampTo(this->t->cache.squared_town_zone_radius[to_underlying(HouseZone::TownEdge)]), 8, 8); diff --git a/src/news_cmd.h b/src/news_cmd.h index df9523c253784..c84c29e141b37 100644 --- a/src/news_cmd.h +++ b/src/news_cmd.h @@ -16,6 +16,6 @@ CommandCost CmdCustomNewsItem(DoCommandFlags flags, NewsType type, CompanyID company, NewsReference reference, const EncodedString &text); -DEF_CMD_TRAIT(CMD_CUSTOM_NEWS_ITEM, CmdCustomNewsItem, CommandFlags({CommandFlag::StrCtrl, CommandFlag::Deity}), CMDT_OTHER_MANAGEMENT) +DEF_CMD_TRAIT(CMD_CUSTOM_NEWS_ITEM, CmdCustomNewsItem, CommandFlags({CommandFlag::StrCtrl, CommandFlag::Deity}), CommandType::OtherManagement) #endif /* NEWS_CMD_H */ diff --git a/src/news_gui.cpp b/src/news_gui.cpp index 351f5595619da..1e45fbd2b4371 100644 --- a/src/news_gui.cpp +++ b/src/news_gui.cpp @@ -102,7 +102,7 @@ static TileIndex GetReferenceTile(const NewsReference &reference) } /* Normal news items. */ -static constexpr NWidgetPart _nested_normal_news_widgets[] = { +static constexpr std::initializer_list _nested_normal_news_widgets = { NWidget(WWT_PANEL, COLOUR_WHITE, WID_N_PANEL), NWidget(NWID_VERTICAL), SetPadding(WidgetDimensions::unscaled.fullbevel), NWidget(NWID_LAYER, INVALID_COLOUR), @@ -134,7 +134,7 @@ static WindowDesc _normal_news_desc( ); /* New vehicles news items. */ -static constexpr NWidgetPart _nested_vehicle_news_widgets[] = { +static constexpr std::initializer_list _nested_vehicle_news_widgets = { NWidget(WWT_PANEL, COLOUR_WHITE, WID_N_PANEL), NWidget(NWID_VERTICAL), SetPadding(WidgetDimensions::unscaled.fullbevel), NWidget(NWID_LAYER, INVALID_COLOUR), @@ -182,7 +182,7 @@ static WindowDesc _vehicle_news_desc( ); /* Company news items. */ -static constexpr NWidgetPart _nested_company_news_widgets[] = { +static constexpr std::initializer_list _nested_company_news_widgets = { NWidget(WWT_PANEL, COLOUR_WHITE, WID_N_PANEL), NWidget(NWID_VERTICAL), SetPadding(WidgetDimensions::unscaled.fullbevel), NWidget(NWID_LAYER, INVALID_COLOUR), @@ -227,7 +227,7 @@ static WindowDesc _company_news_desc( ); /* Thin news items. */ -static constexpr NWidgetPart _nested_thin_news_widgets[] = { +static constexpr std::initializer_list _nested_thin_news_widgets = { NWidget(WWT_PANEL, COLOUR_WHITE, WID_N_PANEL), NWidget(NWID_VERTICAL), SetPadding(WidgetDimensions::unscaled.fullbevel), NWidget(NWID_LAYER, INVALID_COLOUR), @@ -261,7 +261,7 @@ static WindowDesc _thin_news_desc( ); /* Small news items. */ -static constexpr NWidgetPart _nested_small_news_widgets[] = { +static constexpr std::initializer_list _nested_small_news_widgets = { /* Caption + close box. The caption is not WWT_CAPTION as the window shall not be moveable and so on. */ NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_LIGHT_BLUE, WID_N_CLOSEBOX), @@ -1275,7 +1275,7 @@ struct MessageHistoryWindow : Window { } }; -static constexpr NWidgetPart _nested_message_history[] = { +static constexpr std::initializer_list _nested_message_history = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_BROWN), NWidget(WWT_CAPTION, COLOUR_BROWN), SetStringTip(STR_MESSAGE_HISTORY, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), diff --git a/src/object_cmd.cpp b/src/object_cmd.cpp index b17b30c9c3060..2bb29628f99cf 100644 --- a/src/object_cmd.cpp +++ b/src/object_cmd.cpp @@ -97,8 +97,7 @@ void BuildObject(ObjectType type, TileIndex tile, CompanyID owner, Town *town, u if (owner == OWNER_NONE) { o->colour = Random(); } else { - const Livery &l = Company::Get(owner)->livery[0]; - o->colour = l.colour1 + l.colour2 * 16; + o->colour = Company::Get(owner)->GetCompanyRecolourOffset(LS_DEFAULT); } /* If the object wants only one colour, then give it that colour. */ @@ -193,8 +192,7 @@ void UpdateObjectColours(const Company *c) /* Using the object colour callback, so not using company colour. */ if (spec->callback_mask.Test(ObjectCallbackMask::Colour)) continue; - const Livery &l = c->livery[0]; - obj->colour = (spec->flags.Test(ObjectFlag::Uses2CC) ? (l.colour2 * 16) : 0) + l.colour1; + obj->colour = c->GetCompanyRecolourOffset(LS_DEFAULT, spec->flags.Test(ObjectFlag::Uses2CC)); } } @@ -253,6 +251,11 @@ CommandCost CmdBuildObject(DoCommandFlags flags, TileIndex tile, ObjectType type Owner o = GetTileOwner(t); if (o != OWNER_NONE && o != OWNER_WATER) cost.AddCost(CheckOwnership(o, t)); + /* If freeform edges are disabled, don't allow building on edge tiles. */ + if (!_settings_game.construction.freeform_edges && (!IsInsideMM(TileX(t), 1, Map::MaxX() - 1) || !IsInsideMM(TileY(t), 1, Map::MaxY() - 1))) { + return CommandCost(STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP); + } + /* However, the tile has to be clear of vehicles. */ cost.AddCost(EnsureNoVehicleOnGround(t)); } @@ -298,10 +301,10 @@ CommandCost CmdBuildObject(DoCommandFlags flags, TileIndex tile, ObjectType type for (TileIndex t : ta) { if (HasTileWaterGround(t)) { if (!IsWaterTile(t)) { - Command::Do(DoCommandFlags{flags}.Reset(DoCommandFlag::NoWater).Set(DoCommandFlag::NoModifyTownRating), t); + Command::Do(DoCommandFlags{flags}.Reset(DoCommandFlag::NoWater), t); } } else { - Command::Do(flags | DoCommandFlag::NoModifyTownRating, t); + Command::Do(flags, t); } } } diff --git a/src/object_cmd.h b/src/object_cmd.h index 0fb18d7fa8bbe..048b3c6dfdf17 100644 --- a/src/object_cmd.h +++ b/src/object_cmd.h @@ -16,7 +16,7 @@ CommandCost CmdBuildObject(DoCommandFlags flags, TileIndex tile, ObjectType type, uint8_t view); CommandCost CmdBuildObjectArea(DoCommandFlags flags, TileIndex tile, TileIndex start_tile, ObjectType type, uint8_t view, bool diagonal); -DEF_CMD_TRAIT(CMD_BUILD_OBJECT, CmdBuildObject, CommandFlags({CommandFlag::Deity, CommandFlag::NoWater, CommandFlag::Auto}), CMDT_LANDSCAPE_CONSTRUCTION) -DEF_CMD_TRAIT(CMD_BUILD_OBJECT_AREA, CmdBuildObjectArea, CommandFlags({CommandFlag::Deity, CommandFlag::NoWater, CommandFlag::NoTest, CommandFlag::Auto}), CMDT_LANDSCAPE_CONSTRUCTION) +DEF_CMD_TRAIT(CMD_BUILD_OBJECT, CmdBuildObject, CommandFlags({CommandFlag::Deity, CommandFlag::NoWater, CommandFlag::Auto}), CommandType::LandscapeConstruction) +DEF_CMD_TRAIT(CMD_BUILD_OBJECT_AREA, CmdBuildObjectArea, CommandFlags({CommandFlag::Deity, CommandFlag::NoWater, CommandFlag::NoTest, CommandFlag::Auto}), CommandType::LandscapeConstruction) #endif /* OBJECT_CMD_H */ diff --git a/src/object_gui.cpp b/src/object_gui.cpp index 6f1207e585154..76ba2f1199395 100644 --- a/src/object_gui.cpp +++ b/src/object_gui.cpp @@ -385,7 +385,7 @@ class BuildObjectWindow : public PickerWindow { }, BuildObjectGlobalHotkeys}; }; -static constexpr NWidgetPart _nested_build_object_widgets[] = { +static constexpr std::initializer_list _nested_build_object_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN), NWidget(WWT_CAPTION, COLOUR_DARK_GREEN), SetStringTip(STR_OBJECT_BUILD_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), diff --git a/src/object_map.h b/src/object_map.h index a5280c4f8c7ec..d997b673c0fe7 100644 --- a/src/object_map.h +++ b/src/object_map.h @@ -80,8 +80,9 @@ inline void MakeObject(Tile t, Owner o, ObjectID index, WaterClass wc, uint8_t r t.m3() = random; t.m4() = 0; t.m5() = index.base() >> 16; - SB(t.m6(), 2, 4, 0); + SB(t.m6(), 2, 6, 0); t.m7() = 0; + t.m8() = 0; } #endif /* OBJECT_MAP_H */ diff --git a/src/openttd.cpp b/src/openttd.cpp index a26aa68a978d1..4317b99e648ae 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -88,13 +88,13 @@ #include "table/strings.h" -#include "safeguards.h" - #ifdef __EMSCRIPTEN__ # include # include #endif +#include "safeguards.h" + void CallLandscapeTick(); void DoPaletteAnimations(); void MusicLoop(); diff --git a/src/order_base.h b/src/order_base.h index 1b0f6b175255c..5dac764838126 100644 --- a/src/order_base.h +++ b/src/order_base.h @@ -367,7 +367,7 @@ struct OrderList : OrderListPool::PoolItem<&_orderlist_pool> { */ inline VehicleOrderID GetNumManualOrders() const { return this->num_manual_orders; } - StationIDStack GetNextStoppingStation(const Vehicle *v, VehicleOrderID first = INVALID_VEH_ORDER_ID, uint hops = 0) const; + void GetNextStoppingStation(std::vector &next_station, const Vehicle *v, VehicleOrderID first = INVALID_VEH_ORDER_ID, uint hops = 0) const; VehicleOrderID GetNextDecisionNode(VehicleOrderID next, uint hops) const; void InsertOrderAt(Order &&order, VehicleOrderID index); diff --git a/src/order_cmd.cpp b/src/order_cmd.cpp index 9f968a461f54b..8754c96874b5b 100644 --- a/src/order_cmd.cpp +++ b/src/order_cmd.cpp @@ -361,14 +361,14 @@ VehicleOrderID OrderList::GetNextDecisionNode(VehicleOrderID next, uint hops) co * @pre The vehicle is currently loading and v->last_station_visited is meaningful. * @note This function may draw a random number. Don't use it from the GUI. */ -StationIDStack OrderList::GetNextStoppingStation(const Vehicle *v, VehicleOrderID first, uint hops) const +void OrderList::GetNextStoppingStation(std::vector &next_station, const Vehicle *v, VehicleOrderID first, uint hops) const { VehicleOrderID next = first; if (first == INVALID_VEH_ORDER_ID) { next = v->cur_implicit_order_index; if (next >= this->GetNumOrders()) { next = this->GetFirstOrder(); - if (next == INVALID_VEH_ORDER_ID) return StationID::Invalid(); + if (next == INVALID_VEH_ORDER_ID) return; } else { /* GetNext never returns INVALID_VEH_ORDER_ID if there is a valid station in the list. * As the given "next" is already valid and a station in the list, we @@ -392,10 +392,9 @@ StationIDStack OrderList::GetNextStoppingStation(const Vehicle *v, VehicleOrderI } else if (skip_to == INVALID_VEH_ORDER_ID || skip_to == first) { next = (advance == first) ? INVALID_VEH_ORDER_ID : advance; } else { - StationIDStack st1 = this->GetNextStoppingStation(v, skip_to, hops); - StationIDStack st2 = this->GetNextStoppingStation(v, advance, hops); - while (!st2.IsEmpty()) st1.Push(st2.Pop()); - return st1; + this->GetNextStoppingStation(next_station, v, skip_to, hops); + this->GetNextStoppingStation(next_station, v, advance, hops); + return; } ++hops; } @@ -404,11 +403,11 @@ StationIDStack OrderList::GetNextStoppingStation(const Vehicle *v, VehicleOrderI if (next == INVALID_VEH_ORDER_ID || ((orders[next].IsType(OT_GOTO_STATION) || orders[next].IsType(OT_IMPLICIT)) && orders[next].GetDestination() == v->last_station_visited && (orders[next].GetUnloadType() & (OUFB_TRANSFER | OUFB_UNLOAD)) != 0)) { - return StationID::Invalid(); + return; } } while (orders[next].IsType(OT_GOTO_DEPOT) || orders[next].GetDestination() == v->last_station_visited); - return orders[next].GetDestination().ToStationID(); + next_station.push_back(orders[next].GetDestination().ToStationID()); } /** diff --git a/src/order_cmd.h b/src/order_cmd.h index 5d1e9039d45f9..405a0e8c95f81 100644 --- a/src/order_cmd.h +++ b/src/order_cmd.h @@ -23,14 +23,14 @@ CommandCost CmdCloneOrder(DoCommandFlags flags, CloneOptions action, VehicleID v CommandCost CmdMoveOrder(DoCommandFlags flags, VehicleID veh, VehicleOrderID moving_order, VehicleOrderID target_order); CommandCost CmdClearOrderBackup(DoCommandFlags flags, TileIndex tile, ClientID user_id); -DEF_CMD_TRAIT(CMD_MODIFY_ORDER, CmdModifyOrder, CommandFlag::Location, CMDT_ROUTE_MANAGEMENT) -DEF_CMD_TRAIT(CMD_SKIP_TO_ORDER, CmdSkipToOrder, CommandFlag::Location, CMDT_ROUTE_MANAGEMENT) -DEF_CMD_TRAIT(CMD_DELETE_ORDER, CmdDeleteOrder, CommandFlag::Location, CMDT_ROUTE_MANAGEMENT) -DEF_CMD_TRAIT(CMD_INSERT_ORDER, CmdInsertOrder, CommandFlag::Location, CMDT_ROUTE_MANAGEMENT) -DEF_CMD_TRAIT(CMD_ORDER_REFIT, CmdOrderRefit, CommandFlag::Location, CMDT_ROUTE_MANAGEMENT) -DEF_CMD_TRAIT(CMD_CLONE_ORDER, CmdCloneOrder, CommandFlag::Location, CMDT_ROUTE_MANAGEMENT) -DEF_CMD_TRAIT(CMD_MOVE_ORDER, CmdMoveOrder, CommandFlag::Location, CMDT_ROUTE_MANAGEMENT) -DEF_CMD_TRAIT(CMD_CLEAR_ORDER_BACKUP, CmdClearOrderBackup, CommandFlag::ClientID, CMDT_SERVER_SETTING) +DEF_CMD_TRAIT(CMD_MODIFY_ORDER, CmdModifyOrder, CommandFlag::Location, CommandType::RouteManagement) +DEF_CMD_TRAIT(CMD_SKIP_TO_ORDER, CmdSkipToOrder, CommandFlag::Location, CommandType::RouteManagement) +DEF_CMD_TRAIT(CMD_DELETE_ORDER, CmdDeleteOrder, CommandFlag::Location, CommandType::RouteManagement) +DEF_CMD_TRAIT(CMD_INSERT_ORDER, CmdInsertOrder, CommandFlag::Location, CommandType::RouteManagement) +DEF_CMD_TRAIT(CMD_ORDER_REFIT, CmdOrderRefit, CommandFlag::Location, CommandType::RouteManagement) +DEF_CMD_TRAIT(CMD_CLONE_ORDER, CmdCloneOrder, CommandFlag::Location, CommandType::RouteManagement) +DEF_CMD_TRAIT(CMD_MOVE_ORDER, CmdMoveOrder, CommandFlag::Location, CommandType::RouteManagement) +DEF_CMD_TRAIT(CMD_CLEAR_ORDER_BACKUP, CmdClearOrderBackup, CommandFlag::ClientID, CommandType::ServerSetting) template inline EndianBufferWriter &operator <<(EndianBufferWriter &buffer, const Order &order) diff --git a/src/order_gui.cpp b/src/order_gui.cpp index 8193b6b411e3d..d131681252774 100644 --- a/src/order_gui.cpp +++ b/src/order_gui.cpp @@ -1586,7 +1586,7 @@ struct OrdersWindow : public Window { }; /** Nested widget definition for "your" train orders. */ -static constexpr NWidgetPart _nested_orders_train_widgets[] = { +static constexpr std::initializer_list _nested_orders_train_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), NWidget(WWT_CAPTION, COLOUR_GREY, WID_O_CAPTION), @@ -1663,7 +1663,7 @@ static WindowDesc _orders_train_desc( ); /** Nested widget definition for "your" orders (non-train). */ -static constexpr NWidgetPart _nested_orders_widgets[] = { +static constexpr std::initializer_list _nested_orders_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), NWidget(WWT_CAPTION, COLOUR_GREY, WID_O_CAPTION), SetStringTip(STR_ORDERS_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), @@ -1736,7 +1736,7 @@ static WindowDesc _orders_desc( ); /** Nested widget definition for competitor orders. */ -static constexpr NWidgetPart _nested_other_orders_widgets[] = { +static constexpr std::initializer_list _nested_other_orders_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), NWidget(WWT_CAPTION, COLOUR_GREY, WID_O_CAPTION), SetStringTip(STR_ORDERS_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), diff --git a/src/os/macosx/font_osx.cpp b/src/os/macosx/font_osx.cpp index 20c24f078afce..e406a790b2082 100644 --- a/src/os/macosx/font_osx.cpp +++ b/src/os/macosx/font_osx.cpp @@ -211,7 +211,7 @@ class CoreTextFontCacheFactory : public FontCacheFactory { * fallback search, use it. Otherwise, try to resolve it by font name. * @param fs The font size to load. */ - std::unique_ptr LoadFont(FontSize fs, FontType fonttype) override + std::unique_ptr LoadFont(FontSize fs, FontType fonttype) const override { if (fonttype != FontType::TrueType) return nullptr; @@ -259,7 +259,7 @@ class CoreTextFontCacheFactory : public FontCacheFactory { return std::make_unique(fs, std::move(font_ref), GetFontCacheFontSize(fs)); } - bool FindFallbackFont(FontCacheSettings *settings, const std::string &language_isocode, MissingGlyphSearcher *callback) override + bool FindFallbackFont(FontCacheSettings *settings, const std::string &language_isocode, MissingGlyphSearcher *callback) const override { /* Determine fallback font using CoreText. This uses the language isocode * to find a suitable font. CoreText is available from 10.5 onwards. */ diff --git a/src/os/unix/font_unix.cpp b/src/os/unix/font_unix.cpp index dd8f2f1d2a3ef..978695a853141 100644 --- a/src/os/unix/font_unix.cpp +++ b/src/os/unix/font_unix.cpp @@ -123,6 +123,22 @@ FT_Error GetFontByFaceName(std::string_view font_name, FT_Face *face) return err; } +/** + * Get distance between font weight and preferred font weights. + * @param weight Font weight from FontConfig. + * @return Distance from preferred weight, where lower values are preferred. + */ +static int GetPreferredWeightDistance(int weight) +{ + /* Prefer a font between normal and medium weight. */ + static constexpr int PREFERRED_WEIGHT_MIN = FC_WEIGHT_NORMAL; + static constexpr int PREFERRED_WEIGHT_MAX = FC_WEIGHT_MEDIUM; + + if (weight < PREFERRED_WEIGHT_MIN) return std::abs(weight - PREFERRED_WEIGHT_MIN); + if (weight > PREFERRED_WEIGHT_MAX) return weight - PREFERRED_WEIGHT_MAX; + return 0; +} + bool FontConfigFindFallbackFont(FontCacheSettings *settings, const std::string &language_isocode, MissingGlyphSearcher *callback) { bool ret = false; @@ -164,9 +180,10 @@ bool FontConfigFindFallbackFont(FontCacheSettings *settings, const std::string & FcPatternGetInteger(font, FC_SLANT, 0, &value); if (value != 0) continue; - /* We want the fatter font as they look better at small sizes. */ + /* We want a font near to medium weight. */ FcPatternGetInteger(font, FC_WEIGHT, 0, &value); - if (value <= best_weight) continue; + int weight = GetPreferredWeightDistance(value); + if (best_weight != -1 && weight > best_weight) continue; /* Possible match based on attributes, get index. */ int32_t index; @@ -179,7 +196,7 @@ bool FontConfigFindFallbackFont(FontCacheSettings *settings, const std::string & Debug(fontcache, 1, "Font \"{}\" misses{} glyphs", FromFcString(file), missing ? "" : " no"); if (!missing) { - best_weight = value; + best_weight = weight; best_font = FromFcString(file); best_index = index; } diff --git a/src/os/unix/unix.cpp b/src/os/unix/unix.cpp index 36ee069637b2f..5bc89cceac227 100644 --- a/src/os/unix/unix.cpp +++ b/src/os/unix/unix.cpp @@ -14,7 +14,6 @@ #include "../../fios.h" #include "../../thread.h" - #include #include #include @@ -26,6 +25,10 @@ #include #endif +#ifdef WITH_ICONV +#include +#endif /* WITH_ICONV */ + #ifdef __EMSCRIPTEN__ # include #endif @@ -85,10 +88,6 @@ bool FiosIsHiddenFile(const std::filesystem::path &path) #ifdef WITH_ICONV -#include -#include "../../debug.h" -#include "../../string_func.h" - std::optional GetCurrentLocale(const char *param); #define INTERNALCODE "UTF-8" diff --git a/src/os/windows/font_win32.cpp b/src/os/windows/font_win32.cpp index 7413eb70cbe24..24100a1704b75 100644 --- a/src/os/windows/font_win32.cpp +++ b/src/os/windows/font_win32.cpp @@ -38,9 +38,8 @@ struct EFCParam { bool Add(const std::wstring_view &font) { - for (const auto &entry : this->fonts) { - if (font.compare(entry) == 0) return false; - } + auto it = std::ranges::find(this->fonts, font); + if (it != std::end(this->fonts)) return false; this->fonts.emplace_back(font); @@ -276,7 +275,7 @@ class Win32FontCacheFactory : FontCacheFactory { * fallback search, use it. Otherwise, try to resolve it by font name. * @param fs The font size to load. */ - std::unique_ptr LoadFont(FontSize fs, FontType fonttype) override + std::unique_ptr LoadFont(FontSize fs, FontType fonttype) const override { if (fonttype != FontType::TrueType) return nullptr; @@ -308,7 +307,7 @@ class Win32FontCacheFactory : FontCacheFactory { return LoadWin32Font(fs, logfont, GetFontCacheFontSize(fs), font); } - bool FindFallbackFont(FontCacheSettings *settings, const std::string &language_isocode, MissingGlyphSearcher *callback) override + bool FindFallbackFont(FontCacheSettings *settings, const std::string &language_isocode, MissingGlyphSearcher *callback) const override { Debug(fontcache, 1, "Trying fallback fonts"); EFCParam langInfo; diff --git a/src/osk_gui.cpp b/src/osk_gui.cpp index 0e67c0a09e505..cddf84e884b94 100644 --- a/src/osk_gui.cpp +++ b/src/osk_gui.cpp @@ -321,7 +321,7 @@ static std::unique_ptr MakeSpacebarKeys() } -static constexpr NWidgetPart _nested_osk_widgets[] = { +static constexpr std::initializer_list _nested_osk_widgets = { NWidget(WWT_CAPTION, COLOUR_GREY, WID_OSK_CAPTION), SetTextStyle(TC_WHITE), NWidget(WWT_PANEL, COLOUR_GREY), NWidget(WWT_EDITBOX, COLOUR_GREY, WID_OSK_TEXT), SetMinimalSize(252, 0), SetPadding(2, 2, 2, 2), diff --git a/src/pathfinder/yapf/yapf_base.hpp b/src/pathfinder/yapf/yapf_base.hpp index f8888e1364ce1..6555b6539e169 100644 --- a/src/pathfinder/yapf/yapf_base.hpp +++ b/src/pathfinder/yapf/yapf_base.hpp @@ -35,7 +35,6 @@ * Requirements to your pathfinder class derived from CYapfBaseT: * -------------------------------------------------------------- * Your pathfinder derived class needs to implement following methods: - * inline void PfSetStartupNodes() * inline void PfFollowNode(Node &org) * inline bool PfCalcCost(Node &n) * inline bool PfCalcEstimate(Node &n) @@ -104,8 +103,6 @@ class CYapfBaseT { { this->vehicle = v; - Yapf().PfSetStartupNodes(); - for (;;) { this->num_steps++; Node *best_open_node = this->nodes.GetBestOpenNode(); @@ -162,14 +159,13 @@ class CYapfBaseT { /** Add new node (created by CreateNewNode and filled with data) into open list */ inline void AddStartupNode(Node &n) { + assert(n.parent == nullptr); + assert(this->num_steps == 0); + Yapf().PfNodeCacheFetch(n); /* insert the new node only if it is not there */ if (this->nodes.FindOpenNode(n.key) == nullptr) { this->nodes.InsertOpenNode(n); - } else { - /* if we are here, it means that node is already there - how it is possible? - * probably the train is in the position that both its ends point to the same tile/exit-dir - * very unlikely, but it happened */ } } @@ -185,30 +181,14 @@ class CYapfBaseT { } } - /** - * In some cases an intermediate node branch should be pruned. - * The most prominent case is when a red EOL signal is encountered, but - * there was a segment change (e.g. a rail type change) before that. If - * the branch would not be pruned, the rail type change location would - * remain the best intermediate node, and thus the vehicle would still - * go towards the red EOL signal. - */ - void PruneIntermediateNodeBranch(Node *n) - { - bool intermediate_on_branch = false; - while (n != nullptr && !n->segment->end_segment_reason.Test(EndSegmentReason::ChoiceFollows)) { - if (n == Yapf().best_intermediate_node) intermediate_on_branch = true; - n = n->parent; - } - if (intermediate_on_branch) Yapf().best_intermediate_node = n; - } - /** * AddNewNode() - called by Tderived::PfFollowNode() for each child node. * Nodes are evaluated here and added into open list */ - void AddNewNode(Node &n, const TrackFollower &tf) + void AddNewNode(Node &n, const TrackFollower &follower) { + assert(n.parent != nullptr); + /* evaluate the node */ bool cached = Yapf().PfNodeCacheFetch(n); if (!cached) { @@ -217,7 +197,7 @@ class CYapfBaseT { this->stats_cache_hits++; } - bool valid = Yapf().PfCalcCost(n, &tf); + bool valid = Yapf().PfCalcCost(n, &follower); if (valid) valid = Yapf().PfCalcEstimate(n); diff --git a/src/pathfinder/yapf/yapf_common.hpp b/src/pathfinder/yapf/yapf_common.hpp index 7f358dcd33ad6..538f3bd3bfb75 100644 --- a/src/pathfinder/yapf/yapf_common.hpp +++ b/src/pathfinder/yapf/yapf_common.hpp @@ -23,9 +23,6 @@ class CYapfOriginTileT { typedef typename Node::Key Key; ///< key to hash tables protected: - TileIndex origin_tile; ///< origin tile - TrackdirBits origin_trackdirs; ///< origin trackdir mask - /** to access inherited path finder */ inline Tpf &Yapf() { @@ -36,19 +33,12 @@ class CYapfOriginTileT { /** Set origin tile / trackdir mask */ void SetOrigin(TileIndex tile, TrackdirBits trackdirs) { - this->origin_tile = tile; - this->origin_trackdirs = trackdirs; - } - - /** Called when YAPF needs to place origin nodes into open list */ - void PfSetStartupNodes() - { - bool is_choice = (KillFirstBit(this->origin_trackdirs) != TRACKDIR_BIT_NONE); - for (TrackdirBits tdb = this->origin_trackdirs; tdb != TRACKDIR_BIT_NONE; tdb = KillFirstBit(tdb)) { + bool is_choice = (KillFirstBit(trackdirs) != TRACKDIR_BIT_NONE); + for (TrackdirBits tdb = trackdirs; tdb != TRACKDIR_BIT_NONE; tdb = KillFirstBit(tdb)) { Trackdir td = (Trackdir)FindFirstBit(tdb); - Node &n1 = Yapf().CreateNewNode(); - n1.Set(nullptr, this->origin_tile, td, is_choice); - Yapf().AddStartupNode(n1); + Node &node = Yapf().CreateNewNode(); + node.Set(nullptr, tile, td, is_choice); + Yapf().AddStartupNode(node); } } }; @@ -62,12 +52,6 @@ class CYapfOriginTileTwoWayT { typedef typename Node::Key Key; ///< key to hash tables protected: - TileIndex origin_tile; ///< first origin tile - Trackdir origin_td; ///< first origin trackdir - TileIndex reverse_tile; ///< second (reverse) origin tile - Trackdir reverse_td; ///< second (reverse) origin trackdir - int reverse_penalty; ///< penalty to be added for using the reverse origin - /** to access inherited path finder */ inline Tpf &Yapf() { @@ -76,28 +60,19 @@ class CYapfOriginTileTwoWayT { public: /** set origin (tiles, trackdirs, etc.) */ - void SetOrigin(TileIndex tile, Trackdir td, TileIndex tiler = INVALID_TILE, Trackdir tdr = INVALID_TRACKDIR, int reverse_penalty = 0) - { - this->origin_tile = tile; - this->origin_td = td; - this->reverse_tile = tiler; - this->reverse_td = tdr; - this->reverse_penalty = reverse_penalty; - } - - /** Called when YAPF needs to place origin nodes into open list */ - void PfSetStartupNodes() + void SetOrigin(TileIndex forward_tile, Trackdir forward_td, TileIndex reverse_tile = INVALID_TILE, + Trackdir reverse_td = INVALID_TRACKDIR, int reverse_penalty = 0) { - if (this->origin_tile != INVALID_TILE && this->origin_td != INVALID_TRACKDIR) { - Node &n1 = Yapf().CreateNewNode(); - n1.Set(nullptr, this->origin_tile, this->origin_td, false); - Yapf().AddStartupNode(n1); + if (forward_tile != INVALID_TILE && forward_td != INVALID_TRACKDIR) { + Node &node = Yapf().CreateNewNode(); + node.Set(nullptr, forward_tile, forward_td, false); + Yapf().AddStartupNode(node); } - if (this->reverse_tile != INVALID_TILE && this->reverse_td != INVALID_TRACKDIR) { - Node &n2 = Yapf().CreateNewNode(); - n2.Set(nullptr, this->reverse_tile, this->reverse_td, false); - n2.cost = this->reverse_penalty; - Yapf().AddStartupNode(n2); + if (reverse_tile != INVALID_TILE && reverse_td != INVALID_TRACKDIR) { + Node &node = Yapf().CreateNewNode(); + node.Set(nullptr, reverse_tile, reverse_td, false); + node.cost = reverse_penalty; + Yapf().AddStartupNode(node); } } }; diff --git a/src/pathfinder/yapf/yapf_costrail.hpp b/src/pathfinder/yapf/yapf_costrail.hpp index 1c2b1e61fb83d..2cda842dd3796 100644 --- a/src/pathfinder/yapf/yapf_costrail.hpp +++ b/src/pathfinder/yapf/yapf_costrail.hpp @@ -271,11 +271,11 @@ class CYapfCostRailT : public CYapfCostBase { * Calculates only the cost of given node, adds it to the parent node cost * and stores the result into Node::cost member */ - inline bool PfCalcCost(Node &n, const TrackFollower *tf) + inline bool PfCalcCost(Node &n, const TrackFollower *follower) { assert(!n.flags_u.flags_s.target_seen); - assert(tf->new_tile == n.key.tile); - assert((HasTrackdir(tf->new_td_bits, n.key.td))); + assert(follower->new_tile == n.key.tile); + assert((HasTrackdir(follower->new_td_bits, n.key.td))); /* Does the node have some parent node? */ bool has_parent = (n.parent != nullptr); @@ -326,7 +326,7 @@ class CYapfCostRailT : public CYapfCostBase { EndSegmentReasons end_segment_reason{}; - TrackFollower tf_local(v, Yapf().GetCompatibleRailTypes()); + TrackFollower follower_local{v, Yapf().GetCompatibleRailTypes()}; if (!has_parent) { /* We will jump to the middle of the cost calculator assuming that segment cache is not used. */ @@ -378,7 +378,7 @@ class CYapfCostRailT : public CYapfCostBase { segment_cost += Yapf().OneTileCost(cur.tile, cur.td); /* If we skipped some tunnel/bridge/station tiles, add their base cost */ - segment_cost += YAPF_TILE_LENGTH * tf->tiles_skipped; + segment_cost += YAPF_TILE_LENGTH * follower->tiles_skipped; /* Slope cost. */ segment_cost += Yapf().SlopeCost(cur.tile, cur.td); @@ -387,7 +387,7 @@ class CYapfCostRailT : public CYapfCostBase { segment_cost += Yapf().SignalCost(n, cur.tile, cur.td); /* Reserved tiles. */ - segment_cost += Yapf().ReservationCost(n, cur.tile, cur.td, tf->tiles_skipped); + segment_cost += Yapf().ReservationCost(n, cur.tile, cur.td, follower->tiles_skipped); end_segment_reason = segment.end_segment_reason; @@ -445,9 +445,9 @@ class CYapfCostRailT : public CYapfCostBase { /* Waypoint is also a good reason to finish. */ end_segment_reason.Set(EndSegmentReason::Waypoint); - } else if (tf->is_station) { + } else if (follower->is_station) { /* Station penalties. */ - uint platform_length = tf->tiles_skipped + 1; + uint platform_length = follower->tiles_skipped + 1; /* We don't know yet if the station is our target or not. Act like * if it is pass-through station (not our destination). */ segment_cost += Yapf().PfGetSettings().rail_station_penalty * platform_length; @@ -466,10 +466,10 @@ class CYapfCostRailT : public CYapfCostBase { if (n.num_signals_passed < this->sig_look_ahead_costs.size()) { int min_speed = 0; - int max_speed = tf->GetSpeedLimit(&min_speed); + int max_speed = follower->GetSpeedLimit(&min_speed); int max_veh_speed = std::min(v->GetDisplayMaxSpeed(), v->current_order.GetMaxSpeed()); if (max_speed < max_veh_speed) { - extra_cost += YAPF_TILE_LENGTH * (max_veh_speed - max_speed) * (4 + tf->tiles_skipped) / max_veh_speed; + extra_cost += YAPF_TILE_LENGTH * (max_veh_speed - max_speed) * (4 + follower->tiles_skipped) / max_veh_speed; } if (min_speed > max_veh_speed) { extra_cost += YAPF_TILE_LENGTH * (min_speed - max_veh_speed); @@ -483,13 +483,13 @@ class CYapfCostRailT : public CYapfCostBase { } /* Move to the next tile/trackdir. */ - tf = &tf_local; - tf_local.Init(v, Yapf().GetCompatibleRailTypes()); + follower = &follower_local; + follower_local.Init(v, Yapf().GetCompatibleRailTypes()); - if (!tf_local.Follow(cur.tile, cur.td)) { - assert(tf_local.err != TrackFollower::EC_NONE); + if (!follower_local.Follow(cur.tile, cur.td)) { + assert(follower_local.err != TrackFollower::EC_NONE); /* Can't move to the next tile (EOL?). */ - if (tf_local.err == TrackFollower::EC_RAIL_ROAD_TYPE) { + if (follower_local.err == TrackFollower::EC_RAIL_ROAD_TYPE) { end_segment_reason.Set(EndSegmentReason::RailType); } else { end_segment_reason.Set(EndSegmentReason::DeadEnd); @@ -502,14 +502,14 @@ class CYapfCostRailT : public CYapfCostBase { } /* Check if the next tile is not a choice. */ - if (KillFirstBit(tf_local.new_td_bits) != TRACKDIR_BIT_NONE) { + if (KillFirstBit(follower_local.new_td_bits) != TRACKDIR_BIT_NONE) { /* More than one segment will follow. Close this one. */ end_segment_reason.Set(EndSegmentReason::ChoiceFollows); break; } /* Gather the next tile/trackdir/tile_type/rail_type. */ - TILE next(tf_local.new_tile, (Trackdir)FindFirstBit(tf_local.new_td_bits)); + TILE next(follower_local.new_tile, (Trackdir)FindFirstBit(follower_local.new_td_bits)); if (TrackFollower::DoTrackMasking() && IsTileType(next.tile, MP_RAILWAY)) { if (HasSignalOnTrackdir(next.tile, next.td) && IsPbsSignal(GetSignalType(next.tile, TrackdirToTrack(next.td)))) { @@ -538,7 +538,7 @@ class CYapfCostRailT : public CYapfCostBase { if (segment_cost > MAX_SEGMENT_COST) { /* Potentially in the infinite loop (or only very long segment?). We should * not force it to finish prematurely unless we are on a regular tile. */ - if (IsTileType(tf->new_tile, MP_RAILWAY)) { + if (IsTileType(follower->new_tile, MP_RAILWAY)) { end_segment_reason.Set(EndSegmentReason::SegmentTooLong); break; } diff --git a/src/pathfinder/yapf/yapf_destrail.hpp b/src/pathfinder/yapf/yapf_destrail.hpp index 55a3f2bc62f0b..9677b7bec9001 100644 --- a/src/pathfinder/yapf/yapf_destrail.hpp +++ b/src/pathfinder/yapf/yapf_destrail.hpp @@ -30,7 +30,7 @@ class CYapfDestinationRailBase { return this->compatible_railtypes.Test(rt); } - RailTypes GetCompatibleRailTypes() const + const RailTypes &GetCompatibleRailTypes() const { return this->compatible_railtypes; } diff --git a/src/pathfinder/yapf/yapf_node_rail.hpp b/src/pathfinder/yapf/yapf_node_rail.hpp index 53483d30e34e3..cf493e1b95548 100644 --- a/src/pathfinder/yapf/yapf_node_rail.hpp +++ b/src/pathfinder/yapf/yapf_node_rail.hpp @@ -177,17 +177,17 @@ struct CYapfRailNode : CYapfNodeT { template bool IterateTiles(const Train *v, Tpf &yapf, Tbase &obj, bool (Tfunc::*func)(TileIndex, Trackdir)) const { - typename Tbase::TrackFollower ft(v, yapf.GetCompatibleRailTypes()); + typename Tbase::TrackFollower follower{v, yapf.GetCompatibleRailTypes()}; TileIndex cur = this->base::GetTile(); Trackdir cur_td = this->base::GetTrackdir(); while (cur != this->GetLastTile() || cur_td != this->GetLastTrackdir()) { if (!((obj.*func)(cur, cur_td))) return false; - if (!ft.Follow(cur, cur_td)) break; - cur = ft.new_tile; - assert(KillFirstBit(ft.new_td_bits) == TRACKDIR_BIT_NONE); - cur_td = FindFirstTrackdir(ft.new_td_bits); + if (!follower.Follow(cur, cur_td)) break; + cur = follower.new_tile; + assert(KillFirstBit(follower.new_td_bits) == TRACKDIR_BIT_NONE); + cur_td = FindFirstTrackdir(follower.new_td_bits); } return (obj.*func)(cur, cur_td); diff --git a/src/pathfinder/yapf/yapf_rail.cpp b/src/pathfinder/yapf/yapf_rail.cpp index 208b65b737188..57ca8098f4d40 100644 --- a/src/pathfinder/yapf/yapf_rail.cpp +++ b/src/pathfinder/yapf/yapf_rail.cpp @@ -229,9 +229,9 @@ class CYapfFollowAnyDepotRailT { */ inline void PfFollowNode(Node &old_node) { - TrackFollower F(Yapf().GetVehicle()); - if (F.Follow(old_node.GetLastTile(), old_node.GetLastTrackdir())) { - Yapf().AddMultipleNodes(&old_node, F); + TrackFollower follower{Yapf().GetVehicle()}; + if (follower.Follow(old_node.GetLastTile(), old_node.GetLastTrackdir())) { + Yapf().AddMultipleNodes(&old_node, follower); } } @@ -320,9 +320,9 @@ class CYapfFollowAnySafeTileRailT : public CYapfReserveTrack { */ inline void PfFollowNode(Node &old_node) { - TrackFollower F(Yapf().GetVehicle(), Yapf().GetCompatibleRailTypes()); - if (F.Follow(old_node.GetLastTile(), old_node.GetLastTrackdir()) && F.MaskReservedTracks()) { - Yapf().AddMultipleNodes(&old_node, F); + TrackFollower follower{Yapf().GetVehicle(), Yapf().GetCompatibleRailTypes()}; + if (follower.Follow(old_node.GetLastTile(), old_node.GetLastTrackdir()) && follower.MaskReservedTracks()) { + Yapf().AddMultipleNodes(&old_node, follower); } } @@ -402,9 +402,9 @@ class CYapfFollowRailT : public CYapfReserveTrack { */ inline void PfFollowNode(Node &old_node) { - TrackFollower F(Yapf().GetVehicle()); - if (F.Follow(old_node.GetLastTile(), old_node.GetLastTrackdir())) { - Yapf().AddMultipleNodes(&old_node, F); + TrackFollower follower{Yapf().GetVehicle()}; + if (follower.Follow(old_node.GetLastTile(), old_node.GetLastTrackdir())) { + Yapf().AddMultipleNodes(&old_node, follower); } } @@ -544,14 +544,37 @@ struct CYapfRail_TypesT { typedef CYapfCostRailT PfCost; }; -struct CYapfRail : CYapfT> {}; -struct CYapfRailNo90 : CYapfT> {}; +template +struct CYapfRailBase : CYapfT { + typedef typename Types::NodeList::Item Node; -struct CYapfAnyDepotRail : CYapfT> {}; -struct CYapfAnyDepotRailNo90 : CYapfT> {}; + /** + * In some cases an intermediate node branch should be pruned. + * The most prominent case is when a red EOL signal is encountered, but + * there was a segment change (e.g. a rail type change) before that. If + * the branch would not be pruned, the rail type change location would + * remain the best intermediate node, and thus the vehicle would still + * go towards the red EOL signal. + */ + void PruneIntermediateNodeBranch(Node *n) + { + bool intermediate_on_branch = false; + while (n != nullptr && !n->segment->end_segment_reason.Test(EndSegmentReason::ChoiceFollows)) { + if (n == this->best_intermediate_node) intermediate_on_branch = true; + n = n->parent; + } + if (intermediate_on_branch) this->best_intermediate_node = n; + } +}; + +struct CYapfRail : CYapfRailBase> {}; +struct CYapfRailNo90 : CYapfRailBase> {}; + +struct CYapfAnyDepotRail : CYapfRailBase> {}; +struct CYapfAnyDepotRailNo90 : CYapfRailBase> {}; -struct CYapfAnySafeTileRail : CYapfT> {}; -struct CYapfAnySafeTileRailNo90 : CYapfT> {}; +struct CYapfAnySafeTileRail : CYapfRailBase> {}; +struct CYapfAnySafeTileRailNo90 : CYapfRailBase> {}; Track YapfTrainChooseTrack(const Train *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool &path_found, bool reserve_track, PBSTileInfo *target, TileIndex *dest) diff --git a/src/pathfinder/yapf/yapf_river_builder.cpp b/src/pathfinder/yapf/yapf_river_builder.cpp index 697ddd2e8fadd..c084f841c94d7 100644 --- a/src/pathfinder/yapf/yapf_river_builder.cpp +++ b/src/pathfinder/yapf/yapf_river_builder.cpp @@ -22,7 +22,7 @@ struct YapfRiverBuilderNode : CYapfNodeT; /* We don't need a follower but YAPF requires one. */ -struct DummyFollower {}; +struct RiverBuilderFollower {}; /* We don't need a vehicle but YAPF requires one. */ struct DummyVehicle : Vehicle {}; @@ -32,7 +32,7 @@ class YapfRiverBuilder; /* Types struct required for YAPF components. */ struct RiverBuilderTypes { using Tpf = YapfRiverBuilder; - using TrackFollower = DummyFollower; + using TrackFollower = RiverBuilderFollower; using NodeList = RiverBuilderNodeList; using VehicleType = DummyVehicle; }; @@ -47,7 +47,6 @@ class YapfRiverBuilder using Key = Node::Key; protected: - TileIndex start_tile; ///< Start tile of the river TileIndex end_tile; ///< End tile of the river inline YapfRiverBuilder &Yapf() @@ -58,14 +57,10 @@ class YapfRiverBuilder public: YapfRiverBuilder(TileIndex start_tile, TileIndex end_tile) { - this->start_tile = start_tile; this->end_tile = end_tile; - } - void PfSetStartupNodes() - { Node &node = Yapf().CreateNewNode(); - node.Set(nullptr, this->start_tile, INVALID_TRACKDIR, false); + node.Set(nullptr, start_tile, INVALID_TRACKDIR, false); Yapf().AddStartupNode(node); } @@ -74,7 +69,7 @@ class YapfRiverBuilder return n.GetTile() == this->end_tile; } - inline bool PfCalcCost(Node &n, const DummyFollower *) + inline bool PfCalcCost(Node &n, const RiverBuilderFollower *) { n.cost = n.parent->cost + 1 + RandomRange(_settings_game.game_creation.river_route_random); return true; @@ -94,7 +89,7 @@ class YapfRiverBuilder if (IsValidTile(t) && RiverFlowsDown(old_node.GetTile(), t)) { Node &node = Yapf().CreateNewNode(); node.Set(&old_node, t, INVALID_TRACKDIR, true); - Yapf().AddNewNode(node, DummyFollower{}); + Yapf().AddNewNode(node, RiverBuilderFollower{}); } } } diff --git a/src/pathfinder/yapf/yapf_ship.cpp b/src/pathfinder/yapf/yapf_ship.cpp index fcb2e3759c491..bec4068a57a37 100644 --- a/src/pathfinder/yapf/yapf_ship.cpp +++ b/src/pathfinder/yapf/yapf_ship.cpp @@ -133,11 +133,11 @@ class CYapfFollowShipT { */ inline void PfFollowNode(Node &old_node) { - TrackFollower F(Yapf().GetVehicle()); - if (F.Follow(old_node.key.tile, old_node.key.td)) { + TrackFollower follower{Yapf().GetVehicle()}; + if (follower.Follow(old_node.key.tile, old_node.key.td)) { if (this->water_region_corridor.empty() - || std::ranges::find(this->water_region_corridor, GetWaterRegionInfo(F.new_tile)) != this->water_region_corridor.end()) { - Yapf().AddMultipleNodes(&old_node, F); + || std::ranges::find(this->water_region_corridor, GetWaterRegionInfo(follower.new_tile)) != this->water_region_corridor.end()) { + Yapf().AddMultipleNodes(&old_node, follower); } } } @@ -166,7 +166,7 @@ class CYapfFollowShipT { /** Returns a random tile/trackdir that can be reached from the current tile/trackdir, or tile/INVALID_TRACK if none is available. */ static std::pair GetRandomFollowUpTileTrackdir(const Ship *v, TileIndex tile, Trackdir dir) { - TrackFollower follower(v); + TrackFollower follower{v}; if (follower.Follow(tile, dir)) { TrackdirBits dirs = follower.new_td_bits; const TrackdirBits dirs_without_90_degree = dirs & ~TrackdirCrossesTrackdirs(dir); @@ -361,7 +361,7 @@ class CYapfCostShipT { * Calculates only the cost of given node, adds it to the parent node cost * and stores the result into Node::cost member. */ - inline bool PfCalcCost(Node &n, const TrackFollower *tf) + inline bool PfCalcCost(Node &n, const TrackFollower *follower) { /* Base tile cost depending on distance. */ int c = IsDiagonalTrackdir(n.GetTrackdir()) ? YAPF_TILE_LENGTH : YAPF_TILE_CORNER_LENGTH; @@ -381,12 +381,12 @@ class CYapfCostShipT { if (!IsPreferredShipDirection(n.GetTile(), n.GetTrackdir())) c += YAPF_TILE_LENGTH; /* Skipped tile cost for aqueducts. */ - c += YAPF_TILE_LENGTH * tf->tiles_skipped; + c += YAPF_TILE_LENGTH * follower->tiles_skipped; /* Ocean/canal speed penalty. */ const ShipVehicleInfo *svi = ShipVehInfo(Yapf().GetVehicle()->engine_type); uint8_t speed_frac = (GetEffectiveWaterClass(n.GetTile()) == WATER_CLASS_SEA) ? svi->ocean_speed_frac : svi->canal_speed_frac; - if (speed_frac > 0) c += YAPF_TILE_LENGTH * (1 + tf->tiles_skipped) * speed_frac / (256 - speed_frac); + if (speed_frac > 0) c += YAPF_TILE_LENGTH * (1 + follower->tiles_skipped) * speed_frac / (256 - speed_frac); /* Lock penalty. */ if (IsTileType(n.GetTile(), MP_WATER) && IsLock(n.GetTile()) && GetLockPart(n.GetTile()) == LOCK_PART_MIDDLE) { diff --git a/src/pathfinder/yapf/yapf_ship_regions.cpp b/src/pathfinder/yapf/yapf_ship_regions.cpp index 202936a7bdbd7..caa243fc10998 100644 --- a/src/pathfinder/yapf/yapf_ship_regions.cpp +++ b/src/pathfinder/yapf/yapf_ship_regions.cpp @@ -16,12 +16,15 @@ #include "../../safeguards.h" -constexpr int DIRECT_NEIGHBOUR_COST = 100; -constexpr int NODES_PER_REGION = 4; -constexpr int MAX_NUMBER_OF_NODES = 65536; +static constexpr int DIRECT_NEIGHBOUR_COST = 100; +static constexpr int NODES_PER_REGION = 4; +static constexpr int MAX_NUMBER_OF_NODES = 65536; + +static constexpr int NODE_LIST_HASH_BITS_OPEN = 12; +static constexpr int NODE_LIST_HASH_BITS_CLOSED = 12; /** Yapf Node Key that represents a single patch of interconnected water within a water region. */ -struct CYapfRegionPatchNodeKey { +struct WaterRegionPatchKey { WaterRegionPatchDesc water_region_patch; inline void Set(const WaterRegionPatchDesc &water_region_patch) @@ -30,19 +33,18 @@ struct CYapfRegionPatchNodeKey { } inline int CalcHash() const { return CalculateWaterRegionPatchHash(this->water_region_patch); } - inline bool operator==(const CYapfRegionPatchNodeKey &other) const { return this->CalcHash() == other.CalcHash(); } + inline bool operator==(const WaterRegionPatchKey &other) const { return this->CalcHash() == other.CalcHash(); } }; -inline uint ManhattanDistance(const CYapfRegionPatchNodeKey &a, const CYapfRegionPatchNodeKey &b) +inline uint ManhattanDistance(const WaterRegionPatchKey &a, const WaterRegionPatchKey &b) { return (std::abs(a.water_region_patch.x - b.water_region_patch.x) + std::abs(a.water_region_patch.y - b.water_region_patch.y)) * DIRECT_NEIGHBOUR_COST; } /** Yapf Node for water regions. */ -template -struct CYapfRegionNodeT : CYapfNodeT> { - typedef Tkey_ Key; - typedef CYapfRegionNodeT Node; +struct WaterRegionNode : CYapfNodeT { + using Key = WaterRegionPatchKey; + using Node = WaterRegionNode; inline void Set(Node *parent, const WaterRegionPatchDesc &water_region_patch) { @@ -71,68 +73,93 @@ struct CYapfRegionNodeT : CYapfNodeT> { } }; -/** YAPF origin for water regions. */ -template -class CYapfOriginRegionT { -public: - typedef typename Types::Tpf Tpf; ///< The pathfinder class (derived from THIS class). - typedef typename Types::NodeList::Item Node; ///< This will be our node type. - typedef typename Node::Key Key; ///< Key to hash tables. +using WaterRegionNodeList = NodeList; + +/* We don't need a follower but YAPF requires one. */ +struct WaterRegionFollower : public CFollowTrackWater {}; + +class YapfShipRegions; -protected: - inline Tpf &Yapf() { return *static_cast(this); } +/* Types struct required for YAPF internals. */ +struct WaterRegionTypes { + using Tpf = YapfShipRegions; + using TrackFollower = WaterRegionFollower; + using NodeList = WaterRegionNodeList; + using VehicleType = Ship; +}; +/** Water region based YAPF implementation for ships. */ +class YapfShipRegions + : public CYapfBaseT + , public CYapfSegmentCostCacheNoneT +{ private: - std::vector origin_keys; + using Node = typename WaterRegionTypes::NodeList::Item; -public: - void AddOrigin(const WaterRegionPatchDesc &water_region_patch) + std::vector origin_keys; + WaterRegionPatchKey dest; + + inline YapfShipRegions &Yapf() { - if (water_region_patch.label == INVALID_WATER_REGION_PATCH) return; - if (!HasOrigin(water_region_patch)) this->origin_keys.emplace_back(water_region_patch); + return *static_cast(this); } - bool HasOrigin(const WaterRegionPatchDesc &water_region_patch) +public: + explicit YapfShipRegions(int max_nodes) { - return std::ranges::find(this->origin_keys, CYapfRegionPatchNodeKey{ water_region_patch }) != this->origin_keys.end(); + this->max_search_nodes = max_nodes; } - void PfSetStartupNodes() + void AddOrigin(const WaterRegionPatchDesc &water_region_patch) { - for (const CYapfRegionPatchNodeKey &origin_key : this->origin_keys) { + if (water_region_patch.label == INVALID_WATER_REGION_PATCH) return; + if (!HasOrigin(water_region_patch)) { + this->origin_keys.emplace_back(water_region_patch); Node &node = Yapf().CreateNewNode(); - node.Set(nullptr, origin_key); + node.Set(nullptr, water_region_patch); Yapf().AddStartupNode(node); } } -}; -/** YAPF destination provider for water regions. */ -template -class CYapfDestinationRegionT { -public: - typedef typename Types::Tpf Tpf; ///< The pathfinder class (derived from THIS class). - typedef typename Types::NodeList::Item Node; ///< This will be our node type. - typedef typename Node::Key Key; ///< Key to hash tables. - -protected: - Key dest; + bool HasOrigin(const WaterRegionPatchDesc &water_region_patch) + { + return std::ranges::find(this->origin_keys, WaterRegionPatchKey{ water_region_patch }) != this->origin_keys.end(); + } -public: void SetDestination(const WaterRegionPatchDesc &water_region_patch) { this->dest.Set(water_region_patch); } -protected: - Tpf &Yapf() { return *static_cast(this); } + inline void PfFollowNode(Node &old_node) + { + VisitWaterRegionPatchCallback visit_func = [&](const WaterRegionPatchDesc &water_region_patch) { + Node &node = Yapf().CreateNewNode(); + node.Set(&old_node, water_region_patch); + Yapf().AddNewNode(node, TrackFollower{}); + }; + VisitWaterRegionPatchNeighbours(old_node.key.water_region_patch, visit_func); + } -public: inline bool PfDetectDestination(Node &n) const { return n.key == this->dest; } + inline bool PfCalcCost(Node &n, const TrackFollower *) + { + n.cost = n.parent->cost + ManhattanDistance(n.key, n.parent->key); + + /* Incentivise zigzagging by adding a slight penalty when the search continues in the same direction. */ + Node *grandparent = n.parent->parent; + if (grandparent != nullptr) { + const DiagDirDiff dir_diff = DiagDirDifference(n.parent->GetDiagDirFromParent(), n.GetDiagDirFromParent()); + if (dir_diff != DIAGDIRDIFF_90LEFT && dir_diff != DIAGDIRDIFF_90RIGHT) n.cost += 1; + } + + return true; + } + inline bool PfCalcEstimate(Node &n) { if (this->PfDetectDestination(n)) { @@ -144,31 +171,6 @@ class CYapfDestinationRegionT { return true; } -}; - -/** YAPF node following for water region pathfinding. */ -template -class CYapfFollowRegionT { -public: - typedef typename Types::Tpf Tpf; ///< The pathfinder class (derived from THIS class). - typedef typename Types::TrackFollower TrackFollower; - typedef typename Types::NodeList::Item Node; ///< This will be our node type. - typedef typename Node::Key Key; ///< Key to hash tables. - -protected: - inline Tpf &Yapf() { return *static_cast(this); } - -public: - inline void PfFollowNode(Node &old_node) - { - VisitWaterRegionPatchCallback visit_func = [&](const WaterRegionPatchDesc &water_region_patch) - { - Node &node = Yapf().CreateNewNode(); - node.Set(&old_node, water_region_patch); - Yapf().AddNewNode(node, TrackFollower{}); - }; - VisitWaterRegionPatchNeighbours(old_node.key.water_region_patch, visit_func); - } inline char TransportTypeChar() const { return '^'; } @@ -178,7 +180,8 @@ class CYapfFollowRegionT { /* We reserve 4 nodes (patches) per water region. The vast majority of water regions have 1 or 2 regions so this should be a pretty * safe limit. We cap the limit at 65536 which is at a region size of 16x16 is equivalent to one node per region for a 4096x4096 map. */ - Tpf pf(std::min(static_cast(Map::Size() * NODES_PER_REGION) / WATER_REGION_NUMBER_OF_TILES, MAX_NUMBER_OF_NODES)); + const int node_limit = std::min(static_cast(Map::Size() * NODES_PER_REGION) / WATER_REGION_NUMBER_OF_TILES, MAX_NUMBER_OF_NODES); + YapfShipRegions pf(node_limit); pf.SetDestination(start_water_region_patch); if (v->current_order.IsType(OT_GOTO_STATION)) { @@ -215,70 +218,6 @@ class CYapfFollowRegionT { } }; -/** Cost Provider of YAPF for water regions. */ -template -class CYapfCostRegionT { -public: - typedef typename Types::Tpf Tpf; ///< The pathfinder class (derived from THIS class). - typedef typename Types::TrackFollower TrackFollower; - typedef typename Types::NodeList::Item Node; ///< This will be our node type. - typedef typename Node::Key Key; ///< Key to hash tables. - -protected: - /** To access inherited path finder. */ - Tpf &Yapf() { return *static_cast(this); } - -public: - /** - * Called by YAPF to calculate the cost from the origin to the given node. - * Calculates only the cost of given node, adds it to the parent node cost - * and stores the result into Node::cost member. - */ - inline bool PfCalcCost(Node &n, const TrackFollower *) - { - n.cost = n.parent->cost + ManhattanDistance(n.key, n.parent->key); - - /* Incentivise zigzagging by adding a slight penalty when the search continues in the same direction. */ - Node *grandparent = n.parent->parent; - if (grandparent != nullptr) { - const DiagDirDiff dir_diff = DiagDirDifference(n.parent->GetDiagDirFromParent(), n.GetDiagDirFromParent()); - if (dir_diff != DIAGDIRDIFF_90LEFT && dir_diff != DIAGDIRDIFF_90RIGHT) n.cost += 1; - } - - return true; - } -}; - -/* We don't need a follower but YAPF requires one. */ -struct DummyFollower : public CFollowTrackWater {}; - -/** - * Config struct of YAPF for route planning. - * Defines all 6 base YAPF modules as classes providing services for CYapfBaseT. - */ -template -struct CYapfRegion_TypesT { - typedef CYapfRegion_TypesT Types; ///< Shortcut for this struct type. - typedef Tpf_ Tpf; ///< Pathfinder type. - typedef DummyFollower TrackFollower; ///< Track follower helper class - typedef Tnode_list NodeList; - typedef Ship VehicleType; - - /** Pathfinder components (modules). */ - typedef CYapfBaseT PfBase; ///< Base pathfinder class. - typedef CYapfFollowRegionT PfFollow; ///< Node follower. - typedef CYapfOriginRegionT PfOrigin; ///< Origin provider. - typedef CYapfDestinationRegionT PfDestination; ///< Destination/distance provider. - typedef CYapfSegmentCostCacheNoneT PfCache; ///< Segment cost cache provider. - typedef CYapfCostRegionT PfCost; ///< Cost provider. -}; - -typedef NodeList, 12, 12> CRegionNodeListWater; - -struct CYapfRegionWater : CYapfT> { - explicit CYapfRegionWater(int max_nodes) { this->max_search_nodes = max_nodes; } -}; - /** * Finds a path at the water region level. Note that the starting region is always included if the path was found. * @param v The ship to find a path for. @@ -288,5 +227,5 @@ struct CYapfRegionWater : CYapfT YapfShipFindWaterRegionPath(const Ship *v, TileIndex start_tile, int max_returned_path_length) { - return CYapfRegionWater::FindWaterRegionPath(v, start_tile, max_returned_path_length); + return YapfShipRegions::FindWaterRegionPath(v, start_tile, max_returned_path_length); } diff --git a/src/pathfinder/yapf/yapf_type.hpp b/src/pathfinder/yapf/yapf_type.hpp index 2a045e0785107..7aeb0f80af658 100644 --- a/src/pathfinder/yapf/yapf_type.hpp +++ b/src/pathfinder/yapf/yapf_type.hpp @@ -72,7 +72,7 @@ inline std::string ValueStr(EndSegmentReasons flags) "PATH_TOO_LONG", "FIRST_TWO_WAY_RED", "LOOK_AHEAD_END", "TARGET_REACHED" }; - return fmt::format("0x{:04X} ({})", flags.base(), ComposeNameT(flags, end_segment_reason_names, "UNK")); + return fmt::format("0x{:04X} ({})", flags.base(), ComposeName(flags, end_segment_reason_names, "UNK")); } #endif /* YAPF_TYPE_HPP */ diff --git a/src/pbs.cpp b/src/pbs.cpp index f47c990c6d2cc..fff806b80e1f2 100644 --- a/src/pbs.cpp +++ b/src/pbs.cpp @@ -188,7 +188,7 @@ void UnreserveRailTrack(TileIndex tile, Track t) /** Follow a reservation starting from a specific tile to the end. */ -static PBSTileInfo FollowReservation(Owner o, RailTypes rts, TileIndex tile, Trackdir trackdir, bool ignore_oneway = false) +static PBSTileInfo FollowReservation(Owner o, const RailTypes &rts, TileIndex tile, Trackdir trackdir, bool ignore_oneway = false) { TileIndex start_tile = tile; Trackdir start_trackdir = trackdir; diff --git a/src/picker_gui.cpp b/src/picker_gui.cpp index 2f636cf8f7391..4c4bbc5ae010a 100644 --- a/src/picker_gui.cpp +++ b/src/picker_gui.cpp @@ -738,7 +738,7 @@ void PickerWindow::EnsureSelectedTypeIsVisible() /** Create nested widgets for the class picker widgets. */ std::unique_ptr MakePickerClassWidgets() { - static constexpr NWidgetPart picker_class_widgets[] = { + static constexpr std::initializer_list picker_class_widgets = { NWidget(NWID_SELECTION, INVALID_COLOUR, WID_PW_CLASS_SEL), NWidget(NWID_VERTICAL), NWidget(WWT_PANEL, COLOUR_DARK_GREEN), @@ -761,7 +761,7 @@ std::unique_ptr MakePickerClassWidgets() /** Create nested widgets for the type picker widgets. */ std::unique_ptr MakePickerTypeWidgets() { - static constexpr NWidgetPart picker_type_widgets[] = { + static constexpr std::initializer_list picker_type_widgets = { NWidget(NWID_SELECTION, INVALID_COLOUR, WID_PW_TYPE_SEL), NWidget(NWID_VERTICAL), NWidget(NWID_HORIZONTAL), diff --git a/src/provider_manager.h b/src/provider_manager.h index 5ab398de34dd4..377a17af28c11 100644 --- a/src/provider_manager.h +++ b/src/provider_manager.h @@ -25,7 +25,7 @@ class ProviderManager { ProviderManager &operator=(ProviderManager const &) = delete; - static void Register(TProviderType &instance) + static void Register(const TProviderType &instance) { /* Insert according to comparator. */ auto &providers = GetProviders(); @@ -33,7 +33,7 @@ class ProviderManager { providers.insert(it, &instance); } - static void Unregister(TProviderType &instance) + static void Unregister(const TProviderType &instance) { auto &providers = GetProviders(); providers.erase(std::find(std::begin(providers), std::end(providers), &instance)); @@ -43,9 +43,9 @@ class ProviderManager { * Get the currently known providers. * @return The known providers. */ - static std::vector &GetProviders() + static std::vector &GetProviders() { - static std::vector providers{}; + static std::vector providers{}; return providers; } }; diff --git a/src/rail.cpp b/src/rail.cpp index 852a4dce6f2fb..11a859175cf17 100644 --- a/src/rail.cpp +++ b/src/rail.cpp @@ -19,6 +19,17 @@ #include "safeguards.h" +/** + * Get the RailType for this RailTypeInfo. + * @return RailType in static RailTypeInfo definitions. + */ +RailType RailTypeInfo::Index() const +{ + size_t index = this - GetRailTypeInfo().data(); + assert(index < GetNumRailTypes()); + return static_cast(index); +} + /** * Return the rail type of tile, or INVALID_RAILTYPE if this is no rail tile. */ @@ -77,7 +88,7 @@ bool HasAnyRailTypesAvail(const CompanyID company) */ bool ValParamRailType(const RailType rail) { - return rail < RAILTYPE_END && HasRailTypeAvail(_current_company, rail); + return rail < GetNumRailTypes() && HasRailTypeAvail(_current_company, rail); } /** @@ -87,26 +98,24 @@ bool ValParamRailType(const RailType rail) * @return The rail types that should be available when date * introduced rail types are taken into account as well. */ -RailTypes AddDateIntroducedRailTypes(RailTypes current, TimerGameCalendar::Date date) +RailTypes AddDateIntroducedRailTypes(const RailTypes ¤t, TimerGameCalendar::Date date) { RailTypes rts = current; - for (RailType rt = RAILTYPE_BEGIN; rt != RAILTYPE_END; rt++) { - const RailTypeInfo *rti = GetRailTypeInfo(rt); + for (RailTypeInfo &rti : GetRailTypeInfo()) { /* Unused rail type. */ - if (rti->label == 0) continue; + if (rti.label == 0) continue; /* Not date introduced. */ - if (!IsInsideMM(rti->introduction_date, 0, CalendarTime::MAX_DATE.base())) continue; + if (!IsInsideMM(rti.introduction_date, 0, CalendarTime::MAX_DATE.base())) continue; /* Not yet introduced at this date. */ - if (rti->introduction_date > date) continue; + if (rti.introduction_date > date) continue; /* Have we introduced all required railtypes? */ - RailTypes required = rti->introduction_required_railtypes; - if (!rts.All(required)) continue; + if (!rts.All(rti.introduction_required_railtypes)) continue; - rts.Set(rti->introduces_railtypes); + rts.Set(rti.introduces_railtypes); } /* When we added railtypes we need to run this method again; the added @@ -129,7 +138,7 @@ RailTypes GetCompanyRailTypes(CompanyID company, bool introduces) if (ei->climates.Test(_settings_game.game_creation.landscape) && (e->company_avail.Test(company) || TimerGameCalendar::date >= e->intro_date + CalendarTime::DAYS_IN_YEAR)) { - const RailVehicleInfo *rvi = &e->u.rail; + const RailVehicleInfo *rvi = &e->VehInfo(); if (rvi->railveh_type != RAILVEH_WAGON) { assert(rvi->railtypes.Any()); @@ -159,7 +168,7 @@ RailTypes GetRailTypes(bool introduces) const EngineInfo *ei = &e->info; if (!ei->climates.Test(_settings_game.game_creation.landscape)) continue; - const RailVehicleInfo *rvi = &e->u.rail; + const RailVehicleInfo *rvi = &e->VehInfo(); if (rvi->railveh_type != RAILVEH_WAGON) { assert(rvi->railtypes.Any()); if (introduces) { @@ -182,22 +191,49 @@ RailTypes GetRailTypes(bool introduces) */ RailType GetRailTypeByLabel(RailTypeLabel label, bool allow_alternate_labels) { + auto railtypes = GetRailTypeInfo(); if (label == 0) return INVALID_RAILTYPE; - /* Loop through each rail type until the label is found */ - for (RailType r = RAILTYPE_BEGIN; r != RAILTYPE_END; r++) { - const RailTypeInfo *rti = GetRailTypeInfo(r); - if (rti->label == label) return r; - } - - if (allow_alternate_labels) { + auto it = std::ranges::find(railtypes, label, &RailTypeInfo::label); + if (it == std::end(railtypes) && allow_alternate_labels) { /* Test if any rail type defines the label as an alternate. */ - for (RailType r = RAILTYPE_BEGIN; r != RAILTYPE_END; r++) { - const RailTypeInfo *rti = GetRailTypeInfo(r); - if (std::ranges::find(rti->alternate_labels, label) != rti->alternate_labels.end()) return r; - } + it = std::ranges::find_if(railtypes, [label](const RailTypeInfo &rti) { return rti.alternate_labels.contains(label); }); } + if (it != std::end(railtypes)) return it->Index(); + /* No matching label was found, so it is invalid */ return INVALID_RAILTYPE; } + +/** + * Get a set of rail types that are currently in use on the map. + * @return Used rail types. + */ +static RailTypes GetUsedRailTypes() +{ + RailTypes used_types; + for (const Company *c : Company::Iterate()) { + for (const auto &[railtype, count] : c->infrastructure.rail) { + if (count > 0) used_types.Set(railtype); + } + } + return used_types; +} + +/** + * Get the first unused mapped rail type position. + * @return iterator to first unused mapped rail type. + */ +template <> auto RailTypeMapping::FindUnusedMapType() -> MapStorage::iterator +{ + RailTypes used_types = GetUsedRailTypes(); + if (used_types.size() < RailTypeMapping::MAX_SIZE) { + for (auto it = std::begin(this->map); it != std::end(this->map); ++it) { + if (!used_types.contains(*it)) return it; + } + } + return std::end(this->map); +} + +RailTypeMapping _railtype_mapping; diff --git a/src/rail.h b/src/rail.h index 4a294e213dbe5..01e70989e2a52 100644 --- a/src/rail.h +++ b/src/rail.h @@ -15,6 +15,7 @@ #include "gfx_type.h" #include "core/bitmath_func.hpp" #include "core/enum_type.hpp" +#include "core/flatset_type.hpp" #include "economy_func.h" #include "slope_type.h" #include "strings_type.h" @@ -131,6 +132,7 @@ class RailTypeInfo { SpriteID single_sloped;///< single piece of rail for slopes SpriteID crossing; ///< level crossing, rail in X direction SpriteID tunnel; ///< tunnel sprites base + SpriteID bridge_deck; ///< bridge deck sprites base } base_sprites; /** @@ -226,7 +228,7 @@ class RailTypeInfo { /** * Rail type labels this type provides in addition to the main label. */ - std::vector alternate_labels; + FlatSet alternate_labels; /** * Colour on mini-map @@ -286,8 +288,20 @@ class RailTypeInfo { { return 82 * this->fallback_railtype; } + + RailType Index() const; }; +inline std::span GetRailTypeInfo() +{ + extern std::vector _railtypes; + return _railtypes; +} + +inline size_t GetNumRailTypes() +{ + return std::size(GetRailTypeInfo()); +} /** * Returns a pointer to the Railtype information for a given railtype @@ -296,22 +310,8 @@ class RailTypeInfo { */ inline const RailTypeInfo *GetRailTypeInfo(RailType railtype) { - extern RailTypeInfo _railtypes[RAILTYPE_END]; - assert(railtype < RAILTYPE_END); - return &_railtypes[railtype]; -} - -/** - * Returns the railtype for a Railtype information. - * @param rti Pointer to static RailTypeInfo - * @return Railtype in static railtype definitions - */ -inline RailType GetRailTypeInfoIndex(const RailTypeInfo *rti) -{ - extern RailTypeInfo _railtypes[RAILTYPE_END]; - size_t index = rti - _railtypes; - assert(index < RAILTYPE_END && rti == _railtypes + index); - return static_cast(index); + assert(railtype < GetNumRailTypes()); + return &GetRailTypeInfo()[railtype]; } /** @@ -319,7 +319,7 @@ inline RailType GetRailTypeInfoIndex(const RailTypeInfo *rti) * @param railtypes Set of railtypes to get the compatible railtypes from. * @return Union of all compatible railtypes. */ -inline RailTypes GetAllCompatibleRailTypes(RailTypes railtypes) +inline RailTypes GetAllCompatibleRailTypes(const RailTypes &railtypes) { RailTypes compatible{}; for (RailType rt : railtypes) compatible.Set(GetRailTypeInfo(rt)->compatible_railtypes); @@ -331,7 +331,7 @@ inline RailTypes GetAllCompatibleRailTypes(RailTypes railtypes) * @param railtypes Set of railtypes to get the powered railtypes from. * @return Union of all powered railtypes. */ -inline RailTypes GetAllPoweredRailTypes(RailTypes railtypes) +inline RailTypes GetAllPoweredRailTypes(const RailTypes &railtypes) { RailTypes powered{}; for (RailType rt : railtypes) powered.Set(GetRailTypeInfo(rt)->powered_railtypes); @@ -343,7 +343,7 @@ inline RailTypes GetAllPoweredRailTypes(RailTypes railtypes) * @param railtypes Set of railtypes to get the introduced railtypes from. * @return Union of all introduced railtypes. */ -inline RailTypes GetAllIntroducesRailTypes(RailTypes railtypes) +inline RailTypes GetAllIntroducesRailTypes(const RailTypes &railtypes) { RailTypes introduces{}; for (RailType rt : railtypes) introduces.Set(GetRailTypeInfo(rt)->introduces_railtypes); @@ -370,7 +370,7 @@ inline bool IsCompatibleRail(RailType enginetype, RailType tiletype) * @param tiletype The RailType of the tile we are considering. * @return Whether the engine can drive on this tile. */ -inline bool IsCompatibleRail(RailTypes enginetype, RailType tiletype) +inline bool IsCompatibleRail(const RailTypes &enginetype, RailType tiletype) { return GetAllCompatibleRailTypes(enginetype).Test(tiletype); } @@ -395,7 +395,7 @@ inline bool HasPowerOnRail(RailType enginetype, RailType tiletype) * @param tiletype The RailType of the tile we are considering. * @return Whether the engine got power on this tile. */ -inline bool HasPowerOnRail(RailTypes enginetype, RailType tiletype) +inline bool HasPowerOnRail(const RailTypes &enginetype, RailType tiletype) { return GetAllPoweredRailTypes(enginetype).Test(tiletype); } @@ -437,7 +437,7 @@ inline bool Rail90DegTurnDisallowed(RailType rt1, RailType rt2, bool def = _sett */ inline Money RailBuildCost(RailType railtype) { - assert(railtype < RAILTYPE_END); + assert(railtype < GetNumRailTypes()); return (_price[PR_BUILD_RAIL] * GetRailTypeInfo(railtype)->cost_multiplier) >> 3; } @@ -453,7 +453,7 @@ inline Money RailClearCost(RailType railtype) * In this case we limit the removal earnings to 3/4s of the build * cost. */ - assert(railtype < RAILTYPE_END); + assert(railtype < GetNumRailTypes()); return std::max(_price[PR_CLEAR_RAIL], -RailBuildCost(railtype) * 3 / 4); } @@ -492,7 +492,7 @@ inline Money RailConvertCost(RailType from, RailType to) */ inline Money RailMaintenanceCost(RailType railtype, uint32_t num, uint32_t total_num) { - assert(railtype < RAILTYPE_END); + assert(railtype < GetNumRailTypes()); return (_price[PR_INFRASTRUCTURE_RAIL] * GetRailTypeInfo(railtype)->maintenance_multiplier * num * (1 + IntSqrt(total_num))) >> 11; // 4 bits fraction for the multiplier and 7 bits scaling. } @@ -516,7 +516,7 @@ bool HasRailTypeAvail(const CompanyID company, const RailType railtype); bool HasAnyRailTypesAvail(const CompanyID company); bool ValParamRailType(const RailType rail); -RailTypes AddDateIntroducedRailTypes(RailTypes current, TimerGameCalendar::Date date); +RailTypes AddDateIntroducedRailTypes(const RailTypes ¤t, TimerGameCalendar::Date date); RailTypes GetCompanyRailTypes(CompanyID company, bool introduces = true); RailTypes GetRailTypes(bool introduces); diff --git a/src/rail_cmd.cpp b/src/rail_cmd.cpp index fa702799559ba..5a87493211c2d 100644 --- a/src/rail_cmd.cpp +++ b/src/rail_cmd.cpp @@ -43,7 +43,7 @@ /** Helper type for lists/vectors of trains */ typedef std::vector TrainList; -RailTypeInfo _railtypes[RAILTYPE_END]; +std::vector _railtypes; std::vector _sorted_railtypes; ///< Sorted list of rail types. RailTypes _railtypes_hidden_mask; @@ -64,34 +64,32 @@ enum SignalOffsets { */ void ResetRailTypes() { - static_assert(std::size(_original_railtypes) <= std::size(_railtypes)); - - auto insert = std::copy(std::begin(_original_railtypes), std::end(_original_railtypes), std::begin(_railtypes)); - std::fill(insert, std::end(_railtypes), RailTypeInfo{}); + _railtypes.clear(); + std::copy(std::begin(_original_railtypes), std::end(_original_railtypes), std::back_inserter(_railtypes)); _railtypes_hidden_mask = {}; } -void ResolveRailTypeGUISprites(RailTypeInfo *rti) +static void ResolveRailTypeGUISprites(RailTypeInfo &rti) { - SpriteID cursors_base = GetCustomRailSprite(rti, INVALID_TILE, RTSG_CURSORS); + SpriteID cursors_base = GetCustomRailSprite(&rti, INVALID_TILE, RTSG_CURSORS); if (cursors_base != 0) { - rti->gui_sprites.build_ns_rail = cursors_base + 0; - rti->gui_sprites.build_x_rail = cursors_base + 1; - rti->gui_sprites.build_ew_rail = cursors_base + 2; - rti->gui_sprites.build_y_rail = cursors_base + 3; - rti->gui_sprites.auto_rail = cursors_base + 4; - rti->gui_sprites.build_depot = cursors_base + 5; - rti->gui_sprites.build_tunnel = cursors_base + 6; - rti->gui_sprites.convert_rail = cursors_base + 7; - rti->cursor.rail_ns = cursors_base + 8; - rti->cursor.rail_swne = cursors_base + 9; - rti->cursor.rail_ew = cursors_base + 10; - rti->cursor.rail_nwse = cursors_base + 11; - rti->cursor.autorail = cursors_base + 12; - rti->cursor.depot = cursors_base + 13; - rti->cursor.tunnel = cursors_base + 14; - rti->cursor.convert = cursors_base + 15; + rti.gui_sprites.build_ns_rail = cursors_base + 0; + rti.gui_sprites.build_x_rail = cursors_base + 1; + rti.gui_sprites.build_ew_rail = cursors_base + 2; + rti.gui_sprites.build_y_rail = cursors_base + 3; + rti.gui_sprites.auto_rail = cursors_base + 4; + rti.gui_sprites.build_depot = cursors_base + 5; + rti.gui_sprites.build_tunnel = cursors_base + 6; + rti.gui_sprites.convert_rail = cursors_base + 7; + rti.cursor.rail_ns = cursors_base + 8; + rti.cursor.rail_swne = cursors_base + 9; + rti.cursor.rail_ew = cursors_base + 10; + rti.cursor.rail_nwse = cursors_base + 11; + rti.cursor.autorail = cursors_base + 12; + rti.cursor.depot = cursors_base + 13; + rti.cursor.tunnel = cursors_base + 14; + rti.cursor.convert = cursors_base + 15; } /* Array of default GUI signal sprite numbers. */ @@ -105,10 +103,10 @@ void ResolveRailTypeGUISprites(RailTypeInfo *rti) for (SignalType type = SIGTYPE_BLOCK; type < SIGTYPE_END; type = (SignalType)(type + 1)) { for (SignalVariant var = SIG_ELECTRIC; var <= SIG_SEMAPHORE; var = (SignalVariant)(var + 1)) { - SpriteID red = GetCustomSignalSprite(rti, INVALID_TILE, type, var, SIGNAL_STATE_RED, true); - SpriteID green = GetCustomSignalSprite(rti, INVALID_TILE, type, var, SIGNAL_STATE_GREEN, true); - rti->gui_sprites.signals[type][var][0] = (red != 0) ? red + SIGNAL_TO_SOUTH : _signal_lookup[var][type]; - rti->gui_sprites.signals[type][var][1] = (green != 0) ? green + SIGNAL_TO_SOUTH : _signal_lookup[var][type] + 1; + SpriteID red = GetCustomSignalSprite(&rti, INVALID_TILE, type, var, SIGNAL_STATE_RED, true); + SpriteID green = GetCustomSignalSprite(&rti, INVALID_TILE, type, var, SIGNAL_STATE_GREEN, true); + rti.gui_sprites.signals[type][var][0] = (red != 0) ? red + SIGNAL_TO_SOUTH : _signal_lookup[var][type]; + rti.gui_sprites.signals[type][var][1] = (green != 0) ? green + SIGNAL_TO_SOUTH : _signal_lookup[var][type] + 1; } } } @@ -129,15 +127,14 @@ static bool CompareRailTypes(const RailType &first, const RailType &second) */ void InitRailTypes() { - for (RailType rt = RAILTYPE_BEGIN; rt != RAILTYPE_END; rt++) { - RailTypeInfo *rti = &_railtypes[rt]; + _sorted_railtypes.clear(); + for (RailTypeInfo &rti : _railtypes) { + RailType rt = rti.Index(); + ResolveRailTypeGUISprites(rti); - if (rti->flags.Test(RailTypeFlag::Hidden)) _railtypes_hidden_mask.Set(rt); - } + _railtypes_hidden_mask.Set(rt, rti.flags.Test(RailTypeFlag::Hidden)); - _sorted_railtypes.clear(); - for (RailType rt = RAILTYPE_BEGIN; rt != RAILTYPE_END; rt++) { - if (_railtypes[rt].label == 0) continue; + if (rti.label == 0) continue; _sorted_railtypes.push_back(rt); } std::sort(_sorted_railtypes.begin(), _sorted_railtypes.end(), CompareRailTypes); @@ -148,34 +145,32 @@ void InitRailTypes() */ RailType AllocateRailType(RailTypeLabel label) { - for (RailType rt = RAILTYPE_BEGIN; rt != RAILTYPE_END; rt++) { - RailTypeInfo *rti = &_railtypes[rt]; + auto it = std::ranges::find(_railtypes, 0, &RailTypeInfo::label); + if (it == std::end(_railtypes)) it = _railtypes.emplace(it, _original_railtypes[RAILTYPE_RAIL]); - if (rti->label == 0) { - /* Set up new rail type */ - *rti = _original_railtypes[RAILTYPE_RAIL]; - rti->label = label; - rti->alternate_labels.clear(); + RailTypeInfo &rti = *it; + RailType rt = rti.Index(); - /* Make us compatible with ourself. */ - rti->powered_railtypes = rt; - rti->compatible_railtypes = rt; + /* Set up new rail type */ + rti.label = label; + rti.alternate_labels.clear(); - /* We also introduce ourself. */ - rti->introduces_railtypes = rt; + /* Make us compatible with ourself. */ + rti.powered_railtypes = rt; + rti.compatible_railtypes = rt; - /* Default sort order; order of allocation, but with some - * offsets so it's easier for NewGRF to pick a spot without - * changing the order of other (original) rail types. - * The << is so you can place other railtypes in between the - * other railtypes, the 7 is to be able to place something - * before the first (default) rail type. */ - rti->sorting_order = rt << 4 | 7; - return rt; - } - } + /* We also introduce ourself. */ + rti.introduces_railtypes = rt; - return INVALID_RAILTYPE; + /* Default sort order; order of allocation, but with some + * offsets so it's easier for NewGRF to pick a spot without + * changing the order of other (original) rail types. + * The << is so you can place other railtypes in between the + * other railtypes, the 7 is to be able to place something + * before the first (default) rail type. */ + rti.sorting_order = rt << 4 | 7; + + return rt; } static const uint8_t _track_sloped_sprites[14] = { @@ -510,11 +505,11 @@ CommandCost CmdBuildSingleRail(DoCommandFlags flags, TileIndex tile, RailType ra if (RailNoLevelCrossings(railtype)) return CommandCost(STR_ERROR_CROSSING_DISALLOWED_RAIL); - RoadType roadtype_road = GetRoadTypeRoad(tile); - RoadType roadtype_tram = GetRoadTypeTram(tile); + MapRoadType map_roadtype = GetMapRoadTypeRoad(tile); + MapTramType map_tramtype = GetMapRoadTypeTram(tile); - if (roadtype_road != INVALID_ROADTYPE && RoadNoLevelCrossing(roadtype_road)) return CommandCost(STR_ERROR_CROSSING_DISALLOWED_ROAD); - if (roadtype_tram != INVALID_ROADTYPE && RoadNoLevelCrossing(roadtype_tram)) return CommandCost(STR_ERROR_CROSSING_DISALLOWED_ROAD); + if (map_roadtype != RoadTypeMapping::INVALID_MAP_TYPE && RoadNoLevelCrossing(_roadtype_mapping.GetType(map_roadtype))) return CommandCost(STR_ERROR_CROSSING_DISALLOWED_ROAD); + if (map_tramtype != TramTypeMapping::INVALID_MAP_TYPE && RoadNoLevelCrossing(_tramtype_mapping.GetType(map_tramtype))) return CommandCost(STR_ERROR_CROSSING_DISALLOWED_ROAD); RoadBits road = GetRoadBits(tile, RTT_ROAD); RoadBits tram = GetRoadBits(tile, RTT_TRAM); @@ -531,27 +526,40 @@ CommandCost CmdBuildSingleRail(DoCommandFlags flags, TileIndex tile, RailType ra uint num_new_road_pieces = (road != ROAD_NONE) ? 2 - CountBits(road) : 0; if (num_new_road_pieces > 0) { - cost.AddCost(num_new_road_pieces * RoadBuildCost(roadtype_road)); + cost.AddCost(num_new_road_pieces * RoadBuildCost(_roadtype_mapping.GetType(map_roadtype))); } uint num_new_tram_pieces = (tram != ROAD_NONE) ? 2 - CountBits(tram) : 0; if (num_new_tram_pieces > 0) { - cost.AddCost(num_new_tram_pieces * RoadBuildCost(roadtype_tram)); + cost.AddCost(num_new_tram_pieces * RoadBuildCost(_tramtype_mapping.GetType(map_tramtype))); } + MapRailType map_railtype = _railtype_mapping.AllocateMapType(railtype, flags.Test(DoCommandFlag::Execute)); + if (map_railtype == RailTypeMapping::INVALID_MAP_TYPE) return CommandCost{STR_ERROR_TOO_MANY_RAILTYPES}; + if (flags.Test(DoCommandFlag::Execute)) { - MakeRoadCrossing(tile, road_owner, tram_owner, _current_company, (track == TRACK_X ? AXIS_Y : AXIS_X), railtype, roadtype_road, roadtype_tram, GetTownIndex(tile)); + MakeRoadCrossing(tile, road_owner, tram_owner, _current_company, (track == TRACK_X ? AXIS_Y : AXIS_X), map_railtype, map_roadtype, map_tramtype, GetTownIndex(tile)); UpdateLevelCrossing(tile, false); MarkDirtyAdjacentLevelCrossingTiles(tile, GetCrossingRoadAxis(tile)); Company::Get(_current_company)->infrastructure.rail[railtype] += LEVELCROSSING_TRACKBIT_FACTOR; DirtyCompanyInfrastructureWindows(_current_company); - if (num_new_road_pieces > 0 && Company::IsValidID(road_owner)) { - Company::Get(road_owner)->infrastructure.road[roadtype_road] += num_new_road_pieces; - DirtyCompanyInfrastructureWindows(road_owner); + if (num_new_road_pieces > 0) { + RoadType roadtype = _roadtype_mapping.GetType(map_roadtype); + if (Company::IsValidID(road_owner)) { + Company::Get(road_owner)->infrastructure.road[roadtype] += num_new_road_pieces; + DirtyCompanyInfrastructureWindows(road_owner); + } else { + RoadTypeInfo::infrastructure_counts[roadtype] += num_new_road_pieces; + } } - if (num_new_tram_pieces > 0 && Company::IsValidID(tram_owner)) { - Company::Get(tram_owner)->infrastructure.road[roadtype_tram] += num_new_tram_pieces; - DirtyCompanyInfrastructureWindows(tram_owner); + if (num_new_tram_pieces > 0) { + RoadType tramtype = _tramtype_mapping.GetType(map_tramtype); + if (Company::IsValidID(tram_owner)) { + Company::Get(tram_owner)->infrastructure.road[tramtype] += num_new_tram_pieces; + DirtyCompanyInfrastructureWindows(tram_owner); + } else { + RoadTypeInfo::infrastructure_counts[tramtype] += num_new_tram_pieces; + } } } break; @@ -581,8 +589,11 @@ CommandCost CmdBuildSingleRail(DoCommandFlags flags, TileIndex tile, RailType ra cost.AddCost(_price[PR_CLEAR_ROUGH]); } + MapRailType map_railtype = _railtype_mapping.AllocateMapType(railtype, flags.Test(DoCommandFlag::Execute)); + if (map_railtype == RailTypeMapping::INVALID_MAP_TYPE) return CommandCost{STR_ERROR_TOO_MANY_RAILTYPES}; + if (flags.Test(DoCommandFlag::Execute)) { - MakeRailNormal(tile, _current_company, trackbit, railtype); + MakeRailNormal(tile, _current_company, trackbit, map_railtype); if (water_ground) { SetRailGroundType(tile, RAIL_GROUND_WATER); if (IsPossibleDockingTile(tile)) CheckForDockingTile(tile); @@ -654,7 +665,7 @@ CommandCost CmdRemoveSingleRail(DoCommandFlags flags, TileIndex tile, Track trac owner = GetTileOwner(tile); Company::Get(owner)->infrastructure.rail[GetRailType(tile)] -= LEVELCROSSING_TRACKBIT_FACTOR; DirtyCompanyInfrastructureWindows(owner); - MakeRoadNormal(tile, GetCrossingRoadBits(tile), GetRoadTypeRoad(tile), GetRoadTypeTram(tile), GetTownIndex(tile), GetRoadOwner(tile, RTT_ROAD), GetRoadOwner(tile, RTT_TRAM)); + MakeRoadNormal(tile, GetCrossingRoadBits(tile), GetMapRoadTypeRoad(tile), GetMapRoadTypeTram(tile), GetTownIndex(tile), GetRoadOwner(tile, RTT_ROAD), GetRoadOwner(tile, RTT_TRAM)); DeleteNewGRFInspectWindow(GSF_RAILTYPES, tile.base()); } break; @@ -1006,13 +1017,16 @@ CommandCost CmdBuildTrainDepot(DoCommandFlags flags, TileIndex tile, RailType ra if (!Depot::CanAllocateItem()) return CMD_ERROR; } + MapRailType map_railtype = _railtype_mapping.AllocateMapType(railtype, flags.Test(DoCommandFlag::Execute)); + if (map_railtype == RailTypeMapping::INVALID_MAP_TYPE) return CommandCost{STR_ERROR_TOO_MANY_RAILTYPES}; + if (flags.Test(DoCommandFlag::Execute)) { if (rotate_existing_depot) { SetRailDepotExitDirection(tile, dir); } else { Depot *d = new Depot(tile); - MakeRailDepot(tile, _current_company, d->index, dir, railtype); + MakeRailDepot(tile, _current_company, d->index, dir, map_railtype); MakeDefaultName(d); Company::Get(_current_company)->infrastructure.rail[railtype]++; @@ -1551,6 +1565,9 @@ CommandCost CmdConvertRail(DoCommandFlags flags, TileIndex tile, TileIndex area_ CommandCost error = CommandCost(STR_ERROR_NO_SUITABLE_RAILROAD_TRACK); // by default, there is no track to convert. bool found_convertible_track = false; // whether we actually did convert some track (see bug #7633) + MapRailType map_railtype = _railtype_mapping.AllocateMapType(totype, flags.Test(DoCommandFlag::Execute)); + if (map_railtype == RailTypeMapping::INVALID_MAP_TYPE) return CommandCost{STR_ERROR_TOO_MANY_RAILTYPES}; + std::unique_ptr iter = TileIterator::Create(area_start, area_end, diagonal); for (; (tile = *iter) != INVALID_TILE; ++(*iter)) { TileType tt = GetTileType(tile); @@ -1626,7 +1643,7 @@ CommandCost CmdConvertRail(DoCommandFlags flags, TileIndex tile, TileIndex area_ DirtyCompanyInfrastructureWindows(c->index); } - SetRailType(tile, totype); + SetMapRailType(tile, map_railtype); MarkTileDirtyByTile(tile); /* update power of train on this tile */ for (Vehicle *v : VehiclesOnTile(tile)) { @@ -1705,8 +1722,8 @@ CommandCost CmdConvertRail(DoCommandFlags flags, TileIndex tile, TileIndex area_ c->infrastructure.rail[totype] += num_pieces; DirtyCompanyInfrastructureWindows(c->index); - SetRailType(tile, totype); - SetRailType(endtile, totype); + SetMapRailType(tile, map_railtype); + SetMapRailType(endtile, map_railtype); for (Vehicle *v : VehiclesOnTile(tile)) { if (v->type == VEH_TRAIN) include(affected_trains, Train::From(v)->First()); diff --git a/src/rail_cmd.h b/src/rail_cmd.h index eb78df1d1c3a9..9ee4ccf2d46ce 100644 --- a/src/rail_cmd.h +++ b/src/rail_cmd.h @@ -27,16 +27,16 @@ CommandCost CmdConvertRail(DoCommandFlags flags, TileIndex tile, TileIndex area_ CommandCost CmdBuildSignalTrack(DoCommandFlags flags, TileIndex tile, TileIndex end_tile, Track track, SignalType sigtype, SignalVariant sigvar, bool mode, bool autofill, bool minimise_gaps, uint8_t signal_density); CommandCost CmdRemoveSignalTrack(DoCommandFlags flags, TileIndex tile, TileIndex end_tile, Track track, bool autofill); -DEF_CMD_TRAIT(CMD_BUILD_RAILROAD_TRACK, CmdBuildRailroadTrack, CommandFlags({CommandFlag::Auto, CommandFlag::NoWater}), CMDT_LANDSCAPE_CONSTRUCTION) -DEF_CMD_TRAIT(CMD_REMOVE_RAILROAD_TRACK, CmdRemoveRailroadTrack, CommandFlag::Auto, CMDT_LANDSCAPE_CONSTRUCTION) -DEF_CMD_TRAIT(CMD_BUILD_SINGLE_RAIL, CmdBuildSingleRail, CommandFlags({CommandFlag::Auto, CommandFlag::NoWater}), CMDT_LANDSCAPE_CONSTRUCTION) -DEF_CMD_TRAIT(CMD_REMOVE_SINGLE_RAIL, CmdRemoveSingleRail, CommandFlag::Auto, CMDT_LANDSCAPE_CONSTRUCTION) -DEF_CMD_TRAIT(CMD_BUILD_TRAIN_DEPOT, CmdBuildTrainDepot, CommandFlags({CommandFlag::Auto, CommandFlag::NoWater}), CMDT_LANDSCAPE_CONSTRUCTION) -DEF_CMD_TRAIT(CMD_BUILD_SINGLE_SIGNAL, CmdBuildSingleSignal, CommandFlag::Auto, CMDT_LANDSCAPE_CONSTRUCTION) -DEF_CMD_TRAIT(CMD_REMOVE_SINGLE_SIGNAL, CmdRemoveSingleSignal, CommandFlag::Auto, CMDT_LANDSCAPE_CONSTRUCTION) -DEF_CMD_TRAIT(CMD_CONVERT_RAIL, CmdConvertRail, {}, CMDT_LANDSCAPE_CONSTRUCTION) -DEF_CMD_TRAIT(CMD_BUILD_SIGNAL_TRACK, CmdBuildSignalTrack, CommandFlag::Auto, CMDT_LANDSCAPE_CONSTRUCTION) -DEF_CMD_TRAIT(CMD_REMOVE_SIGNAL_TRACK, CmdRemoveSignalTrack, CommandFlag::Auto, CMDT_LANDSCAPE_CONSTRUCTION) +DEF_CMD_TRAIT(CMD_BUILD_RAILROAD_TRACK, CmdBuildRailroadTrack, CommandFlags({CommandFlag::Auto, CommandFlag::NoWater}), CommandType::LandscapeConstruction) +DEF_CMD_TRAIT(CMD_REMOVE_RAILROAD_TRACK, CmdRemoveRailroadTrack, CommandFlag::Auto, CommandType::LandscapeConstruction) +DEF_CMD_TRAIT(CMD_BUILD_SINGLE_RAIL, CmdBuildSingleRail, CommandFlags({CommandFlag::Auto, CommandFlag::NoWater}), CommandType::LandscapeConstruction) +DEF_CMD_TRAIT(CMD_REMOVE_SINGLE_RAIL, CmdRemoveSingleRail, CommandFlag::Auto, CommandType::LandscapeConstruction) +DEF_CMD_TRAIT(CMD_BUILD_TRAIN_DEPOT, CmdBuildTrainDepot, CommandFlags({CommandFlag::Auto, CommandFlag::NoWater}), CommandType::LandscapeConstruction) +DEF_CMD_TRAIT(CMD_BUILD_SINGLE_SIGNAL, CmdBuildSingleSignal, CommandFlag::Auto, CommandType::LandscapeConstruction) +DEF_CMD_TRAIT(CMD_REMOVE_SINGLE_SIGNAL, CmdRemoveSingleSignal, CommandFlag::Auto, CommandType::LandscapeConstruction) +DEF_CMD_TRAIT(CMD_CONVERT_RAIL, CmdConvertRail, {}, CommandType::LandscapeConstruction) +DEF_CMD_TRAIT(CMD_BUILD_SIGNAL_TRACK, CmdBuildSignalTrack, CommandFlag::Auto, CommandType::LandscapeConstruction) +DEF_CMD_TRAIT(CMD_REMOVE_SIGNAL_TRACK, CmdRemoveSignalTrack, CommandFlag::Auto, CommandType::LandscapeConstruction) CommandCallback CcPlaySound_CONSTRUCTION_RAIL; CommandCallback CcStation; diff --git a/src/rail_gui.cpp b/src/rail_gui.cpp index feaccc2a7d129..f15398570a227 100644 --- a/src/rail_gui.cpp +++ b/src/rail_gui.cpp @@ -29,7 +29,6 @@ #include "dropdown_func.h" #include "tunnelbridge.h" #include "tilehighlight_func.h" -#include "spritecache.h" #include "core/geometry_func.hpp" #include "hotkeys.h" #include "engine_base.h" @@ -438,7 +437,7 @@ static void HandleAutoSignalPlacement() /** Rail toolbar management class. */ struct BuildRailToolbarWindow : Window { RailType railtype = INVALID_RAILTYPE; ///< Rail type to build. - int last_user_action = INVALID_WID_RAT; ///< Last started user action. + WidgetID last_user_action = INVALID_WIDGET; ///< Last started user action. BuildRailToolbarWindow(WindowDesc &desc, RailType railtype) : Window(desc), railtype(railtype) { @@ -710,7 +709,7 @@ struct BuildRailToolbarWindow : Window { break; case WID_RAT_BUILD_TUNNEL: - Command::Post(STR_ERROR_CAN_T_BUILD_TUNNEL_HERE, CcBuildRailTunnel, tile, TRANSPORT_RAIL, _cur_railtype); + Command::Post(STR_ERROR_CAN_T_BUILD_TUNNEL_HERE, CcBuildRailTunnel, tile, TRANSPORT_RAIL, _cur_railtype, INVALID_ROADTYPE); break; case WID_RAT_CONVERT_RAIL: @@ -729,6 +728,11 @@ struct BuildRailToolbarWindow : Window { VpSelectTilesWithMethod(pt.x, pt.y, select_method); } + Point OnInitialPosition(int16_t sm_width, [[maybe_unused]] int16_t sm_height, [[maybe_unused]] int window_number) override + { + return AlignInitialConstructionToolbar(sm_width); + } + void OnPlaceMouseUp([[maybe_unused]] ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, [[maybe_unused]] Point pt, TileIndex start_tile, TileIndex end_tile) override { if (pt.x != -1) { @@ -736,7 +740,7 @@ struct BuildRailToolbarWindow : Window { default: NOT_REACHED(); case DDSP_BUILD_BRIDGE: if (!_settings_client.gui.persistent_buildingtools) ResetObjectToPlace(); - ShowBuildBridgeWindow(start_tile, end_tile, TRANSPORT_RAIL, _cur_railtype); + ShowBuildBridgeWindow(start_tile, end_tile, TRANSPORT_RAIL, _cur_railtype, INVALID_ROADTYPE); break; case DDSP_PLACE_RAIL: @@ -810,7 +814,7 @@ struct BuildRailToolbarWindow : Window { void OnPlacePresize([[maybe_unused]] Point pt, TileIndex tile) override { - Command::Do(DoCommandFlag::Auto, tile, TRANSPORT_RAIL, _cur_railtype); + Command::Do(DoCommandFlag::Auto, tile, TRANSPORT_RAIL, _cur_railtype, INVALID_ROADTYPE); VpSetPresizeRange(tile, _build_tunnel_endtile == 0 ? tile : _build_tunnel_endtile); } @@ -858,7 +862,7 @@ struct BuildRailToolbarWindow : Window { }, RailToolbarGlobalHotkeys}; }; -static constexpr NWidgetPart _nested_build_rail_widgets[] = { +static constexpr std::initializer_list _nested_build_rail_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN), NWidget(WWT_CAPTION, COLOUR_DARK_GREEN, WID_RAT_CAPTION), SetTextStyle(TC_WHITE), @@ -900,7 +904,7 @@ static constexpr NWidgetPart _nested_build_rail_widgets[] = { }; static WindowDesc _build_rail_desc( - WDP_ALIGN_TOOLBAR, "toolbar_rail", 0, 0, + WDP_MANUAL, "toolbar_rail", 0, 0, WC_BUILD_TOOLBAR, WC_NONE, WindowDefaultFlag::Construction, _nested_build_rail_widgets, @@ -1384,7 +1388,7 @@ struct BuildRailStationWindow : public PickerWindow { }, BuildRailStationGlobalHotkeys}; }; -static constexpr NWidgetPart _nested_station_builder_widgets[] = { +static constexpr std::initializer_list _nested_station_builder_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN), NWidget(WWT_CAPTION, COLOUR_DARK_GREEN), SetStringTip(STR_STATION_BUILD_RAIL_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), @@ -1626,7 +1630,7 @@ struct BuildSignalWindow : public PickerWindowBase { }; /** Nested widget definition of the build signal window */ -static constexpr NWidgetPart _nested_signal_builder_widgets[] = { +static constexpr std::initializer_list _nested_signal_builder_widgets = { /* Title bar and buttons. */ NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN), @@ -1753,7 +1757,7 @@ struct BuildRailDepotWindow : public PickerWindowBase { }; /** Nested widget definition of the build rail depot window */ -static constexpr NWidgetPart _nested_build_depot_widgets[] = { +static constexpr std::initializer_list _nested_build_depot_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN), NWidget(WWT_CAPTION, COLOUR_DARK_GREEN), SetStringTip(STR_BUILD_DEPOT_TRAIN_ORIENTATION_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), @@ -1878,7 +1882,7 @@ struct BuildRailWaypointWindow : public PickerWindow { }; /** Nested widget definition for the build NewGRF rail waypoint window */ -static constexpr NWidgetPart _nested_build_waypoint_widgets[] = { +static constexpr std::initializer_list _nested_build_waypoint_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN), NWidget(WWT_CAPTION, COLOUR_DARK_GREEN), SetStringTip(STR_WAYPOINT_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), @@ -1942,7 +1946,7 @@ static void SetDefaultRailGui() switch (_settings_client.gui.default_rail_type) { case 2: { /* Find the most used rail type */ - std::array count{}; + std::vector count(GetNumRailTypes()); for (const auto t : Map::Iterate()) { if (IsTileType(t, MP_RAILWAY) || IsLevelCrossingTile(t) || HasStationTileRail(t) || (IsTileType(t, MP_TUNNELBRIDGE) && GetTunnelBridgeTransportType(t) == TRANSPORT_RAIL)) { @@ -2071,7 +2075,7 @@ DropDownList GetRailTypeDropDownList(bool for_replacement, bool all_option) std::string str = rti->max_speed > 0 ? GetString(STR_TOOLBAR_RAILTYPE_VELOCITY, rti->strings.menu_text, rti->max_speed) : GetString(rti->strings.menu_text); - list.push_back(MakeDropDownListBadgeIconItem(badge_class_list, rti->badges, GSF_RAILTYPES, rti->introduction_date, d, rti->gui_sprites.build_x_rail, PAL_NONE, std::move(str), rt, !avail_railtypes.Test(rt))); + list.push_back(MakeDropDownListBadgeIconItem(badge_class_list, rti->badges, GSF_RAILTYPES, rti->introduction_date, RailBuildCost(rt), d, rti->gui_sprites.build_x_rail, PAL_NONE, std::move(str), rt, !avail_railtypes.Test(rt))); } } diff --git a/src/rail_map.h b/src/rail_map.h index 5b06a2cb57756..68496e72c0ba9 100644 --- a/src/rail_map.h +++ b/src/rail_map.h @@ -107,24 +107,37 @@ debug_inline static bool IsRailDepotTile(Tile t) return IsTileType(t, MP_RAILWAY) && IsRailDepot(t); } + /** - * Gets the rail type of the given tile - * @param t the tile to get the rail type from - * @return the rail type of the tile + * Gets the map rail type of the given tile + * @param t the tile to get the map rail type from + * @return the map rail type of the tile */ -inline RailType GetRailType(Tile t) +inline MapRailType GetMapRailType(Tile t) { - return (RailType)GB(t.m8(), 0, 6); + return static_cast(GB(t.m8(), 0, 6)); } + /** * Sets the rail type of the given tile * @param t the tile to set the rail type of - * @param r the new rail type for the tile + * @param map_railtype the new mapped rail type for the tile + */ +inline void SetMapRailType(Tile t, MapRailType map_railtype) +{ + SB(t.m8(), 0, 6, map_railtype.base()); +} + + +/** + * Gets the rail type of the given tile + * @param t the tile to get the rail type from + * @return the rail type of the tile */ -inline void SetRailType(Tile t, RailType r) +inline RailType GetRailType(Tile t) { - SB(t.m8(), 0, 6, r); + return _railtype_mapping.GetType(GetMapRailType(t)); } @@ -515,7 +528,7 @@ inline bool IsSnowRailGround(Tile t) } -inline void MakeRailNormal(Tile t, Owner o, TrackBits b, RailType r) +inline void MakeRailNormal(Tile t, Owner o, TrackBits b, MapRailType map_railtype) { SetTileType(t, MP_RAILWAY); SetTileOwner(t, o); @@ -524,9 +537,9 @@ inline void MakeRailNormal(Tile t, Owner o, TrackBits b, RailType r) t.m3() = 0; t.m4() = 0; t.m5() = RAIL_TILE_NORMAL << 6 | b; - SB(t.m6(), 2, 4, 0); + SB(t.m6(), 2, 6, 0); t.m7() = 0; - t.m8() = r; + t.m8() = map_railtype.base(); } /** @@ -546,9 +559,9 @@ inline void SetRailDepotExitDirection(Tile tile, DiagDirection dir) * @param owner New owner of the depot. * @param depot_id New depot ID. * @param dir Direction of the depot exit. - * @param rail_type Rail type of the depot. + * @param map_railtype Mapped rail type of the depot. */ -inline void MakeRailDepot(Tile tile, Owner owner, DepotID depot_id, DiagDirection dir, RailType rail_type) +inline void MakeRailDepot(Tile tile, Owner owner, DepotID depot_id, DiagDirection dir, MapRailType map_railtype) { SetTileType(tile, MP_RAILWAY); SetTileOwner(tile, owner); @@ -557,9 +570,9 @@ inline void MakeRailDepot(Tile tile, Owner owner, DepotID depot_id, DiagDirectio tile.m3() = 0; tile.m4() = 0; tile.m5() = RAIL_TILE_DEPOT << 6 | dir; - SB(tile.m6(), 2, 4, 0); + SB(tile.m6(), 2, 6, 0); tile.m7() = 0; - tile.m8() = rail_type; + tile.m8() = map_railtype.base(); } #endif /* RAIL_MAP_H */ diff --git a/src/rail_type.h b/src/rail_type.h index cb12a09e37ee3..b1cbc710f6464 100644 --- a/src/rail_type.h +++ b/src/rail_type.h @@ -11,6 +11,9 @@ #define RAIL_TYPE_H #include "core/enum_type.hpp" +#include "core/flatset_type.hpp" +#include "core/strong_typedef_type.hpp" +#include "transport_mapping.hpp" typedef uint32_t RailTypeLabel; @@ -22,21 +25,27 @@ static const RailTypeLabel RAILTYPE_LABEL_MAGLEV = 'MGLV'; /** * Enumeration for all possible railtypes. */ -enum RailType : uint8_t { +enum RailType : uint16_t { RAILTYPE_BEGIN = 0, ///< Used for iterations RAILTYPE_RAIL = 0, ///< Standard non-electric rails RAILTYPE_ELECTRIC = 1, ///< Electric rails RAILTYPE_MONO = 2, ///< Monorail RAILTYPE_MAGLEV = 3, ///< Maglev - RAILTYPE_END = 64, ///< Used for iterations - INVALID_RAILTYPE = 0xFF, ///< Flag for invalid railtype + INVALID_RAILTYPE = UINT16_MAX, ///< Flag for invalid railtype }; /** Allow incrementing of Track variables */ DECLARE_INCREMENT_DECREMENT_OPERATORS(RailType) -using RailTypes = EnumBitSet; +using RailTypes = FlatBitSet; -static constexpr RailTypes INVALID_RAILTYPES{UINT64_MAX}; +static const RailTypes INVALID_RAILTYPES{}; + +/** Mapped rail type. */ +using RailTypeMapping = TransportMapping; +extern RailTypeMapping _railtype_mapping; + +/** Alias for mapped rail type. */ +using MapRailType = RailTypeMapping::MapType; #endif /* RAIL_TYPE_H */ diff --git a/src/road.cpp b/src/road.cpp index 27a6a9bb780d8..417ba51334008 100644 --- a/src/road.cpp +++ b/src/road.cpp @@ -10,6 +10,8 @@ #include "stdafx.h" #include "rail_map.h" #include "road_map.h" +#include "station_map.h" +#include "tunnelbridge_map.h" #include "water_map.h" #include "genworld.h" #include "company_func.h" @@ -23,6 +25,17 @@ #include "safeguards.h" +/** + * Get the RoadType for this RoadTypeInfo. + * @return RoadType in static RoadTypeInfo definitions. + */ +RoadType RoadTypeInfo::Index() const +{ + size_t index = this - GetRoadTypeInfo().data(); + assert(index < GetNumRoadTypes()); + return static_cast(index); +} + /** * Return if the tile is a valid tile for a crossing. * @@ -123,13 +136,14 @@ bool HasRoadTypeAvail(const CompanyID company, RoadType roadtype) * owned by towns. So if a town may build it, it should be buildable by them too. */ return !rti->flags.Test( RoadTypeFlag::Hidden) || rti->flags.Test( RoadTypeFlag::TownBuild); - } else { - const Company *c = Company::GetIfValid(company); - if (c == nullptr) return false; - RoadTypes avail = c->avail_roadtypes; - avail.Reset(_roadtypes_hidden_mask); - return avail.Test(roadtype); } + + if (_roadtypes_hidden_mask.Test(roadtype)) return false; + + const Company *c = Company::GetIfValid(company); + if (c == nullptr) return false; + + return c->avail_roadtypes.Test(roadtype); } /** @@ -151,7 +165,7 @@ bool HasAnyRoadTypesAvail(CompanyID company, RoadTramType rtt) */ bool ValParamRoadType(RoadType roadtype) { - return roadtype < ROADTYPE_END && HasRoadTypeAvail(_current_company, roadtype); + return roadtype < GetNumRoadTypes() && HasRoadTypeAvail(_current_company, roadtype); } /** @@ -162,26 +176,24 @@ bool ValParamRoadType(RoadType roadtype) * @return The road types that should be available when date * introduced road types are taken into account as well. */ -RoadTypes AddDateIntroducedRoadTypes(RoadTypes current, TimerGameCalendar::Date date) +RoadTypes AddDateIntroducedRoadTypes(const RoadTypes ¤t, TimerGameCalendar::Date date) { RoadTypes rts = current; - for (RoadType rt = ROADTYPE_BEGIN; rt != ROADTYPE_END; rt++) { - const RoadTypeInfo *rti = GetRoadTypeInfo(rt); + for (RoadTypeInfo &rti : GetRoadTypeInfo()) { /* Unused road type. */ - if (rti->label == 0) continue; + if (rti.label == 0) continue; /* Not date introduced. */ - if (!IsInsideMM(rti->introduction_date, 0, CalendarTime::MAX_DATE.base())) continue; + if (!IsInsideMM(rti.introduction_date, 0, CalendarTime::MAX_DATE.base())) continue; /* Not yet introduced at this date. */ - if (rti->introduction_date > date) continue; + if (rti.introduction_date > date) continue; /* Have we introduced all required roadtypes? */ - RoadTypes required = rti->introduction_required_roadtypes; - if (!rts.All(required)) continue; + if (!rts.All(rti.introduction_required_roadtypes)) continue; - rts.Set(rti->introduces_roadtypes); + rts.Set(rti.introduces_roadtypes); } /* When we added roadtypes we need to run this method again; the added @@ -204,8 +216,8 @@ RoadTypes GetCompanyRoadTypes(CompanyID company, bool introduces) if (ei->climates.Test(_settings_game.game_creation.landscape) && (e->company_avail.Test(company) || TimerGameCalendar::date >= e->intro_date + CalendarTime::DAYS_IN_YEAR)) { - const RoadVehicleInfo *rvi = &e->u.road; - assert(rvi->roadtype < ROADTYPE_END); + const RoadVehicleInfo *rvi = &e->VehInfo(); + assert(rvi->roadtype < GetNumRoadTypes()); if (introduces) { rts.Set(GetRoadTypeInfo(rvi->roadtype)->introduces_roadtypes); } else { @@ -231,8 +243,8 @@ RoadTypes GetRoadTypes(bool introduces) const EngineInfo *ei = &e->info; if (!ei->climates.Test(_settings_game.game_creation.landscape)) continue; - const RoadVehicleInfo *rvi = &e->u.road; - assert(rvi->roadtype < ROADTYPE_END); + const RoadVehicleInfo *rvi = &e->VehInfo(); + assert(rvi->roadtype < GetNumRoadTypes()); if (introduces) { rts.Set(GetRoadTypeInfo(rvi->roadtype)->introduces_roadtypes); } else { @@ -252,22 +264,70 @@ RoadTypes GetRoadTypes(bool introduces) */ RoadType GetRoadTypeByLabel(RoadTypeLabel label, bool allow_alternate_labels) { + auto roadtypes = GetRoadTypeInfo(); if (label == 0) return INVALID_ROADTYPE; - /* Loop through each road type until the label is found */ - for (RoadType r = ROADTYPE_BEGIN; r != ROADTYPE_END; r++) { - const RoadTypeInfo *rti = GetRoadTypeInfo(r); - if (rti->label == label) return r; - } - - if (allow_alternate_labels) { + auto it = std::ranges::find(roadtypes, label, &RoadTypeInfo::label); + if (it == std::end(roadtypes) && allow_alternate_labels) { /* Test if any road type defines the label as an alternate. */ - for (RoadType r = ROADTYPE_BEGIN; r != ROADTYPE_END; r++) { - const RoadTypeInfo *rti = GetRoadTypeInfo(r); - if (std::ranges::find(rti->alternate_labels, label) != rti->alternate_labels.end()) return r; - } + it = std::ranges::find_if(roadtypes, [label](const RoadTypeInfo &rti) { return rti.alternate_labels.contains(label); }); } + if (it != std::end(roadtypes)) return it->Index(); + /* No matching label was found, so it is invalid */ return INVALID_ROADTYPE; } + +/** + * Get a set of road types that are currently in use on the map. + * @param rtt Requied RoadTramType of road types. + * @return Used road types. + */ +static RoadTypes GetUsedRoadTypes(RoadTramType rtt) +{ + RoadTypes used_types; + for (const Company *c : Company::Iterate()) { + for (const auto &[roadtype, count] : c->infrastructure.road) { + if (count > 0 && GetRoadTramType(roadtype) == rtt) used_types.Set(roadtype); + } + } + + for (const auto &[roadtype, count] : RoadTypeInfo::infrastructure_counts) { + if (count > 0 && GetRoadTramType(roadtype) == rtt) used_types.Set(roadtype); + } + return used_types; +} + +/** + * Get the first unused mapped road type position. + * @return iterator to first unused mapped road type. + */ +template <> auto RoadTypeMapping::FindUnusedMapType() -> MapStorage::iterator +{ + RoadTypes used_types = GetUsedRoadTypes(RoadTramType::RTT_ROAD); + if (used_types.size() < RoadTypeMapping::MAX_SIZE) { + for (auto it = std::begin(this->map); it != std::end(this->map); ++it) { + if (!used_types.contains(*it)) return it; + } + } + return std::end(this->map); +} + +/** + * Get the first unused mapped tram type position. + * @return iterator to first unused mapped tram type. + */ +template <> auto TramTypeMapping::FindUnusedMapType() -> MapStorage::iterator +{ + RoadTypes used_types = GetUsedRoadTypes(RoadTramType::RTT_TRAM); + if (used_types.size() < RoadTypeMapping::MAX_SIZE) { + for (auto it = std::begin(this->map); it != std::end(this->map); ++it) { + if (!used_types.contains(*it)) return it; + } + } + return std::end(this->map); +} + +RoadTypeMapping _roadtype_mapping; +TramTypeMapping _tramtype_mapping; diff --git a/src/road.h b/src/road.h index 76355d216e807..529ee421758cb 100644 --- a/src/road.h +++ b/src/road.h @@ -13,6 +13,7 @@ #include "road_type.h" #include "gfx_type.h" #include "core/bitmath_func.hpp" +#include "core/flatset_type.hpp" #include "strings_type.h" #include "timer/timer_game_calendar.h" #include "core/enum_type.hpp" @@ -20,20 +21,6 @@ #include "newgrf_badge_type.h" #include "economy_func.h" - -enum RoadTramType : bool { - RTT_ROAD, - RTT_TRAM, -}; - -enum RoadTramTypes : uint8_t { - RTTB_ROAD = 1 << RTT_ROAD, - RTTB_TRAM = 1 << RTT_TRAM, -}; -DECLARE_ENUM_AS_BIT_SET(RoadTramTypes) - -static const RoadTramType _roadtramtypes[] = { RTT_ROAD, RTT_TRAM }; - /** Roadtype flag bit numbers. */ enum class RoadTypeFlag : uint8_t { Catenary = 0, ///< Bit number for adding catenary @@ -137,7 +124,7 @@ class RoadTypeInfo { /** * Road type labels this type provides in addition to the main label. */ - std::vector alternate_labels; + FlatSet alternate_labels; /** * Colour on mini-map @@ -185,6 +172,13 @@ class RoadTypeInfo { { return this->group[ROTSG_GROUND] != nullptr; } + + RoadType Index() const; + + /** + * Infrastructure counts for unowned road pieces. + */ + static inline std::map infrastructure_counts{}; }; /** @@ -192,7 +186,7 @@ class RoadTypeInfo { * @param rtt RoadTramType. * @return Mask of road types for RoadTramType. */ -inline RoadTypes GetMaskForRoadTramType(RoadTramType rtt) +inline const RoadTypes &GetMaskForRoadTramType(RoadTramType rtt) { extern RoadTypes _roadtypes_road; extern RoadTypes _roadtypes_tram; @@ -215,10 +209,22 @@ inline RoadTramType GetRoadTramType(RoadType roadtype) } inline RoadTramType OtherRoadTramType(RoadTramType rtt) + { return rtt == RTT_ROAD ? RTT_TRAM : RTT_ROAD; } +inline std::span GetRoadTypeInfo() +{ + extern std::vector _roadtypes; + return _roadtypes; +} + +inline size_t GetNumRoadTypes() +{ + return std::size(GetRoadTypeInfo()); +} + /** * Returns a pointer to the Roadtype information for a given roadtype * @param roadtype the road type which the information is requested for @@ -226,22 +232,8 @@ inline RoadTramType OtherRoadTramType(RoadTramType rtt) */ inline const RoadTypeInfo *GetRoadTypeInfo(RoadType roadtype) { - extern RoadTypeInfo _roadtypes[ROADTYPE_END]; - assert(roadtype < ROADTYPE_END); - return &_roadtypes[roadtype]; -} - -/** - * Returns the railtype for a Railtype information. - * @param rti Pointer to static RailTypeInfo - * @return Railtype in static railtype definitions - */ -inline RoadType GetRoadTypeInfoIndex(const RoadTypeInfo *rti) -{ - extern RoadTypeInfo _roadtypes[ROADTYPE_END]; - size_t index = rti - _roadtypes; - assert(index < ROADTYPE_END && rti == _roadtypes + index); - return static_cast(index); + assert(roadtype < GetNumRoadTypes()); + return &GetRoadTypeInfo()[roadtype]; } /** @@ -264,7 +256,7 @@ inline bool HasPowerOnRoad(RoadType enginetype, RoadType tiletype) */ inline Money RoadBuildCost(RoadType roadtype) { - assert(roadtype < ROADTYPE_END); + assert(roadtype < GetNumRoadTypes()); return (_price[PR_BUILD_ROAD] * GetRoadTypeInfo(roadtype)->cost_multiplier) >> 3; } @@ -275,7 +267,7 @@ inline Money RoadBuildCost(RoadType roadtype) */ inline Money RoadClearCost(RoadType roadtype) { - assert(roadtype < ROADTYPE_END); + assert(roadtype < GetNumRoadTypes()); /* Flat fee for removing road. */ if (RoadTypeIsRoad(roadtype)) return _price[PR_CLEAR_ROAD]; @@ -307,7 +299,7 @@ inline Money RoadConvertCost(RoadType from, RoadType to) */ inline bool RoadNoLevelCrossing(RoadType roadtype) { - assert(roadtype < ROADTYPE_END); + assert(roadtype < GetNumRoadTypes()); return GetRoadTypeInfo(roadtype)->flags.Test(RoadTypeFlag::NoLevelCrossing); } diff --git a/src/road_cmd.cpp b/src/road_cmd.cpp index f1aff80870837..a628772fa3e50 100644 --- a/src/road_cmd.cpp +++ b/src/road_cmd.cpp @@ -51,7 +51,7 @@ /** Helper type for lists/vectors of road vehicles */ typedef std::vector RoadVehicleList; -RoadTypeInfo _roadtypes[ROADTYPE_END]; +std::vector _roadtypes; std::vector _sorted_roadtypes; ///< Sorted list of road types. RoadTypes _roadtypes_hidden_mask; ///< Bitset of hidden roadtypes. RoadTypes _roadtypes_road; ///< Bitset of road roadtypes. @@ -62,32 +62,30 @@ RoadTypes _roadtypes_tram; ///< Bitset of tram roadtypes. */ void ResetRoadTypes() { - static_assert(std::size(_original_roadtypes) <= std::size(_roadtypes)); - - auto insert = std::copy(std::begin(_original_roadtypes), std::end(_original_roadtypes), std::begin(_roadtypes)); - std::fill(insert, std::end(_roadtypes), RoadTypeInfo{}); + _roadtypes.clear(); + std::copy(std::begin(_original_roadtypes), std::end(_original_roadtypes), std::back_inserter(_roadtypes)); _roadtypes_hidden_mask = {}; _roadtypes_road = {ROADTYPE_ROAD}; _roadtypes_tram = {ROADTYPE_TRAM}; } -void ResolveRoadTypeGUISprites(RoadTypeInfo *rti) +static void ResolveRoadTypeGUISprites(RoadTypeInfo &rti) { - SpriteID cursors_base = GetCustomRoadSprite(rti, INVALID_TILE, ROTSG_CURSORS); + SpriteID cursors_base = GetCustomRoadSprite(&rti, INVALID_TILE, ROTSG_CURSORS); if (cursors_base != 0) { - rti->gui_sprites.build_y_road = cursors_base + 0; - rti->gui_sprites.build_x_road = cursors_base + 1; - rti->gui_sprites.auto_road = cursors_base + 2; - rti->gui_sprites.build_depot = cursors_base + 3; - rti->gui_sprites.build_tunnel = cursors_base + 4; - rti->gui_sprites.convert_road = cursors_base + 5; - rti->cursor.road_swne = cursors_base + 6; - rti->cursor.road_nwse = cursors_base + 7; - rti->cursor.autoroad = cursors_base + 8; - rti->cursor.depot = cursors_base + 9; - rti->cursor.tunnel = cursors_base + 10; - rti->cursor.convert_road = cursors_base + 11; + rti.gui_sprites.build_y_road = cursors_base + 0; + rti.gui_sprites.build_x_road = cursors_base + 1; + rti.gui_sprites.auto_road = cursors_base + 2; + rti.gui_sprites.build_depot = cursors_base + 3; + rti.gui_sprites.build_tunnel = cursors_base + 4; + rti.gui_sprites.convert_road = cursors_base + 5; + rti.cursor.road_swne = cursors_base + 6; + rti.cursor.road_nwse = cursors_base + 7; + rti.cursor.autoroad = cursors_base + 8; + rti.cursor.depot = cursors_base + 9; + rti.cursor.tunnel = cursors_base + 10; + rti.cursor.convert_road = cursors_base + 11; } } @@ -110,15 +108,14 @@ static bool CompareRoadTypes(const RoadType &first, const RoadType &second) */ void InitRoadTypes() { - for (RoadType rt = ROADTYPE_BEGIN; rt != ROADTYPE_END; rt++) { - RoadTypeInfo *rti = &_roadtypes[rt]; + _sorted_roadtypes.clear(); + for (RoadTypeInfo &rti : _roadtypes) { + RoadType rt = rti.Index(); + ResolveRoadTypeGUISprites(rti); - if (rti->flags.Test(RoadTypeFlag::Hidden)) _roadtypes_hidden_mask.Set(rt); - } + _roadtypes_hidden_mask.Set(rt, rti.flags.Test(RoadTypeFlag::Hidden)); - _sorted_roadtypes.clear(); - for (RoadType rt = ROADTYPE_BEGIN; rt != ROADTYPE_END; rt++) { - if (_roadtypes[rt].label == 0) continue; + if (rti.label == 0) continue; _sorted_roadtypes.push_back(rt); } std::sort(_sorted_roadtypes.begin(), _sorted_roadtypes.end(), CompareRoadTypes); @@ -129,43 +126,37 @@ void InitRoadTypes() */ RoadType AllocateRoadType(RoadTypeLabel label, RoadTramType rtt) { - for (RoadType rt = ROADTYPE_BEGIN; rt != ROADTYPE_END; rt++) { - RoadTypeInfo *rti = &_roadtypes[rt]; - - if (rti->label == 0) { - /* Set up new road type */ - *rti = _original_roadtypes[(rtt == RTT_TRAM) ? ROADTYPE_TRAM : ROADTYPE_ROAD]; - rti->label = label; - rti->alternate_labels.clear(); - rti->flags = {}; - rti->introduction_date = CalendarTime::INVALID_DATE; - - /* Make us compatible with ourself. */ - rti->powered_roadtypes = rt; - - /* We also introduce ourself. */ - rti->introduces_roadtypes = rt; - - /* Default sort order; order of allocation, but with some - * offsets so it's easier for NewGRF to pick a spot without - * changing the order of other (original) road types. - * The << is so you can place other roadtypes in between the - * other roadtypes, the 7 is to be able to place something - * before the first (default) road type. */ - rti->sorting_order = rt << 2 | 7; - - /* Set bitmap of road/tram types */ - if (rtt == RTT_TRAM) { - _roadtypes_tram.Set(rt); - } else { - _roadtypes_road.Set(rt); - } + auto it = std::ranges::find(_roadtypes, 0, &RoadTypeInfo::label); + if (it == std::end(_roadtypes)) it = _roadtypes.emplace(it, _original_roadtypes[(rtt == RTT_TRAM) ? ROADTYPE_TRAM : ROADTYPE_ROAD]); - return rt; - } - } + RoadTypeInfo &rti = *it; + RoadType rt = rti.Index(); + + /* Set up new road type */ + rti.label = label; + rti.alternate_labels.clear(); + rti.flags = {}; + rti.introduction_date = CalendarTime::INVALID_DATE; + + /* Make us compatible with ourself. */ + rti.powered_roadtypes = rt; + + /* We also introduce ourself. */ + rti.introduces_roadtypes = rt; - return INVALID_ROADTYPE; + /* Default sort order; order of allocation, but with some + * offsets so it's easier for NewGRF to pick a spot without + * changing the order of other (original) road types. + * The << is so you can place other roadtypes in between the + * other roadtypes, the 7 is to be able to place something + * before the first (default) road type. */ + rti.sorting_order = rt << 2 | 7; + + /* Set bitmap of road/tram types */ + _roadtypes_road.Set(rt, rtt == RTT_ROAD); + _roadtypes_tram.Set(rt, rtt == RTT_TRAM); + + return rt; } /** @@ -188,10 +179,12 @@ void UpdateCompanyRoadInfrastructure(RoadType rt, Owner o, int count) if (rt == INVALID_ROADTYPE) return; Company *c = Company::GetIfValid(o); - if (c == nullptr) return; - - c->infrastructure.road[rt] += count; - DirtyCompanyInfrastructureWindows(c->index); + if (c != nullptr) { + c->infrastructure.road[rt] += count; + DirtyCompanyInfrastructureWindows(c->index); + } else { + RoadTypeInfo::infrastructure_counts[rt] += count; + } } /** Invalid RoadBits on slopes. */ @@ -282,7 +275,7 @@ CommandCost CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, Owner owner, R /* check if you're allowed to remove the street owned by a town * removal allowance depends on difficulty setting */ - CommandCost ret = CheckforTownRating(flags, t, ROAD_REMOVE); + CommandCost ret = CheckforTownRating(flags, t, TownRatingCheckType::RoadRemove); if (ret.Failed()) return ret; /* Get a bitmask of which neighbouring roads has a tile */ @@ -371,8 +364,13 @@ static CommandCost RemoveRoad(TileIndex tile, DoCommandFlags flags, RoadBits pie /* A full diagonal road tile has two road bits. */ UpdateCompanyRoadInfrastructure(existing_rt, GetRoadOwner(tile, rtt), -(int)(len * 2 * TUNNELBRIDGE_TRACKBIT_FACTOR)); - SetRoadType(other_end, rtt, INVALID_ROADTYPE); - SetRoadType(tile, rtt, INVALID_ROADTYPE); + if (rtt == RTT_ROAD) { + SetMapRoadTypeRoad(other_end, RoadTypeMapping::INVALID_MAP_TYPE); + SetMapRoadTypeRoad(tile, RoadTypeMapping::INVALID_MAP_TYPE); + } else { /* rtt == RTT_TRAM */ + SetMapRoadTypeTram(other_end, TramTypeMapping::INVALID_MAP_TYPE); + SetMapRoadTypeTram(tile, TramTypeMapping::INVALID_MAP_TYPE); + } /* If the owner of the bridge sells all its road, also move the ownership * to the owner of the other roadtype, unless the bridge owner is a town. */ @@ -396,7 +394,11 @@ static CommandCost RemoveRoad(TileIndex tile, DoCommandFlags flags, RoadBits pie if (flags.Test(DoCommandFlag::Execute)) { /* A full diagonal road tile has two road bits. */ UpdateCompanyRoadInfrastructure(existing_rt, GetRoadOwner(tile, rtt), -2); - SetRoadType(tile, rtt, INVALID_ROADTYPE); + if (rtt == RTT_ROAD) { + SetMapRoadTypeRoad(tile, RoadTypeMapping::INVALID_MAP_TYPE); + } else { /* rtt == RTT_TRAM */ + SetMapRoadTypeTram(tile, TramTypeMapping::INVALID_MAP_TYPE); + } MarkTileDirtyByTile(tile); } } @@ -465,7 +467,11 @@ static CommandCost RemoveRoad(TileIndex tile, DoCommandFlags flags, RoadBits pie } if (rtt == RTT_ROAD) SetDisallowedRoadDirections(tile, DRD_NONE); SetRoadBits(tile, ROAD_NONE, rtt); - SetRoadType(tile, rtt, INVALID_ROADTYPE); + if (rtt == RTT_ROAD) { + SetMapRoadTypeRoad(tile, RoadTypeMapping::INVALID_MAP_TYPE); + } else { /* rtt == RTT_TRAM */ + SetMapRoadTypeTram(tile, TramTypeMapping::INVALID_MAP_TYPE); + } MarkTileDirtyByTile(tile); } } else { @@ -500,7 +506,7 @@ static CommandCost RemoveRoad(TileIndex tile, DoCommandFlags flags, RoadBits pie if (GetRoadType(tile, OtherRoadTramType(rtt)) == INVALID_ROADTYPE) { TrackBits tracks = GetCrossingRailBits(tile); bool reserved = HasCrossingReservation(tile); - MakeRailNormal(tile, GetTileOwner(tile), tracks, GetRailType(tile)); + MakeRailNormal(tile, GetTileOwner(tile), tracks, GetMapRailType(tile)); if (reserved) SetTrackReservation(tile, tracks); /* Update rail count for level crossings. The plain track should still be accounted @@ -511,7 +517,11 @@ static CommandCost RemoveRoad(TileIndex tile, DoCommandFlags flags, RoadBits pie DirtyCompanyInfrastructureWindows(c->index); } } else { - SetRoadType(tile, rtt, INVALID_ROADTYPE); + if (rtt == RTT_ROAD) { + SetMapRoadTypeRoad(tile, RoadTypeMapping::INVALID_MAP_TYPE); + } else { /* rtt == RTT_TRAM */ + SetMapRoadTypeTram(tile, TramTypeMapping::INVALID_MAP_TYPE); + } } MarkTileDirtyByTile(tile); YapfNotifyTrackLayoutChange(tile, railtrack); @@ -634,6 +644,11 @@ CommandCost CmdBuildRoad(DoCommandFlags flags, TileIndex tile, RoadBits pieces, Slope tileh = GetTileSlope(tile); RoadTramType rtt = GetRoadTramType(rt); + MapRoadType map_roadtype = rtt == RTT_ROAD ? _roadtype_mapping.AllocateMapType(rt, flags.Test(DoCommandFlag::Execute)) : RoadTypeMapping::INVALID_MAP_TYPE; + if (rtt == RTT_ROAD && map_roadtype == RoadTypeMapping::INVALID_MAP_TYPE) return CommandCost{STR_ERROR_TOO_MANY_ROADTYPES}; + MapTramType map_tramtype = rtt == RTT_TRAM ? _tramtype_mapping.AllocateMapType(rt, flags.Test(DoCommandFlag::Execute)) : TramTypeMapping::INVALID_MAP_TYPE; + if (rtt == RTT_TRAM && map_tramtype == TramTypeMapping::INVALID_MAP_TYPE) return CommandCost{STR_ERROR_TOO_MANY_TRAMTYPES}; + bool need_to_clear = false; switch (GetTileType(tile)) { case MP_ROAD: @@ -771,7 +786,7 @@ CommandCost CmdBuildRoad(DoCommandFlags flags, TileIndex tile, RoadBits pieces, /* Always add road to the roadtypes (can't draw without it) */ bool reserved = HasBit(GetRailReservationTrackBits(tile), railtrack); - MakeRoadCrossing(tile, company, company, GetTileOwner(tile), roaddir, GetRailType(tile), rtt == RTT_ROAD ? rt : INVALID_ROADTYPE, (rtt == RTT_TRAM) ? rt : INVALID_ROADTYPE, town_id); + MakeRoadCrossing(tile, company, company, GetTileOwner(tile), roaddir, GetMapRailType(tile), map_roadtype, map_tramtype, town_id); SetCrossingReservation(tile, reserved); UpdateLevelCrossing(tile, false); MarkDirtyAdjacentLevelCrossingTiles(tile, GetCrossingRoadAxis(tile)); @@ -880,7 +895,7 @@ do_clear:; case MP_ROAD: { RoadTileType rttype = GetRoadTileType(tile); if (existing == ROAD_NONE || rttype == ROAD_TILE_CROSSING) { - SetRoadType(tile, rtt, rt); + SetMapRoadTypes(tile, map_roadtype, map_tramtype, rtt); SetRoadOwner(tile, rtt, company); if (rtt == RTT_ROAD) SetTownIndex(tile, town_id); } @@ -891,8 +906,8 @@ do_clear:; case MP_TUNNELBRIDGE: { TileIndex other_end = GetOtherTunnelBridgeEnd(tile); - SetRoadType(other_end, rtt, rt); - SetRoadType(tile, rtt, rt); + SetMapRoadTypes(other_end, map_roadtype, map_tramtype, rtt); + SetMapRoadTypes(tile, map_roadtype, map_tramtype, rtt); SetRoadOwner(other_end, rtt, company); SetRoadOwner(tile, rtt, company); @@ -908,13 +923,13 @@ do_clear:; case MP_STATION: { assert(IsDriveThroughStopTile(tile)); - SetRoadType(tile, rtt, rt); + SetMapRoadTypes(tile, map_roadtype, map_tramtype, rtt); SetRoadOwner(tile, rtt, company); break; } default: - MakeRoadNormal(tile, pieces, (rtt == RTT_ROAD) ? rt : INVALID_ROADTYPE, (rtt == RTT_TRAM) ? rt : INVALID_ROADTYPE, town_id, company, company); + MakeRoadNormal(tile, pieces, map_roadtype, map_tramtype, town_id, company, company); break; } @@ -1178,12 +1193,19 @@ CommandCost CmdBuildRoadDepot(DoCommandFlags flags, TileIndex tile, RoadType rt, if (!Depot::CanAllocateItem()) return CMD_ERROR; } + RoadTramType rtt = GetRoadTramType(rt); + + MapRoadType map_roadtype = rtt == RTT_ROAD ? _roadtype_mapping.AllocateMapType(rt, flags.Test(DoCommandFlag::Execute)) : RoadTypeMapping::INVALID_MAP_TYPE; + if (rtt == RTT_ROAD && map_roadtype == RoadTypeMapping::INVALID_MAP_TYPE) return CommandCost{STR_ERROR_TOO_MANY_ROADTYPES}; + MapTramType map_tramtype = rtt == RTT_TRAM ? _tramtype_mapping.AllocateMapType(rt, flags.Test(DoCommandFlag::Execute)) : TramTypeMapping::INVALID_MAP_TYPE; + if (rtt == RTT_TRAM && map_tramtype == TramTypeMapping::INVALID_MAP_TYPE) return CommandCost{STR_ERROR_TOO_MANY_TRAMTYPES}; + if (flags.Test(DoCommandFlag::Execute)) { if (rotate_existing_depot) { SetRoadDepotExitDirection(tile, dir); } else { Depot *dep = new Depot(tile); - MakeRoadDepot(tile, _current_company, dep->index, dir, rt); + MakeRoadDepot(tile, _current_company, dep->index, dir, map_roadtype, map_tramtype); MakeDefaultName(dep); /* A road depot has two road bits. */ @@ -2077,8 +2099,9 @@ static void TileLoop_Road(TileIndex tile) /* Possibly change road type */ if (GetRoadOwner(tile, RTT_ROAD) == OWNER_TOWN) { RoadType rt = GetTownRoadType(); - if (rt != GetRoadTypeRoad(tile)) { - SetRoadType(tile, RTT_ROAD, rt); + MapRoadType map_roadtype = _roadtype_mapping.AllocateMapType(rt, true); + if (map_roadtype != RoadTypeMapping::INVALID_MAP_TYPE && map_roadtype != GetMapRoadTypeRoad(tile)) { + SetMapRoadTypeRoad(tile, map_roadtype); } } @@ -2322,7 +2345,11 @@ static void ChangeTileOwner_Road(TileIndex tile, Owner old_owner, Owner new_owne /* A level crossing has two road bits. No need to dirty windows here, we'll redraw the whole screen anyway. */ uint num_bits = IsLevelCrossing(tile) ? 2 : CountBits(GetRoadBits(tile, rtt)); Company::Get(old_owner)->infrastructure.road[rt] -= num_bits; - if (new_owner != INVALID_OWNER) Company::Get(new_owner)->infrastructure.road[rt] += num_bits; + if (new_owner != INVALID_OWNER) { + Company::Get(new_owner)->infrastructure.road[rt] += num_bits; + } else { + RoadTypeInfo::infrastructure_counts[rt] += num_bits; + } } SetRoadOwner(tile, rtt, new_owner == INVALID_OWNER ? OWNER_NONE : new_owner); @@ -2414,6 +2441,8 @@ static void ConvertRoadTypeOwner(TileIndex tile, uint num_pieces, Owner owner, R switch (owner.base()) { case OWNER_NONE.base(): + RoadTypeInfo::infrastructure_counts[from_type] += num_pieces; + RoadTypeInfo::infrastructure_counts[to_type] += num_pieces; SetRoadOwner(tile, GetRoadTramType(to_type), (Owner)_current_company); UpdateCompanyRoadInfrastructure(to_type, _current_company, num_pieces); break; @@ -2451,6 +2480,11 @@ CommandCost CmdConvertRoad(DoCommandFlags flags, TileIndex tile, TileIndex area_ CommandCost error = CommandCost((rtt == RTT_TRAM) ? STR_ERROR_NO_SUITABLE_TRAMWAY : STR_ERROR_NO_SUITABLE_ROAD); // by default, there is no road to convert. bool found_convertible_road = false; // whether we actually did convert any road/tram (see bug #7633) + MapRoadType map_roadtype = rtt == RTT_ROAD ? _roadtype_mapping.AllocateMapType(to_type, flags.Test(DoCommandFlag::Execute)) : RoadTypeMapping::INVALID_MAP_TYPE; + if (rtt == RTT_ROAD && map_roadtype == RoadTypeMapping::INVALID_MAP_TYPE) return CommandCost{STR_ERROR_TOO_MANY_ROADTYPES}; + MapTramType map_tramtype = rtt == RTT_TRAM ? _tramtype_mapping.AllocateMapType(to_type, flags.Test(DoCommandFlag::Execute)) : TramTypeMapping::INVALID_MAP_TYPE; + if (rtt == RTT_TRAM && map_tramtype == TramTypeMapping::INVALID_MAP_TYPE) return CommandCost{STR_ERROR_TOO_MANY_TRAMTYPES}; + std::unique_ptr iter = TileIterator::Create(area_start, area_end, diagonal); for (; (tile = *iter) != INVALID_TILE; ++(*iter)) { /* Is road present on tile? */ @@ -2492,7 +2526,7 @@ CommandCost CmdConvertRoad(DoCommandFlags flags, TileIndex tile, TileIndex area_ * acceptance of destructive actions. */ if (owner == OWNER_TOWN) { Town *t = ClosestTownFromTile(tile, _settings_game.economy.dist_local_authority); - CommandCost ret = CheckforTownRating({}, t, tt == MP_TUNNELBRIDGE ? TUNNELBRIDGE_REMOVE : ROAD_REMOVE); + CommandCost ret = CheckforTownRating({}, t, tt == MP_TUNNELBRIDGE ? TownRatingCheckType::TunnelBridgeRemove : TownRatingCheckType::RoadRemove); if (ret.Failed()) { error = std::move(ret); continue; @@ -2536,7 +2570,7 @@ CommandCost CmdConvertRoad(DoCommandFlags flags, TileIndex tile, TileIndex area_ } /* Perform the conversion */ - SetRoadType(tile, rtt, to_type); + SetMapRoadTypes(tile, map_roadtype, map_tramtype, rtt); MarkTileDirtyByTile(tile); /* update power of train on this tile */ @@ -2596,8 +2630,8 @@ CommandCost CmdConvertRoad(DoCommandFlags flags, TileIndex tile, TileIndex area_ } /* Perform the conversion */ - SetRoadType(tile, rtt, to_type); - SetRoadType(endtile, rtt, to_type); + SetMapRoadTypes(tile, map_roadtype, map_tramtype, rtt); + SetMapRoadTypes(endtile, map_roadtype, map_tramtype, rtt); for (Vehicle *v : VehiclesOnTile(tile)) { if (v->type == VEH_ROAD) include(affected_rvs, RoadVehicle::From(v)->First()); diff --git a/src/road_cmd.h b/src/road_cmd.h index 24b4c2b636873..e309edc057e16 100644 --- a/src/road_cmd.h +++ b/src/road_cmd.h @@ -27,11 +27,11 @@ CommandCost CmdBuildRoad(DoCommandFlags flags, TileIndex tile, RoadBits pieces, CommandCost CmdBuildRoadDepot(DoCommandFlags flags, TileIndex tile, RoadType rt, DiagDirection dir); CommandCost CmdConvertRoad(DoCommandFlags flags, TileIndex tile, TileIndex area_start, RoadType to_type, bool diagonal); -DEF_CMD_TRAIT(CMD_BUILD_LONG_ROAD, CmdBuildLongRoad, CommandFlags({CommandFlag::Auto, CommandFlag::NoWater, CommandFlag::Deity}), CMDT_LANDSCAPE_CONSTRUCTION) -DEF_CMD_TRAIT(CMD_REMOVE_LONG_ROAD, CmdRemoveLongRoad, CommandFlags({CommandFlag::Auto, CommandFlag::NoTest}), CMDT_LANDSCAPE_CONSTRUCTION) // towns may disallow removing road bits (as they are connected) in test, but in exec they're removed and thus removing is allowed. -DEF_CMD_TRAIT(CMD_BUILD_ROAD, CmdBuildRoad, CommandFlags({CommandFlag::Auto, CommandFlag::NoWater, CommandFlag::Deity}), CMDT_LANDSCAPE_CONSTRUCTION) -DEF_CMD_TRAIT(CMD_BUILD_ROAD_DEPOT, CmdBuildRoadDepot, CommandFlags({CommandFlag::Auto, CommandFlag::NoWater}), CMDT_LANDSCAPE_CONSTRUCTION) -DEF_CMD_TRAIT(CMD_CONVERT_ROAD, CmdConvertRoad, {}, CMDT_LANDSCAPE_CONSTRUCTION) +DEF_CMD_TRAIT(CMD_BUILD_LONG_ROAD, CmdBuildLongRoad, CommandFlags({CommandFlag::Auto, CommandFlag::NoWater, CommandFlag::Deity}), CommandType::LandscapeConstruction) +DEF_CMD_TRAIT(CMD_REMOVE_LONG_ROAD, CmdRemoveLongRoad, CommandFlags({CommandFlag::Auto, CommandFlag::NoTest}), CommandType::LandscapeConstruction) // towns may disallow removing road bits (as they are connected) in test, but in exec they're removed and thus removing is allowed. +DEF_CMD_TRAIT(CMD_BUILD_ROAD, CmdBuildRoad, CommandFlags({CommandFlag::Auto, CommandFlag::NoWater, CommandFlag::Deity}), CommandType::LandscapeConstruction) +DEF_CMD_TRAIT(CMD_BUILD_ROAD_DEPOT, CmdBuildRoadDepot, CommandFlags({CommandFlag::Auto, CommandFlag::NoWater}), CommandType::LandscapeConstruction) +DEF_CMD_TRAIT(CMD_CONVERT_ROAD, CmdConvertRoad, {}, CommandType::LandscapeConstruction) CommandCallback CcPlaySound_CONSTRUCTION_OTHER; CommandCallback CcBuildRoadTunnel; diff --git a/src/road_func.h b/src/road_func.h index 8f7727af56b59..2ac9e529490ca 100644 --- a/src/road_func.h +++ b/src/road_func.h @@ -124,7 +124,7 @@ inline RoadBits AxisToRoadBits(Axis a) */ inline Money RoadMaintenanceCost(RoadType roadtype, uint32_t num, uint32_t total_num) { - assert(roadtype < ROADTYPE_END); + assert(roadtype < GetNumRoadTypes()); return (_price[PR_INFRASTRUCTURE_ROAD] * GetRoadTypeInfo(roadtype)->maintenance_multiplier * num * (1 + IntSqrt(total_num))) >> 12; } @@ -134,7 +134,7 @@ inline Money RoadMaintenanceCost(RoadType roadtype, uint32_t num, uint32_t total */ inline bool HasRoadCatenary(RoadType roadtype) { - assert(roadtype < ROADTYPE_END); + assert(roadtype < GetNumRoadTypes()); return GetRoadTypeInfo(roadtype)->flags.Test(RoadTypeFlag::Catenary); } @@ -151,7 +151,7 @@ bool HasRoadTypeAvail(CompanyID company, RoadType roadtype); bool ValParamRoadType(RoadType roadtype); RoadTypes GetCompanyRoadTypes(CompanyID company, bool introduces = true); RoadTypes GetRoadTypes(bool introduces); -RoadTypes AddDateIntroducedRoadTypes(RoadTypes current, TimerGameCalendar::Date date); +RoadTypes AddDateIntroducedRoadTypes(const RoadTypes ¤t, TimerGameCalendar::Date date); void UpdateLevelCrossing(TileIndex tile, bool sound = true, bool force_bar = false); void MarkDirtyAdjacentLevelCrossingTiles(TileIndex tile, Axis road_axis); diff --git a/src/road_gui.cpp b/src/road_gui.cpp index 46c59c82c914d..f8fe8d3c5e0c5 100644 --- a/src/road_gui.cpp +++ b/src/road_gui.cpp @@ -344,7 +344,7 @@ static bool RoadToolbar_CtrlChanged(Window *w) /** Road toolbar window handler. */ struct BuildRoadToolbarWindow : Window { RoadType roadtype = INVALID_ROADTYPE; ///< Road type to build. - int last_started_action = INVALID_WID_ROT; ///< Last started user action. + WidgetID last_started_action = INVALID_WIDGET; ///< Last started user action. BuildRoadToolbarWindow(WindowDesc &desc, WindowNumber window_number) : Window(desc), roadtype(_cur_roadtype) { @@ -653,7 +653,7 @@ struct BuildRoadToolbarWindow : Window { case WID_ROT_BUILD_TUNNEL: Command::Post(STR_ERROR_CAN_T_BUILD_TUNNEL_HERE, CcBuildRoadTunnel, - tile, TRANSPORT_ROAD, _cur_roadtype); + tile, TRANSPORT_ROAD, INVALID_RAILTYPE, _cur_roadtype); break; case WID_ROT_CONVERT_ROAD: @@ -724,6 +724,11 @@ struct BuildRoadToolbarWindow : Window { VpSelectTilesWithMethod(pt.x, pt.y, select_method); } + Point OnInitialPosition(int16_t sm_width, [[maybe_unused]] int16_t sm_height, [[maybe_unused]] int window_number) override + { + return AlignInitialConstructionToolbar(sm_width); + } + void OnPlaceMouseUp([[maybe_unused]] ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, [[maybe_unused]] Point pt, TileIndex start_tile, TileIndex end_tile) override { if (pt.x != -1) { @@ -731,7 +736,7 @@ struct BuildRoadToolbarWindow : Window { default: NOT_REACHED(); case DDSP_BUILD_BRIDGE: if (!_settings_client.gui.persistent_buildingtools) ResetObjectToPlace(); - ShowBuildBridgeWindow(start_tile, end_tile, TRANSPORT_ROAD, _cur_roadtype); + ShowBuildBridgeWindow(start_tile, end_tile, TRANSPORT_ROAD, INVALID_RAILTYPE, _cur_roadtype); break; case DDSP_DEMOLISH_AREA: @@ -813,7 +818,7 @@ struct BuildRoadToolbarWindow : Window { void OnPlacePresize([[maybe_unused]] Point pt, TileIndex tile) override { - Command::Do(DoCommandFlag::Auto, tile, TRANSPORT_ROAD, _cur_roadtype); + Command::Do(DoCommandFlag::Auto, tile, TRANSPORT_ROAD, INVALID_RAILTYPE, _cur_roadtype); VpSetPresizeRange(tile, _build_tunnel_endtile == 0 ? tile : _build_tunnel_endtile); } @@ -899,7 +904,7 @@ struct BuildRoadToolbarWindow : Window { }, TramToolbarGlobalHotkeys}; }; -static constexpr NWidgetPart _nested_build_road_widgets[] = { +static constexpr std::initializer_list _nested_build_road_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN), NWidget(WWT_CAPTION, COLOUR_DARK_GREEN, WID_ROT_CAPTION), SetTextStyle(TC_WHITE), @@ -939,14 +944,14 @@ static constexpr NWidgetPart _nested_build_road_widgets[] = { }; static WindowDesc _build_road_desc( - WDP_ALIGN_TOOLBAR, "toolbar_road", 0, 0, + WDP_MANUAL, "toolbar_road", 0, 0, WC_BUILD_TOOLBAR, WC_NONE, WindowDefaultFlag::Construction, _nested_build_road_widgets, &BuildRoadToolbarWindow::road_hotkeys ); -static constexpr NWidgetPart _nested_build_tramway_widgets[] = { +static constexpr std::initializer_list _nested_build_tramway_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN), NWidget(WWT_CAPTION, COLOUR_DARK_GREEN, WID_ROT_CAPTION), SetTextStyle(TC_WHITE), @@ -984,7 +989,7 @@ static constexpr NWidgetPart _nested_build_tramway_widgets[] = { }; static WindowDesc _build_tramway_desc( - WDP_ALIGN_TOOLBAR, "toolbar_tramway", 0, 0, + WDP_MANUAL, "toolbar_tramway", 0, 0, WC_BUILD_TOOLBAR, WC_NONE, WindowDefaultFlag::Construction, _nested_build_tramway_widgets, @@ -1009,7 +1014,7 @@ Window *ShowBuildRoadToolbar(RoadType roadtype) return AllocateWindowDescFront(RoadTypeIsRoad(_cur_roadtype) ? _build_road_desc : _build_tramway_desc, TRANSPORT_ROAD); } -static constexpr NWidgetPart _nested_build_road_scen_widgets[] = { +static constexpr std::initializer_list _nested_build_road_scen_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN), NWidget(WWT_CAPTION, COLOUR_DARK_GREEN, WID_ROT_CAPTION), SetTextStyle(TC_WHITE), @@ -1048,7 +1053,7 @@ static WindowDesc _build_road_scen_desc( &BuildRoadToolbarWindow::road_hotkeys ); -static constexpr NWidgetPart _nested_build_tramway_scen_widgets[] = { +static constexpr std::initializer_list _nested_build_tramway_scen_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN), NWidget(WWT_CAPTION, COLOUR_DARK_GREEN, WID_ROT_CAPTION), SetTextStyle(TC_WHITE), @@ -1155,7 +1160,7 @@ struct BuildRoadDepotWindow : public PickerWindowBase { } }; -static constexpr NWidgetPart _nested_build_road_depot_widgets[] = { +static constexpr std::initializer_list _nested_build_road_depot_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN), NWidget(WWT_CAPTION, COLOUR_DARK_GREEN, WID_BROD_CAPTION), SetStringTip(STR_BUILD_DEPOT_ROAD_ORIENTATION_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), @@ -1513,7 +1518,7 @@ struct BuildRoadStationWindow : public PickerWindow { }; /** Widget definition of the build road station window */ -static constexpr NWidgetPart _nested_road_station_picker_widgets[] = { +static constexpr std::initializer_list _nested_road_station_picker_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN), NWidget(WWT_CAPTION, COLOUR_DARK_GREEN, WID_BROS_CAPTION), @@ -1575,7 +1580,7 @@ static WindowDesc _road_station_picker_desc( ); /** Widget definition of the build tram station window */ -static constexpr NWidgetPart _nested_tram_station_picker_widgets[] = { +static constexpr std::initializer_list _nested_tram_station_picker_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN), NWidget(WWT_CAPTION, COLOUR_DARK_GREEN, WID_BROS_CAPTION), @@ -1714,7 +1719,7 @@ struct BuildRoadWaypointWindow : public PickerWindow { }; /** Nested widget definition for the build NewGRF road waypoint window */ -static constexpr NWidgetPart _nested_build_road_waypoint_widgets[] = { +static constexpr std::initializer_list _nested_build_road_waypoint_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN), NWidget(WWT_CAPTION, COLOUR_DARK_GREEN), SetStringTip(STR_WAYPOINT_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), @@ -1810,7 +1815,7 @@ DropDownList GetRoadTypeDropDownList(RoadTramTypes rtts, bool for_replacement, b std::string str = rti->max_speed > 0 ? GetString(STR_TOOLBAR_RAILTYPE_VELOCITY, rti->strings.menu_text, rti->max_speed / 2) : GetString(rti->strings.menu_text); - list.push_back(MakeDropDownListBadgeIconItem(badge_class_list, rti->badges, GSF_ROADTYPES, rti->introduction_date, d, rti->gui_sprites.build_x_road, PAL_NONE, std::move(str), rt, !avail_roadtypes.Test(rt))); + list.push_back(MakeDropDownListBadgeIconItem(badge_class_list, rti->badges, GSF_ROADTYPES, rti->introduction_date, RoadBuildCost(rt), d, rti->gui_sprites.build_x_road, PAL_NONE, std::move(str), rt, !avail_roadtypes.Test(rt))); } } @@ -1854,7 +1859,7 @@ DropDownList GetScenRoadTypeDropDownList(RoadTramTypes rtts) std::string str = rti->max_speed > 0 ? GetString(STR_TOOLBAR_RAILTYPE_VELOCITY, rti->strings.menu_text, rti->max_speed / 2) : GetString(rti->strings.menu_text); - list.push_back(MakeDropDownListBadgeIconItem(badge_class_list, rti->badges, GSF_ROADTYPES, rti->introduction_date, d, rti->gui_sprites.build_x_road, PAL_NONE, std::move(str), rt, !avail_roadtypes.Test(rt))); + list.push_back(MakeDropDownListBadgeIconItem(badge_class_list, rti->badges, GSF_ROADTYPES, rti->introduction_date, RoadBuildCost(rt), d, rti->gui_sprites.build_x_road, PAL_NONE, std::move(str), rt, !avail_roadtypes.Test(rt))); } if (list.empty()) { diff --git a/src/road_map.h b/src/road_map.h index f8436d4258c7f..98924e02c5ef3 100644 --- a/src/road_map.h +++ b/src/road_map.h @@ -17,7 +17,6 @@ #include "tile_map.h" #include "road_type.h" - /** The different types of road tiles. */ enum RoadTileType : uint8_t { ROAD_TILE_NORMAL, ///< Normal road @@ -144,21 +143,31 @@ inline void SetRoadBits(Tile t, RoadBits r, RoadTramType rtt) } } -inline RoadType GetRoadTypeRoad(Tile t) +inline MapRoadType GetMapRoadTypeRoad(Tile t) { assert(MayHaveRoad(t)); - return (RoadType)GB(t.m4(), 0, 6); + return static_cast(GB(t.m4(), 0, 6)); } -inline RoadType GetRoadTypeTram(Tile t) +inline MapTramType GetMapRoadTypeTram(Tile t) { assert(MayHaveRoad(t)); - return (RoadType)GB(t.m8(), 6, 6); + return static_cast(GB(t.m8(), 6, 6)); +} + +inline RoadType GetRoadTypeRoad(Tile t) +{ + return _roadtype_mapping.GetType(GetMapRoadTypeRoad(t)); +} + +inline RoadType GetRoadTypeTram(Tile t) +{ + return _tramtype_mapping.GetType(GetMapRoadTypeTram(t)); } inline RoadType GetRoadType(Tile t, RoadTramType rtt) { - return (rtt == RTT_TRAM) ? GetRoadTypeTram(t) : GetRoadTypeRoad(t); + return (rtt == RTT_ROAD) ? GetRoadTypeRoad(t) : GetRoadTypeTram(t); } /** @@ -170,20 +179,20 @@ inline RoadTypes GetPresentRoadTypes(Tile t) { RoadTypes result{}; if (MayHaveRoad(t)) { - if (GetRoadTypeRoad(t) != INVALID_ROADTYPE) result.Set(GetRoadTypeRoad(t)); - if (GetRoadTypeTram(t) != INVALID_ROADTYPE) result.Set(GetRoadTypeTram(t)); + if (GetMapRoadTypeRoad(t) != RoadTypeMapping::INVALID_MAP_TYPE) result.Set(_roadtype_mapping.GetType(GetMapRoadTypeRoad(t))); + if (GetMapRoadTypeTram(t) != TramTypeMapping::INVALID_MAP_TYPE) result.Set(_tramtype_mapping.GetType(GetMapRoadTypeTram(t))); } return result; } inline bool HasRoadTypeRoad(Tile t) { - return GetRoadTypeRoad(t) != INVALID_ROADTYPE; + return GetMapRoadTypeRoad(t) != RoadTypeMapping::INVALID_MAP_TYPE; } inline bool HasRoadTypeTram(Tile t) { - return GetRoadTypeTram(t) != INVALID_ROADTYPE; + return GetMapRoadTypeTram(t) != TramTypeMapping::INVALID_MAP_TYPE; } /** @@ -554,74 +563,72 @@ RoadBits GetAnyRoadBits(Tile tile, RoadTramType rtt, bool straight_tunnel_bridge /** * Set the road road type of a tile. * @param t The tile to change. - * @param rt The road type to set. + * @param map_roadtype The map road type to set. */ -inline void SetRoadTypeRoad(Tile t, RoadType rt) +inline void SetMapRoadTypeRoad(Tile t, MapRoadType map_roadtype) { assert(MayHaveRoad(t)); - assert(rt == INVALID_ROADTYPE || RoadTypeIsRoad(rt)); - SB(t.m4(), 0, 6, rt); + SB(t.m4(), 0, 6, map_roadtype.base()); } /** * Set the tram road type of a tile. * @param t The tile to change. - * @param rt The road type to set. + * @param map_tramtype The map tram type to set. */ -inline void SetRoadTypeTram(Tile t, RoadType rt) +inline void SetMapRoadTypeTram(Tile t, MapTramType map_tramtype) { assert(MayHaveRoad(t)); - assert(rt == INVALID_ROADTYPE || RoadTypeIsTram(rt)); - SB(t.m8(), 6, 6, rt); + SB(t.m8(), 6, 6, map_tramtype.base()); } /** - * Set the road type of a tile. - * @param t The tile to change. - * @param rtt Set road or tram type. - * @param rt The road type to set. + * Set the present road types of a tile. + * @param t The tile to change. + * @param map_roadtype The map road type to set for the tile. + * @param map_tramtype The map tram type to set for the tile. */ -inline void SetRoadType(Tile t, RoadTramType rtt, RoadType rt) +inline void SetMapRoadTypes(Tile t, MapRoadType map_roadtype, MapTramType map_tramtype) { - if (rtt == RTT_TRAM) { - SetRoadTypeTram(t, rt); - } else { - SetRoadTypeRoad(t, rt); - } + SetMapRoadTypeRoad(t, map_roadtype); + SetMapRoadTypeTram(t, map_tramtype); } + /** - * Set the present road types of a tile. + * Conditionally Set the present road types of a tile. * @param t The tile to change. - * @param road_rt The road roadtype to set for the tile. - * @param tram_rt The tram roadtype to set for the tile. + * @param map_roadtype The map road type to set for the tile. + * @param map_tramtype The map tram type to set for the tile. + * @param rtts Road Tram type bits to set. */ -inline void SetRoadTypes(Tile t, RoadType road_rt, RoadType tram_rt) +inline void SetMapRoadTypes(Tile t, MapRoadType map_roadtype, MapTramType map_tramtype, RoadTramType rtt) { - SetRoadTypeRoad(t, road_rt); - SetRoadTypeTram(t, tram_rt); + if (rtt == RTT_ROAD) SetMapRoadTypeRoad(t, map_roadtype); + if (rtt == RTT_TRAM) SetMapRoadTypeTram(t, map_tramtype); } /** * Make a normal road tile. * @param t Tile to make a normal road. * @param bits Road bits to set for all present road types. - * @param road_rt The road roadtype to set for the tile. - * @param tram_rt The tram roadtype to set for the tile. + * @param map_roadtype The map road type to set for the tile. + * @param map_tramtype The map tram type to set for the tile. * @param town Town ID if the road is a town-owned road. * @param road New owner of road. * @param tram New owner of tram tracks. */ -inline void MakeRoadNormal(Tile t, RoadBits bits, RoadType road_rt, RoadType tram_rt, TownID town, Owner road, Owner tram) +inline void MakeRoadNormal(Tile t, RoadBits bits, MapRoadType map_roadtype, MapTramType map_tramtype, TownID town, Owner road, Owner tram) { SetTileType(t, MP_ROAD); SetTileOwner(t, road); t.m2() = town.base(); - t.m3() = (tram_rt != INVALID_ROADTYPE ? bits : 0); - t.m5() = (road_rt != INVALID_ROADTYPE ? bits : 0) | ROAD_TILE_NORMAL << 6; - SB(t.m6(), 2, 4, 0); + t.m3() = (map_tramtype != TramTypeMapping::INVALID_MAP_TYPE ? bits : 0); + t.m5() = (map_roadtype != RoadTypeMapping::INVALID_MAP_TYPE ? bits : 0) | ROAD_TILE_NORMAL << 6; + SB(t.m6(), 2, 6, 0); t.m7() = 0; - SetRoadTypes(t, road_rt, tram_rt); + t.m8() = 0; + SetMapRoadTypes(t, map_roadtype, map_tramtype); SetRoadOwner(t, RTT_TRAM, tram); } @@ -632,23 +639,23 @@ inline void MakeRoadNormal(Tile t, RoadBits bits, RoadType road_rt, RoadType tra * @param tram New owner of tram tracks. * @param rail New owner of the rail track. * @param roaddir Axis of the road. - * @param rat New rail type. - * @param road_rt The road roadtype to set for the tile. - * @param tram_rt The tram roadtype to set for the tile. + * @param map_railtype New map rail type. + * @param map_roadtype The map road type to set for the tile. + * @param map_tramtype The map tram type to set for the tile. * @param town Town ID if the road is a town-owned road. */ -inline void MakeRoadCrossing(Tile t, Owner road, Owner tram, Owner rail, Axis roaddir, RailType rat, RoadType road_rt, RoadType tram_rt, TownID town) +inline void MakeRoadCrossing(Tile t, Owner road, Owner tram, Owner rail, Axis roaddir, MapRailType map_railtype, MapRoadType map_roadtype, MapTramType map_tramtype, TownID town) { SetTileType(t, MP_ROAD); SetTileOwner(t, rail); t.m2() = town.base(); t.m3() = 0; - t.m4() = INVALID_ROADTYPE; + t.m4() = RoadTypeMapping::INVALID_MAP_TYPE.base(); t.m5() = ROAD_TILE_CROSSING << 6 | roaddir; - SB(t.m6(), 2, 4, 0); + SB(t.m6(), 2, 6, 0); t.m7() = road.base(); - t.m8() = INVALID_ROADTYPE << 6 | rat; - SetRoadTypes(t, road_rt, tram_rt); + t.m8() = TramTypeMapping::INVALID_MAP_TYPE.base() << 6 | map_railtype.base(); + SetMapRoadTypes(t, map_roadtype, map_tramtype); SetRoadOwner(t, RTT_TRAM, tram); } @@ -669,20 +676,21 @@ inline void SetRoadDepotExitDirection(Tile tile, DiagDirection dir) * @param owner New owner of the depot. * @param depot_id New depot ID. * @param dir Direction of the depot exit. - * @param rt Road type of the depot. + * @param map_roadtype Map road type of the depot. + * @param map_tramtype Map road type of the depot. */ -inline void MakeRoadDepot(Tile tile, Owner owner, DepotID depot_id, DiagDirection dir, RoadType rt) +inline void MakeRoadDepot(Tile tile, Owner owner, DepotID depot_id, DiagDirection dir, MapRoadType map_roadtype, MapTramType map_tramtype) { SetTileType(tile, MP_ROAD); SetTileOwner(tile, owner); tile.m2() = depot_id.base(); tile.m3() = 0; - tile.m4() = INVALID_ROADTYPE; + tile.m4() = RoadTypeMapping::INVALID_MAP_TYPE.base(); tile.m5() = ROAD_TILE_DEPOT << 6 | dir; - SB(tile.m6(), 2, 4, 0); + SB(tile.m6(), 2, 6, 0); tile.m7() = owner.base(); - tile.m8() = INVALID_ROADTYPE << 6; - SetRoadType(tile, GetRoadTramType(rt), rt); + tile.m8() = TramTypeMapping::INVALID_MAP_TYPE.base() << 6; + SetMapRoadTypes(tile, map_roadtype, map_tramtype); SetRoadOwner(tile, RTT_TRAM, owner); } diff --git a/src/road_type.h b/src/road_type.h index 07a6deb69ec78..30f5491f95273 100644 --- a/src/road_type.h +++ b/src/road_type.h @@ -11,6 +11,8 @@ #define ROAD_TYPE_H #include "core/enum_type.hpp" +#include "core/flatset_type.hpp" +#include "transport_mapping.hpp" typedef uint32_t RoadTypeLabel; @@ -20,16 +22,31 @@ static const RoadTypeLabel ROADTYPE_LABEL_TRAM = 'ELRL'; /** * The different roadtypes we support */ -enum RoadType : uint8_t { +enum RoadType : uint16_t { ROADTYPE_BEGIN = 0, ///< Used for iterations ROADTYPE_ROAD = 0, ///< Basic road type ROADTYPE_TRAM = 1, ///< Trams - ROADTYPE_END = 63, ///< Used for iterations - INVALID_ROADTYPE = 63, ///< flag for invalid roadtype + INVALID_ROADTYPE = UINT16_MAX, ///< flag for invalid roadtype }; DECLARE_INCREMENT_DECREMENT_OPERATORS(RoadType) -using RoadTypes = EnumBitSet; +using RoadTypes = FlatBitSet; + +/** + * The different types of road type. + */ +enum RoadTramType : bool { + RTT_ROAD, ///< Road road type. + RTT_TRAM, ///< Tram road type. +}; + +enum RoadTramTypes : uint8_t { + RTTB_ROAD = 1 << RTT_ROAD, ///< Road road type bit. + RTTB_TRAM = 1 << RTT_TRAM, ///< Tram road type bit. +}; +DECLARE_ENUM_AS_BIT_SET(RoadTramTypes) + +static const RoadTramType _roadtramtypes[] = { RTT_ROAD, RTT_TRAM }; /** * Enumeration for the road parts on a tile. @@ -67,4 +84,17 @@ enum DisallowedRoadDirections : uint8_t { }; DECLARE_ENUM_AS_BIT_SET(DisallowedRoadDirections) +/** Mapped road type. */ +using RoadTypeMapping = TransportMapping; +extern RoadTypeMapping _roadtype_mapping; + +/** Mapped tram type. */ +using TramTypeMapping = TransportMapping; +extern TramTypeMapping _tramtype_mapping; + +/** Alias for mapped road type. */ +using MapRoadType = RoadTypeMapping::MapType; +/** Alias for mapped tram type. */ +using MapTramType = TramTypeMapping::MapType; + #endif /* ROAD_TYPE_H */ diff --git a/src/roadveh.h b/src/roadveh.h index 8657512d1e95f..5940380ff3c8d 100644 --- a/src/roadveh.h +++ b/src/roadveh.h @@ -272,7 +272,8 @@ struct RoadVehicle final : public GroundVehicle { */ inline uint16_t GetMaxTrackSpeed() const { - return GetRoadTypeInfo(GetRoadType(this->tile, GetRoadTramType(this->roadtype)))->max_speed; + RoadType rt = GetRoadType(this->tile, GetRoadTramType(this->roadtype)); + return GetRoadTypeInfo(rt)->max_speed; } /** diff --git a/src/roadveh_cmd.cpp b/src/roadveh_cmd.cpp index 2117b85159294..060ec3694b32d 100644 --- a/src/roadveh_cmd.cpp +++ b/src/roadveh_cmd.cpp @@ -28,7 +28,6 @@ #include "depot_map.h" #include "effectvehicle_func.h" #include "roadstop_base.h" -#include "spritecache.h" #include "core/random_func.hpp" #include "company_base.h" #include "core/backup_type.hpp" @@ -105,7 +104,7 @@ int RoadVehicle::GetDisplayImageWidth(Point *offset) const static void GetRoadVehIcon(EngineID engine, EngineImageType image_type, VehicleSpriteSeq *result) { const Engine *e = Engine::Get(engine); - uint8_t spritenum = e->u.road.image_index; + uint8_t spritenum = e->VehInfo().image_index; if (IsCustomVehicleSpriteNum(spritenum)) { GetCustomVehicleIcon(engine, DIR_W, image_type, result); @@ -203,7 +202,7 @@ static uint GetRoadVehLength(const RoadVehicle *v) /* Use callback 11 */ veh_len = GetVehicleCallback(CBID_VEHICLE_LENGTH, 0, 0, v->engine_type, v); } - if (veh_len == CALLBACK_FAILED) veh_len = e->u.road.shorten_factor; + if (veh_len == CALLBACK_FAILED) veh_len = e->VehInfo().shorten_factor; if (veh_len != 0) { length -= Clamp(veh_len, 0, VEHICLE_LENGTH - 1); } @@ -263,12 +262,12 @@ void RoadVehUpdateCache(RoadVehicle *v, bool same_length) CommandCost CmdBuildRoadVehicle(DoCommandFlags flags, TileIndex tile, const Engine *e, Vehicle **ret) { /* Check that the vehicle can drive on the road in question */ - RoadType rt = e->u.road.roadtype; + RoadType rt = e->VehInfo().roadtype; const RoadTypeInfo *rti = GetRoadTypeInfo(rt); if (!HasTileAnyRoadType(tile, rti->powered_roadtypes)) return CommandCost(STR_ERROR_DEPOT_WRONG_DEPOT_TYPE); if (flags.Test(DoCommandFlag::Execute)) { - const RoadVehicleInfo *rvi = &e->u.road; + const RoadVehicleInfo *rvi = &e->VehInfo(); RoadVehicle *v = new RoadVehicle(); *ret = v; @@ -1645,12 +1644,12 @@ static bool RoadVehController(RoadVehicle *v) Money RoadVehicle::GetRunningCost() const { const Engine *e = this->GetEngine(); - if (e->u.road.running_cost_class == INVALID_PRICE) return 0; + if (e->VehInfo().running_cost_class == INVALID_PRICE) return 0; - uint cost_factor = GetVehicleProperty(this, PROP_ROADVEH_RUNNING_COST_FACTOR, e->u.road.running_cost); + uint cost_factor = GetVehicleProperty(this, PROP_ROADVEH_RUNNING_COST_FACTOR, e->VehInfo().running_cost); if (cost_factor == 0) return 0; - return GetPrice(e->u.road.running_cost_class, cost_factor, e->GetGRF()); + return GetPrice(e->VehInfo().running_cost_class, cost_factor, e->GetGRF()); } bool RoadVehicle::Tick() diff --git a/src/roadveh_cmd.h b/src/roadveh_cmd.h index ed9a7a11c510b..1fd781f8dddb9 100644 --- a/src/roadveh_cmd.h +++ b/src/roadveh_cmd.h @@ -22,6 +22,6 @@ CommandCost CmdBuildRoadVehicle(DoCommandFlags flags, TileIndex tile, const Engi CommandCost CmdTurnRoadVeh(DoCommandFlags flags, VehicleID veh_id); -DEF_CMD_TRAIT(CMD_TURN_ROADVEH, CmdTurnRoadVeh, CommandFlag::Location, CMDT_VEHICLE_MANAGEMENT) +DEF_CMD_TRAIT(CMD_TURN_ROADVEH, CmdTurnRoadVeh, CommandFlag::Location, CommandType::VehicleManagement) #endif /* ROADVEH_CMD_H */ diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index 908249e53319b..9d1c80728b391 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -50,6 +50,8 @@ #include "../subsidy_base.h" #include "../subsidy_func.h" #include "../newgrf.h" +#include "../newgrf_railtype.h" +#include "../newgrf_roadtype.h" #include "../newgrf_station.h" #include "../engine_func.h" #include "../rail_gui.h" @@ -209,9 +211,9 @@ static void UpdateVoidTiles() for (uint y = 0; y < Map::SizeY(); y++) MakeVoid(TileXY(Map::MaxX(), y)); } -static inline RailType UpdateRailType(RailType rt, RailType min) +static inline MapRailType UpdateRailType(MapRailType rt, RailType min) { - return rt >= min ? (RailType)(rt + 1): rt; + return static_cast(rt.base() >= to_underlying(min) ? rt.base() + 1 : rt.base()); } /** @@ -552,6 +554,50 @@ static void StartScripts() ShowScriptDebugWindowIfScriptError(); } +/** + * Convert rail/road/tram tiles from raw types to mapped types. + */ +static void ConvertTransportMappings() +{ + auto convert_railtype = [](TileIndex t) { + SetMapRailType(t, _railtype_mapping.AllocateMapType(static_cast(GetMapRailType(t).base()), true)); + }; + auto convert_roadtype = [](TileIndex t) { + /* Tiles with roads have a sentinel value to indicate that road or tram is not used. */ + if (auto mrt = GetMapRoadTypeRoad(t); mrt != RoadTypeMapping::INVALID_MAP_TYPE) SetMapRoadTypeRoad(t, _roadtype_mapping.AllocateMapType(static_cast(mrt.base()), true)); + if (auto mtt = GetMapRoadTypeTram(t); mtt != TramTypeMapping::INVALID_MAP_TYPE) SetMapRoadTypeTram(t, _tramtype_mapping.AllocateMapType(static_cast(mtt.base()), true)); + }; + + for (auto t : Map::Iterate()) { + switch (GetTileType(t)) { + case MP_RAILWAY: + convert_railtype(t); + break; + + case MP_ROAD: + convert_roadtype(t); + if (IsLevelCrossingTile(t)) convert_railtype(t); + break; + + case MP_STATION: + if (HasStationRail(t)) convert_railtype(t); + if (IsAnyRoadStop(t)) convert_roadtype(t); + break; + + case MP_TUNNELBRIDGE: + switch (GetTunnelBridgeTransportType(t)) { + case TRANSPORT_RAIL: convert_railtype(t); break; + case TRANSPORT_ROAD: convert_roadtype(t); break; + default: break; + } + break; + + default: + break; + } + } +} + /** * Perform a (large) amount of savegame conversion *magic* in order to * load older savegames and to fill the caches for various purposes. @@ -1007,6 +1053,7 @@ bool AfterLoadGame() case MP_ROAD: t.m4() |= (t.m2() << 4); + if (GB(t.m5(), 4, 2) == ROAD_TILE_DEPOT) break; if ((GB(t.m5(), 4, 2) == ROAD_TILE_CROSSING ? (Owner)t.m3() : GetTileOwner(t)) == OWNER_TOWN) { SetTownIndex(t, CalcClosestTownFromTile(t)->index); } else { @@ -1191,24 +1238,24 @@ bool AfterLoadGame() for (auto t : Map::Iterate()) { switch (GetTileType(t)) { case MP_RAILWAY: - SetRailType(t, (RailType)GB(t.m3(), 0, 4)); + SetMapRailType(t, static_cast(GB(t.m3(), 0, 4))); break; case MP_ROAD: if (IsLevelCrossing(t)) { - SetRailType(t, (RailType)GB(t.m3(), 0, 4)); + SetMapRailType(t, static_cast(GB(t.m3(), 0, 4))); } break; case MP_STATION: if (HasStationRail(t)) { - SetRailType(t, (RailType)GB(t.m3(), 0, 4)); + SetMapRailType(t, static_cast(GB(t.m3(), 0, 4))); } break; case MP_TUNNELBRIDGE: if (GetTunnelBridgeTransportType(t) == TRANSPORT_RAIL) { - SetRailType(t, (RailType)GB(t.m3(), 0, 4)); + SetMapRailType(t, static_cast(GB(t.m3(), 0, 4))); } break; @@ -1231,7 +1278,7 @@ bool AfterLoadGame() t, GetTileOwner(t), axis == AXIS_X ? TRACK_BIT_Y : TRACK_BIT_X, - GetRailType(t) + GetMapRailType(t) ); } else { TownID town = IsTileOwner(t, OWNER_TOWN) ? ClosestTownFromTile(t, UINT_MAX)->index : TownID::Begin(); @@ -1318,11 +1365,12 @@ bool AfterLoadGame() } if (has_road) { - RoadType road_rt = HasBit(t.m7(), 6) ? ROADTYPE_ROAD : INVALID_ROADTYPE; - RoadType tram_rt = HasBit(t.m7(), 7) ? ROADTYPE_TRAM : INVALID_ROADTYPE; + /* Conversion from road type to mapped road type happens later. */ + MapRoadType map_roadtype = HasBit(t.m7(), 6) ? static_cast(ROADTYPE_ROAD) : RoadTypeMapping::INVALID_MAP_TYPE; + MapTramType map_tramtype = HasBit(t.m7(), 7) ? static_cast(ROADTYPE_TRAM) : TramTypeMapping::INVALID_MAP_TYPE; - assert(road_rt != INVALID_ROADTYPE || tram_rt != INVALID_ROADTYPE); - SetRoadTypes(t, road_rt, tram_rt); + assert(map_roadtype != RoadTypeMapping::INVALID_MAP_TYPE || map_tramtype != TramTypeMapping::INVALID_MAP_TYPE); + SetMapRoadTypes(t, map_roadtype, map_tramtype); SB(t.m7(), 6, 2, 0); // Clear pre-NRT road type bits. } } @@ -1343,24 +1391,24 @@ bool AfterLoadGame() for (const auto t : Map::Iterate()) { switch (GetTileType(t)) { case MP_RAILWAY: - SetRailType(t, UpdateRailType(GetRailType(t), min_rail)); + SetMapRailType(t, UpdateRailType(GetMapRailType(t), min_rail)); break; case MP_ROAD: if (IsLevelCrossing(t)) { - SetRailType(t, UpdateRailType(GetRailType(t), min_rail)); + SetMapRailType(t, UpdateRailType(GetMapRailType(t), min_rail)); } break; case MP_STATION: if (HasStationRail(t)) { - SetRailType(t, UpdateRailType(GetRailType(t), min_rail)); + SetMapRailType(t, UpdateRailType(GetMapRailType(t), min_rail)); } break; case MP_TUNNELBRIDGE: if (GetTunnelBridgeTransportType(t) == TRANSPORT_RAIL) { - SetRailType(t, UpdateRailType(GetRailType(t), min_rail)); + SetMapRailType(t, UpdateRailType(GetMapRailType(t), min_rail)); } break; @@ -1370,6 +1418,12 @@ bool AfterLoadGame() } } + PreloadRailTypeMaps(); + PreloadRoadTypeMaps(); + if (IsSavegameVersionBefore(SLV_TRANSPORT_TYPE_MAPPING)) { + ConvertTransportMappings(); + } + /* In version 16.1 of the savegame a company can decide if trains, which get * replaced, shall keep their old length. In all prior versions, just default * to false */ @@ -3120,7 +3174,7 @@ bool AfterLoadGame() /* Convert towns growth_rate and grow_counter to ticks */ for (Town *t : Town::Iterate()) { /* 0x8000 = TOWN_GROWTH_RATE_CUSTOM previously */ - if (t->growth_rate & 0x8000) SetBit(t->flags, TOWN_CUSTOM_GROWTH); + if (t->growth_rate & 0x8000) t->flags.Set(TownFlag::CustomGrowth); if (t->growth_rate != TOWN_GROWTH_RATE_NONE) { t->growth_rate = TownTicksToGameTicks(t->growth_rate & ~0x8000); } diff --git a/src/saveload/ai_sl.cpp b/src/saveload/ai_sl.cpp index 29f759361c899..e6e52f8217d00 100644 --- a/src/saveload/ai_sl.cpp +++ b/src/saveload/ai_sl.cpp @@ -111,7 +111,7 @@ struct AIPLChunkHandler : ChunkHandler { * latest version of the AI instead. */ config->Change(_ai_saveload_name, -1, false); if (!config->HasScript()) { - if (_ai_saveload_name.compare("%_dummy") != 0) { + if (_ai_saveload_name != "%_dummy") { Debug(script, 0, "The savegame has an AI by the name '{}', version {} which is no longer available.", _ai_saveload_name, _ai_saveload_version); Debug(script, 0, "Configuration switched to Random AI."); } @@ -136,7 +136,7 @@ struct AIPLChunkHandler : ChunkHandler { * latest version of the AI instead. */ config->Change(_ai_saveload_name, -1, false); if (!config->HasScript()) { - if (_ai_saveload_name.compare("%_dummy") != 0) { + if (_ai_saveload_name != "%_dummy") { Debug(script, 0, "The savegame has an AI by the name '{}', version {} which is no longer available.", _ai_saveload_name, _ai_saveload_version); Debug(script, 0, "A random other AI will be loaded in its place."); } else { diff --git a/src/saveload/company_sl.cpp b/src/saveload/company_sl.cpp index 679b42bded653..e171acea4a304 100644 --- a/src/saveload/company_sl.cpp +++ b/src/saveload/company_sl.cpp @@ -127,6 +127,7 @@ void AfterLoadCompanyStats() { /* Reset infrastructure statistics to zero. */ for (Company *c : Company::Iterate()) c->infrastructure = {}; + RoadTypeInfo::infrastructure_counts.clear(); /* Collect airport count. */ for (const Station *st : Station::Iterate()) { @@ -163,9 +164,16 @@ void AfterLoadCompanyStats() for (RoadTramType rtt : _roadtramtypes) { RoadType rt = GetRoadType(tile, rtt); if (rt == INVALID_ROADTYPE) continue; - c = Company::GetIfValid(IsRoadDepot(tile) ? GetTileOwner(tile) : GetRoadOwner(tile, rtt)); + /* A level crossings and depots have two road bits. */ - if (c != nullptr) c->infrastructure.road[rt] += IsNormalRoad(tile) ? CountBits(GetRoadBits(tile, rtt)) : 2; + uint num_pieces = IsNormalRoad(tile) ? CountBits(GetRoadBits(tile, rtt)) : 2; + + c = Company::GetIfValid(IsRoadDepot(tile) ? GetTileOwner(tile) : GetRoadOwner(tile, rtt)); + if (c != nullptr) { + c->infrastructure.road[rt] += num_pieces; + } else { + RoadTypeInfo::infrastructure_counts[rt] += num_pieces; + } } break; } @@ -188,7 +196,11 @@ void AfterLoadCompanyStats() RoadType rt = GetRoadType(tile, rtt); if (rt == INVALID_ROADTYPE) continue; c = Company::GetIfValid(GetRoadOwner(tile, rtt)); - if (c != nullptr) c->infrastructure.road[rt] += 2; // A road stop has two road bits. + if (c != nullptr) { + c->infrastructure.road[rt] += 2; // A road stop has two road bits. + } else { + RoadTypeInfo::infrastructure_counts[rt] += 2; + } } break; } @@ -246,7 +258,11 @@ void AfterLoadCompanyStats() RoadType rt = GetRoadType(tile, rtt); if (rt == INVALID_ROADTYPE) continue; c = Company::GetIfValid(GetRoadOwner(tile, rtt)); - if (c != nullptr) c->infrastructure.road[rt] += len * 2; // A full diagonal road has two road bits. + if (c != nullptr) { + c->infrastructure.road[rt] += len * 2; // A full diagonal road has two road bits. + } else { + RoadTypeInfo::infrastructure_counts[rt] += len * 2; + } } break; } @@ -445,11 +461,11 @@ class SlCompanyLiveries : public DefaultSaveLoadHandlerlivery[i], this->GetLoadDescription()); if (update_in_use && i != LS_DEFAULT) { - if (c->livery[i].in_use == 0) { + if (!c->livery[i].in_use.Any({Livery::Flag::Primary, Livery::Flag::Secondary})) { c->livery[i].colour1 = c->livery[LS_DEFAULT].colour1; c->livery[i].colour2 = c->livery[LS_DEFAULT].colour2; } else { - c->livery[i].in_use = 3; + c->livery[i].in_use = {Livery::Flag::Primary, Livery::Flag::Secondary}; } } } diff --git a/src/saveload/game_sl.cpp b/src/saveload/game_sl.cpp index d6a35ffa20424..82b2c783edcc3 100644 --- a/src/saveload/game_sl.cpp +++ b/src/saveload/game_sl.cpp @@ -80,7 +80,7 @@ struct GSDTChunkHandler : ChunkHandler { * latest version of the GameScript instead. */ config->Change(_game_saveload_name, -1, false); if (!config->HasScript()) { - if (_game_saveload_name.compare("%_dummy") != 0) { + if (_game_saveload_name != "%_dummy") { Debug(script, 0, "The savegame has an GameScript by the name '{}', version {} which is no longer available.", _game_saveload_name, _game_saveload_version); Debug(script, 0, "This game will continue to run without GameScript."); } else { diff --git a/src/saveload/labelmaps_sl.cpp b/src/saveload/labelmaps_sl.cpp index 6875cd9ca4ab1..c4167a3c7fd02 100644 --- a/src/saveload/labelmaps_sl.cpp +++ b/src/saveload/labelmaps_sl.cpp @@ -38,17 +38,25 @@ struct RAILChunkHandler : ChunkHandler { static inline const SaveLoad description[] = { SLE_VAR(LabelObject, label, SLE_UINT32), + SLE_VAR(LabelObject, index, SLE_UINT8), }; void Save() const override { SlTableHeader(description); + int index = 0; LabelObject lo; - for (RailType r = RAILTYPE_BEGIN; r != RAILTYPE_END; r++) { - lo.label = GetRailTypeInfo(r)->label; + for (const RailTypeInfo &rti : GetRailTypeInfo()) { + if (rti.label == 0) continue; - SlSetArrayIndex(r); + MapRailType map_railtype = _railtype_mapping.GetMappedType(rti.Index()); + if (map_railtype == RailTypeMapping::INVALID_MAP_TYPE) continue; + + lo.label = rti.label; + lo.index = map_railtype.base(); + + SlSetArrayIndex(index++); SlObject(&lo, description); } } @@ -56,13 +64,16 @@ struct RAILChunkHandler : ChunkHandler { void Load() const override { const std::vector slt = SlCompatTableHeader(description, _label_object_sl_compat); + bool convert = IsSavegameVersionBefore(SLV_TRANSPORT_TYPE_MAPPING); - _railtype_list.reserve(RAILTYPE_END); + _railtype_list.reserve(RailTypeMapping::MAX_SIZE); LabelObject lo; - while (SlIterateArray() != -1) { + int index; + while ((index = SlIterateArray()) != -1) { SlObject(&lo, slt); + if (convert) lo.index = index; _railtype_list.push_back(lo); } } @@ -73,6 +84,7 @@ struct ROTTChunkHandler : ChunkHandler { static inline const SaveLoad description[] = { SLE_VAR(LabelObject, label, SLE_UINT32), + SLE_VAR(LabelObject, index, SLE_UINT8), SLE_VAR(LabelObject, subtype, SLE_UINT8), }; @@ -80,13 +92,27 @@ struct ROTTChunkHandler : ChunkHandler { { SlTableHeader(description); + int index = 0; LabelObject lo; - for (RoadType r = ROADTYPE_BEGIN; r != ROADTYPE_END; r++) { - const RoadTypeInfo *rti = GetRoadTypeInfo(r); - lo.label = rti->label; - lo.subtype = GetRoadTramType(r); + for (const RoadTypeInfo &rti : GetRoadTypeInfo()) { + if (rti.label == 0) continue; + + if (GetRoadTramType(rti.Index()) == RTT_ROAD) { + MapRoadType map_roadtype = _roadtype_mapping.GetMappedType(rti.Index()); + if (map_roadtype == RoadTypeMapping::INVALID_MAP_TYPE) continue; + + lo.index = map_roadtype.base(); + } else { + MapTramType map_tramtype = _tramtype_mapping.GetMappedType(rti.Index()); + if (map_tramtype == TramTypeMapping::INVALID_MAP_TYPE) continue; + + lo.index = map_tramtype.base(); + } + + lo.label = rti.label; + lo.subtype = GetRoadTramType(rti.Index()); - SlSetArrayIndex(r); + SlSetArrayIndex(index++); SlObject(&lo, description); } } @@ -94,13 +120,16 @@ struct ROTTChunkHandler : ChunkHandler { void Load() const override { const std::vector slt = SlCompatTableHeader(description, _label_object_sl_compat); + bool convert = IsSavegameVersionBefore(SLV_TRANSPORT_TYPE_MAPPING); - _roadtype_list.reserve(ROADTYPE_END); + _roadtype_list.reserve(64); LabelObject lo; - while (SlIterateArray() != -1) { + int index; + while ((index = SlIterateArray()) != -1) { SlObject(&lo, slt); + if (convert) lo.index = index; _roadtype_list.push_back(lo); } } diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp index f602bd1524355..a6dd26e3cfbac 100644 --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -56,6 +56,18 @@ # include #endif +#ifdef WITH_LZO +#include +#endif + +#if defined(WITH_ZLIB) +#include +#endif /* WITH_ZLIB */ + +#if defined(WITH_LIBLZMA) +#include +#endif /* WITH_LIBLZMA */ + #include "table/strings.h" #include "../safeguards.h" @@ -2417,7 +2429,6 @@ struct FileWriter : SaveFilter { *******************************************/ #ifdef WITH_LZO -#include /** Buffer size for the LZO compressor */ static const uint LZO_BUFFER_SIZE = 8192; @@ -2546,7 +2557,6 @@ struct NoCompSaveFilter : SaveFilter { ********************************************/ #if defined(WITH_ZLIB) -#include /** Filter using Zlib compression. */ struct ZlibLoadFilter : LoadFilter { @@ -2665,7 +2675,6 @@ struct ZlibSaveFilter : SaveFilter { ********************************************/ #if defined(WITH_LIBLZMA) -#include /** * Have a copy of an initialised LZMA stream. We need this as it's @@ -2852,7 +2861,7 @@ static std::pair GetSavegameFormat(std::string_ std::string_view name = has_comp_level ? full_name.substr(0, separator) : full_name; for (const auto &slf : _saveload_formats) { - if (slf.init_write != nullptr && name.compare(slf.name) == 0) { + if (slf.init_write != nullptr && name == slf.name) { if (has_comp_level) { auto complevel = full_name.substr(separator + 1); diff --git a/src/saveload/saveload.h b/src/saveload/saveload.h index e27825a5dc9e3..5aa9427020cb3 100644 --- a/src/saveload/saveload.h +++ b/src/saveload/saveload.h @@ -412,6 +412,7 @@ enum SaveLoadVersion : uint16_t { SLV_DOCKS_UNDER_BRIDGES, ///< 360 PR#14594 Allow docks under bridges. SLV_LOCKS_UNDER_BRIDGES, ///< 361 PR#14595 Allow locks under bridges. SLV_ENGINE_MULTI_RAILTYPE, ///< 362 PR#14357 Train engines can have multiple railtypes. + SLV_TRANSPORT_TYPE_MAPPING, ///< 363 PR#..... Dynamic rail/road/tram type mapping. SL_MAX_VERSION, ///< Highest possible saveload version }; diff --git a/src/saveload/vehicle_sl.cpp b/src/saveload/vehicle_sl.cpp index 51ef51069d763..3532c6ce8706e 100644 --- a/src/saveload/vehicle_sl.cpp +++ b/src/saveload/vehicle_sl.cpp @@ -439,7 +439,7 @@ void AfterLoadVehiclesPhase2(bool part_of_load) if (rv->IsFrontEngine()) { rv->gcache.last_speed = rv->cur_speed; // update displayed road vehicle speed - rv->roadtype = Engine::Get(rv->engine_type)->u.road.roadtype; + rv->roadtype = Engine::Get(rv->engine_type)->VehInfo().roadtype; rv->compatible_roadtypes = GetRoadTypeInfo(rv->roadtype)->powered_roadtypes; RoadTramType rtt = GetRoadTramType(rv->roadtype); for (RoadVehicle *u = rv; u != nullptr; u = u->Next()) { diff --git a/src/saveload/waypoint_sl.cpp b/src/saveload/waypoint_sl.cpp index 58d014a15dd83..452b4e173f6a9 100644 --- a/src/saveload/waypoint_sl.cpp +++ b/src/saveload/waypoint_sl.cpp @@ -129,14 +129,15 @@ void MoveWaypointsToBaseStations() bool reserved = !IsSavegameVersionBefore(SLV_100) && HasBit(tile.m5(), 4); /* The tile really has our waypoint, so reassign the map array */ - MakeRailWaypoint(tile, GetTileOwner(tile), new_wp->index, (Axis)GB(tile.m5(), 0, 1), 0, GetRailType(tile)); + MakeRailWaypoint(tile, GetTileOwner(tile), new_wp->index, (Axis)GB(tile.m5(), 0, 1), 0, GetMapRailType(tile)); new_wp->facilities.Set(StationFacility::Train); new_wp->owner = GetTileOwner(tile); SetRailStationReservation(tile, reserved); if (wp.spec != nullptr) { - auto specindex = AllocateSpecToStation(wp.spec, new_wp, true); + auto specindex = AllocateSpecToStation(wp.spec, new_wp); + if (specindex.has_value()) AssignSpecToStation(wp.spec, new_wp, *specindex); SetCustomStationSpecIndex(tile, specindex.value_or(0)); } new_wp->rect.BeforeAddTile(tile, StationRect::ADD_FORCE); diff --git a/src/screenshot.cpp b/src/screenshot.cpp index 224241ec52a03..d06db8b15447a 100644 --- a/src/screenshot.cpp +++ b/src/screenshot.cpp @@ -46,12 +46,12 @@ uint _heightmap_highest_peak; ///< When saving a heightmap, this contain * If the selected provider is not found, then the first provider will be used instead. * @returns ScreenshotProvider, or null if none exist. */ -static ScreenshotProvider *GetScreenshotProvider() +static const ScreenshotProvider *GetScreenshotProvider() { - auto providers = ProviderManager::GetProviders(); + const auto &providers = ProviderManager::GetProviders(); if (providers.empty()) return nullptr; - auto it = std::ranges::find_if(providers, [](const auto &p) { return p->GetName() == _screenshot_format_name; }); + auto it = std::ranges::find(providers, _screenshot_format_name, &ScreenshotProvider::GetName); if (it != std::end(providers)) return *it; return providers.front(); diff --git a/src/screenshot_bmp.cpp b/src/screenshot_bmp.cpp index 6ad3c8dd9807f..260eefc6fa9f2 100644 --- a/src/screenshot_bmp.cpp +++ b/src/screenshot_bmp.cpp @@ -43,7 +43,7 @@ class ScreenshotProvider_Bmp : public ScreenshotProvider { public: ScreenshotProvider_Bmp() : ScreenshotProvider("bmp", "BMP", 10) {} - bool MakeImage(std::string_view name, const ScreenshotCallback &callb, uint w, uint h, int pixelformat, const Colour *palette) override + bool MakeImage(std::string_view name, const ScreenshotCallback &callb, uint w, uint h, int pixelformat, const Colour *palette) const override { uint bpp; // bytes per pixel switch (pixelformat) { diff --git a/src/screenshot_gui.cpp b/src/screenshot_gui.cpp index 49a2d73c48d82..5bb532dc50516 100644 --- a/src/screenshot_gui.cpp +++ b/src/screenshot_gui.cpp @@ -47,7 +47,7 @@ struct ScreenshotWindow : Window { } }; -static constexpr NWidgetPart _nested_screenshot[] = { +static constexpr std::initializer_list _nested_screenshot = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), NWidget(WWT_CAPTION, COLOUR_GREY), SetStringTip(STR_SCREENSHOT_CAPTION), diff --git a/src/screenshot_pcx.cpp b/src/screenshot_pcx.cpp index e3c4c70441f29..024609a21222f 100644 --- a/src/screenshot_pcx.cpp +++ b/src/screenshot_pcx.cpp @@ -41,7 +41,7 @@ class ScreenshotProvider_Pcx : public ScreenshotProvider { public: ScreenshotProvider_Pcx() : ScreenshotProvider("pcx", "PCX", 20) {} - bool MakeImage(std::string_view name, const ScreenshotCallback &callb, uint w, uint h, int pixelformat, const Colour *palette) override + bool MakeImage(std::string_view name, const ScreenshotCallback &callb, uint w, uint h, int pixelformat, const Colour *palette) const override { uint maxlines; uint y; diff --git a/src/screenshot_png.cpp b/src/screenshot_png.cpp index c0c868bbe0f52..b636861b649fb 100644 --- a/src/screenshot_png.cpp +++ b/src/screenshot_png.cpp @@ -31,7 +31,7 @@ class ScreenshotProvider_Png : public ScreenshotProvider { public: ScreenshotProvider_Png() : ScreenshotProvider("png", "PNG", 0) {} - bool MakeImage(std::string_view name, const ScreenshotCallback &callb, uint w, uint h, int pixelformat, const Colour *palette) override + bool MakeImage(std::string_view name, const ScreenshotCallback &callb, uint w, uint h, int pixelformat, const Colour *palette) const override { png_color rq[256]; uint i, y, n; diff --git a/src/screenshot_type.h b/src/screenshot_type.h index d93f7c20bb787..4859952899c76 100644 --- a/src/screenshot_type.h +++ b/src/screenshot_type.h @@ -36,7 +36,7 @@ class ScreenshotProvider : public PriorityBaseProvider { ProviderManager::Unregister(*this); } - virtual bool MakeImage(std::string_view name, const ScreenshotCallback &callb, uint w, uint h, int pixelformat, const Colour *palette) = 0; + virtual bool MakeImage(std::string_view name, const ScreenshotCallback &callb, uint w, uint h, int pixelformat, const Colour *palette) const = 0; }; #endif /* SCREENSHOT_TYPE_H */ diff --git a/src/script/api/ai_changelog.hpp b/src/script/api/ai_changelog.hpp index 9d976962a1405..dbb10f1df7460 100644 --- a/src/script/api/ai_changelog.hpp +++ b/src/script/api/ai_changelog.hpp @@ -29,7 +29,7 @@ * \li AICargo::CC_NON_POTABLE * \li AIVehicleList_Waypoint * \li AIError::ERR_BRIDGE_TOO_LOW - * \li AIRail::GetAllRailTypes + * \li AIEngine::GetAllRailTypes * * Other changes: * \li AIBridge::GetBridgeID renamed to AIBridge::GetBridgeType @@ -37,7 +37,7 @@ * \li AIList instances can now be saved * \li AIVehicleList_Station accepts an optional AIVehicle::VehicleType parameter * \li AIList instances can now be cloned - * \li AIRail::GetRailType will only return the first RailType of an engine, use AIRail::GetAllRailTypes instead + * \li AIEngine::GetRailType will only return the first RailType of an engine, use AIEngine::GetAllRailTypes instead * * \b 14.0 * diff --git a/src/script/api/game_changelog.hpp b/src/script/api/game_changelog.hpp index 4a3a3111abea9..4dbb379896ca0 100644 --- a/src/script/api/game_changelog.hpp +++ b/src/script/api/game_changelog.hpp @@ -29,8 +29,8 @@ * \li GSCargo::CC_NON_POTABLE * \li GSVehicleList_Waypoint * \li GSBaseStation::GetOwner - * \li GSError:ERR_BRIDGE_TOO_LOW - * \li GSRail::GetAllRailTypes + * \li GSError::ERR_BRIDGE_TOO_LOW + * \li GSEngine::GetAllRailTypes * * Other changes: * \li GSBridge::GetBridgeID renamed to GSBridge::GetBridgeType @@ -38,7 +38,7 @@ * \li GSList instances can now be saved * \li GSVehicleList_Station accepts an optional GSVehicle::VehicleType parameter * \li GSList instances can now be cloned - * \li GSRail::GetRailType will only return the first RailType of an engine, use GSRail::GetAllRailTypes instead + * \li GSEngine::GetRailType will only return the first RailType of an engine, use GSEngine::GetAllRailTypes instead * * \b 14.0 * diff --git a/src/script/api/script_bridge.cpp b/src/script/api/script_bridge.cpp index f96aaca887f0e..a5b71eee6c376 100644 --- a/src/script/api/script_bridge.cpp +++ b/src/script/api/script_bridge.cpp @@ -86,11 +86,11 @@ static void _DoCommandReturnBuildBridge1(class ScriptInstance &instance) case ScriptVehicle::VT_ROAD: ScriptObject::SetCallbackVariable(0, start.base()); ScriptObject::SetCallbackVariable(1, end.base()); - return ScriptObject::Command::Do(&::_DoCommandReturnBuildBridge1, end, start, TRANSPORT_ROAD, bridge_type, ScriptRoad::GetCurrentRoadType()); + return ScriptObject::Command::Do(&::_DoCommandReturnBuildBridge1, end, start, TRANSPORT_ROAD, bridge_type, INVALID_RAILTYPE, static_cast<::RoadType>(ScriptRoad::GetCurrentRoadType())); case ScriptVehicle::VT_RAIL: - return ScriptObject::Command::Do(end, start, TRANSPORT_RAIL, bridge_type, ScriptRail::GetCurrentRailType()); + return ScriptObject::Command::Do(end, start, TRANSPORT_RAIL, bridge_type, static_cast<::RailType>(ScriptRail::GetCurrentRailType()), INVALID_ROADTYPE); case ScriptVehicle::VT_WATER: - return ScriptObject::Command::Do(end, start, TRANSPORT_WATER, bridge_type, 0); + return ScriptObject::Command::Do(end, start, TRANSPORT_WATER, bridge_type, INVALID_RAILTYPE, INVALID_ROADTYPE); default: NOT_REACHED(); } } diff --git a/src/script/api/script_controller.cpp b/src/script/api/script_controller.cpp index 774b089ef5d4f..65c5970bda602 100644 --- a/src/script/api/script_controller.cpp +++ b/src/script/api/script_controller.cpp @@ -116,7 +116,7 @@ ScriptController::ScriptController(::CompanyID company) : LoadedLibraryList::iterator it = controller.loaded_library.find(library_name); if (it != controller.loaded_library.end()) { - fake_class = (*it).second; + fake_class = it->second; } else { int next_number = ++controller.loaded_library_count; diff --git a/src/script/api/script_engine.cpp b/src/script/api/script_engine.cpp index 873a1154b7407..13b1ad1ea3094 100644 --- a/src/script/api/script_engine.cpp +++ b/src/script/api/script_engine.cpp @@ -242,10 +242,9 @@ if (!IsValidEngine(engine_id)) return ScriptRail::RAILTYPE_INVALID; if (GetVehicleType(engine_id) != ScriptVehicle::VT_RAIL) return ScriptRail::RAILTYPE_INVALID; - auto railtype = ::RailVehInfo(engine_id)->railtypes.GetNthSetBit(0); - if (!railtype.has_value()) return ScriptRail::RAILTYPE_INVALID; + if (::RailVehInfo(engine_id)->railtypes.empty()) return ScriptRail::RAILTYPE_INVALID; - return static_cast(railtype.value()); + return static_cast(*::RailVehInfo(engine_id)->railtypes.begin()); } /* static */ ScriptList *ScriptEngine::GetAllRailTypes(EngineID engine_id) diff --git a/src/script/api/script_error.cpp b/src/script/api/script_error.cpp index 953e9d8d383a4..34c1dfb9d56ff 100644 --- a/src/script/api/script_error.cpp +++ b/src/script/api/script_error.cpp @@ -54,7 +54,7 @@ ScriptError::ScriptErrorMapString ScriptError::error_map_string = ScriptError::S ScriptErrorMap::iterator it = error_map.find(internal_string_id); if (it == error_map.end()) return ERR_UNKNOWN; - return (*it).second; + return it->second; } /* static */ void ScriptError::RegisterErrorMap(StringID internal_string_id, ScriptErrorType ai_error_msg) diff --git a/src/script/api/script_group.cpp b/src/script/api/script_group.cpp index 486032cd70090..5713fddc35ba5 100644 --- a/src/script/api/script_group.cpp +++ b/src/script/api/script_group.cpp @@ -241,7 +241,7 @@ EnforcePrecondition(ScriptCompany::Colours::COLOUR_INVALID, IsValidGroup(group_id)); const Group *g = ::Group::Get(group_id); - if (!HasBit(g->livery.in_use, 0)) return ScriptCompany::Colours::COLOUR_INVALID; + if (!g->livery.in_use.Test(Livery::Flag::Primary)) return ScriptCompany::Colours::COLOUR_INVALID; return (ScriptCompany::Colours)g->livery.colour1; } @@ -250,6 +250,6 @@ EnforcePrecondition(ScriptCompany::Colours::COLOUR_INVALID, IsValidGroup(group_id)); const Group *g = ::Group::Get(group_id); - if (!HasBit(g->livery.in_use, 1)) return ScriptCompany::Colours::COLOUR_INVALID; + if (!g->livery.in_use.Test(Livery::Flag::Secondary)) return ScriptCompany::Colours::COLOUR_INVALID; return (ScriptCompany::Colours)g->livery.colour2; } diff --git a/src/script/api/script_infrastructure.cpp b/src/script/api/script_infrastructure.cpp index 17e65e932b558..f74daa6f73754 100644 --- a/src/script/api/script_infrastructure.cpp +++ b/src/script/api/script_infrastructure.cpp @@ -21,17 +21,17 @@ /* static */ SQInteger ScriptInfrastructure::GetRailPieceCount(ScriptCompany::CompanyID company, ScriptRail::RailType railtype) { company = ScriptCompany::ResolveCompanyID(company); - if (company == ScriptCompany::COMPANY_INVALID || (::RailType)railtype >= RAILTYPE_END) return 0; + if (company == ScriptCompany::COMPANY_INVALID || (::RailType)railtype >= GetNumRailTypes()) return 0; - return ::Company::Get(ScriptCompany::FromScriptCompanyID(company))->infrastructure.rail[railtype]; + return ::Company::Get(ScriptCompany::FromScriptCompanyID(company))->infrastructure.GetRailCount(static_cast<::RailType>(railtype)); } /* static */ SQInteger ScriptInfrastructure::GetRoadPieceCount(ScriptCompany::CompanyID company, ScriptRoad::RoadType roadtype) { company = ScriptCompany::ResolveCompanyID(company); - if (company == ScriptCompany::COMPANY_INVALID || (::RoadType)roadtype >= ROADTYPE_END) return 0; + if (company == ScriptCompany::COMPANY_INVALID || (::RoadType)roadtype >= GetNumRoadTypes()) return 0; - return ::Company::Get(ScriptCompany::FromScriptCompanyID(company))->infrastructure.road[roadtype]; + return ::Company::Get(ScriptCompany::FromScriptCompanyID(company))->infrastructure.GetRoadCount(static_cast<::RoadType>(roadtype)); } /* static */ SQInteger ScriptInfrastructure::GetInfrastructurePieceCount(ScriptCompany::CompanyID company, Infrastructure infra_type) @@ -66,20 +66,22 @@ /* static */ Money ScriptInfrastructure::GetMonthlyRailCosts(ScriptCompany::CompanyID company, ScriptRail::RailType railtype) { + ::RailType rt = static_cast<::RailType>(railtype); company = ScriptCompany::ResolveCompanyID(company); - if (company == ScriptCompany::COMPANY_INVALID || (::RailType)railtype >= RAILTYPE_END || !_settings_game.economy.infrastructure_maintenance) return 0; + if (company == ScriptCompany::COMPANY_INVALID || rt >= GetNumRailTypes() || !_settings_game.economy.infrastructure_maintenance) return 0; const ::Company *c = ::Company::Get(ScriptCompany::FromScriptCompanyID(company)); - return ::RailMaintenanceCost((::RailType)railtype, c->infrastructure.rail[railtype], c->infrastructure.GetRailTotal()); + return ::RailMaintenanceCost(rt, c->infrastructure.GetRailCount(rt), c->infrastructure.GetRailTotal()); } /* static */ Money ScriptInfrastructure::GetMonthlyRoadCosts(ScriptCompany::CompanyID company, ScriptRoad::RoadType roadtype) { + ::RoadType rt = static_cast<::RoadType>(roadtype); company = ScriptCompany::ResolveCompanyID(company); - if (company == ScriptCompany::COMPANY_INVALID || (::RoadType)roadtype >= ROADTYPE_END || !_settings_game.economy.infrastructure_maintenance) return 0; + if (company == ScriptCompany::COMPANY_INVALID || rt >= GetNumRoadTypes() || !_settings_game.economy.infrastructure_maintenance) return 0; const ::Company *c = ::Company::Get(ScriptCompany::FromScriptCompanyID(company)); - return ::RoadMaintenanceCost((::RoadType)roadtype, c->infrastructure.road[roadtype], RoadTypeIsRoad((::RoadType)roadtype) ? c->infrastructure.GetRoadTotal() : c->infrastructure.GetTramTotal()); + return ::RoadMaintenanceCost(rt, c->infrastructure.GetRoadCount(rt), RoadTypeIsRoad(rt) ? c->infrastructure.GetRoadTotal() : c->infrastructure.GetTramTotal()); } /* static */ Money ScriptInfrastructure::GetMonthlyInfrastructureCosts(ScriptCompany::CompanyID company, Infrastructure infra_type) @@ -92,8 +94,8 @@ case INFRASTRUCTURE_RAIL: { Money cost; uint32_t rail_total = c->infrastructure.GetRailTotal(); - for (::RailType rt = ::RAILTYPE_BEGIN; rt != ::RAILTYPE_END; rt++) { - cost += RailMaintenanceCost(rt, c->infrastructure.rail[rt], rail_total); + for (const auto &[railtype, count] : c->infrastructure.rail) { + cost += RailMaintenanceCost(railtype, count, rail_total); } return cost; } @@ -105,8 +107,8 @@ Money cost; uint32_t road_total = c->infrastructure.GetRoadTotal(); uint32_t tram_total = c->infrastructure.GetTramTotal(); - for (::RoadType rt = ::ROADTYPE_BEGIN; rt != ::ROADTYPE_END; rt++) { - cost += RoadMaintenanceCost(rt, c->infrastructure.road[rt], RoadTypeIsRoad(rt) ? road_total : tram_total); + for (const auto &[roadtype, count] : c->infrastructure.road) { + cost += RoadMaintenanceCost(roadtype, count, RoadTypeIsRoad(roadtype) ? road_total : tram_total); } return cost; } diff --git a/src/script/api/script_list.cpp b/src/script/api/script_list.cpp index 134b80287b108..fc629d39fe820 100644 --- a/src/script/api/script_list.cpp +++ b/src/script/api/script_list.cpp @@ -95,12 +95,12 @@ class ScriptListSorterValueAscending : public ScriptListSorter { this->has_no_more_items = false; this->bucket_iter = this->list->buckets.begin(); - this->bucket_list = &(*this->bucket_iter).second; + this->bucket_list = &this->bucket_iter->second; this->bucket_list_iter = this->bucket_list->begin(); this->item_next = *this->bucket_list_iter; SQInteger item_current = this->item_next; - FindNext(); + this->FindNext(); return item_current; } @@ -121,14 +121,14 @@ class ScriptListSorterValueAscending : public ScriptListSorter { return; } - this->bucket_list_iter++; + ++this->bucket_list_iter; if (this->bucket_list_iter == this->bucket_list->end()) { - this->bucket_iter++; + ++this->bucket_iter; if (this->bucket_iter == this->list->buckets.end()) { this->bucket_list = nullptr; return; } - this->bucket_list = &(*this->bucket_iter).second; + this->bucket_list = &this->bucket_iter->second; this->bucket_list_iter = this->bucket_list->begin(); } this->item_next = *this->bucket_list_iter; @@ -139,7 +139,7 @@ class ScriptListSorterValueAscending : public ScriptListSorter { if (this->IsEnd()) return 0; SQInteger item_current = this->item_next; - FindNext(); + this->FindNext(); return item_current; } @@ -149,7 +149,7 @@ class ScriptListSorterValueAscending : public ScriptListSorter { /* If we remove the 'next' item, skip to the next */ if (item == this->item_next) { - FindNext(); + this->FindNext(); return; } } @@ -186,7 +186,7 @@ class ScriptListSorterValueDescending : public ScriptListSorter { /* Go to the end of the bucket-list */ this->bucket_iter = this->list->buckets.end(); --this->bucket_iter; - this->bucket_list = &(*this->bucket_iter).second; + this->bucket_list = &this->bucket_iter->second; /* Go to the end of the items in the bucket */ this->bucket_list_iter = this->bucket_list->end(); @@ -194,7 +194,7 @@ class ScriptListSorterValueDescending : public ScriptListSorter { this->item_next = *this->bucket_list_iter; SQInteger item_current = this->item_next; - FindNext(); + this->FindNext(); return item_current; } @@ -220,14 +220,12 @@ class ScriptListSorterValueDescending : public ScriptListSorter { this->bucket_list = nullptr; return; } - this->bucket_iter--; - this->bucket_list = &(*this->bucket_iter).second; + --this->bucket_iter; + this->bucket_list = &this->bucket_iter->second; /* Go to the end of the items in the bucket */ this->bucket_list_iter = this->bucket_list->end(); - --this->bucket_list_iter; - } else { - this->bucket_list_iter--; } + --this->bucket_list_iter; this->item_next = *this->bucket_list_iter; } @@ -236,7 +234,7 @@ class ScriptListSorterValueDescending : public ScriptListSorter { if (this->IsEnd()) return 0; SQInteger item_current = this->item_next; - FindNext(); + this->FindNext(); return item_current; } @@ -246,7 +244,7 @@ class ScriptListSorterValueDescending : public ScriptListSorter { /* If we remove the 'next' item, skip to the next */ if (item == this->item_next) { - FindNext(); + this->FindNext(); return; } } @@ -276,10 +274,10 @@ class ScriptListSorterItemAscending : public ScriptListSorter { this->has_no_more_items = false; this->item_iter = this->list->items.begin(); - this->item_next = (*this->item_iter).first; + this->item_next = this->item_iter->first; SQInteger item_current = this->item_next; - FindNext(); + this->FindNext(); return item_current; } @@ -297,8 +295,8 @@ class ScriptListSorterItemAscending : public ScriptListSorter { this->has_no_more_items = true; return; } - this->item_iter++; - if (this->item_iter != this->list->items.end()) item_next = (*this->item_iter).first; + ++this->item_iter; + if (this->item_iter != this->list->items.end()) this->item_next = this->item_iter->first; } SQInteger Next() override @@ -306,7 +304,7 @@ class ScriptListSorterItemAscending : public ScriptListSorter { if (this->IsEnd()) return 0; SQInteger item_current = this->item_next; - FindNext(); + this->FindNext(); return item_current; } @@ -316,7 +314,7 @@ class ScriptListSorterItemAscending : public ScriptListSorter { /* If we remove the 'next' item, skip to the next */ if (item == this->item_next) { - FindNext(); + this->FindNext(); return; } } @@ -350,10 +348,10 @@ class ScriptListSorterItemDescending : public ScriptListSorter { this->item_iter = this->list->items.end(); --this->item_iter; - this->item_next = (*this->item_iter).first; + this->item_next = this->item_iter->first; SQInteger item_current = this->item_next; - FindNext(); + this->FindNext(); return item_current; } @@ -375,9 +373,9 @@ class ScriptListSorterItemDescending : public ScriptListSorter { /* Use 'end' as marker for 'beyond begin' */ this->item_iter = this->list->items.end(); } else { - this->item_iter--; + --this->item_iter; } - if (this->item_iter != this->list->items.end()) item_next = (*this->item_iter).first; + if (this->item_iter != this->list->items.end()) this->item_next = this->item_iter->first; } SQInteger Next() override @@ -385,7 +383,7 @@ class ScriptListSorterItemDescending : public ScriptListSorter { if (this->IsEnd()) return 0; SQInteger item_current = this->item_next; - FindNext(); + this->FindNext(); return item_current; } @@ -395,7 +393,7 @@ class ScriptListSorterItemDescending : public ScriptListSorter { /* If we remove the 'next' item, skip to the next */ if (item == this->item_next) { - FindNext(); + this->FindNext(); return; } } @@ -412,9 +410,9 @@ bool ScriptList::SaveObject(HSQUIRRELVM vm) sq_pushbool(vm, this->sort_ascending ? SQTrue : SQFalse); sq_arrayappend(vm, -2); sq_newtable(vm); - for (ScriptListMap::iterator iter = this->items.begin(); iter != this->items.end(); iter++) { - sq_pushinteger(vm, iter->first); - sq_pushinteger(vm, iter->second); + for (const auto &item : this->items) { + sq_pushinteger(vm, item.first); + sq_pushinteger(vm, item.second); sq_rawset(vm, -3); } sq_arrayappend(vm, -2); @@ -509,13 +507,13 @@ void ScriptList::RemoveItem(SQInteger item) { this->modifications++; - ScriptListMap::iterator item_iter = this->items.find(item); + auto item_iter = this->items.find(item); if (item_iter == this->items.end()) return; SQInteger value = item_iter->second; this->sorter->Remove(item); - ScriptListBucket::iterator bucket_iter = this->buckets.find(value); + auto bucket_iter = this->buckets.find(value); assert(bucket_iter != this->buckets.end()); bucket_iter->second.erase(item); if (bucket_iter->second.empty()) this->buckets.erase(bucket_iter); @@ -558,7 +556,7 @@ SQInteger ScriptList::Count() SQInteger ScriptList::GetValue(SQInteger item) { - ScriptListMap::const_iterator item_iter = this->items.find(item); + auto item_iter = this->items.find(item); return item_iter == this->items.end() ? 0 : item_iter->second; } @@ -566,14 +564,14 @@ bool ScriptList::SetValue(SQInteger item, SQInteger value) { this->modifications++; - ScriptListMap::iterator item_iter = this->items.find(item); + auto item_iter = this->items.find(item); if (item_iter == this->items.end()) return false; SQInteger value_old = item_iter->second; if (value_old == value) return true; this->sorter->Remove(item); - ScriptListBucket::iterator bucket_iter = this->buckets.find(value_old); + auto bucket_iter = this->buckets.find(value_old); assert(bucket_iter != this->buckets.end()); bucket_iter->second.erase(item); if (bucket_iter->second.empty()) this->buckets.erase(bucket_iter); @@ -624,10 +622,9 @@ void ScriptList::AddList(ScriptList *list) this->buckets = list->buckets; this->modifications++; } else { - ScriptListMap *list_items = &list->items; - for (auto &it : *list_items) { - this->AddItem(it.first); - this->SetValue(it.first, it.second); + for (const auto &item : list->items) { + this->AddItem(item.first); + this->SetValue(item.first, item.second); } } } @@ -652,8 +649,8 @@ void ScriptList::RemoveAboveValue(SQInteger value) this->modifications++; for (ScriptListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) { - next_iter = iter; next_iter++; - if ((*iter).second > value) this->RemoveItem((*iter).first); + next_iter = std::next(iter); + if (iter->second > value) this->RemoveItem(iter->first); } } @@ -662,8 +659,8 @@ void ScriptList::RemoveBelowValue(SQInteger value) this->modifications++; for (ScriptListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) { - next_iter = iter; next_iter++; - if ((*iter).second < value) this->RemoveItem((*iter).first); + next_iter = std::next(iter); + if (iter->second < value) this->RemoveItem(iter->first); } } @@ -672,8 +669,8 @@ void ScriptList::RemoveBetweenValue(SQInteger start, SQInteger end) this->modifications++; for (ScriptListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) { - next_iter = iter; next_iter++; - if ((*iter).second > start && (*iter).second < end) this->RemoveItem((*iter).first); + next_iter = std::next(iter); + if (iter->second > start && iter->second < end) this->RemoveItem(iter->first); } } @@ -682,8 +679,8 @@ void ScriptList::RemoveValue(SQInteger value) this->modifications++; for (ScriptListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) { - next_iter = iter; next_iter++; - if ((*iter).second == value) this->RemoveItem((*iter).first); + next_iter = std::next(iter); + if (iter->second == value) this->RemoveItem(iter->first); } } @@ -701,10 +698,10 @@ void ScriptList::RemoveTop(SQInteger count) switch (this->sorter_type) { default: NOT_REACHED(); case SORT_BY_VALUE: - for (ScriptListBucket::iterator iter = this->buckets.begin(); iter != this->buckets.end(); iter = this->buckets.begin()) { - ScriptItemList *items = &(*iter).second; + for (auto iter = this->buckets.begin(); iter != this->buckets.end(); iter = this->buckets.begin()) { + ScriptItemList *items = &iter->second; size_t size = items->size(); - for (ScriptItemList::iterator iter = items->begin(); iter != items->end(); iter = items->begin()) { + for (auto iter = items->begin(); iter != items->end(); iter = items->begin()) { if (--count < 0) return; this->RemoveItem(*iter); /* When the last item is removed from the bucket, the bucket itself is removed. @@ -716,9 +713,9 @@ void ScriptList::RemoveTop(SQInteger count) break; case SORT_BY_ITEM: - for (ScriptListMap::iterator iter = this->items.begin(); iter != this->items.end(); iter = this->items.begin()) { + for (auto iter = this->items.begin(); iter != this->items.end(); iter = this->items.begin()) { if (--count < 0) return; - this->RemoveItem((*iter).first); + this->RemoveItem(iter->first); } break; } @@ -738,10 +735,10 @@ void ScriptList::RemoveBottom(SQInteger count) switch (this->sorter_type) { default: NOT_REACHED(); case SORT_BY_VALUE: - for (ScriptListBucket::reverse_iterator iter = this->buckets.rbegin(); iter != this->buckets.rend(); iter = this->buckets.rbegin()) { - ScriptItemList *items = &(*iter).second; + for (auto iter = this->buckets.rbegin(); iter != this->buckets.rend(); iter = this->buckets.rbegin()) { + ScriptItemList *items = &iter->second; size_t size = items->size(); - for (ScriptItemList::reverse_iterator iter = items->rbegin(); iter != items->rend(); iter = items->rbegin()) { + for (auto iter = items->rbegin(); iter != items->rend(); iter = items->rbegin()) { if (--count < 0) return; this->RemoveItem(*iter); /* When the last item is removed from the bucket, the bucket itself is removed. @@ -753,9 +750,9 @@ void ScriptList::RemoveBottom(SQInteger count) break; case SORT_BY_ITEM: - for (ScriptListMap::reverse_iterator iter = this->items.rbegin(); iter != this->items.rend(); iter = this->items.rbegin()) { + for (auto iter = this->items.rbegin(); iter != this->items.rend(); iter = this->items.rbegin()) { if (--count < 0) return; - this->RemoveItem((*iter).first); + this->RemoveItem(iter->first); } break; } @@ -766,11 +763,10 @@ void ScriptList::RemoveList(ScriptList *list) this->modifications++; if (list == this) { - Clear(); + this->Clear(); } else { - ScriptListMap *list_items = &list->items; - for (ScriptListMap::iterator iter = list_items->begin(); iter != list_items->end(); iter++) { - this->RemoveItem((*iter).first); + for (const auto &item : list->items) { + this->RemoveItem(item.first); } } } @@ -780,8 +776,8 @@ void ScriptList::KeepAboveValue(SQInteger value) this->modifications++; for (ScriptListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) { - next_iter = iter; next_iter++; - if ((*iter).second <= value) this->RemoveItem((*iter).first); + next_iter = std::next(iter); + if (iter->second <= value) this->RemoveItem(iter->first); } } @@ -790,8 +786,8 @@ void ScriptList::KeepBelowValue(SQInteger value) this->modifications++; for (ScriptListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) { - next_iter = iter; next_iter++; - if ((*iter).second >= value) this->RemoveItem((*iter).first); + next_iter = std::next(iter); + if (iter->second >= value) this->RemoveItem(iter->first); } } @@ -800,8 +796,8 @@ void ScriptList::KeepBetweenValue(SQInteger start, SQInteger end) this->modifications++; for (ScriptListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) { - next_iter = iter; next_iter++; - if ((*iter).second <= start || (*iter).second >= end) this->RemoveItem((*iter).first); + next_iter = std::next(iter); + if (iter->second <= start || iter->second >= end) this->RemoveItem(iter->first); } } @@ -810,8 +806,8 @@ void ScriptList::KeepValue(SQInteger value) this->modifications++; for (ScriptListMap::iterator next_iter, iter = this->items.begin(); iter != this->items.end(); iter = next_iter) { - next_iter = iter; next_iter++; - if ((*iter).second != value) this->RemoveItem((*iter).first); + next_iter = std::next(iter); + if (iter->second != value) this->RemoveItem(iter->first); } } @@ -848,7 +844,7 @@ SQInteger ScriptList::_get(HSQUIRRELVM vm) SQInteger idx; sq_getinteger(vm, 2, &idx); - ScriptListMap::const_iterator item_iter = this->items.find(idx); + auto item_iter = this->items.find(idx); if (item_iter == this->items.end()) return SQ_ERROR; sq_pushinteger(vm, item_iter->second); @@ -858,18 +854,32 @@ SQInteger ScriptList::_get(HSQUIRRELVM vm) SQInteger ScriptList::_set(HSQUIRRELVM vm) { if (sq_gettype(vm, 2) != OT_INTEGER) return SQ_ERROR; - if (sq_gettype(vm, 3) != OT_INTEGER && sq_gettype(vm, 3) != OT_NULL) { - return sq_throwerror(vm, "you can only assign integers to this list"); - } - SQInteger idx, val; + SQInteger idx; sq_getinteger(vm, 2, &idx); - if (sq_gettype(vm, 3) == OT_NULL) { - this->RemoveItem(idx); - return 0; + + /* Retrieve the return value */ + SQInteger val; + switch (sq_gettype(vm, 3)) { + case OT_NULL: + this->RemoveItem(idx); + return 0; + + case OT_BOOL: { + SQBool v; + sq_getbool(vm, 3, &v); + val = v ? 1 : 0; + break; + } + + case OT_INTEGER: + sq_getinteger(vm, 3, &val); + break; + + default: + return sq_throwerror(vm, "you can only assign integers to this list"); } - sq_getinteger(vm, 3, &val); if (!this->HasItem(idx)) { this->AddItem(idx, val); return 0; @@ -932,14 +942,14 @@ SQInteger ScriptList::Valuate(HSQUIRRELVM vm) /* Push the function to call */ sq_push(vm, 2); - for (ScriptListMap::iterator iter = this->items.begin(); iter != this->items.end(); iter++) { + for (const auto &item : this->items) { /* Check for changing of items. */ int previous_modification_count = this->modifications; /* Push the root table as instance object, this is what squirrel does for meta-functions. */ sq_pushroottable(vm); /* Push all arguments for the valuator function. */ - sq_pushinteger(vm, (*iter).first); + sq_pushinteger(vm, item.first); for (int i = 0; i < nparam - 1; i++) { sq_push(vm, i + 3); } @@ -980,7 +990,7 @@ SQInteger ScriptList::Valuate(HSQUIRRELVM vm) return sq_throwerror(vm, "modifying valuated list outside of valuator function"); } - this->SetValue((*iter).first, value); + this->SetValue(item.first, value); /* Pop the return value. */ sq_poptop(vm); diff --git a/src/script/api/script_rail.cpp b/src/script/api/script_rail.cpp index 592fed196a0f7..425a6e9da9e60 100644 --- a/src/script/api/script_rail.cpp +++ b/src/script/api/script_rail.cpp @@ -70,7 +70,7 @@ /* static */ bool ScriptRail::IsRailTypeAvailable(RailType rail_type) { EnforceDeityOrCompanyModeValid(false); - if ((::RailType)rail_type >= RAILTYPE_END) return false; + if ((::RailType)rail_type >= GetNumRailTypes()) return false; return ScriptCompanyMode::IsDeity() || ::HasRailTypeAvail(ScriptObject::GetCompany(), (::RailType)rail_type); } diff --git a/src/script/api/script_railtypelist.cpp b/src/script/api/script_railtypelist.cpp index c5344a43c9280..320eaf92c2b4b 100644 --- a/src/script/api/script_railtypelist.cpp +++ b/src/script/api/script_railtypelist.cpp @@ -19,7 +19,7 @@ ScriptRailTypeList::ScriptRailTypeList() EnforceDeityOrCompanyModeValid_Void(); bool is_deity = ScriptCompanyMode::IsDeity(); ::CompanyID owner = ScriptObject::GetCompany(); - for (RailType rt = RAILTYPE_BEGIN; rt != RAILTYPE_END; rt++) { + for (RailType rt = RAILTYPE_BEGIN; rt != GetNumRailTypes(); rt++) { if (is_deity || ::HasRailTypeAvail(owner, rt)) this->AddItem(rt); } } diff --git a/src/script/api/script_road.cpp b/src/script/api/script_road.cpp index 1a689f8647045..b8258165912a6 100644 --- a/src/script/api/script_road.cpp +++ b/src/script/api/script_road.cpp @@ -69,7 +69,7 @@ /* static */ bool ScriptRoad::IsRoadTypeAvailable(RoadType road_type) { EnforceDeityOrCompanyModeValid(false); - return (::RoadType)road_type < ROADTYPE_END && ::HasRoadTypeAvail(ScriptObject::GetCompany(), (::RoadType)road_type); + return (::RoadType)road_type < GetNumRoadTypes() && ::HasRoadTypeAvail(ScriptObject::GetCompany(), (::RoadType)road_type); } /* static */ ScriptRoad::RoadType ScriptRoad::GetCurrentRoadType() diff --git a/src/script/api/script_roadtypelist.cpp b/src/script/api/script_roadtypelist.cpp index b5c23c380262a..b1e4209c825ec 100644 --- a/src/script/api/script_roadtypelist.cpp +++ b/src/script/api/script_roadtypelist.cpp @@ -17,7 +17,7 @@ ScriptRoadTypeList::ScriptRoadTypeList(ScriptRoad::RoadTramTypes rtts) { EnforceDeityOrCompanyModeValid_Void(); ::CompanyID owner = ScriptObject::GetCompany(); - for (RoadType rt = ROADTYPE_BEGIN; rt != ROADTYPE_END; rt++) { + for (RoadType rt = ROADTYPE_BEGIN; rt != GetNumRoadTypes(); rt++) { if (!HasBit(rtts, GetRoadTramType(rt))) continue; if (::HasRoadTypeAvail(owner, rt)) this->AddItem(rt); } diff --git a/src/script/api/script_tunnel.cpp b/src/script/api/script_tunnel.cpp index ce7877dd8a561..06c3a8dfdc016 100644 --- a/src/script/api/script_tunnel.cpp +++ b/src/script/api/script_tunnel.cpp @@ -90,10 +90,10 @@ static void _DoCommandReturnBuildTunnel1(class ScriptInstance &instance) if (vehicle_type == ScriptVehicle::VT_RAIL) { /* For rail we do nothing special */ - return ScriptObject::Command::Do(start, TRANSPORT_RAIL, ScriptRail::GetCurrentRailType()); + return ScriptObject::Command::Do(start, TRANSPORT_RAIL, static_cast<::RailType>(ScriptRail::GetCurrentRailType()), INVALID_ROADTYPE); } else { ScriptObject::SetCallbackVariable(0, start.base()); - return ScriptObject::Command::Do(&::_DoCommandReturnBuildTunnel1, start, TRANSPORT_ROAD, ScriptRoad::GetCurrentRoadType()); + return ScriptObject::Command::Do(&::_DoCommandReturnBuildTunnel1, start, TRANSPORT_ROAD, INVALID_RAILTYPE, static_cast<::RoadType>(ScriptRoad::GetCurrentRoadType())); } } diff --git a/src/script/script_config.cpp b/src/script/script_config.cpp index a599a7e30a746..7243af22af08b 100644 --- a/src/script/script_config.cpp +++ b/src/script/script_config.cpp @@ -85,7 +85,7 @@ int ScriptConfig::GetSetting(const std::string &name) const { const auto it = this->settings.find(name); if (it == this->settings.end()) return this->info->GetSettingDefaultValue(name); - return (*it).second; + return it->second; } void ScriptConfig::SetSetting(std::string_view name, int value) diff --git a/src/script/script_gui.cpp b/src/script/script_gui.cpp index ece3632c6f71b..74d9a11b8cda9 100644 --- a/src/script/script_gui.cpp +++ b/src/script/script_gui.cpp @@ -244,7 +244,7 @@ struct ScriptListWindow : public Window { }; /** Widgets for the AI list window. */ -static constexpr NWidgetPart _nested_script_list_widgets[] = { +static constexpr std::initializer_list _nested_script_list_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_MAUVE), NWidget(WWT_CAPTION, COLOUR_MAUVE, WID_SCRL_CAPTION), @@ -555,7 +555,7 @@ struct ScriptSettingsWindow : public Window { }; /** Widgets for the Script settings window. */ -static constexpr NWidgetPart _nested_script_settings_widgets[] = { +static constexpr std::initializer_list _nested_script_settings_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_MAUVE), NWidget(WWT_CAPTION, COLOUR_MAUVE, WID_SCRS_CAPTION), @@ -1200,7 +1200,7 @@ std::unique_ptr MakeCompanyButtonRowsScriptDebug() } /** Widgets for the Script debug window. */ -static constexpr NWidgetPart _nested_script_debug_widgets[] = { +static constexpr std::initializer_list _nested_script_debug_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), NWidget(WWT_CAPTION, COLOUR_GREY), SetStringTip(STR_AI_DEBUG, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), diff --git a/src/settingentry_gui.cpp b/src/settingentry_gui.cpp index 1d86a49369df4..087cff205d00b 100644 --- a/src/settingentry_gui.cpp +++ b/src/settingentry_gui.cpp @@ -94,22 +94,22 @@ uint BaseSettingEntry::Draw(GameSettings *settings_ptr, int left, int right, int if (cur_row >= max_row) return cur_row; bool rtl = _current_text_dir == TD_RTL; - int offset = (rtl ? -(int)_setting_circle_size.width : (int)_setting_circle_size.width) / 2; + int offset = (rtl ? -static_cast(BaseSettingEntry::circle_size.width) : static_cast(BaseSettingEntry::circle_size.width)) / 2; int level_width = rtl ? -WidgetDimensions::scaled.hsep_indent : WidgetDimensions::scaled.hsep_indent; int x = rtl ? right : left; if (cur_row >= first_row) { PixelColour colour = GetColourGradient(COLOUR_ORANGE, SHADE_NORMAL); - y += (cur_row - first_row) * SETTING_HEIGHT; // Compute correct y start position + y += (cur_row - first_row) * BaseSettingEntry::line_height; // Compute correct y start position /* Draw vertical for parent nesting levels */ for (uint lvl = 0; lvl < this->level; lvl++) { - if (!HasBit(parent_last, lvl)) GfxDrawLine(x + offset, y, x + offset, y + SETTING_HEIGHT - 1, colour); + if (!HasBit(parent_last, lvl)) GfxDrawLine(x + offset, y, x + offset, y + BaseSettingEntry::line_height - 1, colour); x += level_width; } /* draw own |- prefix */ - int halfway_y = y + SETTING_HEIGHT / 2; - int bottom_y = flags.Test(SettingEntryFlag::LastField) ? halfway_y : y + SETTING_HEIGHT - 1; + int halfway_y = y + BaseSettingEntry::line_height / 2; + int bottom_y = flags.Test(SettingEntryFlag::LastField) ? halfway_y : y + BaseSettingEntry::line_height - 1; GfxDrawLine(x + offset, y, x + offset, bottom_y, colour); /* Small horizontal line from the last vertical line */ GfxDrawLine(x + offset, halfway_y, x + level_width - (rtl ? -WidgetDimensions::scaled.hsep_normal : WidgetDimensions::scaled.hsep_normal), halfway_y, colour); @@ -274,7 +274,7 @@ void SettingEntry::DrawSetting(GameSettings *settings_ptr, int left, int right, uint buttons_left = rtl ? right + 1 - SETTING_BUTTON_WIDTH : left; uint text_left = left + (rtl ? 0 : SETTING_BUTTON_WIDTH + WidgetDimensions::scaled.hsep_wide); uint text_right = right - (rtl ? SETTING_BUTTON_WIDTH + WidgetDimensions::scaled.hsep_wide : 0); - uint button_y = y + (SETTING_HEIGHT - SETTING_BUTTON_HEIGHT) / 2; + uint button_y = y + (BaseSettingEntry::line_height - SETTING_BUTTON_HEIGHT) / 2; /* We do not allow changes of some items when we are a client in a networkgame */ bool editable = sd->IsEditable(); @@ -293,7 +293,7 @@ void SettingEntry::DrawSetting(GameSettings *settings_ptr, int left, int right, editable && value != (sd->flags.Test(SettingFlag::GuiZeroIsSpecial) ? 0 : min_val), editable && static_cast(value) != max_val); } auto [param1, param2] = sd->GetValueParams(value); - DrawString(text_left, text_right, y + (SETTING_HEIGHT - GetCharacterHeight(FS_NORMAL)) / 2, GetString(sd->GetTitle(), STR_CONFIG_SETTING_VALUE, param1, param2), highlight ? TC_WHITE : TC_LIGHT_BLUE); + DrawString(text_left, text_right, y + (BaseSettingEntry::line_height - GetCharacterHeight(FS_NORMAL)) / 2, GetString(sd->GetTitle(), STR_CONFIG_SETTING_VALUE, param1, param2), highlight ? TC_WHITE : TC_LIGHT_BLUE); } /* == SettingsContainer methods == */ @@ -611,8 +611,8 @@ uint SettingsPage::Draw(GameSettings *settings_ptr, int left, int right, int y, void SettingsPage::DrawSetting(GameSettings *, int left, int right, int y, bool) const { bool rtl = _current_text_dir == TD_RTL; - DrawSprite((this->folded ? SPR_CIRCLE_FOLDED : SPR_CIRCLE_UNFOLDED), PAL_NONE, rtl ? right - _setting_circle_size.width : left, y + (SETTING_HEIGHT - _setting_circle_size.height) / 2); - DrawString(rtl ? left : left + _setting_circle_size.width + WidgetDimensions::scaled.hsep_normal, rtl ? right - _setting_circle_size.width - WidgetDimensions::scaled.hsep_normal : right, y + (SETTING_HEIGHT - GetCharacterHeight(FS_NORMAL)) / 2, this->title, TC_ORANGE); + DrawSprite((this->folded ? SPR_CIRCLE_FOLDED : SPR_CIRCLE_UNFOLDED), PAL_NONE, rtl ? right - BaseSettingEntry::circle_size.width : left, y + (BaseSettingEntry::line_height - BaseSettingEntry::circle_size.height) / 2); + DrawString(rtl ? left : left + BaseSettingEntry::circle_size.width + WidgetDimensions::scaled.hsep_normal, rtl ? right - BaseSettingEntry::circle_size.width - WidgetDimensions::scaled.hsep_normal : right, y + (BaseSettingEntry::line_height - GetCharacterHeight(FS_NORMAL)) / 2, this->title, TC_ORANGE); } /** Construct settings tree */ diff --git a/src/settingentry_gui.h b/src/settingentry_gui.h index 66c017b99f147..e23d54e8bf657 100644 --- a/src/settingentry_gui.h +++ b/src/settingentry_gui.h @@ -14,9 +14,6 @@ #include "settings_internal.h" #include "stringfilter_type.h" -extern Dimension _setting_circle_size; -extern int SETTING_HEIGHT; - /** * Flags for #SettingEntry * @note The #SEF_BUTTONS_MASK matches expectations of the formal parameter 'state' of #DrawArrowButtons @@ -86,6 +83,9 @@ struct BaseSettingEntry { virtual uint Draw(GameSettings *settings_ptr, int left, int right, int y, uint first_row, uint max_row, BaseSettingEntry *selected, uint cur_row = 0, uint parent_last = 0) const; + static inline Dimension circle_size; ///< Dimension of the circle +/- icon. + static inline int line_height; ///< Height of a single setting. + protected: virtual void DrawSetting(GameSettings *settings_ptr, int left, int right, int y, bool highlight) const = 0; }; diff --git a/src/settings.cpp b/src/settings.cpp index 9efb21a0572c8..1b90eb6140359 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -1547,7 +1547,7 @@ StringList GetGRFPresetList() ConfigIniFile ini(_config_file); for (const IniGroup &group : ini.groups) { - if (group.name.compare(0, 7, "preset-") == 0) { + if (group.name.starts_with("preset-")) { list.push_back(group.name.substr(7)); } } diff --git a/src/settings_cmd.h b/src/settings_cmd.h index 613fcfb42adfc..4210869eb97d9 100644 --- a/src/settings_cmd.h +++ b/src/settings_cmd.h @@ -15,7 +15,7 @@ CommandCost CmdChangeSetting(DoCommandFlags flags, const std::string &name, int32_t value); CommandCost CmdChangeCompanySetting(DoCommandFlags flags, const std::string &name, int32_t value); -DEF_CMD_TRAIT(CMD_CHANGE_SETTING, CmdChangeSetting, CommandFlags({CommandFlag::Server, CommandFlag::NoEst}), CMDT_SERVER_SETTING) -DEF_CMD_TRAIT(CMD_CHANGE_COMPANY_SETTING, CmdChangeCompanySetting, CommandFlag::NoEst, CMDT_COMPANY_SETTING) +DEF_CMD_TRAIT(CMD_CHANGE_SETTING, CmdChangeSetting, CommandFlags({CommandFlag::Server, CommandFlag::NoEst}), CommandType::ServerSetting) +DEF_CMD_TRAIT(CMD_CHANGE_COMPANY_SETTING, CmdChangeCompanySetting, CommandFlag::NoEst, CommandType::CompanySetting) #endif /* SETTINGS_CMD_H */ diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp index 034a5da24b965..806d37b688d03 100644 --- a/src/settings_gui.cpp +++ b/src/settings_gui.cpp @@ -84,8 +84,6 @@ static const uint32_t _autosave_dropdown_to_minutes[] = { 120, }; -Dimension _setting_circle_size; ///< Dimension of the circle +/- icon. This is here as not all users are within the class of the settings window. - /** * Get index of the current screen resolution. * @return Index of the current screen resolution if it is a known resolution, _resolutions.size() otherwise. @@ -204,7 +202,7 @@ static constexpr TextColour GAME_OPTIONS_LABEL = TC_LIGHT_BLUE; /** Colour for selected text of game options. */ static constexpr TextColour GAME_OPTIONS_SELECTED = TC_WHITE; -static constexpr NWidgetPart _nested_social_plugins_widgets[] = { +static constexpr std::initializer_list _nested_social_plugins_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_FRAME, GAME_OPTIONS_BACKGROUND, WID_GO_SOCIAL_PLUGIN_TITLE), SetTextStyle(GAME_OPTIONS_FRAME), NWidget(NWID_HORIZONTAL), SetPIP(0, WidgetDimensions::unscaled.hsep_normal, 0), @@ -219,7 +217,7 @@ static constexpr NWidgetPart _nested_social_plugins_widgets[] = { EndContainer(), }; -static constexpr NWidgetPart _nested_social_plugins_none_widgets[] = { +static constexpr std::initializer_list _nested_social_plugins_none_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_TEXT, INVALID_COLOUR), SetResize(1, 0), SetFill(1, 0), SetStringTip(STR_GAME_OPTIONS_SOCIAL_PLUGINS_NONE), SetTextStyle(GAME_OPTIONS_LABEL), EndContainer(), @@ -363,8 +361,6 @@ std::unique_ptr MakeNWidgetSocialPlugins() return std::make_unique(); } -int SETTING_HEIGHT = 11; ///< Height of a single setting in the tree view in pixels - static const StringID _game_settings_restrict_dropdown[] = { STR_CONFIG_SETTING_RESTRICT_BASIC, // RM_BASIC STR_CONFIG_SETTING_RESTRICT_ADVANCED, // RM_ADVANCED @@ -419,6 +415,7 @@ struct GameOptionsWindow : Window { bool reload = false; bool gui_scale_changed = false; int gui_scale = 0; + static inline int previous_gui_scale = 0; ///< Previous GUI scale. static inline WidgetID active_tab = WID_GO_TAB_GENERAL; GameOptionsWindow(WindowDesc &desc) : Window(desc), filter_editbox(50) @@ -453,7 +450,9 @@ struct GameOptionsWindow : Window { void OnInit() override { - _setting_circle_size = maxdim(GetSpriteSize(SPR_CIRCLE_FOLDED), GetSpriteSize(SPR_CIRCLE_UNFOLDED)); + BaseSettingEntry::circle_size = maxdim(GetSpriteSize(SPR_CIRCLE_FOLDED), GetSpriteSize(SPR_CIRCLE_UNFOLDED)); + BaseSettingEntry::line_height = std::max({static_cast(BaseSettingEntry::circle_size.height), SETTING_BUTTON_HEIGHT, GetCharacterHeight(FS_NORMAL)}) + WidgetDimensions::scaled.vsep_normal; + this->gui_scale = _gui_scale; } @@ -709,7 +708,7 @@ struct GameOptionsWindow : Window { case WID_GO_OPTIONSPANEL: { Rect tr = r.Shrink(WidgetDimensions::scaled.frametext, WidgetDimensions::scaled.framerect); - tr.top += this->warn_lines * SETTING_HEIGHT; + tr.top += this->warn_lines * BaseSettingEntry::line_height; uint last_row = this->vscroll->GetPosition() + this->vscroll->GetCapacity() - this->warn_lines; int next_row = GetSettingsTree().Draw(settings_ptr, tr.left, tr.right, tr.top, this->vscroll->GetPosition(), last_row, this->last_clicked); @@ -858,7 +857,7 @@ struct GameOptionsWindow : Window { } case WID_GO_OPTIONSPANEL: - fill.height = resize.height = SETTING_HEIGHT = std::max({(int)_setting_circle_size.height, SETTING_BUTTON_HEIGHT, GetCharacterHeight(FS_NORMAL)}) + WidgetDimensions::scaled.vsep_normal; + fill.height = resize.height = BaseSettingEntry::line_height; resize.width = 1; size.height = 8 * resize.height + WidgetDimensions::scaled.framerect.Vertical(); @@ -1078,9 +1077,12 @@ struct GameOptionsWindow : Window { case WID_GO_GUI_SCALE_AUTO: { if (_gui_scale_cfg == -1) { - _gui_scale_cfg = _gui_scale; + _gui_scale_cfg = this->previous_gui_scale; // Load the previous GUI scale this->SetWidgetLoweredState(WID_GO_GUI_SCALE_AUTO, false); + if (AdjustGUIZoom(false)) ReInitAllWindows(true); + this->gui_scale = _gui_scale; } else { + this->previous_gui_scale = _gui_scale; // Set the previous GUI scale value as the current one _gui_scale_cfg = -1; this->SetWidgetLoweredState(WID_GO_GUI_SCALE_AUTO, true); if (AdjustGUIZoom(false)) ReInitAllWindows(true); @@ -1271,7 +1273,7 @@ struct GameOptionsWindow : Window { Rect wi_rect; wi_rect.left = pt.x - (_current_text_dir == TD_RTL ? SETTING_BUTTON_WIDTH - 1 - x : x); wi_rect.right = wi_rect.left + SETTING_BUTTON_WIDTH - 1; - wi_rect.top = pt.y - rel_y + (SETTING_HEIGHT - SETTING_BUTTON_HEIGHT) / 2; + wi_rect.top = pt.y - rel_y + (BaseSettingEntry::line_height - SETTING_BUTTON_HEIGHT) / 2; wi_rect.bottom = wi_rect.top + SETTING_BUTTON_HEIGHT - 1; /* For dropdowns we also have to check the y position thoroughly, the mouse may not above the just opening dropdown */ @@ -1600,7 +1602,7 @@ struct GameOptionsWindow : Window { } }; -static constexpr NWidgetPart _nested_game_options_widgets[] = { +static constexpr std::initializer_list _nested_game_options_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, GAME_OPTIONS_BACKGROUND), NWidget(WWT_CAPTION, GAME_OPTIONS_BACKGROUND), SetStringTip(STR_GAME_OPTIONS_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), @@ -2140,7 +2142,7 @@ struct CustomCurrencyWindow : Window { } }; -static constexpr NWidgetPart _nested_cust_currency_widgets[] = { +static constexpr std::initializer_list _nested_cust_currency_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), NWidget(WWT_CAPTION, COLOUR_GREY), SetStringTip(STR_CURRENCY_WINDOW, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), diff --git a/src/settings_table.cpp b/src/settings_table.cpp index b75bd3afb6f39..1881cfd79e479 100644 --- a/src/settings_table.cpp +++ b/src/settings_table.cpp @@ -572,7 +572,7 @@ static void MaxVehiclesChanged(int32_t) */ static bool ReplaceAsteriskWithEmptyPassword(std::string &newval) { - if (newval.compare("*") == 0) newval.clear(); + if (newval == "*") newval.clear(); return true; } diff --git a/src/settings_type.h b/src/settings_type.h index 86350e405494e..25a8fd63dec3e 100644 --- a/src/settings_type.h +++ b/src/settings_type.h @@ -10,6 +10,7 @@ #ifndef SETTINGS_TYPE_H #define SETTINGS_TYPE_H +#include "command_type.h" #include "timer/timer_game_calendar.h" #include "economy_type.h" #include "town_type.h" @@ -64,6 +65,13 @@ enum IndustryDensity : uint8_t { ID_END, ///< Number of industry density settings. }; +/** Possible options for the Borders pulldown in the Genworld GUI. */ +enum BorderFlagPresets : uint8_t { + BFP_RANDOM = 0, + BFP_MANUAL, + BFP_INFINITE_WATER, +}; + /** Possible values for the "timekeeping_units" setting. */ enum TimekeepingUnits : uint8_t { TKU_CALENDAR = 0, @@ -375,6 +383,7 @@ struct GameCreationSettings { uint8_t town_name; ///< the town name generator used for town names LandscapeType landscape; ///< the landscape we're currently in BorderFlags water_borders; ///< bitset of the borders that are water + BorderFlagPresets water_border_presets; ///< presets for map border options uint16_t custom_town_number; ///< manually entered number of towns uint16_t custom_industry_number; ///< manually entered number of industries uint8_t variety; ///< variety level applied to TGP @@ -402,7 +411,7 @@ struct ConstructionSettings { uint8_t industry_platform; ///< the amount of flat land around an industry bool freeform_edges; ///< allow terraforming the tiles at the map edges uint8_t extra_tree_placement; ///< (dis)allow building extra trees in-game - uint8_t command_pause_level; ///< level/amount of commands that can't be executed while paused + CommandPauseLevel command_pause_level; ///< level/amount of commands that can't be executed while paused uint32_t terraform_per_64k_frames; ///< how many tile heights may, over a long period, be terraformed per 65536 frames? uint16_t terraform_frame_burst; ///< how many tile heights may, over a short period, be terraformed? diff --git a/src/ship_cmd.cpp b/src/ship_cmd.cpp index 434f85276317b..c976cabc0a296 100644 --- a/src/ship_cmd.cpp +++ b/src/ship_cmd.cpp @@ -19,7 +19,6 @@ #include "pathfinder/yapf/yapf.h" #include "pathfinder/yapf/yapf_ship_regions.h" #include "newgrf_sound.h" -#include "spritecache.h" #include "strings_func.h" #include "window_func.h" #include "timer/timer_game_calendar.h" @@ -81,7 +80,7 @@ static inline TrackBits GetTileShipTrackStatus(TileIndex tile) static void GetShipIcon(EngineID engine, EngineImageType image_type, VehicleSpriteSeq *result) { const Engine *e = Engine::Get(engine); - uint8_t spritenum = e->u.ship.image_index; + uint8_t spritenum = e->VehInfo().image_index; if (IsCustomVehicleSpriteNum(spritenum)) { GetCustomVehicleIcon(engine, DIR_W, image_type, result); @@ -247,7 +246,7 @@ void Ship::UpdateCache() Money Ship::GetRunningCost() const { const Engine *e = this->GetEngine(); - uint cost_factor = GetVehicleProperty(this, PROP_SHIP_RUNNING_COST_FACTOR, e->u.ship.running_cost); + uint cost_factor = GetVehicleProperty(this, PROP_SHIP_RUNNING_COST_FACTOR, e->VehInfo().running_cost); return GetPrice(PR_RUNNING_SHIP, cost_factor, e->GetGRF()); } @@ -359,7 +358,12 @@ static bool CheckReverseShip(const Ship *v, Trackdir *trackdir = nullptr) return YapfShipCheckReverse(v, trackdir); } -static bool CheckShipLeaveDepot(Ship *v) +/** + * Checks whether a ship should stay in the depot. + * @param v Ship to check. + * @return True if the ship should stay in the depot, false if it has to leave. + */ +static bool CheckShipStayInDepot(Ship *v) { if (!v->IsChainInDepot()) return false; @@ -382,34 +386,13 @@ static bool CheckShipLeaveDepot(Ship *v) return u->type == VEH_SHIP && u->cur_speed != 0; })) return true; - TileIndex tile = v->tile; - Axis axis = GetShipDepotAxis(tile); - - DiagDirection north_dir = ReverseDiagDir(AxisToDiagDir(axis)); - TileIndex north_neighbour = TileAdd(tile, TileOffsByDiagDir(north_dir)); - DiagDirection south_dir = AxisToDiagDir(axis); - TileIndex south_neighbour = TileAdd(tile, 2 * TileOffsByDiagDir(south_dir)); - - TrackBits north_tracks = DiagdirReachesTracks(north_dir) & GetTileShipTrackStatus(north_neighbour); - TrackBits south_tracks = DiagdirReachesTracks(south_dir) & GetTileShipTrackStatus(south_neighbour); - if (north_tracks && south_tracks) { - if (CheckReverseShip(v)) north_tracks = TRACK_BIT_NONE; - } + assert(v->GetVehicleTrackdir() == TRACKDIR_X_NE || v->GetVehicleTrackdir() == TRACKDIR_Y_NW); + v->direction = DiagDirToDir(TrackdirToExitdir(v->GetVehicleTrackdir())); + if (CheckReverseShip(v)) v->direction = ReverseDir(v->direction); - if (north_tracks) { - /* Leave towards north */ - v->rotation = v->direction = DiagDirToDir(north_dir); - } else if (south_tracks) { - /* Leave towards south */ - v->rotation = v->direction = DiagDirToDir(south_dir); - } else { - /* Both ways blocked */ - return false; - } - - v->state = AxisToTrackBits(axis); + v->state = AxisToTrackBits(GetShipDepotAxis(v->tile)); + v->rotation = v->direction; v->vehstatus.Reset(VehState::Hidden); - v->cur_speed = 0; v->UpdateViewport(true, true); SetWindowDirty(WC_VEHICLE_DEPOT, v->tile); @@ -698,7 +681,7 @@ static void ShipController(Ship *v) if (v->current_order.IsType(OT_LOADING)) return; - if (CheckShipLeaveDepot(v)) return; + if (CheckShipStayInDepot(v)) return; v->ShowVisualEffect(); @@ -886,7 +869,7 @@ CommandCost CmdBuildShip(DoCommandFlags flags, TileIndex tile, const Engine *e, int x; int y; - const ShipVehicleInfo *svi = &e->u.ship; + const ShipVehicleInfo *svi = &e->VehInfo(); Ship *v = new Ship(); *ret = v; diff --git a/src/ship_gui.cpp b/src/ship_gui.cpp index 7bdedb82dc796..eb5eb4d42fbd0 100644 --- a/src/ship_gui.cpp +++ b/src/ship_gui.cpp @@ -14,7 +14,6 @@ #include "vehicle_gui.h" #include "strings_func.h" #include "vehicle_func.h" -#include "spritecache.h" #include "zoom_func.h" #include "table/strings.h" diff --git a/src/signs_cmd.h b/src/signs_cmd.h index 53b76091de4f4..3d8722b070065 100644 --- a/src/signs_cmd.h +++ b/src/signs_cmd.h @@ -16,8 +16,8 @@ std::tuple CmdPlaceSign(DoCommandFlags flags, TileIndex tile, const std::string &text); CommandCost CmdRenameSign(DoCommandFlags flags, SignID sign_id, const std::string &text); -DEF_CMD_TRAIT(CMD_PLACE_SIGN, CmdPlaceSign, CommandFlag::Deity, CMDT_OTHER_MANAGEMENT) -DEF_CMD_TRAIT(CMD_RENAME_SIGN, CmdRenameSign, CommandFlag::Deity, CMDT_OTHER_MANAGEMENT) +DEF_CMD_TRAIT(CMD_PLACE_SIGN, CmdPlaceSign, CommandFlag::Deity, CommandType::OtherManagement) +DEF_CMD_TRAIT(CMD_RENAME_SIGN, CmdRenameSign, CommandFlag::Deity, CommandType::OtherManagement) void CcPlaceSign(Commands cmd, const CommandCost &result, SignID new_sign); diff --git a/src/signs_gui.cpp b/src/signs_gui.cpp index 37b0ccebab229..eb62f3e95ddab 100644 --- a/src/signs_gui.cpp +++ b/src/signs_gui.cpp @@ -329,7 +329,7 @@ struct SignListWindow : Window, SignList { }, SignListGlobalHotkeys}; }; -static constexpr NWidgetPart _nested_sign_list_widgets[] = { +static constexpr std::initializer_list _nested_sign_list_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_BROWN), NWidget(WWT_CAPTION, COLOUR_BROWN, WID_SIL_CAPTION), @@ -504,7 +504,7 @@ struct SignWindow : Window, SignList { } }; -static constexpr NWidgetPart _nested_query_sign_edit_widgets[] = { +static constexpr std::initializer_list _nested_query_sign_edit_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), NWidget(WWT_CAPTION, COLOUR_GREY, WID_QES_CAPTION), SetTextStyle(TC_WHITE), diff --git a/src/smallmap_gui.cpp b/src/smallmap_gui.cpp index 64a5b4c5650be..984083b37d35d 100644 --- a/src/smallmap_gui.cpp +++ b/src/smallmap_gui.cpp @@ -1963,14 +1963,14 @@ class NWidgetSmallmapDisplay : public NWidgetContainer { }; /** Widget parts of the smallmap display. */ -static constexpr NWidgetPart _nested_smallmap_display[] = { +static constexpr std::initializer_list _nested_smallmap_display = { NWidget(WWT_PANEL, COLOUR_BROWN, WID_SM_MAP_BORDER), NWidget(WWT_INSET, COLOUR_BROWN, WID_SM_MAP), SetMinimalSize(346, 140), SetResize(1, 1), SetPadding(2, 2, 2, 2), EndContainer(), EndContainer(), }; /** Widget parts of the smallmap legend bar + image buttons. */ -static constexpr NWidgetPart _nested_smallmap_bar[] = { +static constexpr std::initializer_list _nested_smallmap_bar = { NWidget(WWT_PANEL, COLOUR_BROWN), NWidget(NWID_HORIZONTAL), NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SM_LEGEND), SetResize(1, 1), @@ -2020,7 +2020,7 @@ static std::unique_ptr SmallMapDisplay() return map_display; } -static constexpr NWidgetPart _nested_smallmap_widgets[] = { +static constexpr std::initializer_list _nested_smallmap_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_BROWN), NWidget(WWT_CAPTION, COLOUR_BROWN, WID_SM_CAPTION), diff --git a/src/soundloader_opus.cpp b/src/soundloader_opus.cpp index 7bb924e9bcd78..79252641cf94f 100644 --- a/src/soundloader_opus.cpp +++ b/src/soundloader_opus.cpp @@ -34,7 +34,7 @@ class SoundLoader_Opus : public SoundLoader { static constexpr size_t DECODE_BUFFER_SAMPLES = 5760 * 2; static constexpr size_t DECODE_BUFFER_BYTES = DECODE_BUFFER_SAMPLES * sizeof(opus_int16); - bool Load(SoundEntry &sound, bool new_format, std::vector &data) override + bool Load(SoundEntry &sound, bool new_format, std::vector &data) const override { if (!new_format) return false; diff --git a/src/soundloader_raw.cpp b/src/soundloader_raw.cpp index 7caaf52905249..2ac0efc1fbf24 100644 --- a/src/soundloader_raw.cpp +++ b/src/soundloader_raw.cpp @@ -22,7 +22,7 @@ class SoundLoader_Raw : public SoundLoader { static constexpr uint16_t RAW_SAMPLE_RATE = 11025; ///< Sample rate of raw pcm samples. static constexpr uint8_t RAW_SAMPLE_BITS = 8; ///< Bit depths of raw pcm samples. - bool Load(SoundEntry &sound, bool new_format, std::vector &data) override + bool Load(SoundEntry &sound, bool new_format, std::vector &data) const override { /* Raw sounds are apecial case for the jackhammer sound (name in Windows sample.cat is "Corrupt sound") * It's not a RIFF file, but raw PCM data. diff --git a/src/soundloader_type.h b/src/soundloader_type.h index 2f00cc8284399..8c91052fd166e 100644 --- a/src/soundloader_type.h +++ b/src/soundloader_type.h @@ -26,7 +26,7 @@ class SoundLoader : public PriorityBaseProvider { ProviderManager::Unregister(*this); } - virtual bool Load(SoundEntry &sound, bool new_format, std::vector &data) = 0; + virtual bool Load(SoundEntry &sound, bool new_format, std::vector &data) const = 0; }; #endif /* SOUNDLOADER_TYPE_H */ diff --git a/src/soundloader_wav.cpp b/src/soundloader_wav.cpp index 36897aab7345d..72dbf0a056ae2 100644 --- a/src/soundloader_wav.cpp +++ b/src/soundloader_wav.cpp @@ -23,7 +23,7 @@ class SoundLoader_Wav : public SoundLoader { static constexpr uint16_t DEFAULT_SAMPLE_RATE = 11025; - bool Load(SoundEntry &sound, bool new_format, std::vector &data) override + bool Load(SoundEntry &sound, bool new_format, std::vector &data) const override { RandomAccessFile &file = *sound.file; diff --git a/src/spritecache_internal.h b/src/spritecache_internal.h index 5d7b02e615eba..367db3601e76e 100644 --- a/src/spritecache_internal.h +++ b/src/spritecache_internal.h @@ -13,7 +13,7 @@ #include "core/math_func.hpp" #include "gfx_type.h" #include "spritecache_type.h" -#include "spriteloader/spriteloader.hpp" +#include "spriteloader/sprite_file_type.hpp" #include "table/sprites.h" diff --git a/src/station_base.h b/src/station_base.h index b1d26cc72151c..4832a0f60cbce 100644 --- a/src/station_base.h +++ b/src/station_base.h @@ -155,7 +155,7 @@ class FlowStatMap : public std::map { void AddFlow(StationID origin, StationID via, uint amount); void PassOnFlow(StationID origin, StationID via, uint amount); - StationIDStack DeleteFlows(StationID via); + std::vector DeleteFlows(StationID via); void RestrictFlows(StationID via); void ReleaseFlows(StationID via); void FinalizeLocalConsumption(StationID self); @@ -599,9 +599,9 @@ class AirportTileIterator : public OrthogonalTileIterator { inline TileIterator& operator ++() override { - (*this).OrthogonalTileIterator::operator++(); + this->OrthogonalTileIterator::operator++(); while (this->tile != INVALID_TILE && !st->TileBelongsToAirport(this->tile)) { - (*this).OrthogonalTileIterator::operator++(); + this->OrthogonalTileIterator::operator++(); } return *this; } diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index 333460b53bbf7..8509e15607663 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -891,7 +891,10 @@ static CommandCost IsStationBridgeAboveOk(TileIndex tile, std::span::Do(DoCommandFlag::Auto, tile); } - if (GetTileMaxZ(tile) + height > bridge_height) return CommandCost{GetBridgeTooLowMessageForStationType(type)}; + if (GetTileMaxZ(tile) + height > bridge_height) { + int height_diff = (GetTileMaxZ(tile) + height - bridge_height) * TILE_HEIGHT_STEP; + return CommandCostWithParam(GetBridgeTooLowMessageForStationType(type), height_diff); + } return CommandCost{}; } @@ -1424,6 +1427,9 @@ CommandCost CmdBuildRailStation(DoCommandFlags flags, TileIndex tile_org, RailTy if (!ValParamRailType(rt) || !IsValidAxis(axis)) return CMD_ERROR; + MapRailType map_railtype = _railtype_mapping.AllocateMapType(rt, flags.Test(DoCommandFlag::Execute)); + if (map_railtype == RailTypeMapping::INVALID_MAP_TYPE) return CommandCost{STR_ERROR_TOO_MANY_RAILTYPES}; + /* Check if the given station class is valid */ if (static_cast(spec_class) >= StationClass::GetClassCount()) return CMD_ERROR; const StationClass *cls = StationClass::Get(spec_class); @@ -1478,20 +1484,26 @@ CommandCost CmdBuildRailStation(DoCommandFlags flags, TileIndex tile_org, RailTy TileIndexDiff track_delta = TileOffsByAxis(OtherAxis(axis)); // offset to go to the next track RailStationTileLayout stl{statspec, numtracks, plat_len}; - auto it = stl.begin(); - TileIndex tile_track = tile_org; - for (uint i = 0; i != numtracks; ++i) { - TileIndex tile = tile_track; - for (uint j = 0; j != plat_len; ++j) { - ret = IsRailStationBridgeAboveOk(tile, statspec, StationType::Rail, *it++ + axis); + for (auto [i, it, tile_track] = std::make_tuple(0, stl.begin(), tile_org); i != numtracks; ++i, tile_track += track_delta) { + for (auto [j, tile] = std::make_tuple(0, tile_track); j != plat_len; ++j, tile += tile_delta, ++it) { + /* Don't check the layout if there's no bridge above anyway. */ + if (!IsBridgeAbove(tile)) continue; + + StationGfx gfx = *it + axis; + if (statspec != nullptr) { + uint32_t platinfo = GetPlatformInfo(AXIS_X, gfx, plat_len, numtracks, j, i, false); + /* As the station is not yet completely finished, the station does not yet exist. */ + uint16_t callback = GetStationCallback(CBID_STATION_BUILD_TILE_LAYOUT, platinfo, 0, statspec, nullptr, tile); + if (callback != CALLBACK_FAILED && callback <= UINT8_MAX) gfx = (callback & ~1) + axis; + } + + ret = IsRailStationBridgeAboveOk(tile, statspec, StationType::Rail, gfx); if (ret.Failed()) return ret; - tile += tile_delta; } - tile_track += track_delta; } /* Check if we can allocate a custom stationspec to this station */ - auto specindex = AllocateSpecToStation(statspec, st, flags.Test(DoCommandFlag::Execute)); + auto specindex = AllocateSpecToStation(statspec, st); if (!specindex.has_value()) return CommandCost(STR_ERROR_TOO_MANY_STATION_SPECS); if (statspec != nullptr) { @@ -1514,6 +1526,7 @@ CommandCost CmdBuildRailStation(DoCommandFlags flags, TileIndex tile_org, RailTy st->rect.BeforeAddRect(tile_org, w_org, h_org, StationRect::ADD_TRY); + if (specindex.has_value()) AssignSpecToStation(statspec, st, *specindex); if (statspec != nullptr) { /* Include this station spec's animation trigger bitmask * in the station's cached copy. */ @@ -1521,14 +1534,9 @@ CommandCost CmdBuildRailStation(DoCommandFlags flags, TileIndex tile_org, RailTy } Track track = AxisToTrack(axis); - - auto it = stl.begin(); - Company *c = Company::Get(st->owner); - TileIndex tile_track = tile_org; - for (uint i = 0; i != numtracks; ++i) { - TileIndex tile = tile_track; - for (uint j = 0; j != plat_len; ++j) { + for (auto [i, it, tile_track] = std::make_tuple(0, stl.begin(), tile_org); i != numtracks; ++i, tile_track += track_delta) { + for (auto [j, tile] = std::make_tuple(0, tile_track); j != plat_len; ++j, tile += tile_delta, ++it) { if (IsRailStationTile(tile) && HasStationReservation(tile)) { /* Check for trains having a reservation for this tile. */ Train *v = GetTrainForReservation(tile, AxisToTrack(GetRailStationAxis(tile))); @@ -1548,7 +1556,7 @@ CommandCost CmdBuildRailStation(DoCommandFlags flags, TileIndex tile_org, RailTy DeleteAnimatedTile(tile); uint8_t old_specindex = HasStationTileRail(tile) ? GetCustomStationSpecIndex(tile) : 0; - MakeRailStation(tile, st->owner, st->index, axis, *it++, rt); + MakeRailStation(tile, st->owner, st->index, axis, *it, map_railtype); /* Free the spec if we overbuild something */ DeallocateSpecFromStation(st, old_specindex); @@ -1578,12 +1586,9 @@ CommandCost CmdBuildRailStation(DoCommandFlags flags, TileIndex tile_org, RailTy if (!IsStationTileBlocked(tile)) c->infrastructure.rail[rt]++; c->infrastructure.station++; - - tile += tile_delta; } AddTrackToSignalBuffer(tile_track, track, _current_company); YapfNotifyTrackLayoutChange(tile_track, track); - tile_track += track_delta; } for (uint i = 0; i < affected_vehicles.size(); ++i) { @@ -1770,7 +1775,7 @@ CommandCost RemoveFromRailBaseStation(TileArea ta, std::vector &affected_st uint specindex = GetCustomStationSpecIndex(tile); Track track = GetRailStationTrack(tile); Owner owner = GetTileOwner(tile); - RailType rt = GetRailType(tile); + MapRailType map_railtype = GetMapRailType(tile); Train *v = nullptr; if (HasStationReservation(tile)) { @@ -1779,11 +1784,11 @@ CommandCost RemoveFromRailBaseStation(TileArea ta, std::vector &affected_st } bool build_rail = keep_rail && !IsStationTileBlocked(tile); - if (!build_rail && !IsStationTileBlocked(tile)) Company::Get(owner)->infrastructure.rail[rt]--; + if (!build_rail && !IsStationTileBlocked(tile)) Company::Get(owner)->infrastructure.rail[_railtype_mapping.GetType(map_railtype)]--; DoClearSquare(tile); DeleteNewGRFInspectWindow(GSF_STATIONS, tile.base()); - if (build_rail) MakeRailNormal(tile, owner, TrackToTrackBits(track), rt); + if (build_rail) MakeRailNormal(tile, owner, TrackToTrackBits(track), map_railtype); Company::Get(owner)->infrastructure.station--; DirtyCompanyInfrastructureWindows(owner); @@ -2113,7 +2118,7 @@ CommandCost CmdBuildRoadStop(DoCommandFlags flags, TileIndex tile, uint8_t width if (ret.Failed()) return ret; /* Check if we can allocate a custom stationspec to this station */ - auto specindex = AllocateSpecToRoadStop(roadstopspec, st, flags.Test(DoCommandFlag::Execute)); + auto specindex = AllocateSpecToRoadStop(roadstopspec, st); if (!specindex.has_value()) return CommandCost(STR_ERROR_TOO_MANY_STATION_SPECS); if (roadstopspec != nullptr) { @@ -2126,14 +2131,21 @@ CommandCost CmdBuildRoadStop(DoCommandFlags flags, TileIndex tile, uint8_t width } } + RoadTramType rtt = GetRoadTramType(rt); + MapRoadType new_map_roadtype = rtt == RTT_ROAD ? _roadtype_mapping.AllocateMapType(rt, flags.Test(DoCommandFlag::Execute)) : RoadTypeMapping::INVALID_MAP_TYPE; + if (rtt == RTT_ROAD && new_map_roadtype == RoadTypeMapping::INVALID_MAP_TYPE) return CommandCost{STR_ERROR_TOO_MANY_ROADTYPES}; + MapTramType new_map_tramtype = rtt == RTT_TRAM ? _tramtype_mapping.AllocateMapType(rt, flags.Test(DoCommandFlag::Execute)) : TramTypeMapping::INVALID_MAP_TYPE; + if (rtt == RTT_TRAM && new_map_tramtype == TramTypeMapping::INVALID_MAP_TYPE) return CommandCost{STR_ERROR_TOO_MANY_TRAMTYPES}; + if (flags.Test(DoCommandFlag::Execute)) { + if (specindex.has_value()) AssignSpecToRoadStop(roadstopspec, st, *specindex); /* Check every tile in the area. */ for (TileIndex cur_tile : roadstop_area) { /* Get existing road types and owners before any tile clearing */ - RoadType road_rt = MayHaveRoad(cur_tile) ? GetRoadType(cur_tile, RTT_ROAD) : INVALID_ROADTYPE; - RoadType tram_rt = MayHaveRoad(cur_tile) ? GetRoadType(cur_tile, RTT_TRAM) : INVALID_ROADTYPE; - Owner road_owner = road_rt != INVALID_ROADTYPE ? GetRoadOwner(cur_tile, RTT_ROAD) : _current_company; - Owner tram_owner = tram_rt != INVALID_ROADTYPE ? GetRoadOwner(cur_tile, RTT_TRAM) : _current_company; + MapRoadType cur_map_roadtype = MayHaveRoad(cur_tile) ? GetMapRoadTypeRoad(cur_tile) : RoadTypeMapping::INVALID_MAP_TYPE; + MapTramType cur_map_tramtype = MayHaveRoad(cur_tile) ? GetMapRoadTypeTram(cur_tile) : TramTypeMapping::INVALID_MAP_TYPE; + Owner road_owner = cur_map_roadtype != RoadTypeMapping::INVALID_MAP_TYPE ? GetRoadOwner(cur_tile, RTT_ROAD) : _current_company; + Owner tram_owner = cur_map_tramtype != TramTypeMapping::INVALID_MAP_TYPE ? GetRoadOwner(cur_tile, RTT_TRAM) : _current_company; if (IsTileType(cur_tile, MP_STATION) && IsStationRoadStop(cur_tile)) { RemoveRoadStop(cur_tile, flags, *specindex); @@ -2166,22 +2178,22 @@ CommandCost CmdBuildRoadStop(DoCommandFlags flags, TileIndex tile, uint8_t width /* Update company infrastructure counts. If the current tile is a normal road tile, remove the old * bits first. */ if (IsNormalRoadTile(cur_tile)) { - UpdateCompanyRoadInfrastructure(road_rt, road_owner, -(int)CountBits(GetRoadBits(cur_tile, RTT_ROAD))); - UpdateCompanyRoadInfrastructure(tram_rt, tram_owner, -(int)CountBits(GetRoadBits(cur_tile, RTT_TRAM))); + UpdateCompanyRoadInfrastructure(_roadtype_mapping.GetType(cur_map_roadtype), road_owner, -(int)CountBits(GetRoadBits(cur_tile, RTT_ROAD))); + UpdateCompanyRoadInfrastructure(_tramtype_mapping.GetType(cur_map_tramtype), tram_owner, -(int)CountBits(GetRoadBits(cur_tile, RTT_TRAM))); } - if (road_rt == INVALID_ROADTYPE && RoadTypeIsRoad(rt)) road_rt = rt; - if (tram_rt == INVALID_ROADTYPE && RoadTypeIsTram(rt)) tram_rt = rt; + if (cur_map_roadtype == RoadTypeMapping::INVALID_MAP_TYPE && RoadTypeIsRoad(rt)) cur_map_roadtype = new_map_roadtype; + if (cur_map_tramtype == TramTypeMapping::INVALID_MAP_TYPE && RoadTypeIsTram(rt)) cur_map_tramtype = new_map_tramtype; - MakeDriveThroughRoadStop(cur_tile, st->owner, road_owner, tram_owner, st->index, (rs_type == RoadStopType::Bus ? StationType::Bus : StationType::Truck), road_rt, tram_rt, axis); + MakeDriveThroughRoadStop(cur_tile, st->owner, road_owner, tram_owner, st->index, (rs_type == RoadStopType::Bus ? StationType::Bus : StationType::Truck), cur_map_roadtype, cur_map_tramtype, axis); road_stop->MakeDriveThrough(); } else { - if (road_rt == INVALID_ROADTYPE && RoadTypeIsRoad(rt)) road_rt = rt; - if (tram_rt == INVALID_ROADTYPE && RoadTypeIsTram(rt)) tram_rt = rt; - MakeRoadStop(cur_tile, st->owner, st->index, rs_type, road_rt, tram_rt, ddir); + if (cur_map_roadtype == RoadTypeMapping::INVALID_MAP_TYPE && RoadTypeIsRoad(rt)) cur_map_roadtype = new_map_roadtype; + if (cur_map_tramtype == TramTypeMapping::INVALID_MAP_TYPE && RoadTypeIsTram(rt)) cur_map_tramtype = new_map_tramtype; + MakeRoadStop(cur_tile, st->owner, st->index, rs_type, cur_map_roadtype, cur_map_tramtype, ddir); } - UpdateCompanyRoadInfrastructure(road_rt, road_owner, ROAD_STOP_TRACKBIT_FACTOR); - UpdateCompanyRoadInfrastructure(tram_rt, tram_owner, ROAD_STOP_TRACKBIT_FACTOR); + UpdateCompanyRoadInfrastructure(_roadtype_mapping.GetType(cur_map_roadtype), road_owner, ROAD_STOP_TRACKBIT_FACTOR); + UpdateCompanyRoadInfrastructure(_tramtype_mapping.GetType(cur_map_tramtype), tram_owner, ROAD_STOP_TRACKBIT_FACTOR); Company::Get(st->owner)->infrastructure.station++; SetCustomRoadStopSpecIndex(cur_tile, *specindex); @@ -2437,7 +2449,7 @@ static CommandCost RemoveGenericRoadStop(DoCommandFlags flags, const TileArea &r /* Restore roads. */ if (flags.Test(DoCommandFlag::Execute) && (road_type[RTT_ROAD] != INVALID_ROADTYPE || road_type[RTT_TRAM] != INVALID_ROADTYPE)) { - MakeRoadNormal(cur_tile, road_bits, road_type[RTT_ROAD], road_type[RTT_TRAM], ClosestTownFromTile(cur_tile, UINT_MAX)->index, + MakeRoadNormal(cur_tile, road_bits, _roadtype_mapping.GetMappedType(road_type[RTT_ROAD]), _tramtype_mapping.GetMappedType(road_type[RTT_TRAM]), ClosestTownFromTile(cur_tile, UINT_MAX)->index, road_owner[RTT_ROAD], road_owner[RTT_TRAM]); /* Update company infrastructure counts. */ @@ -3946,6 +3958,10 @@ static void TruncateCargo(const CargoSpec *cs, GoodsEntry *ge, uint amount = UIN } } +/** + * Periodic update of a station's rating. + * @param st The station to update. + */ static void UpdateStationRating(Station *st) { bool waiting_changed = false; @@ -3955,144 +3971,148 @@ static void UpdateStationRating(Station *st) for (const CargoSpec *cs : CargoSpec::Iterate()) { GoodsEntry *ge = &st->goods[cs->Index()]; - /* Slowly increase the rating back to its original level in the case we - * didn't deliver cargo yet to this station. This happens when a bribe - * failed while you didn't moved that cargo yet to a station. */ - if (!ge->HasRating() && ge->rating < INITIAL_STATION_RATING) { - ge->rating++; - } - - /* Only change the rating if we are moving this cargo */ - if (ge->HasRating()) { - byte_inc_sat(&ge->time_since_pickup); - if (ge->time_since_pickup == 255 && _settings_game.order.selectgoods) { - ge->status.Reset(GoodsEntry::State::Rating); - ge->last_speed = 0; - TruncateCargo(cs, ge); - waiting_changed = true; - continue; - } - bool skip = false; - int rating = 0; - uint waiting = ge->HasData() ? ge->GetData().cargo.AvailableCount() : 0; - - /* num_dests is at least 1 if there is any cargo as - * StationID::Invalid() is also a destination. - */ - uint num_dests = ge->HasData() ? static_cast(ge->GetData().cargo.Packets()->MapSize()) : 0; - - /* Average amount of cargo per next hop, but prefer solitary stations - * with only one or two next hops. They are allowed to have more - * cargo waiting per next hop. - * With manual cargo distribution waiting_avg = waiting / 2 as then - * StationID::Invalid() is the only destination. - */ - uint waiting_avg = waiting / (num_dests + 1); - - if (_cheats.station_rating.value) { - ge->rating = rating = MAX_STATION_RATING; + /* The station might not currently be moving this cargo. */ + if (!ge->HasRating()) { + /* Slowly increase the rating back to its original level in the case we + * didn't deliver cargo yet to this station. This happens when a bribe + * failed while you didn't moved that cargo yet to a station. */ + if (ge->rating < INITIAL_STATION_RATING) ge->rating++; + + /* Nothing else to do with this cargo. */ + continue; + } + + byte_inc_sat(&ge->time_since_pickup); + + /* If this cargo hasn't been picked up in a long time, get rid of it. */ + if (ge->time_since_pickup == 255 && _settings_game.order.selectgoods) { + ge->status.Reset(GoodsEntry::State::Rating); + ge->last_speed = 0; + TruncateCargo(cs, ge); + waiting_changed = true; + continue; + } + + bool skip = false; + int rating = 0; + uint waiting = ge->HasData() ? ge->GetData().cargo.AvailableCount() : 0; + + /* num_dests is at least 1 if there is any cargo as + * StationID::Invalid() is also a destination. + */ + uint num_dests = ge->HasData() ? static_cast(ge->GetData().cargo.Packets()->MapSize()) : 0; + + /* Average amount of cargo per next hop, but prefer solitary stations + * with only one or two next hops. They are allowed to have more + * cargo waiting per next hop. + * With manual cargo distribution waiting_avg = waiting / 2 as then + * StationID::Invalid() is the only destination. + */ + uint waiting_avg = waiting / (num_dests + 1); + + if (_cheats.station_rating.value) { + ge->rating = rating = MAX_STATION_RATING; + skip = true; + } else if (cs->callback_mask.Test(CargoCallbackMask::StationRatingCalc)) { + /* Perform custom station rating. If it succeeds the speed, days in transit and + * waiting cargo ratings must not be executed. */ + + /* NewGRFs expect last speed to be 0xFF when no vehicle has arrived yet. */ + uint last_speed = ge->HasVehicleEverTriedLoading() ? ge->last_speed : 0xFF; + + uint32_t var18 = ClampTo(ge->time_since_pickup) + | (ClampTo(ge->max_waiting_cargo) << 8) + | (ClampTo(last_speed) << 24); + /* Convert to the 'old' vehicle types */ + uint32_t var10 = (st->last_vehicle_type == VEH_INVALID) ? 0x0 : (st->last_vehicle_type + 0x10); + uint16_t callback = GetCargoCallback(CBID_CARGO_STATION_RATING_CALC, var10, var18, cs); + if (callback != CALLBACK_FAILED) { skip = true; - } else if (cs->callback_mask.Test(CargoCallbackMask::StationRatingCalc)) { - /* Perform custom station rating. If it succeeds the speed, days in transit and - * waiting cargo ratings must not be executed. */ - - /* NewGRFs expect last speed to be 0xFF when no vehicle has arrived yet. */ - uint last_speed = ge->HasVehicleEverTriedLoading() ? ge->last_speed : 0xFF; - - uint32_t var18 = ClampTo(ge->time_since_pickup) - | (ClampTo(ge->max_waiting_cargo) << 8) - | (ClampTo(last_speed) << 24); - /* Convert to the 'old' vehicle types */ - uint32_t var10 = (st->last_vehicle_type == VEH_INVALID) ? 0x0 : (st->last_vehicle_type + 0x10); - uint16_t callback = GetCargoCallback(CBID_CARGO_STATION_RATING_CALC, var10, var18, cs); - if (callback != CALLBACK_FAILED) { - skip = true; - rating = GB(callback, 0, 14); - - /* Simulate a 15 bit signed value */ - if (HasBit(callback, 14)) rating -= 0x4000; - } - } + rating = GB(callback, 0, 14); - if (!skip) { - int b = ge->last_speed - 85; - if (b >= 0) rating += b >> 2; - - uint8_t waittime = ge->time_since_pickup; - if (st->last_vehicle_type == VEH_SHIP) waittime >>= 2; - if (waittime <= 21) rating += 25; - if (waittime <= 12) rating += 25; - if (waittime <= 6) rating += 45; - if (waittime <= 3) rating += 35; - - rating -= 90; - if (ge->max_waiting_cargo <= 1500) rating += 55; - if (ge->max_waiting_cargo <= 1000) rating += 35; - if (ge->max_waiting_cargo <= 600) rating += 10; - if (ge->max_waiting_cargo <= 300) rating += 20; - if (ge->max_waiting_cargo <= 100) rating += 10; + /* Simulate a 15 bit signed value */ + if (HasBit(callback, 14)) rating -= 0x4000; } + } - if (Company::IsValidID(st->owner) && st->town->statues.Test(st->owner)) rating += 26; + if (!skip) { + int b = ge->last_speed - 85; + if (b >= 0) rating += b >> 2; - uint8_t age = ge->last_age; - if (age < 3) rating += 10; - if (age < 2) rating += 10; - if (age < 1) rating += 13; + uint8_t waittime = ge->time_since_pickup; + if (st->last_vehicle_type == VEH_SHIP) waittime >>= 2; + if (waittime <= 21) rating += 25; + if (waittime <= 12) rating += 25; + if (waittime <= 6) rating += 45; + if (waittime <= 3) rating += 35; - { - int or_ = ge->rating; // old rating + rating -= 90; + if (ge->max_waiting_cargo <= 1500) rating += 55; + if (ge->max_waiting_cargo <= 1000) rating += 35; + if (ge->max_waiting_cargo <= 600) rating += 10; + if (ge->max_waiting_cargo <= 300) rating += 20; + if (ge->max_waiting_cargo <= 100) rating += 10; + } - /* only modify rating in steps of -2, -1, 0, 1 or 2 */ - ge->rating = rating = ClampTo(or_ + Clamp(rating - or_, -2, 2)); + if (Company::IsValidID(st->owner) && st->town->statues.Test(st->owner)) rating += 26; - /* if rating is <= 64 and more than 100 items waiting on average per destination, - * remove some random amount of goods from the station */ - if (rating <= 64 && waiting_avg >= 100) { - int dec = Random() & 0x1F; - if (waiting_avg < 200) dec &= 7; - waiting -= (dec + 1) * num_dests; - waiting_changed = true; - } + uint8_t age = ge->last_age; + if (age < 3) rating += 10; + if (age < 2) rating += 10; + if (age < 1) rating += 13; - /* if rating is <= 127 and there are any items waiting, maybe remove some goods. */ - if (rating <= 127 && waiting != 0) { - uint32_t r = Random(); - if (rating <= (int)GB(r, 0, 7)) { - /* Need to have int, otherwise it will just overflow etc. */ - waiting = std::max((int)waiting - (int)((GB(r, 8, 2) - 1) * num_dests), 0); - waiting_changed = true; - } - } + { + int or_ = ge->rating; // old rating - /* At some point we really must cap the cargo. Previously this - * was a strict 4095, but now we'll have a less strict, but - * increasingly aggressive truncation of the amount of cargo. */ - static const uint WAITING_CARGO_THRESHOLD = 1 << 12; - static const uint WAITING_CARGO_CUT_FACTOR = 1 << 6; - static const uint MAX_WAITING_CARGO = 1 << 15; + /* only modify rating in steps of -2, -1, 0, 1 or 2 */ + ge->rating = rating = ClampTo(or_ + Clamp(rating - or_, -2, 2)); - if (waiting > WAITING_CARGO_THRESHOLD) { - uint difference = waiting - WAITING_CARGO_THRESHOLD; - waiting -= (difference / WAITING_CARGO_CUT_FACTOR); + /* if rating is <= 64 and more than 100 items waiting on average per destination, + * remove some random amount of goods from the station */ + if (rating <= 64 && waiting_avg >= 100) { + int dec = Random() & 0x1F; + if (waiting_avg < 200) dec &= 7; + waiting -= (dec + 1) * num_dests; + waiting_changed = true; + } - waiting = std::min(waiting, MAX_WAITING_CARGO); + /* if rating is <= 127 and there are any items waiting, maybe remove some goods. */ + if (rating <= 127 && waiting != 0) { + uint32_t r = Random(); + if (rating <= (int)GB(r, 0, 7)) { + /* Need to have int, otherwise it will just overflow etc. */ + waiting = std::max((int)waiting - (int)((GB(r, 8, 2) - 1) * num_dests), 0); waiting_changed = true; } + } - /* We can't truncate cargo that's already reserved for loading. - * Thus StoredCount() here. */ - if (waiting_changed && waiting < (ge->HasData() ? ge->GetData().cargo.AvailableCount() : 0)) { - /* Feed back the exact own waiting cargo at this station for the - * next rating calculation. */ - ge->max_waiting_cargo = 0; + /* At some point we really must cap the cargo. Previously this + * was a strict 4095, but now we'll have a less strict, but + * increasingly aggressive truncation of the amount of cargo. */ + static const uint WAITING_CARGO_THRESHOLD = 1 << 12; + static const uint WAITING_CARGO_CUT_FACTOR = 1 << 6; + static const uint MAX_WAITING_CARGO = 1 << 15; - TruncateCargo(cs, ge, ge->GetData().cargo.AvailableCount() - waiting); - } else { - /* If the average number per next hop is low, be more forgiving. */ - ge->max_waiting_cargo = waiting_avg; - } + if (waiting > WAITING_CARGO_THRESHOLD) { + uint difference = waiting - WAITING_CARGO_THRESHOLD; + waiting -= (difference / WAITING_CARGO_CUT_FACTOR); + + waiting = std::min(waiting, MAX_WAITING_CARGO); + waiting_changed = true; + } + + /* We can't truncate cargo that's already reserved for loading. + * Thus StoredCount() here. */ + if (waiting_changed && waiting < (ge->HasData() ? ge->GetData().cargo.AvailableCount() : 0)) { + /* Feed back the exact own waiting cargo at this station for the + * next rating calculation. */ + ge->max_waiting_cargo = 0; + + TruncateCargo(cs, ge, ge->GetData().cargo.AvailableCount() - waiting); + } else { + /* If the average number per next hop is low, be more forgiving. */ + ge->max_waiting_cargo = waiting_avg; } } } @@ -4349,6 +4369,14 @@ static const IntervalTimer _economy_stations_monthly({TimerGam } }); +/** + * Forcibly modify station ratings near a given tile. + * Used when a crash hurts a company's station ratings nearby, or when local authority actions affect nearby ratings. + * @param tile The center of the ratings change area. + * @param owner The station owner whose stations are affected. + * @param amount The amount to change the rating. + * @param radius The radius to search for stations, from the origin tile. + */ void ModifyStationRatingAround(TileIndex tile, Owner owner, int amount, uint radius) { ForAllStationsRadius(tile, radius, [&](Station *st) { @@ -4694,7 +4722,11 @@ static void ChangeTileOwner_Station(TileIndex tile, Owner old_owner, Owner new_o if (rt != INVALID_ROADTYPE) { /* A drive-through road-stop has always two road bits. No need to dirty windows here, we'll redraw the whole screen anyway. */ Company::Get(old_owner)->infrastructure.road[rt] -= 2; - if (new_owner != INVALID_OWNER) Company::Get(new_owner)->infrastructure.road[rt] += 2; + if (new_owner != INVALID_OWNER) { + Company::Get(new_owner)->infrastructure.road[rt] += 2; + } else { + RoadTypeInfo::infrastructure_counts[rt] += 2; + } } SetRoadOwner(tile, rtt, new_owner == INVALID_OWNER ? OWNER_NONE : new_owner); } @@ -5184,14 +5216,14 @@ void FlowStatMap::FinalizeLocalConsumption(StationID self) * @return IDs of source stations for which the complete FlowStat, not only a * share, has been erased. */ -StationIDStack FlowStatMap::DeleteFlows(StationID via) +std::vector FlowStatMap::DeleteFlows(StationID via) { - StationIDStack ret; + std::vector ret; for (FlowStatMap::iterator f_it = this->begin(); f_it != this->end();) { FlowStat &s_flows = f_it->second; s_flows.ChangeShare(via, INT_MIN); if (s_flows.GetShares()->empty()) { - ret.Push(f_it->first); + ret.push_back(f_it->first); this->erase(f_it++); } else { ++f_it; diff --git a/src/station_cmd.h b/src/station_cmd.h index cd5c69b7fa382..38382cee27bd9 100644 --- a/src/station_cmd.h +++ b/src/station_cmd.h @@ -32,13 +32,13 @@ CommandCost CmdRemoveRoadStop(DoCommandFlags flags, TileIndex tile, uint8_t widt CommandCost CmdRenameStation(DoCommandFlags flags, StationID station_id, const std::string &text); CommandCost CmdOpenCloseAirport(DoCommandFlags flags, StationID station_id); -DEF_CMD_TRAIT(CMD_BUILD_AIRPORT, CmdBuildAirport, CommandFlags({CommandFlag::Auto, CommandFlag::NoWater}), CMDT_LANDSCAPE_CONSTRUCTION) -DEF_CMD_TRAIT(CMD_BUILD_DOCK, CmdBuildDock, CommandFlag::Auto, CMDT_LANDSCAPE_CONSTRUCTION) -DEF_CMD_TRAIT(CMD_BUILD_RAIL_STATION, CmdBuildRailStation, CommandFlags({CommandFlag::Auto, CommandFlag::NoWater}), CMDT_LANDSCAPE_CONSTRUCTION) -DEF_CMD_TRAIT(CMD_REMOVE_FROM_RAIL_STATION, CmdRemoveFromRailStation, {}, CMDT_LANDSCAPE_CONSTRUCTION) -DEF_CMD_TRAIT(CMD_BUILD_ROAD_STOP, CmdBuildRoadStop, CommandFlags({CommandFlag::Auto, CommandFlag::NoWater}), CMDT_LANDSCAPE_CONSTRUCTION) -DEF_CMD_TRAIT(CMD_REMOVE_ROAD_STOP, CmdRemoveRoadStop, {}, CMDT_LANDSCAPE_CONSTRUCTION) -DEF_CMD_TRAIT(CMD_RENAME_STATION, CmdRenameStation, {}, CMDT_OTHER_MANAGEMENT) -DEF_CMD_TRAIT(CMD_OPEN_CLOSE_AIRPORT, CmdOpenCloseAirport, {}, CMDT_ROUTE_MANAGEMENT) +DEF_CMD_TRAIT(CMD_BUILD_AIRPORT, CmdBuildAirport, CommandFlags({CommandFlag::Auto, CommandFlag::NoWater}), CommandType::LandscapeConstruction) +DEF_CMD_TRAIT(CMD_BUILD_DOCK, CmdBuildDock, CommandFlag::Auto, CommandType::LandscapeConstruction) +DEF_CMD_TRAIT(CMD_BUILD_RAIL_STATION, CmdBuildRailStation, CommandFlags({CommandFlag::Auto, CommandFlag::NoWater}), CommandType::LandscapeConstruction) +DEF_CMD_TRAIT(CMD_REMOVE_FROM_RAIL_STATION, CmdRemoveFromRailStation, {}, CommandType::LandscapeConstruction) +DEF_CMD_TRAIT(CMD_BUILD_ROAD_STOP, CmdBuildRoadStop, CommandFlags({CommandFlag::Auto, CommandFlag::NoWater}), CommandType::LandscapeConstruction) +DEF_CMD_TRAIT(CMD_REMOVE_ROAD_STOP, CmdRemoveRoadStop, {}, CommandType::LandscapeConstruction) +DEF_CMD_TRAIT(CMD_RENAME_STATION, CmdRenameStation, {}, CommandType::OtherManagement) +DEF_CMD_TRAIT(CMD_OPEN_CLOSE_AIRPORT, CmdOpenCloseAirport, {}, CommandType::RouteManagement) #endif /* STATION_CMD_H */ diff --git a/src/station_gui.cpp b/src/station_gui.cpp index 1f88fe385bb65..9cb198d434f86 100644 --- a/src/station_gui.cpp +++ b/src/station_gui.cpp @@ -759,7 +759,7 @@ const std::initializer_list CompanyStation &StationRatingMinSorter }; -static constexpr NWidgetPart _nested_company_stations_widgets[] = { +static constexpr std::initializer_list _nested_company_stations_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), NWidget(WWT_CAPTION, COLOUR_GREY, WID_STL_CAPTION), @@ -811,7 +811,7 @@ void ShowCompanyStations(CompanyID company) AllocateWindowDescFront(_company_stations_desc, company); } -static constexpr NWidgetPart _nested_station_view_widgets[] = { +static constexpr std::initializer_list _nested_station_view_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_SV_RENAME), SetAspect(WidgetDimensions::ASPECT_RENAME), SetSpriteTip(SPR_RENAME, STR_STATION_VIEW_RENAME_TOOLTIP), @@ -2269,7 +2269,7 @@ static void FindStationsNearby(TileArea ta, bool distant_join) } } -static constexpr NWidgetPart _nested_select_station_widgets[] = { +static constexpr std::initializer_list _nested_select_station_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN), NWidget(WWT_CAPTION, COLOUR_DARK_GREEN, WID_JS_CAPTION), SetStringTip(STR_JOIN_STATION_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), diff --git a/src/station_map.h b/src/station_map.h index fcb458dbec0c8..2095df3f2897f 100644 --- a/src/station_map.h +++ b/src/station_map.h @@ -726,6 +726,7 @@ inline void MakeStation(Tile t, Owner o, StationID sid, StationType st, uint8_t t.m5() = section; SB(t.m6(), 2, 1, 0); SB(t.m6(), 3, 4, to_underlying(st)); + SB(t.m6(), 7, 1, 0); t.m7() = 0; t.m8() = 0; } @@ -737,12 +738,12 @@ inline void MakeStation(Tile t, Owner o, StationID sid, StationType st, uint8_t * @param sid the station to which this tile belongs * @param a the axis of this tile * @param section the StationGfx to be used for this tile - * @param rt the railtype of this tile + * @param map_railtype the map rail type of this tile */ -inline void MakeRailStation(Tile t, Owner o, StationID sid, Axis a, uint8_t section, RailType rt) +inline void MakeRailStation(Tile t, Owner o, StationID sid, Axis a, uint8_t section, MapRailType map_railtype) { MakeStation(t, o, sid, StationType::Rail, section + a); - SetRailType(t, rt); + SetMapRailType(t, map_railtype); SetRailStationReservation(t, false); } @@ -753,12 +754,12 @@ inline void MakeRailStation(Tile t, Owner o, StationID sid, Axis a, uint8_t sect * @param sid the waypoint to which this tile belongs * @param a the axis of this tile * @param section the StationGfx to be used for this tile - * @param rt the railtype of this tile + * @param map_railtype the map rail type of this tile */ -inline void MakeRailWaypoint(Tile t, Owner o, StationID sid, Axis a, uint8_t section, RailType rt) +inline void MakeRailWaypoint(Tile t, Owner o, StationID sid, Axis a, uint8_t section, MapRailType map_railtype) { MakeStation(t, o, sid, StationType::RailWaypoint, section + a); - SetRailType(t, rt); + SetMapRailType(t, map_railtype); SetRailStationReservation(t, false); } @@ -768,14 +769,14 @@ inline void MakeRailWaypoint(Tile t, Owner o, StationID sid, Axis a, uint8_t sec * @param o the owner of the roadstop * @param sid the station to which this tile belongs * @param rst the type of roadstop to make this tile - * @param road_rt the road roadtype on this tile - * @param tram_rt the tram roadtype on this tile + * @param map_roadtype the map road type on this tile + * @param map_tramtype the map tram type on this tile * @param d the direction of the roadstop */ -inline void MakeRoadStop(Tile t, Owner o, StationID sid, RoadStopType rst, RoadType road_rt, RoadType tram_rt, DiagDirection d) +inline void MakeRoadStop(Tile t, Owner o, StationID sid, RoadStopType rst, MapRoadType map_roadtype, MapTramType map_tramtype, DiagDirection d) { MakeStation(t, o, sid, (rst == RoadStopType::Bus ? StationType::Bus : StationType::Truck), d); - SetRoadTypes(t, road_rt, tram_rt); + SetMapRoadTypes(t, map_roadtype, map_tramtype); SetRoadOwner(t, RTT_ROAD, o); SetRoadOwner(t, RTT_TRAM, o); } @@ -788,14 +789,14 @@ inline void MakeRoadStop(Tile t, Owner o, StationID sid, RoadStopType rst, RoadT * @param tram the owner of the tram * @param sid the station to which this tile belongs * @param rst the type of roadstop to make this tile - * @param road_rt the road roadtype on this tile - * @param tram_rt the tram roadtype on this tile + * @param map_roadtype the map road type on this tile + * @param map_tramtype the map tram type on this tile * @param a the direction of the roadstop */ -inline void MakeDriveThroughRoadStop(Tile t, Owner station, Owner road, Owner tram, StationID sid, StationType rst, RoadType road_rt, RoadType tram_rt, Axis a) +inline void MakeDriveThroughRoadStop(Tile t, Owner station, Owner road, Owner tram, StationID sid, StationType rst, MapRoadType map_roadtype, MapTramType map_tramtype, Axis a) { MakeStation(t, station, sid, rst, GFX_TRUCK_BUS_DRIVETHROUGH_OFFSET + a); - SetRoadTypes(t, road_rt, tram_rt); + SetMapRoadTypes(t, map_roadtype, map_tramtype); SetRoadOwner(t, RTT_ROAD, road); SetRoadOwner(t, RTT_TRAM, tram); } diff --git a/src/station_type.h b/src/station_type.h index 07615dd7a1685..1c4da959dd8bf 100644 --- a/src/station_type.h +++ b/src/station_type.h @@ -11,7 +11,6 @@ #define STATION_TYPE_H #include "core/pool_type.hpp" -#include "core/smallstack_type.hpp" #include "tilearea_type.h" using StationID = PoolID; @@ -26,8 +25,6 @@ struct RoadStop; struct StationSpec; struct Waypoint; -using StationIDStack = SmallStack; - /** Station types */ enum class StationType : uint8_t { Rail, diff --git a/src/statusbar_gui.cpp b/src/statusbar_gui.cpp index ffd5e904945e0..b6e698731815a 100644 --- a/src/statusbar_gui.cpp +++ b/src/statusbar_gui.cpp @@ -210,7 +210,7 @@ struct StatusBarWindow : Window { }}; }; -static constexpr NWidgetPart _nested_main_status_widgets[] = { +static constexpr std::initializer_list _nested_main_status_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_PANEL, COLOUR_GREY, WID_S_LEFT), SetMinimalSize(140, 12), EndContainer(), NWidget(WWT_PUSHBTN, COLOUR_GREY, WID_S_MIDDLE), SetMinimalSize(40, 12), SetToolTip(STR_STATUSBAR_TOOLTIP_SHOW_LAST_NEWS), SetResize(1, 0), diff --git a/src/story_cmd.h b/src/story_cmd.h index 08075db05764e..c001675cbce5e 100644 --- a/src/story_cmd.h +++ b/src/story_cmd.h @@ -25,14 +25,14 @@ CommandCost CmdRemoveStoryPage(DoCommandFlags flags, StoryPageID page_id); CommandCost CmdRemoveStoryPageElement(DoCommandFlags flags, StoryPageElementID page_element_id); CommandCost CmdStoryPageButton(DoCommandFlags flags, TileIndex tile, StoryPageElementID page_element_id, VehicleID reference); -DEF_CMD_TRAIT(CMD_CREATE_STORY_PAGE, CmdCreateStoryPage, CommandFlags({CommandFlag::Deity, CommandFlag::StrCtrl}), CMDT_OTHER_MANAGEMENT) -DEF_CMD_TRAIT(CMD_CREATE_STORY_PAGE_ELEMENT, CmdCreateStoryPageElement, CommandFlags({CommandFlag::Deity, CommandFlag::StrCtrl}), CMDT_OTHER_MANAGEMENT) -DEF_CMD_TRAIT(CMD_UPDATE_STORY_PAGE_ELEMENT, CmdUpdateStoryPageElement, CommandFlags({CommandFlag::Deity, CommandFlag::StrCtrl}), CMDT_OTHER_MANAGEMENT) -DEF_CMD_TRAIT(CMD_SET_STORY_PAGE_TITLE, CmdSetStoryPageTitle, CommandFlags({CommandFlag::Deity, CommandFlag::StrCtrl}), CMDT_OTHER_MANAGEMENT) -DEF_CMD_TRAIT(CMD_SET_STORY_PAGE_DATE, CmdSetStoryPageDate, CommandFlag::Deity, CMDT_OTHER_MANAGEMENT) -DEF_CMD_TRAIT(CMD_SHOW_STORY_PAGE, CmdShowStoryPage, CommandFlag::Deity, CMDT_OTHER_MANAGEMENT) -DEF_CMD_TRAIT(CMD_REMOVE_STORY_PAGE, CmdRemoveStoryPage, CommandFlag::Deity, CMDT_OTHER_MANAGEMENT) -DEF_CMD_TRAIT(CMD_REMOVE_STORY_PAGE_ELEMENT, CmdRemoveStoryPageElement, CommandFlag::Deity, CMDT_OTHER_MANAGEMENT) -DEF_CMD_TRAIT(CMD_STORY_PAGE_BUTTON, CmdStoryPageButton, CommandFlag::Deity, CMDT_OTHER_MANAGEMENT) +DEF_CMD_TRAIT(CMD_CREATE_STORY_PAGE, CmdCreateStoryPage, CommandFlags({CommandFlag::Deity, CommandFlag::StrCtrl}), CommandType::OtherManagement) +DEF_CMD_TRAIT(CMD_CREATE_STORY_PAGE_ELEMENT, CmdCreateStoryPageElement, CommandFlags({CommandFlag::Deity, CommandFlag::StrCtrl}), CommandType::OtherManagement) +DEF_CMD_TRAIT(CMD_UPDATE_STORY_PAGE_ELEMENT, CmdUpdateStoryPageElement, CommandFlags({CommandFlag::Deity, CommandFlag::StrCtrl}), CommandType::OtherManagement) +DEF_CMD_TRAIT(CMD_SET_STORY_PAGE_TITLE, CmdSetStoryPageTitle, CommandFlags({CommandFlag::Deity, CommandFlag::StrCtrl}), CommandType::OtherManagement) +DEF_CMD_TRAIT(CMD_SET_STORY_PAGE_DATE, CmdSetStoryPageDate, CommandFlag::Deity, CommandType::OtherManagement) +DEF_CMD_TRAIT(CMD_SHOW_STORY_PAGE, CmdShowStoryPage, CommandFlag::Deity, CommandType::OtherManagement) +DEF_CMD_TRAIT(CMD_REMOVE_STORY_PAGE, CmdRemoveStoryPage, CommandFlag::Deity, CommandType::OtherManagement) +DEF_CMD_TRAIT(CMD_REMOVE_STORY_PAGE_ELEMENT, CmdRemoveStoryPageElement, CommandFlag::Deity, CommandType::OtherManagement) +DEF_CMD_TRAIT(CMD_STORY_PAGE_BUTTON, CmdStoryPageButton, CommandFlag::Deity, CommandType::OtherManagement) #endif /* STORY_CMD_H */ diff --git a/src/story_gui.cpp b/src/story_gui.cpp index f3c1d4feb0d86..1c2605e1b3ebe 100644 --- a/src/story_gui.cpp +++ b/src/story_gui.cpp @@ -937,7 +937,7 @@ const std::initializer_list Story &PageElementOrderSorter, }; -static constexpr NWidgetPart _nested_story_book_widgets[] = { +static constexpr std::initializer_list _nested_story_book_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_BROWN), NWidget(WWT_CAPTION, COLOUR_BROWN, WID_SB_CAPTION), diff --git a/src/strgen/strgen.h b/src/strgen/strgen.h index 8052107aa9725..f2e4b79014be0 100644 --- a/src/strgen/strgen.h +++ b/src/strgen/strgen.h @@ -137,6 +137,8 @@ struct CmdStruct; struct CmdPair { const CmdStruct *cmd; std::string param; + + auto operator<=>(const CmdPair &other) const = default; }; struct ParsedCommandStruct { diff --git a/src/strgen/strgen_base.cpp b/src/strgen/strgen_base.cpp index 6c733e2cd4845..8184ecf597ea8 100644 --- a/src/strgen/strgen_base.cpp +++ b/src/strgen/strgen_base.cpp @@ -313,9 +313,8 @@ void EmitGender(StringBuilder &builder, std::string_view param, char32_t) static const CmdStruct *FindCmd(std::string_view s) { - for (const auto &cs : _cmd_structs) { - if (cs.cmd == s) return &cs; - } + auto it = std::ranges::find(_cmd_structs, s, &CmdStruct::cmd); + if (it != std::end(_cmd_structs)) return &*it; return nullptr; } @@ -449,17 +448,11 @@ static bool CheckCommandsMatch(std::string_view a, std::string_view b, std::stri for (auto &templ_nc : templ.non_consuming_commands) { /* see if we find it in lang, and zero it out */ - bool found = false; - for (auto &lang_nc : lang.non_consuming_commands) { - if (templ_nc.cmd == lang_nc.cmd && templ_nc.param == lang_nc.param) { - /* it was found in both. zero it out from lang so we don't find it again */ - lang_nc.cmd = nullptr; - found = true; - break; - } - } - - if (!found) { + auto it = std::ranges::find(lang.non_consuming_commands, templ_nc); + if (it != std::end(lang.non_consuming_commands)) { + /* it was found in both. zero it out from lang so we don't find it again */ + it->cmd = nullptr; + } else { StrgenWarning("{}: command '{}' exists in template file but not in language file", name, templ_nc.cmd->cmd); result = false; } diff --git a/src/string.cpp b/src/string.cpp index 18827e59042db..09b3f7250d58c 100644 --- a/src/string.cpp +++ b/src/string.cpp @@ -28,7 +28,10 @@ #ifdef WITH_ICU_I18N /* Required by StrNaturalCompare. */ +# include +# include # include +# include # include "language.h" # include "gfx_func.h" #endif /* WITH_ICU_I18N */ @@ -453,8 +456,6 @@ int StrNaturalCompare(std::string_view s1, std::string_view s2, bool ignore_garb #ifdef WITH_ICU_I18N -#include - /** * Search if a string is contained in another string using the current locale. * @@ -601,9 +602,6 @@ bool ConvertHexToBytes(std::string_view hex, std::span bytes) #elif defined(WITH_ICU_I18N) -#include -#include - /** String iterator using ICU as a backend. */ class IcuStringIterator : public StringIterator { diff --git a/src/strings.cpp b/src/strings.cpp index f4ff461bc7c33..141027f0b791f 100644 --- a/src/strings.cpp +++ b/src/strings.cpp @@ -916,6 +916,7 @@ static const Units _units_height[] = { { { 3.0 }, STR_UNITS_HEIGHT_IMPERIAL, 0 }, // "Wrong" conversion factor for more nicer GUI values { { 1.0 }, STR_UNITS_HEIGHT_METRIC, 0 }, { { 1.0 }, STR_UNITS_HEIGHT_SI, 0 }, + { { .02 }, STR_UNITS_HEIGHT_GAMEUNITS,0 }, }; /** Unit conversions for time in calendar days or wallclock seconds */ @@ -2356,15 +2357,14 @@ class LanguagePackGlyphSearcher : public MissingGlyphSearcher { * mean it might use characters that are not in the * font, which is the whole reason this check has * been added. - * @param base_font Whether to look at the base font as well. * @param searcher The methods to use to search for strings to check. * If nullptr the loaded language pack searcher is used. */ -void CheckForMissingGlyphs(bool base_font, MissingGlyphSearcher *searcher) +void CheckForMissingGlyphs(MissingGlyphSearcher *searcher) { static LanguagePackGlyphSearcher pack_searcher; if (searcher == nullptr) searcher = &pack_searcher; - bool bad_font = !base_font || searcher->FindMissingGlyphs(); + bool bad_font = searcher->FindMissingGlyphs(); #if defined(WITH_FREETYPE) || defined(_WIN32) || defined(WITH_COCOA) if (bad_font) { /* We found an unprintable character... lets try whether we can find @@ -2390,7 +2390,7 @@ void CheckForMissingGlyphs(bool base_font, MissingGlyphSearcher *searcher) ShowErrorMessage(GetEncodedString(STR_JUST_RAW_STRING, std::move(err_str)), {}, WL_WARNING); } - if (bad_font && base_font) { + if (bad_font) { /* Our fallback font does miss characters too, so keep the * user chosen font as that is more likely to be any good than * the wild guess we made */ diff --git a/src/strings_func.h b/src/strings_func.h index 7bb9ae99ffd07..e883504b41c71 100644 --- a/src/strings_func.h +++ b/src/strings_func.h @@ -195,6 +195,6 @@ class MissingGlyphSearcher { bool FindMissingGlyphs(); }; -void CheckForMissingGlyphs(bool base_font = true, MissingGlyphSearcher *search = nullptr); +void CheckForMissingGlyphs(MissingGlyphSearcher *search = nullptr); #endif /* STRINGS_FUNC_H */ diff --git a/src/subsidy_cmd.h b/src/subsidy_cmd.h index a090774490fda..54eb2cfbbebc8 100644 --- a/src/subsidy_cmd.h +++ b/src/subsidy_cmd.h @@ -17,7 +17,7 @@ CommandCost CmdCreateSubsidy(DoCommandFlags flags, CargoType cargo_type, Source src, Source dst); -DEF_CMD_TRAIT(CMD_CREATE_SUBSIDY, CmdCreateSubsidy, CommandFlag::Deity, CMDT_OTHER_MANAGEMENT) +DEF_CMD_TRAIT(CMD_CREATE_SUBSIDY, CmdCreateSubsidy, CommandFlag::Deity, CommandType::OtherManagement) template diff --git a/src/subsidy_gui.cpp b/src/subsidy_gui.cpp index b57bcbe35ccc1..77c8807c7e11d 100644 --- a/src/subsidy_gui.cpp +++ b/src/subsidy_gui.cpp @@ -262,7 +262,7 @@ struct SubsidyListWindow : Window { } }; -static constexpr NWidgetPart _nested_subsidies_list_widgets[] = { +static constexpr std::initializer_list _nested_subsidies_list_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_BROWN), NWidget(WWT_CAPTION, COLOUR_BROWN), SetStringTip(STR_SUBSIDIES_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), diff --git a/src/table/engines.h b/src/table/engines.h index b5e745c1b2837..687a992b0b372 100644 --- a/src/table/engines.h +++ b/src/table/engines.h @@ -410,7 +410,7 @@ static constexpr EngineInfo _orig_engine_info[] = { #define RC_E PR_RUNNING_TRAIN_ELECTRIC #define RC_W INVALID_PRICE -static constexpr RailVehicleInfo _orig_rail_vehicle_info[] = { +static const RailVehicleInfo _orig_rail_vehicle_info[] = { /* image_index max_speed running_cost engclass * | type | power | running_cost_class * | | cost_factor | weight | | capacity diff --git a/src/table/railtypes.h b/src/table/railtypes.h index 0b0112322ebc1..2788212a96be6 100644 --- a/src/table/railtypes.h +++ b/src/table/railtypes.h @@ -25,7 +25,7 @@ static const RailTypeInfo _original_railtypes[] = { SPR_RAIL_SINGLE_NORTH, SPR_RAIL_SINGLE_SOUTH, SPR_RAIL_SINGLE_EAST, SPR_RAIL_SINGLE_WEST, SPR_TRACKS_FOR_SLOPES_RAIL_BASE, SPR_CROSSING_OFF_X_RAIL, - SPR_TUNNEL_ENTRY_REAR_RAIL + SPR_TUNNEL_ENTRY_REAR_RAIL, SPR_BRIDGE_DECKS_RAIL, }, /* GUI sprites */ @@ -123,7 +123,7 @@ static const RailTypeInfo _original_railtypes[] = { SPR_RAIL_SINGLE_NORTH, SPR_RAIL_SINGLE_SOUTH, SPR_RAIL_SINGLE_EAST, SPR_RAIL_SINGLE_WEST, SPR_TRACKS_FOR_SLOPES_RAIL_BASE, SPR_CROSSING_OFF_X_RAIL, - SPR_TUNNEL_ENTRY_REAR_RAIL + SPR_TUNNEL_ENTRY_REAR_RAIL, SPR_BRIDGE_DECKS_RAIL, }, /* GUI sprites */ @@ -225,7 +225,7 @@ static const RailTypeInfo _original_railtypes[] = { SPR_MONO_SINGLE_NORTH, SPR_MONO_SINGLE_SOUTH, SPR_MONO_SINGLE_EAST, SPR_MONO_SINGLE_WEST, SPR_TRACKS_FOR_SLOPES_MONO_BASE, SPR_CROSSING_OFF_X_MONO, - SPR_TUNNEL_ENTRY_REAR_MONO + SPR_TUNNEL_ENTRY_REAR_MONO, SPR_BRIDGE_DECKS_MONO, }, /* GUI sprites */ @@ -323,7 +323,7 @@ static const RailTypeInfo _original_railtypes[] = { SPR_MGLV_SINGLE_NORTH, SPR_MGLV_SINGLE_SOUTH, SPR_MGLV_SINGLE_EAST, SPR_MGLV_SINGLE_WEST, SPR_TRACKS_FOR_SLOPES_MAGLEV_BASE, SPR_CROSSING_OFF_X_MAGLEV, - SPR_TUNNEL_ENTRY_REAR_MAGLEV + SPR_TUNNEL_ENTRY_REAR_MAGLEV, SPR_BRIDGE_DECKS_MGLV, }, /* GUI sprites */ diff --git a/src/table/settings/locale_settings.ini b/src/table/settings/locale_settings.ini index c5c0a520bf10f..1296f15332190 100644 --- a/src/table/settings/locale_settings.ini +++ b/src/table/settings/locale_settings.ini @@ -163,7 +163,7 @@ type = SLE_UINT8 from = SLV_184 flags = SettingFlag::NoNetworkSync, SettingFlag::GuiDropdown def = 1 -max = 2 +max = 3 full = _locale_units post_cb = [](auto) { MarkWholeScreenDirty(); } cat = SC_BASIC diff --git a/src/table/settings/world_settings.ini b/src/table/settings/world_settings.ini index a4c97cf8546a1..f17bf4d7293f8 100644 --- a/src/table/settings/world_settings.ini +++ b/src/table/settings/world_settings.ini @@ -268,6 +268,13 @@ def = 15 min = 0 max = 16 +[SDT_VAR] +var = game_creation.water_border_presets +type = SLE_UINT8 +def = BFP_RANDOM +min = BFP_RANDOM +max = BFP_INFINITE_WATER + [SDT_VAR] var = game_creation.custom_town_number type = SLE_UINT16 diff --git a/src/table/sprites.h b/src/table/sprites.h index 573bead42fdef..caef133af7e97 100644 --- a/src/table/sprites.h +++ b/src/table/sprites.h @@ -321,8 +321,16 @@ static const uint16_t ROAD_WAYPOINTS_SPRITE_COUNT = 4; static constexpr SpriteID SPR_OVERLAY_ROCKS_BASE = SPR_ROAD_WAYPOINTS_BASE + ROAD_WAYPOINTS_SPRITE_COUNT; static constexpr uint16_t OVERLAY_ROCKS_SPRITE_COUNT = 19 * 5; /* Rock overlays: plain, snow 1, snow 2, snow 3 and full snow. */ +/** Bridge deck sprites. */ +static constexpr SpriteID SPR_BRIDGE_DECKS_BASE = SPR_OVERLAY_ROCKS_BASE + OVERLAY_ROCKS_SPRITE_COUNT; +static constexpr uint16_t BRIDGE_DECKS_SPRITE_COUNT = 6 * 4; /* Bridge deck sprites: 6 directions * (3 track types + 1 road type). */ +static const SpriteID SPR_BRIDGE_DECKS_RAIL = SPR_BRIDGE_DECKS_BASE + 0; +static const SpriteID SPR_BRIDGE_DECKS_MONO = SPR_BRIDGE_DECKS_BASE + 6; +static const SpriteID SPR_BRIDGE_DECKS_MGLV = SPR_BRIDGE_DECKS_BASE + 12; +static const SpriteID SPR_BRIDGE_DECKS_ROAD = SPR_BRIDGE_DECKS_BASE + 18; + /* From where can we start putting NewGRFs? */ -static const SpriteID SPR_NEWGRFS_BASE = SPR_OVERLAY_ROCKS_BASE + OVERLAY_ROCKS_SPRITE_COUNT; +static const SpriteID SPR_NEWGRFS_BASE = SPR_BRIDGE_DECKS_BASE + BRIDGE_DECKS_SPRITE_COUNT; /* Manager face sprites */ static const SpriteID SPR_GRADIENT = 874; // background gradient behind manager face diff --git a/src/terraform_cmd.h b/src/terraform_cmd.h index 8d4dea20d55fb..a4bfff5f99b44 100644 --- a/src/terraform_cmd.h +++ b/src/terraform_cmd.h @@ -17,8 +17,8 @@ std::tuple CmdTerraformLand(DoCommandFlags flags, TileIndex tile, Slope slope, bool dir_up); std::tuple CmdLevelLand(DoCommandFlags flags, TileIndex tile, TileIndex start_tile, bool diagonal, LevelMode lm); -DEF_CMD_TRAIT(CMD_TERRAFORM_LAND, CmdTerraformLand, CommandFlags({CommandFlag::AllTiles, CommandFlag::Auto}), CMDT_LANDSCAPE_CONSTRUCTION) -DEF_CMD_TRAIT(CMD_LEVEL_LAND, CmdLevelLand, CommandFlags({CommandFlag::AllTiles, CommandFlag::Auto, CommandFlag::NoTest}), CMDT_LANDSCAPE_CONSTRUCTION) // test run might clear tiles multiple times, in execution that only happens once +DEF_CMD_TRAIT(CMD_TERRAFORM_LAND, CmdTerraformLand, CommandFlags({CommandFlag::AllTiles, CommandFlag::Auto}), CommandType::LandscapeConstruction) +DEF_CMD_TRAIT(CMD_LEVEL_LAND, CmdLevelLand, CommandFlags({CommandFlag::AllTiles, CommandFlag::Auto, CommandFlag::NoTest}), CommandType::LandscapeConstruction) // test run might clear tiles multiple times, in execution that only happens once CommandCallback CcPlaySound_EXPLOSION; void CcTerraform(Commands cmd, const CommandCost &result, Money, TileIndex tile); diff --git a/src/terraform_gui.cpp b/src/terraform_gui.cpp index ab81c7004f8e0..14a4597e1fafb 100644 --- a/src/terraform_gui.cpp +++ b/src/terraform_gui.cpp @@ -155,7 +155,7 @@ void PlaceProc_DemolishArea(TileIndex tile) /** Terra form toolbar managing class. */ struct TerraformToolbarWindow : Window { - int last_user_action = INVALID_WID_TT; ///< Last started user action. + WidgetID last_user_action = INVALID_WIDGET; ///< Last started user action. TerraformToolbarWindow(WindowDesc &desc, WindowNumber window_number) : Window(desc) { @@ -257,7 +257,8 @@ struct TerraformToolbarWindow : Window { Point OnInitialPosition([[maybe_unused]] int16_t sm_width, [[maybe_unused]] int16_t sm_height, [[maybe_unused]] int window_number) override { Point pt = GetToolbarAlignedWindowPosition(sm_width); - pt.y += sm_height; + if (FindWindowByClass(WC_BUILD_TOOLBAR) != nullptr && !_settings_client.gui.link_terraform_toolbar) pt.y += sm_height; + return pt; } @@ -316,7 +317,7 @@ struct TerraformToolbarWindow : Window { }, TerraformToolbarGlobalHotkeys}; }; -static constexpr NWidgetPart _nested_terraform_widgets[] = { +static constexpr std::initializer_list _nested_terraform_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN), NWidget(WWT_CAPTION, COLOUR_DARK_GREEN), SetStringTip(STR_LANDSCAPING_TOOLBAR, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), @@ -364,19 +365,13 @@ Window *ShowTerraformToolbar(Window *link) { if (!Company::IsValidID(_local_company)) return nullptr; - Window *w; - if (link == nullptr) { - w = AllocateWindowDescFront(_terraform_desc, 0); - return w; - } - /* Delete the terraform toolbar to place it again. */ CloseWindowById(WC_SCEN_LAND_GEN, 0, true); - w = AllocateWindowDescFront(_terraform_desc, 0); - /* Align the terraform toolbar under the main toolbar. */ - w->top -= w->height; - w->SetDirty(); - /* Put the linked toolbar to the left / right of it. */ + + if (link == nullptr) return AllocateWindowDescFront(_terraform_desc, 0); + + Window *w = AllocateWindowDescFront(_terraform_desc, 0); + /* Put the linked toolbar to the left / right of the main toolbar. */ link->left = w->left + (_current_text_dir == TD_RTL ? w->width : -link->width); link->top = w->top; link->SetDirty(); @@ -445,7 +440,7 @@ static const int8_t _multi_terraform_coords[][2] = { {-28, 0}, {-24, -2}, {-20, -4}, {-16, -6}, {-12, -8}, { -8,-10}, { -4,-12}, { 0,-14}, { 4,-12}, { 8,-10}, { 12, -8}, { 16, -6}, { 20, -4}, { 24, -2}, { 28, 0}, }; -static constexpr NWidgetPart _nested_scen_edit_land_gen_widgets[] = { +static constexpr std::initializer_list _nested_scen_edit_land_gen_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN), NWidget(WWT_CAPTION, COLOUR_DARK_GREEN), SetStringTip(STR_TERRAFORM_TOOLBAR_LAND_GENERATION_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), @@ -529,7 +524,7 @@ static void ResetLandscapeConfirmationCallback(Window *, bool confirmed) /** Landscape generation window handler in the scenario editor. */ struct ScenarioEditorLandscapeGenerationWindow : Window { - int last_user_action = INVALID_WID_ETT; ///< Last started user action. + WidgetID last_user_action = INVALID_WIDGET; ///< Last started user action. ScenarioEditorLandscapeGenerationWindow(WindowDesc &desc, WindowNumber window_number) : Window(desc) { diff --git a/src/texteff.cpp b/src/texteff.cpp index 82f832e2ded33..36b7a35c231a0 100644 --- a/src/texteff.cpp +++ b/src/texteff.cpp @@ -90,7 +90,7 @@ void RemoveTextEffect(TextEffectID te_id) /** Slowly move text effects upwards. */ const IntervalTimer move_all_text_effects_interval = {std::chrono::milliseconds(30), [](uint count) { - if (_pause_mode.Any() && _game_mode != GM_EDITOR && _settings_game.construction.command_pause_level <= CMDPL_NO_CONSTRUCTION) return; + if (_pause_mode.Any() && _game_mode != GM_EDITOR && _settings_game.construction.command_pause_level <= CommandPauseLevel::NoConstruction) return; for (TextEffect &te : _text_effects) { if (!te.IsValid()) continue; diff --git a/src/textfile_gui.cpp b/src/textfile_gui.cpp index 75650c52ef021..115467f397eb5 100644 --- a/src/textfile_gui.cpp +++ b/src/textfile_gui.cpp @@ -40,7 +40,7 @@ #include "safeguards.h" /** Widgets for the textfile window. */ -static constexpr NWidgetPart _nested_textfile_widgets[] = { +static constexpr std::initializer_list _nested_textfile_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_MAUVE), NWidget(WWT_PUSHARROWBTN, COLOUR_MAUVE, WID_TF_NAVBACK), SetFill(0, 1), SetMinimalSize(15, 1), SetArrowWidgetTypeTip(AWV_DECREASE, STR_TEXTFILE_NAVBACK_TOOLTIP), @@ -923,7 +923,7 @@ void TextfileWindow::LoadText(std::string_view buf) this->AfterLoadText(); this->ReflowContent(); - CheckForMissingGlyphs(true, this); + CheckForMissingGlyphs(this); /* The font may have changed when searching for glyphs, so ensure widget sizes are updated just in case. */ this->ReInit(); diff --git a/src/timetable_cmd.h b/src/timetable_cmd.h index 221b394174059..45879234de730 100644 --- a/src/timetable_cmd.h +++ b/src/timetable_cmd.h @@ -21,10 +21,10 @@ CommandCost CmdSetVehicleOnTime(DoCommandFlags flags, VehicleID veh, bool apply_ CommandCost CmdAutofillTimetable(DoCommandFlags flags, VehicleID veh, bool autofill, bool preserve_wait_time); CommandCost CmdSetTimetableStart(DoCommandFlags flags, VehicleID veh_id, bool timetable_all, TimerGameTick::TickCounter start_tick); -DEF_CMD_TRAIT(CMD_CHANGE_TIMETABLE, CmdChangeTimetable, {}, CMDT_ROUTE_MANAGEMENT) -DEF_CMD_TRAIT(CMD_BULK_CHANGE_TIMETABLE, CmdBulkChangeTimetable, {}, CMDT_ROUTE_MANAGEMENT) -DEF_CMD_TRAIT(CMD_SET_VEHICLE_ON_TIME, CmdSetVehicleOnTime, {}, CMDT_ROUTE_MANAGEMENT) -DEF_CMD_TRAIT(CMD_AUTOFILL_TIMETABLE, CmdAutofillTimetable, {}, CMDT_ROUTE_MANAGEMENT) -DEF_CMD_TRAIT(CMD_SET_TIMETABLE_START, CmdSetTimetableStart, {}, CMDT_ROUTE_MANAGEMENT) +DEF_CMD_TRAIT(CMD_CHANGE_TIMETABLE, CmdChangeTimetable, {}, CommandType::RouteManagement) +DEF_CMD_TRAIT(CMD_BULK_CHANGE_TIMETABLE, CmdBulkChangeTimetable, {}, CommandType::RouteManagement) +DEF_CMD_TRAIT(CMD_SET_VEHICLE_ON_TIME, CmdSetVehicleOnTime, {}, CommandType::RouteManagement) +DEF_CMD_TRAIT(CMD_AUTOFILL_TIMETABLE, CmdAutofillTimetable, {}, CommandType::RouteManagement) +DEF_CMD_TRAIT(CMD_SET_TIMETABLE_START, CmdSetTimetableStart, {}, CommandType::RouteManagement) #endif /* TIMETABLE_CMD_H */ diff --git a/src/timetable_gui.cpp b/src/timetable_gui.cpp index 65732342b0e46..ea3e253e59586 100644 --- a/src/timetable_gui.cpp +++ b/src/timetable_gui.cpp @@ -797,7 +797,7 @@ struct TimetableWindow : Window { }}; }; -static constexpr NWidgetPart _nested_timetable_widgets[] = { +static constexpr std::initializer_list _nested_timetable_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), NWidget(WWT_CAPTION, COLOUR_GREY, WID_VT_CAPTION), diff --git a/src/toolbar_gui.cpp b/src/toolbar_gui.cpp index 8f71d93f1c3c4..b37ef7e837304 100644 --- a/src/toolbar_gui.cpp +++ b/src/toolbar_gui.cpp @@ -117,7 +117,6 @@ class DropDownListCompanyItem : public DropDownIconresult; ShowDropDownList(w, std::move(list), selected, WID_TN_LEAGUE, 140, _settings_client.gui.toolbar_dropdown_autoselect); - SndClickBeep(); - return CBF_NONE; } @@ -876,7 +870,6 @@ static CallBackFunction ToolbarZoomOutClick(Window *w) static CallBackFunction ToolbarBuildRailClick(Window *w) { ShowDropDownList(w, GetRailTypeDropDownList(), _last_built_railtype, WID_TN_RAILS, 140, _settings_client.gui.toolbar_dropdown_autoselect); - SndClickBeep(); return CBF_NONE; } @@ -898,7 +891,6 @@ static CallBackFunction MenuClickBuildRail(int index) static CallBackFunction ToolbarBuildRoadClick(Window *w) { ShowDropDownList(w, GetRoadTypeDropDownList(RTTB_ROAD), _last_built_roadtype, WID_TN_ROADS, 140, _settings_client.gui.toolbar_dropdown_autoselect); - SndClickBeep(); return CBF_NONE; } @@ -920,7 +912,6 @@ static CallBackFunction MenuClickBuildRoad(int index) static CallBackFunction ToolbarBuildTramClick(Window *w) { ShowDropDownList(w, GetRoadTypeDropDownList(RTTB_TRAM), _last_built_tramtype, WID_TN_TRAMS, 140, _settings_client.gui.toolbar_dropdown_autoselect); - SndClickBeep(); return CBF_NONE; } @@ -944,7 +935,6 @@ static CallBackFunction ToolbarBuildWaterClick(Window *w) DropDownList list; list.push_back(MakeDropDownListIconItem(SPR_IMG_BUILD_CANAL, PAL_NONE, STR_WATERWAYS_MENU_WATERWAYS_CONSTRUCTION, 0)); ShowDropDownList(w, std::move(list), 0, WID_TN_WATER, 140, _settings_client.gui.toolbar_dropdown_autoselect); - SndClickBeep(); return CBF_NONE; } @@ -966,7 +956,6 @@ static CallBackFunction ToolbarBuildAirClick(Window *w) DropDownList list; list.push_back(MakeDropDownListIconItem(SPR_IMG_AIRPORT, PAL_NONE, STR_AIRCRAFT_MENU_AIRPORT_CONSTRUCTION, 0)); ShowDropDownList(w, std::move(list), 0, WID_TN_AIR, 140, _settings_client.gui.toolbar_dropdown_autoselect); - SndClickBeep(); return CBF_NONE; } @@ -990,7 +979,6 @@ static CallBackFunction ToolbarForestClick(Window *w) list.push_back(MakeDropDownListIconItem(SPR_IMG_PLANTTREES, PAL_NONE, STR_LANDSCAPING_MENU_PLANT_TREES, 1)); list.push_back(MakeDropDownListIconItem(SPR_IMG_SIGN, PAL_NONE, STR_LANDSCAPING_MENU_PLACE_SIGN, 2)); ShowDropDownList(w, std::move(list), 0, WID_TN_LANDSCAPE, 100, _settings_client.gui.toolbar_dropdown_autoselect); - SndClickBeep(); return CBF_NONE; } @@ -1260,7 +1248,6 @@ static CallBackFunction ToolbarScenGenIndustry(Window *w) static CallBackFunction ToolbarScenBuildRoadClick(Window *w) { ShowDropDownList(w, GetScenRoadTypeDropDownList(RTTB_ROAD), _last_built_roadtype, WID_TE_ROADS, 140, _settings_client.gui.toolbar_dropdown_autoselect); - SndClickBeep(); return CBF_NONE; } @@ -1280,7 +1267,6 @@ static CallBackFunction ToolbarScenBuildRoad(int index) static CallBackFunction ToolbarScenBuildTramClick(Window *w) { ShowDropDownList(w, GetScenRoadTypeDropDownList(RTTB_TRAM), _last_built_tramtype, WID_TE_TRAMS, 140, _settings_client.gui.toolbar_dropdown_autoselect); - SndClickBeep(); return CBF_NONE; } @@ -2109,15 +2095,6 @@ struct MainToolbarWindow : Window { } }}; - void OnTimeout() override - { - /* We do not want to automatically raise the pause, fast forward and - * switchbar buttons; they have to stay down when pressed etc. */ - for (WidgetID i = WID_TN_SETTINGS; i < WID_TN_SWITCH_BAR; i++) { - this->RaiseWidgetWhenLowered(i); - } - } - /** * Some data on this window has become invalid. * @param data Information about the changed data. @@ -2176,43 +2153,43 @@ struct MainToolbarWindow : Window { static std::unique_ptr MakeMainToolbar() { /** Sprites to use for the different toolbar buttons */ - static const SpriteID toolbar_button_sprites[] = { - SPR_IMG_PAUSE, // WID_TN_PAUSE - SPR_IMG_FASTFORWARD, // WID_TN_FAST_FORWARD - SPR_IMG_SETTINGS, // WID_TN_SETTINGS - SPR_IMG_SAVE, // WID_TN_SAVE - SPR_IMG_SMALLMAP, // WID_TN_SMALL_MAP - SPR_IMG_TOWN, // WID_TN_TOWNS - SPR_IMG_SUBSIDIES, // WID_TN_SUBSIDIES - SPR_IMG_COMPANY_LIST, // WID_TN_STATIONS - SPR_IMG_COMPANY_FINANCE, // WID_TN_FINANCES - SPR_IMG_COMPANY_GENERAL, // WID_TN_COMPANIES - SPR_IMG_STORY_BOOK, // WID_TN_STORY - SPR_IMG_GOAL, // WID_TN_GOAL - SPR_IMG_GRAPHS, // WID_TN_GRAPHS - SPR_IMG_COMPANY_LEAGUE, // WID_TN_LEAGUE - SPR_IMG_INDUSTRY, // WID_TN_INDUSTRIES - SPR_IMG_TRAINLIST, // WID_TN_TRAINS - SPR_IMG_TRUCKLIST, // WID_TN_ROADVEHS - SPR_IMG_SHIPLIST, // WID_TN_SHIPS - SPR_IMG_AIRPLANESLIST, // WID_TN_AIRCRAFT - SPR_IMG_ZOOMIN, // WID_TN_ZOOMIN - SPR_IMG_ZOOMOUT, // WID_TN_ZOOMOUT - SPR_IMG_BUILDRAIL, // WID_TN_RAILS - SPR_IMG_BUILDROAD, // WID_TN_ROADS - SPR_IMG_BUILDTRAMS, // WID_TN_TRAMS - SPR_IMG_BUILDWATER, // WID_TN_WATER - SPR_IMG_BUILDAIR, // WID_TN_AIR - SPR_IMG_LANDSCAPING, // WID_TN_LANDSCAPE - SPR_IMG_MUSIC, // WID_TN_MUSIC_SOUND - SPR_IMG_MESSAGES, // WID_TN_MESSAGES - SPR_IMG_QUERY, // WID_TN_HELP - SPR_IMG_SWITCH_TOOLBAR, // WID_TN_SWITCH_BAR + static const std::tuple toolbar_button_sprites[] = { + {WID_TN_PAUSE, WWT_IMGBTN, SPR_IMG_PAUSE}, + {WID_TN_FAST_FORWARD, WWT_IMGBTN, SPR_IMG_FASTFORWARD}, + {WID_TN_SETTINGS, WWT_IMGBTN, SPR_IMG_SETTINGS}, + {WID_TN_SAVE, WWT_IMGBTN_2, SPR_IMG_SAVE}, + {WID_TN_SMALL_MAP, WWT_IMGBTN, SPR_IMG_SMALLMAP}, + {WID_TN_TOWNS, WWT_IMGBTN, SPR_IMG_TOWN}, + {WID_TN_SUBSIDIES, WWT_IMGBTN, SPR_IMG_SUBSIDIES}, + {WID_TN_STATIONS, WWT_IMGBTN, SPR_IMG_COMPANY_LIST}, + {WID_TN_FINANCES, WWT_IMGBTN, SPR_IMG_COMPANY_FINANCE}, + {WID_TN_COMPANIES, WWT_IMGBTN, SPR_IMG_COMPANY_GENERAL}, + {WID_TN_STORY, WWT_IMGBTN, SPR_IMG_STORY_BOOK}, + {WID_TN_GOAL, WWT_IMGBTN, SPR_IMG_GOAL}, + {WID_TN_GRAPHS, WWT_IMGBTN, SPR_IMG_GRAPHS}, + {WID_TN_LEAGUE, WWT_IMGBTN, SPR_IMG_COMPANY_LEAGUE}, + {WID_TN_INDUSTRIES, WWT_IMGBTN, SPR_IMG_INDUSTRY}, + {WID_TN_TRAINS, WWT_IMGBTN, SPR_IMG_TRAINLIST}, + {WID_TN_ROADVEHS, WWT_IMGBTN, SPR_IMG_TRUCKLIST}, + {WID_TN_SHIPS, WWT_IMGBTN, SPR_IMG_SHIPLIST}, + {WID_TN_AIRCRAFT, WWT_IMGBTN, SPR_IMG_AIRPLANESLIST}, + {WID_TN_ZOOM_IN, WWT_PUSHIMGBTN, SPR_IMG_ZOOMIN}, + {WID_TN_ZOOM_OUT, WWT_PUSHIMGBTN, SPR_IMG_ZOOMOUT}, + {WID_TN_RAILS, WWT_IMGBTN, SPR_IMG_BUILDRAIL}, + {WID_TN_ROADS, WWT_IMGBTN, SPR_IMG_BUILDROAD}, + {WID_TN_TRAMS, WWT_IMGBTN, SPR_IMG_BUILDTRAMS}, + {WID_TN_WATER, WWT_IMGBTN, SPR_IMG_BUILDWATER}, + {WID_TN_AIR, WWT_IMGBTN, SPR_IMG_BUILDAIR}, + {WID_TN_LANDSCAPE, WWT_IMGBTN, SPR_IMG_LANDSCAPING}, + {WID_TN_MUSIC_SOUND, WWT_IMGBTN, SPR_IMG_MUSIC}, + {WID_TN_MESSAGES, WWT_IMGBTN, SPR_IMG_MESSAGES}, + {WID_TN_HELP, WWT_IMGBTN, SPR_IMG_QUERY}, + {WID_TN_SWITCH_BAR, WWT_IMGBTN, SPR_IMG_SWITCH_TOOLBAR}, }; auto hor = std::make_unique(); - for (WidgetID i = 0; i < WID_TN_END; i++) { - switch (i) { + for (const auto &[widget, tp, sprite] : toolbar_button_sprites) { + switch (widget) { case WID_TN_SMALL_MAP: case WID_TN_FINANCES: case WID_TN_VEHICLE_START: @@ -2222,7 +2199,7 @@ static std::unique_ptr MakeMainToolbar() hor->Add(std::make_unique(0, 0)); break; } - auto leaf = std::make_unique(i == WID_TN_SAVE ? WWT_IMGBTN_2 : WWT_IMGBTN, COLOUR_GREY, i, WidgetData{.sprite = toolbar_button_sprites[i]}, STR_TOOLBAR_TOOLTIP_PAUSE_GAME + i); + auto leaf = std::make_unique(tp, COLOUR_GREY, widget, WidgetData{.sprite = sprite}, STR_TOOLBAR_TOOLTIP_PAUSE_GAME + widget); leaf->SetMinimalSize(20, 20); hor->Add(std::move(leaf)); } @@ -2230,7 +2207,7 @@ static std::unique_ptr MakeMainToolbar() return hor; } -static constexpr NWidgetPart _nested_toolbar_normal_widgets[] = { +static constexpr std::initializer_list _nested_toolbar_normal_widgets = { NWidgetFunction(MakeMainToolbar), }; @@ -2533,7 +2510,7 @@ struct ScenarioEditorToolbarWindow : Window { }}; }; -static constexpr NWidgetPart _nested_toolb_scen_inner_widgets[] = { +static constexpr std::initializer_list _nested_toolb_scen_inner_widgets = { NWidget(WWT_IMGBTN, COLOUR_GREY, WID_TE_PAUSE), SetSpriteTip(SPR_IMG_PAUSE, STR_TOOLBAR_TOOLTIP_PAUSE_GAME), NWidget(WWT_IMGBTN, COLOUR_GREY, WID_TE_FAST_FORWARD), SetSpriteTip(SPR_IMG_FASTFORWARD, STR_TOOLBAR_TOOLTIP_FORWARD), NWidget(WWT_IMGBTN, COLOUR_GREY, WID_TE_SETTINGS), SetSpriteTip(SPR_IMG_SETTINGS, STR_TOOLBAR_TOOLTIP_OPTIONS), @@ -2555,7 +2532,7 @@ static constexpr NWidgetPart _nested_toolb_scen_inner_widgets[] = { NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_TE_ZOOM_OUT), SetSpriteTip(SPR_IMG_ZOOMOUT, STR_TOOLBAR_TOOLTIP_ZOOM_THE_VIEW_OUT), NWidget(NWID_SPACER), NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_TE_LAND_GENERATE), SetSpriteTip(SPR_IMG_LANDSCAPING, STR_SCENEDIT_TOOLBAR_LANDSCAPE_GENERATION_TOOLTIP), - NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_TE_TOWN_GENERATE), SetSpriteTip(SPR_IMG_TOWN, STR_SCENEDIT_TOOLBAR_TOWN_GENERATION_TOOLTIP), + NWidget(WWT_IMGBTN, COLOUR_GREY, WID_TE_TOWN_GENERATE), SetSpriteTip(SPR_IMG_TOWN, STR_SCENEDIT_TOOLBAR_TOWN_GENERATION_TOOLTIP), NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_TE_INDUSTRY), SetSpriteTip(SPR_IMG_INDUSTRY, STR_SCENEDIT_TOOLBAR_INDUSTRY_GENERATION_TOOLTIP), NWidget(WWT_IMGBTN, COLOUR_GREY, WID_TE_ROADS), SetSpriteTip(SPR_IMG_BUILDROAD, STR_SCENEDIT_TOOLBAR_ROAD_CONSTRUCTION_TOOLTIP), NWidget(WWT_IMGBTN, COLOUR_GREY, WID_TE_TRAMS), SetSpriteTip(SPR_IMG_BUILDTRAMS, STR_SCENEDIT_TOOLBAR_TRAM_CONSTRUCTION_TOOLTIP), @@ -2573,7 +2550,7 @@ static std::unique_ptr MakeScenarioToolbar() return MakeNWidgets(_nested_toolb_scen_inner_widgets, std::make_unique()); } -static constexpr NWidgetPart _nested_toolb_scen_widgets[] = { +static constexpr std::initializer_list _nested_toolb_scen_widgets = { NWidgetFunction(MakeScenarioToolbar), }; diff --git a/src/town.h b/src/town.h index a8786767c9319..5151e3c87cfe6 100644 --- a/src/town.h +++ b/src/town.h @@ -37,6 +37,16 @@ static const uint16_t MAX_TOWN_GROWTH_TICKS = 930; ///< Max amount of original t typedef Pool TownPool; extern TownPool _town_pool; +/** Flags controlling various town behaviours. */ +enum class TownFlag : uint8_t { + IsGrowing = 0, ///< Conditions for town growth are met. Grow according to Town::growth_rate. + HasChurch = 1, ///< There can be only one church by town. + HasStadium = 2, ///< There can be only one stadium by town. + CustomGrowth = 3, ///< Growth rate is controlled by GS. +}; + +using TownFlags = EnumBitSet; + /** Data structure with cached data of towns. */ struct TownCache { uint32_t num_houses = 0; ///< Amount of houses @@ -62,7 +72,7 @@ struct Town : TownPool::PoolItem<&_town_pool> { std::string name{}; ///< Custom town name. If empty, the town was not renamed and uses the generated name. mutable std::string cached_name{}; ///< NOSAVE: Cache of the resolved name of the town, if not using a custom town name - uint8_t flags = 0; ///< See #TownFlags. + TownFlags flags{}; ///< See #TownFlags. uint16_t noise_reached = 0; ///< level of noise that all the airports are generating @@ -211,10 +221,10 @@ enum TownCouncilAttitudes { * Action types that a company must ask permission for to a town authority. * @see CheckforTownRating */ -enum TownRatingCheckType { - ROAD_REMOVE = 0, ///< Removal of a road owned by the town. - TUNNELBRIDGE_REMOVE = 1, ///< Removal of a tunnel or bridge owned by the town. - TOWN_RATING_CHECK_TYPE_COUNT, ///< Number of town checking action types. +enum class TownRatingCheckType : uint8_t { + RoadRemove, ///< Removal of a road owned by the town. + TunnelBridgeRemove, ///< Removal of a tunnel or bridge owned by the town. + End, }; /** Special values for town list window for the data parameter of #InvalidateWindowData. */ @@ -224,20 +234,6 @@ enum TownDirectoryInvalidateWindowData { TDIWD_FORCE_RESORT, }; -/** - * This enum is used in conjunction with town->flags. - * IT simply states what bit is used for. - * It is pretty unrealistic (IMHO) to only have one church/stadium - * per town, NO MATTER the population of it. - * And there are 5 more bits available on flags... - */ -enum TownFlags { - TOWN_IS_GROWING = 0, ///< Conditions for town growth are met. Grow according to Town::growth_rate. - TOWN_HAS_CHURCH = 1, ///< There can be only one church by town. - TOWN_HAS_STADIUM = 2, ///< There can be only one stadium by town. - TOWN_CUSTOM_GROWTH = 3, ///< Growth rate is controlled by GS. -}; - CommandCost CheckforTownRating(DoCommandFlags flags, Town *t, TownRatingCheckType type); diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp index bcb03da78e8bb..6d2273115e30d 100644 --- a/src/town_cmd.cpp +++ b/src/town_cmd.cpp @@ -55,6 +55,7 @@ #include "road_cmd.h" #include "terraform_cmd.h" #include "tunnelbridge_cmd.h" +#include "map_func.h" #include "timer/timer.h" #include "timer/timer_game_calendar.h" #include "timer/timer_game_economy.h" @@ -666,7 +667,7 @@ static void TileLoop_Town(TileIndex tile) Backup cur_company(_current_company, OWNER_TOWN); if (hs->building_flags.Any(BUILDING_HAS_1_TILE) && - HasBit(t->flags, TOWN_IS_GROWING) && + t->flags.Test(TownFlag::IsGrowing) && CanDeleteHouse(tile) && GetHouseAge(tile) >= hs->minimum_life && --t->time_until_rebuild == 0) { @@ -917,7 +918,7 @@ static bool GrowTown(Town *t, TownExpandModes modes); */ static void TownTickHandler(Town *t) { - if (HasBit(t->flags, TOWN_IS_GROWING)) { + if (t->flags.Test(TownFlag::IsGrowing)) { TownExpandModes modes{TownExpandMode::Buildings}; if (_settings_game.economy.allow_town_roads) modes.Set(TownExpandMode::Roads); int i = (int)t->grow_counter - 1; @@ -965,14 +966,9 @@ RoadType GetTownRoadType() const RoadTypeInfo *best = nullptr; const uint16_t assume_max_speed = 50; - for (RoadType rt = ROADTYPE_BEGIN; rt != ROADTYPE_END; rt++) { - if (RoadTypeIsTram(rt)) continue; - + for (RoadType rt : GetMaskForRoadTramType(RTT_ROAD)) { const RoadTypeInfo *rti = GetRoadTypeInfo(rt); - /* Unused road type. */ - if (rti->label == 0) continue; - /* Can town build this road. */ if (!rti->flags.Test(RoadTypeFlag::TownBuild)) continue; @@ -997,10 +993,9 @@ RoadType GetTownRoadType() static TimerGameCalendar::Date GetTownRoadTypeFirstIntroductionDate() { const RoadTypeInfo *best = nullptr; - for (RoadType rt = ROADTYPE_BEGIN; rt != ROADTYPE_END; rt++) { - if (RoadTypeIsTram(rt)) continue; + for (RoadType rt : GetMaskForRoadTramType(RTT_ROAD)) { const RoadTypeInfo *rti = GetRoadTypeInfo(rt); - if (rti->label == 0) continue; // Unused road type. + if (!rti->flags.Test(RoadTypeFlag::TownBuild)) continue; // Town can't build this road type. if (best != nullptr && rti->introduction_date >= best->introduction_date) continue; @@ -1382,8 +1377,8 @@ static bool GrowTownWithBridge(const Town *t, const TileIndex tile, const DiagDi /* Can we actually build the bridge? */ RoadType rt = GetTownRoadType(); - if (Command::Do(CommandFlagsToDCFlags(GetCommandFlags()), tile, bridge_tile, TRANSPORT_ROAD, bridge_type, rt).Succeeded()) { - Command::Do(CommandFlagsToDCFlags(GetCommandFlags()).Set(DoCommandFlag::Execute), tile, bridge_tile, TRANSPORT_ROAD, bridge_type, rt); + if (Command::Do(CommandFlagsToDCFlags(GetCommandFlags()), tile, bridge_tile, TRANSPORT_ROAD, bridge_type, INVALID_RAILTYPE, rt).Succeeded()) { + Command::Do(CommandFlagsToDCFlags(GetCommandFlags()).Set(DoCommandFlag::Execute), tile, bridge_tile, TRANSPORT_ROAD, bridge_type, INVALID_RAILTYPE, rt); return true; } } @@ -1452,8 +1447,8 @@ static bool GrowTownWithTunnel(const Town *t, const TileIndex tile, const DiagDi /* Attempt to build the tunnel. Return false if it fails to let the town build a road instead. */ RoadType rt = GetTownRoadType(); - if (Command::Do(CommandFlagsToDCFlags(GetCommandFlags()), tile, TRANSPORT_ROAD, rt).Succeeded()) { - Command::Do(CommandFlagsToDCFlags(GetCommandFlags()).Set(DoCommandFlag::Execute), tile, TRANSPORT_ROAD, rt); + if (Command::Do(CommandFlagsToDCFlags(GetCommandFlags()), tile, TRANSPORT_ROAD, INVALID_RAILTYPE, rt).Succeeded()) { + Command::Do(CommandFlagsToDCFlags(GetCommandFlags()).Set(DoCommandFlag::Execute), tile, TRANSPORT_ROAD, INVALID_RAILTYPE, rt); return true; } @@ -2046,7 +2041,7 @@ static void DoCreateTown(Town *t, TileIndex tile, uint32_t townnameparts, TownSi t->cache.num_houses = 0; t->time_until_rebuild = 10; UpdateTownRadius(t); - t->flags = 0; + t->flags.Reset(); t->cache.population = 0; InitializeBuildingCounts(t); /* Spread growth across ticks so even if there are many @@ -2428,7 +2423,7 @@ bool GenerateTowns(TownLayout layout, std::optional number) } else if (_settings_game.difficulty.number_towns == static_cast(CUSTOM_TOWN_NUMBER_DIFFICULTY)) { total = GetDefaultTownsForMapSize(); } else { - total = GetDefaultTownsForMapSize() + (Random() & 7); + total = Map::ScaleByLandProportion(GetDefaultTownsForMapSize() + (Random() & 7)); } total = std::min(TownPool::MAX_SIZE, total); @@ -2867,15 +2862,15 @@ static bool TryBuildTownHouse(Town *t, TileIndex tile, TownExpandModes modes) if (TimerGameCalendar::year < hs->min_year || TimerGameCalendar::year > hs->max_year) continue; /* Special houses that there can be only one of. */ - uint oneof = 0; + TownFlags oneof{}; if (hs->building_flags.Test(BuildingFlag::IsChurch)) { - SetBit(oneof, TOWN_HAS_CHURCH); + oneof.Set(TownFlag::HasChurch); } else if (hs->building_flags.Test(BuildingFlag::IsStadium)) { - SetBit(oneof, TOWN_HAS_STADIUM); + oneof.Set(TownFlag::HasStadium); } - if (t->flags & oneof) continue; + if (t->flags.Any(oneof)) continue; /* Make sure there is no slope? */ bool noslope = hs->building_flags.Test(BuildingFlag::NotSloped); @@ -2899,7 +2894,7 @@ static bool TryBuildTownHouse(Town *t, TileIndex tile, TownExpandModes modes) } /* Special houses that there can be only one of. */ - t->flags |= oneof; + t->flags.Set(oneof); BuildTownHouse(t, tile, hs, house, random_bits, false, hs->extra_flags.Test(HouseExtraFlag::BuildingIsProtected)); @@ -3034,9 +3029,9 @@ void ClearTownHouse(Town *t, TileIndex tile) /* Clear flags for houses that only may exist once/town. */ if (hs->building_flags.Test(BuildingFlag::IsChurch)) { - ClrBit(t->flags, TOWN_HAS_CHURCH); + t->flags.Reset(TownFlag::HasChurch); } else if (hs->building_flags.Test(BuildingFlag::IsStadium)) { - ClrBit(t->flags, TOWN_HAS_STADIUM); + t->flags.Reset(TownFlag::HasStadium); } /* Do the actual clearing of tiles */ @@ -3168,7 +3163,7 @@ CommandCost CmdTownGrowthRate(DoCommandFlags flags, TownID town_id, uint16_t gro if (flags.Test(DoCommandFlag::Execute)) { if (growth_rate == 0) { /* Just clear the flag, UpdateTownGrowth will determine a proper growth rate */ - ClrBit(t->flags, TOWN_CUSTOM_GROWTH); + t->flags.Reset(TownFlag::CustomGrowth); } else { uint old_rate = t->growth_rate; if (t->grow_counter >= old_rate) { @@ -3179,7 +3174,7 @@ CommandCost CmdTownGrowthRate(DoCommandFlags flags, TownID town_id, uint16_t gro t->grow_counter = t->grow_counter * growth_rate / old_rate; } t->growth_rate = growth_rate; - SetBit(t->flags, TOWN_CUSTOM_GROWTH); + t->flags.Set(TownFlag::CustomGrowth); } UpdateTownGrowth(t); InvalidateWindowData(WC_TOWN_VIEW, town_id); @@ -3829,7 +3824,7 @@ static uint GetNormalGrowthRate(Town *t) */ static void UpdateTownGrowthRate(Town *t) { - if (HasBit(t->flags, TOWN_CUSTOM_GROWTH)) return; + if (t->flags.Test(TownFlag::CustomGrowth)) return; uint old_rate = t->growth_rate; t->growth_rate = GetNormalGrowthRate(t); UpdateTownGrowCounter(t, old_rate); @@ -3844,7 +3839,7 @@ static void UpdateTownGrowth(Town *t) { UpdateTownGrowthRate(t); - ClrBit(t->flags, TOWN_IS_GROWING); + t->flags.Reset(TownFlag::IsGrowing); SetWindowDirty(WC_TOWN_VIEW, t->index); if (_settings_game.economy.town_growth_rate == 0 && t->fund_buildings_months == 0) return; @@ -3866,15 +3861,15 @@ static void UpdateTownGrowth(Town *t) } } - if (HasBit(t->flags, TOWN_CUSTOM_GROWTH)) { - if (t->growth_rate != TOWN_GROWTH_RATE_NONE) SetBit(t->flags, TOWN_IS_GROWING); + if (t->flags.Test(TownFlag::CustomGrowth)) { + if (t->growth_rate != TOWN_GROWTH_RATE_NONE) t->flags.Set(TownFlag::IsGrowing); SetWindowDirty(WC_TOWN_VIEW, t->index); return; } if (t->fund_buildings_months == 0 && CountActiveStations(t) == 0 && !Chance16(1, 12)) return; - SetBit(t->flags, TOWN_IS_GROWING); + t->flags.Set(TownFlag::IsGrowing); SetWindowDirty(WC_TOWN_VIEW, t->index); } @@ -4050,8 +4045,8 @@ CommandCost CheckforTownRating(DoCommandFlags flags, Town *t, TownRatingCheckTyp } /* minimum rating needed to be allowed to remove stuff */ - static const int needed_rating[][TOWN_RATING_CHECK_TYPE_COUNT] = { - /* ROAD_REMOVE, TUNNELBRIDGE_REMOVE */ + static const int needed_rating[][to_underlying(TownRatingCheckType::End)] = { + /* RoadRemove, TunnelBridgeRemove */ { RATING_ROAD_NEEDED_LENIENT, RATING_TUNNEL_BRIDGE_NEEDED_LENIENT}, // Lenient { RATING_ROAD_NEEDED_NEUTRAL, RATING_TUNNEL_BRIDGE_NEEDED_NEUTRAL}, // Neutral { RATING_ROAD_NEEDED_HOSTILE, RATING_TUNNEL_BRIDGE_NEEDED_HOSTILE}, // Hostile @@ -4062,7 +4057,7 @@ CommandCost CheckforTownRating(DoCommandFlags flags, Town *t, TownRatingCheckTyp * owned by a town no removal if rating is lower than ... depends now on * difficulty setting. Minimum town rating selected by difficulty level */ - int needed = needed_rating[_settings_game.difficulty.town_council_tolerance][type]; + int needed = needed_rating[_settings_game.difficulty.town_council_tolerance][to_underlying(type)]; if (GetRating(t) < needed) { return CommandCostWithParam(STR_ERROR_LOCAL_AUTHORITY_REFUSES_TO_ALLOW_THIS, t->index); diff --git a/src/town_cmd.h b/src/town_cmd.h index 7d247ce7cf452..2a9cce5092310 100644 --- a/src/town_cmd.h +++ b/src/town_cmd.h @@ -29,16 +29,16 @@ CommandCost CmdExpandTown(DoCommandFlags flags, TownID town_id, uint32_t grow_am CommandCost CmdDeleteTown(DoCommandFlags flags, TownID town_id); CommandCost CmdPlaceHouse(DoCommandFlags flags, TileIndex tile, HouseID house, bool house_protected); -DEF_CMD_TRAIT(CMD_FOUND_TOWN, CmdFoundTown, CommandFlags({CommandFlag::Deity, CommandFlag::NoTest}), CMDT_LANDSCAPE_CONSTRUCTION) // founding random town can fail only in exec run -DEF_CMD_TRAIT(CMD_RENAME_TOWN, CmdRenameTown, CommandFlags({CommandFlag::Deity, CommandFlag::Server}), CMDT_OTHER_MANAGEMENT) -DEF_CMD_TRAIT(CMD_DO_TOWN_ACTION, CmdDoTownAction, CommandFlags({CommandFlag::Location}), CMDT_LANDSCAPE_CONSTRUCTION) -DEF_CMD_TRAIT(CMD_TOWN_CARGO_GOAL, CmdTownCargoGoal, CommandFlags({CommandFlag::Deity}), CMDT_OTHER_MANAGEMENT) -DEF_CMD_TRAIT(CMD_TOWN_GROWTH_RATE, CmdTownGrowthRate, CommandFlags({CommandFlag::Deity}), CMDT_OTHER_MANAGEMENT) -DEF_CMD_TRAIT(CMD_TOWN_RATING, CmdTownRating, CommandFlags({CommandFlag::Deity}), CMDT_OTHER_MANAGEMENT) -DEF_CMD_TRAIT(CMD_TOWN_SET_TEXT, CmdTownSetText, CommandFlags({CommandFlag::Deity, CommandFlag::StrCtrl}), CMDT_OTHER_MANAGEMENT) -DEF_CMD_TRAIT(CMD_EXPAND_TOWN, CmdExpandTown, CommandFlags({CommandFlag::Deity}), CMDT_LANDSCAPE_CONSTRUCTION) -DEF_CMD_TRAIT(CMD_DELETE_TOWN, CmdDeleteTown, CommandFlags({CommandFlag::Offline}), CMDT_LANDSCAPE_CONSTRUCTION) -DEF_CMD_TRAIT(CMD_PLACE_HOUSE, CmdPlaceHouse, CommandFlags({CommandFlag::Deity}), CMDT_OTHER_MANAGEMENT) +DEF_CMD_TRAIT(CMD_FOUND_TOWN, CmdFoundTown, CommandFlags({CommandFlag::Deity, CommandFlag::NoTest}), CommandType::LandscapeConstruction) // founding random town can fail only in exec run +DEF_CMD_TRAIT(CMD_RENAME_TOWN, CmdRenameTown, CommandFlags({CommandFlag::Deity, CommandFlag::Server}), CommandType::OtherManagement) +DEF_CMD_TRAIT(CMD_DO_TOWN_ACTION, CmdDoTownAction, CommandFlags({CommandFlag::Location}), CommandType::LandscapeConstruction) +DEF_CMD_TRAIT(CMD_TOWN_CARGO_GOAL, CmdTownCargoGoal, CommandFlags({CommandFlag::Deity}), CommandType::OtherManagement) +DEF_CMD_TRAIT(CMD_TOWN_GROWTH_RATE, CmdTownGrowthRate, CommandFlags({CommandFlag::Deity}), CommandType::OtherManagement) +DEF_CMD_TRAIT(CMD_TOWN_RATING, CmdTownRating, CommandFlags({CommandFlag::Deity}), CommandType::OtherManagement) +DEF_CMD_TRAIT(CMD_TOWN_SET_TEXT, CmdTownSetText, CommandFlags({CommandFlag::Deity, CommandFlag::StrCtrl}), CommandType::OtherManagement) +DEF_CMD_TRAIT(CMD_EXPAND_TOWN, CmdExpandTown, CommandFlags({CommandFlag::Deity}), CommandType::LandscapeConstruction) +DEF_CMD_TRAIT(CMD_DELETE_TOWN, CmdDeleteTown, CommandFlags({CommandFlag::Offline}), CommandType::LandscapeConstruction) +DEF_CMD_TRAIT(CMD_PLACE_HOUSE, CmdPlaceHouse, CommandFlags({CommandFlag::Deity}), CommandType::OtherManagement) CommandCallback CcFoundTown; void CcFoundRandomTown(Commands cmd, const CommandCost &result, Money, TownID town_id); diff --git a/src/town_gui.cpp b/src/town_gui.cpp index 845617634467f..492d6e75f33d7 100644 --- a/src/town_gui.cpp +++ b/src/town_gui.cpp @@ -58,7 +58,7 @@ TownKdtree _town_local_authority_kdtree{}; typedef GUIList GUITownList; -static constexpr NWidgetPart _nested_town_authority_widgets[] = { +static constexpr std::initializer_list _nested_town_authority_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_BROWN), NWidget(WWT_CAPTION, COLOUR_BROWN, WID_TA_CAPTION), @@ -453,7 +453,7 @@ struct TownViewWindow : Window { tr.top += GetCharacterHeight(FS_NORMAL); } - if (HasBit(this->town->flags, TOWN_IS_GROWING)) { + if (this->town->flags.Test(TownFlag::IsGrowing)) { DrawString(tr, GetString(this->town->fund_buildings_months == 0 ? STR_TOWN_VIEW_TOWN_GROWS_EVERY : STR_TOWN_VIEW_TOWN_GROWS_EVERY_FUNDED, RoundDivSU(this->town->growth_rate + 1, Ticks::DAY_TICKS))); tr.top += GetCharacterHeight(FS_NORMAL); } else { @@ -611,7 +611,7 @@ struct TownViewWindow : Window { }}; }; -static constexpr NWidgetPart _nested_town_game_view_widgets[] = { +static constexpr std::initializer_list _nested_town_game_view_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_BROWN), NWidget(WWT_PUSHIMGBTN, COLOUR_BROWN, WID_TV_CHANGE_NAME), SetAspect(WidgetDimensions::ASPECT_RENAME), SetSpriteTip(SPR_RENAME, STR_TOWN_VIEW_RENAME_TOOLTIP), @@ -642,7 +642,7 @@ static WindowDesc _town_game_view_desc( _nested_town_game_view_widgets ); -static constexpr NWidgetPart _nested_town_editor_view_widgets[] = { +static constexpr std::initializer_list _nested_town_editor_view_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_BROWN), NWidget(WWT_PUSHIMGBTN, COLOUR_BROWN, WID_TV_CHANGE_NAME), SetAspect(WidgetDimensions::ASPECT_RENAME), SetSpriteTip(SPR_RENAME, STR_TOWN_VIEW_RENAME_TOOLTIP), @@ -686,7 +686,7 @@ void ShowTownViewWindow(TownID town) } } -static constexpr NWidgetPart _nested_town_directory_widgets[] = { +static constexpr std::initializer_list _nested_town_directory_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_BROWN), NWidget(WWT_CAPTION, COLOUR_BROWN, WID_TD_CAPTION), @@ -1068,7 +1068,7 @@ void CcFoundRandomTown(Commands, const CommandCost &result, Money, TownID town_i if (result.Succeeded()) ScrollMainWindowToTile(Town::Get(town_id)->xy); } -static constexpr NWidgetPart _nested_found_town_widgets[] = { +static constexpr std::initializer_list _nested_found_town_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN), NWidget(WWT_CAPTION, COLOUR_DARK_GREEN), SetStringTip(STR_FOUND_TOWN_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), @@ -1805,7 +1805,7 @@ struct BuildHouseWindow : public PickerWindow { }; /** Nested widget definition for the build NewGRF rail waypoint window */ -static constexpr NWidgetPart _nested_build_house_widgets[] = { +static constexpr std::initializer_list _nested_build_house_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN), NWidget(WWT_CAPTION, COLOUR_DARK_GREEN), SetStringTip(STR_HOUSE_PICKER_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), diff --git a/src/town_map.h b/src/town_map.h index 1a982bcb82da5..442d33f37031f 100644 --- a/src/town_map.h +++ b/src/town_map.h @@ -386,6 +386,7 @@ inline void MakeHouseTile(Tile t, TownID tid, uint8_t counter, uint8_t stage, Ho SetHouseProtected(t, house_protected); SetAnimationFrame(t, 0); SetHouseProcessingTime(t, HouseSpec::Get(type)->processing_time); + SB(t.m8(), 12, 4, 0); } #endif /* TOWN_MAP_H */ diff --git a/src/train.h b/src/train.h index f4bd7889adf8e..f3214c2f2b275 100644 --- a/src/train.h +++ b/src/train.h @@ -322,7 +322,8 @@ struct Train final : public GroundVehicle { */ inline uint16_t GetMaxTrackSpeed() const { - return GetRailTypeInfo(GetRailType(this->tile))->max_speed; + RailType rt = GetRailType(this->tile); + return GetRailTypeInfo(rt)->max_speed; } /** diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index 93a5483cfc40c..5723eb11cff84 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -26,7 +26,6 @@ #include "newgrf_station.h" #include "effectvehicle_func.h" #include "network/network.h" -#include "spritecache.h" #include "core/random_func.hpp" #include "company_base.h" #include "newgrf.h" @@ -146,7 +145,7 @@ void Train::ConsistChanged(ConsistChangeFlags allowed_changes) for (Train *u = this; u != nullptr; u = u->Next()) { const Engine *e_u = u->GetEngine(); - const RailVehicleInfo *rvi_u = &e_u->u.rail; + const RailVehicleInfo *rvi_u = &e_u->VehInfo(); if (!e_u->info.misc_flags.Test(EngineMiscFlag::RailTilts)) train_can_tilt = false; min_curve_speed_mod = std::min(min_curve_speed_mod, u->GetCurveSpeedModifier()); @@ -441,7 +440,7 @@ int Train::GetCursorImageOffset() const int reference_width = TRAININFO_DEFAULT_VEHICLE_WIDTH; const Engine *e = this->GetEngine(); - if (e->GetGRF() != nullptr && IsCustomVehicleSpriteNum(e->u.rail.image_index)) { + if (e->GetGRF() != nullptr && IsCustomVehicleSpriteNum(e->VehInfo().image_index)) { reference_width = e->GetGRF()->traininfo_vehicle_width; } @@ -461,7 +460,7 @@ int Train::GetDisplayImageWidth(Point *offset) const int vehicle_pitch = 0; const Engine *e = this->GetEngine(); - if (e->GetGRF() != nullptr && IsCustomVehicleSpriteNum(e->u.rail.image_index)) { + if (e->GetGRF() != nullptr && IsCustomVehicleSpriteNum(e->VehInfo().image_index)) { reference_width = e->GetGRF()->traininfo_vehicle_width; vehicle_pitch = e->GetGRF()->traininfo_vehicle_pitch; } @@ -515,7 +514,7 @@ static void GetRailIcon(EngineID engine, bool rear_head, int &y, EngineImageType { const Engine *e = Engine::Get(engine); Direction dir = rear_head ? DIR_E : DIR_W; - uint8_t spritenum = e->u.rail.image_index; + uint8_t spritenum = e->VehInfo().image_index; if (IsCustomVehicleSpriteNum(spritenum)) { GetCustomVehicleIcon(engine, dir, image_type, result); @@ -636,7 +635,7 @@ static std::vector GetFreeWagonsInDepot(TileIndex tile) */ static CommandCost CmdBuildRailWagon(DoCommandFlags flags, TileIndex tile, const Engine *e, Vehicle **ret) { - const RailVehicleInfo *rvi = &e->u.rail; + const RailVehicleInfo *rvi = &e->VehInfo(); /* Check that the wagon can drive on the track in question */ if (!IsCompatibleRail(rvi->railtypes, GetRailType(tile))) return CMD_ERROR; @@ -770,7 +769,7 @@ static void AddRearEngineToMultiheadedTrain(Train *v) */ CommandCost CmdBuildRailVehicle(DoCommandFlags flags, TileIndex tile, const Engine *e, Vehicle **ret) { - const RailVehicleInfo *rvi = &e->u.rail; + const RailVehicleInfo *rvi = &e->VehInfo(); if (rvi->railveh_type == RAILVEH_WAGON) return CmdBuildRailWagon(flags, tile, e, ret); @@ -4074,15 +4073,15 @@ Money Train::GetRunningCost() const do { const Engine *e = v->GetEngine(); - if (e->u.rail.running_cost_class == INVALID_PRICE) continue; + if (e->VehInfo().running_cost_class == INVALID_PRICE) continue; - uint cost_factor = GetVehicleProperty(v, PROP_TRAIN_RUNNING_COST_FACTOR, e->u.rail.running_cost); + uint cost_factor = GetVehicleProperty(v, PROP_TRAIN_RUNNING_COST_FACTOR, e->VehInfo().running_cost); if (cost_factor == 0) continue; /* Halve running cost for multiheaded parts */ if (v->IsMultiheaded()) cost_factor /= 2; - cost += GetPrice(e->u.rail.running_cost_class, cost_factor, e->GetGRF()); + cost += GetPrice(e->VehInfo().running_cost_class, cost_factor, e->GetGRF()); } while ((v = v->GetNextVehicle()) != nullptr); return cost; diff --git a/src/train_cmd.h b/src/train_cmd.h index 45a7b5eff1bd9..e3c39aa6f60fa 100644 --- a/src/train_cmd.h +++ b/src/train_cmd.h @@ -22,9 +22,9 @@ CommandCost CmdMoveRailVehicle(DoCommandFlags flags, VehicleID src_veh, VehicleI CommandCost CmdForceTrainProceed(DoCommandFlags flags, VehicleID veh_id); CommandCost CmdReverseTrainDirection(DoCommandFlags flags, VehicleID veh_id, bool reverse_single_veh); -DEF_CMD_TRAIT(CMD_MOVE_RAIL_VEHICLE, CmdMoveRailVehicle, CommandFlag::Location, CMDT_VEHICLE_CONSTRUCTION) -DEF_CMD_TRAIT(CMD_FORCE_TRAIN_PROCEED, CmdForceTrainProceed, CommandFlag::Location, CMDT_VEHICLE_MANAGEMENT) -DEF_CMD_TRAIT(CMD_REVERSE_TRAIN_DIRECTION, CmdReverseTrainDirection, CommandFlag::Location, CMDT_VEHICLE_MANAGEMENT) +DEF_CMD_TRAIT(CMD_MOVE_RAIL_VEHICLE, CmdMoveRailVehicle, CommandFlag::Location, CommandType::VehicleConstruction) +DEF_CMD_TRAIT(CMD_FORCE_TRAIN_PROCEED, CmdForceTrainProceed, CommandFlag::Location, CommandType::VehicleManagement) +DEF_CMD_TRAIT(CMD_REVERSE_TRAIN_DIRECTION, CmdReverseTrainDirection, CommandFlag::Location, CommandType::VehicleManagement) void CcBuildWagon(Commands cmd, const CommandCost &result, VehicleID new_veh_id, uint, uint16_t, CargoArray, TileIndex tile, EngineID, bool, CargoType, ClientID); diff --git a/src/train_gui.cpp b/src/train_gui.cpp index fc4262c89faa9..cfa018c0ecc9c 100644 --- a/src/train_gui.cpp +++ b/src/train_gui.cpp @@ -401,7 +401,7 @@ void DrawTrainDetails(const Train *v, const Rect &r, int vscroll_pos, uint16_t v if (vscroll_pos <= 0 && vscroll_pos > -vscroll_cap) { int py = r.top - line_height * vscroll_pos + text_y_offset; if (i > 0 || separate_sprite_row) { - if (vscroll_pos != 0) GfxFillRect(r.left, py - WidgetDimensions::scaled.matrix.top - 1, r.right, py - WidgetDimensions::scaled.matrix.top, GetColourGradient(COLOUR_GREY, SHADE_LIGHT)); + if (vscroll_pos != 0) GfxFillRect(r.WithY(py - WidgetDimensions::scaled.matrix.top - 1, py - WidgetDimensions::scaled.matrix.top), GetColourGradient(COLOUR_GREY, SHADE_LIGHT)); } switch (det_tab) { case TDW_TAB_CARGO: diff --git a/src/transparency_gui.cpp b/src/transparency_gui.cpp index 0c768f59ff87e..ef0791168d51c 100644 --- a/src/transparency_gui.cpp +++ b/src/transparency_gui.cpp @@ -62,7 +62,7 @@ class TransparenciesWindow : public Window if (i == WID_TT_TEXT) continue; // Loading and cost/income text has no invisibility button. const Rect wr = this->GetWidget(i)->GetCurrentRect().Shrink(WidgetDimensions::scaled.fullbevel); - DrawFrameRect(wr.left, fr.top, wr.right, fr.bottom, COLOUR_PALE_GREEN, + DrawFrameRect(wr.WithY(fr), COLOUR_PALE_GREEN, HasBit(_invisibility_opt, i - WID_TT_BEGIN) ? FrameFlag::Lowered : FrameFlags{}); } break; @@ -126,7 +126,7 @@ class TransparenciesWindow : public Window } }; -static constexpr NWidgetPart _nested_transparency_widgets[] = { +static constexpr std::initializer_list _nested_transparency_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN), NWidget(WWT_CAPTION, COLOUR_DARK_GREEN), SetStringTip(STR_TRANSPARENCY_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), diff --git a/src/transport_mapping.hpp b/src/transport_mapping.hpp new file mode 100644 index 0000000000000..87363ad6dc266 --- /dev/null +++ b/src/transport_mapping.hpp @@ -0,0 +1,112 @@ +/* + * 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 transport_mapping.hpp Transport mapping utilities. */ + +#ifndef TRANSPORT_MAPPING_HPP +#define TRANSPORT_MAPPING_HPP + +#include "core/convertible_through_base.hpp" +#include "core/strong_typedef_type.hpp" + +/** + * Transport type (rail, road, etc) mapping helper. + * @tparam TType Native type to be mapped. + * @tparam TInvalidType Invalid value for native type. + * @tparam TMaxSize maximum number of mapped entries. + */ +template +class TransportMapping { +public: + static constexpr size_t MAX_SIZE = TMaxSize; + static constexpr TType INVALID_TYPE = TInvalidType; + + /** Unique type holds a mapped transport type. */ + using MapType = StrongType::Typedef; + static constexpr MapType INVALID_MAP_TYPE = static_cast(TMaxSize); + + TransportMapping() { this->Init(); } + + void Init() + { + std::ranges::fill(this->map, INVALID_TYPE); + } + + /** + * Get the native type of a mapped type. + * @param mapped_type Mapped type to look up. + * @return native type of mapped type, or INVALID_TYPE if invalid. + */ + TType GetType(MapType mapped_type) const + { + if (mapped_type == INVALID_MAP_TYPE) return INVALID_TYPE; + + assert(mapped_type.base() < std::size(this->map)); + return this->map[mapped_type]; + } + + void Set(MapType mapped_type, TType type) + { + this->map[mapped_type] = type; + } + + /** + * Get the mapped type of a native type. + * @param type Native type to look up. + * @return mapped type of native type, or INVALID_MAP_TYPE if invalid. + */ + MapType GetMappedType(TType type) + { + if (type == INVALID_TYPE) return INVALID_MAP_TYPE; + + auto it = std::ranges::find(this->map, type); + if (it != std::end(this->map)) return this->Index(it); + + return INVALID_MAP_TYPE; + } + + /** + * Allocate a mapped type for a native type. + * If the native type is already mapped then the existing allocation is used. + * @param type Native type to map. + * @param exec Whether to actually set the mapping. + * @return mapped type of native type, or INVALID_MAP_TYPE if allocation was not possible. + */ + MapType AllocateMapType(TType type, bool exec) + { + if (type == INVALID_TYPE) return INVALID_MAP_TYPE; + + /* Check for existing mapped type. */ + auto it = std::ranges::find(this->map, type); + if (it != std::end(this->map)) return this->Index(it); + + /* Check for an unused entry. */ + it = std::ranges::find(this->map, INVALID_TYPE); + if (it == std::end(this->map)) { + /* Didn't find an unused slot, use slower path to find a free map type. */ + it = this->FindUnusedMapType(); + if (it == std::end(this->map)) return INVALID_MAP_TYPE; + } + + if (exec) *it = type; + + return this->Index(it); + } + +private: + using MapStorage = TypedIndexContainer, MapType>; + MapStorage map{}; + + MapType Index(MapStorage::iterator iter) const + { + return static_cast(iter - std::begin(this->map)); + } + + MapStorage::iterator FindUnusedMapType(); +}; + +#endif /* TRANSPORT_MAPPING_HPP */ diff --git a/src/tree_cmd.h b/src/tree_cmd.h index 116d50c5f6eb8..65e1a310ad3c9 100644 --- a/src/tree_cmd.h +++ b/src/tree_cmd.h @@ -14,6 +14,6 @@ CommandCost CmdPlantTree(DoCommandFlags flags, TileIndex tile, TileIndex start_tile, uint8_t tree_to_plant, bool diagonal); -DEF_CMD_TRAIT(CMD_PLANT_TREE, CmdPlantTree, CommandFlag::Auto, CMDT_LANDSCAPE_CONSTRUCTION) +DEF_CMD_TRAIT(CMD_PLANT_TREE, CmdPlantTree, CommandFlag::Auto, CommandType::LandscapeConstruction) #endif /* TREE_CMD_H */ diff --git a/src/tree_gui.cpp b/src/tree_gui.cpp index 8bf4d15af35fe..6bf2ee0281c0e 100644 --- a/src/tree_gui.cpp +++ b/src/tree_gui.cpp @@ -285,7 +285,7 @@ static std::unique_ptr MakeTreeTypeButtons() return vstack; } -static constexpr NWidgetPart _nested_build_trees_widgets[] = { +static constexpr std::initializer_list _nested_build_trees_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_DARK_GREEN), NWidget(WWT_CAPTION, COLOUR_DARK_GREEN), SetStringTip(STR_PLANT_TREE_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), diff --git a/src/tree_map.h b/src/tree_map.h index 9fa0969ed135c..0cabe6a8eb9cb 100644 --- a/src/tree_map.h +++ b/src/tree_map.h @@ -250,8 +250,9 @@ inline void MakeTree(Tile t, TreeType type, uint count, TreeGrowthStage growth, t.m3() = type; t.m4() = 0 << 5 | 0 << 2; t.m5() = count << 6 | static_cast(growth); - SB(t.m6(), 2, 4, 0); + SB(t.m6(), 2, 6, 0); t.m7() = 0; + t.m8() = 0; } #endif /* TREE_MAP_H */ diff --git a/src/tunnel_map.h b/src/tunnel_map.h index 61965c067ca85..ba8841103fb12 100644 --- a/src/tunnel_map.h +++ b/src/tunnel_map.h @@ -45,9 +45,10 @@ bool IsTunnelInWayDir(TileIndex tile, int z, DiagDirection dir); * @param t the entrance of the tunnel * @param o the owner of the entrance * @param d the direction facing out of the tunnel - * @param r the road type used in the tunnel + * @param map_roadtype the map road type used in the tunnel + * @param map_tramtype the map tram type used in the tunnel */ -inline void MakeRoadTunnel(Tile t, Owner o, DiagDirection d, RoadType road_rt, RoadType tram_rt) +inline void MakeRoadTunnel(Tile t, Owner o, DiagDirection d, MapRoadType map_roadtype, MapTramType map_tramtype) { SetTileType(t, MP_TUNNELBRIDGE); SetTileOwner(t, o); @@ -55,12 +56,12 @@ inline void MakeRoadTunnel(Tile t, Owner o, DiagDirection d, RoadType road_rt, R t.m3() = 0; t.m4() = 0; t.m5() = TRANSPORT_ROAD << 2 | d; - SB(t.m6(), 2, 4, 0); + SB(t.m6(), 2, 6, 0); t.m7() = 0; t.m8() = 0; SetRoadOwner(t, RTT_ROAD, o); if (o != OWNER_TOWN) SetRoadOwner(t, RTT_TRAM, o); - SetRoadTypes(t, road_rt, tram_rt); + SetMapRoadTypes(t, map_roadtype, map_tramtype); } /** @@ -68,9 +69,9 @@ inline void MakeRoadTunnel(Tile t, Owner o, DiagDirection d, RoadType road_rt, R * @param t the entrance of the tunnel * @param o the owner of the entrance * @param d the direction facing out of the tunnel - * @param r the rail type used in the tunnel + * @param map_railtype the map rail type used in the tunnel */ -inline void MakeRailTunnel(Tile t, Owner o, DiagDirection d, RailType r) +inline void MakeRailTunnel(Tile t, Owner o, DiagDirection d, MapRailType map_railtype) { SetTileType(t, MP_TUNNELBRIDGE); SetTileOwner(t, o); @@ -78,10 +79,10 @@ inline void MakeRailTunnel(Tile t, Owner o, DiagDirection d, RailType r) t.m3() = 0; t.m4() = 0; t.m5() = TRANSPORT_RAIL << 2 | d; - SB(t.m6(), 2, 4, 0); + SB(t.m6(), 2, 6, 0); t.m7() = 0; t.m8() = 0; - SetRailType(t, r); + SetMapRailType(t, map_railtype); } #endif /* TUNNEL_MAP_H */ diff --git a/src/tunnelbridge_cmd.cpp b/src/tunnelbridge_cmd.cpp index 2d03900ea16b1..a1bb27c0e9073 100644 --- a/src/tunnelbridge_cmd.cpp +++ b/src/tunnelbridge_cmd.cpp @@ -135,6 +135,19 @@ bool HasBridgeFlatRamp(Slope tileh, Axis axis) return (tileh != SLOPE_FLAT); } +/** + * Test if bridge piece uses a custom sprite table. + * @param bridge_type Bridge type. + * @param piece Bridge piece. + * @return True iff a custom sprite table is used for the bridge piece. + */ +static bool BridgeHasCustomSpriteTable(BridgeType bridge_type, BridgePieces piece) +{ + assert(piece < NUM_BRIDGE_PIECES); + const BridgeSpec *bridge = GetBridgeSpec(bridge_type); + return piece < bridge->sprite_table.size() && !bridge->sprite_table[piece].empty(); +} + /** * Get the sprite table for a rail/road bridge piece. * @param bridge_type Bridge type. @@ -294,25 +307,32 @@ static CommandCost CheckBuildAbove(TileIndex tile, DoCommandFlags flags, Axis ax * @param road_rail_type rail type or road types. * @return the cost of this operation or an error */ -CommandCost CmdBuildBridge(DoCommandFlags flags, TileIndex tile_end, TileIndex tile_start, TransportType transport_type, BridgeType bridge_type, uint8_t road_rail_type) +CommandCost CmdBuildBridge(DoCommandFlags flags, TileIndex tile_end, TileIndex tile_start, TransportType transport_type, BridgeType bridge_type, RailType railtype, RoadType roadtype) { CompanyID company = _current_company; - RailType railtype = INVALID_RAILTYPE; - RoadType roadtype = INVALID_ROADTYPE; + MapRailType map_railtype = RailTypeMapping::INVALID_MAP_TYPE; + RoadTramType rtt = RTT_ROAD; + MapRoadType map_roadtype = RoadTypeMapping::INVALID_MAP_TYPE; + MapTramType map_tramtype = TramTypeMapping::INVALID_MAP_TYPE; if (!IsValidTile(tile_start)) return CommandCost(STR_ERROR_BRIDGE_THROUGH_MAP_BORDER); /* type of bridge */ switch (transport_type) { case TRANSPORT_ROAD: - roadtype = (RoadType)road_rail_type; if (!ValParamRoadType(roadtype)) return CMD_ERROR; + rtt = GetRoadTramType(roadtype); + map_roadtype = rtt == RTT_ROAD ? _roadtype_mapping.AllocateMapType(roadtype, flags.Test(DoCommandFlag::Execute)) : RoadTypeMapping::INVALID_MAP_TYPE; + if (rtt == RTT_ROAD && map_roadtype == RoadTypeMapping::INVALID_MAP_TYPE) return CommandCost{STR_ERROR_TOO_MANY_ROADTYPES}; + map_tramtype = rtt == RTT_TRAM ? _tramtype_mapping.AllocateMapType(roadtype, flags.Test(DoCommandFlag::Execute)) : TramTypeMapping::INVALID_MAP_TYPE; + if (rtt == RTT_TRAM && map_tramtype == TramTypeMapping::INVALID_MAP_TYPE) return CommandCost{STR_ERROR_TOO_MANY_TRAMTYPES}; break; case TRANSPORT_RAIL: - railtype = (RailType)road_rail_type; if (!ValParamRailType(railtype)) return CMD_ERROR; + map_railtype = _railtype_mapping.AllocateMapType(railtype, flags.Test(DoCommandFlag::Execute)); + if (map_railtype == RailTypeMapping::INVALID_MAP_TYPE) return CommandCost{STR_ERROR_TOO_MANY_RAILTYPES}; break; case TRANSPORT_WATER: @@ -530,8 +550,8 @@ CommandCost CmdBuildBridge(DoCommandFlags flags, TileIndex tile_end, TileIndex t case TRANSPORT_RAIL: /* Add to company infrastructure count if required. */ if (is_new_owner && c != nullptr) c->infrastructure.rail[railtype] += bridge_len * TUNNELBRIDGE_TRACKBIT_FACTOR; - MakeRailBridgeRamp(tile_start, owner, bridge_type, dir, railtype); - MakeRailBridgeRamp(tile_end, owner, bridge_type, ReverseDiagDir(dir), railtype); + MakeRailBridgeRamp(tile_start, owner, bridge_type, dir, map_railtype); + MakeRailBridgeRamp(tile_end, owner, bridge_type, ReverseDiagDir(dir), map_railtype); SetTunnelBridgeReservation(tile_start, pbs_reservation); SetTunnelBridgeReservation(tile_end, pbs_reservation); break; @@ -542,21 +562,27 @@ CommandCost CmdBuildBridge(DoCommandFlags flags, TileIndex tile_end, TileIndex t if (hasroad && GetRoadOwner(tile_start, RTT_ROAD) == OWNER_NONE) hasroad = false; if (hastram && GetRoadOwner(tile_start, RTT_TRAM) == OWNER_NONE) hastram = false; } - if (c != nullptr) { - /* Add all new road types to the company infrastructure counter. */ - if (!hasroad && road_rt != INVALID_ROADTYPE) { - /* A full diagonal road tile has two road bits. */ + /* Add all new road types to the company infrastructure counter. */ + if (!hasroad && road_rt != INVALID_ROADTYPE) { + /* A full diagonal road tile has two road bits. */ + if (c != nullptr) { c->infrastructure.road[road_rt] += bridge_len * 2 * TUNNELBRIDGE_TRACKBIT_FACTOR; + } else { + RoadTypeInfo::infrastructure_counts[road_rt] += bridge_len * 2 * TUNNELBRIDGE_TRACKBIT_FACTOR; } - if (!hastram && tram_rt != INVALID_ROADTYPE) { - /* A full diagonal road tile has two road bits. */ + } + if (!hastram && tram_rt != INVALID_ROADTYPE) { + /* A full diagonal road tile has two road bits. */ + if (c != nullptr) { c->infrastructure.road[tram_rt] += bridge_len * 2 * TUNNELBRIDGE_TRACKBIT_FACTOR; + } else { + RoadTypeInfo::infrastructure_counts[tram_rt] += bridge_len * 2 * TUNNELBRIDGE_TRACKBIT_FACTOR; } } Owner owner_road = hasroad ? GetRoadOwner(tile_start, RTT_ROAD) : company; Owner owner_tram = hastram ? GetRoadOwner(tile_start, RTT_TRAM) : company; - MakeRoadBridgeRamp(tile_start, owner, owner_road, owner_tram, bridge_type, dir, road_rt, tram_rt); - MakeRoadBridgeRamp(tile_end, owner, owner_road, owner_tram, bridge_type, ReverseDiagDir(dir), road_rt, tram_rt); + MakeRoadBridgeRamp(tile_start, owner, owner_road, owner_tram, bridge_type, dir, map_roadtype, map_tramtype); + MakeRoadBridgeRamp(tile_end, owner, owner_road, owner_tram, bridge_type, ReverseDiagDir(dir), map_roadtype, map_tramtype); break; } @@ -626,22 +652,30 @@ CommandCost CmdBuildBridge(DoCommandFlags flags, TileIndex tile_end, TileIndex t * @param road_rail_type railtype or roadtype * @return the cost of this operation or an error */ -CommandCost CmdBuildTunnel(DoCommandFlags flags, TileIndex start_tile, TransportType transport_type, uint8_t road_rail_type) +CommandCost CmdBuildTunnel(DoCommandFlags flags, TileIndex start_tile, TransportType transport_type, RailType railtype, RoadType roadtype) { CompanyID company = _current_company; - RailType railtype = INVALID_RAILTYPE; - RoadType roadtype = INVALID_ROADTYPE; + MapRailType map_railtype = RailTypeMapping::INVALID_MAP_TYPE; + RoadTramType rtt = RTT_ROAD; + MapRoadType map_roadtype = RoadTypeMapping::INVALID_MAP_TYPE; + MapTramType map_tramtype = TramTypeMapping::INVALID_MAP_TYPE; + _build_tunnel_endtile = TileIndex{}; switch (transport_type) { case TRANSPORT_RAIL: - railtype = (RailType)road_rail_type; if (!ValParamRailType(railtype)) return CMD_ERROR; + map_railtype = _railtype_mapping.AllocateMapType(railtype, flags.Test(DoCommandFlag::Execute)); + if (map_railtype == RailTypeMapping::INVALID_MAP_TYPE) return CommandCost{STR_ERROR_TOO_MANY_RAILTYPES}; break; case TRANSPORT_ROAD: - roadtype = (RoadType)road_rail_type; if (!ValParamRoadType(roadtype)) return CMD_ERROR; + rtt = GetRoadTramType(roadtype); + map_roadtype = rtt == RTT_ROAD ? _roadtype_mapping.AllocateMapType(roadtype, flags.Test(DoCommandFlag::Execute)) : RoadTypeMapping::INVALID_MAP_TYPE; + if (rtt == RTT_ROAD && map_roadtype == RoadTypeMapping::INVALID_MAP_TYPE) return CommandCost{STR_ERROR_TOO_MANY_ROADTYPES}; + map_tramtype = rtt == RTT_TRAM ? _tramtype_mapping.AllocateMapType(roadtype, flags.Test(DoCommandFlag::Execute)) : TramTypeMapping::INVALID_MAP_TYPE; + if (rtt == RTT_TRAM && map_tramtype == TramTypeMapping::INVALID_MAP_TYPE) return CommandCost{STR_ERROR_TOO_MANY_TRAMTYPES}; break; default: return CMD_ERROR; @@ -777,16 +811,18 @@ CommandCost CmdBuildTunnel(DoCommandFlags flags, TileIndex start_tile, Transport uint num_pieces = (tiles + 2) * TUNNELBRIDGE_TRACKBIT_FACTOR; if (transport_type == TRANSPORT_RAIL) { if (c != nullptr) c->infrastructure.rail[railtype] += num_pieces; - MakeRailTunnel(start_tile, company, direction, railtype); - MakeRailTunnel(end_tile, company, ReverseDiagDir(direction), railtype); + MakeRailTunnel(start_tile, company, direction, map_railtype); + MakeRailTunnel(end_tile, company, ReverseDiagDir(direction), map_railtype); AddSideToSignalBuffer(start_tile, INVALID_DIAGDIR, company); YapfNotifyTrackLayoutChange(start_tile, DiagDirToDiagTrack(direction)); } else { - if (c != nullptr) c->infrastructure.road[roadtype] += num_pieces * 2; // A full diagonal road has two road bits. - RoadType road_rt = RoadTypeIsRoad(roadtype) ? roadtype : INVALID_ROADTYPE; - RoadType tram_rt = RoadTypeIsTram(roadtype) ? roadtype : INVALID_ROADTYPE; - MakeRoadTunnel(start_tile, company, direction, road_rt, tram_rt); - MakeRoadTunnel(end_tile, company, ReverseDiagDir(direction), road_rt, tram_rt); + if (c != nullptr) { + c->infrastructure.road[roadtype] += num_pieces * 2; // A full diagonal road has two road bits. + } else { + RoadTypeInfo::infrastructure_counts[roadtype] += num_pieces * 2; + } + MakeRoadTunnel(start_tile, company, direction, map_roadtype, map_tramtype); + MakeRoadTunnel(end_tile, company, ReverseDiagDir(direction), map_roadtype, map_tramtype); } DirtyCompanyInfrastructureWindows(company); } @@ -866,7 +902,7 @@ static CommandCost DoClearTunnel(TileIndex tile, DoCommandFlags flags) /* Check if you are allowed to remove the tunnel owned by a town * Removal depends on difficulty settings */ - ret = CheckforTownRating(flags, t, TUNNELBRIDGE_REMOVE); + ret = CheckforTownRating(flags, t, TownRatingCheckType::TunnelBridgeRemove); if (ret.Failed()) return ret; } @@ -947,7 +983,7 @@ static CommandCost DoClearBridge(TileIndex tile, DoCommandFlags flags) /* Check if you are allowed to remove the bridge owned by a town * Removal depends on difficulty settings */ - ret = CheckforTownRating(flags, t, TUNNELBRIDGE_REMOVE); + ret = CheckforTownRating(flags, t, TownRatingCheckType::TunnelBridgeRemove); if (ret.Failed()) return ret; } @@ -1158,8 +1194,9 @@ static void GetBridgeRoadCatenary(const RoadTypeInfo *rti, TileIndex head_tile, * @param z the z of the bridge * @param offset sprite offset identifying flat to sloped bridge tiles * @param head are we drawing bridge head? + * @param is_custom_layout Set if the bridge uses a custom sprite layout. */ -static void DrawBridgeRoadBits(TileIndex head_tile, int x, int y, int z, int offset, bool head) +static void DrawBridgeRoadBits(TileIndex head_tile, int x, int y, int z, int offset, bool head, bool is_custom_layout) { RoadType road_rt = GetRoadTypeRoad(head_tile); RoadType tram_rt = GetRoadTypeTram(head_tile); @@ -1178,6 +1215,9 @@ static void DrawBridgeRoadBits(TileIndex head_tile, int x, int y, int z, int off if (road_rti != nullptr) { if (road_rti->UsesOverlay()) { seq_back[0] = GetCustomRoadSprite(road_rti, head_tile, ROTSG_BRIDGE, head ? TCX_NORMAL : TCX_ON_BRIDGE) + offset; + } else if (is_custom_layout) { + /* For custom layouts draw a custom bridge deck. */ + seq_back[0] = SPR_BRIDGE_DECKS_ROAD + offset; } } else if (tram_rti != nullptr) { if (tram_rti->UsesOverlay()) { @@ -1428,13 +1468,16 @@ static void DrawTile_TunnelBridge(TileInfo *ti) DrawBridgeMiddle(ti, BridgePillarFlag::EdgeNE + tunnelbridge_direction); } else { // IsBridge(ti->tile) DrawFoundation(ti, GetBridgeFoundation(ti->tileh, DiagDirToAxis(tunnelbridge_direction))); + bool is_custom_layout = false; // Set if rail/road bridge uses a custom layout. uint base_offset = GetBridgeRampDirectionBaseOffset(tunnelbridge_direction); std::span psid; if (transport_type != TRANSPORT_WATER) { + BridgeType bridge_type = GetBridgeType(ti->tile); if (ti->tileh == SLOPE_FLAT) base_offset += 4; // sloped bridge head base_offset += GetBridgeSpriteTableBaseOffset(transport_type, ti->tile); - psid = GetBridgeSpriteTable(GetBridgeType(ti->tile), BRIDGE_PIECE_HEAD); + psid = GetBridgeSpriteTable(bridge_type, BRIDGE_PIECE_HEAD); + is_custom_layout = BridgeHasCustomSpriteTable(bridge_type, BRIDGE_PIECE_HEAD); } else { psid = _aqueduct_sprite_table_heads; } @@ -1473,23 +1516,18 @@ static void DrawTile_TunnelBridge(TileInfo *ti) } /* DrawBridgeRoadBits() calls EndSpriteCombine() and StartSpriteCombine() */ - DrawBridgeRoadBits(ti->tile, ti->x, ti->y, z, offset, true); + DrawBridgeRoadBits(ti->tile, ti->x, ti->y, z, offset, true, is_custom_layout); EndSpriteCombine(); } else if (transport_type == TRANSPORT_RAIL) { const RailTypeInfo *rti = GetRailTypeInfo(GetRailType(ti->tile)); - if (rti->UsesOverlay()) { - SpriteID surface = GetCustomRailSprite(rti, ti->tile, RTSG_BRIDGE); - if (surface != 0) { - if (HasBridgeFlatRamp(ti->tileh, DiagDirToAxis(tunnelbridge_direction))) { - AddSortableSpriteToDraw(surface + ((DiagDirToAxis(tunnelbridge_direction) == AXIS_X) ? RTBO_X : RTBO_Y), PAL_NONE, *ti, {{0, 0, TILE_HEIGHT}, {TILE_SIZE, TILE_SIZE, 0}, {}}); - } else { - AddSortableSpriteToDraw(surface + RTBO_SLOPE + tunnelbridge_direction, PAL_NONE, *ti, {{}, {TILE_SIZE, TILE_SIZE, TILE_HEIGHT}, {}}); - } + SpriteID surface = rti->UsesOverlay() ? GetCustomRailSprite(rti, ti->tile, RTSG_BRIDGE) : rti->base_sprites.bridge_deck; + if (surface != 0) { + if (HasBridgeFlatRamp(ti->tileh, DiagDirToAxis(tunnelbridge_direction))) { + AddSortableSpriteToDraw(surface + ((DiagDirToAxis(tunnelbridge_direction) == AXIS_X) ? RTBO_X : RTBO_Y), PAL_NONE, *ti, {{0, 0, TILE_HEIGHT}, {TILE_SIZE, TILE_SIZE, 0}, {}}); + } else { + AddSortableSpriteToDraw(surface + RTBO_SLOPE + tunnelbridge_direction, PAL_NONE, *ti, {{}, {TILE_SIZE, TILE_SIZE, TILE_HEIGHT}, {}}); } - /* Don't fallback to non-overlay sprite -- the spec states that - * if an overlay is present then the bridge surface must be - * present. */ } /* PBS debugging, draw reserved tracks darker */ @@ -1614,16 +1652,19 @@ void DrawBridgeMiddle(const TileInfo *ti, BridgePillarFlags blocked_pillars) TransportType transport_type = GetTunnelBridgeTransportType(rampsouth); Axis axis = GetBridgeAxis(ti->tile); BridgePillarFlags pillars; + bool is_custom_layout; // Set if rail/road bridge uses a custom layout. uint base_offset = GetBridgeMiddleAxisBaseOffset(axis); std::span psid; bool drawfarpillar; if (transport_type != TRANSPORT_WATER) { BridgeType bridge_type = GetBridgeType(rampsouth); + BridgePieces bridge_piece = CalcBridgePiece(GetTunnelBridgeLength(ti->tile, rampnorth) + 1, GetTunnelBridgeLength(ti->tile, rampsouth) + 1); drawfarpillar = !HasBit(GetBridgeSpec(bridge_type)->flags, 0); base_offset += GetBridgeSpriteTableBaseOffset(transport_type, rampsouth); - psid = GetBridgeSpriteTable(bridge_type, CalcBridgePiece(GetTunnelBridgeLength(ti->tile, rampnorth) + 1, GetTunnelBridgeLength(ti->tile, rampsouth) + 1)); + psid = GetBridgeSpriteTable(bridge_type, bridge_piece); pillars = GetBridgeTilePillarFlags(ti->tile, rampnorth, rampsouth, bridge_type, transport_type); + is_custom_layout = BridgeHasCustomSpriteTable(bridge_type, bridge_piece); } else { drawfarpillar = true; psid = _aqueduct_sprite_table_middle; @@ -1653,11 +1694,11 @@ void DrawBridgeMiddle(const TileInfo *ti, BridgePillarFlags blocked_pillars) if (transport_type == TRANSPORT_ROAD) { /* DrawBridgeRoadBits() calls EndSpriteCombine() and StartSpriteCombine() */ - DrawBridgeRoadBits(rampsouth, x, y, bridge_z, axis ^ 1, false); + DrawBridgeRoadBits(rampsouth, x, y, bridge_z, axis ^ 1, false, is_custom_layout); } else if (transport_type == TRANSPORT_RAIL) { const RailTypeInfo *rti = GetRailTypeInfo(GetRailType(rampsouth)); - if (rti->UsesOverlay() && !IsInvisibilitySet(TO_BRIDGES)) { - SpriteID surface = GetCustomRailSprite(rti, rampsouth, RTSG_BRIDGE, TCX_ON_BRIDGE); + if (!IsInvisibilitySet(TO_BRIDGES)) { + SpriteID surface = rti->UsesOverlay() ? GetCustomRailSprite(rti, rampsouth, RTSG_BRIDGE, TCX_ON_BRIDGE) : rti->base_sprites.bridge_deck; if (surface != 0) { AddSortableSpriteToDraw(surface + axis, PAL_NONE, x, y, bridge_z, {{}, {TILE_SIZE, TILE_SIZE, 0}, {}}, IsTransparencySet(TO_BRIDGES)); } @@ -1859,7 +1900,11 @@ static void ChangeTileOwner_TunnelBridge(TileIndex tile, Owner old_owner, Owner /* Update company infrastructure counts. A full diagonal road tile has two road bits. * No need to dirty windows here, we'll redraw the whole screen anyway. */ Company::Get(old_owner)->infrastructure.road[rt] -= num_pieces * 2; - if (new_owner != INVALID_OWNER) Company::Get(new_owner)->infrastructure.road[rt] += num_pieces * 2; + if (new_owner != INVALID_OWNER) { + Company::Get(new_owner)->infrastructure.road[rt] += num_pieces * 2; + } else { + RoadTypeInfo::infrastructure_counts[rt] += num_pieces * 2; + } } SetRoadOwner(tile, rtt, new_owner == INVALID_OWNER ? OWNER_NONE : new_owner); diff --git a/src/tunnelbridge_cmd.h b/src/tunnelbridge_cmd.h index 25bd0cc2263ca..460da8f90dd23 100644 --- a/src/tunnelbridge_cmd.h +++ b/src/tunnelbridge_cmd.h @@ -10,16 +10,18 @@ #ifndef TUNNELBRIDGE_CMD_H #define TUNNELBRIDGE_CMD_H +#include "bridge_type.h" #include "command_type.h" +#include "rail_type.h" +#include "road_type.h" #include "transport_type.h" -#include "bridge.h" -CommandCost CmdBuildBridge(DoCommandFlags flags, TileIndex tile_end, TileIndex tile_start, TransportType transport_type, BridgeType bridge_type, uint8_t road_rail_type); -CommandCost CmdBuildTunnel(DoCommandFlags flags, TileIndex start_tile, TransportType transport_type, uint8_t road_rail_type); +CommandCost CmdBuildBridge(DoCommandFlags flags, TileIndex tile_end, TileIndex tile_start, TransportType transport_type, BridgeType bridge_type, RailType railtype, RoadType roadtype); +CommandCost CmdBuildTunnel(DoCommandFlags flags, TileIndex start_tile, TransportType transport_type, RailType railtype, RoadType roadtype); -DEF_CMD_TRAIT(CMD_BUILD_BRIDGE, CmdBuildBridge, CommandFlags({CommandFlag::Deity, CommandFlag::Auto, CommandFlag::NoWater}), CMDT_LANDSCAPE_CONSTRUCTION) -DEF_CMD_TRAIT(CMD_BUILD_TUNNEL, CmdBuildTunnel, CommandFlags({CommandFlag::Deity, CommandFlag::Auto}), CMDT_LANDSCAPE_CONSTRUCTION) +DEF_CMD_TRAIT(CMD_BUILD_BRIDGE, CmdBuildBridge, CommandFlags({CommandFlag::Deity, CommandFlag::Auto, CommandFlag::NoWater}), CommandType::LandscapeConstruction) +DEF_CMD_TRAIT(CMD_BUILD_TUNNEL, CmdBuildTunnel, CommandFlags({CommandFlag::Deity, CommandFlag::Auto}), CommandType::LandscapeConstruction) -void CcBuildBridge(Commands cmd, const CommandCost &result, TileIndex end_tile, TileIndex tile_start, TransportType transport_type, BridgeType, uint8_t); +void CcBuildBridge(Commands cmd, const CommandCost &result, TileIndex end_tile, TileIndex tile_start, TransportType transport_type, BridgeType, RailType railtype, RoadType roadtype); #endif /* TUNNELBRIDGE_CMD_H */ diff --git a/src/vehicle.cpp b/src/vehicle.cpp index e6573b372682c..95764752d252e 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -1925,7 +1925,7 @@ bool CanBuildVehicleInfrastructure(VehicleType type, uint8_t subtype) if (max > 0) { /* Can we actually build the vehicle type? */ for (const Engine *e : Engine::IterateType(type)) { - if (type == VEH_ROAD && GetRoadTramType(e->u.road.roadtype) != (RoadTramType)subtype) continue; + if (type == VEH_ROAD && GetRoadTramType(e->VehInfo().roadtype) != (RoadTramType)subtype) continue; if (e->company_avail.Test(_local_company)) return true; } return false; @@ -1955,7 +1955,7 @@ LiveryScheme GetEngineLiveryScheme(EngineID engine_type, EngineID parent_engine_ switch (e->type) { default: NOT_REACHED(); case VEH_TRAIN: - if (v != nullptr && parent_engine_type != EngineID::Invalid() && (UsesWagonOverride(v) || (v->IsArticulatedPart() && e->u.rail.railveh_type != RAILVEH_WAGON))) { + if (v != nullptr && parent_engine_type != EngineID::Invalid() && (UsesWagonOverride(v) || (v->IsArticulatedPart() && e->VehInfo().railveh_type != RAILVEH_WAGON))) { /* Wagonoverrides use the colour scheme of the front engine. * Articulated parts use the colour scheme of the first part. (Not supported for articulated wagons) */ engine_type = parent_engine_type; @@ -1966,7 +1966,7 @@ LiveryScheme GetEngineLiveryScheme(EngineID engine_type, EngineID parent_engine_ if (!IsValidCargoType(cargo_type)) cargo_type = e->GetDefaultCargoType(); if (!IsValidCargoType(cargo_type)) cargo_type = GetCargoTypeByLabel(CT_GOODS); // The vehicle does not carry anything, let's pick some freight cargo assert(IsValidCargoType(cargo_type)); - if (e->u.rail.railveh_type == RAILVEH_WAGON) { + if (e->VehInfo().railveh_type == RAILVEH_WAGON) { if (!CargoSpec::Get(cargo_type)->is_freight) { if (parent_engine_type == EngineID::Invalid()) { return LS_PASSENGER_WAGON_STEAM; @@ -1987,7 +1987,7 @@ LiveryScheme GetEngineLiveryScheme(EngineID engine_type, EngineID parent_engine_ } else { bool is_mu = e->info.misc_flags.Test(EngineMiscFlag::RailIsMU); - switch (e->u.rail.engclass) { + switch (e->VehInfo().engclass) { default: NOT_REACHED(); case EC_STEAM: return LS_STEAM; case EC_DIESEL: return is_mu ? LS_DMU : LS_DIESEL; @@ -2024,7 +2024,7 @@ LiveryScheme GetEngineLiveryScheme(EngineID engine_type, EngineID parent_engine_ return IsCargoInClass(cargo_type, CargoClass::Passengers) ? LS_PASSENGER_SHIP : LS_FREIGHT_SHIP; case VEH_AIRCRAFT: - switch (e->u.air.subtype) { + switch (e->VehInfo().subtype) { case AIR_HELI: return LS_HELICOPTER; case AIR_CTOL: return LS_SMALL_PLANE; case AIR_CTOL | AIR_FAST: return LS_LARGE_PLANE; @@ -2052,16 +2052,16 @@ const Livery *GetEngineLivery(EngineID engine_type, CompanyID company, EngineID const Group *g = Group::GetIfValid(v->First()->group_id); if (g != nullptr) { /* Traverse parents until we find a livery or reach the top */ - while (g->livery.in_use == 0 && g->parent != GroupID::Invalid()) { + while (!g->livery.in_use.Any({Livery::Flag::Primary, Livery::Flag::Secondary}) && g->parent != GroupID::Invalid()) { g = Group::Get(g->parent); } - if (g->livery.in_use != 0) return &g->livery; + if (g->livery.in_use.Any({Livery::Flag::Primary, Livery::Flag::Secondary})) return &g->livery; } } /* The default livery is always available for use, but its in_use flag determines * whether any _other_ liveries are in use. */ - if (c->livery[LS_DEFAULT].in_use != 0) { + if (c->livery[LS_DEFAULT].in_use.Any({Livery::Flag::Primary, Livery::Flag::Secondary})) { /* Determine the livery scheme to use */ scheme = GetEngineLiveryScheme(engine_type, parent_engine_type, v); } @@ -2641,9 +2641,9 @@ void Vehicle::UpdateVisualEffect(bool allow_power_change) /* Evaluate properties */ uint8_t visual_effect; switch (e->type) { - case VEH_TRAIN: visual_effect = e->u.rail.visual_effect; break; - case VEH_ROAD: visual_effect = e->u.road.visual_effect; break; - case VEH_SHIP: visual_effect = e->u.ship.visual_effect; break; + case VEH_TRAIN: visual_effect = e->VehInfo().visual_effect; break; + case VEH_ROAD: visual_effect = e->VehInfo().visual_effect; break; + case VEH_SHIP: visual_effect = e->VehInfo().visual_effect; break; default: visual_effect = 1 << VE_DISABLE_EFFECT; break; } @@ -2670,7 +2670,7 @@ void Vehicle::UpdateVisualEffect(bool allow_power_change) (!HasBit(visual_effect, VE_DISABLE_EFFECT) && GB(visual_effect, VE_TYPE_START, VE_TYPE_COUNT) == VE_TYPE_DEFAULT)) { /* Only train engines have default effects. * Note: This is independent of whether the engine is a front engine or articulated part or whatever. */ - if (e->type != VEH_TRAIN || e->u.rail.railveh_type == RAILVEH_WAGON || !IsInsideMM(e->u.rail.engclass, EC_STEAM, EC_MONORAIL)) { + if (e->type != VEH_TRAIN || e->VehInfo().railveh_type == RAILVEH_WAGON || !IsInsideMM(e->VehInfo().engclass, EC_STEAM, EC_MONORAIL)) { if (visual_effect == VE_DEFAULT) { visual_effect = 1 << VE_DISABLE_EFFECT; } else { @@ -2679,9 +2679,9 @@ void Vehicle::UpdateVisualEffect(bool allow_power_change) } else { if (visual_effect == VE_DEFAULT) { /* Also set the offset */ - visual_effect = (VE_OFFSET_CENTRE - (e->u.rail.engclass == EC_STEAM ? 4 : 0)) << VE_OFFSET_START; + visual_effect = (VE_OFFSET_CENTRE - (e->VehInfo().engclass == EC_STEAM ? 4 : 0)) << VE_OFFSET_START; } - SB(visual_effect, VE_TYPE_START, VE_TYPE_COUNT, e->u.rail.engclass - EC_STEAM + VE_TYPE_STEAM); + SB(visual_effect, VE_TYPE_START, VE_TYPE_COUNT, e->VehInfo().engclass - EC_STEAM + VE_TYPE_STEAM); } } @@ -3063,7 +3063,7 @@ bool CanVehicleUseStation(EngineID engine_type, const Station *st) case VEH_AIRCRAFT: return st->facilities.Test(StationFacility::Airport) && - st->airport.GetFTA()->flags.Test(e->u.air.subtype & AIR_CTOL ? AirportFTAClass::Flag::Airplanes : AirportFTAClass::Flag::Helicopters); + st->airport.GetFTA()->flags.Test(e->VehInfo().subtype & AIR_CTOL ? AirportFTAClass::Flag::Airplanes : AirportFTAClass::Flag::Helicopters); default: return false; @@ -3124,7 +3124,7 @@ StringID GetVehicleCannotUseStationReason(const Vehicle *v, const Station *st) case VEH_AIRCRAFT: if (!st->facilities.Test(StationFacility::Airport)) return STR_ERROR_NO_AIRPORT; - if (v->GetEngine()->u.air.subtype & AIR_CTOL) { + if (v->GetEngine()->VehInfo().subtype & AIR_CTOL) { return STR_ERROR_AIRPORT_NO_PLANES; } else { return STR_ERROR_AIRPORT_NO_HELICOPTERS; diff --git a/src/vehicle_base.h b/src/vehicle_base.h index 8fe5ec0f6d906..6e9cc5e20f2cf 100644 --- a/src/vehicle_base.h +++ b/src/vehicle_base.h @@ -64,26 +64,6 @@ struct NewGRFCache { auto operator<=>(const NewGRFCache &) const = default; }; -/** Meaning of the various bits of the visual effect. */ -enum VisualEffect : uint8_t { - VE_OFFSET_START = 0, ///< First bit that contains the offset (0 = front, 8 = centre, 15 = rear) - VE_OFFSET_COUNT = 4, ///< Number of bits used for the offset - VE_OFFSET_CENTRE = 8, ///< Value of offset corresponding to a position above the centre of the vehicle - - VE_TYPE_START = 4, ///< First bit used for the type of effect - VE_TYPE_COUNT = 2, ///< Number of bits used for the effect type - VE_TYPE_DEFAULT = 0, ///< Use default from engine class - VE_TYPE_STEAM = 1, ///< Steam plumes - VE_TYPE_DIESEL = 2, ///< Diesel fumes - VE_TYPE_ELECTRIC = 3, ///< Electric sparks - - VE_DISABLE_EFFECT = 6, ///< Flag to disable visual effect - VE_ADVANCED_EFFECT = VE_DISABLE_EFFECT, ///< Flag for advanced effects - VE_DISABLE_WAGON_POWER = 7, ///< Flag to disable wagon power - - VE_DEFAULT = 0xFF, ///< Default value to indicate that visual effect should be based on engine class -}; - /** Models for spawning visual effects. */ enum VisualEffectSpawnModel : uint8_t { VESM_NONE = 0, ///< No visual effect @@ -734,9 +714,10 @@ struct Vehicle : VehiclePool::PoolItem<&_vehicle_pool>, BaseVehicle, BaseConsist * Get the next station the vehicle will stop at. * @return ID of the next station the vehicle will stop at or StationID::Invalid(). */ - inline StationIDStack GetNextStoppingStation() const + inline void GetNextStoppingStation(std::vector &next_station) const { - return (this->orders == nullptr) ? StationID::Invalid() : this->orders->GetNextStoppingStation(this); + if (this->orders == nullptr) return; + this->orders->GetNextStoppingStation(next_station, this); } void ResetRefitCaps(); diff --git a/src/vehicle_cmd.cpp b/src/vehicle_cmd.cpp index c27fb92ded52a..c5a93b0f37250 100644 --- a/src/vehicle_cmd.cpp +++ b/src/vehicle_cmd.cpp @@ -122,10 +122,10 @@ std::tuple CmdBuildVehicle(D /* Check whether the number of vehicles we need to build can be built according to pool space. */ uint num_vehicles; switch (type) { - case VEH_TRAIN: num_vehicles = (e->u.rail.railveh_type == RAILVEH_MULTIHEAD ? 2 : 1) + CountArticulatedParts(eid, false); break; + case VEH_TRAIN: num_vehicles = (e->VehInfo().railveh_type == RAILVEH_MULTIHEAD ? 2 : 1) + CountArticulatedParts(eid, false); break; case VEH_ROAD: num_vehicles = 1 + CountArticulatedParts(eid, false); break; case VEH_SHIP: num_vehicles = 1; break; - case VEH_AIRCRAFT: num_vehicles = e->u.air.subtype & AIR_CTOL ? 2 : 3; break; + case VEH_AIRCRAFT: num_vehicles = e->VehInfo().subtype & AIR_CTOL ? 2 : 3; break; default: NOT_REACHED(); // Safe due to IsDepotTile() } if (!Vehicle::CanAllocateItem(num_vehicles)) return { CommandCost(STR_ERROR_TOO_MANY_VEHICLES_IN_GAME), VehicleID::Invalid(), 0, 0, {} }; @@ -133,7 +133,7 @@ std::tuple CmdBuildVehicle(D /* Check whether we can allocate a unit number. Autoreplace does not allocate * an unit number as it will (always) reuse the one of the replaced vehicle * and (train) wagons don't have an unit number in any scenario. */ - UnitID unit_num = (flags.Test(DoCommandFlag::QueryCost) || flags.Test(DoCommandFlag::AutoReplace) || (type == VEH_TRAIN && e->u.rail.railveh_type == RAILVEH_WAGON)) ? 0 : GetFreeUnitNumber(type); + UnitID unit_num = (flags.Test(DoCommandFlag::QueryCost) || flags.Test(DoCommandFlag::AutoReplace) || (type == VEH_TRAIN && e->VehInfo().railveh_type == RAILVEH_WAGON)) ? 0 : GetFreeUnitNumber(type); if (unit_num == UINT16_MAX) return { CommandCost(STR_ERROR_TOO_MANY_VEHICLES_IN_GAME), VehicleID::Invalid(), 0, 0, {} }; /* If we are refitting we need to temporarily purchase the vehicle to be able to @@ -325,7 +325,7 @@ static CommandCost GetRefitCost(const Vehicle *v, EngineID engine_type, CargoTyp break; case VEH_TRAIN: - base_price = (e->u.rail.railveh_type == RAILVEH_WAGON) ? PR_BUILD_VEHICLE_WAGON : PR_BUILD_VEHICLE_TRAIN; + base_price = (e->VehInfo().railveh_type == RAILVEH_WAGON) ? PR_BUILD_VEHICLE_WAGON : PR_BUILD_VEHICLE_TRAIN; cost_factor <<= 1; expense_type = EXPENSES_TRAIN_RUN; break; diff --git a/src/vehicle_cmd.h b/src/vehicle_cmd.h index 8f663673bc15f..b393a6a1f3ede 100644 --- a/src/vehicle_cmd.h +++ b/src/vehicle_cmd.h @@ -29,17 +29,17 @@ CommandCost CmdMassStartStopVehicle(DoCommandFlags flags, TileIndex tile, bool d CommandCost CmdDepotSellAllVehicles(DoCommandFlags flags, TileIndex tile, VehicleType vehicle_type); CommandCost CmdDepotMassAutoReplace(DoCommandFlags flags, TileIndex tile, VehicleType vehicle_type); -DEF_CMD_TRAIT(CMD_BUILD_VEHICLE, CmdBuildVehicle, CommandFlag::ClientID, CMDT_VEHICLE_CONSTRUCTION) -DEF_CMD_TRAIT(CMD_SELL_VEHICLE, CmdSellVehicle, CommandFlags({CommandFlag::ClientID, CommandFlag::Location}), CMDT_VEHICLE_CONSTRUCTION) -DEF_CMD_TRAIT(CMD_REFIT_VEHICLE, CmdRefitVehicle, CommandFlag::Location, CMDT_VEHICLE_CONSTRUCTION) -DEF_CMD_TRAIT(CMD_SEND_VEHICLE_TO_DEPOT, CmdSendVehicleToDepot, {}, CMDT_VEHICLE_MANAGEMENT) -DEF_CMD_TRAIT(CMD_CHANGE_SERVICE_INT, CmdChangeServiceInt, {}, CMDT_VEHICLE_MANAGEMENT) -DEF_CMD_TRAIT(CMD_RENAME_VEHICLE, CmdRenameVehicle, {}, CMDT_OTHER_MANAGEMENT) -DEF_CMD_TRAIT(CMD_CLONE_VEHICLE, CmdCloneVehicle, CommandFlag::NoTest, CMDT_VEHICLE_CONSTRUCTION) // NewGRF callbacks influence building and refitting making it impossible to correctly estimate the cost -DEF_CMD_TRAIT(CMD_START_STOP_VEHICLE, CmdStartStopVehicle, CommandFlag::Location, CMDT_VEHICLE_MANAGEMENT) -DEF_CMD_TRAIT(CMD_MASS_START_STOP, CmdMassStartStopVehicle, {}, CMDT_VEHICLE_MANAGEMENT) -DEF_CMD_TRAIT(CMD_DEPOT_SELL_ALL_VEHICLES, CmdDepotSellAllVehicles, {}, CMDT_VEHICLE_CONSTRUCTION) -DEF_CMD_TRAIT(CMD_DEPOT_MASS_AUTOREPLACE, CmdDepotMassAutoReplace, {}, CMDT_VEHICLE_CONSTRUCTION) +DEF_CMD_TRAIT(CMD_BUILD_VEHICLE, CmdBuildVehicle, CommandFlag::ClientID, CommandType::VehicleConstruction) +DEF_CMD_TRAIT(CMD_SELL_VEHICLE, CmdSellVehicle, CommandFlags({CommandFlag::ClientID, CommandFlag::Location}), CommandType::VehicleConstruction) +DEF_CMD_TRAIT(CMD_REFIT_VEHICLE, CmdRefitVehicle, CommandFlag::Location, CommandType::VehicleConstruction) +DEF_CMD_TRAIT(CMD_SEND_VEHICLE_TO_DEPOT, CmdSendVehicleToDepot, {}, CommandType::VehicleManagement) +DEF_CMD_TRAIT(CMD_CHANGE_SERVICE_INT, CmdChangeServiceInt, {}, CommandType::VehicleManagement) +DEF_CMD_TRAIT(CMD_RENAME_VEHICLE, CmdRenameVehicle, {}, CommandType::OtherManagement) +DEF_CMD_TRAIT(CMD_CLONE_VEHICLE, CmdCloneVehicle, CommandFlag::NoTest, CommandType::VehicleConstruction) // NewGRF callbacks influence building and refitting making it impossible to correctly estimate the cost +DEF_CMD_TRAIT(CMD_START_STOP_VEHICLE, CmdStartStopVehicle, CommandFlag::Location, CommandType::VehicleManagement) +DEF_CMD_TRAIT(CMD_MASS_START_STOP, CmdMassStartStopVehicle, {}, CommandType::VehicleManagement) +DEF_CMD_TRAIT(CMD_DEPOT_SELL_ALL_VEHICLES, CmdDepotSellAllVehicles, {}, CommandType::VehicleConstruction) +DEF_CMD_TRAIT(CMD_DEPOT_MASS_AUTOREPLACE, CmdDepotMassAutoReplace, {}, CommandType::VehicleConstruction) void CcBuildPrimaryVehicle(Commands cmd, const CommandCost &result, VehicleID new_veh_id, uint, uint16_t, CargoArray); void CcStartStopVehicle(Commands cmd, const CommandCost &result, VehicleID veh_id, bool); diff --git a/src/vehicle_gui.cpp b/src/vehicle_gui.cpp index fbd7a69b54a27..a9a37ecd0e5ed 100644 --- a/src/vehicle_gui.cpp +++ b/src/vehicle_gui.cpp @@ -30,7 +30,6 @@ #include "dropdown_func.h" #include "timetable.h" #include "articulated_vehicles.h" -#include "spritecache.h" #include "core/geometry_func.hpp" #include "core/container_func.hpp" #include "company_base.h" @@ -1042,7 +1041,7 @@ struct RefitWindow : public Window { switch (widget) { case WID_VR_VEHICLE_PANEL_DISPLAY: { Vehicle *v = Vehicle::Get(this->window_number); - DrawVehicleImage(v, {this->sprite_left, r.top, this->sprite_right, r.bottom}, + DrawVehicleImage(v, r.WithX(this->sprite_left, this->sprite_right), VehicleID::Invalid(), EIT_IN_DETAILS, this->hscroll != nullptr ? this->hscroll->GetPosition() : 0); /* Highlight selected vehicles. */ @@ -1308,7 +1307,7 @@ struct RefitWindow : public Window { } }; -static constexpr NWidgetPart _nested_vehicle_refit_widgets[] = { +static constexpr std::initializer_list _nested_vehicle_refit_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), NWidget(WWT_CAPTION, COLOUR_GREY, WID_VR_CAPTION), @@ -1596,7 +1595,7 @@ void ChangeVehicleViewWindow(VehicleID from_index, VehicleID to_index) ChangeVehicleWindow(WC_VEHICLE_TIMETABLE, from_index, to_index); } -static constexpr NWidgetPart _nested_vehicle_list[] = { +static constexpr std::initializer_list _nested_vehicle_list = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), NWidget(NWID_SELECTION, INVALID_COLOUR, WID_VL_CAPTION_SELECTION), @@ -1791,7 +1790,7 @@ void BaseVehicleListWindow::DrawVehicleListItems(VehicleID selected_vehicle, int DrawSprite(SPR_WARNING_SIGN, PAL_NONE, vehicle_button_x, ir.top + GetCharacterHeight(FS_NORMAL) + WidgetDimensions::scaled.vsep_normal + profit.height); } - DrawVehicleImage(v, {image_left, ir.top, image_right, ir.bottom}, selected_vehicle, EIT_IN_LIST, 0); + DrawVehicleImage(v, ir.WithX(image_left, image_right), selected_vehicle, EIT_IN_LIST, 0); if (_settings_client.gui.show_cargo_in_vehicle_lists) { /* Get the cargoes the vehicle can carry */ @@ -1843,7 +1842,7 @@ void BaseVehicleListWindow::DrawVehicleListItems(VehicleID selected_vehicle, int for (int i = 0; i < static_cast(vehgroup.NumVehicles()); ++i) { if (image_left + WidgetDimensions::scaled.hsep_wide * i >= image_right) break; // Break if there is no more space to draw any more vehicles anyway. - DrawVehicleImage(vehgroup.vehicles_begin[i], {image_left + WidgetDimensions::scaled.hsep_wide * i, ir.top, image_right, ir.bottom}, selected_vehicle, EIT_IN_LIST, 0); + DrawVehicleImage(vehgroup.vehicles_begin[i], ir.WithX(image_left + WidgetDimensions::scaled.hsep_wide * i, image_right), selected_vehicle, EIT_IN_LIST, 0); } if (show_orderlist) DrawSmallOrderList(vehgroup.vehicles_begin[0]->orders, olr.left, olr.right, ir.top + GetCharacterHeight(FS_SMALL), this->order_arrow_width); @@ -2325,7 +2324,7 @@ static_assert(WID_VD_DETAILS_CAPACITY_OF_EACH == WID_VD_DETAILS_CARGO_CARRIED + static_assert(WID_VD_DETAILS_TOTAL_CARGO == WID_VD_DETAILS_CARGO_CARRIED + TDW_TAB_TOTALS ); /** Vehicle details widgets (other than train). */ -static constexpr NWidgetPart _nested_nontrain_vehicle_details_widgets[] = { +static constexpr std::initializer_list _nested_nontrain_vehicle_details_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), NWidget(WWT_CAPTION, COLOUR_GREY, WID_VD_CAPTION), @@ -2348,7 +2347,7 @@ static constexpr NWidgetPart _nested_nontrain_vehicle_details_widgets[] = { }; /** Train details widgets. */ -static constexpr NWidgetPart _nested_train_vehicle_details_widgets[] = { +static constexpr std::initializer_list _nested_train_vehicle_details_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), NWidget(WWT_CAPTION, COLOUR_GREY, WID_VD_CAPTION), SetStringTip(STR_VEHICLE_DETAILS_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), @@ -2821,7 +2820,7 @@ static void ShowVehicleDetailsWindow(const Vehicle *v) /* Unified vehicle GUI - Vehicle View Window */ /** Vehicle view widgets. */ -static constexpr NWidgetPart _nested_vehicle_view_widgets[] = { +static constexpr std::initializer_list _nested_vehicle_view_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_VV_RENAME), SetAspect(WidgetDimensions::ASPECT_RENAME), SetSpriteTip(SPR_RENAME), diff --git a/src/video/allegro_v.cpp b/src/video/allegro_v.cpp index 424fafa2a973d..11f0d63e9b4e5 100644 --- a/src/video/allegro_v.cpp +++ b/src/video/allegro_v.cpp @@ -28,14 +28,14 @@ #include "allegro_v.h" #include -#include "../safeguards.h" - #ifdef _DEBUG /* Allegro replaces SEGV/ABRT signals meaning that the debugger will never * be triggered, so rereplace the signals and make the debugger useful. */ #include #endif +#include "../safeguards.h" + static FVideoDriver_Allegro iFVideoDriver_Allegro; static BITMAP *_allegro_screen; diff --git a/src/video/win32_v.cpp b/src/video/win32_v.cpp index 728b2be9f922a..d8600faa655f2 100644 --- a/src/video/win32_v.cpp +++ b/src/video/win32_v.cpp @@ -32,6 +32,13 @@ #include #endif +#ifdef WITH_OPENGL +#include +#include "../3rdparty/opengl/glext.h" +#include "../3rdparty/opengl/wglext.h" +#include "opengl.h" +#endif /* WITH_OPENGL */ + #include "../safeguards.h" /* Missing define in MinGW headers. */ @@ -1285,11 +1292,6 @@ void VideoDriver_Win32GDI::Paint() #ifdef WITH_OPENGL -#include -#include "../3rdparty/opengl/glext.h" -#include "../3rdparty/opengl/wglext.h" -#include "opengl.h" - #ifndef PFD_SUPPORT_COMPOSITION # define PFD_SUPPORT_COMPOSITION 0x00008000 #endif diff --git a/src/viewport.cpp b/src/viewport.cpp index 734a34bb7a68a..83d08f5c56610 100644 --- a/src/viewport.cpp +++ b/src/viewport.cpp @@ -1637,8 +1637,8 @@ static void ViewportSortParentSprites(ParentSpriteToSortVector *psdv) auto ssum = std::max(s->xmax, s->xmin) + std::max(s->ymax, s->ymin); auto prev = sprite_list.before_begin(); auto x = sprite_list.begin(); - while (x != sprite_list.end() && ((*x).first <= ssum)) { - auto p = (*x).second; + while (x != sprite_list.end() && x->first <= ssum) { + auto p = x->second; if (p == s) { /* We found the current sprite, remove it and move on. */ x = sprite_list.erase_after(prev); diff --git a/src/viewport_cmd.h b/src/viewport_cmd.h index c50f9db1a7d46..b8d931f56173e 100644 --- a/src/viewport_cmd.h +++ b/src/viewport_cmd.h @@ -15,6 +15,6 @@ CommandCost CmdScrollViewport(DoCommandFlags flags, TileIndex tile, ViewportScrollTarget target, uint32_t ref); -DEF_CMD_TRAIT(CMD_SCROLL_VIEWPORT, CmdScrollViewport, CommandFlag::Deity, CMDT_OTHER_MANAGEMENT) +DEF_CMD_TRAIT(CMD_SCROLL_VIEWPORT, CmdScrollViewport, CommandFlag::Deity, CommandType::OtherManagement) #endif /* VIEWPORT_CMD_H */ diff --git a/src/viewport_gui.cpp b/src/viewport_gui.cpp index 0ea8b683da76c..1c6b8413b5b69 100644 --- a/src/viewport_gui.cpp +++ b/src/viewport_gui.cpp @@ -23,7 +23,7 @@ #include "safeguards.h" /* Extra Viewport Window Stuff */ -static constexpr NWidgetPart _nested_extra_viewport_widgets[] = { +static constexpr std::initializer_list _nested_extra_viewport_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), NWidget(WWT_CAPTION, COLOUR_GREY, WID_EV_CAPTION), diff --git a/src/viewport_sprite_sorter_sse4.cpp b/src/viewport_sprite_sorter_sse4.cpp index a5ce747dc1891..448502ef0c777 100644 --- a/src/viewport_sprite_sorter_sse4.cpp +++ b/src/viewport_sprite_sorter_sse4.cpp @@ -87,8 +87,8 @@ void ViewportSortParentSpritesSSE41(ParentSpriteToSortVector *psdv) auto ssum = std::max(s->xmax, s->xmin) + std::max(s->ymax, s->ymin); auto prev = sprite_list.before_begin(); auto x = sprite_list.begin(); - while (x != sprite_list.end() && ((*x).first <= ssum)) { - auto p = (*x).second; + while (x != sprite_list.end() && x->first <= ssum) { + auto p = x->second; if (p == s) { /* We found the current sprite, remove it and move on. */ x = sprite_list.erase_after(prev); diff --git a/src/void_cmd.cpp b/src/void_cmd.cpp index 2665f4d2bfe44..a49483e91cf40 100644 --- a/src/void_cmd.cpp +++ b/src/void_cmd.cpp @@ -21,7 +21,12 @@ static void DrawTile_Void(TileInfo *ti) { - DrawGroundSprite(SPR_FLAT_BARE_LAND + SlopeToSpriteOffset(ti->tileh), PALETTE_ALL_BLACK); + /* If freeform edges are off, draw infinite water off the edges of the map. */ + if (!_settings_game.construction.freeform_edges) { + DrawGroundSprite(SPR_FLAT_WATER_TILE + SlopeToSpriteOffset(ti->tileh), PAL_NONE); + } else { + DrawGroundSprite(SPR_FLAT_BARE_LAND + SlopeToSpriteOffset(ti->tileh), PALETTE_ALL_BLACK); + } } diff --git a/src/void_map.h b/src/void_map.h index e8e031be79835..4a5976db3ba9c 100644 --- a/src/void_map.h +++ b/src/void_map.h @@ -27,6 +27,7 @@ inline void MakeVoid(Tile t) t.m5() = 0; t.m6() = 0; t.m7() = 0; + t.m8() = 0; } #endif /* VOID_MAP_H */ diff --git a/src/water_cmd.cpp b/src/water_cmd.cpp index 39a06374e1da5..f0a1252a75227 100644 --- a/src/water_cmd.cpp +++ b/src/water_cmd.cpp @@ -365,7 +365,8 @@ static CommandCost DoBuildLock(TileIndex tile, DiagDirection dir, DoCommandFlags for (LockPart lock_part = LOCK_PART_MIDDLE; TileIndex t : {tile, tile - delta, tile + delta}) { if (IsBridgeAbove(t) && GetBridgeHeight(GetSouthernBridgeEnd(t)) < GetTileMaxZ(t) + GetLockPartMinimalBridgeHeight(lock_part)) { - return CommandCost(STR_ERROR_BRIDGE_TOO_LOW_FOR_LOCK); + int height_diff = (GetTileMaxZ(tile) + GetLockPartMinimalBridgeHeight(lock_part) - GetBridgeHeight(GetSouthernBridgeEnd(t))) * TILE_HEIGHT_STEP; + return CommandCostWithParam(STR_ERROR_BRIDGE_TOO_LOW_FOR_LOCK, height_diff); } ++lock_part; } @@ -454,6 +455,13 @@ CommandCost CmdBuildLock(DoCommandFlags flags, TileIndex tile) DiagDirection dir = GetInclinedSlopeDirection(GetTileSlope(tile)); if (dir == INVALID_DIAGDIR) return CommandCost(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION); + TileIndex lower_tile = TileAddByDiagDir(tile, ReverseDiagDir(dir)); + + /* If freeform edges are disabled, don't allow building on edge tiles. */ + if (!_settings_game.construction.freeform_edges && (!IsInsideMM(TileX(lower_tile), 1, Map::MaxX() - 1) || !IsInsideMM(TileY(lower_tile), 1, Map::MaxY() - 1))) { + return CommandCost(STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP); + } + return DoBuildLock(tile, dir, flags); } @@ -1438,7 +1446,8 @@ static CommandCost CheckBuildAbove_Water(TileIndex tile, DoCommandFlags flags, A if (IsWater(tile) || IsCoast(tile)) return CommandCost(); if (IsLock(tile)) { if (GetTileMaxZ(tile) + GetLockPartMinimalBridgeHeight(GetLockPart(tile)) <= height) return CommandCost(); - return CommandCost(STR_ERROR_BRIDGE_TOO_LOW_FOR_LOCK); + int height_diff = (GetTileMaxZ(tile) + GetLockPartMinimalBridgeHeight(GetLockPart(tile)) - height) * TILE_HEIGHT_STEP; + return CommandCostWithParam(STR_ERROR_BRIDGE_TOO_LOW_FOR_LOCK, height_diff); } return Command::Do(flags, tile); } diff --git a/src/water_cmd.h b/src/water_cmd.h index 56911695b152a..9193c5b1c4eaa 100644 --- a/src/water_cmd.h +++ b/src/water_cmd.h @@ -17,8 +17,8 @@ CommandCost CmdBuildShipDepot(DoCommandFlags flags, TileIndex tile, Axis axis); CommandCost CmdBuildCanal(DoCommandFlags flags, TileIndex tile, TileIndex start_tile, WaterClass wc, bool diagonal); CommandCost CmdBuildLock(DoCommandFlags flags, TileIndex tile); -DEF_CMD_TRAIT(CMD_BUILD_SHIP_DEPOT, CmdBuildShipDepot, CommandFlag::Auto, CMDT_LANDSCAPE_CONSTRUCTION) -DEF_CMD_TRAIT(CMD_BUILD_CANAL, CmdBuildCanal, CommandFlag::Auto, CMDT_LANDSCAPE_CONSTRUCTION) -DEF_CMD_TRAIT(CMD_BUILD_LOCK, CmdBuildLock, CommandFlag::Auto, CMDT_LANDSCAPE_CONSTRUCTION) +DEF_CMD_TRAIT(CMD_BUILD_SHIP_DEPOT, CmdBuildShipDepot, CommandFlag::Auto, CommandType::LandscapeConstruction) +DEF_CMD_TRAIT(CMD_BUILD_CANAL, CmdBuildCanal, CommandFlag::Auto, CommandType::LandscapeConstruction) +DEF_CMD_TRAIT(CMD_BUILD_LOCK, CmdBuildLock, CommandFlag::Auto, CommandType::LandscapeConstruction) #endif /* WATER_CMD_H */ diff --git a/src/water_map.h b/src/water_map.h index 2c424d44b1df5..7f8471c00d2f7 100644 --- a/src/water_map.h +++ b/src/water_map.h @@ -391,8 +391,9 @@ inline void MakeShore(Tile t) t.m4() = 0; t.m5() = 0; SetWaterTileType(t, WATER_TILE_COAST); - SB(t.m6(), 2, 4, 0); + SB(t.m6(), 2, 6, 0); t.m7() = 0; + t.m8() = 0; } /** @@ -413,8 +414,9 @@ inline void MakeWater(Tile t, Owner o, WaterClass wc, uint8_t random_bits) t.m4() = random_bits; t.m5() = 0; SetWaterTileType(t, WATER_TILE_CLEAR); - SB(t.m6(), 2, 4, 0); + SB(t.m6(), 2, 6, 0); t.m7() = 0; + t.m8() = 0; } /** @@ -468,8 +470,9 @@ inline void MakeShipDepot(Tile t, Owner o, DepotID did, DepotPart part, Axis a, t.m4() = 0; t.m5() = part << WBL_DEPOT_PART | a << WBL_DEPOT_AXIS; SetWaterTileType(t, WATER_TILE_DEPOT); - SB(t.m6(), 2, 4, 0); + SB(t.m6(), 2, 6, 0); t.m7() = 0; + t.m8() = 0; } /** @@ -492,8 +495,9 @@ inline void MakeLockTile(Tile t, Owner o, LockPart part, DiagDirection dir, Wate t.m4() = 0; t.m5() = part << WBL_LOCK_PART_BEGIN | dir << WBL_LOCK_ORIENT_BEGIN; SetWaterTileType(t, WATER_TILE_LOCK); - SB(t.m6(), 2, 4, 0); + SB(t.m6(), 2, 6, 0); t.m7() = 0; + t.m8() = 0; } /** diff --git a/src/waypoint_cmd.cpp b/src/waypoint_cmd.cpp index 18a0540595c9f..cce1da5e2d309 100644 --- a/src/waypoint_cmd.cpp +++ b/src/waypoint_cmd.cpp @@ -271,7 +271,8 @@ CommandCost CmdBuildRailWaypoint(DoCommandFlags flags, TileIndex start_tile, Axi if (!Waypoint::CanAllocateItem()) return CommandCost(STR_ERROR_TOO_MANY_STATIONS_LOADING); } - auto specindex = AllocateSpecToStation(spec, wp, flags.Test(DoCommandFlag::Execute)); + /* Check if we can allocate a custom spec to this waypoint. */ + auto specindex = AllocateSpecToStation(spec, wp); if (!specindex.has_value()) return CommandCost(STR_ERROR_TOO_MANY_STATION_SPECS); if (flags.Test(DoCommandFlag::Execute)) { @@ -284,6 +285,7 @@ CommandCost CmdBuildRailWaypoint(DoCommandFlags flags, TileIndex start_tile, Axi wp->owner = GetTileOwner(start_tile); wp->rect.BeforeAddRect(start_tile, width, height, StationRect::ADD_TRY); + if (specindex.has_value()) AssignSpecToStation(spec, wp, *specindex); wp->delete_ctr = 0; wp->facilities.Set(StationFacility::Train); @@ -305,7 +307,7 @@ CommandCost CmdBuildRailWaypoint(DoCommandFlags flags, TileIndex start_tile, Axi bool reserved = IsTileType(tile, MP_RAILWAY) ? HasBit(GetRailReservationTrackBits(tile), AxisToTrack(axis)) : HasStationReservation(tile); - MakeRailWaypoint(tile, wp->owner, wp->index, axis, *it++, GetRailType(tile)); + MakeRailWaypoint(tile, wp->owner, wp->index, axis, *it++, GetMapRailType(tile)); SetCustomStationSpecIndex(tile, *specindex); SetRailStationTileFlags(tile, spec); @@ -391,8 +393,8 @@ CommandCost CmdBuildRoadWaypoint(DoCommandFlags flags, TileIndex start_tile, Axi if (!Waypoint::CanAllocateItem()) return CommandCost(STR_ERROR_TOO_MANY_STATIONS_LOADING); } - /* Check if we can allocate a custom roadstopspec to this station */ - auto specindex = AllocateSpecToRoadStop(roadstopspec, wp, flags.Test(DoCommandFlag::Execute)); + /* Check if we can allocate a custom spec to this waypoint. */ + auto specindex = AllocateSpecToRoadStop(roadstopspec, wp); if (!specindex.has_value()) return CommandCost(STR_ERROR_TOO_MANY_STATION_SPECS); if (flags.Test(DoCommandFlag::Execute)) { @@ -406,6 +408,7 @@ CommandCost CmdBuildRoadWaypoint(DoCommandFlags flags, TileIndex start_tile, Axi wp->owner = _current_company; wp->rect.BeforeAddRect(start_tile, width, height, StationRect::ADD_TRY); + if (specindex.has_value()) AssignSpecToRoadStop(roadstopspec, wp, *specindex); if (roadstopspec != nullptr) { /* Include this road stop spec's animation trigger bitmask @@ -425,10 +428,10 @@ CommandCost CmdBuildRoadWaypoint(DoCommandFlags flags, TileIndex start_tile, Axi /* Check every tile in the area. */ for (TileIndex cur_tile : roadstop_area) { /* Get existing road types and owners before any tile clearing */ - RoadType road_rt = MayHaveRoad(cur_tile) ? GetRoadType(cur_tile, RTT_ROAD) : INVALID_ROADTYPE; - RoadType tram_rt = MayHaveRoad(cur_tile) ? GetRoadType(cur_tile, RTT_TRAM) : INVALID_ROADTYPE; - Owner road_owner = road_rt != INVALID_ROADTYPE ? GetRoadOwner(cur_tile, RTT_ROAD) : _current_company; - Owner tram_owner = tram_rt != INVALID_ROADTYPE ? GetRoadOwner(cur_tile, RTT_TRAM) : _current_company; + MapRoadType map_roadtype = MayHaveRoad(cur_tile) ? GetMapRoadTypeRoad(cur_tile) : RoadTypeMapping::INVALID_MAP_TYPE; + MapTramType map_tramtype = MayHaveRoad(cur_tile) ? GetMapRoadTypeTram(cur_tile) : TramTypeMapping::INVALID_MAP_TYPE; + Owner road_owner = map_roadtype != RoadTypeMapping::INVALID_MAP_TYPE ? GetRoadOwner(cur_tile, RTT_ROAD) : _current_company; + Owner tram_owner = map_tramtype != TramTypeMapping::INVALID_MAP_TYPE ? GetRoadOwner(cur_tile, RTT_TRAM) : _current_company; if (IsRoadWaypointTile(cur_tile)) { RemoveRoadWaypointStop(cur_tile, flags, *specindex); @@ -441,14 +444,14 @@ CommandCost CmdBuildRoadWaypoint(DoCommandFlags flags, TileIndex start_tile, Axi /* Update company infrastructure counts. If the current tile is a normal road tile, remove the old * bits first. */ if (IsNormalRoadTile(cur_tile)) { - UpdateCompanyRoadInfrastructure(road_rt, road_owner, -(int)CountBits(GetRoadBits(cur_tile, RTT_ROAD))); - UpdateCompanyRoadInfrastructure(tram_rt, tram_owner, -(int)CountBits(GetRoadBits(cur_tile, RTT_TRAM))); + UpdateCompanyRoadInfrastructure(_roadtype_mapping.GetType(map_roadtype), road_owner, -(int)CountBits(GetRoadBits(cur_tile, RTT_ROAD))); + UpdateCompanyRoadInfrastructure(_tramtype_mapping.GetType(map_tramtype), tram_owner, -(int)CountBits(GetRoadBits(cur_tile, RTT_TRAM))); } - UpdateCompanyRoadInfrastructure(road_rt, road_owner, ROAD_STOP_TRACKBIT_FACTOR); - UpdateCompanyRoadInfrastructure(tram_rt, tram_owner, ROAD_STOP_TRACKBIT_FACTOR); + UpdateCompanyRoadInfrastructure(_roadtype_mapping.GetType(map_roadtype), road_owner, ROAD_STOP_TRACKBIT_FACTOR); + UpdateCompanyRoadInfrastructure(_tramtype_mapping.GetType(map_tramtype), tram_owner, ROAD_STOP_TRACKBIT_FACTOR); - MakeDriveThroughRoadStop(cur_tile, wp->owner, road_owner, tram_owner, wp->index, StationType::RoadWaypoint, road_rt, tram_rt, axis); + MakeDriveThroughRoadStop(cur_tile, wp->owner, road_owner, tram_owner, wp->index, StationType::RoadWaypoint, map_roadtype, map_tramtype, axis); SetCustomRoadStopSpecIndex(cur_tile, *specindex); if (roadstopspec != nullptr) wp->SetRoadStopRandomBits(cur_tile, 0); diff --git a/src/waypoint_cmd.h b/src/waypoint_cmd.h index e0aaf9853c530..2831c5c981395 100644 --- a/src/waypoint_cmd.h +++ b/src/waypoint_cmd.h @@ -23,11 +23,11 @@ CommandCost CmdRemoveFromRoadWaypoint(DoCommandFlags flags, TileIndex start, Til CommandCost CmdBuildBuoy(DoCommandFlags flags, TileIndex tile); CommandCost CmdRenameWaypoint(DoCommandFlags flags, StationID waypoint_id, const std::string &text); -DEF_CMD_TRAIT(CMD_BUILD_RAIL_WAYPOINT, CmdBuildRailWaypoint, {}, CMDT_LANDSCAPE_CONSTRUCTION) -DEF_CMD_TRAIT(CMD_REMOVE_FROM_RAIL_WAYPOINT, CmdRemoveFromRailWaypoint, {}, CMDT_LANDSCAPE_CONSTRUCTION) -DEF_CMD_TRAIT(CMD_BUILD_ROAD_WAYPOINT, CmdBuildRoadWaypoint, {}, CMDT_LANDSCAPE_CONSTRUCTION) -DEF_CMD_TRAIT(CMD_REMOVE_FROM_ROAD_WAYPOINT, CmdRemoveFromRoadWaypoint, {}, CMDT_LANDSCAPE_CONSTRUCTION) -DEF_CMD_TRAIT(CMD_BUILD_BUOY, CmdBuildBuoy, CommandFlag::Auto, CMDT_LANDSCAPE_CONSTRUCTION) -DEF_CMD_TRAIT(CMD_RENAME_WAYPOINT, CmdRenameWaypoint, {}, CMDT_OTHER_MANAGEMENT) +DEF_CMD_TRAIT(CMD_BUILD_RAIL_WAYPOINT, CmdBuildRailWaypoint, {}, CommandType::LandscapeConstruction) +DEF_CMD_TRAIT(CMD_REMOVE_FROM_RAIL_WAYPOINT, CmdRemoveFromRailWaypoint, {}, CommandType::LandscapeConstruction) +DEF_CMD_TRAIT(CMD_BUILD_ROAD_WAYPOINT, CmdBuildRoadWaypoint, {}, CommandType::LandscapeConstruction) +DEF_CMD_TRAIT(CMD_REMOVE_FROM_ROAD_WAYPOINT, CmdRemoveFromRoadWaypoint, {}, CommandType::LandscapeConstruction) +DEF_CMD_TRAIT(CMD_BUILD_BUOY, CmdBuildBuoy, CommandFlag::Auto, CommandType::LandscapeConstruction) +DEF_CMD_TRAIT(CMD_RENAME_WAYPOINT, CmdRenameWaypoint, {}, CommandType::OtherManagement) #endif /* WAYPOINT_CMD_H */ diff --git a/src/waypoint_gui.cpp b/src/waypoint_gui.cpp index d25020282f76f..6efd4cb29a14f 100644 --- a/src/waypoint_gui.cpp +++ b/src/waypoint_gui.cpp @@ -185,7 +185,7 @@ struct WaypointWindow : Window { }; /** The widgets of the waypoint view. */ -static constexpr NWidgetPart _nested_waypoint_view_widgets[] = { +static constexpr std::initializer_list _nested_waypoint_view_widgets = { NWidget(NWID_HORIZONTAL), NWidget(WWT_CLOSEBOX, COLOUR_GREY), NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_W_RENAME), SetAspect(WidgetDimensions::ASPECT_RENAME), SetSpriteTip(SPR_RENAME, STR_BUOY_VIEW_RENAME_TOOLTIP), diff --git a/src/widget.cpp b/src/widget.cpp index 138ce18264c80..b99da3d4bfd5a 100644 --- a/src/widget.cpp +++ b/src/widget.cpp @@ -139,57 +139,48 @@ static inline Point GetAlignedPosition(const Rect &r, const Dimension &d, String /** * Compute the vertical position of the draggable part of scrollbar - * @param sb Scrollbar list data - * @param top Top position of the scrollbar (top position of the up-button) - * @param bottom Bottom position of the scrollbar (bottom position of the down-button) + * @param sb Scrollbar list data + * @param mi Minimum coordinate of the scroll bar. + * @param ma Maximum coordinate of the scroll bar. * @param horizontal Whether the scrollbar is horizontal or not - * @return A Point, with x containing the top coordinate of the draggable part, and - * y containing the bottom coordinate of the draggable part + * @return A pair, with first containing the minimum coordinate of the draggable part, and + * second containing the maximum coordinate of the draggable part */ -static Point HandleScrollbarHittest(const Scrollbar *sb, int top, int bottom, bool horizontal) +static std::pair HandleScrollbarHittest(const Scrollbar *sb, int mi, int ma, bool horizontal) { /* Base for reversion */ - int rev_base = top + bottom; - int button_size; - if (horizontal) { - button_size = NWidgetScrollbar::GetHorizontalDimension().width; - } else { - button_size = NWidgetScrollbar::GetVerticalDimension().height; - } - top += button_size; // top points to just below the up-button - bottom -= button_size; // bottom points to just before the down-button + int rev_base = mi + ma; + int button_size = horizontal ? NWidgetScrollbar::GetHorizontalDimension().width : NWidgetScrollbar::GetVerticalDimension().height; + + mi += button_size; // now points to just after the up/left-button + ma -= button_size; // now points to just before the down/right-button int count = sb->GetCount(); int cap = sb->GetCapacity(); if (count > cap) { - int height = bottom + 1 - top; + int height = ma + 1 - mi; int slider_height = std::max(button_size, cap * height / count); height -= slider_height; - top += height * sb->GetPosition() / (count - cap); - bottom = top + slider_height - 1; + mi += height * sb->GetPosition() / (count - cap); + ma = mi + slider_height - 1; } - Point pt; - if (horizontal && _current_text_dir == TD_RTL) { - pt.x = rev_base - bottom; - pt.y = rev_base - top; - } else { - pt.x = top; - pt.y = bottom; - } - return pt; + /* Reverse coordinates for RTL. */ + if (horizontal && _current_text_dir == TD_RTL) return {rev_base - ma, rev_base - mi}; + + return {mi, ma}; } /** * Compute new position of the scrollbar after a click and updates the window flags. - * @param w Window on which a scroll was performed. - * @param sb Scrollbar - * @param mi Minimum coordinate of the scroll bar. - * @param ma Maximum coordinate of the scroll bar. - * @param x The X coordinate of the mouse click. - * @param y The Y coordinate of the mouse click. + * @param w Window on which a scroll was performed. + * @param sb Scrollbar + * @param x The X coordinate of the mouse click. + * @param y The Y coordinate of the mouse click. + * @param mi Minimum coordinate of the scroll bar. + * @param ma Maximum coordinate of the scroll bar. */ static void ScrollbarClickPositioning(Window *w, NWidgetScrollbar *sb, int x, int y, int mi, int ma) { @@ -224,15 +215,15 @@ static void ScrollbarClickPositioning(Window *w, NWidgetScrollbar *sb, int x, in } w->mouse_capture_widget = sb->GetIndex(); } else { - Point pt = HandleScrollbarHittest(sb, mi, ma, sb->type == NWID_HSCROLLBAR); + auto [start, end] = HandleScrollbarHittest(sb, mi, ma, sb->type == NWID_HSCROLLBAR); - if (pos < pt.x) { + if (pos < start) { changed = sb->UpdatePosition(rtl ? 1 : -1, Scrollbar::SS_BIG); - } else if (pos > pt.y) { + } else if (pos > end) { changed = sb->UpdatePosition(rtl ? -1 : 1, Scrollbar::SS_BIG); } else { - _scrollbar_start_pos = pt.x - mi - button_size; - _scrollbar_size = ma - mi - button_size * 2 - (pt.y - pt.x); + _scrollbar_start_pos = start - mi - button_size; + _scrollbar_size = ma - mi - button_size * 2 - (end - start); w->mouse_capture_widget = sb->GetIndex(); _cursorpos_drag_start = _cursor.pos; } @@ -278,12 +269,12 @@ void ScrollbarClickHandler(Window *w, NWidgetCore *nw, int x, int y) * @param *w Window to look inside * @param x The Window client X coordinate * @param y The Window client y coordinate - * @return A widget index, or -1 if no widget was found. + * @return A widget index, or \c INVALID_WIDGET if no widget was found. */ WidgetID GetWidgetFromPos(const Window *w, int x, int y) { NWidgetCore *nw = w->nested_root->GetWidgetFromPos(x, y); - return (nw != nullptr) ? nw->GetIndex() : -1; + return (nw != nullptr) ? nw->GetIndex() : INVALID_WIDGET; } /** @@ -353,7 +344,7 @@ void DrawSpriteIgnorePadding(SpriteID img, PaletteID pal, const Rect &r, StringA static inline void DrawImageButtons(const Rect &r, WidgetType type, Colours colour, bool clicked, SpriteID img, StringAlignment align) { assert(img != 0); - DrawFrameRect(r.left, r.top, r.right, r.bottom, colour, (clicked) ? FrameFlag::Lowered : FrameFlags{}); + DrawFrameRect(r, colour, clicked ? FrameFlag::Lowered : FrameFlags{}); if ((type & WWT_MASK) == WWT_IMGBTN_2 && clicked) img++; // Show different image when clicked for #WWT_IMGBTN_2. DrawSpriteIgnorePadding(img, PAL_NONE, r, align); @@ -372,7 +363,7 @@ static inline void DrawImageButtons(const Rect &r, WidgetType type, Colours colo */ static inline void DrawImageTextButtons(const Rect &r, Colours colour, bool clicked, SpriteID img, TextColour text_colour, const std::string &text, StringAlignment align, FontSize fs) { - DrawFrameRect(r.left, r.top, r.right, r.bottom, colour, (clicked) ? FrameFlag::Lowered : FrameFlags{}); + DrawFrameRect(r, colour, clicked ? FrameFlag::Lowered : FrameFlags{}); bool rtl = _current_text_dir == TD_RTL; int image_width = img != 0 ? GetScaledSpriteSize(img).width : 0; @@ -435,7 +426,7 @@ static inline void DrawText(const Rect &r, TextColour colour, std::string_view s */ static inline void DrawInset(const Rect &r, Colours colour, TextColour text_colour, std::string_view str, StringAlignment align, FontSize fs) { - DrawFrameRect(r.left, r.top, r.right, r.bottom, colour, {FrameFlag::Lowered, FrameFlag::Darkened}); + DrawFrameRect(r, colour, {FrameFlag::Lowered, FrameFlag::Darkened}); if (!str.empty()) DrawString(r.Shrink(WidgetDimensions::scaled.inset), str, text_colour, align, false, fs); } @@ -451,7 +442,7 @@ static inline void DrawInset(const Rect &r, Colours colour, TextColour text_colo */ static inline void DrawMatrix(const Rect &r, Colours colour, bool clicked, uint32_t num_columns, uint32_t num_rows, uint resize_x, uint resize_y) { - DrawFrameRect(r.left, r.top, r.right, r.bottom, colour, (clicked) ? FrameFlag::Lowered : FrameFlags{}); + DrawFrameRect(r, colour, clicked ? FrameFlag::Lowered : FrameFlags{}); int column_width; // Width of a single column in the matrix. if (num_columns == 0) { @@ -519,8 +510,9 @@ static inline void DrawVerticalScrollbar(const Rect &r, Colours colour, bool up_ PixelColour c2 = GetColourGradient(colour, SHADE_LIGHTEST); /* draw "shaded" background */ - GfxFillRect(r.left, r.top + height, r.right, r.bottom - height, c2); - GfxFillRect(r.left, r.top + height, r.right, r.bottom - height, c1, FILLRECT_CHECKER); + Rect bg = r.Shrink(0, height); + GfxFillRect(bg, c2); + GfxFillRect(bg, c1, FILLRECT_CHECKER); /* track positions. These fractions are based on original 1x dimensions, but scale better. */ int left = r.left + r.Width() * 3 / 11; /* left track is positioned 3/11ths from the left */ @@ -529,13 +521,13 @@ static inline void DrawVerticalScrollbar(const Rect &r, Colours colour, bool up_ const uint8_t br = WidgetDimensions::scaled.bevel.right; /* draw shaded lines */ - GfxFillRect(left - bl, r.top + height, left - 1, r.bottom - height, c1); - GfxFillRect(left, r.top + height, left + br - 1, r.bottom - height, c2); - GfxFillRect(right - bl, r.top + height, right - 1, r.bottom - height, c1); - GfxFillRect(right, r.top + height, right + br - 1, r.bottom - height, c2); + GfxFillRect(bg.WithX(left - bl, left - 1), c1); + GfxFillRect(bg.WithX(left, left + br - 1), c2); + GfxFillRect(bg.WithX(right - bl, right - 1), c1); + GfxFillRect(bg.WithX(right, right + br - 1), c2); - Point pt = HandleScrollbarHittest(scrollbar, r.top, r.bottom, false); - DrawFrameRect(r.left, pt.x, r.right, pt.y, colour, bar_dragged ? FrameFlag::Lowered : FrameFlags{}); + auto [top, bottom] = HandleScrollbarHittest(scrollbar, r.top, r.bottom, false); + DrawFrameRect(r.left, top, r.right, bottom, colour, bar_dragged ? FrameFlag::Lowered : FrameFlags{}); } /** @@ -558,8 +550,9 @@ static inline void DrawHorizontalScrollbar(const Rect &r, Colours colour, bool l PixelColour c2 = GetColourGradient(colour, SHADE_LIGHTEST); /* draw "shaded" background */ - GfxFillRect(r.left + width, r.top, r.right - width, r.bottom, c2); - GfxFillRect(r.left + width, r.top, r.right - width, r.bottom, c1, FILLRECT_CHECKER); + Rect bg = r.Shrink(width, 0); + GfxFillRect(bg, c2); + GfxFillRect(bg, c1, FILLRECT_CHECKER); /* track positions. These fractions are based on original 1x dimensions, but scale better. */ int top = r.top + r.Height() * 3 / 11; /* top track is positioned 3/11ths from the top */ @@ -568,14 +561,14 @@ static inline void DrawHorizontalScrollbar(const Rect &r, Colours colour, bool l const uint8_t bb = WidgetDimensions::scaled.bevel.bottom; /* draw shaded lines */ - GfxFillRect(r.left + width, top - bt, r.right - width, top - 1, c1); - GfxFillRect(r.left + width, top, r.right - width, top + bb - 1, c2); - GfxFillRect(r.left + width, bottom - bt, r.right - width, bottom - 1, c1); - GfxFillRect(r.left + width, bottom, r.right - width, bottom + bb - 1, c2); + GfxFillRect(bg.WithY(top - bt, top - 1), c1); + GfxFillRect(bg.WithY(top, top + bb - 1), c2); + GfxFillRect(bg.WithY(bottom - bt, bottom - 1), c1); + GfxFillRect(bg.WithY(bottom, bottom + bb - 1), c2); /* draw actual scrollbar */ - Point pt = HandleScrollbarHittest(scrollbar, r.left, r.right, true); - DrawFrameRect(pt.x, r.top, pt.y, r.bottom, colour, bar_dragged ? FrameFlag::Lowered : FrameFlags{}); + auto [left, right] = HandleScrollbarHittest(scrollbar, r.left, r.right, true); + DrawFrameRect(left, r.top, right, r.bottom, colour, bar_dragged ? FrameFlag::Lowered : FrameFlags{}); } /** @@ -689,7 +682,7 @@ static inline void DrawDebugBox(const Rect &r, Colours colour, bool clicked) static inline void DrawResizeBox(const Rect &r, Colours colour, bool at_left, bool clicked, bool bevel) { if (bevel) { - DrawFrameRect(r.left, r.top, r.right, r.bottom, colour, (clicked) ? FrameFlag::Lowered : FrameFlags{}); + DrawFrameRect(r, colour, clicked ? FrameFlag::Lowered : FrameFlags{}); } else if (clicked) { GfxFillRect(r.Shrink(WidgetDimensions::scaled.bevel), GetColourGradient(colour, SHADE_LIGHTER)); } @@ -703,7 +696,7 @@ static inline void DrawResizeBox(const Rect &r, Colours colour, bool at_left, bo */ static inline void DrawCloseBox(const Rect &r, Colours colour) { - if (colour != COLOUR_WHITE) DrawFrameRect(r.left, r.top, r.right, r.bottom, colour, {}); + if (colour != COLOUR_WHITE) DrawFrameRect(r, colour, {}); Point offset; Dimension d = GetSpriteSize(SPR_CLOSEBOX, &offset); d.width -= offset.x; @@ -754,21 +747,17 @@ void DrawCaption(const Rect &r, Colours colour, Owner owner, TextColour text_col */ static inline void DrawButtonDropdown(const Rect &r, Colours colour, bool clicked_button, bool clicked_dropdown, std::string_view str, StringAlignment align) { - int dd_width = NWidgetLeaf::dropdown_dimension.width; + bool rtl = _current_text_dir == TD_RTL; - if (_current_text_dir == TD_LTR) { - DrawFrameRect(r.left, r.top, r.right - dd_width, r.bottom, colour, clicked_button ? FrameFlag::Lowered : FrameFlags{}); - DrawImageButtons(r.WithWidth(dd_width, true), WWT_DROPDOWN, colour, clicked_dropdown, SPR_ARROW_DOWN, SA_CENTER); - if (!str.empty()) { - DrawString(r.left + WidgetDimensions::scaled.dropdowntext.left, r.right - dd_width - WidgetDimensions::scaled.dropdowntext.right, CentreBounds(r.top, r.bottom, GetCharacterHeight(FS_NORMAL)), str, TC_BLACK, align); - } - } else { - DrawFrameRect(r.left + dd_width, r.top, r.right, r.bottom, colour, clicked_button ? FrameFlag::Lowered : FrameFlags{}); - DrawImageButtons(r.WithWidth(dd_width, false), WWT_DROPDOWN, colour, clicked_dropdown, SPR_ARROW_DOWN, SA_CENTER); - if (!str.empty()) { - DrawString(r.left + dd_width + WidgetDimensions::scaled.dropdowntext.left, r.right - WidgetDimensions::scaled.dropdowntext.right, CentreBounds(r.top, r.bottom, GetCharacterHeight(FS_NORMAL)), str, TC_BLACK, align); - } + Rect text = r.Indent(NWidgetLeaf::dropdown_dimension.width, !rtl); + DrawFrameRect(text, colour, clicked_button ? FrameFlag::Lowered : FrameFlags{}); + if (!str.empty()) { + text = text.CentreToHeight(GetCharacterHeight(FS_NORMAL)).Shrink(WidgetDimensions::scaled.dropdowntext, RectPadding::zero); + DrawString(text, str, TC_BLACK, align); } + + Rect button = r.WithWidth(NWidgetLeaf::dropdown_dimension.width, !rtl); + DrawImageButtons(button, WWT_DROPDOWN, colour, clicked_dropdown, SPR_ARROW_DOWN, SA_CENTER); } /** @@ -1898,7 +1887,7 @@ void NWidgetVertical::AssignSizePosition(SizingType sizing, int x, int y, uint g * @param width Horizontal size of the spacer widget. * @param height Vertical size of the spacer widget. */ -NWidgetSpacer::NWidgetSpacer(int width, int height) : NWidgetResizeBase(NWID_SPACER, -1, 0, 0) +NWidgetSpacer::NWidgetSpacer(int width, int height) : NWidgetResizeBase(NWID_SPACER, INVALID_WIDGET, 0, 0) { this->SetMinimalSize(width, height); this->SetResize(0, 0); @@ -2320,7 +2309,7 @@ void NWidgetBackground::Draw(const Window *w) switch (this->type) { case WWT_PANEL: - DrawFrameRect(r.left, r.top, r.right, r.bottom, this->colour, this->IsLowered() ? FrameFlag::Lowered : FrameFlags{}); + DrawFrameRect(r, this->colour, this->IsLowered() ? FrameFlag::Lowered : FrameFlags{}); break; case WWT_FRAME: @@ -2999,7 +2988,7 @@ void NWidgetLeaf::Draw(const Window *w) break; case WWT_PUSHBTN: - DrawFrameRect(r.left, r.top, r.right, r.bottom, this->colour, (clicked) ? FrameFlag::Lowered : FrameFlags{}); + DrawFrameRect(r, this->colour, clicked ? FrameFlag::Lowered : FrameFlags{}); break; case WWT_BOOLBTN: { @@ -3019,7 +3008,7 @@ void NWidgetLeaf::Draw(const Window *w) case WWT_TEXTBTN: case WWT_PUSHTXTBTN: case WWT_TEXTBTN_2: - DrawFrameRect(r.left, r.top, r.right, r.bottom, this->colour, (clicked) ? FrameFlag::Lowered : FrameFlags{}); + DrawFrameRect(r, this->colour, clicked ? FrameFlag::Lowered : FrameFlags{}); DrawLabel(r, this->text_colour, GetStringForWidget(w, this, (type & WWT_MASK) == WWT_TEXTBTN_2 && clicked), this->align, this->text_size); break; @@ -3421,7 +3410,7 @@ std::unique_ptr MakeWindowNWidgetTree(std::span if (hor_cont != nullptr && hor_cont->GetWidgetOfType(WWT_CAPTION) != nullptr && hor_cont->GetWidgetOfType(WWT_SHADEBOX) != nullptr) { /* If the first widget has a title bar and a shade box, silently add a shade selection widget in the tree. */ - auto shade_stack = std::make_unique(-1); + auto shade_stack = std::make_unique(INVALID_WIDGET); *shade_select = shade_stack.get(); /* Load the remaining parts into the shade stack. */ shade_stack->Add(MakeNWidgets({nwid_begin, nwid_end}, std::make_unique())); diff --git a/src/widget_type.h b/src/widget_type.h index 063c6b4d6dfac..072d56365e85c 100644 --- a/src/widget_type.h +++ b/src/widget_type.h @@ -136,7 +136,7 @@ using WidgetLookup = std::map; */ class NWidgetBase { public: - NWidgetBase(WidgetType tp, WidgetID index = -1) : type(tp), index(index) {} + NWidgetBase(WidgetType tp, WidgetID index = INVALID_WIDGET) : type(tp), index(index) {} virtual ~NWidgetBase() = default; void ApplyAspectRatio(); @@ -249,7 +249,7 @@ class NWidgetBase { NWidgetBase *parent = nullptr; ///< Parent widget of this widget, automatically filled in when added to container. protected: - const WidgetID index = -1; ///< Index of the nested widget (\c -1 means 'not used'). + const WidgetID index = INVALID_WIDGET; ///< Index of the nested widget (\c INVALID_WIDGET means 'not used'). inline void StoreSizePosition(SizingType sizing, int x, int y, uint given_width, uint given_height); }; @@ -402,7 +402,7 @@ class NWidgetCore : public NWidgetResizeBase { protected: WidgetData widget_data{}; ///< Data of the widget. @see Widget::data StringID tool_tip{}; ///< Tooltip of the widget. @see Widget::tool_tips - WidgetID scrollbar_index = -1; ///< Index of an attached scrollbar. + WidgetID scrollbar_index = INVALID_WIDGET; ///< Index of an attached scrollbar. TextColour highlight_colour{}; ///< Colour of highlight. TextColour text_colour{}; ///< Colour of text within widget. FontSize text_size = FS_NORMAL; ///< Size of text within widget. @@ -471,7 +471,7 @@ inline bool NWidgetCore::IsDisabled() const */ class NWidgetContainer : public NWidgetBase { public: - NWidgetContainer(WidgetType tp, WidgetID index = -1) : NWidgetBase(tp, index) {} + NWidgetContainer(WidgetType tp, WidgetID index = INVALID_WIDGET) : NWidgetBase(tp, index) {} void AdjustPaddingForZoom() override; void Add(std::unique_ptr &&wid); @@ -537,7 +537,7 @@ using NWidContainerFlags = EnumBitSet; /** Container with pre/inter/post child space. */ class NWidgetPIPContainer : public NWidgetContainer { public: - NWidgetPIPContainer(WidgetType tp, NWidContainerFlags flags = {}, WidgetID index = -1) : NWidgetContainer(tp, index), flags(flags) {} + NWidgetPIPContainer(WidgetType tp, NWidContainerFlags flags = {}, WidgetID index = INVALID_WIDGET) : NWidgetContainer(tp, index), flags(flags) {} void AdjustPaddingForZoom() override; void SetPIP(uint8_t pip_pre, uint8_t pip_inter, uint8_t pip_post); @@ -565,7 +565,7 @@ class NWidgetPIPContainer : public NWidgetContainer { */ class NWidgetHorizontal : public NWidgetPIPContainer { public: - NWidgetHorizontal(NWidContainerFlags flags = {}, WidgetID index = -1, WidgetType type = NWID_HORIZONTAL) : NWidgetPIPContainer(type, flags, index) {} + NWidgetHorizontal(NWidContainerFlags flags = {}, WidgetID index = INVALID_WIDGET, WidgetType type = NWID_HORIZONTAL) : NWidgetPIPContainer(type, flags, index) {} void SetupSmallestSize(Window *w) override; void AssignSizePosition(SizingType sizing, int x, int y, uint given_width, uint given_height, bool rtl) override; @@ -577,7 +577,7 @@ class NWidgetHorizontal : public NWidgetPIPContainer { */ class NWidgetHorizontalLTR : public NWidgetHorizontal { public: - NWidgetHorizontalLTR(NWidContainerFlags flags = {}, WidgetID index = -1) : NWidgetHorizontal(flags, index, NWID_HORIZONTAL_LTR) {} + NWidgetHorizontalLTR(NWidContainerFlags flags = {}, WidgetID index = INVALID_WIDGET) : NWidgetHorizontal(flags, index, NWID_HORIZONTAL_LTR) {} void AssignSizePosition(SizingType sizing, int x, int y, uint given_width, uint given_height, bool rtl) override; }; @@ -588,7 +588,7 @@ class NWidgetHorizontalLTR : public NWidgetHorizontal { */ class NWidgetVertical : public NWidgetPIPContainer { public: - NWidgetVertical(NWidContainerFlags flags = {}, WidgetID index = -1) : NWidgetPIPContainer(NWID_VERTICAL, flags, index) {} + NWidgetVertical(NWidContainerFlags flags = {}, WidgetID index = INVALID_WIDGET) : NWidgetPIPContainer(NWID_VERTICAL, flags, index) {} void SetupSmallestSize(Window *w) override; void AssignSizePosition(SizingType sizing, int x, int y, uint given_width, uint given_height, bool rtl) override; @@ -1412,7 +1412,7 @@ constexpr NWidgetPart SetAspect(float ratio, AspectFlags flags = AspectFlag::Res * Child widgets must have a index bigger than the parent index. * @ingroup NestedWidgetParts */ -constexpr NWidgetPart NWidget(WidgetType tp, Colours col, WidgetID idx = -1) +constexpr NWidgetPart NWidget(WidgetType tp, Colours col, WidgetID idx = INVALID_WIDGET) { return NWidgetPart{tp, NWidgetPartWidget{col, idx}}; } @@ -1423,7 +1423,7 @@ constexpr NWidgetPart NWidget(WidgetType tp, Colours col, WidgetID idx = -1) * @param cont_flags Flags for the containers (#NWID_HORIZONTAL and #NWID_VERTICAL). * @ingroup NestedWidgetParts */ -constexpr NWidgetPart NWidget(WidgetType tp, NWidContainerFlags cont_flags = {}, WidgetID idx = -1) +constexpr NWidgetPart NWidget(WidgetType tp, NWidContainerFlags cont_flags = {}, WidgetID idx = INVALID_WIDGET) { return NWidgetPart{tp, NWidgetPartContainer{cont_flags, idx}}; } diff --git a/src/widgets/airport_widget.h b/src/widgets/airport_widget.h index 4e16f4596ea9d..af2261b149eb9 100644 --- a/src/widgets/airport_widget.h +++ b/src/widgets/airport_widget.h @@ -14,8 +14,6 @@ enum AirportToolbarWidgets : WidgetID { WID_AT_AIRPORT, ///< Build airport button. WID_AT_DEMOLISH, ///< Demolish button. - - INVALID_WID_AT = -1, }; /** Widgets of the #BuildAirportWindow class. */ diff --git a/src/widgets/dock_widget.h b/src/widgets/dock_widget.h index 0a1f480eb6187..2877b1ac02a19 100644 --- a/src/widgets/dock_widget.h +++ b/src/widgets/dock_widget.h @@ -17,6 +17,15 @@ enum BuildDockDepotWidgets : WidgetID { WID_BDD_Y, ///< Y-direction button. }; +/** Widgets of the #BuildDocksStationWindow window. */ +enum BuildDocksStationWidgets : WidgetID { + WID_BDSW_BACKGROUND, ///< Background panel. + WID_BDSW_LT_OFF, ///< 'Off' button of coverage high light. + WID_BDSW_LT_ON, ///< 'On' button of coverage high light. + WID_BDSW_INFO, ///< 'Coverage highlight' label. + WID_BDSW_ACCEPTANCE, ///< Acceptance info. +}; + /** Widgets of the #BuildDocksToolbarWindow class. */ enum DockToolbarWidgets : WidgetID { WID_DT_CANAL, ///< Build canal button. @@ -27,8 +36,6 @@ enum DockToolbarWidgets : WidgetID { WID_DT_BUOY, ///< Build buoy button. WID_DT_RIVER, ///< Build river button (in scenario editor). WID_DT_BUILD_AQUEDUCT, ///< Build aqueduct button. - - WID_DT_INVALID, ///< Used to initialize a variable. }; #endif /* WIDGETS_DOCK_WIDGET_H */ diff --git a/src/widgets/game_widget.h b/src/widgets/game_widget.h index 5b105d9934c37..4ad5973fa6db2 100644 --- a/src/widgets/game_widget.h +++ b/src/widgets/game_widget.h @@ -24,7 +24,7 @@ enum GSConfigWidgets : WidgetID { WID_GSC_CONTENT_DOWNLOAD = WID_GSC_TEXTFILE + TFT_CONTENT_END, ///< Download content button. WID_GSC_RESET, ///< Reset button. - WID_GSC_SETTING_DROPDOWN = -1, ///< Dynamically created dropdown for changing setting value. + WID_GSC_SETTING_DROPDOWN = INVALID_WIDGET, ///< Dynamically created dropdown for changing setting value. }; #endif /* WIDGETS_GS_WIDGET_H */ diff --git a/src/widgets/genworld_widget.h b/src/widgets/genworld_widget.h index 8d852a117be6c..e57e4efd085ab 100644 --- a/src/widgets/genworld_widget.h +++ b/src/widgets/genworld_widget.h @@ -54,7 +54,7 @@ enum GenerateLandscapeWidgets : WidgetID { WID_GL_SMOOTHNESS_PULLDOWN, ///< Dropdown 'Smoothness'. WID_GL_VARIETY_PULLDOWN, ///< Dropdown 'Variety distribution'. - WID_GL_BORDERS_RANDOM, ///< 'Random'/'Manual' borders. + WID_GL_BORDERS_PULLDOWN, ///< Dropdown 'Map edges'. WID_GL_WATER_NW, ///< NW 'Water'/'Freeform'. WID_GL_WATER_NE, ///< NE 'Water'/'Freeform'. WID_GL_WATER_SE, ///< SE 'Water'/'Freeform'. diff --git a/src/widgets/rail_widget.h b/src/widgets/rail_widget.h index f290d801622e3..02da916e7265e 100644 --- a/src/widgets/rail_widget.h +++ b/src/widgets/rail_widget.h @@ -28,8 +28,6 @@ enum RailToolbarWidgets : WidgetID { WID_RAT_BUILD_TUNNEL, ///< Build a tunnel. WID_RAT_REMOVE, ///< Bulldozer to remove rail. WID_RAT_CONVERT_RAIL, ///< Convert other rail to this type. - - INVALID_WID_RAT = -1, }; /** Widgets of the #BuildRailStationWindow class. */ diff --git a/src/widgets/road_widget.h b/src/widgets/road_widget.h index 679545728a2e8..23de63ed533d4 100644 --- a/src/widgets/road_widget.h +++ b/src/widgets/road_widget.h @@ -27,8 +27,6 @@ enum RoadToolbarWidgets : WidgetID { WID_ROT_BUILD_TUNNEL, ///< Build tunnel. WID_ROT_REMOVE, ///< Remove road. WID_ROT_CONVERT_ROAD, ///< Convert road. - - INVALID_WID_ROT = -1, }; /** Widgets of the #BuildRoadDepotWindow class. */ diff --git a/src/widgets/script_widget.h b/src/widgets/script_widget.h index 7b9905dcc98fe..71fecc5badb98 100644 --- a/src/widgets/script_widget.h +++ b/src/widgets/script_widget.h @@ -28,7 +28,7 @@ enum ScriptSettingsWidgets : WidgetID { WID_SCRS_SCROLLBAR, ///< Scrollbar to scroll through all settings. WID_SCRS_RESET, ///< Reset button. - WID_SCRS_SETTING_DROPDOWN = -1, ///< Dynamically created dropdown for changing setting value. + WID_SCRS_SETTING_DROPDOWN = INVALID_WIDGET, ///< Dynamically created dropdown for changing setting value. }; /** Widgets of the #ScriptDebugWindow class. */ diff --git a/src/widgets/settings_widget.h b/src/widgets/settings_widget.h index 858f17f104c34..d7a3c069d87ee 100644 --- a/src/widgets/settings_widget.h +++ b/src/widgets/settings_widget.h @@ -85,7 +85,7 @@ enum GameOptionsWidgets : WidgetID { WID_GO_RESTRICT_DROPDOWN, ///< The drop down box to restrict the list of settings WID_GO_TYPE_DROPDOWN, ///< The drop down box to choose client/game/company/all settings - WID_GO_SETTING_DROPDOWN = -1, ///< Dynamically created dropdown for changing setting value. + WID_GO_SETTING_DROPDOWN = INVALID_WIDGET, ///< Dynamically created dropdown for changing setting value. }; /** Widgets of the #CustomCurrencyWindow class. */ diff --git a/src/widgets/terraform_widget.h b/src/widgets/terraform_widget.h index 6b5796f9b5490..d4ce57eabd292 100644 --- a/src/widgets/terraform_widget.h +++ b/src/widgets/terraform_widget.h @@ -22,8 +22,6 @@ enum TerraformToolbarWidgets : WidgetID { WID_TT_PLANT_TREES, ///< Plant trees button (note: opens separate window, no place-push-button). WID_TT_PLACE_SIGN, ///< Place sign button. WID_TT_PLACE_OBJECT, ///< Place object button. - - INVALID_WID_TT = -1, }; /** Widgets of the #ScenarioEditorLandscapeGenerationWindow class. */ @@ -44,8 +42,6 @@ enum EditorTerraformToolbarWidgets : WidgetID { WID_ETT_DECREASE_SIZE, ///< Downwards arrow button to decrease terraforming size. WID_ETT_NEW_SCENARIO, ///< Button for generating a new scenario. WID_ETT_RESET_LANDSCAPE, ///< Button for removing all company-owned property. - - INVALID_WID_ETT = -1, }; #endif /* WIDGETS_TERRAFORM_WIDGET_H */ diff --git a/src/window.cpp b/src/window.cpp index 50422b89de84a..4422cd86ed6b4 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -594,6 +594,9 @@ EventState Window::OnHotkey(int hotkey) */ void Window::HandleButtonClick(WidgetID widget) { + /* Button click for this widget may already have been handled. */ + if (this->IsWidgetLowered(widget) && this->timeout_timer == TIMEOUT_DURATION) return; + this->LowerWidget(widget); this->SetTimeout(); this->SetWidgetDirty(widget); @@ -1674,7 +1677,7 @@ static Point GetAutoPlacePosition(int width, int height) /** * Computer the position of the top-left corner of a window to be opened right * under the toolbar. - * @param window_width the width of the window to get the position for + * @param window_width the width of the window to get the position for. * @return Coordinate of the top-left corner of the new window. */ Point GetToolbarAlignedWindowPosition(int window_width) @@ -1685,6 +1688,24 @@ Point GetToolbarAlignedWindowPosition(int window_width) return pt; } +/** + * Compute the position of the construction toolbars. + * + * If the terraform toolbar is open place them to the right/left of it, + * otherwise use default toolbar aligned position. + * @param window_width the width of the toolbar to get the position for. + * @return Coordinate of the top-left corner of the new toolbar. + */ +Point AlignInitialConstructionToolbar(int window_width) +{ + Point pt = GetToolbarAlignedWindowPosition(window_width); + const Window *w = FindWindowByClass(WC_SCEN_LAND_GEN); + if (w != nullptr && w->top == pt.y && !_settings_client.gui.link_terraform_toolbar) { + pt.x = w->left + (_current_text_dir == TD_RTL ? w->width : - window_width); + } + return pt; +} + /** * Compute the position of the top-left corner of a new window that is opened. * @@ -1806,7 +1827,7 @@ void Window::InitNested(WindowNumber window_number) * Empty constructor, initialization has been moved to #InitNested() called from the constructor of the derived class. * @param desc The description of the window. */ -Window::Window(WindowDesc &desc) : window_desc(desc), scale(_gui_scale), mouse_capture_widget(-1) +Window::Window(WindowDesc &desc) : window_desc(desc), scale(_gui_scale), mouse_capture_widget(INVALID_WIDGET) { this->z_position = _z_windows.insert(_z_windows.end(), this); } @@ -1888,7 +1909,7 @@ static void DecreaseWindowCounters() NWidgetScrollbar *sb = static_cast(nwid); if (sb->disp_flags.Any({NWidgetDisplayFlag::ScrollbarUp, NWidgetDisplayFlag::ScrollbarDown})) { sb->disp_flags.Reset({NWidgetDisplayFlag::ScrollbarUp, NWidgetDisplayFlag::ScrollbarDown}); - w->mouse_capture_widget = -1; + w->mouse_capture_widget = INVALID_WIDGET; sb->SetDirty(w); } } @@ -2387,7 +2408,7 @@ static EventState HandleActiveWidget() /* Abort if no button is clicked any more. */ if (!_left_button_down) { w->SetWidgetDirty(w->mouse_capture_widget); - w->mouse_capture_widget = -1; + w->mouse_capture_widget = INVALID_WIDGET; return ES_HANDLED; } diff --git a/src/window_gui.h b/src/window_gui.h index edfbf94da8f37..bf09cd198512b 100644 --- a/src/window_gui.h +++ b/src/window_gui.h @@ -158,6 +158,7 @@ enum class WindowDefaultFlag : uint8_t { using WindowDefaultFlags = EnumBitSet; Point GetToolbarAlignedWindowPosition(int window_width); +Point AlignInitialConstructionToolbar(int window_width); struct HotkeyList; @@ -323,7 +324,7 @@ struct Window { NWidgetStacked *shade_select = nullptr; ///< Selection widget (#NWID_SELECTION) to use for shading the window. If \c nullptr, window cannot shade. Dimension unshaded_size{}; ///< Last known unshaded size (only valid while shaded). - WidgetID mouse_capture_widget = -1; ///< ID of current mouse capture widget (e.g. dragged scrollbar). -1 if no widget has mouse capture. + WidgetID mouse_capture_widget = INVALID_WIDGET; ///< ID of current mouse capture widget (e.g. dragged scrollbar). \c INVALID_WIDGET if no widget has mouse capture. Window *parent = nullptr; ///< Parent window. WindowList::iterator z_position{}; diff --git a/src/window_type.h b/src/window_type.h index 585ad7a83f676..880738be1dc51 100644 --- a/src/window_type.h +++ b/src/window_type.h @@ -19,6 +19,9 @@ */ using WidgetID = int; +/** An invalid widget index. */ +static constexpr WidgetID INVALID_WIDGET = -1; + /** %Window numbers. */ enum WindowNumberEnum : uint8_t { WN_GAME_OPTIONS_AI = 0, ///< AI settings. diff --git a/src/zoom_type.h b/src/zoom_type.h index 06fb780aab962..272d2fab9541d 100644 --- a/src/zoom_type.h +++ b/src/zoom_type.h @@ -12,8 +12,12 @@ #include "core/enum_type.hpp" -/** All zoom levels we know. */ -enum class ZoomLevel : uint8_t { +/** + * All zoom levels we know. + * + * The underlying type is signed so subtract-and-Clamp works without need for casting. + */ +enum class ZoomLevel : int8_t { /* Our possible zoom-levels */ Begin = 0, ///< Begin for iteration. Min = Begin, ///< Minimum zoom level.