diff --git a/media/baseset/openttd.grf b/media/baseset/openttd.grf index e3ebf2dd67..9e08fb17c3 100644 Binary files a/media/baseset/openttd.grf and b/media/baseset/openttd.grf differ diff --git a/media/baseset/openttd/oneway.nfo b/media/baseset/openttd/oneway.nfo index 46f3b8f947..56d2e2809a 100644 --- a/media/baseset/openttd/oneway.nfo +++ b/media/baseset/openttd/oneway.nfo @@ -4,10 +4,24 @@ // 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 "One way road graphics" - -1 * 3 05 09 06 - -1 sprites/oneway.png 8bpp 34 8 24 16 -12 -8 normal - -1 sprites/oneway.png 8bpp 66 8 24 16 -12 -8 normal - -1 sprites/oneway.png 8bpp 98 8 24 16 -12 -8 normal - -1 sprites/oneway.png 8bpp 130 8 24 16 -12 -8 normal - -1 sprites/oneway.png 8bpp 162 8 24 16 -12 -8 normal - -1 sprites/oneway.png 8bpp 194 8 24 16 -12 -8 normal + -1 * 3 05 09 12 + -1 sprites/oneway.png 8bpp 34 8 24 16 -10 -9 normal + -1 sprites/oneway.png 8bpp 66 8 24 16 -13 -7 normal + -1 sprites/oneway.png 8bpp 98 8 24 16 -12 -8 normal + -1 sprites/oneway.png 8bpp 130 8 24 16 -15 -10 normal + -1 sprites/oneway.png 8bpp 162 8 24 16 -12 -9 normal + -1 sprites/oneway.png 8bpp 194 8 24 16 -11 -8 normal + + -1 sprites/oneway.png 8bpp 34 40 24 16 -13 -10 normal + -1 sprites/oneway.png 8bpp 66 40 24 16 -12 -8 normal + -1 sprites/oneway.png 8bpp 98 40 24 16 -12 -9 normal + -1 sprites/oneway.png 8bpp 130 40 24 16 -11 -8 normal + -1 sprites/oneway.png 8bpp 162 40 24 16 -9 -10 normal + -1 sprites/oneway.png 8bpp 194 40 24 16 -10 -9 normal + + -1 sprites/oneway.png 8bpp 34 72 24 16 -8 -11 normal + -1 sprites/oneway.png 8bpp 66 72 24 16 -11 -5 normal + -1 sprites/oneway.png 8bpp 98 72 24 16 -12 -8 normal + -1 sprites/oneway.png 8bpp 130 72 24 16 -12 -5 normal + -1 sprites/oneway.png 8bpp 162 72 24 16 -14 -10 normal + -1 sprites/oneway.png 8bpp 194 72 24 16 -12 -8 normal diff --git a/media/baseset/openttd/oneway.png b/media/baseset/openttd/oneway.png index 15542af856..843747677f 100644 Binary files a/media/baseset/openttd/oneway.png and b/media/baseset/openttd/oneway.png differ diff --git a/media/baseset/orig_extra.grf b/media/baseset/orig_extra.grf index 728a8b2555..881c4631ce 100644 Binary files a/media/baseset/orig_extra.grf and b/media/baseset/orig_extra.grf differ diff --git a/media/baseset/orig_extra/fix_gui_icons.nfo b/media/baseset/orig_extra/fix_gui_icons.nfo new file mode 100644 index 0000000000..2fdb8880bd --- /dev/null +++ b/media/baseset/orig_extra/fix_gui_icons.nfo @@ -0,0 +1,12 @@ +// 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 "Fix alignment of button icons." + +// Fix alignment of button icons. + -1 * 11 0A 03 01 DC 02 01 E2 02 01 E6 02 + -1 sprites/fix_gui_icons.png 8bpp 8 13 20 20 0 0 normal nocrop + -1 sprites/fix_gui_icons.png 8bpp 40 13 20 20 0 0 normal nocrop + -1 sprites/fix_gui_icons.png 8bpp 72 13 20 20 0 0 normal nocrop diff --git a/media/baseset/orig_extra/fix_gui_icons.png b/media/baseset/orig_extra/fix_gui_icons.png new file mode 100644 index 0000000000..0630179616 Binary files /dev/null and b/media/baseset/orig_extra/fix_gui_icons.png differ diff --git a/media/baseset/orig_extra/orig_extra.nfo b/media/baseset/orig_extra/orig_extra.nfo index 903d96a572..e6ecca8a00 100644 --- a/media/baseset/orig_extra/orig_extra.nfo +++ b/media/baseset/orig_extra/orig_extra.nfo @@ -83,3 +83,4 @@ #include "rivers/arctic.nfo" #include "rivers/tropic.nfo" #include "rivers/toyland.nfo" +#include "fix_gui_icons.nfo" diff --git a/src/autoreplace_gui.cpp b/src/autoreplace_gui.cpp index 221580220c..90a7c71dc8 100644 --- a/src/autoreplace_gui.cpp +++ b/src/autoreplace_gui.cpp @@ -30,11 +30,11 @@ #include "safeguards.h" -void DrawEngineList(VehicleType type, const Rect &r, const GUIEngineList *eng_list, uint16 min, uint16 max, EngineID selected_id, bool show_count, GroupID selected_group); +void DrawEngineList(VehicleType type, const Rect &r, const GUIEngineList &eng_list, uint16 min, uint16 max, EngineID selected_id, bool show_count, GroupID selected_group); -static bool EngineNumberSorter(const EngineID &a, const EngineID &b) +static bool EngineNumberSorter(const GUIEngineListItem &a, const GUIEngineListItem &b) { - return Engine::Get(a)->list_position < Engine::Get(b)->list_position; + return Engine::Get(a.engine_id)->list_position < Engine::Get(b.engine_id)->list_position; } /** @@ -111,6 +111,26 @@ class ReplaceVehicleWindow : public Window { return true; } + void AddChildren(const GUIEngineList &source, GUIEngineList &target, EngineID parent, int indent, int side) + { + for (const auto &item : source) { + if (item.variant_id != parent || item.engine_id == parent) continue; + + const Engine *e = Engine::Get(item.engine_id); + EngineDisplayFlags flags = item.flags; + if (e->display_last_variant != INVALID_ENGINE) flags &= ~EngineDisplayFlags::Shaded; + target.emplace_back(e->display_last_variant == INVALID_ENGINE ? item.engine_id : e->display_last_variant, item.engine_id, flags, indent); + + /* Add variants if not folded */ + if ((item.flags & (EngineDisplayFlags::HasVariants | EngineDisplayFlags::IsFolded)) == EngineDisplayFlags::HasVariants) { + /* Add this engine again as a child */ + if ((item.flags & EngineDisplayFlags::Shaded) == EngineDisplayFlags::None) { + target.emplace_back(item.engine_id, item.engine_id, EngineDisplayFlags::None, indent + 1); + } + AddChildren(source, target, item.engine_id, indent + 1, side); + } + } + } /** * Generate an engines list @@ -118,12 +138,12 @@ class ReplaceVehicleWindow : public Window { */ void GenerateReplaceVehList(bool draw_left) { + std::vector variants; EngineID selected_engine = INVALID_ENGINE; VehicleType type = (VehicleType)this->window_number; byte side = draw_left ? 0 : 1; - GUIEngineList *list = &this->engines[side]; - list->clear(); + GUIEngineList list; for (const Engine *e : Engine::IterateType(type)) { if (!draw_left && !this->show_hidden_engines && e->IsHidden(_local_company)) continue; @@ -153,15 +173,37 @@ class ReplaceVehicleWindow : public Window { if (!CheckAutoreplaceValidity(this->sel_engine[0], eid, _local_company)) continue; } - list->push_back(eid); + EngineDisplayFlags flags = (side == 0) ? EngineDisplayFlags::None : e->display_flags; + if (side == 1 && eid == this->sel_engine[0]) flags |= EngineDisplayFlags::Shaded; + list.emplace_back(eid, e->info.variant_id, flags, 0); + + if (side == 1 && e->info.variant_id != INVALID_ENGINE) variants.push_back(e->info.variant_id); if (eid == this->sel_engine[side]) selected_engine = eid; // The selected engine is still in the list } + + if (side == 1) { + /* ensure primary engine of variant group is in list */ + for (const auto &variant : variants) { + if (std::find(list.begin(), list.end(), variant) == list.end()) { + const Engine *e = Engine::Get(variant); + list.emplace_back(variant, e->info.variant_id, e->display_flags | EngineDisplayFlags::Shaded, 0); + } + } + } + this->sel_engine[side] = selected_engine; // update which engine we selected (the same or none, if it's not in the list anymore) if (draw_left) { - EngList_Sort(list, &EngineNumberSorter); + EngList_Sort(&list, &EngineNumberSorter); } else { _engine_sort_direction = this->descending_sort_order; - EngList_Sort(list, _engine_sort_functions[this->window_number][this->sort_criteria]); + EngList_Sort(&list, _engine_sort_functions[this->window_number][this->sort_criteria]); + } + + this->engines[side].clear(); + if (side == 1) { + AddChildren(list, this->engines[side], INVALID_ENGINE, 0, side); + } else { + this->engines[side].swap(list); } } @@ -175,7 +217,7 @@ class ReplaceVehicleWindow : public Window { this->GenerateReplaceVehList(true); this->vscroll[0]->SetCount((uint)this->engines[0].size()); if (this->reset_sel_engine && this->sel_engine[0] == INVALID_ENGINE && this->engines[0].size() != 0) { - this->sel_engine[0] = this->engines[0][0]; + this->sel_engine[0] = this->engines[0][0].engine_id; } } @@ -196,8 +238,8 @@ class ReplaceVehicleWindow : public Window { this->vscroll[1]->SetCount((uint)this->engines[1].size()); if (this->reset_sel_engine && this->sel_engine[1] != INVALID_ENGINE) { int position = 0; - for (EngineID &eid : this->engines[1]) { - if (eid == this->sel_engine[1]) break; + for (const auto &item : this->engines[1]) { + if (item.engine_id == this->sel_engine[1]) break; ++position; } this->vscroll[1]->ScrollTowards(position); @@ -431,7 +473,7 @@ public: EngineID end = static_cast(std::min(this->vscroll[side]->GetCapacity() + start, this->engines[side].size())); /* Do the actual drawing */ - DrawEngineList((VehicleType)this->window_number, r, &this->engines[side], start, end, this->sel_engine[side], side == 0, this->sel_group); + DrawEngineList((VehicleType)this->window_number, r, this->engines[side], start, end, this->sel_engine[side], side == 0, this->sel_group); break; } } @@ -576,7 +618,22 @@ public: uint i = this->vscroll[click_side]->GetScrolledRowFromWidget(pt.y, this, widget); size_t engine_count = this->engines[click_side].size(); - EngineID e = engine_count > i ? this->engines[click_side][i] : INVALID_ENGINE; + EngineID e = INVALID_ENGINE; + if (i < engine_count) { + const auto &item = this->engines[click_side][i]; + const Rect r = this->GetWidget(widget)->GetCurrentRect().Shrink(WidgetDimensions::scaled.matrix).WithWidth(WidgetDimensions::scaled.hsep_indent * (item.indent + 1), _current_text_dir == TD_RTL); + if ((item.flags & EngineDisplayFlags::HasVariants) != EngineDisplayFlags::None && IsInsideMM(r.left, r.right, pt.x)) { + /* toggle folded flag on engine */ + assert(item.variant_id != INVALID_ENGINE); + Engine *engine = Engine::Get(item.variant_id); + engine->display_flags ^= EngineDisplayFlags::IsFolded; + + InvalidateWindowData(WC_REPLACE_VEHICLE, (VehicleType)this->window_number, 0); // Update the autoreplace window + InvalidateWindowClassesData(WC_BUILD_VEHICLE); // The build windows needs updating as well + return; + } + if ((item.flags & EngineDisplayFlags::Shaded) == EngineDisplayFlags::None) e = item.engine_id; + } /* If Ctrl is pressed on the left side and we don't have any engines of the selected type, stop autoreplacing. * This is most common when we have finished autoreplacing the engine and want to remove it from the list. */ diff --git a/src/build_vehicle_gui.cpp b/src/build_vehicle_gui.cpp index efb0d71260..1b2465c11c 100644 --- a/src/build_vehicle_gui.cpp +++ b/src/build_vehicle_gui.cpp @@ -216,9 +216,9 @@ static CargoID _last_filter_criteria_wagon = CF_ANY; * @param b second engine to compare * @return for descending order: returns true if a < b. Vice versa for ascending order */ -static bool EngineNumberSorter(const EngineID &a, const EngineID &b) +static bool EngineNumberSorter(const GUIEngineListItem &a, const GUIEngineListItem &b) { - int r = Engine::Get(a)->list_position - Engine::Get(b)->list_position; + int r = Engine::Get(a.engine_id)->list_position - Engine::Get(b.engine_id)->list_position; return _engine_sort_direction ? r > 0 : r < 0; } @@ -229,10 +229,10 @@ static bool EngineNumberSorter(const EngineID &a, const EngineID &b) * @param b second engine to compare * @return for descending order: returns true if a < b. Vice versa for ascending order */ -static bool EngineIntroDateSorter(const EngineID &a, const EngineID &b) +static bool EngineIntroDateSorter(const GUIEngineListItem &a, const GUIEngineListItem &b) { - const int va = Engine::Get(a)->intro_date; - const int vb = Engine::Get(b)->intro_date; + const int va = Engine::Get(a.engine_id)->intro_date; + const int vb = Engine::Get(b.engine_id)->intro_date; const int r = va - vb; /* Use EngineID to sort instead since we want consistent sorting */ @@ -246,10 +246,10 @@ static bool EngineIntroDateSorter(const EngineID &a, const EngineID &b) * @param b second engine to compare * @return for descending order: returns true if a < b. Vice versa for ascending order */ -static bool EngineVehicleCountSorter(const EngineID &a, const EngineID &b) +static bool EngineVehicleCountSorter(const GUIEngineListItem &a, const GUIEngineListItem &b) { - const GroupStatistics &stats = GroupStatistics::Get(_local_company, ALL_GROUP, Engine::Get(a)->type); - const int r = ((int) stats.num_engines[a]) - ((int) stats.num_engines[b]); + const GroupStatistics &stats = GroupStatistics::Get(_local_company, ALL_GROUP, Engine::Get(a.engine_id)->type); + const int r = ((int) stats.num_engines[a.engine_id]) - ((int) stats.num_engines[b.engine_id]); /* Use EngineID to sort instead since we want consistent sorting */ if (r == 0) return EngineNumberSorter(a, b); @@ -265,19 +265,19 @@ static EngineID _last_engine[2] = { INVALID_ENGINE, INVALID_ENGINE }; * @param b second engine to compare * @return for descending order: returns true if a < b. Vice versa for ascending order */ -static bool EngineNameSorter(const EngineID &a, const EngineID &b) +static bool EngineNameSorter(const GUIEngineListItem &a, const GUIEngineListItem &b) { static char last_name[2][64] = { "", "" }; - if (a != _last_engine[0]) { - _last_engine[0] = a; - SetDParam(0, a); + if (a.engine_id != _last_engine[0]) { + _last_engine[0] = a.engine_id; + SetDParam(0, a.engine_id); GetString(last_name[0], STR_ENGINE_NAME, lastof(last_name[0])); } - if (b != _last_engine[1]) { - _last_engine[1] = b; - SetDParam(0, b); + if (b.engine_id != _last_engine[1]) { + _last_engine[1] = b.engine_id; + SetDParam(0, b.engine_id); GetString(last_name[1], STR_ENGINE_NAME, lastof(last_name[1])); } @@ -294,10 +294,10 @@ static bool EngineNameSorter(const EngineID &a, const EngineID &b) * @param b second engine to compare * @return for descending order: returns true if a < b. Vice versa for ascending order */ -static bool EngineReliabilitySorter(const EngineID &a, const EngineID &b) +static bool EngineReliabilitySorter(const GUIEngineListItem &a, const GUIEngineListItem &b) { - const int va = Engine::Get(a)->reliability; - const int vb = Engine::Get(b)->reliability; + const int va = Engine::Get(a.engine_id)->reliability; + const int vb = Engine::Get(b.engine_id)->reliability; const int r = va - vb; /* Use EngineID to sort instead since we want consistent sorting */ @@ -311,10 +311,10 @@ static bool EngineReliabilitySorter(const EngineID &a, const EngineID &b) * @param b second engine to compare * @return for descending order: returns true if a < b. Vice versa for ascending order */ -static bool EngineCostSorter(const EngineID &a, const EngineID &b) +static bool EngineCostSorter(const GUIEngineListItem &a, const GUIEngineListItem &b) { - Money va = Engine::Get(a)->GetCost(); - Money vb = Engine::Get(b)->GetCost(); + Money va = Engine::Get(a.engine_id)->GetCost(); + Money vb = Engine::Get(b.engine_id)->GetCost(); int r = ClampToI32(va - vb); /* Use EngineID to sort instead since we want consistent sorting */ @@ -328,10 +328,10 @@ static bool EngineCostSorter(const EngineID &a, const EngineID &b) * @param b second engine to compare * @return for descending order: returns true if a < b. Vice versa for ascending order */ -static bool EngineSpeedSorter(const EngineID &a, const EngineID &b) +static bool EngineSpeedSorter(const GUIEngineListItem &a, const GUIEngineListItem &b) { - int va = Engine::Get(a)->GetDisplayMaxSpeed(); - int vb = Engine::Get(b)->GetDisplayMaxSpeed(); + int va = Engine::Get(a.engine_id)->GetDisplayMaxSpeed(); + int vb = Engine::Get(b.engine_id)->GetDisplayMaxSpeed(); int r = va - vb; /* Use EngineID to sort instead since we want consistent sorting */ @@ -345,10 +345,10 @@ static bool EngineSpeedSorter(const EngineID &a, const EngineID &b) * @param b second engine to compare * @return for descending order: returns true if a < b. Vice versa for ascending order */ -static bool EnginePowerSorter(const EngineID &a, const EngineID &b) +static bool EnginePowerSorter(const GUIEngineListItem &a, const GUIEngineListItem &b) { - int va = Engine::Get(a)->GetPower(); - int vb = Engine::Get(b)->GetPower(); + int va = Engine::Get(a.engine_id)->GetPower(); + int vb = Engine::Get(b.engine_id)->GetPower(); int r = va - vb; /* Use EngineID to sort instead since we want consistent sorting */ @@ -362,10 +362,10 @@ static bool EnginePowerSorter(const EngineID &a, const EngineID &b) * @param b second engine to compare * @return for descending order: returns true if a < b. Vice versa for ascending order */ -static bool EngineTractiveEffortSorter(const EngineID &a, const EngineID &b) +static bool EngineTractiveEffortSorter(const GUIEngineListItem &a, const GUIEngineListItem &b) { - int va = Engine::Get(a)->GetDisplayMaxTractiveEffort(); - int vb = Engine::Get(b)->GetDisplayMaxTractiveEffort(); + int va = Engine::Get(a.engine_id)->GetDisplayMaxTractiveEffort(); + int vb = Engine::Get(b.engine_id)->GetDisplayMaxTractiveEffort(); int r = va - vb; /* Use EngineID to sort instead since we want consistent sorting */ @@ -379,10 +379,10 @@ static bool EngineTractiveEffortSorter(const EngineID &a, const EngineID &b) * @param b second engine to compare * @return for descending order: returns true if a < b. Vice versa for ascending order */ -static bool EngineRunningCostSorter(const EngineID &a, const EngineID &b) +static bool EngineRunningCostSorter(const GUIEngineListItem &a, const GUIEngineListItem &b) { - Money va = Engine::Get(a)->GetRunningCost(); - Money vb = Engine::Get(b)->GetRunningCost(); + Money va = Engine::Get(a.engine_id)->GetRunningCost(); + Money vb = Engine::Get(b.engine_id)->GetRunningCost(); int r = ClampToI32(va - vb); /* Use EngineID to sort instead since we want consistent sorting */ @@ -390,10 +390,10 @@ static bool EngineRunningCostSorter(const EngineID &a, const EngineID &b) return _engine_sort_direction ? r > 0 : r < 0; } -static bool GenericEngineValueVsRunningCostSorter(const EngineID &a, const uint value_a, const EngineID &b, const uint value_b) +static bool GenericEngineValueVsRunningCostSorter(const GUIEngineListItem &a, const uint value_a, const GUIEngineListItem &b, const uint value_b) { - const Engine *e_a = Engine::Get(a); - const Engine *e_b = Engine::Get(b); + const Engine *e_a = Engine::Get(a.engine_id); + const Engine *e_b = Engine::Get(b.engine_id); Money r_a = e_a->GetRunningCost(); Money r_b = e_b->GetRunningCost(); /* Check if running cost is zero in one or both engines. @@ -428,9 +428,9 @@ static bool GenericEngineValueVsRunningCostSorter(const EngineID &a, const uint * @param b second engine to compare * @return for descending order: returns true if a < b. Vice versa for ascending order */ -static bool EnginePowerVsRunningCostSorter(const EngineID &a, const EngineID &b) +static bool EnginePowerVsRunningCostSorter(const GUIEngineListItem &a, const GUIEngineListItem &b) { - return GenericEngineValueVsRunningCostSorter(a, Engine::Get(a)->GetPower(), b, Engine::Get(b)->GetPower()); + return GenericEngineValueVsRunningCostSorter(a, Engine::Get(a.engine_id)->GetPower(), b, Engine::Get(b.engine_id)->GetPower()); } /* Train sorting functions */ @@ -441,13 +441,13 @@ static bool EnginePowerVsRunningCostSorter(const EngineID &a, const EngineID &b) * @param b second engine to compare * @return for descending order: returns true if a < b. Vice versa for ascending order */ -static bool TrainEngineCapacitySorter(const EngineID &a, const EngineID &b) +static bool TrainEngineCapacitySorter(const GUIEngineListItem &a, const GUIEngineListItem &b) { - const RailVehicleInfo *rvi_a = RailVehInfo(a); - const RailVehicleInfo *rvi_b = RailVehInfo(b); + const RailVehicleInfo *rvi_a = RailVehInfo(a.engine_id); + const RailVehicleInfo *rvi_b = RailVehInfo(b.engine_id); - int va = GetTotalCapacityOfArticulatedParts(a) * (rvi_a->railveh_type == RAILVEH_MULTIHEAD ? 2 : 1); - int vb = GetTotalCapacityOfArticulatedParts(b) * (rvi_b->railveh_type == RAILVEH_MULTIHEAD ? 2 : 1); + int va = GetTotalCapacityOfArticulatedParts(a.engine_id) * (rvi_a->railveh_type == RAILVEH_MULTIHEAD ? 2 : 1); + int vb = GetTotalCapacityOfArticulatedParts(b.engine_id) * (rvi_b->railveh_type == RAILVEH_MULTIHEAD ? 2 : 1); int r = va - vb; /* Use EngineID to sort instead since we want consistent sorting */ @@ -461,13 +461,13 @@ static bool TrainEngineCapacitySorter(const EngineID &a, const EngineID &b) * @param b second engine to compare * @return for descending order: returns true if a < b. Vice versa for ascending order */ -static bool TrainEngineCapacityVsRunningCostSorter(const EngineID &a, const EngineID &b) +static bool TrainEngineCapacityVsRunningCostSorter(const GUIEngineListItem &a, const GUIEngineListItem &b) { - const RailVehicleInfo *rvi_a = RailVehInfo(a); - const RailVehicleInfo *rvi_b = RailVehInfo(b); + const RailVehicleInfo *rvi_a = RailVehInfo(a.engine_id); + const RailVehicleInfo *rvi_b = RailVehInfo(b.engine_id); - uint va = GetTotalCapacityOfArticulatedParts(a) * (rvi_a->railveh_type == RAILVEH_MULTIHEAD ? 2 : 1); - uint vb = GetTotalCapacityOfArticulatedParts(b) * (rvi_b->railveh_type == RAILVEH_MULTIHEAD ? 2 : 1); + uint va = GetTotalCapacityOfArticulatedParts(a.engine_id) * (rvi_a->railveh_type == RAILVEH_MULTIHEAD ? 2 : 1); + uint vb = GetTotalCapacityOfArticulatedParts(b.engine_id) * (rvi_b->railveh_type == RAILVEH_MULTIHEAD ? 2 : 1); return GenericEngineValueVsRunningCostSorter(a, va, b, vb); } @@ -478,10 +478,10 @@ static bool TrainEngineCapacityVsRunningCostSorter(const EngineID &a, const Engi * @param b second engine to compare * @return for descending order: returns true if a < b. Vice versa for ascending order */ -static bool TrainEnginesThenWagonsSorter(const EngineID &a, const EngineID &b) +static bool TrainEnginesThenWagonsSorter(const GUIEngineListItem &a, const GUIEngineListItem &b) { - int val_a = (RailVehInfo(a)->railveh_type == RAILVEH_WAGON ? 1 : 0); - int val_b = (RailVehInfo(b)->railveh_type == RAILVEH_WAGON ? 1 : 0); + int val_a = (RailVehInfo(a.engine_id)->railveh_type == RAILVEH_WAGON ? 1 : 0); + int val_b = (RailVehInfo(b.engine_id)->railveh_type == RAILVEH_WAGON ? 1 : 0); int r = val_a - val_b; /* Use EngineID to sort instead since we want consistent sorting */ @@ -497,10 +497,10 @@ static bool TrainEnginesThenWagonsSorter(const EngineID &a, const EngineID &b) * @param b second engine to compare * @return for descending order: returns true if a < b. Vice versa for ascending order */ -static bool RoadVehEngineCapacitySorter(const EngineID &a, const EngineID &b) +static bool RoadVehEngineCapacitySorter(const GUIEngineListItem &a, const GUIEngineListItem &b) { - int va = GetTotalCapacityOfArticulatedParts(a); - int vb = GetTotalCapacityOfArticulatedParts(b); + int va = GetTotalCapacityOfArticulatedParts(a.engine_id); + int vb = GetTotalCapacityOfArticulatedParts(b.engine_id); int r = va - vb; /* Use EngineID to sort instead since we want consistent sorting */ @@ -514,9 +514,9 @@ static bool RoadVehEngineCapacitySorter(const EngineID &a, const EngineID &b) * @param b second engine to compare * @return for descending order: returns true if a < b. Vice versa for ascending order */ -static bool RoadVehEngineCapacityVsRunningCostSorter(const EngineID &a, const EngineID &b) +static bool RoadVehEngineCapacityVsRunningCostSorter(const GUIEngineListItem &a, const GUIEngineListItem &b) { - return GenericEngineValueVsRunningCostSorter(a, GetTotalCapacityOfArticulatedParts(a), b, GetTotalCapacityOfArticulatedParts(b)); + return GenericEngineValueVsRunningCostSorter(a, GetTotalCapacityOfArticulatedParts(a.engine_id), b, GetTotalCapacityOfArticulatedParts(b.engine_id)); } /* Ship vehicle sorting functions */ @@ -527,10 +527,10 @@ static bool RoadVehEngineCapacityVsRunningCostSorter(const EngineID &a, const En * @param b second engine to compare * @return for descending order: returns true if a < b. Vice versa for ascending order */ -static bool ShipEngineCapacitySorter(const EngineID &a, const EngineID &b) +static bool ShipEngineCapacitySorter(const GUIEngineListItem &a, const GUIEngineListItem &b) { - const Engine *e_a = Engine::Get(a); - const Engine *e_b = Engine::Get(b); + const Engine *e_a = Engine::Get(a.engine_id); + const Engine *e_b = Engine::Get(b.engine_id); int va = e_a->GetDisplayDefaultCapacity(); int vb = e_b->GetDisplayDefaultCapacity(); @@ -547,9 +547,9 @@ static bool ShipEngineCapacitySorter(const EngineID &a, const EngineID &b) * @param b second engine to compare * @return for descending order: returns true if a < b. Vice versa for ascending order */ -static bool ShipEngineCapacityVsRunningCostSorter(const EngineID &a, const EngineID &b) +static bool ShipEngineCapacityVsRunningCostSorter(const GUIEngineListItem &a, const GUIEngineListItem &b) { - return GenericEngineValueVsRunningCostSorter(a, Engine::Get(a)->GetDisplayDefaultCapacity(), b, Engine::Get(b)->GetDisplayDefaultCapacity()); + return GenericEngineValueVsRunningCostSorter(a, Engine::Get(a.engine_id)->GetDisplayDefaultCapacity(), b, Engine::Get(b.engine_id)->GetDisplayDefaultCapacity()); } /* Aircraft sorting functions */ @@ -560,10 +560,10 @@ static bool ShipEngineCapacityVsRunningCostSorter(const EngineID &a, const Engin * @param b second engine to compare * @return for descending order: returns true if a < b. Vice versa for ascending order */ -static bool AircraftEngineCargoSorter(const EngineID &a, const EngineID &b) +static bool AircraftEngineCargoSorter(const GUIEngineListItem &a, const GUIEngineListItem &b) { - const Engine *e_a = Engine::Get(a); - const Engine *e_b = Engine::Get(b); + const Engine *e_a = Engine::Get(a.engine_id); + const Engine *e_b = Engine::Get(b.engine_id); uint16 mail_a, mail_b; int va = e_a->GetDisplayDefaultCapacity(&mail_a); @@ -588,10 +588,10 @@ static bool AircraftEngineCargoSorter(const EngineID &a, const EngineID &b) * @param b second engine to compare * @return for descending order: returns true if a < b. Vice versa for ascending order */ -static bool AircraftEngineCapacityVsRunningCostSorter(const EngineID &a, const EngineID &b) +static bool AircraftEngineCapacityVsRunningCostSorter(const GUIEngineListItem &a, const GUIEngineListItem &b) { - const Engine *e_a = Engine::Get(a); - const Engine *e_b = Engine::Get(b); + const Engine *e_a = Engine::Get(a.engine_id); + const Engine *e_b = Engine::Get(b.engine_id); uint16 mail_a, mail_b; int va = e_a->GetDisplayDefaultCapacity(&mail_a); @@ -606,10 +606,10 @@ static bool AircraftEngineCapacityVsRunningCostSorter(const EngineID &a, const E * @param b second engine to compare * @return for descending order: returns true if a < b. Vice versa for ascending order */ -static bool AircraftRangeSorter(const EngineID &a, const EngineID &b) +static bool AircraftRangeSorter(const GUIEngineListItem &a, const GUIEngineListItem &b) { - uint16 r_a = Engine::Get(a)->GetRange(); - uint16 r_b = Engine::Get(b)->GetRange(); + uint16 r_a = Engine::Get(a.engine_id)->GetRange(); + uint16 r_b = Engine::Get(b.engine_id)->GetRange(); int r = r_a - r_b; @@ -739,14 +739,14 @@ const StringID _engine_sort_listing[][14] = {{ }}; /** Filters vehicles by cargo and engine (in case of rail vehicle). */ -static bool CargoAndEngineFilter(const EngineID *eid, const CargoID cid) +static bool CargoAndEngineFilter(const GUIEngineListItem *item, const CargoID cid) { if (cid == CF_ANY) { return true; } else if (cid == CF_ENGINES) { - return Engine::Get(*eid)->GetPower() != 0; + return Engine::Get(item->engine_id)->GetPower() != 0; } else { - CargoTypes refit_mask = GetUnionOfArticulatedRefitMasks(*eid, true) & _standard_cargo_mask; + CargoTypes refit_mask = GetUnionOfArticulatedRefitMasks(item->engine_id, true) & _standard_cargo_mask; return (cid == CF_NONE ? refit_mask == 0 : HasBit(refit_mask, cid)); } } @@ -1185,21 +1185,22 @@ int DrawVehiclePurchaseInfo(int left, int right, int y, EngineID engine_number, * @param show_count Whether to show the amount of engines or not * @param selected_group the group to list the engines of */ -void DrawEngineList(VehicleType type, const Rect &r, const GUIEngineList *eng_list, uint16 min, uint16 max, EngineID selected_id, bool show_count, GroupID selected_group) +void DrawEngineList(VehicleType type, const Rect &r, const GUIEngineList &eng_list, uint16 min, uint16 max, EngineID selected_id, bool show_count, GroupID selected_group) { static const int sprite_y_offsets[] = { -1, -1, -2, -2 }; /* Obligatory sanity checks! */ - assert(max <= eng_list->size()); + assert(max <= eng_list.size()); bool rtl = _current_text_dir == TD_RTL; int step_size = GetEngineListHeight(type); int sprite_left = GetVehicleImageCellSize(type, EIT_PURCHASE).extend_left; int sprite_right = GetVehicleImageCellSize(type, EIT_PURCHASE).extend_right; int sprite_width = sprite_left + sprite_right; + int circle_width = std::max(GetScaledSpriteSize(SPR_CIRCLE_FOLDED).width, GetScaledSpriteSize(SPR_CIRCLE_UNFOLDED).width); + int linecolour = _colour_gradient[COLOUR_ORANGE][4]; Rect ir = r.WithHeight(step_size).Shrink(WidgetDimensions::scaled.matrix); - int sprite_x = ir.WithWidth(sprite_width, rtl).left + sprite_left; int sprite_y_offset = ScaleSpriteTrad(sprite_y_offsets[type]) + ir.Height() / 2; Dimension replace_icon = {0, 0}; @@ -1210,7 +1211,7 @@ void DrawEngineList(VehicleType type, const Rect &r, const GUIEngineList *eng_li count_width = GetStringBoundingBox(STR_TINY_BLACK_COMA).width; } - Rect tr = ir.Indent(sprite_width + WidgetDimensions::scaled.hsep_wide, rtl); // Name position + Rect tr = ir.Indent(circle_width + WidgetDimensions::scaled.hsep_normal + sprite_width + WidgetDimensions::scaled.hsep_wide, rtl); // Name position Rect cr = tr.Indent(replace_icon.width + WidgetDimensions::scaled.hsep_wide, !rtl).WithWidth(count_width, !rtl); // Count position Rect rr = tr.WithWidth(replace_icon.width, !rtl); // Replace icon position if (show_count) tr = tr.Indent(count_width + WidgetDimensions::scaled.hsep_normal + replace_icon.width + WidgetDimensions::scaled.hsep_wide, !rtl); @@ -1221,22 +1222,40 @@ void DrawEngineList(VehicleType type, const Rect &r, const GUIEngineList *eng_li int y = ir.top; for (; min < max; min++, y += step_size) { - const EngineID engine = (*eng_list)[min]; + const auto &item = eng_list[min]; + uint indent = item.indent * WidgetDimensions::scaled.hsep_indent; + bool has_variants = (item.flags & EngineDisplayFlags::HasVariants) != EngineDisplayFlags::None; + bool is_folded = (item.flags & EngineDisplayFlags::IsFolded) != EngineDisplayFlags::None; + bool shaded = (item.flags & EngineDisplayFlags::Shaded) != EngineDisplayFlags::None; /* Note: num_engines is only used in the autoreplace GUI, so it is correct to use _local_company here. */ - const uint num_engines = GetGroupNumEngines(_local_company, selected_group, engine); + const uint num_engines = GetGroupNumEngines(_local_company, selected_group, item.engine_id); - const Engine *e = Engine::Get(engine); + const Engine *e = Engine::Get(item.engine_id); bool hidden = HasBit(e->company_hidden, _local_company); StringID str = hidden ? STR_HIDDEN_ENGINE_NAME : STR_ENGINE_NAME; - TextColour tc = (engine == selected_id) ? TC_WHITE : (TC_NO_SHADE | (hidden ? TC_GREY : TC_BLACK)); + TextColour tc = (item.engine_id == selected_id) ? TC_WHITE : (TC_NO_SHADE | ((hidden | shaded) ? TC_GREY : TC_BLACK)); - SetDParam(0, engine); - DrawString(tr.left, tr.right, y + normal_text_y_offset, str, tc); - DrawVehicleEngine(r.left, r.right, sprite_x, y + sprite_y_offset, engine, (show_count && num_engines == 0) ? PALETTE_CRASH : GetEnginePalette(engine, _local_company), EIT_PURCHASE); + SetDParam(0, item.engine_id); + Rect itr = tr.Indent(indent, rtl); + DrawString(itr.left, itr.right, y + normal_text_y_offset, str, tc); + int sprite_x = ir.Indent(indent + circle_width + WidgetDimensions::scaled.hsep_normal, rtl).WithWidth(sprite_width, rtl).left + sprite_left; + DrawVehicleEngine(r.left, r.right, sprite_x, y + sprite_y_offset, item.engine_id, (show_count && num_engines == 0) ? PALETTE_CRASH : GetEnginePalette(item.engine_id, _local_company), EIT_PURCHASE); if (show_count) { SetDParam(0, num_engines); DrawString(cr.left, cr.right, y + small_text_y_offset, STR_TINY_BLACK_COMA, TC_FROMSTRING, SA_RIGHT | SA_FORCE); - if (EngineHasReplacementForCompany(Company::Get(_local_company), engine, selected_group)) DrawSprite(SPR_GROUP_REPLACE_ACTIVE, num_engines == 0 ? PALETTE_CRASH : PAL_NONE, rr.left, y + replace_icon_y_offset); + if (EngineHasReplacementForCompany(Company::Get(_local_company), item.engine_id, selected_group)) DrawSprite(SPR_GROUP_REPLACE_ACTIVE, num_engines == 0 ? PALETTE_CRASH : PAL_NONE, rr.left, y + replace_icon_y_offset); + } + if (has_variants) { + Rect fr = ir.Indent(indent, rtl).WithWidth(circle_width, rtl); + DrawSpriteIgnorePadding(is_folded ? SPR_CIRCLE_FOLDED : SPR_CIRCLE_UNFOLDED, PAL_NONE, {fr.left, y, fr.right, y + ir.Height() - 1}, false, SA_CENTER); + } + if (indent > 0) { + /* Draw tree lines */ + Rect fr = ir.Indent(indent - WidgetDimensions::scaled.hsep_indent, rtl).WithWidth(circle_width, rtl); + int ycenter = y + normal_text_y_offset + FONT_HEIGHT_NORMAL / 2; + bool continues = (min + 1U) < eng_list.size() && eng_list[min + 1].indent == item.indent; + GfxDrawLine(fr.left + circle_width / 2, y - WidgetDimensions::scaled.matrix.top, fr.left + circle_width / 2, continues ? y - WidgetDimensions::scaled.matrix.top + step_size - 1 : ycenter, linecolour, WidgetDimensions::scaled.fullbevel.top); + GfxDrawLine(fr.left + circle_width / 2, ycenter, fr.right, ycenter, linecolour, WidgetDimensions::scaled.fullbevel.top); } } } @@ -1280,6 +1299,27 @@ struct BuildVehicleWindowBase : Window { this->listview_mode = (tile == INVALID_TILE) && !virtual_train_mode; } + void AddChildren(GUIEngineList &eng_list, const GUIEngineList &source, EngineID parent, int indent) + { + for (const auto &item : source) { + if (item.variant_id != parent || item.engine_id == parent) continue; + + const Engine *e = Engine::Get(item.engine_id); + EngineDisplayFlags flags = item.flags; + if (e->display_last_variant != INVALID_ENGINE) flags &= ~EngineDisplayFlags::Shaded; + eng_list.emplace_back(e->display_last_variant == INVALID_ENGINE ? item.engine_id : e->display_last_variant, item.engine_id, flags, indent); + + /* Add variants if not folded */ + if ((item.flags & (EngineDisplayFlags::HasVariants | EngineDisplayFlags::IsFolded)) == EngineDisplayFlags::HasVariants) { + /* Add this engine again as a child */ + if ((item.flags & EngineDisplayFlags::Shaded) == EngineDisplayFlags::None) { + eng_list.emplace_back(item.engine_id, item.engine_id, EngineDisplayFlags::None, indent + 1); + } + AddChildren(eng_list, source, item.engine_id, indent + 1); + } + } + } + void AddVirtualEngine(Train *toadd) { if (this->virtual_train_out == nullptr) return; @@ -1385,7 +1425,7 @@ struct BuildVehicleWindow : BuildVehicleWindowBase { this->GenerateBuildList(); // generate the list, since we need it in the next line /* Select the first engine in the list as default when opening the window */ if (this->eng_list.size() > 0) { - this->SelectEngine(this->eng_list[0]); + this->SelectEngine(this->eng_list[0].engine_id); } else { this->SelectEngine(INVALID_ENGINE); } @@ -1538,7 +1578,7 @@ struct BuildVehicleWindow : BuildVehicleWindowBase { if (0 == this->eng_list.size()) { // no engine passed through the filter, invalidate the previously selected engine this->SelectEngine(INVALID_ENGINE); } else if (std::find(this->eng_list.begin(), this->eng_list.end(), this->sel_engine) == this->eng_list.end()) { // previously selected engine didn't pass the filter, select the first engine of the list - this->SelectEngine(this->eng_list[0]); + this->SelectEngine(this->eng_list[0].engine_id); } } @@ -1546,17 +1586,19 @@ struct BuildVehicleWindow : BuildVehicleWindowBase { bool FilterSingleEngine(EngineID eid) { CargoID filter_type = this->cargo_filter[this->cargo_filter_criteria]; - return CargoAndEngineFilter(&eid, filter_type); + GUIEngineListItem item = {eid, eid, EngineDisplayFlags::None, 0}; + return CargoAndEngineFilter(&item, filter_type); } /* Figure out what train EngineIDs to put in the list */ - void GenerateBuildTrainList() + void GenerateBuildTrainList(GUIEngineList &list) { + std::vector variants; EngineID sel_id = INVALID_ENGINE; int num_engines = 0; int num_wagons = 0; - this->eng_list.clear(); + list.clear(); /* Make list of all available train engines and wagons. * Also check to see if the previously selected engine is still available, @@ -1573,7 +1615,7 @@ struct BuildVehicleWindow : BuildVehicleWindowBase { /* Filter now! So num_engines and num_wagons is valid */ if (!FilterSingleEngine(eid)) continue; - this->eng_list.push_back(eid); + list.emplace_back(eid, e->info.variant_id, e->display_flags, 0); if (rvi->railveh_type != RAILVEH_WAGON) { num_engines++; @@ -1581,9 +1623,18 @@ struct BuildVehicleWindow : BuildVehicleWindowBase { num_wagons++; } + if (e->info.variant_id != eid && e->info.variant_id != INVALID_ENGINE) variants.push_back(e->info.variant_id); if (eid == this->sel_engine) sel_id = eid; } + /* ensure primary engine of variant group is in list */ + for (const auto &variant : variants) { + if (std::find(list.begin(), list.end(), variant) == list.end()) { + const Engine *e = Engine::Get(variant); + list.emplace_back(variant, e->info.variant_id, e->display_flags | EngineDisplayFlags::Shaded, 0); + } + } + this->SelectEngine(sel_id); /* invalidate cached values for name sorter - engine names could change */ @@ -1591,14 +1642,14 @@ struct BuildVehicleWindow : BuildVehicleWindowBase { /* make engines first, and then wagons, sorted by selected sort_criteria */ _engine_sort_direction = false; - EngList_Sort(&this->eng_list, TrainEnginesThenWagonsSorter); + EngList_Sort(&list, TrainEnginesThenWagonsSorter); /* and then sort engines */ _engine_sort_direction = this->descending_sort_order; - EngList_SortPartial(&this->eng_list, _engine_sort_functions[0][this->sort_criteria], 0, num_engines); + EngList_SortPartial(&list, _engine_sort_functions[0][this->sort_criteria], 0, num_engines); /* and finally sort wagons */ - EngList_SortPartial(&this->eng_list, _engine_sort_functions[0][this->sort_criteria], num_engines, num_wagons); + EngList_SortPartial(&list, _engine_sort_functions[0][this->sort_criteria], num_engines, num_wagons); } /* Figure out what road vehicle EngineIDs to put in the list */ @@ -1614,7 +1665,7 @@ struct BuildVehicleWindow : BuildVehicleWindowBase { if (!IsEngineBuildable(eid, VEH_ROAD, _local_company)) continue; if (this->filter.roadtype != INVALID_ROADTYPE && !HasPowerOnRoad(e->u.road.roadtype, this->filter.roadtype)) continue; - this->eng_list.push_back(eid); + this->eng_list.emplace_back(eid, e->info.variant_id, e->display_flags, 0); if (eid == this->sel_engine) sel_id = eid; } @@ -1631,7 +1682,7 @@ struct BuildVehicleWindow : BuildVehicleWindowBase { if (!this->show_hidden_engines && e->IsHidden(_local_company)) continue; EngineID eid = e->index; if (!IsEngineBuildable(eid, VEH_SHIP, _local_company)) continue; - this->eng_list.push_back(eid); + this->eng_list.emplace_back(eid, e->info.variant_id, e->display_flags, 0); if (eid == this->sel_engine) sel_id = eid; } @@ -1658,7 +1709,7 @@ struct BuildVehicleWindow : BuildVehicleWindowBase { /* First VEH_END window_numbers are fake to allow a window open for all different types at once */ if (!this->listview_mode && !CanVehicleUseStation(eid, st)) continue; - this->eng_list.push_back(eid); + this->eng_list.emplace_back(eid, e->info.variant_id, e->display_flags, 0); if (eid == this->sel_engine) sel_id = eid; } @@ -1673,13 +1724,18 @@ struct BuildVehicleWindow : BuildVehicleWindowBase { /* Update filter type in case the road/railtype of the depot got converted */ this->UpdateFilterByTile(); + this->eng_list.clear(); + + GUIEngineList list; + switch (this->vehicle_type) { default: NOT_REACHED(); case VEH_TRAIN: - this->GenerateBuildTrainList(); + this->GenerateBuildTrainList(list); + AddChildren(this->eng_list, list, INVALID_ENGINE, 0); this->eng_list.shrink_to_fit(); this->eng_list.RebuildDone(); - return; // trains should not reach the last sorting + return; case VEH_ROAD: this->GenerateBuildRoadVehList(); break; @@ -1693,9 +1749,23 @@ struct BuildVehicleWindow : BuildVehicleWindowBase { this->FilterEngineList(); + /* ensure primary engine of variant group is in list after filtering */ + std::vector variants; + for (const auto &item : this->eng_list) { + if (item.engine_id != item.variant_id && item.variant_id != INVALID_ENGINE) variants.push_back(item.variant_id); + } + for (const auto &variant : variants) { + if (std::find(this->eng_list.begin(), this->eng_list.end(), variant) == this->eng_list.end()) { + const Engine *e = Engine::Get(variant); + list.emplace_back(variant, e->info.variant_id, e->display_flags | EngineDisplayFlags::Shaded, 0); + } + } + _engine_sort_direction = this->descending_sort_order; EngList_Sort(&this->eng_list, _engine_sort_functions[this->vehicle_type][this->sort_criteria]); + this->eng_list.swap(list); + AddChildren(this->eng_list, list, INVALID_ENGINE, 0); this->eng_list.shrink_to_fit(); this->eng_list.RebuildDone(); } @@ -1721,7 +1791,23 @@ struct BuildVehicleWindow : BuildVehicleWindowBase { case WID_BV_LIST: { uint i = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_BV_LIST); size_t num_items = this->eng_list.size(); - this->SelectEngine((i < num_items) ? this->eng_list[i] : INVALID_ENGINE); + EngineID e = INVALID_ENGINE; + if (i < num_items) { + const auto &item = this->eng_list[i]; + const Rect r = this->GetWidget(widget)->GetCurrentRect().Shrink(WidgetDimensions::scaled.matrix).WithWidth(WidgetDimensions::scaled.hsep_indent * (item.indent + 1), _current_text_dir == TD_RTL); + if ((item.flags & EngineDisplayFlags::HasVariants) != EngineDisplayFlags::None && IsInsideMM(r.left, r.right, pt.x)) { + /* toggle folded flag on engine */ + assert(item.variant_id != INVALID_ENGINE); + Engine *engine = Engine::Get(item.variant_id); + engine->display_flags ^= EngineDisplayFlags::IsFolded; + + InvalidateWindowData(WC_REPLACE_VEHICLE, this->vehicle_type, 0); // Update the autoreplace window + InvalidateWindowClassesData(WC_BUILD_VEHICLE); // The build windows needs updating as well + return; + } + if ((item.flags & EngineDisplayFlags::Shaded) == EngineDisplayFlags::None) e = item.engine_id; + } + this->SelectEngine(e); this->SetDirty(); if (_ctrl_pressed) { this->OnClick(pt, WID_BV_SHOW_HIDE, 1); @@ -1763,6 +1849,20 @@ struct BuildVehicleWindow : BuildVehicleWindowBase { CargoID cargo = this->cargo_filter[this->cargo_filter_criteria]; if (cargo == CF_ANY || cargo == CF_ENGINES) cargo = CF_NONE; DoCommandP(this->window_number, sel_eng | (cargo << 24), 0, cmd, callback); + + /* Update last used variant and refresh if necessary. */ + bool refresh = false; + int recursion = 10; /* In case of infinite loop */ + for (Engine *e = Engine::Get(sel_eng); recursion > 0; e = Engine::Get(e->info.variant_id), --recursion) { + refresh |= (e->display_last_variant != sel_eng); + e->display_last_variant = sel_eng; + if (e->info.variant_id == INVALID_ENGINE) break; + } + if (refresh) { + InvalidateWindowData(WC_REPLACE_VEHICLE, this->vehicle_type, 0); // Update the autoreplace window + InvalidateWindowClassesData(WC_BUILD_VEHICLE); // The build windows needs updating as well + return; + } } break; } @@ -1876,7 +1976,7 @@ struct BuildVehicleWindow : BuildVehicleWindowBase { DrawEngineList( this->vehicle_type, r, - &this->eng_list, + this->eng_list, this->vscroll->GetPosition(), static_cast(std::min(this->vscroll->GetPosition() + this->vscroll->GetCapacity(), this->eng_list.size())), this->sel_engine, @@ -2263,7 +2363,7 @@ struct BuildVehicleWindowTrainAdvanced final : BuildVehicleWindowBase { if (state.eng_list.empty()) { this->SelectEngine(state, INVALID_ENGINE); } else { - this->SelectEngine(state, state.eng_list[0]); + this->SelectEngine(state, state.eng_list[0].engine_id); } } @@ -2354,15 +2454,17 @@ struct BuildVehicleWindowTrainAdvanced final : BuildVehicleWindowBase { bool FilterSingleEngine(PanelState &state, EngineID eid) { const CargoID filter_type = state.cargo_filter[state.cargo_filter_criteria]; - return (filter_type == CF_ANY || CargoAndEngineFilter(&eid, filter_type)); + GUIEngineListItem item = {eid, eid, EngineDisplayFlags::None, 0}; + return (filter_type == CF_ANY || CargoAndEngineFilter(&item, filter_type)); } /* Figure out what train EngineIDs to put in the list */ - void GenerateBuildTrainList(PanelState &state, const bool wagon, EngList_SortTypeFunction * const sorters[]) + void GenerateBuildTrainList(GUIEngineList &list, PanelState &state, const bool wagon, EngList_SortTypeFunction * const sorters[]) { + std::vector variants; EngineID sel_id = INVALID_ENGINE; - state.eng_list.clear(); + list.clear(); /* Make list of all available train engines and wagons. * Also check to see if the previously selected engine is still available, @@ -2378,13 +2480,21 @@ struct BuildVehicleWindowTrainAdvanced final : BuildVehicleWindowBase { if (!FilterSingleEngine(state, eid)) continue; - if ((rvi->railveh_type == RAILVEH_WAGON) == wagon) { - state.eng_list.push_back(eid); - } + if ((rvi->railveh_type == RAILVEH_WAGON) != wagon) continue; + list.emplace_back(eid, engine->info.variant_id, engine->display_flags, 0); + if (engine->info.variant_id != eid && engine->info.variant_id != INVALID_ENGINE) variants.push_back(engine->info.variant_id); if (eid == state.sel_engine) sel_id = eid; } + /* ensure primary engine of variant group is in list */ + for (const auto &variant : variants) { + if (std::find(list.begin(), list.end(), variant) == list.end()) { + const Engine *e = Engine::Get(variant); + list.emplace_back(variant, e->info.variant_id, e->display_flags | EngineDisplayFlags::Shaded, 0); + } + } + this->SelectEngine(state, sel_id); /* invalidate cached values for name sorter - engine names could change */ @@ -2392,7 +2502,7 @@ struct BuildVehicleWindowTrainAdvanced final : BuildVehicleWindowBase { /* Sort */ _engine_sort_direction = state.descending_sort_order; - EngList_Sort(&state.eng_list, sorters[state.sort_criteria]); + EngList_Sort(&list, sorters[state.sort_criteria]); } /* Generate the list of vehicles */ @@ -2405,8 +2515,16 @@ struct BuildVehicleWindowTrainAdvanced final : BuildVehicleWindowBase { this->railtype = (this->listview_mode || this->virtual_train_mode) ? RAILTYPE_END : GetRailType(this->window_number); - this->GenerateBuildTrainList(this->loco, false, _sorter_loco); - this->GenerateBuildTrainList(this->wagon, true, _sorter_wagon); + this->loco.eng_list.clear(); + this->wagon.eng_list.clear(); + + GUIEngineList list; + + this->GenerateBuildTrainList(list, this->loco, false, _sorter_loco); + AddChildren(this->loco.eng_list, list, INVALID_ENGINE, 0); + + this->GenerateBuildTrainList(list, this->wagon, true, _sorter_wagon); + AddChildren(this->wagon.eng_list, list, INVALID_ENGINE, 0); this->loco.eng_list.shrink_to_fit(); this->loco.eng_list.RebuildDone(); @@ -2430,7 +2548,47 @@ struct BuildVehicleWindowTrainAdvanced final : BuildVehicleWindowBase { } if (cargo == CF_ANY || cargo == CF_ENGINES) cargo = CF_NONE; DoCommandP(this->window_number, selected | (cargo << 24), 0, cmd, callback); + + /* Update last used variant and refresh if necessary. */ + bool refresh = false; + int recursion = 10; /* In case of infinite loop */ + for (Engine *e = Engine::Get(selected); recursion > 0; e = Engine::Get(e->info.variant_id), --recursion) { + refresh |= (e->display_last_variant != selected); + e->display_last_variant = selected; + if (e->info.variant_id == INVALID_ENGINE) break; + } + if (refresh) { + InvalidateWindowData(WC_REPLACE_VEHICLE, this->vehicle_type, 0); // Update the autoreplace window + InvalidateWindowClassesData(WC_BUILD_VEHICLE); // The build windows needs updating as well + return; + } + } + } + + bool OnClickList(Point pt, int widget, PanelState &state, bool column) + { + const uint i = state.vscroll->GetScrolledRowFromWidget(pt.y, this, widget); + const size_t num_items = state.eng_list.size(); + EngineID e = INVALID_ENGINE; + if (i < num_items) { + const auto &item = state.eng_list[i]; + const Rect r = this->GetWidget(widget)->GetCurrentRect().Shrink(WidgetDimensions::scaled.matrix).WithWidth(WidgetDimensions::scaled.hsep_indent * (item.indent + 1), _current_text_dir == TD_RTL); + if ((item.flags & EngineDisplayFlags::HasVariants) != EngineDisplayFlags::None && IsInsideMM(r.left, r.right, pt.x)) { + /* toggle folded flag on engine */ + assert(item.variant_id != INVALID_ENGINE); + Engine *engine = Engine::Get(item.variant_id); + engine->display_flags ^= EngineDisplayFlags::IsFolded; + + InvalidateWindowData(WC_REPLACE_VEHICLE, this->vehicle_type, 0); // Update the autoreplace window + InvalidateWindowClassesData(WC_BUILD_VEHICLE); // The build windows needs updating as well + return true; + } + if ((item.flags & EngineDisplayFlags::Shaded) == EngineDisplayFlags::None) e = item.engine_id; } + this->SelectEngine(state, e); + this->SelectColumn(column); + this->SetDirty(); + return false; } void OnClick(Point pt, int widget, int click_count) override @@ -2465,11 +2623,7 @@ struct BuildVehicleWindowTrainAdvanced final : BuildVehicleWindowBase { } case WID_BV_LIST_LOCO: { - const uint i = this->loco.vscroll->GetScrolledRowFromWidget(pt.y, this, WID_BV_LIST_LOCO); - const size_t num_items = this->loco.eng_list.size(); - this->SelectEngine(this->loco, (i < num_items) ? this->loco.eng_list[i] : INVALID_ENGINE); - this->SelectColumn(false); - this->SetDirty(); + if (this->OnClickList(pt, widget, this->loco, false)) return; if (_ctrl_pressed) { this->OnClick(pt, WID_BV_SHOW_HIDE_LOCO, 1); @@ -2533,11 +2687,7 @@ struct BuildVehicleWindowTrainAdvanced final : BuildVehicleWindowBase { } case WID_BV_LIST_WAGON: { - const uint i = this->wagon.vscroll->GetScrolledRowFromWidget(pt.y, this, WID_BV_LIST_WAGON); - const size_t num_items = this->wagon.eng_list.size(); - this->SelectEngine(this->wagon, (i < num_items) ? this->wagon.eng_list[i] : INVALID_ENGINE); - this->SelectColumn(true); - this->SetDirty(); + if (this->OnClickList(pt, widget, this->wagon, true)) return; if (_ctrl_pressed) { this->OnClick(pt, WID_BV_SHOW_HIDE_WAGON, 1); @@ -2741,7 +2891,7 @@ struct BuildVehicleWindowTrainAdvanced final : BuildVehicleWindowBase { switch (widget) { case WID_BV_LIST_LOCO: { DrawEngineList(this->vehicle_type, r, - &this->loco.eng_list, this->loco.vscroll->GetPosition(), + this->loco.eng_list, this->loco.vscroll->GetPosition(), std::min(this->loco.vscroll->GetPosition() + this->loco.vscroll->GetCapacity(), static_cast(this->loco.eng_list.size())), this->loco.sel_engine, false, DEFAULT_GROUP); @@ -2755,7 +2905,7 @@ struct BuildVehicleWindowTrainAdvanced final : BuildVehicleWindowBase { case WID_BV_LIST_WAGON: { DrawEngineList(this->vehicle_type, r, - &this->wagon.eng_list, this->wagon.vscroll->GetPosition(), + this->wagon.eng_list, this->wagon.vscroll->GetPosition(), std::min(this->wagon.vscroll->GetPosition() + this->wagon.vscroll->GetCapacity(), static_cast(this->wagon.eng_list.size())), this->wagon.sel_engine, false, DEFAULT_GROUP); diff --git a/src/core/enum_type.hpp b/src/core/enum_type.hpp index d4ea82eff1..cd2358eca6 100644 --- a/src/core/enum_type.hpp +++ b/src/core/enum_type.hpp @@ -29,13 +29,13 @@ /** Operators to allow to work with enum as with type safe bit set in C++ */ # define DECLARE_ENUM_AS_BIT_SET(mask_t) \ - inline mask_t operator | (mask_t m1, mask_t m2) {return (mask_t)((std::underlying_type::type)m1 | m2);} \ - inline mask_t operator & (mask_t m1, mask_t m2) {return (mask_t)((std::underlying_type::type)m1 & m2);} \ - inline mask_t operator ^ (mask_t m1, mask_t m2) {return (mask_t)((std::underlying_type::type)m1 ^ m2);} \ - inline mask_t& operator |= (mask_t& m1, mask_t m2) {m1 = m1 | m2; return m1;} \ - inline mask_t& operator &= (mask_t& m1, mask_t m2) {m1 = m1 & m2; return m1;} \ - inline mask_t& operator ^= (mask_t& m1, mask_t m2) {m1 = m1 ^ m2; return m1;} \ - inline mask_t operator ~(mask_t m) {return (mask_t)(~(std::underlying_type::type)m);} + inline constexpr mask_t operator | (mask_t m1, mask_t m2) {return (mask_t)((std::underlying_type::type)m1 | (std::underlying_type::type)m2);} \ + inline constexpr mask_t operator & (mask_t m1, mask_t m2) {return (mask_t)((std::underlying_type::type)m1 & (std::underlying_type::type)m2);} \ + inline constexpr mask_t operator ^ (mask_t m1, mask_t m2) {return (mask_t)((std::underlying_type::type)m1 ^ (std::underlying_type::type)m2);} \ + inline constexpr mask_t& operator |= (mask_t& m1, mask_t m2) {m1 = m1 | m2; return m1;} \ + inline constexpr mask_t& operator &= (mask_t& m1, mask_t m2) {m1 = m1 & m2; return m1;} \ + inline constexpr mask_t& operator ^= (mask_t& m1, mask_t m2) {m1 = m1 ^ m2; return m1;} \ + inline constexpr mask_t operator ~(mask_t m) {return (mask_t)(~(std::underlying_type::type)m);} /** diff --git a/src/engine.cpp b/src/engine.cpp index 9b1b9a0846..b6adc44b60 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -73,6 +73,7 @@ Engine::Engine(VehicleType type, EngineID base) this->grf_prop.local_id = base; this->list_position = base; this->preview_company = INVALID_COMPANY; + this->display_last_variant = INVALID_ENGINE; /* Check if this base engine is within the original engine data range */ if (base >= _engine_counts[type]) { @@ -93,6 +94,8 @@ Engine::Engine(VehicleType type, EngineID base) } /* Set cargo aging period to the default value. */ this->info.cargo_age_period = CARGO_AGING_TICKS; + /* Not a variant */ + this->info.variant_id = INVALID_ENGINE; return; } @@ -580,6 +583,18 @@ static bool IsWagon(EngineID index) return e->type == VEH_TRAIN && e->u.rail.railveh_type == RAILVEH_WAGON; } +/** + * Ensure engine is not set as the last used variant for any other engine. + * @param engine_id Engine being removed. + * @param type Type of engine. + */ +static void ClearLastVariant(EngineID engine_id, VehicleType type) +{ + for (Engine *e : Engine::IterateType(type)) { + if (e->display_last_variant == engine_id) e->display_last_variant = INVALID_ENGINE; + } +} + static void RetireEngineIfPossible(Engine *e, int age_threshold) { if (_settings_game.vehicle.no_expire_vehicles_after > 0) { @@ -589,6 +604,7 @@ static void RetireEngineIfPossible(Engine *e, int age_threshold) } e->company_avail = 0; + ClearLastVariant(e->index, e->type); AddRemoveEngineFromAutoreplaceAndBuildWindows(e->type); } @@ -596,9 +612,16 @@ static void RetireEngineIfPossible(Engine *e, int age_threshold) * Update #Engine::reliability and (if needed) update the engine GUIs. * @param e %Engine to update. */ -static void CalcEngineReliability(Engine *e) +void CalcEngineReliability(Engine *e, bool new_month) { - uint age = e->age; + /* Get source engine for reliability age. This is normally our engine unless variant reliability syncing is requested. */ + Engine *re = e; + while (re->info.variant_id != INVALID_ENGINE && re->info.variant_id != re->index && (re->info.extra_flags & ExtraEngineFlags::SyncReliability) != ExtraEngineFlags::None) { + re = Engine::Get(re->info.variant_id); + } + + uint age = re->age; + if (new_month && re->index > e->index && age != MAX_DAY) age++; /* parent variant's age has not yet updated. */ /* Check for early retirement */ if (e->company_avail != 0 && !_settings_game.vehicle.never_expire_vehicles && e->info.base_life != 0xFF) { @@ -606,6 +629,7 @@ static void CalcEngineReliability(Engine *e) uint retire_early_max_age = std::max(0, e->duration_phase_1 + e->duration_phase_2 - retire_early * 12); if (retire_early != 0 && age >= retire_early_max_age) { /* Early retirement is enabled and we're past the date... */ + RetireEngineIfPossible(e, retire_early_max_age); } } @@ -659,8 +683,9 @@ void SetYearEngineAgingStops() * Start/initialise one engine. * @param e The engine to initialise. * @param aging_date The date used for age calculations. + * @param seed Random seed. */ -void StartupOneEngine(Engine *e, Date aging_date, Date no_introduce_after_date) +void StartupOneEngine(Engine *e, Date aging_date, uint32 seed, Date no_introduce_after_date) { const EngineInfo *ei = &e->info; @@ -673,7 +698,7 @@ void StartupOneEngine(Engine *e, Date aging_date, Date no_introduce_after_date) * Make sure they use the same randomisation of the date. */ SavedRandomSeeds saved_seeds; SaveRandomSeeds(&saved_seeds); - SetRandomSeed(_settings_game.game_creation.generation_seed ^ + SetRandomSeed(_settings_game.game_creation.generation_seed ^ seed ^ ei->base_intro ^ e->type ^ e->GetGRFID()); @@ -689,7 +714,17 @@ void StartupOneEngine(Engine *e, Date aging_date, Date no_introduce_after_date) e->flags |= ENGINE_AVAILABLE; } - RestoreRandomSeeds(saved_seeds); + /* Get parent variant index for syncing reliability via random seed. */ + const Engine *re = e; + while (re->info.variant_id != INVALID_ENGINE && re->info.variant_id != re->index && (re->info.extra_flags & ExtraEngineFlags::SyncReliability) != ExtraEngineFlags::None) { + re = Engine::Get(re->info.variant_id); + } + + SetRandomSeed(_settings_game.game_creation.generation_seed ^ seed ^ + (re->index << 16) ^ (re->info.base_intro << 12) ^ (re->info.decay_speed << 8) ^ + (re->info.lifelength << 4) ^ re->info.retire_early ^ + e->type ^ + e->GetGRFID()); r = Random(); e->reliability_start = GB(r, 16, 14) + 0x7AE0; @@ -701,9 +736,9 @@ void StartupOneEngine(Engine *e, Date aging_date, Date no_introduce_after_date) e->duration_phase_2 = GB(r, 5, 4) + ei->base_life * 12 - 96; e->duration_phase_3 = GB(r, 9, 7) + 120; - e->reliability_spd_dec = ei->decay_speed << 2; + RestoreRandomSeeds(saved_seeds); - CalcEngineReliability(e); + e->reliability_spd_dec = ei->decay_speed << 2; /* prevent certain engines from ever appearing. */ if (!HasBit(ei->climates, _settings_game.game_creation.landscape)) { @@ -730,8 +765,13 @@ void StartupEngines() no_introduce_after_date = ConvertYMDToDate(_settings_game.vehicle.no_introduce_vehicles_after, 0, 1) - 1; } + uint32 seed = Random(); + for (Engine *e : Engine::Iterate()) { - StartupOneEngine(e, aging_date, no_introduce_after_date); + StartupOneEngine(e, aging_date, seed, no_introduce_after_date); + } + for (Engine *e : Engine::Iterate()) { + CalcEngineReliability(e, false); } /* Update the bitmasks for the vehicle lists */ @@ -743,6 +783,9 @@ void StartupEngines() /* Invalidate any open purchase lists */ InvalidateWindowClassesData(WC_BUILD_VEHICLE); InvalidateWindowClassesData(WC_BUILD_VIRTUAL_TRAIN); + + SetWindowClassesDirty(WC_BUILD_VEHICLE); + SetWindowClassesDirty(WC_REPLACE_VEHICLE); } /** @@ -791,6 +834,7 @@ static void DisableEngineForCompany(EngineID eid, CompanyID company) } if (company == _local_company) { + ClearLastVariant(e->index, e->type); AddRemoveEngineFromAutoreplaceAndBuildWindows(e->type); } } @@ -799,8 +843,9 @@ static void DisableEngineForCompany(EngineID eid, CompanyID company) * Company \a company accepts engine \a eid for preview. * @param eid Engine being accepted (is under preview). * @param company Current company previewing the engine. + * @param recursion_depth Recursion depth to avoid infinite loop. */ -static void AcceptEnginePreview(EngineID eid, CompanyID company) +static void AcceptEnginePreview(EngineID eid, CompanyID company, int recursion_depth = 0) { Engine *e = Engine::Get(eid); @@ -815,6 +860,16 @@ static void AcceptEnginePreview(EngineID eid, CompanyID company) * we have to use the GUI-scope scheduling of InvalidateWindowData. */ InvalidateWindowData(WC_ENGINE_PREVIEW, eid); + + /* Don't search for variants to include if we are 10 levels deep already. */ + if (recursion_depth >= 10) return; + + /* Find variants to be included in preview. */ + for (Engine *ve : Engine::IterateType(e->type)) { + if (ve->index != eid && ve->info.variant_id == eid && (ve->info.extra_flags & ExtraEngineFlags::JoinPreview) != ExtraEngineFlags::None) { + AcceptEnginePreview(ve->index, company, recursion_depth + 1); + } + } } /** @@ -1049,7 +1104,7 @@ static void NewVehicleAvailable(Engine *e) if (!IsVehicleTypeDisabled(e->type, true)) AI::BroadcastNewEvent(new ScriptEventEngineAvailable(index)); /* Only provide the "New Vehicle available" news paper entry, if engine can be built. */ - if (!IsVehicleTypeDisabled(e->type, false)) { + if (!IsVehicleTypeDisabled(e->type, false) && (e->info.extra_flags & ExtraEngineFlags::NoNews) == ExtraEngineFlags::None) { SetDParam(0, GetEngineCategoryName(index)); SetDParam(1, index); AddNewsItem(STR_NEWS_NEW_VEHICLE_NOW_AVAILABLE_WITH_TYPE, NT_NEW_VEHICLES, NF_VEHICLE, NR_ENGINE, index); @@ -1076,11 +1131,13 @@ void EnginesMonthlyLoop() no_introduce_after = ConvertYMDToDate(_settings_game.vehicle.no_introduce_vehicles_after, 0, 1) - 1; } + bool refresh = false; for (Engine *e : Engine::Iterate()) { /* Age the vehicle */ if ((e->flags & ENGINE_AVAILABLE) && e->age != MAX_DAY) { e->age++; - CalcEngineReliability(e); + CalcEngineReliability(e, true); + refresh = true; } /* Do not introduce invalid engines */ @@ -1101,6 +1158,9 @@ void EnginesMonthlyLoop() /* Do not introduce new rail wagons */ if (IsWagon(e->index)) continue; + /* Engine has no preview */ + if ((e->info.extra_flags & ExtraEngineFlags::NoPreview) != ExtraEngineFlags::None) continue; + /* Show preview dialog to one of the companies. */ e->flags |= ENGINE_EXCLUSIVE_PREVIEW; e->preview_company = INVALID_COMPANY; @@ -1110,6 +1170,11 @@ void EnginesMonthlyLoop() InvalidateWindowClassesData(WC_BUILD_VEHICLE); // rebuild the purchase list (esp. when sorted by reliability) InvalidateWindowClassesData(WC_BUILD_VIRTUAL_TRAIN); + + if (refresh) { + SetWindowClassesDirty(WC_BUILD_VEHICLE); + SetWindowClassesDirty(WC_REPLACE_VEHICLE); + } } } diff --git a/src/engine_base.h b/src/engine_base.h index c2911b4863..6599ac9bae 100644 --- a/src/engine_base.h +++ b/src/engine_base.h @@ -24,6 +24,15 @@ struct WagonOverride { const SpriteGroup *group; }; +/** Flags used client-side in the purchase/autorenew engine list. */ +enum class EngineDisplayFlags : byte { + None = 0, ///< No flag set. + HasVariants = (1U << 0), ///< Set if engine has variants. + IsFolded = (1U << 1), ///< Set if display of variants should be folded (hidden). + Shaded = (1U << 2), ///< Set if engine should be masked. +}; +DECLARE_ENUM_AS_BIT_SET(EngineDisplayFlags) + typedef Pool EnginePool; extern EnginePool _engine_pool; @@ -53,6 +62,9 @@ struct Engine : EnginePool::PoolItem<&_engine_pool> { uint8 original_image_index; ///< Original vehicle image index, thus the image index of the overridden vehicle VehicleType type; ///< %Vehicle type, ie #VEH_ROAD, #VEH_TRAIN, etc. + EngineDisplayFlags display_flags; ///< NOSAVE client-side-only display flags for build engine list. + EngineID display_last_variant; ///< NOSAVE client-side-only last variant selected. + EngineInfo info; union { diff --git a/src/engine_func.h b/src/engine_func.h index 3cf11140f7..e8658312e1 100644 --- a/src/engine_func.h +++ b/src/engine_func.h @@ -26,7 +26,8 @@ extern const uint8 _engine_offsets[4]; bool IsEngineBuildable(EngineID engine, VehicleType type, CompanyID company); bool IsEngineRefittable(EngineID engine); void SetYearEngineAgingStops(); -void StartupOneEngine(Engine *e, Date aging_date, Date no_introduce_after_date); +void CalcEngineReliability(Engine *e, bool new_month); +void StartupOneEngine(Engine *e, Date aging_date, uint32 seed, Date no_introduce_after_date); uint GetTotalCapacityOfArticulatedParts(EngineID engine); diff --git a/src/engine_gui.h b/src/engine_gui.h index 2a38fcc45d..7a208f88b2 100644 --- a/src/engine_gui.h +++ b/src/engine_gui.h @@ -14,10 +14,23 @@ #include "sortlist_type.h" #include "gfx_type.h" #include "vehicle_type.h" +#include "engine_base.h" -typedef GUIList GUIEngineList; +struct GUIEngineListItem { + EngineID engine_id; ///< Engine to display in build purchase list + EngineID variant_id; ///< Variant group of the engine. + EngineDisplayFlags flags; ///< Flags for toggling/drawing (un)folded status and controlling indentation. + int8 indent; ///< Display indentation level. -typedef bool EngList_SortTypeFunction(const EngineID&, const EngineID&); ///< argument type for #EngList_Sort. + GUIEngineListItem(EngineID engine_id, EngineID variant_id, EngineDisplayFlags flags, int indent) : engine_id(engine_id), variant_id(variant_id), flags(flags), indent(indent) {} + + /* Used when searching list only by engine_id. */ + bool operator == (const EngineID &other) const { return this->engine_id == other; } +}; + +typedef GUIList GUIEngineList; + +typedef bool EngList_SortTypeFunction(const GUIEngineListItem&, const GUIEngineListItem&); ///< argument type for #EngList_Sort. void EngList_Sort(GUIEngineList *el, EngList_SortTypeFunction compare); void EngList_SortPartial(GUIEngineList *el, EngList_SortTypeFunction compare, uint begin, uint num_items); diff --git a/src/engine_type.h b/src/engine_type.h index 8d008c4586..1cdaf80d7a 100644 --- a/src/engine_type.h +++ b/src/engine_type.h @@ -126,6 +126,15 @@ struct RoadVehicleInfo { RoadType roadtype; ///< Road type }; +enum class ExtraEngineFlags : uint8 { + None = 0, + NoNews = (1U << 0), ///< No 'new vehicle' news will be generated. + NoPreview = (1U << 1), ///< No exclusive preview will be offered. + JoinPreview = (1U << 2), ///< Engine will join exclusive preview with variant parent. + SyncReliability = (1U << 3), ///< Engine reliability will be synced with variant parent. +}; +DECLARE_ENUM_AS_BIT_SET(ExtraEngineFlags); + /** * Information about a vehicle * @see table/engines.h @@ -145,6 +154,8 @@ struct EngineInfo { int8 retire_early; ///< Number of years early to retire vehicle StringID string_id; ///< Default name of engine uint16 cargo_age_period; ///< Number of ticks before carried cargo is aged. + EngineID variant_id; ///< Engine variant ID. If set, will be treated specially in purchase lists. + ExtraEngineFlags extra_flags; }; /** diff --git a/src/gfx.cpp b/src/gfx.cpp index ee2abe0d0e..d675f5e198 100644 --- a/src/gfx.cpp +++ b/src/gfx.cpp @@ -956,6 +956,21 @@ Dimension GetStringBoundingBox(StringID strid, FontSize start_fontsize) return GetStringBoundingBox(buffer, start_fontsize); } +/** + * Get maximum width of a list of strings. + * @param list List of strings, terminated with INVALID_STRING_ID. + * @param fontsize Font size to use. + * @return Width of longest string within the list. + */ +uint GetStringListWidth(const StringID *list, FontSize fontsize) +{ + uint width = 0; + for (const StringID *str = list; *str != INVALID_STRING_ID; str++) { + width = std::max(width, GetStringBoundingBox(*str, fontsize).width); + } + return width; +} + /** * Get the leading corner of a character in a single-line string relative * to the start of the string. diff --git a/src/gfx_func.h b/src/gfx_func.h index 85974f4d34..a6446cd583 100644 --- a/src/gfx_func.h +++ b/src/gfx_func.h @@ -161,6 +161,7 @@ static inline void GfxFillRect(const Rect &r, int colour, FillRectMode mode = FI Dimension GetStringBoundingBox(const char *str, FontSize start_fontsize = FS_NORMAL); Dimension GetStringBoundingBox(const std::string &str, FontSize start_fontsize = FS_NORMAL); Dimension GetStringBoundingBox(StringID strid, FontSize start_fontsize = FS_NORMAL); +uint GetStringListWidth(const StringID *list, FontSize fontsize = FS_NORMAL); int GetStringHeight(const char *str, int maxw, FontSize fontsize = FS_NORMAL); int GetStringHeight(StringID str, int maxw); int GetStringLineCount(StringID str, int maxw); diff --git a/src/group_gui.cpp b/src/group_gui.cpp index 0e4ec5e1e2..85dc52a31f 100644 --- a/src/group_gui.cpp +++ b/src/group_gui.cpp @@ -25,6 +25,7 @@ #include "company_base.h" #include "company_gui.h" #include "gui.h" +#include "gfx_func.h" #include "tbtr_template_gui_main.h" #include "newgrf_debug.h" @@ -77,17 +78,23 @@ static const NWidgetPart _nested_group_widgets[] = { /* right part */ NWidget(NWID_VERTICAL), NWidget(NWID_HORIZONTAL), - NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_GL_GROUP_BY_ORDER), SetMinimalSize(81, 12), SetDataTip(STR_STATION_VIEW_GROUP, STR_TOOLTIP_GROUP_ORDER), - NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GL_GROUP_BY_DROPDOWN), SetMinimalSize(167, 12), SetDataTip(0x0, STR_TOOLTIP_GROUP_ORDER), - NWidget(WWT_PANEL, COLOUR_GREY), SetMinimalSize(12, 12), SetResize(1, 0), EndContainer(), - EndContainer(), - NWidget(NWID_HORIZONTAL), - NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_GL_SORT_BY_ORDER), SetMinimalSize(81, 12), SetDataTip(STR_BUTTON_SORT_BY, STR_TOOLTIP_SORT_ORDER), - NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GL_SORT_BY_DROPDOWN), SetMinimalSize(167, 12), SetDataTip(0x0, STR_TOOLTIP_SORT_CRITERIA), - NWidget(NWID_SELECTION, INVALID_COLOUR, WID_GL_FILTER_BY_CARGO_SEL), - NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GL_FILTER_BY_CARGO), SetMinimalSize(167, 12), SetDataTip(STR_JUST_STRING, STR_TOOLTIP_FILTER_CRITERIA), + NWidget(NWID_VERTICAL), + NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_GL_GROUP_BY_ORDER), SetFill(1, 0), SetMinimalSize(0, 12), SetDataTip(STR_STATION_VIEW_GROUP, STR_TOOLTIP_GROUP_ORDER), + NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_GL_SORT_BY_ORDER), SetFill(1, 0), SetMinimalSize(0, 12), SetDataTip(STR_BUTTON_SORT_BY, STR_TOOLTIP_SORT_ORDER), + EndContainer(), + NWidget(NWID_VERTICAL), + NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GL_GROUP_BY_DROPDOWN), SetFill(1, 0), SetMinimalSize(0, 12), SetDataTip(0x0, STR_TOOLTIP_GROUP_ORDER), + NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GL_SORT_BY_DROPDOWN), SetFill(1, 0), SetMinimalSize(0, 12), SetDataTip(0x0, STR_TOOLTIP_SORT_CRITERIA), + EndContainer(), + NWidget(NWID_VERTICAL), + NWidget(WWT_PANEL, COLOUR_GREY), SetMinimalSize(0, 12), SetResize(1, 0), EndContainer(), + NWidget(NWID_HORIZONTAL), + NWidget(NWID_SELECTION, INVALID_COLOUR, WID_GL_FILTER_BY_CARGO_SEL), + NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GL_FILTER_BY_CARGO), SetMinimalSize(167, 12), SetDataTip(STR_JUST_STRING, STR_TOOLTIP_FILTER_CRITERIA), + EndContainer(), + NWidget(WWT_PANEL, COLOUR_GREY), SetMinimalSize(0, 12), SetResize(1, 0), EndContainer(), + EndContainer(), EndContainer(), - NWidget(WWT_PANEL, COLOUR_GREY), SetMinimalSize(12, 12), SetResize(1, 0), EndContainer(), EndContainer(), NWidget(NWID_HORIZONTAL), NWidget(WWT_MATRIX, COLOUR_GREY, WID_GL_LIST_VEHICLE), SetMinimalSize(248, 0), SetMatrixDataTip(1, 0, STR_NULL), SetResize(1, 1), SetFill(1, 0), SetScrollbar(WID_GL_LIST_VEHICLE_SCROLLBAR), @@ -482,6 +489,20 @@ public: size->height = 4 * resize->height; break; + case WID_GL_GROUP_BY_DROPDOWN: + size->width = GetStringListWidth(this->vehicle_group_by_names) + padding.width; + break; + + case WID_GL_SORT_BY_DROPDOWN: + size->width = GetStringListWidth(this->vehicle_group_none_sorter_names); + size->width = std::max(size->width, GetStringListWidth(this->vehicle_group_shared_orders_sorter_names)); + size->width += padding.width; + break; + + case WID_GL_FILTER_BY_CARGO: + size->width = GetStringListWidth(this->cargo_filter_texts) + padding.width; + break; + case WID_GL_MANAGE_VEHICLES_DROPDOWN: { Dimension d = this->GetActionDropdownSize(true, true, this->vli.vtype == VEH_TRAIN); d.height += padding.height; diff --git a/src/industry_cmd.cpp b/src/industry_cmd.cpp index f1f3082abd..ced00ed40d 100644 --- a/src/industry_cmd.cpp +++ b/src/industry_cmd.cpp @@ -2122,12 +2122,13 @@ CommandCost CmdBuildIndustry(TileIndex tile, DoCommandFlag flags, uint32 p1, uin Industry *ind = nullptr; if (deity_prospect || (_game_mode != GM_EDITOR && _current_company != OWNER_DEITY && _settings_game.construction.raw_industry_construction == 2 && indspec->IsRawIndustry())) { if (flags & DC_EXEC) { - /* Prospected industries are build as OWNER_TOWN to not e.g. be build on owned land of the founder */ - Backup cur_company(_current_company, OWNER_TOWN, FILE_LINE); /* Prospecting has a chance to fail, however we cannot guarantee that something can * be built on the map, so the chance gets lower when the map is fuller, but there * is nothing we can really do about that. */ - if (deity_prospect || Random() <= indspec->prospecting_chance) { + bool prospect_success = deity_prospect || Random() <= indspec->prospecting_chance; + if (prospect_success) { + /* Prospected industries are build as OWNER_TOWN to not e.g. be build on owned land of the founder */ + Backup cur_company(_current_company, OWNER_TOWN, FILE_LINE); for (int i = 0; i < 5000; i++) { /* We should not have more than one Random() in a function call * because parameter evaluation order is not guaranteed in the c++ standard @@ -2143,8 +2144,15 @@ CommandCost CmdBuildIndustry(TileIndex tile, DoCommandFlag flags, uint32 p1, uin } if (ret.Succeeded()) break; } + cur_company.Restore(); + } + if (ret.Failed()) { + if (prospect_success) { + ShowErrorMessage(STR_ERROR_CAN_T_PROSPECT_INDUSTRY, STR_ERROR_NO_SUITABLE_PLACES_FOR_PROSPECTING, WL_INFO); + } else { + ShowErrorMessage(STR_ERROR_CAN_T_PROSPECT_INDUSTRY, STR_ERROR_PROSPECTING_WAS_UNLUCKY, WL_INFO); + } } - cur_company.Restore(); } } else { size_t layout = GB(p1, 8, 8); diff --git a/src/intro_gui.cpp b/src/intro_gui.cpp index 001736a8f5..7e86c1e53c 100644 --- a/src/intro_gui.cpp +++ b/src/intro_gui.cpp @@ -380,7 +380,7 @@ static const NWidgetPart _nested_select_game_widgets[] = { NWidget(WWT_PANEL, COLOUR_BROWN), NWidget(NWID_SPACER), SetMinimalSize(0, 8), - /* 'generate game' and 'load game' buttons */ + /* 'New Game' and 'Load Game' buttons */ NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), NWidget(WWT_PUSHTXTBTN, COLOUR_ORANGE, WID_SGI_GENERATE_GAME), SetMinimalSize(158, 12), SetDataTip(STR_INTRO_NEW_GAME, STR_INTRO_TOOLTIP_NEW_GAME), SetPadding(0, 0, 0, 10), SetFill(1, 0), @@ -390,7 +390,7 @@ static const NWidgetPart _nested_select_game_widgets[] = { NWidget(NWID_SPACER), SetMinimalSize(0, 6), - /* 'play scenario' and 'play heightmap' buttons */ + /* 'Play Scenario' and 'Play Heightmap' buttons */ NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), NWidget(WWT_PUSHTXTBTN, COLOUR_ORANGE, WID_SGI_PLAY_SCENARIO), SetMinimalSize(158, 12), SetDataTip(STR_INTRO_PLAY_SCENARIO, STR_INTRO_TOOLTIP_PLAY_SCENARIO), SetPadding(0, 0, 0, 10), SetFill(1, 0), @@ -400,7 +400,7 @@ static const NWidgetPart _nested_select_game_widgets[] = { NWidget(NWID_SPACER), SetMinimalSize(0, 6), - /* 'edit scenario' and 'play multiplayer' buttons */ + /* 'Scenario Editor' and 'Multiplayer' buttons */ NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), NWidget(WWT_PUSHTXTBTN, COLOUR_ORANGE, WID_SGI_EDIT_SCENARIO), SetMinimalSize(158, 12), SetDataTip(STR_INTRO_SCENARIO_EDITOR, STR_INTRO_TOOLTIP_SCENARIO_EDITOR), SetPadding(0, 0, 0, 10), SetFill(1, 0), @@ -410,7 +410,7 @@ static const NWidgetPart _nested_select_game_widgets[] = { NWidget(NWID_SPACER), SetMinimalSize(0, 7), - /* climate selection buttons */ + /* Climate selection buttons */ NWidget(NWID_HORIZONTAL), NWidget(NWID_SPACER), SetMinimalSize(10, 0), SetFill(1, 0), NWidget(WWT_IMGBTN_2, COLOUR_ORANGE, WID_SGI_TEMPERATE_LANDSCAPE), SetMinimalSize(77, 55), @@ -439,7 +439,7 @@ static const NWidgetPart _nested_select_game_widgets[] = { EndContainer(), EndContainer(), - /* 'game options' and 'advanced settings' buttons */ + /* 'Game Options' and 'Settings' buttons */ NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), NWidget(WWT_PUSHTXTBTN, COLOUR_ORANGE, WID_SGI_OPTIONS), SetMinimalSize(158, 12), SetDataTip(STR_INTRO_GAME_OPTIONS, STR_INTRO_TOOLTIP_GAME_OPTIONS), SetPadding(0, 0, 0, 10), SetFill(1, 0), @@ -449,29 +449,35 @@ static const NWidgetPart _nested_select_game_widgets[] = { NWidget(NWID_SPACER), SetMinimalSize(0, 6), - /* 'AO settings', 'Game Script settings', and 'newgrf settings' buttons */ + /* 'AI Settings' and 'Game Script Settings' buttons */ NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), - NWidget(WWT_PUSHTXTBTN, COLOUR_ORANGE, WID_SGI_AI_SETTINGS), SetMinimalSize(105, 12), + NWidget(WWT_PUSHTXTBTN, COLOUR_ORANGE, WID_SGI_AI_SETTINGS), SetMinimalSize(158, 12), SetDataTip(STR_INTRO_AI_SETTINGS, STR_INTRO_TOOLTIP_AI_SETTINGS), SetPadding(0, 0, 0, 10), SetFill(1, 0), - NWidget(WWT_PUSHTXTBTN, COLOUR_ORANGE, WID_SGI_GS_SETTINGS), SetMinimalSize(106, 12), - SetDataTip(STR_INTRO_GAMESCRIPT_SETTINGS, STR_INTRO_TOOLTIP_GAMESCRIPT_SETTINGS), SetPadding(0, 0, 0, 0), SetFill(1, 0), - NWidget(WWT_PUSHTXTBTN, COLOUR_ORANGE, WID_SGI_GRF_SETTINGS), SetMinimalSize(105, 12), - SetDataTip(STR_INTRO_NEWGRF_SETTINGS, STR_INTRO_TOOLTIP_NEWGRF_SETTINGS), SetPadding(0, 10, 0, 0), SetFill(1, 0), + NWidget(WWT_PUSHTXTBTN, COLOUR_ORANGE, WID_SGI_GS_SETTINGS), SetMinimalSize(158, 12), + SetDataTip(STR_INTRO_GAMESCRIPT_SETTINGS, STR_INTRO_TOOLTIP_GAMESCRIPT_SETTINGS), SetPadding(0, 10, 0, 0), SetFill(1, 0), EndContainer(), NWidget(NWID_SPACER), SetMinimalSize(0, 6), - /* 'online content' and 'highscore' buttons */ + /* 'Check Online Content' and 'NewGRF Settings' buttons */ NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), NWidget(WWT_PUSHTXTBTN, COLOUR_ORANGE, WID_SGI_CONTENT_DOWNLOAD), SetMinimalSize(158, 12), SetDataTip(STR_INTRO_ONLINE_CONTENT, STR_INTRO_TOOLTIP_ONLINE_CONTENT), SetPadding(0, 0, 0, 10), SetFill(1, 0), - NWidget(WWT_PUSHTXTBTN, COLOUR_ORANGE, WID_SGI_HIGHSCORE), SetMinimalSize(158, 12), - SetDataTip(STR_INTRO_HIGHSCORE, STR_INTRO_TOOLTIP_HIGHSCORE), SetPadding(0, 10, 0, 0), SetFill(1, 0), + NWidget(WWT_PUSHTXTBTN, COLOUR_ORANGE, WID_SGI_GRF_SETTINGS), SetMinimalSize(158, 12), + SetDataTip(STR_INTRO_NEWGRF_SETTINGS, STR_INTRO_TOOLTIP_NEWGRF_SETTINGS), SetPadding(0, 10, 0, 0), SetFill(1, 0), + EndContainer(), + + NWidget(NWID_SPACER), SetMinimalSize(0, 6), + + /* 'Highscore Table' button */ + NWidget(NWID_HORIZONTAL), + NWidget(WWT_PUSHTXTBTN, COLOUR_ORANGE, WID_SGI_HIGHSCORE), SetMinimalSize(316, 12), + SetDataTip(STR_INTRO_HIGHSCORE, STR_INTRO_TOOLTIP_HIGHSCORE), SetPadding(0, 10, 0, 10), SetFill(1, 0), EndContainer(), NWidget(NWID_SPACER), SetMinimalSize(0, 6), - /* 'exit program' button */ + /* 'Exit' button */ NWidget(NWID_HORIZONTAL), NWidget(NWID_SPACER), SetFill(1, 0), NWidget(WWT_PUSHTXTBTN, COLOUR_ORANGE, WID_SGI_EXIT), SetMinimalSize(128, 12), diff --git a/src/lang/english.txt b/src/lang/english.txt index 7393d989b6..d0d2fb9c6d 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -3812,6 +3812,8 @@ STR_FOUND_TOWN_RANDOM_TOWN_BUTTON :{BLACK}Random T STR_FOUND_TOWN_RANDOM_TOWN_TOOLTIP :{BLACK}Found town in random location STR_FOUND_TOWN_MANY_RANDOM_TOWNS :{BLACK}Many random towns STR_FOUND_TOWN_RANDOM_TOWNS_TOOLTIP :{BLACK}Cover the map with randomly placed towns +STR_FOUND_TOWN_EXPAND_ALL_TOWNS :{BLACK}Expand all towns +STR_FOUND_TOWN_EXPAND_ALL_TOWNS_TOOLTIP :{BLACK}Make all towns grow slightly STR_FOUND_TOWN_NAME_TITLE :{YELLOW}Town name: STR_FOUND_TOWN_NAME_EDITOR_TITLE :{BLACK}Enter town name @@ -5906,26 +5908,22 @@ STR_TIMETABLE_STARTING_DATE :{BLACK}Start da STR_TIMETABLE_STARTING_DATE_TOOLTIP :{BLACK}Select a date as starting point of this timetable. Ctrl+Click distributes all vehicles sharing this order evenly from the given date based on their relative order, if the order is completely timetabled STR_TIMETABLE_CHANGE_TIME :{BLACK}Change Time -STR_TIMETABLE_WAIT_TIME_TOOLTIP :{BLACK}Change the amount of time that the highlighted order should take -STR_TIMETABLE_WAIT_TIME_TOOLTIP_EXTRA :{BLACK}{STRING} (Ctrl+Click sets the time for all orders) +STR_TIMETABLE_WAIT_TIME_TOOLTIP :{BLACK}Change the amount of time that the highlighted order should take. Ctrl+Click sets the time for all orders STR_TIMETABLE_CLEAR_TIME :{BLACK}Clear Time -STR_TIMETABLE_CLEAR_TIME_TOOLTIP :{BLACK}Clear the amount of time for the highlighted order -STR_TIMETABLE_CLEAR_TIME_TOOLTIP_EXTRA :{BLACK}{STRING} (Ctrl+Click clears the time for all orders) +STR_TIMETABLE_CLEAR_TIME_TOOLTIP :{BLACK}Clear the amount of time for the highlighted order. Ctrl+Click clears the time for all orders STR_TIMETABLE_CHANGE_SPEED :{BLACK}Change Speed Limit -STR_TIMETABLE_CHANGE_SPEED_TOOLTIP :{BLACK}Change the maximum travel speed of the highlighted order -STR_TIMETABLE_CHANGE_SPEED_TOOLTIP_EXTRA :{BLACK}{STRING} (Ctrl+Click sets the speed for all orders) +STR_TIMETABLE_CHANGE_SPEED_TOOLTIP :{BLACK}Change the maximum travel speed of the highlighted order. Ctrl+Click sets the speed for all orders STR_TIMETABLE_CLEAR_SPEED :{BLACK}Clear Speed Limit -STR_TIMETABLE_CLEAR_SPEED_TOOLTIP :{BLACK}Clear the maximum travel speed of the highlighted order -STR_TIMETABLE_CLEAR_SPEED_TOOLTIP_EXTRA :{BLACK}{STRING} (Ctrl+Click clears the speed for all orders) +STR_TIMETABLE_CLEAR_SPEED_TOOLTIP :{BLACK}Clear the maximum travel speed of the highlighted order. Ctrl+Click clears the speed for all orders STR_TIMETABLE_RESET_LATENESS :{BLACK}Reset Late Counter STR_TIMETABLE_RESET_LATENESS_TOOLTIP :{BLACK}Reset the lateness counter, so the vehicle will be on time STR_TIMETABLE_AUTOFILL :{BLACK}Autofill -STR_TIMETABLE_AUTOFILL_TOOLTIP :{BLACK}Fill the timetable automatically with the values from the next journey (Ctrl+Click to try to keep waiting times) +STR_TIMETABLE_AUTOFILL_TOOLTIP :{BLACK}Fill the timetable automatically with the values from the next journey. Ctrl+Click to try to keep waiting times STR_TIMETABLE_AUTOMATE :{BLACK}Automate STR_TIMETABLE_AUTOMATE_TOOLTIP :{BLACK}Manage the timetables automatically by updating the values for each journey @@ -6291,6 +6289,7 @@ STR_ERROR_TOO_MANY_INDUSTRIES :{WHITE}... too STR_ERROR_CAN_T_GENERATE_INDUSTRIES :{WHITE}Can't generate industries... STR_ERROR_CAN_T_BUILD_HERE :{WHITE}Can't build {STRING} here... STR_ERROR_CAN_T_CONSTRUCT_THIS_INDUSTRY :{WHITE}Can't construct this industry type here... +STR_ERROR_CAN_T_PROSPECT_INDUSTRY :{WHITE}Can't prospect industry... STR_ERROR_INDUSTRY_TOO_CLOSE :{WHITE}... too close to another industry STR_ERROR_MUST_FOUND_TOWN_FIRST :{WHITE}... must found town first STR_ERROR_ONLY_ONE_ALLOWED_PER_TOWN :{WHITE}... only one allowed per town @@ -6305,6 +6304,8 @@ STR_ERROR_FOREST_CAN_ONLY_BE_PLANTED :{WHITE}... fore STR_ERROR_CAN_ONLY_BE_BUILT_ABOVE_SNOW_LINE :{WHITE}... can only be built above the snow-line STR_ERROR_CAN_ONLY_BE_BUILT_BELOW_SNOW_LINE :{WHITE}... can only be built below the snow-line +STR_ERROR_PROSPECTING_WAS_UNLUCKY :{WHITE}The funding failed to prospect due to bad luck; try again +STR_ERROR_NO_SUITABLE_PLACES_FOR_PROSPECTING :{WHITE}There were no suitable places to prospect for this industry STR_ERROR_NO_SUITABLE_PLACES_FOR_INDUSTRIES :{WHITE}There were no suitable places for '{STRING}' industries STR_ERROR_NO_SUITABLE_PLACES_FOR_INDUSTRIES_EXPLANATION :{WHITE}Change the map generation parameters to get a better map diff --git a/src/lang/finnish.txt b/src/lang/finnish.txt index f25c7a023d..b25163d83c 100644 --- a/src/lang/finnish.txt +++ b/src/lang/finnish.txt @@ -1340,7 +1340,7 @@ STR_CONFIG_SETTING_NONSTOP_BY_DEFAULT :Uudet käskyt o STR_CONFIG_SETTING_NONSTOP_BY_DEFAULT_HELPTEXT :Normaalisti kulkuneuvo pysähtyy jokaisella läpikulkemallaan asemalla. Mikäli tämä asetus on käytössä kulkuneuvot eivät pysähdy ajaessaan asemien läpi. Huomioi, että tämä asetus määrittää oletusarvoisen toiminnon uusille kulkuneuvoille. Asetusta voidaan muuttaa erikseen kunkin kulkuneuvon kohdalla STR_CONFIG_SETTING_STOP_LOCATION :Uudet junien käskyt pysäyttävät junan aseman {STRING} -STR_CONFIG_SETTING_STOP_LOCATION_HELPTEXT :Paikka, johon juna pysähtyy oletuksena asemalla. ”Alkuun” tarkoittaa, että junan viimeinen vaunu pysähtyy laiturin alkuun; ”keskelle” tarkoittaa junan pysähtymistä keskelle laituria; ja ”loppuun” tarkoittaa, että veturi pysähtyy laiturin päähän. Huomaa, että tämä asetus määrittää vain oletusarvon uusille määräyksille. Yksittäisten määräysten kohdalla käyttäytymistä voi muuttaa tästä asetuksesta huolimatta +STR_CONFIG_SETTING_STOP_LOCATION_HELPTEXT :Paikka, johon juna pysähtyy oletuksena asemalla. ”Alkuun” tarkoittaa, että junan viimeinen vaunu pysähtyy laiturin alkuun; ”keskelle” tarkoittaa junan pysähtymistä keskelle laituria; ja ”loppuun” tarkoittaa, että veturi pysähtyy laiturin päähän. Huomaa, että tämä asetus määrittää vain oletusarvon uusille käskyille. Yksittäisten käskyjen kohdalla käyttäytymistä voi muuttaa tästä asetuksesta huolimatta ###length 3 STR_CONFIG_SETTING_STOP_LOCATION_NEAR_END :alkuun STR_CONFIG_SETTING_STOP_LOCATION_MIDDLE :keskelle @@ -1402,7 +1402,7 @@ STR_CONFIG_SETTING_WARN_LOST_VEHICLE :Varoita, jos ku STR_CONFIG_SETTING_WARN_LOST_VEHICLE_HELPTEXT :Lähetä viesti, jos kulkuneuvo ei löydä reittiä määränpäähänsä STR_CONFIG_SETTING_ORDER_REVIEW :Tarkista kulkuneuvojen pysähdykset: {STRING} -STR_CONFIG_SETTING_ORDER_REVIEW_HELPTEXT :Mikäli käytössä, kulkuneuvojen määräykset tarkistetaan väliajoin ja havaituista ongelmista ilmoitetaan uutisviestillä +STR_CONFIG_SETTING_ORDER_REVIEW_HELPTEXT :Mikäli käytössä, kulkuneuvojen käskyjä tarkastetaan väliajoin, ja havaituista ongelmista ilmoitetaan uutisviestillä ###length 3 STR_CONFIG_SETTING_ORDER_REVIEW_OFF :Ei STR_CONFIG_SETTING_ORDER_REVIEW_EXDEPOT :Kyllä, mutta ei pysäytetyille @@ -2863,6 +2863,8 @@ STR_FOUND_TOWN_RANDOM_TOWN_BUTTON :{BLACK}Satunnai STR_FOUND_TOWN_RANDOM_TOWN_TOOLTIP :{BLACK}Perusta kunta satunnaiseen paikkaan STR_FOUND_TOWN_MANY_RANDOM_TOWNS :{BLACK}Monta satunnaista kuntaa STR_FOUND_TOWN_RANDOM_TOWNS_TOOLTIP :{BLACK}Täytä kartta satunnaisesti sijoitetuilla kunnilla +STR_FOUND_TOWN_EXPAND_ALL_TOWNS :{BLACK}Laajenna kaikkia kuntia +STR_FOUND_TOWN_EXPAND_ALL_TOWNS_TOOLTIP :{BLACK}Kasvata kaikkia kuntia hieman STR_FOUND_TOWN_NAME_TITLE :{YELLOW}Kunnan nimi: STR_FOUND_TOWN_NAME_EDITOR_TITLE :{BLACK}Syötä kunnan nimi @@ -4528,22 +4530,22 @@ STR_TIMETABLE_STARTING_DATE :{BLACK}Aloitusp STR_TIMETABLE_STARTING_DATE_TOOLTIP :{BLACK}Valitse päivämäärä aikataulun aloitusajankohdaksi. Ctrl+napsautus levittää kaikki tämän käskyjoukon jakavat kulkuneuvot tasaisesti niiden keskinäisen järjestyksen mukaan, mikäli käskyjoukko on kokonaan aikataulutettu STR_TIMETABLE_CHANGE_TIME :{BLACK}Muuta aikaa -STR_TIMETABLE_WAIT_TIME_TOOLTIP :{BLACK}Aseta kuinka kauan käskyn tulisi kestää +STR_TIMETABLE_WAIT_TIME_TOOLTIP :{BLACK}Muuta aikaa, jonka valitun käskyn tulisi kestää. Ctrl+napsautus asettaa keston kaikille käskyille STR_TIMETABLE_CLEAR_TIME :{BLACK}Nollaa aika -STR_TIMETABLE_CLEAR_TIME_TOOLTIP :{BLACK}Nollaa tämän rivin aika +STR_TIMETABLE_CLEAR_TIME_TOOLTIP :{BLACK}Nollaa valitun käskyn keston. Ctrl+napsautus nollaa kaikkien käskyjen kestot STR_TIMETABLE_CHANGE_SPEED :{BLACK}Muuta nopeusrajoitusta -STR_TIMETABLE_CHANGE_SPEED_TOOLTIP :{BLACK}Muuta valitun määräyksen suurinta sallittua nopeutta +STR_TIMETABLE_CHANGE_SPEED_TOOLTIP :{BLACK}Muuta suurinta sallittua nopeutta valitulle käskylle. Ctrl+napsautus asettaa nopeusrajoituksen kaikille käskyille STR_TIMETABLE_CLEAR_SPEED :{BLACK}Tyhjennä nopeusrajoitus -STR_TIMETABLE_CLEAR_SPEED_TOOLTIP :{BLACK}Tyhjennä valitun määräyksen suurin sallittu nopeus +STR_TIMETABLE_CLEAR_SPEED_TOOLTIP :{BLACK}Poista suurin sallittu nopeus valitulta käskyltä. Ctrl+napsautus poistaa kaikkien käskyjen nopeusrajoitukset STR_TIMETABLE_RESET_LATENESS :{BLACK}Nollaa myöhästymislaskuri STR_TIMETABLE_RESET_LATENESS_TOOLTIP :{BLACK}Nollaa myöhästymislaskuri, jotta vaunu olisi taas aikataulussa STR_TIMETABLE_AUTOFILL :{BLACK}Automaattinen -STR_TIMETABLE_AUTOFILL_TOOLTIP :{BLACK}Täytä aikataulu automaattisesti seuraavan matkan arvoilla (Ctrl+napsautus: yritä säilyttää odotusajat) +STR_TIMETABLE_AUTOFILL_TOOLTIP :{BLACK}Täytä aikataulu automaattisesti seuraavan matkan arvoilla. Ctrl+napsautus: yritä säilyttää odotusajat STR_TIMETABLE_EXPECTED :{BLACK}Odotettu STR_TIMETABLE_SCHEDULED :{BLACK}Aikataulu diff --git a/src/lang/galician.txt b/src/lang/galician.txt index 4caeafa3ae..244a6f8f66 100644 --- a/src/lang/galician.txt +++ b/src/lang/galician.txt @@ -4477,16 +4477,16 @@ STR_TIMETABLE_STARTING_DATE :{BLACK}Data com STR_TIMETABLE_STARTING_DATE_TOOLTIP :{BLACK}Selecciona unha data coma punto de inicio para este horario. Ctrl + click distribúe uniformemente tódolos vehículos que compartan esta orde baséandose na súa orde relativa. se a orde está completamente tabulada nos horarios STR_TIMETABLE_CHANGE_TIME :{BLACK}Cambiar Tempo -STR_TIMETABLE_WAIT_TIME_TOOLTIP :{BLACK}Cambiar o tempo que debería levar a orde seleccionada +STR_TIMETABLE_WAIT_TIME_TOOLTIP :{BLACK}Cambiar o tempo que debería levar a orde seleccionada (Ctrl+Click fixa a hora para todas as ordes) STR_TIMETABLE_CLEAR_TIME :{BLACK}Borrar tempo -STR_TIMETABLE_CLEAR_TIME_TOOLTIP :{BLACK}Borrar o tempo para a orde seleccionada +STR_TIMETABLE_CLEAR_TIME_TOOLTIP :{BLACK}Borrar o tempo para a orde seleccionada (Ctrl+Click despexa a hora para todas as ordes) STR_TIMETABLE_CHANGE_SPEED :{BLACK}Cambiar o límite de velocidade -STR_TIMETABLE_CHANGE_SPEED_TOOLTIP :{BLACK}Cambiar a velocidade máxima da orde seleccionada +STR_TIMETABLE_CHANGE_SPEED_TOOLTIP :{BLACK}Cambiar a velocidade máxima da orde seleccionada (Ctrl+Click fixa a velocidade para todas as ordes) STR_TIMETABLE_CLEAR_SPEED :{BLACK}Borrar o límite de velocidade -STR_TIMETABLE_CLEAR_SPEED_TOOLTIP :{BLACK}Borrar a velocidade máxima da orde seleccionada +STR_TIMETABLE_CLEAR_SPEED_TOOLTIP :{BLACK}Borrar a velocidade máxima da orde seleccionada (Ctrl+Click despexa a velocidade para todas as ordes) STR_TIMETABLE_RESET_LATENESS :{BLACK}Reiniciar atraso STR_TIMETABLE_RESET_LATENESS_TOOLTIP :{BLACK}Reiniciar o contador de atraso, para que o vehículo vaia en hora @@ -6671,10 +6671,6 @@ STR_TIMETABLE_MINUTES_LONG :{COMMA}{NBSP}mi STR_TIMETABLE_HOURS :{COMMA}{NBSP}hora{P "" s} STR_TIMETABLE_HOURS_MINUTES :{COMMA}{NBSP}hora{P "" s} e {COMMA}{NBSP}minuto{P "" s} STR_TIMETABLE_LEFTOVER_TICKS :{STRING} + {COMMA} tick{P "" s} -STR_TIMETABLE_WAIT_TIME_TOOLTIP_EXTRA :{BLACK}{STRING} (Ctrl+Click fixa a hora para todas as ordes) -STR_TIMETABLE_CLEAR_TIME_TOOLTIP_EXTRA :{BLACK}{STRING} (Ctrl+Click despexa a hora para todas as ordes) -STR_TIMETABLE_CHANGE_SPEED_TOOLTIP_EXTRA :{BLACK}{STRING} (Ctrl+Click fixa a velocidade para todas as ordes) -STR_TIMETABLE_CLEAR_SPEED_TOOLTIP_EXTRA :{BLACK}{STRING} (Ctrl+Click despexa a velocidade para todas as ordes) STR_TIMETABLE_AUTOMATE :{BLACK}Automatizar STR_TIMETABLE_AUTOMATE_TOOLTIP :{BLACK}Xestiona os horarios automáticamente actualizando os valores para cada viaxe STR_TIMETABLE_AUTO_SEPARATION :{BLACK}Auto Separation diff --git a/src/lang/german.txt b/src/lang/german.txt index 37c664d82b..eecb920d39 100644 --- a/src/lang/german.txt +++ b/src/lang/german.txt @@ -5785,20 +5785,16 @@ STR_TIMETABLE_STARTING_DATE :{BLACK}Anfangsd STR_TIMETABLE_STARTING_DATE_TOOLTIP :{BLACK}Wähle ein Anfangsdatum für diesen Fahrplan aus. Mit Strg+Klick wird bei allen Fahrzeugen, die nach demselben Fahrplan unterwegs sind, ein zeitlich versetztes Anfangsdatum gesetzt, so dass die Abstände zwischen den einzelnen Fahrzeugen immer gleich sind. Dazu muss der Fahrplan erst komplett erfasst worden sein. STR_TIMETABLE_CHANGE_TIME :{BLACK}Zeit ändern -STR_TIMETABLE_WAIT_TIME_TOOLTIP :{BLACK}Zeitrahmen für den markierten Auftrag ändern -STR_TIMETABLE_WAIT_TIME_TOOLTIP_EXTRA :{BLACK}{STRING} (Strg+Klick setzt die Zeit für alle Aufträge) +STR_TIMETABLE_WAIT_TIME_TOOLTIP :{BLACK}Zeitrahmen für den markierten Auftrag ändern (Strg+Klick setzt die Zeit für alle Aufträge) STR_TIMETABLE_CLEAR_TIME :{BLACK}Zeit löschen -STR_TIMETABLE_CLEAR_TIME_TOOLTIP :{BLACK}Zeitrahmen für den markierten Auftrag löschen -STR_TIMETABLE_CLEAR_TIME_TOOLTIP_EXTRA :{BLACK}{STRING} (Strg+Klick löscht die Zeit für alle Aufträge) +STR_TIMETABLE_CLEAR_TIME_TOOLTIP :{BLACK}Zeitrahmen für den markierten Auftrag löschen (Strg+Klick löscht die Zeit für alle Aufträge) STR_TIMETABLE_CHANGE_SPEED :{BLACK}Tempolimit ändern -STR_TIMETABLE_CHANGE_SPEED_TOOLTIP :{BLACK}Tempolimit beim Ausführen des ausgewählten Auftrags ändern -STR_TIMETABLE_CHANGE_SPEED_TOOLTIP_EXTRA :{BLACK}{STRING} (Strg+Klick setzt das Tempolimit für alle Aufträge) +STR_TIMETABLE_CHANGE_SPEED_TOOLTIP :{BLACK}Tempolimit beim Ausführen des ausgewählten Auftrags ändern (Strg+Klick setzt das Tempolimit für alle Aufträge) STR_TIMETABLE_CLEAR_SPEED :{BLACK}Tempolimit löschen -STR_TIMETABLE_CLEAR_SPEED_TOOLTIP :{BLACK}Tempolimit für das Ausführen des ausgewählten Auftrags löschen -STR_TIMETABLE_CLEAR_SPEED_TOOLTIP_EXTRA :{BLACK}{STRING} (Strg+Klick löscht das Tempolimit für alle Aufträge) +STR_TIMETABLE_CLEAR_SPEED_TOOLTIP :{BLACK}Tempolimit für das Ausführen des ausgewählten Auftrags löschen (Strg+Klick löscht das Tempolimit für alle Aufträge) STR_TIMETABLE_RESET_LATENESS :{BLACK}Verspätung löschen STR_TIMETABLE_RESET_LATENESS_TOOLTIP :{BLACK}Verspätungsmelder zurücksetzen (das Fahrzeug gilt dann als pünktlich). diff --git a/src/lang/italian.txt b/src/lang/italian.txt index 45a5f95b30..e25820e98d 100644 --- a/src/lang/italian.txt +++ b/src/lang/italian.txt @@ -2906,6 +2906,8 @@ STR_FOUND_TOWN_RANDOM_TOWN_BUTTON :{BLACK}Città c STR_FOUND_TOWN_RANDOM_TOWN_TOOLTIP :{BLACK}Fonda una città in una posizione casuale STR_FOUND_TOWN_MANY_RANDOM_TOWNS :{BLACK}Alcune città casuali STR_FOUND_TOWN_RANDOM_TOWNS_TOOLTIP :{BLACK}Copre la mappa con città posizionate casualmente +STR_FOUND_TOWN_EXPAND_ALL_TOWNS :{BLACK}Espandi tutte le città +STR_FOUND_TOWN_EXPAND_ALL_TOWNS_TOOLTIP :{BLACK}Fa crescere leggermente tutte le città STR_FOUND_TOWN_NAME_TITLE :{YELLOW}Nome città: STR_FOUND_TOWN_NAME_EDITOR_TITLE :{BLACK}Inserire il nome della città @@ -3386,7 +3388,10 @@ STR_SPRITE_ALIGNER_SPRITE_TOOLTIP :{BLACK}Rapprese STR_SPRITE_ALIGNER_MOVE_TOOLTIP :{BLACK}Sposta lo sprite, cambiando gli spiazzamenti X e Y. CTRL+clic sposta lo sprite di otto unità alla volta ###length 2 +STR_SPRITE_ALIGNER_CENTRE_OFFSET :{BLACK}Spiazzamento del centro +STR_SPRITE_ALIGNER_CENTRE_SPRITE :{BLACK}Sprite centrato +STR_SPRITE_ALIGNER_CROSSHAIR :{BLACK}Mirino STR_SPRITE_ALIGNER_RESET_BUTTON :{BLACK}Reimposta posizione relativa STR_SPRITE_ALIGNER_RESET_TOOLTIP :{BLACK}Reimposta gli spiazzamenti relativi attuali @@ -4567,22 +4572,22 @@ STR_TIMETABLE_STARTING_DATE :{BLACK}Data ini STR_TIMETABLE_STARTING_DATE_TOOLTIP :{BLACK}Seleziona una data come punto di partenza della tabella oraria. Ctrl+click distribuisce tutti i veicoli che condividono questo ordine in modo uniforme dalla data indicata in base al loro ordine relativo, se l'ordine è completamente programmato. STR_TIMETABLE_CHANGE_TIME :{BLACK}Cambia tempo -STR_TIMETABLE_WAIT_TIME_TOOLTIP :{BLACK}Cambia la quantità di tempo che dovrebbe essere impiegata per l'ordine selezionato +STR_TIMETABLE_WAIT_TIME_TOOLTIP :{BLACK}Cambia la quantità di tempo che dovrebbe essere impiegata per l'ordine selezionato. CTRL+clic imposta il tempo di tutti gli ordini STR_TIMETABLE_CLEAR_TIME :{BLACK}Elimina tempo -STR_TIMETABLE_CLEAR_TIME_TOOLTIP :{BLACK}Elimina l'impostazione della quantità di tempo per l'ordine selezionato +STR_TIMETABLE_CLEAR_TIME_TOOLTIP :{BLACK}Elimina l'impostazione della quantità di tempo per l'ordine selezionato. CTRL+clic la rimuove da tutti gli ordini STR_TIMETABLE_CHANGE_SPEED :{BLACK}Cambia limite di velocità -STR_TIMETABLE_CHANGE_SPEED_TOOLTIP :{BLACK}Cambia l'impostazione del limite di velocità per l'ordine selezionato +STR_TIMETABLE_CHANGE_SPEED_TOOLTIP :{BLACK}Cambia l'impostazione del limite di velocità per l'ordine selezionato. CTRL+clic lo imposta per tutti gli ordini STR_TIMETABLE_CLEAR_SPEED :{BLACK}Elimina limite di velocità -STR_TIMETABLE_CLEAR_SPEED_TOOLTIP :{BLACK}Elimina l'impostazione del limite di velocità per l'ordine selezionato +STR_TIMETABLE_CLEAR_SPEED_TOOLTIP :{BLACK}Elimina l'impostazione del limite di velocità per l'ordine selezionato. CTRL+clic rimuove la velocità da tutti gli ordini STR_TIMETABLE_RESET_LATENESS :{BLACK}Azzera ritardo STR_TIMETABLE_RESET_LATENESS_TOOLTIP :{BLACK}Azzera il contatore del ritardo, in modo che il veicolo sia considerato in orario STR_TIMETABLE_AUTOFILL :{BLACK}Auto -STR_TIMETABLE_AUTOFILL_TOOLTIP :{BLACK}Riempie automaticamente la tabella oraria con i tempi del prossimo viaggio (CTRL+clic per cercare di mantenere i tempi di attesa) +STR_TIMETABLE_AUTOFILL_TOOLTIP :{BLACK}Riempie automaticamente la tabella oraria con i tempi del prossimo viaggio. CTRL+clic per cercare di mantenere i tempi di attesa STR_TIMETABLE_EXPECTED :{BLACK}Orari attesi STR_TIMETABLE_SCHEDULED :{BLACK}Orari programmati diff --git a/src/lang/korean.txt b/src/lang/korean.txt index f8b57320bb..dc9f884734 100644 --- a/src/lang/korean.txt +++ b/src/lang/korean.txt @@ -5908,20 +5908,16 @@ STR_TIMETABLE_STARTING_DATE :{BLACK}시작 STR_TIMETABLE_STARTING_DATE_TOOLTIP :{BLACK}이 시간표의 시작 날짜를 선택하세요. CTRL+클릭하면, 시간표가 모두 작성되어 있다는 가정 하에, 주어진 경로를 기반으로 설정한 날짜부터 이 경로를 공유하는 모든 차량을 균등하게 출발시킵니다 STR_TIMETABLE_CHANGE_TIME :{BLACK}시간값 변경 -STR_TIMETABLE_WAIT_TIME_TOOLTIP :{BLACK}선택한 경로에서 소요되는 시간 값을 변경합니다 -STR_TIMETABLE_WAIT_TIME_TOOLTIP_EXTRA :{BLACK}{STRING} (CTRL+클릭하면 모든 경로의 시간을 설정합니다) +STR_TIMETABLE_WAIT_TIME_TOOLTIP :{BLACK}선택한 경로에서 소요되는 시간 값을 변경합니다 (CTRL+클릭하면 모든 경로의 시간을 설정합니다) STR_TIMETABLE_CLEAR_TIME :{BLACK}시간값 초기화 -STR_TIMETABLE_CLEAR_TIME_TOOLTIP :{BLACK}선택한 경로에서 소요되는 시간 값을 초기화합니다 -STR_TIMETABLE_CLEAR_TIME_TOOLTIP_EXTRA :{BLACK}{STRING} (CTRL+클릭하면 모든 경로의 시간을 초기화합니다) +STR_TIMETABLE_CLEAR_TIME_TOOLTIP :{BLACK}선택한 경로에서 소요되는 시간 값을 초기화합니다 (CTRL+클릭하면 모든 경로의 시간을 초기화합니다) STR_TIMETABLE_CHANGE_SPEED :{BLACK}속력 제한 -STR_TIMETABLE_CHANGE_SPEED_TOOLTIP :{BLACK}선택한 경로의 최대 여행 속력을 제한합니다 -STR_TIMETABLE_CHANGE_SPEED_TOOLTIP_EXTRA :{BLACK}{STRING} (CTRL+클릭하면 모든 경로의 속력을 설정합니다) +STR_TIMETABLE_CHANGE_SPEED_TOOLTIP :{BLACK}선택한 경로의 최대 여행 속력을 제한합니다 (CTRL+클릭하면 모든 경로의 속력을 설정합니다) STR_TIMETABLE_CLEAR_SPEED :{BLACK}속력 제한값 초기화 -STR_TIMETABLE_CLEAR_SPEED_TOOLTIP :{BLACK}선택한 경로의 최대 여행 속력 제한값을 초기화합니다 -STR_TIMETABLE_CLEAR_SPEED_TOOLTIP_EXTRA :{BLACK}{STRING} (CTRL+클릭하면 모든 경로의 속력을 초기화합니다) +STR_TIMETABLE_CLEAR_SPEED_TOOLTIP :{BLACK}선택한 경로의 최대 여행 속력 제한값을 초기화합니다 (CTRL+클릭하면 모든 경로의 속력을 초기화합니다) STR_TIMETABLE_RESET_LATENESS :{BLACK}지연 시간 초기화 STR_TIMETABLE_RESET_LATENESS_TOOLTIP :{BLACK}이 차량의 지연 시간값을 초기화하여, 정시운행 상태로 바꿉니다 diff --git a/src/lang/portuguese.txt b/src/lang/portuguese.txt index c9628f318b..1b5cb9cfeb 100644 --- a/src/lang/portuguese.txt +++ b/src/lang/portuguese.txt @@ -2866,6 +2866,8 @@ STR_FOUND_TOWN_RANDOM_TOWN_BUTTON :{BLACK}Localida STR_FOUND_TOWN_RANDOM_TOWN_TOOLTIP :{BLACK}Fundar uma localidade num local aleatório STR_FOUND_TOWN_MANY_RANDOM_TOWNS :{BLACK}Várias localidades aleatórias STR_FOUND_TOWN_RANDOM_TOWNS_TOOLTIP :{BLACK}Cobrir o mapa com localidades colocadas aleatoriamente +STR_FOUND_TOWN_EXPAND_ALL_TOWNS :{BLACK}Expandir todas as localidades +STR_FOUND_TOWN_EXPAND_ALL_TOWNS_TOOLTIP :{BLACK}Fazer com que todas as localidades cresçam ligeiramente STR_FOUND_TOWN_NAME_TITLE :{YELLOW}Nome da localidade: STR_FOUND_TOWN_NAME_EDITOR_TITLE :{BLACK}Introduza o nome da localidade @@ -4421,7 +4423,7 @@ STR_ORDER_GO_TO_NEAREST_DEPOT :Ir para o depó STR_ORDER_GO_TO_NEAREST_HANGAR :Ir para o hangar mais próximo STR_ORDER_CONDITIONAL :Saltar ordem condicional STR_ORDER_SHARE :Partilhar ordens -STR_ORDERS_GO_TO_TOOLTIP :{BLACK}Inserir nova ordem antes da ordem seleccionada, ou adicionar ao fim da lista. Ctrl torna em 'encher' as ordens em estações, em 'sem parar' as ordens de pontos de passagem e em 'serviço' as ordens em depósitos. 'Ordens Partilhadas' ou Ctrl permite que este veículos partilhe ordens com o veículo escolhido. Clicando em um veículo de copia as ordens desse veículo +STR_ORDERS_GO_TO_TOOLTIP :{BLACK}Inserir nova ordem antes da ordem selecionada, ou adicionar ao fim da lista. Ctrl torna as ordens de estações em 'encher completamente qualquer carga'; as ordens em pontos de passagem 'sem parar'; e ordens de depósitos 'serviço'. 'Partilhar ordens' ou Ctrl permite que este veículo partilhe ordens com o veículo selecionado. Clicar num veículo copia as ordens desse veículo. Uma ordem para depósito desativa a manutenção programada (serviço) do veículo. STR_ORDERS_VEH_WITH_SHARED_ORDERS_LIST_TOOLTIP :{BLACK}Mostra todos os veículos que seguem este mesmo trajecto @@ -4531,22 +4533,22 @@ STR_TIMETABLE_STARTING_DATE :{BLACK}Data de STR_TIMETABLE_STARTING_DATE_TOOLTIP :{BLACK}Selecione uma data como ponto de partida deste horário. Ctrl+Clique distribui uniformemente todos os veiculos partilhando esta ordem pela sua ordem relativa, se a ordem for completamente calendarizada STR_TIMETABLE_CHANGE_TIME :{BLACK}Mudar Tempo -STR_TIMETABLE_WAIT_TIME_TOOLTIP :{BLACK}Muda o espaço de tempo que a ordem seleccionada deve durar +STR_TIMETABLE_WAIT_TIME_TOOLTIP :{BLACK}Mudar a duração do tempo que a ordem selecionada deve durar. Ctrl+Clique define o tempo para todas as ordens STR_TIMETABLE_CLEAR_TIME :{BLACK}Apagar Tempo -STR_TIMETABLE_CLEAR_TIME_TOOLTIP :{BLACK}Apagar o tempo que dura a ordem seleccionada +STR_TIMETABLE_CLEAR_TIME_TOOLTIP :{BLACK}Limpar a duração do tempo da ordem selecionada. Ctrl+Clique limpa os tempos para todas as ordens STR_TIMETABLE_CHANGE_SPEED :{BLACK}Alterar limite de velocidade -STR_TIMETABLE_CHANGE_SPEED_TOOLTIP :{BLACK}Mudar a velocidade maxima durante a viagem da ordem selecionada +STR_TIMETABLE_CHANGE_SPEED_TOOLTIP :{BLACK}Mudar a velocidade máxima durante a viagem da ordem selecionada. Ctrl+Clique define a velocidade para todas as ordens STR_TIMETABLE_CLEAR_SPEED :{BLACK}Remover limite de velocidade -STR_TIMETABLE_CLEAR_SPEED_TOOLTIP :{BLACK}Limpar a velocidade maxima durante a viagem da ordem selecionada +STR_TIMETABLE_CLEAR_SPEED_TOOLTIP :{BLACK}Limpar a velocidade máxima de viagem da ordem selecionada. Ctrl+Clique limpa as velocidades para todas as ordens. STR_TIMETABLE_RESET_LATENESS :{BLACK}Apagar Contador Atraso STR_TIMETABLE_RESET_LATENESS_TOOLTIP :{BLACK}Limpar o contador de atraso, para que o veículo passe a estar a horas STR_TIMETABLE_AUTOFILL :{BLACK}Auto preencher -STR_TIMETABLE_AUTOFILL_TOOLTIP :{BLACK}Preencher o horário automaticamente com os valores da próxima viagem (CTRL-clique para tentar manter os tempos de espera) +STR_TIMETABLE_AUTOFILL_TOOLTIP :{BLACK}Preencher o horário automaticamente com os valores da próxima viagem. Ctrl+Clique para tentar manter os tempos de espera. STR_TIMETABLE_EXPECTED :{BLACK}Esperado STR_TIMETABLE_SCHEDULED :{BLACK}Marcado diff --git a/src/lang/romanian.txt b/src/lang/romanian.txt index 26edf6667b..65630d38f6 100644 --- a/src/lang/romanian.txt +++ b/src/lang/romanian.txt @@ -205,6 +205,15 @@ STR_UNITS_POWER_IMPERIAL :{COMMA}cp STR_UNITS_POWER_METRIC :{COMMA}cp STR_UNITS_POWER_SI :{COMMA}kW +STR_UNITS_POWER_IMPERIAL_TO_WEIGHT_IMPERIAL :{DECIMAL}{NBSP}cp/t +STR_UNITS_POWER_IMPERIAL_TO_WEIGHT_METRIC :{DECIMAL}{NBSP}cp/t +STR_UNITS_POWER_IMPERIAL_TO_WEIGHT_SI :{DECIMAL}{NBSP}cp/kg +STR_UNITS_POWER_METRIC_TO_WEIGHT_IMPERIAL :{DECIMAL}{NBSP}cp/t +STR_UNITS_POWER_METRIC_TO_WEIGHT_METRIC :{DECIMAL}{NBSP}cp/t +STR_UNITS_POWER_METRIC_TO_WEIGHT_SI :{DECIMAL}{NBSP}cp/kg +STR_UNITS_POWER_SI_TO_WEIGHT_IMPERIAL :{DECIMAL}{NBSP}kW/t +STR_UNITS_POWER_SI_TO_WEIGHT_METRIC :{DECIMAL}{NBSP}kW/t +STR_UNITS_POWER_SI_TO_WEIGHT_SI :{DECIMAL}{NBSP}W/kg STR_UNITS_WEIGHT_SHORT_IMPERIAL :{COMMA}t STR_UNITS_WEIGHT_SHORT_METRIC :{COMMA}t @@ -232,8 +241,8 @@ STR_UNITS_HEIGHT_SI :{COMMA} m # Common window strings STR_LIST_FILTER_TITLE :{BLACK}Filtru: -STR_LIST_FILTER_OSKTITLE :{BLACK}Filtru -STR_LIST_FILTER_TOOLTIP :{BLACK}Introduceți un cuvânt-cheie pentru filtrarea listei +STR_LIST_FILTER_OSKTITLE :{BLACK}Introduceți unul sau mai multe cuvinte cheie pentru a filtra lista +STR_LIST_FILTER_TOOLTIP :{BLACK}Introduceți unul sau mai multe cuvinte cheie pentru a filtra lista STR_TOOLTIP_GROUP_ORDER :{BLACK}Selectează ordinea de grupare STR_TOOLTIP_SORT_ORDER :{BLACK}Alegeți ordinea de sortare (ascendentă/descendentă) @@ -385,7 +394,7 @@ STR_SCENEDIT_TOOLBAR_ROAD_CONSTRUCTION :{BLACK}Construc STR_SCENEDIT_TOOLBAR_TRAM_CONSTRUCTION :{BLACK}Construcție tramvai STR_SCENEDIT_TOOLBAR_PLANT_TREES :{BLACK}Plantează arbori. Shift comută între plantare/afişare cost estimat STR_SCENEDIT_TOOLBAR_PLACE_SIGN :{BLACK}Plasează semn -STR_SCENEDIT_TOOLBAR_PLACE_OBJECT :{BLACK}Amplasează obiect. Shift comută între amplasare/afişare cost estimat +STR_SCENEDIT_TOOLBAR_PLACE_OBJECT :{BLACK}Plasați obiectul. Ctrl selectează zona în diagonală. Shift comută construirea/afișarea estimării costurilor # Scenario editor file menu ###length 7 @@ -402,6 +411,7 @@ STR_SCENEDIT_FILE_MENU_QUIT :Ieşire din joc STR_SETTINGS_MENU_GAME_OPTIONS :Opţiunile jocului STR_SETTINGS_MENU_CONFIG_SETTINGS_TREE :Setări STR_SETTINGS_MENU_AI_SETTINGS :Setările AI +STR_SETTINGS_MENU_GAMESCRIPT_SETTINGS :Setări pentru scriptul jocului STR_SETTINGS_MENU_NEWGRF_SETTINGS :Setări NewGRF STR_SETTINGS_MENU_TRANSPARENCY_OPTIONS :Opţiuni transparenţă STR_SETTINGS_MENU_TOWN_NAMES_DISPLAYED :Afişează numele oraşelor @@ -1010,9 +1020,19 @@ STR_GAME_OPTIONS_VIDEO_VSYNC_TOOLTIP :{BLACK}Bifați STR_GAME_OPTIONS_VIDEO_DRIVER_INFO :{BLACK}Driver curent: {STRING} +STR_GAME_OPTIONS_GUI_SCALE_FRAME :{BLACK}Dimensiune interfaţă +STR_GAME_OPTIONS_GUI_SCALE_TOOLTIP :{BLACK}Trageți glisorul pentru a seta dimensiunea interfeței. Țineți apăsat Ctrl pentru ajustare continuă +STR_GAME_OPTIONS_GUI_SCALE_AUTO :{BLACK}Detectează automat dimensiunea +STR_GAME_OPTIONS_GUI_SCALE_AUTO_TOOLTIP :{BLACK}Bifați această căsuţă pentru a detecta automat dimensiunea interfeței +STR_GAME_OPTIONS_GUI_SCALE_BEVELS :{BLACK}Scalează marginile +STR_GAME_OPTIONS_GUI_SCALE_BEVELS_TOOLTIP :{BLACK}Bifați această casetă pentru a scala marginile în funcție de dimensiunea interfeței +STR_GAME_OPTIONS_GUI_SCALE_1X :1x STR_GAME_OPTIONS_GUI_SCALE_2X :2x +STR_GAME_OPTIONS_GUI_SCALE_3X :3x +STR_GAME_OPTIONS_GUI_SCALE_4X :4x +STR_GAME_OPTIONS_GUI_SCALE_5X :5x STR_GAME_OPTIONS_GRAPHICS :{BLACK}Grafică @@ -1425,6 +1445,7 @@ STR_CONFIG_SETTING_GRAPH_LINE_THICKNESS_HELPTEXT :Grosimea liniil STR_CONFIG_SETTING_SHOW_NEWGRF_NAME :Afișează numele NewGRF în fereastra de construcție a vehiculului: {STRING} STR_CONFIG_SETTING_SHOW_NEWGRF_NAME_HELPTEXT :Adaugă o linie în fereastra de construcție a vehiculului, afișând din care NewGRF vine vehiculul selectat. STR_CONFIG_SETTING_SHOW_CARGO_IN_LISTS :Afișați mărfurile pe care vehiculele le pot transporta în ferestrele listei {STRING} +STR_CONFIG_SETTING_SHOW_CARGO_IN_LISTS_HELPTEXT :Dacă este activată, încărcătura transportabilă a vehiculului va apărea deasupra acestuia în listele de vehicule STR_CONFIG_SETTING_LANDSCAPE :Peisaj: {STRING} STR_CONFIG_SETTING_LANDSCAPE_HELPTEXT :Peisajele definesc scenariile de bază a jocului cu cerințe diferite pentru încărcături și dezvoltare a orașelor. NewGRF și scripturile de joc permit un control mai fin @@ -1846,7 +1867,7 @@ STR_CONFIG_SETTING_TOWN_FOUNDING_ALLOWED :permis STR_CONFIG_SETTING_TOWN_FOUNDING_ALLOWED_CUSTOM_LAYOUT :permis, aspect particularizat al oraşului STR_CONFIG_SETTING_TOWN_CARGOGENMODE :Modalitatea de generare a cargoului dintr-un oraș: {STRING} -STR_CONFIG_SETTING_TOWN_CARGOGENMODE_HELPTEXT :Cât cargo este produs de casele dintr-un oraș, relativ la populația totală a orașului.{}Creștere pătratică: Un oraș de 2 ori mai mare generează de 4 ori mai mulți pasageri.{}Creștere liniară: Un oraș de 2 ori mai mare generează de 4 ori mai mulți pasageri. +STR_CONFIG_SETTING_TOWN_CARGOGENMODE_HELPTEXT :Câtă marfa este produsă de casele dintr-un oraș, relativ la populația totală a orașului.{}Creștere pătratică: Un oraș de 2 ori mai mare generează de 4 ori mai mulți pasageri.{}Creștere liniară: Un oraș de 2 ori mai mare generează de 4 ori mai mulți pasageri. ###length 2 STR_CONFIG_SETTING_TOWN_CARGOGENMODE_ORIGINAL :Pătratică (originală) STR_CONFIG_SETTING_TOWN_CARGOGENMODE_BITCOUNT :Liniar @@ -2060,6 +2081,8 @@ STR_INTRO_HIGHSCORE :{BLACK}Tabela c STR_INTRO_CONFIG_SETTINGS_TREE :{BLACK}Setări STR_INTRO_NEWGRF_SETTINGS :{BLACK}Setări NewGRF STR_INTRO_ONLINE_CONTENT :{BLACK}Resurse online +STR_INTRO_AI_SETTINGS :{BLACK}Setări AI +STR_INTRO_GAMESCRIPT_SETTINGS :{BLACK}Setări pentru scriptul jocului STR_INTRO_QUIT :{BLACK}Ieşire STR_INTRO_TOOLTIP_NEW_GAME :{BLACK}Începere joc nou. Ctrl+Click pentru a sări peste fereastra de configuraţie a harţii @@ -2079,6 +2102,8 @@ STR_INTRO_TOOLTIP_HIGHSCORE :{BLACK}Afișeaz STR_INTRO_TOOLTIP_CONFIG_SETTINGS_TREE :{BLACK}Setări afişare STR_INTRO_TOOLTIP_NEWGRF_SETTINGS :{BLACK}Afişează setările NewGRF STR_INTRO_TOOLTIP_ONLINE_CONTENT :{BLACK}Verifică dacă există resurse noi sau actualizate pentru descărcare +STR_INTRO_TOOLTIP_AI_SETTINGS :{BLACK}Afișează setările AI +STR_INTRO_TOOLTIP_GAMESCRIPT_SETTINGS :{BLACK}Afișează setările scriptului de joc STR_INTRO_TOOLTIP_QUIT :{BLACK}Ieși din 'OpenTTD' STR_INTRO_BASESET :{BLACK}Setul grafic actual are lipsă {NUM} {P sprite spriteuri "de spriteuri"}. Verificați actualizările pentru setul de bază. @@ -2469,13 +2494,13 @@ STR_NETWORK_SERVER_MESSAGE_GAME_REASON_LINK_GRAPH :se așteaptă p STR_NETWORK_MESSAGE_CLIENT_LEAVING :iese STR_NETWORK_MESSAGE_CLIENT_JOINED :*** {STRING} a intrat în joc -STR_NETWORK_MESSAGE_CLIENT_JOINED_ID :*** {STRING} a intrat în joc (Clientul #{2:NUM}) -STR_NETWORK_MESSAGE_CLIENT_COMPANY_JOIN :*** {STRING} a intrat în compania #{2:NUM} +STR_NETWORK_MESSAGE_CLIENT_JOINED_ID :*** {0:STRING} a intrat în joc (Clientul #{2:NUM}) +STR_NETWORK_MESSAGE_CLIENT_COMPANY_JOIN :*** {0:STRING} a intrat în compania #{2:NUM} STR_NETWORK_MESSAGE_CLIENT_COMPANY_SPECTATE :*** {STRING} a intrat ca spectator STR_NETWORK_MESSAGE_CLIENT_COMPANY_NEW :*** {STRING} a început o companie nouă (#{2:NUM}) -STR_NETWORK_MESSAGE_CLIENT_LEFT :*** {STRING} a ieşit din joc ({2:STRING}) +STR_NETWORK_MESSAGE_CLIENT_LEFT :*** {0:STRING} a ieşit din joc ({2:STRING}) STR_NETWORK_MESSAGE_NAME_CHANGE :*** {STRING} și-a schimbat numele în {STRING} -STR_NETWORK_MESSAGE_GIVE_MONEY :*** {STRING} a dat {2:CURRENCY_LONG} către {1:STRING} +STR_NETWORK_MESSAGE_GIVE_MONEY :*** {0:STRING} a dat {2:CURRENCY_LONG} către {1:STRING} STR_NETWORK_MESSAGE_SERVER_SHUTDOWN :{WHITE}Serverul a închis conexiunea STR_NETWORK_MESSAGE_SERVER_REBOOT :{WHITE}Serverul este repornit...{}Vă rugăm aşteptaţi... STR_NETWORK_MESSAGE_KICKED :*** {STRING} a fost dat afară. Motiv: ({STRING}) @@ -2590,6 +2615,8 @@ STR_LINKGRAPH_LEGEND_SATURATED :{TINY_FONT}{BLA STR_LINKGRAPH_LEGEND_OVERLOADED :{TINY_FONT}{BLACK}supraîncărcat # Linkgraph tooltip +STR_LINKGRAPH_STATS_TOOLTIP :{BLACK}{CARGO_LONG} care urmează să fie transportat pe lună de la {STATION} la {STATION} ({COMMA}% din capacitate){STRING} +STR_LINKGRAPH_STATS_TOOLTIP_RETURN_EXTENSION :{}{CARGO_LONG} de transportat înapoi ({COMMA}% din capacitate) # Base for station construction window(s) STR_STATION_BUILD_COVERAGE_AREA_TITLE :{BLACK}Aria de acoperire @@ -2599,6 +2626,7 @@ STR_STATION_BUILD_COVERAGE_AREA_OFF_TOOLTIP :{BLACK}Nu arăt STR_STATION_BUILD_COVERAGE_AREA_ON_TOOLTIP :{BLACK}Arată aria de acoperire a locaţiei propuse STR_STATION_BUILD_ACCEPTS_CARGO :{BLACK}Acceptă: {GOLD}{CARGO_LIST} STR_STATION_BUILD_SUPPLIES_CARGO :{BLACK}Furnizează: {GOLD}{CARGO_LIST} +STR_STATION_BUILD_INFRASTRUCTURE_COST :{BLACK}Cost întreținere: {GOLD}{CURRENCY_SHORT}/an # Join station window STR_JOIN_STATION_CAPTION :{WHITE}Uneşte staţia @@ -2786,11 +2814,11 @@ STR_LANDSCAPING_TOOLBAR :{WHITE}Modifica STR_LANDSCAPING_TOOLTIP_LOWER_A_CORNER_OF_LAND :{BLACK}Scade altitudinea unui punct de teren. Trage cu mouse-ul pentru a coborî primul punct de teren și a nivela restul zonei la noua înălțime a acestuia. Ctrl pentru selecţie pe diagonală. STR_LANDSCAPING_TOOLTIP_RAISE_A_CORNER_OF_LAND :{BLACK}Creşte altitudinea unui punct de teren. Trage cu mouse-ul pentru a ridica primul punct de teren și a nivela restul zonei la noua înălțime a acestuia. Ctrl pentru selecţie pe diagonală. STR_LANDSCAPING_LEVEL_LAND_TOOLTIP :{BLACK}Nivelează terenul la înălțimea primului colț selectat. Ctrl pentru selecție pe diagonală -STR_LANDSCAPING_TOOLTIP_PURCHASE_LAND :{BLACK}Cumpără teren pentru folosire ulterioară. Shift comută între cumpărare/afişare cost estimat +STR_LANDSCAPING_TOOLTIP_PURCHASE_LAND :{BLACK}Cumpărați teren pentru utilizare ulterioară. Ctrl selectează zona în diagonală. Shift comută construirea/afișarea estimării costurilor # Object construction window STR_OBJECT_BUILD_CAPTION :{WHITE}Selecţia obiectelor -STR_OBJECT_BUILD_TOOLTIP :{BLACK}Selectaţi obiectele pentru construcţie. Shift comută între construire/afişare cost estimat +STR_OBJECT_BUILD_TOOLTIP :{BLACK}Selectați obiectul de construit. Ctrl selectează zona în diagonală. Shift comută construirea/afișarea estimării costurilor STR_OBJECT_BUILD_CLASS_TOOLTIP :{BLACK}Selectează clasa obiectului de construit STR_OBJECT_BUILD_PREVIEW_TOOLTIP :{BLACK}Previzualizarea obiectului STR_OBJECT_BUILD_SIZE :{BLACK}Dimensiune: {GOLD}{NUM} x {NUM} pătrăţele @@ -2834,6 +2862,8 @@ STR_FOUND_TOWN_RANDOM_TOWN_BUTTON :{BLACK}Oraş al STR_FOUND_TOWN_RANDOM_TOWN_TOOLTIP :{BLACK}Construieşte un oraş într-o locaţie aleatoare STR_FOUND_TOWN_MANY_RANDOM_TOWNS :{BLACK}Mai multe oraşe aleatoare STR_FOUND_TOWN_RANDOM_TOWNS_TOOLTIP :{BLACK}Umple harta cu oraşe generate aleator +STR_FOUND_TOWN_EXPAND_ALL_TOWNS :{BLACK}Extinde orasele +STR_FOUND_TOWN_EXPAND_ALL_TOWNS_TOOLTIP :{BLACK}Fă toate orașele să crească ușor STR_FOUND_TOWN_NAME_TITLE :{YELLOW}Nume oraş: STR_FOUND_TOWN_NAME_EDITOR_TITLE :{BLACK}Introdu numele oraşului @@ -3098,7 +3128,7 @@ STR_SAVELOAD_DETAIL_CAPTION :{BLACK}Detalii STR_SAVELOAD_DETAIL_NOT_AVAILABLE :{BLACK}Nicio informaţie disponibilă STR_SAVELOAD_DETAIL_COMPANY_INDEX :{SILVER}{COMMA}: {WHITE}{STRING} STR_SAVELOAD_DETAIL_GRFSTATUS :{SILVER}NewGRF: {WHITE}{STRING} -STR_SAVELOAD_FILTER_TITLE :{BLACK}Filtrare după: +STR_SAVELOAD_FILTER_TITLE :{BLACK}Filtru: STR_SAVELOAD_OVERWRITE_TITLE :{WHITE}Suprascrie fișierul STR_SAVELOAD_OVERWRITE_WARNING :{YELLOW}Sigur vrei să suprascrii fișierul existent? STR_SAVELOAD_DIRECTORY :{STRING} (listă) @@ -3137,6 +3167,12 @@ STR_MAPGEN_QUANTITY_OF_RIVERS :{BLACK}Râuri: STR_MAPGEN_SMOOTHNESS :{BLACK}Netezime: STR_MAPGEN_VARIETY :{BLACK}Distribuţia varietăţii: STR_MAPGEN_GENERATE :{WHITE}Generează +STR_MAPGEN_NEWGRF_SETTINGS :{BLACK}Setări NewGRF +STR_MAPGEN_NEWGRF_SETTINGS_TOOLTIP :{BLACK}Afişează setările NewGRF +STR_MAPGEN_AI_SETTINGS :{BLACK}Configurație AI +STR_MAPGEN_AI_SETTINGS_TOOLTIP :{BLACK}Afișează setările AI +STR_MAPGEN_GS_SETTINGS :{BLACK}Setări pentru scriptul de joc +STR_MAPGEN_GS_SETTINGS_TOOLTIP :{BLACK}Afișează setările scriptului de joc ###length 21 STR_MAPGEN_TOWN_NAME_ORIGINAL_ENGLISH :Englezeşti (Original) @@ -3308,7 +3344,10 @@ STR_SPRITE_ALIGNER_SPRITE_TOOLTIP :{BLACK}Reprezen STR_SPRITE_ALIGNER_MOVE_TOOLTIP :{BLACK}Mișcă imaginea schimbând distanțele pe axele X şi Y. Ctrl+Clic pentru mutarea imaginii câte opt unități la un pas ###length 2 +STR_SPRITE_ALIGNER_CENTRE_OFFSET :{BLACK}Offset centrat +STR_SPRITE_ALIGNER_CENTRE_SPRITE :{BLACK}Centrază sprite +STR_SPRITE_ALIGNER_CROSSHAIR :{BLACK}Focus STR_SPRITE_ALIGNER_RESET_BUTTON :{BLACK}Resetează relativele STR_SPRITE_ALIGNER_RESET_TOOLTIP :{BLACK}Resetază limitele relative actuale @@ -3327,15 +3366,15 @@ STR_NEWGRF_ERROR_MSG_FATAL :{RED}Fatal: {SI STR_NEWGRF_ERROR_FATAL_POPUP :{WHITE}O eroare fatală NewGRF a avut loc:{}{STRING} STR_NEWGRF_ERROR_POPUP :{WHITE}O eroare NewGRF a avut loc:{}{STRING} STR_NEWGRF_ERROR_VERSION_NUMBER :{1:STRING} nu va funcţiona cu versiunea TTDPatch raportată de OpenTTD -STR_NEWGRF_ERROR_DOS_OR_WINDOWS :{1:STRING} este pentru versiunea {STRING} a TTD -STR_NEWGRF_ERROR_UNSET_SWITCH :{1:STRING} este conceput pentru a fi folosit cu {STRING} -STR_NEWGRF_ERROR_INVALID_PARAMETER :Parametru invalid pentru {1:STRING}: parametrul {STRING} ({NUM}) -STR_NEWGRF_ERROR_LOAD_BEFORE :{1:STRING} trebuie să fie încărcat înaintea {STRING} -STR_NEWGRF_ERROR_LOAD_AFTER :{1:STRING} trebuie să fie încărcat după {STRING} -STR_NEWGRF_ERROR_OTTD_VERSION_NUMBER :{1:STRING} necesită OpenTTD versiunea {STRING} sau mai nouă +STR_NEWGRF_ERROR_DOS_OR_WINDOWS :{1:STRING} este pentru versiunea {2:STRING} a TTD +STR_NEWGRF_ERROR_UNSET_SWITCH :{1:STRING} este conceput pentru a fi folosit cu {2:STRING} +STR_NEWGRF_ERROR_INVALID_PARAMETER :Parametru invalid pentru {1:STRING}: parametrul {2:STRING} ({3:NUM}) +STR_NEWGRF_ERROR_LOAD_BEFORE :{1:STRING} trebuie să fie încărcat înaintea {2:STRING} +STR_NEWGRF_ERROR_LOAD_AFTER :{1:STRING} trebuie să fie încărcat după {2:STRING} +STR_NEWGRF_ERROR_OTTD_VERSION_NUMBER :{1:STRING} necesită OpenTTD versiunea {2:STRING} sau mai nouă STR_NEWGRF_ERROR_AFTER_TRANSLATED_FILE :fişierul GRF conceput pentru traducere STR_NEWGRF_ERROR_TOO_MANY_NEWGRFS_LOADED :Sunt încărcate prea multe NewGRF-uri -STR_NEWGRF_ERROR_STATIC_GRF_CAUSES_DESYNC :Încărcarea {1:STRING} ca un NewGRF static cu {STRING} ar putea cauza desincronizări +STR_NEWGRF_ERROR_STATIC_GRF_CAUSES_DESYNC :Încărcarea {1:STRING} ca un NewGRF static cu {2:STRING} ar putea cauza desincronizări STR_NEWGRF_ERROR_UNEXPECTED_SPRITE :Element grafic neașteptat (sprite {3:NUM}) STR_NEWGRF_ERROR_UNKNOWN_PROPERTY :Proprietate necunoscută pentru Acțiunea 0 {4:HEX} (sprite {3:NUM}) STR_NEWGRF_ERROR_INVALID_ID :Încercare de a folosi un ID invalid (sprite {3:NUM}) @@ -3467,14 +3506,14 @@ STR_LOCAL_AUTHORITY_ACTION_EXCLUSIVE_TRANSPORT :Cumpără drept STR_LOCAL_AUTHORITY_ACTION_BRIBE :Mituieşte autoritatea locală ###length 8 -STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_SMALL_ADVERTISING :{YELLOW}Inițiază o campanie publicitară mică pentru a atrage mai mulți călători și mai multe mărfuri spre compania ta.{}Oferă temporar un spor la cotația stației tale pe o rază mică în jurul centrului orașului.{}Cost: {CURRENCY_LONG} -STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_MEDIUM_ADVERTISING :{YELLOW}Inițiază o campanie publicitară medie pentru a atrage mai mulți călători și mai multe mărfuri spre compania ta.{}Oferă temporar un spor la cotația stației tale pe o rază medie în jurul centrului orașului.{}Cost: {CURRENCY_LONG} -STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_LARGE_ADVERTISING :{YELLOW}Inițiază o mare campanie publicitară pentru a atrage mai mulți călători și mai multe mărfuri spre compania ta.{}Oferă temporar un spor la cotația stației tale pe o rază mare în jurul centrului orașului.{}Cost: {CURRENCY_LONG} -STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_ROAD_RECONSTRUCTION :{YELLOW}Finanțează reconstrucția rețelei locale de drumuri.{}Aceasta cauzează perturbări majore ale traficului rutier timp de până la 6 luni.{}Cost: {CURRENCY_LONG} -STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_STATUE_OF_COMPANY :{YELLOW}Construiește o statuie în cinstea companiei tale.{}Oferă un spor permanent la cotația stației tale în acest oraș.{}Cost: {CURRENCY_LONG} -STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_NEW_BUILDINGS :{YELLOW}Finanțează construcția de noi clădiri comerciale în oraș.{}Oferă un spor temporar dezvoltării în acest oraș.{}Cost: {CURRENCY_LONG} -STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_EXCLUSIVE_TRANSPORT :{YELLOW}Cumpără drepturi exclusive de transport în acest oraș, timp de un an.{}Autoritățile locale nu vor permite călătorilor și mărfurilor să folosească stațiile competitorilor.{}Cost: {CURRENCY_LONG} -STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_BRIBE :{YELLOW}Mituieşte autorităţile locale pentru a-ţi îmbunătăţi ratingul, dar cu riscul de a fi prins şi de a plăti amenzi serioase.{} Cost: {CURRENCY_LONG} +STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_SMALL_ADVERTISING :{PUSH_COLOUR}{YELLOW}Inițiază o campanie publicitară mică pentru a atrage mai mulți călători și mai multe mărfuri spre compania ta.{}Oferă temporar un spor la cotația staților tale pe o rază mică în jurul centrului orașului.{}{POP_COLOUR}Cost: {CURRENCY_LONG} +STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_MEDIUM_ADVERTISING :{PUSH_COLOUR}{YELLOW}Inițiază o campanie publicitară medie pentru a atrage mai mulți călători și mai multe mărfuri spre compania ta.{}Oferă temporar un spor la cotația stațiilor tale pe o rază medie în jurul centrului orașului.{}{POP_COLOUR}Cost: {CURRENCY_LONG} +STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_LARGE_ADVERTISING :{PUSH_COLOUR}{YELLOW}Inițiază o mare campanie publicitară pentru a atrage mai mulți călători și mai multe mărfuri spre compania ta.{}Oferă temporar un spor la cotația stațiilor tale pe o rază mare în jurul centrului orașului.{}{POP_COLOUR}Cost: {CURRENCY_LONG} +STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_ROAD_RECONSTRUCTION :{PUSH_COLOUR}{YELLOW}Finanțați reconstrucția rețelei de drumuri urbane.{}Provoacă perturbări considerabile ale traficului rutier timp de până la 6 luni.{}{POP_COLOUR}Cost: {CURRENCY_LONG} +STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_STATUE_OF_COMPANY :{PUSH_COLOUR}{YELLOW}Construiește o statuie în onoarea companiei tale.{}Oferă un spor permanent pentru cotele stațiilor tale din acest oraș.{}{POP_COLOUR}Cost: {CURRENCY_LONG} +STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_NEW_BUILDINGS :{PUSH_COLOUR}{YELLOW}Finanțează construcția de noi clădiri în oraș.{}Oferă un spor temporar dezvoltării în acest oraș.{}{POP_COLOUR}Cost: {CURRENCY_LONG} +STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_EXCLUSIVE_TRANSPORT :{PUSH_COLOUR}{YELLOW}Cumpără drepturi exclusive de transport în acest oraș, timp de un an.{}Autoritățile locale nu vor permite călătorilor și mărfurilor să folosească stațiile competitorilor.{}{POP_COLOUR}Cost: {CURRENCY_LONG} +STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_BRIBE :{PUSH_COLOUR}{YELLOW}Mituiți autoritatea locală pentru a vă crește ratingul, cu riscul unei sancțiuni severe dacă eşti prins.{}{POP_COLOUR}Cost: {CURRENCY_LONG} # Goal window STR_GOALS_CAPTION :{WHITE}{COMPANY} Scopuri @@ -3647,14 +3686,18 @@ STR_FINANCES_SECTION_SHIP_REVENUE :{GOLD}Nave STR_FINANCES_SECTION_LOAN_INTEREST :{GOLD}Dobânda la credit STR_FINANCES_SECTION_OTHER :{GOLD}Altele +STR_FINANCES_TOTAL_CAPTION :{WHITE}Total STR_FINANCES_NEGATIVE_INCOME :-{CURRENCY_LONG} +STR_FINANCES_ZERO_INCOME :{CURRENCY_LONG} STR_FINANCES_POSITIVE_INCOME :+{CURRENCY_LONG} +STR_FINANCES_PROFIT :{WHITE}Profit STR_FINANCES_BANK_BALANCE_TITLE :{WHITE}Balanţă curentă STR_FINANCES_OWN_FUNDS_TITLE :{WHITE}Fonduri proprii STR_FINANCES_LOAN_TITLE :{WHITE}Credite STR_FINANCES_INTEREST_RATE :{WHITE}Dobândā la credit: {BLACK}{NUM}% STR_FINANCES_MAX_LOAN :{WHITE}Limită credit: {BLACK}{CURRENCY_LONG} STR_FINANCES_TOTAL_CURRENCY :{BLACK}{CURRENCY_LONG} +STR_FINANCES_BANK_BALANCE :{WHITE}{CURRENCY_LONG} STR_FINANCES_BORROW_BUTTON :{BLACK}Împrumută {CURRENCY_LONG} STR_FINANCES_BORROW_TOOLTIP :{BLACK}Împrumută o nouă sumă de bani. Ctrl-click pentru a împrumuta suma maximă posibilă STR_FINANCES_REPAY_BUTTON :{BLACK}Plăteşte înapoi {CURRENCY_LONG} @@ -3755,7 +3798,7 @@ STR_INDUSTRY_VIEW_PRODUCES_N_CARGO :{BLACK}Produce: STR_INDUSTRY_VIEW_CARGO_LIST_EXTENSION :, {STRING}{STRING} STR_INDUSTRY_VIEW_REQUIRES :{BLACK}Necesită: -STR_INDUSTRY_VIEW_ACCEPT_CARGO :{YELLOW}{STRING}{BLACK}{3:STRING} +STR_INDUSTRY_VIEW_ACCEPT_CARGO :{YELLOW}{0:STRING}{BLACK}{3:STRING} STR_INDUSTRY_VIEW_ACCEPT_CARGO_AMOUNT :{YELLOW}{STRING}{BLACK}: {CARGO_SHORT} așteaptă{STRING} STR_CONFIG_GAME_PRODUCTION :{WHITE}Schimba productia (multiplu de 8, până la 2040) @@ -3785,6 +3828,8 @@ STR_VEHICLE_LIST_MANAGE_LIST_TOOLTIP :{BLACK}Trimite STR_VEHICLE_LIST_REPLACE_VEHICLES :Inlocuieste vehiculele STR_VEHICLE_LIST_SEND_FOR_SERVICING :Trimite in service STR_VEHICLE_LIST_PROFIT_THIS_YEAR_LAST_YEAR :{TINY_FONT}{BLACK}Profit anul acesta: {CURRENCY_LONG} (anul trecut: {CURRENCY_LONG}) +STR_VEHICLE_LIST_CARGO :{TINY_FONT}{BLACK}[{CARGO_LIST}] +STR_VEHICLE_LIST_NAME_AND_CARGO :{TINY_FONT}{BLACK}{STRING} {STRING} STR_VEHICLE_LIST_SEND_TRAIN_TO_DEPOT :Trimite la depou STR_VEHICLE_LIST_SEND_ROAD_VEHICLE_TO_DEPOT :Trimite la depou @@ -3878,6 +3923,9 @@ STR_PURCHASE_INFO_AIRCRAFT_RANGE :{BLACK}Rază ac STR_PURCHASE_INFO_AIRCRAFT_TYPE :{BLACK}Tip de aeronavă: {GOLD}{STRING} ###length 3 +STR_CARGO_TYPE_FILTER_ALL :Toate tipurile de marfă +STR_CARGO_TYPE_FILTER_FREIGHT :Marfă +STR_CARGO_TYPE_FILTER_NONE :Niciunul ###length VEHICLE_TYPES STR_BUY_VEHICLE_TRAIN_LIST_TOOLTIP :{BLACK}Lista de selectie a componentelor trenului - clic pe vehicule pt. informatii @@ -4047,7 +4095,7 @@ STR_ENGINE_PREVIEW_AIRCRAFT :aeronavă STR_ENGINE_PREVIEW_SHIP :navă STR_ENGINE_PREVIEW_COST_WEIGHT_SPEED_POWER :{BLACK}Cost: {CURRENCY_LONG} Greutate: {WEIGHT_SHORT}{}Viteză: {VELOCITY} Putere: {POWER}{}Mentenanță: {CURRENCY_LONG}/an{}Capacitate: {CARGO_LONG} -STR_ENGINE_PREVIEW_COST_WEIGHT_SPEED_POWER_MAX_TE :{BLACK}Cost: {CURRENCY_LONG} Greutate: {WEIGHT_SHORT}{}Viteză: {VELOCITY} Putere: {POWER} Ef. T. Max.: {6:FORCE}{}Mentenanță: {4:CURRENCY_LONG}/an{}Capacitate: {5:CARGO_LONG} +STR_ENGINE_PREVIEW_COST_WEIGHT_SPEED_POWER_MAX_TE :{BLACK}Cost: {0:CURRENCY_LONG} Greutate: {1:WEIGHT_SHORT}{}Viteză: {2:VELOCITY} Putere: {3:POWER} Ef. T. Max.: {6:FORCE}{}Cost operare: {4:CURRENCY_LONG}/an{}Capacitate: {5:CARGO_LONG} STR_ENGINE_PREVIEW_COST_MAX_SPEED_CAP_RUNCOST :{BLACK}Cost: {CURRENCY_LONG} Viteză max.: {VELOCITY}{}Capacitate: {CARGO_LONG}{}Mentenanță: {CURRENCY_LONG}/an STR_ENGINE_PREVIEW_COST_MAX_SPEED_TYPE_CAP_CAP_RUNCOST :{BLACK}Cost: {CURRENCY_LONG} Viteză max.: {VELOCITY}{}Tip de aeronavă: {STRING}{}Capacitate: {CARGO_LONG}, {CARGO_LONG}{}Mentenanță: {CURRENCY_LONG}/an STR_ENGINE_PREVIEW_COST_MAX_SPEED_TYPE_CAP_RUNCOST :{BLACK}Cost: {CURRENCY_LONG} Viteză max.: {VELOCITY}{}Tip aeronavă: {STRING}{}Capacitate: {CARGO_LONG}{}Mentenanță: {CURRENCY_LONG}/an @@ -4206,12 +4254,13 @@ STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED :{BLACK}Greutate STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED_MAX_TE :{BLACK}Greutate: {LTBLUE}{WEIGHT_SHORT} {BLACK}Putere: {LTBLUE}{POWER}{BLACK} Viteză max.: {LTBLUE}{VELOCITY} {BLACK}Efort tractiv: {LTBLUE}{FORCE} STR_VEHICLE_INFO_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Profit pe anul curent: {LTBLUE}{CURRENCY_LONG} (anul precedent: {CURRENCY_LONG}) +STR_VEHICLE_INFO_PROFIT_THIS_YEAR_LAST_YEAR_MIN_PERFORMANCE :{BLACK}Profit anul curent: {LTBLUE}{CURRENCY_LONG} (anul trecut: {CURRENCY_LONG}) {BLACK}performanta minima: {LTBLUE}{POWER_TO_WEIGHT} STR_VEHICLE_INFO_RELIABILITY_BREAKDOWNS :{BLACK}Eficienţă: {LTBLUE}{COMMA}% {BLACK}Defecţiuni de la ultimul service: {LTBLUE}{COMMA} STR_VEHICLE_INFO_BUILT_VALUE :{LTBLUE}{ENGINE} {BLACK}Construit: {LTBLUE}{NUM}{BLACK} Valoare: {LTBLUE}{CURRENCY_LONG} STR_VEHICLE_INFO_NO_CAPACITY :{BLACK}Capacitate: {LTBLUE}Nimic{STRING} -STR_VEHICLE_INFO_CAPACITY :{BLACK}Capacitate: {LTBLUE}{CARGO_LONG}{3:STRING} -STR_VEHICLE_INFO_CAPACITY_MULT :{BLACK}Capacitate: {LTBLUE}{CARGO_LONG}{3:STRING} (x{4:NUM}) +STR_VEHICLE_INFO_CAPACITY :{BLACK}Capacitate: {LTBLUE}{0:CARGO_LONG}{3:STRING} +STR_VEHICLE_INFO_CAPACITY_MULT :{BLACK}Capacitate: {LTBLUE}{0:CARGO_LONG}{3:STRING} (x{4:NUM}) STR_VEHICLE_INFO_CAPACITY_CAPACITY :{BLACK}Capacitate: {LTBLUE}{CARGO_LONG}, {CARGO_LONG}{STRING} STR_VEHICLE_INFO_FEEDER_CARGO_VALUE :{BLACK}Transferă Credit: {LTBLUE}{CURRENCY_LONG} @@ -4480,22 +4529,22 @@ STR_TIMETABLE_STARTING_DATE :{BLACK}Dată po STR_TIMETABLE_STARTING_DATE_TOOLTIP :{BLACK}Alege o dată ca punct de pornire pentru acest orar. Ctrl+clic distribuie toate vehiculele uniform de la data setată bazată pe comenzile relative, dacă comenzile au un orar complet STR_TIMETABLE_CHANGE_TIME :{BLACK}Modifică timpul -STR_TIMETABLE_WAIT_TIME_TOOLTIP :{BLACK}Modifică durata de timp alocată comenzii selectate +STR_TIMETABLE_WAIT_TIME_TOOLTIP :{BLACK}Modificați timpul pe care ar trebui să o dureze comanda evidențiată. Ctrl+Click setează ora pentru toate comenzile STR_TIMETABLE_CLEAR_TIME :{BLACK}Curata timp STR_TIMETABLE_CLEAR_TIME_TOOLTIP :{BLACK}Elimină durata de timp pentru comanda selectată STR_TIMETABLE_CHANGE_SPEED :{BLACK}Schimbă limita de viteză -STR_TIMETABLE_CHANGE_SPEED_TOOLTIP :{BLACK}Schimbă limita maximă de viteză a comenzii selectate +STR_TIMETABLE_CHANGE_SPEED_TOOLTIP :{BLACK}Schimbă limita maximă de viteză a comenzii selectate. Ctrl+Click setează viteza pentru toate comenzile STR_TIMETABLE_CLEAR_SPEED :{BLACK}Şterge limita de viteză -STR_TIMETABLE_CLEAR_SPEED_TOOLTIP :{BLACK}Șterge limita maximă de viteză a comenzii selectate +STR_TIMETABLE_CLEAR_SPEED_TOOLTIP :{BLACK}Ștergeți viteza maximă de deplasare a comenzii evidențiate. Ctrl+Click șterge viteza pentru toate comenzile STR_TIMETABLE_RESET_LATENESS :{BLACK}Reinitializeaza contorul de intarziere STR_TIMETABLE_RESET_LATENESS_TOOLTIP :{BLACK}Reiniţializează contorul de întârziere, astfel ca vehiculul să ajungă la timp STR_TIMETABLE_AUTOFILL :{BLACK}Auto-completare -STR_TIMETABLE_AUTOFILL_TOOLTIP :{BLACK}Completează automat tabela cu timpi cu valorile pentru urmatoarea călătorie (CTRL-clic pentru a încerca să păstraţi timpii de aşteptare) +STR_TIMETABLE_AUTOFILL_TOOLTIP :{BLACK}Completați automat orarul cu valorile din următoarea călătorie. Ctrl+Click pentru a încerca să păstrați timpii de așteptare STR_TIMETABLE_EXPECTED :{BLACK}Estimat STR_TIMETABLE_SCHEDULED :{BLACK}Planificat @@ -4539,6 +4588,8 @@ STR_ERROR_AI_PLEASE_REPORT_CRASH :{WHITE}O Inteli STR_ERROR_AI_DEBUG_SERVER_ONLY :{YELLOW}Fereastra pentru depanare IA / Script Joc este disponibilă doar serverului # AI configuration window +STR_AI_CONFIG_CAPTION_AI :{WHITE}Configurație AI +STR_AI_CONFIG_CAPTION_GAMESCRIPT :{WHITE}Configurarea scriptului de joc STR_AI_CONFIG_GAMELIST_TOOLTIP :{BLACK}Script Joc încărcat în jocul următor STR_AI_CONFIG_AILIST_TOOLTIP :{BLACK}Modulul de IA care va fi încărcat în jocul următor STR_AI_CONFIG_HUMAN_PLAYER :Jucator uman @@ -4552,10 +4603,11 @@ STR_AI_CONFIG_MOVE_DOWN :{BLACK}În jos STR_AI_CONFIG_MOVE_DOWN_TOOLTIP :{BLACK}Mută IA selectată jos în listă STR_AI_CONFIG_GAMESCRIPT :{SILVER}Script Joc +STR_AI_CONFIG_GAMESCRIPT_PARAM :{SILVER}Parametri STR_AI_CONFIG_AI :{SILVER}IA -STR_AI_CONFIG_CHANGE_AI :IA -STR_AI_CONFIG_CHANGE_GAMESCRIPT :Script Joc +STR_AI_CONFIG_CHANGE_AI :{BLACK}Selectați IA +STR_AI_CONFIG_CHANGE_GAMESCRIPT :{BLACK}Selectați Scriptul jocului STR_AI_CONFIG_CHANGE_TOOLTIP :{BLACK}Încarcă un alt script STR_AI_CONFIG_CONFIGURE :{BLACK}Configurază STR_AI_CONFIG_CONFIGURE_TOOLTIP :{BLACK}Configurează parametrii scriptului @@ -4584,7 +4636,7 @@ STR_SCREENSHOT_HEIGHTMAP_SCREENSHOT :{BLACK}Captură STR_SCREENSHOT_MINIMAP_SCREENSHOT :{BLACK}Captură de hartă a lumii # AI Parameters -STR_AI_SETTINGS_CAPTION_AI :IA +STR_AI_SETTINGS_CAPTION_AI :{WHITE}Parametrii IA STR_AI_SETTINGS_CLOSE :{BLACK}Închide STR_AI_SETTINGS_RESET :{BLACK}Resetează STR_AI_SETTINGS_SETTING :{STRING}: {ORANGE}{STRING} @@ -5030,6 +5082,8 @@ STR_ERROR_CAN_T_SKIP_TO_ORDER :{WHITE}Nu pot s STR_ERROR_CAN_T_COPY_SHARE_ORDER :{WHITE}... vehiculul nu poate ajunge la toate staţiile STR_ERROR_CAN_T_ADD_ORDER :{WHITE}... vehiculul nu poate ajunge la acea staţie STR_ERROR_CAN_T_ADD_ORDER_SHARED :{WHITE}... un vehicul care are acest ordin nu poate ajunge la acea staţie +STR_ERROR_CAN_T_COPY_ORDER_VEHICLE_LIST :{WHITE}... nu toate vehiculele au aceleași comenzi +STR_ERROR_CAN_T_SHARE_ORDER_VEHICLE_LIST :{WHITE}... nu toate vehiculele împart comenzi STR_ERROR_CAN_T_SHARE_ORDER_LIST :{WHITE}Nu se poate trece la comenzi sincronizate... STR_ERROR_CAN_T_STOP_SHARING_ORDER_LIST :{WHITE}Nu pot opri sincronizarea listei de comenzi... diff --git a/src/lang/russian.txt b/src/lang/russian.txt index f5b219579a..9301892bb5 100644 --- a/src/lang/russian.txt +++ b/src/lang/russian.txt @@ -3045,6 +3045,8 @@ STR_FOUND_TOWN_RANDOM_TOWN_BUTTON :{BLACK}Случ STR_FOUND_TOWN_RANDOM_TOWN_TOOLTIP :{BLACK}Создать город в случайном месте STR_FOUND_TOWN_MANY_RANDOM_TOWNS :{BLACK}Множество различных городов STR_FOUND_TOWN_RANDOM_TOWNS_TOOLTIP :{BLACK}Разместить на карте различные города случайным образом +STR_FOUND_TOWN_EXPAND_ALL_TOWNS :{BLACK}Расширить все города +STR_FOUND_TOWN_EXPAND_ALL_TOWNS_TOOLTIP :{BLACK}Увеличить размер всех городов STR_FOUND_TOWN_NAME_TITLE :{YELLOW}Название города: STR_FOUND_TOWN_NAME_EDITOR_TITLE :{BLACK}Введите название города @@ -4737,16 +4739,16 @@ STR_TIMETABLE_STARTING_DATE :{BLACK}Нача STR_TIMETABLE_STARTING_DATE_TOOLTIP :{BLACK}Выберите начальную дату для этого графика. Ctrl+щелчок равномерно распределит все транспортные средства, следующие по этому маршруту, если время движения по нему полностью рассчитано. STR_TIMETABLE_CHANGE_TIME :{BLACK}Изменить время -STR_TIMETABLE_WAIT_TIME_TOOLTIP :{BLACK}Изменить время для выделенного задания +STR_TIMETABLE_WAIT_TIME_TOOLTIP :{BLACK}Изменить время исполнения выделенного задания. Ctrl+щелчок устанавливает время для всех заданий. STR_TIMETABLE_CLEAR_TIME :{BLACK}Сбросить время -STR_TIMETABLE_CLEAR_TIME_TOOLTIP :{BLACK}Сбросить время в выделенном задании +STR_TIMETABLE_CLEAR_TIME_TOOLTIP :{BLACK}Сбросить время в выделенном задании. Ctrl+щелчок - сбросить время во всех заданиях. STR_TIMETABLE_CHANGE_SPEED :{BLACK}Изменить огранич. скорости -STR_TIMETABLE_CHANGE_SPEED_TOOLTIP :{BLACK}Изменить ограничение скорости движения для выбранного задания +STR_TIMETABLE_CHANGE_SPEED_TOOLTIP :{BLACK}Изменить ограничение скорости движения для выбранного задания. Ctrl+щелчок устанавливает скорость для всех заданий. STR_TIMETABLE_CLEAR_SPEED :{BLACK}Сбросить огранич. скорости -STR_TIMETABLE_CLEAR_SPEED_TOOLTIP :{BLACK}Сбросить ограничение скорости движения для выделенного задания +STR_TIMETABLE_CLEAR_SPEED_TOOLTIP :{BLACK}Сбросить ограничение скорости движения для выделенного задания. Ctrl+щелчок - сбросить время для всех заданий. STR_TIMETABLE_RESET_LATENESS :{BLACK}Сбросить счетчик опозд. STR_TIMETABLE_RESET_LATENESS_TOOLTIP :{BLACK}Сбросить счётчик отклонения от графика, чтобы транспорт снова считался приходящим вовремя diff --git a/src/newgrf.cpp b/src/newgrf.cpp index 0511dace9f..056abaa97d 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -341,13 +341,7 @@ static GRFFile *GetFileByFilename(const char *filename) /** Reset all NewGRFData that was used only while processing data */ static void ClearTemporaryNewGRFData(GRFFile *gf) { - /* Clear the GOTO labels used for GRF processing */ - for (GRFLabel *l = gf->label; l != nullptr;) { - GRFLabel *l2 = l->next; - free(l); - l = l2; - } - gf->label = nullptr; + gf->labels.clear(); } /** @@ -1276,6 +1270,14 @@ static ChangeInfoResult RailVehicleChangeInfo(uint engine, int numinfo, int prop rvi->curve_speed_mod = buf->ReadWord(); break; + case 0x2F: // Engine variant + ei->variant_id = GetNewEngineID(_cur.grffile, VEH_TRAIN, buf->ReadWord()); + break; + + case 0x30: // Extra miscellaneous flags + ei->extra_flags = static_cast(buf->ReadDWord()); + break; + default: ret = CommonVehicleChangeInfo(ei, prop, mapping_entry, buf); break; @@ -1470,6 +1472,14 @@ static ChangeInfoResult RoadVehicleChangeInfo(uint engine, int numinfo, int prop break; } + case 0x26: // Engine variant + ei->variant_id = GetNewEngineID(_cur.grffile, VEH_ROAD, buf->ReadWord()); + break; + + case 0x27: // Extra miscellaneous flags + ei->extra_flags = static_cast(buf->ReadDWord()); + break; + default: ret = CommonVehicleChangeInfo(ei, prop, mapping_entry, buf); break; @@ -1642,6 +1652,14 @@ static ChangeInfoResult ShipVehicleChangeInfo(uint engine, int numinfo, int prop break; } + case 0x20: // Engine variant + ei->variant_id = GetNewEngineID(_cur.grffile, VEH_SHIP, buf->ReadWord()); + break; + + case 0x21: // Extra miscellaneous flags + ei->extra_flags = static_cast(buf->ReadDWord()); + break; + default: ret = CommonVehicleChangeInfo(ei, prop, mapping_entry, buf); break; @@ -1796,6 +1814,14 @@ static ChangeInfoResult AircraftVehicleChangeInfo(uint engine, int numinfo, int avi->max_range = buf->ReadWord(); break; + case 0x20: // Engine variant + ei->variant_id = GetNewEngineID(_cur.grffile, VEH_AIRCRAFT, buf->ReadWord()); + break; + + case 0x21: // Extra miscellaneous flags + ei->extra_flags = static_cast(buf->ReadDWord()); + break; + default: ret = CommonVehicleChangeInfo(ei, prop, mapping_entry, buf); break; @@ -7126,9 +7152,17 @@ static void GraphicsNew(ByteReader *buf) if (offset <= depot_no_track_offset && offset + num > depot_no_track_offset) _loaded_newgrf_features.tram = TRAMWAY_REPLACE_DEPOT_NO_TRACK; } + /* If the baseset or grf only provides sprites for flat tiles (pre #10282), duplicate those for use on slopes. */ + bool dup_oneway_sprites = ((type == 0x09) && (offset + num <= SPR_ONEWAY_SLOPE_N_OFFSET)); + for (uint16 n = num; n > 0; n--) { _cur.nfo_line++; - LoadNextSprite(replace == 0 ? _cur.spriteid++ : replace++, *_cur.file, _cur.nfo_line); + int load_index = (replace == 0 ? _cur.spriteid++ : replace++); + LoadNextSprite(load_index, *_cur.file, _cur.nfo_line); + if (dup_oneway_sprites) { + DupSprite(load_index, load_index + SPR_ONEWAY_SLOPE_N_OFFSET); + DupSprite(load_index, load_index + SPR_ONEWAY_SLOPE_S_OFFSET); + } } if (type == 0x04 && ((_cur.grfconfig->ident.grfid & 0x00FFFFFF) == OPENTTD_GRAPHICS_BASE_GRF_ID || _cur.grfconfig->ident.grfid == BSWAP32(0xFF4F4701))) { @@ -7616,15 +7650,15 @@ static void SkipIf(ByteReader *buf) * file. The jump will always be the first matching label that follows * the current nfo_line. If no matching label is found, the first matching * label in the file is used. */ - GRFLabel *choice = nullptr; - for (GRFLabel *label = _cur.grffile->label; label != nullptr; label = label->next) { - if (label->label != numsprites) continue; + const GRFLabel *choice = nullptr; + for (const auto &label : _cur.grffile->labels) { + if (label.label != numsprites) continue; /* Remember a goto before the current line */ - if (choice == nullptr) choice = label; + if (choice == nullptr) choice = &label; /* If we find a label here, this is definitely good */ - if (label->nfo_line > _cur.nfo_line) { - choice = label; + if (label.nfo_line > _cur.nfo_line) { + choice = &label; break; } } @@ -8479,23 +8513,9 @@ static void DefineGotoLabel(ByteReader *buf) byte nfo_label = buf->ReadByte(); - GRFLabel *label = MallocT(1); - label->label = nfo_label; - label->nfo_line = _cur.nfo_line; - label->pos = _cur.file->GetPos(); - label->next = nullptr; - - /* Set up a linked list of goto targets which we will search in an Action 0x7/0x9 */ - if (_cur.grffile->label == nullptr) { - _cur.grffile->label = label; - } else { - /* Attach the label to the end of the list */ - GRFLabel *l; - for (l = _cur.grffile->label; l->next != nullptr; l = l->next) {} - l->next = label; - } + _cur.grffile->labels.emplace_back(nfo_label, _cur.nfo_line, _cur.file->GetPos()); - grfmsg(2, "DefineGotoLabel: GOTO target with label 0x%02X", label->label); + grfmsg(2, "DefineGotoLabel: GOTO target with label 0x%02X", nfo_label); } /** @@ -10557,6 +10577,11 @@ static void FinaliseEngineArray() if (!HasBit(e->info.climates, _settings_game.game_creation.landscape)) continue; + /* Set appropriate flags on variant engine */ + if (e->info.variant_id != INVALID_ENGINE) { + Engine::Get(e->info.variant_id)->display_flags |= EngineDisplayFlags::HasVariants | EngineDisplayFlags::IsFolded; + } + /* Skip wagons, there livery is defined via the engine */ if (e->type != VEH_TRAIN || e->u.rail.railveh_type != RAILVEH_WAGON) { LiveryScheme ls = GetEngineLiveryScheme(e->index, INVALID_ENGINE, nullptr); diff --git a/src/newgrf.h b/src/newgrf.h index e56688f6b3..c0230e8a64 100644 --- a/src/newgrf.h +++ b/src/newgrf.h @@ -108,7 +108,8 @@ struct GRFLabel { byte label; uint32 nfo_line; size_t pos; - struct GRFLabel *next; + + GRFLabel(byte label, uint32 nfo_line, size_t pos) : label(label), nfo_line(nfo_line), pos(pos) {} }; enum GRFPropertyMapFallbackMode { @@ -330,7 +331,7 @@ struct GRFFile : ZeroedMemoryAllocator { uint32 param[0x80]; uint param_end; ///< one more than the highest set parameter - GRFLabel *label; ///< Pointer to the first label. This is a linked list, not an array. + std::vector labels; ///< List of labels std::vector cargo_list; ///< Cargo translation table (local ID -> label) uint8 cargo_map[NUM_CARGO]; ///< Inverse cargo translation table (CargoID -> local ID) diff --git a/src/newgrf_engine.cpp b/src/newgrf_engine.cpp index 8d9c9254a2..3d5606a757 100644 --- a/src/newgrf_engine.cpp +++ b/src/newgrf_engine.cpp @@ -1133,6 +1133,8 @@ static uint32 VehicleGetVariable(Vehicle *v, const VehicleScopeResolver *object, case 0x92: return Clamp(_date - DAYS_TILL_ORIGINAL_BASE_YEAR, 0, 0xFFFF); // Date of last service case 0x93: return GB(Clamp(_date - DAYS_TILL_ORIGINAL_BASE_YEAR, 0, 0xFFFF), 8, 8); case 0xC4: return Clamp(_cur_year, ORIGINAL_BASE_YEAR, ORIGINAL_MAX_YEAR) - ORIGINAL_BASE_YEAR; // Build year + case 0xC6: return Engine::Get(this->self_type)->grf_prop.local_id; + case 0xC7: return GB(Engine::Get(this->self_type)->grf_prop.local_id, 8, 8); case 0xDA: return INVALID_VEHICLE; // Next vehicle case 0xF2: return 0; // Cargo subtype } diff --git a/src/road.h b/src/road.h index f2ddb901f9..a64ca2e9b6 100644 --- a/src/road.h +++ b/src/road.h @@ -77,6 +77,7 @@ enum RoadTypeSpriteGroup { ROTSG_DEPOT, ///< Optional: Depot images ROTSG_reserved3, ///< Placeholder, if we add road fences (for highways). ROTSG_ROADSTOP, ///< Required: Drive-in stop surface + ROTSG_ONEWAY, ///< Optional: One-way indicator images ROTSG_END, }; diff --git a/src/road_cmd.cpp b/src/road_cmd.cpp index 8fb07606af..0c06b661ca 100644 --- a/src/road_cmd.cpp +++ b/src/road_cmd.cpp @@ -2159,7 +2159,17 @@ void DrawRoadBits(TileInfo *ti, RoadBits road, RoadBits tram, Roadside roadside, if (is_road_tile && road_rti != nullptr) { DisallowedRoadDirections drd = GetDisallowedRoadDirections(ti->tile); if (drd != DRD_NONE) { - DrawGroundSpriteAt(SPR_ONEWAY_BASE + drd - 1 + ((road == ROAD_X) ? 0 : 3), PAL_NONE, 8, 8, GetPartialPixelZ(8, 8, ti->tileh)); + SpriteID oneway = GetCustomRoadSprite(road_rti, ti->tile, ROTSG_ONEWAY); + + if (oneway == 0) oneway = SPR_ONEWAY_BASE; + + if ((ti->tileh == SLOPE_NE) || (ti->tileh == SLOPE_NW)) { + oneway += SPR_ONEWAY_SLOPE_N_OFFSET; + } else if ((ti->tileh == SLOPE_SE) || (ti->tileh == SLOPE_SW)) { + oneway += SPR_ONEWAY_SLOPE_S_OFFSET; + } + + DrawGroundSpriteAt(oneway + drd - 1 + ((road == ROAD_X) ? 0 : 3), PAL_NONE, 8, 8, GetPartialPixelZ(8, 8, ti->tileh)); } } diff --git a/src/saveload/oldloader_sl.cpp b/src/saveload/oldloader_sl.cpp index dfc375c216..6450d07b16 100644 --- a/src/saveload/oldloader_sl.cpp +++ b/src/saveload/oldloader_sl.cpp @@ -402,7 +402,8 @@ static bool FixTTOEngines() if (oi == 255) { /* Default engine is used */ _date += DAYS_TILL_ORIGINAL_BASE_YEAR; - StartupOneEngine(e, aging_date, INT_MAX); + StartupOneEngine(e, aging_date, 0, INT_MAX); + CalcEngineReliability(e, false); e->intro_date -= DAYS_TILL_ORIGINAL_BASE_YEAR; _date -= DAYS_TILL_ORIGINAL_BASE_YEAR; diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp index 63701ecbd5..84d182e834 100644 --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -242,7 +242,6 @@ struct SaveLoadParams { StringID error_str; ///< the translatable error message to show char *extra_msg; ///< the error message - uint16 game_speed; ///< The game speed when saving started. bool saveinprogress; ///< Whether there is currently a save in progress. SaveModeFlags save_flags; ///< Save mode flags }; @@ -3148,15 +3147,9 @@ static inline void ClearSaveLoadState() GamelogStopAnyAction(); } -/** - * Update the gui accordingly when starting saving - * and set locks on saveload. Also turn off fast-forward cause with that - * saving takes Aaaaages - */ +/** Update the gui accordingly when starting saving and set locks on saveload. */ static void SaveFileStart() { - _sl.game_speed = _game_speed; - _game_speed = 100; SetMouseCursorBusy(true); InvalidateWindowData(WC_STATUS_BAR, 0, SBI_SAVELOAD_START); @@ -3166,7 +3159,6 @@ static void SaveFileStart() /** Update the gui accordingly when saving is done and release locks on saveload. */ static void SaveFileDone() { - if (_game_mode != GM_MENU) _game_speed = _sl.game_speed; SetMouseCursorBusy(false); InvalidateWindowData(WC_STATUS_BAR, 0, SBI_SAVELOAD_FINISH); diff --git a/src/table/engines.h b/src/table/engines.h index 2a207dd760..e3b1481d7f 100644 --- a/src/table/engines.h +++ b/src/table/engines.h @@ -24,7 +24,7 @@ * @param f Bitmask of the climates * @note the 5 between b and f is the load amount */ -#define MT(a, b, c, d, e, f) { DAYS_TILL_ORIGINAL_BASE_YEAR + a, c, d, b, 5, f, e, 0, 8, 0, 0, 0, STR_EMPTY, CARGO_AGING_TICKS } +#define MT(a, b, c, d, e, f) { DAYS_TILL_ORIGINAL_BASE_YEAR + a, c, d, b, 5, f, e, 0, 8, 0, 0, 0, STR_EMPTY, CARGO_AGING_TICKS, INVALID_ENGINE, ExtraEngineFlags::None } /** * Writes the properties of a multiple-unit train into the EngineInfo struct. @@ -37,7 +37,7 @@ * @param f Bitmask of the climates * @note the 5 between b and f is the load amount */ -#define MM(a, b, c, d, e, f) { DAYS_TILL_ORIGINAL_BASE_YEAR + a, c, d, b, 5, f, e, 0, 8, 1 << EF_RAIL_IS_MU, 0, 0, STR_EMPTY, CARGO_AGING_TICKS } +#define MM(a, b, c, d, e, f) { DAYS_TILL_ORIGINAL_BASE_YEAR + a, c, d, b, 5, f, e, 0, 8, 1 << EF_RAIL_IS_MU, 0, 0, STR_EMPTY, CARGO_AGING_TICKS, INVALID_ENGINE, ExtraEngineFlags::None } /** * Writes the properties of a train carriage into the EngineInfo struct. @@ -50,7 +50,7 @@ * @see MT * @note the 5 between b and f is the load amount */ -#define MW(a, b, c, d, e, f) { DAYS_TILL_ORIGINAL_BASE_YEAR + a, c, d, b, 5, f, e, 0, 8, 0, 0, 0, STR_EMPTY, CARGO_AGING_TICKS } +#define MW(a, b, c, d, e, f) { DAYS_TILL_ORIGINAL_BASE_YEAR + a, c, d, b, 5, f, e, 0, 8, 0, 0, 0, STR_EMPTY, CARGO_AGING_TICKS, INVALID_ENGINE, ExtraEngineFlags::None } /** * Writes the properties of a road vehicle into the EngineInfo struct. @@ -63,7 +63,7 @@ * @param f Bitmask of the climates * @note the 5 between b and f is the load amount */ -#define MR(a, b, c, d, e, f) { DAYS_TILL_ORIGINAL_BASE_YEAR + a, c, d, b, 5, f, e, 0, 8, 0, 0, 0, STR_EMPTY, CARGO_AGING_TICKS } +#define MR(a, b, c, d, e, f) { DAYS_TILL_ORIGINAL_BASE_YEAR + a, c, d, b, 5, f, e, 0, 8, 0, 0, 0, STR_EMPTY, CARGO_AGING_TICKS, INVALID_ENGINE, ExtraEngineFlags::None } /** * Writes the properties of a ship into the EngineInfo struct. @@ -75,7 +75,7 @@ * @param f Bitmask of the climates * @note the 10 between b and f is the load amount */ -#define MS(a, b, c, d, e, f) { DAYS_TILL_ORIGINAL_BASE_YEAR + a, c, d, b, 10, f, e, 0, 8, 0, 0, 0, STR_EMPTY, CARGO_AGING_TICKS } +#define MS(a, b, c, d, e, f) { DAYS_TILL_ORIGINAL_BASE_YEAR + a, c, d, b, 10, f, e, 0, 8, 0, 0, 0, STR_EMPTY, CARGO_AGING_TICKS, INVALID_ENGINE, ExtraEngineFlags::None } /** * Writes the properties of an aeroplane into the EngineInfo struct. @@ -86,7 +86,7 @@ * @param e Bitmask of the climates * @note the 20 between b and e is the load amount */ -#define MA(a, b, c, d, e) { DAYS_TILL_ORIGINAL_BASE_YEAR + a, c, d, b, 20, e, CT_INVALID, 0, 8, 0, 0, 0, STR_EMPTY, CARGO_AGING_TICKS } +#define MA(a, b, c, d, e) { DAYS_TILL_ORIGINAL_BASE_YEAR + a, c, d, b, 20, e, CT_INVALID, 0, 8, 0, 0, 0, STR_EMPTY, CARGO_AGING_TICKS, INVALID_ENGINE, ExtraEngineFlags::None } /* Climates * T = Temperate diff --git a/src/table/sprites.h b/src/table/sprites.h index edbd286ebd..83d442bd10 100644 --- a/src/table/sprites.h +++ b/src/table/sprites.h @@ -290,8 +290,10 @@ static const SpriteID SPR_TRAMWAY_DEPOT_NO_TRACK = SPR_TRAMWAY_BASE + 113; static const uint16 TRAMWAY_SPRITE_COUNT = 119; /** One way road sprites */ -static const SpriteID SPR_ONEWAY_BASE = SPR_TRAMWAY_BASE + TRAMWAY_SPRITE_COUNT; -static const uint16 ONEWAY_SPRITE_COUNT = 6; +static const SpriteID SPR_ONEWAY_BASE = SPR_TRAMWAY_BASE + TRAMWAY_SPRITE_COUNT; +static const SpriteID SPR_ONEWAY_SLOPE_N_OFFSET = 6; +static const SpriteID SPR_ONEWAY_SLOPE_S_OFFSET = 12; +static const uint16 ONEWAY_SPRITE_COUNT = 18; /** Tunnel sprites with grass only for custom railtype tunnel. */ static const SpriteID SPR_RAILTYPE_TUNNEL_BASE = SPR_ONEWAY_BASE + ONEWAY_SPRITE_COUNT; diff --git a/src/timetable_gui.cpp b/src/timetable_gui.cpp index 23a5eb5e4f..4d7ca57a03 100644 --- a/src/timetable_gui.cpp +++ b/src/timetable_gui.cpp @@ -636,27 +636,19 @@ struct TimetableWindow : GeneralVehicleWindow { { switch (widget) { case WID_VT_CHANGE_TIME: { - uint64 params[1]; - params[0] = STR_TIMETABLE_WAIT_TIME_TOOLTIP; - GuiShowTooltips(this, STR_TIMETABLE_WAIT_TIME_TOOLTIP_EXTRA, 1, params, close_cond); + GuiShowTooltips(this, STR_TIMETABLE_WAIT_TIME_TOOLTIP, 0, nullptr, close_cond); return true; } case WID_VT_CLEAR_TIME: { - uint64 params[1]; - params[0] = STR_TIMETABLE_CLEAR_TIME_TOOLTIP; - GuiShowTooltips(this, STR_TIMETABLE_CLEAR_TIME_TOOLTIP_EXTRA, 1, params, close_cond); + GuiShowTooltips(this, STR_TIMETABLE_CLEAR_TIME_TOOLTIP, 0, nullptr, close_cond); return true; } case WID_VT_CHANGE_SPEED: { - uint64 params[1]; - params[0] = STR_TIMETABLE_CHANGE_SPEED_TOOLTIP; - GuiShowTooltips(this, STR_TIMETABLE_CHANGE_SPEED_TOOLTIP_EXTRA, 1, params, close_cond); + GuiShowTooltips(this, STR_TIMETABLE_CHANGE_SPEED_TOOLTIP, 0, nullptr, close_cond); return true; } case WID_VT_CLEAR_SPEED: { - uint64 params[1]; - params[0] = STR_TIMETABLE_CLEAR_SPEED_TOOLTIP; - GuiShowTooltips(this, STR_TIMETABLE_CLEAR_SPEED_TOOLTIP_EXTRA, 1, params, close_cond); + GuiShowTooltips(this, STR_TIMETABLE_CLEAR_SPEED_TOOLTIP, 0, nullptr, close_cond); return true; } default: diff --git a/src/town_gui.cpp b/src/town_gui.cpp index 3820ec08b8..05572f85d4 100644 --- a/src/town_gui.cpp +++ b/src/town_gui.cpp @@ -84,6 +84,9 @@ private: Scrollbar *vscroll; uint displayed_actions_on_previous_painting; ///< Actions that were available on the previous call to OnPaint() + Dimension icon_size; ///< Dimensions of company icon + Dimension exclusive_size; ///< Dimensions of exlusive icon + /** * Get the position of the Nth set bit. * @@ -121,6 +124,12 @@ public: this->vscroll->SetCapacity((this->GetWidget(WID_TA_COMMAND_LIST)->current_y - WidgetDimensions::scaled.framerect.Vertical()) / FONT_HEIGHT_NORMAL); } + void OnInit() override + { + this->icon_size = GetSpriteSize(SPR_COMPANY_ICON); + this->exclusive_size = GetSpriteSize(SPR_EXCLUSIVE_TRANSPORT); + } + void OnPaint() override { int numact; @@ -149,26 +158,22 @@ public: { Rect r = this->GetWidget(WID_TA_RATING_INFO)->GetCurrentRect().Shrink(WidgetDimensions::scaled.framerect); - DrawString(r, STR_LOCAL_AUTHORITY_COMPANY_RATINGS); - r.top += FONT_HEIGHT_NORMAL; + int text_y_offset = (this->resize.step_height - FONT_HEIGHT_NORMAL) / 2; + int icon_y_offset = (this->resize.step_height - this->icon_size.height) / 2; + int exclusive_y_offset = (this->resize.step_height - this->exclusive_size.height) / 2; - Dimension icon_size = GetSpriteSize(SPR_COMPANY_ICON); - int icon_width = icon_size.width; - int icon_y_offset = (FONT_HEIGHT_NORMAL - icon_size.height) / 2; - - Dimension exclusive_size = GetSpriteSize(SPR_EXCLUSIVE_TRANSPORT); - int exclusive_width = exclusive_size.width; - int exclusive_y_offset = (FONT_HEIGHT_NORMAL - exclusive_size.height) / 2; + DrawString(r.left, r.right, r.top + text_y_offset, STR_LOCAL_AUTHORITY_COMPANY_RATINGS); + r.top += this->resize.step_height; bool rtl = _current_text_dir == TD_RTL; - Rect text = r.Indent(icon_width + WidgetDimensions::scaled.hsep_normal + exclusive_width + WidgetDimensions::scaled.hsep_normal, rtl); - uint icon_left = r.WithWidth(icon_width, rtl).left; - uint exclusive_left = r.Indent(icon_width + WidgetDimensions::scaled.hsep_normal, rtl).WithWidth(exclusive_width, rtl).left; + Rect icon = r.WithWidth(this->icon_size.width, rtl); + Rect exclusive = r.Indent(this->icon_size.width + WidgetDimensions::scaled.hsep_normal, rtl).WithWidth(this->exclusive_size.width, rtl); + Rect text = r.Indent(this->icon_size.width + WidgetDimensions::scaled.hsep_normal + this->exclusive_size.width + WidgetDimensions::scaled.hsep_normal, rtl); /* Draw list of companies */ for (const Company *c : Company::Iterate()) { if ((HasBit(this->town->have_ratings, c->index) || this->town->exclusivity == c->index)) { - DrawCompanyIcon(c->index, icon_left, text.top + icon_y_offset); + DrawCompanyIcon(c->index, icon.left, text.top + icon_y_offset); SetDParam(0, c->index); SetDParam(1, c->index); @@ -185,11 +190,11 @@ public: SetDParam(2, str); if (this->town->exclusivity == c->index) { - DrawSprite(SPR_EXCLUSIVE_TRANSPORT, COMPANY_SPRITE_COLOUR(c->index), exclusive_left, r.top + exclusive_y_offset); + DrawSprite(SPR_EXCLUSIVE_TRANSPORT, COMPANY_SPRITE_COLOUR(c->index), exclusive.left, text.top + exclusive_y_offset); } - DrawString(text, STR_LOCAL_AUTHORITY_COMPANY_RATING); - text.top += FONT_HEIGHT_NORMAL; + DrawString(text.left, text.right, text.top + text_y_offset, STR_LOCAL_AUTHORITY_COMPANY_RATING); + text.top += this->resize.step_height; } } @@ -346,8 +351,8 @@ public: break; case WID_TA_RATING_INFO: - resize->height = FONT_HEIGHT_NORMAL; - size->height = 9 * FONT_HEIGHT_NORMAL + padding.height; + resize->height = std::max({this->icon_size.height + WidgetDimensions::scaled.vsep_normal, this->exclusive_size.height + WidgetDimensions::scaled.vsep_normal, (uint)FONT_HEIGHT_NORMAL}); + size->height = 9 * resize->height + padding.height; break; } } @@ -1217,7 +1222,9 @@ static const NWidgetPart _nested_found_town_widgets[] = { NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_TF_RANDOM_TOWN), SetMinimalSize(156, 12), SetFill(1, 0), SetDataTip(STR_FOUND_TOWN_RANDOM_TOWN_BUTTON, STR_FOUND_TOWN_RANDOM_TOWN_TOOLTIP), SetPadding(0, 2, 1, 2), NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_TF_MANY_RANDOM_TOWNS), SetMinimalSize(156, 12), SetFill(1, 0), - SetDataTip(STR_FOUND_TOWN_MANY_RANDOM_TOWNS, STR_FOUND_TOWN_RANDOM_TOWNS_TOOLTIP), SetPadding(0, 2, 0, 2), + SetDataTip(STR_FOUND_TOWN_MANY_RANDOM_TOWNS, STR_FOUND_TOWN_RANDOM_TOWNS_TOOLTIP), SetPadding(0, 2, 1, 2), + NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_TF_EXPAND_ALL_TOWNS), SetMinimalSize(156, 12), SetFill(1, 0), + SetDataTip(STR_FOUND_TOWN_EXPAND_ALL_TOWNS, STR_FOUND_TOWN_EXPAND_ALL_TOWNS_TOOLTIP), SetPadding(0, 2, 0, 2), /* Town name selection. */ NWidget(WWT_LABEL, COLOUR_DARK_GREEN), SetMinimalSize(156, 14), SetPadding(0, 2, 0, 2), SetDataTip(STR_FOUND_TOWN_NAME_TITLE, STR_NULL), NWidget(WWT_EDITBOX, COLOUR_GREY, WID_TF_TOWN_NAME_EDITBOX), SetMinimalSize(156, 12), SetPadding(0, 2, 3, 2), @@ -1311,7 +1318,7 @@ public: void UpdateButtons(bool check_availability) { if (check_availability && _game_mode != GM_EDITOR) { - this->SetWidgetsDisabledState(true, WID_TF_RANDOM_TOWN, WID_TF_MANY_RANDOM_TOWNS, WID_TF_SIZE_LARGE, WIDGET_LIST_END); + this->SetWidgetsDisabledState(true, WID_TF_RANDOM_TOWN, WID_TF_MANY_RANDOM_TOWNS, WID_TF_EXPAND_ALL_TOWNS, WID_TF_SIZE_LARGE, WIDGET_LIST_END); this->SetWidgetsDisabledState(_settings_game.economy.found_town != TF_CUSTOM_LAYOUT, WID_TF_LAYOUT_ORIGINAL, WID_TF_LAYOUT_BETTER, WID_TF_LAYOUT_GRID2, WID_TF_LAYOUT_GRID3, WID_TF_LAYOUT_RANDOM, WIDGET_LIST_END); if (_settings_game.economy.found_town != TF_CUSTOM_LAYOUT) town_layout = _settings_game.economy.town_layout; @@ -1377,6 +1384,12 @@ public: break; } + case WID_TF_EXPAND_ALL_TOWNS: + for (Town *t : Town::Iterate()) { + DoCommand(0, t->index, 0, DC_EXEC, CMD_EXPAND_TOWN); + } + break; + case WID_TF_SIZE_SMALL: case WID_TF_SIZE_MEDIUM: case WID_TF_SIZE_LARGE: case WID_TF_SIZE_RANDOM: this->town_size = (TownSize)(widget - WID_TF_SIZE_SMALL); this->UpdateButtons(false); diff --git a/src/vehicle_gui.cpp b/src/vehicle_gui.cpp index e7ae8e760d..f090aa71a2 100644 --- a/src/vehicle_gui.cpp +++ b/src/vehicle_gui.cpp @@ -1666,18 +1666,23 @@ static const NWidgetPart _nested_vehicle_list[] = { EndContainer(), NWidget(NWID_HORIZONTAL), - NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_VL_GROUP_ORDER), SetMinimalSize(81, 12), SetFill(0, 1), SetDataTip(STR_STATION_VIEW_GROUP, STR_TOOLTIP_GROUP_ORDER), - NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_VL_GROUP_BY_PULLDOWN), SetMinimalSize(167, 12), SetFill(0, 1), SetDataTip(0x0, STR_TOOLTIP_GROUP_ORDER), - NWidget(WWT_PANEL, COLOUR_GREY), SetMinimalSize(12, 12), SetFill(1, 1), SetResize(1, 0), EndContainer(), - EndContainer(), - - NWidget(NWID_HORIZONTAL), - NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_VL_SORT_ORDER), SetMinimalSize(81, 12), SetFill(0, 1), SetDataTip(STR_BUTTON_SORT_BY, STR_TOOLTIP_SORT_ORDER), - NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_VL_SORT_BY_PULLDOWN), SetMinimalSize(167, 12), SetFill(0, 1), SetDataTip(0x0, STR_TOOLTIP_SORT_CRITERIA), - NWidget(NWID_SELECTION, INVALID_COLOUR, WID_VL_FILTER_BY_CARGO_SEL), - NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_VL_FILTER_BY_CARGO), SetMinimalSize(167, 12), SetFill(0, 1), SetDataTip(STR_JUST_STRING, STR_TOOLTIP_FILTER_CRITERIA), + NWidget(NWID_VERTICAL), + NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_VL_GROUP_ORDER), SetMinimalSize(0, 12), SetFill(1, 0), SetDataTip(STR_STATION_VIEW_GROUP, STR_TOOLTIP_GROUP_ORDER), + NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_VL_SORT_ORDER), SetMinimalSize(0, 12), SetFill(1, 0), SetDataTip(STR_BUTTON_SORT_BY, STR_TOOLTIP_SORT_ORDER), + EndContainer(), + NWidget(NWID_VERTICAL), + NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_VL_GROUP_BY_PULLDOWN), SetMinimalSize(0, 12), SetFill(1, 0), SetDataTip(0x0, STR_TOOLTIP_GROUP_ORDER), + NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_VL_SORT_BY_PULLDOWN), SetMinimalSize(0, 12), SetFill(1, 0), SetDataTip(0x0, STR_TOOLTIP_SORT_CRITERIA), + EndContainer(), + NWidget(NWID_VERTICAL), + NWidget(WWT_PANEL, COLOUR_GREY), SetMinimalSize(0, 12), SetFill(1, 1), SetResize(1, 0), EndContainer(), + NWidget(NWID_HORIZONTAL), + NWidget(NWID_SELECTION, INVALID_COLOUR, WID_VL_FILTER_BY_CARGO_SEL), + NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_VL_FILTER_BY_CARGO), SetMinimalSize(0, 12), SetFill(0, 0), SetDataTip(STR_JUST_STRING, STR_TOOLTIP_FILTER_CRITERIA), + EndContainer(), + NWidget(WWT_PANEL, COLOUR_GREY), SetMinimalSize(0, 12), SetFill(1, 1), SetResize(1, 0), EndContainer(), + EndContainer(), EndContainer(), - NWidget(WWT_PANEL, COLOUR_GREY), SetMinimalSize(12, 12), SetFill(1, 1), SetResize(1, 0), EndContainer(), EndContainer(), NWidget(NWID_HORIZONTAL), @@ -2211,6 +2216,20 @@ public: break; } + case WID_VL_GROUP_BY_PULLDOWN: + size->width = GetStringListWidth(this->vehicle_group_by_names) + padding.width; + break; + + case WID_VL_SORT_BY_PULLDOWN: + size->width = GetStringListWidth(this->vehicle_group_none_sorter_names); + size->width = std::max(size->width, GetStringListWidth(this->vehicle_group_shared_orders_sorter_names)); + size->width += padding.width; + break; + + case WID_VL_FILTER_BY_CARGO: + size->width = GetStringListWidth(this->cargo_filter_texts) + padding.width; + break; + case WID_VL_MANAGE_VEHICLES_DROPDOWN: { Dimension d = this->GetActionDropdownSize(this->vli.type == VL_STANDARD, false, this->vli.vtype == VEH_TRAIN, this->GetChangeOrderStringID()); diff --git a/src/widgets/town_widget.h b/src/widgets/town_widget.h index 3a8f1e3b6d..85901f4587 100644 --- a/src/widgets/town_widget.h +++ b/src/widgets/town_widget.h @@ -51,6 +51,7 @@ enum TownFoundingWidgets { WID_TF_NEW_TOWN, ///< Create a new town. WID_TF_RANDOM_TOWN, ///< Randomly place a town. WID_TF_MANY_RANDOM_TOWNS, ///< Randomly place many towns. + WID_TF_EXPAND_ALL_TOWNS, ///< Make all towns grow slightly. WID_TF_TOWN_NAME_EDITBOX, ///< Editor for the town name. WID_TF_TOWN_NAME_RANDOM, ///< Generate a random town name. WID_TF_SIZE_SMALL, ///< Selection for a small town.