From 99e50906de4eb6af1b7c429917af7eff32017041 Mon Sep 17 00:00:00 2001 From: J0anJosep Date: Tue, 30 Mar 2021 16:37:32 +0200 Subject: [PATCH] Add: Allow removing company rail depots in an area. --- src/command_type.h | 1 + src/lang/english.txt | 1 + src/rail_cmd.cpp | 26 ++++++++++++++++++++++++++ src/rail_cmd.h | 2 ++ src/rail_gui.cpp | 30 +++++++++++++++++++----------- src/script/api/script_rail.cpp | 9 +++++++++ src/script/api/script_rail.hpp | 13 +++++++++++++ src/viewport_type.h | 1 + 8 files changed, 72 insertions(+), 11 deletions(-) diff --git a/src/command_type.h b/src/command_type.h index 85f5680aead87..69f6632ff86f3 100644 --- a/src/command_type.h +++ b/src/command_type.h @@ -182,6 +182,7 @@ enum Commands : uint16 { CMD_BUILD_BRIDGE, ///< build a bridge CMD_BUILD_RAIL_STATION, ///< build a rail station CMD_BUILD_TRAIN_DEPOT, ///< build a train depot + CMD_REMOVE_TRAIN_DEPOT, ///< remove a train depot CMD_BUILD_SIGNALS, ///< build a signal CMD_REMOVE_SIGNALS, ///< remove a signal CMD_TERRAFORM_LAND, ///< terraform a tile diff --git a/src/lang/english.txt b/src/lang/english.txt index b345999dbbfc5..637660f624786 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -4840,6 +4840,7 @@ STR_ERROR_BUOY_IS_IN_USE :{WHITE}... buoy # Depot related errors STR_ERROR_CAN_T_BUILD_TRAIN_DEPOT :{WHITE}Can't build train depot here... +STR_ERROR_CAN_T_REMOVE_TRAIN_DEPOT :{WHITE}Can't remove train depot here... STR_ERROR_CAN_T_BUILD_ROAD_DEPOT :{WHITE}Can't build road vehicle depot here... STR_ERROR_CAN_T_BUILD_TRAM_DEPOT :{WHITE}Can't build tram vehicle depot here... STR_ERROR_CAN_T_BUILD_SHIP_DEPOT :{WHITE}Can't build ship depot here... diff --git a/src/rail_cmd.cpp b/src/rail_cmd.cpp index 67d14ec7089fd..b4d4601f03dec 100644 --- a/src/rail_cmd.cpp +++ b/src/rail_cmd.cpp @@ -1771,6 +1771,8 @@ CommandCost CmdConvertRail(DoCommandFlag flags, TileIndex tile, TileIndex area_s static CommandCost RemoveTrainDepot(TileIndex tile, DoCommandFlag flags) { + assert(IsRailDepotTile(tile)); + if (_current_company != OWNER_WATER) { CommandCost ret = CheckTileOwnership(tile); if (ret.Failed()) return ret; @@ -1808,6 +1810,30 @@ static CommandCost RemoveTrainDepot(TileIndex tile, DoCommandFlag flags) return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_CLEAR_DEPOT_TRAIN]); } +/** + * Remove train depots from an area + * @param flags operation to perform + * @param start_tile start tile of the area + * @param end_tile end tile of the area + * @return the cost of this operation or an error + */ +CommandCost CmdRemoveTrainDepot(DoCommandFlag flags, TileIndex start_tile, TileIndex end_tile) +{ + assert(IsValidTile(start_tile)); + assert(IsValidTile(end_tile)); + + CommandCost cost(EXPENSES_CONSTRUCTION); + TileArea ta(start_tile, end_tile); + for (TileIndex t : ta) { + if (!IsRailDepotTile(t)) continue; + CommandCost ret = RemoveTrainDepot(t, flags); + if (ret.Failed()) return ret; + cost.AddCost(ret); + } + + return cost; +} + static CommandCost ClearTile_Track(TileIndex tile, DoCommandFlag flags) { CommandCost cost(EXPENSES_CONSTRUCTION); diff --git a/src/rail_cmd.h b/src/rail_cmd.h index 32db8633ebaad..28d7c15191fe0 100644 --- a/src/rail_cmd.h +++ b/src/rail_cmd.h @@ -20,6 +20,7 @@ CommandCost CmdRemoveRailroadTrack(DoCommandFlag flags, TileIndex end_tile, Tile CommandCost CmdBuildSingleRail(DoCommandFlag flags, TileIndex tile, RailType railtype, Track track, bool auto_remove_signals); CommandCost CmdRemoveSingleRail(DoCommandFlag flags, TileIndex tile, Track track); CommandCost CmdBuildTrainDepot(DoCommandFlag flags, TileIndex tile, RailType railtype, DiagDirection dir, bool adjacent, DepotID depot_id, TileIndex end_tile); +CommandCost CmdRemoveTrainDepot(DoCommandFlag flags, TileIndex start_tile, TileIndex end_tile); CommandCost CmdBuildSingleSignal(DoCommandFlag flags, TileIndex tile, Track track, SignalType sigtype, SignalVariant sigvar, bool convert_signal, bool skip_existing_signals, bool ctrl_pressed, SignalType cycle_start, SignalType cycle_stop, uint8 num_dir_cycle, byte signals_copy); CommandCost CmdRemoveSingleSignal(DoCommandFlag flags, TileIndex tile, Track track); CommandCost CmdConvertRail(DoCommandFlag flags, TileIndex tile, TileIndex area_start, RailType totype, bool diagonal); @@ -31,6 +32,7 @@ DEF_CMD_TRAIT(CMD_REMOVE_RAILROAD_TRACK, CmdRemoveRailroadTrack, CMD_AUTO, DEF_CMD_TRAIT(CMD_BUILD_SINGLE_RAIL, CmdBuildSingleRail, CMD_AUTO | CMD_NO_WATER, CMDT_LANDSCAPE_CONSTRUCTION) DEF_CMD_TRAIT(CMD_REMOVE_SINGLE_RAIL, CmdRemoveSingleRail, CMD_AUTO, CMDT_LANDSCAPE_CONSTRUCTION) DEF_CMD_TRAIT(CMD_BUILD_TRAIN_DEPOT, CmdBuildTrainDepot, CMD_AUTO | CMD_NO_WATER, CMDT_LANDSCAPE_CONSTRUCTION) +DEF_CMD_TRAIT(CMD_REMOVE_TRAIN_DEPOT, CmdRemoveTrainDepot, CMD_AUTO | CMD_NO_WATER, CMDT_LANDSCAPE_CONSTRUCTION) DEF_CMD_TRAIT(CMD_BUILD_SIGNALS, CmdBuildSingleSignal, CMD_AUTO, CMDT_LANDSCAPE_CONSTRUCTION) DEF_CMD_TRAIT(CMD_REMOVE_SIGNALS, CmdRemoveSingleSignal, CMD_AUTO, CMDT_LANDSCAPE_CONSTRUCTION) DEF_CMD_TRAIT(CMD_CONVERT_RAIL, CmdConvertRail, 0, CMDT_LANDSCAPE_CONSTRUCTION) diff --git a/src/rail_gui.cpp b/src/rail_gui.cpp index b051c7c474b6e..a3ed445c2d1d3 100644 --- a/src/rail_gui.cpp +++ b/src/rail_gui.cpp @@ -294,6 +294,7 @@ void CcBuildRailTunnel(Commands cmd, const CommandCost &result, TileIndex tile) static void ToggleRailButton_Remove(Window *w) { CloseWindowById(WC_SELECT_STATION, 0); + CloseWindowById(WC_SELECT_DEPOT, VEH_TRAIN); w->ToggleWidgetLoweredState(WID_RAT_REMOVE); w->SetWidgetDirty(WID_RAT_REMOVE); _remove_button_clicked = w->IsWidgetLowered(WID_RAT_REMOVE); @@ -311,7 +312,7 @@ static bool RailToolbar_CtrlChanged(Window *w) /* allow ctrl to switch remove mode only for these widgets */ for (uint i = WID_RAT_BUILD_NS; i <= WID_RAT_BUILD_STATION; i++) { - if ((i <= WID_RAT_AUTORAIL || i >= WID_RAT_BUILD_WAYPOINT) && w->IsWidgetLowered(i)) { + if ((i <= WID_RAT_AUTORAIL || i >= WID_RAT_BUILD_DEPOT) && w->IsWidgetLowered(i)) { ToggleRailButton_Remove(w); return true; } @@ -474,6 +475,7 @@ struct BuildRailToolbarWindow : Window { case WID_RAT_BUILD_EW: case WID_RAT_BUILD_Y: case WID_RAT_AUTORAIL: + case WID_RAT_BUILD_DEPOT: case WID_RAT_BUILD_WAYPOINT: case WID_RAT_BUILD_STATION: case WID_RAT_BUILD_SIGNALS: @@ -634,7 +636,7 @@ struct BuildRailToolbarWindow : Window { CloseWindowById(WC_SELECT_DEPOT, VEH_TRAIN); ViewportPlaceMethod vpm = (DiagDirToAxis(_build_depot_direction) == 0) ? VPM_X_LIMITED : VPM_Y_LIMITED; - VpStartPlaceSizing(tile, vpm, DDSP_BUILD_DEPOT); + VpStartPlaceSizing(tile, vpm, _remove_button_clicked ? DDSP_REMOVE_DEPOT : DDSP_BUILD_DEPOT); VpSetPlaceSizingLimit(_settings_game.depot.depot_spread); break; } @@ -735,16 +737,19 @@ struct BuildRailToolbarWindow : Window { } break; - case DDSP_BUILD_DEPOT: { - bool adjacent = _ctrl_pressed; + case DDSP_BUILD_DEPOT: + if (_remove_button_clicked) { + Command::Post(STR_ERROR_CAN_T_REMOVE_TRAIN_DEPOT, CcPlaySound_CONSTRUCTION_RAIL, start_tile, end_tile); + } else { + bool adjacent = _ctrl_pressed; - auto proc = [=](DepotID join_to) -> bool { - return Command::Post(STR_ERROR_CAN_T_BUILD_TRAIN_DEPOT, CcRailDepot, start_tile, _cur_railtype, _build_depot_direction, adjacent, join_to, end_tile); - }; + auto proc = [=](DepotID join_to) -> bool { + return Command::Post(STR_ERROR_CAN_T_BUILD_TRAIN_DEPOT, CcRailDepot, start_tile, _cur_railtype, _build_depot_direction, adjacent, join_to, end_tile); + }; - ShowSelectDepotIfNeeded(TileArea(start_tile, end_tile), proc, VEH_TRAIN); + ShowSelectDepotIfNeeded(TileArea(start_tile, end_tile), proc, VEH_TRAIN); + } break; - } } } } @@ -776,8 +781,11 @@ struct BuildRailToolbarWindow : Window { EventState OnCTRLStateChange() override { - /* do not toggle Remove button by Ctrl when placing station */ - if (!this->IsWidgetLowered(WID_RAT_BUILD_STATION) && !this->IsWidgetLowered(WID_RAT_BUILD_WAYPOINT) && RailToolbar_CtrlChanged(this)) return ES_HANDLED; + /* do not toggle Remove button by Ctrl when placing station or depot */ + if (!this->IsWidgetLowered(WID_RAT_BUILD_STATION) && + !this->IsWidgetLowered(WID_RAT_BUILD_WAYPOINT) && + !this->IsWidgetLowered(WID_RAT_BUILD_DEPOT) && + RailToolbar_CtrlChanged(this)) return ES_HANDLED; return ES_NOT_HANDLED; } diff --git a/src/script/api/script_rail.cpp b/src/script/api/script_rail.cpp index 246b29cb922d5..3e32c0bb800cb 100644 --- a/src/script/api/script_rail.cpp +++ b/src/script/api/script_rail.cpp @@ -147,6 +147,15 @@ return ScriptObject::Command::Do(tile, (::RailType)ScriptObject::GetRailType(), entrance_dir, false, NEW_DEPOT, tile); } +/* static */ bool ScriptRail::RemoveRailDepot(TileIndex start_tile, TileIndex end_tile) +{ + EnforcePrecondition(false, ScriptObject::GetCompany() != OWNER_DEITY); + EnforcePrecondition(false, ::IsValidTile(start_tile)); + EnforcePrecondition(false, ::IsValidTile(end_tile)); + + return ScriptObject::Command::Do(start_tile, end_tile); +} + /* static */ bool ScriptRail::BuildRailStation(TileIndex tile, RailTrack direction, uint num_platforms, uint platform_length, StationID station_id) { EnforcePrecondition(false, ScriptObject::GetCompany() != OWNER_DEITY); diff --git a/src/script/api/script_rail.hpp b/src/script/api/script_rail.hpp index ec056dacb5257..b696cacca47dc 100644 --- a/src/script/api/script_rail.hpp +++ b/src/script/api/script_rail.hpp @@ -238,6 +238,19 @@ class ScriptRail : public ScriptObject { */ static bool BuildRailDepot(TileIndex tile, TileIndex front); + /** + * Removes rail depots from an area. + * @param start_tile Start tile of the area. + * @param end_tile End tile of the area. + * @pre ScriptMap::IsValidTile(start_tile). + * @pre ScriptMap::IsValidTile(end_tile). + * @game @pre Valid ScriptCompanyMode active in scope. + * @exception ScriptError::ERR_FLAT_LAND_REQUIRED + * @return Whether all depot tiles of the owner in the area have been/can be cleared or not. + * @todo look for all the exceptions. + */ + static bool RemoveRailDepot(TileIndex start_tile, TileIndex end_tile); + /** * Build a rail station. * @param tile Place to build the station. diff --git a/src/viewport_type.h b/src/viewport_type.h index 6c08748f1eba8..c242758e69c4a 100644 --- a/src/viewport_type.h +++ b/src/viewport_type.h @@ -127,6 +127,7 @@ enum ViewportDragDropSelectionProcess { DDSP_BUILD_BRIDGE, ///< Bridge placement DDSP_BUILD_OBJECT, ///< Build an object DDSP_BUILD_DEPOT, ///< Depot placement + DDSP_REMOVE_DEPOT, ///< Depot removal /* Rail specific actions */ DDSP_PLACE_RAIL, ///< Rail placement