diff --git a/src/lang/english.txt b/src/lang/english.txt index 102f4aae6d..2e5430d08d 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -1574,7 +1574,7 @@ STR_CONFIG_SETTING_SHOW_NOENTRYSIG_FEATURES_HELPTEXT :Show no-entry s STR_CONFIG_SETTING_SHOW_VEH_LIST_CARGO_FILTER :Show cargo type filter in vehicle lists: {STRING2} STR_CONFIG_SETTING_SHOW_VEH_LIST_CARGO_FILTER_HELPTEXT :Show cargo type filter in vehicle lists. When enabled vehicle list windows include an additional filter dropdown. STR_CONFIG_SETTING_SHOW_ADV_LOADING_MODE_FEATURES :Show advanced loading mode features: {STRING2} -STR_CONFIG_SETTING_SHOW_ADV_LOADING_MODE_FEATURES_HELPTEXT :Show advanced loading mode features (through load/unload). When disabled, some advanced loading mode features are not shown in the UI, but are still available to all players. +STR_CONFIG_SETTING_SHOW_ADV_LOADING_MODE_FEATURES_HELPTEXT :Show advanced loading mode features (through load/unload, road vehicle direction). When disabled, some advanced loading mode features are not shown in the UI, but are still available to all players. STR_CONFIG_SETTING_DISABLE_TOP_VEH_LIST_MASS_ACTIONS :Disable mass action buttons for top-level vehicle lists: {STRING2} STR_CONFIG_SETTING_DISABLE_TOP_VEH_LIST_MASS_ACTIONS_HELPTEXT :This disables depot/service and start/stop buttons for all vehicle and all ungrouped vehicle lists. This is intended to help avoid the negative impact of accidentally pressing one of these buttons. STR_CONFIG_SETTING_SHOW_DEPOT_SELL_GUI :Show go to depot/hangar and sell feature: {STRING2} @@ -5632,6 +5632,11 @@ STR_ORDER_STOP_LOCATION_MIDDLE :[middle] STR_ORDER_STOP_LOCATION_FAR_END :[far end] STR_ORDER_STOP_LOCATION_THROUGH :[through load] +STR_ORDER_RV_DIR_NE :[north-east direction] +STR_ORDER_RV_DIR_SE :[south-east direction] +STR_ORDER_RV_DIR_SW :[south-west direction] +STR_ORDER_RV_DIR_NW :[north-west direction] + STR_ORDER_OUT_OF_RANGE :{RED} (Next destination is out of range) STR_ORDER_CONDITIONAL_UNCONDITIONAL :Jump to order {COMMA} diff --git a/src/order_base.h b/src/order_base.h index 1a6ff77a88..29d3583031 100644 --- a/src/order_base.h +++ b/src/order_base.h @@ -498,6 +498,15 @@ public: if (leave_type != this->GetLeaveType()) SB(this->GetXFlagsRef(), 2, 2, leave_type); } + /** Get the road vehicle travel direction */ + inline DiagDirection GetRoadVehTravelDirection() const { return (DiagDirection)((GB(this->GetXFlags(), 5, 3) - 1) & 0xFF); } + + /** Set the road vehicle travel direction */ + inline void SetRoadVehTravelDirection(DiagDirection dir) + { + if (dir != this->GetRoadVehTravelDirection()) SB(this->GetXFlagsRef(), 5, 3, (dir + 1) & 0x7); + } + /** * Get the occupancy value * @return occupancy diff --git a/src/order_cmd.cpp b/src/order_cmd.cpp index 23ae7e2e57..7e10d9b84a 100644 --- a/src/order_cmd.cpp +++ b/src/order_cmd.cpp @@ -1711,7 +1711,7 @@ CommandCost CmdModifyOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3 Order *order = v->GetOrder(sel_ord); switch (order->GetType()) { case OT_GOTO_STATION: - if (mof != MOF_NON_STOP && mof != MOF_STOP_LOCATION && mof != MOF_UNLOAD && mof != MOF_LOAD && mof != MOF_CARGO_TYPE_UNLOAD && mof != MOF_CARGO_TYPE_LOAD) return CMD_ERROR; + if (mof != MOF_NON_STOP && mof != MOF_STOP_LOCATION && mof != MOF_UNLOAD && mof != MOF_LOAD && mof != MOF_CARGO_TYPE_UNLOAD && mof != MOF_CARGO_TYPE_LOAD && mof != MOF_RV_TRAVEL_DIR) return CMD_ERROR; break; case OT_GOTO_DEPOT: @@ -1719,7 +1719,7 @@ CommandCost CmdModifyOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3 break; case OT_GOTO_WAYPOINT: - if (mof != MOF_NON_STOP && mof != MOF_WAYPOINT_FLAGS) return CMD_ERROR; + if (mof != MOF_NON_STOP && mof != MOF_WAYPOINT_FLAGS && mof != MOF_RV_TRAVEL_DIR) return CMD_ERROR; break; case OT_CONDITIONAL: @@ -1901,6 +1901,11 @@ CommandCost CmdModifyOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3 if (slot == nullptr || slot->vehicle_type != v->type) return CMD_ERROR; } break; + + case MOF_RV_TRAVEL_DIR: + if (v->type != VEH_ROAD) return CMD_ERROR; + if (data >= DIAGDIR_END && data != INVALID_DIAGDIR) return CMD_ERROR; + break; } if (flags & DC_EXEC) { @@ -2120,6 +2125,10 @@ CommandCost CmdModifyOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3 order->SetDestination(data); break; + case MOF_RV_TRAVEL_DIR: + order->SetRoadVehTravelDirection((DiagDirection)data); + break; + default: NOT_REACHED(); } @@ -2169,6 +2178,10 @@ CommandCost CmdModifyOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3 break; } } + if (mof == MOF_RV_TRAVEL_DIR && sel_ord == u->cur_real_order_index && + (u->current_order.IsType(OT_GOTO_STATION) || u->current_order.IsType(OT_GOTO_WAYPOINT))) { + u->current_order.SetRoadVehTravelDirection((DiagDirection)data); + } InvalidateVehicleOrder(u, VIWD_MODIFY_ORDERS); } CheckMarkDirtyFocusedRoutePaths(v); diff --git a/src/order_gui.cpp b/src/order_gui.cpp index c14e7f0100..9caee23db5 100644 --- a/src/order_gui.cpp +++ b/src/order_gui.cpp @@ -870,6 +870,9 @@ void DrawOrderString(const Vehicle *v, const Order *order, int order_index, int if (v->type == VEH_TRAIN && (order->GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION) == 0) { SetDParam(7, order->GetStopLocation() + STR_ORDER_STOP_LOCATION_NEAR_END); } + if (v->type == VEH_ROAD && order->GetRoadVehTravelDirection() != INVALID_DIAGDIR && _settings_game.pf.pathfinder_for_roadvehs == VPF_YAPF) { + SetDParam(7, order->GetRoadVehTravelDirection() + STR_ORDER_RV_DIR_NE); + } } break; } @@ -928,6 +931,9 @@ void DrawOrderString(const Vehicle *v, const Order *order, int order_index, int SetTimetableParams(8, order->GetWaitTime()); timetable_wait_time_valid = true; } + if (!timetable && v->type == VEH_ROAD && order->GetRoadVehTravelDirection() != INVALID_DIAGDIR && _settings_game.pf.pathfinder_for_roadvehs == VPF_YAPF) { + SetDParam(7, order->GetRoadVehTravelDirection() + STR_ORDER_RV_DIR_NE); + } break; } @@ -2321,6 +2327,14 @@ public: } this->ModifyOrder(sel, MOF_STOP_LOCATION | osl << 4); } + if (this->vehicle->type == VEH_ROAD && sel < this->vehicle->GetNumOrders() && _settings_game.pf.pathfinder_for_roadvehs == VPF_YAPF) { + DiagDirection current = this->vehicle->GetOrder(sel)->GetRoadVehTravelDirection(); + if (_settings_client.gui.show_adv_load_mode_features || current != INVALID_DIAGDIR) { + uint dir = (current + 1) & 0xFF; + if (dir >= DIAGDIR_END) dir = INVALID_DIAGDIR; + this->ModifyOrder(sel, MOF_RV_TRAVEL_DIR | dir << 4); + } + } } else { /* Select clicked order */ this->selected_order = sel; diff --git a/src/order_type.h b/src/order_type.h index 56ebf6cfb9..809cf8a33e 100644 --- a/src/order_type.h +++ b/src/order_type.h @@ -196,6 +196,7 @@ enum ModifyOrderFlags { MOF_CARGO_TYPE_UNLOAD, ///< Passes an OrderUnloadType and a CargoID. MOF_CARGO_TYPE_LOAD, ///< Passes an OrderLoadType and a CargoID. MOF_SLOT, ///< Change the slot value + MOF_RV_TRAVEL_DIR, ///< Change the road vehicle travel direction. MOF_END }; template <> struct EnumPropsT : MakeEnumPropsT {}; diff --git a/src/pathfinder/yapf/yapf_road.cpp b/src/pathfinder/yapf/yapf_road.cpp index 38b1694586..fb3ee0c25a 100644 --- a/src/pathfinder/yapf/yapf_road.cpp +++ b/src/pathfinder/yapf/yapf_road.cpp @@ -278,18 +278,22 @@ protected: public: void SetDestination(const RoadVehicle *v) { + auto set_trackdirs = [&]() { + DiagDirection dir = v->current_order.GetRoadVehTravelDirection(); + m_destTrackdirs = (dir == INVALID_DIAGDIR) ? INVALID_TRACKDIR_BIT : TrackdirToTrackdirBits(DiagDirToDiagTrackdir(dir)); + }; if (v->current_order.IsType(OT_GOTO_STATION)) { m_dest_station = v->current_order.GetDestination(); + set_trackdirs(); m_station_type = v->IsBus() ? STATION_BUS : STATION_TRUCK; m_destTile = CalcClosestStationTile(m_dest_station, v->tile, m_station_type); m_non_artic = !v->HasArticulatedPart(); - m_destTrackdirs = INVALID_TRACKDIR_BIT; } else if (v->current_order.IsType(OT_GOTO_WAYPOINT)) { m_dest_station = v->current_order.GetDestination(); + set_trackdirs(); m_station_type = STATION_ROADWAYPOINT; m_destTile = CalcClosestStationTile(m_dest_station, v->tile, m_station_type); m_non_artic = !v->HasArticulatedPart(); - m_destTrackdirs = INVALID_TRACKDIR_BIT; } else { m_dest_station = INVALID_STATION; m_destTile = v->dest_tile; @@ -322,7 +326,9 @@ public: return IsTileType(tile, MP_STATION) && GetStationIndex(tile) == m_dest_station && (m_station_type == GetStationType(tile)) && - (m_non_artic || IsDriveThroughStopTile(tile)); + (m_non_artic || IsDriveThroughStopTile(tile)) && + (m_destTrackdirs == INVALID_TRACKDIR_BIT || + (IsDriveThroughStopTile(tile) ? HasTrackdir(m_destTrackdirs, trackdir) : HasTrackdir(m_destTrackdirs, DiagDirToDiagTrackdir(ReverseDiagDir(GetRoadStopDir(tile)))))); } return tile == m_destTile && HasTrackdir(m_destTrackdirs, trackdir); diff --git a/src/saveload/extended_ver_sl.cpp b/src/saveload/extended_ver_sl.cpp index 9936e4bd69..dd4e429e76 100644 --- a/src/saveload/extended_ver_sl.cpp +++ b/src/saveload/extended_ver_sl.cpp @@ -168,6 +168,7 @@ const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = { { XSLFI_WAYPOINT_FLAGS, XSCF_NULL, 1, 1, "waypoint_flags", nullptr, nullptr, nullptr }, { XSLFI_ROAD_WAYPOINTS, XSCF_NULL, 1, 1, "road_waypoints", nullptr, nullptr, nullptr }, { XSLFI_MORE_STATION_TYPES, XSCF_NULL, 1, 1, "more_station_types", nullptr, nullptr, nullptr }, + { XSLFI_RV_ORDER_EXTRA_FLAGS, XSCF_IGNORABLE_UNKNOWN, 1, 1, "rv_order_extra_flags", nullptr, nullptr, nullptr }, { XSLFI_SCRIPT_INT64, XSCF_NULL, 1, 1, "script_int64", nullptr, nullptr, nullptr }, { XSLFI_NULL, XSCF_NULL, 0, 0, nullptr, nullptr, nullptr, nullptr },// This is the end marker }; diff --git a/src/saveload/extended_ver_sl.h b/src/saveload/extended_ver_sl.h index 001539950b..5bc452825d 100644 --- a/src/saveload/extended_ver_sl.h +++ b/src/saveload/extended_ver_sl.h @@ -122,6 +122,7 @@ enum SlXvFeatureIndex { XSLFI_WAYPOINT_FLAGS, ///< Waypoint flags XSLFI_ROAD_WAYPOINTS, ///< Road waypoints XSLFI_MORE_STATION_TYPES, ///< More station types (field widening) + XSLFI_RV_ORDER_EXTRA_FLAGS, ///< Road vehicle order extra flags XSLFI_SCRIPT_INT64, ///< See: SLV_SCRIPT_INT64