mirror of https://github.com/OpenTTD/OpenTTD
Compare commits
13 Commits
dcdc6f5f65
...
0972d3373f
Author | SHA1 | Date |
---|---|---|
|
0972d3373f | |
|
9a106c4af4 | |
|
db7dd4b03f | |
|
d56312d344 | |
|
1b01a0636c | |
|
bccbd64037 | |
|
434163aa31 | |
|
55605ae8f2 | |
|
7f792e9c5f | |
|
6b6caa6fa8 | |
|
67e56391c7 | |
|
e015e3ecc3 | |
|
8330957a4d |
|
@ -36,3 +36,11 @@ AITown.FoundTown <- function(tile, size, city, layout, name) { return AITown.Fou
|
||||||
|
|
||||||
AIVehicle.SetNameCompat14 <- AIVehicle.SetName;
|
AIVehicle.SetNameCompat14 <- AIVehicle.SetName;
|
||||||
AIVehicle.SetName <- function(id, name) { return AIVehicle.SetNameCompat14(id, AICompat14.Text(name)); }
|
AIVehicle.SetName <- function(id, name) { return AIVehicle.SetNameCompat14(id, AICompat14.Text(name)); }
|
||||||
|
|
||||||
|
AIObject.constructorCompat14 <- AIObject.constructor;
|
||||||
|
foreach(name, object in CompatScriptRootTable) {
|
||||||
|
if (type(object) != "class") continue;
|
||||||
|
if (!object.rawin("constructor")) continue;
|
||||||
|
if (object.constructor != AIObject.constructorCompat14) continue;
|
||||||
|
object.constructor <- function() : (name) { AILog.Error("'" + name + "' is not instantiable"); }
|
||||||
|
}
|
||||||
|
|
|
@ -81,3 +81,11 @@ GSTown.FoundTown <- function(tile, size, city, layout, name) { return GSTown.Fou
|
||||||
|
|
||||||
GSVehicle.SetNameCompat14 <- GSVehicle.SetName;
|
GSVehicle.SetNameCompat14 <- GSVehicle.SetName;
|
||||||
GSVehicle.SetName <- function(id, name) { return GSVehicle.SetNameCompat14(id, GSCompat14.Text(name)); }
|
GSVehicle.SetName <- function(id, name) { return GSVehicle.SetNameCompat14(id, GSCompat14.Text(name)); }
|
||||||
|
|
||||||
|
GSObject.constructorCompat14 <- GSObject.constructor;
|
||||||
|
foreach(name, object in CompatScriptRootTable) {
|
||||||
|
if (type(object) != "class") continue;
|
||||||
|
if (!object.rawin("constructor")) continue;
|
||||||
|
if (object.constructor != GSObject.constructorCompat14) continue;
|
||||||
|
object.constructor <- function() : (name) { GSLog.Error("'" + name + "' is not instantiable"); }
|
||||||
|
}
|
||||||
|
|
|
@ -1125,6 +1125,15 @@ static bool AircraftController(Aircraft *v)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (amd.flags.Test(AirportMovingDataFlag::Land)) {
|
if (amd.flags.Test(AirportMovingDataFlag::Land)) {
|
||||||
|
if (st->airport.blocks.Test(AirportBlock::Zeppeliner)) {
|
||||||
|
/* Zeppeliner blocked the runway, abort landing */
|
||||||
|
v->state = FLYING;
|
||||||
|
UpdateAircraftCache(v);
|
||||||
|
SetAircraftPosition(v, gp.x, gp.y, GetAircraftFlightLevel(v));
|
||||||
|
v->pos = v->previous_pos;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (st->airport.tile == INVALID_TILE) {
|
if (st->airport.tile == INVALID_TILE) {
|
||||||
/* Airport has been removed, abort the landing procedure */
|
/* Airport has been removed, abort the landing procedure */
|
||||||
v->state = FLYING;
|
v->state = FLYING;
|
||||||
|
@ -1782,6 +1791,11 @@ static void AirportClearBlock(const Aircraft *v, const AirportFTAClass *apc)
|
||||||
if (apc->layout[v->previous_pos].blocks != apc->layout[v->pos].blocks) {
|
if (apc->layout[v->previous_pos].blocks != apc->layout[v->pos].blocks) {
|
||||||
Station *st = Station::Get(v->targetairport);
|
Station *st = Station::Get(v->targetairport);
|
||||||
|
|
||||||
|
if (st->airport.blocks.Test(AirportBlock::Zeppeliner) &&
|
||||||
|
apc->layout[v->previous_pos].blocks == AirportBlock::RunwayIn) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
st->airport.blocks.Reset(apc->layout[v->previous_pos].blocks);
|
st->airport.blocks.Reset(apc->layout[v->previous_pos].blocks);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@ enum AirportTypes : uint8_t {
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Flags for airport movement data. */
|
/** Flags for airport movement data. */
|
||||||
enum AirportMovingDataFlag : uint8_t {
|
enum class AirportMovingDataFlag : uint8_t {
|
||||||
NoSpeedClamp, ///< No speed restrictions.
|
NoSpeedClamp, ///< No speed restrictions.
|
||||||
Takeoff, ///< Takeoff movement.
|
Takeoff, ///< Takeoff movement.
|
||||||
SlowTurn, ///< Turn slowly (mostly used in the air).
|
SlowTurn, ///< Turn slowly (mostly used in the air).
|
||||||
|
@ -127,6 +127,7 @@ enum class AirportBlock : uint8_t {
|
||||||
/* end of new blocks */
|
/* end of new blocks */
|
||||||
|
|
||||||
Nothing = 30,
|
Nothing = 30,
|
||||||
|
Zeppeliner = 62, ///< Block for the zeppeliner disaster vehicle.
|
||||||
AirportClosed = 63, ///< Dummy block for indicating a closed airport.
|
AirportClosed = 63, ///< Dummy block for indicating a closed airport.
|
||||||
};
|
};
|
||||||
using AirportBlocks = EnumBitSet<AirportBlock, uint64_t>;
|
using AirportBlocks = EnumBitSet<AirportBlock, uint64_t>;
|
||||||
|
|
|
@ -215,7 +215,7 @@ void DisasterVehicle::UpdatePosition(int x, int y, int z)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Zeppeliner handling, v->state states:
|
* Zeppeliner handling, v->state states:
|
||||||
* 0: Zeppeliner initialization has found a small airport, go there and crash
|
* 0: Zeppeliner initialization has found an airport, go there and crash
|
||||||
* 1: Create crash and animate falling down for extra dramatic effect
|
* 1: Create crash and animate falling down for extra dramatic effect
|
||||||
* 2: Create more smoke and leave debris on ground
|
* 2: Create more smoke and leave debris on ground
|
||||||
* 2: Clear the runway after some time and remove crashed zeppeliner
|
* 2: Clear the runway after some time and remove crashed zeppeliner
|
||||||
|
@ -263,7 +263,7 @@ static bool DisasterTick_Zeppeliner(DisasterVehicle *v)
|
||||||
|
|
||||||
if (IsValidTile(v->tile) && IsAirportTile(v->tile)) {
|
if (IsValidTile(v->tile) && IsAirportTile(v->tile)) {
|
||||||
Station *st = Station::GetByTile(v->tile);
|
Station *st = Station::GetByTile(v->tile);
|
||||||
st->airport.blocks.Reset(AirportBlock::RunwayIn);
|
st->airport.blocks.Reset({AirportBlock::Zeppeliner, AirportBlock::RunwayIn});
|
||||||
AI::NewEvent(GetTileOwner(v->tile), new ScriptEventDisasterZeppelinerCleared(st->index));
|
AI::NewEvent(GetTileOwner(v->tile), new ScriptEventDisasterZeppelinerCleared(st->index));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -300,7 +300,7 @@ static bool DisasterTick_Zeppeliner(DisasterVehicle *v)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsValidTile(v->tile) && IsAirportTile(v->tile)) {
|
if (IsValidTile(v->tile) && IsAirportTile(v->tile)) {
|
||||||
Station::GetByTile(v->tile)->airport.blocks.Set(AirportBlock::RunwayIn);
|
Station::GetByTile(v->tile)->airport.blocks.Reset({AirportBlock::Zeppeliner, AirportBlock::RunwayIn});
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -722,14 +722,14 @@ typedef void DisasterInitProc();
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Zeppeliner which crashes on a small airport if one found,
|
* Zeppeliner which crashes on an airport if one found,
|
||||||
* otherwise crashes on a random tile
|
* otherwise crashes on a random tile
|
||||||
*/
|
*/
|
||||||
static void Disaster_Zeppeliner_Init()
|
static void Disaster_Zeppeliner_Init()
|
||||||
{
|
{
|
||||||
if (!Vehicle::CanAllocateItem(2)) return;
|
if (!Vehicle::CanAllocateItem(2)) return;
|
||||||
|
|
||||||
/* Pick a random place, unless we find a small airport */
|
/* Pick a random place, unless we find an airport */
|
||||||
int x = TileX(RandomTile()) * TILE_SIZE + TILE_SIZE / 2;
|
int x = TileX(RandomTile()) * TILE_SIZE + TILE_SIZE / 2;
|
||||||
|
|
||||||
for (const Station *st : Station::Iterate()) {
|
for (const Station *st : Station::Iterate()) {
|
||||||
|
|
|
@ -1067,6 +1067,7 @@ static uint DeliverGoodsToIndustry(const Station *st, CargoType cargo_type, uint
|
||||||
|
|
||||||
uint amount = std::min(num_pieces, 0xFFFFu - it->waiting);
|
uint amount = std::min(num_pieces, 0xFFFFu - it->waiting);
|
||||||
it->waiting += amount;
|
it->waiting += amount;
|
||||||
|
it->GetOrCreateHistory()[THIS_MONTH].accepted += amount;
|
||||||
it->last_accepted = TimerGameEconomy::date;
|
it->last_accepted = TimerGameEconomy::date;
|
||||||
num_pieces -= amount;
|
num_pieces -= amount;
|
||||||
accepted += amount;
|
accepted += amount;
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
/** @file graph_gui.cpp GUI that shows performance graphs. */
|
/** @file graph_gui.cpp GUI that shows performance graphs. */
|
||||||
|
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
|
#include <ranges>
|
||||||
#include "misc/history_func.hpp"
|
#include "misc/history_func.hpp"
|
||||||
#include "graph_gui.h"
|
#include "graph_gui.h"
|
||||||
#include "window_gui.h"
|
#include "window_gui.h"
|
||||||
|
@ -174,6 +175,7 @@ protected:
|
||||||
static const int GRAPH_PAYMENT_RATE_STEPS = 20; ///< Number of steps on Payment rate graph.
|
static const int GRAPH_PAYMENT_RATE_STEPS = 20; ///< Number of steps on Payment rate graph.
|
||||||
static const int PAYMENT_GRAPH_X_STEP_DAYS = 10; ///< X-axis step label for cargo payment rates "Days in transit".
|
static const int PAYMENT_GRAPH_X_STEP_DAYS = 10; ///< X-axis step label for cargo payment rates "Days in transit".
|
||||||
static const int PAYMENT_GRAPH_X_STEP_SECONDS = 20; ///< X-axis step label for cargo payment rates "Seconds in transit".
|
static const int PAYMENT_GRAPH_X_STEP_SECONDS = 20; ///< X-axis step label for cargo payment rates "Seconds in transit".
|
||||||
|
static const int ECONOMY_YEAR_MINUTES = 12; ///< Minutes per economic year.
|
||||||
static const int ECONOMY_QUARTER_MINUTES = 3; ///< Minutes per economic quarter.
|
static const int ECONOMY_QUARTER_MINUTES = 3; ///< Minutes per economic quarter.
|
||||||
static const int ECONOMY_MONTH_MINUTES = 1; ///< Minutes per economic month.
|
static const int ECONOMY_MONTH_MINUTES = 1; ///< Minutes per economic month.
|
||||||
|
|
||||||
|
@ -182,8 +184,27 @@ protected:
|
||||||
static const int MIN_GRAPH_NUM_LINES_Y = 9; ///< Minimal number of horizontal lines to draw.
|
static const int MIN_GRAPH_NUM_LINES_Y = 9; ///< Minimal number of horizontal lines to draw.
|
||||||
static const int MIN_GRID_PIXEL_SIZE = 20; ///< Minimum distance between graph lines.
|
static const int MIN_GRID_PIXEL_SIZE = 20; ///< Minimum distance between graph lines.
|
||||||
|
|
||||||
uint64_t excluded_data = 0; ///< bitmask of the datasets that shouldn't be displayed.
|
struct GraphScale {
|
||||||
uint64_t excluded_range = 0; ///< bitmask of ranges that should not be displayed.
|
StringID label = STR_NULL;
|
||||||
|
uint8_t month_increment = 0;
|
||||||
|
int16_t x_values_increment = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline constexpr GraphScale MONTHLY_SCALE_WALLCLOCK[] = {
|
||||||
|
{STR_GRAPH_LAST_24_MINUTES_TIME_LABEL, HISTORY_MONTH.total_division, ECONOMY_MONTH_MINUTES},
|
||||||
|
{STR_GRAPH_LAST_72_MINUTES_TIME_LABEL, HISTORY_QUARTER.total_division, ECONOMY_QUARTER_MINUTES},
|
||||||
|
{STR_GRAPH_LAST_288_MINUTES_TIME_LABEL, HISTORY_YEAR.total_division, ECONOMY_YEAR_MINUTES},
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline constexpr GraphScale MONTHLY_SCALE_CALENDAR[] = {
|
||||||
|
{STR_GRAPH_LAST_24_MONTHS, HISTORY_MONTH.total_division, ECONOMY_MONTH_MINUTES},
|
||||||
|
{STR_GRAPH_LAST_24_QUARTERS, HISTORY_QUARTER.total_division, ECONOMY_QUARTER_MINUTES},
|
||||||
|
{STR_GRAPH_LAST_24_YEARS, HISTORY_YEAR.total_division, ECONOMY_YEAR_MINUTES},
|
||||||
|
};
|
||||||
|
|
||||||
|
uint64_t excluded_data = 0; ///< bitmask of datasets hidden by the player.
|
||||||
|
uint64_t excluded_range = 0; ///< bitmask of ranges hidden by the player.
|
||||||
|
uint64_t masked_range = 0; ///< bitmask of ranges that are not available for the current data.
|
||||||
uint8_t num_on_x_axis = 0;
|
uint8_t num_on_x_axis = 0;
|
||||||
uint8_t num_vert_lines = GRAPH_NUM_MONTHS;
|
uint8_t num_vert_lines = GRAPH_NUM_MONTHS;
|
||||||
|
|
||||||
|
@ -210,19 +231,28 @@ protected:
|
||||||
};
|
};
|
||||||
std::vector<DataSet> data{};
|
std::vector<DataSet> data{};
|
||||||
|
|
||||||
std::span<const StringID> ranges = {};
|
std::span<const StringID> ranges{};
|
||||||
|
std::span<const GraphScale> scales{};
|
||||||
|
uint8_t selected_scale = 0;
|
||||||
|
|
||||||
uint8_t highlight_data = UINT8_MAX; ///< Data set that should be highlighted, or UINT8_MAX for none.
|
uint8_t highlight_data = UINT8_MAX; ///< Data set that should be highlighted, or UINT8_MAX for none.
|
||||||
uint8_t highlight_range = UINT8_MAX; ///< Data range that should be highlighted, or UINT8_MAX for none.
|
uint8_t highlight_range = UINT8_MAX; ///< Data range that should be highlighted, or UINT8_MAX for none.
|
||||||
bool highlight_state = false; ///< Current state of highlight, toggled every TIMER_BLINK_INTERVAL period.
|
bool highlight_state = false; ///< Current state of highlight, toggled every TIMER_BLINK_INTERVAL period.
|
||||||
|
|
||||||
template <typename Tprojection>
|
struct BaseFiller {
|
||||||
struct Filler {
|
|
||||||
DataSet &dataset; ///< Dataset to fill.
|
DataSet &dataset; ///< Dataset to fill.
|
||||||
|
|
||||||
|
inline void MakeZero(uint i) const { this->dataset.values[i] = 0; }
|
||||||
|
inline void MakeInvalid(uint i) const { this->dataset.values[i] = INVALID_DATAPOINT; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Tprojection>
|
||||||
|
struct Filler : BaseFiller {
|
||||||
const Tprojection &proj; ///< Projection to apply.
|
const Tprojection &proj; ///< Projection to apply.
|
||||||
|
|
||||||
|
constexpr Filler(DataSet &dataset, const Tprojection &proj) : BaseFiller(dataset), proj(proj) {}
|
||||||
|
|
||||||
inline void Fill(uint i, const auto &data) const { this->dataset.values[i] = std::invoke(this->proj, data); }
|
inline void Fill(uint i, const auto &data) const { this->dataset.values[i] = std::invoke(this->proj, data); }
|
||||||
inline void MakeInvalid(uint i) const { this->dataset.values[i] = INVALID_DATAPOINT; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -609,24 +639,34 @@ protected:
|
||||||
this->SetDirty();
|
this->SetDirty();
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
void UpdateMatrixSize(WidgetID widget, Dimension &size, Dimension &resize, auto labels)
|
||||||
|
{
|
||||||
|
size = {};
|
||||||
|
for (const StringID &str : labels) {
|
||||||
|
size = maxdim(size, GetStringBoundingBox(str, FS_SMALL));
|
||||||
|
}
|
||||||
|
|
||||||
|
size.width += WidgetDimensions::scaled.framerect.Horizontal();
|
||||||
|
size.height += WidgetDimensions::scaled.framerect.Vertical();
|
||||||
|
|
||||||
|
/* Set fixed height for number of ranges. */
|
||||||
|
size.height *= static_cast<uint>(std::size(labels));
|
||||||
|
|
||||||
|
resize.width = 0;
|
||||||
|
resize.height = 0;
|
||||||
|
this->GetWidget<NWidgetCore>(widget)->SetMatrixDimension(1, ClampTo<uint32_t>(std::size(labels)));
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
|
void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
|
||||||
{
|
{
|
||||||
switch (widget) {
|
switch (widget) {
|
||||||
case WID_GRAPH_RANGE_MATRIX:
|
case WID_GRAPH_RANGE_MATRIX:
|
||||||
for (const StringID &str : this->ranges) {
|
this->UpdateMatrixSize(widget, size, resize, this->ranges);
|
||||||
size = maxdim(size, GetStringBoundingBox(str, FS_SMALL));
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
size.width += WidgetDimensions::scaled.framerect.Horizontal();
|
case WID_GRAPH_SCALE_MATRIX:
|
||||||
size.height += WidgetDimensions::scaled.framerect.Vertical();
|
this->UpdateMatrixSize(widget, size, resize, this->scales | std::views::transform(&GraphScale::label));
|
||||||
|
|
||||||
/* Set fixed height for number of ranges. */
|
|
||||||
size.height *= static_cast<uint>(std::size(this->ranges));
|
|
||||||
|
|
||||||
resize.width = 0;
|
|
||||||
resize.height = 0;
|
|
||||||
this->GetWidget<NWidgetCore>(WID_GRAPH_RANGE_MATRIX)->SetMatrixDimension(1, ClampTo<uint32_t>(std::size(this->ranges)));
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WID_GRAPH_GRAPH: {
|
case WID_GRAPH_GRAPH: {
|
||||||
|
@ -675,13 +715,17 @@ public:
|
||||||
uint index = 0;
|
uint index = 0;
|
||||||
Rect line = r.WithHeight(line_height);
|
Rect line = r.WithHeight(line_height);
|
||||||
for (const auto &str : this->ranges) {
|
for (const auto &str : this->ranges) {
|
||||||
bool lowered = !HasBit(this->excluded_range, index);
|
bool lowered = !HasBit(this->excluded_range, index) && !HasBit(this->masked_range, index);
|
||||||
|
|
||||||
/* Redraw frame if lowered */
|
/* Redraw frame if lowered */
|
||||||
if (lowered) DrawFrameRect(line, COLOUR_BROWN, FrameFlag::Lowered);
|
if (lowered) DrawFrameRect(line, COLOUR_BROWN, FrameFlag::Lowered);
|
||||||
|
|
||||||
const Rect text = line.Shrink(WidgetDimensions::scaled.framerect);
|
const Rect text = line.Shrink(WidgetDimensions::scaled.framerect);
|
||||||
DrawString(text, str, TC_BLACK, SA_CENTER, false, FS_SMALL);
|
DrawString(text, str, (this->highlight_state && this->highlight_range == index) ? TC_WHITE : TC_BLACK, SA_CENTER, false, FS_SMALL);
|
||||||
|
|
||||||
|
if (HasBit(this->masked_range, index)) {
|
||||||
|
GfxFillRect(line.Shrink(WidgetDimensions::scaled.bevel), GetColourGradient(COLOUR_BROWN, SHADE_DARKER), FILLRECT_CHECKER);
|
||||||
|
}
|
||||||
|
|
||||||
line = line.Translate(0, line_height);
|
line = line.Translate(0, line_height);
|
||||||
++index;
|
++index;
|
||||||
|
@ -689,6 +733,21 @@ public:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case WID_GRAPH_SCALE_MATRIX: {
|
||||||
|
uint line_height = GetCharacterHeight(FS_SMALL) + WidgetDimensions::scaled.framerect.Vertical();
|
||||||
|
uint8_t selected_month_increment = this->scales[this->selected_scale].month_increment;
|
||||||
|
Rect line = r.WithHeight(line_height);
|
||||||
|
for (const auto &scale : this->scales) {
|
||||||
|
/* Redraw frame if selected */
|
||||||
|
if (selected_month_increment == scale.month_increment) DrawFrameRect(line, COLOUR_BROWN, FrameFlag::Lowered);
|
||||||
|
|
||||||
|
DrawString(line.Shrink(WidgetDimensions::scaled.framerect), scale.label, TC_BLACK, SA_CENTER, false, FS_SMALL);
|
||||||
|
|
||||||
|
line = line.Translate(0, line_height);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -704,11 +763,24 @@ public:
|
||||||
case WID_GRAPH_RANGE_MATRIX: {
|
case WID_GRAPH_RANGE_MATRIX: {
|
||||||
int row = GetRowFromWidget(pt.y, widget, 0, GetCharacterHeight(FS_SMALL) + WidgetDimensions::scaled.framerect.Vertical());
|
int row = GetRowFromWidget(pt.y, widget, 0, GetCharacterHeight(FS_SMALL) + WidgetDimensions::scaled.framerect.Vertical());
|
||||||
|
|
||||||
|
if (HasBit(this->masked_range, row)) break;
|
||||||
ToggleBit(this->excluded_range, row);
|
ToggleBit(this->excluded_range, row);
|
||||||
this->SetDirty();
|
this->SetDirty();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case WID_GRAPH_SCALE_MATRIX: {
|
||||||
|
int row = GetRowFromWidget(pt.y, widget, 0, GetCharacterHeight(FS_SMALL) + WidgetDimensions::scaled.framerect.Vertical());
|
||||||
|
const auto &scale = this->scales[row];
|
||||||
|
if (this->selected_scale != row) {
|
||||||
|
this->selected_scale = row;
|
||||||
|
this->month_increment = scale.month_increment;
|
||||||
|
this->x_values_increment = scale.x_values_increment;
|
||||||
|
this->InvalidateData();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1115,6 +1187,7 @@ struct BaseCargoGraphWindow : BaseGraphWindow {
|
||||||
{
|
{
|
||||||
this->CreateNestedTree();
|
this->CreateNestedTree();
|
||||||
|
|
||||||
|
this->excluded_range = this->masked_range;
|
||||||
this->cargo_types = this->GetCargoTypes(number);
|
this->cargo_types = this->GetCargoTypes(number);
|
||||||
|
|
||||||
this->vscroll = this->GetScrollbar(WID_GRAPH_MATRIX_SCROLLBAR);
|
this->vscroll = this->GetScrollbar(WID_GRAPH_MATRIX_SCROLLBAR);
|
||||||
|
@ -1608,7 +1681,9 @@ CompanyID PerformanceRatingDetailWindow::company = CompanyID::Invalid();
|
||||||
struct IndustryProductionGraphWindow : BaseCargoGraphWindow {
|
struct IndustryProductionGraphWindow : BaseCargoGraphWindow {
|
||||||
static inline constexpr StringID RANGE_LABELS[] = {
|
static inline constexpr StringID RANGE_LABELS[] = {
|
||||||
STR_GRAPH_INDUSTRY_RANGE_PRODUCED,
|
STR_GRAPH_INDUSTRY_RANGE_PRODUCED,
|
||||||
STR_GRAPH_INDUSTRY_RANGE_TRANSPORTED
|
STR_GRAPH_INDUSTRY_RANGE_TRANSPORTED,
|
||||||
|
STR_GRAPH_INDUSTRY_RANGE_DELIVERED,
|
||||||
|
STR_GRAPH_INDUSTRY_RANGE_WAITING,
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline CargoTypes excluded_cargo_types{};
|
static inline CargoTypes excluded_cargo_types{};
|
||||||
|
@ -1623,13 +1698,27 @@ struct IndustryProductionGraphWindow : BaseCargoGraphWindow {
|
||||||
this->draw_dates = !TimerGameEconomy::UsingWallclockUnits();
|
this->draw_dates = !TimerGameEconomy::UsingWallclockUnits();
|
||||||
this->ranges = RANGE_LABELS;
|
this->ranges = RANGE_LABELS;
|
||||||
|
|
||||||
|
const Industry *i = Industry::Get(window_number);
|
||||||
|
if (!i->IsCargoProduced()) this->masked_range = (1U << 0) | (1U << 1);
|
||||||
|
if (!i->IsCargoAccepted()) this->masked_range = (1U << 2) | (1U << 3);
|
||||||
|
|
||||||
this->InitializeWindow(window_number, STR_GRAPH_LAST_24_MINUTES_TIME_LABEL);
|
this->InitializeWindow(window_number, STR_GRAPH_LAST_24_MINUTES_TIME_LABEL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OnInit() override
|
||||||
|
{
|
||||||
|
this->BaseCargoGraphWindow::OnInit();
|
||||||
|
|
||||||
|
this->scales = TimerGameEconomy::UsingWallclockUnits() ? MONTHLY_SCALE_WALLCLOCK : MONTHLY_SCALE_CALENDAR;
|
||||||
|
}
|
||||||
|
|
||||||
CargoTypes GetCargoTypes(WindowNumber window_number) const override
|
CargoTypes GetCargoTypes(WindowNumber window_number) const override
|
||||||
{
|
{
|
||||||
CargoTypes cargo_types{};
|
CargoTypes cargo_types{};
|
||||||
const Industry *i = Industry::Get(window_number);
|
const Industry *i = Industry::Get(window_number);
|
||||||
|
for (const auto &a : i->accepted) {
|
||||||
|
if (IsValidCargoType(a.cargo)) SetBit(cargo_types, a.cargo);
|
||||||
|
}
|
||||||
for (const auto &p : i->produced) {
|
for (const auto &p : i->produced) {
|
||||||
if (IsValidCargoType(p.cargo)) SetBit(cargo_types, p.cargo);
|
if (IsValidCargoType(p.cargo)) SetBit(cargo_types, p.cargo);
|
||||||
}
|
}
|
||||||
|
@ -1643,14 +1732,14 @@ struct IndustryProductionGraphWindow : BaseCargoGraphWindow {
|
||||||
|
|
||||||
std::string GetWidgetString(WidgetID widget, StringID stringid) const override
|
std::string GetWidgetString(WidgetID widget, StringID stringid) const override
|
||||||
{
|
{
|
||||||
if (widget == WID_GRAPH_CAPTION) return GetString(STR_GRAPH_INDUSTRY_PRODUCTION_CAPTION, this->window_number);
|
if (widget == WID_GRAPH_CAPTION) return GetString(STR_GRAPH_INDUSTRY_CAPTION, this->window_number);
|
||||||
|
|
||||||
return this->Window::GetWidgetString(widget, stringid);
|
return this->Window::GetWidgetString(widget, stringid);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateStatistics(bool initialize) override
|
void UpdateStatistics(bool initialize) override
|
||||||
{
|
{
|
||||||
int mo = TimerGameEconomy::month - this->num_vert_lines;
|
int mo = (TimerGameEconomy::month / this->month_increment - this->num_vert_lines) * this->month_increment;
|
||||||
auto yr = TimerGameEconomy::year;
|
auto yr = TimerGameEconomy::year;
|
||||||
while (mo < 0) {
|
while (mo < 0) {
|
||||||
yr--;
|
yr--;
|
||||||
|
@ -1688,7 +1777,34 @@ struct IndustryProductionGraphWindow : BaseCargoGraphWindow {
|
||||||
transported.dash = 2;
|
transported.dash = 2;
|
||||||
auto transported_filler = Filler{transported, &Industry::ProducedHistory::transported};
|
auto transported_filler = Filler{transported, &Industry::ProducedHistory::transported};
|
||||||
|
|
||||||
FillFromHistory<GRAPH_NUM_MONTHS>(p.history, i->valid_history, produced_filler, transported_filler);
|
FillFromHistory<GRAPH_NUM_MONTHS>(p.history, i->valid_history, this->selected_scale, produced_filler, transported_filler);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto &a : i->accepted) {
|
||||||
|
if (!IsValidCargoType(a.cargo)) continue;
|
||||||
|
const CargoSpec *cs = CargoSpec::Get(a.cargo);
|
||||||
|
|
||||||
|
this->data.reserve(this->data.size() + 2);
|
||||||
|
|
||||||
|
DataSet &accepted = this->data.emplace_back();
|
||||||
|
accepted.colour = cs->legend_colour;
|
||||||
|
accepted.exclude_bit = cs->Index();
|
||||||
|
accepted.range_bit = 2;
|
||||||
|
accepted.dash = 1;
|
||||||
|
auto accepted_filler = Filler{accepted, &Industry::AcceptedHistory::accepted};
|
||||||
|
|
||||||
|
DataSet &waiting = this->data.emplace_back();
|
||||||
|
waiting.colour = cs->legend_colour;
|
||||||
|
waiting.exclude_bit = cs->Index();
|
||||||
|
waiting.range_bit = 3;
|
||||||
|
waiting.dash = 4;
|
||||||
|
auto waiting_filler = Filler{waiting, &Industry::AcceptedHistory::waiting};
|
||||||
|
|
||||||
|
if (a.history == nullptr) {
|
||||||
|
FillFromEmpty<GRAPH_NUM_MONTHS>(i->valid_history, this->selected_scale, accepted_filler, waiting_filler);
|
||||||
|
} else {
|
||||||
|
FillFromHistory<GRAPH_NUM_MONTHS>(*a.history, i->valid_history, this->selected_scale, accepted_filler, waiting_filler);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this->SetDirty();
|
this->SetDirty();
|
||||||
|
@ -1708,7 +1824,7 @@ static constexpr NWidgetPart _nested_industry_production_widgets[] = {
|
||||||
NWidget(WWT_EMPTY, INVALID_COLOUR, WID_GRAPH_GRAPH), SetMinimalSize(495, 0), SetFill(1, 1), SetResize(1, 1),
|
NWidget(WWT_EMPTY, INVALID_COLOUR, WID_GRAPH_GRAPH), SetMinimalSize(495, 0), SetFill(1, 1), SetResize(1, 1),
|
||||||
NWidget(NWID_VERTICAL),
|
NWidget(NWID_VERTICAL),
|
||||||
NWidget(NWID_SPACER), SetMinimalSize(0, 24), SetFill(0, 1),
|
NWidget(NWID_SPACER), SetMinimalSize(0, 24), SetFill(0, 1),
|
||||||
NWidget(WWT_MATRIX, COLOUR_BROWN, WID_GRAPH_RANGE_MATRIX), SetFill(1, 0), SetResize(0, 0), SetMatrixDataTip(1, 0, STR_GRAPH_CARGO_PAYMENT_TOGGLE_CARGO),
|
NWidget(WWT_MATRIX, COLOUR_BROWN, WID_GRAPH_RANGE_MATRIX), SetFill(1, 0), SetResize(0, 0), SetMatrixDataTip(1, 0, STR_GRAPH_TOGGLE_RANGE),
|
||||||
NWidget(NWID_SPACER), SetMinimalSize(0, 4),
|
NWidget(NWID_SPACER), SetMinimalSize(0, 4),
|
||||||
NWidget(WWT_PUSHTXTBTN, COLOUR_BROWN, WID_GRAPH_ENABLE_CARGOES), SetStringTip(STR_GRAPH_CARGO_ENABLE_ALL, STR_GRAPH_CARGO_TOOLTIP_ENABLE_ALL), SetFill(1, 0),
|
NWidget(WWT_PUSHTXTBTN, COLOUR_BROWN, WID_GRAPH_ENABLE_CARGOES), SetStringTip(STR_GRAPH_CARGO_ENABLE_ALL, STR_GRAPH_CARGO_TOOLTIP_ENABLE_ALL), SetFill(1, 0),
|
||||||
NWidget(WWT_PUSHTXTBTN, COLOUR_BROWN, WID_GRAPH_DISABLE_CARGOES), SetStringTip(STR_GRAPH_CARGO_DISABLE_ALL, STR_GRAPH_CARGO_TOOLTIP_DISABLE_ALL), SetFill(1, 0),
|
NWidget(WWT_PUSHTXTBTN, COLOUR_BROWN, WID_GRAPH_DISABLE_CARGOES), SetStringTip(STR_GRAPH_CARGO_DISABLE_ALL, STR_GRAPH_CARGO_TOOLTIP_DISABLE_ALL), SetFill(1, 0),
|
||||||
|
@ -1717,6 +1833,8 @@ static constexpr NWidgetPart _nested_industry_production_widgets[] = {
|
||||||
NWidget(WWT_MATRIX, COLOUR_BROWN, WID_GRAPH_MATRIX), SetFill(1, 0), SetResize(0, 2), SetMatrixDataTip(1, 0, STR_GRAPH_CARGO_PAYMENT_TOGGLE_CARGO), SetScrollbar(WID_GRAPH_MATRIX_SCROLLBAR),
|
NWidget(WWT_MATRIX, COLOUR_BROWN, WID_GRAPH_MATRIX), SetFill(1, 0), SetResize(0, 2), SetMatrixDataTip(1, 0, STR_GRAPH_CARGO_PAYMENT_TOGGLE_CARGO), SetScrollbar(WID_GRAPH_MATRIX_SCROLLBAR),
|
||||||
NWidget(NWID_VSCROLLBAR, COLOUR_BROWN, WID_GRAPH_MATRIX_SCROLLBAR),
|
NWidget(NWID_VSCROLLBAR, COLOUR_BROWN, WID_GRAPH_MATRIX_SCROLLBAR),
|
||||||
EndContainer(),
|
EndContainer(),
|
||||||
|
NWidget(NWID_SPACER), SetMinimalSize(0, 4),
|
||||||
|
NWidget(WWT_MATRIX, COLOUR_BROWN, WID_GRAPH_SCALE_MATRIX), SetFill(1, 0), SetResize(0, 0), SetMatrixDataTip(1, 0, STR_GRAPH_SELECT_SCALE),
|
||||||
NWidget(NWID_SPACER), SetMinimalSize(0, 24), SetFill(0, 1),
|
NWidget(NWID_SPACER), SetMinimalSize(0, 24), SetFill(0, 1),
|
||||||
EndContainer(),
|
EndContainer(),
|
||||||
NWidget(NWID_SPACER), SetMinimalSize(5, 0), SetFill(0, 1), SetResize(0, 1),
|
NWidget(NWID_SPACER), SetMinimalSize(5, 0), SetFill(0, 1), SetResize(0, 1),
|
||||||
|
|
|
@ -77,10 +77,27 @@ struct Industry : IndustryPool::PoolItem<&_industry_pool> {
|
||||||
HistoryData<ProducedHistory> history{}; ///< History of cargo produced and transported for this month and 24 previous months
|
HistoryData<ProducedHistory> history{}; ///< History of cargo produced and transported for this month and 24 previous months
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct AcceptedHistory {
|
||||||
|
uint16_t accepted = 0; /// Total accepted.
|
||||||
|
uint16_t waiting = 0; /// Average waiting.
|
||||||
|
};
|
||||||
|
|
||||||
struct AcceptedCargo {
|
struct AcceptedCargo {
|
||||||
CargoType cargo = 0; ///< Cargo type
|
CargoType cargo = 0; ///< Cargo type
|
||||||
uint16_t waiting = 0; ///< Amount of cargo waiting to processed
|
uint16_t waiting = 0; ///< Amount of cargo waiting to processed
|
||||||
|
uint32_t accumulated_waiting = 0; ///< Accumulated waiting total over the last month, used to calculate average.
|
||||||
TimerGameEconomy::Date last_accepted{}; ///< Last day cargo was accepted by this industry
|
TimerGameEconomy::Date last_accepted{}; ///< Last day cargo was accepted by this industry
|
||||||
|
std::unique_ptr<HistoryData<AcceptedHistory>> history{}; ///< History of accepted and waiting cargo.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get history data, creating it if necessary.
|
||||||
|
* @return Accepted history data.
|
||||||
|
*/
|
||||||
|
inline HistoryData<AcceptedHistory> &GetOrCreateHistory()
|
||||||
|
{
|
||||||
|
if (this->history == nullptr) this->history = std::make_unique<HistoryData<AcceptedHistory>>();
|
||||||
|
return *this->history;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
using ProducedCargoes = std::vector<ProducedCargo>;
|
using ProducedCargoes = std::vector<ProducedCargo>;
|
||||||
|
@ -151,7 +168,7 @@ struct Industry : IndustryPool::PoolItem<&_industry_pool> {
|
||||||
*/
|
*/
|
||||||
inline const AcceptedCargo &GetAccepted(size_t slot) const
|
inline const AcceptedCargo &GetAccepted(size_t slot) const
|
||||||
{
|
{
|
||||||
static const AcceptedCargo empty{INVALID_CARGO, 0, {}};
|
static const AcceptedCargo empty{INVALID_CARGO, 0, 0, {}, {}};
|
||||||
return slot < this->accepted.size() ? this->accepted[slot] : empty;
|
return slot < this->accepted.size() ? this->accepted[slot] : empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1245,6 +1245,10 @@ void OnTick_Industry()
|
||||||
|
|
||||||
for (Industry *i : Industry::Iterate()) {
|
for (Industry *i : Industry::Iterate()) {
|
||||||
ProduceIndustryGoods(i);
|
ProduceIndustryGoods(i);
|
||||||
|
|
||||||
|
if ((TimerGameTick::counter + i->index) % Ticks::DAY_TICKS == 0) {
|
||||||
|
for (auto &a : i->accepted) a.accumulated_waiting += a.waiting;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1838,7 +1842,7 @@ static void DoCreateNewIndustry(Industry *i, TileIndex tile, IndustryType type,
|
||||||
p.history[LAST_MONTH].production += ScaleByCargoScale(p.rate * 8, false);
|
p.history[LAST_MONTH].production += ScaleByCargoScale(p.rate * 8, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateValidHistory(i->valid_history);
|
UpdateValidHistory(i->valid_history, TimerGameEconomy::month);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (indspec->callback_mask.Test(IndustryCallbackMask::DecideColour)) {
|
if (indspec->callback_mask.Test(IndustryCallbackMask::DecideColour)) {
|
||||||
|
@ -2490,21 +2494,48 @@ void GenerateIndustries()
|
||||||
_industry_builder.Reset();
|
_industry_builder.Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
Industry::ProducedHistory SumHistory(std::span<const Industry::ProducedHistory> history)
|
||||||
|
{
|
||||||
|
uint32_t production = std::accumulate(std::begin(history), std::end(history), 0, [](uint32_t r, const auto &p) { return r + p.production; });
|
||||||
|
uint32_t transported = std::accumulate(std::begin(history), std::end(history), 0, [](uint32_t r, const auto &p) { return r + p.transported; });
|
||||||
|
auto count = std::size(history);
|
||||||
|
return {.production = ClampTo<uint16_t>(production / count), .transported = ClampTo<uint16_t>(transported / count)};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
Industry::AcceptedHistory SumHistory(std::span<const Industry::AcceptedHistory> history)
|
||||||
|
{
|
||||||
|
uint32_t accepted = std::accumulate(std::begin(history), std::end(history), 0, [](uint32_t r, const auto &a) { return r + a.accepted; });
|
||||||
|
uint32_t waiting = std::accumulate(std::begin(history), std::end(history), 0, [](uint32_t r, const auto &a) { return r + a.waiting; });;
|
||||||
|
auto count = std::size(history);
|
||||||
|
return {.accepted = ClampTo<uint16_t>(accepted / count), .waiting = ClampTo<uint16_t>(waiting / count)};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Monthly update of industry statistics.
|
* Monthly update of industry statistics.
|
||||||
* @param i Industry to update.
|
* @param i Industry to update.
|
||||||
*/
|
*/
|
||||||
static void UpdateIndustryStatistics(Industry *i)
|
static void UpdateIndustryStatistics(Industry *i)
|
||||||
{
|
{
|
||||||
UpdateValidHistory(i->valid_history);
|
auto month = TimerGameEconomy::month;
|
||||||
|
UpdateValidHistory(i->valid_history, month);
|
||||||
|
|
||||||
for (auto &p : i->produced) {
|
for (auto &p : i->produced) {
|
||||||
if (IsValidCargoType(p.cargo)) {
|
if (IsValidCargoType(p.cargo)) {
|
||||||
if (p.history[THIS_MONTH].production != 0) i->last_prod_year = TimerGameEconomy::year;
|
if (p.history[THIS_MONTH].production != 0) i->last_prod_year = TimerGameEconomy::year;
|
||||||
|
|
||||||
RotateHistory(p.history);
|
RotateHistory(p.history, i->valid_history, month);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (auto &a : i->accepted) {
|
||||||
|
if (!IsValidCargoType(a.cargo)) continue;
|
||||||
|
if (a.history == nullptr) continue;
|
||||||
|
|
||||||
|
(*a.history)[THIS_MONTH].waiting = GetAndResetAccumulatedAverage<uint16_t>(a.accumulated_waiting);
|
||||||
|
RotateHistory(*a.history, i->valid_history, month);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -845,7 +845,7 @@ public:
|
||||||
nvp->InitializeViewport(this, Industry::Get(window_number)->location.GetCenterTile(), ScaleZoomGUI(ZoomLevel::Industry));
|
nvp->InitializeViewport(this, Industry::Get(window_number)->location.GetCenterTile(), ScaleZoomGUI(ZoomLevel::Industry));
|
||||||
|
|
||||||
const Industry *i = Industry::Get(window_number);
|
const Industry *i = Industry::Get(window_number);
|
||||||
if (!i->IsCargoProduced()) this->DisableWidget(WID_IV_GRAPH);
|
if (!i->IsCargoProduced() && !i->IsCargoAccepted()) this->DisableWidget(WID_IV_GRAPH);
|
||||||
|
|
||||||
this->InvalidateData();
|
this->InvalidateData();
|
||||||
}
|
}
|
||||||
|
@ -1242,7 +1242,7 @@ static constexpr NWidgetPart _nested_industry_view_widgets[] = {
|
||||||
EndContainer(),
|
EndContainer(),
|
||||||
NWidget(NWID_HORIZONTAL),
|
NWidget(NWID_HORIZONTAL),
|
||||||
NWidget(WWT_PUSHTXTBTN, COLOUR_CREAM, WID_IV_DISPLAY), SetFill(1, 0), SetResize(1, 0), SetStringTip(STR_INDUSTRY_DISPLAY_CHAIN, STR_INDUSTRY_DISPLAY_CHAIN_TOOLTIP),
|
NWidget(WWT_PUSHTXTBTN, COLOUR_CREAM, WID_IV_DISPLAY), SetFill(1, 0), SetResize(1, 0), SetStringTip(STR_INDUSTRY_DISPLAY_CHAIN, STR_INDUSTRY_DISPLAY_CHAIN_TOOLTIP),
|
||||||
NWidget(WWT_PUSHTXTBTN, COLOUR_CREAM, WID_IV_GRAPH), SetFill(1, 0), SetResize(1, 0), SetStringTip(STR_INDUSTRY_VIEW_PRODUCTION_GRAPH, STR_INDUSTRY_VIEW_PRODUCTION_GRAPH_TOOLTIP),
|
NWidget(WWT_PUSHTXTBTN, COLOUR_CREAM, WID_IV_GRAPH), SetFill(1, 0), SetResize(1, 0), SetStringTip(STR_INDUSTRY_VIEW_CARGO_GRAPH, STR_INDUSTRY_VIEW_CARGO_GRAPH_TOOLTIP),
|
||||||
NWidget(WWT_RESIZEBOX, COLOUR_CREAM),
|
NWidget(WWT_RESIZEBOX, COLOUR_CREAM),
|
||||||
EndContainer(),
|
EndContainer(),
|
||||||
};
|
};
|
||||||
|
|
|
@ -5002,6 +5002,7 @@ STR_ERROR_FLAT_LAND_REQUIRED :{WHITE}O terren
|
||||||
STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION :{WHITE}Terreno inclinado na direção errada
|
STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION :{WHITE}Terreno inclinado na direção errada
|
||||||
STR_ERROR_CAN_T_DO_THIS :{WHITE}Não é possível fazer isto...
|
STR_ERROR_CAN_T_DO_THIS :{WHITE}Não é possível fazer isto...
|
||||||
STR_ERROR_BUILDING_MUST_BE_DEMOLISHED :{WHITE}A construção precisa ser demolida primeiro
|
STR_ERROR_BUILDING_MUST_BE_DEMOLISHED :{WHITE}A construção precisa ser demolida primeiro
|
||||||
|
STR_ERROR_BUILDING_IS_PROTECTED :{WHITE}... construção é protegida
|
||||||
STR_ERROR_CAN_T_CLEAR_THIS_AREA :{WHITE}Não é possível limpar esta área...
|
STR_ERROR_CAN_T_CLEAR_THIS_AREA :{WHITE}Não é possível limpar esta área...
|
||||||
STR_ERROR_SITE_UNSUITABLE :{WHITE}... local não adequado
|
STR_ERROR_SITE_UNSUITABLE :{WHITE}... local não adequado
|
||||||
STR_ERROR_ALREADY_BUILT :{WHITE}... já construído
|
STR_ERROR_ALREADY_BUILT :{WHITE}... já construído
|
||||||
|
|
|
@ -268,6 +268,7 @@ STR_UNITS_YEARS :{NUM}{NBSP}any{
|
||||||
STR_UNITS_PERIODS :{NUM}{NBSP}període{P "" s}
|
STR_UNITS_PERIODS :{NUM}{NBSP}període{P "" s}
|
||||||
|
|
||||||
STR_LIST_SEPARATOR :,{SPACE}
|
STR_LIST_SEPARATOR :,{SPACE}
|
||||||
|
STR_TRUNCATION_ELLIPSIS :...
|
||||||
|
|
||||||
# Common window strings
|
# Common window strings
|
||||||
STR_LIST_FILTER_TITLE :{BLACK}Filtre:
|
STR_LIST_FILTER_TITLE :{BLACK}Filtre:
|
||||||
|
@ -286,7 +287,7 @@ STR_TOOLTIP_CLOSE_WINDOW :{BLACK}Tanca la
|
||||||
STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS :{BLACK}Títol de la finestra: arrossegueu el títol per desplaçar la finestra.
|
STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS :{BLACK}Títol de la finestra: arrossegueu el títol per desplaçar la finestra.
|
||||||
STR_TOOLTIP_SHADE :{BLACK}Ombra de la finestra: mostra només la barra de títol.
|
STR_TOOLTIP_SHADE :{BLACK}Ombra de la finestra: mostra només la barra de títol.
|
||||||
STR_TOOLTIP_DEBUG :{BLACK}Mostra la informació de depuració NewGRF
|
STR_TOOLTIP_DEBUG :{BLACK}Mostra la informació de depuració NewGRF
|
||||||
STR_TOOLTIP_DEFSIZE :{BLACK}Redimensiona la finestra a la mida predeterminada. Ctrl+Clic desa la mida actual com a predeterminada.
|
STR_TOOLTIP_DEFSIZE :{BLACK}Redimensiona la finestra a la mida predeterminada. Amb Ctrl+Clic, es desa la mida actual com a predeterminada. Amb Ctrl+doble clic, es restableix als valors per defecte.
|
||||||
STR_TOOLTIP_STICKY :{BLACK}Marca aquesta finestra com a no eliminable per la tecla «Tanca totes les finestres». Ctrl+Clic per desar també l'estat predeterminat.
|
STR_TOOLTIP_STICKY :{BLACK}Marca aquesta finestra com a no eliminable per la tecla «Tanca totes les finestres». Ctrl+Clic per desar també l'estat predeterminat.
|
||||||
STR_TOOLTIP_RESIZE :{BLACK}Clica i arrossega per redimensionar aquesta finestra
|
STR_TOOLTIP_RESIZE :{BLACK}Clica i arrossega per redimensionar aquesta finestra
|
||||||
STR_TOOLTIP_TOGGLE_LARGE_SMALL_WINDOW :{BLACK}Commuta entre la mida gran i petita de la finestra
|
STR_TOOLTIP_TOGGLE_LARGE_SMALL_WINDOW :{BLACK}Commuta entre la mida gran i petita de la finestra
|
||||||
|
@ -1108,7 +1109,7 @@ STR_GAME_OPTIONS_BASE_MUSIC_DESCRIPTION_TOOLTIP :Informació add
|
||||||
STR_GAME_OPTIONS_ONLINE_CONTENT :Descarrega contingut
|
STR_GAME_OPTIONS_ONLINE_CONTENT :Descarrega contingut
|
||||||
STR_GAME_OPTIONS_ONLINE_CONTENT_TOOLTIP :Comprova si hi ha continguts nous o actualitzats per a descarregar.
|
STR_GAME_OPTIONS_ONLINE_CONTENT_TOOLTIP :Comprova si hi ha continguts nous o actualitzats per a descarregar.
|
||||||
|
|
||||||
STR_GAME_OPTIONS_SOCIAL_PLUGINS_NONE :{LTBLUE}(no s'han instal·lat complements per a interactuar amb plataformes socials)
|
STR_GAME_OPTIONS_SOCIAL_PLUGINS_NONE :(no s'han instal·lat complements per a interactuar amb plataformes socials)
|
||||||
|
|
||||||
STR_GAME_OPTIONS_SOCIAL_PLUGIN_TITLE :{STRING} ({STRING})
|
STR_GAME_OPTIONS_SOCIAL_PLUGIN_TITLE :{STRING} ({STRING})
|
||||||
STR_GAME_OPTIONS_SOCIAL_PLUGIN_PLATFORM :Plataforma:
|
STR_GAME_OPTIONS_SOCIAL_PLUGIN_PLATFORM :Plataforma:
|
||||||
|
@ -1226,7 +1227,7 @@ STR_CITY_APPROVAL_PERMISSIVE :Permissiva (les
|
||||||
STR_WARNING_NO_SUITABLE_AI :{WHITE}No hi ha cap IA disponible...{}Podeu descarregar-ne a través del «Contingut en línia».
|
STR_WARNING_NO_SUITABLE_AI :{WHITE}No hi ha cap IA disponible...{}Podeu descarregar-ne a través del «Contingut en línia».
|
||||||
|
|
||||||
# Settings tree in the Game Options window
|
# Settings tree in the Game Options window
|
||||||
STR_CONFIG_SETTING_FILTER_TITLE :{G=Masculin}{BLACK}Filtre:
|
STR_CONFIG_SETTING_FILTER_TITLE :{G=Masculin}Filtre:
|
||||||
STR_CONFIG_SETTING_EXPAND_ALL :Desplega-ho tot
|
STR_CONFIG_SETTING_EXPAND_ALL :Desplega-ho tot
|
||||||
STR_CONFIG_SETTING_COLLAPSE_ALL :Plega-ho tot
|
STR_CONFIG_SETTING_COLLAPSE_ALL :Plega-ho tot
|
||||||
STR_CONFIG_SETTING_RESET_ALL :Restableix tots els valors
|
STR_CONFIG_SETTING_RESET_ALL :Restableix tots els valors
|
||||||
|
@ -1302,6 +1303,9 @@ STR_CONFIG_SETTING_INTEREST_RATE_HELPTEXT :Tipus d'interè
|
||||||
STR_CONFIG_SETTING_RUNNING_COSTS :Costos d'utilització: {STRING}
|
STR_CONFIG_SETTING_RUNNING_COSTS :Costos d'utilització: {STRING}
|
||||||
STR_CONFIG_SETTING_RUNNING_COSTS_HELPTEXT :Fixa el nivell de manteniment i els costos d'utilització dels vehicles i infraestructures
|
STR_CONFIG_SETTING_RUNNING_COSTS_HELPTEXT :Fixa el nivell de manteniment i els costos d'utilització dels vehicles i infraestructures
|
||||||
###length 3
|
###length 3
|
||||||
|
STR_CONFIG_SETTING_RUNNING_COSTS_LOW :Baix
|
||||||
|
STR_CONFIG_SETTING_RUNNING_COSTS_MEDIUM :Mitjà
|
||||||
|
STR_CONFIG_SETTING_RUNNING_COSTS_HIGH :Alt
|
||||||
|
|
||||||
STR_CONFIG_SETTING_CONSTRUCTION_SPEED :Ritme de construcció: {STRING}
|
STR_CONFIG_SETTING_CONSTRUCTION_SPEED :Ritme de construcció: {STRING}
|
||||||
STR_CONFIG_SETTING_CONSTRUCTION_SPEED_HELPTEXT :Limita la quantitat d'accions de construcció per part de les IA
|
STR_CONFIG_SETTING_CONSTRUCTION_SPEED_HELPTEXT :Limita la quantitat d'accions de construcció per part de les IA
|
||||||
|
@ -1324,6 +1328,9 @@ STR_CONFIG_SETTING_SUBSIDY_DURATION_DISABLED :Sense subsidis
|
||||||
STR_CONFIG_SETTING_CONSTRUCTION_COSTS :Costos de construcció: {STRING}
|
STR_CONFIG_SETTING_CONSTRUCTION_COSTS :Costos de construcció: {STRING}
|
||||||
STR_CONFIG_SETTING_CONSTRUCTION_COSTS_HELPTEXT :Fixa el nivell de construcció i els preus de compra
|
STR_CONFIG_SETTING_CONSTRUCTION_COSTS_HELPTEXT :Fixa el nivell de construcció i els preus de compra
|
||||||
###length 3
|
###length 3
|
||||||
|
STR_CONFIG_SETTING_CONSTRUCTION_COSTS_LOW :Baix
|
||||||
|
STR_CONFIG_SETTING_CONSTRUCTION_COSTS_MEDIUM :Mitjà
|
||||||
|
STR_CONFIG_SETTING_CONSTRUCTION_COSTS_HIGH :Alt
|
||||||
|
|
||||||
STR_CONFIG_SETTING_RECESSIONS :Recessions: {STRING}
|
STR_CONFIG_SETTING_RECESSIONS :Recessions: {STRING}
|
||||||
STR_CONFIG_SETTING_RECESSIONS_HELPTEXT :Si està activat, poden haver recessions periòdicament. Durant una recessió, tota la producció és significativament més baixa, tornant al nivell previ quan s'acabi el període de recessió.
|
STR_CONFIG_SETTING_RECESSIONS_HELPTEXT :Si està activat, poden haver recessions periòdicament. Durant una recessió, tota la producció és significativament més baixa, tornant al nivell previ quan s'acabi el període de recessió.
|
||||||
|
@ -2079,9 +2086,9 @@ STR_CONFIG_SETTING_DISTRIBUTION_ARMOURED_HELPTEXT :La classe de c
|
||||||
STR_CONFIG_SETTING_DISTRIBUTION_DEFAULT :Mode de distribució per altres classes de càrrega: {STRING}
|
STR_CONFIG_SETTING_DISTRIBUTION_DEFAULT :Mode de distribució per altres classes de càrrega: {STRING}
|
||||||
STR_CONFIG_SETTING_DISTRIBUTION_DEFAULT_HELPTEXT :"Asimètric" vol dir que quantitats arbitràries de càrrega poden ser enviades en qualsevol sentit. "Manual" significa que no s'aplicarà cap distribució automàtica a aquestes càrregues.
|
STR_CONFIG_SETTING_DISTRIBUTION_DEFAULT_HELPTEXT :"Asimètric" vol dir que quantitats arbitràries de càrrega poden ser enviades en qualsevol sentit. "Manual" significa que no s'aplicarà cap distribució automàtica a aquestes càrregues.
|
||||||
###length 3
|
###length 3
|
||||||
STR_CONFIG_SETTING_DISTRIBUTION_MANUAL :manual
|
STR_CONFIG_SETTING_DISTRIBUTION_MANUAL :Manual
|
||||||
STR_CONFIG_SETTING_DISTRIBUTION_ASYMMETRIC :asimètric
|
STR_CONFIG_SETTING_DISTRIBUTION_ASYMMETRIC :Asimètric
|
||||||
STR_CONFIG_SETTING_DISTRIBUTION_SYMMETRIC :simètric
|
STR_CONFIG_SETTING_DISTRIBUTION_SYMMETRIC :Simètric
|
||||||
|
|
||||||
STR_CONFIG_SETTING_LINKGRAPH_ACCURACY :Precisió de la distribució: {STRING}
|
STR_CONFIG_SETTING_LINKGRAPH_ACCURACY :Precisió de la distribució: {STRING}
|
||||||
STR_CONFIG_SETTING_LINKGRAPH_ACCURACY_HELPTEXT :Com més alt el valor indicat, més temps de processador requerirà el càlcul del graf de distribució. Si requereix massa temps podeu notar ralentització. Si indiqueu un valor baix, però, la distribució serà poc acurada, i us podeu trobar que la càrrega no és enviada als llocs que espereu.
|
STR_CONFIG_SETTING_LINKGRAPH_ACCURACY_HELPTEXT :Com més alt el valor indicat, més temps de processador requerirà el càlcul del graf de distribució. Si requereix massa temps podeu notar ralentització. Si indiqueu un valor baix, però, la distribució serà poc acurada, i us podeu trobar que la càrrega no és enviada als llocs que espereu.
|
||||||
|
@ -2331,16 +2338,19 @@ STR_FACE_SIMPLE_TOOLTIP :{BLACK}Selecci
|
||||||
STR_FACE_LOAD :{BLACK}Carrega
|
STR_FACE_LOAD :{BLACK}Carrega
|
||||||
STR_FACE_LOAD_TOOLTIP :{BLACK}Carrega la cara preferida
|
STR_FACE_LOAD_TOOLTIP :{BLACK}Carrega la cara preferida
|
||||||
STR_FACE_LOAD_DONE :{WHITE}S'ha carregat la cara personalitzada des de l'arxiu de configuració de l'OpenTTD.
|
STR_FACE_LOAD_DONE :{WHITE}S'ha carregat la cara personalitzada des de l'arxiu de configuració de l'OpenTTD.
|
||||||
STR_FACE_FACECODE :{BLACK}Número de la cara
|
STR_FACE_FACECODE :{BLACK}Codi de la cara
|
||||||
STR_FACE_FACECODE_TOOLTIP :{BLACK}Veure i/o assigna el número de la cara del president
|
STR_FACE_FACECODE_TOOLTIP :{BLACK}Veure i/o assigna el codi de la cara del president
|
||||||
STR_FACE_FACECODE_CAPTION :{WHITE}Veure i/o assigna el número de la cara del president
|
STR_FACE_FACECODE_CAPTION :{WHITE}Veure i/o assigna el codi de la cara del president
|
||||||
STR_FACE_FACECODE_SET :{WHITE}El número de la nova cara ha estat assignat
|
STR_FACE_FACECODE_SET :{WHITE}S'ha assignat el codi de la nova cara del president.
|
||||||
STR_FACE_FACECODE_ERR :{WHITE}No s'ha pogut assignar el número de cara del president - ha de ser un nombre entre 0 i 4,294,967,295!
|
STR_FACE_FACECODE_ERR :{WHITE}No s'ha pogut assignar el codi de cara del president - ha de ser una etiqueta i nombre vàlids.
|
||||||
STR_FACE_SAVE :{BLACK}Desa
|
STR_FACE_SAVE :{BLACK}Desa
|
||||||
STR_FACE_SAVE_TOOLTIP :{BLACK}Desa la cara preferida
|
STR_FACE_SAVE_TOOLTIP :{BLACK}Desa la cara preferida
|
||||||
STR_FACE_SAVE_DONE :{WHITE}Es desarà aquesta cara personalitzada a l'arxiu de configuració de l'OpenTTD.
|
STR_FACE_SAVE_DONE :{WHITE}Es desarà aquesta cara personalitzada a l'arxiu de configuració de l'OpenTTD.
|
||||||
|
STR_FACE_SETTING_TOGGLE :{STRING} {ORANGE}{STRING}
|
||||||
|
STR_FACE_SETTING_NUMERIC :{STRING} {ORANGE}{NUM} / {NUM}
|
||||||
STR_FACE_YES :Sí
|
STR_FACE_YES :Sí
|
||||||
STR_FACE_NO :No
|
STR_FACE_NO :No
|
||||||
|
STR_FACE_STYLE :Estil:
|
||||||
STR_FACE_HAIR :Cabell:
|
STR_FACE_HAIR :Cabell:
|
||||||
STR_FACE_EYEBROWS :Celles:
|
STR_FACE_EYEBROWS :Celles:
|
||||||
STR_FACE_EYECOLOUR :Color dels ulls:
|
STR_FACE_EYECOLOUR :Color dels ulls:
|
||||||
|
@ -2813,6 +2823,10 @@ STR_PICKER_MODE_USED_TOOLTIP :Commuta entre m
|
||||||
STR_PICKER_MODE_SAVED :Desats
|
STR_PICKER_MODE_SAVED :Desats
|
||||||
STR_PICKER_MODE_SAVED_TOOLTIP :Commuta entre mostrar tots o bé només els elements desats.
|
STR_PICKER_MODE_SAVED_TOOLTIP :Commuta entre mostrar tots o bé només els elements desats.
|
||||||
|
|
||||||
|
STR_PICKER_PREVIEW_SHRINK :‒
|
||||||
|
STR_PICKER_PREVIEW_SHRINK_TOOLTIP :Redueix l'alçària de les vistes prèvies. Amb Ctrl+clic, es redueix fins al mínim.
|
||||||
|
STR_PICKER_PREVIEW_EXPAND :+
|
||||||
|
STR_PICKER_PREVIEW_EXPAND_TOOLTIP :Augmenta l'alçària de les vistes prèvies. Amb Ctrl+clic, s'augmenta fins al màxim.
|
||||||
|
|
||||||
STR_PICKER_STATION_CLASS_TOOLTIP :Trieu quina classe d'estació voleu veure.
|
STR_PICKER_STATION_CLASS_TOOLTIP :Trieu quina classe d'estació voleu veure.
|
||||||
STR_PICKER_STATION_TYPE_TOOLTIP :Trieu quin tipus d'estació voleu construir. Amb Ctrl+clic, s'afegeix o es trau l'element de la llista de desats.
|
STR_PICKER_STATION_TYPE_TOOLTIP :Trieu quin tipus d'estació voleu construir. Amb Ctrl+clic, s'afegeix o es trau l'element de la llista de desats.
|
||||||
|
@ -3053,6 +3067,11 @@ STR_FOUND_TOWN_INITIAL_SIZE_TOOLTIP :{BLACK}Seleccio
|
||||||
STR_FOUND_TOWN_CITY :{BLACK}Ciutat
|
STR_FOUND_TOWN_CITY :{BLACK}Ciutat
|
||||||
STR_FOUND_TOWN_CITY_TOOLTIP :{BLACK}Les ciutats creixen més ràpid que els pobles{}Depenent de la configuració, són més grans quan es funden
|
STR_FOUND_TOWN_CITY_TOOLTIP :{BLACK}Les ciutats creixen més ràpid que els pobles{}Depenent de la configuració, són més grans quan es funden
|
||||||
|
|
||||||
|
STR_FOUND_TOWN_EXPAND_MODE :{YELLOW}Expansió de la població:
|
||||||
|
STR_FOUND_TOWN_EXPAND_BUILDINGS :Edificis
|
||||||
|
STR_FOUND_TOWN_EXPAND_BUILDINGS_TOOLTIP :Augmenta el nombre d'edificis de les poblacions.
|
||||||
|
STR_FOUND_TOWN_EXPAND_ROADS :Carreteres
|
||||||
|
STR_FOUND_TOWN_EXPAND_ROADS_TOOLTIP :Augmenta el nombre de carreteres de la població.
|
||||||
|
|
||||||
STR_FOUND_TOWN_ROAD_LAYOUT :{YELLOW}Disposició de les carreteres de la població:
|
STR_FOUND_TOWN_ROAD_LAYOUT :{YELLOW}Disposició de les carreteres de la població:
|
||||||
STR_FOUND_TOWN_SELECT_LAYOUT_TOOLTIP :{BLACK}Selecciona la disposició de les carreteres utilitzades per a aquesta població
|
STR_FOUND_TOWN_SELECT_LAYOUT_TOOLTIP :{BLACK}Selecciona la disposició de les carreteres utilitzades per a aquesta població
|
||||||
|
@ -3677,6 +3696,10 @@ STR_TOWN_VIEW_RENAME_TOOLTIP :{BLACK}Canvia e
|
||||||
|
|
||||||
STR_TOWN_VIEW_EXPAND_BUTTON :{BLACK}Eixampla
|
STR_TOWN_VIEW_EXPAND_BUTTON :{BLACK}Eixampla
|
||||||
STR_TOWN_VIEW_EXPAND_TOOLTIP :{BLACK}Incrementa la mida de la població
|
STR_TOWN_VIEW_EXPAND_TOOLTIP :{BLACK}Incrementa la mida de la població
|
||||||
|
STR_TOWN_VIEW_EXPAND_BUILDINGS_BUTTON :{BLACK}Expandeix els edificis
|
||||||
|
STR_TOWN_VIEW_EXPAND_BUILDINGS_TOOLTIP :{BLACK}Augmenta el nombre d'edificis de la població.
|
||||||
|
STR_TOWN_VIEW_EXPAND_ROADS_BUTTON :{BLACK}Expandeix les carreteres
|
||||||
|
STR_TOWN_VIEW_EXPAND_ROADS_TOOLTIP :{BLACK}Augmenta el nombre de carreteres de la població.
|
||||||
STR_TOWN_VIEW_DELETE_BUTTON :{BLACK}Esborra
|
STR_TOWN_VIEW_DELETE_BUTTON :{BLACK}Esborra
|
||||||
STR_TOWN_VIEW_DELETE_TOOLTIP :{BLACK}Esborra totalment aquesta població
|
STR_TOWN_VIEW_DELETE_TOOLTIP :{BLACK}Esborra totalment aquesta població
|
||||||
|
|
||||||
|
@ -4415,10 +4438,10 @@ STR_VEHICLE_VIEW_SHIP_ORDERS_TOOLTIP :{BLACK}Mostra l
|
||||||
STR_VEHICLE_VIEW_AIRCRAFT_ORDERS_TOOLTIP :{BLACK}Mostra les ordres de l'avió. Ctrl+Clic per mostrar l'horari de l'avió
|
STR_VEHICLE_VIEW_AIRCRAFT_ORDERS_TOOLTIP :{BLACK}Mostra les ordres de l'avió. Ctrl+Clic per mostrar l'horari de l'avió
|
||||||
|
|
||||||
###length VEHICLE_TYPES
|
###length VEHICLE_TYPES
|
||||||
STR_VEHICLE_VIEW_TRAIN_SHOW_DETAILS_TOOLTIP :{BLACK}Mostra els detalls del tren
|
STR_VEHICLE_VIEW_TRAIN_SHOW_DETAILS_TOOLTIP :{BLACK}Mostra els detalls del tren. Amb Ctrl+clic, es mostra el grup del tren.
|
||||||
STR_VEHICLE_VIEW_ROAD_VEHICLE_SHOW_DETAILS_TOOLTIP :{BLACK}Mostra els detalls del vehicle
|
STR_VEHICLE_VIEW_ROAD_VEHICLE_SHOW_DETAILS_TOOLTIP :{BLACK}Mostra els detalls del vehicle. Amb Ctrl+clic, es mostra el grup del vehicle.
|
||||||
STR_VEHICLE_VIEW_SHIP_SHOW_DETAILS_TOOLTIP :{BLACK}Mostra els detalls del vaixell
|
STR_VEHICLE_VIEW_SHIP_SHOW_DETAILS_TOOLTIP :{BLACK}Mostra els detalls del vaixell. Amb Ctrl+clic, es mostra el grup del vaixell.
|
||||||
STR_VEHICLE_VIEW_AIRCRAFT_SHOW_DETAILS_TOOLTIP :{BLACK}Mostra els detalls de l'avió
|
STR_VEHICLE_VIEW_AIRCRAFT_SHOW_DETAILS_TOOLTIP :{BLACK}Mostra els detalls de l'aeronau. Amb Ctrl+clic, es mostra el grup de l'aeronau.
|
||||||
|
|
||||||
###length VEHICLE_TYPES
|
###length VEHICLE_TYPES
|
||||||
STR_VEHICLE_VIEW_TRAIN_STATUS_START_STOP_TOOLTIP :{BLACK}Acció actual del tren - Feu clic per parar-lo o engegar-lo.
|
STR_VEHICLE_VIEW_TRAIN_STATUS_START_STOP_TOOLTIP :{BLACK}Acció actual del tren - Feu clic per parar-lo o engegar-lo.
|
||||||
|
@ -4742,14 +4765,15 @@ STR_TIMETABLE_TOOLTIP :{BLACK}Horari -
|
||||||
STR_TIMETABLE_NO_TRAVEL :Sense viatge
|
STR_TIMETABLE_NO_TRAVEL :Sense viatge
|
||||||
STR_TIMETABLE_NOT_TIMETABLEABLE :Viatge (automàtic; programat per la següent ordre manual)
|
STR_TIMETABLE_NOT_TIMETABLEABLE :Viatge (automàtic; programat per la següent ordre manual)
|
||||||
STR_TIMETABLE_TRAVEL_NOT_TIMETABLED :Viatge (fora d'horari)
|
STR_TIMETABLE_TRAVEL_NOT_TIMETABLED :Viatge (fora d'horari)
|
||||||
|
STR_TIMETABLE_TRAVEL_NOT_TIMETABLED_SPEED :Viatja (sense horari) com a molt a {VELOCITY}
|
||||||
STR_TIMETABLE_TRAVEL_FOR :Viatge a {STRING}
|
STR_TIMETABLE_TRAVEL_FOR :Viatge a {STRING}
|
||||||
STR_TIMETABLE_TRAVEL_FOR_SPEED :Viatja durant {STRING} com a molt a {VELOCITY}
|
STR_TIMETABLE_TRAVEL_FOR_SPEED :Viatja durant {STRING} com a molt a {VELOCITY}
|
||||||
STR_TIMETABLE_TRAVEL_FOR_ESTIMATED :Viatja (durant {STRING}, sense horari)
|
STR_TIMETABLE_TRAVEL_FOR_ESTIMATED :Viatja (durant {STRING}, sense horari)
|
||||||
STR_TIMETABLE_TRAVEL_FOR_SPEED_ESTIMATED :Viatja (durant {STRING}, sense horari) com a molt a {VELOCITY}
|
STR_TIMETABLE_TRAVEL_FOR_SPEED_ESTIMATED :Viatja (durant {STRING}, sense horari) com a molt a {VELOCITY}
|
||||||
STR_TIMETABLE_STAY_FOR_ESTIMATED :{SPACE}(quedar-s'hi durant {STRING}, sense horari)
|
STR_TIMETABLE_STAY_FOR_ESTIMATED :{SPACE}(quedar-s'hi durant {STRING}, sense horari)
|
||||||
STR_TIMETABLE_AND_TRAVEL_FOR_ESTIMATED :{SPACE}(viatja durant {STRING}, sense horari)
|
STR_TIMETABLE_AND_TRAVEL_FOR_ESTIMATED :{SPACE}(viatja durant {STRING}, sense horari)
|
||||||
STR_TIMETABLE_STAY_FOR :i estigues {STRING}
|
STR_TIMETABLE_STAY_FOR :{SPACE}i estigues {STRING}
|
||||||
STR_TIMETABLE_AND_TRAVEL_FOR :i viatge per {STRING}
|
STR_TIMETABLE_AND_TRAVEL_FOR :{SPACE}i viatja durant {STRING}
|
||||||
|
|
||||||
STR_TIMETABLE_APPROX_TIME :{BLACK}L'horari trigara aproximadament {STRING} a completar-se.
|
STR_TIMETABLE_APPROX_TIME :{BLACK}L'horari trigara aproximadament {STRING} a completar-se.
|
||||||
STR_TIMETABLE_TOTAL_TIME :{BLACK}L'horari tardarà {STRING} a complir-se
|
STR_TIMETABLE_TOTAL_TIME :{BLACK}L'horari tardarà {STRING} a complir-se
|
||||||
|
@ -4978,6 +5002,7 @@ STR_ERROR_FLAT_LAND_REQUIRED :{WHITE}Es neces
|
||||||
STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION :{WHITE}Terreny inclinat en direcció incorrecta
|
STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION :{WHITE}Terreny inclinat en direcció incorrecta
|
||||||
STR_ERROR_CAN_T_DO_THIS :{WHITE}Això no es pot fer...
|
STR_ERROR_CAN_T_DO_THIS :{WHITE}Això no es pot fer...
|
||||||
STR_ERROR_BUILDING_MUST_BE_DEMOLISHED :{WHITE}L'edifici s'ha d'enderrocar primer
|
STR_ERROR_BUILDING_MUST_BE_DEMOLISHED :{WHITE}L'edifici s'ha d'enderrocar primer
|
||||||
|
STR_ERROR_BUILDING_IS_PROTECTED :{WHITE}... l'edifici està protegit
|
||||||
STR_ERROR_CAN_T_CLEAR_THIS_AREA :{WHITE}No es pot netejar aquesta àrea...
|
STR_ERROR_CAN_T_CLEAR_THIS_AREA :{WHITE}No es pot netejar aquesta àrea...
|
||||||
STR_ERROR_SITE_UNSUITABLE :{WHITE}... lloc inadequat
|
STR_ERROR_SITE_UNSUITABLE :{WHITE}... lloc inadequat
|
||||||
STR_ERROR_ALREADY_BUILT :{WHITE}... ja construït
|
STR_ERROR_ALREADY_BUILT :{WHITE}... ja construït
|
||||||
|
@ -5897,3 +5922,11 @@ STR_SHIP :{BLACK}{SHIP}
|
||||||
STR_TOOLBAR_RAILTYPE_VELOCITY :{STRING} ({VELOCITY})
|
STR_TOOLBAR_RAILTYPE_VELOCITY :{STRING} ({VELOCITY})
|
||||||
|
|
||||||
STR_BADGE_NAME_LIST :{STRING}: {GOLD}{STRING}
|
STR_BADGE_NAME_LIST :{STRING}: {GOLD}{STRING}
|
||||||
|
STR_BADGE_CONFIG_MENU_TOOLTIP :Obre la configuració d'insígnies
|
||||||
|
STR_BADGE_CONFIG_RESET :Restableix
|
||||||
|
STR_BADGE_CONFIG_ICONS :{WHITE}Icones d'insígnies
|
||||||
|
STR_BADGE_CONFIG_FILTERS :{WHITE}Filtres d'insígnies
|
||||||
|
STR_BADGE_CONFIG_PREVIEW :Imatge de previsualització
|
||||||
|
STR_BADGE_CONFIG_NAME :Nom
|
||||||
|
STR_BADGE_FILTER_ANY_LABEL :Qualsevol {STRING}
|
||||||
|
STR_BADGE_FILTER_IS_LABEL :{STRING} és {STRING}
|
||||||
|
|
|
@ -622,6 +622,14 @@ STR_GRAPH_COMPANY_VALUES_CAPTION :{WHITE}Company
|
||||||
|
|
||||||
STR_GRAPH_LAST_24_MINUTES_TIME_LABEL :{TINY_FONT}{BLACK}Last 24 minutes
|
STR_GRAPH_LAST_24_MINUTES_TIME_LABEL :{TINY_FONT}{BLACK}Last 24 minutes
|
||||||
STR_GRAPH_LAST_72_MINUTES_TIME_LABEL :{TINY_FONT}{BLACK}Last 72 minutes
|
STR_GRAPH_LAST_72_MINUTES_TIME_LABEL :{TINY_FONT}{BLACK}Last 72 minutes
|
||||||
|
STR_GRAPH_LAST_288_MINUTES_TIME_LABEL :{TINY_FONT}{BLACK}Last 288 minutes
|
||||||
|
|
||||||
|
STR_GRAPH_LAST_24_MONTHS :{TINY_FONT}{BLACK}2 years (monthly)
|
||||||
|
STR_GRAPH_LAST_24_QUARTERS :{TINY_FONT}{BLACK}6 years (quarterly)
|
||||||
|
STR_GRAPH_LAST_24_YEARS :{TINY_FONT}{BLACK}24 years (yearly)
|
||||||
|
|
||||||
|
STR_GRAPH_TOGGLE_RANGE :Toggle graph for this data range
|
||||||
|
STR_GRAPH_SELECT_SCALE :Change horizontal scale of graph
|
||||||
|
|
||||||
STR_GRAPH_CARGO_PAYMENT_RATES_CAPTION :{WHITE}Cargo Payment Rates
|
STR_GRAPH_CARGO_PAYMENT_RATES_CAPTION :{WHITE}Cargo Payment Rates
|
||||||
STR_GRAPH_CARGO_PAYMENT_RATES_DAYS :{TINY_FONT}{BLACK}Days in transit
|
STR_GRAPH_CARGO_PAYMENT_RATES_DAYS :{TINY_FONT}{BLACK}Days in transit
|
||||||
|
@ -634,9 +642,11 @@ STR_GRAPH_CARGO_TOOLTIP_DISABLE_ALL :{BLACK}Display
|
||||||
STR_GRAPH_CARGO_PAYMENT_TOGGLE_CARGO :{BLACK}Toggle graph of this cargo type
|
STR_GRAPH_CARGO_PAYMENT_TOGGLE_CARGO :{BLACK}Toggle graph of this cargo type
|
||||||
STR_GRAPH_CARGO_PAYMENT_CARGO :{TINY_FONT}{BLACK}{STRING}
|
STR_GRAPH_CARGO_PAYMENT_CARGO :{TINY_FONT}{BLACK}{STRING}
|
||||||
|
|
||||||
STR_GRAPH_INDUSTRY_PRODUCTION_CAPTION :{WHITE}{INDUSTRY} - Production History
|
STR_GRAPH_INDUSTRY_CAPTION :{WHITE}{INDUSTRY} - Cargo History
|
||||||
STR_GRAPH_INDUSTRY_RANGE_PRODUCED :Produced
|
STR_GRAPH_INDUSTRY_RANGE_PRODUCED :Produced
|
||||||
STR_GRAPH_INDUSTRY_RANGE_TRANSPORTED :Transported
|
STR_GRAPH_INDUSTRY_RANGE_TRANSPORTED :Transported
|
||||||
|
STR_GRAPH_INDUSTRY_RANGE_DELIVERED :Delivered
|
||||||
|
STR_GRAPH_INDUSTRY_RANGE_WAITING :Waiting
|
||||||
|
|
||||||
STR_GRAPH_PERFORMANCE_DETAIL_TOOLTIP :{BLACK}Show detailed performance ratings
|
STR_GRAPH_PERFORMANCE_DETAIL_TOOLTIP :{BLACK}Show detailed performance ratings
|
||||||
|
|
||||||
|
@ -4024,8 +4034,8 @@ STR_INDUSTRY_VIEW_PRODUCTION_LAST_MONTH_TITLE :{BLACK}Producti
|
||||||
STR_INDUSTRY_VIEW_PRODUCTION_LAST_MINUTE_TITLE :{BLACK}Production last minute:
|
STR_INDUSTRY_VIEW_PRODUCTION_LAST_MINUTE_TITLE :{BLACK}Production last minute:
|
||||||
STR_INDUSTRY_VIEW_TRANSPORTED :{YELLOW}{CARGO_LONG}{RAW_STRING}{BLACK} ({COMMA}% transported)
|
STR_INDUSTRY_VIEW_TRANSPORTED :{YELLOW}{CARGO_LONG}{RAW_STRING}{BLACK} ({COMMA}% transported)
|
||||||
STR_INDUSTRY_VIEW_LOCATION_TOOLTIP :{BLACK}Centre the main view on industry location. Ctrl+Click to open a new viewport on industry location
|
STR_INDUSTRY_VIEW_LOCATION_TOOLTIP :{BLACK}Centre the main view on industry location. Ctrl+Click to open a new viewport on industry location
|
||||||
STR_INDUSTRY_VIEW_PRODUCTION_GRAPH :{BLACK}Production Graph
|
STR_INDUSTRY_VIEW_CARGO_GRAPH :{BLACK}Cargo Graph
|
||||||
STR_INDUSTRY_VIEW_PRODUCTION_GRAPH_TOOLTIP :{BLACK}Shows the graph of industry production history
|
STR_INDUSTRY_VIEW_CARGO_GRAPH_TOOLTIP :{BLACK}Shows the graph of industry cargo history
|
||||||
STR_INDUSTRY_VIEW_PRODUCTION_LEVEL :{BLACK}Production level: {YELLOW}{COMMA}%
|
STR_INDUSTRY_VIEW_PRODUCTION_LEVEL :{BLACK}Production level: {YELLOW}{COMMA}%
|
||||||
STR_INDUSTRY_VIEW_INDUSTRY_ANNOUNCED_CLOSURE :{YELLOW}The industry has announced imminent closure!
|
STR_INDUSTRY_VIEW_INDUSTRY_ANNOUNCED_CLOSURE :{YELLOW}The industry has announced imminent closure!
|
||||||
|
|
||||||
|
@ -5001,6 +5011,7 @@ STR_ERROR_FLAT_LAND_REQUIRED :{WHITE}Flat lan
|
||||||
STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION :{WHITE}Land sloped in wrong direction
|
STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION :{WHITE}Land sloped in wrong direction
|
||||||
STR_ERROR_CAN_T_DO_THIS :{WHITE}Can't do this...
|
STR_ERROR_CAN_T_DO_THIS :{WHITE}Can't do this...
|
||||||
STR_ERROR_BUILDING_MUST_BE_DEMOLISHED :{WHITE}Building must be demolished first
|
STR_ERROR_BUILDING_MUST_BE_DEMOLISHED :{WHITE}Building must be demolished first
|
||||||
|
STR_ERROR_BUILDING_IS_PROTECTED :{WHITE}... building is protected
|
||||||
STR_ERROR_CAN_T_CLEAR_THIS_AREA :{WHITE}Can't clear this area...
|
STR_ERROR_CAN_T_CLEAR_THIS_AREA :{WHITE}Can't clear this area...
|
||||||
STR_ERROR_SITE_UNSUITABLE :{WHITE}... site unsuitable
|
STR_ERROR_SITE_UNSUITABLE :{WHITE}... site unsuitable
|
||||||
STR_ERROR_ALREADY_BUILT :{WHITE}... already built
|
STR_ERROR_ALREADY_BUILT :{WHITE}... already built
|
||||||
|
|
|
@ -5001,6 +5001,7 @@ STR_ERROR_FLAT_LAND_REQUIRED :{WHITE}Flat lan
|
||||||
STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION :{WHITE}Land sloped in wrong direction
|
STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION :{WHITE}Land sloped in wrong direction
|
||||||
STR_ERROR_CAN_T_DO_THIS :{WHITE}Can't do this...
|
STR_ERROR_CAN_T_DO_THIS :{WHITE}Can't do this...
|
||||||
STR_ERROR_BUILDING_MUST_BE_DEMOLISHED :{WHITE}Building must be demolished first
|
STR_ERROR_BUILDING_MUST_BE_DEMOLISHED :{WHITE}Building must be demolished first
|
||||||
|
STR_ERROR_BUILDING_IS_PROTECTED :{WHITE}... building is protected
|
||||||
STR_ERROR_CAN_T_CLEAR_THIS_AREA :{WHITE}Can't clear this area...
|
STR_ERROR_CAN_T_CLEAR_THIS_AREA :{WHITE}Can't clear this area...
|
||||||
STR_ERROR_SITE_UNSUITABLE :{WHITE}... site unsuitable
|
STR_ERROR_SITE_UNSUITABLE :{WHITE}... site unsuitable
|
||||||
STR_ERROR_ALREADY_BUILT :{WHITE}... already built
|
STR_ERROR_ALREADY_BUILT :{WHITE}... already built
|
||||||
|
|
|
@ -5001,6 +5001,7 @@ STR_ERROR_FLAT_LAND_REQUIRED :{WHITE}Tarvitaa
|
||||||
STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION :{WHITE}Maa viettää väärään suuntaan.
|
STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION :{WHITE}Maa viettää väärään suuntaan.
|
||||||
STR_ERROR_CAN_T_DO_THIS :{WHITE}Ei onnistu...
|
STR_ERROR_CAN_T_DO_THIS :{WHITE}Ei onnistu...
|
||||||
STR_ERROR_BUILDING_MUST_BE_DEMOLISHED :{WHITE}Rakennus täytyy purkaa ensin.
|
STR_ERROR_BUILDING_MUST_BE_DEMOLISHED :{WHITE}Rakennus täytyy purkaa ensin.
|
||||||
|
STR_ERROR_BUILDING_IS_PROTECTED :{WHITE}… rakennus on suojattu
|
||||||
STR_ERROR_CAN_T_CLEAR_THIS_AREA :{WHITE}Aluetta ei voi tyhjentää...
|
STR_ERROR_CAN_T_CLEAR_THIS_AREA :{WHITE}Aluetta ei voi tyhjentää...
|
||||||
STR_ERROR_SITE_UNSUITABLE :{WHITE}... maasto on sopimaton
|
STR_ERROR_SITE_UNSUITABLE :{WHITE}... maasto on sopimaton
|
||||||
STR_ERROR_ALREADY_BUILT :{WHITE}... se on jo rakennettu
|
STR_ERROR_ALREADY_BUILT :{WHITE}... se on jo rakennettu
|
||||||
|
|
|
@ -5102,6 +5102,7 @@ STR_ERROR_FLAT_LAND_REQUIRED :{WHITE}Απαι
|
||||||
STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION :{WHITE}Το έδαφος έχει λάθος κλίση
|
STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION :{WHITE}Το έδαφος έχει λάθος κλίση
|
||||||
STR_ERROR_CAN_T_DO_THIS :{WHITE}Αυτό δεν γίνεται...
|
STR_ERROR_CAN_T_DO_THIS :{WHITE}Αυτό δεν γίνεται...
|
||||||
STR_ERROR_BUILDING_MUST_BE_DEMOLISHED :{WHITE}Το κτίριο πρέπει πρώτα να κατεδαφιστεί
|
STR_ERROR_BUILDING_MUST_BE_DEMOLISHED :{WHITE}Το κτίριο πρέπει πρώτα να κατεδαφιστεί
|
||||||
|
STR_ERROR_BUILDING_IS_PROTECTED :{WHITE}... το κτίριο προστατεύεται
|
||||||
STR_ERROR_CAN_T_CLEAR_THIS_AREA :{WHITE}Είναι αδύνατο να καθαριστεί αυτή η περιοχή...
|
STR_ERROR_CAN_T_CLEAR_THIS_AREA :{WHITE}Είναι αδύνατο να καθαριστεί αυτή η περιοχή...
|
||||||
STR_ERROR_SITE_UNSUITABLE :{WHITE}... ακατάλληλη περιοχή
|
STR_ERROR_SITE_UNSUITABLE :{WHITE}... ακατάλληλη περιοχή
|
||||||
STR_ERROR_ALREADY_BUILT :{WHITE}... ήδη κατασκευασμένο
|
STR_ERROR_ALREADY_BUILT :{WHITE}... ήδη κατασκευασμένο
|
||||||
|
|
|
@ -330,6 +330,7 @@ STR_UNITS_YEARS :{NUM}{NBSP}év
|
||||||
STR_UNITS_PERIODS :{NUM}{NBSP}időszak
|
STR_UNITS_PERIODS :{NUM}{NBSP}időszak
|
||||||
|
|
||||||
STR_LIST_SEPARATOR :,{SPACE}
|
STR_LIST_SEPARATOR :,{SPACE}
|
||||||
|
STR_TRUNCATION_ELLIPSIS :...
|
||||||
|
|
||||||
# Common window strings
|
# Common window strings
|
||||||
STR_LIST_FILTER_TITLE :{BLACK}Szűrő kifejezés:
|
STR_LIST_FILTER_TITLE :{BLACK}Szűrő kifejezés:
|
||||||
|
|
|
@ -5387,6 +5387,7 @@ STR_ERROR_FLAT_LAND_REQUIRED :{WHITE}Wymagany
|
||||||
STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION :{WHITE}Teren pochylony w złym kierunku
|
STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION :{WHITE}Teren pochylony w złym kierunku
|
||||||
STR_ERROR_CAN_T_DO_THIS :{WHITE}Nie można tego zrobić...
|
STR_ERROR_CAN_T_DO_THIS :{WHITE}Nie można tego zrobić...
|
||||||
STR_ERROR_BUILDING_MUST_BE_DEMOLISHED :{WHITE}Należy najpierw zburzyć budynek
|
STR_ERROR_BUILDING_MUST_BE_DEMOLISHED :{WHITE}Należy najpierw zburzyć budynek
|
||||||
|
STR_ERROR_BUILDING_IS_PROTECTED :{WHITE}... budynek jest chroniony
|
||||||
STR_ERROR_CAN_T_CLEAR_THIS_AREA :{WHITE}Nie można wyczyścić terenu...
|
STR_ERROR_CAN_T_CLEAR_THIS_AREA :{WHITE}Nie można wyczyścić terenu...
|
||||||
STR_ERROR_SITE_UNSUITABLE :{WHITE}... nieodpowiednie miejsce
|
STR_ERROR_SITE_UNSUITABLE :{WHITE}... nieodpowiednie miejsce
|
||||||
STR_ERROR_ALREADY_BUILT :{WHITE}... już zbudowano
|
STR_ERROR_ALREADY_BUILT :{WHITE}... już zbudowano
|
||||||
|
|
|
@ -647,7 +647,7 @@ STR_GRAPH_KEY_COMPANY_SELECTION_TOOLTIP :{BLACK}Alternar
|
||||||
|
|
||||||
# Company league window
|
# Company league window
|
||||||
STR_COMPANY_LEAGUE_TABLE_CAPTION :{WHITE}Classificação de Empresas
|
STR_COMPANY_LEAGUE_TABLE_CAPTION :{WHITE}Classificação de Empresas
|
||||||
STR_COMPANY_LEAGUE_COMPANY_NAME :{ORANGE}{COMPANY} {BLACK}{COMPANY_NUM} '{STRING}'
|
STR_COMPANY_LEAGUE_COMPANY_NAME :{ORANGE}{COMPANY} {BLACK}{COMPANY_NUM} “{STRING}”
|
||||||
STR_COMPANY_LEAGUE_COMPANY_RANK :{YELLOW}#{NUM}
|
STR_COMPANY_LEAGUE_COMPANY_RANK :{YELLOW}#{NUM}
|
||||||
STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_ENGINEER :Engenheiro
|
STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_ENGINEER :Engenheiro
|
||||||
STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_TRAFFIC_MANAGER :Gestor de Tráfego
|
STR_COMPANY_LEAGUE_PERFORMANCE_TITLE_TRAFFIC_MANAGER :Gestor de Tráfego
|
||||||
|
@ -3441,20 +3441,20 @@ STR_SE_MAPGEN_FLAT_WORLD_HEIGHT_QUERY_CAPT :{WHITE}Mudar al
|
||||||
STR_GENERATION_WORLD :{WHITE}A Gerar Mundo...
|
STR_GENERATION_WORLD :{WHITE}A Gerar Mundo...
|
||||||
STR_GENERATION_ABORT :{BLACK}Cancelar
|
STR_GENERATION_ABORT :{BLACK}Cancelar
|
||||||
STR_GENERATION_ABORT_CAPTION :{WHITE}Cancelar criação do mundo
|
STR_GENERATION_ABORT_CAPTION :{WHITE}Cancelar criação do mundo
|
||||||
STR_GENERATION_ABORT_MESSAGE :{YELLOW}Quer mesmo cancelar a criação?
|
STR_GENERATION_ABORT_MESSAGE :{YELLOW}Quer mesmo cancelar o processo de geração?
|
||||||
STR_GENERATION_PROGRESS :{WHITE}{NUM}% completo
|
STR_GENERATION_PROGRESS :{WHITE}{NUM}% completo
|
||||||
STR_GENERATION_PROGRESS_NUM :{BLACK}{NUM} / {NUM}
|
STR_GENERATION_PROGRESS_NUM :{BLACK}{NUM} / {NUM}
|
||||||
STR_GENERATION_WORLD_GENERATION :{BLACK}A gerar mundo
|
STR_GENERATION_WORLD_GENERATION :{BLACK}A gerar mundo
|
||||||
STR_GENERATION_LANDSCAPE_GENERATION :{BLACK}Geração de paisagem
|
STR_GENERATION_LANDSCAPE_GENERATION :{BLACK}A gerar paisagem
|
||||||
STR_GENERATION_RIVER_GENERATION :{BLACK}A gerar rios
|
STR_GENERATION_RIVER_GENERATION :{BLACK}A gerar rios
|
||||||
STR_GENERATION_CLEARING_TILES :{BLACK}A gerar zonas rochosas e montanhosas
|
STR_GENERATION_CLEARING_TILES :{BLACK}A gerar zonas rochosas e montanhosas
|
||||||
STR_GENERATION_TOWN_GENERATION :{BLACK}Geração de localidades
|
STR_GENERATION_TOWN_GENERATION :{BLACK}A gerar localidades
|
||||||
STR_GENERATION_INDUSTRY_GENERATION :{BLACK}Geração de indústrias
|
STR_GENERATION_INDUSTRY_GENERATION :{BLACK}A gerar indústrias
|
||||||
STR_GENERATION_OBJECT_GENERATION :{BLACK}Geração inamovível
|
STR_GENERATION_OBJECT_GENERATION :{BLACK}A gerar objetos
|
||||||
STR_GENERATION_TREE_GENERATION :{BLACK}A gerar árvores
|
STR_GENERATION_TREE_GENERATION :{BLACK}A gerar árvores
|
||||||
STR_GENERATION_SETTINGUP_GAME :{BLACK}Definindo jogo
|
STR_GENERATION_SETTINGUP_GAME :{BLACK}A configurar jogo
|
||||||
STR_GENERATION_PREPARING_TILELOOP :{BLACK}A preparar o terreno
|
STR_GENERATION_PREPARING_TILELOOP :{BLACK}A preparar o terreno
|
||||||
STR_GENERATION_PREPARING_SCRIPT :{BLACK}Script a correr
|
STR_GENERATION_PREPARING_SCRIPT :{BLACK}A correr script
|
||||||
STR_GENERATION_PREPARING_GAME :{BLACK}A preparar jogo
|
STR_GENERATION_PREPARING_GAME :{BLACK}A preparar jogo
|
||||||
|
|
||||||
STR_TOWN_DATA_ERROR_LOAD_FAILED :{WHITE}Falha ao carregar dados da localidade
|
STR_TOWN_DATA_ERROR_LOAD_FAILED :{WHITE}Falha ao carregar dados da localidade
|
||||||
|
@ -5002,6 +5002,7 @@ STR_ERROR_FLAT_LAND_REQUIRED :{WHITE}É neces
|
||||||
STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION :{WHITE}Terreno inclinado na direcção incorrecta
|
STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION :{WHITE}Terreno inclinado na direcção incorrecta
|
||||||
STR_ERROR_CAN_T_DO_THIS :{WHITE}Não é possível fazer isto...
|
STR_ERROR_CAN_T_DO_THIS :{WHITE}Não é possível fazer isto...
|
||||||
STR_ERROR_BUILDING_MUST_BE_DEMOLISHED :{WHITE}O edifício deve ser demolido primeiro
|
STR_ERROR_BUILDING_MUST_BE_DEMOLISHED :{WHITE}O edifício deve ser demolido primeiro
|
||||||
|
STR_ERROR_BUILDING_IS_PROTECTED :{WHITE}... o edifício está protegido
|
||||||
STR_ERROR_CAN_T_CLEAR_THIS_AREA :{WHITE}Não é possível limpar esta área...
|
STR_ERROR_CAN_T_CLEAR_THIS_AREA :{WHITE}Não é possível limpar esta área...
|
||||||
STR_ERROR_SITE_UNSUITABLE :{WHITE}... sítio inadequado
|
STR_ERROR_SITE_UNSUITABLE :{WHITE}... sítio inadequado
|
||||||
STR_ERROR_ALREADY_BUILT :{WHITE}... já está construído
|
STR_ERROR_ALREADY_BUILT :{WHITE}... já está construído
|
||||||
|
|
|
@ -5188,6 +5188,7 @@ STR_ERROR_FLAT_LAND_REQUIRED :{WHITE}Необ
|
||||||
STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION :{WHITE}Неверный уклон земли
|
STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION :{WHITE}Неверный уклон земли
|
||||||
STR_ERROR_CAN_T_DO_THIS :{WHITE}Это невозможно...
|
STR_ERROR_CAN_T_DO_THIS :{WHITE}Это невозможно...
|
||||||
STR_ERROR_BUILDING_MUST_BE_DEMOLISHED :{WHITE}Сначала снесите здания
|
STR_ERROR_BUILDING_MUST_BE_DEMOLISHED :{WHITE}Сначала снесите здания
|
||||||
|
STR_ERROR_BUILDING_IS_PROTECTED :{WHITE}... это здание защищено от изменений
|
||||||
STR_ERROR_CAN_T_CLEAR_THIS_AREA :{WHITE}Невозможно расчистить данный участок...
|
STR_ERROR_CAN_T_CLEAR_THIS_AREA :{WHITE}Невозможно расчистить данный участок...
|
||||||
STR_ERROR_SITE_UNSUITABLE :{WHITE}... неподходящее место
|
STR_ERROR_SITE_UNSUITABLE :{WHITE}... неподходящее место
|
||||||
STR_ERROR_ALREADY_BUILT :{WHITE}... уже построено
|
STR_ERROR_ALREADY_BUILT :{WHITE}... уже построено
|
||||||
|
|
|
@ -5001,6 +5001,7 @@ STR_ERROR_FLAT_LAND_REQUIRED :{WHITE}需要
|
||||||
STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION :{WHITE}地面斜坡方向不對
|
STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION :{WHITE}地面斜坡方向不對
|
||||||
STR_ERROR_CAN_T_DO_THIS :{WHITE}不能執行以下動作...
|
STR_ERROR_CAN_T_DO_THIS :{WHITE}不能執行以下動作...
|
||||||
STR_ERROR_BUILDING_MUST_BE_DEMOLISHED :{WHITE}必須先摧毀建築物
|
STR_ERROR_BUILDING_MUST_BE_DEMOLISHED :{WHITE}必須先摧毀建築物
|
||||||
|
STR_ERROR_BUILDING_IS_PROTECTED :{WHITE}……建築物受到保護
|
||||||
STR_ERROR_CAN_T_CLEAR_THIS_AREA :{WHITE}不能清除這個地段...
|
STR_ERROR_CAN_T_CLEAR_THIS_AREA :{WHITE}不能清除這個地段...
|
||||||
STR_ERROR_SITE_UNSUITABLE :{WHITE}... 地點不適合
|
STR_ERROR_SITE_UNSUITABLE :{WHITE}... 地點不適合
|
||||||
STR_ERROR_ALREADY_BUILT :{WHITE}……經已建成
|
STR_ERROR_ALREADY_BUILT :{WHITE}……經已建成
|
||||||
|
|
|
@ -8,6 +8,7 @@ add_files(
|
||||||
getoptdata.cpp
|
getoptdata.cpp
|
||||||
getoptdata.h
|
getoptdata.h
|
||||||
hashtable.hpp
|
hashtable.hpp
|
||||||
|
history.cpp
|
||||||
history_func.hpp
|
history_func.hpp
|
||||||
history_type.hpp
|
history_type.hpp
|
||||||
lrucache.hpp
|
lrucache.hpp
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @file history.cpp Implementation of functions for storing historical data. */
|
||||||
|
|
||||||
|
#ifndef HISTORY_CPP
|
||||||
|
#define HISTORY_CPP
|
||||||
|
|
||||||
|
#include "../stdafx.h"
|
||||||
|
|
||||||
|
#include "../core/bitmath_func.hpp"
|
||||||
|
#include "history_type.hpp"
|
||||||
|
#include "history_func.hpp"
|
||||||
|
|
||||||
|
#include "../safeguards.h"
|
||||||
|
|
||||||
|
static void UpdateValidHistory(ValidHistoryMask &valid_history, const HistoryRange &hr, uint cur_month)
|
||||||
|
{
|
||||||
|
if (cur_month % hr.total_division != 0) return;
|
||||||
|
if (hr.division != 1 && !HasBit(valid_history, hr.first - hr.division)) return;
|
||||||
|
|
||||||
|
SB(valid_history, hr.first, hr.records, GB(valid_history, hr.first, hr.records) << 1ULL | 1ULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update mask of valid records.
|
||||||
|
* @param[in,out] valid_history Valid history records.
|
||||||
|
* @param age Current economy month.
|
||||||
|
*/
|
||||||
|
void UpdateValidHistory(ValidHistoryMask &valid_history, uint cur_month)
|
||||||
|
{
|
||||||
|
UpdateValidHistory(valid_history, HISTORY_MONTH, cur_month);
|
||||||
|
UpdateValidHistory(valid_history, HISTORY_QUARTER, cur_month);
|
||||||
|
UpdateValidHistory(valid_history, HISTORY_YEAR, cur_month);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool IsValidHistory(ValidHistoryMask valid_history, const HistoryRange &hr, uint age)
|
||||||
|
{
|
||||||
|
if (hr.hr == nullptr) {
|
||||||
|
if (age < hr.periods) {
|
||||||
|
uint slot = hr.first + age;
|
||||||
|
return HasBit(valid_history, slot);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (age * hr.division < static_cast<uint>(hr.hr->periods - hr.division)) {
|
||||||
|
uint start = age * hr.division + ((TimerGameEconomy::month / hr.hr->division) % hr.division);
|
||||||
|
return IsValidHistory(valid_history, *hr.hr, start/* + hr.division - 1*/);
|
||||||
|
}
|
||||||
|
if (age < hr.periods) {
|
||||||
|
uint slot = hr.first + age - ((hr.hr->periods / hr.division) - 1);
|
||||||
|
return HasBit(valid_history, slot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsValidHistory(ValidHistoryMask valid_history, uint period, uint age)
|
||||||
|
{
|
||||||
|
switch (period) {
|
||||||
|
case 0: return IsValidHistory(valid_history, HISTORY_MONTH, age);
|
||||||
|
case 1: return IsValidHistory(valid_history, HISTORY_QUARTER, age);
|
||||||
|
case 2: return IsValidHistory(valid_history, HISTORY_YEAR, age);
|
||||||
|
default: NOT_REACHED();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* HISTORY_CPP */
|
|
@ -11,16 +11,22 @@
|
||||||
#define HISTORY_FUNC_HPP
|
#define HISTORY_FUNC_HPP
|
||||||
|
|
||||||
#include "../core/bitmath_func.hpp"
|
#include "../core/bitmath_func.hpp"
|
||||||
|
#include "../core/math_func.hpp"
|
||||||
|
#include "../timer/timer_game_economy.h"
|
||||||
#include "history_type.hpp"
|
#include "history_type.hpp"
|
||||||
|
|
||||||
|
void UpdateValidHistory(ValidHistoryMask &valid_history, uint cur_month);
|
||||||
|
bool IsValidHistory(ValidHistoryMask valid_history, uint period, uint age);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update mask of valid history records.
|
* Sum history data elements.
|
||||||
* @param[in,out] valid_history Valid history records.
|
* @note The summation should prevent overflowing, and perform transformations relevant to the type of data.
|
||||||
|
* @tparam T type of history data element.
|
||||||
|
* @param history History elements to sum.
|
||||||
|
* @return Sum of history elements.
|
||||||
*/
|
*/
|
||||||
inline void UpdateValidHistory(ValidHistoryMask &valid_history)
|
template <typename T>
|
||||||
{
|
T SumHistory(typename std::span<const T> history);
|
||||||
SB(valid_history, LAST_MONTH, HISTORY_RECORDS - LAST_MONTH, GB(valid_history, LAST_MONTH, HISTORY_RECORDS - LAST_MONTH) << 1ULL | 1ULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rotate history.
|
* Rotate history.
|
||||||
|
@ -28,24 +34,105 @@ inline void UpdateValidHistory(ValidHistoryMask &valid_history)
|
||||||
* @param history Historical data to rotate.
|
* @param history Historical data to rotate.
|
||||||
*/
|
*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void RotateHistory(HistoryData<T> &history)
|
void RotateHistory(HistoryData<T> &history, ValidHistoryMask valid_history, const HistoryRange &hr, uint cur_month)
|
||||||
{
|
{
|
||||||
std::rotate(std::rbegin(history), std::rbegin(history) + 1, std::rend(history));
|
if (cur_month % hr.total_division != 0) return;
|
||||||
history[THIS_MONTH] = {};
|
|
||||||
|
std::move_backward(std::next(std::begin(history), hr.first), std::next(std::begin(history), hr.last - 1), std::next(std::begin(history), hr.last));
|
||||||
|
|
||||||
|
if (hr.division == 1) {
|
||||||
|
history[hr.first] = history[hr.first - 1];
|
||||||
|
} else if (HasBit(valid_history, hr.first - hr.division)) {
|
||||||
|
auto first = std::next(std::begin(history), hr.first - hr.division);
|
||||||
|
auto last = std::next(first, hr.division);
|
||||||
|
history[hr.first] = SumHistory<T>(std::span{first, last});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void RotateHistory(HistoryData<T> &history, ValidHistoryMask valid_history, uint cur_month)
|
||||||
|
{
|
||||||
|
RotateHistory(history, valid_history, HISTORY_MONTH, cur_month);
|
||||||
|
RotateHistory(history, valid_history, HISTORY_QUARTER, cur_month);
|
||||||
|
RotateHistory(history, valid_history, HISTORY_YEAR, cur_month);
|
||||||
|
history.front() = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an average value for the previous month, as reset for the next month.
|
||||||
|
* @param total Accrued total to average. Will be reset to zero.
|
||||||
|
* @return Average value for the month.
|
||||||
|
*/
|
||||||
|
template <typename T, typename Taccrued>
|
||||||
|
T GetAndResetAccumulatedAverage(Taccrued &total)
|
||||||
|
{
|
||||||
|
T result = ClampTo<T>(total / std::max(1U, TimerGameEconomy::days_since_last_month));
|
||||||
|
total = 0;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
bool GetHistory(const HistoryData<T> &history, ValidHistoryMask valid_history, const HistoryRange &hr, uint age, T &result)
|
||||||
|
{
|
||||||
|
if (hr.hr == nullptr) {
|
||||||
|
if (age < hr.periods) {
|
||||||
|
uint slot = hr.first + age;
|
||||||
|
result = history[slot];
|
||||||
|
return HasBit(valid_history, slot);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (age * hr.division < static_cast<uint>(hr.hr->periods - hr.division)) {
|
||||||
|
bool is_valid = false;
|
||||||
|
std::array<T, HISTORY_MAX_DIVISION> tmp_result; // No need to clear as we fill every element we use.
|
||||||
|
uint start = age * hr.division + ((TimerGameEconomy::month / hr.hr->division) % hr.division);
|
||||||
|
for (auto i = start; i != start + hr.division; ++i) {
|
||||||
|
is_valid |= GetHistory(history, valid_history, *hr.hr, i, tmp_result[i - start]);
|
||||||
|
}
|
||||||
|
result = SumHistory<T>(std::span{std::begin(tmp_result), hr.division});
|
||||||
|
return is_valid;
|
||||||
|
}
|
||||||
|
if (age < hr.periods) {
|
||||||
|
uint slot = hr.first + age - ((hr.hr->periods / hr.division) - 1);
|
||||||
|
result = history[slot];
|
||||||
|
return HasBit(valid_history, slot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get history data for the specified period and age within that period.
|
||||||
|
* @param history History data to extract from.
|
||||||
|
* @param valid_history Mask of valid history records.
|
||||||
|
* @param period Period to get.
|
||||||
|
* @param age Age of data to get.
|
||||||
|
* @param[out] result Variable to store historical value for period and age.
|
||||||
|
* @return True if the value is valid.
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
bool GetHistory(const HistoryData<T> &history, ValidHistoryMask valid_history, uint period, uint age, T &result)
|
||||||
|
{
|
||||||
|
switch (period) {
|
||||||
|
case 0: return GetHistory(history, valid_history, HISTORY_MONTH, age, result);
|
||||||
|
case 1: return GetHistory(history, valid_history, HISTORY_QUARTER, age, result);
|
||||||
|
case 2: return GetHistory(history, valid_history, HISTORY_YEAR, age, result);
|
||||||
|
default: NOT_REACHED();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fill some data with historical data.
|
* Fill some data with historical data.
|
||||||
* @param history Historical data to fill from.
|
* @param history Historical data to fill from.
|
||||||
* @param valid_history Mask of valid history records.
|
* @param valid_history Mask of valid history records.
|
||||||
|
* @param period Period (monthly, quarterly, yearly) to fill with.
|
||||||
* @param fillers Fillers to fill with history data.
|
* @param fillers Fillers to fill with history data.
|
||||||
*/
|
*/
|
||||||
template <uint N, typename T, typename... Tfillers>
|
template <uint N, typename T, typename... Tfillers>
|
||||||
void FillFromHistory(const HistoryData<T> &history, ValidHistoryMask valid_history, Tfillers... fillers)
|
void FillFromHistory(const HistoryData<T> &history, ValidHistoryMask valid_history, uint period, Tfillers... fillers)
|
||||||
{
|
{
|
||||||
|
T data{};
|
||||||
for (uint i = 0; i != N; ++i) {
|
for (uint i = 0; i != N; ++i) {
|
||||||
if (HasBit(valid_history, N - i)) {
|
if (GetHistory(history, valid_history, period, N - i - 1, data)) {
|
||||||
auto &data = history[N - i];
|
|
||||||
(fillers.Fill(i, data), ...);
|
(fillers.Fill(i, data), ...);
|
||||||
} else {
|
} else {
|
||||||
(fillers.MakeInvalid(i), ...);
|
(fillers.MakeInvalid(i), ...);
|
||||||
|
@ -53,4 +140,22 @@ void FillFromHistory(const HistoryData<T> &history, ValidHistoryMask valid_histo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fill some data with empty records.
|
||||||
|
* @param valid_history Mask of valid history records.
|
||||||
|
* @param period Period (monthly, quarterly, yearly) to fill with.
|
||||||
|
* @param fillers Fillers to fill with history data.
|
||||||
|
*/
|
||||||
|
template <uint N, typename... Tfillers>
|
||||||
|
void FillFromEmpty(ValidHistoryMask valid_history, uint period, Tfillers... fillers)
|
||||||
|
{
|
||||||
|
for (uint i = 0; i != N; ++i) {
|
||||||
|
if (IsValidHistory(valid_history, period, N - i - 1)) {
|
||||||
|
(fillers.MakeZero(i), ...);
|
||||||
|
} else {
|
||||||
|
(fillers.MakeInvalid(i), ...);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* HISTORY_FUNC_HPP */
|
#endif /* HISTORY_FUNC_HPP */
|
||||||
|
|
|
@ -10,7 +10,40 @@
|
||||||
#ifndef HISTORY_TYPE_HPP
|
#ifndef HISTORY_TYPE_HPP
|
||||||
#define HISTORY_TYPE_HPP
|
#define HISTORY_TYPE_HPP
|
||||||
|
|
||||||
static constexpr uint8_t HISTORY_RECORDS = 25;
|
#include "../stdafx.h"
|
||||||
|
|
||||||
|
static constexpr uint8_t HISTORY_PERIODS = 24;
|
||||||
|
|
||||||
|
struct HistoryRange {
|
||||||
|
const HistoryRange *hr;
|
||||||
|
const uint8_t periods; ///< Number of periods for this range.
|
||||||
|
const uint8_t records; ///< Number of records needed for this range.
|
||||||
|
const uint8_t first; ///< Index of first element in history data.
|
||||||
|
const uint8_t last; ///< Index of last element in history data.
|
||||||
|
const uint8_t division; ///< Number of divisions of the previous history range.
|
||||||
|
const uint8_t total_division; ///< Number of divisions of the initial history range.
|
||||||
|
|
||||||
|
explicit constexpr HistoryRange(uint8_t periods) :
|
||||||
|
hr(nullptr), periods(periods), records(this->periods), first(1), last(this->first + this->records), division(1), total_division(1)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr HistoryRange(const HistoryRange &hr, uint8_t division, uint8_t periods) :
|
||||||
|
hr(&hr), periods(periods), records(this->periods - ((hr.periods / division) - 1)), first(hr.last), last(this->first + this->records),
|
||||||
|
division(division), total_division(division * hr.total_division)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static constexpr HistoryRange HISTORY_MONTH{HISTORY_PERIODS};
|
||||||
|
static constexpr HistoryRange HISTORY_QUARTER{HISTORY_MONTH, 3, HISTORY_PERIODS};
|
||||||
|
static constexpr HistoryRange HISTORY_YEAR{HISTORY_QUARTER, 4, HISTORY_PERIODS};
|
||||||
|
|
||||||
|
/** Maximum number of divisions from previous history range. */
|
||||||
|
static constexpr uint8_t HISTORY_MAX_DIVISION = std::max({HISTORY_MONTH.division, HISTORY_QUARTER.division, HISTORY_YEAR.division});
|
||||||
|
|
||||||
|
/** Total number of records require for all history data. */
|
||||||
|
static constexpr uint8_t HISTORY_RECORDS = HISTORY_YEAR.last;
|
||||||
|
|
||||||
static constexpr uint8_t THIS_MONTH = 0;
|
static constexpr uint8_t THIS_MONTH = 0;
|
||||||
static constexpr uint8_t LAST_MONTH = 1;
|
static constexpr uint8_t LAST_MONTH = 1;
|
||||||
|
|
|
@ -476,7 +476,7 @@ CommandCost GetErrorMessageFromLocationCallbackResult(uint16_t cb_res, std::span
|
||||||
/* If this error isn't for the local player then it won't be seen, so don't bother encoding anything. */
|
/* If this error isn't for the local player then it won't be seen, so don't bother encoding anything. */
|
||||||
if (IsLocalCompany()) {
|
if (IsLocalCompany()) {
|
||||||
StringID stringid = GetGRFStringID(grffile->grfid, text_id);
|
StringID stringid = GetGRFStringID(grffile->grfid, text_id);
|
||||||
auto params = GetGRFSringTextStackParameters(grffile, stringid, textstack);
|
auto params = GetGRFStringTextStackParameters(grffile, stringid, textstack);
|
||||||
res.SetEncodedMessage(GetEncodedStringWithArgs(stringid, params));
|
res.SetEncodedMessage(GetEncodedStringWithArgs(stringid, params));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -973,7 +973,7 @@ static void HandleNewGRFStringControlCodes(std::string_view str, TextRefStack &s
|
||||||
* @param textstack Text parameter stack.
|
* @param textstack Text parameter stack.
|
||||||
* @returns Parameters for GRF string.
|
* @returns Parameters for GRF string.
|
||||||
*/
|
*/
|
||||||
std::vector<StringParameter> GetGRFSringTextStackParameters(const GRFFile *grffile, StringID stringid, std::span<const int32_t> textstack)
|
std::vector<StringParameter> GetGRFStringTextStackParameters(const GRFFile *grffile, StringID stringid, std::span<const int32_t> textstack)
|
||||||
{
|
{
|
||||||
if (stringid == INVALID_STRING_ID) return {};
|
if (stringid == INVALID_STRING_ID) return {};
|
||||||
|
|
||||||
|
@ -998,6 +998,6 @@ std::vector<StringParameter> GetGRFSringTextStackParameters(const GRFFile *grffi
|
||||||
std::string GetGRFStringWithTextStack(const struct GRFFile *grffile, GRFStringID grfstringid, std::span<const int32_t> textstack)
|
std::string GetGRFStringWithTextStack(const struct GRFFile *grffile, GRFStringID grfstringid, std::span<const int32_t> textstack)
|
||||||
{
|
{
|
||||||
StringID stringid = GetGRFStringID(grffile->grfid, grfstringid);
|
StringID stringid = GetGRFStringID(grffile->grfid, grfstringid);
|
||||||
auto params = GetGRFSringTextStackParameters(grffile, stringid, textstack);
|
auto params = GetGRFStringTextStackParameters(grffile, stringid, textstack);
|
||||||
return GetStringWithArgs(stringid, params);
|
return GetStringWithArgs(stringid, params);
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ void AddGRFTextToList(GRFTextWrapper &list, std::string_view text_to_add);
|
||||||
|
|
||||||
bool CheckGrfLangID(uint8_t lang_id, uint8_t grf_version);
|
bool CheckGrfLangID(uint8_t lang_id, uint8_t grf_version);
|
||||||
|
|
||||||
std::vector<StringParameter> GetGRFSringTextStackParameters(const struct GRFFile *grffile, StringID stringid, std::span<const int32_t> textstack);
|
std::vector<StringParameter> GetGRFStringTextStackParameters(const struct GRFFile *grffile, StringID stringid, std::span<const int32_t> textstack);
|
||||||
std::string GetGRFStringWithTextStack(const struct GRFFile *grffile, GRFStringID grfstringid, std::span<const int32_t> textstack);
|
std::string GetGRFStringWithTextStack(const struct GRFFile *grffile, GRFStringID grfstringid, std::span<const int32_t> textstack);
|
||||||
|
|
||||||
#endif /* NEWGRF_TEXT_H */
|
#endif /* NEWGRF_TEXT_H */
|
||||||
|
|
|
@ -19,12 +19,50 @@
|
||||||
|
|
||||||
static OldPersistentStorage _old_ind_persistent_storage;
|
static OldPersistentStorage _old_ind_persistent_storage;
|
||||||
|
|
||||||
|
class SlIndustryAcceptedHistory : public DefaultSaveLoadHandler<SlIndustryAcceptedHistory, Industry::AcceptedCargo> {
|
||||||
|
public:
|
||||||
|
static inline const SaveLoad description[] = {
|
||||||
|
SLE_VAR(Industry::AcceptedHistory, accepted, SLE_UINT16),
|
||||||
|
SLE_VAR(Industry::AcceptedHistory, waiting, SLE_UINT16),
|
||||||
|
};
|
||||||
|
static inline const SaveLoadCompatTable compat_description = _industry_produced_history_sl_compat;
|
||||||
|
|
||||||
|
void Save(Industry::AcceptedCargo *a) const override
|
||||||
|
{
|
||||||
|
if (!IsValidCargoType(a->cargo) || a->history == nullptr) {
|
||||||
|
/* Don't save any history if cargo slot isn't used. */
|
||||||
|
SlSetStructListLength(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SlSetStructListLength(a->history->size());
|
||||||
|
|
||||||
|
for (auto &h : *a->history) {
|
||||||
|
SlObject(&h, this->GetDescription());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Load(Industry::AcceptedCargo *a) const override
|
||||||
|
{
|
||||||
|
size_t len = SlGetStructListLength(UINT32_MAX);
|
||||||
|
if (len == 0) return;
|
||||||
|
|
||||||
|
auto &history = a->GetOrCreateHistory();
|
||||||
|
for (auto &h : history) {
|
||||||
|
if (--len > history.size()) break; // unsigned so wraps after hitting zero.
|
||||||
|
SlObject(&h, this->GetDescription());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class SlIndustryAccepted : public VectorSaveLoadHandler<SlIndustryAccepted, Industry, Industry::AcceptedCargo, INDUSTRY_NUM_INPUTS> {
|
class SlIndustryAccepted : public VectorSaveLoadHandler<SlIndustryAccepted, Industry, Industry::AcceptedCargo, INDUSTRY_NUM_INPUTS> {
|
||||||
public:
|
public:
|
||||||
static inline const SaveLoad description[] = {
|
static inline const SaveLoad description[] = {
|
||||||
SLE_VAR(Industry::AcceptedCargo, cargo, SLE_UINT8),
|
SLE_VAR(Industry::AcceptedCargo, cargo, SLE_UINT8),
|
||||||
SLE_VAR(Industry::AcceptedCargo, waiting, SLE_UINT16),
|
SLE_VAR(Industry::AcceptedCargo, waiting, SLE_UINT16),
|
||||||
SLE_VAR(Industry::AcceptedCargo, last_accepted, SLE_INT32),
|
SLE_VAR(Industry::AcceptedCargo, last_accepted, SLE_INT32),
|
||||||
|
SLE_CONDVAR(Industry::AcceptedCargo, accumulated_waiting, SLE_UINT32, SLV_INDUSTRY_ACCEPTED_HISTORY, SL_MAX_VERSION),
|
||||||
|
SLEG_CONDSTRUCTLIST("history", SlIndustryAcceptedHistory, SLV_INDUSTRY_ACCEPTED_HISTORY, SL_MAX_VERSION),
|
||||||
};
|
};
|
||||||
static inline const SaveLoadCompatTable compat_description = _industry_accepts_sl_compat;
|
static inline const SaveLoadCompatTable compat_description = _industry_accepts_sl_compat;
|
||||||
|
|
||||||
|
|
|
@ -858,7 +858,7 @@ static bool LoadOldIndustry(LoadgameState &ls, int num)
|
||||||
|
|
||||||
if (i->location.tile != 0) {
|
if (i->location.tile != 0) {
|
||||||
/* Copy data from old fixed arrays to industry. */
|
/* Copy data from old fixed arrays to industry. */
|
||||||
std::copy(std::begin(_old_accepted), std::end(_old_accepted), std::back_inserter(i->accepted));
|
std::move(std::begin(_old_accepted), std::end(_old_accepted), std::back_inserter(i->accepted));
|
||||||
std::copy(std::begin(_old_produced), std::end(_old_produced), std::back_inserter(i->produced));
|
std::copy(std::begin(_old_produced), std::end(_old_produced), std::back_inserter(i->produced));
|
||||||
|
|
||||||
i->town = RemapTown(i->location.tile);
|
i->town = RemapTown(i->location.tile);
|
||||||
|
|
|
@ -405,6 +405,7 @@ enum SaveLoadVersion : uint16_t {
|
||||||
|
|
||||||
SLV_FACE_STYLES, ///< 355 PR#14319 Addition of face styles, replacing gender and ethnicity.
|
SLV_FACE_STYLES, ///< 355 PR#14319 Addition of face styles, replacing gender and ethnicity.
|
||||||
SLV_INDUSTRY_NUM_VALID_HISTORY, ///< 356 PR#14416 Store number of valid history records for industries.
|
SLV_INDUSTRY_NUM_VALID_HISTORY, ///< 356 PR#14416 Store number of valid history records for industries.
|
||||||
|
SLV_INDUSTRY_ACCEPTED_HISTORY, ///< 357 PR#14321 Add per-industry history of cargo delivered and waiting.
|
||||||
|
|
||||||
SL_MAX_VERSION, ///< Highest possible saveload version
|
SL_MAX_VERSION, ///< Highest possible saveload version
|
||||||
};
|
};
|
||||||
|
|
|
@ -130,6 +130,13 @@ bool ScriptInstance::LoadCompatibilityScripts(Subdirectory dir, std::span<const
|
||||||
|
|
||||||
ScriptLog::Info(fmt::format("Downgrading API to be compatible with version {}", this->api_version));
|
ScriptLog::Info(fmt::format("Downgrading API to be compatible with version {}", this->api_version));
|
||||||
|
|
||||||
|
HSQUIRRELVM vm = this->engine->GetVM();
|
||||||
|
sq_pushroottable(vm);
|
||||||
|
sq_pushstring(vm, "CompatScriptRootTable");
|
||||||
|
sq_pushroottable(vm);
|
||||||
|
sq_newslot(vm, -3, SQFalse);
|
||||||
|
sq_pop(vm, 1);
|
||||||
|
|
||||||
/* Downgrade the API till we are the same version as the script. The last
|
/* Downgrade the API till we are the same version as the script. The last
|
||||||
* entry in the list is always the current version, so skip that one. */
|
* entry in the list is always the current version, so skip that one. */
|
||||||
for (auto it = std::rbegin(api_versions) + 1; it != std::rend(api_versions); ++it) {
|
for (auto it = std::rbegin(api_versions) + 1; it != std::rend(api_versions); ++it) {
|
||||||
|
@ -138,6 +145,11 @@ bool ScriptInstance::LoadCompatibilityScripts(Subdirectory dir, std::span<const
|
||||||
if (*it == this->api_version) break;
|
if (*it == this->api_version) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sq_pushroottable(vm);
|
||||||
|
sq_pushstring(vm, "CompatScriptRootTable");
|
||||||
|
sq_deleteslot(vm, -2, SQFalse);
|
||||||
|
sq_pop(vm, 1);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -607,28 +607,25 @@ bool ConvertHexToBytes(std::string_view hex, std::span<uint8_t> bytes)
|
||||||
/** String iterator using ICU as a backend. */
|
/** String iterator using ICU as a backend. */
|
||||||
class IcuStringIterator : public StringIterator
|
class IcuStringIterator : public StringIterator
|
||||||
{
|
{
|
||||||
icu::BreakIterator *char_itr; ///< ICU iterator for characters.
|
std::unique_ptr<icu::BreakIterator> char_itr; ///< ICU iterator for characters.
|
||||||
icu::BreakIterator *word_itr; ///< ICU iterator for words.
|
std::unique_ptr<icu::BreakIterator> word_itr; ///< ICU iterator for words.
|
||||||
|
|
||||||
std::vector<UChar> utf16_str; ///< UTF-16 copy of the string.
|
std::vector<UChar> utf16_str; ///< UTF-16 copy of the string.
|
||||||
std::vector<size_t> utf16_to_utf8; ///< Mapping from UTF-16 code point position to index in the UTF-8 source string.
|
std::vector<size_t> utf16_to_utf8; ///< Mapping from UTF-16 code point position to index in the UTF-8 source string.
|
||||||
|
|
||||||
public:
|
public:
|
||||||
IcuStringIterator() : char_itr(nullptr), word_itr(nullptr)
|
IcuStringIterator()
|
||||||
{
|
{
|
||||||
UErrorCode status = U_ZERO_ERROR;
|
UErrorCode status = U_ZERO_ERROR;
|
||||||
this->char_itr = icu::BreakIterator::createCharacterInstance(icu::Locale(_current_language != nullptr ? _current_language->isocode : "en"), status);
|
auto locale = icu::Locale(_current_language != nullptr ? _current_language->isocode : "en");
|
||||||
this->word_itr = icu::BreakIterator::createWordInstance(icu::Locale(_current_language != nullptr ? _current_language->isocode : "en"), status);
|
this->char_itr.reset(icu::BreakIterator::createCharacterInstance(locale, status));
|
||||||
|
this->word_itr.reset(icu::BreakIterator::createWordInstance(locale, status));
|
||||||
|
|
||||||
this->utf16_str.push_back('\0');
|
this->utf16_str.push_back('\0');
|
||||||
this->utf16_to_utf8.push_back(0);
|
this->utf16_to_utf8.push_back(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
~IcuStringIterator() override
|
~IcuStringIterator() override = default;
|
||||||
{
|
|
||||||
delete this->char_itr;
|
|
||||||
delete this->word_itr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetString(std::string_view s) override
|
void SetString(std::string_view s) override
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,6 +3,7 @@ add_test_files(
|
||||||
bitmath_func.cpp
|
bitmath_func.cpp
|
||||||
enum_over_optimisation.cpp
|
enum_over_optimisation.cpp
|
||||||
flatset_type.cpp
|
flatset_type.cpp
|
||||||
|
history_func.cpp
|
||||||
landscape_partial_pixel_z.cpp
|
landscape_partial_pixel_z.cpp
|
||||||
math_func.cpp
|
math_func.cpp
|
||||||
mock_environment.h
|
mock_environment.h
|
||||||
|
|
|
@ -0,0 +1,87 @@
|
||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @file history_func.cpp Test functionality for misc/history_func. */
|
||||||
|
|
||||||
|
#include "../stdafx.h"
|
||||||
|
|
||||||
|
#include "../3rdparty/catch2/catch.hpp"
|
||||||
|
|
||||||
|
#include "../misc/history_type.hpp"
|
||||||
|
#include "../misc/history_func.hpp"
|
||||||
|
|
||||||
|
#include "../safeguards.h"
|
||||||
|
|
||||||
|
template <>
|
||||||
|
uint16_t SumHistory(std::span<const uint16_t> history)
|
||||||
|
{
|
||||||
|
uint32_t total = std::accumulate(std::begin(history), std::end(history), 0, [](uint32_t r, const uint16_t &value) { return r + value; });
|
||||||
|
return ClampTo<uint16_t>(total);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper to get history records and return the value, instead returning its validity.
|
||||||
|
* @param history History data to extract from.
|
||||||
|
* @param period Period to get.
|
||||||
|
* @param age Age of data to get.
|
||||||
|
* @return Historical value for the period and age.
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
T GetHistory(const HistoryData<T> &history, uint period, uint age)
|
||||||
|
{
|
||||||
|
T result;
|
||||||
|
switch (period) {
|
||||||
|
case 0: GetHistory(history, 0, HISTORY_MONTH, age, result); break;
|
||||||
|
case 1: GetHistory(history, 0, HISTORY_QUARTER, age, result); break;
|
||||||
|
case 2: GetHistory(history, 0, HISTORY_YEAR, age, result); break;
|
||||||
|
default: NOT_REACHED();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("History Rotation and Reporting tests")
|
||||||
|
{
|
||||||
|
HistoryData<uint16_t> history{};
|
||||||
|
uint64_t valid_history = 0;
|
||||||
|
|
||||||
|
/* Fill the history with decreasing data points for 24 years of history. This ensures that no data period should
|
||||||
|
* contain the same value as another period. */
|
||||||
|
uint16_t i = 12 * HISTORY_PERIODS;
|
||||||
|
for (uint date = 1; date <= 12 * HISTORY_PERIODS; ++date, --i) {
|
||||||
|
history[THIS_MONTH] = i;
|
||||||
|
RotateHistory(history, valid_history, date % 12);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* With the decreasing sequence, the expected value is triangle number (x*x+n)/2 and the square of the total divisions.
|
||||||
|
* for quarters: 1 + 2 + 3 = 6, 4 + 5 + 6 = 15, 7 + 8 + 9 = 24, 10 + 11 + 12 = 33
|
||||||
|
* 13 + 14 + 15 = 42, 16 + 17 + 18 = 51, 19 + 20 + 21 = 60, 22 + 23 + 24 = 69...
|
||||||
|
* for years: 6 + 15 + 24 + 33 = 78, 42 + 51 + 60 + 69 = 222...
|
||||||
|
*/
|
||||||
|
for (uint j = 0; j < HISTORY_PERIODS; ++j) {
|
||||||
|
CHECK(GetHistory(history, 0, j) == (( 1 * 1 + 1) / 2) + 1 * 1 * j);
|
||||||
|
CHECK(GetHistory(history, 1, j) == (( 3 * 3 + 3) / 2) + 3 * 3 * j);
|
||||||
|
CHECK(GetHistory(history, 2, j) == ((12 * 12 + 12) / 2) + 12 * 12 * j);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Double-check quarter history matches summed month history. */
|
||||||
|
CHECK(GetHistory(history, 0, 0) + GetHistory(history, 0, 1) + GetHistory(history, 0, 2) == GetHistory(history, 1, 0));
|
||||||
|
CHECK(GetHistory(history, 0, 3) + GetHistory(history, 0, 4) + GetHistory(history, 0, 5) == GetHistory(history, 1, 1));
|
||||||
|
CHECK(GetHistory(history, 0, 6) + GetHistory(history, 0, 7) + GetHistory(history, 0, 8) == GetHistory(history, 1, 2));
|
||||||
|
CHECK(GetHistory(history, 0, 9) + GetHistory(history, 0, 10) + GetHistory(history, 0, 11) == GetHistory(history, 1, 3));
|
||||||
|
CHECK(GetHistory(history, 0, 12) + GetHistory(history, 0, 13) + GetHistory(history, 0, 14) == GetHistory(history, 1, 4));
|
||||||
|
CHECK(GetHistory(history, 0, 15) + GetHistory(history, 0, 16) + GetHistory(history, 0, 17) == GetHistory(history, 1, 5));
|
||||||
|
CHECK(GetHistory(history, 0, 18) + GetHistory(history, 0, 19) + GetHistory(history, 0, 20) == GetHistory(history, 1, 6));
|
||||||
|
CHECK(GetHistory(history, 0, 21) + GetHistory(history, 0, 22) + GetHistory(history, 0, 23) == GetHistory(history, 1, 7));
|
||||||
|
|
||||||
|
/* Double-check year history matches summed quarter history. */
|
||||||
|
CHECK(GetHistory(history, 1, 0) + GetHistory(history, 1, 1) + GetHistory(history, 1, 2) + GetHistory(history, 1, 3) == GetHistory(history, 2, 0));
|
||||||
|
CHECK(GetHistory(history, 1, 4) + GetHistory(history, 1, 5) + GetHistory(history, 1, 6) + GetHistory(history, 1, 7) == GetHistory(history, 2, 1));
|
||||||
|
CHECK(GetHistory(history, 1, 8) + GetHistory(history, 1, 9) + GetHistory(history, 1, 10) + GetHistory(history, 1, 11) == GetHistory(history, 2, 2));
|
||||||
|
CHECK(GetHistory(history, 1, 12) + GetHistory(history, 1, 13) + GetHistory(history, 1, 14) + GetHistory(history, 1, 15) == GetHistory(history, 2, 3));
|
||||||
|
CHECK(GetHistory(history, 1, 16) + GetHistory(history, 1, 17) + GetHistory(history, 1, 18) + GetHistory(history, 1, 19) == GetHistory(history, 2, 4));
|
||||||
|
CHECK(GetHistory(history, 1, 20) + GetHistory(history, 1, 21) + GetHistory(history, 1, 22) + GetHistory(history, 1, 23) == GetHistory(history, 2, 5));
|
||||||
|
}
|
|
@ -37,6 +37,7 @@ TimerGameEconomy::Year TimerGameEconomy::year = {};
|
||||||
TimerGameEconomy::Month TimerGameEconomy::month = {};
|
TimerGameEconomy::Month TimerGameEconomy::month = {};
|
||||||
TimerGameEconomy::Date TimerGameEconomy::date = {};
|
TimerGameEconomy::Date TimerGameEconomy::date = {};
|
||||||
TimerGameEconomy::DateFract TimerGameEconomy::date_fract = {};
|
TimerGameEconomy::DateFract TimerGameEconomy::date_fract = {};
|
||||||
|
uint TimerGameEconomy::days_since_last_month = {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a Date to a Year, Month & Day.
|
* Converts a Date to a Year, Month & Day.
|
||||||
|
@ -133,6 +134,7 @@ bool TimerManager<TimerGameEconomy>::Elapsed([[maybe_unused]] TimerGameEconomy::
|
||||||
|
|
||||||
/* increase day counter */
|
/* increase day counter */
|
||||||
TimerGameEconomy::date++;
|
TimerGameEconomy::date++;
|
||||||
|
++TimerGameEconomy::days_since_last_month;
|
||||||
|
|
||||||
TimerGameEconomy::YearMonthDay ymd = TimerGameEconomy::ConvertDateToYMD(TimerGameEconomy::date);
|
TimerGameEconomy::YearMonthDay ymd = TimerGameEconomy::ConvertDateToYMD(TimerGameEconomy::date);
|
||||||
|
|
||||||
|
@ -177,6 +179,8 @@ bool TimerManager<TimerGameEconomy>::Elapsed([[maybe_unused]] TimerGameEconomy::
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (new_month) TimerGameEconomy::days_since_last_month = 0;
|
||||||
|
|
||||||
/* check if we reached the maximum year, decrement dates by a year */
|
/* check if we reached the maximum year, decrement dates by a year */
|
||||||
if (TimerGameEconomy::year == EconomyTime::MAX_YEAR + 1) {
|
if (TimerGameEconomy::year == EconomyTime::MAX_YEAR + 1) {
|
||||||
TimerGameEconomy::year--;
|
TimerGameEconomy::year--;
|
||||||
|
|
|
@ -37,6 +37,8 @@ public:
|
||||||
static Date date; ///< Current date in days (day counter).
|
static Date date; ///< Current date in days (day counter).
|
||||||
static DateFract date_fract; ///< Fractional part of the day.
|
static DateFract date_fract; ///< Fractional part of the day.
|
||||||
|
|
||||||
|
static uint days_since_last_month; ///< Number of days that have elapsed since the last month.
|
||||||
|
|
||||||
static YearMonthDay ConvertDateToYMD(Date date);
|
static YearMonthDay ConvertDateToYMD(Date date);
|
||||||
static Date ConvertYMDToDate(Year year, Month month, Day day);
|
static Date ConvertYMDToDate(Year year, Month month, Day day);
|
||||||
static void SetDate(Date date, DateFract fract);
|
static void SetDate(Date date, DateFract fract);
|
||||||
|
|
|
@ -710,7 +710,7 @@ static void TileLoop_Town(TileIndex tile)
|
||||||
static CommandCost ClearTile_Town(TileIndex tile, DoCommandFlags flags)
|
static CommandCost ClearTile_Town(TileIndex tile, DoCommandFlags flags)
|
||||||
{
|
{
|
||||||
if (flags.Test(DoCommandFlag::Auto)) return CommandCost(STR_ERROR_BUILDING_MUST_BE_DEMOLISHED);
|
if (flags.Test(DoCommandFlag::Auto)) return CommandCost(STR_ERROR_BUILDING_MUST_BE_DEMOLISHED);
|
||||||
if (!CanDeleteHouse(tile)) return CMD_ERROR;
|
if (!CanDeleteHouse(tile)) return CommandCost(STR_ERROR_BUILDING_IS_PROTECTED);
|
||||||
|
|
||||||
const HouseSpec *hs = HouseSpec::Get(GetHouseType(tile));
|
const HouseSpec *hs = HouseSpec::Get(GetHouseType(tile));
|
||||||
|
|
||||||
|
@ -724,7 +724,7 @@ static CommandCost ClearTile_Town(TileIndex tile, DoCommandFlags flags)
|
||||||
if (!_cheats.magic_bulldozer.value && !flags.Test(DoCommandFlag::NoTestTownRating)) {
|
if (!_cheats.magic_bulldozer.value && !flags.Test(DoCommandFlag::NoTestTownRating)) {
|
||||||
/* NewGRFs can add indestructible houses. */
|
/* NewGRFs can add indestructible houses. */
|
||||||
if (rating > RATING_MAXIMUM) {
|
if (rating > RATING_MAXIMUM) {
|
||||||
return CommandCost(CMD_ERROR);
|
return CommandCost(STR_ERROR_BUILDING_IS_PROTECTED);
|
||||||
}
|
}
|
||||||
/* If town authority controls removal, check the company's rating. */
|
/* If town authority controls removal, check the company's rating. */
|
||||||
if (rating > t->ratings[_current_company] && _settings_game.difficulty.town_council_tolerance != TOWN_COUNCIL_PERMISSIVE) {
|
if (rating > t->ratings[_current_company] && _settings_game.difficulty.town_council_tolerance != TOWN_COUNCIL_PERMISSIVE) {
|
||||||
|
|
|
@ -118,7 +118,7 @@ std::optional<std::string_view> VideoDriver_SDL_OpenGL::AllocateContext()
|
||||||
}
|
}
|
||||||
|
|
||||||
this->gl_context = SDL_GL_CreateContext(this->sdl_window);
|
this->gl_context = SDL_GL_CreateContext(this->sdl_window);
|
||||||
if (this->gl_context == nullptr) return "SDL2: Can't active GL context";
|
if (this->gl_context == nullptr) return "SDL2: Can't activate GL context";
|
||||||
|
|
||||||
ToggleVsync(_video_vsync);
|
ToggleVsync(_video_vsync);
|
||||||
|
|
||||||
|
|
|
@ -1541,7 +1541,7 @@ std::optional<std::string_view> VideoDriver_Win32OpenGL::AllocateContext()
|
||||||
rc = wglCreateContext(this->dc);
|
rc = wglCreateContext(this->dc);
|
||||||
if (rc == nullptr) return "Can't create OpenGL context";
|
if (rc == nullptr) return "Can't create OpenGL context";
|
||||||
}
|
}
|
||||||
if (!wglMakeCurrent(this->dc, rc)) return "Can't active GL context";
|
if (!wglMakeCurrent(this->dc, rc)) return "Can't activate GL context";
|
||||||
|
|
||||||
this->ToggleVsync(_video_vsync);
|
this->ToggleVsync(_video_vsync);
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,7 @@ enum GraphWidgets : WidgetID {
|
||||||
WID_GRAPH_MATRIX_SCROLLBAR,///< Cargo list scrollbar.
|
WID_GRAPH_MATRIX_SCROLLBAR,///< Cargo list scrollbar.
|
||||||
|
|
||||||
WID_GRAPH_RANGE_MATRIX, ///< Range list.
|
WID_GRAPH_RANGE_MATRIX, ///< Range list.
|
||||||
|
WID_GRAPH_SCALE_MATRIX, ///< Horizontal axis scale list.
|
||||||
|
|
||||||
WID_PHG_DETAILED_PERFORMANCE, ///< Detailed performance.
|
WID_PHG_DETAILED_PERFORMANCE, ///< Detailed performance.
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue