summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/order_cmd.cpp30
-rw-r--r--src/order_func.h2
-rw-r--r--src/saveload/afterload.cpp3
3 files changed, 27 insertions, 8 deletions
diff --git a/src/order_cmd.cpp b/src/order_cmd.cpp
index aa0f0eacc..ccfb330db 100644
--- a/src/order_cmd.cpp
+++ b/src/order_cmd.cpp
@@ -1404,8 +1404,10 @@ CommandCost CmdCloneOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32
}
if (flags & DC_EXEC) {
- /* If the destination vehicle had a OrderList, destroy it */
- DeleteVehicleOrders(dst);
+ /* If the destination vehicle had a OrderList, destroy it.
+ * We only reset the order indices, if the new orders are obviously different.
+ * (We mainly do this to keep the order indices valid and in range.) */
+ DeleteVehicleOrders(dst, false, dst->GetNumOrders() != src->GetNumOrders());
dst->orders.list = src->orders.list;
@@ -1451,8 +1453,10 @@ CommandCost CmdCloneOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32
Order *first = NULL;
Order **order_dst;
- /* If the destination vehicle had an order list, destroy the chain but keep the OrderList */
- DeleteVehicleOrders(dst, true);
+ /* If the destination vehicle had an order list, destroy the chain but keep the OrderList.
+ * We only reset the order indices, if the new orders are obviously different.
+ * (We mainly do this to keep the order indices valid and in range.) */
+ DeleteVehicleOrders(dst, true, dst->GetNumOrders() != src->GetNumOrders());
order_dst = &first;
FOR_VEHICLE_ORDERS(src, order) {
@@ -1674,11 +1678,15 @@ 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
+ * 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!
*/
-void DeleteVehicleOrders(Vehicle *v, bool keep_orderlist)
+void DeleteVehicleOrders(Vehicle *v, bool keep_orderlist, bool reset_order_indices)
{
DeleteOrderWarnings(v);
@@ -1691,6 +1699,13 @@ void DeleteVehicleOrders(Vehicle *v, bool keep_orderlist)
v->orders.list->FreeChain(keep_orderlist);
if (!keep_orderlist) v->orders.list = NULL;
}
+
+ if (reset_order_indices) {
+ v->cur_auto_order_index = v->cur_real_order_index = 0;
+ if (v->current_order.IsType(OT_LOADING)) {
+ CancelLoadingDueToDeletedOrder(v);
+ }
+ }
}
/**
@@ -1927,6 +1942,7 @@ bool ProcessOrders(Vehicle *v)
}
/* Get the current order */
+ assert(v->cur_auto_order_index == 0 || v->cur_auto_order_index < v->GetNumOrders());
v->UpdateRealOrderIndex();
const Order *order = v->GetOrder(v->cur_real_order_index);
diff --git a/src/order_func.h b/src/order_func.h
index 235f9cdc9..c6ed76d23 100644
--- a/src/order_func.h
+++ b/src/order_func.h
@@ -20,7 +20,7 @@
void RemoveOrderFromAllVehicles(OrderType type, DestinationID destination);
void InvalidateVehicleOrder(const Vehicle *v, int data);
void CheckOrders(const Vehicle*);
-void DeleteVehicleOrders(Vehicle *v, bool keep_orderlist = false);
+void DeleteVehicleOrders(Vehicle *v, bool keep_orderlist = false, bool reset_order_indices = true);
bool ProcessOrders(Vehicle *v);
bool UpdateOrderDest(Vehicle *v, const Order *order, int conditional_depth = 0);
VehicleOrderID ProcessConditionalOrder(const Order *order, const Vehicle *v);
diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp
index 17ac9bc81..fe99e3c3e 100644
--- a/src/saveload/afterload.cpp
+++ b/src/saveload/afterload.cpp
@@ -2564,6 +2564,9 @@ bool AfterLoadGame()
FOR_ALL_VEHICLES(v) {
if (!v->IsPrimaryVehicle()) continue;
+ /* Older versions are less strict with indices being in range and fix them on the fly */
+ if (v->cur_auto_order_index >= v->GetNumOrders()) v->cur_auto_order_index = 0;
+
v->cur_real_order_index = v->cur_auto_order_index;
v->UpdateRealOrderIndex();
}