OpenTTD Source: src/timer/timer_game_calendar.cpp Source File

OpenTTD Source 15.0-RC2

timer_game_calendar.cpp
Go to the documentation of this file.
1/*
2 * This file is part of OpenTTD.
3 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
6 */
7
23#include "../stdafx.h"
24#include "../openttd.h"
25#include "timer.h"
26#include "timer_game_calendar.h"
27#include "../vehicle_base.h"
28
29#include "../safeguards.h"
30
31 TimerGameCalendar::Year TimerGameCalendar::year = {};
32 TimerGameCalendar::Month TimerGameCalendar::month = {};
33 TimerGameCalendar::Date TimerGameCalendar::date = {};
34 TimerGameCalendar::DateFract TimerGameCalendar::date_fract = {};
35uint16_t TimerGameCalendar::sub_date_fract = {};
36
42/* static */ TimerGameCalendar::YearMonthDay TimerGameCalendar::ConvertDateToYMD(TimerGameCalendar::Date date)
43{
44 /* This wrapper function only exists because economy time sometimes does things differently, when using wallclock units. */
45 return CalendarConvertDateToYMD(date);
46}
47
55/* static */ TimerGameCalendar::Date TimerGameCalendar::ConvertYMDToDate(TimerGameCalendar::Year year, TimerGameCalendar::Month month, TimerGameCalendar::Day day)
56{
57 /* This wrapper function only exists because economy time sometimes does things differently, when using wallclock units. */
58 return CalendarConvertYMDToDate(year, month, day);
59}
60
66/* static */ void TimerGameCalendar::SetDate(TimerGameCalendar::Date date, TimerGameCalendar::DateFract fract)
67{
68 assert(fract < Ticks::DAY_TICKS);
69
70 TimerGameCalendar::date = date;
71 TimerGameCalendar::date_fract = fract;
72 TimerGameCalendar::YearMonthDay ymd = TimerGameCalendar::ConvertDateToYMD(date);
73 TimerGameCalendar::year = TimerGameCalendar::Year{ymd.year};
74 TimerGameCalendar::month = ymd.month;
75}
76
77template <>
78void IntervalTimer<TimerGameCalendar>::Elapsed(TimerGameCalendar::TElapsed trigger)
79{
80 if (trigger == this->period.trigger) {
81 this->callback(1);
82 }
83}
84
85template <>
86void TimeoutTimer<TimerGameCalendar>::Elapsed(TimerGameCalendar::TElapsed trigger)
87{
88 if (this->fired) return;
89
90 if (trigger == this->period.trigger) {
91 this->callback();
92 this->fired = true;
93 }
94}
95
96template <>
97bool TimerManager<TimerGameCalendar>::Elapsed([[maybe_unused]] TimerGameCalendar::TElapsed delta)
98{
99 assert(delta == 1);
100
101 if (_game_mode == GM_MENU) return false;
102
103 /* If calendar day progress is frozen, don't try to advance time. */
104 if (_settings_game.economy.minutes_per_calendar_year == CalendarTime::FROZEN_MINUTES_PER_YEAR) return false;
105
106 /* If we are using a non-default calendar progression speed, we need to check the sub_date_fract before updating date_fract. */
107 if (_settings_game.economy.minutes_per_calendar_year != CalendarTime::DEF_MINUTES_PER_YEAR) {
108 TimerGameCalendar::sub_date_fract += Ticks::DAY_TICKS;
109
110 /* Check if we are ready to increment date_fract */
111 const uint16_t threshold = (_settings_game.economy.minutes_per_calendar_year * Ticks::DAY_TICKS) / CalendarTime::DEF_MINUTES_PER_YEAR;
112 if (TimerGameCalendar::sub_date_fract < threshold) return false;
113
114 TimerGameCalendar::sub_date_fract = std::min<uint16_t>(TimerGameCalendar::sub_date_fract - threshold, Ticks::DAY_TICKS - 1);
115 }
116
117 TimerGameCalendar::date_fract++;
118
119 /* Check if we entered a new day. */
120 if (TimerGameCalendar::date_fract < Ticks::DAY_TICKS) return true;
121 TimerGameCalendar::date_fract = 0;
122 TimerGameCalendar::sub_date_fract = 0;
123
124 /* Increase day counter. */
125 TimerGameCalendar::date++;
126
127 TimerGameCalendar::YearMonthDay ymd = TimerGameCalendar::ConvertDateToYMD(TimerGameCalendar::date);
128
129 /* Check if we entered a new month. */
130 bool new_month = ymd.month != TimerGameCalendar::month;
131
132 /* Check if we entered a new year. */
133 bool new_year = ymd.year != TimerGameCalendar::year;
134
135 /* Update internal variables before calling the daily/monthly/yearly loops. */
136 TimerGameCalendar::month = ymd.month;
137 TimerGameCalendar::year = ymd.year;
138
139 /* Make a temporary copy of the timers, as a timer's callback might add/remove other timers. */
140 auto timers = TimerManager<TimerGameCalendar>::GetTimers();
141
142 for (auto timer : timers) {
143 timer->Elapsed(TimerGameCalendar::DAY);
144 }
145
146 if (new_month) {
147 for (auto timer : timers) {
148 timer->Elapsed(TimerGameCalendar::MONTH);
149 }
150 }
151
152 if (new_year) {
153 for (auto timer : timers) {
154 timer->Elapsed(TimerGameCalendar::YEAR);
155 }
156 }
157
158 /* If we reached the maximum year, decrement dates by a year. */
159 if (TimerGameCalendar::year == CalendarTime::MAX_YEAR + 1) {
160 TimerGameCalendar::year--;
161 TimerGameCalendar::Date days_this_year{TimerGameCalendar::IsLeapYear(TimerGameCalendar::year) ? CalendarTime::DAYS_IN_LEAP_YEAR : CalendarTime::DAYS_IN_YEAR};
162 TimerGameCalendar::date -= days_this_year;
163 }
164
165 return true;
166}
167
168#ifdef WITH_ASSERT
169template <>
170void TimerManager<TimerGameCalendar>::Validate(TimerGameCalendar::TPeriod period)
171{
172 if (period.priority == TimerGameCalendar::Priority::NONE) return;
173
174 /* Validate we didn't make a developer error and scheduled more than one
175 * entry on the same priority/trigger. There can only be one timer on
176 * a specific trigger/priority, to ensure we are deterministic. */
177 for (const auto &timer : TimerManager<TimerGameCalendar>::GetTimers()) {
178 if (timer->period.trigger != period.trigger) continue;
179
180 assert(timer->period.priority != period.priority);
181 }
182}
183#endif /* WITH_ASSERT */
IntervalTimer::Elapsed
void Elapsed(TElapsed count) override
Called by the timer manager to notify the timer that the given amount of time has elapsed.
Ticks::DAY_TICKS
static constexpr TimerGameTick::Ticks DAY_TICKS
1 day is 74 ticks; TimerGameCalendar::date_fract used to be uint16_t and incremented by 885.
Definition timer_game_tick.h:75
TimeoutTimer::Elapsed
void Elapsed(TElapsed count) override
Called by the timer manager to notify the timer that the given amount of time has elapsed.
TimerGameCalendar
Timer that is increased every 27ms, and counts towards ticks / days / months / years.
Definition timer_game_calendar.h:28
TimerGameCalendar::sub_date_fract
static uint16_t sub_date_fract
Subpart of date_fract that we use when calendar days are slower than economy days.
Definition timer_game_calendar.h:35
TimerGameCalendar::month
static Month month
Current month (0..11).
Definition timer_game_calendar.h:32
TimerGameCalendar::ConvertYMDToDate
static Date ConvertYMDToDate(Year year, Month month, Day day)
Converts a tuple of Year, Month and Day to a Date.
Definition timer_game_calendar.cpp:55
TimerGameCalendar::ConvertDateToYMD
static YearMonthDay ConvertDateToYMD(Date date)
Converts a Date to a Year, Month & Day.
Definition timer_game_calendar.cpp:42
TimerGameCalendar::SetDate
static void SetDate(Date date, DateFract fract)
Set the date.
Definition timer_game_calendar.cpp:66
TimerGameCalendar::date
static Date date
Current date in days (day counter).
Definition timer_game_calendar.h:33
TimerGameCalendar::year
static Year year
Current year, starting at 0.
Definition timer_game_calendar.h:31
TimerGameCalendar::date_fract
static DateFract date_fract
Fractional part of the day.
Definition timer_game_calendar.h:34
TimerGameConst< struct Calendar >::DAYS_IN_YEAR
static constexpr int DAYS_IN_YEAR
days per year
Definition timer_game_common.h:149
TimerGameConst< struct Calendar >::MAX_YEAR
static constexpr TimerGame< struct Calendar >::Year MAX_YEAR
MAX_YEAR, nicely rounded value of the number of years that can be encoded in a single 32 bits date,...
Definition timer_game_common.h:173
TimerGameConst< struct Calendar >::DAYS_IN_LEAP_YEAR
static constexpr int DAYS_IN_LEAP_YEAR
sometimes, you need one day more...
Definition timer_game_common.h:150
TimerGame< struct Calendar >::CalendarConvertDateToYMD
static YearMonthDay CalendarConvertDateToYMD(Date date)
Converts a Date to a Year, Month & Day.
Definition timer_game_common.cpp:64
TimerGame< struct Calendar >::DateFract
uint16_t DateFract
The fraction of a date we're in, i.e.
Definition timer_game_common.h:38
TimerGame< struct Calendar >::CalendarConvertYMDToDate
static Date CalendarConvertYMDToDate(Year year, Month month, Day day)
Converts a tuple of Year, Month and Day to a Date.
Definition timer_game_common.cpp:122
TimerGame< struct Calendar >::Day
uint8_t Day
Type for the day of the month, note: 1 based, first day of a month is 1.
Definition timer_game_common.h:46
TimerGame< struct Calendar >::Month
uint8_t Month
Type for the month, note: 0 based, i.e.
Definition timer_game_common.h:44
TimerGame< struct Calendar >::IsLeapYear
static constexpr bool IsLeapYear(Year year)
Checks whether the given year is a leap year or not.
Definition timer_game_common.h:63
TimerManager
The TimerManager manages a single Timer-type.
Definition timer_manager.h:25
TimerManager::GetTimers
static std::set< BaseTimer< TTimerType > *, base_timer_sorter > & GetTimers()
Singleton list, to store all the active timers.
Definition timer_manager.h:113
TimerManager::Elapsed
static bool Elapsed(TElapsed value)
Called when time for this timer elapsed.
_settings_game
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Definition settings.cpp:61
EconomySettings::minutes_per_calendar_year
uint16_t minutes_per_calendar_year
minutes per calendar year. Special value 0 means that calendar time is frozen.
Definition settings_type.h:565
GameSettings::economy
EconomySettings economy
settings to change the economy
Definition settings_type.h:642
StrongType::Typedef
Templated helper to make a type-safe 'typedef' representing a single POD value.
Definition strong_typedef_type.hpp:130
timer.h
Definition of Interval and OneShot timers.
timer_game_calendar.h
Definition of the game-calendar-timer.