mirror of https://github.com/OpenTTD/OpenTTD
(svn r26547) -Codechange: Collect order travel and wait times independent of timetables
parent
c915d9fa55
commit
3ee31a8f89
|
@ -1675,7 +1675,7 @@ static void LoadUnloadVehicle(Vehicle *front)
|
||||||
/* We loaded less cargo than possible for all cargo types and it's not full
|
/* We loaded less cargo than possible for all cargo types and it's not full
|
||||||
* load and we're not supposed to wait any longer: stop loading. */
|
* load and we're not supposed to wait any longer: stop loading. */
|
||||||
if (!anything_unloaded && full_load_amount == 0 && reservation_left == 0 && !(front->current_order.GetLoadType() & OLFB_FULL_LOAD) &&
|
if (!anything_unloaded && full_load_amount == 0 && reservation_left == 0 && !(front->current_order.GetLoadType() & OLFB_FULL_LOAD) &&
|
||||||
front->current_order_time >= (uint)max(front->current_order.GetWaitTime() - front->lateness_counter, 0)) {
|
front->current_order_time >= (uint)max(front->current_order.GetTimetabledWait() - front->lateness_counter, 0)) {
|
||||||
SetBit(front->vehicle_flags, VF_STOP_LOADING);
|
SetBit(front->vehicle_flags, VF_STOP_LOADING);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -126,17 +126,17 @@ public:
|
||||||
void SetRefit(CargoID cargo);
|
void SetRefit(CargoID cargo);
|
||||||
|
|
||||||
/** How must the consist be loaded? */
|
/** How must the consist be loaded? */
|
||||||
inline OrderLoadFlags GetLoadType() const { return (OrderLoadFlags)GB(this->flags, 4, 4); }
|
inline OrderLoadFlags GetLoadType() const { return (OrderLoadFlags)GB(this->flags, 4, 3); }
|
||||||
/** How must the consist be unloaded? */
|
/** How must the consist be unloaded? */
|
||||||
inline OrderUnloadFlags GetUnloadType() const { return (OrderUnloadFlags)GB(this->flags, 0, 4); }
|
inline OrderUnloadFlags GetUnloadType() const { return (OrderUnloadFlags)GB(this->flags, 0, 3); }
|
||||||
/** At which stations must we stop? */
|
/** At which stations must we stop? */
|
||||||
inline OrderNonStopFlags GetNonStopType() const { return (OrderNonStopFlags)GB(this->type, 6, 2); }
|
inline OrderNonStopFlags GetNonStopType() const { return (OrderNonStopFlags)GB(this->type, 6, 2); }
|
||||||
/** Where must we stop at the platform? */
|
/** Where must we stop at the platform? */
|
||||||
inline OrderStopLocation GetStopLocation() const { return (OrderStopLocation)GB(this->type, 4, 2); }
|
inline OrderStopLocation GetStopLocation() const { return (OrderStopLocation)GB(this->type, 4, 2); }
|
||||||
/** What caused us going to the depot? */
|
/** What caused us going to the depot? */
|
||||||
inline OrderDepotTypeFlags GetDepotOrderType() const { return (OrderDepotTypeFlags)GB(this->flags, 0, 4); }
|
inline OrderDepotTypeFlags GetDepotOrderType() const { return (OrderDepotTypeFlags)GB(this->flags, 0, 3); }
|
||||||
/** What are we going to do when in the depot. */
|
/** What are we going to do when in the depot. */
|
||||||
inline OrderDepotActionFlags GetDepotActionType() const { return (OrderDepotActionFlags)GB(this->flags, 4, 4); }
|
inline OrderDepotActionFlags GetDepotActionType() const { return (OrderDepotActionFlags)GB(this->flags, 4, 3); }
|
||||||
/** What variable do we have to compare? */
|
/** What variable do we have to compare? */
|
||||||
inline OrderConditionVariable GetConditionVariable() const { return (OrderConditionVariable)GB(this->dest, 11, 5); }
|
inline OrderConditionVariable GetConditionVariable() const { return (OrderConditionVariable)GB(this->dest, 11, 5); }
|
||||||
/** What is the comparator to use? */
|
/** What is the comparator to use? */
|
||||||
|
@ -147,17 +147,17 @@ public:
|
||||||
inline uint16 GetConditionValue() const { return GB(this->dest, 0, 11); }
|
inline uint16 GetConditionValue() const { return GB(this->dest, 0, 11); }
|
||||||
|
|
||||||
/** Set how the consist must be loaded. */
|
/** Set how the consist must be loaded. */
|
||||||
inline void SetLoadType(OrderLoadFlags load_type) { SB(this->flags, 4, 4, load_type); }
|
inline void SetLoadType(OrderLoadFlags load_type) { SB(this->flags, 4, 3, load_type); }
|
||||||
/** Set how the consist must be unloaded. */
|
/** Set how the consist must be unloaded. */
|
||||||
inline void SetUnloadType(OrderUnloadFlags unload_type) { SB(this->flags, 0, 4, unload_type); }
|
inline void SetUnloadType(OrderUnloadFlags unload_type) { SB(this->flags, 0, 3, unload_type); }
|
||||||
/** Set whether we must stop at stations or not. */
|
/** Set whether we must stop at stations or not. */
|
||||||
inline void SetNonStopType(OrderNonStopFlags non_stop_type) { SB(this->type, 6, 2, non_stop_type); }
|
inline void SetNonStopType(OrderNonStopFlags non_stop_type) { SB(this->type, 6, 2, non_stop_type); }
|
||||||
/** Set where we must stop at the platform. */
|
/** Set where we must stop at the platform. */
|
||||||
inline void SetStopLocation(OrderStopLocation stop_location) { SB(this->type, 4, 2, stop_location); }
|
inline void SetStopLocation(OrderStopLocation stop_location) { SB(this->type, 4, 2, stop_location); }
|
||||||
/** Set the cause to go to the depot. */
|
/** Set the cause to go to the depot. */
|
||||||
inline void SetDepotOrderType(OrderDepotTypeFlags depot_order_type) { SB(this->flags, 0, 4, depot_order_type); }
|
inline void SetDepotOrderType(OrderDepotTypeFlags depot_order_type) { SB(this->flags, 0, 3, depot_order_type); }
|
||||||
/** Set what we are going to do in the depot. */
|
/** Set what we are going to do in the depot. */
|
||||||
inline void SetDepotActionType(OrderDepotActionFlags depot_service_type) { SB(this->flags, 4, 4, depot_service_type); }
|
inline void SetDepotActionType(OrderDepotActionFlags depot_service_type) { SB(this->flags, 4, 3, depot_service_type); }
|
||||||
/** Set variable we have to compare. */
|
/** Set variable we have to compare. */
|
||||||
inline void SetConditionVariable(OrderConditionVariable condition_variable) { SB(this->dest, 11, 5, condition_variable); }
|
inline void SetConditionVariable(OrderConditionVariable condition_variable) { SB(this->dest, 11, 5, condition_variable); }
|
||||||
/** Set the comparator to use. */
|
/** Set the comparator to use. */
|
||||||
|
@ -167,9 +167,23 @@ public:
|
||||||
/** Set the value to base the skip on. */
|
/** Set the value to base the skip on. */
|
||||||
inline void SetConditionValue(uint16 value) { SB(this->dest, 0, 11, value); }
|
inline void SetConditionValue(uint16 value) { SB(this->dest, 0, 11, value); }
|
||||||
|
|
||||||
/** Get the time in ticks a vehicle should wait at the destination. */
|
/* As conditional orders write their "skip to" order all over the flags, we cannot check the
|
||||||
|
* flags to find out if timetabling is enabled. However, as conditional orders are never
|
||||||
|
* autofilled we can be sure that any non-zero values for their wait_time and travel_time are
|
||||||
|
* 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); }
|
||||||
|
/** 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); }
|
||||||
|
|
||||||
|
/** Get the time in ticks a vehicle should wait at the destination or 0 if it's not timetabled. */
|
||||||
|
inline uint16 GetTimetabledWait() const { return this->IsWaitTimetabled() ? this->wait_time : 0; }
|
||||||
|
/** Get the time in ticks a vehicle should take to reach the destination or 0 if it's not timetabled. */
|
||||||
|
inline uint16 GetTimetabledTravel() const { return this->IsTravelTimetabled() ? this->travel_time : 0; }
|
||||||
|
/** Get the time in ticks a vehicle will probably wait at the destination (timetabled or not). */
|
||||||
inline uint16 GetWaitTime() const { return this->wait_time; }
|
inline uint16 GetWaitTime() const { return this->wait_time; }
|
||||||
/** Get the time in ticks a vehicle should take to reach the destination. */
|
/** Get the time in ticks a vehicle will probably take to reach the destination (timetabled or not). */
|
||||||
inline uint16 GetTravelTime() const { return this->travel_time; }
|
inline uint16 GetTravelTime() const { return this->travel_time; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -179,9 +193,21 @@ public:
|
||||||
*/
|
*/
|
||||||
inline uint16 GetMaxSpeed() const { return this->max_speed; }
|
inline uint16 GetMaxSpeed() const { return this->max_speed; }
|
||||||
|
|
||||||
/** Set the time in ticks a vehicle should wait at the destination. */
|
/** Set if the wait time is explicitly timetabled (unless the order is conditional). */
|
||||||
inline void SetWaitTime(uint16 time) { this->wait_time = time; }
|
inline void SetWaitTimetabled(bool timetabled) { if (!this->IsType(OT_CONDITIONAL)) SB(this->flags, 3, 1, timetabled ? 1 : 0); }
|
||||||
/** Set the time in ticks a vehicle should take to reach the destination. */
|
/** 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); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the time in ticks to wait at the destination.
|
||||||
|
* @param time Time to set as wait time.
|
||||||
|
*/
|
||||||
|
inline void SetWaitTime(uint16 time) { this->wait_time = time; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the time in ticks to take for travelling to the destination.
|
||||||
|
* @param time Time to set as travel time.
|
||||||
|
*/
|
||||||
inline void SetTravelTime(uint16 time) { this->travel_time = time; }
|
inline void SetTravelTime(uint16 time) { this->travel_time = time; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -197,11 +223,14 @@ public:
|
||||||
|
|
||||||
TileIndex GetLocation(const Vehicle *v, bool airport = false) const;
|
TileIndex GetLocation(const Vehicle *v, bool airport = false) const;
|
||||||
|
|
||||||
/** Checks if this order has travel_time and if needed wait_time set. */
|
/** Checks if travel_time and wait_time apply to this order and if they are timetabled. */
|
||||||
inline bool IsCompletelyTimetabled() const
|
inline bool IsCompletelyTimetabled() const
|
||||||
{
|
{
|
||||||
if (this->travel_time == 0 && !this->IsType(OT_CONDITIONAL)) return false;
|
if (!this->IsTravelTimetabled() && !this->IsType(OT_CONDITIONAL)) return false;
|
||||||
if (this->wait_time == 0 && this->IsType(OT_GOTO_STATION) && !(this->GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION)) return false;
|
if (!this->IsWaitTimetabled() && this->IsType(OT_GOTO_STATION) &&
|
||||||
|
!(this->GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -233,13 +262,14 @@ private:
|
||||||
uint num_vehicles; ///< NOSAVE: Number of vehicles that share this order list.
|
uint num_vehicles; ///< NOSAVE: Number of vehicles that share this order list.
|
||||||
Vehicle *first_shared; ///< NOSAVE: pointer to the first vehicle in the shared order chain.
|
Vehicle *first_shared; ///< NOSAVE: pointer to the first vehicle in the shared order chain.
|
||||||
|
|
||||||
Ticks timetable_duration; ///< NOSAVE: Total duration of the order list
|
Ticks timetable_duration; ///< NOSAVE: Total timetabled duration of the order list.
|
||||||
|
Ticks total_duration; ///< NOSAVE: Total (timetabled or not) duration of the order list.
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/** Default constructor producing an invalid order list. */
|
/** Default constructor producing an invalid order list. */
|
||||||
OrderList(VehicleOrderID num_orders = INVALID_VEH_ORDER_ID)
|
OrderList(VehicleOrderID num_orders = INVALID_VEH_ORDER_ID)
|
||||||
: first(NULL), num_orders(num_orders), num_manual_orders(0), num_vehicles(0), first_shared(NULL),
|
: first(NULL), num_orders(num_orders), num_manual_orders(0), num_vehicles(0), first_shared(NULL),
|
||||||
timetable_duration(0) { }
|
timetable_duration(0), total_duration(0) { }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an order list with the given order chain for the given vehicle.
|
* Create an order list with the given order chain for the given vehicle.
|
||||||
|
@ -339,11 +369,23 @@ public:
|
||||||
*/
|
*/
|
||||||
inline Ticks GetTimetableDurationIncomplete() const { return this->timetable_duration; }
|
inline Ticks GetTimetableDurationIncomplete() const { return this->timetable_duration; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the known duration of the vehicles orders, timetabled or not.
|
||||||
|
* @return known order duration.
|
||||||
|
*/
|
||||||
|
inline Ticks GetTotalDuration() const { return this->total_duration; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Must be called if an order's timetable is changed to update internal book keeping.
|
* Must be called if an order's timetable is changed to update internal book keeping.
|
||||||
* @param delta By how many ticks has the timetable duration changed
|
* @param delta By how many ticks has the timetable duration changed
|
||||||
*/
|
*/
|
||||||
void UpdateOrderTimetable(Ticks delta) { this->timetable_duration += delta; }
|
void UpdateTimetableDuration(Ticks delta) { this->timetable_duration += delta; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Must be called if an order's timetable is changed to update internal book keeping.
|
||||||
|
* @param delta By how many ticks has the total duration changed
|
||||||
|
*/
|
||||||
|
void UpdateTotalDuration(Ticks delta) { this->total_duration += delta; }
|
||||||
|
|
||||||
void FreeChain(bool keep_orderlist = false);
|
void FreeChain(bool keep_orderlist = false);
|
||||||
|
|
||||||
|
|
|
@ -297,11 +297,13 @@ void OrderList::Initialize(Order *chain, Vehicle *v)
|
||||||
this->num_manual_orders = 0;
|
this->num_manual_orders = 0;
|
||||||
this->num_vehicles = 1;
|
this->num_vehicles = 1;
|
||||||
this->timetable_duration = 0;
|
this->timetable_duration = 0;
|
||||||
|
this->total_duration = 0;
|
||||||
|
|
||||||
for (Order *o = this->first; o != NULL; o = o->next) {
|
for (Order *o = this->first; o != NULL; o = o->next) {
|
||||||
++this->num_orders;
|
++this->num_orders;
|
||||||
if (!o->IsType(OT_IMPLICIT)) ++this->num_manual_orders;
|
if (!o->IsType(OT_IMPLICIT)) ++this->num_manual_orders;
|
||||||
this->timetable_duration += o->GetWaitTime() + o->GetTravelTime();
|
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()) {
|
for (Vehicle *u = this->first_shared->PreviousShared(); u != NULL; u = u->PreviousShared()) {
|
||||||
|
@ -476,7 +478,8 @@ void OrderList::InsertOrderAt(Order *new_order, int index)
|
||||||
}
|
}
|
||||||
++this->num_orders;
|
++this->num_orders;
|
||||||
if (!new_order->IsType(OT_IMPLICIT)) ++this->num_manual_orders;
|
if (!new_order->IsType(OT_IMPLICIT)) ++this->num_manual_orders;
|
||||||
this->timetable_duration += new_order->GetWaitTime() + new_order->GetTravelTime();
|
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
|
/* 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. */
|
* the list of stations. So, we need to invalidate that window if needed. */
|
||||||
|
@ -508,7 +511,8 @@ void OrderList::DeleteOrderAt(int index)
|
||||||
}
|
}
|
||||||
--this->num_orders;
|
--this->num_orders;
|
||||||
if (!to_remove->IsType(OT_IMPLICIT)) --this->num_manual_orders;
|
if (!to_remove->IsType(OT_IMPLICIT)) --this->num_manual_orders;
|
||||||
this->timetable_duration -= (to_remove->GetWaitTime() + to_remove->GetTravelTime());
|
this->timetable_duration -= (to_remove->GetTimetabledWait() + to_remove->GetTimetabledTravel());
|
||||||
|
this->total_duration -= (to_remove->GetWaitTime() + to_remove->GetTravelTime());
|
||||||
delete to_remove;
|
delete to_remove;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -603,26 +607,29 @@ void OrderList::DebugCheckSanity() const
|
||||||
VehicleOrderID check_num_manual_orders = 0;
|
VehicleOrderID check_num_manual_orders = 0;
|
||||||
uint check_num_vehicles = 0;
|
uint check_num_vehicles = 0;
|
||||||
Ticks check_timetable_duration = 0;
|
Ticks check_timetable_duration = 0;
|
||||||
|
Ticks check_total_duration = 0;
|
||||||
|
|
||||||
DEBUG(misc, 6, "Checking OrderList %hu for sanity...", this->index);
|
DEBUG(misc, 6, "Checking OrderList %hu for sanity...", this->index);
|
||||||
|
|
||||||
for (const Order *o = this->first; o != NULL; o = o->next) {
|
for (const Order *o = this->first; o != NULL; o = o->next) {
|
||||||
++check_num_orders;
|
++check_num_orders;
|
||||||
if (!o->IsType(OT_IMPLICIT)) ++check_num_manual_orders;
|
if (!o->IsType(OT_IMPLICIT)) ++check_num_manual_orders;
|
||||||
check_timetable_duration += o->GetWaitTime() + o->GetTravelTime();
|
check_timetable_duration += o->GetTimetabledWait() + o->GetTimetabledTravel();
|
||||||
|
check_total_duration += o->GetWaitTime() + o->GetTravelTime();
|
||||||
}
|
}
|
||||||
assert(this->num_orders == check_num_orders);
|
assert(this->num_orders == check_num_orders);
|
||||||
assert(this->num_manual_orders == check_num_manual_orders);
|
assert(this->num_manual_orders == check_num_manual_orders);
|
||||||
assert(this->timetable_duration == check_timetable_duration);
|
assert(this->timetable_duration == check_timetable_duration);
|
||||||
|
assert(this->total_duration == check_total_duration);
|
||||||
|
|
||||||
for (const Vehicle *v = this->first_shared; v != NULL; v = v->NextShared()) {
|
for (const Vehicle *v = this->first_shared; v != NULL; v = v->NextShared()) {
|
||||||
++check_num_vehicles;
|
++check_num_vehicles;
|
||||||
assert(v->orders.list == this);
|
assert(v->orders.list == this);
|
||||||
}
|
}
|
||||||
assert(this->num_vehicles == check_num_vehicles);
|
assert(this->num_vehicles == check_num_vehicles);
|
||||||
DEBUG(misc, 6, "... detected %u orders (%u manual), %u vehicles, %i ticks",
|
DEBUG(misc, 6, "... detected %u orders (%u manual), %u vehicles, %i timetabled, %i total",
|
||||||
(uint)this->num_orders, (uint)this->num_manual_orders,
|
(uint)this->num_orders, (uint)this->num_manual_orders,
|
||||||
this->num_vehicles, this->timetable_duration);
|
this->num_vehicles, this->timetable_duration, this->total_duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2081,7 +2088,7 @@ bool UpdateOrderDest(Vehicle *v, const Order *order, int conditional_depth, bool
|
||||||
UpdateVehicleTimetable(v, false);
|
UpdateVehicleTimetable(v, false);
|
||||||
v->cur_implicit_order_index = v->cur_real_order_index = next_order;
|
v->cur_implicit_order_index = v->cur_real_order_index = next_order;
|
||||||
v->UpdateRealOrderIndex();
|
v->UpdateRealOrderIndex();
|
||||||
v->current_order_time += v->GetOrder(v->cur_real_order_index)->GetTravelTime();
|
v->current_order_time += v->GetOrder(v->cur_real_order_index)->GetTimetabledTravel();
|
||||||
|
|
||||||
/* Disable creation of implicit orders.
|
/* Disable creation of implicit orders.
|
||||||
* When inserting them we do not know that we would have to make the conditional orders point to them. */
|
* When inserting them we do not know that we would have to make the conditional orders point to them. */
|
||||||
|
|
|
@ -266,7 +266,7 @@ void DrawOrderString(const Vehicle *v, const Order *order, int order_index, int
|
||||||
if (timetable) {
|
if (timetable) {
|
||||||
SetDParam(3, STR_EMPTY);
|
SetDParam(3, STR_EMPTY);
|
||||||
|
|
||||||
if (order->GetWaitTime() > 0) {
|
if (order->IsWaitTimetabled()) {
|
||||||
SetDParam(5, STR_TIMETABLE_STAY_FOR);
|
SetDParam(5, STR_TIMETABLE_STAY_FOR);
|
||||||
SetTimetableParams(6, 7, order->GetWaitTime());
|
SetTimetableParams(6, 7, order->GetWaitTime());
|
||||||
}
|
}
|
||||||
|
@ -334,7 +334,7 @@ void DrawOrderString(const Vehicle *v, const Order *order, int order_index, int
|
||||||
SetDParam(4, value);
|
SetDParam(4, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (timetable && order->GetWaitTime() > 0) {
|
if (timetable && order->IsWaitTimetabled()) {
|
||||||
SetDParam(5, STR_TIMETABLE_AND_TRAVEL_FOR);
|
SetDParam(5, STR_TIMETABLE_AND_TRAVEL_FOR);
|
||||||
SetTimetableParams(6, 7, order->GetWaitTime());
|
SetTimetableParams(6, 7, order->GetWaitTime());
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -186,6 +186,10 @@ static void Load_ORDR()
|
||||||
while ((index = SlIterateArray()) != -1) {
|
while ((index = SlIterateArray()) != -1) {
|
||||||
Order *order = new (index) Order();
|
Order *order = new (index) Order();
|
||||||
SlObject(order, GetOrderDescription());
|
SlObject(order, GetOrderDescription());
|
||||||
|
if (IsSavegameVersionBefore(190)) {
|
||||||
|
order->SetTravelTimetabled(order->GetTravelTime() > 0);
|
||||||
|
order->SetWaitTimetabled(order->GetWaitTime() > 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -257,8 +257,9 @@
|
||||||
* 187 25899
|
* 187 25899
|
||||||
* 188 26169 1.4.x
|
* 188 26169 1.4.x
|
||||||
* 189 26450
|
* 189 26450
|
||||||
|
* 190 ?????
|
||||||
*/
|
*/
|
||||||
extern const uint16 SAVEGAME_VERSION = 189; ///< Current savegame version of OpenTTD.
|
extern const uint16 SAVEGAME_VERSION = 190; ///< Current savegame version of OpenTTD.
|
||||||
|
|
||||||
SavegameType _savegame_type; ///< type of savegame we are loading
|
SavegameType _savegame_type; ///< type of savegame we are loading
|
||||||
|
|
||||||
|
|
|
@ -28,21 +28,27 @@
|
||||||
* @param order_number The index of the timetable in the order list.
|
* @param order_number The index of the timetable in the order list.
|
||||||
* @param val The new data of the timetable entry.
|
* @param val The new data of the timetable entry.
|
||||||
* @param mtf Which part of the timetable entry to change.
|
* @param mtf Which part of the timetable entry to change.
|
||||||
|
* @param timetabled If the new value is explicitly timetabled.
|
||||||
*/
|
*/
|
||||||
static void ChangeTimetable(Vehicle *v, VehicleOrderID order_number, uint16 val, ModifyTimetableFlags mtf)
|
static void ChangeTimetable(Vehicle *v, VehicleOrderID order_number, uint16 val, ModifyTimetableFlags mtf, bool timetabled)
|
||||||
{
|
{
|
||||||
Order *order = v->GetOrder(order_number);
|
Order *order = v->GetOrder(order_number);
|
||||||
int delta = 0;
|
int total_delta = 0;
|
||||||
|
int timetable_delta = 0;
|
||||||
|
|
||||||
switch (mtf) {
|
switch (mtf) {
|
||||||
case MTF_WAIT_TIME:
|
case MTF_WAIT_TIME:
|
||||||
delta = val - order->GetWaitTime();
|
total_delta = val - order->GetWaitTime();
|
||||||
|
timetable_delta = (timetabled ? val : 0) - order->GetTimetabledWait();
|
||||||
order->SetWaitTime(val);
|
order->SetWaitTime(val);
|
||||||
|
order->SetWaitTimetabled(timetabled);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MTF_TRAVEL_TIME:
|
case MTF_TRAVEL_TIME:
|
||||||
delta = val - order->GetTravelTime();
|
total_delta = val - order->GetTravelTime();
|
||||||
|
timetable_delta = (timetabled ? val : 0) - order->GetTimetabledTravel();
|
||||||
order->SetTravelTime(val);
|
order->SetTravelTime(val);
|
||||||
|
order->SetTravelTimetabled(timetabled);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MTF_TRAVEL_SPEED:
|
case MTF_TRAVEL_SPEED:
|
||||||
|
@ -52,17 +58,20 @@ static void ChangeTimetable(Vehicle *v, VehicleOrderID order_number, uint16 val,
|
||||||
default:
|
default:
|
||||||
NOT_REACHED();
|
NOT_REACHED();
|
||||||
}
|
}
|
||||||
v->orders.list->UpdateOrderTimetable(delta);
|
v->orders.list->UpdateTotalDuration(total_delta);
|
||||||
|
v->orders.list->UpdateTimetableDuration(timetable_delta);
|
||||||
|
|
||||||
for (v = v->FirstShared(); v != NULL; v = v->NextShared()) {
|
for (v = v->FirstShared(); v != NULL; v = v->NextShared()) {
|
||||||
if (v->cur_real_order_index == order_number && v->current_order.Equals(*order)) {
|
if (v->cur_real_order_index == order_number && v->current_order.Equals(*order)) {
|
||||||
switch (mtf) {
|
switch (mtf) {
|
||||||
case MTF_WAIT_TIME:
|
case MTF_WAIT_TIME:
|
||||||
v->current_order.SetWaitTime(val);
|
v->current_order.SetWaitTime(val);
|
||||||
|
v->current_order.SetWaitTimetabled(timetabled);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MTF_TRAVEL_TIME:
|
case MTF_TRAVEL_TIME:
|
||||||
v->current_order.SetTravelTime(val);
|
v->current_order.SetTravelTime(val);
|
||||||
|
v->current_order.SetTravelTimetabled(timetabled);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MTF_TRAVEL_SPEED:
|
case MTF_TRAVEL_SPEED:
|
||||||
|
@ -107,8 +116,8 @@ CommandCost CmdChangeTimetable(TileIndex tile, DoCommandFlag flags, uint32 p1, u
|
||||||
ModifyTimetableFlags mtf = Extract<ModifyTimetableFlags, 28, 2>(p1);
|
ModifyTimetableFlags mtf = Extract<ModifyTimetableFlags, 28, 2>(p1);
|
||||||
if (mtf >= MTF_END) return CMD_ERROR;
|
if (mtf >= MTF_END) return CMD_ERROR;
|
||||||
|
|
||||||
int wait_time = order->GetWaitTime();
|
int wait_time = order->GetTimetabledWait();
|
||||||
int travel_time = order->GetTravelTime();
|
int travel_time = order->GetTimetabledTravel();
|
||||||
int max_speed = order->GetMaxSpeed();
|
int max_speed = order->GetMaxSpeed();
|
||||||
switch (mtf) {
|
switch (mtf) {
|
||||||
case MTF_WAIT_TIME:
|
case MTF_WAIT_TIME:
|
||||||
|
@ -128,7 +137,7 @@ CommandCost CmdChangeTimetable(TileIndex tile, DoCommandFlag flags, uint32 p1, u
|
||||||
NOT_REACHED();
|
NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wait_time != order->GetWaitTime()) {
|
if (wait_time != order->GetTimetabledWait()) {
|
||||||
switch (order->GetType()) {
|
switch (order->GetType()) {
|
||||||
case OT_GOTO_STATION:
|
case OT_GOTO_STATION:
|
||||||
if (order->GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION) return_cmd_error(STR_ERROR_TIMETABLE_NOT_STOPPING_HERE);
|
if (order->GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION) return_cmd_error(STR_ERROR_TIMETABLE_NOT_STOPPING_HERE);
|
||||||
|
@ -141,13 +150,13 @@ CommandCost CmdChangeTimetable(TileIndex tile, DoCommandFlag flags, uint32 p1, u
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (travel_time != order->GetTravelTime() && order->IsType(OT_CONDITIONAL)) return CMD_ERROR;
|
if (travel_time != order->GetTimetabledTravel() && order->IsType(OT_CONDITIONAL)) return CMD_ERROR;
|
||||||
if (max_speed != order->GetMaxSpeed() && (order->IsType(OT_CONDITIONAL) || v->type == VEH_AIRCRAFT)) return CMD_ERROR;
|
if (max_speed != order->GetMaxSpeed() && (order->IsType(OT_CONDITIONAL) || v->type == VEH_AIRCRAFT)) return CMD_ERROR;
|
||||||
|
|
||||||
if (flags & DC_EXEC) {
|
if (flags & DC_EXEC) {
|
||||||
if (wait_time != order->GetWaitTime()) ChangeTimetable(v, order_number, wait_time, MTF_WAIT_TIME);
|
if (wait_time != order->GetTimetabledWait()) ChangeTimetable(v, order_number, wait_time, MTF_WAIT_TIME, wait_time > 0);
|
||||||
if (travel_time != order->GetTravelTime()) ChangeTimetable(v, order_number, travel_time, MTF_TRAVEL_TIME);
|
if (travel_time != order->GetTimetabledTravel()) ChangeTimetable(v, order_number, travel_time, MTF_TRAVEL_TIME, travel_time > 0);
|
||||||
if (max_speed != order->GetMaxSpeed()) ChangeTimetable(v, order_number, max_speed, MTF_TRAVEL_SPEED);
|
if (max_speed != order->GetMaxSpeed()) ChangeTimetable(v, order_number, max_speed, MTF_TRAVEL_SPEED, max_speed != UINT16_MAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
return CommandCost();
|
return CommandCost();
|
||||||
|
@ -347,7 +356,6 @@ CommandCost CmdAutofillTimetable(TileIndex tile, DoCommandFlag flags, uint32 p1,
|
||||||
*/
|
*/
|
||||||
void UpdateVehicleTimetable(Vehicle *v, bool travelling)
|
void UpdateVehicleTimetable(Vehicle *v, bool travelling)
|
||||||
{
|
{
|
||||||
uint timetabled = travelling ? v->current_order.GetTravelTime() : v->current_order.GetWaitTime();
|
|
||||||
uint time_taken = v->current_order_time;
|
uint time_taken = v->current_order_time;
|
||||||
|
|
||||||
v->current_order_time = 0;
|
v->current_order_time = 0;
|
||||||
|
@ -380,43 +388,48 @@ void UpdateVehicleTimetable(Vehicle *v, bool travelling)
|
||||||
|
|
||||||
if (!HasBit(v->vehicle_flags, VF_TIMETABLE_STARTED)) return;
|
if (!HasBit(v->vehicle_flags, VF_TIMETABLE_STARTED)) return;
|
||||||
|
|
||||||
if (HasBit(v->vehicle_flags, VF_AUTOFILL_TIMETABLE)) {
|
bool autofilling = HasBit(v->vehicle_flags, VF_AUTOFILL_TIMETABLE);
|
||||||
if (travelling && !HasBit(v->vehicle_flags, VF_AUTOFILL_PRES_WAIT_TIME)) {
|
if (travelling && !HasBit(v->vehicle_flags, VF_AUTOFILL_PRES_WAIT_TIME)) {
|
||||||
/* Need to clear that now as otherwise we are not able to reduce the wait time */
|
/* Need to clear that now as otherwise we are not able to reduce the wait time */
|
||||||
v->current_order.SetWaitTime(0);
|
v->current_order.SetWaitTime(0);
|
||||||
}
|
|
||||||
|
|
||||||
if (just_started) return;
|
|
||||||
|
|
||||||
/* Modify station waiting time only if our new value is larger (this is
|
|
||||||
* always the case when we cleared the timetable). */
|
|
||||||
if (!v->current_order.IsType(OT_CONDITIONAL) && (travelling || time_taken > v->current_order.GetWaitTime())) {
|
|
||||||
/* Round the time taken up to the nearest day, as this will avoid
|
|
||||||
* confusion for people who are timetabling in days, and can be
|
|
||||||
* adjusted later by people who aren't.
|
|
||||||
* For trains/aircraft multiple movement cycles are done in one
|
|
||||||
* tick. This makes it possible to leave the station and process
|
|
||||||
* e.g. a depot order in the same tick, causing it to not fill
|
|
||||||
* the timetable entry like is done for road vehicles/ships.
|
|
||||||
* Thus always make sure at least one tick is used between the
|
|
||||||
* processing of different orders when filling the timetable. */
|
|
||||||
time_taken = CeilDiv(max(time_taken, 1U), DAY_TICKS) * DAY_TICKS;
|
|
||||||
|
|
||||||
ChangeTimetable(v, v->cur_real_order_index, time_taken, travelling ? MTF_TRAVEL_TIME : MTF_WAIT_TIME);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (v->cur_real_order_index == first_manual_order && travelling) {
|
|
||||||
/* If we just started we would have returned earlier and have not reached
|
|
||||||
* this code. So obviously, we have completed our round: So turn autofill
|
|
||||||
* off again. */
|
|
||||||
ClrBit(v->vehicle_flags, VF_AUTOFILL_TIMETABLE);
|
|
||||||
ClrBit(v->vehicle_flags, VF_AUTOFILL_PRES_WAIT_TIME);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (just_started) return;
|
if (just_started) return;
|
||||||
|
|
||||||
|
/* Modify station waiting time only if our new value is larger (this is
|
||||||
|
* always the case when we cleared the timetable). */
|
||||||
|
if (!v->current_order.IsType(OT_CONDITIONAL) && (travelling || time_taken > v->current_order.GetWaitTime())) {
|
||||||
|
/* Round the time taken up to the nearest day, as this will avoid
|
||||||
|
* confusion for people who are timetabling in days, and can be
|
||||||
|
* adjusted later by people who aren't.
|
||||||
|
* For trains/aircraft multiple movement cycles are done in one
|
||||||
|
* tick. This makes it possible to leave the station and process
|
||||||
|
* e.g. a depot order in the same tick, causing it to not fill
|
||||||
|
* the timetable entry like is done for road vehicles/ships.
|
||||||
|
* Thus always make sure at least one tick is used between the
|
||||||
|
* processing of different orders when filling the timetable. */
|
||||||
|
uint time_to_set = CeilDiv(max(time_taken, 1U), DAY_TICKS) * DAY_TICKS;
|
||||||
|
|
||||||
|
if (travelling && (autofilling || !v->current_order.IsTravelTimetabled())) {
|
||||||
|
ChangeTimetable(v, v->cur_real_order_index, time_to_set, MTF_TRAVEL_TIME, autofilling);
|
||||||
|
} else if (!travelling && (autofilling || !v->current_order.IsWaitTimetabled())) {
|
||||||
|
ChangeTimetable(v, v->cur_real_order_index, time_to_set, MTF_WAIT_TIME, autofilling);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (v->cur_real_order_index == first_manual_order && travelling) {
|
||||||
|
/* If we just started we would have returned earlier and have not reached
|
||||||
|
* this code. So obviously, we have completed our round: So turn autofill
|
||||||
|
* off again. */
|
||||||
|
ClrBit(v->vehicle_flags, VF_AUTOFILL_TIMETABLE);
|
||||||
|
ClrBit(v->vehicle_flags, VF_AUTOFILL_PRES_WAIT_TIME);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (autofilling) return;
|
||||||
|
|
||||||
|
uint timetabled = travelling ? v->current_order.GetTimetabledTravel() :
|
||||||
|
v->current_order.GetTimetabledWait();
|
||||||
|
|
||||||
/* Vehicles will wait at stations if they arrive early even if they are not
|
/* Vehicles will wait at stations if they arrive early even if they are not
|
||||||
* timetabled to wait there, so make sure the lateness counter is updated
|
* timetabled to wait there, so make sure the lateness counter is updated
|
||||||
* when this happens. */
|
* when this happens. */
|
||||||
|
|
|
@ -78,9 +78,9 @@ static bool CanDetermineTimeTaken(const Order *order, bool travelling)
|
||||||
/* Current order is conditional */
|
/* Current order is conditional */
|
||||||
if (order->IsType(OT_CONDITIONAL) || order->IsType(OT_IMPLICIT)) return false;
|
if (order->IsType(OT_CONDITIONAL) || order->IsType(OT_IMPLICIT)) return false;
|
||||||
/* No travel time and we have not already finished travelling */
|
/* No travel time and we have not already finished travelling */
|
||||||
if (travelling && order->GetTravelTime() == 0) return false;
|
if (travelling && !order->IsTravelTimetabled()) return false;
|
||||||
/* No wait time but we are loading at this timetabled station */
|
/* No wait time but we are loading at this timetabled station */
|
||||||
if (!travelling && order->GetWaitTime() == 0 && order->IsType(OT_GOTO_STATION) &&
|
if (!travelling && !order->IsWaitTimetabled() && order->IsType(OT_GOTO_STATION) &&
|
||||||
!(order->GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION)) {
|
!(order->GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -121,12 +121,12 @@ static void FillTimetableArrivalDepartureTable(const Vehicle *v, VehicleOrderID
|
||||||
if (!order->IsType(OT_IMPLICIT)) {
|
if (!order->IsType(OT_IMPLICIT)) {
|
||||||
if (travelling || i != start) {
|
if (travelling || i != start) {
|
||||||
if (!CanDetermineTimeTaken(order, true)) return;
|
if (!CanDetermineTimeTaken(order, true)) return;
|
||||||
sum += order->GetTravelTime();
|
sum += order->GetTimetabledTravel();
|
||||||
table[i].arrival = sum;
|
table[i].arrival = sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!CanDetermineTimeTaken(order, false)) return;
|
if (!CanDetermineTimeTaken(order, false)) return;
|
||||||
sum += order->GetWaitTime();
|
sum += order->GetTimetabledWait();
|
||||||
table[i].departure = sum;
|
table[i].departure = sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,7 +143,7 @@ static void FillTimetableArrivalDepartureTable(const Vehicle *v, VehicleOrderID
|
||||||
* travelling part of the first order. */
|
* travelling part of the first order. */
|
||||||
if (!travelling) {
|
if (!travelling) {
|
||||||
if (!CanDetermineTimeTaken(order, true)) return;
|
if (!CanDetermineTimeTaken(order, true)) return;
|
||||||
sum += order->GetTravelTime();
|
sum += order->GetTimetabledTravel();
|
||||||
table[i].arrival = sum;
|
table[i].arrival = sum;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -401,12 +401,12 @@ struct TimetableWindow : Window {
|
||||||
} else if (order->IsType(OT_IMPLICIT)) {
|
} else if (order->IsType(OT_IMPLICIT)) {
|
||||||
string = STR_TIMETABLE_NOT_TIMETABLEABLE;
|
string = STR_TIMETABLE_NOT_TIMETABLEABLE;
|
||||||
colour = ((i == selected) ? TC_SILVER : TC_GREY) | TC_NO_SHADE;
|
colour = ((i == selected) ? TC_SILVER : TC_GREY) | TC_NO_SHADE;
|
||||||
} else if (order->GetTravelTime() == 0) {
|
} else if (!order->IsTravelTimetabled()) {
|
||||||
string = order->GetMaxSpeed() != UINT16_MAX ?
|
string = order->GetMaxSpeed() != UINT16_MAX ?
|
||||||
STR_TIMETABLE_TRAVEL_NOT_TIMETABLED_SPEED :
|
STR_TIMETABLE_TRAVEL_NOT_TIMETABLED_SPEED :
|
||||||
STR_TIMETABLE_TRAVEL_NOT_TIMETABLED;
|
STR_TIMETABLE_TRAVEL_NOT_TIMETABLED;
|
||||||
} else {
|
} else {
|
||||||
SetTimetableParams(0, 1, order->GetTravelTime());
|
SetTimetableParams(0, 1, order->GetTimetabledTravel());
|
||||||
string = order->GetMaxSpeed() != UINT16_MAX ?
|
string = order->GetMaxSpeed() != UINT16_MAX ?
|
||||||
STR_TIMETABLE_TRAVEL_FOR_SPEED : STR_TIMETABLE_TRAVEL_FOR;
|
STR_TIMETABLE_TRAVEL_FOR_SPEED : STR_TIMETABLE_TRAVEL_FOR;
|
||||||
}
|
}
|
||||||
|
@ -546,7 +546,7 @@ struct TimetableWindow : Window {
|
||||||
StringID current = STR_EMPTY;
|
StringID current = STR_EMPTY;
|
||||||
|
|
||||||
if (order != NULL) {
|
if (order != NULL) {
|
||||||
uint time = (selected % 2 == 1) ? order->GetTravelTime() : order->GetWaitTime();
|
uint time = (selected % 2 == 1) ? order->GetTimetabledTravel() : order->GetTimetabledWait();
|
||||||
if (!_settings_client.gui.timetable_in_ticks) time /= DAY_TICKS;
|
if (!_settings_client.gui.timetable_in_ticks) time /= DAY_TICKS;
|
||||||
|
|
||||||
if (time != 0) {
|
if (time != 0) {
|
||||||
|
|
|
@ -2137,7 +2137,7 @@ void Vehicle::HandleLoading(bool mode)
|
||||||
{
|
{
|
||||||
switch (this->current_order.GetType()) {
|
switch (this->current_order.GetType()) {
|
||||||
case OT_LOADING: {
|
case OT_LOADING: {
|
||||||
uint wait_time = max(this->current_order.GetWaitTime() - this->lateness_counter, 0);
|
uint wait_time = max(this->current_order.GetTimetabledWait() - this->lateness_counter, 0);
|
||||||
|
|
||||||
/* Not the first call for this tick, or still loading */
|
/* Not the first call for this tick, or still loading */
|
||||||
if (mode || !HasBit(this->vehicle_flags, VF_LOADING_FINISHED) || this->current_order_time < wait_time) return;
|
if (mode || !HasBit(this->vehicle_flags, VF_LOADING_FINISHED) || this->current_order_time < wait_time) return;
|
||||||
|
|
Loading…
Reference in New Issue