Strong typedef: Use strong typedefs for date, date tick, minutes types
Add delta types Adjust/add type conversion functions Add various utility methods on types Remove the various minute macros Fix some minute conversion inconsistencies
This commit is contained in:
@@ -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) {
|
if (e->type != VEH_TRAIN || e->u.rail.railveh_type != RAILVEH_WAGON) {
|
||||||
/* Design date - Life length */
|
/* Design date - Life length */
|
||||||
SetDParam(0, ymd.year);
|
SetDParam(0, ymd.year);
|
||||||
SetDParam(1, DateToYear(e->GetLifeLengthInDays()));
|
SetDParam(1, DateDeltaToYears(e->GetLifeLengthInDays()));
|
||||||
DrawString(left, right, y, STR_PURCHASE_INFO_DESIGNED_LIFE);
|
DrawString(left, right, y, STR_PURCHASE_INFO_DESIGNED_LIFE);
|
||||||
y += GetCharacterHeight(FS_NORMAL);
|
y += GetCharacterHeight(FS_NORMAL);
|
||||||
|
|
||||||
|
@@ -1173,7 +1173,7 @@ CommandCost DoCommandPInternal(TileIndex tile, uint32 p1, uint32 p2, uint64 p3,
|
|||||||
if (!random_state.Check()) {
|
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)",
|
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));
|
(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));
|
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
|
/* Log the failed command as well. Just to be able to be find
|
||||||
* causes of desyncs due to bad command test implementations. */
|
* 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)",
|
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();
|
cur_company.Restore();
|
||||||
return_dcpi(res);
|
return_dcpi(res);
|
||||||
@@ -1212,7 +1212,7 @@ CommandCost DoCommandPInternal(TileIndex tile, uint32 p1, uint32 p2, uint64 p3,
|
|||||||
return_dcpi(CommandCost());
|
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)",
|
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
|
/* Actually try and execute the command. If no cost-type is given
|
||||||
* use the construction one */
|
* use the construction one */
|
||||||
|
@@ -949,7 +949,7 @@ CommandCost CmdCompanyCtrl(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
|
|||||||
}
|
}
|
||||||
|
|
||||||
NetworkServerNewCompany(c, ci);
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -967,7 +967,7 @@ CommandCost CmdCompanyCtrl(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
|
|||||||
Company *c = DoStartupNewCompany(DSNC_AI, company_id);
|
Company *c = DoStartupNewCompany(DSNC_AI, company_id);
|
||||||
if (c != nullptr) {
|
if (c != nullptr) {
|
||||||
NetworkServerNewCompany(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;
|
break;
|
||||||
}
|
}
|
||||||
@@ -984,7 +984,7 @@ CommandCost CmdCompanyCtrl(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
|
|||||||
|
|
||||||
if (!(flags & DC_EXEC)) return CommandCost();
|
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);
|
CompanyNewsInformation *cni = new CompanyNewsInformation(c);
|
||||||
|
|
||||||
|
@@ -1876,7 +1876,7 @@ struct CompanyInfrastructureWindow : Window
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Get the date introduced railtypes as well. */
|
/* 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. */
|
/* Find the used roadtypes. */
|
||||||
for (const Engine *e : Engine::IterateType(VEH_ROAD)) {
|
for (const Engine *e : Engine::IterateType(VEH_ROAD)) {
|
||||||
@@ -1886,7 +1886,7 @@ struct CompanyInfrastructureWindow : Window
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Get the date introduced roadtypes as well. */
|
/* 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;
|
this->roadtypes &= ~_roadtypes_hidden_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -2490,7 +2490,7 @@ DEF_CONSOLE_CMD(ConMergeLinkgraphJobsAsap)
|
|||||||
return true;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2739,14 +2739,14 @@ DEF_CONSOLE_CMD(ConDumpLinkgraphJobs)
|
|||||||
IConsolePrintF(CC_DEFAULT, PRINTF_SIZE " link graph jobs", LinkGraphJob::GetNumItems());
|
IConsolePrintF(CC_DEFAULT, PRINTF_SIZE " link graph jobs", LinkGraphJob::GetNumItems());
|
||||||
for (const LinkGraphJob *lgj : LinkGraphJob::Iterate()) {
|
for (const LinkGraphJob *lgj : LinkGraphJob::Iterate()) {
|
||||||
YearMonthDay start_ymd;
|
YearMonthDay start_ymd;
|
||||||
ConvertDateToYMD(lgj->StartDateTicks() / DAY_TICKS, &start_ymd);
|
ConvertDateToYMD(lgj->StartDateTicks().ToDate(), &start_ymd);
|
||||||
YearMonthDay join_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",
|
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->index, lgj->Graph().Size(), lgj->Graph().CalculateCostEstimate(),
|
||||||
lgj->StartDateTicks(), start_ymd.year, start_ymd.month + 1, start_ymd.day, lgj->StartDateTicks() % DAY_TICKS,
|
lgj->StartDateTicks().base(), start_ymd.year, start_ymd.month + 1, start_ymd.day, lgj->StartDateTicks().ToDateFractRemainder(),
|
||||||
lgj->JoinDateTicks(), join_ymd.year, join_ymd.month + 1, join_ymd.day, lgj->JoinDateTicks() % DAY_TICKS,
|
lgj->JoinDateTicks().base(), join_ymd.year, join_ymd.month + 1, join_ymd.day, lgj->JoinDateTicks().ToDateFractRemainder(),
|
||||||
lgj->JoinDateTicks() - lgj->StartDateTicks());
|
(lgj->JoinDateTicks() - lgj->StartDateTicks()).base());
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -3686,20 +3686,20 @@ DEF_CONSOLE_CMD(ConIfDay)
|
|||||||
|
|
||||||
DEF_CONSOLE_CMD(ConIfHour)
|
DEF_CONSOLE_CMD(ConIfHour)
|
||||||
{
|
{
|
||||||
Minutes minutes = _scaled_date_ticks / _settings_time.ticks_per_minute + _settings_time.clock_offset;
|
TickMinutes minutes = _settings_time.NowInTickMinutes();
|
||||||
return ConConditionalCommon(argc, argv, MINUTES_HOUR(minutes), "the current hour (in game, assuming time is in minutes)", "if_hour");
|
return ConConditionalCommon(argc, argv, minutes.ClockHour(), "the current hour (in game, assuming time is in minutes)", "if_hour");
|
||||||
}
|
}
|
||||||
|
|
||||||
DEF_CONSOLE_CMD(ConIfMinute)
|
DEF_CONSOLE_CMD(ConIfMinute)
|
||||||
{
|
{
|
||||||
Minutes minutes = _scaled_date_ticks / _settings_time.ticks_per_minute + _settings_time.clock_offset;
|
TickMinutes minutes = _settings_time.NowInTickMinutes();
|
||||||
return ConConditionalCommon(argc, argv, MINUTES_MINUTE(minutes), "the current minute (in game, assuming time is in minutes)", "if_minute");
|
return ConConditionalCommon(argc, argv, minutes.ClockMinute(), "the current minute (in game, assuming time is in minutes)", "if_minute");
|
||||||
}
|
}
|
||||||
|
|
||||||
DEF_CONSOLE_CMD(ConIfHourMinute)
|
DEF_CONSOLE_CMD(ConIfHourMinute)
|
||||||
{
|
{
|
||||||
Minutes minutes = _scaled_date_ticks / _settings_time.ticks_per_minute + _settings_time.clock_offset;
|
TickMinutes minutes = _settings_time.NowInTickMinutes();
|
||||||
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");
|
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
|
#ifdef _DEBUG
|
||||||
|
@@ -44,7 +44,7 @@ inline bool ShouldLogUpdateStateChecksum()
|
|||||||
return _networking && (!_network_server || (NetworkClientSocket::IsValidID(0) && NetworkClientSocket::Get(0)->status != NetworkClientSocket::STATUS_INACTIVE));
|
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, \
|
# 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
|
#else
|
||||||
# define DEBUG_UPDATESTATECHECKSUM(str, ...)
|
# define DEBUG_UPDATESTATECHECKSUM(str, ...)
|
||||||
#endif /* RANDOM_DEBUG */
|
#endif /* RANDOM_DEBUG */
|
||||||
|
@@ -72,7 +72,7 @@ void SetRandomSeed(uint32 seed)
|
|||||||
uint32 DoRandom(int line, const char *file)
|
uint32 DoRandom(int line, const char *file)
|
||||||
{
|
{
|
||||||
if (_networking && (!_network_server || (NetworkClientSocket::IsValidID(0) && NetworkClientSocket::Get(0)->status != NetworkClientSocket::STATUS_INACTIVE))) {
|
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();
|
return _random.Next();
|
||||||
|
20
src/date.cpp
20
src/date.cpp
@@ -44,15 +44,15 @@ extern void ClearOutOfDateSignalSpeedRestrictions();
|
|||||||
|
|
||||||
void CheckScaledDateTicksWrap()
|
void CheckScaledDateTicksWrap()
|
||||||
{
|
{
|
||||||
DateTicksScaled tick_adjust = 0;
|
DateTicksScaledDelta tick_adjust = 0;
|
||||||
auto get_tick_adjust = [&](DateTicksScaled target) {
|
auto get_tick_adjust = [&](DateTicksScaled target) {
|
||||||
int32 rounding = _settings_time.time_in_minutes * 1440;
|
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)) {
|
if (_scaled_date_ticks >= ((int64)1 << 60)) {
|
||||||
tick_adjust = get_tick_adjust(_scaled_date_ticks);
|
tick_adjust = get_tick_adjust(_scaled_date_ticks);
|
||||||
} else if (_scaled_date_ticks <= -((int64)1 << 60)) {
|
} 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 {
|
} else {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -60,13 +60,13 @@ void CheckScaledDateTicksWrap()
|
|||||||
_scaled_date_ticks_offset -= tick_adjust;
|
_scaled_date_ticks_offset -= tick_adjust;
|
||||||
_scaled_date_ticks -= tick_adjust;
|
_scaled_date_ticks -= tick_adjust;
|
||||||
|
|
||||||
extern void AdjustAllSignalSpeedRestrictionTickValues(DateTicksScaled delta);
|
extern void AdjustAllSignalSpeedRestrictionTickValues(DateTicksScaledDelta delta);
|
||||||
AdjustAllSignalSpeedRestrictionTickValues(-tick_adjust);
|
AdjustAllSignalSpeedRestrictionTickValues(-tick_adjust);
|
||||||
|
|
||||||
extern void AdjustVehicleScaledTickBase(int64 delta);
|
extern void AdjustVehicleScaledTickBase(DateTicksScaledDelta delta);
|
||||||
AdjustVehicleScaledTickBase(-tick_adjust);
|
AdjustVehicleScaledTickBase(-tick_adjust);
|
||||||
|
|
||||||
extern void AdjustLinkGraphScaledTickBase(int64 delta);
|
extern void AdjustLinkGraphScaledTickBase(DateTicksScaledDelta delta);
|
||||||
AdjustLinkGraphScaledTickBase(-tick_adjust);
|
AdjustLinkGraphScaledTickBase(-tick_adjust);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,7 +106,7 @@ void SetDate(Date date, DateFract fract, bool preserve_scaled_ticks)
|
|||||||
|
|
||||||
void SetScaledTickVariables()
|
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)
|
#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 */
|
/* There are 97 leap years in 400 years */
|
||||||
Year yr = 400 * (date / (DAYS_IN_YEAR * 400 + 97));
|
Year yr = 400 * (date.base() / (DAYS_IN_YEAR * 400 + 97));
|
||||||
int rem = date % (DAYS_IN_YEAR * 400 + 97);
|
int rem = date.base() % (DAYS_IN_YEAR * 400 + 97);
|
||||||
uint16 x;
|
uint16 x;
|
||||||
|
|
||||||
if (rem >= DAYS_IN_YEAR * 100 + 25) {
|
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 */
|
/* Account for the missing of the 29th of February in non-leap years */
|
||||||
if (!IsLeapYear(year) && days >= ACCUM_MAR) days--;
|
if (!IsLeapYear(year) && days >= ACCUM_MAR) days--;
|
||||||
|
|
||||||
return DAYS_TILL(year) + days;
|
return DateAtStartOfYear(year) + days;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Functions used by the IncreaseDate function */
|
/** Functions used by the IncreaseDate function */
|
||||||
|
@@ -38,7 +38,7 @@ inline Date ConvertYMDToDate(const YearMonthDay &ymd)
|
|||||||
return ConvertYMDToDate(ymd.year, ymd.month, ymd.day);
|
return ConvertYMDToDate(ymd.year, ymd.month, ymd.day);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define _cur_year (static_cast<Year>(_cur_date_ymd.year))
|
#define _cur_year (_cur_date_ymd.year)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether the given year is a leap year or not.
|
* 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)
|
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)
|
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)
|
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)
|
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)
|
static constexpr Year DateToYear(Date date)
|
||||||
{
|
{
|
||||||
return date / DAYS_IN_LEAP_YEAR;
|
return date.base() / DAYS_IN_LEAP_YEAR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
static constexpr Year DateDeltaToYears(DateDelta date)
|
||||||
* Calculate the date of the first day of a given year.
|
|
||||||
* @param year the year to get the first day of.
|
|
||||||
* @return the date.
|
|
||||||
*/
|
|
||||||
static constexpr Date DateAtStartOfYear(Year year)
|
|
||||||
{
|
{
|
||||||
int32 year_as_int = year;
|
return date.base() / DAYS_IN_LEAP_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. */
|
static constexpr DateTicks DateToDateTicks(Date date, DateFract fract = 0)
|
||||||
return (365 * year_as_int) + number_of_leap_years;
|
{
|
||||||
|
return (date.base() * DAY_TICKS) + fract;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 */
|
#endif /* DATE_FUNC_H */
|
||||||
|
@@ -181,13 +181,13 @@ struct SetDateWindow : Window {
|
|||||||
|
|
||||||
struct SetMinutesWindow : SetDateWindow
|
struct SetMinutesWindow : SetDateWindow
|
||||||
{
|
{
|
||||||
Minutes minutes;
|
TickMinutes minutes;
|
||||||
|
|
||||||
/** Constructor. */
|
/** Constructor. */
|
||||||
SetMinutesWindow(WindowDesc *desc, WindowNumber window_number, Window *parent, DateTicksScaled initial_date, Year min_year, Year max_year,
|
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) :
|
SetDateCallback *callback, StringID button_text, StringID button_tooltip) :
|
||||||
SetDateWindow(desc, window_number, parent, initial_date, min_year, max_year, callback, button_text, button_tooltip),
|
SetDateWindow(desc, window_number, parent, 0, min_year, max_year, callback, button_text, button_tooltip),
|
||||||
minutes(initial_date / _settings_time.ticks_per_minute)
|
minutes(_settings_time.ToTickMinutes(initial_date))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -208,7 +208,7 @@ struct SetMinutesWindow : SetDateWindow
|
|||||||
SetDParam(0, i);
|
SetDParam(0, i);
|
||||||
list.emplace_back(new DropDownListStringItem(STR_JUST_INT, i, false));
|
list.emplace_back(new DropDownListStringItem(STR_JUST_INT, i, false));
|
||||||
}
|
}
|
||||||
selected = MINUTES_MINUTE(minutes);
|
selected = this->minutes.ClockMinute();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WID_SD_MONTH:
|
case WID_SD_MONTH:
|
||||||
@@ -216,7 +216,7 @@ struct SetMinutesWindow : SetDateWindow
|
|||||||
SetDParam(0, i);
|
SetDParam(0, i);
|
||||||
list.emplace_back(new DropDownListStringItem(STR_JUST_INT, i, false));
|
list.emplace_back(new DropDownListStringItem(STR_JUST_INT, i, false));
|
||||||
}
|
}
|
||||||
selected = MINUTES_HOUR(minutes);
|
selected = this->minutes.ClockHour();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -253,8 +253,8 @@ struct SetMinutesWindow : SetDateWindow
|
|||||||
virtual void SetStringParameters(int widget) const override
|
virtual void SetStringParameters(int widget) const override
|
||||||
{
|
{
|
||||||
switch (widget) {
|
switch (widget) {
|
||||||
case WID_SD_DAY: SetDParam(0, MINUTES_MINUTE(minutes)); break;
|
case WID_SD_DAY: SetDParam(0, this->minutes.ClockMinute()); break;
|
||||||
case WID_SD_MONTH: SetDParam(0, MINUTES_HOUR(minutes)); break;
|
case WID_SD_MONTH: SetDParam(0, this->minutes.ClockHour()); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -269,7 +269,7 @@ struct SetMinutesWindow : SetDateWindow
|
|||||||
|
|
||||||
case WID_SD_SET_DATE:
|
case WID_SD_SET_DATE:
|
||||||
if (this->callback != nullptr) {
|
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();
|
this->Close();
|
||||||
break;
|
break;
|
||||||
@@ -278,19 +278,23 @@ struct SetMinutesWindow : SetDateWindow
|
|||||||
|
|
||||||
virtual void OnDropdownSelect(int widget, int index) override
|
virtual void OnDropdownSelect(int widget, int index) override
|
||||||
{
|
{
|
||||||
Minutes current = 0;
|
const TickMinutes now = _settings_time.NowInTickMinutes();
|
||||||
|
TickMinutes current = 0;
|
||||||
switch (widget) {
|
switch (widget) {
|
||||||
case WID_SD_DAY:
|
case WID_SD_DAY:
|
||||||
current = MINUTES_DATE(MINUTES_DAY(CURRENT_MINUTE), MINUTES_HOUR(minutes), index);
|
current = now.ToSameDayClockTime(now.ClockHour(), index);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WID_SD_MONTH:
|
case WID_SD_MONTH:
|
||||||
current = MINUTES_DATE(MINUTES_DAY(CURRENT_MINUTE), index, MINUTES_MINUTE(minutes));
|
current = now.ToSameDayClockTime(index, now.ClockMinute());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (current < (CURRENT_MINUTE - 60)) current += 60 * 24;
|
if (current < (now - 60)) current += 60 * 24;
|
||||||
minutes = current;
|
this->minutes = current;
|
||||||
|
|
||||||
this->SetDirty();
|
this->SetDirty();
|
||||||
}
|
}
|
||||||
|
173
src/date_type.h
173
src/date_type.h
@@ -10,16 +10,8 @@
|
|||||||
#ifndef DATE_TYPE_H
|
#ifndef DATE_TYPE_H
|
||||||
#define DATE_TYPE_H
|
#define DATE_TYPE_H
|
||||||
|
|
||||||
typedef int32 Date; ///< The type to store our dates in
|
#include "core/strong_typedef_type.hpp"
|
||||||
typedef uint16 DateFract; ///< The fraction of a date we're in, i.e. the number of ticks since the last date changeover
|
#include "core/math_func.hpp"
|
||||||
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.
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 1 day is 74 ticks; _date_fract used to be uint16 and incremented by 885. On
|
* 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
|
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<int32_t, struct DateDeltaTag, StrongType::Compare, StrongType::IntegerScalable>;
|
||||||
|
using Date = StrongType::Typedef<int32_t, struct DateTag, StrongType::Compare, StrongType::IntegerDelta<DateDelta>>;
|
||||||
|
|
||||||
|
/* Mixin for DateTicks */
|
||||||
|
struct DateTicksOperations {
|
||||||
|
template <typename TType, typename TBaseType>
|
||||||
|
struct mixin {
|
||||||
|
private:
|
||||||
|
TBaseType GetBase() const { return static_cast<const TType &>(*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<int32_t, struct DateTicksDeltaTag, StrongType::Compare, StrongType::IntegerScalable>;
|
||||||
|
using DateTicks = StrongType::Typedef<int32_t, struct DateTicksTag, StrongType::Compare, StrongType::IntegerDelta<DateTicksDelta>, DateTicksOperations>;
|
||||||
|
|
||||||
|
/* Mixin for DateTicksScaledDelta */
|
||||||
|
struct DateTicksScaledDeltaOperations {
|
||||||
|
template <typename TType, typename TBaseType>
|
||||||
|
struct mixin {
|
||||||
|
private:
|
||||||
|
TBaseType GetBase() const { return static_cast<const TType &>(*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<int64_t, struct DateTicksScaledDeltaTag, StrongType::Compare, StrongType::IntegerScalable, DateTicksScaledDeltaOperations>;
|
||||||
|
using DateTicksScaled = StrongType::Typedef<int64_t, struct DateTicksScaledTag, StrongType::Compare, StrongType::IntegerDelta<DateTicksScaledDelta>>;
|
||||||
|
|
||||||
|
/* Mixin for TickMinutes, ClockFaceMinutes */
|
||||||
|
struct MinuteOperations {
|
||||||
|
template <typename TType, typename TBaseType>
|
||||||
|
struct mixin {
|
||||||
|
private:
|
||||||
|
TBaseType GetBase() const { return static_cast<const TType &>(*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 <typename TType, typename TBaseType>
|
||||||
|
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<int, struct ClockFaceMinutesTag, StrongType::Compare, StrongType::Integer, MinuteOperations, ClockFaceMinuteOperations>;
|
||||||
|
|
||||||
|
/* Mixin for TickMinutes */
|
||||||
|
struct TickMinuteOperations {
|
||||||
|
template <typename TType, typename TBaseType>
|
||||||
|
struct mixin {
|
||||||
|
private:
|
||||||
|
TBaseType GetBase() const { return static_cast<const TType &>(*this).base(); }
|
||||||
|
|
||||||
|
public:
|
||||||
|
TType ToSameDayClockTime(int hour, int minute) const
|
||||||
|
{
|
||||||
|
TBaseType day = DivTowardsNegativeInf<TBaseType>(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<int64_t, struct TickMinutesTag, StrongType::Compare, StrongType::Integer, MinuteOperations, TickMinuteOperations>;
|
||||||
|
|
||||||
#define DATE_UNIT_SIZE (_settings_time.time_in_minutes ? _settings_time.ticks_per_minute : (DAY_TICKS * _settings_game.economy.day_length_factor))
|
#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
|
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 */
|
/** 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 */
|
/** 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 */
|
/** The maximum year of the original TTD */
|
||||||
static const Year ORIGINAL_MAX_YEAR = 2090;
|
static constexpr 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)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate the date of the first day of a given year.
|
* Calculate the date of the first day of a given year.
|
||||||
* @param year the year to get the first day of.
|
* @param year the year to get the first day of.
|
||||||
* @return the date.
|
* @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
|
* The offset in days from the '_date == 0' till
|
||||||
* 'ConvertYMDToDate(ORIGINAL_BASE_YEAR, 0, 1)'
|
* '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 */
|
/** The absolute minimum & maximum years in OTTD */
|
||||||
static const Year MIN_YEAR = 0;
|
static constexpr Year MIN_YEAR = 0;
|
||||||
|
|
||||||
/** The default starting year */
|
/** The default starting year */
|
||||||
static const Year DEF_START_YEAR = 1950;
|
static constexpr Year DEF_START_YEAR = 1950;
|
||||||
/** The default scoring end year */
|
/** 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
|
* 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;
|
static const Year MAX_YEAR = 5000000;
|
||||||
|
|
||||||
/** The number of days till the last day */
|
/** The number of days till the last day */
|
||||||
#define MAX_DAY (DAYS_TILL(MAX_YEAR + 1) - 1)
|
static constexpr Date MAX_DATE = DateAtStartOfYear(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)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Data structure to convert between Date and triplet (year, month, and day).
|
* Data structure to convert between Date and triplet (year, month, and day).
|
||||||
@@ -129,8 +197,9 @@ struct YearMonthDay {
|
|||||||
Day day; ///< Day (1..31)
|
Day day; ///< Day (1..31)
|
||||||
};
|
};
|
||||||
|
|
||||||
static const Year INVALID_YEAR = -1; ///< Representation of an invalid year
|
static constexpr Year INVALID_YEAR = -1; ///< Representation of an invalid year
|
||||||
static const Date INVALID_DATE = -1; ///< Representation of an invalid date
|
static constexpr Date INVALID_DATE = -1; ///< Representation of an invalid date
|
||||||
static const Ticks INVALID_TICKS = -1; ///< Representation of an invalid number of ticks
|
static constexpr DateTicks INVALID_DATE_TICKS = -1; ///< Representation of an invalid date ticks
|
||||||
|
static constexpr Ticks INVALID_TICKS = -1; ///< Representation of an invalid number of ticks
|
||||||
|
|
||||||
#endif /* DATE_TYPE_H */
|
#endif /* DATE_TYPE_H */
|
||||||
|
@@ -43,15 +43,23 @@
|
|||||||
typedef btree::btree_map<const DispatchSchedule *, btree::btree_set<DateTicksScaled>> schdispatch_cache_t;
|
typedef btree::btree_map<const DispatchSchedule *, btree::btree_set<DateTicksScaled>> schdispatch_cache_t;
|
||||||
|
|
||||||
/** A scheduled order. */
|
/** A scheduled order. */
|
||||||
typedef struct OrderDate
|
struct OrderDate {
|
||||||
{
|
|
||||||
const Order *order; ///< The order
|
const Order *order; ///< The order
|
||||||
const Vehicle *v; ///< The vehicle carrying out 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
|
Ticks lateness; ///< How late this order is expected to finish
|
||||||
DepartureStatus status; ///< Whether the vehicle has arrived to carry out the order yet
|
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
|
Ticks scheduled_waiting_time; ///< Scheduled waiting time if scheduled dispatch is used
|
||||||
} OrderDate;
|
|
||||||
|
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) {
|
static bool IsDeparture(const Order *order, StationID station) {
|
||||||
return (order->GetType() == OT_GOTO_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;
|
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)) {
|
if (HasBit(v->vehicle_flags, VF_SCHEDULED_DISPATCH)) {
|
||||||
auto is_current_implicit_order = [&v](const Order *o) -> bool {
|
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();
|
DateTicksScaled earliest_departure = begin_time + ds.GetScheduledDispatchLastDispatch();
|
||||||
|
|
||||||
/* Earliest possible departure according to vehicle current timetable */
|
/* 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) {
|
if (earliest_departure + max_delay < ready_to_depart_time) {
|
||||||
earliest_departure = ready_to_depart_time - max_delay - 1;
|
earliest_departure = ready_to_depart_time - max_delay - 1;
|
||||||
/* -1 because this number is actually a moment before actual departure */
|
/* -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();
|
*waiting_time = (actual_departure - date_ticks_base).AsTicks() - *previous_departure - order->GetTravelTime();
|
||||||
*previous_departure = actual_departure - date_only_scaled;
|
*previous_departure = (actual_departure - date_ticks_base).AsTicks();
|
||||||
slot_cache.insert(actual_departure);
|
slot_cache.insert(actual_departure);
|
||||||
|
|
||||||
/* Return true means that vehicle lateness should be clear from this point onward */
|
/* 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 */
|
/* Sort the departure list by arrival time */
|
||||||
std::sort(d_list.begin(), d_list.end(), [](const Departure * const &a, const Departure * const &b) -> bool {
|
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_a = a->scheduled_date - a->EffectiveWaitingTime();
|
||||||
DateTicksScaled arr_b = b->scheduled_date - (b->scheduled_waiting_time > 0 ? b->scheduled_waiting_time : b->order->GetWaitTime());
|
DateTicksScaled arr_b = b->scheduled_date - b->EffectiveWaitingTime();
|
||||||
return arr_a < arr_b;
|
return arr_a < arr_b;
|
||||||
});
|
});
|
||||||
|
|
||||||
/* Re-assign them sequentially */
|
/* Re-assign them sequentially */
|
||||||
for (size_t i = 0; i < d_list.size(); i++) {
|
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());
|
const DateTicksScaled arrival = d_list[i]->scheduled_date - d_list[i]->EffectiveWaitingTime();
|
||||||
d_list[i]->scheduled_waiting_time = departure_time_list[i] - arrival;
|
d_list[i]->scheduled_waiting_time = (departure_time_list[i] - arrival).AsTicks();
|
||||||
d_list[i]->scheduled_date = departure_time_list[i];
|
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;
|
d_list[i]->scheduled_waiting_time = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -237,12 +245,11 @@ DepartureList* MakeDepartureList(StationID station, const std::vector<const Vehi
|
|||||||
std::vector<OrderDate*> next_orders;
|
std::vector<OrderDate*> next_orders;
|
||||||
|
|
||||||
/* The maximum possible date for departures to be scheduled to occur. */
|
/* 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);
|
const DateTicksScaled date_ticks_base = _scaled_date_ticks;
|
||||||
DateTicksScaled date_fract_scaled = ((DateTicksScaled)_date_fract * _settings_game.economy.day_length_factor) + _tick_skip_counter;
|
|
||||||
|
|
||||||
/* 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;
|
OrderDate *least_order = nullptr;
|
||||||
|
|
||||||
/* Cache for scheduled departure time */
|
/* Cache for scheduled departure time */
|
||||||
@@ -272,20 +279,20 @@ DepartureList* MakeDepartureList(StationID station, const std::vector<const Vehi
|
|||||||
|
|
||||||
const Order *order = v->GetOrder(v->cur_implicit_order_index % v->GetNumOrders());
|
const Order *order = v->GetOrder(v->cur_implicit_order_index % v->GetNumOrders());
|
||||||
if (order == nullptr) continue;
|
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) {
|
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 */
|
/* 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_current_order = v->GetOrder(v->cur_real_order_index);
|
||||||
const Order *real_timetable_order = v->GetOrder(v->cur_timetable_order_index);
|
const Order *real_timetable_order = v->GetOrder(v->cur_timetable_order_index);
|
||||||
if (real_timetable_order->IsType(OT_CONDITIONAL)) {
|
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 {
|
} else {
|
||||||
/* This can also occur with implicit orders, when there are no real orders, do nothing */
|
/* This can also occur with implicit orders, when there are no real orders, do nothing */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DepartureStatus status = D_TRAVELLING;
|
DepartureStatus status = D_TRAVELLING;
|
||||||
bool should_reset_lateness = false;
|
bool should_reset_lateness = false;
|
||||||
uint waiting_time = 0;
|
Ticks waiting_time = 0;
|
||||||
|
|
||||||
/* If the vehicle is stopped in a depot, ignore it. */
|
/* If the vehicle is stopped in a depot, ignore it. */
|
||||||
if (v->IsStoppedInDepot()) {
|
if (v->IsStoppedInDepot()) {
|
||||||
@@ -301,20 +308,20 @@ DepartureList* MakeDepartureList(StationID station, const std::vector<const Vehi
|
|||||||
if (v->current_order.IsAnyLoadingType() || v->current_order.IsType(OT_WAITING)) {
|
if (v->current_order.IsAnyLoadingType() || v->current_order.IsType(OT_WAITING)) {
|
||||||
/* Account for the vehicle having reached the current order and being in the loading phase. */
|
/* Account for the vehicle having reached the current order and being in the loading phase. */
|
||||||
status = D_ARRIVED;
|
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;
|
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. */
|
/* 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. */
|
/* We only need to consider each order at most once. */
|
||||||
for (int i = v->GetNumOrders(); i > 0; --i) {
|
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;
|
should_reset_lateness = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the order is a conditional branch, handle it. */
|
/* If the order is a conditional branch, handle it. */
|
||||||
if (order->IsType(OT_CONDITIONAL)) {
|
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: {
|
case 0: {
|
||||||
/* Give up */
|
/* Give up */
|
||||||
break;
|
break;
|
||||||
@@ -329,7 +336,7 @@ DepartureList* MakeDepartureList(StationID station, const std::vector<const Vehi
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
start_date -= order->GetTravelTime();
|
start_ticks -= order->GetTravelTime();
|
||||||
require_travel_time = false;
|
require_travel_time = false;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -338,7 +345,7 @@ DepartureList* MakeDepartureList(StationID station, const std::vector<const Vehi
|
|||||||
if (status != D_CANCELLED) {
|
if (status != D_CANCELLED) {
|
||||||
status = D_TRAVELLING;
|
status = D_TRAVELLING;
|
||||||
}
|
}
|
||||||
start_date -= order->GetWaitTime(); /* Added previously in VehicleSetNextDepartureTime */
|
start_ticks -= order->GetWaitTime(); /* Added previously in VehicleSetNextDepartureTime */
|
||||||
order = (order->next == nullptr) ? v->GetFirstOrder() : order->next;
|
order = (order->next == nullptr) ? v->GetFirstOrder() : order->next;
|
||||||
require_travel_time = true;
|
require_travel_time = true;
|
||||||
continue;
|
continue;
|
||||||
@@ -348,7 +355,7 @@ DepartureList* MakeDepartureList(StationID station, const std::vector<const Vehi
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* If the scheduled departure date is too far in the future, stop. */
|
/* If the scheduled departure date is too far in the future, stop. */
|
||||||
if (start_date - v->lateness_counter > max_date) {
|
if (start_ticks - v->lateness_counter > max_ticks) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -363,7 +370,7 @@ DepartureList* MakeDepartureList(StationID station, const std::vector<const Vehi
|
|||||||
(type == D_DEPARTURE && show_vehicles_via && IsVia(order, station)) ||
|
(type == D_DEPARTURE && show_vehicles_via && IsVia(order, station)) ||
|
||||||
(type == D_ARRIVAL && IsArrival(order, station))) {
|
(type == D_ARRIVAL && IsArrival(order, station))) {
|
||||||
/* If the departure was scheduled to have already begun and has been cancelled, do not show it. */
|
/* If the departure was scheduled to have already begun and has been cancelled, do not show it. */
|
||||||
if (start_date < 0 && status == D_CANCELLED) {
|
if (start_ticks < 0 && status == D_CANCELLED) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -371,7 +378,7 @@ DepartureList* MakeDepartureList(StationID station, const std::vector<const Vehi
|
|||||||
od->order = order;
|
od->order = order;
|
||||||
od->v = v;
|
od->v = v;
|
||||||
/* We store the expected date for now, so that vehicles will be shown in order of expected time. */
|
/* 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->lateness = v->lateness_counter > 0 ? v->lateness_counter : 0;
|
||||||
od->status = status;
|
od->status = status;
|
||||||
od->scheduled_waiting_time = waiting_time;
|
od->scheduled_waiting_time = waiting_time;
|
||||||
@@ -383,16 +390,21 @@ DepartureList* MakeDepartureList(StationID station, const std::vector<const Vehi
|
|||||||
|
|
||||||
/* If we are early, use the scheduled date as the expected date. We also take lateness to be zero. */
|
/* If we are early, use the scheduled date as the expected date. We also take lateness to be zero. */
|
||||||
if (!should_reset_lateness && v->lateness_counter < 0 && !(v->current_order.IsAnyLoadingType() || v->current_order.IsType(OT_WAITING))) {
|
if (!should_reset_lateness && v->lateness_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. */
|
/* Update least_order if this is the current least order. */
|
||||||
if (least_order == nullptr) {
|
if (least_order == nullptr) {
|
||||||
least_order = od;
|
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))) {
|
} else if (type == D_ARRIVAL) {
|
||||||
/* Somehow my compiler perform an unsigned comparition above so integer cast is required */
|
if ((least_order->expected_tick - least_order->lateness - least_order->EffectiveWaitingTime()) > (od->expected_tick - od->lateness - od->EffectiveWaitingTime())) {
|
||||||
least_order = od;
|
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);
|
next_orders.push_back(od);
|
||||||
|
|
||||||
@@ -420,22 +432,22 @@ DepartureList* MakeDepartureList(StationID station, const std::vector<const Vehi
|
|||||||
for(int i = 10000; i > 0; --i) {
|
for(int i = 10000; i > 0; --i) {
|
||||||
/* I should probably try to convince you that this loop always terminates regardless of the safeguard. */
|
/* I should probably try to convince you that this loop always terminates regardless of the safeguard. */
|
||||||
/* 1. next_orders contains at least one element. */
|
/* 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.) */
|
/* (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. */
|
/* 4. Therefore the loop must eventually terminate. */
|
||||||
|
|
||||||
/* least_order is the best candidate for the next departure. */
|
/* least_order is the best candidate for the next departure. */
|
||||||
|
|
||||||
/* First, we check if we can stop looking for departures yet. */
|
/* First, we check if we can stop looking for departures yet. */
|
||||||
if (result->size() >= _settings_client.gui.max_departures ||
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We already know the least order and that it's a suitable departure, so make it into a departure. */
|
/* We already know the least order and that it's a suitable departure, so make it into a departure. */
|
||||||
Departure *d = new 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->lateness = least_order->lateness;
|
||||||
d->status = least_order->status;
|
d->status = least_order->status;
|
||||||
d->vehicle = least_order->v;
|
d->vehicle = least_order->v;
|
||||||
@@ -751,7 +763,7 @@ DepartureList* MakeDepartureList(StationID station, const std::vector<const Vehi
|
|||||||
|
|
||||||
/* Go to the next order so we don't add the current order again. */
|
/* Go to the next order so we don't add the current order again. */
|
||||||
order = (order->next == nullptr) ? least_order->v->GetFirstOrder() : order->next;
|
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;
|
least_order->lateness = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -762,7 +774,7 @@ DepartureList* MakeDepartureList(StationID station, const std::vector<const Vehi
|
|||||||
for (int i = least_order->v->GetNumOrders(); i > 0; --i) {
|
for (int i = least_order->v->GetNumOrders(); i > 0; --i) {
|
||||||
/* If the order is a conditional branch, handle it. */
|
/* If the order is a conditional branch, handle it. */
|
||||||
if (order->IsType(OT_CONDITIONAL)) {
|
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: {
|
case 0: {
|
||||||
/* Give up */
|
/* Give up */
|
||||||
break;
|
break;
|
||||||
@@ -774,8 +786,8 @@ DepartureList* MakeDepartureList(StationID station, const std::vector<const Vehi
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
least_order->expected_date -= order->GetTravelTime(); /* Added in next VehicleSetNextDepartureTime */
|
least_order->expected_tick -= 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)) {
|
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;
|
least_order->lateness = 0;
|
||||||
}
|
}
|
||||||
require_travel_time = false;
|
require_travel_time = false;
|
||||||
@@ -783,9 +795,9 @@ DepartureList* MakeDepartureList(StationID station, const std::vector<const Vehi
|
|||||||
}
|
}
|
||||||
case 2: {
|
case 2: {
|
||||||
/* Do not take the branch */
|
/* Do not take the branch */
|
||||||
least_order->expected_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;
|
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;
|
least_order->lateness = 0;
|
||||||
}
|
}
|
||||||
require_travel_time = true;
|
require_travel_time = true;
|
||||||
@@ -801,7 +813,7 @@ DepartureList* MakeDepartureList(StationID station, const std::vector<const Vehi
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* If the departure is scheduled to be too late, then stop. */
|
/* If the departure is scheduled to be too late, then stop. */
|
||||||
if (least_order->expected_date - least_order->lateness > max_date) {
|
if (least_order->expected_tick - least_order->lateness > max_ticks) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -815,7 +827,7 @@ DepartureList* MakeDepartureList(StationID station, const std::vector<const Vehi
|
|||||||
}
|
}
|
||||||
|
|
||||||
order = (order->next == nullptr) ? least_order->v->GetFirstOrder() : order->next;
|
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;
|
least_order->lateness = 0;
|
||||||
}
|
}
|
||||||
require_travel_time = true;
|
require_travel_time = true;
|
||||||
@@ -826,7 +838,7 @@ DepartureList* MakeDepartureList(StationID station, const std::vector<const Vehi
|
|||||||
/* Make sure we don't try to get departures out of this order. */
|
/* Make sure we don't try to get departures out of this order. */
|
||||||
/* This is cheaper than deleting it from next_orders. */
|
/* This is cheaper than deleting it from next_orders. */
|
||||||
/* If we ever get to a state where _date * DAY_TICKS is close to INT_MAX, then we'll have other problems anyway as departures' scheduled dates will wrap around. */
|
/* If we ever get to a state where _date * DAY_TICKS is close to INT_MAX, then we'll have other problems anyway as departures' scheduled dates will wrap around. */
|
||||||
least_order->expected_date = INT32_MAX;
|
least_order->expected_tick = INT32_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The vehicle can't possibly have arrived at its next candidate departure yet. */
|
/* The vehicle can't possibly have arrived at its next candidate departure yet. */
|
||||||
@@ -838,15 +850,15 @@ DepartureList* MakeDepartureList(StationID station, const std::vector<const Vehi
|
|||||||
for (uint i = 0; i < next_orders.size(); ++i) {
|
for (uint i = 0; i < next_orders.size(); ++i) {
|
||||||
OrderDate *od = next_orders[i];
|
OrderDate *od = next_orders[i];
|
||||||
|
|
||||||
DateTicks lod = least_order->expected_date - least_order->lateness;
|
DateTicks lod = least_order->expected_tick - least_order->lateness;
|
||||||
DateTicks odd = od->expected_date - od->lateness;
|
DateTicks odd = od->expected_tick - od->lateness;
|
||||||
|
|
||||||
if (type == D_ARRIVAL) {
|
if (type == D_ARRIVAL) {
|
||||||
lod -= least_order->scheduled_waiting_time > 0 ? least_order->scheduled_waiting_time : least_order->order->GetWaitTime();
|
lod -= least_order->scheduled_waiting_time > 0 ? least_order->scheduled_waiting_time : least_order->order->GetWaitTime();
|
||||||
odd -= od->scheduled_waiting_time > 0 ? od->scheduled_waiting_time : od->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;
|
least_order = od;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -864,7 +876,7 @@ DepartureList* MakeDepartureList(StationID station, const std::vector<const Vehi
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
DateTicksScaled GetDeparturesMaxTicksAhead()
|
Ticks GetDeparturesMaxTicksAhead()
|
||||||
{
|
{
|
||||||
if (_settings_time.time_in_minutes) {
|
if (_settings_time.time_in_minutes) {
|
||||||
return _settings_client.gui.max_departure_time_minutes * _settings_time.ticks_per_minute;
|
return _settings_client.gui.max_departure_time_minutes * _settings_time.ticks_per_minute;
|
||||||
|
@@ -20,6 +20,6 @@
|
|||||||
DepartureList* MakeDepartureList(StationID station, const std::vector<const Vehicle *> &vehicles, DepartureType type = D_DEPARTURE,
|
DepartureList* MakeDepartureList(StationID station, const std::vector<const Vehicle *> &vehicles, DepartureType type = D_DEPARTURE,
|
||||||
bool show_vehicles_via = false, bool show_pax = true, bool show_freight = true);
|
bool show_vehicles_via = false, bool show_pax = true, bool show_freight = true);
|
||||||
|
|
||||||
DateTicksScaled GetDeparturesMaxTicksAhead();
|
Ticks GetDeparturesMaxTicksAhead();
|
||||||
|
|
||||||
#endif /* DEPARTURES_FUNC_H */
|
#endif /* DEPARTURES_FUNC_H */
|
||||||
|
@@ -32,10 +32,10 @@ typedef enum {
|
|||||||
|
|
||||||
struct CallAt {
|
struct CallAt {
|
||||||
StationID station;
|
StationID station;
|
||||||
DateTicks scheduled_date;
|
DateTicksScaled scheduled_date;
|
||||||
|
|
||||||
CallAt(const StationID& s) : station(s), scheduled_date(0) { }
|
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) { }
|
CallAt(const CallAt& c) : station(c.station), scheduled_date(c.scheduled_date) { }
|
||||||
|
|
||||||
inline bool operator==(const CallAt& c) const {
|
inline bool operator==(const CallAt& c) const {
|
||||||
@@ -82,7 +82,7 @@ struct Departure {
|
|||||||
DepartureType type; ///< The type of the departure (departure or arrival)
|
DepartureType type; ///< The type of the departure (departure or arrival)
|
||||||
const Vehicle *vehicle; ///< The vehicle performing this departure
|
const Vehicle *vehicle; ///< The vehicle performing this departure
|
||||||
const Order *order; ///< The order corresponding to 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) { }
|
Departure() : terminus(INVALID_STATION), via(INVALID_STATION), via2(INVALID_STATION), vehicle(nullptr), order(nullptr) { }
|
||||||
|
|
||||||
inline bool operator==(const Departure& d) const {
|
inline bool operator==(const Departure& d) const {
|
||||||
@@ -93,13 +93,22 @@ struct Departure {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return
|
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->vehicle->type == d.vehicle->type &&
|
||||||
this->via == d.via &&
|
this->via == d.via &&
|
||||||
this->via2 == d.via2 &&
|
this->via2 == d.via2 &&
|
||||||
this->type == d.type
|
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<Departure*> DepartureList;
|
typedef std::vector<Departure*> DepartureList;
|
||||||
|
@@ -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);
|
DrawSpriteIgnorePadding((v->vehstatus & VS_STOPPED) ? SPR_FLAG_VEH_STOPPED : SPR_FLAG_VEH_RUNNING, PAL_NONE, flag, false, SA_CENTER);
|
||||||
|
|
||||||
SetDParam(0, v->unitnumber);
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -2459,7 +2459,7 @@ static void DoAcquireCompany(Company *c, bool hostile_takeover)
|
|||||||
{
|
{
|
||||||
CompanyID ci = c->index;
|
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));
|
CompanyNewsInformation *cni = new CompanyNewsInformation(c, Company::Get(_current_company));
|
||||||
|
|
||||||
|
@@ -484,7 +484,7 @@ uint Engine::GetDisplayMaxTractiveEffort() const
|
|||||||
* Returns the vehicle's (not model's!) life length in days.
|
* Returns the vehicle's (not model's!) life length in days.
|
||||||
* @return the life length
|
* @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. */
|
/* Assume leap years; this gives the player a bit more than the given amount of years, but never less. */
|
||||||
return static_cast<int32_t>(this->info.lifelength + _settings_game.vehicle.extend_vehicle_life) * DAYS_IN_LEAP_YEAR;
|
return static_cast<int32_t>(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;
|
SavedRandomSeeds saved_seeds;
|
||||||
SaveRandomSeeds(&saved_seeds);
|
SaveRandomSeeds(&saved_seeds);
|
||||||
SetRandomSeed(_settings_game.game_creation.generation_seed ^ seed ^
|
SetRandomSeed(_settings_game.game_creation.generation_seed ^ seed ^
|
||||||
ei->base_intro ^
|
ei->base_intro.base() ^
|
||||||
e->type ^
|
e->type ^
|
||||||
e->GetGRFID());
|
e->GetGRFID());
|
||||||
uint32 r = Random();
|
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
|
/* Don't randomise the start-date in the first two years after gamestart to ensure availability
|
||||||
* of engines in early starting games.
|
* of engines in early starting games.
|
||||||
* Note: TTDP uses fixed 1922 */
|
* Note: TTDP uses fixed 1922 */
|
||||||
e->intro_date = ei->base_intro <= ConvertYMDToDate(_settings_game.game_creation.starting_year + 2, 0, 1) ? ei->base_intro : (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) {
|
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->company_avail = MAX_UVALUE(CompanyMask);
|
||||||
e->flags |= ENGINE_AVAILABLE;
|
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 ^
|
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 ^
|
(re->info.lifelength << 4) ^ re->info.retire_early ^
|
||||||
e->type ^
|
e->type ^
|
||||||
e->GetGRFID());
|
e->GetGRFID());
|
||||||
|
@@ -140,7 +140,7 @@ struct Engine : EnginePool::PoolItem<&_engine_pool> {
|
|||||||
uint GetPower() const;
|
uint GetPower() const;
|
||||||
uint GetDisplayWeight() const;
|
uint GetDisplayWeight() const;
|
||||||
uint GetDisplayMaxTractiveEffort() const;
|
uint GetDisplayMaxTractiveEffort() const;
|
||||||
Date GetLifeLengthInDays() const;
|
DateDelta GetLifeLengthInDays() const;
|
||||||
uint16 GetRange() const;
|
uint16 GetRange() const;
|
||||||
StringID GetAircraftTypeText() const;
|
StringID GetAircraftTypeText() const;
|
||||||
|
|
||||||
|
@@ -204,7 +204,7 @@ static void _GenerateWorld()
|
|||||||
|
|
||||||
if (_debug_desync_level > 0) {
|
if (_debug_desync_level > 0) {
|
||||||
char name[MAX_PATH];
|
char name[MAX_PATH];
|
||||||
seprintf(name, lastof(name), "dmp_cmds_%08x_%08x.sav", _settings_game.game_creation.generation_seed, _date);
|
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);
|
SaveOrLoad(name, SLO_SAVE, DFT_GAME_FILE, AUTOSAVE_DIR, false, SMF_ZSTD_OK);
|
||||||
}
|
}
|
||||||
} catch (AbortGenerateWorldSignal&) {
|
} catch (AbortGenerateWorldSignal&) {
|
||||||
|
@@ -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
|
/* 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
|
* division by 0 if spawn date == last compression date. This matches
|
||||||
* LinkGraph::Monthly(). */
|
* LinkGraph::Monthly(). */
|
||||||
uint runtime = (uint)Clamp<DateTicksScaled>(DateTicksToScaledDateTicks(job.StartDateTicks()) - job.LastCompression() + 1, 1, UINT32_MAX);
|
uint runtime = (uint)Clamp<DateTicksScaledDelta>(DateTicksToScaledDateTicks(job.StartDateTicks()) - job.LastCompression() + 1, 1, UINT32_MAX).base();
|
||||||
for (auto &it : flows) {
|
for (auto &it : flows) {
|
||||||
it.ScaleToMonthly(runtime);
|
it.ScaleToMonthly(runtime);
|
||||||
}
|
}
|
||||||
|
@@ -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.
|
* This is useful if the date has been modified with the cheat menu.
|
||||||
* @param interval Number of days to be added or subtracted.
|
* @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) {
|
for (NodeID node1 = 0; node1 < this->Size(); ++node1) {
|
||||||
BaseNode &source = this->nodes[node1];
|
BaseNode &source = this->nodes[node1];
|
||||||
@@ -54,7 +54,7 @@ void LinkGraph::ShiftDates(int interval)
|
|||||||
|
|
||||||
void LinkGraph::Compress()
|
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) {
|
for (NodeID node1 = 0; node1 < this->Size(); ++node1) {
|
||||||
this->nodes[node1].supply /= 2;
|
this->nodes[node1].supply /= 2;
|
||||||
}
|
}
|
||||||
@@ -79,8 +79,8 @@ void LinkGraph::Compress()
|
|||||||
*/
|
*/
|
||||||
void LinkGraph::Merge(LinkGraph *other)
|
void LinkGraph::Merge(LinkGraph *other)
|
||||||
{
|
{
|
||||||
uint32 age = ClampTo<uint32>(CeilDivT<DateTicksScaled>(_scaled_date_ticks - this->last_compression + 1, DAY_TICKS));
|
uint32 age = ClampTo<uint32>(CeilDivT<int64>(_scaled_date_ticks.base() - this->last_compression.base() + 1, DAY_TICKS));
|
||||||
uint32 other_age = ClampTo<uint32>(CeilDivT<DateTicksScaled>(_scaled_date_ticks - other->last_compression + 1, DAY_TICKS));
|
uint32 other_age = ClampTo<uint32>(CeilDivT<int64>(_scaled_date_ticks.base() - other->last_compression.base() + 1, DAY_TICKS));
|
||||||
NodeID first = this->Size();
|
NodeID first = this->Size();
|
||||||
this->nodes.reserve(first + other->Size());
|
this->nodes.reserve(first + other->Size());
|
||||||
for (NodeID node1 = 0; node1 < other->Size(); ++node1) {
|
for (NodeID node1 = 0; node1 < other->Size(); ++node1) {
|
||||||
@@ -266,7 +266,7 @@ void LinkGraph::Init(uint size)
|
|||||||
this->nodes.resize(size);
|
this->nodes.resize(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdjustLinkGraphScaledTickBase(int64 delta)
|
void AdjustLinkGraphScaledTickBase(DateTicksScaledDelta delta)
|
||||||
{
|
{
|
||||||
for (LinkGraph *lg : LinkGraph::Iterate()) lg->last_compression += delta;
|
for (LinkGraph *lg : LinkGraph::Iterate()) lg->last_compression += delta;
|
||||||
|
|
||||||
@@ -279,10 +279,10 @@ void AdjustLinkGraphScaledTickBase(int64 delta)
|
|||||||
void LinkGraphFixupLastCompressionAfterLoad()
|
void LinkGraphFixupLastCompressionAfterLoad()
|
||||||
{
|
{
|
||||||
/* last_compression was previously a Date, change it to a DateTicksScaled */
|
/* 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()) {
|
for (LinkGraphJob *lgj : LinkGraphJob::Iterate()) {
|
||||||
LinkGraph *lg = &(const_cast<LinkGraph &>(lgj->Graph()));
|
LinkGraph *lg = &(const_cast<LinkGraph &>(lgj->Graph()));
|
||||||
lg->last_compression = DateToScaledDateTicks((Date)lg->last_compression);
|
lg->last_compression = DateToScaledDateTicks((Date)lg->last_compression.base());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -287,10 +287,10 @@ public:
|
|||||||
static const uint MIN_TIMEOUT_DISTANCE = 32;
|
static const uint MIN_TIMEOUT_DISTANCE = 32;
|
||||||
|
|
||||||
/** Number of days before deleting links served only by vehicles stopped in depot. */
|
/** 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. */
|
/** Minimum number of ticks between subsequent compressions of a LG. */
|
||||||
static const uint COMPRESSION_INTERVAL = 256 * DAY_TICKS;
|
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
|
* 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) {}
|
LinkGraph(CargoID cargo) : cargo(cargo), last_compression(_scaled_date_ticks) {}
|
||||||
|
|
||||||
void Init(uint size);
|
void Init(uint size);
|
||||||
void ShiftDates(int interval);
|
void ShiftDates(DateDelta interval);
|
||||||
void Compress();
|
void Compress();
|
||||||
void Merge(LinkGraph *other);
|
void Merge(LinkGraph *other);
|
||||||
|
|
||||||
@@ -365,7 +365,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
inline uint Monthly(uint base) const
|
inline uint Monthly(uint base) const
|
||||||
{
|
{
|
||||||
return (static_cast<uint64>(base) * 30 * DAY_TICKS * _settings_game.economy.day_length_factor) / std::max<uint64>(_scaled_date_ticks - this->last_compression, DAY_TICKS);
|
return (static_cast<uint64>(base) * 30 * DAY_TICKS * _settings_game.economy.day_length_factor) / std::max<uint64>((_scaled_date_ticks - this->last_compression).base(), DAY_TICKS);
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeID AddNode(const Station *st);
|
NodeID AddNode(const Station *st);
|
||||||
@@ -392,7 +392,7 @@ protected:
|
|||||||
friend upstream_sl::SlLinkgraphNode;
|
friend upstream_sl::SlLinkgraphNode;
|
||||||
friend upstream_sl::SlLinkgraphEdge;
|
friend upstream_sl::SlLinkgraphEdge;
|
||||||
|
|
||||||
friend void AdjustLinkGraphScaledTickBase(int64 delta);
|
friend void AdjustLinkGraphScaledTickBase(DateTicksScaledDelta delta);
|
||||||
friend void LinkGraphFixupLastCompressionAfterLoad();
|
friend void LinkGraphFixupLastCompressionAfterLoad();
|
||||||
|
|
||||||
CargoID cargo; ///< Cargo of this component's link graph.
|
CargoID cargo; ///< Cargo of this component's link graph.
|
||||||
|
@@ -28,8 +28,8 @@ INSTANTIATE_POOL_METHODS(LinkGraphJob)
|
|||||||
|
|
||||||
static DateTicks GetLinkGraphJobJoinDateTicks(uint duration_multiplier)
|
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);
|
DateTicksDelta 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;
|
return ticks + NowDateTicks();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -44,7 +44,7 @@ LinkGraphJob::LinkGraphJob(const LinkGraph &orig, uint duration_multiplier) :
|
|||||||
link_graph(orig),
|
link_graph(orig),
|
||||||
settings(_settings_game.linkgraph),
|
settings(_settings_game.linkgraph),
|
||||||
join_date_ticks(GetLinkGraphJobJoinDateTicks(duration_multiplier)),
|
join_date_ticks(GetLinkGraphJobJoinDateTicks(duration_multiplier)),
|
||||||
start_date_ticks((_date * DAY_TICKS) + _date_fract),
|
start_date_ticks(NowDateTicks()),
|
||||||
job_completed(false),
|
job_completed(false),
|
||||||
job_aborted(false)
|
job_aborted(false)
|
||||||
{
|
{
|
||||||
|
@@ -262,7 +262,7 @@ public:
|
|||||||
* settings have to be brutally const-casted in order to populate them.
|
* settings have to be brutally const-casted in order to populate them.
|
||||||
*/
|
*/
|
||||||
LinkGraphJob() : settings(_settings_game.linkgraph),
|
LinkGraphJob() : settings(_settings_game.linkgraph),
|
||||||
join_date_ticks(INVALID_DATE), 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(const LinkGraph &orig, uint duration_multiplier);
|
||||||
~LinkGraphJob();
|
~LinkGraphJob();
|
||||||
@@ -297,7 +297,7 @@ public:
|
|||||||
* @param tick_offset Optional number of ticks to add to the current date
|
* @param tick_offset Optional number of ticks to add to the current date
|
||||||
* @return True if job should be finished by now, false if not.
|
* @return True if job should be finished by now, false if not.
|
||||||
*/
|
*/
|
||||||
inline bool IsScheduledToBeJoined(int tick_offset = 0) const { return this->join_date_ticks <= (_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.
|
* Get the date when the job should be finished.
|
||||||
@@ -315,10 +315,10 @@ public:
|
|||||||
* Change the start and join dates on date cheating.
|
* Change the start and join dates on date cheating.
|
||||||
* @param interval Number of days to add.
|
* @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->join_date_ticks += DateDeltaToDateTicksDelta(interval);
|
||||||
this->start_date_ticks += interval * DAY_TICKS;
|
this->start_date_ticks += DateDeltaToDateTicksDelta(interval);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -200,7 +200,7 @@ void LinkGraphSchedule::SpawnAll()
|
|||||||
* graph jobs by the number of days given.
|
* graph jobs by the number of days given.
|
||||||
* @param interval Number of days to be added or subtracted.
|
* @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 (LinkGraph *lg : LinkGraph::Iterate()) lg->ShiftDates(interval);
|
||||||
for (LinkGraphJob *lgj : LinkGraphJob::Iterate()) lgj->ShiftJoinDate(interval);
|
for (LinkGraphJob *lgj : LinkGraphJob::Iterate()) lgj->ShiftJoinDate(interval);
|
||||||
@@ -285,7 +285,7 @@ void LinkGraphJobGroup::JoinThread()
|
|||||||
auto flush_bucket = [&]() {
|
auto flush_bucket = [&]() {
|
||||||
if (!bucket_cost) return;
|
if (!bucket_cost) return;
|
||||||
DEBUG(linkgraph, 2, "LinkGraphJobGroup::ExecuteJobSet: Creating Job Group: jobs: " PRINTF_SIZE ", cost: %u, join after: %d",
|
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<LinkGraphJobGroup>(constructor_token(), std::move(bucket));
|
auto group = std::make_shared<LinkGraphJobGroup>(constructor_token(), std::move(bucket));
|
||||||
group->SpawnThread();
|
group->SpawnThread();
|
||||||
bucket_cost = 0;
|
bucket_cost = 0;
|
||||||
@@ -321,9 +321,9 @@ void StateGameLoop_LinkGraphPauseControl()
|
|||||||
} else if (_pause_mode == PM_UNPAUSED && _tick_skip_counter == 0) {
|
} else if (_pause_mode == PM_UNPAUSED && _tick_skip_counter == 0) {
|
||||||
if (_settings_game.economy.day_length_factor == 1) {
|
if (_settings_game.economy.day_length_factor == 1) {
|
||||||
if (_date_fract != LinkGraphSchedule::SPAWN_JOIN_TICK - 2) return;
|
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 {
|
} 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<int>(2, (_settings_game.linkgraph.recalc_interval * DAY_TICKS / (SECONDS_PER_DAY * _settings_game.economy.day_length_factor)));
|
int interval = std::max<int>(2, (_settings_game.linkgraph.recalc_interval * DAY_TICKS / (SECONDS_PER_DAY * _settings_game.economy.day_length_factor)));
|
||||||
if (date_ticks % interval != interval / 2) return;
|
if (date_ticks % interval != interval / 2) return;
|
||||||
}
|
}
|
||||||
@@ -358,10 +358,10 @@ void OnTick_LinkGraph()
|
|||||||
if (_settings_game.economy.day_length_factor == 1) {
|
if (_settings_game.economy.day_length_factor == 1) {
|
||||||
if (_date_fract != LinkGraphSchedule::SPAWN_JOIN_TICK) return;
|
if (_date_fract != LinkGraphSchedule::SPAWN_JOIN_TICK) return;
|
||||||
interval = _settings_game.linkgraph.recalc_interval / SECONDS_PER_DAY;
|
interval = _settings_game.linkgraph.recalc_interval / SECONDS_PER_DAY;
|
||||||
offset = _date % interval;
|
offset = _date.base() % interval;
|
||||||
} else {
|
} else {
|
||||||
interval = std::max<int>(2, (_settings_game.linkgraph.recalc_interval * DAY_TICKS / (SECONDS_PER_DAY * _settings_game.economy.day_length_factor)));
|
interval = std::max<int>(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) {
|
if (offset == 0) {
|
||||||
LinkGraphSchedule::instance.SpawnNext();
|
LinkGraphSchedule::instance.SpawnNext();
|
||||||
|
@@ -66,7 +66,7 @@ public:
|
|||||||
bool IsJoinWithUnfinishedJobDue() const;
|
bool IsJoinWithUnfinishedJobDue() const;
|
||||||
void JoinNext();
|
void JoinNext();
|
||||||
void SpawnAll();
|
void SpawnAll();
|
||||||
void ShiftDates(int interval);
|
void ShiftDates(DateDelta interval);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Queue a link graph for execution.
|
* Queue a link graph for execution.
|
||||||
|
@@ -235,8 +235,8 @@ void SerializeNetworkGameInfo(Packet *p, const NetworkServerGameInfo *info, bool
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* NETWORK_GAME_INFO_VERSION = 3 */
|
/* NETWORK_GAME_INFO_VERSION = 3 */
|
||||||
p->Send_uint32(info->game_date);
|
p->Send_uint32(info->game_date.base());
|
||||||
p->Send_uint32(info->start_date);
|
p->Send_uint32(info->start_date.base());
|
||||||
|
|
||||||
/* NETWORK_GAME_INFO_VERSION = 2 */
|
/* NETWORK_GAME_INFO_VERSION = 2 */
|
||||||
p->Send_uint8 (info->companies_max);
|
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_uint8(version); // version num
|
||||||
|
|
||||||
p->Send_uint32(info->game_date);
|
p->Send_uint32(info->game_date.base());
|
||||||
p->Send_uint32(info->start_date);
|
p->Send_uint32(info->start_date.base());
|
||||||
p->Send_uint8 (info->companies_max);
|
p->Send_uint8 (info->companies_max);
|
||||||
p->Send_uint8 (info->companies_on);
|
p->Send_uint8 (info->companies_on);
|
||||||
p->Send_uint8 (info->clients_max); // Used to be max-spectators
|
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:
|
case 3:
|
||||||
info->game_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);
|
info->start_date = Clamp(p->Recv_uint32(), 0, MAX_DATE.base());
|
||||||
FALLTHROUGH;
|
FALLTHROUGH;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
@@ -455,8 +455,8 @@ void DeserializeNetworkGameInfoExtended(Packet *p, NetworkGameInfo *info)
|
|||||||
|
|
||||||
NewGRFSerializationType newgrf_serialisation = NST_GRFID_MD5;
|
NewGRFSerializationType newgrf_serialisation = NST_GRFID_MD5;
|
||||||
|
|
||||||
info->game_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);
|
info->start_date = Clamp(p->Recv_uint32(), 0, MAX_DATE.base());
|
||||||
info->companies_max = p->Recv_uint8 ();
|
info->companies_max = p->Recv_uint8 ();
|
||||||
info->companies_on = p->Recv_uint8 ();
|
info->companies_on = p->Recv_uint8 ();
|
||||||
p->Recv_uint8(); // Used to contain max-spectators.
|
p->Recv_uint8(); // Used to contain max-spectators.
|
||||||
|
@@ -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);
|
char *msg_ptr = message + Utf8Encode(message, _current_text_dir == TD_LTR ? CHAR_TD_LRM : CHAR_TD_RLM);
|
||||||
GetString(msg_ptr, strid, lastof(message));
|
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);
|
IConsolePrintF(colour, "%s", message);
|
||||||
NetworkAddChatMessage(colour, _settings_client.gui.network_chat_timeout, 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. */
|
/* We don't want to log multiple times if paused. */
|
||||||
static Date last_log;
|
static Date last_log;
|
||||||
if (last_log != _date) {
|
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;
|
last_log = _date;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1185,15 +1185,15 @@ void NetworkGameLoop()
|
|||||||
if (_date == next_date && _date_fract == next_date_fract) {
|
if (_date == next_date && _date_fract == next_date_fract) {
|
||||||
if (cp != nullptr) {
|
if (cp != nullptr) {
|
||||||
NetworkSendCommand(cp->tile, cp->p1, cp->p2, cp->p3, cp->cmd & ~CMD_FLAGS_MASK, nullptr, cp->text.c_str(), cp->company, cp->aux_data);
|
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();
|
cp.reset();
|
||||||
}
|
}
|
||||||
if (check_sync_state) {
|
if (check_sync_state) {
|
||||||
if (sync_state[0] == _random.state[0] && sync_state[1] == _random.state[1]) {
|
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 {
|
} else {
|
||||||
DEBUG(net, 0, "sync check: date{%08x; %02x; %02x}; mismatch expected {%08x, %08x}, got {%08x, %08x}",
|
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();
|
NOT_REACHED();
|
||||||
}
|
}
|
||||||
check_sync_state = false;
|
check_sync_state = false;
|
||||||
|
@@ -179,7 +179,7 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::SendWelcome()
|
|||||||
p->Send_string(""); // Used to be map-name.
|
p->Send_string(""); // Used to be map-name.
|
||||||
p->Send_uint32(_settings_game.game_creation.generation_seed);
|
p->Send_uint32(_settings_game.game_creation.generation_seed);
|
||||||
p->Send_uint8 (_settings_game.game_creation.landscape);
|
p->Send_uint8 (_settings_game.game_creation.landscape);
|
||||||
p->Send_uint32(ConvertYMDToDate(_settings_game.game_creation.starting_year, 0, 1));
|
p->Send_uint32(ConvertYMDToDate(_settings_game.game_creation.starting_year, 0, 1).base());
|
||||||
p->Send_uint16(MapSizeX());
|
p->Send_uint16(MapSizeX());
|
||||||
p->Send_uint16(MapSizeY());
|
p->Send_uint16(MapSizeY());
|
||||||
|
|
||||||
@@ -209,7 +209,7 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::SendDate()
|
|||||||
{
|
{
|
||||||
Packet *p = new Packet(ADMIN_PACKET_SERVER_DATE);
|
Packet *p = new Packet(ADMIN_PACKET_SERVER_DATE);
|
||||||
|
|
||||||
p->Send_uint32(_date);
|
p->Send_uint32(_date.base());
|
||||||
this->SendPacket(p);
|
this->SendPacket(p);
|
||||||
|
|
||||||
return NETWORK_RECV_STATUS_OKAY;
|
return NETWORK_RECV_STATUS_OKAY;
|
||||||
@@ -245,7 +245,7 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::SendClientInfo(const NetworkC
|
|||||||
p->Send_string(cs == nullptr ? "" : const_cast<NetworkAddress &>(cs->client_address).GetHostname());
|
p->Send_string(cs == nullptr ? "" : const_cast<NetworkAddress &>(cs->client_address).GetHostname());
|
||||||
p->Send_string(ci->client_name);
|
p->Send_string(ci->client_name);
|
||||||
p->Send_uint8 (0); // Used to be language
|
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);
|
p->Send_uint8 (ci->client_playas);
|
||||||
|
|
||||||
this->SendPacket(p);
|
this->SendPacket(p);
|
||||||
|
@@ -331,7 +331,7 @@ void ClientNetworkGameSocketHandler::ClientError(NetworkRecvStatus res)
|
|||||||
|
|
||||||
ShowNetworkError(STR_NETWORK_ERROR_DESYNC);
|
ShowNetworkError(STR_NETWORK_ERROR_DESYNC);
|
||||||
DEBUG(desync, 1, "sync_err: date{%08x; %02x; %02x} {%x, " OTTD_PRINTFHEX64 "} != {%x, " OTTD_PRINTFHEX64 "}"
|
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!");
|
DEBUG(net, 0, "Sync error detected!");
|
||||||
|
|
||||||
std::string desync_log;
|
std::string desync_log;
|
||||||
@@ -632,7 +632,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::SendDesyncLog(const std::strin
|
|||||||
NetworkRecvStatus ClientNetworkGameSocketHandler::SendDesyncMessage(const char *msg)
|
NetworkRecvStatus ClientNetworkGameSocketHandler::SendDesyncMessage(const char *msg)
|
||||||
{
|
{
|
||||||
Packet *p = new Packet(PACKET_CLIENT_DESYNC_MSG, SHRT_MAX);
|
Packet *p = new Packet(PACKET_CLIENT_DESYNC_MSG, SHRT_MAX);
|
||||||
p->Send_uint32(_date);
|
p->Send_uint32(_date.base());
|
||||||
p->Send_uint16(_date_fract);
|
p->Send_uint16(_date_fract);
|
||||||
p->Send_uint8(_tick_skip_counter);
|
p->Send_uint8(_tick_skip_counter);
|
||||||
p->Send_string(msg);
|
p->Send_string(msg);
|
||||||
|
@@ -287,7 +287,7 @@ protected:
|
|||||||
/** Sort servers by the number of days the game is running */
|
/** Sort servers by the number of days the game is running */
|
||||||
static bool NGameYearsSorter(NetworkGameList * const &a, NetworkGameList * const &b)
|
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);
|
return (r != 0) ? r < 0: NGameDateSorter(a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -650,11 +650,11 @@ public:
|
|||||||
DrawString(tr, invite_or_address); // server address / invite code
|
DrawString(tr, invite_or_address); // server address / invite code
|
||||||
tr.top += GetCharacterHeight(FS_NORMAL);
|
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
|
DrawString(tr, STR_NETWORK_SERVER_LIST_START_DATE); // start date
|
||||||
tr.top += GetCharacterHeight(FS_NORMAL);
|
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
|
DrawString(tr, STR_NETWORK_SERVER_LIST_CURRENT_DATE); // current date
|
||||||
tr.top += GetCharacterHeight(FS_NORMAL);
|
tr.top += GetCharacterHeight(FS_NORMAL);
|
||||||
|
|
||||||
|
@@ -1020,7 +1020,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_JOIN(Packet *p)
|
|||||||
ci->join_frame = _frame_counter;
|
ci->join_frame = _frame_counter;
|
||||||
ci->client_name = client_name;
|
ci->client_name = client_name;
|
||||||
ci->client_playas = playas;
|
ci->client_playas = playas;
|
||||||
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 */
|
/* Make sure companies to which people try to join are not autocleaned */
|
||||||
if (Company::IsValidID(playas)) _network_company_states[playas].months_empty = 0;
|
if (Company::IsValidID(playas)) _network_company_states[playas].months_empty = 0;
|
||||||
@@ -1812,7 +1812,7 @@ void NetworkUpdateClientInfo(ClientID client_id)
|
|||||||
|
|
||||||
if (ci == nullptr) return;
|
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()) {
|
for (NetworkClientSocket *cs : NetworkClientSocket::Iterate()) {
|
||||||
if (cs->status >= ServerNetworkGameSocketHandler::STATUS_AUTHORIZED) {
|
if (cs->status >= ServerNetworkGameSocketHandler::STATUS_AUTHORIZED) {
|
||||||
@@ -2169,7 +2169,7 @@ void NetworkServerMonthlyLoop()
|
|||||||
void NetworkServerDailyLoop()
|
void NetworkServerDailyLoop()
|
||||||
{
|
{
|
||||||
NetworkAdminUpdate(ADMIN_FREQUENCY_DAILY);
|
NetworkAdminUpdate(ADMIN_FREQUENCY_DAILY);
|
||||||
if ((_date % 7) == 3) NetworkAdminUpdate(ADMIN_FREQUENCY_WEEKLY);
|
if ((_date.base() % 7) == 3) NetworkAdminUpdate(ADMIN_FREQUENCY_WEEKLY);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -7403,7 +7403,7 @@ bool GetGlobalVariable(byte param, uint32 *value, const GRFFile *grffile)
|
|||||||
|
|
||||||
switch (param) {
|
switch (param) {
|
||||||
case 0x00: // current date
|
case 0x00: // current date
|
||||||
*value = std::max(_date - DAYS_TILL_ORIGINAL_BASE_YEAR, 0);
|
*value = std::max<DateDelta>(_date - DAYS_TILL_ORIGINAL_BASE_YEAR, 0).base();
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case 0x01: // current year
|
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)
|
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);
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7518,7 +7518,7 @@ bool GetGlobalVariable(byte param, uint32 *value, const GRFFile *grffile)
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
case 0x23: // long format date
|
case 0x23: // long format date
|
||||||
*value = _date;
|
*value = _date.base();
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case 0x24: // long format year
|
case 0x24: // long format year
|
||||||
|
@@ -169,7 +169,7 @@ void AirportOverrideManager::SetEntitySpec(AirportSpec *as)
|
|||||||
case 0x7C: return (this->st->airport.psa != nullptr) ? this->st->airport.psa->GetValue(parameter) : 0;
|
case 0x7C: return (this->st->airport.psa != nullptr) ? this->st->airport.psa->GetValue(parameter) : 0;
|
||||||
|
|
||||||
case 0xF0: return this->st->facilities;
|
case 0xF0: return this->st->facilities;
|
||||||
case 0xFA: return ClampTo<uint16_t>(this->st->build_date - DAYS_TILL_ORIGINAL_BASE_YEAR);
|
case 0xFA: return ClampTo<uint16_t>((this->st->build_date - DAYS_TILL_ORIGINAL_BASE_YEAR).base());
|
||||||
}
|
}
|
||||||
|
|
||||||
return this->st->GetNewGRFVariable(this->ro, variable, parameter, &(extra->available));
|
return this->st->GetNewGRFVariable(this->ro, variable, parameter, &(extra->available));
|
||||||
|
@@ -729,7 +729,7 @@ static uint32 VehicleGetVariable(Vehicle *v, const VehicleScopeResolver *object,
|
|||||||
}
|
}
|
||||||
|
|
||||||
case 0x4B: // Long date of last service
|
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
|
case 0x4C: // Current maximum speed in NewGRF units
|
||||||
if (!v->IsPrimaryVehicle()) return 0;
|
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 0x48: return Engine::Get(this->self_type)->flags; // Vehicle Type Info
|
||||||
case 0x49: return _cur_year; // 'Long' format build year
|
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<uint16>(_date - DAYS_TILL_ORIGINAL_BASE_YEAR); // Date of last service
|
case 0x92: return ClampTo<uint16>(_date - DAYS_TILL_ORIGINAL_BASE_YEAR); // Date of last service
|
||||||
case 0x93: return GB(ClampTo<uint16>(_date - DAYS_TILL_ORIGINAL_BASE_YEAR), 8, 8);
|
case 0x93: return GB(ClampTo<uint16>(_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
|
case 0xC4: return Clamp(_cur_year, ORIGINAL_BASE_YEAR, ORIGINAL_MAX_YEAR) - ORIGINAL_BASE_YEAR; // Build year
|
||||||
|
@@ -271,7 +271,7 @@ static uint32 GetCountAndDistanceOfClosestInstance(byte param_setID, byte layout
|
|||||||
return this->industry->founder | (is_ai ? 0x10000 : 0) | (colours << 24);
|
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 */
|
/* Override flags from GS */
|
||||||
case 0x47: return this->industry->ctlflags;
|
case 0x47: return this->industry->ctlflags;
|
||||||
@@ -362,7 +362,7 @@ static uint32 GetCountAndDistanceOfClosestInstance(byte param_setID, byte layout
|
|||||||
if (cargo == CT_INVALID) return 0;
|
if (cargo == CT_INVALID) return 0;
|
||||||
int index = this->industry->GetCargoAcceptedIndex(cargo);
|
int index = this->industry->GetCargoAcceptedIndex(cargo);
|
||||||
if (index < 0) return 0; // invalid 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];
|
if (variable == 0x6F) return this->industry->incoming_cargo_waiting[index];
|
||||||
NOT_REACHED();
|
NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
@@ -281,7 +281,7 @@ static uint32 GetCountAndDistanceOfClosestInstance(uint32 local_id, uint32 grfid
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
/* Construction date */
|
/* Construction date */
|
||||||
case 0x42: return _date;
|
case 0x42: return _date.base();
|
||||||
|
|
||||||
/* Object founder information */
|
/* Object founder information */
|
||||||
case 0x44: return _current_company;
|
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);
|
case 0x41: return GetTileSlope(this->tile) << 8 | GetTerrainType(this->tile);
|
||||||
|
|
||||||
/* Construction date */
|
/* Construction date */
|
||||||
case 0x42: return this->obj->build_date;
|
case 0x42: return this->obj->build_date.base();
|
||||||
|
|
||||||
/* Animation counter */
|
/* Animation counter */
|
||||||
case 0x43: return GetAnimationFrame(this->tile);
|
case 0x43: return GetAnimationFrame(this->tile);
|
||||||
|
@@ -34,7 +34,7 @@
|
|||||||
case 0x40: return 0;
|
case 0x40: return 0;
|
||||||
case 0x41: return 0;
|
case 0x41: return 0;
|
||||||
case 0x42: return 0;
|
case 0x42: return 0;
|
||||||
case 0x43: return _date;
|
case 0x43: return _date.base();
|
||||||
case 0x44: return HZB_TOWN_EDGE;
|
case 0x44: return HZB_TOWN_EDGE;
|
||||||
case A2VRI_RAILTYPE_SIGNAL_RESTRICTION_INFO: return 0;
|
case A2VRI_RAILTYPE_SIGNAL_RESTRICTION_INFO: return 0;
|
||||||
case A2VRI_RAILTYPE_SIGNAL_CONTEXT: return this->signal_context;
|
case A2VRI_RAILTYPE_SIGNAL_CONTEXT: return this->signal_context;
|
||||||
@@ -49,8 +49,8 @@
|
|||||||
case 0x41: return 0;
|
case 0x41: return 0;
|
||||||
case 0x42: return IsLevelCrossingTile(this->tile) && IsCrossingBarred(this->tile);
|
case 0x42: return IsLevelCrossingTile(this->tile) && IsCrossingBarred(this->tile);
|
||||||
case 0x43:
|
case 0x43:
|
||||||
if (IsRailDepotTile(this->tile)) return Depot::GetByTile(this->tile)->build_date;
|
if (IsRailDepotTile(this->tile)) return Depot::GetByTile(this->tile)->build_date.base();
|
||||||
return _date;
|
return _date.base();
|
||||||
case 0x44: {
|
case 0x44: {
|
||||||
const Town *t = nullptr;
|
const Town *t = nullptr;
|
||||||
if (IsRailDepotTile(this->tile)) {
|
if (IsRailDepotTile(this->tile)) {
|
||||||
|
@@ -30,7 +30,7 @@
|
|||||||
case 0x40: return 0;
|
case 0x40: return 0;
|
||||||
case 0x41: return 0;
|
case 0x41: return 0;
|
||||||
case 0x42: return 0;
|
case 0x42: return 0;
|
||||||
case 0x43: return _date;
|
case 0x43: return _date.base();
|
||||||
case 0x44: return HZB_TOWN_EDGE;
|
case 0x44: return HZB_TOWN_EDGE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -40,8 +40,8 @@
|
|||||||
case 0x41: return 0;
|
case 0x41: return 0;
|
||||||
case 0x42: return IsLevelCrossingTile(this->tile) && IsCrossingBarred(this->tile);
|
case 0x42: return IsLevelCrossingTile(this->tile) && IsCrossingBarred(this->tile);
|
||||||
case 0x43:
|
case 0x43:
|
||||||
if (IsRoadDepotTile(this->tile)) return Depot::GetByTile(this->tile)->build_date;
|
if (IsRoadDepotTile(this->tile)) return Depot::GetByTile(this->tile)->build_date.base();
|
||||||
return _date;
|
return _date.base();
|
||||||
case 0x44: {
|
case 0x44: {
|
||||||
const Town *t = nullptr;
|
const Town *t = nullptr;
|
||||||
if (IsRoadDepotTile(this->tile)) {
|
if (IsRoadDepotTile(this->tile)) {
|
||||||
|
@@ -1554,7 +1554,7 @@ void CheckCaches(bool force_check, std::function<void(const char *)> log, CheckC
|
|||||||
desync_level = 1;
|
desync_level = 1;
|
||||||
if (HasChickenBit(DCBF_DESYNC_CHECK_NO_GENERAL)) flags &= ~CHECK_CACHE_GENERAL;
|
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;
|
if (!SignalInfraTotalMatches()) desync_level = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1562,7 +1562,7 @@ void CheckCaches(bool force_check, std::function<void(const char *)> log, CheckC
|
|||||||
* always to aid testing of caches. */
|
* always to aid testing of caches. */
|
||||||
if (desync_level < 1) return;
|
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);
|
SCOPE_INFO_FMT([flags], "CheckCaches: %X", flags);
|
||||||
@@ -2103,10 +2103,10 @@ void StateGameLoop()
|
|||||||
CallWindowGameTickEvent();
|
CallWindowGameTickEvent();
|
||||||
NewsLoop();
|
NewsLoop();
|
||||||
} else {
|
} 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. */
|
/* Save the desync savegame if needed. */
|
||||||
char name[MAX_PATH];
|
char name[MAX_PATH];
|
||||||
seprintf(name, lastof(name), "dmp_cmds_%08x_%08x.sav", _settings_game.game_creation.generation_seed, _date);
|
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);
|
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 &&
|
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;
|
_do_autosave = true;
|
||||||
_check_special_modes = true;
|
_check_special_modes = true;
|
||||||
SetWindowDirty(WC_STATUS_BAR, 0);
|
SetWindowDirty(WC_STATUS_BAR, 0);
|
||||||
|
@@ -979,6 +979,6 @@ public:
|
|||||||
inline const DispatchSchedule &GetDispatchScheduleByIndex(uint index) const { return this->dispatch_schedules[index]; }
|
inline const DispatchSchedule &GetDispatchScheduleByIndex(uint index) const { return this->dispatch_schedules[index]; }
|
||||||
};
|
};
|
||||||
|
|
||||||
void ShiftOrderDates(int interval);
|
void ShiftOrderDates(DateDelta interval);
|
||||||
|
|
||||||
#endif /* ORDER_BASE_H */
|
#endif /* ORDER_BASE_H */
|
||||||
|
@@ -3042,7 +3042,7 @@ bool EvaluateDispatchSlotConditionalOrder(const Order *order, const Vehicle *v,
|
|||||||
} else {
|
} else {
|
||||||
extern DateTicksScaled GetScheduledDispatchTime(const DispatchSchedule &ds, DateTicksScaled leave_time);
|
extern DateTicksScaled GetScheduledDispatchTime(const DispatchSchedule &ds, DateTicksScaled leave_time);
|
||||||
DateTicksScaled slot = GetScheduledDispatchTime(sched, _scaled_date_ticks);
|
DateTicksScaled slot = GetScheduledDispatchTime(sched, _scaled_date_ticks);
|
||||||
offset = (slot - sched.GetScheduledDispatchStartTick()) % sched.GetScheduledDispatchDuration();
|
offset = (slot - sched.GetScheduledDispatchStartTick()).base() % sched.GetScheduledDispatchDuration();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool value;
|
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_RELIABILITY: skip_order = OrderConditionCompare(occ, ToPercent16(v->reliability), value); break;
|
||||||
case OCV_MAX_RELIABILITY: skip_order = OrderConditionCompare(occ, ToPercent16(v->GetEngine()->reliability), value); break;
|
case OCV_MAX_RELIABILITY: skip_order = OrderConditionCompare(occ, ToPercent16(v->GetEngine()->reliability), value); break;
|
||||||
case OCV_MAX_SPEED: skip_order = OrderConditionCompare(occ, v->GetDisplayMaxSpeed() * 10 / 16, value); break;
|
case OCV_MAX_SPEED: skip_order = OrderConditionCompare(occ, v->GetDisplayMaxSpeed() * 10 / 16, value); break;
|
||||||
case OCV_AGE: skip_order = OrderConditionCompare(occ, 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_REQUIRES_SERVICE: skip_order = OrderConditionCompare(occ, v->NeedsServicing(), value); break;
|
||||||
case OCV_UNCONDITIONALLY: skip_order = true; break;
|
case OCV_UNCONDITIONALLY: skip_order = true; break;
|
||||||
case OCV_CARGO_WAITING: {
|
case OCV_CARGO_WAITING: {
|
||||||
@@ -3172,7 +3172,7 @@ VehicleOrderID ProcessConditionalOrder(const Order *order, const Vehicle *v, Pro
|
|||||||
skip_order = ord->UpdateJumpCounter((byte)value, mode == PCO_DRY_RUN);
|
skip_order = ord->UpdateJumpCounter((byte)value, mode == PCO_DRY_RUN);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case OCV_REMAINING_LIFETIME: skip_order = OrderConditionCompare(occ, std::max(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: {
|
case OCV_COUNTER_VALUE: {
|
||||||
const TraceRestrictCounter* ctr = TraceRestrictCounter::GetIfValid(GB(order->GetXData(), 16, 16));
|
const TraceRestrictCounter* ctr = TraceRestrictCounter::GetIfValid(GB(order->GetXData(), 16, 16));
|
||||||
if (ctr != nullptr) {
|
if (ctr != nullptr) {
|
||||||
@@ -3690,7 +3690,7 @@ CommandCost CmdMassChangeOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, u
|
|||||||
return CommandCost();
|
return CommandCost();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShiftOrderDates(int interval)
|
void ShiftOrderDates(DateDelta interval)
|
||||||
{
|
{
|
||||||
SetWindowClassesDirty(WC_VEHICLE_ORDERS);
|
SetWindowClassesDirty(WC_VEHICLE_ORDERS);
|
||||||
SetWindowClassesDirty(WC_VEHICLE_TIMETABLE);
|
SetWindowClassesDirty(WC_VEHICLE_TIMETABLE);
|
||||||
|
@@ -325,7 +325,7 @@ RailTypes AddDateIntroducedRailTypes(RailTypes current, Date date)
|
|||||||
if (rti->label == 0) continue;
|
if (rti->label == 0) continue;
|
||||||
|
|
||||||
/* Not date introduced. */
|
/* Not date introduced. */
|
||||||
if (!IsInsideMM(rti->introduction_date, 0, MAX_DAY)) continue;
|
if (!IsInsideMM(rti->introduction_date, 0, MAX_DATE.base())) continue;
|
||||||
|
|
||||||
/* Not yet introduced at this date. */
|
/* Not yet introduced at this date. */
|
||||||
if (rti->introduction_date > date) continue;
|
if (rti->introduction_date > date) continue;
|
||||||
@@ -403,7 +403,7 @@ RailTypes GetRailTypes(bool introduces)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (introduces) return AddDateIntroducedRailTypes(rts, MAX_DAY);
|
if (introduces) return AddDateIntroducedRailTypes(rts, MAX_DATE);
|
||||||
return rts;
|
return rts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -147,7 +147,7 @@ bool HasRoadTypeAvail(const CompanyID company, RoadType roadtype)
|
|||||||
if (rti->label == 0) return false;
|
if (rti->label == 0) return false;
|
||||||
|
|
||||||
/* Not yet introduced at this date. */
|
/* Not yet introduced at this date. */
|
||||||
if (IsInsideMM(rti->introduction_date, 0, MAX_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.
|
* 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;
|
if (rti->label == 0) continue;
|
||||||
|
|
||||||
/* Not date introduced. */
|
/* 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. */
|
/* Not yet introduced at this date. */
|
||||||
if (rti->introduction_date > date) continue;
|
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;
|
return rts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1790,19 +1790,19 @@ bool AfterLoadGame()
|
|||||||
/* Time starts at 0 instead of 1920.
|
/* Time starts at 0 instead of 1920.
|
||||||
* Account for this in older games by adding an offset */
|
* Account for this in older games by adding an offset */
|
||||||
if (IsSavegameVersionBefore(SLV_31)) {
|
if (IsSavegameVersionBefore(SLV_31)) {
|
||||||
_date += DAYS_TILL_ORIGINAL_BASE_YEAR;
|
_date += DAYS_TILL_ORIGINAL_BASE_YEAR.AsDelta();
|
||||||
SetScaledTickVariables();
|
SetScaledTickVariables();
|
||||||
ConvertDateToYMD(_date, &_cur_date_ymd);
|
ConvertDateToYMD(_date, &_cur_date_ymd);
|
||||||
UpdateCachedSnowLine();
|
UpdateCachedSnowLine();
|
||||||
|
|
||||||
for (Station *st : Station::Iterate()) st->build_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;
|
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;
|
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 (Company *c : Company::Iterate()) c->inaugurated_year += ORIGINAL_BASE_YEAR;
|
||||||
for (Industry *i : Industry::Iterate()) i->last_prod_year += ORIGINAL_BASE_YEAR;
|
for (Industry *i : Industry::Iterate()) i->last_prod_year += ORIGINAL_BASE_YEAR;
|
||||||
|
|
||||||
for (Vehicle *v : Vehicle::Iterate()) {
|
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;
|
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 the start date is 0, the vehicle is not waiting to start and can be ignored. */
|
||||||
if (v->timetable_start == 0) continue;
|
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)) {
|
} else if (!SlXvIsFeaturePresent(XSLFI_TIMETABLES_START_TICKS, 3)) {
|
||||||
extern btree::btree_map<VehicleID, uint16> _old_timetable_start_subticks_map;
|
extern btree::btree_map<VehicleID, uint16> _old_timetable_start_subticks_map;
|
||||||
@@ -3612,10 +3612,10 @@ bool AfterLoadGame()
|
|||||||
if (v->timetable_start == 0) continue;
|
if (v->timetable_start == 0) continue;
|
||||||
|
|
||||||
if (SlXvIsFeatureMissing(XSLFI_TIMETABLES_START_TICKS)) {
|
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)) {
|
if (SlXvIsFeaturePresent(XSLFI_TIMETABLES_START_TICKS, 2, 2)) {
|
||||||
v->timetable_start += _old_timetable_start_subticks_map[v->index];
|
v->timetable_start += _old_timetable_start_subticks_map[v->index];
|
||||||
@@ -4194,7 +4194,7 @@ bool AfterLoadGame()
|
|||||||
|
|
||||||
for (OrderList *order_list : OrderList::Iterate()) {
|
for (OrderList *order_list : OrderList::Iterate()) {
|
||||||
for (DispatchSchedule &ds : order_list->GetScheduledDispatchScheduleSet()) {
|
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);
|
ds.SetScheduledDispatchStartTick(start_tick);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -104,7 +104,7 @@ struct DATEChunkHandler : ChunkHandler {
|
|||||||
this->LoadCommon(_date_check_desc, _date_check_sl_compat);
|
this->LoadCommon(_date_check_desc, _date_check_sl_compat);
|
||||||
|
|
||||||
if (IsSavegameVersionBefore(SLV_31)) {
|
if (IsSavegameVersionBefore(SLV_31)) {
|
||||||
_load_check_data.current_date += DAYS_TILL_ORIGINAL_BASE_YEAR;
|
_load_check_data.current_date += DAYS_TILL_ORIGINAL_BASE_YEAR.AsDelta();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@@ -674,9 +674,9 @@ bool DispatchSchedule::UpdateScheduledDispatchToDate(DateTicksScaled now)
|
|||||||
{
|
{
|
||||||
bool update_windows = false;
|
bool update_windows = false;
|
||||||
if (this->GetScheduledDispatchStartTick() == 0) {
|
if (this->GetScheduledDispatchStartTick() == 0) {
|
||||||
DateTicksScaled start = now - (now % this->GetScheduledDispatchDuration());
|
DateTicksScaled start = now - (now.base() % this->GetScheduledDispatchDuration());
|
||||||
this->SetScheduledDispatchStartTick(start);
|
this->SetScheduledDispatchStartTick(start);
|
||||||
int64 last_dispatch = -start;
|
int64 last_dispatch = -(start.base());
|
||||||
if (last_dispatch < INT_MIN && _settings_game.game_time.time_in_minutes) {
|
if (last_dispatch < INT_MIN && _settings_game.game_time.time_in_minutes) {
|
||||||
/* Advance by multiples of 24 hours */
|
/* Advance by multiples of 24 hours */
|
||||||
const int64 day = 24 * 60 * _settings_game.game_time.ticks_per_minute;
|
const int64 day = 24 * 60 * _settings_game.game_time.ticks_per_minute;
|
||||||
|
@@ -67,7 +67,7 @@ enum SchdispatchWidgets {
|
|||||||
*/
|
*/
|
||||||
static void SetScheduleStartDateIntl(uint32 p1, DateTicksScaled date)
|
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) {
|
if (extra_slots > 0 && offset > 0 && !wrap_mode) {
|
||||||
DateTicksScaled end_tick = start_tick + duration;
|
DateTicksScaled end_tick = start_tick + duration;
|
||||||
DateTicksScaled max_extra_slots = (end_tick - 1 - date) / offset;
|
int64 max_extra_slots = (end_tick - 1 - date).base() / offset;
|
||||||
if (max_extra_slots < extra_slots) extra_slots = static_cast<uint>(std::max<DateTicksScaled>(0, max_extra_slots));
|
if (max_extra_slots < extra_slots) extra_slots = static_cast<uint>(std::max<int64>(0, max_extra_slots));
|
||||||
extra_slots = std::min<uint>(extra_slots, UINT16_MAX);
|
extra_slots = std::min<uint>(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) {
|
if (_settings_time.time_in_minutes) {
|
||||||
/* Set to 00:00 of today, and 1 day */
|
/* Set to 00:00 of today, and 1 day */
|
||||||
|
|
||||||
start_tick = MINUTES_DATE(MINUTES_DAY(CURRENT_MINUTE), 0, 0);
|
start_tick = _settings_time.FromTickMinutes(_settings_time.NowInTickMinutes().ToSameDayClockTime(0, 0));
|
||||||
start_tick -= _settings_time.clock_offset;
|
|
||||||
start_tick *= _settings_time.ticks_per_minute;
|
|
||||||
|
|
||||||
duration = 24 * 60 * _settings_time.ticks_per_minute;
|
duration = 24 * 60 * _settings_time.ticks_per_minute;
|
||||||
} else {
|
} else {
|
||||||
/* Set Jan 1st and 365 day */
|
/* Set Jan 1st and 365 day */
|
||||||
start_tick = DateToScaledDateTicks(DAYS_TILL(_cur_year));
|
start_tick = DateToScaledDateTicks(DateAtStartOfYear(_cur_year));
|
||||||
duration = 365 * DAY_TICKS;
|
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 {
|
struct SchdispatchWindow : GeneralVehicleWindow {
|
||||||
@@ -700,12 +698,7 @@ struct SchdispatchWindow : GeneralVehicleWindow {
|
|||||||
case WID_SCHDISPATCH_SET_START_DATE: {
|
case WID_SCHDISPATCH_SET_START_DATE: {
|
||||||
if (!this->IsScheduleSelected()) break;
|
if (!this->IsScheduleSelected()) break;
|
||||||
if (_settings_time.time_in_minutes && _settings_client.gui.timetable_start_text_entry) {
|
if (_settings_time.time_in_minutes && _settings_client.gui.timetable_start_text_entry) {
|
||||||
uint64 time = _scaled_date_ticks;
|
SetDParam(0, _settings_time.NowInTickMinutes().ClockHHMM());
|
||||||
time /= _settings_time.ticks_per_minute;
|
|
||||||
time += _settings_time.clock_offset;
|
|
||||||
time %= (24 * 60);
|
|
||||||
time = (time % 60) + (((time / 60) % 24) * 100);
|
|
||||||
SetDParam(0, time);
|
|
||||||
ShowQueryString(STR_JUST_INT, STR_SCHDISPATCH_START_CAPTION_MINUTE, 31, this, CS_NUMERAL, QSF_ACCEPT_UNCHANGED);
|
ShowQueryString(STR_JUST_INT, STR_SCHDISPATCH_START_CAPTION_MINUTE, 31, this, CS_NUMERAL, QSF_ACCEPT_UNCHANGED);
|
||||||
} else {
|
} else {
|
||||||
ShowSetDateWindow(this, v->index | (this->schedule_index << 20), _scaled_date_ticks, _cur_year, _cur_year + 15, SetScheduleStartDateCallback, STR_SCHDISPATCH_SET_START, STR_SCHDISPATCH_START_TOOLTIP);
|
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) {
|
if (val >= 0 && end != nullptr && *end == 0) {
|
||||||
uint minutes = (val % 100) % 60;
|
uint minutes = (val % 100) % 60;
|
||||||
uint hours = (val / 100) % 24;
|
uint hours = (val / 100) % 24;
|
||||||
DateTicksScaled slot = MINUTES_DATE(MINUTES_DAY(CURRENT_MINUTE), hours, minutes);
|
DateTicksScaled slot = _settings_time.FromTickMinutes(_settings_time.NowInTickMinutes().ToSameDayClockTime(hours, minutes));
|
||||||
slot -= _settings_time.clock_offset;
|
|
||||||
slot *= _settings_time.ticks_per_minute;
|
|
||||||
ScheduleAddIntl(v->index | (this->schedule_index << 20), slot, 0, 0);
|
ScheduleAddIntl(v->index | (this->schedule_index << 20), slot, 0, 0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -885,9 +876,7 @@ struct SchdispatchWindow : GeneralVehicleWindow {
|
|||||||
if (val >= 0 && end != nullptr && *end == 0) {
|
if (val >= 0 && end != nullptr && *end == 0) {
|
||||||
uint minutes = (val % 100) % 60;
|
uint minutes = (val % 100) % 60;
|
||||||
uint hours = (val / 100) % 24;
|
uint hours = (val / 100) % 24;
|
||||||
DateTicksScaled start = MINUTES_DATE(MINUTES_DAY(CURRENT_MINUTE), hours, minutes);
|
DateTicksScaled start = _settings_time.FromTickMinutes(_settings_time.NowInTickMinutes().ToSameDayClockTime(hours, minutes));
|
||||||
start -= _settings_time.clock_offset;
|
|
||||||
start *= _settings_time.ticks_per_minute;
|
|
||||||
SetScheduleStartDateIntl(v->index | (this->schedule_index << 20), start);
|
SetScheduleStartDateIntl(v->index | (this->schedule_index << 20), start);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -974,9 +963,7 @@ struct SchdispatchWindow : GeneralVehicleWindow {
|
|||||||
}
|
}
|
||||||
if (end < start || step == 0 || !this->IsScheduleSelected()) return;
|
if (end < start || step == 0 || !this->IsScheduleSelected()) return;
|
||||||
|
|
||||||
DateTicksScaled slot = MINUTES_DATE(MINUTES_DAY(CURRENT_MINUTE), 0, start);
|
DateTicksScaled slot = _settings_time.FromTickMinutes(_settings_time.NowInTickMinutes().ToSameDayClockTime(0, start));
|
||||||
slot -= _settings_time.clock_offset;
|
|
||||||
slot *= _settings_time.ticks_per_minute;
|
|
||||||
ScheduleAddIntl(this->vehicle->index | (this->schedule_index << 20), slot, (end - start) / step, step * _settings_time.ticks_per_minute, wrap_mode);
|
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 {
|
struct ScheduledDispatchAddSlotsWindow : Window {
|
||||||
uint start;
|
ClockFaceMinutes start;
|
||||||
uint step;
|
ClockFaceMinutes step;
|
||||||
uint end;
|
ClockFaceMinutes end;
|
||||||
|
|
||||||
ScheduledDispatchAddSlotsWindow(WindowDesc *desc, WindowNumber window_number, SchdispatchWindow *parent) :
|
ScheduledDispatchAddSlotsWindow(WindowDesc *desc, WindowNumber window_number, SchdispatchWindow *parent) :
|
||||||
Window(desc)
|
Window(desc)
|
||||||
{
|
{
|
||||||
this->start = (_scaled_date_ticks / _settings_time.ticks_per_minute) % (60 * 24);
|
this->start = _settings_time.NowInTickMinutes().ToClockFaceMinutes();
|
||||||
this->step = 30;
|
this->step = 30;
|
||||||
this->end = this->start + 60;
|
this->end = this->start + 60;
|
||||||
this->parent = parent;
|
this->parent = parent;
|
||||||
@@ -1137,33 +1124,33 @@ struct ScheduledDispatchAddSlotsWindow : Window {
|
|||||||
virtual void SetStringParameters(int widget) const override
|
virtual void SetStringParameters(int widget) const override
|
||||||
{
|
{
|
||||||
switch (widget) {
|
switch (widget) {
|
||||||
case WID_SCHDISPATCH_ADD_SLOT_START_HOUR: SetDParam(0, MINUTES_HOUR(start)); break;
|
case WID_SCHDISPATCH_ADD_SLOT_START_HOUR: SetDParam(0, start.ClockHour()); break;
|
||||||
case WID_SCHDISPATCH_ADD_SLOT_START_MINUTE: SetDParam(0, MINUTES_MINUTE(start)); break;
|
case WID_SCHDISPATCH_ADD_SLOT_START_MINUTE: SetDParam(0, start.ClockMinute()); break;
|
||||||
case WID_SCHDISPATCH_ADD_SLOT_STEP_HOUR: SetDParam(0, MINUTES_HOUR(step)); break;
|
case WID_SCHDISPATCH_ADD_SLOT_STEP_HOUR: SetDParam(0, step.ClockHour()); break;
|
||||||
case WID_SCHDISPATCH_ADD_SLOT_STEP_MINUTE: SetDParam(0, MINUTES_MINUTE(step)); break;
|
case WID_SCHDISPATCH_ADD_SLOT_STEP_MINUTE: SetDParam(0, step.ClockMinute()); break;
|
||||||
case WID_SCHDISPATCH_ADD_SLOT_END_HOUR: SetDParam(0, MINUTES_HOUR(end)); break;
|
case WID_SCHDISPATCH_ADD_SLOT_END_HOUR: SetDParam(0, end.ClockHour()); break;
|
||||||
case WID_SCHDISPATCH_ADD_SLOT_END_MINUTE: SetDParam(0, MINUTES_MINUTE(end)); break;
|
case WID_SCHDISPATCH_ADD_SLOT_END_MINUTE: SetDParam(0, end.ClockMinute()); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void OnClick(Point pt, int widget, int click_count) override
|
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;
|
DropDownList list;
|
||||||
for (uint i = 0; i < 24; i++) {
|
for (uint i = 0; i < 24; i++) {
|
||||||
SetDParam(0, i);
|
SetDParam(0, i);
|
||||||
list.emplace_back(new DropDownListStringItem(STR_JUST_INT, i, false));
|
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;
|
DropDownList list;
|
||||||
for (uint i = 0; i < 60; i++) {
|
for (uint i = 0; i < 60; i++) {
|
||||||
SetDParam(0, i);
|
SetDParam(0, i);
|
||||||
list.emplace_back(new DropDownListStringItem(STR_JUST_INT, i, false));
|
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) {
|
switch (widget) {
|
||||||
@@ -1187,7 +1174,7 @@ struct ScheduledDispatchAddSlotsWindow : Window {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case WID_SCHDISPATCH_ADD_SLOT_ADD_BUTTON:
|
case WID_SCHDISPATCH_ADD_SLOT_ADD_BUTTON:
|
||||||
static_cast<SchdispatchWindow *>(this->parent)->AddMultipleDepartureSlots(this->start, this->step, this->end);
|
static_cast<SchdispatchWindow *>(this->parent)->AddMultipleDepartureSlots(this->start.base(), this->step.base(), this->end.base());
|
||||||
this->Close();
|
this->Close();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1197,22 +1184,22 @@ struct ScheduledDispatchAddSlotsWindow : Window {
|
|||||||
{
|
{
|
||||||
switch (widget) {
|
switch (widget) {
|
||||||
case WID_SCHDISPATCH_ADD_SLOT_START_HOUR:
|
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;
|
break;
|
||||||
case WID_SCHDISPATCH_ADD_SLOT_START_MINUTE:
|
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;
|
break;
|
||||||
case WID_SCHDISPATCH_ADD_SLOT_STEP_HOUR:
|
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;
|
break;
|
||||||
case WID_SCHDISPATCH_ADD_SLOT_STEP_MINUTE:
|
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;
|
break;
|
||||||
case WID_SCHDISPATCH_ADD_SLOT_END_HOUR:
|
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;
|
break;
|
||||||
case WID_SCHDISPATCH_ADD_SLOT_END_MINUTE:
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -57,5 +57,5 @@
|
|||||||
{
|
{
|
||||||
if (!IsValidBaseStation(station_id)) return ScriptDate::DATE_INVALID;
|
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();
|
||||||
}
|
}
|
||||||
|
@@ -50,5 +50,5 @@ static NetworkClientInfo *FindClientInfo(ScriptClient::ClientID client)
|
|||||||
{
|
{
|
||||||
NetworkClientInfo *ci = FindClientInfo(client);
|
NetworkClientInfo *ci = FindClientInfo(client);
|
||||||
if (ci == nullptr) return ScriptDate::DATE_INVALID;
|
if (ci == nullptr) return ScriptDate::DATE_INVALID;
|
||||||
return (ScriptDate::Date)ci->join_date;
|
return (ScriptDate::Date)ci->join_date.base();
|
||||||
}
|
}
|
||||||
|
@@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
/* static */ ScriptDate::Date ScriptDate::GetCurrentDate()
|
/* static */ ScriptDate::Date ScriptDate::GetCurrentDate()
|
||||||
{
|
{
|
||||||
return (ScriptDate::Date)_date;
|
return (ScriptDate::Date)_date.base();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ SQInteger ScriptDate::GetDayLengthFactor()
|
/* static */ SQInteger ScriptDate::GetDayLengthFactor()
|
||||||
@@ -66,7 +66,7 @@
|
|||||||
if (day_of_month < 1 || day_of_month > 31) return DATE_INVALID;
|
if (day_of_month < 1 || day_of_month > 31) return DATE_INVALID;
|
||||||
if (year < 0 || year > MAX_YEAR) return DATE_INVALID;
|
if (year < 0 || year > 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()
|
/* static */ SQInteger ScriptDate::GetSystemTime()
|
||||||
@@ -88,17 +88,17 @@
|
|||||||
|
|
||||||
/* static */ SQInteger ScriptDate::GetCurrentScaledDateTicks()
|
/* 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;
|
TickMinutes minutes = _settings_game.game_time.ToTickMinutes(DateTicksScaled(ticks));
|
||||||
return MINUTES_HOUR(minutes);
|
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;
|
TickMinutes minutes = _settings_game.game_time.ToTickMinutes(DateTicksScaled(ticks));
|
||||||
return MINUTES_MINUTE(minutes);
|
return minutes.ClockMinute();
|
||||||
}
|
}
|
||||||
|
@@ -31,7 +31,7 @@ public:
|
|||||||
* compose valid date values for a known year, month and day.
|
* compose valid date values for a known year, month and day.
|
||||||
*/
|
*/
|
||||||
enum Date {
|
enum Date {
|
||||||
DATE_INVALID = ::INVALID_DATE, ///< 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 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 */
|
#endif /* SCRIPT_DATE_HPP */
|
||||||
|
@@ -131,7 +131,7 @@
|
|||||||
if (!IsValidEngine(engine_id)) return -1;
|
if (!IsValidEngine(engine_id)) return -1;
|
||||||
if (GetVehicleType(engine_id) == ScriptVehicle::VT_RAIL && IsWagon(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)
|
/* static */ Money ScriptEngine::GetRunningCost(EngineID engine_id)
|
||||||
@@ -171,7 +171,7 @@
|
|||||||
{
|
{
|
||||||
if (!IsValidEngine(engine_id)) return ScriptDate::DATE_INVALID;
|
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)
|
/* static */ ScriptVehicle::VehicleType ScriptEngine::GetVehicleType(EngineID engine_id)
|
||||||
|
@@ -52,7 +52,7 @@
|
|||||||
{
|
{
|
||||||
Industry *i = Industry::GetIfValid(industry_id);
|
Industry *i = Industry::GetIfValid(industry_id);
|
||||||
if (i == nullptr) return ScriptDate::DATE_INVALID;
|
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)
|
/* static */ bool ScriptIndustry::SetText(IndustryID industry_id, Text *text)
|
||||||
@@ -230,11 +230,11 @@
|
|||||||
if (i == nullptr) return ScriptDate::DATE_INVALID;
|
if (i == nullptr) return ScriptDate::DATE_INVALID;
|
||||||
|
|
||||||
if (cargo_type == CT_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 {
|
} else {
|
||||||
int index = i->GetCargoAcceptedIndex(cargo_type);
|
int index = i->GetCargoAcceptedIndex(cargo_type);
|
||||||
if (index < 0) return ScriptDate::DATE_INVALID;
|
if (index < 0) return ScriptDate::DATE_INVALID;
|
||||||
return (ScriptDate::Date)i->last_cargo_accepted_at[index];
|
return (ScriptDate::Date)i->last_cargo_accepted_at[index].base();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -190,7 +190,7 @@ static inline bool StoryPageElementTypeRequiresText(StoryPageElementType type)
|
|||||||
EnforcePrecondition(ScriptDate::DATE_INVALID, IsValidStoryPage(story_page_id));
|
EnforcePrecondition(ScriptDate::DATE_INVALID, IsValidStoryPage(story_page_id));
|
||||||
EnforceDeityMode(ScriptDate::DATE_INVALID);
|
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)
|
/* static */ bool ScriptStoryPage::SetDate(StoryPageID story_page_id, ScriptDate::Date date)
|
||||||
|
@@ -310,7 +310,7 @@
|
|||||||
{
|
{
|
||||||
if (!IsValidVehicle(vehicle_id)) return -1;
|
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)
|
/* static */ SQInteger ScriptVehicle::GetWagonAge(VehicleID vehicle_id, SQInteger wagon)
|
||||||
@@ -322,21 +322,21 @@
|
|||||||
if (v->type == VEH_TRAIN) {
|
if (v->type == VEH_TRAIN) {
|
||||||
while (wagon-- > 0) v = ::Train::From(v)->GetNextUnit();
|
while (wagon-- > 0) v = ::Train::From(v)->GetNextUnit();
|
||||||
}
|
}
|
||||||
return v->age;
|
return v->age.base();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ SQInteger ScriptVehicle::GetMaxAge(VehicleID vehicle_id)
|
/* static */ SQInteger ScriptVehicle::GetMaxAge(VehicleID vehicle_id)
|
||||||
{
|
{
|
||||||
if (!IsPrimaryVehicle(vehicle_id)) return -1;
|
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)
|
/* static */ SQInteger ScriptVehicle::GetAgeLeft(VehicleID vehicle_id)
|
||||||
{
|
{
|
||||||
if (!IsPrimaryVehicle(vehicle_id)) return -1;
|
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)
|
/* static */ SQInteger ScriptVehicle::GetCurrentSpeed(VehicleID vehicle_id)
|
||||||
|
@@ -135,6 +135,22 @@ struct TimeSettings {
|
|||||||
bool time_in_minutes; ///< whether to use the hh:mm conversion when printing dates
|
bool time_in_minutes; ///< whether to use the hh:mm conversion when printing dates
|
||||||
uint16 ticks_per_minute; ///< how many ticks per minute
|
uint16 ticks_per_minute; ///< how many ticks per minute
|
||||||
uint16 clock_offset; ///< clock offset in minutes
|
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. */
|
/** Settings related to the GUI and other stuff that is not saved in the savegame. */
|
||||||
|
@@ -39,7 +39,7 @@ SaveLoadTable GetLinkGraphDesc()
|
|||||||
|
|
||||||
void GetLinkGraphJobDayLengthScaleAfterLoad(LinkGraphJob *lgj)
|
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;
|
lgj->join_date_ticks += LinkGraphSchedule::SPAWN_JOIN_TICK;
|
||||||
|
|
||||||
uint recalc_scale;
|
uint recalc_scale;
|
||||||
|
@@ -162,7 +162,7 @@ static void Check_DATE()
|
|||||||
{
|
{
|
||||||
SlGlobList(_date_check_desc);
|
SlGlobList(_date_check_desc);
|
||||||
if (IsSavegameVersionBefore(SLV_31)) {
|
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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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);
|
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++) {
|
for (EngineID i = 0; i < 256; i++) {
|
||||||
int oi = ttd_to_tto[i];
|
int oi = ttd_to_tto[i];
|
||||||
@@ -403,17 +403,17 @@ static bool FixTTOEngines()
|
|||||||
|
|
||||||
if (oi == 255) {
|
if (oi == 255) {
|
||||||
/* Default engine is used */
|
/* Default engine is used */
|
||||||
_date += DAYS_TILL_ORIGINAL_BASE_YEAR;
|
_date += DAYS_TILL_ORIGINAL_BASE_YEAR.AsDelta();
|
||||||
StartupOneEngine(e, aging_date, 0, INT_MAX);
|
StartupOneEngine(e, aging_date, 0, INT_MAX);
|
||||||
CalcEngineReliability(e, false);
|
CalcEngineReliability(e, false);
|
||||||
e->intro_date -= DAYS_TILL_ORIGINAL_BASE_YEAR;
|
e->intro_date -= DAYS_TILL_ORIGINAL_BASE_YEAR.AsDelta();
|
||||||
_date -= DAYS_TILL_ORIGINAL_BASE_YEAR;
|
_date -= DAYS_TILL_ORIGINAL_BASE_YEAR.AsDelta();
|
||||||
|
|
||||||
/* Make sure for example monorail and maglev are available when they should be */
|
/* Make sure for example monorail and maglev are available when they should be */
|
||||||
if (_date >= e->intro_date && HasBit(e->info.climates, 0)) {
|
if (_date >= e->intro_date && HasBit(e->info.climates, 0)) {
|
||||||
e->flags |= ENGINE_AVAILABLE;
|
e->flags |= ENGINE_AVAILABLE;
|
||||||
e->company_avail = MAX_UVALUE(CompanyMask);
|
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 {
|
} else {
|
||||||
/* Using data from TTO savegame */
|
/* Using data from TTO savegame */
|
||||||
|
@@ -3726,7 +3726,7 @@ SaveOrLoadResult SaveOrLoad(const std::string &filename, SaveLoadOperation fop,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (fop == SLO_SAVE) { // SAVE game
|
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;
|
if (!_settings_client.gui.threaded_saves) threaded = false;
|
||||||
|
|
||||||
return DoSave(new FileWriter(fh), threaded);
|
return DoSave(new FileWriter(fh), threaded);
|
||||||
|
@@ -17,6 +17,7 @@
|
|||||||
#include "../scope.h"
|
#include "../scope.h"
|
||||||
#include "../core/ring_buffer.hpp"
|
#include "../core/ring_buffer.hpp"
|
||||||
#include "../core/tinystring_type.hpp"
|
#include "../core/tinystring_type.hpp"
|
||||||
|
#include "../core/strong_typedef_type.hpp"
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -338,7 +339,7 @@ static inline constexpr bool SlCheckPrimitiveTypeVar(VarType type)
|
|||||||
if (GetVarMemType(type) == SLE_VAR_CNAME) {
|
if (GetVarMemType(type) == SLE_VAR_CNAME) {
|
||||||
return std::is_same_v<T, char *> || std::is_same_v<T, const char *> || std::is_same_v<T, TinyString>;
|
return std::is_same_v<T, char *> || std::is_same_v<T, const char *> || std::is_same_v<T, TinyString>;
|
||||||
}
|
}
|
||||||
if (!std::is_integral_v<T> && !std::is_enum_v<T> && !sl_is_instance<T, OverflowSafeInt>{}) return false;
|
if (!std::is_integral_v<T> && !std::is_enum_v<T> && !sl_is_instance<T, OverflowSafeInt>{} && !std::is_base_of_v<StrongTypedefBase, T>) return false;
|
||||||
return sizeof(T) == SlVarSize(type);
|
return sizeof(T) == SlVarSize(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -4452,11 +4452,11 @@ void DeleteStaleLinks(Station *from)
|
|||||||
Station *to = Station::Get((*lg)[to_id].Station());
|
Station *to = Station::Get((*lg)[to_id].Station());
|
||||||
assert(to->goods[c].node == to_id);
|
assert(to->goods[c].node == to_id);
|
||||||
assert(_date >= edge.LastUpdate());
|
assert(_date >= edge.LastUpdate());
|
||||||
uint timeout = std::max<uint>((LinkGraph::MIN_TIMEOUT_DISTANCE + (DistanceManhattan(from->xy, to->xy) >> 3)) / _settings_game.economy.day_length_factor, 1);
|
DateDelta timeout = std::max<uint>((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) {
|
if (edge.LastAircraftUpdate() != INVALID_DATE && (_date - edge.LastAircraftUpdate()) > timeout) {
|
||||||
edge.ClearAircraft();
|
edge.ClearAircraft();
|
||||||
}
|
}
|
||||||
if ((uint)(_date - edge.LastUpdate()) > timeout) {
|
if ((_date - edge.LastUpdate()) > timeout) {
|
||||||
bool updated = false;
|
bool updated = false;
|
||||||
|
|
||||||
if (auto_distributed) {
|
if (auto_distributed) {
|
||||||
@@ -4488,7 +4488,7 @@ void DeleteStaleLinks(Station *from)
|
|||||||
// Only run LinkRefresher if vehicle was not already in the cache
|
// Only run LinkRefresher if vehicle was not already in the cache
|
||||||
if (res.second) {
|
if (res.second) {
|
||||||
/* Do not refresh links of vehicles that have been stopped in depot for a long time. */
|
/* Do not refresh links of vehicles that have been stopped in depot for a long time. */
|
||||||
if (!v->IsStoppedInDepot() || static_cast<uint>(_date - v->date_of_last_service) <=
|
if (!v->IsStoppedInDepot() || (_date - v->date_of_last_service) <=
|
||||||
LinkGraph::STALE_LINK_DEPOT_TIMEOUT) {
|
LinkGraph::STALE_LINK_DEPOT_TIMEOUT) {
|
||||||
edge_helper.RecordSize();
|
edge_helper.RecordSize();
|
||||||
LinkRefresher::Run(v, false); // Don't allow merging. Otherwise lg might get deleted.
|
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);
|
if (ge.data != nullptr) ge.data->flows.DeleteFlows(to->index);
|
||||||
RerouteCargo(from, c, to->index, from->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();
|
edge.Restrict();
|
||||||
if (ge.data != nullptr) ge.data->flows.RestrictFlows(to->index);
|
if (ge.data != nullptr) ge.data->flows.RestrictFlows(to->index);
|
||||||
RerouteCargo(from, c, to->index, from->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();
|
edge.Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4643,7 +4643,7 @@ void OnTick_Station()
|
|||||||
void StationDailyLoop()
|
void StationDailyLoop()
|
||||||
{
|
{
|
||||||
// Only record cargo history every second day.
|
// Only record cargo history every second day.
|
||||||
if (_date % 2 != 0) {
|
if (_date.base() % 2 != 0) {
|
||||||
for (Station *st : Station::Iterate()) {
|
for (Station *st : Station::Iterate()) {
|
||||||
st->UpdateCargoHistory();
|
st->UpdateCargoHistory();
|
||||||
}
|
}
|
||||||
|
@@ -59,7 +59,7 @@ struct StatusBarWindow : Window {
|
|||||||
int ticker_scroll;
|
int ticker_scroll;
|
||||||
GUITimer ticker_timer;
|
GUITimer ticker_timer;
|
||||||
GUITimer reminder_timeout;
|
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 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
|
static const int REMINDER_START = 1350; ///< time in ms for reminder notification (red dot on the right) to stay
|
||||||
@@ -211,10 +211,13 @@ struct StatusBarWindow : Window {
|
|||||||
{
|
{
|
||||||
if (_pause_mode != PM_UNPAUSED) return;
|
if (_pause_mode != PM_UNPAUSED) return;
|
||||||
|
|
||||||
if (_settings_time.time_in_minutes && this->last_minute != CURRENT_MINUTE) {
|
if (_settings_time.time_in_minutes) {
|
||||||
this->last_minute = CURRENT_MINUTE;
|
const TickMinutes now = _settings_time.NowInTickMinutes();
|
||||||
|
if (this->last_minute != now) {
|
||||||
|
this->last_minute = now;
|
||||||
this->SetWidgetDirty(WID_S_LEFT);
|
this->SetWidgetDirty(WID_S_LEFT);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (this->ticker_scroll < TICKER_STOP) { // Scrolling text
|
if (this->ticker_scroll < TICKER_STOP) { // Scrolling text
|
||||||
uint count = this->ticker_timer.CountElapsed(delta_ms);
|
uint count = this->ticker_timer.CountElapsed(delta_ms);
|
||||||
|
@@ -413,6 +413,7 @@ static_assert(SIZE_MAX >= UINT32_MAX);
|
|||||||
# define GetString OTTD_GetString
|
# define GetString OTTD_GetString
|
||||||
# define DrawString OTTD_DrawString
|
# define DrawString OTTD_DrawString
|
||||||
# define CloseConnection OTTD_CloseConnection
|
# define CloseConnection OTTD_CloseConnection
|
||||||
|
# define DateDelta OTTD_DateDelta
|
||||||
#endif /* __APPLE__ */
|
#endif /* __APPLE__ */
|
||||||
|
|
||||||
#if defined(__GNUC__) || defined(__clang__)
|
#if defined(__GNUC__) || defined(__clang__)
|
||||||
|
@@ -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)
|
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];
|
char hour[3], minute[3];
|
||||||
seprintf(hour, lastof(hour), "%02i", (int) MINUTES_HOUR(minutes) );
|
seprintf(hour, lastof(hour), "%02i", minutes.ClockHour());
|
||||||
seprintf(minute, lastof(minute), "%02i", (int) MINUTES_MINUTE(minutes));
|
seprintf(minute, lastof(minute), "%02i", minutes.ClockMinute());
|
||||||
if (show_date) {
|
if (show_date) {
|
||||||
int64 final_arg = ScaledDateTicksToDate(ticks);
|
Date date = ScaledDateTicksToDate(ticks);
|
||||||
|
int64 final_arg;
|
||||||
if (_settings_client.gui.date_with_time == 1) {
|
if (_settings_client.gui.date_with_time == 1) {
|
||||||
YearMonthDay ymd;
|
YearMonthDay ymd;
|
||||||
ConvertDateToYMD(final_arg, &ymd);
|
ConvertDateToYMD(date, &ymd);
|
||||||
final_arg = ymd.year;
|
final_arg = ymd.year;
|
||||||
|
} else {
|
||||||
|
final_arg = date.base();
|
||||||
}
|
}
|
||||||
auto tmp_params = MakeParameters(hour, minute, final_arg);
|
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);
|
return FormatString(buff, GetStringPtr(STR_FORMAT_DATE_MINUTES + _settings_client.gui.date_with_time), tmp_params, last, case_index);
|
||||||
|
@@ -94,9 +94,9 @@ WChar GetDecimalSeparatorChar();
|
|||||||
* @param n Index of the string parameter.
|
* @param n Index of the string parameter.
|
||||||
* @param v Value of the string parameter.
|
* @param v Value of the string parameter.
|
||||||
*/
|
*/
|
||||||
static inline void SetDParam(size_t n, uint64 v)
|
template <typename T>
|
||||||
{
|
static inline void SetDParam(size_t n, T &&v) {
|
||||||
_global_string_params.SetParam(n, v);
|
_global_string_params.SetParam(n, std::forward<T>(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetDParamMaxValue(size_t n, uint64 max_value, uint min_count = 0, FontSize size = FS_NORMAL);
|
void SetDParamMaxValue(size_t n, uint64 max_value, uint min_count = 0, FontSize size = FS_NORMAL);
|
||||||
|
@@ -13,6 +13,7 @@
|
|||||||
#include "strings_func.h"
|
#include "strings_func.h"
|
||||||
#include "string_func.h"
|
#include "string_func.h"
|
||||||
#include "core/span_type.hpp"
|
#include "core/span_type.hpp"
|
||||||
|
#include "core/strong_typedef_type.hpp"
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
@@ -155,11 +156,11 @@ public:
|
|||||||
this->parameters[n].string_view = nullptr;
|
this->parameters[n].string_view = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
//template <typename T, std::enable_if_t<std::is_base_of<StrongTypedefBase, T>::value, int> = 0>
|
template <typename T, std::enable_if_t<std::is_base_of<StrongTypedefBase, T>::value, int> = 0>
|
||||||
//void SetParam(size_t n, T v)
|
void SetParam(size_t n, T v)
|
||||||
//{
|
{
|
||||||
// SetParam(n, v.base());
|
SetParam(n, v.base());
|
||||||
//}
|
}
|
||||||
|
|
||||||
void SetParam(size_t n, const char *str)
|
void SetParam(size_t n, const char *str)
|
||||||
{
|
{
|
||||||
|
@@ -1428,7 +1428,7 @@ class NIHSignals : public NIHelper {
|
|||||||
if (it.second.IsOutOfDate()) {
|
if (it.second.IsOutOfDate()) {
|
||||||
b += seprintf(b, lastof(buffer), ", expired");
|
b += seprintf(b, lastof(buffer), ", expired");
|
||||||
} else {
|
} 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);
|
output.print(buffer);
|
||||||
}
|
}
|
||||||
@@ -1532,7 +1532,7 @@ class NIHObject : public NIHelper {
|
|||||||
ConvertDateToYMD(spec->introduction_date, &ymd);
|
ConvertDateToYMD(spec->introduction_date, &ymd);
|
||||||
char *b = buffer + seprintf(buffer, lastof(buffer), " intro: %4i-%02i-%02i",
|
char *b = buffer + seprintf(buffer, lastof(buffer), " intro: %4i-%02i-%02i",
|
||||||
ymd.year, ymd.month + 1, ymd.day);
|
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);
|
ConvertDateToYMD(spec->end_of_life_date, &ymd);
|
||||||
seprintf(b, lastof(buffer), ", end of life: %4i-%02i-%02i",
|
seprintf(b, lastof(buffer), ", end of life: %4i-%02i-%02i",
|
||||||
ymd.year, ymd.month + 1, ymd.day);
|
ymd.year, ymd.month + 1, ymd.day);
|
||||||
|
@@ -121,7 +121,7 @@ static const DrawTileSprites _object_hq[] = {
|
|||||||
|
|
||||||
#undef TILE_SPRITE_LINE
|
#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
|
/* Climates
|
||||||
* T = Temperate
|
* T = Temperate
|
||||||
|
@@ -863,8 +863,8 @@ void UpdateVehicleTimetable(Vehicle *v, bool travelling)
|
|||||||
if (slot > -1) {
|
if (slot > -1) {
|
||||||
just_started = !HasBit(v->vehicle_flags, VF_TIMETABLE_STARTED);
|
just_started = !HasBit(v->vehicle_flags, VF_TIMETABLE_STARTED);
|
||||||
SetBit(v->vehicle_flags, VF_TIMETABLE_STARTED);
|
SetBit(v->vehicle_flags, VF_TIMETABLE_STARTED);
|
||||||
v->lateness_counter = _scaled_date_ticks - slot + wait_offset;
|
v->lateness_counter = (_scaled_date_ticks - slot + wait_offset).AsTicks();
|
||||||
ds.SetScheduledDispatchLastDispatch(slot - ds.GetScheduledDispatchStartTick());
|
ds.SetScheduledDispatchLastDispatch((slot - ds.GetScheduledDispatchStartTick()).AsTicks());
|
||||||
set_scheduled_dispatch = true;
|
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 (!set_scheduled_dispatch) just_started = !HasBit(v->vehicle_flags, VF_TIMETABLE_STARTED);
|
||||||
|
|
||||||
if (v->timetable_start != 0) {
|
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;
|
v->timetable_start = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -198,7 +198,7 @@ static void FillTimetableArrivalDepartureTable(const Vehicle *v, VehicleOrderID
|
|||||||
DateTicksScaled slot = GetScheduledDispatchTime(predicted_ds, _scaled_date_ticks + sum + order->GetTimetabledWait());
|
DateTicksScaled slot = GetScheduledDispatchTime(predicted_ds, _scaled_date_ticks + sum + order->GetTimetabledWait());
|
||||||
predicted_ds.ReturnSchedule(ds);
|
predicted_ds.ReturnSchedule(ds);
|
||||||
if (slot <= -1) return;
|
if (slot <= -1) return;
|
||||||
sum = slot - _scaled_date_ticks;
|
sum = (slot - _scaled_date_ticks).AsTicks();
|
||||||
predicted = true;
|
predicted = true;
|
||||||
no_offset = true;
|
no_offset = true;
|
||||||
} else {
|
} else {
|
||||||
@@ -239,7 +239,7 @@ static void FillTimetableArrivalDepartureTable(const Vehicle *v, VehicleOrderID
|
|||||||
*/
|
*/
|
||||||
static void ChangeTimetableStartIntl(uint32 p1, DateTicksScaled date)
|
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) {
|
if (_settings_time.time_in_minutes && _settings_client.gui.timetable_start_text_entry) {
|
||||||
this->set_start_date_all = v->orders->IsCompleteTimetable() && _ctrl_pressed;
|
this->set_start_date_all = v->orders->IsCompleteTimetable() && _ctrl_pressed;
|
||||||
StringID str = STR_JUST_INT;
|
StringID str = STR_JUST_INT;
|
||||||
uint64 time = _scaled_date_ticks;
|
SetDParam(0, _settings_time.NowInTickMinutes().ClockHHMM());
|
||||||
time /= _settings_time.ticks_per_minute;
|
|
||||||
time += _settings_time.clock_offset;
|
|
||||||
time %= (24 * 60);
|
|
||||||
time = (time % 60) + (((time / 60) % 24) * 100);
|
|
||||||
SetDParam(0, time);
|
|
||||||
ShowQueryString(str, STR_TIMETABLE_STARTING_DATE, 31, this, CS_NUMERAL, QSF_ACCEPT_UNCHANGED);
|
ShowQueryString(str, STR_TIMETABLE_STARTING_DATE, 31, this, CS_NUMERAL, QSF_ACCEPT_UNCHANGED);
|
||||||
} else {
|
} else {
|
||||||
ShowSetDateWindow(this, v->index | (_ctrl_pressed ? 1U << 20 : 0),
|
ShowSetDateWindow(this, v->index | (_ctrl_pressed ? 1U << 20 : 0),
|
||||||
@@ -1123,12 +1118,12 @@ struct TimetableWindow : GeneralVehicleWindow {
|
|||||||
if (val >= 0 && end && *end == 0) {
|
if (val >= 0 && end && *end == 0) {
|
||||||
uint minutes = (val % 100) % 60;
|
uint minutes = (val % 100) % 60;
|
||||||
uint hours = (val / 100) % 24;
|
uint hours = (val / 100) % 24;
|
||||||
DateTicksScaled time = MINUTES_DATE(MINUTES_DAY(CURRENT_MINUTE), hours, minutes);
|
const TickMinutes now = _settings_time.NowInTickMinutes();
|
||||||
time -= _settings_time.clock_offset;
|
TickMinutes time = now.ToSameDayClockTime(hours, minutes);
|
||||||
|
|
||||||
if (time < (CURRENT_MINUTE - 60)) time += 60 * 24;
|
if (time < (now - 60)) time += 60 * 24;
|
||||||
time *= _settings_time.ticks_per_minute;
|
|
||||||
ChangeTimetableStartIntl(v->index | (this->set_start_date_all ? 1 << 20 : 0), time);
|
ChangeTimetableStartIntl(v->index | (this->set_start_date_all ? 1 << 20 : 0), _settings_time.FromTickMinutes(time));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@@ -1033,7 +1033,7 @@ RoadType GetTownRoadType()
|
|||||||
if (HasBit(rti->extra_flags, RXTF_NO_TOWN_MODIFICATION)) continue;
|
if (HasBit(rti->extra_flags, RXTF_NO_TOWN_MODIFICATION)) continue;
|
||||||
|
|
||||||
/* Not yet introduced at this date. */
|
/* 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 (best != nullptr) {
|
||||||
if ((rti->max_speed == 0 ? assume_max_speed : rti->max_speed) < (best->max_speed == 0 ? assume_max_speed : best->max_speed)) continue;
|
if ((rti->max_speed == 0 ? assume_max_speed : rti->max_speed) < (best->max_speed == 0 ? assume_max_speed : best->max_speed)) continue;
|
||||||
|
@@ -2371,17 +2371,17 @@ CommandCost CmdProgramSignalTraceRestrictProgMgmt(TileIndex tile, DoCommandFlag
|
|||||||
|
|
||||||
int GetTraceRestrictTimeDateValue(TraceRestrictTimeDateValueField type)
|
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) {
|
switch (type) {
|
||||||
case TRTDVF_MINUTE:
|
case TRTDVF_MINUTE:
|
||||||
return MINUTES_MINUTE(minutes);
|
return now.ClockMinute();
|
||||||
|
|
||||||
case TRTDVF_HOUR:
|
case TRTDVF_HOUR:
|
||||||
return MINUTES_HOUR(minutes);
|
return now.ClockHour();
|
||||||
|
|
||||||
case TRTDVF_HOUR_MINUTE:
|
case TRTDVF_HOUR_MINUTE:
|
||||||
return (MINUTES_HOUR(minutes) * 100) + MINUTES_MINUTE(minutes);
|
return now.ClockHHMM();
|
||||||
|
|
||||||
case TRTDVF_DAY:
|
case TRTDVF_DAY:
|
||||||
return _cur_date_ymd.day;
|
return _cur_date_ymd.day;
|
||||||
@@ -2396,17 +2396,17 @@ int GetTraceRestrictTimeDateValue(TraceRestrictTimeDateValueField type)
|
|||||||
|
|
||||||
int GetTraceRestrictTimeDateValueFromDate(TraceRestrictTimeDateValueField type, DateTicksScaled scaled_date_ticks)
|
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) {
|
switch (type) {
|
||||||
case TRTDVF_MINUTE:
|
case TRTDVF_MINUTE:
|
||||||
return MINUTES_MINUTE(minutes);
|
return minutes.ClockMinute();
|
||||||
|
|
||||||
case TRTDVF_HOUR:
|
case TRTDVF_HOUR:
|
||||||
return MINUTES_HOUR(minutes);
|
return minutes.ClockHour();
|
||||||
|
|
||||||
case TRTDVF_HOUR_MINUTE:
|
case TRTDVF_HOUR_MINUTE:
|
||||||
return (MINUTES_HOUR(minutes) * 100) + MINUTES_MINUTE(minutes);
|
return minutes.ClockHHMM();
|
||||||
|
|
||||||
case TRTDVF_DAY: {
|
case TRTDVF_DAY: {
|
||||||
YearMonthDay ymd;
|
YearMonthDay ymd;
|
||||||
|
@@ -120,7 +120,7 @@ void ClearAllSignalSpeedRestrictions()
|
|||||||
_signal_speeds.clear();
|
_signal_speeds.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdjustAllSignalSpeedRestrictionTickValues(DateTicksScaled delta)
|
void AdjustAllSignalSpeedRestrictionTickValues(DateTicksScaledDelta delta)
|
||||||
{
|
{
|
||||||
for (auto &it : _signal_speeds) {
|
for (auto &it : _signal_speeds) {
|
||||||
it.second.time_stamp += delta;
|
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)
|
void SetSignalTrainAdaptationSpeed(const Train *v, TileIndex tile, uint16 track)
|
||||||
{
|
{
|
||||||
SignalSpeedKey speed_key = {
|
SignalSpeedKey speed_key = {};
|
||||||
speed_key.signal_tile = tile,
|
speed_key.signal_tile = tile;
|
||||||
speed_key.signal_track = track,
|
speed_key.signal_track = track;
|
||||||
speed_key.last_passing_train_dir = v->GetVehicleTrackdir()
|
speed_key.last_passing_train_dir = v->GetVehicleTrackdir();
|
||||||
};
|
|
||||||
SignalSpeedValue speed_value = {
|
SignalSpeedValue speed_value = {};
|
||||||
speed_value.train_speed = v->First()->cur_speed,
|
speed_value.train_speed = v->First()->cur_speed;
|
||||||
speed_value.time_stamp = GetSpeedRestrictionTimeout(v->First())
|
speed_value.time_stamp = GetSpeedRestrictionTimeout(v->First());
|
||||||
};
|
|
||||||
_signal_speeds[speed_key] = speed_value;
|
_signal_speeds[speed_key] = speed_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -2418,16 +2418,16 @@ void AgeVehicle(Vehicle *v)
|
|||||||
/* Stop if a virtual vehicle */
|
/* Stop if a virtual vehicle */
|
||||||
if (HasBit(v->subtype, GVSF_VIRTUAL)) return;
|
if (HasBit(v->subtype, GVSF_VIRTUAL)) return;
|
||||||
|
|
||||||
if (v->age < MAX_DAY) {
|
if (v->age < MAX_DATE.AsDelta()) {
|
||||||
v->age++;
|
v->age++;
|
||||||
if (v->IsPrimaryVehicle() && v->age == VEHICLE_PROFIT_MIN_AGE + 1) GroupStatistics::VehicleReachedMinAge(v);
|
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;
|
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++) {
|
for (int i = 0; i <= 4; i++) {
|
||||||
if (age == DateAtStartOfYear(i)) {
|
if (age == DateAtStartOfYear(i).AsDelta()) {
|
||||||
v->reliability_spd_dec <<= 1;
|
v->reliability_spd_dec <<= 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -4649,7 +4649,7 @@ void DumpVehicleStats(char *buffer, const char *last)
|
|||||||
buffer += seprintf(buffer, last, " %10s: %5u\n", "total", (uint)Vehicle::GetNumItems());
|
buffer += seprintf(buffer, last, " %10s: %5u\n", "total", (uint)Vehicle::GetNumItems());
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdjustVehicleScaledTickBase(int64 delta)
|
void AdjustVehicleScaledTickBase(DateTicksScaledDelta delta)
|
||||||
{
|
{
|
||||||
for (Vehicle *v : Vehicle::Iterate()) {
|
for (Vehicle *v : Vehicle::Iterate()) {
|
||||||
if (v->timetable_start != 0) v->timetable_start += delta;
|
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()) {
|
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<Date>(v->date_of_last_service + interval, 0);
|
||||||
}
|
}
|
||||||
/* date_of_last_service_newgrf is not updated here as it must stay stable
|
/* date_of_last_service_newgrf is not updated here as it must stay stable
|
||||||
* for vehicles outside of a depot. */
|
* for vehicles outside of a depot. */
|
||||||
|
@@ -317,8 +317,8 @@ public:
|
|||||||
|
|
||||||
/* Related to age and service time */
|
/* Related to age and service time */
|
||||||
Year build_year; ///< Year the vehicle has been built.
|
Year build_year; ///< Year the vehicle has been built.
|
||||||
Date age; ///< Age in days
|
DateDelta age; ///< Age in days
|
||||||
Date max_age; ///< Maximum age
|
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; ///< 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.
|
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.
|
uint16 reliability; ///< Reliability.
|
||||||
@@ -1536,6 +1536,6 @@ void ClearVehicleTickCaches();
|
|||||||
void RemoveFromOtherVehicleTickCache(const Vehicle *v);
|
void RemoveFromOtherVehicleTickCache(const Vehicle *v);
|
||||||
void UpdateAllVehiclesIsDrawn();
|
void UpdateAllVehiclesIsDrawn();
|
||||||
|
|
||||||
void ShiftVehicleDates(int interval);
|
void ShiftVehicleDates(DateDelta interval);
|
||||||
|
|
||||||
#endif /* VEHICLE_BASE_H */
|
#endif /* VEHICLE_BASE_H */
|
||||||
|
@@ -26,7 +26,7 @@
|
|||||||
#define IS_CUSTOM_FIRSTHEAD_SPRITE(x) (x == 0xFD)
|
#define IS_CUSTOM_FIRSTHEAD_SPRITE(x) (x == 0xFD)
|
||||||
#define IS_CUSTOM_SECONDHEAD_SPRITE(x) (x == 0xFE)
|
#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.
|
static const Money VEHICLE_PROFIT_THRESHOLD = 10000; ///< Threshold for a vehicle to be considered making good profit.
|
||||||
|
|
||||||
struct Viewport;
|
struct Viewport;
|
||||||
|
@@ -457,7 +457,7 @@ void DepotSortList(VehicleList *list)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** draw the vehicle profit button in the vehicle list window. */
|
/** 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;
|
SpriteID spr;
|
||||||
|
|
||||||
@@ -1882,8 +1882,8 @@ void BaseVehicleListWindow::DrawVehicleListItems(VehicleID selected_vehicle, int
|
|||||||
switch (this->vehgroups.SortType()) {
|
switch (this->vehgroups.SortType()) {
|
||||||
case VST_AGE: {
|
case VST_AGE: {
|
||||||
str = (v->age + DAYS_IN_YEAR < v->max_age) ? STR_VEHICLE_LIST_AGE : STR_VEHICLE_LIST_AGE_RED;
|
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(3, DateDeltaToYears(v->age));
|
||||||
SetDParam(4, v->max_age / DAYS_IN_LEAP_YEAR);
|
SetDParam(4, DateDeltaToYears(v->max_age));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1938,7 +1938,7 @@ void BaseVehicleListWindow::DrawVehicleListItems(VehicleID selected_vehicle, int
|
|||||||
case VST_TIME_TO_LIVE: {
|
case VST_TIME_TO_LIVE: {
|
||||||
auto years_remaining = (v->max_age / DAYS_IN_LEAP_YEAR) - (v->age / DAYS_IN_LEAP_YEAR);
|
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);
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3079,9 +3079,9 @@ struct VehicleDetailsWindow : Window {
|
|||||||
Rect tr = r.Shrink(WidgetDimensions::scaled.framerect);
|
Rect tr = r.Shrink(WidgetDimensions::scaled.framerect);
|
||||||
|
|
||||||
/* Draw running cost */
|
/* 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(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());
|
SetDParam(3, v->GetDisplayRunningCost());
|
||||||
DrawString(tr, STR_VEHICLE_INFO_AGE_RUNNING_COST_YR);
|
DrawString(tr, STR_VEHICLE_INFO_AGE_RUNNING_COST_YR);
|
||||||
tr.top += GetCharacterHeight(FS_NORMAL);
|
tr.top += GetCharacterHeight(FS_NORMAL);
|
||||||
|
@@ -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) {
|
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;
|
return v_a->age < v_b->age;
|
||||||
|
Reference in New Issue
Block a user