Merge branch 'master' into jgrpp

# Conflicts:
#	src/build_vehicle_gui.cpp
#	src/engine.cpp
#	src/engine_func.h
#	src/group_gui.cpp
#	src/lang/english.txt
#	src/newgrf.cpp
#	src/saveload/oldloader_sl.cpp
#	src/timetable_cmd.cpp
#	src/timetable_cmd.h
#	src/timetable_gui.cpp
pull/474/head
Jonathan G Rennison 1 year ago
commit 64c210f770

Binary file not shown.

@ -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 <http://www.gnu.org/licenses/>.
//
-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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

@ -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 <http://www.gnu.org/licenses/>.
//
-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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

@ -83,3 +83,4 @@
#include "rivers/arctic.nfo"
#include "rivers/tropic.nfo"
#include "rivers/toyland.nfo"
#include "fix_gui_icons.nfo"

@ -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<EngineID> 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<EngineID>(std::min<size_t>(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<NWidgetBase>(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. */

@ -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<EngineID> 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<EngineID> 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<NWidgetBase>(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<uint16>(std::min<size_t>(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<EngineID> 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<NWidgetBase>(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<uint16>(this->loco.vscroll->GetPosition() + this->loco.vscroll->GetCapacity(),
static_cast<uint16>(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<uint16>(this->wagon.vscroll->GetPosition() + this->wagon.vscroll->GetCapacity(),
static_cast<uint16>(this->wagon.eng_list.size())), this->wagon.sel_engine, false,
DEFAULT_GROUP);

@ -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<mask_t>::type)m1 | m2);} \
inline mask_t operator & (mask_t m1, mask_t m2) {return (mask_t)((std::underlying_type<mask_t>::type)m1 & m2);} \
inline mask_t operator ^ (mask_t m1, mask_t m2) {return (mask_t)((std::underlying_type<mask_t>::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<mask_t>::type)m);}
inline constexpr mask_t operator | (mask_t m1, mask_t m2) {return (mask_t)((std::underlying_type<mask_t>::type)m1 | (std::underlying_type<mask_t>::type)m2);} \
inline constexpr mask_t operator & (mask_t m1, mask_t m2) {return (mask_t)((std::underlying_type<mask_t>::type)m1 & (std::underlying_type<mask_t>::type)m2);} \
inline constexpr mask_t operator ^ (mask_t m1, mask_t m2) {return (mask_t)((std::underlying_type<mask_t>::type)m1 ^ (std::underlying_type<mask_t>::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<mask_t>::type)m);}
/**

@ -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);
}
}
}

@ -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<Engine, EngineID, 64, 64000> 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 {

@ -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);

@ -14,10 +14,23 @@
#include "sortlist_type.h"
#include "gfx_type.h"
#include "vehicle_type.h"
#include "engine_base.h"
typedef GUIList<EngineID, CargoID> 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<GUIEngineListItem, CargoID> 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);

@ -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;
};
/**

@ -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.

@ -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);

@ -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;

@ -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<CompanyID> 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<CompanyID> 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);

@ -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),

@ -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

@ -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

@ -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

@ -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).

@ -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

@ -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}이 차량의 지연 시간값을 초기화하여, 정시운행 상태로 바꿉니다

@ -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

@ -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 du:
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...

@ -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}Сбросить счётчик отклонения от графика, чтобы транспорт снова считался приходящим вовремя

@ -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<ExtraEngineFlags>(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<ExtraEngineFlags>(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<ExtraEngineFlags>(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<ExtraEngineFlags>(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<GRFLabel>(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);

@ -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<GRFLabel> labels; ///< List of labels
std::vector<CargoLabel> cargo_list; ///< Cargo translation table (local ID -> label)
uint8 cargo_map[NUM_CARGO]; ///< Inverse cargo translation table (CargoID -> local ID)

@ -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
}

@ -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,
};

@ -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));
}
}

@ -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;

@ -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);

@ -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

@ -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;

@ -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:

@ -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<NWidgetBase>(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<NWidgetBase>(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);

@ -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());

@ -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.

Loading…
Cancel
Save