Changeset - r28561:d3b2600c3b1b
[Not reviewed]
master
0 15 0
Tyler Trahan - 3 months ago 2024-01-23 23:33:54
tyler@tylertrahan.com
Feature: Setting for minutes per calendar year (#11428)
15 files changed with 118 insertions and 18 deletions:
0 comments (0 inline, 0 general)
src/lang/english.txt
Show inline comments
 
@@ -1487,6 +1487,13 @@ STR_CONFIG_SETTING_TIMEKEEPING_UNITS_HEL
 
STR_CONFIG_SETTING_TIMEKEEPING_UNITS_CALENDAR                   :Calendar
 
STR_CONFIG_SETTING_TIMEKEEPING_UNITS_WALLCLOCK                  :Wallclock
 

	
 
STR_CONFIG_SETTING_MINUTES_PER_YEAR                             :Minutes per year: {STRING2}
 
STR_CONFIG_SETTING_MINUTES_PER_YEAR_HELPTEXT                    :Choose the number of minutes in a calendar year. The default is 12 minutes. Set to 0 to stop calendar time from changing. This setting does not affect the economic simulation of the game, and is only available when using wallclock timekeeping.
 

	
 
STR_CONFIG_SETTING_MINUTES_PER_YEAR_VALUE                       :{NUM}
 
###setting-zero-is-special
 
STR_CONFIG_SETTING_MINUTES_PER_YEAR_FROZEN                      :0 (calendar time frozen)
 

	
 
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
 

	
src/openttd.cpp
Show inline comments
 
@@ -1472,11 +1472,12 @@ void StateGameLoop()
 

	
 
		BasePersistentStorageArray::SwitchMode(PSM_ENTER_GAMELOOP);
 
		AnimateAnimatedTiles();
 
		TimerManager<TimerGameCalendar>::Elapsed(1);
 
		if (TimerManager<TimerGameCalendar>::Elapsed(1)) {
 
			RunVehicleCalendarDayProc();
 
		}
 
		TimerManager<TimerGameEconomy>::Elapsed(1);
 
		TimerManager<TimerGameTick>::Elapsed(1);
 
		RunTileLoop();
 
		RunVehicleCalendarDayProc();
 
		CallVehicleTicks();
 
		CallLandscapeTick();
 
		BasePersistentStorageArray::SwitchMode(PSM_LEAVE_GAMELOOP);
src/saveload/misc_sl.cpp
Show inline comments
 
@@ -88,6 +88,7 @@ static const SaveLoad _date_desc[] = {
 
	SLEG_CONDVAR("tick_counter",           TimerGameTick::counter,           SLE_UINT64,                  SLV_U64_TICK_COUNTER, SL_MAX_VERSION),
 
	SLEG_CONDVAR("economy_date",           TimerGameEconomy::date,           SLE_INT32,                   SLV_ECONOMY_DATE, SL_MAX_VERSION),
 
	SLEG_CONDVAR("economy_date_fract",     TimerGameEconomy::date_fract,     SLE_UINT16,                  SLV_ECONOMY_DATE, SL_MAX_VERSION),
 
	SLEG_CONDVAR("calendar_sub_date_fract", TimerGameCalendar::sub_date_fract, SLE_UINT16,                SLV_CALENDAR_SUB_DATE_FRACT, SL_MAX_VERSION),
 
	SLEG_CONDVAR("age_cargo_skip_counter", _age_cargo_skip_counter, SLE_UINT8,                   SL_MIN_VERSION, SLV_162),
 
	SLEG_CONDVAR("cur_tileloop_tile",      _cur_tileloop_tile,      SLE_FILE_U16 | SLE_VAR_U32,  SL_MIN_VERSION, SLV_6),
 
	SLEG_CONDVAR("cur_tileloop_tile",      _cur_tileloop_tile,      SLE_UINT32,                  SLV_6, SL_MAX_VERSION),
src/saveload/saveload.h
Show inline comments
 
@@ -370,6 +370,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.
 
	SLV_CALENDAR_SUB_DATE_FRACT,            ///< 328  PR#11428 Add sub_date_fract to measure calendar days.
 

	
 
	SL_MAX_VERSION,                         ///< Highest possible saveload version
 
};
src/settings_gui.cpp
Show inline comments
 
@@ -2213,6 +2213,7 @@ static SettingsContainer &GetSettingsTre
 
			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"));
src/settings_table.cpp
Show inline comments
 
@@ -22,6 +22,7 @@
 
#include "news_func.h"
 
#include "window_func.h"
 
#include "company_func.h"
 
#include "timer/timer_game_calendar.h"
 
#if defined(WITH_FREETYPE) || defined(_WIN32) || defined(WITH_COCOA)
 
#define HAS_TRUETYPE_FONT
 
#include "fontcache.h"
 
@@ -500,10 +501,49 @@ static void ChangeTimekeepingUnits(int32
 
		UpdateAllServiceInterval(0);
 
	}
 

	
 
	/* If we are using calendar timekeeping, "minutes per year" must be default. */
 
	if (!TimerGameEconomy::UsingWallclockUnits(true)) {
 
		_settings_newgame.economy.minutes_per_calendar_year = CalendarTime::DEF_MINUTES_PER_YEAR;
 
	}
 

	
 
	InvalidateWindowClassesData(WC_GAME_OPTIONS, 0);
 
}
 

	
 
/**
 
 * 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 < CalendarTime::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 = CalendarTime::DEF_MINUTES_PER_YEAR;
 
		} else {
 
			clamped = CalendarTime::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 != CalendarTime::DEF_MINUTES_PER_YEAR)) {
 
		_settings_newgame.economy.timekeeping_units = TKU_WALLCLOCK;
 
		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.
src/settings_type.h
Show inline comments
 
@@ -558,6 +558,7 @@ struct EconomySettings {
 
	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
 
	uint16_t minutes_per_calendar_year;      ///< minutes per calendar year. Special value 0 means that calendar time is frozen.
 
};
 

	
 
struct LinkGraphSettings {
src/table/settings/economy_settings.ini
Show inline comments
 
@@ -10,6 +10,7 @@
 
[pre-amble]
 
static void TownFoundingChanged(int32_t new_value);
 
static void ChangeTimekeepingUnits(int32_t new_value);
 
static void ChangeMinutesPerYear(int32_t new_value);
 

	
 
static const SettingVariant _economy_settings_table[] = {
 
[post-amble]
 
@@ -294,3 +295,18 @@ strval   = STR_CONFIG_SETTING_TIMEKEEPIN
 
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 | SF_NO_NETWORK
 
def      = CalendarTime::DEF_MINUTES_PER_YEAR
 
min      = CalendarTime::FROZEN_MINUTES_PER_YEAR
 
max      = CalendarTime::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
src/timer/timer_game_calendar.cpp
Show inline comments
 
@@ -32,6 +32,7 @@ TimerGameCalendar::Year TimerGameCalenda
 
TimerGameCalendar::Month TimerGameCalendar::month = {};
 
TimerGameCalendar::Date TimerGameCalendar::date = {};
 
TimerGameCalendar::DateFract TimerGameCalendar::date_fract = {};
 
uint16_t TimerGameCalendar::sub_date_fract = {};
 

	
 
/**
 
 * Converts a Date to a Year, Month & Day.
 
@@ -93,28 +94,42 @@ void TimeoutTimer<TimerGameCalendar>::El
 
}
 

	
 
template<>
 
void TimerManager<TimerGameCalendar>::Elapsed([[maybe_unused]] TimerGameCalendar::TElapsed delta)
 
bool TimerManager<TimerGameCalendar>::Elapsed([[maybe_unused]] TimerGameCalendar::TElapsed delta)
 
{
 
	assert(delta == 1);
 

	
 
	if (_game_mode == GM_MENU) return;
 
	if (_game_mode == GM_MENU) return false;
 

	
 
	/* If calendar day progress is frozen, don't try to advance time. */
 
	if (_settings_game.economy.minutes_per_calendar_year == CalendarTime::FROZEN_MINUTES_PER_YEAR) return false;
 

	
 
	/* 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 != CalendarTime::DEF_MINUTES_PER_YEAR) {
 
		TimerGameCalendar::sub_date_fract++;
 

	
 
		/* Check if we are ready to increment date_fract */
 
		if (TimerGameCalendar::sub_date_fract < (Ticks::DAY_TICKS * _settings_game.economy.minutes_per_calendar_year) / CalendarTime::DEF_MINUTES_PER_YEAR) return false;
 
	}
 

	
 
	TimerGameCalendar::date_fract++;
 
	if (TimerGameCalendar::date_fract < Ticks::DAY_TICKS) return;
 

	
 
	/* Check if we entered a new day. */
 
	if (TimerGameCalendar::date_fract < Ticks::DAY_TICKS) return true;
 
	TimerGameCalendar::date_fract = 0;
 
	TimerGameCalendar::sub_date_fract = 0;
 

	
 
	/* increase day counter */
 
	/* Increase day counter. */
 
	TimerGameCalendar::date++;
 

	
 
	TimerGameCalendar::YearMonthDay ymd = TimerGameCalendar::ConvertDateToYMD(TimerGameCalendar::date);
 

	
 
	/* check if we entered a new month? */
 
	/* Check if we entered a new month. */
 
	bool new_month = ymd.month != TimerGameCalendar::month;
 

	
 
	/* check if we entered a new year? */
 
	/* Check if we entered a new year. */
 
	bool new_year = ymd.year != TimerGameCalendar::year;
 

	
 
	/* update internal variables before calling the daily/monthly/yearly loops */
 
	/* Update internal variables before calling the daily/monthly/yearly loops. */
 
	TimerGameCalendar::month = ymd.month;
 
	TimerGameCalendar::year = ymd.year;
 

	
 
@@ -137,7 +152,7 @@ void TimerManager<TimerGameCalendar>::El
 
		}
 
	}
 

	
 
	/* check if we reached the maximum year, decrement dates by a year */
 
	/* If we reached the maximum year, decrement dates by a year. */
 
	if (TimerGameCalendar::year == CalendarTime::MAX_YEAR + 1) {
 
		int days_this_year;
 

	
 
@@ -145,6 +160,8 @@ void TimerManager<TimerGameCalendar>::El
 
		days_this_year = TimerGameCalendar::IsLeapYear(TimerGameCalendar::year) ? CalendarTime::DAYS_IN_LEAP_YEAR : CalendarTime::DAYS_IN_YEAR;
 
		TimerGameCalendar::date -= days_this_year;
 
	}
 

	
 
	return true;
 
}
 

	
 
#ifdef WITH_ASSERT
src/timer/timer_game_calendar.h
Show inline comments
 
@@ -33,6 +33,7 @@ public:
 
	static Month month; ///< Current month (0..11).
 
	static Date date; ///< Current date in days (day counter).
 
	static DateFract date_fract; ///< Fractional part of the day.
 
	static uint16_t sub_date_fract; ///< Subpart of date_fract that we use when calendar days are slower than economy days.
 

	
 
	static YearMonthDay ConvertDateToYMD(Date date);
 
	static Date ConvertYMDToDate(Year year, Month month, Day day);
 
@@ -42,6 +43,11 @@ public:
 
/**
 
 * Storage class for Calendar time constants.
 
 */
 
class CalendarTime : public TimerGameConst<struct Calendar> {};
 
class CalendarTime : public TimerGameConst<struct Calendar> {
 
public:
 
	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.
 
};
 

	
 
#endif /* TIMER_GAME_CALENDAR_H */
src/timer/timer_game_economy.cpp
Show inline comments
 
@@ -121,14 +121,14 @@ void TimeoutTimer<TimerGameEconomy>::Ela
 
}
 

	
 
template<>
 
void TimerManager<TimerGameEconomy>::Elapsed([[maybe_unused]] TimerGameEconomy::TElapsed delta)
 
bool TimerManager<TimerGameEconomy>::Elapsed([[maybe_unused]] TimerGameEconomy::TElapsed delta)
 
{
 
	assert(delta == 1);
 

	
 
	if (_game_mode == GM_MENU) return;
 
	if (_game_mode == GM_MENU) return false;
 

	
 
	TimerGameEconomy::date_fract++;
 
	if (TimerGameEconomy::date_fract < Ticks::DAY_TICKS) return;
 
	if (TimerGameEconomy::date_fract < Ticks::DAY_TICKS) return true;
 
	TimerGameEconomy::date_fract = 0;
 

	
 
	/* increase day counter */
 
@@ -187,6 +187,8 @@ void TimerManager<TimerGameEconomy>::Ela
 
		for (Vehicle *v : Vehicle::Iterate()) v->ShiftDates(-days_this_year);
 
		for (LinkGraph *lg : LinkGraph::Iterate()) lg->ShiftDates(-days_this_year);
 
	}
 

	
 
	return true;
 
}
 

	
 
#ifdef WITH_ASSERT
src/timer/timer_game_realtime.cpp
Show inline comments
 
@@ -54,11 +54,13 @@ void TimeoutTimer<TimerGameRealtime>::El
 
}
 

	
 
template<>
 
void TimerManager<TimerGameRealtime>::Elapsed(TimerGameRealtime::TElapsed delta)
 
bool TimerManager<TimerGameRealtime>::Elapsed(TimerGameRealtime::TElapsed delta)
 
{
 
	for (auto timer : TimerManager<TimerGameRealtime>::GetTimers()) {
 
		timer->Elapsed(delta);
 
	}
 

	
 
	return true;
 
}
 

	
 
#ifdef WITH_ASSERT
src/timer/timer_game_tick.cpp
Show inline comments
 
@@ -51,13 +51,15 @@ void TimeoutTimer<TimerGameTick>::Elapse
 
}
 

	
 
template<>
 
void TimerManager<TimerGameTick>::Elapsed(TimerGameTick::TElapsed delta)
 
bool TimerManager<TimerGameTick>::Elapsed(TimerGameTick::TElapsed delta)
 
{
 
	TimerGameTick::counter++;
 

	
 
	for (auto timer : TimerManager<TimerGameTick>::GetTimers()) {
 
		timer->Elapsed(delta);
 
	}
 

	
 
	return true;
 
}
 

	
 
#ifdef WITH_ASSERT
src/timer/timer_manager.h
Show inline comments
 
@@ -78,8 +78,9 @@ public:
 
	 *   Call the Elapsed() method of all active timers.
 
	 *
 
	 * @param value The amount of time that has elapsed.
 
	 * @return True iff time has progressed.
 
	 */
 
	static void Elapsed(TElapsed value);
 
	static bool Elapsed(TElapsed value);
 

	
 
private:
 
	/**
src/timer/timer_window.cpp
Show inline comments
 
@@ -49,7 +49,7 @@ void TimeoutTimer<TimerWindow>::Elapsed(
 
}
 

	
 
template<>
 
void TimerManager<TimerWindow>::Elapsed(TimerWindow::TElapsed delta)
 
bool TimerManager<TimerWindow>::Elapsed(TimerWindow::TElapsed delta)
 
{
 
	/* Make a temporary copy of the timers, as a timer's callback might add/remove other timers. */
 
	auto timers = TimerManager<TimerWindow>::GetTimers();
 
@@ -57,6 +57,8 @@ void TimerManager<TimerWindow>::Elapsed(
 
	for (auto timer : timers) {
 
		timer->Elapsed(delta);
 
	}
 

	
 
	return true;
 
}
 

	
 
#ifdef WITH_ASSERT
0 comments (0 inline, 0 general)