summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/train_cmd.cpp105
1 files changed, 58 insertions, 47 deletions
diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp
index 3028ad366..5cebea8d3 100644
--- a/src/train_cmd.cpp
+++ b/src/train_cmd.cpp
@@ -2809,49 +2809,66 @@ static bool TryReserveSafeTrack(const Vehicle* v, TileIndex tile, Trackdir td, b
}
}
-/**
- * Query the next order after a certain order index.
- *
- * @param v The vehicle
- * @param order_index [in/out] Index of the current order, returns index of the chosen order
- * @return Pointer to the order or NULL if the order chain was completely followed
- * without finding a suitable order.
- */
-static const Order* GetNextTrainOrder(const Vehicle *v, VehicleOrderID *order_index)
+/** This class will save the current order of a vehicle and restore it on destruction. */
+class VehicleOrderSaver
{
- ++(*order_index);
+private:
+ Vehicle *v;
+ Order old_order;
+ TileIndex old_dest_tile;
+ VehicleOrderID index;
+
+public:
+ VehicleOrderSaver(Vehicle *_v) : v(_v), old_order(_v->current_order), old_dest_tile(_v->dest_tile), index(_v->cur_order_index)
+ {
+ }
- do {
- /* Wrap around. */
- if (*order_index >= v->num_orders) *order_index = 0;
-
- Order *order = GetVehicleOrder(v, *order_index);
- assert(order != NULL);
-
- switch (order->GetType()) {
- case OT_GOTO_DEPOT:
- /* Skip service in depot orders when the train doesn't need service. */
- if ((order->GetDepotOrderType() & ODTFB_SERVICE) && !v->NeedsServicing()) break;
- case OT_GOTO_STATION:
- case OT_GOTO_WAYPOINT:
- return order;
- case OT_CONDITIONAL: {
- VehicleOrderID next = ProcessConditionalOrder(order, v);
- if (next != INVALID_VEH_ORDER_ID) {
- *order_index = next;
- continue;
+ ~VehicleOrderSaver()
+ {
+ this->v->current_order = this->old_order;
+ this->v->dest_tile = this->old_dest_tile;
+ }
+
+ /**
+ * Set the current vehicle order to the next order in the order list.
+ * @return True if a suitable next order could be found.
+ */
+ bool SwitchToNextOrder()
+ {
+ ++this->index;
+
+ do {
+ /* Wrap around. */
+ if (this->index >= this->v->num_orders) this->index = 0;
+
+ Order *order = GetVehicleOrder(this->v, this->index);
+ assert(order != NULL);
+
+ switch (order->GetType()) {
+ case OT_GOTO_DEPOT:
+ /* Skip service in depot orders when the train doesn't need service. */
+ if ((order->GetDepotOrderType() & ODTFB_SERVICE) && !this->v->NeedsServicing()) break;
+ case OT_GOTO_STATION:
+ case OT_GOTO_WAYPOINT:
+ this->v->current_order = *order;
+ UpdateOrderDest(this->v, order);
+ return true;
+ case OT_CONDITIONAL: {
+ VehicleOrderID next = ProcessConditionalOrder(order, this->v);
+ if (next != INVALID_VEH_ORDER_ID) {
+ this->index = next;
+ continue;
+ }
+ break;
}
- break;
+ default:
+ break;
}
- default:
- break;
- }
-
- ++(*order_index);
- } while (*order_index != v->cur_order_index);
+ } while (++this->index != this->v->cur_order_index);
- return NULL;
-}
+ return false;
+ }
+};
/* choose a track */
static Track ChooseTrainTrack(Vehicle* v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool force_res, bool *got_reservation, bool mark_stuck)
@@ -2964,10 +2981,9 @@ static Track ChooseTrainTrack(Vehicle* v, TileIndex tile, DiagDirection enterdir
if (got_reservation != NULL) *got_reservation = true;
+ /* Save the current train order. The destructor will restore the old order on function exit. */
+ VehicleOrderSaver orders(v);
/* Reservation target found and free, check if it is safe. */
- Order cur_order = v->current_order;
- TileIndex cur_dest_tile = v->dest_tile;
- VehicleOrderID order_index = v->cur_order_index;
while (!IsSafeWaitingPosition(v, res_dest.tile, res_dest.trackdir, true, _settings_game.pf.forbid_90_deg)) {
/* Extend reservation until we have found a safe position. */
DiagDirection exitdir = TrackdirToExitdir(res_dest.trackdir);
@@ -2978,10 +2994,7 @@ static Track ChooseTrainTrack(Vehicle* v, TileIndex tile, DiagDirection enterdir
}
/* Get next order with destination. */
- const Order *order = GetNextTrainOrder(v, &order_index);
- if (order != NULL) {
- v->current_order = *order;
- UpdateOrderDest(v, order);
+ if (orders.SwitchToNextOrder()) {
PBSTileInfo cur_dest;
DoTrainPathfind(v, next_tile, exitdir, reachable, NULL, true, &cur_dest);
if (cur_dest.tile != INVALID_TILE) {
@@ -3004,8 +3017,6 @@ static Track ChooseTrainTrack(Vehicle* v, TileIndex tile, DiagDirection enterdir
}
break;
}
- v->current_order = cur_order;
- v->dest_tile = cur_dest_tile;
TryReserveRailTrack(v->tile, TrackdirToTrack(GetVehicleTrackdir(v)));