Add wallclock time settings
This commit is contained in:
@@ -113,7 +113,7 @@ static int32_t ClickChangeDateCheat(int32_t p1, int32_t p2)
|
||||
/* Change the date. */
|
||||
CalTime::Detail::SetDate(new_date, CalTime::CurDateFract());
|
||||
|
||||
{
|
||||
if (!EconTime::UsingWallclockUnits()) {
|
||||
EconTime::Date new_econ_date = new_date.base();
|
||||
EconTime::DateFract new_econ_date_fract = CalTime::CurDateFract();
|
||||
|
||||
|
36
src/date.cpp
36
src/date.cpp
@@ -246,21 +246,37 @@ CalTime::Date CalTime::ConvertYMDToDate(CalTime::Year year, CalTime::Month month
|
||||
|
||||
EconTime::YearMonthDay EconTime::ConvertDateToYMD(EconTime::Date date)
|
||||
{
|
||||
/* Process the same as calendar time (for now) */
|
||||
if (EconTime::UsingWallclockUnits()) {
|
||||
/* If we're using wallclock units, economy months have 30 days and an economy year has 360 days. */
|
||||
EconTime::YearMonthDay ymd;
|
||||
ymd.year =date.base() / EconTime::DAYS_IN_ECONOMY_WALLCLOCK_YEAR;
|
||||
ymd.month = (date.base() % EconTime::DAYS_IN_ECONOMY_WALLCLOCK_YEAR) / EconTime::DAYS_IN_ECONOMY_WALLCLOCK_MONTH;
|
||||
ymd.day = date.base() % EconTime::DAYS_IN_ECONOMY_WALLCLOCK_MONTH;
|
||||
return ymd;
|
||||
}
|
||||
|
||||
/* Process the same as calendar time */
|
||||
CalTime::YearMonthDay ymd = CalTime::ConvertDateToYMD(date.base());
|
||||
return { ymd.year.base(), ymd.month, ymd.day };
|
||||
}
|
||||
|
||||
EconTime::Date EconTime::ConvertYMDToDate(EconTime::Year year, EconTime::Month month, EconTime::Day day)
|
||||
{
|
||||
/* Process the same as calendar time (for now) */
|
||||
if (EconTime::UsingWallclockUnits()) {
|
||||
/* If we're using wallclock units, economy months have 30 days and an economy year has 360 days. */
|
||||
const int total_months = (year.base() * MONTHS_IN_YEAR) + month;
|
||||
return (total_months * EconTime::DAYS_IN_ECONOMY_WALLCLOCK_MONTH) + day - 1; // Day is 1-indexed but Date is 0-indexed, hence the - 1.
|
||||
}
|
||||
|
||||
/* Process the same as calendar time */
|
||||
return CalTime::ConvertYMDToDate(year.base(), month, day).base();
|
||||
}
|
||||
|
||||
bool EconTime::UsingWallclockUnits(bool newgame)
|
||||
{
|
||||
/* Always return false (for now) */
|
||||
return false;
|
||||
if (newgame) return (_settings_newgame.economy.timekeeping_units == TKU_WALLCLOCK);
|
||||
|
||||
return (_settings_game.economy.timekeeping_units == TKU_WALLCLOCK);
|
||||
}
|
||||
|
||||
/** Functions used by the IncreaseDate function */
|
||||
@@ -397,6 +413,18 @@ static void OnNewEconomyDay()
|
||||
|
||||
static void IncreaseCalendarDate()
|
||||
{
|
||||
/* If calendar day progress is frozen, don't try to advance time. */
|
||||
if (_settings_game.economy.minutes_per_calendar_year == CalTime::FROZEN_MINUTES_PER_YEAR) return;
|
||||
|
||||
/* If we are using a non-default calendar progression speed, we need to check the sub_date_fract before updating date_fract. */
|
||||
if (_settings_game.economy.minutes_per_calendar_year != CalTime::DEF_MINUTES_PER_YEAR) {
|
||||
CalTime::Detail::now.sub_date_fract++;
|
||||
|
||||
/* Check if we are ready to increment date_fract */
|
||||
if (CalTime::Detail::now.sub_date_fract < (DAY_TICKS * _settings_game.economy.minutes_per_calendar_year) / CalTime::DEF_MINUTES_PER_YEAR) return;
|
||||
}
|
||||
CalTime::Detail::now.sub_date_fract = 0;
|
||||
|
||||
CalTime::Detail::now.cal_date_fract++;
|
||||
if (CalTime::Detail::now.cal_date_fract < DAY_TICKS) return;
|
||||
CalTime::Detail::now.cal_date_fract = 0;
|
||||
|
@@ -124,7 +124,7 @@ struct SetDateWindow : Window {
|
||||
break;
|
||||
|
||||
case WID_SD_YEAR:
|
||||
SetDParamMaxValue(0, this->max_year.base());
|
||||
SetDParamMaxValue(0, this->max_year);
|
||||
d = maxdim(d, GetStringBoundingBox(STR_JUST_INT));
|
||||
break;
|
||||
}
|
||||
|
@@ -176,6 +176,10 @@ struct CalTime : public DateDetail::BaseTime<struct CalendarTimeTag> {
|
||||
static State NewState(Year year);
|
||||
};
|
||||
|
||||
static constexpr int DEF_MINUTES_PER_YEAR = 12;
|
||||
static constexpr int FROZEN_MINUTES_PER_YEAR = 0;
|
||||
static constexpr int MAX_MINUTES_PER_YEAR = 10080; // One week of real time. The actual max that doesn't overflow TimerGameCalendar::sub_date_fract is 10627, but this is neater.
|
||||
|
||||
static inline const YearMonthDay &CurYMD() { return Detail::now.cal_ymd; }
|
||||
static inline Year CurYear() { return Detail::now.cal_ymd.year; }
|
||||
static inline Month CurMonth() { return Detail::now.cal_ymd.month; }
|
||||
@@ -213,20 +217,42 @@ struct CalTime : public DateDetail::BaseTime<struct CalendarTimeTag> {
|
||||
};
|
||||
|
||||
struct EconTime : public DateDetail::BaseTime<struct EconTimeTag> {
|
||||
using ParentBaseTime = DateDetail::BaseTime<struct EconTimeTag>;
|
||||
|
||||
/* Use a state struct to make backup/restore/init simpler */
|
||||
struct State {
|
||||
YearMonthDay econ_ymd;
|
||||
Date econ_date;
|
||||
DateFract econ_date_fract;
|
||||
};
|
||||
|
||||
static constexpr int DAYS_IN_ECONOMY_WALLCLOCK_YEAR = 360; ///< Days in an economy year, when in wallclock timekeeping mode.
|
||||
static constexpr int DAYS_IN_ECONOMY_WALLCLOCK_MONTH = 30; ///< Days in an economy month, when in wallclock timekeeping mode.
|
||||
|
||||
/* Use a detail struct/namespace to more easily control writes */
|
||||
struct Detail {
|
||||
static State now;
|
||||
|
||||
static void SetDate(Date date, DateFract fract);
|
||||
static State NewState(Year year);
|
||||
|
||||
/**
|
||||
* Calculate the date of the first day of a given year.
|
||||
* @param year the year to get the first day of.
|
||||
* @return the date (when using wallclock 30-day months).
|
||||
*/
|
||||
static constexpr Date DateAtStartOfWallclockModeYear(Year year)
|
||||
{
|
||||
return DAYS_IN_ECONOMY_WALLCLOCK_YEAR * year.base();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* The offset in days from the '_date == 0' till
|
||||
* 'ConvertYMDToDate(ORIGINAL_BASE_YEAR, 0, 1)', when using wallclock 30-day months
|
||||
*/
|
||||
static constexpr Date DAYS_TILL_ORIGINAL_BASE_YEAR_WALLCLOCK_MODE = DAYS_IN_ECONOMY_WALLCLOCK_YEAR * ORIGINAL_BASE_YEAR.base();
|
||||
|
||||
static inline const YearMonthDay &CurYMD() { return Detail::now.econ_ymd; }
|
||||
static inline Year CurYear() { return Detail::now.econ_ymd.year; }
|
||||
static inline Month CurMonth() { return Detail::now.econ_ymd.month; }
|
||||
@@ -244,6 +270,17 @@ struct EconTime : public DateDetail::BaseTime<struct EconTimeTag> {
|
||||
}
|
||||
|
||||
static bool UsingWallclockUnits(bool newgame = false);
|
||||
|
||||
/**
|
||||
* Calculate the date of the first day of a given year.
|
||||
* @param year the year to get the first day of.
|
||||
* @return the date.
|
||||
*/
|
||||
static inline Date DateAtStartOfYear(Year year)
|
||||
{
|
||||
if (UsingWallclockUnits()) return Detail::DateAtStartOfWallclockModeYear(year);
|
||||
return ParentBaseTime::Detail::DateAtStartOfCalendarYear(year);
|
||||
}
|
||||
};
|
||||
|
||||
namespace DateDetail {
|
||||
|
@@ -158,7 +158,9 @@ void InitializeGame(uint size_x, uint size_y, bool reset_date, bool reset_settin
|
||||
|
||||
if (reset_date) {
|
||||
CalTime::Detail::SetDate(CalTime::ConvertYMDToDate(_settings_game.game_creation.starting_year, 0, 1), 0);
|
||||
{
|
||||
if (EconTime::UsingWallclockUnits()) {
|
||||
EconTime::Detail::SetDate(EconTime::DAYS_TILL_ORIGINAL_BASE_YEAR_WALLCLOCK_MODE, 0);
|
||||
} else {
|
||||
EconTime::Detail::SetDate(CalTime::CurDate().base(), 0);
|
||||
}
|
||||
InitializeOldNames();
|
||||
|
@@ -431,6 +431,7 @@ uint32_t IndustriesScopeResolver::GetCountAndDistanceOfClosestInstance(byte para
|
||||
case 0xB3: return this->industry->construction_type; // Construction type
|
||||
case 0xB4: {
|
||||
EconTime::Date *latest = std::max_element(this->industry->last_cargo_accepted_at, endof(this->industry->last_cargo_accepted_at));
|
||||
if (EconTime::UsingWallclockUnits()) return ClampTo<uint16_t>((*latest) - EconTime::DAYS_TILL_ORIGINAL_BASE_YEAR_WALLCLOCK_MODE);
|
||||
return ClampTo<uint16_t>((*latest) - EconTime::DAYS_TILL_ORIGINAL_BASE_YEAR); // Date last cargo accepted since 1920 (in days)
|
||||
}
|
||||
}
|
||||
|
@@ -2962,13 +2962,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 (EconTime::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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -42,6 +42,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;
|
||||
|
@@ -873,6 +873,11 @@ bool AfterLoadGame()
|
||||
* must be done before loading sprites as some newgrfs check it */
|
||||
CalTime::Detail::SetDate(CalTime::CurDate(), CalTime::CurDateFract());
|
||||
|
||||
/* Only new games can use wallclock units. */
|
||||
if (SlXvIsFeatureMissing(XSLFI_VARIABLE_DAY_LENGTH, 5) && IsSavegameVersionBefore(SLV_ECONOMY_MODE_TIMEKEEPING_UNITS)) {
|
||||
_settings_game.economy.timekeeping_units = TKU_CALENDAR;
|
||||
}
|
||||
|
||||
if (SlXvIsFeaturePresent(XSLFI_VARIABLE_DAY_LENGTH, 5) || !IsSavegameVersionBefore(SLV_ECONOMY_DATE)) {
|
||||
EconTime::Detail::SetDate(EconTime::CurDate(), EconTime::CurDateFract());
|
||||
} else {
|
||||
|
@@ -1079,6 +1079,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 (EconTime::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;
|
||||
@@ -1127,6 +1133,85 @@ static void UpdateServiceInterval(VehicleType type, int32_t new_value)
|
||||
SetWindowClassesDirty(WC_VEHICLE_DETAILS);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
/* If we are using calendar timekeeping, "minutes per year" must be default. */
|
||||
if (_game_mode == GM_MENU && !EconTime::UsingWallclockUnits(true)) {
|
||||
_settings_newgame.economy.minutes_per_calendar_year = CalTime::DEF_MINUTES_PER_YEAR;
|
||||
}
|
||||
|
||||
InvalidateWindowClassesData(WC_GAME_OPTIONS, 0);
|
||||
|
||||
/* It is possible to change these units in Scenario Editor. We must set the economy date appropriately. */
|
||||
if (_game_mode == GM_EDITOR) {
|
||||
EconTime::Date new_economy_date;
|
||||
EconTime::DateFract new_economy_date_fract;
|
||||
|
||||
if (EconTime::UsingWallclockUnits()) {
|
||||
/* If the new mode is wallclock units, set the economy year back to 1. */
|
||||
new_economy_date = EconTime::DAYS_TILL_ORIGINAL_BASE_YEAR_WALLCLOCK_MODE;
|
||||
new_economy_date_fract = 0;
|
||||
} else {
|
||||
/* If the new mode is calendar units, sync the economy year with the calendar year. */
|
||||
new_economy_date = CalTime::CurDate().base();
|
||||
new_economy_date_fract = CalTime::CurDateFract();
|
||||
}
|
||||
|
||||
/* If you open a savegame as a scenario, there may already be link graphs and/or vehicles. These use economy date. */
|
||||
LinkGraphSchedule::instance.ShiftDates(new_economy_date - EconTime::CurDate());
|
||||
ShiftVehicleDates(new_economy_date - EconTime::CurDate());
|
||||
|
||||
/* Only change the date after changing cached values above. */
|
||||
EconTime::Detail::SetDate(new_economy_date, new_economy_date_fract);
|
||||
UpdateOrderUIOnDateChange();
|
||||
}
|
||||
|
||||
UpdateEffectiveDayLengthFactor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback after the player changes the minutes per year.
|
||||
* @param new_value The intended new value of the setting, used for clamping.
|
||||
*/
|
||||
static void ChangeMinutesPerYear(int32_t new_value)
|
||||
{
|
||||
/* We don't allow setting Minutes Per Year below default, unless it's to 0 for frozen calendar time. */
|
||||
if (new_value < CalTime::DEF_MINUTES_PER_YEAR) {
|
||||
int clamped;
|
||||
|
||||
/* If the new value is 1, we're probably at 0 and trying to increase the value, so we should jump up to default. */
|
||||
if (new_value == 1) {
|
||||
clamped = CalTime::DEF_MINUTES_PER_YEAR;
|
||||
} else {
|
||||
clamped = CalTime::FROZEN_MINUTES_PER_YEAR;
|
||||
}
|
||||
|
||||
/* Override the setting with the clamped value. */
|
||||
if (_game_mode == GM_MENU) {
|
||||
_settings_newgame.economy.minutes_per_calendar_year = clamped;
|
||||
} else {
|
||||
_settings_game.economy.minutes_per_calendar_year = clamped;
|
||||
}
|
||||
}
|
||||
|
||||
/* If the setting value is not the default, force the game to use wallclock timekeeping units.
|
||||
* This can only happen in the menu, since the pre_cb ensures this setting can only be changed there, or if we're already using wallclock units.
|
||||
*/
|
||||
if (_game_mode == GM_MENU && (_settings_newgame.economy.minutes_per_calendar_year != CalTime::DEF_MINUTES_PER_YEAR)) {
|
||||
_settings_newgame.economy.timekeeping_units = TKU_WALLCLOCK;
|
||||
InvalidateWindowClassesData(WC_GAME_OPTIONS, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void TrainAccelerationModelChanged(int32_t new_value)
|
||||
{
|
||||
for (Train *t : Train::Iterate()) {
|
||||
|
@@ -2432,6 +2432,8 @@ 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("economy.minutes_per_calendar_year"));
|
||||
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"));
|
||||
|
@@ -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,
|
||||
@@ -763,6 +769,8 @@ struct EconomySettings {
|
||||
uint8_t town_max_road_slope; ///< maximum number of consecutive sloped road tiles which towns are allowed to build
|
||||
bool allow_town_bridges; ///< towns are allowed to build bridges
|
||||
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
|
||||
uint16_t minutes_per_calendar_year; ///< minutes per calendar year. Special value 0 means that calendar time is frozen.
|
||||
uint16_t town_cargo_scale; ///< scale cargo production of towns by this percentage.
|
||||
uint16_t industry_cargo_scale; ///< scale cargo production of industries by this percentage.
|
||||
CargoScalingMode town_cargo_scale_mode; ///< scaling mode for town cargo.
|
||||
@@ -890,7 +898,7 @@ struct GameSettings {
|
||||
|
||||
uint8_t EffectiveDayLengthFactor() const
|
||||
{
|
||||
return this->economy.day_length_factor;
|
||||
return this->economy.timekeeping_units == TKU_CALENDAR ? this->economy.day_length_factor : 1;
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -157,7 +157,15 @@ struct SubsidyListWindow : Window {
|
||||
if (IsInsideMM(pos, 0, cap)) {
|
||||
/* Displays the two offered towns */
|
||||
SetupSubsidyDecodeParam(s, SubsidyDecodeParamType::Gui);
|
||||
SetDParam(7, EconTime::CurDate() - EconTime::CurDay() + s->remaining * 32);
|
||||
/* If using wallclock units, show minutes remaining. Otherwise show the date when the subsidy ends. */
|
||||
if (EconTime::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, EconTime::CurDate() - EconTime::CurDay() + s->remaining * 32);
|
||||
}
|
||||
|
||||
DrawString(tr.left, tr.right, tr.top + pos * GetCharacterHeight(FS_NORMAL), STR_SUBSIDIES_OFFERED_FROM_TO);
|
||||
}
|
||||
pos++;
|
||||
@@ -181,7 +189,15 @@ struct SubsidyListWindow : Window {
|
||||
if (IsInsideMM(pos, 0, cap)) {
|
||||
SetupSubsidyDecodeParam(s, SubsidyDecodeParamType::Gui);
|
||||
SetDParam(7, s->awarded);
|
||||
SetDParam(8, EconTime::CurDate() - EconTime::CurDay() + s->remaining * 32);
|
||||
/* If using wallclock units, show minutes remaining. Otherwise show the date when the subsidy ends. */
|
||||
if (EconTime::UsingWallclockUnits()) {
|
||||
SetDParam(8, STR_SUBSIDIES_SUBSIDISED_EXPIRY_TIME);
|
||||
SetDParam(9, s->remaining);
|
||||
}
|
||||
else {
|
||||
SetDParam(8, STR_SUBSIDIES_SUBSIDISED_EXPIRY_DATE);
|
||||
SetDParam(9, EconTime::CurDate() - EconTime::CurDay() + s->remaining * 32);
|
||||
}
|
||||
|
||||
/* Displays the two connected stations */
|
||||
DrawString(tr.left, tr.right, tr.top + pos * GetCharacterHeight(FS_NORMAL), STR_SUBSIDIES_SUBSIDISED_FROM_TO);
|
||||
|
@@ -9,6 +9,8 @@
|
||||
|
||||
[pre-amble]
|
||||
static void TownFoundingChanged(int32_t new_value);
|
||||
static void ChangeTimekeepingUnits(int32_t new_value);
|
||||
static void ChangeMinutesPerYear(int32_t new_value);
|
||||
static void InvalidateCompanyWindow(int32_t new_value);
|
||||
static void DayLengthChanged(int32_t new_value);
|
||||
static bool CheckSharingRail(int32_t &new_value);
|
||||
@@ -702,10 +704,37 @@ 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
|
||||
|
||||
[SDT_VAR]
|
||||
var = economy.minutes_per_calendar_year
|
||||
type = SLE_UINT16
|
||||
flags = SF_GUI_0_IS_SPECIAL
|
||||
def = CalTime::DEF_MINUTES_PER_YEAR
|
||||
min = CalTime::FROZEN_MINUTES_PER_YEAR
|
||||
max = CalTime::MAX_MINUTES_PER_YEAR
|
||||
interval = 1
|
||||
str = STR_CONFIG_SETTING_MINUTES_PER_YEAR
|
||||
strhelp = STR_CONFIG_SETTING_MINUTES_PER_YEAR_HELPTEXT
|
||||
strval = STR_CONFIG_SETTING_MINUTES_PER_YEAR_VALUE
|
||||
pre_cb = [](auto) { return _game_mode == GM_MENU || _settings_game.economy.timekeeping_units == 1; }
|
||||
post_cb = ChangeMinutesPerYear
|
||||
cat = SC_BASIC
|
||||
|
||||
[SDT_VAR]
|
||||
var = economy.town_cargo_scale
|
||||
type = SLE_UINT16
|
||||
flags = SF_PATCH
|
||||
def = 100
|
||||
min = 1
|
||||
max = 5000
|
||||
@@ -720,7 +749,6 @@ guiproc = TownCargoScaleGUI
|
||||
[SDT_VAR]
|
||||
var = economy.industry_cargo_scale
|
||||
type = SLE_UINT16
|
||||
flags = SF_PATCH
|
||||
def = 100
|
||||
min = 5
|
||||
max = 3000
|
||||
|
@@ -2819,13 +2819,20 @@ extern void DrawRoadVehDetails(const Vehicle *v, const Rect &r);
|
||||
extern void DrawShipDetails(const Vehicle *v, const Rect &r);
|
||||
extern void DrawAircraftDetails(const Aircraft *v, const Rect &r);
|
||||
|
||||
static StringID _service_interval_dropdown[] = {
|
||||
static StringID _service_interval_dropdown_calendar[] = {
|
||||
STR_VEHICLE_DETAILS_DEFAULT,
|
||||
STR_VEHICLE_DETAILS_DAYS,
|
||||
STR_VEHICLE_DETAILS_PERCENT,
|
||||
INVALID_STRING_ID,
|
||||
};
|
||||
|
||||
static StringID _service_interval_dropdown_wallclock[] = {
|
||||
STR_VEHICLE_DETAILS_DEFAULT,
|
||||
STR_VEHICLE_DETAILS_MINUTES,
|
||||
STR_VEHICLE_DETAILS_PERCENT,
|
||||
INVALID_STRING_ID,
|
||||
};
|
||||
|
||||
/** Class for managing the vehicle details window. */
|
||||
struct VehicleDetailsWindow : Window {
|
||||
TrainDetailsWindowTabs tab; ///< For train vehicles: which tab is displayed.
|
||||
@@ -3024,10 +3031,11 @@ struct VehicleDetailsWindow : Window {
|
||||
|
||||
case WID_VD_SERVICE_INTERVAL_DROPDOWN: {
|
||||
Dimension d{0, 0};
|
||||
StringID *strs = _service_interval_dropdown;
|
||||
for (const StringID *strs : {_service_interval_dropdown_calendar, _service_interval_dropdown_wallclock}) {
|
||||
while (*strs != INVALID_STRING_ID) {
|
||||
d = maxdim(d, GetStringBoundingBox(*strs++));
|
||||
}
|
||||
}
|
||||
d.width += padding.width;
|
||||
d.height += padding.height;
|
||||
*size = maxdim(*size, d);
|
||||
@@ -3036,7 +3044,17 @@ struct VehicleDetailsWindow : Window {
|
||||
|
||||
case WID_VD_SERVICING_INTERVAL:
|
||||
SetDParamMaxValue(0, MAX_SERVINT_DAYS); // Roughly the maximum interval
|
||||
SetDParamMaxValue(1, CalTime::MAX_YEAR.base() * DAYS_IN_YEAR); // Roughly the maximum year
|
||||
|
||||
/* Do we show the last serviced value as a date or minutes since service? */
|
||||
if (EconTime::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, MONTHS_IN_YEAR * EconTime::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, EconTime::DateAtStartOfYear(EconTime::MAX_YEAR));
|
||||
}
|
||||
size->width = std::max(
|
||||
GetStringBoundingBox(STR_VEHICLE_DETAILS_SERVICING_INTERVAL_PERCENT).width,
|
||||
GetStringBoundingBox(STR_VEHICLE_DETAILS_SERVICING_INTERVAL_DAYS).width
|
||||
@@ -3264,8 +3282,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 (EconTime::UsingWallclockUnits()) {
|
||||
int minutes_since_serviced = (EconTime::CurDate() - v->date_of_last_service).base() / EconTime::DAYS_IN_ECONOMY_WALLCLOCK_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;
|
||||
@@ -3288,9 +3320,10 @@ struct VehicleDetailsWindow : Window {
|
||||
WID_VD_INCREASE_SERVICING_INTERVAL,
|
||||
WID_VD_DECREASE_SERVICING_INTERVAL);
|
||||
|
||||
StringID str = v->ServiceIntervalIsCustom() ?
|
||||
(v->ServiceIntervalIsPercent() ? STR_VEHICLE_DETAILS_PERCENT : STR_VEHICLE_DETAILS_DAYS) :
|
||||
STR_VEHICLE_DETAILS_DEFAULT;
|
||||
StringID str =
|
||||
!v->ServiceIntervalIsCustom() ? STR_VEHICLE_DETAILS_DEFAULT :
|
||||
v->ServiceIntervalIsPercent() ? STR_VEHICLE_DETAILS_PERCENT :
|
||||
EconTime::UsingWallclockUnits() ? STR_VEHICLE_DETAILS_MINUTES : STR_VEHICLE_DETAILS_DAYS;
|
||||
this->GetWidget<NWidgetCore>(WID_VD_SERVICE_INTERVAL_DROPDOWN)->widget_data = str;
|
||||
|
||||
this->DrawWidgets();
|
||||
@@ -3301,8 +3334,13 @@ 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;
|
||||
const Vehicle *v = Vehicle::Get(this->window_number);
|
||||
int mod;
|
||||
if (!v->ServiceIntervalIsPercent() && EconTime::UsingWallclockUnits()) {
|
||||
mod = _ctrl_pressed ? 1 : 5;
|
||||
} else {
|
||||
mod = _ctrl_pressed ? 5 : 10;
|
||||
}
|
||||
|
||||
mod = (widget == WID_VD_DECREASE_SERVICING_INTERVAL) ? -mod : mod;
|
||||
mod = GetServiceIntervalClamped(mod + v->GetServiceInterval(), v->ServiceIntervalIsPercent());
|
||||
@@ -3314,7 +3352,9 @@ struct VehicleDetailsWindow : Window {
|
||||
|
||||
case WID_VD_SERVICE_INTERVAL_DROPDOWN: {
|
||||
const Vehicle *v = Vehicle::Get(this->window_number);
|
||||
ShowDropDownMenu(this, _service_interval_dropdown, v->ServiceIntervalIsCustom() ? (v->ServiceIntervalIsPercent() ? 2 : 1) : 0, widget, 0, 0, 0, DDSF_LOST_FOCUS);
|
||||
ShowDropDownMenu(this,
|
||||
EconTime::UsingWallclockUnits() ? _service_interval_dropdown_wallclock : _service_interval_dropdown_calendar,
|
||||
v->ServiceIntervalIsCustom() ? (v->ServiceIntervalIsPercent() ? 2 : 1) : 0, widget, 0, 0, 0, DDSF_LOST_FOCUS);
|
||||
break;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user