diff --git a/src/build_vehicle_gui.cpp b/src/build_vehicle_gui.cpp index 8b014169b8..b026f0ddc6 100644 --- a/src/build_vehicle_gui.cpp +++ b/src/build_vehicle_gui.cpp @@ -1177,7 +1177,7 @@ int DrawVehiclePurchaseInfo(int left, int right, int y, EngineID engine_number, if (e->type != VEH_TRAIN || e->u.rail.railveh_type != RAILVEH_WAGON) { /* Design date - Life length */ SetDParam(0, ymd.year); - SetDParam(1, DateToYear(e->GetLifeLengthInDays())); + SetDParam(1, DateDeltaToYears(e->GetLifeLengthInDays())); DrawString(left, right, y, STR_PURCHASE_INFO_DESIGNED_LIFE); y += GetCharacterHeight(FS_NORMAL); diff --git a/src/command.cpp b/src/command.cpp index af6cf5cd6c..120c781acb 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -1173,7 +1173,7 @@ CommandCost DoCommandPInternal(TileIndex tile, uint32 p1, uint32 p2, uint64 p3, if (!random_state.Check()) { std::string msg = stdstr_fmt("Random seed changed in test command: company: %02x; tile: %06x (%u x %u); p1: %08x; p2: %08x; p3: " OTTD_PRINTFHEX64PAD "; cmd: %08x; \"%s\"%s (%s)", (int)_current_company, tile, TileX(tile), TileY(tile), p1, p2, p3, cmd & ~CMD_NETWORK_COMMAND, text, aux_data != nullptr ? ", aux data present" : "", GetCommandName(cmd)); - DEBUG(desync, 0, "msg: date{%08x; %02x; %02x}; %s", _date, _date_fract, _tick_skip_counter, msg.c_str()); + DEBUG(desync, 0, "msg: date{%08x; %02x; %02x}; %s", _date.base(), _date_fract, _tick_skip_counter, msg.c_str()); LogDesyncMsg(std::move(msg)); } @@ -1191,7 +1191,7 @@ CommandCost DoCommandPInternal(TileIndex tile, uint32 p1, uint32 p2, uint64 p3, /* Log the failed command as well. Just to be able to be find * causes of desyncs due to bad command test implementations. */ DEBUG(desync, 1, "cmdf: date{%08x; %02x; %02x}; company: %02x; tile: %06x (%u x %u); p1: %08x; p2: %08x; p3: " OTTD_PRINTFHEX64PAD "; cmd: %08x; \"%s\"%s (%s)", - _date, _date_fract, _tick_skip_counter, (int)_current_company, tile, TileX(tile), TileY(tile), p1, p2, p3, cmd & ~CMD_NETWORK_COMMAND, text, aux_data != nullptr ? ", aux data present" : "", GetCommandName(cmd)); + _date.base(), _date_fract, _tick_skip_counter, (int)_current_company, tile, TileX(tile), TileY(tile), p1, p2, p3, cmd & ~CMD_NETWORK_COMMAND, text, aux_data != nullptr ? ", aux data present" : "", GetCommandName(cmd)); } cur_company.Restore(); return_dcpi(res); @@ -1212,7 +1212,7 @@ CommandCost DoCommandPInternal(TileIndex tile, uint32 p1, uint32 p2, uint64 p3, return_dcpi(CommandCost()); } DEBUG(desync, 1, "cmd: date{%08x; %02x; %02x}; company: %02x; tile: %06x (%u x %u); p1: %08x; p2: %08x; p3: " OTTD_PRINTFHEX64PAD "; cmd: %08x; \"%s\"%s(%s)", - _date, _date_fract, _tick_skip_counter, (int)_current_company, tile, TileX(tile), TileY(tile), p1, p2, p3, cmd & ~CMD_NETWORK_COMMAND, text, aux_data != nullptr ? ", aux data present" : "", GetCommandName(cmd)); + _date.base(), _date_fract, _tick_skip_counter, (int)_current_company, tile, TileX(tile), TileY(tile), p1, p2, p3, cmd & ~CMD_NETWORK_COMMAND, text, aux_data != nullptr ? ", aux data present" : "", GetCommandName(cmd)); /* Actually try and execute the command. If no cost-type is given * use the construction one */ diff --git a/src/company_cmd.cpp b/src/company_cmd.cpp index 3d7dfd1023..8253f541af 100644 --- a/src/company_cmd.cpp +++ b/src/company_cmd.cpp @@ -949,7 +949,7 @@ CommandCost CmdCompanyCtrl(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3 } NetworkServerNewCompany(c, ci); - DEBUG(desync, 1, "new_company: date{%08x; %02x; %02x}, company_id: %u", _date, _date_fract, _tick_skip_counter, c->index); + DEBUG(desync, 1, "new_company: date{%08x; %02x; %02x}, company_id: %u", _date.base(), _date_fract, _tick_skip_counter, c->index); break; } @@ -967,7 +967,7 @@ CommandCost CmdCompanyCtrl(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3 Company *c = DoStartupNewCompany(DSNC_AI, company_id); if (c != nullptr) { NetworkServerNewCompany(c, nullptr); - DEBUG(desync, 1, "new_company_ai: date{%08x; %02x; %02x}, company_id: %u", _date, _date_fract, _tick_skip_counter, c->index); + DEBUG(desync, 1, "new_company_ai: date{%08x; %02x; %02x}, company_id: %u", _date.base(), _date_fract, _tick_skip_counter, c->index); } break; } @@ -984,7 +984,7 @@ CommandCost CmdCompanyCtrl(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3 if (!(flags & DC_EXEC)) return CommandCost(); - DEBUG(desync, 1, "delete_company: date{%08x; %02x; %02x}, company_id: %u, reason: %u", _date, _date_fract, _tick_skip_counter, company_id, reason); + DEBUG(desync, 1, "delete_company: date{%08x; %02x; %02x}, company_id: %u, reason: %u", _date.base(), _date_fract, _tick_skip_counter, company_id, reason); CompanyNewsInformation *cni = new CompanyNewsInformation(c); diff --git a/src/company_gui.cpp b/src/company_gui.cpp index 6121244045..4fe2168d3e 100644 --- a/src/company_gui.cpp +++ b/src/company_gui.cpp @@ -1876,7 +1876,7 @@ struct CompanyInfrastructureWindow : Window } /* Get the date introduced railtypes as well. */ - this->railtypes = AddDateIntroducedRailTypes(this->railtypes, MAX_DAY); + this->railtypes = AddDateIntroducedRailTypes(this->railtypes, MAX_DATE); /* Find the used roadtypes. */ for (const Engine *e : Engine::IterateType(VEH_ROAD)) { @@ -1886,7 +1886,7 @@ struct CompanyInfrastructureWindow : Window } /* Get the date introduced roadtypes as well. */ - this->roadtypes = AddDateIntroducedRoadTypes(this->roadtypes, MAX_DAY); + this->roadtypes = AddDateIntroducedRoadTypes(this->roadtypes, MAX_DATE); this->roadtypes &= ~_roadtypes_hidden_mask; } diff --git a/src/console_cmds.cpp b/src/console_cmds.cpp index 654e407ce0..bb51f4c0c8 100644 --- a/src/console_cmds.cpp +++ b/src/console_cmds.cpp @@ -2490,7 +2490,7 @@ DEF_CONSOLE_CMD(ConMergeLinkgraphJobsAsap) return true; } - for (LinkGraphJob *lgj : LinkGraphJob::Iterate()) lgj->ShiftJoinDate((((_date * DAY_TICKS) + _date_fract) - lgj->JoinDateTicks()) / DAY_TICKS); + for (LinkGraphJob *lgj : LinkGraphJob::Iterate()) lgj->ShiftJoinDate((NowDateTicks() - lgj->JoinDateTicks()).base() / DAY_TICKS); return true; } @@ -2739,14 +2739,14 @@ DEF_CONSOLE_CMD(ConDumpLinkgraphJobs) IConsolePrintF(CC_DEFAULT, PRINTF_SIZE " link graph jobs", LinkGraphJob::GetNumItems()); for (const LinkGraphJob *lgj : LinkGraphJob::Iterate()) { YearMonthDay start_ymd; - ConvertDateToYMD(lgj->StartDateTicks() / DAY_TICKS, &start_ymd); + ConvertDateToYMD(lgj->StartDateTicks().ToDate(), &start_ymd); YearMonthDay join_ymd; - ConvertDateToYMD(lgj->JoinDateTicks() / DAY_TICKS, &join_ymd); + ConvertDateToYMD(lgj->JoinDateTicks().ToDate(), &join_ymd); IConsolePrintF(CC_DEFAULT, " Job: %5u, nodes: %u, cost: " OTTD_PRINTF64U ", start: (%u, %4i-%02i-%02i, %i), end: (%u, %4i-%02i-%02i, %i), duration: %u", lgj->index, lgj->Graph().Size(), lgj->Graph().CalculateCostEstimate(), - lgj->StartDateTicks(), start_ymd.year, start_ymd.month + 1, start_ymd.day, lgj->StartDateTicks() % DAY_TICKS, - lgj->JoinDateTicks(), join_ymd.year, join_ymd.month + 1, join_ymd.day, lgj->JoinDateTicks() % DAY_TICKS, - lgj->JoinDateTicks() - lgj->StartDateTicks()); + lgj->StartDateTicks().base(), start_ymd.year, 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() - lgj->StartDateTicks()).base()); } return true; } @@ -3686,20 +3686,20 @@ DEF_CONSOLE_CMD(ConIfDay) DEF_CONSOLE_CMD(ConIfHour) { - Minutes minutes = _scaled_date_ticks / _settings_time.ticks_per_minute + _settings_time.clock_offset; - return ConConditionalCommon(argc, argv, MINUTES_HOUR(minutes), "the current hour (in game, assuming time is in minutes)", "if_hour"); + TickMinutes minutes = _settings_time.NowInTickMinutes(); + return ConConditionalCommon(argc, argv, minutes.ClockHour(), "the current hour (in game, assuming time is in minutes)", "if_hour"); } DEF_CONSOLE_CMD(ConIfMinute) { - Minutes minutes = _scaled_date_ticks / _settings_time.ticks_per_minute + _settings_time.clock_offset; - return ConConditionalCommon(argc, argv, MINUTES_MINUTE(minutes), "the current minute (in game, assuming time is in minutes)", "if_minute"); + TickMinutes minutes = _settings_time.NowInTickMinutes(); + return ConConditionalCommon(argc, argv, minutes.ClockMinute(), "the current minute (in game, assuming time is in minutes)", "if_minute"); } DEF_CONSOLE_CMD(ConIfHourMinute) { - Minutes minutes = _scaled_date_ticks / _settings_time.ticks_per_minute + _settings_time.clock_offset; - return ConConditionalCommon(argc, argv, (MINUTES_HOUR(minutes) * 100) + MINUTES_MINUTE(minutes), "the current hour and minute 0000 - 2359 (in game, assuming time is in minutes)", "if_hour_minute"); + TickMinutes minutes = _settings_time.NowInTickMinutes(); + return ConConditionalCommon(argc, argv, minutes.ClockHHMM(), "the current hour and minute 0000 - 2359 (in game, assuming time is in minutes)", "if_hour_minute"); } #ifdef _DEBUG diff --git a/src/core/checksum_func.hpp b/src/core/checksum_func.hpp index a70911bc4c..25664eedf3 100644 --- a/src/core/checksum_func.hpp +++ b/src/core/checksum_func.hpp @@ -44,7 +44,7 @@ inline bool ShouldLogUpdateStateChecksum() return _networking && (!_network_server || (NetworkClientSocket::IsValidID(0) && NetworkClientSocket::Get(0)->status != NetworkClientSocket::STATUS_INACTIVE)); } # define DEBUG_UPDATESTATECHECKSUM(str, ...) if (ShouldLogUpdateStateChecksum()) DEBUG(statecsum, 0, "date{%08x; %02x; %02x}; %04x; %02x; " OTTD_PRINTFHEX64PAD "; %s:%d " str, \ - _date, _date_fract, _tick_skip_counter, _frame_counter, (byte)_current_company, _state_checksum.state, __FILE__, __LINE__, __VA_ARGS__); + _date.base(), _date_fract, _tick_skip_counter, _frame_counter, (byte)_current_company, _state_checksum.state, __FILE__, __LINE__, __VA_ARGS__); #else # define DEBUG_UPDATESTATECHECKSUM(str, ...) #endif /* RANDOM_DEBUG */ diff --git a/src/core/random_func.cpp b/src/core/random_func.cpp index 83b402bb02..687a0a033f 100644 --- a/src/core/random_func.cpp +++ b/src/core/random_func.cpp @@ -72,7 +72,7 @@ void SetRandomSeed(uint32 seed) uint32 DoRandom(int line, const char *file) { if (_networking && (!_network_server || (NetworkClientSocket::IsValidID(0) && NetworkClientSocket::Get(0)->status != NetworkClientSocket::STATUS_INACTIVE))) { - DEBUG(random, 0, "date{%08x; %02x; %02x}; %04x; %02x; %s:%d", _date, _date_fract, _tick_skip_counter, _frame_counter, (byte)_current_company, file, line); + DEBUG(random, 0, "date{%08x; %02x; %02x}; %04x; %02x; %s:%d", _date.base(), _date_fract, _tick_skip_counter, _frame_counter, (byte)_current_company, file, line); } return _random.Next(); diff --git a/src/date.cpp b/src/date.cpp index d77909527e..c22a788880 100644 --- a/src/date.cpp +++ b/src/date.cpp @@ -44,15 +44,15 @@ extern void ClearOutOfDateSignalSpeedRestrictions(); void CheckScaledDateTicksWrap() { - DateTicksScaled tick_adjust = 0; + DateTicksScaledDelta tick_adjust = 0; auto get_tick_adjust = [&](DateTicksScaled target) { int32 rounding = _settings_time.time_in_minutes * 1440; - return target - (target % rounding); + return target.AsDelta() - (target.base() % rounding); }; if (_scaled_date_ticks >= ((int64)1 << 60)) { tick_adjust = get_tick_adjust(_scaled_date_ticks); } else if (_scaled_date_ticks <= -((int64)1 << 60)) { - tick_adjust = -get_tick_adjust(-_scaled_date_ticks); + tick_adjust = -get_tick_adjust(-(_scaled_date_ticks.base())); } else { return; } @@ -60,13 +60,13 @@ void CheckScaledDateTicksWrap() _scaled_date_ticks_offset -= tick_adjust; _scaled_date_ticks -= tick_adjust; - extern void AdjustAllSignalSpeedRestrictionTickValues(DateTicksScaled delta); + extern void AdjustAllSignalSpeedRestrictionTickValues(DateTicksScaledDelta delta); AdjustAllSignalSpeedRestrictionTickValues(-tick_adjust); - extern void AdjustVehicleScaledTickBase(int64 delta); + extern void AdjustVehicleScaledTickBase(DateTicksScaledDelta delta); AdjustVehicleScaledTickBase(-tick_adjust); - extern void AdjustLinkGraphScaledTickBase(int64 delta); + extern void AdjustLinkGraphScaledTickBase(DateTicksScaledDelta delta); AdjustLinkGraphScaledTickBase(-tick_adjust); } @@ -106,7 +106,7 @@ void SetDate(Date date, DateFract fract, bool preserve_scaled_ticks) void SetScaledTickVariables() { - _scaled_date_ticks = ((((DateTicksScaled)_date * DAY_TICKS) + _date_fract) * _settings_game.economy.day_length_factor) + _tick_skip_counter + _scaled_date_ticks_offset; + _scaled_date_ticks = ((int64)(DateToDateTicks(_date, _date_fract).base()) * _settings_game.economy.day_length_factor) + _tick_skip_counter + _scaled_date_ticks_offset; } #define M(a, b) ((a << 5) | b) @@ -160,8 +160,8 @@ void ConvertDateToYMD(Date date, YearMonthDay *ymd) */ /* There are 97 leap years in 400 years */ - Year yr = 400 * (date / (DAYS_IN_YEAR * 400 + 97)); - int rem = date % (DAYS_IN_YEAR * 400 + 97); + Year yr = 400 * (date.base() / (DAYS_IN_YEAR * 400 + 97)); + int rem = date.base() % (DAYS_IN_YEAR * 400 + 97); uint16 x; if (rem >= DAYS_IN_YEAR * 100 + 25) { @@ -216,7 +216,7 @@ Date ConvertYMDToDate(Year year, Month month, Day day) /* Account for the missing of the 29th of February in non-leap years */ if (!IsLeapYear(year) && days >= ACCUM_MAR) days--; - return DAYS_TILL(year) + days; + return DateAtStartOfYear(year) + days; } /** Functions used by the IncreaseDate function */ diff --git a/src/date_func.h b/src/date_func.h index d7cb2d5eca..d532ae900d 100644 --- a/src/date_func.h +++ b/src/date_func.h @@ -38,7 +38,7 @@ inline Date ConvertYMDToDate(const YearMonthDay &ymd) return ConvertYMDToDate(ymd.year, ymd.month, ymd.day); } -#define _cur_year (static_cast(_cur_date_ymd.year)) +#define _cur_year (_cur_date_ymd.year) /** * Checks whether the given year is a leap year or not. @@ -52,22 +52,22 @@ static inline bool IsLeapYear(Year yr) static inline Date ScaledDateTicksToDate(DateTicksScaled ticks) { - return (ticks - _scaled_date_ticks_offset) / (DAY_TICKS * _settings_game.economy.day_length_factor); + return (ticks.base() - _scaled_date_ticks_offset.base()) / (DAY_TICKS * _settings_game.economy.day_length_factor); } static inline DateTicksScaled DateToScaledDateTicks(Date date) { - return ((int64)date * DAY_TICKS * _settings_game.economy.day_length_factor) + _scaled_date_ticks_offset; + return ((int64)date.base() * DAY_TICKS * _settings_game.economy.day_length_factor) + _scaled_date_ticks_offset.base(); } static inline DateTicks ScaledDateTicksToDateTicks(DateTicksScaled ticks) { - return (ticks - _scaled_date_ticks_offset) / _settings_game.economy.day_length_factor; + return (ticks.base() - _scaled_date_ticks_offset.base()) / _settings_game.economy.day_length_factor; } static inline DateTicksScaled DateTicksToScaledDateTicks(DateTicks date_ticks) { - return ((int64)date_ticks * _settings_game.economy.day_length_factor) + _scaled_date_ticks_offset; + return ((int64)date_ticks.base() * _settings_game.economy.day_length_factor) + _scaled_date_ticks_offset.base(); } /** @@ -77,21 +77,27 @@ static inline DateTicksScaled DateTicksToScaledDateTicks(DateTicks date_ticks) */ static constexpr Year DateToYear(Date date) { - return date / DAYS_IN_LEAP_YEAR; + 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) +static constexpr Year DateDeltaToYears(DateDelta date) +{ + return date.base() / DAYS_IN_LEAP_YEAR; +} + +static constexpr DateTicks DateToDateTicks(Date date, DateFract fract = 0) { - int32 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); + return (date.base() * DAY_TICKS) + fract; +} - /* 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; +static constexpr DateTicksDelta DateDeltaToDateTicksDelta(DateDelta date, DateFract fract = 0) +{ + return (date.base() * DAY_TICKS) + fract; +} + +static inline DateTicks NowDateTicks() +{ + return DateToDateTicks(_date, _date_fract); } #endif /* DATE_FUNC_H */ diff --git a/src/date_gui.cpp b/src/date_gui.cpp index 307a9d3917..1353cb1697 100644 --- a/src/date_gui.cpp +++ b/src/date_gui.cpp @@ -181,13 +181,13 @@ struct SetDateWindow : Window { struct SetMinutesWindow : SetDateWindow { - Minutes minutes; + TickMinutes minutes; /** Constructor. */ SetMinutesWindow(WindowDesc *desc, WindowNumber window_number, Window *parent, DateTicksScaled initial_date, Year min_year, Year max_year, SetDateCallback *callback, StringID button_text, StringID button_tooltip) : - SetDateWindow(desc, window_number, parent, initial_date, min_year, max_year, callback, button_text, button_tooltip), - minutes(initial_date / _settings_time.ticks_per_minute) + SetDateWindow(desc, window_number, parent, 0, min_year, max_year, callback, button_text, button_tooltip), + minutes(_settings_time.ToTickMinutes(initial_date)) { } @@ -208,7 +208,7 @@ struct SetMinutesWindow : SetDateWindow SetDParam(0, i); list.emplace_back(new DropDownListStringItem(STR_JUST_INT, i, false)); } - selected = MINUTES_MINUTE(minutes); + selected = this->minutes.ClockMinute(); break; case WID_SD_MONTH: @@ -216,7 +216,7 @@ struct SetMinutesWindow : SetDateWindow SetDParam(0, i); list.emplace_back(new DropDownListStringItem(STR_JUST_INT, i, false)); } - selected = MINUTES_HOUR(minutes); + selected = this->minutes.ClockHour(); break; } @@ -253,8 +253,8 @@ struct SetMinutesWindow : SetDateWindow virtual void SetStringParameters(int widget) const override { switch (widget) { - case WID_SD_DAY: SetDParam(0, MINUTES_MINUTE(minutes)); break; - case WID_SD_MONTH: SetDParam(0, MINUTES_HOUR(minutes)); break; + case WID_SD_DAY: SetDParam(0, this->minutes.ClockMinute()); break; + case WID_SD_MONTH: SetDParam(0, this->minutes.ClockHour()); break; } } @@ -269,7 +269,7 @@ struct SetMinutesWindow : SetDateWindow case WID_SD_SET_DATE: if (this->callback != nullptr) { - this->callback(this, ((DateTicks)minutes - _settings_time.clock_offset) * (DateTicksScaled)_settings_time.ticks_per_minute); + this->callback(this, _settings_time.FromTickMinutes(this->minutes)); } this->Close(); break; @@ -278,19 +278,23 @@ struct SetMinutesWindow : SetDateWindow virtual void OnDropdownSelect(int widget, int index) override { - Minutes current = 0; + const TickMinutes now = _settings_time.NowInTickMinutes(); + TickMinutes current = 0; switch (widget) { case WID_SD_DAY: - current = MINUTES_DATE(MINUTES_DAY(CURRENT_MINUTE), MINUTES_HOUR(minutes), index); + current = now.ToSameDayClockTime(now.ClockHour(), index); break; case WID_SD_MONTH: - current = MINUTES_DATE(MINUTES_DAY(CURRENT_MINUTE), index, MINUTES_MINUTE(minutes)); + current = now.ToSameDayClockTime(index, now.ClockMinute()); break; + + default: + return; } - if (current < (CURRENT_MINUTE - 60)) current += 60 * 24; - minutes = current; + if (current < (now - 60)) current += 60 * 24; + this->minutes = current; this->SetDirty(); } diff --git a/src/date_type.h b/src/date_type.h index 387a8aacb4..74266f046a 100644 --- a/src/date_type.h +++ b/src/date_type.h @@ -10,16 +10,8 @@ #ifndef DATE_TYPE_H #define DATE_TYPE_H -typedef int32 Date; ///< The type to store our dates in -typedef uint16 DateFract; ///< The fraction of a date we're in, i.e. the number of ticks since the last date changeover -typedef int32 Ticks; ///< The type to store ticks in -typedef int32 DateTicks; ///< The type to store dates in when tick-precision is required -typedef int64 DateTicksScaled; ///< The type to store dates scaled by the day length factor in when tick-precision is required -typedef int64 Minutes; ///< The type to store minutes in - -typedef int32 Year; ///< Type for the year, note: 0 based, i.e. starts at the year 0. -typedef uint8 Month; ///< Type for the month, note: 0 based, i.e. 0 = January, 11 = December. -typedef uint8 Day; ///< Type for the day of the month, note: 1 based, first day of a month is 1. +#include "core/strong_typedef_type.hpp" +#include "core/math_func.hpp" /** * 1 day is 74 ticks; _date_fract used to be uint16 and incremented by 885. On @@ -34,6 +26,104 @@ 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 +typedef uint16 DateFract; ///< The fraction of a date we're in, i.e. the number of ticks since the last date changeover +typedef int32 Ticks; ///< The type to store ticks in + +typedef int32 Year; ///< Type for the year, note: 0 based, i.e. starts at the year 0. +typedef uint8 Month; ///< Type for the month, note: 0 based, i.e. 0 = January, 11 = December. +typedef uint8 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; +using Date = StrongType::Typedef>; + +/* Mixin for DateTicks */ +struct DateTicksOperations { + template + struct mixin { + private: + TBaseType GetBase() const { return static_cast(*this).base(); } + + public: + Date ToDate() const { return this->GetBase() / DAY_TICKS; } + DateFract ToDateFractRemainder() const { return this->GetBase() % DAY_TICKS; } + }; +}; + +/* The type to store dates in when tick-precision is required */ +using DateTicksDelta = StrongType::Typedef; +using DateTicks = StrongType::Typedef, DateTicksOperations>; + +/* Mixin for DateTicksScaledDelta */ +struct DateTicksScaledDeltaOperations { + template + struct mixin { + private: + TBaseType GetBase() const { return static_cast(*this).base(); } + + public: + Ticks AsTicks() const { return (Ticks)this->GetBase(); } + }; +}; + +/* The type to store dates scaled by the day length factor in when tick-precision is required */ +using DateTicksScaledDelta = StrongType::Typedef; +using DateTicksScaled = StrongType::Typedef>; + +/* Mixin for TickMinutes, ClockFaceMinutes */ +struct MinuteOperations { + template + struct mixin { + private: + TBaseType GetBase() const { return static_cast(*this).base(); } + + public: + int ClockMinute() const { return this->GetBase() % 60; } + int ClockHour() const { return (this->GetBase() / 60) % 24; } + int ClockHHMM() const { return (this->ClockHour() * 100) + this->ClockMinute(); } + }; +}; + +/* Mixin for ClockFaceMinutes */ +struct ClockFaceMinuteOperations { + template + struct mixin { + static constexpr TType FromClockFace(int hours, int minutes) + { + return (TBaseType(hours) * 60) + minutes; + } + }; +}; + +/* The type to store general clock-face minutes in (i.e. 0..1440) */ +using ClockFaceMinutes = StrongType::Typedef; + +/* Mixin for TickMinutes */ +struct TickMinuteOperations { + template + struct mixin { + private: + TBaseType GetBase() const { return static_cast(*this).base(); } + + public: + TType ToSameDayClockTime(int hour, int minute) const + { + TBaseType day = DivTowardsNegativeInf(this->GetBase(), 1440); + return (day * 1440) + (hour * 60) + minute; + } + + ClockFaceMinutes ToClockFaceMinutes() const + { + TBaseType minutes = this->GetBase() % 1440; + if (minutes < 0) minutes += 1440; + return minutes; + } + }; +}; + +/* The type to store DateTicksScaled-based minutes in */ +using TickMinutes = StrongType::Typedef; + #define DATE_UNIT_SIZE (_settings_time.time_in_minutes ? _settings_time.ticks_per_minute : (DAY_TICKS * _settings_game.economy.day_length_factor)) static const int STATION_RATING_TICKS = 185; ///< cycle duration for updating station rating @@ -52,48 +142,41 @@ static const int INDUSTRY_CUT_TREE_TICKS = INDUSTRY_PRODUCE_TICKS * 2; ///< cyc */ /** The minimum starting year/base year of the original TTD */ -static const Year ORIGINAL_BASE_YEAR = 1920; +static constexpr Year ORIGINAL_BASE_YEAR = 1920; /** The original ending year */ -static const Year ORIGINAL_END_YEAR = 2051; +static constexpr Year ORIGINAL_END_YEAR = 2051; /** The maximum year of the original TTD */ -static const Year ORIGINAL_MAX_YEAR = 2090; - -/** - * Calculate the number of leap years till a given year. - * - * Each passed leap year adds one day to the 'day count'. - * - * A special case for the year 0 as no year has been passed, - * but '(year - 1) / 4' does not yield '-1' to counteract the - * '+1' at the end of the formula as divisions round to zero. - * - * @param year the year to get the leap years till. - * @return the number of leap years. - */ -#define LEAP_YEARS_TILL(year) ((year) == 0 ? 0 : ((year) - 1) / 4 - ((year) - 1) / 100 + ((year) - 1) / 400 + 1) +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. */ -#define DAYS_TILL(year) (DAYS_IN_YEAR * (year) + LEAP_YEARS_TILL(year)) +static constexpr Date DateAtStartOfYear(Year year) +{ + int32 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)' */ -#define DAYS_TILL_ORIGINAL_BASE_YEAR DAYS_TILL(ORIGINAL_BASE_YEAR) +static constexpr Date DAYS_TILL_ORIGINAL_BASE_YEAR = DateAtStartOfYear(ORIGINAL_BASE_YEAR); -static const Date MIN_DATE = 0; +static constexpr Date MIN_DATE = 0; /** The absolute minimum & maximum years in OTTD */ -static const Year MIN_YEAR = 0; +static constexpr Year MIN_YEAR = 0; /** The default starting year */ -static const Year DEF_START_YEAR = 1950; +static constexpr Year DEF_START_YEAR = 1950; /** The default scoring end year */ -static const Year DEF_END_YEAR = ORIGINAL_END_YEAR - 1; +static constexpr Year DEF_END_YEAR = ORIGINAL_END_YEAR - 1; /** * MAX_YEAR, nicely rounded value of the number of years that can @@ -102,22 +185,7 @@ static const Year DEF_END_YEAR = ORIGINAL_END_YEAR - 1; static const Year MAX_YEAR = 5000000; /** The number of days till the last day */ -#define MAX_DAY (DAYS_TILL(MAX_YEAR + 1) - 1) - -/** The day when converting to minutes */ -#define MINUTES_DAY(minutes) (minutes / 1440) - -/** The hour when converting to minutes */ -#define MINUTES_HOUR(minutes) ((minutes / 60) % 24) - -/** The day when converting to minutes */ -#define MINUTES_MINUTE(minutes) (minutes % 60) - -/** Convert minutes to a date */ -#define MINUTES_DATE(day, hour, minute) ((day * 1440) + (hour * 60) + minute) - -/** Get the current date in minutes */ -#define CURRENT_MINUTE (_scaled_date_ticks / _settings_time.ticks_per_minute) +static constexpr Date MAX_DATE = DateAtStartOfYear(MAX_YEAR + 1) - 1; /** * Data structure to convert between Date and triplet (year, month, and day). @@ -129,8 +197,9 @@ struct YearMonthDay { Day day; ///< Day (1..31) }; -static const Year INVALID_YEAR = -1; ///< Representation of an invalid year -static const Date INVALID_DATE = -1; ///< Representation of an invalid date -static const Ticks INVALID_TICKS = -1; ///< Representation of an invalid number of ticks +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 */ diff --git a/src/departures.cpp b/src/departures.cpp index 293bcc5a9a..d797de7eb0 100644 --- a/src/departures.cpp +++ b/src/departures.cpp @@ -43,15 +43,23 @@ typedef btree::btree_map> schdispatch_cache_t; /** A scheduled order. */ -typedef struct OrderDate -{ +struct OrderDate { const Order *order; ///< The order const Vehicle *v; ///< The vehicle carrying out the order - DateTicks expected_date;///< The date on which the order is expected to complete + Ticks expected_tick; ///< The tick on which the order is expected to complete Ticks lateness; ///< How late this order is expected to finish DepartureStatus status; ///< Whether the vehicle has arrived to carry out the order yet - uint scheduled_waiting_time; ///< Scheduled waiting time if scheduled dispatch is used -} OrderDate; + Ticks scheduled_waiting_time; ///< Scheduled waiting time if scheduled dispatch is used + + inline Ticks EffectiveWaitingTime() const + { + if (this->scheduled_waiting_time > 0) { + return this->scheduled_waiting_time; + } else { + return this->order->GetWaitTime(); + } + } +}; static bool IsDeparture(const Order *order, StationID station) { return (order->GetType() == OT_GOTO_STATION && @@ -93,7 +101,7 @@ static uint8 GetDepartureConditionalOrderMode(const Order *order, const Vehicle return _settings_client.gui.departure_conditionals; } -static bool VehicleSetNextDepartureTime(DateTicks *previous_departure, uint *waiting_time, const DateTicksScaled date_only_scaled, const Vehicle *v, const Order *order, bool arrived_at_timing_point, schdispatch_cache_t &dept_schedule_last) +static bool VehicleSetNextDepartureTime(Ticks *previous_departure, Ticks *waiting_time, const DateTicksScaled date_ticks_base, const Vehicle *v, const Order *order, bool arrived_at_timing_point, schdispatch_cache_t &dept_schedule_last) { if (HasBit(v->vehicle_flags, VF_SCHEDULED_DISPATCH)) { auto is_current_implicit_order = [&v](const Order *o) -> bool { @@ -115,7 +123,7 @@ static bool VehicleSetNextDepartureTime(DateTicks *previous_departure, uint *wai DateTicksScaled earliest_departure = begin_time + ds.GetScheduledDispatchLastDispatch(); /* Earliest possible departure according to vehicle current timetable */ - const uint32 ready_to_depart_time = date_only_scaled + *previous_departure + order->GetTravelTime() + order->GetTimetabledWait(); + const DateTicksScaled ready_to_depart_time = date_ticks_base + *previous_departure + order->GetTravelTime() + order->GetTimetabledWait(); if (earliest_departure + max_delay < ready_to_depart_time) { earliest_departure = ready_to_depart_time - max_delay - 1; /* -1 because this number is actually a moment before actual departure */ @@ -141,8 +149,8 @@ static bool VehicleSetNextDepartureTime(DateTicks *previous_departure, uint *wai } } - *waiting_time = actual_departure - date_only_scaled - *previous_departure - order->GetTravelTime(); - *previous_departure = actual_departure - date_only_scaled; + *waiting_time = (actual_departure - date_ticks_base).AsTicks() - *previous_departure - order->GetTravelTime(); + *previous_departure = (actual_departure - date_ticks_base).AsTicks(); slot_cache.insert(actual_departure); /* Return true means that vehicle lateness should be clear from this point onward */ @@ -185,18 +193,18 @@ static void ScheduledDispatchDepartureLocalFix(DepartureList *departure_list) /* Sort the departure list by arrival time */ std::sort(d_list.begin(), d_list.end(), [](const Departure * const &a, const Departure * const &b) -> bool { - DateTicksScaled arr_a = a->scheduled_date - (a->scheduled_waiting_time > 0 ? a->scheduled_waiting_time : a->order->GetWaitTime()); - DateTicksScaled arr_b = b->scheduled_date - (b->scheduled_waiting_time > 0 ? b->scheduled_waiting_time : b->order->GetWaitTime()); + DateTicksScaled arr_a = a->scheduled_date - a->EffectiveWaitingTime(); + DateTicksScaled arr_b = b->scheduled_date - b->EffectiveWaitingTime(); return arr_a < arr_b; }); /* Re-assign them sequentially */ for (size_t i = 0; i < d_list.size(); i++) { - const DateTicksScaled arrival = d_list[i]->scheduled_date - (d_list[i]->scheduled_waiting_time > 0 ? d_list[i]->scheduled_waiting_time : d_list[i]->order->GetWaitTime()); - d_list[i]->scheduled_waiting_time = departure_time_list[i] - arrival; + const DateTicksScaled arrival = d_list[i]->scheduled_date - d_list[i]->EffectiveWaitingTime(); + d_list[i]->scheduled_waiting_time = (departure_time_list[i] - arrival).AsTicks(); d_list[i]->scheduled_date = departure_time_list[i]; - if (d_list[i]->scheduled_waiting_time == d_list[i]->order->GetWaitTime()) { + if (d_list[i]->scheduled_waiting_time == (Ticks)d_list[i]->order->GetWaitTime()) { d_list[i]->scheduled_waiting_time = 0; } } @@ -237,12 +245,11 @@ DepartureList* MakeDepartureList(StationID station, const std::vector next_orders; /* The maximum possible date for departures to be scheduled to occur. */ - DateTicksScaled max_date = GetDeparturesMaxTicksAhead(); + const Ticks max_ticks = GetDeparturesMaxTicksAhead(); - DateTicksScaled date_only_scaled = DateToScaledDateTicks(_date); - DateTicksScaled date_fract_scaled = ((DateTicksScaled)_date_fract * _settings_game.economy.day_length_factor) + _tick_skip_counter; + const DateTicksScaled date_ticks_base = _scaled_date_ticks; - /* The scheduled order in next_orders with the earliest expected_date field. */ + /* The scheduled order in next_orders with the earliest expected_tick field. */ OrderDate *least_order = nullptr; /* Cache for scheduled departure time */ @@ -272,20 +279,20 @@ DepartureList* MakeDepartureList(StationID station, const std::vectorGetOrder(v->cur_implicit_order_index % v->GetNumOrders()); if (order == nullptr) continue; - DateTicks start_date = date_fract_scaled - v->current_order_time; + Ticks start_ticks = -((Ticks)v->current_order_time); if (v->cur_timetable_order_index != INVALID_VEH_ORDER_ID && v->cur_timetable_order_index != v->cur_real_order_index) { /* vehicle is taking a conditional order branch, adjust start time to compensate */ const Order *real_current_order = v->GetOrder(v->cur_real_order_index); const Order *real_timetable_order = v->GetOrder(v->cur_timetable_order_index); if (real_timetable_order->IsType(OT_CONDITIONAL)) { - start_date += (real_timetable_order->GetWaitTime() - real_current_order->GetTravelTime()); + start_ticks += (real_timetable_order->GetWaitTime() - real_current_order->GetTravelTime()); } else { /* This can also occur with implicit orders, when there are no real orders, do nothing */ } } DepartureStatus status = D_TRAVELLING; bool should_reset_lateness = false; - uint waiting_time = 0; + Ticks waiting_time = 0; /* If the vehicle is stopped in a depot, ignore it. */ if (v->IsStoppedInDepot()) { @@ -301,20 +308,20 @@ DepartureList* MakeDepartureList(StationID station, const std::vectorcurrent_order.IsAnyLoadingType() || v->current_order.IsType(OT_WAITING)) { /* Account for the vehicle having reached the current order and being in the loading phase. */ status = D_ARRIVED; - start_date -= order->GetTravelTime() + ((v->lateness_counter < 0) ? v->lateness_counter : 0); + start_ticks -= order->GetTravelTime() + ((v->lateness_counter < 0) ? v->lateness_counter : 0); require_travel_time = false; } /* Loop through the vehicle's orders until we've found a suitable order or we've determined that no such order exists. */ /* We only need to consider each order at most once. */ for (int i = v->GetNumOrders(); i > 0; --i) { - if (VehicleSetNextDepartureTime(&start_date, &waiting_time, date_only_scaled, v, order, status == D_ARRIVED, schdispatch_last_planned_dispatch)) { + if (VehicleSetNextDepartureTime(&start_ticks, &waiting_time, date_ticks_base, v, order, status == D_ARRIVED, schdispatch_last_planned_dispatch)) { should_reset_lateness = true; } /* If the order is a conditional branch, handle it. */ if (order->IsType(OT_CONDITIONAL)) { - switch(GetDepartureConditionalOrderMode(order, v, start_date + date_only_scaled)) { + switch(GetDepartureConditionalOrderMode(order, v, date_ticks_base + start_ticks)) { case 0: { /* Give up */ break; @@ -329,7 +336,7 @@ DepartureList* MakeDepartureList(StationID station, const std::vectorGetTravelTime(); + start_ticks -= order->GetTravelTime(); require_travel_time = false; continue; } @@ -338,7 +345,7 @@ DepartureList* MakeDepartureList(StationID station, const std::vectorGetWaitTime(); /* Added previously in VehicleSetNextDepartureTime */ + start_ticks -= order->GetWaitTime(); /* Added previously in VehicleSetNextDepartureTime */ order = (order->next == nullptr) ? v->GetFirstOrder() : order->next; require_travel_time = true; continue; @@ -348,7 +355,7 @@ DepartureList* MakeDepartureList(StationID station, const std::vectorlateness_counter > max_date) { + if (start_ticks - v->lateness_counter > max_ticks) { break; } @@ -363,7 +370,7 @@ DepartureList* MakeDepartureList(StationID station, const std::vectororder = order; od->v = v; /* We store the expected date for now, so that vehicles will be shown in order of expected time. */ - od->expected_date = start_date; + od->expected_tick = start_ticks; od->lateness = v->lateness_counter > 0 ? v->lateness_counter : 0; od->status = status; od->scheduled_waiting_time = waiting_time; @@ -383,15 +390,20 @@ DepartureList* MakeDepartureList(StationID station, const std::vectorlateness_counter < 0 && !(v->current_order.IsAnyLoadingType() || v->current_order.IsType(OT_WAITING))) { - od->expected_date -= v->lateness_counter; + od->expected_tick -= v->lateness_counter; } /* Update least_order if this is the current least order. */ if (least_order == nullptr) { least_order = od; - } else if (int(least_order->expected_date - least_order->lateness - (type == D_ARRIVAL ? (least_order->scheduled_waiting_time > 0 ? least_order->scheduled_waiting_time : least_order->order->GetWaitTime()) : 0)) > int(od->expected_date - od->lateness - (type == D_ARRIVAL ? (od->scheduled_waiting_time > 0 ? od->scheduled_waiting_time : od->order->GetWaitTime()) : 0))) { - /* Somehow my compiler perform an unsigned comparition above so integer cast is required */ - least_order = od; + } else if (type == D_ARRIVAL) { + if ((least_order->expected_tick - least_order->lateness - least_order->EffectiveWaitingTime()) > (od->expected_tick - od->lateness - od->EffectiveWaitingTime())) { + least_order = od; + } + } else { + if ((least_order->expected_tick - least_order->lateness) > (od->expected_tick - od->lateness)) { + least_order = od; + } } next_orders.push_back(od); @@ -420,22 +432,22 @@ DepartureList* MakeDepartureList(StationID station, const std::vector 0; --i) { /* I should probably try to convince you that this loop always terminates regardless of the safeguard. */ /* 1. next_orders contains at least one element. */ - /* 2. The loop terminates if result->size() exceeds a fixed (for this loop) value, or if the least order's scheduled date is later than max_date. */ + /* 2. The loop terminates if result->size() exceeds a fixed (for this loop) value, or if the least order's scheduled date is later than max_ticks. */ /* (We ignore the case that the least order's scheduled date has overflown, as it is a relative rather than absolute date.) */ - /* 3. Every time we loop round, either result->size() will have increased -OR- we will have increased the expected_date of one of the elements of next_orders. */ + /* 3. Every time we loop round, either result->size() will have increased -OR- we will have increased the expected_tick of one of the elements of next_orders. */ /* 4. Therefore the loop must eventually terminate. */ /* least_order is the best candidate for the next departure. */ /* First, we check if we can stop looking for departures yet. */ if (result->size() >= _settings_client.gui.max_departures || - least_order->expected_date - least_order->lateness > max_date) { + least_order->expected_tick - least_order->lateness > max_ticks) { break; } /* We already know the least order and that it's a suitable departure, so make it into a departure. */ Departure *d = new Departure(); - d->scheduled_date = date_only_scaled + least_order->expected_date - least_order->lateness; + d->scheduled_date = date_ticks_base + least_order->expected_tick - least_order->lateness; d->lateness = least_order->lateness; d->status = least_order->status; d->vehicle = least_order->v; @@ -751,7 +763,7 @@ DepartureList* MakeDepartureList(StationID station, const std::vectornext == nullptr) ? least_order->v->GetFirstOrder() : order->next; - if (VehicleSetNextDepartureTime(&least_order->expected_date, &least_order->scheduled_waiting_time, date_only_scaled, least_order->v, order, false, schdispatch_last_planned_dispatch)) { + if (VehicleSetNextDepartureTime(&least_order->expected_tick, &least_order->scheduled_waiting_time, date_ticks_base, least_order->v, order, false, schdispatch_last_planned_dispatch)) { least_order->lateness = 0; } @@ -762,7 +774,7 @@ DepartureList* MakeDepartureList(StationID station, const std::vectorv->GetNumOrders(); i > 0; --i) { /* If the order is a conditional branch, handle it. */ if (order->IsType(OT_CONDITIONAL)) { - switch(GetDepartureConditionalOrderMode(order, least_order->v, least_order->expected_date)) { + switch(GetDepartureConditionalOrderMode(order, least_order->v, least_order->expected_tick)) { case 0: { /* Give up */ break; @@ -774,8 +786,8 @@ DepartureList* MakeDepartureList(StationID station, const std::vectorexpected_date -= order->GetTravelTime(); /* Added in next VehicleSetNextDepartureTime */ - if (VehicleSetNextDepartureTime(&least_order->expected_date, &least_order->scheduled_waiting_time, date_only_scaled, least_order->v, order, false, schdispatch_last_planned_dispatch)) { + least_order->expected_tick -= order->GetTravelTime(); /* Added in next VehicleSetNextDepartureTime */ + if (VehicleSetNextDepartureTime(&least_order->expected_tick, &least_order->scheduled_waiting_time, date_ticks_base, least_order->v, order, false, schdispatch_last_planned_dispatch)) { least_order->lateness = 0; } require_travel_time = false; @@ -783,9 +795,9 @@ DepartureList* MakeDepartureList(StationID station, const std::vectorexpected_date -= order->GetWaitTime(); /* Added previously in VehicleSetNextDepartureTime */ + least_order->expected_tick -= order->GetWaitTime(); /* Added previously in VehicleSetNextDepartureTime */ order = (order->next == nullptr) ? least_order->v->GetFirstOrder() : order->next; - if (VehicleSetNextDepartureTime(&least_order->expected_date, &least_order->scheduled_waiting_time, date_only_scaled, least_order->v, order, false, schdispatch_last_planned_dispatch)) { + if (VehicleSetNextDepartureTime(&least_order->expected_tick, &least_order->scheduled_waiting_time, date_ticks_base, least_order->v, order, false, schdispatch_last_planned_dispatch)) { least_order->lateness = 0; } require_travel_time = true; @@ -801,7 +813,7 @@ DepartureList* MakeDepartureList(StationID station, const std::vectorexpected_date - least_order->lateness > max_date) { + if (least_order->expected_tick - least_order->lateness > max_ticks) { break; } @@ -815,7 +827,7 @@ DepartureList* MakeDepartureList(StationID station, const std::vectornext == nullptr) ? least_order->v->GetFirstOrder() : order->next; - if (VehicleSetNextDepartureTime(&least_order->expected_date, &least_order->scheduled_waiting_time, date_only_scaled, least_order->v, order, false, schdispatch_last_planned_dispatch)) { + if (VehicleSetNextDepartureTime(&least_order->expected_tick, &least_order->scheduled_waiting_time, date_ticks_base, least_order->v, order, false, schdispatch_last_planned_dispatch)) { least_order->lateness = 0; } require_travel_time = true; @@ -826,7 +838,7 @@ DepartureList* MakeDepartureList(StationID station, const std::vectorexpected_date = INT32_MAX; + least_order->expected_tick = INT32_MAX; } /* The vehicle can't possibly have arrived at its next candidate departure yet. */ @@ -838,15 +850,15 @@ DepartureList* MakeDepartureList(StationID station, const std::vectorexpected_date - least_order->lateness; - DateTicks odd = od->expected_date - od->lateness; + DateTicks lod = least_order->expected_tick - least_order->lateness; + DateTicks odd = od->expected_tick - od->lateness; if (type == D_ARRIVAL) { lod -= least_order->scheduled_waiting_time > 0 ? least_order->scheduled_waiting_time : least_order->order->GetWaitTime(); odd -= od->scheduled_waiting_time > 0 ? od->scheduled_waiting_time : od->order->GetWaitTime(); } - if (lod > odd && od->expected_date - od->lateness < max_date) { + if (lod > odd && od->expected_tick - od->lateness < max_ticks) { least_order = od; } } @@ -864,7 +876,7 @@ DepartureList* MakeDepartureList(StationID station, const std::vector &vehicles, DepartureType type = D_DEPARTURE, bool show_vehicles_via = false, bool show_pax = true, bool show_freight = true); -DateTicksScaled GetDeparturesMaxTicksAhead(); +Ticks GetDeparturesMaxTicksAhead(); #endif /* DEPARTURES_FUNC_H */ diff --git a/src/departures_type.h b/src/departures_type.h index 82e7d33941..85e8b147e5 100644 --- a/src/departures_type.h +++ b/src/departures_type.h @@ -32,10 +32,10 @@ typedef enum { struct CallAt { StationID station; - DateTicks scheduled_date; + DateTicksScaled scheduled_date; CallAt(const StationID& s) : station(s), scheduled_date(0) { } - CallAt(const StationID& s, const DateTicks& t) : station(s), scheduled_date(t) { } + CallAt(const StationID& s, DateTicksScaled t) : station(s), scheduled_date(t) { } CallAt(const CallAt& c) : station(c.station), scheduled_date(c.scheduled_date) { } inline bool operator==(const CallAt& c) const { @@ -82,7 +82,7 @@ struct Departure { DepartureType type; ///< The type of the departure (departure or arrival) const Vehicle *vehicle; ///< The vehicle performing this departure const Order *order; ///< The order corresponding to this departure - uint scheduled_waiting_time; ///< Scheduled waiting time if scheduled dispatch is used + Ticks scheduled_waiting_time; ///< Scheduled waiting time if scheduled dispatch is used Departure() : terminus(INVALID_STATION), via(INVALID_STATION), via2(INVALID_STATION), vehicle(nullptr), order(nullptr) { } inline bool operator==(const Departure& d) const { @@ -93,13 +93,22 @@ struct Departure { } return - (this->scheduled_date / DATE_UNIT_SIZE) == (d.scheduled_date / DATE_UNIT_SIZE) && + (this->scheduled_date.base() / DATE_UNIT_SIZE) == (d.scheduled_date.base() / DATE_UNIT_SIZE) && this->vehicle->type == d.vehicle->type && this->via == d.via && this->via2 == d.via2 && this->type == d.type ; } + + inline Ticks EffectiveWaitingTime() const + { + if (this->scheduled_waiting_time > 0) { + return this->scheduled_waiting_time; + } else { + return this->order->GetWaitTime(); + } + } }; typedef std::vector DepartureList; diff --git a/src/depot_gui.cpp b/src/depot_gui.cpp index fdc90f5794..1ea9550aff 100644 --- a/src/depot_gui.cpp +++ b/src/depot_gui.cpp @@ -361,7 +361,7 @@ struct DepotWindow : Window { DrawSpriteIgnorePadding((v->vehstatus & VS_STOPPED) ? SPR_FLAG_VEH_STOPPED : SPR_FLAG_VEH_RUNNING, PAL_NONE, flag, false, SA_CENTER); SetDParam(0, v->unitnumber); - DrawString(text, STR_JUST_COMMA, (uint16)(v->max_age - DAYS_IN_LEAP_YEAR) >= v->age ? TC_BLACK : TC_RED); + DrawString(text, STR_JUST_COMMA, (v->max_age - DAYS_IN_LEAP_YEAR) >= v->age ? TC_BLACK : TC_RED); } } diff --git a/src/economy.cpp b/src/economy.cpp index a57de5964e..67e96c25ed 100644 --- a/src/economy.cpp +++ b/src/economy.cpp @@ -2459,7 +2459,7 @@ static void DoAcquireCompany(Company *c, bool hostile_takeover) { CompanyID ci = c->index; - DEBUG(desync, 1, "buy_company: date{%08x; %02x; %02x}, buyer: %u, bought: %u", _date, _date_fract, _tick_skip_counter, (uint) _current_company, (uint) ci); + DEBUG(desync, 1, "buy_company: date{%08x; %02x; %02x}, buyer: %u, bought: %u", _date.base(), _date_fract, _tick_skip_counter, (uint) _current_company, (uint) ci); CompanyNewsInformation *cni = new CompanyNewsInformation(c, Company::Get(_current_company)); diff --git a/src/engine.cpp b/src/engine.cpp index 5e81ae93b0..5ec8e7a385 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -484,7 +484,7 @@ uint Engine::GetDisplayMaxTractiveEffort() const * Returns the vehicle's (not model's!) life length in days. * @return the life length */ -Date 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. */ return static_cast(this->info.lifelength + _settings_game.vehicle.extend_vehicle_life) * DAYS_IN_LEAP_YEAR; @@ -752,7 +752,7 @@ void StartupOneEngine(Engine *e, Date aging_date, uint32 seed, Date no_introduce SavedRandomSeeds saved_seeds; SaveRandomSeeds(&saved_seeds); SetRandomSeed(_settings_game.game_creation.generation_seed ^ seed ^ - ei->base_intro ^ + ei->base_intro.base() ^ e->type ^ e->GetGRFID()); uint32 r = Random(); @@ -760,9 +760,9 @@ void StartupOneEngine(Engine *e, Date aging_date, uint32 seed, Date no_introduce /* Don't randomise the start-date in the first two years after gamestart to ensure availability * of engines in early starting games. * Note: TTDP uses fixed 1922 */ - e->intro_date = ei->base_intro <= ConvertYMDToDate(_settings_game.game_creation.starting_year + 2, 0, 1) ? ei->base_intro : (Date)GB(r, 0, 9) + ei->base_intro; + 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; if (e->intro_date <= _date && e->intro_date <= no_introduce_after_date) { - e->age = (aging_date - e->intro_date) >> 5; + e->age = (aging_date - e->intro_date).base() >> 5; e->company_avail = MAX_UVALUE(CompanyMask); e->flags |= ENGINE_AVAILABLE; } @@ -774,7 +774,7 @@ void StartupOneEngine(Engine *e, Date aging_date, uint32 seed, Date no_introduce } SetRandomSeed(_settings_game.game_creation.generation_seed ^ seed ^ - (re->index << 16) ^ (re->info.base_intro << 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 ^ e->type ^ e->GetGRFID()); diff --git a/src/engine_base.h b/src/engine_base.h index c199aacbce..87ff6732a9 100644 --- a/src/engine_base.h +++ b/src/engine_base.h @@ -140,7 +140,7 @@ struct Engine : EnginePool::PoolItem<&_engine_pool> { uint GetPower() const; uint GetDisplayWeight() const; uint GetDisplayMaxTractiveEffort() const; - Date GetLifeLengthInDays() const; + DateDelta GetLifeLengthInDays() const; uint16 GetRange() const; StringID GetAircraftTypeText() const; diff --git a/src/genworld.cpp b/src/genworld.cpp index bed2609371..1799dfc085 100644 --- a/src/genworld.cpp +++ b/src/genworld.cpp @@ -204,7 +204,7 @@ static void _GenerateWorld() if (_debug_desync_level > 0) { char name[MAX_PATH]; - seprintf(name, lastof(name), "dmp_cmds_%08x_%08x.sav", _settings_game.game_creation.generation_seed, _date); + seprintf(name, lastof(name), "dmp_cmds_%08x_%08x.sav", _settings_game.game_creation.generation_seed, _date.base()); SaveOrLoad(name, SLO_SAVE, DFT_GAME_FILE, AUTOSAVE_DIR, false, SMF_ZSTD_OK); } } catch (AbortGenerateWorldSignal&) { diff --git a/src/linkgraph/flowmapper.cpp b/src/linkgraph/flowmapper.cpp index 8176abbb43..08af858620 100644 --- a/src/linkgraph/flowmapper.cpp +++ b/src/linkgraph/flowmapper.cpp @@ -53,7 +53,7 @@ void FlowMapper::Run(LinkGraphJob &job) const /* Scale by time the graph has been running without being compressed. Add 1 to avoid * division by 0 if spawn date == last compression date. This matches * LinkGraph::Monthly(). */ - uint runtime = (uint)Clamp(DateTicksToScaledDateTicks(job.StartDateTicks()) - job.LastCompression() + 1, 1, UINT32_MAX); + uint runtime = (uint)Clamp(DateTicksToScaledDateTicks(job.StartDateTicks()) - job.LastCompression() + 1, 1, UINT32_MAX).base(); for (auto &it : flows) { it.ScaleToMonthly(runtime); } diff --git a/src/linkgraph/linkgraph.cpp b/src/linkgraph/linkgraph.cpp index be119fff20..b350122859 100644 --- a/src/linkgraph/linkgraph.cpp +++ b/src/linkgraph/linkgraph.cpp @@ -38,7 +38,7 @@ inline void LinkGraph::BaseNode::Init(TileIndex xy, StationID st, uint demand) * This is useful if the date has been modified with the cheat menu. * @param interval Number of days to be added or subtracted. */ -void LinkGraph::ShiftDates(int interval) +void LinkGraph::ShiftDates(DateDelta interval) { for (NodeID node1 = 0; node1 < this->Size(); ++node1) { BaseNode &source = this->nodes[node1]; @@ -54,7 +54,7 @@ void LinkGraph::ShiftDates(int interval) void LinkGraph::Compress() { - this->last_compression = (_scaled_date_ticks + this->last_compression) / 2; + this->last_compression = (_scaled_date_ticks.base() + this->last_compression.base()) / 2; for (NodeID node1 = 0; node1 < this->Size(); ++node1) { this->nodes[node1].supply /= 2; } @@ -79,8 +79,8 @@ void LinkGraph::Compress() */ void LinkGraph::Merge(LinkGraph *other) { - uint32 age = ClampTo(CeilDivT(_scaled_date_ticks - this->last_compression + 1, DAY_TICKS)); - uint32 other_age = ClampTo(CeilDivT(_scaled_date_ticks - other->last_compression + 1, DAY_TICKS)); + uint32 age = ClampTo(CeilDivT(_scaled_date_ticks.base() - this->last_compression.base() + 1, DAY_TICKS)); + uint32 other_age = ClampTo(CeilDivT(_scaled_date_ticks.base() - other->last_compression.base() + 1, DAY_TICKS)); NodeID first = this->Size(); this->nodes.reserve(first + other->Size()); for (NodeID node1 = 0; node1 < other->Size(); ++node1) { @@ -266,7 +266,7 @@ void LinkGraph::Init(uint size) this->nodes.resize(size); } -void AdjustLinkGraphScaledTickBase(int64 delta) +void AdjustLinkGraphScaledTickBase(DateTicksScaledDelta delta) { for (LinkGraph *lg : LinkGraph::Iterate()) lg->last_compression += delta; @@ -279,10 +279,10 @@ void AdjustLinkGraphScaledTickBase(int64 delta) void LinkGraphFixupLastCompressionAfterLoad() { /* last_compression was previously a Date, change it to a DateTicksScaled */ - for (LinkGraph *lg : LinkGraph::Iterate()) lg->last_compression = DateToScaledDateTicks((Date)lg->last_compression); + for (LinkGraph *lg : LinkGraph::Iterate()) lg->last_compression = DateToScaledDateTicks((Date)lg->last_compression.base()); for (LinkGraphJob *lgj : LinkGraphJob::Iterate()) { LinkGraph *lg = &(const_cast(lgj->Graph())); - lg->last_compression = DateToScaledDateTicks((Date)lg->last_compression); + lg->last_compression = DateToScaledDateTicks((Date)lg->last_compression.base()); } } diff --git a/src/linkgraph/linkgraph.h b/src/linkgraph/linkgraph.h index 989758565c..4715462741 100644 --- a/src/linkgraph/linkgraph.h +++ b/src/linkgraph/linkgraph.h @@ -287,10 +287,10 @@ public: static const uint MIN_TIMEOUT_DISTANCE = 32; /** Number of days before deleting links served only by vehicles stopped in depot. */ - static const uint STALE_LINK_DEPOT_TIMEOUT = 1024; + static constexpr DateDelta STALE_LINK_DEPOT_TIMEOUT = 1024; - /** Minimum number of days between subsequent compressions of a LG. */ - static const uint COMPRESSION_INTERVAL = 256 * DAY_TICKS; + /** Minimum number of ticks between subsequent compressions of a LG. */ + static constexpr DateTicksScaledDelta COMPRESSION_INTERVAL = 256 * DAY_TICKS; /** * Scale a value from a link graph of age orig_age for usage in one of age @@ -314,7 +314,7 @@ public: LinkGraph(CargoID cargo) : cargo(cargo), last_compression(_scaled_date_ticks) {} void Init(uint size); - void ShiftDates(int interval); + void ShiftDates(DateDelta interval); void Compress(); void Merge(LinkGraph *other); @@ -365,7 +365,7 @@ public: */ inline uint Monthly(uint base) const { - return (static_cast(base) * 30 * DAY_TICKS * _settings_game.economy.day_length_factor) / std::max(_scaled_date_ticks - this->last_compression, DAY_TICKS); + return (static_cast(base) * 30 * DAY_TICKS * _settings_game.economy.day_length_factor) / std::max((_scaled_date_ticks - this->last_compression).base(), DAY_TICKS); } NodeID AddNode(const Station *st); @@ -392,7 +392,7 @@ protected: friend upstream_sl::SlLinkgraphNode; friend upstream_sl::SlLinkgraphEdge; - friend void AdjustLinkGraphScaledTickBase(int64 delta); + friend void AdjustLinkGraphScaledTickBase(DateTicksScaledDelta delta); friend void LinkGraphFixupLastCompressionAfterLoad(); CargoID cargo; ///< Cargo of this component's link graph. diff --git a/src/linkgraph/linkgraphjob.cpp b/src/linkgraph/linkgraphjob.cpp index 2233b9124f..3a33d85db9 100644 --- a/src/linkgraph/linkgraphjob.cpp +++ b/src/linkgraph/linkgraphjob.cpp @@ -28,8 +28,8 @@ INSTANTIATE_POOL_METHODS(LinkGraphJob) static DateTicks GetLinkGraphJobJoinDateTicks(uint duration_multiplier) { - DateTicks ticks = (_settings_game.linkgraph.recalc_time * DAY_TICKS * duration_multiplier) / (SECONDS_PER_DAY * _settings_game.economy.day_length_factor); - return ticks + (_date * DAY_TICKS) + _date_fract; + DateTicksDelta ticks = (_settings_game.linkgraph.recalc_time * DAY_TICKS * duration_multiplier) / (SECONDS_PER_DAY * _settings_game.economy.day_length_factor); + return ticks + NowDateTicks(); } /** @@ -44,7 +44,7 @@ LinkGraphJob::LinkGraphJob(const LinkGraph &orig, uint duration_multiplier) : link_graph(orig), settings(_settings_game.linkgraph), join_date_ticks(GetLinkGraphJobJoinDateTicks(duration_multiplier)), - start_date_ticks((_date * DAY_TICKS) + _date_fract), + start_date_ticks(NowDateTicks()), job_completed(false), job_aborted(false) { diff --git a/src/linkgraph/linkgraphjob.h b/src/linkgraph/linkgraphjob.h index 5f8d84a9b1..9db6eb6c33 100644 --- a/src/linkgraph/linkgraphjob.h +++ b/src/linkgraph/linkgraphjob.h @@ -262,7 +262,7 @@ public: * settings have to be brutally const-casted in order to populate them. */ LinkGraphJob() : settings(_settings_game.linkgraph), - join_date_ticks(INVALID_DATE), start_date_ticks(INVALID_DATE), job_completed(false), job_aborted(false) {} + join_date_ticks(INVALID_DATE_TICKS), start_date_ticks(INVALID_DATE_TICKS), job_completed(false), job_aborted(false) {} LinkGraphJob(const LinkGraph &orig, uint duration_multiplier); ~LinkGraphJob(); @@ -297,7 +297,7 @@ public: * @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. */ - inline bool IsScheduledToBeJoined(int tick_offset = 0) const { return this->join_date_ticks <= (_date * DAY_TICKS) + _date_fract + tick_offset; } + inline bool IsScheduledToBeJoined(int tick_offset = 0) const { return this->join_date_ticks <= NowDateTicks() + tick_offset; } /** * Get the date when the job should be finished. @@ -315,10 +315,10 @@ public: * Change the start and join dates on date cheating. * @param interval Number of days to add. */ - inline void ShiftJoinDate(int interval) + inline void ShiftJoinDate(DateDelta interval) { - this->join_date_ticks += interval * DAY_TICKS; - this->start_date_ticks += interval * DAY_TICKS; + this->join_date_ticks += DateDeltaToDateTicksDelta(interval); + this->start_date_ticks += DateDeltaToDateTicksDelta(interval); } /** diff --git a/src/linkgraph/linkgraphschedule.cpp b/src/linkgraph/linkgraphschedule.cpp index ea02398e4e..78e527044d 100644 --- a/src/linkgraph/linkgraphschedule.cpp +++ b/src/linkgraph/linkgraphschedule.cpp @@ -200,7 +200,7 @@ void LinkGraphSchedule::SpawnAll() * graph jobs by the number of days given. * @param interval Number of days to be added or subtracted. */ -void LinkGraphSchedule::ShiftDates(int interval) +void LinkGraphSchedule::ShiftDates(DateDelta interval) { for (LinkGraph *lg : LinkGraph::Iterate()) lg->ShiftDates(interval); for (LinkGraphJob *lgj : LinkGraphJob::Iterate()) lgj->ShiftJoinDate(interval); @@ -285,7 +285,7 @@ void LinkGraphJobGroup::JoinThread() auto flush_bucket = [&]() { if (!bucket_cost) return; DEBUG(linkgraph, 2, "LinkGraphJobGroup::ExecuteJobSet: Creating Job Group: jobs: " PRINTF_SIZE ", cost: %u, join after: %d", - bucket.size(), bucket_cost, bucket_join_date - ((_date * DAY_TICKS) + _date_fract)); + bucket.size(), bucket_cost, (bucket_join_date - NowDateTicks()).base()); auto group = std::make_shared(constructor_token(), std::move(bucket)); group->SpawnThread(); bucket_cost = 0; @@ -321,9 +321,9 @@ void StateGameLoop_LinkGraphPauseControl() } else if (_pause_mode == PM_UNPAUSED && _tick_skip_counter == 0) { if (_settings_game.economy.day_length_factor == 1) { if (_date_fract != LinkGraphSchedule::SPAWN_JOIN_TICK - 2) return; - if (_date % _settings_game.linkgraph.recalc_interval != (_settings_game.linkgraph.recalc_interval / SECONDS_PER_DAY) / 2) return; + if (_date.base() % _settings_game.linkgraph.recalc_interval != (_settings_game.linkgraph.recalc_interval / SECONDS_PER_DAY) / 2) return; } else { - int date_ticks = ((_date * DAY_TICKS) + _date_fract - (LinkGraphSchedule::SPAWN_JOIN_TICK - 2)); + int date_ticks = (NowDateTicks() - (LinkGraphSchedule::SPAWN_JOIN_TICK - 2)).base(); int interval = std::max(2, (_settings_game.linkgraph.recalc_interval * DAY_TICKS / (SECONDS_PER_DAY * _settings_game.economy.day_length_factor))); if (date_ticks % interval != interval / 2) return; } @@ -358,10 +358,10 @@ void OnTick_LinkGraph() if (_settings_game.economy.day_length_factor == 1) { if (_date_fract != LinkGraphSchedule::SPAWN_JOIN_TICK) return; interval = _settings_game.linkgraph.recalc_interval / SECONDS_PER_DAY; - offset = _date % interval; + offset = _date.base() % interval; } else { interval = std::max(2, (_settings_game.linkgraph.recalc_interval * DAY_TICKS / (SECONDS_PER_DAY * _settings_game.economy.day_length_factor))); - offset = ((_date * DAY_TICKS) + _date_fract - LinkGraphSchedule::SPAWN_JOIN_TICK) % interval; + offset = (NowDateTicks() - LinkGraphSchedule::SPAWN_JOIN_TICK).base() % interval; } if (offset == 0) { LinkGraphSchedule::instance.SpawnNext(); diff --git a/src/linkgraph/linkgraphschedule.h b/src/linkgraph/linkgraphschedule.h index ee7602a221..41300f2944 100644 --- a/src/linkgraph/linkgraphschedule.h +++ b/src/linkgraph/linkgraphschedule.h @@ -66,7 +66,7 @@ public: bool IsJoinWithUnfinishedJobDue() const; void JoinNext(); void SpawnAll(); - void ShiftDates(int interval); + void ShiftDates(DateDelta interval); /** * Queue a link graph for execution. diff --git a/src/network/core/network_game_info.cpp b/src/network/core/network_game_info.cpp index 972c3a6660..d2f84aca83 100644 --- a/src/network/core/network_game_info.cpp +++ b/src/network/core/network_game_info.cpp @@ -235,8 +235,8 @@ void SerializeNetworkGameInfo(Packet *p, const NetworkServerGameInfo *info, bool } /* NETWORK_GAME_INFO_VERSION = 3 */ - p->Send_uint32(info->game_date); - p->Send_uint32(info->start_date); + p->Send_uint32(info->game_date.base()); + p->Send_uint32(info->start_date.base()); /* NETWORK_GAME_INFO_VERSION = 2 */ p->Send_uint8 (info->companies_max); @@ -275,8 +275,8 @@ void SerializeNetworkGameInfoExtended(Packet *p, const NetworkServerGameInfo *in p->Send_uint8(version); // version num - p->Send_uint32(info->game_date); - p->Send_uint32(info->start_date); + p->Send_uint32(info->game_date.base()); + p->Send_uint32(info->start_date.base()); p->Send_uint8 (info->companies_max); p->Send_uint8 (info->companies_on); p->Send_uint8 (info->clients_max); // Used to be max-spectators @@ -400,8 +400,8 @@ void DeserializeNetworkGameInfo(Packet *p, NetworkGameInfo *info, const GameInfo } case 3: - info->game_date = Clamp(p->Recv_uint32(), 0, MAX_DATE); - info->start_date = Clamp(p->Recv_uint32(), 0, MAX_DATE); + info->game_date = Clamp(p->Recv_uint32(), 0, MAX_DATE.base()); + info->start_date = Clamp(p->Recv_uint32(), 0, MAX_DATE.base()); FALLTHROUGH; case 2: @@ -455,8 +455,8 @@ void DeserializeNetworkGameInfoExtended(Packet *p, NetworkGameInfo *info) NewGRFSerializationType newgrf_serialisation = NST_GRFID_MD5; - info->game_date = Clamp(p->Recv_uint32(), 0, MAX_DATE); - info->start_date = Clamp(p->Recv_uint32(), 0, MAX_DATE); + info->game_date = Clamp(p->Recv_uint32(), 0, MAX_DATE.base()); + info->start_date = Clamp(p->Recv_uint32(), 0, MAX_DATE.base()); info->companies_max = p->Recv_uint8 (); info->companies_on = p->Recv_uint8 (); p->Recv_uint8(); // Used to contain max-spectators. diff --git a/src/network/network.cpp b/src/network/network.cpp index a4671e8012..a56b12b658 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -326,7 +326,7 @@ void NetworkTextMessage(NetworkAction action, TextColour colour, bool self_send, char *msg_ptr = message + Utf8Encode(message, _current_text_dir == TD_LTR ? CHAR_TD_LRM : CHAR_TD_RLM); GetString(msg_ptr, strid, lastof(message)); - DEBUG(desync, 1, "msg: date{%08x; %02x; %02x}; %s", _date, _date_fract, _tick_skip_counter, message); + DEBUG(desync, 1, "msg: date{%08x; %02x; %02x}; %s", _date.base(), _date_fract, _tick_skip_counter, message); IConsolePrintF(colour, "%s", message); NetworkAddChatMessage(colour, _settings_client.gui.network_chat_timeout, message); } @@ -1162,7 +1162,7 @@ void NetworkGameLoop() /* We don't want to log multiple times if paused. */ static Date last_log; if (last_log != _date) { - DEBUG(desync, 2, "sync: date{%08x; %02x; %02x}; %08x; %08x", _date, _date_fract, _tick_skip_counter, _random.state[0], _random.state[1]); + DEBUG(desync, 2, "sync: date{%08x; %02x; %02x}; %08x; %08x", _date.base(), _date_fract, _tick_skip_counter, _random.state[0], _random.state[1]); last_log = _date; } } @@ -1185,15 +1185,15 @@ void NetworkGameLoop() if (_date == next_date && _date_fract == next_date_fract) { 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); - DEBUG(net, 0, "injecting: date{%08x; %02x; %02x}; %02x; %06x; %08x; %08x; " OTTD_PRINTFHEX64PAD " %08x; \"%s\" (%x) (%s)", _date, _date_fract, _tick_skip_counter, (int)_current_company, cp->tile, cp->p1, cp->p2, cp->p3, cp->cmd, cp->text.c_str(), cp->binary_length, GetCommandName(cp->cmd)); + DEBUG(net, 0, "injecting: date{%08x; %02x; %02x}; %02x; %06x; %08x; %08x; " OTTD_PRINTFHEX64PAD " %08x; \"%s\" (%x) (%s)", _date.base(), _date_fract, _tick_skip_counter, (int)_current_company, cp->tile, cp->p1, cp->p2, cp->p3, cp->cmd, cp->text.c_str(), cp->binary_length, GetCommandName(cp->cmd)); cp.reset(); } if (check_sync_state) { if (sync_state[0] == _random.state[0] && sync_state[1] == _random.state[1]) { - DEBUG(net, 0, "sync check: date{%08x; %02x; %02x}; match", _date, _date_fract, _tick_skip_counter); + DEBUG(net, 0, "sync check: date{%08x; %02x; %02x}; match", _date.base(), _date_fract, _tick_skip_counter); } else { DEBUG(net, 0, "sync check: date{%08x; %02x; %02x}; mismatch expected {%08x, %08x}, got {%08x, %08x}", - _date, _date_fract, _tick_skip_counter, sync_state[0], sync_state[1], _random.state[0], _random.state[1]); + _date.base(), _date_fract, _tick_skip_counter, sync_state[0], sync_state[1], _random.state[0], _random.state[1]); NOT_REACHED(); } check_sync_state = false; diff --git a/src/network/network_admin.cpp b/src/network/network_admin.cpp index 69d2092c4e..ddbc3d3793 100644 --- a/src/network/network_admin.cpp +++ b/src/network/network_admin.cpp @@ -179,7 +179,7 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::SendWelcome() p->Send_string(""); // Used to be map-name. p->Send_uint32(_settings_game.game_creation.generation_seed); p->Send_uint8 (_settings_game.game_creation.landscape); - p->Send_uint32(ConvertYMDToDate(_settings_game.game_creation.starting_year, 0, 1)); + p->Send_uint32(ConvertYMDToDate(_settings_game.game_creation.starting_year, 0, 1).base()); p->Send_uint16(MapSizeX()); p->Send_uint16(MapSizeY()); @@ -209,7 +209,7 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::SendDate() { Packet *p = new Packet(ADMIN_PACKET_SERVER_DATE); - p->Send_uint32(_date); + p->Send_uint32(_date.base()); this->SendPacket(p); return NETWORK_RECV_STATUS_OKAY; @@ -245,7 +245,7 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::SendClientInfo(const NetworkC p->Send_string(cs == nullptr ? "" : const_cast(cs->client_address).GetHostname()); p->Send_string(ci->client_name); p->Send_uint8 (0); // Used to be language - p->Send_uint32(ci->join_date); + p->Send_uint32(ci->join_date.base()); p->Send_uint8 (ci->client_playas); this->SendPacket(p); diff --git a/src/network/network_client.cpp b/src/network/network_client.cpp index 1283387cf1..039ab153dc 100644 --- a/src/network/network_client.cpp +++ b/src/network/network_client.cpp @@ -331,7 +331,7 @@ void ClientNetworkGameSocketHandler::ClientError(NetworkRecvStatus res) ShowNetworkError(STR_NETWORK_ERROR_DESYNC); DEBUG(desync, 1, "sync_err: date{%08x; %02x; %02x} {%x, " OTTD_PRINTFHEX64 "} != {%x, " OTTD_PRINTFHEX64 "}" - , _date, _date_fract, _tick_skip_counter, _sync_seed_1, _sync_state_checksum, _random.state[0], _state_checksum.state); + , _date.base(), _date_fract, _tick_skip_counter, _sync_seed_1, _sync_state_checksum, _random.state[0], _state_checksum.state); DEBUG(net, 0, "Sync error detected!"); std::string desync_log; @@ -632,7 +632,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::SendDesyncLog(const std::strin NetworkRecvStatus ClientNetworkGameSocketHandler::SendDesyncMessage(const char *msg) { Packet *p = new Packet(PACKET_CLIENT_DESYNC_MSG, SHRT_MAX); - p->Send_uint32(_date); + p->Send_uint32(_date.base()); p->Send_uint16(_date_fract); p->Send_uint8(_tick_skip_counter); p->Send_string(msg); diff --git a/src/network/network_gui.cpp b/src/network/network_gui.cpp index c53e5c7697..f92dccfc02 100644 --- a/src/network/network_gui.cpp +++ b/src/network/network_gui.cpp @@ -287,7 +287,7 @@ protected: /** Sort servers by the number of days the game is running */ static bool NGameYearsSorter(NetworkGameList * const &a, NetworkGameList * const &b) { - auto r = a->info.game_date - a->info.start_date - b->info.game_date + b->info.start_date; + auto r = a->info.game_date.base() - a->info.start_date.base() - b->info.game_date.base() + b->info.start_date.base(); return (r != 0) ? r < 0: NGameDateSorter(a, b); } @@ -650,11 +650,11 @@ public: DrawString(tr, invite_or_address); // server address / invite code tr.top += GetCharacterHeight(FS_NORMAL); - SetDParam(0, sel->info.start_date); + SetDParam(0, sel->info.start_date.base()); DrawString(tr, STR_NETWORK_SERVER_LIST_START_DATE); // start date tr.top += GetCharacterHeight(FS_NORMAL); - SetDParam(0, sel->info.game_date); + SetDParam(0, sel->info.game_date.base()); DrawString(tr, STR_NETWORK_SERVER_LIST_CURRENT_DATE); // current date tr.top += GetCharacterHeight(FS_NORMAL); diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp index a686995786..e340a54ac1 100644 --- a/src/network/network_server.cpp +++ b/src/network/network_server.cpp @@ -1020,7 +1020,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_JOIN(Packet *p) ci->join_frame = _frame_counter; ci->client_name = client_name; ci->client_playas = playas; - DEBUG(desync, 1, "client: date{%08x; %02x; %02x}; client: %02x; company: %02x", _date, _date_fract, _tick_skip_counter, (int)ci->index, (int)ci->client_playas); + DEBUG(desync, 1, "client: date{%08x; %02x; %02x}; client: %02x; company: %02x", _date.base(), _date_fract, _tick_skip_counter, (int)ci->index, (int)ci->client_playas); /* Make sure companies to which people try to join are not autocleaned */ if (Company::IsValidID(playas)) _network_company_states[playas].months_empty = 0; @@ -1812,7 +1812,7 @@ void NetworkUpdateClientInfo(ClientID client_id) if (ci == nullptr) return; - DEBUG(desync, 1, "client: date{%08x; %02x; %02x}; client: %02x; company: %02x", _date, _date_fract, _tick_skip_counter, client_id, (int)ci->client_playas); + DEBUG(desync, 1, "client: date{%08x; %02x; %02x}; client: %02x; company: %02x", _date.base(), _date_fract, _tick_skip_counter, client_id, (int)ci->client_playas); for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) { if (cs->status >= ServerNetworkGameSocketHandler::STATUS_AUTHORIZED) { @@ -2169,7 +2169,7 @@ void NetworkServerMonthlyLoop() void NetworkServerDailyLoop() { NetworkAdminUpdate(ADMIN_FREQUENCY_DAILY); - if ((_date % 7) == 3) NetworkAdminUpdate(ADMIN_FREQUENCY_WEEKLY); + if ((_date.base() % 7) == 3) NetworkAdminUpdate(ADMIN_FREQUENCY_WEEKLY); } /** diff --git a/src/newgrf.cpp b/src/newgrf.cpp index 8c9ce85c5c..cd1902e091 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -7403,7 +7403,7 @@ bool GetGlobalVariable(byte param, uint32 *value, const GRFFile *grffile) switch (param) { case 0x00: // current date - *value = std::max(_date - DAYS_TILL_ORIGINAL_BASE_YEAR, 0); + *value = std::max(_date - DAYS_TILL_ORIGINAL_BASE_YEAR, 0).base(); return true; case 0x01: // current year @@ -7412,7 +7412,7 @@ bool GetGlobalVariable(byte param, uint32 *value, const GRFFile *grffile) 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); - *value = _cur_date_ymd.month | (_cur_date_ymd.day - 1) << 8 | (IsLeapYear(_cur_date_ymd.year) ? 1 << 15 : 0) | (_date - start_of_year) << 16; + *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; return true; } @@ -7518,7 +7518,7 @@ bool GetGlobalVariable(byte param, uint32 *value, const GRFFile *grffile) return true; case 0x23: // long format date - *value = _date; + *value = _date.base(); return true; case 0x24: // long format year diff --git a/src/newgrf_airport.cpp b/src/newgrf_airport.cpp index ea56926ed9..a9ae4ede02 100644 --- a/src/newgrf_airport.cpp +++ b/src/newgrf_airport.cpp @@ -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 0xF0: return this->st->facilities; - case 0xFA: return ClampTo(this->st->build_date - DAYS_TILL_ORIGINAL_BASE_YEAR); + case 0xFA: return ClampTo((this->st->build_date - DAYS_TILL_ORIGINAL_BASE_YEAR).base()); } return this->st->GetNewGRFVariable(this->ro, variable, parameter, &(extra->available)); diff --git a/src/newgrf_engine.cpp b/src/newgrf_engine.cpp index 83b0e6d296..8753111776 100644 --- a/src/newgrf_engine.cpp +++ b/src/newgrf_engine.cpp @@ -729,7 +729,7 @@ static uint32 VehicleGetVariable(Vehicle *v, const VehicleScopeResolver *object, } case 0x4B: // Long date of last service - return v->date_of_last_service_newgrf; + return v->date_of_last_service_newgrf.base(); case 0x4C: // Current maximum speed in NewGRF units if (!v->IsPrimaryVehicle()) return 0; @@ -1118,7 +1118,7 @@ static uint32 VehicleGetVariable(Vehicle *v, const VehicleScopeResolver *object, } case 0x48: return Engine::Get(this->self_type)->flags; // Vehicle Type Info case 0x49: return _cur_year; // 'Long' format build year - case 0x4B: return _date; // Long date of last service + case 0x4B: return _date.base(); // Long date of last service case 0x92: return ClampTo(_date - DAYS_TILL_ORIGINAL_BASE_YEAR); // Date of last service case 0x93: return GB(ClampTo(_date - DAYS_TILL_ORIGINAL_BASE_YEAR), 8, 8); case 0xC4: return Clamp(_cur_year, ORIGINAL_BASE_YEAR, ORIGINAL_MAX_YEAR) - ORIGINAL_BASE_YEAR; // Build year diff --git a/src/newgrf_industries.cpp b/src/newgrf_industries.cpp index d5df46d60d..62da76dde9 100644 --- a/src/newgrf_industries.cpp +++ b/src/newgrf_industries.cpp @@ -271,7 +271,7 @@ static uint32 GetCountAndDistanceOfClosestInstance(byte param_setID, byte layout return this->industry->founder | (is_ai ? 0x10000 : 0) | (colours << 24); } - case 0x46: return this->industry->construction_date; // Date when built - long format - (in days) + case 0x46: return this->industry->construction_date.base(); // Date when built - long format - (in days) /* Override flags from GS */ case 0x47: return this->industry->ctlflags; @@ -362,7 +362,7 @@ static uint32 GetCountAndDistanceOfClosestInstance(byte param_setID, byte layout if (cargo == CT_INVALID) return 0; int index = this->industry->GetCargoAcceptedIndex(cargo); if (index < 0) return 0; // invalid cargo - if (variable == 0x6E) return this->industry->last_cargo_accepted_at[index]; + if (variable == 0x6E) return this->industry->last_cargo_accepted_at[index].base(); if (variable == 0x6F) return this->industry->incoming_cargo_waiting[index]; NOT_REACHED(); } diff --git a/src/newgrf_object.cpp b/src/newgrf_object.cpp index bbb2b19ccb..e0ac20081b 100644 --- a/src/newgrf_object.cpp +++ b/src/newgrf_object.cpp @@ -281,7 +281,7 @@ static uint32 GetCountAndDistanceOfClosestInstance(uint32 local_id, uint32 grfid break; /* Construction date */ - case 0x42: return _date; + case 0x42: return _date.base(); /* Object founder information */ case 0x44: return _current_company; @@ -325,7 +325,7 @@ static uint32 GetCountAndDistanceOfClosestInstance(uint32 local_id, uint32 grfid case 0x41: return GetTileSlope(this->tile) << 8 | GetTerrainType(this->tile); /* Construction date */ - case 0x42: return this->obj->build_date; + case 0x42: return this->obj->build_date.base(); /* Animation counter */ case 0x43: return GetAnimationFrame(this->tile); diff --git a/src/newgrf_railtype.cpp b/src/newgrf_railtype.cpp index b21959b27a..e70d3c4092 100644 --- a/src/newgrf_railtype.cpp +++ b/src/newgrf_railtype.cpp @@ -34,7 +34,7 @@ case 0x40: return 0; case 0x41: return 0; case 0x42: return 0; - case 0x43: return _date; + case 0x43: return _date.base(); case 0x44: return HZB_TOWN_EDGE; case A2VRI_RAILTYPE_SIGNAL_RESTRICTION_INFO: return 0; case A2VRI_RAILTYPE_SIGNAL_CONTEXT: return this->signal_context; @@ -49,8 +49,8 @@ case 0x41: return 0; case 0x42: return IsLevelCrossingTile(this->tile) && IsCrossingBarred(this->tile); case 0x43: - if (IsRailDepotTile(this->tile)) return Depot::GetByTile(this->tile)->build_date; - return _date; + if (IsRailDepotTile(this->tile)) return Depot::GetByTile(this->tile)->build_date.base(); + return _date.base(); case 0x44: { const Town *t = nullptr; if (IsRailDepotTile(this->tile)) { diff --git a/src/newgrf_roadtype.cpp b/src/newgrf_roadtype.cpp index 59e6abe647..4933e678a6 100644 --- a/src/newgrf_roadtype.cpp +++ b/src/newgrf_roadtype.cpp @@ -30,7 +30,7 @@ case 0x40: return 0; case 0x41: return 0; case 0x42: return 0; - case 0x43: return _date; + case 0x43: return _date.base(); case 0x44: return HZB_TOWN_EDGE; } } @@ -40,8 +40,8 @@ case 0x41: return 0; case 0x42: return IsLevelCrossingTile(this->tile) && IsCrossingBarred(this->tile); case 0x43: - if (IsRoadDepotTile(this->tile)) return Depot::GetByTile(this->tile)->build_date; - return _date; + if (IsRoadDepotTile(this->tile)) return Depot::GetByTile(this->tile)->build_date.base(); + return _date.base(); case 0x44: { const Town *t = nullptr; if (IsRoadDepotTile(this->tile)) { diff --git a/src/openttd.cpp b/src/openttd.cpp index 5fd1eead58..5333ac892a 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -1554,7 +1554,7 @@ void CheckCaches(bool force_check, std::function log, CheckC desync_level = 1; if (HasChickenBit(DCBF_DESYNC_CHECK_NO_GENERAL)) flags &= ~CHECK_CACHE_GENERAL; } - if (unlikely(HasChickenBit(DCBF_DESYNC_CHECK_PERIODIC_SIGNALS)) && desync_level < 2 && _scaled_date_ticks % 256 == 0) { + if (unlikely(HasChickenBit(DCBF_DESYNC_CHECK_PERIODIC_SIGNALS)) && desync_level < 2 && _scaled_date_ticks.base() % 256 == 0) { if (!SignalInfraTotalMatches()) desync_level = 2; } @@ -1562,7 +1562,7 @@ void CheckCaches(bool force_check, std::function log, CheckC * always to aid testing of caches. */ if (desync_level < 1) return; - if (desync_level == 1 && _scaled_date_ticks % 500 != 0) return; + if (desync_level == 1 && _scaled_date_ticks.base() % 500 != 0) return; } SCOPE_INFO_FMT([flags], "CheckCaches: %X", flags); @@ -2103,10 +2103,10 @@ void StateGameLoop() CallWindowGameTickEvent(); NewsLoop(); } else { - if (_debug_desync_level > 2 && _tick_skip_counter == 0 && _date_fract == 0 && (_date & 0x1F) == 0) { + if (_debug_desync_level > 2 && _tick_skip_counter == 0 && _date_fract == 0 && (_date.base() & 0x1F) == 0) { /* Save the desync savegame if needed. */ char name[MAX_PATH]; - seprintf(name, lastof(name), "dmp_cmds_%08x_%08x.sav", _settings_game.game_creation.generation_seed, _date); + seprintf(name, lastof(name), "dmp_cmds_%08x_%08x.sav", _settings_game.game_creation.generation_seed, _date.base()); SaveOrLoad(name, SLO_SAVE, DFT_GAME_FILE, AUTOSAVE_DIR, false); } @@ -2124,7 +2124,7 @@ void StateGameLoop() } if (!(_game_mode == GM_MENU || _game_mode == GM_BOOTSTRAP) && !_settings_client.gui.autosave_realtime && - (_scaled_date_ticks % (_settings_client.gui.autosave_interval * (_settings_game.economy.tick_rate == TRM_MODERN ? (60000 / 27) : (60000 / 30)))) == 0) { + (_scaled_date_ticks.base() % (_settings_client.gui.autosave_interval * (_settings_game.economy.tick_rate == TRM_MODERN ? (60000 / 27) : (60000 / 30)))) == 0) { _do_autosave = true; _check_special_modes = true; SetWindowDirty(WC_STATUS_BAR, 0); diff --git a/src/order_base.h b/src/order_base.h index 64246c5d6c..9158dd6d0d 100644 --- a/src/order_base.h +++ b/src/order_base.h @@ -979,6 +979,6 @@ public: inline const DispatchSchedule &GetDispatchScheduleByIndex(uint index) const { return this->dispatch_schedules[index]; } }; -void ShiftOrderDates(int interval); +void ShiftOrderDates(DateDelta interval); #endif /* ORDER_BASE_H */ diff --git a/src/order_cmd.cpp b/src/order_cmd.cpp index e7ee97875f..2443eda693 100644 --- a/src/order_cmd.cpp +++ b/src/order_cmd.cpp @@ -3042,7 +3042,7 @@ bool EvaluateDispatchSlotConditionalOrder(const Order *order, const Vehicle *v, } else { extern DateTicksScaled GetScheduledDispatchTime(const DispatchSchedule &ds, DateTicksScaled leave_time); DateTicksScaled slot = GetScheduledDispatchTime(sched, _scaled_date_ticks); - offset = (slot - sched.GetScheduledDispatchStartTick()) % sched.GetScheduledDispatchDuration(); + offset = (slot - sched.GetScheduledDispatchStartTick()).base() % sched.GetScheduledDispatchDuration(); } bool value; @@ -3082,7 +3082,7 @@ VehicleOrderID ProcessConditionalOrder(const Order *order, const Vehicle *v, Pro 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_SPEED: skip_order = OrderConditionCompare(occ, v->GetDisplayMaxSpeed() * 10 / 16, value); break; - case OCV_AGE: skip_order = OrderConditionCompare(occ, DateToYear(v->age), value); break; + case OCV_AGE: skip_order = OrderConditionCompare(occ, DateDeltaToYears(v->age), value); break; case OCV_REQUIRES_SERVICE: skip_order = OrderConditionCompare(occ, v->NeedsServicing(), value); break; case OCV_UNCONDITIONALLY: skip_order = true; break; case OCV_CARGO_WAITING: { @@ -3172,7 +3172,7 @@ VehicleOrderID ProcessConditionalOrder(const Order *order, const Vehicle *v, Pro skip_order = ord->UpdateJumpCounter((byte)value, mode == PCO_DRY_RUN); break; } - case OCV_REMAINING_LIFETIME: skip_order = OrderConditionCompare(occ, std::max(DateToYear(v->max_age - v->age + DAYS_IN_LEAP_YEAR - 1), 0), value); 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_COUNTER_VALUE: { const TraceRestrictCounter* ctr = TraceRestrictCounter::GetIfValid(GB(order->GetXData(), 16, 16)); if (ctr != nullptr) { @@ -3690,7 +3690,7 @@ CommandCost CmdMassChangeOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, u return CommandCost(); } -void ShiftOrderDates(int interval) +void ShiftOrderDates(DateDelta interval) { SetWindowClassesDirty(WC_VEHICLE_ORDERS); SetWindowClassesDirty(WC_VEHICLE_TIMETABLE); diff --git a/src/rail.cpp b/src/rail.cpp index bd88dffaec..01b16aa8f9 100644 --- a/src/rail.cpp +++ b/src/rail.cpp @@ -325,7 +325,7 @@ RailTypes AddDateIntroducedRailTypes(RailTypes current, Date date) if (rti->label == 0) continue; /* Not date introduced. */ - if (!IsInsideMM(rti->introduction_date, 0, MAX_DAY)) continue; + if (!IsInsideMM(rti->introduction_date, 0, MAX_DATE.base())) continue; /* Not yet introduced at this date. */ if (rti->introduction_date > date) continue; @@ -403,7 +403,7 @@ RailTypes GetRailTypes(bool introduces) } } - if (introduces) return AddDateIntroducedRailTypes(rts, MAX_DAY); + if (introduces) return AddDateIntroducedRailTypes(rts, MAX_DATE); return rts; } diff --git a/src/road.cpp b/src/road.cpp index f6239b26db..da541b1e2f 100644 --- a/src/road.cpp +++ b/src/road.cpp @@ -147,7 +147,7 @@ bool HasRoadTypeAvail(const CompanyID company, RoadType roadtype) if (rti->label == 0) return false; /* Not yet introduced at this date. */ - if (IsInsideMM(rti->introduction_date, 0, MAX_DAY) && rti->introduction_date > _date) return false; + if (IsInsideMM(rti->introduction_date, 0, MAX_DATE.base()) && rti->introduction_date > _date) return false; /* * Do not allow building hidden road types, except when a town may build it. @@ -209,7 +209,7 @@ RoadTypes AddDateIntroducedRoadTypes(RoadTypes current, Date date) if (rti->label == 0) continue; /* Not date introduced. */ - if (!IsInsideMM(rti->introduction_date, 0, MAX_DAY)) continue; + if (!IsInsideMM(rti->introduction_date, 0, MAX_DATE.base())) continue; /* Not yet introduced at this date. */ if (rti->introduction_date > date) continue; @@ -277,7 +277,7 @@ RoadTypes GetRoadTypes(bool introduces) } } - if (introduces) return AddDateIntroducedRoadTypes(rts, MAX_DAY); + if (introduces) return AddDateIntroducedRoadTypes(rts, MAX_DATE); return rts; } diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index f564348bf2..4562b4d78a 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -1790,19 +1790,19 @@ bool AfterLoadGame() /* Time starts at 0 instead of 1920. * Account for this in older games by adding an offset */ if (IsSavegameVersionBefore(SLV_31)) { - _date += DAYS_TILL_ORIGINAL_BASE_YEAR; + _date += DAYS_TILL_ORIGINAL_BASE_YEAR.AsDelta(); SetScaledTickVariables(); ConvertDateToYMD(_date, &_cur_date_ymd); UpdateCachedSnowLine(); - for (Station *st : Station::Iterate()) st->build_date += DAYS_TILL_ORIGINAL_BASE_YEAR; - for (Waypoint *wp : Waypoint::Iterate()) wp->build_date += DAYS_TILL_ORIGINAL_BASE_YEAR; - for (Engine *e : Engine::Iterate()) e->intro_date += DAYS_TILL_ORIGINAL_BASE_YEAR; + for (Station *st : Station::Iterate()) st->build_date += DAYS_TILL_ORIGINAL_BASE_YEAR.AsDelta(); + for (Waypoint *wp : Waypoint::Iterate()) wp->build_date += DAYS_TILL_ORIGINAL_BASE_YEAR.AsDelta(); + for (Engine *e : Engine::Iterate()) e->intro_date += DAYS_TILL_ORIGINAL_BASE_YEAR.AsDelta(); for (Company *c : Company::Iterate()) c->inaugurated_year += ORIGINAL_BASE_YEAR; for (Industry *i : Industry::Iterate()) i->last_prod_year += ORIGINAL_BASE_YEAR; for (Vehicle *v : Vehicle::Iterate()) { - v->date_of_last_service += DAYS_TILL_ORIGINAL_BASE_YEAR; + v->date_of_last_service += DAYS_TILL_ORIGINAL_BASE_YEAR.AsDelta(); v->build_year += ORIGINAL_BASE_YEAR; } } @@ -3603,7 +3603,7 @@ bool AfterLoadGame() /* If the start date is 0, the vehicle is not waiting to start and can be ignored. */ if (v->timetable_start == 0) continue; - v->timetable_start += _scaled_date_ticks - _tick_counter; + v->timetable_start += _scaled_date_ticks.base() - _tick_counter; } } else if (!SlXvIsFeaturePresent(XSLFI_TIMETABLES_START_TICKS, 3)) { extern btree::btree_map _old_timetable_start_subticks_map; @@ -3612,10 +3612,10 @@ bool AfterLoadGame() if (v->timetable_start == 0) continue; if (SlXvIsFeatureMissing(XSLFI_TIMETABLES_START_TICKS)) { - v->timetable_start *= DAY_TICKS; + v->timetable_start.edit_base() *= DAY_TICKS; } - v->timetable_start = DateTicksToScaledDateTicks(v->timetable_start); + v->timetable_start = DateTicksToScaledDateTicks(v->timetable_start.base()); if (SlXvIsFeaturePresent(XSLFI_TIMETABLES_START_TICKS, 2, 2)) { v->timetable_start += _old_timetable_start_subticks_map[v->index]; @@ -4194,7 +4194,7 @@ bool AfterLoadGame() for (OrderList *order_list : OrderList::Iterate()) { for (DispatchSchedule &ds : order_list->GetScheduledDispatchScheduleSet()) { - DateTicksScaled start_tick = DateToScaledDateTicks(ds.GetScheduledDispatchStartTick()) + _old_scheduled_dispatch_start_full_date_fract_map[&ds]; + DateTicksScaled start_tick = DateToScaledDateTicks(ds.GetScheduledDispatchStartTick().base()) + _old_scheduled_dispatch_start_full_date_fract_map[&ds]; ds.SetScheduledDispatchStartTick(start_tick); } } diff --git a/src/saveload/misc_sl.cpp b/src/saveload/misc_sl.cpp index 857a499a85..f33911e36c 100644 --- a/src/saveload/misc_sl.cpp +++ b/src/saveload/misc_sl.cpp @@ -104,7 +104,7 @@ struct DATEChunkHandler : ChunkHandler { this->LoadCommon(_date_check_desc, _date_check_sl_compat); if (IsSavegameVersionBefore(SLV_31)) { - _load_check_data.current_date += DAYS_TILL_ORIGINAL_BASE_YEAR; + _load_check_data.current_date += DAYS_TILL_ORIGINAL_BASE_YEAR.AsDelta(); } } }; diff --git a/src/schdispatch_cmd.cpp b/src/schdispatch_cmd.cpp index 5f2b4062ec..2a891d11c1 100644 --- a/src/schdispatch_cmd.cpp +++ b/src/schdispatch_cmd.cpp @@ -674,9 +674,9 @@ bool DispatchSchedule::UpdateScheduledDispatchToDate(DateTicksScaled now) { bool update_windows = false; if (this->GetScheduledDispatchStartTick() == 0) { - DateTicksScaled start = now - (now % this->GetScheduledDispatchDuration()); + DateTicksScaled start = now - (now.base() % this->GetScheduledDispatchDuration()); this->SetScheduledDispatchStartTick(start); - int64 last_dispatch = -start; + int64 last_dispatch = -(start.base()); if (last_dispatch < INT_MIN && _settings_game.game_time.time_in_minutes) { /* Advance by multiples of 24 hours */ const int64 day = 24 * 60 * _settings_game.game_time.ticks_per_minute; diff --git a/src/schdispatch_gui.cpp b/src/schdispatch_gui.cpp index d31fe9d729..f127794fc0 100644 --- a/src/schdispatch_gui.cpp +++ b/src/schdispatch_gui.cpp @@ -67,7 +67,7 @@ enum SchdispatchWidgets { */ static void SetScheduleStartDateIntl(uint32 p1, DateTicksScaled date) { - DoCommandPEx(0, p1, 0, (uint64)date, CMD_SCHEDULED_DISPATCH_SET_START_DATE | CMD_MSG(STR_ERROR_CAN_T_TIMETABLE_VEHICLE), nullptr, nullptr, 0); + DoCommandPEx(0, p1, 0, (uint64)date.base(), CMD_SCHEDULED_DISPATCH_SET_START_DATE | CMD_MSG(STR_ERROR_CAN_T_TIMETABLE_VEHICLE), nullptr, nullptr, 0); } /** @@ -102,12 +102,12 @@ static void ScheduleAddIntl(uint32 p1, DateTicksScaled date, uint extra_slots, u if (extra_slots > 0 && offset > 0 && !wrap_mode) { DateTicksScaled end_tick = start_tick + duration; - DateTicksScaled max_extra_slots = (end_tick - 1 - date) / offset; - if (max_extra_slots < extra_slots) extra_slots = static_cast(std::max(0, max_extra_slots)); + int64 max_extra_slots = (end_tick - 1 - date).base() / offset; + if (max_extra_slots < extra_slots) extra_slots = static_cast(std::max(0, max_extra_slots)); extra_slots = std::min(extra_slots, UINT16_MAX); } - DoCommandPEx(0, p1, (uint32)(date - start_tick), (((uint64)extra_slots) << 32) | offset, CMD_SCHEDULED_DISPATCH_ADD | CMD_MSG(STR_ERROR_CAN_T_TIMETABLE_VEHICLE), nullptr, nullptr, 0); + DoCommandPEx(0, p1, (uint32)(date - start_tick).base(), (((uint64)extra_slots) << 32) | offset, CMD_SCHEDULED_DISPATCH_ADD | CMD_MSG(STR_ERROR_CAN_T_TIMETABLE_VEHICLE), nullptr, nullptr, 0); } /** @@ -163,18 +163,16 @@ static void AddNewScheduledDispatchSchedule(VehicleID vindex) if (_settings_time.time_in_minutes) { /* Set to 00:00 of today, and 1 day */ - start_tick = MINUTES_DATE(MINUTES_DAY(CURRENT_MINUTE), 0, 0); - start_tick -= _settings_time.clock_offset; - start_tick *= _settings_time.ticks_per_minute; + start_tick = _settings_time.FromTickMinutes(_settings_time.NowInTickMinutes().ToSameDayClockTime(0, 0)); duration = 24 * 60 * _settings_time.ticks_per_minute; } else { /* Set Jan 1st and 365 day */ - start_tick = DateToScaledDateTicks(DAYS_TILL(_cur_year)); + start_tick = DateToScaledDateTicks(DateAtStartOfYear(_cur_year)); duration = 365 * DAY_TICKS; } - DoCommandPEx(0, vindex, duration, (uint64)start_tick, CMD_SCHEDULED_DISPATCH_ADD_NEW_SCHEDULE | CMD_MSG(STR_ERROR_CAN_T_TIMETABLE_VEHICLE), CcAddNewSchDispatchSchedule, nullptr, 0); + DoCommandPEx(0, vindex, duration, (uint64)start_tick.base(), CMD_SCHEDULED_DISPATCH_ADD_NEW_SCHEDULE | CMD_MSG(STR_ERROR_CAN_T_TIMETABLE_VEHICLE), CcAddNewSchDispatchSchedule, nullptr, 0); } struct SchdispatchWindow : GeneralVehicleWindow { @@ -700,12 +698,7 @@ struct SchdispatchWindow : GeneralVehicleWindow { case WID_SCHDISPATCH_SET_START_DATE: { if (!this->IsScheduleSelected()) break; if (_settings_time.time_in_minutes && _settings_client.gui.timetable_start_text_entry) { - uint64 time = _scaled_date_ticks; - time /= _settings_time.ticks_per_minute; - time += _settings_time.clock_offset; - time %= (24 * 60); - time = (time % 60) + (((time / 60) % 24) * 100); - SetDParam(0, time); + SetDParam(0, _settings_time.NowInTickMinutes().ClockHHMM()); ShowQueryString(STR_JUST_INT, STR_SCHDISPATCH_START_CAPTION_MINUTE, 31, this, CS_NUMERAL, QSF_ACCEPT_UNCHANGED); } else { ShowSetDateWindow(this, v->index | (this->schedule_index << 20), _scaled_date_ticks, _cur_year, _cur_year + 15, SetScheduleStartDateCallback, STR_SCHDISPATCH_SET_START, STR_SCHDISPATCH_START_TOOLTIP); @@ -867,9 +860,7 @@ struct SchdispatchWindow : GeneralVehicleWindow { if (val >= 0 && end != nullptr && *end == 0) { uint minutes = (val % 100) % 60; uint hours = (val / 100) % 24; - DateTicksScaled slot = MINUTES_DATE(MINUTES_DAY(CURRENT_MINUTE), hours, minutes); - slot -= _settings_time.clock_offset; - slot *= _settings_time.ticks_per_minute; + DateTicksScaled slot = _settings_time.FromTickMinutes(_settings_time.NowInTickMinutes().ToSameDayClockTime(hours, minutes)); ScheduleAddIntl(v->index | (this->schedule_index << 20), slot, 0, 0); } break; @@ -885,9 +876,7 @@ struct SchdispatchWindow : GeneralVehicleWindow { if (val >= 0 && end != nullptr && *end == 0) { uint minutes = (val % 100) % 60; uint hours = (val / 100) % 24; - DateTicksScaled start = MINUTES_DATE(MINUTES_DAY(CURRENT_MINUTE), hours, minutes); - start -= _settings_time.clock_offset; - start *= _settings_time.ticks_per_minute; + DateTicksScaled start = _settings_time.FromTickMinutes(_settings_time.NowInTickMinutes().ToSameDayClockTime(hours, minutes)); SetScheduleStartDateIntl(v->index | (this->schedule_index << 20), start); } break; @@ -974,9 +963,7 @@ struct SchdispatchWindow : GeneralVehicleWindow { } if (end < start || step == 0 || !this->IsScheduleSelected()) return; - DateTicksScaled slot = MINUTES_DATE(MINUTES_DAY(CURRENT_MINUTE), 0, start); - slot -= _settings_time.clock_offset; - slot *= _settings_time.ticks_per_minute; + DateTicksScaled slot = _settings_time.FromTickMinutes(_settings_time.NowInTickMinutes().ToSameDayClockTime(0, start)); ScheduleAddIntl(this->vehicle->index | (this->schedule_index << 20), slot, (end - start) / step, step * _settings_time.ticks_per_minute, wrap_mode); } }; @@ -1075,14 +1062,14 @@ enum ScheduledDispatchAddSlotsWindowWidgets { }; struct ScheduledDispatchAddSlotsWindow : Window { - uint start; - uint step; - uint end; + ClockFaceMinutes start; + ClockFaceMinutes step; + ClockFaceMinutes end; ScheduledDispatchAddSlotsWindow(WindowDesc *desc, WindowNumber window_number, SchdispatchWindow *parent) : Window(desc) { - this->start = (_scaled_date_ticks / _settings_time.ticks_per_minute) % (60 * 24); + this->start = _settings_time.NowInTickMinutes().ToClockFaceMinutes(); this->step = 30; this->end = this->start + 60; this->parent = parent; @@ -1137,33 +1124,33 @@ struct ScheduledDispatchAddSlotsWindow : Window { virtual void SetStringParameters(int widget) const override { switch (widget) { - case WID_SCHDISPATCH_ADD_SLOT_START_HOUR: SetDParam(0, MINUTES_HOUR(start)); break; - case WID_SCHDISPATCH_ADD_SLOT_START_MINUTE: SetDParam(0, MINUTES_MINUTE(start)); break; - case WID_SCHDISPATCH_ADD_SLOT_STEP_HOUR: SetDParam(0, MINUTES_HOUR(step)); break; - case WID_SCHDISPATCH_ADD_SLOT_STEP_MINUTE: SetDParam(0, MINUTES_MINUTE(step)); break; - case WID_SCHDISPATCH_ADD_SLOT_END_HOUR: SetDParam(0, MINUTES_HOUR(end)); break; - case WID_SCHDISPATCH_ADD_SLOT_END_MINUTE: SetDParam(0, MINUTES_MINUTE(end)); break; + case WID_SCHDISPATCH_ADD_SLOT_START_HOUR: SetDParam(0, start.ClockHour()); break; + case WID_SCHDISPATCH_ADD_SLOT_START_MINUTE: SetDParam(0, start.ClockMinute()); break; + case WID_SCHDISPATCH_ADD_SLOT_STEP_HOUR: SetDParam(0, step.ClockHour()); break; + case WID_SCHDISPATCH_ADD_SLOT_STEP_MINUTE: SetDParam(0, step.ClockMinute()); break; + case WID_SCHDISPATCH_ADD_SLOT_END_HOUR: SetDParam(0, end.ClockHour()); break; + case WID_SCHDISPATCH_ADD_SLOT_END_MINUTE: SetDParam(0, end.ClockMinute()); break; } } virtual void OnClick(Point pt, int widget, int click_count) override { - auto handle_hours_dropdown = [&](uint current) { + auto handle_hours_dropdown = [&](ClockFaceMinutes current) { DropDownList list; for (uint i = 0; i < 24; i++) { SetDParam(0, i); list.emplace_back(new DropDownListStringItem(STR_JUST_INT, i, false)); } - ShowDropDownList(this, std::move(list), MINUTES_HOUR(current), widget); + ShowDropDownList(this, std::move(list), current.ClockHour(), widget); }; - auto handle_minutes_dropdown = [&](uint current) { + auto handle_minutes_dropdown = [&](ClockFaceMinutes current) { DropDownList list; for (uint i = 0; i < 60; i++) { SetDParam(0, i); list.emplace_back(new DropDownListStringItem(STR_JUST_INT, i, false)); } - ShowDropDownList(this, std::move(list), MINUTES_MINUTE(current), widget); + ShowDropDownList(this, std::move(list), current.ClockMinute(), widget); }; switch (widget) { @@ -1187,7 +1174,7 @@ struct ScheduledDispatchAddSlotsWindow : Window { break; case WID_SCHDISPATCH_ADD_SLOT_ADD_BUTTON: - static_cast(this->parent)->AddMultipleDepartureSlots(this->start, this->step, this->end); + static_cast(this->parent)->AddMultipleDepartureSlots(this->start.base(), this->step.base(), this->end.base()); this->Close(); break; } @@ -1197,22 +1184,22 @@ struct ScheduledDispatchAddSlotsWindow : Window { { switch (widget) { case WID_SCHDISPATCH_ADD_SLOT_START_HOUR: - this->start = MINUTES_DATE(0, index, MINUTES_MINUTE(this->start)); + this->start = ClockFaceMinutes::FromClockFace(index, this->start.ClockMinute()); break; case WID_SCHDISPATCH_ADD_SLOT_START_MINUTE: - this->start = MINUTES_DATE(0, MINUTES_HOUR(this->start), index); + this->start = ClockFaceMinutes::FromClockFace(this->start.ClockHour(), index); break; case WID_SCHDISPATCH_ADD_SLOT_STEP_HOUR: - this->step = MINUTES_DATE(0, index, MINUTES_MINUTE(this->step)); + this->step = ClockFaceMinutes::FromClockFace(index, this->step.ClockMinute()); break; case WID_SCHDISPATCH_ADD_SLOT_STEP_MINUTE: - this->step = MINUTES_DATE(0, MINUTES_HOUR(this->step), index); + this->step = ClockFaceMinutes::FromClockFace(this->step.ClockHour(), index); break; case WID_SCHDISPATCH_ADD_SLOT_END_HOUR: - this->end = MINUTES_DATE(0, index, MINUTES_MINUTE(this->end)); + this->end = ClockFaceMinutes::FromClockFace(index, this->end.ClockMinute()); break; case WID_SCHDISPATCH_ADD_SLOT_END_MINUTE: - this->end = MINUTES_DATE(0, MINUTES_HOUR(this->end), index); + this->end = ClockFaceMinutes::FromClockFace(this->end.ClockHour(), index); break; } diff --git a/src/script/api/script_basestation.cpp b/src/script/api/script_basestation.cpp index aef9e3b5f6..3cb39aea1b 100644 --- a/src/script/api/script_basestation.cpp +++ b/src/script/api/script_basestation.cpp @@ -57,5 +57,5 @@ { if (!IsValidBaseStation(station_id)) return ScriptDate::DATE_INVALID; - return (ScriptDate::Date)::BaseStation::Get(station_id)->build_date; + return (ScriptDate::Date)::BaseStation::Get(station_id)->build_date.base(); } diff --git a/src/script/api/script_client.cpp b/src/script/api/script_client.cpp index 87f90d65c8..9b65f638db 100644 --- a/src/script/api/script_client.cpp +++ b/src/script/api/script_client.cpp @@ -50,5 +50,5 @@ static NetworkClientInfo *FindClientInfo(ScriptClient::ClientID client) { NetworkClientInfo *ci = FindClientInfo(client); if (ci == nullptr) return ScriptDate::DATE_INVALID; - return (ScriptDate::Date)ci->join_date; + return (ScriptDate::Date)ci->join_date.base(); } diff --git a/src/script/api/script_date.cpp b/src/script/api/script_date.cpp index 911dceedfe..daf1180ba2 100644 --- a/src/script/api/script_date.cpp +++ b/src/script/api/script_date.cpp @@ -25,7 +25,7 @@ /* static */ ScriptDate::Date ScriptDate::GetCurrentDate() { - return (ScriptDate::Date)_date; + return (ScriptDate::Date)_date.base(); } /* static */ SQInteger ScriptDate::GetDayLengthFactor() @@ -66,7 +66,7 @@ if (day_of_month < 1 || day_of_month > 31) return DATE_INVALID; if (year < 0 || year > MAX_YEAR) return DATE_INVALID; - return (ScriptDate::Date)::ConvertYMDToDate(year, month - 1, day_of_month); + return (ScriptDate::Date)::ConvertYMDToDate(year, month - 1, day_of_month).base(); } /* static */ SQInteger ScriptDate::GetSystemTime() @@ -88,17 +88,17 @@ /* static */ SQInteger ScriptDate::GetCurrentScaledDateTicks() { - return _scaled_date_ticks; + return _scaled_date_ticks.base(); } -/* static */ SQInteger ScriptDate::GetHour(DateTicksScaled ticks) +/* static */ SQInteger ScriptDate::GetHour(SQInteger ticks) { - Minutes minutes = (ticks / _settings_game.game_time.ticks_per_minute) + _settings_game.game_time.clock_offset; - return MINUTES_HOUR(minutes); + TickMinutes minutes = _settings_game.game_time.ToTickMinutes(DateTicksScaled(ticks)); + return minutes.ClockHour(); } -/* static */ SQInteger ScriptDate::GetMinute(DateTicksScaled ticks) +/* static */ SQInteger ScriptDate::GetMinute(SQInteger ticks) { - Minutes minutes = (ticks / _settings_game.game_time.ticks_per_minute) + _settings_game.game_time.clock_offset; - return MINUTES_MINUTE(minutes); + TickMinutes minutes = _settings_game.game_time.ToTickMinutes(DateTicksScaled(ticks)); + return minutes.ClockMinute(); } diff --git a/src/script/api/script_date.hpp b/src/script/api/script_date.hpp index d1a5e61c2b..3b0dc979eb 100644 --- a/src/script/api/script_date.hpp +++ b/src/script/api/script_date.hpp @@ -31,7 +31,7 @@ public: * compose valid date values for a known year, month and day. */ enum Date { - DATE_INVALID = ::INVALID_DATE, ///< A value representing an invalid date. + DATE_INVALID = ::INVALID_DATE.base(), ///< A value representing an invalid date. }; /** @@ -96,9 +96,9 @@ public: static SQInteger GetCurrentScaledDateTicks(); - static SQInteger GetHour(DateTicksScaled ticks); + static SQInteger GetHour(SQInteger ticks); - static SQInteger GetMinute(DateTicksScaled ticks); + static SQInteger GetMinute(SQInteger ticks); }; #endif /* SCRIPT_DATE_HPP */ diff --git a/src/script/api/script_engine.cpp b/src/script/api/script_engine.cpp index e731158132..31f554fd7d 100644 --- a/src/script/api/script_engine.cpp +++ b/src/script/api/script_engine.cpp @@ -131,7 +131,7 @@ if (!IsValidEngine(engine_id)) return -1; if (GetVehicleType(engine_id) == ScriptVehicle::VT_RAIL && IsWagon(engine_id)) return -1; - return ::Engine::Get(engine_id)->GetLifeLengthInDays(); + return ::Engine::Get(engine_id)->GetLifeLengthInDays().base(); } /* static */ Money ScriptEngine::GetRunningCost(EngineID engine_id) @@ -171,7 +171,7 @@ { if (!IsValidEngine(engine_id)) return ScriptDate::DATE_INVALID; - return (ScriptDate::Date)::Engine::Get(engine_id)->intro_date; + return (ScriptDate::Date)::Engine::Get(engine_id)->intro_date.base(); } /* static */ ScriptVehicle::VehicleType ScriptEngine::GetVehicleType(EngineID engine_id) diff --git a/src/script/api/script_industry.cpp b/src/script/api/script_industry.cpp index dcbaebfa1e..b9908a2b8b 100644 --- a/src/script/api/script_industry.cpp +++ b/src/script/api/script_industry.cpp @@ -52,7 +52,7 @@ { Industry *i = Industry::GetIfValid(industry_id); if (i == nullptr) return ScriptDate::DATE_INVALID; - return (ScriptDate::Date)i->construction_date; + return (ScriptDate::Date)i->construction_date.base(); } /* static */ bool ScriptIndustry::SetText(IndustryID industry_id, Text *text) @@ -230,11 +230,11 @@ if (i == nullptr) return ScriptDate::DATE_INVALID; if (cargo_type == CT_INVALID) { - return (ScriptDate::Date)std::accumulate(std::begin(i->last_cargo_accepted_at), std::end(i->last_cargo_accepted_at), 0, [](Date a, Date b) { return std::max(a, b); }); + 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(); } else { int index = i->GetCargoAcceptedIndex(cargo_type); if (index < 0) return ScriptDate::DATE_INVALID; - return (ScriptDate::Date)i->last_cargo_accepted_at[index]; + return (ScriptDate::Date)i->last_cargo_accepted_at[index].base(); } } diff --git a/src/script/api/script_story_page.cpp b/src/script/api/script_story_page.cpp index 3102b3ca6d..6616777345 100644 --- a/src/script/api/script_story_page.cpp +++ b/src/script/api/script_story_page.cpp @@ -190,7 +190,7 @@ static inline bool StoryPageElementTypeRequiresText(StoryPageElementType type) EnforcePrecondition(ScriptDate::DATE_INVALID, IsValidStoryPage(story_page_id)); EnforceDeityMode(ScriptDate::DATE_INVALID); - return (ScriptDate::Date)StoryPage::Get(story_page_id)->date; + return (ScriptDate::Date)StoryPage::Get(story_page_id)->date.base(); } /* static */ bool ScriptStoryPage::SetDate(StoryPageID story_page_id, ScriptDate::Date date) diff --git a/src/script/api/script_vehicle.cpp b/src/script/api/script_vehicle.cpp index 1d6f432589..a7c501874d 100644 --- a/src/script/api/script_vehicle.cpp +++ b/src/script/api/script_vehicle.cpp @@ -310,7 +310,7 @@ { if (!IsValidVehicle(vehicle_id)) return -1; - return ::Vehicle::Get(vehicle_id)->age; + return ::Vehicle::Get(vehicle_id)->age.base(); } /* static */ SQInteger ScriptVehicle::GetWagonAge(VehicleID vehicle_id, SQInteger wagon) @@ -322,21 +322,21 @@ if (v->type == VEH_TRAIN) { while (wagon-- > 0) v = ::Train::From(v)->GetNextUnit(); } - return v->age; + return v->age.base(); } /* static */ SQInteger ScriptVehicle::GetMaxAge(VehicleID vehicle_id) { if (!IsPrimaryVehicle(vehicle_id)) return -1; - return ::Vehicle::Get(vehicle_id)->max_age; + return ::Vehicle::Get(vehicle_id)->max_age.base(); } /* static */ SQInteger ScriptVehicle::GetAgeLeft(VehicleID vehicle_id) { if (!IsPrimaryVehicle(vehicle_id)) return -1; - return ::Vehicle::Get(vehicle_id)->max_age - ::Vehicle::Get(vehicle_id)->age; + return ::Vehicle::Get(vehicle_id)->max_age.base() - ::Vehicle::Get(vehicle_id)->age.base(); } /* static */ SQInteger ScriptVehicle::GetCurrentSpeed(VehicleID vehicle_id) diff --git a/src/settings_type.h b/src/settings_type.h index 2b7a930f14..1cf975718e 100644 --- a/src/settings_type.h +++ b/src/settings_type.h @@ -135,6 +135,22 @@ struct TimeSettings { bool time_in_minutes; ///< whether to use the hh:mm conversion when printing dates uint16 ticks_per_minute; ///< how many ticks per minute uint16 clock_offset; ///< clock offset in minutes + + TickMinutes ToTickMinutes(DateTicksScaled ticks) const + { + return (ticks.base() / this->ticks_per_minute) + this->clock_offset; + } + + TickMinutes NowInTickMinutes() const + { + extern DateTicksScaled _scaled_date_ticks; + return this->ToTickMinutes(_scaled_date_ticks); + } + + DateTicksScaled FromTickMinutes(TickMinutes minutes) const + { + return (minutes.base() - this->clock_offset) * this->ticks_per_minute; + } }; /** Settings related to the GUI and other stuff that is not saved in the savegame. */ diff --git a/src/sl/linkgraph_sl.cpp b/src/sl/linkgraph_sl.cpp index 973c31c90e..9368dd38bd 100644 --- a/src/sl/linkgraph_sl.cpp +++ b/src/sl/linkgraph_sl.cpp @@ -39,7 +39,7 @@ SaveLoadTable GetLinkGraphDesc() void GetLinkGraphJobDayLengthScaleAfterLoad(LinkGraphJob *lgj) { - lgj->join_date_ticks *= DAY_TICKS; + lgj->join_date_ticks.edit_base() *= DAY_TICKS; lgj->join_date_ticks += LinkGraphSchedule::SPAWN_JOIN_TICK; uint recalc_scale; diff --git a/src/sl/misc_sl.cpp b/src/sl/misc_sl.cpp index 9a4d2551f3..0d8fc1a8b5 100644 --- a/src/sl/misc_sl.cpp +++ b/src/sl/misc_sl.cpp @@ -162,7 +162,7 @@ static void Check_DATE() { SlGlobList(_date_check_desc); if (IsSavegameVersionBefore(SLV_31)) { - _load_check_data.current_date += DAYS_TILL_ORIGINAL_BASE_YEAR; + _load_check_data.current_date += DAYS_TILL_ORIGINAL_BASE_YEAR.AsDelta(); } } diff --git a/src/sl/oldloader_sl.cpp b/src/sl/oldloader_sl.cpp index 07a3211026..3fda18ee47 100644 --- a/src/sl/oldloader_sl.cpp +++ b/src/sl/oldloader_sl.cpp @@ -395,7 +395,7 @@ static bool FixTTOEngines() for (uint i = 0; i < lengthof(_orig_aircraft_vehicle_info); i++, j++) new (GetTempDataEngine(j)) Engine(VEH_AIRCRAFT, i); } - Date aging_date = std::min(_date + DAYS_TILL_ORIGINAL_BASE_YEAR, ConvertYMDToDate(2050, 0, 1)); + Date aging_date = std::min(_date + DAYS_TILL_ORIGINAL_BASE_YEAR.AsDelta(), ConvertYMDToDate(2050, 0, 1)); for (EngineID i = 0; i < 256; i++) { int oi = ttd_to_tto[i]; @@ -403,17 +403,17 @@ static bool FixTTOEngines() if (oi == 255) { /* Default engine is used */ - _date += DAYS_TILL_ORIGINAL_BASE_YEAR; + _date += DAYS_TILL_ORIGINAL_BASE_YEAR.AsDelta(); StartupOneEngine(e, aging_date, 0, INT_MAX); CalcEngineReliability(e, false); - e->intro_date -= DAYS_TILL_ORIGINAL_BASE_YEAR; - _date -= DAYS_TILL_ORIGINAL_BASE_YEAR; + e->intro_date -= DAYS_TILL_ORIGINAL_BASE_YEAR.AsDelta(); + _date -= DAYS_TILL_ORIGINAL_BASE_YEAR.AsDelta(); /* Make sure for example monorail and maglev are available when they should be */ if (_date >= e->intro_date && HasBit(e->info.climates, 0)) { e->flags |= ENGINE_AVAILABLE; e->company_avail = MAX_UVALUE(CompanyMask); - e->age = _date > e->intro_date ? (_date - e->intro_date) / 30 : 0; + e->age = _date > e->intro_date ? (_date - e->intro_date).base() / 30 : 0; } } else { /* Using data from TTO savegame */ diff --git a/src/sl/saveload.cpp b/src/sl/saveload.cpp index 27235fcb0f..9e783fdb5b 100644 --- a/src/sl/saveload.cpp +++ b/src/sl/saveload.cpp @@ -3726,7 +3726,7 @@ SaveOrLoadResult SaveOrLoad(const std::string &filename, SaveLoadOperation fop, } if (fop == SLO_SAVE) { // SAVE game - DEBUG(desync, 1, "save: date{%08x; %02x; %02x}; %s", _date, _date_fract, _tick_skip_counter, filename.c_str()); + DEBUG(desync, 1, "save: date{%08x; %02x; %02x}; %s", _date.base(), _date_fract, _tick_skip_counter, filename.c_str()); if (!_settings_client.gui.threaded_saves) threaded = false; return DoSave(new FileWriter(fh), threaded); diff --git a/src/sl/saveload.h b/src/sl/saveload.h index 2961721ea8..6ffc089014 100644 --- a/src/sl/saveload.h +++ b/src/sl/saveload.h @@ -17,6 +17,7 @@ #include "../scope.h" #include "../core/ring_buffer.hpp" #include "../core/tinystring_type.hpp" +#include "../core/strong_typedef_type.hpp" #include #include @@ -338,7 +339,7 @@ static inline constexpr bool SlCheckPrimitiveTypeVar(VarType type) if (GetVarMemType(type) == SLE_VAR_CNAME) { return std::is_same_v || std::is_same_v || std::is_same_v; } - if (!std::is_integral_v && !std::is_enum_v && !sl_is_instance{}) return false; + if (!std::is_integral_v && !std::is_enum_v && !sl_is_instance{} && !std::is_base_of_v) return false; return sizeof(T) == SlVarSize(type); } diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index 80064da3f7..698684cbe4 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -4452,11 +4452,11 @@ void DeleteStaleLinks(Station *from) Station *to = Station::Get((*lg)[to_id].Station()); assert(to->goods[c].node == to_id); assert(_date >= edge.LastUpdate()); - uint timeout = std::max((LinkGraph::MIN_TIMEOUT_DISTANCE + (DistanceManhattan(from->xy, to->xy) >> 3)) / _settings_game.economy.day_length_factor, 1); - if (edge.LastAircraftUpdate() != INVALID_DATE && (uint)(_date - edge.LastAircraftUpdate()) > timeout) { + DateDelta timeout = std::max((LinkGraph::MIN_TIMEOUT_DISTANCE + (DistanceManhattan(from->xy, to->xy) >> 3)) / _settings_game.economy.day_length_factor, 1); + if (edge.LastAircraftUpdate() != INVALID_DATE && (_date - edge.LastAircraftUpdate()) > timeout) { edge.ClearAircraft(); } - if ((uint)(_date - edge.LastUpdate()) > timeout) { + if ((_date - edge.LastUpdate()) > timeout) { bool updated = false; if (auto_distributed) { @@ -4488,7 +4488,7 @@ void DeleteStaleLinks(Station *from) // Only run LinkRefresher if vehicle was not already in the cache if (res.second) { /* Do not refresh links of vehicles that have been stopped in depot for a long time. */ - if (!v->IsStoppedInDepot() || static_cast(_date - v->date_of_last_service) <= + if (!v->IsStoppedInDepot() || (_date - v->date_of_last_service) <= LinkGraph::STALE_LINK_DEPOT_TIMEOUT) { edge_helper.RecordSize(); LinkRefresher::Run(v, false); // Don't allow merging. Otherwise lg might get deleted. @@ -4520,11 +4520,11 @@ void DeleteStaleLinks(Station *from) if (ge.data != nullptr) ge.data->flows.DeleteFlows(to->index); RerouteCargo(from, c, to->index, from->index); } - } else if (edge.LastUnrestrictedUpdate() != INVALID_DATE && (uint)(_date - edge.LastUnrestrictedUpdate()) > timeout) { + } else if (edge.LastUnrestrictedUpdate() != INVALID_DATE && (_date - edge.LastUnrestrictedUpdate()) > timeout) { edge.Restrict(); if (ge.data != nullptr) ge.data->flows.RestrictFlows(to->index); RerouteCargo(from, c, to->index, from->index); - } else if (edge.LastRestrictedUpdate() != INVALID_DATE && (uint)(_date - edge.LastRestrictedUpdate()) > timeout) { + } else if (edge.LastRestrictedUpdate() != INVALID_DATE && (_date - edge.LastRestrictedUpdate()) > timeout) { edge.Release(); } @@ -4643,7 +4643,7 @@ void OnTick_Station() void StationDailyLoop() { // Only record cargo history every second day. - if (_date % 2 != 0) { + if (_date.base() % 2 != 0) { for (Station *st : Station::Iterate()) { st->UpdateCargoHistory(); } diff --git a/src/statusbar_gui.cpp b/src/statusbar_gui.cpp index 9d3a8a5a7b..83d30c1ade 100644 --- a/src/statusbar_gui.cpp +++ b/src/statusbar_gui.cpp @@ -59,7 +59,7 @@ struct StatusBarWindow : Window { int ticker_scroll; GUITimer ticker_timer; GUITimer reminder_timeout; - int64 last_minute = 0; + TickMinutes last_minute = 0; static const int TICKER_STOP = 1640; ///< scrolling is finished when counter reaches this value static const int REMINDER_START = 1350; ///< time in ms for reminder notification (red dot on the right) to stay @@ -211,9 +211,12 @@ struct StatusBarWindow : Window { { if (_pause_mode != PM_UNPAUSED) return; - if (_settings_time.time_in_minutes && this->last_minute != CURRENT_MINUTE) { - this->last_minute = CURRENT_MINUTE; - this->SetWidgetDirty(WID_S_LEFT); + if (_settings_time.time_in_minutes) { + const TickMinutes now = _settings_time.NowInTickMinutes(); + if (this->last_minute != now) { + this->last_minute = now; + this->SetWidgetDirty(WID_S_LEFT); + } } if (this->ticker_scroll < TICKER_STOP) { // Scrolling text diff --git a/src/stdafx.h b/src/stdafx.h index 57aec562c0..3564934c02 100644 --- a/src/stdafx.h +++ b/src/stdafx.h @@ -413,6 +413,7 @@ static_assert(SIZE_MAX >= UINT32_MAX); # define GetString OTTD_GetString # define DrawString OTTD_DrawString # define CloseConnection OTTD_CloseConnection +# define DateDelta OTTD_DateDelta #endif /* __APPLE__ */ #if defined(__GNUC__) || defined(__clang__) diff --git a/src/strings.cpp b/src/strings.cpp index 2846ad09e6..6531a5956f 100644 --- a/src/strings.cpp +++ b/src/strings.cpp @@ -454,16 +454,19 @@ static char *FormatBytes(char *buff, int64 number, const char *last) static char *FormatWallClockString(char *buff, DateTicksScaled ticks, const char *last, bool show_date, uint case_index) { - Minutes minutes = ticks / _settings_time.ticks_per_minute + _settings_time.clock_offset; + TickMinutes minutes = _settings_time.ToTickMinutes(ticks); char hour[3], minute[3]; - seprintf(hour, lastof(hour), "%02i", (int) MINUTES_HOUR(minutes) ); - seprintf(minute, lastof(minute), "%02i", (int) MINUTES_MINUTE(minutes)); + seprintf(hour, lastof(hour), "%02i", minutes.ClockHour()); + seprintf(minute, lastof(minute), "%02i", minutes.ClockMinute()); if (show_date) { - int64 final_arg = ScaledDateTicksToDate(ticks); + Date date = ScaledDateTicksToDate(ticks); + int64 final_arg; if (_settings_client.gui.date_with_time == 1) { YearMonthDay ymd; - ConvertDateToYMD(final_arg, &ymd); + ConvertDateToYMD(date, &ymd); final_arg = ymd.year; + } else { + final_arg = date.base(); } auto tmp_params = MakeParameters(hour, minute, final_arg); return FormatString(buff, GetStringPtr(STR_FORMAT_DATE_MINUTES + _settings_client.gui.date_with_time), tmp_params, last, case_index); diff --git a/src/strings_func.h b/src/strings_func.h index e8551074bd..7e2ceb8c68 100644 --- a/src/strings_func.h +++ b/src/strings_func.h @@ -94,9 +94,9 @@ WChar GetDecimalSeparatorChar(); * @param n Index of the string parameter. * @param v Value of the string parameter. */ -static inline void SetDParam(size_t n, uint64 v) -{ - _global_string_params.SetParam(n, v); +template +static inline void SetDParam(size_t n, T &&v) { + _global_string_params.SetParam(n, std::forward(v)); } void SetDParamMaxValue(size_t n, uint64 max_value, uint min_count = 0, FontSize size = FS_NORMAL); diff --git a/src/strings_internal.h b/src/strings_internal.h index 9037930235..496df1fdbf 100644 --- a/src/strings_internal.h +++ b/src/strings_internal.h @@ -13,6 +13,7 @@ #include "strings_func.h" #include "string_func.h" #include "core/span_type.hpp" +#include "core/strong_typedef_type.hpp" #include @@ -155,11 +156,11 @@ public: this->parameters[n].string_view = nullptr; } - //template ::value, int> = 0> - //void SetParam(size_t n, T v) - //{ - // SetParam(n, v.base()); - //} + template ::value, int> = 0> + void SetParam(size_t n, T v) + { + SetParam(n, v.base()); + } void SetParam(size_t n, const char *str) { diff --git a/src/table/newgrf_debug_data.h b/src/table/newgrf_debug_data.h index b63b2dd21c..163e90baaa 100644 --- a/src/table/newgrf_debug_data.h +++ b/src/table/newgrf_debug_data.h @@ -1428,7 +1428,7 @@ class NIHSignals : public NIHelper { if (it.second.IsOutOfDate()) { b += seprintf(b, lastof(buffer), ", expired"); } else { - b += seprintf(b, lastof(buffer), ", expires in %u ticks", (uint)(it.second.time_stamp - _scaled_date_ticks)); + b += seprintf(b, lastof(buffer), ", expires in %u ticks", (uint)(it.second.time_stamp - _scaled_date_ticks).base()); } output.print(buffer); } @@ -1532,7 +1532,7 @@ class NIHObject : public NIHelper { ConvertDateToYMD(spec->introduction_date, &ymd); char *b = buffer + seprintf(buffer, lastof(buffer), " intro: %4i-%02i-%02i", ymd.year, ymd.month + 1, ymd.day); - if (spec->end_of_life_date < MAX_DAY) { + if (spec->end_of_life_date < MAX_DATE) { ConvertDateToYMD(spec->end_of_life_date, &ymd); seprintf(b, lastof(buffer), ", end of life: %4i-%02i-%02i", ymd.year, ymd.month + 1, ymd.day); diff --git a/src/table/object_land.h b/src/table/object_land.h index 08639fc403..fe3b055369 100644 --- a/src/table/object_land.h +++ b/src/table/object_land.h @@ -121,7 +121,7 @@ static const DrawTileSprites _object_hq[] = { #undef TILE_SPRITE_LINE -#define M(name, size, build_cost_multiplier, clear_cost_multiplier, height, climate, gen_amount, flags) { GRFFilePropsBase<2>(), {0, 0, 0, 0}, INVALID_OBJECT_CLASS, name, climate, size, build_cost_multiplier, clear_cost_multiplier, 0, MAX_DAY + 1, flags, OBJECT_CTRL_FLAG_NONE, {0, 0, 0, 0}, 0, height, 1, gen_amount, OVMT_DEFAULT, 0 } +#define M(name, size, build_cost_multiplier, clear_cost_multiplier, height, climate, gen_amount, flags) { GRFFilePropsBase<2>(), {0, 0, 0, 0}, INVALID_OBJECT_CLASS, name, climate, size, build_cost_multiplier, clear_cost_multiplier, 0, MAX_DATE + 1, flags, OBJECT_CTRL_FLAG_NONE, {0, 0, 0, 0}, 0, height, 1, gen_amount, OVMT_DEFAULT, 0 } /* Climates * T = Temperate diff --git a/src/timetable_cmd.cpp b/src/timetable_cmd.cpp index 22f7db42c6..fab6b49cb9 100644 --- a/src/timetable_cmd.cpp +++ b/src/timetable_cmd.cpp @@ -863,8 +863,8 @@ void UpdateVehicleTimetable(Vehicle *v, bool travelling) if (slot > -1) { just_started = !HasBit(v->vehicle_flags, VF_TIMETABLE_STARTED); SetBit(v->vehicle_flags, VF_TIMETABLE_STARTED); - v->lateness_counter = _scaled_date_ticks - slot + wait_offset; - ds.SetScheduledDispatchLastDispatch(slot - ds.GetScheduledDispatchStartTick()); + v->lateness_counter = (_scaled_date_ticks - slot + wait_offset).AsTicks(); + ds.SetScheduledDispatchLastDispatch((slot - ds.GetScheduledDispatchStartTick()).AsTicks()); set_scheduled_dispatch = true; } } @@ -890,7 +890,7 @@ void UpdateVehicleTimetable(Vehicle *v, bool travelling) if (!set_scheduled_dispatch) just_started = !HasBit(v->vehicle_flags, VF_TIMETABLE_STARTED); if (v->timetable_start != 0) { - v->lateness_counter = (int32)(_scaled_date_ticks - v->timetable_start); + v->lateness_counter = (_scaled_date_ticks - v->timetable_start).AsTicks(); v->timetable_start = 0; } diff --git a/src/timetable_gui.cpp b/src/timetable_gui.cpp index 0b43c45b52..feecc2f832 100644 --- a/src/timetable_gui.cpp +++ b/src/timetable_gui.cpp @@ -198,7 +198,7 @@ static void FillTimetableArrivalDepartureTable(const Vehicle *v, VehicleOrderID DateTicksScaled slot = GetScheduledDispatchTime(predicted_ds, _scaled_date_ticks + sum + order->GetTimetabledWait()); predicted_ds.ReturnSchedule(ds); if (slot <= -1) return; - sum = slot - _scaled_date_ticks; + sum = (slot - _scaled_date_ticks).AsTicks(); predicted = true; no_offset = true; } else { @@ -239,7 +239,7 @@ static void FillTimetableArrivalDepartureTable(const Vehicle *v, VehicleOrderID */ static void ChangeTimetableStartIntl(uint32 p1, DateTicksScaled date) { - DoCommandPEx(0, p1, 0, (uint64)date, CMD_SET_TIMETABLE_START | CMD_MSG(STR_ERROR_CAN_T_TIMETABLE_VEHICLE), nullptr, nullptr, 0); + DoCommandPEx(0, p1, 0, (uint64)date.base(), CMD_SET_TIMETABLE_START | CMD_MSG(STR_ERROR_CAN_T_TIMETABLE_VEHICLE), nullptr, nullptr, 0); } /** @@ -906,12 +906,7 @@ struct TimetableWindow : GeneralVehicleWindow { if (_settings_time.time_in_minutes && _settings_client.gui.timetable_start_text_entry) { this->set_start_date_all = v->orders->IsCompleteTimetable() && _ctrl_pressed; StringID str = STR_JUST_INT; - uint64 time = _scaled_date_ticks; - time /= _settings_time.ticks_per_minute; - time += _settings_time.clock_offset; - time %= (24 * 60); - time = (time % 60) + (((time / 60) % 24) * 100); - SetDParam(0, time); + SetDParam(0, _settings_time.NowInTickMinutes().ClockHHMM()); ShowQueryString(str, STR_TIMETABLE_STARTING_DATE, 31, this, CS_NUMERAL, QSF_ACCEPT_UNCHANGED); } else { ShowSetDateWindow(this, v->index | (_ctrl_pressed ? 1U << 20 : 0), @@ -1123,12 +1118,12 @@ struct TimetableWindow : GeneralVehicleWindow { if (val >= 0 && end && *end == 0) { uint minutes = (val % 100) % 60; uint hours = (val / 100) % 24; - DateTicksScaled time = MINUTES_DATE(MINUTES_DAY(CURRENT_MINUTE), hours, minutes); - time -= _settings_time.clock_offset; + const TickMinutes now = _settings_time.NowInTickMinutes(); + TickMinutes time = now.ToSameDayClockTime(hours, minutes); - if (time < (CURRENT_MINUTE - 60)) time += 60 * 24; - time *= _settings_time.ticks_per_minute; - ChangeTimetableStartIntl(v->index | (this->set_start_date_all ? 1 << 20 : 0), time); + if (time < (now - 60)) time += 60 * 24; + + ChangeTimetableStartIntl(v->index | (this->set_start_date_all ? 1 << 20 : 0), _settings_time.FromTickMinutes(time)); } break; } diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp index 6b6b2b3edf..23ee6387b9 100644 --- a/src/town_cmd.cpp +++ b/src/town_cmd.cpp @@ -1033,7 +1033,7 @@ RoadType GetTownRoadType() if (HasBit(rti->extra_flags, RXTF_NO_TOWN_MODIFICATION)) continue; /* Not yet introduced at this date. */ - if (IsInsideMM(rti->introduction_date, 0, MAX_DAY) && rti->introduction_date > _date) continue; + if (IsInsideMM(rti->introduction_date, 0, MAX_DATE.base()) && rti->introduction_date > _date) continue; if (best != nullptr) { if ((rti->max_speed == 0 ? assume_max_speed : rti->max_speed) < (best->max_speed == 0 ? assume_max_speed : best->max_speed)) continue; diff --git a/src/tracerestrict.cpp b/src/tracerestrict.cpp index 1cb5e529eb..ada6aef001 100644 --- a/src/tracerestrict.cpp +++ b/src/tracerestrict.cpp @@ -2371,17 +2371,17 @@ CommandCost CmdProgramSignalTraceRestrictProgMgmt(TileIndex tile, DoCommandFlag int GetTraceRestrictTimeDateValue(TraceRestrictTimeDateValueField type) { - Minutes minutes = (_scaled_date_ticks / _settings_game.game_time.ticks_per_minute) + _settings_game.game_time.clock_offset; + const TickMinutes now = _settings_game.game_time.NowInTickMinutes(); switch (type) { case TRTDVF_MINUTE: - return MINUTES_MINUTE(minutes); + return now.ClockMinute(); case TRTDVF_HOUR: - return MINUTES_HOUR(minutes); + return now.ClockHour(); case TRTDVF_HOUR_MINUTE: - return (MINUTES_HOUR(minutes) * 100) + MINUTES_MINUTE(minutes); + return now.ClockHHMM(); case TRTDVF_DAY: return _cur_date_ymd.day; @@ -2396,17 +2396,17 @@ int GetTraceRestrictTimeDateValue(TraceRestrictTimeDateValueField type) int GetTraceRestrictTimeDateValueFromDate(TraceRestrictTimeDateValueField type, DateTicksScaled scaled_date_ticks) { - Minutes minutes = (scaled_date_ticks / _settings_game.game_time.ticks_per_minute) + _settings_game.game_time.clock_offset; + const TickMinutes minutes = _settings_game.game_time.ToTickMinutes(scaled_date_ticks); switch (type) { case TRTDVF_MINUTE: - return MINUTES_MINUTE(minutes); + return minutes.ClockMinute(); case TRTDVF_HOUR: - return MINUTES_HOUR(minutes); + return minutes.ClockHour(); case TRTDVF_HOUR_MINUTE: - return (MINUTES_HOUR(minutes) * 100) + MINUTES_MINUTE(minutes); + return minutes.ClockHHMM(); case TRTDVF_DAY: { YearMonthDay ymd; diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index 3f72c7f304..4b70599b9e 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -120,7 +120,7 @@ void ClearAllSignalSpeedRestrictions() _signal_speeds.clear(); } -void AdjustAllSignalSpeedRestrictionTickValues(DateTicksScaled delta) +void AdjustAllSignalSpeedRestrictionTickValues(DateTicksScaledDelta delta) { for (auto &it : _signal_speeds) { it.second.time_stamp += delta; @@ -7558,15 +7558,15 @@ int GetTrainEstimatedMaxAchievableSpeed(const Train *train, int mass, const int void SetSignalTrainAdaptationSpeed(const Train *v, TileIndex tile, uint16 track) { - SignalSpeedKey speed_key = { - speed_key.signal_tile = tile, - speed_key.signal_track = track, - speed_key.last_passing_train_dir = v->GetVehicleTrackdir() - }; - SignalSpeedValue speed_value = { - speed_value.train_speed = v->First()->cur_speed, - speed_value.time_stamp = GetSpeedRestrictionTimeout(v->First()) - }; + SignalSpeedKey speed_key = {}; + speed_key.signal_tile = tile; + speed_key.signal_track = track; + speed_key.last_passing_train_dir = v->GetVehicleTrackdir(); + + SignalSpeedValue speed_value = {}; + speed_value.train_speed = v->First()->cur_speed; + speed_value.time_stamp = GetSpeedRestrictionTimeout(v->First()); + _signal_speeds[speed_key] = speed_value; } diff --git a/src/vehicle.cpp b/src/vehicle.cpp index e49225052a..2ac6d3ba7b 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -2418,16 +2418,16 @@ void AgeVehicle(Vehicle *v) /* Stop if a virtual vehicle */ if (HasBit(v->subtype, GVSF_VIRTUAL)) return; - if (v->age < MAX_DAY) { + if (v->age < MAX_DATE.AsDelta()) { v->age++; if (v->IsPrimaryVehicle() && v->age == VEHICLE_PROFIT_MIN_AGE + 1) GroupStatistics::VehicleReachedMinAge(v); } if (!v->IsPrimaryVehicle() && (v->type != VEH_TRAIN || !Train::From(v)->IsEngine())) return; - int age = v->age - v->max_age; + DateDelta age = v->age - v->max_age; for (int i = 0; i <= 4; i++) { - if (age == DateAtStartOfYear(i)) { + if (age == DateAtStartOfYear(i).AsDelta()) { v->reliability_spd_dec <<= 1; break; } @@ -4649,7 +4649,7 @@ void DumpVehicleStats(char *buffer, const char *last) buffer += seprintf(buffer, last, " %10s: %5u\n", "total", (uint)Vehicle::GetNumItems()); } -void AdjustVehicleScaledTickBase(int64 delta) +void AdjustVehicleScaledTickBase(DateTicksScaledDelta delta) { for (Vehicle *v : Vehicle::Iterate()) { if (v->timetable_start != 0) v->timetable_start += delta; @@ -4662,10 +4662,10 @@ void AdjustVehicleScaledTickBase(int64 delta) } } -void ShiftVehicleDates(int interval) +void ShiftVehicleDates(DateDelta interval) { for (Vehicle *v : Vehicle::Iterate()) { - v->date_of_last_service = std::max(v->date_of_last_service + interval, 0); + v->date_of_last_service = std::max(v->date_of_last_service + interval, 0); } /* date_of_last_service_newgrf is not updated here as it must stay stable * for vehicles outside of a depot. */ diff --git a/src/vehicle_base.h b/src/vehicle_base.h index 19553b0ea5..b79f6439ba 100644 --- a/src/vehicle_base.h +++ b/src/vehicle_base.h @@ -317,8 +317,8 @@ public: /* Related to age and service time */ Year build_year; ///< Year the vehicle has been built. - Date age; ///< Age in days - Date max_age; ///< Maximum age + DateDelta age; ///< Age in days + DateDelta max_age; ///< Maximum age Date date_of_last_service; ///< Last date the vehicle had a service at a depot. Date date_of_last_service_newgrf; ///< Last date the vehicle had a service at a depot, unchanged by the date cheat to protect against unsafe NewGRF behavior. uint16 reliability; ///< Reliability. @@ -1536,6 +1536,6 @@ void ClearVehicleTickCaches(); void RemoveFromOtherVehicleTickCache(const Vehicle *v); void UpdateAllVehiclesIsDrawn(); -void ShiftVehicleDates(int interval); +void ShiftVehicleDates(DateDelta interval); #endif /* VEHICLE_BASE_H */ diff --git a/src/vehicle_func.h b/src/vehicle_func.h index 5df1f5159d..2d7db2fbb2 100644 --- a/src/vehicle_func.h +++ b/src/vehicle_func.h @@ -26,7 +26,7 @@ #define IS_CUSTOM_FIRSTHEAD_SPRITE(x) (x == 0xFD) #define IS_CUSTOM_SECONDHEAD_SPRITE(x) (x == 0xFE) -static const int VEHICLE_PROFIT_MIN_AGE = DAYS_IN_YEAR * 2; ///< Only vehicles older than this have a meaningful profit. +static constexpr DateDelta VEHICLE_PROFIT_MIN_AGE = DAYS_IN_YEAR * 2; ///< Only vehicles older than this have a meaningful profit. static const Money VEHICLE_PROFIT_THRESHOLD = 10000; ///< Threshold for a vehicle to be considered making good profit. struct Viewport; diff --git a/src/vehicle_gui.cpp b/src/vehicle_gui.cpp index 3d45f09987..17df9f9456 100644 --- a/src/vehicle_gui.cpp +++ b/src/vehicle_gui.cpp @@ -457,7 +457,7 @@ void DepotSortList(VehicleList *list) } /** draw the vehicle profit button in the vehicle list window. */ -static void DrawVehicleProfitButton(Date age, Money display_profit_last_year, uint num_vehicles, int x, int y) +static void DrawVehicleProfitButton(DateDelta age, Money display_profit_last_year, uint num_vehicles, int x, int y) { SpriteID spr; @@ -1882,8 +1882,8 @@ void BaseVehicleListWindow::DrawVehicleListItems(VehicleID selected_vehicle, int switch (this->vehgroups.SortType()) { case VST_AGE: { str = (v->age + DAYS_IN_YEAR < v->max_age) ? STR_VEHICLE_LIST_AGE : STR_VEHICLE_LIST_AGE_RED; - SetDParam(3, v->age / DAYS_IN_LEAP_YEAR); - SetDParam(4, v->max_age / DAYS_IN_LEAP_YEAR); + SetDParam(3, DateDeltaToYears(v->age)); + SetDParam(4, DateDeltaToYears(v->max_age)); break; } @@ -1938,7 +1938,7 @@ void BaseVehicleListWindow::DrawVehicleListItems(VehicleID selected_vehicle, int case VST_TIME_TO_LIVE: { auto years_remaining = (v->max_age / DAYS_IN_LEAP_YEAR) - (v->age / DAYS_IN_LEAP_YEAR); str = (years_remaining > 1) ? STR_VEHICLE_LIST_TIME_TO_LIVE : ((years_remaining < 0) ? STR_VEHICLE_LIST_TIME_TO_LIVE_OVERDUE : STR_VEHICLE_LIST_TIME_TO_LIVE_RED); - SetDParam(3, std::abs(years_remaining)); + SetDParam(3, std::abs(years_remaining.base())); break; } @@ -3079,9 +3079,9 @@ struct VehicleDetailsWindow : Window { Rect tr = r.Shrink(WidgetDimensions::scaled.framerect); /* Draw running cost */ - SetDParam(1, DateToYear(v->age)); + SetDParam(1, DateDeltaToYears(v->age)); SetDParam(0, (v->age + DAYS_IN_YEAR < v->max_age) ? STR_VEHICLE_INFO_AGE : STR_VEHICLE_INFO_AGE_RED); - SetDParam(2, DateToYear(v->max_age)); + SetDParam(2, DateDeltaToYears(v->max_age)); SetDParam(3, v->GetDisplayRunningCost()); DrawString(tr, STR_VEHICLE_INFO_AGE_RUNNING_COST_YR); tr.top += GetCharacterHeight(FS_NORMAL); diff --git a/src/vehicle_gui_base.h b/src/vehicle_gui_base.h index 482898fe8b..dcdb7ffb9d 100644 --- a/src/vehicle_gui_base.h +++ b/src/vehicle_gui_base.h @@ -55,7 +55,7 @@ struct GUIVehicleGroup { }); } - Date GetOldestVehicleAge() const + DateDelta GetOldestVehicleAge() const { const Vehicle *oldest = *std::max_element(this->vehicles_begin, this->vehicles_end, [](const Vehicle *v_a, const Vehicle *v_b) { return v_a->age < v_b->age;