* Build or remove a stretch of railroad tracks. * @param flags operation to perform * @param tile start tile of drag * @param end_tile end tile of drag * @param railtype railroad type normal/maglev (0 = normal, 1 = mono, 2 = maglev), only used for building * @param track track-orientation * @param remove remove tracks? * @param auto_remove_signals false = error on signal in the way, true =
| 871 | * @return the cost of this operation or an error |
| 872 | */ |
| 873 | static CommandCost CmdRailTrackHelper(DoCommandFlags flags, TileIndex tile, TileIndex end_tile, RailType railtype, Track track, bool remove, bool auto_remove_signals, bool fail_on_obstacle) |
| 874 | { |
| 875 | CommandCost total_cost(EXPENSES_CONSTRUCTION); |
| 876 | |
| 877 | if ((!remove && !ValParamRailType(railtype)) || !ValParamTrackOrientation(track)) return CMD_ERROR; |
| 878 | if (end_tile >= Map::Size() || tile >= Map::Size()) return CMD_ERROR; |
| 879 | |
| 880 | Trackdir trackdir = TrackToTrackdir(track); |
| 881 | |
| 882 | CommandCost ret = ValidateAutoDrag(&trackdir, tile, end_tile); |
| 883 | if (ret.Failed()) return ret; |
| 884 | |
| 885 | bool had_success = false; |
| 886 | CommandCost last_error = CMD_ERROR; |
| 887 | for (;;) { |
| 888 | ret = remove ? Command<CMD_REMOVE_SINGLE_RAIL>::Do(flags, tile, TrackdirToTrack(trackdir)) : Command<CMD_BUILD_SINGLE_RAIL>::Do(flags, tile, railtype, TrackdirToTrack(trackdir), auto_remove_signals); |
| 889 | if (!remove && !fail_on_obstacle && last_error.GetErrorMessage() == STR_ERROR_ALREADY_BUILT) had_success = true; |
| 890 | |
| 891 | if (ret.Failed()) { |
| 892 | last_error = std::move(ret); |
| 893 | if (last_error.GetErrorMessage() != STR_ERROR_ALREADY_BUILT && !remove) { |
| 894 | if (fail_on_obstacle) return last_error; |
| 895 | if (had_success) break; // Keep going if we haven't constructed any rail yet, skipping the start of the drag |
| 896 | } |
| 897 | |
| 898 | /* Ownership errors are more important. */ |
| 899 | if (last_error.GetErrorMessage() == STR_ERROR_OWNED_BY && remove) break; |
| 900 | } else { |
| 901 | had_success = true; |
| 902 | total_cost.AddCost(ret.GetCost()); |
| 903 | } |
| 904 | |
| 905 | if (tile == end_tile) break; |
| 906 | |
| 907 | tile += ToTileIndexDiff(_trackdelta[trackdir]); |
| 908 | |
| 909 | /* toggle railbit for the non-diagonal tracks */ |
| 910 | if (!IsDiagonalTrackdir(trackdir)) ToggleBit(trackdir, 0); |
| 911 | } |
| 912 | |
| 913 | if (had_success) return total_cost; |
| 914 | return last_error; |
| 915 | } |
| 916 | |
| 917 | /** |
| 918 | * Build rail on a stretch of track. |
no test coverage detected