Feature: Use real-time "wallclock" timekeeping units (#11341)

This commit is contained in:
Tyler Trahan 2024-01-23 11:36:09 -05:00 committed by GitHub
parent bbdbf9a589
commit fd9e72a7e7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
30 changed files with 546 additions and 140 deletions

View File

@ -116,7 +116,9 @@ static int32_t ClickChangeDateCheat(int32_t new_value, int32_t)
/* Now it's safe to actually change the date. */
TimerGameCalendar::SetDate(new_calendar_date, TimerGameCalendar::date_fract);
TimerGameEconomy::SetDate(new_economy_date, TimerGameEconomy::date_fract);
/* If not using wallclock units, we keep economy date in sync with calendar date and must change it also. */
if (!TimerGameEconomy::UsingWallclockUnits()) TimerGameEconomy::SetDate(new_economy_date, TimerGameEconomy::date_fract);
CalendarEnginesMonthlyLoop();
SetWindowDirty(WC_STATUS_BAR, 0);

View File

@ -138,7 +138,7 @@ static uint GetTotalCategoriesHeight()
*/
static uint GetMaxCategoriesWidth()
{
uint max_width = 0;
uint max_width = GetStringBoundingBox(STR_FINANCES_YEAR_CAPTION).width;
/* Loop through categories to check max widths. */
for (const ExpensesList &list : _expenses_list_types) {
@ -173,8 +173,10 @@ static void DrawCategory(const Rect &r, int start_y, const ExpensesList &list)
*/
static void DrawCategories(const Rect &r)
{
/* Start with an empty space in the year row, plus the blockspace under the year. */
int y = r.top + GetCharacterHeight(FS_NORMAL) + WidgetDimensions::scaled.vsep_wide;
int y = r.top;
/* Draw description of 12-minute economic period. */
DrawString(r.left, r.right, y, (STR_FINANCES_YEAR_CAPTION), TC_FROMSTRING, SA_LEFT, true);
y += GetCharacterHeight(FS_NORMAL) + WidgetDimensions::scaled.vsep_wide;
for (const ExpensesList &list : _expenses_list_types) {
/* Draw category title and advance y */

View File

@ -170,6 +170,9 @@ protected:
static const int GRAPH_ZERO_LINE_COLOUR = GREY_SCALE(8);
static const int GRAPH_YEAR_LINE_COLOUR = GREY_SCALE(5);
static const int GRAPH_NUM_MONTHS = 24; ///< Number of months displayed in the graph.
static const int PAYMENT_GRAPH_X_STEP_DAYS = 20; ///< X-axis step label for cargo payment rates "Days in transit".
static const int PAYMENT_GRAPH_X_STEP_SECONDS = 10; ///< X-axis step label for cargo payment rates "Seconds in transit".
static const int ECONOMY_QUARTER_MINUTES = 3; ///< Minutes per economic quarter.
static const TextColour GRAPH_AXIS_LABEL_COLOUR = TC_BLACK; ///< colour of the graph axis label.
@ -336,8 +339,13 @@ protected:
/* Don't draw the first line, as that's where the axis will be. */
x = r.left + x_sep;
for (int i = 0; i < this->num_vert_lines; i++) {
GfxFillRect(x, r.top, x, r.bottom, GRAPH_GRID_COLOUR);
int grid_colour = GRAPH_GRID_COLOUR;
for (int i = 1; i < this->num_vert_lines + 1; i++) {
/* If using wallclock units, we separate periods with a lighter line. */
if (TimerGameEconomy::UsingWallclockUnits()) {
grid_colour = (i % 4 == 0) ? GRAPH_YEAR_LINE_COLOUR : GRAPH_GRID_COLOUR;
}
GfxFillRect(x, r.top, x, r.bottom, grid_colour);
x += x_sep;
}
@ -399,7 +407,7 @@ protected:
x += x_sep;
}
} else {
/* Draw x-axis labels for graphs not based on quarterly performance (cargo payment rates). */
/* Draw x-axis labels for graphs not based on quarterly performance (cargo payment rates, and all graphs when using wallclock units). */
x = r.left;
y = r.bottom + ScaleGUITrad(2);
uint16_t label = this->x_values_start;
@ -622,6 +630,12 @@ struct OperatingProfitGraphWindow : BaseGraphWindow {
OperatingProfitGraphWindow(WindowDesc *desc, WindowNumber window_number) :
BaseGraphWindow(desc, WID_CV_GRAPH, STR_JUST_CURRENCY_SHORT)
{
this->num_on_x_axis = GRAPH_NUM_MONTHS;
this->num_vert_lines = GRAPH_NUM_MONTHS;
this->x_values_start = ECONOMY_QUARTER_MINUTES;
this->x_values_increment = ECONOMY_QUARTER_MINUTES;
this->draw_dates = !TimerGameEconomy::UsingWallclockUnits();
this->InitializeWindow(window_number);
}
@ -641,10 +655,12 @@ static constexpr NWidgetPart _nested_operating_profit_widgets[] = {
NWidget(WWT_STICKYBOX, COLOUR_BROWN),
EndContainer(),
NWidget(WWT_PANEL, COLOUR_BROWN, WID_CV_BACKGROUND),
NWidget(NWID_HORIZONTAL),
NWidget(NWID_VERTICAL),
NWidget(WWT_EMPTY, COLOUR_BROWN, WID_CV_GRAPH), SetMinimalSize(576, 160), SetFill(1, 1), SetResize(1, 1),
NWidget(NWID_VERTICAL),
NWidget(NWID_SPACER), SetFill(0, 1), SetResize(0, 1),
NWidget(NWID_HORIZONTAL),
NWidget(NWID_SPACER), SetMinimalSize(12, 0), SetFill(1, 0), SetResize(1, 0),
NWidget(WWT_TEXT, COLOUR_BROWN, WID_CV_FOOTER), SetMinimalSize(0, 6), SetPadding(2, 0, 2, 0), SetDataTip(STR_GRAPH_LAST_72_MINUTES_TIME_LABEL, STR_NULL),
NWidget(NWID_SPACER), SetFill(1, 0), SetResize(1, 0),
NWidget(WWT_RESIZEBOX, COLOUR_BROWN, WID_CV_RESIZE), SetDataTip(RWV_HIDE_BEVEL, STR_TOOLTIP_RESIZE),
EndContainer(),
EndContainer(),
@ -673,6 +689,12 @@ struct IncomeGraphWindow : BaseGraphWindow {
IncomeGraphWindow(WindowDesc *desc, WindowNumber window_number) :
BaseGraphWindow(desc, WID_CV_GRAPH, STR_JUST_CURRENCY_SHORT)
{
this->num_on_x_axis = GRAPH_NUM_MONTHS;
this->num_vert_lines = GRAPH_NUM_MONTHS;
this->x_values_start = ECONOMY_QUARTER_MINUTES;
this->x_values_increment = ECONOMY_QUARTER_MINUTES;
this->draw_dates = !TimerGameEconomy::UsingWallclockUnits();
this->InitializeWindow(window_number);
}
@ -692,10 +714,12 @@ static constexpr NWidgetPart _nested_income_graph_widgets[] = {
NWidget(WWT_STICKYBOX, COLOUR_BROWN),
EndContainer(),
NWidget(WWT_PANEL, COLOUR_BROWN, WID_CV_BACKGROUND),
NWidget(NWID_HORIZONTAL),
NWidget(NWID_VERTICAL),
NWidget(WWT_EMPTY, COLOUR_BROWN, WID_CV_GRAPH), SetMinimalSize(576, 128), SetFill(1, 1), SetResize(1, 1),
NWidget(NWID_VERTICAL),
NWidget(NWID_SPACER), SetFill(0, 1), SetResize(0, 1),
NWidget(NWID_HORIZONTAL),
NWidget(NWID_SPACER), SetMinimalSize(12, 0), SetFill(1, 0), SetResize(1, 0),
NWidget(WWT_TEXT, COLOUR_BROWN, WID_CV_FOOTER), SetMinimalSize(0, 6), SetPadding(2, 0, 2, 0), SetDataTip(STR_GRAPH_LAST_72_MINUTES_TIME_LABEL, STR_NULL),
NWidget(NWID_SPACER), SetFill(1, 0), SetResize(1, 0),
NWidget(WWT_RESIZEBOX, COLOUR_BROWN, WID_CV_RESIZE), SetDataTip(RWV_HIDE_BEVEL, STR_TOOLTIP_RESIZE),
EndContainer(),
EndContainer(),
@ -722,6 +746,12 @@ struct DeliveredCargoGraphWindow : BaseGraphWindow {
DeliveredCargoGraphWindow(WindowDesc *desc, WindowNumber window_number) :
BaseGraphWindow(desc, WID_CV_GRAPH, STR_JUST_COMMA)
{
this->num_on_x_axis = GRAPH_NUM_MONTHS;
this->num_vert_lines = GRAPH_NUM_MONTHS;
this->x_values_start = ECONOMY_QUARTER_MINUTES;
this->x_values_increment = ECONOMY_QUARTER_MINUTES;
this->draw_dates = !TimerGameEconomy::UsingWallclockUnits();
this->InitializeWindow(window_number);
}
@ -741,10 +771,12 @@ static constexpr NWidgetPart _nested_delivered_cargo_graph_widgets[] = {
NWidget(WWT_STICKYBOX, COLOUR_BROWN),
EndContainer(),
NWidget(WWT_PANEL, COLOUR_BROWN, WID_CV_BACKGROUND),
NWidget(NWID_HORIZONTAL),
NWidget(NWID_VERTICAL),
NWidget(WWT_EMPTY, COLOUR_BROWN, WID_CV_GRAPH), SetMinimalSize(576, 128), SetFill(1, 1), SetResize(1, 1),
NWidget(NWID_VERTICAL),
NWidget(NWID_SPACER), SetFill(0, 1), SetResize(0, 1),
NWidget(NWID_HORIZONTAL),
NWidget(NWID_SPACER), SetMinimalSize(12, 0), SetFill(1, 0), SetResize(1, 0),
NWidget(WWT_TEXT, COLOUR_BROWN, WID_CV_FOOTER), SetMinimalSize(0, 6), SetPadding(2, 0, 2, 0), SetDataTip(STR_GRAPH_LAST_72_MINUTES_TIME_LABEL, STR_NULL),
NWidget(NWID_SPACER), SetFill(1, 0), SetResize(1, 0),
NWidget(WWT_RESIZEBOX, COLOUR_BROWN, WID_CV_RESIZE), SetDataTip(RWV_HIDE_BEVEL, STR_TOOLTIP_RESIZE),
EndContainer(),
EndContainer(),
@ -771,6 +803,12 @@ struct PerformanceHistoryGraphWindow : BaseGraphWindow {
PerformanceHistoryGraphWindow(WindowDesc *desc, WindowNumber window_number) :
BaseGraphWindow(desc, WID_PHG_GRAPH, STR_JUST_COMMA)
{
this->num_on_x_axis = GRAPH_NUM_MONTHS;
this->num_vert_lines = GRAPH_NUM_MONTHS;
this->x_values_start = ECONOMY_QUARTER_MINUTES;
this->x_values_increment = ECONOMY_QUARTER_MINUTES;
this->draw_dates = !TimerGameEconomy::UsingWallclockUnits();
this->InitializeWindow(window_number);
}
@ -797,10 +835,12 @@ static constexpr NWidgetPart _nested_performance_history_widgets[] = {
NWidget(WWT_STICKYBOX, COLOUR_BROWN),
EndContainer(),
NWidget(WWT_PANEL, COLOUR_BROWN, WID_PHG_BACKGROUND),
NWidget(NWID_HORIZONTAL),
NWidget(NWID_VERTICAL),
NWidget(WWT_EMPTY, COLOUR_BROWN, WID_PHG_GRAPH), SetMinimalSize(576, 224), SetFill(1, 1), SetResize(1, 1),
NWidget(NWID_VERTICAL),
NWidget(NWID_SPACER), SetFill(0, 1), SetResize(0, 1),
NWidget(NWID_HORIZONTAL),
NWidget(NWID_SPACER), SetMinimalSize(12, 0), SetFill(1, 0), SetResize(1, 0),
NWidget(WWT_TEXT, COLOUR_BROWN, WID_PHG_FOOTER), SetMinimalSize(0, 6), SetPadding(2, 0, 2, 0), SetDataTip(STR_GRAPH_LAST_72_MINUTES_TIME_LABEL, STR_NULL),
NWidget(NWID_SPACER), SetFill(1, 0), SetResize(1, 0),
NWidget(WWT_RESIZEBOX, COLOUR_BROWN, WID_PHG_RESIZE), SetDataTip(RWV_HIDE_BEVEL, STR_TOOLTIP_RESIZE),
EndContainer(),
EndContainer(),
@ -827,6 +867,12 @@ struct CompanyValueGraphWindow : BaseGraphWindow {
CompanyValueGraphWindow(WindowDesc *desc, WindowNumber window_number) :
BaseGraphWindow(desc, WID_CV_GRAPH, STR_JUST_CURRENCY_SHORT)
{
this->num_on_x_axis = GRAPH_NUM_MONTHS;
this->num_vert_lines = GRAPH_NUM_MONTHS;
this->x_values_start = ECONOMY_QUARTER_MINUTES;
this->x_values_increment = ECONOMY_QUARTER_MINUTES;
this->draw_dates = !TimerGameEconomy::UsingWallclockUnits();
this->InitializeWindow(window_number);
}
@ -846,10 +892,12 @@ static constexpr NWidgetPart _nested_company_value_graph_widgets[] = {
NWidget(WWT_STICKYBOX, COLOUR_BROWN),
EndContainer(),
NWidget(WWT_PANEL, COLOUR_BROWN, WID_CV_BACKGROUND),
NWidget(NWID_HORIZONTAL),
NWidget(NWID_VERTICAL),
NWidget(WWT_EMPTY, COLOUR_BROWN, WID_CV_GRAPH), SetMinimalSize(576, 224), SetFill(1, 1), SetResize(1, 1),
NWidget(NWID_VERTICAL),
NWidget(NWID_SPACER), SetFill(0, 1), SetResize(0, 1),
NWidget(NWID_HORIZONTAL),
NWidget(NWID_SPACER), SetMinimalSize(12, 0), SetFill(1, 0), SetResize(1, 0),
NWidget(WWT_TEXT, COLOUR_BROWN, WID_CV_FOOTER), SetMinimalSize(0, 6), SetPadding(2, 0, 2, 0), SetDataTip(STR_GRAPH_LAST_72_MINUTES_TIME_LABEL, STR_NULL),
NWidget(NWID_SPACER), SetFill(1, 0), SetResize(1, 0),
NWidget(WWT_RESIZEBOX, COLOUR_BROWN, WID_CV_RESIZE), SetDataTip(RWV_HIDE_BEVEL, STR_TOOLTIP_RESIZE),
EndContainer(),
EndContainer(),
@ -883,8 +931,9 @@ struct PaymentRatesGraphWindow : BaseGraphWindow {
this->num_on_x_axis = 20;
this->num_vert_lines = 20;
this->draw_dates = false;
this->x_values_start = 10;
this->x_values_increment = 10;
/* The x-axis is labeled in either seconds or days. A day is two seconds, so we adjust the label if needed. */
this->x_values_start = (TimerGameEconomy::UsingWallclockUnits() ? PAYMENT_GRAPH_X_STEP_SECONDS : PAYMENT_GRAPH_X_STEP_DAYS);
this->x_values_increment = (TimerGameEconomy::UsingWallclockUnits() ? PAYMENT_GRAPH_X_STEP_SECONDS : PAYMENT_GRAPH_X_STEP_DAYS);
this->CreateNestedTree();
this->vscroll = this->GetScrollbar(WID_CPR_MATRIX_SCROLLBAR);
@ -1085,7 +1134,7 @@ static constexpr NWidgetPart _nested_cargo_payment_rates_widgets[] = {
EndContainer(),
NWidget(NWID_HORIZONTAL),
NWidget(NWID_SPACER), SetMinimalSize(12, 0), SetFill(1, 0), SetResize(1, 0),
NWidget(WWT_TEXT, COLOUR_BROWN, WID_CPR_FOOTER), SetMinimalSize(0, 6), SetPadding(2, 0, 2, 0), SetDataTip(STR_GRAPH_CARGO_PAYMENT_RATES_X_LABEL, STR_NULL),
NWidget(WWT_TEXT, COLOUR_BROWN, WID_CPR_FOOTER), SetMinimalSize(0, 6), SetPadding(2, 0, 2, 0), SetDataTip(STR_GRAPH_CARGO_PAYMENT_RATES_TIME_LABEL, STR_NULL),
NWidget(NWID_SPACER), SetFill(1, 0), SetResize(1, 0),
NWidget(WWT_RESIZEBOX, COLOUR_BROWN, WID_CPR_RESIZE), SetDataTip(RWV_HIDE_BEVEL, STR_TOOLTIP_RESIZE),
EndContainer(),

View File

@ -214,7 +214,8 @@ STR_COLOUR_SECONDARY_SAME_AS_PRIMARY :Same As Primary
STR_UNITS_VELOCITY_IMPERIAL :{DECIMAL}{NBSP}mph
STR_UNITS_VELOCITY_METRIC :{DECIMAL}{NBSP}km/h
STR_UNITS_VELOCITY_SI :{DECIMAL}{NBSP}m/s
STR_UNITS_VELOCITY_GAMEUNITS :{DECIMAL}{NBSP}tiles/day
STR_UNITS_VELOCITY_GAMEUNITS_DAY :{DECIMAL}{NBSP}tiles/day
STR_UNITS_VELOCITY_GAMEUNITS_SEC :{DECIMAL}{NBSP}tiles/sec
STR_UNITS_VELOCITY_KNOTS :{DECIMAL}{NBSP}knots
STR_UNITS_POWER_IMPERIAL :{DECIMAL}{NBSP}hp
@ -255,10 +256,17 @@ STR_UNITS_HEIGHT_IMPERIAL :{DECIMAL}{NBSP}
STR_UNITS_HEIGHT_METRIC :{DECIMAL}{NBSP}m
STR_UNITS_HEIGHT_SI :{DECIMAL}{NBSP}m
# Time units used in string control characters
STR_UNITS_DAYS :{COMMA}{NBSP}day{P "" s}
STR_UNITS_SECONDS :{COMMA}{NBSP}second{P "" s}
STR_UNITS_TICKS :{COMMA}{NBSP}tick{P "" s}
STR_UNITS_MONTHS :{NUM}{NBSP}month{P "" s}
STR_UNITS_MINUTES :{NUM}{NBSP}minute{P "" s}
STR_UNITS_YEARS :{NUM}{NBSP}year{P "" s}
STR_UNITS_PERIODS :{NUM}{NBSP}period{P "" s}
# Common window strings
STR_LIST_FILTER_TITLE :{BLACK}Filter:
STR_LIST_FILTER_OSKTITLE :{BLACK}Enter one or more keywords to filter the list for
@ -323,8 +331,8 @@ STR_SORT_BY_PRODUCTION :Production
STR_SORT_BY_TYPE :Type
STR_SORT_BY_TRANSPORTED :Transported
STR_SORT_BY_NUMBER :Number
STR_SORT_BY_PROFIT_LAST_YEAR :Profit last year
STR_SORT_BY_PROFIT_THIS_YEAR :Profit this year
STR_SORT_BY_PROFIT_LAST_YEAR :Profit last {TKM year period}
STR_SORT_BY_PROFIT_THIS_YEAR :Profit this {TKM year period}
STR_SORT_BY_AGE :Age
STR_SORT_BY_RELIABILITY :Reliability
STR_SORT_BY_TOTAL_CAPACITY_PER_CARGOTYPE :Total capacity per cargo type
@ -351,10 +359,10 @@ STR_SORT_BY_RANGE :Range
STR_SORT_BY_POPULATION :Population
STR_SORT_BY_RATING :Rating
STR_SORT_BY_NUM_VEHICLES :Number of vehicles
STR_SORT_BY_TOTAL_PROFIT_LAST_YEAR :Total profit last year
STR_SORT_BY_TOTAL_PROFIT_THIS_YEAR :Total profit this year
STR_SORT_BY_AVERAGE_PROFIT_LAST_YEAR :Average profit last year
STR_SORT_BY_AVERAGE_PROFIT_THIS_YEAR :Average profit this year
STR_SORT_BY_TOTAL_PROFIT_LAST_YEAR :Total profit last {TKM year period}
STR_SORT_BY_TOTAL_PROFIT_THIS_YEAR :Total profit this {TKM year period}
STR_SORT_BY_AVERAGE_PROFIT_LAST_YEAR :Average profit last {TKM year period}
STR_SORT_BY_AVERAGE_PROFIT_THIS_YEAR :Average profit this {TKM year period}
# Group by options for vehicle list
STR_GROUP_BY_NONE :None
@ -615,8 +623,10 @@ STR_GRAPH_CARGO_DELIVERED_CAPTION :{WHITE}Units of
STR_GRAPH_COMPANY_PERFORMANCE_RATINGS_CAPTION :{WHITE}Company performance ratings (maximum rating=1000)
STR_GRAPH_COMPANY_VALUES_CAPTION :{WHITE}Company Value Graph
STR_GRAPH_LAST_72_MINUTES_TIME_LABEL :{TINY_FONT}{BLACK}{TKM "" "Last 72 minutes"}
STR_GRAPH_CARGO_PAYMENT_RATES_CAPTION :{WHITE}Cargo Payment Rates
STR_GRAPH_CARGO_PAYMENT_RATES_X_LABEL :{TINY_FONT}{BLACK}Days in transit
STR_GRAPH_CARGO_PAYMENT_RATES_TIME_LABEL :{TINY_FONT}{BLACK}{TKM Days Seconds} in transit
STR_GRAPH_CARGO_PAYMENT_RATES_TITLE :{TINY_FONT}{BLACK}Payment for delivering 10 units (or 10,000 litres) of cargo a distance of 20 squares
STR_GRAPH_CARGO_ENABLE_ALL :{TINY_FONT}{BLACK}Enable all
STR_GRAPH_CARGO_DISABLE_ALL :{TINY_FONT}{BLACK}Disable all
@ -665,9 +675,9 @@ STR_PERFORMANCE_DETAIL_LOAN :{BLACK}Loan:
STR_PERFORMANCE_DETAIL_TOTAL :{BLACK}Total:
###length 10
STR_PERFORMANCE_DETAIL_VEHICLES_TOOLTIP :{BLACK}Number of vehicles that turned a profit last year. This includes road vehicles, trains, ships and aircraft
STR_PERFORMANCE_DETAIL_VEHICLES_TOOLTIP :{BLACK}Number of vehicles that turned a profit last {TKM year period}. This includes road vehicles, trains, ships and aircraft
STR_PERFORMANCE_DETAIL_STATIONS_TOOLTIP :{BLACK}Number of recently-serviced stations. Train stations, bus stops, airports and so on are counted separately even if they belong to the same station
STR_PERFORMANCE_DETAIL_MIN_PROFIT_TOOLTIP :{BLACK}The profit of the vehicle with the lowest income (only vehicles older than two years are considered)
STR_PERFORMANCE_DETAIL_MIN_PROFIT_TOOLTIP :{BLACK}The profit of the vehicle with the lowest income (only vehicles older than two {TKM years periods} are considered)
STR_PERFORMANCE_DETAIL_MIN_INCOME_TOOLTIP :{BLACK}Amount of cash made in the quarter with the lowest profit of the last 12 quarters
STR_PERFORMANCE_DETAIL_MAX_INCOME_TOOLTIP :{BLACK}Amount of cash made in the quarter with the highest profit of the last 12 quarters
STR_PERFORMANCE_DETAIL_DELIVERED_TOOLTIP :{BLACK}Units of cargo delivered in the last four quarters
@ -899,7 +909,7 @@ STR_NEWS_VEHICLE_IS_GETTING_VERY_OLD :{WHITE}{VEHICLE
STR_NEWS_VEHICLE_IS_GETTING_VERY_OLD_AND :{WHITE}{VEHICLE} is getting very old and urgently needs replacing
STR_NEWS_TRAIN_IS_STUCK :{WHITE}{VEHICLE} can't find a path to continue
STR_NEWS_VEHICLE_IS_LOST :{WHITE}{VEHICLE} is lost
STR_NEWS_VEHICLE_IS_UNPROFITABLE :{WHITE}{VEHICLE}'s profit last year was {CURRENCY_LONG}
STR_NEWS_VEHICLE_IS_UNPROFITABLE :{WHITE}{VEHICLE}'s profit last {TKM year period} was {CURRENCY_LONG}
STR_NEWS_AIRCRAFT_DEST_TOO_FAR :{WHITE}{VEHICLE} can't get to the next destination because it is out of range
STR_NEWS_ORDER_REFIT_FAILED :{WHITE}{VEHICLE} stopped because an ordered refit failed
@ -916,16 +926,16 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_LIST :{WHITE}{STATION
STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Offer of subsidy expired:{}{}{STRING} from {STRING2} to {STRING2} will now not attract a subsidy
STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Subsidy withdrawn:{}{}{STRING} service from {STRING2} to {STRING2} is no longer subsidised
STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Service subsidy offered:{}{}First {STRING} from {STRING2} to {STRING2} will attract a {NUM} year subsidy from the local authority!
STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Service subsidy offered:{}{}First {STRING} from {STRING2} to {STRING2} will attract a {UNITS_YEARS_OR_MINUTES} subsidy from the local authority!
###length 4
STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}Service subsidy awarded to {RAW_STRING}!{}{}{STRING} from {STRING2} to {STRING2} will pay 50% extra for the next {NUM} year{P "" s}!
STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}Service subsidy awarded to {RAW_STRING}!{}{}{STRING} from {STRING2} to {STRING2} will pay double rates for the next {NUM} year{P "" s}!
STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}Service subsidy awarded to {RAW_STRING}!{}{}{STRING} from {STRING2} to {STRING2} will pay triple rates for the next {NUM} year{P "" s}!
STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}Service subsidy awarded to {RAW_STRING}!{}{}{STRING} from {STRING2} to {STRING2} will pay quadruple rates for the next {NUM} year{P "" s}!
STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}Service subsidy awarded to {RAW_STRING}!{}{}{STRING} from {STRING2} to {STRING2} will pay 50% extra for the next {UNITS_YEARS_OR_MINUTES}!
STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}Service subsidy awarded to {RAW_STRING}!{}{}{STRING} from {STRING2} to {STRING2} will pay double rates for the next {UNITS_YEARS_OR_MINUTES}!
STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}Service subsidy awarded to {RAW_STRING}!{}{}{STRING} from {STRING2} to {STRING2} will pay triple rates for the next {UNITS_YEARS_OR_MINUTES}!
STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}Service subsidy awarded to {RAW_STRING}!{}{}{STRING} from {STRING2} to {STRING2} will pay quadruple rates for the next {UNITS_YEARS_OR_MINUTES}!
STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}Traffic chaos in {TOWN}!{}{}Road rebuilding programme funded by {RAW_STRING} brings 6 months of misery to motorists!
STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}Traffic chaos in {TOWN}!{}{}Road rebuilding programme funded by {RAW_STRING} brings 6 {TKM months minutes} of misery to motorists!
STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}Transport monopoly!
STR_NEWS_EXCLUSIVE_RIGHTS_DESCRIPTION :{BIG_FONT}{BLACK}Local authority of {TOWN} signs contract with {RAW_STRING} for one year of exclusive transport rights!
STR_NEWS_EXCLUSIVE_RIGHTS_DESCRIPTION :{BIG_FONT}{BLACK}Local authority of {TOWN} signs contract with {RAW_STRING} for 12 {TKM months minutes} of exclusive transport rights!
# Extra view window
STR_EXTRA_VIEWPORT_TITLE :{WHITE}Viewport {COMMA}
@ -1286,9 +1296,9 @@ STR_CONFIG_SETTING_SUBSIDY_MULTIPLIER :Subsidy multipl
STR_CONFIG_SETTING_SUBSIDY_MULTIPLIER_HELPTEXT :Set how much is paid for subsidised connections
STR_CONFIG_SETTING_SUBSIDY_DURATION :Subsidy duration: {STRING2}
STR_CONFIG_SETTING_SUBSIDY_DURATION_HELPTEXT :Set the number of years for which a subsidy is awarded
STR_CONFIG_SETTING_SUBSIDY_DURATION_HELPTEXT :Set the number of {TKM years periods} for which a subsidy is awarded
STR_CONFIG_SETTING_SUBSIDY_DURATION_VALUE :{NUM} year{P "" s}
STR_CONFIG_SETTING_SUBSIDY_DURATION_VALUE :{UNITS_YEARS_OR_PERIODS}
###setting-zero-is-special
STR_CONFIG_SETTING_SUBSIDY_DURATION_DISABLED :No subsidies
@ -1296,7 +1306,7 @@ STR_CONFIG_SETTING_CONSTRUCTION_COSTS :Construction co
STR_CONFIG_SETTING_CONSTRUCTION_COSTS_HELPTEXT :Set level of construction and purchase costs
STR_CONFIG_SETTING_RECESSIONS :Recessions: {STRING2}
STR_CONFIG_SETTING_RECESSIONS_HELPTEXT :If enabled, recessions may occur every few years. During a recession all production is significantly lower (it returns to previous level when the recession is over)
STR_CONFIG_SETTING_RECESSIONS_HELPTEXT :If enabled, recessions may occur periodically. During a recession all production is significantly lower (it returns to previous level when the recession is over)
STR_CONFIG_SETTING_TRAIN_REVERSING :Disallow train reversing in stations: {STRING2}
STR_CONFIG_SETTING_TRAIN_REVERSING_HELPTEXT :If enabled, trains will not reverse in non-terminus stations, even if there is a shorter path to their next destination when reversing
@ -1384,8 +1394,8 @@ STR_CONFIG_SETTING_SIGNALSIDE_LEFT :On the left
STR_CONFIG_SETTING_SIGNALSIDE_DRIVING_SIDE :On the driving side
STR_CONFIG_SETTING_SIGNALSIDE_RIGHT :On the right
STR_CONFIG_SETTING_SHOWFINANCES :Show finances window at the end of the year: {STRING2}
STR_CONFIG_SETTING_SHOWFINANCES_HELPTEXT :If enabled, the finances window pops up at the end of each year to allow easy inspection of the financial status of the company
STR_CONFIG_SETTING_SHOWFINANCES :Show finances window at the end of the {TKM year period}: {STRING2}
STR_CONFIG_SETTING_SHOWFINANCES_HELPTEXT :If enabled, the finances window pops up at the end of each {TKM year period} to allow easy inspection of the financial status of the company
STR_CONFIG_SETTING_NONSTOP_BY_DEFAULT :New orders are 'non-stop' by default: {STRING2}
STR_CONFIG_SETTING_NONSTOP_BY_DEFAULT_HELPTEXT :Normally, a vehicle will stop at every station it passes. By enabling this setting, it will drive through all station on the way to its final destination without stopping. Note, that this setting only defines a default value for new orders. Individual orders can be set explicitly to either behaviour nevertheless
@ -1406,10 +1416,10 @@ STR_CONFIG_SETTING_AUTOSCROLL_MAIN_VIEWPORT :Main viewport
STR_CONFIG_SETTING_AUTOSCROLL_EVERY_VIEWPORT :Every viewport
STR_CONFIG_SETTING_BRIBE :Allow bribing of the local authority: {STRING2}
STR_CONFIG_SETTING_BRIBE_HELPTEXT :Allow companies to try bribing the local town authority. If the bribe is noticed by an inspector, the company will not be able to act in the town for six months
STR_CONFIG_SETTING_BRIBE_HELPTEXT :Allow companies to try bribing the local town authority. If the bribe is noticed by an inspector, the company will not be able to act in the town for six {TKM months minutes}
STR_CONFIG_SETTING_ALLOW_EXCLUSIVE :Allow buying exclusive transport rights: {STRING2}
STR_CONFIG_SETTING_ALLOW_EXCLUSIVE_HELPTEXT :If a company buys exclusive transport rights for a town, opponents' stations (passenger and cargo) won't receive any cargo for a whole year
STR_CONFIG_SETTING_ALLOW_EXCLUSIVE_HELPTEXT :If a company buys exclusive transport rights for a town, opponents' stations (passenger and cargo) won't receive any cargo for twelve {TKM months minutes}
STR_CONFIG_SETTING_ALLOW_FUND_BUILDINGS :Allow funding buildings: {STRING2}
STR_CONFIG_SETTING_ALLOW_FUND_BUILDINGS_HELPTEXT :Allow companies to give money to towns for funding new houses
@ -1466,11 +1476,17 @@ STR_CONFIG_SETTING_ORDER_REVIEW_EXDEPOT :Yes, but exclud
STR_CONFIG_SETTING_ORDER_REVIEW_ON :Of all vehicles
STR_CONFIG_SETTING_WARN_INCOME_LESS :Warn if a vehicle's income is negative: {STRING2}
STR_CONFIG_SETTING_WARN_INCOME_LESS_HELPTEXT :When enabled, a news message gets sent when a vehicle has not made any profit within a calendar year
STR_CONFIG_SETTING_WARN_INCOME_LESS_HELPTEXT :When enabled, a news message gets sent when a vehicle has not made any profit within a {TKM year period}
STR_CONFIG_SETTING_NEVER_EXPIRE_VEHICLES :Vehicles never expire: {STRING2}
STR_CONFIG_SETTING_NEVER_EXPIRE_VEHICLES_HELPTEXT :When enabled, all vehicle models remain available forever after their introduction
STR_CONFIG_SETTING_TIMEKEEPING_UNITS :Timekeeping: {STRING2}
STR_CONFIG_SETTING_TIMEKEEPING_UNITS_HELPTEXT :Select the timekeeping units of the game. This cannot be changed later.{}{}Calendar-based is the classic OpenTTD experience, with a year consisting of 12 months, and each month having 28-31 days.{}{}In Wallclock-based time, vehicle movement, cargo production, and financials are instead based on one-minute increments, which is about as long as a 30 day month takes in Calendar-based mode. These are grouped into 12-minute periods, equivalent to a year in Calendar-based mode.{}{}In either mode there is always a classic calendar, which is used for introduction dates of vehicles, houses, and other infrastructure.
###length 2
STR_CONFIG_SETTING_TIMEKEEPING_UNITS_CALENDAR :Calendar
STR_CONFIG_SETTING_TIMEKEEPING_UNITS_WALLCLOCK :Wallclock
STR_CONFIG_SETTING_AUTORENEW_VEHICLE :Autorenew vehicle when it gets old: {STRING2}
STR_CONFIG_SETTING_AUTORENEW_VEHICLE_HELPTEXT :When enabled, a vehicle nearing its end of life gets automatically replaced when the renew conditions are fulfilled
@ -1723,8 +1739,8 @@ STR_CONFIG_SETTING_SOUND_TICKER_HELPTEXT :Play sound for
STR_CONFIG_SETTING_SOUND_NEWS :Newspaper: {STRING2}
STR_CONFIG_SETTING_SOUND_NEWS_HELPTEXT :Play sound upon display of newspapers
STR_CONFIG_SETTING_SOUND_NEW_YEAR :End of year: {STRING2}
STR_CONFIG_SETTING_SOUND_NEW_YEAR_HELPTEXT :Play sound at the end of a year summarising the company's performance during the year compared to the previous year
STR_CONFIG_SETTING_SOUND_NEW_YEAR :End of {TKM year period}: {STRING2}
STR_CONFIG_SETTING_SOUND_NEW_YEAR_HELPTEXT :Play sound at the end of a {TKM year period} summarising the company's performance during the {TKM year period} compared to the previous {TKM year period}
STR_CONFIG_SETTING_SOUND_CONFIRM :Construction: {STRING2}
STR_CONFIG_SETTING_SOUND_CONFIRM_HELPTEXT :Play sound on successful constructions or other actions
@ -1792,7 +1808,7 @@ STR_CONFIG_SETTING_SERVINT_AIRCRAFT :Default service
STR_CONFIG_SETTING_SERVINT_AIRCRAFT_HELPTEXT :Set the default service interval for new aircraft, if no explicit service interval is set for the vehicle
STR_CONFIG_SETTING_SERVINT_SHIPS :Default service interval for ships: {STRING2}
STR_CONFIG_SETTING_SERVINT_SHIPS_HELPTEXT :Set the default service interval for new ships, if no explicit service interval is set for the vehicle
STR_CONFIG_SETTING_SERVINT_VALUE :{COMMA}{NBSP}day{P 0 "" s}/%
STR_CONFIG_SETTING_SERVINT_VALUE :{COMMA}{NBSP}Day{P 0 "" s}/Minute{P 0 "" s}/%
###setting-zero-is-special
STR_CONFIG_SETTING_SERVINT_DISABLED :Disabled
@ -2026,7 +2042,7 @@ STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_HELPTEXT :Whenever a spee
STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_IMPERIAL :Imperial (mph)
STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_METRIC :Metric (km/h)
STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_SI :SI (m/s)
STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_GAMEUNITS :Game units (tiles/day)
STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_GAMEUNITS :Game units ({TKM "tiles/day" "tiles/sec"})
STR_CONFIG_SETTING_LOCALISATION_UNITS_VELOCITY_KNOTS :Knots
STR_CONFIG_SETTING_LOCALISATION_UNITS_POWER :Vehicle power units: {STRING2}
@ -2712,9 +2728,9 @@ STR_LINKGRAPH_LEGEND_SATURATED :{TINY_FONT}{BLA
STR_LINKGRAPH_LEGEND_OVERLOADED :{TINY_FONT}{BLACK}overloaded
# Linkgraph tooltip
STR_LINKGRAPH_STATS_TOOLTIP :{BLACK}{CARGO_LONG} to be transported per month from {STATION} to {STATION} ({COMMA}% of capacity){RAW_STRING}
STR_LINKGRAPH_STATS_TOOLTIP :{BLACK}{CARGO_LONG} to be transported per {TKM month minute} from {STATION} to {STATION} ({COMMA}% of capacity){RAW_STRING}
STR_LINKGRAPH_STATS_TOOLTIP_RETURN_EXTENSION :{}{CARGO_LONG} to be transported back ({COMMA}% of capacity)
STR_LINKGRAPH_STATS_TOOLTIP_TIME_EXTENSION :{}Average travel time: {NUM}{NBSP}day{P "" s}
STR_LINKGRAPH_STATS_TOOLTIP_TIME_EXTENSION :{}Average travel time: {UNITS_DAYS_OR_SECONDS}
# Base for station construction window(s)
STR_STATION_BUILD_COVERAGE_AREA_TITLE :{BLACK}Coverage area highlight
@ -2724,7 +2740,7 @@ STR_STATION_BUILD_COVERAGE_AREA_OFF_TOOLTIP :{BLACK}Don't hi
STR_STATION_BUILD_COVERAGE_AREA_ON_TOOLTIP :{BLACK}Highlight coverage area of proposed site
STR_STATION_BUILD_ACCEPTS_CARGO :{BLACK}Accepts: {GOLD}{CARGO_LIST}
STR_STATION_BUILD_SUPPLIES_CARGO :{BLACK}Supplies: {GOLD}{CARGO_LIST}
STR_STATION_BUILD_INFRASTRUCTURE_COST :{BLACK}Maintenance cost: {GOLD}{CURRENCY_SHORT}/yr
STR_STATION_BUILD_INFRASTRUCTURE_COST :{BLACK}Maintenance cost: {GOLD}{CURRENCY_SHORT}/{TKM year period}
# Join station window
STR_JOIN_STATION_CAPTION :{WHITE}Join station
@ -3571,15 +3587,15 @@ STR_TOWN_POPULATION :{BLACK}World po
STR_TOWN_VIEW_TOWN_CAPTION :{WHITE}{TOWN}
STR_TOWN_VIEW_CITY_CAPTION :{WHITE}{TOWN} (City)
STR_TOWN_VIEW_POPULATION_HOUSES :{BLACK}Population: {ORANGE}{COMMA}{BLACK} Houses: {ORANGE}{COMMA}
STR_TOWN_VIEW_CARGO_LAST_MONTH_MAX :{BLACK}{CARGO_LIST} last month: {ORANGE}{COMMA}{BLACK} max: {ORANGE}{COMMA}
STR_TOWN_VIEW_CARGO_LAST_MONTH_MAX :{BLACK}{CARGO_LIST} last {TKM month minute}: {ORANGE}{COMMA}{BLACK} max: {ORANGE}{COMMA}
STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH :{BLACK}Cargo needed for town growth:
STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_GENERAL :{ORANGE}{STRING}{RED} required
STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED_WINTER :{ORANGE}{STRING}{BLACK} required in winter
STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_DELIVERED_GENERAL :{ORANGE}{STRING}{GREEN} delivered
STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_REQUIRED :{ORANGE}{CARGO_TINY} / {CARGO_LONG}{RED} (still required)
STR_TOWN_VIEW_CARGO_FOR_TOWNGROWTH_DELIVERED :{ORANGE}{CARGO_TINY} / {CARGO_LONG}{GREEN} (delivered)
STR_TOWN_VIEW_TOWN_GROWS_EVERY :{BLACK}Town grows every {ORANGE}{COMMA}{BLACK}{NBSP}day{P "" s}
STR_TOWN_VIEW_TOWN_GROWS_EVERY_FUNDED :{BLACK}Town grows every {ORANGE}{COMMA}{BLACK}{NBSP}day{P "" s} (funded)
STR_TOWN_VIEW_TOWN_GROWS_EVERY :{BLACK}Town grows every {ORANGE}{UNITS_DAYS_OR_SECONDS}
STR_TOWN_VIEW_TOWN_GROWS_EVERY_FUNDED :{BLACK}Town grows every {ORANGE}{UNITS_DAYS_OR_SECONDS} (funded)
STR_TOWN_VIEW_TOWN_GROW_STOPPED :{BLACK}Town is {RED}not{BLACK} growing
STR_TOWN_VIEW_NOISE_IN_TOWN :{BLACK}Noise limit in town: {ORANGE}{COMMA}{BLACK} max: {ORANGE}{COMMA}
STR_TOWN_VIEW_CENTER_TOOLTIP :{BLACK}Centre the main view on town location. Ctrl+Click to open a new viewport on town location
@ -3619,10 +3635,10 @@ STR_LOCAL_AUTHORITY_ACTION_BRIBE :Bribe the local
STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_SMALL_ADVERTISING :{PUSH_COLOUR}{YELLOW}Initiate a small local advertising campaign, to attract more passengers and cargo to your transport services.{}Provides a temporary boost to station rating in a small radius around the town centre.{}{POP_COLOUR}Cost: {CURRENCY_LONG}
STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_MEDIUM_ADVERTISING :{PUSH_COLOUR}{YELLOW}Initiate a medium local advertising campaign, to attract more passengers and cargo to your transport services.{}Provides a temporary boost to station rating in a medium radius around the town centre.{}{POP_COLOUR}Cost: {CURRENCY_LONG}
STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_LARGE_ADVERTISING :{PUSH_COLOUR}{YELLOW}Initiate a large local advertising campaign, to attract more passengers and cargo to your transport services.{}Provides a temporary boost to station rating in a large radius around the town centre.{}{POP_COLOUR}Cost: {CURRENCY_LONG}
STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_ROAD_RECONSTRUCTION :{PUSH_COLOUR}{YELLOW}Fund the reconstruction of the urban road network.{}Causes considerable disruption to road traffic for up to 6 months.{}{POP_COLOUR}Cost: {CURRENCY_LONG}
STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_ROAD_RECONSTRUCTION :{PUSH_COLOUR}{YELLOW}Fund the reconstruction of the urban road network.{}Causes considerable disruption to road traffic for up to 6 {TKM months minutes}.{}{POP_COLOUR}Cost: {CURRENCY_LONG}
STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_STATUE_OF_COMPANY :{PUSH_COLOUR}{YELLOW}Build a statue in honour of your company.{}Provides a permanent boost to station rating in this town.{}{POP_COLOUR}Cost: {CURRENCY_LONG}
STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_NEW_BUILDINGS :{PUSH_COLOUR}{YELLOW}Fund the construction of new buildings in the town.{}Provides a temporary boost to town growth in this town.{}{POP_COLOUR}Cost: {CURRENCY_LONG}
STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_EXCLUSIVE_TRANSPORT :{PUSH_COLOUR}{YELLOW}Buy 1 year's exclusive transport rights in town.{}Town authority will not allow passengers and cargo to use your competitors' stations. A successful bribe from a competitor will cancel this contract.{}{POP_COLOUR}Cost: {CURRENCY_LONG}
STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_EXCLUSIVE_TRANSPORT :{PUSH_COLOUR}{YELLOW}Buy exclusive transport rights in town for 12 {TKM months minutes}.{}Town authority will not allow passengers and cargo to use your competitors' stations. A successful bribe from a competitor will cancel this contract.{}{POP_COLOUR}Cost: {CURRENCY_LONG}
STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_BRIBE :{PUSH_COLOUR}{YELLOW}Bribe the local authority to increase your rating and abort a competitor's exclusive transport rights, at the risk of a severe penalty if caught.{}{POP_COLOUR}Cost: {CURRENCY_LONG}
# Goal window
@ -3669,11 +3685,15 @@ STR_GOAL_QUESTION_BUTTON_CLOSE :Close
# Subsidies window
STR_SUBSIDIES_CAPTION :{WHITE}Subsidies
STR_SUBSIDIES_OFFERED_TITLE :{BLACK}Subsidies on offer for services taking:
STR_SUBSIDIES_OFFERED_FROM_TO :{ORANGE}{STRING} from {STRING2} to {STRING2}{YELLOW} (by {DATE_SHORT})
STR_SUBSIDIES_OFFERED_FROM_TO :{ORANGE}{STRING} from {STRING2} to {STRING2}{YELLOW} ({STRING1})
STR_SUBSIDIES_NONE :{ORANGE}- None -
STR_SUBSIDIES_SUBSIDISED_TITLE :{BLACK}Services already subsidised:
STR_SUBSIDIES_SUBSIDISED_FROM_TO :{ORANGE}{STRING} from {STRING2} to {STRING2}{YELLOW} ({COMPANY}{YELLOW}, until {DATE_SHORT})
STR_SUBSIDIES_SUBSIDISED_FROM_TO :{ORANGE}{STRING} from {STRING2} to {STRING2}{YELLOW} ({COMPANY}{YELLOW}, {STRING1})
STR_SUBSIDIES_TOOLTIP_CLICK_ON_SERVICE_TO_CENTER :{BLACK}Click on service to centre main view on industry/town. Ctrl+Click to open a new viewport on industry/town location
STR_SUBSIDIES_OFFERED_EXPIRY_DATE :by {DATE_SHORT}
STR_SUBSIDIES_OFFERED_EXPIRY_TIME :within {UNITS_MONTHS_OR_MINUTES}
STR_SUBSIDIES_SUBSIDISED_EXPIRY_DATE :until {DATE_SHORT}
STR_SUBSIDIES_SUBSIDISED_EXPIRY_TIME :{UNITS_MONTHS_OR_MINUTES} remaining
# Story book window
STR_STORY_BOOK_CAPTION :{WHITE}{COMPANY} Story Book
@ -3713,7 +3733,7 @@ STR_STATION_VIEW_EXCLUSIVE_RIGHTS_COMPANY :{YELLOW}{COMPAN
STR_STATION_VIEW_RATINGS_BUTTON :{BLACK}Ratings
STR_STATION_VIEW_RATINGS_TOOLTIP :{BLACK}Show station ratings
STR_STATION_VIEW_SUPPLY_RATINGS_TITLE :{BLACK}Monthly supply and local rating:
STR_STATION_VIEW_SUPPLY_RATINGS_TITLE :{BLACK}Supply per {TKM month minute} and local rating:
STR_STATION_VIEW_CARGO_SUPPLY_RATING :{WHITE}{STRING}: {YELLOW}{COMMA} / {STRING} ({COMMA}%)
STR_STATION_VIEW_GROUP :{BLACK}Group by
@ -3774,6 +3794,7 @@ STR_EDIT_WAYPOINT_NAME :{WHITE}Edit way
# Finances window
STR_FINANCES_CAPTION :{WHITE}{COMPANY} Finances {BLACK}{COMPANY_NUM}
STR_FINANCES_YEAR :{WHITE}{NUM}
STR_FINANCES_YEAR_CAPTION :{WHITE}{TKM Year Period}
###length 3
STR_FINANCES_REVENUE_TITLE :{WHITE}Revenue
@ -3875,7 +3896,7 @@ STR_COMPANY_INFRASTRUCTURE_VIEW_CANALS :{WHITE}Canals
STR_COMPANY_INFRASTRUCTURE_VIEW_STATION_SECT :{GOLD}Stations:
STR_COMPANY_INFRASTRUCTURE_VIEW_STATIONS :{WHITE}Station tiles
STR_COMPANY_INFRASTRUCTURE_VIEW_AIRPORTS :{WHITE}Airports
STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL :{WHITE}{CURRENCY_LONG}/yr
STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL :{WHITE}{CURRENCY_LONG}/{TKM year period}
# Industry directory
STR_INDUSTRY_DIRECTORY_CAPTION :{WHITE}Industries
@ -3894,7 +3915,7 @@ STR_INDUSTRY_DIRECTORY_FILTER_NONE :None
# Industry view
STR_INDUSTRY_VIEW_CAPTION :{WHITE}{INDUSTRY}
STR_INDUSTRY_VIEW_PRODUCTION_LAST_MONTH_TITLE :{BLACK}Production last month:
STR_INDUSTRY_VIEW_PRODUCTION_LAST_MONTH_TITLE :{BLACK}Production last {TKM month minute}:
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_PRODUCTION_LEVEL :{BLACK}Production level: {YELLOW}{COMMA}%
@ -3935,7 +3956,7 @@ STR_VEHICLE_LIST_MANAGE_LIST_TOOLTIP :{BLACK}Send ins
STR_VEHICLE_LIST_REPLACE_VEHICLES :Replace vehicles
STR_VEHICLE_LIST_SEND_FOR_SERVICING :Send for servicing
STR_VEHICLE_LIST_CREATE_GROUP :Create group
STR_VEHICLE_LIST_PROFIT_THIS_YEAR_LAST_YEAR :{TINY_FONT}{BLACK}Profit this year: {CURRENCY_LONG} (last year: {CURRENCY_LONG})
STR_VEHICLE_LIST_PROFIT_THIS_YEAR_LAST_YEAR :{TINY_FONT}{BLACK}Profit this {TKM year period}: {CURRENCY_LONG} (last {TKM year period}: {CURRENCY_LONG})
STR_VEHICLE_LIST_CARGO :[{CARGO_LIST}]
STR_VEHICLE_LIST_NAME_AND_CARGO :{STRING1} {STRING1}
@ -3980,8 +4001,8 @@ STR_GROUP_REMOVE_ALL_VEHICLES :Remove all vehi
STR_GROUP_RENAME_CAPTION :{BLACK}Rename a group
STR_GROUP_PROFIT_THIS_YEAR :Profit this year:
STR_GROUP_PROFIT_LAST_YEAR :Profit last year:
STR_GROUP_PROFIT_THIS_YEAR :Profit this {TKM year period}:
STR_GROUP_PROFIT_LAST_YEAR :Profit last {TKM year period}:
STR_GROUP_OCCUPANCY :Current usage:
STR_GROUP_OCCUPANCY_VALUE :{NUM}%
@ -4008,7 +4029,7 @@ STR_PURCHASE_INFO_SPEED_POWER :{BLACK}Speed: {
STR_PURCHASE_INFO_SPEED :{BLACK}Speed: {GOLD}{VELOCITY}
STR_PURCHASE_INFO_SPEED_OCEAN :{BLACK}Speed on ocean: {GOLD}{VELOCITY}
STR_PURCHASE_INFO_SPEED_CANAL :{BLACK}Speed on canal/river: {GOLD}{VELOCITY}
STR_PURCHASE_INFO_RUNNINGCOST :{BLACK}Running Cost: {GOLD}{CURRENCY_LONG}/yr
STR_PURCHASE_INFO_RUNNINGCOST :{BLACK}Running Cost: {GOLD}{CURRENCY_LONG}/{TKM year period}
STR_PURCHASE_INFO_CAPACITY :{BLACK}Capacity: {GOLD}{CARGO_LONG} {STRING}
STR_PURCHASE_INFO_REFITTABLE :(refittable)
STR_PURCHASE_INFO_DESIGNED_LIFE :{BLACK}Designed: {GOLD}{NUM}{BLACK} Life: {GOLD}{COMMA} year{P "" s}
@ -4201,13 +4222,13 @@ STR_ENGINE_PREVIEW_TRAM_VEHICLE :tramway vehicle
STR_ENGINE_PREVIEW_AIRCRAFT :aircraft
STR_ENGINE_PREVIEW_SHIP :ship
STR_ENGINE_PREVIEW_COST_WEIGHT_SPEED_POWER :{BLACK}Cost: {CURRENCY_LONG} Weight: {WEIGHT_SHORT}{}Speed: {VELOCITY} Power: {POWER}{}Running Cost: {CURRENCY_LONG}/yr{}Capacity: {CARGO_LONG}
STR_ENGINE_PREVIEW_COST_WEIGHT_SPEED_POWER_MAX_TE :{BLACK}Cost: {0:CURRENCY_LONG} Weight: {1:WEIGHT_SHORT}{}Speed: {2:VELOCITY} Power: {3:POWER} Max. T.E.: {6:FORCE}{}Running Cost: {4:CURRENCY_LONG}/yr{}Capacity: {5:CARGO_LONG}
STR_ENGINE_PREVIEW_COST_MAX_SPEED_CAP_RUNCOST :{BLACK}Cost: {CURRENCY_LONG} Max. Speed: {VELOCITY}{}Capacity: {CARGO_LONG}{}Running Cost: {CURRENCY_LONG}/yr
STR_ENGINE_PREVIEW_COST_MAX_SPEED_TYPE_CAP_CAP_RUNCOST :{BLACK}Cost: {CURRENCY_LONG} Max. Speed: {VELOCITY}{}Aircraft type: {STRING}{}Capacity: {CARGO_LONG}, {CARGO_LONG}{}Running Cost: {CURRENCY_LONG}/yr
STR_ENGINE_PREVIEW_COST_MAX_SPEED_TYPE_CAP_RUNCOST :{BLACK}Cost: {CURRENCY_LONG} Max. Speed: {VELOCITY}{}Aircraft type: {STRING}{}Capacity: {CARGO_LONG}{}Running Cost: {CURRENCY_LONG}/yr
STR_ENGINE_PREVIEW_COST_MAX_SPEED_TYPE_RANGE_CAP_CAP_RUNCOST :{BLACK}Cost: {CURRENCY_LONG} Max. Speed: {VELOCITY}{}Aircraft type: {STRING} Range: {COMMA} tiles{}Capacity: {CARGO_LONG}, {CARGO_LONG}{}Running Cost: {CURRENCY_LONG}/yr
STR_ENGINE_PREVIEW_COST_MAX_SPEED_TYPE_RANGE_CAP_RUNCOST :{BLACK}Cost: {CURRENCY_LONG} Max. Speed: {VELOCITY}{}Aircraft type: {STRING} Range: {COMMA} tiles{}Capacity: {CARGO_LONG}{}Running Cost: {CURRENCY_LONG}/yr
STR_ENGINE_PREVIEW_COST_WEIGHT_SPEED_POWER :{BLACK}Cost: {CURRENCY_LONG} Weight: {WEIGHT_SHORT}{}Speed: {VELOCITY} Power: {POWER}{}Running Cost: {CURRENCY_LONG}/{TKM year period}{}Capacity: {CARGO_LONG}
STR_ENGINE_PREVIEW_COST_WEIGHT_SPEED_POWER_MAX_TE :{BLACK}Cost: {0:CURRENCY_LONG} Weight: {1:WEIGHT_SHORT}{}Speed: {2:VELOCITY} Power: {3:POWER} Max. T.E.: {6:FORCE}{}Running Cost: {4:CURRENCY_LONG}/{TKM year period}{}Capacity: {5:CARGO_LONG}
STR_ENGINE_PREVIEW_COST_MAX_SPEED_CAP_RUNCOST :{BLACK}Cost: {CURRENCY_LONG} Max. Speed: {VELOCITY}{}Capacity: {CARGO_LONG}{}Running Cost: {CURRENCY_LONG}/{TKM year period}
STR_ENGINE_PREVIEW_COST_MAX_SPEED_TYPE_CAP_CAP_RUNCOST :{BLACK}Cost: {CURRENCY_LONG} Max. Speed: {VELOCITY}{}Aircraft type: {STRING}{}Capacity: {CARGO_LONG}, {CARGO_LONG}{}Running Cost: {CURRENCY_LONG}/{TKM year period}
STR_ENGINE_PREVIEW_COST_MAX_SPEED_TYPE_CAP_RUNCOST :{BLACK}Cost: {CURRENCY_LONG} Max. Speed: {VELOCITY}{}Aircraft type: {STRING}{}Capacity: {CARGO_LONG}{}Running Cost: {CURRENCY_LONG}/{TKM year period}
STR_ENGINE_PREVIEW_COST_MAX_SPEED_TYPE_RANGE_CAP_CAP_RUNCOST :{BLACK}Cost: {CURRENCY_LONG} Max. Speed: {VELOCITY}{}Aircraft type: {STRING} Range: {COMMA} tiles{}Capacity: {CARGO_LONG}, {CARGO_LONG}{}Running Cost: {CURRENCY_LONG}/{TKM year period}
STR_ENGINE_PREVIEW_COST_MAX_SPEED_TYPE_RANGE_CAP_RUNCOST :{BLACK}Cost: {CURRENCY_LONG} Max. Speed: {VELOCITY}{}Aircraft type: {STRING} Range: {COMMA} tiles{}Capacity: {CARGO_LONG}{}Running Cost: {CURRENCY_LONG}/{TKM year period}
# Autoreplace window
STR_REPLACE_VEHICLES_WHITE :{WHITE}Replace {STRING} - {STRING1}
@ -4350,9 +4371,9 @@ STR_VEHICLE_DETAILS_ROAD_VEHICLE_RENAME :{BLACK}Name roa
STR_VEHICLE_DETAILS_SHIP_RENAME :{BLACK}Name ship
STR_VEHICLE_DETAILS_AIRCRAFT_RENAME :{BLACK}Name aircraft
STR_VEHICLE_INFO_AGE_RUNNING_COST_YR :{BLACK}Age: {LTBLUE}{STRING2}{BLACK} Running Cost: {LTBLUE}{CURRENCY_LONG}/yr
STR_VEHICLE_INFO_AGE :{COMMA} year{P "" s} ({COMMA})
STR_VEHICLE_INFO_AGE_RED :{RED}{COMMA} year{P "" s} ({COMMA})
STR_VEHICLE_INFO_AGE_RUNNING_COST_YR :{BLACK}Age: {LTBLUE}{STRING2}{BLACK} Running Cost: {LTBLUE}{CURRENCY_LONG}/{TKM year period}
STR_VEHICLE_INFO_MAX_SPEED :{BLACK}Max. speed: {LTBLUE}{VELOCITY}
STR_VEHICLE_INFO_MAX_SPEED_TYPE :{BLACK}Max. speed: {LTBLUE}{VELOCITY} {BLACK}Aircraft type: {LTBLUE}{STRING}
@ -4360,8 +4381,8 @@ STR_VEHICLE_INFO_MAX_SPEED_TYPE_RANGE :{BLACK}Max. spe
STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED :{BLACK}Weight: {LTBLUE}{WEIGHT_SHORT} {BLACK}Power: {LTBLUE}{POWER}{BLACK} Max. speed: {LTBLUE}{VELOCITY}
STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED_MAX_TE :{BLACK}Weight: {LTBLUE}{WEIGHT_SHORT} {BLACK}Power: {LTBLUE}{POWER}{BLACK} Max. speed: {LTBLUE}{VELOCITY} {BLACK}Max. T.E.: {LTBLUE}{FORCE}
STR_VEHICLE_INFO_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Profit this year: {LTBLUE}{CURRENCY_LONG} (last year: {CURRENCY_LONG})
STR_VEHICLE_INFO_PROFIT_THIS_YEAR_LAST_YEAR_MIN_PERFORMANCE :{BLACK}Profit this year: {LTBLUE}{CURRENCY_LONG} (last year: {CURRENCY_LONG}) {BLACK}Min. performance: {LTBLUE}{POWER_TO_WEIGHT}
STR_VEHICLE_INFO_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Profit this {TKM year period}: {LTBLUE}{CURRENCY_LONG} (last {TKM year period}: {CURRENCY_LONG})
STR_VEHICLE_INFO_PROFIT_THIS_YEAR_LAST_YEAR_MIN_PERFORMANCE :{BLACK}Profit this {TKM year period}: {LTBLUE}{CURRENCY_LONG} (last {TKM year period}: {CURRENCY_LONG}) {BLACK}Min. performance: {LTBLUE}{POWER_TO_WEIGHT}
STR_VEHICLE_INFO_RELIABILITY_BREAKDOWNS :{BLACK}Reliability: {LTBLUE}{COMMA}% {BLACK}Breakdowns since last service: {LTBLUE}{COMMA}
STR_VEHICLE_INFO_BUILT_VALUE :{LTBLUE}{ENGINE} {BLACK}Built: {LTBLUE}{NUM}{BLACK} Value: {LTBLUE}{CURRENCY_LONG}
@ -4372,14 +4393,17 @@ STR_VEHICLE_INFO_CAPACITY_CAPACITY :{BLACK}Capacity
STR_VEHICLE_INFO_FEEDER_CARGO_VALUE :{BLACK}Transfer Credits: {LTBLUE}{CURRENCY_LONG}
STR_VEHICLE_DETAILS_SERVICING_INTERVAL_DAYS :{BLACK}Servicing interval: {LTBLUE}{COMMA}{NBSP}days{BLACK} Last service: {LTBLUE}{DATE_LONG}
STR_VEHICLE_DETAILS_SERVICING_INTERVAL_PERCENT :{BLACK}Servicing interval: {LTBLUE}{COMMA}%{BLACK} Last service: {LTBLUE}{DATE_LONG}
STR_VEHICLE_DETAILS_INCREASE_SERVICING_INTERVAL_TOOLTIP :{BLACK}Increase servicing interval by 10. Ctrl+Click to increase servicing interval by 5
STR_VEHICLE_DETAILS_DECREASE_SERVICING_INTERVAL_TOOLTIP :{BLACK}Decrease servicing interval by 10. Ctrl+Click to decrease servicing interval by 5
STR_VEHICLE_DETAILS_SERVICING_INTERVAL_DAYS :{BLACK}Servicing interval: {LTBLUE}{COMMA}{NBSP}days{BLACK} {STRING1}
STR_VEHICLE_DETAILS_SERVICING_INTERVAL_MINUTES :{BLACK}Servicing interval: {LTBLUE}{COMMA}{NBSP}minutes{BLACK} {STRING1}
STR_VEHICLE_DETAILS_SERVICING_INTERVAL_PERCENT :{BLACK}Servicing interval: {LTBLUE}{COMMA}%{BLACK} {STRING1}
STR_VEHICLE_DETAILS_LAST_SERVICE_DATE :Last service: {LTBLUE}{DATE_LONG}
STR_VEHICLE_DETAILS_LAST_SERVICE_MINUTES_AGO :Last service: {LTBLUE}{NUM} minutes ago
STR_VEHICLE_DETAILS_INCREASE_SERVICING_INTERVAL_TOOLTIP :{BLACK}Increase servicing interval by {TKM 10 5}. Ctrl+Click to increase servicing interval by {TKM 5 1}
STR_VEHICLE_DETAILS_DECREASE_SERVICING_INTERVAL_TOOLTIP :{BLACK}Decrease servicing interval by {TKM 10 5}. Ctrl+Click to decrease servicing interval by {TKM 5 1}
STR_SERVICE_INTERVAL_DROPDOWN_TOOLTIP :{BLACK}Change servicing interval type
STR_VEHICLE_DETAILS_DEFAULT :Default
STR_VEHICLE_DETAILS_DAYS :Days
STR_VEHICLE_DETAILS_TIME :{TKM Days Minutes}
STR_VEHICLE_DETAILS_PERCENT :Percentage
###length VEHICLE_TYPES

View File

@ -112,8 +112,14 @@ void InitializeGame(uint size_x, uint size_y, bool reset_date, bool reset_settin
if (reset_date) {
TimerGameCalendar::Date new_date = TimerGameCalendar::ConvertYMDToDate(_settings_game.game_creation.starting_year, 0, 1);
TimerGameCalendar::SetDate(new_date, 0);
/* Keep the economy date synced with the calendar date. */
TimerGameEconomy::SetDate(new_date.base(), 0);
if (TimerGameEconomy::UsingWallclockUnits()) {
/* If using wallclock units, start at year 1. */
TimerGameEconomy::SetDate(TimerGameEconomy::ConvertYMDToDate(1, 0, 1), 0);
} else {
/* Otherwise, we always keep the economy date synced with the calendar date. */
TimerGameEconomy::SetDate(new_date.base(), 0);
}
InitializeOldNames();
}

View File

@ -1845,13 +1845,21 @@ void DeleteVehicleOrders(Vehicle *v, bool keep_orderlist, bool reset_order_indic
/**
* Clamp the service interval to the correct min/max. The actual min/max values
* depend on whether it's in percent or days.
* @param interval proposed service interval
* @return Clamped service interval
* depend on whether it's in days, minutes, or percent.
* @param interval The proposed service interval.
* @param ispercent Whether the interval is a percent.
* @return The service interval clamped to use the chosen units.
*/
uint16_t GetServiceIntervalClamped(int interval, bool ispercent)
{
return ispercent ? Clamp(interval, MIN_SERVINT_PERCENT, MAX_SERVINT_PERCENT) : Clamp(interval, MIN_SERVINT_DAYS, MAX_SERVINT_DAYS);
/* Service intervals are in percents. */
if (ispercent) return Clamp(interval, MIN_SERVINT_PERCENT, MAX_SERVINT_PERCENT);
/* Service intervals are in minutes. */
if (TimerGameEconomy::UsingWallclockUnits(_game_mode == GM_MENU)) return Clamp(interval, MIN_SERVINT_MINUTES, MAX_SERVINT_MINUTES);
/* Service intervals are in days. */
return Clamp(interval, MIN_SERVINT_DAYS, MAX_SERVINT_DAYS);
}
/**

View File

@ -33,6 +33,13 @@ static const uint DEF_SERVINT_DAYS_SHIPS = 360;
static const uint MIN_SERVINT_DAYS = 30;
static const uint MAX_SERVINT_DAYS = 800;
static const uint DEF_SERVINT_MINUTES_TRAINS = 5;
static const uint DEF_SERVINT_MINUTES_ROADVEH = 5;
static const uint DEF_SERVINT_MINUTES_AIRCRAFT = 3;
static const uint DEF_SERVINT_MINUTES_SHIPS = 12;
static const uint MIN_SERVINT_MINUTES = 1;
static const uint MAX_SERVINT_MINUTES = 30;
static const uint DEF_SERVINT_PERCENT = 50;
static const uint MIN_SERVINT_PERCENT = 5;
static const uint MAX_SERVINT_PERCENT = 90;

View File

@ -735,6 +735,9 @@ bool AfterLoadGame()
* must be done before loading sprites as some newgrfs check it */
TimerGameCalendar::SetDate(TimerGameCalendar::date, TimerGameCalendar::date_fract);
/* Only new games can use wallclock units. */
if (IsSavegameVersionBefore(SLV_ECONOMY_MODE_TIMEKEEPING_UNITS)) _settings_game.economy.timekeeping_units = TKU_CALENDAR;
/* Update economy year. If we don't have a separate economy date saved, follow the calendar date. */
if (IsSavegameVersionBefore(SLV_ECONOMY_DATE)) {
TimerGameEconomy::SetDate(TimerGameCalendar::date.base(), TimerGameCalendar::date_fract);

View File

@ -369,6 +369,7 @@ enum SaveLoadVersion : uint16_t {
SLV_WATER_REGION_EVAL_SIMPLIFIED, ///< 325 PR#11750 Simplified Water Region evaluation.
SLV_ECONOMY_DATE, ///< 326 PR#10700 Split calendar and economy timers and dates.
SLV_ECONOMY_MODE_TIMEKEEPING_UNITS, ///< 327 PR#11341 Mode to display economy measurements in wallclock units.
SL_MAX_VERSION, ///< Highest possible saveload version
};

View File

@ -2212,6 +2212,7 @@ static SettingsContainer &GetSettingsTree()
{
SettingsPage *time = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_TIME));
{
time->Add(new SettingEntry("economy.timekeeping_units"));
time->Add(new SettingEntry("game_creation.ending_year"));
time->Add(new SettingEntry("gui.pause_on_newgame"));
time->Add(new SettingEntry("gui.fast_forward_speed_limit"));

View File

@ -130,7 +130,7 @@ static void UpdateConsists(int32_t)
/**
* Check and update if needed all vehicle service intervals.
* @param new_value Contains 0 if service intervals are in days, otherwise intervals use percents.
* @param new_value Contains 0 if service intervals are in time (days or real-world minutes), otherwise intervals use percents.
*/
static void UpdateAllServiceInterval(int32_t new_value)
{
@ -150,6 +150,12 @@ static void UpdateAllServiceInterval(int32_t new_value)
vds->servint_roadveh = DEF_SERVINT_PERCENT;
vds->servint_aircraft = DEF_SERVINT_PERCENT;
vds->servint_ships = DEF_SERVINT_PERCENT;
} else if (TimerGameEconomy::UsingWallclockUnits(_game_mode == GM_MENU)) {
/* Service intervals are in minutes. */
vds->servint_trains = DEF_SERVINT_MINUTES_TRAINS;
vds->servint_roadveh = DEF_SERVINT_MINUTES_ROADVEH;
vds->servint_aircraft = DEF_SERVINT_MINUTES_AIRCRAFT;
vds->servint_ships = DEF_SERVINT_MINUTES_SHIPS;
} else {
/* Service intervals are in days. */
vds->servint_trains = DEF_SERVINT_DAYS_TRAINS;
@ -483,4 +489,28 @@ static void UpdateClientConfigValues()
}
}
/**
* Callback for when the player changes the timekeeping units.
* @param Unused.
*/
static void ChangeTimekeepingUnits(int32_t)
{
/* If service intervals are in time units (calendar days or real-world minutes), reset them to the correct defaults. */
if (!_settings_client.company.vehicle.servint_ispercent) {
UpdateAllServiceInterval(0);
}
InvalidateWindowClassesData(WC_GAME_OPTIONS, 0);
}
/**
* Pre-callback check when trying to change the timetable mode. This is locked to Seconds when using wallclock units.
* @param Unused.
* @return True if we allow changing the timetable mode.
*/
static bool CanChangeTimetableMode(int32_t &)
{
return !TimerGameEconomy::UsingWallclockUnits();
}
/* End - Callback Functions */

View File

@ -64,6 +64,12 @@ enum IndustryDensity {
ID_END, ///< Number of industry density settings.
};
/** Possible values for the "timekeeping_units" setting. */
enum TimekeepingUnits : uint8_t {
TKU_CALENDAR = 0,
TKU_WALLCLOCK,
};
/** Possible values for "use_relay_service" setting. */
enum UseRelayService : uint8_t {
URS_NEVER = 0,
@ -551,6 +557,7 @@ struct EconomySettings {
uint16_t town_noise_population[4]; ///< population to base decision on noise evaluation (@see town_council_tolerance)
bool allow_town_level_crossings; ///< towns are allowed to build level crossings
bool infrastructure_maintenance; ///< enable monthly maintenance fee for owner infrastructure
TimekeepingUnits timekeeping_units; ///< time units to use for the game economy, either calendar or wallclock
};
struct LinkGraphSettings {

View File

@ -377,6 +377,33 @@ void EmitPlural(Buffer *buffer, char *buf, int)
EmitWordList(buffer, words, nw);
}
/**
* Handle the selection of timekeeping units based on the timekeeping setting.
* This uses the string control character {TKM [value if calendar] [value if wallclock]}, e.g. {TKM month minute}.
* @param buffer The output buffer
* @param buf The input buffer
* @param Unused
*/
void EmitTKM(Buffer* buffer, char* buf, int)
{
/* The correct number of words is 2, but we'll check for more in case of typos. */
std::vector<const char *> words(3, nullptr);
/* Parse each string. */
uint nw = 0;
for (nw = 0; nw < 3; nw++) {
words[nw] = ParseWord(&buf);
if (words[nw] == nullptr) break;
}
/* Warn about the wrong number of parameters. */
if (nw != 2) {
StrgenFatal("%s: Invalid number of TKM options. Expecting %d, found %d.", _cur_ident, 2, nw);
}
buffer->AppendUtf8(SCC_TIMEKEEPING_MODE_LIST);
EmitWordList(buffer, words, 2);
}
void EmitGender(Buffer *buffer, char *buf, int)
{

View File

@ -746,12 +746,21 @@ struct UnitsLong {
};
/** Unit conversions for velocity. */
static const Units _units_velocity[] = {
{ { 1.0 }, STR_UNITS_VELOCITY_IMPERIAL, 0 },
{ { 1.609344 }, STR_UNITS_VELOCITY_METRIC, 0 },
{ { 0.44704 }, STR_UNITS_VELOCITY_SI, 0 },
{ { 0.578125 }, STR_UNITS_VELOCITY_GAMEUNITS, 1 },
{ { 0.868976 }, STR_UNITS_VELOCITY_KNOTS, 0 },
static const Units _units_velocity_calendar[] = {
{ { 1.0 }, STR_UNITS_VELOCITY_IMPERIAL, 0 },
{ { 1.609344 }, STR_UNITS_VELOCITY_METRIC, 0 },
{ { 0.44704 }, STR_UNITS_VELOCITY_SI, 0 },
{ { 0.578125 }, STR_UNITS_VELOCITY_GAMEUNITS_DAY, 1 },
{ { 0.868976 }, STR_UNITS_VELOCITY_KNOTS, 0 },
};
/** Unit conversions for velocity. */
static const Units _units_velocity_realtime[] = {
{ { 1.0 }, STR_UNITS_VELOCITY_IMPERIAL, 0 },
{ { 1.609344 }, STR_UNITS_VELOCITY_METRIC, 0 },
{ { 0.44704 }, STR_UNITS_VELOCITY_SI, 0 },
{ { 0.289352 }, STR_UNITS_VELOCITY_GAMEUNITS_SEC, 1 },
{ { 0.868976 }, STR_UNITS_VELOCITY_KNOTS, 0 },
};
/** Unit conversions for power. */
@ -802,16 +811,45 @@ static const Units _units_height[] = {
{ { 1.0 }, STR_UNITS_HEIGHT_SI, 0 },
};
/**
* Get index for velocity conversion units for a vehicle type.
* @param type VehicleType to convert velocity for.
* @return Index within velocity conversion units for vehicle type.
*/
static byte GetVelocityUnits(VehicleType type)
{
if (type == VEH_SHIP || type == VEH_AIRCRAFT) return _settings_game.locale.units_velocity_nautical;
/** Unit conversions for time in calendar days or wallclock seconds */
static const Units _units_time_days_or_seconds[] = {
{ { 1 }, STR_UNITS_DAYS, 0 },
{ { 2 }, STR_UNITS_SECONDS, 0 },
};
return _settings_game.locale.units_velocity;
/** Unit conversions for time in calendar months or wallclock minutes */
static const Units _units_time_months_or_minutes[] = {
{ { 1 }, STR_UNITS_MONTHS, 0 },
{ { 1 }, STR_UNITS_MINUTES, 0 },
};
/** Unit conversions for time in calendar years or economic periods */
static const Units _units_time_years_or_periods[] = {
{ { 1 }, STR_UNITS_YEARS, 0 },
{ { 1 }, STR_UNITS_PERIODS, 0 },
};
/** Unit conversions for time in calendar years or wallclock minutes */
static const Units _units_time_years_or_minutes[] = {
{ { 1 }, STR_UNITS_YEARS, 0 },
{ { 12 }, STR_UNITS_MINUTES, 0 },
};
/**
* Get the correct velocity units depending on the vehicle type and whether we're using real-time units.
* @param type VehicleType to convert velocity for.
* @return The Units for the proper vehicle and time mode.
*/
static const Units GetVelocityUnits(VehicleType type)
{
byte setting = (type == VEH_SHIP || type == VEH_AIRCRAFT) ? _settings_game.locale.units_velocity_nautical : _settings_game.locale.units_velocity;
assert(setting < lengthof(_units_velocity_calendar));
assert(setting < lengthof(_units_velocity_realtime));
if (TimerGameEconomy::UsingWallclockUnits()) return _units_velocity_realtime[setting];
return _units_velocity_calendar[setting];
}
/**
@ -824,7 +862,7 @@ uint ConvertSpeedToDisplaySpeed(uint speed, VehicleType type)
/* For historical reasons we don't want to mess with the
* conversion for speed. So, don't round it and keep the
* original conversion factors instead of the real ones. */
return _units_velocity[GetVelocityUnits(type)].c.ToDisplay(speed, false);
return GetVelocityUnits(type).c.ToDisplay(speed, false);
}
/**
@ -834,7 +872,7 @@ uint ConvertSpeedToDisplaySpeed(uint speed, VehicleType type)
*/
uint ConvertDisplaySpeedToSpeed(uint speed, VehicleType type)
{
return _units_velocity[GetVelocityUnits(type)].c.FromDisplay(speed);
return GetVelocityUnits(type).c.FromDisplay(speed);
}
/**
@ -844,7 +882,7 @@ uint ConvertDisplaySpeedToSpeed(uint speed, VehicleType type)
*/
uint ConvertKmhishSpeedToDisplaySpeed(uint speed, VehicleType type)
{
return _units_velocity[GetVelocityUnits(type)].c.ToDisplay(speed * 10, false) / 16;
return GetVelocityUnits(type).c.ToDisplay(speed * 10, false) / 16;
}
/**
@ -854,7 +892,7 @@ uint ConvertKmhishSpeedToDisplaySpeed(uint speed, VehicleType type)
*/
uint ConvertDisplaySpeedToKmhishSpeed(uint speed, VehicleType type)
{
return _units_velocity[GetVelocityUnits(type)].c.FromDisplay(speed * 16, true, 10);
return GetVelocityUnits(type).c.FromDisplay(speed * 16, true, 10);
}
/**
@ -1334,9 +1372,7 @@ static void FormatString(StringBuilder &builder, const char *str_arg, StringPara
int64_t arg = args.GetNextParameter<int64_t>();
// Unpack vehicle type from packed argument to get desired units.
VehicleType vt = static_cast<VehicleType>(GB(arg, 56, 8));
byte units = GetVelocityUnits(vt);
assert(units < lengthof(_units_velocity));
const auto &x = _units_velocity[units];
const auto &x = GetVelocityUnits(vt);
auto tmp_params = MakeParameters(ConvertKmhishSpeedToDisplaySpeed(GB(arg, 0, 56), vt), x.decimal_places);
FormatString(builder, GetStringPtr(x.s), tmp_params);
break;
@ -1374,6 +1410,43 @@ static void FormatString(StringBuilder &builder, const char *str_arg, StringPara
break;
}
case SCC_UNITS_DAYS_OR_SECONDS: { // {UNITS_DAYS_OR_SECONDS}
uint8_t realtime = TimerGameEconomy::UsingWallclockUnits(_game_mode == GM_MENU);
const auto &x = _units_time_days_or_seconds[realtime];
auto tmp_params = MakeParameters(x.c.ToDisplay(args.GetNextParameter<int64_t>()), x.decimal_places);
FormatString(builder, GetStringPtr(x.s), tmp_params);
break;
}
case SCC_UNITS_MONTHS_OR_MINUTES: { // {UNITS_MONTHS_OR_MINUTES}
uint8_t realtime = TimerGameEconomy::UsingWallclockUnits(_game_mode == GM_MENU);
const auto &x = _units_time_months_or_minutes[realtime];
auto tmp_params = MakeParameters(x.c.ToDisplay(args.GetNextParameter<int64_t>()), x.decimal_places);
FormatString(builder, GetStringPtr(x.s), tmp_params);
break;
}
case SCC_UNITS_YEARS_OR_PERIODS: { // {UNITS_YEARS_OR_PERIODS}
uint8_t realtime = TimerGameEconomy::UsingWallclockUnits(_game_mode == GM_MENU);
const auto &x = _units_time_years_or_periods[realtime];
auto tmp_params = MakeParameters(x.c.ToDisplay(args.GetNextParameter<int64_t>()), x.decimal_places);
FormatString(builder, GetStringPtr(x.s), tmp_params);
break;
}
case SCC_UNITS_YEARS_OR_MINUTES: { // {UNITS_YEARS_OR_MINUTES}
uint8_t realtime = TimerGameEconomy::UsingWallclockUnits(_game_mode == GM_MENU);
const auto &x = _units_time_years_or_minutes[realtime];
auto tmp_params = MakeParameters(x.c.ToDisplay(args.GetNextParameter<int64_t>()), x.decimal_places);
FormatString(builder, GetStringPtr(x.s), tmp_params);
break;
}
case SCC_TIMEKEEPING_MODE_LIST: { // {TKM}
str = ParseStringChoice(str, (uint8_t)TimerGameEconomy::UsingWallclockUnits(_game_mode == GM_MENU), builder);
break;
}
case SCC_COMPANY_NAME: { // {COMPANY}
const Company *c = Company::GetIfValid(args.GetNextParameter<CompanyID>());
if (c == nullptr) break;

View File

@ -159,7 +159,15 @@ struct SubsidyListWindow : Window {
if (IsInsideMM(pos, 0, cap)) {
/* Displays the two offered towns */
SetupSubsidyDecodeParam(s, SubsidyDecodeParamType::Gui);
SetDParam(7, TimerGameEconomy::date - ymd.day + s->remaining * 32);
/* If using wallclock units, show minutes remaining. Otherwise show the date when the subsidy ends. */
if (TimerGameEconomy::UsingWallclockUnits()) {
SetDParam(7, STR_SUBSIDIES_OFFERED_EXPIRY_TIME);
SetDParam(8, s->remaining + 1); // We get the rest of the current economy month for free, since the expiration is checked on each new month.
} else {
SetDParam(7, STR_SUBSIDIES_OFFERED_EXPIRY_DATE);
SetDParam(8, TimerGameEconomy::date - ymd.day + s->remaining * 32);
}
DrawString(tr.left, tr.right, tr.top + pos * GetCharacterHeight(FS_NORMAL), STR_SUBSIDIES_OFFERED_FROM_TO);
}
pos++;
@ -183,7 +191,15 @@ struct SubsidyListWindow : Window {
if (IsInsideMM(pos, 0, cap)) {
SetupSubsidyDecodeParam(s, SubsidyDecodeParamType::Gui);
SetDParam(7, s->awarded);
SetDParam(8, TimerGameEconomy::date - ymd.day + s->remaining * 32);
/* If using wallclock units, show minutes remaining. Otherwise show the date when the subsidy ends. */
if (TimerGameEconomy::UsingWallclockUnits()) {
SetDParam(8, STR_SUBSIDIES_SUBSIDISED_EXPIRY_TIME);
SetDParam(9, s->remaining);
}
else {
SetDParam(8, STR_SUBSIDIES_SUBSIDISED_EXPIRY_DATE);
SetDParam(9, TimerGameEconomy::date - ymd.day + s->remaining * 32);
}
/* Displays the two connected stations */
DrawString(tr.left, tr.right, tr.top + pos * GetCharacterHeight(FS_NORMAL), STR_SUBSIDIES_SUBSIDISED_FROM_TO);

View File

@ -65,6 +65,12 @@ enum StringControlCode {
SCC_VELOCITY,
SCC_HEIGHT,
SCC_UNITS_DAYS_OR_SECONDS,
SCC_UNITS_MONTHS_OR_MINUTES,
SCC_UNITS_YEARS_OR_PERIODS,
SCC_UNITS_YEARS_OR_MINUTES,
SCC_TIMEKEEPING_MODE_LIST,
SCC_DATE_TINY,
SCC_DATE_SHORT,
SCC_DATE_LONG,

View File

@ -84,7 +84,7 @@ var = vehicle.servint_trains
type = SLE_UINT16
flags = SF_PER_COMPANY | SF_GUI_0_IS_SPECIAL
def = DEF_SERVINT_DAYS_TRAINS
min = MIN_SERVINT_PERCENT
min = MIN_SERVINT_MINUTES
max = MAX_SERVINT_DAYS
interval = 1
str = STR_CONFIG_SETTING_SERVINT_TRAINS
@ -98,7 +98,7 @@ var = vehicle.servint_roadveh
type = SLE_UINT16
flags = SF_PER_COMPANY | SF_GUI_0_IS_SPECIAL
def = DEF_SERVINT_DAYS_ROADVEH
min = MIN_SERVINT_PERCENT
min = MIN_SERVINT_MINUTES
max = MAX_SERVINT_DAYS
interval = 1
str = STR_CONFIG_SETTING_SERVINT_ROAD_VEHICLES
@ -112,7 +112,7 @@ var = vehicle.servint_ships
type = SLE_UINT16
flags = SF_PER_COMPANY | SF_GUI_0_IS_SPECIAL
def = DEF_SERVINT_DAYS_SHIPS
min = MIN_SERVINT_PERCENT
min = MIN_SERVINT_MINUTES
max = MAX_SERVINT_DAYS
interval = 1
str = STR_CONFIG_SETTING_SERVINT_SHIPS
@ -126,7 +126,7 @@ var = vehicle.servint_aircraft
type = SLE_UINT16
flags = SF_PER_COMPANY | SF_GUI_0_IS_SPECIAL
def = DEF_SERVINT_DAYS_AIRCRAFT
min = MIN_SERVINT_PERCENT
min = MIN_SERVINT_MINUTES
max = MAX_SERVINT_DAYS
interval = 1
str = STR_CONFIG_SETTING_SERVINT_AIRCRAFT

View File

@ -9,6 +9,7 @@
[pre-amble]
static void TownFoundingChanged(int32_t new_value);
static void ChangeTimekeepingUnits(int32_t new_value);
static const SettingVariant _economy_settings_table[] = {
[post-amble]
@ -280,3 +281,16 @@ str = STR_CONFIG_SETTING_INFRASTRUCTURE_MAINTENANCE
strhelp = STR_CONFIG_SETTING_INFRASTRUCTURE_MAINTENANCE_HELPTEXT
post_cb = [](auto) { InvalidateWindowClassesData(WC_COMPANY_INFRASTRUCTURE); }
cat = SC_BASIC
[SDT_VAR]
var = economy.timekeeping_units
type = SLE_UINT8
flags = SF_GUI_DROPDOWN | SF_NEWGAME_ONLY | SF_SCENEDIT_TOO
def = TKU_CALENDAR
min = TKU_CALENDAR
max = TKU_WALLCLOCK
str = STR_CONFIG_SETTING_TIMEKEEPING_UNITS
strval = STR_CONFIG_SETTING_TIMEKEEPING_UNITS_CALENDAR
strhelp = STR_CONFIG_SETTING_TIMEKEEPING_UNITS_HELPTEXT
post_cb = ChangeTimekeepingUnits
cat = SC_BASIC

View File

@ -7,6 +7,7 @@
; GUI settings as stored in the main configuration file ("openttd.cfg").
[pre-amble]
static bool CanChangeTimetableMode(int32_t &new_value);
static void v_PositionMainToolbar(int32_t new_value);
static void v_PositionStatusbar(int32_t new_value);
static void RedrawSmallmap(int32_t new_value);
@ -430,6 +431,7 @@ max = 2
str = STR_CONFIG_SETTING_TIMETABLE_MODE
strhelp = STR_CONFIG_SETTING_TIMETABLE_MODE_HELPTEXT
strval = STR_CONFIG_SETTING_TIMETABLE_MODE_DAYS
pre_cb = CanChangeTimetableMode
post_cb = [](auto) { InvalidateWindowClassesData(WC_VEHICLE_TIMETABLE, VIWD_MODIFY_ORDERS); }
cat = SC_ADVANCED

View File

@ -30,6 +30,7 @@ struct CmdStruct {
};
extern void EmitSingleChar(Buffer *buffer, char *buf, int value);
extern void EmitTKM(Buffer* buffer, char* buf, int value);
extern void EmitPlural(Buffer *buffer, char *buf, int value);
extern void EmitGender(Buffer *buffer, char *buf, int value);
@ -88,6 +89,13 @@ static const CmdStruct _cmd_structs[] = {
{"VELOCITY", EmitSingleChar, SCC_VELOCITY, 1, 0, C_NONE},
{"HEIGHT", EmitSingleChar, SCC_HEIGHT, 1, 0, C_NONE},
{"UNITS_DAYS_OR_SECONDS", EmitSingleChar, SCC_UNITS_DAYS_OR_SECONDS, 1, 0, C_NONE},
{"UNITS_MONTHS_OR_MINUTES", EmitSingleChar, SCC_UNITS_MONTHS_OR_MINUTES, 1, 0, C_NONE},
{"UNITS_YEARS_OR_PERIODS", EmitSingleChar, SCC_UNITS_YEARS_OR_PERIODS, 1, 0, C_NONE},
{"UNITS_YEARS_OR_MINUTES", EmitSingleChar, SCC_UNITS_YEARS_OR_MINUTES, 1, 0, C_NONE},
{"TKM", EmitTKM, 0, 0, -1, C_DONTCOUNT}, // Timekeeping mode string selection, e.g. "{TKM month minute}"
{"P", EmitPlural, 0, 0, -1, C_DONTCOUNT}, // plural specifier
{"G", EmitGender, 0, 0, -1, C_DONTCOUNT}, // gender specifier

View File

@ -33,6 +33,30 @@ TimerGameCalendar::Month TimerGameCalendar::month = {};
TimerGameCalendar::Date TimerGameCalendar::date = {};
TimerGameCalendar::DateFract TimerGameCalendar::date_fract = {};
/**
* Converts a Date to a Year, Month & Day.
* @param date the date to convert from
* @returns YearMonthDay representation of the Date.
*/
/* static */ TimerGameCalendar::YearMonthDay TimerGameCalendar::ConvertDateToYMD(TimerGameCalendar::Date date)
{
/* This wrapper function only exists because economy time sometimes does things differently, when using wallclock units. */
return CalendarConvertDateToYMD(date);
}
/**
* Converts a tuple of Year, Month and Day to a Date.
* @param year is a number between 0..MAX_YEAR
* @param month is a number between 0..11
* @param day is a number between 1..31
* @returns The equivalent date.
*/
/* static */ TimerGameCalendar::Date TimerGameCalendar::ConvertYMDToDate(TimerGameCalendar::Year year, TimerGameCalendar::Month month, TimerGameCalendar::Day day)
{
/* This wrapper function only exists because economy time sometimes does things differently, when using wallclock units. */
return CalendarConvertYMDToDate(year, month, day);
}
/**
* Set the date.
* @param date New date

View File

@ -34,6 +34,8 @@ public:
static Date date; ///< Current date in days (day counter).
static DateFract date_fract; ///< Fractional part of the day.
static YearMonthDay ConvertDateToYMD(Date date);
static Date ConvertYMDToDate(Year year, Month month, Day day);
static void SetDate(Date date, DateFract fract);
};

View File

@ -63,7 +63,7 @@ static constexpr uint16_t _accum_days_for_month[] = {
* @returns YearMonthDay representation of the Date.
*/
template <class T>
/* static */ typename TimerGame<T>::YearMonthDay TimerGame<T>::ConvertDateToYMD(Date date)
/* static */ typename TimerGame<T>::YearMonthDay TimerGame<T>::CalendarConvertDateToYMD(Date date)
{
/* Year determination in multiple steps to account for leap
* years. First do the large steps, then the smaller ones.
@ -118,9 +118,10 @@ template <class T>
* @param year is a number between 0..MAX_YEAR
* @param month is a number between 0..11
* @param day is a number between 1..31
* @returns The equivalent date.
*/
template <class T>
/* static */ typename TimerGame<T>::Date TimerGame<T>::ConvertYMDToDate(Year year, Month month, Day day)
/* static */ typename TimerGame<T>::Date TimerGame<T>::CalendarConvertYMDToDate(Year year, Month month, Day day)
{
/* Day-offset in a leap year */
int days = _accum_days_for_month[month] + day - 1;
@ -133,8 +134,8 @@ template <class T>
/* Create instances of the two template variants that we have.
* This is needed, as this templated functions are not in a header-file. */
template TimerGame<struct Calendar>::YearMonthDay TimerGame<struct Calendar>::ConvertDateToYMD(Date date);
template TimerGame<struct Economy>::YearMonthDay TimerGame<struct Economy>::ConvertDateToYMD(Date date);
template TimerGame<struct Calendar>::YearMonthDay TimerGame<struct Calendar>::CalendarConvertDateToYMD(Date date);
template TimerGame<struct Economy>::YearMonthDay TimerGame<struct Economy>::CalendarConvertDateToYMD(Date date);
template TimerGame<struct Calendar>::Date TimerGame<struct Calendar>::ConvertYMDToDate(Year year, Month month, Day day);
template TimerGame<struct Economy>::Date TimerGame<struct Economy>::ConvertYMDToDate(Year year, Month month, Day day);
template TimerGame<struct Calendar>::Date TimerGame<struct Calendar>::CalendarConvertYMDToDate(Year year, Month month, Day day);
template TimerGame<struct Economy>::Date TimerGame<struct Economy>::CalendarConvertYMDToDate(Year year, Month month, Day day);

View File

@ -66,8 +66,8 @@ public:
return year_as_int % 4 == 0 && (year_as_int % 100 != 0 || year_as_int % 400 == 0);
}
static YearMonthDay ConvertDateToYMD(Date date);
static Date ConvertYMDToDate(Year year, Month month, Day day);
static YearMonthDay CalendarConvertDateToYMD(Date date);
static Date CalendarConvertYMDToDate(Year year, Month month, Day day);
/**
* Calculate the year of a given date.

View File

@ -38,6 +38,41 @@ TimerGameEconomy::Month TimerGameEconomy::month = {};
TimerGameEconomy::Date TimerGameEconomy::date = {};
TimerGameEconomy::DateFract TimerGameEconomy::date_fract = {};
/**
* Converts a Date to a Year, Month & Day.
* @param date the date to convert from
* @returns YearMonthDay representation of the Date.
*/
/* static */ TimerGameEconomy::YearMonthDay TimerGameEconomy::ConvertDateToYMD(TimerGameEconomy::Date date)
{
/* If we're not using wallclock units, we keep the economy date in sync with the calendar. */
if (!UsingWallclockUnits()) return CalendarConvertDateToYMD(date);
/* If we're using wallclock units, economy months have 30 days and an economy year has 360 days. */
TimerGameEconomy::YearMonthDay ymd;
ymd.year = TimerGameEconomy::date.base() / EconomyTime::DAYS_IN_ECONOMY_YEAR;
ymd.month = (TimerGameEconomy::date.base() % EconomyTime::DAYS_IN_ECONOMY_YEAR) / EconomyTime::DAYS_IN_ECONOMY_MONTH;
ymd.day = TimerGameEconomy::date.base() % EconomyTime::DAYS_IN_ECONOMY_MONTH;
return ymd;
}
/**
* Converts a tuple of Year, Month and Day to a Date.
* @param year is a number between 0..MAX_YEAR
* @param month is a number between 0..11
* @param day is a number between 1..31
* @returns The equivalent date.
*/
/* static */ TimerGameEconomy::Date TimerGameEconomy::ConvertYMDToDate(TimerGameEconomy::Year year, TimerGameEconomy::Month month, TimerGameEconomy::Day day)
{
/* If we're not using wallclock units, we keep the economy date in sync with the calendar. */
if (!UsingWallclockUnits()) return CalendarConvertYMDToDate(year, month, day);
/* If we're using wallclock units, economy months have 30 days and an economy year has 360 days. */
const int total_months = (year.base() * EconomyTime::MONTHS_IN_YEAR) + month;
return (total_months * EconomyTime::DAYS_IN_ECONOMY_MONTH) + day - 1; // Day is 1-indexed but Date is 0-indexed, hence the - 1.
}
/**
* Set the date.
* @param date The new date
@ -54,6 +89,18 @@ TimerGameEconomy::DateFract TimerGameEconomy::date_fract = {};
TimerGameEconomy::month = ymd.month;
}
/**
* Check if we are using wallclock units.
* @param newgame Should we check the settings for a new game (since we are in the main menu)?
* @return True if the game is using wallclock units, or false if the game is using calendar units.
*/
/* static */ bool TimerGameEconomy::UsingWallclockUnits(bool newgame)
{
if (newgame) return (_settings_newgame.economy.timekeeping_units == TKU_WALLCLOCK);
return (_settings_game.economy.timekeeping_units == TKU_WALLCLOCK);
}
template<>
void IntervalTimer<TimerGameEconomy>::Elapsed(TimerGameEconomy::TElapsed trigger)
{

View File

@ -37,12 +37,19 @@ public:
static Date date; ///< Current date in days (day counter).
static DateFract date_fract; ///< Fractional part of the day.
static YearMonthDay ConvertDateToYMD(Date date);
static Date ConvertYMDToDate(Year year, Month month, Day day);
static void SetDate(Date date, DateFract fract);
static bool UsingWallclockUnits(bool newgame = false);
};
/**
* Storage class for Economy time constants.
*/
class EconomyTime : public TimerGameConst<struct Economy> {};
class EconomyTime : public TimerGameConst<struct Economy> {
public:
static constexpr int DAYS_IN_ECONOMY_YEAR = 360; ///< Days in an economy year, when in wallclock timekeeping mode.
static constexpr int DAYS_IN_ECONOMY_MONTH = 30; ///< Days in an economy month, when in wallclock timekeeping mode.
};
#endif /* TIMER_GAME_ECONOMY_H */

View File

@ -215,6 +215,12 @@ struct TimetableWindow : Window {
{
this->CreateNestedTree();
this->vscroll = this->GetScrollbar(WID_VT_SCROLLBAR);
/* When using wallclock units, we must ensure the client displays timetables in seconds. */
if (TimerGameEconomy::UsingWallclockUnits()) {
_settings_client.gui.timetable_mode = TimetableMode::Seconds;
}
this->UpdateSelectionStates();
this->FinishInitNested(window_number);

View File

@ -195,10 +195,17 @@ bool Vehicle::NeedsServicing() const
/* Are we ready for the next service cycle? */
const Company *c = Company::Get(this->owner);
if (this->ServiceIntervalIsPercent() ?
(this->reliability >= this->GetEngine()->reliability * (100 - this->GetServiceInterval()) / 100) :
(this->date_of_last_service + this->GetServiceInterval() >= TimerGameEconomy::date)) {
return false;
/* Service intervals can be measured in different units, which we handle individually. */
if (this->ServiceIntervalIsPercent()) {
/* Service interval is in percents. */
if (this->reliability >= this->GetEngine()->reliability * (100 - this->GetServiceInterval()) / 100) return false;
} else if (TimerGameEconomy::UsingWallclockUnits()) {
/* Service interval is in minutes. */
if (this->date_of_last_service + (this->GetServiceInterval() * EconomyTime::DAYS_IN_ECONOMY_MONTH) >= TimerGameEconomy::date) return false;
} else {
/* Service interval is in days. */
if (this->date_of_last_service + this->GetServiceInterval() >= TimerGameEconomy::date) return false;
}
/* If we're servicing anyway, because we have not disabled servicing when

View File

@ -2299,7 +2299,7 @@ extern void DrawAircraftDetails(const Aircraft *v, const Rect &r);
static StringID _service_interval_dropdown[] = {
STR_VEHICLE_DETAILS_DEFAULT,
STR_VEHICLE_DETAILS_DAYS,
STR_VEHICLE_DETAILS_TIME,
STR_VEHICLE_DETAILS_PERCENT,
INVALID_STRING_ID,
};
@ -2431,7 +2431,17 @@ struct VehicleDetailsWindow : Window {
case WID_VD_SERVICING_INTERVAL:
SetDParamMaxValue(0, MAX_SERVINT_DAYS); // Roughly the maximum interval
SetDParamMaxValue(1, TimerGameEconomy::DateAtStartOfYear(EconomyTime::MAX_YEAR)); // Roughly the maximum year
/* Do we show the last serviced value as a date or minutes since service? */
if (TimerGameEconomy::UsingWallclockUnits()) {
SetDParam(1, STR_VEHICLE_DETAILS_LAST_SERVICE_MINUTES_AGO);
/*/ Vehicle was last serviced at year 0, and we're at max year */
SetDParamMaxValue(2, EconomyTime::MONTHS_IN_YEAR * EconomyTime::MAX_YEAR.base());
} else {
SetDParam(1, STR_VEHICLE_DETAILS_LAST_SERVICE_DATE);
/*/ Vehicle was last serviced at year 0, and we're at max year */
SetDParamMaxValue(2, TimerGameEconomy::DateAtStartOfYear(EconomyTime::MAX_YEAR));
}
size->width = std::max(
GetStringBoundingBox(STR_VEHICLE_DETAILS_SERVICING_INTERVAL_PERCENT).width,
GetStringBoundingBox(STR_VEHICLE_DETAILS_SERVICING_INTERVAL_DAYS).width
@ -2572,8 +2582,22 @@ struct VehicleDetailsWindow : Window {
case WID_VD_SERVICING_INTERVAL: {
/* Draw service interval text */
Rect tr = r.Shrink(WidgetDimensions::scaled.framerect);
SetDParam(0, v->GetServiceInterval());
SetDParam(1, v->date_of_last_service);
/* We're using wallclock units. Show minutes since last serviced. */
if (TimerGameEconomy::UsingWallclockUnits()) {
int minutes_since_serviced = (TimerGameEconomy::date - v->date_of_last_service).base() / EconomyTime::DAYS_IN_ECONOMY_MONTH;
SetDParam(1, STR_VEHICLE_DETAILS_LAST_SERVICE_MINUTES_AGO);
SetDParam(2, minutes_since_serviced);
DrawString(tr.left, tr.right, CenterBounds(r.top, r.bottom, GetCharacterHeight(FS_NORMAL)),
v->ServiceIntervalIsPercent() ? STR_VEHICLE_DETAILS_SERVICING_INTERVAL_PERCENT : STR_VEHICLE_DETAILS_SERVICING_INTERVAL_MINUTES);
break;
}
/* We're using calendar dates. Show the date of last service. */
SetDParam(1, STR_VEHICLE_DETAILS_LAST_SERVICE_DATE);
SetDParam(2, v->date_of_last_service);
DrawString(tr.left, tr.right, CenterBounds(r.top, r.bottom, GetCharacterHeight(FS_NORMAL)),
v->ServiceIntervalIsPercent() ? STR_VEHICLE_DETAILS_SERVICING_INTERVAL_PERCENT : STR_VEHICLE_DETAILS_SERVICING_INTERVAL_DAYS);
break;
@ -2597,7 +2621,7 @@ struct VehicleDetailsWindow : Window {
WID_VD_DECREASE_SERVICING_INTERVAL);
StringID str = v->ServiceIntervalIsCustom() ?
(v->ServiceIntervalIsPercent() ? STR_VEHICLE_DETAILS_PERCENT : STR_VEHICLE_DETAILS_DAYS) :
(v->ServiceIntervalIsPercent() ? STR_VEHICLE_DETAILS_PERCENT : STR_VEHICLE_DETAILS_TIME) :
STR_VEHICLE_DETAILS_DEFAULT;
this->GetWidget<NWidgetCore>(WID_VD_SERVICE_INTERVAL_DROPDOWN)->widget_data = str;
@ -2609,7 +2633,7 @@ struct VehicleDetailsWindow : Window {
switch (widget) {
case WID_VD_INCREASE_SERVICING_INTERVAL: // increase int
case WID_VD_DECREASE_SERVICING_INTERVAL: { // decrease int
int mod = _ctrl_pressed ? 5 : 10;
int mod = TimerGameEconomy::UsingWallclockUnits() ? (_ctrl_pressed ? 1 : 5) : (_ctrl_pressed ? 5 : 10);
const Vehicle *v = Vehicle::Get(this->window_number);
mod = (widget == WID_VD_DECREASE_SERVICING_INTERVAL) ? -mod : mod;

View File

@ -27,6 +27,7 @@ enum CompanyValueWidgets : WidgetID {
WID_CV_BACKGROUND, ///< Background of the window.
WID_CV_GRAPH, ///< Graph itself.
WID_CV_RESIZE, ///< Resize button.
WID_CV_FOOTER, ///< Footer.
};
/** Widget of the #PerformanceHistoryGraphWindow class. */
@ -36,6 +37,7 @@ enum PerformanceHistoryGraphWidgets : WidgetID {
WID_PHG_BACKGROUND, ///< Background of the window.
WID_PHG_GRAPH, ///< Graph itself.
WID_PHG_RESIZE, ///< Resize button.
WID_PHG_FOOTER, ///< Footer.
};
/** Widget of the #PaymentRatesGraphWindow class. */