mirror of
https://github.com/JGRennison/OpenTTD-patches.git
synced 2024-11-11 13:10:45 +00:00
Scheduled dispatch: Store vehicle last dispatch records
This commit is contained in:
parent
0d863bdf0d
commit
a2b6363584
@ -60,4 +60,6 @@ void BaseConsist::CopyConsistPropertiesFrom(const BaseConsist *src)
|
||||
} else {
|
||||
ClrBit(this->vehicle_flags, VF_SCHEDULED_DISPATCH);
|
||||
}
|
||||
|
||||
this->dispatch_records = src->dispatch_records;
|
||||
}
|
||||
|
@ -14,11 +14,26 @@
|
||||
#include "date_type.h"
|
||||
#include "timetable.h"
|
||||
#include "core/tinystring_type.hpp"
|
||||
#include "3rdparty/cpp-btree/btree_map.h"
|
||||
|
||||
struct LastDispatchRecord {
|
||||
enum RecordFlags {
|
||||
RF_FIRST_SLOT = 0, ///< Dispatch slot was first
|
||||
RF_LAST_SLOT, ///< Dispatch slot was last
|
||||
};
|
||||
|
||||
StateTicks dispatched;
|
||||
uint32_t offset;
|
||||
uint16_t slot_flags;
|
||||
uint8_t record_flags;
|
||||
};
|
||||
|
||||
/** Various front vehicle properties that are preserved when autoreplacing, using order-backup or switching front engines within a consist. */
|
||||
struct BaseConsist {
|
||||
TinyString name; ///< Name of vehicle
|
||||
|
||||
btree::btree_map<uint16_t, LastDispatchRecord> dispatch_records; ///< Records of last scheduled dispatches
|
||||
|
||||
/* Used for timetabling. */
|
||||
uint32_t current_order_time; ///< How many ticks have passed since this order started.
|
||||
int32_t lateness_counter; ///< How many ticks late (or early if negative) this vehicle is.
|
||||
|
@ -2237,8 +2237,22 @@ STR_SCHDISPATCH_SLOT_TOOLTIP_TAG :{}Tag {NUM}
|
||||
STR_SCHDISPATCH_SLOT_TOOLTIP_TAG_NAMED :{}Tag {NUM}: {RAW_STRING}
|
||||
|
||||
STR_SCHDISPATCH_SUMMARY_NO_LAST_DEPARTURE :{BLACK}No previous departures.
|
||||
STR_SCHDISPATCH_SUMMARY_VEHICLE_NO_LAST_DEPARTURE :{BLACK}This vehicle has not departed.
|
||||
STR_SCHDISPATCH_SUMMARY_DEPARTURE_DETAILS : ({RAW_STRING})
|
||||
STR_SCHDISPATCH_SUMMARY_DEPARTURE_DETAIL_SEPARATOR :, {STRING}
|
||||
STR_SCHDISPATCH_SUMMARY_DEPARTURE_DETAIL_WAS_FIRST :first slot
|
||||
STR_SCHDISPATCH_SUMMARY_DEPARTURE_DETAIL_WAS_LAST :last slot
|
||||
STR_SCHDISPATCH_SUMMARY_DEPARTURE_DETAIL_TAG :tag {NUM}
|
||||
STR_SCHDISPATCH_SUMMARY_DEPARTURE_DETAIL_TAG_NAMED :tag {NUM} ({RAW_STRING})
|
||||
|
||||
###length 2
|
||||
STR_SCHDISPATCH_SUMMARY_LAST_DEPARTURE_PAST :{BLACK}Last departure at {TT_TIME}.
|
||||
STR_SCHDISPATCH_SUMMARY_LAST_DEPARTURE_FUTURE :{BLACK}Last departure has not left yet, it will depart at {TT_TIME}.
|
||||
|
||||
###length 2
|
||||
STR_SCHDISPATCH_SUMMARY_VEHICLE_DEPARTURE_PAST :{BLACK}This vehicle departed at {TT_TIME}{STRING1}.
|
||||
STR_SCHDISPATCH_SUMMARY_VEHICLE_DEPARTURE_FUTURE :{BLACK}This vehicle has not left yet, it will depart at {TT_TIME}{STRING1}.
|
||||
|
||||
STR_SCHDISPATCH_SUMMARY_L1 :{BLACK}This schedule is estimated to require at least {COMMA} vehicle{P "" s}.
|
||||
STR_SCHDISPATCH_SUMMARY_L2 :{BLACK}This schedule repeats every {STRING1}.
|
||||
STR_SCHDISPATCH_SUMMARY_L3 :{BLACK}This schedule began at {TT_TIME}, and ends at {TT_TIME}.
|
||||
|
@ -2657,6 +2657,7 @@ CommandCost CmdCloneOrder(TileIndex tile, DoCommandFlag flags, uint32_t p1, uint
|
||||
* We reset the order indices, if the new orders are different.
|
||||
* (We mainly do this to keep the order indices valid and in range.) */
|
||||
DeleteVehicleOrders(dst, false, ShouldResetOrderIndicesOnOrderCopy(src, dst));
|
||||
dst->dispatch_records.clear();
|
||||
|
||||
dst->orders = src->orders;
|
||||
|
||||
@ -2745,6 +2746,7 @@ CommandCost CmdCloneOrder(TileIndex tile, DoCommandFlag flags, uint32_t p1, uint
|
||||
* We only the order indices, if the new orders are different.
|
||||
* (We mainly do this to keep the order indices valid and in range.) */
|
||||
DeleteVehicleOrders(dst, true, ShouldResetOrderIndicesOnOrderCopy(src, dst));
|
||||
dst->dispatch_records.clear();
|
||||
|
||||
order_dst = &first;
|
||||
for (const Order *order : src->Orders()) {
|
||||
@ -3219,7 +3221,7 @@ bool EvaluateDispatchSlotConditionalOrder(const Order *order, const Vehicle *v,
|
||||
}
|
||||
offset = last % sched.GetScheduledDispatchDuration();
|
||||
} else {
|
||||
StateTicks slot = GetScheduledDispatchTime(sched, state_ticks);
|
||||
StateTicks slot = GetScheduledDispatchTime(sched, state_ticks).first;
|
||||
if (slot == INVALID_STATE_TICKS) {
|
||||
/* No next dispatch */
|
||||
return OrderConditionCompare(order->GetConditionComparator(), 0, 0);
|
||||
|
@ -431,6 +431,19 @@ CommandCost CmdScheduledDispatchRemoveSchedule(TileIndex tile, DoCommandFlag fla
|
||||
}
|
||||
}
|
||||
}
|
||||
for (Vehicle *v2 = v->FirstShared(); v2 != nullptr; v2 = v2->NextShared()) {
|
||||
if (v2->dispatch_records.empty()) continue;
|
||||
|
||||
btree::btree_map<uint16_t, LastDispatchRecord> new_records;
|
||||
for (auto &iter : v2->dispatch_records) {
|
||||
if (iter.first < schedule_index) {
|
||||
new_records[iter.first] = std::move(iter.second);
|
||||
} else if (iter.first > schedule_index) {
|
||||
new_records[iter.first - 1] = std::move(iter.second);
|
||||
}
|
||||
}
|
||||
v2->dispatch_records = std::move(new_records);
|
||||
}
|
||||
SchdispatchInvalidateWindows(v);
|
||||
}
|
||||
|
||||
@ -682,6 +695,23 @@ CommandCost CmdScheduledDispatchSwapSchedules(TileIndex tile, DoCommandFlag flag
|
||||
}
|
||||
}
|
||||
}
|
||||
for (Vehicle *v2 = v->FirstShared(); v2 != nullptr; v2 = v2->NextShared()) {
|
||||
if (v2->dispatch_records.empty()) continue;
|
||||
|
||||
auto iter_1 = v2->dispatch_records.find(static_cast<uint16_t>(schedule_index_1));
|
||||
auto iter_2 = v2->dispatch_records.find(static_cast<uint16_t>(schedule_index_2));
|
||||
if (iter_1 != v2->dispatch_records.end() && iter_2 != v2->dispatch_records.end()) {
|
||||
std::swap(iter_1->second, iter_2->second);
|
||||
} else if (iter_1 != v2->dispatch_records.end()) {
|
||||
LastDispatchRecord r = std::move(iter_1->second);
|
||||
v2->dispatch_records.erase(iter_1);
|
||||
v2->dispatch_records[static_cast<uint16_t>(schedule_index_2)] = std::move(r);
|
||||
} else if (iter_2 != v2->dispatch_records.end()) {
|
||||
LastDispatchRecord r = std::move(iter_2->second);
|
||||
v2->dispatch_records.erase(iter_2);
|
||||
v2->dispatch_records[static_cast<uint16_t>(schedule_index_1)] = std::move(r);
|
||||
}
|
||||
}
|
||||
SchdispatchInvalidateWindows(v);
|
||||
SetTimetableWindowsDirty(v, STWDF_SCHEDULED_DISPATCH);
|
||||
}
|
||||
|
@ -526,7 +526,7 @@ struct SchdispatchWindow : GeneralVehicleWindow {
|
||||
}
|
||||
have_last = true;
|
||||
}
|
||||
StateTicks next_slot = GetScheduledDispatchTime(ds, _state_ticks);
|
||||
StateTicks next_slot = GetScheduledDispatchTime(ds, _state_ticks).first;
|
||||
if (next_slot != INVALID_STATE_TICKS && ((next_slot - ds.GetScheduledDispatchStartTick()).AsTicks() % ds.GetScheduledDispatchDuration() == slot->offset)) {
|
||||
if (!have_last) _temp_special_strings[0] += '\n';
|
||||
_temp_special_strings[0] += GetString(STR_SCHDISPATCH_SLOT_TOOLTIP_NEXT);
|
||||
@ -638,7 +638,7 @@ struct SchdispatchWindow : GeneralVehicleWindow {
|
||||
const StateTicks start_tick = ds.GetScheduledDispatchStartTick();
|
||||
const StateTicks end_tick = ds.GetScheduledDispatchStartTick() + ds.GetScheduledDispatchDuration();
|
||||
|
||||
StateTicks slot = GetScheduledDispatchTime(ds, _state_ticks);
|
||||
StateTicks slot = GetScheduledDispatchTime(ds, _state_ticks).first;
|
||||
int32_t next_offset = (slot != INVALID_STATE_TICKS) ? (slot - ds.GetScheduledDispatchStartTick()).AsTicks() % ds.GetScheduledDispatchDuration() : INT32_MIN;
|
||||
|
||||
int32_t last_dispatch;
|
||||
@ -806,8 +806,7 @@ struct SchdispatchWindow : GeneralVehicleWindow {
|
||||
|
||||
y += WidgetDimensions::scaled.vsep_wide;
|
||||
|
||||
if (ds.GetScheduledDispatchLastDispatch() != INVALID_SCHEDULED_DISPATCH_OFFSET) {
|
||||
const StateTicks last_departure = ds.GetScheduledDispatchStartTick() + ds.GetScheduledDispatchLastDispatch();
|
||||
auto show_last_departure = [&](const StateTicks last_departure, bool vehicle_mode, std::string details) {
|
||||
StringID str;
|
||||
if (_state_ticks < last_departure) {
|
||||
str = STR_SCHDISPATCH_SUMMARY_LAST_DEPARTURE_FUTURE;
|
||||
@ -815,7 +814,16 @@ struct SchdispatchWindow : GeneralVehicleWindow {
|
||||
} else {
|
||||
str = STR_SCHDISPATCH_SUMMARY_LAST_DEPARTURE_PAST;
|
||||
}
|
||||
if (vehicle_mode) str += (STR_SCHDISPATCH_SUMMARY_VEHICLE_DEPARTURE_PAST - STR_SCHDISPATCH_SUMMARY_LAST_DEPARTURE_PAST);
|
||||
|
||||
SetDParam(0, last_departure);
|
||||
if (details.empty()) {
|
||||
SetDParam(1, STR_EMPTY);
|
||||
} else {
|
||||
SetDParam(1, STR_SCHDISPATCH_SUMMARY_DEPARTURE_DETAILS);
|
||||
SetDParamStr(2, std::move(details));
|
||||
}
|
||||
|
||||
DrawString(ir.left, ir.right, y, str);
|
||||
y += GetCharacterHeight(FS_NORMAL);
|
||||
|
||||
@ -836,12 +844,42 @@ struct SchdispatchWindow : GeneralVehicleWindow {
|
||||
set_next_departure_update(_settings_time.FromTickMinutes(target + ((hours + 1) * 60) + 1));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
auto record_iter = v->dispatch_records.find(static_cast<uint16_t>(this->schedule_index));
|
||||
if (record_iter != v->dispatch_records.end()) {
|
||||
const LastDispatchRecord &record = record_iter->second;
|
||||
std::string details;
|
||||
auto add_detail = [&](StringID str) {
|
||||
auto tmp_params = MakeParameters(str);
|
||||
GetStringWithArgs(StringBuilder(details), details.empty() ? STR_JUST_STRING : STR_SCHDISPATCH_SUMMARY_DEPARTURE_DETAIL_SEPARATOR, tmp_params);
|
||||
};
|
||||
if (HasBit(record.record_flags, LastDispatchRecord::RF_FIRST_SLOT)) add_detail(STR_SCHDISPATCH_SUMMARY_DEPARTURE_DETAIL_WAS_FIRST);
|
||||
if (HasBit(record.record_flags, LastDispatchRecord::RF_LAST_SLOT)) add_detail(STR_SCHDISPATCH_SUMMARY_DEPARTURE_DETAIL_WAS_LAST);
|
||||
|
||||
for (uint8_t flag_bit = DispatchSlot::SDSF_FIRST_TAG; flag_bit <= DispatchSlot::SDSF_LAST_TAG; flag_bit++) {
|
||||
if (HasBit(record.slot_flags, flag_bit)) {
|
||||
std::string_view name = ds.GetSupplementaryName(SDSNT_DEPARTURE_TAG, flag_bit - DispatchSlot::SDSF_FIRST_TAG);
|
||||
auto tmp_params = MakeParameters(1 + flag_bit - DispatchSlot::SDSF_FIRST_TAG, std::string{name});
|
||||
_temp_special_strings[1] = GetStringWithArgs(name.empty() ? STR_SCHDISPATCH_SUMMARY_DEPARTURE_DETAIL_TAG : STR_SCHDISPATCH_SUMMARY_DEPARTURE_DETAIL_TAG_NAMED, tmp_params);
|
||||
add_detail(SPECSTR_TEMP_START + 1);
|
||||
}
|
||||
}
|
||||
|
||||
show_last_departure(record.dispatched, true, std::move(details));
|
||||
} else {
|
||||
DrawString(ir.left, ir.right, y, STR_SCHDISPATCH_SUMMARY_VEHICLE_NO_LAST_DEPARTURE);
|
||||
y += GetCharacterHeight(FS_NORMAL);
|
||||
}
|
||||
|
||||
if (ds.GetScheduledDispatchLastDispatch() != INVALID_SCHEDULED_DISPATCH_OFFSET) {
|
||||
show_last_departure(ds.GetScheduledDispatchStartTick() + ds.GetScheduledDispatchLastDispatch(), false, "");
|
||||
} else {
|
||||
DrawString(ir.left, ir.right, y, STR_SCHDISPATCH_SUMMARY_NO_LAST_DEPARTURE);
|
||||
y += GetCharacterHeight(FS_NORMAL);
|
||||
}
|
||||
|
||||
const StateTicks next_departure = GetScheduledDispatchTime(ds, _state_ticks);
|
||||
const StateTicks next_departure = GetScheduledDispatchTime(ds, _state_ticks).first;
|
||||
if (next_departure != INVALID_STATE_TICKS) {
|
||||
set_next_departure_update(next_departure + ds.GetScheduledDispatchDelay());
|
||||
SetDParam(0, next_departure);
|
||||
|
@ -54,5 +54,6 @@ add_files(
|
||||
train_speed_adaptation.cpp
|
||||
tunnel_sl.cpp
|
||||
vehicle_sl.cpp
|
||||
vehicle_sl.h
|
||||
waypoint_sl.cpp
|
||||
)
|
||||
|
@ -117,7 +117,7 @@ const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = {
|
||||
{ XSLFI_STATION_CATCHMENT_INC, XSCF_NULL, 1, 1, "station_catchment_inc", nullptr, nullptr, nullptr },
|
||||
{ XSLFI_CUSTOM_BRIDGE_HEADS, XSCF_NULL, 4, 4, "custom_bridge_heads", nullptr, nullptr, nullptr },
|
||||
{ XSLFI_CHUNNEL, XSCF_NULL, 3, 3, "chunnel", nullptr, nullptr, "TUNN" },
|
||||
{ XSLFI_SCHEDULED_DISPATCH, XSCF_NULL, 8, 8, "scheduled_dispatch", nullptr, nullptr, nullptr },
|
||||
{ XSLFI_SCHEDULED_DISPATCH, XSCF_NULL, 9, 9, "scheduled_dispatch", nullptr, nullptr, nullptr },
|
||||
{ XSLFI_MORE_TOWN_GROWTH_RATES, XSCF_NULL, 1, 1, "more_town_growth_rates", nullptr, nullptr, nullptr },
|
||||
{ XSLFI_MULTIPLE_DOCKS, XSCF_NULL, 2, 2, "multiple_docks", nullptr, nullptr, nullptr },
|
||||
{ XSLFI_TIMETABLE_EXTRA, XSCF_NULL, 8, 8, "timetable_extra", nullptr, nullptr, nullptr },
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "../network/network.h"
|
||||
|
||||
#include "saveload_internal.h"
|
||||
#include "vehicle_sl.h"
|
||||
|
||||
#include "../safeguards.h"
|
||||
|
||||
@ -449,6 +450,12 @@ struct OrderBackupDispatchScheduleStructHandler final : public DispatchScheduleS
|
||||
void Load(void *object) const override { this->LoadSchedules(static_cast<OrderBackup *>(object)->dispatch_schedules); }
|
||||
};
|
||||
|
||||
struct OrderBackupDispatchRecordsStructHandlerBase final : public DispatchRecordsStructHandlerBase {
|
||||
void Save(void *object) const override { this->SaveDispatchRecords(static_cast<OrderBackup *>(object)->dispatch_records); }
|
||||
|
||||
void Load(void *object) const override { this->LoadDispatchRecords(static_cast<OrderBackup *>(object)->dispatch_records); }
|
||||
};
|
||||
|
||||
NamedSaveLoadTable GetOrderListDescription()
|
||||
{
|
||||
static const NamedSaveLoad _orderlist_desc[] = {
|
||||
@ -488,6 +495,7 @@ NamedSaveLoadTable GetOrderBackupDescription()
|
||||
NSL("", SLE_CONDNULL_X(18, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_SCHEDULED_DISPATCH, 2, 2))),
|
||||
|
||||
NSLT_STRUCTLIST<OrderBackupDispatchScheduleStructHandler>("dispatch_schedule"),
|
||||
NSLT_STRUCTLIST<OrderBackupDispatchRecordsStructHandlerBase>("dispatch_records"),
|
||||
};
|
||||
|
||||
return _order_backup_desc;
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "../core/format.hpp"
|
||||
|
||||
#include "saveload.h"
|
||||
#include "vehicle_sl.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
@ -939,6 +940,43 @@ struct TrainLookaheadStateStructHandler final : public TypedSaveLoadStructHandle
|
||||
}
|
||||
};
|
||||
|
||||
NamedSaveLoadTable DispatchRecordsStructHandlerBase::GetDescription() const
|
||||
{
|
||||
static const NamedSaveLoad _record_desc[] = {
|
||||
NSL("id", SLE_VAR(RecordPair, first, SLE_UINT16)),
|
||||
NSL("dispatched", SLE_VAR(RecordPair, second.dispatched, SLE_INT64)),
|
||||
NSL("offset", SLE_VAR(RecordPair, second.offset, SLE_UINT32)),
|
||||
NSL("slot_flags", SLE_VAR(RecordPair, second.slot_flags, SLE_UINT16)),
|
||||
NSL("record_flags", SLE_VAR(RecordPair, second.record_flags, SLE_UINT8)),
|
||||
};
|
||||
|
||||
return _record_desc;
|
||||
}
|
||||
|
||||
void DispatchRecordsStructHandlerBase::SaveDispatchRecords(btree::btree_map<uint16_t, LastDispatchRecord> &records) const
|
||||
{
|
||||
SlSetStructListLength(records.size());
|
||||
for (RecordPair &it : records) {
|
||||
SlObjectSaveFiltered(&it, this->GetLoadDescription());
|
||||
}
|
||||
}
|
||||
|
||||
void DispatchRecordsStructHandlerBase::LoadDispatchRecords(btree::btree_map<uint16_t, LastDispatchRecord> &records) const
|
||||
{
|
||||
size_t count = SlGetStructListLength(UINT32_MAX);
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
RecordPair it{};
|
||||
SlObjectLoadFiltered(&it, this->GetLoadDescription());
|
||||
records.insert(it);
|
||||
}
|
||||
}
|
||||
|
||||
struct VehicleDispatchRecordsStructHandlerBase final : public DispatchRecordsStructHandlerBase {
|
||||
void Save(void *object) const override { this->SaveDispatchRecords(static_cast<Vehicle *>(object)->dispatch_records); }
|
||||
|
||||
void Load(void *object) const override { this->LoadDispatchRecords(static_cast<Vehicle *>(object)->dispatch_records); }
|
||||
};
|
||||
|
||||
/**
|
||||
* Make it possible to make the saveload tables "friends" of other classes.
|
||||
* @param vt the vehicle type. Can be VEH_END for the common vehicle description data
|
||||
@ -1119,6 +1157,7 @@ NamedSaveLoadTable GetVehicleDescription(VehicleType vt)
|
||||
NSL("", SLE_CONDNULL_X(160, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_JOKERPP))),
|
||||
|
||||
NSLT_STRUCT<VehicleUnbunchStateStructHandler>("depot_unbunch_state"),
|
||||
NSLT_STRUCTLIST<VehicleDispatchRecordsStructHandlerBase>("dispatch_records"),
|
||||
};
|
||||
|
||||
static const NamedSaveLoad _train_desc[] = {
|
||||
|
24
src/sl/vehicle_sl.h
Normal file
24
src/sl/vehicle_sl.h
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* This file is part of OpenTTD.
|
||||
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/** @file vehicle_sl.h Code handling saving and loading of vehicles. */
|
||||
|
||||
#ifndef SL_VEHICLE_SL_H
|
||||
#define SL_VEHICLE_SL_H
|
||||
|
||||
#include "../base_consist.h"
|
||||
#include "saveload.h"
|
||||
|
||||
struct DispatchRecordsStructHandlerBase : public SaveLoadStructHandler {
|
||||
using RecordPair = std::pair<const uint16_t, LastDispatchRecord>;
|
||||
|
||||
NamedSaveLoadTable GetDescription() const override;
|
||||
void SaveDispatchRecords(btree::btree_map<uint16_t, LastDispatchRecord> &records) const;
|
||||
void LoadDispatchRecords(btree::btree_map<uint16_t, LastDispatchRecord> &records) const;
|
||||
};
|
||||
|
||||
#endif /* SL_NEWGRF_SL_H */
|
@ -41,6 +41,6 @@ struct TimetableProgress {
|
||||
std::vector<TimetableProgress> PopulateSeparationState(const Vehicle *v_start);
|
||||
|
||||
struct DispatchSchedule;
|
||||
StateTicks GetScheduledDispatchTime(const DispatchSchedule &ds, StateTicks leave_time);
|
||||
std::pair<StateTicks, int> GetScheduledDispatchTime(const DispatchSchedule &ds, StateTicks leave_time);
|
||||
|
||||
#endif /* TIMETABLE_H */
|
||||
|
@ -808,9 +808,11 @@ void UpdateSeparationOrder(Vehicle *v_start)
|
||||
* Get next scheduled dispatch time
|
||||
* @param ds Dispatch schedule.
|
||||
* @param leave_time Leave time.
|
||||
* @return Dispatch time, or INVALID_STATE_TICKS
|
||||
* @return Pair of:
|
||||
* * Dispatch time, or INVALID_STATE_TICKS
|
||||
* * Index of departure slot, or -1
|
||||
*/
|
||||
StateTicks GetScheduledDispatchTime(const DispatchSchedule &ds, StateTicks leave_time)
|
||||
std::pair<StateTicks, int> GetScheduledDispatchTime(const DispatchSchedule &ds, StateTicks leave_time)
|
||||
{
|
||||
const uint32_t dispatch_duration = ds.GetScheduledDispatchDuration();
|
||||
const int32_t max_delay = ds.GetScheduledDispatchDelay();
|
||||
@ -828,9 +830,13 @@ StateTicks GetScheduledDispatchTime(const DispatchSchedule &ds, StateTicks leave
|
||||
}
|
||||
|
||||
StateTicks first_slot = INVALID_STATE_TICKS;
|
||||
int first_slot_index = -1;
|
||||
|
||||
/* Find next available slots */
|
||||
int slot_idx = 0;
|
||||
for (const DispatchSlot &slot : ds.GetScheduledDispatch()) {
|
||||
int this_slot = slot_idx++;
|
||||
|
||||
auto current_offset = slot.offset;
|
||||
if (current_offset >= dispatch_duration) continue;
|
||||
|
||||
@ -847,10 +853,25 @@ StateTicks GetScheduledDispatchTime(const DispatchSchedule &ds, StateTicks leave
|
||||
|
||||
if (first_slot == INVALID_STATE_TICKS || first_slot > current_departure) {
|
||||
first_slot = current_departure;
|
||||
first_slot_index = this_slot;
|
||||
}
|
||||
}
|
||||
|
||||
return first_slot;
|
||||
return std::make_pair(first_slot, first_slot_index);
|
||||
}
|
||||
|
||||
LastDispatchRecord MakeLastDispatchRecord(const DispatchSchedule &ds, StateTicks slot, int slot_index)
|
||||
{
|
||||
uint8_t record_flags = 0;
|
||||
if (slot_index == 0) SetBit(record_flags, LastDispatchRecord::RF_FIRST_SLOT);
|
||||
if (slot_index == (int)(ds.GetScheduledDispatch().size() - 1)) SetBit(record_flags, LastDispatchRecord::RF_LAST_SLOT);
|
||||
const DispatchSlot &dispatch_slot = ds.GetScheduledDispatch()[slot_index];
|
||||
return {
|
||||
slot,
|
||||
dispatch_slot.offset,
|
||||
dispatch_slot.flags,
|
||||
record_flags,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@ -896,7 +917,11 @@ void UpdateVehicleTimetable(Vehicle *v, bool travelling)
|
||||
ds.UpdateScheduledDispatch(v);
|
||||
|
||||
const int wait_offset = real_current_order->GetTimetabledWait();
|
||||
StateTicks slot = GetScheduledDispatchTime(ds, _state_ticks + wait_offset);
|
||||
|
||||
StateTicks slot;
|
||||
int slot_index;
|
||||
std::tie(slot, slot_index) = GetScheduledDispatchTime(ds, _state_ticks + wait_offset);
|
||||
|
||||
if (slot != INVALID_STATE_TICKS) {
|
||||
just_started = !HasBit(v->vehicle_flags, VF_TIMETABLE_STARTED);
|
||||
SetBit(v->vehicle_flags, VF_TIMETABLE_STARTED);
|
||||
@ -904,6 +929,7 @@ void UpdateVehicleTimetable(Vehicle *v, bool travelling)
|
||||
ds.SetScheduledDispatchLastDispatch((slot - ds.GetScheduledDispatchStartTick()).AsTicks());
|
||||
SetTimetableWindowsDirty(v, STWDF_SCHEDULED_DISPATCH);
|
||||
set_scheduled_dispatch = true;
|
||||
v->dispatch_records[static_cast<uint16_t>(real_implicit_order->GetDispatchScheduleIndex())] = MakeLastDispatchRecord(ds, slot, slot_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -194,7 +194,7 @@ static void FillTimetableArrivalDepartureTable(const Vehicle *v, VehicleOrderID
|
||||
DispatchSchedule predicted_ds;
|
||||
predicted_ds.BorrowSchedule(ds);
|
||||
predicted_ds.UpdateScheduledDispatchToDate(_state_ticks + sum);
|
||||
StateTicks slot = GetScheduledDispatchTime(predicted_ds, _state_ticks + sum + order->GetTimetabledWait());
|
||||
StateTicks slot = GetScheduledDispatchTime(predicted_ds, _state_ticks + sum + order->GetTimetabledWait()).first;
|
||||
predicted_ds.ReturnSchedule(ds);
|
||||
if (slot == INVALID_STATE_TICKS) return;
|
||||
sum = (slot - _state_ticks).AsTicks();
|
||||
|
@ -2255,6 +2255,7 @@ CommandCost CmdMoveRailVehicle(TileIndex tile, DoCommandFlag flags, uint32_t p1,
|
||||
/* Remove stuff not valid anymore for non-front engines. */
|
||||
DeleteVehicleOrders(src);
|
||||
src->ReleaseUnitNumber();
|
||||
src->dispatch_records.clear();
|
||||
if (!_settings_game.vehicle.non_leading_engines_keep_name) {
|
||||
src->name.clear();
|
||||
}
|
||||
|
@ -4995,6 +4995,9 @@ void AdjustVehicleStateTicksBase(StateTicksDelta delta)
|
||||
if (v->unbunch_state->depot_unbunching_last_departure != INVALID_STATE_TICKS) v->unbunch_state->depot_unbunching_last_departure += delta;
|
||||
if (v->unbunch_state->depot_unbunching_next_departure != INVALID_STATE_TICKS) v->unbunch_state->depot_unbunching_next_departure += delta;
|
||||
}
|
||||
for (auto &it : v->dispatch_records) {
|
||||
it.second.dispatched += delta;
|
||||
}
|
||||
}
|
||||
|
||||
for (OrderList *order_list : OrderList::Iterate()) {
|
||||
@ -5002,6 +5005,12 @@ void AdjustVehicleStateTicksBase(StateTicksDelta delta)
|
||||
ds.SetScheduledDispatchStartTick(ds.GetScheduledDispatchStartTick() + delta);
|
||||
}
|
||||
}
|
||||
|
||||
for (OrderBackup *ob : OrderBackup::Iterate()) {
|
||||
for (auto &it : ob->dispatch_records) {
|
||||
it.second.dispatched += delta;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ShiftVehicleDates(DateDelta interval)
|
||||
|
Loading…
Reference in New Issue
Block a user