diff --git a/src/order_cmd.cpp b/src/order_cmd.cpp index ce09ce93b9..ccedb8e31d 100644 --- a/src/order_cmd.cpp +++ b/src/order_cmd.cpp @@ -819,7 +819,16 @@ CommandCost CmdInsertOrder(DoCommandFlag flags, VehicleID veh, VehicleOrderID se if (new_order.GetNonStopType() != ONSF_STOP_EVERYWHERE && !v->IsGroundVehicle()) return CMD_ERROR; if (new_order.GetDepotOrderType() & ~(ODTFB_PART_OF_ORDERS | ((new_order.GetDepotOrderType() & ODTFB_PART_OF_ORDERS) != 0 ? ODTFB_SERVICE : 0))) return CMD_ERROR; if (new_order.GetDepotActionType() & ~(ODATFB_HALT | ODATFB_NEAREST_DEPOT | ODATFB_UNBUNCH)) return CMD_ERROR; - if ((new_order.GetDepotOrderType() & ODTFB_SERVICE) && (new_order.GetDepotActionType() & ODATFB_HALT)) return CMD_ERROR; + + /* Vehicles cannot have a "service if needed" order that also has a depot action. */ + if ((new_order.GetDepotOrderType() & ODTFB_SERVICE) && (new_order.GetDepotActionType() & (ODATFB_HALT | ODATFB_UNBUNCH))) return CMD_ERROR; + + /* Check if we're allowed to have a new unbunching order. */ + if ((new_order.GetDepotActionType() & ODATFB_UNBUNCH)) { + if (v->HasFullLoadOrder()) return CommandCost(STR_ERROR_CAN_T_ADD_ORDER, STR_ERROR_UNBUNCHING_NO_UNBUNCHING_FULL_LOAD); + if (v->HasUnbunchingOrder()) return CommandCost(STR_ERROR_CAN_T_ADD_ORDER, STR_ERROR_UNBUNCHING_ONLY_ONE_ALLOWED); + if (v->HasConditionalOrder()) return CommandCost(STR_ERROR_CAN_T_ADD_ORDER, STR_ERROR_UNBUNCHING_NO_UNBUNCHING_CONDITIONAL); + } break; } @@ -1304,12 +1313,10 @@ CommandCost CmdModifyOrder(DoCommandFlag flags, VehicleID veh, VehicleOrderID se if (data == DA_UNBUNCH) { /* Only one unbunching order is allowed in a vehicle's orders. If this order already has an unbunching action, no error is needed. */ if (v->HasUnbunchingOrder() && !(order->GetDepotActionType() & ODATFB_UNBUNCH)) return_cmd_error(STR_ERROR_UNBUNCHING_ONLY_ONE_ALLOWED); - for (Order *o : v->Orders()) { - /* We don't allow unbunching if the vehicle has a conditional order. */ - if (o->IsType(OT_CONDITIONAL)) return_cmd_error(STR_ERROR_UNBUNCHING_NO_UNBUNCHING_CONDITIONAL); - /* We don't allow unbunching if the vehicle has a full load order. */ - if (o->IsType(OT_GOTO_STATION) && o->GetLoadType() & (OLFB_FULL_LOAD | OLF_FULL_LOAD_ANY)) return_cmd_error(STR_ERROR_UNBUNCHING_NO_UNBUNCHING_FULL_LOAD); - } + /* We don't allow unbunching if the vehicle has a conditional order. */ + if (v->HasConditionalOrder()) return_cmd_error(STR_ERROR_UNBUNCHING_NO_UNBUNCHING_CONDITIONAL); + /* We don't allow unbunching if the vehicle has a full load order. */ + if (v->HasFullLoadOrder()) return_cmd_error(STR_ERROR_UNBUNCHING_NO_UNBUNCHING_FULL_LOAD); } break; diff --git a/src/order_gui.cpp b/src/order_gui.cpp index 8c8e16dfa9..02765ceece 100644 --- a/src/order_gui.cpp +++ b/src/order_gui.cpp @@ -399,16 +399,32 @@ static Order GetOrderCmdFromTile(const Vehicle *v, TileIndex tile) (_settings_client.gui.new_nonstop && v->IsGroundVehicle()) ? ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS : ONSF_STOP_EVERYWHERE); if (_ctrl_pressed) { - /* Don't allow a new unbunching order if we already have one. */ - if (v->HasUnbunchingOrder()) { + /* Check to see if we are allowed to make this an unbunching order. */ + bool failed = false; + if (v->HasFullLoadOrder()) { + /* We don't allow unbunching if the vehicle has a full load order. */ + ShowErrorMessage(STR_ERROR_CAN_T_INSERT_NEW_ORDER, STR_ERROR_UNBUNCHING_NO_UNBUNCHING_FULL_LOAD, WL_ERROR); + failed = true; + } else if (v->HasUnbunchingOrder()) { + /* Don't allow a new unbunching order if we already have one. */ ShowErrorMessage(STR_ERROR_CAN_T_INSERT_NEW_ORDER, STR_ERROR_UNBUNCHING_ONLY_ONE_ALLOWED, WL_ERROR); - /* Return an empty order to bail out. */ + failed = true; + } else if (v->HasConditionalOrder()) { + /* We don't allow unbunching if the vehicle has a conditional order. */ + ShowErrorMessage(STR_ERROR_CAN_T_INSERT_NEW_ORDER, STR_ERROR_UNBUNCHING_NO_UNBUNCHING_CONDITIONAL, WL_ERROR); + failed = true; + } + + /* Return an empty order to bail out. */ + if (failed) { order.Free(); return order; - } else { - order.SetDepotActionType(ODATFB_UNBUNCH); } + + /* Now we are allowed to set the action type. */ + order.SetDepotActionType(ODATFB_UNBUNCH); } + return order; } diff --git a/src/vehicle.cpp b/src/vehicle.cpp index 9ca49be6ad..2a03d75301 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -2426,6 +2426,30 @@ void Vehicle::HandleLoading(bool mode) this->IncrementImplicitOrderIndex(); } +/** + * Check if the current vehicle has a full load order. + * @return true Iff this vehicle has a full load order. + */ +bool Vehicle::HasFullLoadOrder() const +{ + for (Order *o : this->Orders()) { + if (o->IsType(OT_GOTO_STATION) && o->GetLoadType() & (OLFB_FULL_LOAD | OLF_FULL_LOAD_ANY)) return true; + } + return false; +} + +/** + * Check if the current vehicle has a conditional order. + * @return true Iff this vehicle has a conditional order. + */ +bool Vehicle::HasConditionalOrder() const +{ + for (Order *o : this->Orders()) { + if (o->IsType(OT_CONDITIONAL)) return true; + } + return false; +} + /** * Check if the current vehicle has an unbunching order. * @return true Iff this vehicle has an unbunching order. diff --git a/src/vehicle_base.h b/src/vehicle_base.h index 073a356c79..947e6f86a0 100644 --- a/src/vehicle_base.h +++ b/src/vehicle_base.h @@ -819,6 +819,8 @@ public: inline void SetServiceIntervalIsPercent(bool on) { SB(this->vehicle_flags, VF_SERVINT_IS_PERCENT, 1, on); } + bool HasFullLoadOrder() const; + bool HasConditionalOrder() const; bool HasUnbunchingOrder() const; void LeaveUnbunchingDepot(); bool IsWaitingForUnbunching() const;