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

OpenTTD Source 14.0-beta3

timer_game_economy.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 <http://www.gnu.org/licenses/>.
6 */
7
26 #include "../stdafx.h"
27 #include "../openttd.h"
28 #include "timer.h"
29 #include "timer_game_economy.h"
30 #include "timer_game_tick.h"
31 #include "../vehicle_base.h"
32 #include "../linkgraph/linkgraph.h"
33
34 #include "../safeguards.h"
35
36 TimerGameEconomy::Year TimerGameEconomy::year = {};
37 TimerGameEconomy::Month TimerGameEconomy::month = {};
38 TimerGameEconomy::Date TimerGameEconomy::date = {};
39 TimerGameEconomy::DateFract TimerGameEconomy::date_fract = {};
40
46 /* static */ TimerGameEconomy::YearMonthDay TimerGameEconomy::ConvertDateToYMD(TimerGameEconomy::Date date)
47 {
48 /* If we're not using wallclock units, we keep the economy date in sync with the calendar. */
49 if (!UsingWallclockUnits()) return CalendarConvertDateToYMD(date);
50
51 /* If we're using wallclock units, economy months have 30 days and an economy year has 360 days. */
52 TimerGameEconomy::YearMonthDay ymd;
53 ymd.year = date.base() / EconomyTime::DAYS_IN_ECONOMY_YEAR;
54 ymd.month = (date.base() % EconomyTime::DAYS_IN_ECONOMY_YEAR) / EconomyTime::DAYS_IN_ECONOMY_MONTH;
55 ymd.day = date.base() % EconomyTime::DAYS_IN_ECONOMY_MONTH;
56 return ymd;
57 }
58
66 /* static */ TimerGameEconomy::Date TimerGameEconomy::ConvertYMDToDate(TimerGameEconomy::Year year, TimerGameEconomy::Month month, TimerGameEconomy::Day day)
67 {
68 /* If we're not using wallclock units, we keep the economy date in sync with the calendar. */
69 if (!UsingWallclockUnits()) return CalendarConvertYMDToDate(year, month, day);
70
71 /* If we're using wallclock units, economy months have 30 days and an economy year has 360 days. */
72 const int total_months = (year.base() * EconomyTime::MONTHS_IN_YEAR) + month;
73 return (total_months * EconomyTime::DAYS_IN_ECONOMY_MONTH) + day - 1; // Day is 1-indexed but Date is 0-indexed, hence the - 1.
74 }
75
81 /* static */ void TimerGameEconomy::SetDate(TimerGameEconomy::Date date, TimerGameEconomy::DateFract fract)
82 {
83 assert(fract < Ticks::DAY_TICKS);
84
85 TimerGameEconomy::date = date;
86 TimerGameEconomy::date_fract = fract;
87 TimerGameEconomy::YearMonthDay ymd = TimerGameEconomy::ConvertDateToYMD(date);
88 TimerGameEconomy::year = ymd.year;
89 TimerGameEconomy::month = ymd.month;
90 }
91
97 /* static */ bool TimerGameEconomy::UsingWallclockUnits(bool newgame)
98 {
99 if (newgame) return (_settings_newgame.economy.timekeeping_units == TKU_WALLCLOCK);
100
101 return (_settings_game.economy.timekeeping_units == TKU_WALLCLOCK);
102 }
103
104 template<>
105 void IntervalTimer<TimerGameEconomy>::Elapsed(TimerGameEconomy::TElapsed trigger)
106 {
107 if (trigger == this->period.trigger) {
108 this->callback(1);
109 }
110 }
111
112 template<>
113 void TimeoutTimer<TimerGameEconomy>::Elapsed(TimerGameEconomy::TElapsed trigger)
114 {
115 if (this->fired) return;
116
117 if (trigger == this->period.trigger) {
118 this->callback();
119 this->fired = true;
120 }
121 }
122
123 template<>
124 bool TimerManager<TimerGameEconomy>::Elapsed([[maybe_unused]] TimerGameEconomy::TElapsed delta)
125 {
126 assert(delta == 1);
127
128 if (_game_mode == GM_MENU) return false;
129
130 TimerGameEconomy::date_fract++;
131 if (TimerGameEconomy::date_fract < Ticks::DAY_TICKS) return true;
132 TimerGameEconomy::date_fract = 0;
133
134 /* increase day counter */
135 TimerGameEconomy::date++;
136
137 TimerGameEconomy::YearMonthDay ymd = TimerGameEconomy::ConvertDateToYMD(TimerGameEconomy::date);
138
139 /* check if we entered a new month? */
140 bool new_month = ymd.month != TimerGameEconomy::month;
141
142 /* check if we entered a new year? */
143 bool new_year = ymd.year != TimerGameEconomy::year;
144
145 /* update internal variables before calling the daily/monthly/yearly loops */
146 TimerGameEconomy::month = ymd.month;
147 TimerGameEconomy::year = ymd.year;
148
149 /* Make a temporary copy of the timers, as a timer's callback might add/remove other timers. */
150 auto timers = TimerManager<TimerGameEconomy>::GetTimers();
151
152 for (auto timer : timers) {
153 timer->Elapsed(TimerGameEconomy::DAY);
154 }
155
156 if ((TimerGameEconomy::date.base() % 7) == 3) {
157 for (auto timer : timers) {
158 timer->Elapsed(TimerGameEconomy::WEEK);
159 }
160 }
161
162 if (new_month) {
163 for (auto timer : timers) {
164 timer->Elapsed(TimerGameEconomy::MONTH);
165 }
166
167 if ((TimerGameEconomy::month % 3) == 0) {
168 for (auto timer : timers) {
169 timer->Elapsed(TimerGameEconomy::QUARTER);
170 }
171 }
172 }
173
174 if (new_year) {
175 for (auto timer : timers) {
176 timer->Elapsed(TimerGameEconomy::YEAR);
177 }
178 }
179
180 /* check if we reached the maximum year, decrement dates by a year */
181 if (TimerGameEconomy::year == EconomyTime::MAX_YEAR + 1) {
182 int days_this_year;
183
184 TimerGameEconomy::year--;
185 days_this_year = TimerGameEconomy::IsLeapYear(TimerGameEconomy::year) ? EconomyTime::DAYS_IN_LEAP_YEAR : EconomyTime::DAYS_IN_YEAR;
186 TimerGameEconomy::date -= days_this_year;
187 for (Vehicle *v : Vehicle::Iterate()) v->ShiftDates(-days_this_year);
188 for (LinkGraph *lg : LinkGraph::Iterate()) lg->ShiftDates(-days_this_year);
189 }
190
191 return true;
192 }
193
194 #ifdef WITH_ASSERT
195 template<>
196 void TimerManager<TimerGameEconomy>::Validate(TimerGameEconomy::TPeriod period)
197 {
198 if (period.priority == TimerGameEconomy::Priority::NONE) return;
199
200 /* Validate we didn't make a developer error and scheduled more than one
201 * entry on the same priority/trigger. There can only be one timer on
202 * a specific trigger/priority, to ensure we are deterministic. */
203 for (const auto &timer : TimerManager<TimerGameEconomy>::GetTimers()) {
204 if (timer->period.trigger != period.trigger) continue;
205
206 assert(timer->period.priority != period.priority);
207 }
208 }
209 #endif /* WITH_ASSERT */
LinkGraph
A connected component of a link graph.
Definition: linkgraph.h:37
TimerManager::GetTimers
static std::set< BaseTimer< TTimerType > *, base_timer_sorter > & GetTimers()
Singleton list, to store all the active timers.
Definition: timer_manager.h:101
TimerGameEconomy::ConvertYMDToDate
static Date ConvertYMDToDate(Year year, Month month, Day day)
Converts a tuple of Year, Month and Day to a Date.
Definition: timer_game_economy.cpp:66
TimerGameEconomy::month
static Month month
Current month (0..11).
Definition: timer_game_economy.h:36
EconomySettings::timekeeping_units
TimekeepingUnits timekeeping_units
time units to use for the game economy, either calendar or wallclock
Definition: settings_type.h:561
TimerGameEconomy::date_fract
static DateFract date_fract
Fractional part of the day.
Definition: timer_game_economy.h:38
TimerGameEconomy::UsingWallclockUnits
static bool UsingWallclockUnits(bool newgame=false)
Check if we are using wallclock units.
Definition: timer_game_economy.cpp:97
Vehicle
Vehicle data structure.
Definition: vehicle_base.h:240
TimerGameConst< struct Economy >::DAYS_IN_LEAP_YEAR
static constexpr int DAYS_IN_LEAP_YEAR
sometimes, you need one day more...
Definition: timer_game_common.h:150
EconomyTime::DAYS_IN_ECONOMY_YEAR
static constexpr int DAYS_IN_ECONOMY_YEAR
Days in an economy year, when in wallclock timekeeping mode.
Definition: timer_game_economy.h:51
TimeoutTimer::Elapsed
void Elapsed(TElapsed count) override
Called by the timer manager to notify the timer that the given amount of time has elapsed.
IntervalTimer::Elapsed
void Elapsed(TElapsed count) override
Called by the timer manager to notify the timer that the given amount of time has elapsed.
_settings_game
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Definition: settings.cpp:55
timer_game_tick.h
GameSettings::economy
EconomySettings economy
settings to change the economy
Definition: settings_type.h:628
timer.h
TimerManager
The TimerManager manages a single Timer-type.
Definition: timer_manager.h:27
TimerGameConst< struct Economy >::MAX_YEAR
static constexpr TimerGame< struct Economy >::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
TimerManager::Elapsed
static bool Elapsed(TElapsed value)
Called when time for this timer elapsed.
TimerGameEconomy::ConvertDateToYMD
static YearMonthDay ConvertDateToYMD(Date date)
Converts a Date to a Year, Month & Day.
Definition: timer_game_economy.cpp:46
Pool::PoolItem<&_vehicle_pool >::Iterate
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
Definition: pool_type.hpp:384
TimerGameEconomy::year
static Year year
Current year, starting at 0.
Definition: timer_game_economy.h:35
TimerGameConst< struct Economy >::MONTHS_IN_YEAR
static constexpr int MONTHS_IN_YEAR
months per year
Definition: timer_game_common.h:151
TimerGame< struct Economy >::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:124
TimerGame< struct Economy >::IsLeapYear
static constexpr bool IsLeapYear(Year year)
Checks whether the given year is a leap year or not.
Definition: timer_game_common.h:63
TimerGameEconomy::SetDate
static void SetDate(Date date, DateFract fract)
Set the date.
Definition: timer_game_economy.cpp:81
TimerGame< struct Economy >::DateFract
uint16_t DateFract
The fraction of a date we're in, i.e.
Definition: timer_game_common.h:38
TimerGame< struct Economy >::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
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:48
EconomyTime::DAYS_IN_ECONOMY_MONTH
static constexpr int DAYS_IN_ECONOMY_MONTH
Days in an economy month, when in wallclock timekeeping mode.
Definition: timer_game_economy.h:52
TimerGameConst< struct Economy >::DAYS_IN_YEAR
static constexpr int DAYS_IN_YEAR
days per year
Definition: timer_game_common.h:149
TimerGame< struct Economy >::CalendarConvertDateToYMD
static YearMonthDay CalendarConvertDateToYMD(Date date)
Converts a Date to a Year, Month & Day.
Definition: timer_game_common.cpp:66
TimerGame< struct Economy >::Month
uint8_t Month
Type for the month, note: 0 based, i.e.
Definition: timer_game_common.h:44
timer_game_economy.h
_settings_newgame
GameSettings _settings_newgame
Game settings for new games (updated from the intro screen).
Definition: settings.cpp:56
TimerGameEconomy::date
static Date date
Current date in days (day counter).
Definition: timer_game_economy.h:37