|
|
|
@ -134,12 +134,12 @@ void Order::MakeConditional(VehicleOrderID order)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Makes this order an automatic order.
|
|
|
|
|
* Makes this order an implicit order.
|
|
|
|
|
* @param destination the station to go to.
|
|
|
|
|
*/
|
|
|
|
|
void Order::MakeAutomatic(StationID destination)
|
|
|
|
|
void Order::MakeImplicit(StationID destination)
|
|
|
|
|
{
|
|
|
|
|
this->type = OT_AUTOMATIC;
|
|
|
|
|
this->type = OT_IMPLICIT;
|
|
|
|
|
this->dest = destination;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -288,7 +288,7 @@ void OrderList::Initialize(Order *chain, Vehicle *v)
|
|
|
|
|
|
|
|
|
|
for (Order *o = this->first; o != NULL; o = o->next) {
|
|
|
|
|
++this->num_orders;
|
|
|
|
|
if (!o->IsType(OT_AUTOMATIC)) ++this->num_manual_orders;
|
|
|
|
|
if (!o->IsType(OT_IMPLICIT)) ++this->num_manual_orders;
|
|
|
|
|
this->timetable_duration += o->wait_time + o->travel_time;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -365,7 +365,7 @@ void OrderList::InsertOrderAt(Order *new_order, int index)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
++this->num_orders;
|
|
|
|
|
if (!new_order->IsType(OT_AUTOMATIC)) ++this->num_manual_orders;
|
|
|
|
|
if (!new_order->IsType(OT_IMPLICIT)) ++this->num_manual_orders;
|
|
|
|
|
this->timetable_duration += new_order->wait_time + new_order->travel_time;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -389,7 +389,7 @@ void OrderList::DeleteOrderAt(int index)
|
|
|
|
|
prev->next = to_remove->next;
|
|
|
|
|
}
|
|
|
|
|
--this->num_orders;
|
|
|
|
|
if (!to_remove->IsType(OT_AUTOMATIC)) --this->num_manual_orders;
|
|
|
|
|
if (!to_remove->IsType(OT_IMPLICIT)) --this->num_manual_orders;
|
|
|
|
|
this->timetable_duration -= (to_remove->wait_time + to_remove->travel_time);
|
|
|
|
|
delete to_remove;
|
|
|
|
|
}
|
|
|
|
@ -469,8 +469,8 @@ int OrderList::GetPositionInSharedOrderList(const Vehicle *v) const
|
|
|
|
|
bool OrderList::IsCompleteTimetable() const
|
|
|
|
|
{
|
|
|
|
|
for (Order *o = this->first; o != NULL; o = o->next) {
|
|
|
|
|
/* Automatic orders are, by definition, not timetabled. */
|
|
|
|
|
if (o->IsType(OT_AUTOMATIC)) continue;
|
|
|
|
|
/* Implicit orders are, by definition, not timetabled. */
|
|
|
|
|
if (o->IsType(OT_IMPLICIT)) continue;
|
|
|
|
|
if (!o->IsCompletelyTimetabled()) return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
@ -490,7 +490,7 @@ void OrderList::DebugCheckSanity() const
|
|
|
|
|
|
|
|
|
|
for (const Order *o = this->first; o != NULL; o = o->next) {
|
|
|
|
|
++check_num_orders;
|
|
|
|
|
if (!o->IsType(OT_AUTOMATIC)) ++check_num_manual_orders;
|
|
|
|
|
if (!o->IsType(OT_IMPLICIT)) ++check_num_manual_orders;
|
|
|
|
|
check_timetable_duration += o->wait_time + o->travel_time;
|
|
|
|
|
}
|
|
|
|
|
assert(this->num_orders == check_num_orders);
|
|
|
|
@ -544,7 +544,7 @@ TileIndex Order::GetLocation(const Vehicle *v) const
|
|
|
|
|
switch (this->GetType()) {
|
|
|
|
|
case OT_GOTO_WAYPOINT:
|
|
|
|
|
case OT_GOTO_STATION:
|
|
|
|
|
case OT_AUTOMATIC:
|
|
|
|
|
case OT_IMPLICIT:
|
|
|
|
|
return BaseStation::Get(this->GetDestination())->xy;
|
|
|
|
|
|
|
|
|
|
case OT_GOTO_DEPOT:
|
|
|
|
@ -820,8 +820,8 @@ void InsertOrder(Vehicle *v, Order *new_o, VehicleOrderID sel_ord)
|
|
|
|
|
assert(v->orders.list == u->orders.list);
|
|
|
|
|
|
|
|
|
|
/* If there is added an order before the current one, we need
|
|
|
|
|
* to update the selected order. We do not change automatic/real order indices though.
|
|
|
|
|
* If the new order is between the current auto order and real order, the auto order will
|
|
|
|
|
* to update the selected order. We do not change implicit/real order indices though.
|
|
|
|
|
* If the new order is between the current implicit order and real order, the implicit order will
|
|
|
|
|
* later skip the inserted order. */
|
|
|
|
|
if (sel_ord <= u->cur_real_order_index) {
|
|
|
|
|
uint cur = u->cur_real_order_index + 1;
|
|
|
|
@ -830,18 +830,18 @@ void InsertOrder(Vehicle *v, Order *new_o, VehicleOrderID sel_ord)
|
|
|
|
|
u->cur_real_order_index = cur;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (sel_ord == u->cur_auto_order_index && u->IsGroundVehicle()) {
|
|
|
|
|
/* We are inserting an order just before the current automatic order.
|
|
|
|
|
* We do not know whether we will reach current automatic or the newly inserted order first.
|
|
|
|
|
* So, disable creation of automatic orders until we are on track again. */
|
|
|
|
|
if (sel_ord == u->cur_implicit_order_index && u->IsGroundVehicle()) {
|
|
|
|
|
/* We are inserting an order just before the current implicit order.
|
|
|
|
|
* We do not know whether we will reach current implicit or the newly inserted order first.
|
|
|
|
|
* So, disable creation of implicit orders until we are on track again. */
|
|
|
|
|
uint16 &gv_flags = u->GetGroundVehicleFlags();
|
|
|
|
|
SetBit(gv_flags, GVF_SUPPRESS_AUTOMATIC_ORDERS);
|
|
|
|
|
SetBit(gv_flags, GVF_SUPPRESS_IMPLICIT_ORDERS);
|
|
|
|
|
}
|
|
|
|
|
if (sel_ord <= u->cur_auto_order_index) {
|
|
|
|
|
uint cur = u->cur_auto_order_index + 1;
|
|
|
|
|
if (sel_ord <= u->cur_implicit_order_index) {
|
|
|
|
|
uint cur = u->cur_implicit_order_index + 1;
|
|
|
|
|
/* Check if we don't go out of bound */
|
|
|
|
|
if (cur < u->GetNumOrders()) {
|
|
|
|
|
u->cur_auto_order_index = cur;
|
|
|
|
|
u->cur_implicit_order_index = cur;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/* Update any possible open window of the vehicle */
|
|
|
|
@ -952,16 +952,16 @@ void DeleteOrder(Vehicle *v, VehicleOrderID sel_ord)
|
|
|
|
|
u->UpdateRealOrderIndex();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (sel_ord < u->cur_auto_order_index) {
|
|
|
|
|
u->cur_auto_order_index--;
|
|
|
|
|
} else if (sel_ord == u->cur_auto_order_index) {
|
|
|
|
|
if (sel_ord < u->cur_implicit_order_index) {
|
|
|
|
|
u->cur_implicit_order_index--;
|
|
|
|
|
} else if (sel_ord == u->cur_implicit_order_index) {
|
|
|
|
|
/* Make sure the index is valid */
|
|
|
|
|
if (u->cur_auto_order_index >= u->GetNumOrders()) u->cur_auto_order_index = 0;
|
|
|
|
|
if (u->cur_implicit_order_index >= u->GetNumOrders()) u->cur_implicit_order_index = 0;
|
|
|
|
|
|
|
|
|
|
/* Skip non-automatic orders for the auto-order-index (e.g. if the current auto order was deleted */
|
|
|
|
|
while (u->cur_auto_order_index != u->cur_real_order_index && !u->GetOrder(u->cur_auto_order_index)->IsType(OT_AUTOMATIC)) {
|
|
|
|
|
u->cur_auto_order_index++;
|
|
|
|
|
if (u->cur_auto_order_index >= u->GetNumOrders()) u->cur_auto_order_index = 0;
|
|
|
|
|
/* Skip non-implicit orders for the implicit-order-index (e.g. if the current implicit order was deleted */
|
|
|
|
|
while (u->cur_implicit_order_index != u->cur_real_order_index && !u->GetOrder(u->cur_implicit_order_index)->IsType(OT_IMPLICIT)) {
|
|
|
|
|
u->cur_implicit_order_index++;
|
|
|
|
|
if (u->cur_implicit_order_index >= u->GetNumOrders()) u->cur_implicit_order_index = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1005,13 +1005,13 @@ CommandCost CmdSkipToOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
|
|
|
|
|
|
|
|
|
|
Vehicle *v = Vehicle::GetIfValid(veh_id);
|
|
|
|
|
|
|
|
|
|
if (v == NULL || !v->IsPrimaryVehicle() || sel_ord == v->cur_auto_order_index || sel_ord >= v->GetNumOrders() || v->GetNumOrders() < 2) return CMD_ERROR;
|
|
|
|
|
if (v == NULL || !v->IsPrimaryVehicle() || sel_ord == v->cur_implicit_order_index || sel_ord >= v->GetNumOrders() || v->GetNumOrders() < 2) return CMD_ERROR;
|
|
|
|
|
|
|
|
|
|
CommandCost ret = CheckOwnership(v->owner);
|
|
|
|
|
if (ret.Failed()) return ret;
|
|
|
|
|
|
|
|
|
|
if (flags & DC_EXEC) {
|
|
|
|
|
v->cur_auto_order_index = v->cur_real_order_index = sel_ord;
|
|
|
|
|
v->cur_implicit_order_index = v->cur_real_order_index = sel_ord;
|
|
|
|
|
v->UpdateRealOrderIndex();
|
|
|
|
|
|
|
|
|
|
if (v->current_order.IsType(OT_LOADING)) v->LeaveStation();
|
|
|
|
@ -1069,7 +1069,7 @@ CommandCost CmdMoveOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32
|
|
|
|
|
|
|
|
|
|
for (; u != NULL; u = u->NextShared()) {
|
|
|
|
|
/* Update the current order.
|
|
|
|
|
* There are multiple ways to move orders, which result in cur_auto_order_index
|
|
|
|
|
* There are multiple ways to move orders, which result in cur_implicit_order_index
|
|
|
|
|
* and cur_real_order_index to not longer make any sense. E.g. moving another
|
|
|
|
|
* real order between them.
|
|
|
|
|
*
|
|
|
|
@ -1079,10 +1079,10 @@ CommandCost CmdMoveOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32
|
|
|
|
|
* However, from an AI point of view, preserving cur_real_order_index is the most
|
|
|
|
|
* predictable and transparent behaviour.
|
|
|
|
|
*
|
|
|
|
|
* With that decision it basically does not matter what we do to cur_auto_order_index.
|
|
|
|
|
* If we change orders between the auto- and real-index, the auto orders are mostly likely
|
|
|
|
|
* completely out-dated anyway. So, keep it simple and just keep cur_auto_order_index as well.
|
|
|
|
|
* The worst which can happen is that a lot of automatic orders are removed when reaching current_order.
|
|
|
|
|
* With that decision it basically does not matter what we do to cur_implicit_order_index.
|
|
|
|
|
* If we change orders between the implict- and real-index, the implicit orders are mostly likely
|
|
|
|
|
* completely out-dated anyway. So, keep it simple and just keep cur_implicit_order_index as well.
|
|
|
|
|
* The worst which can happen is that a lot of implicit orders are removed when reaching current_order.
|
|
|
|
|
*/
|
|
|
|
|
if (u->cur_real_order_index == moving_order) {
|
|
|
|
|
u->cur_real_order_index = target_order;
|
|
|
|
@ -1092,12 +1092,12 @@ CommandCost CmdMoveOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32
|
|
|
|
|
u->cur_real_order_index++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (u->cur_auto_order_index == moving_order) {
|
|
|
|
|
u->cur_auto_order_index = target_order;
|
|
|
|
|
} else if (u->cur_auto_order_index > moving_order && u->cur_auto_order_index <= target_order) {
|
|
|
|
|
u->cur_auto_order_index--;
|
|
|
|
|
} else if (u->cur_auto_order_index < moving_order && u->cur_auto_order_index >= target_order) {
|
|
|
|
|
u->cur_auto_order_index++;
|
|
|
|
|
if (u->cur_implicit_order_index == moving_order) {
|
|
|
|
|
u->cur_implicit_order_index = target_order;
|
|
|
|
|
} else if (u->cur_implicit_order_index > moving_order && u->cur_implicit_order_index <= target_order) {
|
|
|
|
|
u->cur_implicit_order_index--;
|
|
|
|
|
} else if (u->cur_implicit_order_index < moving_order && u->cur_implicit_order_index >= target_order) {
|
|
|
|
|
u->cur_implicit_order_index++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
assert(v->orders.list == u->orders.list);
|
|
|
|
@ -1650,12 +1650,12 @@ restart:
|
|
|
|
|
|
|
|
|
|
OrderType ot = order->GetType();
|
|
|
|
|
if (ot == OT_GOTO_DEPOT && (order->GetDepotActionType() & ODATFB_NEAREST_DEPOT) != 0) continue;
|
|
|
|
|
if (ot == OT_AUTOMATIC || (v->type == VEH_AIRCRAFT && ot == OT_GOTO_DEPOT)) ot = OT_GOTO_STATION;
|
|
|
|
|
if (ot == OT_IMPLICIT || (v->type == VEH_AIRCRAFT && ot == OT_GOTO_DEPOT)) ot = OT_GOTO_STATION;
|
|
|
|
|
if (ot == type && order->GetDestination() == destination) {
|
|
|
|
|
/* We want to clear automatic orders, but we don't want to make them
|
|
|
|
|
/* We want to clear implicit orders, but we don't want to make them
|
|
|
|
|
* dummy orders. They should just vanish. Also check the actual order
|
|
|
|
|
* type as ot is currently OT_GOTO_STATION. */
|
|
|
|
|
if (order->IsType(OT_AUTOMATIC)) {
|
|
|
|
|
if (order->IsType(OT_IMPLICIT)) {
|
|
|
|
|
order = order->next; // DeleteOrder() invalidates current order
|
|
|
|
|
DeleteOrder(v, id);
|
|
|
|
|
if (order != NULL) goto restart;
|
|
|
|
@ -1692,7 +1692,7 @@ bool Vehicle::HasDepotOrder() const
|
|
|
|
|
* Delete all orders from a vehicle
|
|
|
|
|
* @param v Vehicle whose orders to reset
|
|
|
|
|
* @param keep_orderlist If true, do not free the order list, only empty it.
|
|
|
|
|
* @param reset_order_indices If true, reset cur_auto_order_index and cur_real_order_index
|
|
|
|
|
* @param reset_order_indices If true, reset cur_implicit_order_index and cur_real_order_index
|
|
|
|
|
* and cancel the current full load order (if the vehicle is loading).
|
|
|
|
|
* If false, _you_ have to make sure the order indices are valid after
|
|
|
|
|
* your messing with them!
|
|
|
|
@ -1712,7 +1712,7 @@ void DeleteVehicleOrders(Vehicle *v, bool keep_orderlist, bool reset_order_indic
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (reset_order_indices) {
|
|
|
|
|
v->cur_auto_order_index = v->cur_real_order_index = 0;
|
|
|
|
|
v->cur_implicit_order_index = v->cur_real_order_index = 0;
|
|
|
|
|
if (v->current_order.IsType(OT_LOADING)) {
|
|
|
|
|
CancelLoadingDueToDeletedOrder(v);
|
|
|
|
|
}
|
|
|
|
@ -1866,18 +1866,18 @@ bool UpdateOrderDest(Vehicle *v, const Order *order, int conditional_depth)
|
|
|
|
|
case OT_CONDITIONAL: {
|
|
|
|
|
VehicleOrderID next_order = ProcessConditionalOrder(order, v);
|
|
|
|
|
if (next_order != INVALID_VEH_ORDER_ID) {
|
|
|
|
|
/* Jump to next_order. cur_auto_order_index becomes exactly that order,
|
|
|
|
|
/* Jump to next_order. cur_implicit_order_index becomes exactly that order,
|
|
|
|
|
* cur_real_order_index might come after next_order. */
|
|
|
|
|
UpdateVehicleTimetable(v, false);
|
|
|
|
|
v->cur_auto_order_index = v->cur_real_order_index = next_order;
|
|
|
|
|
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)->travel_time;
|
|
|
|
|
|
|
|
|
|
/* Disable creation of automatic 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. */
|
|
|
|
|
if (v->IsGroundVehicle()) {
|
|
|
|
|
uint16 &gv_flags = v->GetGroundVehicleFlags();
|
|
|
|
|
SetBit(gv_flags, GVF_SUPPRESS_AUTOMATIC_ORDERS);
|
|
|
|
|
SetBit(gv_flags, GVF_SUPPRESS_IMPLICIT_ORDERS);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
UpdateVehicleTimetable(v, true);
|
|
|
|
@ -1891,12 +1891,12 @@ bool UpdateOrderDest(Vehicle *v, const Order *order, int conditional_depth)
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
assert(v->cur_auto_order_index < v->GetNumOrders());
|
|
|
|
|
assert(v->cur_implicit_order_index < v->GetNumOrders());
|
|
|
|
|
assert(v->cur_real_order_index < v->GetNumOrders());
|
|
|
|
|
|
|
|
|
|
/* Get the current order */
|
|
|
|
|
order = v->GetOrder(v->cur_real_order_index);
|
|
|
|
|
if (order != NULL && order->IsType(OT_AUTOMATIC)) {
|
|
|
|
|
if (order != NULL && order->IsType(OT_IMPLICIT)) {
|
|
|
|
|
assert(v->GetNumManualOrders() == 0);
|
|
|
|
|
order = NULL;
|
|
|
|
|
}
|
|
|
|
@ -1949,22 +1949,22 @@ bool ProcessOrders(Vehicle *v)
|
|
|
|
|
if (((v->current_order.IsType(OT_GOTO_STATION) && (v->current_order.GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION)) || v->current_order.IsType(OT_GOTO_WAYPOINT)) &&
|
|
|
|
|
IsTileType(v->tile, MP_STATION) &&
|
|
|
|
|
v->current_order.GetDestination() == GetStationIndex(v->tile)) {
|
|
|
|
|
v->DeleteUnreachedAutoOrders();
|
|
|
|
|
v->DeleteUnreachedImplicitOrders();
|
|
|
|
|
/* We set the last visited station here because we do not want
|
|
|
|
|
* the train to stop at this 'via' station if the next order
|
|
|
|
|
* is a no-non-stop order; in that case not setting the last
|
|
|
|
|
* visited station will cause the vehicle to still stop. */
|
|
|
|
|
v->last_station_visited = v->current_order.GetDestination();
|
|
|
|
|
UpdateVehicleTimetable(v, true);
|
|
|
|
|
v->IncrementAutoOrderIndex();
|
|
|
|
|
v->IncrementImplicitOrderIndex();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Get the current order */
|
|
|
|
|
assert(v->cur_auto_order_index == 0 || v->cur_auto_order_index < v->GetNumOrders());
|
|
|
|
|
assert(v->cur_implicit_order_index == 0 || v->cur_implicit_order_index < v->GetNumOrders());
|
|
|
|
|
v->UpdateRealOrderIndex();
|
|
|
|
|
|
|
|
|
|
const Order *order = v->GetOrder(v->cur_real_order_index);
|
|
|
|
|
if (order != NULL && order->IsType(OT_AUTOMATIC)) {
|
|
|
|
|
if (order != NULL && order->IsType(OT_IMPLICIT)) {
|
|
|
|
|
assert(v->GetNumManualOrders() == 0);
|
|
|
|
|
order = NULL;
|
|
|
|
|
}
|
|
|
|
|