diff --git a/src/lang/english.txt b/src/lang/english.txt --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -1451,6 +1451,8 @@ STR_CONFIG_SETTING_PERSISTENT_BUILDINGTO STR_CONFIG_SETTING_PERSISTENT_BUILDINGTOOLS_HELPTEXT :Keep the building tools for bridges, tunnels, etc. open after use STR_CONFIG_SETTING_EXPENSES_LAYOUT :Group expenses in company finance window: {STRING2} STR_CONFIG_SETTING_EXPENSES_LAYOUT_HELPTEXT :Define the layout for the company expenses window +STR_CONFIG_SETTING_AUTO_REMOVE_SIGNALS :Automatically remove signals during rail construction: {STRING2} +STR_CONFIG_SETTING_AUTO_REMOVE_SIGNALS_HELPTEXT :Automatically remove signals during rail construction if the signals are in the way. Note that this can potentially lead to train crashes. STR_CONFIG_SETTING_SOUND_TICKER :News ticker: {STRING2} STR_CONFIG_SETTING_SOUND_TICKER_HELPTEXT :Play sound for summarised news messages diff --git a/src/rail_cmd.cpp b/src/rail_cmd.cpp --- a/src/rail_cmd.cpp +++ b/src/rail_cmd.cpp @@ -262,10 +262,6 @@ static CommandCost CheckTrackCombination return_cmd_error(STR_ERROR_ALREADY_BUILT); } - /* Let's see if we may build this */ - if (HasSignals(tile) && future != TRACK_BIT_HORZ && future != TRACK_BIT_VERT) { - return_cmd_error(STR_ERROR_MUST_REMOVE_SIGNALS_FIRST); - } /* Normally, we may overlap and any combination is valid */ return CommandCost(); } @@ -432,7 +428,9 @@ static inline bool ValParamTrackOrientat * @param tile tile to build on * @param flags operation to perform * @param p1 railtype of being built piece (normal, mono, maglev) - * @param p2 rail track to build + * @param p2 various bitstuffed elements + * - (bit 0- 2) - track-orientation, valid values: 0-5 (@see Track) + * - (bit 3) - 0 = error on signal in the way, 1 = auto remove signals when in the way * @param text unused * @return the cost of this operation or an error */ @@ -440,6 +438,7 @@ CommandCost CmdBuildSingleRail(TileIndex { RailType railtype = Extract(p1); Track track = Extract(p2); + bool auto_remove_signals = HasBit(p2, 3); CommandCost cost(EXPENSES_CONSTRUCTION); if (!ValParamRailtype(railtype) || !ValParamTrackOrientation(track)) return CMD_ERROR; @@ -460,6 +459,19 @@ CommandCost CmdBuildSingleRail(TileIndex if (ret.Succeeded()) ret = EnsureNoTrainOnTrack(tile, track); if (ret.Failed()) return ret; + if (HasSignals(tile) && TracksOverlap(GetTrackBits(tile) | TrackToTrackBits(track))) { + /* If adding the new track causes any overlap, all signals must be removed first */ + if (!auto_remove_signals) return_cmd_error(STR_ERROR_MUST_REMOVE_SIGNALS_FIRST); + + for (Track track_it = TRACK_BEGIN; track_it < TRACK_END; track_it++) { + if (HasTrack(tile, track_it) && HasSignalOnTrack(tile, track_it)) { + CommandCost ret_remove_signals = DoCommand(tile, track_it, 0, flags, CMD_REMOVE_SIGNALS); + if (ret_remove_signals.Failed()) return ret_remove_signals; + cost.AddCost(ret_remove_signals); + } + } + } + ret = CheckRailSlope(tileh, trackbit, GetTrackBits(tile), tile); if (ret.Failed()) return ret; cost.AddCost(ret); @@ -868,6 +880,7 @@ static CommandCost ValidateAutoDrag(Trac * - p2 = (bit 6-8) - track-orientation, valid values: 0-5 (Track enum) * - p2 = (bit 9) - 0 = build, 1 = remove tracks * - p2 = (bit 10) - 0 = build up to an obstacle, 1 = fail if an obstacle is found (used for AIs). + * - p2 = (bit 11) - 0 = error on signal in the way, 1 = auto remove signals when in the way * @param text unused * @return the cost of this operation or an error */ @@ -876,6 +889,7 @@ static CommandCost CmdRailTrackHelper(Ti CommandCost total_cost(EXPENSES_CONSTRUCTION); Track track = Extract(p2); bool remove = HasBit(p2, 9); + bool auto_remove_signals = HasBit(p2, 11); RailType railtype = Extract(p2); if ((!remove && !ValParamRailtype(railtype)) || !ValParamTrackOrientation(track)) return CMD_ERROR; @@ -889,7 +903,7 @@ static CommandCost CmdRailTrackHelper(Ti bool had_success = false; CommandCost last_error = CMD_ERROR; for (;;) { - CommandCost ret = DoCommand(tile, remove ? 0 : railtype, TrackdirToTrack(trackdir), flags, remove ? CMD_REMOVE_SINGLE_RAIL : CMD_BUILD_SINGLE_RAIL); + CommandCost ret = DoCommand(tile, remove ? 0 : railtype, TrackdirToTrack(trackdir) | (auto_remove_signals << 3), flags, remove ? CMD_REMOVE_SINGLE_RAIL : CMD_BUILD_SINGLE_RAIL); if (ret.Failed()) { last_error = ret; diff --git a/src/rail_gui.cpp b/src/rail_gui.cpp --- a/src/rail_gui.cpp +++ b/src/rail_gui.cpp @@ -91,7 +91,7 @@ void CcPlaySound_SPLAT_RAIL(const Comman static void GenericPlaceRail(TileIndex tile, int cmd) { - DoCommandP(tile, _cur_railtype, cmd, + DoCommandP(tile, _cur_railtype, cmd | (_settings_client.gui.auto_remove_signals << 3), _remove_button_clicked ? CMD_REMOVE_SINGLE_RAIL | CMD_MSG(STR_ERROR_CAN_T_REMOVE_RAILROAD_TRACK) : CMD_BUILD_SINGLE_RAIL | CMD_MSG(STR_ERROR_CAN_T_BUILD_RAILROAD_TRACK), @@ -107,10 +107,11 @@ static void GenericPlaceRail(TileIndex t */ static void PlaceExtraDepotRail(TileIndex tile, DiagDirection dir, Track track) { - if (GetRailTileType(tile) != RAIL_TILE_NORMAL) return; + if (GetRailTileType(tile) == RAIL_TILE_DEPOT) return; + if (GetRailTileType(tile) == RAIL_TILE_SIGNALS && !_settings_client.gui.auto_remove_signals) return; if ((GetTrackBits(tile) & DiagdirReachesTracks(dir)) == 0) return; - DoCommandP(tile, _cur_railtype, track, CMD_BUILD_SINGLE_RAIL); + DoCommandP(tile, _cur_railtype, track | (_settings_client.gui.auto_remove_signals << 3), CMD_BUILD_SINGLE_RAIL); } /** Additional pieces of track to add at the entrance of a depot. */ @@ -350,7 +351,8 @@ static void BuildRailClick_Remove(Window static void DoRailroadTrack(int mode) { - DoCommandP(TileVirtXY(_thd.selstart.x, _thd.selstart.y), TileVirtXY(_thd.selend.x, _thd.selend.y), _cur_railtype | (mode << 6), + uint32 p2 = _cur_railtype | (mode << 6) | (_settings_client.gui.auto_remove_signals << 11); + DoCommandP(TileVirtXY(_thd.selstart.x, _thd.selstart.y), TileVirtXY(_thd.selend.x, _thd.selend.y), p2, _remove_button_clicked ? CMD_REMOVE_RAILROAD_TRACK | CMD_MSG(STR_ERROR_CAN_T_REMOVE_RAILROAD_TRACK) : CMD_BUILD_RAILROAD_TRACK | CMD_MSG(STR_ERROR_CAN_T_BUILD_RAILROAD_TRACK), diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp --- a/src/settings_gui.cpp +++ b/src/settings_gui.cpp @@ -1599,6 +1599,7 @@ static SettingsContainer &GetSettingsTre company->Add(new SettingEntry("gui.default_signal_type")); company->Add(new SettingEntry("gui.cycle_signal_types")); company->Add(new SettingEntry("gui.drag_signals_fixed_distance")); + company->Add(new SettingEntry("gui.auto_remove_signals")); company->Add(new SettingEntry("gui.new_nonstop")); company->Add(new SettingEntry("gui.stop_location")); company->Add(new SettingEntry("gui.starting_colour")); diff --git a/src/settings_type.h b/src/settings_type.h --- a/src/settings_type.h +++ b/src/settings_type.h @@ -147,6 +147,7 @@ struct GUISettings { uint8 osk_activation; ///< Mouse gesture to trigger the OSK. byte starting_colour; ///< default color scheme for the company to start a new game with bool show_newgrf_name; ///< Show the name of the NewGRF in the build vehicle window + bool auto_remove_signals; ///< automatically remove signals when in the way during rail construction uint16 console_backlog_timeout; ///< the minimum amount of time items should be in the console backlog before they will be removed in ~3 seconds granularity. uint16 console_backlog_length; ///< the minimum amount of items in the console backlog before items will be removed. diff --git a/src/table/settings.ini b/src/table/settings.ini --- a/src/table/settings.ini +++ b/src/table/settings.ini @@ -2859,6 +2859,14 @@ strhelp = STR_CONFIG_SETTING_COMPANY_ST strval = STR_COLOUR_DARK_BLUE [SDTC_BOOL] +var = gui.auto_remove_signals +flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC +def = false +str = STR_CONFIG_SETTING_AUTO_REMOVE_SIGNALS +strhelp = STR_CONFIG_SETTING_AUTO_REMOVE_SIGNALS_HELPTEXT +cat = SC_ADVANCED + +[SDTC_BOOL] var = gui.prefer_teamchat flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC def = false