OpenTTD Source  20240917-master-g9ab0a47812
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 = {};
38 TimerGameEconomy::Date TimerGameEconomy::date = {};
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. */
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;
55  ymd.day = (date.base() % EconomyTime::DAYS_IN_ECONOMY_MONTH) + 1;
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. */
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 
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 
133 
134  /* increase day counter */
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. */
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 */
182  int days_this_year;
183 
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:115
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:536
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:244
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:57
timer_game_tick.h
GameSettings::economy
EconomySettings economy
settings to change the economy
Definition: settings_type.h:603
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:388
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:75
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:58
TimerGameEconomy::date
static Date date
Current date in days (day counter).
Definition: timer_game_economy.h:37