Fix #12118: When adding an unbunching order, properly check for unsafe conditions (#12136)

This commit is contained in:
Tyler Trahan 2024-03-09 08:28:05 -05:00 committed by GitHub
parent 6e0f58f700
commit ab315d0dc9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 61 additions and 12 deletions

View File

@ -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;

View File

@ -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;
}

View File

@ -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.

View File

@ -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;