* Convert one road subtype to another. * Not meant to convert from road to tram. * * @param flags operation to perform * @param tile end tile of road conversion drag * @param area_start start tile of drag * @param to_type new roadtype to convert to. * @return the cost of this operation or an error */
| 2458 | * @return the cost of this operation or an error |
| 2459 | */ |
| 2460 | CommandCost CmdConvertRoad(DoCommandFlags flags, TileIndex tile, TileIndex area_start, RoadType to_type, bool diagonal) |
| 2461 | { |
| 2462 | TileIndex area_end = tile; |
| 2463 | |
| 2464 | if (!ValParamRoadType(to_type)) return CMD_ERROR; |
| 2465 | if (area_start >= Map::Size()) return CMD_ERROR; |
| 2466 | |
| 2467 | RoadVehicleList affected_rvs; |
| 2468 | RoadTramType rtt = GetRoadTramType(to_type); |
| 2469 | |
| 2470 | CommandCost cost(EXPENSES_CONSTRUCTION); |
| 2471 | CommandCost error = CommandCost((rtt == RTT_TRAM) ? STR_ERROR_NO_SUITABLE_TRAMWAY : STR_ERROR_NO_SUITABLE_ROAD); // by default, there is no road to convert. |
| 2472 | bool found_convertible_road = false; // whether we actually did convert any road/tram (see bug #7633) |
| 2473 | |
| 2474 | std::unique_ptr<TileIterator> iter = TileIterator::Create(area_start, area_end, diagonal); |
| 2475 | for (; (tile = *iter) != INVALID_TILE; ++(*iter)) { |
| 2476 | /* Is road present on tile? */ |
| 2477 | if (!MayHaveRoad(tile)) continue; |
| 2478 | |
| 2479 | /* Converting to the same subtype? */ |
| 2480 | RoadType from_type = GetRoadType(tile, rtt); |
| 2481 | if (from_type == INVALID_ROADTYPE || from_type == to_type) continue; |
| 2482 | |
| 2483 | /* Check if there is any infrastructure on tile */ |
| 2484 | TileType tt = GetTileType(tile); |
| 2485 | switch (tt) { |
| 2486 | case MP_STATION: |
| 2487 | if (!IsAnyRoadStop(tile)) continue; |
| 2488 | break; |
| 2489 | case MP_ROAD: |
| 2490 | if (IsLevelCrossing(tile) && RoadNoLevelCrossing(to_type)) { |
| 2491 | error.MakeError(STR_ERROR_CROSSING_DISALLOWED_ROAD); |
| 2492 | continue; |
| 2493 | } |
| 2494 | break; |
| 2495 | case MP_TUNNELBRIDGE: |
| 2496 | if (GetTunnelBridgeTransportType(tile) != TRANSPORT_ROAD) continue; |
| 2497 | break; |
| 2498 | default: continue; |
| 2499 | } |
| 2500 | |
| 2501 | /* Trying to convert other's road */ |
| 2502 | Owner owner = GetRoadOwner(tile, rtt); |
| 2503 | if (!CanConvertUnownedRoadType(owner, rtt)) { |
| 2504 | CommandCost ret = CheckOwnership(owner, tile); |
| 2505 | if (ret.Failed()) { |
| 2506 | error = std::move(ret); |
| 2507 | continue; |
| 2508 | } |
| 2509 | } |
| 2510 | |
| 2511 | /* Base the ability to replace town roads and bridges on the town's |
| 2512 | * acceptance of destructive actions. */ |
| 2513 | if (owner == OWNER_TOWN) { |
| 2514 | Town *t = ClosestTownFromTile(tile, _settings_game.economy.dist_local_authority); |
| 2515 | CommandCost ret = CheckforTownRating({}, t, tt == MP_TUNNELBRIDGE ? TownRatingCheckType::TunnelBridgeRemove : TownRatingCheckType::RoadRemove); |
| 2516 | if (ret.Failed()) { |
| 2517 | error = std::move(ret); |
nothing calls this directly
no test coverage detected