* Convert one rail type to the other. You can convert normal rail to * monorail/maglev easily or vice-versa. * @param flags operation to perform * @param tile end tile of rail conversion drag * @param area_start start tile of drag * @param totype new railtype to convert to. * @param diagonal build diagonally or not. * @return the cost of this operation or an error */
| 1537 | * @return the cost of this operation or an error |
| 1538 | */ |
| 1539 | CommandCost CmdConvertRail(DoCommandFlags flags, TileIndex tile, TileIndex area_start, RailType totype, bool diagonal) |
| 1540 | { |
| 1541 | TileIndex area_end = tile; |
| 1542 | |
| 1543 | if (!ValParamRailType(totype)) return CMD_ERROR; |
| 1544 | if (area_start >= Map::Size()) return CMD_ERROR; |
| 1545 | |
| 1546 | TrainList affected_trains; |
| 1547 | |
| 1548 | CommandCost cost(EXPENSES_CONSTRUCTION); |
| 1549 | CommandCost error = CommandCost(STR_ERROR_NO_SUITABLE_RAILROAD_TRACK); // by default, there is no track to convert. |
| 1550 | bool found_convertible_track = false; // whether we actually did convert some track (see bug #7633) |
| 1551 | |
| 1552 | std::unique_ptr<TileIterator> iter = TileIterator::Create(area_start, area_end, diagonal); |
| 1553 | for (; (tile = *iter) != INVALID_TILE; ++(*iter)) { |
| 1554 | TileType tt = GetTileType(tile); |
| 1555 | |
| 1556 | /* Check if there is any track on tile */ |
| 1557 | switch (tt) { |
| 1558 | case MP_RAILWAY: |
| 1559 | break; |
| 1560 | case MP_STATION: |
| 1561 | if (!HasStationRail(tile)) continue; |
| 1562 | break; |
| 1563 | case MP_ROAD: |
| 1564 | if (!IsLevelCrossing(tile)) continue; |
| 1565 | if (RailNoLevelCrossings(totype)) { |
| 1566 | error.MakeError(STR_ERROR_CROSSING_DISALLOWED_RAIL); |
| 1567 | continue; |
| 1568 | } |
| 1569 | break; |
| 1570 | case MP_TUNNELBRIDGE: |
| 1571 | if (GetTunnelBridgeTransportType(tile) != TRANSPORT_RAIL) continue; |
| 1572 | break; |
| 1573 | default: continue; |
| 1574 | } |
| 1575 | |
| 1576 | /* Original railtype we are converting from */ |
| 1577 | RailType type = GetRailType(tile); |
| 1578 | |
| 1579 | /* Converting to the same type or converting 'hidden' elrail -> rail */ |
| 1580 | if (type == totype || (_settings_game.vehicle.disable_elrails && totype == RAILTYPE_RAIL && type == RAILTYPE_ELECTRIC)) continue; |
| 1581 | |
| 1582 | /* Trying to convert other's rail */ |
| 1583 | CommandCost ret = CheckTileOwnership(tile); |
| 1584 | if (ret.Failed()) { |
| 1585 | error = std::move(ret); |
| 1586 | continue; |
| 1587 | } |
| 1588 | |
| 1589 | std::vector<Train *> vehicles_affected; |
| 1590 | |
| 1591 | /* Vehicle on the tile when not converting Rail <-> ElRail |
| 1592 | * Tunnels and bridges have special check later */ |
| 1593 | if (tt != MP_TUNNELBRIDGE) { |
| 1594 | if (!IsCompatibleRail(type, totype)) { |
| 1595 | ret = IsPlainRailTile(tile) ? EnsureNoTrainOnTrackBits(tile, GetTrackBits(tile)) : EnsureNoVehicleOnGround(tile); |
| 1596 | if (ret.Failed()) { |
nothing calls this directly
no test coverage detected