From d3efa2afe043fab82eadb21548fb50fbd65e4c61 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Tue, 29 Mar 2022 22:14:12 +0100 Subject: [PATCH] Show specific reason why vehicle cannot be ordered to a particular station --- src/lang/english.txt | 13 ++++++++++++ src/order_cmd.cpp | 10 ++++----- src/vehicle.cpp | 49 ++++++++++++++++++++++++++++++++++++++++++++ src/vehicle_func.h | 1 + 4 files changed, 68 insertions(+), 5 deletions(-) diff --git a/src/lang/english.txt b/src/lang/english.txt index b8d79a5a02..334f3ef48b 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -6413,6 +6413,19 @@ STR_ERROR_CAN_T_COPY_ORDER_LIST :{WHITE}Can't co STR_ERROR_TOO_FAR_FROM_PREVIOUS_DESTINATION :{WHITE}... too far from previous destination STR_ERROR_AIRCRAFT_NOT_ENOUGH_RANGE :{WHITE}... aircraft has not enough range +STR_ERROR_NO_RAIL_STATION :{WHITE}There is no railway station... +STR_ERROR_NO_BUS_STATION :{WHITE}There is no bus station... +STR_ERROR_NO_TRUCK_STATION :{WHITE}There is no lorry station... +STR_ERROR_NO_DOCK :{WHITE}There is no dock... +STR_ERROR_NO_AIRPORT :{WHITE}There is no airport/heliport... +STR_ERROR_NO_STOP_COMPATIBLE_ROAD_TYPE :{WHITE}There are no stops with a compatible road/tram type... +STR_ERROR_NO_STOP_ARTIC_VEH :{WHITE}There are no stops which are suitable for articulated road vehicles.{}Articulated road vehicles require a drive-through stop, not a bay stop... +STR_ERROR_AIRPORT_NO_PLANES :{WHITE}This plane cannot land at this heliport... +STR_ERROR_AIRPORT_NO_HELIS :{WHITE}This helicopter cannot land at this airport... +STR_ERROR_NO_RAIL_WAYPOINT :{WHITE}There is no railway waypoint... +STR_ERROR_NO_ROAD_WAYPOINT :{WHITE}There is no road waypoint... +STR_ERROR_NO_BUOY :{WHITE}There is no buoy... + # Timetable related errors STR_ERROR_CAN_T_TIMETABLE_VEHICLE :{WHITE}Can't timetable vehicle... STR_ERROR_TIMETABLE_ONLY_WAIT_AT_STATIONS :{WHITE}Vehicles can only wait at stations diff --git a/src/order_cmd.cpp b/src/order_cmd.cpp index e30a3e506b..57ba2b49be 100644 --- a/src/order_cmd.cpp +++ b/src/order_cmd.cpp @@ -984,9 +984,9 @@ CommandCost CmdInsertOrderIntl(DoCommandFlag flags, Vehicle *v, VehicleOrderID s if (ret.Failed()) return ret; } - if (!CanVehicleUseStation(v, st)) return_cmd_error(STR_ERROR_CAN_T_ADD_ORDER); + if (!CanVehicleUseStation(v, st)) return CommandCost::DualErrorMessage(STR_ERROR_CAN_T_ADD_ORDER, GetVehicleCannotUseStationReason(v, st)); for (Vehicle *u = v->FirstShared(); u != nullptr; u = u->NextShared()) { - if (!CanVehicleUseStation(u, st)) return_cmd_error(STR_ERROR_CAN_T_ADD_ORDER_SHARED); + if (!CanVehicleUseStation(u, st)) return CommandCost::DualErrorMessage(STR_ERROR_CAN_T_ADD_ORDER_SHARED, GetVehicleCannotUseStationReason(u, st)); } /* Non stop only allowed for ground vehicles. */ @@ -1083,7 +1083,7 @@ CommandCost CmdInsertOrderIntl(DoCommandFlag flags, Vehicle *v, VehicleOrderID s default: return CMD_ERROR; case VEH_TRAIN: { - if (!(wp->facilities & FACIL_TRAIN)) return_cmd_error(STR_ERROR_CAN_T_ADD_ORDER); + if (!(wp->facilities & FACIL_TRAIN)) return CommandCost::DualErrorMessage(STR_ERROR_CAN_T_ADD_ORDER, STR_ERROR_NO_RAIL_WAYPOINT); CommandCost ret = CheckInfraUsageAllowed(v->type, wp->owner); if (ret.Failed()) return ret; @@ -1091,7 +1091,7 @@ CommandCost CmdInsertOrderIntl(DoCommandFlag flags, Vehicle *v, VehicleOrderID s } case VEH_ROAD: { - if (!(wp->facilities & FACIL_BUS_STOP) || !(wp->facilities & FACIL_TRUCK_STOP)) return_cmd_error(STR_ERROR_CAN_T_ADD_ORDER); + if (!(wp->facilities & FACIL_BUS_STOP) || !(wp->facilities & FACIL_TRUCK_STOP)) return CommandCost::DualErrorMessage(STR_ERROR_CAN_T_ADD_ORDER, STR_ERROR_NO_ROAD_WAYPOINT); CommandCost ret = CheckInfraUsageAllowed(v->type, wp->owner); if (ret.Failed()) return ret; @@ -1099,7 +1099,7 @@ CommandCost CmdInsertOrderIntl(DoCommandFlag flags, Vehicle *v, VehicleOrderID s } case VEH_SHIP: - if (!(wp->facilities & FACIL_DOCK)) return_cmd_error(STR_ERROR_CAN_T_ADD_ORDER); + if (!(wp->facilities & FACIL_DOCK)) return CommandCost::DualErrorMessage(STR_ERROR_CAN_T_ADD_ORDER, STR_ERROR_NO_BUOY); if (wp->owner != OWNER_NONE) { CommandCost ret = CheckInfraUsageAllowed(v->type, wp->owner); if (ret.Failed()) return ret; diff --git a/src/vehicle.cpp b/src/vehicle.cpp index f7a0470359..e34c9eba25 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -4338,6 +4338,55 @@ bool CanVehicleUseStation(const Vehicle *v, const Station *st) return CanVehicleUseStation(v->engine_type, st); } +/** + * Get reason string why this station can't be used by the given vehicle + * @param v the vehicle to test + * @param st the station to test for + * @return true if and only if the vehicle can use this station. + */ +StringID GetVehicleCannotUseStationReason(const Vehicle *v, const Station *st) +{ + switch (v->type) { + case VEH_TRAIN: + return STR_ERROR_NO_RAIL_STATION; + + case VEH_ROAD: { + const RoadVehicle *rv = RoadVehicle::From(v); + RoadStop *rs = st->GetPrimaryRoadStop(rv->IsBus() ? ROADSTOP_BUS : ROADSTOP_TRUCK); + + StringID err = rv->IsBus() ? STR_ERROR_NO_BUS_STATION : STR_ERROR_NO_TRUCK_STATION; + + for (; rs != nullptr; rs = rs->next) { + /* The vehicle is articulated and can therefore not go to a standard road stop. */ + if (IsStandardRoadStopTile(rs->xy) && rv->HasArticulatedPart()) { + err = STR_ERROR_NO_STOP_ARTIC_VEH; + continue; + } + /* The vehicle cannot go to this roadstop (different roadtype) */ + if (!HasTileAnyRoadType(rs->xy, rv->compatible_roadtypes)) return STR_ERROR_NO_STOP_COMPATIBLE_ROAD_TYPE; + + return INVALID_STRING_ID; + } + + return err; + } + + case VEH_SHIP: + return STR_ERROR_NO_DOCK; + + case VEH_AIRCRAFT: + if ((st->facilities & FACIL_AIRPORT) == 0) return STR_ERROR_NO_AIRPORT; + if (v->GetEngine()->u.air.subtype & AIR_CTOL) { + return STR_ERROR_AIRPORT_NO_PLANES; + } else { + return STR_ERROR_AIRPORT_NO_HELIS; + } + + default: + return INVALID_STRING_ID; + } +} + /** * Access the ground vehicle cache of the vehicle. * @pre The vehicle is a #GroundVehicle. diff --git a/src/vehicle_func.h b/src/vehicle_func.h index 6df1292733..7be1addcf0 100644 --- a/src/vehicle_func.h +++ b/src/vehicle_func.h @@ -248,6 +248,7 @@ extern uint16 _returned_mail_refit_capacity; bool CanVehicleUseStation(EngineID engine_type, const struct Station *st); bool CanVehicleUseStation(const Vehicle *v, const struct Station *st); +StringID GetVehicleCannotUseStationReason(const Vehicle *v, const Station *st); void ReleaseDisastersTargetingVehicle(VehicleID vehicle);