Timetable: Remove timetable_start_subticks, use DateTicksScaled

wip-string
Jonathan G Rennison 5 months ago
parent fa29a3d606
commit c76a5ed638

@ -28,7 +28,6 @@ void BaseConsist::CopyConsistPropertiesFrom(const BaseConsist *src)
this->current_order_time = src->current_order_time;
this->lateness_counter = src->lateness_counter;
this->timetable_start = src->timetable_start;
this->timetable_start_subticks = src->timetable_start_subticks;
this->service_interval = src->service_interval;

@ -22,8 +22,7 @@ struct BaseConsist {
/* Used for timetabling. */
uint32 current_order_time; ///< How many ticks have passed since this order started.
int32 lateness_counter; ///< How many ticks late (or early if negative) this vehicle is.
DateTicks timetable_start; ///< When the vehicle is supposed to start the timetable.
uint16 timetable_start_subticks; ///< When the vehicle is supposed to start the timetable: sub-ticks.
DateTicksScaled timetable_start; ///< When the vehicle is supposed to start the timetable.
uint16 service_interval; ///< The interval for (automatic) servicing; either in days or %.

@ -263,7 +263,7 @@ CommandProc CmdSetVehicleOnTime;
CommandProc CmdAutofillTimetable;
CommandProc CmdAutomateTimetable;
CommandProc CmdTimetableSeparation;
CommandProc CmdSetTimetableStart;
CommandProcEx CmdSetTimetableStart;
CommandProc CmdOpenCloseAirport;

@ -70,12 +70,6 @@ static inline DateTicksScaled DateTicksToScaledDateTicks(DateTicks date_ticks)
return ((int64)date_ticks * _settings_game.economy.day_length_factor) + _scaled_date_ticks_offset;
}
static inline std::pair<DateTicks, uint16> ScaledDateTicksToDateTicksAndSubTicks(DateTicksScaled ticks)
{
ticks -= _scaled_date_ticks_offset;
return std::make_pair<DateTicks, uint16>(ticks / _settings_game.economy.day_length_factor, ticks % _settings_game.economy.day_length_factor);
}
static inline std::pair<Date, uint16> ScaledDateTicksToDateAndFullSubTicks(DateTicksScaled ticks)
{
ticks -= _scaled_date_ticks_offset;

@ -3592,18 +3592,24 @@ bool AfterLoadGame()
}
}
if (SlXvIsFeatureMissing(XSLFI_TIMETABLES_START_TICKS)) {
// savegame timetable start is in days, but we want it in ticks, fix it up
if (!SlXvIsFeaturePresent(XSLFI_TIMETABLES_START_TICKS, 3)) {
extern btree::btree_map<VehicleID, uint16> _old_timetable_start_subticks_map;
for (Vehicle *v : Vehicle::Iterate()) {
if (v->timetable_start != 0) {
if (v->timetable_start == 0) continue;
if (SlXvIsFeatureMissing(XSLFI_TIMETABLES_START_TICKS)) {
v->timetable_start *= DAY_TICKS;
}
v->timetable_start = DateTicksToScaledDateTicks(v->timetable_start);
if (SlXvIsFeaturePresent(XSLFI_TIMETABLES_START_TICKS, 2, 2)) {
v->timetable_start += _old_timetable_start_subticks_map[v->index];
}
}
}
if (!SlXvIsFeaturePresent(XSLFI_TIMETABLES_START_TICKS, 2)) {
for (Vehicle *v : Vehicle::Iterate()) {
v->timetable_start_subticks = 0;
}
_old_timetable_start_subticks_map.clear();
}
if (SlXvIsFeaturePresent(XSLFI_SPRINGPP, 1, 1)) {

@ -204,7 +204,7 @@ SaveLoadTable GetOrderBackupDescription()
SLE_CONDVAR(OrderBackup, cur_implicit_order_index, SLE_FILE_U8 | SLE_VAR_U16, SLV_176, SL_MAX_VERSION),
SLE_CONDVAR(OrderBackup, current_order_time, SLE_UINT32, SLV_176, SL_MAX_VERSION),
SLE_CONDVAR(OrderBackup, lateness_counter, SLE_INT32, SLV_176, SL_MAX_VERSION),
SLE_CONDVAR(OrderBackup, timetable_start, SLE_INT32, SLV_176, SL_MAX_VERSION),
SLE_CONDVAR(OrderBackup, timetable_start, SLE_FILE_I32 | SLE_VAR_I64, SLV_176, SL_MAX_VERSION),
SLE_CONDVAR(OrderBackup, vehicle_flags, SLE_FILE_U8 | SLE_VAR_U32, SLV_176, SLV_180),
SLE_CONDVAR(OrderBackup, vehicle_flags, SLE_FILE_U16 | SLE_VAR_U32, SLV_180, SL_MAX_VERSION),
SLE_REF(OrderBackup, orders, REF_ORDER),

@ -130,7 +130,7 @@ public:
SLE_CONDVAR(Vehicle, current_order.wait_time, SLE_FILE_U16 | SLE_VAR_U32, SLV_67, SL_MAX_VERSION),
SLE_CONDVAR(Vehicle, current_order.travel_time, SLE_FILE_U16 | SLE_VAR_U32, SLV_67, SL_MAX_VERSION),
SLE_CONDVAR(Vehicle, current_order.max_speed, SLE_UINT16, SLV_174, SL_MAX_VERSION),
SLE_CONDVAR(Vehicle, timetable_start, SLE_INT32, SLV_129, SL_MAX_VERSION),
SLE_CONDVAR(Vehicle, timetable_start, SLE_FILE_I32 | SLE_VAR_I64, SLV_129, SL_MAX_VERSION),
SLE_CONDREF(Vehicle, orders, REF_ORDER, SL_MIN_VERSION, SLV_105),
SLE_CONDREF(Vehicle, orders, REF_ORDERLIST, SLV_105, SL_MAX_VERSION),

@ -93,7 +93,7 @@ const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = {
{ XSLFI_ADJACENT_CROSSINGS, XSCF_NULL, 1, 1, "adjacent_crossings", nullptr, nullptr, nullptr },
{ XSLFI_SAFER_CROSSINGS, XSCF_NULL, 1, 1, "safer_crossings", nullptr, nullptr, nullptr },
{ XSLFI_DEPARTURE_BOARDS, XSCF_IGNORABLE_UNKNOWN, 1, 1, "departure_boards", nullptr, nullptr, nullptr },
{ XSLFI_TIMETABLES_START_TICKS, XSCF_NULL, 2, 2, "timetable_start_ticks", nullptr, nullptr, nullptr },
{ XSLFI_TIMETABLES_START_TICKS, XSCF_NULL, 3, 3, "timetable_start_ticks", nullptr, nullptr, nullptr },
{ XSLFI_TOWN_CARGO_ADJ, XSCF_IGNORABLE_UNKNOWN, 2, 2, "town_cargo_adj", nullptr, nullptr, nullptr },
{ XSLFI_SIG_TUNNEL_BRIDGE, XSCF_NULL, 10, 10, "signal_tunnel_bridge", nullptr, nullptr, "XBSS" },
{ XSLFI_IMPROVED_BREAKDOWNS, XSCF_NULL, 8, 8, "improved_breakdowns", nullptr, nullptr, nullptr },

@ -42,7 +42,7 @@ enum SlXvFeatureIndex {
XSLFI_ADJACENT_CROSSINGS, ///< Adjacent level crossings closure patch
XSLFI_SAFER_CROSSINGS, ///< Safer level crossings
XSLFI_DEPARTURE_BOARDS, ///< Departure boards patch, in ticks mode
XSLFI_TIMETABLES_START_TICKS, ///< Timetable start time is in ticks, instead of days (from departure boards patch)
XSLFI_TIMETABLES_START_TICKS, ///< Timetable start time format: 1: is in ticks, instead of days, 2: also has subticks, 3: uses DateTicksScaled
XSLFI_TOWN_CARGO_ADJ, ///< Town cargo adjustment patch
XSLFI_SIG_TUNNEL_BRIDGE, ///< Signals on tunnels and bridges
XSLFI_IMPROVED_BREAKDOWNS, ///< Improved breakdowns patch

@ -350,8 +350,9 @@ SaveLoadTable GetOrderBackupDescription()
SLE_CONDVAR_X(OrderBackup, cur_timetable_order_index, SLE_VEHORDERID, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_TIMETABLE_EXTRA)),
SLE_CONDVAR(OrderBackup, current_order_time, SLE_UINT32, SLV_176, SL_MAX_VERSION),
SLE_CONDVAR(OrderBackup, lateness_counter, SLE_INT32, SLV_176, SL_MAX_VERSION),
SLE_CONDVAR(OrderBackup, timetable_start, SLE_INT32, SLV_176, SL_MAX_VERSION),
SLE_CONDVAR_X(OrderBackup,timetable_start_subticks, SLE_UINT16, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_TIMETABLES_START_TICKS, 2)),
SLE_CONDVAR_X(OrderBackup, timetable_start, SLE_FILE_I32 | SLE_VAR_I64, SLV_176, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_TIMETABLES_START_TICKS, 0, 2)),
SLE_CONDVAR_X(OrderBackup, timetable_start, SLE_INT64, SLV_176, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_TIMETABLES_START_TICKS, 3)),
SLE_CONDNULL_X(2, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_TIMETABLES_START_TICKS, 2, 2)),
SLE_CONDVAR(OrderBackup, vehicle_flags, SLE_FILE_U8 | SLE_VAR_U32, SLV_176, SLV_180),
SLE_CONDVAR_X(OrderBackup, vehicle_flags, SLE_FILE_U16 | SLE_VAR_U32, SLV_180, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_VEHICLE_FLAGS_EXTRA, 0, 0)),
SLE_CONDVAR_X(OrderBackup, vehicle_flags, SLE_UINT32, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_VEHICLE_FLAGS_EXTRA, 1)),

@ -648,6 +648,9 @@ static std::vector<TileIndex> _path_tile;
static uint32 _path_layout_ctr;
static uint32 _old_ahead_separation;
static uint16 _old_timetable_start_subticks;
btree::btree_map<VehicleID, uint16> _old_timetable_start_subticks_map;
/**
* Make it possible to make the saveload tables "friends" of other classes.
@ -746,9 +749,10 @@ SaveLoadTable GetVehicleDescription(VehicleType vt)
SLE_CONDVAR_X(Vehicle, current_order.wait_time, SLE_UINT32, SLV_67, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_TIMETABLE_EXTRA, 6)),
SLE_CONDVAR_X(Vehicle, current_order.travel_time, SLE_FILE_U16 | SLE_VAR_U32, SLV_67, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_TIMETABLE_EXTRA, 0, 5)),
SLE_CONDVAR_X(Vehicle, current_order.travel_time, SLE_UINT32, SLV_67, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_TIMETABLE_EXTRA, 6)),
SLE_CONDVAR(Vehicle, current_order.max_speed, SLE_UINT16, SLV_174, SL_MAX_VERSION),
SLE_CONDVAR(Vehicle, timetable_start, SLE_INT32, SLV_129, SL_MAX_VERSION),
SLE_CONDVAR_X(Vehicle, timetable_start_subticks, SLE_UINT16, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_TIMETABLES_START_TICKS, 2)),
SLE_CONDVAR(Vehicle, current_order.max_speed, SLE_UINT16, SLV_174, SL_MAX_VERSION),
SLE_CONDVAR_X(Vehicle, timetable_start, SLE_FILE_I32 | SLE_VAR_I64, SLV_129, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_TIMETABLES_START_TICKS, 0, 2)),
SLE_CONDVAR_X(Vehicle, timetable_start, SLE_INT64, SLV_129, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_TIMETABLES_START_TICKS, 3)),
SLEG_CONDVAR_X(_old_timetable_start_subticks, SLE_UINT16, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_TIMETABLES_START_TICKS, 2, 2)),
SLE_CONDREF(Vehicle, orders, REF_ORDER, SL_MIN_VERSION, SLV_105),
SLE_CONDREF(Vehicle, orders, REF_ORDERLIST, SLV_105, SL_MAX_VERSION),
@ -1076,6 +1080,9 @@ void Load_VEHS()
_path_tile.clear();
_path_layout_ctr = 0;
_old_timetable_start_subticks = 0;
_old_timetable_start_subticks_map.clear();
while ((index = SlIterateArray()) != -1) {
Vehicle *v;
VehicleType vtype = (VehicleType)SlReadByte();
@ -1125,6 +1132,10 @@ void Load_VEHS()
SB(v->vehicle_flags, VF_SEPARATION_ACTIVE, 1, _old_ahead_separation ? 1 : 0);
}
if (SlXvIsFeaturePresent(XSLFI_TIMETABLES_START_TICKS, 2, 2) && v->timetable_start != 0 && _old_timetable_start_subticks != 0) {
_old_timetable_start_subticks_map[v->index] = _old_timetable_start_subticks;
}
if (vtype == VEH_ROAD && !_path_td.empty() && _path_td.size() <= RV_PATH_CACHE_SEGMENTS && _path_td.size() == _path_tile.size()) {
RoadVehicle *rv = RoadVehicle::From(v);
rv->cached_path.reset(new RoadVehPathCache());

@ -473,25 +473,27 @@ static bool VehicleTimetableSorter(Vehicle * const &a, Vehicle * const &b)
* @param p1 Various bitstuffed elements
* - p1 = (bit 0-19) - Vehicle ID.
* - p1 = (bit 20) - Set to 1 to set timetable start for all vehicles sharing this order
* - p1 = (bit 21-31)- Timetable start date: sub-ticks
* @param p2 The timetable start date.
* @param p3 The timetable start ticks.
* @param text Not used.
* @return The error or cost of the operation.
*/
CommandCost CmdSetTimetableStart(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
CommandCost CmdSetTimetableStart(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, uint64 p3, const char *text, const CommandAuxiliaryBase *aux_data)
{
bool timetable_all = HasBit(p1, 20);
Vehicle *v = Vehicle::GetIfValid(GB(p1, 0, 20));
uint16 sub_ticks = GB(p1, 21, 11);
if (v == nullptr || !v->IsPrimaryVehicle() || v->orders == nullptr) return CMD_ERROR;
CommandCost ret = CheckOwnership(v->owner);
if (ret.Failed()) return ret;
if (timetable_all && !v->orders->IsCompleteTimetable()) return CommandCost(STR_ERROR_TIMETABLE_INCOMPLETE);
DateTicksScaled start_date_scaled = (DateTicksScaled)p3;
/* Don't let a timetable start more than 15 unscaled years into the future... */
if (start_date_scaled - _scaled_date_ticks > 15 * DAY_TICKS * DAYS_IN_LEAP_YEAR) return CMD_ERROR;
/* ...or 1 unscaled year in the past. */
if (_scaled_date_ticks - start_date_scaled > DAY_TICKS * DAYS_IN_LEAP_YEAR) return CMD_ERROR;
const DateTicksScaled now = _scaled_date_ticks;
DateTicksScaled start_date_scaled = DateTicksToScaledDateTicks(_date * DAY_TICKS + _date_fract + (int32)p2) + sub_ticks;
if (timetable_all && !v->orders->IsCompleteTimetable()) return CommandCost(STR_ERROR_TIMETABLE_INCOMPLETE);
if (flags & DC_EXEC) {
std::vector<Vehicle *> vehs;
@ -519,11 +521,7 @@ CommandCost CmdSetTimetableStart(TileIndex tile, DoCommandFlag flags, uint32 p1,
w->lateness_counter = 0;
ClrBit(w->vehicle_flags, VF_TIMETABLE_STARTED);
/* Do multiplication, then division to reduce rounding errors. */
DateTicksScaled tt_start = start_date_scaled + ((idx * total_duration) / num_vehs);
if (tt_start < now && idx < 0) {
tt_start += total_duration;
}
std::tie(w->timetable_start, w->timetable_start_subticks) = ScaledDateTicksToDateTicksAndSubTicks(tt_start);
w->timetable_start = start_date_scaled + ((idx * total_duration) / num_vehs);
++idx;
}
@ -568,7 +566,6 @@ CommandCost CmdAutofillTimetable(TileIndex tile, DoCommandFlag flags, uint32 p1,
if (HasBit(p2, 1)) SetBit(v->vehicle_flags, VF_AUTOFILL_PRES_WAIT_TIME);
v->timetable_start = 0;
v->timetable_start_subticks = 0;
v->lateness_counter = 0;
} else {
ClrBit(v->vehicle_flags, VF_AUTOFILL_TIMETABLE);
@ -618,7 +615,6 @@ CommandCost CmdAutomateTimetable(TileIndex index, DoCommandFlag flags, uint32 p1
ClrBit(v2->vehicle_flags, VF_AUTOFILL_PRES_WAIT_TIME);
ClrBit(v2->vehicle_flags, VF_TIMETABLE_STARTED);
v2->timetable_start = 0;
v2->timetable_start_subticks = 0;
v2->lateness_counter = 0;
v2->current_loading_time = 0;
v2->ClearSeparation();
@ -894,9 +890,8 @@ void UpdateVehicleTimetable(Vehicle *v, bool travelling)
if (!set_scheduled_dispatch) just_started = !HasBit(v->vehicle_flags, VF_TIMETABLE_STARTED);
if (v->timetable_start != 0) {
v->lateness_counter = _scaled_date_ticks - (DateTicksToScaledDateTicks(v->timetable_start) + v->timetable_start_subticks);
v->lateness_counter = (int32)(_scaled_date_ticks - v->timetable_start);
v->timetable_start = 0;
v->timetable_start_subticks = 0;
}
SetBit(v->vehicle_flags, VF_TIMETABLE_STARTED);

@ -239,10 +239,7 @@ static void FillTimetableArrivalDepartureTable(const Vehicle *v, VehicleOrderID
*/
static void ChangeTimetableStartIntl(uint32 p1, DateTicksScaled date)
{
DateTicks date_part;
uint16 sub_ticks;
std::tie(date_part, sub_ticks) = ScaledDateTicksToDateTicksAndSubTicks(date);
DoCommandP(0, p1 | (sub_ticks << 21), (Ticks)(date_part - (((DateTicks)_date * DAY_TICKS) + _date_fract)), CMD_SET_TIMETABLE_START | CMD_MSG(STR_ERROR_CAN_T_TIMETABLE_VEHICLE));
DoCommandPEx(0, p1, 0, (uint64)date, CMD_SET_TIMETABLE_START | CMD_MSG(STR_ERROR_CAN_T_TIMETABLE_VEHICLE), nullptr, nullptr, 0);
}
/**
@ -801,7 +798,7 @@ struct TimetableWindow : GeneralVehicleWindow {
/* We are running towards the first station so we can start the
* timetable at the given time. */
SetDParam(0, STR_JUST_DATE_WALLCLOCK_TINY);
SetDParam(1, DateTicksToScaledDateTicks(v->timetable_start) + v->timetable_start_subticks);
SetDParam(1, v->timetable_start);
DrawString(tr, STR_TIMETABLE_STATUS_START_AT);
} else if (!HasBit(v->vehicle_flags, VF_TIMETABLE_STARTED)) {
/* We aren't running on a timetable yet, so how can we be "on time"

@ -4652,7 +4652,7 @@ void DumpVehicleStats(char *buffer, const char *last)
void AdjustVehicleScaledTickBase(int64 delta)
{
for (Vehicle *v : Vehicle::Iterate()) {
v->last_loading_tick += delta;
if (v->timetable_start != 0) v->timetable_start += delta;
}
}
@ -4669,14 +4669,6 @@ extern void VehicleDayLengthChanged(DateTicksScaled old_scaled_date_ticks, DateT
{
if (_settings_game.economy.day_length_factor == old_day_length_factor || !_settings_game.game_time.time_in_minutes) return;
for (Vehicle *v : Vehicle::Iterate()) {
if (v->timetable_start != 0) {
DateTicksScaled tt_start = ((int64)v->timetable_start * old_day_length_factor) + v->timetable_start_subticks + old_scaled_date_ticks_offset;
tt_start += (_scaled_date_ticks - old_scaled_date_ticks);
std::tie(v->timetable_start, v->timetable_start_subticks) = ScaledDateTicksToDateTicksAndSubTicks(tt_start);
}
}
for (OrderList *orderlist : OrderList::Iterate()) {
for (DispatchSchedule &ds : orderlist->GetScheduledDispatchScheduleSet()) {
if (ds.GetScheduledDispatchStartDatePart() >= 0) {

Loading…
Cancel
Save