Timetable: Implement autofill/automate for taken conditional orders.

Fix wrong timetable values being set after using skip or send to depot.
Add timetabled flag for conditional order branch taken travel time.
This commit is contained in:
Jonathan G Rennison
2017-12-18 01:26:27 +00:00
parent 102c55bc57
commit 218085c535
16 changed files with 187 additions and 34 deletions

View File

@@ -41,6 +41,7 @@ void BaseConsist::CopyConsistPropertiesFrom(const BaseConsist *src)
this->cur_real_order_index = src->cur_real_order_index;
this->cur_implicit_order_index = src->cur_implicit_order_index;
this->cur_timetable_order_index = src->cur_timetable_order_index;
if (HasBit(src->vehicle_flags, VF_TIMETABLE_STARTED)) SetBit(this->vehicle_flags, VF_TIMETABLE_STARTED);
if (HasBit(src->vehicle_flags, VF_AUTOFILL_TIMETABLE)) SetBit(this->vehicle_flags, VF_AUTOFILL_TIMETABLE);

View File

@@ -30,6 +30,7 @@ struct BaseConsist {
VehicleOrderID cur_real_order_index;///< The index to the current real (non-implicit) order
VehicleOrderID cur_implicit_order_index;///< The index to the current implicit order
VehicleOrderID cur_timetable_order_index;///< The index to the current real (non-implicit) order used for timetable updates
uint16 vehicle_flags; ///< Used for gradual loading and other miscellaneous things (@see VehicleFlags enum)

View File

@@ -272,6 +272,13 @@ DepartureList* MakeDepartureList(StationID station, bool show_vehicle_types[5],
const Order *order = (*v)->GetOrder((*v)->cur_implicit_order_index % (*v)->GetNumOrders());
DateTicks start_date = date_fract_scaled - (*v)->current_order_time;
if ((*v)->cur_timetable_order_index != INVALID_VEH_ORDER_ID && (*v)->cur_timetable_order_index != (*v)->cur_real_order_index) {
/* vehicle is taking a conditional order branch, adjust start time to compensate */
const Order *real_current_order = (*v)->GetOrder((*v)->cur_real_order_index);
const Order *real_timetable_order = (*v)->GetOrder((*v)->cur_timetable_order_index);
assert(real_timetable_order->IsType(OT_CONDITIONAL));
start_date += (real_timetable_order->GetWaitTime() - real_current_order->GetTravelTime());
}
DepartureStatus status = D_TRAVELLING;
bool should_reset_lateness = false;
uint waiting_time = 0;

View File

@@ -89,6 +89,7 @@ void OrderBackup::DoRestore(Vehicle *v)
/* Make sure orders are in range */
v->UpdateRealOrderIndex();
if (v->cur_implicit_order_index >= v->GetNumOrders()) v->cur_implicit_order_index = v->cur_real_order_index;
if (v->cur_timetable_order_index >= v->GetNumOrders()) v->cur_timetable_order_index = INVALID_VEH_ORDER_ID;
/* Restore vehicle group */
DoCommand(0, this->group, v->index, DC_EXEC, CMD_ADD_VEHICLE_GROUP);

View File

@@ -32,6 +32,7 @@ extern OrderListPool _orderlist_pool;
struct OrderExtraInfo {
uint8 cargo_type_flags[NUM_CARGO] = {}; ///< Load/unload types for each cargo type.
uint8 xflags = 0; ///< Extra flags
};
/* If you change this, keep in mind that it is saved on 3 places:
@@ -72,6 +73,17 @@ private:
if (!this->extra) this->AllocExtraInfo();
}
inline uint8 GetXFlags() const
{
return this->extra != nullptr ? this->extra->xflags : 0;
}
inline uint8 &GetXFlagsRef()
{
CheckExtraInfoAlloced();
return this->extra->xflags;
}
public:
Order *next; ///< Pointer to next order. If NULL, end of list
@@ -340,7 +352,7 @@ public:
* explicitly set (but travel_time is actually unused for conditionals). */
/** Does this order have an explicit wait time set? */
inline bool IsWaitTimetabled() const { return this->IsType(OT_CONDITIONAL) ? this->wait_time > 0 : HasBit(this->flags, 3); }
inline bool IsWaitTimetabled() const { return this->IsType(OT_CONDITIONAL) ? HasBit(this->GetXFlags(), 0) : HasBit(this->flags, 3); }
/** Does this order have an explicit travel time set? */
inline bool IsTravelTimetabled() const { return this->IsType(OT_CONDITIONAL) ? this->travel_time > 0 : HasBit(this->flags, 7); }
@@ -361,7 +373,15 @@ public:
inline uint16 GetMaxSpeed() const { return this->max_speed; }
/** Set if the wait time is explicitly timetabled (unless the order is conditional). */
inline void SetWaitTimetabled(bool timetabled) { if (!this->IsType(OT_CONDITIONAL)) SB(this->flags, 3, 1, timetabled ? 1 : 0); }
inline void SetWaitTimetabled(bool timetabled)
{
if (this->IsType(OT_CONDITIONAL)) {
SB(this->GetXFlagsRef(), 0, 1, timetabled ? 1 : 0);
} else {
SB(this->flags, 3, 1, timetabled ? 1 : 0);
}
}
/** Set if the travel time is explicitly timetabled (unless the order is conditional). */
inline void SetTravelTimetabled(bool timetabled) { if (!this->IsType(OT_CONDITIONAL)) SB(this->flags, 7, 1, timetabled ? 1 : 0); }
@@ -494,7 +514,7 @@ private:
Ticks timetable_duration; ///< NOSAVE: Total timetabled duration of the order list.
Ticks total_duration; ///< NOSAVE: Total (timetabled or not) duration of the order list.
std::vector<uint32> scheduled_dispatch; ///< Scheduled dispatch time
uint32 scheduled_dispatch_duration; ///< Scheduled dispatch duration
Date scheduled_dispatch_start_date; ///< Scheduled dispatch start date
@@ -531,6 +551,8 @@ public:
Order *GetOrderAt(int index) const;
VehicleOrderID GetIndexOfOrder(const Order *order) const;
/**
* Get the last order of the order chain.
* @return the last order of the chain.
@@ -636,7 +658,7 @@ public:
* @return first scheduled dispatch
*/
inline const std::vector<uint32> &GetScheduledDispatch() { return this->scheduled_dispatch; }
void AddScheduledDispatch(uint32 offset);
void RemoveScheduledDispatch(uint32 offset);
void UpdateScheduledDispatch();

View File

@@ -375,8 +375,10 @@ void OrderList::Initialize(Order *chain, Vehicle *v)
for (Order *o = this->first; o != NULL; o = o->next) {
++this->num_orders;
if (!o->IsType(OT_IMPLICIT)) ++this->num_manual_orders;
this->timetable_duration += o->GetTimetabledWait() + o->GetTimetabledTravel();
this->total_duration += o->GetWaitTime() + o->GetTravelTime();
if (!o->IsType(OT_CONDITIONAL)) {
this->timetable_duration += o->GetTimetabledWait() + o->GetTimetabledTravel();
this->total_duration += o->GetWaitTime() + o->GetTravelTime();
}
}
for (Vehicle *u = this->first_shared->PreviousShared(); u != NULL; u = u->PreviousShared()) {
@@ -427,6 +429,24 @@ Order *OrderList::GetOrderAt(int index) const
return order;
}
/**
* Get the index of an order of the order chain, or INVALID_VEH_ORDER_ID.
* @param order order to get the index of.
* @return the position index of the given order, or INVALID_VEH_ORDER_ID.
*/
VehicleOrderID OrderList::GetIndexOfOrder(const Order *order) const
{
VehicleOrderID index = 0;
const Order *o = this->first;
while (o != nullptr) {
if (o == order) return index;
index++;
o = o->next;
}
return INVALID_VEH_ORDER_ID;
}
/**
* Get the next order which will make the given vehicle stop at a station
* or refit at a depot or evaluate a non-trivial condition.
@@ -580,8 +600,10 @@ void OrderList::InsertOrderAt(Order *new_order, int index)
}
++this->num_orders;
if (!new_order->IsType(OT_IMPLICIT)) ++this->num_manual_orders;
this->timetable_duration += new_order->GetTimetabledWait() + new_order->GetTimetabledTravel();
this->total_duration += new_order->GetWaitTime() + new_order->GetTravelTime();
if (!new_order->IsType(OT_CONDITIONAL)) {
this->timetable_duration += new_order->GetTimetabledWait() + new_order->GetTimetabledTravel();
this->total_duration += new_order->GetWaitTime() + new_order->GetTravelTime();
}
/* We can visit oil rigs and buoys that are not our own. They will be shown in
* the list of stations. So, we need to invalidate that window if needed. */
@@ -613,8 +635,10 @@ void OrderList::DeleteOrderAt(int index)
}
--this->num_orders;
if (!to_remove->IsType(OT_IMPLICIT)) --this->num_manual_orders;
this->timetable_duration -= (to_remove->GetTimetabledWait() + to_remove->GetTimetabledTravel());
this->total_duration -= (to_remove->GetWaitTime() + to_remove->GetTravelTime());
if (!to_remove->IsType(OT_CONDITIONAL)) {
this->timetable_duration -= (to_remove->GetTimetabledWait() + to_remove->GetTimetabledTravel());
this->total_duration -= (to_remove->GetWaitTime() + to_remove->GetTravelTime());
}
delete to_remove;
}
@@ -716,8 +740,10 @@ void OrderList::DebugCheckSanity() const
for (const Order *o = this->first; o != NULL; o = o->next) {
++check_num_orders;
if (!o->IsType(OT_IMPLICIT)) ++check_num_manual_orders;
check_timetable_duration += o->GetTimetabledWait() + o->GetTimetabledTravel();
check_total_duration += o->GetWaitTime() + o->GetTravelTime();
if (!o->IsType(OT_CONDITIONAL)) {
check_timetable_duration += o->GetTimetabledWait() + o->GetTimetabledTravel();
check_total_duration += o->GetWaitTime() + o->GetTravelTime();
}
}
assert_msg(this->num_orders == check_num_orders, "%u, %u", this->num_orders, check_num_orders);
assert_msg(this->num_manual_orders == check_num_manual_orders, "%u, %u", this->num_manual_orders, check_num_manual_orders);
@@ -1103,6 +1129,13 @@ void InsertOrder(Vehicle *v, Order *new_o, VehicleOrderID sel_ord)
u->cur_implicit_order_index = cur;
}
}
if (sel_ord <= u->cur_timetable_order_index) {
uint cur = u->cur_timetable_order_index + 1;
/* Check if we don't go out of bound */
if (cur < u->GetNumOrders()) {
u->cur_timetable_order_index = cur;
}
}
/* Update any possible open window of the vehicle */
InvalidateVehicleOrder(u, INVALID_VEH_ORDER_ID | (sel_ord << 8));
}
@@ -1245,6 +1278,12 @@ void DeleteOrder(Vehicle *v, VehicleOrderID sel_ord)
}
}
if (sel_ord < u->cur_timetable_order_index) {
u->cur_timetable_order_index--;
} else if (sel_ord == u->cur_timetable_order_index) {
u->cur_timetable_order_index = INVALID_VEH_ORDER_ID;
}
/* Update any possible open window of the vehicle */
InvalidateVehicleOrder(u, sel_ord | (INVALID_VEH_ORDER_ID << 8));
}
@@ -1296,6 +1335,7 @@ CommandCost CmdSkipToOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
v->cur_implicit_order_index = v->cur_real_order_index = sel_ord;
v->UpdateRealOrderIndex();
v->cur_timetable_order_index = INVALID_VEH_ORDER_ID;
InvalidateVehicleOrder(v, VIWD_MODIFY_ORDERS);
@@ -1384,6 +1424,8 @@ CommandCost CmdMoveOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32
u->cur_implicit_order_index++;
}
u->cur_timetable_order_index = INVALID_VEH_ORDER_ID;
assert(v->orders.list == u->orders.list);
/* Update any possible open window of the vehicle */
InvalidateVehicleOrder(u, moving_order | (target_order << 8));
@@ -2169,6 +2211,7 @@ void DeleteVehicleOrders(Vehicle *v, bool keep_orderlist, bool reset_order_indic
if (reset_order_indices) {
v->cur_implicit_order_index = v->cur_real_order_index = 0;
v->cur_timetable_order_index = INVALID_VEH_ORDER_ID;
if (v->current_order.IsType(OT_LOADING)) {
CancelLoadingDueToDeletedOrder(v);
}
@@ -2408,7 +2451,7 @@ bool UpdateOrderDest(Vehicle *v, const Order *order, int conditional_depth, bool
UpdateVehicleTimetable(v, false);
v->cur_implicit_order_index = v->cur_real_order_index = next_order;
v->UpdateRealOrderIndex();
v->current_order_time += v->GetOrder(v->cur_real_order_index)->GetTimetabledTravel();
v->cur_timetable_order_index = v->GetIndexOfOrder(order);
/* Disable creation of implicit orders.
* When inserting them we do not know that we would have to make the conditional orders point to them. */
@@ -2417,6 +2460,7 @@ bool UpdateOrderDest(Vehicle *v, const Order *order, int conditional_depth, bool
SetBit(gv_flags, GVF_SUPPRESS_IMPLICIT_ORDERS);
}
} else {
v->cur_timetable_order_index = INVALID_VEH_ORDER_ID;
UpdateVehicleTimetable(v, true);
v->IncrementRealOrderIndex();
}

View File

@@ -42,9 +42,9 @@ restart:
}
/* Clear wait time */
v->orders.list->UpdateTotalDuration(-order->GetWaitTime());
if (!order->IsType(OT_CONDITIONAL)) v->orders.list->UpdateTotalDuration(-order->GetWaitTime());
if (order->IsWaitTimetabled()) {
v->orders.list->UpdateTimetableDuration(-order->GetTimetabledWait());
if (!order->IsType(OT_CONDITIONAL)) v->orders.list->UpdateTimetableDuration(-order->GetTimetabledWait());
order->SetWaitTimetabled(false);
}
order->SetWaitTime(0);

View File

@@ -3415,6 +3415,27 @@ bool AfterLoadGame()
}
}
if (SlXvIsFeatureMissing(XSLFI_TIMETABLE_EXTRA)) {
Vehicle *v;
FOR_ALL_VEHICLES(v) {
v->cur_timetable_order_index = v->GetNumManualOrders() > 0 ? v->cur_real_order_index : INVALID_VEH_ORDER_ID;
}
OrderBackup *bckup;
FOR_ALL_ORDER_BACKUPS(bckup) {
bckup->cur_timetable_order_index = INVALID_VEH_ORDER_ID;
}
Order *order;
FOR_ALL_ORDERS(order) {
if (order->IsType(OT_CONDITIONAL)) {
assert(order->GetTravelTime() == 0);
}
}
OrderList *order_list;
FOR_ALL_ORDER_LISTS(order_list) {
order_list->DebugCheckSanity();
}
}
/* Road stops is 'only' updating some caches */
AfterLoadRoadStops();
AfterLoadLabelMaps();

View File

@@ -79,6 +79,7 @@ const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = {
{ XSLFI_SCHEDULED_DISPATCH, XSCF_NULL, 1, 1, "scheduled_dispatch", NULL, NULL, NULL },
{ XSLFI_MORE_TOWN_GROWTH_RATES, XSCF_NULL, 1, 1, "more_town_growth_rates", NULL, NULL, NULL },
{ XSLFI_MULTIPLE_DOCKS, XSCF_NULL, 1, 1, "multiple_docks", NULL, NULL, "DOCK" },
{ XSLFI_TIMETABLE_EXTRA, XSCF_NULL, 1, 1, "timetable_extra", NULL, NULL, "ORDX" },
{ XSLFI_NULL, XSCF_NULL, 0, 0, NULL, NULL, NULL, NULL },// This is the end marker
};

View File

@@ -53,6 +53,7 @@ enum SlXvFeatureIndex {
XSLFI_SCHEDULED_DISPATCH, ///< Scheduled vehicle dispatching
XSLFI_MORE_TOWN_GROWTH_RATES, ///< More town growth rates
XSLFI_MULTIPLE_DOCKS, ///< Multiple docks
XSLFI_TIMETABLE_EXTRA, ///< Vehicle timetable extra fields
XSLFI_RIFF_HEADER_60_BIT, ///< Size field in RIFF chunk header is 60 bit
XSLFI_HEIGHT_8_BIT, ///< Map tile height is 8 bit instead of 4 bit, but savegame version may be before this became true in trunk

View File

@@ -192,6 +192,8 @@ static void Load_ORDR()
if (IsSavegameVersionBefore(190)) {
order->SetTravelTimetabled(order->GetTravelTime() > 0);
order->SetWaitTimetabled(order->GetWaitTime() > 0);
} else if (order->IsType(OT_CONDITIONAL) && SlXvIsFeatureMissing(XSLFI_TIMETABLE_EXTRA)) {
order->SetWaitTimetabled(order->GetWaitTime() > 0);
}
}
}
@@ -201,6 +203,7 @@ const SaveLoad *GetOrderExtraInfoDescription()
{
static const SaveLoad _order_extra_info_desc[] = {
SLE_ARR(OrderExtraInfo, cargo_type_flags, SLE_UINT8, NUM_CARGO),
SLE_CONDVAR_X(OrderExtraInfo, xflags, SLE_UINT8, 0, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_TIMETABLE_EXTRA)),
SLE_END()
};
@@ -302,6 +305,7 @@ const SaveLoad *GetOrderBackupDescription()
SLE_CONDREF(OrderBackup, clone, REF_VEHICLE, 192, SL_MAX_VERSION),
SLE_VAR(OrderBackup, cur_real_order_index, SLE_UINT8),
SLE_CONDVAR(OrderBackup, cur_implicit_order_index, SLE_UINT8, 176, SL_MAX_VERSION),
SLE_CONDVAR_X(OrderBackup, cur_timetable_order_index, SLE_UINT8, 0, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_TIMETABLE_EXTRA)),
SLE_CONDVAR(OrderBackup, current_order_time, SLE_UINT32, 176, SL_MAX_VERSION),
SLE_CONDVAR(OrderBackup, lateness_counter, SLE_INT32, 176, SL_MAX_VERSION),
SLE_CONDVAR(OrderBackup, timetable_start, SLE_INT32, 176, SL_MAX_VERSION),

View File

@@ -632,6 +632,7 @@ const SaveLoad *GetVehicleDescription(VehicleType vt)
SLE_VAR(Vehicle, cur_implicit_order_index, SLE_UINT8),
SLE_CONDVAR(Vehicle, cur_real_order_index, SLE_UINT8, 158, SL_MAX_VERSION),
SLE_CONDVAR_X(Vehicle, cur_timetable_order_index, SLE_UINT8, 0, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_TIMETABLE_EXTRA)),
/* num_orders is now part of OrderList and is not saved but counted */
SLE_CONDNULL(1, 0, 104),

View File

@@ -21,6 +21,7 @@
#include "company_base.h"
#include "core/sort_func.hpp"
#include "settings_type.h"
#include "scope.h"
#include "table/strings.h"
@@ -42,15 +43,20 @@ static void ChangeTimetable(Vehicle *v, VehicleOrderID order_number, uint16 val,
switch (mtf) {
case MTF_WAIT_TIME:
total_delta = val - order->GetWaitTime();
timetable_delta = (timetabled ? val : 0) - order->GetTimetabledWait();
if (!order->IsType(OT_CONDITIONAL)) {
total_delta = val - order->GetWaitTime();
timetable_delta = (timetabled ? val : 0) - order->GetTimetabledWait();
}
order->SetWaitTime(val);
order->SetWaitTimetabled(timetabled);
break;
case MTF_TRAVEL_TIME:
total_delta = val - order->GetTravelTime();
timetable_delta = (timetabled ? val : 0) - order->GetTimetabledTravel();
if (!order->IsType(OT_CONDITIONAL)) {
total_delta = val - order->GetTravelTime();
timetable_delta = (timetabled ? val : 0) - order->GetTimetabledTravel();
}
if (order->IsType(OT_CONDITIONAL)) assert_msg(val == order->GetTravelTime(), "%u == %u", val, order->GetTravelTime());
order->SetTravelTime(val);
order->SetTravelTimetabled(timetabled);
break;
@@ -714,6 +720,12 @@ void UpdateVehicleTimetable(Vehicle *v, bool travelling)
if (v->cur_real_order_index >= v->GetNumOrders()) return;
Order *real_current_order = v->GetOrder(v->cur_real_order_index);
Order *real_timetable_order = v->cur_timetable_order_index != INVALID_VEH_ORDER_ID ? v->GetOrder(v->cur_timetable_order_index) : nullptr;
auto guard = scope_guard([v, travelling]() {
/* On next call, when updating waiting time, use current order even if travel field of current order isn't being updated */
if (travelling) v->cur_timetable_order_index = v->cur_real_order_index;
});
VehicleOrderID first_manual_order = 0;
for (Order *o = v->GetFirstOrder(); o != NULL && o->IsType(OT_IMPLICIT); o = o->next) {
@@ -768,10 +780,12 @@ void UpdateVehicleTimetable(Vehicle *v, bool travelling)
}
if (!HasBit(v->vehicle_flags, VF_TIMETABLE_STARTED)) return;
if (real_timetable_order == nullptr) return;
bool autofilling = HasBit(v->vehicle_flags, VF_AUTOFILL_TIMETABLE);
bool remeasure_wait_time = !real_current_order->IsWaitTimetabled() ||
(autofilling && !HasBit(v->vehicle_flags, VF_AUTOFILL_PRES_WAIT_TIME));
bool is_conditional = real_timetable_order->IsType(OT_CONDITIONAL);
bool remeasure_wait_time = !is_conditional && (!real_timetable_order->IsWaitTimetabled() ||
(autofilling && !HasBit(v->vehicle_flags, VF_AUTOFILL_PRES_WAIT_TIME)));
if (travelling && remeasure_wait_time) {
/* We just finished travelling and want to remeasure the loading time,
@@ -779,11 +793,23 @@ void UpdateVehicleTimetable(Vehicle *v, bool travelling)
v->current_order.SetWaitTime(0);
}
bool travel_field = travelling;
if (is_conditional) {
if (travelling) {
/* conditional orders use the wait field for the jump-taken travel time */
travel_field = false;
} else {
/* doesn't make sense to update wait time for conditional orders */
return;
}
} else {
assert(real_timetable_order == real_current_order);
}
if (just_started) return;
/* Before modifying waiting times, check whether we want to preserve bigger ones. */
if (!real_current_order->IsType(OT_CONDITIONAL) &&
(travelling || time_taken > real_current_order->GetWaitTime() || remeasure_wait_time)) {
if ((travelling || time_taken > real_timetable_order->GetWaitTime() || remeasure_wait_time)) {
/* Round the time taken up to the nearest timetable rounding factor
* (default: day), as this will avoid confusion for people who are
* timetabling in days, and can be adjusted later by people who aren't.
@@ -797,10 +823,10 @@ void UpdateVehicleTimetable(Vehicle *v, bool travelling)
uint rounding_factor = owner ? owner->settings.timetable_autofill_rounding : DAY_TICKS;
uint time_to_set = CeilDiv(max(time_taken, 1U), rounding_factor) * rounding_factor;
if (travelling && (autofilling || !real_current_order->IsTravelTimetabled())) {
ChangeTimetable(v, v->cur_real_order_index, time_to_set, MTF_TRAVEL_TIME, autofilling);
} else if (!travelling && (autofilling || !real_current_order->IsWaitTimetabled())) {
ChangeTimetable(v, v->cur_real_order_index, time_to_set, MTF_WAIT_TIME, autofilling);
if (travel_field && (autofilling || !real_timetable_order->IsTravelTimetabled())) {
ChangeTimetable(v, v->cur_timetable_order_index, time_to_set, MTF_TRAVEL_TIME, autofilling);
} else if (!travel_field && (autofilling || !real_timetable_order->IsWaitTimetabled())) {
ChangeTimetable(v, v->cur_timetable_order_index, time_to_set, MTF_WAIT_TIME, autofilling);
}
}
@@ -814,8 +840,8 @@ void UpdateVehicleTimetable(Vehicle *v, bool travelling)
if (autofilling) return;
uint timetabled = travelling ? real_current_order->GetTimetabledTravel() :
real_current_order->GetTimetabledWait();
uint timetabled = travel_field ? real_timetable_order->GetTimetabledTravel() :
real_timetable_order->GetTimetabledWait();
/* Update the timetable to gradually shift order times towards the actual travel times. */
if (timetabled != 0 && HasBit(v->vehicle_flags, VF_AUTOMATE_TIMETABLE)) {
@@ -829,7 +855,7 @@ void UpdateVehicleTimetable(Vehicle *v, bool travelling)
if (new_time > (int32)timetabled * 4 && travelling) {
/* Possible jam, clear time and restart timetable for all vehicles.
* Otherwise we risk trains blocking 1-lane stations for long times. */
ChangeTimetable(v, v->cur_real_order_index, 0, travelling ? MTF_TRAVEL_TIME : MTF_WAIT_TIME, true);
ChangeTimetable(v, v->cur_timetable_order_index, 0, travel_field ? MTF_TRAVEL_TIME : MTF_WAIT_TIME, true);
for (Vehicle *v2 = v->FirstShared(); v2 != NULL; v2 = v2->NextShared()) {
v2->ClearSeparation();
ClrBit(v2->vehicle_flags, VF_TIMETABLE_STARTED);
@@ -849,14 +875,15 @@ void UpdateVehicleTimetable(Vehicle *v, bool travelling)
if (new_time < 1) new_time = 1;
if (new_time != (int32)timetabled) {
ChangeTimetable(v, v->cur_real_order_index, new_time, travelling ? MTF_TRAVEL_TIME : MTF_WAIT_TIME, true);
ChangeTimetable(v, v->cur_timetable_order_index, new_time, travel_field ? MTF_TRAVEL_TIME : MTF_WAIT_TIME, true);
}
} else if (timetabled == 0 && HasBit(v->vehicle_flags, VF_AUTOMATE_TIMETABLE)) {
/* Add times for orders that are not yet timetabled, even while not autofilling */
if (travelling) {
ChangeTimetable(v, v->cur_real_order_index, time_taken, MTF_TRAVEL_TIME, true);
const int32 new_time = travelling ? time_taken : time_loading;
if (travel_field) {
ChangeTimetable(v, v->cur_timetable_order_index, new_time, MTF_TRAVEL_TIME, true);
} else {
ChangeTimetable(v, v->cur_real_order_index, time_loading, MTF_WAIT_TIME, true);
ChangeTimetable(v, v->cur_timetable_order_index, new_time, MTF_WAIT_TIME, true);
}
}

View File

@@ -217,6 +217,13 @@ struct TimetableWindow : Window {
bool travelling = (!(v->current_order.IsType(OT_LOADING) || v->current_order.IsType(OT_WAITING)) || v->current_order.GetNonStopType() == ONSF_STOP_EVERYWHERE);
Ticks start_time = -v->current_order_time;
if (v->cur_timetable_order_index != INVALID_VEH_ORDER_ID && v->cur_timetable_order_index != v->cur_real_order_index) {
/* vehicle is taking a conditional order branch, adjust start time to compensate */
const Order *real_current_order = v->GetOrder(v->cur_real_order_index);
const Order *real_timetable_order = v->GetOrder(v->cur_timetable_order_index);
assert(real_timetable_order->IsType(OT_CONDITIONAL));
start_time += (real_timetable_order->GetWaitTime() - real_current_order->GetTravelTime());
}
FillTimetableArrivalDepartureTable(v, v->cur_real_order_index % v->GetNumOrders(), travelling, table, start_time);

View File

@@ -2892,6 +2892,9 @@ CommandCost Vehicle::SendToDepot(DoCommandFlag flags, DepotCommand command, Tile
this->current_order.MakeDummy();
SetWindowWidgetDirty(WC_VEHICLE_VIEW, this->index, WID_VV_START_STOP);
}
/* prevent any attempt to update timetable for current order, as actual travel time will be incorrect due to depot command */
this->cur_timetable_order_index = INVALID_VEH_ORDER_ID;
}
return CommandCost();
}

View File

@@ -855,8 +855,10 @@ private:
this->cur_real_order_index++;
if (this->cur_real_order_index >= this->GetNumOrders()) this->cur_real_order_index = 0;
} while (this->GetOrder(this->cur_real_order_index)->IsType(OT_IMPLICIT));
this->cur_timetable_order_index = this->cur_real_order_index;
} else {
this->cur_real_order_index = 0;
this->cur_timetable_order_index = INVALID_VEH_ORDER_ID;
}
}
@@ -931,6 +933,16 @@ public:
return (this->orders.list == NULL) ? NULL : this->orders.list->GetOrderAt(index);
}
/**
* Get the index of an order of the order chain, or INVALID_VEH_ORDER_ID.
* @param order order to get the index of.
* @return the position index of the given order, or INVALID_VEH_ORDER_ID.
*/
inline VehicleOrderID GetIndexOfOrder(const Order *order) const
{
return (this->orders.list == NULL) ? INVALID_VEH_ORDER_ID : this->orders.list->GetIndexOfOrder(order);
}
/**
* Returns the last order of a vehicle, or NULL if it doesn't exists
* @return last order of a vehicle, if available