From a93087ec5cd1be7bcc9b8a0277680aadf640071a Mon Sep 17 00:00:00 2001 From: Richard Wheeler <2762690+zephyris@users.noreply.github.com> Date: Sat, 12 Apr 2025 18:50:11 +0100 Subject: [PATCH] Fix #13980: Allow diagonal selection for road convert (#13983) Fixes #13980 --- src/road_cmd.cpp | 12 ++++++++---- src/road_cmd.h | 2 +- src/road_gui.cpp | 4 ++-- src/script/api/script_road.cpp | 2 +- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/road_cmd.cpp b/src/road_cmd.cpp index 0d974bbdf5..2d9a6d2de5 100644 --- a/src/road_cmd.cpp +++ b/src/road_cmd.cpp @@ -857,7 +857,7 @@ do_clear:; if (HasPowerOnRoad(rt, existing_rt)) { rt = existing_rt; } else if (HasPowerOnRoad(existing_rt, rt)) { - ret = Command::Do(flags, tile, tile, rt); + ret = Command::Do(flags, tile, tile, rt, false); if (ret.Failed()) return ret; cost.AddCost(ret.GetCost()); } else { @@ -2435,7 +2435,7 @@ static void ConvertRoadTypeOwner(TileIndex tile, uint num_pieces, Owner owner, R * @param to_type new roadtype to convert to. * @return the cost of this operation or an error */ -CommandCost CmdConvertRoad(DoCommandFlags flags, TileIndex tile, TileIndex area_start, RoadType to_type) +CommandCost CmdConvertRoad(DoCommandFlags flags, TileIndex tile, TileIndex area_start, RoadType to_type, bool diagonal) { TileIndex area_end = tile; @@ -2449,7 +2449,7 @@ CommandCost CmdConvertRoad(DoCommandFlags flags, TileIndex tile, TileIndex area_ CommandCost error = CommandCost((rtt == RTT_TRAM) ? STR_ERROR_NO_SUITABLE_TRAMWAY : STR_ERROR_NO_SUITABLE_ROAD); // by default, there is no road to convert. bool found_convertible_road = false; // whether we actually did convert any road/tram (see bug #7633) - std::unique_ptr iter = std::make_unique(area_start, area_end); + std::unique_ptr iter = TileIterator::Create(area_start, area_end, diagonal); for (; (tile = *iter) != INVALID_TILE; ++(*iter)) { /* Is road present on tile? */ if (!MayHaveRoad(tile)) continue; @@ -2552,7 +2552,11 @@ CommandCost CmdConvertRoad(DoCommandFlags flags, TileIndex tile, TileIndex area_ /* If both ends of tunnel/bridge are in the range, do not try to convert twice - * it would cause assert because of different test and exec runs */ if (endtile < tile) { - if (OrthogonalTileArea(area_start, area_end).Contains(endtile)) continue; + if (diagonal) { + if (DiagonalTileArea(area_start, area_end).Contains(endtile)) continue; + } else { + if (OrthogonalTileArea(area_start, area_end).Contains(endtile)) continue; + } } /* When not converting rail <-> el. rail, any vehicle cannot be in tunnel/bridge */ diff --git a/src/road_cmd.h b/src/road_cmd.h index ad53a3e111..84f31c3be0 100644 --- a/src/road_cmd.h +++ b/src/road_cmd.h @@ -23,7 +23,7 @@ CommandCost CmdBuildLongRoad(DoCommandFlags flags, TileIndex end_tile, TileIndex std::tuple CmdRemoveLongRoad(DoCommandFlags flags, TileIndex end_tile, TileIndex start_tile, RoadType rt, Axis axis, bool start_half, bool end_half); CommandCost CmdBuildRoad(DoCommandFlags flags, TileIndex tile, RoadBits pieces, RoadType rt, DisallowedRoadDirections toggle_drd, TownID town_id); CommandCost CmdBuildRoadDepot(DoCommandFlags flags, TileIndex tile, RoadType rt, DiagDirection dir); -CommandCost CmdConvertRoad(DoCommandFlags flags, TileIndex tile, TileIndex area_start, RoadType to_type); +CommandCost CmdConvertRoad(DoCommandFlags flags, TileIndex tile, TileIndex area_start, RoadType to_type, bool diagonal); DEF_CMD_TRAIT(CMD_BUILD_LONG_ROAD, CmdBuildLongRoad, CommandFlags({CommandFlag::Auto, CommandFlag::NoWater, CommandFlag::Deity}), CMDT_LANDSCAPE_CONSTRUCTION) DEF_CMD_TRAIT(CMD_REMOVE_LONG_ROAD, CmdRemoveLongRoad, CommandFlags({CommandFlag::Auto, CommandFlag::NoTest}), CMDT_LANDSCAPE_CONSTRUCTION) // towns may disallow removing road bits (as they are connected) in test, but in exec they're removed and thus removing is allowed. diff --git a/src/road_gui.cpp b/src/road_gui.cpp index 70406eaecf..0eb0cec738 100644 --- a/src/road_gui.cpp +++ b/src/road_gui.cpp @@ -586,7 +586,7 @@ struct BuildRoadToolbarWindow : Window { break; case WID_ROT_CONVERT_ROAD: - HandlePlacePushButton(this, WID_ROT_CONVERT_ROAD, GetRoadTypeInfo(this->roadtype)->cursor.convert_road, HT_RECT); + HandlePlacePushButton(this, WID_ROT_CONVERT_ROAD, GetRoadTypeInfo(this->roadtype)->cursor.convert_road, HT_RECT | HT_DIAGONAL); this->last_started_action = widget; break; @@ -805,7 +805,7 @@ struct BuildRoadToolbarWindow : Window { break; case DDSP_CONVERT_ROAD: - Command::Post(GetRoadTypeInfo(this->roadtype)->strings.err_convert_road, CcPlaySound_CONSTRUCTION_OTHER, end_tile, start_tile, _cur_roadtype); + Command::Post(GetRoadTypeInfo(this->roadtype)->strings.err_convert_road, CcPlaySound_CONSTRUCTION_OTHER, end_tile, start_tile, _cur_roadtype, _ctrl_pressed); break; } } diff --git a/src/script/api/script_road.cpp b/src/script/api/script_road.cpp index b2152b409b..b6a3cceb14 100644 --- a/src/script/api/script_road.cpp +++ b/src/script/api/script_road.cpp @@ -132,7 +132,7 @@ EnforcePrecondition(false, ::IsValidTile(end_tile)); EnforcePrecondition(false, IsRoadTypeAvailable(road_type)); - return ScriptObject::Command::Do(start_tile, end_tile, (::RoadType)road_type); + return ScriptObject::Command::Do(start_tile, end_tile, (::RoadType)road_type, false); } /* Helper functions for ScriptRoad::CanBuildConnectedRoadParts(). */