Split date types into calendar and economy dates

See: 735abfe1
pull/661/head
Jonathan G Rennison 3 months ago
parent fad5ee56e7
commit 7ce06e22b8

@ -357,9 +357,9 @@ CommandCost CmdBuildAircraft(TileIndex tile, DoCommandFlag flags, const Engine *
v->SetServiceInterval(Company::Get(_current_company)->settings.vehicle.servint_aircraft); v->SetServiceInterval(Company::Get(_current_company)->settings.vehicle.servint_aircraft);
v->date_of_last_service = _date; v->date_of_last_service = EconTime::CurDate();
v->date_of_last_service_newgrf = _date; v->date_of_last_service_newgrf = CalTime::CurDate();
v->build_year = u->build_year = _cur_year; v->build_year = u->build_year = CalTime::CurYear();
v->sprite_seq.Set(SPR_IMG_QUERY); v->sprite_seq.Set(SPR_IMG_QUERY);
u->sprite_seq.Set(SPR_IMG_QUERY); u->sprite_seq.Set(SPR_IMG_QUERY);
@ -1669,8 +1669,8 @@ static void AircraftEventHandler_AtTerminal(Aircraft *v, const AirportFTAClass *
if (_settings_game.order.serviceathelipad) { if (_settings_game.order.serviceathelipad) {
if (v->subtype == AIR_HELICOPTER && apc->num_helipads > 0) { if (v->subtype == AIR_HELICOPTER && apc->num_helipads > 0) {
/* an excerpt of ServiceAircraft, without the invisibility stuff */ /* an excerpt of ServiceAircraft, without the invisibility stuff */
v->date_of_last_service = _date; v->date_of_last_service = EconTime::CurDate();
v->date_of_last_service_newgrf = _date; v->date_of_last_service_newgrf = CalTime::CurDate();
v->breakdowns_since_last_service = 0; v->breakdowns_since_last_service = 0;
v->reliability = v->GetEngine()->reliability; v->reliability = v->GetEngine()->reliability;
SetWindowDirty(WC_VEHICLE_DETAILS, v->index); SetWindowDirty(WC_VEHICLE_DETAILS, v->index);

@ -74,7 +74,7 @@ struct BaseStation : StationPool::PoolItem<&_station_pool> {
TinyString name; ///< Custom name TinyString name; ///< Custom name
StringID string_id; ///< Default name (town area) of station StringID string_id; ///< Default name (town area) of station
Date build_date; ///< Date of construction CalTime::Date build_date; ///< Date of construction
Town *town; ///< The town this station is associated with Town *town; ///< The town this station is associated with

@ -62,7 +62,7 @@ enum BridgeSpecCtrlFlags {
* Struct containing information about a single bridge type * Struct containing information about a single bridge type
*/ */
struct BridgeSpec { struct BridgeSpec {
Year avail_year; ///< the year where it becomes available CalTime::Year avail_year; ///< the year where it becomes available
byte min_length; ///< the minimum length (not counting start and end tile) byte min_length; ///< the minimum length (not counting start and end tile)
uint16_t max_length; ///< the maximum length (not counting start and end tile) uint16_t max_length; ///< the maximum length (not counting start and end tile)
uint16_t price; ///< the price multiplier uint16_t price; ///< the price multiplier

@ -1120,7 +1120,7 @@ void TestedEngineDetails::FillDefaultCapacities(const Engine *e)
int DrawVehiclePurchaseInfo(int left, int right, int y, EngineID engine_number, TestedEngineDetails &te) int DrawVehiclePurchaseInfo(int left, int right, int y, EngineID engine_number, TestedEngineDetails &te)
{ {
const Engine *e = Engine::Get(engine_number); const Engine *e = Engine::Get(engine_number);
YearMonthDay ymd = ConvertDateToYMD(e->intro_date); CalTime::YearMonthDay ymd = CalTime::ConvertDateToYMD(e->intro_date);
bool refittable = IsArticulatedVehicleRefittable(engine_number); bool refittable = IsArticulatedVehicleRefittable(engine_number);
bool articulated_cargo = false; bool articulated_cargo = false;
@ -1168,7 +1168,7 @@ int DrawVehiclePurchaseInfo(int left, int right, int y, EngineID engine_number,
if (e->type != VEH_TRAIN || e->u.rail.railveh_type != RAILVEH_WAGON) { if (e->type != VEH_TRAIN || e->u.rail.railveh_type != RAILVEH_WAGON) {
/* Design date - Life length */ /* Design date - Life length */
SetDParam(0, ymd.year); SetDParam(0, ymd.year);
SetDParam(1, DateDeltaToYears(e->GetLifeLengthInDays())); SetDParam(1, DateDeltaToYearDelta(e->GetLifeLengthInDays()));
DrawString(left, right, y, STR_PURCHASE_INFO_DESIGNED_LIFE); DrawString(left, right, y, STR_PURCHASE_INFO_DESIGNED_LIFE);
y += GetCharacterHeight(FS_NORMAL); y += GetCharacterHeight(FS_NORMAL);

@ -105,19 +105,25 @@ extern void EnginesMonthlyLoop();
static int32_t ClickChangeDateCheat(int32_t p1, int32_t p2) static int32_t ClickChangeDateCheat(int32_t p1, int32_t p2)
{ {
/* Don't allow changing to an invalid year, or the current year. */ /* Don't allow changing to an invalid year, or the current year. */
p1 = Clamp(p1, MIN_YEAR, MAX_YEAR); p1 = Clamp(p1, CalTime::MIN_YEAR.base(), CalTime::MAX_YEAR.base());
if (p1 == _cur_year) return _cur_year; if (p1 == CalTime::CurYear()) return CalTime::CurYear().base();
YearMonthDay ymd = ConvertDateToYMD(_date); CalTime::Date new_date = CalTime::ConvertYMDToDate(p1, CalTime::CurMonth(), CalTime::CurDay());
Date new_date = ConvertYMDToDate(p1, ymd.month, ymd.day);
/* Shift cached dates. */
LinkGraphSchedule::instance.ShiftDates(new_date - _date);
ShiftOrderDates(new_date - _date);
ShiftVehicleDates(new_date - _date);
/* Change the date. */ /* Change the date. */
SetDate(new_date, _date_fract); CalTime::Detail::SetDate(new_date, CalTime::CurDateFract());
{
EconTime::Date new_econ_date = new_date.base();
EconTime::DateFract new_econ_date_fract = CalTime::CurDateFract();
/* Shift cached dates. */
LinkGraphSchedule::instance.ShiftDates(new_econ_date - EconTime::CurDate());
ShiftVehicleDates(new_econ_date - EconTime::CurDate());
EconTime::Detail::SetDate(new_econ_date, new_econ_date_fract);
UpdateOrderUIOnDateChange();
}
EnginesMonthlyLoop(); EnginesMonthlyLoop();
InvalidateWindowClassesData(WC_BUILD_STATION, 0); InvalidateWindowClassesData(WC_BUILD_STATION, 0);
@ -125,7 +131,7 @@ static int32_t ClickChangeDateCheat(int32_t p1, int32_t p2)
InvalidateWindowClassesData(WC_BUILD_OBJECT, 0); InvalidateWindowClassesData(WC_BUILD_OBJECT, 0);
ResetSignalVariant(); ResetSignalVariant();
MarkWholeScreenDirty(); MarkWholeScreenDirty();
return _cur_year; return CalTime::CurYear().base();
} }
/** /**
@ -194,7 +200,7 @@ static const CheatEntry _cheats_ui[] = {
{CNM_ALL, SLE_BOOL, STR_CHEAT_NO_JETCRASH, &_cheats.no_jetcrash.value, &_cheats.no_jetcrash.been_used, nullptr }, {CNM_ALL, SLE_BOOL, STR_CHEAT_NO_JETCRASH, &_cheats.no_jetcrash.value, &_cheats.no_jetcrash.been_used, nullptr },
{CNM_LOCAL_ONLY, SLE_BOOL, STR_CHEAT_SETUP_PROD, &_cheats.setup_prod.value, &_cheats.setup_prod.been_used, &ClickSetProdCheat }, {CNM_LOCAL_ONLY, SLE_BOOL, STR_CHEAT_SETUP_PROD, &_cheats.setup_prod.value, &_cheats.setup_prod.been_used, &ClickSetProdCheat },
{CNM_LOCAL_ONLY, SLE_UINT8, STR_CHEAT_EDIT_MAX_HL, &_settings_game.construction.map_height_limit, &_cheats.edit_max_hl.been_used, &ClickChangeMaxHlCheat }, {CNM_LOCAL_ONLY, SLE_UINT8, STR_CHEAT_EDIT_MAX_HL, &_settings_game.construction.map_height_limit, &_cheats.edit_max_hl.been_used, &ClickChangeMaxHlCheat },
{CNM_LOCAL_ONLY, SLE_INT32, STR_CHEAT_CHANGE_DATE, &_cur_date_ymd.year, &_cheats.change_date.been_used, &ClickChangeDateCheat }, {CNM_LOCAL_ONLY, SLE_INT32, STR_CHEAT_CHANGE_DATE, &CalTime::Detail::now.cal_ymd.year, &_cheats.change_date.been_used, &ClickChangeDateCheat },
{CNM_ALL, SLF_ALLOW_CONTROL, STR_CHEAT_INFLATION_COST, &_economy.inflation_prices, &_cheats.inflation_cost.been_used, nullptr }, {CNM_ALL, SLF_ALLOW_CONTROL, STR_CHEAT_INFLATION_COST, &_economy.inflation_prices, &_cheats.inflation_cost.been_used, nullptr },
{CNM_ALL, SLF_ALLOW_CONTROL, STR_CHEAT_INFLATION_INCOME, &_economy.inflation_payment, &_cheats.inflation_income.been_used, nullptr }, {CNM_ALL, SLF_ALLOW_CONTROL, STR_CHEAT_INFLATION_INCOME, &_economy.inflation_payment, &_cheats.inflation_income.been_used, nullptr },
{CNM_ALL, SLE_BOOL, STR_CHEAT_STATION_RATING, &_cheats.station_rating.value, &_cheats.station_rating.been_used, nullptr }, {CNM_ALL, SLE_BOOL, STR_CHEAT_STATION_RATING, &_cheats.station_rating.value, &_cheats.station_rating.been_used, nullptr },
@ -304,7 +310,7 @@ struct CheatWindow : Window {
switch (ce->str) { switch (ce->str) {
/* Display date for change date cheat */ /* Display date for change date cheat */
case STR_CHEAT_CHANGE_DATE: SetDParam(0, _date); break; case STR_CHEAT_CHANGE_DATE: SetDParam(0, CalTime::CurDate()); break;
/* Draw coloured flag for change company cheat */ /* Draw coloured flag for change company cheat */
case STR_CHEAT_CHANGE_COMPANY: { case STR_CHEAT_CHANGE_COMPANY: {
@ -352,7 +358,7 @@ struct CheatWindow : Window {
switch (ce->str) { switch (ce->str) {
/* Display date for change date cheat */ /* Display date for change date cheat */
case STR_CHEAT_CHANGE_DATE: case STR_CHEAT_CHANGE_DATE:
SetDParam(0, ConvertYMDToDate(MAX_YEAR, 11, 31)); SetDParam(0, CalTime::ConvertYMDToDate(CalTime::MAX_YEAR, 11, 31));
width = std::max(width, GetStringBoundingBox(ce->str).width); width = std::max(width, GetStringBoundingBox(ce->str).width);
break; break;

@ -615,8 +615,8 @@ struct CommandLogEntry {
uint32_t p2; uint32_t p2;
uint32_t cmd; uint32_t cmd;
uint64_t p3; uint64_t p3;
Date date; EconTime::Date date;
DateFract date_fract; EconTime::DateFract date_fract;
uint8_t tick_skip_counter; uint8_t tick_skip_counter;
CompanyID current_company; CompanyID current_company;
CompanyID local_company; CompanyID local_company;
@ -627,7 +627,7 @@ struct CommandLogEntry {
CommandLogEntry() { } CommandLogEntry() { }
CommandLogEntry(TileIndex tile, uint32_t p1, uint32_t p2, uint64_t p3, uint32_t cmd, CommandLogEntryFlag log_flags, std::string text) CommandLogEntry(TileIndex tile, uint32_t p1, uint32_t p2, uint64_t p3, uint32_t cmd, CommandLogEntryFlag log_flags, std::string text)
: text(text), tile(tile), p1(p1), p2(p2), cmd(cmd), p3(p3), date(_date), date_fract(_date_fract), tick_skip_counter(_tick_skip_counter), : text(text), tile(tile), p1(p1), p2(p2), cmd(cmd), p3(p3), date(EconTime::CurDate()), date_fract(EconTime::CurDateFract()), tick_skip_counter(TickSkipCounter()),
current_company(_current_company), local_company(_local_company), log_flags(log_flags), client_id(_cmd_client_id), frame_counter(_frame_counter) { } current_company(_current_company), local_company(_local_company), log_flags(log_flags), client_id(_cmd_client_id), frame_counter(_frame_counter) { }
}; };
@ -669,8 +669,8 @@ static void DumpSubCommandLogEntry(char *&buffer, const char *last, const Comman
return (entry.log_flags & CLEF_SCRIPT_ASYNC) ? 'A' : 'a'; return (entry.log_flags & CLEF_SCRIPT_ASYNC) ? 'A' : 'a';
}; };
YearMonthDay ymd = ConvertDateToYMD(entry.date); EconTime::YearMonthDay ymd = EconTime::ConvertDateToYMD(entry.date);
buffer += seprintf(buffer, last, "%4i-%02i-%02i, %2i, %3i", ymd.year, ymd.month + 1, ymd.day, entry.date_fract, entry.tick_skip_counter); buffer += seprintf(buffer, last, "%4i-%02i-%02i, %2i, %3i", ymd.year.base(), ymd.month + 1, ymd.day, entry.date_fract, entry.tick_skip_counter);
if (_networking) { if (_networking) {
buffer += seprintf(buffer, last, ", %08X", entry.frame_counter); buffer += seprintf(buffer, last, ", %08X", entry.frame_counter);
} }
@ -923,8 +923,9 @@ static void AppendCommandLogEntry(const CommandCost &res, TileIndex tile, uint32
if (_networking && cmd_log.count > 0) { if (_networking && cmd_log.count > 0) {
CommandLogEntry &current = cmd_log.log[(cmd_log.next - 1) % cmd_log.log.size()]; CommandLogEntry &current = cmd_log.log[(cmd_log.next - 1) % cmd_log.log.size()];
if (current.log_flags & CLEF_ONLY_SENDING && ((current.log_flags ^ log_flags) & ~(CLEF_SCRIPT | CLEF_MY_CMD)) == CLEF_ONLY_SENDING && if (current.log_flags & CLEF_ONLY_SENDING && ((current.log_flags ^ log_flags) & ~(CLEF_SCRIPT | CLEF_MY_CMD)) == CLEF_ONLY_SENDING &&
current.tile == tile && current.p1 == p1 && current.p2 == p2 && current.p3 == p3 && ((current.cmd ^ cmd) & ~CMD_NETWORK_COMMAND) == 0 && current.date == _date && current.tile == tile && current.p1 == p1 && current.p2 == p2 && current.p3 == p3 && ((current.cmd ^ cmd) & ~CMD_NETWORK_COMMAND) == 0 &&
current.date_fract == _date_fract && current.tick_skip_counter == _tick_skip_counter && current.date == EconTime::CurDate() && current.date_fract == EconTime::CurDateFract() &&
current.tick_skip_counter == TickSkipCounter() &&
current.frame_counter == _frame_counter && current.frame_counter == _frame_counter &&
current.current_company == _current_company && current.local_company == _local_company) { current.current_company == _current_company && current.local_company == _local_company) {
current.log_flags |= log_flags | CLEF_TWICE; current.log_flags |= log_flags | CLEF_TWICE;

@ -86,7 +86,7 @@ struct CompanyProperties {
std::array<Owner, MAX_COMPANY_SHARE_OWNERS> share_owners; ///< Owners of the shares of the company. #INVALID_OWNER if nobody has bought them yet. std::array<Owner, MAX_COMPANY_SHARE_OWNERS> share_owners; ///< Owners of the shares of the company. #INVALID_OWNER if nobody has bought them yet.
Year inaugurated_year; ///< Year of starting the company. CalTime::Year inaugurated_year; ///< Year of starting the company.
byte months_of_bankruptcy; ///< Number of months that the company is unable to pay its debts byte months_of_bankruptcy; ///< Number of months that the company is unable to pay its debts
CompanyID bankrupt_last_asked; ///< Which company was most recently asked about buying it? CompanyID bankrupt_last_asked; ///< Which company was most recently asked about buying it?

@ -596,7 +596,7 @@ Company *DoStartupNewCompany(DoStartupNewCompanyFlag flags, CompanyID company)
c->avail_railtypes = GetCompanyRailTypes(c->index); c->avail_railtypes = GetCompanyRailTypes(c->index);
c->avail_roadtypes = GetCompanyRoadTypes(c->index); c->avail_roadtypes = GetCompanyRoadTypes(c->index);
c->inaugurated_year = _cur_year; c->inaugurated_year = CalTime::CurYear();
/* If starting a player company in singleplayer and a favorite company manager face is selected, choose it. Otherwise, use a random face. /* If starting a player company in singleplayer and a favorite company manager face is selected, choose it. Otherwise, use a random face.
* In a network game, we'll choose the favorite face later in CmdCompanyCtrl to sync it to all clients. */ * In a network game, we'll choose the favorite face later in CmdCompanyCtrl to sync it to all clients. */

@ -420,10 +420,10 @@ struct CompanyFinancesWindow : Window {
case WID_CF_EXPS_PRICE2: case WID_CF_EXPS_PRICE2:
case WID_CF_EXPS_PRICE3: { case WID_CF_EXPS_PRICE3: {
const Company *c = Company::Get((CompanyID)this->window_number); const Company *c = Company::Get((CompanyID)this->window_number);
int age = std::min(_cur_year - c->inaugurated_year, 2); YearDelta age = std::min<YearDelta>(CalTime::CurYear() - c->inaugurated_year, 2);
int wid_offset = widget - WID_CF_EXPS_PRICE1; int wid_offset = widget - WID_CF_EXPS_PRICE1;
if (wid_offset <= age) { if (wid_offset <= age.base()) {
DrawYearColumn(r, _cur_year - (age - wid_offset), c->yearly_expenses[age - wid_offset]); DrawYearColumn(r, CalTime::CurYear().base() - (age.base() - wid_offset), c->yearly_expenses[age.base() - wid_offset]);
} }
break; break;
} }
@ -1859,7 +1859,7 @@ struct CompanyInfrastructureWindow : Window
} }
/* Get the date introduced railtypes as well. */ /* Get the date introduced railtypes as well. */
this->railtypes = AddDateIntroducedRailTypes(this->railtypes, MAX_DATE); this->railtypes = AddDateIntroducedRailTypes(this->railtypes, CalTime::MAX_DATE);
/* Find the used roadtypes. */ /* Find the used roadtypes. */
for (const Engine *e : Engine::IterateType(VEH_ROAD)) { for (const Engine *e : Engine::IterateType(VEH_ROAD)) {
@ -1869,7 +1869,7 @@ struct CompanyInfrastructureWindow : Window
} }
/* Get the date introduced roadtypes as well. */ /* Get the date introduced roadtypes as well. */
this->roadtypes = AddDateIntroducedRoadTypes(this->roadtypes, MAX_DATE); this->roadtypes = AddDateIntroducedRoadTypes(this->roadtypes, CalTime::MAX_DATE);
this->roadtypes &= ~_roadtypes_hidden_mask; this->roadtypes &= ~_roadtypes_hidden_mask;
} }

@ -1596,7 +1596,7 @@ DEF_CONSOLE_CMD(ConGetDate)
return true; return true;
} }
IConsolePrintF(CC_DEFAULT, "Date: %04d-%02d-%02d", _cur_date_ymd.year, _cur_date_ymd.month + 1, _cur_date_ymd.day); IConsolePrintF(CC_DEFAULT, "Date: %04d-%02d-%02d", CalTime::CurYear().base(), CalTime::CurMonth() + 1, CalTime::CurDay());
return true; return true;
} }
@ -1912,7 +1912,7 @@ DEF_CONSOLE_CMD(ConCompanies)
IConsolePrintF(CC_INFO, "#:%d(%s) Company Name: '%s' Year Founded: %d Money: " OTTD_PRINTF64 " Loan: " OTTD_PRINTF64 " Value: " OTTD_PRINTF64 " (T:%d, R:%d, P:%d, S:%d) %s", IConsolePrintF(CC_INFO, "#:%d(%s) Company Name: '%s' Year Founded: %d Money: " OTTD_PRINTF64 " Loan: " OTTD_PRINTF64 " Value: " OTTD_PRINTF64 " (T:%d, R:%d, P:%d, S:%d) %s",
c->index + 1, GetStringPtr(STR_COLOUR_DARK_BLUE + _company_colours[c->index]), company_name.c_str(), c->index + 1, GetStringPtr(STR_COLOUR_DARK_BLUE + _company_colours[c->index]), company_name.c_str(),
c->inaugurated_year, (int64_t)c->money, (int64_t)c->current_loan, (int64_t)CalculateCompanyValue(c), c->inaugurated_year.base(), (int64_t)c->money, (int64_t)c->current_loan, (int64_t)CalculateCompanyValue(c),
c->group_all[VEH_TRAIN].num_vehicle, c->group_all[VEH_TRAIN].num_vehicle,
c->group_all[VEH_ROAD].num_vehicle, c->group_all[VEH_ROAD].num_vehicle,
c->group_all[VEH_AIRCRAFT].num_vehicle, c->group_all[VEH_AIRCRAFT].num_vehicle,
@ -2489,7 +2489,7 @@ DEF_CONSOLE_CMD(ConMergeLinkgraphJobsAsap)
return true; return true;
} }
for (LinkGraphJob *lgj : LinkGraphJob::Iterate()) lgj->ShiftJoinDate((NowDateTicks() - lgj->JoinDateTicks()).base() / DAY_TICKS); for (LinkGraphJob *lgj : LinkGraphJob::Iterate()) lgj->ShiftJoinDate((EconTime::CurDateTicks() - lgj->JoinDateTicks()).base() / DAY_TICKS);
return true; return true;
} }
@ -2562,11 +2562,12 @@ DEF_CONSOLE_CMD(ConRunTileLoopTile)
DEF_CONSOLE_CMD(ConGetFullDate) DEF_CONSOLE_CMD(ConGetFullDate)
{ {
if (argc == 0) { if (argc == 0) {
IConsoleHelp("Returns the current full date (year-month-day, date fract, tick skip, counter) of the game. Usage: 'getfulldate'"); IConsoleHelp("Returns the current full date (year-month-day, date fract, tick skip counter/subtick) of the game. Usage: 'getfulldate'");
return true; return true;
} }
IConsolePrintF(CC_DEFAULT, "Date: %04d-%02d-%02d, %i, %i", _cur_date_ymd.year, _cur_date_ymd.month + 1, _cur_date_ymd.day, _date_fract, _tick_skip_counter); IConsolePrintF(CC_DEFAULT, "Calendar Date: %04d-%02d-%02d, %i, %i", CalTime::CurYear().base(), CalTime::CurMonth() + 1, CalTime::CurDay(), CalTime::CurDateFract(), CalTime::Detail::now.sub_date_fract);
IConsolePrintF(CC_DEFAULT, "Economy Date: %04d-%02d-%02d, %i, %i", EconTime::CurYear().base(), EconTime::CurMonth() + 1, EconTime::CurDay(), EconTime::CurDateFract(), TickSkipCounter());
return true; return true;
} }
@ -2735,12 +2736,12 @@ DEF_CONSOLE_CMD(ConDumpLinkgraphJobs)
IConsolePrintF(CC_DEFAULT, PRINTF_SIZE " link graph jobs", LinkGraphJob::GetNumItems()); IConsolePrintF(CC_DEFAULT, PRINTF_SIZE " link graph jobs", LinkGraphJob::GetNumItems());
for (const LinkGraphJob *lgj : LinkGraphJob::Iterate()) { for (const LinkGraphJob *lgj : LinkGraphJob::Iterate()) {
YearMonthDay start_ymd = ConvertDateToYMD(lgj->StartDateTicks().ToDate()); EconTime::YearMonthDay start_ymd = EconTime::ConvertDateToYMD(lgj->StartDateTicks().ToDate());
YearMonthDay join_ymd = ConvertDateToYMD(lgj->JoinDateTicks().ToDate()); EconTime::YearMonthDay join_ymd = EconTime::ConvertDateToYMD(lgj->JoinDateTicks().ToDate());
IConsolePrintF(CC_DEFAULT, " Job: %5u, nodes: %u, cost: " OTTD_PRINTF64U ", start: (" OTTD_PRINTF64 ", %4i-%02i-%02i, %i), end: (" OTTD_PRINTF64 ", %4i-%02i-%02i, %i), duration: " OTTD_PRINTF64, IConsolePrintF(CC_DEFAULT, " Job: %5u, nodes: %u, cost: " OTTD_PRINTF64U ", start: (" OTTD_PRINTF64 ", %4i-%02i-%02i, %i), end: (" OTTD_PRINTF64 ", %4i-%02i-%02i, %i), duration: " OTTD_PRINTF64,
lgj->index, lgj->Graph().Size(), lgj->Graph().CalculateCostEstimate(), lgj->index, lgj->Graph().Size(), lgj->Graph().CalculateCostEstimate(),
lgj->StartDateTicks().base(), start_ymd.year, start_ymd.month + 1, start_ymd.day, lgj->StartDateTicks().ToDateFractRemainder(), lgj->StartDateTicks().base(), start_ymd.year.base(), start_ymd.month + 1, start_ymd.day, lgj->StartDateTicks().ToDateFractRemainder(),
lgj->JoinDateTicks().base(), join_ymd.year, join_ymd.month + 1, join_ymd.day, lgj->JoinDateTicks().ToDateFractRemainder(), lgj->JoinDateTicks().base(), join_ymd.year.base(), join_ymd.month + 1, join_ymd.day, lgj->JoinDateTicks().ToDateFractRemainder(),
(lgj->JoinDateTicks() - lgj->StartDateTicks()).base()); (lgj->JoinDateTicks() - lgj->StartDateTicks()).base());
} }
return true; return true;
@ -2883,7 +2884,7 @@ DEF_CONSOLE_CMD(ConDumpBridgeTypes)
if (grfid != 0) grfids.insert(grfid); if (grfid != 0) grfids.insert(grfid);
IConsolePrintF(CC_DEFAULT, " %02u Year: %7u, Min: %3u, Max: %5u, Flags: %02X, Ctrl Flags: %c%c%c%c, Pillars: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X, GRF: %08X, %s", IConsolePrintF(CC_DEFAULT, " %02u Year: %7u, Min: %3u, Max: %5u, Flags: %02X, Ctrl Flags: %c%c%c%c, Pillars: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X, GRF: %08X, %s",
(uint) bt, (uint) bt,
spec->avail_year, spec->avail_year.base(),
spec->min_length, spec->min_length,
spec->max_length, spec->max_length,
spec->flags, spec->flags,
@ -3663,17 +3664,17 @@ static bool ConConditionalCommon(byte argc, char *argv[], int value, const char
DEF_CONSOLE_CMD(ConIfYear) DEF_CONSOLE_CMD(ConIfYear)
{ {
return ConConditionalCommon(argc, argv, _cur_date_ymd.year, "the current year (in game)", "if_year"); return ConConditionalCommon(argc, argv, CalTime::CurYear().base(), "the current year (in game)", "if_year");
} }
DEF_CONSOLE_CMD(ConIfMonth) DEF_CONSOLE_CMD(ConIfMonth)
{ {
return ConConditionalCommon(argc, argv, _cur_date_ymd.month + 1, "the current month (in game)", "if_month"); return ConConditionalCommon(argc, argv, CalTime::CurMonth() + 1, "the current month (in game)", "if_month");
} }
DEF_CONSOLE_CMD(ConIfDay) DEF_CONSOLE_CMD(ConIfDay)
{ {
return ConConditionalCommon(argc, argv, _cur_date_ymd.day, "the current day of the month (in game)", "if_day"); return ConConditionalCommon(argc, argv, CalTime::CurDay(), "the current day of the month (in game)", "if_day");
} }
DEF_CONSOLE_CMD(ConIfHour) DEF_CONSOLE_CMD(ConIfHour)

@ -486,9 +486,9 @@ char *CrashLog::LogRecentNews(char *buffer, const char *last) const
int i = 0; int i = 0;
for (NewsItem *news = _latest_news; i < 32 && news != nullptr; news = news->prev, i++) { for (NewsItem *news = _latest_news; i < 32 && news != nullptr; news = news->prev, i++) {
YearMonthDay ymd = ConvertDateToYMD(news->date); CalTime::YearMonthDay ymd = CalTime::ConvertDateToYMD(news->date);
buffer += seprintf(buffer, last, "(%i-%02i-%02i) StringID: %u, Type: %u, Ref1: %u, %u, Ref2: %u, %u\n", buffer += seprintf(buffer, last, "(%i-%02i-%02i) StringID: %u, Type: %u, Ref1: %u, %u, Ref2: %u, %u\n",
ymd.year, ymd.month + 1, ymd.day, news->string_id, news->type, ymd.year.base(), ymd.month + 1, ymd.day, news->string_id, news->type,
news->reftype1, news->ref1, news->reftype2, news->ref2); news->reftype1, news->ref1, news->reftype2, news->ref2);
} }
buffer += seprintf(buffer, last, "\n"); buffer += seprintf(buffer, last, "\n");
@ -559,7 +559,8 @@ char *CrashLog::FillCrashLog(char *buffer, const char *last)
buffer = this->TryCrashLogFaultSection(buffer, last, "times", [](CrashLog *self, char *buffer, const char *last) -> char * { buffer = this->TryCrashLogFaultSection(buffer, last, "times", [](CrashLog *self, char *buffer, const char *last) -> char * {
buffer += UTCTime::Format(buffer, last, "Crash at: %Y-%m-%d %H:%M:%S (UTC)\n"); buffer += UTCTime::Format(buffer, last, "Crash at: %Y-%m-%d %H:%M:%S (UTC)\n");
buffer += seprintf(buffer, last, "In game date: %i-%02i-%02i (%i, %i) (DL: %u)\n", _cur_date_ymd.year, _cur_date_ymd.month + 1, _cur_date_ymd.day, _date_fract, _tick_skip_counter, DayLengthFactor()); buffer += seprintf(buffer, last, "In game date: %i-%02i-%02i (%i, %i) (DL: %u)\n", EconTime::CurYear().base(), EconTime::CurMonth() + 1, EconTime::CurDay(), EconTime::CurDateFract(), TickSkipCounter(), DayLengthFactor());
buffer += seprintf(buffer, last, "Calendar date: %i-%02i-%02i (%i, %i)\n", CalTime::CurYear().base(), CalTime::CurMonth() + 1, CalTime::CurDay(), CalTime::CurDateFract(), CalTime::Detail::now.sub_date_fract);
LogGameLoadDateTimes(buffer, last); LogGameLoadDateTimes(buffer, last);
return buffer; return buffer;
}); });
@ -650,6 +651,27 @@ char *CrashLog::FillCrashLog(char *buffer, const char *last)
return buffer; return buffer;
} }
static char *LogDesyncDateHeader(char *buffer, const char *last)
{
extern uint32_t _frame_counter;
buffer += seprintf(buffer, last, "In game date: %i-%02i-%02i (%i, %i) (DL: %u), %08X\n",
EconTime::CurYear().base(), EconTime::CurMonth() + 1, EconTime::CurDay(), EconTime::CurDateFract(), TickSkipCounter(), DayLengthFactor(), _frame_counter);
buffer += seprintf(buffer, last, "Calendar date: %i-%02i-%02i (%i, %i)\n", CalTime::CurYear().base(), CalTime::CurMonth() + 1, CalTime::CurDay(), CalTime::CurDateFract(), CalTime::Detail::now.sub_date_fract);
LogGameLoadDateTimes(buffer, last);
if (_networking && !_network_server) {
extern EconTime::Date _last_sync_date;
extern EconTime::DateFract _last_sync_date_fract;
extern uint8_t _last_sync_tick_skip_counter;
extern uint32_t _last_sync_frame_counter;
EconTime::YearMonthDay ymd = EconTime::ConvertDateToYMD(_last_sync_date);
buffer += seprintf(buffer, last, "Last sync at: %i-%02i-%02i (%i, %i), %08X\n",
ymd.year.base(), ymd.month + 1, ymd.day, _last_sync_date_fract, _last_sync_tick_skip_counter, _last_sync_frame_counter);
}
return buffer;
}
/** /**
* Fill the crash log buffer with all data of a desync event. * Fill the crash log buffer with all data of a desync event.
* @param buffer The begin where to write at. * @param buffer The begin where to write at.
@ -673,22 +695,8 @@ char *CrashLog::FillDesyncCrashLog(char *buffer, const char *last, const DesyncE
if (_network_server && !info.desync_frame_info.empty()) { if (_network_server && !info.desync_frame_info.empty()) {
buffer += seprintf(buffer, last, "%s\n", info.desync_frame_info.c_str()); buffer += seprintf(buffer, last, "%s\n", info.desync_frame_info.c_str());
} }
buffer = LogDesyncDateHeader(buffer, last);
extern uint32_t _frame_counter;
buffer += seprintf(buffer, last, "In game date: %i-%02i-%02i (%i, %i) (DL: %u), %08X\n",
_cur_date_ymd.year, _cur_date_ymd.month + 1, _cur_date_ymd.day, _date_fract, _tick_skip_counter, DayLengthFactor(), _frame_counter);
LogGameLoadDateTimes(buffer, last);
if (!_network_server) {
extern Date _last_sync_date;
extern DateFract _last_sync_date_fract;
extern uint8_t _last_sync_tick_skip_counter;
extern uint32_t _last_sync_frame_counter;
YearMonthDay ymd = ConvertDateToYMD(_last_sync_date);
buffer += seprintf(buffer, last, "Last sync at: %i-%02i-%02i (%i, %i), %08X\n",
ymd.year, ymd.month + 1, ymd.day, _last_sync_date_fract, _last_sync_tick_skip_counter, _last_sync_frame_counter);
}
if (info.client_id >= 0) { if (info.client_id >= 0) {
buffer += seprintf(buffer, last, "Client #%d, \"%s\"\n", info.client_id, info.client_name != nullptr ? info.client_name : ""); buffer += seprintf(buffer, last, "Client #%d, \"%s\"\n", info.client_id, info.client_name != nullptr ? info.client_name : "");
} }
@ -735,21 +743,7 @@ char *CrashLog::FillInconsistencyLog(char *buffer, const char *last, const Incon
buffer += WriteScopeLog(buffer, last); buffer += WriteScopeLog(buffer, last);
#endif #endif
extern uint32_t _frame_counter; buffer = LogDesyncDateHeader(buffer, last);
buffer += seprintf(buffer, last, "In game date: %i-%02i-%02i (%i, %i) (DL: %u), %08X\n",
_cur_date_ymd.year, _cur_date_ymd.month + 1, _cur_date_ymd.day, _date_fract, _tick_skip_counter, DayLengthFactor(), _frame_counter);
LogGameLoadDateTimes(buffer, last);
if (_networking && !_network_server) {
extern Date _last_sync_date;
extern DateFract _last_sync_date_fract;
extern uint8_t _last_sync_tick_skip_counter;
extern uint32_t _last_sync_frame_counter;
YearMonthDay ymd = ConvertDateToYMD(_last_sync_date);
buffer += seprintf(buffer, last, "Last sync at: %i-%02i-%02i (%i, %i), %08X\n",
ymd.year, ymd.month + 1, ymd.day, _last_sync_date_fract, _last_sync_tick_skip_counter, _last_sync_frame_counter);
}
buffer += seprintf(buffer, last, "\n"); buffer += seprintf(buffer, last, "\n");
buffer = this->LogOpenTTDVersion(buffer, last); buffer = this->LogOpenTTDVersion(buffer, last);

@ -126,10 +126,10 @@ uint64_t GetMaskOfAllowedCurrencies()
uint i; uint i;
for (i = 0; i < CURRENCY_END; i++) { for (i = 0; i < CURRENCY_END; i++) {
Year to_euro = _currency_specs[i].to_euro; CalTime::Year to_euro = _currency_specs[i].to_euro;
if (to_euro != CF_NOEURO && to_euro != CF_ISEURO && _cur_year >= to_euro) continue; if (to_euro != CF_NOEURO && to_euro != CF_ISEURO && CalTime::CurYear() >= to_euro) continue;
if (to_euro == CF_ISEURO && _cur_year < 2000) continue; if (to_euro == CF_ISEURO && CalTime::CurYear() < 2000) continue;
SetBit(mask, i); SetBit(mask, i);
} }
SetBit(mask, CURRENCY_CUSTOM); // always allow custom currency SetBit(mask, CURRENCY_CUSTOM); // always allow custom currency
@ -143,7 +143,7 @@ void CheckSwitchToEuro()
{ {
if (_currency_specs[_settings_game.locale.currency].to_euro != CF_NOEURO && if (_currency_specs[_settings_game.locale.currency].to_euro != CF_NOEURO &&
_currency_specs[_settings_game.locale.currency].to_euro != CF_ISEURO && _currency_specs[_settings_game.locale.currency].to_euro != CF_ISEURO &&
_cur_year >= _currency_specs[_settings_game.locale.currency].to_euro) { CalTime::CurYear() >= _currency_specs[_settings_game.locale.currency].to_euro) {
_settings_game.locale.currency = 2; // this is the index of euro above. _settings_game.locale.currency = 2; // this is the index of euro above.
AddNewsItem(STR_NEWS_EURO_INTRODUCTION, NT_ECONOMY, NF_NORMAL); AddNewsItem(STR_NEWS_EURO_INTRODUCTION, NT_ECONOMY, NF_NORMAL);
} }

@ -73,7 +73,7 @@ enum Currencies {
struct CurrencySpec { struct CurrencySpec {
uint16_t rate; ///< The conversion rate compared to the base currency. uint16_t rate; ///< The conversion rate compared to the base currency.
std::string separator; ///< The thousands separator for this currency. std::string separator; ///< The thousands separator for this currency.
Year to_euro; ///< %Year of switching to the Euro. May also be #CF_NOEURO or #CF_ISEURO. CalTime::Year to_euro; ///< %Year of switching to the Euro. May also be #CF_NOEURO or #CF_ISEURO.
std::string prefix; ///< Prefix to apply when formatting money in this currency. std::string prefix; ///< Prefix to apply when formatting money in this currency.
std::string suffix; ///< Suffix to apply when formatting money in this currency. std::string suffix; ///< Suffix to apply when formatting money in this currency.
std::string code; ///< 3 letter untranslated code to identify the currency. std::string code; ///< 3 letter untranslated code to identify the currency.
@ -91,7 +91,7 @@ struct CurrencySpec {
CurrencySpec() = default; CurrencySpec() = default;
CurrencySpec(uint16_t rate, const char *separator, Year to_euro, const char *prefix, const char *suffix, const char *code, byte symbol_pos, StringID name) : CurrencySpec(uint16_t rate, const char *separator, CalTime::Year to_euro, const char *prefix, const char *suffix, const char *code, byte symbol_pos, StringID name) :
rate(rate), separator(separator), to_euro(to_euro), prefix(prefix), suffix(suffix), code(code), symbol_pos(symbol_pos), name(name) rate(rate), separator(separator), to_euro(to_euro), prefix(prefix), suffix(suffix), code(code), symbol_pos(symbol_pos), name(name)
{ {
} }

@ -27,16 +27,19 @@
#include "safeguards.h" #include "safeguards.h"
YearMonthDay _cur_date_ymd; ///< Current date as YearMonthDay struct
Date _date; ///< Current date in days (day counter)
DateFract _date_fract; ///< Fractional part of the day.
uint64_t _tick_counter; ///< Ever incrementing tick counter for setting off various events uint64_t _tick_counter; ///< Ever incrementing tick counter for setting off various events
uint8_t _tick_skip_counter; ///< Counter for ticks, when only vehicles are moving and nothing else happens
uint64_t _scaled_tick_counter; ///< Tick counter in daylength-scaled ticks uint64_t _scaled_tick_counter; ///< Tick counter in daylength-scaled ticks
StateTicks _state_ticks; ///< Current state tick StateTicks _state_ticks; ///< Current state tick
StateTicksDelta _state_ticks_offset; ///< Offset to add when calculating a StateTicks value from a date/date fract/tick skip counter uint32_t _quit_after_days; ///< Quit after this many days of run time
uint8_t _effective_day_length; ///< Current effective day length
uint32_t _quit_after_days; ///< Quit after this many days of run time CalTime::State CalTime::Detail::now;
EconTime::State EconTime::Detail::now;
namespace DateDetail {
StateTicksDelta _state_ticks_offset; ///< Offset to add when calculating a StateTicks value from an economy date, date fract and tick skip counter
uint8_t _tick_skip_counter; ///< Counter for ticks, when only vehicles are moving and nothing else happens
uint8_t _effective_day_length; ///< Current effective day length
};
extern void ClearOutOfDateSignalSpeedRestrictions(); extern void ClearOutOfDateSignalSpeedRestrictions();
@ -55,7 +58,7 @@ void CheckStateTicksWrap()
return; return;
} }
_state_ticks_offset -= tick_adjust; DateDetail::_state_ticks_offset -= tick_adjust;
_state_ticks -= tick_adjust; _state_ticks -= tick_adjust;
_game_load_state_ticks -= tick_adjust; _game_load_state_ticks -= tick_adjust;
@ -74,31 +77,61 @@ void CheckStateTicksWrap()
* @param date New date * @param date New date
* @param fract The number of ticks that have passed on this date. * @param fract The number of ticks that have passed on this date.
*/ */
void SetDate(Date date, DateFract fract) void CalTime::Detail::SetDate(CalTime::Date date, CalTime::DateFract fract)
{ {
assert(fract < DAY_TICKS); assert(fract < DAY_TICKS);
_date = date; CalTime::Detail::now.cal_date = date;
_date_fract = fract; CalTime::Detail::now.cal_date_fract = fract;
YearMonthDay ymd = ConvertDateToYMD(date); CalTime::Detail::now.cal_ymd = CalTime::ConvertDateToYMD(date);
_cur_date_ymd = ymd;
RecalculateStateTicksOffset();
UpdateCachedSnowLine(); UpdateCachedSnowLine();
} }
void EconTime::Detail::SetDate(EconTime::Date date, EconTime::DateFract fract)
{
assert(fract < DAY_TICKS);
EconTime::Detail::now.econ_date = date;
EconTime::Detail::now.econ_date_fract = fract;
EconTime::Detail::now.econ_ymd = EconTime::ConvertDateToYMD(date);
RecalculateStateTicksOffset();
}
CalTime::State CalTime::Detail::NewState(CalTime::Year year)
{
CalTime::State state{};
state.cal_ymd = { year, 0, 1 };
state.cal_date = CalTime::ConvertYMDToDate(year, 0, 1);
return state;
}
EconTime::State EconTime::Detail::NewState(EconTime::Year year)
{
EconTime::State state{};
state.econ_ymd = { year, 0, 1 };
state.econ_date = EconTime::ConvertYMDToDate(year, 0, 1);
return state;
}
StateTicks GetStateTicksFromCurrentDateWithoutOffset() StateTicks GetStateTicksFromCurrentDateWithoutOffset()
{ {
return ((int64_t)(DateToDateTicks(_date, _date_fract).base()) * DayLengthFactor()) + _tick_skip_counter; return ((int64_t)(EconTime::DateToDateTicks(EconTime::CurDate(), EconTime::CurDateFract()).base()) * DayLengthFactor()) + TickSkipCounter();
} }
void RecalculateStateTicksOffset() void RecalculateStateTicksOffset()
{ {
_state_ticks_offset = _state_ticks - GetStateTicksFromCurrentDateWithoutOffset(); DateDetail::_state_ticks_offset = _state_ticks - GetStateTicksFromCurrentDateWithoutOffset();
} }
void UpdateEffectiveDayLengthFactor() void UpdateEffectiveDayLengthFactor()
{ {
_effective_day_length = _settings_game.EffectiveDayLengthFactor(); DateDetail::_effective_day_length = _settings_game.EffectiveDayLengthFactor();
}
CalTime::Date StateTicksToCalendarDate(StateTicks ticks)
{
/* Process the same as calendar time (for now) */
return StateTicksToDate(ticks).base();
} }
#define M(a, b) ((a << 5) | b) #define M(a, b) ((a << 5) | b)
@ -145,14 +178,14 @@ static const uint16_t _accum_days_for_month[] = {
* @param date the date to convert from * @param date the date to convert from
* @param ymd the year, month and day to write to * @param ymd the year, month and day to write to
*/ */
YearMonthDay ConvertDateToYMD(Date date) CalTime::YearMonthDay CalTime::ConvertDateToYMD(CalTime::Date date)
{ {
/* Year determination in multiple steps to account for leap /* Year determination in multiple steps to account for leap
* years. First do the large steps, then the smaller ones. * years. First do the large steps, then the smaller ones.
*/ */
/* There are 97 leap years in 400 years */ /* There are 97 leap years in 400 years */
Year yr = 400 * (date.base() / (DAYS_IN_YEAR * 400 + 97)); CalTime::Year yr = 400 * (date.base() / (DAYS_IN_YEAR * 400 + 97));
int rem = date.base() % (DAYS_IN_YEAR * 400 + 97); int rem = date.base() % (DAYS_IN_YEAR * 400 + 97);
uint16_t x; uint16_t x;
@ -167,7 +200,7 @@ YearMonthDay ConvertDateToYMD(Date date)
rem = (rem % (DAYS_IN_YEAR * 100 + 24)); rem = (rem % (DAYS_IN_YEAR * 100 + 24));
} }
if (!IsLeapYear(yr) && rem >= DAYS_IN_YEAR * 4) { if (!CalTime::IsLeapYear(yr) && rem >= DAYS_IN_YEAR * 4) {
/* The first 4 year of the century are not always a leap year */ /* The first 4 year of the century are not always a leap year */
yr += 4; yr += 4;
rem -= DAYS_IN_YEAR * 4; rem -= DAYS_IN_YEAR * 4;
@ -179,15 +212,15 @@ YearMonthDay ConvertDateToYMD(Date date)
/* The last (max 3) years to account for; the first one /* The last (max 3) years to account for; the first one
* can be, but is not necessarily a leap year */ * can be, but is not necessarily a leap year */
while (rem >= (IsLeapYear(yr) ? DAYS_IN_LEAP_YEAR : DAYS_IN_YEAR)) { while (rem >= (CalTime::IsLeapYear(yr) ? DAYS_IN_LEAP_YEAR : DAYS_IN_YEAR)) {
rem -= IsLeapYear(yr) ? DAYS_IN_LEAP_YEAR : DAYS_IN_YEAR; rem -= CalTime::IsLeapYear(yr) ? DAYS_IN_LEAP_YEAR : DAYS_IN_YEAR;
yr++; yr++;
} }
/* Skip the 29th of February in non-leap years */ /* Skip the 29th of February in non-leap years */
if (!IsLeapYear(yr) && rem >= ACCUM_MAR - 1) rem++; if (!CalTime::IsLeapYear(yr) && rem >= ACCUM_MAR - 1) rem++;
YearMonthDay ymd; CalTime::YearMonthDay ymd;
ymd.year = yr; ymd.year = yr;
x = _month_date_from_year_day[rem]; x = _month_date_from_year_day[rem];
@ -203,7 +236,7 @@ YearMonthDay ConvertDateToYMD(Date date)
* @param month is a number between 0..11 * @param month is a number between 0..11
* @param day is a number between 1..31 * @param day is a number between 1..31
*/ */
Date ConvertYMDToDate(Year year, Month month, Day day) CalTime::Date CalTime::ConvertYMDToDate(CalTime::Year year, CalTime::Month month, CalTime::Day day)
{ {
/* Day-offset in a leap year */ /* Day-offset in a leap year */
int days = _accum_days_for_month[month] + day - 1; int days = _accum_days_for_month[month] + day - 1;
@ -211,7 +244,20 @@ Date ConvertYMDToDate(Year year, Month month, Day day)
/* Account for the missing of the 29th of February in non-leap years */ /* Account for the missing of the 29th of February in non-leap years */
if (!IsLeapYear(year) && days >= ACCUM_MAR) days--; if (!IsLeapYear(year) && days >= ACCUM_MAR) days--;
return DateAtStartOfYear(year) + days; return CalTime::DateAtStartOfYear(year) + days;
}
EconTime::YearMonthDay EconTime::ConvertDateToYMD(EconTime::Date date)
{
/* Process the same as calendar time (for now) */
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) */
return CalTime::ConvertYMDToDate(year.base(), month, day).base();
} }
/** Functions used by the IncreaseDate function */ /** Functions used by the IncreaseDate function */
@ -220,7 +266,8 @@ extern void EnginesDailyLoop();
extern void DisasterDailyLoop(); extern void DisasterDailyLoop();
extern void IndustryDailyLoop(); extern void IndustryDailyLoop();
extern void CompaniesMonthlyLoop(); extern void CompaniesCalendarMonthlyLoop();
extern void CompaniesEconomyMonthlyLoop();
extern void EnginesMonthlyLoop(); extern void EnginesMonthlyLoop();
extern void TownsMonthlyLoop(); extern void TownsMonthlyLoop();
extern void IndustryMonthlyLoop(); extern void IndustryMonthlyLoop();
@ -237,83 +284,106 @@ extern void ShowEndGameChart();
/** /**
* Runs various procedures that have to be done yearly * Runs various procedures that have to be done yearly
*/ */
static void OnNewYear() static void OnNewCalendarYear()
{ {
CompaniesYearlyLoop();
VehiclesYearlyLoop();
TownsYearlyLoop();
InvalidateWindowClassesData(WC_BUILD_STATION); InvalidateWindowClassesData(WC_BUILD_STATION);
InvalidateWindowClassesData(WC_BUS_STATION); InvalidateWindowClassesData(WC_BUS_STATION);
InvalidateWindowClassesData(WC_TRUCK_STATION); InvalidateWindowClassesData(WC_TRUCK_STATION);
if (_network_server) NetworkServerYearlyLoop(); if (_network_server) NetworkServerCalendarYearlyLoop();
if (_cur_date_ymd.year == _settings_client.gui.semaphore_build_before) ResetSignalVariant(); if (CalTime::CurYear() == _settings_client.gui.semaphore_build_before) ResetSignalVariant();
/* check if we reached end of the game (end of ending year); 0 = never */ /* check if we reached end of the game (end of ending year); 0 = never */
if (_cur_date_ymd.year == _settings_game.game_creation.ending_year + 1 && _settings_game.game_creation.ending_year != 0) { if (CalTime::CurYear() == _settings_game.game_creation.ending_year + 1 && _settings_game.game_creation.ending_year != 0) {
ShowEndGameChart(); ShowEndGameChart();
} }
/* check if we reached the maximum year, decrement dates by a year */ /* check if we reached the maximum year, decrement dates by a year */
if (_cur_date_ymd.year == MAX_YEAR + 1) { if (CalTime::CurYear() == CalTime::MAX_YEAR + 1) {
int days_this_year; CalTime::Detail::now.cal_ymd.year--;
int days_this_year = CalTime::IsLeapYear(CalTime::Detail::now.cal_ymd.year) ? DAYS_IN_LEAP_YEAR : DAYS_IN_YEAR;
CalTime::Detail::now.cal_date -= days_this_year;
}
_cur_date_ymd.year--; if (_settings_client.gui.auto_euro) CheckSwitchToEuro();
days_this_year = IsLeapYear(_cur_date_ymd.year) ? DAYS_IN_LEAP_YEAR : DAYS_IN_YEAR; IConsoleCmdExec("exec scripts/on_newyear.scr 0");
_date -= days_this_year; }
/**
* Runs various procedures that have to be done yearly
*/
static void OnNewEconomyYear()
{
CompaniesYearlyLoop();
VehiclesYearlyLoop();
TownsYearlyLoop();
if (_network_server) NetworkServerEconomyYearlyLoop();
/* check if we reached the maximum year, decrement dates by a year */
if (EconTime::CurYear() == EconTime::MAX_YEAR + 1) {
EconTime::Detail::now.econ_ymd.year--;
int days_this_year = EconTime::IsLeapYear(EconTime::Detail::now.econ_ymd.year) ? DAYS_IN_LEAP_YEAR : DAYS_IN_YEAR;
EconTime::Detail::now.econ_date -= days_this_year;
LinkGraphSchedule::instance.ShiftDates(-days_this_year); LinkGraphSchedule::instance.ShiftDates(-days_this_year);
ShiftOrderDates(-days_this_year); UpdateOrderUIOnDateChange();
ShiftVehicleDates(-days_this_year); ShiftVehicleDates(-days_this_year);
RecalculateStateTicksOffset(); RecalculateStateTicksOffset();
/* Because the _date wraps here, and text-messages expire by game-days, we have to clean out
* all of them if the date is set back, else those messages will hang for ever */
NetworkInitChatMessage();
} }
CheckStateTicksWrap(); CheckStateTicksWrap();
if (_settings_client.gui.auto_euro) CheckSwitchToEuro();
IConsoleCmdExec("exec scripts/on_newyear.scr 0");
} }
/** /**
* Runs various procedures that have to be done monthly * Runs various procedures that have to be done monthly
*/ */
static void OnNewMonth() static void OnNewCalendarMonth()
{ {
SetWindowClassesDirty(WC_CHEATS); SetWindowClassesDirty(WC_CHEATS);
CompaniesMonthlyLoop(); CompaniesCalendarMonthlyLoop();
EnginesMonthlyLoop(); EnginesMonthlyLoop();
IConsoleCmdExec("exec scripts/on_newmonth.scr 0");
}
/**
* Runs various procedures that have to be done monthly
*/
static void OnNewEconomyMonth()
{
CompaniesEconomyMonthlyLoop();
TownsMonthlyLoop(); TownsMonthlyLoop();
IndustryMonthlyLoop(); IndustryMonthlyLoop();
SubsidyMonthlyLoop(); SubsidyMonthlyLoop();
StationMonthlyLoop(); StationMonthlyLoop();
if (_network_server) NetworkServerMonthlyLoop(); if (_network_server) NetworkServerEconomyMonthlyLoop();
IConsoleCmdExec("exec scripts/on_newmonth.scr 0"); }
/**
* Runs various procedures that have to be done daily
*/
static void OnNewCalendarDay()
{
if (!_settings_time.time_in_minutes || _settings_client.gui.date_with_time > 0) {
SetWindowWidgetDirty(WC_STATUS_BAR, 0, WID_S_LEFT);
}
/* Refresh after possible snowline change */
SetWindowClassesDirty(WC_TOWN_VIEW);
IConsoleCmdExec("exec scripts/on_newday.scr 0");
} }
/** /**
* Runs various procedures that have to be done daily * Runs various procedures that have to be done daily
*/ */
static void OnNewDay() static void OnNewEconomyDay()
{ {
if (_network_server) NetworkServerDailyLoop(); if (_network_server) NetworkServerEconomyDailyLoop();
DisasterDailyLoop(); DisasterDailyLoop();
IndustryDailyLoop(); IndustryDailyLoop();
StationDailyLoop(); StationDailyLoop();
if (!_settings_time.time_in_minutes || _settings_client.gui.date_with_time > 0) {
SetWindowWidgetDirty(WC_STATUS_BAR, 0, WID_S_LEFT);
}
EnginesDailyLoop(); EnginesDailyLoop();
ClearOutOfDateSignalSpeedRestrictions(); ClearOutOfDateSignalSpeedRestrictions();
/* Refresh after possible snowline change */
SetWindowClassesDirty(WC_TOWN_VIEW);
IConsoleCmdExec("exec scripts/on_newday.scr 0");
if (_quit_after_days > 0) { if (_quit_after_days > 0) {
if (--_quit_after_days == 0) { if (--_quit_after_days == 0) {
DEBUG(misc, 0, "Quitting as day limit reached"); DEBUG(misc, 0, "Quitting as day limit reached");
@ -322,48 +392,84 @@ static void OnNewDay()
} }
} }
/** static void IncreaseCalendarDate()
* Increases the tick counter, increases date and possibly calls
* procedures that have to be called daily, monthly or yearly.
*/
void IncreaseDate()
{ {
/* increase day, and check if a new day is there? */ CalTime::Detail::now.cal_date_fract++;
_tick_counter++; if (CalTime::Detail::now.cal_date_fract < DAY_TICKS) return;
CalTime::Detail::now.cal_date_fract = 0;
if (_game_mode == GM_MENU || _game_mode == GM_BOOTSTRAP) return;
_date_fract++;
if (_date_fract < DAY_TICKS) return;
_date_fract = 0;
/* increase day counter */ /* increase day counter */
_date++; CalTime::Detail::now.cal_date++;
YearMonthDay ymd = ConvertDateToYMD(_date); CalTime::YearMonthDay ymd = CalTime::ConvertDateToYMD(CalTime::Detail::now.cal_date);
/* check if we entered a new month? */ /* check if we entered a new month? */
bool new_month = ymd.month != _cur_date_ymd.month; bool new_month = ymd.month != CalTime::Detail::now.cal_ymd.month;
/* check if we entered a new year? */ /* check if we entered a new year? */
bool new_year = ymd.year != _cur_date_ymd.year; bool new_year = ymd.year != CalTime::Detail::now.cal_ymd.year;
/* update internal variables before calling the daily/monthly/yearly loops */ /* update internal variables before calling the daily/monthly/yearly loops */
_cur_date_ymd = ymd; CalTime::Detail::now.cal_ymd = ymd;
UpdateCachedSnowLine(); UpdateCachedSnowLine();
/* yes, call various daily loops */ /* yes, call various daily loops */
OnNewDay(); OnNewCalendarDay();
/* yes, call various monthly loops */ /* yes, call various monthly loops */
if (new_month) OnNewMonth(); if (new_month) OnNewCalendarMonth();
/* yes, call various yearly loops */ /* yes, call various yearly loops */
if (new_year) OnNewYear(); if (new_year) OnNewCalendarYear();
}
static void IncreaseEconomyDate()
{
EconTime::Detail::now.econ_date_fract++;
if (EconTime::Detail::now.econ_date_fract < DAY_TICKS) return;
EconTime::Detail::now.econ_date_fract = 0;
/* increase day counter */
EconTime::Detail::now.econ_date++;
EconTime::YearMonthDay ymd = EconTime::ConvertDateToYMD(EconTime::Detail::now.econ_date);
/* check if we entered a new month? */
bool new_month = ymd.month != EconTime::Detail::now.econ_ymd.month;
/* check if we entered a new year? */
bool new_year = ymd.year != EconTime::Detail::now.econ_ymd.year;
/* update internal variables before calling the daily/monthly/yearly loops */
EconTime::Detail::now.econ_ymd = ymd;
/* yes, call various daily loops */
OnNewEconomyDay();
/* yes, call various monthly loops */
if (new_month) OnNewEconomyMonth();
/* yes, call various yearly loops */
if (new_year) OnNewEconomyYear();
}
/**
* Increases the tick counter, increases date and possibly calls
* procedures that have to be called daily, monthly or yearly.
*/
void IncreaseDate()
{
/* increase day, and check if a new day is there? */
_tick_counter++;
if (_game_mode == GM_MENU || _game_mode == GM_BOOTSTRAP) return;
IncreaseCalendarDate();
IncreaseEconomyDate();
} }
const char *debug_date_dumper::HexDate(Date date, DateFract date_fract, uint8_t tick_skip_counter) const char *debug_date_dumper::HexDate(EconTime::Date date, EconTime::DateFract date_fract, uint8_t tick_skip_counter)
{ {
seprintf(this->buffer, lastof(this->buffer), "date{%08x; %02x; %02x}", date.base(), date_fract, tick_skip_counter); seprintf(this->buffer, lastof(this->buffer), "date{%08x; %02x; %02x}", date.base(), date_fract, tick_skip_counter);
return this->buffer; return this->buffer;

@ -12,97 +12,63 @@
#include "date_type.h" #include "date_type.h"
#include "settings_type.h" #include "settings_type.h"
#include <utility>
extern YearMonthDay _cur_date_ymd;
extern Date _date;
extern DateFract _date_fract;
extern uint64_t _tick_counter; extern uint64_t _tick_counter;
extern uint8_t _tick_skip_counter;
extern uint64_t _scaled_tick_counter; extern uint64_t _scaled_tick_counter;
extern StateTicks _state_ticks; extern StateTicks _state_ticks;
extern StateTicksDelta _state_ticks_offset;
extern uint32_t _quit_after_days; extern uint32_t _quit_after_days;
void SetDate(Date date, DateFract fract); namespace DateDetail {
YearMonthDay ConvertDateToYMD(Date date); extern StateTicksDelta _state_ticks_offset;
Date ConvertYMDToDate(Year year, Month month, Day day); extern uint8_t _tick_skip_counter;
extern uint8_t _effective_day_length;
};
StateTicks GetStateTicksFromCurrentDateWithoutOffset(); StateTicks GetStateTicksFromCurrentDateWithoutOffset();
void RecalculateStateTicksOffset(); void RecalculateStateTicksOffset();
inline Date ConvertYMDToDate(const YearMonthDay &ymd) inline uint8_t TickSkipCounter()
{ {
return ConvertYMDToDate(ymd.year, ymd.month, ymd.day); return DateDetail::_tick_skip_counter;
} }
#define _cur_year (_cur_date_ymd.year)
inline uint8_t DayLengthFactor() inline uint8_t DayLengthFactor()
{ {
extern uint8_t _effective_day_length; return DateDetail::_effective_day_length;
return _effective_day_length;
} }
void UpdateEffectiveDayLengthFactor(); void UpdateEffectiveDayLengthFactor();
/** inline constexpr YearDelta DateDeltaToYearDelta(DateDelta date)
* Checks whether the given year is a leap year or not.
* @param yr The year to check.
* @return True if \c yr is a leap year, otherwise false.
*/
inline bool IsLeapYear(Year yr)
{
return yr % 4 == 0 && (yr % 100 != 0 || yr % 400 == 0);
}
inline Date StateTicksToDate(StateTicks ticks)
{
return (ticks.base() - _state_ticks_offset.base()) / (DAY_TICKS * DayLengthFactor());
}
inline StateTicks DateToStateTicks(Date date)
{ {
return ((int64_t)date.base() * DAY_TICKS * DayLengthFactor()) + _state_ticks_offset.base(); return date.base() / DAYS_IN_LEAP_YEAR;
}
inline DateTicks StateTicksToDateTicks(StateTicks ticks)
{
return (ticks.base() - _state_ticks_offset.base()) / DayLengthFactor();
} }
inline StateTicks DateTicksToStateTicks(DateTicks date_ticks) inline constexpr DateTicksDelta DateDeltaToDateTicksDelta(DateDelta date, uint16_t fract = 0)
{ {
return ((int64_t)date_ticks.base() * DayLengthFactor()) + _state_ticks_offset.base(); return ((int64_t)date.base() * DAY_TICKS) + fract;
} }
/** inline EconTime::Date StateTicksToDate(StateTicks ticks)
* Calculate the year of a given date.
* @param date The date to consider.
* @return the year.
*/
inline constexpr Year DateToYear(Date date)
{ {
return date.base() / DAYS_IN_LEAP_YEAR; return (ticks.base() - DateDetail::_state_ticks_offset.base()) / (DAY_TICKS * DayLengthFactor());
} }
inline constexpr Year DateDeltaToYears(DateDelta date) CalTime::Date StateTicksToCalendarDate(StateTicks ticks);
{
return date.base() / DAYS_IN_LEAP_YEAR;
}
inline constexpr DateTicks DateToDateTicks(Date date, DateFract fract = 0) inline StateTicks DateToStateTicks(EconTime::Date date)
{ {
return ((int64_t)date.base() * DAY_TICKS) + fract; return ((int64_t)date.base() * DAY_TICKS * DayLengthFactor()) + DateDetail::_state_ticks_offset.base();
} }
inline constexpr DateTicksDelta DateDeltaToDateTicksDelta(DateDelta date, DateFract fract = 0) inline EconTime::DateTicks StateTicksToDateTicks(StateTicks ticks)
{ {
return ((int64_t)date.base() * DAY_TICKS) + fract; return (ticks.base() - DateDetail::_state_ticks_offset.base()) / DayLengthFactor();
} }
inline DateTicks NowDateTicks() inline StateTicks DateTicksToStateTicks(EconTime::DateTicks date_ticks)
{ {
return DateToDateTicks(_date, _date_fract); return ((int64_t)date_ticks.base() * DayLengthFactor()) + DateDetail::_state_ticks_offset.base();
} }
inline Ticks TimetableDisplayUnitSize() inline Ticks TimetableDisplayUnitSize()
@ -115,9 +81,9 @@ inline Ticks TimetableDisplayUnitSize()
} }
struct debug_date_dumper { struct debug_date_dumper {
const char *HexDate(Date date, DateFract date_fract, uint8_t tick_skip_counter); const char *HexDate(EconTime::Date date, EconTime::DateFract date_fract, uint8_t tick_skip_counter);
inline const char *HexDate() { return this->HexDate(_date, _date_fract, _tick_skip_counter); } inline const char *HexDate() { return this->HexDate(EconTime::CurDate(), EconTime::CurDateFract(), TickSkipCounter()); }
private: private:
char buffer[24]; char buffer[24];

@ -24,10 +24,10 @@
/** Window to select a date graphically by using dropdowns */ /** Window to select a date graphically by using dropdowns */
struct SetDateWindow : Window { struct SetDateWindow : Window {
SetTickCallback *callback; ///< Callback to call when a date has been selected SetTickCallback *callback; ///< Callback to call when a date has been selected
YearMonthDay date; ///< The currently selected date EconTime::YearMonthDay date; ///< The currently selected date
Year min_year; ///< The minimum year in the year dropdown EconTime::Year min_year; ///< The minimum year in the year dropdown
Year max_year; ///< The maximum year (inclusive) in the year dropdown EconTime::Year max_year; ///< The maximum year (inclusive) in the year dropdown
/** /**
* Create the new 'set date' window * Create the new 'set date' window
@ -39,12 +39,12 @@ struct SetDateWindow : Window {
* @param max_year the maximum year (inclusive) to show in the year dropdown * @param max_year the maximum year (inclusive) to show in the year dropdown
* @param callback the callback to call once a date has been selected * @param callback the callback to call once a date has been selected
*/ */
SetDateWindow(WindowDesc *desc, WindowNumber window_number, Window *parent, Date initial_date, Year min_year, Year max_year, SetDateWindow(WindowDesc *desc, WindowNumber window_number, Window *parent, EconTime::Date initial_date, EconTime::Year min_year, EconTime::Year max_year,
SetTickCallback *callback, StringID button_text, StringID button_tooltip) : SetTickCallback *callback, StringID button_text, StringID button_tooltip) :
Window(desc), Window(desc),
callback(callback), callback(callback),
min_year(std::max(MIN_YEAR, min_year)), min_year(std::max(EconTime::MIN_YEAR, min_year)),
max_year(std::min(MAX_YEAR, max_year)) max_year(std::min(EconTime::MAX_YEAR, max_year))
{ {
assert(this->min_year <= this->max_year); assert(this->min_year <= this->max_year);
this->parent = parent; this->parent = parent;
@ -56,8 +56,8 @@ struct SetDateWindow : Window {
} }
this->FinishInitNested(window_number); this->FinishInitNested(window_number);
if (initial_date == 0) initial_date = _date; if (initial_date == 0) initial_date = EconTime::CurDate();
this->date = ConvertDateToYMD(initial_date); this->date = EconTime::ConvertDateToYMD(initial_date);
this->date.year = Clamp(this->date.year, min_year, max_year); this->date.year = Clamp(this->date.year, min_year, max_year);
} }
@ -94,11 +94,11 @@ struct SetDateWindow : Window {
break; break;
case WID_SD_YEAR: case WID_SD_YEAR:
for (Year i = this->min_year; i <= this->max_year; i++) { for (EconTime::Year i = this->min_year; i <= this->max_year; i++) {
SetDParam(0, i); SetDParam(0, i);
list.push_back(std::make_unique<DropDownListStringItem>(STR_JUST_INT, i, false)); list.push_back(std::make_unique<DropDownListStringItem>(STR_JUST_INT, i.base(), false));
} }
selected = this->date.year; selected = this->date.year.base();
break; break;
} }
@ -124,7 +124,7 @@ struct SetDateWindow : Window {
break; break;
case WID_SD_YEAR: case WID_SD_YEAR:
SetDParamMaxValue(0, this->max_year); SetDParamMaxValue(0, this->max_year.base());
d = maxdim(d, GetStringBoundingBox(STR_JUST_INT)); d = maxdim(d, GetStringBoundingBox(STR_JUST_INT));
break; break;
} }
@ -153,7 +153,7 @@ struct SetDateWindow : Window {
break; break;
case WID_SD_SET_DATE: case WID_SD_SET_DATE:
if (this->callback != nullptr) { if (this->callback != nullptr) {
this->callback(this, DateToStateTicks(ConvertYMDToDate(this->date.year, this->date.month, this->date.day))); this->callback(this, DateToStateTicks(EconTime::ConvertYMDToDate(this->date.year, this->date.month, this->date.day)));
} }
this->Close(); this->Close();
break; break;
@ -184,7 +184,7 @@ struct SetMinutesWindow : SetDateWindow
TickMinutes minutes; TickMinutes minutes;
/** Constructor. */ /** Constructor. */
SetMinutesWindow(WindowDesc *desc, WindowNumber window_number, Window *parent, StateTicks initial_tick, Year min_year, Year max_year, SetMinutesWindow(WindowDesc *desc, WindowNumber window_number, Window *parent, StateTicks initial_tick, EconTime::Year min_year, EconTime::Year max_year,
SetTickCallback *callback, StringID button_text, StringID button_tooltip) : SetTickCallback *callback, StringID button_text, StringID button_tooltip) :
SetDateWindow(desc, window_number, parent, 0, min_year, max_year, callback, button_text, button_tooltip), SetDateWindow(desc, window_number, parent, 0, min_year, max_year, callback, button_text, button_tooltip),
minutes(_settings_time.ToTickMinutes(initial_tick)) minutes(_settings_time.ToTickMinutes(initial_tick))
@ -366,7 +366,7 @@ static WindowDesc _set_minutes_desc(__FILE__, __LINE__,
* @param max_year the maximum year (inclusive) to show in the year dropdown * @param max_year the maximum year (inclusive) to show in the year dropdown
* @param callback the callback to call once a date has been selected * @param callback the callback to call once a date has been selected
*/ */
void ShowSetDateWindow(Window *parent, int window_number, StateTicks initial_tick, Year min_year, Year max_year, void ShowSetDateWindow(Window *parent, int window_number, StateTicks initial_tick, EconTime::Year min_year, EconTime::Year max_year,
SetTickCallback *callback, StringID button_text, StringID button_tooltip) SetTickCallback *callback, StringID button_text, StringID button_tooltip)
{ {
CloseWindowByClass(WC_SET_DATE); CloseWindowByClass(WC_SET_DATE);

@ -20,7 +20,7 @@
*/ */
typedef void SetTickCallback(const Window *w, StateTicks tick); typedef void SetTickCallback(const Window *w, StateTicks tick);
void ShowSetDateWindow(Window *parent, int window_number, StateTicks initial_tick, Year min_year, Year max_year, SetTickCallback *callback, void ShowSetDateWindow(Window *parent, int window_number, StateTicks initial_tick, EconTime::Year min_year, EconTime::Year max_year, SetTickCallback *callback,
StringID button_text = STR_NULL, StringID button_tooltip = STR_NULL); StringID button_text = STR_NULL, StringID button_tooltip = STR_NULL);
#endif /* DATE_GUI_H */ #endif /* DATE_GUI_H */

@ -26,116 +26,310 @@ static const int MONTHS_IN_YEAR = 12; ///< months per year
static const int SECONDS_PER_DAY = 2; ///< approximate seconds per day, not for precise calculations static const int SECONDS_PER_DAY = 2; ///< approximate seconds per day, not for precise calculations
typedef uint16_t DateFract; ///< The fraction of a date we're in, i.e. the number of ticks since the last date changeover using Ticks = int32_t; ///< The type to store ticks in
typedef int32_t Ticks; ///< The type to store ticks in static constexpr Ticks INVALID_TICKS = -1; ///< Representation of an invalid number of ticks
typedef int32_t Year; ///< Type for the year, note: 0 based, i.e. starts at the year 0. using YearDelta = StrongType::Typedef<int32_t, struct YearDeltaTag, StrongType::Compare, StrongType::IntegerScalable>;
typedef uint8_t Month; ///< Type for the month, note: 0 based, i.e. 0 = January, 11 = December.
typedef uint8_t Day; ///< Type for the day of the month, note: 1 based, first day of a month is 1.
/* The type to store our dates in */
using DateDelta = StrongType::Typedef<int32_t, struct DateDeltaTag, StrongType::Compare, StrongType::IntegerScalable>; using DateDelta = StrongType::Typedef<int32_t, struct DateDeltaTag, StrongType::Compare, StrongType::IntegerScalable>;
using Date = StrongType::Typedef<int32_t, struct DateTag, StrongType::Compare, StrongType::IntegerDelta<DateDelta>>; using DateTicksDelta = StrongType::Typedef<int64_t, struct DateTicksDeltaTag, StrongType::Compare, StrongType::IntegerScalable>;
/* Mixin for DateTicks */ namespace DateDetail {
struct DateTicksOperations { /* Mixin for DateTicks */
template <typename TType, typename TBaseType> template <typename TDate, typename TDateFract>
struct mixin { struct DateTicksOperations {
private: template <typename TType, typename TBaseType>
TBaseType GetBase() const { return static_cast<const TType &>(*this).base(); } struct mixin {
private:
public: TBaseType GetBase() const { return static_cast<const TType &>(*this).base(); }
Date ToDate() const { return this->GetBase() / DAY_TICKS; }
DateFract ToDateFractRemainder() const { return this->GetBase() % DAY_TICKS; } public:
TDate ToDate() const { return this->GetBase() / DAY_TICKS; }
TDateFract ToDateFractRemainder() const { return this->GetBase() % DAY_TICKS; }
};
};
template <typename T>
struct BaseTime {
/* The type to store our dates in */
template <class ST> struct DateDeltaTag;
template <class ST> struct DateTag;
using Date = StrongType::Typedef<int32_t, struct DateTag<T>, StrongType::Compare, StrongType::IntegerDelta<DateDelta>>;
using DateFract = uint16_t; ///< The fraction of a date we're in, i.e. the number of ticks since the last date changeover
/* The type to store dates in when tick-precision is required */
template <class ST> struct DateTicksTag;
using DateTicks = StrongType::Typedef<int64_t, struct DateTicksTag<T>, StrongType::Compare, StrongType::IntegerDelta<DateTicksDelta>, DateTicksOperations<Date, DateFract>>;
static constexpr DateTicks DateToDateTicks(Date date, DateFract fract = 0)
{
return ((int64_t)date.base() * DAY_TICKS) + fract;
}
/* Year type */
template <class ST> struct YearTag;
using Year = StrongType::Typedef<int32_t, struct YearTag<T>, StrongType::Compare, StrongType::IntegerDelta<YearDelta>>;
using Month = uint8_t; ///< Type for the month, note: 0 based, i.e. 0 = January, 11 = December.
using Day = uint8_t; ///< Type for the day of the month, note: 1 based, first day of a month is 1.
/**
* Data structure to convert between Date and triplet (year, month, and day).
* @see ConvertDateToYMD(), ConvertYMDToDate()
*/
struct YearMonthDay {
Year year; ///< Year (0...)
Month month; ///< Month (0..11)
Day day; ///< Day (1..31)
};
struct Detail {
/**
* 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 constexpr Date DateAtStartOfCalendarYear(Year year)
{
int32_t year_as_int = year.base();
uint number_of_leap_years = (year == 0) ? 0 : ((year_as_int - 1) / 4 - (year_as_int - 1) / 100 + (year_as_int - 1) / 400 + 1);
/* Hardcode the number of days in a year because we can't access CalendarTime from here. */
return (365 * year_as_int) + number_of_leap_years;
}
};
/**
* Checks whether the given year is a leap year or not.
* @param year The year to check.
* @return True if \c year is a leap year, otherwise false.
*/
static constexpr bool IsLeapYear(Year year)
{
int32_t year_as_int = year.base();
return year_as_int % 4 == 0 && (year_as_int % 100 != 0 || year_as_int % 400 == 0);
}
/*
* ORIGINAL_BASE_YEAR, ORIGINAL_MAX_YEAR and DAYS_TILL_ORIGINAL_BASE_YEAR are
* primarily used for loading newgrf and savegame data and returning some
* newgrf (callback) functions that were in the original (TTD) inherited
* format, where '_date == 0' meant that it was 1920-01-01.
*/
/** The minimum starting year/base year of the original TTD */
static constexpr Year ORIGINAL_BASE_YEAR = 1920;
/** The original ending year */
static constexpr Year ORIGINAL_END_YEAR = 2051;
/** The maximum year of the original TTD */
static constexpr Year ORIGINAL_MAX_YEAR = 2090;
/**
* The offset in days from the '_date == 0' till
* 'ConvertYMDToDate(ORIGINAL_BASE_YEAR, 0, 1)'
*/
static constexpr Date DAYS_TILL_ORIGINAL_BASE_YEAR = Detail::DateAtStartOfCalendarYear(ORIGINAL_BASE_YEAR);
static constexpr Date MIN_DATE = 0;
/** The absolute minimum & maximum years in OTTD */
static constexpr Year MIN_YEAR = 0;
/** The default starting year */
static constexpr Year DEF_START_YEAR = 1950;
/** The default scoring end year */
static constexpr Year DEF_END_YEAR = ORIGINAL_END_YEAR - 1;
/**
* MAX_YEAR, nicely rounded value of the number of years that can
* be encoded in a single 32 bits date, about 2^31 / 366 years.
*/
static constexpr Year MAX_YEAR = 5000000;
/** The number of days till the last day */
static constexpr Date MAX_DATE = Detail::DateAtStartOfCalendarYear(MAX_YEAR + 1) - 1;
static constexpr Year INVALID_YEAR = -1; ///< Representation of an invalid year
static constexpr Date INVALID_DATE = -1; ///< Representation of an invalid date
static constexpr DateTicks INVALID_DATE_TICKS = -1; ///< Representation of an invalid date ticks
}; };
}; };
/* The type to store dates in when tick-precision is required */ struct CalTime : public DateDetail::BaseTime<struct CalendarTimeTag> {
using DateTicksDelta = StrongType::Typedef<int64_t, struct DateTicksDeltaTag, StrongType::Compare, StrongType::IntegerScalable>; using ParentBaseTime = DateDetail::BaseTime<struct CalendarTimeTag>;
using DateTicks = StrongType::Typedef<int64_t, struct DateTicksTag, StrongType::Compare, StrongType::IntegerDelta<DateTicksDelta>, DateTicksOperations>;
/* Mixin for StateTicksDelta */ /* Use a state struct to make backup/restore/init simpler */
struct StateTicksDeltaOperations { struct State {
template <typename TType, typename TBaseType> YearMonthDay cal_ymd;
struct mixin { Date cal_date;
private: DateFract cal_date_fract;
TBaseType GetBase() const { return static_cast<const TType &>(*this).base(); } uint16_t sub_date_fract; ///< Subpart of date_fract that we use when calendar days are slower than economy days.
};
/* 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);
};
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; }
static inline Day CurDay() { return Detail::now.cal_ymd.day; }
static inline Date CurDate() { return Detail::now.cal_date; }
static inline DateFract CurDateFract() { return Detail::now.cal_date_fract; }
static YearMonthDay ConvertDateToYMD(Date date);
static Date ConvertYMDToDate(Year year, Month month, Day day);
static inline Date ConvertYMDToDate(const YearMonthDay &ymd)
{
return ConvertYMDToDate(ymd.year, ymd.month, ymd.day);
}
/**
* Calculate the year of a given date.
* @param date The date to consider.
* @return the year.
*/
static constexpr Year DateToYear(Date date)
{
return date.base() / DAYS_IN_LEAP_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.
*/
static constexpr Date DateAtStartOfYear(Year year)
{
return ParentBaseTime::Detail::DateAtStartOfCalendarYear(year);
}
};
struct EconTime : public 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;
};
/* 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);
};
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; }
static inline Day CurDay() { return Detail::now.econ_ymd.day; }
static inline Date CurDate() { return Detail::now.econ_date; }
static inline DateFract CurDateFract() { return Detail::now.econ_date_fract; }
static inline DateTicks CurDateTicks() { return DateToDateTicks(CurDate(), CurDateFract()); }
static YearMonthDay ConvertDateToYMD(Date date);
static Date ConvertYMDToDate(Year year, Month month, Day day);
static inline Date ConvertYMDToDate(const YearMonthDay &ymd)
{
return ConvertYMDToDate(ymd.year, ymd.month, ymd.day);
}
};
namespace DateDetail {
/* Mixin for StateTicksDelta */
struct StateTicksDeltaOperations {
template <typename TType, typename TBaseType>
struct mixin {
private:
TBaseType GetBase() const { return static_cast<const TType &>(*this).base(); }
public: public:
template<typename T> template<typename T>
T AsTicksT() const { return ClampTo<T>(this->GetBase()); } T AsTicksT() const { return ClampTo<T>(this->GetBase()); }
Ticks AsTicks() const { return this->AsTicksT<Ticks>(); } Ticks AsTicks() const { return this->AsTicksT<Ticks>(); }
};
}; };
}; };
/* The type to store state ticks (this always ticks at the same rate regardless of day length, even in the scenario editor */ /* The type to store state ticks (this always ticks at the same rate regardless of day length, even in the scenario editor */
using StateTicksDelta = StrongType::Typedef<int64_t, struct StateTicksDeltaTag, StrongType::Compare, StrongType::IntegerScalable, StateTicksDeltaOperations>; using StateTicksDelta = StrongType::Typedef<int64_t, struct StateTicksDeltaTag, StrongType::Compare, StrongType::IntegerScalable, DateDetail::StateTicksDeltaOperations>;
using StateTicks = StrongType::Typedef<int64_t, struct StateTicksTag, StrongType::Compare, StrongType::IntegerDelta<StateTicksDelta>>; using StateTicks = StrongType::Typedef<int64_t, struct StateTicksTag, StrongType::Compare, StrongType::IntegerDelta<StateTicksDelta>>;
/* Mixin for TickMinutes, ClockFaceMinutes */ namespace DateDetail {
template <bool TNegativeCheck> /* Mixin for TickMinutes, ClockFaceMinutes */
struct MinuteOperations { template <bool TNegativeCheck>
template <typename TType, typename TBaseType> struct MinuteOperations {
struct mixin { template <typename TType, typename TBaseType>
private: struct mixin {
TBaseType GetBase() const private:
{ TBaseType GetBase() const
TBaseType value = static_cast<const TType &>(*this).base(); {
if constexpr (TNegativeCheck) { TBaseType value = static_cast<const TType &>(*this).base();
if (value < 0) { if constexpr (TNegativeCheck) {
value = (value % 1440) + 1440; if (value < 0) {
value = (value % 1440) + 1440;
}
} }
return value;
} }
return value;
}
public: public:
int ClockMinute() const { return this->GetBase() % 60; } int ClockMinute() const { return this->GetBase() % 60; }
int ClockHour() const { return (this->GetBase() / 60) % 24; } int ClockHour() const { return (this->GetBase() / 60) % 24; }
int ClockHHMM() const { return (this->ClockHour() * 100) + this->ClockMinute(); } int ClockHHMM() const { return (this->ClockHour() * 100) + this->ClockMinute(); }
};
}; };
};
/* Mixin for ClockFaceMinutes */ /* Mixin for ClockFaceMinutes */
struct ClockFaceMinuteOperations { struct ClockFaceMinuteOperations {
template <typename TType, typename TBaseType> template <typename TType, typename TBaseType>
struct mixin { struct mixin {
static constexpr TType FromClockFace(int hours, int minutes) static constexpr TType FromClockFace(int hours, int minutes)
{ {
return (TBaseType(hours) * 60) + minutes; return (TBaseType(hours) * 60) + minutes;
} }
};
}; };
}; };
/* The type to store general clock-face minutes in (i.e. 0..1440) */ /* The type to store general clock-face minutes in (i.e. 0..1440) */
using ClockFaceMinutes = StrongType::Typedef<int, struct ClockFaceMinutesTag, StrongType::Compare, StrongType::Integer, MinuteOperations<false>, ClockFaceMinuteOperations>; using ClockFaceMinutes = StrongType::Typedef<int, struct ClockFaceMinutesTag, StrongType::Compare, StrongType::Integer, DateDetail::MinuteOperations<false>, DateDetail::ClockFaceMinuteOperations>;
/* Mixin for TickMinutes */ namespace DateDetail {
struct TickMinuteOperations { /* Mixin for TickMinutes */
template <typename TType, typename TBaseType> struct TickMinuteOperations {
struct mixin { template <typename TType, typename TBaseType>
private: struct mixin {
TBaseType GetBase() const { return static_cast<const TType &>(*this).base(); } private:
TBaseType GetBase() const { return static_cast<const TType &>(*this).base(); }
public:
TType ToSameDayClockTime(int hour, int minute) const public:
{ TType ToSameDayClockTime(int hour, int minute) const
TBaseType day = DivTowardsNegativeInf<TBaseType>(this->GetBase(), 1440); {
return (day * 1440) + (hour * 60) + minute; TBaseType day = DivTowardsNegativeInf<TBaseType>(this->GetBase(), 1440);
} return (day * 1440) + (hour * 60) + minute;
}
ClockFaceMinutes ToClockFaceMinutes() const ClockFaceMinutes ToClockFaceMinutes() const
{ {
TBaseType minutes = this->GetBase() % 1440; TBaseType minutes = this->GetBase() % 1440;
if (minutes < 0) minutes += 1440; if (minutes < 0) minutes += 1440;
return minutes; return minutes;
} }
};
}; };
}; };
/* The type to store StateTicks-based minutes in */ /* The type to store StateTicks-based minutes in */
using TickMinutes = StrongType::Typedef<int64_t, struct TickMinutesTag, StrongType::Compare, StrongType::Integer, MinuteOperations<true>, TickMinuteOperations>; using TickMinutes = StrongType::Typedef<int64_t, struct TickMinutesTag, StrongType::Compare, StrongType::Integer, DateDetail::MinuteOperations<true>, DateDetail::TickMinuteOperations>;
static const int STATION_RATING_TICKS = 185; ///< cycle duration for updating station rating static const int STATION_RATING_TICKS = 185; ///< cycle duration for updating station rating
static const int STATION_ACCEPTANCE_TICKS = 250; ///< cycle duration for updating station acceptance static const int STATION_ACCEPTANCE_TICKS = 250; ///< cycle duration for updating station acceptance
@ -145,75 +339,7 @@ static const int INDUSTRY_PRODUCE_TICKS = 256; ///< cycle duration for industr
static const int TOWN_GROWTH_TICKS = 70; ///< cycle duration for towns trying to grow. (this originates from the size of the town array in TTD static const int TOWN_GROWTH_TICKS = 70; ///< cycle duration for towns trying to grow. (this originates from the size of the town array in TTD
static const int INDUSTRY_CUT_TREE_TICKS = INDUSTRY_PRODUCE_TICKS * 2; ///< cycle duration for lumber mill's extra action static const int INDUSTRY_CUT_TREE_TICKS = INDUSTRY_PRODUCE_TICKS * 2; ///< cycle duration for lumber mill's extra action
/*
* ORIGINAL_BASE_YEAR, ORIGINAL_MAX_YEAR and DAYS_TILL_ORIGINAL_BASE_YEAR are
* primarily used for loading newgrf and savegame data and returning some
* newgrf (callback) functions that were in the original (TTD) inherited
* format, where '_date == 0' meant that it was 1920-01-01.
*/
/** The minimum starting year/base year of the original TTD */
static constexpr Year ORIGINAL_BASE_YEAR = 1920;
/** The original ending year */
static constexpr Year ORIGINAL_END_YEAR = 2051;
/** The maximum year of the original TTD */
static constexpr Year ORIGINAL_MAX_YEAR = 2090;
/**
* 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 constexpr Date DateAtStartOfYear(Year year)
{
int32_t year_as_int = year;
uint number_of_leap_years = (year == 0) ? 0 : ((year_as_int - 1) / 4 - (year_as_int - 1) / 100 + (year_as_int - 1) / 400 + 1);
/* Hardcode the number of days in a year because we can't access CalendarTime from here. */
return (365 * year_as_int) + number_of_leap_years;
}
/**
* The offset in days from the '_date == 0' till
* 'ConvertYMDToDate(ORIGINAL_BASE_YEAR, 0, 1)'
*/
static constexpr Date DAYS_TILL_ORIGINAL_BASE_YEAR = DateAtStartOfYear(ORIGINAL_BASE_YEAR);
static constexpr Date MIN_DATE = 0;
/** The absolute minimum & maximum years in OTTD */
static constexpr Year MIN_YEAR = 0;
/** The default starting year */
static constexpr Year DEF_START_YEAR = 1950;
/** The default scoring end year */
static constexpr Year DEF_END_YEAR = ORIGINAL_END_YEAR - 1;
/**
* MAX_YEAR, nicely rounded value of the number of years that can
* be encoded in a single 32 bits date, about 2^31 / 366 years.
*/
static const Year MAX_YEAR = 5000000;
/** The number of days till the last day */
static constexpr Date MAX_DATE = DateAtStartOfYear(MAX_YEAR + 1) - 1;
/** An initial value for StateTicks when starting a new game */ /** An initial value for StateTicks when starting a new game */
static constexpr StateTicks INITIAL_STATE_TICKS_VALUE = 1 << 24; static constexpr StateTicks INITIAL_STATE_TICKS_VALUE = 1 << 24;
/**
* Data structure to convert between Date and triplet (year, month, and day).
* @see ConvertDateToYMD(), ConvertYMDToDate()
*/
struct YearMonthDay {
Year year; ///< Year (0...)
Month month; ///< Month (0..11)
Day day; ///< Day (1..31)
};
static constexpr Year INVALID_YEAR = -1; ///< Representation of an invalid year
static constexpr Date INVALID_DATE = -1; ///< Representation of an invalid date
static constexpr DateTicks INVALID_DATE_TICKS = -1; ///< Representation of an invalid date ticks
static constexpr Ticks INVALID_TICKS = -1; ///< Representation of an invalid number of ticks
#endif /* DATE_TYPE_H */ #endif /* DATE_TYPE_H */

@ -321,8 +321,8 @@ const char *log_prefix::GetLogPrefix()
} }
struct DesyncMsgLogEntry { struct DesyncMsgLogEntry {
Date date; EconTime::Date date;
DateFract date_fract; EconTime::DateFract date_fract;
uint8_t tick_skip_counter; uint8_t tick_skip_counter;
uint32_t src_id; uint32_t src_id;
std::string msg; std::string msg;
@ -330,7 +330,7 @@ struct DesyncMsgLogEntry {
DesyncMsgLogEntry() { } DesyncMsgLogEntry() { }
DesyncMsgLogEntry(std::string msg) DesyncMsgLogEntry(std::string msg)
: date(_date), date_fract(_date_fract), tick_skip_counter(_tick_skip_counter), src_id(0), msg(msg) { } : date(EconTime::CurDate()), date_fract(EconTime::CurDateFract()), tick_skip_counter(TickSkipCounter()), src_id(0), msg(msg) { }
}; };
struct DesyncMsgLog { struct DesyncMsgLog {
@ -385,12 +385,12 @@ void ClearDesyncMsgLog()
char *DumpDesyncMsgLog(char *buffer, const char *last) char *DumpDesyncMsgLog(char *buffer, const char *last)
{ {
buffer = _desync_msg_log.Dump(buffer, last, "Desync Msg Log", [](int display_num, char *buffer, const char *last, const DesyncMsgLogEntry &entry) -> int { buffer = _desync_msg_log.Dump(buffer, last, "Desync Msg Log", [](int display_num, char *buffer, const char *last, const DesyncMsgLogEntry &entry) -> int {
YearMonthDay ymd = ConvertDateToYMD(entry.date); EconTime::YearMonthDay ymd = EconTime::ConvertDateToYMD(entry.date);
return seprintf(buffer, last, "%5u | %4i-%02i-%02i, %2i, %3i | %s\n", display_num, ymd.year, ymd.month + 1, ymd.day, entry.date_fract, entry.tick_skip_counter, entry.msg.c_str()); return seprintf(buffer, last, "%5u | %4i-%02i-%02i, %2i, %3i | %s\n", display_num, ymd.year.base(), ymd.month + 1, ymd.day, entry.date_fract, entry.tick_skip_counter, entry.msg.c_str());
}); });
buffer = _remote_desync_msg_log.Dump(buffer, last, "Remote Client Desync Msg Log", [](int display_num, char *buffer, const char *last, const DesyncMsgLogEntry &entry) -> int { buffer = _remote_desync_msg_log.Dump(buffer, last, "Remote Client Desync Msg Log", [](int display_num, char *buffer, const char *last, const DesyncMsgLogEntry &entry) -> int {
YearMonthDay ymd = ConvertDateToYMD(entry.date); EconTime::YearMonthDay ymd = EconTime::ConvertDateToYMD(entry.date);
return seprintf(buffer, last, "%5u | Client %5u | %4i-%02i-%02i, %2i, %3i | %s\n", display_num, entry.src_id, ymd.year, ymd.month + 1, ymd.day, entry.date_fract, entry.tick_skip_counter, entry.msg.c_str()); return seprintf(buffer, last, "%5u | Client %5u | %4i-%02i-%02i, %2i, %3i | %s\n", display_num, entry.src_id, ymd.year.base(), ymd.month + 1, ymd.day, entry.date_fract, entry.tick_skip_counter, entry.msg.c_str());
}); });
return buffer; return buffer;
} }
@ -403,7 +403,7 @@ void LogDesyncMsg(std::string msg)
_desync_msg_log.LogMsg(DesyncMsgLogEntry(std::move(msg))); _desync_msg_log.LogMsg(DesyncMsgLogEntry(std::move(msg)));
} }
void LogRemoteDesyncMsg(Date date, DateFract date_fract, uint8_t tick_skip_counter, uint32_t src_id, std::string msg) void LogRemoteDesyncMsg(EconTime::Date date, EconTime::DateFract date_fract, uint8_t tick_skip_counter, uint32_t src_id, std::string msg)
{ {
DesyncMsgLogEntry entry(std::move(msg)); DesyncMsgLogEntry entry(std::move(msg));
entry.date = date; entry.date = date;

@ -856,8 +856,8 @@ DepartureList* MakeDepartureList(StationID station, const std::vector<const Vehi
for (uint i = 0; i < next_orders.size(); ++i) { for (uint i = 0; i < next_orders.size(); ++i) {
OrderDate *od = next_orders[i]; OrderDate *od = next_orders[i];
DateTicks lod = least_order->expected_tick - least_order->lateness; Ticks lod = least_order->expected_tick - least_order->lateness;
DateTicks odd = od->expected_tick - od->lateness; Ticks odd = od->expected_tick - od->lateness;
if (type == D_ARRIVAL) { if (type == D_ARRIVAL) {
lod -= least_order->scheduled_waiting_time > 0 ? least_order->scheduled_waiting_time : least_order->order->GetWaitTime(); lod -= least_order->scheduled_waiting_time > 0 ? least_order->scheduled_waiting_time : least_order->order->GetWaitTime();

@ -23,7 +23,7 @@ struct Depot : DepotPool::PoolItem<&_depot_pool> {
TileIndex xy; TileIndex xy;
Town *town; Town *town;
TinyString name; TinyString name;
Date build_date; ///< Date of construction CalTime::Date build_date; ///< Date of construction
Depot(TileIndex xy = INVALID_TILE) : xy(xy) {} Depot(TileIndex xy = INVALID_TILE) : xy(xy) {}
~Depot(); ~Depot();

@ -946,8 +946,8 @@ static void Disaster_CoalMine_Init()
struct Disaster { struct Disaster {
DisasterInitProc *init_proc; ///< The init function for this disaster. DisasterInitProc *init_proc; ///< The init function for this disaster.
Year min_year; ///< The first year this disaster will occur. CalTime::Year min_year; ///< The first year this disaster will occur.
Year max_year; ///< The last year this disaster will occur. CalTime::Year max_year; ///< The last year this disaster will occur.
}; };
static const Disaster _disasters[] = { static const Disaster _disasters[] = {
@ -967,7 +967,7 @@ void DoDisaster()
byte j = 0; byte j = 0;
for (size_t i = 0; i != lengthof(_disasters); i++) { for (size_t i = 0; i != lengthof(_disasters); i++) {
if (_cur_year >= _disasters[i].min_year && _cur_year < _disasters[i].max_year) buf[j++] = (byte)i; if (CalTime::CurYear() >= _disasters[i].min_year && CalTime::CurYear() < _disasters[i].max_year) buf[j++] = (byte)i;
} }
if (j == 0) return; if (j == 0) return;

@ -806,7 +806,7 @@ static void CompaniesGenStatistics()
cur_company.Restore(); cur_company.Restore();
/* Only run the economic statics and update company stats every 3rd month (1st of quarter). */ /* Only run the economic statics and update company stats every 3rd month (1st of quarter). */
if (!HasBit(1 << 0 | 1 << 3 | 1 << 6 | 1 << 9, _cur_date_ymd.month)) return; if ((EconTime::CurMonth() % 3) == 0) return;
for (Company *c : Company::Iterate()) { for (Company *c : Company::Iterate()) {
/* Drop the oldest history off the end */ /* Drop the oldest history off the end */
@ -851,9 +851,9 @@ bool AddInflation(bool check_year)
* it impossible due to the diverging cost and income rates. * it impossible due to the diverging cost and income rates.
*/ */
if (_settings_game.economy.inflation_fixed_dates) { if (_settings_game.economy.inflation_fixed_dates) {
if (check_year && (_cur_year < ORIGINAL_BASE_YEAR || _cur_year >= ORIGINAL_MAX_YEAR)) return true; if (check_year && (CalTime::CurYear() < CalTime::ORIGINAL_BASE_YEAR || CalTime::CurYear() >= CalTime::ORIGINAL_MAX_YEAR)) return true;
} else { } else {
if (check_year && (_cur_year - _settings_game.game_creation.starting_year) >= (ORIGINAL_MAX_YEAR - ORIGINAL_BASE_YEAR)) return true; if (check_year && (CalTime::CurYear() - _settings_game.game_creation.starting_year) >= (CalTime::ORIGINAL_MAX_YEAR - CalTime::ORIGINAL_BASE_YEAR)) return true;
} }
if (_economy.inflation_prices == MAX_INFLATION || _economy.inflation_payment == MAX_INFLATION) return true; if (_economy.inflation_prices == MAX_INFLATION || _economy.inflation_payment == MAX_INFLATION) return true;
@ -964,8 +964,8 @@ static void CompaniesPayInterest()
if (c->money < 0) { if (c->money < 0) {
yearly_fee += -c->money *_economy.interest_rate / 100; yearly_fee += -c->money *_economy.interest_rate / 100;
} }
Money up_to_previous_month = yearly_fee * _cur_date_ymd.month / 12; Money up_to_previous_month = yearly_fee * EconTime::CurMonth() / 12;
Money up_to_this_month = yearly_fee * (_cur_date_ymd.month + 1) / 12; Money up_to_this_month = yearly_fee * (EconTime::CurMonth() + 1) / 12;
SubtractMoneyFromCompany(CommandCost(EXPENSES_LOAN_INTEREST, up_to_this_month - up_to_previous_month)); SubtractMoneyFromCompany(CommandCost(EXPENSES_LOAN_INTEREST, up_to_this_month - up_to_previous_month));
@ -1048,7 +1048,7 @@ void StartupEconomy()
if (_settings_game.economy.inflation && _settings_game.economy.inflation_fixed_dates) { if (_settings_game.economy.inflation && _settings_game.economy.inflation_fixed_dates) {
/* Apply inflation that happened before our game start year. */ /* Apply inflation that happened before our game start year. */
int months = (std::min(_cur_year, ORIGINAL_MAX_YEAR) - ORIGINAL_BASE_YEAR) * 12; int months = (std::min(CalTime::CurYear(), CalTime::ORIGINAL_MAX_YEAR) - CalTime::ORIGINAL_BASE_YEAR).base() * 12;
for (int i = 0; i < months; i++) { for (int i = 0; i < months; i++) {
AddInflation(false); AddInflation(false);
} }
@ -1197,7 +1197,7 @@ uint DeliverGoodsToIndustryNearestFirst(const Station *st, CargoID cargo_type, u
uint amount = std::min(num_pieces, 0xFFFFu - ind->incoming_cargo_waiting[cargo_index]); uint amount = std::min(num_pieces, 0xFFFFu - ind->incoming_cargo_waiting[cargo_index]);
ind->incoming_cargo_waiting[cargo_index] += amount; ind->incoming_cargo_waiting[cargo_index] += amount;
ind->last_cargo_accepted_at[cargo_index] = _date; ind->last_cargo_accepted_at[cargo_index] = EconTime::CurDate();
num_pieces -= amount; num_pieces -= amount;
accepted += amount; accepted += amount;
@ -1242,7 +1242,7 @@ uint DeliverGoodsToIndustryEqually(const Station *st, CargoID cargo_type, uint n
if (e.delivered == 0) return; if (e.delivered == 0) return;
include(_cargo_delivery_destinations, e.ind); include(_cargo_delivery_destinations, e.ind);
e.ind->incoming_cargo_waiting[e.cargo_index] += e.delivered; e.ind->incoming_cargo_waiting[e.cargo_index] += e.delivered;
e.ind->last_cargo_accepted_at[e.cargo_index] = _date; e.ind->last_cargo_accepted_at[e.cargo_index] = EconTime::CurDate();
AddCargoDelivery(cargo_type, company, e.delivered, SourceType::Industry, source, st, e.ind->index); AddCargoDelivery(cargo_type, company, e.delivered, SourceType::Industry, source, st, e.ind->index);
}; };
@ -2191,7 +2191,7 @@ static void LoadUnloadVehicle(Vehicle *front)
/* if last speed is 0, we treat that as if no vehicle has ever visited the station. */ /* if last speed is 0, we treat that as if no vehicle has ever visited the station. */
ge->last_speed = ClampTo<uint8_t>(t); ge->last_speed = ClampTo<uint8_t>(t);
ge->last_age = ClampTo<uint8_t>(_cur_year - front->build_year); ge->last_age = ClampTo<uint8_t>(DateDeltaToYearDelta(front->age));
assert(v->cargo_cap >= v->cargo.StoredCount()); assert(v->cargo_cap >= v->cargo.StoredCount());
/* Capacity available for loading more cargo. */ /* Capacity available for loading more cargo. */
@ -2451,14 +2451,21 @@ void LoadUnloadStation(Station *st)
/** /**
* Monthly update of the economic data (of the companies as well as economic fluctuations). * Monthly update of the economic data (of the companies as well as economic fluctuations).
*/ */
void CompaniesMonthlyLoop() void CompaniesCalendarMonthlyLoop()
{ {
CompaniesPayInterest();
CompaniesGenStatistics();
if (_settings_game.economy.inflation) { if (_settings_game.economy.inflation) {
AddInflation(); AddInflation();
RecomputePrices(); RecomputePrices();
} }
}
/**
* Monthly update of the economic data (of the companies as well as economic fluctuations).
*/
void CompaniesEconomyMonthlyLoop()
{
CompaniesPayInterest();
CompaniesGenStatistics();
HandleEconomyFluctuations(); HandleEconomyFluctuations();
} }
@ -2518,7 +2525,7 @@ CommandCost CmdBuyShareInCompany(TileIndex tile, DoCommandFlag flags, uint32_t p
if (c == nullptr || !_settings_game.economy.allow_shares || _current_company == target_company) return CMD_ERROR; if (c == nullptr || !_settings_game.economy.allow_shares || _current_company == target_company) return CMD_ERROR;
/* Protect new companies from hostile takeovers */ /* Protect new companies from hostile takeovers */
if (_cur_year - c->inaugurated_year < _settings_game.economy.min_years_for_shares) return_cmd_error(STR_ERROR_PROTECTED); if (CalTime::CurYear() - c->inaugurated_year < _settings_game.economy.min_years_for_shares) return_cmd_error(STR_ERROR_PROTECTED);
/* Those lines are here for network-protection (clients can be slow) */ /* Those lines are here for network-protection (clients can be slow) */
if (GetAmountOwnedBy(c, COMPANY_SPECTATOR) == 0) return cost; if (GetAmountOwnedBy(c, COMPANY_SPECTATOR) == 0) return cost;

@ -45,7 +45,7 @@ EngineOverrideManager _engine_mngr;
* Year that engine aging stops. Engines will not reduce in reliability * Year that engine aging stops. Engines will not reduce in reliability
* and no more engines will be introduced * and no more engines will be introduced
*/ */
static Year _year_engine_aging_stops; static CalTime::Year _year_engine_aging_stops;
/** Number of engines of each vehicle type in original engine data */ /** Number of engines of each vehicle type in original engine data */
const uint8_t _engine_counts[4] = { const uint8_t _engine_counts[4] = {
@ -487,7 +487,7 @@ uint Engine::GetDisplayMaxTractiveEffort() const
DateDelta Engine::GetLifeLengthInDays() const DateDelta Engine::GetLifeLengthInDays() const
{ {
/* Assume leap years; this gives the player a bit more than the given amount of years, but never less. */ /* Assume leap years; this gives the player a bit more than the given amount of years, but never less. */
return static_cast<int32_t>(this->info.lifelength + _settings_game.vehicle.extend_vehicle_life) * DAYS_IN_LEAP_YEAR; return (this->info.lifelength + _settings_game.vehicle.extend_vehicle_life).base() * DAYS_IN_LEAP_YEAR;
} }
/** /**
@ -651,8 +651,8 @@ static void ClearLastVariant(EngineID engine_id, VehicleType type)
static void RetireEngineIfPossible(Engine *e, int age_threshold) static void RetireEngineIfPossible(Engine *e, int age_threshold)
{ {
if (_settings_game.vehicle.no_expire_vehicles_after > 0) { if (_settings_game.vehicle.no_expire_vehicles_after > 0) {
YearMonthDay ymd = ConvertDateToYMD(e->intro_date); CalTime::YearMonthDay ymd = CalTime::ConvertDateToYMD(e->intro_date);
if ((ymd.year * 12) + ymd.month + age_threshold >= _settings_game.vehicle.no_expire_vehicles_after * 12) return; if ((ymd.year.base() * 12) + ymd.month + age_threshold >= _settings_game.vehicle.no_expire_vehicles_after.base() * 12) return;
} }
e->company_avail = 0; e->company_avail = 0;
@ -724,7 +724,7 @@ void SetYearEngineAgingStops()
if (e->type == VEH_TRAIN && e->u.rail.railveh_type == RAILVEH_WAGON) continue; if (e->type == VEH_TRAIN && e->u.rail.railveh_type == RAILVEH_WAGON) continue;
/* Base year ending date on half the model life */ /* Base year ending date on half the model life */
YearMonthDay ymd = ConvertDateToYMD(ei->base_intro + (static_cast<int32_t>(ei->lifelength) * DAYS_IN_LEAP_YEAR) / 2); CalTime::YearMonthDay ymd = CalTime::ConvertDateToYMD(ei->base_intro + (ei->lifelength.base() * DAYS_IN_LEAP_YEAR) / 2);
_year_engine_aging_stops = std::max(_year_engine_aging_stops, ymd.year); _year_engine_aging_stops = std::max(_year_engine_aging_stops, ymd.year);
} }
@ -736,7 +736,7 @@ void SetYearEngineAgingStops()
* @param aging_date The date used for age calculations. * @param aging_date The date used for age calculations.
* @param seed Random seed. * @param seed Random seed.
*/ */
void StartupOneEngine(Engine *e, Date aging_date, const YearMonthDay &aging_ymd, uint32_t seed, Date no_introduce_after_date) void StartupOneEngine(Engine *e, CalTime::Date aging_date, const CalTime::YearMonthDay &aging_ymd, uint32_t seed, CalTime::Date no_introduce_after_date)
{ {
const EngineInfo *ei = &e->info; const EngineInfo *ei = &e->info;
@ -758,11 +758,11 @@ void StartupOneEngine(Engine *e, Date aging_date, const YearMonthDay &aging_ymd,
/* Don't randomise the start-date in the first two years after gamestart to ensure availability /* Don't randomise the start-date in the first two years after gamestart to ensure availability
* of engines in early starting games. * of engines in early starting games.
* Note: TTDP uses fixed 1922 */ * Note: TTDP uses fixed 1922 */
e->intro_date = ei->base_intro <= ConvertYMDToDate(_settings_game.game_creation.starting_year + 2, 0, 1) ? ei->base_intro : (DateDelta)GB(r, 0, 9) + ei->base_intro; e->intro_date = ei->base_intro <= CalTime::ConvertYMDToDate(_settings_game.game_creation.starting_year + 2, 0, 1) ? ei->base_intro : (DateDelta)GB(r, 0, 9) + ei->base_intro;
if (e->intro_date <= _date && e->intro_date <= no_introduce_after_date) { if (e->intro_date <= CalTime::CurDate() && e->intro_date <= no_introduce_after_date) {
YearMonthDay intro_ymd = ConvertDateToYMD(e->intro_date); CalTime::YearMonthDay intro_ymd = CalTime::ConvertDateToYMD(e->intro_date);
int aging_months = aging_ymd.year * 12 + aging_ymd.month; int aging_months = aging_ymd.year.base() * 12 + aging_ymd.month;
int intro_months = intro_ymd.year * 12 + intro_ymd.month; int intro_months = intro_ymd.year.base() * 12 + intro_ymd.month;
if (intro_ymd.day > 1) intro_months++; // Engines are introduced at the first month start at/after intro date. if (intro_ymd.day > 1) intro_months++; // Engines are introduced at the first month start at/after intro date.
e->age = aging_months - intro_months; e->age = aging_months - intro_months;
e->company_avail = MAX_UVALUE(CompanyMask); e->company_avail = MAX_UVALUE(CompanyMask);
@ -777,7 +777,7 @@ void StartupOneEngine(Engine *e, Date aging_date, const YearMonthDay &aging_ymd,
SetRandomSeed(_settings_game.game_creation.generation_seed ^ seed ^ SetRandomSeed(_settings_game.game_creation.generation_seed ^ seed ^
(re->index << 16) ^ (re->info.base_intro.base() << 12) ^ (re->info.decay_speed << 8) ^ (re->index << 16) ^ (re->info.base_intro.base() << 12) ^ (re->info.decay_speed << 8) ^
(re->info.lifelength << 4) ^ re->info.retire_early ^ (re->info.lifelength.base() << 4) ^ re->info.retire_early ^
e->type ^ e->type ^
e->GetGRFID()); e->GetGRFID());
@ -799,7 +799,7 @@ void StartupOneEngine(Engine *e, Date aging_date, const YearMonthDay &aging_ymd,
e->reliability_final = GB(r, 16, 14) + RELIABILITY_FINAL; e->reliability_final = GB(r, 16, 14) + RELIABILITY_FINAL;
e->duration_phase_1 = GB(r, 0, 5) + 7; e->duration_phase_1 = GB(r, 0, 5) + 7;
e->duration_phase_2 = std::max(0, int(GB(r, 5, 4)) + ei->base_life * 12 - 96); e->duration_phase_2 = std::max(0, int(GB(r, 5, 4)) + ei->base_life.base() * 12 - 96);
e->duration_phase_3 = GB(r, 9, 7) + 120; e->duration_phase_3 = GB(r, 9, 7) + 120;
RestoreRandomSeeds(saved_seeds); RestoreRandomSeeds(saved_seeds);
@ -820,16 +820,16 @@ void StartupOneEngine(Engine *e, Date aging_date, const YearMonthDay &aging_ymd,
void StartupEngines() void StartupEngines()
{ {
/* Aging of vehicles stops, so account for that when starting late */ /* Aging of vehicles stops, so account for that when starting late */
Year aging_stop_year = _year_engine_aging_stops; CalTime::Year aging_stop_year = _year_engine_aging_stops;
if (_settings_game.vehicle.no_introduce_vehicles_after > 0 && _settings_game.vehicle.no_expire_vehicles_after > 0) { if (_settings_game.vehicle.no_introduce_vehicles_after > 0 && _settings_game.vehicle.no_expire_vehicles_after > 0) {
aging_stop_year = std::min<Year>(aging_stop_year, std::max<Year>(_settings_game.vehicle.no_introduce_vehicles_after, _settings_game.vehicle.no_expire_vehicles_after)); aging_stop_year = std::min<CalTime::Year>(aging_stop_year, std::max<CalTime::Year>(_settings_game.vehicle.no_introduce_vehicles_after, _settings_game.vehicle.no_expire_vehicles_after));
} }
const Date aging_date = std::min(_date, ConvertYMDToDate(aging_stop_year, 0, 1)); const CalTime::Date aging_date = std::min(CalTime::CurDate(), CalTime::ConvertYMDToDate(aging_stop_year, 0, 1));
const YearMonthDay aging_ymd = ConvertDateToYMD(aging_date); const CalTime::YearMonthDay aging_ymd = CalTime::ConvertDateToYMD(aging_date);
Date no_introduce_after_date = INT_MAX; CalTime::Date no_introduce_after_date = INT_MAX;
if (_settings_game.vehicle.no_introduce_vehicles_after > 0) { if (_settings_game.vehicle.no_introduce_vehicles_after > 0) {
no_introduce_after_date = ConvertYMDToDate(_settings_game.vehicle.no_introduce_vehicles_after, 0, 1) - 1; no_introduce_after_date = CalTime::ConvertYMDToDate(_settings_game.vehicle.no_introduce_vehicles_after, 0, 1) - 1;
} }
uint32_t seed = Random(); uint32_t seed = Random();
@ -994,11 +994,11 @@ static bool IsVehicleTypeDisabled(VehicleType type, bool ai)
void EnginesDailyLoop() void EnginesDailyLoop()
{ {
for (Company *c : Company::Iterate()) { for (Company *c : Company::Iterate()) {
c->avail_railtypes = AddDateIntroducedRailTypes(c->avail_railtypes, _date); c->avail_railtypes = AddDateIntroducedRailTypes(c->avail_railtypes, CalTime::CurDate());
c->avail_roadtypes = AddDateIntroducedRoadTypes(c->avail_roadtypes, _date); c->avail_roadtypes = AddDateIntroducedRoadTypes(c->avail_roadtypes, CalTime::CurDate());
} }
if (_cur_year >= _year_engine_aging_stops) return; if (CalTime::CurYear() >= _year_engine_aging_stops) return;
for (Engine *e : Engine::Iterate()) { for (Engine *e : Engine::Iterate()) {
EngineID i = e->index; EngineID i = e->index;
@ -1160,11 +1160,11 @@ static void NewVehicleAvailable(Engine *e)
if (e->type == VEH_TRAIN) { if (e->type == VEH_TRAIN) {
/* maybe make another rail type available */ /* maybe make another rail type available */
assert(e->u.rail.railtype < RAILTYPE_END); assert(e->u.rail.railtype < RAILTYPE_END);
for (Company *c : Company::Iterate()) c->avail_railtypes = AddDateIntroducedRailTypes(c->avail_railtypes | GetRailTypeInfo(e->u.rail.railtype)->introduces_railtypes, _date); for (Company *c : Company::Iterate()) c->avail_railtypes = AddDateIntroducedRailTypes(c->avail_railtypes | GetRailTypeInfo(e->u.rail.railtype)->introduces_railtypes, CalTime::CurDate());
} else if (e->type == VEH_ROAD) { } else if (e->type == VEH_ROAD) {
/* maybe make another road type available */ /* maybe make another road type available */
assert(e->u.road.roadtype < ROADTYPE_END); assert(e->u.road.roadtype < ROADTYPE_END);
for (Company *c : Company::Iterate()) c->avail_roadtypes = AddDateIntroducedRoadTypes(c->avail_roadtypes | GetRoadTypeInfo(e->u.road.roadtype)->introduces_roadtypes, _date); for (Company *c : Company::Iterate()) c->avail_roadtypes = AddDateIntroducedRoadTypes(c->avail_roadtypes | GetRoadTypeInfo(e->u.road.roadtype)->introduces_roadtypes, CalTime::CurDate());
} }
/* Only broadcast event if AIs are able to build this vehicle type. */ /* Only broadcast event if AIs are able to build this vehicle type. */
@ -1189,13 +1189,13 @@ static void NewVehicleAvailable(Engine *e)
/** Monthly update of the availability, reliability, and preview offers of the engines. */ /** Monthly update of the availability, reliability, and preview offers of the engines. */
void EnginesMonthlyLoop() void EnginesMonthlyLoop()
{ {
if (_cur_year < _year_engine_aging_stops) { if (CalTime::CurYear() < _year_engine_aging_stops) {
Date no_introduce_after = INT_MAX; CalTime::Date no_introduce_after = INT_MAX;
if (_settings_game.vehicle.no_introduce_vehicles_after > 0) { if (_settings_game.vehicle.no_introduce_vehicles_after > 0) {
if (_settings_game.vehicle.no_expire_vehicles_after > 0 && _cur_year >= std::max<Year>(_settings_game.vehicle.no_introduce_vehicles_after, _settings_game.vehicle.no_expire_vehicles_after)) { if (_settings_game.vehicle.no_expire_vehicles_after > 0 && CalTime::CurYear() >= std::max<CalTime::Year>(_settings_game.vehicle.no_introduce_vehicles_after, _settings_game.vehicle.no_expire_vehicles_after)) {
return; return;
} }
no_introduce_after = ConvertYMDToDate(_settings_game.vehicle.no_introduce_vehicles_after, 0, 1) - 1; no_introduce_after = CalTime::ConvertYMDToDate(_settings_game.vehicle.no_introduce_vehicles_after, 0, 1) - 1;
} }
bool refresh = false; bool refresh = false;
@ -1212,10 +1212,10 @@ void EnginesMonthlyLoop()
if (e->intro_date > no_introduce_after) continue; if (e->intro_date > no_introduce_after) continue;
if (!(e->flags & ENGINE_AVAILABLE) && _date >= (e->intro_date + DAYS_IN_YEAR)) { if (!(e->flags & ENGINE_AVAILABLE) && CalTime::CurDate() >= (e->intro_date + DAYS_IN_YEAR)) {
/* Introduce it to all companies */ /* Introduce it to all companies */
NewVehicleAvailable(e); NewVehicleAvailable(e);
} else if (!(e->flags & (ENGINE_AVAILABLE | ENGINE_EXCLUSIVE_PREVIEW)) && _date >= e->intro_date) { } else if (!(e->flags & (ENGINE_AVAILABLE | ENGINE_EXCLUSIVE_PREVIEW)) && CalTime::CurDate() >= e->intro_date) {
/* Introduction date has passed... /* Introduction date has passed...
* Check if it is allowed to build this vehicle type at all * Check if it is allowed to build this vehicle type at all
* based on the current game settings. If not, it does not * based on the current game settings. If not, it does not
@ -1372,7 +1372,7 @@ bool IsEngineRefittable(EngineID engine)
*/ */
void CheckEngines() void CheckEngines()
{ {
Date min_date = INT32_MAX; CalTime::Date min_date = INT32_MAX;
for (const Engine *e : Engine::Iterate()) { for (const Engine *e : Engine::Iterate()) {
if (!e->IsEnabled()) continue; if (!e->IsEnabled()) continue;

@ -44,7 +44,7 @@ struct EngineRefitCapacityValue {
struct Engine : EnginePool::PoolItem<&_engine_pool> { struct Engine : EnginePool::PoolItem<&_engine_pool> {
TinyString name; ///< Custom name of engine. TinyString name; ///< Custom name of engine.
Date intro_date; ///< Date of introduction of the engine. CalTime::Date intro_date; ///< Date of introduction of the engine.
int32_t age; ///< Age of the engine in months. int32_t age; ///< Age of the engine in months.
uint16_t reliability; ///< Current reliability of the engine. uint16_t reliability; ///< Current reliability of the engine.
uint16_t reliability_spd_dec; ///< Speed of reliability decay between services (per day). uint16_t reliability_spd_dec; ///< Speed of reliability decay between services (per day).

@ -27,7 +27,7 @@ bool IsEngineBuildable(EngineID engine, VehicleType type, CompanyID company);
bool IsEngineRefittable(EngineID engine); bool IsEngineRefittable(EngineID engine);
void SetYearEngineAgingStops(); void SetYearEngineAgingStops();
void CalcEngineReliability(Engine *e, bool new_month); void CalcEngineReliability(Engine *e, bool new_month);
void StartupOneEngine(Engine *e, Date aging_date, const YearMonthDay &aging_ymd, uint32_t seed, Date no_introduce_after_date); void StartupOneEngine(Engine *e, CalTime::Date aging_date, const CalTime::YearMonthDay &aging_ymd, uint32_t seed, CalTime::Date no_introduce_after_date);
uint GetTotalCapacityOfArticulatedParts(EngineID engine); uint GetTotalCapacityOfArticulatedParts(EngineID engine);

@ -141,9 +141,9 @@ DECLARE_ENUM_AS_BIT_SET(ExtraEngineFlags);
* @see table/engines.h * @see table/engines.h
*/ */
struct EngineInfo { struct EngineInfo {
Date base_intro; ///< Basic date of engine introduction (without random parts). CalTime::Date base_intro; ///< Basic date of engine introduction (without random parts).
Year lifelength; ///< Lifetime of a single vehicle YearDelta lifelength; ///< Lifetime of a single vehicle
Year base_life; ///< Basic duration of engine availability (without random parts). \c 0xFF means infinite life. YearDelta base_life; ///< Basic duration of engine availability (without random parts). \c 0xFF means infinite life.
byte decay_speed; byte decay_speed;
byte load_amount; byte load_amount;
byte climates; ///< Climates supported by the engine. byte climates; ///< Climates supported by the engine.

@ -22,8 +22,8 @@ GameEventFlags _game_events_since_load;
GameEventFlags _game_events_overall; GameEventFlags _game_events_overall;
time_t _game_load_time; time_t _game_load_time;
YearMonthDay _game_load_cur_date_ymd; EconTime::YearMonthDay _game_load_cur_date_ymd;
DateFract _game_load_date_fract; EconTime::DateFract _game_load_date_fract;
uint8_t _game_load_tick_skip_counter; uint8_t _game_load_tick_skip_counter;
StateTicks _game_load_state_ticks; StateTicks _game_load_state_ticks;
@ -47,8 +47,8 @@ char *DumpGameEventFlags(GameEventFlags events, char *b, const char *last)
struct SpecialEventLogEntry { struct SpecialEventLogEntry {
std::string msg; std::string msg;
Date date; EconTime::Date date;
DateFract date_fract; EconTime::DateFract date_fract;
uint8_t tick_skip_counter; uint8_t tick_skip_counter;
CompanyID current_company; CompanyID current_company;
CompanyID local_company; CompanyID local_company;
@ -56,7 +56,7 @@ struct SpecialEventLogEntry {
SpecialEventLogEntry() { } SpecialEventLogEntry() { }
SpecialEventLogEntry(std::string msg) SpecialEventLogEntry(std::string msg)
: msg(std::move(msg)), date(_date), date_fract(_date_fract), tick_skip_counter(_tick_skip_counter), : msg(std::move(msg)), date(EconTime::CurDate()), date_fract(EconTime::CurDateFract()), tick_skip_counter(TickSkipCounter()),
current_company(_current_company), local_company(_local_company) { } current_company(_current_company), local_company(_local_company) { }
}; };
@ -95,9 +95,9 @@ char *DumpSpecialEventsLog(char *buffer, const char *last)
} }
const SpecialEventLogEntry &entry = _special_event_log.log[log_index]; const SpecialEventLogEntry &entry = _special_event_log.log[log_index];
YearMonthDay ymd = ConvertDateToYMD(entry.date); EconTime::YearMonthDay ymd = EconTime::ConvertDateToYMD(entry.date);
buffer += seprintf(buffer, last, " %3u | %4i-%02i-%02i, %2i, %3i | cc: %3u, lc: %3u | %s\n", buffer += seprintf(buffer, last, " %3u | %4i-%02i-%02i, %2i, %3i | cc: %3u, lc: %3u | %s\n",
i, ymd.year, ymd.month + 1, ymd.day, entry.date_fract, entry.tick_skip_counter, (uint) entry.current_company, (uint) entry.local_company, entry.msg.c_str()); i, ymd.year.base(), ymd.month + 1, ymd.day, entry.date_fract, entry.tick_skip_counter, (uint) entry.current_company, (uint) entry.local_company, entry.msg.c_str());
} }
return buffer; return buffer;
} }
@ -111,7 +111,7 @@ void LogGameLoadDateTimes(char *buffer, const char *last)
{ {
if (_game_load_time != 0) { if (_game_load_time != 0) {
buffer += seprintf(buffer, last, "Game loaded at: %i-%02i-%02i (%i, %i), (" OTTD_PRINTF64 " state ticks ago), ", buffer += seprintf(buffer, last, "Game loaded at: %i-%02i-%02i (%i, %i), (" OTTD_PRINTF64 " state ticks ago), ",
_game_load_cur_date_ymd.year, _game_load_cur_date_ymd.month + 1, _game_load_cur_date_ymd.day, _game_load_cur_date_ymd.year.base(), _game_load_cur_date_ymd.month + 1, _game_load_cur_date_ymd.day,
_game_load_date_fract, _game_load_tick_skip_counter, (_state_ticks - _game_load_state_ticks).base()); _game_load_date_fract, _game_load_tick_skip_counter, (_state_ticks - _game_load_state_ticks).base());
buffer += UTCTime::Format(buffer, last, _game_load_time, "%Y-%m-%d %H:%M:%S"); buffer += UTCTime::Format(buffer, last, _game_load_time, "%Y-%m-%d %H:%M:%S");
buffer += seprintf(buffer, last, "\n"); buffer += seprintf(buffer, last, "\n");

@ -31,8 +31,8 @@ extern GameEventFlags _game_events_since_load;
extern GameEventFlags _game_events_overall; extern GameEventFlags _game_events_overall;
extern time_t _game_load_time; extern time_t _game_load_time;
extern YearMonthDay _game_load_cur_date_ymd; extern EconTime::YearMonthDay _game_load_cur_date_ymd;
extern DateFract _game_load_date_fract; extern EconTime::DateFract _game_load_date_fract;
extern uint8_t _game_load_tick_skip_counter; extern uint8_t _game_load_tick_skip_counter;
extern StateTicks _game_load_state_ticks; extern StateTicks _game_load_state_ticks;

@ -535,7 +535,7 @@ public:
/* Start date (if available) */ /* Start date (if available) */
if (_load_check_data.settings.game_creation.starting_year != 0) { if (_load_check_data.settings.game_creation.starting_year != 0) {
SetDParam(0, ConvertYMDToDate(_load_check_data.settings.game_creation.starting_year, 0, 1)); SetDParam(0, CalTime::ConvertYMDToDate(_load_check_data.settings.game_creation.starting_year, 0, 1));
DrawString(tr, STR_NETWORK_SERVER_LIST_START_DATE); DrawString(tr, STR_NETWORK_SERVER_LIST_START_DATE);
tr.top += GetCharacterHeight(FS_NORMAL); tr.top += GetCharacterHeight(FS_NORMAL);
} }

@ -211,7 +211,7 @@ static void _GenerateWorld()
if (_debug_desync_level > 0) { if (_debug_desync_level > 0) {
char name[MAX_PATH]; char name[MAX_PATH];
seprintf(name, lastof(name), "dmp_cmds_%08x_%08x.sav", _settings_game.game_creation.generation_seed, _date.base()); seprintf(name, lastof(name), "dmp_cmds_%08x_%08x.sav", _settings_game.game_creation.generation_seed, EconTime::CurDate().base());
SaveOrLoad(name, SLO_SAVE, DFT_GAME_FILE, AUTOSAVE_DIR, false, SMF_ZSTD_OK); SaveOrLoad(name, SLO_SAVE, DFT_GAME_FILE, AUTOSAVE_DIR, false, SMF_ZSTD_OK);
} }
} catch (AbortGenerateWorldSignal&) { } catch (AbortGenerateWorldSignal&) {

@ -482,7 +482,7 @@ struct GenerateLandscapeWindow : public Window {
void SetStringParameters(WidgetID widget) const override void SetStringParameters(WidgetID widget) const override
{ {
switch (widget) { switch (widget) {
case WID_GL_START_DATE_TEXT: SetDParam(0, ConvertYMDToDate(_settings_newgame.game_creation.starting_year, 0, 1)); break; case WID_GL_START_DATE_TEXT: SetDParam(0, CalTime::ConvertYMDToDate(_settings_newgame.game_creation.starting_year, 0, 1)); break;
case WID_GL_MAPSIZE_X_PULLDOWN: SetDParam(0, 1LL << _settings_newgame.game_creation.map_x); break; case WID_GL_MAPSIZE_X_PULLDOWN: SetDParam(0, 1LL << _settings_newgame.game_creation.map_x); break;
case WID_GL_MAPSIZE_Y_PULLDOWN: SetDParam(0, 1LL << _settings_newgame.game_creation.map_y); break; case WID_GL_MAPSIZE_Y_PULLDOWN: SetDParam(0, 1LL << _settings_newgame.game_creation.map_y); break;
case WID_GL_HEIGHTMAP_HEIGHT_TEXT: SetDParam(0, _settings_newgame.game_creation.heightmap_height); break; case WID_GL_HEIGHTMAP_HEIGHT_TEXT: SetDParam(0, _settings_newgame.game_creation.heightmap_height); break;
@ -619,8 +619,8 @@ struct GenerateLandscapeWindow : public Window {
this->SetWidgetDisabledState(WID_GL_HEIGHTMAP_HEIGHT_DOWN, _settings_newgame.game_creation.heightmap_height <= MIN_HEIGHTMAP_HEIGHT); this->SetWidgetDisabledState(WID_GL_HEIGHTMAP_HEIGHT_DOWN, _settings_newgame.game_creation.heightmap_height <= MIN_HEIGHTMAP_HEIGHT);
this->SetWidgetDisabledState(WID_GL_HEIGHTMAP_HEIGHT_UP, _settings_newgame.game_creation.heightmap_height >= GetMapHeightLimit()); this->SetWidgetDisabledState(WID_GL_HEIGHTMAP_HEIGHT_UP, _settings_newgame.game_creation.heightmap_height >= GetMapHeightLimit());
} }
this->SetWidgetDisabledState(WID_GL_START_DATE_DOWN, _settings_newgame.game_creation.starting_year <= MIN_YEAR); this->SetWidgetDisabledState(WID_GL_START_DATE_DOWN, _settings_newgame.game_creation.starting_year <= CalTime::MIN_YEAR);
this->SetWidgetDisabledState(WID_GL_START_DATE_UP, _settings_newgame.game_creation.starting_year >= MAX_YEAR); this->SetWidgetDisabledState(WID_GL_START_DATE_UP, _settings_newgame.game_creation.starting_year >= CalTime::MAX_YEAR);
this->SetWidgetDisabledState(WID_GL_SNOW_COVERAGE_DOWN, _settings_newgame.game_creation.snow_coverage <= 0 || _settings_newgame.game_creation.landscape != LT_ARCTIC); this->SetWidgetDisabledState(WID_GL_SNOW_COVERAGE_DOWN, _settings_newgame.game_creation.snow_coverage <= 0 || _settings_newgame.game_creation.landscape != LT_ARCTIC);
this->SetWidgetDisabledState(WID_GL_SNOW_COVERAGE_UP, _settings_newgame.game_creation.snow_coverage >= 100 || _settings_newgame.game_creation.landscape != LT_ARCTIC); this->SetWidgetDisabledState(WID_GL_SNOW_COVERAGE_UP, _settings_newgame.game_creation.snow_coverage >= 100 || _settings_newgame.game_creation.landscape != LT_ARCTIC);
this->SetWidgetDisabledState(WID_GL_DESERT_COVERAGE_DOWN, _settings_newgame.game_creation.desert_coverage <= 0 || _settings_newgame.game_creation.landscape != LT_TROPIC); this->SetWidgetDisabledState(WID_GL_DESERT_COVERAGE_DOWN, _settings_newgame.game_creation.desert_coverage <= 0 || _settings_newgame.game_creation.landscape != LT_TROPIC);
@ -660,7 +660,7 @@ struct GenerateLandscapeWindow : public Window {
break; break;
case WID_GL_START_DATE_TEXT: case WID_GL_START_DATE_TEXT:
SetDParam(0, ConvertYMDToDate(MAX_YEAR, 0, 1)); SetDParam(0, CalTime::ConvertYMDToDate(CalTime::MAX_YEAR, 0, 1));
d = GetStringBoundingBox(STR_JUST_DATE_LONG); d = GetStringBoundingBox(STR_JUST_DATE_LONG);
break; break;
@ -835,7 +835,7 @@ struct GenerateLandscapeWindow : public Window {
if (!(this->flags & WF_TIMEOUT) || this->timeout_timer <= 1) { if (!(this->flags & WF_TIMEOUT) || this->timeout_timer <= 1) {
this->HandleButtonClick(widget); this->HandleButtonClick(widget);
_settings_newgame.game_creation.starting_year = Clamp(_settings_newgame.game_creation.starting_year + widget - WID_GL_START_DATE_TEXT, MIN_YEAR, MAX_YEAR); _settings_newgame.game_creation.starting_year = Clamp(_settings_newgame.game_creation.starting_year + widget - WID_GL_START_DATE_TEXT, CalTime::MIN_YEAR, CalTime::MAX_YEAR);
this->InvalidateData(); this->InvalidateData();
} }
_left_button_clicked = false; _left_button_clicked = false;
@ -1079,7 +1079,7 @@ struct GenerateLandscapeWindow : public Window {
/* An empty string means revert to the default */ /* An empty string means revert to the default */
switch (this->widget_id) { switch (this->widget_id) {
case WID_GL_HEIGHTMAP_HEIGHT_TEXT: value = MAP_HEIGHT_LIMIT_AUTO_MINIMUM; break; case WID_GL_HEIGHTMAP_HEIGHT_TEXT: value = MAP_HEIGHT_LIMIT_AUTO_MINIMUM; break;
case WID_GL_START_DATE_TEXT: value = DEF_START_YEAR; break; case WID_GL_START_DATE_TEXT: value = CalTime::DEF_START_YEAR.base(); break;
case WID_GL_SNOW_COVERAGE_TEXT: value = DEF_SNOW_COVERAGE; break; case WID_GL_SNOW_COVERAGE_TEXT: value = DEF_SNOW_COVERAGE; break;
case WID_GL_DESERT_COVERAGE_TEXT: value = DEF_DESERT_COVERAGE; break; case WID_GL_DESERT_COVERAGE_TEXT: value = DEF_DESERT_COVERAGE; break;
case WID_GL_TOWN_PULLDOWN: value = 1; break; case WID_GL_TOWN_PULLDOWN: value = 1; break;
@ -1100,7 +1100,7 @@ struct GenerateLandscapeWindow : public Window {
case WID_GL_START_DATE_TEXT: case WID_GL_START_DATE_TEXT:
this->SetWidgetDirty(WID_GL_START_DATE_TEXT); this->SetWidgetDirty(WID_GL_START_DATE_TEXT);
_settings_newgame.game_creation.starting_year = Clamp(value, MIN_YEAR, MAX_YEAR); _settings_newgame.game_creation.starting_year = Clamp<CalTime::Year>(value, CalTime::MIN_YEAR, CalTime::MAX_YEAR);
break; break;
case WID_GL_SNOW_COVERAGE_TEXT: case WID_GL_SNOW_COVERAGE_TEXT:
@ -1238,7 +1238,7 @@ struct CreateScenarioWindow : public Window
{ {
switch (widget) { switch (widget) {
case WID_CS_START_DATE_TEXT: case WID_CS_START_DATE_TEXT:
SetDParam(0, ConvertYMDToDate(_settings_newgame.game_creation.starting_year, 0, 1)); SetDParam(0, CalTime::ConvertYMDToDate(_settings_newgame.game_creation.starting_year, 0, 1));
break; break;
case WID_CS_MAPSIZE_X_PULLDOWN: case WID_CS_MAPSIZE_X_PULLDOWN:
@ -1257,8 +1257,8 @@ struct CreateScenarioWindow : public Window
void OnPaint() override void OnPaint() override
{ {
this->SetWidgetDisabledState(WID_CS_START_DATE_DOWN, _settings_newgame.game_creation.starting_year <= MIN_YEAR); this->SetWidgetDisabledState(WID_CS_START_DATE_DOWN, _settings_newgame.game_creation.starting_year <= CalTime::MIN_YEAR);
this->SetWidgetDisabledState(WID_CS_START_DATE_UP, _settings_newgame.game_creation.starting_year >= MAX_YEAR); this->SetWidgetDisabledState(WID_CS_START_DATE_UP, _settings_newgame.game_creation.starting_year >= CalTime::MAX_YEAR);
this->SetWidgetDisabledState(WID_CS_FLAT_LAND_HEIGHT_DOWN, _settings_newgame.game_creation.se_flat_world_height <= 0); this->SetWidgetDisabledState(WID_CS_FLAT_LAND_HEIGHT_DOWN, _settings_newgame.game_creation.se_flat_world_height <= 0);
this->SetWidgetDisabledState(WID_CS_FLAT_LAND_HEIGHT_UP, _settings_newgame.game_creation.se_flat_world_height >= GetMapHeightLimit()); this->SetWidgetDisabledState(WID_CS_FLAT_LAND_HEIGHT_UP, _settings_newgame.game_creation.se_flat_world_height >= GetMapHeightLimit());
@ -1281,7 +1281,7 @@ struct CreateScenarioWindow : public Window
break; break;
case WID_CS_START_DATE_TEXT: case WID_CS_START_DATE_TEXT:
SetDParam(0, ConvertYMDToDate(MAX_YEAR, 0, 1)); SetDParam(0, CalTime::ConvertYMDToDate(CalTime::MAX_YEAR, 0, 1));
str = STR_JUST_DATE_LONG; str = STR_JUST_DATE_LONG;
break; break;
@ -1339,7 +1339,7 @@ struct CreateScenarioWindow : public Window
this->HandleButtonClick(widget); this->HandleButtonClick(widget);
this->SetDirty(); this->SetDirty();
_settings_newgame.game_creation.starting_year = Clamp(_settings_newgame.game_creation.starting_year + widget - WID_CS_START_DATE_TEXT, MIN_YEAR, MAX_YEAR); _settings_newgame.game_creation.starting_year = Clamp(_settings_newgame.game_creation.starting_year + widget - WID_CS_START_DATE_TEXT, CalTime::MIN_YEAR, CalTime::MAX_YEAR);
} }
_left_button_clicked = false; _left_button_clicked = false;
break; break;
@ -1394,7 +1394,7 @@ struct CreateScenarioWindow : public Window
switch (this->widget_id) { switch (this->widget_id) {
case WID_CS_START_DATE_TEXT: case WID_CS_START_DATE_TEXT:
this->SetWidgetDirty(WID_CS_START_DATE_TEXT); this->SetWidgetDirty(WID_CS_START_DATE_TEXT);
_settings_newgame.game_creation.starting_year = Clamp(value, MIN_YEAR, MAX_YEAR); _settings_newgame.game_creation.starting_year = Clamp<CalTime::Year>(value, CalTime::MIN_YEAR, CalTime::MAX_YEAR);
break; break;
case WID_CS_FLAT_LAND_HEIGHT_TEXT: case WID_CS_FLAT_LAND_HEIGHT_TEXT:

@ -184,8 +184,8 @@ protected:
byte num_vert_lines; byte num_vert_lines;
/* The starting month and year that values are plotted against. */ /* The starting month and year that values are plotted against. */
byte month; EconTime::Month month;
Year year; EconTime::Year year;
bool draw_dates = true; ///< Should we draw months and years on the time axis? bool draw_dates = true; ///< Should we draw months and years on the time axis?
@ -395,8 +395,8 @@ protected:
if (this->draw_dates) { if (this->draw_dates) {
x = r.left; x = r.left;
y = r.bottom + ScaleGUITrad(2); y = r.bottom + ScaleGUITrad(2);
byte month = this->month; EconTime::Month month = this->month;
Year year = this->year; EconTime::Year year = this->year;
for (int i = 0; i < this->num_on_x_axis; i++) { for (int i = 0; i < this->num_on_x_axis; i++) {
SetDParam(0, month + STR_MONTH_ABBREV_JAN); SetDParam(0, month + STR_MONTH_ABBREV_JAN);
SetDParam(1, year); SetDParam(1, year);
@ -518,8 +518,8 @@ public:
/* Draw x-axis labels and markings for graphs based on financial quarters and years. */ /* Draw x-axis labels and markings for graphs based on financial quarters and years. */
if (this->draw_dates) { if (this->draw_dates) {
byte month = this->month; EconTime::Month month = this->month;
Year year = this->year; EconTime::Year year = this->year;
for (int i = 0; i < this->num_on_x_axis; i++) { for (int i = 0; i < this->num_on_x_axis; i++) {
SetDParam(0, month + STR_MONTH_ABBREV_JAN); SetDParam(0, month + STR_MONTH_ABBREV_JAN);
SetDParam(1, year); SetDParam(1, year);
@ -598,8 +598,8 @@ public:
nums = std::min(this->num_vert_lines, std::max(nums, c->num_valid_stat_ent)); nums = std::min(this->num_vert_lines, std::max(nums, c->num_valid_stat_ent));
} }
int mo = (_cur_date_ymd.month / 3 - nums) * 3; int mo = (EconTime::CurMonth() / 3 - nums) * 3;
int yr = _cur_year; EconTime::Year yr = EconTime::CurYear();
while (mo < 0) { while (mo < 0) {
yr--; yr--;
mo += 12; mo += 12;
@ -950,8 +950,8 @@ struct DeliveredCargoGraphWindow : ExcludingCargoBaseGraphWindow {
nums = std::min(this->num_vert_lines, std::max(nums, c->num_valid_stat_ent)); nums = std::min(this->num_vert_lines, std::max(nums, c->num_valid_stat_ent));
} }
int mo = (_cur_date_ymd.month / 3 - nums) * 3; int mo = (EconTime::CurMonth() / 3 - nums) * 3;
int yr = _cur_year; EconTime::Year yr = EconTime::CurYear();
while (mo < 0) { while (mo < 0) {
yr--; yr--;
mo += 12; mo += 12;

@ -104,8 +104,8 @@ DECLARE_ENUM_AS_BIT_SET(HouseCtrlFlags)
struct HouseSpec { struct HouseSpec {
/* Standard properties */ /* Standard properties */
Year min_year; ///< introduction year of the house CalTime::Year min_year; ///< introduction year of the house
Year max_year; ///< last year it can be built CalTime::Year max_year; ///< last year it can be built
byte population; ///< population (Zero on other tiles in multi tile house.) byte population; ///< population (Zero on other tiles in multi tile house.)
byte removal_cost; ///< cost multiplier for removing it byte removal_cost; ///< cost multiplier for removing it
StringID building_name; ///< building name StringID building_name; ///< building name

@ -21,7 +21,7 @@
typedef Pool<Industry, IndustryID, 64, 64000> IndustryPool; typedef Pool<Industry, IndustryID, 64, 64000> IndustryPool;
extern IndustryPool _industry_pool; extern IndustryPool _industry_pool;
static const Year PROCESSING_INDUSTRY_ABANDONMENT_YEARS = 5; ///< If a processing industry doesn't produce for this many consecutive years, it may close. static const YearDelta PROCESSING_INDUSTRY_ABANDONMENT_YEARS = 5; ///< If a processing industry doesn't produce for this many consecutive years, it may close.
/** /**
* Production level maximum, minimum and default values. * Production level maximum, minimum and default values.
@ -63,7 +63,7 @@ DECLARE_ENUM_AS_BIT_SET(IndustryControlFlags);
struct Industry : IndustryPool::PoolItem<&_industry_pool> { struct Industry : IndustryPool::PoolItem<&_industry_pool> {
IndustryType type; ///< Type of industry. IndustryType type; ///< Type of industry.
Owner owner; ///< Owner of the industry. Which SHOULD always be (imho) OWNER_NONE Owner owner; ///< Owner of the industry. Which SHOULD always be (imho) OWNER_NONE
Date construction_date; ///< Date of the construction of the industry CalTime::Date construction_date; ///< Date of the construction of the industry
TileArea location; ///< Location of the industry TileArea location; ///< Location of the industry
Town *town; ///< Nearest town Town *town; ///< Nearest town
Station *neutral_station; ///< Associated neutral station Station *neutral_station; ///< Associated neutral station
@ -84,7 +84,7 @@ struct Industry : IndustryPool::PoolItem<&_industry_pool> {
uint16_t counter; ///< used for animation and/or production (if available cargo) uint16_t counter; ///< used for animation and/or production (if available cargo)
byte prod_level; ///< general production level byte prod_level; ///< general production level
Colours random_colour; ///< randomized colour of the industry, for display purpose Colours random_colour; ///< randomized colour of the industry, for display purpose
Year last_prod_year; ///< last year of production EconTime::Year last_prod_year; ///< last year of production
byte was_cargo_delivered; ///< flag that indicate this has been the closest industry chosen for cargo delivery by a station. see DeliverGoodsToIndustry byte was_cargo_delivered; ///< flag that indicate this has been the closest industry chosen for cargo delivery by a station. see DeliverGoodsToIndustry
IndustryControlFlags ctlflags; ///< flags overriding standard behaviours IndustryControlFlags ctlflags; ///< flags overriding standard behaviours
@ -95,7 +95,7 @@ struct Industry : IndustryPool::PoolItem<&_industry_pool> {
byte selected_layout; ///< Which tile layout was used when creating the industry byte selected_layout; ///< Which tile layout was used when creating the industry
Owner exclusive_supplier; ///< Which company has exclusive rights to deliver cargo (INVALID_OWNER = anyone) Owner exclusive_supplier; ///< Which company has exclusive rights to deliver cargo (INVALID_OWNER = anyone)
Owner exclusive_consumer; ///< Which company has exclusive rights to take cargo (INVALID_OWNER = anyone) Owner exclusive_consumer; ///< Which company has exclusive rights to take cargo (INVALID_OWNER = anyone)
Date last_cargo_accepted_at[INDUSTRY_NUM_INPUTS]; ///< Last day each cargo type was accepted by this industry EconTime::Date last_cargo_accepted_at[INDUSTRY_NUM_INPUTS]; ///< Last day each cargo type was accepted by this industry
std::string text; ///< General text with additional information. std::string text; ///< General text with additional information.
uint16_t random; ///< Random value used for randomisation of all kinds of things uint16_t random; ///< Random value used for randomisation of all kinds of things

@ -1853,11 +1853,11 @@ static void DoCreateNewIndustry(Industry *i, TileIndex tile, IndustryType type,
i->counter = GB(r, 4, 12); i->counter = GB(r, 4, 12);
i->random = initial_random_bits; i->random = initial_random_bits;
i->was_cargo_delivered = false; i->was_cargo_delivered = false;
i->last_prod_year = _cur_year; i->last_prod_year = EconTime::CurYear();
i->founder = founder; i->founder = founder;
i->ctlflags = INDCTL_NONE; i->ctlflags = INDCTL_NONE;
i->construction_date = _date; i->construction_date = CalTime::CurDate();
i->construction_type = (_game_mode == GM_EDITOR) ? ICT_SCENARIO_EDITOR : i->construction_type = (_game_mode == GM_EDITOR) ? ICT_SCENARIO_EDITOR :
(_generating_world ? ICT_MAP_GENERATION : ICT_NORMAL_GAMEPLAY); (_generating_world ? ICT_MAP_GENERATION : ICT_NORMAL_GAMEPLAY);
@ -2393,8 +2393,8 @@ static uint16_t GetIndustryGamePlayProbability(IndustryType it, byte *min_number
const IndustrySpec *ind_spc = GetIndustrySpec(it); const IndustrySpec *ind_spc = GetIndustrySpec(it);
byte chance = ind_spc->appear_ingame[_settings_game.game_creation.landscape]; byte chance = ind_spc->appear_ingame[_settings_game.game_creation.landscape];
if (!ind_spc->enabled || ind_spc->layouts.empty() || if (!ind_spc->enabled || ind_spc->layouts.empty() ||
((ind_spc->behaviour & INDUSTRYBEH_BEFORE_1950) && _cur_year > 1950) || ((ind_spc->behaviour & INDUSTRYBEH_BEFORE_1950) && CalTime::CurYear() > 1950) ||
((ind_spc->behaviour & INDUSTRYBEH_AFTER_1960) && _cur_year < 1960) || ((ind_spc->behaviour & INDUSTRYBEH_AFTER_1960) && CalTime::CurYear() < 1960) ||
(chance = GetIndustryProbabilityCallback(it, IACT_RANDOMCREATION, chance)) == 0) { (chance = GetIndustryProbabilityCallback(it, IACT_RANDOMCREATION, chance)) == 0) {
*min_number = 0; *min_number = 0;
return 0; return 0;
@ -2566,7 +2566,7 @@ static void UpdateIndustryStatistics(Industry *i)
if (i->produced_cargo[j] != INVALID_CARGO) { if (i->produced_cargo[j] != INVALID_CARGO) {
byte pct = 0; byte pct = 0;
if (i->this_month_production[j] != 0) { if (i->this_month_production[j] != 0) {
i->last_prod_year = _cur_year; i->last_prod_year = EconTime::CurYear();
pct = ClampTo<byte>(i->this_month_transported[j] * 256 / i->this_month_production[j]); pct = ClampTo<byte>(i->this_month_transported[j] * 256 / i->this_month_production[j]);
} }
i->last_month_pct_transported[j] = pct; i->last_month_pct_transported[j] = pct;
@ -2993,7 +2993,7 @@ static void ChangeIndustryProduction(Industry *i, bool monthly)
} }
if (!callback_enabled && (indspec->life_type & INDUSTRYLIFE_PROCESSING)) { if (!callback_enabled && (indspec->life_type & INDUSTRYLIFE_PROCESSING)) {
if ((_cur_year - i->last_prod_year) >= PROCESSING_INDUSTRY_ABANDONMENT_YEARS && Chance16(1, original_economy ? 2 : 180)) { if ((EconTime::CurYear() - i->last_prod_year) >= PROCESSING_INDUSTRY_ABANDONMENT_YEARS && Chance16(1, original_economy ? 2 : 180)) {
closeit = true; closeit = true;
} }
} }

@ -562,7 +562,7 @@ byte GetSnowLineUncached()
{ {
if (_snow_line == nullptr) return _settings_game.game_creation.snow_line_height; if (_snow_line == nullptr) return _settings_game.game_creation.snow_line_height;
return _snow_line->table[_cur_date_ymd.month][_cur_date_ymd.day]; return _snow_line->table[CalTime::CurMonth()][CalTime::CurDay()];
} }
void UpdateCachedSnowLine() void UpdateCachedSnowLine()
@ -754,7 +754,7 @@ void RunTileLoop(bool apply_day_length)
/* We update every tile every 256 ticks, so divide the map size by 2^8 = 256 */ /* We update every tile every 256 ticks, so divide the map size by 2^8 = 256 */
uint count; uint count;
if (apply_day_length && DayLengthFactor() > 1) { if (apply_day_length && DayLengthFactor() > 1) {
count = _tile_loop_counts[_tick_skip_counter]; count = _tile_loop_counts[TickSkipCounter()];
if (count == 0) return; if (count == 0) return;
} else { } else {
count = 1 << (MapLogX() + MapLogY() - 8); count = 1 << (MapLogX() + MapLogY() - 8);

@ -30,7 +30,7 @@ inline void LinkGraph::BaseNode::Init(TileIndex xy, StationID st, uint demand)
this->supply = 0; this->supply = 0;
this->demand = demand; this->demand = demand;
this->station = st; this->station = st;
this->last_update = INVALID_DATE; this->last_update = EconTime::INVALID_DATE;
} }
/** /**
@ -42,13 +42,13 @@ void LinkGraph::ShiftDates(DateDelta interval)
{ {
for (NodeID node1 = 0; node1 < this->Size(); ++node1) { for (NodeID node1 = 0; node1 < this->Size(); ++node1) {
BaseNode &source = this->nodes[node1]; BaseNode &source = this->nodes[node1];
if (source.last_update != INVALID_DATE) source.last_update += interval; if (source.last_update != EconTime::INVALID_DATE) source.last_update += interval;
} }
for (auto &it : this->edges) { for (auto &it : this->edges) {
BaseEdge &edge = it.second; BaseEdge &edge = it.second;
if (edge.last_unrestricted_update != INVALID_DATE) edge.last_unrestricted_update += interval; if (edge.last_unrestricted_update != EconTime::INVALID_DATE) edge.last_unrestricted_update += interval;
if (edge.last_restricted_update != INVALID_DATE) edge.last_restricted_update += interval; if (edge.last_restricted_update != EconTime::INVALID_DATE) edge.last_restricted_update += interval;
if (edge.last_aircraft_update != INVALID_DATE) edge.last_aircraft_update += interval; if (edge.last_aircraft_update != EconTime::INVALID_DATE) edge.last_aircraft_update += interval;
} }
} }
@ -172,9 +172,9 @@ static void AddEdge(LinkGraph::BaseEdge &edge, uint capacity, uint usage, uint32
edge.capacity = capacity; edge.capacity = capacity;
edge.usage = usage; edge.usage = usage;
edge.travel_time_sum = static_cast<uint64_t>(travel_time) * capacity; edge.travel_time_sum = static_cast<uint64_t>(travel_time) * capacity;
if (mode & EUM_UNRESTRICTED) edge.last_unrestricted_update = _date; if (mode & EUM_UNRESTRICTED) edge.last_unrestricted_update = EconTime::CurDate();
if (mode & EUM_RESTRICTED) edge.last_restricted_update = _date; if (mode & EUM_RESTRICTED) edge.last_restricted_update = EconTime::CurDate();
if (mode & EUM_AIRCRAFT) edge.last_aircraft_update = _date; if (mode & EUM_AIRCRAFT) edge.last_aircraft_update = EconTime::CurDate();
} }
/** /**
@ -250,9 +250,9 @@ void LinkGraph::Edge::Update(uint capacity, uint usage, uint32_t travel_time, Ed
} }
edge.usage = std::max(edge.usage, usage); edge.usage = std::max(edge.usage, usage);
} }
if (mode & EUM_UNRESTRICTED) edge.last_unrestricted_update = _date; if (mode & EUM_UNRESTRICTED) edge.last_unrestricted_update = EconTime::CurDate();
if (mode & EUM_RESTRICTED) edge.last_restricted_update = _date; if (mode & EUM_RESTRICTED) edge.last_restricted_update = EconTime::CurDate();
if (mode & EUM_AIRCRAFT) edge.last_aircraft_update = _date; if (mode & EUM_AIRCRAFT) edge.last_aircraft_update = EconTime::CurDate();
} }
/** /**
@ -279,10 +279,10 @@ void AdjustLinkGraphStateTicksBase(StateTicksDelta delta)
void LinkGraphFixupLastCompressionAfterLoad() void LinkGraphFixupLastCompressionAfterLoad()
{ {
/* last_compression was previously a Date, change it to a StateTicks */ /* last_compression was previously a Date, change it to a StateTicks */
for (LinkGraph *lg : LinkGraph::Iterate()) lg->last_compression = DateToStateTicks((Date)lg->last_compression.base()); for (LinkGraph *lg : LinkGraph::Iterate()) lg->last_compression = DateToStateTicks((EconTime::Date)lg->last_compression.base());
for (LinkGraphJob *lgj : LinkGraphJob::Iterate()) { for (LinkGraphJob *lgj : LinkGraphJob::Iterate()) {
LinkGraph *lg = &(const_cast<LinkGraph &>(lgj->Graph())); LinkGraph *lg = &(const_cast<LinkGraph &>(lgj->Graph()));
lg->last_compression = DateToStateTicks((Date)lg->last_compression.base()); lg->last_compression = DateToStateTicks((EconTime::Date)lg->last_compression.base());
} }
} }

@ -57,7 +57,7 @@ public:
uint demand; ///< Acceptance at the station. uint demand; ///< Acceptance at the station.
StationID station; ///< Station ID. StationID station; ///< Station ID.
TileIndex xy; ///< Location of the station referred to by the node. TileIndex xy; ///< Location of the station referred to by the node.
Date last_update; ///< When the supply was last updated. EconTime::Date last_update; ///< When the supply was last updated.
void Init(TileIndex xy = INVALID_TILE, StationID st = INVALID_STATION, uint demand = 0); void Init(TileIndex xy = INVALID_TILE, StationID st = INVALID_STATION, uint demand = 0);
}; };
@ -71,18 +71,18 @@ public:
uint capacity; ///< Capacity of the link. uint capacity; ///< Capacity of the link.
uint usage; ///< Usage of the link. uint usage; ///< Usage of the link.
uint64_t travel_time_sum; ///< Sum of the travel times of the link, in ticks. uint64_t travel_time_sum; ///< Sum of the travel times of the link, in ticks.
Date last_unrestricted_update; ///< When the unrestricted part of the link was last updated. EconTime::Date last_unrestricted_update; ///< When the unrestricted part of the link was last updated.
Date last_restricted_update; ///< When the restricted part of the link was last updated. EconTime::Date last_restricted_update; ///< When the restricted part of the link was last updated.
Date last_aircraft_update; ///< When aircraft capacity of the link was last updated. EconTime::Date last_aircraft_update; ///< When aircraft capacity of the link was last updated.
void Init() void Init()
{ {
this->capacity = 0; this->capacity = 0;
this->usage = 0; this->usage = 0;
this->travel_time_sum = 0; this->travel_time_sum = 0;
this->last_unrestricted_update = INVALID_DATE; this->last_unrestricted_update = EconTime::INVALID_DATE;
this->last_restricted_update = INVALID_DATE; this->last_restricted_update = EconTime::INVALID_DATE;
this->last_aircraft_update = INVALID_DATE; this->last_aircraft_update = EconTime::INVALID_DATE;
} }
BaseEdge() { this->Init(); } BaseEdge() { this->Init(); }
@ -130,25 +130,25 @@ public:
* Get the date of the last update to the edge's unrestricted capacity. * Get the date of the last update to the edge's unrestricted capacity.
* @return Last update. * @return Last update.
*/ */
Date LastUnrestrictedUpdate() const { return this->edge->last_unrestricted_update; } EconTime::Date LastUnrestrictedUpdate() const { return this->edge->last_unrestricted_update; }
/** /**
* Get the date of the last update to the edge's restricted capacity. * Get the date of the last update to the edge's restricted capacity.
* @return Last update. * @return Last update.
*/ */
Date LastRestrictedUpdate() const { return this->edge->last_restricted_update; } EconTime::Date LastRestrictedUpdate() const { return this->edge->last_restricted_update; }
/** /**
* Get the date of the last update to the edge's aircraft capacity. * Get the date of the last update to the edge's aircraft capacity.
* @return Last update. * @return Last update.
*/ */
Date LastAircraftUpdate() const { return this->edge->last_aircraft_update; } EconTime::Date LastAircraftUpdate() const { return this->edge->last_aircraft_update; }
/** /**
* Get the date of the last update to any part of the edge's capacity. * Get the date of the last update to any part of the edge's capacity.
* @return Last update. * @return Last update.
*/ */
Date LastUpdate() const { return std::max(this->edge->last_unrestricted_update, this->edge->last_restricted_update); } EconTime::Date LastUpdate() const { return std::max(this->edge->last_unrestricted_update, this->edge->last_restricted_update); }
}; };
/** /**
@ -192,7 +192,7 @@ public:
* Get node's last update. * Get node's last update.
* @return Last update. * @return Last update.
*/ */
Date LastUpdate() const { return this->node.last_update; } EconTime::Date LastUpdate() const { return this->node.last_update; }
/** /**
* Get the location of the station associated with the node. * Get the location of the station associated with the node.
@ -219,9 +219,9 @@ public:
*/ */
Edge(BaseEdge &edge) : EdgeWrapper<BaseEdge>(edge) {} Edge(BaseEdge &edge) : EdgeWrapper<BaseEdge>(edge) {}
void Update(uint capacity, uint usage, uint32_t time, EdgeUpdateMode mode); void Update(uint capacity, uint usage, uint32_t time, EdgeUpdateMode mode);
void Restrict() { this->edge->last_unrestricted_update = INVALID_DATE; } void Restrict() { this->edge->last_unrestricted_update = EconTime::INVALID_DATE; }
void Release() { this->edge->last_restricted_update = INVALID_DATE; } void Release() { this->edge->last_restricted_update = EconTime::INVALID_DATE; }
void ClearAircraft() { this->edge->last_aircraft_update = INVALID_DATE; } void ClearAircraft() { this->edge->last_aircraft_update = EconTime::INVALID_DATE; }
}; };
/** /**
@ -261,7 +261,7 @@ public:
void UpdateSupply(uint supply) void UpdateSupply(uint supply)
{ {
this->node.supply += supply; this->node.supply += supply;
this->node.last_update = _date; this->node.last_update = EconTime::CurDate();
} }
/** /**

@ -26,10 +26,10 @@ INSTANTIATE_POOL_METHODS(LinkGraphJob)
*/ */
/* static */ Path *Path::invalid_path = new Path(INVALID_NODE, true); /* static */ Path *Path::invalid_path = new Path(INVALID_NODE, true);
static DateTicks GetLinkGraphJobJoinDateTicks(uint duration_multiplier) static EconTime::DateTicks GetLinkGraphJobJoinDateTicks(uint duration_multiplier)
{ {
DateTicksDelta ticks = (_settings_game.linkgraph.recalc_time * DAY_TICKS * duration_multiplier) / (SECONDS_PER_DAY * _settings_game.economy.day_length_factor); DateTicksDelta ticks = (_settings_game.linkgraph.recalc_time * DAY_TICKS * duration_multiplier) / (SECONDS_PER_DAY * _settings_game.economy.day_length_factor);
return ticks + NowDateTicks(); return ticks + EconTime::CurDateTicks();
} }
/** /**
@ -44,7 +44,7 @@ LinkGraphJob::LinkGraphJob(const LinkGraph &orig, uint duration_multiplier) :
link_graph(orig), link_graph(orig),
settings(_settings_game.linkgraph), settings(_settings_game.linkgraph),
join_date_ticks(GetLinkGraphJobJoinDateTicks(duration_multiplier)), join_date_ticks(GetLinkGraphJobJoinDateTicks(duration_multiplier)),
start_date_ticks(NowDateTicks()), start_date_ticks(EconTime::CurDateTicks()),
job_completed(false), job_completed(false),
job_aborted(false) job_aborted(false)
{ {
@ -130,14 +130,14 @@ void LinkGraphJob::FinaliseJob()
LinkGraph::ConstEdge lg_edge = lg->GetConstEdge(edge.From(), edge.To()); LinkGraph::ConstEdge lg_edge = lg->GetConstEdge(edge.From(), edge.To());
if (st2 == nullptr || st2->goods[this->Cargo()].link_graph != this->link_graph.index || if (st2 == nullptr || st2->goods[this->Cargo()].link_graph != this->link_graph.index ||
st2->goods[this->Cargo()].node != edge.To() || st2->goods[this->Cargo()].node != edge.To() ||
lg_edge.LastUpdate() == INVALID_DATE) { lg_edge.LastUpdate() == EconTime::INVALID_DATE) {
/* Edge has been removed. Delete flows. */ /* Edge has been removed. Delete flows. */
StationIDStack erased = flows.DeleteFlows(to); StationIDStack erased = flows.DeleteFlows(to);
/* Delete old flows for source stations which have been deleted /* Delete old flows for source stations which have been deleted
* from the new flows. This avoids flow cycles between old and * from the new flows. This avoids flow cycles between old and
* new flows. */ * new flows. */
while (!erased.IsEmpty()) geflows.erase(erased.Pop()); while (!erased.IsEmpty()) geflows.erase(erased.Pop());
} else if (lg_edge.LastUnrestrictedUpdate() == INVALID_DATE) { } else if (lg_edge.LastUnrestrictedUpdate() == EconTime::INVALID_DATE) {
/* Edge is fully restricted. */ /* Edge is fully restricted. */
flows.RestrictFlows(to); flows.RestrictFlows(to);
} }
@ -242,7 +242,7 @@ void LinkGraphJob::Init()
distance_anno = calculate_distance(); distance_anno = calculate_distance();
} }
if (edge.LastAircraftUpdate() != INVALID_DATE && aircraft_link_scale > 100) { if (edge.LastAircraftUpdate() != EconTime::INVALID_DATE && aircraft_link_scale > 100) {
distance_anno *= aircraft_link_scale; distance_anno *= aircraft_link_scale;
distance_anno /= 100; distance_anno /= 100;
} }

@ -139,8 +139,8 @@ protected:
std::shared_ptr<LinkGraphJobGroup> group; ///< Job group thread the job is running in or nullptr if it's running in the main thread. std::shared_ptr<LinkGraphJobGroup> group; ///< Job group thread the job is running in or nullptr if it's running in the main thread.
const LinkGraphSettings settings; ///< Copy of _settings_game.linkgraph at spawn time. const LinkGraphSettings settings; ///< Copy of _settings_game.linkgraph at spawn time.
DateTicks join_date_ticks; ///< Date when the job is to be joined. EconTime::DateTicks join_date_ticks; ///< Date when the job is to be joined.
DateTicks start_date_ticks; ///< Date when the job was started. EconTime::DateTicks start_date_ticks; ///< Date when the job was started.
NodeAnnotationVector nodes; ///< Extra node data necessary for link graph calculation. NodeAnnotationVector nodes; ///< Extra node data necessary for link graph calculation.
EdgeAnnotationVector edges; ///< Edge data necessary for link graph calculation. EdgeAnnotationVector edges; ///< Edge data necessary for link graph calculation.
std::atomic<bool> job_completed; ///< Is the job still running. This is accessed by multiple threads and reads may be stale. std::atomic<bool> job_completed; ///< Is the job still running. This is accessed by multiple threads and reads may be stale.
@ -263,7 +263,7 @@ public:
* settings have to be brutally const-casted in order to populate them. * settings have to be brutally const-casted in order to populate them.
*/ */
LinkGraphJob() : settings(_settings_game.linkgraph), LinkGraphJob() : settings(_settings_game.linkgraph),
join_date_ticks(INVALID_DATE_TICKS), start_date_ticks(INVALID_DATE_TICKS), job_completed(false), job_aborted(false) {} join_date_ticks(EconTime::INVALID_DATE_TICKS), start_date_ticks(EconTime::INVALID_DATE_TICKS), job_completed(false), job_aborted(false) {}
LinkGraphJob(const LinkGraph &orig, uint duration_multiplier); LinkGraphJob(const LinkGraph &orig, uint duration_multiplier);
~LinkGraphJob(); ~LinkGraphJob();
@ -298,19 +298,19 @@ public:
* @param tick_offset Optional number of ticks to add to the current date * @param tick_offset Optional number of ticks to add to the current date
* @return True if job should be finished by now, false if not. * @return True if job should be finished by now, false if not.
*/ */
inline bool IsScheduledToBeJoined(int tick_offset = 0) const { return this->join_date_ticks <= NowDateTicks() + tick_offset; } inline bool IsScheduledToBeJoined(int tick_offset = 0) const { return this->join_date_ticks <= EconTime::CurDateTicks() + tick_offset; }
/** /**
* Get the date when the job should be finished. * Get the date when the job should be finished.
* @return Join date. * @return Join date.
*/ */
inline DateTicks JoinDateTicks() const { return join_date_ticks; } inline EconTime::DateTicks JoinDateTicks() const { return join_date_ticks; }
/** /**
* Get the date when the job was started. * Get the date when the job was started.
* @return Start date. * @return Start date.
*/ */
inline DateTicks StartDateTicks() const { return start_date_ticks; } inline EconTime::DateTicks StartDateTicks() const { return start_date_ticks; }
/** /**
* Change the start and join dates on date cheating. * Change the start and join dates on date cheating.

@ -87,7 +87,7 @@ void LinkGraphSchedule::SpawnNext()
lg->index, lg->Size(), cost, duration_multiplier); lg->index, lg->Size(), cost, duration_multiplier);
} else { } else {
// find right place to insert // find right place to insert
auto iter = std::upper_bound(this->running.begin(), this->running.end(), job->JoinDateTicks(), [](DateTicks a, const std::unique_ptr<LinkGraphJob> &b) { auto iter = std::upper_bound(this->running.begin(), this->running.end(), job->JoinDateTicks(), [](EconTime::DateTicks a, const std::unique_ptr<LinkGraphJob> &b) {
return a < b->JoinDateTicks(); return a < b->JoinDateTicks();
}); });
this->running.insert(iter, std::move(job)); this->running.insert(iter, std::move(job));
@ -281,11 +281,11 @@ void LinkGraphJobGroup::JoinThread()
std::vector<LinkGraphJob *> bucket; std::vector<LinkGraphJob *> bucket;
uint bucket_cost = 0; uint bucket_cost = 0;
DateTicks bucket_join_date = 0; EconTime::DateTicks bucket_join_date = 0;
auto flush_bucket = [&]() { auto flush_bucket = [&]() {
if (!bucket_cost) return; if (!bucket_cost) return;
DEBUG(linkgraph, 2, "LinkGraphJobGroup::ExecuteJobSet: Creating Job Group: jobs: " PRINTF_SIZE ", cost: %u, join after: " OTTD_PRINTF64, DEBUG(linkgraph, 2, "LinkGraphJobGroup::ExecuteJobSet: Creating Job Group: jobs: " PRINTF_SIZE ", cost: %u, join after: " OTTD_PRINTF64,
bucket.size(), bucket_cost, (bucket_join_date - NowDateTicks()).base()); bucket.size(), bucket_cost, (bucket_join_date - EconTime::CurDateTicks()).base());
auto group = std::make_shared<LinkGraphJobGroup>(constructor_token(), std::move(bucket)); auto group = std::make_shared<LinkGraphJobGroup>(constructor_token(), std::move(bucket));
group->SpawnThread(); group->SpawnThread();
bucket_cost = 0; bucket_cost = 0;
@ -318,12 +318,12 @@ void StateGameLoop_LinkGraphPauseControl()
if (!LinkGraphSchedule::instance.IsJoinWithUnfinishedJobDue()) { if (!LinkGraphSchedule::instance.IsJoinWithUnfinishedJobDue()) {
DoCommandP(0, PM_PAUSED_LINK_GRAPH, 0, CMD_PAUSE); DoCommandP(0, PM_PAUSED_LINK_GRAPH, 0, CMD_PAUSE);
} }
} else if (_pause_mode == PM_UNPAUSED && _tick_skip_counter == 0) { } else if (_pause_mode == PM_UNPAUSED && TickSkipCounter() == 0) {
if (DayLengthFactor() == 1) { if (DayLengthFactor() == 1) {
if (_date_fract != LinkGraphSchedule::SPAWN_JOIN_TICK - 2) return; if (EconTime::CurDateFract() != LinkGraphSchedule::SPAWN_JOIN_TICK - 2) return;
if (_date.base() % _settings_game.linkgraph.recalc_interval != (_settings_game.linkgraph.recalc_interval / SECONDS_PER_DAY) / 2) return; if (EconTime::CurDate().base() % _settings_game.linkgraph.recalc_interval != (_settings_game.linkgraph.recalc_interval / SECONDS_PER_DAY) / 2) return;
} else { } else {
int date_ticks = (NowDateTicks() - (LinkGraphSchedule::SPAWN_JOIN_TICK - 2)).base(); int date_ticks = (EconTime::CurDateTicks() - (LinkGraphSchedule::SPAWN_JOIN_TICK - 2)).base();
int interval = std::max<int>(2, (_settings_game.linkgraph.recalc_interval * DAY_TICKS / (SECONDS_PER_DAY * DayLengthFactor()))); int interval = std::max<int>(2, (_settings_game.linkgraph.recalc_interval * DAY_TICKS / (SECONDS_PER_DAY * DayLengthFactor())));
if (date_ticks % interval != interval / 2) return; if (date_ticks % interval != interval / 2) return;
} }
@ -356,12 +356,12 @@ void OnTick_LinkGraph()
int offset; int offset;
int interval; int interval;
if (DayLengthFactor() == 1) { if (DayLengthFactor() == 1) {
if (_date_fract != LinkGraphSchedule::SPAWN_JOIN_TICK) return; if (EconTime::CurDateFract() != LinkGraphSchedule::SPAWN_JOIN_TICK) return;
interval = _settings_game.linkgraph.recalc_interval / SECONDS_PER_DAY; interval = _settings_game.linkgraph.recalc_interval / SECONDS_PER_DAY;
offset = _date.base() % interval; offset = EconTime::CurDate().base() % interval;
} else { } else {
interval = std::max<int>(2, (_settings_game.linkgraph.recalc_interval * DAY_TICKS / (SECONDS_PER_DAY * DayLengthFactor()))); interval = std::max<int>(2, (_settings_game.linkgraph.recalc_interval * DAY_TICKS / (SECONDS_PER_DAY * DayLengthFactor())));
offset = (NowDateTicks() - LinkGraphSchedule::SPAWN_JOIN_TICK).base() % interval; offset = (EconTime::CurDateTicks() - LinkGraphSchedule::SPAWN_JOIN_TICK).base() % interval;
} }
if (offset == 0) { if (offset == 0) {
LinkGraphSchedule::instance.SpawnNext(); LinkGraphSchedule::instance.SpawnNext();

@ -31,7 +31,7 @@ struct LoadCheckData {
std::string error_msg; ///< Data to pass to SetDParamStr when displaying #error. std::string error_msg; ///< Data to pass to SetDParamStr when displaying #error.
uint32_t map_size_x, map_size_y; uint32_t map_size_x, map_size_y;
Date current_date; CalTime::Date current_date;
GameSettings settings; GameSettings settings;

@ -129,11 +129,12 @@ void InitializeGame(uint size_x, uint size_y, bool reset_date, bool reset_settin
_pause_mode = PM_UNPAUSED; _pause_mode = PM_UNPAUSED;
_pause_countdown = 0; _pause_countdown = 0;
_game_speed = 100; _game_speed = 100;
CalTime::Detail::now.sub_date_fract = 0;
_tick_counter = 0; _tick_counter = 0;
_tick_skip_counter = 0; DateDetail::_tick_skip_counter = 0;
_scaled_tick_counter = 0; _scaled_tick_counter = 0;
_state_ticks = INITIAL_STATE_TICKS_VALUE; _state_ticks = INITIAL_STATE_TICKS_VALUE;
_state_ticks_offset = 0; DateDetail::_state_ticks_offset = 0;
_cur_tileloop_tile = 1; _cur_tileloop_tile = 1;
_aux_tileloop_tile = 1; _aux_tileloop_tile = 1;
_thd.redsq = INVALID_TILE; _thd.redsq = INVALID_TILE;
@ -156,7 +157,10 @@ void InitializeGame(uint size_x, uint size_y, bool reset_date, bool reset_settin
_newgrf_profilers.clear(); _newgrf_profilers.clear();
if (reset_date) { if (reset_date) {
SetDate(ConvertYMDToDate(_settings_game.game_creation.starting_year, 0, 1), 0); CalTime::Detail::SetDate(CalTime::ConvertYMDToDate(_settings_game.game_creation.starting_year, 0, 1), 0);
{
EconTime::Detail::SetDate(CalTime::CurDate().base(), 0);
}
InitializeOldNames(); InitializeOldNames();
} else { } else {
RecalculateStateTicksOffset(); RecalculateStateTicksOffset();

@ -156,7 +156,7 @@ public:
/* Because build_date is not set yet in every TileDesc, we make sure it is empty */ /* Because build_date is not set yet in every TileDesc, we make sure it is empty */
TileDesc td; TileDesc td;
td.build_date = INVALID_DATE; td.build_date = CalTime::INVALID_DATE;
/* Most tiles have only one owner, but /* Most tiles have only one owner, but
* - drivethrough roadstops can be build on town owned roads (up to 2 owners) and * - drivethrough roadstops can be build on town owned roads (up to 2 owners) and
@ -247,7 +247,7 @@ public:
this->landinfo_data.push_back(GetString(STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY)); this->landinfo_data.push_back(GetString(STR_LAND_AREA_INFORMATION_LOCAL_AUTHORITY));
/* Build date */ /* Build date */
if (td.build_date != INVALID_DATE) { if (td.build_date != CalTime::INVALID_DATE) {
SetDParam(0, td.build_date); SetDParam(0, td.build_date);
this->landinfo_data.push_back(GetString(STR_LAND_AREA_INFORMATION_BUILD_DATE)); this->landinfo_data.push_back(GetString(STR_LAND_AREA_INFORMATION_BUILD_DATE));
} }

@ -131,7 +131,7 @@ void CheckGameCompatibility(NetworkGameInfo &ngi, bool extended)
void FillStaticNetworkServerGameInfo() void FillStaticNetworkServerGameInfo()
{ {
_network_game_info.use_password = !_settings_client.network.server_password.empty(); _network_game_info.use_password = !_settings_client.network.server_password.empty();
_network_game_info.start_date = ConvertYMDToDate(_settings_game.game_creation.starting_year, 0, 1); _network_game_info.start_date = CalTime::ConvertYMDToDate(_settings_game.game_creation.starting_year, 0, 1);
_network_game_info.clients_max = _settings_client.network.max_clients; _network_game_info.clients_max = _settings_client.network.max_clients;
_network_game_info.companies_max = _settings_client.network.max_companies; _network_game_info.companies_max = _settings_client.network.max_companies;
_network_game_info.map_width = MapSizeX(); _network_game_info.map_width = MapSizeX();
@ -157,7 +157,7 @@ const NetworkServerGameInfo *GetCurrentNetworkServerGameInfo()
*/ */
_network_game_info.companies_on = (byte)Company::GetNumItems(); _network_game_info.companies_on = (byte)Company::GetNumItems();
_network_game_info.spectators_on = NetworkSpectatorCount(); _network_game_info.spectators_on = NetworkSpectatorCount();
_network_game_info.game_date = _date; _network_game_info.game_date = CalTime::CurDate();
_network_game_info.ticks_playing = _scaled_tick_counter; _network_game_info.ticks_playing = _scaled_tick_counter;
return &_network_game_info; return &_network_game_info;
} }
@ -336,7 +336,7 @@ void SerializeNetworkGameInfoExtended(Packet *p, const NetworkServerGameInfo *in
*/ */
void DeserializeNetworkGameInfo(Packet *p, NetworkGameInfo *info, const GameInfoNewGRFLookupTable *newgrf_lookup_table) void DeserializeNetworkGameInfo(Packet *p, NetworkGameInfo *info, const GameInfoNewGRFLookupTable *newgrf_lookup_table)
{ {
static const Date MAX_DATE = ConvertYMDToDate(MAX_YEAR, 11, 31); // December is month 11 static const CalTime::Date MAX_DATE = CalTime::ConvertYMDToDate(CalTime::MAX_YEAR, 11, 31); // December is month 11
byte game_info_version = p->Recv_uint8(); byte game_info_version = p->Recv_uint8();
NewGRFSerializationType newgrf_serialisation = NST_GRFID_MD5; NewGRFSerializationType newgrf_serialisation = NST_GRFID_MD5;
@ -427,8 +427,8 @@ void DeserializeNetworkGameInfo(Packet *p, NetworkGameInfo *info, const GameInfo
info->clients_on = p->Recv_uint8 (); info->clients_on = p->Recv_uint8 ();
info->spectators_on = p->Recv_uint8 (); info->spectators_on = p->Recv_uint8 ();
if (game_info_version < 3) { // 16 bits dates got scrapped and are read earlier if (game_info_version < 3) { // 16 bits dates got scrapped and are read earlier
info->game_date = p->Recv_uint16() + DAYS_TILL_ORIGINAL_BASE_YEAR; info->game_date = p->Recv_uint16() + CalTime::DAYS_TILL_ORIGINAL_BASE_YEAR;
info->start_date = p->Recv_uint16() + DAYS_TILL_ORIGINAL_BASE_YEAR; info->start_date = p->Recv_uint16() + CalTime::DAYS_TILL_ORIGINAL_BASE_YEAR;
} }
if (game_info_version < 6) while (p->Recv_uint8() != 0) {} // Used to contain the map-name. if (game_info_version < 6) while (p->Recv_uint8() != 0) {} // Used to contain the map-name.
@ -456,7 +456,7 @@ void DeserializeNetworkGameInfo(Packet *p, NetworkGameInfo *info, const GameInfo
*/ */
void DeserializeNetworkGameInfoExtended(Packet *p, NetworkGameInfo *info) void DeserializeNetworkGameInfoExtended(Packet *p, NetworkGameInfo *info)
{ {
static const Date MAX_DATE = ConvertYMDToDate(MAX_YEAR, 11, 31); // December is month 11 static const CalTime::Date MAX_DATE = CalTime::ConvertYMDToDate(CalTime::MAX_YEAR, 11, 31); // December is month 11
const uint8_t version = p->Recv_uint8(); const uint8_t version = p->Recv_uint8();
if (version > SERVER_GAME_INFO_EXTENDED_MAX_VERSION) return; // Unknown version if (version > SERVER_GAME_INFO_EXTENDED_MAX_VERSION) return; // Unknown version

@ -94,8 +94,8 @@ enum NewGRFSerializationType {
*/ */
struct NetworkServerGameInfo { struct NetworkServerGameInfo {
GRFConfig *grfconfig; ///< List of NewGRF files used GRFConfig *grfconfig; ///< List of NewGRF files used
Date start_date; ///< When the game started CalTime::Date start_date; ///< When the game started
Date game_date; ///< Current date CalTime::Date game_date; ///< Current date
uint64_t ticks_playing; ///< Amount of ticks the game has been running unpaused. uint64_t ticks_playing; ///< Amount of ticks the game has been running unpaused.
uint32_t map_width; ///< Map width uint32_t map_width; ///< Map width
uint32_t map_height; ///< Map height uint32_t map_height; ///< Map height

@ -87,8 +87,8 @@ NetworkAddressList _broadcast_list; ///< List of broadcast a
uint32_t _sync_seed_1; ///< Seed to compare during sync checks. uint32_t _sync_seed_1; ///< Seed to compare during sync checks.
uint64_t _sync_state_checksum; ///< State checksum to compare during sync checks. uint64_t _sync_state_checksum; ///< State checksum to compare during sync checks.
uint32_t _sync_frame; ///< The frame to perform the sync check. uint32_t _sync_frame; ///< The frame to perform the sync check.
Date _last_sync_date; ///< The game date of the last successfully received sync frame EconTime::Date _last_sync_date; ///< The game date of the last successfully received sync frame
DateFract _last_sync_date_fract; ///< " EconTime::DateFract _last_sync_date_fract; ///< "
uint8_t _last_sync_tick_skip_counter; ///< " uint8_t _last_sync_tick_skip_counter; ///< "
uint32_t _last_sync_frame_counter; ///< " uint32_t _last_sync_frame_counter; ///< "
bool _network_first_time; ///< Whether we have finished joining or not. bool _network_first_time; ///< Whether we have finished joining or not.
@ -1160,19 +1160,19 @@ void NetworkGameLoop()
if (_network_server) { if (_network_server) {
/* Log the sync state to check for in-syncedness of replays. */ /* Log the sync state to check for in-syncedness of replays. */
if (_date_fract == 0 && _tick_skip_counter == 0) { if (EconTime::CurDateFract() == 0 && TickSkipCounter() == 0) {
/* We don't want to log multiple times if paused. */ /* We don't want to log multiple times if paused. */
static Date last_log; static EconTime::Date last_log;
if (last_log != _date) { if (last_log != EconTime::CurDate()) {
DEBUG(desync, 2, "sync: %s; %08x; %08x", debug_date_dumper().HexDate(), _random.state[0], _random.state[1]); DEBUG(desync, 2, "sync: %s; %08x; %08x", debug_date_dumper().HexDate(), _random.state[0], _random.state[1]);
last_log = _date; last_log = EconTime::CurDate();
} }
} }
#ifdef DEBUG_DUMP_COMMANDS #ifdef DEBUG_DUMP_COMMANDS
/* Loading of the debug commands from -ddesync>=1 */ /* Loading of the debug commands from -ddesync>=1 */
static FILE *f = FioFOpenFile("commands.log", "rb", SAVE_DIR); static FILE *f = FioFOpenFile("commands.log", "rb", SAVE_DIR);
static Date next_date = 0; static EconTime::Date next_date = 0;
static uint next_date_fract; static uint next_date_fract;
static uint next_tick_skip_counter; static uint next_tick_skip_counter;
static std::unique_ptr<CommandPacket> cp; static std::unique_ptr<CommandPacket> cp;
@ -1184,7 +1184,7 @@ void NetworkGameLoop()
} }
while (f != nullptr && !feof(f)) { while (f != nullptr && !feof(f)) {
if (_date == next_date && _date_fract == next_date_fract) { if (EconTime::CurDate() == next_date && EconTime::CurDateFract() == next_date_fract) {
if (cp != nullptr) { if (cp != nullptr) {
NetworkSendCommand(cp->tile, cp->p1, cp->p2, cp->p3, cp->cmd & ~CMD_FLAGS_MASK, nullptr, cp->text.c_str(), cp->company, cp->aux_data.get()); NetworkSendCommand(cp->tile, cp->p1, cp->p2, cp->p3, cp->cmd & ~CMD_FLAGS_MASK, nullptr, cp->text.c_str(), cp->company, cp->aux_data.get());
DEBUG(net, 0, "injecting: %s; %02x; %06x; %08x; %08x; " OTTD_PRINTFHEX64PAD " %08x; \"%s\"%s (%s)", DEBUG(net, 0, "injecting: %s; %02x; %06x; %08x; %08x; " OTTD_PRINTFHEX64PAD " %08x; \"%s\"%s (%s)",

@ -179,7 +179,7 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::SendWelcome()
p->Send_string(""); // Used to be map-name. p->Send_string(""); // Used to be map-name.
p->Send_uint32(_settings_game.game_creation.generation_seed); p->Send_uint32(_settings_game.game_creation.generation_seed);
p->Send_uint8 (_settings_game.game_creation.landscape); p->Send_uint8 (_settings_game.game_creation.landscape);
p->Send_uint32(ConvertYMDToDate(_settings_game.game_creation.starting_year, 0, 1).base()); p->Send_uint32(CalTime::ConvertYMDToDate(_settings_game.game_creation.starting_year, 0, 1).base());
p->Send_uint16(MapSizeX()); p->Send_uint16(MapSizeX());
p->Send_uint16(MapSizeY()); p->Send_uint16(MapSizeY());
@ -209,7 +209,7 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::SendDate()
{ {
Packet *p = new Packet(ADMIN_PACKET_SERVER_DATE); Packet *p = new Packet(ADMIN_PACKET_SERVER_DATE);
p->Send_uint32(_date.base()); p->Send_uint32(CalTime::CurDate().base());
this->SendPacket(p); this->SendPacket(p);
return NETWORK_RECV_STATUS_OKAY; return NETWORK_RECV_STATUS_OKAY;
@ -330,7 +330,7 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCompanyInfo(const Company
p->Send_string(GetString(STR_PRESIDENT_NAME)); p->Send_string(GetString(STR_PRESIDENT_NAME));
p->Send_uint8 (c->colour); p->Send_uint8 (c->colour);
p->Send_bool (NetworkCompanyIsPassworded(c->index)); p->Send_bool (NetworkCompanyIsPassworded(c->index));
p->Send_uint32(c->inaugurated_year); p->Send_uint32(c->inaugurated_year.base());
p->Send_bool (c->is_ai); p->Send_bool (c->is_ai);
p->Send_uint8 (CeilDiv(c->months_of_bankruptcy, 3)); // send as quarters_of_bankruptcy p->Send_uint8 (CeilDiv(c->months_of_bankruptcy, 3)); // send as quarters_of_bankruptcy

@ -25,8 +25,8 @@ struct NetworkClientInfo : NetworkClientInfoPool::PoolItem<&_networkclientinfo_p
ClientID client_id; ///< Client identifier (same as ClientState->client_id) ClientID client_id; ///< Client identifier (same as ClientState->client_id)
std::string client_name; ///< Name of the client std::string client_name; ///< Name of the client
CompanyID client_playas; ///< As which company is this client playing (CompanyID) CompanyID client_playas; ///< As which company is this client playing (CompanyID)
Date join_date; ///< Gamedate the client has joined EconTime::Date join_date; ///< Gamedate the client has joined
DateFract join_date_fract; EconTime::DateFract join_date_fract;
uint8_t join_tick_skip_counter; uint8_t join_tick_skip_counter;
uint32_t join_frame; uint32_t join_frame;

@ -347,9 +347,9 @@ void ClientNetworkGameSocketHandler::ClientError(NetworkRecvStatus res)
CrashLog::WriteDesyncSavegame(desync_log.c_str(), deferred_save.name_buffer.c_str()); CrashLog::WriteDesyncSavegame(desync_log.c_str(), deferred_save.name_buffer.c_str());
return false; return false;
} }
_last_sync_date = _date; _last_sync_date = EconTime::CurDate();
_last_sync_date_fract = _date_fract; _last_sync_date_fract = EconTime::CurDateFract();
_last_sync_tick_skip_counter = _tick_skip_counter; _last_sync_tick_skip_counter = TickSkipCounter();
_last_sync_frame_counter = _sync_frame; _last_sync_frame_counter = _sync_frame;
_network_sync_records.clear(); _network_sync_records.clear();
_network_sync_record_counts.clear(); _network_sync_record_counts.clear();
@ -636,9 +636,9 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::SendDesyncLog(const std::strin
NetworkRecvStatus ClientNetworkGameSocketHandler::SendDesyncMessage(const char *msg) NetworkRecvStatus ClientNetworkGameSocketHandler::SendDesyncMessage(const char *msg)
{ {
Packet *p = new Packet(PACKET_CLIENT_DESYNC_MSG, SHRT_MAX); Packet *p = new Packet(PACKET_CLIENT_DESYNC_MSG, SHRT_MAX);
p->Send_uint32(_date.base()); p->Send_uint32(EconTime::CurDate().base());
p->Send_uint16(_date_fract); p->Send_uint16(EconTime::CurDateFract());
p->Send_uint8(_tick_skip_counter); p->Send_uint8(TickSkipCounter());
p->Send_string(msg); p->Send_string(msg);
my_client->SendPacket(p); my_client->SendPacket(p);
return NETWORK_RECV_STATUS_OKAY; return NETWORK_RECV_STATUS_OKAY;

@ -70,9 +70,10 @@ void NetworkPrintClients();
void NetworkHandlePauseChange(PauseMode prev_mode, PauseMode changed_mode); void NetworkHandlePauseChange(PauseMode prev_mode, PauseMode changed_mode);
/*** Commands ran by the server ***/ /*** Commands ran by the server ***/
void NetworkServerDailyLoop(); void NetworkServerEconomyDailyLoop();
void NetworkServerMonthlyLoop(); void NetworkServerEconomyMonthlyLoop();
void NetworkServerYearlyLoop(); void NetworkServerEconomyYearlyLoop();
void NetworkServerCalendarYearlyLoop();
void NetworkServerSendConfigUpdate(); void NetworkServerSendConfigUpdate();
void NetworkServerUpdateGameInfo(); void NetworkServerUpdateGameInfo();
void NetworkServerShowStatusToConsole(); void NetworkServerShowStatusToConsole();

@ -397,7 +397,7 @@ protected:
if (const NWidgetBase *nwid = this->GetWidget<NWidgetBase>(WID_NG_DATE); nwid->current_x != 0) { if (const NWidgetBase *nwid = this->GetWidget<NWidgetBase>(WID_NG_DATE); nwid->current_x != 0) {
/* current date */ /* current date */
Rect date = nwid->GetCurrentRect(); Rect date = nwid->GetCurrentRect();
YearMonthDay ymd = ConvertDateToYMD(cur_item->info.game_date); CalTime::YearMonthDay ymd = CalTime::ConvertDateToYMD(cur_item->info.game_date);
SetDParam(0, ymd.year); SetDParam(0, ymd.year);
DrawString(date.left, date.right, y + text_y_offset, STR_JUST_INT, TC_BLACK, SA_HOR_CENTER); DrawString(date.left, date.right, y + text_y_offset, STR_JUST_INT, TC_BLACK, SA_HOR_CENTER);
} }
@ -405,8 +405,8 @@ protected:
if (const NWidgetBase *nwid = this->GetWidget<NWidgetBase>(WID_NG_YEARS); nwid->current_x != 0) { if (const NWidgetBase *nwid = this->GetWidget<NWidgetBase>(WID_NG_YEARS); nwid->current_x != 0) {
/* number of years the game is running */ /* number of years the game is running */
Rect years = nwid->GetCurrentRect(); Rect years = nwid->GetCurrentRect();
YearMonthDay ymd_cur = ConvertDateToYMD(cur_item->info.game_date); CalTime::YearMonthDay ymd_cur = CalTime::ConvertDateToYMD(cur_item->info.game_date);
YearMonthDay ymd_start = ConvertDateToYMD(cur_item->info.start_date); CalTime::YearMonthDay ymd_start = CalTime::ConvertDateToYMD(cur_item->info.start_date);
SetDParam(0, ymd_cur.year - ymd_start.year); SetDParam(0, ymd_cur.year - ymd_start.year);
DrawString(years.left, years.right, y + text_y_offset, STR_JUST_INT, TC_BLACK, SA_HOR_CENTER); DrawString(years.left, years.right, y + text_y_offset, STR_JUST_INT, TC_BLACK, SA_HOR_CENTER);
} }

@ -31,7 +31,7 @@ void ShowSurveyResultTextfileWindow();
/** Company information stored at the client side */ /** Company information stored at the client side */
struct NetworkCompanyInfo : NetworkCompanyStats { struct NetworkCompanyInfo : NetworkCompanyStats {
std::string company_name; ///< Company name std::string company_name; ///< Company name
Year inaugurated_year; ///< What year the company started in CalTime::Year inaugurated_year; ///< What year the company started in
Money company_value; ///< The company value Money company_value; ///< The company value
Money money; ///< The amount of money the company has Money money; ///< The amount of money the company has
Money income; ///< How much did the company earn last year Money income; ///< How much did the company earn last year

@ -76,10 +76,10 @@ extern NetworkAddressList _broadcast_list;
extern uint32_t _sync_seed_1; extern uint32_t _sync_seed_1;
extern uint64_t _sync_state_checksum; extern uint64_t _sync_state_checksum;
extern uint32_t _sync_frame; extern uint32_t _sync_frame;
extern Date _last_sync_date; extern EconTime::Date _last_sync_date;
extern DateFract _last_sync_date_fract; extern EconTime::DateFract _last_sync_date_fract;
extern uint8_t _last_sync_tick_skip_counter; extern uint8_t _last_sync_tick_skip_counter;
extern uint32_t _last_sync_frame_counter; extern uint32_t _last_sync_frame_counter;
extern bool _network_first_time; extern bool _network_first_time;
/* Vars needed for the join-GUI */ /* Vars needed for the join-GUI */
extern NetworkJoinStatus _network_join_status; extern NetworkJoinStatus _network_join_status;

@ -1017,9 +1017,9 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_JOIN(Packet *p)
assert(NetworkClientInfo::CanAllocateItem()); assert(NetworkClientInfo::CanAllocateItem());
NetworkClientInfo *ci = new NetworkClientInfo(this->client_id); NetworkClientInfo *ci = new NetworkClientInfo(this->client_id);
this->SetInfo(ci); this->SetInfo(ci);
ci->join_date = _date; ci->join_date = EconTime::CurDate();
ci->join_date_fract = _date_fract; ci->join_date_fract = EconTime::CurDateFract();
ci->join_tick_skip_counter = _tick_skip_counter; ci->join_tick_skip_counter = TickSkipCounter();
ci->join_frame = _frame_counter; ci->join_frame = _frame_counter;
ci->client_name = client_name; ci->client_name = client_name;
ci->client_playas = playas; ci->client_playas = playas;
@ -1322,13 +1322,13 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_DESYNC_LOG(Pack
NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_DESYNC_MSG(Packet *p) NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_DESYNC_MSG(Packet *p)
{ {
Date date = p->Recv_uint32(); EconTime::Date date = p->Recv_uint32();
DateFract date_fract = p->Recv_uint16(); EconTime::DateFract date_fract = p->Recv_uint16();
uint8_t tick_skip_counter = p->Recv_uint8(); uint8_t tick_skip_counter = p->Recv_uint8();
std::string msg; std::string msg;
p->Recv_string(msg); p->Recv_string(msg);
DEBUG(desync, 0, "Client-id %d desync msg: %s", this->client_id, msg.c_str()); DEBUG(desync, 0, "Client-id %d desync msg: %s", this->client_id, msg.c_str());
extern void LogRemoteDesyncMsg(Date date, DateFract date_fract, uint8_t tick_skip_counter, uint32_t src_id, std::string msg); extern void LogRemoteDesyncMsg(EconTime::Date date, EconTime::DateFract date_fract, uint8_t tick_skip_counter, uint32_t src_id, std::string msg);
LogRemoteDesyncMsg(date, date_fract, tick_skip_counter, this->client_id, std::move(msg)); LogRemoteDesyncMsg(date, date_fract, tick_skip_counter, this->client_id, std::move(msg));
return NETWORK_RECV_STATUS_OKAY; return NETWORK_RECV_STATUS_OKAY;
} }
@ -1829,8 +1829,8 @@ void NetworkUpdateClientInfo(ClientID client_id)
/** Check if we want to restart the map */ /** Check if we want to restart the map */
static void NetworkCheckRestartMap() static void NetworkCheckRestartMap()
{ {
if (_settings_client.network.restart_game_year != 0 && _cur_year >= _settings_client.network.restart_game_year) { if (_settings_client.network.restart_game_year != 0 && CalTime::CurYear() >= _settings_client.network.restart_game_year) {
DEBUG(net, 3, "Auto-restarting map: year %d reached", _cur_year); DEBUG(net, 3, "Auto-restarting map: year %d reached", CalTime::CurYear().base());
_settings_newgame.game_creation.generation_seed = GENERATE_NEW_SEED; _settings_newgame.game_creation.generation_seed = GENERATE_NEW_SEED;
switch(_file_to_saveload.abstract_ftype) { switch(_file_to_saveload.abstract_ftype) {
@ -2149,25 +2149,30 @@ void NetworkServer_Tick(bool send_frame)
} }
/** Yearly "callback". Called whenever the year changes. */ /** Yearly "callback". Called whenever the year changes. */
void NetworkServerYearlyLoop() void NetworkServerCalendarYearlyLoop()
{ {
NetworkCheckRestartMap(); NetworkCheckRestartMap();
}
/** Yearly "callback". Called whenever the year changes. */
void NetworkServerEconomyYearlyLoop()
{
NetworkAdminUpdate(ADMIN_FREQUENCY_ANUALLY); NetworkAdminUpdate(ADMIN_FREQUENCY_ANUALLY);
} }
/** Monthly "callback". Called whenever the month changes. */ /** Monthly "callback". Called whenever the month changes. */
void NetworkServerMonthlyLoop() void NetworkServerEconomyMonthlyLoop()
{ {
NetworkAutoCleanCompanies(); NetworkAutoCleanCompanies();
NetworkAdminUpdate(ADMIN_FREQUENCY_MONTHLY); NetworkAdminUpdate(ADMIN_FREQUENCY_MONTHLY);
if ((_cur_date_ymd.month % 3) == 0) NetworkAdminUpdate(ADMIN_FREQUENCY_QUARTERLY); if ((CalTime::CurMonth() % 3) == 0) NetworkAdminUpdate(ADMIN_FREQUENCY_QUARTERLY);
} }
/** Daily "callback". Called whenever the date changes. */ /** Daily "callback". Called whenever the date changes. */
void NetworkServerDailyLoop() void NetworkServerEconomyDailyLoop()
{ {
NetworkAdminUpdate(ADMIN_FREQUENCY_DAILY); NetworkAdminUpdate(ADMIN_FREQUENCY_DAILY);
if ((_date.base() % 7) == 3) NetworkAdminUpdate(ADMIN_FREQUENCY_WEEKLY); if ((CalTime::CurDate().base() % 7) == 3) NetworkAdminUpdate(ADMIN_FREQUENCY_WEEKLY);
} }
/** /**
@ -2458,9 +2463,9 @@ char *NetworkServerDumpClients(char *buffer, const char *last)
ci->client_name.c_str(), ci->client_name.c_str(),
ci->client_playas); ci->client_playas);
if (ci->join_date != 0) { if (ci->join_date != 0) {
YearMonthDay ymd = ConvertDateToYMD(ci->join_date); EconTime::YearMonthDay ymd = EconTime::ConvertDateToYMD(ci->join_date);
buffer += seprintf(buffer, last, ", joined: %4i-%02i-%02i, %i, %i, frame: %08X", buffer += seprintf(buffer, last, ", joined: %4i-%02i-%02i, %i, %i, frame: %08X",
ymd.year, ymd.month + 1, ymd.day, ci->join_date_fract, ci->join_tick_skip_counter, ci->join_frame); ymd.year.base(), ymd.month + 1, ymd.day, ci->join_date_fract, ci->join_tick_skip_counter, ci->join_frame);
} }
buffer += seprintf(buffer, last, "\n"); buffer += seprintf(buffer, last, "\n");
} }

@ -950,7 +950,7 @@ static ChangeInfoResult CommonVehicleChangeInfo(EngineInfo *ei, int prop, const
{ {
switch (prop) { switch (prop) {
case 0x00: // Introduction date case 0x00: // Introduction date
ei->base_intro = buf->ReadWord() + DAYS_TILL_ORIGINAL_BASE_YEAR; ei->base_intro = buf->ReadWord() + CalTime::DAYS_TILL_ORIGINAL_BASE_YEAR;
break; break;
case 0x02: // Decay speed case 0x02: // Decay speed
@ -2166,7 +2166,7 @@ static ChangeInfoResult BridgeChangeInfo(uint brid, int numinfo, int prop, const
case 0x08: { // Year of availability case 0x08: { // Year of availability
/* We treat '0' as always available */ /* We treat '0' as always available */
byte year = buf->ReadByte(); byte year = buf->ReadByte();
bridge->avail_year = (year > 0 ? ORIGINAL_BASE_YEAR + year : 0); bridge->avail_year = (year > 0 ? CalTime::ORIGINAL_BASE_YEAR + year : 0);
break; break;
} }
@ -2227,7 +2227,7 @@ static ChangeInfoResult BridgeChangeInfo(uint brid, int numinfo, int prop, const
break; break;
case 0x0F: // Long format year of availability (year since year 0) case 0x0F: // Long format year of availability (year since year 0)
bridge->avail_year = Clamp(buf->ReadDWord(), MIN_YEAR, MAX_YEAR); bridge->avail_year = Clamp<CalTime::Year>(buf->ReadDWord(), CalTime::MIN_YEAR, CalTime::MAX_YEAR);
break; break;
case 0x10: { // purchase string case 0x10: { // purchase string
@ -2426,8 +2426,8 @@ static ChangeInfoResult TownHouseChangeInfo(uint hid, int numinfo, int prop, con
case 0x0A: { // Availability years case 0x0A: { // Availability years
uint16_t years = buf->ReadWord(); uint16_t years = buf->ReadWord();
housespec->min_year = GB(years, 0, 8) > 150 ? MAX_YEAR : ORIGINAL_BASE_YEAR + GB(years, 0, 8); housespec->min_year = GB(years, 0, 8) > 150 ? CalTime::MAX_YEAR : CalTime::ORIGINAL_BASE_YEAR + GB(years, 0, 8);
housespec->max_year = GB(years, 8, 8) > 150 ? MAX_YEAR : ORIGINAL_BASE_YEAR + GB(years, 8, 8); housespec->max_year = GB(years, 8, 8) > 150 ? CalTime::MAX_YEAR : CalTime::ORIGINAL_BASE_YEAR + GB(years, 8, 8);
break; break;
} }
@ -2764,7 +2764,7 @@ static ChangeInfoResult GlobalVarChangeInfo(uint gvid, int numinfo, int prop, co
case 0x0F: { // Euro introduction dates case 0x0F: { // Euro introduction dates
uint curidx = GetNewgrfCurrencyIdConverted(gvid + i); uint curidx = GetNewgrfCurrencyIdConverted(gvid + i);
Year year_euro = buf->ReadWord(); CalTime::Year year_euro = buf->ReadWord();
if (curidx < CURRENCY_END) { if (curidx < CURRENCY_END) {
_currency_specs[curidx].to_euro = year_euro; _currency_specs[curidx].to_euro = year_euro;
@ -4033,7 +4033,7 @@ static ChangeInfoResult AirportChangeInfo(uint airport, int numinfo, int prop, c
case 0x0C: case 0x0C:
as->min_year = buf->ReadWord(); as->min_year = buf->ReadWord();
as->max_year = buf->ReadWord(); as->max_year = buf->ReadWord();
if (as->max_year == 0xFFFF) as->max_year = MAX_YEAR; if (as->max_year == 0xFFFF) as->max_year = CalTime::MAX_YEAR;
break; break;
case 0x0D: case 0x0D:
@ -7404,16 +7404,16 @@ bool GetGlobalVariable(byte param, uint32_t *value, const GRFFile *grffile)
switch (param) { switch (param) {
case 0x00: // current date case 0x00: // current date
*value = std::max<DateDelta>(_date - DAYS_TILL_ORIGINAL_BASE_YEAR, 0).base(); *value = std::max<DateDelta>(CalTime::CurDate() - CalTime::DAYS_TILL_ORIGINAL_BASE_YEAR, 0).base();
return true; return true;
case 0x01: // current year case 0x01: // current year
*value = Clamp(_cur_year, ORIGINAL_BASE_YEAR, ORIGINAL_MAX_YEAR) - ORIGINAL_BASE_YEAR; *value = (Clamp(CalTime::CurYear(), CalTime::ORIGINAL_BASE_YEAR, CalTime::ORIGINAL_MAX_YEAR) - CalTime::ORIGINAL_BASE_YEAR).base();
return true; return true;
case 0x02: { // detailed date information: month of year (bit 0-7), day of month (bit 8-12), leap year (bit 15), day of year (bit 16-24) case 0x02: { // detailed date information: month of year (bit 0-7), day of month (bit 8-12), leap year (bit 15), day of year (bit 16-24)
Date start_of_year = ConvertYMDToDate(_cur_date_ymd.year, 0, 1); CalTime::Date start_of_year = CalTime::ConvertYMDToDate(CalTime::CurYear(), 0, 1);
*value = _cur_date_ymd.month | (_cur_date_ymd.day - 1) << 8 | (IsLeapYear(_cur_date_ymd.year) ? 1 << 15 : 0) | (_date - start_of_year).base() << 16; *value = CalTime::CurMonth() | (CalTime::CurDay() - 1) << 8 | (CalTime::IsLeapYear(CalTime::CurYear()) ? 1 << 15 : 0) | (CalTime::CurDate() - start_of_year).base() << 16;
return true; return true;
} }
@ -7426,7 +7426,7 @@ bool GetGlobalVariable(byte param, uint32_t *value, const GRFFile *grffile)
return true; return true;
case 0x09: // date fraction case 0x09: // date fraction
*value = _date_fract * 885; *value = CalTime::CurDateFract() * 885;
return true; return true;
case 0x0A: // animation counter case 0x0A: // animation counter
@ -7519,11 +7519,11 @@ bool GetGlobalVariable(byte param, uint32_t *value, const GRFFile *grffile)
return true; return true;
case 0x23: // long format date case 0x23: // long format date
*value = _date.base(); *value = CalTime::CurDate().base();
return true; return true;
case 0x24: // long format year case 0x24: // long format year
*value = _cur_year; *value = CalTime::CurYear().base();
return true; return true;
default: return false; default: return false;
@ -8137,7 +8137,7 @@ static uint32_t GetPatchVariable(uint8_t param)
{ {
switch (param) { switch (param) {
/* start year - 1920 */ /* start year - 1920 */
case 0x0B: return std::max(_settings_game.game_creation.starting_year, ORIGINAL_BASE_YEAR) - ORIGINAL_BASE_YEAR; case 0x0B: return (std::max(_settings_game.game_creation.starting_year, CalTime::ORIGINAL_BASE_YEAR) - CalTime::ORIGINAL_BASE_YEAR).base();
/* freight trains weight factor */ /* freight trains weight factor */
case 0x0E: return _settings_game.vehicle.freight_trains; case 0x0E: return _settings_game.vehicle.freight_trains;
@ -10896,7 +10896,7 @@ static bool IsHouseSpecValid(HouseSpec *hs, const HouseSpec *next1, const HouseS
*/ */
static void EnsureEarlyHouse(HouseZones bitmask) static void EnsureEarlyHouse(HouseZones bitmask)
{ {
Year min_year = MAX_YEAR; CalTime::Year min_year = CalTime::MAX_YEAR;
for (int i = 0; i < NUM_HOUSES; i++) { for (int i = 0; i < NUM_HOUSES; i++) {
HouseSpec *hs = HouseSpec::Get(i); HouseSpec *hs = HouseSpec::Get(i);
@ -11600,22 +11600,19 @@ void LoadNewGRF(uint load_index, uint num_baseset)
* so all NewGRFs are loaded equally. For this we use the * so all NewGRFs are loaded equally. For this we use the
* start date of the game and we set the counters, etc. to * start date of the game and we set the counters, etc. to
* 0 so they're the same too. */ * 0 so they're the same too. */
YearMonthDay date_ymd = _cur_date_ymd; CalTime::State cal_state = CalTime::Detail::now;
Date date = _date; EconTime::State econ_state = EconTime::Detail::now;
DateFract date_fract = _date_fract; uint8_t tick_skip_counter = DateDetail::_tick_skip_counter;
uint64_t tick_counter = _tick_counter; uint64_t tick_counter = _tick_counter;
uint8_t tick_skip_counter = _tick_skip_counter;
uint64_t scaled_tick_counter = _scaled_tick_counter; uint64_t scaled_tick_counter = _scaled_tick_counter;
StateTicks state_ticks = _state_ticks; StateTicks state_ticks = _state_ticks;
StateTicksDelta state_ticks_offset = _state_ticks_offset; StateTicksDelta state_ticks_offset = DateDetail::_state_ticks_offset;
byte display_opt = _display_opt; byte display_opt = _display_opt;
if (_networking) { if (_networking) {
_cur_date_ymd = { _settings_game.game_creation.starting_year, 0, 1}; CalTime::Detail::now = CalTime::Detail::NewState(_settings_game.game_creation.starting_year);
_date = ConvertYMDToDate(_cur_date_ymd); EconTime::Detail::now = EconTime::Detail::NewState(_settings_game.game_creation.starting_year.base());
_date_fract = 0;
_tick_counter = 0; _tick_counter = 0;
_tick_skip_counter = 0;
_scaled_tick_counter = 0; _scaled_tick_counter = 0;
_state_ticks = 0; _state_ticks = 0;
_display_opt = 0; _display_opt = 0;
@ -11718,14 +11715,13 @@ void LoadNewGRF(uint load_index, uint num_baseset)
AfterLoadGRFs(); AfterLoadGRFs();
/* Now revert back to the original situation */ /* Now revert back to the original situation */
_cur_date_ymd = date_ymd; CalTime::Detail::now = cal_state;
_date = date; EconTime::Detail::now = econ_state;
_date_fract = date_fract; DateDetail::_tick_skip_counter = tick_skip_counter;
_tick_counter = tick_counter; _tick_counter = tick_counter;
_tick_skip_counter = tick_skip_counter;
_scaled_tick_counter = scaled_tick_counter; _scaled_tick_counter = scaled_tick_counter;
_state_ticks = state_ticks; _state_ticks = state_ticks;
_state_ticks_offset = state_ticks_offset; DateDetail::_state_ticks_offset = state_ticks_offset;
_display_opt = display_opt; _display_opt = display_opt;
UpdateCachedSnowLine(); UpdateCachedSnowLine();
} }

@ -81,9 +81,9 @@ AirportSpec AirportSpec::specs[NUM_AIRPORTS]; ///< Airport specifications.
bool AirportSpec::IsAvailable() const bool AirportSpec::IsAvailable() const
{ {
if (!this->enabled) return false; if (!this->enabled) return false;
if (_cur_year < this->min_year) return false; if (CalTime::CurYear() < this->min_year) return false;
if (_settings_game.station.never_expire_airports) return true; if (_settings_game.station.never_expire_airports) return true;
return _cur_year <= this->max_year; return CalTime::CurYear() <= this->max_year;
} }
/** /**
@ -169,7 +169,7 @@ void AirportOverrideManager::SetEntitySpec(AirportSpec *as)
case 0x7C: return (this->st->airport.psa != nullptr) ? this->st->airport.psa->GetValue(parameter) : 0; case 0x7C: return (this->st->airport.psa != nullptr) ? this->st->airport.psa->GetValue(parameter) : 0;
case 0xF0: return this->st->facilities; case 0xF0: return this->st->facilities;
case 0xFA: return ClampTo<uint16_t>((this->st->build_date - DAYS_TILL_ORIGINAL_BASE_YEAR).base()); case 0xFA: return ClampTo<uint16_t>((this->st->build_date - CalTime::DAYS_TILL_ORIGINAL_BASE_YEAR).base());
} }
return this->st->GetNewGRFVariable(this->ro, variable, parameter, &(extra->available)); return this->st->GetNewGRFVariable(this->ro, variable, parameter, &(extra->available));

@ -108,8 +108,8 @@ struct AirportSpec {
byte size_y; ///< size of airport in y direction byte size_y; ///< size of airport in y direction
byte noise_level; ///< noise that this airport generates byte noise_level; ///< noise that this airport generates
byte catchment; ///< catchment area of this airport byte catchment; ///< catchment area of this airport
Year min_year; ///< first year the airport is available CalTime::Year min_year; ///< first year the airport is available
Year max_year; ///< last year the airport is available CalTime::Year max_year; ///< last year the airport is available
StringID name; ///< name of this airport StringID name; ///< name of this airport
TTDPAirportType ttd_airport_type; ///< ttdpatch airport type (Small/Large/Helipad/Oilrig) TTDPAirportType ttd_airport_type; ///< ttdpatch airport type (Small/Large/Helipad/Oilrig)
AirportClassID cls_id; ///< the class to which this airport type belongs AirportClassID cls_id; ///< the class to which this airport type belongs

@ -700,7 +700,7 @@ static uint32_t VehicleGetVariable(Vehicle *v, const VehicleScopeResolver *objec
} }
case 0x48: return v->GetEngine()->flags; // Vehicle Type Info case 0x48: return v->GetEngine()->flags; // Vehicle Type Info
case 0x49: return v->build_year; case 0x49: return v->build_year.base();
case 0x4A: case 0x4A:
switch (v->type) { switch (v->type) {
@ -912,8 +912,8 @@ static uint32_t VehicleGetVariable(Vehicle *v, const VehicleScopeResolver *objec
} }
return (variable - 0x80) == 0x10 ? ticks : GB(ticks, 8, 8); return (variable - 0x80) == 0x10 ? ticks : GB(ticks, 8, 8);
} }
case 0x12: return ClampTo<uint16_t>(v->date_of_last_service_newgrf - DAYS_TILL_ORIGINAL_BASE_YEAR); case 0x12: return ClampTo<uint16_t>(v->date_of_last_service_newgrf - CalTime::DAYS_TILL_ORIGINAL_BASE_YEAR);
case 0x13: return GB(ClampTo<uint16_t>(v->date_of_last_service_newgrf - DAYS_TILL_ORIGINAL_BASE_YEAR), 8, 8); case 0x13: return GB(ClampTo<uint16_t>(v->date_of_last_service_newgrf - CalTime::DAYS_TILL_ORIGINAL_BASE_YEAR), 8, 8);
case 0x14: return v->GetServiceInterval(); case 0x14: return v->GetServiceInterval();
case 0x15: return GB(v->GetServiceInterval(), 8, 8); case 0x15: return GB(v->GetServiceInterval(), 8, 8);
case 0x16: return v->last_station_visited; case 0x16: return v->last_station_visited;
@ -974,7 +974,7 @@ static uint32_t VehicleGetVariable(Vehicle *v, const VehicleScopeResolver *objec
case 0x41: return GB(ClampTo<uint16_t>(v->age), 8, 8); case 0x41: return GB(ClampTo<uint16_t>(v->age), 8, 8);
case 0x42: return ClampTo<uint16_t>(v->max_age); case 0x42: return ClampTo<uint16_t>(v->max_age);
case 0x43: return GB(ClampTo<uint16_t>(v->max_age), 8, 8); case 0x43: return GB(ClampTo<uint16_t>(v->max_age), 8, 8);
case 0x44: return Clamp(v->build_year, ORIGINAL_BASE_YEAR, ORIGINAL_MAX_YEAR) - ORIGINAL_BASE_YEAR; case 0x44: return (Clamp(v->build_year, CalTime::ORIGINAL_BASE_YEAR, CalTime::ORIGINAL_MAX_YEAR) - CalTime::ORIGINAL_BASE_YEAR).base();
case 0x45: return v->unitnumber; case 0x45: return v->unitnumber;
case 0x46: return v->GetEngine()->grf_prop.local_id; case 0x46: return v->GetEngine()->grf_prop.local_id;
case 0x47: return GB(v->GetEngine()->grf_prop.local_id, 8, 8); case 0x47: return GB(v->GetEngine()->grf_prop.local_id, 8, 8);
@ -1117,11 +1117,11 @@ static uint32_t VehicleGetVariable(Vehicle *v, const VehicleScopeResolver *objec
} }
} }
case 0x48: return Engine::Get(this->self_type)->flags; // Vehicle Type Info case 0x48: return Engine::Get(this->self_type)->flags; // Vehicle Type Info
case 0x49: return _cur_year; // 'Long' format build year case 0x49: return CalTime::CurYear().base(); // 'Long' format build year
case 0x4B: return _date.base(); // Long date of last service case 0x4B: return CalTime::CurDate().base(); // Long date of last service
case 0x92: return ClampTo<uint16_t>(_date - DAYS_TILL_ORIGINAL_BASE_YEAR); // Date of last service case 0x92: return ClampTo<uint16_t>(CalTime::CurDate() - CalTime::DAYS_TILL_ORIGINAL_BASE_YEAR); // Date of last service
case 0x93: return GB(ClampTo<uint16_t>(_date - DAYS_TILL_ORIGINAL_BASE_YEAR), 8, 8); case 0x93: return GB(ClampTo<uint16_t>(CalTime::CurDate() - CalTime::DAYS_TILL_ORIGINAL_BASE_YEAR), 8, 8);
case 0xC4: return Clamp(_cur_year, ORIGINAL_BASE_YEAR, ORIGINAL_MAX_YEAR) - ORIGINAL_BASE_YEAR; // Build year case 0xC4: return (Clamp(CalTime::CurYear(), CalTime::ORIGINAL_BASE_YEAR, CalTime::ORIGINAL_MAX_YEAR) - CalTime::ORIGINAL_BASE_YEAR).base(); // Build year
case 0xC6: return Engine::Get(this->self_type)->grf_prop.local_id; case 0xC6: return Engine::Get(this->self_type)->grf_prop.local_id;
case 0xC7: return GB(Engine::Get(this->self_type)->grf_prop.local_id, 8, 8); case 0xC7: return GB(Engine::Get(this->self_type)->grf_prop.local_id, 8, 8);
case 0xDA: return INVALID_VEHICLE; // Next vehicle case 0xDA: return INVALID_VEHICLE; // Next vehicle

@ -334,7 +334,7 @@ static uint32_t GetDistanceFromNearbyHouse(uint8_t parameter, TileIndex tile, Ho
case 0x40: return (IsTileType(this->tile, MP_HOUSE) ? GetHouseBuildingStage(this->tile) : 0) | TileHash2Bit(TileX(this->tile), TileY(this->tile)) << 2; case 0x40: return (IsTileType(this->tile, MP_HOUSE) ? GetHouseBuildingStage(this->tile) : 0) | TileHash2Bit(TileX(this->tile), TileY(this->tile)) << 2;
/* Building age. */ /* Building age. */
case 0x41: return IsTileType(this->tile, MP_HOUSE) ? GetHouseAge(this->tile) : 0; case 0x41: return IsTileType(this->tile, MP_HOUSE) ? GetHouseAge(this->tile).base() : 0;
/* Town zone */ /* Town zone */
case 0x42: return GetTownRadiusGroup(this->town, this->tile); case 0x42: return GetTownRadiusGroup(this->town, this->tile);

@ -422,16 +422,16 @@ uint32_t IndustriesScopeResolver::GetCountAndDistanceOfClosestInstance(byte para
case 0xA6: return indspec->grf_prop.local_id; case 0xA6: return indspec->grf_prop.local_id;
case 0xA7: return this->industry->founder; case 0xA7: return this->industry->founder;
case 0xA8: return this->industry->random_colour; case 0xA8: return this->industry->random_colour;
case 0xA9: return ClampTo<uint8_t>(this->industry->last_prod_year - ORIGINAL_BASE_YEAR); case 0xA9: return ClampTo<uint8_t>(this->industry->last_prod_year - EconTime::ORIGINAL_BASE_YEAR);
case 0xAA: return this->industry->counter; case 0xAA: return this->industry->counter;
case 0xAB: return GB(this->industry->counter, 8, 8); case 0xAB: return GB(this->industry->counter, 8, 8);
case 0xAC: return this->industry->was_cargo_delivered; case 0xAC: return this->industry->was_cargo_delivered;
case 0xB0: return ClampTo<uint16_t>(this->industry->construction_date - DAYS_TILL_ORIGINAL_BASE_YEAR); // Date when built since 1920 (in days) case 0xB0: return ClampTo<uint16_t>(this->industry->construction_date - CalTime::DAYS_TILL_ORIGINAL_BASE_YEAR); // Date when built since 1920 (in days)
case 0xB3: return this->industry->construction_type; // Construction type case 0xB3: return this->industry->construction_type; // Construction type
case 0xB4: { case 0xB4: {
Date *latest = std::max_element(this->industry->last_cargo_accepted_at, endof(this->industry->last_cargo_accepted_at)); EconTime::Date *latest = std::max_element(this->industry->last_cargo_accepted_at, endof(this->industry->last_cargo_accepted_at));
return ClampTo<uint16_t>((*latest) - DAYS_TILL_ORIGINAL_BASE_YEAR); // Date last cargo accepted since 1920 (in days) return ClampTo<uint16_t>((*latest) - EconTime::DAYS_TILL_ORIGINAL_BASE_YEAR); // Date last cargo accepted since 1920 (in days)
} }
} }

@ -84,7 +84,7 @@ bool ObjectSpec::IsEverAvailable() const
*/ */
bool ObjectSpec::WasEverAvailable() const bool ObjectSpec::WasEverAvailable() const
{ {
return this->IsEverAvailable() && (_date > this->introduction_date || (_settings_game.construction.ignore_object_intro_dates && !_generating_world)); return this->IsEverAvailable() && ((CalTime::CurDate() > this->introduction_date) || (_settings_game.construction.ignore_object_intro_dates && !_generating_world));
} }
/** /**
@ -94,8 +94,8 @@ bool ObjectSpec::WasEverAvailable() const
bool ObjectSpec::IsAvailable() const bool ObjectSpec::IsAvailable() const
{ {
return this->WasEverAvailable() && return this->WasEverAvailable() &&
(_date < this->end_of_life_date || this->end_of_life_date < this->introduction_date + 365 || ((CalTime::CurDate() < this->end_of_life_date) || (this->end_of_life_date < this->introduction_date + 365) ||
(_settings_game.construction.no_expire_objects_after != 0 && _cur_year >= _settings_game.construction.no_expire_objects_after)); (_settings_game.construction.no_expire_objects_after != 0 && CalTime::CurYear() >= _settings_game.construction.no_expire_objects_after));
} }
/** /**
@ -281,7 +281,7 @@ static uint32_t GetCountAndDistanceOfClosestInstance(uint32_t local_id, uint32_t
break; break;
/* Construction date */ /* Construction date */
case 0x42: return _date.base(); case 0x42: return CalTime::CurDate().base();
/* Object founder information */ /* Object founder information */
case 0x44: return _current_company; case 0x44: return _current_company;

@ -100,8 +100,8 @@ struct ObjectSpec {
uint8_t size; ///< The size of this objects; low nibble for X, high nibble for Y. uint8_t size; ///< The size of this objects; low nibble for X, high nibble for Y.
uint8_t build_cost_multiplier; ///< Build cost multiplier per tile. uint8_t build_cost_multiplier; ///< Build cost multiplier per tile.
uint8_t clear_cost_multiplier; ///< Clear cost multiplier per tile. uint8_t clear_cost_multiplier; ///< Clear cost multiplier per tile.
Date introduction_date; ///< From when can this object be built. CalTime::Date introduction_date;///< From when can this object be built.
Date end_of_life_date; ///< When can't this object be built anymore. CalTime::Date end_of_life_date; ///< When can't this object be built anymore.
ObjectFlags flags; ///< Flags/settings related to the object. ObjectFlags flags; ///< Flags/settings related to the object.
ObjectCtrlFlags ctrl_flags; ///< Extra control flags. ObjectCtrlFlags ctrl_flags; ///< Extra control flags.
uint8_t edge_foundation[4]; ///< Edge foundation flags uint8_t edge_foundation[4]; ///< Edge foundation flags

@ -34,7 +34,7 @@
case 0x40: return 0; case 0x40: return 0;
case 0x41: return 0; case 0x41: return 0;
case 0x42: return 0; case 0x42: return 0;
case 0x43: return _date.base(); case 0x43: return CalTime::CurDate().base();
case 0x44: return HZB_TOWN_EDGE; case 0x44: return HZB_TOWN_EDGE;
case A2VRI_RAILTYPE_SIGNAL_RESTRICTION_INFO: return 0; case A2VRI_RAILTYPE_SIGNAL_RESTRICTION_INFO: return 0;
case A2VRI_RAILTYPE_SIGNAL_CONTEXT: return this->signal_context; case A2VRI_RAILTYPE_SIGNAL_CONTEXT: return this->signal_context;
@ -50,7 +50,7 @@
case 0x42: return IsLevelCrossingTile(this->tile) && IsCrossingBarred(this->tile); case 0x42: return IsLevelCrossingTile(this->tile) && IsCrossingBarred(this->tile);
case 0x43: case 0x43:
if (IsRailDepotTile(this->tile)) return Depot::GetByTile(this->tile)->build_date.base(); if (IsRailDepotTile(this->tile)) return Depot::GetByTile(this->tile)->build_date.base();
return _date.base(); return CalTime::CurDate().base();
case 0x44: { case 0x44: {
const Town *t = nullptr; const Town *t = nullptr;
if (IsRailDepotTile(this->tile)) { if (IsRailDepotTile(this->tile)) {

@ -255,7 +255,7 @@ uint32_t RoadStopScopeResolver::GetVariable(uint16_t variable, uint32_t paramete
case 0xF0: return this->st == nullptr ? 0 : this->st->facilities; // facilities case 0xF0: return this->st == nullptr ? 0 : this->st->facilities; // facilities
case 0xFA: return ClampTo<uint16_t>((this->st == nullptr ? _date : this->st->build_date) - DAYS_TILL_ORIGINAL_BASE_YEAR); // build date case 0xFA: return ClampTo<uint16_t>((this->st == nullptr ? CalTime::CurDate() : this->st->build_date) - CalTime::DAYS_TILL_ORIGINAL_BASE_YEAR); // build date
} }
if (this->st != nullptr) return this->st->GetNewGRFVariable(this->ro, variable, parameter, &(extra->available)); if (this->st != nullptr) return this->st->GetNewGRFVariable(this->ro, variable, parameter, &(extra->available));

@ -30,7 +30,7 @@
case 0x40: return 0; case 0x40: return 0;
case 0x41: return 0; case 0x41: return 0;
case 0x42: return 0; case 0x42: return 0;
case 0x43: return _date.base(); case 0x43: return CalTime::CurDate().base();
case 0x44: return HZB_TOWN_EDGE; case 0x44: return HZB_TOWN_EDGE;
} }
} }
@ -41,7 +41,7 @@
case 0x42: return IsLevelCrossingTile(this->tile) && IsCrossingBarred(this->tile); case 0x42: return IsLevelCrossingTile(this->tile) && IsCrossingBarred(this->tile);
case 0x43: case 0x43:
if (IsRoadDepotTile(this->tile)) return Depot::GetByTile(this->tile)->build_date.base(); if (IsRoadDepotTile(this->tile)) return Depot::GetByTile(this->tile)->build_date.base();
return _date.base(); return CalTime::CurDate().base();
case 0x44: { case 0x44: {
const Town *t = nullptr; const Town *t = nullptr;
if (IsRoadDepotTile(this->tile)) { if (IsRoadDepotTile(this->tile)) {

@ -323,7 +323,7 @@ uint32_t StationScopeResolver::GetNearbyStationInfo(uint32_t parameter, StationS
} }
break; break;
case 0xFA: return ClampTo<uint16_t>(_date - DAYS_TILL_ORIGINAL_BASE_YEAR); // Build date, clamped to a 16 bit value case 0xFA: return ClampTo<uint16_t>(CalTime::CurDate() - CalTime::DAYS_TILL_ORIGINAL_BASE_YEAR); // Build date, clamped to a 16 bit value
} }
extra->available = false; extra->available = false;
@ -424,7 +424,7 @@ uint32_t StationScopeResolver::GetNearbyStationInfo(uint32_t parameter, StationS
case 0x84: return this->st->string_id; case 0x84: return this->st->string_id;
case 0x86: return 0; case 0x86: return 0;
case 0xF0: return this->st->facilities; case 0xF0: return this->st->facilities;
case 0xFA: return ClampTo<uint16_t>(this->st->build_date - DAYS_TILL_ORIGINAL_BASE_YEAR); case 0xFA: return ClampTo<uint16_t>(this->st->build_date - CalTime::DAYS_TILL_ORIGINAL_BASE_YEAR);
} }
return this->st->GetNewGRFVariable(this->ro, variable, parameter, &(extra->available)); return this->st->GetNewGRFVariable(this->ro, variable, parameter, &(extra->available));

@ -1005,7 +1005,7 @@ uint RemapNewGRFStringControlCode(uint scc, std::string *buffer, const char **st
/* Dates from NewGRFs have 1920-01-01 as their zero point, convert it to OpenTTD's epoch. */ /* Dates from NewGRFs have 1920-01-01 as their zero point, convert it to OpenTTD's epoch. */
case SCC_NEWGRF_PRINT_WORD_DATE_LONG: case SCC_NEWGRF_PRINT_WORD_DATE_LONG:
case SCC_NEWGRF_PRINT_WORD_DATE_SHORT: parameters.SetParam(0, _newgrf_textrefstack.PopUnsignedWord() + DAYS_TILL_ORIGINAL_BASE_YEAR); break; case SCC_NEWGRF_PRINT_WORD_DATE_SHORT: parameters.SetParam(0, _newgrf_textrefstack.PopUnsignedWord() + CalTime::DAYS_TILL_ORIGINAL_BASE_YEAR); break;
case SCC_NEWGRF_DISCARD_WORD: _newgrf_textrefstack.PopUnsignedWord(); break; case SCC_NEWGRF_DISCARD_WORD: _newgrf_textrefstack.PopUnsignedWord(); break;

@ -692,7 +692,7 @@ static void MoveToNextTickerItem()
const NewsType type = ni->type; const NewsType type = ni->type;
/* check the date, don't show too old items */ /* check the date, don't show too old items */
if (_date - _news_type_data[type].age > ni->date) continue; if (_scaled_tick_counter - ni->creation_tick > _news_type_data[type].age * DAY_TICKS) continue;
switch (_news_type_data[type].GetDisplay()) { switch (_news_type_data[type].GetDisplay()) {
default: NOT_REACHED(); default: NOT_REACHED();
@ -729,7 +729,7 @@ static void MoveToNextNewsItem()
const NewsType type = ni->type; const NewsType type = ni->type;
/* check the date, don't show too old items */ /* check the date, don't show too old items */
if (_date - _news_type_data[type].age > ni->date) continue; if (_scaled_tick_counter - ni->creation_tick > _news_type_data[type].age * DAY_TICKS) continue;
switch (_news_type_data[type].GetDisplay()) { switch (_news_type_data[type].GetDisplay()) {
default: NOT_REACHED(); default: NOT_REACHED();
@ -806,10 +806,10 @@ static void DeleteNewsItem(NewsItem *ni)
* @see NewsSubtype * @see NewsSubtype
*/ */
NewsItem::NewsItem(StringID string_id, NewsType type, NewsFlag flags, NewsReferenceType reftype1, uint32_t ref1, NewsReferenceType reftype2, uint32_t ref2, const NewsAllocatedData *data) : NewsItem::NewsItem(StringID string_id, NewsType type, NewsFlag flags, NewsReferenceType reftype1, uint32_t ref1, NewsReferenceType reftype2, uint32_t ref2, const NewsAllocatedData *data) :
string_id(string_id), date(_date), type(type), flags(flags), reftype1(reftype1), reftype2(reftype2), ref1(ref1), ref2(ref2), data(data) string_id(string_id), date(CalTime::CurDate()), creation_tick(_scaled_tick_counter), type(type), flags(flags), reftype1(reftype1), reftype2(reftype2), ref1(ref1), ref2(ref2), data(data)
{ {
/* show this news message in colour? */ /* show this news message in colour? */
if (_cur_year >= _settings_client.gui.coloured_news_year) this->flags |= NF_INCOLOUR; if (CalTime::CurYear() >= _settings_client.gui.coloured_news_year) this->flags |= NF_INCOLOUR;
CopyOutDParam(this->params, 10); CopyOutDParam(this->params, 10);
} }
@ -995,7 +995,7 @@ static void RemoveOldNewsItems()
NewsItem *next; NewsItem *next;
for (NewsItem *cur = _oldest_news; _total_news > MIN_NEWS_AMOUNT && cur != nullptr; cur = next) { for (NewsItem *cur = _oldest_news; _total_news > MIN_NEWS_AMOUNT && cur != nullptr; cur = next) {
next = cur->next; next = cur->next;
if (_date - _news_type_data[cur->type].age * _settings_client.gui.news_message_timeout > cur->date) DeleteNewsItem(cur); if (_scaled_tick_counter - cur->creation_tick > (uint)(_news_type_data[cur->type].age * _settings_client.gui.news_message_timeout * DAY_TICKS)) DeleteNewsItem(cur);
} }
} }
@ -1021,9 +1021,9 @@ void NewsLoop()
static byte _last_clean_month = 0; static byte _last_clean_month = 0;
if (_last_clean_month != _cur_date_ymd.month) { if (_last_clean_month != EconTime::CurMonth()) {
RemoveOldNewsItems(); RemoveOldNewsItems();
_last_clean_month = _cur_date_ymd.month; _last_clean_month = EconTime::CurMonth();
} }
if (ReadyForNextTickerItem()) MoveToNextTickerItem(); if (ReadyForNextTickerItem()) MoveToNextTickerItem();
@ -1143,7 +1143,7 @@ struct MessageHistoryWindow : Window {
/* Months are off-by-one, so it's actually 8. Not using /* Months are off-by-one, so it's actually 8. Not using
* month 12 because the 1 is usually less wide. */ * month 12 because the 1 is usually less wide. */
SetDParam(0, ConvertYMDToDate(ORIGINAL_MAX_YEAR, 7, 30)); SetDParam(0, CalTime::ConvertYMDToDate(CalTime::ORIGINAL_MAX_YEAR, 7, 30));
this->date_width = GetStringBoundingBox(STR_JUST_DATE_TINY).width + WidgetDimensions::scaled.hsep_wide; this->date_width = GetStringBoundingBox(STR_JUST_DATE_TINY).width + WidgetDimensions::scaled.hsep_wide;
size->height = 4 * resize->height + WidgetDimensions::scaled.framerect.Vertical(); // At least 4 lines are visible. size->height = 4 * resize->height + WidgetDimensions::scaled.framerect.Vertical(); // At least 4 lines are visible.

@ -129,7 +129,8 @@ struct NewsItem {
NewsItem *prev; ///< Previous news item NewsItem *prev; ///< Previous news item
NewsItem *next; ///< Next news item NewsItem *next; ///< Next news item
StringID string_id; ///< Message text StringID string_id; ///< Message text
Date date; ///< Date of the news CalTime::Date date; ///< Date of the news
uint64_t creation_tick; ///< Tick when news was created
NewsType type; ///< Type of the news NewsType type; ///< Type of the news
NewsFlag flags; ///< NewsFlags bits @see NewsFlag NewsFlag flags; ///< NewsFlags bits @see NewsFlag

@ -25,7 +25,7 @@ struct Object : ObjectPool::PoolItem<&_object_pool> {
ObjectType type; ///< Type of the object ObjectType type; ///< Type of the object
Town *town; ///< Town the object is built in Town *town; ///< Town the object is built in
TileArea location; ///< Location of the object TileArea location; ///< Location of the object
Date build_date; ///< Date of construction CalTime::Date build_date; ///< Date of construction
byte colour; ///< Colour of the object, for display purpose byte colour; ///< Colour of the object, for display purpose
byte view; ///< The view setting for this object byte view; ///< The view setting for this object

@ -143,7 +143,7 @@ void BuildObject(ObjectType type, TileIndex tile, CompanyID owner, Town *town, u
o->type = type; o->type = type;
o->location = ta; o->location = ta;
o->town = town == nullptr ? CalcClosestTownFromTile(tile) : town; o->town = town == nullptr ? CalcClosestTownFromTile(tile) : town;
o->build_date = _date; o->build_date = CalTime::CurDate();
o->view = view; o->view = view;
/* If nothing owns the object, the colour will be random. Otherwise /* If nothing owns the object, the colour will be random. Otherwise

@ -624,7 +624,7 @@ void OpenBrowser(const std::string &url)
/** Callback structure of statements to be executed after the NewGRF scan. */ /** Callback structure of statements to be executed after the NewGRF scan. */
struct AfterNewGRFScan : NewGRFScanCallback { struct AfterNewGRFScan : NewGRFScanCallback {
Year startyear = INVALID_YEAR; ///< The start year. CalTime::Year startyear = CalTime::INVALID_YEAR; ///< The start year.
uint32_t generation_seed = GENERATE_NEW_SEED; ///< Seed for the new game. uint32_t generation_seed = GENERATE_NEW_SEED; ///< Seed for the new game.
std::string dedicated_host; ///< Hostname for the dedicated server. std::string dedicated_host; ///< Hostname for the dedicated server.
uint16_t dedicated_port = 0; ///< Port for the dedicated server. uint16_t dedicated_port = 0; ///< Port for the dedicated server.
@ -673,7 +673,7 @@ struct AfterNewGRFScan : NewGRFScanCallback {
MusicDriver::GetInstance()->SetVolume(_settings_client.music.music_vol); MusicDriver::GetInstance()->SetVolume(_settings_client.music.music_vol);
SetEffectVolume(_settings_client.music.effect_vol); SetEffectVolume(_settings_client.music.effect_vol);
if (startyear != INVALID_YEAR) IConsoleSetSetting("game_creation.starting_year", startyear); if (startyear != CalTime::INVALID_YEAR) IConsoleSetSetting("game_creation.starting_year", startyear.base());
if (generation_seed != GENERATE_NEW_SEED) _settings_newgame.game_creation.generation_seed = generation_seed; if (generation_seed != GENERATE_NEW_SEED) _settings_newgame.game_creation.generation_seed = generation_seed;
if (!dedicated_host.empty()) { if (!dedicated_host.empty()) {
@ -1127,7 +1127,7 @@ static void OnStartScenario()
/* Make sure all industries were built "this year", to avoid too early closures. (#9918) */ /* Make sure all industries were built "this year", to avoid too early closures. (#9918) */
for (Industry *i : Industry::Iterate()) { for (Industry *i : Industry::Iterate()) {
i->last_prod_year = _cur_year; i->last_prod_year = EconTime::CurYear();
} }
} }
@ -1442,7 +1442,7 @@ void SwitchToMode(SwitchMode new_mode)
if (SafeLoad(_file_to_saveload.name, _file_to_saveload.file_op, _file_to_saveload.detail_ftype, GM_EDITOR, NO_DIRECTORY)) { if (SafeLoad(_file_to_saveload.name, _file_to_saveload.file_op, _file_to_saveload.detail_ftype, GM_EDITOR, NO_DIRECTORY)) {
SetLocalCompany(OWNER_NONE); SetLocalCompany(OWNER_NONE);
GenerateSavegameId(); GenerateSavegameId();
_settings_newgame.game_creation.starting_year = _cur_year; _settings_newgame.game_creation.starting_year = CalTime::CurYear();
/* Cancel the saveload pausing */ /* Cancel the saveload pausing */
DoCommandP(0, PM_PAUSED_SAVELOAD, 0, CMD_PAUSE); DoCommandP(0, PM_PAUSED_SAVELOAD, 0, CMD_PAUSE);
} else { } else {
@ -2126,7 +2126,7 @@ void StateGameLoop()
* to avoid problems with timetables and train speed adaptation * to avoid problems with timetables and train speed adaptation
*/ */
_state_ticks++; _state_ticks++;
_state_ticks_offset++; DateDetail::_state_ticks_offset++;
RunTileLoop(); RunTileLoop();
CallVehicleTicks(); CallVehicleTicks();
@ -2138,10 +2138,10 @@ void StateGameLoop()
CallWindowGameTickEvent(); CallWindowGameTickEvent();
NewsLoop(); NewsLoop();
} else { } else {
if (_debug_desync_level > 2 && _tick_skip_counter == 0 && _date_fract == 0 && (_date.base() & 0x1F) == 0) { if (_debug_desync_level > 2 && DateDetail::_tick_skip_counter == 0 && EconTime::CurDateFract() == 0 && (EconTime::CurDate().base() & 0x1F) == 0) {
/* Save the desync savegame if needed. */ /* Save the desync savegame if needed. */
char name[MAX_PATH]; char name[MAX_PATH];
seprintf(name, lastof(name), "dmp_cmds_%08x_%08x.sav", _settings_game.game_creation.generation_seed, _date.base()); seprintf(name, lastof(name), "dmp_cmds_%08x_%08x.sav", _settings_game.game_creation.generation_seed, EconTime::CurDate().base());
SaveOrLoad(name, SLO_SAVE, DFT_GAME_FILE, AUTOSAVE_DIR, false); SaveOrLoad(name, SLO_SAVE, DFT_GAME_FILE, AUTOSAVE_DIR, false);
} }
@ -2152,7 +2152,7 @@ void StateGameLoop()
Backup<CompanyID> cur_company(_current_company, OWNER_NONE, FILE_LINE); Backup<CompanyID> cur_company(_current_company, OWNER_NONE, FILE_LINE);
BasePersistentStorageArray::SwitchMode(PSM_ENTER_GAMELOOP); BasePersistentStorageArray::SwitchMode(PSM_ENTER_GAMELOOP);
_tick_skip_counter++; DateDetail::_tick_skip_counter++;
_scaled_tick_counter++; _scaled_tick_counter++;
if (_game_mode != GM_BOOTSTRAP) { if (_game_mode != GM_BOOTSTRAP) {
_state_ticks++; // This must update in lock-step with _tick_skip_counter, such that _state_ticks_offset doesn't need to be changed. _state_ticks++; // This must update in lock-step with _tick_skip_counter, such that _state_ticks_offset doesn't need to be changed.
@ -2166,13 +2166,13 @@ void StateGameLoop()
} }
RunAuxiliaryTileLoop(); RunAuxiliaryTileLoop();
if (_tick_skip_counter < DayLengthFactor()) { if (DateDetail::_tick_skip_counter < DayLengthFactor()) {
AnimateAnimatedTiles(); AnimateAnimatedTiles();
RunTileLoop(true); RunTileLoop(true);
CallVehicleTicks(); CallVehicleTicks();
OnTick_Companies(false); OnTick_Companies(false);
} else { } else {
_tick_skip_counter = 0; DateDetail::_tick_skip_counter = 0;
IncreaseDate(); IncreaseDate();
AnimateAnimatedTiles(); AnimateAnimatedTiles();
RunTileLoop(true); RunTileLoop(true);

@ -1028,6 +1028,6 @@ public:
inline const DispatchSchedule &GetDispatchScheduleByIndex(uint index) const { return this->dispatch_schedules[index]; } inline const DispatchSchedule &GetDispatchScheduleByIndex(uint index) const { return this->dispatch_schedules[index]; }
}; };
void ShiftOrderDates(DateDelta interval); void UpdateOrderUIOnDateChange();
#endif /* ORDER_BASE_H */ #endif /* ORDER_BASE_H */

@ -3147,7 +3147,7 @@ VehicleOrderID ProcessConditionalOrder(const Order *order, const Vehicle *v, Pro
case OCV_RELIABILITY: skip_order = OrderConditionCompare(occ, ToPercent16(v->reliability), value); break; case OCV_RELIABILITY: skip_order = OrderConditionCompare(occ, ToPercent16(v->reliability), value); break;
case OCV_MAX_RELIABILITY: skip_order = OrderConditionCompare(occ, ToPercent16(v->GetEngine()->reliability), value); break; case OCV_MAX_RELIABILITY: skip_order = OrderConditionCompare(occ, ToPercent16(v->GetEngine()->reliability), value); break;
case OCV_MAX_SPEED: skip_order = OrderConditionCompare(occ, v->GetDisplayMaxSpeed() * 10 / 16, value); break; case OCV_MAX_SPEED: skip_order = OrderConditionCompare(occ, v->GetDisplayMaxSpeed() * 10 / 16, value); break;
case OCV_AGE: skip_order = OrderConditionCompare(occ, DateDeltaToYears(v->age), value); break; case OCV_AGE: skip_order = OrderConditionCompare(occ, DateDeltaToYearDelta(v->age).base(), value); break;
case OCV_REQUIRES_SERVICE: skip_order = OrderConditionCompare(occ, v->NeedsServicing(), value); break; case OCV_REQUIRES_SERVICE: skip_order = OrderConditionCompare(occ, v->NeedsServicing(), value); break;
case OCV_UNCONDITIONALLY: skip_order = true; break; case OCV_UNCONDITIONALLY: skip_order = true; break;
case OCV_CARGO_WAITING: { case OCV_CARGO_WAITING: {
@ -3221,7 +3221,7 @@ VehicleOrderID ProcessConditionalOrder(const Order *order, const Vehicle *v, Pro
skip_order = ord->UpdateJumpCounter((byte)value, mode == PCO_DRY_RUN); skip_order = ord->UpdateJumpCounter((byte)value, mode == PCO_DRY_RUN);
break; break;
} }
case OCV_REMAINING_LIFETIME: skip_order = OrderConditionCompare(occ, std::max(DateDeltaToYears(v->max_age - v->age + DAYS_IN_LEAP_YEAR - 1), 0), value); break; case OCV_REMAINING_LIFETIME: skip_order = OrderConditionCompare(occ, std::max(DateDeltaToYearDelta(v->max_age - v->age + DAYS_IN_LEAP_YEAR - 1).base(), 0), value); break;
case OCV_COUNTER_VALUE: { case OCV_COUNTER_VALUE: {
const TraceRestrictCounter* ctr = TraceRestrictCounter::GetIfValid(GB(order->GetXData(), 16, 16)); const TraceRestrictCounter* ctr = TraceRestrictCounter::GetIfValid(GB(order->GetXData(), 16, 16));
if (ctr != nullptr) { if (ctr != nullptr) {
@ -3759,7 +3759,7 @@ CommandCost CmdMassChangeOrder(TileIndex tile, DoCommandFlag flags, uint32_t p1,
return CommandCost(); return CommandCost();
} }
void ShiftOrderDates(DateDelta interval) void UpdateOrderUIOnDateChange()
{ {
SetWindowClassesDirty(WC_VEHICLE_ORDERS); SetWindowClassesDirty(WC_VEHICLE_ORDERS);
SetWindowClassesDirty(WC_VEHICLE_TIMETABLE); SetWindowClassesDirty(WC_VEHICLE_TIMETABLE);

@ -145,7 +145,7 @@ struct PlanLine {
struct Plan : PlanPool::PoolItem<&_plan_pool> { struct Plan : PlanPool::PoolItem<&_plan_pool> {
Owner owner; Owner owner;
Colours colour; Colours colour;
Date creation_date; CalTime::Date creation_date;
PlanLineVector lines; PlanLineVector lines;
PlanLine *temp_line; PlanLine *temp_line;
std::string name; std::string name;
@ -157,7 +157,7 @@ struct Plan : PlanPool::PoolItem<&_plan_pool> {
Plan(Owner owner = INVALID_OWNER) Plan(Owner owner = INVALID_OWNER)
{ {
this->owner = owner; this->owner = owner;
this->creation_date = _date; this->creation_date = CalTime::CurDate();
this->visible = false; this->visible = false;
this->visible_by_all = false; this->visible_by_all = false;
this->show_lines = false; this->show_lines = false;

@ -311,12 +311,12 @@ bool ValParamRailType(const RailType rail)
* @return The rail types that should be available when date * @return The rail types that should be available when date
* introduced rail types are taken into account as well. * introduced rail types are taken into account as well.
*/ */
RailTypes AddDateIntroducedRailTypes(RailTypes current, Date date) RailTypes AddDateIntroducedRailTypes(RailTypes current, CalTime::Date date)
{ {
RailTypes rts = current; RailTypes rts = current;
if (_settings_game.vehicle.no_introduce_vehicles_after > 0) { if (_settings_game.vehicle.no_introduce_vehicles_after > 0) {
date = std::min<Date>(date, ConvertYMDToDate(_settings_game.vehicle.no_introduce_vehicles_after, 0, 1) - 1); date = std::min<CalTime::Date>(date, CalTime::ConvertYMDToDate(_settings_game.vehicle.no_introduce_vehicles_after, 0, 1) - 1);
} }
for (RailType rt = RAILTYPE_BEGIN; rt != RAILTYPE_END; rt++) { for (RailType rt = RAILTYPE_BEGIN; rt != RAILTYPE_END; rt++) {
@ -325,7 +325,7 @@ RailTypes AddDateIntroducedRailTypes(RailTypes current, Date date)
if (rti->label == 0) continue; if (rti->label == 0) continue;
/* Not date introduced. */ /* Not date introduced. */
if (!IsInsideMM(rti->introduction_date, 0, MAX_DATE.base())) continue; if (!IsInsideMM(rti->introduction_date, 0, CalTime::MAX_DATE.base())) continue;
/* Not yet introduced at this date. */ /* Not yet introduced at this date. */
if (rti->introduction_date > date) continue; if (rti->introduction_date > date) continue;
@ -352,9 +352,9 @@ RailTypes GetCompanyRailTypes(CompanyID company, bool introduces)
{ {
RailTypes rts = RAILTYPES_NONE; RailTypes rts = RAILTYPES_NONE;
Date date = _date; CalTime::Date date = CalTime::CurDate();
if (_settings_game.vehicle.no_introduce_vehicles_after > 0) { if (_settings_game.vehicle.no_introduce_vehicles_after > 0) {
date = std::min<Date>(date, ConvertYMDToDate(_settings_game.vehicle.no_introduce_vehicles_after, 0, 1) - 1); date = std::min<CalTime::Date>(date, CalTime::ConvertYMDToDate(_settings_game.vehicle.no_introduce_vehicles_after, 0, 1) - 1);
} }
for (const Engine *e : Engine::IterateType(VEH_TRAIN)) { for (const Engine *e : Engine::IterateType(VEH_TRAIN)) {
@ -375,7 +375,7 @@ RailTypes GetCompanyRailTypes(CompanyID company, bool introduces)
} }
} }
if (introduces) return AddDateIntroducedRailTypes(rts, _date); if (introduces) return AddDateIntroducedRailTypes(rts, CalTime::CurDate());
return rts; return rts;
} }
@ -403,7 +403,7 @@ RailTypes GetRailTypes(bool introduces)
} }
} }
if (introduces) return AddDateIntroducedRailTypes(rts, MAX_DATE); if (introduces) return AddDateIntroducedRailTypes(rts, CalTime::MAX_DATE);
return rts; return rts;
} }

@ -276,7 +276,7 @@ public:
* The introduction at this date is furthermore limited by the * The introduction at this date is furthermore limited by the
* #introduction_required_railtypes. * #introduction_required_railtypes.
*/ */
Date introduction_date; CalTime::Date introduction_date;
/** /**
* Bitmask of railtypes that are required for this railtype to be introduced * Bitmask of railtypes that are required for this railtype to be introduced
@ -496,7 +496,7 @@ bool HasRailTypeAvail(const CompanyID company, const RailType railtype);
bool HasAnyRailTypesAvail(const CompanyID company); bool HasAnyRailTypesAvail(const CompanyID company);
bool ValParamRailType(const RailType rail); bool ValParamRailType(const RailType rail);
RailTypes AddDateIntroducedRailTypes(RailTypes current, Date date); RailTypes AddDateIntroducedRailTypes(RailTypes current, CalTime::Date date);
RailTypes GetCompanyRailTypes(CompanyID company, bool introduces = true); RailTypes GetCompanyRailTypes(CompanyID company, bool introduces = true);
RailTypes GetRailTypes(bool introduces); RailTypes GetRailTypes(bool introduces);

@ -1421,7 +1421,7 @@ CommandCost CmdBuildTrainDepot(TileIndex tile, DoCommandFlag flags, uint32_t p1,
if (flags & DC_EXEC) { if (flags & DC_EXEC) {
Depot *d = new Depot(tile); Depot *d = new Depot(tile);
d->build_date = _date; d->build_date = CalTime::CurDate();
MakeRailDepot(tile, _current_company, d->index, dir, railtype); MakeRailDepot(tile, _current_company, d->index, dir, railtype);
MarkTileDirtyByTile(tile); MarkTileDirtyByTile(tile);

@ -302,7 +302,7 @@ static void GenericPlaceSignals(TileIndex tile)
if (_cur_signal_type == SIGTYPE_NO_ENTRY) SB(p1, 15, 2, 1); // reverse default signal direction if (_cur_signal_type == SIGTYPE_NO_ENTRY) SB(p1, 15, 2, 1); // reverse default signal direction
} else { } else {
SB(p1, 3, 1, _ctrl_pressed); SB(p1, 3, 1, _ctrl_pressed);
SB(p1, 4, 1, (_cur_year < _settings_client.gui.semaphore_build_before ? SIG_SEMAPHORE : SIG_ELECTRIC)); SB(p1, 4, 1, (CalTime::CurYear() < _settings_client.gui.semaphore_build_before ? SIG_SEMAPHORE : SIG_ELECTRIC));
SB(p1, 5, 3, GetDefaultSignalType()); SB(p1, 5, 3, GetDefaultSignalType());
SB(p1, 8, 1, 0); SB(p1, 8, 1, 0);
SB(p1, 9, 6, cycle_types); SB(p1, 9, 6, cycle_types);
@ -484,7 +484,7 @@ static void HandleAutoSignalPlacement()
SB(p2, 11, 4, _cur_signal_style); SB(p2, 11, 4, _cur_signal_style);
} else { } else {
SB(p2, 3, 1, 0); SB(p2, 3, 1, 0);
SB(p2, 4, 1, (_cur_year < _settings_client.gui.semaphore_build_before ? SIG_SEMAPHORE : SIG_ELECTRIC)); SB(p2, 4, 1, (CalTime::CurYear() < _settings_client.gui.semaphore_build_before ? SIG_SEMAPHORE : SIG_ELECTRIC));
SB(p2, 6, 1, _ctrl_pressed); SB(p2, 6, 1, _ctrl_pressed);
SB(p2, 7, 3, GetDefaultSignalType()); SB(p2, 7, 3, GetDefaultSignalType());
SB(p2, 24, 8, _settings_client.gui.drag_signals_density); SB(p2, 24, 8, _settings_client.gui.drag_signals_density);
@ -2788,7 +2788,7 @@ static void SetDefaultRailGui()
*/ */
void ResetSignalVariant(int32_t new_value) void ResetSignalVariant(int32_t new_value)
{ {
SignalVariant new_variant = (_cur_year < _settings_client.gui.semaphore_build_before ? SIG_SEMAPHORE : SIG_ELECTRIC); SignalVariant new_variant = (CalTime::CurYear() < _settings_client.gui.semaphore_build_before ? SIG_SEMAPHORE : SIG_ELECTRIC);
if (new_variant != _cur_signal_variant) { if (new_variant != _cur_signal_variant) {
Window *w = FindWindowById(WC_BUILD_SIGNAL, 0); Window *w = FindWindowById(WC_BUILD_SIGNAL, 0);

@ -147,7 +147,7 @@ bool HasRoadTypeAvail(const CompanyID company, RoadType roadtype)
if (rti->label == 0) return false; if (rti->label == 0) return false;
/* Not yet introduced at this date. */ /* Not yet introduced at this date. */
if (IsInsideMM(rti->introduction_date, 0, MAX_DATE.base()) && rti->introduction_date > _date) return false; if (IsInsideMM(rti->introduction_date, 0, CalTime::MAX_DATE.base()) && rti->introduction_date > CalTime::CurDate()) return false;
/* /*
* Do not allow building hidden road types, except when a town may build it. * Do not allow building hidden road types, except when a town may build it.
@ -199,7 +199,7 @@ bool ValParamRoadType(RoadType roadtype)
* @return The road types that should be available when date * @return The road types that should be available when date
* introduced road types are taken into account as well. * introduced road types are taken into account as well.
*/ */
RoadTypes AddDateIntroducedRoadTypes(RoadTypes current, Date date) RoadTypes AddDateIntroducedRoadTypes(RoadTypes current, CalTime::Date date)
{ {
RoadTypes rts = current; RoadTypes rts = current;
@ -209,7 +209,7 @@ RoadTypes AddDateIntroducedRoadTypes(RoadTypes current, Date date)
if (rti->label == 0) continue; if (rti->label == 0) continue;
/* Not date introduced. */ /* Not date introduced. */
if (!IsInsideMM(rti->introduction_date, 0, MAX_DATE.base())) continue; if (!IsInsideMM(rti->introduction_date, 0, CalTime::MAX_DATE.base())) continue;
/* Not yet introduced at this date. */ /* Not yet introduced at this date. */
if (rti->introduction_date > date) continue; if (rti->introduction_date > date) continue;
@ -240,7 +240,7 @@ RoadTypes GetCompanyRoadTypes(CompanyID company, bool introduces)
const EngineInfo *ei = &e->info; const EngineInfo *ei = &e->info;
if (HasBit(ei->climates, _settings_game.game_creation.landscape) && if (HasBit(ei->climates, _settings_game.game_creation.landscape) &&
(HasBit(e->company_avail, company) || _date >= e->intro_date + DAYS_IN_YEAR)) { (HasBit(e->company_avail, company) || CalTime::CurDate() >= e->intro_date + DAYS_IN_YEAR)) {
const RoadVehicleInfo *rvi = &e->u.road; const RoadVehicleInfo *rvi = &e->u.road;
assert(rvi->roadtype < ROADTYPE_END); assert(rvi->roadtype < ROADTYPE_END);
if (introduces) { if (introduces) {
@ -251,7 +251,7 @@ RoadTypes GetCompanyRoadTypes(CompanyID company, bool introduces)
} }
} }
if (introduces) return AddDateIntroducedRoadTypes(rts, _date); if (introduces) return AddDateIntroducedRoadTypes(rts, CalTime::CurDate());
return rts; return rts;
} }
@ -277,7 +277,7 @@ RoadTypes GetRoadTypes(bool introduces)
} }
} }
if (introduces) return AddDateIntroducedRoadTypes(rts, MAX_DATE); if (introduces) return AddDateIntroducedRoadTypes(rts, CalTime::MAX_DATE);
return rts; return rts;
} }

@ -201,7 +201,7 @@ public:
* The introduction at this date is furthermore limited by the * The introduction at this date is furthermore limited by the
* #introduction_required_types. * #introduction_required_types.
*/ */
Date introduction_date; CalTime::Date introduction_date;
/** /**
* Bitmask of roadtypes that are required for this roadtype to be introduced * Bitmask of roadtypes that are required for this roadtype to be introduced

@ -157,7 +157,7 @@ RoadType AllocateRoadType(RoadTypeLabel label, RoadTramType rtt)
rti->flags = ROTFB_NONE; rti->flags = ROTFB_NONE;
rti->extra_flags = RXTFB_NONE; rti->extra_flags = RXTFB_NONE;
rti->collision_mode = RTCM_NORMAL; rti->collision_mode = RTCM_NORMAL;
rti->introduction_date = INVALID_DATE; rti->introduction_date = CalTime::INVALID_DATE;
/* Make us compatible with ourself. */ /* Make us compatible with ourself. */
rti->powered_roadtypes = (RoadTypes)(1ULL << rt); rti->powered_roadtypes = (RoadTypes)(1ULL << rt);
@ -1768,7 +1768,7 @@ CommandCost CmdBuildRoadDepot(TileIndex tile, DoCommandFlag flags, uint32_t p1,
if (flags & DC_EXEC) { if (flags & DC_EXEC) {
Depot *dep = new Depot(tile); Depot *dep = new Depot(tile);
dep->build_date = _date; dep->build_date = CalTime::CurDate();
/* A road depot has two road bits. */ /* A road depot has two road bits. */
UpdateCompanyRoadInfrastructure(rt, _current_company, ROAD_DEPOT_TRACKBIT_FACTOR); UpdateCompanyRoadInfrastructure(rt, _current_company, ROAD_DEPOT_TRACKBIT_FACTOR);

@ -152,7 +152,7 @@ bool HasRoadTypeAvail(CompanyID company, RoadType roadtype);
bool ValParamRoadType(RoadType roadtype); bool ValParamRoadType(RoadType roadtype);
RoadTypes GetCompanyRoadTypes(CompanyID company, bool introduces = true); RoadTypes GetCompanyRoadTypes(CompanyID company, bool introduces = true);
RoadTypes GetRoadTypes(bool introduces); RoadTypes GetRoadTypes(bool introduces);
RoadTypes AddDateIntroducedRoadTypes(RoadTypes current, Date date); RoadTypes AddDateIntroducedRoadTypes(RoadTypes current, CalTime::Date date);
void UpdateLevelCrossing(TileIndex tile, bool sound = true, bool force_close = false); void UpdateLevelCrossing(TileIndex tile, bool sound = true, bool force_close = false);
void MarkDirtyAdjacentLevelCrossingTilesOnAdd(TileIndex tile, Axis road_axis); void MarkDirtyAdjacentLevelCrossingTilesOnAdd(TileIndex tile, Axis road_axis);

@ -2333,7 +2333,7 @@ DropDownList GetRoadTypeDropDownList(RoadTramTypes rtts, bool for_replacement, b
DropDownList GetScenRoadTypeDropDownList(RoadTramTypes rtts) DropDownList GetScenRoadTypeDropDownList(RoadTramTypes rtts)
{ {
RoadTypes avail_roadtypes = GetRoadTypes(false); RoadTypes avail_roadtypes = GetRoadTypes(false);
avail_roadtypes = AddDateIntroducedRoadTypes(avail_roadtypes, _date); avail_roadtypes = AddDateIntroducedRoadTypes(avail_roadtypes, CalTime::CurDate());
RoadTypes used_roadtypes = GetRoadTypes(true); RoadTypes used_roadtypes = GetRoadTypes(true);
/* Filter listed road types */ /* Filter listed road types */

@ -318,9 +318,9 @@ CommandCost CmdBuildRoadVehicle(TileIndex tile, DoCommandFlag flags, const Engin
v->SetServiceInterval(Company::Get(v->owner)->settings.vehicle.servint_roadveh); v->SetServiceInterval(Company::Get(v->owner)->settings.vehicle.servint_roadveh);
v->date_of_last_service = _date; v->date_of_last_service = EconTime::CurDate();
v->date_of_last_service_newgrf = _date; v->date_of_last_service_newgrf = CalTime::CurDate();
v->build_year = _cur_year; v->build_year = CalTime::CurYear();
v->sprite_seq.Set(SPR_IMG_QUERY); v->sprite_seq.Set(SPR_IMG_QUERY);
v->random_bits = Random(); v->random_bits = Random();

@ -279,8 +279,8 @@ static void InitializeWindowsAndCaches()
/* For each company, verify (while loading a scenario) that the inauguration date is the current year and set it /* For each company, verify (while loading a scenario) that the inauguration date is the current year and set it
* accordingly if it is not the case. No need to set it on companies that are not been used already, * accordingly if it is not the case. No need to set it on companies that are not been used already,
* thus the MIN_YEAR (which is really nothing more than Zero, initialized value) test */ * thus the MIN_YEAR (which is really nothing more than Zero, initialized value) test */
if (_file_to_saveload.abstract_ftype == FT_SCENARIO && c->inaugurated_year != MIN_YEAR) { if (_file_to_saveload.abstract_ftype == FT_SCENARIO && c->inaugurated_year != CalTime::MIN_YEAR) {
c->inaugurated_year = _cur_year; c->inaugurated_year = CalTime::CurYear();
} }
} }
@ -842,14 +842,14 @@ bool AfterLoadGame()
} }
/* The value of _date_fract got divided, so make sure that old games are converted correctly. */ /* The value of _date_fract got divided, so make sure that old games are converted correctly. */
if (IsSavegameVersionBefore(SLV_11, 1) || (IsSavegameVersionBefore(SLV_147) && _date_fract > DAY_TICKS)) _date_fract /= 885; if (IsSavegameVersionBefore(SLV_11, 1) || (IsSavegameVersionBefore(SLV_147) && CalTime::CurDateFract() > DAY_TICKS)) CalTime::Detail::now.cal_date_fract /= 885;
if (SlXvIsFeaturePresent(XSLFI_SPRINGPP) || SlXvIsFeaturePresent(XSLFI_JOKERPP) || SlXvIsFeaturePresent(XSLFI_CHILLPP)) { if (SlXvIsFeaturePresent(XSLFI_SPRINGPP) || SlXvIsFeaturePresent(XSLFI_JOKERPP) || SlXvIsFeaturePresent(XSLFI_CHILLPP)) {
assert(DayLengthFactor() >= 1); assert(DayLengthFactor() >= 1);
_tick_skip_counter = _date_fract % DayLengthFactor(); DateDetail::_tick_skip_counter = CalTime::CurDateFract() % DayLengthFactor();
_date_fract /= DayLengthFactor(); CalTime::Detail::now.cal_date_fract /= DayLengthFactor();
assert(_date_fract < DAY_TICKS); assert(CalTime::CurDateFract() < DAY_TICKS);
assert(_tick_skip_counter < DayLengthFactor()); assert(TickSkipCounter() < DayLengthFactor());
} }
/* Set day length factor to 1 if loading a pre day length savegame */ /* Set day length factor to 1 if loading a pre day length savegame */
@ -863,15 +863,23 @@ bool AfterLoadGame()
} }
} }
if (SlXvIsFeatureMissing(XSLFI_VARIABLE_DAY_LENGTH, 3)) { if (SlXvIsFeatureMissing(XSLFI_VARIABLE_DAY_LENGTH, 3)) {
_scaled_tick_counter = (uint64_t)((_tick_counter * DayLengthFactor()) + _tick_skip_counter); _scaled_tick_counter = (uint64_t)((_tick_counter * DayLengthFactor()) + TickSkipCounter());
} }
if (SlXvIsFeaturePresent(XSLFI_VARIABLE_DAY_LENGTH, 1, 3)) { if (SlXvIsFeaturePresent(XSLFI_VARIABLE_DAY_LENGTH, 1, 3)) {
_state_ticks = GetStateTicksFromCurrentDateWithoutOffset() + _state_ticks_offset; _state_ticks = GetStateTicksFromCurrentDateWithoutOffset() + DateDetail::_state_ticks_offset;
} }
/* Update current year /* Update current year
* must be done before loading sprites as some newgrfs check it */ * must be done before loading sprites as some newgrfs check it */
SetDate(_date, _date_fract); CalTime::Detail::SetDate(CalTime::CurDate(), CalTime::CurDateFract());
if (SlXvIsFeaturePresent(XSLFI_VARIABLE_DAY_LENGTH, 5) || !IsSavegameVersionBefore(SLV_ECONOMY_DATE)) {
EconTime::Detail::SetDate(EconTime::CurDate(), EconTime::CurDateFract());
} else {
/* Set economy date from calendar date */
EconTime::Detail::SetDate(CalTime::CurDate().base(), CalTime::CurDateFract());
}
SetupTileLoopCounts(); SetupTileLoopCounts();
/* /*
@ -917,7 +925,7 @@ bool AfterLoadGame()
} }
if (IsSavegameVersionBefore(SLV_ENDING_YEAR)) { if (IsSavegameVersionBefore(SLV_ENDING_YEAR)) {
_settings_game.game_creation.ending_year = DEF_END_YEAR; _settings_game.game_creation.ending_year = CalTime::DEF_END_YEAR;
} }
/* Convert linkgraph update settings from days to seconds. */ /* Convert linkgraph update settings from days to seconds. */
@ -1804,20 +1812,22 @@ bool AfterLoadGame()
/* Time starts at 0 instead of 1920. /* Time starts at 0 instead of 1920.
* Account for this in older games by adding an offset */ * Account for this in older games by adding an offset */
if (IsSavegameVersionBefore(SLV_31)) { if (IsSavegameVersionBefore(SLV_31)) {
_date += DAYS_TILL_ORIGINAL_BASE_YEAR.AsDelta(); CalTime::Detail::now.cal_date += CalTime::DAYS_TILL_ORIGINAL_BASE_YEAR.AsDelta();
EconTime::Detail::now.econ_date += EconTime::DAYS_TILL_ORIGINAL_BASE_YEAR.AsDelta();
CalTime::Detail::now.cal_ymd = CalTime::ConvertDateToYMD(CalTime::CurDate());
EconTime::Detail::now.econ_ymd = EconTime::ConvertDateToYMD(EconTime::CurDate());
RecalculateStateTicksOffset(); RecalculateStateTicksOffset();
_cur_date_ymd = ConvertDateToYMD(_date);
UpdateCachedSnowLine(); UpdateCachedSnowLine();
for (Station *st : Station::Iterate()) st->build_date += DAYS_TILL_ORIGINAL_BASE_YEAR.AsDelta(); for (Station *st : Station::Iterate()) st->build_date += CalTime::DAYS_TILL_ORIGINAL_BASE_YEAR.AsDelta();
for (Waypoint *wp : Waypoint::Iterate()) wp->build_date += DAYS_TILL_ORIGINAL_BASE_YEAR.AsDelta(); for (Waypoint *wp : Waypoint::Iterate()) wp->build_date += CalTime::DAYS_TILL_ORIGINAL_BASE_YEAR.AsDelta();
for (Engine *e : Engine::Iterate()) e->intro_date += DAYS_TILL_ORIGINAL_BASE_YEAR.AsDelta(); for (Engine *e : Engine::Iterate()) e->intro_date += CalTime::DAYS_TILL_ORIGINAL_BASE_YEAR.AsDelta();
for (Company *c : Company::Iterate()) c->inaugurated_year += ORIGINAL_BASE_YEAR; for (Company *c : Company::Iterate()) c->inaugurated_year += CalTime::ORIGINAL_BASE_YEAR.AsDelta();
for (Industry *i : Industry::Iterate()) i->last_prod_year += ORIGINAL_BASE_YEAR; for (Industry *i : Industry::Iterate()) i->last_prod_year += CalTime::ORIGINAL_BASE_YEAR.AsDelta();
for (Vehicle *v : Vehicle::Iterate()) { for (Vehicle *v : Vehicle::Iterate()) {
v->date_of_last_service += DAYS_TILL_ORIGINAL_BASE_YEAR.AsDelta(); v->date_of_last_service += EconTime::DAYS_TILL_ORIGINAL_BASE_YEAR.AsDelta();
v->build_year += ORIGINAL_BASE_YEAR; v->build_year += CalTime::ORIGINAL_BASE_YEAR.AsDelta();
} }
} }
@ -2327,7 +2337,7 @@ bool AfterLoadGame()
/* Replace "house construction year" with "house age" */ /* Replace "house construction year" with "house age" */
if (IsTileType(t, MP_HOUSE) && IsHouseCompleted(t)) { if (IsTileType(t, MP_HOUSE) && IsHouseCompleted(t)) {
_m[t].m5 = ClampTo<uint8_t>(_cur_year - (_m[t].m5 + ORIGINAL_BASE_YEAR)); _m[t].m5 = ClampTo<uint8_t>(CalTime::CurYear() - (_m[t].m5 + CalTime::ORIGINAL_BASE_YEAR.base()));
} }
} }
} }
@ -2507,7 +2517,7 @@ bool AfterLoadGame()
o->location.tile = t; o->location.tile = t;
o->location.w = size; o->location.w = size;
o->location.h = size; o->location.h = size;
o->build_date = _date; o->build_date = CalTime::CurDate();
o->town = type == OBJECT_STATUE ? Town::Get(_m[t].m2) : CalcClosestTownFromTile(t, UINT_MAX); o->town = type == OBJECT_STATUE ? Town::Get(_m[t].m2) : CalcClosestTownFromTile(t, UINT_MAX);
_m[t].m2 = o->index; _m[t].m2 = o->index;
Object::IncTypeCount(type); Object::IncTypeCount(type);
@ -2826,7 +2836,7 @@ bool AfterLoadGame()
} }
if (IsSavegameVersionBefore(SLV_142)) { if (IsSavegameVersionBefore(SLV_142)) {
for (Depot *d : Depot::Iterate()) d->build_date = _date; for (Depot *d : Depot::Iterate()) d->build_date = CalTime::CurDate();
} }
if (SlXvIsFeatureMissing(XSLFI_INFRA_SHARING)) { if (SlXvIsFeatureMissing(XSLFI_INFRA_SHARING)) {
@ -3714,7 +3724,7 @@ bool AfterLoadGame()
/* clear the PBS bit, update the end signal state */ /* clear the PBS bit, update the end signal state */
for (TileIndex t = 0; t < map_size; t++) { for (TileIndex t = 0; t < map_size; t++) {
if (IsTileType(t, MP_TUNNELBRIDGE) && GetTunnelBridgeTransportType(t) == TRANSPORT_RAIL && IsTunnelBridgeWithSignalSimulation(t)) { if (IsTileType(t, MP_TUNNELBRIDGE) && GetTunnelBridgeTransportType(t) == TRANSPORT_RAIL && IsTunnelBridgeWithSignalSimulation(t)) {
SetTunnelBridgeSemaphore(t, _cur_year < _settings_client.gui.semaphore_build_before); SetTunnelBridgeSemaphore(t, CalTime::CurYear() < _settings_client.gui.semaphore_build_before);
SetTunnelBridgePBS(t, false); SetTunnelBridgePBS(t, false);
UpdateSignalsOnSegment(t, INVALID_DIAGDIR, GetTileOwner(t)); UpdateSignalsOnSegment(t, INVALID_DIAGDIR, GetTileOwner(t));
} }
@ -4340,7 +4350,7 @@ bool AfterLoadGame()
if (IsSavegameVersionBefore(SLV_NEWGRF_LAST_SERVICE) && SlXvIsFeatureMissing(XSLFI_NEWGRF_LAST_SERVICE)) { if (IsSavegameVersionBefore(SLV_NEWGRF_LAST_SERVICE) && SlXvIsFeatureMissing(XSLFI_NEWGRF_LAST_SERVICE)) {
/* Set service date provided to NewGRF. */ /* Set service date provided to NewGRF. */
for (Vehicle *v : Vehicle::Iterate()) { for (Vehicle *v : Vehicle::Iterate()) {
v->date_of_last_service_newgrf = v->date_of_last_service; v->date_of_last_service_newgrf = v->date_of_last_service.base();
} }
} }
@ -4425,9 +4435,9 @@ bool AfterLoadGame()
#endif #endif
} }
_game_load_cur_date_ymd = _cur_date_ymd; _game_load_cur_date_ymd = EconTime::CurYMD();
_game_load_date_fract = _date_fract; _game_load_date_fract = EconTime::CurDateFract();
_game_load_tick_skip_counter = _tick_skip_counter; _game_load_tick_skip_counter = TickSkipCounter();
_game_load_state_ticks = _state_ticks; _game_load_state_ticks = _state_ticks;
_game_load_time = time(nullptr); _game_load_time = time(nullptr);

@ -43,7 +43,7 @@ struct ProducedCargo {
struct AcceptedCargo { struct AcceptedCargo {
CargoID cargo; ///< Cargo type CargoID cargo; ///< Cargo type
uint16_t waiting; ///< Amount of cargo waiting to processed uint16_t waiting; ///< Amount of cargo waiting to processed
Date last_accepted; ///< Last day cargo was accepted by this industry EconTime::Date last_accepted; ///< Last day cargo was accepted by this industry
}; };
class SlIndustryAccepted : public DefaultSaveLoadHandler<SlIndustryAccepted, Industry> { class SlIndustryAccepted : public DefaultSaveLoadHandler<SlIndustryAccepted, Industry> {

@ -43,11 +43,14 @@ extern TimeoutTimer<TimerGameTick> _new_competitor_timeout;
namespace upstream_sl { namespace upstream_sl {
static const SaveLoad _date_desc[] = { static const SaveLoad _date_desc[] = {
SLEG_CONDVAR("date", _date, SLE_FILE_U16 | SLE_VAR_I32, SL_MIN_VERSION, SLV_31), SLEG_CONDVAR("date", CalTime::Detail::now.cal_date, SLE_FILE_U16 | SLE_VAR_I32, SL_MIN_VERSION, SLV_31),
SLEG_CONDVAR("date", _date, SLE_INT32, SLV_31, SL_MAX_VERSION), SLEG_CONDVAR("date", CalTime::Detail::now.cal_date, SLE_INT32, SLV_31, SL_MAX_VERSION),
SLEG_VAR("date_fract", _date_fract, SLE_UINT16), SLEG_VAR("date_fract", CalTime::Detail::now.cal_date_fract, SLE_UINT16),
SLEG_CONDVAR("tick_counter", _tick_counter, SLE_FILE_U16 | SLE_VAR_U64, SL_MIN_VERSION, SLV_U64_TICK_COUNTER), SLEG_CONDVAR("tick_counter", _tick_counter, SLE_FILE_U16 | SLE_VAR_U64, SL_MIN_VERSION, SLV_U64_TICK_COUNTER),
SLEG_CONDVAR("tick_counter", _tick_counter, SLE_UINT64, SLV_U64_TICK_COUNTER, SL_MAX_VERSION), SLEG_CONDVAR("tick_counter", _tick_counter, SLE_UINT64, SLV_U64_TICK_COUNTER, SL_MAX_VERSION),
SLEG_CONDVAR("economy_date", EconTime::Detail::now.econ_date, SLE_INT32, SLV_ECONOMY_DATE, SL_MAX_VERSION),
SLEG_CONDVAR("economy_date_fract", EconTime::Detail::now.econ_date_fract, SLE_UINT16, SLV_ECONOMY_DATE, SL_MAX_VERSION),
SLEG_CONDVAR("calendar_sub_date_fract", CalTime::Detail::now.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("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_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), SLEG_CONDVAR("cur_tileloop_tile", _cur_tileloop_tile, SLE_UINT32, SLV_6, SL_MAX_VERSION),
@ -104,7 +107,7 @@ struct DATEChunkHandler : ChunkHandler {
this->LoadCommon(_date_check_desc, _date_check_sl_compat); this->LoadCommon(_date_check_desc, _date_check_sl_compat);
if (IsSavegameVersionBefore(SLV_31)) { if (IsSavegameVersionBefore(SLV_31)) {
_load_check_data.current_date += DAYS_TILL_ORIGINAL_BASE_YEAR.AsDelta(); _load_check_data.current_date += CalTime::DAYS_TILL_ORIGINAL_BASE_YEAR.AsDelta();
} }
} }
}; };

@ -178,8 +178,8 @@ static void AddNewScheduledDispatchSchedule(VehicleID vindex)
duration = 24 * 60 * _settings_time.ticks_per_minute; duration = 24 * 60 * _settings_time.ticks_per_minute;
} else { } else {
/* Set Jan 1st and 365 day */ /* Set Jan 1st and 365 day, calendar and economy time must be locked together for this to result in a useful schedule */
start_tick = DateToStateTicks(DateAtStartOfYear(_cur_year)); start_tick = DateToStateTicks(CalTime::DateAtStartOfYear(CalTime::CurYear()).base());
duration = 365 * DAY_TICKS; duration = 365 * DAY_TICKS;
} }
@ -280,7 +280,7 @@ struct SchdispatchWindow : GeneralVehicleWindow {
case WID_SCHDISPATCH_MATRIX: { case WID_SCHDISPATCH_MATRIX: {
uint min_height = 0; uint min_height = 0;
SetDParamMaxValue(0, _settings_time.time_in_minutes ? 0 : MAX_YEAR * DAYS_IN_YEAR); SetDParamMaxValue(0, _settings_time.time_in_minutes ? 0 : EconTime::MAX_YEAR.base() * DAYS_IN_YEAR);
Dimension unumber = GetStringBoundingBox(STR_SCHDISPATCH_DATE_WALLCLOCK_TINY_FLAGGED); Dimension unumber = GetStringBoundingBox(STR_SCHDISPATCH_DATE_WALLCLOCK_TINY_FLAGGED);
const Sprite *spr = GetSprite(SPR_FLAG_VEH_STOPPED, SpriteType::Normal, ZoomMask(ZOOM_LVL_GUI)); const Sprite *spr = GetSprite(SPR_FLAG_VEH_STOPPED, SpriteType::Normal, ZoomMask(ZOOM_LVL_GUI));
@ -940,7 +940,7 @@ struct SchdispatchWindow : GeneralVehicleWindow {
} else if (_settings_time.time_in_minutes && _settings_client.gui.timetable_start_text_entry) { } else if (_settings_time.time_in_minutes && _settings_client.gui.timetable_start_text_entry) {
ShowQueryString(STR_EMPTY, STR_SCHDISPATCH_ADD_CAPTION, 31, this, CS_NUMERAL, QSF_NONE); ShowQueryString(STR_EMPTY, STR_SCHDISPATCH_ADD_CAPTION, 31, this, CS_NUMERAL, QSF_NONE);
} else { } else {
ShowSetDateWindow(this, v->index | (this->schedule_index << 20), _state_ticks, _cur_year, _cur_year + 15, ScheduleAddCallback, STR_SCHDISPATCH_ADD, STR_SCHDISPATCH_ADD_TOOLTIP); ShowSetDateWindow(this, v->index | (this->schedule_index << 20), _state_ticks, EconTime::CurYear(), EconTime::CurYear() + 15, ScheduleAddCallback, STR_SCHDISPATCH_ADD, STR_SCHDISPATCH_ADD_TOOLTIP);
} }
break; break;
} }
@ -959,7 +959,7 @@ struct SchdispatchWindow : GeneralVehicleWindow {
SetDParam(0, _settings_time.NowInTickMinutes().ClockHHMM()); SetDParam(0, _settings_time.NowInTickMinutes().ClockHHMM());
ShowQueryString(STR_JUST_INT, STR_SCHDISPATCH_START_CAPTION_MINUTE, 31, this, CS_NUMERAL, QSF_ACCEPT_UNCHANGED); ShowQueryString(STR_JUST_INT, STR_SCHDISPATCH_START_CAPTION_MINUTE, 31, this, CS_NUMERAL, QSF_ACCEPT_UNCHANGED);
} else { } else {
ShowSetDateWindow(this, v->index | (this->schedule_index << 20), _state_ticks, _cur_year, _cur_year + 15, SetScheduleStartDateCallback, STR_SCHDISPATCH_SET_START, STR_SCHDISPATCH_START_TOOLTIP); ShowSetDateWindow(this, v->index | (this->schedule_index << 20), _state_ticks, EconTime::CurYear(), EconTime::CurYear() + 15, SetScheduleStartDateCallback, STR_SCHDISPATCH_SET_START, STR_SCHDISPATCH_START_TOOLTIP);
} }
break; break;
} }

@ -22,7 +22,7 @@
{ {
if (bridge_id >= MAX_BRIDGES) return false; if (bridge_id >= MAX_BRIDGES) return false;
const BridgeSpec *b = ::GetBridgeSpec(bridge_id); const BridgeSpec *b = ::GetBridgeSpec(bridge_id);
return b->avail_year <= _cur_year && !HasBit(b->ctrl_flags, BSCF_NOT_AVAILABLE_AI_GS); return b->avail_year <= CalTime::CurYear() && !HasBit(b->ctrl_flags, BSCF_NOT_AVAILABLE_AI_GS);
} }
/* static */ bool ScriptBridge::IsBridgeTile(TileIndex tile) /* static */ bool ScriptBridge::IsBridgeTile(TileIndex tile)

@ -25,7 +25,7 @@
/* static */ ScriptDate::Date ScriptDate::GetCurrentDate() /* static */ ScriptDate::Date ScriptDate::GetCurrentDate()
{ {
return (ScriptDate::Date)_date.base(); return (ScriptDate::Date)::CalTime::CurDate().base();
} }
/* static */ SQInteger ScriptDate::GetDayLengthFactor() /* static */ SQInteger ScriptDate::GetDayLengthFactor()
@ -37,15 +37,15 @@
{ {
if (date < 0) return DATE_INVALID; if (date < 0) return DATE_INVALID;
::YearMonthDay ymd = ::ConvertDateToYMD(date); ::CalTime::YearMonthDay ymd = ::CalTime::ConvertDateToYMD(date);
return ymd.year; return ymd.year.base();
} }
/* static */ SQInteger ScriptDate::GetMonth(ScriptDate::Date date) /* static */ SQInteger ScriptDate::GetMonth(ScriptDate::Date date)
{ {
if (date < 0) return DATE_INVALID; if (date < 0) return DATE_INVALID;
::YearMonthDay ymd = ::ConvertDateToYMD(date); ::CalTime::YearMonthDay ymd = ::CalTime::ConvertDateToYMD(date);
return ymd.month + 1; return ymd.month + 1;
} }
@ -53,7 +53,7 @@
{ {
if (date < 0) return DATE_INVALID; if (date < 0) return DATE_INVALID;
::YearMonthDay ymd = ::ConvertDateToYMD(date); ::CalTime::YearMonthDay ymd = ::CalTime::ConvertDateToYMD(date);
return ymd.day; return ymd.day;
} }
@ -61,9 +61,9 @@
{ {
if (month < 1 || month > 12) return DATE_INVALID; if (month < 1 || month > 12) return DATE_INVALID;
if (day_of_month < 1 || day_of_month > 31) return DATE_INVALID; if (day_of_month < 1 || day_of_month > 31) return DATE_INVALID;
if (year < 0 || year > MAX_YEAR) return DATE_INVALID; if (year < 0 || year > CalTime::MAX_YEAR) return DATE_INVALID;
return (ScriptDate::Date)::ConvertYMDToDate(year, month - 1, day_of_month).base(); return (ScriptDate::Date)::CalTime::ConvertYMDToDate(year, month - 1, day_of_month).base();
} }
/* static */ SQInteger ScriptDate::GetSystemTime() /* static */ SQInteger ScriptDate::GetSystemTime()

@ -31,7 +31,7 @@ public:
* compose valid date values for a known year, month and day. * compose valid date values for a known year, month and day.
*/ */
enum Date { enum Date {
DATE_INVALID = ::INVALID_DATE.base(), ///< A value representing an invalid date. DATE_INVALID = ::CalTime::INVALID_DATE.base(), ///< A value representing an invalid date.
}; };
/** /**

@ -221,7 +221,7 @@
{ {
Industry *i = Industry::GetIfValid(industry_id); Industry *i = Industry::GetIfValid(industry_id);
if (i == nullptr) return 0; if (i == nullptr) return 0;
return i->last_prod_year; return i->last_prod_year.base();
} }
/* static */ ScriptDate::Date ScriptIndustry::GetCargoLastAcceptedDate(IndustryID industry_id, CargoID cargo_type) /* static */ ScriptDate::Date ScriptIndustry::GetCargoLastAcceptedDate(IndustryID industry_id, CargoID cargo_type)
@ -230,7 +230,7 @@
if (i == nullptr) return ScriptDate::DATE_INVALID; if (i == nullptr) return ScriptDate::DATE_INVALID;
if (cargo_type == INVALID_CARGO) { if (cargo_type == INVALID_CARGO) {
return (ScriptDate::Date)std::accumulate(std::begin(i->last_cargo_accepted_at), std::end(i->last_cargo_accepted_at), Date(0), [](Date a, Date b) { return std::max(a, b); }).base(); return (ScriptDate::Date)std::accumulate(std::begin(i->last_cargo_accepted_at), std::end(i->last_cargo_accepted_at), EconTime::Date(0), [](EconTime::Date a, EconTime::Date b) { return std::max(a, b); }).base();
} else { } else {
int index = i->GetCargoAcceptedIndex(cargo_type); int index = i->GetCargoAcceptedIndex(cargo_type);
if (index < 0) return ScriptDate::DATE_INVALID; if (index < 0) return ScriptDate::DATE_INVALID;

@ -3368,7 +3368,7 @@ struct CustomCurrencyWindow : Window {
this->SetWidgetDisabledState(WID_CC_RATE_DOWN, _custom_currency.rate == 1); this->SetWidgetDisabledState(WID_CC_RATE_DOWN, _custom_currency.rate == 1);
this->SetWidgetDisabledState(WID_CC_RATE_UP, _custom_currency.rate == UINT16_MAX); this->SetWidgetDisabledState(WID_CC_RATE_UP, _custom_currency.rate == UINT16_MAX);
this->SetWidgetDisabledState(WID_CC_YEAR_DOWN, _custom_currency.to_euro == CF_NOEURO); this->SetWidgetDisabledState(WID_CC_YEAR_DOWN, _custom_currency.to_euro == CF_NOEURO);
this->SetWidgetDisabledState(WID_CC_YEAR_UP, _custom_currency.to_euro == MAX_YEAR); this->SetWidgetDisabledState(WID_CC_YEAR_UP, _custom_currency.to_euro == CalTime::MAX_YEAR);
} }
void SetStringParameters(WidgetID widget) const override void SetStringParameters(WidgetID widget) const override
@ -3475,8 +3475,8 @@ struct CustomCurrencyWindow : Window {
break; break;
case WID_CC_YEAR_UP: case WID_CC_YEAR_UP:
_custom_currency.to_euro = Clamp(_custom_currency.to_euro + 1, 2000, MAX_YEAR); _custom_currency.to_euro = Clamp<CalTime::Year>(_custom_currency.to_euro + 1, 2000, CalTime::MAX_YEAR);
if (_custom_currency.to_euro == MAX_YEAR) this->DisableWidget(WID_CC_YEAR_UP); if (_custom_currency.to_euro == CalTime::MAX_YEAR) this->DisableWidget(WID_CC_YEAR_UP);
this->EnableWidget(WID_CC_YEAR_DOWN); this->EnableWidget(WID_CC_YEAR_DOWN);
break; break;
@ -3522,7 +3522,7 @@ struct CustomCurrencyWindow : Window {
case WID_CC_YEAR: { // Year to switch to euro case WID_CC_YEAR: { // Year to switch to euro
int val = atoi(str); int val = atoi(str);
_custom_currency.to_euro = (val < 2000 ? CF_NOEURO : std::min(val, MAX_YEAR)); _custom_currency.to_euro = (val < 2000 ? CF_NOEURO : std::min<CalTime::Year>(val, CalTime::MAX_YEAR));
break; break;
} }
} }

@ -244,7 +244,7 @@ struct GUISettings : public TimeSettings {
SignalGUISettings signal_gui_mode; ///< select which signal types are shown in the signal GUI SignalGUISettings signal_gui_mode; ///< select which signal types are shown in the signal GUI
SignalCycleSettings cycle_signal_types; ///< Which signal types to cycle with the build signal tool. SignalCycleSettings cycle_signal_types; ///< Which signal types to cycle with the build signal tool.
SignalType default_signal_type; ///< The default signal type, which is set automatically by the last signal used. Not available in Settings. SignalType default_signal_type; ///< The default signal type, which is set automatically by the last signal used. Not available in Settings.
Year coloured_news_year; ///< when does newspaper become coloured? CalTime::Year coloured_news_year; ///< when does newspaper become coloured?
bool override_time_settings; ///< Whether to override time display settings stored in savegame. bool override_time_settings; ///< Whether to override time display settings stored in savegame.
bool timetable_in_ticks; ///< whether to show the timetable in ticks rather than days bool timetable_in_ticks; ///< whether to show the timetable in ticks rather than days
bool timetable_leftover_ticks; ///< whether to show leftover ticks after converting to minutes/days, in the timetable bool timetable_leftover_ticks; ///< whether to show leftover ticks after converting to minutes/days, in the timetable
@ -255,7 +255,7 @@ struct GUISettings : public TimeSettings {
byte drag_signals_density; ///< many signals density byte drag_signals_density; ///< many signals density
bool drag_signals_fixed_distance; ///< keep fixed distance between signals when dragging bool drag_signals_fixed_distance; ///< keep fixed distance between signals when dragging
bool drag_signals_skip_stations; ///< continue past station/waypoint tiles when auto-fill dragging signals bool drag_signals_skip_stations; ///< continue past station/waypoint tiles when auto-fill dragging signals
Year semaphore_build_before; ///< build semaphore signals automatically before this year CalTime::Year semaphore_build_before; ///< build semaphore signals automatically before this year
byte news_message_timeout; ///< how much longer than the news message "age" should we keep the message in the history byte news_message_timeout; ///< how much longer than the news message "age" should we keep the message in the history
bool show_track_reservation; ///< highlight reserved tracks. bool show_track_reservation; ///< highlight reserved tracks.
byte station_numtracks; ///< the number of platforms to default on for rail stations byte station_numtracks; ///< the number of platforms to default on for rail stations
@ -441,7 +441,7 @@ struct NetworkSettings {
uint8_t autoclean_novehicles; ///< remove companies with no vehicles after this many months uint8_t autoclean_novehicles; ///< remove companies with no vehicles after this many months
uint8_t max_companies; ///< maximum amount of companies uint8_t max_companies; ///< maximum amount of companies
uint8_t max_clients; ///< maximum amount of clients uint8_t max_clients; ///< maximum amount of clients
Year restart_game_year; ///< year the server restarts CalTime::Year restart_game_year; ///< year the server restarts
uint8_t min_active_clients; ///< minimum amount of active clients to unpause the game uint8_t min_active_clients; ///< minimum amount of active clients to unpause the game
bool reload_cfg; ///< reload the config file before restarting bool reload_cfg; ///< reload the config file before restarting
std::string last_joined; ///< Last joined server std::string last_joined; ///< Last joined server
@ -454,8 +454,8 @@ struct NetworkSettings {
struct GameCreationSettings { struct GameCreationSettings {
uint32_t generation_seed; ///< noise seed for world generation uint32_t generation_seed; ///< noise seed for world generation
uint32_t generation_unique_id; ///< random id to differentiate savegames uint32_t generation_unique_id; ///< random id to differentiate savegames
Year starting_year; ///< starting date CalTime::Year starting_year; ///< starting date
Year ending_year; ///< scoring end date CalTime::Year ending_year; ///< scoring end date
uint8_t map_x; ///< X size of map uint8_t map_x; ///< X size of map
uint8_t map_y; ///< Y size of map uint8_t map_y; ///< Y size of map
byte land_generator; ///< the landscape generator byte land_generator; ///< the landscape generator
@ -527,7 +527,7 @@ struct ConstructionSettings {
bool allow_docks_under_bridges; ///< allow docks under bridges bool allow_docks_under_bridges; ///< allow docks under bridges
byte purchase_land_permitted; ///< whether and how purchasing land is permitted byte purchase_land_permitted; ///< whether and how purchasing land is permitted
bool build_object_area_permitted; ///< whether building objects by area is permitted bool build_object_area_permitted; ///< whether building objects by area is permitted
Year no_expire_objects_after; ///< do not expire objects after this year CalTime::Year no_expire_objects_after; ///< do not expire objects after this year
bool ignore_object_intro_dates; ///< allow players to build objects before their introduction dates (does not include during map generation) bool ignore_object_intro_dates; ///< allow players to build objects before their introduction dates (does not include during map generation)
bool convert_town_road_no_houses; ///< allow converting town roads to a type which does not allow houses bool convert_town_road_no_houses; ///< allow converting town roads to a type which does not allow houses
@ -694,8 +694,8 @@ struct VehicleSettings {
uint8_t freight_trains; ///< value to multiply the weight of cargo by uint8_t freight_trains; ///< value to multiply the weight of cargo by
bool dynamic_engines; ///< enable dynamic allocation of engine data bool dynamic_engines; ///< enable dynamic allocation of engine data
bool never_expire_vehicles; ///< never expire vehicles bool never_expire_vehicles; ///< never expire vehicles
Year no_expire_vehicles_after; ///< do not expire vehicles after this year CalTime::Year no_expire_vehicles_after; ///< do not expire vehicles after this year
Year no_introduce_vehicles_after; ///< do not introduce vehicles after this year CalTime::Year no_introduce_vehicles_after; ///< do not introduce vehicles after this year
byte extend_vehicle_life; ///< extend vehicle life by this many years byte extend_vehicle_life; ///< extend vehicle life by this many years
byte road_side; ///< the side of the road vehicles drive on byte road_side; ///< the side of the road vehicles drive on
uint8_t plane_crashes; ///< number of plane crashes, 0 = none, 1 = reduced, 2 = normal uint8_t plane_crashes; ///< number of plane crashes, 0 = none, 1 = reduced, 2 = normal

@ -1196,9 +1196,9 @@ CommandCost CmdBuildShip(TileIndex tile, DoCommandFlag flags, const Engine *e, V
v->state = TRACK_BIT_DEPOT; v->state = TRACK_BIT_DEPOT;
v->SetServiceInterval(Company::Get(_current_company)->settings.vehicle.servint_ships); v->SetServiceInterval(Company::Get(_current_company)->settings.vehicle.servint_ships);
v->date_of_last_service = _date; v->date_of_last_service = EconTime::CurDate();
v->date_of_last_service_newgrf = _date; v->date_of_last_service_newgrf = CalTime::CurDate();
v->build_year = _cur_year; v->build_year = CalTime::CurYear();
v->sprite_seq.Set(SPR_IMG_QUERY); v->sprite_seq.Set(SPR_IMG_QUERY);
v->random_bits = Random(); v->random_bits = Random();

@ -103,7 +103,7 @@ const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = {
{ XSLFI_VEHICLE_REPAIR_COST, XSCF_NULL, 2, 2, "vehicle_repair_cost", nullptr, nullptr, nullptr }, { XSLFI_VEHICLE_REPAIR_COST, XSCF_NULL, 2, 2, "vehicle_repair_cost", nullptr, nullptr, nullptr },
{ XSLFI_ENH_VIEWPORT_PLANS, XSCF_IGNORABLE_ALL, 4, 4, "enh_viewport_plans", nullptr, nullptr, "PLAN" }, { XSLFI_ENH_VIEWPORT_PLANS, XSCF_IGNORABLE_ALL, 4, 4, "enh_viewport_plans", nullptr, nullptr, "PLAN" },
{ XSLFI_INFRA_SHARING, XSCF_NULL, 2, 2, "infra_sharing", nullptr, nullptr, "CPDP" }, { XSLFI_INFRA_SHARING, XSCF_NULL, 2, 2, "infra_sharing", nullptr, nullptr, "CPDP" },
{ XSLFI_VARIABLE_DAY_LENGTH, XSCF_NULL, 4, 4, "variable_day_length", nullptr, nullptr, nullptr }, { XSLFI_VARIABLE_DAY_LENGTH, XSCF_NULL, 5, 5, "variable_day_length", nullptr, nullptr, nullptr },
{ XSLFI_ORDER_OCCUPANCY, XSCF_NULL, 2, 2, "order_occupancy", nullptr, nullptr, nullptr }, { XSLFI_ORDER_OCCUPANCY, XSCF_NULL, 2, 2, "order_occupancy", nullptr, nullptr, nullptr },
{ XSLFI_MORE_COND_ORDERS, XSCF_NULL, 17, 17, "more_cond_orders", nullptr, nullptr, nullptr }, { XSLFI_MORE_COND_ORDERS, XSCF_NULL, 17, 17, "more_cond_orders", nullptr, nullptr, nullptr },
{ XSLFI_EXTRA_LARGE_MAP, XSCF_NULL, 0, 1, "extra_large_map", nullptr, nullptr, nullptr }, { XSLFI_EXTRA_LARGE_MAP, XSCF_NULL, 0, 1, "extra_large_map", nullptr, nullptr, nullptr },

@ -84,14 +84,14 @@ byte _age_cargo_skip_counter; ///< Skip aging of cargo? Used before savegame ver
extern TimeoutTimer<TimerGameTick> _new_competitor_timeout; extern TimeoutTimer<TimerGameTick> _new_competitor_timeout;
static const NamedSaveLoad _date_desc[] = { static const NamedSaveLoad _date_desc[] = {
NSL("", SLEG_CONDVAR(_date, SLE_FILE_U16 | SLE_VAR_I32, SL_MIN_VERSION, SLV_31)), NSL("", SLEG_CONDVAR(CalTime::Detail::now.cal_date, SLE_FILE_U16 | SLE_VAR_I32, SL_MIN_VERSION, SLV_31)),
NSL("date", SLEG_CONDVAR(_date, SLE_INT32, SLV_31, SL_MAX_VERSION)), NSL("date", SLEG_CONDVAR(CalTime::Detail::now.cal_date, SLE_INT32, SLV_31, SL_MAX_VERSION)),
NSL("date_fract", SLEG_VAR(_date_fract, SLE_UINT16)), NSL("date_fract", SLEG_VAR(CalTime::Detail::now.cal_date_fract, SLE_UINT16)),
NSL("", SLEG_CONDVAR_X(_tick_counter, SLE_FILE_U16 | SLE_VAR_U64, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_U64_TICK_COUNTER, 0, 0))), NSL("", SLEG_CONDVAR_X(_tick_counter, SLE_FILE_U16 | SLE_VAR_U64, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_U64_TICK_COUNTER, 0, 0))),
NSL("tick_counter", SLEG_CONDVAR_X(_tick_counter, SLE_UINT64, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_U64_TICK_COUNTER))), NSL("tick_counter", SLEG_CONDVAR_X(_tick_counter, SLE_UINT64, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_U64_TICK_COUNTER))),
NSL("tick_skip_counter", SLEG_CONDVAR_X(_tick_skip_counter, SLE_UINT8, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_VARIABLE_DAY_LENGTH))), NSL("tick_skip_counter", SLEG_CONDVAR_X(DateDetail::_tick_skip_counter, SLE_UINT8, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_VARIABLE_DAY_LENGTH))),
NSL("scaled_tick_counter", SLEG_CONDVAR_X(_scaled_tick_counter, SLE_UINT64, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_VARIABLE_DAY_LENGTH, 3))), NSL("scaled_tick_counter", SLEG_CONDVAR_X(_scaled_tick_counter, SLE_UINT64, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_VARIABLE_DAY_LENGTH, 3))),
NSL("", SLEG_CONDVAR_X(_state_ticks_offset, SLE_INT64, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_VARIABLE_DAY_LENGTH, 3, 3))), NSL("", SLEG_CONDVAR_X(DateDetail::_state_ticks_offset, SLE_INT64, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_VARIABLE_DAY_LENGTH, 3, 3))),
NSL("state_ticks", SLEG_CONDVAR_X(_state_ticks, SLE_INT64, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_VARIABLE_DAY_LENGTH, 4))), NSL("state_ticks", SLEG_CONDVAR_X(_state_ticks, SLE_INT64, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_VARIABLE_DAY_LENGTH, 4))),
NSL("", SLE_CONDNULL(2, SL_MIN_VERSION, SLV_157)), // _vehicle_id_ctr_day NSL("", SLE_CONDNULL(2, SL_MIN_VERSION, SLV_157)), // _vehicle_id_ctr_day
NSL("", SLEG_CONDVAR(_age_cargo_skip_counter, SLE_UINT8, SL_MIN_VERSION, SLV_162)), NSL("", SLEG_CONDVAR(_age_cargo_skip_counter, SLE_UINT8, SL_MIN_VERSION, SLV_162)),
@ -122,6 +122,9 @@ static const NamedSaveLoad _date_desc[] = {
/* New (table only) fields below */ /* New (table only) fields below */
NSLT("id", SLEG_CONDSSTR_X(_savegame_id, SLE_STR, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_SAVEGAME_ID))), NSLT("id", SLEG_CONDSSTR_X(_savegame_id, SLE_STR, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_SAVEGAME_ID))),
NSLT("economy_date", SLEG_CONDVAR_X(EconTime::Detail::now.econ_date, SLE_INT32, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_VARIABLE_DAY_LENGTH, 5))),
NSLT("economy_date_fract", SLEG_CONDVAR_X(EconTime::Detail::now.econ_date_fract, SLE_UINT16, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_VARIABLE_DAY_LENGTH, 5))),
NSLT("calendar_sub_date_fract", SLEG_CONDVAR_X(CalTime::Detail::now.sub_date_fract, SLE_UINT16, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_VARIABLE_DAY_LENGTH, 5))),
}; };
static const NamedSaveLoad _date_check_desc[] = { static const NamedSaveLoad _date_check_desc[] = {
@ -176,7 +179,7 @@ static void Check_DATE()
{ {
SlLoadTableOrRiffFiltered(_date_check_desc); SlLoadTableOrRiffFiltered(_date_check_desc);
if (IsSavegameVersionBefore(SLV_31)) { if (IsSavegameVersionBefore(SLV_31)) {
_load_check_data.current_date += DAYS_TILL_ORIGINAL_BASE_YEAR.AsDelta(); _load_check_data.current_date += CalTime::DAYS_TILL_ORIGINAL_BASE_YEAR.AsDelta();
} }
} }

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save