747 * @return The cost and state of the operation |
747 * @return The cost and state of the operation |
748 * @retval CMD_ERROR An error occured during the operation. |
748 * @retval CMD_ERROR An error occured during the operation. |
749 */ |
749 */ |
750 CommandCost DoConvertTunnelBridgeRail(TileIndex tile, RailType totype, bool exec) |
750 CommandCost DoConvertTunnelBridgeRail(TileIndex tile, RailType totype, bool exec) |
751 { |
751 { |
752 TileIndex endtile; |
|
753 |
|
754 if (IsTunnel(tile) && GetTunnelTransportType(tile) == TRANSPORT_RAIL) { |
752 if (IsTunnel(tile) && GetTunnelTransportType(tile) == TRANSPORT_RAIL) { |
755 uint length; |
753 uint length; |
756 |
754 TileIndex endtile; |
757 if (!CheckTileOwnership(tile)) return CMD_ERROR; |
755 |
758 |
756 /* If not coverting rail <-> el. rail, any vehicle cannot be in tunnel */ |
759 if (GetRailType(tile) == totype) return CMD_ERROR; |
757 if (!IsCompatibleRail(GetRailType(tile), totype)) { |
760 |
758 endtile = CheckTunnelBusy(tile, &length); |
761 /* 'hidden' elrails can't be downgraded to normal rail when elrails are disabled */ |
759 if (endtile == INVALID_TILE) return CMD_ERROR; |
762 if (_patches.disable_elrails && totype == RAILTYPE_RAIL && GetRailType(tile) == RAILTYPE_ELECTRIC) return CMD_ERROR; |
760 } else { |
763 |
761 endtile = GetOtherTunnelEnd(tile); |
764 endtile = CheckTunnelBusy(tile, &length); |
762 length = DistanceManhattan(tile, endtile); |
765 if (endtile == INVALID_TILE) return CMD_ERROR; |
763 } |
766 |
764 |
767 if (exec) { |
765 if (exec) { |
768 Track track; |
|
769 SetRailType(tile, totype); |
766 SetRailType(tile, totype); |
770 SetRailType(endtile, totype); |
767 SetRailType(endtile, totype); |
771 MarkTileDirtyByTile(tile); |
768 MarkTileDirtyByTile(tile); |
772 MarkTileDirtyByTile(endtile); |
769 MarkTileDirtyByTile(endtile); |
773 |
770 |
774 track = AxisToTrack(DiagDirToAxis(GetTunnelDirection(tile))); |
771 Track track = AxisToTrack(DiagDirToAxis(GetTunnelDirection(tile))); |
|
772 |
775 YapfNotifyTrackLayoutChange(tile, track); |
773 YapfNotifyTrackLayoutChange(tile, track); |
776 YapfNotifyTrackLayoutChange(endtile, track); |
774 YapfNotifyTrackLayoutChange(endtile, track); |
777 } |
775 |
778 return CommandCost((length + 1) * (_price.build_rail / 2)); |
776 VehicleFromPos(tile, &tile, UpdateTrainPowerProc); |
|
777 VehicleFromPos(endtile, &endtile, UpdateTrainPowerProc); |
|
778 } |
|
779 |
|
780 return CommandCost((length + 1) * (_price.build_rail >> 1)); |
779 } else if (IsBridge(tile) && GetBridgeTransportType(tile) == TRANSPORT_RAIL) { |
781 } else if (IsBridge(tile) && GetBridgeTransportType(tile) == TRANSPORT_RAIL) { |
780 |
782 TileIndex endtile = GetOtherBridgeEnd(tile); |
781 if (!CheckTileOwnership(tile)) return CMD_ERROR; |
|
782 |
|
783 endtile = GetOtherBridgeEnd(tile); |
|
784 byte bridge_height = GetBridgeHeight(tile); |
783 byte bridge_height = GetBridgeHeight(tile); |
785 |
784 |
786 if (FindVehicleOnTileZ(tile, bridge_height) != NULL || |
785 if (!IsCompatibleRail(GetRailType(tile), totype) && |
|
786 (FindVehicleOnTileZ(tile, bridge_height) != NULL || |
787 FindVehicleOnTileZ(endtile, bridge_height) != NULL || |
787 FindVehicleOnTileZ(endtile, bridge_height) != NULL || |
788 IsVehicleOnBridge(tile, endtile, bridge_height)) { |
788 IsVehicleOnBridge(tile, endtile, bridge_height))) { |
789 return CMD_ERROR; |
789 return CMD_ERROR; |
790 } |
790 } |
791 |
791 |
792 if (GetRailType(tile) == totype) return CMD_ERROR; |
|
793 |
|
794 if (exec) { |
792 if (exec) { |
795 TileIndexDiff delta; |
|
796 Track track; |
|
797 |
|
798 SetRailType(tile, totype); |
793 SetRailType(tile, totype); |
799 SetRailType(endtile, totype); |
794 SetRailType(endtile, totype); |
800 MarkTileDirtyByTile(tile); |
795 MarkTileDirtyByTile(tile); |
801 MarkTileDirtyByTile(endtile); |
796 MarkTileDirtyByTile(endtile); |
802 |
797 |
803 track = AxisToTrack(DiagDirToAxis(GetBridgeRampDirection(tile))); |
798 Track track = AxisToTrack(DiagDirToAxis(GetBridgeRampDirection(tile))); |
|
799 TileIndexDiff delta = TileOffsByDiagDir(GetBridgeRampDirection(tile)); |
|
800 |
804 YapfNotifyTrackLayoutChange(tile, track); |
801 YapfNotifyTrackLayoutChange(tile, track); |
805 YapfNotifyTrackLayoutChange(endtile, track); |
802 YapfNotifyTrackLayoutChange(endtile, track); |
806 |
803 |
807 delta = TileOffsByDiagDir(GetBridgeRampDirection(tile)); |
804 VehicleFromPos(tile, &tile, UpdateTrainPowerProc); |
|
805 VehicleFromPos(endtile, &endtile, UpdateTrainPowerProc); |
|
806 |
808 for (tile += delta; tile != endtile; tile += delta) { |
807 for (tile += delta; tile != endtile; tile += delta) { |
809 MarkTileDirtyByTile(tile); // TODO encapsulate this into a function |
808 MarkTileDirtyByTile(tile); // TODO encapsulate this into a function |
810 } |
809 } |
811 } |
810 } |
812 |
811 |
813 return CommandCost((DistanceManhattan(tile, endtile) + 1) * (_price.build_rail / 2)); |
812 return CommandCost((DistanceManhattan(tile, endtile) + 1) * (_price.build_rail >> 1)); |
814 } else { |
813 } else { |
815 return CMD_ERROR; |
814 return CMD_ERROR; |
816 } |
815 } |
817 } |
816 } |
818 |
817 |